cfitsio-4.3.1/0000755000225700000360000000000014523176740012456 5ustar cagordonlheacfitsio-4.3.1/fitsio.h0000644000225700000360000035257214523041446014134 0ustar cagordonlhea/* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." */ #ifndef _FITSIO_H #define _FITSIO_H #define CFITSIO_VERSION 4.3.1 /* Minor and micro numbers must not exceed 99 under current method of version representataion in ffvers(). */ #define CFITSIO_MICRO 1 #define CFITSIO_MINOR 3 #define CFITSIO_MAJOR 4 #define CFITSIO_SONAME 10 /* the SONAME is incremented in a new release if the binary shared */ /* library (on linux and Mac systems) is not backward compatible */ /* with the previous release of CFITSIO */ /* CFITS_API is defined below for use on Windows systems. */ /* It is used to identify the public functions which should be exported. */ /* This has no effect on non-windows platforms where "WIN32" is not defined */ #if defined (WIN32) #if defined(cfitsio_EXPORTS) #define CFITS_API __declspec(dllexport) #else #define CFITS_API /* __declspec(dllimport) */ #endif /* CFITS_API */ #else /* defined (WIN32) */ #define CFITS_API #endif #include /* the following was provided by Michael Greason (GSFC) to fix a */ /* C/Fortran compatibility problem on an SGI Altix system running */ /* SGI ProPack 4 [this is a Novell SuSE Enterprise 9 derivative] */ /* and using the Intel C++ and Fortran compilers (version 9.1) */ #if defined(__INTEL_COMPILER) && defined(__itanium__) # define mipsFortran 1 # define _MIPS_SZLONG 64 #endif #if defined(linux) || defined(__APPLE__) || defined(__sgi) # include /* apparently needed on debian linux systems */ #endif /* to define off_t */ #include /* apparently needed to define size_t with gcc 2.8.1 */ #include /* needed for LLONG_MAX and INT64_MAX definitions */ /* Define the datatype for variables which store file offset values. */ /* The newer 'off_t' datatype should be used for this purpose, but some */ /* older compilers do not recognize this type, in which case we use 'long' */ /* instead. Note that _OFF_T is defined (or not) in stdio.h depending */ /* on whether _LARGEFILE_SOURCE is defined in sys/feature_tests.h */ /* (at least on Solaris platforms using cc) */ /* Debian systems require: "(defined(linux) && defined(__off_t_defined))" */ /* the mingw-w64 compiler requires: "(defined(__MINGW32__) && defined(_OFF_T_DEFINED))" */ #if defined(_OFF_T) \ || (defined(linux) && defined(__off_t_defined)) \ || (defined(__MINGW32__) && defined(_OFF_T_DEFINED)) \ || defined(_MIPS_SZLONG) || defined(__APPLE__) || defined(_AIX) # define OFF_T off_t #elif defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER>= 1400)) # define OFF_T long long #else # define OFF_T long #endif /* this block determines if the the string function name is strtol or strtoll, and whether to use %ld or %lld in printf statements */ /* The following 2 cases for that Athon64 were removed on 4 Jan 2006; they appear to be incorrect now that LONGLONG is always typedef'ed to 'long long' || defined(__ia64__) \ || defined(__x86_64__) \ */ #if (defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) )) \ || defined(__sparcv9) || (defined(__sparc__) && defined(__arch64__)) \ || defined(__powerpc64__) || defined(__64BIT__) \ || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) \ || defined( _MSC_VER)|| defined(__BORLANDC__) # define USE_LL_SUFFIX 0 #else # define USE_LL_SUFFIX 1 #endif /* Determine what 8-byte integer data type is available. 'long long' is now supported by most compilers, but older MS Visual C++ compilers before V7.0 use '__int64' instead. */ #ifndef LONGLONG_TYPE /* this may have been previously defined */ #if defined(_MSC_VER) /* Microsoft Visual C++ */ #if (_MSC_VER < 1300) /* versions earlier than V7.0 do not have 'long long' */ typedef __int64 LONGLONG; typedef unsigned __int64 ULONGLONG; #else /* newer versions do support 'long long' */ typedef long long LONGLONG; typedef unsigned long long ULONGLONG; #endif #elif defined( __BORLANDC__) /* for the Borland 5.5 compiler, in particular */ typedef __int64 LONGLONG; typedef unsigned __int64 ULONGLONG; #else typedef long long LONGLONG; typedef unsigned long long ULONGLONG; #endif #define LONGLONG_TYPE #endif #ifndef LONGLONG_MAX #ifdef LLONG_MAX /* Linux and Solaris definition */ #define LONGLONG_MAX LLONG_MAX #define LONGLONG_MIN LLONG_MIN #elif defined(LONG_LONG_MAX) #define LONGLONG_MAX LONG_LONG_MAX #define LONGLONG_MIN LONG_LONG_MIN #elif defined(__LONG_LONG_MAX__) /* Mac OS X & CYGWIN defintion */ #define LONGLONG_MAX __LONG_LONG_MAX__ #define LONGLONG_MIN (-LONGLONG_MAX -1LL) #elif defined(INT64_MAX) /* windows definition */ #define LONGLONG_MAX INT64_MAX #define LONGLONG_MIN INT64_MIN #elif defined(_I64_MAX) /* windows definition */ #define LONGLONG_MAX _I64_MAX #define LONGLONG_MIN _I64_MIN #elif (defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) )) \ || defined(__sparcv9) \ || defined(__ia64__) \ || defined(__x86_64__) \ || defined(_SX) \ || defined(__powerpc64__) || defined(__64BIT__) \ || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) /* sizeof(long) = 64 */ #define LONGLONG_MAX 9223372036854775807L /* max 64-bit integer */ #define LONGLONG_MIN (-LONGLONG_MAX -1L) /* min 64-bit integer */ #else /* define a default value, even if it is never used */ #define LONGLONG_MAX 9223372036854775807LL /* max 64-bit integer */ #define LONGLONG_MIN (-LONGLONG_MAX -1LL) /* min 64-bit integer */ #endif #endif /* end of ndef LONGLONG_MAX section */ /* ================================================================= */ /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ #include "longnam.h" #endif #define NIOBUF 40 /* number of IO buffers to create (default = 40) */ /* !! Significantly increasing NIOBUF may degrade performance !! */ #define IOBUFLEN 2880 /* size in bytes of each IO buffer (DONT CHANGE!) */ /* global variables */ #define FLEN_FILENAME 1025 /* max length of a filename */ #define FLEN_KEYWORD 75 /* max length of a keyword (HIERARCH convention) */ #define FLEN_CARD 81 /* length of a FITS header card */ #define FLEN_VALUE 71 /* max length of a keyword value string */ #define FLEN_COMMENT 73 /* max length of a keyword comment string */ #define FLEN_ERRMSG 81 /* max length of a FITSIO error message */ #define FLEN_STATUS 31 /* max length of a FITSIO status text string */ #define TBIT 1 /* codes for FITS table data types */ #define TBYTE 11 #define TSBYTE 12 #define TLOGICAL 14 #define TSTRING 16 #define TUSHORT 20 #define TSHORT 21 #define TUINT 30 #define TINT 31 #define TULONG 40 #define TLONG 41 #define TINT32BIT 41 /* used when returning datatype of a column */ #define TFLOAT 42 #define TULONGLONG 80 #define TLONGLONG 81 #define TDOUBLE 82 #define TCOMPLEX 83 #define TDBLCOMPLEX 163 #define TYP_STRUC_KEY 10 #define TYP_CMPRS_KEY 20 #define TYP_SCAL_KEY 30 #define TYP_NULL_KEY 40 #define TYP_DIM_KEY 50 #define TYP_RANG_KEY 60 #define TYP_UNIT_KEY 70 #define TYP_DISP_KEY 80 #define TYP_HDUID_KEY 90 #define TYP_CKSUM_KEY 100 #define TYP_WCS_KEY 110 #define TYP_REFSYS_KEY 120 #define TYP_COMM_KEY 130 #define TYP_CONT_KEY 140 #define TYP_USER_KEY 150 #define INT32BIT int /* 32-bit integer datatype. Currently this */ /* datatype is an 'int' on all useful platforms */ /* however, it is possible that that are cases */ /* where 'int' is a 2-byte integer, in which case */ /* INT32BIT would need to be defined as 'long'. */ #define BYTE_IMG 8 /* BITPIX code values for FITS image types */ #define SHORT_IMG 16 #define LONG_IMG 32 #define LONGLONG_IMG 64 #define FLOAT_IMG -32 #define DOUBLE_IMG -64 /* The following 2 codes are not true FITS */ /* datatypes; these codes are only used internally */ /* within cfitsio to make it easier for users */ /* to deal with unsigned integers. */ #define SBYTE_IMG 10 #define USHORT_IMG 20 #define ULONG_IMG 40 #define ULONGLONG_IMG 80 #define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ #define ASCII_TBL 1 /* ASCII table HDU */ #define BINARY_TBL 2 /* Binary table HDU */ #define ANY_HDU -1 /* matches any HDU type */ #define READONLY 0 /* options when opening a file */ #define READWRITE 1 /* adopt a hopefully obscure number to use as a null value flag */ #define FLOATNULLVALUE -9.11912E-36F #define DOUBLENULLVALUE -9.1191291391491E-36 /* compression algorithm codes */ #define NO_DITHER -1 #define SUBTRACTIVE_DITHER_1 1 #define SUBTRACTIVE_DITHER_2 2 #define MAX_COMPRESS_DIM 6 #define RICE_1 11 #define GZIP_1 21 #define GZIP_2 22 #define PLIO_1 31 #define HCOMPRESS_1 41 #define BZIP2_1 51 /* not publicly supported; only for test purposes */ #define NOCOMPRESS -1 #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define CASESEN 1 /* do case-sensitive string match */ #define CASEINSEN 0 /* do case-insensitive string match */ #define GT_ID_ALL_URI 0 /* hierarchical grouping parameters */ #define GT_ID_REF 1 #define GT_ID_POS 2 #define GT_ID_ALL 3 #define GT_ID_REF_URI 11 #define GT_ID_POS_URI 12 #define OPT_RM_GPT 0 #define OPT_RM_ENTRY 1 #define OPT_RM_MBR 2 #define OPT_RM_ALL 3 #define OPT_GCP_GPT 0 #define OPT_GCP_MBR 1 #define OPT_GCP_ALL 2 #define OPT_MCP_ADD 0 #define OPT_MCP_NADD 1 #define OPT_MCP_REPL 2 #define OPT_MCP_MOV 3 #define OPT_MRG_COPY 0 #define OPT_MRG_MOV 1 #define OPT_CMT_MBR 1 #define OPT_CMT_MBR_DEL 11 typedef struct /* structure used to store table column information */ { char ttype[70]; /* column name = FITS TTYPEn keyword; */ LONGLONG tbcol; /* offset in row to first byte of each column */ int tdatatype; /* datatype code of each column */ LONGLONG trepeat; /* repeat count of column; number of elements */ double tscale; /* FITS TSCALn linear scaling factor */ double tzero; /* FITS TZEROn linear scaling zero point */ LONGLONG tnull; /* FITS null value for int image or binary table cols */ char strnull[20]; /* FITS null value string for ASCII table columns */ char tform[10]; /* FITS tform keyword value */ long twidth; /* width of each ASCII table column */ }tcolumn; #define VALIDSTRUC 555 /* magic value used to identify if structure is valid */ typedef struct /* structure used to store basic FITS file information */ { int filehandle; /* handle returned by the file open function */ int driver; /* defines which set of I/O drivers should be used */ int open_count; /* number of opened 'fitsfiles' using this structure */ char *filename; /* file name */ int validcode; /* magic value used to verify that structure is valid */ int only_one; /* flag meaning only copy the specified extension */ int noextsyntax; /* flag for file opened with request to ignore extended syntax*/ LONGLONG filesize; /* current size of the physical disk file in bytes */ LONGLONG logfilesize; /* logical size of file, including unflushed buffers */ int lasthdu; /* is this the last HDU in the file? 0 = no, else yes */ LONGLONG bytepos; /* current logical I/O pointer position in file */ LONGLONG io_pos; /* current I/O pointer position in the physical file */ int curbuf; /* number of I/O buffer currently in use */ int curhdu; /* current HDU number; 0 = primary array */ int hdutype; /* 0 = primary array, 1 = ASCII table, 2 = binary table */ int writemode; /* 0 = readonly, 1 = readwrite */ int maxhdu; /* highest numbered HDU known to exist in the file */ int MAXHDU; /* dynamically allocated dimension of headstart array */ LONGLONG *headstart; /* byte offset in file to start of each HDU */ LONGLONG headend; /* byte offest in file to end of the current HDU header */ LONGLONG ENDpos; /* byte offest to where the END keyword was last written */ LONGLONG nextkey; /* byte offset in file to beginning of next keyword */ LONGLONG datastart; /* byte offset in file to start of the current data unit */ int imgdim; /* dimension of image; cached for fast access */ LONGLONG imgnaxis[99]; /* length of each axis; cached for fast access */ int tfield; /* number of fields in the table (primary array has 2 */ int startcol; /* used by ffgcnn to record starting column number */ LONGLONG origrows; /* original number of rows (value of NAXIS2 keyword) */ LONGLONG numrows; /* number of rows in the table (dynamically updated) */ LONGLONG rowlength; /* length of a table row or image size (bytes) */ tcolumn *tableptr; /* pointer to the table structure */ LONGLONG heapstart; /* heap start byte relative to start of data unit */ LONGLONG heapsize; /* size of the heap, in bytes */ /* the following elements are related to compressed images */ /* these record the 'requested' options to be used when the image is compressed */ int request_compress_type; /* requested image compression algorithm */ long request_tilesize[MAX_COMPRESS_DIM]; /* requested tiling size */ float request_quantize_level; /* requested quantize level */ int request_quantize_method ; /* requested quantizing method */ int request_dither_seed; /* starting offset into the array of random dithering */ int request_lossy_int_compress; /* lossy compress integer image as if float image? */ int request_huge_hdu; /* use '1Q' rather then '1P' variable length arrays */ float request_hcomp_scale; /* requested HCOMPRESS scale factor */ int request_hcomp_smooth; /* requested HCOMPRESS smooth parameter */ /* these record the actual options that were used when the image was compressed */ int compress_type; /* type of compression algorithm */ long tilesize[MAX_COMPRESS_DIM]; /* size of compression tiles */ float quantize_level; /* floating point quantization level */ int quantize_method; /* floating point pixel quantization algorithm */ int dither_seed; /* starting offset into the array of random dithering */ /* other compression parameters */ int compressimg; /* 1 if HDU contains a compressed image, else 0 */ char zcmptype[12]; /* compression type string */ int zbitpix; /* FITS data type of image (BITPIX) */ int zndim; /* dimension of image */ long znaxis[MAX_COMPRESS_DIM]; /* length of each axis */ long maxtilelen; /* max number of pixels in each image tile */ long maxelem; /* maximum byte length of tile compressed arrays */ int cn_compressed; /* column number for COMPRESSED_DATA column */ int cn_uncompressed; /* column number for UNCOMPRESSED_DATA column */ int cn_gzip_data; /* column number for GZIP2 lossless compressed data */ int cn_zscale; /* column number for ZSCALE column */ int cn_zzero; /* column number for ZZERO column */ int cn_zblank; /* column number for the ZBLANK column */ double zscale; /* scaling value, if same for all tiles */ double zzero; /* zero pt, if same for all tiles */ double cn_bscale; /* value of the BSCALE keyword in header */ double cn_bzero; /* value of the BZERO keyword (may be reset) */ double cn_actual_bzero; /* actual value of the BZERO keyword */ int zblank; /* value for null pixels, if not a column */ int rice_blocksize; /* first compression parameter: Rice pixels/block */ int rice_bytepix; /* 2nd compression parameter: Rice bytes/pixel */ float hcomp_scale; /* 1st hcompress compression parameter */ int hcomp_smooth; /* 2nd hcompress compression parameter */ int *tilerow; /* row number of the array of uncompressed tiledata */ long *tiledatasize; /* length of the array of tile data in bytes */ int *tiletype; /* datatype of the array of tile (TINT, TSHORT, etc) */ void **tiledata; /* array of uncompressed tile of data, for row *tilerow */ void **tilenullarray; /* array of optional array of null value flags */ int *tileanynull; /* anynulls in the array of tile? */ char *iobuffer; /* pointer to FITS file I/O buffers */ long bufrecnum[NIOBUF]; /* file record number of each of the buffers */ int dirty[NIOBUF]; /* has the corresponding buffer been modified? */ int ageindex[NIOBUF]; /* relative age of each buffer */ } FITSfile; typedef struct /* structure used to store basic HDU information */ { int HDUposition; /* HDU position in file; 0 = first HDU */ FITSfile *Fptr; /* pointer to FITS file structure */ }fitsfile; typedef struct /* structure for the iterator function column information */ { /* elements required as input to fits_iterate_data: */ fitsfile *fptr; /* pointer to the HDU containing the column */ int colnum; /* column number in the table (use name if < 1) */ char colname[70]; /* name (= TTYPEn value) of the column (optional) */ int datatype; /* output datatype (converted if necessary */ int iotype; /* = InputCol, InputOutputCol, or OutputCol */ /* output elements that may be useful for the work function: */ void *array; /* pointer to the array (and the null value) */ long repeat; /* binary table vector repeat value */ long tlmin; /* legal minimum data value */ long tlmax; /* legal maximum data value */ char tunit[70]; /* physical unit string */ char tdisp[70]; /* suggested display format */ } iteratorCol; #define InputCol 0 /* flag for input only iterator column */ #define InputOutputCol 1 /* flag for input and output iterator column */ #define OutputCol 2 /* flag for output only iterator column */ #define TemporaryCol 3 /* flag for temporary iterator column INTERNAL */ /*============================================================================= * * The following wtbarr typedef is used in the fits_read_wcstab() routine, * which is intended for use with the WCSLIB library written by Mark * Calabretta, http://www.atnf.csiro.au/~mcalabre/index.html * * In order to maintain WCSLIB and CFITSIO as independent libraries it * was not permissible for any CFITSIO library code to include WCSLIB * header files, or vice versa. However, the CFITSIO function * fits_read_wcstab() accepts an array of structs defined by wcs.h within * WCSLIB. The problem then was to define this struct within fitsio.h * without including wcs.h, especially noting that wcs.h will often (but * not always) be included together with fitsio.h in an applications * program that uses fits_read_wcstab(). * * Of the various possibilities, the solution adopted was for WCSLIB to * define "struct wtbarr" while fitsio.h defines "typedef wtbarr", a * untagged struct with identical members. This allows both wcs.h and * fitsio.h to define a wtbarr data type without conflict by virtue of * the fact that structure tags and typedef names share different * namespaces in C. Therefore, declarations within WCSLIB look like * * struct wtbarr *w; * * while within CFITSIO they are simply * * wtbarr *w; * * but as suggested by the commonality of the names, these are really the * same aggregate data type. However, in passing a (struct wtbarr *) to * fits_read_wcstab() a cast to (wtbarr *) is formally required. *===========================================================================*/ #ifndef WCSLIB_GETWCSTAB #define WCSLIB_GETWCSTAB typedef struct { int i; /* Image axis number. */ int m; /* Array axis number for index vectors. */ int kind; /* Array type, 'c' (coord) or 'i' (index). */ char extnam[72]; /* EXTNAME of binary table extension. */ int extver; /* EXTVER of binary table extension. */ int extlev; /* EXTLEV of binary table extension. */ char ttype[72]; /* TTYPEn of column containing the array. */ long row; /* Table row number. */ int ndim; /* Expected array dimensionality. */ int *dimlen; /* Where to write the array axis lengths. */ double **arrayp; /* Where to write the address of the array */ /* allocated to store the array. */ } wtbarr; /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ /* the following 3 lines are needed to support C++ compilers */ #ifdef __cplusplus extern "C" { #endif #endif int CFITS_API fits_read_wcstab(fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ #ifdef __cplusplus } #endif #endif #endif /* WCSLIB_GETWCSTAB */ /* error status codes */ #define CREATE_DISK_FILE -106 /* create disk file, without extended filename syntax */ #define OPEN_DISK_FILE -105 /* open disk file, without extended filename syntax */ #define SKIP_TABLE -104 /* move to 1st image when opening file */ #define SKIP_IMAGE -103 /* move to 1st table when opening file */ #define SKIP_NULL_PRIMARY -102 /* skip null primary array when opening file */ #define USE_MEM_BUFF -101 /* use memory buffer when opening file */ #define OVERFLOW_ERR -11 /* overflow during datatype conversion */ #define PREPEND_PRIMARY -9 /* used in ffiimg to insert new primary array */ #define SAME_FILE 101 /* input and output files are the same */ #define TOO_MANY_FILES 103 /* tried to open too many FITS files */ #define FILE_NOT_OPENED 104 /* could not open the named file */ #define FILE_NOT_CREATED 105 /* could not create the named file */ #define WRITE_ERROR 106 /* error writing to FITS file */ #define END_OF_FILE 107 /* tried to move past end of file */ #define READ_ERROR 108 /* error reading from FITS file */ #define FILE_NOT_CLOSED 110 /* could not close the file */ #define ARRAY_TOO_BIG 111 /* array dimensions exceed internal limit */ #define READONLY_FILE 112 /* Cannot write to readonly file */ #define MEMORY_ALLOCATION 113 /* Could not allocate memory */ #define BAD_FILEPTR 114 /* invalid fitsfile pointer */ #define NULL_INPUT_PTR 115 /* NULL input pointer to routine */ #define SEEK_ERROR 116 /* error seeking position in file */ #define BAD_NETTIMEOUT 117 /* bad value for file download timeout setting */ #define BAD_URL_PREFIX 121 /* invalid URL prefix on file name */ #define TOO_MANY_DRIVERS 122 /* tried to register too many IO drivers */ #define DRIVER_INIT_FAILED 123 /* driver initialization failed */ #define NO_MATCHING_DRIVER 124 /* matching driver is not registered */ #define URL_PARSE_ERROR 125 /* failed to parse input file URL */ #define RANGE_PARSE_ERROR 126 /* failed to parse input file URL */ #define SHARED_ERRBASE (150) #define SHARED_BADARG (SHARED_ERRBASE + 1) #define SHARED_NULPTR (SHARED_ERRBASE + 2) #define SHARED_TABFULL (SHARED_ERRBASE + 3) #define SHARED_NOTINIT (SHARED_ERRBASE + 4) #define SHARED_IPCERR (SHARED_ERRBASE + 5) #define SHARED_NOMEM (SHARED_ERRBASE + 6) #define SHARED_AGAIN (SHARED_ERRBASE + 7) #define SHARED_NOFILE (SHARED_ERRBASE + 8) #define SHARED_NORESIZE (SHARED_ERRBASE + 9) #define HEADER_NOT_EMPTY 201 /* header already contains keywords */ #define KEY_NO_EXIST 202 /* keyword not found in header */ #define KEY_OUT_BOUNDS 203 /* keyword record number is out of bounds */ #define VALUE_UNDEFINED 204 /* keyword value field is blank */ #define NO_QUOTE 205 /* string is missing the closing quote */ #define BAD_INDEX_KEY 206 /* illegal indexed keyword name */ #define BAD_KEYCHAR 207 /* illegal character in keyword name or card */ #define BAD_ORDER 208 /* required keywords out of order */ #define NOT_POS_INT 209 /* keyword value is not a positive integer */ #define NO_END 210 /* couldn't find END keyword */ #define BAD_BITPIX 211 /* illegal BITPIX keyword value*/ #define BAD_NAXIS 212 /* illegal NAXIS keyword value */ #define BAD_NAXES 213 /* illegal NAXISn keyword value */ #define BAD_PCOUNT 214 /* illegal PCOUNT keyword value */ #define BAD_GCOUNT 215 /* illegal GCOUNT keyword value */ #define BAD_TFIELDS 216 /* illegal TFIELDS keyword value */ #define NEG_WIDTH 217 /* negative table row size */ #define NEG_ROWS 218 /* negative number of rows in table */ #define COL_NOT_FOUND 219 /* column with this name not found in table */ #define BAD_SIMPLE 220 /* illegal value of SIMPLE keyword */ #define NO_SIMPLE 221 /* Primary array doesn't start with SIMPLE */ #define NO_BITPIX 222 /* Second keyword not BITPIX */ #define NO_NAXIS 223 /* Third keyword not NAXIS */ #define NO_NAXES 224 /* Couldn't find all the NAXISn keywords */ #define NO_XTENSION 225 /* HDU doesn't start with XTENSION keyword */ #define NOT_ATABLE 226 /* the CHDU is not an ASCII table extension */ #define NOT_BTABLE 227 /* the CHDU is not a binary table extension */ #define NO_PCOUNT 228 /* couldn't find PCOUNT keyword */ #define NO_GCOUNT 229 /* couldn't find GCOUNT keyword */ #define NO_TFIELDS 230 /* couldn't find TFIELDS keyword */ #define NO_TBCOL 231 /* couldn't find TBCOLn keyword */ #define NO_TFORM 232 /* couldn't find TFORMn keyword */ #define NOT_IMAGE 233 /* the CHDU is not an IMAGE extension */ #define BAD_TBCOL 234 /* TBCOLn keyword value < 0 or > rowlength */ #define NOT_TABLE 235 /* the CHDU is not a table */ #define COL_TOO_WIDE 236 /* column is too wide to fit in table */ #define COL_NOT_UNIQUE 237 /* more than 1 column name matches template */ #define BAD_ROW_WIDTH 241 /* sum of column widths not = NAXIS1 */ #define UNKNOWN_EXT 251 /* unrecognizable FITS extension type */ #define UNKNOWN_REC 252 /* unrecognizable FITS record */ #define END_JUNK 253 /* END keyword is not blank */ #define BAD_HEADER_FILL 254 /* Header fill area not blank */ #define BAD_DATA_FILL 255 /* Data fill area not blank or zero */ #define BAD_TFORM 261 /* illegal TFORM format code */ #define BAD_TFORM_DTYPE 262 /* unrecognizable TFORM datatype code */ #define BAD_TDIM 263 /* illegal TDIMn keyword value */ #define BAD_HEAP_PTR 264 /* invalid BINTABLE heap address */ #define BAD_HDU_NUM 301 /* HDU number < 1 or > MAXHDU */ #define BAD_COL_NUM 302 /* column number < 1 or > tfields */ #define NEG_FILE_POS 304 /* tried to move before beginning of file */ #define NEG_BYTES 306 /* tried to read or write negative bytes */ #define BAD_ROW_NUM 307 /* illegal starting row number in table */ #define BAD_ELEM_NUM 308 /* illegal starting element number in vector */ #define NOT_ASCII_COL 309 /* this is not an ASCII string column */ #define NOT_LOGICAL_COL 310 /* this is not a logical datatype column */ #define BAD_ATABLE_FORMAT 311 /* ASCII table column has wrong format */ #define BAD_BTABLE_FORMAT 312 /* Binary table column has wrong format */ #define NO_NULL 314 /* null value has not been defined */ #define NOT_VARI_LEN 317 /* this is not a variable length column */ #define BAD_DIMEN 320 /* illegal number of dimensions in array */ #define BAD_PIX_NUM 321 /* first pixel number greater than last pixel */ #define ZERO_SCALE 322 /* illegal BSCALE or TSCALn keyword = 0 */ #define NEG_AXIS 323 /* illegal axis length < 1 */ #define NOT_GROUP_TABLE 340 #define HDU_ALREADY_MEMBER 341 #define MEMBER_NOT_FOUND 342 #define GROUP_NOT_FOUND 343 #define BAD_GROUP_ID 344 #define TOO_MANY_HDUS_TRACKED 345 #define HDU_ALREADY_TRACKED 346 #define BAD_OPTION 347 #define IDENTICAL_POINTERS 348 #define BAD_GROUP_ATTACH 349 #define BAD_GROUP_DETACH 350 #define BAD_I2C 401 /* bad int to formatted string conversion */ #define BAD_F2C 402 /* bad float to formatted string conversion */ #define BAD_INTKEY 403 /* can't interprete keyword value as integer */ #define BAD_LOGICALKEY 404 /* can't interprete keyword value as logical */ #define BAD_FLOATKEY 405 /* can't interprete keyword value as float */ #define BAD_DOUBLEKEY 406 /* can't interprete keyword value as double */ #define BAD_C2I 407 /* bad formatted string to int conversion */ #define BAD_C2F 408 /* bad formatted string to float conversion */ #define BAD_C2D 409 /* bad formatted string to double conversion */ #define BAD_DATATYPE 410 /* bad keyword datatype code */ #define BAD_DECIM 411 /* bad number of decimal places specified */ #define NUM_OVERFLOW 412 /* overflow during datatype conversion */ # define DATA_COMPRESSION_ERR 413 /* error in imcompress routines */ # define DATA_DECOMPRESSION_ERR 414 /* error in imcompress routines */ # define NO_COMPRESSED_TILE 415 /* compressed tile doesn't exist */ #define BAD_DATE 420 /* error in date or time conversion */ #define PARSE_SYNTAX_ERR 431 /* syntax error in parser expression */ #define PARSE_BAD_TYPE 432 /* expression did not evaluate to desired type */ #define PARSE_LRG_VECTOR 433 /* vector result too large to return in array */ #define PARSE_NO_OUTPUT 434 /* data parser failed not sent an out column */ #define PARSE_BAD_COL 435 /* bad data encounter while parsing column */ #define PARSE_BAD_OUTPUT 436 /* Output file not of proper type */ #define ANGLE_TOO_BIG 501 /* celestial angle too large for projection */ #define BAD_WCS_VAL 502 /* bad celestial coordinate or pixel value */ #define WCS_ERROR 503 /* error in celestial coordinate calculation */ #define BAD_WCS_PROJ 504 /* unsupported type of celestial projection */ #define NO_WCS_KEY 505 /* celestial coordinate keywords not found */ #define APPROX_WCS_KEY 506 /* approximate WCS keywords were calculated */ #define NO_CLOSE_ERROR 999 /* special value used internally to switch off */ /* the error message from ffclos and ffchdu */ /*------- following error codes are used in the grparser.c file -----------*/ #define NGP_ERRBASE (360) /* base chosen so not to interfere with CFITSIO */ #define NGP_OK (0) #define NGP_NO_MEMORY (NGP_ERRBASE + 0) /* malloc failed */ #define NGP_READ_ERR (NGP_ERRBASE + 1) /* read error from file */ #define NGP_NUL_PTR (NGP_ERRBASE + 2) /* null pointer passed as argument */ #define NGP_EMPTY_CURLINE (NGP_ERRBASE + 3) /* line read seems to be empty */ #define NGP_UNREAD_QUEUE_FULL (NGP_ERRBASE + 4) /* cannot unread more then 1 line (or single line twice) */ #define NGP_INC_NESTING (NGP_ERRBASE + 5) /* too deep include file nesting (inf. loop ?) */ #define NGP_ERR_FOPEN (NGP_ERRBASE + 6) /* fopen() failed, cannot open file */ #define NGP_EOF (NGP_ERRBASE + 7) /* end of file encountered */ #define NGP_BAD_ARG (NGP_ERRBASE + 8) /* bad arguments passed */ #define NGP_TOKEN_NOT_EXPECT (NGP_ERRBASE + 9) /* token not expected here */ /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ /* the following 3 lines are needed to support C++ compilers */ #ifdef __cplusplus extern "C" { #endif #endif int CFITS2Unit( fitsfile *fptr ); CFITS_API fitsfile* CUnit2FITS(int unit); /*---------------- FITS file URL parsing routines -------------*/ int CFITS_API fits_get_token (char **ptr, char *delimiter, char *token, int *isanumber); int CFITS_API fits_get_token2(char **ptr, char *delimiter, char **token, int *isanumber, int *status); char CFITS_API *fits_split_names(char *list); int CFITS_API ffiurl( char *url, char *urltype, char *infile, char *outfile, char *extspec, char *rowfilter, char *binspec, char *colspec, int *status); int CFITS_API ffifile (char *url, char *urltype, char *infile, char *outfile, char *extspec, char *rowfilter, char *binspec, char *colspec, char *pixfilter, int *status); int CFITS_API ffifile2 (char *url, char *urltype, char *infile, char *outfile, char *extspec, char *rowfilter, char *binspec, char *colspec, char *pixfilter, char *compspec, int *status); int CFITS_API ffrtnm(char *url, char *rootname, int *status); int CFITS_API ffexist(const char *infile, int *exists, int *status); int CFITS_API ffexts(char *extspec, int *extnum, char *extname, int *extvers, int *hdutype, char *colname, char *rowexpress, int *status); int CFITS_API ffextn(char *url, int *extension_num, int *status); int CFITS_API ffurlt(fitsfile *fptr, char *urlType, int *status); int CFITS_API ffbins(char *binspec, int *imagetype, int *haxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double *weight, char *wtname, int *recip, int *status); int CFITS_API ffbinr(char **binspec, char *colname, double *minin, double *maxin, double *binsizein, char *minname, char *maxname, char *binname, int *status); int CFITS_API fits_copy_cell2image(fitsfile *fptr, fitsfile *newptr, char *colname, long rownum, int *status); int CFITS_API fits_copy_image2cell(fitsfile *fptr, fitsfile *newptr, char *colname, long rownum, int copykeyflag, int *status); int CFITS_API fits_copy_pixlist2image(fitsfile *infptr, fitsfile *outfptr, int firstkey, /* I - first HDU record number to start with */ int naxis, int *colnum, int *status); int CFITS_API ffimport_file( char *filename, char **contents, int *status ); int CFITS_API ffrwrg( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges, long *minrow, long *maxrow, int *status); int CFITS_API ffrwrgll( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges, LONGLONG *minrow, LONGLONG *maxrow, int *status); /*---------------- FITS file I/O routines -------------*/ int CFITS_API fits_init_cfitsio(void); int CFITS_API ffomem(fitsfile **fptr, const char *name, int mode, void **buffptr, size_t *buffsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status); int CFITS_API ffopen(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffopentest(int soname, fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffdopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffeopn(fitsfile **fptr, const char *filename, int iomode, char *extlist, int *hdutype, int *status); int CFITS_API fftopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffiopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffdkopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffreopen(fitsfile *openfptr, fitsfile **newfptr, int *status); int CFITS_API ffinit( fitsfile **fptr, const char *filename, int *status); int CFITS_API ffdkinit(fitsfile **fptr, const char *filename, int *status); int CFITS_API ffimem(fitsfile **fptr, void **buffptr, size_t *buffsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status); int CFITS_API fftplt(fitsfile **fptr, const char *filename, const char *tempname, int *status); int CFITS_API ffflus(fitsfile *fptr, int *status); int CFITS_API ffflsh(fitsfile *fptr, int clearbuf, int *status); int CFITS_API ffclos(fitsfile *fptr, int *status); int CFITS_API ffdelt(fitsfile *fptr, int *status); int CFITS_API ffflnm(fitsfile *fptr, char *filename, int *status); int CFITS_API ffflmd(fitsfile *fptr, int *filemode, int *status); int CFITS_API fits_delete_iraf_file(const char *filename, int *status); /*---------------- utility routines -------------*/ float CFITS_API ffvers(float *version); void CFITS_API ffupch(char *string); void CFITS_API ffgerr(int status, char *errtext); void CFITS_API ffpmsg(const char *err_message); void CFITS_API ffpmrk(void); int CFITS_API ffgmsg(char *err_message); void CFITS_API ffcmsg(void); void CFITS_API ffcmrk(void); void CFITS_API ffrprt(FILE *stream, int status); void CFITS_API ffcmps(char *templt, char *colname, int casesen, int *match, int *exact); int CFITS_API fftkey(const char *keyword, int *status); int CFITS_API fftrec(char *card, int *status); int CFITS_API ffnchk(fitsfile *fptr, int *status); int CFITS_API ffkeyn(const char *keyroot, int value, char *keyname, int *status); int CFITS_API ffnkey(int value, const char *keyroot, char *keyname, int *status); int CFITS_API ffgkcl(char *card); int CFITS_API ffdtyp(const char *cval, char *dtype, int *status); int CFITS_API ffinttyp(char *cval, int *datatype, int *negative, int *status); int CFITS_API ffpsvc(char *card, char *value, char *comm, int *status); int CFITS_API ffgknm(char *card, char *name, int *length, int *status); int CFITS_API ffgthd(char *tmplt, char *card, int *hdtype, int *status); int CFITS_API ffmkky(const char *keyname, char *keyval, const char *comm, char *card, int *status); int CFITS_API fits_translate_keyword(char *inrec, char *outrec, char *patterns[][2], int npat, int n_value, int n_offset, int n_range, int *pat_num, int *i, int *j, int *m, int *n, int *status); int CFITS_API fits_translate_keywords(fitsfile *infptr, fitsfile *outfptr, int firstkey, char *patterns[][2], int npat, int n_value, int n_offset, int n_range, int *status); int CFITS_API ffasfm(char *tform, int *datacode, long *width, int *decim, int *status); int CFITS_API ffbnfm(char *tform, int *datacode, long *repeat, long *width, int *status); int CFITS_API ffbnfmll(char *tform, int *datacode, LONGLONG *repeat, long *width, int *status); int CFITS_API ffgabc(int tfields, char **tform, int space, long *rowlen, long *tbcol, int *status); int CFITS_API fits_get_section_range(char **ptr,long *secmin,long *secmax,long *incre, int *status); /* ffmbyt should not normally be used in application programs, but it is defined here as a publicly available routine because there are a few rare cases where it is needed */ int CFITS_API ffmbyt(fitsfile *fptr, LONGLONG bytpos, int ignore_err, int *status); /*----------------- write single keywords --------------*/ int CFITS_API ffpky(fitsfile *fptr, int datatype, const char *keyname, void *value, const char *comm, int *status); int CFITS_API ffprec(fitsfile *fptr, const char *card, int *status); int CFITS_API ffpcom(fitsfile *fptr, const char *comm, int *status); int CFITS_API ffpunt(fitsfile *fptr, const char *keyname, const char *unit, int *status); int CFITS_API ffphis(fitsfile *fptr, const char *history, int *status); int CFITS_API ffpdat(fitsfile *fptr, int *status); int CFITS_API ffverifydate(int year, int month, int day, int *status); int CFITS_API ffgstm(char *timestr, int *timeref, int *status); int CFITS_API ffgsdt(int *day, int *month, int *year, int *status); int CFITS_API ffdt2s(int year, int month, int day, char *datestr, int *status); int CFITS_API fftm2s(int year, int month, int day, int hour, int minute, double second, int decimals, char *datestr, int *status); int CFITS_API ffs2dt(char *datestr, int *year, int *month, int *day, int *status); int CFITS_API ffs2tm(char *datestr, int *year, int *month, int *day, int *hour, int *minute, double *second, int *status); int CFITS_API ffpkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffpkys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffpkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffplsw(fitsfile *fptr, int *status); int CFITS_API ffpkyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffpkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffpkyuj(fitsfile *fptr, const char *keyname, ULONGLONG value, const char *comm, int *status); int CFITS_API ffpkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffpkye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffpkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffpkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffpkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffpkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffpkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffpkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffpkyt(fitsfile *fptr, const char *keyname, long intval, double frac, const char *comm, int *status); int CFITS_API ffptdm( fitsfile *fptr, int colnum, int naxis, long naxes[], int *status); int CFITS_API ffptdmll( fitsfile *fptr, int colnum, int naxis, LONGLONG naxes[], int *status); /*----------------- write array of keywords --------------*/ int CFITS_API ffpkns(fitsfile *fptr, const char *keyroot, int nstart, int nkey, char *value[], char *comm[], int *status); int CFITS_API ffpknl(fitsfile *fptr, const char *keyroot, int nstart, int nkey, int *value, char *comm[], int *status); int CFITS_API ffpknj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, long *value, char *comm[], int *status); int CFITS_API ffpknjj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, LONGLONG *value, char *comm[], int *status); int CFITS_API ffpknf(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value, int decim, char *comm[], int *status); int CFITS_API ffpkne(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value, int decim, char *comm[], int *status); int CFITS_API ffpkng(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value, int decim, char *comm[], int *status); int CFITS_API ffpknd(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value, int decim, char *comm[], int *status); int CFITS_API ffcpky(fitsfile *infptr,fitsfile *outfptr,int incol,int outcol, char *rootname, int *status); /*----------------- write required header keywords --------------*/ int CFITS_API ffphps( fitsfile *fptr, int bitpix, int naxis, long naxes[], int *status); int CFITS_API ffphpsll( fitsfile *fptr, int bitpix, int naxis, LONGLONG naxes[], int *status); int CFITS_API ffphpr( fitsfile *fptr, int simple, int bitpix, int naxis, long naxes[], LONGLONG pcount, LONGLONG gcount, int extend, int *status); int CFITS_API ffphprll( fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG naxes[], LONGLONG pcount, LONGLONG gcount, int extend, int *status); int CFITS_API ffphtb(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype, long *tbcol, char **tform, char **tunit, const char *extname, int *status); int CFITS_API ffphbn(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, char **tform, char **tunit, const char *extname, LONGLONG pcount, int *status); int CFITS_API ffphext( fitsfile *fptr, const char *xtension, int bitpix, int naxis, long naxes[], LONGLONG pcount, LONGLONG gcount, int *status); /*----------------- write template keywords --------------*/ int CFITS_API ffpktp(fitsfile *fptr, const char *filename, int *status); /*------------------ get header information --------------*/ int CFITS_API ffghsp(fitsfile *fptr, int *nexist, int *nmore, int *status); int CFITS_API ffghps(fitsfile *fptr, int *nexist, int *position, int *status); /*------------------ move position in header -------------*/ int CFITS_API ffmaky(fitsfile *fptr, int nrec, int *status); int CFITS_API ffmrky(fitsfile *fptr, int nrec, int *status); /*------------------ read single keywords -----------------*/ int CFITS_API ffgnxk(fitsfile *fptr, char **inclist, int ninc, char **exclist, int nexc, char *card, int *status); int CFITS_API ffgrec(fitsfile *fptr, int nrec, char *card, int *status); int CFITS_API ffgcrd(fitsfile *fptr, const char *keyname, char *card, int *status); int CFITS_API ffgstr(fitsfile *fptr, const char *string, char *card, int *status); int CFITS_API ffgunt(fitsfile *fptr, const char *keyname, char *unit, int *status); int CFITS_API ffgkyn(fitsfile *fptr, int nkey, char *keyname, char *keyval, char *comm, int *status); int CFITS_API ffgkey(fitsfile *fptr, const char *keyname, char *keyval, char *comm, int *status); int CFITS_API ffgky( fitsfile *fptr, int datatype, const char *keyname, void *value, char *comm, int *status); int CFITS_API ffgkys(fitsfile *fptr, const char *keyname, char *value, char *comm, int *status); int CFITS_API ffgksl(fitsfile *fptr, const char *keyname, int *length, int *status); int CFITS_API ffgkcsl(fitsfile *fptr, const char *keyname, int *length, int *comlength, int *status); int CFITS_API ffgkls(fitsfile *fptr, const char *keyname, char **value, char *comm, int *status); int CFITS_API ffgsky(fitsfile *fptr, const char *keyname, int firstchar, int maxchar, char *value, int *valuelen, char *comm, int *status); int CFITS_API ffgskyc(fitsfile *fptr, const char *keyname, int firstchar, int maxchar, int maxcomchar, char *value, int *valuelen, char *comm, int *comlen, int *status); int CFITS_API fffree(void *value, int *status); int CFITS_API fffkls(char *value, int *status); int CFITS_API ffgkyl(fitsfile *fptr, const char *keyname, int *value, char *comm, int *status); int CFITS_API ffgkyj(fitsfile *fptr, const char *keyname, long *value, char *comm, int *status); int CFITS_API ffgkyjj(fitsfile *fptr, const char *keyname, LONGLONG *value, char *comm, int *status); int CFITS_API ffgkyujj(fitsfile *fptr, const char *keyname, ULONGLONG *value, char *comm, int *status); int CFITS_API ffgkye(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status); int CFITS_API ffgkyd(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status); int CFITS_API ffgkyc(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status); int CFITS_API ffgkym(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status); int CFITS_API ffgkyt(fitsfile *fptr, const char *keyname, long *ivalue, double *dvalue, char *comm, int *status); int CFITS_API ffgtdm(fitsfile *fptr, int colnum, int maxdim, int *naxis, long naxes[], int *status); int CFITS_API ffgtdmll(fitsfile *fptr, int colnum, int maxdim, int *naxis, LONGLONG naxes[], int *status); int CFITS_API ffdtdm(fitsfile *fptr, char *tdimstr, int colnum, int maxdim, int *naxis, long naxes[], int *status); int CFITS_API ffdtdmll(fitsfile *fptr, char *tdimstr, int colnum, int maxdim, int *naxis, LONGLONG naxes[], int *status); /*------------------ read array of keywords -----------------*/ int CFITS_API ffgkns(fitsfile *fptr, const char *keyname, int nstart, int nmax, char *value[], int *nfound, int *status); int CFITS_API ffgknl(fitsfile *fptr, const char *keyname, int nstart, int nmax, int *value, int *nfound, int *status); int CFITS_API ffgknj(fitsfile *fptr, const char *keyname, int nstart, int nmax, long *value, int *nfound, int *status); int CFITS_API ffgknjj(fitsfile *fptr, const char *keyname, int nstart, int nmax, LONGLONG *value, int *nfound, int *status); int CFITS_API ffgkne(fitsfile *fptr, const char *keyname, int nstart, int nmax, float *value, int *nfound, int *status); int CFITS_API ffgknd(fitsfile *fptr, const char *keyname, int nstart, int nmax, double *value, int *nfound, int *status); int CFITS_API ffh2st(fitsfile *fptr, char **header, int *status); int CFITS_API ffhdr2str( fitsfile *fptr, int exclude_comm, char **exclist, int nexc, char **header, int *nkeys, int *status); int CFITS_API ffcnvthdr2str( fitsfile *fptr, int exclude_comm, char **exclist, int nexc, char **header, int *nkeys, int *status); /*----------------- read required header keywords --------------*/ int CFITS_API ffghpr(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, long naxes[], long *pcount, long *gcount, int *extend, int *status); int CFITS_API ffghprll(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, LONGLONG naxes[], long *pcount, long *gcount, int *extend, int *status); int CFITS_API ffghtb(fitsfile *fptr,int maxfield, long *naxis1, long *naxis2, int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, char *extname, int *status); int CFITS_API ffghtbll(fitsfile *fptr,int maxfield, LONGLONG *naxis1, LONGLONG *naxis2, int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, char *extname, int *status); int CFITS_API ffghbn(fitsfile *fptr, int maxfield, long *naxis2, int *tfields, char **ttype, char **tform, char **tunit, char *extname, long *pcount, int *status); int CFITS_API ffghbnll(fitsfile *fptr, int maxfield, LONGLONG *naxis2, int *tfields, char **ttype, char **tform, char **tunit, char *extname, LONGLONG *pcount, int *status); /*--------------------- update keywords ---------------*/ int CFITS_API ffuky(fitsfile *fptr, int datatype, const char *keyname, void *value, const char *comm, int *status); int CFITS_API ffucrd(fitsfile *fptr, const char *keyname, const char *card, int *status); int CFITS_API ffukyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffukys(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int *status); int CFITS_API ffukls(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int *status); int CFITS_API ffukyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffukyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffukyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffukye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffukyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffukyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffukyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffukym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffukfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffukfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); /*--------------------- modify keywords ---------------*/ int CFITS_API ffmrec(fitsfile *fptr, int nkey, const char *card, int *status); int CFITS_API ffmcrd(fitsfile *fptr, const char *keyname, const char *card, int *status); int CFITS_API ffmnam(fitsfile *fptr, const char *oldname, const char *newname, int *status); int CFITS_API ffmcom(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffmkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffmkys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffmkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffmkyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffmkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffmkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffmkye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffmkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffmkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffmkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffmkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffmkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffmkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); /*--------------------- insert keywords ---------------*/ int CFITS_API ffirec(fitsfile *fptr, int nkey, const char *card, int *status); int CFITS_API ffikey(fitsfile *fptr, const char *card, int *status); int CFITS_API ffikyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffikys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffikls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffikyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffikyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffikyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffikye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffikyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffikyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffikyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffikym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffikfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffikfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); /*--------------------- delete keywords ---------------*/ int CFITS_API ffdkey(fitsfile *fptr, const char *keyname, int *status); int CFITS_API ffdstr(fitsfile *fptr, const char *string, int *status); int CFITS_API ffdrec(fitsfile *fptr, int keypos, int *status); /*--------------------- get HDU information -------------*/ int CFITS_API ffghdn(fitsfile *fptr, int *chdunum); int CFITS_API ffghdt(fitsfile *fptr, int *exttype, int *status); int CFITS_API ffghad(fitsfile *fptr, long *headstart, long *datastart, long *dataend, int *status); int CFITS_API ffghadll(fitsfile *fptr, LONGLONG *headstart, LONGLONG *datastart, LONGLONG *dataend, int *status); int CFITS_API ffghof(fitsfile *fptr, OFF_T *headstart, OFF_T *datastart, OFF_T *dataend, int *status); int CFITS_API ffgipr(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis, long *naxes, int *status); int CFITS_API ffgiprll(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis, LONGLONG *naxes, int *status); int CFITS_API ffgidt(fitsfile *fptr, int *imgtype, int *status); int CFITS_API ffgiet(fitsfile *fptr, int *imgtype, int *status); int CFITS_API ffgidm(fitsfile *fptr, int *naxis, int *status); int CFITS_API ffgisz(fitsfile *fptr, int nlen, long *naxes, int *status); int CFITS_API ffgiszll(fitsfile *fptr, int nlen, LONGLONG *naxes, int *status); /*--------------------- HDU operations -------------*/ int CFITS_API ffmahd(fitsfile *fptr, int hdunum, int *exttype, int *status); int CFITS_API ffmrhd(fitsfile *fptr, int hdumov, int *exttype, int *status); int CFITS_API ffmnhd(fitsfile *fptr, int exttype, char *hduname, int hduvers, int *status); int CFITS_API ffthdu(fitsfile *fptr, int *nhdu, int *status); int CFITS_API ffcrhd(fitsfile *fptr, int *status); int CFITS_API ffcrim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); int CFITS_API ffcrimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); int CFITS_API ffcrtb(fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char **ttype, char **tform, char **tunit, const char *extname, int *status); int CFITS_API ffiimg(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); int CFITS_API ffiimgll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); int CFITS_API ffitab(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype, long *tbcol, char **tform, char **tunit, const char *extname, int *status); int CFITS_API ffibin(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, char **tform, char **tunit, const char *extname, LONGLONG pcount, int *status); int CFITS_API ffrsim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); int CFITS_API ffrsimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); int CFITS_API ffdhdu(fitsfile *fptr, int *hdutype, int *status); int CFITS_API ffcopy(fitsfile *infptr, fitsfile *outfptr, int morekeys, int *status); int CFITS_API ffcpfl(fitsfile *infptr, fitsfile *outfptr, int prev, int cur, int follow, int *status); int CFITS_API ffcphd(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API ffcpdt(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API ffchfl(fitsfile *fptr, int *status); int CFITS_API ffcdfl(fitsfile *fptr, int *status); int CFITS_API ffwrhdu(fitsfile *fptr, FILE *outstream, int *status); int CFITS_API ffrdef(fitsfile *fptr, int *status); int CFITS_API ffrhdu(fitsfile *fptr, int *hdutype, int *status); int CFITS_API ffhdef(fitsfile *fptr, int morekeys, int *status); int CFITS_API ffpthp(fitsfile *fptr, long theap, int *status); int CFITS_API ffcsum(fitsfile *fptr, long nrec, unsigned long *sum, int *status); void CFITS_API ffesum(unsigned long sum, int complm, char *ascii); unsigned long CFITS_API ffdsum(char *ascii, int complm, unsigned long *sum); int CFITS_API ffpcks(fitsfile *fptr, int *status); int CFITS_API ffupck(fitsfile *fptr, int *status); int CFITS_API ffvcks(fitsfile *fptr, int *datastatus, int *hdustatus, int *status); int CFITS_API ffgcks(fitsfile *fptr, unsigned long *datasum, unsigned long *hdusum, int *status); /*--------------------- define scaling or null values -------------*/ int CFITS_API ffpscl(fitsfile *fptr, double scale, double zeroval, int *status); int CFITS_API ffpnul(fitsfile *fptr, LONGLONG nulvalue, int *status); int CFITS_API fftscl(fitsfile *fptr, int colnum, double scale, double zeroval, int *status); int CFITS_API fftnul(fitsfile *fptr, int colnum, LONGLONG nulvalue, int *status); int CFITS_API ffsnul(fitsfile *fptr, int colnum, char *nulstring, int *status); /*--------------------- get column information -------------*/ int CFITS_API ffgcno(fitsfile *fptr, int casesen, char *templt, int *colnum, int *status); int CFITS_API ffgcnn(fitsfile *fptr, int casesen, char *templt, char *colname, int *colnum, int *status); int CFITS_API ffgtcl(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status); int CFITS_API ffgtclll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat, LONGLONG *width, int *status); int CFITS_API ffeqty(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status); int CFITS_API ffeqtyll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat, LONGLONG *width, int *status); int CFITS_API ffgncl(fitsfile *fptr, int *ncols, int *status); int CFITS_API ffgnrw(fitsfile *fptr, long *nrows, int *status); int CFITS_API ffgnrwll(fitsfile *fptr, LONGLONG *nrows, int *status); int CFITS_API ffgacl(fitsfile *fptr, int colnum, char *ttype, long *tbcol, char *tunit, char *tform, double *tscal, double *tzero, char *tnull, char *tdisp, int *status); int CFITS_API ffgbcl(fitsfile *fptr, int colnum, char *ttype, char *tunit, char *dtype, long *repeat, double *tscal, double *tzero, long *tnull, char *tdisp, int *status); int CFITS_API ffgbclll(fitsfile *fptr, int colnum, char *ttype, char *tunit, char *dtype, LONGLONG *repeat, double *tscal, double *tzero, LONGLONG *tnull, char *tdisp, int *status); int CFITS_API ffgrsz(fitsfile *fptr, long *nrows, int *status); int CFITS_API ffgcdw(fitsfile *fptr, int colnum, int *width, int *status); /*--------------------- read primary array or image elements -------------*/ int CFITS_API ffgpxv(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpxvll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpxf(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgpxfll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgsv(fitsfile *fptr, int datatype, long *blc, long *trc, long *inc, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpv(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpf(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgpvb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char nulval, unsigned char *array, int *anynul, int *status); int CFITS_API ffgpvsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char nulval, signed char *array, int *anynul, int *status); int CFITS_API ffgpvui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short nulval, unsigned short *array, int *anynul, int *status); int CFITS_API ffgpvi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short nulval, short *array, int *anynul, int *status); int CFITS_API ffgpvuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long nulval, unsigned long *array, int *anynul, int *status); int CFITS_API ffgpvj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long nulval, long *array, int *anynul, int *status); int CFITS_API ffgpvujj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, ULONGLONG nulval, ULONGLONG *array, int *anynul, int *status); int CFITS_API ffgpvjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG nulval, LONGLONG *array, int *anynul, int *status); int CFITS_API ffgpvuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int nulval, unsigned int *array, int *anynul, int *status); int CFITS_API ffgpvk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int nulval, int *array, int *anynul, int *status); int CFITS_API ffgpve(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgpvd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgpfb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfujj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, ULONGLONG *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfe(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); int CFITS_API ffg2db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned char *array, int *anynul, int *status); int CFITS_API ffg2dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, signed char *array, int *anynul, int *status); int CFITS_API ffg2dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned short *array, int *anynul, int *status); int CFITS_API ffg2di(fitsfile *fptr, long group, short nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, short *array, int *anynul, int *status); int CFITS_API ffg2duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned long *array, int *anynul, int *status); int CFITS_API ffg2dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, long *array, int *anynul, int *status); int CFITS_API ffg2dujj(fitsfile *fptr, long group, ULONGLONG nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, ULONGLONG *array, int *anynul, int *status); int CFITS_API ffg2djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, LONGLONG *array, int *anynul, int *status); int CFITS_API ffg2duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned int *array, int *anynul, int *status); int CFITS_API ffg2dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, int *array, int *anynul, int *status); int CFITS_API ffg2de(fitsfile *fptr, long group, float nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, float *array, int *anynul, int *status); int CFITS_API ffg2dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, double *array, int *anynul, int *status); int CFITS_API ffg3db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned char *array, int *anynul, int *status); int CFITS_API ffg3dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, signed char *array, int *anynul, int *status); int CFITS_API ffg3dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned short *array, int *anynul, int *status); int CFITS_API ffg3di(fitsfile *fptr, long group, short nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, short *array, int *anynul, int *status); int CFITS_API ffg3duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned long *array, int *anynul, int *status); int CFITS_API ffg3dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, long *array, int *anynul, int *status); int CFITS_API ffg3dujj(fitsfile *fptr, long group, ULONGLONG nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, ULONGLONG *array, int *anynul, int *status); int CFITS_API ffg3djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, LONGLONG *array, int *anynul, int *status); int CFITS_API ffg3duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned int *array, int *anynul, int *status); int CFITS_API ffg3dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, int *array, int *anynul, int *status); int CFITS_API ffg3de(fitsfile *fptr, long group, float nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, float *array, int *anynul, int *status); int CFITS_API ffg3dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, double *array, int *anynul, int *status); int CFITS_API ffgsvb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char nulval, unsigned char *array, int *anynul, int *status); int CFITS_API ffgsvsb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, signed char nulval, signed char *array, int *anynul, int *status); int CFITS_API ffgsvui(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned short nulval, unsigned short *array, int *anynul, int *status); int CFITS_API ffgsvi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, short nulval, short *array, int *anynul, int *status); int CFITS_API ffgsvuj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned long nulval, unsigned long *array, int *anynul, int *status); int CFITS_API ffgsvj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, long nulval, long *array, int *anynul, int *status); int CFITS_API ffgsvujj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, ULONGLONG nulval, ULONGLONG *array, int *anynul, int *status); int CFITS_API ffgsvjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, LONGLONG nulval, LONGLONG *array, int *anynul, int *status); int CFITS_API ffgsvuk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned int nulval, unsigned int *array, int *anynul, int *status); int CFITS_API ffgsvk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, int nulval, int *array, int *anynul, int *status); int CFITS_API ffgsve(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgsvd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgsfb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfsb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, signed char *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfui(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned short *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, short *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfuj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned long *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, long *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfujj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, ULONGLONG *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, LONGLONG *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfuk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned int *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, int *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfe(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, float *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, double *array, char *flagval, int *anynul, int *status); int CFITS_API ffggpb(fitsfile *fptr, long group, long firstelem, long nelem, unsigned char *array, int *status); int CFITS_API ffggpsb(fitsfile *fptr, long group, long firstelem, long nelem, signed char *array, int *status); int CFITS_API ffggpui(fitsfile *fptr, long group, long firstelem, long nelem, unsigned short *array, int *status); int CFITS_API ffggpi(fitsfile *fptr, long group, long firstelem, long nelem, short *array, int *status); int CFITS_API ffggpuj(fitsfile *fptr, long group, long firstelem, long nelem, unsigned long *array, int *status); int CFITS_API ffggpj(fitsfile *fptr, long group, long firstelem, long nelem, long *array, int *status); int CFITS_API ffggpujj(fitsfile *fptr, long group, long firstelem, long nelem, ULONGLONG *array, int *status); int CFITS_API ffggpjj(fitsfile *fptr, long group, long firstelem, long nelem, LONGLONG *array, int *status); int CFITS_API ffggpuk(fitsfile *fptr, long group, long firstelem, long nelem, unsigned int *array, int *status); int CFITS_API ffggpk(fitsfile *fptr, long group, long firstelem, long nelem, int *array, int *status); int CFITS_API ffggpe(fitsfile *fptr, long group, long firstelem, long nelem, float *array, int *status); int CFITS_API ffggpd(fitsfile *fptr, long group, long firstelem, long nelem, double *array, int *status); /*--------------------- read column elements -------------*/ int CFITS_API ffgcv( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgcvn (fitsfile *fptr, int ncols, int *datatype, int *colnum, LONGLONG firstrow, LONGLONG nrows, void **nulval, void **array, int *anynul, int *status); int CFITS_API ffgcf( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgcvs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *nulval, char **array, int *anynul, int *status); int CFITS_API ffgcl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, int *status); int CFITS_API ffgcvl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char nulval, char *array, int *anynul, int *status); int CFITS_API ffgcvb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char nulval, unsigned char *array, int *anynul, int *status); int CFITS_API ffgcvsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char nulval, signed char *array, int *anynul, int *status); int CFITS_API ffgcvui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short nulval, unsigned short *array, int *anynul, int *status); int CFITS_API ffgcvi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short nulval, short *array, int *anynul, int *status); int CFITS_API ffgcvuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long nulval, unsigned long *array, int *anynul, int *status); int CFITS_API ffgcvj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long nulval, long *array, int *anynul, int *status); int CFITS_API ffgcvujj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, ULONGLONG nulval, ULONGLONG *array, int *anynul, int *status); int CFITS_API ffgcvjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG nulval, LONGLONG *array, int *anynul, int *status); int CFITS_API ffgcvuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int nulval, unsigned int *array, int *anynul, int *status); int CFITS_API ffgcvk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nulval, int *array, int *anynul, int *status); int CFITS_API ffgcve(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgcvd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgcvc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgcvm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgcx(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, LONGLONG nbits, char *larray, int *status); int CFITS_API ffgcxui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long firstbit, int nbits, unsigned short *array, int *status); int CFITS_API ffgcxuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long firstbit, int nbits, unsigned int *array, int *status); int CFITS_API ffgcfs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char **array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfl(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfujj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, ULONGLONG *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfe(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); int CFITS_API ffgdes(fitsfile *fptr, int colnum, LONGLONG rownum, long *length, long *heapaddr, int *status); int CFITS_API ffgdesll(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG *length, LONGLONG *heapaddr, int *status); int CFITS_API ffgdess(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long *length, long *heapaddr, int *status); int CFITS_API ffgdessll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, LONGLONG *length, LONGLONG *heapaddr, int *status); int CFITS_API ffpdes(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG length, LONGLONG heapaddr, int *status); int CFITS_API fftheap(fitsfile *fptr, LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, int *valid, int *status); int CFITS_API ffcmph(fitsfile *fptr, int *status); int CFITS_API ffgtbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, unsigned char *values, int *status); int CFITS_API ffgextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status); int CFITS_API ffpextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status); /*------------ write primary array or image elements -------------*/ int CFITS_API ffppx(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *array, int *status); int CFITS_API ffppxll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *array, int *status); int CFITS_API ffppxn(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffppxnll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffppr(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *array, int *status); int CFITS_API ffpprb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, int *status); int CFITS_API ffpprsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char *array, int *status); int CFITS_API ffpprui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, int *status); int CFITS_API ffppri(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short *array, int *status); int CFITS_API ffppruj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, int *status); int CFITS_API ffpprj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long *array, int *status); int CFITS_API ffppruk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, int *status); int CFITS_API ffpprk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *array, int *status); int CFITS_API ffppre(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float *array, int *status); int CFITS_API ffpprd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double *array, int *status); int CFITS_API ffpprjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, int *status); int CFITS_API ffpprujj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, ULONGLONG *array, int *status); int CFITS_API ffppru(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *status); int CFITS_API ffpprn(fitsfile *fptr, LONGLONG firstelem, LONGLONG nelem, int *status); int CFITS_API ffppn(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffppnb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, unsigned char nulval, int *status); int CFITS_API ffppnsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char *array, signed char nulval, int *status); int CFITS_API ffppnui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, unsigned short nulval, int *status); int CFITS_API ffppni(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short *array, short nulval, int *status); int CFITS_API ffppnj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long *array, long nulval, int *status); int CFITS_API ffppnuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, unsigned long nulval, int *status); int CFITS_API ffppnuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, unsigned int nulval, int *status); int CFITS_API ffppnk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *array, int nulval, int *status); int CFITS_API ffppne(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float *array, float nulval, int *status); int CFITS_API ffppnd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double *array, double nulval, int *status); int CFITS_API ffppnjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, LONGLONG nulval, int *status); int CFITS_API ffppnujj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, ULONGLONG *array, ULONGLONG nulval, int *status); int CFITS_API ffp2db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned char *array, int *status); int CFITS_API ffp2dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, signed char *array, int *status); int CFITS_API ffp2dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned short *array, int *status); int CFITS_API ffp2di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, short *array, int *status); int CFITS_API ffp2duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned long *array, int *status); int CFITS_API ffp2dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, long *array, int *status); int CFITS_API ffp2duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned int *array, int *status); int CFITS_API ffp2dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, int *array, int *status); int CFITS_API ffp2de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, float *array, int *status); int CFITS_API ffp2dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, double *array, int *status); int CFITS_API ffp2djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, LONGLONG *array, int *status); int CFITS_API ffp2dujj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, ULONGLONG *array, int *status); int CFITS_API ffp3db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned char *array, int *status); int CFITS_API ffp3dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, signed char *array, int *status); int CFITS_API ffp3dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned short *array, int *status); int CFITS_API ffp3di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, short *array, int *status); int CFITS_API ffp3duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned long *array, int *status); int CFITS_API ffp3dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, long *array, int *status); int CFITS_API ffp3duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned int *array, int *status); int CFITS_API ffp3dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, int *array, int *status); int CFITS_API ffp3de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, float *array, int *status); int CFITS_API ffp3dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, double *array, int *status); int CFITS_API ffp3djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, LONGLONG *array, int *status); int CFITS_API ffp3dujj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, ULONGLONG *array, int *status); int CFITS_API ffpss(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, void *array, int *status); int CFITS_API ffpssb(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned char *array, int *status); int CFITS_API ffpsssb(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, signed char *array, int *status); int CFITS_API ffpssui(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned short *array, int *status); int CFITS_API ffpssi(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, short *array, int *status); int CFITS_API ffpssuj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned long *array, int *status); int CFITS_API ffpssj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, long *array, int *status); int CFITS_API ffpssuk(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned int *array, int *status); int CFITS_API ffpssk(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, int *array, int *status); int CFITS_API ffpsse(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, float *array, int *status); int CFITS_API ffpssd(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, double *array, int *status); int CFITS_API ffpssjj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, LONGLONG *array, int *status); int CFITS_API ffpssujj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, ULONGLONG *array, int *status); int CFITS_API ffpgpb(fitsfile *fptr, long group, long firstelem, long nelem, unsigned char *array, int *status); int CFITS_API ffpgpsb(fitsfile *fptr, long group, long firstelem, long nelem, signed char *array, int *status); int CFITS_API ffpgpui(fitsfile *fptr, long group, long firstelem, long nelem, unsigned short *array, int *status); int CFITS_API ffpgpi(fitsfile *fptr, long group, long firstelem, long nelem, short *array, int *status); int CFITS_API ffpgpuj(fitsfile *fptr, long group, long firstelem, long nelem, unsigned long *array, int *status); int CFITS_API ffpgpj(fitsfile *fptr, long group, long firstelem, long nelem, long *array, int *status); int CFITS_API ffpgpuk(fitsfile *fptr, long group, long firstelem, long nelem, unsigned int *array, int *status); int CFITS_API ffpgpk(fitsfile *fptr, long group, long firstelem, long nelem, int *array, int *status); int CFITS_API ffpgpe(fitsfile *fptr, long group, long firstelem, long nelem, float *array, int *status); int CFITS_API ffpgpd(fitsfile *fptr, long group, long firstelem, long nelem, double *array, int *status); int CFITS_API ffpgpjj(fitsfile *fptr, long group, long firstelem, long nelem, LONGLONG *array, int *status); int CFITS_API ffpgpujj(fitsfile *fptr, long group, long firstelem, long nelem, ULONGLONG *array, int *status); /*--------------------- iterator functions -------------*/ int CFITS_API fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, char *colname, int datatype, int iotype); int CFITS_API fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, int colnum, int datatype, int iotype); int CFITS_API fits_iter_set_file(iteratorCol *col, fitsfile *fptr); int CFITS_API fits_iter_set_colname(iteratorCol *col, char *colname); int CFITS_API fits_iter_set_colnum(iteratorCol *col, int colnum); int CFITS_API fits_iter_set_datatype(iteratorCol *col, int datatype); int CFITS_API fits_iter_set_iotype(iteratorCol *col, int iotype); CFITS_API fitsfile * fits_iter_get_file(iteratorCol *col); char CFITS_API * fits_iter_get_colname(iteratorCol *col); int CFITS_API fits_iter_get_colnum(iteratorCol *col); int CFITS_API fits_iter_get_datatype(iteratorCol *col); int CFITS_API fits_iter_get_iotype(iteratorCol *col); void CFITS_API *fits_iter_get_array(iteratorCol *col); long CFITS_API fits_iter_get_tlmin(iteratorCol *col); long CFITS_API fits_iter_get_tlmax(iteratorCol *col); long CFITS_API fits_iter_get_repeat(iteratorCol *col); char CFITS_API *fits_iter_get_tunit(iteratorCol *col); char CFITS_API *fits_iter_get_tdisp(iteratorCol *col); int CFITS_API ffiter(int ncols, iteratorCol *data, long offset, long nPerLoop, int (*workFn)( long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *data, void *userPointer), void *userPointer, int *status); /*--------------------- write column elements -------------*/ int CFITS_API ffpcl(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *array, int *status); int CFITS_API ffpcln(fitsfile *fptr, int ncols, int *datatype, int *colnum, LONGLONG firstrow, LONGLONG nrows, void **array, void **nulval, int *status); int CFITS_API ffpcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char **array, int *status); int CFITS_API ffpcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, int *status); int CFITS_API ffpclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, int *status); int CFITS_API ffpclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char *array, int *status); int CFITS_API ffpclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, int *status); int CFITS_API ffpcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short *array, int *status); int CFITS_API ffpcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, int *status); int CFITS_API ffpclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long *array, int *status); int CFITS_API ffpcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, int *status); int CFITS_API ffpclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *array, int *status); int CFITS_API ffpcle(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, int *status); int CFITS_API ffpcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, int *status); int CFITS_API ffpclc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, int *status); int CFITS_API ffpclm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, int *status); int CFITS_API ffpclu(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *status); int CFITS_API ffprwu(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffpcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, int *status); int CFITS_API ffpclujj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, ULONGLONG *array, int *status); int CFITS_API ffpclx(fitsfile *fptr, int colnum, LONGLONG frow, long fbit, long nbit, char *larray, int *status); int CFITS_API ffpcn(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffpcns( fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char **array, char *nulvalue, int *status); int CFITS_API ffpcnl( fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, char nulvalue, int *status); int CFITS_API ffpcnb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, unsigned char nulvalue, int *status); int CFITS_API ffpcnsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char *array, signed char nulvalue, int *status); int CFITS_API ffpcnui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, unsigned short nulvalue, int *status); int CFITS_API ffpcni(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short *array, short nulvalue, int *status); int CFITS_API ffpcnuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, unsigned long nulvalue, int *status); int CFITS_API ffpcnj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long *array, long nulvalue, int *status); int CFITS_API ffpcnuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, unsigned int nulvalue, int *status); int CFITS_API ffpcnk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *array, int nulvalue, int *status); int CFITS_API ffpcne(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, float nulvalue, int *status); int CFITS_API ffpcnd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, double nulvalue, int *status); int CFITS_API ffpcnjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, LONGLONG nulvalue, int *status); int CFITS_API ffpcnujj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, ULONGLONG *array, ULONGLONG nulvalue, int *status); int CFITS_API ffptbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, unsigned char *values, int *status); int CFITS_API ffirow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffdrow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffdrrg(fitsfile *fptr, char *ranges, int *status); int CFITS_API ffdrws(fitsfile *fptr, long *rownum, long nrows, int *status); int CFITS_API ffdrwsll(fitsfile *fptr, LONGLONG *rownum, LONGLONG nrows, int *status); int CFITS_API fficol(fitsfile *fptr, int numcol, char *ttype, char *tform, int *status); int CFITS_API fficls(fitsfile *fptr, int firstcol, int ncols, char **ttype, char **tform, int *status); int CFITS_API ffmvec(fitsfile *fptr, int colnum, LONGLONG newveclen, int *status); int CFITS_API ffdcol(fitsfile *fptr, int numcol, int *status); int CFITS_API ffcpcl(fitsfile *infptr, fitsfile *outfptr, int incol, int outcol, int create_col, int *status); int CFITS_API ffccls(fitsfile *infptr, fitsfile *outfptr, int incol, int outcol, int ncols, int create_col, int *status); int CFITS_API ffcprw(fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffcpsr(fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, char *row_status, int *status); int CFITS_API ffcpht(fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, int *status); /*--------------------- WCS Utilities ------------------*/ int CFITS_API ffgics(fitsfile *fptr, double *xrval, double *yrval, double *xrpix, double *yrpix, double *xinc, double *yinc, double *rot, char *type, int *status); int CFITS_API ffgicsa(fitsfile *fptr, char version, double *xrval, double *yrval, double *xrpix, double *yrpix, double *xinc, double *yinc, double *rot, char *type, int *status); int CFITS_API ffgtcs(fitsfile *fptr, int xcol, int ycol, double *xrval, double *yrval, double *xrpix, double *yrpix, double *xinc, double *yinc, double *rot, char *type, int *status); int CFITS_API ffwldp(double xpix, double ypix, double xref, double yref, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *type, double *xpos, double *ypos, int *status); int CFITS_API ffxypx(double xpos, double ypos, double xref, double yref, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *type, double *xpix, double *ypix, int *status); /* WCS support routines (provide interface to Doug Mink's WCS library */ int CFITS_API ffgiwcs(fitsfile *fptr, char **header, int *status); int CFITS_API ffgtwcs(fitsfile *fptr, int xcol, int ycol, char **header, int *status); /*--------------------- lexical parsing routines ------------------*/ int CFITS_API fftexp( fitsfile *fptr, char *expr, int maxdim, int *datatype, long *nelem, int *naxis, long *naxes, int *status ); int CFITS_API fffrow( fitsfile *infptr, char *expr, long firstrow, long nrows, long *n_good_rows, char *row_status, int *status); int CFITS_API ffffrw( fitsfile *fptr, char *expr, long *rownum, int *status); int CFITS_API fffrwc( fitsfile *fptr, char *expr, char *timeCol, char *parCol, char *valCol, long ntimes, double *times, char *time_status, int *status ); int CFITS_API ffsrow( fitsfile *infptr, fitsfile *outfptr, char *expr, int *status); int CFITS_API ffcrow( fitsfile *fptr, int datatype, char *expr, long firstrow, long nelements, void *nulval, void *array, int *anynul, int *status ); int CFITS_API ffcalc_rng( fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, int nRngs, long *start, long *end, int *status ); int CFITS_API ffcalc( fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, int *status ); /* ffhist is not really intended as a user-callable routine */ /* but it may be useful for some specialized applications */ /* ffhist2 is a newer version which is strongly recommended instead of ffhist */ int CFITS_API ffhist(fitsfile **fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], int recip, char *rowselect, int *status); int CFITS_API ffhist2(fitsfile **fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], int recip, char *rowselect, int *status); CFITS_API fitsfile *ffhist3(fitsfile *fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], int recip, char *selectrow, int *status); int CFITS_API fits_select_image_section(fitsfile **fptr, char *outfile, char *imagesection, int *status); int CFITS_API fits_copy_image_section(fitsfile *infptr, fitsfile *outfile, char *imagesection, int *status); int CFITS_API fits_calc_binning(fitsfile *fptr, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], int *colnum, long *haxes, float *amin, float *amax, float *binsize, int *status); int CFITS_API fits_calc_binningd(fitsfile *fptr, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], int *colnum, long *haxes, double *amin, double *amax, double *binsize, int *status); int CFITS_API fits_write_keys_histo(fitsfile *fptr, fitsfile *histptr, int naxis, int *colnum, int *status); int CFITS_API fits_rebin_wcs( fitsfile *fptr, int naxis, float *amin, float *binsize, int *status); int CFITS_API fits_rebin_wcsd( fitsfile *fptr, int naxis, double *amin, double *binsize, int *status); int CFITS_API fits_make_hist(fitsfile *fptr, fitsfile *histptr, int bitpix,int naxis, long *naxes, int *colnum, float *amin, float *amax, float *binsize, float weight, int wtcolnum, int recip, char *selectrow, int *status); int CFITS_API fits_make_histd(fitsfile *fptr, fitsfile *histptr, int bitpix,int naxis, long *naxes, int *colnum, double *amin, double *amax, double *binsize, double weight, int wtcolnum, int recip, char *selectrow, int *status); typedef struct { /* input(s) */ int count; char ** path; char ** tag; fitsfile ** ifptr; char * expression; /* output control */ int bitpix; long blank; fitsfile * ofptr; char keyword[FLEN_KEYWORD]; char comment[FLEN_COMMENT]; } PixelFilter; int CFITS_API fits_pixel_filter (PixelFilter * filter, int * status); /*--------------------- grouping routines ------------------*/ int CFITS_API ffgtcr(fitsfile *fptr, char *grpname, int grouptype, int *status); int CFITS_API ffgtis(fitsfile *fptr, char *grpname, int grouptype, int *status); int CFITS_API ffgtch(fitsfile *gfptr, int grouptype, int *status); int CFITS_API ffgtrm(fitsfile *gfptr, int rmopt, int *status); int CFITS_API ffgtcp(fitsfile *infptr, fitsfile *outfptr, int cpopt, int *status); int CFITS_API ffgtmg(fitsfile *infptr, fitsfile *outfptr, int mgopt, int *status); int CFITS_API ffgtcm(fitsfile *gfptr, int cmopt, int *status); int CFITS_API ffgtvf(fitsfile *gfptr, long *firstfailed, int *status); int CFITS_API ffgtop(fitsfile *mfptr,int group,fitsfile **gfptr,int *status); int CFITS_API ffgtam(fitsfile *gfptr, fitsfile *mfptr, int hdupos, int *status); int CFITS_API ffgtnm(fitsfile *gfptr, long *nmembers, int *status); int CFITS_API ffgmng(fitsfile *mfptr, long *nmembers, int *status); int CFITS_API ffgmop(fitsfile *gfptr, long member, fitsfile **mfptr, int *status); int CFITS_API ffgmcp(fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, int *status); int CFITS_API ffgmtf(fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, int *status); int CFITS_API ffgmrm(fitsfile *fptr, long member, int rmopt, int *status); /*--------------------- group template parser routines ------------------*/ int CFITS_API fits_execute_template(fitsfile *ff, char *ngp_template, int *status); int CFITS_API fits_img_stats_short(short *array,long nx, long ny, int nullcheck, short nullvalue,long *ngoodpix, short *minvalue, short *maxvalue, double *mean, double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); int CFITS_API fits_img_stats_int(int *array,long nx, long ny, int nullcheck, int nullvalue,long *ngoodpix, int *minvalue, int *maxvalue, double *mean, double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); int CFITS_API fits_img_stats_float(float *array, long nx, long ny, int nullcheck, float nullvalue,long *ngoodpix, float *minvalue, float *maxvalue, double *mean, double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); /*--------------------- image compression routines ------------------*/ int CFITS_API fits_set_compression_type(fitsfile *fptr, int ctype, int *status); int CFITS_API fits_set_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status); int CFITS_API fits_set_noise_bits(fitsfile *fptr, int noisebits, int *status); int CFITS_API fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status); int CFITS_API fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status); int CFITS_API fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status); int CFITS_API fits_set_quantize_method(fitsfile *fptr, int method, int *status); int CFITS_API fits_set_quantize_dither(fitsfile *fptr, int dither, int *status); int CFITS_API fits_set_dither_seed(fitsfile *fptr, int seed, int *status); int CFITS_API fits_set_dither_offset(fitsfile *fptr, int offset, int *status); int CFITS_API fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status); int CFITS_API fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); int CFITS_API fits_set_compression_pref(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_get_compression_type(fitsfile *fptr, int *ctype, int *status); int CFITS_API fits_get_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status); int CFITS_API fits_get_quantize_level(fitsfile *fptr, float *qlevel, int *status); int CFITS_API fits_get_noise_bits(fitsfile *fptr, int *noisebits, int *status); int CFITS_API fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status); int CFITS_API fits_get_hcomp_smooth(fitsfile *fptr, int *smooth, int *status); int CFITS_API fits_get_dither_seed(fitsfile *fptr, int *seed, int *status); int CFITS_API fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_compress_img(fitsfile *infptr, fitsfile *outfptr, int compress_type, long *tilesize, int parm1, int parm2, int *status); int CFITS_API fits_is_compressed_image(fitsfile *fptr, int *status); int CFITS_API fits_is_reentrant(void); int CFITS_API fits_decompress_img (fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_img_decompress_header(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); /* H-compress routines */ int CFITS_API fits_hcompress(int *a, int nx, int ny, int scale, char *output, long *nbytes, int *status); int CFITS_API fits_hcompress64(LONGLONG *a, int nx, int ny, int scale, char *output, long *nbytes, int *status); int CFITS_API fits_hdecompress(unsigned char *input, int smooth, int *a, int *nx, int *ny, int *scale, int *status); int CFITS_API fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *nx, int *ny, int *scale, int *status); int CFITS_API fits_compress_table (fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status); /* curl library wrapper routines (for https access) */ int CFITS_API fits_init_https(void); int CFITS_API fits_cleanup_https(void); void CFITS_API fits_verbose_https(int flag); void CFITS_API ffshdwn(int flag); int CFITS_API ffgtmo(void); int CFITS_API ffstmo(int sec, int *status); /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ #ifdef __cplusplus } #endif #endif #endif cfitsio-4.3.1/README0000644000225700000360000001066013472024437013336 0ustar cagordonlhea CFITSIO Interface Library CFITSIO is a library of ANSI C routines for reading and writing FITS format data files. A set of Fortran-callable wrapper routines are also included for the convenience of Fortran programmers. This README file gives a brief summary of how to build and test CFITSIO, but the CFITSIO User's Guide, found in the files cfitsio.doc (plain text), cfitsio.tex (LaTeX source file), cfitsio.ps, or cfitsio.pdf should be referenced for the latest and most complete information. BUILDING CFITSIO ---------------- The CFITSIO code is contained in about 40 *.c source files and several *.h header files. CFITSIO should compile and run on most Unix platforms without modification, except that Cray supercomputers computers are currently not supported. The CFITSIO library is built on Unix systems by typing: > ./configure [--prefix=/target/installation/path] > make (or 'make shared') > make install (this step is optional) at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, > ./configure --prefix=/usr1/local will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). All the available configure options can be seen by entering the command > ./configure --help On VAX/VMS and ALPHA/VMS systems the make.com command file may be used to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. A precompiled DLL version of CFITSIO is available for IBM-PC users of the Borland or Microsoft Visual C++ compilers in the files cfitsiodll_xxxx_borland.zip and cfitsiodll_xxxx_vcc.zip, where 'xxxx' represents the current release number. These zip archives also contains other files and instructions on how to use the CFITSIO DLL library. The CFITSIO library may also be built from the source code using the makefile.bc or makefile.vcc files. Finally, the makepc.bat file gives an example of building CFITSIO with the Borland C++ v4.5 compiler using simpler DOS commands. Instructions for building CFITSIO on Mac OS can be found in the README.MacOS file. TESTING CFITSIO --------------- The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems, type: - % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std - On VMS systems, (assuming cc is the name of the C compiler command), type: - $ cc testprog.c $ link testprog, cfitsio/lib $ run testprog - The testprog program should produce a FITS file called `testprog.fit' that is identical to the testprog.std FITS file included in this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. USING CFITSIO ------------- The CFITSIO User's Guide, contained in the files cfitsio.doc (plain text file) and cfitsio.ps (postscript file), provides detailed documentation about how to build and use the CFITSIO library. It contains a description of every user-callable routine in the CFITSIO interface. The cookbook.c file provides some sample routines for performing common operations on various types of FITS files. Programmers are urged to examine these routines for recommended programming practices when using CFITSIO. Users are free to copy or modify these routines for their own purposes. Any problem reports or suggestions for improvements are welcome and should be sent to the HEASARC help desk. ------------------------------------------------------------------------- William D. Pence HEASARC, NASA/GSFC cfitsio-4.3.1/f77_wrap.h0000644000225700000360000002442114214470324014256 0ustar cagordonlhea#define UNSIGNED_BYTE #include "cfortran.h" /************************************************************************ Some platforms creates longs as 8-byte integers. On other machines, ints and longs are both 4-bytes, so both are compatible with Fortrans default integer which is 4-bytes. To support 8-byte longs, we must redefine LONGs and convert them to 8-bytes when going to C, and restore them to 4-bytes when returning to Fortran. Ugh!!! *************************************************************************/ #if defined(DECFortran) || (defined(__alpha) && defined(g77Fortran)) \ || (defined(mipsFortran) && _MIPS_SZLONG==64) \ || (defined(IBMR2Fortran) && defined(__64BIT__)) \ || defined(__ia64__) \ || defined (__sparcv9) || (defined(__sparc__) && defined(__arch64__)) \ || defined (__x86_64__) \ || defined (_SX) \ || defined (__powerpc64__)\ || defined (__s390x__)\ || (defined(__arm64__) && defined(__APPLE__)) \ || defined(__aarch64__) #define LONG8BYTES_INT4BYTES #undef LONGV_cfSTR #undef PLONG_cfSTR #undef LONGVVVVVVV_cfTYPE #undef PLONG_cfTYPE #undef LONGV_cfT #undef PLONG_cfT #define LONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LONGV,A,B,C,D,E) #define PLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PLONG,A,B,C,D,E) #define LONGVVVVVVV_cfTYPE int #define PLONG_cfTYPE int #define LONGV_cfQ(B) long *B, _(B,N); #define PLONG_cfQ(B) long B; #define LONGV_cfT(M,I,A,B,D) ( (_(B,N) = * _3(M,_LONGV_A,I)), \ B = F2Clongv(_(B,N),A) ) #define PLONG_cfT(M,I,A,B,D) ((B=*A),&B) #define LONGV_cfR(A,B,D) C2Flongv(_(B,N),A,B); #define PLONG_cfR(A,B,D) *A=B; #define LONGV_cfH(S,U,B) #define PLONG_cfH(S,U,B) static long *F2Clongv(long size, int *A) { long i; long *B; B=(long *)malloc( size*sizeof(long) ); for(i=0;idsc$a_pointer /* We want single strings to be equivalent to string vectors with */ /* a single element, so ignore the number of elements info in the */ /* vector structure, and rely on the NUM_ELEM definitions. */ #undef STRINGV_cfT #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A->dsc$a_pointer, B, \ A->dsc$w_length, \ num_elem(A->dsc$a_pointer, \ A->dsc$w_length, \ _3(M,_STRV_A,I) ) ) #else #ifdef CRAYFortran #define PPSTRING_cfT(M,I,A,B,D) (unsigned char*)_fcdtocp(A) #else #define PPSTRING_cfT(M,I,A,B,D) (unsigned char*)A #endif #endif #define _cfMAX(A,B) ( (A>B) ? A : B ) #define STRINGV_cfQ(B) char **B; unsigned int _(B,N), _(B,M); #define STRINGV_cfR(A,B,D) free(B[0]); free(B); #define TTSTR( A,B,D) \ ((B=(char*)malloc(_cfMAX(D,gMinStrLen)+1))[D]='\0',memcpy(B,A,D), \ kill_trailing(B,' ')) #define TTTTSTRV( A,B,D,E) ( \ _(B,N)=_cfMAX(E,1), \ _(B,M)=_cfMAX(D,gMinStrLen)+1, \ B=(char**)malloc(_(B,N)*sizeof(char*)), \ B[0]=(char*)malloc(_(B,N)*_(B,M)), \ vindex(B,_(B,M),_(B,N),f2cstrv2(A,B[0],D,_(B,M),_(B,N))) \ ) #define RRRRPSTRV(A,B,D) \ c2fstrv2(B[0],A,_(B,M),D,_(B,N)), \ free(B[0]), \ free(B); static char **vindex(char **B, int elem_len, int nelem, char *B0) { int i; if( nelem ) for( i=0;idsc$a_pointer)[0]) #define BYTEV_cfT(M,I,A,B,D) (INTEGER_BYTE*)A->dsc$a_pointer #else #ifdef CRAYFortran #define BYTE_cfN(T,A) _fcd A #define BYTEV_cfN(T,A) _fcd A #define BYTE_cfT(M,I,A,B,D) (INTEGER_BYTE)((_fcdtocp(A))[0]) #define BYTEV_cfT(M,I,A,B,D) (INTEGER_BYTE*)_fcdtocp(A) #else #define BYTE_cfN(T,A) INTEGER_BYTE * A #define BYTEV_cfN(T,A) INTEGER_BYTE * A #define BYTE_cfT(M,I,A,B,D) A[0] #define BYTEV_cfT(M,I,A,B,D) A #endif #endif /************************************************************************ The following definitions and functions handle conversions between C and Fortran arrays of LOGICALS. Individually, LOGICALS are treated as int's but as char's when in an array. cfortran defines (F2C/C2F)LOGICALV but never uses them, so these routines also handle TRUE/FALSE conversions. *************************************************************************/ #undef LOGICALV_cfSTR #undef LOGICALV_cfT #define LOGICALV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LOGICALV,A,B,C,D,E) #define LOGICALV_cfQ(B) char *B; unsigned int _(B,N); #define LOGICALV_cfT(M,I,A,B,D) (_(B,N)= * _3(M,_LOGV_A,I), \ B=F2CcopyLogVect(_(B,N),A)) #define LOGICALV_cfR(A,B,D) C2FcopyLogVect(_(B,N),A,B); #define LOGICALV_cfH(S,U,B) static char *F2CcopyLogVect(long size, int *A) { long i; char *B; B=(char *)malloc(size*sizeof(char)); for( i=0; i #include #include #include #include #include /* apparently needed to define size_t */ #include "fitsio2.h" #include "group.h" #ifdef CFITSIO_HAVE_CURL #include #endif #define MAX_PREFIX_LEN 20 /* max length of file type prefix (e.g. 'http://') */ #define MAX_DRIVERS 31 /* max number of file I/O drivers */ typedef struct /* structure containing pointers to I/O driver functions */ { char prefix[MAX_PREFIX_LEN]; int (*init)(void); int (*shutdown)(void); int (*setoptions)(int option); int (*getoptions)(int *options); int (*getversion)(int *version); int (*checkfile)(char *urltype, char *infile, char *outfile); int (*open)(char *filename, int rwmode, int *driverhandle); int (*create)(char *filename, int *drivehandle); int (*truncate)(int drivehandle, LONGLONG size); int (*close)(int drivehandle); int (*remove)(char *filename); int (*size)(int drivehandle, LONGLONG *size); int (*flush)(int drivehandle); int (*seek)(int drivehandle, LONGLONG offset); int (*read)(int drivehandle, void *buffer, long nbytes); int (*write)(int drivehandle, void *buffer, long nbytes); } fitsdriver; fitsdriver driverTable[MAX_DRIVERS]; /* allocate driver tables */ FITSfile *FptrTable[NMAXFILES]; /* this table of Fptr pointers is */ /* used by fits_already_open */ int need_to_initialize = 1; /* true if CFITSIO has not been initialized */ int no_of_drivers = 0; /* number of currently defined I/O drivers */ static int pixel_filter_helper(fitsfile **fptr, char *outfile, char *expr, int *status); static int find_quote(char **string); static int find_doublequote(char **string); static int find_paren(char **string); static int find_bracket(char **string); static int find_curlybracket(char **string); static int standardize_path(char *fullpath, int *status); int comma2semicolon(char *string); #ifdef _REENTRANT pthread_mutex_t Fitsio_InitLock = PTHREAD_MUTEX_INITIALIZER; #endif /*--------------------------------------------------------------------------*/ int fitsio_init_lock(void) { int status = 0; #ifdef _REENTRANT static int need_to_init = 1; pthread_mutexattr_t mutex_init; FFLOCK1(Fitsio_InitLock); if (need_to_init) { /* Init the main fitsio lock here since we need a a recursive lock */ status = pthread_mutexattr_init(&mutex_init); if (status) { ffpmsg("pthread_mutexattr_init failed (fitsio_init_lock)"); return(status); } #ifdef __GLIBC__ status = pthread_mutexattr_settype(&mutex_init, PTHREAD_MUTEX_RECURSIVE_NP); #else status = pthread_mutexattr_settype(&mutex_init, PTHREAD_MUTEX_RECURSIVE); #endif if (status) { ffpmsg("pthread_mutexattr_settype failed (fitsio_init_lock)"); return(status); } status = pthread_mutex_init(&Fitsio_Lock,&mutex_init); if (status) { ffpmsg("pthread_mutex_init failed (fitsio_init_lock)"); return(status); } need_to_init = 0; } FFUNLOCK1(Fitsio_InitLock); #endif return(status); } /*--------------------------------------------------------------------------*/ int ffomem(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ void **buffptr, /* I - address of memory pointer */ size_t *buffsize, /* I - size of buffer, in bytes */ size_t deltasize, /* I - increment for future realloc's */ void *(*mem_realloc)(void *p, size_t newsize), /* function */ int *status) /* IO - error status */ /* Open an existing FITS file in core memory. This is a specialized version of ffopen. */ { int ii, driver, handle, hdutyp, slen, movetotype, extvers, extnum; char extname[FLEN_VALUE]; LONGLONG filesize; char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME]; char extspec[FLEN_FILENAME], rowfilter[FLEN_FILENAME]; char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME]; char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; char *url, errmsg[FLEN_ERRMSG]; char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"}; if (*status > 0) return(*status); *fptr = 0; /* initialize null file pointer */ if (need_to_initialize) /* this is called only once */ { *status = fits_init_cfitsio(); if (*status > 0) return(*status); } url = (char *) name; while (*url == ' ') /* ignore leading spaces in the file spec */ url++; /* parse the input file specification */ fits_parse_input_url(url, urltype, infile, outfile, extspec, rowfilter, binspec, colspec, status); strcpy(urltype, "memkeep://"); /* URL type for pre-existing memory file */ *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not find driver for pre-existing memory file: (ffomem)"); return(*status); } /* call driver routine to open the memory file */ FFLOCK; /* lock this while searching for vacant handle */ *status = mem_openmem( buffptr, buffsize,deltasize, mem_realloc, &handle); FFUNLOCK; if (*status > 0) { ffpmsg("failed to open pre-existing memory file: (ffomem)"); return(*status); } /* get initial file size */ *status = (*driverTable[driver].size)(handle, &filesize); if (*status > 0) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed get the size of the memory file: (ffomem)"); return(*status); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffomem)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffomem)"); ffpmsg(url); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = strlen(url) + 1; slen = maxvalue(slen, 32); /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffomem)"); ffpmsg(url); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffomem)"); ffpmsg(url); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffomem)"); ffpmsg(url); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* file handle */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ ((*fptr)->Fptr)->filesize = filesize; /* physical file size */ ((*fptr)->Fptr)->logfilesize = filesize; /* logical file size */ ((*fptr)->Fptr)->writemode = mode; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ((*fptr)->Fptr)->noextsyntax = 0; /* extended syntax can be used in filename */ ffldrc(*fptr, 0, REPORT_EOF, status); /* load first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ if (ffrhdu(*fptr, &hdutyp, status) > 0) /* determine HDU structure */ { ffpmsg( "ffomem could not interpret primary array header of file: (ffomem)"); ffpmsg(url); if (*status == UNKNOWN_REC) ffpmsg("This does not look like a FITS file."); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ } /* ---------------------------------------------------------- */ /* move to desired extension, if specified as part of the URL */ /* ---------------------------------------------------------- */ imagecolname[0] = '\0'; rowexpress[0] = '\0'; if (*extspec) { /* parse the extension specifier into individual parameters */ ffexts(extspec, &extnum, extname, &extvers, &movetotype, imagecolname, rowexpress, status); if (*status > 0) return(*status); if (extnum) { ffmahd(*fptr, extnum + 1, &hdutyp, status); } else if (*extname) /* move to named extension, if specified */ { ffmnhd(*fptr, movetotype, extname, extvers, status); } if (*status > 0) { ffpmsg("ffomem could not move to the specified extension:"); if (extnum > 0) { snprintf(errmsg, FLEN_ERRMSG, " extension number %d doesn't exist or couldn't be opened.",extnum); ffpmsg(errmsg); } else { snprintf(errmsg, FLEN_ERRMSG, " extension with EXTNAME = %s,", extname); ffpmsg(errmsg); if (extvers) { snprintf(errmsg, FLEN_ERRMSG, " and with EXTVERS = %d,", extvers); ffpmsg(errmsg); } if (movetotype != ANY_HDU) { snprintf(errmsg, FLEN_ERRMSG, " and with XTENSION = %s,", hdtype[movetotype]); ffpmsg(errmsg); } ffpmsg(" doesn't exist or couldn't be opened."); } return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffdkopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file on magnetic disk with either readonly or read/write access. The routine does not support CFITSIO's extended filename syntax and simply uses the entire input 'name' string as the name of the file. */ { if (*status > 0) return(*status); *status = OPEN_DISK_FILE; ffopen(fptr, name, mode, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and move to the first HDU that contains 'interesting' data, if the primary array contains a null image (i.e., NAXIS = 0). */ { if (*status > 0) return(*status); *status = SKIP_NULL_PRIMARY; ffopen(fptr, name, mode, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffeopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ char *extlist, /* I - list of 'good' extensions to move to */ int *hdutype, /* O - type of extension that is moved to */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and if the primary array contains a null image (i.e., NAXIS = 0) then attempt to move to the first extension named in the extlist of extension names. If none are found, then simply move to the 2nd extension. */ { int hdunum, naxis = 0, thdutype, gotext=0; char *ext, *textlist; char *saveptr; if (*status > 0) return(*status); if (ffopen(fptr, name, mode, status) > 0) return(*status); fits_get_hdu_num(*fptr, &hdunum); fits_get_hdu_type(*fptr, &thdutype, status); if (hdunum == 1 && thdutype == IMAGE_HDU) { fits_get_img_dim(*fptr, &naxis, status); } /* We are in the "default" primary extension */ /* look through the extension list */ if( (hdunum == 1) && (naxis == 0) ){ if( extlist ){ gotext = 0; textlist = malloc(strlen(extlist) + 1); if (!textlist) { *status = MEMORY_ALLOCATION; return(*status); } strcpy(textlist, extlist); for(ext=(char *)ffstrtok(textlist, " ",&saveptr); ext != NULL; ext=(char *)ffstrtok(NULL," ",&saveptr)){ fits_movnam_hdu(*fptr, ANY_HDU, ext, 0, status); if( *status == 0 ){ gotext = 1; break; } else { *status = 0; } } free(textlist); } if( !gotext ){ /* if all else fails, move to extension #2 and hope for the best */ fits_movabs_hdu(*fptr, 2, &thdutype, status); } } if (hdutype) { fits_get_hdu_type(*fptr, hdutype, status); } return(*status); } /*--------------------------------------------------------------------------*/ int fftopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and move to the first HDU that contains 'interesting' table (not an image). */ { int hdutype; if (*status > 0) return(*status); *status = SKIP_IMAGE; ffopen(fptr, name, mode, status); if (ffghdt(*fptr, &hdutype, status) <= 0) { if (hdutype == IMAGE_HDU) *status = NOT_TABLE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffiopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and move to the first HDU that contains 'interesting' image (not an table). */ { int hdutype; if (*status > 0) return(*status); *status = SKIP_TABLE; ffopen(fptr, name, mode, status); if (ffghdt(*fptr, &hdutype, status) <= 0) { if (hdutype != IMAGE_HDU) *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffopentest(int soname, /* I - CFITSIO shared library version */ /* application program (fitsio.h file) */ fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. First test that the SONAME of fitsio.h used to build the CFITSIO library is the same as was used in compiling the application program that links to the library. */ { if (soname != CFITSIO_SONAME) { printf("\nERROR: Mismatch in the CFITSIO_SONAME value in the fitsio.h include file\n"); printf("that was used to build the CFITSIO library, and the value in the include file\n"); printf("that was used when compiling the application program:\n"); printf(" Version used to build the CFITSIO library = %d\n",CFITSIO_SONAME); printf(" Version included by the application program = %d\n",soname); printf("\nFix this by recompiling and then relinking this application program \n"); printf("with the CFITSIO library.\n"); *status = FILE_NOT_OPENED; return(*status); } /* now call the normal file open routine */ ffopen(fptr, name, mode, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffopen(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. */ { fitsfile *newptr; int ii, driver, hdutyp, hdunum, slen, writecopy, isopen; LONGLONG filesize; long rownum, nrows, goodrows; int extnum, extvers, handle, movetotype, tstatus = 0, only_one = 0; char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME]; char origurltype[MAX_PREFIX_LEN], extspec[FLEN_FILENAME]; char extname[FLEN_VALUE], rowfilter[FLEN_FILENAME], tblname[FLEN_VALUE]; char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME], pixfilter[FLEN_FILENAME]; char histfilename[FLEN_FILENAME]; char filtfilename[FLEN_FILENAME], compspec[FLEN_FILENAME]; char wtcol[FLEN_VALUE]; char minname[4][FLEN_VALUE], maxname[4][FLEN_VALUE]; char binname[4][FLEN_VALUE]; char *url; double minin[4], maxin[4], binsizein[4], weight; int imagetype, naxis = 1, haxis, recip; int skip_null = 0, skip_image = 0, skip_table = 0, open_disk_file = 0; char colname[4][FLEN_VALUE]; char errmsg[FLEN_ERRMSG]; char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"}; char *rowselect = 0; if (*status > 0) return(*status); if (*status == SKIP_NULL_PRIMARY) { /* this special status value is used as a flag by ffdopn to tell */ /* ffopen to skip over a null primary array when opening the file. */ skip_null = 1; *status = 0; } else if (*status == SKIP_IMAGE) { /* this special status value is used as a flag by fftopn to tell */ /* ffopen to move to 1st significant table when opening the file. */ skip_image = 1; *status = 0; } else if (*status == SKIP_TABLE) { /* this special status value is used as a flag by ffiopn to tell */ /* ffopen to move to 1st significant image when opening the file. */ skip_table = 1; *status = 0; } else if (*status == OPEN_DISK_FILE) { /* this special status value is used as a flag by ffdkopn to tell */ /* ffopen to not interpret the input filename using CFITSIO's */ /* extended filename syntax, and simply open the specified disk file */ open_disk_file = 1; *status = 0; } *fptr = 0; /* initialize null file pointer */ writecopy = 0; /* have we made a write-able copy of the input file? */ if (need_to_initialize) { /* this is called only once */ *status = fits_init_cfitsio(); } if (*status > 0) return(*status); url = (char *) name; while (*url == ' ') /* ignore leading spaces in the filename */ url++; if (*url == '\0') { ffpmsg("Name of file to open is blank. (ffopen)"); return(*status = FILE_NOT_OPENED); } if (open_disk_file) { /* treat the input URL literally as the name of the file to open */ /* and don't try to parse the URL using the extended filename syntax */ if (strlen(url) > FLEN_FILENAME - 1) { ffpmsg("Name of file to open is too long. (ffopen)"); return(*status = FILE_NOT_OPENED); } strcpy(infile,url); strcpy(urltype, "file://"); outfile[0] = '\0'; extspec[0] = '\0'; binspec[0] = '\0'; colspec[0] = '\0'; rowfilter[0] = '\0'; pixfilter[0] = '\0'; compspec[0] = '\0'; } else { /* parse the input file specification */ /* NOTE: This routine tests that all the strings do not */ /* overflow the standard buffer sizes (FLEN_FILENAME, etc.) */ /* therefore in general we do not have to worry about buffer */ /* overflow of any of the returned strings. */ /* call the newer version of this parsing routine that supports 'compspec' */ ffifile2(url, urltype, infile, outfile, extspec, rowfilter, binspec, colspec, pixfilter, compspec, status); } if (*status > 0) { ffpmsg("could not parse the input filename: (ffopen)"); ffpmsg(url); return(*status); } imagecolname[0] = '\0'; rowexpress[0] = '\0'; if (*extspec) { slen = strlen(extspec); if (extspec[slen - 1] == '#') { /* special symbol to mean only copy this extension */ extspec[slen - 1] = '\0'; only_one = 1; } /* parse the extension specifier into individual parameters */ ffexts(extspec, &extnum, extname, &extvers, &movetotype, imagecolname, rowexpress, status); if (*status > 0) return(*status); } /*-------------------------------------------------------------------*/ /* special cases: */ /*-------------------------------------------------------------------*/ histfilename[0] = '\0'; filtfilename[0] = '\0'; if (*outfile && (*binspec || *imagecolname || *pixfilter)) { /* if binspec or imagecolumn are specified, then the */ /* output file name is intended for the final image, */ /* and not a copy of the input file. */ strcpy(histfilename, outfile); outfile[0] = '\0'; } else if (*outfile && (*rowfilter || *colspec)) { /* if rowfilter or colspece are specified, then the */ /* output file name is intended for the filtered file */ /* and not a copy of the input file. */ strcpy(filtfilename, outfile); outfile[0] = '\0'; } /*-------------------------------------------------------------------*/ /* check if this same file is already open, and if so, attach to it */ /*-------------------------------------------------------------------*/ FFLOCK; if (fits_already_open(fptr, url, urltype, infile, extspec, rowfilter, binspec, colspec, mode, open_disk_file, &isopen, status) > 0) { FFUNLOCK; return(*status); } FFUNLOCK; if (isopen) { goto move2hdu; } /* get the driver number corresponding to this urltype */ *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not find driver for this file: (ffopen)"); ffpmsg(urltype); ffpmsg(url); return(*status); } /*------------------------------------------------------------------- deal with all those messy special cases which may require that a different driver be used: - is disk file compressed? - are ftp:, gsiftp:, or http: files compressed? - has user requested that a local copy be made of the ftp or http file? -------------------------------------------------------------------*/ if (driverTable[driver].checkfile) { strcpy(origurltype,urltype); /* Save the urltype */ /* 'checkfile' may modify the urltype, infile and outfile strings */ *status = (*driverTable[driver].checkfile)(urltype, infile, outfile); if (*status) { ffpmsg("checkfile failed for this file: (ffopen)"); ffpmsg(url); return(*status); } if (strcmp(origurltype, urltype)) /* did driver changed on us? */ { *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not change driver for this file: (ffopen)"); ffpmsg(url); ffpmsg(urltype); return(*status); } } } /* call appropriate driver to open the file */ if (driverTable[driver].open) { FFLOCK; /* lock this while searching for vacant handle */ *status = (*driverTable[driver].open)(infile, mode, &handle); FFUNLOCK; if (*status > 0) { ffpmsg("failed to find or open the following file: (ffopen)"); ffpmsg(url); return(*status); } } else { ffpmsg("cannot open an existing file of this type: (ffopen)"); ffpmsg(url); return(*status = FILE_NOT_OPENED); } /* get initial file size */ *status = (*driverTable[driver].size)(handle, &filesize); if (*status > 0) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed get the size of the following file: (ffopen)"); ffpmsg(url); return(*status); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = strlen(url) + 1; slen = maxvalue(slen, 32); /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffopen)"); ffpmsg(url); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffopen)"); ffpmsg(url); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffopen)"); ffpmsg(url); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* file handle */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ ((*fptr)->Fptr)->filesize = filesize; /* physical file size */ ((*fptr)->Fptr)->logfilesize = filesize; /* logical file size */ ((*fptr)->Fptr)->writemode = mode; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ((*fptr)->Fptr)->only_one = only_one; /* flag denoting only copy single extension */ ((*fptr)->Fptr)->noextsyntax = open_disk_file; /* true if extended syntax is disabled */ ffldrc(*fptr, 0, REPORT_EOF, status); /* load first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ if (ffrhdu(*fptr, &hdutyp, status) > 0) /* determine HDU structure */ { ffpmsg( "ffopen could not interpret primary array header of file: "); ffpmsg(url); if (*status == UNKNOWN_REC) ffpmsg("This does not look like a FITS file."); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* ------------------------------------------------------------- */ /* At this point, the input file has been opened. If outfile was */ /* specified, then we have opened a copy of the file, not the */ /* original file so it is safe to modify it if necessary */ /* ------------------------------------------------------------- */ if (*outfile) writecopy = 1; move2hdu: /* ---------------------------------------------------------- */ /* move to desired extension, if specified as part of the URL */ /* ---------------------------------------------------------- */ if (*extspec) { if (extnum) /* extension number was specified */ { ffmahd(*fptr, extnum + 1, &hdutyp, status); } else if (*extname) /* move to named extension, if specified */ { ffmnhd(*fptr, movetotype, extname, extvers, status); } if (*status > 0) /* clean up after error */ { ffpmsg("ffopen could not move to the specified extension:"); if (extnum > 0) { snprintf(errmsg, FLEN_ERRMSG, " extension number %d doesn't exist or couldn't be opened.",extnum); ffpmsg(errmsg); } else { snprintf(errmsg, FLEN_ERRMSG, " extension with EXTNAME = %s,", extname); ffpmsg(errmsg); if (extvers) { snprintf(errmsg, FLEN_ERRMSG, " and with EXTVERS = %d,", extvers); ffpmsg(errmsg); } if (movetotype != ANY_HDU) { snprintf(errmsg, FLEN_ERRMSG, " and with XTENSION = %s,", hdtype[movetotype]); ffpmsg(errmsg); } ffpmsg(" doesn't exist or couldn't be opened."); } ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } else if (skip_null || skip_image || skip_table || (*imagecolname || *colspec || *rowfilter || *binspec)) { /* ------------------------------------------------------------------ If no explicit extension specifier is given as part of the file name, and, if a) skip_null is true (set if ffopen is called by ffdopn) or b) skip_image or skip_table is true (set if ffopen is called by fftopn or ffdopn) or c) other file filters are specified, then CFITSIO will attempt to move to the first 'interesting' HDU after opening an existing FITS file (or to first interesting table HDU if skip_image is true); An 'interesting' HDU is defined to be either an image with NAXIS > 0 (i.e., not a null array) or a table which has an EXTNAME value which does not contain any of the following strings: 'GTI' - Good Time Interval extension 'OBSTABLE' - used in Beppo SAX data files The main purpose for this is to allow CFITSIO to skip over a null primary and other non-interesting HDUs when opening an existing file, and move directly to the first extension that contains significant data. ------------------------------------------------------------------ */ fits_get_hdu_num(*fptr, &hdunum); if (hdunum == 1) { fits_get_img_dim(*fptr, &naxis, status); if (naxis == 0 || skip_image) /* skip primary array */ { while(1) { /* see if the next HDU is 'interesting' */ if (fits_movrel_hdu(*fptr, 1, &hdutyp, status)) { if (*status == END_OF_FILE) *status = 0; /* reset expected error */ /* didn't find an interesting HDU so move back to beginning */ fits_movabs_hdu(*fptr, 1, &hdutyp, status); break; } if (hdutyp == IMAGE_HDU && skip_image) { continue; /* skip images */ } else if (hdutyp != IMAGE_HDU && skip_table) { continue; /* skip tables */ } else if (hdutyp == IMAGE_HDU) { fits_get_img_dim(*fptr, &naxis, status); if (naxis > 0) break; /* found a non-null image */ } else { tstatus = 0; tblname[0] = '\0'; fits_read_key(*fptr, TSTRING, "EXTNAME", tblname, NULL,&tstatus); if ( (!strstr(tblname, "GTI") && !strstr(tblname, "gti")) && fits_strncasecmp(tblname, "OBSTABLE", 8) ) break; /* found an interesting table */ } } /* end while */ } } /* end if (hdunum==1) */ } if (*imagecolname) { /* ----------------------------------------------------------------- */ /* we need to open an image contained in a single table cell */ /* First, determine which row of the table to use. */ /* ----------------------------------------------------------------- */ if (isdigit((int) *rowexpress)) /* is the row specification a number? */ { sscanf(rowexpress, "%ld", &rownum); if (rownum < 1) { ffpmsg("illegal rownum for image cell:"); ffpmsg(rowexpress); ffpmsg("Could not open the following image in a table cell:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status = BAD_ROW_NUM); } } else if (fits_find_first_row(*fptr, rowexpress, &rownum, status) > 0) { ffpmsg("Failed to find row matching this expression:"); ffpmsg(rowexpress); ffpmsg("Could not open the following image in a table cell:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } if (rownum == 0) { ffpmsg("row satisfying this expression doesn't exist::"); ffpmsg(rowexpress); ffpmsg("Could not open the following image in a table cell:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status = BAD_ROW_NUM); } /* determine the name of the new file to contain copy of the image */ if (*histfilename && !(*pixfilter) ) strcpy(outfile, histfilename); /* the original outfile name */ else strcpy(outfile, "mem://_1"); /* create image file in memory */ /* Copy the image into new primary array and open it as the current */ /* fptr. This will close the table that contains the original image. */ /* create new empty file to hold copy of the image */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg("failed to create file for copy of image in table cell:"); ffpmsg(outfile); return(*status); } if (fits_copy_cell2image(*fptr, newptr, imagecolname, rownum, status) > 0) { ffpmsg("Failed to copy table cell to new primary array:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* close the original file and set fptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ writecopy = 1; /* we are now dealing with a copy of the original file */ /* leave it up to calling routine to write any HISTORY keywords */ } /* --------------------------------------------------------------------- */ /* edit columns (and/or keywords) in the table, if specified in the URL */ /* --------------------------------------------------------------------- */ if (*colspec) { /* the column specifier will modify the file, so make sure */ /* we are already dealing with a copy, or else make a new copy */ if (!writecopy) /* Is the current file already a copy? */ writecopy = fits_is_this_a_copy(urltype); if (!writecopy) { if (*filtfilename && *outfile == '\0') strcpy(outfile, filtfilename); /* the original outfile name */ else strcpy(outfile, "mem://_1"); /* will create copy in memory */ writecopy = 1; } else { ((*fptr)->Fptr)->writemode = READWRITE; /* we have write access */ outfile[0] = '\0'; } if (ffedit_columns(fptr, outfile, colspec, status) > 0) { ffpmsg("editing columns in input table failed (ffopen)"); ffpmsg(" while trying to perform the following operation:"); ffpmsg(colspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } /* ------------------------------------------------------------------- */ /* select rows from the table, if specified in the URL */ /* or select a subimage (if this is an image HDU and not a table) */ /* ------------------------------------------------------------------- */ if (*rowfilter) { fits_get_hdu_type(*fptr, &hdutyp, status); /* get type of HDU */ if (hdutyp == IMAGE_HDU) { /* this is an image so 'rowfilter' is an image section specification */ if (*filtfilename && *outfile == '\0') strcpy(outfile, filtfilename); /* the original outfile name */ else if (*outfile == '\0') /* output file name not already defined? */ strcpy(outfile, "mem://_2"); /* will create file in memory */ /* create new file containing the image section, plus a copy of */ /* any other HDUs that exist in the input file. This routine */ /* will close the original image file and return a pointer */ /* to the new file. */ if (fits_select_image_section(fptr, outfile, rowfilter, status) > 0) { ffpmsg("on-the-fly selection of image section failed (ffopen)"); ffpmsg(" while trying to use the following section filter:"); ffpmsg(rowfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } else { /* this is a table HDU, so the rowfilter is really a row filter */ if (*binspec) { /* since we are going to make a histogram of the selected rows, */ /* it would be a waste of time and memory to make a whole copy of */ /* the selected rows. Instead, just construct an array of TRUE */ /* or FALSE values that indicate which rows are to be included */ /* in the histogram and pass that to the histogram generating */ /* routine */ fits_get_num_rows(*fptr, &nrows, status); /* get no. of rows */ rowselect = (char *) calloc(nrows, 1); if (!rowselect) { ffpmsg( "failed to allocate memory for selected columns array (ffopen)"); ffpmsg(" while trying to select rows with the following filter:"); ffpmsg(rowfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } if (fits_find_rows(*fptr, rowfilter, 1L, nrows, &goodrows, rowselect, status) > 0) { ffpmsg("selection of rows in input table failed (ffopen)"); ffpmsg(" while trying to select rows with the following filter:"); ffpmsg(rowfilter); free(rowselect); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } else { if (!writecopy) /* Is the current file already a copy? */ writecopy = fits_is_this_a_copy(urltype); if (!writecopy) { if (*filtfilename && *outfile == '\0') strcpy(outfile, filtfilename); /* the original outfile name */ else if (*outfile == '\0') /* output filename not already defined? */ strcpy(outfile, "mem://_2"); /* will create copy in memory */ } else { ((*fptr)->Fptr)->writemode = READWRITE; /* we have write access */ outfile[0] = '\0'; } /* select rows in the table. If a copy of the input file has */ /* not already been made, then this routine will make a copy */ /* and then close the input file, so that the modifications will */ /* only be made on the copy, not the original */ if (ffselect_table(fptr, outfile, rowfilter, status) > 0) { ffpmsg("on-the-fly selection of rows in input table failed (ffopen)"); ffpmsg(" while trying to select rows with the following filter:"); ffpmsg(rowfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* write history records */ ffphis(*fptr, "CFITSIO used the following filtering expression to create this table:", status); ffphis(*fptr, name, status); } /* end of no binspec case */ } /* end of table HDU case */ } /* end of rowfilter exists case */ /* ------------------------------------------------------------------- */ /* make an image histogram by binning columns, if specified in the URL */ /* ------------------------------------------------------------------- */ if (*binspec) { char **exprs = 0; if (*histfilename && !(*pixfilter) ) strcpy(outfile, histfilename); /* the original outfile name */ else strcpy(outfile, "mem://_3"); /* create histogram in memory */ /* if not already copied the file */ /* parse the binning specifier into individual parameters */ ffbinse(binspec, &imagetype, &haxis, colname, minin, maxin, binsizein, minname, maxname, binname, &weight, wtcol, &recip, &(exprs), status); /* Create the histogram primary array and open it as the current fptr */ /* This will close the table that was used to create the histogram. */ ffhist2e(fptr, outfile, imagetype, haxis, colname, exprs, minin, maxin, binsizein, minname, maxname, binname, weight, wtcol, (exprs?exprs[4]:0), recip, rowselect, status); if (exprs) free(exprs); if (rowselect) free(rowselect); if (*status > 0) { ffpmsg("on-the-fly histogramming of input table failed (ffopen)"); ffpmsg(" while trying to execute the following histogram specification:"); ffpmsg(binspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* write history records */ ffphis(*fptr, "CFITSIO used the following expression to create this histogram:", status); ffphis(*fptr, name, status); } if (*pixfilter) { if (*histfilename) strcpy(outfile, histfilename); /* the original outfile name */ else strcpy(outfile, "mem://_4"); /* create in memory */ /* if not already copied the file */ /* Ensure type of HDU is consistent with pixel filtering */ fits_get_hdu_type(*fptr, &hdutyp, status); /* get type of HDU */ if (hdutyp == IMAGE_HDU) { pixel_filter_helper(fptr, outfile, pixfilter, status); if (*status > 0) { ffpmsg("pixel filtering of input image failed (ffopen)"); ffpmsg(" while trying to execute the following:"); ffpmsg(pixfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* write history records */ ffphis(*fptr, "CFITSIO used the following expression to create this image:", status); ffphis(*fptr, name, status); } else { ffpmsg("cannot use pixel filter on non-IMAGE HDU"); ffpmsg(pixfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ *status = NOT_IMAGE; return(*status); } } /* parse and save image compression specification, if given */ if (*compspec) { ffparsecompspec(*fptr, compspec, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffreopen(fitsfile *openfptr, /* I - FITS file pointer to open file */ fitsfile **newfptr, /* O - pointer to new re opened file */ int *status) /* IO - error status */ /* Reopen an existing FITS file with either readonly or read/write access. The reopened file shares the same FITSfile structure but may point to a different HDU within the file. */ { if (*status > 0) return(*status); /* check that the open file pointer is valid */ if (!openfptr) return(*status = NULL_INPUT_PTR); else if ((openfptr->Fptr)->validcode != VALIDSTRUC) /* check magic value */ return(*status = BAD_FILEPTR); /* allocate fitsfile structure and initialize = 0 */ *newfptr = (fitsfile *) calloc(1, sizeof(fitsfile)); (*newfptr)->Fptr = openfptr->Fptr; /* both point to the same structure */ (*newfptr)->HDUposition = 0; /* set initial position to primary array */ (((*newfptr)->Fptr)->open_count)++; /* increment the file usage counter */ return(*status); } /*--------------------------------------------------------------------------*/ int fits_store_Fptr(FITSfile *Fptr, /* O - FITS file pointer */ int *status) /* IO - error status */ /* store the new Fptr address for future use by fits_already_open */ { int ii; if (*status > 0) return(*status); FFLOCK; for (ii = 0; ii < NMAXFILES; ii++) { if (FptrTable[ii] == 0) { FptrTable[ii] = Fptr; break; } } FFUNLOCK; return(*status); } /*--------------------------------------------------------------------------*/ int fits_clear_Fptr(FITSfile *Fptr, /* O - FITS file pointer */ int *status) /* IO - error status */ /* clear the Fptr address from the Fptr Table */ { int ii; FFLOCK; for (ii = 0; ii < NMAXFILES; ii++) { if (FptrTable[ii] == Fptr) { FptrTable[ii] = 0; break; } } FFUNLOCK; return(*status); } /*--------------------------------------------------------------------------*/ int fits_already_open(fitsfile **fptr, /* I/O - FITS file pointer */ char *url, char *urltype, char *infile, char *extspec, char *rowfilter, char *binspec, char *colspec, int mode, /* I - 0 = open readonly; 1 = read/write */ int noextsyn, /* I - 0 = ext syntax may be used; 1 = ext syntax disabled */ int *isopen, /* O - 1 = file is already open */ int *status) /* IO - error status */ /* Check if the file to be opened is already open. If so, then attach to it. */ /* the input strings must not exceed the standard lengths */ /* of FLEN_FILENAME, MAX_PREFIX_LEN, etc. */ /* this function was changed so that for files of access method FILE:// the file paths are compared using standard URL syntax and absolute paths (as opposed to relative paths). This eliminates some instances where a file is already opened but it is not realized because it was opened with another file path. For instance, if the CWD is /a/b/c and I open /a/b/c/foo.fits then open ./foo.fits the previous version of this function would not have reconized that the two files were the same. This version does recognize that the two files are the same. */ { FITSfile *oldFptr; int ii, iMatch=-1; char oldurltype[MAX_PREFIX_LEN], oldinfile[FLEN_FILENAME]; char oldextspec[FLEN_FILENAME], oldoutfile[FLEN_FILENAME]; char oldrowfilter[FLEN_FILENAME]; char oldbinspec[FLEN_FILENAME], oldcolspec[FLEN_FILENAME]; char cwd[FLEN_FILENAME]; char tmpStr[FLEN_FILENAME]; char tmpinfile[FLEN_FILENAME]; *isopen = 0; /* When opening a file with readonly access then we simply let the operating system open the file again, instead of using the CFITSIO trick of attaching to the previously opened file. This is required if CFITSIO is running in a multi-threaded environment, because 2 different threads cannot share the same FITSfile pointer. If the file is opened/reopened with write access, then the file MUST only be physically opened once.. */ if (mode == 0) return(*status); strcpy(tmpinfile, infile); if(fits_strcasecmp(urltype,"FILE://") == 0) { if (standardize_path(tmpinfile, status)) return(*status); } for (ii = 0; ii < NMAXFILES; ii++) /* check every buffer */ { if (FptrTable[ii] != 0) { oldFptr = FptrTable[ii]; if (oldFptr->noextsyntax) { /* old urltype must be "file://" */ if (fits_strcasecmp(urltype,"FILE://") == 0) { /* compare tmpinfile to adjusted oldFptr->filename */ /* This shouldn't be possible, but check anyway */ if (strlen(oldFptr->filename) > FLEN_FILENAME-1) { ffpmsg("Name of old file is too long. (fits_already_open)"); return (*status = FILE_NOT_OPENED); } strcpy(oldinfile, oldFptr->filename); if (standardize_path(oldinfile, status)) return(*status); if (!strcmp(tmpinfile, oldinfile)) { /* if infile is not noextsyn, must check that it is not using filters of any kind */ if (noextsyn || (!rowfilter[0] && !binspec[0] && !colspec[0])) { if (mode == READWRITE && oldFptr->writemode == READONLY) { /* cannot assume that a file previously opened with READONLY can now be written to (e.g., files on CDROM, or over the the network, or STDIN), so return with an error. */ ffpmsg( "cannot reopen file READWRITE when previously opened READONLY"); ffpmsg(url); return(*status = FILE_NOT_OPENED); } iMatch = ii; } } } } /* end if old file has disabled extended syntax */ else { fits_parse_input_url(oldFptr->filename, oldurltype, oldinfile, oldoutfile, oldextspec, oldrowfilter, oldbinspec, oldcolspec, status); if (*status > 0) { ffpmsg("could not parse the previously opened filename: (ffopen)"); ffpmsg(oldFptr->filename); return(*status); } if(fits_strcasecmp(oldurltype,"FILE://") == 0) { if (standardize_path(oldinfile, status)) return(*status); } if (!strcmp(urltype, oldurltype) && !strcmp(tmpinfile, oldinfile) ) { /* identical type of file and root file name */ if ( (!rowfilter[0] && !oldrowfilter[0] && !binspec[0] && !oldbinspec[0] && !colspec[0] && !oldcolspec[0]) /* no filtering or binning specs for either file, so */ /* this is a case where the same file is being reopened. */ /* It doesn't matter if the extensions are different */ || /* or */ (!strcmp(rowfilter, oldrowfilter) && !strcmp(binspec, oldbinspec) && !strcmp(colspec, oldcolspec) && !strcmp(extspec, oldextspec) ) ) /* filtering specs are given and are identical, and */ /* the same extension is specified */ { if (mode == READWRITE && oldFptr->writemode == READONLY) { /* cannot assume that a file previously opened with READONLY can now be written to (e.g., files on CDROM, or over the the network, or STDIN), so return with an error. */ ffpmsg( "cannot reopen file READWRITE when previously opened READONLY"); ffpmsg(url); return(*status = FILE_NOT_OPENED); } iMatch = ii; } } } /* end if old file recognizes extended syntax */ } /* end if old fptr exists */ } /* end loop over NMAXFILES */ if (iMatch >= 0) { oldFptr = FptrTable[iMatch]; *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { ffpmsg( "failed to allocate structure for following file: (ffopen)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } (*fptr)->Fptr = oldFptr; /* point to the structure */ (*fptr)->HDUposition = 0; /* set initial position */ (((*fptr)->Fptr)->open_count)++; /* increment usage counter */ if (binspec[0]) /* if binning specified, don't move */ extspec[0] = '\0'; /* all the filtering has already been applied, so ignore */ rowfilter[0] = '\0'; binspec[0] = '\0'; colspec[0] = '\0'; *isopen = 1; } return(*status); } /*--------------------------------------------------------------------------*/ int standardize_path(char *fullpath, int* status) { /* Utility function for common operation in fits_already_open fullpath: I/O string to be standardized. Assume len = FLEN_FILENAME */ char tmpPath[FLEN_FILENAME]; char cwd [FLEN_FILENAME]; if (fits_path2url(fullpath, FLEN_FILENAME, tmpPath, status)) return(*status); if (tmpPath[0] != '/') { fits_get_cwd(cwd,status); if (strlen(cwd) + strlen(tmpPath) + 1 > FLEN_FILENAME-1) { ffpmsg("Tile name is too long. (standardize_path)"); return(*status = FILE_NOT_OPENED); } strcat(cwd,"/"); strcat(cwd,tmpPath); fits_clean_url(cwd,tmpPath,status); } strcpy(fullpath, tmpPath); return (*status); } /*--------------------------------------------------------------------------*/ int fits_is_this_a_copy(char *urltype) /* I - type of file */ /* specialized routine that returns 1 if the file is known to be a temporary copy of the originally opened file. Otherwise it returns 0. */ { int iscopy; if (!strncmp(urltype, "mem", 3) ) iscopy = 1; /* file copy is in memory */ else if (!strncmp(urltype, "compress", 8) ) iscopy = 1; /* compressed diskfile that is uncompressed in memory */ else if (!strncmp(urltype, "http", 4) ) iscopy = 1; /* copied file using http protocol */ else if (!strncmp(urltype, "ftp", 3) ) iscopy = 1; /* copied file using ftp protocol */ else if (!strncmp(urltype, "gsiftp", 6) ) iscopy = 1; /* copied file using gsiftp protocol */ else if (!strncpy(urltype, "stdin", 5) ) iscopy = 1; /* piped stdin has been copied to memory */ else iscopy = 0; /* file is not known to be a copy */ return(iscopy); } /*--------------------------------------------------------------------------*/ static int find_quote(char **string) /* look for the closing single quote character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == '\'') { /* found the closing quote */ *string = tstr + 1; /* set pointer to next char */ return(0); } else { /* skip over any other character */ tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ char *fits_find_match_delim(char *string, char delim) /* Find matching delimiter, respecting quoting and (potentially nested) parentheses char *string - null-terminated string to be searched for delimiter char delim - single delimiter to search for (one of '")]} ) returns: pointer to character after delimiter, or 0 if not found */ { char *tstr = string; int retval = 0; if (!string) return 0; switch (delim) { case '\'': retval = find_quote(&tstr); break; case '"': retval = find_doublequote(&tstr); break; case '}': retval = find_curlybracket(&tstr); break; case ']': retval = find_bracket(&tstr); break; case ')': retval = find_paren(&tstr); break; default: return 0; /* Invalid delimeter, return failure */ } /* Delimeter not found, return failure */ if (retval) return 0; /* Delimeter was found, return next position */ return (tstr); } /*--------------------------------------------------------------------------*/ static int find_doublequote(char **string) /* look for the closing double quote character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == '"') { /* found the closing quote */ *string = tstr + 1; /* set pointer to next char */ return(0); } else { /* skip over any other character */ tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_paren(char **string) /* look for the closing parenthesis character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == ')') { /* found the closing parens */ *string = tstr + 1; /* set pointer to next char */ return(0); } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_bracket(char **string) /* look for the closing bracket character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == ']') { /* found the closing bracket */ *string = tstr + 1; /* set pointer to next char */ return(0); } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_curlybracket(char **string) /* look for the closing curly bracket character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == '}') { /* found the closing curly bracket */ *string = tstr + 1; /* set pointer to next char */ return(0); } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ int comma2semicolon(char *string) /* replace commas with semicolons, unless the comma is within a quoted or bracketed expression */ { char *tstr; tstr = string; while (*tstr) { if (*tstr == ',') { /* found a comma */ *tstr = ';'; tstr++; } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(0); /* reached end of string */ } /*--------------------------------------------------------------------------*/ int ffedit_columns( fitsfile **fptr, /* IO - pointer to input table; on output it */ /* points to the new selected rows table */ char *outfile, /* I - name for output file */ char *expr, /* I - column edit expression */ int *status) /* modify columns in a table and/or header keywords in the HDU */ { fitsfile *newptr; int ii, hdunum, slen, colnum = -1, testnum, deletecol = 0, savecol = 0; int numcols = 0, *colindex = 0, tstatus = 0; char *tstbuff=0, *cptr, *cptr2, *cptr3, *clause = NULL, keyname[FLEN_KEYWORD]; char colname[FLEN_VALUE], oldname[FLEN_VALUE], colformat[FLEN_VALUE]; char *file_expr = NULL, testname[FLEN_VALUE], card[FLEN_CARD]; if (*outfile) { /* create new empty file in to hold the selected rows */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg("failed to create file for copy (ffedit_columns)"); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ /* copy all HDUs to the output copy, if the 'only_one' flag is not set */ if (!((*fptr)->Fptr)->only_one) { for (ii = 1; 1; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, newptr, 0, status); } if (*status == END_OF_FILE) { *status = 0; /* got the expected EOF error; reset = 0 */ } else if (*status > 0) { ffclos(newptr, status); ffpmsg("failed to copy all HDUs from input file (ffedit_columns)"); return(*status); } } else { /* only copy the primary array and the designated table extension */ fits_movabs_hdu(*fptr, 1, NULL, status); fits_copy_hdu(*fptr, newptr, 0, status); fits_movabs_hdu(*fptr, hdunum, NULL, status); fits_copy_hdu(*fptr, newptr, 0, status); if (*status > 0) { ffclos(newptr, status); ffpmsg("failed to copy all HDUs from input file (ffedit_columns)"); return(*status); } hdunum = 2; } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ /* move back to the selected table HDU */ if (fits_movabs_hdu(*fptr, hdunum, NULL, status) > 0) { ffpmsg("failed to copy the input file (ffedit_columns)"); return(*status); } } /* remove the "col " from the beginning of the column edit expression */ cptr = expr + 4; while (*cptr == ' ') cptr++; /* skip leading white space */ /* Check if need to import expression from a file */ if( *cptr=='@' ) { if( ffimport_file( cptr+1, &file_expr, status ) ) return(*status); cptr = file_expr; while (*cptr == ' ') cptr++; /* skip leading white space... again */ } tstatus = 0; ffgncl(*fptr, &numcols, &tstatus); /* get initial # of cols */ /* as of July 2012, the CFITSIO column filter syntax was modified */ /* so that commas may be used to separate clauses, as well as semi-colons. */ /* This was done because users cannot enter the semi-colon in the HEASARC's */ /* Hera on-line data processing system for computer security reasons. */ /* Therefore, we must convert those commas back to semi-colons here, but we */ /* must not convert any columns that occur within parenthesies. */ if (comma2semicolon(cptr)) { ffpmsg("parsing error in column filter expression"); ffpmsg(cptr); if( file_expr ) free( file_expr ); *status = PARSE_SYNTAX_ERR; return(*status); } /* parse expression and get first clause, if more than 1 */ while ((slen = fits_get_token2(&cptr, ";", &clause, NULL, status)) > 0 ) { if( *cptr==';' ) cptr++; clause[slen] = '\0'; if (clause[0] == '!' || clause[0] == '-') { char *clause1 = clause+1; int clen = clause1[0] ? strlen(clause1) : 0; /* ===================================== */ /* Case I. delete this column or keyword */ /* ===================================== */ /* Case Ia. delete column names with 0-or-more wildcard -COLNAME+ - delete repeated columns with exact name -COLNAM*+ - delete columns matching patterns */ if (*status == 0 && clen > 1 && clause1[0] != '#' && clause1[clen-1] == '+') { clause1[clen-1] = 0; clen--; /* Note that this is a delete 0 or more specification, which means that no matching columns is not an error. */ do { int status_del = 0; /* Have to set status=0 so we can reset the search at start column. Because we are deleting columns on the fly here, we have to reset the search every time. The only penalty here is execution time because leaving *status == COL_NOT_UNIQUE is merely an optimization for tables assuming the tables do not change from one call to the next. (an assumption broken in this loop) */ *status = 0; ffgcno(*fptr, CASEINSEN, clause1, &colnum, status); /* ffgcno returns COL_NOT_UNIQUE if there are multiple columns, and COL_NOT_FOUND after the last column is found, and COL_NOT_FOUND if no matches were found */ if (*status != 0 && *status != COL_NOT_UNIQUE) break; if (ffdcol(*fptr, colnum, &status_del) > 0) { ffpmsg("failed to delete column in input file:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if( clause ) free(clause); return (*status = status_del); } deletecol = 1; /* set flag that at least one col was deleted */ numcols--; } while (*status == COL_NOT_UNIQUE); *status = 0; /* No matches are still successful */ colnum = -1; /* Ignore the column we found */ /* Case Ib. delete column names with wildcard or not -COLNAME - deleted exact column -COLNAM* - delete first column that matches pattern Note no leading '#' */ } else if (clause1[0] && clause1[0] != '#' && ((ffgcno(*fptr, CASEINSEN, clause1, &colnum, status) <= 0) || *status == COL_NOT_UNIQUE)) { /* a column with this name exists, so try to delete it */ *status = 0; /* Clear potential status=COL_NOT_UNIQUE */ if (ffdcol(*fptr, colnum, status) > 0) { ffpmsg("failed to delete column in input file:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if( clause ) free(clause); return(*status); } deletecol = 1; /* set flag that at least one col was deleted */ numcols--; colnum = -1; } /* Case Ic. delete keyword(s) -KEYNAME,#KEYNAME - delete exact keyword (first match) -KEYNAM*,#KEYNAM* - delete first matching keyword -KEYNAME+,-#KEYNAME+ - delete 0-or-more exact matches of exact keyword -KEYNAM*+,-#KEYNAM*+ - delete 0-or-more wildcard matches Note the preceding # is optional if no conflicting column name exists and that wildcard patterns are described in "colfilter" section of documentation. */ else { int delall = 0; int haswild = 0; ffcmsg(); /* clear previous error message from ffgcno */ /* try deleting a keyword with this name */ *status = 0; /* skip past leading '#' if any */ if (clause1[0] == '#') clause1++; clen = strlen(clause1); /* Repeat deletion of keyword if requested with trailing '+' */ if (clen > 1 && clause1[clen-1] == '+') { delall = 1; clause1[clen-1] = 0; } /* Determine if this pattern has wildcards */ if (strchr(clause1,'?') || strchr(clause1,'*') || strchr(clause1,'#')) { haswild = 1; } if (haswild) { /* ffdkey() behaves differently if the pattern has a wildcard: it only checks from the "current" header position to the end, and doesn't check before the "current" header position. Therefore, for the case of wildcards we will have to reset to the beginning. */ ffmaky(*fptr, 1, status); /* reset pointer to beginning of header */ } /* Single or repeated deletions until done */ do { if (ffdkey(*fptr, clause1, status) > 0) { if (delall && *status == KEY_NO_EXIST) { /* Found last wildcard item. Stop deleting */ ffcmsg(); *status = 0; delall = 0; /* Force end of this loop */ } else { /* This was not a wildcard deletion, or it resulted in another kind of error */ ffpmsg("column or keyword to be deleted does not exist:"); ffpmsg(clause1); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if( clause ) free(clause); return(*status); } } } while(delall); /* end do{} */ } } else { /* ===================================================== */ /* Case II: this is either a column name, (case 1) or a new column name followed by double = ("==") followed by the old name which is to be renamed. (case 2A) or a column or keyword name followed by a single "=" and a calculation expression (case 2B) */ /* ===================================================== */ cptr2 = clause; slen = fits_get_token2(&cptr2, "( =", &tstbuff, NULL, status); if (slen == 0 || *status) { ffpmsg("error: column or keyword name is blank (ffedit_columns):"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); if (*status==0) *status=URL_PARSE_ERROR; return(*status); } if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("error: column or keyword name is too long (ffedit_columns):"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); free(tstbuff); return(*status= URL_PARSE_ERROR); } strcpy(colname, tstbuff); free(tstbuff); tstbuff=0; /* If this is a keyword of the form #KEYWORD# then transform to the form #KEYWORDn where n is the previously used column number */ if (colname[0] == '#' && strstr(colname+1, "#") == (colname + strlen(colname) - 1)) { if (colnum <= 0) { ffpmsg("The keyword name:"); ffpmsg(colname); ffpmsg("is invalid unless a column has been previously"); ffpmsg("created or editted by a calculator command"); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status = URL_PARSE_ERROR); } colname[strlen(colname)-1] = '\0'; /* Make keyword name and put it in oldname */ ffkeyn(colname+1, colnum, oldname, status); if (*status) return (*status); /* Re-copy back into colname */ strcpy(colname+1,oldname); } else if (strstr(colname, "#") == (colname + strlen(colname) - 1)) { /* colname is of the form "NAME#"; if a) colnum is defined, and b) a column with literal name "NAME#" does not exist, and c) a keyword with name "NAMEn" (where n=colnum) exists, then transfrom the colname string to "NAMEn", otherwise do nothing. */ if (colnum > 0) { /* colnum must be defined */ tstatus = 0; ffgcno(*fptr, CASEINSEN, colname, &testnum, &tstatus); if (tstatus != 0 && tstatus != COL_NOT_UNIQUE) { /* OK, column doesn't exist, now see if keyword exists */ ffcmsg(); /* clear previous error message from ffgcno */ strcpy(testname, colname); testname[strlen(testname)-1] = '\0'; /* Make keyword name and put it in oldname */ ffkeyn(testname, colnum, oldname, status); if (*status) { if( file_expr ) free( file_expr ); if (clause) free(clause); return (*status); } tstatus = 0; if (!fits_read_card(*fptr, oldname, card, &tstatus)) { /* Keyword does exist; copy real name back into colname */ strcpy(colname,oldname); } } } } /* if we encountered an opening parenthesis, then we need to */ /* find the closing parenthesis, and concatinate the 2 strings */ /* This supports expressions like: [col #EXTNAME(Extension name)="GTI"] */ if (*cptr2 == '(') { if (fits_get_token2(&cptr2, ")", &tstbuff, NULL, status)==0) { strcat(colname,")"); } else { if ((strlen(tstbuff) + strlen(colname) + 1) > FLEN_VALUE-1) { ffpmsg("error: column name is too long (ffedit_columns):"); if( file_expr ) free( file_expr ); if (clause) free(clause); free(tstbuff); *status=URL_PARSE_ERROR; return (*status); } strcat(colname, tstbuff); strcat(colname, ")"); free(tstbuff); tstbuff=0; } cptr2++; } while (*cptr2 == ' ') cptr2++; /* skip white space */ if (*cptr2 != '=') { /* ------------------------------------ */ /* case 1 - simply the name of a column */ /* ------------------------------------ */ /* look for matching column */ ffgcno(*fptr, CASEINSEN, colname, &testnum, status); while (*status == COL_NOT_UNIQUE) { /* the column name contained wild cards, and it */ /* matches more than one column in the table. */ colnum = testnum; /* keep this column in the output file */ savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; /* flag this column number */ /* look for other matching column names */ ffgcno(*fptr, CASEINSEN, colname, &testnum, status); if (*status == COL_NOT_FOUND) *status = 999; /* temporary status flag value */ } if (*status <= 0) { colnum = testnum; /* keep this column in the output file */ savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; /* flag this column number */ } else if (*status == 999) { /* this special flag value does not represent an error */ *status = 0; } else { ffpmsg("Syntax error in columns specifier in input URL:"); ffpmsg(cptr2); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status = URL_PARSE_ERROR); } } else { /* ----------------------------------------------- */ /* case 2 where the token ends with an equals sign */ /* ----------------------------------------------- */ cptr2++; /* skip over the first '=' */ if (*cptr2 == '=') { /*................................................. */ /* Case A: rename a column or keyword; syntax is "new_name == old_name" */ /*................................................. */ cptr2++; /* skip the 2nd '=' */ while (*cptr2 == ' ') cptr2++; /* skip white space */ if (fits_get_token2(&cptr2, " ", &tstbuff, NULL, status)==0) { oldname[0]=0; } else { if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("error: column name syntax is too long (ffedit_columns):"); if( file_expr ) free( file_expr ); if (clause) free(clause); free(tstbuff); *status=URL_PARSE_ERROR; return (*status); } strcpy(oldname, tstbuff); free(tstbuff); tstbuff=0; } /* get column number of the existing column */ if (ffgcno(*fptr, CASEINSEN, oldname, &colnum, status) <= 0) { /* modify the TTYPEn keyword value with the new name */ ffkeyn("TTYPE", colnum, keyname, status); if (ffmkys(*fptr, keyname, colname, NULL, status) > 0) { ffpmsg("failed to rename column in input file"); ffpmsg(" oldname ="); ffpmsg(oldname); ffpmsg(" newname ="); ffpmsg(colname); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } /* keep this column in the output file */ savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; /* flag this column number */ } else { /* try renaming a keyword */ ffcmsg(); /* clear error message stack */ *status = 0; if (ffmnam(*fptr, oldname, colname, status) > 0) { ffpmsg("column or keyword to be renamed does not exist:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } } } else { /*...................................................... */ /* Case B: */ /* this must be a general column/keyword calc expression */ /* "name = expression" or "colname(TFORM) = expression" */ /*...................................................... */ /* parse the name and TFORM values, if present */ colformat[0] = '\0'; cptr3 = colname; if (fits_get_token2(&cptr3, "(", &tstbuff, NULL, status)==0) { oldname[0]=0; } else { if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("column expression is too long (ffedit_columns)"); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); free(tstbuff); *status=URL_PARSE_ERROR; return(*status); } strcpy(oldname, tstbuff); free(tstbuff); tstbuff=0; } if (cptr3[0] == '(' ) { cptr3++; /* skip the '(' */ if (fits_get_token2(&cptr3, ")", &tstbuff, NULL, status)==0) { colformat[0]=0; } else { if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("column expression is too long (ffedit_columns)"); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); free(tstbuff); *status=URL_PARSE_ERROR; return(*status); } strcpy(colformat, tstbuff); free(tstbuff); tstbuff=0; } } /* calculate values for the column or keyword */ /* cptr2 = the expression to be calculated */ /* oldname = name of the column or keyword */ /* colformat = column format, or keyword comment string */ if (fits_calculator(*fptr, cptr2, *fptr, oldname, colformat, status) > 0) { ffpmsg("Unable to calculate expression"); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } /* test if this is a column and not a keyword */ tstatus = 0; ffgcno(*fptr, CASEINSEN, oldname, &testnum, &tstatus); if (tstatus == 0) { /* keep this column in the output file */ colnum = testnum; savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; if (colnum > numcols)numcols++; } else { ffcmsg(); /* clear the error message stack */ } } } } if (clause) free(clause); /* free old clause before getting new one */ clause = NULL; } if (savecol && !deletecol) { /* need to delete all but the specified columns */ for (ii = numcols; ii > 0; ii--) { if (!colindex[ii-1]) /* delete this column */ { if (ffdcol(*fptr, ii, status) > 0) { ffpmsg("failed to delete column in input file:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } } } } if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_cell2image( fitsfile *fptr, /* I - point to input table */ fitsfile *newptr, /* O - existing output file; new image HDU will be appended to it */ char *colname, /* I - column name / number containing the image*/ long rownum, /* I - number of the row containing the image */ int *status) /* IO - error status */ /* Copy a table cell of a given row and column into an image extension. The output file must already have been created. A new image extension will be created in that file. This routine was written by Craig Markwardt, GSFC */ { unsigned char buffer[30000]; int hdutype, colnum, typecode, bitpix, naxis, maxelem, tstatus; LONGLONG naxes[9], nbytes, firstbyte, ntodo; LONGLONG repeat, startpos, elemnum, rowlen, tnull; long twidth, incre; double scale, zero; char tform[20]; char card[FLEN_CARD]; char templt[FLEN_CARD] = ""; /* Table-to-image keyword translation table */ /* INPUT OUTPUT */ /* 01234567 01234567 */ char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ {"TZEROn", "BZERO" }, {"TUNITn", "BUNIT" }, {"TNULLn", "BLANK" }, {"TDMINn", "DATAMIN" }, {"TDMAXn", "DATAMAX" }, {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ {"iCTYna", "CTYPEia" }, {"iCUNIn", "CUNITi" }, /* Coordinate units */ {"iCUNna", "CUNITia" }, {"iCRVLn", "CRVALi" }, /* WCS keywords */ {"iCRVna", "CRVALia" }, {"iCDLTn", "CDELTi" }, {"iCDEna", "CDELTia" }, {"iCRPXn", "CRPIXi" }, {"iCRPna", "CRPIXia" }, {"ijPCna", "PCi_ja" }, {"ijCDna", "CDi_ja" }, {"iVn_ma", "PVi_ma" }, {"iSn_ma", "PSi_ma" }, {"iCRDna", "CRDERia" }, {"iCSYna", "CSYERia" }, {"iCROTn", "CROTAi" }, {"WCAXna", "WCSAXESa"}, {"WCSNna", "WCSNAMEa"}, {"LONPna", "LONPOLEa"}, {"LATPna", "LATPOLEa"}, {"EQUIna", "EQUINOXa"}, {"MJDOBn", "MJD-OBS" }, {"MJDAn", "MJD-AVG" }, {"RADEna", "RADESYSa"}, {"iCNAna", "CNAMEia" }, {"DAVGn", "DATE-AVG"}, /* Delete table keywords related to other columns */ {"T????#a", "-" }, {"TC??#a", "-" }, {"TWCS#a", "-" }, {"TDIM#", "-" }, {"iCTYPm", "-" }, {"iCUNIm", "-" }, {"iCRVLm", "-" }, {"iCDLTm", "-" }, {"iCRPXm", "-" }, {"iCTYma", "-" }, {"iCUNma", "-" }, {"iCRVma", "-" }, {"iCDEma", "-" }, {"iCRPma", "-" }, {"ijPCma", "-" }, {"ijCDma", "-" }, {"iVm_ma", "-" }, {"iSm_ma", "-" }, {"iCRDma", "-" }, {"iCSYma", "-" }, {"iCROTm", "-" }, {"WCAXma", "-" }, {"WCSNma", "-" }, {"LONPma", "-" }, {"LATPma", "-" }, {"EQUIma", "-" }, {"MJDOBm", "-" }, {"MJDAm", "-" }, {"RADEma", "-" }, {"iCNAma", "-" }, {"DAVGm", "-" }, {"EXTNAME", "-" }, /* Remove structural keywords*/ {"EXTVER", "-" }, {"EXTLEVEL","-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"*", "+" }}; /* copy all other keywords */ int npat; if (*status > 0) return(*status); /* get column number */ if (ffgcno(fptr, CASEINSEN, colname, &colnum, status) > 0) { ffpmsg("column containing image in table cell does not exist:"); ffpmsg(colname); return(*status); } /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if ( ffgcprll(fptr, colnum, rownum, 1L, 1L, 0, &scale, &zero, tform, &twidth, &typecode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, (char *) buffer, status) > 0 ) return(*status); /* get the actual column name, in case a column number was given */ ffkeyn("", colnum, templt, &tstatus); ffgcnn(fptr, CASEINSEN, templt, colname, &colnum, &tstatus); if (hdutype != BINARY_TBL) { ffpmsg("This extension is not a binary table."); ffpmsg(" Cannot open the image in a binary table cell."); return(*status = NOT_BTABLE); } if (typecode < 0) { /* variable length array */ typecode *= -1; /* variable length arrays are 1-dimensional by default */ naxis = 1; naxes[0] = repeat; } else { /* get the dimensions of the image */ ffgtdmll(fptr, colnum, 9, &naxis, naxes, status); } if (*status > 0) { ffpmsg("Error getting the dimensions of the image"); return(*status); } /* determine BITPIX value for the image */ if (typecode == TBYTE) { bitpix = BYTE_IMG; nbytes = repeat; } else if (typecode == TSHORT) { bitpix = SHORT_IMG; nbytes = repeat * 2; } else if (typecode == TLONG) { bitpix = LONG_IMG; nbytes = repeat * 4; } else if (typecode == TFLOAT) { bitpix = FLOAT_IMG; nbytes = repeat * 4; } else if (typecode == TDOUBLE) { bitpix = DOUBLE_IMG; nbytes = repeat * 8; } else if (typecode == TLONGLONG) { bitpix = LONGLONG_IMG; nbytes = repeat * 8; } else if (typecode == TLOGICAL) { bitpix = BYTE_IMG; nbytes = repeat; } else { ffpmsg("Error: the following image column has invalid datatype:"); ffpmsg(colname); ffpmsg(tform); ffpmsg("Cannot open an image in a single row of this column."); return(*status = BAD_TFORM); } /* create new image in output file */ if (ffcrimll(newptr, bitpix, naxis, naxes, status) > 0) { ffpmsg("failed to write required primary array keywords in the output file"); return(*status); } npat = sizeof(patterns)/sizeof(patterns[0][0])/2; /* skip over the first 8 keywords, starting just after TFIELDS */ fits_translate_keywords(fptr, newptr, 9, patterns, npat, colnum, 0, 0, status); /* add some HISTORY */ snprintf(card,FLEN_CARD,"HISTORY This image was copied from row %ld of column '%s',", rownum, colname); /* disable this; leave it up to the caller to write history if needed. ffprec(newptr, card, status); */ /* the use of ffread routine, below, requires that any 'dirty' */ /* buffers in memory be flushed back to the file first */ ffflsh(fptr, FALSE, status); /* finally, copy the data, one buffer size at a time */ ffmbyt(fptr, startpos, TRUE, status); firstbyte = 1; /* the upper limit on the number of bytes must match the declaration */ /* read up to the first 30000 bytes in the normal way with ffgbyt */ ntodo = minvalue(30000, nbytes); ffgbyt(fptr, ntodo, buffer, status); ffptbb(newptr, 1, firstbyte, ntodo, buffer, status); nbytes -= ntodo; firstbyte += ntodo; /* read any additional bytes with low-level ffread routine, for speed */ while (nbytes && (*status <= 0) ) { ntodo = minvalue(30000, nbytes); ffread((fptr)->Fptr, (long) ntodo, buffer, status); ffptbb(newptr, 1, firstbyte, ntodo, buffer, status); nbytes -= ntodo; firstbyte += ntodo; } /* Re-scan the header so that CFITSIO knows about all the new keywords */ ffrdef(newptr,status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_image2cell( fitsfile *fptr, /* I - pointer to input image extension */ fitsfile *newptr, /* I - pointer to output table */ char *colname, /* I - name of column containing the image */ long rownum, /* I - number of the row containing the image */ int copykeyflag, /* I - controls which keywords to copy */ int *status) /* IO - error status */ /* Copy an image extension into a table cell at a given row and column. The table must have already been created. If the "colname" column exists, it will be used, otherwise a new column will be created in the table. The "copykeyflag" parameter controls which keywords to copy from the input image to the output table header (with any appropriate translation). copykeyflag = 0 -- no keywords will be copied copykeyflag = 1 -- essentially all keywords will be copied copykeyflag = 2 -- copy only the WCS related keywords This routine was written by Craig Markwardt, GSFC */ { tcolumn *colptr; unsigned char buffer[30000]; int ii, hdutype, colnum, typecode, bitpix, naxis, ncols, hdunum; char tformchar, tform[20], card[FLEN_CARD]; LONGLONG imgstart, naxes[9], nbytes, repeat, ntodo,firstbyte; char filename[FLEN_FILENAME+20]; int npat; int naxis1; LONGLONG naxes1[9] = {0,0,0,0,0,0,0,0,0}, repeat1, width1; int typecode1; unsigned char dummy = 0; LONGLONG headstart, datastart, dataend; /* Image-to-table keyword translation table */ /* INPUT OUTPUT */ /* 01234567 01234567 */ char *patterns[][2] = {{"BSCALE", "TSCALn" }, /* Standard FITS keywords */ {"BZERO", "TZEROn" }, {"BUNIT", "TUNITn" }, {"BLANK", "TNULLn" }, {"DATAMIN", "TDMINn" }, {"DATAMAX", "TDMAXn" }, {"CTYPEi", "iCTYPn" }, /* Coordinate labels */ {"CTYPEia", "iCTYna" }, {"CUNITi", "iCUNIn" }, /* Coordinate units */ {"CUNITia", "iCUNna" }, {"CRVALi", "iCRVLn" }, /* WCS keywords */ {"CRVALia", "iCRVna" }, {"CDELTi", "iCDLTn" }, {"CDELTia", "iCDEna" }, {"CRPIXj", "jCRPXn" }, {"CRPIXja", "jCRPna" }, {"PCi_ja", "ijPCna" }, {"CDi_ja", "ijCDna" }, {"PVi_ma", "iVn_ma" }, {"PSi_ma", "iSn_ma" }, {"WCSAXESa","WCAXna" }, {"WCSNAMEa","WCSNna" }, {"CRDERia", "iCRDna" }, {"CSYERia", "iCSYna" }, {"CROTAi", "iCROTn" }, {"LONPOLEa","LONPna"}, {"LATPOLEa","LATPna"}, {"EQUINOXa","EQUIna"}, {"MJD-OBS", "MJDOBn" }, {"MJD-AVG", "MJDAn" }, {"RADESYSa","RADEna"}, {"CNAMEia", "iCNAna" }, {"DATE-AVG","DAVGn"}, {"NAXISi", "-" }, /* Remove structural keywords*/ {"PCOUNT", "-" }, {"GCOUNT", "-" }, {"EXTEND", "-" }, {"EXTNAME", "-" }, {"EXTVER", "-" }, {"EXTLEVEL","-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"*", "+" }}; /* copy all other keywords */ if (*status > 0) return(*status); if (fptr == 0 || newptr == 0) return (*status = NULL_INPUT_PTR); if (ffghdt(fptr, &hdutype, status) > 0) { ffpmsg("could not get input HDU type"); return (*status); } if (hdutype != IMAGE_HDU) { ffpmsg("The input extension is not an image."); ffpmsg(" Cannot open the image."); return(*status = NOT_IMAGE); } if (ffghdt(newptr, &hdutype, status) > 0) { ffpmsg("could not get output HDU type"); return (*status); } if (hdutype != BINARY_TBL) { ffpmsg("The output extension is not a table."); return(*status = NOT_BTABLE); } if (ffgiprll(fptr, 9, &bitpix, &naxis, naxes, status) > 0) { ffpmsg("Could not read image parameters."); return (*status); } /* Determine total number of pixels in the image */ repeat = 1; for (ii = 0; ii < naxis; ii++) repeat *= naxes[ii]; /* Determine the TFORM value for the table cell */ if (bitpix == BYTE_IMG) { typecode = TBYTE; tformchar = 'B'; nbytes = repeat; } else if (bitpix == SHORT_IMG) { typecode = TSHORT; tformchar = 'I'; nbytes = repeat*2; } else if (bitpix == LONG_IMG) { typecode = TLONG; tformchar = 'J'; nbytes = repeat*4; } else if (bitpix == FLOAT_IMG) { typecode = TFLOAT; tformchar = 'E'; nbytes = repeat*4; } else if (bitpix == DOUBLE_IMG) { typecode = TDOUBLE; tformchar = 'D'; nbytes = repeat*8; } else if (bitpix == LONGLONG_IMG) { typecode = TLONGLONG; tformchar = 'K'; nbytes = repeat*8; } else { ffpmsg("Error: the image has an invalid datatype."); return (*status = BAD_BITPIX); } /* get column number */ ffpmrk(); ffgcno(newptr, CASEINSEN, colname, &colnum, status); ffcmrk(); /* Column does not exist; create it */ if (*status) { *status = 0; snprintf(tform, 20, "%.0f%c", (double) repeat, tformchar); ffgncl(newptr, &ncols, status); colnum = ncols+1; fficol(newptr, colnum, colname, tform, status); ffptdmll(newptr, colnum, naxis, naxes, status); if (*status) { ffpmsg("Could not insert new column into output table."); return *status; } } else { ffgtdmll(newptr, colnum, 9, &naxis1, naxes1, status); if (*status > 0 || naxis != naxis1) { ffpmsg("Input image dimensions and output table cell dimensions do not match."); return (*status = BAD_DIMEN); } for (ii=0; ii 0) || (typecode1 != typecode) || (repeat1 != repeat)) { ffpmsg("Input image data type does not match output table cell type."); return (*status = BAD_TFORM); } } /* copy keywords from input image to output table, if required */ if (copykeyflag) { npat = sizeof(patterns)/sizeof(patterns[0][0])/2; if (copykeyflag == 2) { /* copy only the WCS-related keywords */ patterns[npat-1][1] = "-"; } /* The 3rd parameter value = 5 means skip the first 4 keywords in the image */ fits_translate_keywords(fptr, newptr, 5, patterns, npat, colnum, 0, 0, status); } /* Here is all the code to compute offsets: * * byte offset from start of row to column (dest table) * * byte offset from start of file to image data (source image) */ /* Force the writing of the row of the table by writing the last byte of the array, which grows the table, and/or shifts following extensions */ ffpcl(newptr, TBYTE, colnum, rownum, repeat, 1, &dummy, status); /* byte offset within the row to the start of the image column */ colptr = (newptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ firstbyte = colptr->tbcol + 1; /* get starting address of input image to be read */ ffghadll(fptr, &headstart, &datastart, &dataend, status); imgstart = datastart; snprintf(card, FLEN_CARD, "HISTORY Table column '%s' row %ld copied from image", colname, rownum); /* Don't automatically write History keywords; leave this up to the caller. ffprec(newptr, card, status); */ /* write HISTORY keyword with the file name (this is now disabled)*/ filename[0] = '\0'; hdunum = 0; strcpy(filename, "HISTORY "); ffflnm(fptr, filename+strlen(filename), status); ffghdn(fptr, &hdunum); snprintf(filename+strlen(filename),FLEN_FILENAME+20-strlen(filename),"[%d]", hdunum-1); /* ffprec(newptr, filename, status); */ /* the use of ffread routine, below, requires that any 'dirty' */ /* buffers in memory be flushed back to the file first */ ffflsh(fptr, FALSE, status); /* move to the first byte of the input image */ ffmbyt(fptr, imgstart, TRUE, status); ntodo = minvalue(30000L, nbytes); ffgbyt(fptr, ntodo, buffer, status); /* read input image */ ffptbb(newptr, rownum, firstbyte, ntodo, buffer, status); /* write to table */ nbytes -= ntodo; firstbyte += ntodo; /* read any additional bytes with low-level ffread routine, for speed */ while (nbytes && (*status <= 0) ) { ntodo = minvalue(30000L, nbytes); ffread(fptr->Fptr, (long) ntodo, buffer, status); ffptbb(newptr, rownum, firstbyte, ntodo, buffer, status); nbytes -= ntodo; firstbyte += ntodo; } /* Re-scan the header so that CFITSIO knows about all the new keywords */ ffrdef(newptr,status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_select_image_section( fitsfile **fptr, /* IO - pointer to input image; on output it */ /* points to the new subimage */ char *outfile, /* I - name for output file */ char *expr, /* I - Image section expression */ int *status) { /* copies an image section from the input file to a new output file. Any HDUs preceding or following the image are also copied to the output file. */ fitsfile *newptr; int ii, hdunum; /* create new empty file to hold the image section */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg( "failed to create output file for image section:"); ffpmsg(outfile); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ /* copy all preceding extensions to the output file, if 'only_one' flag not set */ if (!(((*fptr)->Fptr)->only_one)) { for (ii = 1; ii < hdunum; ii++) { fits_movabs_hdu(*fptr, ii, NULL, status); if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) { ffclos(newptr, status); return(*status); } } /* move back to the original HDU position */ fits_movabs_hdu(*fptr, hdunum, NULL, status); } if (fits_copy_image_section(*fptr, newptr, expr, status) > 0) { ffclos(newptr, status); return(*status); } /* copy any remaining HDUs to the output file, if 'only_one' flag not set */ if (!(((*fptr)->Fptr)->only_one)) { for (ii = hdunum + 1; 1; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, newptr, 0, status); } if (*status == END_OF_FILE) *status = 0; /* got the expected EOF error; reset = 0 */ else if (*status > 0) { ffclos(newptr, status); return(*status); } } else { ii = hdunum + 1; /* this value of ii is required below */ } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ /* move back to the image subsection */ if (ii - 1 != hdunum) fits_movabs_hdu(*fptr, hdunum, NULL, status); else { /* may have to reset BSCALE and BZERO pixel scaling, */ /* since the keywords were previously turned off */ if (ffrdef(*fptr, status) > 0) { ffclos(*fptr, status); return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_image_section( fitsfile *fptr, /* I - pointer to input image */ fitsfile *newptr, /* I - pointer to output image */ char *expr, /* I - Image section expression */ int *status) { /* copies an image section from the input file to a new output HDU */ int bitpix, naxis, numkeys, nkey; long naxes[] = {1,1,1,1,1,1,1,1,1}, smin, smax, sinc; long fpixels[] = {1,1,1,1,1,1,1,1,1}; long lpixels[] = {1,1,1,1,1,1,1,1,1}; long incs[] = {1,1,1,1,1,1,1,1,1}; char *cptr, keyname[FLEN_KEYWORD], card[FLEN_CARD]; int ii, tstatus, anynull; long minrow, maxrow, minslice, maxslice, mincube, maxcube; long firstpix; long ncubeiter, nsliceiter, nrowiter, kiter, jiter, iiter; int klen, kk, jj; long outnaxes[9], outsize, buffsize; double *buffer, crpix, cdelt; if (*status > 0) return(*status); /* get the size of the input image */ fits_get_img_type(fptr, &bitpix, status); fits_get_img_dim(fptr, &naxis, status); if (fits_get_img_size(fptr, naxis, naxes, status) > 0) return(*status); if (naxis < 1 || naxis > 4) { ffpmsg( "Input image either had NAXIS = 0 (NULL image) or has > 4 dimensions"); return(*status = BAD_NAXIS); } /* create output image with same size and type as the input image */ /* Will update the size later */ fits_create_img(newptr, bitpix, naxis, naxes, status); /* copy all other non-structural keywords from the input to output file */ fits_get_hdrspace(fptr, &numkeys, NULL, status); for (nkey = 4; nkey <= numkeys; nkey++) /* skip the first few keywords */ { fits_read_record(fptr, nkey, card, status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY) { /* write the record to the output file */ fits_write_record(newptr, card, status); } } if (*status > 0) { ffpmsg("error copying header from input image to output image"); return(*status); } /* parse the section specifier to get min, max, and inc for each axis */ /* and the size of each output image axis */ cptr = expr; for (ii=0; ii < naxis; ii++) { if (fits_get_section_range(&cptr, &smin, &smax, &sinc, status) > 0) { ffpmsg("error parsing the following image section specifier:"); ffpmsg(expr); return(*status); } if (smax == 0) smax = naxes[ii]; /* use whole axis by default */ else if (smin == 0) smin = naxes[ii]; /* use inverted whole axis */ if (smin > naxes[ii] || smax > naxes[ii]) { ffpmsg("image section exceeds dimensions of input image:"); ffpmsg(expr); return(*status = BAD_NAXIS); } fpixels[ii] = smin; lpixels[ii] = smax; incs[ii] = sinc; if (smin <= smax) outnaxes[ii] = (smax - smin + sinc) / sinc; else outnaxes[ii] = (smin - smax + sinc) / sinc; /* modify the NAXISn keyword */ fits_make_keyn("NAXIS", ii + 1, keyname, status); fits_modify_key_lng(newptr, keyname, outnaxes[ii], NULL, status); /* modify the WCS keywords if necessary */ if (fpixels[ii] != 1 || incs[ii] != 1) { for (kk=-1;kk<26; kk++) /* modify any alternate WCS keywords */ { /* read the CRPIXn keyword if it exists in the input file */ fits_make_keyn("CRPIX", ii + 1, keyname, status); if (kk != -1) { klen = strlen(keyname); keyname[klen]='A' + kk; keyname[klen + 1] = '\0'; } tstatus = 0; if (fits_read_key(fptr, TDOUBLE, keyname, &crpix, NULL, &tstatus) == 0) { /* calculate the new CRPIXn value */ if (fpixels[ii] <= lpixels[ii]) { crpix = (crpix - (fpixels[ii])) / incs[ii] + 1.0; /* crpix = (crpix - (fpixels[ii] - 1.0) - .5) / incs[ii] + 0.5; */ } else { crpix = (fpixels[ii] - crpix) / incs[ii] + 1.0; /* crpix = (fpixels[ii] - (crpix - 1.0) - .5) / incs[ii] + 0.5; */ } /* modify the value in the output file */ fits_modify_key_dbl(newptr, keyname, crpix, 15, NULL, status); if (incs[ii] != 1 || fpixels[ii] > lpixels[ii]) { /* read the CDELTn keyword if it exists in the input file */ fits_make_keyn("CDELT", ii + 1, keyname, status); if (kk != -1) { klen = strlen(keyname); keyname[klen]='A' + kk; keyname[klen + 1] = '\0'; } tstatus = 0; if (fits_read_key(fptr, TDOUBLE, keyname, &cdelt, NULL, &tstatus) == 0) { /* calculate the new CDELTn value */ if (fpixels[ii] <= lpixels[ii]) cdelt = cdelt * incs[ii]; else cdelt = cdelt * (-incs[ii]); /* modify the value in the output file */ fits_modify_key_dbl(newptr, keyname, cdelt, 15, NULL, status); } /* modify the CDi_j keywords if they exist in the input file */ fits_make_keyn("CD1_", ii + 1, keyname, status); if (kk != -1) { klen = strlen(keyname); keyname[klen]='A' + kk; keyname[klen + 1] = '\0'; } for (jj=0; jj < 9; jj++) /* look for up to 9 dimensions */ { keyname[2] = '1' + jj; tstatus = 0; if (fits_read_key(fptr, TDOUBLE, keyname, &cdelt, NULL, &tstatus) == 0) { /* calculate the new CDi_j value */ if (fpixels[ii] <= lpixels[ii]) cdelt = cdelt * incs[ii]; else cdelt = cdelt * (-incs[ii]); /* modify the value in the output file */ fits_modify_key_dbl(newptr, keyname, cdelt, 15, NULL, status); } } } /* end of if (incs[ii]... loop */ } /* end of fits_read_key loop */ } /* end of for (kk loop */ } } /* end of main NAXIS loop */ if (ffrdef(newptr, status) > 0) /* force the header to be scanned */ { return(*status); } /* turn off any scaling of the pixel values */ fits_set_bscale(fptr, 1.0, 0.0, status); fits_set_bscale(newptr, 1.0, 0.0, status); /* to reduce memory foot print, just read/write image 1 row at a time */ outsize = outnaxes[0]; buffsize = (abs(bitpix) / 8) * outsize; buffer = (double *) malloc(buffsize); /* allocate memory for the image row */ if (!buffer) { ffpmsg("fits_copy_image_section: no memory for image section"); return(*status = MEMORY_ALLOCATION); } /* read the image section then write it to the output file */ minrow = fpixels[1]; maxrow = lpixels[1]; if (minrow > maxrow) { nrowiter = (minrow - maxrow + incs[1]) / incs[1]; } else { nrowiter = (maxrow - minrow + incs[1]) / incs[1]; } minslice = fpixels[2]; maxslice = lpixels[2]; if (minslice > maxslice) { nsliceiter = (minslice - maxslice + incs[2]) / incs[2]; } else { nsliceiter = (maxslice - minslice + incs[2]) / incs[2]; } mincube = fpixels[3]; maxcube = lpixels[3]; if (mincube > maxcube) { ncubeiter = (mincube - maxcube + incs[3]) / incs[3]; } else { ncubeiter = (maxcube - mincube + incs[3]) / incs[3]; } firstpix = 1; for (kiter = 0; kiter < ncubeiter; kiter++) { if (mincube > maxcube) { fpixels[3] = mincube - (kiter * incs[3]); } else { fpixels[3] = mincube + (kiter * incs[3]); } lpixels[3] = fpixels[3]; for (jiter = 0; jiter < nsliceiter; jiter++) { if (minslice > maxslice) { fpixels[2] = minslice - (jiter * incs[2]); } else { fpixels[2] = minslice + (jiter * incs[2]); } lpixels[2] = fpixels[2]; for (iiter = 0; iiter < nrowiter; iiter++) { if (minrow > maxrow) { fpixels[1] = minrow - (iiter * incs[1]); } else { fpixels[1] = minrow + (iiter * incs[1]); } lpixels[1] = fpixels[1]; if (bitpix == 8) { ffgsvb(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (unsigned char *) buffer, &anynull, status); ffpprb(newptr, 1, firstpix, outsize, (unsigned char *) buffer, status); } else if (bitpix == 16) { ffgsvi(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (short *) buffer, &anynull, status); ffppri(newptr, 1, firstpix, outsize, (short *) buffer, status); } else if (bitpix == 32) { ffgsvk(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (int *) buffer, &anynull, status); ffpprk(newptr, 1, firstpix, outsize, (int *) buffer, status); } else if (bitpix == -32) { ffgsve(fptr, 1, naxis, naxes, fpixels, lpixels, incs, FLOATNULLVALUE, (float *) buffer, &anynull, status); ffppne(newptr, 1, firstpix, outsize, (float *) buffer, FLOATNULLVALUE, status); } else if (bitpix == -64) { ffgsvd(fptr, 1, naxis, naxes, fpixels, lpixels, incs, DOUBLENULLVALUE, buffer, &anynull, status); ffppnd(newptr, 1, firstpix, outsize, buffer, DOUBLENULLVALUE, status); } else if (bitpix == 64) { ffgsvjj(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (LONGLONG *) buffer, &anynull, status); ffpprjj(newptr, 1, firstpix, outsize, (LONGLONG *) buffer, status); } firstpix += outsize; } } } free(buffer); /* finished with the memory */ if (*status > 0) { ffpmsg("fits_copy_image_section: error copying image section"); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_section_range(char **ptr, long *secmin, long *secmax, long *incre, int *status) /* Parse the input image section specification string, returning the min, max and increment values. Typical string = "1:512:2" or "1:512" */ { int slen, isanumber; char token[FLEN_VALUE], *tstbuff=0; if (*status > 0) return(*status); slen = fits_get_token2(ptr, " ,:", &tstbuff, &isanumber, status); /* get 1st token */ if (slen==0) { /* support [:2,:2] type syntax, where the leading * is implied */ strcpy(token,"*"); } else { if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("Error: image section string too long (fits_get_section_range)"); free(tstbuff); *status = URL_PARSE_ERROR; return(*status); } strcpy(token, tstbuff); free(tstbuff); tstbuff=0; } if (*token == '*') /* wild card means to use the whole range */ { *secmin = 1; *secmax = 0; } else if (*token == '-' && *(token+1) == '*' ) /* invert the whole range */ { *secmin = 0; *secmax = 1; } else { if (slen == 0 || !isanumber || **ptr != ':') return(*status = URL_PARSE_ERROR); /* the token contains the min value */ *secmin = atol(token); (*ptr)++; /* skip the colon between the min and max values */ slen = fits_get_token2(ptr, " ,:", &tstbuff, &isanumber, status); /* get token */ if (slen == 0 || !isanumber) { if (tstbuff) free(tstbuff); return(*status = URL_PARSE_ERROR); } if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("Error: image section string too long (fits_get_section_range)"); free(tstbuff); *status = URL_PARSE_ERROR; return(*status); } strcpy(token, tstbuff); free(tstbuff); tstbuff=0; /* the token contains the max value */ *secmax = atol(token); } if (**ptr == ':') { (*ptr)++; /* skip the colon between the max and incre values */ slen = fits_get_token2(ptr, " ,", &tstbuff, &isanumber, status); /* get token */ if (slen == 0 || !isanumber) { if (tstbuff) free(tstbuff); return(*status = URL_PARSE_ERROR); } if (strlen(tstbuff) > FLEN_VALUE-1) { ffpmsg("Error: image section string too long (fits_get_section_range)"); free(tstbuff); *status = URL_PARSE_ERROR; return(*status); } strcpy(token, tstbuff); free(tstbuff); tstbuff=0; *incre = atol(token); } else *incre = 1; /* default increment if none is supplied */ if (**ptr == ',') (*ptr)++; while (**ptr == ' ') /* skip any trailing blanks */ (*ptr)++; if (*secmin < 0 || *secmax < 0 || *incre < 1) *status = URL_PARSE_ERROR; return(*status); } /*--------------------------------------------------------------------------*/ int ffselect_table( fitsfile **fptr, /* IO - pointer to input table; on output it */ /* points to the new selected rows table */ char *outfile, /* I - name for output file */ char *expr, /* I - Boolean expression */ int *status) { fitsfile *newptr; int ii, hdunum; if (*outfile) { /* create new empty file in to hold the selected rows */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg( "failed to create file for selected rows from input table"); ffpmsg(outfile); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ /* copy all preceding extensions to the output file, if the 'only_one' flag is not set */ if (!((*fptr)->Fptr)->only_one) { for (ii = 1; ii < hdunum; ii++) { fits_movabs_hdu(*fptr, ii, NULL, status); if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) { ffclos(newptr, status); return(*status); } } } else { /* just copy the primary array */ fits_movabs_hdu(*fptr, 1, NULL, status); if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) { ffclos(newptr, status); return(*status); } } fits_movabs_hdu(*fptr, hdunum, NULL, status); /* copy all the header keywords from the input to output file */ if (fits_copy_header(*fptr, newptr, status) > 0) { ffclos(newptr, status); return(*status); } /* set number of rows = 0 */ fits_modify_key_lng(newptr, "NAXIS2", 0, NULL,status); (newptr->Fptr)->numrows = 0; (newptr->Fptr)->origrows = 0; if (ffrdef(newptr, status) > 0) /* force the header to be scanned */ { ffclos(newptr, status); return(*status); } } else newptr = *fptr; /* will delete rows in place in the table */ /* copy rows which satisfy the selection expression to the output table */ /* or delete the nonqualifying rows if *fptr = newptr. */ if (fits_select_rows(*fptr, newptr, expr, status) > 0) { if (*outfile) ffclos(newptr, status); return(*status); } if (*outfile) { /* copy any remaining HDUs to the output copy */ if (!((*fptr)->Fptr)->only_one) { for (ii = hdunum + 1; 1; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, newptr, 0, status); } if (*status == END_OF_FILE) *status = 0; /* got the expected EOF error; reset = 0 */ else if (*status > 0) { ffclos(newptr, status); return(*status); } } else { hdunum = 2; } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ /* move back to the selected table HDU */ fits_movabs_hdu(*fptr, hdunum, NULL, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffparsecompspec(fitsfile *fptr, /* I - FITS file pointer */ char *compspec, /* I - image compression specification */ int *status) /* IO - error status */ /* Parse the image compression specification that was give in square brackets following the output FITS file name, as in these examples: myfile.fits[compress] - default Rice compression, row by row myfile.fits[compress TYPE] - the first letter of TYPE defines the compression algorithm: R = Rice G = GZIP H = HCOMPRESS HS = HCOMPRESS (with smoothing) B - BZIP2 P = PLIO myfile.fits[compress TYPE 100,100] - the numbers give the dimensions of the compression tiles. Default is NAXIS1, 1, 1, ... other optional parameters may be specified following a semi-colon myfile.fits[compress; q 8.0] q specifies the floating point mufile.fits[compress TYPE; q -.0002] quantization level; myfile.fits[compress TYPE 100,100; q 10, s 25] s specifies the HCOMPRESS integer scaling parameter The compression parameters are saved in the fptr->Fptr structure for use when writing FITS images. */ { char *ptr1; /* initialize with default values */ int ii, compresstype = RICE_1, smooth = 0; int quantize_method = SUBTRACTIVE_DITHER_1; long tilesize[MAX_COMPRESS_DIM] = {0,0,0,0,0,0}; float qlevel = -99., scale = 0.; ptr1 = compspec; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; if (strncmp(ptr1, "compress", 8) && strncmp(ptr1, "COMPRESS", 8) ) { /* apparently this string does not specify compression parameters */ return(*status = URL_PARSE_ERROR); } ptr1 += 8; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; /* ========================= */ /* look for compression type */ /* ========================= */ if (*ptr1 == 'r' || *ptr1 == 'R') { compresstype = RICE_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } else if (*ptr1 == 'g' || *ptr1 == 'G') { compresstype = GZIP_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } /* else if (*ptr1 == 'b' || *ptr1 == 'B') { compresstype = BZIP2_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } */ else if (*ptr1 == 'p' || *ptr1 == 'P') { compresstype = PLIO_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } else if (*ptr1 == 'h' || *ptr1 == 'H') { compresstype = HCOMPRESS_1; ptr1++; if (*ptr1 == 's' || *ptr1 == 'S') smooth = 1; /* apply smoothing when uncompressing HCOMPRESSed image */ while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } /* ======================== */ /* look for tile dimensions */ /* ======================== */ while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; ii = 0; while (isdigit( (int) *ptr1) && ii < 9) { tilesize[ii] = atol(ptr1); /* read the integer value */ ii++; while (isdigit((int) *ptr1)) /* skip over the integer */ ptr1++; if (*ptr1 == ',') ptr1++; /* skip over the comma */ while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; } /* ========================================================= */ /* look for semi-colon, followed by other optional parameters */ /* ========================================================= */ if (*ptr1 == ';') { ptr1++; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; while (*ptr1 != 0) { /* haven't reached end of string yet */ if (*ptr1 == 's' || *ptr1 == 'S') { /* this should be the HCOMPRESS "scale" parameter; default = 1 */ ptr1++; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; scale = (float) strtod(ptr1, &ptr1); while (*ptr1 == ' ' || *ptr1 == ',') /* skip over blanks or comma */ ptr1++; } else if (*ptr1 == 'q' || *ptr1 == 'Q') { /* this should be the floating point quantization parameter */ ptr1++; if (*ptr1 == 'z' || *ptr1 == 'Z') { /* use the subtractive_dither_2 option */ quantize_method = SUBTRACTIVE_DITHER_2; ptr1++; } else if (*ptr1 == '0') { /* do not dither */ quantize_method = NO_DITHER; ptr1++; } while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; qlevel = (float) strtod(ptr1, &ptr1); while (*ptr1 == ' ' || *ptr1 == ',') /* skip over blanks or comma */ ptr1++; } else { return(*status = URL_PARSE_ERROR); } } } /* ================================= */ /* finished parsing; save the values */ /* ================================= */ fits_set_compression_type(fptr, compresstype, status); fits_set_tile_dim(fptr, MAX_COMPRESS_DIM, tilesize, status); if (compresstype == HCOMPRESS_1) { fits_set_hcomp_scale (fptr, scale, status); fits_set_hcomp_smooth(fptr, smooth, status); } if (qlevel != -99.) { fits_set_quantize_level(fptr, qlevel, status); fits_set_quantize_method(fptr, quantize_method, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffdkinit(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - name of file to create */ int *status) /* IO - error status */ /* Create and initialize a new FITS file on disk. This routine differs from ffinit in that the input 'name' is literally taken as the name of the disk file to be created, and it does not support CFITSIO's extended filename syntax. */ { *fptr = 0; /* initialize null file pointer, */ /* regardless of the value of *status */ if (*status > 0) return(*status); *status = CREATE_DISK_FILE; ffinit(fptr, name,status); return(*status); } /*--------------------------------------------------------------------------*/ int ffinit(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - name of file to create */ int *status) /* IO - error status */ /* Create and initialize a new FITS file. */ { int ii, driver, slen, clobber = 0; char *url; char urltype[MAX_PREFIX_LEN], outfile[FLEN_FILENAME]; char tmplfile[FLEN_FILENAME], compspec[80]; int handle, create_disk_file = 0; *fptr = 0; /* initialize null file pointer, */ /* regardless of the value of *status */ if (*status > 0) return(*status); if (*status == CREATE_DISK_FILE) { create_disk_file = 1; *status = 0; } if (need_to_initialize) { /* this is called only once */ *status = fits_init_cfitsio(); } if (*status > 0) return(*status); url = (char *) name; while (*url == ' ') /* ignore leading spaces in the filename */ url++; if (*url == '\0') { ffpmsg("Name of file to create is blank. (ffinit)"); return(*status = FILE_NOT_CREATED); } if (create_disk_file) { if (strlen(url) > FLEN_FILENAME - 1) { ffpmsg("Filename is too long. (ffinit)"); return(*status = FILE_NOT_CREATED); } strcpy(outfile, url); strcpy(urltype, "file://"); tmplfile[0] = '\0'; compspec[0] = '\0'; } else { /* check for clobber symbol, i.e, overwrite existing file */ if (*url == '!') { clobber = TRUE; url++; } else clobber = FALSE; /* parse the output file specification */ /* this routine checks that the strings will not overflow */ ffourl(url, urltype, outfile, tmplfile, compspec, status); if (*status > 0) { ffpmsg("could not parse the output filename: (ffinit)"); ffpmsg(url); return(*status); } } /* find which driver corresponds to the urltype */ *status = urltype2driver(urltype, &driver); if (*status) { ffpmsg("could not find driver for this file: (ffinit)"); ffpmsg(url); return(*status); } /* delete pre-existing file, if asked to do so */ if (clobber) { if (driverTable[driver].remove) (*driverTable[driver].remove)(outfile); } /* call appropriate driver to create the file */ if (driverTable[driver].create) { FFLOCK; /* lock this while searching for vacant handle */ *status = (*driverTable[driver].create)(outfile, &handle); FFUNLOCK; if (*status) { ffpmsg("failed to create new file (already exists?):"); ffpmsg(url); return(*status); } } else { ffpmsg("cannot create a new file of this type: (ffinit)"); ffpmsg(url); return(*status = FILE_NOT_CREATED); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = strlen(url) + 1; slen = maxvalue(slen, 32); /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffinit)"); ffpmsg(url); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = FILE_NOT_CREATED); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffinit)"); ffpmsg(url); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffinit)"); ffpmsg(url); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* store the file pointer */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ ((*fptr)->Fptr)->filesize = 0; /* physical file size */ ((*fptr)->Fptr)->logfilesize = 0; /* logical file size */ ((*fptr)->Fptr)->writemode = 1; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ((*fptr)->Fptr)->noextsyntax = create_disk_file; /* true if extended syntax is disabled */ ffldrc(*fptr, 0, IGNORE_EOF, status); /* initialize first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ /* if template file was given, use it to define structure of new file */ if (tmplfile[0]) ffoptplt(*fptr, tmplfile, status); /* parse and save image compression specification, if given */ if (compspec[0]) ffparsecompspec(*fptr, compspec, status); return(*status); /* successful return */ } /*--------------------------------------------------------------------------*/ /* ffimem == fits_create_memfile */ int ffimem(fitsfile **fptr, /* O - FITS file pointer */ void **buffptr, /* I - address of memory pointer */ size_t *buffsize, /* I - size of buffer, in bytes */ size_t deltasize, /* I - increment for future realloc's */ void *(*mem_realloc)(void *p, size_t newsize), /* function */ int *status) /* IO - error status */ /* Create and initialize a new FITS file in memory */ { int ii, driver, slen; char urltype[MAX_PREFIX_LEN]; int handle; if (*status > 0) return(*status); *fptr = 0; /* initialize null file pointer */ if (need_to_initialize) { /* this is called only once */ *status = fits_init_cfitsio(); } if (*status > 0) return(*status); strcpy(urltype, "memkeep://"); /* URL type for pre-existing memory file */ *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not find driver for pre-existing memory file: (ffimem)"); return(*status); } /* call driver routine to "open" the memory file */ FFLOCK; /* lock this while searching for vacant handle */ *status = mem_openmem( buffptr, buffsize, deltasize, mem_realloc, &handle); FFUNLOCK; if (*status > 0) { ffpmsg("failed to open pre-existing memory file: (ffimem)"); return(*status); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for memory file: (ffimem)"); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for memory file: (ffimem)"); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = 32; /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffimem)"); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffimem)"); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffimem)"); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* file handle */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, "memfile"); /* dummy filename */ ((*fptr)->Fptr)->filesize = *buffsize; /* physical file size */ ((*fptr)->Fptr)->logfilesize = *buffsize; /* logical file size */ ((*fptr)->Fptr)->writemode = 1; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ((*fptr)->Fptr)->noextsyntax = 0; /* extended syntax can be used in filename */ ffldrc(*fptr, 0, IGNORE_EOF, status); /* initialize first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ return(*status); } /*--------------------------------------------------------------------------*/ int fits_init_cfitsio(void) /* initialize anything that is required before using the CFITSIO routines */ { int status; union u_tag { short ival; char cval[2]; } u; fitsio_init_lock(); FFLOCK; /* lockout other threads while executing this critical */ /* section of code */ if (need_to_initialize == 0) { /* already initialized? */ FFUNLOCK; return(0); } /* test for correct byteswapping. */ u.ival = 1; if ((BYTESWAPPED && u.cval[0] != 1) || (BYTESWAPPED == FALSE && u.cval[1] != 1) ) { printf ("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf(" Byteswapping is not being done correctly on this system.\n"); printf(" Check the MACHINE and BYTESWAPPED definitions in fitsio2.h\n"); printf(" Please report this problem to the CFITSIO developers.\n"); printf( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); FFUNLOCK; return(1); } /* test that LONGLONG is an 8 byte integer */ if (sizeof(LONGLONG) != 8) { printf ("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf(" CFITSIO did not find an 8-byte long integer data type.\n"); printf(" sizeof(LONGLONG) = %d\n",(int)sizeof(LONGLONG)); printf(" Please report this problem to the CFITSIO developers.\n"); printf( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); FFUNLOCK; return(1); } /* register the standard I/O drivers that are always available */ /* 1--------------------disk file driver-----------------------*/ status = fits_register_driver("file://", file_init, file_shutdown, file_setoptions, file_getoptions, file_getversion, file_checkfile, file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the file:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 2------------ output temporary memory file driver ----------------*/ status = fits_register_driver("mem://", mem_init, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* open function not allowed */ mem_create, mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the mem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 3--------------input pre-existing memory file driver----------------*/ status = fits_register_driver("memkeep://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* file open driver function is not used */ NULL, /* create function not allowed */ mem_truncate, mem_close_keep, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the memkeep:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 4-------------------stdin stream driver----------------------*/ /* the stdin stream is copied to memory then opened in memory */ status = fits_register_driver("stdin://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, stdin_checkfile, stdin_open, NULL, /* create function not allowed */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the stdin:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 5-------------------stdin file stream driver----------------------*/ /* the stdin stream is copied to a disk file then the disk file is opened */ status = fits_register_driver("stdinfile://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ stdin_open, NULL, /* create function not allowed */ #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the stdinfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 6-----------------------stdout stream driver------------------*/ status = fits_register_driver("stdout://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* open function not required */ mem_create, mem_truncate, stdout_close, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the stdout:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 7------------------iraf disk file to memory driver -----------*/ status = fits_register_driver("irafmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_iraf_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the irafmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 8------------------raw binary file to memory driver -----------*/ status = fits_register_driver("rawfile://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_rawfile_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the rawfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 9------------------compressed disk file to memory driver -----------*/ status = fits_register_driver("compress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_compress_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the compress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 10------------------compressed disk file to memory driver -----------*/ /* Identical to compress://, except it allows READWRITE access */ status = fits_register_driver("compressmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_compress_openrw, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the compressmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 11------------------compressed disk file to disk file driver -------*/ status = fits_register_driver("compressfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ file_compress_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the compressfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 12---create file in memory, then compress it to disk file on close--*/ status = fits_register_driver("compressoutfile://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* open function not allowed */ mem_create_comp, mem_truncate, mem_close_comp, file_remove, /* delete existing compressed disk file */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg( "failed to register the compressoutfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* Register Optional drivers */ #ifdef HAVE_NET_SERVICES /* 13--------------------root driver-----------------------*/ status = fits_register_driver("root://", root_init, root_shutdown, root_setoptions, root_getoptions, root_getversion, NULL, /* checkfile not needed */ root_open, root_create, NULL, /* No truncate possible */ root_close, NULL, /* No remove possible */ root_size, /* no size possible */ root_flush, root_seek, /* Though will always succeed */ root_read, root_write); if (status) { ffpmsg("failed to register the root:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 14--------------------http driver-----------------------*/ status = fits_register_driver("http://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, http_checkfile, http_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the http:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 15--------------------http file driver-----------------------*/ status = fits_register_driver("httpfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ http_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the httpfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 16--------------------http memory driver-----------------------*/ /* same as http:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("httpmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, http_checkfile, http_file_open, /* this will simply call http_open */ NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the httpmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 17--------------------httpcompress file driver-----------------------*/ status = fits_register_driver("httpcompress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ http_compress_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the httpcompress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 18--------------------ftp driver-----------------------*/ status = fits_register_driver("ftp://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, ftp_checkfile, ftp_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftp:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 19--------------------ftp file driver-----------------------*/ status = fits_register_driver("ftpfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ ftp_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the ftpfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 20--------------------ftp mem driver-----------------------*/ /* same as ftp:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("ftpmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, ftp_checkfile, ftp_file_open, /* this will simply call ftp_open */ NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftpmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 21--------------------ftp compressed file driver------------------*/ status = fits_register_driver("ftpcompress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ ftp_compress_open, 0, /* create function not required */ mem_truncate, mem_close_free, 0, /* remove function not required */ mem_size, 0, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftpcompress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* === End of net drivers section === */ #endif /* ==================== SHARED MEMORY DRIVER SECTION ======================= */ #ifdef HAVE_SHMEM_SERVICES /* 22--------------------shared memory driver-----------------------*/ status = fits_register_driver("shmem://", smem_init, smem_shutdown, smem_setoptions, smem_getoptions, smem_getversion, NULL, /* checkfile not needed */ smem_open, smem_create, NULL, /* truncate file not supported yet */ smem_close, smem_remove, smem_size, smem_flush, smem_seek, smem_read, smem_write ); if (status) { ffpmsg("failed to register the shmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #endif /* ==================== END OF SHARED MEMORY DRIVER SECTION ================ */ #ifdef HAVE_GSIFTP /* 23--------------------gsiftp driver-----------------------*/ status = fits_register_driver("gsiftp://", gsiftp_init, gsiftp_shutdown, gsiftp_setoptions, gsiftp_getoptions, gsiftp_getversion, gsiftp_checkfile, gsiftp_open, gsiftp_create, #ifdef HAVE_FTRUNCATE gsiftp_truncate, #else NULL, #endif gsiftp_close, NULL, /* remove function not yet implemented */ gsiftp_size, gsiftp_flush, gsiftp_seek, gsiftp_read, gsiftp_write); if (status) { ffpmsg("failed to register the gsiftp:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #endif /* 24---------------stdin and stdout stream driver-------------------*/ status = fits_register_driver("stream://", NULL, NULL, NULL, NULL, NULL, NULL, stream_open, stream_create, NULL, /* no stream truncate function */ stream_close, NULL, /* no stream remove */ stream_size, stream_flush, stream_seek, stream_read, stream_write); if (status) { ffpmsg("failed to register the stream:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #ifdef HAVE_NET_SERVICES /* 25--------------------https driver-----------------------*/ status = fits_register_driver("https://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, https_checkfile, https_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the https:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 26--------------------https file driver-----------------------*/ status = fits_register_driver("httpsfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ https_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the httpsfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 27--------------------https memory driver-----------------------*/ /* same as https:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("httpsmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, https_checkfile, https_file_open, /* this will simply call https_open */ NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the httpsmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* === End of https net drivers section === */ /* 28--------------------ftps driver-----------------------*/ status = fits_register_driver("ftps://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, ftps_checkfile, ftps_open, NULL, mem_truncate, mem_close_free, NULL, mem_size, NULL, mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftps:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 29--------------------ftps file driver-----------------------*/ status = fits_register_driver("ftpsfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, ftps_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the ftpsfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 30--------------------ftps memory driver-----------------------*/ /* same as ftps:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("ftpsmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, ftps_checkfile, ftps_file_open, NULL, mem_truncate, mem_close_free, NULL, mem_size, NULL, mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftpsmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 31--------------------ftps compressed file driver------------------*/ status = fits_register_driver("ftpscompress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ ftps_compress_open, 0, /* create function not required */ mem_truncate, mem_close_free, 0, /* remove function not required */ mem_size, 0, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftpscompress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #endif /* reset flag. Any other threads will now not need to call this routine */ need_to_initialize = 0; FFUNLOCK; return(status); } /*--------------------------------------------------------------------------*/ int fits_register_driver(char *prefix, int (*init)(void), int (*shutdown)(void), int (*setoptions)(int option), int (*getoptions)(int *options), int (*getversion)(int *version), int (*checkfile) (char *urltype, char *infile, char *outfile), int (*open)(char *filename, int rwmode, int *driverhandle), int (*create)(char *filename, int *driverhandle), int (*truncate)(int driverhandle, LONGLONG filesize), int (*close)(int driverhandle), int (*fremove)(char *filename), int (*size)(int driverhandle, LONGLONG *sizex), int (*flush)(int driverhandle), int (*seek)(int driverhandle, LONGLONG offset), int (*read) (int driverhandle, void *buffer, long nbytes), int (*write)(int driverhandle, void *buffer, long nbytes) ) /* register all the functions needed to support an I/O driver */ { int status; if (no_of_drivers < 0 ) { /* This is bad. looks like memory has been corrupted. */ ffpmsg("Vital CFITSIO parameters held in memory have been corrupted!!"); ffpmsg("Fatal condition detected in fits_register_driver."); return(TOO_MANY_DRIVERS); } if (no_of_drivers + 1 > MAX_DRIVERS) return(TOO_MANY_DRIVERS); if (prefix == NULL) return(BAD_URL_PREFIX); if (init != NULL) { status = (*init)(); /* initialize the driver */ if (status) return(status); } /* fill in data in table */ strncpy(driverTable[no_of_drivers].prefix, prefix, MAX_PREFIX_LEN); driverTable[no_of_drivers].prefix[MAX_PREFIX_LEN - 1] = 0; driverTable[no_of_drivers].init = init; driverTable[no_of_drivers].shutdown = shutdown; driverTable[no_of_drivers].setoptions = setoptions; driverTable[no_of_drivers].getoptions = getoptions; driverTable[no_of_drivers].getversion = getversion; driverTable[no_of_drivers].checkfile = checkfile; driverTable[no_of_drivers].open = open; driverTable[no_of_drivers].create = create; driverTable[no_of_drivers].truncate = truncate; driverTable[no_of_drivers].close = close; driverTable[no_of_drivers].remove = fremove; driverTable[no_of_drivers].size = size; driverTable[no_of_drivers].flush = flush; driverTable[no_of_drivers].seek = seek; driverTable[no_of_drivers].read = read; driverTable[no_of_drivers].write = write; no_of_drivers++; /* increment the number of drivers */ return(0); } /*--------------------------------------------------------------------------*/ /* fits_parse_input_url */ int ffiurl(char *url, /* input filename */ char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ char *infilex, /* root filename (may be complete path) */ char *outfile, /* optional output file name */ char *extspec, /* extension spec: +n or [extname, extver] */ char *rowfilterx, /* boolean row filter expression */ char *binspec, /* histogram binning specifier */ char *colspec, /* column or keyword modifier expression */ int *status) /* parse the input URL into its basic components. This routine does not support the pixfilter or compspec components. */ { return ffifile2(url, urltype, infilex, outfile, extspec, rowfilterx, binspec, colspec, 0, 0, status); } /*--------------------------------------------------------------------------*/ /* fits_parse_input_file */ int ffifile(char *url, /* input filename */ char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ char *infilex, /* root filename (may be complete path) */ char *outfile, /* optional output file name */ char *extspec, /* extension spec: +n or [extname, extver] */ char *rowfilterx, /* boolean row filter expression */ char *binspec, /* histogram binning specifier */ char *colspec, /* column or keyword modifier expression */ char *pixfilter, /* pixel filter expression */ int *status) /* fits_parse_input_filename parse the input URL into its basic components. This routine does not support the compspec component. */ { return ffifile2(url, urltype, infilex, outfile, extspec, rowfilterx, binspec, colspec, pixfilter, 0, status); } /*--------------------------------------------------------------------------*/ int ffifile2(char *url, /* input filename */ char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ char *infilex, /* root filename (may be complete path) */ char *outfile, /* optional output file name */ char *extspec, /* extension spec: +n or [extname, extver] */ char *rowfilterx, /* boolean row filter expression */ char *binspec, /* histogram binning specifier */ char *colspec, /* column or keyword modifier expression */ char *pixfilter, /* pixel filter expression */ char *compspec, /* image compression specification */ int *status) /* fits_parse_input_filename parse the input URL into its basic components. This routine is big and ugly and should be redesigned someday! */ { int ii, jj, slen, infilelen, plus_ext = 0, collen; char *ptr1, *ptr2, *ptr3, *ptr4, *tmptr; int hasAt, hasDot, hasOper, followingOper, spaceTerm, rowFilter; int colStart, binStart, pixStart, compStart; /* must have temporary variable for these, in case inputs are NULL */ char *infile; char *rowfilter; char *tmpstr; if (*status > 0) return(*status); /* Initialize null strings */ if (infilex) *infilex = '\0'; if (urltype) *urltype = '\0'; if (outfile) *outfile = '\0'; if (extspec) *extspec = '\0'; if (binspec) *binspec = '\0'; if (colspec) *colspec = '\0'; if (rowfilterx) *rowfilterx = '\0'; if (pixfilter) *pixfilter = '\0'; if (compspec) *compspec = '\0'; slen = strlen(url); if (slen == 0) /* blank filename ?? */ return(*status); /* allocate memory for 3 strings, each as long as the input url */ infile = (char *) calloc(3, slen + 1); if (!infile) return(*status = MEMORY_ALLOCATION); rowfilter = &infile[slen + 1]; tmpstr = &rowfilter[slen + 1]; ptr1 = url; /* -------------------------------------------------------- */ /* get urltype (e.g., file://, ftp://, http://, etc.) */ /* --------------------------------------------------------- */ if (*ptr1 == '-' && ( *(ptr1 +1) == 0 || *(ptr1 +1) == ' ' || *(ptr1 +1) == '[' || *(ptr1 +1) == '(' ) ) { /* "-" means read file from stdin. Also support "- ", */ /* "-[extname]" and '-(outfile.fits)" but exclude disk file */ /* names that begin with a minus sign, e.g., "-55d33m.fits" */ if (urltype) strcat(urltype, "stdin://"); ptr1++; } else if (!fits_strncasecmp(ptr1, "stdin", 5)) { if (urltype) strcat(urltype, "stdin://"); ptr1 = ptr1 + 5; } else { ptr2 = strstr(ptr1, "://"); ptr3 = strstr(ptr1, "(" ); if (ptr3 && (ptr3 < ptr2) ) { /* the urltype follows a '(' character, so it must apply */ /* to the output file, and is not the urltype of the input file */ ptr2 = 0; /* so reset pointer to zero */ } if (ptr2) /* copy the explicit urltype string */ { if (ptr2-ptr1+3 >= MAX_PREFIX_LEN) { ffpmsg("Name of urltype is too long."); return(*status = URL_PARSE_ERROR); } if (urltype) strncat(urltype, ptr1, ptr2 - ptr1 + 3); ptr1 = ptr2 + 3; } else if (!strncmp(ptr1, "ftp:", 4) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "ftp://"); ptr1 += 4; } else if (!strncmp(ptr1, "gsiftp:", 7) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "gsiftp://"); ptr1 += 7; } else if (!strncmp(ptr1, "http:", 5) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "http://"); ptr1 += 5; } else if (!strncmp(ptr1, "mem:", 4) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "mem://"); ptr1 += 4; } else if (!strncmp(ptr1, "shmem:", 6) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "shmem://"); ptr1 += 6; } else if (!strncmp(ptr1, "file:", 5) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "file://"); ptr1 += 5; } else /* assume file driver */ { if (urltype) strcat(urltype, "file://"); } } /* ---------------------------------------------------------- If this is a http:// type file, then the cgi file name could include the '[' character, which should not be interpreted as part of CFITSIO's Extended File Name Syntax. Test for this case by seeing if the last character is a ']' or ')'. If it is not, then just treat the whole input string as the file name and do not attempt to interprete the name using the extended filename syntax. ----------------------------------------------------------- */ if (urltype && !strncmp(urltype, "http://", 7) ) { /* test for opening parenthesis or bracket in the file name */ if( strchr(ptr1, '(' ) || strchr(ptr1, '[' ) ) { slen = strlen(ptr1); ptr3 = ptr1 + slen - 1; while (*ptr3 == ' ') /* ignore trailing blanks */ ptr3--; if (*ptr3 != ']' && *ptr3 != ')' ) { /* name doesn't end with a ']' or ')' so don't try */ /* to parse this unusual string (may be cgi string) */ if (infilex) { if (strlen(ptr1) > FLEN_FILENAME - 1) { ffpmsg("Name of file is too long."); return(*status = URL_PARSE_ERROR); } strcpy(infilex, ptr1); } free(infile); return(*status); } } } /* ---------------------------------------------------------- Look for VMS style filenames like: disk:[directory.subdirectory]filename.ext, or [directory.subdirectory]filename.ext Check if the first character is a '[' and urltype != stdin or if there is a ':[' string in the remaining url string. If so, then need to move past this bracket character before search for the opening bracket of a filter specification. ----------------------------------------------------------- */ tmptr = ptr1; if (*ptr1 == '[') { if (*url != '-') tmptr = ptr1 + 1; /* this bracket encloses a VMS directory name */ } else { tmptr = strstr(ptr1, ":["); if (tmptr) /* these 2 chars are part of the VMS disk and directory */ tmptr += 2; else tmptr = ptr1; } /* ------------------------ */ /* get the input file name */ /* ------------------------ */ ptr2 = strchr(tmptr, '('); /* search for opening parenthesis ( */ ptr3 = strchr(tmptr, '['); /* search for opening bracket [ */ if (ptr2) { ptr4 = strchr(ptr2, ')'); /* search for closing parenthesis ) */ while (ptr4 && ptr2) { do { ++ptr4; } while (*ptr4 == ' '); /* find next non-blank char after ')' */ if (*ptr4 == 0 || *ptr4 == '[') break; ptr2 = strchr(ptr2+1, '('); ptr4 = strchr(ptr4, ')'); } } if (ptr2 == ptr3) /* simple case: no [ or ( in the file name */ { strcat(infile, ptr1); } else if (!ptr3 || /* no bracket, so () enclose output file name */ (ptr2 && (ptr2 < ptr3)) ) /* () enclose output name before bracket */ { strncat(infile, ptr1, ptr2 - ptr1); ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) { free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } if (outfile) { if (ptr1 - ptr2 > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncat(outfile, ptr2, ptr1 - ptr2); } /* the opening [ could have been part of output name, */ /* e.g., file(out[compress])[3][#row > 5] */ /* so search again for opening bracket following the closing ) */ ptr3 = strchr(ptr1, '['); } else /* bracket comes first, so there is no output name */ { strncat(infile, ptr1, ptr3 - ptr1); } /* strip off any trailing blanks in the names */ slen = strlen(infile); while ( (--slen) > 0 && infile[slen] == ' ') infile[slen] = '\0'; if (outfile) { slen = strlen(outfile); while ( (--slen) > 0 && outfile[slen] == ' ') outfile[slen] = '\0'; } /* --------------------------------------------- */ /* check if this is an IRAF file (.imh extension */ /* --------------------------------------------- */ ptr4 = strstr(infile, ".imh"); /* did the infile name end with ".imh" ? */ if (ptr4 && (*(ptr4 + 4) == '\0')) { if (urltype) strcpy(urltype, "irafmem://"); } /* --------------------------------------------- */ /* check if the 'filename+n' convention has been */ /* used to specifiy which HDU number to open */ /* --------------------------------------------- */ jj = strlen(infile); for (ii = jj - 1; ii >= 0; ii--) { if (infile[ii] == '+') /* search backwards for '+' sign */ break; } if (ii > 0 && (jj - ii) < 7) /* limit extension numbers to 5 digits */ { infilelen = ii; ii++; ptr1 = infile+ii; /* pointer to start of sequence */ for (; ii < jj; ii++) { if (!isdigit((int) infile[ii] ) ) /* are all the chars digits? */ break; } if (ii == jj) { /* yes, the '+n' convention was used. Copy */ /* the digits to the output extspec string. */ plus_ext = 1; if (extspec) { if (jj - infilelen > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncpy(extspec, ptr1, jj - infilelen); } infile[infilelen] = '\0'; /* delete the extension number */ } } /* -------------------------------------------------------------------- */ /* if '*' was given for the output name expand it to the root file name */ /* -------------------------------------------------------------------- */ if (outfile && outfile[0] == '*') { /* scan input name backwards to the first '/' character */ for (ii = jj - 1; ii >= 0; ii--) { if (infile[ii] == '/' || ii == 0) { if (strlen(&infile[ii + 1]) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(outfile, &infile[ii + 1]); break; } } } /* ------------------------------------------ */ /* copy strings from local copy to the output */ /* ------------------------------------------ */ if (infilex) { if (strlen(infile) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(infilex, infile); } /* ---------------------------------------------------------- */ /* if no '[' character in the input string, then we are done. */ /* ---------------------------------------------------------- */ if (!ptr3) { free(infile); return(*status); } /* ------------------------------------------- */ /* see if [ extension specification ] is given */ /* ------------------------------------------- */ if (!plus_ext) /* extension no. not already specified? Then */ /* first brackets must enclose extension name or # */ /* or it encloses a image subsection specification */ /* or a raw binary image specifier */ /* or a image compression specifier */ /* Or, the extension specification may have been */ /* omitted and we have to guess what the user intended */ { ptr1 = ptr3 + 1; /* pointer to first char after the [ */ ptr2 = strchr(ptr1, ']' ); /* search for closing ] */ if (!ptr2) { ffpmsg("input file URL is missing closing bracket ']'"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } /* ---------------------------------------------- */ /* First, test if this is a rawfile specifier */ /* which looks something like: '[ib512,512:2880]' */ /* Test if first character is b,i,j,d,r,f, or u, */ /* and optional second character is b or l, */ /* followed by one or more digits, */ /* finally followed by a ',', ':', or ']' */ /* ---------------------------------------------- */ if (*ptr1 == 'b' || *ptr1 == 'B' || *ptr1 == 'i' || *ptr1 == 'I' || *ptr1 == 'j' || *ptr1 == 'J' || *ptr1 == 'd' || *ptr1 == 'D' || *ptr1 == 'r' || *ptr1 == 'R' || *ptr1 == 'f' || *ptr1 == 'F' || *ptr1 == 'u' || *ptr1 == 'U') { /* next optional character may be a b or l (for Big or Little) */ ptr1++; if (*ptr1 == 'b' || *ptr1 == 'B' || *ptr1 == 'l' || *ptr1 == 'L') ptr1++; if (isdigit((int) *ptr1)) /* must have at least 1 digit */ { while (isdigit((int) *ptr1)) ptr1++; /* skip over digits */ if (*ptr1 == ',' || *ptr1 == ':' || *ptr1 == ']' ) { /* OK, this looks like a rawfile specifier */ if (urltype) { if (strstr(urltype, "stdin") ) strcpy(urltype, "rawstdin://"); else strcpy(urltype, "rawfile://"); } /* append the raw array specifier to infilex */ if (infilex) { if (strlen(infilex) + strlen(ptr3) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcat(infilex, ptr3); ptr1 = strchr(infilex, ']'); /* find the closing ] char */ if (ptr1) *(ptr1 + 1) = '\0'; /* terminate string after the ] */ } if (extspec) strcpy(extspec, "0"); /* the 0 ext number is implicit */ tmptr = strchr(ptr2 + 1, '[' ); /* search for another [ char */ /* copy any remaining characters into rowfilterx */ if (tmptr && rowfilterx) { if (strlen(rowfilterx) + strlen(tmptr + 1) > FLEN_FILENAME -1) { free(infile); return(*status = URL_PARSE_ERROR); } strcat(rowfilterx, tmptr + 1); tmptr = strchr(rowfilterx, ']' ); /* search for closing ] */ if (tmptr) *tmptr = '\0'; /* overwrite the ] with null terminator */ } free(infile); /* finished parsing, so return */ return(*status); } } } /* end of rawfile specifier test */ /* -------------------------------------------------------- */ /* Not a rawfile, so next, test if this is an image section */ /* i.e., an integer followed by a ':' or a '*' or '-*' */ /* -------------------------------------------------------- */ ptr1 = ptr3 + 1; /* reset pointer to first char after the [ */ tmptr = ptr1; while (*tmptr == ' ') tmptr++; /* skip leading blanks */ while (isdigit((int) *tmptr)) tmptr++; /* skip over leading digits */ if (*tmptr == ':' || *tmptr == '*' || *tmptr == '-') { /* this is an image section specifier */ strcat(rowfilter, ptr3); /* don't want to assume 0 extension any more; may imply an image extension. if (extspec) strcpy(extspec, "0"); */ } else { /* ----------------------------------------------------------------- Not an image section or rawfile spec so may be an extension spec. Examples of valid extension specifiers: [3] - 3rd extension; 0 = primary array [events] - events extension [events, 2] - events extension, with EXTVER = 2 [events,2] - spaces are optional [events, 3, b] - same as above, plus XTENSION = 'BINTABLE' [PICS; colName(12)] - an image in row 12 of the colName column in the PICS table extension [PICS; colName(exposure > 1000)] - as above, but find image in first row with with exposure column value > 1000. [Rate Table] - extension name can contain spaces! [Rate Table;colName(exposure>1000)] Examples of other types of specifiers (Not extension specifiers) [bin] !!! this is ambiguous, and can't be distinguished from a valid extension specifier [bini X=1:512:16] (also binb, binj, binr, and bind are allowed) [binr (X,Y) = 5] [bin @binfilter.txt] [col Time;rate] [col PI=PHA * 1.1] [col -Time; status] [X > 5] [X>5] [@filter.txt] [StatusCol] !!! this is ambiguous, and can't be distinguished from a valid extension specifier [StatusCol==0] [StatusCol || x>6] [gtifilter()] [regfilter("region.reg")] [compress Rice] There will always be some ambiguity between an extension name and a boolean row filtering expression, (as in a couple of the above examples). If there is any doubt, the expression should be treated as an extension specification; The user can always add an explicit expression specifier to override this interpretation. The following decision logic will be used: 1) locate the first token, terminated with a space, comma, semi-colon, or closing bracket. 2) the token is not part of an extension specifier if any of the following is true: - if the token begins with '@' and contains a '.' - if the token contains an operator: = > < || && - if the token begins with "gtifilter(" or "regfilter(" - if the token is terminated by a space and is followed by additional characters (not a ']') AND any of the following: - the token is 'col' - the token is 3 or 4 chars long and begins with 'bin' - the second token begins with an operator: ! = < > | & + - * / % 3) otherwise, the string is assumed to be an extension specifier ----------------------------------------------------------------- */ tmptr = ptr1; while(*tmptr == ' ') tmptr++; hasAt = 0; hasDot = 0; hasOper = 0; followingOper = 0; spaceTerm = 0; rowFilter = 0; colStart = 0; binStart = 0; pixStart = 0; compStart = 0; if (*tmptr == '@') /* test for leading @ symbol */ hasAt = 1; if ( !fits_strncasecmp(tmptr, "col ", 4) ) colStart = 1; if ( !fits_strncasecmp(tmptr, "bin", 3) ) binStart = 1; if ( !fits_strncasecmp(tmptr, "pix", 3) ) pixStart = 1; if ( !fits_strncasecmp(tmptr, "compress ", 9) || !fits_strncasecmp(tmptr, "compress]", 9) ) compStart = 1; if ( !fits_strncasecmp(tmptr, "gtifilter(", 10) || !fits_strncasecmp(tmptr, "regfilter(", 10) ) { rowFilter = 1; } else { /* parse the first token of the expression */ for (ii = 0; ii < ptr2 - ptr1 + 1; ii++, tmptr++) { if (*tmptr == '.') hasDot = 1; else if (*tmptr == '=' || *tmptr == '>' || *tmptr == '<' || (*tmptr == '|' && *(tmptr+1) == '|') || (*tmptr == '&' && *(tmptr+1) == '&') ) hasOper = 1; else if (*tmptr == ',' || *tmptr == ';' || *tmptr == ']') { break; } else if (*tmptr == ' ') /* a space char? */ { while(*tmptr == ' ') /* skip spaces */ tmptr++; if (*tmptr == ']') /* is this the end? */ break; spaceTerm = 1; /* 1st token is terminated by space */ /* test if this is a column or binning specifier */ if (colStart || (ii <= 4 && (binStart || pixStart)) ) rowFilter = 1; else { /* check if next character is an operator */ if (*tmptr == '=' || *tmptr == '>' || *tmptr == '<' || *tmptr == '|' || *tmptr == '&' || *tmptr == '!' || *tmptr == '+' || *tmptr == '-' || *tmptr == '*' || *tmptr == '/' || *tmptr == '%') followingOper = 1; } break; } } } /* test if this is NOT an extension specifier */ if ( rowFilter || (pixStart && spaceTerm) || (hasAt && hasDot) || hasOper || compStart || (spaceTerm && followingOper) ) { /* this is (probably) not an extension specifier */ /* so copy all chars to filter spec string */ strcat(rowfilter, ptr3); } else { /* this appears to be a legit extension specifier */ /* copy the extension specification */ if (extspec) { if (ptr2 - ptr1 > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncat(extspec, ptr1, ptr2 - ptr1); } /* copy any remaining chars to filter spec string */ strcat(rowfilter, ptr2 + 1); } } } /* end of if (!plus_ext) */ else { /* ------------------------------------------------------------------ */ /* already have extension, so this must be a filter spec of some sort */ /* ------------------------------------------------------------------ */ strcat(rowfilter, ptr3); } /* strip off any trailing blanks from filter */ slen = strlen(rowfilter); while ( (--slen) >= 0 && rowfilter[slen] == ' ') rowfilter[slen] = '\0'; if (!rowfilter[0]) { free(infile); return(*status); /* nothing left to parse */ } /* ------------------------------------------------ */ /* does the filter contain a binning specification? */ /* ------------------------------------------------ */ ptr1 = strstr(rowfilter, "[bin"); /* search for "[bin" */ if (!ptr1) ptr1 = strstr(rowfilter, "[BIN"); /* search for "[BIN" */ if (!ptr1) ptr1 = strstr(rowfilter, "[Bin"); /* search for "[Bin" */ if (ptr1) { ptr2 = ptr1 + 4; /* end of the '[bin' string */ if (*ptr2 == 'b' || *ptr2 == 'i' || *ptr2 == 'j' || *ptr2 == 'r' || *ptr2 == 'd') ptr2++; /* skip the datatype code letter */ if ( *ptr2 != ' ' && *ptr2 != ']') ptr1 = NULL; /* bin string must be followed by space or ] */ } if (ptr1) { /* found the binning string */ if (binspec) { if (strlen(ptr1 +1) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(binspec, ptr1 + 1); ptr2 = fits_find_match_delim(binspec, ']'); if (ptr2) /* terminate the binning filter */ { --ptr2; /* points beyond delimeter, so rewind by 1 */ *ptr2 = '\0'; if ( *(--ptr2) == ' ') /* delete trailing spaces */ *ptr2 = '\0'; } else { ffpmsg("input file URL is missing closing bracket ']'"); ffpmsg(rowfilter); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } /* delete the binning spec from the row filter string */ ptr2 = fits_find_match_delim(ptr1+1, ']'); if (ptr2) { strcpy(tmpstr, ptr2); /* copy any chars after the binspec */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } else { ffpmsg("input file URL is missing closing bracket ']'"); ffpmsg(rowfilter); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } /* --------------------------------------------------------- */ /* does the filter contain a column selection specification? */ /* --------------------------------------------------------- */ ptr1 = strstr(rowfilter, "[col "); if (!ptr1) { ptr1 = strstr(rowfilter, "[COL "); if (!ptr1) ptr1 = strstr(rowfilter, "[Col "); } hasAt = 0; while (ptr1) { /* find the end of the column specifier */ ptr2 = ptr1 + 5; /* Scan past any whitespace and check for @filename */ while (*ptr2 == ' ') ptr2++; if (*ptr2 == '@') hasAt = 1; while (*ptr2 != ']') { if (*ptr2 == '\0') { ffpmsg("input file URL is missing closing bracket ']'"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } if (*ptr2 == '\'') /* start of a literal string */ { ptr2 = strchr(ptr2 + 1, '\''); /* find closing quote */ if (!ptr2) { ffpmsg ("literal string in input file URL is missing closing single quote"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } if (*ptr2 == '[') /* set of nested square brackets */ { ptr2 = strchr(ptr2 + 1, ']'); /* find closing bracket */ if (!ptr2) { ffpmsg ("nested brackets in input file URL is missing closing bracket"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } ptr2++; /* continue search for the closing bracket character */ } collen = ptr2 - ptr1 - 1; if (colspec) { /* copy the column specifier to output string */ if (collen + strlen(colspec) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } if (*colspec == 0) { strncpy(colspec, ptr1 + 1, collen); colspec[collen] = '\0'; } else { /* Pre-existing colspec, append with ";" */ strcat(colspec, ";"); strncat(colspec, ptr1 + 5, collen-4); /* Note that strncat always null-terminates the destination string */ /* Special error checking here. We can't allow there to be a col @filename.txt includes if there are multiple col expressions */ if (hasAt) { ffpmsg("input URL multiple column filter cannot use @filename.txt"); free(infile); return(*status = URL_PARSE_ERROR); } } collen = strlen(colspec); while (colspec[--collen] == ' ') colspec[collen] = '\0'; /* strip trailing blanks */ } /* delete the column selection spec from the row filter string */ strcpy(tmpstr, ptr2 + 1); /* copy any chars after the colspec */ strcpy(ptr1, tmpstr); /* overwrite binspec */ /* Check for additional column specifiers */ ptr1 = strstr(rowfilter, "[col "); if (!ptr1) ptr1 = strstr(rowfilter, "[COL "); if (!ptr1) ptr1 = strstr(rowfilter, "[Col "); } /* --------------------------------------------------------- */ /* does the filter contain a pixel filter specification? */ /* --------------------------------------------------------- */ ptr1 = strstr(rowfilter, "[pix"); if (!ptr1) { ptr1 = strstr(rowfilter, "[PIX"); if (!ptr1) ptr1 = strstr(rowfilter, "[Pix"); } if (ptr1) { ptr2 = ptr1 + 4; /* end of the '[pix' string */ if (*ptr2 == 'b' || *ptr2 == 'i' || *ptr2 == 'j' || *ptr2 == 'B' || *ptr2 == 'I' || *ptr2 == 'J' || *ptr2 == 'r' || *ptr2 == 'd' || *ptr2 == 'R' || *ptr2 == 'D') ptr2++; /* skip the datatype code letter */ if (*ptr2 == '1') ptr2++; /* skip the single HDU indicator */ if ( *ptr2 != ' ') ptr1 = NULL; /* pix string must be followed by space */ } if (ptr1) { /* find the end of the pixel filter */ while (*ptr2 != ']') { if (*ptr2 == '\0') { ffpmsg("input file URL is missing closing bracket ']'"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } if (*ptr2 == '\'') /* start of a literal string */ { ptr2 = strchr(ptr2 + 1, '\''); /* find closing quote */ if (!ptr2) { ffpmsg ("literal string in input file URL is missing closing single quote"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } if (*ptr2 == '[') /* set of nested square brackets */ { ptr2 = strchr(ptr2 + 1, ']'); /* find closing bracket */ if (!ptr2) { ffpmsg ("nested brackets in input file URL is missing closing bracket"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } ptr2++; /* continue search for the closing bracket character */ } collen = ptr2 - ptr1 - 1; if (pixfilter) /* copy the column specifier to output string */ { if (collen > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncpy(pixfilter, ptr1 + 1, collen); pixfilter[collen] = '\0'; while (pixfilter[--collen] == ' ') pixfilter[collen] = '\0'; /* strip trailing blanks */ } /* delete the pixel filter from the row filter string */ strcpy(tmpstr, ptr2 + 1); /* copy any chars after the pixel filter */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } /* ------------------------------------------------------------ */ /* does the filter contain an image compression specification? */ /* ------------------------------------------------------------ */ ptr1 = strstr(rowfilter, "[compress"); if (ptr1) { ptr2 = ptr1 + 9; /* end of the '[compress' string */ if ( *ptr2 != ' ' && *ptr2 != ']') ptr1 = NULL; /* compress string must be followed by space or ] */ } if (ptr1) { /* found the compress string */ if (compspec) { if (strlen(ptr1 +1) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(compspec, ptr1 + 1); ptr2 = strchr(compspec, ']'); if (ptr2) /* terminate the binning filter */ { *ptr2 = '\0'; if ( *(--ptr2) == ' ') /* delete trailing spaces */ *ptr2 = '\0'; } else { ffpmsg("input file URL is missing closing bracket ']'"); ffpmsg(rowfilter); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } /* delete the compression spec from the row filter string */ ptr2 = strchr(ptr1, ']'); strcpy(tmpstr, ptr2+1); /* copy any chars after the binspec */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } /* copy the remaining string to the rowfilter output... should only */ /* contain a rowfilter expression of the form "[expr]" */ if (rowfilterx && rowfilter[0]) { hasAt = 0; /* Check for multiple expressions, which would appear as "[expr][expr]..." */ ptr1 = rowfilter; while((*ptr1 == '[') && (ptr2 = strstr(rowfilter,"]["))-ptr1 > 2) { /* Advance past any white space */ ptr3 = ptr1+1; while (*ptr3 == ' ') ptr3++; /* Check for @filename.txt */ if (*ptr3 == '@') hasAt = 1; /* Add expression of the form "((expr))&&", note the addition of 6 characters */ if ((strlen(rowfilterx) + (ptr2-ptr1) + 6) > FLEN_FILENAME - 1) { free(infile); return (*status = URL_PARSE_ERROR); } /* Special error checking here. We can't allow there to be a @filename.txt includes if there are multiple row expressions */ if (*rowfilterx && hasAt) { ffpmsg("input URL multiple row filter cannot use @filename.txt"); free(infile); return(*status = URL_PARSE_ERROR); } /* Append the expression */ strcat(rowfilterx, "(("); strncat(rowfilterx, ptr1+1, (ptr2-ptr1-1)); /* Note that strncat always null-terminates the destination string */ strcat(rowfilterx, "))&&"); /* Advance to next expression */ ptr1 = ptr2 + 1; } /* At final iteration, ptr1 points to beginning [ and ptr2 to ending ] */ ptr2 = rowfilter + strlen(rowfilter) - 1; if( *ptr1=='[' && *ptr2==']' ) { /* Check for @include in final position */ ptr3 = ptr1 + 1; while (*ptr3 == ' ') ptr3++; if (*ptr3 == '@') hasAt = 1; /* Check for overflow; add extra 4 characters if we have pre-existing expression */ if (strlen(rowfilterx) + (ptr2-ptr1 + (*rowfilterx)?4:0) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } /* Special error checking here. We can't allow there to be a @filename.txt includes if there are multiple row expressions */ if (*rowfilterx && hasAt) { ffpmsg("input URL multiple row filter cannot use @filename.txt"); free(infile); return(*status = URL_PARSE_ERROR); } if (*rowfilterx) { /* A pre-existing row filter: we bracket by ((expr)) to be sure */ strcat(rowfilterx, "(("); strncat(rowfilterx, ptr1+1, (ptr2-ptr1-1)); strcat(rowfilterx, "))"); } else { /* We have only one filter, so just copy the expression alone. This will be the most typical case */ strncat(rowfilterx, ptr1+1, (ptr2-ptr1-1)); } } else { ffpmsg("input file URL lacks valid row filter expression"); *status = URL_PARSE_ERROR; } } free(infile); return(*status); } /*--------------------------------------------------------------------------*/ int ffexist(const char *infile, /* I - input filename or URL */ int *exists, /* O - 2 = a compressed version of file exists */ /* 1 = yes, disk file exists */ /* 0 = no, disk file could not be found */ /* -1 = infile is not a disk file (could */ /* be a http, ftp, gsiftp, smem, or stdin file) */ int *status) /* I/O status */ /* test if the input file specifier is an existing file on disk If the specified file can't be found, it then searches for a compressed version of the file. */ { FILE *diskfile; char rootname[FLEN_FILENAME]; char *ptr1; if (*status > 0) return(*status); /* strip off any extname or filters from the name */ ffrtnm( (char *)infile, rootname, status); ptr1 = strstr(rootname, "://"); if (ptr1 || *rootname == '-') { if (!strncmp(rootname, "file", 4) ) { ptr1 = ptr1 + 3; /* pointer to start of the disk file name */ } else { *exists = -1; /* this is not a disk file */ return (*status); } } else { ptr1 = rootname; } /* see if the disk file exists */ if (file_openfile(ptr1, 0, &diskfile)) { /* no, couldn't open file, so see if there is a compressed version */ if (file_is_compressed(ptr1) ) { *exists = 2; /* a compressed version of the file exists */ } else { *exists = 0; /* neither file nor compressed version exist */ } } else { /* yes, file exists */ *exists = 1; fclose(diskfile); } return(*status); } /*--------------------------------------------------------------------------*/ int ffrtnm(char *url, char *rootname, int *status) /* parse the input URL, returning the root name (filetype://basename). */ { int ii, jj, slen, infilelen; char *ptr1, *ptr2, *ptr3, *ptr4; char urltype[MAX_PREFIX_LEN]; char infile[FLEN_FILENAME]; if (*status > 0) return(*status); ptr1 = url; *rootname = '\0'; *urltype = '\0'; *infile = '\0'; /* get urltype (e.g., file://, ftp://, http://, etc.) */ if (*ptr1 == '-') /* "-" means read file from stdin */ { strcat(urltype, "-"); ptr1++; } else if (!strncmp(ptr1, "stdin", 5) || !strncmp(ptr1, "STDIN", 5)) { strcat(urltype, "-"); ptr1 = ptr1 + 5; } else { ptr2 = strstr(ptr1, "://"); ptr3 = strstr(ptr1, "(" ); if (ptr3 && (ptr3 < ptr2) ) { /* the urltype follows a '(' character, so it must apply */ /* to the output file, and is not the urltype of the input file */ ptr2 = 0; /* so reset pointer to zero */ } if (ptr2) /* copy the explicit urltype string */ { if (ptr2 - ptr1 + 3 > MAX_PREFIX_LEN - 1) { return(*status = URL_PARSE_ERROR); } strncat(urltype, ptr1, ptr2 - ptr1 + 3); ptr1 = ptr2 + 3; } else if (!strncmp(ptr1, "ftp:", 4) ) { /* the 2 //'s are optional */ strcat(urltype, "ftp://"); ptr1 += 4; } else if (!strncmp(ptr1, "gsiftp:", 7) ) { /* the 2 //'s are optional */ strcat(urltype, "gsiftp://"); ptr1 += 7; } else if (!strncmp(ptr1, "http:", 5) ) { /* the 2 //'s are optional */ strcat(urltype, "http://"); ptr1 += 5; } else if (!strncmp(ptr1, "mem:", 4) ) { /* the 2 //'s are optional */ strcat(urltype, "mem://"); ptr1 += 4; } else if (!strncmp(ptr1, "shmem:", 6) ) { /* the 2 //'s are optional */ strcat(urltype, "shmem://"); ptr1 += 6; } else if (!strncmp(ptr1, "file:", 5) ) { /* the 2 //'s are optional */ ptr1 += 5; } /* else assume file driver */ } /* get the input file name */ ptr2 = strchr(ptr1, '('); /* search for opening parenthesis ( */ ptr3 = strchr(ptr1, '['); /* search for opening bracket [ */ if (ptr2) { ptr4 = strchr(ptr2, ')'); while (ptr4 && ptr2) { do { ++ptr4; } while (*ptr4 == ' '); if (*ptr4 == 0 || *ptr4 == '[') break; ptr2 = strchr(ptr2+1, '('); ptr4 = strchr(ptr4, ')'); } } if (ptr2 == ptr3) /* simple case: no [ or ( in the file name */ { if (strlen(ptr1) > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strcat(infile, ptr1); } else if (!ptr3) /* no bracket, so () enclose output file name */ { if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(infile, ptr1, ptr2 - ptr1); ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } else if (ptr2 && (ptr2 < ptr3)) /* () enclose output name before bracket */ { if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(infile, ptr1, ptr2 - ptr1); ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } else /* bracket comes first, so there is no output name */ { if (ptr3 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(infile, ptr1, ptr3 - ptr1); } /* strip off any trailing blanks in the names */ slen = strlen(infile); for (ii = slen - 1; ii > 0; ii--) { if (infile[ii] == ' ') infile[ii] = '\0'; else break; } /* --------------------------------------------- */ /* check if the 'filename+n' convention has been */ /* used to specifiy which HDU number to open */ /* --------------------------------------------- */ jj = strlen(infile); for (ii = jj - 1; ii >= 0; ii--) { if (infile[ii] == '+') /* search backwards for '+' sign */ break; } if (ii > 0 && (jj - ii) < 5) /* limit extension numbers to 4 digits */ { infilelen = ii; ii++; for (; ii < jj; ii++) { if (!isdigit((int) infile[ii] ) ) /* are all the chars digits? */ break; } if (ii == jj) { /* yes, the '+n' convention was used. */ infile[infilelen] = '\0'; /* delete the extension number */ } } if (strlen(urltype) + strlen(infile) > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strcat(rootname, urltype); /* construct the root name */ strcat(rootname, infile); return(*status); } /*--------------------------------------------------------------------------*/ int ffourl(char *url, /* I - full input URL */ char *urltype, /* O - url type */ char *outfile, /* O - base file name */ char *tpltfile, /* O - template file name, if any */ char *compspec, /* O - compression specification, if any */ int *status) /* parse the output URL into its basic components. */ { char *ptr1, *ptr2, *ptr3; if (*status > 0) return(*status); if (urltype) *urltype = '\0'; if (outfile) *outfile = '\0'; if (tpltfile) *tpltfile = '\0'; if (compspec) *compspec = '\0'; ptr1 = url; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; if ( ( (*ptr1 == '-') && ( *(ptr1 +1) == 0 || *(ptr1 +1) == ' ' ) ) || !strcmp(ptr1, "stdout") || !strcmp(ptr1, "STDOUT")) /* "-" means write to stdout; also support "- " */ /* but exclude disk file names that begin with a minus sign */ /* e.g., "-55d33m.fits" */ { if (urltype) strcpy(urltype, "stdout://"); } else { /* not writing to stdout */ /* get urltype (e.g., file://, ftp://, http://, etc.) */ ptr2 = strstr(ptr1, "://"); if (ptr2) /* copy the explicit urltype string */ { if (urltype) { if (ptr2 - ptr1 + 3 > MAX_PREFIX_LEN - 1) { return(*status = URL_PARSE_ERROR); } strncat(urltype, ptr1, ptr2 - ptr1 + 3); } ptr1 = ptr2 + 3; } else /* assume file driver */ { if (urltype) strcat(urltype, "file://"); } /* look for template file name, enclosed in parenthesis */ ptr2 = strchr(ptr1, '('); /* look for image compression parameters, enclosed in sq. brackets */ ptr3 = strchr(ptr1, '['); if (outfile) { if (ptr2) { /* template file was specified */ if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(outfile, ptr1, ptr2 - ptr1); } else if (ptr3) { /* compression was specified */ if (ptr3 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(outfile, ptr1, ptr3 - ptr1); } else { /* no template file or compression */ if (strlen(ptr1) > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strcpy(outfile, ptr1); } } if (ptr2) /* template file was specified */ { ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) { return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } if (tpltfile) { if (ptr1 - ptr2 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(tpltfile, ptr2, ptr1 - ptr2); } } if (ptr3) /* compression was specified */ { ptr3++; ptr1 = strchr(ptr3, ']' ); /* search for closing ] */ if (!ptr1) { return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } if (compspec) { if (ptr1 - ptr3 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(compspec, ptr3, ptr1 - ptr3); } } /* check if a .gz compressed output file is to be created */ /* by seeing if the filename ends in '.gz' */ if (urltype && outfile) { if (!strcmp(urltype, "file://") ) { ptr1 = strstr(outfile, ".gz"); if (ptr1) { /* make sure the ".gz" is at the end of the file name */ ptr1 += 3; if (*ptr1 == 0 || *ptr1 == ' ' ) strcpy(urltype, "compressoutfile://"); } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffexts(char *extspec, int *extnum, char *extname, int *extvers, int *hdutype, char *imagecolname, char *rowexpress, int *status) { /* Parse the input extension specification string, returning either the extension number or the values of the EXTNAME, EXTVERS, and XTENSION keywords in desired extension. Also return the name of the column containing an image, and an expression to be used to determine which row to use, if present. */ char *ptr1, *ptr2; int slen, nvals; int notint = 1; /* initially assume specified extname is not an integer */ char tmpname[FLEN_VALUE], *loc; *extnum = 0; *extname = '\0'; *extvers = 0; *hdutype = ANY_HDU; *imagecolname = '\0'; *rowexpress = '\0'; if (*status > 0) return(*status); ptr1 = extspec; /* pointer to first char */ while (*ptr1 == ' ') /* skip over any leading blanks */ ptr1++; if (isdigit((int) *ptr1)) /* is the extension specification a number? */ { notint = 0; /* looks like extname may actually be the ext. number */ errno = 0; /* reset this prior to calling strtol */ *extnum = strtol(ptr1, &loc, 10); /* read the string as an integer */ while (*loc == ' ') /* skip over trailing blanks */ loc++; /* check for read error, or junk following the integer */ if ((*loc != '\0' && *loc != ';' ) || (errno == ERANGE) ) { *extnum = 0; notint = 1; /* no, extname was not a simple integer after all */ errno = 0; /* reset error condition flag if it was set */ } if ( *extnum < 0 || *extnum > 99999) { *extnum = 0; /* this is not a reasonable extension number */ ffpmsg("specified extension number is out of range:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } } /* This logic was too simple, and failed on extnames like '1000TEMP' where it would try to move to the 1000th extension if (isdigit((int) *ptr1)) { sscanf(ptr1, "%d", extnum); if (*extnum < 0 || *extnum > 9999) { *extnum = 0; ffpmsg("specified extension number is out of range:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } } */ if (notint) { /* not a number, so EXTNAME must be specified, followed by */ /* optional EXTVERS and XTENSION values */ /* don't use space char as end indicator, because there */ /* may be imbedded spaces in the EXTNAME value */ slen = strcspn(ptr1, ",:;"); /* length of EXTNAME */ if (slen > FLEN_VALUE - 1) { return(*status = URL_PARSE_ERROR); } strncat(extname, ptr1, slen); /* EXTNAME value */ /* now remove any trailing blanks */ while (slen > 0 && *(extname + slen -1) == ' ') { *(extname + slen -1) = '\0'; slen--; } ptr1 += slen; slen = strspn(ptr1, " ,:"); /* skip delimiter characters */ ptr1 += slen; slen = strcspn(ptr1, " ,:;"); /* length of EXTVERS */ if (slen) { nvals = sscanf(ptr1, "%d", extvers); /* EXTVERS value */ if (nvals != 1) { ffpmsg("illegal EXTVER value in input URL:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } ptr1 += slen; slen = strspn(ptr1, " ,:"); /* skip delimiter characters */ ptr1 += slen; slen = strcspn(ptr1, ";"); /* length of HDUTYPE */ if (slen) { if (*ptr1 == 'b' || *ptr1 == 'B') *hdutype = BINARY_TBL; else if (*ptr1 == 't' || *ptr1 == 'T' || *ptr1 == 'a' || *ptr1 == 'A') *hdutype = ASCII_TBL; else if (*ptr1 == 'i' || *ptr1 == 'I') *hdutype = IMAGE_HDU; else { ffpmsg("unknown type of HDU in input URL:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } } } else { strcpy(tmpname, extname); ffupch(tmpname); if (!strcmp(tmpname, "PRIMARY") || !strcmp(tmpname, "P") ) *extname = '\0'; /* return extnum = 0 */ } } ptr1 = strchr(ptr1, ';'); if (ptr1) { /* an image is to be opened; the image is contained in a single */ /* cell of a binary table. A column name and an expression to */ /* determine which row to use has been entered. */ ptr1++; /* skip over the ';' delimiter */ while (*ptr1 == ' ') /* skip over any leading blanks */ ptr1++; ptr2 = strchr(ptr1, '('); if (!ptr2) { ffpmsg("illegal specification of image in table cell in input URL:"); ffpmsg(" did not find a row expression enclosed in ( )"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(imagecolname, ptr1, ptr2 - ptr1); /* copy column name */ ptr2++; /* skip over the '(' delimiter */ while (*ptr2 == ' ') /* skip over any leading blanks */ ptr2++; ptr1 = strchr(ptr2, ')'); if (!ptr1) { ffpmsg("illegal specification of image in table cell in input URL:"); ffpmsg(" missing closing ')' character in row expression"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } if (ptr1 - ptr2 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(rowexpress, ptr2, ptr1 - ptr2); /* row expression */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffextn(char *url, /* I - input filename/URL */ int *extension_num, /* O - returned extension number */ int *status) { /* Parse the input url string and return the number of the extension that CFITSIO would automatically move to if CFITSIO were to open this input URL. The extension numbers are one's based, so 1 = the primary array, 2 = the first extension, etc. The extension number that gets returned is determined by the following algorithm: 1. If the input URL includes a binning specification (e.g. 'myfile.fits[3][bin X,Y]') then the returned extension number will always = 1, since CFITSIO would create a temporary primary image on the fly in this case. The same is true if an image within a single cell of a binary table is opened. 2. Else if the input URL specifies an extension number (e.g., 'myfile.fits[3]' or 'myfile.fits+3') then the specified extension number (+ 1) is returned. 3. Else if the extension name is specified in brackets (e.g., this 'myfile.fits[EVENTS]') then the file will be opened and searched for the extension number. If the input URL is '-' (reading from the stdin file stream) this is not possible and an error will be returned. 4. Else if the URL does not specify an extension (e.g. 'myfile.fits') then a special extension number = -99 will be returned to signal that no extension was specified. This feature is mainly for compatibility with existing FTOOLS software. CFITSIO would open the primary array by default (extension_num = 1) in this case. */ fitsfile *fptr; char urltype[20]; char infile[FLEN_FILENAME]; char outfile[FLEN_FILENAME]; char extspec[FLEN_FILENAME]; char extname[FLEN_FILENAME]; char rowfilter[FLEN_FILENAME]; char binspec[FLEN_FILENAME]; char colspec[FLEN_FILENAME]; char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; char *cptr; int extnum, extvers, hdutype, tstatus = 0; if (*status > 0) return(*status); /* parse the input URL into its basic components */ fits_parse_input_url(url, urltype, infile, outfile, extspec, rowfilter,binspec, colspec, status); if (*status > 0) return(*status); if (*binspec) /* is there a binning specification? */ { *extension_num = 1; /* a temporary primary array image is created */ return(*status); } if (*extspec) /* is an extension specified? */ { ffexts(extspec, &extnum, extname, &extvers, &hdutype, imagecolname, rowexpress, status); if (*status > 0) return(*status); if (*imagecolname) /* is an image within a table cell being opened? */ { *extension_num = 1; /* a temporary primary array image is created */ return(*status); } if (*extname) { /* have to open the file to search for the extension name (curses!) */ if (!strcmp(urltype, "stdin://")) /* opening stdin would destroying it! */ return(*status = URL_PARSE_ERROR); /* First, strip off any filtering specification */ infile[0] = '\0'; strncat(infile, url, FLEN_FILENAME -1); cptr = strchr(infile, ']'); /* locate the closing bracket */ if (!cptr) { return(*status = URL_PARSE_ERROR); } else { cptr++; *cptr = '\0'; /* terminate URl after the extension spec */ } if (ffopen(&fptr, infile, READONLY, status) > 0) /* open the file */ { ffclos(fptr, &tstatus); return(*status); } ffghdn(fptr, &extnum); /* where am I in the file? */ *extension_num = extnum; ffclos(fptr, status); return(*status); } else { *extension_num = extnum + 1; /* return the specified number (+ 1) */ return(*status); } } else { *extension_num = -99; /* no specific extension was specified */ /* defaults to primary array */ return(*status); } } /*--------------------------------------------------------------------------*/ int ffurlt(fitsfile *fptr, char *urlType, int *status) /* return the prefix string associated with the driver in use by the fitsfile pointer fptr */ { strcpy(urlType, driverTable[fptr->Fptr->driver].prefix); return(*status); } /*--------------------------------------------------------------------------*/ int ffimport_file( char *filename, /* Text file to read */ char **contents, /* Pointer to pointer to hold file */ int *status ) /* CFITSIO error code */ /* Read and concatenate all the lines from the given text file. User must free the pointer returned in contents. Pointer is guaranteed to hold 2 characters more than the length of the text... allows the calling routine to append (or prepend) a newline (or quotes?) without reallocating memory. */ { int allocLen, totalLen, llen, eoline = 1; char *lines,line[256]; FILE *aFile; if( *status > 0 ) return( *status ); totalLen = 0; allocLen = 1024; lines = (char *)malloc( allocLen * sizeof(char) ); if( !lines ) { ffpmsg("Couldn't allocate memory to hold ASCII file contents."); return(*status = MEMORY_ALLOCATION ); } lines[0] = '\0'; if( (aFile = fopen( filename, "r" ))==NULL ) { snprintf(line,256,"Could not open ASCII file %s.",filename); ffpmsg(line); free( lines ); return(*status = FILE_NOT_OPENED); } while( fgets(line,256,aFile)!=NULL ) { llen = strlen(line); if ( eoline && (llen > 1) && (line[0] == '/' && line[1] == '/')) continue; /* skip comment lines begging with // */ eoline = 0; /* replace CR and newline chars at end of line with nulls */ if ((llen > 0) && (line[llen-1]=='\n' || line[llen-1] == '\r')) { line[--llen] = '\0'; eoline = 1; /* found an end of line character */ if ((llen > 0) && (line[llen-1]=='\n' || line[llen-1] == '\r')) { line[--llen] = '\0'; } } if( totalLen + llen + 3 >= allocLen ) { allocLen += 256; lines = (char *)realloc(lines, allocLen * sizeof(char) ); if( ! lines ) { ffpmsg("Couldn't allocate memory to hold ASCII file contents."); *status = MEMORY_ALLOCATION; break; } } strcpy( lines+totalLen, line ); totalLen += llen; if (eoline) { strcpy( lines+totalLen, " "); /* add a space between lines */ totalLen += 1; } } fclose(aFile); *contents = lines; return( *status ); } /*--------------------------------------------------------------------------*/ int fits_get_token(char **ptr, char *delimiter, char *token, int *isanumber) /* O - is this token a number? */ /* parse off the next token, delimited by a character in 'delimiter', from the input ptr string; increment *ptr to the end of the token. Returns the length of the token, not including the delimiter char; */ { char *loc, tval[73]; int slen; double dval; *token = '\0'; while (**ptr == ' ') /* skip over leading blanks */ (*ptr)++; slen = strcspn(*ptr, delimiter); /* length of next token */ if (slen) { strncat(token, *ptr, slen); /* copy token */ (*ptr) += slen; /* skip over the token */ if (isanumber) /* check if token is a number */ { *isanumber = 1; if (strchr(token, 'D')) { strncpy(tval, token, 72); tval[72] = '\0'; /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; dval = strtod(tval, &loc); } else { dval = strtod(token, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) *isanumber = 0; if (errno == ERANGE) *isanumber = 0; } } return(slen); } /*--------------------------------------------------------------------------*/ int fits_get_token2(char **ptr, char *delimiter, char **token, int *isanumber, /* O - is this token a number? */ int *status) /* parse off the next token, delimited by a character in 'delimiter', from the input ptr string; increment *ptr to the end of the token. Returns the length of the token, not including the delimiter char; This routine allocates the *token string; the calling routine must free it */ { char *loc, tval[73]; int slen; double dval; if (*status) return(0); while (**ptr == ' ') /* skip over leading blanks */ (*ptr)++; slen = strcspn(*ptr, delimiter); /* length of next token */ if (slen) { *token = (char *) calloc(slen + 1, 1); if (!(*token)) { ffpmsg("Couldn't allocate memory to hold token string (fits_get_token2)."); *status = MEMORY_ALLOCATION ; return(0); } strncat(*token, *ptr, slen); /* copy token */ (*ptr) += slen; /* skip over the token */ if (isanumber) /* check if token is a number */ { *isanumber = 1; if (strchr(*token, 'D')) { strncpy(tval, *token, 72); tval[72] = '\0'; /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; dval = strtod(tval, &loc); } else { dval = strtod(*token, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) *isanumber = 0; if (errno == ERANGE) *isanumber = 0; } } return(slen); } /*---------------------------------------------------------------------------*/ char *fits_split_names( char *list) /* I - input list of names */ { /* A sequence of calls to fits_split_names will split the input string into name tokens. The string typically contains a list of file or column names. The names must be delimited by a comma and/or spaces. This routine ignores spaces and commas that occur within parentheses, brackets, or curly brackets. It also strips any leading and trailing blanks from the returned name. This routine is similar to the ANSI C 'strtok' function: The first call to fits_split_names has a non-null input string. It finds the first name in the string and terminates it by overwriting the next character of the string with a '\0' and returns a pointer to the name. Each subsequent call, indicated by a NULL value of the input string, returns the next name, searching from just past the end of the previous name. It returns NULL when no further names are found. The following line illustrates how a string would be split into 3 names: myfile[1][bin (x,y)=4], file2.fits file3.fits ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ 1st name 2nd name 3rd name NOTE: This routine is not thread-safe. This routine is simply provided as a utility routine for other external software. It is not used by any CFITSIO routine. */ int depth = 0; char *start; static char *ptr; if (list) /* reset ptr if a string is given */ ptr = list; while (*ptr == ' ')ptr++; /* skip leading white space */ if (*ptr == '\0')return(0); /* no remaining file names */ start = ptr; while (*ptr != '\0') { if ((*ptr == '[') || (*ptr == '(') || (*ptr == '{')) depth ++; else if ((*ptr == '}') || (*ptr == ')') || (*ptr == ']')) depth --; else if ((depth == 0) && (*ptr == ',' || *ptr == ' ')) { *ptr = '\0'; /* terminate the filename here */ ptr++; /* save pointer to start of next filename */ break; } ptr++; } return(start); } /*--------------------------------------------------------------------------*/ int urltype2driver(char *urltype, int *driver) /* compare input URL with list of known drivers, returning the matching driver numberL. */ { int ii; /* find matching driver; search most recent drivers first */ for (ii=no_of_drivers - 1; ii >= 0; ii--) { if (0 == strcmp(driverTable[ii].prefix, urltype)) { *driver = ii; return(0); } } return(NO_MATCHING_DRIVER); } /*--------------------------------------------------------------------------*/ int ffclos(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* close the FITS file by completing the current HDU, flushing it to disk, then calling the system dependent routine to physically close the FITS file */ { int tstatus = NO_CLOSE_ERROR, zerostatus = 0; if (!fptr) return(*status = NULL_INPUT_PTR); else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */ return(*status = BAD_FILEPTR); /* close and flush the current HDU */ if (*status > 0) ffchdu(fptr, &tstatus); /* turn off the error message from ffchdu */ else ffchdu(fptr, status); ((fptr->Fptr)->open_count)--; /* decrement usage counter */ if ((fptr->Fptr)->open_count == 0) /* if no other files use structure */ { ffflsh(fptr, TRUE, status); /* flush and disassociate IO buffers */ /* call driver function to actually close the file */ if ((*driverTable[(fptr->Fptr)->driver].close)((fptr->Fptr)->filehandle)) { if (*status <= 0) { *status = FILE_NOT_CLOSED; /* report if no previous error */ ffpmsg("failed to close the following file: (ffclos)"); ffpmsg((fptr->Fptr)->filename); } } fits_clear_Fptr( fptr->Fptr, status); /* clear Fptr address */ free((fptr->Fptr)->iobuffer); /* free memory for I/O buffers */ free((fptr->Fptr)->headstart); /* free memory for headstart array */ free((fptr->Fptr)->filename); /* free memory for the filename */ (fptr->Fptr)->filename = 0; (fptr->Fptr)->validcode = 0; /* magic value to indicate invalid fptr */ free(fptr->Fptr); /* free memory for the FITS file structure */ free(fptr); /* free memory for the FITS file structure */ } else { /* to minimize the fallout from any previous error (e.g., trying to open a non-existent extension in a already opened file), always call ffflsh with status = 0. */ /* just flush the buffers, don't disassociate them */ if (*status > 0) ffflsh(fptr, FALSE, &zerostatus); else ffflsh(fptr, FALSE, status); free(fptr); /* free memory for the FITS file structure */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffdelt(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* close and DELETE the FITS file. */ { char *basename; int slen, tstatus = NO_CLOSE_ERROR, zerostatus = 0; if (!fptr) return(*status = NULL_INPUT_PTR); else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */ return(*status = BAD_FILEPTR); if (*status > 0) ffchdu(fptr, &tstatus); /* turn off the error message from ffchdu */ else ffchdu(fptr, status); ffflsh(fptr, TRUE, status); /* flush and disassociate IO buffers */ /* call driver function to actually close the file */ if ( (*driverTable[(fptr->Fptr)->driver].close)((fptr->Fptr)->filehandle) ) { if (*status <= 0) { *status = FILE_NOT_CLOSED; /* report error if no previous error */ ffpmsg("failed to close the following file: (ffdelt)"); ffpmsg((fptr->Fptr)->filename); } } /* call driver function to actually delete the file */ if ( (driverTable[(fptr->Fptr)->driver].remove) ) { /* parse the input URL to get the base filename */ slen = strlen((fptr->Fptr)->filename); basename = (char *) malloc(slen +1); if (!basename) return(*status = MEMORY_ALLOCATION); fits_parse_input_url((fptr->Fptr)->filename, NULL, basename, NULL, NULL, NULL, NULL, NULL, &zerostatus); if ((*driverTable[(fptr->Fptr)->driver].remove)(basename)) { ffpmsg("failed to delete the following file: (ffdelt)"); ffpmsg((fptr->Fptr)->filename); if (!(*status)) *status = FILE_NOT_CLOSED; } free(basename); } fits_clear_Fptr( fptr->Fptr, status); /* clear Fptr address */ free((fptr->Fptr)->iobuffer); /* free memory for I/O buffers */ free((fptr->Fptr)->headstart); /* free memory for headstart array */ free((fptr->Fptr)->filename); /* free memory for the filename */ (fptr->Fptr)->filename = 0; (fptr->Fptr)->validcode = 0; /* magic value to indicate invalid fptr */ free(fptr->Fptr); /* free memory for the FITS file structure */ free(fptr); /* free memory for the FITS file structure */ return(*status); } /*--------------------------------------------------------------------------*/ int fftrun( fitsfile *fptr, /* I - FITS file pointer */ LONGLONG filesize, /* I - size to truncate the file */ int *status) /* O - error status */ /* low level routine to truncate a file to a new smaller size. */ { if (driverTable[(fptr->Fptr)->driver].truncate) { ffflsh(fptr, FALSE, status); /* flush all the buffers first */ (fptr->Fptr)->filesize = filesize; (fptr->Fptr)->io_pos = filesize; (fptr->Fptr)->logfilesize = filesize; (fptr->Fptr)->bytepos = filesize; ffbfeof(fptr, status); /* eliminate any buffers beyond current EOF */ return (*status = (*driverTable[(fptr->Fptr)->driver].truncate)((fptr->Fptr)->filehandle, filesize) ); } else return(*status); } /*--------------------------------------------------------------------------*/ int ffflushx( FITSfile *fptr) /* I - FITS file pointer */ /* low level routine to flush internal file buffers to the file. */ { if (driverTable[fptr->driver].flush) return ( (*driverTable[fptr->driver].flush)(fptr->filehandle) ); else return(0); /* no flush function defined for this driver */ } /*--------------------------------------------------------------------------*/ int ffseek( FITSfile *fptr, /* I - FITS file pointer */ LONGLONG position) /* I - byte position to seek to */ /* low level routine to seek to a position in a file. */ { return( (*driverTable[fptr->driver].seek)(fptr->filehandle, position) ); } /*--------------------------------------------------------------------------*/ int ffwrite( FITSfile *fptr, /* I - FITS file pointer */ long nbytes, /* I - number of bytes to write */ void *buffer, /* I - buffer to write */ int *status) /* O - error status */ /* low level routine to write bytes to a file. */ { if ( (*driverTable[fptr->driver].write)(fptr->filehandle, buffer, nbytes) ) { ffpmsg("Error writing data buffer to file:"); ffpmsg(fptr->filename); *status = WRITE_ERROR; } return(*status); } /*--------------------------------------------------------------------------*/ int ffread( FITSfile *fptr, /* I - FITS file pointer */ long nbytes, /* I - number of bytes to read */ void *buffer, /* O - buffer to read into */ int *status) /* O - error status */ /* low level routine to read bytes from a file. */ { int readstatus; readstatus = (*driverTable[fptr->driver].read)(fptr->filehandle, buffer, nbytes); if (readstatus == END_OF_FILE) *status = END_OF_FILE; else if (readstatus > 0) { ffpmsg("Error reading data buffer from file:"); ffpmsg(fptr->filename); *status = READ_ERROR; } return(*status); } /*--------------------------------------------------------------------------*/ int fftplt(fitsfile **fptr, /* O - FITS file pointer */ const char *filename, /* I - name of file to create */ const char *tempname, /* I - name of template file */ int *status) /* IO - error status */ /* Create and initialize a new FITS file based on a template file. Uses C fopen and fgets functions. */ { *fptr = 0; /* initialize null file pointer, */ /* regardless of the value of *status */ if (*status > 0) return(*status); if ( ffinit(fptr, filename, status) ) /* create empty file */ return(*status); ffoptplt(*fptr, tempname, status); /* open and use template */ return(*status); } /*--------------------------------------------------------------------------*/ int ffoptplt(fitsfile *fptr, /* O - FITS file pointer */ const char *tempname, /* I - name of template file */ int *status) /* IO - error status */ /* open template file and use it to create new file */ { fitsfile *tptr; int tstatus = 0, nkeys, nadd, ii; char card[FLEN_CARD]; if (*status > 0) return(*status); if (tempname == NULL || *tempname == '\0') /* no template file? */ return(*status); /* try opening template */ ffopen(&tptr, (char *) tempname, READONLY, &tstatus); if (tstatus) /* not a FITS file, so treat it as an ASCII template */ { ffxmsg(2, card); /* clear the error message */ fits_execute_template(fptr, (char *) tempname, status); ffmahd(fptr, 1, 0, status); /* move back to the primary array */ return(*status); } else /* template is a valid FITS file */ { ffmahd(tptr, 1, NULL, status); /* make sure we are at the beginning */ while (*status <= 0) { ffghsp(tptr, &nkeys, &nadd, status); /* get no. of keywords */ for (ii = 1; ii <= nkeys; ii++) /* copy keywords */ { ffgrec(tptr, ii, card, status); /* must reset the PCOUNT keyword to zero in the new output file */ if (strncmp(card, "PCOUNT ",8) == 0) { /* the PCOUNT keyword? */ if (strncmp(card+25, " 0", 5)) { /* non-zero value? */ strncpy(card, "PCOUNT = 0", 30); } } ffprec(fptr, card, status); } ffmrhd(tptr, 1, 0, status); /* move to next HDU until error */ ffcrhd(fptr, status); /* create empty new HDU in output file */ } if (*status == END_OF_FILE) { *status = 0; /* expected error condition */ } ffclos(tptr, status); /* close the template file */ } ffmahd(fptr, 1, 0, status); /* move to the primary array */ return(*status); } /*--------------------------------------------------------------------------*/ void ffrprt( FILE *stream, int status) /* Print out report of cfitsio error status and messages on the error stack. Uses C FILE stream. */ { char status_str[FLEN_STATUS], errmsg[FLEN_ERRMSG]; if (status) { fits_get_errstatus(status, status_str); /* get the error description */ fprintf(stream, "\nFITSIO status = %d: %s\n", status, status_str); while ( fits_read_errmsg(errmsg) ) /* get error stack messages */ fprintf(stream, "%s\n", errmsg); } return; } /*--------------------------------------------------------------------------*/ int pixel_filter_helper( fitsfile **fptr, /* IO - pointer to input image; on output it */ /* points to the new image */ char *outfile, /* I - name for output file */ char *expr, /* I - Image filter expression */ int *status) { PixelFilter filter = { 0 }; char * DEFAULT_TAG = "X"; int ii, hdunum; int singleHDU = 0; filter.count = 1; filter.ifptr = fptr; filter.tag = &DEFAULT_TAG; /* create new empty file for result */ if (ffinit(&filter.ofptr, outfile, status) > 0) { ffpmsg("failed to create output file for pixel filter:"); ffpmsg(outfile); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ expr += 3; /* skip 'pix' */ switch (expr[0]) { case 'b': case 'B': filter.bitpix = BYTE_IMG; break; case 'i': case 'I': filter.bitpix = SHORT_IMG; break; case 'j': case 'J': filter.bitpix = LONG_IMG; break; case 'r': case 'R': filter.bitpix = FLOAT_IMG; break; case 'd': case 'D': filter.bitpix = DOUBLE_IMG; break; } if (filter.bitpix) /* skip bitpix indicator */ ++expr; if (*expr == '1') { ++expr; singleHDU = 1; } if (((*fptr)->Fptr)->only_one) singleHDU = 1; if (*expr != ' ') { ffpmsg("pixel filtering expression not space separated:"); ffpmsg(expr); } while (*expr == ' ') ++expr; /* copy all preceding extensions to the output file */ for (ii = 1; !singleHDU && ii < hdunum; ii++) { fits_movabs_hdu(*fptr, ii, NULL, status); if (fits_copy_hdu(*fptr, filter.ofptr, 0, status) > 0) { ffclos(filter.ofptr, status); return(*status); } } /* move back to the original HDU position */ fits_movabs_hdu(*fptr, hdunum, NULL, status); filter.expression = expr; if (fits_pixel_filter(&filter, status)) { ffpmsg("failed to execute image filter:"); ffpmsg(expr); ffclos(filter.ofptr, status); return(*status); } /* copy any remaining HDUs to the output file */ for (ii = hdunum + 1; !singleHDU; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, filter.ofptr, 0, status); } if (*status == END_OF_FILE) *status = 0; /* got the expected EOF error; reset = 0 */ else if (*status > 0) { ffclos(filter.ofptr, status); return(*status); } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = filter.ofptr; /* reset the pointer to the new table */ /* move back to the image subsection */ if (ii - 1 != hdunum) fits_movabs_hdu(*fptr, hdunum, NULL, status); return(*status); } /*-------------------------------------------------------------------*/ int ffihtps(void) { /* Wrapper function for global initialization of curl library. This is NOT THREAD-SAFE */ int status=0; #ifdef CFITSIO_HAVE_CURL if (curl_global_init(CURL_GLOBAL_ALL)) /* Do we want to define a new CFITSIO error code for this? */ status = -1; #endif return status; } /*-------------------------------------------------------------------*/ int ffchtps(void) { /* Wrapper function for global cleanup of curl library. This is NOT THREAD-SAFE */ #ifdef CFITSIO_HAVE_CURL curl_global_cleanup(); #endif return 0; } /*-------------------------------------------------------------------*/ void ffvhtps(int flag) { /* Turn libcurl's verbose output on (1) or off (0). This is NOT THREAD-SAFE */ #ifdef HAVE_NET_SERVICES https_set_verbose(flag); #endif } /*-------------------------------------------------------------------*/ void ffshdwn(int flag) { /* Display download status bar (to stderr), where applicable. This is NOT THREAD-SAFE */ #ifdef HAVE_NET_SERVICES fits_dwnld_prog_bar(flag); #endif } /*-------------------------------------------------------------------*/ int ffgtmo(void) { int timeout=0; #ifdef HAVE_NET_SERVICES timeout = fits_net_timeout(-1); #endif return timeout; } /*-------------------------------------------------------------------*/ int ffstmo(int sec, int *status) { if (*status > 0) return (*status); #ifdef HAVE_NET_SERVICES if (sec <= 0) { *status = BAD_NETTIMEOUT; ffpmsg("Bad value for net timeout setting (fits_set_timeout)."); return(*status); } fits_net_timeout(sec); #endif return(*status); } cfitsio-4.3.1/group.c0000644000225700000360000055233613717263734014000 0ustar cagordonlhea/* This file, group.c, contains the grouping convention suport routines. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* */ /* The group.c module of CFITSIO was written by Donald G. Jennings of */ /* the INTEGRAL Science Data Centre (ISDC) under NASA contract task */ /* 66002J6. The above copyright laws apply. Copyright guidelines of The */ /* University of Geneva might also apply. */ /* The following routines are designed to create, read, and manipulate */ /* FITS Grouping Tables as defined in the FITS Grouping Convention paper */ /* by Jennings, Pence, Folk and Schlesinger. The development of the */ /* grouping structure was partially funded under the NASA AISRP Program. */ #include "fitsio2.h" #include "group.h" #include #include #include #if defined(WIN32) || defined(__WIN32__) #include /* defines the getcwd function on Windows PCs */ #endif #if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) #include /* needed for getcwd prototype on unix machines */ #endif #define HEX_ESCAPE '%' /*--------------------------------------------------------------------------- Change record: D. Jennings, 18/06/98, version 1.0 of group module delivered to B. Pence for integration into CFITSIO 2.005 D. Jennings, 17/11/98, fixed bug in ffgtcpr(). Now use fits_find_nextkey() correctly and insert auxiliary keyword records directly before the TTYPE1 keyword in the copied group table. D. Jennings, 22/01/99, ffgmop() now looks for relative file paths when the MEMBER_LOCATION information is given in a grouping table. D. Jennings, 01/02/99, ffgtop() now looks for relatve file paths when the GRPLCn keyword value is supplied in the member HDU header. D. Jennings, 01/02/99, ffgtam() now trys to construct relative file paths from the member's file to the group table's file (and visa versa) when both the member's file and group table file are of access type FILE://. D. Jennings, 05/05/99, removed the ffgtcn() function; made obsolete by fits_get_url(). D. Jennings, 05/05/99, updated entire module to handle partial URLs and absolute URLs more robustly. Host dependent directory paths are now converted to true URLs before being read from/written to grouping tables. D. Jennings, 05/05/99, added the following new functions (note, none of these are directly callable by the application) int fits_path2url() int fits_url2path() int fits_get_cwd() int fits_get_url() int fits_clean_url() int fits_relurl2url() int fits_encode_url() int fits_unencode_url() int fits_is_url_absolute() -----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int ffgtcr(fitsfile *fptr, /* FITS file pointer */ char *grpname, /* name of the grouping table */ int grouptype, /* code specifying the type of grouping table information: GT_ID_ALL_URI 0 ==> defualt (all columns) GT_ID_REF 1 ==> ID by reference GT_ID_POS 2 ==> ID by position GT_ID_ALL 3 ==> ID by ref. and position GT_ID_REF_URI 11 ==> (1) + URI info GT_ID_POS_URI 12 ==> (2) + URI info */ int *status )/* return status code */ /* create a grouping table at the end of the current FITS file. This function makes the last HDU in the file the CHDU, then calls the fits_insert_group() function to actually create the new grouping table. */ { int hdutype; int hdunum; if(*status != 0) return(*status); *status = fits_get_num_hdus(fptr,&hdunum,status); /* If hdunum is 0 then we are at the beginning of the file and we actually haven't closed the first header yet, so don't do anything more */ if (0 != hdunum) { *status = fits_movabs_hdu(fptr,hdunum,&hdutype,status); } /* Now, the whole point of the above two fits_ calls was to get to the end of file. Let's ignore errors at this point and keep going since any error is likely to mean that we are already at the EOF, or the file is fatally corrupted. If we are at the EOF then the next fits_ call will be ok. If it's corrupted then the next call will fail, but that's not big deal at this point. */ if (0 != *status ) *status = 0; *status = fits_insert_group(fptr,grpname,grouptype,status); return(*status); } /*---------------------------------------------------------------------------*/ int ffgtis(fitsfile *fptr, /* FITS file pointer */ char *grpname, /* name of the grouping table */ int grouptype, /* code specifying the type of grouping table information: GT_ID_ALL_URI 0 ==> defualt (all columns) GT_ID_REF 1 ==> ID by reference GT_ID_POS 2 ==> ID by position GT_ID_ALL 3 ==> ID by ref. and position GT_ID_REF_URI 11 ==> (1) + URI info GT_ID_POS_URI 12 ==> (2) + URI info */ int *status) /* return status code */ /* insert a grouping table just after the current HDU of the current FITS file. This is the same as fits_create_group() only it allows the user to select the place within the FITS file to add the grouping table. */ { int tfields = 0; int hdunum = 0; int hdutype = 0; int extver; int i; long pcount = 0; char *ttype[6]; char *tform[6]; char ttypeBuff[102]; char tformBuff[54]; char extname[] = "GROUPING"; char keyword[FLEN_KEYWORD]; char keyvalue[FLEN_VALUE]; char comment[FLEN_COMMENT]; do { /* set up the ttype and tform character buffers */ for(i = 0; i < 6; ++i) { ttype[i] = ttypeBuff+(i*17); tform[i] = tformBuff+(i*9); } /* define the columns required according to the grouptype parameter */ *status = ffgtdc(grouptype,0,0,0,0,0,0,ttype,tform,&tfields,status); /* create the grouping table using the columns defined above */ *status = fits_insert_btbl(fptr,0,tfields,ttype,tform,NULL, NULL,pcount,status); if(*status != 0) continue; /* retrieve the hdu position of the new grouping table for future use */ fits_get_hdu_num(fptr,&hdunum); /* add the EXTNAME and EXTVER keywords to the HDU just after the TFIELDS keyword; for now the EXTVER value is set to 0, it will be set to the correct value later on */ fits_read_keyword(fptr,"TFIELDS",keyvalue,comment,status); fits_insert_key_str(fptr,"EXTNAME",extname, "HDU contains a Grouping Table",status); fits_insert_key_lng(fptr,"EXTVER",0,"Grouping Table vers. (this file)", status); /* if the grpname parameter value was defined (Non NULL and non zero length) then add the GRPNAME keyword and value */ if(grpname != NULL && strlen(grpname) > 0) fits_insert_key_str(fptr,"GRPNAME",grpname,"Grouping Table name", status); /* add the TNULL keywords and values for each integer column defined; integer null values are zero (0) for the MEMBER_POSITION and MEMBER_VERSION columns. */ for(i = 0; i < tfields && *status == 0; ++i) { if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 || fits_strcasecmp(ttype[i],"MEMBER_VERSION") == 0) { snprintf(keyword,FLEN_KEYWORD,"TFORM%d",i+1); *status = fits_read_key_str(fptr,keyword,keyvalue,comment, status); snprintf(keyword,FLEN_KEYWORD,"TNULL%d",i+1); *status = fits_insert_key_lng(fptr,keyword,0,"Column Null Value", status); } } /* determine the correct EXTVER value for the new grouping table by finding the highest numbered grouping table EXTVER value the currently exists */ for(extver = 1; (fits_movnam_hdu(fptr,ANY_HDU,"GROUPING",extver,status)) == 0; ++extver); if(*status == BAD_HDU_NUM) *status = 0; /* move back to the new grouping table HDU and update the EXTVER keyword value */ fits_movabs_hdu(fptr,hdunum,&hdutype,status); fits_modify_key_lng(fptr,"EXTVER",extver,"&",status); }while(0); return(*status); } /*---------------------------------------------------------------------------*/ int ffgtch(fitsfile *gfptr, /* FITS pointer to group */ int grouptype, /* code specifying the type of grouping table information: GT_ID_ALL_URI 0 ==> defualt (all columns) GT_ID_REF 1 ==> ID by reference GT_ID_POS 2 ==> ID by position GT_ID_ALL 3 ==> ID by ref. and position GT_ID_REF_URI 11 ==> (1) + URI info GT_ID_POS_URI 12 ==> (2) + URI info */ int *status) /* return status code */ /* Change the grouping table structure of the grouping table pointed to by gfptr. The grouptype code specifies the new structure of the table. This operation only adds or removes grouping table columns, it does not add or delete group members (i.e., table rows). If the grouping table already has the desired structure then no operations are performed and function simply returns with a (0) success status code. If the requested structure change creates new grouping table columns, then the column values for all existing members will be filled with the appropriate null values. */ { int xtensionCol, extnameCol, extverCol, positionCol, locationCol, uriCol; int ncols = 0; int colnum = 0; int nrows = 0; int grptype = 0; int i,j; long intNull = 0; long tfields = 0; char *tform[6]; char *ttype[6]; unsigned char charNull[1] = {'\0'}; char ttypeBuff[102]; char tformBuff[54]; char keyword[FLEN_KEYWORD]; char keyvalue[FLEN_VALUE]; char comment[FLEN_COMMENT]; if(*status != 0) return(*status); do { /* set up the ttype and tform character buffers */ for(i = 0; i < 6; ++i) { ttype[i] = ttypeBuff+(i*17); tform[i] = tformBuff+(i*9); } /* retrieve positions of all Grouping table reserved columns */ *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol, &locationCol,&uriCol,&grptype,status); if(*status != 0) continue; /* determine the total number of grouping table columns */ *status = fits_read_key_lng(gfptr,"TFIELDS",&tfields,comment,status); /* define grouping table columns to be added to the configuration */ *status = ffgtdc(grouptype,xtensionCol,extnameCol,extverCol,positionCol, locationCol,uriCol,ttype,tform,&ncols,status); /* delete any grouping tables columns that exist but do not belong to new desired configuration; note that we delete before creating new columns for (file size) efficiency reasons */ switch(grouptype) { case GT_ID_ALL_URI: /* no columns to be deleted in this case */ break; case GT_ID_REF: if(positionCol != 0) { *status = fits_delete_col(gfptr,positionCol,status); --tfields; if(uriCol > positionCol) --uriCol; if(locationCol > positionCol) --locationCol; } if(uriCol != 0) { *status = fits_delete_col(gfptr,uriCol,status); --tfields; if(locationCol > uriCol) --locationCol; } if(locationCol != 0) *status = fits_delete_col(gfptr,locationCol,status); break; case GT_ID_POS: if(xtensionCol != 0) { *status = fits_delete_col(gfptr,xtensionCol,status); --tfields; if(extnameCol > xtensionCol) --extnameCol; if(extverCol > xtensionCol) --extverCol; if(uriCol > xtensionCol) --uriCol; if(locationCol > xtensionCol) --locationCol; } if(extnameCol != 0) { *status = fits_delete_col(gfptr,extnameCol,status); --tfields; if(extverCol > extnameCol) --extverCol; if(uriCol > extnameCol) --uriCol; if(locationCol > extnameCol) --locationCol; } if(extverCol != 0) { *status = fits_delete_col(gfptr,extverCol,status); --tfields; if(uriCol > extverCol) --uriCol; if(locationCol > extverCol) --locationCol; } if(uriCol != 0) { *status = fits_delete_col(gfptr,uriCol,status); --tfields; if(locationCol > uriCol) --locationCol; } if(locationCol != 0) { *status = fits_delete_col(gfptr,locationCol,status); --tfields; } break; case GT_ID_ALL: if(uriCol != 0) { *status = fits_delete_col(gfptr,uriCol,status); --tfields; if(locationCol > uriCol) --locationCol; } if(locationCol != 0) { *status = fits_delete_col(gfptr,locationCol,status); --tfields; } break; case GT_ID_REF_URI: if(positionCol != 0) { *status = fits_delete_col(gfptr,positionCol,status); --tfields; } break; case GT_ID_POS_URI: if(xtensionCol != 0) { *status = fits_delete_col(gfptr,xtensionCol,status); --tfields; if(extnameCol > xtensionCol) --extnameCol; if(extverCol > xtensionCol) --extverCol; } if(extnameCol != 0) { *status = fits_delete_col(gfptr,extnameCol,status); --tfields; if(extverCol > extnameCol) --extverCol; } if(extverCol != 0) { *status = fits_delete_col(gfptr,extverCol,status); --tfields; } break; default: *status = BAD_OPTION; ffpmsg("Invalid value for grouptype parameter specified (ffgtch)"); break; } /* add all the new grouping table columns that were not there previously but are called for by the grouptype parameter */ for(i = 0; i < ncols && *status == 0; ++i) *status = fits_insert_col(gfptr,tfields+i+1,ttype[i],tform[i],status); /* add the TNULL keywords and values for each new integer column defined; integer null values are zero (0) for the MEMBER_POSITION and MEMBER_VERSION columns. Insert a null ("/0") into each new string column defined: MEMBER_XTENSION, MEMBER_NAME, MEMBER_URI_TYPE and MEMBER_LOCATION. Note that by convention a null string is the TNULL value for character fields so no TNULL is required. */ for(i = 0; i < ncols && *status == 0; ++i) { if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 || fits_strcasecmp(ttype[i],"MEMBER_VERSION") == 0) { /* col contains int data; set TNULL and insert 0 for each col */ *status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum, status); snprintf(keyword,FLEN_KEYWORD,"TFORM%d",colnum); *status = fits_read_key_str(gfptr,keyword,keyvalue,comment, status); snprintf(keyword,FLEN_KEYWORD,"TNULL%d",colnum); *status = fits_insert_key_lng(gfptr,keyword,0, "Column Null Value",status); for(j = 1; j <= nrows && *status == 0; ++j) *status = fits_write_col_lng(gfptr,colnum,j,1,1,&intNull, status); } else if(fits_strcasecmp(ttype[i],"MEMBER_XTENSION") == 0 || fits_strcasecmp(ttype[i],"MEMBER_NAME") == 0 || fits_strcasecmp(ttype[i],"MEMBER_URI_TYPE") == 0 || fits_strcasecmp(ttype[i],"MEMBER_LOCATION") == 0) { /* new col contains character data; insert NULLs into each col */ *status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum, status); for(j = 1; j <= nrows && *status == 0; ++j) /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/ *status = fits_write_col_byt(gfptr,colnum,j,1,1,charNull, status); } } }while(0); return(*status); } /*---------------------------------------------------------------------------*/ int ffgtrm(fitsfile *gfptr, /* FITS file pointer to group */ int rmopt, /* code specifying if member elements are to be deleted: OPT_RM_GPT ==> remove only group table OPT_RM_ALL ==> recursively remove members and their members (if groups) */ int *status) /* return status code */ /* remove a grouping table, and optionally all its members. Any groups containing the grouping table are updated, and all members (if not deleted) have their GRPIDn and GRPLCn keywords updated accordingly. If the (deleted) members are members of another grouping table then those tables are also updated. The CHDU of the FITS file pointed to by gfptr must be positioned to the grouping table to be deleted. */ { int hdutype; long i; long nmembers = 0; HDUtracker HDU; if(*status != 0) return(*status); /* remove the grouping table depending upon the rmopt parameter */ switch(rmopt) { case OPT_RM_GPT: /* for this option, the grouping table is deleted, but the member HDUs remain; in this case we only have to remove each member from the grouping table by calling fits_remove_member() with the OPT_RM_ENTRY option */ /* get the number of members contained by this table */ *status = fits_get_num_members(gfptr,&nmembers,status); /* loop over all grouping table members and remove them */ for(i = nmembers; i > 0 && *status == 0; --i) *status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status); break; case OPT_RM_ALL: /* for this option the entire Group is deleted -- this includes all members and their members (if grouping tables themselves). Call the recursive form of this function to perform the removal. */ /* add the current grouping table to the HDUtracker struct */ HDU.nHDU = 0; *status = fftsad(gfptr,&HDU,NULL,NULL); /* call the recursive group remove function */ *status = ffgtrmr(gfptr,&HDU,status); /* free the memory allocated to the HDUtracker struct */ for(i = 0; i < HDU.nHDU; ++i) { free(HDU.filename[i]); free(HDU.newFilename[i]); } break; default: *status = BAD_OPTION; ffpmsg("Invalid value for the rmopt parameter specified (ffgtrm)"); break; } /* if all went well then unlink and delete the grouping table HDU */ *status = ffgmul(gfptr,0,status); *status = fits_delete_hdu(gfptr,&hdutype,status); return(*status); } /*---------------------------------------------------------------------------*/ int ffgtcp(fitsfile *infptr, /* input FITS file pointer */ fitsfile *outfptr, /* output FITS file pointer */ int cpopt, /* code specifying copy options: OPT_GCP_GPT (0) ==> copy only grouping table OPT_GCP_ALL (2) ==> recusrively copy members and their members (if groups) */ int *status) /* return status code */ /* copy a grouping table, and optionally all its members, to a new FITS file. If the cpopt is set to OPT_GCP_GPT (copy grouping table only) then the existing members have their GRPIDn and GRPLCn keywords updated to reflect the existance of the new group, since they now belong to another group. If cpopt is set to OPT_GCP_ALL (copy grouping table and members recursively) then the original members are not updated; the new grouping table is modified to include only the copied member HDUs and not the original members. Note that the recursive version of this function, ffgtcpr(), is called to perform the group table copy. In the case of cpopt == OPT_GCP_GPT ffgtcpr() does not actually use recursion. */ { int i; HDUtracker HDU; if(*status != 0) return(*status); /* make sure infptr and outfptr are not the same pointer */ if(infptr == outfptr) *status = IDENTICAL_POINTERS; else { /* initialize the HDUtracker struct */ HDU.nHDU = 0; *status = fftsad(infptr,&HDU,NULL,NULL); /* call the recursive form of this function to copy the grouping table. If the cpopt is OPT_GCP_GPT then there is actually no recursion performed */ *status = ffgtcpr(infptr,outfptr,cpopt,&HDU,status); /* free memory allocated for the HDUtracker struct */ for(i = 0; i < HDU.nHDU; ++i) { free(HDU.filename[i]); free(HDU.newFilename[i]); } } return(*status); } /*---------------------------------------------------------------------------*/ int ffgtmg(fitsfile *infptr, /* FITS file ptr to source grouping table */ fitsfile *outfptr, /* FITS file ptr to target grouping table */ int mgopt, /* code specifying merge options: OPT_MRG_COPY (0) ==> copy members to target group, leaving source group in place OPT_MRG_MOV (1) ==> move members to target group, source group is deleted after merge */ int *status) /* return status code */ /* merge two grouping tables by combining their members into a single table. The source grouping table must be the CHDU of the fitsfile pointed to by infptr, and the target grouping table must be the CHDU of the fitsfile to by outfptr. All members of the source grouping table shall be copied to the target grouping table. If the mgopt parameter is OPT_MRG_COPY then the source grouping table continues to exist after the merge. If the mgopt parameter is OPT_MRG_MOV then the source grouping table is deleted after the merge, and all member HDUs are updated accordingly. */ { long i ; long nmembers = 0; fitsfile *tmpfptr = NULL; if(*status != 0) return(*status); do { *status = fits_get_num_members(infptr,&nmembers,status); for(i = 1; i <= nmembers && *status == 0; ++i) { *status = fits_open_member(infptr,i,&tmpfptr,status); *status = fits_add_group_member(outfptr,tmpfptr,0,status); if(*status == HDU_ALREADY_MEMBER) *status = 0; if(tmpfptr != NULL) { fits_close_file(tmpfptr,status); tmpfptr = NULL; } } if(*status != 0) continue; if(mgopt == OPT_MRG_MOV) *status = fits_remove_group(infptr,OPT_RM_GPT,status); }while(0); if(tmpfptr != NULL) { fits_close_file(tmpfptr,status); } return(*status); } /*---------------------------------------------------------------------------*/ int ffgtcm(fitsfile *gfptr, /* FITS file pointer to grouping table */ int cmopt, /* code specifying compact options OPT_CMT_MBR (1) ==> compact only direct members (if groups) OPT_CMT_MBR_DEL (11) ==> (1) + delete all compacted groups */ int *status) /* return status code */ /* "Compact" a group pointed to by the FITS file pointer gfptr. This is achieved by flattening the tree structure of a group and its (grouping table) members. All members HDUs of a grouping table which is itself a member of the grouping table gfptr are added to gfptr. Optionally, the grouping tables which are "compacted" are deleted. If the grouping table contains no members that are themselves grouping tables then this function performs a NOOP. */ { long i; long nmembers = 0; char keyvalue[FLEN_VALUE]; char comment[FLEN_COMMENT]; fitsfile *mfptr = NULL; if(*status != 0) return(*status); do { if(cmopt != OPT_CMT_MBR && cmopt != OPT_CMT_MBR_DEL) { *status = BAD_OPTION; ffpmsg("Invalid value for cmopt parameter specified (ffgtcm)"); continue; } /* reteive the number of grouping table members */ *status = fits_get_num_members(gfptr,&nmembers,status); /* loop over all the grouping table members; if the member is a grouping table then merge its members with the parent grouping table */ for(i = 1; i <= nmembers && *status == 0; ++i) { *status = fits_open_member(gfptr,i,&mfptr,status); if(*status != 0) continue; *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status); /* if no EXTNAME keyword then cannot be a grouping table */ if(*status == KEY_NO_EXIST) { *status = 0; continue; } prepare_keyvalue(keyvalue); if(*status != 0) continue; /* if EXTNAME == "GROUPING" then process member as grouping table */ if(fits_strcasecmp(keyvalue,"GROUPING") == 0) { /* merge the member (grouping table) into the grouping table */ *status = fits_merge_groups(mfptr,gfptr,OPT_MRG_COPY,status); *status = fits_close_file(mfptr,status); mfptr = NULL; /* remove the member from the grouping table now that all of its members have been transferred; if cmopt is set to OPT_CMT_MBR_DEL then remove and delete the member */ if(cmopt == OPT_CMT_MBR) *status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status); else *status = fits_remove_member(gfptr,i,OPT_RM_MBR,status); } else { /* not a grouping table; just close the opened member */ *status = fits_close_file(mfptr,status); mfptr = NULL; } } }while(0); return(*status); } /*--------------------------------------------------------------------------*/ int ffgtvf(fitsfile *gfptr, /* FITS file pointer to group */ long *firstfailed, /* Member ID (if positive) of first failed member HDU verify check or GRPID index (if negitive) of first failed group link verify check. */ int *status) /* return status code */ /* check the integrity of a grouping table to make sure that all group members are accessible and all the links to other grouping tables are valid. The firstfailed parameter returns the member ID of the first member HDU to fail verification if positive or the first group link to fail if negative; otherwise firstfailed contains a return value of 0. */ { long i; long nmembers = 0; long ngroups = 0; char errstr[FLEN_VALUE]; fitsfile *fptr = NULL; if(*status != 0) return(*status); *firstfailed = 0; do { /* attempt to open all the members of the grouping table. We stop at the first member which cannot be opened (which implies that it cannot be located) */ *status = fits_get_num_members(gfptr,&nmembers,status); for(i = 1; i <= nmembers && *status == 0; ++i) { *status = fits_open_member(gfptr,i,&fptr,status); fits_close_file(fptr,status); } /* if the status is non-zero from the above loop then record the member index that caused the error */ if(*status != 0) { *firstfailed = i; snprintf(errstr,FLEN_VALUE,"Group table verify failed for member %ld (ffgtvf)", i); ffpmsg(errstr); continue; } /* attempt to open all the groups linked to this grouping table. We stop at the first group which cannot be opened (which implies that it cannot be located) */ *status = fits_get_num_groups(gfptr,&ngroups,status); for(i = 1; i <= ngroups && *status == 0; ++i) { *status = fits_open_group(gfptr,i,&fptr,status); fits_close_file(fptr,status); } /* if the status from the above loop is non-zero, then record the GRPIDn index of the group that caused the failure */ if(*status != 0) { *firstfailed = -1*i; snprintf(errstr,FLEN_VALUE, "Group table verify failed for GRPID index %ld (ffgtvf)",i); ffpmsg(errstr); continue; } }while(0); return(*status); } /*---------------------------------------------------------------------------*/ int ffgtop(fitsfile *mfptr, /* FITS file pointer to the member HDU */ int grpid, /* group ID (GRPIDn index) within member HDU */ fitsfile **gfptr, /* FITS file pointer to grouping table HDU */ int *status) /* return status code */ /* open the grouping table that contains the member HDU. The member HDU must be the CHDU of the FITS file pointed to by mfptr, and the grouping table is identified by the Nth index number of the GRPIDn keywords specified in the member HDU's header. The fitsfile gfptr pointer is positioned with the appropriate FITS file with the grouping table as the CHDU. If the group grouping table resides in a file other than the member then an attempt is first made to open the file readwrite, and failing that readonly. Note that it is possible for the GRPIDn/GRPLCn keywords in a member header to be non-continuous, e.g., GRPID1, GRPID2, GRPID5, GRPID6. In such cases, the grpid index value specified in the function call shall identify the (grpid)th GRPID value. In the above example, if grpid == 3, then the group specified by GRPID5 would be opened. */ { int i; int found; long ngroups = 0; long grpExtver = 0; char keyword[FLEN_KEYWORD]; char keyvalue[FLEN_FILENAME]; char *tkeyvalue; char location[FLEN_FILENAME]; char location1[FLEN_FILENAME]; char location2[FLEN_FILENAME]; char comment[FLEN_COMMENT]; char *url[2]; if(*status != 0) return(*status); do { /* set the grouping table pointer to NULL for error checking later */ *gfptr = NULL; /* make sure that the group ID requested is valid ==> cannot be larger than the number of GRPIDn keywords in the member HDU header */ *status = fits_get_num_groups(mfptr,&ngroups,status); if(grpid > ngroups) { *status = BAD_GROUP_ID; snprintf(comment,FLEN_COMMENT, "GRPID index %d larger total GRPID keywords %ld (ffgtop)", grpid,ngroups); ffpmsg(comment); continue; } /* find the (grpid)th group that the member HDU belongs to and read the value of the GRPID(grpid) keyword; fits_get_num_groups() automatically re-enumerates the GRPIDn/GRPLCn keywords to fill in any gaps */ snprintf(keyword,FLEN_KEYWORD,"GRPID%d",grpid); *status = fits_read_key_lng(mfptr,keyword,&grpExtver,comment,status); if(*status != 0) continue; /* if the value of the GRPIDn keyword is positive then the member is in the same FITS file as the grouping table and we only have to reopen the current FITS file. Else the member and grouping table HDUs reside in different files and another FITS file must be opened as specified by the corresponding GRPLCn keyword The DO WHILE loop only executes once and is used to control the file opening logic. */ do { if(grpExtver > 0) { /* the member resides in the same file as the grouping table, so just reopen the grouping table file */ *status = fits_reopen_file(mfptr,gfptr,status); continue; } else if(grpExtver == 0) { /* a GRPIDn value of zero (0) is undefined */ *status = BAD_GROUP_ID; snprintf(comment,FLEN_COMMENT,"Invalid value of %ld for GRPID%d (ffgtop)", grpExtver,grpid); ffpmsg(comment); continue; } /* The GRPLCn keyword value is negative, which implies that the grouping table must reside in another FITS file; search for the corresponding GRPLCn keyword */ /* set the grpExtver value positive */ grpExtver = -1*grpExtver; /* read the GRPLCn keyword value */ snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",grpid); /* SPR 1738 */ *status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment, status); if (0 == *status) { strcpy(keyvalue,tkeyvalue); free(tkeyvalue); } /* if the GRPLCn keyword was not found then there is a problem */ if(*status == KEY_NO_EXIST) { *status = BAD_GROUP_ID; snprintf(comment,FLEN_COMMENT,"Cannot find GRPLC%d keyword (ffgtop)", grpid); ffpmsg(comment); continue; } prepare_keyvalue(keyvalue); /* if the GRPLCn keyword value specifies an absolute URL then try to open the file; we cannot attempt any relative URL or host-dependent file path reconstruction */ if(fits_is_url_absolute(keyvalue)) { ffpmsg("Try to open group table file as absolute URL (ffgtop)"); *status = fits_open_file(gfptr,keyvalue,READWRITE,status); /* if the open was successful then continue */ if(*status == 0) continue; /* if READWRITE failed then try opening it READONLY */ ffpmsg("OK, try open group table file as READONLY (ffgtop)"); *status = 0; *status = fits_open_file(gfptr,keyvalue,READONLY,status); /* continue regardless of the outcome */ continue; } /* see if the URL gives a file path that is absolute on the host machine */ *status = fits_url2path(keyvalue,location1,status); *status = fits_open_file(gfptr,location1,READWRITE,status); /* if the file opened then continue */ if(*status == 0) continue; /* if READWRITE failed then try opening it READONLY */ ffpmsg("OK, try open group table file as READONLY (ffgtop)"); *status = 0; *status = fits_open_file(gfptr,location1,READONLY,status); /* if the file opened then continue */ if(*status == 0) continue; /* the grouping table location given by GRPLCn must specify a relative URL. We assume that this URL is relative to the member HDU's FITS file. Try to construct a full URL location for the grouping table's FITS file and then open it */ *status = 0; /* retrieve the URL information for the member HDU's file */ url[0] = location1; url[1] = location2; *status = fits_get_url(mfptr,url[0],url[1],NULL,NULL,NULL,status); /* It is possible that the member HDU file has an initial URL it was opened with and a real URL that the file actually exists at (e.g., an HTTP accessed file copied to a local file). For each possible URL try to construct a */ for(i = 0, found = 0, *gfptr = NULL; i < 2 && !found; ++i) { /* the url string could be empty */ if(*url[i] == 0) continue; /* create a full URL from the partial and the member HDU file URL */ *status = fits_relurl2url(url[i],keyvalue,location,status); /* if an error occured then contniue */ if(*status != 0) { *status = 0; continue; } /* if the location does not specify an access method then turn it into a host dependent path */ if(! fits_is_url_absolute(location)) { *status = fits_url2path(location,url[i],status); strcpy(location,url[i]); } /* try to open the grouping table file READWRITE */ *status = fits_open_file(gfptr,location,READWRITE,status); if(*status != 0) { /* try to open the grouping table file READONLY */ ffpmsg("opening file as READWRITE failed (ffgtop)"); ffpmsg("OK, try to open file as READONLY (ffgtop)"); *status = 0; *status = fits_open_file(gfptr,location,READONLY,status); } /* either set the found flag or reset the status flag */ if(*status == 0) found = 1; else *status = 0; } }while(0); /* end of file opening loop */ /* if an error occured with the file opening then exit */ if(*status != 0) continue; if(*gfptr == NULL) { ffpmsg("Cannot open or find grouping table FITS file (ffgtop)"); *status = GROUP_NOT_FOUND; continue; } /* search for the grouping table in its FITS file */ *status = fits_movnam_hdu(*gfptr,ANY_HDU,"GROUPING",(int)grpExtver, status); if(*status != 0) *status = GROUP_NOT_FOUND; }while(0); if(*status != 0 && *gfptr != NULL) { fits_close_file(*gfptr,status); *gfptr = NULL; } return(*status); } /*---------------------------------------------------------------------------*/ int ffgtam(fitsfile *gfptr, /* FITS file pointer to grouping table HDU */ fitsfile *mfptr, /* FITS file pointer to member HDU */ int hdupos, /* member HDU position IF in the same file as the grouping table AND mfptr == NULL */ int *status) /* return status code */ /* add a member HDU to an existing grouping table. The fitsfile pointer gfptr must be positioned with the grouping table as the CHDU. The member HDU may either be identifed with the fitsfile *mfptr (which must be positioned to the member HDU) or the hdupos parameter (the HDU number of the member HDU) if both reside in the same FITS file. The hdupos value is only used if the mfptr parameter has a value of NULL (0). The new member HDU shall have the appropriate GRPIDn and GRPLCn keywords created in its header. Note that if the member HDU to be added to the grouping table is already a member of the group then it will not be added a sceond time. */ { int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol; int memberPosition = 0; int grptype = 0; int hdutype = 0; int useLocation = 0; int nkeys = 6; int found; int i; int memberIOstate; int groupIOstate; int iomode; long memberExtver = 0; long groupExtver = 0; long memberID = 0; long nmembers = 0; long ngroups = 0; long grpid = 0; char memberAccess1[FLEN_VALUE]; char memberAccess2[FLEN_VALUE]; char memberFileName[FLEN_FILENAME]; char memberLocation[FLEN_FILENAME]; char grplc[FLEN_FILENAME]; char *tgrplc; char memberHDUtype[FLEN_VALUE]; char memberExtname[FLEN_VALUE]; char memberURI[] = "URL"; char groupAccess1[FLEN_VALUE]; char groupAccess2[FLEN_VALUE]; char groupFileName[FLEN_FILENAME]; char groupLocation[FLEN_FILENAME]; char tmprootname[FLEN_FILENAME], grootname[FLEN_FILENAME]; char cwd[FLEN_FILENAME]; char *keys[] = {"GRPNAME","EXTVER","EXTNAME","TFIELDS","GCOUNT","EXTEND"}; char *tmpPtr[1]; char keyword[FLEN_KEYWORD]; char card[FLEN_CARD]; unsigned char charNull[] = {'\0'}; fitsfile *tmpfptr = NULL; int parentStatus = 0; if(*status != 0) return(*status); do { /* make sure the grouping table can be modified before proceeding */ fits_file_mode(gfptr,&iomode,status); if(iomode != READWRITE) { ffpmsg("cannot modify grouping table (ffgtam)"); *status = BAD_GROUP_ATTACH; continue; } /* if the calling function supplied the HDU position of the member HDU instead of fitsfile pointer then get a fitsfile pointer */ if(mfptr == NULL) { *status = fits_reopen_file(gfptr,&tmpfptr,status); *status = fits_movabs_hdu(tmpfptr,hdupos,&hdutype,status); if(*status != 0) continue; } else tmpfptr = mfptr; /* determine all the information about the member HDU that will be needed later; note that we establish the default values for all information values that are not explicitly found */ *status = fits_read_key_str(tmpfptr,"XTENSION",memberHDUtype,card, status); if(*status == KEY_NO_EXIST) { strcpy(memberHDUtype,"PRIMARY"); *status = 0; } prepare_keyvalue(memberHDUtype); *status = fits_read_key_lng(tmpfptr,"EXTVER",&memberExtver,card,status); if(*status == KEY_NO_EXIST) { memberExtver = 1; *status = 0; } *status = fits_read_key_str(tmpfptr,"EXTNAME",memberExtname,card, status); if(*status == KEY_NO_EXIST) { memberExtname[0] = 0; *status = 0; } prepare_keyvalue(memberExtname); fits_get_hdu_num(tmpfptr,&memberPosition); /* Determine if the member HDU's FITS file location needs to be taken into account when building its grouping table reference If the member location needs to be used (==> grouping table and member HDU reside in different files) then create an appropriate URL for the member HDU's file and grouping table's file. Note that the logic for this is rather complicated */ /* SPR 3463, don't do this if(tmpfptr->Fptr == gfptr->Fptr) { */ /* member HDU and grouping table reside in the same file, no need to use the location information */ /* printf ("same file\n"); useLocation = 0; memberIOstate = 1; *memberFileName = 0; } else { */ /* the member HDU and grouping table FITS file location information must be used. First determine the correct driver and file name for the group table and member HDU files. If either are disk files then construct an absolute file path for them. Finally, if both are disk files construct relative file paths from the group(member) file to the member(group) file. */ /* set the USELOCATION flag to true */ useLocation = 1; /* get the location, access type and iostate (RO, RW) of the member HDU file */ *status = fits_get_url(tmpfptr,memberFileName,memberLocation, memberAccess1,memberAccess2,&memberIOstate, status); /* if the memberFileName string is empty then use the values of the memberLocation string. This corresponds to a file where the "real" file is a temporary memory file, and we must assume the the application really wants the original file to be the group member */ if(strlen(memberFileName) == 0) { strcpy(memberFileName,memberLocation); strcpy(memberAccess1,memberAccess2); } /* get the location, access type and iostate (RO, RW) of the grouping table file */ *status = fits_get_url(gfptr,groupFileName,groupLocation, groupAccess1,groupAccess2,&groupIOstate, status); if(*status != 0) continue; /* the grouping table file must be writable to continue */ if(groupIOstate == 0) { ffpmsg("cannot modify grouping table (ffgtam)"); *status = BAD_GROUP_ATTACH; continue; } /* determine how to construct the resulting URLs for the member and group files */ if(fits_strcasecmp(groupAccess1,"file://") && fits_strcasecmp(memberAccess1,"file://")) { *cwd = 0; /* nothing to do in this case; both the member and group files must be of an access type that already gives valid URLs; i.e., URLs that we can pass directly to the file drivers */ } else { /* retrieve the Current Working Directory as a Unix-like URL standard string */ *status = fits_get_cwd(cwd,status); /* create full file path for the member HDU FITS file URL if it is of access type file:// */ if(fits_strcasecmp(memberAccess1,"file://") == 0) { if(*memberFileName == '/') { strcpy(memberLocation,memberFileName); } else { strcpy(memberLocation,cwd); if (strlen(memberLocation)+strlen(memberFileName)+1 > FLEN_FILENAME-1) { ffpmsg("member path and filename is too long (ffgtam)"); *status = URL_PARSE_ERROR; continue; } strcat(memberLocation,"/"); strcat(memberLocation,memberFileName); } *status = fits_clean_url(memberLocation,memberFileName, status); } /* create full file path for the grouping table HDU FITS file URL if it is of access type file:// */ if(fits_strcasecmp(groupAccess1,"file://") == 0) { if(*groupFileName == '/') { strcpy(groupLocation,groupFileName); } else { strcpy(groupLocation,cwd); if (strlen(groupLocation)+strlen(groupFileName)+1 > FLEN_FILENAME-1) { ffpmsg("group path and filename is too long (ffgtam)"); *status = URL_PARSE_ERROR; continue; } strcat(groupLocation,"/"); strcat(groupLocation,groupFileName); } *status = fits_clean_url(groupLocation,groupFileName,status); } /* if both the member and group files are disk files then create a relative path (relative URL) strings with respect to the grouping table's file and the grouping table's file with respect to the member HDU's file */ if(fits_strcasecmp(groupAccess1,"file://") == 0 && fits_strcasecmp(memberAccess1,"file://") == 0) { fits_url2relurl(memberFileName,groupFileName, groupLocation,status); fits_url2relurl(groupFileName,memberFileName, memberLocation,status); /* copy the resulting partial URL strings to the memberFileName and groupFileName variables for latter use in the function */ strcpy(memberFileName,memberLocation); strcpy(groupFileName,groupLocation); } } /* beo done */ /* } */ /* retrieve the grouping table's EXTVER value */ *status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,status); /* if useLocation is true then make the group EXTVER value negative for the subsequent GRPIDn/GRPLCn matching */ /* SPR 3463 change test; WDP added test for same filename */ /* Now, if either the Fptr values are the same, or the root filenames are the same, then assume these refer to the same file. */ fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status); fits_parse_rootname(gfptr->Fptr->filename, grootname, status); if((tmpfptr->Fptr != gfptr->Fptr) && strncmp(tmprootname, grootname, FLEN_FILENAME)) groupExtver = -1*groupExtver; /* retrieve the number of group members */ *status = fits_get_num_members(gfptr,&nmembers,status); do { /* make sure the member HDU is not already an entry in the grouping table before adding it */ *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver, memberPosition,memberFileName,&memberID,status); if(*status == MEMBER_NOT_FOUND) *status = 0; else if(*status == 0) { parentStatus = HDU_ALREADY_MEMBER; ffpmsg("Specified HDU is already a member of the Grouping table (ffgtam)"); continue; } else continue; /* if the member HDU is not already recorded in the grouping table then add it */ /* add a new row to the grouping table */ *status = fits_insert_rows(gfptr,nmembers,1,status); ++nmembers; /* retrieve the grouping table column IDs and structure type */ *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol, &locationCol,&uriCol,&grptype,status); /* fill in the member HDU data in the new grouping table row */ *tmpPtr = memberHDUtype; if(xtensionCol != 0) fits_write_col_str(gfptr,xtensionCol,nmembers,1,1,tmpPtr,status); *tmpPtr = memberExtname; if(extnameCol != 0) { if(strlen(memberExtname) != 0) fits_write_col_str(gfptr,extnameCol,nmembers,1,1,tmpPtr,status); else /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/ fits_write_col_byt(gfptr,extnameCol,nmembers,1,1,charNull,status); } if(extverCol != 0) fits_write_col_lng(gfptr,extverCol,nmembers,1,1,&memberExtver, status); if(positionCol != 0) fits_write_col_int(gfptr,positionCol,nmembers,1,1, &memberPosition,status); *tmpPtr = memberFileName; if(locationCol != 0) { /* Change the test for SPR 3463 */ /* Now, if either the Fptr values are the same, or the root filenames are the same, then assume these refer to the same file. */ fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status); fits_parse_rootname(gfptr->Fptr->filename, grootname, status); if((tmpfptr->Fptr != gfptr->Fptr) && strncmp(tmprootname, grootname, FLEN_FILENAME)) fits_write_col_str(gfptr,locationCol,nmembers,1,1,tmpPtr,status); else /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/ fits_write_col_byt(gfptr,locationCol,nmembers,1,1,charNull,status); } *tmpPtr = memberURI; if(uriCol != 0) { /* Change the test for SPR 3463 */ /* Now, if either the Fptr values are the same, or the root filenames are the same, then assume these refer to the same file. */ fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status); fits_parse_rootname(gfptr->Fptr->filename, grootname, status); if((tmpfptr->Fptr != gfptr->Fptr) && strncmp(tmprootname, grootname, FLEN_FILENAME)) fits_write_col_str(gfptr,uriCol,nmembers,1,1,tmpPtr,status); else /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/ fits_write_col_byt(gfptr,uriCol,nmembers,1,1,charNull,status); } } while(0); if(0 != *status) continue; /* add GRPIDn/GRPLCn keywords to the member HDU header to link it to the grouing table if the they do not already exist and the member file is RW */ fits_file_mode(tmpfptr,&iomode,status); if(memberIOstate == 0 || iomode != READWRITE) { ffpmsg("cannot add GRPID/LC keywords to member HDU: (ffgtam)"); ffpmsg(memberFileName); continue; } *status = fits_get_num_groups(tmpfptr,&ngroups,status); /* look for the GRPID/LC keywords in the member HDU; if the keywords for the back-link to the grouping table already exist then no need to add them again */ for(i = 1, found = 0; i <= ngroups && !found && *status == 0; ++i) { snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups); *status = fits_read_key_lng(tmpfptr,keyword,&grpid,card,status); if(grpid == groupExtver) { if(grpid < 0) { /* have to make sure the GRPLCn keyword matches too */ snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)ngroups); /* SPR 1738 */ *status = fits_read_key_longstr(mfptr,keyword,&tgrplc,card, status); if (0 == *status) { strcpy(grplc,tgrplc); free(tgrplc); } /* always compare files using absolute paths the presence of a non-empty cwd indicates that the file names may require conversion to absolute paths */ if(0 < strlen(cwd)) { /* temp buffer for use in assembling abs. path(s) */ char tmp[FLEN_FILENAME]; /* make grplc absolute if necessary */ if(!fits_is_url_absolute(grplc)) { fits_path2url(grplc,FLEN_FILENAME,groupLocation,status); if(groupLocation[0] != '/') { strcpy(tmp, cwd); if (strlen(tmp)+strlen(groupLocation)+1 > FLEN_FILENAME-1) { ffpmsg("path and group location is too long (ffgtam)"); *status = URL_PARSE_ERROR; continue; } strcat(tmp,"/"); strcat(tmp,groupLocation); fits_clean_url(tmp,grplc,status); } } /* make groupFileName absolute if necessary */ if(!fits_is_url_absolute(groupFileName)) { fits_path2url(groupFileName,FLEN_FILENAME,groupLocation,status); if(groupLocation[0] != '/') { strcpy(tmp, cwd); if (strlen(tmp)+strlen(groupLocation)+1 > FLEN_FILENAME-1) { ffpmsg("path and group location is too long (ffgtam)"); *status = URL_PARSE_ERROR; continue; } strcat(tmp,"/"); strcat(tmp,groupLocation); /* note: use groupLocation (which is not used below this block), to store the absolute file name instead of using groupFileName. The latter may be needed unaltered if the GRPLC is written below */ fits_clean_url(tmp,groupLocation,status); } } } /* see if the grplc value and the group file name match */ if(strcmp(grplc,groupLocation) == 0) found = 1; } else { /* the match is found with GRPIDn alone */ found = 1; } } } /* if FOUND is true then no need to continue */ if(found) { ffpmsg("HDU already has GRPID/LC keywords for group table (ffgtam)"); continue; } /* add the GRPID/LC keywords to the member header for this grouping table If NGROUPS == 0 then we must position the header pointer to the record where we want to insert the GRPID/LC keywords (the pointer is already correctly positioned if the above search loop activiated) */ if(ngroups == 0) { /* no GRPIDn/GRPLCn keywords currently exist in header so try to position the header pointer to a desirable position */ for(i = 0, *status = KEY_NO_EXIST; i < nkeys && *status == KEY_NO_EXIST; ++i) { *status = 0; *status = fits_read_card(tmpfptr,keys[i],card,status); } /* all else fails: move write pointer to end of header */ if(*status == KEY_NO_EXIST) { *status = 0; fits_get_hdrspace(tmpfptr,&nkeys,&i,status); ffgrec(tmpfptr,nkeys,card,status); } /* any other error status then abort */ if(*status != 0) continue; } /* now that the header pointer is positioned for the GRPID/LC keyword insertion increment the number of group links counter for the member HDU */ ++ngroups; /* if the member HDU and grouping table reside in the same FITS file then there is no need to add a GRPLCn keyword */ /* SPR 3463 change test */ /* Now, if either the Fptr values are the same, or the root filenames are the same, then assume these refer to the same file. */ fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status); fits_parse_rootname(gfptr->Fptr->filename, grootname, status); if((tmpfptr->Fptr == gfptr->Fptr) || strncmp(tmprootname, grootname, FLEN_FILENAME) == 0) { /* add the GRPIDn keyword only */ snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups); fits_insert_key_lng(tmpfptr,keyword,groupExtver, "EXTVER of Group containing this HDU",status); } else { /* add the GRPIDn and GRPLCn keywords */ snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups); fits_insert_key_lng(tmpfptr,keyword,groupExtver, "EXTVER of Group containing this HDU",status); snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)ngroups); /* SPR 1738 */ fits_insert_key_longstr(tmpfptr,keyword,groupFileName, "URL of file containing Group",status); fits_write_key_longwarn(tmpfptr,status); } }while(0); /* close the tmpfptr pointer if it was opened in this function */ if(mfptr == NULL) { *status = fits_close_file(tmpfptr,status); } *status = 0 == *status ? parentStatus : *status; return(*status); } /*---------------------------------------------------------------------------*/ int ffgtnm(fitsfile *gfptr, /* FITS file pointer to grouping table */ long *nmembers, /* member count of the groping table */ int *status) /* return status code */ /* return the number of member HDUs in a grouping table. The fitsfile pointer gfptr must be positioned with the grouping table as the CHDU. The number of grouping table member HDUs is just the NAXIS2 value of the grouping table. */ { char keyvalue[FLEN_VALUE]; char comment[FLEN_COMMENT]; if(*status != 0) return(*status); *status = fits_read_keyword(gfptr,"EXTNAME",keyvalue,comment,status); if(*status == KEY_NO_EXIST) *status = NOT_GROUP_TABLE; else { prepare_keyvalue(keyvalue); if(fits_strcasecmp(keyvalue,"GROUPING") != 0) { *status = NOT_GROUP_TABLE; ffpmsg("Specified HDU is not a Grouping table (ffgtnm)"); } *status = fits_read_key_lng(gfptr,"NAXIS2",nmembers,comment,status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgmng(fitsfile *mfptr, /* FITS file pointer to member HDU */ long *ngroups, /* total number of groups linked to HDU */ int *status) /* return status code */ /* return the number of groups to which a HDU belongs, as defined by the number of GRPIDn/GRPLCn keyword records that appear in the HDU header. The fitsfile pointer mfptr must be positioned with the member HDU as the CHDU. Each time this function is called, the indicies of the GRPIDn/GRPLCn keywords are checked to make sure they are continuous (ie no gaps) and are re-enumerated to eliminate gaps if gaps are found to be present. */ { int offset; int index; int newIndex; int i; long grpid; char *inclist[] = {"GRPID#"}; char keyword[FLEN_KEYWORD]; char newKeyword[FLEN_KEYWORD]; char card[FLEN_CARD]; char comment[FLEN_COMMENT]; char *tkeyvalue; if(*status != 0) return(*status); *ngroups = 0; /* reset the member HDU keyword counter to the beginning */ *status = ffgrec(mfptr,0,card,status); /* search for the number of GRPIDn keywords in the member HDU header and count them with the ngroups variable */ while(*status == 0) { /* read the next GRPIDn keyword in the series */ *status = fits_find_nextkey(mfptr,inclist,1,NULL,0,card,status); if(*status != 0) continue; ++(*ngroups); } if(*status == KEY_NO_EXIST) *status = 0; /* read each GRPIDn/GRPLCn keyword and adjust their index values so that there are no gaps in the index count */ for(index = 1, offset = 0, i = 1; i <= *ngroups && *status == 0; ++index) { snprintf(keyword,FLEN_KEYWORD,"GRPID%d",index); /* try to read the next GRPIDn keyword in the series */ *status = fits_read_key_lng(mfptr,keyword,&grpid,card,status); /* if not found then increment the offset counter and continue */ if(*status == KEY_NO_EXIST) { *status = 0; ++offset; } else { /* increment the number_keys_found counter and see if the index of the keyword needs to be updated */ ++i; if(offset > 0) { /* compute the new index for the GRPIDn/GRPLCn keywords */ newIndex = index - offset; /* update the GRPIDn keyword index */ snprintf(newKeyword,FLEN_KEYWORD,"GRPID%d",newIndex); fits_modify_name(mfptr,keyword,newKeyword,status); /* If present, update the GRPLCn keyword index */ snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",index); snprintf(newKeyword,FLEN_KEYWORD,"GRPLC%d",newIndex); /* SPR 1738 */ *status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment, status); if (0 == *status) { fits_delete_key(mfptr,keyword,status); fits_insert_key_longstr(mfptr,newKeyword,tkeyvalue,comment,status); fits_write_key_longwarn(mfptr,status); free(tkeyvalue); } if(*status == KEY_NO_EXIST) *status = 0; } } } return(*status); } /*---------------------------------------------------------------------------*/ int ffgmop(fitsfile *gfptr, /* FITS file pointer to grouping table */ long member, /* member ID (row num) within grouping table */ fitsfile **mfptr, /* FITS file pointer to member HDU */ int *status) /* return status code */ /* open a grouping table member, returning a pointer to the member's FITS file with the CHDU set to the member HDU. The grouping table must be the CHDU of the FITS file pointed to by gfptr. The member to open is identified by its row number within the grouping table (first row/member == 1). If the member resides in a FITS file different from the grouping table the member file is first opened readwrite and if this fails then it is opened readonly. For access type of FILE:// the member file is searched for assuming (1) an absolute path is given, (2) a path relative to the CWD is given, and (3) a path relative to the grouping table file but not relative to the CWD is given. If all of these fail then the error FILE_NOT_FOUND is returned. */ { int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol; int grptype,hdutype; int dummy; long hdupos = 0; long extver = 0; char xtension[FLEN_VALUE]; char extname[FLEN_VALUE]; char uri[FLEN_VALUE]; char grpLocation1[FLEN_FILENAME]; char grpLocation2[FLEN_FILENAME]; char mbrLocation1[FLEN_FILENAME]; char mbrLocation2[FLEN_FILENAME]; char mbrLocation3[FLEN_FILENAME]; char cwd[FLEN_FILENAME]; char card[FLEN_CARD]; char nstr[] = {'\0'}; char *tmpPtr[1]; if(*status != 0) return(*status); do { /* retrieve the Grouping Convention reserved column positions within the grouping table */ *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol, &locationCol,&uriCol,&grptype,status); if(*status != 0) continue; /* verify the column formats */ *status = ffvcfm(gfptr,xtensionCol,extnameCol,extverCol,positionCol, locationCol,uriCol,status); if(*status != 0) continue; /* extract the member information from grouping table */ tmpPtr[0] = xtension; if(xtensionCol != 0) { *status = fits_read_col_str(gfptr,xtensionCol,member,1,1,nstr, tmpPtr,&dummy,status); /* convert the xtension string to a hdutype code */ if(fits_strcasecmp(xtension,"PRIMARY") == 0) hdutype = IMAGE_HDU; else if(fits_strcasecmp(xtension,"IMAGE") == 0) hdutype = IMAGE_HDU; else if(fits_strcasecmp(xtension,"TABLE") == 0) hdutype = ASCII_TBL; else if(fits_strcasecmp(xtension,"BINTABLE") == 0) hdutype = BINARY_TBL; else hdutype = ANY_HDU; } tmpPtr[0] = extname; if(extnameCol != 0) *status = fits_read_col_str(gfptr,extnameCol,member,1,1,nstr, tmpPtr,&dummy,status); if(extverCol != 0) *status = fits_read_col_lng(gfptr,extverCol,member,1,1,0, (long*)&extver,&dummy,status); if(positionCol != 0) *status = fits_read_col_lng(gfptr,positionCol,member,1,1,0, (long*)&hdupos,&dummy,status); tmpPtr[0] = mbrLocation1; if(locationCol != 0) *status = fits_read_col_str(gfptr,locationCol,member,1,1,nstr, tmpPtr,&dummy,status); tmpPtr[0] = uri; if(uriCol != 0) *status = fits_read_col_str(gfptr,uriCol,member,1,1,nstr, tmpPtr,&dummy,status); if(*status != 0) continue; /* decide what FITS file the member HDU resides in and open the file using the fitsfile* pointer mfptr; note that this logic is rather complicated and is based primiarly upon if a URL specifier is given for the member file in the grouping table */ switch(grptype) { case GT_ID_POS: case GT_ID_REF: case GT_ID_ALL: /* no location information is given so we must assume that the member HDU resides in the same FITS file as the grouping table; if the grouping table was incorrectly constructed then this assumption will be false, but there is nothing to be done about it at this point */ *status = fits_reopen_file(gfptr,mfptr,status); break; case GT_ID_REF_URI: case GT_ID_POS_URI: case GT_ID_ALL_URI: /* The member location column exists. Determine if the member resides in the same file as the grouping table or in a separate file; open the member file in either case */ if(strlen(mbrLocation1) == 0) { /* since no location information was given we must assume that the member is in the same FITS file as the grouping table */ *status = fits_reopen_file(gfptr,mfptr,status); } else { /* make sure the location specifiation is "URL"; we cannot decode any other URI types at this time */ if(fits_strcasecmp(uri,"URL") != 0) { *status = FILE_NOT_OPENED; snprintf(card,FLEN_CARD, "Cannot open member HDU file with URI type %s (ffgmop)", uri); ffpmsg(card); continue; } /* The location string for the member is not NULL, so it does not necessially reside in the same FITS file as the grouping table. Three cases are attempted for opening the member's file in the following order: 1. The URL given for the member's file is absolute (i.e., access method supplied); try to open the member 2. The URL given for the member's file is not absolute but is an absolute file path; try to open the member as a file after the file path is converted to a host-dependent form 3. The URL given for the member's file is not absolute and is given as a relative path to the location of the grouping table's file. Create an absolute URL using the grouping table's file URL and try to open the member. If all three cases fail then an error is returned. In each case the file is first opened in read/write mode and failing that readonly mode. The following DO loop is only used as a mechanism to break (continue) when the proper file opening method is found */ do { /* CASE 1: See if the member URL is absolute (i.e., includes a access directive) and if so open the file */ if(fits_is_url_absolute(mbrLocation1)) { /* the URL must specify an access method, which implies that its an absolute reference regardless of the access method, pass the whole URL to the open function for processing */ ffpmsg("member URL is absolute, try open R/W (ffgmop)"); *status = fits_open_file(mfptr,mbrLocation1,READWRITE, status); if(*status == 0) continue; *status = 0; /* now try to open file using full URL specs in readonly mode */ ffpmsg("OK, now try to open read-only (ffgmop)"); *status = fits_open_file(mfptr,mbrLocation1,READONLY, status); /* break from DO loop regardless of status */ continue; } /* CASE 2: If we got this far then the member URL location has no access type ==> FILE:// Try to open the member file using the URL as is, i.e., assume that it is given as absolute, if it starts with a '/' character */ ffpmsg("Member URL is of type FILE (ffgmop)"); if(*mbrLocation1 == '/') { ffpmsg("Member URL specifies abs file path (ffgmop)"); /* convert the URL path to a host dependent path */ *status = fits_url2path(mbrLocation1,mbrLocation2, status); ffpmsg("Try to open member URL in R/W mode (ffgmop)"); *status = fits_open_file(mfptr,mbrLocation2,READWRITE, status); if(*status == 0) continue; *status = 0; /* now try to open file using the URL as an absolute path in readonly mode */ ffpmsg("OK, now try to open read-only (ffgmop)"); *status = fits_open_file(mfptr,mbrLocation2,READONLY, status); /* break from the Do loop regardless of the status */ continue; } /* CASE 3: If we got this far then the URL does not specify an absoulte file path or URL with access method. Since the path to the group table's file is (obviously) valid for the CWD, create a full location string for the member HDU using the grouping table URL as a basis The only problem is that the grouping table file might have two URLs, the original one used to open it and the one that points to the real file being accessed (i.e., a file accessed via HTTP but transferred to a local disk file). Have to attempt to build a URL to the member HDU file using both of these URLs if defined. */ ffpmsg("Try to open member file as relative URL (ffgmop)"); /* get the URL information for the grouping table file */ *status = fits_get_url(gfptr,grpLocation1,grpLocation2, NULL,NULL,NULL,status); /* if the "real" grouping table file URL is defined then build a full url for the member HDU file using it and try to open the member HDU file */ if(*grpLocation1) { /* make sure the group location is absolute */ if(! fits_is_url_absolute(grpLocation1) && *grpLocation1 != '/') { fits_get_cwd(cwd,status); strcat(cwd,"/"); if (strlen(cwd)+strlen(grpLocation1)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and group location1 is too long (ffgmop)"); *status = URL_PARSE_ERROR; continue; } strcat(cwd,grpLocation1); strcpy(grpLocation1,cwd); } /* create a full URL for the member HDU file */ *status = fits_relurl2url(grpLocation1,mbrLocation1, mbrLocation2,status); if(*status != 0) continue; /* if the URL does not have an access method given then translate it into a host dependent file path */ if(! fits_is_url_absolute(mbrLocation2)) { *status = fits_url2path(mbrLocation2,mbrLocation3, status); strcpy(mbrLocation2,mbrLocation3); } /* try to open the member file READWRITE */ *status = fits_open_file(mfptr,mbrLocation2,READWRITE, status); if(*status == 0) continue; *status = 0; /* now try to open in readonly mode */ ffpmsg("now try to open file as READONLY (ffgmop)"); *status = fits_open_file(mfptr,mbrLocation2,READONLY, status); if(*status == 0) continue; *status = 0; } /* if we got this far then either the "real" grouping table file URL was not defined or all attempts to open the resulting member HDU file URL failed. if the "original" grouping table file URL is defined then build a full url for the member HDU file using it and try to open the member HDU file */ if(*grpLocation2) { /* make sure the group location is absolute */ if(! fits_is_url_absolute(grpLocation2) && *grpLocation2 != '/') { fits_get_cwd(cwd,status); if (strlen(cwd)+strlen(grpLocation2)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and group location2 is too long (ffgmop)"); *status = URL_PARSE_ERROR; continue; } strcat(cwd,"/"); strcat(cwd,grpLocation2); strcpy(grpLocation2,cwd); } /* create an absolute URL for the member HDU file */ *status = fits_relurl2url(grpLocation2,mbrLocation1, mbrLocation2,status); if(*status != 0) continue; /* if the URL does not have an access method given then translate it into a host dependent file path */ if(! fits_is_url_absolute(mbrLocation2)) { *status = fits_url2path(mbrLocation2,mbrLocation3, status); strcpy(mbrLocation2,mbrLocation3); } /* try to open the member file READWRITE */ *status = fits_open_file(mfptr,mbrLocation2,READWRITE, status); if(*status == 0) continue; *status = 0; /* now try to open in readonly mode */ ffpmsg("now try to open file as READONLY (ffgmop)"); *status = fits_open_file(mfptr,mbrLocation2,READONLY, status); if(*status == 0) continue; *status = 0; } /* if we got this far then the member HDU file could not be opened using any method. Log the error. */ ffpmsg("Cannot open member HDU FITS file (ffgmop)"); *status = MEMBER_NOT_FOUND; }while(0); } break; default: /* no default action */ break; } if(*status != 0) continue; /* attempt to locate the member HDU within its FITS file as determined and opened above */ switch(grptype) { case GT_ID_POS: case GT_ID_POS_URI: /* try to find the member hdu in the the FITS file pointed to by mfptr based upon its HDU posistion value. Note that is impossible to verify if the HDU is actually the correct HDU due to a lack of information. */ *status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,status); break; case GT_ID_REF: case GT_ID_REF_URI: /* try to find the member hdu in the FITS file pointed to by mfptr based upon its XTENSION, EXTNAME and EXTVER keyword values */ *status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status); if(*status == BAD_HDU_NUM) { *status = MEMBER_NOT_FOUND; ffpmsg("Cannot find specified member HDU (ffgmop)"); } /* if the above function returned without error then the mfptr is pointed to the member HDU */ break; case GT_ID_ALL: case GT_ID_ALL_URI: /* if the member entry has reference information then use it (ID by reference is safer than ID by position) else use the position information */ if(strlen(xtension) > 0 && strlen(extname) > 0 && extver > 0) { /* valid reference info exists so use it */ /* try to find the member hdu in the grouping table's file */ *status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status); if(*status == BAD_HDU_NUM) { *status = MEMBER_NOT_FOUND; ffpmsg("Cannot find specified member HDU (ffgmop)"); } } else { *status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype, status); if(*status == END_OF_FILE) *status = MEMBER_NOT_FOUND; } /* if the above function returned without error then the mfptr is pointed to the member HDU */ break; default: /* no default action */ break; } }while(0); if(*status != 0 && *mfptr != NULL) { fits_close_file(*mfptr,status); } return(*status); } /*---------------------------------------------------------------------------*/ int ffgmcp(fitsfile *gfptr, /* FITS file pointer to group */ fitsfile *mfptr, /* FITS file pointer to new member FITS file */ long member, /* member ID (row num) within grouping table */ int cpopt, /* code specifying copy options: OPT_MCP_ADD (0) ==> add copied member to the grouping table OPT_MCP_NADD (1) ==> do not add member copy to the grouping table OPT_MCP_REPL (2) ==> replace current member entry with member copy */ int *status) /* return status code */ /* copy a member HDU of a grouping table to a new FITS file. The grouping table must be the CHDU of the FITS file pointed to by gfptr. The copy of the group member shall be appended to the end of the FITS file pointed to by mfptr. If the cpopt parameter is set to OPT_MCP_ADD then the copy of the member is added to the grouping table as a new member, if OPT_MCP_NADD then the copied member is not added to the grouping table, and if OPT_MCP_REPL then the copied member is used to replace the original member. The copied member HDU also has its EXTVER value updated so that its combination of XTENSION, EXTNAME and EXVTER is unique within its new FITS file. */ { int numkeys = 0; int keypos = 0; int hdunum = 0; int hdutype = 0; int i; char *incList[] = {"GRPID#","GRPLC#"}; char extname[FLEN_VALUE]; char card[FLEN_CARD]; char comment[FLEN_COMMENT]; char keyname[FLEN_CARD]; char value[FLEN_CARD]; fitsfile *tmpfptr = NULL; if(*status != 0) return(*status); do { /* open the member HDU to be copied */ *status = fits_open_member(gfptr,member,&tmpfptr,status); if(*status != 0) continue; /* if the member is a grouping table then copy it with a call to fits_copy_group() using the "copy only the grouping table" option if it is not a grouping table then copy the hdu with fits_copy_hdu() remove all GRPIDn and GRPLCn keywords, and update the EXTVER keyword value */ /* get the member HDU's EXTNAME value */ *status = fits_read_key_str(tmpfptr,"EXTNAME",extname,comment,status); /* if no EXTNAME value was found then set the extname to a null string */ if(*status == KEY_NO_EXIST) { extname[0] = 0; *status = 0; } else if(*status != 0) continue; prepare_keyvalue(extname); /* if a grouping table then copy with fits_copy_group() */ if(fits_strcasecmp(extname,"GROUPING") == 0) *status = fits_copy_group(tmpfptr,mfptr,OPT_GCP_GPT,status); else { /* copy the non-grouping table HDU the conventional way */ *status = fits_copy_hdu(tmpfptr,mfptr,0,status); ffgrec(mfptr,0,card,status); /* delete all the GRPIDn and GRPLCn keywords in the copied HDU */ while(*status == 0) { *status = fits_find_nextkey(mfptr,incList,2,NULL,0,card,status); *status = fits_get_hdrpos(mfptr,&numkeys,&keypos,status); /* SPR 1738 */ *status = fits_read_keyn(mfptr,keypos-1,keyname,value, comment,status); *status = fits_read_record(mfptr,keypos-1,card,status); *status = fits_delete_key(mfptr,keyname,status); } if(*status == KEY_NO_EXIST) *status = 0; if(*status != 0) continue; } /* if the member HDU does not have an EXTNAME keyword then add one with a default value */ if(strlen(extname) == 0) { if(fits_get_hdu_num(tmpfptr,&hdunum) == 1) { strcpy(extname,"PRIMARY"); *status = fits_write_key_str(mfptr,"EXTNAME",extname, "HDU was Formerly a Primary Array", status); } else { strcpy(extname,"DEFAULT"); *status = fits_write_key_str(mfptr,"EXTNAME",extname, "default EXTNAME set by CFITSIO", status); } } /* update the member HDU's EXTVER value (add it if not present) */ fits_get_hdu_num(mfptr,&hdunum); fits_get_hdu_type(mfptr,&hdutype,status); /* set the EXTVER value to 0 for now */ *status = fits_modify_key_lng(mfptr,"EXTVER",0,NULL,status); /* if the EXTVER keyword was not found then add it */ if(*status == KEY_NO_EXIST) { *status = 0; *status = fits_read_key_str(mfptr,"EXTNAME",extname,comment, status); *status = fits_insert_key_lng(mfptr,"EXTVER",0, "Extension version ID",status); } if(*status != 0) continue; /* find the first available EXTVER value for the copied HDU */ for(i = 1; fits_movnam_hdu(mfptr,hdutype,extname,i,status) == 0; ++i); *status = 0; fits_movabs_hdu(mfptr,hdunum,&hdutype,status); /* reset the copied member HDUs EXTVER value */ *status = fits_modify_key_lng(mfptr,"EXTVER",(long)i,NULL,status); /* perform member copy operations that are dependent upon the cpopt parameter value */ switch(cpopt) { case OPT_MCP_ADD: /* add the copied member to the grouping table, leaving the entry for the original member in place */ *status = fits_add_group_member(gfptr,mfptr,0,status); break; case OPT_MCP_NADD: /* nothing to do for this copy option */ break; case OPT_MCP_REPL: /* remove the original member from the grouping table and add the copied member in its place */ *status = fits_remove_member(gfptr,member,OPT_RM_ENTRY,status); *status = fits_add_group_member(gfptr,mfptr,0,status); break; default: *status = BAD_OPTION; ffpmsg("Invalid value specified for the cmopt parameter (ffgmcp)"); break; } }while(0); if(tmpfptr != NULL) { fits_close_file(tmpfptr,status); } return(*status); } /*---------------------------------------------------------------------------*/ int ffgmtf(fitsfile *infptr, /* FITS file pointer to source grouping table */ fitsfile *outfptr, /* FITS file pointer to target grouping table */ long member, /* member ID within source grouping table */ int tfopt, /* code specifying transfer opts: OPT_MCP_ADD (0) ==> copy member to dest. OPT_MCP_MOV (3) ==> move member to dest. */ int *status) /* return status code */ /* transfer a group member from one grouping table to another. The source grouping table must be the CHDU of the fitsfile pointed to by infptr, and the destination grouping table must be the CHDU of the fitsfile to by outfptr. If the tfopt parameter is OPT_MCP_ADD then the member is made a member of the target group and remains a member of the source group. If the tfopt parameter is OPT_MCP_MOV then the member is deleted from the source group after the transfer to the destination group. The member to be transfered is identified by its row number within the source grouping table. */ { fitsfile *mfptr = NULL; if(*status != 0) return(*status); if(tfopt != OPT_MCP_MOV && tfopt != OPT_MCP_ADD) { *status = BAD_OPTION; ffpmsg("Invalid value specified for the tfopt parameter (ffgmtf)"); } else { /* open the member of infptr to be transfered */ *status = fits_open_member(infptr,member,&mfptr,status); /* add the member to the outfptr grouping table */ *status = fits_add_group_member(outfptr,mfptr,0,status); /* close the member HDU */ *status = fits_close_file(mfptr,status); /* if the tfopt is "move member" then remove it from the infptr grouping table */ if(tfopt == OPT_MCP_MOV) *status = fits_remove_member(infptr,member,OPT_RM_ENTRY,status); } return(*status); } /*---------------------------------------------------------------------------*/ int ffgmrm(fitsfile *gfptr, /* FITS file pointer to group table */ long member, /* member ID (row num) in the group */ int rmopt, /* code specifying the delete option: OPT_RM_ENTRY ==> delete the member entry OPT_RM_MBR ==> delete entry and member HDU */ int *status) /* return status code */ /* remove a member HDU from a grouping table. The fitsfile pointer gfptr must be positioned with the grouping table as the CHDU, and the member to delete is identified by its row number in the table (first member == 1). The rmopt parameter determines if the member entry is deleted from the grouping table (in which case GRPIDn and GRPLCn keywords in the member HDU's header shall be updated accordingly) or if the member HDU shall itself be removed from its FITS file. */ { int found; int hdutype = 0; int index; int iomode = 0; long i; long ngroups = 0; long nmembers = 0; long groupExtver = 0; long grpid = 0; char grpLocation1[FLEN_FILENAME]; char grpLocation2[FLEN_FILENAME]; char grpLocation3[FLEN_FILENAME]; char cwd[FLEN_FILENAME]; char keyword[FLEN_KEYWORD]; /* SPR 1738 This can now be longer */ char grplc[FLEN_FILENAME]; char *tgrplc; char keyvalue[FLEN_VALUE]; char card[FLEN_CARD]; char *editLocation; char mrootname[FLEN_FILENAME], grootname[FLEN_FILENAME]; fitsfile *mfptr = NULL; if(*status != 0) return(*status); do { /* make sure the grouping table can be modified before proceeding */ fits_file_mode(gfptr,&iomode,status); if(iomode != READWRITE) { ffpmsg("cannot modify grouping table (ffgtam)"); *status = BAD_GROUP_DETACH; continue; } /* open the group member to be deleted and get its IOstatus*/ *status = fits_open_member(gfptr,member,&mfptr,status); *status = fits_file_mode(mfptr,&iomode,status); /* if the member HDU is to be deleted then call fits_unlink_member() to remove it from all groups to which it belongs (including this one) and then delete it. Note that if the member is a grouping table then we have to recursively call fits_remove_member() for each member of the member before we delete the member itself. */ if(rmopt == OPT_RM_MBR) { /* cannot delete a PHDU */ if(fits_get_hdu_num(mfptr,&hdutype) == 1) { *status = BAD_HDU_NUM; continue; } /* determine if the member HDU is itself a grouping table */ *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,status); /* if no EXTNAME is found then the HDU cannot be a grouping table */ if(*status == KEY_NO_EXIST) { keyvalue[0] = 0; *status = 0; } prepare_keyvalue(keyvalue); /* Any other error is a reason to abort */ if(*status != 0) continue; /* if the EXTNAME == GROUPING then the member is a grouping table */ if(fits_strcasecmp(keyvalue,"GROUPING") == 0) { /* remove each of the grouping table members */ *status = fits_get_num_members(mfptr,&nmembers,status); for(i = nmembers; i > 0 && *status == 0; --i) *status = fits_remove_member(mfptr,i,OPT_RM_ENTRY,status); if(*status != 0) continue; } /* unlink the member HDU from all groups that contain it */ *status = ffgmul(mfptr,0,status); if(*status != 0) continue; /* reset the grouping table HDU struct */ fits_set_hdustruc(gfptr,status); /* delete the member HDU */ if(iomode != READONLY) *status = fits_delete_hdu(mfptr,&hdutype,status); } else if(rmopt == OPT_RM_ENTRY) { /* The member HDU is only to be removed as an entry from this grouping table. Actions are (1) find the GRPIDn/GRPLCn keywords that link the member to the grouping table, (2) remove the GRPIDn/GRPLCn keyword from the member HDU header and (3) remove the member entry from the grouping table */ /* there is no need to seach for and remove the GRPIDn/GRPLCn keywords from the member HDU if it has not been opened in READWRITE mode */ if(iomode == READWRITE) { /* determine the group EXTVER value of the grouping table; if the member HDU and grouping table HDU do not reside in the same file then set the groupExtver value to its negative */ *status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card, status); /* Now, if either the Fptr values are the same, or the root filenames are the same, then assume these refer to the same file. */ fits_parse_rootname(mfptr->Fptr->filename, mrootname, status); fits_parse_rootname(gfptr->Fptr->filename, grootname, status); if((mfptr->Fptr != gfptr->Fptr) && strncmp(mrootname, grootname, FLEN_FILENAME)) groupExtver = -1*groupExtver; /* retrieve the URLs for the grouping table; note that it is possible that the grouping table file has two URLs, the one used to open it and the "real" one pointing to the actual file being accessed */ *status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL, NULL,NULL,status); if(*status != 0) continue; /* if either of the group location strings specify a relative file path then convert them into absolute file paths */ *status = fits_get_cwd(cwd,status); if(*grpLocation1 != 0 && *grpLocation1 != '/' && !fits_is_url_absolute(grpLocation1)) { strcpy(grpLocation3,cwd); if (strlen(grpLocation3)+strlen(grpLocation1)+1 > FLEN_FILENAME-1) { ffpmsg("group locations are too long (ffgmrm)"); *status = URL_PARSE_ERROR; continue; } strcat(grpLocation3,"/"); strcat(grpLocation3,grpLocation1); fits_clean_url(grpLocation3,grpLocation1,status); } if(*grpLocation2 != 0 && *grpLocation2 != '/' && !fits_is_url_absolute(grpLocation2)) { strcpy(grpLocation3,cwd); if (strlen(grpLocation3)+strlen(grpLocation2)+1 > FLEN_FILENAME-1) { ffpmsg("group locations are too long (ffgmrm)"); *status = URL_PARSE_ERROR; continue; } strcat(grpLocation3,"/"); strcat(grpLocation3,grpLocation2); fits_clean_url(grpLocation3,grpLocation2,status); } /* determine the number of groups to which the member HDU belongs */ *status = fits_get_num_groups(mfptr,&ngroups,status); /* reset the HDU keyword position counter to the beginning */ *status = ffgrec(mfptr,0,card,status); /* loop over all the GRPIDn keywords in the member HDU header and find the appropriate GRPIDn and GRPLCn keywords that identify it as belonging to the group */ for(index = 1, found = 0; index <= ngroups && *status == 0 && !found; ++index) { /* read the next GRPIDn keyword in the series */ snprintf(keyword,FLEN_KEYWORD,"GRPID%d",index); *status = fits_read_key_lng(mfptr,keyword,&grpid,card, status); if(*status != 0) continue; /* grpid value == group EXTVER value then we could have a match */ if(grpid == groupExtver && grpid > 0) { /* if GRPID is positive then its a match because both the member HDU and grouping table HDU reside in the same FITS file */ found = index; } else if(grpid == groupExtver && grpid < 0) { /* have to look at the GRPLCn value to determine a match because the member HDU and grouping table HDU reside in different FITS files */ snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",index); /* SPR 1738 */ *status = fits_read_key_longstr(mfptr,keyword,&tgrplc, card, status); if (0 == *status) { strcpy(grplc,tgrplc); free(tgrplc); } if(*status == KEY_NO_EXIST) { /* no GRPLCn keyword value found ==> grouping convention not followed; nothing we can do about it, so just continue */ snprintf(card,FLEN_CARD,"No GRPLC%d found for GRPID%d", index,index); ffpmsg(card); *status = 0; continue; } else if (*status != 0) continue; /* construct the URL for the GRPLCn value */ prepare_keyvalue(grplc); /* if the grplc value specifies a relative path then turn it into a absolute file path for comparison purposes */ if(*grplc != 0 && !fits_is_url_absolute(grplc) && *grplc != '/') { /* No, wrong, strcpy(grpLocation3,cwd); should be */ *status = fits_file_name(mfptr,grpLocation3,status); /* Remove everything after the last / */ if (NULL != (editLocation = strrchr(grpLocation3,'/'))) { *editLocation = '\0'; } if (strlen(grpLocation3)+strlen(grplc)+1 > FLEN_FILENAME-1) { ffpmsg("group locations are too long (ffgmrm)"); *status = URL_PARSE_ERROR; continue; } strcat(grpLocation3,"/"); strcat(grpLocation3,grplc); *status = fits_clean_url(grpLocation3,grplc, status); } /* if the absolute value of GRPIDn is equal to the EXTVER value of the grouping table and (one of the possible two) grouping table file URL matches the GRPLCn keyword value then we hava a match */ if(strcmp(grplc,grpLocation1) == 0 || strcmp(grplc,grpLocation2) == 0) found = index; } } /* if found == 0 (false) after the above search then we assume that it is due to an inpromper updating of the GRPIDn and GRPLCn keywords in the member header ==> nothing to delete in the header. Else delete the GRPLCn and GRPIDn keywords that identify the member HDU with the group HDU and re-enumerate the remaining GRPIDn and GRPLCn keywords */ if(found != 0) { snprintf(keyword,FLEN_KEYWORD,"GRPID%d",found); *status = fits_delete_key(mfptr,keyword,status); snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",found); *status = fits_delete_key(mfptr,keyword,status); *status = 0; /* call fits_get_num_groups() to re-enumerate the GRPIDn */ *status = fits_get_num_groups(mfptr,&ngroups,status); } } /* finally, remove the member entry from the current grouping table pointed to by gfptr */ *status = fits_delete_rows(gfptr,member,1,status); } else { *status = BAD_OPTION; ffpmsg("Invalid value specified for the rmopt parameter (ffgmrm)"); } }while(0); if(mfptr != NULL) { fits_close_file(mfptr,status); } return(*status); } /*--------------------------------------------------------------------------- Grouping Table support functions ---------------------------------------------------------------------------*/ int ffgtgc(fitsfile *gfptr, /* pointer to the grouping table */ int *xtensionCol, /* column ID of the MEMBER_XTENSION column */ int *extnameCol, /* column ID of the MEMBER_NAME column */ int *extverCol, /* column ID of the MEMBER_VERSION column */ int *positionCol, /* column ID of the MEMBER_POSITION column */ int *locationCol, /* column ID of the MEMBER_LOCATION column */ int *uriCol, /* column ID of the MEMBER_URI_TYPE column */ int *grptype, /* group structure type code specifying the grouping table columns that are defined: GT_ID_ALL_URI (0) ==> all columns defined GT_ID_REF (1) ==> reference cols only GT_ID_POS (2) ==> position col only GT_ID_ALL (3) ==> ref & pos cols GT_ID_REF_URI (11) ==> ref & loc cols GT_ID_POS_URI (12) ==> pos & loc cols */ int *status) /* return status code */ /* examine the grouping table pointed to by gfptr and determine the column index ID of each possible grouping column. If a column is not found then an index of 0 is returned. the grptype parameter returns the structure of the grouping table ==> what columns are defined. */ { char keyvalue[FLEN_VALUE]; char comment[FLEN_COMMENT]; if(*status != 0) return(*status); do { /* if the HDU does not have an extname of "GROUPING" then it is not a grouping table */ *status = fits_read_key_str(gfptr,"EXTNAME",keyvalue,comment,status); if(*status == KEY_NO_EXIST) { *status = NOT_GROUP_TABLE; ffpmsg("Specified HDU is not a Grouping Table (ffgtgc)"); } if(*status != 0) continue; prepare_keyvalue(keyvalue); if(fits_strcasecmp(keyvalue,"GROUPING") != 0) { *status = NOT_GROUP_TABLE; continue; } /* search for the MEMBER_XTENSION, MEMBER_NAME, MEMBER_VERSION, MEMBER_POSITION, MEMBER_LOCATION and MEMBER_URI_TYPE columns and determine their column index ID */ *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_XTENSION",xtensionCol, status); if(*status == COL_NOT_FOUND) { *status = 0; *xtensionCol = 0; } if(*status != 0) continue; *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_NAME",extnameCol,status); if(*status == COL_NOT_FOUND) { *status = 0; *extnameCol = 0; } if(*status != 0) continue; *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_VERSION",extverCol, status); if(*status == COL_NOT_FOUND) { *status = 0; *extverCol = 0; } if(*status != 0) continue; *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_POSITION",positionCol, status); if(*status == COL_NOT_FOUND) { *status = 0; *positionCol = 0; } if(*status != 0) continue; *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_LOCATION",locationCol, status); if(*status == COL_NOT_FOUND) { *status = 0; *locationCol = 0; } if(*status != 0) continue; *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_URI_TYPE",uriCol, status); if(*status == COL_NOT_FOUND) { *status = 0; *uriCol = 0; } if(*status != 0) continue; /* determine the type of grouping table structure used by this grouping table and record it in the grptype parameter */ if(*xtensionCol && *extnameCol && *extverCol && *positionCol && *locationCol && *uriCol) *grptype = GT_ID_ALL_URI; else if(*xtensionCol && *extnameCol && *extverCol && *locationCol && *uriCol) *grptype = GT_ID_REF_URI; else if(*xtensionCol && *extnameCol && *extverCol && *positionCol) *grptype = GT_ID_ALL; else if(*xtensionCol && *extnameCol && *extverCol) *grptype = GT_ID_REF; else if(*positionCol && *locationCol && *uriCol) *grptype = GT_ID_POS_URI; else if(*positionCol) *grptype = GT_ID_POS; else *status = NOT_GROUP_TABLE; }while(0); /* if the table contained more than one column with a reserved name then this cannot be considered a vailid grouping table */ if(*status == COL_NOT_UNIQUE) { *status = NOT_GROUP_TABLE; ffpmsg("Specified HDU has multipule Group table cols defined (ffgtgc)"); } return(*status); } /*****************************************************************************/ int ffvcfm(fitsfile *gfptr, int xtensionCol, int extnameCol, int extverCol, int positionCol, int locationCol, int uriCol, int *status) { /* Perform validation on column formats to ensure this matches the grouping format the get functions expect. Particularly want to check widths of string columns. */ int typecode=0; long repeat=0, width=0; if (*status != 0) return (*status); do { if (xtensionCol) { fits_get_coltype(gfptr, xtensionCol, &typecode, &repeat, &width, status); if (*status || typecode != TSTRING || repeat != width || repeat > 8) { if (*status==0) *status=NOT_GROUP_TABLE; ffpmsg("Wrong format for Grouping xtension col. (ffvcfm)"); continue; } } if (extnameCol) { fits_get_coltype(gfptr, extnameCol, &typecode, &repeat, &width, status); if (*status || typecode != TSTRING || repeat != width || repeat > 32) { if (*status==0) *status=NOT_GROUP_TABLE; ffpmsg("Wrong format for Grouping name col. (ffvcfm)"); continue; } } if (extverCol) { fits_get_coltype(gfptr, extverCol, &typecode, &repeat, &width, status); if (*status || typecode != TINT32BIT || repeat > 1) { if (*status==0) *status=NOT_GROUP_TABLE; ffpmsg("Wrong format for Grouping version col. (ffvcfm)"); continue; } } if (positionCol) { fits_get_coltype(gfptr, positionCol, &typecode, &repeat, &width, status); if (*status || typecode != TINT32BIT || repeat > 1) { if (*status==0) *status=NOT_GROUP_TABLE; ffpmsg("Wrong format for Grouping position col. (ffvcfm)"); continue; } } if (locationCol) { fits_get_coltype(gfptr, locationCol, &typecode, &repeat, &width, status); if (*status || typecode != TSTRING || repeat != width || repeat > 256) { if (*status==0) *status=NOT_GROUP_TABLE; ffpmsg("Wrong format for Grouping location col. (ffvcfm)"); continue; } } if (uriCol) { fits_get_coltype(gfptr, uriCol, &typecode, &repeat, &width, status); if (*status || typecode != TSTRING || repeat != width || repeat > 3) { if (*status==0) *status=NOT_GROUP_TABLE; ffpmsg("Wrong format for Grouping URI col. (ffvcfm)"); continue; } } } while (0); return (*status); } /*****************************************************************************/ int ffgtdc(int grouptype, /* code specifying the type of grouping table information: GT_ID_ALL_URI 0 ==> defualt (all columns) GT_ID_REF 1 ==> ID by reference GT_ID_POS 2 ==> ID by position GT_ID_ALL 3 ==> ID by ref. and position GT_ID_REF_URI 11 ==> (1) + URI info GT_ID_POS_URI 12 ==> (2) + URI info */ int xtensioncol, /* does MEMBER_XTENSION already exist? */ int extnamecol, /* does MEMBER_NAME aleady exist? */ int extvercol, /* does MEMBER_VERSION already exist? */ int positioncol, /* does MEMBER_POSITION already exist? */ int locationcol, /* does MEMBER_LOCATION already exist? */ int uricol, /* does MEMBER_URI_TYPE aleardy exist? */ char *ttype[], /* array of grouping table column TTYPE names to define (if *col var false) */ char *tform[], /* array of grouping table column TFORM values to define (if*col variable false) */ int *ncols, /* number of TTYPE and TFORM values returned */ int *status) /* return status code */ /* create the TTYPE and TFORM values for the grouping table according to the value of the grouptype parameter and the values of the *col flags. The resulting TTYPE and TFORM are returned in ttype[] and tform[] respectively. The number of TTYPE and TFORMs returned is given by ncols. Both the TTYPE[] and TTFORM[] arrays must contain enough pre-allocated strings to hold the returned information. */ { int i = 0; char xtension[] = "MEMBER_XTENSION"; char xtenTform[] = "8A"; char name[] = "MEMBER_NAME"; char nameTform[] = "32A"; char version[] = "MEMBER_VERSION"; char verTform[] = "1J"; char position[] = "MEMBER_POSITION"; char posTform[] = "1J"; char URI[] = "MEMBER_URI_TYPE"; char URITform[] = "3A"; char location[] = "MEMBER_LOCATION"; /* SPR 01720, move from 160A to 256A */ char locTform[] = "256A"; if(*status != 0) return(*status); switch(grouptype) { case GT_ID_ALL_URI: if(xtensioncol == 0) { strcpy(ttype[i],xtension); strcpy(tform[i],xtenTform); ++i; } if(extnamecol == 0) { strcpy(ttype[i],name); strcpy(tform[i],nameTform); ++i; } if(extvercol == 0) { strcpy(ttype[i],version); strcpy(tform[i],verTform); ++i; } if(positioncol == 0) { strcpy(ttype[i],position); strcpy(tform[i],posTform); ++i; } if(locationcol == 0) { strcpy(ttype[i],location); strcpy(tform[i],locTform); ++i; } if(uricol == 0) { strcpy(ttype[i],URI); strcpy(tform[i],URITform); ++i; } break; case GT_ID_REF: if(xtensioncol == 0) { strcpy(ttype[i],xtension); strcpy(tform[i],xtenTform); ++i; } if(extnamecol == 0) { strcpy(ttype[i],name); strcpy(tform[i],nameTform); ++i; } if(extvercol == 0) { strcpy(ttype[i],version); strcpy(tform[i],verTform); ++i; } break; case GT_ID_POS: if(positioncol == 0) { strcpy(ttype[i],position); strcpy(tform[i],posTform); ++i; } break; case GT_ID_ALL: if(xtensioncol == 0) { strcpy(ttype[i],xtension); strcpy(tform[i],xtenTform); ++i; } if(extnamecol == 0) { strcpy(ttype[i],name); strcpy(tform[i],nameTform); ++i; } if(extvercol == 0) { strcpy(ttype[i],version); strcpy(tform[i],verTform); ++i; } if(positioncol == 0) { strcpy(ttype[i],position); strcpy(tform[i], posTform); ++i; } break; case GT_ID_REF_URI: if(xtensioncol == 0) { strcpy(ttype[i],xtension); strcpy(tform[i],xtenTform); ++i; } if(extnamecol == 0) { strcpy(ttype[i],name); strcpy(tform[i],nameTform); ++i; } if(extvercol == 0) { strcpy(ttype[i],version); strcpy(tform[i],verTform); ++i; } if(locationcol == 0) { strcpy(ttype[i],location); strcpy(tform[i],locTform); ++i; } if(uricol == 0) { strcpy(ttype[i],URI); strcpy(tform[i],URITform); ++i; } break; case GT_ID_POS_URI: if(positioncol == 0) { strcpy(ttype[i],position); strcpy(tform[i],posTform); ++i; } if(locationcol == 0) { strcpy(ttype[i],location); strcpy(tform[i],locTform); ++i; } if(uricol == 0) { strcpy(ttype[i],URI); strcpy(tform[i],URITform); ++i; } break; default: *status = BAD_OPTION; ffpmsg("Invalid value specified for the grouptype parameter (ffgtdc)"); break; } *ncols = i; return(*status); } /*****************************************************************************/ int ffgmul(fitsfile *mfptr, /* pointer to the grouping table member HDU */ int rmopt, /* 0 ==> leave GRPIDn/GRPLCn keywords, 1 ==> remove GRPIDn/GRPLCn keywords */ int *status) /* return status code */ /* examine all the GRPIDn and GRPLCn keywords in the member HDUs header and remove the member from the grouping tables referenced; This effectively "unlinks" the member from all of its groups. The rmopt specifies if the GRPIDn/GRPLCn keywords are to be removed from the member HDUs header after the unlinking. */ { int memberPosition = 0; int iomode; long index; long ngroups = 0; long memberExtver = 0; long memberID = 0; char mbrLocation1[FLEN_FILENAME]; char mbrLocation2[FLEN_FILENAME]; char memberHDUtype[FLEN_VALUE]; char memberExtname[FLEN_VALUE]; char keyword[FLEN_KEYWORD]; char card[FLEN_CARD]; fitsfile *gfptr = NULL; if(*status != 0) return(*status); do { /* determine location parameters of the member HDU; note that default values are supplied if the expected keywords are not found */ *status = fits_read_key_str(mfptr,"XTENSION",memberHDUtype,card,status); if(*status == KEY_NO_EXIST) { strcpy(memberHDUtype,"PRIMARY"); *status = 0; } prepare_keyvalue(memberHDUtype); *status = fits_read_key_lng(mfptr,"EXTVER",&memberExtver,card,status); if(*status == KEY_NO_EXIST) { memberExtver = 1; *status = 0; } *status = fits_read_key_str(mfptr,"EXTNAME",memberExtname,card,status); if(*status == KEY_NO_EXIST) { memberExtname[0] = 0; *status = 0; } prepare_keyvalue(memberExtname); fits_get_hdu_num(mfptr,&memberPosition); *status = fits_get_url(mfptr,mbrLocation1,mbrLocation2,NULL,NULL, NULL,status); if(*status != 0) continue; /* open each grouping table linked to this HDU and remove the member from the grouping tables */ *status = fits_get_num_groups(mfptr,&ngroups,status); /* loop over each group linked to the member HDU */ for(index = 1; index <= ngroups && *status == 0; ++index) { /* open the (index)th group linked to the member HDU */ *status = fits_open_group(mfptr,index,&gfptr,status); /* if the group could not be opened then just skip it */ if(*status != 0) { *status = 0; snprintf(card,FLEN_CARD,"Cannot open the %dth group table (ffgmul)", (int)index); ffpmsg(card); continue; } /* make sure the grouping table can be modified before proceeding */ fits_file_mode(gfptr,&iomode,status); if(iomode != READWRITE) { snprintf(card,FLEN_CARD,"The %dth group cannot be modified (ffgtam)", (int)index); ffpmsg(card); continue; } /* try to find the member's row within the grouping table; first try using the member HDU file's "real" URL string then try using its originally opened URL string if either string exist */ memberID = 0; if(strlen(mbrLocation1) != 0) { *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver, memberPosition,mbrLocation1,&memberID,status); } if(*status == MEMBER_NOT_FOUND && strlen(mbrLocation2) != 0) { *status = 0; *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver, memberPosition,mbrLocation2,&memberID,status); } /* if the member was found then delete it from the grouping table */ if(*status == 0) *status = fits_delete_rows(gfptr,memberID,1,status); /* continue the loop over all member groups even if an error was generated */ if(*status == MEMBER_NOT_FOUND) { ffpmsg("cannot locate member's entry in group table (ffgmul)"); } *status = 0; /* close the file pointed to by gfptr if it is non NULL to prepare for the next loop iterration */ if(gfptr != NULL) { fits_close_file(gfptr,status); gfptr = NULL; } } if(*status != 0) continue; /* if rmopt is non-zero then find and delete the GRPIDn/GRPLCn keywords from the member HDU header */ if(rmopt != 0) { fits_file_mode(mfptr,&iomode,status); if(iomode == READONLY) { ffpmsg("Cannot modify member HDU, opened READONLY (ffgmul)"); continue; } /* delete all the GRPIDn/GRPLCn keywords */ for(index = 1; index <= ngroups && *status == 0; ++index) { snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)index); fits_delete_key(mfptr,keyword,status); snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)index); fits_delete_key(mfptr,keyword,status); if(*status == KEY_NO_EXIST) *status = 0; } } }while(0); /* make sure the gfptr has been closed */ if(gfptr != NULL) { fits_close_file(gfptr,status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgmf(fitsfile *gfptr, /* pointer to grouping table HDU to search */ char *xtension, /* XTENSION value for member HDU */ char *extname, /* EXTNAME value for member HDU */ int extver, /* EXTVER value for member HDU */ int position, /* HDU position value for member HDU */ char *location, /* FITS file location value for member HDU */ long *member, /* member HDU ID within group table (if found) */ int *status) /* return status code */ /* try to find the entry for the member HDU defined by the xtension, extname, extver, position, and location parameters within the grouping table pointed to by gfptr. If the member HDU is found then its ID (row number) within the grouping table is returned in the member variable; if not found then member is returned with a value of 0 and the status return code will be set to MEMBER_NOT_FOUND. Note that the member HDU postion information is used to obtain a member match only if the grouping table type is GT_ID_POS_URI or GT_ID_POS. This is because the position information can become invalid much more easily then the reference information for a group member. */ { int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol; int mposition = 0; int grptype; int dummy; int i; long nmembers = 0; long mextver = 0; char charBuff1[FLEN_FILENAME]; char charBuff2[FLEN_FILENAME]; char tmpLocation[FLEN_FILENAME]; char mbrLocation1[FLEN_FILENAME]; char mbrLocation2[FLEN_FILENAME]; char mbrLocation3[FLEN_FILENAME]; char grpLocation1[FLEN_FILENAME]; char grpLocation2[FLEN_FILENAME]; char cwd[FLEN_FILENAME]; char nstr[] = {'\0'}; char *tmpPtr[2]; if(*status != 0) return(*status); *member = 0; tmpPtr[0] = charBuff1; tmpPtr[1] = charBuff2; if(*status != 0) return(*status); /* if the passed LOCATION value is not an absolute URL then turn it into an absolute path */ if(location == NULL) { *tmpLocation = 0; } else if(*location == 0) { *tmpLocation = 0; } else if(!fits_is_url_absolute(location)) { fits_path2url(location,FLEN_FILENAME,tmpLocation,status); if(*tmpLocation != '/') { fits_get_cwd(cwd,status); if (strlen(cwd)+strlen(tmpLocation)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and location are too long (ffgmf)"); return (*status = URL_PARSE_ERROR); } strcat(cwd,"/"); strcat(cwd,tmpLocation); fits_clean_url(cwd,tmpLocation,status); } } else strcpy(tmpLocation,location); /* retrieve the Grouping Convention reserved column positions within the grouping table */ *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol, &locationCol,&uriCol,&grptype,status); /* retrieve the number of group members */ *status = fits_get_num_members(gfptr,&nmembers,status); /* loop over all grouping table rows until the member HDU is found */ for(i = 1; i <= nmembers && *member == 0 && *status == 0; ++i) { if(xtensionCol != 0) { fits_read_col_str(gfptr,xtensionCol,i,1,1,nstr,tmpPtr,&dummy,status); if(fits_strcasecmp(tmpPtr[0],xtension) != 0) continue; } if(extnameCol != 0) { fits_read_col_str(gfptr,extnameCol,i,1,1,nstr,tmpPtr,&dummy,status); if(fits_strcasecmp(tmpPtr[0],extname) != 0) continue; } if(extverCol != 0) { fits_read_col_lng(gfptr,extverCol,i,1,1,0, (long*)&mextver,&dummy,status); if(extver != mextver) continue; } /* note we only use postionCol if we have to */ if(positionCol != 0 && (grptype == GT_ID_POS || grptype == GT_ID_POS_URI)) { fits_read_col_int(gfptr,positionCol,i,1,1,0, &mposition,&dummy,status); if(position != mposition) continue; } /* if no location string was passed to the function then assume that the calling application does not wish to use it as a comparision critera ==> if we got this far then we have a match */ if(location == NULL) { ffpmsg("NULL Location string given ==> ignore location (ffgmf)"); *member = i; continue; } /* if the grouping table MEMBER_LOCATION column exists then read the location URL for the member, else set the location string to a zero-length string for subsequent comparisions */ if(locationCol != 0) { fits_read_col_str(gfptr,locationCol,i,1,1,nstr,tmpPtr,&dummy,status); strcpy(mbrLocation1,tmpPtr[0]); *mbrLocation2 = 0; } else *mbrLocation1 = 0; /* if the member location string from the grouping table is zero length (either implicitly or explicitly) then assume that the member HDU is in the same file as the grouping table HDU; retrieve the possible URL values of the grouping table HDU file */ if(*mbrLocation1 == 0) { /* retrieve the possible URLs of the grouping table file */ *status = fits_get_url(gfptr,mbrLocation1,mbrLocation2,NULL,NULL, NULL,status); /* if non-NULL, make sure the first URL is absolute or a full path */ if(*mbrLocation1 != 0 && !fits_is_url_absolute(mbrLocation1) && *mbrLocation1 != '/') { fits_get_cwd(cwd,status); if (strlen(cwd)+strlen(mbrLocation1)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and member locations are too long (ffgmf)"); *status = URL_PARSE_ERROR; continue; } strcat(cwd,"/"); strcat(cwd,mbrLocation1); fits_clean_url(cwd,mbrLocation1,status); } /* if non-NULL, make sure the first URL is absolute or a full path */ if(*mbrLocation2 != 0 && !fits_is_url_absolute(mbrLocation2) && *mbrLocation2 != '/') { fits_get_cwd(cwd,status); if (strlen(cwd)+strlen(mbrLocation2)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and member locations are too long (ffgmf)"); *status = URL_PARSE_ERROR; continue; } strcat(cwd,"/"); strcat(cwd,mbrLocation2); fits_clean_url(cwd,mbrLocation2,status); } } /* if the member location was specified, then make sure that it is either an absolute URL or specifies a full path */ else if(!fits_is_url_absolute(mbrLocation1) && *mbrLocation1 != '/') { strcpy(mbrLocation2,mbrLocation1); /* get the possible URLs for the grouping table file */ *status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,NULL, NULL,status); if(*grpLocation1 != 0) { /* make sure the first grouping table URL is absolute */ if(!fits_is_url_absolute(grpLocation1) && *grpLocation1 != '/') { fits_get_cwd(cwd,status); if (strlen(cwd)+strlen(grpLocation1)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and group locations are too long (ffgmf)"); *status = URL_PARSE_ERROR; continue; } strcat(cwd,"/"); strcat(cwd,grpLocation1); fits_clean_url(cwd,grpLocation1,status); } /* create an absoute URL for the member */ fits_relurl2url(grpLocation1,mbrLocation1,mbrLocation3,status); /* if URL construction succeeded then copy it to the first location string; else set the location string to empty */ if(*status == 0) { strcpy(mbrLocation1,mbrLocation3); } else if(*status == URL_PARSE_ERROR) { *status = 0; *mbrLocation1 = 0; } } else *mbrLocation1 = 0; if(*grpLocation2 != 0) { /* make sure the second grouping table URL is absolute */ if(!fits_is_url_absolute(grpLocation2) && *grpLocation2 != '/') { fits_get_cwd(cwd,status); if (strlen(cwd)+strlen(grpLocation2)+1 > FLEN_FILENAME-1) { ffpmsg("cwd and group locations are too long (ffgmf)"); *status = URL_PARSE_ERROR; continue; } strcat(cwd,"/"); strcat(cwd,grpLocation2); fits_clean_url(cwd,grpLocation2,status); } /* create an absolute URL for the member */ fits_relurl2url(grpLocation2,mbrLocation2,mbrLocation3,status); /* if URL construction succeeded then copy it to the second location string; else set the location string to empty */ if(*status == 0) { strcpy(mbrLocation2,mbrLocation3); } else if(*status == URL_PARSE_ERROR) { *status = 0; *mbrLocation2 = 0; } } else *mbrLocation2 = 0; } /* compare the passed member HDU file location string with the (possibly two) member location strings to see if there is a match */ if(strcmp(mbrLocation1,tmpLocation) != 0 && strcmp(mbrLocation2,tmpLocation) != 0 ) continue; /* if we made it this far then a match to the member HDU was found */ *member = i; } /* if a match was not found then set the return status code */ if(*member == 0 && *status == 0) { *status = MEMBER_NOT_FOUND; ffpmsg("Cannot find specified member HDU (ffgmf)"); } return(*status); } /*-------------------------------------------------------------------------- Recursive Group Functions --------------------------------------------------------------------------*/ int ffgtrmr(fitsfile *gfptr, /* FITS file pointer to group */ HDUtracker *HDU, /* list of processed HDUs */ int *status) /* return status code */ /* recursively remove a grouping table and all its members. Each member of the grouping table pointed to by gfptr it processed. If the member is itself a grouping table then ffgtrmr() is recursively called to process all of its members. The HDUtracker struct *HDU is used to make sure a member is not processed twice, thus avoiding an infinite loop (e.g., a grouping table contains itself as a member). */ { int i; int hdutype; long nmembers = 0; char keyvalue[FLEN_VALUE]; char comment[FLEN_COMMENT]; fitsfile *mfptr = NULL; if(*status != 0) return(*status); /* get the number of members contained by this grouping table */ *status = fits_get_num_members(gfptr,&nmembers,status); /* loop over all group members and delete them */ for(i = nmembers; i > 0 && *status == 0; --i) { /* open the member HDU */ *status = fits_open_member(gfptr,i,&mfptr,status); /* if the member cannot be opened then just skip it and continue */ if(*status == MEMBER_NOT_FOUND) { *status = 0; continue; } /* Any other error is a reason to abort */ if(*status != 0) continue; /* add the member HDU to the HDUtracker struct */ *status = fftsad(mfptr,HDU,NULL,NULL); /* status == HDU_ALREADY_TRACKED ==> HDU has already been processed */ if(*status == HDU_ALREADY_TRACKED) { *status = 0; fits_close_file(mfptr,status); continue; } else if(*status != 0) continue; /* determine if the member HDU is itself a grouping table */ *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status); /* if no EXTNAME is found then the HDU cannot be a grouping table */ if(*status == KEY_NO_EXIST) { *status = 0; keyvalue[0] = 0; } prepare_keyvalue(keyvalue); /* Any other error is a reason to abort */ if(*status != 0) continue; /* if the EXTNAME == GROUPING then the member is a grouping table and we must call ffgtrmr() to process its members */ if(fits_strcasecmp(keyvalue,"GROUPING") == 0) *status = ffgtrmr(mfptr,HDU,status); /* unlink all the grouping tables that contain this HDU as a member and then delete the HDU (if not a PHDU) */ if(fits_get_hdu_num(mfptr,&hdutype) == 1) *status = ffgmul(mfptr,1,status); else { *status = ffgmul(mfptr,0,status); *status = fits_delete_hdu(mfptr,&hdutype,status); } /* close the fitsfile pointer */ fits_close_file(mfptr,status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgtcpr(fitsfile *infptr, /* input FITS file pointer */ fitsfile *outfptr, /* output FITS file pointer */ int cpopt, /* code specifying copy options: OPT_GCP_GPT (0) ==> cp only grouping table OPT_GCP_ALL (2) ==> recusrively copy members and their members (if groups) */ HDUtracker *HDU, /* list of already copied HDUs */ int *status) /* return status code */ /* copy a Group to a new FITS file. If the cpopt parameter is set to OPT_GCP_GPT (copy grouping table only) then the existing members have their GRPIDn and GRPLCn keywords updated to reflect the existance of the new group, since they now belong to another group. If cpopt is set to OPT_GCP_ALL (copy grouping table and members recursively) then the original members are not updated; the new grouping table is modified to include only the copied member HDUs and not the original members. Note that this function is recursive. When copt is OPT_GCP_ALL it will call itself whenever a member HDU of the current grouping table is itself a grouping table (i.e., EXTNAME = 'GROUPING'). */ { int i; int nexclude = 8; int hdutype = 0; int groupHDUnum = 0; int numkeys = 0; int keypos = 0; int startSearch = 0; int newPosition = 0; long nmembers = 0; long tfields = 0; long newTfields = 0; char keyword[FLEN_KEYWORD]; char keyvalue[FLEN_VALUE]; char card[FLEN_CARD]; char comment[FLEN_CARD]; char *tkeyvalue; char *includeList[] = {"*"}; char *excludeList[] = {"EXTNAME","EXTVER","GRPNAME","GRPID#","GRPLC#", "THEAP","TDIM#","T????#"}; fitsfile *mfptr = NULL; if(*status != 0) return(*status); do { /* create a new grouping table in the FITS file pointed to by outptr */ *status = fits_get_num_members(infptr,&nmembers,status); *status = fits_read_key_str(infptr,"GRPNAME",keyvalue,card,status); if(*status == KEY_NO_EXIST) { keyvalue[0] = 0; *status = 0; } prepare_keyvalue(keyvalue); *status = fits_create_group(outfptr,keyvalue,GT_ID_ALL_URI,status); /* save the new grouping table's HDU position for future use */ fits_get_hdu_num(outfptr,&groupHDUnum); /* update the HDUtracker struct with the grouping table's new position */ *status = fftsud(infptr,HDU,groupHDUnum,NULL); /* Now populate the copied grouping table depending upon the copy option parameter value */ switch(cpopt) { /* for the "copy grouping table only" option we only have to add the members of the original grouping table to the new grouping table */ case OPT_GCP_GPT: for(i = 1; i <= nmembers && *status == 0; ++i) { *status = fits_open_member(infptr,i,&mfptr,status); *status = fits_add_group_member(outfptr,mfptr,0,status); fits_close_file(mfptr,status); mfptr = NULL; } break; case OPT_GCP_ALL: /* for the "copy the entire group" option */ /* loop over all the grouping table members */ for(i = 1; i <= nmembers && *status == 0; ++i) { /* open the ith member */ *status = fits_open_member(infptr,i,&mfptr,status); if(*status != 0) continue; /* add it to the HDUtracker struct */ *status = fftsad(mfptr,HDU,&newPosition,NULL); /* if already copied then just add the member to the group */ if(*status == HDU_ALREADY_TRACKED) { *status = 0; *status = fits_add_group_member(outfptr,NULL,newPosition, status); fits_close_file(mfptr,status); mfptr = NULL; continue; } else if(*status != 0) continue; /* see if the member is a grouping table */ *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card, status); if(*status == KEY_NO_EXIST) { keyvalue[0] = 0; *status = 0; } prepare_keyvalue(keyvalue); /* if the member is a grouping table then copy it and all of its members using ffgtcpr(), else copy it using fits_copy_member(); the outptr will point to the newly copied member upon return from both functions */ if(fits_strcasecmp(keyvalue,"GROUPING") == 0) *status = ffgtcpr(mfptr,outfptr,OPT_GCP_ALL,HDU,status); else *status = fits_copy_member(infptr,outfptr,i,OPT_MCP_NADD, status); /* retrieve the position of the newly copied member */ fits_get_hdu_num(outfptr,&newPosition); /* update the HDUtracker struct with member's new position */ if(fits_strcasecmp(keyvalue,"GROUPING") != 0) *status = fftsud(mfptr,HDU,newPosition,NULL); /* move the outfptr back to the copied grouping table HDU */ *status = fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status); /* add the copied member HDU to the copied grouping table */ *status = fits_add_group_member(outfptr,NULL,newPosition,status); /* close the mfptr pointer */ fits_close_file(mfptr,status); mfptr = NULL; } break; default: *status = BAD_OPTION; ffpmsg("Invalid value specified for cmopt parameter (ffgtcpr)"); break; } if(*status != 0) continue; /* reposition the outfptr to the grouping table so that the grouping table is the CHDU upon return to the calling function */ fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status); /* copy all auxiliary keyword records from the original grouping table to the new grouping table; they are copied in their original order and inserted just before the TTYPE1 keyword record */ *status = fits_read_card(outfptr,"TTYPE1",card,status); *status = fits_get_hdrpos(outfptr,&numkeys,&keypos,status); --keypos; startSearch = 8; while(*status == 0) { ffgrec(infptr,startSearch,card,status); *status = fits_find_nextkey(infptr,includeList,1,excludeList, nexclude,card,status); *status = fits_get_hdrpos(infptr,&numkeys,&startSearch,status); --startSearch; /* SPR 1738 */ if (strncmp(card,"GRPLC",5)) { /* Not going to be a long string so we're ok */ *status = fits_insert_record(outfptr,keypos,card,status); } else { /* We could have a long string */ *status = fits_read_record(infptr,startSearch,card,status); card[9] = '\0'; *status = fits_read_key_longstr(infptr,card,&tkeyvalue,comment, status); if (0 == *status) { fits_insert_key_longstr(outfptr,card,tkeyvalue,comment,status); fits_write_key_longwarn(outfptr,status); free(tkeyvalue); } } ++keypos; } if(*status == KEY_NO_EXIST) *status = 0; else if(*status != 0) continue; /* search all the columns of the original grouping table and copy those to the new grouping table that were not part of the grouping convention. Note that is legal to have additional columns in a grouping table. Also note that the order of the columns may not be the same in the original and copied grouping table. */ /* retrieve the number of columns in the original and new group tables */ *status = fits_read_key_lng(infptr,"TFIELDS",&tfields,card,status); *status = fits_read_key_lng(outfptr,"TFIELDS",&newTfields,card,status); for(i = 1; i <= tfields; ++i) { snprintf(keyword,FLEN_KEYWORD,"TTYPE%d",i); *status = fits_read_key_str(infptr,keyword,keyvalue,card,status); if(*status == KEY_NO_EXIST) { *status = 0; keyvalue[0] = 0; } prepare_keyvalue(keyvalue); if(fits_strcasecmp(keyvalue,"MEMBER_XTENSION") != 0 && fits_strcasecmp(keyvalue,"MEMBER_NAME") != 0 && fits_strcasecmp(keyvalue,"MEMBER_VERSION") != 0 && fits_strcasecmp(keyvalue,"MEMBER_POSITION") != 0 && fits_strcasecmp(keyvalue,"MEMBER_LOCATION") != 0 && fits_strcasecmp(keyvalue,"MEMBER_URI_TYPE") != 0 ) { /* SPR 3956, add at the end of the table */ *status = fits_copy_col(infptr,outfptr,i,newTfields+1,1,status); ++newTfields; } } }while(0); if(mfptr != NULL) { fits_close_file(mfptr,status); } return(*status); } /*-------------------------------------------------------------------------- HDUtracker struct manipulation functions --------------------------------------------------------------------------*/ int fftsad(fitsfile *mfptr, /* pointer to an member HDU */ HDUtracker *HDU, /* pointer to an HDU tracker struct */ int *newPosition, /* new HDU position of the member HDU */ char *newFileName) /* file containing member HDU */ /* add an HDU to the HDUtracker struct pointed to by HDU. The HDU is only added if it does not already reside in the HDUtracker. If it already resides in the HDUtracker then the new HDU postion and file name are returned in newPosition and newFileName (if != NULL) */ { int i; int hdunum; int status = 0; char filename1[FLEN_FILENAME]; char filename2[FLEN_FILENAME]; do { /* retrieve the HDU's position within the FITS file */ fits_get_hdu_num(mfptr,&hdunum); /* retrieve the HDU's file name */ status = fits_file_name(mfptr,filename1,&status); /* parse the file name and construct the "standard" URL for it */ status = ffrtnm(filename1,filename2,&status); /* examine all the existing HDUs in the HDUtracker an see if this HDU has already been registered */ for(i = 0; i < HDU->nHDU && !(HDU->position[i] == hdunum && strcmp(HDU->filename[i],filename2) == 0); ++i); if(i != HDU->nHDU) { status = HDU_ALREADY_TRACKED; if(newPosition != NULL) *newPosition = HDU->newPosition[i]; if(newFileName != NULL) strcpy(newFileName,HDU->newFilename[i]); continue; } if(HDU->nHDU == MAX_HDU_TRACKER) { status = TOO_MANY_HDUS_TRACKED; continue; } HDU->filename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char)); if(HDU->filename[i] == NULL) { status = MEMORY_ALLOCATION; continue; } HDU->newFilename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char)); if(HDU->newFilename[i] == NULL) { status = MEMORY_ALLOCATION; free(HDU->filename[i]); continue; } HDU->position[i] = hdunum; HDU->newPosition[i] = hdunum; strcpy(HDU->filename[i],filename2); strcpy(HDU->newFilename[i],filename2); ++(HDU->nHDU); }while(0); return(status); } /*--------------------------------------------------------------------------*/ int fftsud(fitsfile *mfptr, /* pointer to an member HDU */ HDUtracker *HDU, /* pointer to an HDU tracker struct */ int newPosition, /* new HDU position of the member HDU */ char *newFileName) /* file containing member HDU */ /* update the HDU information in the HDUtracker struct pointed to by HDU. The HDU to update is pointed to by mfptr. If non-zero, the value of newPosition is used to update the HDU->newPosition[] value for the mfptr, and if non-NULL the newFileName value is used to update the HDU->newFilename[] value for mfptr. */ { int i; int hdunum; int status = 0; char filename1[FLEN_FILENAME]; char filename2[FLEN_FILENAME]; /* retrieve the HDU's position within the FITS file */ fits_get_hdu_num(mfptr,&hdunum); /* retrieve the HDU's file name */ status = fits_file_name(mfptr,filename1,&status); /* parse the file name and construct the "standard" URL for it */ status = ffrtnm(filename1,filename2,&status); /* examine all the existing HDUs in the HDUtracker an see if this HDU has already been registered */ for(i = 0; i < HDU->nHDU && !(HDU->position[i] == hdunum && strcmp(HDU->filename[i],filename2) == 0); ++i); /* if previously registered then change newPosition and newFileName */ if(i != HDU->nHDU) { if(newPosition != 0) HDU->newPosition[i] = newPosition; if(newFileName != NULL) { strcpy(HDU->newFilename[i],newFileName); } } else status = MEMBER_NOT_FOUND; return(status); } /*---------------------------------------------------------------------------*/ void prepare_keyvalue(char *keyvalue) /* string containing keyword value */ /* strip off all single quote characters "'" and blank spaces from a keyword value retrieved via fits_read_key*() routines this is necessary so that a standard comparision of keyword values may be made */ { int i; int length; /* strip off any leading or trailing single quotes (`) and (') from the keyword value */ length = strlen(keyvalue) - 1; if(keyvalue[0] == '\'' && keyvalue[length] == '\'') { for(i = 0; i < length - 1; ++i) keyvalue[i] = keyvalue[i+1]; keyvalue[length-1] = 0; } /* strip off any trailing blanks from the keyword value; note that if the keyvalue consists of nothing but blanks then no blanks are stripped */ length = strlen(keyvalue) - 1; for(i = 0; i < length && keyvalue[i] == ' '; ++i); if(i != length) { for(i = length; i >= 0 && keyvalue[i] == ' '; --i) keyvalue[i] = '\0'; } } /*--------------------------------------------------------------------------- Host dependent directory path to/from URL functions --------------------------------------------------------------------------*/ int fits_path2url(char *inpath, /* input file path string */ int maxlength, /* I max number of chars that can be written to output, including terminating NULL */ char *outpath, /* output file path string */ int *status) /* convert a file path into its Unix-style equivelent for URL purposes. Note that this process is platform dependent. This function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. The plaform dependant code is conditionally compiled depending upon the setting of the appropriate C preprocessor macros. */ { char buff[FLEN_FILENAME]; #if defined(WINNT) || defined(__WINNT__) /* Microsoft Windows NT case. We assume input file paths of the form: //disk/path/filename All path segments may be null, so that a single file name is the simplist case. The leading "//" becomes a single "/" if present. If no "//" is present, then make sure the resulting URL path is relative, i.e., does not begin with a "/". In other words, the only way that an absolute URL file path may be generated is if the drive specification is given. */ if(*status > 0) return(*status); if(inpath[0] == '/') { strcpy(buff,inpath+1); } else { strcpy(buff,inpath); } #elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32) /* MSDOS or Microsoft windows/NT case. The assumed form of the input path is: disk:\path\filename All path segments may be null, so that a single file name is the simplist case. All back-slashes '\' become slashes '/'; if the path starts with a string of the form "X:" then it is replaced with "/X/" */ int i,j,k; int size; if(*status > 0) return(*status); for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0; i < size; j = strlen(buff)) { switch(inpath[i]) { case ':': /* must be a disk desiginator; add a slash '/' at the start of outpath to designate that the path is absolute, then change the colon ':' to a slash '/' */ for(k = j; k >= 0; --k) buff[k+1] = buff[k]; buff[0] = '/'; strcat(buff,"/"); ++i; break; case '\\': /* just replace the '\' with a '/' IF its not the first character */ if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/') { buff[j] = '/'; buff[j+1] = 0; } ++i; break; default: /* copy the character from inpath to buff as is */ buff[j] = inpath[i]; buff[j+1] = 0; ++i; break; } } #elif defined(VMS) || defined(vms) || defined(__vms) /* VMS case. Assumed format of the input path is: node::disk:[path]filename.ext;version Any part of the file path may be missing, so that in the simplist case a single file name/extension is given. all brackets "[", "]" and dots "." become "/"; dashes "-" become "..", all single colons ":" become ":/", all double colons "::" become "FILE://" */ int i,j,k; int done; int size; if(*status > 0) return(*status); /* see if inpath contains a directory specification */ if(strchr(inpath,']') == NULL) done = 1; else done = 0; for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0; i < size && j < FLEN_FILENAME - 8; j = strlen(buff)) { switch(inpath[i]) { case ':': /* must be a logical/symbol separator or (in the case of a double colon "::") machine node separator */ if(inpath[i+1] == ':') { /* insert a "FILE://" at the start of buff ==> machine given */ for(k = j; k >= 0; --k) buff[k+7] = buff[k]; strncpy(buff,"FILE://",7); i += 2; } else if(strstr(buff,"FILE://") == NULL) { /* insert a "/" at the start of buff ==> absolute path */ for(k = j; k >= 0; --k) buff[k+1] = buff[k]; buff[0] = '/'; ++i; } else ++i; /* a colon always ==> path separator */ strcat(buff,"/"); break; case ']': /* end of directory spec, file name spec begins after this */ done = 1; buff[j] = '/'; buff[j+1] = 0; ++i; break; case '[': /* begin directory specification; add a '/' only if the last char is not '/' */ if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/') { buff[j] = '/'; buff[j+1] = 0; } ++i; break; case '.': /* directory segment separator or file name/extension separator; we decide which by looking at the value of done */ if(!done) { /* must be a directory segment separator */ if(inpath[i-1] == '[') { strcat(buff,"./"); ++j; } else buff[j] = '/'; } else /* must be a filename/extension separator */ buff[j] = '.'; buff[j+1] = 0; ++i; break; case '-': /* a dash is the same as ".." in Unix speak, but lets make sure that its not part of the file name first! */ if(!done) /* must be part of the directory path specification */ strcat(buff,".."); else { /* the dash is part of the filename, so just copy it as is */ buff[j] = '-'; buff[j+1] = 0; } ++i; break; default: /* nothing special, just copy the character as is */ buff[j] = inpath[i]; buff[j+1] = 0; ++i; break; } } if(j > FLEN_FILENAME - 8) { *status = URL_PARSE_ERROR; ffpmsg("resulting path to URL conversion too big (fits_path2url)"); } #elif defined(macintosh) /* MacOS case. The assumed form of the input path is: disk:path:filename It is assumed that all paths are absolute with disk and path specified, unless no colons ":" are supplied with the string ==> a single file name only. All colons ":" become slashes "/", and if one or more colon is encountered then the path is specified as absolute. */ int i,j,k; int firstColon; int size; if(*status > 0) return(*status); for(i = 0, j = 0, firstColon = 1, size = strlen(inpath), buff[0] = 0; i < size; j = strlen(buff)) { switch(inpath[i]) { case ':': /* colons imply path separators. If its the first colon encountered then assume that its the disk designator and add a slash to the beginning of the buff string */ if(firstColon) { firstColon = 0; for(k = j; k >= 0; --k) buff[k+1] = buff[k]; buff[0] = '/'; } /* all colons become slashes */ strcat(buff,"/"); ++i; break; default: /* copy the character from inpath to buff as is */ buff[j] = inpath[i]; buff[j+1] = 0; ++i; break; } } #else /* Default Unix case. Nothing special to do here except to remove the double or more // and replace them with single / */ int ii = 0; int jj = 0; if(*status > 0) return(*status); while (inpath[ii]) { if (inpath[ii] == '/' && inpath[ii+1] == '/') { /* do nothing */ } else { buff[jj] = inpath[ii]; jj++; } ii++; } buff[jj] = '\0'; /* printf("buff is %s\ninpath is %s\n",buff,inpath); */ /* strcpy(buff,inpath); */ #endif /* encode all "unsafe" and "reserved" URL characters */ *status = fits_encode_url(buff,maxlength,outpath,status); return(*status); } /*---------------------------------------------------------------------------*/ int fits_url2path(char *inpath, /* input file path string */ char *outpath, /* output file path string */ int *status) /* convert a Unix-style URL into a platform dependent directory path. Note that this process is platform dependent. This function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. Each platform dependent code segment is conditionally compiled depending upon the setting of the appropriate C preprocesser macros. */ { char buff[FLEN_FILENAME]; int absolute; #if defined(MSDOS) || defined(__WIN32__) || defined(WIN32) char *tmpStr, *saveptr; #elif defined(VMS) || defined(vms) || defined(__vms) int i; char *tmpStr, *saveptr; #elif defined(macintosh) char *tmpStr, *saveptr; #endif if(*status != 0) return(*status); /* make a copy of the inpath so that we can manipulate it */ strcpy(buff,inpath); /* convert any encoded characters to their unencoded values */ *status = fits_unencode_url(inpath,buff,status); /* see if the URL is given as absolute w.r.t. the "local" file system */ if(buff[0] == '/') absolute = 1; else absolute = 0; #if defined(WINNT) || defined(__WINNT__) /* Microsoft Windows NT case. We create output paths of the form //disk/path/filename All path segments but the last may be null, so that a single file name is the simplist case. */ if(absolute) { strcpy(outpath,"/"); strcat(outpath,buff); } else { strcpy(outpath,buff); } #elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32) /* MSDOS or Microsoft windows/NT case. The output path will be of the form disk:\path\filename All path segments but the last may be null, so that a single file name is the simplist case. */ /* separate the URL into tokens at each slash '/' and process until all tokens have been examined */ for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0; tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr)) { strcat(outpath,tmpStr); /* if the absolute flag is set then process the token as a disk specification; else just process it as a directory path or filename */ if(absolute) { strcat(outpath,":\\"); absolute = 0; } else strcat(outpath,"\\"); } /* remove the last "\" from the outpath, it does not belong there */ outpath[strlen(outpath)-1] = 0; #elif defined(VMS) || defined(vms) || defined(__vms) /* VMS case. The output path will be of the form: node::disk:[path]filename.ext;version Any part of the file path may be missing execpt filename.ext, so that in the simplist case a single file name/extension is given. if the path is specified as relative starting with "./" then the first part of the VMS path is "[.". If the path is relative and does not start with "./" (e.g., "a/b/c") then the VMS path is constructed as "[a.b.c]" */ /* separate the URL into tokens at each slash '/' and process until all tokens have been examined */ for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0; tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr)) { if(fits_strcasecmp(tmpStr,"FILE:") == 0) { /* the next token should contain the DECnet machine name */ tmpStr = ffstrtok(NULL,"/",&saveptr); if(tmpStr == NULL) continue; strcat(outpath,tmpStr); strcat(outpath,"::"); /* set the absolute flag to true for the next token */ absolute = 1; } else if(strcmp(tmpStr,"..") == 0) { /* replace all Unix-like ".." with VMS "-" */ if(strlen(outpath) == 0) strcat(outpath,"["); strcat(outpath,"-."); } else if(strcmp(tmpStr,".") == 0 && strlen(outpath) == 0) { /* must indicate a relative path specifier */ strcat(outpath,"[."); } else if(strchr(tmpStr,'.') != NULL) { /* must be up to the file name; turn the last "." path separator into a "]" and then add the file name to the outpath */ i = strlen(outpath); if(i > 0 && outpath[i-1] == '.') outpath[i-1] = ']'; strcat(outpath,tmpStr); } else { /* process the token as a a directory path segement */ if(absolute) { /* treat the token as a disk specifier */ absolute = 0; strcat(outpath,tmpStr); strcat(outpath,":["); } else if(strlen(outpath) == 0) { /* treat the token as the first directory path specifier */ strcat(outpath,"["); strcat(outpath,tmpStr); strcat(outpath,"."); } else { /* treat the token as an imtermediate path specifier */ strcat(outpath,tmpStr); strcat(outpath,"."); } } } #elif defined(macintosh) /* MacOS case. The output path will be of the form disk:path:filename All path segments but the last may be null, so that a single file name is the simplist case. */ /* separate the URL into tokens at each slash '/' and process until all tokens have been examined */ for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0; tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr)) { strcat(outpath,tmpStr); strcat(outpath,":"); } /* remove the last ":" from the outpath, it does not belong there */ outpath[strlen(outpath)-1] = 0; #else /* Default Unix case. Nothing special to do here */ strcpy(outpath,buff); #endif return(*status); } /****************************************************************************/ int fits_get_cwd(char *cwd, /* IO current working directory string */ int *status) /* retrieve the string containing the current working directory absolute path in Unix-like URL standard notation. It is assumed that the CWD string has a size of at least FLEN_FILENAME. Note that this process is platform dependent. This function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. Each platform dependent code segment is conditionally compiled depending upon the setting of the appropriate C preprocesser macros. */ { char buff[FLEN_FILENAME]; if(*status != 0) return(*status); #if defined(macintosh) /* MacOS case. Currently unknown !!!! */ *buff = 0; #else /* Good old getcwd() seems to work with all other platforms */ if (!getcwd(buff,FLEN_FILENAME)) { cwd[0]=0; ffpmsg("Path and file name too long (fits_get_cwd)"); return (*status=URL_PARSE_ERROR); } #endif /* convert the cwd string to a URL standard path string */ fits_path2url(buff,FLEN_FILENAME,cwd,status); return(*status); } /*---------------------------------------------------------------------------*/ int fits_get_url(fitsfile *fptr, /* I ptr to FITS file to evaluate */ char *realURL, /* O URL of real FITS file */ char *startURL, /* O URL of starting FITS file */ char *realAccess, /* O true access method of FITS file */ char *startAccess,/* O "official" access of FITS file */ int *iostate, /* O can this file be modified? */ int *status) /* For grouping convention purposes, determine the URL of the FITS file associated with the fitsfile pointer fptr. The true access type (file://, mem://, shmem://, root://), starting "official" access type, and iostate (0 ==> readonly, 1 ==> readwrite) are also returned. It is assumed that the url string has enough room to hold the resulting URL, and the the accessType string has enough room to hold the access type. */ { int i; int tmpIOstate = 0; char infile[FLEN_FILENAME]; char outfile[FLEN_FILENAME]; char tmpStr1[FLEN_FILENAME]; char tmpStr2[FLEN_FILENAME]; char tmpStr3[FLEN_FILENAME]; char tmpStr4[FLEN_FILENAME]; char *tmpPtr; if(*status != 0) return(*status); do { /* retrieve the member HDU's file name as opened by ffopen() and parse it into its constitutent pieces; get the currently active driver token too */ *tmpStr1 = *tmpStr2 = *tmpStr3 = *tmpStr4 = 0; *status = fits_file_name(fptr,tmpStr1,status); *status = ffiurl(tmpStr1,NULL,infile,outfile,NULL,tmpStr2,tmpStr3, tmpStr4,status); if((*tmpStr2) || (*tmpStr3) || (*tmpStr4)) tmpIOstate = -1; *status = ffurlt(fptr,tmpStr3,status); strcpy(tmpStr4,tmpStr3); *status = ffrtnm(tmpStr1,tmpStr2,status); strcpy(tmpStr1,tmpStr2); /* for grouping convention purposes (only) determine the URL of the actual FITS file being used for the given fptr, its true access type (file://, mem://, shmem://, root://) and its iostate (0 ==> read only, 1 ==> readwrite) */ /* The first set of access types are "simple" in that they do not use any redirection to temporary memory or outfiles */ /* standard disk file driver is in use */ if(fits_strcasecmp(tmpStr3,"file://") == 0) { tmpIOstate = 1; if(strlen(outfile)) strcpy(tmpStr1,outfile); else *tmpStr2 = 0; /* make sure no FILE:// specifier is given in the tmpStr1 or tmpStr2 strings; the convention calls for local files to have no access specification */ if((tmpPtr = strstr(tmpStr1,"://")) != NULL) { strcpy(infile,tmpPtr+3); strcpy(tmpStr1,infile); } if((tmpPtr = strstr(tmpStr2,"://")) != NULL) { strcpy(infile,tmpPtr+3); strcpy(tmpStr2,infile); } } /* file stored in conventional memory */ else if(fits_strcasecmp(tmpStr3,"mem://") == 0) { if(tmpIOstate < 0) { /* file is a temp mem file only */ ffpmsg("cannot make URL from temp MEM:// file (fits_get_url)"); *status = URL_PARSE_ERROR; } else { /* file is a "perminate" mem file for this process */ tmpIOstate = 1; *tmpStr2 = 0; } } /* file stored in conventional memory */ else if(fits_strcasecmp(tmpStr3,"memkeep://") == 0) { strcpy(tmpStr3,"mem://"); *tmpStr4 = 0; *tmpStr2 = 0; tmpIOstate = 1; } /* file residing in shared memory */ else if(fits_strcasecmp(tmpStr3,"shmem://") == 0) { *tmpStr4 = 0; *tmpStr2 = 0; tmpIOstate = 1; } /* file accessed via the ROOT network protocol */ else if(fits_strcasecmp(tmpStr3,"root://") == 0) { *tmpStr4 = 0; *tmpStr2 = 0; tmpIOstate = 1; } /* the next set of access types redirect the contents of the original file to an special outfile because the original could not be directly modified (i.e., resides on the network, was compressed). In these cases the URL string takes on the value of the OUTFILE, the access type becomes file://, and the iostate is set to 1 (can read/write to the file). */ /* compressed file uncompressed and written to disk */ else if(fits_strcasecmp(tmpStr3,"compressfile://") == 0) { strcpy(tmpStr1,outfile); strcpy(tmpStr2,infile); strcpy(tmpStr3,"file://"); strcpy(tmpStr4,"file://"); tmpIOstate = 1; } /* HTTP accessed file written locally to disk */ else if(fits_strcasecmp(tmpStr3,"httpfile://") == 0) { strcpy(tmpStr1,outfile); strcpy(tmpStr3,"file://"); strcpy(tmpStr4,"http://"); tmpIOstate = 1; } /* FTP accessd file written locally to disk */ else if(fits_strcasecmp(tmpStr3,"ftpfile://") == 0) { strcpy(tmpStr1,outfile); strcpy(tmpStr3,"file://"); strcpy(tmpStr4,"ftp://"); tmpIOstate = 1; } /* file from STDIN written to disk */ else if(fits_strcasecmp(tmpStr3,"stdinfile://") == 0) { strcpy(tmpStr1,outfile); strcpy(tmpStr3,"file://"); strcpy(tmpStr4,"stdin://"); tmpIOstate = 1; } /* the following access types use memory resident files as temporary storage; they cannot be modified or be made group members for grouping conventions purposes, but their original files can be. Thus, their tmpStr3s are reset to mem://, their iostate values are set to 0 (for no-modification), and their URL string values remain set to their original values */ /* compressed disk file uncompressed into memory */ else if(fits_strcasecmp(tmpStr3,"compress://") == 0) { *tmpStr1 = 0; strcpy(tmpStr2,infile); strcpy(tmpStr3,"mem://"); strcpy(tmpStr4,"file://"); tmpIOstate = 0; } /* HTTP accessed file transferred into memory */ else if(fits_strcasecmp(tmpStr3,"http://") == 0) { *tmpStr1 = 0; strcpy(tmpStr3,"mem://"); strcpy(tmpStr4,"http://"); tmpIOstate = 0; } /* HTTP accessed compressed file transferred into memory */ else if(fits_strcasecmp(tmpStr3,"httpcompress://") == 0) { *tmpStr1 = 0; strcpy(tmpStr3,"mem://"); strcpy(tmpStr4,"http://"); tmpIOstate = 0; } /* FTP accessed file transferred into memory */ else if(fits_strcasecmp(tmpStr3,"ftp://") == 0) { *tmpStr1 = 0; strcpy(tmpStr3,"mem://"); strcpy(tmpStr4,"ftp://"); tmpIOstate = 0; } /* FTP accessed compressed file transferred into memory */ else if(fits_strcasecmp(tmpStr3,"ftpcompress://") == 0) { *tmpStr1 = 0; strcpy(tmpStr3,"mem://"); strcpy(tmpStr4,"ftp://"); tmpIOstate = 0; } /* The last set of access types cannot be used to make a meaningful URL strings from; thus an error is generated */ else if(fits_strcasecmp(tmpStr3,"stdin://") == 0) { *status = URL_PARSE_ERROR; ffpmsg("cannot make valid URL from stdin:// (fits_get_url)"); *tmpStr1 = *tmpStr2 = 0; } else if(fits_strcasecmp(tmpStr3,"stdout://") == 0) { *status = URL_PARSE_ERROR; ffpmsg("cannot make valid URL from stdout:// (fits_get_url)"); *tmpStr1 = *tmpStr2 = 0; } else if(fits_strcasecmp(tmpStr3,"irafmem://") == 0) { *status = URL_PARSE_ERROR; ffpmsg("cannot make valid URL from irafmem:// (fits_get_url)"); *tmpStr1 = *tmpStr2 = 0; } if(*status != 0) continue; /* assign values to the calling parameters if they are non-NULL */ if(realURL != NULL) { if(strlen(tmpStr1) == 0) *realURL = 0; else { if((tmpPtr = strstr(tmpStr1,"://")) != NULL) { tmpPtr += 3; i = (long)tmpPtr - (long)tmpStr1; strncpy(realURL,tmpStr1,i); } else { tmpPtr = tmpStr1; i = 0; } *status = fits_path2url(tmpPtr,FLEN_FILENAME-i,realURL+i,status); } } if(startURL != NULL) { if(strlen(tmpStr2) == 0) *startURL = 0; else { if((tmpPtr = strstr(tmpStr2,"://")) != NULL) { tmpPtr += 3; i = (long)tmpPtr - (long)tmpStr2; strncpy(startURL,tmpStr2,i); } else { tmpPtr = tmpStr2; i = 0; } *status = fits_path2url(tmpPtr,FLEN_FILENAME-i,startURL+i,status); } } if(realAccess != NULL) strcpy(realAccess,tmpStr3); if(startAccess != NULL) strcpy(startAccess,tmpStr4); if(iostate != NULL) *iostate = tmpIOstate; }while(0); return(*status); } /*-------------------------------------------------------------------------- URL parse support functions --------------------------------------------------------------------------*/ /* simple push/pop/shift/unshift string stack for use by fits_clean_url */ typedef char* grp_stack_data; /* type of data held by grp_stack */ typedef struct grp_stack_item_struct { grp_stack_data data; /* value of this stack item */ struct grp_stack_item_struct* next; /* next stack item */ struct grp_stack_item_struct* prev; /* previous stack item */ } grp_stack_item; typedef struct grp_stack_struct { size_t stack_size; /* number of items on stack */ grp_stack_item* top; /* top item */ } grp_stack; static char* grp_stack_default = NULL; /* initial value for new instances of grp_stack_data */ /* the following functions implement the group string stack grp_stack */ static void delete_grp_stack(grp_stack** mystack); static grp_stack_item* grp_stack_append( grp_stack_item* last, grp_stack_data data ); static grp_stack_data grp_stack_remove(grp_stack_item* last); static grp_stack* new_grp_stack(void); static grp_stack_data pop_grp_stack(grp_stack* mystack); static void push_grp_stack(grp_stack* mystack, grp_stack_data data); static grp_stack_data shift_grp_stack(grp_stack* mystack); /* static void unshift_grp_stack(grp_stack* mystack, grp_stack_data data); */ int fits_clean_url(char *inURL, /* I input URL string */ char *outURL, /* O output URL string */ int *status) /* clean the URL by eliminating any ".." or "." specifiers in the inURL string, and write the output to the outURL string. Note that this function must have a valid Unix-style URL as input; platform dependent path strings are not allowed. */ { grp_stack* mystack; /* stack to hold pieces of URL */ char* tmp; char *saveptr; if(*status) return *status; mystack = new_grp_stack(); *outURL = 0; do { /* handle URL scheme and domain if they exist */ tmp = strstr(inURL, "://"); if(tmp) { /* there is a URL scheme, so look for the end of the domain too */ tmp = strchr(tmp + 3, '/'); if(tmp) { /* tmp is now the end of the domain, so * copy URL scheme and domain as is, and terminate by hand */ size_t string_size = (size_t) (tmp - inURL); strncpy(outURL, inURL, string_size); outURL[string_size] = 0; /* now advance the input pointer to just after the domain and go on */ inURL = tmp; } else { /* '/' was not found, which means there are no path-like * portions, so copy whole inURL to outURL and we're done */ strcpy(outURL, inURL); continue; /* while(0) */ } } /* explicitly copy a leading / (absolute path) */ if('/' == *inURL) strcat(outURL, "/"); /* now clean the remainder of the inURL. push URL segments onto * stack, dealing with .. and . as we go */ tmp = ffstrtok(inURL, "/",&saveptr); /* finds first / */ while(tmp) { if(!strcmp(tmp, "..")) { /* discard previous URL segment, if there was one. if not, * add the .. to the stack if this is *not* an absolute path * (for absolute paths, leading .. has no effect, so skip it) */ if(0 < mystack->stack_size) pop_grp_stack(mystack); else if('/' != *inURL) push_grp_stack(mystack, tmp); } else { /* always just skip ., but otherwise add segment to stack */ if(strcmp(tmp, ".")) push_grp_stack(mystack, tmp); } tmp = ffstrtok(NULL, "/",&saveptr); /* get the next segment */ } /* stack now has pieces of cleaned URL, so just catenate them * onto output string until stack is empty */ while(0 < mystack->stack_size) { tmp = shift_grp_stack(mystack); if (strlen(outURL) + strlen(tmp) + 1 > FLEN_FILENAME-1) { outURL[0]=0; ffpmsg("outURL is too long (fits_clean_url)"); *status = URL_PARSE_ERROR; delete_grp_stack(&mystack); return *status; } strcat(outURL, tmp); strcat(outURL, "/"); } outURL[strlen(outURL) - 1] = 0; /* blank out trailing / */ } while(0); delete_grp_stack(&mystack); return *status; } /* free all stack contents using pop_grp_stack before freeing the * grp_stack itself */ static void delete_grp_stack(grp_stack** mystack) { if(!mystack || !*mystack) return; while((*mystack)->stack_size) pop_grp_stack(*mystack); free(*mystack); *mystack = NULL; } /* append an item to the stack, handling the special case of the first * item appended */ static grp_stack_item* grp_stack_append( grp_stack_item* last, grp_stack_data data ) { /* first create a new stack item, and copy data to it */ grp_stack_item* new_item = (grp_stack_item*) malloc(sizeof(grp_stack_item)); new_item->data = data; if(last) { /* attach this item between the "last" item and its "next" item */ new_item->next = last->next; new_item->prev = last; last->next->prev = new_item; last->next = new_item; } else { /* stack is empty, so "next" and "previous" both point back to it */ new_item->next = new_item; new_item->prev = new_item; } return new_item; } /* remove an item from the stack, handling the special case of the last * item removed */ static grp_stack_data grp_stack_remove(grp_stack_item* last) { grp_stack_data retval = last->data; last->prev->next = last->next; last->next->prev = last->prev; free(last); return retval; } /* create new stack dynamically, and give it valid initial values */ static grp_stack* new_grp_stack(void) { grp_stack* retval = (grp_stack*) malloc(sizeof(grp_stack)); if(retval) { retval->stack_size = 0; retval->top = NULL; } return retval; } /* return the value at the top of the stack and remove it, updating * stack_size. top->prev becomes the new "top" */ static grp_stack_data pop_grp_stack(grp_stack* mystack) { grp_stack_data retval = grp_stack_default; if(mystack && mystack->top) { grp_stack_item* newtop = mystack->top->prev; retval = grp_stack_remove(mystack->top); mystack->top = newtop; if(0 == --mystack->stack_size) mystack->top = NULL; } return retval; } /* add to the stack after the top element. the added element becomes * the new "top" */ static void push_grp_stack(grp_stack* mystack, grp_stack_data data) { if(!mystack) return; mystack->top = grp_stack_append(mystack->top, data); ++mystack->stack_size; return; } /* return the value at the bottom of the stack and remove it, updating * stack_size. "top" pointer is unaffected */ static grp_stack_data shift_grp_stack(grp_stack* mystack) { grp_stack_data retval = grp_stack_default; if(mystack && mystack->top) { retval = grp_stack_remove(mystack->top->next); /* top->next == bottom */ if(0 == --mystack->stack_size) mystack->top = NULL; } return retval; } /* add to the stack after the top element. "top" is unaffected, except * in the special case of an initially empty stack */ /* static void unshift_grp_stack(grp_stack* mystack, grp_stack_data data) { if(!mystack) return; if(mystack->top) grp_stack_append(mystack->top, data); else mystack->top = grp_stack_append(NULL, data); ++mystack->stack_size; return; } */ /*--------------------------------------------------------------------------*/ int fits_url2relurl(char *refURL, /* I reference URL string */ char *absURL, /* I absoulute URL string to process */ char *relURL, /* O resulting relative URL string */ int *status) /* create a relative URL to the file referenced by absURL with respect to the reference URL refURL. The relative URL is returned in relURL. Both refURL and absURL must be absolute URL strings; i.e. either begin with an access method specification "XXX://" or with a '/' character signifiying that they are absolute file paths. Note that it is possible to make a relative URL from two input URLs (absURL and refURL) that are not compatable. This function does not check to see if the resulting relative URL makes any sence. For instance, it is impossible to make a relative URL from the following two inputs: absURL = ftp://a.b.c.com/x/y/z/foo.fits refURL = /a/b/c/ttt.fits The resulting relURL will be: ../../../ftp://a.b.c.com/x/y/z/foo.fits Which is syntically correct but meaningless. The problem is that a file with an access method of ftp:// cannot be expressed a a relative URL to a local disk file. */ { int i,j; int refcount,abscount; int refsize,abssize; int done; if(*status != 0) return(*status); /* initialize the relative URL string */ relURL[0] = 0; do { /* refURL and absURL must be absolute to process */ if(!(fits_is_url_absolute(refURL) || *refURL == '/') || !(fits_is_url_absolute(absURL) || *absURL == '/')) { *status = URL_PARSE_ERROR; ffpmsg("Cannot make rel. URL from non abs. URLs (fits_url2relurl)"); continue; } /* determine the size of the refURL and absURL strings */ refsize = strlen(refURL); abssize = strlen(absURL); /* process the two URL strings and build the relative URL between them */ for(done = 0, refcount = 0, abscount = 0; !done && refcount < refsize && abscount < abssize; ++refcount, ++abscount) { for(; abscount < abssize && absURL[abscount] == '/'; ++abscount); for(; refcount < refsize && refURL[refcount] == '/'; ++refcount); /* find the next path segment in absURL */ for(i = abscount; absURL[i] != '/' && i < abssize; ++i); /* find the next path segment in refURL */ for(j = refcount; refURL[j] != '/' && j < refsize; ++j); /* do the two path segments match? */ if(i == j && strncmp(absURL+abscount, refURL+refcount,i-refcount) == 0) { /* they match, so ignore them and continue */ abscount = i; refcount = j; continue; } /* We found a difference in the paths in refURL and absURL. For every path segment remaining in the refURL string, append a "../" path segment to the relataive URL relURL. */ for(j = refcount; j < refsize; ++j) if(refURL[j] == '/') { if (strlen(relURL)+3 > FLEN_FILENAME-1) { *status = URL_PARSE_ERROR; ffpmsg("relURL too long (fits_url2relurl)"); return (*status); } strcat(relURL,"../"); } /* copy all remaining characters of absURL to the output relURL */ if (strlen(relURL) + strlen(absURL+abscount) > FLEN_FILENAME-1) { *status = URL_PARSE_ERROR; ffpmsg("relURL too long (fits_url2relurl)"); return (*status); } strcat(relURL,absURL+abscount); /* we are done building the relative URL */ done = 1; } }while(0); return(*status); } /*--------------------------------------------------------------------------*/ int fits_relurl2url(char *refURL, /* I reference URL string */ char *relURL, /* I relative URL string to process */ char *absURL, /* O absolute URL string */ int *status) /* create an absolute URL from a relative url and a reference URL. The reference URL is given by the FITS file pointed to by fptr. The construction of the absolute URL from the partial and reference URl is performed using the rules set forth in: http://www.w3.org/Addressing/URL/URL_TOC.html and http://www.w3.org/Addressing/URL/4_3_Partial.html Note that the relative URL string relURL must conform to the Unix-like URL syntax; host dependent partial URL strings are not allowed. */ { int i; char tmpStr[FLEN_FILENAME]; char *tmpStr1, *tmpStr2; if(*status != 0) return(*status); do { /* make a copy of the reference URL string refURL for parsing purposes */ if (strlen(refURL) > FLEN_FILENAME-1) { absURL[0]=0; ffpmsg("ref URL is too long (fits_relurl2url)"); *status = URL_PARSE_ERROR; continue; } strcpy(tmpStr,refURL); /* if the reference file has an access method of mem:// or shmem:// then we cannot use it as the basis of an absolute URL construction for a partial URL */ if(fits_strncasecmp(tmpStr,"MEM:",4) == 0 || fits_strncasecmp(tmpStr,"SHMEM:",6) == 0) { ffpmsg("ref URL has access mem:// or shmem:// (fits_relurl2url)"); ffpmsg(" cannot construct full URL from a partial URL and "); ffpmsg(" MEM/SHMEM base URL"); *status = URL_PARSE_ERROR; continue; } if(relURL[0] != '/') { /* just append the relative URL string to the reference URL string (minus the reference URL file name) to form the absolute URL string */ tmpStr1 = strrchr(tmpStr,'/'); if(tmpStr1 != NULL) tmpStr1[1] = 0; else tmpStr[0] = 0; if (strlen(tmpStr)+strlen(relURL) > FLEN_FILENAME-1) { absURL[0]=0; ffpmsg("rel + ref URL is too long (fits_relurl2url)"); *status = URL_PARSE_ERROR; continue; } strcat(tmpStr,relURL); } else { /* have to parse the refURL string for the first occurnace of the same number of '/' characters as contained in the beginning of location that is not followed by a greater number of consective '/' charaters (yes, that is a confusing statement); this is the location in the refURL string where the relURL string is to be appended to form the new absolute URL string */ /* first, build up a slash pattern string that has one more slash in it than the starting slash pattern of the relURL string */ strcpy(absURL,"/"); for(i = 0; relURL[i] == '/'; ++i) { if (strlen(absURL) + 1 > FLEN_FILENAME-1) { absURL[0]=0; ffpmsg("abs URL is too long (fits_relurl2url)"); *status = URL_PARSE_ERROR; return (*status); } strcat(absURL,"/"); } /* loop over the refURL string until the slash pattern stored in absURL is no longer found */ for(tmpStr1 = tmpStr, i = strlen(absURL); (tmpStr2 = strstr(tmpStr1,absURL)) != NULL; tmpStr1 = tmpStr2 + i); /* reduce the slash pattern string by one slash */ absURL[i-1] = 0; /* search for the slash pattern in the remaining portion of the refURL string */ tmpStr2 = strstr(tmpStr1,absURL); /* if no slash pattern match was found */ if(tmpStr2 == NULL) { /* just strip off the file name from the refURL */ tmpStr2 = strrchr(tmpStr1,'/'); if(tmpStr2 != NULL) tmpStr2[0] = 0; else tmpStr[0] = 0; } else { /* set a string terminator at the slash pattern match */ *tmpStr2 = 0; } /* conatenate the relURL string to the refURL string to form the absURL */ if (strlen(tmpStr)+strlen(relURL) > FLEN_FILENAME-1) { absURL[0]=0; ffpmsg("rel + ref URL is too long (fits_relurl2url)"); *status = URL_PARSE_ERROR; continue; } strcat(tmpStr,relURL); } /* normalize the absURL by removing any ".." or "." specifiers in the string */ *status = fits_clean_url(tmpStr,absURL,status); }while(0); return(*status); } /*--------------------------------------------------------------------------*/ int fits_encode_url(char *inpath, /* I URL to be encoded */ int maxlength, /* I max number of chars that may be copied to outpath, including terminating NULL. */ char *outpath, /* O output encoded URL */ int *status) /* encode all URL "unsafe" and "reserved" characters using the "%XX" convention, where XX stand for the two hexidecimal digits of the encode character's ASCII code. Note that the outpath length, as specified by the maxlength argument, should be at least as large as inpath and preferably larger (to hold any characters that need encoding). If more than maxlength chars are required for outpath, including the terminating NULL, outpath will be set to size 0 and an error status will be returned. This function was adopted from code in the libwww.a library available via the W3 consortium */ { unsigned char a; char *p; char *q; char *hex = "0123456789ABCDEF"; int iout=0; unsigned const char isAcceptable[96] = {/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF */ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0xE,0x0,0xF,0xF,0xC, /* 2x !"#$%&'()*+,-./ */ 0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x8,0x0,0x0,0x0,0x0,0x0, /* 3x 0123456789:;<=>? */ 0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, /* 4x @ABCDEFGHIJKLMNO */ 0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xF, /* 5X PQRSTUVWXYZ[\]^_ */ 0x0,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, /* 6x `abcdefghijklmno */ 0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0x0 /* 7X pqrstuvwxyz{\}~DEL */ }; if(*status != 0) return(*status); /* loop over all characters in inpath until '\0' is encountered */ for(q = outpath, p = inpath; *p && (iout < maxlength-1) ; p++) { a = (unsigned char)*p; /* if the charcter requires encoding then process it */ if(!( a>=32 && a<128 && (isAcceptable[a-32]))) { if (iout+2 < maxlength-1) { /* add a '%' character to the outpath */ *q++ = HEX_ESCAPE; /* add the most significant ASCII code hex value */ *q++ = hex[a >> 4]; /* add the least significant ASCII code hex value */ *q++ = hex[a & 15]; iout += 3; } else { ffpmsg("URL input is too long to encode (fits_encode_url)"); *status = URL_PARSE_ERROR; outpath[0] = 0; return (*status); } } /* else just copy the character as is */ else { *q++ = *p; iout++; } } /* null terminate the outpath string */ if (*p && (iout == maxlength-1)) { ffpmsg("URL input is too long to encode (fits_encode_url)"); *status = URL_PARSE_ERROR; outpath[0] = 0; return (*status); } *q++ = 0; return(*status); } /*---------------------------------------------------------------------------*/ int fits_unencode_url(char *inpath, /* I input URL with encoding */ char *outpath, /* O unencoded URL */ int *status) /* unencode all URL "unsafe" and "reserved" characters to their actual ASCII representation. All tokens of the form "%XX" where XX is the hexidecimal code for an ASCII character, are searched for and translated into the actuall ASCII character (so three chars become 1 char). It is assumed that OUTPATH has enough room to hold the unencoded URL. This function was adopted from code in the libwww.a library available via the W3 consortium */ { char *p; char *q; char c; if(*status != 0) return(*status); p = inpath; q = outpath; /* loop over all characters in the inpath looking for the '%' escape character; if found the process the escape sequence */ while(*p != 0) { /* if the character is '%' then unencode the sequence, else just copy the character from inpath to outpath */ if (*p == HEX_ESCAPE) { if((c = *(++p)) != 0) { *q = ( (c >= '0' && c <= '9') ? (c - '0') : ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) : (c - 'a' + 10)) )*16; if((c = *(++p)) != 0) { *q = *q + ( (c >= '0' && c <= '9') ? (c - '0') : ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) : (c - 'a' + 10)) ); p++, q++; } } } else *q++ = *p++; } /* terminate the outpath */ *q = 0; return(*status); } /*---------------------------------------------------------------------------*/ int fits_is_url_absolute(char *url) /* Return a True (1) or False (0) value indicating whether or not the passed URL string contains an access method specifier or not. Note that this is a boolean function and it neither reads nor returns the standard error status parameter */ { char *tmpStr1, *tmpStr2; char reserved[] = {':',';','/','?','@','&','=','+','$',','}; /* The rule for determing if an URL is relative or absolute is that it (1) must have a colon ":" and (2) that the colon must appear before any other reserved URL character in the URL string. We first see if a colon exists, get its position in the string, and then check to see if any of the other reserved characters exists and if their position in the string is greater than that of the colons. */ if( (tmpStr1 = strchr(url,reserved[0])) != NULL && ((tmpStr2 = strchr(url,reserved[1])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[2])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[3])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[4])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[5])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[6])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[7])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[8])) == NULL || tmpStr2 > tmpStr1) && ((tmpStr2 = strchr(url,reserved[9])) == NULL || tmpStr2 > tmpStr1) ) { return(1); } else { return(0); } } cfitsio-4.3.1/f77_wrap3.c0000644000225700000360000010177613472024437014352 0ustar cagordonlhea/************************************************************************ f77_wrap1.c and f77_wrap2.c have now been split into 4 files to prevent compile-time memory errors (from expansion of compiler commands). f77_wrap1.c was split into f77_wrap1.c and f77_wrap3.c, and f77_wrap2.c was split into f77_wrap2.c and f77_wrap4.c: f77_wrap1.c contains routines operating on whole files and some utility routines. f77_wrap2.c contains routines operating on primary array, image, or column elements. f77_wrap3.c contains routines operating on headers & keywords. f77_wrap4.c contains miscellaneous routines. Peter's original comments: Together, f77_wrap1.c and f77_wrap2.c contain C wrappers for all the CFITSIO routines prototyped in fitsio.h, except for the generic datatype routines and features not supported in fortran (eg, unsigned integers), a few routines prototyped in fitsio2.h, which only a handful of FTOOLS use, plus a few obsolete FITSIO routines not present in CFITSIO. This file allows Fortran code to use the CFITSIO library instead of the FITSIO library without modification. It also gives access to new routines not present in FITSIO. Fortran FTOOLS must continue using the old routine names from FITSIO (ie, ftxxxx), but most of the C-wrappers simply redirect those calls to the corresponding CFITSIO routines (ie, ffxxxx), with appropriate parameter massaging where necessary. The main exception are read/write routines ending in j (ie, long data) which get redirected to C routines ending in k (ie, int data). This is more consistent with the default integer type in Fortran. f77_wrap1.c primarily holds routines operating on whole files and extension headers. f77_wrap2.c handle routines which read and write the data portion, plus miscellaneous extra routines. File created by Peter Wilson (HSTX), Oct-Dec. 1997 ************************************************************************/ #include "fitsio2.h" #include "f77_wrap.h" /*----------------- write single keywords --------------*/ FCALLSCSUB3(ffprec,FTPREC,ftprec,FITSUNIT,STRING,PINT) FCALLSCSUB3(ffpcom,FTPCOM,ftpcom,FITSUNIT,STRING,PINT) FCALLSCSUB4(ffpunt,FTPUNT,ftpunt,FITSUNIT,STRING,STRING,PINT) FCALLSCSUB3(ffphis,FTPHIS,ftphis,FITSUNIT,STRING,PINT) FCALLSCSUB2(ffpdat,FTPDAT,ftpdat,FITSUNIT,PINT) FCALLSCSUB3(ffgstm,FTGSTM,ftgstm,PSTRING,PINT,PINT) FCALLSCSUB4(ffgsdt,FTGSDT,ftgsdt,PINT,PINT,PINT,PINT) FCALLSCSUB5(ffdt2s,FTDT2S,ftdt2s,INT,INT,INT,PSTRING,PINT) FCALLSCSUB9(fftm2s,FTTM2S,fttm2s,INT,INT,INT,INT,INT,DOUBLE,INT,PSTRING,PINT) FCALLSCSUB5(ffs2dt,FTS2DT,fts2dt,STRING,PINT,PINT,PINT,PINT) FCALLSCSUB8(ffs2tm,FTS2TM,fts2tm,STRING,PINT,PINT,PINT,PINT,PINT,PDOUBLE,PINT) FCALLSCSUB4(ffpkyu,FTPKYU,ftpkyu,FITSUNIT,STRING,STRING,PINT) FCALLSCSUB5(ffpkys,FTPKYS,ftpkys,FITSUNIT,STRING,STRING,STRING,PINT) FCALLSCSUB5(ffpkls,FTPKLS,ftpkls,FITSUNIT,STRING,STRING,STRING,PINT) FCALLSCSUB2(ffplsw,FTPLSW,ftplsw,FITSUNIT,PINT) FCALLSCSUB5(ffpkyl,FTPKYL,ftpkyl,FITSUNIT,STRING,INT,STRING,PINT) FCALLSCSUB5(ffpkyj,FTPKYJ,ftpkyj,FITSUNIT,STRING,LONG,STRING,PINT) FCALLSCSUB5(ffpkyj,FTPKYK,ftpkyk,FITSUNIT,STRING,LONGLONG,STRING,PINT) FCALLSCSUB6(ffpkyf,FTPKYF,ftpkyf,FITSUNIT,STRING,FLOAT,INT,STRING,PINT) FCALLSCSUB6(ffpkye,FTPKYE,ftpkye,FITSUNIT,STRING,FLOAT,INT,STRING,PINT) FCALLSCSUB6(ffpkyg,FTPKYG,ftpkyg,FITSUNIT,STRING,DOUBLE,INT,STRING,PINT) FCALLSCSUB6(ffpkyd,FTPKYD,ftpkyd,FITSUNIT,STRING,DOUBLE,INT,STRING,PINT) FCALLSCSUB6(ffpkyc,FTPKYC,ftpkyc,FITSUNIT,STRING,FLOATV,INT,STRING,PINT) FCALLSCSUB6(ffpkym,FTPKYM,ftpkym,FITSUNIT,STRING,DOUBLEV,INT,STRING,PINT) FCALLSCSUB6(ffpkfc,FTPKFC,ftpkfc,FITSUNIT,STRING,FLOATV,INT,STRING,PINT) FCALLSCSUB6(ffpkfm,FTPKFM,ftpkfm,FITSUNIT,STRING,DOUBLEV,INT,STRING,PINT) FCALLSCSUB6(ffpkyt,FTPKYT,ftpkyt,FITSUNIT,STRING,LONG,DOUBLE,STRING,PINT) #define ftptdm_LONGV_A4 A3 FCALLSCSUB5(ffptdm,FTPTDM,ftptdm,FITSUNIT,INT,INT,LONGV,PINT) /*----------------- write array of keywords --------------*/ #define ftpkns_STRV_A5 NUM_ELEM_ARG(4) #define ftpkns_STRV_A6 NUM_ELEM_ARG(4) FCALLSCSUB7(ffpkns,FTPKNS,ftpkns,FITSUNIT,STRING,INT,INT,STRINGV,STRINGV,PINT) /* Must handle LOGICALV conversion manually... ffpknl uses ints */ void Cffpknl( fitsfile *fptr, char *keyroot, int nstart, int nkeys, int *numval, char **comment, int *status ); void Cffpknl( fitsfile *fptr, char *keyroot, int nstart, int nkeys, int *numval, char **comment, int *status ) { int i; for( i=0; i #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffppre( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ float *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine cannot be called directly by users to write to large arrays with > 2**31 pixels (although CFITSIO can do so by passing the firstelem thru a LONGLONG sized global variable) */ { long row; float nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem, 0, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcle(fptr, 2, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffppne( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ float *array, /* I - array of values that are written */ float nulval, /* I - undefined pixel value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). Any array values that are equal to the value of nulval will be replaced with the null pixel value that is appropriate for this column. This routine cannot be called directly by users to write to large arrays with > 2**31 pixels (although CFITSIO can do so by passing the firstelem thru a LONGLONG sized global variable) */ { long row; float nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem, 1, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcne(fptr, 2, row, firstelem, nelem, array, nulval, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp2de(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ float *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine does not support writing to large images with more than 2**31 pixels. */ { /* call the 3D writing routine, with the 3rd dimension = 1 */ ffp3de(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp3de(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ float *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 3-D cube of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine does not support writing to large images with more than 2**31 pixels. */ { long tablerow, ii, jj; long fpixel[3]= {1,1,1}, lpixel[3]; LONGLONG nfits, narray; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = (long) ncols; lpixel[1] = (long) nrows; lpixel[2] = (long) naxis3; fits_write_compressed_img(fptr, TFLOAT, fpixel, lpixel, 0, array, NULL, status); return(*status); } tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so write all at once */ ffpcle(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to write to */ narray = 0; /* next pixel in input array to be written */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* writing naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffpcle(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpsse(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long naxis, /* I - number of data axes in array */ long *naxes, /* I - size of each FITS axis */ long *fpixel, /* I - 1st pixel in each axis to write (1=1st) */ long *lpixel, /* I - last pixel in each axis to write */ float *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write a subsection of pixels to the primary array or image. A subsection is defined to be any contiguous rectangular array of pixels within the n-dimensional FITS data file. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow; LONGLONG fpix[7], dimen[7], astart, pstart; LONGLONG off2, off3, off4, off5, off6, off7; LONGLONG st10, st20, st30, st40, st50, st60, st70; LONGLONG st1, st2, st3, st4, st5, st6, st7; long ii, i1, i2, i3, i4, i5, i6, i7, irange[7]; if (*status > 0) return(*status); if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_img(fptr, TFLOAT, fpixel, lpixel, 0, array, NULL, status); return(*status); } if (naxis < 1 || naxis > 7) return(*status = BAD_DIMEN); tablerow=maxvalue(1,group); /* calculate the size and number of loops to perform in each dimension */ for (ii = 0; ii < 7; ii++) { fpix[ii]=1; irange[ii]=1; dimen[ii]=1; } for (ii = 0; ii < naxis; ii++) { fpix[ii]=fpixel[ii]; irange[ii]=lpixel[ii]-fpixel[ii]+1; dimen[ii]=naxes[ii]; } i1=irange[0]; /* compute the pixel offset between each dimension */ off2 = dimen[0]; off3 = off2 * dimen[1]; off4 = off3 * dimen[2]; off5 = off4 * dimen[3]; off6 = off5 * dimen[4]; off7 = off6 * dimen[5]; st10 = fpix[0]; st20 = (fpix[1] - 1) * off2; st30 = (fpix[2] - 1) * off3; st40 = (fpix[3] - 1) * off4; st50 = (fpix[4] - 1) * off5; st60 = (fpix[5] - 1) * off6; st70 = (fpix[6] - 1) * off7; /* store the initial offset in each dimension */ st1 = st10; st2 = st20; st3 = st30; st4 = st40; st5 = st50; st6 = st60; st7 = st70; astart = 0; for (i7 = 0; i7 < irange[6]; i7++) { for (i6 = 0; i6 < irange[5]; i6++) { for (i5 = 0; i5 < irange[4]; i5++) { for (i4 = 0; i4 < irange[3]; i4++) { for (i3 = 0; i3 < irange[2]; i3++) { pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7; for (i2 = 0; i2 < irange[1]; i2++) { if (ffpcle(fptr, 2, tablerow, pstart, i1, &array[astart], status) > 0) return(*status); astart += i1; pstart += off2; } st2 = st20; st3 = st3+off3; } st3 = st30; st4 = st4+off4; } st4 = st40; st5 = st5+off5; } st5 = st50; st6 = st6+off6; } st6 = st60; st7 = st7+off7; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpgpe( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long firstelem, /* I - first vector element to write(1 = 1st) */ long nelem, /* I - number of values to write */ float *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of group parameters to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffpcle(fptr, 1L, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpcle( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ float *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of values to a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer to a virtual column in a 1 or more grouped FITS primary array. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary. */ { int tcode, maxelem2, hdutype, writeraw; long twidth, incre; long ntodo; LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem; double scale, zero; char tform[20], cform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero, tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); maxelem = maxelem2; if (tcode == TSTRING) ffcfmt(tform, cform); /* derive C format for writing strings */ /* if there is no scaling and the native machine format is not byteswapped then we can simply write the raw data bytes into the FITS file if the datatype of the FITS column is the same as the input values. Otherwise, we must convert the raw values into the scaled and/or machine dependent format in a temporary buffer that has been allocated for this purpose. */ if (scale == 1. && zero == 0. && MACHINE == NATIVE && tcode == TFLOAT) { writeraw = 1; if (nelem < (LONGLONG)INT32_MAX) { maxelem = nelem; } else { maxelem = INT32_MAX/4; } } else writeraw = 0; /*---------------------------------------------------------------------*/ /* Now write the pixels to the FITS column. */ /* First call the ffXXfYY routine to (1) convert the datatype */ /* if necessary, and (2) scale the values by the FITS TSCALn and */ /* TZEROn linear scaling parameters into a temporary buffer. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to write */ next = 0; /* next element in array to be written */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to process a one time to the number that will fit in the buffer space or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre); ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */ switch (tcode) { case (TFLOAT): if (writeraw) { /* write raw input bytes without conversion */ ffpr4b(fptr, ntodo, incre, &array[next], status); } else { /* convert the raw data before writing to FITS file */ ffr4fr4(&array[next], ntodo, scale, zero, (float *) buffer, status); ffpr4b(fptr, ntodo, incre, (float *) buffer, status); } break; case (TLONGLONG): ffr4fi8(&array[next], ntodo, scale, zero, (LONGLONG *) buffer, status); ffpi8b(fptr, ntodo, incre, (long *) buffer, status); break; case (TBYTE): ffr4fi1(&array[next], ntodo, scale, zero, (unsigned char *) buffer, status); ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status); break; case (TSHORT): ffr4fi2(&array[next], ntodo, scale, zero, (short *) buffer, status); ffpi2b(fptr, ntodo, incre, (short *) buffer, status); break; case (TLONG): ffr4fi4(&array[next], ntodo, scale, zero, (INT32BIT *) buffer, status); ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status); break; case (TDOUBLE): ffr4fr8(&array[next], ntodo, scale, zero, (double *) buffer, status); ffpr8b(fptr, ntodo, incre, (double *) buffer, status); break; case (TSTRING): /* numerical column in an ASCII table */ if (cform[1] != 's') /* "%s" format is a string */ { ffr4fstr(&array[next], ntodo, scale, zero, cform, twidth, (char *) buffer, status); if (incre == twidth) /* contiguous bytes */ ffpbyt(fptr, ntodo * twidth, buffer, status); else ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); break; } /* can't write to string column, so fall thru to default: */ default: /* error trap */ snprintf(message, FLEN_ERRMSG, "Cannot write numbers to column %d which has format %s", colnum,tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous write operation */ { snprintf(message,FLEN_ERRMSG, "Error writing elements %.0f thru %.0f of input data array (ffpcle).", (double) (next+1), (double) (next+ntodo)); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while writing FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpclc( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ float *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of complex values to a column in the current FITS HDU. Each complex number if interpreted as a pair of float values. The column number may refer to a real column in an ASCII or binary table, or it may refer to a virtual column in a 1 or more grouped FITS primary array. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The input array of values will be converted to the datatype of the column if necessary, but normally complex values should only be written to a binary table with TFORMn = 'rC' where r is an optional repeat count. The TSCALn and TZERO keywords should not be used with complex numbers because mathmatically the scaling should only be applied to the real (first) component of the complex value. */ { /* simply multiply the number of elements by 2, and call ffpcle */ ffpcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpcne( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ float *array, /* I - array of values to write */ float nulvalue, /* I - value used to flag undefined pixels */ int *status) /* IO - error status */ /* Write an array of elements to the specified column of a table. Any input pixels equal to the value of nulvalue will be replaced by the appropriate null value in the output FITS file. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary */ { tcolumn *colptr; LONGLONG ngood = 0, nbad = 0, ii; LONGLONG repeat, first, fstelm, fstrow; int tcode, overflow = 0; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode > 0) repeat = colptr->trepeat; /* repeat count for this column */ else repeat = firstelem -1 + nelem; /* variable length arrays */ if (abs(tcode) >= TCOMPLEX) { /* treat complex columns as pairs of numbers */ repeat *= 2; } /* if variable length array, first write the whole input vector, then go back and fill in the nulls */ if (tcode < 0) { if (ffpcle(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) { if (*status == NUM_OVERFLOW) { /* ignore overflows, which are possibly the null pixel values */ /* overflow = 1; */ *status = 0; } else { return(*status); } } } /* absolute element number in the column */ first = (firstrow - 1) * repeat + firstelem; for (ii = 0; ii < nelem; ii++) { if (array[ii] != nulvalue) /* is this a good pixel? */ { if (nbad) /* write previous string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ /* call ffpcluc, not ffpclu, in case we are writing to a complex ('C') binary table column */ if (ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status) > 0) return(*status); nbad=0; } ngood = ngood +1; /* the consecutive number of good pixels */ } else { if (ngood) /* write previous string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ if (ffpcle(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status) > 0) { if (*status == NUM_OVERFLOW) { overflow = 1; *status = 0; } else { return(*status); } } } ngood=0; } nbad = nbad +1; /* the consecutive number of bad pixels */ } } /* finished loop; now just write the last set of pixels */ if (ngood) /* write last string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ ffpcle(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status); } } else if (nbad) /* write last string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status); } if (*status <= 0) { if (overflow) { *status = NUM_OVERFLOW; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fi1(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ unsigned char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) (dvalue + .5); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fi2(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ short *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DSHRT_MIN) { *status = OVERFLOW_ERR; output[ii] = SHRT_MIN; } else if (input[ii] > DSHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else output[ii] = (short) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; output[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else { if (dvalue >= 0) output[ii] = (short) (dvalue + .5); else output[ii] = (short) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fi4(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ INT32BIT *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DINT_MIN) { *status = OVERFLOW_ERR; output[ii] = INT32_MIN; } else if (input[ii] > DINT_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else output[ii] = (INT32BIT) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; output[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else { if (dvalue >= 0) output[ii] = (INT32BIT) (dvalue + .5); else output[ii] = (INT32BIT) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fi8(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ LONGLONG *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 9223372036854775808.) { /* Writing to unsigned long long column. Input values must not be negative */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] < -0.49) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (input[ii] > 2.* DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { output[ii] = ((LONGLONG) input[ii]) ^ 0x8000000000000000; } } } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (input[ii] > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (long) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { if (dvalue >= 0) output[ii] = (LONGLONG) (dvalue + .5); else output[ii] = (LONGLONG) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fr4(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ float *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { memcpy(output, input, ntodo * sizeof(float) ); /* copy input to output */ } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) ((input[ii] - zero) / scale); } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fr8(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ double *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (double) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (input[ii] - zero) / scale; } return(*status); } /*--------------------------------------------------------------------------*/ int ffr4fstr(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ char *cform, /* I - format for output string values */ long twidth, /* I - width of each field, in chars */ char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do scaling if required. */ { long ii; double dvalue; char *cptr; cptr = output; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { sprintf(output, cform, (double) input[ii]); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; sprintf(output, cform, dvalue); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } /* replace any commas with periods (e.g., in French locale) */ while ((cptr = strchr(cptr, ','))) *cptr = '.'; return(*status); } cfitsio-4.3.1/testf77.f0000644000225700000360000023441413472024437014135 0ustar cagordonlheaC This is a big and complicated program that tests most of C the fitsio routines. This code does not represent C the most efficient method of reading or writing FITS files C because this code is primarily designed to stress the fitsio C library routines. character asciisum*17 character*3 cval character*1 xinarray(21), binarray(21), boutarray(21), bnul character colname*70, tdisp*40, nulstr*40 character oskey*15 character iskey*21 character lstr*200 character comm*73 character*30 inskey(21) character*30 onskey(3) character filename*40, card*78, card2*78 character keyword*8 character value*68, comment*72 character uchars*78 character*15 ttype(10), tform(10), tunit(10) character*15 tblname character*15 binname character errmsg*75 character*8 inclist(2),exclist(2) character*8 xctype,yctype,ctype character*18 kunit logical simple,extend,larray(42), larray2(42) logical olkey, ilkey, onlkey(3), inlkey(3), anynull integer*2 imgarray(19,30), imgarray2(10,20) integer*2 iinarray(21), ioutarray(21), inul integer naxes(3), pcount, gcount, npixels, nrows, rowlen integer existkeys, morekeys, keynum integer datastatus, hdustatus integer status, bitpix, naxis, block integer ii, jj, jjj, hdutype, hdunum, tfields integer nkeys, nfound, colnum, typecode, signval,nmsg integer repeat, offset, width, jnulval integer kinarray(21), koutarray(21), knul integer jinarray(21), joutarray(21), jnul integer ojkey, ijkey, otint integer onjkey(3), injkey(3) integer tbcol(5) integer iunit, tmpunit integer fpixels(2), lpixels(2), inc(2) real estatus, vers real einarray(21), eoutarray(21), enul, cinarray(42) real ofkey, oekey, iekey, onfkey(3),onekey(3), inekey(3) double precision dinarray(21),doutarray(21),dnul, minarray(42) double precision scale, zero double precision ogkey, odkey, idkey, otfrac, ongkey(3) double precision ondkey(3), indkey(3) double precision checksum, datsum double precision xrval,yrval,xrpix,yrpix,xinc,yinc,rot double precision xpos,ypos,xpix,ypix tblname = 'Test-ASCII' binname = 'Test-BINTABLE' onskey(1) = 'first string' onskey(2) = 'second string' onskey(3) = ' ' oskey = 'value_string' inclist(1)='key*' inclist(2)='newikys' exclist(1)='key_pr*' exclist(2)='key_pkls' xctype='RA---TAN' yctype='DEC--TAN' olkey = .true. ojkey = 11 otint = 12345678 ofkey = 12.121212 oekey = 13.131313 ogkey = 14.1414141414141414D+00 odkey = 15.1515151515151515D+00 otfrac = .1234567890123456D+00 onlkey(1) = .true. onlkey(2) = .false. onlkey(3) = .true. onjkey(1) = 11 onjkey(2) = 12 onjkey(3) = 13 onfkey(1) = 12.121212 onfkey(2) = 13.131313 onfkey(3) = 14.141414 onekey(1) = 13.131313 onekey(2) = 14.141414 onekey(3) = 15.151515 ongkey(1) = 14.1414141414141414D+00 ongkey(2) = 15.1515151515151515D+00 ongkey(3) = 16.1616161616161616D+00 ondkey(1) = 15.1515151515151515D+00 ondkey(2) = 16.1616161616161616D+00 ondkey(3) = 17.1717171717171717D+00 tbcol(1) = 1 tbcol(2) = 17 tbcol(3) = 28 tbcol(4) = 43 tbcol(5) = 56 status = 0 call ftvers(vers) write(*,'(1x,A)') 'FITSIO TESTPROG' write(*, '(1x,A)')' ' iunit = 15 tmpunit = 16 write(*,'(1x,A)') 'Try opening then closing a nonexistent file: ' call ftopen(iunit, 'tq123x.kjl', 1, block, status) write(*,'(1x,A,2i4)')' ftopen iunit, status (expect an error) =' & ,iunit, status call ftclos(iunit, status) write(*,'(1x,A,i4)')' ftclos status = ', status write(*,'(1x,A)')' ' call ftcmsg status = 0 filename = 'testf77.fit' C delete previous version of the file, if it exists call ftopen(iunit, filename, 1, block, status) if (status .eq. 0)then call ftdelt(iunit, status) else C clear the error message stack call ftcmsg end if status = 0 C C ##################### C # create FITS file # C ##################### call ftinit(iunit, filename, 1, status) write(*,'(1x,A,i4)')'ftinit create new file status = ', status write(*,'(1x,A)')' ' if (status .ne. 0)go to 999 simple = .true. bitpix = 32 naxis = 2 naxes(1) = 10 naxes(2) = 2 npixels = 20 pcount = 0 gcount = 1 extend = .true. C ############################ C # write single keywords # C ############################ call ftphpr(iunit,simple, bitpix, naxis, naxes, & 0,1,extend,status) call ftprec(iunit, &'key_prec= ''This keyword was written by fxprec'' / '// & 'comment goes here', status) write(*,'(1x,A)') 'test writing of long string keywords: ' card = '1234567890123456789012345678901234567890'// & '12345678901234567890123456789012345' call ftpkys(iunit, 'card1', card, ' ', status) call ftgkey(iunit, 'card1', card2, comment, status) write(*,'(1x,A)') card write(*,'(1x,A)') card2 card = '1234567890123456789012345678901234567890'// & '123456789012345678901234''6789012345' call ftpkys(iunit, 'card2', card, ' ', status) call ftgkey(iunit, 'card2', card2, comment, status) write(*,'(1x,A)') card write(*,'(1x,A)') card2 card = '1234567890123456789012345678901234567890'// & '123456789012345678901234''''789012345' call ftpkys(iunit, 'card3', card, ' ', status) call ftgkey(iunit, 'card3', card2, comment, status) write(*,'(1x,A)') card write(*,'(1x,A)') card2 card = '1234567890123456789012345678901234567890'// & '123456789012345678901234567''9012345' call ftpkys(iunit, 'card4', card, ' ', status) call ftgkey(iunit, 'card4', card2, comment, status) write(*,'(1x,A)') card write(*,'(1x,A)') card2 call ftpkys(iunit, 'key_pkys', oskey, 'fxpkys comment', status) call ftpkyl(iunit, 'key_pkyl', olkey, 'fxpkyl comment', status) call ftpkyj(iunit, 'key_pkyj', ojkey, 'fxpkyj comment', status) call ftpkyf(iunit,'key_pkyf',ofkey,5, 'fxpkyf comment', status) call ftpkye(iunit,'key_pkye',oekey,6, 'fxpkye comment', status) call ftpkyg(iunit,'key_pkyg',ogkey,14, 'fxpkyg comment',status) call ftpkyd(iunit,'key_pkyd',odkey,14, 'fxpkyd comment',status) lstr='This is a very long string '// & 'value that is continued over more than one keyword.' call ftpkls(iunit,'key_pkls',lstr,'fxpkls comment',status) call ftplsw(iunit, status) call ftpkyt(iunit,'key_pkyt',otint,otfrac,'fxpkyt comment', & status) call ftpcom(iunit, 'This keyword was written by fxpcom.', & status) call ftphis(iunit, &' This keyword written by fxphis (w/ 2 leading spaces).', & status) call ftpdat(iunit, status) if (status .gt. 0)go to 999 C C ############################### C # write arrays of keywords # C ############################### nkeys = 3 comm = 'fxpkns comment&' call ftpkns(iunit, 'ky_pkns', 1, nkeys, onskey, comm, status) comm = 'fxpknl comment&' call ftpknl(iunit, 'ky_pknl', 1, nkeys, onlkey, comm, status) comm = 'fxpknj comment&' call ftpknj(iunit, 'ky_pknj', 1, nkeys, onjkey, comm, status) comm = 'fxpknf comment&' call ftpknf(iunit, 'ky_pknf', 1, nkeys, onfkey,5,comm,status) comm = 'fxpkne comment&' call ftpkne(iunit, 'ky_pkne', 1, nkeys, onekey,6,comm,status) comm = 'fxpkng comment&' call ftpkng(iunit, 'ky_pkng', 1, nkeys, ongkey,13,comm,status) comm = 'fxpknd comment&' call ftpknd(iunit, 'ky_pknd', 1, nkeys, ondkey,14,comm,status) if (status .gt. 0)go to 999 C ############################ C # write generic keywords # C ############################ oskey = '1' call ftpkys(iunit, 'tstring', oskey, 'tstring comment',status) olkey = .true. call ftpkyl(iunit, 'tlogical', olkey, 'tlogical comment', & status) ojkey = 11 call ftpkyj(iunit, 'tbyte', ojkey, 'tbyte comment', status) ojkey = 21 call ftpkyj(iunit, 'tshort', ojkey, 'tshort comment', status) ojkey = 31 call ftpkyj(iunit, 'tint', ojkey, 'tint comment', status) ojkey = 41 call ftpkyj(iunit, 'tlong', ojkey, 'tlong comment', status) oekey = 42 call ftpkye(iunit, 'tfloat', oekey, 6,'tfloat comment', status) odkey = 82.D+00 call ftpkyd(iunit, 'tdouble', odkey, 14, 'tdouble comment', & status) if (status .gt. 0)go to 999 write(*,'(1x,A)') 'Wrote all Keywords successfully ' C ############################ C # write data # C ############################ C define the null value (must do this before writing any data) call ftpkyj(iunit,'BLANK',-99, & 'value to use for undefined pixels', status) C initialize arrays of values to write to primary array do ii = 1, npixels boutarray(ii) = char(ii) ioutarray(ii) = ii joutarray(ii) = ii eoutarray(ii) = ii doutarray(ii) = ii end do C write a few pixels with each datatype C set the last value in each group of 4 as undefined call ftpprb(iunit, 1, 1, 2, boutarray(1), status) call ftppri(iunit, 1, 5, 2, ioutarray(5), status) call ftpprj(iunit, 1, 9, 2, joutarray(9), status) call ftppre(iunit, 1, 13, 2, eoutarray(13), status) call ftpprd(iunit, 1, 17, 2, doutarray(17), status) bnul = char(4) call ftppnb(iunit, 1, 3, 2, boutarray(3), bnul, status) inul = 8 call ftppni(iunit, 1, 7, 2, ioutarray(7), inul, status) call ftppnj(iunit, 1, 11, 2, joutarray(11), 12, status) call ftppne(iunit, 1, 15, 2, eoutarray(15), 16., status) dnul = 20. call ftppnd(iunit, 1, 19, 2, doutarray(19), dnul, status) call ftppru(iunit, 1, 1, 1, status) if (status .gt. 0)then write(*,'(1x,A,I4)')'ftppnx status = ', status goto 999 end if call ftflus(iunit, status) C flush all data to the disk file write(*,'(1x,A,I4)')'ftflus status = ', status write(*,'(1x,A)')' ' call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)')'HDU number = ', hdunum C ############################ C # read data # C ############################ C read back the data, setting null values = 99 write(*,'(1x,A)') & 'Values read back from primary array (99 = null pixel)' write(*,'(1x,A)') & 'The 1st, and every 4th pixel should be undefined: ' anynull = .false. bnul = char(99) call ftgpvb(iunit, 1, 1, 10, bnul, binarray, anynull, status) call ftgpvb(iunit, 1, 11, 10, bnul, binarray(11),anynull,status) do ii = 1,npixels iinarray(ii) = ichar(binarray(ii)) end do write(*,1101) (iinarray(ii), ii = 1, npixels), anynull, & ' (ftgpvb) ' 1101 format(1x,20i3,l3,a) inul = 99 call ftgpvi(iunit, 1, 1, npixels, inul, iinarray,anynull,status) write(*,1101) (iinarray(ii), ii = 1, npixels), anynull, & ' (ftgpvi) ' call ftgpvj(iunit, 1, 1, npixels, 99, jinarray,anynull,status) write(*,1101) (jinarray(ii), ii = 1, npixels), anynull, & ' (ftgpvj) ' call ftgpve(iunit, 1, 1, npixels, 99., einarray,anynull,status) write(*,1102) (einarray(ii), ii = 1, npixels), anynull, & ' (ftgpve) ' 1102 format(2x,20f3.0,l2,a) dnul = 99. call ftgpvd(iunit, 1, 1, 10, dnul, dinarray, anynull, status) call ftgpvd(iunit, 1, 11, 10, dnul,dinarray(11),anynull,status) write(*,1102) (dinarray(ii), ii = 1, npixels), anynull, & ' (ftgpvd) ' if (status .gt. 0)then write(*,'(1x,A,I4)')'ERROR: ftgpv_ status = ', status goto 999 end if if (.not. anynull)then write(*,'(1x,A)') 'ERROR: ftgpv_ did not detect null values ' go to 999 end if C reset the output null value to the expected input value do ii = 4, npixels, 4 boutarray(ii) = char(99) ioutarray(ii) = 99 joutarray(ii) = 99 eoutarray(ii) = 99. doutarray(ii) = 99. end do ii = 1 boutarray(ii) = char(99) ioutarray(ii) = 99 joutarray(ii) = 99 eoutarray(ii) = 99. doutarray(ii) = 99. C compare the output with the input flag any differences do ii = 1, npixels if (boutarray(ii) .ne. binarray(ii))then write(*,'(1x,A,2A2)') 'bout != bin ', boutarray(ii), & binarray(ii) end if if (ioutarray(ii) .ne. iinarray(ii))then write(*,'(1x,A,2I8)') 'bout != bin ', ioutarray(ii), & iinarray(ii) end if if (joutarray(ii) .ne. jinarray(ii))then write(*,'(1x,A,2I12)') 'bout != bin ', joutarray(ii), & jinarray(ii) end if if (eoutarray(ii) .ne. einarray(ii))then write(*,'(1x,A,2E15.3)') 'bout != bin ', eoutarray(ii), & einarray(ii) end if if (doutarray(ii) .ne. dinarray(ii))then write(*,'(1x,A,2D20.6)') 'bout != bin ', doutarray(ii), & dinarray(ii) end if end do do ii = 1, npixels binarray(ii) = char(0) iinarray(ii) = 0 jinarray(ii) = 0 einarray(ii) = 0. dinarray(ii) = 0. end do anynull = .false. call ftgpfb(iunit, 1, 1, 10, binarray, larray, anynull,status) call ftgpfb(iunit, 1, 11, 10, binarray(11), larray(11), & anynull, status) do ii = 1, npixels if (larray(ii))binarray(ii) = char(0) end do do ii = 1,npixels iinarray(ii) = ichar(binarray(ii)) end do write(*,1101)(iinarray(ii),ii = 1,npixels),anynull,' (ftgpfb)' call ftgpfi(iunit, 1, 1, npixels, iinarray, larray, anynull, & status) do ii = 1, npixels if (larray(ii))iinarray(ii) = 0 end do write(*,1101)(iinarray(ii),ii = 1,npixels),anynull,' (ftgpfi)' call ftgpfj(iunit, 1, 1, npixels, jinarray, larray, anynull, & status) do ii = 1, npixels if (larray(ii))jinarray(ii) = 0 end do write(*,1101)(jinarray(ii),ii = 1,npixels),anynull,' (ftgpfj)' call ftgpfe(iunit, 1, 1, npixels, einarray, larray, anynull, & status) do ii = 1, npixels if (larray(ii))einarray(ii) = 0. end do write(*,1102)(einarray(ii),ii = 1,npixels),anynull,' (ftgpfe)' call ftgpfd(iunit, 1, 1, 10, dinarray, larray, anynull,status) call ftgpfd(iunit, 1, 11, 10, dinarray(11), larray(11), & anynull, status) do ii = 1, npixels if (larray(ii))dinarray(ii) = 0. end do write(*,1102)(dinarray(ii),ii = 1,npixels),anynull,' (ftgpfd)' if (status .gt. 0)then write(*,'(1x,A,I4)')'ERROR: ftgpf_ status = ', status go to 999 end if if (.not. anynull)then write(*,'(1x,A)') 'ERROR: ftgpf_ did not detect null values' go to 999 end if C ########################################## C # close and reopen file multiple times # C ########################################## do ii = 1, 10 call ftclos(iunit, status) if (status .gt. 0)then write(*,'(1x,A,I4)')'ERROR in ftclos (1) = ', status go to 999 end if call ftopen(iunit, filename, 1, block, status) if (status .gt. 0)then write(*,'(1x,A,I4)')'ERROR: ftopen open file status = ', & status go to 999 end if end do write(*,'(1x,A)') ' ' write(*,'(1x,A)') 'Closed then reopened the FITS file 10 times.' write(*,'(1x,A)')' ' call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)')'HDU number = ', hdunum C ############################ C # read single keywords # C ############################ simple = .false. bitpix = 0 naxis = 0 naxes(1) = 0 naxes(2) = 0 pcount = -99 gcount = -99 extend = .false. write(*,'(1x,A)') 'Read back keywords: ' call ftghpr(iunit, 3, simple, bitpix, naxis, naxes, pcount, & gcount, extend, status) write(*,'(1x,A,L4,4I4)')'simple, bitpix, naxis, naxes = ', & simple, bitpix, naxis, naxes(1), naxes(2) write(*,'(1x,A,2I4,L4)')' pcount, gcount, extend = ', & pcount, gcount, extend call ftgrec(iunit, 9, card, status) write(*,'(1x,A)') card if (card(1:15) .ne. 'KEY_PREC= ''This') & write(*,'(1x,A)') 'ERROR in ftgrec ' call ftgkyn(iunit, 9, keyword, value, comment, status) write(*,'(1x,5A)') keyword,' ', value(1:35),' ', comment(1:20) if (keyword(1:8) .ne. 'KEY_PREC' ) & write(*,'(1x,2A)') 'ERROR in ftgkyn: ', keyword call ftgcrd(iunit, keyword, card, status) write(*,'(1x,A)') card if (keyword(1:8) .ne. card(1:8) ) & write(*,'(1x,2A)') 'ERROR in ftgcrd: ', keyword call ftgkey(iunit, 'KY_PKNS1', value, comment, status) write(*,'(1x,5A)') 'KY_PKNS1 ',':', value(1:15),':', comment(1:16) if (value(1:14) .ne. '''first string''') & write(*,'(1x,2A)') 'ERROR in ftgkey: ', value call ftgkys(iunit, 'key_pkys', iskey, comment, status) write(*,'(1x,5A,I4)')'KEY_PKYS ',':',iskey,':',comment(1:16), & status call ftgkyl(iunit, 'key_pkyl', ilkey, comment, status) write(*,'(1x,2A,L4,2A,I4)') 'KEY_PKYL ',':', ilkey,':', &comment(1:16), status call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status) write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', & comment(1:16), status call ftgkye(iunit, 'KEY_PKYJ', iekey, comment, status) write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', & comment(1:16), status call ftgkyd(iunit, 'KEY_PKYJ', idkey, comment, status) write(*,'(1x,2A,F12.5,2A,I4)') 'KEY_PKYD ',':',idkey,':', & comment(1:16), status if (ijkey .ne. 11 .or. iekey .ne. 11. .or. idkey .ne. 11.) & write(*,'(1x,A,I4,2F5.1)') 'ERROR in ftgky(jed): ', & ijkey, iekey, idkey iskey= ' ' call ftgkys(iunit, 'key_pkys', iskey, comment, status) write(*,'(1x,5A,I4)') 'KEY_PKYS ',':', iskey,':', comment(1:16), & status ilkey = .false. call ftgkyl(iunit, 'key_pkyl', ilkey, comment, status) write(*,'(1x,2A,L4,2A,I4)') 'KEY_PKYL ',':', ilkey,':', & comment(1:16), status ijkey = 0 call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status) write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', & comment(1:16), status iekey = 0 call ftgkye(iunit, 'KEY_PKYE', iekey, comment, status) write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', & comment(1:16), status idkey = 0 call ftgkyd(iunit, 'KEY_PKYD', idkey, comment, status) write(*,'(1x,2A,F12.5,2A,I4)') 'KEY_PKYD ',':',idkey,':', & comment(1:16), status iekey = 0 call ftgkye(iunit, 'KEY_PKYF', iekey, comment, status) write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYF ',':',iekey,':', & comment(1:16), status iekey = 0 call ftgkye(iunit, 'KEY_PKYE', iekey, comment, status) write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', & comment(1:16), status idkey = 0 call ftgkyd(iunit, 'KEY_PKYG', idkey, comment, status) write(*,'(1x,2A,f16.12,2A,I4)') 'KEY_PKYG ',':',idkey,':', & comment(1:16), status idkey = 0 call ftgkyd(iunit, 'KEY_PKYD', idkey, comment, status) write(*,'(1x,2A,f16.12,2A,I4)') 'KEY_PKYD ',':',idkey,':', & comment(1:16), status call ftgkyt(iunit, 'KEY_PKYT', ijkey, idkey, comment, status) write(*,'(1x,2A,i10,A,f16.14,A,I4)') 'KEY_PKYT ',':', & ijkey,':', idkey, comment(1:16), status call ftpunt(iunit, 'KEY_PKYJ', 'km/s/Mpc', status) ijkey = 0 call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status) write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', & comment(1:38), status call ftgunt(iunit,'KEY_PKYJ',kunit,status) write(*,'(1x,2A)') 'keyword unit=', kunit call ftpunt(iunit, 'KEY_PKYJ', ' ', status) ijkey = 0 call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status) write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', & comment(1:38), status call ftgunt(iunit,'KEY_PKYJ',kunit,status) write(*,'(1x,2A)') 'keyword unit=', kunit call ftpunt(iunit, 'KEY_PKYJ', 'feet/second/second', status) ijkey = 0 call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status) write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', & comment(1:38), status call ftgunt(iunit,'KEY_PKYJ',kunit,status) write(*,'(1x,2A)') 'keyword unit=', kunit call ftgkys(iunit, 'key_pkls', lstr, comment, status) write(*,'(1x,2A)') 'KEY_PKLS long string value = ', lstr(1:50) write(*,'(1x,A)')lstr(51:120) C get size and position in header call ftghps(iunit, existkeys, keynum, status) write(*,'(1x,A,I4,A,I4)') 'header contains ', existkeys, & ' keywords; located at keyword ', keynum C ############################ C # read array keywords # C ############################ call ftgkns(iunit, 'ky_pkns', 1, 3, inskey, nfound, status) write(*,'(1x,4A)') 'ftgkns: ', inskey(1)(1:14), inskey(2)(1:14), & inskey(3)(1:14) if (nfound .ne. 3 .or. status .gt. 0) & write(*,'(1x,A,2I4)') ' ERROR in ftgkns ', nfound, status call ftgknl(iunit, 'ky_pknl', 1, 3, inlkey, nfound, status) write(*,'(1x,A,3L4)') 'ftgknl: ', inlkey(1), inlkey(2), inlkey(3) if (nfound .ne. 3 .or. status .gt. 0) & write(*,'(1x,A,2I4)') ' ERROR in ftgknl ', nfound, status call ftgknj(iunit, 'ky_pknj', 1, 3, injkey, nfound, status) write(*,'(1x,A,3I4)') 'ftgknj: ', injkey(1), injkey(2), injkey(3) if (nfound .ne. 3 .or. status .gt. 0) & write(*,'(1x,A,2I4)') ' ERROR in ftgknj ', nfound, status call ftgkne(iunit, 'ky_pkne', 1, 3, inekey, nfound, status) write(*,'(1x,A,3F10.5)') 'ftgkne: ',inekey(1),inekey(2),inekey(3) if (nfound .ne. 3 .or. status .gt. 0) & write(*,'(1x,A,2I4)') ' ERROR in ftgkne ', nfound, status call ftgknd(iunit, 'ky_pknd', 1, 3, indkey, nfound, status) write(*,'(1x,A,3F10.5)') 'ftgknd: ',indkey(1),indkey(2),indkey(3) if (nfound .ne. 3 .or. status .gt. 0) & write(*,'(1x,A,2I4)') ' ERROR in ftgknd ', nfound, status write(*,'(1x,A)')' ' write(*,'(1x,A)') & 'Before deleting the HISTORY and DATE keywords...' do ii = 29, 32 call ftgrec(iunit, ii, card, status) write(*,'(1x,A)') card(1:8) end do C don't print date value, so that C the output will always be the same C ############################ C # delete keywords # C ############################ call ftdrec(iunit, 30, status) call ftdkey(iunit, 'DATE', status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'After deleting the keywords... ' do ii = 29, 30 call ftgrec(iunit, ii, card, status) write(*,'(1x,A)') card end do if (status .gt. 0) & write(*,'(1x,A)') ' ERROR deleting keywords ' C ############################ C # insert keywords # C ############################ call ftirec(iunit,26, & 'KY_IREC = ''This keyword inserted by fxirec''', & status) call ftikys(iunit, 'KY_IKYS', 'insert_value_string', & 'ikys comment', status) call ftikyj(iunit, 'KY_IKYJ', 49, 'ikyj comment', status) call ftikyl(iunit, 'KY_IKYL', .true., 'ikyl comment', status) call ftikye(iunit, 'KY_IKYE',12.3456,4,'ikye comment',status) odkey = 12.345678901234567D+00 call ftikyd(iunit, 'KY_IKYD', odkey, 14, & 'ikyd comment', status) call ftikyf(iunit, 'KY_IKYF', 12.3456, 4, 'ikyf comment', & status) call ftikyg(iunit, 'KY_IKYG', odkey, 13, & 'ikyg comment', status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'After inserting the keywords... ' do ii = 25, 34 call ftgrec(iunit, ii, card, status) write(*,'(1x,A)') card end do if (status .gt. 0) & write(*,'(1x,A)') ' ERROR inserting keywords ' C ############################ C # modify keywords # C ############################ call ftmrec(iunit, 25, & 'COMMENT This keyword was modified by fxmrec', status) call ftmcrd(iunit, 'KY_IREC', & 'KY_MREC = ''This keyword was modified by fxmcrd''', status) call ftmnam(iunit, 'KY_IKYS', 'NEWIKYS', status) call ftmcom(iunit,'KY_IKYJ','This is a modified comment', & status) call ftmkyj(iunit, 'KY_IKYJ', 50, '&', status) call ftmkyl(iunit, 'KY_IKYL', .false., '&', status) call ftmkys(iunit, 'NEWIKYS', 'modified_string', '&', status) call ftmkye(iunit, 'KY_IKYE', -12.3456, 4, '&', status) odkey = -12.345678901234567D+00 call ftmkyd(iunit, 'KY_IKYD', odkey, 14, & 'modified comment', status) call ftmkyf(iunit, 'KY_IKYF', -12.3456, 4, '&', status) call ftmkyg(iunit,'KY_IKYG', odkey,13,'&',status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'After modifying the keywords... ' do ii = 25, 34 call ftgrec(iunit, ii, card, status) write(*,'(1x,A)') card end do if (status .gt. 0)then write(*,'(1x,A)') ' ERROR modifying keywords ' go to 999 end if C ############################ C # update keywords # C ############################ call ftucrd(iunit, 'KY_MREC', & 'KY_UCRD = ''This keyword was updated by fxucrd''', & status) call ftukyj(iunit, 'KY_IKYJ', 51, '&', status) call ftukyl(iunit, 'KY_IKYL', .true., '&', status) call ftukys(iunit, 'NEWIKYS', 'updated_string', '&', status) call ftukye(iunit, 'KY_IKYE', -13.3456, 4, '&', status) odkey = -13.345678901234567D+00 call ftukyd(iunit, 'KY_IKYD',odkey , 14, & 'modified comment', status) call ftukyf(iunit, 'KY_IKYF', -13.3456, 4, '&', status) call ftukyg(iunit, 'KY_IKYG', odkey, 13, '&', status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'After updating the keywords... ' do ii = 25, 34 call ftgrec(iunit, ii, card, status) write(*,'(1x,A)') card end do if (status .gt. 0)then write(*,'(1x,A)') ' ERROR modifying keywords ' go to 999 end if C move to top of header and find keywords using wild cards call ftgrec(iunit, 0, card, status) write(*,'(1x,A)')' ' write(*,'(1x,A)') & 'Keywords found using wildcard search (should be 9)...' nfound = -1 91 nfound = nfound +1 call ftgnxk(iunit, inclist, 2, exclist, 2, card, status) if (status .eq. 0)then write(*,'(1x,A)') card go to 91 end if if (nfound .ne. 9)then write(*,'(1x,A)') & 'ERROR reading keywords using wildcards (ftgnxk)' go to 999 end if status = 0 C ############################ C # create binary table # C ############################ tform(1) = '15A' tform(2) = '1L' tform(3) = '16X' tform(4) = '1B' tform(5) = '1I' tform(6) = '1J' tform(7) = '1E' tform(8) = '1D' tform(9) = '1C' tform(10)= '1M' ttype(1) = 'Avalue' ttype(2) = 'Lvalue' ttype(3) = 'Xvalue' ttype(4) = 'Bvalue' ttype(5) = 'Ivalue' ttype(6) = 'Jvalue' ttype(7) = 'Evalue' ttype(8) = 'Dvalue' ttype(9) = 'Cvalue' ttype(10)= 'Mvalue' tunit(1) = ' ' tunit(2) = 'm**2' tunit(3) = 'cm' tunit(4) = 'erg/s' tunit(5) = 'km/s' tunit(6) = ' ' tunit(7) = ' ' tunit(8) = ' ' tunit(9) = ' ' tunit(10)= ' ' nrows = 21 tfields = 10 pcount = 0 call ftibin(iunit, nrows, tfields, ttype, tform, tunit, & binname, pcount, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)') 'ftibin status = ', status call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum C get size and position in header, and reserve space for more keywords call ftghps(iunit, existkeys, keynum, status) write(*,'(1x,A,I4,A,I4)') 'header contains ',existkeys, & ' keywords located at keyword ', keynum morekeys = 40 call fthdef(iunit, morekeys, status) call ftghsp(iunit, existkeys, morekeys, status) write(*,'(1x,A,I4,A,I4,A)') 'header contains ', existkeys, &' keywords with room for ', morekeys,' more' C define null value for int cols call fttnul(iunit, 4, 99, status) call fttnul(iunit, 5, 99, status) call fttnul(iunit, 6, 99, status) call ftpkyj(iunit, 'TNULL4', 99, 'value for undefined pixels', & status) call ftpkyj(iunit, 'TNULL5', 99, 'value for undefined pixels', & status) call ftpkyj(iunit, 'TNULL6', 99, 'value for undefined pixels', & status) naxis = 3 naxes(1) = 1 naxes(2) = 2 naxes(3) = 8 call ftptdm(iunit, 3, naxis, naxes, status) naxis = 0 naxes(1) = 0 naxes(2) = 0 naxes(3) = 0 call ftgtdm(iunit, 3, 3, naxis, naxes, status) call ftgkys(iunit, 'TDIM3', iskey, comment, status) write(*,'(1x,2A,4I4)') 'TDIM3 = ', iskey, naxis, naxes(1), & naxes(2), naxes(3) C force header to be scanned (not required) call ftrdef(iunit, status) C ############################ C # write data to columns # C ############################ C initialize arrays of values to write to table signval = -1 do ii = 1, 21 signval = signval * (-1) boutarray(ii) = char(ii) ioutarray(ii) = (ii) * signval joutarray(ii) = (ii) * signval koutarray(ii) = (ii) * signval eoutarray(ii) = (ii) * signval doutarray(ii) = (ii) * signval end do call ftpcls(iunit, 1, 1, 1, 3, onskey, status) C write string values call ftpclu(iunit, 1, 4, 1, 1, status) C write null value larray(1) = .false. larray(2) =.true. larray(3) = .false. larray(4) = .false. larray(5) =.true. larray(6) =.true. larray(7) = .false. larray(8) = .false. larray(9) = .false. larray(10) =.true. larray(11) =.true. larray(12) = .true. larray(13) = .false. larray(14) = .false. larray(15) =.false. larray(16) =.false. larray(17) = .true. larray(18) = .true. larray(19) = .true. larray(20) = .true. larray(21) =.false. larray(22) =.false. larray(23) =.false. larray(24) =.false. larray(25) =.false. larray(26) = .true. larray(27) = .true. larray(28) = .true. larray(29) = .true. larray(30) = .true. larray(31) =.false. larray(32) =.false. larray(33) =.false. larray(34) =.false. larray(35) =.false. larray(36) =.false. C write bits call ftpclx(iunit, 3, 1, 1, 36, larray, status) C loop over cols 4 - 8 do ii = 4, 8 call ftpclb(iunit, ii, 1, 1, 2, boutarray, status) if (status .eq. 412) status = 0 call ftpcli(iunit, ii, 3, 1, 2, ioutarray(3), status) if (status .eq. 412) status = 0 call ftpclj(iunit, ii, 5, 1, 2, koutarray(5), status) if (status .eq. 412) status = 0 call ftpcle(iunit, ii, 7, 1, 2, eoutarray(7), status) if (status .eq. 412)status = 0 call ftpcld(iunit, ii, 9, 1, 2, doutarray(9), status) if (status .eq. 412)status = 0 C write null value call ftpclu(iunit, ii, 11, 1, 1, status) end do call ftpclc(iunit, 9, 1, 1, 10, eoutarray, status) call ftpclm(iunit, 10, 1, 1, 10, doutarray, status) C loop over cols 4 - 8 do ii = 4, 8 bnul = char(13) call ftpcnb(iunit, ii, 12, 1, 2, boutarray(12),bnul,status) if (status .eq. 412) status = 0 inul=15 call ftpcni(iunit, ii, 14, 1, 2, ioutarray(14),inul,status) if (status .eq. 412) status = 0 call ftpcnj(iunit, ii, 16, 1, 2, koutarray(16), 17, status) if (status .eq. 412) status = 0 call ftpcne(iunit, ii, 18, 1, 2, eoutarray(18), 19.,status) if (status .eq. 412) status = 0 dnul = 21. call ftpcnd(iunit, ii, 20, 1, 2, doutarray(20),dnul,status) if (status .eq. 412) status = 0 end do C write logicals call ftpcll(iunit, 2, 1, 1, 21, larray, status) C write null value call ftpclu(iunit, 2, 11, 1, 1, status) write(*,'(1x,A,I4)') 'ftpcl_ status = ', status if (status .gt. 0)go to 999 C ######################################### C # get information about the columns # C ######################################### write(*,'(1x,A)')' ' write(*,'(1x,A)') & 'Find the column numbers a returned status value'// & ' of 237 is' write(*,'(1x,A)') & 'expected and indicates that more than one column'// & ' name matches' write(*,'(1x,A)')'the input column name template.'// & ' Status = 219 indicates that' write(*,'(1x,A)') 'there was no matching column name.' call ftgcno(iunit, 0, 'Xvalue', colnum, status) write(*,'(1x,A,I4,A,I4)') 'Column Xvalue is number', colnum, &' status =',status 219 continue if (status .ne. 219)then call ftgcnn(iunit, 1, '*ue', colname, colnum, status) write(*,'(1x,3A,I4,A,I4)') 'Column ',colname(1:6),' is number', & colnum,' status = ', status go to 219 end if status = 0 write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Information about each column: ' do ii = 1, tfields call ftgtcl(iunit, ii, typecode, repeat, width, status) call ftgbcl(iunit,ii,ttype,tunit,cval,repeat,scale, & zero, jnulval, tdisp, status) write(*,'(1x,A,3I4,5A,2F8.2,I12,A)') & tform(ii)(1:3), typecode, repeat, width,' ', & ttype(1)(1:6),' ',tunit(1)(1:6), cval, scale, zero, jnulval, & tdisp(1:8) end do write(*,'(1x,A)') ' ' C ############################################### C # insert ASCII table before the binary table # C ############################################### call ftmrhd(iunit, -1, hdutype, status) if (status .gt. 0)goto 999 tform(1) = 'A15' tform(2) = 'I10' tform(3) = 'F14.6' tform(4) = 'E12.5' tform(5) = 'D21.14' ttype(1) = 'Name' ttype(2) = 'Ivalue' ttype(3) = 'Fvalue' ttype(4) = 'Evalue' ttype(5) = 'Dvalue' tunit(1) = ' ' tunit(2) = 'm**2' tunit(3) = 'cm' tunit(4) = 'erg/s' tunit(5) = 'km/s' rowlen = 76 nrows = 11 tfields = 5 call ftitab(iunit, rowlen, nrows, tfields, ttype, tbcol, & tform, tunit, tblname, status) write(*,'(1x,A,I4)') 'ftitab status = ', status call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum C define null value for int cols call ftsnul(iunit, 1, 'null1', status) call ftsnul(iunit, 2, 'null2', status) call ftsnul(iunit, 3, 'null3', status) call ftsnul(iunit, 4, 'null4', status) call ftsnul(iunit, 5, 'null5', status) call ftpkys(iunit, 'TNULL1', 'null1', & 'value for undefined pixels', status) call ftpkys(iunit, 'TNULL2', 'null2', & 'value for undefined pixels', status) call ftpkys(iunit, 'TNULL3', 'null3', & 'value for undefined pixels', status) call ftpkys(iunit, 'TNULL4', 'null4', & 'value for undefined pixels', status) call ftpkys(iunit, 'TNULL5', 'null5', & 'value for undefined pixels', status) if (status .gt. 0) goto 999 C ############################ C # write data to columns # C ############################ C initialize arrays of values to write to table do ii = 1,21 boutarray(ii) = char(ii) ioutarray(ii) = ii joutarray(ii) = ii eoutarray(ii) = ii doutarray(ii) = ii end do C write string values call ftpcls(iunit, 1, 1, 1, 3, onskey, status) C write null value call ftpclu(iunit, 1, 4, 1, 1, status) do ii = 2,5 C loop over cols 2 - 5 call ftpclb(iunit, ii, 1, 1, 2, boutarray, status) C char array if (status .eq. 412) status = 0 call ftpcli(iunit, ii, 3, 1, 2, ioutarray(3), status) C short array if (status .eq. 412) status = 0 call ftpclj(iunit, ii, 5, 1, 2, joutarray(5), status) C long array if (status .eq. 412)status = 0 call ftpcle(iunit, ii, 7, 1, 2, eoutarray(7), status) C float array if (status .eq. 412) status = 0 call ftpcld(iunit, ii, 9, 1, 2, doutarray(9), status) C double array if (status .eq. 412) status = 0 call ftpclu(iunit, ii, 11, 1, 1, status) C write null value end do write(*,'(1x,A,I4)') 'ftpcl_ status = ', status write(*,'(1x,A)')' ' C ################################ C # read data from ASCII table # C ################################ call ftghtb(iunit, 99, rowlen, nrows, tfields, ttype, tbcol, & tform, tunit, tblname, status) write(*,'(1x,A,3I3,2A)') & 'ASCII table: rowlen, nrows, tfields, extname:', & rowlen, nrows, tfields,' ',tblname do ii = 1,tfields write(*,'(1x,A,I4,3A)') & ttype(ii)(1:7), tbcol(ii),' ',tform(ii)(1:7), tunit(ii)(1:7) end do nrows = 11 call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey, & anynull, status) bnul = char(99) call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, & anynull, status) inul = 99 call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, & anynull, status) call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray, & anynull, status) call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray, & anynull, status) dnul = 99. call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray, & anynull, status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values read from ASCII table: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1011) inskey(ii), jj, & iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii) 1011 format(1x,a15,3i3,1x,2f3.0) end do call ftgtbs(iunit, 1, 20, 78, uchars, status) write(*,'(1x,A)')' ' write(*,'(1x,A)') uchars call ftptbs(iunit, 1, 20, 78, uchars, status) C ######################################### C # get information about the columns # C ######################################### call ftgcno(iunit, 0, 'name', colnum, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4,A,I4)') & 'Column name is number',colnum,' status = ', status 2190 continue if (status .ne. 219)then if (status .gt. 0 .and. status .ne. 237)go to 999 call ftgcnn(iunit, 1, '*ue', colname, colnum, status) write(*,'(1x,3A,I4,A,I4)') & 'Column ',colname(1:6),' is number',colnum,' status = ',status go to 2190 end if status = 0 do ii = 1, tfields call ftgtcl(iunit, ii, typecode, repeat, width, status) call ftgacl(iunit, ii, ttype, tbcol,tunit,tform, & scale,zero, nulstr, tdisp, status) write(*,'(1x,A,3I4,2A,I4,2A,2F10.2,3A)') & tform(ii)(1:7), typecode, repeat, width,' ', & ttype(1)(1:6), tbcol(1), ' ',tunit(1)(1:5), & scale, zero, ' ', nulstr(1:6), tdisp(1:2) end do write(*,'(1x,A)') ' ' C ############################################### C # test the insert/delete row/column routines # C ############################################### call ftirow(iunit, 2, 3, status) if (status .gt. 0) goto 999 nrows = 14 call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', & inskey, anynull, status) call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, & anynull, status) call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, & anynull, status) call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray, & anynull, status) call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray, & anynull, status) call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray, & anynull, status) write(*,'(1x,A)')' ' write(*,'(1x,A)')'Data values after inserting 3 rows after row 2:' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1011) inskey(ii), jj, & iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii) end do call ftdrow(iunit, 10, 2, status) nrows = 12 call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey, & anynull, status) call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull, & status) call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull, & status) call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray, anynull, & status) call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray, anynull, & status) call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray, anynull, & status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values after deleting 2 rows at row 10: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1011) inskey(ii), jj, & iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii) end do call ftdcol(iunit, 3, status) call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey, & anynull, status) call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull, & status) call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull, & status) call ftgcve(iunit, 3, 1, 1, nrows, 99., einarray, anynull, & status) call ftgcvd(iunit, 4, 1, 1, nrows, dnul, dinarray, anynull, & status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values after deleting column 3: ' do ii = 1,nrows jj = ichar(binarray(ii)) write(*,1012) inskey(ii), jj, & iinarray(ii), einarray(ii), dinarray(ii) 1012 format(1x,a15,2i3,1x,2f3.0) end do call fticol(iunit, 5, 'INSERT_COL', 'F14.6', status) call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey, & anynull, status) call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull, & status) call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull, & status) call ftgcve(iunit, 3, 1, 1, nrows, 99., einarray, anynull, & status) call ftgcvd(iunit, 4, 1, 1, nrows, dnul, dinarray, anynull, & status) call ftgcvj(iunit, 5, 1, 1, nrows, 99, jinarray, anynull, & status) write(*,'(1x,A)')' ' write(*,'(1x,A)') ' Data values after inserting column 5: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1013) inskey(ii), jj, & iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii) 1013 format(1x,a15,2i3,1x,2f3.0,i2) end do C ################################ C # read data from binary table # C ################################ call ftmrhd(iunit, 1, hdutype, status) if (status .gt. 0)go to 999 call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum call ftghsp(iunit, existkeys, morekeys, status) write(*,'(1x,A)')' ' write(*,'(1x,A)')'Moved to binary table' write(*,'(1x,A,I4,A,I4,A)') 'header contains ',existkeys, & ' keywords with room for ',morekeys,' more ' call ftghbn(iunit, 99, nrows, tfields, ttype, & tform, tunit, binname, pcount, status) write(*,'(1x,A)')' ' write(*,'(1x,A,2I4,A,I4)') & 'Binary table: nrows, tfields, extname, pcount:', & nrows, tfields, binname, pcount do ii = 1,tfields write(*,'(1x,3A)') ttype(ii), tform(ii), tunit(ii) end do do ii = 1, 40 larray(ii) = .false. end do write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values read from binary table: ' write(*,'(1x,A)') ' Bit column (X) data values: ' call ftgcx(iunit, 3, 1, 1, 36, larray, status) write(*,1014) (larray(ii), ii = 1,40) 1014 format(1x,8l1,' ',8l1,' ',8l1,' ',8l1,' ',8l1) nrows = 21 do ii = 1, nrows larray(ii) = .false. xinarray(ii) = ' ' binarray(ii) = ' ' iinarray(ii) = 0 kinarray(ii) = 0 einarray(ii) = 0. dinarray(ii) = 0. cinarray(ii * 2 -1) = 0. minarray(ii * 2 -1) = 0. cinarray(ii * 2 ) = 0. minarray(ii * 2 ) = 0. end do write(*,'(1x,A)') ' ' call ftgcvs(iunit, 1, 4, 1, 1, ' ', inskey, anynull,status) if (ichar(inskey(1)(1:1)) .eq. 0)inskey(1)=' ' write(*,'(1x,2A)') 'null string column value (should be blank):', & inskey(1) call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED', inskey, & anynull, status) call ftgcl( iunit, 2, 1, 1, nrows, larray, status) bnul = char(98) call ftgcvb(iunit, 3, 1, 1,nrows,bnul, xinarray,anynull,status) call ftgcvb(iunit, 4, 1, 1,nrows,bnul, binarray,anynull,status) inul = 98 call ftgcvi(iunit, 5, 1, 1,nrows,inul, iinarray,anynull,status) call ftgcvj(iunit, 6, 1, 1, nrows, 98, kinarray,anynull,status) call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status) dnul = 98. call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status) call ftgcvc(iunit, 9, 1, 1, nrows, 98.,cinarray,anynull,status) call ftgcvm(iunit,10, 1, 1, nrows,dnul,minarray,anynull,status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Read columns with ftgcv_: ' do ii = 1,nrows jj = ichar(xinarray(ii)) jjj = ichar(binarray(ii)) write(*,1201)inskey(ii),larray(ii),jj,jjj,iinarray(ii), & kinarray(ii), einarray(ii), dinarray(ii), cinarray(ii * 2 -1), &cinarray(ii * 2 ), minarray(ii * 2 -1), minarray(ii * 2 ) end do 1201 format(1x,a14,l4,4i4,6f5.0) do ii = 1, nrows larray(ii) = .false. xinarray(ii) = ' ' binarray(ii) = ' ' iinarray(ii) = 0 kinarray(ii) = 0 einarray(ii) = 0. dinarray(ii) = 0. cinarray(ii * 2 -1) = 0. minarray(ii * 2 -1) = 0. cinarray(ii * 2 ) = 0. minarray(ii * 2 ) = 0. end do call ftgcfs(iunit, 1, 1, 1, nrows, inskey, larray2, anynull, & status) C put blanks in strings if they are undefined. (contain nulls) do ii = 1, nrows if (larray2(ii))inskey(ii) = ' ' end do call ftgcfl(iunit, 2, 1, 1, nrows, larray, larray2, anynull, & status) call ftgcfb(iunit, 3, 1, 1, nrows, xinarray, larray2, anynull, & status) call ftgcfb(iunit, 4, 1, 1, nrows, binarray, larray2, anynull, & status) call ftgcfi(iunit, 5, 1, 1, nrows, iinarray, larray2, anynull, & status) call ftgcfj(iunit, 6, 1, 1, nrows, kinarray, larray2, anynull, & status) call ftgcfe(iunit, 7, 1, 1, nrows, einarray, larray2, anynull, & status) call ftgcfd(iunit, 8, 1, 1, nrows, dinarray, larray2, anynull, & status) call ftgcfc(iunit, 9, 1, 1, nrows, cinarray, larray2, anynull, & status) call ftgcfm(iunit, 10,1, 1, nrows, minarray, larray2, anynull, & status) write(*,'(1x,A)')' ' write(*,'(1x,A)') ' Read columns with ftgcf_: ' do ii = 1, 10 jj = ichar(xinarray(ii)) jjj = ichar(binarray(ii)) write(*,1201) & inskey(ii),larray(ii),jj,jjj,iinarray(ii), & kinarray(ii), einarray(ii), dinarray(ii), cinarray(ii * 2 -1), & cinarray(ii * 2 ), minarray(ii * 2 -1), minarray(ii * 2) end do do ii = 11, 21 C don't try to print the NaN values jj = ichar(xinarray(ii)) jjj = ichar(binarray(ii)) write(*,1201) inskey(ii), larray(ii), jj, & jjj, iinarray(ii) end do call ftprec(iunit,'key_prec= '// &'''This keyword was written by f_prec'' / comment here', & status) C ############################################### C # test the insert/delete row/column routines # C ############################################### call ftirow(iunit, 2, 3, status) if (status .gt. 0) go to 999 nrows = 14 call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED', inskey, & anynull, status) call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status) call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status) call ftgcvj(iunit, 6, 1, 1, nrows, 98, jinarray,anynull,status) call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status) call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status) write(*,'(1x,A)')' ' write(*,'(1x,A)')'Data values after inserting 3 rows after row 2:' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1202) inskey(ii), jj, & iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii) end do 1202 format(1x,a14,3i4,2f5.0) call ftdrow(iunit, 10, 2, status) if (status .gt. 0)goto 999 nrows = 12 call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED', inskey, & anynull, status) call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status) call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status) call ftgcvj(iunit, 6, 1, 1, nrows, 98,jinarray,anynull,status) call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status) call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values after deleting 2 rows at row 10: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1202) inskey(ii), jj, & iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii) end do call ftdcol(iunit, 6, status) call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED', inskey, & anynull, status) call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status) call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status) call ftgcve(iunit, 6, 1, 1, nrows, 98.,einarray,anynull,status) call ftgcvd(iunit, 7, 1, 1, nrows,dnul,dinarray,anynull,status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values after deleting column 6: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1203) inskey(ii), jj, & iinarray(ii), einarray(ii), dinarray(ii) 1203 format(1x,a14,2i4,2f5.0) end do call fticol(iunit, 8, 'INSERT_COL', '1E', status) call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED', inskey, & anynull, status) call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status) call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status) call ftgcve(iunit, 6, 1, 1, nrows, 98.,einarray,anynull,status) call ftgcvd(iunit, 7, 1, 1, nrows,dnul,dinarray,anynull,status) call ftgcvj(iunit, 8, 1, 1, nrows, 98,jinarray,anynull,status) write(*,'(1x,A)')' ' write(*,'(1x,A)') 'Data values after inserting column 8: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1204) inskey(ii), jj, & iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii) 1204 format(1x,a14,2i4,2f5.0,i3) end do call ftpclu(iunit, 8, 1, 1, 10, status) call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED', inskey, & anynull, status) call ftgcvb(iunit, 4,1,1,nrows,bnul,binarray,anynull,status) call ftgcvi(iunit, 5,1,1,nrows,inul,iinarray,anynull,status) call ftgcve(iunit, 6,1,1,nrows,98., einarray,anynull,status) call ftgcvd(iunit, 7,1,1,nrows,dnul, dinarray,anynull,status) call ftgcvj(iunit, 8,1,1,nrows,98, jinarray,anynull, status) write(*,'(1x,A)')' ' write(*,'(1x,A)') & 'Values after setting 1st 10 elements in column 8 = null: ' do ii = 1, nrows jj = ichar(binarray(ii)) write(*,1204) inskey(ii), jj, & iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii) end do C #################################################### C # insert binary table following the primary array # C #################################################### call ftmahd(iunit, 1, hdutype, status) tform(1) = '15A' tform(2) = '1L' tform(3) = '16X' tform(4) = '1B' tform(5) = '1I' tform(6) = '1J' tform(7) = '1E' tform(8) = '1D' tform(9) = '1C' tform(10)= '1M' ttype(1) = 'Avalue' ttype(2) = 'Lvalue' ttype(3) = 'Xvalue' ttype(4) = 'Bvalue' ttype(5) = 'Ivalue' ttype(6) = 'Jvalue' ttype(7) = 'Evalue' ttype(8) = 'Dvalue' ttype(9) = 'Cvalue' ttype(10)= 'Mvalue' tunit(1)= ' ' tunit(2)= 'm**2' tunit(3)= 'cm' tunit(4)= 'erg/s' tunit(5)= 'km/s' tunit(6)= ' ' tunit(7)= ' ' tunit(8)= ' ' tunit(9)= ' ' tunit(10)= ' ' nrows = 20 tfields = 10 pcount = 0 call ftibin(iunit, nrows, tfields, ttype, tform, tunit, & binname, pcount, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)') 'ftibin status = ', status call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum call ftpkyj(iunit, 'TNULL4', 77, & 'value for undefined pixels', status) call ftpkyj(iunit, 'TNULL5', 77, & 'value for undefined pixels', status) call ftpkyj(iunit, 'TNULL6', 77, & 'value for undefined pixels', status) call ftpkyj(iunit, 'TSCAL4', 1000, 'scaling factor', status) call ftpkyj(iunit, 'TSCAL5', 1, 'scaling factor', status) call ftpkyj(iunit, 'TSCAL6', 100, 'scaling factor', status) call ftpkyj(iunit, 'TZERO4', 0, 'scaling offset', status) call ftpkyj(iunit, 'TZERO5', 32768, 'scaling offset', status) call ftpkyj(iunit, 'TZERO6', 100, 'scaling offset', status) call fttnul(iunit, 4, 77, status) C define null value for int cols call fttnul(iunit, 5, 77, status) call fttnul(iunit, 6, 77, status) C set scaling scale=1000. zero = 0. call fttscl(iunit, 4, scale, zero, status) scale=1. zero = 32768. call fttscl(iunit, 5, scale, zero, status) scale=100. zero = 100. call fttscl(iunit, 6, scale, zero, status) C for some reason, it is still necessary to call ftrdef at this point call ftrdef(iunit,status) C ############################ C # write data to columns # C ############################ C initialize arrays of values to write to table joutarray(1) = 0 joutarray(2) = 1000 joutarray(3) = 10000 joutarray(4) = 32768 joutarray(5) = 65535 do ii = 4,6 call ftpclj(iunit, ii, 1, 1, 5, joutarray, status) if (status .eq. 412)then write(*,'(1x,A,I4)') 'Overflow writing to column ', ii status = 0 end if call ftpclu(iunit, ii, 6, 1, 1, status) C write null value end do do jj = 4,6 call ftgcvj(iunit, jj, 1,1,6, -999,jinarray,anynull,status) write(*,'(1x,6I6)') (jinarray(ii), ii=1,6) end do write(*,'(1x,A)') ' ' C turn off scaling, and read the unscaled values scale = 1. zero = 0. call fttscl(iunit, 4, scale, zero, status) call fttscl(iunit, 5, scale, zero, status) call fttscl(iunit, 6, scale, zero, status) do jj = 4,6 call ftgcvj(iunit, jj,1,1,6,-999,jinarray,anynull,status) write(*,'(1x,6I6)') (jinarray(ii), ii = 1,6) end do if (status .gt. 0)go to 999 C ###################################################### C # insert image extension following the binary table # C ###################################################### bitpix = -32 naxis = 2 naxes(1) = 15 naxes(2) = 25 call ftiimg(iunit, bitpix, naxis, naxes, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)') & ' Create image extension: ftiimg status = ', status call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum do jj = 0,29 do ii = 0,18 imgarray(ii+1,jj+1) = (jj * 10) + ii end do end do call ftp2di(iunit, 1, 19, naxes(1),naxes(2),imgarray,status) write(*,'(1x,A)') ' ' write(*,'(1x,A,I4)')'Wrote whole 2D array: ftp2di status =', & status do jj =1, 30 do ii = 1, 19 imgarray(ii,jj) = 0 end do end do call ftg2di(iunit,1,0,19,naxes(1),naxes(2),imgarray,anynull, & status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)')'Read whole 2D array: ftg2di status =',status do jj =1, 30 write (*,1301)(imgarray(ii,jj),ii=1,19) 1301 format(1x,19I4) end do write(*,'(1x,A)') ' ' do jj =1, 30 do ii = 1, 19 imgarray(ii,jj) = 0 end do end do do jj =0, 19 do ii = 0, 9 imgarray2(ii+1,jj+1) = (jj * (-10)) - ii end do end do fpixels(1) = 5 fpixels(2) = 5 lpixels(1) = 14 lpixels(2) = 14 call ftpssi(iunit, 1, naxis, naxes, fpixels, lpixels, & imgarray2, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)')'Wrote subset 2D array: ftpssi status =', & status call ftg2di(iunit,1,0,19,naxes(1), naxes(2),imgarray,anynull, & status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)')'Read whole 2D array: ftg2di status =',status do jj =1, 30 write (*,1301)(imgarray(ii,jj),ii=1,19) end do write(*,'(1x,A)') ' ' fpixels(1) = 2 fpixels(2) = 5 lpixels(1) = 10 lpixels(2) = 8 inc(1) = 2 inc(2) = 3 do jj = 1,30 do ii = 1, 19 imgarray(ii,jj) = 0 end do end do call ftgsvi(iunit, 1, naxis, naxes, fpixels, lpixels, inc, 0, & imgarray, anynull, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)') & 'Read subset of 2D array: ftgsvi status = ',status write(*,'(1x,10I5)')(imgarray(ii,1),ii = 1,10) C ########################################################### C # insert another image extension # C # copy the image extension to primary array of tmp file. # C # then delete the tmp file, and the image extension # C ########################################################### bitpix = 16 naxis = 2 naxes(1) = 15 naxes(2) = 25 call ftiimg(iunit, bitpix, naxis, naxes, status) write(*,'(1x,A)') ' ' write(*,'(1x,A,I4)')'Create image extension: ftiimg status =', & status call ftrdef(iunit, status) call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum filename = 't1q2s3v4.tmp' call ftinit(tmpunit, filename, 1, status) write(*,'(1x,A,I4)')'Create temporary file: ftinit status = ', & status call ftcopy(iunit, tmpunit, 0, status) write(*,'(1x,A)') & 'Copy image extension to primary array of tmp file.' write(*,'(1x,A,I4)')'ftcopy status = ',status call ftgrec(tmpunit, 1, card, status) write(*,'(1x,A)') card call ftgrec(tmpunit, 2, card, status) write(*,'(1x,A)') card call ftgrec(tmpunit, 3, card, status) write(*,'(1x,A)') card call ftgrec(tmpunit, 4, card, status) write(*,'(1x,A)') card call ftgrec(tmpunit, 5, card, status) write(*,'(1x,A)') card call ftgrec(tmpunit, 6, card, status) write(*,'(1x,A)') card call ftdelt(tmpunit, status) write(*,'(1x,A,I4)')'Delete the tmp file: ftdelt status =',status call ftdhdu(iunit, hdutype, status) write(*,'(1x,A,2I4)') & 'Delete the image extension hdutype, status =', & hdutype, status call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum C ########################################################### C # append bintable extension with variable length columns # C ########################################################### call ftcrhd(iunit, status) write(*,'(1x,A,I4)') 'ftcrhd status = ', status tform(1)= '1PA' tform(2)= '1PL' tform(3)= '1PB' C Fortran FITSIO doesn't support 1PX tform(4)= '1PB' tform(5)= '1PI' tform(6)= '1PJ' tform(7)= '1PE' tform(8)= '1PD' tform(9)= '1PC' tform(10)= '1PM' ttype(1)= 'Avalue' ttype(2)= 'Lvalue' ttype(3)= 'Xvalue' ttype(4)= 'Bvalue' ttype(5)= 'Ivalue' ttype(6)= 'Jvalue' ttype(7)= 'Evalue' ttype(8)= 'Dvalue' ttype(9)= 'Cvalue' ttype(10)= 'Mvalue' tunit(1)= ' ' tunit(2)= 'm**2' tunit(3)= 'cm' tunit(4)= 'erg/s' tunit(5)= 'km/s' tunit(6)= ' ' tunit(7)= ' ' tunit(8)= ' ' tunit(9)= ' ' tunit(10)= ' ' nrows = 20 tfields = 10 pcount = 0 call ftphbn(iunit, nrows, tfields, ttype, tform, & tunit, binname, pcount, status) write(*,'(1x,A,I4)')'Variable length arrays: ftphbn status =', & status call ftpkyj(iunit, 'TNULL4', 88, 'value for undefined pixels', & status) call ftpkyj(iunit, 'TNULL5', 88, 'value for undefined pixels', & status) call ftpkyj(iunit, 'TNULL6', 88, 'value for undefined pixels', & status) C ############################ C # write data to columns # C ############################ C initialize arrays of values to write to table iskey='abcdefghijklmnopqrst' do ii = 1, 20 boutarray(ii) = char(ii) ioutarray(ii) = ii joutarray(ii) = ii eoutarray(ii) = ii doutarray(ii) = ii end do larray(1) = .false. larray(2) = .true. larray(3) = .false. larray(4) = .false. larray(5) = .true. larray(6) = .true. larray(7) = .false. larray(8) = .false. larray(9) = .false. larray(10) = .true. larray(11) = .true. larray(12) = .true. larray(13) = .false. larray(14) = .false. larray(15) = .false. larray(16) = .false. larray(17) = .true. larray(18) = .true. larray(19) = .true. larray(20) = .true. C inskey(1) = iskey(1:1) inskey(1) = ' ' call ftpcls(iunit, 1, 1, 1, 1, inskey, status) C write string values call ftpcll(iunit, 2, 1, 1, 1, larray, status) C write logicals call ftpclx(iunit, 3, 1, 1, 1, larray, status) C write bits call ftpclb(iunit, 4, 1, 1, 1, boutarray, status) call ftpcli(iunit, 5, 1, 1, 1, ioutarray, status) call ftpclj(iunit, 6, 1, 1, 1, joutarray, status) call ftpcle(iunit, 7, 1, 1, 1, eoutarray, status) call ftpcld(iunit, 8, 1, 1, 1, doutarray, status) do ii = 2, 20 C loop over rows 1 - 20 inskey(1) = iskey(1:ii) call ftpcls(iunit, 1, ii, 1, ii, inskey, status) C write string values call ftpcll(iunit, 2, ii, 1, ii, larray, status) C write logicals call ftpclu(iunit, 2, ii, ii-1, 1, status) call ftpclx(iunit, 3, ii, 1, ii, larray, status) C write bits call ftpclb(iunit, 4, ii, 1, ii, boutarray, status) call ftpclu(iunit, 4, ii, ii-1, 1, status) call ftpcli(iunit, 5, ii, 1, ii, ioutarray, status) call ftpclu(iunit, 5, ii, ii-1, 1, status) call ftpclj(iunit, 6, ii, 1, ii, joutarray, status) call ftpclu(iunit, 6, ii, ii-1, 1, status) call ftpcle(iunit, 7, ii, 1, ii, eoutarray, status) call ftpclu(iunit, 7, ii, ii-1, 1, status) call ftpcld(iunit, 8, ii, 1, ii, doutarray, status) call ftpclu(iunit, 8, ii, ii-1, 1, status) end do C it is no longer necessary to update the PCOUNT keyword; C FITSIO now does this automatically when the HDU is closed. C call ftmkyj(iunit,'PCOUNT',4446, '&',status) write(*,'(1x,A,I4)') 'ftpcl_ status = ', status C ################################# C # close then reopen this HDU # C ################################# call ftmrhd(iunit, -1, hdutype, status) call ftmrhd(iunit, 1, hdutype, status) C ############################# C # read data from columns # C ############################# call ftgkyj(iunit, 'PCOUNT', pcount, comm, status) write(*,'(1x,A,I4)') 'PCOUNT = ', pcount C initialize the variables to be read inskey(1) =' ' iskey = ' ' do jj = 1, ii larray(jj) = .false. boutarray(jj) = char(0) ioutarray(jj) = 0 joutarray(jj) = 0 eoutarray(jj) = 0 doutarray(jj) = 0 end do call ftghdn(iunit, hdunum) write(*,'(1x,A,I4)') 'HDU number = ', hdunum do ii = 1, 20 C loop over rows 1 - 20 do jj = 1, ii larray(jj) = .false. boutarray(jj) = char(0) ioutarray(jj) = 0 joutarray(jj) = 0 eoutarray(jj) = 0 doutarray(jj) = 0 end do call ftgcvs(iunit, 1, ii, 1,1,iskey,inskey,anynull,status) write(*,'(1x,2A,I4)') 'A ', inskey(1), status call ftgcl( iunit, 2, ii, 1, ii, larray, status) write(*,1400)'L',status,(larray(jj),jj=1,ii) 1400 format(1x,a1,i3,20l3) 1401 format(1x,a1,21i3) call ftgcx(iunit, 3, ii, 1, ii, larray, status) write(*,1400)'X',status,(larray(jj),jj=1,ii) bnul = char(99) call ftgcvb(iunit, 4, ii, 1,ii,bnul,boutarray,anynull,status) do jj = 1,ii jinarray(jj) = ichar(boutarray(jj)) end do write(*,1401)'B',(jinarray(jj),jj=1,ii),status inul = 99 call ftgcvi(iunit, 5, ii, 1,ii,inul,ioutarray,anynull,status) write(*,1401)'I',(ioutarray(jj),jj=1,ii),status call ftgcvj(iunit, 6, ii, 1, ii,99,joutarray,anynull,status) write(*,1401)'J',(joutarray(jj),jj=1,ii),status call ftgcve(iunit, 7, ii, 1,ii,99.,eoutarray,anynull,status) estatus=status write(*,1402)'E',(eoutarray(jj),jj=1,ii),estatus 1402 format(1x,a1,1x,21f3.0) dnul = 99. call ftgcvd(iunit, 8, ii,1,ii,dnul,doutarray,anynull,status) estatus=status write(*,1402)'D',(doutarray(jj),jj=1,ii),estatus call ftgdes(iunit, 8, ii, repeat, offset, status) write(*,'(1x,A,2I5)')'Column 8 repeat and offset =', & repeat,offset end do C ##################################### C # create another image extension # C ##################################### bitpix = 32 naxis = 2 naxes(1) = 10 naxes(2) = 2 npixels = 20 call ftiimg(iunit, bitpix, naxis, naxes, status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)')'Create image extension: ftiimg status =', & status C initialize arrays of values to write to primary array do ii = 1, npixels boutarray(ii) = char(ii * 2 -2) ioutarray(ii) = ii * 2 -2 joutarray(ii) = ii * 2 -2 koutarray(ii) = ii * 2 -2 eoutarray(ii) = ii * 2 -2 doutarray(ii) = ii * 2 -2 end do C write a few pixels with each datatype call ftpprb(iunit, 1, 1, 2, boutarray(1), status) call ftppri(iunit, 1, 3, 2, ioutarray(3), status) call ftpprj(iunit, 1, 5, 2, koutarray(5), status) call ftppri(iunit, 1, 7, 2, ioutarray(7), status) call ftpprj(iunit, 1, 9, 2, joutarray(9), status) call ftppre(iunit, 1, 11, 2, eoutarray(11), status) call ftpprd(iunit, 1, 13, 2, doutarray(13), status) write(*,'(1x,A,I4)') 'ftppr status = ', status C read back the pixels with each datatype bnul = char(0) inul = 0 knul = 0 jnul = 0 enul = 0. dnul = 0. call ftgpvb(iunit, 1, 1, 14, bnul, binarray, anynull, status) call ftgpvi(iunit, 1, 1, 14, inul, iinarray, anynull, status) call ftgpvj(iunit, 1, 1, 14, knul, kinarray, anynull, status) call ftgpvj(iunit, 1, 1, 14, jnul, jinarray, anynull, status) call ftgpve(iunit, 1, 1, 14, enul, einarray, anynull, status) call ftgpvd(iunit, 1, 1, 14, dnul, dinarray, anynull, status) write(*,'(1x,A)')' ' write(*,'(1x,A)') & 'Image values written with ftppr and read with ftgpv:' npixels = 14 do jj = 1,ii joutarray(jj) = ichar(binarray(jj)) end do write(*,1501)(joutarray(ii),ii=1,npixels),anynull,'(byte)' 1501 format(1x,14i3,l3,1x,a) write(*,1501)(iinarray(ii),ii=1,npixels),anynull,'(short)' write(*,1501)(kinarray(ii),ii=1,npixels),anynull,'(int)' write(*,1501)(jinarray(ii),ii=1,npixels),anynull,'(long)' write(*,1502)(einarray(ii),ii=1,npixels),anynull,'(float)' write(*,1502)(dinarray(ii),ii=1,npixels),anynull,'(double)' 1502 format(2x,14f3.0,l2,1x,a) C ########################################## C # test world coordinate system routines # C ########################################## xrval = 45.83D+00 yrval = 63.57D+00 xrpix = 256.D+00 yrpix = 257.D+00 xinc = -.00277777D+00 yinc = .00277777D+00 C write the WCS keywords C use example values from the latest WCS document call ftpkyd(iunit, 'CRVAL1', xrval, 10, 'comment', status) call ftpkyd(iunit, 'CRVAL2', yrval, 10, 'comment', status) call ftpkyd(iunit, 'CRPIX1', xrpix, 10, 'comment', status) call ftpkyd(iunit, 'CRPIX2', yrpix, 10, 'comment', status) call ftpkyd(iunit, 'CDELT1', xinc, 10, 'comment', status) call ftpkyd(iunit, 'CDELT2', yinc, 10, 'comment', status) C call ftpkyd(iunit, 'CROTA2', rot, 10, 'comment', status) call ftpkys(iunit, 'CTYPE1', xctype, 'comment', status) call ftpkys(iunit, 'CTYPE2', yctype, 'comment', status) write(*,'(1x,A)')' ' write(*,'(1x,A,I4)')'Wrote WCS keywords status =', status C reset value, to make sure they are reread correctly xrval = 0.D+00 yrval = 0.D+00 xrpix = 0.D+00 yrpix = 0.D+00 xinc = 0.D+00 yinc = 0.D+00 rot = 67.D+00 call ftgics(iunit, xrval, yrval, xrpix, & yrpix, xinc, yinc, rot, ctype, status) write(*,'(1x,A,I4)')'Read WCS keywords with ftgics status =', & status xpix = 0.5D+00 ypix = 0.5D+00 call ftwldp(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc, & rot,ctype, xpos, ypos,status) write(*,'(1x,A,2f8.3)')' CRVAL1, CRVAL2 =', xrval,yrval write(*,'(1x,A,2f8.3)')' CRPIX1, CRPIX2 =', xrpix,yrpix write(*,'(1x,A,2f12.8)')' CDELT1, CDELT2 =', xinc,yinc write(*,'(1x,A,f8.3,2A)')' Rotation =',rot,' CTYPE =',ctype write(*,'(1x,A,I4)')'Calculated sky coord. with ftwldp status =', & status write(*,6501)xpix,ypix,xpos,ypos 6501 format(' Pixels (',f10.6,f10.6,') --> (',f10.6,f10.6,') Sky') call ftxypx(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc, & rot,ctype, xpix, ypix,status) write(*,'(1x,A,I4)') & 'Calculated pixel coord. with ftxypx status =', status write(*,6502)xpos,ypos,xpix,ypix 6502 format(' Sky (',f10.6,f10.6,') --> (',f10.6,f10.6,') Pixels') C ###################################### C # append another ASCII table # C ###################################### tform(1)= 'A15' tform(2)= 'I11' tform(3)= 'F15.6' tform(4)= 'E13.5' tform(5)= 'D22.14' tbcol(1)= 1 tbcol(2)= 17 tbcol(3)= 29 tbcol(4)= 45 tbcol(5)= 59 rowlen = 80 ttype(1)= 'Name' ttype(2)= 'Ivalue' ttype(3)= 'Fvalue' ttype(4)= 'Evalue' ttype(5)= 'Dvalue' tunit(1)= ' ' tunit(2)= 'm**2' tunit(3)= 'cm' tunit(4)= 'erg/s' tunit(5)= 'km/s' nrows = 11 tfields = 5 tblname = 'new_table' call ftitab(iunit, rowlen, nrows, tfields, ttype, tbcol, & tform, tunit, tblname, status) write(*,'(1x,A)') ' ' write(*,'(1x,A,I4)') 'ftitab status = ', status call ftpcls(iunit, 1, 1, 1, 3, onskey, status) C write string values C initialize arrays of values to write to primary array do ii = 1,npixels boutarray(ii) = char(ii * 3 -3) ioutarray(ii) = ii * 3 -3 joutarray(ii) = ii * 3 -3 koutarray(ii) = ii * 3 -3 eoutarray(ii) = ii * 3 -3 doutarray(ii) = ii * 3 -3 end do do ii = 2,5 C loop over cols 2 - 5 call ftpclb(iunit, ii, 1, 1, 2, boutarray, status) call ftpcli(iunit, ii, 3, 1, 2,ioutarray(3),status) call ftpclj(iunit, ii, 5, 1, 2,joutarray(5),status) call ftpcle(iunit, ii, 7, 1, 2,eoutarray(7),status) call ftpcld(iunit, ii, 9, 1, 2,doutarray(9),status) end do write(*,'(1x,A,I4)') 'ftpcl status = ', status C read back the pixels with each datatype call ftgcvb(iunit, 2, 1, 1, 10, bnul, binarray,anynull, & status) call ftgcvi(iunit, 2, 1, 1, 10, inul, iinarray,anynull, & status) call ftgcvj(iunit, 3, 1, 1, 10, knul, kinarray,anynull, & status) call ftgcvj(iunit, 3, 1, 1, 10, jnul, jinarray,anynull, & status) call ftgcve(iunit, 4, 1, 1, 10, enul, einarray,anynull, & status) call ftgcvd(iunit, 5, 1, 1, 10, dnul, dinarray,anynull, & status) write(*,'(1x,A)') &'Column values written with ftpcl and read with ftgcl: ' npixels = 10 do ii = 1,npixels joutarray(ii) = ichar(binarray(ii)) end do write(*,1601)(joutarray(ii),ii = 1, npixels),anynull,'(byte) ' write(*,1601)(iinarray(ii),ii = 1, npixels),anynull,'(short) ' write(*,1601)(kinarray(ii),ii = 1, npixels),anynull,'(int) ' write(*,1601)(jinarray(ii),ii = 1, npixels),anynull,'(long) ' write(*,1602)(einarray(ii),ii = 1, npixels),anynull,'(float) ' write(*,1602)(dinarray(ii),ii = 1, npixels),anynull,'(double) ' 1601 format(1x,10i3,l3,1x,a) 1602 format(2x,10f3.0,l2,1x,a) C ########################################################### C # perform stress test by cycling thru all the extensions # C ########################################################### write(*,'(1x,A)')' ' write(*,'(1x,A)')'Repeatedly move to the 1st 4 HDUs of the file: ' do ii = 1,10 call ftmahd(iunit, 1, hdutype, status) call ftghdn(iunit, hdunum) call ftmrhd(iunit, 1, hdutype, status) call ftghdn(iunit, hdunum) call ftmrhd(iunit, 1, hdutype, status) call ftghdn(iunit, hdunum) call ftmrhd(iunit, 1, hdutype, status) call ftghdn(iunit, hdunum) call ftmrhd(iunit, -1, hdutype, status) call ftghdn(iunit, hdunum) if (status .gt. 0) go to 999 end do write(*,'(1x,A)') ' ' checksum = 1234567890.D+00 call ftesum(checksum, .false., asciisum) write(*,'(1x,A,F13.1,2A)')'Encode checksum: ',checksum,' -> ', & asciisum checksum = 0 call ftdsum(asciisum, 0, checksum) write(*,'(1x,3A,F13.1)') 'Decode checksum: ',asciisum,' -> ', & checksum call ftpcks(iunit, status) C don't print the CHECKSUM value because it is different every day C because the current date is in the comment field. call ftgcrd(iunit, 'CHECKSUM', card, status) C write(*,'(1x,A)') card call ftgcrd(iunit, 'DATASUM', card, status) write(*,'(1x,A)') card(1:22) call ftgcks(iunit, datsum, checksum, status) write(*,'(1x,A,F13.1,I4)') 'ftgcks data checksum, status = ', & datsum, status call ftvcks(iunit, datastatus, hdustatus, status) write(*,'(1x,A,3I4)')'ftvcks datastatus, hdustatus, status = ', & datastatus, hdustatus, status call ftprec(iunit, & 'new_key = ''written by fxprec'' / to change checksum',status) call ftucks(iunit, status) write(*,'(1x,A,I4)') 'ftupck status = ', status call ftgcrd(iunit, 'DATASUM', card, status) write(*,'(1x,A)') card(1:22) call ftvcks(iunit, datastatus, hdustatus, status) write(*,'(1x,A,3I4)') 'ftvcks datastatus, hdustatus, status = ', & datastatus, hdustatus, status C delete the checksum keywords, so that the FITS file is always C the same, regardless of the date of when testprog is run. call ftdkey(iunit, 'CHECKSUM', status) call ftdkey(iunit, 'DATASUM', status) C ############################ C # close file and quit # C ############################ 999 continue C jump here on error call ftclos(iunit, status) write(*,'(1x,A,I4)') 'ftclos status = ', status write(*,'(1x,A)')' ' write(*,'(1x,A)') & 'Normally, there should be 8 error messages on the' write(*,'(1x,A)') 'stack all regarding ''numerical overflows'':' call ftgmsg(errmsg) nmsg = 0 998 continue if (errmsg .ne. ' ')then write(*,'(1x,A)') errmsg nmsg = nmsg + 1 call ftgmsg(errmsg) go to 998 end if if (nmsg .ne. 8)write(*,'(1x,A)') & ' WARNING: Did not find the expected 8 error messages!' call ftgerr(status, errmsg) write(*,'(1x,A)')' ' write(*,'(1x,A,I4,2A)') 'Status =', status,': ', errmsg(1:50) end cfitsio-4.3.1/getcolb.c0000644000225700000360000023100214075614240014231 0ustar cagordonlhea/* This file, getcolb.c, contains routines that read data elements from */ /* a FITS image or table, with unsigned char (unsigned byte) data type. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgpvb( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned char nulval, /* I - value for undefined pixels */ unsigned char *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; char cdummy; int nullcheck = 1; unsigned char nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclb(fptr, 2, row, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpfb( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned char *array, /* O - array of values that are returned */ char *nularray, /* O - array of null pixel flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any undefined pixels in the returned array will be set = 0 and the corresponding nularray value will be set = 1. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; int nullcheck = 2; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem, nullcheck, NULL, array, nularray, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclb(fptr, 2, row, firstelem, nelem, 1, 2, 0, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg2db(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ unsigned char nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ unsigned char *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { /* call the 3D reading routine, with the 3rd dimension = 1 */ ffg3db(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg3db(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ unsigned char nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ unsigned char *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 3-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { long tablerow, ii, jj; LONGLONG narray, nfits; char cdummy; int nullcheck = 1; long inc[] = {1,1,1}; LONGLONG fpixel[] = {1,1,1}; LONGLONG lpixel[3]; unsigned char nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = ncols; lpixel[1] = nrows; lpixel[2] = naxis3; nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TBYTE, fpixel, lpixel, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so read all at once */ ffgclb(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to read */ narray = 0; /* next pixel in output array to be filled */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* reading naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffgclb(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval, &array[narray], &cdummy, anynul, status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsvb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ unsigned char nulval, /* I - value to set undefined pixels */ unsigned char *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii, i0, i1, i2, i3, i4, i5, i6, i7, i8, row, rstr, rstp, rinc; long str[9], stp[9], incr[9], dir[9]; long nelem, nultyp, ninc, numcol; LONGLONG felem, dsize[10], blcll[9], trcll[9]; int hdutype, anyf; char ldummy, msg[FLEN_ERRMSG]; int nullcheck = 1; unsigned char nullvalue; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvb is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TBYTE, blcll, trcll, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 1; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; dir[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { if (hdutype == IMAGE_HDU) { dir[ii] = -1; } else { snprintf(msg, FLEN_ERRMSG,"ffgsvb: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; dsize[ii] = dsize[ii] * dir[ii]; } dsize[naxis] = dsize[naxis] * dir[naxis]; if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1; ninc = incr[0] * dir[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8]) { for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7]) { for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6]) { for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5]) { for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4]) { for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3]) { for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2]) { for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1]) { felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] + (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] + (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8]; if ( ffgclb(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &ldummy, &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsfb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ unsigned char *array, /* O - array to be filled and returned */ char *flagval, /* O - set to 1 if corresponding value is null */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dsize[10]; LONGLONG blcll[9], trcll[9]; long felem, nelem, nultyp, ninc, numcol; int hdutype, anyf; unsigned char nulval = 0; char msg[FLEN_ERRMSG]; int nullcheck = 2; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvb is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } fits_read_compressed_img(fptr, TBYTE, blcll, trcll, inc, nullcheck, NULL, array, flagval, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 2; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { snprintf(msg, FLEN_ERRMSG,"ffgsvb: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; } if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0] - str[0]) / inc[0] + 1; ninc = incr[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8]) { for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7]) { for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6]) { for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5]) { for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4]) { for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3]) { for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2]) { for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1]) { felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] + (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] + (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8]; if ( ffgclb(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &flagval[i0], &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffggpb( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long firstelem, /* I - first vector element to read (1 = 1st) */ long nelem, /* I - number of values to read */ unsigned char *array, /* O - array of values that are returned */ int *status) /* IO - error status */ /* Read an array of group parameters from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). */ { long row; int idummy; char cdummy; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclb(fptr, 1, row, firstelem, nelem, 1, 1, 0, array, &cdummy, &idummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcvb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned char nulval, /* I - value for null pixels */ unsigned char *array, /* O - array of values that are read */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = 0 in which case no checks for undefined pixels will be made. */ { char cdummy; ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned char *array, /* O - array of values that are read */ char *nularray, /* O - array of flags: 1 if null pixel; else 0 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Nularray will be set = 1 if the corresponding array pixel is undefined, otherwise nularray will = 0. */ { unsigned char dummy = 0; ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgclb( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long elemincre, /* I - pixel increment; e.g., 2 = every other */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ unsigned char nulval, /* I - value for null pixels if nultyp = 1 */ unsigned char *array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer be a virtual column in a 1 or more grouped FITS primary array or image extension. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The output array of values will be converted from the datatype of the column and will be scaled by the FITS TSCALn and TZEROn values if necessary. */ { double scale, zero, power = 1., dtemp; int tcode, maxelem2, hdutype, xcode, decimals; long twidth, incre, ntodo; long ii, xwidth; int convert, nulcheck, readcheck = 16; /* see note below on readcheck */ LONGLONG repeat, startpos, elemnum, readptr, tnull; LONGLONG rowlen, rownum, remain, next, rowincre, maxelem; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value if reading from ASCII table */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; union u_tag { char charval; unsigned char ucharval; } u; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (elemincre < 0) readcheck -= 1; /* don't do range checking in this case */ /* IMPORTANT NOTE: that the special case of using this subroutine to read bytes from a character column are handled internally by the call to ffgcprll() below. It will adjust the effective *tcode, repeats, etc, to appear as a TBYTE column. */ /* Note that readcheck = 16 is equivalent to readcheck = 0 and readcheck = 15 is equivalent to readcheck = -1, but either of those settings allow TSTRINGS to be treated as TBYTE vectors, but with full error checking */ ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero, tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status); maxelem = maxelem2; /* special case */ if (tcode == TLOGICAL && elemincre == 1) { u.ucharval = nulval; ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, u.charval, (char *) array, nularray, anynul, status); return(*status); } if (*status > 0) return(*status); incre *= elemincre; /* multiply incre to just get every nth pixel */ if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */ { /* get the number of implied decimal places if no explicit decmal point */ ffasfm(tform, &xcode, &xwidth, &decimals, status); for(ii = 0; ii < decimals; ii++) power *= 10.; } /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default, check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (tcode%10 == 1 && /* if reading an integer column, and */ tnull == NULL_UNDEFINED) /* if a null value is not defined, */ nulcheck = 0; /* then do not check for null values. */ else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TBYTE && (tnull > 255 || tnull < 0) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED) nulcheck = 0; /*----------------------------------------------------------------------*/ /* If FITS column and output data array have same datatype, then we do */ /* not need to use a temporary buffer to store intermediate datatype. */ /*----------------------------------------------------------------------*/ convert = 1; if (tcode == TBYTE) /* Special Case: */ { /* no type convertion required, so read */ /* data directly into output buffer. */ if (nelem < (LONGLONG)INT32_MAX) { maxelem = nelem; } else { maxelem = INT32_MAX; } if (nulcheck == 0 && scale == 1. && zero == 0.) convert = 0; /* no need to scale data or find nulls */ } /*---------------------------------------------------------------------*/ /* Now read the pixels from the FITS column. If the column does not */ /* have the same datatype as the output array, then we have to read */ /* the raw values into a temporary buffer (of limited size). In */ /* the case of a vector colum read only 1 vector of values at a time */ /* then skip to the next row if more values need to be read. */ /* After reading the raw values, then call the fffXXYY routine to (1) */ /* test for undefined values, (2) convert the datatype if necessary, */ /* and (3) scale the values by the FITS TSCALn and TZEROn linear */ /* scaling parameters. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to read */ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to read at one time to the number that will fit in the buffer or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); if (elemincre >= 0) { ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1)); } else { ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1)); } readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre)); switch (tcode) { case (TBYTE): ffgi1b(fptr, readptr, ntodo, incre, &array[next], status); if (convert) fffi1i1(&array[next], ntodo, scale, zero, nulcheck, (unsigned char) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TSHORT): ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status); fffi2i1((short *) buffer, ntodo, scale, zero, nulcheck, (short) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TLONG): ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer, status); fffi4i1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, (INT32BIT) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TLONGLONG): ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status); fffi8i1( (LONGLONG *) buffer, ntodo, scale, zero, nulcheck, tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TFLOAT): ffgr4b(fptr, readptr, ntodo, incre, (float *) buffer, status); fffr4i1((float *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TDOUBLE): ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status); fffr8i1((double *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TSTRING): ffmbyt(fptr, readptr, REPORT_EOF, status); if (incre == twidth) /* contiguous bytes */ ffgbyt(fptr, ntodo * twidth, buffer, status); else ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); /* interpret the string as an ASCII formated number */ fffstri1((char *) buffer, ntodo, scale, zero, twidth, power, nulcheck, snull, nulval, &nularray[next], anynul, &array[next], status); break; default: /* error trap for invalid column format */ snprintf(message, FLEN_ERRMSG, "Cannot read bytes from column %d which has format %s", colnum, tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; if (hdutype > 0) snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from column %d (ffgclb).", dtemp+1., dtemp+ntodo, colnum); else snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from image (ffgclb).", dtemp+1., dtemp+ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum = elemnum + (ntodo * elemincre); if (elemnum >= repeat) /* completed a row; start on later row */ { rowincre = elemnum / repeat; rownum += rowincre; elemnum = elemnum - (rowincre * repeat); } else if (elemnum < 0) /* completed a row; start on a previous row */ { rowincre = (-elemnum - 1) / repeat + 1; rownum -= rowincre; elemnum = (rowincre * repeat) + elemnum; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while reading FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgextn( fitsfile *fptr, /* I - FITS file pointer */ LONGLONG offset, /* I - byte offset from start of extension data */ LONGLONG nelem, /* I - number of elements to read */ void *buffer, /* I - stream of bytes to read */ int *status) /* IO - error status */ /* Read a stream of bytes from the current FITS HDU. This primative routine is mainly for reading non-standard "conforming" extensions and should not be used for standard IMAGE, TABLE or BINTABLE extensions. */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); /* move to write position */ ffmbyt(fptr, (fptr->Fptr)->datastart+ offset, IGNORE_EOF, status); /* read the buffer */ ffgbyt(fptr, nelem, buffer, status); return(*status); } /*--------------------------------------------------------------------------*/ int fffi1i1(unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ unsigned char nullval,/* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output,/* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { /* this routine is normally not called in this case */ memmove(output, input, ntodo ); } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi2i1(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ unsigned char nullval,/* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output,/* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi4i1(INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ unsigned char nullval,/* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output,/* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi8i1(LONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG tnull, /* I - value of FITS TNULLn keyword if any */ unsigned char nullval,/* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output,/* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; ULONGLONG ulltemp; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) ulltemp; } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else { output[ii] = (unsigned char) ulltemp; } } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr4i1(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char nullval,/* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output,/* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { /* use redundant boolean logic in following statement */ /* to suppress irritating Borland compiler warning message */ if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (zero > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr8i1(double *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char nullval,/* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output,/* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (zero > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffstri1(char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ long twidth, /* I - width of each substring of chars */ double implipower, /* I - power of 10 of implied decimal */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ char *snull, /* I - value of FITS null string, if any */ unsigned char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to snull. If nullcheck= 0, then no special checking for nulls is performed. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { int nullen; long ii; double dvalue; char *cstring, message[FLEN_ERRMSG]; char *cptr, *tpos; char tempstore, chrzero = '0'; double val, power; int exponent, sign, esign, decpt; nullen = strlen(snull); cptr = input; /* pointer to start of input string */ for (ii = 0; ii < ntodo; ii++) { cstring = cptr; /* temporarily insert a null terminator at end of the string */ tpos = cptr + twidth; tempstore = *tpos; *tpos = 0; /* check if null value is defined, and if the */ /* column string is identical to the null string */ if (snull[0] != ASCII_NULL_UNDEFINED && !strncmp(snull, cptr, nullen) ) { if (nullcheck) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } cptr += twidth; } else { /* value is not the null value, so decode it */ /* remove any embedded blank characters from the string */ decpt = 0; sign = 1; val = 0.; power = 1.; exponent = 0; esign = 1; while (*cptr == ' ') /* skip leading blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for leading sign */ { if (*cptr == '-') sign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and value */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } if (*cptr == '.' || *cptr == ',') /* check for decimal point */ { decpt = 1; cptr++; while (*cptr == ' ') /* skip any blanks */ cptr++; while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ power = power * 10.; cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } } if (*cptr == 'E' || *cptr == 'D') /* check for exponent */ { cptr++; while (*cptr == ' ') /* skip blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for exponent sign */ { if (*cptr == '-') esign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and exp */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { exponent = exponent * 10 + *cptr - chrzero; /* accumulate exp */ cptr++; while (*cptr == ' ') /* skip embedded blanks */ cptr++; } } if (*cptr != 0) /* should end up at the null terminator */ { snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table"); ffpmsg(message); snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring); ffpmsg(message); /* restore the char that was overwritten by the null */ *tpos = tempstore; return(*status = BAD_C2D); } if (!decpt) /* if no explicit decimal, use implied */ power = implipower; dvalue = (sign * val / power) * pow(10., (double) (esign * exponent)); dvalue = dvalue * scale + zero; /* apply the scaling */ if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) dvalue; } /* restore the char that was overwritten by the null */ *tpos = tempstore; } return(*status); } cfitsio-4.3.1/simplerng.h0000644000225700000360000000206613472024437014630 0ustar cagordonlhea/* Simple Random Number Generators - getuniform - uniform deviate [0,1] - getnorm - gaussian (normal) deviate (mean=0, stddev=1) - getpoisson - poisson deviate for given expected mean lambda This code is adapted from SimpleRNG by John D Cook, which is provided in the public domain. The original C++ code is found here: http://www.johndcook.com/cpp_random_number_generation.html This code has been modified in the following ways compared to the original. 1. convert to C from C++ 2. keep only uniform, gaussian and poisson deviates 3. state variables are module static instead of class variables 4. provide an srand() equivalent to initialize the state */ extern void simplerng_setstate(unsigned int u, unsigned int v); extern void simplerng_getstate(unsigned int *u, unsigned int *v); extern void simplerng_srand(unsigned int seed); extern double simplerng_getuniform(void); extern double simplerng_getnorm(void); extern int simplerng_getpoisson(double lambda); extern double simplerng_logfactorial(int n); cfitsio-4.3.1/cookbook.c0000644000225700000360000005254213472024437014435 0ustar cagordonlhea#include #include #include /* Every program which uses the CFITSIO interface must include the the fitsio.h header file. This contains the prototypes for all the routines and defines the error status values and other symbolic constants used in the interface. */ #include "fitsio.h" int main( void ); void writeimage( void ); void writeascii( void ); void writebintable( void ); void copyhdu( void ); void selectrows( void ); void readheader( void ); void readimage( void ); void readtable( void ); void printerror( int status); int main() { /************************************************************************* This is a simple main program that calls the following routines: writeimage - write a FITS primary array image writeascii - write a FITS ASCII table extension writebintable - write a FITS binary table extension copyhdu - copy a header/data unit from one FITS file to another selectrows - copy selected row from one HDU to another readheader - read and print the header keywords in every extension readimage - read a FITS image and compute the min and max value readtable - read columns of data from ASCII and binary tables **************************************************************************/ writeimage(); writeascii(); writebintable(); copyhdu(); selectrows(); readheader(); readimage(); readtable(); printf("\nAll the cfitsio cookbook routines ran successfully.\n"); return(0); } /*--------------------------------------------------------------------------*/ void writeimage( void ) /******************************************************/ /* Create a FITS primary array containing a 2-D image */ /******************************************************/ { fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ int status, ii, jj; long fpixel, nelements, exposure; unsigned short *array[200]; /* initialize FITS image parameters */ char filename[] = "atestfil.fit"; /* name for new FITS file */ int bitpix = USHORT_IMG; /* 16-bit unsigned short pixel values */ long naxis = 2; /* 2-dimensional image */ long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ /* allocate memory for the whole image */ array[0] = (unsigned short *)malloc( naxes[0] * naxes[1] * sizeof( unsigned short ) ); /* initialize pointers to the start of each row of the image */ for( ii=1; ii 0) { nbuffer = npixels; if (npixels > buffsize) nbuffer = buffsize; /* read as many pixels as will fit in buffer */ /* Note that even though the FITS images contains unsigned integer */ /* pixel values (or more accurately, signed integer pixels with */ /* a bias of 32768), this routine is reading the values into a */ /* float array. Cfitsio automatically performs the datatype */ /* conversion in cases like this. */ if ( fits_read_img(fptr, TFLOAT, fpixel, nbuffer, &nullval, buffer, &anynull, &status) ) printerror( status ); for (ii = 0; ii < nbuffer; ii++) { if ( buffer[ii] < datamin ) datamin = buffer[ii]; if ( buffer[ii] > datamax ) datamax = buffer[ii]; } npixels -= nbuffer; /* increment remaining number of pixels */ fpixel += nbuffer; /* next pixel to be read in image */ } printf("\nMin and max image pixels = %.0f, %.0f\n", datamin, datamax); if ( fits_close_file(fptr, &status) ) printerror( status ); return; } /*--------------------------------------------------------------------------*/ void readtable( void ) /************************************************************/ /* read and print data values from an ASCII or binary table */ /************************************************************/ { fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ int status, hdunum, hdutype, nfound, anynull, ii; long frow, felem, nelem, longnull, dia[6]; float floatnull, den[6]; char strnull[10], *name[6], *ttype[3]; char filename[] = "atestfil.fit"; /* name of existing FITS file */ status = 0; if ( fits_open_file(&fptr, filename, READONLY, &status) ) printerror( status ); for (ii = 0; ii < 3; ii++) /* allocate space for the column labels */ ttype[ii] = (char *) malloc(FLEN_VALUE); /* max label length = 69 */ for (ii = 0; ii < 6; ii++) /* allocate space for string column value */ name[ii] = (char *) malloc(10); for (hdunum = 2; hdunum <= 3; hdunum++) /*read ASCII, then binary table */ { /* move to the HDU */ if ( fits_movabs_hdu(fptr, hdunum, &hdutype, &status) ) printerror( status ); if (hdutype == ASCII_TBL) printf("\nReading ASCII table in HDU %d:\n", hdunum); else if (hdutype == BINARY_TBL) printf("\nReading binary table in HDU %d:\n", hdunum); else { printf("Error: this HDU is not an ASCII or binary table\n"); printerror( status ); } /* read the column names from the TTYPEn keywords */ fits_read_keys_str(fptr, "TTYPE", 1, 3, ttype, &nfound, &status); printf(" Row %10s %10s %10s\n", ttype[0], ttype[1], ttype[2]); frow = 1; felem = 1; nelem = 6; strcpy(strnull, " "); longnull = 0; floatnull = 0.; /* read the columns */ fits_read_col(fptr, TSTRING, 1, frow, felem, nelem, strnull, name, &anynull, &status); fits_read_col(fptr, TLONG, 2, frow, felem, nelem, &longnull, dia, &anynull, &status); fits_read_col(fptr, TFLOAT, 3, frow, felem, nelem, &floatnull, den, &anynull, &status); for (ii = 0; ii < 6; ii++) printf("%5d %10s %10ld %10.2f\n", ii + 1, name[ii], dia[ii], den[ii]); } for (ii = 0; ii < 3; ii++) /* free the memory for the column labels */ free( ttype[ii] ); for (ii = 0; ii < 6; ii++) /* free the memory for the string column */ free( name[ii] ); if ( fits_close_file(fptr, &status) ) printerror( status ); return; } /*--------------------------------------------------------------------------*/ void printerror( int status) { /*****************************************************/ /* Print out cfitsio error messages and exit program */ /*****************************************************/ if (status) { fits_report_error(stderr, status); /* print error report */ exit( status ); /* terminate the program, returning error status */ } return; } cfitsio-4.3.1/cfitsio.xcodeproj/0000755000225700000360000000000013472024437016107 5ustar cagordonlheacfitsio-4.3.1/cfitsio.xcodeproj/project.pbxproj0000644000225700000360000000624113472024437021166 0ustar cagordonlhea// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXAggregateTarget section */ 462A28570A4EF04900AB8766 /* CFITSIO */ = { isa = PBXAggregateTarget; buildConfigurationList = 462A285C0A4EF05400AB8766 /* Build configuration list for PBXAggregateTarget "CFITSIO" */; buildPhases = ( 462A28580A4EF05100AB8766 /* ShellScript */, ); dependencies = ( ); name = CFITSIO; productName = "Build Universal"; }; /* End PBXAggregateTarget section */ /* Begin PBXGroup section */ 22831BBD1146D2B6004A1DD3 /* Products */ = { isa = PBXGroup; children = ( ); name = Products; sourceTree = ""; }; 462A28340A4EEE3200AB8766 = { isa = PBXGroup; children = ( 22831BBD1146D2B6004A1DD3 /* Products */, ); sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXProject section */ 462A28360A4EEE3200AB8766 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0630; }; buildConfigurationList = 462A28370A4EEE3200AB8766 /* Build configuration list for PBXProject "cfitsio" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 462A28340A4EEE3200AB8766; productRefGroup = 22831BBD1146D2B6004A1DD3 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 462A28570A4EF04900AB8766 /* CFITSIO */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ 462A28580A4EF05100AB8766 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "# shell script goes here\nmake distclean\n./configure\nmake shared\nmake testprog\nmake fpack\nmake funpack\nmake fitscopy\nexit 0"; }; /* End PBXShellScriptBuildPhase section */ /* Begin XCBuildConfiguration section */ 462A28390A4EEE3200AB8766 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; }; name = Release; }; 462A285E0A4EF05400AB8766 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; PRODUCT_NAME = CFITSIO; ZERO_LINK = NO; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 462A28370A4EEE3200AB8766 /* Build configuration list for PBXProject "cfitsio" */ = { isa = XCConfigurationList; buildConfigurations = ( 462A28390A4EEE3200AB8766 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 462A285C0A4EF05400AB8766 /* Build configuration list for PBXAggregateTarget "CFITSIO" */ = { isa = XCConfigurationList; buildConfigurations = ( 462A285E0A4EF05400AB8766 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 462A28360A4EEE3200AB8766 /* Project object */; } cfitsio-4.3.1/windumpexts.c0000644000225700000360000003135513472024437015215 0ustar cagordonlhea/* * winDumpExts.c -- * Author: Gordon Chaffee, Scott Stanton * * History: The real functionality of this file was written by * Matt Pietrek in 1993 in his pedump utility. I've * modified it to dump the externals in a bunch of object * files to create a .def file. * * 10/12/95 Modified by Scott Stanton to support Relocatable Object Module * Format files for Borland C++ 4.5. * * Notes: Visual C++ puts an underscore before each exported symbol. * This file removes them. I don't know if this is a problem * this other compilers. If _MSC_VER is defined, * the underscore is removed. If not, it isn't. To get a * full dump of an object file, use the -f option. This can * help determine the something that may be different with a * compiler other than Visual C++. *---------------------------------------------------------------------- * */ #include #include #include #include #ifdef _ALPHA_ #define e_magic_number IMAGE_FILE_MACHINE_ALPHA #else #define e_magic_number IMAGE_FILE_MACHINE_I386 #endif /* *---------------------------------------------------------------------- * GetArgcArgv -- * * Break up a line into argc argv *---------------------------------------------------------------------- */ int GetArgcArgv(char *s, char **argv) { int quote = 0; int argc = 0; char *bp; bp = s; while (1) { while (isspace(*bp)) { bp++; } if (*bp == '\n' || *bp == '\0') { *bp = '\0'; return argc; } if (*bp == '\"') { quote = 1; bp++; } argv[argc++] = bp; while (*bp != '\0') { if (quote) { if (*bp == '\"') { quote = 0; *bp = '\0'; bp++; break; } bp++; continue; } if (isspace(*bp)) { *bp = '\0'; bp++; break; } bp++; } } } /* * The names of the first group of possible symbol table storage classes */ char * SzStorageClass1[] = { "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL", "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG", "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC", "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD" }; /* * The names of the second group of possible symbol table storage classes */ char * SzStorageClass2[] = { "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL" }; /* *---------------------------------------------------------------------- * GetSZStorageClass -- * * Given a symbol storage class value, return a descriptive * ASCII string *---------------------------------------------------------------------- */ PSTR GetSZStorageClass(BYTE storageClass) { if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD ) return SzStorageClass1[storageClass]; else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK) && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) ) return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK]; else return "???"; } /* *---------------------------------------------------------------------- * GetSectionName -- * * Used by DumpSymbolTable, it gives meaningful names to * the non-normal section number. * * Results: * A name is returned in buffer *---------------------------------------------------------------------- */ void GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer) { char tempbuffer[10]; switch ( (SHORT)section ) { case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break; case IMAGE_SYM_ABSOLUTE: strcpy(tempbuffer, "ABS "); break; case IMAGE_SYM_DEBUG: strcpy(tempbuffer, "DEBUG"); break; default: wsprintf(tempbuffer, "%-5X", section); } strncpy(buffer, tempbuffer, cbBuffer-1); } /* *---------------------------------------------------------------------- * DumpSymbolTable -- * * Dumps a COFF symbol table from an EXE or OBJ. We only use * it to dump tables from OBJs. *---------------------------------------------------------------------- */ void DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols) { unsigned i; PSTR stringTable; char sectionName[10]; fprintf(fout, "Symbol Table - %X entries (* = auxillary symbol)\n", cSymbols); fprintf(fout, "Indx Name Value Section cAux Type Storage\n" "---- -------------------- -------- ---------- ----- ------- --------\n"); /* * The string table apparently starts right after the symbol table */ stringTable = (PSTR)&pSymbolTable[cSymbols]; for ( i=0; i < cSymbols; i++ ) { fprintf(fout, "%04X ", i); if ( pSymbolTable->N.Name.Short != 0 ) fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName); else fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long); fprintf(fout, " %08X", pSymbolTable->Value); GetSectionName(pSymbolTable->SectionNumber, sectionName, sizeof(sectionName)); fprintf(fout, " sect:%s aux:%X type:%02X st:%s\n", sectionName, pSymbolTable->NumberOfAuxSymbols, pSymbolTable->Type, GetSZStorageClass(pSymbolTable->StorageClass) ); #if 0 if ( pSymbolTable->NumberOfAuxSymbols ) DumpAuxSymbols(pSymbolTable); #endif /* * Take into account any aux symbols */ i += pSymbolTable->NumberOfAuxSymbols; pSymbolTable += pSymbolTable->NumberOfAuxSymbols; pSymbolTable++; } } /* *---------------------------------------------------------------------- * DumpExternals -- * * Dumps a COFF symbol table from an EXE or OBJ. We only use * it to dump tables from OBJs. *---------------------------------------------------------------------- */ void DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols) { unsigned i; PSTR stringTable; char *s, *f; char symbol[1024]; /* * The string table apparently starts right after the symbol table */ stringTable = (PSTR)&pSymbolTable[cSymbols]; for ( i=0; i < cSymbols; i++ ) { if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) { if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { if (pSymbolTable->N.Name.Short != 0) { strncpy(symbol, pSymbolTable->N.ShortName, 8); symbol[8] = 0; } else { s = stringTable + pSymbolTable->N.Name.Long; strncpy(symbol, s, 1023); symbol[1023]=0; } s = symbol; f = strchr(s, '@'); if (f) { *f = 0; } #if defined(_MSC_VER) && defined(_X86_) if (symbol[0] == '_') { s = &symbol[1]; } #endif if ((stricmp(s, "DllEntryPoint") != 0) && (stricmp(s, "DllMain") != 0)) { fprintf(fout, "\t%s\n", s); } } } /* * Take into account any aux symbols */ i += pSymbolTable->NumberOfAuxSymbols; pSymbolTable += pSymbolTable->NumberOfAuxSymbols; pSymbolTable++; } } /* *---------------------------------------------------------------------- * DumpObjFile -- * * Dump an object file--either a full listing or just the exported * symbols. *---------------------------------------------------------------------- */ void DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full) { PIMAGE_SYMBOL PCOFFSymbolTable; DWORD COFFSymbolCount; PCOFFSymbolTable = (PIMAGE_SYMBOL) ((DWORD)pImageFileHeader + pImageFileHeader->PointerToSymbolTable); COFFSymbolCount = pImageFileHeader->NumberOfSymbols; if (full) { DumpSymbolTable(PCOFFSymbolTable, fout, COFFSymbolCount); } else { DumpExternals(PCOFFSymbolTable, fout, COFFSymbolCount); } } /* *---------------------------------------------------------------------- * SkipToNextRecord -- * * Skip over the current ROMF record and return the type of the * next record. *---------------------------------------------------------------------- */ BYTE SkipToNextRecord(BYTE **ppBuffer) { int length; (*ppBuffer)++; /* Skip over the type.*/ length = *((WORD*)(*ppBuffer))++; /* Retrieve the length. */ *ppBuffer += length; /* Skip over the rest. */ return **ppBuffer; /* Return the type. */ } /* *---------------------------------------------------------------------- * DumpROMFObjFile -- * * Dump a Relocatable Object Module Format file, displaying only * the exported symbols. *---------------------------------------------------------------------- */ void DumpROMFObjFile(LPVOID pBuffer, FILE *fout) { BYTE type, length; char symbol[1024], *s; while (1) { type = SkipToNextRecord(&(BYTE*)pBuffer); if (type == 0x90) { /* PUBDEF */ if (((BYTE*)pBuffer)[4] != 0) { length = ((BYTE*)pBuffer)[5]; strncpy(symbol, ((char*)pBuffer) + 6, length); symbol[length] = '\0'; s = symbol; if ((stricmp(s, "DllEntryPoint") != 0) && (stricmp(s, "DllMain") != 0)) { if (s[0] == '_') { s++; fprintf(fout, "\t_%s\n\t%s=_%s\n", s, s, s); } else { fprintf(fout, "\t%s\n", s); } } } } else if (type == 0x8B || type == 0x8A) { /* MODEND */ break; } } } /* *---------------------------------------------------------------------- * DumpFile -- * * Open up a file, memory map it, and call the appropriate * dumping routine *---------------------------------------------------------------------- */ void DumpFile(LPSTR filename, FILE *fout, int full) { HANDLE hFile; HANDLE hFileMapping; LPVOID lpFileBase; PIMAGE_DOS_HEADER dosHeader; hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "Couldn't open file with CreateFile()\n"); return; } hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hFileMapping == 0) { CloseHandle(hFile); fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n"); return; } lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); if (lpFileBase == 0) { CloseHandle(hFileMapping); CloseHandle(hFile); fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n"); return; } dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { #if 0 DumpExeFile( dosHeader ); #else fprintf(stderr, "File is an executable. I don't dump those.\n"); return; #endif } /* Does it look like a i386 COFF OBJ file??? */ else if ((dosHeader->e_magic == e_magic_number) && (dosHeader->e_sp == 0)) { /* * The two tests above aren't what they look like. They're * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; */ DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full); } else if (*((BYTE *)lpFileBase) == 0x80) { /* * This file looks like it might be a ROMF file. */ DumpROMFObjFile(lpFileBase, fout); } else { printf("unrecognized file format\n"); } UnmapViewOfFile(lpFileBase); CloseHandle(hFileMapping); CloseHandle(hFile); } void main(int argc, char **argv) { char *fargv[1000]; char cmdline[10000]; int i, arg; FILE *fout; int pos; int full = 0; char *outfile = NULL; if (argc < 3) { Usage: fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)? ..\n", argv[0]); exit(1); } arg = 1; while (argv[arg][0] == '-') { if (strcmp(argv[arg], "--") == 0) { arg++; break; } else if (strcmp(argv[arg], "-f") == 0) { full = 1; } else if (strcmp(argv[arg], "-o") == 0) { arg++; if (arg == argc) { goto Usage; } outfile = argv[arg]; } arg++; } if (arg == argc) { goto Usage; } if (outfile) { fout = fopen(outfile, "w+"); if (fout == NULL) { fprintf(stderr, "Unable to open \'%s\' for writing:\n", argv[arg]); perror(""); exit(1); } } else { fout = stdout; } if (! full) { char *dllname = argv[arg]; arg++; if (arg == argc) { goto Usage; } fprintf(fout, "LIBRARY %s\n", dllname); fprintf(fout, "EXETYPE WINDOWS\n"); fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n"); fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n"); fprintf(fout, "EXPORTS\n"); } for (; arg < argc; arg++) { if (argv[arg][0] == '@') { FILE *fargs = fopen(&argv[arg][1], "r"); if (fargs == NULL) { fprintf(stderr, "Unable to open \'%s\' for reading:\n", argv[arg]); perror(""); exit(1); } pos = 0; for (i = 0; i < arg; i++) { strncpy(&cmdline[pos], argv[i], 9999-pos); cmdline[9999]=0; pos += strlen(&cmdline[pos]) + 1; fargv[i] = argv[i]; } fgets(&cmdline[pos], sizeof(cmdline), fargs); fprintf(stderr, "%s\n", &cmdline[pos]); fclose(fargs); i += GetArgcArgv(&cmdline[pos], &fargv[i]); argc = i; argv = fargv; } DumpFile(argv[arg], fout, full); } exit(0); } cfitsio-4.3.1/histo.c0000644000225700000360000033676514456514035013772 0ustar cagordonlhea/* Globally defined histogram parameters */ #include #include #include #include #include "fitsio2.h" #include "eval_defs.h" typedef struct { /* Structure holding all the histogramming information */ union { /* the iterator work functions (ffwritehist, ffcalchist) */ char *b; /* need to do their job... passed via *userPointer. */ short *i; int *j; float *r; double *d; } hist; fitsfile *tblptr; int haxis, hcolnum[4], himagetype; long haxis1, haxis2, haxis3, haxis4; double amin1, amin2, amin3, amin4; double maxbin1, maxbin2, maxbin3, maxbin4; double binsize1, binsize2, binsize3, binsize4; long incr[5]; int wtrecip, wtcolnum; char *wtexpr; double weight; char *rowselector; char *rowselector_cur; long repeat; int startCols[5]; int numIterCols; iteratorCol *iterCols; ParseData *parsers; parseInfo *infos; } histType; /*--------------------------------------------------------------------------*/ int ffbinse(char *binspec, /* I - binning specification */ int *imagetype, /* O - image type, TINT or TSHORT */ int *histaxis, /* O - no. of axes in the histogram */ char colname[4][FLEN_VALUE], /* column name for axis */ double *minin, /* minimum value for each axis */ double *maxin, /* maximum value for each axis */ double *binsizein, /* size of bins on each axis */ char minname[4][FLEN_VALUE], /* keyword name for min */ char maxname[4][FLEN_VALUE], /* keyword name for max */ char binname[4][FLEN_VALUE], /* keyword name for binsize */ double *wt, /* weighting factor */ char *wtname, /* keyword or column name for weight */ int *recip, /* the reciprocal of the weight? */ char ***exprs, /* returned with expressions (or 0) */ int *status) { /* Parse the extended input binning specification string, returning the binning parameters. Supports up to 4 dimensions. The binspec string has one of these forms: bin binsize - 2D histogram with binsize on each axis bin xcol - 1D histogram on column xcol bin (xcol, ycol) = binsize - 2D histogram with binsize on each axis bin x=min:max:size, y=min:max:size, z..., t... bin x=:max, y=::size bin x=size, y=min::size bin x(expr), y(expr)=min:max:size, ... most other reasonable combinations are supported. The (expr) is an optional expression that will be calculated on the fly instead of a table column name. The name is still used for the output pixel array metadata. If expr == 0, then expressions are forbidden. The caller does not expect expressions. If exprs is non-zero, then upon return an array of expressions is passed back to the caller. Storage may be allocated by this routine, If *exprs is non-zero upon return, the caller is responsible to free(*exprs). Upon return, the contains of exprs is, (*exprs)[0] = expression for column 1 (or 0 if none) (*exprs)[1] = expression for column 2 (or 0 if none) (*exprs)[2] = expression for column 3 (or 0 if none) (*exprs)[3] = expression for column 4 (or 0 if none) (*exprs)[4] = expression for weighting (or 0 if none) If the user specifies a column name and not an expression for bin axis i, then the corresponding (*exprs)[i] will be a null pointer. To be recognized as an expression, the weighting expression must be enclosed in parentheses. Expressions are never allowed using the bin (xcol,ycol) notation. */ int ii, slen, defaulttype; char *ptr, tmpname[FLEN_VALUE], *file_expr = NULL; double dummy; char *exprbeg[5] = {0}, *exprend[5] = {0}; int has_exprs = 0; if (exprs) (*exprs) = 0; /* initialized output */ if (*status > 0) return(*status); /* set the default values */ *histaxis = 2; *imagetype = TINT; defaulttype = 1; *wt = 1.; *recip = 0; *wtname = '\0'; /* set default values */ for (ii = 0; ii < 4; ii++) { *colname[ii] = '\0'; *minname[ii] = '\0'; *maxname[ii] = '\0'; *binname[ii] = '\0'; minin[ii] = DOUBLENULLVALUE; /* undefined values */ maxin[ii] = DOUBLENULLVALUE; binsizein[ii] = DOUBLENULLVALUE; } ptr = binspec + 3; /* skip over 'bin' */ if (*ptr == 'i' ) /* bini */ { *imagetype = TSHORT; defaulttype = 0; ptr++; } else if (*ptr == 'j' ) /* binj; same as default */ { defaulttype = 0; ptr ++; } else if (*ptr == 'r' ) /* binr */ { *imagetype = TFLOAT; defaulttype = 0; ptr ++; } else if (*ptr == 'd' ) /* bind */ { *imagetype = TDOUBLE; defaulttype = 0; ptr ++; } else if (*ptr == 'b' ) /* binb */ { *imagetype = TBYTE; defaulttype = 0; ptr ++; } if (*ptr == '\0') /* use all defaults for other parameters */ return(*status); else if (*ptr != ' ') /* must be at least one blank */ { ffpmsg("binning specification syntax error:"); ffpmsg(binspec); return(*status = URL_PARSE_ERROR); } while (*ptr == ' ') /* skip over blanks */ ptr++; if (*ptr == '\0') /* no other parameters; use defaults */ return(*status); /* Check if need to import expression from a file */ if( *ptr=='@' ) { if( ffimport_file( ptr+1, &file_expr, status ) ) return(*status); ptr = file_expr; while (*ptr == ' ') ptr++; /* skip leading white space... again */ } if (*ptr == '(' ) { /* this must be the opening parenthesis around a list of column */ /* names, optionally followed by a '=' and the binning spec. */ for (ii = 0; ii < 4; ii++) { ptr++; /* skip over the '(', ',', or ' ') */ while (*ptr == ' ') /* skip over blanks */ ptr++; slen = strcspn(ptr, " ,)"); strncat(colname[ii], ptr, slen); /* copy 1st column name */ ptr += slen; while (*ptr == ' ') /* skip over blanks */ ptr++; if (*ptr == ')' ) /* end of the list of names */ { *histaxis = ii + 1; break; } } if (ii == 4) /* too many names in the list , or missing ')' */ { ffpmsg( "binning specification has too many column names or is missing closing ')':"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status = URL_PARSE_ERROR); } ptr++; /* skip over the closing parenthesis */ while (*ptr == ' ') /* skip over blanks */ ptr++; if (*ptr == '\0') { if( file_expr ) free( file_expr ); return(*status); /* parsed the entire string */ } else if (*ptr != '=') /* must be an equals sign now*/ { ffpmsg("illegal binning specification in URL:"); ffpmsg(" an equals sign '=' must follow the column names"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status = URL_PARSE_ERROR); } ptr++; /* skip over the equals sign */ while (*ptr == ' ') /* skip over blanks */ ptr++; /* get the single range specification for all the columns */ /* Note that the extended syntax is not allowed here */ ffbinr(&ptr, tmpname, minin, maxin, binsizein, minname[0], maxname[0], binname[0], status); if (*status > 0) { ffpmsg("illegal binning specification in URL:"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status); } for (ii = 1; ii < *histaxis; ii++) { minin[ii] = minin[0]; maxin[ii] = maxin[0]; binsizein[ii] = binsizein[0]; strcpy(minname[ii], minname[0]); strcpy(maxname[ii], maxname[0]); strcpy(binname[ii], binname[0]); } while (*ptr == ' ') /* skip over blanks */ ptr++; if (*ptr == ';') goto getweight; /* a weighting factor is specified */ if (*ptr != '\0') /* must have reached end of string */ { ffpmsg("illegal syntax after binning range specification in URL:"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status = URL_PARSE_ERROR); } return(*status); } /* end of case with list of column names in ( ) */ /* if we've reached this point, then the binning specification */ /* must be of the form: XCOL = min:max:binsize, YCOL = ... */ /* where the column name followed by '=' are optional. */ /* If the column name is not specified, then use the default name */ for (ii = 0; ii < 4; ii++) /* allow up to 4 histogram dimensions */ { exprbeg[ii] = exprend[ii] = 0; ffbinre(&ptr, colname[ii], &(exprbeg[ii]), &(exprend[ii]), &minin[ii], &maxin[ii], &binsizein[ii], minname[ii], maxname[ii], binname[ii], status); /* Check for expressions */ if (exprbeg[ii]) has_exprs = 1; if (*status > 0) { ffpmsg("illegal syntax in binning range specification in URL:"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status); } if (*ptr == '\0' || *ptr == ';') break; /* reached the end of the string */ if (*ptr == ' ') { while (*ptr == ' ') /* skip over blanks */ ptr++; if (*ptr == '\0' || *ptr == ';') break; /* reached the end of the string */ if (*ptr == ',') ptr++; /* comma separates the next column specification */ } else if (*ptr == ',') { ptr++; /* comma separates the next column specification */ } else { ffpmsg("illegal characters following binning specification in URL:"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status = URL_PARSE_ERROR); } } if (ii == 4) { /* there are yet more characters in the string */ ffpmsg("illegal binning specification in URL:"); ffpmsg("apparently greater than 4 histogram dimensions"); ffpmsg(binspec); return(*status = URL_PARSE_ERROR); } else *histaxis = ii + 1; /* special case: if a single number was entered it should be */ /* interpreted as the binning factor for the default X and Y axes */ if (*histaxis == 1 && *colname[0] == '\0' && minin[0] == DOUBLENULLVALUE && maxin[0] == DOUBLENULLVALUE) { *histaxis = 2; binsizein[1] = binsizein[0]; } getweight: if (*ptr == ';') /* looks like a weighting factor is given */ { ptr++; while (*ptr == ' ') /* skip over blanks */ ptr++; *recip = 0; if (*ptr == '/') { *recip = 1; /* the reciprocal of the weight is entered */ ptr++; while (*ptr == ' ') /* skip over blanks */ ptr++; } /* parse the weight as though it were a binrange. */ /* either a column name or a numerical value will be returned */ exprbeg[4] = exprend[4] = 0; ffbinre(&ptr, wtname, &(exprbeg[4]), &(exprend[4]), &dummy, &dummy, wt, tmpname, tmpname, tmpname, status); if (exprbeg[4]) has_exprs = 1; if (*status > 0) { ffpmsg("illegal binning weight specification in URL:"); ffpmsg(binspec); if( file_expr ) free( file_expr ); return(*status); } /* creat a float datatype histogram by default, if weight */ /* factor is not = 1.0 */ if ( (defaulttype && *wt != 1.0) || (defaulttype && *wtname) || (defaulttype && exprbeg[4])) { *imagetype = TFLOAT; } } while (*ptr == ' ') /* skip over blanks */ ptr++; if (*ptr != '\0') /* should have reached the end of string */ { ffpmsg("illegal syntax after binning weight specification in URL:"); ffpmsg(binspec); *status = URL_PARSE_ERROR; } if( file_expr ) free( file_expr ); /* If we found expressions, this is where we accumulate them into something to be returned to the caller. The start and end of each expression will be found in exprbeg[] and exprend[], with the 5th entry being the weight expression if any */ if (has_exprs) { size_t nchars = 0; char *ptr; for (ii = 0; ii <= 4; ii++) { nchars += (exprend[ii] - exprbeg[ii]) + 1; /* null terminator */ } /* Allocate storage for 5 pointers plus the characters. Caller is responsible to free(*exprs) which will free both the 5-array and the character string data. */ ptr = malloc( sizeof(char *) * 5 + nchars * sizeof(char) ); if (!ptr) { ffpmsg("ffbinse: memory allocation failure"); return(*status = MEMORY_ALLOCATION); } (*exprs) = (char **) ptr; /* Pointer array portion */ ptr = (char *) (&((*exprs)[5])); /* String portion starts after the pointer array */ for (ii = 0; ii <= 4; ii++) { (*exprs)[ii] = ptr; nchars = (exprend[ii]-exprbeg[ii]); strncpy(ptr, exprbeg[ii], nchars); ptr += nchars; ptr[0] = 0; /* Ensure null terminator */ ptr ++; /* Advance to next string position */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffbins(char *binspec, /* I - binning specification */ int *imagetype, /* O - image type, TINT or TSHORT */ int *histaxis, /* O - no. of axes in the histogram */ char colname[4][FLEN_VALUE], /* column name for axis */ double *minin, /* minimum value for each axis */ double *maxin, /* maximum value for each axis */ double *binsizein, /* size of bins on each axis */ char minname[4][FLEN_VALUE], /* keyword name for min */ char maxname[4][FLEN_VALUE], /* keyword name for max */ char binname[4][FLEN_VALUE], /* keyword name for binsize */ double *wt, /* weighting factor */ char *wtname, /* keyword or column name for weight */ int *recip, /* the reciprocal of the weight? */ int *status) { /* Parse non-extended expression, but otherwise the same as ffbinse() */ return ffbinse(binspec, imagetype, histaxis, colname, minin, maxin, binsizein, minname, maxname, binname, wt, wtname, recip, 0, /* No exprs pointer */ status); } /*--------------------------------------------------------------------------*/ int ffbinre(char **ptr, char *colname, char **exprbeg, char **exprend, double *minin, double *maxin, double *binsizein, char *minname, char *maxname, char *binname, int *status) /* Parse the input binning range specification string, returning the column name, histogram min and max values, and bin size. This is the "extended" binning syntax that allows for an expression of the form XCOL(expr). The expression must be enclosed in parentheses. The start and end of the expression are returned in *exprbeg and *exprend. If exprbeg and exprend are null pointers then the expression is forbidden. */ { int slen, isanumber=0; char *token=0; if (*status > 0) return(*status); slen = fits_get_token2(ptr, " ,=:;(", &token, &isanumber, status); /* get 1st token */ if ((*status) || (slen == 0 && (**ptr == '\0' || **ptr == ',' || **ptr == ';')) ) return(*status); /* a null range string */ if (!isanumber && **ptr != ':') { /* this looks like the column name */ /* Check for case where col name string is empty but '=' is still there (indicating a following specification string). Musn't enter this block as token would not have been allocated. */ if (token) { if (strlen(token) > FLEN_VALUE-1) { ffpmsg("column name too long (ffbinr)"); free(token); return(*status=PARSE_SYNTAX_ERR); } if (token[0] == '#' && isdigit((int) token[1]) ) { /* omit the leading '#' in the column number */ strcpy(colname, token+1); } else strcpy(colname, token); free(token); token=0; } while (**ptr == ' ') /* skip over blanks */ (*ptr)++; /* An optional expression of the form XCOL(expr) is allowed here, but only if exprbeg and exprend are non-null */ if (**ptr == '(' && exprbeg && exprend) { *exprbeg = *ptr; if ((*exprend = fits_find_match_delim(*ptr+1,')')) == 0) { /* find ')' */ ffpmsg("bin expression syntax error (ffbinr)"); return(*status=PARSE_SYNTAX_ERR); } *ptr = *exprend; /* Advance pointer past delimeter */ } while (**ptr == ' ') (*ptr)++; /* skip over more possible blanks */ if (**ptr != '=') return(*status); /* reached the end */ (*ptr)++; /* skip over the = sign */ while (**ptr == ' ') /* skip over blanks */ (*ptr)++; /* get specification info */ slen = fits_get_token2(ptr, " ,:;", &token, &isanumber, status); if (*status) return(*status); } if (**ptr != ':') { /* This is the first token, and since it is not followed by a ':' this must be the binsize token. Or it could be empty. */ if (token) { if (!isanumber) { if (strlen(token) > FLEN_VALUE-1) { ffpmsg("binname too long (ffbinr)"); free(token); return(*status=PARSE_SYNTAX_ERR); } strcpy(binname, token); } else *binsizein = strtod(token, NULL); free(token); } return(*status); /* reached the end */ } else { /* the token contains the min value */ if (slen) { if (!isanumber) { if (strlen(token) > FLEN_VALUE-1) { ffpmsg("minname too long (ffbinr)"); free(token); return(*status=PARSE_SYNTAX_ERR); } strcpy(minname, token); } else *minin = strtod(token, NULL); free(token); token=0; } } (*ptr)++; /* skip the colon between the min and max values */ slen = fits_get_token2(ptr, " ,:;", &token, &isanumber, status); /* get token */ if (*status) return(*status); /* the token contains the max value */ if (slen) { if (!isanumber) { if (strlen(token) > FLEN_VALUE-1) { ffpmsg("maxname too long (ffbinr)"); free(token); return(*status=PARSE_SYNTAX_ERR); } strcpy(maxname, token); } else *maxin = strtod(token, NULL); free(token); token=0; } if (**ptr != ':') { free(token); return(*status); /* reached the end; no binsize token */ } (*ptr)++; /* skip the colon between the max and binsize values */ slen = fits_get_token2(ptr, " ,:;", &token, &isanumber, status); /* get token */ if (*status) return(*status); /* the token contains the binsize value */ if (slen) { if (!isanumber) { if (strlen(token) > FLEN_VALUE-1) { ffpmsg("binname too long (ffbinr)"); free(token); return(*status=PARSE_SYNTAX_ERR); } strcpy(binname, token); } else *binsizein = strtod(token, NULL); free(token); } return(*status); } /*--------------------------------------------------------------------------*/ int ffbinr(char **ptr, char *colname, double *minin, double *maxin, double *binsizein, char *minname, char *maxname, char *binname, int *status) /* Parse the input binning range specification string, returning the column name, histogram min and max values, and bin size. This is the non-extended version of the parser which disallows binning expressions. Only column names are allowed. */ { return ffbinre(ptr, colname, 0, 0, minin, maxin, binsizein, minname, maxname, binname, status); } /*--------------------------------------------------------------------------*/ int ffhist2e(fitsfile **fptr, /* IO - pointer to table with X and Y cols; */ /* on output, points to histogram image */ char *outfile, /* I - name for the output histogram file */ int imagetype, /* I - datatype for image: TINT, TSHORT, etc */ int naxis, /* I - number of axes in the histogram image */ char colname[4][FLEN_VALUE], /* I - column names */ char *colexpr[4], /* I - optionally, expression intead of colum */ double *minin, /* I - minimum histogram value, for each axis */ double *maxin, /* I - maximum histogram value, for each axis */ double *binsizein, /* I - bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ double weightin, /* I - binning weighting factor */ char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/ char *wtexpr, /* I - optionally, weight expression */ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { fitsfile *histptr; int bitpix, colnum[4], wtcolnum; long haxes[4]; double amin[4], amax[4], binsize[4], weight; int numIterCols = 0; int datatypes[4], wtdatatype = 0; long *repeat, wtrepeat = 0; char errmsg[FLEN_ERRMSG]; long vectorRepeat; if (*status > 0) return(*status); if (naxis > 4) { ffpmsg("histogram has more than 4 dimensions"); *status = BAD_DIMEN; goto cleanup; } /* reset position to the correct HDU if necessary */ if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu) ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status); if (imagetype == TBYTE) bitpix = BYTE_IMG; else if (imagetype == TSHORT) bitpix = SHORT_IMG; else if (imagetype == TINT) bitpix = LONG_IMG; else if (imagetype == TFLOAT) bitpix = FLOAT_IMG; else if (imagetype == TDOUBLE) bitpix = DOUBLE_IMG; else { *status = BAD_DATATYPE; goto cleanup; } /* Calculate the binning parameters: */ /* columm numbers, axes length, min values, max values, and binsizes. */ if (fits_calc_binningde( *fptr, naxis, colname, colexpr, minin, maxin, binsizein, minname, maxname, binname, colnum, datatypes, haxes, amin, amax, binsize, &vectorRepeat, status) > 0) { ffpmsg("failed to determine binning parameters"); goto cleanup; } /* get the histogramming weighting factor, if any */ if (*wtcol) { /* first, look for a keyword with the weight value */ if (ffgky(*fptr, TDOUBLE, wtcol, &weight, NULL, status) == 0) { /* Data type if keyword was found */ wtdatatype = TDOUBLE; wtrepeat = 1; } else { /* not a keyword, so look for column with this name */ *status = 0; /* get the column number in the table */ if (ffgcno(*fptr, CASEINSEN, wtcol, &wtcolnum, status) > 0) { ffpmsg( "keyword or column for histogram weights doesn't exist: "); ffpmsg(wtcol); goto cleanup; } /* get the datatype of the column */ fits_get_eqcoltype(*fptr, wtcolnum, &wtdatatype, &wtrepeat, NULL, status); weight = DOUBLENULLVALUE; } } else if (wtexpr && wtexpr[0]) /* A weighting expression - always TDOUBLE */ { /* Initialize the parser so that we can determine the datatype of the returned type as well as the vector dimensions. The parsers is kept allocated so we can assemble an iterator that uses it below. */ int naxis1; long int nelem, naxes[MAXDIMS]; ParseData lParse; ffiprs( *fptr, 0, wtexpr, MAXDIMS, &wtdatatype, &nelem, &naxis1, naxes, &lParse, status ); ffcprs( &lParse ); if (nelem < 0) nelem = 1; /* If it's a constant expression */ weight = DOUBLENULLVALUE; wtrepeat = nelem; wtdatatype = wtdatatype; } else { weight = (double) weightin; wtrepeat = vectorRepeat; wtdatatype = TDOUBLE; } /* Make sure weighting column is not an un-binnable data type */ if (wtdatatype < 0 || wtdatatype == TSTRING || wtdatatype == TBIT || wtdatatype == TLOGICAL) { ffpmsg("Invalid datatype for bin weighting factor"); *status = BAD_DATATYPE; goto cleanup; } /* And dimensions of weighting must agree with input column data */ if (wtrepeat != vectorRepeat) { ffpmsg("Vector dimensions of weighting do not agree with binning columns"); *status = BAD_DIMEN; goto cleanup; } if (weight <= 0. && weight != DOUBLENULLVALUE) { ffpmsg("Illegal histogramming weighting factor <= 0."); *status = URL_PARSE_ERROR; goto cleanup; } if (recip && weight != DOUBLENULLVALUE) { /* take reciprocal of weight */ weight = (double) (1.0 / weight); } /* size of histogram is now known, so create temp output file */ if (fits_create_file(&histptr, outfile, status) > 0) { ffpmsg("failed to create temp output file for histogram"); goto cleanup; } /* create output FITS image HDU */ if (ffcrim(histptr, bitpix, naxis, haxes, status) > 0) { ffpmsg("failed to create output histogram FITS image"); goto cleanup; } /* copy header keywords, converting pixel list WCS keywords to image WCS form */ if (fits_copy_pixlist2image(*fptr, histptr, 9, naxis, colnum, status) > 0) { ffpmsg("failed to copy pixel list keywords to new histogram header"); goto cleanup; } /* if the table columns have no WCS keywords, then write default keywords */ fits_write_keys_histoe(*fptr, histptr, naxis, colnum, colname, colexpr, status); /* update the WCS keywords for the ref. pixel location, and pixel size */ fits_rebin_wcsd(histptr, naxis, amin, binsize, status); /* now compute the output image by binning the column values */ if (fits_make_histde(*fptr, histptr, datatypes, bitpix, naxis, haxes, colnum, colexpr, amin, amax, binsize, weight, wtcolnum, wtexpr, recip, selectrow, status) > 0) { ffpmsg("failed to calculate new histogram values"); goto cleanup; } /* finally, close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = histptr; cleanup: return(*status); } /*--------------------------------------------------------------------------*/ int ffhist2(fitsfile **fptr, /* IO - pointer to table with X and Y cols; */ /* on output, points to histogram image */ char *outfile, /* I - name for the output histogram file */ int imagetype, /* I - datatype for image: TINT, TSHORT, etc */ int naxis, /* I - number of axes in the histogram image */ char colname[4][FLEN_VALUE], /* I - column names */ double *minin, /* I - minimum histogram value, for each axis */ double *maxin, /* I - maximum histogram value, for each axis */ double *binsizein, /* I - bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ double weightin, /* I - binning weighting factor */ char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { /* Non-extended-syntax version of ffhist2e() */ return ffhist2e(fptr, outfile, imagetype, naxis, colname, 0, minin, maxin, binsizein, minname, maxname, binname, weightin, wtcol, 0, recip, selectrow, status); } /*--------------------------------------------------------------------------*/ /* ffhist3: same as ffhist2, but does not close the original file */ /* and/or replace the original file pointer */ fitsfile *ffhist3(fitsfile *fptr, /* I - ptr to table with X and Y cols*/ char *outfile, /* I - name for the output histogram file */ int imagetype, /* I - datatype for image: TINT, TSHORT, etc */ int naxis, /* I - number of axes in the histogram image */ char colname[4][FLEN_VALUE], /* I - column names */ double *minin, /* I - minimum histogram value, for each axis */ double *maxin, /* I - maximum histogram value, for each axis */ double *binsizein, /* I - bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ double weightin, /* I - binning weighting factor */ char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { fitsfile *histptr; int bitpix, colnum[4], wtcolnum; long haxes[4]; double amin[4], amax[4], binsize[4], weight; if (*status > 0) return(NULL); if (naxis > 4) { ffpmsg("histogram has more than 4 dimensions"); *status = BAD_DIMEN; return(NULL); } /* reset position to the correct HDU if necessary */ if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu) ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status); if (imagetype == TBYTE) bitpix = BYTE_IMG; else if (imagetype == TSHORT) bitpix = SHORT_IMG; else if (imagetype == TINT) bitpix = LONG_IMG; else if (imagetype == TFLOAT) bitpix = FLOAT_IMG; else if (imagetype == TDOUBLE) bitpix = DOUBLE_IMG; else{ *status = BAD_DATATYPE; return(NULL); } /* Calculate the binning parameters: */ /* columm numbers, axes length, min values, max values, and binsizes. */ if (fits_calc_binningd( fptr, naxis, colname, minin, maxin, binsizein, minname, maxname, binname, colnum, haxes, amin, amax, binsize, status) > 0) { ffpmsg("failed to determine binning parameters"); return(NULL); } /* get the histogramming weighting factor, if any */ if (*wtcol) { /* first, look for a keyword with the weight value */ if (fits_read_key(fptr, TDOUBLE, wtcol, &weight, NULL, status) ) { /* not a keyword, so look for column with this name */ *status = 0; /* get the column number in the table */ if (ffgcno(fptr, CASEINSEN, wtcol, &wtcolnum, status) > 0) { ffpmsg( "keyword or column for histogram weights doesn't exist: "); ffpmsg(wtcol); return(NULL); } weight = DOUBLENULLVALUE; } } else weight = (double) weightin; if (weight <= 0. && weight != DOUBLENULLVALUE) { ffpmsg("Illegal histogramming weighting factor <= 0."); *status = URL_PARSE_ERROR; return(NULL); } if (recip && weight != DOUBLENULLVALUE) /* take reciprocal of weight */ weight = (double) (1.0 / weight); /* size of histogram is now known, so create temp output file */ if (fits_create_file(&histptr, outfile, status) > 0) { ffpmsg("failed to create temp output file for histogram"); return(NULL); } /* create output FITS image HDU */ if (ffcrim(histptr, bitpix, naxis, haxes, status) > 0) { ffpmsg("failed to create output histogram FITS image"); return(NULL); } /* copy header keywords, converting pixel list WCS keywords to image WCS */ if (fits_copy_pixlist2image(fptr, histptr, 9, naxis, colnum, status) > 0) { ffpmsg("failed to copy pixel list keywords to new histogram header"); return(NULL); } /* if the table columns have no WCS keywords, then write default keywords */ fits_write_keys_histo(fptr, histptr, naxis, colnum, status); /* update the WCS keywords for the ref. pixel location, and pixel size */ fits_rebin_wcsd(histptr, naxis, amin, binsize, status); /* now compute the output image by binning the column values */ if (fits_make_histd(fptr, histptr, bitpix, naxis, haxes, colnum, amin, amax, binsize, weight, wtcolnum, recip, selectrow, status) > 0) { ffpmsg("failed to calculate new histogram values"); return(NULL); } return(histptr); } /*--------------------------------------------------------------------------*/ int ffhist(fitsfile **fptr, /* IO - pointer to table with X and Y cols; */ /* on output, points to histogram image */ char *outfile, /* I - name for the output histogram file */ int imagetype, /* I - datatype for image: TINT, TSHORT, etc */ int naxis, /* I - number of axes in the histogram image */ char colname[4][FLEN_VALUE], /* I - column names */ double *minin, /* I - minimum histogram value, for each axis */ double *maxin, /* I - maximum histogram value, for each axis */ double *binsizein, /* I - bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ double weightin, /* I - binning weighting factor */ char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { int ii, datatype, repeat, imin, imax, ibin, bitpix, tstatus, use_datamax = 0; long haxes[4]; fitsfile *histptr; char errmsg[FLEN_ERRMSG], keyname[FLEN_KEYWORD], card[FLEN_CARD]; tcolumn *colptr; iteratorCol imagepars[1]; int n_cols = 1, nkeys; long offset = 0; long n_per_loop = -1; /* force whole array to be passed at one time */ histType histData; /* Structure holding histogram info for iterator */ double amin[4], amax[4], binsize[4], maxbin[4]; double datamin = DOUBLENULLVALUE, datamax = DOUBLENULLVALUE; char svalue[FLEN_VALUE]; double dvalue; char cpref[4][FLEN_VALUE]; char *cptr; if (*status > 0) return(*status); if (naxis > 4) { ffpmsg("histogram has more than 4 dimensions"); return(*status = BAD_DIMEN); } /* reset position to the correct HDU if necessary */ if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu) ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status); histData.tblptr = *fptr; histData.himagetype = imagetype; histData.haxis = naxis; histData.rowselector = selectrow; if (imagetype == TBYTE) bitpix = BYTE_IMG; else if (imagetype == TSHORT) bitpix = SHORT_IMG; else if (imagetype == TINT) bitpix = LONG_IMG; else if (imagetype == TFLOAT) bitpix = FLOAT_IMG; else if (imagetype == TDOUBLE) bitpix = DOUBLE_IMG; else return(*status = BAD_DATATYPE); /* The CPREF keyword, if it exists, gives the preferred columns. */ /* Otherwise, assume "X", "Y", "Z", and "T" */ tstatus = 0; ffgky(*fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus); if (!tstatus) { /* Preferred column names are given; separate them */ cptr = cpref[0]; /* the first preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[1], cptr); cptr = cpref[1]; /* the second preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[2], cptr); cptr = cpref[2]; /* the third preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[3], cptr); } } } } for (ii = 0; ii < naxis; ii++) { /* get the min, max, and binsize values from keywords, if specified */ if (*minname[ii]) { if (ffgky(*fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) ) { ffpmsg("error reading histogramming minimum keyword"); ffpmsg(minname[ii]); return(*status); } } if (*maxname[ii]) { if (ffgky(*fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) ) { ffpmsg("error reading histogramming maximum keyword"); ffpmsg(maxname[ii]); return(*status); } } if (*binname[ii]) { if (ffgky(*fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) ) { ffpmsg("error reading histogramming binsize keyword"); ffpmsg(binname[ii]); return(*status); } } if (binsizein[ii] == 0.) { ffpmsg("error: histogram binsize = 0"); return(*status = ZERO_SCALE); } if (*colname[ii] == '\0') { strcpy(colname[ii], cpref[ii]); /* try using the preferred column */ if (*colname[ii] == '\0') { if (ii == 0) strcpy(colname[ii], "X"); else if (ii == 1) strcpy(colname[ii], "Y"); else if (ii == 2) strcpy(colname[ii], "Z"); else if (ii == 3) strcpy(colname[ii], "T"); } } /* get the column number in the table */ if (ffgcno(*fptr, CASEINSEN, colname[ii], histData.hcolnum+ii, status) > 0) { strcpy(errmsg, "column for histogram axis doesn't exist: "); strncat(errmsg, colname[ii], FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status); } colptr = ((*fptr)->Fptr)->tableptr; colptr += (histData.hcolnum[ii] - 1); repeat = (int) colptr->trepeat; /* vector repeat factor of the column */ if (repeat > 1) { strcpy(errmsg, "Can't bin a vector column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status = BAD_DATATYPE); } /* get the datatype of the column */ fits_get_eqcoltype(*fptr, histData.hcolnum[ii], &datatype, NULL, NULL, status); if (datatype < 0 || datatype == TSTRING) { strcpy(errmsg, "Inappropriate datatype; can't bin this column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status = BAD_DATATYPE); } /* use TLMINn and TLMAXn keyword values if min and max were not given */ /* else use actual data min and max if TLMINn and TLMAXn don't exist */ if (minin[ii] == DOUBLENULLVALUE) { ffkeyn("TLMIN", histData.hcolnum[ii], keyname, status); if (ffgky(*fptr, TDOUBLE, keyname, amin+ii, NULL, status) > 0) { /* use actual data minimum value for the histogram minimum */ *status = 0; if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], amin+ii, &datamax, status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status); } } } else { amin[ii] = (double) minin[ii]; } if (maxin[ii] == DOUBLENULLVALUE) { ffkeyn("TLMAX", histData.hcolnum[ii], keyname, status); if (ffgky(*fptr, TDOUBLE, keyname, &amax[ii], NULL, status) > 0) { *status = 0; if(datamax != DOUBLENULLVALUE) /* already computed max value */ { amax[ii] = datamax; } else { /* use actual data maximum value for the histogram maximum */ if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], &datamin, &amax[ii], status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status); } } } use_datamax = 1; /* flag that the max was determined by the data values */ /* and not specifically set by the calling program */ } else { amax[ii] = (double) maxin[ii]; } /* use TDBINn keyword or else 1 if bin size is not given */ if (binsizein[ii] == DOUBLENULLVALUE) { tstatus = 0; ffkeyn("TDBIN", histData.hcolnum[ii], keyname, &tstatus); if (ffgky(*fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus) > 0) { /* make at least 10 bins */ binsizein[ii] = (amax[ii] - amin[ii]) / 10. ; if (binsizein[ii] > 1.) binsizein[ii] = 1.; /* use default bin size */ } } if ( (amin[ii] > amax[ii] && binsizein[ii] > 0. ) || (amin[ii] < amax[ii] && binsizein[ii] < 0. ) ) binsize[ii] = (double) -binsizein[ii]; /* reverse the sign of binsize */ else binsize[ii] = (double) binsizein[ii]; /* binsize has the correct sign */ ibin = (int) binsize[ii]; imin = (int) amin[ii]; imax = (int) amax[ii]; /* Determine the range and number of bins in the histogram. This */ /* depends on whether the input columns are integer or floats, so */ /* treat each case separately. */ if (datatype <= TLONG && (double) imin == amin[ii] && (double) imax == amax[ii] && (double) ibin == binsize[ii] ) { /* This is an integer column and integer limits were entered. */ /* Shift the lower and upper histogramming limits by 0.5, so that */ /* the values fall in the center of the bin, not on the edge. */ haxes[ii] = (imax - imin) / ibin + 1; /* last bin may only */ /* be partially full */ maxbin[ii] = (double) (haxes[ii] + 1.); /* add 1. instead of .5 to avoid roundoff */ if (amin[ii] < amax[ii]) { amin[ii] = (double) (amin[ii] - 0.5); amax[ii] = (double) (amax[ii] + 0.5); } else { amin[ii] = (double) (amin[ii] + 0.5); amax[ii] = (double) (amax[ii] - 0.5); } } else if (use_datamax) { /* Either the column datatype and/or the limits are floating point, */ /* and the histogram limits are being defined by the min and max */ /* values of the array. Add 1 to the number of histogram bins to */ /* make sure that pixels that are equal to the maximum or are */ /* in the last partial bin are included. */ maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii]; haxes[ii] = (long) (maxbin[ii] + 1); } else { /* float datatype column and/or limits, and the maximum value to */ /* include in the histogram is specified by the calling program. */ /* The lower limit is inclusive, but upper limit is exclusive */ maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii]; haxes[ii] = (long) maxbin[ii]; if (amin[ii] < amax[ii]) { if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii]) haxes[ii]++; /* need to include another partial bin */ } else { if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii]) haxes[ii]++; /* need to include another partial bin */ } } } /* get the histogramming weighting factor */ if (*wtcol) { /* first, look for a keyword with the weight value */ if (ffgky(*fptr, TDOUBLE, wtcol, &histData.weight, NULL, status) ) { /* not a keyword, so look for column with this name */ *status = 0; /* get the column number in the table */ if (ffgcno(*fptr, CASEINSEN, wtcol, &histData.wtcolnum, status) > 0) { ffpmsg( "keyword or column for histogram weights doesn't exist: "); ffpmsg(wtcol); return(*status); } histData.weight = DOUBLENULLVALUE; } } else histData.weight = (double) weightin; if (histData.weight <= 0. && histData.weight != DOUBLENULLVALUE) { ffpmsg("Illegal histogramming weighting factor <= 0."); return(*status = URL_PARSE_ERROR); } if (recip && histData.weight != DOUBLENULLVALUE) /* take reciprocal of weight */ histData.weight = (double) (1.0 / histData.weight); histData.wtrecip = recip; /* size of histogram is now known, so create temp output file */ if (ffinit(&histptr, outfile, status) > 0) { ffpmsg("failed to create temp output file for histogram"); return(*status); } if (ffcrim(histptr, bitpix, histData.haxis, haxes, status) > 0) { ffpmsg("failed to create primary array histogram in temp file"); ffclos(histptr, status); return(*status); } /* copy all non-structural keywords from the table to the image */ fits_get_hdrspace(*fptr, &nkeys, NULL, status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(*fptr, ii, card, status); if (fits_get_keyclass(card) >= 120) fits_write_record(histptr, card, status); } /* Set global variables with histogram parameter values. */ /* Use separate scalar variables rather than arrays because */ /* it is more efficient when computing the histogram. */ histData.amin1 = amin[0]; histData.maxbin1 = maxbin[0]; histData.binsize1 = binsize[0]; histData.haxis1 = haxes[0]; if (histData.haxis > 1) { histData.amin2 = amin[1]; histData.maxbin2 = maxbin[1]; histData.binsize2 = binsize[1]; histData.haxis2 = haxes[1]; if (histData.haxis > 2) { histData.amin3 = amin[2]; histData.maxbin3 = maxbin[2]; histData.binsize3 = binsize[2]; histData.haxis3 = haxes[2]; if (histData.haxis > 3) { histData.amin4 = amin[3]; histData.maxbin4 = maxbin[3]; histData.binsize4 = binsize[3]; histData.haxis4 = haxes[3]; } } } /* define parameters of image for the iterator function */ fits_iter_set_file(imagepars, histptr); /* pointer to image */ fits_iter_set_datatype(imagepars, imagetype); /* image datatype */ fits_iter_set_iotype(imagepars, OutputCol); /* image is output */ /* call the iterator function to write out the histogram image */ if (fits_iterate_data(n_cols, imagepars, offset, n_per_loop, ffwritehisto, (void*)&histData, status) ) return(*status); /* write the World Coordinate System (WCS) keywords */ /* create default values if WCS keywords are not present in the table */ for (ii = 0; ii < histData.haxis; ii++) { /* CTYPEn */ tstatus = 0; ffkeyn("TCTYP", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); if (tstatus) { /* just use column name as the type */ tstatus = 0; ffkeyn("TTYPE", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); } if (!tstatus) { ffkeyn("CTYPE", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus); } else tstatus = 0; /* CUNITn */ ffkeyn("TCUNI", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); if (tstatus) { /* use the column units */ tstatus = 0; ffkeyn("TUNIT", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus); } if (!tstatus) { ffkeyn("CUNIT", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus); } else tstatus = 0; /* CRPIXn - Reference Pixel */ ffkeyn("TCRPX", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (tstatus) { dvalue = 1.0; /* choose first pixel in new image as ref. pix. */ tstatus = 0; } else { /* calculate locate of the ref. pix. in the new image */ dvalue = (dvalue - amin[ii]) / binsize[ii] + .5; } ffkeyn("CRPIX", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus); /* CRVALn - Value at the location of the reference pixel */ ffkeyn("TCRVL", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (tstatus) { /* calculate value at ref. pix. location (at center of 1st pixel) */ dvalue = amin[ii] + binsize[ii]/2.; tstatus = 0; } ffkeyn("CRVAL", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus); /* CDELTn - unit size of pixels */ ffkeyn("TCDLT", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (tstatus) { dvalue = 1.0; /* use default pixel size */ tstatus = 0; } dvalue = dvalue * binsize[ii]; ffkeyn("CDELT", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus); /* CROTAn - Rotation angle (degrees CCW) */ /* There should only be a CROTA2 keyword, and only for 2+ D images */ if (ii == 1) { ffkeyn("TCROT", histData.hcolnum[ii], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus && dvalue != 0.) /* only write keyword if angle != 0 */ { ffkeyn("CROTA", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Rotation angle", &tstatus); } else { /* didn't find CROTA for the 2nd axis, so look for one */ /* on the first axis */ tstatus = 0; ffkeyn("TCROT", histData.hcolnum[0], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus && dvalue != 0.) /* only write keyword if angle != 0 */ { dvalue *= -1.; /* negate the value, because mirror image */ ffkeyn("CROTA", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Rotation angle", &tstatus); } } } } /* convert any TPn_k keywords to PCi_j; the value remains unchanged */ /* also convert any TCn_k to CDi_j; the value is modified by n binning size */ /* This is a bit of a kludge, and only works for 2D WCS */ if (histData.haxis == 2) { /* PC1_1 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[0], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[0], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC1_1", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[0]; ffpky(histptr, TDOUBLE, "CD1_1", &dvalue, card, &tstatus); } /* PC1_2 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[0], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[1], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC1_2", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[0]; ffpky(histptr, TDOUBLE, "CD1_2", &dvalue, card, &tstatus); } /* PC2_1 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[1], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[0], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC2_1", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[1]; ffpky(histptr, TDOUBLE, "CD2_1", &dvalue, card, &tstatus); } /* PC2_2 */ tstatus = 0; ffkeyn("TP", histData.hcolnum[1], card, &tstatus); strcat(card,"_"); ffkeyn(card, histData.hcolnum[1], keyname, &tstatus); ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) ffpky(histptr, TDOUBLE, "PC2_2", &dvalue, card, &tstatus); tstatus = 0; keyname[1] = 'C'; ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus); if (!tstatus) { dvalue *= binsize[1]; ffpky(histptr, TDOUBLE, "CD2_2", &dvalue, card, &tstatus); } } /* finally, close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = histptr; return(*status); } /*--------------------------------------------------------------------------*/ /* Single-precision version */ int fits_calc_binning( fitsfile *fptr, /* IO - pointer to table to be binned ; */ int naxis, /* I - number of axes/columns in the binned image */ char colname[4][FLEN_VALUE], /* I - optional column names */ double *minin, /* I - optional lower bound value for each axis */ double *maxin, /* I - optional upper bound value, for each axis */ double *binsizein, /* I - optional bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ /* The returned parameters for each axis of the n-dimensional histogram are */ int *colnum, /* O - column numbers, to be binned */ long *haxes, /* O - number of bins in each histogram axis */ float *amin, /* O - lower bound of the histogram axes */ float *amax, /* O - upper bound of the histogram axes */ float *binsize, /* O - width of histogram bins/pixels on each axis */ int *status) { double amind[4], amaxd[4], binsized[4]; fits_calc_binningd(fptr, naxis, colname, minin, maxin, binsizein, minname, maxname, binname, colnum, haxes, amind, amaxd, binsized, status); /* Copy double precision values into single precision */ if (*status == 0) { int i, naxis1 = 4; if (naxis < naxis1) naxis1 = naxis; for (i=0; i 0) return(*status); /* Initialize the number of iterator columns required */ if (repeat) (*repeat) = 0; if (naxis > 4) { ffpmsg("histograms with more than 4 dimensions are not supported"); return(*status = BAD_DIMEN); } /* reset position to the correct HDU if necessary */ if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu) ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status); /* ============================================================= */ /* The CPREF keyword, if it exists, gives the preferred columns. */ /* Otherwise, assume "X", "Y", "Z", and "T" */ *cpref[0] = '\0'; *cpref[1] = '\0'; *cpref[2] = '\0'; *cpref[3] = '\0'; tstatus = 0; ffgky(fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus); if (!tstatus) { /* Preferred column names are given; separate them */ cptr = cpref[0]; /* the first preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[1], cptr); cptr = cpref[1]; /* the second preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[2], cptr); cptr = cpref[2]; /* the third preferred axis... */ while (*cptr != ',' && *cptr != '\0') cptr++; if (*cptr != '\0') { *cptr = '\0'; cptr++; while (*cptr == ' ') cptr++; strcpy(cpref[3], cptr); } } } } /* ============================================================= */ /* Main Loop for calculating parameters for each column */ for (ii = 0; ii < naxis; ii++) { /* =========================================================== */ /* Determine column Number, based on, in order of priority, 1 input column name, or 2 name given by CPREF keyword, or 3 assume X, Y, Z and T for the name */ if (*colname[ii] == '\0' && (colexpr == 0 || colexpr[ii] == 0 || colexpr[ii][0] == '\0')) { strcpy(colname[ii], cpref[ii]); /* try using the preferred column */ if (*colname[ii] == '\0') { if (ii == 0) strcpy(colname[ii], "X"); else if (ii == 1) strcpy(colname[ii], "Y"); else if (ii == 2) strcpy(colname[ii], "Z"); else if (ii == 3) strcpy(colname[ii], "T"); } } /* get the column number in the table */ colnum[ii] = 0; if (colexpr == 0 || colexpr[ii] == 0 || colexpr[ii][0] == '\0') { if (ffgcno(fptr, CASEINSEN, colname[ii], colnum+ii, status) > 0) { strcpy(errmsg, "column for histogram axis doesn't exist: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status); } /* ================================================================ */ /* check tha column is not a vector or a string */ /* get the datatype of the column */ fits_get_eqcoltype(fptr, colnum[ii], &datatype, &repeat1, NULL, status); ncols = 1; /* Require only one iterator column, the actual column */ } else { /* column expression: use parse to determine datatype and dimensions */ long nelem, naxes[MAXDIMS]; int naxis; ParseData lParse; /* Initialize the parser so that we can determine the datatype of the returned type as well as the vector dimensions */ if ( ffiprs( fptr, 0, colexpr[ii], MAXDIMS, &datatype, &nelem, &naxis, naxes, &lParse, status ) ) { snprintf(errmsg, FLEN_ERRMSG, "Parser error of binning expression: %s", colexpr[ii]); ffpmsg(errmsg); return *status; } if (nelem < 0) nelem = 1; /* If it's a constant expression */ repeat1 = nelem; /* We require lParse.nCols columns to be read from input, plus one for the Temporary calculator result */ ncols = lParse.nCols + 1; ffcprs( &lParse ); } /* Not sure why this repeat limitation is here -- CM The iterator system can handle vector columns just fine ` */ if (datatype < 0 || datatype == TSTRING) { strcpy(errmsg, "Inappropriate datatype; can't bin this column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status = BAD_DATATYPE); } /* Store repeat value for future use */ if (repeat) { if (ii == 0) { *repeat = repeat1; /* First time around save the repeat value */ } else if (*repeat != repeat1) { /* later dimensions, keep same dims */ strcpy(errmsg, "Vector repeat of input columns do not agree"); ffpmsg(errmsg); return (*status = BAD_DIMEN); } } if (datatypes) datatypes[ii] = datatype; /* ================================================================ */ /* get the minimum value */ datamin = DOUBLENULLVALUE; datamax = DOUBLENULLVALUE; if (*minname[ii]) { if (ffgky(fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) ) { ffpmsg("error reading histogramming minimum keyword"); ffpmsg(minname[ii]); return(*status); } } if (minin[ii] != DOUBLENULLVALUE) { amin[ii] = (double) minin[ii]; } else if (colexpr == 0 || colexpr[ii] == 0 || colexpr[ii][0] == '\0') { ffkeyn("TLMIN", colnum[ii], keyname, status); if (ffgky(fptr, TDOUBLE, keyname, amin+ii, NULL, status) > 0) { /* use actual data minimum value for the histogram minimum */ *status = 0; if (fits_get_col_minmax(fptr, colnum[ii], amin+ii, &datamax, status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status); } } } else { /* it's an expression */ if (fits_get_expr_minmax(fptr, colexpr[ii], amin+ii, &datamax, 0, status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for expression: "); ffpmsg(errmsg); ffpmsg(colexpr[ii]); return(*status); } if (amin[ii] == DOUBLENULLVALUE) amin[ii] = 0.0; } /* ================================================================ */ /* get the maximum value */ if (*maxname[ii]) { if (ffgky(fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) ) { ffpmsg("error reading histogramming maximum keyword"); ffpmsg(maxname[ii]); return(*status); } } if (maxin[ii] != DOUBLENULLVALUE) { amax[ii] = (double) maxin[ii]; } else if (colexpr == 0 || colexpr[ii] == 0 || colexpr[ii][0] == '\0') { ffkeyn("TLMAX", colnum[ii], keyname, status); if (ffgky(fptr, TDOUBLE, keyname, &amax[ii], NULL, status) > 0) { *status = 0; if(datamax != DOUBLENULLVALUE) /* already computed max value */ { amax[ii] = datamax; } else { /* use actual data maximum value for the histogram maximum */ if (fits_get_col_minmax(fptr, colnum[ii], &datamin, &amax[ii], status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for column: "); strncat(errmsg, colname[ii],FLEN_ERRMSG-strlen(errmsg)-1); ffpmsg(errmsg); return(*status); } } } use_datamax = 1; /* flag that the max was determined by the data values */ /* and not specifically set by the calling program */ } else { /* it's an expression */ if (fits_get_expr_minmax(fptr, colexpr[ii], &datamin, &amax[ii], 0, status) > 0) { strcpy(errmsg, "Error calculating datamin and datamax for expression: "); ffpmsg(errmsg); ffpmsg(colexpr[ii]); return(*status); } if (amax[ii] == DOUBLENULLVALUE) amin[ii] = 1.0; use_datamax = 1; } /* ================================================================ */ /* determine binning size and range */ if (*binname[ii]) { if (ffgky(fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) ) { ffpmsg("error reading histogramming binsize keyword"); ffpmsg(binname[ii]); return(*status); } } if (binsizein[ii] == 0.) { ffpmsg("error: histogram binsize = 0"); return(*status = ZERO_SCALE); } /* use TDBINn keyword or else 1 if bin size is not given */ if (binsizein[ii] != DOUBLENULLVALUE) { binsize[ii] = (double) binsizein[ii]; } else { tstatus = 0; if (colexpr == 0 || colexpr[ii] == 0 || colexpr[ii][0] == '\0') { ffkeyn("TDBIN", colnum[ii], keyname, &tstatus); ffgky(fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus); } if (tstatus || colexpr && colexpr[ii] && colexpr[ii][0]) { /* make at least 10 bins */ binsize[ii] = (amax[ii] - amin[ii]) / 10.F ; if (binsize[ii] > 1.) binsize[ii] = 1.; /* use default bin size */ } } /* ================================================================ */ /* if the min is greater than the max, make the binsize negative */ if ( (amin[ii] > amax[ii] && binsize[ii] > 0. ) || (amin[ii] < amax[ii] && binsize[ii] < 0. ) ) binsize[ii] = -binsize[ii]; /* reverse the sign of binsize */ ibin = (int) binsize[ii]; imin = (int) amin[ii]; imax = (int) amax[ii]; /* Determine the range and number of bins in the histogram. This */ /* depends on whether the input columns are integer or floats, so */ /* treat each case separately. */ if (datatype <= TLONG && (double) imin == amin[ii] && (double) imax == amax[ii] && (double) ibin == binsize[ii] ) { /* This is an integer column and integer limits were entered. */ /* Shift the lower and upper histogramming limits by 0.5, so that */ /* the values fall in the center of the bin, not on the edge. */ haxes[ii] = (imax - imin) / ibin + 1; /* last bin may only */ /* be partially full */ if (amin[ii] < amax[ii]) { amin[ii] = (double) (amin[ii] - 0.5); amax[ii] = (double) (amax[ii] + 0.5); } else { amin[ii] = (double) (amin[ii] + 0.5); amax[ii] = (double) (amax[ii] - 0.5); } } else if (use_datamax) { /* Either the column datatype and/or the limits are floating point, */ /* and the histogram limits are being defined by the min and max */ /* values of the array. Add 1 to the number of histogram bins to */ /* make sure that pixels that are equal to the maximum or are */ /* in the last partial bin are included. */ haxes[ii] = (long) (((amax[ii] - amin[ii]) / binsize[ii]) + 1.); } else { /* float datatype column and/or limits, and the maximum value to */ /* include in the histogram is specified by the calling program. */ /* The lower limit is inclusive, but upper limit is exclusive */ haxes[ii] = (long) ((amax[ii] - amin[ii]) / binsize[ii]); if (amin[ii] < amax[ii]) { if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii]) haxes[ii]++; /* need to include another partial bin */ } else { if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii]) haxes[ii]++; /* need to include another partial bin */ } } } return(*status); } /* Double precision version, with non-extended syntax */ int fits_calc_binningd( fitsfile *fptr, /* IO - pointer to table to be binned ; */ int naxis, /* I - number of axes/columns in the binned image */ char colname[4][FLEN_VALUE], /* I - optional column names */ double *minin, /* I - optional lower bound value for each axis */ double *maxin, /* I - optional upper bound value, for each axis */ double *binsizein, /* I - optional bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ /* The returned parameters for each axis of the n-dimensional histogram are */ int *colnum, /* O - column numbers, to be binned */ long *haxes, /* O - number of bins in each histogram axis */ double *amin, /* O - lower bound of the histogram axes */ double *amax, /* O - upper bound of the histogram axes */ double *binsize, /* O - width of histogram bins/pixels on each axis */ int *status) /* Calculate the actual binning parameters, non-extended-syntax version */ { return fits_calc_binningde(fptr, naxis, colname, 0, minin, maxin, binsizein, minname, maxname, binname, colnum, 0, haxes, amin, amax, binsize, 0, status); } /*--------------------------------------------------------------------------*/ int fits_write_keys_histoe( fitsfile *fptr, /* I - pointer to table to be binned */ fitsfile *histptr, /* I - pointer to output histogram image HDU */ int naxis, /* I - number of axes in the histogram image */ int *colnum, /* I - column numbers (array length = naxis) */ char colname[4][FLEN_VALUE], /* I - if expression, then column name to use */ char *colexpr[4], /* I - if expression, then column name to use */ int *status) { /* Write default WCS keywords in the output histogram image header */ /* if the keywords do not already exist. */ int ii, tstatus; char keyname[FLEN_KEYWORD], svalue[FLEN_VALUE]; double dvalue; if (*status > 0) return(*status); for (ii = 0; ii < naxis; ii++) { /* CTYPEn */ tstatus = 0; if (colexpr && colexpr[ii] && colexpr[ii][0] && colname[ii]) { /* Column expression: we need to put the column name from the binning expression */ ffkeyn("CTYPE", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, colname[ii], "Coordinate Type", &tstatus); } else { /* Column name */ tstatus = 0; ffkeyn("CTYPE", ii+1, keyname, &tstatus); ffgky(histptr, TSTRING, keyname, svalue, NULL, &tstatus); if (!tstatus) continue; /* keyword already exists, so skip to next axis */ /* use column name as the axis name */ tstatus = 0; ffkeyn("TTYPE", colnum[ii], keyname, &tstatus); ffgky(fptr, TSTRING, keyname, svalue, NULL, &tstatus); if (!tstatus) { ffkeyn("CTYPE", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus); } /* CUNITn, use the column units */ tstatus = 0; ffkeyn("TUNIT", colnum[ii], keyname, &tstatus); ffgky(fptr, TSTRING, keyname, svalue, NULL, &tstatus); if (!tstatus) { ffkeyn("CUNIT", ii + 1, keyname, &tstatus); ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus); } } /* CRPIXn - Reference Pixel choose first pixel in new image as ref. pix. */ dvalue = 1.0; tstatus = 0; ffkeyn("CRPIX", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus); /* CRVALn - Value at the location of the reference pixel */ dvalue = 1.0; tstatus = 0; ffkeyn("CRVAL", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus); /* CDELTn - unit size of pixels */ dvalue = 1.0; tstatus = 0; dvalue = 1.; ffkeyn("CDELT", ii + 1, keyname, &tstatus); ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_write_keys_histo( fitsfile *fptr, /* I - pointer to table to be binned */ fitsfile *histptr, /* I - pointer to output histogram image HDU */ int naxis, /* I - number of axes in the histogram image */ int *colnum, /* I - column numbers (array length = naxis) */ int *status) { return fits_write_keys_histoe(fptr, histptr, naxis, colnum, 0, 0, status); } /*--------------------------------------------------------------------------*/ int fits_rebin_wcs( fitsfile *fptr, /* I - pointer to table to be binned */ int naxis, /* I - number of axes in the histogram image */ float *amin, /* I - first pixel include in each axis */ float *binsize, /* I - binning factor for each axis */ int *status) { double amind[4], binsized[4]; /* Copy single precision values into double precision */ if (*status == 0) { int i, naxis1 = 4; if (naxis < naxis1) naxis1 = naxis; for (i=0; i 0) return(*status); for (ii = 0; ii < naxis; ii++) { reset = 0; /* flag to reset the reference pixel */ tstatus = 0; ffkeyn("CRVAL", ii + 1, keyname, &tstatus); /* get previous (pre-binning) value */ ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus && dvalue == 1.0) { reset = 1; } tstatus = 0; /* CRPIXn - update location of the ref. pix. in the binned image */ ffkeyn("CRPIX", ii + 1, keyname, &tstatus); /* get previous (pre-binning) value */ ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus) { if (dvalue != 1.0) reset = 0; /* updated value to give pixel location after binning */ dvalue = (dvalue - amin[ii]) / ((double) binsize[ii]) + .5; fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus); } else { reset = 0; } /* CDELTn - update unit size of pixels */ tstatus = 0; ffkeyn("CDELT", ii + 1, keyname, &tstatus); /* get previous (pre-binning) value */ ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus) { if (dvalue != 1.0) reset = 0; /* updated to give post-binning value */ dvalue = dvalue * binsize[ii]; fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus); } else { /* no CDELTn keyword, so look for a CDij keywords */ reset = 0; for (jj = 0; jj < naxis; jj++) { tstatus = 0; ffkeyn("CD", jj + 1, svalue, &tstatus); strcat(svalue,"_"); ffkeyn(svalue, ii + 1, keyname, &tstatus); /* get previous (pre-binning) value */ ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); if (!tstatus) { /* updated to give post-binning value */ dvalue = dvalue * binsize[ii]; fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus); } } } if (reset) { /* the original CRPIX, CRVAL, and CDELT keywords were all = 1.0 */ /* In this special case, reset the reference pixel to be the */ /* first pixel in the array (instead of possibly far off the array) */ dvalue = 1.0; ffkeyn("CRPIX", ii + 1, keyname, &tstatus); fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus); ffkeyn("CRVAL", ii + 1, keyname, &tstatus); dvalue = amin[ii] + (binsize[ii] / 2.0); fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus); } } return(*status); } /*--------------------------------------------------------------------------*/ /* Single-precision version */ int fits_make_hist(fitsfile *fptr, /* IO - pointer to table with X and Y cols; */ fitsfile *histptr, /* I - pointer to output FITS image */ int bitpix, /* I - datatype for image: 16, 32, -32, etc */ int naxis, /* I - number of axes in the histogram image */ long *naxes, /* I - size of axes in the histogram image */ int *colnum, /* I - column numbers (array length = naxis) */ float *amin, /* I - minimum histogram value, for each axis */ float *amax, /* I - maximum histogram value, for each axis */ float *binsize, /* I - bin size along each axis */ float weight, /* I - binning weighting factor */ int wtcolnum, /* I - optional keyword or col for weight*/ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { double amind[4], amaxd[4], binsized[4], weightd; /* Copy single precision values into double precision */ if (*status == 0) { int i, naxis1 = 4; if (naxis < naxis1) naxis1 = naxis; for (i=0; i 0) return(*status); /* Make sure the parser information is initialized because we will use this to determine what needs to be deallocated at the end */ memset(infos, 0, sizeof(infos)); memset(parsers, 0, sizeof(parsers)); memset(&histData, 0, sizeof(histData)); if (naxis > 4) { ffpmsg("histogram has more than 4 dimensions"); return(*status = BAD_DIMEN); } if (bitpix == BYTE_IMG) imagetype = TBYTE; else if (bitpix == SHORT_IMG) imagetype = TSHORT; else if (bitpix == LONG_IMG) imagetype = TINT; else if (bitpix == FLOAT_IMG) imagetype = TFLOAT; else if (bitpix == DOUBLE_IMG) imagetype = TDOUBLE; else return(*status = BAD_DATATYPE); /* reset position to the correct HDU if necessary */ if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu) ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status); /* Resolve the conflict between wtexpr, wtcolnum, and weight */ if ( ((wtcolnum > 0) || (wtexpr && wtexpr[0])) && weight == 0 ) weight = DOUBLENULLVALUE; histData.weight = weight; histData.wtcolnum = wtcolnum; histData.wtexpr = wtexpr; histData.wtrecip = recip; histData.tblptr = fptr; histData.himagetype = imagetype; histData.haxis = naxis; histData.rowselector = selectrow; /* Now make iterator columns for input, as well as any calculated values */ numAllocCols = 5; iterCols = fits_recalloc(0, 0, numAllocCols, sizeof(iteratorCol)); if (!iterCols) { ffpmsg("memory allocation failure (fits_make_histde)"); *status = MEMORY_ALLOCATION; goto cleanup; } /* We fill the iterCols in order, starting from column 1 through 4, and then moving on to the weighting column */ for (ii = 0; ii < 5; ii++) histData.startCols[ii] = -1; startCol = 0; /* Loop through each axis and recheck the binning parameters */ for (ii = 0; ii < naxis; ii++) { long colrepeat = 0; int datatype; histData.startCols[ii] = startCol; taxes[ii] = (double) naxes[ii]; tmin[ii] = amin[ii]; tmax[ii] = amax[ii]; if ( (amin[ii] > amax[ii] && binsize[ii] > 0. ) || (amin[ii] < amax[ii] && binsize[ii] < 0. ) ) tbin[ii] = -binsize[ii]; /* reverse the sign of binsize */ else tbin[ii] = binsize[ii]; /* binsize has the correct sign */ imin = (long) tmin[ii]; imax = (long) tmax[ii]; ibin = (long) tbin[ii]; /* get the datatype of the column and repeat */ if (! (colexpr && colexpr[ii] && colexpr[ii][0]) ) { fits_get_eqcoltype(fptr, colnum[ii], &datatype, &colrepeat, NULL, status); } /* If caller specified datatype, use that */ if (datatypes && datatypes[ii]) { datatype = datatypes[ii]; } if (datatype <= TLONG && (double) imin == tmin[ii] && (double) imax == tmax[ii] && (double) ibin == tbin[ii] ) { /* This is an integer column and integer limits were entered. */ /* Shift the lower and upper histogramming limits by 0.5, so that */ /* the values fall in the center of the bin, not on the edge. */ maxbin[ii] = (taxes[ii] + 1.F); /* add 1. instead of .5 to avoid roundoff */ if (tmin[ii] < tmax[ii]) { tmin[ii] = tmin[ii] - 0.5F; tmax[ii] = tmax[ii] + 0.5F; } else { tmin[ii] = tmin[ii] + 0.5F; tmax[ii] = tmax[ii] - 0.5F; } } else { /* not an integer column with integer limits */ maxbin[ii] = (tmax[ii] - tmin[ii]) / tbin[ii]; } /* This is a column expression. Here is where we allocate the parser for it during the actual evaluation. */ if (colexpr && colexpr[ii] && colexpr[ii][0]) { int datatype, naxis1; long nelem, naxes[MAXDIMS]; int jj; /* Initialize the parser for this binning expression */ ffiprs( fptr, 0, colexpr[ii], MAXDIMS, &datatype, &nelem, &naxis1, naxes, &(parsers[ii]), status ); if (*status) goto cleanup; if (nelem < 0) nelem = 1; /* If it's a constant expression */ colrepeat = nelem; /* Set up the parser data for evaluation to a TemporaryCol */ fits_get_num_rows(fptr, &nrows, status); if (fits_parser_set_temporary_col(&(parsers[ii]), &(infos[ii]), nrows, (void *) &(double_nulval), status)) goto cleanup; /* Copy iterator columns from the parser to the master iterator columns */ iterCols = fits_recalloc(iterCols, numAllocCols, numAllocCols+parsers[ii].nCols, sizeof(iteratorCol)); if (!iterCols) { *status = MEMORY_ALLOCATION; goto cleanup; } numAllocCols += parsers[ii].nCols; for (jj = 0; jj < parsers[ii].nCols; jj++) iterCols[startCol++] = parsers[ii].colData[jj]; } else { /* Just a "regular" column name, we already have enough allocated for these */ fits_iter_set_by_num(&(iterCols[startCol]), fptr, colnum[ii], TDOUBLE, InputCol); startCol ++; } /* Check that all the vector dimensions agree */ if (repeat == 0) { repeat = colrepeat; } else { if (repeat != colrepeat) { ffpmsg("vector dimensions of binning values do not agree"); *status = BAD_DIMEN; goto cleanup; } } } /* End of loop over columns */ /* Now initialize the iterator column data for the weighting */ if (wtexpr && wtexpr[0] && weight == DOUBLENULLVALUE) { int wtdatatype, wtnaxis; long wtnaxes[MAXDIMS]; int jj; histData.startCols[4] = startCol; ffiprs( fptr, 0, wtexpr, MAXDIMS, &wtdatatype, &wtrepeat, &wtnaxis, wtnaxes, &(parsers[4]), status ); if (*status) goto cleanup; if (wtrepeat < 0) wtrepeat = 1; /* If it's a constant expression */ /* Set up the parser data for evaluation to a TemporaryCol */ /* It's a weighting expression, set that up and ... */ fits_get_num_rows(fptr, &nrows, status); if (fits_parser_set_temporary_col(&(parsers[4]), &(infos[4]), nrows, (void *) &(double_nulval), status)) goto cleanup; /* Copy iterator columns from the parser to the master iterator columns */ iterCols = fits_recalloc(iterCols, numAllocCols, numAllocCols+parsers[4].nCols, sizeof(iteratorCol)); if (!iterCols) { *status = MEMORY_ALLOCATION; goto cleanup; } numAllocCols += parsers[ii].nCols; for (jj = 0; jj < parsers[4].nCols; jj++) iterCols[startCol++] = parsers[4].colData[jj]; } else if (weight == DOUBLENULLVALUE) { int wtdatatype; /* It's a "regular" weighting column */ fits_get_eqcoltype(fptr, wtcolnum, &wtdatatype, &wtrepeat, NULL, status); histData.startCols[4] = startCol; fits_iter_set_by_num(&(iterCols[startCol]), fptr, wtcolnum, TDOUBLE, InputCol); startCol ++; } else { /* In case of explicit numerical value, we can just use that number in the vector expression, so the vector repeat of the weighting can be set to that of the input */ wtrepeat = repeat; } /* Vector dimension of weighting must agree with binning */ if (wtrepeat != 0 && repeat != 0 && wtrepeat != repeat) { ffpmsg("vector dimensions of weights do not agree with bins"); *status = BAD_DIMEN; goto cleanup; } /* We now know he number of iterator columns */ numIterCols = startCol; /* Fill in iterator information for the parser*/ histData.numIterCols = numIterCols; histData.iterCols = iterCols; histData.parsers = parsers; histData.infos = infos; histData.repeat = repeat; /* Set global variables with histogram parameter values. */ /* Use separate scalar variables rather than arrays because */ /* it is more efficient when computing the histogram. */ histData.hcolnum[0] = colnum[0]; histData.amin1 = tmin[0]; histData.maxbin1 = maxbin[0]; histData.binsize1 = tbin[0]; histData.haxis1 = (long) taxes[0]; histData.incr[0] = 1; if (histData.haxis > 1) { histData.hcolnum[1] = colnum[1]; histData.amin2 = tmin[1]; histData.maxbin2 = maxbin[1]; histData.binsize2 = tbin[1]; histData.haxis2 = (long) taxes[1]; histData.incr[1] = histData.incr[0] * histData.haxis1; if (histData.haxis > 2) { histData.hcolnum[2] = colnum[2]; histData.amin3 = tmin[2]; histData.maxbin3 = maxbin[2]; histData.binsize3 = tbin[2]; histData.haxis3 = (long) taxes[2]; histData.incr[2] = histData.incr[1] * histData.haxis2; if (histData.haxis > 3) { histData.hcolnum[3] = colnum[3]; histData.amin4 = tmin[3]; histData.maxbin4 = maxbin[3]; histData.binsize4 = tbin[3]; histData.haxis4 = (long) taxes[3]; histData.incr[3] = histData.incr[2] * histData.haxis3; } } } /* define parameters of image for the iterator function */ fits_iter_set_file(imagepars, histptr); /* pointer to image */ fits_iter_set_datatype(imagepars, imagetype); /* image datatype */ fits_iter_set_iotype(imagepars, OutputCol); /* image is output */ /* call the iterator function to write out the histogram image */ fits_iterate_data(n_cols, imagepars, offset, n_per_loop, ffwritehisto, (void*)&histData, status); cleanup: /* Free any allocated memory ... */ if (iterCols) free(iterCols); /* ... and parsers */ for (ii = 0; ii <= 4; ii ++) { if (parsers[ii].nCols > 0) ffcprs(&(parsers[ii])); } return(*status); } /* Double-precision version, non-extended syntax */ int fits_make_histd(fitsfile *fptr, /* IO - pointer to table with X and Y cols; */ fitsfile *histptr, /* I - pointer to output FITS image */ int bitpix, /* I - datatype for image: 16, 32, -32, etc */ int naxis, /* I - number of axes in the histogram image */ long *naxes, /* I - size of axes in the histogram image */ int *colnum, /* I - column numbers (array length = naxis) */ double *amin, /* I - minimum histogram value, for each axis */ double *amax, /* I - maximum histogram value, for each axis */ double *binsize, /* I - bin size along each axis */ double weight, /* I - binning weighting factor */ int wtcolnum, /* I - optional keyword or col for weight*/ int recip, /* I - use reciprocal of the weight? */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will*/ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow*/ /* is equal to NULL. */ int *status) { return fits_make_histde(fptr, histptr, 0, bitpix, naxis, naxes, colnum, 0, amin, amax, binsize, weight, wtcolnum, 0, recip, selectrow, status); } /*--------------------------------------------------------------------------*/ int fits_get_col_minmax(fitsfile *fptr, int colnum, double *datamin, double *datamax, int *status) /* Simple utility routine to compute the min and max value in a column */ { int anynul; long nrows, ntodo, firstrow, ii; double array[1000], nulval; ffgky(fptr, TLONG, "NAXIS2", &nrows, NULL, status); /* no. of rows */ firstrow = 1; nulval = DOUBLENULLVALUE; *datamin = 9.0E36; *datamax = -9.0E36; while(nrows) { ntodo = minvalue(nrows, 100); ffgcv(fptr, TDOUBLE, colnum, firstrow, 1, ntodo, &nulval, array, &anynul, status); for (ii = 0; ii < ntodo; ii++) { if (array[ii] != nulval) { *datamin = minvalue(*datamin, array[ii]); *datamax = maxvalue(*datamax, array[ii]); } } nrows -= ntodo; firstrow += ntodo; } return(*status); } struct histo_minmax_workfn_struct { parseInfo *Info; double datamin, datamax; long ntotal, ngood; }; /*---------------------------------------------------------------------------*/ static int histo_minmax_expr_workfn( long totalrows, /* I - Total rows to be processed */ long offset, /* I - Number of rows skipped at start*/ long firstrow, /* I - First row of this iteration */ long nrows, /* I - Number of rows in this iter */ int nCols, /* I - Number of columns in use */ iteratorCol *colData, /* IO- Column information/data */ void *userPtr ) /* I - Data handling instructions */ /* */ /* Iterator work function which evaluates a parser result and computes */ /* min max value */ /*---------------------------------------------------------------------------*/ { int status = 0; long i; double *data; double nulval; struct histo_minmax_workfn_struct *wf = ((struct histo_minmax_workfn_struct *)userPtr); struct ParseStatusVariables *pv = &(wf->Info->parseVariables); iteratorCol *outcol = &(colData[nCols-1]); /* Call calculator work function. Result is put in final column of colData as a TemporaryCol */ status = fits_parser_workfn(totalrows, offset, firstrow, nrows, nCols, colData, (void *) wf->Info); /* The result of the calculation is in pv->Data, and null value in pv->Null */ data = (double *)(outcol->array); nulval = *((double *)(wf->Info->nullPtr)); for (i = 1; i<=(nrows*pv->repeat); i++ ) { /* Note that data[0] == 0 indicates no null values at all!!! */ if (data[0] == 0 || data[i] != nulval) { if (data[i] < wf->datamin || wf->datamin == DOUBLENULLVALUE) wf->datamin = data[i]; if (data[i] > wf->datamax || wf->datamax == DOUBLENULLVALUE) wf->datamax = data[i]; wf->ngood ++; } wf->ntotal ++; } return status; } /*--------------------------------------------------------------------------*/ int fits_get_expr_minmax(fitsfile *fptr, char *expr, double *datamin, double *datamax, int *datatype, int *status) /* Simple utility routine to compute the min and max value in an expression */ { parseInfo Info; ParseData lParse; struct histo_minmax_workfn_struct minmaxWorkFn; int naxis, constant, typecode, newNullKwd=0; long nelem, naxes[MAXDIMS], repeat, width, nrows; int col_cnt, colNo; Node *result; char card[81], tform[16], nullKwd[9], tdimKwd[9]; double double_nulval = DOUBLENULLVALUE; if( *status ) return( *status ); memset(&minmaxWorkFn, 0, sizeof(minmaxWorkFn)); memset(&Info, 0, sizeof(Info)); memset(&lParse, 0, sizeof(lParse)); if (datatype) *datatype = 0; ffgky(fptr, TLONG, "NAXIS2", &nrows, NULL, status); /* no. of rows */ if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, &lParse, status ) ) { ffcprs(&lParse); return( *status ); } if (datatype) *datatype = Info.datatype; if( nelem<0 ) { /* Constant already computed */ result = lParse.Nodes + lParse.resultNode; switch( Info.datatype ) { case TDOUBLE: *datamin = *datamax = result->value.data.dbl; break; case TLONG: *datamin = *datamax = (double) result->value.data.lng; break; case TLOGICAL:*datamin = *datamax = (double) ((result->value.data.log == 1)?1:0); break; case TBIT: *datamin = *datamax = (double) ((result->value.data.str[0])?1:0); break; } ffcprs(&lParse); return( *status ); } Info.parseData = &lParse; /* Add a temporary column which contains the expression value */ if ( fits_parser_set_temporary_col( &lParse, &Info, nrows, &double_nulval, status) ) { ffcprs(&lParse); return( *status ); } /* Initialize the work function computing min/max */ minmaxWorkFn.Info = &Info; minmaxWorkFn.datamin = minmaxWorkFn.datamax = DOUBLENULLVALUE; minmaxWorkFn.ntotal = minmaxWorkFn.ngood = 0; if( ffiter( lParse.nCols, lParse.colData, 0, 0, histo_minmax_expr_workfn, (void*)&minmaxWorkFn, status ) == -1 ) *status = 0; /* -1 indicates exitted without error before end... OK */ if (datamin) *datamin = minmaxWorkFn.datamin; if (datamax) *datamax = minmaxWorkFn.datamax; ffcprs(&lParse); return(*status); } /*--------------------------------------------------------------------------*/ int ffwritehisto(long totaln, long pixoffset, long firstn, long nvalues, int narrays, iteratorCol *imagepars, void *userPointer) /* Interator work function that writes out the histogram. The histogram values are calculated by another work function, ffcalchisto. This work function only gets called once, and totaln = nvalues. */ { iteratorCol *colpars; int ii, status = 0, ncols; long rows_per_loop = 0, offset = 0; histType *histData; histData = (histType *)userPointer; /* store pointer to the histogram array, and initialize to zero */ switch( histData->himagetype ) { case TBYTE: histData->hist.b = (char * ) fits_iter_get_array(imagepars); break; case TSHORT: histData->hist.i = (short * ) fits_iter_get_array(imagepars); break; case TINT: histData->hist.j = (int * ) fits_iter_get_array(imagepars); break; case TFLOAT: histData->hist.r = (float * ) fits_iter_get_array(imagepars); break; case TDOUBLE: histData->hist.d = (double *) fits_iter_get_array(imagepars); break; } /* call iterator function to calc the histogram pixel values */ /* must lock this call in multithreaded environoments because */ /* the ffcalchist work routine uses static vaiables that would */ /* get clobbered if multiple threads were running at the same time */ fits_iterate_data(histData->numIterCols, histData->iterCols, offset, rows_per_loop, ffcalchist, (void*)histData, &status); return(status); } /*--------------------------------------------------------------------------*/ int ffcalchist(long totalrows, long offset, long firstrow, long nrows, int ncols, iteratorCol *colpars, void *userPointer) /* Interator work function that calculates values for the 2D histogram. */ { long ii, ipix, iaxisbin; double pix, axisbin; char *rowselect; histType *histData = (histType*)userPointer; double *colptr[MAXDIMS] = {0}; int status = 0; long irow; if (firstrow == 1) { histData->rowselector_cur = histData->rowselector; } rowselect = histData->rowselector_cur; for (ii=0; ii<=4; ii++) { int startCol = histData->startCols[ii]; iteratorCol *outcol = 0; /* Call calculator work function. Result is put in final column of colData as a TemporaryCol */ colptr[ii] = 0; /* Do not process unspecified axes (but do process weight column) */ if ( (ii >= histData->haxis && ii != 4) || histData->startCols[ii] < 0) continue; /* We have a parser for this, evaluate it */ if (histData->parsers[ii].nCols > 0) { struct ParseStatusVariables *pv = &(histData->infos[ii].parseVariables); iteratorCol *colData = &(histData->iterCols[startCol]); int nCols = histData->parsers[ii].nCols; status = fits_parser_workfn(totalrows, offset, firstrow, nrows, nCols, colData, (void *) &(histData->infos[ii])); if (status) return status; /* Output column is last iterator column, which better be a TemporaryCol */ outcol = &(colData[nCols-1]); } else { outcol = &(histData->iterCols[startCol]); } if (outcol) { /* Note that the 0th array element returned by the iterator is actually the null value! This is actually rather a big undocumented "feature" of the iterator. However, "ii" below starts at a value of 1 which skips over the null value */ colptr[ii] = ((double *) fits_iter_get_array(outcol)); } } /* Main loop over rows */ /* irow = row counter (1 .. nrows) */ /* elem = counter of element (1 .. histData->repeat) for each row */ /* ii = counts up from 1 (see note below) used to index colptr[]'s */ /* Note that ii starts at 1 because position [0] in the column data arrays is for the "null" value! */ for (ii = 1, irow = 1; irow <= nrows; irow++) { long elem; if (rowselect) { /* if a row selector array is supplied... */ if (*rowselect) { rowselect++; /* this row is included in the histogram */ } else { rowselect++; /* this row is excluded from the histogram */ ii += histData->repeat; /* skip this portion of data */ continue; } } /* Loop over elements in each row, increment ii after each element */ for (elem = 1; elem <= histData->repeat; elem++, ii++) { if (colptr[0][ii] == DOUBLENULLVALUE) /* test for null value */ continue; if (colptr[4] && colptr[4][ii] == DOUBLENULLVALUE) /* and null weight */ continue; pix = (colptr[0][ii] - histData->amin1) / histData->binsize1; ipix = (long) (pix + 1.); /* add 1 because the 1st pixel is the null value */ /* test if bin is within range */ if (ipix < 1 || ipix > histData->haxis1 || pix > histData->maxbin1) continue; if (histData->haxis > 1) { if (colptr[1][ii] == DOUBLENULLVALUE) continue; axisbin = (colptr[1][ii] - histData->amin2) / histData->binsize2; iaxisbin = (long) axisbin; if (axisbin < 0. || iaxisbin >= histData->haxis2 || axisbin > histData->maxbin2) continue; ipix += (iaxisbin * histData->incr[1]); if (histData->haxis > 2) { if (colptr[2][ii] == DOUBLENULLVALUE) continue; axisbin = (colptr[2][ii] - histData->amin3) / histData->binsize3; iaxisbin = (long) axisbin; if (axisbin < 0. || iaxisbin >= histData->haxis3 || axisbin > histData->maxbin3) continue; ipix += (iaxisbin * histData->incr[2]); if (histData->haxis > 3) { if (colptr[3][ii] == DOUBLENULLVALUE) continue; axisbin = (colptr[3][ii] - histData->amin4) / histData->binsize4; iaxisbin = (long) axisbin; if (axisbin < 0. || iaxisbin >= histData->haxis4 || axisbin > histData->maxbin4) continue; ipix += (iaxisbin * histData->incr[3]); } /* end of haxis > 3 case */ } /* end of haxis > 2 case */ } /* end of haxis > 1 case */ /* increment the histogram pixel */ if (histData->weight != DOUBLENULLVALUE) /* constant weight factor */ { /* Note that if wtrecip == 1, the reciprocal was precomputed above */ if (histData->himagetype == TINT) histData->hist.j[ipix] += (int) histData->weight; else if (histData->himagetype == TSHORT) histData->hist.i[ipix] += (short) histData->weight; else if (histData->himagetype == TFLOAT) histData->hist.r[ipix] += histData->weight; else if (histData->himagetype == TDOUBLE) histData->hist.d[ipix] += histData->weight; else if (histData->himagetype == TBYTE) histData->hist.b[ipix] += (char) histData->weight; } else if (histData->wtrecip) /* use reciprocal of the weight */ { if (histData->himagetype == TINT) histData->hist.j[ipix] += (int) (1./colptr[4][ii]); else if (histData->himagetype == TSHORT) histData->hist.i[ipix] += (short) (1./colptr[4][ii]); else if (histData->himagetype == TFLOAT) histData->hist.r[ipix] += (float) (1./colptr[4][ii]); else if (histData->himagetype == TDOUBLE) histData->hist.d[ipix] += 1./colptr[4][ii]; else if (histData->himagetype == TBYTE) histData->hist.b[ipix] += (char) (1./colptr[4][ii]); } else /* no weights */ { if (histData->himagetype == TINT) histData->hist.j[ipix] += (int) colptr[4][ii]; else if (histData->himagetype == TSHORT) histData->hist.i[ipix] += (short) colptr[4][ii]; else if (histData->himagetype == TFLOAT) histData->hist.r[ipix] += colptr[4][ii]; else if (histData->himagetype == TDOUBLE) histData->hist.d[ipix] += colptr[4][ii]; else if (histData->himagetype == TBYTE) histData->hist.b[ipix] += (char) colptr[4][ii]; } } /* end of loop over elements per row */ } /* end of main loop over all rows */ histData->rowselector_cur = rowselect; /* Save row pointer for next go-round */ return(status); } cfitsio-4.3.1/longnam.h0000644000225700000360000005273014456514035014267 0ustar cagordonlhea#ifndef _LONGNAME_H #define _LONGNAME_H #define fits_parse_input_url ffiurl #define fits_parse_input_filename ffifile #define fits_parse_rootname ffrtnm #define fits_file_exists ffexist #define fits_parse_output_url ffourl #define fits_parse_extspec ffexts #define fits_parse_extnum ffextn #define fits_parse_binspec ffbins #define fits_parse_binrange ffbinr #define fits_parse_range ffrwrg #define fits_parse_rangell ffrwrgll #define fits_open_memfile ffomem /* use the following special macro to test that the fitsio.h include file that was used to build the CFITSIO library is compatible with the version as included when compiling the application program */ #define fits_open_file(A, B, C, D) ffopentest( CFITSIO_SONAME, A, B, C, D) #define fits_open_data ffdopn #define fits_open_extlist ffeopn #define fits_open_table fftopn #define fits_open_image ffiopn #define fits_open_diskfile ffdkopn #define fits_reopen_file ffreopen #define fits_create_file ffinit #define fits_create_diskfile ffdkinit #define fits_create_memfile ffimem #define fits_create_template fftplt #define fits_flush_file ffflus #define fits_flush_buffer ffflsh #define fits_close_file ffclos #define fits_delete_file ffdelt #define fits_file_name ffflnm #define fits_file_mode ffflmd #define fits_url_type ffurlt #define fits_get_version ffvers #define fits_uppercase ffupch #define fits_get_errstatus ffgerr #define fits_write_errmsg ffpmsg #define fits_write_errmark ffpmrk #define fits_read_errmsg ffgmsg #define fits_clear_errmsg ffcmsg #define fits_clear_errmark ffcmrk #define fits_report_error ffrprt #define fits_compare_str ffcmps #define fits_test_keyword fftkey #define fits_test_record fftrec #define fits_null_check ffnchk #define fits_make_keyn ffkeyn #define fits_make_nkey ffnkey #define fits_make_key ffmkky #define fits_get_keyclass ffgkcl #define fits_get_keytype ffdtyp #define fits_get_inttype ffinttyp #define fits_parse_value ffpsvc #define fits_get_keyname ffgknm #define fits_parse_template ffgthd #define fits_ascii_tform ffasfm #define fits_binary_tform ffbnfm #define fits_binary_tformll ffbnfmll #define fits_get_tbcol ffgabc #define fits_get_rowsize ffgrsz #define fits_get_col_display_width ffgcdw #define fits_write_record ffprec #define fits_write_key ffpky #define fits_write_key_unit ffpunt #define fits_write_comment ffpcom #define fits_write_history ffphis #define fits_write_date ffpdat #define fits_get_system_time ffgstm #define fits_get_system_date ffgsdt #define fits_date2str ffdt2s #define fits_time2str fftm2s #define fits_str2date ffs2dt #define fits_str2time ffs2tm #define fits_write_key_longstr ffpkls #define fits_write_key_longwarn ffplsw #define fits_write_key_null ffpkyu #define fits_write_key_str ffpkys #define fits_write_key_log ffpkyl #define fits_write_key_lng ffpkyj #define fits_write_key_ulng ffpkyuj #define fits_write_key_fixflt ffpkyf #define fits_write_key_flt ffpkye #define fits_write_key_fixdbl ffpkyg #define fits_write_key_dbl ffpkyd #define fits_write_key_fixcmp ffpkfc #define fits_write_key_cmp ffpkyc #define fits_write_key_fixdblcmp ffpkfm #define fits_write_key_dblcmp ffpkym #define fits_write_key_triple ffpkyt #define fits_write_tdim ffptdm #define fits_write_tdimll ffptdmll #define fits_write_keys_str ffpkns #define fits_write_keys_log ffpknl #define fits_write_keys_lng ffpknj #define fits_write_keys_fixflt ffpknf #define fits_write_keys_flt ffpkne #define fits_write_keys_fixdbl ffpkng #define fits_write_keys_dbl ffpknd #define fits_copy_key ffcpky #define fits_write_imghdr ffphps #define fits_write_imghdrll ffphpsll #define fits_write_grphdr ffphpr #define fits_write_grphdrll ffphprll #define fits_write_atblhdr ffphtb #define fits_write_btblhdr ffphbn #define fits_write_exthdr ffphext #define fits_write_key_template ffpktp #define fits_get_hdrspace ffghsp #define fits_get_hdrpos ffghps #define fits_movabs_key ffmaky #define fits_movrel_key ffmrky #define fits_find_nextkey ffgnxk #define fits_read_record ffgrec #define fits_read_card ffgcrd #define fits_read_str ffgstr #define fits_read_key_unit ffgunt #define fits_read_keyn ffgkyn #define fits_read_key ffgky #define fits_read_keyword ffgkey #define fits_read_key_str ffgkys #define fits_read_key_log ffgkyl #define fits_read_key_lng ffgkyj #define fits_read_key_lnglng ffgkyjj #define fits_read_key_ulnglng ffgkyujj #define fits_read_key_flt ffgkye #define fits_read_key_dbl ffgkyd #define fits_read_key_cmp ffgkyc #define fits_read_key_dblcmp ffgkym #define fits_read_key_triple ffgkyt #define fits_get_key_strlen ffgksl #define fits_get_key_com_strlen ffgkcsl #define fits_read_key_longstr ffgkls #define fits_read_string_key ffgsky #define fits_read_string_key_com ffgskyc #define fits_free_memory fffree #define fits_read_tdim ffgtdm #define fits_read_tdimll ffgtdmll #define fits_decode_tdim ffdtdm #define fits_decode_tdimll ffdtdmll #define fits_read_keys_str ffgkns #define fits_read_keys_log ffgknl #define fits_read_keys_lng ffgknj #define fits_read_keys_lnglng ffgknjj #define fits_read_keys_flt ffgkne #define fits_read_keys_dbl ffgknd #define fits_read_imghdr ffghpr #define fits_read_imghdrll ffghprll #define fits_read_atblhdr ffghtb #define fits_read_btblhdr ffghbn #define fits_read_atblhdrll ffghtbll #define fits_read_btblhdrll ffghbnll #define fits_hdr2str ffhdr2str #define fits_convert_hdr2str ffcnvthdr2str #define fits_update_card ffucrd #define fits_update_key ffuky #define fits_update_key_null ffukyu #define fits_update_key_str ffukys #define fits_update_key_longstr ffukls #define fits_update_key_log ffukyl #define fits_update_key_lng ffukyj #define fits_update_key_fixflt ffukyf #define fits_update_key_flt ffukye #define fits_update_key_fixdbl ffukyg #define fits_update_key_dbl ffukyd #define fits_update_key_fixcmp ffukfc #define fits_update_key_cmp ffukyc #define fits_update_key_fixdblcmp ffukfm #define fits_update_key_dblcmp ffukym #define fits_modify_record ffmrec #define fits_modify_card ffmcrd #define fits_modify_name ffmnam #define fits_modify_comment ffmcom #define fits_modify_key_null ffmkyu #define fits_modify_key_str ffmkys #define fits_modify_key_longstr ffmkls #define fits_modify_key_log ffmkyl #define fits_modify_key_lng ffmkyj #define fits_modify_key_fixflt ffmkyf #define fits_modify_key_flt ffmkye #define fits_modify_key_fixdbl ffmkyg #define fits_modify_key_dbl ffmkyd #define fits_modify_key_fixcmp ffmkfc #define fits_modify_key_cmp ffmkyc #define fits_modify_key_fixdblcmp ffmkfm #define fits_modify_key_dblcmp ffmkym #define fits_insert_record ffirec #define fits_insert_card ffikey #define fits_insert_key_null ffikyu #define fits_insert_key_str ffikys #define fits_insert_key_longstr ffikls #define fits_insert_key_log ffikyl #define fits_insert_key_lng ffikyj #define fits_insert_key_fixflt ffikyf #define fits_insert_key_flt ffikye #define fits_insert_key_fixdbl ffikyg #define fits_insert_key_dbl ffikyd #define fits_insert_key_fixcmp ffikfc #define fits_insert_key_cmp ffikyc #define fits_insert_key_fixdblcmp ffikfm #define fits_insert_key_dblcmp ffikym #define fits_delete_key ffdkey #define fits_delete_str ffdstr #define fits_delete_record ffdrec #define fits_get_hdu_num ffghdn #define fits_get_hdu_type ffghdt #define fits_get_hduaddr ffghad #define fits_get_hduaddrll ffghadll #define fits_get_hduoff ffghof #define fits_get_img_param ffgipr #define fits_get_img_paramll ffgiprll #define fits_get_img_type ffgidt #define fits_get_img_equivtype ffgiet #define fits_get_img_dim ffgidm #define fits_get_img_size ffgisz #define fits_get_img_sizell ffgiszll #define fits_movabs_hdu ffmahd #define fits_movrel_hdu ffmrhd #define fits_movnam_hdu ffmnhd #define fits_get_num_hdus ffthdu #define fits_create_img ffcrim #define fits_create_imgll ffcrimll #define fits_create_tbl ffcrtb #define fits_create_hdu ffcrhd #define fits_insert_img ffiimg #define fits_insert_imgll ffiimgll #define fits_insert_atbl ffitab #define fits_insert_btbl ffibin #define fits_resize_img ffrsim #define fits_resize_imgll ffrsimll #define fits_delete_hdu ffdhdu #define fits_copy_hdu ffcopy #define fits_copy_file ffcpfl #define fits_copy_header ffcphd #define fits_copy_hdutab ffcpht #define fits_copy_data ffcpdt #define fits_write_hdu ffwrhdu #define fits_set_hdustruc ffrdef #define fits_set_hdrsize ffhdef #define fits_write_theap ffpthp #define fits_encode_chksum ffesum #define fits_decode_chksum ffdsum #define fits_write_chksum ffpcks #define fits_update_chksum ffupck #define fits_verify_chksum ffvcks #define fits_get_chksum ffgcks #define fits_set_bscale ffpscl #define fits_set_tscale fftscl #define fits_set_imgnull ffpnul #define fits_set_btblnull fftnul #define fits_set_atblnull ffsnul #define fits_get_colnum ffgcno #define fits_get_colname ffgcnn #define fits_get_coltype ffgtcl #define fits_get_coltypell ffgtclll #define fits_get_eqcoltype ffeqty #define fits_get_eqcoltypell ffeqtyll #define fits_get_num_rows ffgnrw #define fits_get_num_rowsll ffgnrwll #define fits_get_num_cols ffgncl #define fits_get_acolparms ffgacl #define fits_get_bcolparms ffgbcl #define fits_get_bcolparmsll ffgbclll #define fits_iterate_data ffiter #define fits_read_grppar_byt ffggpb #define fits_read_grppar_sbyt ffggpsb #define fits_read_grppar_usht ffggpui #define fits_read_grppar_ulng ffggpuj #define fits_read_grppar_ulnglng ffggpujj #define fits_read_grppar_sht ffggpi #define fits_read_grppar_lng ffggpj #define fits_read_grppar_lnglng ffggpjj #define fits_read_grppar_int ffggpk #define fits_read_grppar_uint ffggpuk #define fits_read_grppar_flt ffggpe #define fits_read_grppar_dbl ffggpd #define fits_read_pix ffgpxv #define fits_read_pixll ffgpxvll #define fits_read_pixnull ffgpxf #define fits_read_pixnullll ffgpxfll #define fits_read_img ffgpv #define fits_read_imgnull ffgpf #define fits_read_img_byt ffgpvb #define fits_read_img_sbyt ffgpvsb #define fits_read_img_usht ffgpvui #define fits_read_img_ulng ffgpvuj #define fits_read_img_sht ffgpvi #define fits_read_img_lng ffgpvj #define fits_read_img_ulnglng ffgpvujj #define fits_read_img_lnglng ffgpvjj #define fits_read_img_uint ffgpvuk #define fits_read_img_int ffgpvk #define fits_read_img_flt ffgpve #define fits_read_img_dbl ffgpvd #define fits_read_imgnull_byt ffgpfb #define fits_read_imgnull_sbyt ffgpfsb #define fits_read_imgnull_usht ffgpfui #define fits_read_imgnull_ulng ffgpfuj #define fits_read_imgnull_sht ffgpfi #define fits_read_imgnull_lng ffgpfj #define fits_read_imgnull_ulnglng ffgpfujj #define fits_read_imgnull_lnglng ffgpfjj #define fits_read_imgnull_uint ffgpfuk #define fits_read_imgnull_int ffgpfk #define fits_read_imgnull_flt ffgpfe #define fits_read_imgnull_dbl ffgpfd #define fits_read_2d_byt ffg2db #define fits_read_2d_sbyt ffg2dsb #define fits_read_2d_usht ffg2dui #define fits_read_2d_ulng ffg2duj #define fits_read_2d_sht ffg2di #define fits_read_2d_lng ffg2dj #define fits_read_2d_ulnglng ffg2dujj #define fits_read_2d_lnglng ffg2djj #define fits_read_2d_uint ffg2duk #define fits_read_2d_int ffg2dk #define fits_read_2d_flt ffg2de #define fits_read_2d_dbl ffg2dd #define fits_read_3d_byt ffg3db #define fits_read_3d_sbyt ffg3dsb #define fits_read_3d_usht ffg3dui #define fits_read_3d_ulng ffg3duj #define fits_read_3d_sht ffg3di #define fits_read_3d_lng ffg3dj #define fits_read_3d_ulnglng ffg3dujj #define fits_read_3d_lnglng ffg3djj #define fits_read_3d_uint ffg3duk #define fits_read_3d_int ffg3dk #define fits_read_3d_flt ffg3de #define fits_read_3d_dbl ffg3dd #define fits_read_subset ffgsv #define fits_read_subset_byt ffgsvb #define fits_read_subset_sbyt ffgsvsb #define fits_read_subset_usht ffgsvui #define fits_read_subset_ulng ffgsvuj #define fits_read_subset_sht ffgsvi #define fits_read_subset_lng ffgsvj #define fits_read_subset_ulnglng ffgsvujj #define fits_read_subset_lnglng ffgsvjj #define fits_read_subset_uint ffgsvuk #define fits_read_subset_int ffgsvk #define fits_read_subset_flt ffgsve #define fits_read_subset_dbl ffgsvd #define fits_read_subsetnull_byt ffgsfb #define fits_read_subsetnull_sbyt ffgsfsb #define fits_read_subsetnull_usht ffgsfui #define fits_read_subsetnull_ulng ffgsfuj #define fits_read_subsetnull_sht ffgsfi #define fits_read_subsetnull_lng ffgsfj #define fits_read_subsetnull_ulnglng ffgsfujj #define fits_read_subsetnull_lnglng ffgsfjj #define fits_read_subsetnull_uint ffgsfuk #define fits_read_subsetnull_int ffgsfk #define fits_read_subsetnull_flt ffgsfe #define fits_read_subsetnull_dbl ffgsfd #define ffcpimg fits_copy_image_section #define fits_compress_img fits_comp_img #define fits_decompress_img fits_decomp_img #define fits_read_col ffgcv #define fits_read_cols ffgcvn #define fits_read_colnull ffgcf #define fits_read_col_str ffgcvs #define fits_read_col_log ffgcvl #define fits_read_col_byt ffgcvb #define fits_read_col_sbyt ffgcvsb #define fits_read_col_usht ffgcvui #define fits_read_col_ulng ffgcvuj #define fits_read_col_sht ffgcvi #define fits_read_col_lng ffgcvj #define fits_read_col_ulnglng ffgcvujj #define fits_read_col_lnglng ffgcvjj #define fits_read_col_uint ffgcvuk #define fits_read_col_int ffgcvk #define fits_read_col_flt ffgcve #define fits_read_col_dbl ffgcvd #define fits_read_col_cmp ffgcvc #define fits_read_col_dblcmp ffgcvm #define fits_read_col_bit ffgcx #define fits_read_col_bit_usht ffgcxui #define fits_read_col_bit_uint ffgcxuk #define fits_read_colnull_str ffgcfs #define fits_read_colnull_log ffgcfl #define fits_read_colnull_byt ffgcfb #define fits_read_colnull_sbyt ffgcfsb #define fits_read_colnull_usht ffgcfui #define fits_read_colnull_ulng ffgcfuj #define fits_read_colnull_sht ffgcfi #define fits_read_colnull_lng ffgcfj #define fits_read_colnull_ulnglng ffgcfujj #define fits_read_colnull_lnglng ffgcfjj #define fits_read_colnull_uint ffgcfuk #define fits_read_colnull_int ffgcfk #define fits_read_colnull_flt ffgcfe #define fits_read_colnull_dbl ffgcfd #define fits_read_colnull_cmp ffgcfc #define fits_read_colnull_dblcmp ffgcfm #define fits_read_descript ffgdes #define fits_read_descriptll ffgdesll #define fits_read_descripts ffgdess #define fits_read_descriptsll ffgdessll #define fits_read_tblbytes ffgtbb #define fits_write_grppar_byt ffpgpb #define fits_write_grppar_sbyt ffpgpsb #define fits_write_grppar_usht ffpgpui #define fits_write_grppar_ulng ffpgpuj #define fits_write_grppar_sht ffpgpi #define fits_write_grppar_lng ffpgpj #define fits_write_grppar_ulnglng ffpgpujj #define fits_write_grppar_lnglng ffpgpjj #define fits_write_grppar_uint ffpgpuk #define fits_write_grppar_int ffpgpk #define fits_write_grppar_flt ffpgpe #define fits_write_grppar_dbl ffpgpd #define fits_write_pix ffppx #define fits_write_pixll ffppxll #define fits_write_pixnull ffppxn #define fits_write_pixnullll ffppxnll #define fits_write_img ffppr #define fits_write_img_byt ffpprb #define fits_write_img_sbyt ffpprsb #define fits_write_img_usht ffpprui #define fits_write_img_ulng ffppruj #define fits_write_img_sht ffppri #define fits_write_img_lng ffpprj #define fits_write_img_ulnglng ffpprujj #define fits_write_img_lnglng ffpprjj #define fits_write_img_uint ffppruk #define fits_write_img_int ffpprk #define fits_write_img_flt ffppre #define fits_write_img_dbl ffpprd #define fits_write_imgnull ffppn #define fits_write_imgnull_byt ffppnb #define fits_write_imgnull_sbyt ffppnsb #define fits_write_imgnull_usht ffppnui #define fits_write_imgnull_ulng ffppnuj #define fits_write_imgnull_sht ffppni #define fits_write_imgnull_lng ffppnj #define fits_write_imgnull_ulnglng ffppnujj #define fits_write_imgnull_lnglng ffppnjj #define fits_write_imgnull_uint ffppnuk #define fits_write_imgnull_int ffppnk #define fits_write_imgnull_flt ffppne #define fits_write_imgnull_dbl ffppnd #define fits_write_img_null ffppru #define fits_write_null_img ffpprn #define fits_write_2d_byt ffp2db #define fits_write_2d_sbyt ffp2dsb #define fits_write_2d_usht ffp2dui #define fits_write_2d_ulng ffp2duj #define fits_write_2d_sht ffp2di #define fits_write_2d_lng ffp2dj #define fits_write_2d_ulnglng ffp2dujj #define fits_write_2d_lnglng ffp2djj #define fits_write_2d_uint ffp2duk #define fits_write_2d_int ffp2dk #define fits_write_2d_flt ffp2de #define fits_write_2d_dbl ffp2dd #define fits_write_3d_byt ffp3db #define fits_write_3d_sbyt ffp3dsb #define fits_write_3d_usht ffp3dui #define fits_write_3d_ulng ffp3duj #define fits_write_3d_sht ffp3di #define fits_write_3d_lng ffp3dj #define fits_write_3d_ulnglng ffp3dujj #define fits_write_3d_lnglng ffp3djj #define fits_write_3d_uint ffp3duk #define fits_write_3d_int ffp3dk #define fits_write_3d_flt ffp3de #define fits_write_3d_dbl ffp3dd #define fits_write_subset ffpss #define fits_write_subset_byt ffpssb #define fits_write_subset_sbyt ffpsssb #define fits_write_subset_usht ffpssui #define fits_write_subset_ulng ffpssuj #define fits_write_subset_sht ffpssi #define fits_write_subset_lng ffpssj #define fits_write_subset_ulnglng ffpssujj #define fits_write_subset_lnglng ffpssjj #define fits_write_subset_uint ffpssuk #define fits_write_subset_int ffpssk #define fits_write_subset_flt ffpsse #define fits_write_subset_dbl ffpssd #define fits_write_col ffpcl #define fits_write_cols ffpcln #define fits_write_col_str ffpcls #define fits_write_col_log ffpcll #define fits_write_col_byt ffpclb #define fits_write_col_sbyt ffpclsb #define fits_write_col_usht ffpclui #define fits_write_col_ulng ffpcluj #define fits_write_col_sht ffpcli #define fits_write_col_lng ffpclj #define fits_write_col_ulnglng ffpclujj #define fits_write_col_lnglng ffpcljj #define fits_write_col_uint ffpcluk #define fits_write_col_int ffpclk #define fits_write_col_flt ffpcle #define fits_write_col_dbl ffpcld #define fits_write_col_cmp ffpclc #define fits_write_col_dblcmp ffpclm #define fits_write_col_null ffpclu #define fits_write_col_bit ffpclx #define fits_write_nulrows ffprwu #define fits_write_nullrows ffprwu #define fits_write_colnull ffpcn #define fits_write_colnull_str ffpcns #define fits_write_colnull_log ffpcnl #define fits_write_colnull_byt ffpcnb #define fits_write_colnull_sbyt ffpcnsb #define fits_write_colnull_usht ffpcnui #define fits_write_colnull_ulng ffpcnuj #define fits_write_colnull_sht ffpcni #define fits_write_colnull_lng ffpcnj #define fits_write_colnull_ulnglng ffpcnujj #define fits_write_colnull_lnglng ffpcnjj #define fits_write_colnull_uint ffpcnuk #define fits_write_colnull_int ffpcnk #define fits_write_colnull_flt ffpcne #define fits_write_colnull_dbl ffpcnd #define fits_write_ext ffpextn #define fits_read_ext ffgextn #define fits_write_descript ffpdes #define fits_compress_heap ffcmph #define fits_test_heap fftheap #define fits_write_tblbytes ffptbb #define fits_insert_rows ffirow #define fits_delete_rows ffdrow #define fits_delete_rowrange ffdrrg #define fits_delete_rowlist ffdrws #define fits_delete_rowlistll ffdrwsll #define fits_insert_col fficol #define fits_insert_cols fficls #define fits_delete_col ffdcol #define fits_copy_col ffcpcl #define fits_copy_cols ffccls #define fits_copy_rows ffcprw #define fits_copy_selrows ffcpsr #define fits_modify_vector_len ffmvec #define fits_read_img_coord ffgics #define fits_read_img_coord_version ffgicsa #define fits_read_tbl_coord ffgtcs #define fits_pix_to_world ffwldp #define fits_world_to_pix ffxypx #define fits_get_image_wcs_keys ffgiwcs #define fits_get_table_wcs_keys ffgtwcs #define fits_find_rows fffrow #define fits_find_first_row ffffrw #define fits_find_rows_cmp fffrwc #define fits_select_rows ffsrow #define fits_calc_rows ffcrow #define fits_calculator ffcalc #define fits_calculator_rng ffcalc_rng #define fits_test_expr fftexp #define fits_create_group ffgtcr #define fits_insert_group ffgtis #define fits_change_group ffgtch #define fits_remove_group ffgtrm #define fits_copy_group ffgtcp #define fits_merge_groups ffgtmg #define fits_compact_group ffgtcm #define fits_verify_group ffgtvf #define fits_open_group ffgtop #define fits_add_group_member ffgtam #define fits_get_num_members ffgtnm #define fits_get_num_groups ffgmng #define fits_open_member ffgmop #define fits_copy_member ffgmcp #define fits_transfer_member ffgmtf #define fits_remove_member ffgmrm #define fits_init_https ffihtps #define fits_cleanup_https ffchtps #define fits_verbose_https ffvhtps #define fits_show_download_progress ffshdwn #define fits_get_timeout ffgtmo #define fits_set_timeout ffstmo #endif cfitsio-4.3.1/group.h0000644000225700000360000000406113472024437013761 0ustar cagordonlhea#define MAX_HDU_TRACKER 1000 typedef struct _HDUtracker HDUtracker; struct _HDUtracker { int nHDU; char *filename[MAX_HDU_TRACKER]; int position[MAX_HDU_TRACKER]; char *newFilename[MAX_HDU_TRACKER]; int newPosition[MAX_HDU_TRACKER]; }; /* functions used internally in the grouping convention module */ int ffgtdc(int grouptype, int xtensioncol, int extnamecol, int extvercol, int positioncol, int locationcol, int uricol, char *ttype[], char *tform[], int *ncols, int *status); int ffgtgc(fitsfile *gfptr, int *xtensionCol, int *extnameCol, int *extverCol, int *positionCol, int *locationCol, int *uriCol, int *grptype, int *status); int ffvcfm(fitsfile *gfptr, int xtensionCol, int extnameCol, int extverCol, int positionCol, int locationCol, int uriCol, int *status); int ffgmul(fitsfile *mfptr, int rmopt, int *status); int ffgmf(fitsfile *gfptr, char *xtension, char *extname, int extver, int position, char *location, long *member, int *status); int ffgtrmr(fitsfile *gfptr, HDUtracker *HDU, int *status); int ffgtcpr(fitsfile *infptr, fitsfile *outfptr, int cpopt, HDUtracker *HDU, int *status); int fftsad(fitsfile *mfptr, HDUtracker *HDU, int *newPosition, char *newFileName); int fftsud(fitsfile *mfptr, HDUtracker *HDU, int newPosition, char *newFileName); void prepare_keyvalue(char *keyvalue); int fits_path2url(char *inpath, int maxlength, char *outpath, int *status); int fits_url2path(char *inpath, char *outpath, int *status); int fits_get_cwd(char *cwd, int *status); int fits_get_url(fitsfile *fptr, char *realURL, char *startURL, char *realAccess, char *startAccess, int *iostate, int *status); int fits_clean_url(char *inURL, char *outURL, int *status); int fits_relurl2url(char *refURL, char *relURL, char *absURL, int *status); int fits_url2relurl(char *refURL, char *absURL, char *relURL, int *status); int fits_encode_url(char *inpath, int maxlength, char *outpath, int *status); int fits_unencode_url(char *inpath, char *outpath, int *status); int fits_is_url_absolute(char *url); cfitsio-4.3.1/drvrmem.c0000644000225700000360000011673314335036354014306 0ustar cagordonlhea/* This file, drvrmem.c, contains driver routines for memory files. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include /* apparently needed to define size_t */ #include "fitsio2.h" #if HAVE_BZIP2 #include "bzlib.h" #endif /* prototype for .Z file uncompression function in zuncompress.c */ int zuncompress2mem(char *filename, FILE *diskfile, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); #if HAVE_BZIP2 /* prototype for .bz2 uncompression function (in this file) */ void bzip2uncompress2mem(char *filename, FILE *diskfile, int hdl, size_t* filesize, int* status); #endif #define RECBUFLEN 1000 static char stdin_outfile[FLEN_FILENAME]; typedef struct /* structure containing mem file structure */ { char **memaddrptr; /* Pointer to memory address pointer; */ /* This may or may not point to memaddr. */ char *memaddr; /* Pointer to starting memory address; may */ /* not always be used, so use *memaddrptr instead */ size_t *memsizeptr; /* Pointer to the size of the memory allocation. */ /* This may or may not point to memsize. */ size_t memsize; /* Size of the memory allocation; this may not */ /* always be used, so use *memsizeptr instead. */ size_t deltasize; /* Suggested increment for reallocating memory */ void *(*mem_realloc)(void *p, size_t newsize); /* realloc function */ LONGLONG currentpos; /* current file position, relative to start */ LONGLONG fitsfilesize; /* size of the FITS file (always <= *memsizeptr) */ FILE *fileptr; /* pointer to compressed output disk file */ } memdriver; static memdriver memTable[NMAXFILES]; /* allocate mem file handle tables */ /*--------------------------------------------------------------------------*/ int mem_init(void) { int ii; for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ { memTable[ii].memaddrptr = 0; memTable[ii].memaddr = 0; } return(0); } /*--------------------------------------------------------------------------*/ int mem_setoptions(int options) { /* do something with the options argument, to stop compiler warning */ options = 0; return(options); } /*--------------------------------------------------------------------------*/ int mem_getoptions(int *options) { *options = 0; return(0); } /*--------------------------------------------------------------------------*/ int mem_getversion(int *version) { *version = 10; return(0); } /*--------------------------------------------------------------------------*/ int mem_shutdown(void) { return(0); } /*--------------------------------------------------------------------------*/ int mem_create(char *filename, int *handle) /* Create a new empty memory file for subsequent writes. The file name is ignored in this case. */ { int status; /* initially allocate 1 FITS block = 2880 bytes */ status = mem_createmem(2880L, handle); if (status) { ffpmsg("failed to create empty memory file (mem_create)"); return(status); } return(0); } /*--------------------------------------------------------------------------*/ int mem_create_comp(char *filename, int *handle) /* Create a new empty memory file for subsequent writes. Also create an empty compressed .gz file. The memory file will be compressed and written to the disk file when the file is closed. */ { FILE *diskfile; char mode[4]; int status; /* first, create disk file for the compressed output */ if ( !strcmp(filename, "-.gz") || !strcmp(filename, "stdout.gz") || !strcmp(filename, "STDOUT.gz") ) { /* special case: create uncompressed FITS file in memory, then compress it an write it out to 'stdout' when it is closed. */ diskfile = stdout; } else { /* normal case: create disk file for the compressed output */ strcpy(mode, "w+b"); /* create file with read-write */ diskfile = fopen(filename, "r"); /* does file already exist? */ if (diskfile) { fclose(diskfile); /* close file and exit with error */ return(FILE_NOT_CREATED); } #if MACHINE == ALPHAVMS || MACHINE == VAXVMS /* specify VMS record structure: fixed format, 2880 byte records */ /* but force stream mode access to enable random I/O access */ diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); #else diskfile = fopen(filename, mode); #endif if (!(diskfile)) /* couldn't create file */ { return(FILE_NOT_CREATED); } } /* now create temporary memory file */ /* initially allocate 1 FITS block = 2880 bytes */ status = mem_createmem(2880L, handle); if (status) { ffpmsg("failed to create empty memory file (mem_create_comp)"); return(status); } memTable[*handle].fileptr = diskfile; return(0); } /*--------------------------------------------------------------------------*/ int mem_openmem(void **buffptr, /* I - address of memory pointer */ size_t *buffsize, /* I - size of buffer, in bytes */ size_t deltasize, /* I - increment for future realloc's */ void *(*memrealloc)(void *p, size_t newsize), /* function */ int *handle) /* lowest level routine to open a pre-existing memory file. */ { int ii; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */ { if (memTable[ii].memaddrptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ memTable[ii].memaddrptr = (char **) buffptr; /* pointer to start addres */ memTable[ii].memsizeptr = buffsize; /* allocated size of memory */ memTable[ii].deltasize = deltasize; /* suggested realloc increment */ memTable[ii].fitsfilesize = *buffsize; /* size of FITS file (upper limit) */ memTable[ii].currentpos = 0; /* at beginning of the file */ memTable[ii].mem_realloc = memrealloc; /* memory realloc function */ return(0); } /*--------------------------------------------------------------------------*/ int mem_createmem(size_t msize, int *handle) /* lowest level routine to allocate a memory file. */ { int ii; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */ { if (memTable[ii].memaddrptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /* use the internally allocated memaddr and memsize variables */ memTable[ii].memaddrptr = &memTable[ii].memaddr; memTable[ii].memsizeptr = &memTable[ii].memsize; /* allocate initial block of memory for the file */ if (msize > 0) { memTable[ii].memaddr = (char *) malloc(msize); if ( !(memTable[ii].memaddr) ) { ffpmsg("malloc of initial memory failed (mem_createmem)"); return(FILE_NOT_OPENED); } } /* set initial state of the file */ memTable[ii].memsize = msize; memTable[ii].deltasize = 2880; memTable[ii].fitsfilesize = 0; memTable[ii].currentpos = 0; memTable[ii].mem_realloc = realloc; return(0); } /*--------------------------------------------------------------------------*/ int mem_truncate(int handle, LONGLONG filesize) /* truncate the file to a new size */ { char *ptr; /* call the memory reallocation function, if defined */ if ( memTable[handle].mem_realloc ) { /* explicit LONGLONG->size_t cast */ ptr = (memTable[handle].mem_realloc)( *(memTable[handle].memaddrptr), (size_t) filesize); if (!ptr) { ffpmsg("Failed to reallocate memory (mem_truncate)"); return(MEMORY_ALLOCATION); } /* if allocated more memory, initialize it to zero */ if ( filesize > *(memTable[handle].memsizeptr) ) { memset(ptr + *(memTable[handle].memsizeptr), 0, ((size_t) filesize) - *(memTable[handle].memsizeptr) ); } *(memTable[handle].memaddrptr) = ptr; *(memTable[handle].memsizeptr) = (size_t) (filesize); } memTable[handle].currentpos = filesize; memTable[handle].fitsfilesize = filesize; return(0); } /*--------------------------------------------------------------------------*/ int stdin_checkfile(char *urltype, char *infile, char *outfile) /* do any special case checking when opening a file on the stdin stream */ { if (strlen(outfile)) { stdin_outfile[0] = '\0'; strncat(stdin_outfile,outfile,FLEN_FILENAME-1); /* an output file is specified */ strcpy(urltype,"stdinfile://"); } else *stdin_outfile = '\0'; /* no output file was specified */ return(0); } /*--------------------------------------------------------------------------*/ int stdin_open(char *filename, int rwmode, int *handle) /* open a FITS file from the stdin file stream by copying it into memory The file name is ignored in this case. */ { int status; char cbuff; if (*stdin_outfile) { /* copy the stdin stream to the specified disk file then open the file */ /* Create the output file */ status = file_create(stdin_outfile,handle); if (status) { ffpmsg("Unable to create output file to copy stdin (stdin_open):"); ffpmsg(stdin_outfile); return(status); } /* copy the whole stdin stream to the file */ status = stdin2file(*handle); file_close(*handle); if (status) { ffpmsg("failed to copy stdin to file (stdin_open)"); ffpmsg(stdin_outfile); return(status); } /* reopen file with proper rwmode attribute */ status = file_open(stdin_outfile, rwmode, handle); } else { /* get the first character, then put it back */ cbuff = fgetc(stdin); ungetc(cbuff, stdin); /* compressed files begin with 037 or 'P' */ if (cbuff == 31 || cbuff == 75) { /* looks like the input stream is compressed */ status = mem_compress_stdin_open(filename, rwmode, handle); } else { /* copy the stdin stream into memory then open file in memory */ if (rwmode != READONLY) { ffpmsg("cannot open stdin with WRITE access"); return(READONLY_FILE); } status = mem_createmem(2880L, handle); if (status) { ffpmsg("failed to create empty memory file (stdin_open)"); return(status); } /* copy the whole stdin stream into memory */ status = stdin2mem(*handle); if (status) { ffpmsg("failed to copy stdin into memory (stdin_open)"); free(memTable[*handle].memaddr); } } } return(status); } /*--------------------------------------------------------------------------*/ int stdin2mem(int hd) /* handle number */ /* Copy the stdin stream into memory. Fill whatever amount of memory has already been allocated, then realloc more memory if necessary. */ { size_t nread, memsize, delta; LONGLONG filesize; char *memptr; char simple[] = "SIMPLE"; int c, ii, jj; memptr = *memTable[hd].memaddrptr; memsize = *memTable[hd].memsizeptr; delta = memTable[hd].deltasize; filesize = 0; ii = 0; for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++) { /* Skip over any garbage at the beginning of the stdin stream by */ /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */ /* Give up if not found in the first 2000 characters */ if (c == simple[ii]) { ii++; if (ii == 6) /* found the complete string? */ { memcpy(memptr, simple, 6); /* copy "SIMPLE" to buffer */ filesize = 6; break; } } else ii = 0; /* reset search to beginning of the string */ } if (filesize == 0) { ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream."); ffpmsg("This does not look like a FITS file."); return(FILE_NOT_OPENED); } /* fill up the remainder of the initial memory allocation */ nread = fread(memptr + 6, 1, memsize - 6, stdin); nread += 6; /* add in the 6 characters in 'SIMPLE' */ if (nread < memsize) /* reached the end? */ { memTable[hd].fitsfilesize = nread; return(0); } filesize = nread; while (1) { /* allocate memory for another FITS block */ memptr = realloc(memptr, memsize + delta); if (!memptr) { ffpmsg("realloc failed while copying stdin (stdin2mem)"); return(MEMORY_ALLOCATION); } memsize += delta; /* read another FITS block */ nread = fread(memptr + filesize, 1, delta, stdin); filesize += nread; if (nread < delta) /* reached the end? */ break; } memTable[hd].fitsfilesize = filesize; *memTable[hd].memaddrptr = memptr; *memTable[hd].memsizeptr = memsize; return(0); } /*--------------------------------------------------------------------------*/ int stdin2file(int handle) /* handle number */ /* Copy the stdin stream to a file. . */ { size_t nread; char simple[] = "SIMPLE"; int c, ii, jj, status; char recbuf[RECBUFLEN]; ii = 0; for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++) { /* Skip over any garbage at the beginning of the stdin stream by */ /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */ /* Give up if not found in the first 2000 characters */ if (c == simple[ii]) { ii++; if (ii == 6) /* found the complete string? */ { memcpy(recbuf, simple, 6); /* copy "SIMPLE" to buffer */ break; } } else ii = 0; /* reset search to beginning of the string */ } if (ii != 6) { ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream"); return(FILE_NOT_OPENED); } /* fill up the remainder of the buffer */ nread = fread(recbuf + 6, 1, RECBUFLEN - 6, stdin); nread += 6; /* add in the 6 characters in 'SIMPLE' */ status = file_write(handle, recbuf, nread); if (status) return(status); /* copy the rest of stdin stream */ while(0 != (nread = fread(recbuf,1,RECBUFLEN, stdin))) { status = file_write(handle, recbuf, nread); if (status) return(status); } return(status); } /*--------------------------------------------------------------------------*/ int stdout_close(int handle) /* copy the memory file to stdout, then free the memory */ { int status = 0; /* copy from memory to standard out. explicit LONGLONG->size_t cast */ if(fwrite(memTable[handle].memaddr, 1, ((size_t) memTable[handle].fitsfilesize), stdout) != (size_t) memTable[handle].fitsfilesize ) { ffpmsg("failed to copy memory file to stdout (stdout_close)"); status = WRITE_ERROR; } free( memTable[handle].memaddr ); /* free the memory */ memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; return(status); } /*--------------------------------------------------------------------------*/ int mem_compress_openrw(char *filename, int rwmode, int *hdl) /* This routine opens the compressed diskfile and creates an empty memory buffer with an appropriate size, then calls mem_uncompress2mem. It allows the memory 'file' to be opened with READWRITE access. */ { return(mem_compress_open(filename, READONLY, hdl)); } /*--------------------------------------------------------------------------*/ int mem_compress_open(char *filename, int rwmode, int *hdl) /* This routine opens the compressed diskfile and creates an empty memory buffer with an appropriate size, then calls mem_uncompress2mem. */ { FILE *diskfile; int status, estimated = 1; unsigned char buffer[4]; size_t finalsize, filesize; LONGLONG llsize = 0; unsigned int modulosize; char *ptr; if (rwmode != READONLY) { ffpmsg( "cannot open compressed file with WRITE access (mem_compress_open)"); ffpmsg(filename); return(READONLY_FILE); } /* open the compressed disk file */ status = file_openfile(filename, READONLY, &diskfile); if (status) { ffpmsg("failed to open compressed disk file (compress_open)"); ffpmsg(filename); return(status); } if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */ { fclose(diskfile); return(READ_ERROR); } if (memcmp(buffer, "\037\213", 2) == 0) /* GZIP */ { /* the uncompressed file size is give at the end */ /* of the file in the ISIZE field (modulo 2^32) */ fseek(diskfile, 0, 2); /* move to end of file */ filesize = ftell(diskfile); /* position = size of file */ fseek(diskfile, -4L, 1); /* move back 4 bytes */ fread(buffer, 1, 4L, diskfile); /* read 4 bytes */ /* have to worry about integer byte order */ modulosize = buffer[0]; modulosize |= buffer[1] << 8; modulosize |= buffer[2] << 16; modulosize |= buffer[3] << 24; /* the field ISIZE in the gzipped file header only stores 4 bytes and contains the uncompressed file size modulo 2^32. If the uncompressed file size is less than the compressed file size (filesize), then one probably needs to add 2^32 = 4294967296 to the uncompressed file size, assuming that the gzip produces a compressed file that is smaller than the original file. But one must allow for the case of very small files, where the gzipped file may actually be larger then the original uncompressed file. Therefore, only perform the modulo 2^32 correction test if the compressed file is greater than 10,000 bytes in size. (Note: this threhold would fail only if the original file was greater than 2^32 bytes in size AND gzip was able to compress it by more than a factor of 400,000 (!) which seems highly unlikely.) Also, obviously, this 2^32 modulo correction cannot be performed if the finalsize variable is only 32-bits long. Typically, the 'size_t' integer type must be 8 bytes or larger in size to support data files that are greater than 2 GB (2^31 bytes) in size. */ finalsize = modulosize; if (sizeof(size_t) > 4 && filesize > 10000) { llsize = (LONGLONG) finalsize; /* use LONGLONG variable to suppress compiler warning */ while (llsize < (LONGLONG) filesize) llsize += 4294967296; finalsize = (size_t) llsize; } estimated = 0; /* file size is known, not estimated */ } else if (memcmp(buffer, "\120\113", 2) == 0) /* PKZIP */ { /* the uncompressed file size is give at byte 22 the file */ fseek(diskfile, 22L, 0); /* move to byte 22 */ fread(buffer, 1, 4L, diskfile); /* read 4 bytes */ /* have to worry about integer byte order */ modulosize = buffer[0]; modulosize |= buffer[1] << 8; modulosize |= buffer[2] << 16; modulosize |= buffer[3] << 24; finalsize = modulosize; estimated = 0; /* file size is known, not estimated */ } else if (memcmp(buffer, "\037\036", 2) == 0) /* PACK */ finalsize = 0; /* for most methods we can't determine final size */ else if (memcmp(buffer, "\037\235", 2) == 0) /* LZW */ finalsize = 0; /* for most methods we can't determine final size */ else if (memcmp(buffer, "\037\240", 2) == 0) /* LZH */ finalsize = 0; /* for most methods we can't determine final size */ #if HAVE_BZIP2 else if (memcmp(buffer, "BZ", 2) == 0) /* BZip2 */ finalsize = 0; /* for most methods we can't determine final size */ #endif else { /* not a compressed file; this should never happen */ fclose(diskfile); return(1); } if (finalsize == 0) /* estimate uncompressed file size */ { fseek(diskfile, 0, 2); /* move to end of the compressed file */ finalsize = ftell(diskfile); /* position = size of file */ finalsize = finalsize * 3; /* assume factor of 3 compression */ } fseek(diskfile, 0, 0); /* move back to beginning of file */ /* create a memory file big enough (hopefully) for the uncompressed file */ status = mem_createmem(finalsize, hdl); if (status && estimated) { /* memory allocation failed, so try a smaller estimated size */ finalsize = finalsize / 3; status = mem_createmem(finalsize, hdl); } if (status) { fclose(diskfile); ffpmsg("failed to create empty memory file (compress_open)"); return(status); } /* uncompress file into memory */ status = mem_uncompress2mem(filename, diskfile, *hdl); fclose(diskfile); if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to uncompress file into memory (compress_open)"); return(status); } /* if we allocated too much memory initially, then free it */ if (*(memTable[*hdl].memsizeptr) > (( (size_t) memTable[*hdl].fitsfilesize) + 256L) ) { ptr = realloc(*(memTable[*hdl].memaddrptr), ((size_t) memTable[*hdl].fitsfilesize) ); if (!ptr) { ffpmsg("Failed to reduce size of allocated memory (compress_open)"); return(MEMORY_ALLOCATION); } *(memTable[*hdl].memaddrptr) = ptr; *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize); } return(0); } /*--------------------------------------------------------------------------*/ int mem_compress_stdin_open(char *filename, int rwmode, int *hdl) /* This routine reads the compressed input stream and creates an empty memory buffer, then calls mem_uncompress2mem. */ { int status; char *ptr; if (rwmode != READONLY) { ffpmsg( "cannot open compressed input stream with WRITE access (mem_compress_stdin_open)"); return(READONLY_FILE); } /* create a memory file for the uncompressed file */ status = mem_createmem(28800, hdl); if (status) { ffpmsg("failed to create empty memory file (compress_stdin_open)"); return(status); } /* uncompress file into memory */ status = mem_uncompress2mem(filename, stdin, *hdl); if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to uncompress stdin into memory (compress_stdin_open)"); return(status); } /* if we allocated too much memory initially, then free it */ if (*(memTable[*hdl].memsizeptr) > (( (size_t) memTable[*hdl].fitsfilesize) + 256L) ) { ptr = realloc(*(memTable[*hdl].memaddrptr), ((size_t) memTable[*hdl].fitsfilesize) ); if (!ptr) { ffpmsg("Failed to reduce size of allocated memory (compress_stdin_open)"); return(MEMORY_ALLOCATION); } *(memTable[*hdl].memaddrptr) = ptr; *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize); } return(0); } /*--------------------------------------------------------------------------*/ int mem_iraf_open(char *filename, int rwmode, int *hdl) /* This routine creates an empty memory buffer, then calls iraf2mem to open the IRAF disk file and convert it to a FITS file in memeory. */ { int status; size_t filesize = 0; /* create a memory file with size = 0 for the FITS converted IRAF file */ status = mem_createmem(filesize, hdl); if (status) { ffpmsg("failed to create empty memory file (mem_iraf_open)"); return(status); } /* convert the iraf file into a FITS file in memory */ status = iraf2mem(filename, memTable[*hdl].memaddrptr, memTable[*hdl].memsizeptr, &filesize, &status); if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to convert IRAF file into memory (mem_iraf_open)"); return(status); } memTable[*hdl].currentpos = 0; /* save starting position */ memTable[*hdl].fitsfilesize=filesize; /* and initial file size */ return(0); } /*--------------------------------------------------------------------------*/ int mem_rawfile_open(char *filename, int rwmode, int *hdl) /* This routine creates an empty memory buffer, writes a minimal image header, then copies the image data from the raw file into memory. It will byteswap the pixel values if the raw array is in little endian byte order. */ { FILE *diskfile; fitsfile *fptr; short *sptr; int status, endian, datatype, bytePerPix, naxis; long dim[5] = {1,1,1,1,1}, ii, nvals, offset = 0; size_t filesize = 0, datasize; char rootfile[FLEN_FILENAME], *cptr = 0, *cptr2 = 0; void *ptr; if (rwmode != READONLY) { ffpmsg( "cannot open raw binary file with WRITE access (mem_rawfile_open)"); ffpmsg(filename); return(READONLY_FILE); } cptr = strchr(filename, '['); /* search for opening bracket [ */ if (!cptr) { ffpmsg("binary file name missing '[' character (mem_rawfile_open)"); ffpmsg(filename); return(URL_PARSE_ERROR); } *rootfile = '\0'; strncat(rootfile, filename, cptr - filename); /* store the rootname */ cptr++; while (*cptr == ' ') cptr++; /* skip leading blanks */ /* Get the Data Type of the Image */ if (*cptr == 'b' || *cptr == 'B') { datatype = BYTE_IMG; bytePerPix = 1; } else if (*cptr == 'i' || *cptr == 'I') { datatype = SHORT_IMG; bytePerPix = 2; } else if (*cptr == 'u' || *cptr == 'U') { datatype = USHORT_IMG; bytePerPix = 2; } else if (*cptr == 'j' || *cptr == 'J') { datatype = LONG_IMG; bytePerPix = 4; } else if (*cptr == 'r' || *cptr == 'R' || *cptr == 'f' || *cptr == 'F') { datatype = FLOAT_IMG; bytePerPix = 4; } else if (*cptr == 'd' || *cptr == 'D') { datatype = DOUBLE_IMG; bytePerPix = 8; } else { ffpmsg("error in raw binary file datatype (mem_rawfile_open)"); ffpmsg(filename); return(URL_PARSE_ERROR); } cptr++; /* get Endian: Big or Little; default is same as the local machine */ if (*cptr == 'b' || *cptr == 'B') { endian = 0; cptr++; } else if (*cptr == 'l' || *cptr == 'L') { endian = 1; cptr++; } else endian = BYTESWAPPED; /* byteswapped machines are little endian */ /* read each dimension (up to 5) */ naxis = 1; dim[0] = strtol(cptr, &cptr2, 10); if (cptr2 && *cptr2 == ',') { naxis = 2; dim[1] = strtol(cptr2+1, &cptr, 10); if (cptr && *cptr == ',') { naxis = 3; dim[2] = strtol(cptr+1, &cptr2, 10); if (cptr2 && *cptr2 == ',') { naxis = 4; dim[3] = strtol(cptr2+1, &cptr, 10); if (cptr && *cptr == ',') naxis = 5; dim[4] = strtol(cptr+1, &cptr2, 10); } } } cptr = maxvalue(cptr, cptr2); if (*cptr == ':') /* read starting offset value */ offset = strtol(cptr+1, 0, 10); nvals = dim[0] * dim[1] * dim[2] * dim[3] * dim[4]; datasize = nvals * bytePerPix; filesize = nvals * bytePerPix + 2880; filesize = ((filesize - 1) / 2880 + 1) * 2880; /* open the raw binary disk file */ status = file_openfile(rootfile, READONLY, &diskfile); if (status) { ffpmsg("failed to open raw binary file (mem_rawfile_open)"); ffpmsg(rootfile); return(status); } /* create a memory file with corrct size for the FITS converted raw file */ status = mem_createmem(filesize, hdl); if (status) { ffpmsg("failed to create memory file (mem_rawfile_open)"); fclose(diskfile); return(status); } /* open this piece of memory as a new FITS file */ ffimem(&fptr, (void **) memTable[*hdl].memaddrptr, &filesize, 0, 0, &status); /* write the required header keywords */ ffcrim(fptr, datatype, naxis, dim, &status); /* close the FITS file, but keep the memory allocated */ ffclos(fptr, &status); if (status > 0) { ffpmsg("failed to write basic image header (mem_rawfile_open)"); fclose(diskfile); mem_close_free(*hdl); /* free up the memory */ return(status); } if (offset > 0) fseek(diskfile, offset, 0); /* offset to start of the data */ /* read the raw data into memory */ ptr = *memTable[*hdl].memaddrptr + 2880; if (fread((char *) ptr, 1, datasize, diskfile) != datasize) status = READ_ERROR; fclose(diskfile); /* close the raw binary disk file */ if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to copy raw file data into memory (mem_rawfile_open)"); return(status); } if (datatype == USHORT_IMG) /* have to subtract 32768 from each unsigned */ { /* value to conform to FITS convention. More */ /* efficient way to do this is to just flip */ /* the most significant bit. */ sptr = (short *) ptr; if (endian == BYTESWAPPED) /* working with native format */ { for (ii = 0; ii < nvals; ii++, sptr++) { *sptr = ( *sptr ) ^ 0x8000; } } else /* pixels are byteswapped WRT the native format */ { for (ii = 0; ii < nvals; ii++, sptr++) { *sptr = ( *sptr ) ^ 0x80; } } } if (endian) /* swap the bytes if array is in little endian byte order */ { if (datatype == SHORT_IMG || datatype == USHORT_IMG) { ffswap2( (short *) ptr, nvals); } else if (datatype == LONG_IMG || datatype == FLOAT_IMG) { ffswap4( (INT32BIT *) ptr, nvals); } else if (datatype == DOUBLE_IMG) { ffswap8( (double *) ptr, nvals); } } memTable[*hdl].currentpos = 0; /* save starting position */ memTable[*hdl].fitsfilesize=filesize; /* and initial file size */ return(0); } /*--------------------------------------------------------------------------*/ int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl) { /* lower level routine to uncompress a file into memory. The file has already been opened and the memory buffer has been allocated. */ size_t finalsize; int status; /* uncompress file into memory */ status = 0; if (strstr(filename, ".Z")) { zuncompress2mem(filename, diskfile, memTable[hdl].memaddrptr, /* pointer to memory address */ memTable[hdl].memsizeptr, /* pointer to size of memory */ realloc, /* reallocation function */ &finalsize, &status); /* returned file size nd status*/ #if HAVE_BZIP2 } else if (strstr(filename, ".bz2")) { bzip2uncompress2mem(filename, diskfile, hdl, &finalsize, &status); #endif } else { uncompress2mem(filename, diskfile, memTable[hdl].memaddrptr, /* pointer to memory address */ memTable[hdl].memsizeptr, /* pointer to size of memory */ realloc, /* reallocation function */ &finalsize, &status); /* returned file size nd status*/ } memTable[hdl].currentpos = 0; /* save starting position */ memTable[hdl].fitsfilesize=finalsize; /* and initial file size */ return status; } /*--------------------------------------------------------------------------*/ int mem_size(int handle, LONGLONG *filesize) /* return the size of the file; only called when the file is first opened */ { *filesize = memTable[handle].fitsfilesize; return(0); } /*--------------------------------------------------------------------------*/ int mem_close_free(int handle) /* close the file and free the memory. */ { free( *(memTable[handle].memaddrptr) ); memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; return(0); } /*--------------------------------------------------------------------------*/ int mem_close_keep(int handle) /* close the memory file but do not free the memory. */ { memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; return(0); } /*--------------------------------------------------------------------------*/ int mem_close_comp(int handle) /* compress the memory file, writing it out to the fileptr (which might be stdout) */ { int status = 0; size_t compsize; /* compress file in memory to a .gz disk file */ if(compress2file_from_mem(memTable[handle].memaddr, (size_t) (memTable[handle].fitsfilesize), memTable[handle].fileptr, &compsize, &status ) ) { ffpmsg("failed to copy memory file to file (mem_close_comp)"); status = WRITE_ERROR; } free( memTable[handle].memaddr ); /* free the memory */ memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; /* close the compressed disk file (except if it is 'stdout' */ if (memTable[handle].fileptr != stdout) fclose(memTable[handle].fileptr); return(status); } /*--------------------------------------------------------------------------*/ int mem_seek(int handle, LONGLONG offset) /* seek to position relative to start of the file. */ { if (offset > memTable[handle].fitsfilesize ) return(END_OF_FILE); memTable[handle].currentpos = offset; return(0); } /*--------------------------------------------------------------------------*/ int mem_read(int hdl, void *buffer, long nbytes) /* read bytes from the current position in the file */ { if (memTable[hdl].currentpos + nbytes > memTable[hdl].fitsfilesize) return(END_OF_FILE); memcpy(buffer, *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos, nbytes); memTable[hdl].currentpos += nbytes; return(0); } /*--------------------------------------------------------------------------*/ int mem_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { size_t newsize; char *ptr; if ((size_t) (memTable[hdl].currentpos + nbytes) > *(memTable[hdl].memsizeptr) ) { if (!(memTable[hdl].mem_realloc)) { ffpmsg("realloc function not defined (mem_write)"); return(WRITE_ERROR); } /* Attempt to reallocate additional memory: the memory buffer size is incremented by the larger of: 1 FITS block (2880 bytes) or the defined 'deltasize' parameter */ newsize = maxvalue( (size_t) (((memTable[hdl].currentpos + nbytes - 1) / 2880) + 1) * 2880, *(memTable[hdl].memsizeptr) + memTable[hdl].deltasize); /* call the realloc function */ ptr = (memTable[hdl].mem_realloc)( *(memTable[hdl].memaddrptr), newsize); if (!ptr) { ffpmsg("Failed to reallocate memory (mem_write)"); return(MEMORY_ALLOCATION); } *(memTable[hdl].memaddrptr) = ptr; *(memTable[hdl].memsizeptr) = newsize; } /* now copy the bytes from the buffer into memory */ memcpy( *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos, buffer, nbytes); memTable[hdl].currentpos += nbytes; memTable[hdl].fitsfilesize = maxvalue(memTable[hdl].fitsfilesize, memTable[hdl].currentpos); return(0); } /*--------------------------------------------------------------------------*/ int mem_zuncompress_and_write(int hdl, void *buffer, long nbytes) /* uncompress input buffer, length nbytes and write bytes to current position in file. output buffer needs to be at position 0 to start. */ { size_t newsize; int status = 0; if (memTable[hdl].currentpos != 0) { ffpmsg("cannot append uncompressed data (mem_uncompress_and_write)"); return(WRITE_ERROR); } uncompress2mem_from_mem(buffer, nbytes, memTable[hdl].memaddrptr, memTable[hdl].memsizeptr, memTable[hdl].mem_realloc, &newsize, &status); if (status) { ffpmsg("unabled to uncompress memory file (mem_uncompress_and_write)"); return(WRITE_ERROR); } memTable[hdl].currentpos += newsize; memTable[hdl].fitsfilesize = newsize; return(0); } #if HAVE_BZIP2 void bzip2uncompress2mem(char *filename, FILE *diskfile, int hdl, size_t* filesize, int* status) { BZFILE* b; int bzerror; char buf[8192]; size_t total_read = 0; char* errormsg = NULL; *filesize = 0; *status = 0; b = BZ2_bzReadOpen(&bzerror, diskfile, 0, 0, NULL, 0); if (bzerror != BZ_OK) { BZ2_bzReadClose(&bzerror, b); if (bzerror == BZ_MEM_ERROR) ffpmsg("failed to open a bzip2 file: out of memory\n"); else if (bzerror == BZ_CONFIG_ERROR) ffpmsg("failed to open a bzip2 file: miscompiled bzip2 library\n"); else if (bzerror == BZ_IO_ERROR) ffpmsg("failed to open a bzip2 file: I/O error"); else ffpmsg("failed to open a bzip2 file"); *status = READ_ERROR; return; } bzerror = BZ_OK; while (bzerror == BZ_OK) { int nread; nread = BZ2_bzRead(&bzerror, b, buf, sizeof(buf)); if (bzerror == BZ_OK || bzerror == BZ_STREAM_END) { *status = mem_write(hdl, buf, nread); if (*status) { BZ2_bzReadClose(&bzerror, b); if (*status == MEMORY_ALLOCATION) ffpmsg("Failed to reallocate memory while uncompressing bzip2 file"); return; } total_read += nread; } else { if (bzerror == BZ_IO_ERROR) errormsg = "failed to read bzip2 file: I/O error"; else if (bzerror == BZ_UNEXPECTED_EOF) errormsg = "failed to read bzip2 file: unexpected end-of-file"; else if (bzerror == BZ_DATA_ERROR) errormsg = "failed to read bzip2 file: data integrity error"; else if (bzerror == BZ_MEM_ERROR) errormsg = "failed to read bzip2 file: insufficient memory"; } } BZ2_bzReadClose(&bzerror, b); if (bzerror != BZ_OK) { if (errormsg) ffpmsg(errormsg); else ffpmsg("failure closing bzip2 file after reading\n"); *status = READ_ERROR; return; } *filesize = total_read; } #endif cfitsio-4.3.1/cfitsio-config-version.cmake.in0000644000225700000360000000126714335036354020456 0ustar cagordonlheaset(PACKAGE_VERSION "@CFITSIO_VERSION@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif() endif() # alternate: #set(PACKAGE_VERSION "@version@") #if(NOT "${PACKAGE_FIND_VERSION}" VERSION_GREATER "@version@") # set(PACKAGE_VERSION_COMPATIBLE 1) # compatible with older # if("${PACKAGE_FIND_VERSION}" VERSION_EQUAL "@version@") # set(PACKAGE_VERSION_EXACT 1) # exact match for this version # endif() #endif() cfitsio-4.3.1/cfortran.h0000644000225700000360000041367414335036354014461 0ustar cagordonlhea/* cfortran.h 4.4 */ /* http://www-zeus.desy.de/~burow/cfortran/ */ /* Burkhard Burow burow@desy.de 1990 - 2002. */ #ifndef __CFORTRAN_LOADED #define __CFORTRAN_LOADED /* THIS FILE IS PROPERTY OF BURKHARD BUROW. IF YOU ARE USING THIS FILE YOU SHOULD ALSO HAVE ACCESS TO CFORTRAN.DOC WHICH PROVIDES TERMS FOR USING, MODIFYING, COPYING AND DISTRIBUTING THE CFORTRAN.H PACKAGE. */ /* The following modifications were made by the authors of CFITSIO or by me. * They are flagged below with CFITSIO, the author's initials, or KMCCARTY. * PDW = Peter Wilson * DM = Doug Mink * LEB = Lee E Brotzman * MR = Martin Reinecke * WDP = William D Pence * -- Kevin McCarty, for Debian (19 Dec. 2005) */ /******* Modifications: Oct 1997: Changed symbol name extname to appendus (PDW/HSTX) (Conflicted with a common variable name in FTOOLS) Nov 1997: If g77Fortran defined, also define f2cFortran (PDW/HSTX) Feb 1998: Let VMS see the NUM_ELEMS code. Lets programs treat single strings as vectors with single elements Nov 1999: If macintoxh defined, also define f2cfortran (for Mac OS-X) Apr 2000: If WIN32 defined, also define PowerStationFortran and VISUAL_CPLUSPLUS (Visual C++) Jun 2000: If __GNUC__ and linux defined, also define f2cFortran (linux/gcc environment detection) Apr 2002: If __CYGWIN__ is defined, also define f2cFortran Nov 2002: If __APPLE__ defined, also define f2cfortran (for Mac OS-X) Nov 2003: If __INTEL_COMPILER or INTEL_COMPILER defined, also define f2cFortran (KMCCARTY) Dec 2005: If f2cFortran is defined, enforce REAL functions in FORTRAN returning "double" in C. This was one of the items on Burkhard's TODO list. (KMCCARTY) Dec 2005: Modifications to support 8-byte integers. (MR) USE AT YOUR OWN RISK! Feb 2006 Added logic to typedef the symbol 'LONGLONG' to an appropriate intrinsic 8-byte integer datatype (WDP) Apr 2006: Modifications to support gfortran (and g77 with -fno-f2c flag) since by default it returns "float" for FORTRAN REAL function. (KMCCARTY) May 2008: Revert commenting out of "extern" in COMMON_BLOCK_DEF macro. Add braces around do-nothing ";" in 3 empty while blocks to get rid of compiler warnings. Thanks to ROOT developers Jacek Holeczek and Rene Brun for these suggestions. (KMCCARTY) Dec 2008 Added typedef for LONGLONG to support Borland compiler (WDP) Jan 2020 Added __attribute__((unused)) for GCC to prevent warnings (C. Markwardt) Jan 2022 Changed H_CF_SPECIAL definition from 'unsigned' to 'size_t'. This determines the type of the hidden length argument which gets added to functions passing strings from Fortran to C. This change was first required when testing Homebrew compilers native to Mac/ARM Silicon. (C. Gordon) Apr 2022 Made equivalent 'unsigned'/'size_t' change to STRING_cfKK(B) definition. This is required for passing strings from C to Fortran. To avoid duplication, defined an 'if' block for setting new CF_STRLENTYPE variable. H_CF_SPECIAL and STRING_cfKK(B) are now set to this. May 2022 Set ALL Mac/ARM platforms to 'size_t' for CF_STRLENTYPE since Clang/Clang++ will not pass GNUC>7 test, yet its (3rd-party) Fortran still needs this. *******/ #ifndef __CFORTRAN__PCTYPE__UNUSED__ #ifdef __GNUC__ #define __CFORTRAN__PCTYPE__UNUSED__ __attribute__ ((unused)) #else #define __CFORTRAN__PCTYPE__UNUSED__ #endif #endif /* Avoid symbols already used by compilers and system *.h: __ - OSF1 zukal06 V3.0 347 alpha, cc -c -std1 cfortest.c */ /* Determine what 8-byte integer data type is available. 'long long' is now supported by most compilers, but older MS Visual C++ compilers before V7.0 use '__int64' instead. (WDP) */ #ifndef LONGLONG_TYPE /* this may have been previously defined */ #if defined(_MSC_VER) /* Microsoft Visual C++ */ #if (_MSC_VER < 1300) /* versions earlier than V7.0 do not have 'long long' */ typedef __int64 LONGLONG; typedef unsigned __int64 ULONGLONG; #else /* newer versions do support 'long long' */ typedef long long LONGLONG; typedef unsigned long long ULONGLONG; #endif #elif defined( __BORLANDC__) /* (WDP) for the free Borland compiler, in particular */ typedef __int64 LONGLONG; typedef unsigned __int64 ULONGLONG; #else typedef long long LONGLONG; typedef unsigned long long ULONGLONG; #endif #define LONGLONG_TYPE #endif /* Microsoft Visual C++ requires alternate form for static inline. */ #if defined(_MSC_VER) /* Microsoft Visual C++ */ #define STIN static __inline #else #define STIN static inline #endif /* First prepare for the C compiler. */ #ifndef ANSI_C_preprocessor /* i.e. user can override. */ #ifdef __CF__KnR #define ANSI_C_preprocessor 0 #else #ifdef __STDC__ #define ANSI_C_preprocessor 1 #else #define _cfleft 1 #define _cfright #define _cfleft_cfright 0 #define ANSI_C_preprocessor _cfleft/**/_cfright #endif #endif #endif #if ANSI_C_preprocessor #define _0(A,B) A##B #define _(A,B) _0(A,B) /* see cat,xcat of K&R ANSI C p. 231 */ #define _2(A,B) A##B /* K&R ANSI C p.230: .. identifier is not replaced */ #define _3(A,B,C) _(A,_(B,C)) #else /* if it turns up again during rescanning. */ #define _(A,B) A/**/B #define _2(A,B) A/**/B #define _3(A,B,C) A/**/B/**/C #endif #if (defined(vax)&&defined(unix)) || (defined(__vax__)&&defined(__unix__)) #define VAXUltrix #endif #include /* NULL [in all machines stdio.h] */ #include /* strlen, memset, memcpy, memchr. */ #if !( defined(VAXUltrix) || defined(sun) || (defined(apollo)&&!defined(__STDCPP__)) ) #include /* malloc,free */ #else #include /* Had to be removed for DomainOS h105 10.4 sys5.3 425t*/ #ifdef apollo #define __CF__APOLLO67 /* __STDCPP__ is in Apollo 6.8 (i.e. ANSI) and onwards */ #endif #endif #if !defined(__GNUC__) && !defined(__sun) && (defined(sun)||defined(VAXUltrix)||defined(lynx)) #define __CF__KnR /* Sun, LynxOS and VAX Ultrix cc only supports K&R. */ /* Manually define __CF__KnR for HP if desired/required.*/ #endif /* i.e. We will generate Kernighan and Ritchie C. */ /* Note that you may define __CF__KnR before #include cfortran.h, in order to generate K&R C instead of the default ANSI C. The differences are mainly in the function prototypes and declarations. All machines, except the Apollo, work with either style. The Apollo's argument promotion rules require ANSI or use of the obsolete std_$call which we have not implemented here. Hence on the Apollo, only C calling FORTRAN subroutines will work using K&R style.*/ /* Remainder of cfortran.h depends on the Fortran compiler. */ /* 11/29/2003 (KMCCARTY): add *INTEL_COMPILER symbols here */ /* 04/05/2006 (KMCCARTY): add gFortran symbol here */ #if defined(CLIPPERFortran) || defined(pgiFortran) || defined(__INTEL_COMPILER) || defined(INTEL_COMPILER) || defined(gFortran) #define f2cFortran #endif /* VAX/VMS does not let us \-split long #if lines. */ /* Split #if into 2 because some HP-UX can't handle long #if */ #if !(defined(NAGf90Fortran)||defined(f2cFortran)||defined(hpuxFortran)||defined(apolloFortran)||defined(sunFortran)||defined(IBMR2Fortran)||defined(CRAYFortran)) #if !(defined(mipsFortran)||defined(DECFortran)||defined(vmsFortran)||defined(CONVEXFortran)||defined(PowerStationFortran)||defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)||defined(SXFortran)) /* If no Fortran compiler is given, we choose one for the machines we know. */ #if defined(lynx) || defined(VAXUltrix) #define f2cFortran /* Lynx: Only support f2c at the moment. VAXUltrix: f77 behaves like f2c. Support f2c or f77 with gcc, vcc with f2c. f77 with vcc works, missing link magic for f77 I/O.*/ #endif /* 04/13/00 DM (CFITSIO): Add these lines for NT */ /* with PowerStationFortran and and Visual C++ */ #if defined(WIN32) && !defined(__CYGWIN__) #define PowerStationFortran #define VISUAL_CPLUSPLUS #endif #if defined(g77Fortran) /* 11/03/97 PDW (CFITSIO) */ #define f2cFortran #endif #if defined(__CYGWIN__) /* 04/11/02 LEB (CFITSIO) */ #define f2cFortran #endif #if defined(__GNUC__) && defined(linux) /* 06/21/00 PDW (CFITSIO) */ #define f2cFortran #endif #if defined(macintosh) /* 11/1999 (CFITSIO) */ #define f2cFortran #endif #if defined(__APPLE__) /* 11/2002 (CFITSIO) */ #define f2cFortran #endif #if defined(__hpux) /* 921107: Use __hpux instead of __hp9000s300 */ #define hpuxFortran /* Should also allow hp9000s7/800 use.*/ #endif #if defined(apollo) #define apolloFortran /* __CF__APOLLO67 also defines some behavior. */ #endif #if defined(sun) || defined(__sun) #define sunFortran #endif #if defined(_IBMR2) #define IBMR2Fortran #endif #if defined(_CRAY) #define CRAYFortran /* _CRAYT3E also defines some behavior. */ #endif #if defined(_SX) #define SXFortran #endif #if defined(mips) || defined(__mips) #define mipsFortran #endif #if defined(vms) || defined(__vms) #define vmsFortran #endif #if defined(__alpha) && defined(__unix__) #define DECFortran #endif #if defined(__convex__) #define CONVEXFortran #endif #if defined(VISUAL_CPLUSPLUS) #define PowerStationFortran #endif #endif /* ...Fortran */ #endif /* ...Fortran */ /* Split #if into 2 because some HP-UX can't handle long #if */ #if !(defined(NAGf90Fortran)||defined(f2cFortran)||defined(hpuxFortran)||defined(apolloFortran)||defined(sunFortran)||defined(IBMR2Fortran)||defined(CRAYFortran)) #if !(defined(mipsFortran)||defined(DECFortran)||defined(vmsFortran)||defined(CONVEXFortran)||defined(PowerStationFortran)||defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)||defined(SXFortran)) /* If your compiler barfs on ' #error', replace # with the trigraph for # */ #error "cfortran.h: Can't find your environment among:\ - GNU gcc (g77) on Linux. \ - MIPS cc and f77 2.0. (e.g. Silicon Graphics, DECstations, ...) \ - IBM AIX XL C and FORTRAN Compiler/6000 Version 01.01.0000.0000 \ - VAX VMS CC 3.1 and FORTRAN 5.4. \ - Alpha VMS DEC C 1.3 and DEC FORTRAN 6.0. \ - Alpha OSF DEC C and DEC Fortran for OSF/1 AXP Version 1.2 \ - Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7. \ - CRAY \ - NEC SX-4 SUPER-UX \ - CONVEX \ - Sun \ - PowerStation Fortran with Visual C++ \ - HP9000s300/s700/s800 Latest test with: HP-UX A.08.07 A 9000/730 \ - LynxOS: cc or gcc with f2c. \ - VAXUltrix: vcc,cc or gcc with f2c. gcc or cc with f77. \ - f77 with vcc works; but missing link magic for f77 I/O. \ - NO fort. None of gcc, cc or vcc generate required names.\ - f2c/g77: Use #define f2cFortran, or cc -Df2cFortran \ - gfortran: Use #define gFortran, or cc -DgFortran \ (also necessary for g77 with -fno-f2c option) \ - NAG f90: Use #define NAGf90Fortran, or cc -DNAGf90Fortran \ - Absoft UNIX F77: Use #define AbsoftUNIXFortran or cc -DAbsoftUNIXFortran \ - Absoft Pro Fortran: Use #define AbsoftProFortran \ - Portland Group Fortran: Use #define pgiFortran \ - Intel Fortran: Use #define INTEL_COMPILER" /* Compiler must throw us out at this point! */ #endif #endif #if defined(VAXC) && !defined(__VAXC) #define OLD_VAXC #pragma nostandard /* Prevent %CC-I-PARAMNOTUSED. */ #endif /* Throughout cfortran.h we use: UN = Uppercase Name. LN = Lowercase Name. */ /* "extname" changed to "appendus" below (CFITSIO) */ #if defined(f2cFortran) || defined(NAGf90Fortran) || defined(DECFortran) || defined(mipsFortran) || defined(apolloFortran) || defined(sunFortran) || defined(CONVEXFortran) || defined(SXFortran) || defined(appendus) #define CFC_(UN,LN) _(LN,_) /* Lowercase FORTRAN symbols. */ #define orig_fcallsc(UN,LN) CFC_(UN,LN) #else #if defined(CRAYFortran) || defined(PowerStationFortran) || defined(AbsoftProFortran) #ifdef _CRAY /* (UN), not UN, circumvents CRAY preprocessor bug. */ #define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */ #else /* At least VISUAL_CPLUSPLUS barfs on (UN), so need UN. */ #define CFC_(UN,LN) UN /* Uppercase FORTRAN symbols. */ #endif #define orig_fcallsc(UN,LN) CFC_(UN,LN) /* CRAY insists on arg.'s here. */ #else /* For following machines one may wish to change the fcallsc default. */ #define CF_SAME_NAMESPACE #ifdef vmsFortran #define CFC_(UN,LN) LN /* Either case FORTRAN symbols. */ /* BUT we usually use UN for C macro to FORTRAN routines, so use LN here,*/ /* because VAX/VMS doesn't do recursive macros. */ #define orig_fcallsc(UN,LN) UN #else /* HP-UX without +ppu or IBMR2 without -qextname. NOT reccomended. */ #define CFC_(UN,LN) LN /* Lowercase FORTRAN symbols. */ #define orig_fcallsc(UN,LN) CFC_(UN,LN) #endif /* vmsFortran */ #endif /* CRAYFortran PowerStationFortran */ #endif /* ....Fortran */ #define fcallsc(UN,LN) orig_fcallsc(UN,LN) #define preface_fcallsc(P,p,UN,LN) CFC_(_(P,UN),_(p,LN)) #define append_fcallsc(P,p,UN,LN) CFC_(_(UN,P),_(LN,p)) #define C_FUNCTION(UN,LN) fcallsc(UN,LN) #define FORTRAN_FUNCTION(UN,LN) CFC_(UN,LN) #ifndef COMMON_BLOCK #ifndef CONVEXFortran #ifndef CLIPPERFortran #if !(defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)) #define COMMON_BLOCK(UN,LN) CFC_(UN,LN) #else #define COMMON_BLOCK(UN,LN) _(_C,LN) #endif /* AbsoftUNIXFortran or AbsoftProFortran */ #else #define COMMON_BLOCK(UN,LN) _(LN,__) #endif /* CLIPPERFortran */ #else #define COMMON_BLOCK(UN,LN) _3(_,LN,_) #endif /* CONVEXFortran */ #endif /* COMMON_BLOCK */ #ifndef DOUBLE_PRECISION #if defined(CRAYFortran) && !defined(_CRAYT3E) #define DOUBLE_PRECISION long double #else #define DOUBLE_PRECISION double #endif #endif #ifndef FORTRAN_REAL #if defined(CRAYFortran) && defined(_CRAYT3E) #define FORTRAN_REAL double #else #define FORTRAN_REAL float #endif #endif #ifdef CRAYFortran #ifdef _CRAY #include #else #include "fortran.h" /* i.e. if crosscompiling assume user has file. */ #endif #define FLOATVVVVVVV_cfPP (FORTRAN_REAL *) /* Used for C calls FORTRAN. */ /* CRAY's double==float but CRAY says pointers to doubles and floats are diff.*/ #define VOIDP (void *) /* When FORTRAN calls C, we don't know if C routine arg.'s have been declared float *, or double *. */ #else #define FLOATVVVVVVV_cfPP #define VOIDP #endif #ifdef vmsFortran #if defined(vms) || defined(__vms) #include #else #include "descrip.h" /* i.e. if crosscompiling assume user has file. */ #endif #endif #ifdef sunFortran #if defined(sun) || defined(__sun) #include /* Sun's FLOATFUNCTIONTYPE, ASSIGNFLOAT, RETURNFLOAT. */ #else #include "math.h" /* i.e. if crosscompiling assume user has file. */ #endif /* At least starting with the default C compiler SC3.0.1 of SunOS 5.3, * FLOATFUNCTIONTYPE, ASSIGNFLOAT, RETURNFLOAT are not required and not in * , since sun C no longer promotes C float return values to doubles. * Therefore, only use them if defined. * Even if gcc is being used, assume that it exhibits the Sun C compiler * behavior in order to be able to use *.o from the Sun C compiler. * i.e. If FLOATFUNCTIONTYPE, etc. are in math.h, they required by gcc. */ #endif #ifndef apolloFortran #define COMMON_BLOCK_DEF(DEFINITION, NAME) extern DEFINITION NAME #define CF_NULL_PROTO #else /* HP doesn't understand #elif. */ /* Without ANSI prototyping, Apollo promotes float functions to double. */ /* Note that VAX/VMS, IBM, Mips choke on 'type function(...);' prototypes. */ #define CF_NULL_PROTO ... #ifndef __CF__APOLLO67 #define COMMON_BLOCK_DEF(DEFINITION, NAME) \ DEFINITION NAME __attribute((__section(NAME))) #else #define COMMON_BLOCK_DEF(DEFINITION, NAME) \ DEFINITION NAME #attribute[section(NAME)] #endif #endif #ifdef __cplusplus #undef CF_NULL_PROTO #define CF_NULL_PROTO ... #endif #ifndef USE_NEW_DELETE #ifdef __cplusplus #define USE_NEW_DELETE 1 #else #define USE_NEW_DELETE 0 #endif #endif #if USE_NEW_DELETE #define _cf_malloc(N) new char[N] #define _cf_free(P) delete[] P #else #define _cf_malloc(N) (char *)malloc(N) #define _cf_free(P) free(P) #endif #ifdef mipsFortran #define CF_DECLARE_GETARG int f77argc; char **f77argv #define CF_SET_GETARG(ARGC,ARGV) f77argc = ARGC; f77argv = ARGV #else #define CF_DECLARE_GETARG #define CF_SET_GETARG(ARGC,ARGV) #endif #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define AcfCOMMA , #define AcfCOLON ; /* Use CF_STRLENTYPE = size_t for all Fortran newer than GNU version 7.x. Apple clang identifies itself as GNUC=4, but we want it to use size_t too. Note that 2 assumptions are in play here: 1) Aside from clang, the C version (GNUC) also represents the version of Fortran being used! 2) No one is pairing clang with gfortran older than v8.x anymore. */ #if (defined(__GNUC__) && !defined(__clang__)) && __GNUC__ < 8 #define CF_STRLENTYPE unsigned #else #define CF_STRLENTYPE size_t #endif /*-------------------------------------------------------------------------*/ /* UTILITIES USED WITHIN CFORTRAN.H */ #define _cfMIN(A,B) (As) { /* Need this to handle NULL string.*/ while (e>s && *--e==t) {;} /* Don't follow t's past beginning. */ e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */ } return s; } /* kill_trailingn(s,t,e) will kill the trailing t's in string s. e normally points to the terminating '\0' of s, but may actually point to anywhere in s. s's new '\0' will be placed at e or earlier in order to remove any trailing t's. If es) { /* Watch out for neg. length string.*/ while (e>s && *--e==t){;} /* Don't follow t's past beginning. */ e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */ } return s; } /* Note the following assumes that any element which has t's to be chopped off, does indeed fill the entire element. */ #ifndef __CF__KnR static char *vkill_trailing(char* cstr, int elem_len, int sizeofcstr, char t) #else static char *vkill_trailing( cstr, elem_len, sizeofcstr, t) char* cstr; int elem_len; int sizeofcstr; char t; #endif { int i; for (i=0; i= 4.3 gives message: zow35> cc -c -DDECFortran cfortest.c cfe: Fatal: Out of memory: cfortest.c zow35> Old __hpux had the problem, but new 'HP-UX A.09.03 A 9000/735' is fine if using -Aa, otherwise we have a problem. */ #ifndef MAX_PREPRO_ARGS #if !defined(__GNUC__) && (defined(VAXUltrix) || defined(__CF__APOLLO67) || (defined(sun)&&!defined(__sun)) || defined(_CRAY) || defined(__ultrix__) || (defined(__hpux)&&defined(__CF__KnR))) #define MAX_PREPRO_ARGS 31 #else #define MAX_PREPRO_ARGS 99 #endif #endif #if defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) /* In addition to explicit Absoft stuff, only Absoft requires: - DEFAULT coming from _cfSTR. DEFAULT could have been called e.g. INT, but keep it for clarity. - M term in CFARGT14 and CFARGT14FS. */ #define ABSOFT_cf1(T0) _(T0,_cfSTR)(0,ABSOFT1,0,0,0,0,0) #define ABSOFT_cf2(T0) _(T0,_cfSTR)(0,ABSOFT2,0,0,0,0,0) #define ABSOFT_cf3(T0) _(T0,_cfSTR)(0,ABSOFT3,0,0,0,0,0) #define DEFAULT_cfABSOFT1 #define LOGICAL_cfABSOFT1 #define STRING_cfABSOFT1 ,MAX_LEN_FORTRAN_FUNCTION_STRING #define DEFAULT_cfABSOFT2 #define LOGICAL_cfABSOFT2 #define STRING_cfABSOFT2 ,unsigned D0 #define DEFAULT_cfABSOFT3 #define LOGICAL_cfABSOFT3 #define STRING_cfABSOFT3 ,D0 #else #define ABSOFT_cf1(T0) #define ABSOFT_cf2(T0) #define ABSOFT_cf3(T0) #endif /* _Z introduced to cicumvent IBM and HP silly preprocessor warning. e.g. "Macro CFARGT14 invoked with a null argument." */ #define _Z #define CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) #define CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) \ S(TF,15) S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) S(TL,21) \ S(TM,22) S(TN,23) S(TO,24) S(TP,25) S(TQ,26) S(TR,27) #define CFARGT14FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ M CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CFARGT27FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) F(TL,21,1) \ F(TM,22,1) F(TN,23,1) F(TO,24,1) F(TP,25,1) F(TQ,26,1) F(TR,27,1) \ M CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #if !(defined(PowerStationFortran)||defined(hpuxFortran800)) /* Old CFARGT14 -> CFARGT14FS as seen below, for Absoft cross-compile yields: SunOS> cc -c -Xa -DAbsoftUNIXFortran c.c "c.c", line 406: warning: argument mismatch Haven't checked if this is ANSI C or a SunOS bug. SunOS -Xs works ok. Behavior is most clearly seen in example: #define A 1 , 2 #define C(X,Y,Z) x=X. y=Y. z=Z. #define D(X,Y,Z) C(X,Y,Z) D(x,A,z) Output from preprocessor is: x = x . y = 1 . z = 2 . #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ CFARGT14FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) */ #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ M CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CFARGT27(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) F(TL,21,1) \ F(TM,22,1) F(TN,23,1) F(TO,24,1) F(TP,25,1) F(TQ,26,1) F(TR,27,1) \ M CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #define CFARGT20(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) \ S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) \ S(TF,15) S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) #define CFARGTA14(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) \ F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ F(TD,AD,13,1) F(TE,AE,14,1) S(T1,1) S(T2,2) S(T3,3) S(T4,4) \ S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) S(TA,10) \ S(TB,11) S(TC,12) S(TD,13) S(TE,14) #if MAX_PREPRO_ARGS>31 #define CFARGTA20(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ F(TD,AD,13,1) F(TE,AE,14,1) F(TF,AF,15,1) F(TG,AG,16,1) F(TH,AH,17,1) F(TI,AI,18,1) \ F(TJ,AJ,19,1) F(TK,AK,20,1) S(T1,1) S(T2,2) S(T3,3) S(T4,4) \ S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) S(TA,10) \ S(TB,11) S(TC,12) S(TD,13) S(TE,14) S(TF,15) S(TG,16) \ S(TH,17) S(TI,18) S(TJ,19) S(TK,20) #define CFARGTA27(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ F(TD,AD,13,1) F(TE,AE,14,1) F(TF,AF,15,1) F(TG,AG,16,1) F(TH,AH,17,1) F(TI,AI,18,1) \ F(TJ,AJ,19,1) F(TK,AK,20,1) F(TL,AL,21,1) F(TM,AM,22,1) F(TN,AN,23,1) F(TO,AO,24,1) \ F(TP,AP,25,1) F(TQ,AQ,26,1) F(TR,AR,27,1) S(T1,1) S(T2,2) S(T3,3) \ S(T4,4) S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) \ S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) S(TF,15) \ S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) S(TL,21) \ S(TM,22) S(TN,23) S(TO,24) S(TP,25) S(TQ,26) S(TR,27) #endif #else #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) #define CFARGT27(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) F(TF,15,1) S(TF,15) F(TG,16,1) S(TG,16) \ F(TH,17,1) S(TH,17) F(TI,18,1) S(TI,18) F(TJ,19,1) S(TJ,19) F(TK,20,1) S(TK,20) \ F(TL,21,1) S(TL,21) F(TM,22,1) S(TM,22) F(TN,23,1) S(TN,23) F(TO,24,1) S(TO,24) \ F(TP,25,1) S(TP,25) F(TQ,26,1) S(TQ,26) F(TR,27,1) S(TR,27) #define CFARGT20(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) F(TF,15,1) S(TF,15) F(TG,16,1) S(TG,16) \ F(TH,17,1) S(TH,17) F(TI,18,1) S(TI,18) F(TJ,19,1) S(TJ,19) F(TK,20,1) S(TK,20) #define CFARGTA14(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) \ F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) #if MAX_PREPRO_ARGS>31 #define CFARGTA20(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) F(TF,AF,15,1) S(TF,15) \ F(TG,AG,16,1) S(TG,16) F(TH,AH,17,1) S(TH,17) F(TI,AI,18,1) S(TI,18) \ F(TJ,AJ,19,1) S(TJ,19) F(TK,AK,20,1) S(TK,20) #define CFARGTA27(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) F(TF,AF,15,1) S(TF,15) \ F(TG,AG,16,1) S(TG,16) F(TH,AH,17,1) S(TH,17) F(TI,AI,18,1) S(TI,18) \ F(TJ,AJ,19,1) S(TJ,19) F(TK,AK,20,1) S(TK,20) F(TL,AL,21,1) S(TL,21) \ F(TM,AM,22,1) S(TM,22) F(TN,AN,23,1) S(TN,23) F(TO,AO,24,1) S(TO,24) \ F(TP,AP,25,1) S(TP,25) F(TQ,AQ,26,1) S(TQ,26) F(TR,AR,27,1) S(TR,27) #endif #endif #define PROTOCCALLSFSUB1( UN,LN,T1) \ PROTOCCALLSFSUB14(UN,LN,T1,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB2( UN,LN,T1,T2) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB3( UN,LN,T1,T2,T3) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB4( UN,LN,T1,T2,T3,T4) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB5( UN,LN,T1,T2,T3,T4,T5) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB6( UN,LN,T1,T2,T3,T4,T5,T6) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB7( UN,LN,T1,T2,T3,T4,T5,T6,T7) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) #define PROTOCCALLSFSUB13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) #define PROTOCCALLSFSUB15(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB16(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB17(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB18(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0) #define PROTOCCALLSFSUB19(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0) #define PROTOCCALLSFSUB21(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB22(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB23(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB24(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB25(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0) #define PROTOCCALLSFSUB26(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0) #ifndef FCALLSC_QUALIFIER #ifdef VISUAL_CPLUSPLUS #define FCALLSC_QUALIFIER __stdcall #else #define FCALLSC_QUALIFIER #endif #endif #ifdef __cplusplus #define CFextern extern "C" #else #define CFextern extern #endif #ifdef CFSUBASFUN #define PROTOCCALLSFSUB0(UN,LN) \ PROTOCCALLSFFUN0( VOID,UN,LN) #define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ PROTOCCALLSFFUN14(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK)\ PROTOCCALLSFFUN20(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)\ PROTOCCALLSFFUN27(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #else /* Note: Prevent compiler warnings, null #define PROTOCCALLSFSUB14/20 after #include-ing cfortran.h if calling the FORTRAN wrapper within the same source code where the wrapper is created. */ #define PROTOCCALLSFSUB0(UN,LN) _(VOID,_cfPU)(CFC_(UN,LN))(); #ifndef __CF__KnR #define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT14(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ); #define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK)\ _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT20(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) ); #define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)\ _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT27(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) ); #else #define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ PROTOCCALLSFSUB0(UN,LN) #define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ PROTOCCALLSFSUB0(UN,LN) #define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ PROTOCCALLSFSUB0(UN,LN) #endif #endif #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define CCALLSFSUB1( UN,LN,T1, A1) \ CCALLSFSUB5 (UN,LN,T1,CF_0,CF_0,CF_0,CF_0,A1,0,0,0,0) #define CCALLSFSUB2( UN,LN,T1,T2, A1,A2) \ CCALLSFSUB5 (UN,LN,T1,T2,CF_0,CF_0,CF_0,A1,A2,0,0,0) #define CCALLSFSUB3( UN,LN,T1,T2,T3, A1,A2,A3) \ CCALLSFSUB5 (UN,LN,T1,T2,T3,CF_0,CF_0,A1,A2,A3,0,0) #define CCALLSFSUB4( UN,LN,T1,T2,T3,T4, A1,A2,A3,A4)\ CCALLSFSUB5 (UN,LN,T1,T2,T3,T4,CF_0,A1,A2,A3,A4,0) #define CCALLSFSUB5( UN,LN,T1,T2,T3,T4,T5, A1,A2,A3,A4,A5) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,0,0,0,0,0) #define CCALLSFSUB6( UN,LN,T1,T2,T3,T4,T5,T6, A1,A2,A3,A4,A5,A6) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,0,0,0,0) #define CCALLSFSUB7( UN,LN,T1,T2,T3,T4,T5,T6,T7, A1,A2,A3,A4,A5,A6,A7) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,0,0,0) #define CCALLSFSUB8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8, A1,A2,A3,A4,A5,A6,A7,A8) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,0,0) #define CCALLSFSUB9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,A1,A2,A3,A4,A5,A6,A7,A8,A9)\ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,0) #define CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,0,0,0,0) #define CCALLSFSUB11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,0,0,0) #define CCALLSFSUB12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,0,0) #define CCALLSFSUB13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,0) #ifdef __cplusplus #define CPPPROTOCLSFSUB0( UN,LN) #define CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #else #define CPPPROTOCLSFSUB0(UN,LN) \ PROTOCCALLSFSUB0(UN,LN) #define CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #endif #ifdef CFSUBASFUN #define CCALLSFSUB0(UN,LN) CCALLSFFUN0(UN,LN) #define CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) #else /* do{...}while(0) allows if(a==b) FORT(); else BORT(); */ #define CCALLSFSUB0( UN,LN) do{CPPPROTOCLSFSUB0(UN,LN) CFC_(UN,LN)();}while(0) #define CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) \ CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) \ ACF(LN,T4,A4,4) ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) \ ACF(LN,T8,A8,8) ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) \ ACF(LN,TC,AC,12) ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) \ CFC_(UN,LN)( CFARGTA14(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) );\ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) \ WCF(TB,AB,11) WCF(TC,AC,12) WCF(TD,AD,13) WCF(TE,AE,14) }while(0) #endif #if MAX_PREPRO_ARGS>31 #define CCALLSFSUB15(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,0,0,0,0,0) #define CCALLSFSUB16(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,0,0,0,0) #define CCALLSFSUB17(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,0,0,0) #define CCALLSFSUB18(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,0,0) #define CCALLSFSUB19(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,0) #ifdef CFSUBASFUN #define CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ CCALLSFFUN20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) #else #define CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) VVCF(TF,AF,B15) \ VVCF(TG,AG,B16) VVCF(TH,AH,B17) VVCF(TI,AI,B18) VVCF(TJ,AJ,B19) VVCF(TK,AK,B20) \ CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) ACF(LN,T4,A4,4) \ ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) ACF(LN,T8,A8,8) \ ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) ACF(LN,TC,AC,12) \ ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) ACF(LN,TF,AF,15) ACF(LN,TG,AG,16) \ ACF(LN,TH,AH,17) ACF(LN,TI,AI,18) ACF(LN,TJ,AJ,19) ACF(LN,TK,AK,20) \ CFC_(UN,LN)( CFARGTA20(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) ); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) WCF(T6,A6,6) \ WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) WCF(TB,AB,11) WCF(TC,AC,12) \ WCF(TD,AD,13) WCF(TE,AE,14) WCF(TF,AF,15) WCF(TG,AG,16) WCF(TH,AH,17) WCF(TI,AI,18) \ WCF(TJ,AJ,19) WCF(TK,AK,20) }while(0) #endif #endif /* MAX_PREPRO_ARGS */ #if MAX_PREPRO_ARGS>31 #define CCALLSFSUB21(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,0,0,0,0,0,0) #define CCALLSFSUB22(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,0,0,0,0,0) #define CCALLSFSUB23(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,0,0,0,0) #define CCALLSFSUB24(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,0,0,0) #define CCALLSFSUB25(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,0,0) #define CCALLSFSUB26(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,0) #ifdef CFSUBASFUN #define CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ CCALLSFFUN27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) #else #define CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) VVCF(TF,AF,B15) \ VVCF(TG,AG,B16) VVCF(TH,AH,B17) VVCF(TI,AI,B18) VVCF(TJ,AJ,B19) VVCF(TK,AK,B20) \ VVCF(TL,AL,B21) VVCF(TM,AM,B22) VVCF(TN,AN,B23) VVCF(TO,AO,B24) VVCF(TP,AP,B25) \ VVCF(TQ,AQ,B26) VVCF(TR,AR,B27) \ CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) ACF(LN,T4,A4,4) \ ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) ACF(LN,T8,A8,8) \ ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) ACF(LN,TC,AC,12) \ ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) ACF(LN,TF,AF,15) ACF(LN,TG,AG,16) \ ACF(LN,TH,AH,17) ACF(LN,TI,AI,18) ACF(LN,TJ,AJ,19) ACF(LN,TK,AK,20) \ ACF(LN,TL,AL,21) ACF(LN,TM,AM,22) ACF(LN,TN,AN,23) ACF(LN,TO,AO,24) \ ACF(LN,TP,AP,25) ACF(LN,TQ,AQ,26) ACF(LN,TR,AR,27) \ CFC_(UN,LN)( CFARGTA27(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,\ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) ); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) WCF(T6,A6,6) \ WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) WCF(TB,AB,11) WCF(TC,AC,12) \ WCF(TD,AD,13) WCF(TE,AE,14) WCF(TF,AF,15) WCF(TG,AG,16) WCF(TH,AH,17) WCF(TI,AI,18) \ WCF(TJ,AJ,19) WCF(TK,AK,20) WCF(TL,AL,21) WCF(TM,AM,22) WCF(TN,AN,23) WCF(TO,AO,24) \ WCF(TP,AP,25) WCF(TQ,AQ,26) WCF(TR,AR,27) }while(0) #endif #endif /* MAX_PREPRO_ARGS */ /*-------------------------------------------------------------------------*/ /* UTILITIES FOR C TO CALL FORTRAN FUNCTIONS */ /*N.B. PROTOCCALLSFFUNn(..) generates code, whether or not the FORTRAN function is called. Therefore, especially for creator's of C header files for large FORTRAN libraries which include many functions, to reduce compile time and object code size, it may be desirable to create preprocessor directives to allow users to create code for only those functions which they use. */ /* The following defines the maximum length string that a function can return. Of course it may be undefine-d and re-define-d before individual PROTOCCALLSFFUNn(..) as required. It would also be nice to have this derived from the individual machines' limits. */ #define MAX_LEN_FORTRAN_FUNCTION_STRING 0x4FE /* The following defines a character used by CFORTRAN.H to flag the end of a string coming out of a FORTRAN routine. */ #define CFORTRAN_NON_CHAR 0x7F #ifdef OLD_VAXC /* Prevent %CC-I-PARAMNOTUSED. */ #pragma nostandard #endif #define _SEP_(TN,C,cfCOMMA) _(__SEP_,C)(TN,cfCOMMA) #define __SEP_0(TN,cfCOMMA) #define __SEP_1(TN,cfCOMMA) _Icf(2,SEP,TN,cfCOMMA,0) #define INT_cfSEP(T,B) _(A,B) #define INTV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define PINT_cfSEP(T,B) INT_cfSEP(T,B) #define PVOID_cfSEP(T,B) INT_cfSEP(T,B) #define ROUTINE_cfSEP(T,B) INT_cfSEP(T,B) #define SIMPLE_cfSEP(T,B) INT_cfSEP(T,B) #define VOID_cfSEP(T,B) INT_cfSEP(T,B) /* For FORTRAN calls C subr.s.*/ #define STRING_cfSEP(T,B) INT_cfSEP(T,B) #define STRINGV_cfSEP(T,B) INT_cfSEP(T,B) #define PSTRING_cfSEP(T,B) INT_cfSEP(T,B) #define PSTRINGV_cfSEP(T,B) INT_cfSEP(T,B) #define PNSTRING_cfSEP(T,B) INT_cfSEP(T,B) #define PPSTRING_cfSEP(T,B) INT_cfSEP(T,B) #define ZTRINGV_cfSEP(T,B) INT_cfSEP(T,B) #define PZTRINGV_cfSEP(T,B) INT_cfSEP(T,B) #if defined(SIGNED_BYTE) || !defined(UNSIGNED_BYTE) #ifdef OLD_VAXC #define INTEGER_BYTE char /* Old VAXC barfs on 'signed char' */ #else #define INTEGER_BYTE signed char /* default */ #endif #else #define INTEGER_BYTE unsigned char #endif #define BYTEVVVVVVV_cfTYPE INTEGER_BYTE #define DOUBLEVVVVVVV_cfTYPE DOUBLE_PRECISION #define FLOATVVVVVVV_cfTYPE FORTRAN_REAL #define INTVVVVVVV_cfTYPE int #define LOGICALVVVVVVV_cfTYPE int #define LONGVVVVVVV_cfTYPE long #define LONGLONGVVVVVVV_cfTYPE LONGLONG /* added by MR December 2005 */ #define SHORTVVVVVVV_cfTYPE short #define PBYTE_cfTYPE INTEGER_BYTE #define PDOUBLE_cfTYPE DOUBLE_PRECISION #define PFLOAT_cfTYPE FORTRAN_REAL #define PINT_cfTYPE int #define PLOGICAL_cfTYPE int #define PLONG_cfTYPE long #define PLONGLONG_cfTYPE LONGLONG /* added by MR December 2005 */ #define PSHORT_cfTYPE short #define CFARGS0(A,T,V,W,X,Y,Z) _3(T,_cf,A) #define CFARGS1(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V) #define CFARGS2(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W) #define CFARGS3(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X) #define CFARGS4(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X,Y) #define CFARGS5(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X,Y,Z) #define _Icf(N,T,I,X,Y) _(I,_cfINT)(N,T,I,X,Y,0) #define _Icf4(N,T,I,X,Y,Z) _(I,_cfINT)(N,T,I,X,Y,Z) #define BYTE_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define DOUBLE_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INT,B,X,Y,Z,0) #define FLOAT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define INT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define LOGICAL_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define LONG_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define LONGLONG_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define SHORT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define PBYTE_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PDOUBLE_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,PINT,B,X,Y,Z,0) #define PFLOAT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PINT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PLOGICAL_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PLONG_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PLONGLONG_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define PSHORT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define BYTEV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define BYTEVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define DOUBLEV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTV,B,X,Y,Z,0) #define DOUBLEVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVV,B,X,Y,Z,0) #define DOUBLEVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVV,B,X,Y,Z,0) #define DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVV,B,X,Y,Z,0) #define DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVV,B,X,Y,Z,0) #define DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVVV,B,X,Y,Z,0) #define DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVVVV,B,X,Y,Z,0) #define FLOATV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define FLOATVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define INTV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define INTVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define INTVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define LOGICALVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define LONGVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define LONGVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGLONGV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define SHORTV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define SHORTVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define PVOID_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,B,B,X,Y,Z,0) #define ROUTINE_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) /*CRAY coughs on the first, i.e. the usual trouble of not being able to define macros to macros with arguments. New ultrix is worse, it coughs on all such uses. */ /*#define SIMPLE_cfINT PVOID_cfINT*/ #define SIMPLE_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define VOID_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define STRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define STRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PSTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PNSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PPSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define ZTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PZTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define CF_0_cfINT(N,A,B,X,Y,Z) #define UCF(TN,I,C) _SEP_(TN,C,cfCOMMA) _Icf(2,U,TN,_(A,I),0) #define UUCF(TN,I,C) _SEP_(TN,C,cfCOMMA) _SEP_(TN,1,I) #define UUUCF(TN,I,C) _SEP_(TN,C,cfCOLON) _Icf(2,U,TN,_(A,I),0) #define INT_cfU(T,A) _(T,VVVVVVV_cfTYPE) A #define INTV_cfU(T,A) _(T,VVVVVV_cfTYPE) * A #define INTVV_cfU(T,A) _(T,VVVVV_cfTYPE) * A #define INTVVV_cfU(T,A) _(T,VVVV_cfTYPE) * A #define INTVVVV_cfU(T,A) _(T,VVV_cfTYPE) * A #define INTVVVVV_cfU(T,A) _(T,VV_cfTYPE) * A #define INTVVVVVV_cfU(T,A) _(T,V_cfTYPE) * A #define INTVVVVVVV_cfU(T,A) _(T,_cfTYPE) * A #define PINT_cfU(T,A) _(T,_cfTYPE) * A #define PVOID_cfU(T,A) void *A #define ROUTINE_cfU(T,A) void (*A)(CF_NULL_PROTO) #define VOID_cfU(T,A) void A /* Needed for C calls FORTRAN sub.s. */ #define STRING_cfU(T,A) char *A /* via VOID and wrapper. */ #define STRINGV_cfU(T,A) char *A #define PSTRING_cfU(T,A) char *A #define PSTRINGV_cfU(T,A) char *A #define ZTRINGV_cfU(T,A) char *A #define PZTRINGV_cfU(T,A) char *A /* VOID breaks U into U and UU. */ #define INT_cfUU(T,A) _(T,VVVVVVV_cfTYPE) A #define VOID_cfUU(T,A) /* Needed for FORTRAN calls C sub.s. */ #define STRING_cfUU(T,A) char *A #define BYTE_cfPU(A) CFextern INTEGER_BYTE FCALLSC_QUALIFIER A #define DOUBLE_cfPU(A) CFextern DOUBLE_PRECISION FCALLSC_QUALIFIER A #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfPU(A) CFextern DOUBLE_PRECISION FCALLSC_QUALIFIER A #else #define FLOAT_cfPU(A) CFextern FORTRAN_REAL FCALLSC_QUALIFIER A #endif #else #define FLOAT_cfPU(A) CFextern FLOATFUNCTIONTYPE FCALLSC_QUALIFIER A #endif #define INT_cfPU(A) CFextern int FCALLSC_QUALIFIER A #define LOGICAL_cfPU(A) CFextern int FCALLSC_QUALIFIER A #define LONG_cfPU(A) CFextern long FCALLSC_QUALIFIER A #define SHORT_cfPU(A) CFextern short FCALLSC_QUALIFIER A #define STRING_cfPU(A) CFextern void FCALLSC_QUALIFIER A #define VOID_cfPU(A) CFextern void FCALLSC_QUALIFIER A #define BYTE_cfE INTEGER_BYTE A0; #define DOUBLE_cfE DOUBLE_PRECISION A0; #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #define FLOAT_cfE FORTRAN_REAL A0; #else #define FLOAT_cfE FORTRAN_REAL AA0; FLOATFUNCTIONTYPE A0; #endif #define INT_cfE int A0; #define LOGICAL_cfE int A0; #define LONG_cfE long A0; #define SHORT_cfE short A0; #define VOID_cfE #ifdef vmsFortran #define STRING_cfE static char AA0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ static fstring A0 = \ {MAX_LEN_FORTRAN_FUNCTION_STRING,DSC$K_DTYPE_T,DSC$K_CLASS_S,AA0};\ memset(AA0, CFORTRAN_NON_CHAR, MAX_LEN_FORTRAN_FUNCTION_STRING);\ *(AA0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0'; #else #ifdef CRAYFortran #define STRING_cfE static char AA0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ static _fcd A0; *(AA0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0';\ memset(AA0,CFORTRAN_NON_CHAR, MAX_LEN_FORTRAN_FUNCTION_STRING);\ A0 = _cptofcd(AA0,MAX_LEN_FORTRAN_FUNCTION_STRING); #else /* 'cc: SC3.0.1 13 Jul 1994' barfs on char A0[0x4FE+1]; * char A0[0x4FE +1]; char A0[1+0x4FE]; are both OK. */ #define STRING_cfE static char A0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ memset(A0, CFORTRAN_NON_CHAR, \ MAX_LEN_FORTRAN_FUNCTION_STRING); \ *(A0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0'; #endif #endif /* ESTRING must use static char. array which is guaranteed to exist after function returns. */ /* N.B.i) The diff. for 0 (Zero) and >=1 arguments. ii)That the following create an unmatched bracket, i.e. '(', which must of course be matched in the call. iii)Commas must be handled very carefully */ #define INT_cfGZ(T,UN,LN) A0=CFC_(UN,LN)( #define VOID_cfGZ(T,UN,LN) CFC_(UN,LN)( #ifdef vmsFortran #define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)(&A0 #else #if defined(CRAYFortran) || defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) #define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)( A0 #else #define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)( A0,MAX_LEN_FORTRAN_FUNCTION_STRING #endif #endif #define INT_cfG(T,UN,LN) INT_cfGZ(T,UN,LN) #define VOID_cfG(T,UN,LN) VOID_cfGZ(T,UN,LN) #define STRING_cfG(T,UN,LN) STRING_cfGZ(T,UN,LN), /*, is only diff. from _cfG*/ #define BYTEVVVVVVV_cfPP #define INTVVVVVVV_cfPP /* These complement FLOATVVVVVVV_cfPP. */ #define DOUBLEVVVVVVV_cfPP #define LOGICALVVVVVVV_cfPP #define LONGVVVVVVV_cfPP #define SHORTVVVVVVV_cfPP #define PBYTE_cfPP #define PINT_cfPP #define PDOUBLE_cfPP #define PLOGICAL_cfPP #define PLONG_cfPP #define PSHORT_cfPP #define PFLOAT_cfPP FLOATVVVVVVV_cfPP #define BCF(TN,AN,C) _SEP_(TN,C,cfCOMMA) _Icf(2,B,TN,AN,0) #define INT_cfB(T,A) (_(T,VVVVVVV_cfTYPE)) A #define INTV_cfB(T,A) A #define INTVV_cfB(T,A) (A)[0] #define INTVVV_cfB(T,A) (A)[0][0] #define INTVVVV_cfB(T,A) (A)[0][0][0] #define INTVVVVV_cfB(T,A) (A)[0][0][0][0] #define INTVVVVVV_cfB(T,A) (A)[0][0][0][0][0] #define INTVVVVVVV_cfB(T,A) (A)[0][0][0][0][0][0] #define PINT_cfB(T,A) _(T,_cfPP)&A #define STRING_cfB(T,A) (char *) A #define STRINGV_cfB(T,A) (char *) A #define PSTRING_cfB(T,A) (char *) A #define PSTRINGV_cfB(T,A) (char *) A #define PVOID_cfB(T,A) (void *) A #define ROUTINE_cfB(T,A) (cfCAST_FUNCTION)A #define ZTRINGV_cfB(T,A) (char *) A #define PZTRINGV_cfB(T,A) (char *) A #define SCF(TN,NAME,I,A) _(TN,_cfSTR)(3,S,NAME,I,A,0,0) #define DEFAULT_cfS(M,I,A) #define LOGICAL_cfS(M,I,A) #define PLOGICAL_cfS(M,I,A) #define STRING_cfS(M,I,A) ,sizeof(A) #define STRINGV_cfS(M,I,A) ,( (unsigned)0xFFFF*firstindexlength(A) \ +secondindexlength(A)) #define PSTRING_cfS(M,I,A) ,sizeof(A) #define PSTRINGV_cfS(M,I,A) STRINGV_cfS(M,I,A) #define ZTRINGV_cfS(M,I,A) #define PZTRINGV_cfS(M,I,A) #define HCF(TN,I) _(TN,_cfSTR)(3,H,cfCOMMA, H,_(C,I),0,0) #define HHCF(TN,I) _(TN,_cfSTR)(3,H,cfCOMMA,HH,_(C,I),0,0) #define HHHCF(TN,I) _(TN,_cfSTR)(3,H,cfCOLON, H,_(C,I),0,0) #define H_CF_SPECIAL CF_STRLENTYPE #define HH_CF_SPECIAL #define DEFAULT_cfH(M,I,A) #define LOGICAL_cfH(S,U,B) #define PLOGICAL_cfH(S,U,B) #define STRING_cfH(S,U,B) _(A,S) _(U,_CF_SPECIAL) B #define STRINGV_cfH(S,U,B) STRING_cfH(S,U,B) #define PSTRING_cfH(S,U,B) STRING_cfH(S,U,B) #define PSTRINGV_cfH(S,U,B) STRING_cfH(S,U,B) #define PNSTRING_cfH(S,U,B) STRING_cfH(S,U,B) #define PPSTRING_cfH(S,U,B) STRING_cfH(S,U,B) #define ZTRINGV_cfH(S,U,B) #define PZTRINGV_cfH(S,U,B) /* Need VOID_cfSTR because Absoft forced function types go through _cfSTR. */ /* No spaces inside expansion. They screws up macro catenation kludge. */ #define VOID_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOAT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICAL_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LOGICAL,A,B,C,D,E) #define LONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define SHORT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGLONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define SHORTV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PBYTE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PDOUBLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PFLOAT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PINT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PLOGICAL_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PLOGICAL,A,B,C,D,E) #define PLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PLONGLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define PSHORT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define STRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,STRING,A,B,C,D,E) #define PSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PSTRING,A,B,C,D,E) #define STRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,STRINGV,A,B,C,D,E) #define PSTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PSTRINGV,A,B,C,D,E) #define PNSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PNSTRING,A,B,C,D,E) #define PPSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PPSTRING,A,B,C,D,E) #define PVOID_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define ROUTINE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SIMPLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define ZTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,ZTRINGV,A,B,C,D,E) #define PZTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PZTRINGV,A,B,C,D,E) #define CF_0_cfSTR(N,T,A,B,C,D,E) /* See ACF table comments, which explain why CCF was split into two. */ #define CCF(NAME,TN,I) _(TN,_cfSTR)(5,C,NAME,I,_(A,I),_(B,I),_(C,I)) #define DEFAULT_cfC(M,I,A,B,C) #define LOGICAL_cfC(M,I,A,B,C) A=C2FLOGICAL( A); #define PLOGICAL_cfC(M,I,A,B,C) *A=C2FLOGICAL(*A); #ifdef vmsFortran #define STRING_cfC(M,I,A,B,C) (B.clen=strlen(A),B.f.dsc$a_pointer=A, \ C==sizeof(char*)||C==(unsigned)(B.clen+1)?B.f.dsc$w_length=B.clen: \ (memset((A)+B.clen,' ',C-B.clen-1),A[B.f.dsc$w_length=C-1]='\0')); /* PSTRING_cfC to beware of array A which does not contain any \0. */ #define PSTRING_cfC(M,I,A,B,C) (B.dsc$a_pointer=A, C==sizeof(char*) ? \ B.dsc$w_length=strlen(A): (A[C-1]='\0',B.dsc$w_length=strlen(A), \ memset((A)+B.dsc$w_length,' ',C-B.dsc$w_length-1), B.dsc$w_length=C-1)); #else #define STRING_cfC(M,I,A,B,C) (B.nombre=A,B.clen=strlen(A), \ C==sizeof(char*)||C==(unsigned)(B.clen+1)?B.flen=B.clen: \ (memset(B.nombre+B.clen,' ',C-B.clen-1),B.nombre[B.flen=C-1]='\0')); #define PSTRING_cfC(M,I,A,B,C) (C==sizeof(char*)? B=strlen(A): \ (A[C-1]='\0',B=strlen(A),memset((A)+B,' ',C-B-1),B=C-1)); #endif /* For CRAYFortran for (P)STRINGV_cfC, B.fs is set, but irrelevant. */ #define STRINGV_cfC(M,I,A,B,C) \ AATRINGV_cfA( A,B,(C/0xFFFF)*(C%0xFFFF),C/0xFFFF,C%0xFFFF) #define PSTRINGV_cfC(M,I,A,B,C) \ APATRINGV_cfA( A,B,(C/0xFFFF)*(C%0xFFFF),C/0xFFFF,C%0xFFFF) #define ZTRINGV_cfC(M,I,A,B,C) \ AATRINGV_cfA( A,B, (_3(M,_ELEMS_,I))*((_3(M,_ELEMLEN_,I))+1), \ (_3(M,_ELEMS_,I)), (_3(M,_ELEMLEN_,I))+1 ) #define PZTRINGV_cfC(M,I,A,B,C) \ APATRINGV_cfA( A,B, (_3(M,_ELEMS_,I))*((_3(M,_ELEMLEN_,I))+1), \ (_3(M,_ELEMS_,I)), (_3(M,_ELEMLEN_,I))+1 ) #define BYTE_cfCCC(A,B) &A #define DOUBLE_cfCCC(A,B) &A #if !defined(__CF__KnR) #define FLOAT_cfCCC(A,B) &A /* Although the VAX doesn't, at least the */ #else /* HP and K&R mips promote float arg.'s of */ #define FLOAT_cfCCC(A,B) &B /* unprototyped functions to double. Cannot */ #endif /* use A here to pass the argument to FORTRAN. */ #define INT_cfCCC(A,B) &A #define LOGICAL_cfCCC(A,B) &A #define LONG_cfCCC(A,B) &A #define SHORT_cfCCC(A,B) &A #define PBYTE_cfCCC(A,B) A #define PDOUBLE_cfCCC(A,B) A #define PFLOAT_cfCCC(A,B) A #define PINT_cfCCC(A,B) A #define PLOGICAL_cfCCC(A,B) B=A /* B used to keep a common W table. */ #define PLONG_cfCCC(A,B) A #define PSHORT_cfCCC(A,B) A #define CCCF(TN,I,M) _SEP_(TN,M,cfCOMMA) _Icf(3,CC,TN,_(A,I),_(B,I)) #define INT_cfCC(T,A,B) _(T,_cfCCC)(A,B) #define INTV_cfCC(T,A,B) A #define INTVV_cfCC(T,A,B) A #define INTVVV_cfCC(T,A,B) A #define INTVVVV_cfCC(T,A,B) A #define INTVVVVV_cfCC(T,A,B) A #define INTVVVVVV_cfCC(T,A,B) A #define INTVVVVVVV_cfCC(T,A,B) A #define PINT_cfCC(T,A,B) _(T,_cfCCC)(A,B) #define PVOID_cfCC(T,A,B) A #if defined(apolloFortran) || defined(hpuxFortran800) || defined(AbsoftUNIXFortran) #define ROUTINE_cfCC(T,A,B) &A #else #define ROUTINE_cfCC(T,A,B) A #endif #define SIMPLE_cfCC(T,A,B) A #ifdef vmsFortran #define STRING_cfCC(T,A,B) &B.f #define STRINGV_cfCC(T,A,B) &B #define PSTRING_cfCC(T,A,B) &B #define PSTRINGV_cfCC(T,A,B) &B #else #ifdef CRAYFortran #define STRING_cfCC(T,A,B) _cptofcd(A,B.flen) #define STRINGV_cfCC(T,A,B) _cptofcd(B.s,B.flen) #define PSTRING_cfCC(T,A,B) _cptofcd(A,B) #define PSTRINGV_cfCC(T,A,B) _cptofcd(A,B.flen) #else #define STRING_cfCC(T,A,B) A #define STRINGV_cfCC(T,A,B) B.fs #define PSTRING_cfCC(T,A,B) A #define PSTRINGV_cfCC(T,A,B) B.fs #endif #endif #define ZTRINGV_cfCC(T,A,B) STRINGV_cfCC(T,A,B) #define PZTRINGV_cfCC(T,A,B) PSTRINGV_cfCC(T,A,B) #define BYTE_cfX return A0; #define DOUBLE_cfX return A0; #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #define FLOAT_cfX return A0; #else #define FLOAT_cfX ASSIGNFLOAT(AA0,A0); return AA0; #endif #define INT_cfX return A0; #define LOGICAL_cfX return F2CLOGICAL(A0); #define LONG_cfX return A0; #define SHORT_cfX return A0; #define VOID_cfX return ; #if defined(vmsFortran) || defined(CRAYFortran) #define STRING_cfX return kill_trailing( \ kill_trailing(AA0,CFORTRAN_NON_CHAR),' '); #else #define STRING_cfX return kill_trailing( \ kill_trailing( A0,CFORTRAN_NON_CHAR),' '); #endif #define CFFUN(NAME) _(__cf__,NAME) /* Note that we don't use LN here, but we keep it for consistency. */ #define CCALLSFFUN0(UN,LN) CFFUN(UN)() #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define CCALLSFFUN1( UN,LN,T1, A1) \ CCALLSFFUN5 (UN,LN,T1,CF_0,CF_0,CF_0,CF_0,A1,0,0,0,0) #define CCALLSFFUN2( UN,LN,T1,T2, A1,A2) \ CCALLSFFUN5 (UN,LN,T1,T2,CF_0,CF_0,CF_0,A1,A2,0,0,0) #define CCALLSFFUN3( UN,LN,T1,T2,T3, A1,A2,A3) \ CCALLSFFUN5 (UN,LN,T1,T2,T3,CF_0,CF_0,A1,A2,A3,0,0) #define CCALLSFFUN4( UN,LN,T1,T2,T3,T4, A1,A2,A3,A4)\ CCALLSFFUN5 (UN,LN,T1,T2,T3,T4,CF_0,A1,A2,A3,A4,0) #define CCALLSFFUN5( UN,LN,T1,T2,T3,T4,T5, A1,A2,A3,A4,A5) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,0,0,0,0,0) #define CCALLSFFUN6( UN,LN,T1,T2,T3,T4,T5,T6, A1,A2,A3,A4,A5,A6) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,0,0,0,0) #define CCALLSFFUN7( UN,LN,T1,T2,T3,T4,T5,T6,T7, A1,A2,A3,A4,A5,A6,A7) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,0,0,0) #define CCALLSFFUN8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8, A1,A2,A3,A4,A5,A6,A7,A8) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,0,0) #define CCALLSFFUN9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,A1,A2,A3,A4,A5,A6,A7,A8,A9)\ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,0) #define CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,0,0,0,0) #define CCALLSFFUN11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,0,0,0) #define CCALLSFFUN12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,0,0) #define CCALLSFFUN13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,0) #define CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ ((CFFUN(UN)( BCF(T1,A1,0) BCF(T2,A2,1) BCF(T3,A3,1) BCF(T4,A4,1) BCF(T5,A5,1) \ BCF(T6,A6,1) BCF(T7,A7,1) BCF(T8,A8,1) BCF(T9,A9,1) BCF(TA,AA,1) \ BCF(TB,AB,1) BCF(TC,AC,1) BCF(TD,AD,1) BCF(TE,AE,1) \ SCF(T1,LN,1,A1) SCF(T2,LN,2,A2) SCF(T3,LN,3,A3) SCF(T4,LN,4,A4) \ SCF(T5,LN,5,A5) SCF(T6,LN,6,A6) SCF(T7,LN,7,A7) SCF(T8,LN,8,A8) \ SCF(T9,LN,9,A9) SCF(TA,LN,10,AA) SCF(TB,LN,11,AB) SCF(TC,LN,12,AC) \ SCF(TD,LN,13,AD) SCF(TE,LN,14,AE)))) /* N.B. Create a separate function instead of using (call function, function value here) because in order to create the variables needed for the input arg.'s which may be const.'s one has to do the creation within {}, but these can never be placed within ()'s. Therefore one must create wrapper functions. gcc, on the other hand may be able to avoid the wrapper functions. */ /* Prototypes are needed to correctly handle the value returned correctly. N.B. Can only have prototype arg.'s with difficulty, a la G... table since FORTRAN functions returning strings have extra arg.'s. Don't bother, since this only causes a compiler warning to come up when one uses FCALLSCFUNn and CCALLSFFUNn for the same function in the same source code. Something done by the experts in debugging only.*/ #define PROTOCCALLSFFUN0(F,UN,LN) \ _(F,_cfPU)( CFC_(UN,LN))(CF_NULL_PROTO); \ static _Icf(2,U,F,CFFUN(UN),0)() {_(F,_cfE) _Icf(3,GZ,F,UN,LN) ABSOFT_cf1(F));_(F,_cfX)} #define PROTOCCALLSFFUN1( T0,UN,LN,T1) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN2( T0,UN,LN,T1,T2) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN3( T0,UN,LN,T1,T2,T3) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,T3,CF_0,CF_0) #define PROTOCCALLSFFUN4( T0,UN,LN,T1,T2,T3,T4) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,T3,T4,CF_0) #define PROTOCCALLSFFUN5( T0,UN,LN,T1,T2,T3,T4,T5) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN6( T0,UN,LN,T1,T2,T3,T4,T5,T6) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN7( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN8( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0) #define PROTOCCALLSFFUN9( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0) #define PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN11(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN12(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) #define PROTOCCALLSFFUN13(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) /* HP/UX 9.01 cc requires the blank between '_Icf(3,G,T0,UN,LN) CCCF(T1,1,0)' */ #ifndef __CF__KnR #define PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _(T0,_cfPU)(CFC_(UN,LN))(CF_NULL_PROTO); static _Icf(2,U,T0,CFFUN(UN),0)( \ CFARGT14FS(UCF,HCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ { CFARGT14S(VCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfE) \ CCF(LN,T1,1) CCF(LN,T2,2) CCF(LN,T3,3) CCF(LN,T4,4) CCF(LN,T5,5) \ CCF(LN,T6,6) CCF(LN,T7,7) CCF(LN,T8,8) CCF(LN,T9,9) CCF(LN,TA,10) \ CCF(LN,TB,11) CCF(LN,TC,12) CCF(LN,TD,13) CCF(LN,TE,14) _Icf(3,G,T0,UN,LN) \ CFARGT14(CCCF,JCF,ABSOFT_cf1(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,A10,10) \ WCF(TB,A11,11) WCF(TC,A12,12) WCF(TD,A13,13) WCF(TE,A14,14) _(T0,_cfX)} #else #define PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _(T0,_cfPU)(CFC_(UN,LN))(CF_NULL_PROTO); static _Icf(2,U,T0,CFFUN(UN),0)( \ CFARGT14FS(UUCF,HHCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ CFARGT14FS(UUUCF,HHHCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ; \ { CFARGT14S(VCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfE) \ CCF(LN,T1,1) CCF(LN,T2,2) CCF(LN,T3,3) CCF(LN,T4,4) CCF(LN,T5,5) \ CCF(LN,T6,6) CCF(LN,T7,7) CCF(LN,T8,8) CCF(LN,T9,9) CCF(LN,TA,10) \ CCF(LN,TB,11) CCF(LN,TC,12) CCF(LN,TD,13) CCF(LN,TE,14) _Icf(3,G,T0,UN,LN) \ CFARGT14(CCCF,JCF,ABSOFT_cf1(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,A10,10) \ WCF(TB,A11,11) WCF(TC,A12,12) WCF(TD,A13,13) WCF(TE,A14,14) _(T0,_cfX)} #endif /*-------------------------------------------------------------------------*/ /* UTILITIES FOR FORTRAN TO CALL C ROUTINES */ #ifdef OLD_VAXC /* Prevent %CC-I-PARAMNOTUSED. */ #pragma nostandard #endif #if defined(vmsFortran) || defined(CRAYFortran) #define DCF(TN,I) #define DDCF(TN,I) #define DDDCF(TN,I) #else #define DCF(TN,I) HCF(TN,I) #define DDCF(TN,I) HHCF(TN,I) #define DDDCF(TN,I) HHHCF(TN,I) #endif #define QCF(TN,I) _(TN,_cfSTR)(1,Q,_(B,I), 0,0,0,0) #define DEFAULT_cfQ(B) #define LOGICAL_cfQ(B) #define PLOGICAL_cfQ(B) #define STRINGV_cfQ(B) char *B; unsigned int _(B,N); #define STRING_cfQ(B) char *B=NULL; #define PSTRING_cfQ(B) char *B=NULL; #define PSTRINGV_cfQ(B) STRINGV_cfQ(B) #define PNSTRING_cfQ(B) char *B=NULL; #define PPSTRING_cfQ(B) #ifdef __sgi /* Else SGI gives warning 182 contrary to its C LRM A.17.7 */ #define ROUTINE_orig *(void**)& #else #define ROUTINE_orig (void *) #endif #define ROUTINE_1 ROUTINE_orig #define ROUTINE_2 ROUTINE_orig #define ROUTINE_3 ROUTINE_orig #define ROUTINE_4 ROUTINE_orig #define ROUTINE_5 ROUTINE_orig #define ROUTINE_6 ROUTINE_orig #define ROUTINE_7 ROUTINE_orig #define ROUTINE_8 ROUTINE_orig #define ROUTINE_9 ROUTINE_orig #define ROUTINE_10 ROUTINE_orig #define ROUTINE_11 ROUTINE_orig #define ROUTINE_12 ROUTINE_orig #define ROUTINE_13 ROUTINE_orig #define ROUTINE_14 ROUTINE_orig #define ROUTINE_15 ROUTINE_orig #define ROUTINE_16 ROUTINE_orig #define ROUTINE_17 ROUTINE_orig #define ROUTINE_18 ROUTINE_orig #define ROUTINE_19 ROUTINE_orig #define ROUTINE_20 ROUTINE_orig #define ROUTINE_21 ROUTINE_orig #define ROUTINE_22 ROUTINE_orig #define ROUTINE_23 ROUTINE_orig #define ROUTINE_24 ROUTINE_orig #define ROUTINE_25 ROUTINE_orig #define ROUTINE_26 ROUTINE_orig #define ROUTINE_27 ROUTINE_orig #define TCF(NAME,TN,I,M) _SEP_(TN,M,cfCOMMA) _(TN,_cfT)(NAME,I,_(A,I),_(B,I),_(C,I)) #define BYTE_cfT(M,I,A,B,D) *A #define DOUBLE_cfT(M,I,A,B,D) *A #define FLOAT_cfT(M,I,A,B,D) *A #define INT_cfT(M,I,A,B,D) *A #define LOGICAL_cfT(M,I,A,B,D) F2CLOGICAL(*A) #define LONG_cfT(M,I,A,B,D) *A #define LONGLONG_cfT(M,I,A,B,D) *A /* added by MR December 2005 */ #define SHORT_cfT(M,I,A,B,D) *A #define BYTEV_cfT(M,I,A,B,D) A #define DOUBLEV_cfT(M,I,A,B,D) A #define FLOATV_cfT(M,I,A,B,D) VOIDP A #define INTV_cfT(M,I,A,B,D) A #define LOGICALV_cfT(M,I,A,B,D) A #define LONGV_cfT(M,I,A,B,D) A #define LONGLONGV_cfT(M,I,A,B,D) A /* added by MR December 2005 */ #define SHORTV_cfT(M,I,A,B,D) A #define BYTEVV_cfT(M,I,A,B,D) (void *)A /* We have to cast to void *,*/ #define BYTEVVV_cfT(M,I,A,B,D) (void *)A /* since we don't know the */ #define BYTEVVVV_cfT(M,I,A,B,D) (void *)A /* dimensions of the array. */ #define BYTEVVVVV_cfT(M,I,A,B,D) (void *)A /* i.e. Unfortunately, can't */ #define BYTEVVVVVV_cfT(M,I,A,B,D) (void *)A /* check that the type */ #define BYTEVVVVVVV_cfT(M,I,A,B,D) (void *)A /* matches the prototype. */ #define DOUBLEVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVVVVV_cfT(M,I,A,B,D) (void *)A #define INTVV_cfT(M,I,A,B,D) (void *)A #define INTVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVV_cfT(M,I,A,B,D) (void *)A #define LONGVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGLONGVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define SHORTVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVVVVV_cfT(M,I,A,B,D) (void *)A #define PBYTE_cfT(M,I,A,B,D) A #define PDOUBLE_cfT(M,I,A,B,D) A #define PFLOAT_cfT(M,I,A,B,D) VOIDP A #define PINT_cfT(M,I,A,B,D) A #define PLOGICAL_cfT(M,I,A,B,D) ((*A=F2CLOGICAL(*A)),A) #define PLONG_cfT(M,I,A,B,D) A #define PLONGLONG_cfT(M,I,A,B,D) A /* added by MR December 2005 */ #define PSHORT_cfT(M,I,A,B,D) A #define PVOID_cfT(M,I,A,B,D) A #if defined(apolloFortran) || defined(hpuxFortran800) || defined(AbsoftUNIXFortran) #define ROUTINE_cfT(M,I,A,B,D) _(ROUTINE_,I) (*A) #else #define ROUTINE_cfT(M,I,A,B,D) _(ROUTINE_,I) A #endif /* A == pointer to the characters D == length of the string, or of an element in an array of strings E == number of elements in an array of strings */ #define TTSTR( A,B,D) \ ((B=_cf_malloc(D+1))[D]='\0', memcpy(B,A,D), kill_trailing(B,' ')) #define TTTTSTR( A,B,D) (!(D<4||A[0]||A[1]||A[2]||A[3]))?NULL: \ memchr(A,'\0',D) ?A : TTSTR(A,B,D) #define TTTTSTRV( A,B,D,E) (_(B,N)=E,B=_cf_malloc(_(B,N)*(D+1)), (void *) \ vkill_trailing(f2cstrv(A,B,D+1, _(B,N)*(D+1)), D+1,_(B,N)*(D+1),' ')) #ifdef vmsFortran #define STRING_cfT(M,I,A,B,D) TTTTSTR( A->dsc$a_pointer,B,A->dsc$w_length) #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A->dsc$a_pointer, B, \ A->dsc$w_length , A->dsc$l_m[0]) #define PSTRING_cfT(M,I,A,B,D) TTSTR( A->dsc$a_pointer,B,A->dsc$w_length) #define PPSTRING_cfT(M,I,A,B,D) A->dsc$a_pointer #else #ifdef CRAYFortran #define STRING_cfT(M,I,A,B,D) TTTTSTR( _fcdtocp(A),B,_fcdlen(A)) #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(_fcdtocp(A),B,_fcdlen(A), \ num_elem(_fcdtocp(A),_fcdlen(A),_3(M,_STRV_A,I))) #define PSTRING_cfT(M,I,A,B,D) TTSTR( _fcdtocp(A),B,_fcdlen(A)) #define PPSTRING_cfT(M,I,A,B,D) _fcdtocp(A) #else #define STRING_cfT(M,I,A,B,D) TTTTSTR( A,B,D) #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A,B,D, num_elem(A,D,_3(M,_STRV_A,I))) #define PSTRING_cfT(M,I,A,B,D) TTSTR( A,B,D) #define PPSTRING_cfT(M,I,A,B,D) A #endif #endif #define PNSTRING_cfT(M,I,A,B,D) STRING_cfT(M,I,A,B,D) #define PSTRINGV_cfT(M,I,A,B,D) STRINGV_cfT(M,I,A,B,D) #define CF_0_cfT(M,I,A,B,D) #define RCF(TN,I) _(TN,_cfSTR)(3,R,_(A,I),_(B,I),_(C,I),0,0) #define DEFAULT_cfR(A,B,D) #define LOGICAL_cfR(A,B,D) #define PLOGICAL_cfR(A,B,D) *A=C2FLOGICAL(*A); #define STRING_cfR(A,B,D) if (B) _cf_free(B); #define STRINGV_cfR(A,B,D) _cf_free(B); /* A and D as defined above for TSTRING(V) */ #define RRRRPSTR( A,B,D) if (B) memcpy(A,B, _cfMIN(strlen(B),D)), \ (D>strlen(B)?memset(A+strlen(B),' ', D-strlen(B)):0), _cf_free(B); #define RRRRPSTRV(A,B,D) c2fstrv(B,A,D+1,(D+1)*_(B,N)), _cf_free(B); #ifdef vmsFortran #define PSTRING_cfR(A,B,D) RRRRPSTR( A->dsc$a_pointer,B,A->dsc$w_length) #define PSTRINGV_cfR(A,B,D) RRRRPSTRV(A->dsc$a_pointer,B,A->dsc$w_length) #else #ifdef CRAYFortran #define PSTRING_cfR(A,B,D) RRRRPSTR( _fcdtocp(A),B,_fcdlen(A)) #define PSTRINGV_cfR(A,B,D) RRRRPSTRV(_fcdtocp(A),B,_fcdlen(A)) #else #define PSTRING_cfR(A,B,D) RRRRPSTR( A,B,D) #define PSTRINGV_cfR(A,B,D) RRRRPSTRV(A,B,D) #endif #endif #define PNSTRING_cfR(A,B,D) PSTRING_cfR(A,B,D) #define PPSTRING_cfR(A,B,D) #define BYTE_cfFZ(UN,LN) INTEGER_BYTE FCALLSC_QUALIFIER fcallsc(UN,LN)( #define DOUBLE_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( #define INT_cfFZ(UN,LN) int FCALLSC_QUALIFIER fcallsc(UN,LN)( #define LOGICAL_cfFZ(UN,LN) int FCALLSC_QUALIFIER fcallsc(UN,LN)( #define LONG_cfFZ(UN,LN) long FCALLSC_QUALIFIER fcallsc(UN,LN)( #define LONGLONG_cfFZ(UN,LN) LONGLONG FCALLSC_QUALIFIER fcallsc(UN,LN)( /* added by MR December 2005 */ #define SHORT_cfFZ(UN,LN) short FCALLSC_QUALIFIER fcallsc(UN,LN)( #define VOID_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)( #ifndef __CF__KnR /* The void is req'd by the Apollo, to make this an ANSI function declaration. The Apollo promotes K&R float functions to double. */ #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)(void #else #define FLOAT_cfFZ(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)(void #endif #ifdef vmsFortran #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(fstring *AS #else #ifdef CRAYFortran #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(_fcd AS #else #if defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(char *AS #else #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(char *AS, unsigned D0 #endif #endif #endif #else #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( #else #define FLOAT_cfFZ(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)( #endif #else #define FLOAT_cfFZ(UN,LN) FLOATFUNCTIONTYPE FCALLSC_QUALIFIER fcallsc(UN,LN)( #endif #if defined(vmsFortran) || defined(CRAYFortran) || defined(AbsoftUNIXFortran) #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(AS #else #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(AS, D0 #endif #endif #define BYTE_cfF(UN,LN) BYTE_cfFZ(UN,LN) #define DOUBLE_cfF(UN,LN) DOUBLE_cfFZ(UN,LN) #ifndef __CF_KnR #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfF(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( #else #define FLOAT_cfF(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)( #endif #else #define FLOAT_cfF(UN,LN) FLOAT_cfFZ(UN,LN) #endif #define INT_cfF(UN,LN) INT_cfFZ(UN,LN) #define LOGICAL_cfF(UN,LN) LOGICAL_cfFZ(UN,LN) #define LONG_cfF(UN,LN) LONG_cfFZ(UN,LN) #define LONGLONG_cfF(UN,LN) LONGLONG_cfFZ(UN,LN) /* added by MR December 2005 */ #define SHORT_cfF(UN,LN) SHORT_cfFZ(UN,LN) #define VOID_cfF(UN,LN) VOID_cfFZ(UN,LN) #define STRING_cfF(UN,LN) STRING_cfFZ(UN,LN), #define INT_cfFF #define VOID_cfFF #ifdef vmsFortran #define STRING_cfFF fstring *AS; #else #ifdef CRAYFortran #define STRING_cfFF _fcd AS; #else #define STRING_cfFF char *AS; unsigned D0; #endif #endif #define INT_cfL A0= #define STRING_cfL A0= #define VOID_cfL #define INT_cfK #define VOID_cfK /* KSTRING copies the string into the position provided by the caller. */ #ifdef vmsFortran #define STRING_cfK \ memcpy(AS->dsc$a_pointer,A0,_cfMIN(AS->dsc$w_length,(A0==NULL?0:strlen(A0))));\ AS->dsc$w_length>(A0==NULL?0:strlen(A0))? \ memset(AS->dsc$a_pointer+(A0==NULL?0:strlen(A0)),' ', \ AS->dsc$w_length-(A0==NULL?0:strlen(A0))):0; #else #ifdef CRAYFortran #define STRING_cfK \ memcpy(_fcdtocp(AS),A0, _cfMIN(_fcdlen(AS),(A0==NULL?0:strlen(A0))) ); \ _fcdlen(AS)>(A0==NULL?0:strlen(A0))? \ memset(_fcdtocp(AS)+(A0==NULL?0:strlen(A0)),' ', \ _fcdlen(AS)-(A0==NULL?0:strlen(A0))):0; #else #define STRING_cfK memcpy(AS,A0, _cfMIN(D0,(A0==NULL?0:strlen(A0))) ); \ D0>(A0==NULL?0:strlen(A0))?memset(AS+(A0==NULL?0:strlen(A0)), \ ' ', D0-(A0==NULL?0:strlen(A0))):0; #endif #endif /* Note that K.. and I.. can't be combined since K.. has to access data before R.., in order for functions returning strings which are also passed in as arguments to work correctly. Note that R.. frees and hence may corrupt the string. */ #define BYTE_cfI return A0; #define DOUBLE_cfI return A0; #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #define FLOAT_cfI return A0; #else #define FLOAT_cfI RETURNFLOAT(A0); #endif #define INT_cfI return A0; #ifdef hpuxFortran800 /* Incredibly, functions must return true as 1, elsewhere .true.==0x01000000. */ #define LOGICAL_cfI return ((A0)?1:0); #else #define LOGICAL_cfI return C2FLOGICAL(A0); #endif #define LONG_cfI return A0; #define LONGLONG_cfI return A0; /* added by MR December 2005 */ #define SHORT_cfI return A0; #define STRING_cfI return ; #define VOID_cfI return ; #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define FCALLSCSUB0( CN,UN,LN) FCALLSCFUN0(VOID,CN,UN,LN) #define FCALLSCSUB1( CN,UN,LN,T1) FCALLSCFUN1(VOID,CN,UN,LN,T1) #define FCALLSCSUB2( CN,UN,LN,T1,T2) FCALLSCFUN2(VOID,CN,UN,LN,T1,T2) #define FCALLSCSUB3( CN,UN,LN,T1,T2,T3) FCALLSCFUN3(VOID,CN,UN,LN,T1,T2,T3) #define FCALLSCSUB4( CN,UN,LN,T1,T2,T3,T4) \ FCALLSCFUN4(VOID,CN,UN,LN,T1,T2,T3,T4) #define FCALLSCSUB5( CN,UN,LN,T1,T2,T3,T4,T5) \ FCALLSCFUN5(VOID,CN,UN,LN,T1,T2,T3,T4,T5) #define FCALLSCSUB6( CN,UN,LN,T1,T2,T3,T4,T5,T6) \ FCALLSCFUN6(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6) #define FCALLSCSUB7( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ FCALLSCFUN7(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) #define FCALLSCSUB8( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ FCALLSCFUN8(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) #define FCALLSCSUB9( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ FCALLSCFUN9(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) #define FCALLSCSUB10(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ FCALLSCFUN10(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) #define FCALLSCSUB11(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ FCALLSCFUN11(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) #define FCALLSCSUB12(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ FCALLSCFUN12(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) #define FCALLSCSUB13(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ FCALLSCFUN13(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) #define FCALLSCSUB14(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ FCALLSCFUN14(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define FCALLSCSUB15(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ FCALLSCFUN15(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) #define FCALLSCSUB16(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ FCALLSCFUN16(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) #define FCALLSCSUB17(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ FCALLSCFUN17(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) #define FCALLSCSUB18(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ FCALLSCFUN18(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) #define FCALLSCSUB19(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ FCALLSCFUN19(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) #define FCALLSCSUB20(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ FCALLSCFUN20(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define FCALLSCSUB21(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ FCALLSCFUN21(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) #define FCALLSCSUB22(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ FCALLSCFUN22(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) #define FCALLSCSUB23(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ FCALLSCFUN23(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) #define FCALLSCSUB24(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ FCALLSCFUN24(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) #define FCALLSCSUB25(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ FCALLSCFUN25(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) #define FCALLSCSUB26(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ FCALLSCFUN26(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) #define FCALLSCSUB27(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ FCALLSCFUN27(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #define FCALLSCFUN1( T0,CN,UN,LN,T1) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN2( T0,CN,UN,LN,T1,T2) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,CF_0,CF_0,CF_0) #define FCALLSCFUN3( T0,CN,UN,LN,T1,T2,T3) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,T3,CF_0,CF_0) #define FCALLSCFUN4( T0,CN,UN,LN,T1,T2,T3,T4) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,T3,T4,CF_0) #define FCALLSCFUN5( T0,CN,UN,LN,T1,T2,T3,T4,T5) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN6( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN7( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0) #define FCALLSCFUN8( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0) #define FCALLSCFUN9( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0) #define FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN11(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) #define FCALLSCFUN12(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) #define FCALLSCFUN13(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) #define FCALLSCFUN15(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN16(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN17(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0) #define FCALLSCFUN18(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0) #define FCALLSCFUN19(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0) #define FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN21(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN22(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN23(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN24(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0) #define FCALLSCFUN25(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0) #define FCALLSCFUN26(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0) #ifndef __CF__KnR #define FCALLSCFUN0(T0,CN,UN,LN) CFextern _(T0,_cfFZ)(UN,LN) ABSOFT_cf2(T0)) \ {_Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN(); _Icf(0,K,T0,0,0) _(T0,_cfI)} #define FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT14(NCF,DCF,ABSOFT_cf2(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ { CFARGT14S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) ); _Icf(0,K,T0,0,0) \ CFARGT14S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfI) } #define FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT27(NCF,DCF,ABSOFT_cf2(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) ) \ { CFARGT27S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) TCF(LN,TF,15,1) TCF(LN,TG,16,1) TCF(LN,TH,17,1) \ TCF(LN,TI,18,1) TCF(LN,TJ,19,1) TCF(LN,TK,20,1) TCF(LN,TL,21,1) TCF(LN,TM,22,1) \ TCF(LN,TN,23,1) TCF(LN,TO,24,1) TCF(LN,TP,25,1) TCF(LN,TQ,26,1) TCF(LN,TR,27,1) ); _Icf(0,K,T0,0,0) \ CFARGT27S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) _(T0,_cfI) } #else #define FCALLSCFUN0(T0,CN,UN,LN) CFextern _(T0,_cfFZ)(UN,LN) ABSOFT_cf3(T0)) _Icf(0,FF,T0,0,0)\ {_Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN(); _Icf(0,K,T0,0,0) _(T0,_cfI)} #define FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT14(NNCF,DDCF,ABSOFT_cf3(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)) _Icf(0,FF,T0,0,0) \ CFARGT14FS(NNNCF,DDDCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE); \ { CFARGT14S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) ); _Icf(0,K,T0,0,0) \ CFARGT14S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfI)} #define FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT27(NNCF,DDCF,ABSOFT_cf3(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)) _Icf(0,FF,T0,0,0) \ CFARGT27FS(NNNCF,DDDCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR); \ { CFARGT27S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) TCF(LN,TF,15,1) TCF(LN,TG,16,1) TCF(LN,TH,17,1) \ TCF(LN,TI,18,1) TCF(LN,TJ,19,1) TCF(LN,TK,20,1) TCF(LN,TL,21,1) TCF(LN,TM,22,1) \ TCF(LN,TN,23,1) TCF(LN,TO,24,1) TCF(LN,TP,25,1) TCF(LN,TQ,26,1) TCF(LN,TR,27,1) ); _Icf(0,K,T0,0,0) \ CFARGT27S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) _(T0,_cfI)} #endif #endif /* __CFORTRAN_LOADED */ cfitsio-4.3.1/region.h0000644000225700000360000000415513472024437014114 0ustar cagordonlhea/***************************************************************/ /* REGION STUFF */ /***************************************************************/ #include "fitsio.h" #define myPI 3.1415926535897932385 #define RadToDeg 180.0/myPI typedef struct { int exists; double xrefval, yrefval; double xrefpix, yrefpix; double xinc, yinc; double rot; char type[6]; } WCSdata; typedef enum { point_rgn, line_rgn, circle_rgn, annulus_rgn, ellipse_rgn, elliptannulus_rgn, box_rgn, boxannulus_rgn, rectangle_rgn, diamond_rgn, sector_rgn, poly_rgn, panda_rgn, epanda_rgn, bpanda_rgn } shapeType; typedef enum { pixel_fmt, degree_fmt, hhmmss_fmt } coordFmt; typedef struct { char sign; /* Include or exclude? */ shapeType shape; /* Shape of this region */ int comp; /* Component number for this region */ double xmin,xmax; /* bounding box */ double ymin,ymax; union { /* Parameters - In pixels */ /**** Generic Shape Data ****/ struct { double p[11]; /* Region parameters */ double sinT, cosT; /* For rotated shapes */ double a, b; /* Extra scratch area */ } gen; /**** Polygon Data ****/ struct { int nPts; /* Number of Polygon pts */ double *Pts; /* Polygon points */ } poly; } param; } RgnShape; typedef struct { int nShapes; RgnShape *Shapes; WCSdata wcs; } SAORegion; /* SAO region file routines */ int fits_read_rgnfile( const char *filename, WCSdata *wcs, SAORegion **Rgn, int *status ); int fits_in_region( double X, double Y, SAORegion *Rgn ); void fits_free_region( SAORegion *Rgn ); void fits_set_region_components ( SAORegion *Rgn ); void fits_setup_shape ( RgnShape *shape); int fits_read_fits_region ( fitsfile *fptr, WCSdata * wcs, SAORegion **Rgn, int *status); int fits_read_ascii_region ( const char *filename, WCSdata * wcs, SAORegion **Rgn, int *status); cfitsio-4.3.1/fitscore.c0000644000225700000360000116535314523041213014440 0ustar cagordonlhea/* This file, fitscore.c, contains the core set of FITSIO routines. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." */ #include #include #include #include #include #include /* stddef.h is apparently needed to define size_t with some compilers ?? */ #include #include #include "fitsio2.h" #define errmsgsiz 25 #define ESMARKER 27 /* Escape character is used as error stack marker */ #define DelAll 1 /* delete all messages on the error stack */ #define DelMark 2 /* delete newest messages back to and including marker */ #define DelNewest 3 /* delete the newest message from the stack */ #define GetMesg 4 /* pop and return oldest message, ignoring marks */ #define PutMesg 5 /* add a new message to the stack */ #define PutMark 6 /* add a marker to the stack */ #ifdef _REENTRANT /* Fitsio_Lock and Fitsio_Pthread_Status are declared in fitsio2.h. */ pthread_mutex_t Fitsio_Lock; int Fitsio_Pthread_Status = 0; #endif int STREAM_DRIVER = 0; struct lconv *lcxxx; /*--------------------------------------------------------------------------*/ float ffvers(float *version) /* IO - version number */ /* return the current version number of the FITSIO software Note that this method of calculation limits minor/micro fields to < 100. */ { *version = (float)CFITSIO_MAJOR + (float)(.01*CFITSIO_MINOR) + (float)(.0001*CFITSIO_MICRO); /* *version = 4.3.1 Nov 2023 Previous releases: *version = 4.3.0 Jul 2023 *version = 4.2.0 Nov 2022 *version = 4.1.0 Feb 2022 *version = 4.0.0 May 2021 *version = 3.49 Aug 2020 *version = 3.48 Apr 2020 *version = 3.47 May 2019 *version = 3.46 Oct 2018 *version = 3.45 May 2018 *version = 3.44 Apr 2018 *version = 3.43 Mar 2018 *version = 3.42 Mar 2017 *version = 3.41 Nov 2016 *version = 3.40 Oct 2016 *version = 3.39 Apr 2016 *version = 3.38 Feb 2016 *version = 3.37 3 Jun 2014 *version = 3.36 6 Dec 2013 *version = 3.35 23 May 2013 *version = 3.34 20 Mar 2013 *version = 3.33 14 Feb 2013 *version = 3.32 Oct 2012 *version = 3.31 18 Jul 2012 *version = 3.30 11 Apr 2012 *version = 3.29 22 Sep 2011 *version = 3.28 12 May 2011 *version = 3.27 3 Mar 2011 *version = 3.26 30 Dec 2010 *version = 3.25 9 June 2010 *version = 3.24 26 Jan 2010 *version = 3.23 7 Jan 2010 *version = 3.22 28 Oct 2009 *version = 3.21 24 Sep 2009 *version = 3.20 31 Aug 2009 *version = 3.18 12 May 2009 (beta version) *version = 3.14 18 Mar 2009 *version = 3.13 5 Jan 2009 *version = 3.12 8 Oct 2008 *version = 3.11 19 Sep 2008 *version = 3.10 20 Aug 2008 *version = 3.09 3 Jun 2008 *version = 3.08 15 Apr 2007 (internal release) *version = 3.07 5 Nov 2007 (internal release) *version = 3.06 27 Aug 2007 *version = 3.05 12 Jul 2007 (internal release) *version = 3.03 11 Dec 2006 *version = 3.02 18 Sep 2006 *version = 3.01 May 2006 included in FTOOLS 6.1 release *version = 3.006 20 Feb 2006 *version = 3.005 20 Dec 2005 (beta, in heasoft swift release *version = 3.004 16 Sep 2005 (beta, in heasoft swift release *version = 3.003 28 Jul 2005 (beta, in heasoft swift release *version = 3.002 15 Apr 2005 (beta) *version = 3.001 15 Mar 2005 (beta) released with heasoft 6.0 *version = 3.000 1 Mar 2005 (internal release only) *version = 2.51 2 Dec 2004 *version = 2.50 28 Jul 2004 *version = 2.49 11 Feb 2004 *version = 2.48 28 Jan 2004 *version = 2.470 18 Aug 2003 *version = 2.460 20 May 2003 *version = 2.450 30 Apr 2003 (internal release only) *version = 2.440 8 Jan 2003 *version = 2.430; 4 Nov 2002 *version = 2.420; 19 Jul 2002 *version = 2.410; 22 Apr 2002 used in ftools v5.2 *version = 2.401; 28 Jan 2002 *version = 2.400; 18 Jan 2002 *version = 2.301; 7 Dec 2001 *version = 2.300; 23 Oct 2001 *version = 2.204; 26 Jul 2001 *version = 2.203; 19 Jul 2001 used in ftools v5.1 *version = 2.202; 22 May 2001 *version = 2.201; 15 Mar 2001 *version = 2.200; 26 Jan 2001 *version = 2.100; 26 Sep 2000 *version = 2.037; 6 Jul 2000 *version = 2.036; 1 Feb 2000 *version = 2.035; 7 Dec 1999 (internal release only) *version = 2.034; 23 Nov 1999 *version = 2.033; 17 Sep 1999 *version = 2.032; 25 May 1999 *version = 2.031; 31 Mar 1999 *version = 2.030; 24 Feb 1999 *version = 2.029; 11 Feb 1999 *version = 2.028; 26 Jan 1999 *version = 2.027; 12 Jan 1999 *version = 2.026; 23 Dec 1998 *version = 2.025; 1 Dec 1998 *version = 2.024; 9 Nov 1998 *version = 2.023; 1 Nov 1998 first full release of V2.0 *version = 1.42; 30 Apr 1998 *version = 1.40; 6 Feb 1998 *version = 1.33; 16 Dec 1997 (internal release only) *version = 1.32; 21 Nov 1997 (internal release only) *version = 1.31; 4 Nov 1997 (internal release only) *version = 1.30; 11 Sep 1997 *version = 1.27; 3 Sep 1997 (internal release only) *version = 1.25; 2 Jul 1997 *version = 1.24; 2 May 1997 *version = 1.23; 24 Apr 1997 *version = 1.22; 18 Apr 1997 *version = 1.21; 26 Mar 1997 *version = 1.2; 29 Jan 1997 *version = 1.11; 04 Dec 1996 *version = 1.101; 13 Nov 1996 *version = 1.1; 6 Nov 1996 *version = 1.04; 17 Sep 1996 *version = 1.03; 20 Aug 1996 *version = 1.02; 15 Aug 1996 *version = 1.01; 12 Aug 1996 */ return(*version); } /*--------------------------------------------------------------------------*/ int ffflnm(fitsfile *fptr, /* I - FITS file pointer */ char *filename, /* O - name of the file */ int *status) /* IO - error status */ /* return the name of the FITS file */ { strcpy(filename,(fptr->Fptr)->filename); return(*status); } /*--------------------------------------------------------------------------*/ int ffflmd(fitsfile *fptr, /* I - FITS file pointer */ int *filemode, /* O - open mode of the file */ int *status) /* IO - error status */ /* return the access mode of the FITS file */ { *filemode = (fptr->Fptr)->writemode; return(*status); } /*--------------------------------------------------------------------------*/ void ffgerr(int status, /* I - error status value */ char *errtext) /* O - error message (max 30 char long + null) */ /* Return a short descriptive error message that corresponds to the input error status value. The message may be up to 30 characters long, plus the terminating null character. */ { errtext[0] = '\0'; if (status >= 0 && status < 300) { switch (status) { case 0: strcpy(errtext, "OK - no error"); break; case 1: strcpy(errtext, "non-CFITSIO program error"); break; case 101: strcpy(errtext, "same input and output files"); break; case 103: strcpy(errtext, "attempt to open too many files"); break; case 104: strcpy(errtext, "could not open the named file"); break; case 105: strcpy(errtext, "couldn't create the named file"); break; case 106: strcpy(errtext, "error writing to FITS file"); break; case 107: strcpy(errtext, "tried to move past end of file"); break; case 108: strcpy(errtext, "error reading from FITS file"); break; case 110: strcpy(errtext, "could not close the file"); break; case 111: strcpy(errtext, "array dimensions too big"); break; case 112: strcpy(errtext, "cannot write to readonly file"); break; case 113: strcpy(errtext, "could not allocate memory"); break; case 114: strcpy(errtext, "invalid fitsfile pointer"); break; case 115: strcpy(errtext, "NULL input pointer"); break; case 116: strcpy(errtext, "error seeking file position"); break; case 117: strcpy(errtext, "bad value for file download timeout setting"); break; case 121: strcpy(errtext, "invalid URL prefix"); break; case 122: strcpy(errtext, "too many I/O drivers"); break; case 123: strcpy(errtext, "I/O driver init failed"); break; case 124: strcpy(errtext, "no I/O driver for this URLtype"); break; case 125: strcpy(errtext, "parse error in input file URL"); break; case 126: strcpy(errtext, "parse error in range list"); break; case 151: strcpy(errtext, "bad argument (shared mem drvr)"); break; case 152: strcpy(errtext, "null ptr arg (shared mem drvr)"); break; case 153: strcpy(errtext, "no free shared memory handles"); break; case 154: strcpy(errtext, "share mem drvr not initialized"); break; case 155: strcpy(errtext, "IPC system error (shared mem)"); break; case 156: strcpy(errtext, "no memory (shared mem drvr)"); break; case 157: strcpy(errtext, "share mem resource deadlock"); break; case 158: strcpy(errtext, "lock file open/create failed"); break; case 159: strcpy(errtext, "can't resize share mem block"); break; case 201: strcpy(errtext, "header already has keywords"); break; case 202: strcpy(errtext, "keyword not found in header"); break; case 203: strcpy(errtext, "keyword number out of bounds"); break; case 204: strcpy(errtext, "keyword value is undefined"); break; case 205: strcpy(errtext, "string missing closing quote"); break; case 206: strcpy(errtext, "error in indexed keyword name"); break; case 207: strcpy(errtext, "illegal character in keyword"); break; case 208: strcpy(errtext, "required keywords out of order"); break; case 209: strcpy(errtext, "keyword value not positive int"); break; case 210: strcpy(errtext, "END keyword not found"); break; case 211: strcpy(errtext, "illegal BITPIX keyword value"); break; case 212: strcpy(errtext, "illegal NAXIS keyword value"); break; case 213: strcpy(errtext, "illegal NAXISn keyword value"); break; case 214: strcpy(errtext, "illegal PCOUNT keyword value"); break; case 215: strcpy(errtext, "illegal GCOUNT keyword value"); break; case 216: strcpy(errtext, "illegal TFIELDS keyword value"); break; case 217: strcpy(errtext, "negative table row size"); break; case 218: strcpy(errtext, "negative number of rows"); break; case 219: strcpy(errtext, "named column not found"); break; case 220: strcpy(errtext, "illegal SIMPLE keyword value"); break; case 221: strcpy(errtext, "first keyword not SIMPLE"); break; case 222: strcpy(errtext, "second keyword not BITPIX"); break; case 223: strcpy(errtext, "third keyword not NAXIS"); break; case 224: strcpy(errtext, "missing NAXISn keywords"); break; case 225: strcpy(errtext, "first keyword not XTENSION"); break; case 226: strcpy(errtext, "CHDU not an ASCII table"); break; case 227: strcpy(errtext, "CHDU not a binary table"); break; case 228: strcpy(errtext, "PCOUNT keyword not found"); break; case 229: strcpy(errtext, "GCOUNT keyword not found"); break; case 230: strcpy(errtext, "TFIELDS keyword not found"); break; case 231: strcpy(errtext, "missing TBCOLn keyword"); break; case 232: strcpy(errtext, "missing TFORMn keyword"); break; case 233: strcpy(errtext, "CHDU not an IMAGE extension"); break; case 234: strcpy(errtext, "illegal TBCOLn keyword value"); break; case 235: strcpy(errtext, "CHDU not a table extension"); break; case 236: strcpy(errtext, "column exceeds width of table"); break; case 237: strcpy(errtext, "more than 1 matching col. name"); break; case 241: strcpy(errtext, "row width not = field widths"); break; case 251: strcpy(errtext, "unknown FITS extension type"); break; case 252: strcpy(errtext, "1st key not SIMPLE or XTENSION"); break; case 253: strcpy(errtext, "END keyword is not blank"); break; case 254: strcpy(errtext, "Header fill area not blank"); break; case 255: strcpy(errtext, "Data fill area invalid"); break; case 261: strcpy(errtext, "illegal TFORM format code"); break; case 262: strcpy(errtext, "unknown TFORM datatype code"); break; case 263: strcpy(errtext, "illegal TDIMn keyword value"); break; case 264: strcpy(errtext, "invalid BINTABLE heap pointer"); break; default: strcpy(errtext, "unknown error status"); break; } } else if (status < 600) { switch(status) { case 301: strcpy(errtext, "illegal HDU number"); break; case 302: strcpy(errtext, "column number < 1 or > tfields"); break; case 304: strcpy(errtext, "negative byte address"); break; case 306: strcpy(errtext, "negative number of elements"); break; case 307: strcpy(errtext, "bad first row number"); break; case 308: strcpy(errtext, "bad first element number"); break; case 309: strcpy(errtext, "not an ASCII (A) column"); break; case 310: strcpy(errtext, "not a logical (L) column"); break; case 311: strcpy(errtext, "bad ASCII table datatype"); break; case 312: strcpy(errtext, "bad binary table datatype"); break; case 314: strcpy(errtext, "null value not defined"); break; case 317: strcpy(errtext, "not a variable length column"); break; case 320: strcpy(errtext, "illegal number of dimensions"); break; case 321: strcpy(errtext, "1st pixel no. > last pixel no."); break; case 322: strcpy(errtext, "BSCALE or TSCALn = 0."); break; case 323: strcpy(errtext, "illegal axis length < 1"); break; case 340: strcpy(errtext, "not group table"); break; case 341: strcpy(errtext, "HDU already member of group"); break; case 342: strcpy(errtext, "group member not found"); break; case 343: strcpy(errtext, "group not found"); break; case 344: strcpy(errtext, "bad group id"); break; case 345: strcpy(errtext, "too many HDUs tracked"); break; case 346: strcpy(errtext, "HDU alread tracked"); break; case 347: strcpy(errtext, "bad Grouping option"); break; case 348: strcpy(errtext, "identical pointers (groups)"); break; case 360: strcpy(errtext, "malloc failed in parser"); break; case 361: strcpy(errtext, "file read error in parser"); break; case 362: strcpy(errtext, "null pointer arg (parser)"); break; case 363: strcpy(errtext, "empty line (parser)"); break; case 364: strcpy(errtext, "cannot unread > 1 line"); break; case 365: strcpy(errtext, "parser too deeply nested"); break; case 366: strcpy(errtext, "file open failed (parser)"); break; case 367: strcpy(errtext, "hit EOF (parser)"); break; case 368: strcpy(errtext, "bad argument (parser)"); break; case 369: strcpy(errtext, "unexpected token (parser)"); break; case 401: strcpy(errtext, "bad int to string conversion"); break; case 402: strcpy(errtext, "bad float to string conversion"); break; case 403: strcpy(errtext, "keyword value not integer"); break; case 404: strcpy(errtext, "keyword value not logical"); break; case 405: strcpy(errtext, "keyword value not floating pt"); break; case 406: strcpy(errtext, "keyword value not double"); break; case 407: strcpy(errtext, "bad string to int conversion"); break; case 408: strcpy(errtext, "bad string to float conversion"); break; case 409: strcpy(errtext, "bad string to double convert"); break; case 410: strcpy(errtext, "illegal datatype code value"); break; case 411: strcpy(errtext, "illegal no. of decimals"); break; case 412: strcpy(errtext, "datatype conversion overflow"); break; case 413: strcpy(errtext, "error compressing image"); break; case 414: strcpy(errtext, "error uncompressing image"); break; case 420: strcpy(errtext, "bad date or time conversion"); break; case 431: strcpy(errtext, "syntax error in expression"); break; case 432: strcpy(errtext, "expression result wrong type"); break; case 433: strcpy(errtext, "vector result too large"); break; case 434: strcpy(errtext, "missing output column"); break; case 435: strcpy(errtext, "bad data in parsed column"); break; case 436: strcpy(errtext, "output extension of wrong type"); break; case 501: strcpy(errtext, "WCS angle too large"); break; case 502: strcpy(errtext, "bad WCS coordinate"); break; case 503: strcpy(errtext, "error in WCS calculation"); break; case 504: strcpy(errtext, "bad WCS projection type"); break; case 505: strcpy(errtext, "WCS keywords not found"); break; default: strcpy(errtext, "unknown error status"); break; } } else { strcpy(errtext, "unknown error status"); } return; } /*--------------------------------------------------------------------------*/ void ffpmsg(const char *err_message) /* put message on to error stack */ { ffxmsg(PutMesg, (char *)err_message); return; } /*--------------------------------------------------------------------------*/ void ffpmrk(void) /* write a marker to the stack. It is then possible to pop only those messages following the marker off of the stack, leaving the previous messages unaffected. The marker is ignored by the ffgmsg routine. */ { char *dummy = 0; ffxmsg(PutMark, dummy); return; } /*--------------------------------------------------------------------------*/ int ffgmsg(char *err_message) /* get oldest message from error stack, ignoring markers */ { ffxmsg(GetMesg, err_message); return(*err_message); } /*--------------------------------------------------------------------------*/ void ffcmsg(void) /* erase all messages in the error stack */ { char *dummy = 0; ffxmsg(DelAll, dummy); return; } /*--------------------------------------------------------------------------*/ void ffcmrk(void) /* erase newest messages in the error stack, stopping if a marker is found. The marker is also erased in this case. */ { char *dummy = 0; ffxmsg(DelMark, dummy); return; } /*--------------------------------------------------------------------------*/ void ffxmsg( int action, char *errmsg) /* general routine to get, put, or clear the error message stack. Use a static array rather than allocating memory as needed for the error messages because it is likely to be more efficient and simpler to implement. Action Code: DelAll 1 delete all messages on the error stack DelMark 2 delete messages back to and including the 1st marker DelNewest 3 delete the newest message from the stack GetMesg 4 pop and return oldest message, ignoring marks PutMesg 5 add a new message to the stack PutMark 6 add a marker to the stack */ { int ii; char markflag; static char *txtbuff[errmsgsiz], *tmpbuff, *msgptr; static char errbuff[errmsgsiz][81]; /* initialize all = \0 */ static int nummsg = 0; FFLOCK; if (action == DelAll) /* clear the whole message stack */ { for (ii = 0; ii < nummsg; ii ++) *txtbuff[ii] = '\0'; nummsg = 0; } else if (action == DelMark) /* clear up to and including first marker */ { while (nummsg > 0) { nummsg--; markflag = *txtbuff[nummsg]; /* store possible marker character */ *txtbuff[nummsg] = '\0'; /* clear the buffer for this msg */ if (markflag == ESMARKER) break; /* found a marker, so quit */ } } else if (action == DelNewest) /* remove newest message from stack */ { if (nummsg > 0) { nummsg--; *txtbuff[nummsg] = '\0'; /* clear the buffer for this msg */ } } else if (action == GetMesg) /* pop and return oldest message from stack */ { /* ignoring markers */ while (nummsg > 0) { strcpy(errmsg, txtbuff[0]); /* copy oldest message to output */ *txtbuff[0] = '\0'; /* clear the buffer for this msg */ nummsg--; for (ii = 0; ii < nummsg; ii++) txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ if (errmsg[0] != ESMARKER) { /* quit if this is not a marker */ FFUNLOCK; return; } } errmsg[0] = '\0'; /* no messages in the stack */ } else if (action == PutMesg) /* add new message to stack */ { msgptr = errmsg; while (strlen(msgptr)) { if (nummsg == errmsgsiz) { tmpbuff = txtbuff[0]; /* buffers full; reuse oldest buffer */ *txtbuff[0] = '\0'; /* clear the buffer for this msg */ nummsg--; for (ii = 0; ii < nummsg; ii++) txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ txtbuff[nummsg] = tmpbuff; /* set pointer for the new message */ } else { for (ii = 0; ii < errmsgsiz; ii++) { if (*errbuff[ii] == '\0') /* find first empty buffer */ { txtbuff[nummsg] = errbuff[ii]; break; } } } strncat(txtbuff[nummsg], msgptr, 80); nummsg++; msgptr += minvalue(80, strlen(msgptr)); } } else if (action == PutMark) /* put a marker on the stack */ { if (nummsg == errmsgsiz) { tmpbuff = txtbuff[0]; /* buffers full; reuse oldest buffer */ *txtbuff[0] = '\0'; /* clear the buffer for this msg */ nummsg--; for (ii = 0; ii < nummsg; ii++) txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ txtbuff[nummsg] = tmpbuff; /* set pointer for the new message */ } else { for (ii = 0; ii < errmsgsiz; ii++) { if (*errbuff[ii] == '\0') /* find first empty buffer */ { txtbuff[nummsg] = errbuff[ii]; break; } } } *txtbuff[nummsg] = ESMARKER; /* write the marker */ *(txtbuff[nummsg] + 1) = '\0'; nummsg++; } FFUNLOCK; return; } /*--------------------------------------------------------------------------*/ int ffpxsz(int datatype) /* return the number of bytes per pixel associated with the datatype */ { if (datatype == TBYTE) return(sizeof(char)); else if (datatype == TUSHORT) return(sizeof(short)); else if (datatype == TSHORT) return(sizeof(short)); else if (datatype == TULONG) return(sizeof(long)); else if (datatype == TLONG) return(sizeof(long)); else if (datatype == TINT) return(sizeof(int)); else if (datatype == TUINT) return(sizeof(int)); else if (datatype == TFLOAT) return(sizeof(float)); else if (datatype == TDOUBLE) return(sizeof(double)); else if (datatype == TLOGICAL) return(sizeof(char)); else return(0); } /*--------------------------------------------------------------------------*/ int fftkey(const char *keyword, /* I - keyword name */ int *status) /* IO - error status */ /* Test that the keyword name conforms to the FITS standard. Must contain only capital letters, digits, minus or underscore chars. Trailing spaces are allowed. If the input status value is less than zero, then the test is modified so that upper or lower case letters are allowed, and no error messages are printed if the keyword is not legal. */ { size_t maxchr, ii; int spaces=0; char msg[FLEN_ERRMSG], testchar; if (*status > 0) /* inherit input status value if > 0 */ return(*status); maxchr=strlen(keyword); if (maxchr > 8) maxchr = 8; for (ii = 0; ii < maxchr; ii++) { if (*status == 0) testchar = keyword[ii]; else testchar = toupper(keyword[ii]); if ( (testchar >= 'A' && testchar <= 'Z') || (testchar >= '0' && testchar <= '9') || testchar == '-' || testchar == '_' ) { if (spaces) { if (*status == 0) { /* don't print error message if status < 0 */ snprintf(msg, FLEN_ERRMSG, "Keyword name contains embedded space(s): %.8s", keyword); ffpmsg(msg); } return(*status = BAD_KEYCHAR); } } else if (keyword[ii] == ' ') spaces = 1; else { if (*status == 0) { /* don't print error message if status < 0 */ snprintf(msg, FLEN_ERRMSG,"Character %d in this keyword is illegal: %.8s", (int) (ii+1), keyword); ffpmsg(msg); /* explicitly flag the 2 most common cases */ if (keyword[ii] == 0) ffpmsg(" (This a NULL (0) character)."); else if (keyword[ii] == 9) ffpmsg(" (This an ASCII TAB (9) character)."); } return(*status = BAD_KEYCHAR); } } return(*status); } /*--------------------------------------------------------------------------*/ int fftrec(char *card, /* I - keyword card to test */ int *status) /* IO - error status */ /* Test that the keyword card conforms to the FITS standard. Must contain only printable ASCII characters; */ { size_t ii, maxchr; char msg[FLEN_ERRMSG]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); maxchr = strlen(card); for (ii = 8; ii < maxchr; ii++) { if (card[ii] < 32 || card[ii] > 126) { snprintf(msg, FLEN_ERRMSG, "Character %d in this keyword is illegal. Hex Value = %X", (int) (ii+1), (int) card[ii] ); if (card[ii] == 0) strncat(msg, " (NULL char.)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 9) strncat(msg, " (TAB char.)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 10) strncat(msg, " (Line Feed char.)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 11) strncat(msg, " (Vertical Tab)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 12) strncat(msg, " (Form Feed char.)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 13) strncat(msg, " (Carriage Return)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 27) strncat(msg, " (Escape char.)",FLEN_ERRMSG-strlen(msg)-1); else if (card[ii] == 127) strncat(msg, " (Delete char.)",FLEN_ERRMSG-strlen(msg)-1); ffpmsg(msg); strncpy(msg, card, 80); msg[80] = '\0'; ffpmsg(msg); return(*status = BAD_KEYCHAR); } } return(*status); } /*--------------------------------------------------------------------------*/ void ffupch(char *string) /* convert string to upper case, in place. */ { size_t len, ii; len = strlen(string); for (ii = 0; ii < len; ii++) string[ii] = toupper(string[ii]); return; } /*--------------------------------------------------------------------------*/ int ffmkky(const char *keyname, /* I - keyword name */ char *value, /* I - keyword value */ const char *comm, /* I - keyword comment */ char *card, /* O - constructed keyword card */ int *status) /* IO - status value */ /* Make a complete FITS 80-byte keyword card from the input name, value and comment strings. Output card is null terminated without any trailing blanks. */ { size_t namelen, len, ii; char tmpname[FLEN_KEYWORD], tmpname2[FLEN_KEYWORD],*cptr; char *saveptr; int tstatus = -1, nblank = 0, ntoken = 0, maxlen = 0, specialchar = 0; if (*status > 0) return(*status); *tmpname = '\0'; *tmpname2 = '\0'; *card = '\0'; /* skip leading blanks in the name */ while(*(keyname + nblank) == ' ') nblank++; strncat(tmpname, keyname + nblank, FLEN_KEYWORD - 1); len = strlen(value); namelen = strlen(tmpname); /* delete non-significant trailing blanks in the name */ if (namelen) { cptr = tmpname + namelen - 1; while(*cptr == ' ') { *cptr = '\0'; cptr--; } namelen = cptr - tmpname + 1; } /* check that the name does not contain an '=' (equals sign) */ if (strchr(tmpname, '=') ) { ffpmsg("Illegal keyword name; contains an equals sign (=)"); ffpmsg(tmpname); return(*status = BAD_KEYCHAR); } if (namelen <= 8 && fftkey(tmpname, &tstatus) <= 0 ) { /* a normal 8-char (or less) FITS keyword. */ strcat(card, tmpname); /* copy keyword name to buffer */ for (ii = namelen; ii < 8; ii++) card[ii] = ' '; /* pad keyword name with spaces */ card[8] = '='; /* append '= ' in columns 9-10 */ card[9] = ' '; card[10] = '\0'; /* terminate the partial string */ namelen = 10; } else if ((FSTRNCMP(tmpname, "HIERARCH ", 9) == 0) || (FSTRNCMP(tmpname, "hierarch ", 9) == 0) ) { /* this is an explicit ESO HIERARCH keyword */ strcat(card, tmpname); /* copy keyword name to buffer */ if (namelen + 3 + len > 80) { /* save 1 char by not putting a space before the equals sign */ strcat(card, "= "); namelen += 2; } else { strcat(card, " = "); namelen += 3; } } else { /* scan the keyword name to determine the number and max length of the tokens */ /* and test if any of the tokens contain nonstandard characters */ strncat(tmpname2, tmpname, FLEN_KEYWORD - 1); cptr = ffstrtok(tmpname2, " ",&saveptr); while (cptr) { if (strlen(cptr) > maxlen) maxlen = strlen(cptr); /* find longest token */ /* name contains special characters? */ tstatus = -1; /* suppress any error message */ if (fftkey(cptr, &tstatus) > 0) specialchar = 1; cptr = ffstrtok(NULL, " ",&saveptr); ntoken++; } tstatus = -1; /* suppress any error message */ /* if (ntoken > 1) { */ if (ntoken > 0) { /* temporarily change so that this case should always be true */ /* for now at least, treat all cases as an implicit ESO HIERARCH keyword. */ /* This could change if FITS is ever expanded to directly support longer keywords. */ if (namelen + 11 > FLEN_CARD-1) { ffpmsg( "The following keyword is too long to fit on a card:"); ffpmsg(keyname); return(*status = BAD_KEYCHAR); } strcat(card, "HIERARCH "); strcat(card, tmpname); namelen += 9; if (namelen + 3 + len > 80) { /* save 1 char by not putting a space before the equals sign */ strcat(card, "= "); namelen += 2; } else { strcat(card, " = "); namelen += 3; } } else if ((fftkey(tmpname, &tstatus) <= 0)) { /* should never get here (at least for now) */ /* allow keyword names longer than 8 characters */ strncat(card, tmpname, FLEN_KEYWORD - 1); strcat(card, "= "); namelen += 2; } else { /* should never get here (at least for now) */ ffpmsg("Illegal keyword name:"); ffpmsg(tmpname); return(*status = BAD_KEYCHAR); } } if (len > 0) /* now process the value string */ { if (value[0] == '\'') /* is this a quoted string value? */ { if (namelen > 77) { ffpmsg( "The following keyword + value is too long to fit on a card:"); ffpmsg(keyname); ffpmsg(value); return(*status = BAD_KEYCHAR); } strncat(card, value, 80 - namelen); /* append the value string */ len = minvalue(80, namelen + len); /* restore the closing quote if it got truncated */ if (len == 80) { card[79] = '\''; } if (comm) { if (comm[0] != 0) { if (len < 30) { for (ii = len; ii < 30; ii++) card[ii] = ' '; /* fill with spaces to col 30 */ card[30] = '\0'; len = 30; } } } } else { if (namelen + len > 80) { ffpmsg( "The following keyword + value is too long to fit on a card:"); ffpmsg(keyname); ffpmsg(value); return(*status = BAD_KEYCHAR); } else if (namelen + len < 30) { /* add spaces so field ends at least in col 30 */ strncat(card, " ", 30 - (namelen + len)); } strncat(card, value, 80 - namelen); /* append the value string */ len = minvalue(80, namelen + len); len = maxvalue(30, len); } if (comm) { if ((len < 77) && ( strlen(comm) > 0) ) /* room for a comment? */ { strcat(card, " / "); /* append comment separator */ strncat(card, comm, 77 - len); /* append comment (what fits) */ } } } else { if (namelen == 10) /* This case applies to normal keywords only */ { card[8] = ' '; /* keywords with no value have no '=' */ if (comm) { strncat(card, comm, 80 - namelen); /* append comment (what fits) */ } } } /* issue a warning if this keyword does not strictly conform to the standard HIERARCH convention, which requires, 1) at least 2 tokens in the name, 2) no tokens longer than 8 characters, and 3) no special characters in any of the tokens */ if (ntoken == 1 || specialchar == 1) { ffpmsg("Warning: the following keyword does not conform to the HIERARCH convention"); /* ffpmsg(" (e.g., name is not hierarchical or contains non-standard characters)."); */ ffpmsg(card); } return(*status); } /*--------------------------------------------------------------------------*/ int ffmkey(fitsfile *fptr, /* I - FITS file pointer */ const char *card, /* I - card string value */ int *status) /* IO - error status */ /* replace the previously read card (i.e. starting 80 bytes before the (fptr->Fptr)->nextkey position) with the contents of the input card. */ { char tcard[81]; size_t len, ii; int keylength = 8; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); strncpy(tcard,card,80); tcard[80] = '\0'; len = strlen(tcard); /* silently replace any illegal characters with a space */ for (ii=0; ii < len; ii++) if (tcard[ii] < ' ' || tcard[ii] > 126) tcard[ii] = ' '; for (ii=len; ii < 80; ii++) /* fill card with spaces if necessary */ tcard[ii] = ' '; keylength = strcspn(tcard, "="); if (keylength == 80) keylength = 8; for (ii=0; ii < keylength; ii++) /* make sure keyword name is uppercase */ tcard[ii] = toupper(tcard[ii]); fftkey(tcard, status); /* test keyword name contains legal chars */ /* no need to do this any more, since any illegal characters have been removed fftrec(tcard, status); */ /* test rest of keyword for legal chars */ /* move position of keyword to be over written */ ffmbyt(fptr, ((fptr->Fptr)->nextkey) - 80, REPORT_EOF, status); ffpbyt(fptr, 80, tcard, status); /* write the 80 byte card */ return(*status); } /*--------------------------------------------------------------------------*/ int ffkeyn(const char *keyroot, /* I - root string for keyword name */ int value, /* I - index number to be appended to root name */ char *keyname, /* O - output root + index keyword name */ int *status) /* IO - error status */ /* Construct a keyword name string by appending the index number to the root. e.g., if root = "TTYPE" and value = 12 then keyname = "TTYPE12". */ { char suffix[16]; size_t rootlen; keyname[0] = '\0'; /* initialize output name to null */ rootlen = strlen(keyroot); if (rootlen == 0 || value < 0 ) return(*status = 206); snprintf(suffix, 16, "%d", value); /* construct keyword suffix */ strcpy(keyname, keyroot); /* copy root string to name string */ while (rootlen > 0 && keyname[rootlen - 1] == ' ') { rootlen--; /* remove trailing spaces in root name */ keyname[rootlen] = '\0'; } if (strlen(suffix) + strlen(keyname) > 8) return (*status=206); strcat(keyname, suffix); /* append suffix to the root */ return(*status); } /*--------------------------------------------------------------------------*/ int ffnkey(int value, /* I - index number to be appended to root name */ const char *keyroot, /* I - root string for keyword name */ char *keyname, /* O - output root + index keyword name */ int *status) /* IO - error status */ /* Construct a keyword name string by appending the root string to the index number. e.g., if root = "TTYPE" and value = 12 then keyname = "12TTYPE". */ { size_t rootlen; keyname[0] = '\0'; /* initialize output name to null */ rootlen = strlen(keyroot); if (rootlen == 0 || rootlen > 7 || value < 0 ) return(*status = 206); snprintf(keyname, FLEN_VALUE,"%d", value); /* construct keyword prefix */ if (rootlen + strlen(keyname) > 8) return(*status = 206); strcat(keyname, keyroot); /* append root to the prefix */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpsvc(char *card, /* I - FITS header card (nominally 80 bytes long) */ char *value, /* O - value string parsed from the card */ char *comm, /* O - comment string parsed from the card */ int *status) /* IO - error status */ /* ParSe the Value and Comment strings from the input header card string. If the card contains a quoted string value, the returned value string includes the enclosing quote characters. If comm = NULL, don't return the comment string. */ { int jj; size_t ii, cardlen, nblank, valpos; char strbuf[21]; if (*status > 0) return(*status); value[0] = '\0'; if (comm) comm[0] = '\0'; cardlen = strlen(card); if (cardlen >= FLEN_CARD) { strncpy(strbuf,card,20); strbuf[20]='\0'; ffpmsg("The card string starting with the chars below is too long:"); ffpmsg(strbuf); return(*status = BAD_KEYCHAR); } /* support for ESO HIERARCH keywords; find the '=' */ if (FSTRNCMP(card, "HIERARCH ", 9) == 0) { valpos = strcspn(card, "="); if (valpos == cardlen) /* no value indicator ??? */ { if (comm != NULL) { if (cardlen > 8) { strcpy(comm, &card[8]); jj=cardlen - 8; for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); /* no value indicator */ } valpos++; /* point to the position after the '=' */ } else if (cardlen < 9 || FSTRNCMP(card, "COMMENT ", 8) == 0 || /* keywords with no value */ FSTRNCMP(card, "HISTORY ", 8) == 0 || FSTRNCMP(card, "END ", 8) == 0 || FSTRNCMP(card, "CONTINUE", 8) == 0 || FSTRNCMP(card, " ", 8) == 0 ) { /* no value, so the comment extends from cols 9 - 80 */ if (comm != NULL) { if (cardlen > 8) { strcpy(comm, &card[8]); jj=cardlen - 8; for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); } else if (FSTRNCMP(&card[8], "= ", 2) == 0 ) { /* normal keyword with '= ' in cols 9-10 */ valpos = 10; /* starting position of the value field */ } else { valpos = strcspn(card, "="); if (valpos == cardlen) /* no value indicator ??? */ { if (comm != NULL) { if (cardlen > 8) { strcpy(comm, &card[8]); jj=cardlen - 8; for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); /* no value indicator */ } valpos++; /* point to the position after the '=' */ } nblank = strspn(&card[valpos], " "); /* find number of leading blanks */ if (nblank + valpos == cardlen) { /* the absence of a value string is legal, and simply indicates that the keyword value is undefined. Don't write an error message in this case. */ return(*status); } ii = valpos + nblank; if (card[ii] == '/' ) /* slash indicates start of the comment */ { ii++; } else if (card[ii] == '\'' ) /* is this a quoted string value? */ { value[0] = card[ii]; for (jj=1, ii++; ii < cardlen && jj < FLEN_VALUE-1; ii++, jj++) { if (card[ii] == '\'') /* is this the closing quote? */ { if (card[ii+1] == '\'') /* 2 successive quotes? */ { value[jj] = card[ii]; ii++; jj++; } else { value[jj] = card[ii]; break; /* found the closing quote, so exit this loop */ } } value[jj] = card[ii]; /* copy the next character to the output */ } if (ii == cardlen || jj == FLEN_VALUE-1) { jj = minvalue(jj, FLEN_VALUE-2); /* don't exceed 70 char string length */ value[jj] = '\''; /* close the bad value string */ value[jj+1] = '\0'; /* terminate the bad value string */ ffpmsg("This keyword string value has no closing quote:"); ffpmsg(card); /* May 2008 - modified to not fail on this minor error */ /* return(*status = NO_QUOTE); */ } else { value[jj+1] = '\0'; /* terminate the good value string */ ii++; /* point to the character following the value */ } } else if (card[ii] == '(' ) /* is this a complex value? */ { nblank = strcspn(&card[ii], ")" ); /* find closing ) */ if (nblank == strlen( &card[ii] ) || nblank >= FLEN_VALUE-1 ) { ffpmsg("This complex keyword value has no closing ')' within range:"); ffpmsg(card); return(*status = NO_QUOTE); } nblank++; strncpy(value, &card[ii], nblank); value[nblank] = '\0'; ii = ii + nblank; } else /* an integer, floating point, or logical FITS value string */ { nblank = strcspn(&card[ii], " /"); /* find the end of the token */ if (nblank >= FLEN_VALUE) /* This should not happen for correct input */ nblank = FLEN_VALUE-1; strncpy(value, &card[ii], nblank); value[nblank] = '\0'; ii = ii + nblank; } /* now find the comment string, if any */ if (comm) { nblank = strspn(&card[ii], " "); /* find next non-space character */ ii = ii + nblank; if (ii < 80) { if (card[ii] == '/') /* ignore the slash separator */ { ii++; if (card[ii] == ' ') /* also ignore the following space */ ii++; } strncpy(comm, &card[ii],FLEN_COMMENT-1); /* copy the remaining characters */ comm[FLEN_COMMENT-1] = '\0'; jj=strlen(comm); for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgthd(char *tmplt, /* I - input header template string */ char *card, /* O - returned FITS header record */ int *hdtype, /* O - how to interpreter the returned card string */ /* -2 = modify the name of a keyword; the old keyword name is returned starting at address chars[0]; the new name is returned starting at address char[40] (to be consistent with the Fortran version). Both names are null terminated. -1 = card contains the name of a keyword that is to be deleted 0 = append this keyword if it doesn't already exist, or modify the value if the keyword already exists. 1 = append this comment keyword ('HISTORY', 'COMMENT', or blank keyword name) 2 = this is the END keyword; do not write it to the header */ int *status) /* IO - error status */ /* 'Get Template HeaDer' parse a template header line and create a formated character string which is suitable for appending to a FITS header */ { char keyname[FLEN_KEYWORD], value[140], comment[140]; char *tok, *suffix, *loc, tvalue[140]; int len, vlen, more, tstatus, lentok1=0, remainlen=0; double dval; if (*status > 0) return(*status); card[0] = '\0'; *hdtype = 0; if (!FSTRNCMP(tmplt, " ", 8) ) { /* if first 8 chars of template are blank, then this is a comment */ strncat(card, tmplt, 80); *hdtype = 1; return(*status); } tok = tmplt; /* point to start of template string */ keyname[0] = '\0'; value[0] = '\0'; comment[0] = '\0'; len = strspn(tok, " "); /* no. of spaces before keyword */ tok += len; /* test for pecular case where token is a string of dashes */ if (strncmp(tok, "--------------------", 20) == 0) return(*status = BAD_KEYCHAR); if (tok[0] == '-') /* is there a leading minus sign? */ { /* first token is name of keyword to be deleted or renamed */ *hdtype = -1; tok++; len = strspn(tok, " "); /* no. of spaces before keyword */ tok += len; len = strcspn(tok, " =+"); /* length of name */ if (len >= FLEN_KEYWORD) return(*status = BAD_KEYCHAR); lentok1 = len; strncat(card, tok, len); /* The HIERARCH convention supports non-standard characters in the keyword name, so don't always convert to upper case or abort if there are illegal characters in the name or if the name is greater than 8 characters long. */ if (len < 9) /* this is possibly a normal FITS keyword name */ { ffupch(card); tstatus = 0; if (fftkey(card, &tstatus) > 0) { /* name contained non-standard characters, so reset */ card[0] = '\0'; strncat(card, tok, len); } } tok += len; /* Check optional "+" indicator to delete multiple keywords */ if (tok[0] == '+' && len < FLEN_KEYWORD) { strcat(card, "+"); return (*status); } /* second token, if present, is the new name for the keyword */ len = strspn(tok, " "); /* no. of spaces before next token */ tok += len; if (tok[0] == '\0' || tok[0] == '=') return(*status); /* no second token */ *hdtype = -2; len = strcspn(tok, " "); /* length of new name */ /* this name has to fit on columns 41-80 of card, and first name must now fit in 1-40 */ if (lentok1 > 40) { card[0] = '\0'; return (*status = BAD_KEYCHAR); } if (len > 40) { card[0] = '\0'; return(*status = BAD_KEYCHAR); } /* copy the new name to card + 40; This is awkward, */ /* but is consistent with the way the Fortran FITSIO works */ strcat(card," "); strncpy(&card[40], tok, len); card[80] = '\0'; /* necessary to add terminator in case len = 40 */ /* The HIERARCH convention supports non-standard characters in the keyword name, so don't always convert to upper case or abort if there are illegal characters in the name or if the name is greater than 8 characters long. */ if (len < 9) /* this is possibly a normal FITS keyword name */ { ffupch(&card[40]); tstatus = 0; if (fftkey(&card[40], &tstatus) > 0) { /* name contained non-standard characters, so reset */ strncpy(&card[40], tok, len); } } } else /* no negative sign at beginning of template */ { /* get the keyword name token */ len = strcspn(tok, " ="); /* length of keyword name */ if (len >= FLEN_KEYWORD) return(*status = BAD_KEYCHAR); strncat(keyname, tok, len); /* The HIERARCH convention supports non-standard characters in the keyword name, so don't always convert to upper case or abort if there are illegal characters in the name or if the name is greater than 8 characters long. */ if (len < 9) /* this is possibly a normal FITS keyword name */ { ffupch(keyname); tstatus = 0; if (fftkey(keyname, &tstatus) > 0) { /* name contained non-standard characters, so reset */ keyname[0] = '\0'; strncat(keyname, tok, len); } } if (!FSTRCMP(keyname, "END") ) { strcpy(card, "END"); *hdtype = 2; return(*status); } tok += len; /* move token pointer to end of the keyword */ if (!FSTRCMP(keyname, "COMMENT") || !FSTRCMP(keyname, "HISTORY") || !FSTRCMP(keyname, "HIERARCH") ) { *hdtype = 1; /* simply append COMMENT and HISTORY keywords */ strcpy(card, keyname); strncat(card, tok, 72); return(*status); } /* look for the value token */ len = strspn(tok, " ="); /* spaces or = between name and value */ tok += len; if (*tok == '\'') /* is value enclosed in quotes? */ { more = TRUE; remainlen = 139; while (more) { tok++; /* temporarily move past the quote char */ len = strcspn(tok, "'"); /* length of quoted string */ tok--; if (len+2 > remainlen) return (*status=BAD_KEYCHAR); strncat(value, tok, len + 2); remainlen -= (len+2); tok += len + 1; if (tok[0] != '\'') /* check there is a closing quote */ return(*status = NO_QUOTE); tok++; if (tok[0] != '\'') /* 2 quote chars = literal quote */ more = FALSE; } } else if (*tok == '/' || *tok == '\0') /* There is no value */ { strcat(value, " "); } else /* not a quoted string value */ { len = strcspn(tok, " /"); /* length of value string */ if (len > 139) return (*status=BAD_KEYCHAR); strncat(value, tok, len); if (!( (tok[0] == 'T' || tok[0] == 'F') && (tok[1] == ' ' || tok[1] == '/' || tok[1] == '\0') )) { /* not a logical value */ dval = strtod(value, &suffix); /* try to read value as number */ if (*suffix != '\0' && *suffix != ' ' && *suffix != '/') { /* value not recognized as a number; might be because it */ /* contains a 'd' or 'D' exponent character */ strcpy(tvalue, value); if ((loc = strchr(tvalue, 'D'))) { *loc = 'E'; /* replace D's with E's. */ dval = strtod(tvalue, &suffix); /* read value again */ } else if ((loc = strchr(tvalue, 'd'))) { *loc = 'E'; /* replace d's with E's. */ dval = strtod(tvalue, &suffix); /* read value again */ } else if ((loc = strchr(tvalue, '.'))) { *loc = ','; /* replace period with a comma */ dval = strtod(tvalue, &suffix); /* read value again */ } } if (*suffix != '\0' && *suffix != ' ' && *suffix != '/') { /* value is not a number; must enclose it in quotes */ if (len > 137) return (*status=BAD_KEYCHAR); strcpy(value, "'"); strncat(value, tok, len); strcat(value, "'"); /* the following useless statement stops the compiler warning */ /* that dval is not used anywhere */ if (dval == 0.) len += (int) dval; } else { /* value is a number; convert any 'e' to 'E', or 'd' to 'D' */ loc = strchr(value, 'e'); if (loc) { *loc = 'E'; } else { loc = strchr(value, 'd'); if (loc) { *loc = 'D'; } } } } tok += len; } len = strspn(tok, " /"); /* no. of spaces between value and comment */ tok += len; vlen = strlen(value); if (vlen > 0 && vlen < 10 && value[0] == '\'') { /* pad quoted string with blanks so it is at least 8 chars long */ value[vlen-1] = '\0'; strncat(value, " ", 10 - vlen); strcat(&value[9], "'"); } /* get the comment string */ strncat(comment, tok, 70); /* construct the complete FITS header card */ ffmkky(keyname, value, comment, card, status); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_translate_keyword( char *inrec, /* I - input string */ char *outrec, /* O - output converted string, or */ /* a null string if input does not */ /* match any of the patterns */ char *patterns[][2],/* I - pointer to input / output string */ /* templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *pat_num, /* O - matched pattern number (0 based) or -1 */ int *i, /* O - value of i, if any, else 0 */ int *j, /* O - value of j, if any, else 0 */ int *m, /* O - value of m, if any, else 0 */ int *n, /* O - value of n, if any, else 0 */ int *status) /* IO - error status */ /* Translate a keyword name to a new name, based on a set of patterns. The user passes an array of patterns to be matched. Input pattern number i is pattern[i][0], and output pattern number i is pattern[i][1]. Keywords are matched against the input patterns. If a match is found then the keyword is re-written according to the output pattern. Order is important. The first match is accepted. The fastest match will be made when templates with the same first character are grouped together. Several characters have special meanings: i,j - single digits, preserved in output template n - column number of one or more digits, preserved in output template m - generic number of one or more digits, preserved in output template a - coordinate designator, preserved in output template # - number of one or more digits ? - any character * - only allowed in first character position, to match all keywords; only useful as last pattern in the list i, j, n, and m are returned by the routine. For example, the input pattern "iCTYPn" will match "1CTYP5" (if n_value is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". Notice that "i" is preserved. The following output patterns are special Special output pattern characters: "-" - do not copy a keyword that matches the corresponding input pattern "+" - copy the input unchanged The inrec string could be just the 8-char keyword name, or the entire 80-char header record. Characters 9 = 80 in the input string simply get appended to the translated keyword name. If n_range = 0, then only keywords with 'n' equal to n_value will be considered as a pattern match. If n_range = +1, then all values of 'n' greater than or equal to n_value will be a match, and if -1, then values of 'n' less than or equal to n_value will match. This routine was written by Craig Markwardt, GSFC */ { int i1 = 0, j1 = 0, n1 = 0, m1 = 0; int fac; char a = ' '; char oldp; char c, s; int ip, ic, pat, pass = 0, firstfail; char *spat; if (*status > 0) return(*status); if ((inrec == 0) || (outrec == 0)) return (*status = NULL_INPUT_PTR); *outrec = '\0'; /* if (*inrec == '\0') return 0; */ if (*inrec == '\0') /* expand to full 8 char blank keyword name */ strcpy(inrec, " "); oldp = '\0'; firstfail = 0; /* ===== Pattern match stage */ for (pat=0; pat < npat; pat++) { spat = patterns[pat][0]; i1 = 0; j1 = 0; m1 = -1; n1 = -1; a = ' '; /* Initialize the place-holders */ pass = 0; /* Pass the wildcard pattern */ if (spat[0] == '*') { pass = 1; break; } /* Optimization: if we have seen this initial pattern character before, then it must have failed, and we can skip the pattern */ if (firstfail && spat[0] == oldp) continue; oldp = spat[0]; /* ip = index of pattern character being matched ic = index of keyname character being matched firstfail = 1 if we fail on the first characteor (0=not) */ for (ip=0, ic=0, firstfail=1; (spat[ip]) && (ic < 8); ip++, ic++, firstfail=0) { c = inrec[ic]; s = spat[ip]; if (s == 'i') { /* Special pattern: 'i' placeholder */ if (isdigit(c)) { i1 = c - '0'; pass = 1;} } else if (s == 'j') { /* Special pattern: 'j' placeholder */ if (isdigit(c)) { j1 = c - '0'; pass = 1;} } else if ((s == 'n')||(s == 'm')||(s == '#')) { /* Special patterns: multi-digit number */ int val = 0; pass = 0; if (isdigit(c)) { pass = 1; /* NOTE, could fail below */ /* Parse decimal number */ while (ic<8 && isdigit(c)) { val = val*10 + (c - '0'); ic++; c = inrec[ic]; } ic--; c = inrec[ic]; if (s == 'n') { /* Is it a column number? */ if ( val >= 1 && val <= 999 && /* Row range check */ (((n_range == 0) && (val == n_value)) || /* Strict equality */ ((n_range == -1) && (val <= n_value)) || /* n <= n_value */ ((n_range == +1) && (val >= n_value))) ) { /* n >= n_value */ n1 = val; } else { pass = 0; } } else if (s == 'm') { /* Generic number */ m1 = val; } } } else if (s == 'a') { /* Special pattern: coordinate designator */ if (isupper(c) || c == ' ') { a = c; pass = 1;} } else if (s == '?') { /* Match any individual character */ pass = 1; } else if (c == s) { /* Match a specific character */ pass = 1; } else { /* FAIL */ pass = 0; } if (!pass) break; } /* Must pass to the end of the keyword. No partial matches allowed */ if (pass && (ic >= 8 || inrec[ic] == ' ')) break; } /* Transfer the pattern-matched numbers to the output parameters */ if (i) { *i = i1; } if (j) { *j = j1; } if (n) { *n = n1; } if (m) { *m = m1; } if (pat_num) { *pat_num = pat; } /* ===== Keyword rewriting and output stage */ spat = patterns[pat][1]; /* Return case: explicit deletion, return '-' */ if (pass && strcmp(spat,"--") == 0) { strcpy(outrec, "-"); strncat(outrec, inrec, 8); outrec[9] = 0; for(i1=8; i1>1 && outrec[i1] == ' '; i1--) outrec[i1] = 0; return 0; } /* Return case: no match, or do-not-transfer pattern */ if (pass == 0 || spat[0] == '\0' || strcmp(spat,"-") == 0) return 0; /* A match: we start by copying the input record to the output */ strcpy(outrec, inrec); /* Return case: return the input record unchanged */ if (spat[0] == '+') return 0; /* Final case: a new output pattern */ for (ip=0, ic=0; spat[ip]; ip++, ic++) { s = spat[ip]; if (s == 'i') { outrec[ic] = (i1+'0'); } else if (s == 'j') { outrec[ic] = (j1+'0'); } else if (s == 'n') { if (n1 == -1) { n1 = n_value; } if (n1 > 0) { n1 += n_offset; for (fac = 1; (n1/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((n1/fac) % 10) + '0'; fac /= 10; ic ++; } ic--; } } else if (s == 'm' && m1 >= 0) { for (fac = 1; (m1/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((m1/fac) % 10) + '0'; fac /= 10; ic ++; } ic --; } else if (s == 'a') { outrec[ic] = a; } else { outrec[ic] = s; } } /* Pad the keyword name with spaces */ for ( ; ic<8; ic++) { outrec[ic] = ' '; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_translate_keywords( fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU record number to start with */ char *patterns[][2],/* I - pointer to input / output keyword templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *status) /* IO - error status */ /* Copy relevant keywords from the table header into the newly created primary array header. Convert names of keywords where appropriate. See fits_translate_keyword() for the definitions. Translation begins at header record number 'firstkey', and continues to the end of the header. This routine was written by Craig Markwardt, GSFC */ { int nrec, nkeys, nmore; char rec[FLEN_CARD]; int i = 0, j = 0, n = 0, m = 0; int pat_num = 0, maxchr, ii; char outrec[FLEN_CARD]; if (*status > 0) return(*status); ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords */ for (nrec = firstkey; (*status == 0) && (nrec <= nkeys); nrec++) { outrec[0] = '\0'; ffgrec(infptr, nrec, rec, status); /* silently overlook any illegal ASCII characters in the value or */ /* comment fields of the record. It is usually not appropriate to */ /* abort the process because of this minor transgression of the FITS rules. */ /* Set the offending character to a blank */ maxchr = strlen(rec); for (ii = 8; ii < maxchr; ii++) { if (rec[ii] < 32 || rec[ii] > 126) rec[ii] = ' '; } fits_translate_keyword(rec, outrec, patterns, npat, n_value, n_offset, n_range, &pat_num, &i, &j, &m, &n, status); if (*status == 0) { if (outrec[0] == '-') { /* prefix -KEYNAME means delete */ int i1; /* Preserve only the keyword portion of name */ outrec[9] = 0; for(i1=8; i1>1 && outrec[i1] == ' '; i1--) outrec[i1] = 0; ffpmrk(); ffdkey(outfptr, outrec+1, status); /* delete the keyword */ if (*status == 0) { int nkeys1; /* get number of keywords again in case of change*/ ffghsp(infptr, &nkeys1, &nmore, status); if (nkeys1 != nkeys) { nrec --; nkeys = nkeys1; } } *status = 0; ffcmrk(); } else if (outrec[0]) { ffprec(outfptr, outrec, status); /* copy the keyword */ } } rec[8] = 0; outrec[8] = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_pixlist2image( fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU record number to start with */ int naxis, /* I - number of axes in the image */ int *colnum, /* I - numbers of the columns to be binned */ int *status) /* IO - error status */ /* Copy relevant keywords from the pixel list table header into a newly created primary array header. Convert names of keywords where appropriate. See fits_translate_pixkeyword() for the definitions. Translation begins at header record number 'firstkey', and continues to the end of the header. */ { int nrec, nkeys, nmore; char rec[FLEN_CARD], outrec[FLEN_CARD]; int pat_num = 0, npat; int iret, jret, nret, mret, lret; char *patterns[][2] = { {"TCTYPn", "CTYPEn" }, {"TCTYna", "CTYPEna" }, {"TCUNIn", "CUNITn" }, {"TCUNna", "CUNITna" }, {"TCRVLn", "CRVALn" }, {"TCRVna", "CRVALna" }, {"TCDLTn", "CDELTn" }, {"TCDEna", "CDELTna" }, {"TCRPXn", "CRPIXn" }, {"TCRPna", "CRPIXna" }, {"TCROTn", "CROTAn" }, {"TPn_ma", "PCn_ma" }, {"TPCn_m", "PCn_ma" }, {"TCn_ma", "CDn_ma" }, {"TCDn_m", "CDn_ma" }, {"TVn_la", "PVn_la" }, {"TPVn_l", "PVn_la" }, {"TSn_la", "PSn_la" }, {"TPSn_l", "PSn_la" }, {"TWCSna", "WCSNAMEa" }, {"TCNAna", "CNAMEna" }, {"TCRDna", "CRDERna" }, {"TCSYna", "CSYERna" }, {"LONPna", "LONPOLEa" }, {"LATPna", "LATPOLEa" }, {"EQUIna", "EQUINOXa" }, {"MJDOBn", "MJD-OBS" }, {"MJDAn", "MJD-AVG" }, {"DAVGn", "DATE-AVG" }, {"RADEna", "RADESYSa" }, {"RFRQna", "RESTFRQa" }, {"RWAVna", "RESTWAVa" }, {"SPECna", "SPECSYSa" }, {"SOBSna", "SSYSOBSa" }, {"SSRCna", "SSYSSRCa" }, /* preserve common keywords */ {"LONPOLEa", "+" }, {"LATPOLEa", "+" }, {"EQUINOXa", "+" }, {"EPOCH", "+" }, {"MJD-????", "+" }, {"DATE????", "+" }, {"TIME????", "+" }, {"RADESYSa", "+" }, {"RADECSYS", "+" }, {"TELESCOP", "+" }, {"INSTRUME", "+" }, {"OBSERVER", "+" }, {"OBJECT", "+" }, /* Delete general table column keywords */ {"XTENSION", "-" }, {"BITPIX", "-" }, {"NAXIS", "-" }, {"NAXISi", "-" }, {"PCOUNT", "-" }, {"GCOUNT", "-" }, {"TFIELDS", "-" }, {"TDIM#", "-" }, {"THEAP", "-" }, {"EXTNAME", "-" }, {"EXTVER", "-" }, {"EXTLEVEL","-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"NAXLEN", "-" }, {"AXLEN#", "-" }, {"CPREF", "-" }, /* Delete table keywords related to other columns */ {"T????#a", "-" }, {"TC??#a", "-" }, {"T??#_#", "-" }, {"TWCS#a", "-" }, {"LONP#a", "-" }, {"LATP#a", "-" }, {"EQUI#a", "-" }, {"MJDOB#", "-" }, {"MJDA#", "-" }, {"RADE#a", "-" }, {"DAVG#", "-" }, {"iCTYP#", "-" }, {"iCTY#a", "-" }, {"iCUNI#", "-" }, {"iCUN#a", "-" }, {"iCRVL#", "-" }, {"iCDLT#", "-" }, {"iCRPX#", "-" }, {"iCTY#a", "-" }, {"iCUN#a", "-" }, {"iCRV#a", "-" }, {"iCDE#a", "-" }, {"iCRP#a", "-" }, {"ijPC#a", "-" }, {"ijCD#a", "-" }, {"iV#_#a", "-" }, {"iS#_#a", "-" }, {"iCRD#a", "-" }, {"iCSY#a", "-" }, {"iCROT#", "-" }, {"WCAX#a", "-" }, {"WCSN#a", "-" }, {"iCNA#a", "-" }, {"*", "+" }}; /* copy all other keywords */ if (*status > 0) return(*status); npat = sizeof(patterns)/sizeof(patterns[0][0])/2; ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords */ for (nrec = firstkey; nrec <= nkeys; nrec++) { outrec[0] = '\0'; ffgrec(infptr, nrec, rec, status); fits_translate_pixkeyword(rec, outrec, patterns, npat, naxis, colnum, &pat_num, &iret, &jret, &nret, &mret, &lret, status); if (outrec[0]) { ffprec(outfptr, outrec, status); /* copy the keyword */ } rec[8] = 0; outrec[8] = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_translate_pixkeyword( char *inrec, /* I - input string */ char *outrec, /* O - output converted string, or */ /* a null string if input does not */ /* match any of the patterns */ char *patterns[][2],/* I - pointer to input / output string */ /* templates */ int npat, /* I - number of templates passed */ int naxis, /* I - number of columns to be binned */ int *colnum, /* I - numbers of the columns to be binned */ int *pat_num, /* O - matched pattern number (0 based) or -1 */ int *i, int *j, int *n, int *m, int *l, int *status) /* IO - error status */ /* Translate a keyword name to a new name, based on a set of patterns. The user passes an array of patterns to be matched. Input pattern number i is pattern[i][0], and output pattern number i is pattern[i][1]. Keywords are matched against the input patterns. If a match is found then the keyword is re-written according to the output pattern. Order is important. The first match is accepted. The fastest match will be made when templates with the same first character are grouped together. Several characters have special meanings: i,j - single digits, preserved in output template n, m - column number of one or more digits, preserved in output template k - generic number of one or more digits, preserved in output template a - coordinate designator, preserved in output template # - number of one or more digits ? - any character * - only allowed in first character position, to match all keywords; only useful as last pattern in the list i, j, n, and m are returned by the routine. For example, the input pattern "iCTYPn" will match "1CTYP5" (if n_value is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". Notice that "i" is preserved. The following output patterns are special Special output pattern characters: "-" - do not copy a keyword that matches the corresponding input pattern "+" - copy the input unchanged The inrec string could be just the 8-char keyword name, or the entire 80-char header record. Characters 9 = 80 in the input string simply get appended to the translated keyword name. If n_range = 0, then only keywords with 'n' equal to n_value will be considered as a pattern match. If n_range = +1, then all values of 'n' greater than or equal to n_value will be a match, and if -1, then values of 'n' less than or equal to n_value will match. */ { int i1 = 0, j1 = 0, val; int fac, nval = 0, mval = 0, lval = 0; char a = ' '; char oldp; char c, s; int ip, ic, pat, pass = 0, firstfail; char *spat; if (*status > 0) return(*status); if ((inrec == 0) || (outrec == 0)) return (*status = NULL_INPUT_PTR); *outrec = '\0'; if (*inrec == '\0') return 0; oldp = '\0'; firstfail = 0; /* ===== Pattern match stage */ for (pat=0; pat < npat; pat++) { spat = patterns[pat][0]; i1 = 0; j1 = 0; a = ' '; /* Initialize the place-holders */ pass = 0; /* Pass the wildcard pattern */ if (spat[0] == '*') { pass = 1; break; } /* Optimization: if we have seen this initial pattern character before, then it must have failed, and we can skip the pattern */ if (firstfail && spat[0] == oldp) continue; oldp = spat[0]; /* ip = index of pattern character being matched ic = index of keyname character being matched firstfail = 1 if we fail on the first characteor (0=not) */ for (ip=0, ic=0, firstfail=1; (spat[ip]) && (ic < 8); ip++, ic++, firstfail=0) { c = inrec[ic]; s = spat[ip]; if (s == 'i') { /* Special pattern: 'i' placeholder */ if (isdigit(c)) { i1 = c - '0'; pass = 1;} } else if (s == 'j') { /* Special pattern: 'j' placeholder */ if (isdigit(c)) { j1 = c - '0'; pass = 1;} } else if ((s == 'n')||(s == 'm')||(s == 'l')||(s == '#')) { /* Special patterns: multi-digit number */ val = 0; pass = 0; if (isdigit(c)) { pass = 1; /* NOTE, could fail below */ /* Parse decimal number */ while (ic<8 && isdigit(c)) { val = val*10 + (c - '0'); ic++; c = inrec[ic]; } ic--; c = inrec[ic]; if (s == 'n' || s == 'm') { /* Is it a column number? */ if ( val >= 1 && val <= 999) { if (val == colnum[0]) val = 1; else if (val == colnum[1]) val = 2; else if (val == colnum[2]) val = 3; else if (val == colnum[3]) val = 4; else { pass = 0; val = 0; } if (s == 'n') nval = val; else mval = val; } else { pass = 0; } } else if (s == 'l') { /* Generic number */ lval = val; } } } else if (s == 'a') { /* Special pattern: coordinate designator */ if (isupper(c) || c == ' ') { a = c; pass = 1;} } else if (s == '?') { /* Match any individual character */ pass = 1; } else if (c == s) { /* Match a specific character */ pass = 1; } else { /* FAIL */ pass = 0; } if (!pass) break; } /* Must pass to the end of the keyword. No partial matches allowed */ if (pass && (ic >= 8 || inrec[ic] == ' ')) break; } /* Transfer the pattern-matched numbers to the output parameters */ if (i) { *i = i1; } if (j) { *j = j1; } if (n) { *n = nval; } if (m) { *m = mval; } if (l) { *l = lval; } if (pat_num) { *pat_num = pat; } /* ===== Keyword rewriting and output stage */ spat = patterns[pat][1]; /* Return case: no match, or explicit deletion pattern */ if (pass == 0 || spat[0] == '\0' || spat[0] == '-') return 0; /* A match: we start by copying the input record to the output */ strcpy(outrec, inrec); /* Return case: return the input record unchanged */ if (spat[0] == '+') return 0; /* Final case: a new output pattern */ for (ip=0, ic=0; spat[ip]; ip++, ic++) { s = spat[ip]; if (s == 'i') { outrec[ic] = (i1+'0'); } else if (s == 'j') { outrec[ic] = (j1+'0'); } else if (s == 'n' && nval > 0) { for (fac = 1; (nval/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((nval/fac) % 10) + '0'; fac /= 10; ic ++; } ic--; } else if (s == 'm' && mval > 0) { for (fac = 1; (mval/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((mval/fac) % 10) + '0'; fac /= 10; ic ++; } ic--; } else if (s == 'l' && lval >= 0) { for (fac = 1; (lval/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((lval/fac) % 10) + '0'; fac /= 10; ic ++; } ic --; } else if (s == 'a') { outrec[ic] = a; } else { outrec[ic] = s; } } /* Pad the keyword name with spaces */ for ( ; ic<8; ic++) { outrec[ic] = ' '; } return(*status); } /*--------------------------------------------------------------------------*/ int ffasfm(char *tform, /* I - format code from the TFORMn keyword */ int *dtcode, /* O - numerical datatype code */ long *twidth, /* O - width of the field, in chars */ int *decimals, /* O - number of decimal places (F, E, D format) */ int *status) /* IO - error status */ { /* parse the ASCII table TFORM column format to determine the data type, the field width, and number of decimal places (if relevant) */ int ii, datacode; long longval, width; float fwidth; char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; if (*status > 0) return(*status); if (dtcode) *dtcode = 0; if (twidth) *twidth = 0; if (decimals) *decimals = 0; ii = 0; while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ ii++; if (strlen(&tform[ii]) > FLEN_VALUE-1) { ffpmsg("Error: ASCII table TFORM code is too long (ffasfm)"); return(*status = BAD_TFORM); } strcpy(temp, &tform[ii]); /* copy format string */ ffupch(temp); /* make sure it is in upper case */ form = temp; /* point to start of format string */ if (form[0] == 0) { ffpmsg("Error: ASCII table TFORM code is blank"); return(*status = BAD_TFORM); } /*-----------------------------------------------*/ /* determine default datatype code */ /*-----------------------------------------------*/ if (form[0] == 'A') datacode = TSTRING; else if (form[0] == 'I') datacode = TLONG; else if (form[0] == 'F') datacode = TFLOAT; else if (form[0] == 'E') datacode = TFLOAT; else if (form[0] == 'D') datacode = TDOUBLE; else { snprintf(message, FLEN_ERRMSG, "Illegal ASCII table TFORMn datatype: \'%s\'", tform); ffpmsg(message); return(*status = BAD_TFORM_DTYPE); } if (dtcode) *dtcode = datacode; form++; /* point to the start of field width */ if (datacode == TSTRING || datacode == TLONG) { /*-----------------------------------------------*/ /* A or I data formats: */ /*-----------------------------------------------*/ if (ffc2ii(form, &width, status) <= 0) /* read the width field */ { if (width <= 0) { width = 0; *status = BAD_TFORM; } else { /* set to shorter precision if I4 or less */ if (width <= 4 && datacode == TLONG) datacode = TSHORT; } } } else { /*-----------------------------------------------*/ /* F, E or D data formats: */ /*-----------------------------------------------*/ if (ffc2rr(form, &fwidth, status) <= 0) /* read ww.dd width field */ { if (fwidth <= 0.) *status = BAD_TFORM; else { width = (long) fwidth; /* convert from float to long */ if (width > 7 && *temp == 'F') datacode = TDOUBLE; /* type double if >7 digits */ if (width < 10) form = form + 1; /* skip 1 digit */ else form = form + 2; /* skip 2 digits */ if (form[0] == '.') /* should be a decimal point here */ { form++; /* point to start of decimals field */ if (ffc2ii(form, &longval, status) <= 0) /* read decimals */ { if (decimals) *decimals = longval; /* long to short convertion */ if (longval >= width) /* width < no. of decimals */ *status = BAD_TFORM; if (longval > 6 && *temp == 'E') datacode = TDOUBLE; /* type double if >6 digits */ } } } } } if (*status > 0) { *status = BAD_TFORM; snprintf(message,FLEN_ERRMSG,"Illegal ASCII table TFORMn code: \'%s\'", tform); ffpmsg(message); } if (dtcode) *dtcode = datacode; if (twidth) *twidth = width; return(*status); } /*--------------------------------------------------------------------------*/ int ffbnfm(char *tform, /* I - format code from the TFORMn keyword */ int *dtcode, /* O - numerical datatype code */ long *trepeat, /* O - repeat count of the field */ long *twidth, /* O - width of the field, in chars */ int *status) /* IO - error status */ { /* parse the binary table TFORM column format to determine the data type, repeat count, and the field width (if it is an ASCII (A) field) */ size_t ii, nchar; int datacode, variable, iread; long width, repeat; char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; if (*status > 0) return(*status); if (dtcode) *dtcode = 0; if (trepeat) *trepeat = 0; if (twidth) *twidth = 0; nchar = strlen(tform); for (ii = 0; ii < nchar; ii++) { if (tform[ii] != ' ') /* find first non-space char */ break; } if (ii == nchar) { ffpmsg("Error: binary table TFORM code is blank (ffbnfm)."); return(*status = BAD_TFORM); } if (nchar-ii > FLEN_VALUE-1) { ffpmsg("Error: binary table TFORM code is too long (ffbnfm)."); return (*status = BAD_TFORM); } strcpy(temp, &tform[ii]); /* copy format string */ ffupch(temp); /* make sure it is in upper case */ form = temp; /* point to start of format string */ /*-----------------------------------------------*/ /* get the repeat count */ /*-----------------------------------------------*/ ii = 0; while(isdigit((int) form[ii])) ii++; /* look for leading digits in the field */ if (ii == 0) repeat = 1; /* no explicit repeat count */ else { if (sscanf(form,"%ld", &repeat) != 1) /* read repeat count */ { ffpmsg("Error: Bad repeat format in TFORM (ffbnfm)."); return(*status = BAD_TFORM); } } /*-----------------------------------------------*/ /* determine datatype code */ /*-----------------------------------------------*/ form = form + ii; /* skip over the repeat field */ if (form[0] == 'P' || form[0] == 'Q') { variable = 1; /* this is a variable length column */ /* repeat = 1; */ /* disregard any other repeat value */ form++; /* move to the next data type code char */ } else variable = 0; if (form[0] == 'U') /* internal code to signify unsigned short integer */ { datacode = TUSHORT; width = 2; } else if (form[0] == 'I') { datacode = TSHORT; width = 2; } else if (form[0] == 'V') /* internal code to signify unsigned integer */ { datacode = TULONG; width = 4; } else if (form[0] == 'W') /* internal code to signify unsigned long long integer */ { datacode = TULONGLONG; width = 8; } else if (form[0] == 'J') { datacode = TLONG; width = 4; } else if (form[0] == 'K') { datacode = TLONGLONG; width = 8; } else if (form[0] == 'E') { datacode = TFLOAT; width = 4; } else if (form[0] == 'D') { datacode = TDOUBLE; width = 8; } else if (form[0] == 'A') { datacode = TSTRING; /* the following code is used to support the non-standard datatype of the form rAw where r = total width of the field and w = width of fixed-length substrings within the field. */ iread = 0; if (form[1] != 0) { if (form[1] == '(' ) /* skip parenthesis around */ form++; /* variable length column width */ iread = sscanf(&form[1],"%ld", &width); } if (iread != 1 || (!variable && (width > repeat)) ) width = repeat; } else if (form[0] == 'L') { datacode = TLOGICAL; width = 1; } else if (form[0] == 'X') { datacode = TBIT; width = 1; } else if (form[0] == 'B') { datacode = TBYTE; width = 1; } else if (form[0] == 'S') /* internal code to signify signed byte */ { datacode = TSBYTE; width = 1; } else if (form[0] == 'C') { datacode = TCOMPLEX; width = 8; } else if (form[0] == 'M') { datacode = TDBLCOMPLEX; width = 16; } else { snprintf(message, FLEN_ERRMSG, "Illegal binary table TFORMn datatype: \'%s\' ", tform); ffpmsg(message); return(*status = BAD_TFORM_DTYPE); } if (variable) datacode = datacode * (-1); /* flag variable cols w/ neg type code */ if (dtcode) *dtcode = datacode; if (trepeat) *trepeat = repeat; if (twidth) *twidth = width; return(*status); } /*--------------------------------------------------------------------------*/ int ffbnfmll(char *tform, /* I - format code from the TFORMn keyword */ int *dtcode, /* O - numerical datatype code */ LONGLONG *trepeat, /* O - repeat count of the field */ long *twidth, /* O - width of the field, in chars */ int *status) /* IO - error status */ { /* parse the binary table TFORM column format to determine the data type, repeat count, and the field width (if it is an ASCII (A) field) */ size_t ii, nchar; int datacode, variable, iread; long width; LONGLONG repeat; char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; double drepeat; if (*status > 0) return(*status); if (dtcode) *dtcode = 0; if (trepeat) *trepeat = 0; if (twidth) *twidth = 0; nchar = strlen(tform); for (ii = 0; ii < nchar; ii++) { if (tform[ii] != ' ') /* find first non-space char */ break; } if (ii == nchar) { ffpmsg("Error: binary table TFORM code is blank (ffbnfmll)."); return(*status = BAD_TFORM); } if (strlen(&tform[ii]) > FLEN_VALUE-1) { ffpmsg("Error: binary table TFORM code is too long (ffbnfmll)."); return(*status = BAD_TFORM); } strcpy(temp, &tform[ii]); /* copy format string */ ffupch(temp); /* make sure it is in upper case */ form = temp; /* point to start of format string */ /*-----------------------------------------------*/ /* get the repeat count */ /*-----------------------------------------------*/ ii = 0; while(isdigit((int) form[ii])) ii++; /* look for leading digits in the field */ if (ii == 0) repeat = 1; /* no explicit repeat count */ else { /* read repeat count */ /* print as double, because the string-to-64-bit int conversion */ /* character is platform dependent (%lld, %ld, %I64d) */ sscanf(form,"%lf", &drepeat); repeat = (LONGLONG) (drepeat + 0.1); } /*-----------------------------------------------*/ /* determine datatype code */ /*-----------------------------------------------*/ form = form + ii; /* skip over the repeat field */ if (form[0] == 'P' || form[0] == 'Q') { variable = 1; /* this is a variable length column */ /* repeat = 1; */ /* disregard any other repeat value */ form++; /* move to the next data type code char */ } else variable = 0; if (form[0] == 'U') /* internal code to signify unsigned integer */ { datacode = TUSHORT; width = 2; } else if (form[0] == 'I') { datacode = TSHORT; width = 2; } else if (form[0] == 'V') /* internal code to signify unsigned integer */ { datacode = TULONG; width = 4; } else if (form[0] == 'W') /* internal code to signify unsigned long long integer */ { datacode = TULONGLONG; width = 8; } else if (form[0] == 'J') { datacode = TLONG; width = 4; } else if (form[0] == 'K') { datacode = TLONGLONG; width = 8; } else if (form[0] == 'E') { datacode = TFLOAT; width = 4; } else if (form[0] == 'D') { datacode = TDOUBLE; width = 8; } else if (form[0] == 'A') { datacode = TSTRING; /* the following code is used to support the non-standard datatype of the form rAw where r = total width of the field and w = width of fixed-length substrings within the field. */ iread = 0; if (form[1] != 0) { if (form[1] == '(' ) /* skip parenthesis around */ form++; /* variable length column width */ iread = sscanf(&form[1],"%ld", &width); } if (iread != 1 || (!variable && (width > repeat)) ) width = (long) repeat; } else if (form[0] == 'L') { datacode = TLOGICAL; width = 1; } else if (form[0] == 'X') { datacode = TBIT; width = 1; } else if (form[0] == 'B') { datacode = TBYTE; width = 1; } else if (form[0] == 'S') /* internal code to signify signed byte */ { datacode = TSBYTE; width = 1; } else if (form[0] == 'C') { datacode = TCOMPLEX; width = 8; } else if (form[0] == 'M') { datacode = TDBLCOMPLEX; width = 16; } else { snprintf(message, FLEN_ERRMSG, "Illegal binary table TFORMn datatype: \'%s\' ", tform); ffpmsg(message); return(*status = BAD_TFORM_DTYPE); } if (variable) datacode = datacode * (-1); /* flag variable cols w/ neg type code */ if (dtcode) *dtcode = datacode; if (trepeat) *trepeat = repeat; if (twidth) *twidth = width; return(*status); } /*--------------------------------------------------------------------------*/ void ffcfmt(char *tform, /* value of an ASCII table TFORMn keyword */ char *cform) /* equivalent format code in C language syntax */ /* convert the FITS format string for an ASCII Table extension column into the equivalent C format string that can be used in a printf statement, after the values have been read as a double. */ { int ii; cform[0] = '\0'; ii = 0; while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ ii++; if (tform[ii] == 0) return; /* input format string was blank */ cform[0] = '%'; /* start the format string */ strcpy(&cform[1], &tform[ii + 1]); /* append the width and decimal code */ if (tform[ii] == 'A') strcat(cform, "s"); else if (tform[ii] == 'I') strcat(cform, ".0f"); /* 0 precision to suppress decimal point */ if (tform[ii] == 'F') strcat(cform, "f"); if (tform[ii] == 'E') strcat(cform, "E"); if (tform[ii] == 'D') strcat(cform, "E"); return; } /*--------------------------------------------------------------------------*/ void ffcdsp(char *tform, /* value of an ASCII table TFORMn keyword */ char *cform) /* equivalent format code in C language syntax */ /* convert the FITS TDISPn display format into the equivalent C format suitable for use in a printf statement. */ { int ii; cform[0] = '\0'; ii = 0; while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ ii++; if (tform[ii] == 0) { cform[0] = '\0'; return; /* input format string was blank */ } if (strchr(tform+ii, '%')) /* is there a % character in the string?? */ { cform[0] = '\0'; return; /* illegal TFORM string (possibly even harmful) */ } cform[0] = '%'; /* start the format string */ strcpy(&cform[1], &tform[ii + 1]); /* append the width and decimal code */ if (tform[ii] == 'A' || tform[ii] == 'a') strcat(cform, "s"); else if (tform[ii] == 'I' || tform[ii] == 'i') strcat(cform, "d"); else if (tform[ii] == 'O' || tform[ii] == 'o') strcat(cform, "o"); else if (tform[ii] == 'Z' || tform[ii] == 'z') strcat(cform, "X"); else if (tform[ii] == 'F' || tform[ii] == 'f') strcat(cform, "f"); else if (tform[ii] == 'E' || tform[ii] == 'e') strcat(cform, "E"); else if (tform[ii] == 'D' || tform[ii] == 'd') strcat(cform, "E"); else if (tform[ii] == 'G' || tform[ii] == 'g') strcat(cform, "G"); else cform[0] = '\0'; /* unrecognized tform code */ return; } /*--------------------------------------------------------------------------*/ int ffgcno( fitsfile *fptr, /* I - FITS file pionter */ int casesen, /* I - case sensitive string comparison? 0=no */ char *templt, /* I - input name of column (w/wildcards) */ int *colnum, /* O - number of the named column; 1=first col */ int *status) /* IO - error status */ /* Determine the column number corresponding to an input column name. The first column of the table = column 1; This supports the * and ? wild cards in the input template. */ { char colname[FLEN_VALUE]; /* temporary string to hold column name */ ffgcnn(fptr, casesen, templt, colname, colnum, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcnn( fitsfile *fptr, /* I - FITS file pointer */ int casesen, /* I - case sensitive string comparison? 0=no */ char *templt, /* I - input name of column (w/wildcards) */ char *colname, /* O - full column name up to 68 + 1 chars long*/ int *colnum, /* O - number of the named column; 1=first col */ int *status) /* IO - error status */ /* Return the full column name and column number of the next column whose TTYPEn keyword value matches the input template string. The template may contain the * and ? wildcards. Status = 237 is returned if the match is not unique. If so, one may call this routine again with input status=237 to get the next match. A status value of 219 is returned when there are no more matching columns. */ { char errmsg[FLEN_ERRMSG]; int tstatus, ii, founde, foundw, match, exact, unique; long ivalue; tcolumn *colptr; if (*status <= 0) { (fptr->Fptr)->startcol = 0; /* start search with first column */ tstatus = 0; } else if (*status == COL_NOT_UNIQUE) /* start search from previous spot */ { tstatus = COL_NOT_UNIQUE; *status = 0; } else return(*status); /* bad input status value */ colname[0] = 0; /* initialize null return */ *colnum = 0; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header to get col struct */ return(*status); colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += ((fptr->Fptr)->startcol); /* offset to starting column */ founde = FALSE; /* initialize 'found exact match' flag */ foundw = FALSE; /* initialize 'found wildcard match' flag */ unique = FALSE; for (ii = (fptr->Fptr)->startcol; ii < (fptr->Fptr)->tfield; ii++, colptr++) { ffcmps(templt, colptr->ttype, casesen, &match, &exact); if (match) { if (founde && exact) { /* warning: this is the second exact match we've found */ /*reset pointer to first match so next search starts there */ (fptr->Fptr)->startcol = *colnum; return(*status = COL_NOT_UNIQUE); } else if (founde) /* a wildcard match */ { /* already found exact match so ignore this non-exact match */ } else if (exact) { /* this is the first exact match we have found, so save it. */ strcpy(colname, colptr->ttype); *colnum = ii + 1; founde = TRUE; } else if (foundw) { /* we have already found a wild card match, so not unique */ /* continue searching for other matches */ unique = FALSE; } else { /* this is the first wild card match we've found. save it */ strcpy(colname, colptr->ttype); *colnum = ii + 1; (fptr->Fptr)->startcol = *colnum; foundw = TRUE; unique = TRUE; } } } /* OK, we've checked all the names now see if we got any matches */ if (founde) { if (tstatus == COL_NOT_UNIQUE) /* we did find 1 exact match but */ *status = COL_NOT_UNIQUE; /* there was a previous match too */ } else if (foundw) { /* found one or more wildcard matches; report error if not unique */ if (!unique || tstatus == COL_NOT_UNIQUE) *status = COL_NOT_UNIQUE; } else { /* didn't find a match; check if template is a positive integer */ ffc2ii(templt, &ivalue, &tstatus); if (tstatus == 0 && ivalue <= (fptr->Fptr)->tfield && ivalue > 0) { *colnum = ivalue; colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (ivalue - 1); /* offset to correct column */ strcpy(colname, colptr->ttype); } else { *status = COL_NOT_FOUND; if (tstatus != COL_NOT_UNIQUE) { snprintf(errmsg, FLEN_ERRMSG, "ffgcnn could not find column: %.45s", templt); ffpmsg(errmsg); } } } (fptr->Fptr)->startcol = *colnum; /* save pointer for next time */ return(*status); } /*--------------------------------------------------------------------------*/ void ffcmps(char *templt, /* I - input template (may have wildcards) */ char *colname, /* I - full column name up to 68 + 1 chars long */ int casesen, /* I - case sensitive string comparison? 1=yes */ int *match, /* O - do template and colname match? 1=yes */ int *exact) /* O - do strings exactly match, or wildcards */ /* compare the template to the string and test if they match. The strings are limited to 68 characters or less (the max. length of a FITS string keyword value. This routine reports whether the two strings match and whether the match is exact or involves wildcards. This algorithm is very similar to the way unix filename wildcards work except that this first treats a wild card as a literal character when looking for a match. If there is no literal match, then it interpretes it as a wild card. So the template 'AB*DE' is considered to be an exact rather than a wild card match to the string 'AB*DE'. The '#' wild card in the template string will match any consecutive string of decimal digits in the colname. */ { int ii, found, t1, s1, wildsearch = 0, tsave = 0, ssave = 0; char temp[FLEN_VALUE], col[FLEN_VALUE]; *match = FALSE; *exact = TRUE; strncpy(temp, templt, FLEN_VALUE); /* copy strings to work area */ strncpy(col, colname, FLEN_VALUE); temp[FLEN_VALUE - 1] = '\0'; /* make sure strings are terminated */ col[FLEN_VALUE - 1] = '\0'; /* truncate trailing non-significant blanks */ for (ii = strlen(temp) - 1; ii >= 0 && temp[ii] == ' '; ii--) temp[ii] = '\0'; for (ii = strlen(col) - 1; ii >= 0 && col[ii] == ' '; ii--) col[ii] = '\0'; if (!casesen) { /* convert both strings to uppercase before comparison */ ffupch(temp); ffupch(col); } if (!FSTRCMP(temp, col) ) { *match = TRUE; /* strings exactly match */ return; } *exact = FALSE; /* strings don't exactly match */ t1 = 0; /* start comparison with 1st char of each string */ s1 = 0; while(1) /* compare corresponding chars in each string */ { if (temp[t1] == '\0' && col[s1] == '\0') { /* completely scanned both strings so they match */ *match = TRUE; return; } else if (temp[t1] == '\0') { if (wildsearch) { /* the previous wildcard search may have been going down a blind alley. Backtrack, and resume the wildcard search with the next character in the string. */ t1 = tsave; s1 = ssave + 1; } else { /* reached end of template string so they don't match */ return; } } else if (col[s1] == '\0') { /* reached end of other string; they match if the next */ /* character in the template string is a '*' wild card */ if (temp[t1] == '*' && temp[t1 + 1] == '\0') { *match = TRUE; } return; } if (temp[t1] == col[s1] || (temp[t1] == '?') ) { s1++; /* corresponding chars in the 2 strings match */ t1++; /* increment both pointers and loop back again */ } else if (temp[t1] == '#' && isdigit((int) col[s1]) ) { s1++; /* corresponding chars in the 2 strings match */ t1++; /* increment both pointers */ /* find the end of the string of digits */ while (isdigit((int) col[s1]) ) s1++; } else if (temp[t1] == '*') { /* save current string locations, in case we need to restart */ wildsearch = 1; tsave = t1; ssave = s1; /* get next char from template and look for it in the col name */ t1++; if (temp[t1] == '\0' || temp[t1] == ' ') { /* reached end of template so strings match */ *match = TRUE; return; } found = FALSE; while (col[s1] && !found) { if (temp[t1] == col[s1]) { t1++; /* found matching characters; incre both pointers */ s1++; /* and loop back to compare next chars */ found = TRUE; } else s1++; /* increment the column name pointer and try again */ } if (!found) { return; /* hit end of column name and failed to find a match */ } } else { if (wildsearch) { /* the previous wildcard search may have been going down a blind alley. Backtrack, and resume the wildcard search with the next character in the string. */ t1 = tsave; s1 = ssave + 1; } else { return; /* strings don't match */ } } } } /*--------------------------------------------------------------------------*/ int ffgtcl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ long *repeat, /* O - repeat count of field */ long *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get Type of table column. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { LONGLONG trepeat, twidth; ffgtclll(fptr, colnum, typecode, &trepeat, &twidth, status); if (*status > 0) return(*status); if (repeat) *repeat= (long) trepeat; if (width) *width = (long) twidth; return(*status); } /*--------------------------------------------------------------------------*/ int ffgtclll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ LONGLONG *repeat, /* O - repeat count of field */ LONGLONG *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get Type of table column. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { tcolumn *colptr; int hdutype, decims; long tmpwidth; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum - 1); /* offset to correct column */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == ASCII_TBL) { ffasfm(colptr->tform, typecode, &tmpwidth, &decims, status); *width = tmpwidth; if (repeat) *repeat = 1; } else { if (typecode) *typecode = colptr->tdatatype; if (width) *width = colptr->twidth; if (repeat) *repeat = colptr->trepeat; } return(*status); } /*--------------------------------------------------------------------------*/ int ffeqty( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ long *repeat, /* O - repeat count of field */ long *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get the 'equivalent' table column type. This routine is similar to the ffgtcl routine (which returns the physical datatype of the column, as stored in the FITS file) except that if the TSCALn and TZEROn keywords are defined for the column, then it returns the 'equivalent' datatype. Thus, if the column is defined as '1I' (short integer) this routine may return the type as 'TUSHORT' or as 'TFLOAT' depending on the TSCALn and TZEROn values. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { LONGLONG trepeat, twidth; ffeqtyll(fptr, colnum, typecode, &trepeat, &twidth, status); if (repeat) *repeat= (long) trepeat; if (width) *width = (long) twidth; return(*status); } /*--------------------------------------------------------------------------*/ int ffeqtyll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ LONGLONG *repeat, /* O - repeat count of field */ LONGLONG *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get the 'equivalent' table column type. This routine is similar to the ffgtcl routine (which returns the physical datatype of the column, as stored in the FITS file) except that if the TSCALn and TZEROn keywords are defined for the column, then it returns the 'equivalent' datatype. Thus, if the column is defined as '1I' (short integer) this routine may return the type as 'TUSHORT' or as 'TFLOAT' depending on the TSCALn and TZEROn values. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { tcolumn *colptr; int hdutype, decims, tcode, effcode; double tscale, tzero, min_val, max_val; long lngscale, lngzero = 0, tmpwidth; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum - 1); /* offset to correct column */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == ASCII_TBL) { ffasfm(colptr->tform, typecode, &tmpwidth, &decims, status); if (width) *width = tmpwidth; if (repeat) *repeat = 1; } else { if (typecode) *typecode = colptr->tdatatype; if (width) *width = colptr->twidth; if (repeat) *repeat = colptr->trepeat; } /* return if caller is not interested in the typecode value */ if (!typecode) return(*status); /* check if the tscale and tzero keywords are defined, which might change the effective datatype of the column */ tscale = colptr->tscale; tzero = colptr->tzero; if (tscale == 1.0 && tzero == 0.0) /* no scaling */ return(*status); tcode = abs(*typecode); switch (tcode) { case TBYTE: /* binary table 'rB' column */ min_val = 0.; max_val = 255.0; break; case TSHORT: min_val = -32768.0; max_val = 32767.0; break; case TLONG: min_val = -2147483648.0; max_val = 2147483647.0; break; case TLONGLONG: min_val = -9.2233720368547755808E18; max_val = 9.2233720368547755807E18; break; default: /* don't have to deal with other data types */ return(*status); } if (tscale >= 0.) { min_val = tzero + tscale * min_val; max_val = tzero + tscale * max_val; } else { max_val = tzero + tscale * min_val; min_val = tzero + tscale * max_val; } if (tzero < 2147483648.) /* don't exceed range of 32-bit integer */ lngzero = (long) tzero; lngscale = (long) tscale; if ((tzero != 2147483648.) && /* special value that exceeds integer range */ (tzero != 9223372036854775808.) && /* indicates unsigned long long */ (lngzero != tzero || lngscale != tscale)) { /* not integers? */ /* floating point scaled values; just decide on required precision */ if (tcode == TBYTE || tcode == TSHORT) effcode = TFLOAT; else effcode = TDOUBLE; /* In all the remaining cases, TSCALn and TZEROn are integers, and not equal to 1 and 0, respectively. */ } else if ((min_val == -128.) && (max_val == 127.)) { effcode = TSBYTE; } else if ((min_val >= -32768.0) && (max_val <= 32767.0)) { effcode = TSHORT; } else if ((min_val >= 0.0) && (max_val <= 65535.0)) { effcode = TUSHORT; } else if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) { effcode = TLONG; } else if ((min_val >= 0.0) && (max_val < 4294967296.0)) { effcode = TULONG; } else if ((min_val >= -9.2233720368547755808E18) && (max_val <= 9.2233720368547755807E18)) { effcode = TLONGLONG; } else if ((min_val >= 0.0) && (max_val <= 1.8446744073709551616E19)) { effcode = TULONGLONG; } else { /* exceeds the range of a 64-bit integer */ effcode = TDOUBLE; } /* return the effective datatype code (negative if variable length col.) */ if (*typecode < 0) /* variable length array column */ *typecode = -effcode; else *typecode = effcode; return(*status); } /*--------------------------------------------------------------------------*/ int ffgncl( fitsfile *fptr, /* I - FITS file pointer */ int *ncols, /* O - number of columns in the table */ int *status) /* IO - error status */ /* Get the number of columns in the table (= TFIELDS keyword) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) return(*status = NOT_TABLE); *ncols = (fptr->Fptr)->tfield; return(*status); } /*--------------------------------------------------------------------------*/ int ffgnrw( fitsfile *fptr, /* I - FITS file pointer */ long *nrows, /* O - number of rows in the table */ int *status) /* IO - error status */ /* Get the number of rows in the table (= NAXIS2 keyword) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) return(*status = NOT_TABLE); /* the NAXIS2 keyword may not be up to date, so use the structure value */ *nrows = (long) (fptr->Fptr)->numrows; return(*status); } /*--------------------------------------------------------------------------*/ int ffgnrwll( fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *nrows, /* O - number of rows in the table */ int *status) /* IO - error status */ /* Get the number of rows in the table (= NAXIS2 keyword) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) return(*status = NOT_TABLE); /* the NAXIS2 keyword may not be up to date, so use the structure value */ *nrows = (fptr->Fptr)->numrows; return(*status); } /*--------------------------------------------------------------------------*/ int ffgacl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ char *ttype, /* O - TTYPEn keyword value */ long *tbcol, /* O - TBCOLn keyword value */ char *tunit, /* O - TUNITn keyword value */ char *tform, /* O - TFORMn keyword value */ double *tscal, /* O - TSCALn keyword value */ double *tzero, /* O - TZEROn keyword value */ char *tnull, /* O - TNULLn keyword value */ char *tdisp, /* O - TDISPn keyword value */ int *status) /* IO - error status */ /* get ASCII column keyword values */ { char name[FLEN_KEYWORD], comm[FLEN_COMMENT]; tcolumn *colptr; int tstatus; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); /* get what we can from the column structure */ colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum -1); /* offset to correct column */ if (ttype) strcpy(ttype, colptr->ttype); if (tbcol) *tbcol = (long) ((colptr->tbcol) + 1); /* first col is 1, not 0 */ if (tform) strcpy(tform, colptr->tform); if (tscal) *tscal = colptr->tscale; if (tzero) *tzero = colptr->tzero; if (tnull) strcpy(tnull, colptr->strnull); /* read keywords to get additional parameters */ if (tunit) { ffkeyn("TUNIT", colnum, name, status); tstatus = 0; *tunit = '\0'; ffgkys(fptr, name, tunit, comm, &tstatus); } if (tdisp) { ffkeyn("TDISP", colnum, name, status); tstatus = 0; *tdisp = '\0'; ffgkys(fptr, name, tdisp, comm, &tstatus); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgbcl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ char *ttype, /* O - TTYPEn keyword value */ char *tunit, /* O - TUNITn keyword value */ char *dtype, /* O - datatype char: I, J, E, D, etc. */ long *repeat, /* O - vector column repeat count */ double *tscal, /* O - TSCALn keyword value */ double *tzero, /* O - TZEROn keyword value */ long *tnull, /* O - TNULLn keyword value integer cols only */ char *tdisp, /* O - TDISPn keyword value */ int *status) /* IO - error status */ /* get BINTABLE column keyword values */ { LONGLONG trepeat, ttnull; if (*status > 0) return(*status); ffgbclll(fptr, colnum, ttype, tunit, dtype, &trepeat, tscal, tzero, &ttnull, tdisp, status); if (repeat) *repeat = (long) trepeat; if (tnull) *tnull = (long) ttnull; return(*status); } /*--------------------------------------------------------------------------*/ int ffgbclll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ char *ttype, /* O - TTYPEn keyword value */ char *tunit, /* O - TUNITn keyword value */ char *dtype, /* O - datatype char: I, J, E, D, etc. */ LONGLONG *repeat, /* O - vector column repeat count */ double *tscal, /* O - TSCALn keyword value */ double *tzero, /* O - TZEROn keyword value */ LONGLONG *tnull, /* O - TNULLn keyword value integer cols only */ char *tdisp, /* O - TDISPn keyword value */ int *status) /* IO - error status */ /* get BINTABLE column keyword values */ { char name[FLEN_KEYWORD], comm[FLEN_COMMENT]; tcolumn *colptr; int tstatus; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); /* get what we can from the column structure */ colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum -1); /* offset to correct column */ if (ttype) strcpy(ttype, colptr->ttype); if (dtype) { if (colptr->tdatatype < 0) /* add the "P" prefix for */ strcpy(dtype, "P"); /* variable length columns */ else dtype[0] = 0; if (abs(colptr->tdatatype) == TBIT) strcat(dtype, "X"); else if (abs(colptr->tdatatype) == TBYTE) strcat(dtype, "B"); else if (abs(colptr->tdatatype) == TLOGICAL) strcat(dtype, "L"); else if (abs(colptr->tdatatype) == TSTRING) strcat(dtype, "A"); else if (abs(colptr->tdatatype) == TSHORT) strcat(dtype, "I"); else if (abs(colptr->tdatatype) == TLONG) strcat(dtype, "J"); else if (abs(colptr->tdatatype) == TLONGLONG) strcat(dtype, "K"); else if (abs(colptr->tdatatype) == TFLOAT) strcat(dtype, "E"); else if (abs(colptr->tdatatype) == TDOUBLE) strcat(dtype, "D"); else if (abs(colptr->tdatatype) == TCOMPLEX) strcat(dtype, "C"); else if (abs(colptr->tdatatype) == TDBLCOMPLEX) strcat(dtype, "M"); } if (repeat) *repeat = colptr->trepeat; if (tscal) *tscal = colptr->tscale; if (tzero) *tzero = colptr->tzero; if (tnull) *tnull = colptr->tnull; /* read keywords to get additional parameters */ if (tunit) { ffkeyn("TUNIT", colnum, name, status); tstatus = 0; *tunit = '\0'; ffgkys(fptr, name, tunit, comm, &tstatus); } if (tdisp) { ffkeyn("TDISP", colnum, name, status); tstatus = 0; *tdisp = '\0'; ffgkys(fptr, name, tdisp, comm, &tstatus); } return(*status); } /*--------------------------------------------------------------------------*/ int ffghdn(fitsfile *fptr, /* I - FITS file pointer */ int *chdunum) /* O - number of the CHDU; 1 = primary array */ /* Return the number of the Current HDU in the FITS file. The primary array is HDU number 1. Note that this is one of the few cfitsio routines that does not return the error status value as the value of the function. */ { *chdunum = (fptr->HDUposition) + 1; return(*chdunum); } /*--------------------------------------------------------------------------*/ int ffghadll(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *headstart, /* O - byte offset to beginning of CHDU */ LONGLONG *datastart, /* O - byte offset to beginning of next HDU */ LONGLONG *dataend, /* O - byte offset to beginning of next HDU */ int *status) /* IO - error status */ /* Return the address (= byte offset) in the FITS file to the beginning of the current HDU, the beginning of the data unit, and the end of the data unit. */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { if (ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status) > 0) return(*status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if (ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } if (headstart) *headstart = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; if (datastart) *datastart = (fptr->Fptr)->datastart; if (dataend) *dataend = (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; return(*status); } /*--------------------------------------------------------------------------*/ int ffghof(fitsfile *fptr, /* I - FITS file pointer */ OFF_T *headstart, /* O - byte offset to beginning of CHDU */ OFF_T *datastart, /* O - byte offset to beginning of next HDU */ OFF_T *dataend, /* O - byte offset to beginning of next HDU */ int *status) /* IO - error status */ /* Return the address (= byte offset) in the FITS file to the beginning of the current HDU, the beginning of the data unit, and the end of the data unit. */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { if (ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status) > 0) return(*status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if (ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } if (headstart) *headstart = (OFF_T) (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; if (datastart) *datastart = (OFF_T) (fptr->Fptr)->datastart; if (dataend) *dataend = (OFF_T) (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; return(*status); } /*--------------------------------------------------------------------------*/ int ffghad(fitsfile *fptr, /* I - FITS file pointer */ long *headstart, /* O - byte offset to beginning of CHDU */ long *datastart, /* O - byte offset to beginning of next HDU */ long *dataend, /* O - byte offset to beginning of next HDU */ int *status) /* IO - error status */ /* Return the address (= byte offset) in the FITS file to the beginning of the current HDU, the beginning of the data unit, and the end of the data unit. */ { LONGLONG shead, sdata, edata; if (*status > 0) return(*status); ffghadll(fptr, &shead, &sdata, &edata, status); if (headstart) { if (shead > LONG_MAX) *status = NUM_OVERFLOW; else *headstart = (long) shead; } if (datastart) { if (sdata > LONG_MAX) *status = NUM_OVERFLOW; else *datastart = (long) sdata; } if (dataend) { if (edata > LONG_MAX) *status = NUM_OVERFLOW; else *dataend = (long) edata; } return(*status); } /*--------------------------------------------------------------------------*/ int ffrhdu(fitsfile *fptr, /* I - FITS file pointer */ int *hdutype, /* O - type of HDU */ int *status) /* IO - error status */ /* read the required keywords of the CHDU and initialize the corresponding structure elements that describe the format of the HDU */ { int ii, tstatus; char card[FLEN_CARD]; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xname[FLEN_VALUE], *xtension, urltype[20]; if (*status > 0) return(*status); if (ffgrec(fptr, 1, card, status) > 0 ) /* get the 80-byte card */ { ffpmsg("Cannot read first keyword in header (ffrhdu)."); return(*status); } strncpy(name,card,8); /* first 8 characters = the keyword name */ name[8] = '\0'; for (ii=7; ii >= 0; ii--) /* replace trailing blanks with nulls */ { if (name[ii] == ' ') name[ii] = '\0'; else break; } if (ffpsvc(card, value, comm, status) > 0) /* parse value and comment */ { ffpmsg("Cannot read value of first keyword in header (ffrhdu):"); ffpmsg(card); return(*status); } if (!strcmp(name, "SIMPLE")) /* this is the primary array */ { ffpinit(fptr, status); /* initialize the primary array */ if (hdutype != NULL) *hdutype = 0; } else if (!strcmp(name, "XTENSION")) /* this is an XTENSION keyword */ { if (ffc2s(value, xname, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } xtension = xname; while (*xtension == ' ') /* ignore any leading spaces in name */ xtension++; if (!strcmp(xtension, "TABLE")) { ffainit(fptr, status); /* initialize the ASCII table */ if (hdutype != NULL) *hdutype = 1; } else if (!strcmp(xtension, "BINTABLE") || !strcmp(xtension, "A3DTABLE") || !strcmp(xtension, "3DTABLE") ) { ffbinit(fptr, status); /* initialize the binary table */ if (hdutype != NULL) *hdutype = 2; } else { tstatus = 0; ffpinit(fptr, &tstatus); /* probably an IMAGE extension */ if (tstatus == UNKNOWN_EXT && hdutype != NULL) *hdutype = -1; /* don't recognize this extension type */ else { *status = tstatus; if (hdutype != NULL) *hdutype = 0; } } } else /* not the start of a new extension */ { if (card[0] == 0 || card[0] == 10) /* some editors append this character to EOF */ { *status = END_OF_FILE; } else { *status = UNKNOWN_REC; /* found unknown type of record */ ffpmsg ("Extension doesn't start with SIMPLE or XTENSION keyword. (ffrhdu)"); ffpmsg(card); } } /* compare the starting position of the next HDU (if any) with the size */ /* of the whole file to see if this is the last HDU in the file */ if ((fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] < (fptr->Fptr)->logfilesize ) { (fptr->Fptr)->lasthdu = 0; /* no, not the last HDU */ } else { (fptr->Fptr)->lasthdu = 1; /* yes, this is the last HDU */ /* special code for mem:// type files (FITS file in memory) */ /* Allocate enough memory to hold the entire HDU. */ /* Without this code, CFITSIO would repeatedly realloc memory */ /* to incrementally increase the size of the file by 2880 bytes */ /* at a time, until it reached the final size */ ffurlt(fptr, urltype, status); if (!strcmp(urltype,"mem://") || !strcmp(urltype,"memkeep://")) { fftrun(fptr, (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1], status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffpinit(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* initialize the parameters defining the structure of the primary array or an Image extension */ { int groups, tstatus, simple, bitpix, naxis, extend, nspace; int ttype = 0, bytlen = 0, ii, ntilebins; long pcount, gcount; LONGLONG naxes[999], npix, blank; double bscale, bzero; char comm[FLEN_COMMENT]; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->hdutype = IMAGE_HDU; /* primary array or IMAGE extension */ (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ groups = 0; tstatus = *status; /* get all the descriptive info about this HDU */ ffgphd(fptr, 999, &simple, &bitpix, &naxis, naxes, &pcount, &gcount, &extend, &bscale, &bzero, &blank, &nspace, status); if (*status == NOT_IMAGE) *status = tstatus; /* ignore 'unknown extension type' error */ else if (*status > 0) return(*status); /* the logical end of the header is 80 bytes before the current position, minus any trailing blank keywords just before the END keyword. */ (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); /* the data unit begins at the beginning of the next logical block */ (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) * 2880; if (naxis > 0 && naxes[0] == 0) /* test for 'random groups' */ { tstatus = 0; ffmaky(fptr, 2, status); /* reset to beginning of header */ if (ffgkyl(fptr, "GROUPS", &groups, comm, &tstatus)) groups = 0; /* GROUPS keyword not found */ } if (bitpix == BYTE_IMG) /* test bitpix and set the datatype code */ { ttype=TBYTE; bytlen=1; } else if (bitpix == SHORT_IMG) { ttype=TSHORT; bytlen=2; } else if (bitpix == LONG_IMG) { ttype=TLONG; bytlen=4; } else if (bitpix == LONGLONG_IMG) { ttype=TLONGLONG; bytlen=8; } else if (bitpix == FLOAT_IMG) { ttype=TFLOAT; bytlen=4; } else if (bitpix == DOUBLE_IMG) { ttype=TDOUBLE; bytlen=8; } /* calculate the size of the primary array */ (fptr->Fptr)->imgdim = naxis; if (naxis == 0) { npix = 0; } else { if (groups) { npix = 1; /* NAXIS1 = 0 is a special flag for 'random groups' */ } else { npix = naxes[0]; } (fptr->Fptr)->imgnaxis[0] = naxes[0]; for (ii=1; ii < naxis; ii++) { npix = npix*naxes[ii]; /* calc number of pixels in the array */ (fptr->Fptr)->imgnaxis[ii] = naxes[ii]; } } /* now we know everything about the array; just fill in the parameters: the next HDU begins in the next logical block after the data */ (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = (fptr->Fptr)->datastart + ( ((LONGLONG) pcount + npix) * bytlen * gcount + 2879) / 2880 * 2880; /* initialize the fictitious heap starting address (immediately following the array data) and a zero length heap. This is used to find the end of the data when checking the fill values in the last block. */ (fptr->Fptr)->heapstart = (npix + pcount) * bytlen * gcount; (fptr->Fptr)->heapsize = 0; (fptr->Fptr)->compressimg = 0; /* this is not a compressed image */ if (naxis == 0) { (fptr->Fptr)->rowlength = 0; /* rows have zero length */ (fptr->Fptr)->tfield = 0; /* table has no fields */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ (fptr->Fptr)->numrows = 0; (fptr->Fptr)->origrows = 0; } else { /* The primary array is actually interpreted as a binary table. There are two columns: the first column contains the group parameters if any. The second column contains the primary array of data as a single vector column element. In the case of 'random grouped' format, each group is stored in a separate row of the table. */ /* the number of rows is equal to the number of groups */ (fptr->Fptr)->numrows = gcount; (fptr->Fptr)->origrows = gcount; (fptr->Fptr)->rowlength = (npix + pcount) * bytlen; /* total size */ (fptr->Fptr)->tfield = 2; /* 2 fields: group params and the image */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ colptr = (tcolumn *) calloc(2, sizeof(tcolumn) ) ; if (!colptr) { ffpmsg ("malloc failed to get memory for FITS array descriptors (ffpinit)"); (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ return(*status = ARRAY_TOO_BIG); } /* copy the table structure address to the fitsfile structure */ (fptr->Fptr)->tableptr = colptr; /* the first column represents the group parameters, if any */ colptr->tbcol = 0; colptr->tdatatype = ttype; colptr->twidth = bytlen; colptr->trepeat = (LONGLONG) pcount; colptr->tscale = 1.; colptr->tzero = 0.; colptr->tnull = blank; colptr++; /* increment pointer to the second column */ /* the second column represents the image array */ colptr->tbcol = pcount * bytlen; /* col starts after the group parms */ colptr->tdatatype = ttype; colptr->twidth = bytlen; colptr->trepeat = npix; colptr->tscale = bscale; colptr->tzero = bzero; colptr->tnull = blank; } /* reset next keyword pointer to the start of the header */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; return(*status); } /*--------------------------------------------------------------------------*/ int ffainit(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* initialize the parameters defining the structure of an ASCII table */ int ii, nspace, ntilebins; long tfield; LONGLONG pcount, rowlen, nrows, tbcoln; tcolumn *colptr = 0; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char message[FLEN_ERRMSG], errmsg[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->hdutype = ASCII_TBL; /* set that this is an ASCII table */ (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ /* get table parameters and test that the header is a valid: */ if (ffgttb(fptr, &rowlen, &nrows, &pcount, &tfield, status) > 0) return(*status); if (pcount != 0) { ffpmsg("PCOUNT keyword not equal to 0 in ASCII table (ffainit)."); snprintf(errmsg, FLEN_ERRMSG," PCOUNT = %ld", (long) pcount); ffpmsg(errmsg); return(*status = BAD_PCOUNT); } (fptr->Fptr)->rowlength = rowlen; /* store length of a row */ (fptr->Fptr)->tfield = tfield; /* store number of table fields in row */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ /* mem for column structures ; space is initialized = 0 */ if (tfield > 0) { colptr = (tcolumn *) calloc(tfield, sizeof(tcolumn) ); if (!colptr) { ffpmsg ("malloc failed to get memory for FITS table descriptors (ffainit)"); (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ return(*status = ARRAY_TOO_BIG); } } /* copy the table structure address to the fitsfile structure */ (fptr->Fptr)->tableptr = colptr; /* initialize the table field parameters */ for (ii = 0; ii < tfield; ii++, colptr++) { colptr->ttype[0] = '\0'; /* null column name */ colptr->tscale = 1.; colptr->tzero = 0.; colptr->strnull[0] = ASCII_NULL_UNDEFINED; /* null value undefined */ colptr->tbcol = -1; /* initialize to illegal value */ colptr->tdatatype = -9999; /* initialize to illegal value */ } /* Initialize the fictitious heap starting address (immediately following the table data) and a zero length heap. This is used to find the end of the table data when checking the fill values in the last block. There is no special data following an ASCII table. */ (fptr->Fptr)->numrows = nrows; (fptr->Fptr)->origrows = nrows; (fptr->Fptr)->heapstart = rowlen * nrows; (fptr->Fptr)->heapsize = 0; (fptr->Fptr)->compressimg = 0; /* this is not a compressed image */ /* now search for the table column keywords and the END keyword */ for (nspace = 0, ii = 8; 1; ii++) /* infinite loop */ { ffgkyn(fptr, ii, name, value, comm, status); /* try to ignore minor syntax errors */ if (*status == NO_QUOTE) { strcat(value, "'"); *status = 0; } else if (*status == BAD_KEYCHAR) { *status = 0; } if (*status == END_OF_FILE) { ffpmsg("END keyword not found in ASCII table header (ffainit)."); return(*status = NO_END); } else if (*status > 0) return(*status); else if (name[0] == 'T') /* keyword starts with 'T' ? */ ffgtbp(fptr, name, value, status); /* test if column keyword */ else if (!FSTRCMP(name, "END")) /* is this the END keyword? */ break; if (!name[0] && !value[0] && !comm[0]) /* a blank keyword? */ nspace++; else nspace = 0; } /* test that all required keywords were found and have legal values */ colptr = (fptr->Fptr)->tableptr; for (ii = 0; ii < tfield; ii++, colptr++) { tbcoln = colptr->tbcol; /* the starting column number (zero based) */ if (colptr->tdatatype == -9999) { ffkeyn("TFORM", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Required %s keyword not found (ffainit).", name); ffpmsg(message); return(*status = NO_TFORM); } else if (tbcoln == -1) { ffkeyn("TBCOL", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Required %s keyword not found (ffainit).", name); ffpmsg(message); return(*status = NO_TBCOL); } else if ((fptr->Fptr)->rowlength != 0 && (tbcoln < 0 || tbcoln >= (fptr->Fptr)->rowlength ) ) { ffkeyn("TBCOL", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Value of %s keyword out of range: %ld (ffainit).", name, (long) tbcoln); ffpmsg(message); return(*status = BAD_TBCOL); } else if ((fptr->Fptr)->rowlength != 0 && tbcoln + colptr->twidth > (fptr->Fptr)->rowlength ) { snprintf(message,FLEN_ERRMSG,"Column %d is too wide to fit in table (ffainit)", ii+1); ffpmsg(message); snprintf(message, FLEN_ERRMSG," TFORM = %s and NAXIS1 = %ld", colptr->tform, (long) (fptr->Fptr)->rowlength); ffpmsg(message); return(*status = COL_TOO_WIDE); } } /* now we know everything about the table; just fill in the parameters: the 'END' record is 80 bytes before the current position, minus any trailing blank keywords just before the END keyword. */ (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); /* the data unit begins at the beginning of the next logical block */ (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) * 2880; /* the next HDU begins in the next logical block after the data */ (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = (fptr->Fptr)->datastart + ( ((LONGLONG)rowlen * nrows + 2879) / 2880 * 2880 ); /* reset next keyword pointer to the start of the header */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; return(*status); } /*--------------------------------------------------------------------------*/ int ffbinit(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* initialize the parameters defining the structure of a binary table */ int ii, nspace, ntilebins; long tfield; LONGLONG pcount, rowlen, nrows, totalwidth; tcolumn *colptr = 0; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char message[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->hdutype = BINARY_TBL; /* set that this is a binary table */ (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ /* get table parameters and test that the header is valid: */ if (ffgttb(fptr, &rowlen, &nrows, &pcount, &tfield, status) > 0) return(*status); (fptr->Fptr)->rowlength = rowlen; /* store length of a row */ (fptr->Fptr)->tfield = tfield; /* store number of table fields in row */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ /* mem for column structures ; space is initialized = 0 */ if (tfield > 0) { colptr = (tcolumn *) calloc(tfield, sizeof(tcolumn) ); if (!colptr) { ffpmsg ("malloc failed to get memory for FITS table descriptors (ffbinit)"); (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ return(*status = ARRAY_TOO_BIG); } } /* copy the table structure address to the fitsfile structure */ (fptr->Fptr)->tableptr = colptr; /* initialize the table field parameters */ for (ii = 0; ii < tfield; ii++, colptr++) { colptr->ttype[0] = '\0'; /* null column name */ colptr->tscale = 1.; colptr->tzero = 0.; colptr->tnull = NULL_UNDEFINED; /* (integer) null value undefined */ colptr->tdatatype = -9999; /* initialize to illegal value */ colptr->trepeat = 1; colptr->strnull[0] = '\0'; /* for ASCII string columns (TFORM = rA) */ } /* Initialize the heap starting address (immediately following the table data) and the size of the heap. This is used to find the end of the table data when checking the fill values in the last block. */ (fptr->Fptr)->numrows = nrows; (fptr->Fptr)->origrows = nrows; (fptr->Fptr)->heapstart = rowlen * nrows; (fptr->Fptr)->heapsize = pcount; (fptr->Fptr)->compressimg = 0; /* initialize as not a compressed image */ /* now search for the table column keywords and the END keyword */ for (nspace = 0, ii = 8; 1; ii++) /* infinite loop */ { ffgkyn(fptr, ii, name, value, comm, status); /* try to ignore minor syntax errors */ if (*status == NO_QUOTE) { strcat(value, "'"); *status = 0; } else if (*status == BAD_KEYCHAR) { *status = 0; } if (*status == END_OF_FILE) { ffpmsg("END keyword not found in binary table header (ffbinit)."); return(*status = NO_END); } else if (*status > 0) return(*status); else if (name[0] == 'T') /* keyword starts with 'T' ? */ ffgtbp(fptr, name, value, status); /* test if column keyword */ else if (!FSTRCMP(name, "ZIMAGE")) { if (value[0] == 'T') (fptr->Fptr)->compressimg = 1; /* this is a compressed image */ } else if (!FSTRCMP(name, "END")) /* is this the END keyword? */ break; if (!name[0] && !value[0] && !comm[0]) /* a blank keyword? */ nspace++; else nspace = 0; /* reset number of consecutive spaces before END */ } /* test that all the required keywords were found and have legal values */ colptr = (fptr->Fptr)->tableptr; /* set pointer to first column */ for (ii = 0; ii < tfield; ii++, colptr++) { if (colptr->tdatatype == -9999) { ffkeyn("TFORM", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Required %s keyword not found (ffbinit).", name); ffpmsg(message); return(*status = NO_TFORM); } } /* now we know everything about the table; just fill in the parameters: the 'END' record is 80 bytes before the current position, minus any trailing blank keywords just before the END keyword. */ (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); /* the data unit begins at the beginning of the next logical block */ (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) * 2880; /* the next HDU begins in the next logical block after the data */ (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = (fptr->Fptr)->datastart + ( ((fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize + 2879) / 2880 * 2880 ); /* determine the byte offset to the beginning of each column */ ffgtbc(fptr, &totalwidth, status); if (totalwidth != rowlen) { snprintf(message,FLEN_ERRMSG, "NAXIS1 = %ld is not equal to the sum of column widths: %ld", (long) rowlen, (long) totalwidth); ffpmsg(message); *status = BAD_ROW_WIDTH; } /* reset next keyword pointer to the start of the header */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; if ( (fptr->Fptr)->compressimg == 1) /* Is this a compressed image */ imcomp_get_compressed_image_par(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgabc(int tfields, /* I - number of columns in the table */ char **tform, /* I - value of TFORMn keyword for each column */ int space, /* I - number of spaces to leave between cols */ long *rowlen, /* O - total width of a table row */ long *tbcol, /* O - starting byte in row for each column */ int *status) /* IO - error status */ /* calculate the starting byte offset of each column of an ASCII table and the total length of a row, in bytes. The input space value determines how many blank spaces to leave between each column (1 is recommended). */ { int ii, datacode, decims; long width; if (*status > 0) return(*status); *rowlen=0; if (tfields <= 0) return(*status); tbcol[0] = 1; for (ii = 0; ii < tfields; ii++) { tbcol[ii] = *rowlen + 1; /* starting byte in row of column */ ffasfm(tform[ii], &datacode, &width, &decims, status); *rowlen += (width + space); /* total length of row */ } *rowlen -= space; /* don't add space after the last field */ return (*status); } /*--------------------------------------------------------------------------*/ int ffgtbc(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *totalwidth, /* O - total width of a table row */ int *status) /* IO - error status */ { /* calculate the starting byte offset of each column of a binary table. Use the values of the datatype code and repeat counts in the column structure. Return the total length of a row, in bytes. */ int tfields, ii; LONGLONG nbytes; tcolumn *colptr; char message[FLEN_ERRMSG], *cptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); tfields = (fptr->Fptr)->tfield; colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ *totalwidth = 0; for (ii = 0; ii < tfields; ii++, colptr++) { colptr->tbcol = *totalwidth; /* byte offset in row to this column */ if (colptr->tdatatype == TSTRING) { nbytes = colptr->trepeat; /* one byte per char */ } else if (colptr->tdatatype == TBIT) { nbytes = ( colptr->trepeat + 7) / 8; } else if (colptr->tdatatype > 0) { nbytes = colptr->trepeat * (colptr->tdatatype / 10); } else { cptr = colptr->tform; while (isdigit(*cptr)) cptr++; if (*cptr == 'P') /* this is a 'P' variable length descriptor (neg. tdatatype) */ nbytes = colptr->trepeat * 8; else if (*cptr == 'Q') /* this is a 'Q' variable length descriptor (neg. tdatatype) */ nbytes = colptr->trepeat * 16; else { snprintf(message,FLEN_ERRMSG, "unknown binary table column type: %s", colptr->tform); ffpmsg(message); *status = BAD_TFORM; return(*status); } } *totalwidth = *totalwidth + nbytes; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgtbp(fitsfile *fptr, /* I - FITS file pointer */ char *name, /* I - name of the keyword */ char *value, /* I - value string of the keyword */ int *status) /* IO - error status */ { /* Get TaBle Parameter. The input keyword name begins with the letter T. Test if the keyword is one of the table column definition keywords of an ASCII or binary table. If so, decode it and update the value in the structure. */ int tstatus, datacode, decimals; long width, repeat, nfield, ivalue; LONGLONG jjvalue; double dvalue; char tvalue[FLEN_VALUE], *loc; char message[FLEN_ERRMSG]; tcolumn *colptr; if (*status > 0) return(*status); tstatus = 0; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if(!FSTRNCMP(name + 1, "TYPE", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ return(*status); strcpy(colptr->ttype, tvalue); /* copy col name to structure */ } else if(!FSTRNCMP(name + 1, "FORM", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ return(*status); strncpy(colptr->tform, tvalue, 9); /* copy TFORM to structure */ colptr->tform[9] = '\0'; /* make sure it is terminated */ if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ { if (ffasfm(tvalue, &datacode, &width, &decimals, status) > 0) return(*status); /* bad format code */ colptr->tdatatype = TSTRING; /* store datatype code */ colptr->trepeat = 1; /* field repeat count == 1 */ colptr->twidth = width; /* the width of the field, in bytes */ } else /* binary table */ { if (ffbnfm(tvalue, &datacode, &repeat, &width, status) > 0) return(*status); /* bad format code */ colptr->tdatatype = datacode; /* store datatype code */ colptr->trepeat = (LONGLONG) repeat; /* field repeat count */ /* Don't overwrite the unit string width if it was previously */ /* set by a TDIMn keyword and has a legal value */ if (datacode == TSTRING) { if (colptr->twidth == 0 || colptr->twidth > repeat) colptr->twidth = width; /* width of a unit string */ } else { colptr->twidth = width; /* width of a unit value in chars */ } } } else if(!FSTRNCMP(name + 1, "BCOL", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if ((fptr->Fptr)->hdutype == BINARY_TBL) return(*status); /* binary tables don't have TBCOL keywords */ if (ffc2ii(value, &ivalue, status) > 0) { snprintf(message, FLEN_ERRMSG, "Error reading value of %s as an integer: %s", name, value); ffpmsg(message); return(*status); } colptr->tbcol = ivalue - 1; /* convert to zero base */ } else if(!FSTRNCMP(name + 1, "SCAL", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2dd(value, &dvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as a double: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } colptr->tscale = dvalue; } else if(!FSTRNCMP(name + 1, "ZERO", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2dd(value, &dvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as a double: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } colptr->tzero = dvalue; } else if(!FSTRNCMP(name + 1, "NULL", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ { if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ return(*status); strncpy(colptr->strnull, tvalue, 17); /* copy TNULL string */ colptr->strnull[17] = '\0'; /* terminate the strnull field */ } else /* binary table */ { if (ffc2jj(value, &jjvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as an integer: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } colptr->tnull = jjvalue; /* null value for integer column */ } } else if(!FSTRNCMP(name + 1, "DIM", 3) ) { if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ return(*status); /* ASCII tables don't support TDIMn keyword */ /* get the index number */ if( ffc2ii(name + 4, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ /* uninitialized columns have tdatatype set = -9999 */ if (colptr->tdatatype != -9999 && colptr->tdatatype != TSTRING) return(*status); /* this is not an ASCII string column */ loc = strchr(value, '(' ); /* find the opening parenthesis */ if (!loc) return(*status); /* not a proper TDIM keyword */ loc++; width = strtol(loc, &loc, 10); /* read size of first dimension */ if (colptr->trepeat != 1 && colptr->trepeat < width) return(*status); /* string length is greater than column width */ colptr->twidth = width; /* set width of a unit string in chars */ } else if (!FSTRNCMP(name + 1, "HEAP", 4) ) { if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ return(*status); /* ASCII tables don't have a heap */ if (ffc2jj(value, &jjvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as an integer: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } (fptr->Fptr)->heapstart = jjvalue; /* starting byte of the heap */ return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgcprll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ LONGLONG firstelem, /* I - first element within vector (1 = 1st) */ LONGLONG nelem, /* I - number of elements to read or write */ int writemode, /* I - = 1 if writing data, = 0 if reading data */ /* If = 2, then writing data, but don't modify */ /* the returned values of repeat and incre. */ /* If = -1, then reading data in reverse */ /* direction. */ /* If writemode has 16 added, then treat */ /* TSTRING column as TBYTE vector */ double *scale, /* O - FITS scaling factor (TSCALn keyword value) */ double *zero, /* O - FITS scaling zero pt (TZEROn keyword value) */ char *tform, /* O - ASCII column format: value of TFORMn keyword */ long *twidth, /* O - width of ASCII column (characters) */ int *tcode, /* O - abs(column datatype code): I*4=41, R*4=42, etc */ int *maxelem, /* O - max number of elements that fit in buffer */ LONGLONG *startpos,/* O - offset in file to starting row & column */ LONGLONG *elemnum, /* O - starting element number ( 0 = 1st element) */ long *incre, /* O - byte offset between elements within a row */ LONGLONG *repeat, /* O - number of elements in a row (vector column) */ LONGLONG *rowlen, /* O - length of a row, in bytes */ int *hdutype, /* O - HDU type: 0, 1, 2 = primary, table, bintable */ LONGLONG *tnull, /* O - null value for integer columns */ char *snull, /* O - null value for ASCII table columns */ int *status) /* IO - error status */ /* Get Column PaRameters, and test starting row and element numbers for validity. This is a workhorse routine that is call by nearly every other routine that reads or writes to FITS files. */ { int nulpos, rangecheck = 1, tstatus = 0; LONGLONG datastart, endpos; long nblock; LONGLONG heapoffset, lrepeat, endrow, nrows, tbcol; char message[FLEN_ERRMSG]; tcolumn *colptr; if (fptr->HDUposition != (fptr->Fptr)->curhdu) { /* reset position to the correct HDU if necessary */ ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { /* rescan header if data structure is undefined */ if ( ffrdef(fptr, status) > 0) return(*status); } else if (writemode > 0 && writemode != 15) { /* Only terminate the header with the END card if */ /* writing to the stdout stream (don't have random access). */ /* Initialize STREAM_DRIVER to be the device number for */ /* writing FITS files directly out to the stdout stream. */ /* This only needs to be done once and is thread safe. */ if (STREAM_DRIVER <= 0 || STREAM_DRIVER > 40) { urltype2driver("stream://", &STREAM_DRIVER); } if ((fptr->Fptr)->driver == STREAM_DRIVER) { if ((fptr->Fptr)->ENDpos != maxvalue((fptr->Fptr)->headend , (fptr->Fptr)->datastart -2880)) { ffwend(fptr, status); } } } /* Do sanity check of input parameters */ if (firstrow < 1) { if ((fptr->Fptr)->hdutype == IMAGE_HDU) /* Primary Array or IMAGE */ { snprintf(message,FLEN_ERRMSG, "Image group number is less than 1: %.0f", (double) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } else { snprintf(message, FLEN_ERRMSG,"Starting row number is less than 1: %.0f", (double) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } } else if ((fptr->Fptr)->hdutype != ASCII_TBL && firstelem < 1) { snprintf(message, FLEN_ERRMSG,"Starting element number less than 1: %ld", (long) firstelem); ffpmsg(message); return(*status = BAD_ELEM_NUM); } else if (nelem < 0) { snprintf(message, FLEN_ERRMSG,"Tried to read or write less than 0 elements: %.0f", (double) nelem); ffpmsg(message); return(*status = NEG_BYTES); } else if (colnum < 1 || colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d", colnum); ffpmsg(message); snprintf(message, FLEN_ERRMSG," There are %d columns in this table.", (fptr->Fptr)->tfield ); ffpmsg(message); return(*status = BAD_COL_NUM); } /* copy relevant parameters from the structure */ *hdutype = (fptr->Fptr)->hdutype; /* image, ASCII table, or BINTABLE */ *rowlen = (fptr->Fptr)->rowlength; /* width of the table, in bytes */ datastart = (fptr->Fptr)->datastart; /* offset in file to start of table */ colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ *scale = colptr->tscale; /* value scaling factor; default = 1.0 */ *zero = colptr->tzero; /* value scaling zeropoint; default = 0.0 */ *tnull = colptr->tnull; /* null value for integer columns */ tbcol = colptr->tbcol; /* offset to start of column within row */ *twidth = colptr->twidth; /* width of a single datum, in bytes */ *incre = colptr->twidth; /* increment between datums, in bytes */ *tcode = colptr->tdatatype; *repeat = colptr->trepeat; strcpy(tform, colptr->tform); /* value of TFORMn keyword */ strcpy(snull, colptr->strnull); /* null value for ASCII table columns */ if (*hdutype == ASCII_TBL && snull[0] == '\0') { /* In ASCII tables, a null value is equivalent to all spaces */ strcpy(snull, " "); /* maximum of 17 spaces */ nulpos = minvalue(17, *twidth); /* truncate to width of column */ snull[nulpos] = '\0'; } /* Special case: use writemode = 15,16,17,18 to interpret TSTRING columns as TBYTE vectors instead (but not for ASCII tables). writemode = 15 equivalent to writemode =-1 writemode = 16 equivalent to writemode = 0 writemode = 17 equivalent to writemode = 1 writemode = 18 equivalent to writemode = 2 */ if (writemode >= 15 && writemode <= 18) { if (abs(*tcode) == TSTRING && *hdutype != ASCII_TBL ) { *incre = 1; /* each element is 1 byte wide */ if (*tcode < 0) *repeat = *twidth; /* variable columns appear to put width in *twidth */ *twidth = 1; /* width of each element */ *scale = 1.0; /* no scaling */ *zero = 0.0; *tnull = NULL_UNDEFINED; /* don't test for nulls */ *maxelem = DBUFFSIZE; if (*tcode < 0) { *tcode = -TBYTE; /* variable-length */ } else { *tcode = TBYTE; } } /* translate to the equivalent as listed above */ writemode -= 16; } /* Special case: interpret writemode = -1 as reading data, but */ /* don't do error check for exceeding the range of pixels */ if (writemode == -1) { writemode = 0; rangecheck = 0; } /* Special case: interprete 'X' column as 'B' */ if (abs(*tcode) == TBIT) { *tcode = *tcode / TBIT * TBYTE; *repeat = (*repeat + 7) / 8; } /* Special case: support the 'rAw' format in BINTABLEs */ if (*hdutype == BINARY_TBL && *tcode == TSTRING) { if (*twidth) *repeat = *repeat / *twidth; /* repeat = # of unit strings in field */ else *repeat = 0; } else if (*hdutype == BINARY_TBL && *tcode == -TSTRING) { /* variable length string */ *incre = 1; *twidth = (long) nelem; } if (*hdutype == ASCII_TBL) *elemnum = 0; /* ASCII tables don't have vector elements */ else *elemnum = firstelem - 1; /* interprete complex and double complex as pairs of floats or doubles */ if (abs(*tcode) >= TCOMPLEX) { if (*tcode > 0) *tcode = (*tcode + 1) / 2; else *tcode = (*tcode - 1) / 2; *repeat = *repeat * 2; *twidth = *twidth / 2; *incre = *incre / 2; } /* calculate no. of pixels that fit in buffer */ /* allow for case where floats are 8 bytes long */ if (abs(*tcode) == TFLOAT) *maxelem = DBUFFSIZE / sizeof(float); else if (abs(*tcode) == TDOUBLE) *maxelem = DBUFFSIZE / sizeof(double); else if (abs(*tcode) == TSTRING) { if (*twidth) *maxelem = (DBUFFSIZE - 1)/ *twidth; /* leave room for final \0 */ else *maxelem = DBUFFSIZE - 1; if (*maxelem == 0) { snprintf(message,FLEN_ERRMSG, "ASCII string column is too wide: %ld; max supported width is %d", *twidth, DBUFFSIZE - 1); ffpmsg(message); return(*status = COL_TOO_WIDE); } } else *maxelem = DBUFFSIZE / *twidth; /* calc starting byte position to 1st element of col */ /* (this does not apply to variable length columns) */ *startpos = datastart + ((LONGLONG)(firstrow - 1) * *rowlen) + tbcol; if (*hdutype == IMAGE_HDU && writemode) /* Primary Array or IMAGE */ { /* For primary arrays, set the repeat count greater than the total number of pixels to be written. This prevents an out-of-range error message in cases where the final image array size is not yet known or defined. */ if (*repeat < *elemnum + nelem) *repeat = *elemnum + nelem; } else if (*tcode > 0) /* Fixed length table column */ { if (*elemnum >= *repeat) { snprintf(message,FLEN_ERRMSG, "First element to write is too large: %ld; max allowed value is %ld", (long) ((*elemnum) + 1), (long) *repeat); ffpmsg(message); return(*status = BAD_ELEM_NUM); } /* last row number to be read or written */ endrow = ((*elemnum + nelem - 1) / *repeat) + firstrow; if (writemode) { /* check if we are writing beyond the current end of table */ if ((endrow > (fptr->Fptr)->numrows) && (nelem > 0) ) { /* if there are more HDUs following the current one, or */ /* if there is a data heap, then we must insert space */ /* for the new rows. */ if ( !((fptr->Fptr)->lasthdu) || (fptr->Fptr)->heapsize > 0) { nrows = endrow - ((fptr->Fptr)->numrows); if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) { snprintf(message,FLEN_ERRMSG, "Failed to add space for %.0f new rows in table.", (double) nrows); ffpmsg(message); return(*status); } } else { /* update heap starting address */ (fptr->Fptr)->heapstart += ((LONGLONG)(endrow - (fptr->Fptr)->numrows) * (fptr->Fptr)->rowlength ); (fptr->Fptr)->numrows = endrow; /* update number of rows */ } } } else /* reading from the file */ { if ( endrow > (fptr->Fptr)->numrows && rangecheck) { if (*hdutype == IMAGE_HDU) /* Primary Array or IMAGE */ { if (firstrow > (fptr->Fptr)->numrows) { snprintf(message, FLEN_ERRMSG, "Attempted to read from group %ld of the HDU,", (long) firstrow); ffpmsg(message); snprintf(message, FLEN_ERRMSG, "however the HDU only contains %ld group(s).", (long) ((fptr->Fptr)->numrows) ); ffpmsg(message); } else { ffpmsg("Attempt to read past end of array:"); snprintf(message, FLEN_ERRMSG, " Image has %ld elements;", (long) *repeat); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Tried to read %ld elements starting at element %ld.", (long) nelem, (long) firstelem); ffpmsg(message); } } else { ffpmsg("Attempt to read past end of table:"); snprintf(message, FLEN_ERRMSG, " Table has %.0f rows with %.0f elements per row;", (double) ((fptr->Fptr)->numrows), (double) *repeat); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Tried to read %.0f elements starting at row %.0f, element %.0f.", (double) nelem, (double) firstrow, (double) ((*elemnum) + 1)); ffpmsg(message); } return(*status = BAD_ROW_NUM); } } if (*repeat == 1 && nelem > 1 && writemode != 2) { /* When accessing a scalar column, fool the calling routine into thinking that this is a vector column with very big elements. This allows multiple values (up to the maxelem number of elements that will fit in the buffer) to be read or written with a single routine call, which increases the efficiency. If writemode == 2, then the calling program does not want to have this efficiency trick applied. */ if (*rowlen <= LONG_MAX) { *incre = (long) *rowlen; *repeat = nelem; } } } else /* Variable length Binary Table column */ { *tcode *= (-1); if (writemode) /* return next empty heap address for writing */ { *repeat = nelem + *elemnum; /* total no. of elements in the field */ /* first, check if we are overwriting an existing row, and */ /* if so, if the existing space is big enough for the new vector */ if ( firstrow <= (fptr->Fptr)->numrows ) { ffgdesll(fptr, colnum, firstrow, &lrepeat, &heapoffset, &tstatus); if (!tstatus) { if (colptr->tdatatype <= -TCOMPLEX) lrepeat = lrepeat * 2; /* no. of float or double values */ else if (colptr->tdatatype == -TBIT) lrepeat = (lrepeat + 7) / 8; /* convert from bits to bytes */ if (lrepeat >= *repeat) /* enough existing space? */ { *startpos = datastart + heapoffset + (fptr->Fptr)->heapstart; /* write the descriptor into the fixed length part of table */ if (colptr->tdatatype <= -TCOMPLEX) { /* divide repeat count by 2 to get no. of complex values */ ffpdes(fptr, colnum, firstrow, *repeat / 2, heapoffset, status); } else { ffpdes(fptr, colnum, firstrow, *repeat, heapoffset, status); } return(*status); } } } /* Add more rows to the table, if writing beyond the end. */ /* It is necessary to shift the heap down in this case */ if ( firstrow > (fptr->Fptr)->numrows) { nrows = firstrow - ((fptr->Fptr)->numrows); if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) { snprintf(message,FLEN_ERRMSG, "Failed to add space for %.0f new rows in table.", (double) nrows); ffpmsg(message); return(*status); } } /* calculate starting position (for writing new data) in the heap */ *startpos = datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; /* write the descriptor into the fixed length part of table */ if (colptr->tdatatype <= -TCOMPLEX) { /* divide repeat count by 2 to get no. of complex values */ ffpdes(fptr, colnum, firstrow, *repeat / 2, (fptr->Fptr)->heapsize, status); } else { ffpdes(fptr, colnum, firstrow, *repeat, (fptr->Fptr)->heapsize, status); } /* If this is not the last HDU in the file, then check if */ /* extending the heap would overwrite the following header. */ /* If so, then have to insert more blocks. */ if ( !((fptr->Fptr)->lasthdu) ) { endpos = datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize + ( *repeat * (*incre)); if (endpos > (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1]) { /* calc the number of blocks that need to be added */ nblock = (long) (((endpos - 1 - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] ) / 2880) + 1); if (ffiblk(fptr, nblock, 1, status) > 0) /* insert blocks */ { snprintf(message,FLEN_ERRMSG, "Failed to extend the size of the variable length heap by %ld blocks.", nblock); ffpmsg(message); return(*status); } } } /* increment the address to the next empty heap position */ (fptr->Fptr)->heapsize += ( *repeat * (*incre)); } else /* get the read start position in the heap */ { if ( firstrow > (fptr->Fptr)->numrows) { ffpmsg("Attempt to read past end of table"); snprintf(message,FLEN_ERRMSG, " Table has %.0f rows and tried to read row %.0f.", (double) ((fptr->Fptr)->numrows), (double) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } ffgdesll(fptr, colnum, firstrow, &lrepeat, &heapoffset, status); *repeat = lrepeat; if (colptr->tdatatype <= -TCOMPLEX) *repeat = *repeat * 2; /* no. of float or double values */ else if (colptr->tdatatype == -TBIT) *repeat = (*repeat + 7) / 8; /* convert from bits to bytes */ if (*elemnum >= *repeat) { snprintf(message,FLEN_ERRMSG, "Starting element to read in variable length column is too large: %ld", (long) firstelem); ffpmsg(message); snprintf(message,FLEN_ERRMSG, " This row only contains %ld elements", (long) *repeat); ffpmsg(message); return(*status = BAD_ELEM_NUM); } *startpos = datastart + heapoffset + (fptr->Fptr)->heapstart; } } return(*status); } /*---------------------------------------------------------------------------*/ int fftheap(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *heapsz, /* O - current size of the heap */ LONGLONG *unused, /* O - no. of unused bytes in the heap */ LONGLONG *overlap, /* O - no. of bytes shared by > 1 descriptors */ int *valid, /* O - are all the heap addresses valid? */ int *status) /* IO - error status */ /* Tests the contents of the binary table variable length array heap. Returns the number of bytes that are currently not pointed to by any of the descriptors, and also the number of bytes that are pointed to by more than one descriptor. It returns valid = FALSE if any of the descriptors point to addresses that are out of the bounds of the heap. */ { int jj, typecode, pixsize; long ii, kk, theapsz, nbytes; LONGLONG repeat, offset, tunused = 0, toverlap = 0; char *buffer, message[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if ( fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header to make sure everything is up to date */ else if ( ffrdef(fptr, status) > 0) return(*status); if (valid) *valid = TRUE; if (heapsz) *heapsz = (fptr->Fptr)->heapsize; if (unused) *unused = 0; if (overlap) *overlap = 0; /* return if this is not a binary table HDU or if the heap is empty */ if ( (fptr->Fptr)->hdutype != BINARY_TBL || (fptr->Fptr)->heapsize == 0 ) return(*status); if ((fptr->Fptr)->heapsize > LONG_MAX) { ffpmsg("Heap is too big to test ( > 2**31 bytes). (fftheap)"); return(*status = MEMORY_ALLOCATION); } theapsz = (long) (fptr->Fptr)->heapsize; buffer = calloc(1, theapsz); /* allocate temp space */ if (!buffer ) { snprintf(message,FLEN_ERRMSG,"Failed to allocate buffer to test the heap"); ffpmsg(message); return(*status = MEMORY_ALLOCATION); } /* loop over all cols */ for (jj = 1; jj <= (fptr->Fptr)->tfield && *status <= 0; jj++) { ffgtcl(fptr, jj, &typecode, NULL, NULL, status); if (typecode > 0) continue; /* ignore fixed length columns */ pixsize = -typecode / 10; for (ii = 1; ii <= (fptr->Fptr)->numrows; ii++) { ffgdesll(fptr, jj, ii, &repeat, &offset, status); if (typecode == -TBIT) nbytes = (long) (repeat + 7) / 8; else nbytes = (long) repeat * pixsize; if (offset < 0 || offset + nbytes > theapsz) { if (valid) *valid = FALSE; /* address out of bounds */ snprintf(message,FLEN_ERRMSG, "Descriptor in row %ld, column %d has invalid heap address", ii, jj); ffpmsg(message); } else { for (kk = 0; kk < nbytes; kk++) buffer[kk + offset]++; /* increment every used byte */ } } } for (kk = 0; kk < theapsz; kk++) { if (buffer[kk] == 0) tunused++; else if (buffer[kk] > 1) toverlap++; } if (heapsz) *heapsz = theapsz; if (unused) *unused = tunused; if (overlap) *overlap = toverlap; free(buffer); return(*status); } /*--------------------------------------------------------------------------*/ int ffcmph(fitsfile *fptr, /* I -FITS file pointer */ int *status) /* IO - error status */ /* compress the binary table heap by reordering the contents heap and recovering any unused space */ { fitsfile *tptr; int jj, typecode, pixsize, valid; long ii, buffsize = 10000, nblock, nbytes; LONGLONG unused, overlap; LONGLONG repeat, offset; char *buffer, *tbuff, comm[FLEN_COMMENT]; char message[FLEN_ERRMSG]; LONGLONG pcount; LONGLONG readheapstart, writeheapstart, endpos, t1heapsize, t2heapsize; if (*status > 0) return(*status); /* get information about the current heap */ fftheap(fptr, NULL, &unused, &overlap, &valid, status); if (!valid) return(*status = BAD_HEAP_PTR); /* bad heap pointers */ /* return if this is not a binary table HDU or if the heap is OK as is */ if ( (fptr->Fptr)->hdutype != BINARY_TBL || (fptr->Fptr)->heapsize == 0 || (unused == 0 && overlap == 0) || *status > 0 ) return(*status); /* copy the current HDU to a temporary file in memory */ if (ffinit( &tptr, "mem://tempheapfile", status) ) { snprintf(message,FLEN_ERRMSG,"Failed to create temporary file for the heap"); ffpmsg(message); return(*status); } if ( ffcopy(fptr, tptr, 0, status) ) { snprintf(message,FLEN_ERRMSG,"Failed to create copy of the heap"); ffpmsg(message); ffclos(tptr, status); return(*status); } buffer = (char *) malloc(buffsize); /* allocate initial buffer */ if (!buffer) { snprintf(message,FLEN_ERRMSG,"Failed to allocate buffer to copy the heap"); ffpmsg(message); ffclos(tptr, status); return(*status = MEMORY_ALLOCATION); } readheapstart = (tptr->Fptr)->datastart + (tptr->Fptr)->heapstart; writeheapstart = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; t1heapsize = (fptr->Fptr)->heapsize; /* save original heap size */ (fptr->Fptr)->heapsize = 0; /* reset heap to zero */ /* loop over all cols */ for (jj = 1; jj <= (fptr->Fptr)->tfield && *status <= 0; jj++) { ffgtcl(tptr, jj, &typecode, NULL, NULL, status); if (typecode > 0) continue; /* ignore fixed length columns */ pixsize = -typecode / 10; /* copy heap data, row by row */ for (ii = 1; ii <= (fptr->Fptr)->numrows; ii++) { ffgdesll(tptr, jj, ii, &repeat, &offset, status); if (typecode == -TBIT) nbytes = (long) (repeat + 7) / 8; else nbytes = (long) repeat * pixsize; /* increase size of buffer if necessary to read whole array */ if (nbytes > buffsize) { tbuff = realloc(buffer, nbytes); if (tbuff) { buffer = tbuff; buffsize = nbytes; } else *status = MEMORY_ALLOCATION; } /* If this is not the last HDU in the file, then check if */ /* extending the heap would overwrite the following header. */ /* If so, then have to insert more blocks. */ if ( !((fptr->Fptr)->lasthdu) ) { endpos = writeheapstart + (fptr->Fptr)->heapsize + nbytes; if (endpos > (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1]) { /* calc the number of blocks that need to be added */ nblock = (long) (((endpos - 1 - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] ) / 2880) + 1); if (ffiblk(fptr, nblock, 1, status) > 0) /* insert blocks */ { snprintf(message,FLEN_ERRMSG, "Failed to extend the size of the variable length heap by %ld blocks.", nblock); ffpmsg(message); } } } /* read arrray of bytes from temporary copy */ ffmbyt(tptr, readheapstart + offset, REPORT_EOF, status); ffgbyt(tptr, nbytes, buffer, status); /* write arrray of bytes back to original file */ ffmbyt(fptr, writeheapstart + (fptr->Fptr)->heapsize, IGNORE_EOF, status); ffpbyt(fptr, nbytes, buffer, status); /* write descriptor */ ffpdes(fptr, jj, ii, repeat, (fptr->Fptr)->heapsize, status); (fptr->Fptr)->heapsize += nbytes; /* update heapsize */ if (*status > 0) { free(buffer); ffclos(tptr, status); return(*status); } } } free(buffer); ffclos(tptr, status); /* delete any empty blocks at the end of the HDU */ nblock = (long) (( (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] - (writeheapstart + (fptr->Fptr)->heapsize) ) / 2880); if (nblock > 0) { t2heapsize = (fptr->Fptr)->heapsize; /* save new heap size */ (fptr->Fptr)->heapsize = t1heapsize; /* restore original heap size */ ffdblk(fptr, nblock, status); (fptr->Fptr)->heapsize = t2heapsize; /* reset correct heap size */ } /* update the PCOUNT value (size of heap) */ ffmaky(fptr, 2, status); /* reset to beginning of header */ ffgkyjj(fptr, "PCOUNT", &pcount, comm, status); if ((fptr->Fptr)->heapsize != pcount) { ffmkyj(fptr, "PCOUNT", (fptr->Fptr)->heapsize, comm, status); } ffrdef(fptr, status); /* rescan new HDU structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgdes(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG rownum, /* I - row number (1 = 1st row of table) */ long *length, /* O - number of elements in the row */ long *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) the variable length vector descriptor from the table. */ { LONGLONG lengthjj, heapaddrjj; if (ffgdesll(fptr, colnum, rownum, &lengthjj, &heapaddrjj, status) > 0) return(*status); /* convert the temporary 8-byte values to 4-byte values */ /* check for overflow */ if (length) { if (lengthjj > LONG_MAX) *status = NUM_OVERFLOW; else *length = (long) lengthjj; } if (heapaddr) { if (heapaddrjj > LONG_MAX) *status = NUM_OVERFLOW; else *heapaddr = (long) heapaddrjj; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgdesll(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG rownum, /* I - row number (1 = 1st row of table) */ LONGLONG *length, /* O - number of elements in the row */ LONGLONG *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) the variable length vector descriptor from the binary table. This is similar to ffgdes, except it supports the full 8-byte range of the length and offset values in 'Q' columns, as well as 'P' columns. */ { LONGLONG bytepos; unsigned int descript4[2] = {0,0}; LONGLONG descript8[2] = {0,0}; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) { *status = NOT_VARI_LEN; return(*status); } bytepos = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * (rownum - 1)) + colptr->tbcol; if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { /* read 4-byte descriptor */ if (ffgi4b(fptr, bytepos, 2, 4, (INT32BIT *) descript4, status) <= 0) { if (length) *length = (LONGLONG) descript4[0]; /* 1st word is the length */ if (heapaddr) *heapaddr = (LONGLONG) descript4[1]; /* 2nd word is the address */ } } else /* this is for 'Q' columns */ { /* read 8 byte descriptor */ if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) { if (length) *length = descript8[0]; /* 1st word is the length */ if (heapaddr) *heapaddr = descript8[1]; /* 2nd word is the address */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgdess(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ LONGLONG nrows, /* I - number or rows to read */ long *length, /* O - number of elements in the row */ long *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) a range of variable length vector descriptors from the table. */ { LONGLONG rowsize, bytepos; long ii; INT32BIT descript4[2] = {0,0}; LONGLONG descript8[2] = {0,0}; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) { *status = NOT_VARI_LEN; return(*status); } rowsize = (fptr->Fptr)->rowlength; bytepos = (fptr->Fptr)->datastart + (rowsize * (firstrow - 1)) + colptr->tbcol; if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { /* read 4-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ if (ffgi4b(fptr, bytepos, 2, 4, descript4, status) <= 0) { if (length) { *length = (long) descript4[0]; /* 1st word is the length */ length++; } if (heapaddr) { *heapaddr = (long) descript4[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } else /* this is for 'Q' columns */ { /* read 8-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) { if (length) { if (descript8[0] > LONG_MAX)*status = NUM_OVERFLOW; *length = (long) descript8[0]; /* 1st word is the length */ length++; } if (heapaddr) { if (descript8[1] > LONG_MAX)*status = NUM_OVERFLOW; *heapaddr = (long) descript8[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgdessll(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ LONGLONG nrows, /* I - number or rows to read */ LONGLONG *length, /* O - number of elements in the row */ LONGLONG *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) a range of variable length vector descriptors from the table. */ { LONGLONG rowsize, bytepos; long ii; unsigned int descript4[2] = {0,0}; LONGLONG descript8[2] = {0,0}; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) { *status = NOT_VARI_LEN; return(*status); } rowsize = (fptr->Fptr)->rowlength; bytepos = (fptr->Fptr)->datastart + (rowsize * (firstrow - 1)) + colptr->tbcol; if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { /* read 4-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ if (ffgi4b(fptr, bytepos, 2, 4, (INT32BIT *) descript4, status) <= 0) { if (length) { *length = (LONGLONG) descript4[0]; /* 1st word is the length */ length++; } if (heapaddr) { *heapaddr = (LONGLONG) descript4[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } else /* this is for 'Q' columns */ { /* read 8-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ /* cast to type (long *) even though it is actually (LONGLONG *) */ if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) { if (length) { *length = descript8[0]; /* 1st word is the length */ length++; } if (heapaddr) { *heapaddr = descript8[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffpdes(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG rownum, /* I - row number (1 = 1st row of table) */ LONGLONG length, /* I - number of elements in the row */ LONGLONG heapaddr, /* I - heap pointer to the data */ int *status) /* IO - error status */ /* put (write) the variable length vector descriptor to the table. */ { LONGLONG bytepos; unsigned int descript4[2]; LONGLONG descript8[2]; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) *status = NOT_VARI_LEN; bytepos = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * (rownum - 1)) + colptr->tbcol; ffmbyt(fptr, bytepos, IGNORE_EOF, status); /* move to element */ if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { if (length > UINT_MAX || length < 0 || heapaddr > UINT_MAX || heapaddr < 0) { ffpmsg("P variable length column descriptor is out of range"); *status = NUM_OVERFLOW; return(*status); } descript4[0] = (unsigned int) length; /* 1st word is the length */ descript4[1] = (unsigned int) heapaddr; /* 2nd word is the address */ ffpi4b(fptr, 2, 4, (INT32BIT *) descript4, status); /* write the descriptor */ } else /* this is a 'Q' descriptor column */ { descript8[0] = length; /* 1st word is the length */ descript8[1] = heapaddr; /* 2nd word is the address */ ffpi8b(fptr, 2, 8, (long *) descript8, status); /* write the descriptor */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffchdu(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* close the current HDU. If we have write access to the file, then: - write the END keyword and pad header with blanks if necessary - check the data fill values, and rewrite them if not correct */ char message[FLEN_ERRMSG]; int ii, stdriver, ntilebins; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* no need to do any further updating of the HDU */ } else if ((fptr->Fptr)->writemode == 1) { urltype2driver("stream://", &stdriver); /* don't rescan header in special case of writing to stdout */ if (((fptr->Fptr)->driver != stdriver)) ffrdef(fptr, status); if ((fptr->Fptr)->heapsize > 0) { ffuptf(fptr, status); /* update the variable length TFORM values */ } ffpdfl(fptr, status); /* insure correct data fill values */ } if ((fptr->Fptr)->open_count == 1) { /* free memory for the CHDU structure only if no other files are using it */ if ((fptr->Fptr)->tableptr) { free((fptr->Fptr)->tableptr); (fptr->Fptr)->tableptr = NULL; /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } } } if (*status > 0 && *status != NO_CLOSE_ERROR) { snprintf(message,FLEN_ERRMSG, "Error while closing HDU number %d (ffchdu).", (fptr->Fptr)->curhdu); ffpmsg(message); } return(*status); } /*--------------------------------------------------------------------------*/ int ffuptf(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Update the value of the TFORM keywords for the variable length array columns to make sure they all have the form 1Px(len) or Px(len) where 'len' is the maximum length of the vector in the table (e.g., '1PE(400)') */ { int ii, lenform=0; long tflds; LONGLONG length, addr, maxlen, naxis2, jj; char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD]; char tform[FLEN_VALUE], newform[FLEN_VALUE], lenval[40]; char card[FLEN_CARD]; char message[FLEN_ERRMSG]; char *tmp; ffmaky(fptr, 2, status); /* reset to beginning of header */ ffgkyjj(fptr, "NAXIS2", &naxis2, comment, status); ffgkyj(fptr, "TFIELDS", &tflds, comment, status); for (ii = 1; ii <= tflds; ii++) /* loop over all the columns */ { ffkeyn("TFORM", ii, keyname, status); /* construct name */ if (ffgkys(fptr, keyname, tform, comment, status) > 0) { snprintf(message,FLEN_ERRMSG, "Error while updating variable length vector TFORMn values (ffuptf)."); ffpmsg(message); return(*status); } /* is this a variable array length column ? */ if (tform[0] == 'P' || tform[1] == 'P' || tform[0] == 'Q' || tform[1] == 'Q') { /* get the max length */ maxlen = 0; for (jj=1; jj <= naxis2; jj++) { ffgdesll(fptr, ii, jj, &length, &addr, status); if (length > maxlen) maxlen = length; } /* construct the new keyword value */ strcpy(newform, "'"); tmp = strchr(tform, '('); /* truncate old length, if present */ if (tmp) *tmp = 0; lenform = strlen(tform); /* print as double, because the string-to-64-bit */ /* conversion is platform dependent (%lld, %ld, %I64d) */ snprintf(lenval,40, "(%.0f)", (double) maxlen); if (lenform+strlen(lenval)+2 > FLEN_VALUE-1) { ffpmsg("Error assembling TFORMn string (ffuptf)."); return(*status = BAD_TFORM); } strcat(newform, tform); strcat(newform,lenval); while(strlen(newform) < 9) strcat(newform," "); /* append spaces 'till length = 8 */ strcat(newform,"'" ); /* append closing parenthesis */ /* would be simpler to just call ffmkyj here, but this */ /* would force linking in all the modkey & putkey routines */ ffmkky(keyname, newform, comment, card, status); /* make new card */ ffmkey(fptr, card, status); /* replace last read keyword */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffrdef(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* ReDEFine the structure of a data unit. This routine re-reads the CHDU header keywords to determine the structure and length of the current data unit. This redefines the start of the next HDU. */ { int dummy, tstatus = 0; LONGLONG naxis2; LONGLONG pcount; char card[FLEN_CARD], comm[FLEN_COMMENT], valstring[FLEN_VALUE]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->writemode == 1) /* write access to the file? */ { /* don't need to check NAXIS2 and PCOUNT if data hasn't been written */ if ((fptr->Fptr)->datastart != DATA_UNDEFINED) { /* update NAXIS2 keyword if more rows were written to the table */ /* and if the user has not explicitly reset the NAXIS2 value */ if ((fptr->Fptr)->hdutype != IMAGE_HDU) { ffmaky(fptr, 2, status); if (ffgkyjj(fptr, "NAXIS2", &naxis2, comm, &tstatus) > 0) { /* Couldn't read NAXIS2 (odd!); in certain circumstances */ /* this may be normal, so ignore the error. */ naxis2 = (fptr->Fptr)->numrows; } if ((fptr->Fptr)->numrows > naxis2 && (fptr->Fptr)->origrows == naxis2) /* if origrows is not equal to naxis2, then the user must */ /* have manually modified the NAXIS2 keyword value, and */ /* we will assume that the current value is correct. */ { /* would be simpler to just call ffmkyj here, but this */ /* would force linking in all the modkey & putkey routines */ /* print as double because the 64-bit int conversion */ /* is platform dependent (%lld, %ld, %I64 ) */ snprintf(valstring,FLEN_VALUE, "%.0f", (double) ((fptr->Fptr)->numrows)); ffmkky("NAXIS2", valstring, comm, card, status); ffmkey(fptr, card, status); } } /* if data has been written to variable length columns in a */ /* binary table, then we may need to update the PCOUNT value */ if ((fptr->Fptr)->heapsize > 0) { ffmaky(fptr, 2, status); ffgkyjj(fptr, "PCOUNT", &pcount, comm, status); if ((fptr->Fptr)->heapsize != pcount) { ffmkyj(fptr, "PCOUNT", (fptr->Fptr)->heapsize, comm, status); } } } if (ffwend(fptr, status) <= 0) /* rewrite END keyword and fill */ { ffrhdu(fptr, &dummy, status); /* re-scan the header keywords */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffhdef(fitsfile *fptr, /* I - FITS file pointer */ int morekeys, /* I - reserve space for this many keywords */ int *status) /* IO - error status */ /* based on the number of keywords which have already been written, plus the number of keywords to reserve space for, we then can define where the data unit should start (it must start at the beginning of a 2880-byte logical block). This routine will only have any effect if the starting location of the data unit following the header is not already defined. In any case, it is always possible to add more keywords to the header even if the data has already been written. It is just more efficient to reserve the space in advance. */ { LONGLONG delta; if (*status > 0 || morekeys < 1) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { ffrdef(fptr, status); /* ffrdef defines the offset to datastart and the start of */ /* the next HDU based on the number of existing keywords. */ /* We need to increment both of these values based on */ /* the number of new keywords to be added. */ delta = (((fptr->Fptr)->headend + (morekeys * 80)) / 2880 + 1) * 2880 - (fptr->Fptr)->datastart; (fptr->Fptr)->datastart += delta; (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] += delta; } return(*status); } /*--------------------------------------------------------------------------*/ int ffwend(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* write the END card and following fill (space chars) in the current header */ { int ii, tstatus; LONGLONG endpos; long nspace; char blankkey[FLEN_CARD], endkey[FLEN_CARD], keyrec[FLEN_CARD] = ""; if (*status > 0) return(*status); endpos = (fptr->Fptr)->headend; /* we assume that the HDUposition == curhdu in all cases */ /* calc the data starting position if not currently defined */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) (fptr->Fptr)->datastart = ( endpos / 2880 + 1 ) * 2880; /* calculate the number of blank keyword slots in the header */ nspace = (long) (( (fptr->Fptr)->datastart - endpos ) / 80); /* construct a blank and END keyword (80 spaces ) */ strcpy(blankkey, " "); strcat(blankkey, " "); strcpy(endkey, "END "); strcat(endkey, " "); /* check if header is already correctly terminated with END and fill */ tstatus=0; ffmbyt(fptr, endpos, REPORT_EOF, &tstatus); /* move to header end */ for (ii=0; ii < nspace; ii++) { ffgbyt(fptr, 80, keyrec, &tstatus); /* get next keyword */ if (tstatus) break; if (strncmp(keyrec, blankkey, 80) && strncmp(keyrec, endkey, 80)) break; } if (ii == nspace && !tstatus) { /* check if the END keyword exists at the correct position */ endpos=maxvalue( endpos, ( (fptr->Fptr)->datastart - 2880 ) ); ffmbyt(fptr, endpos, REPORT_EOF, &tstatus); /* move to END position */ ffgbyt(fptr, 80, keyrec, &tstatus); /* read the END keyword */ if ( !strncmp(keyrec, endkey, 80) && !tstatus) { /* store this position, for later reference */ (fptr->Fptr)->ENDpos = endpos; return(*status); /* END card was already correct */ } } /* header was not correctly terminated, so write the END and blank fill */ endpos = (fptr->Fptr)->headend; ffmbyt(fptr, endpos, IGNORE_EOF, status); /* move to header end */ for (ii=0; ii < nspace; ii++) ffpbyt(fptr, 80, blankkey, status); /* write the blank keywords */ /* The END keyword must either be placed immediately after the last keyword that was written (as indicated by the headend value), or must be in the first 80 bytes of the 2880-byte FITS record immediately preceeding the data unit, whichever is further in the file. The latter will occur if space has been reserved for more header keywords which have not yet been written. */ endpos=maxvalue( endpos, ( (fptr->Fptr)->datastart - 2880 ) ); ffmbyt(fptr, endpos, REPORT_EOF, status); /* move to END position */ ffpbyt(fptr, 80, endkey, status); /* write the END keyword to header */ /* store this position, for later reference */ (fptr->Fptr)->ENDpos = endpos; if (*status > 0) ffpmsg("Error while writing END card (ffwend)."); return(*status); } /*--------------------------------------------------------------------------*/ int ffpdfl(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Write the Data Unit Fill values if they are not already correct. The fill values are used to fill out the last 2880 byte block of the HDU. Fill the data unit with zeros or blanks depending on the type of HDU from the end of the data to the end of the current FITS 2880 byte block */ { char chfill, fill[2880]; LONGLONG fillstart; int nfill, tstatus, ii; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) return(*status); /* fill has already been correctly written */ if ((fptr->Fptr)->heapstart == 0) return(*status); /* null data unit, so there is no fill */ fillstart = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; nfill = (long) ((fillstart + 2879) / 2880 * 2880 - fillstart); if ((fptr->Fptr)->hdutype == ASCII_TBL) chfill = 32; /* ASCII tables are filled with spaces */ else chfill = 0; /* all other extensions are filled with zeros */ tstatus = 0; if (!nfill) /* no fill bytes; just check that entire table exists */ { fillstart--; nfill = 1; ffmbyt(fptr, fillstart, REPORT_EOF, &tstatus); /* move to last byte */ ffgbyt(fptr, nfill, fill, &tstatus); /* get the last byte */ if (tstatus == 0) return(*status); /* no EOF error, so everything is OK */ } else { ffmbyt(fptr, fillstart, REPORT_EOF, &tstatus); /* move to fill area */ ffgbyt(fptr, nfill, fill, &tstatus); /* get the fill bytes */ if (tstatus == 0) { for (ii = 0; ii < nfill; ii++) { if (fill[ii] != chfill) break; } if (ii == nfill) return(*status); /* all the fill values were correct */ } } /* fill values are incorrect or have not been written, so write them */ memset(fill, chfill, nfill); /* fill the buffer with the fill value */ ffmbyt(fptr, fillstart, IGNORE_EOF, status); /* move to fill area */ ffpbyt(fptr, nfill, fill, status); /* write the fill bytes */ if (*status > 0) ffpmsg("Error writing Data Unit fill bytes (ffpdfl)."); return(*status); } /********************************************************************** ffchfl : Check Header Fill values Check that the header unit is correctly filled with blanks from the END card to the end of the current FITS 2880-byte block Function parameters: fptr Fits file pointer status output error status Translated ftchfl into C by Peter Wilson, Oct. 1997 **********************************************************************/ int ffchfl( fitsfile *fptr, int *status) { int nblank,i,gotend; LONGLONG endpos; char rec[FLEN_CARD]; char *blanks=" "; /* 80 spaces */ if( *status > 0 ) return (*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* calculate the number of blank keyword slots in the header */ endpos=(fptr->Fptr)->headend; nblank=(long) (((fptr->Fptr)->datastart-endpos)/80); /* move the i/o pointer to the end of the header keywords */ ffmbyt(fptr,endpos,TRUE,status); /* find the END card (there may be blank keywords perceeding it) */ gotend=FALSE; for(i=0;i 0 ) { rec[FLEN_CARD - 1] = '\0'; /* make sure string is null terminated */ ffpmsg(rec); return( *status ); } } return( *status ); } /********************************************************************** ffcdfl : Check Data Unit Fill values Check that the data unit is correctly filled with zeros or blanks from the end of the data to the end of the current FITS 2880 byte block Function parameters: fptr Fits file pointer status output error status Translated ftcdfl into C by Peter Wilson, Oct. 1997 **********************************************************************/ int ffcdfl( fitsfile *fptr, int *status) { int nfill,i; LONGLONG filpos; char chfill,chbuff[2880]; if( *status > 0 ) return( *status ); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* check if the data unit is null */ if( (fptr->Fptr)->heapstart==0 ) return( *status ); /* calculate starting position of the fill bytes, if any */ filpos = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; /* calculate the number of fill bytes */ nfill = (long) ((filpos + 2879) / 2880 * 2880 - filpos); if( nfill == 0 ) return( *status ); /* move to the beginning of the fill bytes */ ffmbyt(fptr, filpos, FALSE, status); if( ffgbyt(fptr, nfill, chbuff, status) > 0) { ffpmsg("Error reading data unit fill bytes (ffcdfl)."); return( *status ); } if( (fptr->Fptr)->hdutype==ASCII_TBL ) chfill = 32; /* ASCII tables are filled with spaces */ else chfill = 0; /* all other extensions are filled with zeros */ /* check for all zeros or blanks */ for(i=0;iFptr)->hdutype==ASCII_TBL ) ffpmsg("Warning: remaining bytes following ASCII table data are not filled with blanks."); else ffpmsg("Warning: remaining bytes following data are not filled with zeros."); return( *status ); } } return( *status ); } /*--------------------------------------------------------------------------*/ int ffcrhd(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* CReate Header Data unit: Create, initialize, and move the i/o pointer to a new extension appended to the end of the FITS file. */ { int tstatus = 0; LONGLONG bytepos, *ptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* If the current header is empty, we don't have to do anything */ if ((fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) return(*status); while (ffmrhd(fptr, 1, 0, &tstatus) == 0); /* move to end of file */ if ((fptr->Fptr)->maxhdu == (fptr->Fptr)->MAXHDU) { /* allocate more space for the headstart array */ ptr = (LONGLONG*) realloc( (fptr->Fptr)->headstart, ((fptr->Fptr)->MAXHDU + 1001) * sizeof(LONGLONG) ); if (ptr == NULL) return (*status = MEMORY_ALLOCATION); else { (fptr->Fptr)->MAXHDU = (fptr->Fptr)->MAXHDU + 1000; (fptr->Fptr)->headstart = ptr; } } if (ffchdu(fptr, status) <= 0) /* close the current HDU */ { bytepos = (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1]; /* last */ ffmbyt(fptr, bytepos, IGNORE_EOF, status); /* move file ptr to it */ (fptr->Fptr)->maxhdu++; /* increment the known number of HDUs */ (fptr->Fptr)->curhdu = (fptr->Fptr)->maxhdu; /* set current HDU loc */ fptr->HDUposition = (fptr->Fptr)->maxhdu; /* set current HDU loc */ (fptr->Fptr)->nextkey = bytepos; /* next keyword = start of header */ (fptr->Fptr)->headend = bytepos; /* end of header */ (fptr->Fptr)->datastart = DATA_UNDEFINED; /* start data unit undefined */ /* any other needed resets */ /* reset the dithering offset that may have been calculated for the */ /* previous HDU back to the requested default value */ (fptr->Fptr)->dither_seed = (fptr->Fptr)->request_dither_seed; } return(*status); } /*--------------------------------------------------------------------------*/ int ffdblk(fitsfile *fptr, /* I - FITS file pointer */ long nblocks, /* I - number of 2880-byte blocks to delete */ int *status) /* IO - error status */ /* Delete the specified number of 2880-byte blocks from the end of the CHDU by shifting all following extensions up this number of blocks. */ { char buffer[2880]; int tstatus, ii; LONGLONG readpos, writepos; if (*status > 0 || nblocks <= 0) return(*status); tstatus = 0; /* pointers to the read and write positions */ readpos = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; readpos = ((readpos + 2879) / 2880) * 2880; /* start of block */ /* the following formula is wrong because the current data unit may have been extended without updating the headstart value of the following HDU. readpos = (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; */ writepos = readpos - ((LONGLONG)nblocks * 2880); while ( !ffmbyt(fptr, readpos, REPORT_EOF, &tstatus) && !ffgbyt(fptr, 2880L, buffer, &tstatus) ) { ffmbyt(fptr, writepos, REPORT_EOF, status); ffpbyt(fptr, 2880L, buffer, status); if (*status > 0) { ffpmsg("Error deleting FITS blocks (ffdblk)"); return(*status); } readpos += 2880; /* increment to next block to transfer */ writepos += 2880; } /* now fill the last nblock blocks with zeros */ memset(buffer, 0, 2880); ffmbyt(fptr, writepos, REPORT_EOF, status); for (ii = 0; ii < nblocks; ii++) ffpbyt(fptr, 2880L, buffer, status); /* move back before the deleted blocks, since they may be deleted */ /* and we do not want to delete the current active buffer */ ffmbyt(fptr, writepos - 1, REPORT_EOF, status); /* truncate the file to the new size, if supported on this device */ fftrun(fptr, writepos, status); /* recalculate the starting location of all subsequent HDUs */ for (ii = (fptr->Fptr)->curhdu; ii <= (fptr->Fptr)->maxhdu; ii++) (fptr->Fptr)->headstart[ii + 1] -= ((LONGLONG)nblocks * 2880); return(*status); } /*--------------------------------------------------------------------------*/ int ffghdt(fitsfile *fptr, /* I - FITS file pointer */ int *exttype, /* O - type of extension, 0, 1, or 2 */ /* for IMAGE_HDU, ASCII_TBL, or BINARY_TBL */ int *status) /* IO - error status */ /* Return the type of the CHDU. This returns the 'logical' type of the HDU, not necessarily the physical type, so in the case of a compressed image stored in a binary table, this will return the type as an Image, not a binary table. */ { if (*status > 0) return(*status); if (fptr->HDUposition == 0 && (fptr->Fptr)->headend == 0) { /* empty primary array is alway an IMAGE_HDU */ *exttype = IMAGE_HDU; } else { /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { /* rescan header if data structure is undefined */ if ( ffrdef(fptr, status) > 0) return(*status); } *exttype = (fptr->Fptr)->hdutype; /* return the type of HDU */ /* check if this is a compressed image */ if ((fptr->Fptr)->compressimg) *exttype = IMAGE_HDU; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_is_reentrant(void) /* Was CFITSIO compiled with the -D_REENTRANT flag? 1 = yes, 0 = no. Note that specifying the -D_REENTRANT flag is required, but may not be sufficient, to ensure that CFITSIO can be safely used in a multi-threaded environoment. */ { #ifdef _REENTRANT return(1); #else return(0); #endif } /*--------------------------------------------------------------------------*/ int fits_is_compressed_image(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Returns TRUE if the CHDU is a compressed image, else returns zero. */ { if (*status > 0) return(0); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { /* rescan header if data structure is undefined */ if ( ffrdef(fptr, status) > 0) return(*status); } /* check if this is a compressed image */ if ((fptr->Fptr)->compressimg) return(1); return(0); } /*--------------------------------------------------------------------------*/ int ffgipr(fitsfile *infptr, /* I - FITS file pointer */ int maxaxis, /* I - max number of axes to return */ int *bitpix, /* O - image data type */ int *naxis, /* O - image dimension (NAXIS value) */ long *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* get the datatype and size of the input image */ { if (*status > 0) return(*status); /* don't return the parameter if a null pointer was given */ if (bitpix) fits_get_img_type(infptr, bitpix, status); /* get BITPIX value */ if (naxis) fits_get_img_dim(infptr, naxis, status); /* get NAXIS value */ if (naxes) fits_get_img_size(infptr, maxaxis, naxes, status); /* get NAXISn values */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgiprll(fitsfile *infptr, /* I - FITS file pointer */ int maxaxis, /* I - max number of axes to return */ int *bitpix, /* O - image data type */ int *naxis, /* O - image dimension (NAXIS value) */ LONGLONG *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* get the datatype and size of the input image */ { if (*status > 0) return(*status); /* don't return the parameter if a null pointer was given */ if (bitpix) fits_get_img_type(infptr, bitpix, status); /* get BITPIX value */ if (naxis) fits_get_img_dim(infptr, naxis, status); /* get NAXIS value */ if (naxes) fits_get_img_sizell(infptr, maxaxis, naxes, status); /* get NAXISn values */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgidt( fitsfile *fptr, /* I - FITS file pointer */ int *imgtype, /* O - image data type */ int *status) /* IO - error status */ /* Get the datatype of the image (= BITPIX keyword for normal image, or ZBITPIX for a compressed image) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); /* reset to beginning of header */ ffmaky(fptr, 1, status); /* simply move to beginning of header */ if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffgky(fptr, TINT, "BITPIX", imgtype, NULL, status); } else if ((fptr->Fptr)->compressimg) { /* this is a binary table containing a compressed image */ ffgky(fptr, TINT, "ZBITPIX", imgtype, NULL, status); } else { *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgiet( fitsfile *fptr, /* I - FITS file pointer */ int *imgtype, /* O - image data type */ int *status) /* IO - error status */ /* Get the effective datatype of the image (= BITPIX keyword for normal image, or ZBITPIX for a compressed image) */ { int tstatus; long lngscale, lngzero = 0; double bscale, bzero, min_val, max_val; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); /* reset to beginning of header */ ffmaky(fptr, 2, status); /* simply move to beginning of header */ if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffgky(fptr, TINT, "BITPIX", imgtype, NULL, status); } else if ((fptr->Fptr)->compressimg) { /* this is a binary table containing a compressed image */ ffgky(fptr, TINT, "ZBITPIX", imgtype, NULL, status); } else { *status = NOT_IMAGE; return(*status); } /* check if the BSCALE and BZERO keywords are defined, which might change the effective datatype of the image */ tstatus = 0; ffgky(fptr, TDOUBLE, "BSCALE", &bscale, NULL, &tstatus); if (tstatus) bscale = 1.0; tstatus = 0; ffgky(fptr, TDOUBLE, "BZERO", &bzero, NULL, &tstatus); if (tstatus) bzero = 0.0; if (bscale == 1.0 && bzero == 0.0) /* no scaling */ return(*status); switch (*imgtype) { case BYTE_IMG: /* 8-bit image */ min_val = 0.; max_val = 255.0; break; case SHORT_IMG: min_val = -32768.0; max_val = 32767.0; break; case LONG_IMG: min_val = -2147483648.0; max_val = 2147483647.0; break; default: /* don't have to deal with other data types */ return(*status); } if (bscale >= 0.) { min_val = bzero + bscale * min_val; max_val = bzero + bscale * max_val; } else { max_val = bzero + bscale * min_val; min_val = bzero + bscale * max_val; } if (bzero < 2147483648.) /* don't exceed range of 32-bit integer */ lngzero = (long) bzero; lngscale = (long) bscale; if ((bzero != 2147483648.) && /* special value that exceeds integer range */ (lngzero != bzero || lngscale != bscale)) { /* not integers? */ /* floating point scaled values; just decide on required precision */ if (*imgtype == BYTE_IMG || *imgtype == SHORT_IMG) *imgtype = FLOAT_IMG; else *imgtype = DOUBLE_IMG; /* In all the remaining cases, BSCALE and BZERO are integers, and not equal to 1 and 0, respectively. */ } else if ((min_val == -128.) && (max_val == 127.)) { *imgtype = SBYTE_IMG; } else if ((min_val >= -32768.0) && (max_val <= 32767.0)) { *imgtype = SHORT_IMG; } else if ((min_val >= 0.0) && (max_val <= 65535.0)) { *imgtype = USHORT_IMG; } else if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) { *imgtype = LONG_IMG; } else if ((min_val >= 0.0) && (max_val < 4294967296.0)) { *imgtype = ULONG_IMG; } else { /* exceeds the range of a 32-bit integer */ *imgtype = DOUBLE_IMG; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgidm( fitsfile *fptr, /* I - FITS file pointer */ int *naxis , /* O - image dimension (NAXIS value) */ int *status) /* IO - error status */ /* Get the dimension of the image (= NAXIS keyword for normal image, or ZNAXIS for a compressed image) These values are cached for faster access. */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { *naxis = (fptr->Fptr)->imgdim; } else if ((fptr->Fptr)->compressimg) { *naxis = (fptr->Fptr)->zndim; } else { *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgisz( fitsfile *fptr, /* I - FITS file pointer */ int nlen, /* I - number of axes to return */ long *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* Get the size of the image dimensions (= NAXISn keywords for normal image, or ZNAXISn for a compressed image) These values are cached for faster access. */ { int ii, naxis; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { naxis = minvalue((fptr->Fptr)->imgdim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (long) (fptr->Fptr)->imgnaxis[ii]; } } else if ((fptr->Fptr)->compressimg) { naxis = minvalue( (fptr->Fptr)->zndim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (long) (fptr->Fptr)->znaxis[ii]; } } else { *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgiszll( fitsfile *fptr, /* I - FITS file pointer */ int nlen, /* I - number of axes to return */ LONGLONG *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* Get the size of the image dimensions (= NAXISn keywords for normal image, or ZNAXISn for a compressed image) */ { int ii, naxis; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { naxis = minvalue((fptr->Fptr)->imgdim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (fptr->Fptr)->imgnaxis[ii]; } } else if ((fptr->Fptr)->compressimg) { naxis = minvalue( (fptr->Fptr)->zndim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (fptr->Fptr)->znaxis[ii]; } } else { *status = NOT_IMAGE; } return(*status); }/*--------------------------------------------------------------------------*/ int ffmahd(fitsfile *fptr, /* I - FITS file pointer */ int hdunum, /* I - number of the HDU to move to */ int *exttype, /* O - type of extension, 0, 1, or 2 */ int *status) /* IO - error status */ /* Move to Absolute Header Data unit. Move to the specified HDU and read the header to initialize the table structure. Note that extnum is one based, so the primary array is extnum = 1. */ { int moveto, tstatus; char message[FLEN_ERRMSG]; LONGLONG *ptr; if (*status > 0) return(*status); else if (hdunum < 1 ) return(*status = BAD_HDU_NUM); else if (hdunum >= (fptr->Fptr)->MAXHDU ) { /* allocate more space for the headstart array */ ptr = (LONGLONG*) realloc( (fptr->Fptr)->headstart, (hdunum + 1001) * sizeof(LONGLONG) ); if (ptr == NULL) return (*status = MEMORY_ALLOCATION); else { (fptr->Fptr)->MAXHDU = hdunum + 1000; (fptr->Fptr)->headstart = ptr; } } /* set logical HDU position to the actual position, in case they differ */ fptr->HDUposition = (fptr->Fptr)->curhdu; while( ((fptr->Fptr)->curhdu) + 1 != hdunum) /* at the correct HDU? */ { /* move directly to the extension if we know that it exists, otherwise move to the highest known extension. */ moveto = minvalue(hdunum - 1, ((fptr->Fptr)->maxhdu) + 1); /* test if HDU exists */ if ((fptr->Fptr)->headstart[moveto] < (fptr->Fptr)->logfilesize ) { if (ffchdu(fptr, status) <= 0) /* close out the current HDU */ { if (ffgext(fptr, moveto, exttype, status) > 0) { /* failed to get the requested extension */ tstatus = 0; ffrhdu(fptr, exttype, &tstatus); /* restore the CHDU */ } } } else *status = END_OF_FILE; if (*status > 0) { if (*status != END_OF_FILE) { /* don't clutter up the message stack in the common case of */ /* simply hitting the end of file (often an expected error) */ snprintf(message,FLEN_ERRMSG, "Failed to move to HDU number %d (ffmahd).", hdunum); ffpmsg(message); } return(*status); } } /* return the type of HDU; tile compressed images which are stored */ /* in a binary table will return exttype = IMAGE_HDU, not BINARY_TBL */ if (exttype != NULL) ffghdt(fptr, exttype, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffmrhd(fitsfile *fptr, /* I - FITS file pointer */ int hdumov, /* I - rel. no. of HDUs to move by (+ or -) */ int *exttype, /* O - type of extension, 0, 1, or 2 */ int *status) /* IO - error status */ /* Move a Relative number of Header Data units. Offset to the specified extension and read the header to initialize the HDU structure. */ { int extnum; if (*status > 0) return(*status); extnum = fptr->HDUposition + 1 + hdumov; /* the absolute HDU number */ ffmahd(fptr, extnum, exttype, status); /* move to the HDU */ return(*status); } /*--------------------------------------------------------------------------*/ int ffmnhd(fitsfile *fptr, /* I - FITS file pointer */ int exttype, /* I - desired extension type */ char *hduname, /* I - desired EXTNAME value for the HDU */ int hduver, /* I - desired EXTVERS value for the HDU */ int *status) /* IO - error status */ /* Move to the next HDU with a given extension type (IMAGE_HDU, ASCII_TBL, BINARY_TBL, or ANY_HDU), extension name (EXTNAME or HDUNAME keyword), and EXTVERS keyword values. If hduvers = 0, then move to the first HDU with the given type and name regardless of EXTVERS value. If no matching HDU is found in the file, then the current open HDU will remain unchanged. */ { char extname[FLEN_VALUE]; int ii, hdutype, alttype, extnum, tstatus, match, exact; int slen, putback = 0, chopped = 0; long extver; if (*status > 0) return(*status); extnum = fptr->HDUposition + 1; /* save the current HDU number */ /* This is a kludge to deal with a special case where the user specified a hduname that ended with a # character, which CFITSIO previously interpreted as a flag to mean "don't copy any other HDUs in the file into the virtual file in memory. If the remaining hduname does not end with a # character (meaning that the user originally entered a hduname ending in 2 # characters) then there is the possibility that the # character should be treated literally, if the actual EXTNAME also ends with a #. Setting putback = 1 means that we need to test for this case later on. */ if ((fptr->Fptr)->only_one) { /* if true, name orignally ended with a # */ slen = strlen(hduname); if (hduname[slen - 1] != '#') /* This will fail if real EXTNAME value */ putback = 1; /* ends with 2 # characters. */ } for (ii=1; 1; ii++) /* loop over all HDUs until EOF */ { tstatus = 0; if (ffmahd(fptr, ii, &hdutype, &tstatus)) /* move to next HDU */ { ffmahd(fptr, extnum, 0, status); /* restore original file position */ return(*status = BAD_HDU_NUM); /* couldn't find desired HDU */ } alttype = -1; if (fits_is_compressed_image(fptr, status)) alttype = BINARY_TBL; /* Does this HDU have a matching type? */ if (exttype == ANY_HDU || hdutype == exttype || hdutype == alttype) { ffmaky(fptr, 2, status); /* reset to the 2nd keyword in the header */ if (ffgkys(fptr, "EXTNAME", extname, 0, &tstatus) <= 0) /* get keyword */ { if (putback) { /* more of the kludge */ /* test if the EXTNAME value ends with a #; if so, chop it */ /* off before comparing the strings */ chopped = 0; slen = strlen(extname); if (extname[slen - 1] == '#') { extname[slen - 1] = '\0'; chopped = 1; } } /* see if the strings are an exact match */ ffcmps(hduname, extname, CASEINSEN, &match, &exact); } /* if EXTNAME keyword doesn't exist, or it does not match, then try HDUNAME */ if (tstatus || !exact) { tstatus = 0; if (ffgkys(fptr, "HDUNAME", extname, 0, &tstatus) <= 0) { if (putback) { /* more of the kludge */ chopped = 0; slen = strlen(extname); if (extname[slen - 1] == '#') { extname[slen - 1] = '\0'; /* chop off the # */ chopped = 1; } } /* see if the strings are an exact match */ ffcmps(hduname, extname, CASEINSEN, &match, &exact); } } if (!tstatus && exact) /* found a matching name */ { if (hduver) /* need to check if version numbers match? */ { if (ffgkyj(fptr, "EXTVER", &extver, 0, &tstatus) > 0) extver = 1; /* assume default EXTVER value */ if ( (int) extver == hduver) { if (chopped) { /* The # was literally part of the name, not a flag */ (fptr->Fptr)->only_one = 0; } return(*status); /* found matching name and vers */ } } else { if (chopped) { /* The # was literally part of the name, not a flag */ (fptr->Fptr)->only_one = 0; } return(*status); /* found matching name */ } } /* end of !tstatus && exact */ } /* end of matching HDU type */ } /* end of loop over HDUs */ } /*--------------------------------------------------------------------------*/ int ffthdu(fitsfile *fptr, /* I - FITS file pointer */ int *nhdu, /* O - number of HDUs in the file */ int *status) /* IO - error status */ /* Return the number of HDUs that currently exist in the file. */ { int ii, extnum, tstatus; if (*status > 0) return(*status); extnum = fptr->HDUposition + 1; /* save the current HDU number */ *nhdu = extnum - 1; /* if the CHDU is empty or not completely defined, just return */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) return(*status); tstatus = 0; /* loop until EOF */ for (ii=extnum; ffmahd(fptr, ii, 0, &tstatus) <= 0; ii++) { *nhdu = ii; } ffmahd(fptr, extnum, 0, status); /* restore orig file position */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgext(fitsfile *fptr, /* I - FITS file pointer */ int hdunum, /* I - no. of HDU to move get (0 based) */ int *exttype, /* O - type of extension, 0, 1, or 2 */ int *status) /* IO - error status */ /* Get Extension. Move to the specified extension and initialize the HDU structure. */ { int xcurhdu, xmaxhdu; LONGLONG xheadend; if (*status > 0) return(*status); if (ffmbyt(fptr, (fptr->Fptr)->headstart[hdunum], REPORT_EOF, status) <= 0) { /* temporarily save current values, in case of error */ xcurhdu = (fptr->Fptr)->curhdu; xmaxhdu = (fptr->Fptr)->maxhdu; xheadend = (fptr->Fptr)->headend; /* set new parameter values */ (fptr->Fptr)->curhdu = hdunum; fptr->HDUposition = hdunum; (fptr->Fptr)->maxhdu = maxvalue((fptr->Fptr)->maxhdu, hdunum); (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ if (ffrhdu(fptr, exttype, status) > 0) { /* failed to get the new HDU, so restore previous values */ (fptr->Fptr)->curhdu = xcurhdu; fptr->HDUposition = xcurhdu; (fptr->Fptr)->maxhdu = xmaxhdu; (fptr->Fptr)->headend = xheadend; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffiblk(fitsfile *fptr, /* I - FITS file pointer */ long nblock, /* I - no. of blocks to insert */ int headdata, /* I - insert where? 0=header, 1=data */ /* -1=beginning of file */ int *status) /* IO - error status */ /* insert 2880-byte blocks at the end of the current header or data unit */ { int tstatus, savehdu, typhdu; LONGLONG insertpt, jpoint; long ii, nshift; char charfill; char buff1[2880], buff2[2880]; char *inbuff, *outbuff, *tmpbuff; char card[FLEN_CARD]; if (*status > 0 || nblock <= 0) return(*status); tstatus = *status; if (headdata == 0 || (fptr->Fptr)->hdutype == ASCII_TBL) charfill = 32; /* headers and ASCII tables have space (32) fill */ else charfill = 0; /* images and binary tables have zero fill */ if (headdata == 0) insertpt = (fptr->Fptr)->datastart; /* insert just before data, or */ else if (headdata == -1) { insertpt = 0; strcpy(card, "XTENSION= 'IMAGE ' / IMAGE extension"); } else /* at end of data, */ { insertpt = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; insertpt = ((insertpt + 2879) / 2880) * 2880; /* start of block */ /* the following formula is wrong because the current data unit may have been extended without updating the headstart value of the following HDU. */ /* insertpt = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1]; */ } inbuff = buff1; /* set pointers to input and output buffers */ outbuff = buff2; memset(outbuff, charfill, 2880); /* initialize buffer with fill */ if (nblock == 1) /* insert one block */ { if (headdata == -1) ffmrec(fptr, 1, card, status); /* change SIMPLE -> XTENSION */ ffmbyt(fptr, insertpt, REPORT_EOF, status); /* move to 1st point */ ffgbyt(fptr, 2880, inbuff, status); /* read first block of bytes */ while (*status <= 0) { ffmbyt(fptr, insertpt, REPORT_EOF, status); /* insert point */ ffpbyt(fptr, 2880, outbuff, status); /* write the output buffer */ if (*status > 0) return(*status); tmpbuff = inbuff; /* swap input and output pointers */ inbuff = outbuff; outbuff = tmpbuff; insertpt += 2880; /* increment insert point by 1 block */ ffmbyt(fptr, insertpt, REPORT_EOF, status); /* move to next block */ ffgbyt(fptr, 2880, inbuff, status); /* read block of bytes */ } *status = tstatus; /* reset status value */ ffmbyt(fptr, insertpt, IGNORE_EOF, status); /* move back to insert pt */ ffpbyt(fptr, 2880, outbuff, status); /* write the final block */ } else /* inserting more than 1 block */ { savehdu = (fptr->Fptr)->curhdu; /* save the current HDU number */ tstatus = *status; while(*status <= 0) /* find the last HDU in file */ ffmrhd(fptr, 1, &typhdu, status); if (*status == END_OF_FILE) { *status = tstatus; } ffmahd(fptr, savehdu + 1, &typhdu, status); /* move back to CHDU */ if (headdata == -1) ffmrec(fptr, 1, card, status); /* NOW change SIMPLE -> XTENSION */ /* number of 2880-byte blocks that have to be shifted down */ nshift = (long) (((fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] - insertpt) / 2880); /* position of last block in file to be shifted */ jpoint = (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] - 2880; /* move all the blocks starting at end of file working backwards */ for (ii = 0; ii < nshift; ii++) { /* move to the read start position */ if (ffmbyt(fptr, jpoint, REPORT_EOF, status) > 0) return(*status); ffgbyt(fptr, 2880, inbuff,status); /* read one record */ /* move forward to the write postion */ ffmbyt(fptr, jpoint + ((LONGLONG) nblock * 2880), IGNORE_EOF, status); ffpbyt(fptr, 2880, inbuff, status); /* write the record */ jpoint -= 2880; } /* move back to the write start postion (might be EOF) */ ffmbyt(fptr, insertpt, IGNORE_EOF, status); for (ii = 0; ii < nblock; ii++) /* insert correct fill value */ ffpbyt(fptr, 2880, outbuff, status); } if (headdata == 0) /* update data start address */ (fptr->Fptr)->datastart += ((LONGLONG) nblock * 2880); /* update following HDU addresses */ for (ii = (fptr->Fptr)->curhdu; ii <= (fptr->Fptr)->maxhdu; ii++) (fptr->Fptr)->headstart[ii + 1] += ((LONGLONG) nblock * 2880); return(*status); } /*--------------------------------------------------------------------------*/ int ffgkcl(char *tcard) /* Return the type classification of the input header record TYP_STRUC_KEY: SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY: The keywords used in the compressed image format ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK, EXTNAME = 'COMPRESSED_IMAGE' ZSIMPLE, ZTENSION, ZEXTEND, ZBLOCKED, ZPCOUNT, ZGCOUNT ZQUANTIZ, ZDITHER0 TYP_SCAL_KEY: BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY: BLANK, TNULLn TYP_DIM_KEY: TDIMn TYP_RANG_KEY: TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY: BUNIT, TUNITn TYP_DISP_KEY: TDISPn TYP_HDUID_KEY: EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY CHECKSUM, DATASUM TYP_WCS_KEY: Primary array: WCAXES, CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs Pixel list: TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn Bintable vector: jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn TYP_REFSYS_KEY: EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs TYP_COMM_KEY: COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY: CONTINUE TYP_USER_KEY: all other keywords */ { char card[20], *card1, *card5; card[0] = '\0'; strncat(card, tcard, 8); /* copy the keyword name */ strcat(card, " "); /* append blanks to make at least 8 chars long */ ffupch(card); /* make sure it is in upper case */ card1 = card + 1; /* pointer to 2nd character */ card5 = card + 5; /* pointer to 6th character */ /* the strncmp function is slow, so try to be more efficient */ if (*card == 'Z') { if (FSTRNCMP (card1, "IMAGE ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "CMPTYPE", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "NAME", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "VAL", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "TILE", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "BITPIX ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "NAXIS", 5) == 0) { if ( ( *(card + 6) >= '0' && *(card + 6) <= '9' ) || (*(card + 6) == ' ') ) return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "SCALE ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "ZERO ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "BLANK ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "SIMPLE ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "TENSION", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "EXTEND ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "BLOCKED", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "PCOUNT ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "GCOUNT ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "QUANTIZ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "DITHER0", 7) == 0) return (TYP_CMPRS_KEY); } else if (*card == ' ') { return (TYP_COMM_KEY); } else if (*card == 'B') { if (FSTRNCMP (card1, "ITPIX ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "LOCKED ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "LANK ", 7) == 0) return (TYP_NULL_KEY); if (FSTRNCMP (card1, "SCALE ", 7) == 0) return (TYP_SCAL_KEY); if (FSTRNCMP (card1, "ZERO ", 7) == 0) return (TYP_SCAL_KEY); if (FSTRNCMP (card1, "UNIT ", 7) == 0) return (TYP_UNIT_KEY); } else if (*card == 'C') { if (FSTRNCMP (card1, "OMMENT",6) == 0) { /* new comment string starting Oct 2001 */ if (FSTRNCMP (tcard, "COMMENT and Astrophysics', volume 376, page 3", 47) == 0) return (TYP_STRUC_KEY); /* original COMMENT strings from 1993 - 2001 */ if (FSTRNCMP (tcard, "COMMENT FITS (Flexible Image Transport System", 47) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (tcard, "COMMENT Astrophysics Supplement Series v44/p3", 47) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (tcard, "COMMENT Contact the NASA Science Office of St", 47) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (tcard, "COMMENT FITS Definition document #100 and oth", 47) == 0) return (TYP_STRUC_KEY); if (*(card + 7) == ' ') return (TYP_COMM_KEY); else return (TYP_USER_KEY); } if (FSTRNCMP (card1, "HECKSUM", 7) == 0) return (TYP_CKSUM_KEY); if (FSTRNCMP (card1, "ONTINUE", 7) == 0) return (TYP_CONT_KEY); if (FSTRNCMP (card1, "TYPE",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "UNIT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "RVAL",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "RPIX",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "ROTA",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "RDER",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "SYER",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "DELT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (*card1 == 'D') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'D') { if (FSTRNCMP (card1, "ATASUM ", 7) == 0) return (TYP_CKSUM_KEY); if (FSTRNCMP (card1, "ATAMIN ", 7) == 0) return (TYP_RANG_KEY); if (FSTRNCMP (card1, "ATAMAX ", 7) == 0) return (TYP_RANG_KEY); if (FSTRNCMP (card1, "ATE-OBS", 7) == 0) return (TYP_REFSYS_KEY); } else if (*card == 'E') { if (FSTRNCMP (card1, "XTEND ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "ND ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "XTNAME ", 7) == 0) { /* check for special compressed image value */ if (FSTRNCMP(tcard, "EXTNAME = 'COMPRESSED_IMAGE'", 28) == 0) return (TYP_CMPRS_KEY); else return (TYP_HDUID_KEY); } if (FSTRNCMP (card1, "XTVER ", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "XTLEVEL", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "QUINOX", 6) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "QUI",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_REFSYS_KEY); } if (FSTRNCMP (card1, "POCH ", 7) == 0) return (TYP_REFSYS_KEY); } else if (*card == 'G') { if (FSTRNCMP (card1, "COUNT ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "ROUPS ", 7) == 0) return (TYP_STRUC_KEY); } else if (*card == 'H') { if (FSTRNCMP (card1, "DUNAME ", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "DUVER ", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "DULEVEL", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "ISTORY",6) == 0) { if (*(card + 7) == ' ') return (TYP_COMM_KEY); else return (TYP_USER_KEY); } } else if (*card == 'L') { if (FSTRNCMP (card1, "ONPOLE",6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "ATPOLE",6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "ONP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "ATP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'M') { if (FSTRNCMP (card1, "JD-OBS ", 7) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "JDOB",4) == 0) { if (*(card+5) >= '0' && *(card+5) <= '9') return (TYP_REFSYS_KEY); } } else if (*card == 'N') { if (FSTRNCMP (card1, "AXIS", 4) == 0) { if ((*card5 >= '0' && *card5 <= '9') || (*card5 == ' ')) return (TYP_STRUC_KEY); } } else if (*card == 'P') { if (FSTRNCMP (card1, "COUNT ", 7) == 0) return (TYP_STRUC_KEY); if (*card1 == 'C') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (*card1 == 'V') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (*card1 == 'S') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'R') { if (FSTRNCMP (card1, "ADECSYS", 7) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "ADESYS", 6) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "ADE",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_REFSYS_KEY); } } else if (*card == 'S') { if (FSTRNCMP (card1, "IMPLE ", 7) == 0) return (TYP_STRUC_KEY); } else if (*card == 'T') { if (FSTRNCMP (card1, "TYPE", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_STRUC_KEY); } else if (FSTRNCMP (card1, "FORM", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_STRUC_KEY); } else if (FSTRNCMP (card1, "BCOL", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_STRUC_KEY); } else if (FSTRNCMP (card1, "FIELDS ", 7) == 0) return (TYP_STRUC_KEY); else if (FSTRNCMP (card1, "HEAP ", 7) == 0) return (TYP_STRUC_KEY); else if (FSTRNCMP (card1, "NULL", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_NULL_KEY); } else if (FSTRNCMP (card1, "DIM", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_DIM_KEY); } else if (FSTRNCMP (card1, "UNIT", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_UNIT_KEY); } else if (FSTRNCMP (card1, "DISP", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_DISP_KEY); } else if (FSTRNCMP (card1, "SCAL", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_SCAL_KEY); } else if (FSTRNCMP (card1, "ZERO", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_SCAL_KEY); } else if (FSTRNCMP (card1, "LMIN", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "LMAX", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "DMIN", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "DMAX", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "CTYP",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CTY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUNI",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUN",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRVL",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRV",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRPX",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CROT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDLT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDE",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRD",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CSY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "WCS",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "C",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "P",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "V",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "S",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'X') { if (FSTRNCMP (card1, "TENSION", 7) == 0) return (TYP_STRUC_KEY); } else if (*card == 'W') { if (FSTRNCMP (card1, "CSAXES", 6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "CSNAME", 6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "CAX", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CSN", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); } } else if (*card >= '0' && *card <= '9') { if (*card1 == 'C') { if (FSTRNCMP (card1, "CTYP",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CTY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUNI",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUN",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRVL",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRV",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRPX",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CROT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDLT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDE",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRD",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CSY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } } else if (FSTRNCMP (card1, "V",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "S",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (*card1 >= '0' && *card1 <= '9') { /* 2 digits at beginning of keyword */ if ( (*(card + 2) == 'P') && (*(card + 3) == 'C') ) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); /* ijPCn keyword */ } else if ( (*(card + 2) == 'C') && (*(card + 3) == 'D') ) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); /* ijCDn keyword */ } } } return (TYP_USER_KEY); /* by default all others are user keywords */ } /*--------------------------------------------------------------------------*/ int ffdtyp(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I, or X */ int *status) /* IO - error status */ /* determine implicit datatype of input string. This assumes that the string conforms to the FITS standard for keyword values, so may not detect all invalid formats. */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); else if (cval[0] == '\'') *dtype = 'C'; /* character string starts with a quote */ else if (cval[0] == 'T' || cval[0] == 'F') *dtype = 'L'; /* logical = T or F character */ else if (cval[0] == '(') *dtype = 'X'; /* complex datatype "(1.2, -3.4)" */ else if (strchr(cval,'.')) *dtype = 'F'; /* float usualy contains a decimal point */ else if (strchr(cval,'E') || strchr(cval,'D') ) *dtype = 'F'; /* exponential contains a E or D */ else *dtype = 'I'; /* if none of the above assume it is integer */ return(*status); } /*--------------------------------------------------------------------------*/ int ffinttyp(char *cval, /* I - formatted string representation of the integer */ int *dtype, /* O - datatype code: TBYTE, TSHORT, TUSHORT, etc */ int *negative, /* O - is cval negative? */ int *status) /* IO - error status */ /* determine implicit datatype of input integer string. This assumes that the string conforms to the FITS standard for integer keyword value, so may not detect all invalid formats. */ { int ii, len; char *p; if (*status > 0) /* inherit input status value if > 0 */ return(*status); *dtype = 0; /* initialize to NULL */ *negative = 0; p = cval; if (*p == '+') { p++; /* ignore leading + sign */ } else if (*p == '-') { p++; *negative = 1; /* this is a negative number */ } if (*p == '0') { while (*p == '0') p++; /* skip leading zeros */ if (*p == 0) { /* the value is a string of 1 or more zeros */ *dtype = TSBYTE; return(*status); } } len = strlen(p); for (ii = 0; ii < len; ii++) { if (!isdigit(*(p+ii))) { *status = BAD_INTKEY; return(*status); } } /* check for unambiguous cases, based on length of the string */ if (len == 0) { *status = VALUE_UNDEFINED; } else if (len < 3) { *dtype = TSBYTE; } else if (len == 4) { *dtype = TSHORT; } else if (len > 5 && len < 10) { *dtype = TINT; } else if (len > 10 && len < 19) { *dtype = TLONGLONG; } else if (len > 20) { *status = BAD_INTKEY; } else { if (!(*negative)) { /* positive integers */ if (len == 3) { if (strcmp(p,"127") <= 0 ) { *dtype = TSBYTE; } else if (strcmp(p,"255") <= 0 ) { *dtype = TBYTE; } else { *dtype = TSHORT; } } else if (len == 5) { if (strcmp(p,"32767") <= 0 ) { *dtype = TSHORT; } else if (strcmp(p,"65535") <= 0 ) { *dtype = TUSHORT; } else { *dtype = TINT; } } else if (len == 10) { if (strcmp(p,"2147483647") <= 0 ) { *dtype = TINT; } else if (strcmp(p,"4294967295") <= 0 ) { *dtype = TUINT; } else { *dtype = TLONGLONG; } } else if (len == 19) { if (strcmp(p,"9223372036854775807") <= 0 ) { *dtype = TLONGLONG; } else { *dtype = TULONGLONG; } } else if (len == 20) { if (strcmp(p,"18446744073709551615") <= 0 ) { *dtype = TULONGLONG; } else { *status = BAD_INTKEY; } } } else { /* negative integers */ if (len == 3) { if (strcmp(p,"128") <= 0 ) { *dtype = TSBYTE; } else { *dtype = TSHORT; } } else if (len == 5) { if (strcmp(p,"32768") <= 0 ) { *dtype = TSHORT; } else { *dtype = TINT; } } else if (len == 10) { if (strcmp(p,"2147483648") <= 0 ) { *dtype = TINT; } else { *dtype = TLONGLONG; } } else if (len == 19) { if (strcmp(p,"9223372036854775808") <= 0 ) { *dtype = TLONGLONG; } else { *status = BAD_INTKEY; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2x(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I or X */ /* Only one of the following will be defined, depending on datatype */ long *ival, /* O - integer value */ int *lval, /* O - logical value */ char *sval, /* O - string value */ double *dval, /* O - double value */ int *status) /* IO - error status */ /* high level routine to convert formatted character string to its intrinsic data type */ { ffdtyp(cval, dtype, status); /* determine the datatype */ if (*dtype == 'I') ffc2ii(cval, ival, status); else if (*dtype == 'F') ffc2dd(cval, dval, status); else if (*dtype == 'L') ffc2ll(cval, lval, status); else ffc2s(cval, sval, status); /* C and X formats */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2xx(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I or X */ /* Only one of the following will be defined, depending on datatype */ LONGLONG *ival, /* O - integer value */ int *lval, /* O - logical value */ char *sval, /* O - string value */ double *dval, /* O - double value */ int *status) /* IO - error status */ /* high level routine to convert formatted character string to its intrinsic data type */ { ffdtyp(cval, dtype, status); /* determine the datatype */ if (*dtype == 'I') ffc2jj(cval, ival, status); else if (*dtype == 'F') ffc2dd(cval, dval, status); else if (*dtype == 'L') ffc2ll(cval, lval, status); else ffc2s(cval, sval, status); /* C and X formats */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2uxx(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I or X */ /* Only one of the following will be defined, depending on datatype */ ULONGLONG *ival, /* O - integer value */ int *lval, /* O - logical value */ char *sval, /* O - string value */ double *dval, /* O - double value */ int *status) /* IO - error status */ /* high level routine to convert formatted character string to its intrinsic data type */ { ffdtyp(cval, dtype, status); /* determine the datatype */ if (*dtype == 'I') ffc2ujj(cval, ival, status); else if (*dtype == 'F') ffc2dd(cval, dval, status); else if (*dtype == 'L') ffc2ll(cval, lval, status); else ffc2s(cval, sval, status); /* C and X formats */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2i(const char *cval, /* I - string representation of the value */ long *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to an integer value, doing implicit datatype conversion if necessary. */ { char dtype, sval[81], msg[81]; int lval; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2x(cval, &dtype, ival, &lval, sval, &dval, status); if (dtype == 'X' ) { *status = BAD_INTKEY; } else if (dtype == 'C') { /* try reading the string as a number */ if (ffc2dd(sval, &dval, status) <= 0) { if (dval > (double) LONG_MAX || dval < (double) LONG_MIN) *status = NUM_OVERFLOW; else *ival = (long) dval; } } else if (dtype == 'F') { if (dval > (double) LONG_MAX || dval < (double) LONG_MIN) *status = NUM_OVERFLOW; else *ival = (long) dval; } else if (dtype == 'L') { *ival = (long) lval; } if (*status > 0) { *ival = 0; strcpy(msg,"Error in ffc2i evaluating string as an integer: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2j(const char *cval, /* I - string representation of the value */ LONGLONG *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a LONGLONG integer value, doing implicit datatype conversion if necessary. */ { char dtype, sval[81], msg[81]; int lval; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2xx(cval, &dtype, ival, &lval, sval, &dval, status); if (dtype == 'X' ) { *status = BAD_INTKEY; } else if (dtype == 'C') { /* try reading the string as a number */ if (ffc2dd(sval, &dval, status) <= 0) { if (dval > (double) LONGLONG_MAX || dval < (double) LONGLONG_MIN) *status = NUM_OVERFLOW; else *ival = (LONGLONG) dval; } } else if (dtype == 'F') { if (dval > (double) LONGLONG_MAX || dval < (double) LONGLONG_MIN) *status = NUM_OVERFLOW; else *ival = (LONGLONG) dval; } else if (dtype == 'L') { *ival = (LONGLONG) lval; } if (*status > 0) { *ival = 0; strcpy(msg,"Error in ffc2j evaluating string as a long integer: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2uj(const char *cval, /* I - string representation of the value */ ULONGLONG *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a ULONGLONG integer value, doing implicit datatype conversion if necessary. */ { char dtype, sval[81], msg[81]; int lval; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2uxx(cval, &dtype, ival, &lval, sval, &dval, status); if (dtype == 'X' ) { *status = BAD_INTKEY; } else if (dtype == 'C') { /* try reading the string as a number */ if (ffc2dd(sval, &dval, status) <= 0) { if (dval > (double) DULONGLONG_MAX || dval < -0.49) *status = NUM_OVERFLOW; else *ival = (ULONGLONG) dval; } } else if (dtype == 'F') { if (dval > (double) DULONGLONG_MAX || dval < -0.49) *status = NUM_OVERFLOW; else *ival = (ULONGLONG) dval; } else if (dtype == 'L') { *ival = (ULONGLONG) lval; } if (*status > 0) { *ival = 0; strcpy(msg,"Error in ffc2j evaluating string as a long integer: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2l(const char *cval, /* I - string representation of the value */ int *lval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a logical value, doing implicit datatype conversion if necessary */ { char dtype, sval[81], msg[81]; long ival; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2x(cval, &dtype, &ival, lval, sval, &dval, status); if (dtype == 'C' || dtype == 'X' ) *status = BAD_LOGICALKEY; if (*status > 0) { *lval = 0; strcpy(msg,"Error in ffc2l evaluating string as a logical: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } if (dtype == 'I') { if (ival) *lval = 1; else *lval = 0; } else if (dtype == 'F') { if (dval) *lval = 1; else *lval = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2r(const char *cval, /* I - string representation of the value */ float *fval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a real float value, doing implicit datatype conversion if necessary */ { char dtype, sval[81], msg[81]; int lval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ ffdtyp(cval, &dtype, status); /* determine the datatype */ if (dtype == 'I' || dtype == 'F') ffc2rr(cval, fval, status); else if (dtype == 'L') { ffc2ll(cval, &lval, status); *fval = (float) lval; } else if (dtype == 'C') { /* try reading the string as a number */ ffc2s(cval, sval, status); ffc2rr(sval, fval, status); } else *status = BAD_FLOATKEY; if (*status > 0) { *fval = 0.; strcpy(msg,"Error in ffc2r evaluating string as a float: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2d(const char *cval, /* I - string representation of the value */ double *dval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a double value, doing implicit datatype conversion if necessary */ { char dtype, sval[81], msg[81]; int lval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ ffdtyp(cval, &dtype, status); /* determine the datatype */ if (dtype == 'I' || dtype == 'F') ffc2dd(cval, dval, status); else if (dtype == 'L') { ffc2ll(cval, &lval, status); *dval = (double) lval; } else if (dtype == 'C') { /* try reading the string as a number */ ffc2s(cval, sval, status); ffc2dd(sval, dval, status); } else *status = BAD_DOUBLEKEY; if (*status > 0) { *dval = 0.; strcpy(msg,"Error in ffc2d evaluating string as a double: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2ii(const char *cval, /* I - string representation of the value */ long *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to an integer value */ { char *loc, msg[81]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); errno = 0; *ival = 0; *ival = strtol(cval, &loc, 10); /* read the string as an integer */ /* check for read error, or junk following the integer */ if (*loc != '\0' && *loc != ' ' ) *status = BAD_C2I; if (errno == ERANGE) { strcpy(msg,"Range Error in ffc2ii converting string to long int: "); strncat(msg,cval,25); ffpmsg(msg); *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2jj(const char *cval, /* I - string representation of the value */ LONGLONG *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to an long long integer value */ { char *loc, msg[81]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); errno = 0; *ival = 0; #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 does not have the strtoll function */ *ival = _atoi64(cval); loc = (char *) cval; while (*loc == ' ') loc++; /* skip spaces */ if (*loc == '-') loc++; /* skip minus sign */ if (*loc == '+') loc++; /* skip plus sign */ while (isdigit(*loc)) loc++; /* skip digits */ #elif (USE_LL_SUFFIX == 1) *ival = strtoll(cval, &loc, 10); /* read the string as an integer */ #else *ival = strtol(cval, &loc, 10); /* read the string as an integer */ #endif /* check for read error, or junk following the integer */ if (*loc != '\0' && *loc != ' ' ) *status = BAD_C2I; if (errno == ERANGE) { strcpy(msg,"Range Error in ffc2jj converting string to longlong int: "); strncat(msg,cval,23); ffpmsg(msg); *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2ujj(const char *cval, /* I - string representation of the value */ ULONGLONG *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to an unsigned long long integer value */ { char *loc, msg[81]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); errno = 0; *ival = 0; #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 does not have the strtoll function */ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* !!!!! This needs to be modified to use the unsigned long long version of _atoi64 */ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ *ival = _atoi64(cval); loc = (char *) cval; while (*loc == ' ') loc++; /* skip spaces */ if (*loc == '-') loc++; /* skip minus sign */ if (*loc == '+') loc++; /* skip plus sign */ while (isdigit(*loc)) loc++; /* skip digits */ #elif (USE_LL_SUFFIX == 1) *ival = strtoull(cval, &loc, 10); /* read the string as an integer */ #else *ival = strtoul(cval, &loc, 10); /* read the string as an integer */ #endif /* check for read error, or junk following the integer */ if (*loc != '\0' && *loc != ' ' ) *status = BAD_C2I; if (errno == ERANGE) { strcpy(msg,"Range Error in ffc2ujj converting string to unsigned longlong int: "); strncat(msg,cval,25); ffpmsg(msg); *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2ll(const char *cval, /* I - string representation of the value: T or F */ int *lval, /* O - numerical value of the input string: 1 or 0 */ int *status) /* IO - error status */ /* convert null-terminated formatted string to a logical value */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == 'T') *lval = 1; else *lval = 0; /* any character besides T is considered false */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2s(const char *instr, /* I - null terminated quoted input string */ char *outstr, /* O - null terminated output string without quotes */ int *status) /* IO - error status */ /* convert an input quoted string to an unquoted string by removing the leading and trailing quote character. Also, replace any pairs of single quote characters with just a single quote character (FITS used a pair of single quotes to represent a literal quote character within the string). */ { int jj; size_t len, ii; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (instr[0] != '\'') { if (instr[0] == '\0') { outstr[0] = '\0'; return(*status = VALUE_UNDEFINED); /* null value string */ } else { strcpy(outstr, instr); /* no leading quote, so return input string */ return(*status); } } len = strlen(instr); for (ii=1, jj=0; ii < len; ii++, jj++) { if (instr[ii] == '\'') /* is this the closing quote? */ { if (instr[ii+1] == '\'') /* 2 successive quotes? */ ii++; /* copy only one of the quotes */ else break; /* found the closing quote, so exit this loop */ } outstr[jj] = instr[ii]; /* copy the next character to the output */ } outstr[jj] = '\0'; /* terminate the output string */ if (ii == len) { ffpmsg("This string value has no closing quote (ffc2s):"); ffpmsg(instr); return(*status = 205); } for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (outstr[jj] == ' ') outstr[jj] = 0; else break; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2rr(const char *cval, /* I - string representation of the value */ float *fval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to a float value */ { char *loc, msg[81], tval[73]; struct lconv *lcc = 0; static char decimalpt = 0; short *sptr, iret; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (!decimalpt) { /* only do this once for efficiency */ lcc = localeconv(); /* set structure containing local decimal point symbol */ decimalpt = *(lcc->decimal_point); } errno = 0; *fval = 0.; if (strchr(cval, 'D') || decimalpt == ',') { /* strtod expects a comma, not a period, as the decimal point */ if (strlen(cval) > 72) { strcpy(msg,"Error: Invalid string to float in ffc2rr"); ffpmsg(msg); return (*status=BAD_C2F); } strcpy(tval, cval); /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; if (decimalpt == ',') { /* strtod expects a comma, not a period, as the decimal point */ if ((loc = strchr(tval, '.'))) *loc = ','; } *fval = (float) strtod(tval, &loc); /* read the string as an float */ } else { *fval = (float) strtod(cval, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) { strcpy(msg,"Error in ffc2rr converting string to float: "); strncat(msg,cval,30); ffpmsg(msg); *status = BAD_C2F; } sptr = (short *) fval; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif iret = fnan(*sptr); /* if iret == 1, then the float value is a NaN */ if (errno == ERANGE || (iret == 1) ) { strcpy(msg,"Error in ffc2rr converting string to float: "); strncat(msg,cval,30); ffpmsg(msg); *fval = 0.; *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2dd(const char *cval, /* I - string representation of the value */ double *dval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to a double value */ { char *loc, msg[81], tval[73]; struct lconv *lcc = 0; static char decimalpt = 0; short *sptr, iret; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (!decimalpt) { /* only do this once for efficiency */ lcc = localeconv(); /* set structure containing local decimal point symbol */ decimalpt = *(lcc->decimal_point); } errno = 0; *dval = 0.; if (strchr(cval, 'D') || decimalpt == ',') { /* need to modify a temporary copy of the string before parsing it */ if (strlen(cval) > 72) { strcpy(msg,"Error: Invalid string to double in ffc2dd"); ffpmsg(msg); return (*status=BAD_C2D); } strcpy(tval, cval); /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; if (decimalpt == ',') { /* strtod expects a comma, not a period, as the decimal point */ if ((loc = strchr(tval, '.'))) *loc = ','; } *dval = strtod(tval, &loc); /* read the string as an double */ } else { *dval = strtod(cval, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) { strcpy(msg,"Error in ffc2dd converting string to double: "); strncat(msg,cval,30); ffpmsg(msg); *status = BAD_C2D; } sptr = (short *) dval; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif iret = dnan(*sptr); /* if iret == 1, then the double value is a NaN */ if (errno == ERANGE || (iret == 1) ) { strcpy(msg,"Error in ffc2dd converting string to double: "); strncat(msg,cval,30); ffpmsg(msg); *dval = 0.; *status = NUM_OVERFLOW; errno = 0; } return(*status); } /* ================================================================== */ /* A hack for nonunix machines, which lack strcasecmp and strncasecmp */ /* ================================================================== */ int fits_strcasecmp(const char *s1, const char *s2) { char c1, c2; for (;;) { c1 = toupper( *s1 ); c2 = toupper( *s2 ); if (c1 < c2) return(-1); if (c1 > c2) return(1); if (c1 == 0) return(0); s1++; s2++; } } int fits_strncasecmp(const char *s1, const char *s2, size_t n) { char c1, c2; for (; n-- ;) { c1 = toupper( *s1 ); c2 = toupper( *s2 ); if (c1 < c2) return(-1); if (c1 > c2) return(1); if (c1 == 0) return(0); s1++; s2++; } return(0); } /* * fits_recalloc - an allocator/reallocator in the style of calloc and realloc * * Allocates or reallocates storage upon request. Newly allocated * storage is zeroed in the style of calloc. * * Cases handled are: * ptr == 0 or old_num == 0 - use calloc to allocate new storage * new_num = 0 - frees any storage if ptr is non-NULL * new_num < old_num - uses realloc() to reduce storage allocated * new_num > old_num - uses realloc() and sets newly allocated * storage to zero (old portion left unchanged) * * void *ptr - "old" pointer, or NULL to allocate new storage * size_t old_num - old number of records allocated * size_t new_num - new number of records allocated * size_t size - size of record in bytes * * RETURNS: newly allocated storage * * */ void *fits_recalloc(void *ptr, size_t old_num, size_t new_num, size_t size) { void *newptr; if (ptr == 0 || old_num == 0) { /* Starting from nothing */ return calloc(new_num, size); } else if (new_num == old_num) { /* Same size, do nothing */ return ptr; } else if (new_num == 0) { /* Freeing */ if (ptr) free(ptr); return 0; } else if (new_num < old_num) { /* Shrinking */ newptr = realloc(ptr, new_num*size); if (!newptr) free(ptr); return (newptr); } /* Growing */ newptr = realloc(ptr, new_num*size); if (!newptr) { free(ptr); return newptr; } /* Zero the new portion of the array */ memset( (char *) newptr + old_num*size/sizeof(char), 0, (new_num - old_num)*size ); return (newptr); } cfitsio-4.3.1/iter_b.c0000644000225700000360000000716613472024437014075 0ustar cagordonlhea#include #include #include #include "fitsio.h" /* This program illustrates how to use the CFITSIO iterator function. It simply prints out the values in a character string and a logical type column in a table, and toggles the value in the logical column so that T -> F and F -> T. */ main() { extern str_iter(); /* external work function is passed to the iterator */ fitsfile *fptr; iteratorCol cols[2]; int n_cols; long rows_per_loop, offset; int status = 0; char filename[] = "iter_b.fit"; /* name of rate FITS file */ /* open the file and move to the correct extension */ fits_open_file(&fptr, filename, READWRITE, &status); fits_movnam_hdu(fptr, BINARY_TBL, "iter_test", 0, &status); /* define input column structure members for the iterator function */ n_cols = 2; /* number of columns */ /* define input column structure members for the iterator function */ fits_iter_set_by_name(&cols[0], fptr, "Avalue", TSTRING, InputOutputCol); fits_iter_set_by_name(&cols[1], fptr, "Lvalue", TLOGICAL, InputOutputCol); rows_per_loop = 0; /* use default optimum number of rows */ offset = 0; /* process all the rows */ /* apply the function to each row of the table */ printf("Calling iterator function...%d\n", status); fits_iterate_data(n_cols, cols, offset, rows_per_loop, str_iter, 0L, &status); fits_close_file(fptr, &status); /* all done */ if (status) fits_report_error(stderr, status); /* print out error messages */ return(status); } /*--------------------------------------------------------------------------*/ int str_iter(long totalrows, long offset, long firstrow, long nrows, int ncols, iteratorCol *cols, void *user_strct ) /* Sample iterator function. */ { int ii; /* declare variables static to preserve their values between calls */ static char **stringvals; static char *logicalvals; /*--------------------------------------------------------*/ /* Initialization procedures: execute on the first call */ /*--------------------------------------------------------*/ if (firstrow == 1) { if (ncols != 2) return(-1); /* number of columns incorrect */ if (fits_iter_get_datatype(&cols[0]) != TSTRING || fits_iter_get_datatype(&cols[1]) != TLOGICAL ) return(-2); /* bad data type */ /* assign the input pointers to the appropriate arrays */ stringvals = (char **) fits_iter_get_array(&cols[0]); logicalvals = (char *) fits_iter_get_array(&cols[1]); printf("Total rows, No. rows = %d %d\n",totalrows, nrows); } /*------------------------------------------*/ /* Main loop: process all the rows of data */ /*------------------------------------------*/ /* NOTE: 1st element of array is the null pixel value! */ /* Loop from 1 to nrows, not 0 to nrows - 1. */ for (ii = 1; ii <= nrows; ii++) { printf("%s %d\n", stringvals[ii], logicalvals[ii]); if (logicalvals[ii]) { logicalvals[ii] = FALSE; strcpy(stringvals[ii], "changed to false"); } else { logicalvals[ii] = TRUE; strcpy(stringvals[ii], "changed to true"); } } /*-------------------------------------------------------*/ /* Clean up procedures: after processing all the rows */ /*-------------------------------------------------------*/ if (firstrow + nrows - 1 == totalrows) { /* no action required in this case */ } return(0); } cfitsio-4.3.1/iter_c.f0000644000225700000360000002443513472024437014077 0ustar cagordonlhea program f77iterate_c C C This example program illustrates how to use the CFITSIO iterator function. C C This program creates a 2D histogram of the X and Y columns of an event C list. The 'main' routine just creates the empty new image, then executes C the 'writehisto' work function by calling the CFITSIO iterator function. C C 'writehisto' opens the FITS event list that contains the X and Y columns. C It then calls a second work function, calchisto, (by recursively calling C the CFITSIO iterator function) which actually computes the 2D histogram. C external work function to be passed to the iterator external writehisto integer ncols parameter (ncols=1) integer units(ncols), colnum(ncols), datatype(ncols) integer iotype(ncols), offset, n_per_loop, status character*70 colname(ncols) integer naxes(2), ounit, blocksize character*80 fname logical exists C include f77.inc ------------------------------------- C Codes for FITS extension types integer IMAGE_HDU, ASCII_TBL, BINARY_TBL parameter ( & IMAGE_HDU = 0, & ASCII_TBL = 1, & BINARY_TBL = 2 ) C Codes for FITS table data types integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX parameter ( & TBIT = 1, & TBYTE = 11, & TLOGICAL = 14, & TSTRING = 16, & TSHORT = 21, & TINT = 31, & TFLOAT = 42, & TDOUBLE = 82, & TCOMPLEX = 83, & TDBLCOMPLEX = 163 ) C Codes for iterator column types integer InputCol, InputOutputCol, OutputCol parameter ( & InputCol = 0, & InputOutputCol = 1, & OutputCol = 2 ) C End of f77.inc ------------------------------------- C********************************************************************** C Need to make these variables available to the 2 work functions integer xsize,ysize,xbinsize,ybinsize common /histcomm/ xsize,ysize,xbinsize,ybinsize C********************************************************************** status = 0 xsize = 480 ysize = 480 xbinsize = 32 ybinsize = 32 fname = 'histoimg.fit' ounit = 15 C delete previous version of the file if it exists inquire(file=fname,exist=exists) if( exists ) then open(ounit,file=fname,status='old') close(ounit,status='delete') endif 99 blocksize = 2880 C create new output image call ftinit(ounit,fname,blocksize,status) naxes(1) = xsize naxes(2) = ysize C create primary HDU call ftiimg(ounit,32,2,naxes,status) units(1) = ounit C Define column as TINT and Output datatype(1) = TINT iotype(1) = OutputCol C force whole array to be passed at one time n_per_loop = -1 offset = 0 C execute the function to create and write the 2D histogram print *,'Calling writehisto iterator work function... ',status call ftiter( ncols, units, colnum, colname, datatype, iotype, & offset, n_per_loop, writehisto, 0, status ) call ftclos(ounit, status) C print out error messages if problem if (status.ne.0) then call ftrprt('STDERR', status) else print *,'Program completed successfully.' endif stop end C-------------------------------------------------------------------------- C C Sample iterator function. C C Iterator work function that writes out the 2D histogram. C The histogram values are calculated by another work function, calchisto. C C-------------------------------------------------------------------------- subroutine writehisto(totaln, offset, firstn, nvalues, narrays, & units_out, colnum_out, datatype_out, iotype_out, repeat, & status, userData, histogram ) integer totaln,offset,firstn,nvalues,narrays,status integer units_out(narrays),colnum_out(narrays) integer datatype_out(narrays),iotype_out(narrays) integer repeat(narrays) integer histogram(*), userData external calchisto integer ncols parameter (ncols=2) integer units(ncols), colnum(ncols), datatype(ncols) integer iotype(ncols), rowoffset, rows_per_loop character*70 colname(ncols) integer iunit, blocksize character*80 fname C include f77.inc ------------------------------------- C Codes for FITS extension types integer IMAGE_HDU, ASCII_TBL, BINARY_TBL parameter ( & IMAGE_HDU = 0, & ASCII_TBL = 1, & BINARY_TBL = 2 ) C Codes for FITS table data types integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX parameter ( & TBIT = 1, & TBYTE = 11, & TLOGICAL = 14, & TSTRING = 16, & TSHORT = 21, & TINT = 31, & TFLOAT = 42, & TDOUBLE = 82, & TCOMPLEX = 83, & TDBLCOMPLEX = 163 ) C Codes for iterator column types integer InputCol, InputOutputCol, OutputCol parameter ( & InputCol = 0, & InputOutputCol = 1, & OutputCol = 2 ) C End of f77.inc ------------------------------------- C********************************************************************** C Need to make these variables available to the 2 work functions integer xsize,ysize,xbinsize,ybinsize common /histcomm/ xsize,ysize,xbinsize,ybinsize C********************************************************************** if (status .ne. 0) return C name of FITS table fname = 'iter_c.fit' iunit = 16 C do sanity checking of input values if (totaln .ne. nvalues) then C whole image must be passed at one time status = -1 return endif if (narrays .ne. 1) then C number of images is incorrect status = -2 return endif if (datatype_out(1) .ne. TINT) then C input array has wrong data type status = -3 return endif C open the file and move to the table containing the X and Y columns call ftopen(iunit,fname,0,blocksize,status) call ftmnhd(iunit, BINARY_TBL, 'EVENTS', 0, status) if (status) return C both the columns are in the same FITS file units(1) = iunit units(2) = iunit C desired datatype for each column: TINT datatype(1) = TINT datatype(2) = TINT C names of the columns colname(1) = 'X' colname(2) = 'Y' C leave column numbers undefined colnum(1) = 0 colnum(2) = 0 C define whether columns are input, input/output, or output only C Both input iotype(1) = InputCol iotype(1) = InputCol C take default number of rows per iteration rows_per_loop = 0 rowoffset = 0 C calculate the histogram print *,'Calling calchisto iterator work function... ', status call ftiter( ncols, units, colnum, colname, datatype, iotype, & rowoffset, rows_per_loop, calchisto, histogram, status ) call ftclos(iunit,status) return end C-------------------------------------------------------------------------- C C Iterator work function that calculates values for the 2D histogram. C C-------------------------------------------------------------------------- subroutine calchisto(totalrows, offset, firstrow, nrows, ncols, & units, colnum, datatype, iotype, repeat, status, & histogram, xcol, ycol ) integer totalrows,offset,firstrow,nrows,ncols,status integer units(ncols),colnum(ncols),datatype(ncols) integer iotype(ncols),repeat(ncols) integer histogram(*),xcol(*),ycol(*) C include f77.inc ------------------------------------- C Codes for FITS extension types integer IMAGE_HDU, ASCII_TBL, BINARY_TBL parameter ( & IMAGE_HDU = 0, & ASCII_TBL = 1, & BINARY_TBL = 2 ) C Codes for FITS table data types integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX parameter ( & TBIT = 1, & TBYTE = 11, & TLOGICAL = 14, & TSTRING = 16, & TSHORT = 21, & TINT = 31, & TFLOAT = 42, & TDOUBLE = 82, & TCOMPLEX = 83, & TDBLCOMPLEX = 163 ) C Codes for iterator column types integer InputCol, InputOutputCol, OutputCol parameter ( & InputCol = 0, & InputOutputCol = 1, & OutputCol = 2 ) C End of f77.inc ------------------------------------- integer ii, ihisto, xbin, ybin C********************************************************************** C Need to make these variables available to the 2 work functions integer xsize,ysize,xbinsize,ybinsize common /histcomm/ xsize,ysize,xbinsize,ybinsize C********************************************************************** if (status .ne. 0) return C -------------------------------------------------------- C Initialization procedures: execute on the first call C -------------------------------------------------------- if (firstrow .eq. 1) then C do sanity checking of input values if (ncols .ne. 2) then C number of arrays is incorrect status = -4 return endif if (datatype(1).ne.TINT .or. datatype(2).ne.TINT) then C wrong datatypes status = -5 return endif C initialize the histogram image pixels = 0, including null value do 10 ii = 1, xsize * ysize + 1 histogram(ii) = 0 10 continue endif C ------------------------------------------------------------------ C Main loop: increment the 2D histogram at position of each event C ------------------------------------------------------------------ do 20 ii=2,nrows+1 xbin = xcol(ii) / xbinsize ybin = ycol(ii) / ybinsize ihisto = ( ybin * xsize ) + xbin + 2 histogram(ihisto) = histogram(ihisto) + 1 20 continue return end cfitsio-4.3.1/getcoll.c0000644000225700000360000005540213472024437014256 0ustar cagordonlhea/* This file, getcoll.c, contains routines that read data elements from */ /* a FITS image or table, with logical datatype. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgcvl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ char nulval, /* I - value for null pixels */ char *array, /* O - array of values */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of logical values from a column in the current FITS HDU. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = 0 in which case no checks for undefined pixels will be made. */ { char cdummy; ffgcll( fptr, colnum, firstrow, firstelem, nelem, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ char *array, /* O - array of values */ int *status) /* IO - error status */ /* !!!! THIS ROUTINE IS DEPRECATED AND SHOULD NOT BE USED !!!!!! !!!! USE ffgcvl INSTEAD !!!!!! Read an array of logical values from a column in the current FITS HDU. No checking for null values will be performed. */ { char nulval = 0; int anynul; ffgcvl( fptr, colnum, firstrow, firstelem, nelem, nulval, array, &anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ char *array, /* O - array of values */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of logical values from a column in the current FITS HDU. */ { char nulval = 0; ffgcll( fptr, colnum, firstrow, firstelem, nelem, 2, nulval, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ char nulval, /* I - value for null pixels if nultyp = 1 */ char *array, /* O - array of values */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of logical values from a column in the current FITS HDU. */ { double dtemp; int tcode, maxelem, hdutype, ii, nulcheck; long twidth, incre; long ntodo; LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next; double scale, zero; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ unsigned char buffer[DBUFFSIZE], *buffptr; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); if (tcode != TLOGICAL) return(*status = NOT_LOGICAL_COL); /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default, check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ /*---------------------------------------------------------------------*/ /* Now read the logical values from the FITS column. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to read */ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ ntodo = (long) remain; /* max number of elements to read at one time */ while (ntodo) { /* limit the number of pixels to read at one time to the number that remain in the current vector. */ ntodo = (long) minvalue(ntodo, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); readptr = startpos + (rowlen * rownum) + (elemnum * incre); ffgi1b(fptr, readptr, ntodo, incre, buffer, status); /* convert from T or F to 1 or 0 */ buffptr = buffer; for (ii = 0; ii < ntodo; ii++, next++, buffptr++) { if (*buffptr == 'T') array[next] = 1; else if (*buffptr =='F') array[next] = 0; else if (*buffptr == 0) { array[next] = nulval; /* set null values to input nulval */ if (anynul) *anynul = 1; if (nulcheck == 2) { nularray[next] = 1; /* set null flags */ } } else /* some other illegal character; return the char value */ { if (*buffptr == 1) { /* this is an unfortunate case where the illegal value is the same as what we set True values to, so set the value to the character '1' instead, which has ASCII value 49. */ array[next] = 49; } else { array[next] = (char) *buffptr; } } } if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thruough %.0f of logical array (ffgcl).", dtemp+1., dtemp + ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on later row */ { elemnum = 0; rownum++; } } ntodo = (long) remain; /* this is the maximum number to do in next loop */ } /* End of main while Loop */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgcx( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG frow, /* I - first row to write (1 = 1st row) */ LONGLONG fbit, /* I - first bit to write (1 = 1st) */ LONGLONG nbit, /* I - number of bits to write */ char *larray, /* O - array of logicals corresponding to bits */ int *status) /* IO - error status */ /* read an array of logical values from a specified bit or byte column of the binary table. larray is set = TRUE, if the corresponding bit = 1, otherwise it is set to FALSE. The binary table column being read from must have datatype 'B' or 'X'. */ { LONGLONG bstart; long offset, ndone, ii, repeat, bitloc, fbyte; LONGLONG rstart, estart; int tcode, descrp; unsigned char cbuff; static unsigned char onbit[8] = {128, 64, 32, 16, 8, 4, 2, 1}; tcolumn *colptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check input parameters */ if (nbit < 1) return(*status); else if (frow < 1) return(*status = BAD_ROW_NUM); else if (fbit < 1) return(*status = BAD_ELEM_NUM); /* position to the correct HDU */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); fbyte = (long) ((fbit + 7) / 8); bitloc = (long) (fbit - 1 - ((fbit - 1) / 8 * 8)); ndone = 0; rstart = frow - 1; estart = fbyte - 1; colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (abs(tcode) > TBYTE) return(*status = NOT_LOGICAL_COL); /* not correct datatype column */ if (tcode > 0) { descrp = FALSE; /* not a variable length descriptor column */ /* N.B: REPEAT is the number of bytes, not number of bits */ repeat = (long) colptr->trepeat; if (tcode == TBIT) repeat = (repeat + 7) / 8; /* convert from bits to bytes */ if (fbyte > repeat) return(*status = BAD_ELEM_NUM); /* calc the i/o pointer location to start of sequence of pixels */ bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) + colptr->tbcol + estart; } else { descrp = TRUE; /* a variable length descriptor column */ /* only bit arrays (tform = 'X') are supported for variable */ /* length arrays. REPEAT is the number of BITS in the array. */ ffgdes(fptr, colnum, frow, &repeat, &offset, status); if (tcode == -TBIT) repeat = (repeat + 7) / 8; if ((fbit + nbit + 6) / 8 > repeat) return(*status = BAD_ELEM_NUM); /* calc the i/o pointer location to start of sequence of pixels */ bstart = (fptr->Fptr)->datastart + offset + (fptr->Fptr)->heapstart + estart; } /* move the i/o pointer to the start of the pixel sequence */ if (ffmbyt(fptr, bstart, REPORT_EOF, status) > 0) return(*status); /* read the next byte */ while (1) { if (ffgbyt(fptr, 1, &cbuff, status) > 0) return(*status); for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++) { if(cbuff & onbit[ii]) /* test if bit is set */ larray[ndone] = TRUE; else larray[ndone] = FALSE; } if (ndone == nbit) /* finished all the bits */ return(*status); /* not done, so get the next byte */ if (!descrp) { estart++; if (estart == repeat) { /* move the i/o pointer to the next row of pixels */ estart = 0; rstart = rstart + 1; bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) + colptr->tbcol; ffmbyt(fptr, bstart, REPORT_EOF, status); } } bitloc = 0; } } /*--------------------------------------------------------------------------*/ int ffgcxui(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG nrows, /* I - no. of rows to read */ long input_first_bit, /* I - first bit to read (1 = 1st) */ int input_nbits, /* I - number of bits to read (<= 32) */ unsigned short *array, /* O - array of integer values */ int *status) /* IO - error status */ /* Read a consecutive string of bits from an 'X' or 'B' column and interprete them as an unsigned integer. The number of bits must be less than or equal to 16 or the total number of bits in the column, which ever is less. */ { int ii, firstbit, nbits, bytenum, startbit, numbits, endbit; int firstbyte, lastbyte, nbytes, rshift, lshift; unsigned short colbyte[5]; tcolumn *colptr; char message[FLEN_ERRMSG]; if (*status > 0 || nrows == 0) return(*status); /* check input parameters */ if (firstrow < 1) { snprintf(message,FLEN_ERRMSG, "Starting row number is less than 1: %ld (ffgcxui)", (long) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } else if (input_first_bit < 1) { snprintf(message,FLEN_ERRMSG, "Starting bit number is less than 1: %ld (ffgcxui)", input_first_bit); ffpmsg(message); return(*status = BAD_ELEM_NUM); } else if (input_nbits > 16) { snprintf(message, FLEN_ERRMSG,"Number of bits to read is > 16: %d (ffgcxui)", input_nbits); ffpmsg(message); return(*status = BAD_ELEM_NUM); } /* position to the correct HDU */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg("This is not a binary table extension (ffgcxui)"); return(*status = NOT_BTABLE); } if (colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d (ffgcxui)", colnum); ffpmsg(message); snprintf(message, FLEN_ERRMSG," There are %d columns in this table.", (fptr->Fptr)->tfield ); ffpmsg(message); return(*status = BAD_COL_NUM); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ if (abs(colptr->tdatatype) > TBYTE) { ffpmsg("Can only read bits from X or B type columns. (ffgcxui)"); return(*status = NOT_LOGICAL_COL); /* not correct datatype column */ } firstbyte = (input_first_bit - 1 ) / 8 + 1; lastbyte = (input_first_bit + input_nbits - 2) / 8 + 1; nbytes = lastbyte - firstbyte + 1; if (colptr->tdatatype == TBIT && input_first_bit + input_nbits - 1 > (long) colptr->trepeat) { ffpmsg("Too many bits. Tried to read past width of column (ffgcxui)"); return(*status = BAD_ELEM_NUM); } else if (colptr->tdatatype == TBYTE && lastbyte > (long) colptr->trepeat) { ffpmsg("Too many bits. Tried to read past width of column (ffgcxui)"); return(*status = BAD_ELEM_NUM); } for (ii = 0; ii < nrows; ii++) { /* read the relevant bytes from the row */ if (ffgcvui(fptr, colnum, firstrow+ii, firstbyte, nbytes, 0, colbyte, NULL, status) > 0) { ffpmsg("Error reading bytes from column (ffgcxui)"); return(*status); } firstbit = (input_first_bit - 1) % 8; /* modulus operator */ nbits = input_nbits; array[ii] = 0; /* select and shift the bits from each byte into the output word */ while(nbits) { bytenum = firstbit / 8; startbit = firstbit % 8; numbits = minvalue(nbits, 8 - startbit); endbit = startbit + numbits - 1; rshift = 7 - endbit; lshift = nbits - numbits; array[ii] = ((colbyte[bytenum] >> rshift) << lshift) | array[ii]; nbits -= numbits; firstbit += numbits; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgcxuk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG nrows, /* I - no. of rows to read */ long input_first_bit, /* I - first bit to read (1 = 1st) */ int input_nbits, /* I - number of bits to read (<= 32) */ unsigned int *array, /* O - array of integer values */ int *status) /* IO - error status */ /* Read a consecutive string of bits from an 'X' or 'B' column and interprete them as an unsigned integer. The number of bits must be less than or equal to 32 or the total number of bits in the column, which ever is less. */ { int ii, firstbit, nbits, bytenum, startbit, numbits, endbit; int firstbyte, lastbyte, nbytes, rshift, lshift; unsigned int colbyte[5]; tcolumn *colptr; char message[FLEN_ERRMSG]; if (*status > 0 || nrows == 0) return(*status); /* check input parameters */ if (firstrow < 1) { snprintf(message, FLEN_ERRMSG,"Starting row number is less than 1: %ld (ffgcxuk)", (long) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } else if (input_first_bit < 1) { snprintf(message, FLEN_ERRMSG,"Starting bit number is less than 1: %ld (ffgcxuk)", input_first_bit); ffpmsg(message); return(*status = BAD_ELEM_NUM); } else if (input_nbits > 32) { snprintf(message, FLEN_ERRMSG,"Number of bits to read is > 32: %d (ffgcxuk)", input_nbits); ffpmsg(message); return(*status = BAD_ELEM_NUM); } /* position to the correct HDU */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg("This is not a binary table extension (ffgcxuk)"); return(*status = NOT_BTABLE); } if (colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d (ffgcxuk)", colnum); ffpmsg(message); snprintf(message, FLEN_ERRMSG," There are %d columns in this table.", (fptr->Fptr)->tfield ); ffpmsg(message); return(*status = BAD_COL_NUM); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ if (abs(colptr->tdatatype) > TBYTE) { ffpmsg("Can only read bits from X or B type columns. (ffgcxuk)"); return(*status = NOT_LOGICAL_COL); /* not correct datatype column */ } firstbyte = (input_first_bit - 1 ) / 8 + 1; lastbyte = (input_first_bit + input_nbits - 2) / 8 + 1; nbytes = lastbyte - firstbyte + 1; if (colptr->tdatatype == TBIT && input_first_bit + input_nbits - 1 > (long) colptr->trepeat) { ffpmsg("Too many bits. Tried to read past width of column (ffgcxuk)"); return(*status = BAD_ELEM_NUM); } else if (colptr->tdatatype == TBYTE && lastbyte > (long) colptr->trepeat) { ffpmsg("Too many bits. Tried to read past width of column (ffgcxuk)"); return(*status = BAD_ELEM_NUM); } for (ii = 0; ii < nrows; ii++) { /* read the relevant bytes from the row */ if (ffgcvuk(fptr, colnum, firstrow+ii, firstbyte, nbytes, 0, colbyte, NULL, status) > 0) { ffpmsg("Error reading bytes from column (ffgcxuk)"); return(*status); } firstbit = (input_first_bit - 1) % 8; /* modulus operator */ nbits = input_nbits; array[ii] = 0; /* select and shift the bits from each byte into the output word */ while(nbits) { bytenum = firstbit / 8; startbit = firstbit % 8; numbits = minvalue(nbits, 8 - startbit); endbit = startbit + numbits - 1; rshift = 7 - endbit; lshift = nbits - numbits; array[ii] = ((colbyte[bytenum] >> rshift) << lshift) | array[ii]; nbits -= numbits; firstbit += numbits; } } return(*status); } cfitsio-4.3.1/putcoluk.c0000644000225700000360000010550513472024437014473 0ustar cagordonlhea/* This file, putcolk.c, contains routines that write data elements to */ /* a FITS image or table, with 'unsigned int' datatype. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffppruk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned int *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; unsigned int nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_pixels(fptr, TUINT, firstelem, nelem, 0, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcluk(fptr, 2, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffppnuk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned int *array, /* I - array of values that are written */ unsigned int nulval, /* I - undefined pixel value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). Any array values that are equal to the value of nulval will be replaced with the null pixel value that is appropriate for this column. */ { long row; unsigned int nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_write_compressed_pixels(fptr, TUINT, firstelem, nelem, 1, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcnuk(fptr, 2, row, firstelem, nelem, array, nulval, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp2duk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ unsigned int *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { /* call the 3D writing routine, with the 3rd dimension = 1 */ ffp3duk(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp3duk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ unsigned int *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 3-D cube of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow, ii, jj; long fpixel[3]= {1,1,1}, lpixel[3]; LONGLONG nfits, narray; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = (long) ncols; lpixel[1] = (long) nrows; lpixel[2] = (long) naxis3; fits_write_compressed_img(fptr, TUINT, fpixel, lpixel, 0, array, NULL, status); return(*status); } tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so write all at once */ ffpcluk(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to write to */ narray = 0; /* next pixel in input array to be written */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* writing naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffpcluk(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpssuk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long naxis, /* I - number of data axes in array */ long *naxes, /* I - size of each FITS axis */ long *fpixel, /* I - 1st pixel in each axis to write (1=1st) */ long *lpixel, /* I - last pixel in each axis to write */ unsigned int *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write a subsection of pixels to the primary array or image. A subsection is defined to be any contiguous rectangular array of pixels within the n-dimensional FITS data file. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow; LONGLONG fpix[7], dimen[7], astart, pstart; LONGLONG off2, off3, off4, off5, off6, off7; LONGLONG st10, st20, st30, st40, st50, st60, st70; LONGLONG st1, st2, st3, st4, st5, st6, st7; long ii, i1, i2, i3, i4, i5, i6, i7, irange[7]; if (*status > 0) return(*status); if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_img(fptr, TUINT, fpixel, lpixel, 0, array, NULL, status); return(*status); } if (naxis < 1 || naxis > 7) return(*status = BAD_DIMEN); tablerow=maxvalue(1,group); /* calculate the size and number of loops to perform in each dimension */ for (ii = 0; ii < 7; ii++) { fpix[ii]=1; irange[ii]=1; dimen[ii]=1; } for (ii = 0; ii < naxis; ii++) { fpix[ii]=fpixel[ii]; irange[ii]=lpixel[ii]-fpixel[ii]+1; dimen[ii]=naxes[ii]; } i1=irange[0]; /* compute the pixel offset between each dimension */ off2 = dimen[0]; off3 = off2 * dimen[1]; off4 = off3 * dimen[2]; off5 = off4 * dimen[3]; off6 = off5 * dimen[4]; off7 = off6 * dimen[5]; st10 = fpix[0]; st20 = (fpix[1] - 1) * off2; st30 = (fpix[2] - 1) * off3; st40 = (fpix[3] - 1) * off4; st50 = (fpix[4] - 1) * off5; st60 = (fpix[5] - 1) * off6; st70 = (fpix[6] - 1) * off7; /* store the initial offset in each dimension */ st1 = st10; st2 = st20; st3 = st30; st4 = st40; st5 = st50; st6 = st60; st7 = st70; astart = 0; for (i7 = 0; i7 < irange[6]; i7++) { for (i6 = 0; i6 < irange[5]; i6++) { for (i5 = 0; i5 < irange[4]; i5++) { for (i4 = 0; i4 < irange[3]; i4++) { for (i3 = 0; i3 < irange[2]; i3++) { pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7; for (i2 = 0; i2 < irange[1]; i2++) { if (ffpcluk(fptr, 2, tablerow, pstart, i1, &array[astart], status) > 0) return(*status); astart += i1; pstart += off2; } st2 = st20; st3 = st3+off3; } st3 = st30; st4 = st4+off4; } st4 = st40; st5 = st5+off5; } st5 = st50; st6 = st6+off6; } st6 = st60; st7 = st7+off7; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpgpuk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long firstelem, /* I - first vector element to write(1 = 1st) */ long nelem, /* I - number of values to write */ unsigned int *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of group parameters to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffpcluk(fptr, 1L, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpcluk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned int *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of values to a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer to a virtual column in a 1 or more grouped FITS primary array. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary. */ { int tcode, maxelem, hdutype; long twidth, incre; long ntodo; LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull; double scale, zero; char tform[20], cform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* call the 'short' or 'long' version of this routine, if possible */ if (sizeof(int) == sizeof(short)) ffpclui(fptr, colnum, firstrow, firstelem, nelem, (unsigned short *) array, status); else if (sizeof(int) == sizeof(long)) ffpcluj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array, status); else { /* This is a special case: sizeof(int) is not equal to sizeof(short) or sizeof(long). This occurs on Alpha OSF systems where short = 2 bytes, int = 4 bytes, and long = 8 bytes. */ buffer = cbuff; /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); if (tcode == TSTRING) ffcfmt(tform, cform); /* derive C format for writing strings */ /*---------------------------------------------------------------------*/ /* Now write the pixels to the FITS column. */ /* First call the ffXXfYY routine to (1) convert the datatype */ /* if necessary, and (2) scale the values by the FITS TSCALn and */ /* TZEROn linear scaling parameters into a temporary buffer. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to write */ next = 0; /* next element in array to be written */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to process a one time to the number that will fit in the buffer space or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre); ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */ switch (tcode) { case (TLONG): /* convert the raw data before writing to FITS file */ ffuintfi4(&array[next], ntodo, scale, zero, (INT32BIT *) buffer, status); ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status); break; case (TLONGLONG): ffuintfi8(&array[next], ntodo, scale, zero, (LONGLONG *) buffer, status); ffpi8b(fptr, ntodo, incre, (long *) buffer, status); break; case (TBYTE): ffuintfi1(&array[next], ntodo, scale, zero, (unsigned char *) buffer, status); ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status); break; case (TSHORT): ffuintfi2(&array[next], ntodo, scale, zero, (short *) buffer, status); ffpi2b(fptr, ntodo, incre, (short *) buffer, status); break; case (TFLOAT): ffuintfr4(&array[next], ntodo, scale, zero, (float *) buffer, status); ffpr4b(fptr, ntodo, incre, (float *) buffer, status); break; case (TDOUBLE): ffuintfr8(&array[next], ntodo, scale, zero, (double *) buffer, status); ffpr8b(fptr, ntodo, incre, (double *) buffer, status); break; case (TSTRING): /* numerical column in an ASCII table */ if (cform[1] != 's') /* "%s" format is a string */ { ffuintfstr(&array[next], ntodo, scale, zero, cform, twidth, (char *) buffer, status); if (incre == twidth) /* contiguous bytes */ ffpbyt(fptr, ntodo * twidth, buffer, status); else ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); break; } /* can't write to string column, so fall thru to default: */ default: /* error trap */ snprintf(message,FLEN_ERRMSG, "Cannot write numbers to column %d which has format %s", colnum,tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous write operation */ { snprintf(message,FLEN_ERRMSG, "Error writing elements %.0f thru %.0f of input data array (ffpcluk).", (double) (next+1), (double) (next+ntodo)); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while writing FITS data."); *status = NUM_OVERFLOW; } } /* end of Dec ALPHA special case */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpcnuk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned int *array, /* I - array of values to write */ unsigned int nulvalue, /* I - value used to flag undefined pixels */ int *status) /* IO - error status */ /* Write an array of elements to the specified column of a table. Any input pixels equal to the value of nulvalue will be replaced by the appropriate null value in the output FITS file. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary */ { tcolumn *colptr; LONGLONG ngood = 0, nbad = 0, ii; LONGLONG repeat, first, fstelm, fstrow; int tcode, overflow = 0; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode > 0) repeat = colptr->trepeat; /* repeat count for this column */ else repeat = firstelem -1 + nelem; /* variable length arrays */ /* if variable length array, first write the whole input vector, then go back and fill in the nulls */ if (tcode < 0) { if (ffpcluk(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) { if (*status == NUM_OVERFLOW) { /* ignore overflows, which are possibly the null pixel values */ /* overflow = 1; */ *status = 0; } else { return(*status); } } } /* absolute element number in the column */ first = (firstrow - 1) * repeat + firstelem; for (ii = 0; ii < nelem; ii++) { if (array[ii] != nulvalue) /* is this a good pixel? */ { if (nbad) /* write previous string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0) return(*status); nbad=0; } ngood = ngood +1; /* the consecutive number of good pixels */ } else { if (ngood) /* write previous string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ if (ffpcluk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status) > 0) { if (*status == NUM_OVERFLOW) { overflow = 1; *status = 0; } else { return(*status); } } } ngood=0; } nbad = nbad +1; /* the consecutive number of bad pixels */ } } /* finished loop; now just write the last set of pixels */ if (ngood) /* write last string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ ffpcluk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status); } } else if (nbad) /* write last string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ ffpclu(fptr, colnum, fstrow, fstelm, nbad, status); } if (*status <= 0) { if (overflow) { *status = NUM_OVERFLOW; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfi1(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ unsigned char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) (dvalue + .5); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfi2(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ short *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > SHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else output[ii] = input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; output[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else { if (dvalue >= 0) output[ii] = (short) (dvalue + .5); else output[ii] = (short) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfi4(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ INT32BIT *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 2147483648.) { /* Instead of subtracting 2147483648, it is more efficient */ /* to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) output[ii] = ( *(int *) &input[ii] ) ^ 0x80000000; } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > INT32_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else output[ii] = input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; output[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else { if (dvalue >= 0) output[ii] = (INT32BIT) (dvalue + .5); else output[ii] = (INT32BIT) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfi8(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ LONGLONG *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 9223372036854775808.) { /* Writing to unsigned long long column. */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ /* no need to check range limits because all unsigned int values */ /* are valid ULONGLONG values. */ for (ii = 0; ii < ntodo; ii++) { output[ii] = ((LONGLONG) input[ii]) ^ 0x8000000000000000; } } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { output[ii] = input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { if (dvalue >= 0) output[ii] = (LONGLONG) (dvalue + .5); else output[ii] = (LONGLONG) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfr4(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ float *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) ((input[ii] - zero) / scale); } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfr8(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ double *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (double) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (input[ii] - zero) / scale; } return(*status); } /*--------------------------------------------------------------------------*/ int ffuintfstr(unsigned int *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ char *cform, /* I - format for output string values */ long twidth, /* I - width of each field, in chars */ char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do scaling if required. */ { long ii; double dvalue; char *cptr; cptr = output; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { sprintf(output, cform, (double) input[ii]); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; sprintf(output, cform, dvalue); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } /* replace any commas with periods (e.g., in French locale) */ while ((cptr = strchr(cptr, ','))) *cptr = '.'; return(*status); } cfitsio-4.3.1/iter_image.c0000644000225700000360000000600413472024437014724 0ustar cagordonlhea#include #include #include #include "fitsio.h" /* This program illustrates how to use the CFITSIO iterator function. It reads and modifies the input 'iter_image.fit' image file by setting all the pixel values to zero (DESTROYING THE ORIGINAL IMAGE!!!) */ main() { extern zero_image(); /* external work function is passed to the iterator */ fitsfile *fptr; iteratorCol cols[3]; /* structure used by the iterator function */ int n_cols; long rows_per_loop, offset; int status, nkeys, keypos, hdutype, ii, jj; char filename[] = "iter_image.fit"; /* name of rate FITS file */ status = 0; fits_open_file(&fptr, filename, READWRITE, &status); /* open file */ n_cols = 1; /* define input column structure members for the iterator function */ fits_iter_set_file(&cols[0], fptr); fits_iter_set_iotype(&cols[0], InputOutputCol); fits_iter_set_datatype(&cols[0], 0); rows_per_loop = 0; /* use default optimum number of rows */ offset = 0; /* process all the rows */ /* apply the rate function to each row of the table */ printf("Calling iterator function...%d\n", status); fits_iterate_data(n_cols, cols, offset, rows_per_loop, zero_image, 0L, &status); fits_close_file(fptr, &status); /* all done */ if (status) fits_report_error(stderr, status); /* print out error messages */ return(status); } /*--------------------------------------------------------------------------*/ int zero_image(long totalrows, long offset, long firstrow, long nrows, int ncols, iteratorCol *cols, void *user_strct ) /* Sample iterator function that calculates the output flux 'rate' column by dividing the input 'counts' by the 'time' column. It also applies a constant deadtime correction factor if the 'deadtime' keyword exists. Finally, this creates or updates the 'LIVETIME' keyword with the sum of all the individual integration times. */ { int ii, status = 0; /* declare variables static to preserve their values between calls */ static int *counts; /*--------------------------------------------------------*/ /* Initialization procedures: execute on the first call */ /*--------------------------------------------------------*/ if (firstrow == 1) { if (ncols != 1) return(-1); /* number of columns incorrect */ /* assign the input pointers to the appropriate arrays and null ptrs*/ counts = (int *) fits_iter_get_array(&cols[0]); } /*--------------------------------------------*/ /* Main loop: process all the rows of data */ /*--------------------------------------------*/ /* NOTE: 1st element of array is the null pixel value! */ /* Loop from 1 to nrows, not 0 to nrows - 1. */ for (ii = 1; ii <= nrows; ii++) { counts[ii] = 1.; } printf("firstrows, nrows = %d %d\n", firstrow, nrows); return(0); /* return successful status */ } cfitsio-4.3.1/config.sub0000755000225700000360000010315414214470324014435 0ustar cagordonlhea#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. timestamp='2021-01-08' # This file 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 . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=$(echo "$0" | sed -e 's,.*/,,') usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv4 ;; i*86v) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv ;; i*86sol2) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=$(echo "$basic_machine" | sed 's/-.*//') ;; *-*) # shellcheck disable=SC2162 IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc caes, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') ;; os2-emx) kernel=os2 os=$(echo $basic_os | sed -e 's|os2-emx|emx|') ;; nto-qnx*) kernel=nto os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') ;; *-*) # shellcheck disable=SC2162 IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; -dietlibc* | -newlib* | -musl* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; vxworks-simlinux | vxworks-simwindows | vxworks-spe) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfitsio-4.3.1/getcols.c0000644000225700000360000010216313640736632014266 0ustar cagordonlhea/* This file, getcols.c, contains routines that read data elements from */ /* a FITS image or table, with a character string datatype. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include /* stddef.h is apparently needed to define size_t */ #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgcvs( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of strings to read */ char *nulval, /* I - string for null pixels */ char **array, /* O - array of values that are read */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of string values from a column in the current FITS HDU. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = null in which case no checks for undefined pixels will be made. */ { char cdummy[2]; ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, nulval, array, cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfs( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of strings to read */ char **array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of string values from a column in the current FITS HDU. Nularray will be set = 1 if the corresponding array pixel is undefined, otherwise nularray will = 0. */ { char dummy[2]; ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcls( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of strings to read */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ char *nulval, /* I - value for null pixels if nultyp = 1 */ char **array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of string values from a column in the current FITS HDU. Returns a formated string value, regardless of the datatype of the column */ { int tcode, hdutype, tstatus, scaled, intcol, dwidth, nulwidth, ll, dlen; int equivtype; long ii, jj; tcolumn *colptr; char message[FLEN_ERRMSG], *carray, keyname[FLEN_KEYWORD]; char cform[20], dispfmt[20], tmpstr[400], *flgarray, tmpnull[80]; unsigned char byteval; float *earray; double *darray, tscale = 1.0; LONGLONG *llarray; ULONGLONG *ullarray; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d", colnum); ffpmsg(message); return(*status = BAD_COL_NUM); } /* get equivalent dataype of column (only needed for TLONGLONG columns) */ ffeqtyll(fptr, colnum, &equivtype, NULL, NULL, status); if (equivtype < 0) equivtype = abs(equivtype); colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = abs(colptr->tdatatype); intcol = 0; if (tcode == TSTRING) { /* simply call the string column reading routine */ ffgcls2(fptr, colnum, firstrow, firstelem, nelem, nultyp, nulval, array, nularray, anynul, status); } else if (tcode == TLOGICAL) { /* allocate memory for the array of logical values */ carray = (char *) malloc((size_t) nelem); /* call the logical column reading routine */ ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, *nulval, carray, nularray, anynul, status); if (*status <= 0) { /* convert logical values to "T", "F", or "N" (Null) */ for (ii = 0; ii < nelem; ii++) { if (carray[ii] == 1) strcpy(array[ii], "T"); else if (carray[ii] == 0) strcpy(array[ii], "F"); else /* undefined values = 2 */ strcpy(array[ii],"N"); } } free(carray); /* free the memory */ } else if (tcode == TCOMPLEX) { /* allocate memory for the array of double values */ earray = (float *) calloc((size_t) (nelem * 2), sizeof(float) ); ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 1, 1, FLOATNULLVALUE, earray, nularray, anynul, status); if (*status <= 0) { /* determine the format for the output strings */ ffgcdw(fptr, colnum, &dwidth, status); dwidth = (dwidth - 3) / 2; /* use the TDISPn keyword if it exists */ ffkeyn("TDISP", colnum, keyname, status); tstatus = 0; cform[0] = '\0'; if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0) { /* convert the Fortran style format to a C style format */ ffcdsp(dispfmt, cform); /* Special case: TDISPn='Aw' disallowed for numeric types */ if (dispfmt[0] == 'A') { cform[0] = 0; /* Special case: if the output is intended to be represented as an integer, but we read it as a double, we need to set intcol = 1 so it is printed as an integer */ } else if ((dispfmt[0] == 'I') || (dispfmt[0] == 'i') || (dispfmt[0] == 'O') || (dispfmt[0] == 'o') || (dispfmt[0] == 'Z') || (dispfmt[0] == 'z')) { intcol = 1; } } if (!cform[0]) strcpy(cform, "%14.6E"); /* write the formated string for each value: "(real,imag)" */ jj = 0; for (ii = 0; ii < nelem; ii++) { strcpy(array[ii], "("); /* test for null value */ if (earray[jj] == FLOATNULLVALUE) { strcpy(tmpstr, "NULL"); if (nultyp == 2) nularray[ii] = 1; } else if (intcol) { snprintf(tmpstr, 400,cform, (int) earray[jj]); } else { snprintf(tmpstr, 400,cform, earray[jj]); } strncat(array[ii], tmpstr, dwidth); strcat(array[ii], ","); jj++; /* test for null value */ if (earray[jj] == FLOATNULLVALUE) { strcpy(tmpstr, "NULL"); if (nultyp == 2) nularray[ii] = 1; } else if (intcol) { snprintf(tmpstr, 400,cform, (int) earray[jj]); } else { snprintf(tmpstr, 400,cform, earray[jj]); } strncat(array[ii], tmpstr, dwidth); strcat(array[ii], ")"); jj++; } } free(earray); /* free the memory */ } else if (tcode == TDBLCOMPLEX) { /* allocate memory for the array of double values */ darray = (double *) calloc((size_t) (nelem * 2), sizeof(double) ); ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 1, 1, DOUBLENULLVALUE, darray, nularray, anynul, status); if (*status <= 0) { /* determine the format for the output strings */ ffgcdw(fptr, colnum, &dwidth, status); dwidth = (dwidth - 3) / 2; /* use the TDISPn keyword if it exists */ ffkeyn("TDISP", colnum, keyname, status); tstatus = 0; cform[0] = '\0'; if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0) { /* convert the Fortran style format to a C style format */ ffcdsp(dispfmt, cform); /* Special case: TDISPn='Aw' disallowed for numeric types */ if (dispfmt[0] == 'A') { cform[0] = 0; /* Special case: if the output is intended to be represented as an integer, but we read it as a double, we need to set intcol = 1 so it is printed as an integer */ } else if ((dispfmt[0] == 'I') || (dispfmt[0] == 'i') || (dispfmt[0] == 'O') || (dispfmt[0] == 'o') || (dispfmt[0] == 'Z') || (dispfmt[0] == 'z')) { intcol = 1; } } if (!cform[0]) strcpy(cform, "%23.15E"); /* write the formated string for each value: "(real,imag)" */ jj = 0; for (ii = 0; ii < nelem; ii++) { strcpy(array[ii], "("); /* test for null value */ if (darray[jj] == DOUBLENULLVALUE) { strcpy(tmpstr, "NULL"); if (nultyp == 2) nularray[ii] = 1; } else if (intcol) { snprintf(tmpstr, 400,cform, (int) darray[jj]); } else { snprintf(tmpstr, 400,cform, darray[jj]); } strncat(array[ii], tmpstr, dwidth); strcat(array[ii], ","); jj++; /* test for null value */ if (darray[jj] == DOUBLENULLVALUE) { strcpy(tmpstr, "NULL"); if (nultyp == 2) nularray[ii] = 1; } else if (intcol) { snprintf(tmpstr, 400,cform, (int) darray[jj]); } else { snprintf(tmpstr, 400,cform, darray[jj]); } strncat(array[ii], tmpstr, dwidth); strcat(array[ii], ")"); jj++; } } free(darray); /* free the memory */ } else if (tcode == TLONGLONG && equivtype == TLONGLONG) { /* allocate memory for the array of LONGLONG values */ llarray = (LONGLONG *) calloc((size_t) nelem, sizeof(LONGLONG) ); flgarray = (char *) calloc((size_t) nelem, sizeof(char) ); dwidth = 20; /* max width of displayed long long integer value */ if (ffgcfjj(fptr, colnum, firstrow, firstelem, nelem, llarray, flgarray, anynul, status) > 0) { free(flgarray); free(llarray); return(*status); } /* write the formated string for each value */ if (nulval) { strncpy(tmpnull, nulval,79); tmpnull[79]='\0'; /* In case len(nulval) >= 79 */ nulwidth = strlen(tmpnull); } else { strcpy(tmpnull, " "); nulwidth = 1; } for (ii = 0; ii < nelem; ii++) { if ( flgarray[ii] ) { *array[ii] = '\0'; if (dwidth < nulwidth) strncat(array[ii], tmpnull, dwidth); else sprintf(array[ii],"%*s",dwidth,tmpnull); if (nultyp == 2) nularray[ii] = 1; } else { #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ snprintf(tmpstr, 400,"%20I64d", llarray[ii]); #elif (USE_LL_SUFFIX == 1) snprintf(tmpstr, 400,"%20lld", llarray[ii]); #else snprintf(tmpstr, 400,"%20ld", llarray[ii]); #endif *array[ii] = '\0'; strncat(array[ii], tmpstr, 20); } } free(flgarray); free(llarray); /* free the memory */ } else if (tcode == TLONGLONG && equivtype == TULONGLONG) { /* allocate memory for the array of ULONGLONG values */ ullarray = (ULONGLONG *) calloc((size_t) nelem, sizeof(ULONGLONG) ); flgarray = (char *) calloc((size_t) nelem, sizeof(char) ); dwidth = 20; /* max width of displayed unsigned long long integer value */ if (ffgcfujj(fptr, colnum, firstrow, firstelem, nelem, ullarray, flgarray, anynul, status) > 0) { free(flgarray); free(ullarray); return(*status); } /* write the formated string for each value */ if (nulval) { strncpy(tmpnull, nulval, 79); tmpnull[79]='\0'; /* In case len(nulval) >= 79 */ nulwidth = strlen(tmpnull); } else { strcpy(tmpnull, " "); nulwidth = 1; } for (ii = 0; ii < nelem; ii++) { if ( flgarray[ii] ) { *array[ii] = '\0'; if (dwidth < nulwidth) strncat(array[ii], tmpnull, dwidth); else sprintf(array[ii],"%*s",dwidth,tmpnull); if (nultyp == 2) nularray[ii] = 1; } else { #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ snprintf(tmpstr, 400, "%20I64u", ullarray[ii]); #elif (USE_LL_SUFFIX == 1) snprintf(tmpstr, 400, "%20llu", ullarray[ii]); #else snprintf(tmpstr, 400, "%20lu", ullarray[ii]); #endif *array[ii] = '\0'; strncat(array[ii], tmpstr, 20); } } free(flgarray); free(ullarray); /* free the memory */ } else { /* allocate memory for the array of double values */ darray = (double *) calloc((size_t) nelem, sizeof(double) ); /* read all other numeric type columns as doubles */ if (ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, nultyp, DOUBLENULLVALUE, darray, nularray, anynul, status) > 0) { free(darray); return(*status); } /* determine the format for the output strings */ ffgcdw(fptr, colnum, &dwidth, status); /* check if column is scaled */ ffkeyn("TSCAL", colnum, keyname, status); tstatus = 0; scaled = 0; if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0) { if (tscale != 1.0) scaled = 1; /* yes, this is a scaled column */ } intcol = 0; if (tcode <= TLONG && !scaled) intcol = 1; /* this is an unscaled integer column */ /* use the TDISPn keyword if it exists */ ffkeyn("TDISP", colnum, keyname, status); tstatus = 0; cform[0] = '\0'; if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0) { /* convert the Fortran style TDISPn to a C style format */ ffcdsp(dispfmt, cform); /* Special case: TDISPn='Aw' disallowed for numeric types */ if (dispfmt[0] == 'A') { cform[0] = 0; /* Special case: if the output is intended to be represented as an integer, but we read it as a double, we need to set intcol = 1 so it is printed as an integer */ } else if ((dispfmt[0] == 'I') || (dispfmt[0] == 'i') || (dispfmt[0] == 'O') || (dispfmt[0] == 'o') || (dispfmt[0] == 'Z') || (dispfmt[0] == 'z')) { intcol = 1; } } if (!cform[0]) { /* no TDISPn keyword; use TFORMn instead */ ffkeyn("TFORM", colnum, keyname, status); ffgkys(fptr, keyname, dispfmt, NULL, status); if (scaled && tcode <= TSHORT) { /* scaled short integer column == float */ strcpy(cform, "%#14.6G"); } else if (scaled && tcode == TLONG) { /* scaled long integer column == double */ strcpy(cform, "%#23.15G"); } else if (scaled && tcode == TLONGLONG) { /* scaled long long integer column == double */ strcpy(cform, "%#23.15G"); } else { ffghdt(fptr, &hdutype, status); if (hdutype == ASCII_TBL) { /* convert the Fortran style TFORMn to a C style format */ ffcdsp(dispfmt, cform); } else { /* this is a binary table, need to convert the format */ if (tcode == TBIT) { /* 'X' */ strcpy(cform, "%4d"); } else if (tcode == TBYTE) { /* 'B' */ strcpy(cform, "%4d"); } else if (tcode == TSHORT) { /* 'I' */ strcpy(cform, "%6d"); } else if (tcode == TLONG) { /* 'J' */ strcpy(cform, "%11.0f"); intcol = 0; /* needed to support unsigned int */ } else if (tcode == TFLOAT) { /* 'E' */ strcpy(cform, "%#14.6G"); } else if (tcode == TDOUBLE) { /* 'D' */ strcpy(cform, "%#23.15G"); } } } } if (nulval) { strncpy(tmpnull, nulval,79); tmpnull[79]='\0'; nulwidth = strlen(tmpnull); } else { strcpy(tmpnull, " "); nulwidth = 1; } /* write the formated string for each value */ for (ii = 0; ii < nelem; ii++) { if (tcode == TBIT) { byteval = (char) darray[ii]; for (ll=0; ll < 8; ll++) { if ( ((unsigned char) (byteval << ll)) >> 7 ) *(array[ii] + ll) = '1'; else *(array[ii] + ll) = '0'; } *(array[ii] + 8) = '\0'; } /* test for null value */ else if ( (nultyp == 1 && darray[ii] == DOUBLENULLVALUE) || (nultyp == 2 && nularray[ii]) ) { *array[ii] = '\0'; if (dwidth < nulwidth) strncat(array[ii], tmpnull, dwidth); else sprintf(array[ii],"%*s",dwidth,tmpnull); } else { if (intcol) { snprintf(tmpstr, 400,cform, (int) darray[ii]); } else { snprintf(tmpstr, 400,cform, darray[ii]); } /* fill field with '*' if number is too wide */ dlen = strlen(tmpstr); if (dlen > dwidth) { memset(tmpstr, '*', dwidth); } *array[ii] = '\0'; strncat(array[ii], tmpstr, dwidth); } } free(darray); /* free the memory */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffgcdw( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column (1 = 1st col) */ int *width, /* O - display width */ int *status) /* IO - error status */ /* Get Column Display Width. */ { tcolumn *colptr; char *cptr; char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], dispfmt[20]; int tcode, hdutype, tstatus, scaled; double tscale; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d", colnum); ffpmsg(message); return(*status = BAD_COL_NUM); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = abs(colptr->tdatatype); /* use the TDISPn keyword if it exists */ ffkeyn("TDISP", colnum, keyname, status); *width = 0; tstatus = 0; if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0) { /* parse TDISPn get the display width */ cptr = dispfmt; while(*cptr == ' ') /* skip leading blanks */ cptr++; if (*cptr == 'A' || *cptr == 'a' || *cptr == 'I' || *cptr == 'i' || *cptr == 'O' || *cptr == 'o' || *cptr == 'Z' || *cptr == 'z' || *cptr == 'F' || *cptr == 'f' || *cptr == 'E' || *cptr == 'e' || *cptr == 'D' || *cptr == 'd' || *cptr == 'G' || *cptr == 'g') { while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */ cptr++; *width = atoi(cptr); if (tcode >= TCOMPLEX) *width = (2 * (*width)) + 3; } } if (*width == 0) { /* no valid TDISPn keyword; use TFORMn instead */ ffkeyn("TFORM", colnum, keyname, status); ffgkys(fptr, keyname, dispfmt, NULL, status); /* check if column is scaled */ ffkeyn("TSCAL", colnum, keyname, status); tstatus = 0; scaled = 0; if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0) { if (tscale != 1.0) scaled = 1; /* yes, this is a scaled column */ } if (scaled && tcode <= TSHORT) { /* scaled short integer col == float; default format is 14.6G */ *width = 14; } else if (scaled && tcode == TLONG) { /* scaled long integer col == double; default format is 23.15G */ *width = 23; } else if (scaled && tcode == TLONGLONG) { /* scaled long long integer col == double; default format is 23.15G */ *width = 23; } else { ffghdt(fptr, &hdutype, status); /* get type of table */ if (hdutype == ASCII_TBL) { /* parse TFORMn get the display width */ cptr = dispfmt; while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */ cptr++; *width = atoi(cptr); } else { /* this is a binary table */ if (tcode == TBIT) /* 'X' */ *width = 8; else if (tcode == TBYTE) /* 'B' */ *width = 4; else if (tcode == TSHORT) /* 'I' */ *width = 6; else if (tcode == TLONG) /* 'J' */ *width = 11; else if (tcode == TLONGLONG) /* 'K' */ *width = 20; else if (tcode == TFLOAT) /* 'E' */ *width = 14; else if (tcode == TDOUBLE) /* 'D' */ *width = 23; else if (tcode == TCOMPLEX) /* 'C' */ *width = 31; else if (tcode == TDBLCOMPLEX) /* 'M' */ *width = 49; else if (tcode == TLOGICAL) /* 'L' */ *width = 1; else if (tcode == TSTRING) /* 'A' */ { int typecode; long int repeat = 0, rwidth = 0; int gstatus = 0; /* Deal with possible vector string with repeat / width by parsing the TFORM=rAw keyword */ if (ffgtcl(fptr, colnum, &typecode, &repeat, &rwidth, &gstatus) == 0 && rwidth >= 1 && rwidth < repeat) { *width = rwidth; } else { /* Hmmm, we couldn't parse the TFORM keyword by standard, so just do simple parsing */ cptr = dispfmt; while(!isdigit((int) *cptr) && *cptr != '\0') cptr++; *width = atoi(cptr); } if (*width < 1) *width = 1; /* default is at least 1 column */ } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgcls2 ( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of strings to read */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ char *nulval, /* I - value for null pixels if nultyp = 1 */ char **array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of string values from a column in the current FITS HDU. */ { double dtemp; long nullen; int tcode, maxelem, hdutype, nulcheck; long twidth, incre; long ii, jj, ntodo; LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next; double scale, zero; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ tcolumn *colptr; double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ char *buffer, *arrayptr; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (colnum < 1 || colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d", colnum); ffpmsg(message); return(*status = BAD_COL_NUM); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode == -TSTRING) /* variable length column in a binary table? */ { /* only read a single string; ignore value of firstelem */ if (ffgcprll( fptr, colnum, firstrow, 1, 1, 0, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); remain = 1; twidth = (long) repeat; } else if (tcode == TSTRING) { if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); /* if string length is greater than a FITS block (2880 char) then must */ /* only read 1 string at a time, to force reading by ffgbyt instead of */ /* ffgbytoff (ffgbytoff can't handle this case) */ if (twidth > IOBUFLEN) { maxelem = 1; incre = twidth; repeat = 1; } remain = nelem; } else return(*status = NOT_ASCII_COL); nullen = strlen(snull); /* length of the undefined pixel string */ if (nullen == 0) nullen = 1; /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (nultyp == 1 && nulval && nulval[0] == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (snull[0] == ASCII_NULL_UNDEFINED) nulcheck = 0; /* null value string in ASCII table not defined */ else if (nullen > twidth) nulcheck = 0; /* null value string is longer than width of column */ /* thus impossible for any column elements to = null */ /*---------------------------------------------------------------------*/ /* Now read the strings one at a time from the FITS column. */ /*---------------------------------------------------------------------*/ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to process at one time to the number that will fit in the buffer space or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre); ffmbyt(fptr, readptr, REPORT_EOF, status); /* move to read position */ /* read the array of strings from the FITS file into the buffer */ if (incre == twidth) ffgbyt(fptr, ntodo * twidth, cbuff, status); else ffgbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status); /* copy from the buffer into the user's array of strings */ /* work backwards from last char of last string to 1st char of 1st */ buffer = ((char *) cbuff) + (ntodo * twidth) - 1; for (ii = (long) (next + ntodo - 1); ii >= next; ii--) { arrayptr = array[ii] + twidth - 1; for (jj = twidth - 1; jj > 0; jj--) /* ignore trailing blanks */ { if (*buffer == ' ') { buffer--; arrayptr--; } else break; } *(arrayptr + 1) = 0; /* write the string terminator */ for (; jj >= 0; jj--) /* copy the string itself */ { *arrayptr = *buffer; buffer--; arrayptr--; } /* check if null value is defined, and if the */ /* column string is identical to the null string */ if (nulcheck && !strncmp(snull, array[ii], nullen) ) { *anynul = 1; /* this is a null value */ if (nultyp == 1) { if (nulval) strcpy(array[ii], nulval); else strcpy(array[ii], " "); } else nularray[ii] = 1; } } if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f of data array (ffpcls).", dtemp+1., dtemp+ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ next += ntodo; remain -= ntodo; if (remain) { elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ return(*status); } cfitsio-4.3.1/f77.inc0000644000225700000360000000152513472024437013554 0ustar cagordonlheaC Codes for FITS extension types integer IMAGE_HDU, ASCII_TBL, BINARY_TBL parameter ( & IMAGE_HDU = 0, & ASCII_TBL = 1, & BINARY_TBL = 2 ) C Codes for FITS table data types integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX parameter ( & TBIT = 1, & TBYTE = 11, & TLOGICAL = 14, & TSTRING = 16, & TSHORT = 21, & TINT = 31, & TFLOAT = 42, & TDOUBLE = 82, & TCOMPLEX = 83, & TDBLCOMPLEX = 163 ) C Codes for iterator column types integer InputCol, InputOutputCol, OutputCol parameter ( & InputCol = 0, & InputOutputCol = 1, & OutputCol = 2 ) cfitsio-4.3.1/getcol.c0000644000225700000360000013117214335036354014101 0ustar cagordonlhea /* This file, getcol.c, contains routines that read data elements from */ /* a FITS image or table. There are generic datatype routines. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgpxv( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ long *firstpix, /* I - coord of first pixel to read (1s based) */ LONGLONG nelem, /* I - number of values to read */ void *nulval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { LONGLONG tfirstpix[99]; int naxis, ii; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); for (ii=0; ii < naxis; ii++) tfirstpix[ii] = firstpix[ii]; ffgpxvll(fptr, datatype, tfirstpix, nelem, nulval, array, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpxvll( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG *firstpix, /* I - coord of first pixel to read (1s based) */ LONGLONG nelem, /* I - number of values to read */ void *nulval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { int naxis, ii; char cdummy; int nullcheck = 1; LONGLONG naxes[9], trc[9]= {1,1,1,1,1,1,1,1,1}; long inc[9]= {1,1,1,1,1,1,1,1,1}; LONGLONG dimsize = 1, firstelem; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgiszll(fptr, 9, naxes, status); if (naxis == 0 || naxes[0] == 0) { *status = BAD_DIMEN; return(*status); } /* calculate the position of the first element in the array */ firstelem = 0; for (ii=0; ii < naxis; ii++) { firstelem += ((firstpix[ii] - 1) * dimsize); dimsize *= naxes[ii]; trc[ii] = firstpix[ii]; } firstelem++; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ /* test for special case of reading an integral number of */ /* rows in a 2D or 3D image (which includes reading the whole image */ if (naxis > 1 && naxis < 4 && firstpix[0] == 1 && (nelem / naxes[0]) * naxes[0] == nelem) { /* calculate coordinate of last pixel */ trc[0] = naxes[0]; /* reading whole rows */ trc[1] = firstpix[1] + (nelem / naxes[0] - 1); while (trc[1] > naxes[1]) { trc[1] = trc[1] - naxes[1]; trc[2] = trc[2] + 1; /* increment to next plane of cube */ } fits_read_compressed_img(fptr, datatype, firstpix, trc, inc, 1, nulval, array, NULL, anynul, status); } else { fits_read_compressed_pixels(fptr, datatype, firstelem, nelem, nullcheck, nulval, array, NULL, anynul, status); } return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (datatype == TBYTE) { if (nulval == 0) ffgclb(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (unsigned char *) array, &cdummy, anynul, status); else ffgclb(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned char *) nulval, (unsigned char *) array, &cdummy, anynul, status); } else if (datatype == TSBYTE) { if (nulval == 0) ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (signed char *) array, &cdummy, anynul, status); else ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 1, *(signed char *) nulval, (signed char *) array, &cdummy, anynul, status); } else if (datatype == TUSHORT) { if (nulval == 0) ffgclui(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (unsigned short *) array, &cdummy, anynul, status); else ffgclui(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned short *) nulval, (unsigned short *) array, &cdummy, anynul, status); } else if (datatype == TSHORT) { if (nulval == 0) ffgcli(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (short *) array, &cdummy, anynul, status); else ffgcli(fptr, 2, 1, firstelem, nelem, 1, 1, *(short *) nulval, (short *) array, &cdummy, anynul, status); } else if (datatype == TUINT) { if (nulval == 0) ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (unsigned int *) array, &cdummy, anynul, status); else ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned int *) nulval, (unsigned int *) array, &cdummy, anynul, status); } else if (datatype == TINT) { if (nulval == 0) ffgclk(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (int *) array, &cdummy, anynul, status); else ffgclk(fptr, 2, 1, firstelem, nelem, 1, 1, *(int *) nulval, (int *) array, &cdummy, anynul, status); } else if (datatype == TULONG) { if (nulval == 0) ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (unsigned long *) array, &cdummy, anynul, status); else ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned long *) nulval, (unsigned long *) array, &cdummy, anynul, status); } else if (datatype == TLONG) { if (nulval == 0) ffgclj(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (long *) array, &cdummy, anynul, status); else ffgclj(fptr, 2, 1, firstelem, nelem, 1, 1, *(long *) nulval, (long *) array, &cdummy, anynul, status); } else if (datatype == TULONGLONG) { if (nulval == 0) ffgclujj(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (ULONGLONG *) array, &cdummy, anynul, status); else ffgclujj(fptr, 2, 1, firstelem, nelem, 1, 1, *(ULONGLONG *) nulval, (ULONGLONG *) array, &cdummy, anynul, status); } else if (datatype == TLONGLONG) { if (nulval == 0) ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (LONGLONG *) array, &cdummy, anynul, status); else ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 1, *(LONGLONG *) nulval, (LONGLONG *) array, &cdummy, anynul, status); } else if (datatype == TFLOAT) { if (nulval == 0) ffgcle(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (float *) array, &cdummy, anynul, status); else ffgcle(fptr, 2, 1, firstelem, nelem, 1, 1, *(float *) nulval, (float *) array, &cdummy, anynul, status); } else if (datatype == TDOUBLE) { if (nulval == 0) ffgcld(fptr, 2, 1, firstelem, nelem, 1, 1, 0, (double *) array, &cdummy, anynul, status); else ffgcld(fptr, 2, 1, firstelem, nelem, 1, 1, *(double *) nulval, (double *) array, &cdummy, anynul, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgpxf( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ long *firstpix, /* I - coord of first pixel to read (1s based) */ LONGLONG nelem, /* I - number of values to read */ void *array, /* O - array of values that are returned */ char *nullarray, /* O - returned array of null value flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). The nullarray values will = 1 if the corresponding array value is null. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { LONGLONG tfirstpix[99]; int naxis, ii; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); for (ii=0; ii < naxis; ii++) tfirstpix[ii] = firstpix[ii]; ffgpxfll(fptr, datatype, tfirstpix, nelem, array, nullarray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpxfll( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG *firstpix, /* I - coord of first pixel to read (1s based) */ LONGLONG nelem, /* I - number of values to read */ void *array, /* O - array of values that are returned */ char *nullarray, /* O - returned array of null value flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). The nullarray values will = 1 if the corresponding array value is null. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { int naxis, ii; int nullcheck = 2; LONGLONG naxes[9]; LONGLONG dimsize = 1, firstelem; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgiszll(fptr, 9, naxes, status); /* calculate the position of the first element in the array */ firstelem = 0; for (ii=0; ii < naxis; ii++) { firstelem += ((firstpix[ii] - 1) * dimsize); dimsize *= naxes[ii]; } firstelem++; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_read_compressed_pixels(fptr, datatype, firstelem, nelem, nullcheck, NULL, array, nullarray, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (datatype == TBYTE) { ffgclb(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (unsigned char *) array, nullarray, anynul, status); } else if (datatype == TSBYTE) { ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (signed char *) array, nullarray, anynul, status); } else if (datatype == TUSHORT) { ffgclui(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (unsigned short *) array, nullarray, anynul, status); } else if (datatype == TSHORT) { ffgcli(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (short *) array, nullarray, anynul, status); } else if (datatype == TUINT) { ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (unsigned int *) array, nullarray, anynul, status); } else if (datatype == TINT) { ffgclk(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (int *) array, nullarray, anynul, status); } else if (datatype == TULONG) { ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (unsigned long *) array, nullarray, anynul, status); } else if (datatype == TLONG) { ffgclj(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (long *) array, nullarray, anynul, status); } else if (datatype == TULONGLONG) { ffgclujj(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (ULONGLONG *) array, nullarray, anynul, status); } else if (datatype == TLONGLONG) { ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (LONGLONG *) array, nullarray, anynul, status); } else if (datatype == TFLOAT) { ffgcle(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (float *) array, nullarray, anynul, status); } else if (datatype == TDOUBLE) { ffgcld(fptr, 2, 1, firstelem, nelem, 1, 2, 0, (double *) array, nullarray, anynul, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgsv( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc , /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dim. */ void *nulval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an section of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { int naxis, ii; long naxes[9]; LONGLONG nelem = 1; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgisz(fptr, 9, naxes, status); /* test for the important special case where we are reading the whole image */ /* this is only useful for images that are not tile-compressed */ if (!fits_is_compressed_image(fptr, status)) { for (ii = 0; ii < naxis; ii++) { if (inc[ii] != 1 || blc[ii] !=1 || trc[ii] != naxes[ii]) break; nelem = nelem * naxes[ii]; } if (ii == naxis) { /* read the whole image more efficiently */ ffgpxv(fptr, datatype, blc, nelem, nulval, array, anynul, status); return(*status); } } if (datatype == TBYTE) { if (nulval == 0) ffgsvb(fptr, 1, naxis, naxes, blc, trc, inc, 0, (unsigned char *) array, anynul, status); else ffgsvb(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned char *) nulval, (unsigned char *) array, anynul, status); } else if (datatype == TSBYTE) { if (nulval == 0) ffgsvsb(fptr, 1, naxis, naxes, blc, trc, inc, 0, (signed char *) array, anynul, status); else ffgsvsb(fptr, 1, naxis, naxes, blc, trc, inc, *(signed char *) nulval, (signed char *) array, anynul, status); } else if (datatype == TUSHORT) { if (nulval == 0) ffgsvui(fptr, 1, naxis, naxes, blc, trc, inc, 0, (unsigned short *) array, anynul, status); else ffgsvui(fptr, 1, naxis, naxes,blc, trc, inc, *(unsigned short *) nulval, (unsigned short *) array, anynul, status); } else if (datatype == TSHORT) { if (nulval == 0) ffgsvi(fptr, 1, naxis, naxes, blc, trc, inc, 0, (short *) array, anynul, status); else ffgsvi(fptr, 1, naxis, naxes, blc, trc, inc, *(short *) nulval, (short *) array, anynul, status); } else if (datatype == TUINT) { if (nulval == 0) ffgsvuk(fptr, 1, naxis, naxes, blc, trc, inc, 0, (unsigned int *) array, anynul, status); else ffgsvuk(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned int *) nulval, (unsigned int *) array, anynul, status); } else if (datatype == TINT) { if (nulval == 0) ffgsvk(fptr, 1, naxis, naxes, blc, trc, inc, 0, (int *) array, anynul, status); else ffgsvk(fptr, 1, naxis, naxes, blc, trc, inc, *(int *) nulval, (int *) array, anynul, status); } else if (datatype == TULONG) { if (nulval == 0) ffgsvuj(fptr, 1, naxis, naxes, blc, trc, inc, 0, (unsigned long *) array, anynul, status); else ffgsvuj(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned long *) nulval, (unsigned long *) array, anynul, status); } else if (datatype == TLONG) { if (nulval == 0) ffgsvj(fptr, 1, naxis, naxes, blc, trc, inc, 0, (long *) array, anynul, status); else ffgsvj(fptr, 1, naxis, naxes, blc, trc, inc, *(long *) nulval, (long *) array, anynul, status); } else if (datatype == TULONGLONG) { if (nulval == 0) ffgsvujj(fptr, 1, naxis, naxes, blc, trc, inc, 0, (ULONGLONG *) array, anynul, status); else ffgsvujj(fptr, 1, naxis, naxes, blc, trc, inc, *(ULONGLONG *) nulval, (ULONGLONG *) array, anynul, status); } else if (datatype == TLONGLONG) { if (nulval == 0) ffgsvjj(fptr, 1, naxis, naxes, blc, trc, inc, 0, (LONGLONG *) array, anynul, status); else ffgsvjj(fptr, 1, naxis, naxes, blc, trc, inc, *(LONGLONG *) nulval, (LONGLONG *) array, anynul, status); } else if (datatype == TFLOAT) { if (nulval == 0) ffgsve(fptr, 1, naxis, naxes, blc, trc, inc, 0, (float *) array, anynul, status); else ffgsve(fptr, 1, naxis, naxes, blc, trc, inc, *(float *) nulval, (float *) array, anynul, status); } else if (datatype == TDOUBLE) { if (nulval == 0) ffgsvd(fptr, 1, naxis, naxes, blc, trc, inc, 0, (double *) array, anynul, status); else ffgsvd(fptr, 1, naxis, naxes, blc, trc, inc, *(double *) nulval, (double *) array, anynul, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgpv( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ void *nulval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (datatype == TBYTE) { if (nulval == 0) ffgpvb(fptr, 1, firstelem, nelem, 0, (unsigned char *) array, anynul, status); else ffgpvb(fptr, 1, firstelem, nelem, *(unsigned char *) nulval, (unsigned char *) array, anynul, status); } else if (datatype == TSBYTE) { if (nulval == 0) ffgpvsb(fptr, 1, firstelem, nelem, 0, (signed char *) array, anynul, status); else ffgpvsb(fptr, 1, firstelem, nelem, *(signed char *) nulval, (signed char *) array, anynul, status); } else if (datatype == TUSHORT) { if (nulval == 0) ffgpvui(fptr, 1, firstelem, nelem, 0, (unsigned short *) array, anynul, status); else ffgpvui(fptr, 1, firstelem, nelem, *(unsigned short *) nulval, (unsigned short *) array, anynul, status); } else if (datatype == TSHORT) { if (nulval == 0) ffgpvi(fptr, 1, firstelem, nelem, 0, (short *) array, anynul, status); else ffgpvi(fptr, 1, firstelem, nelem, *(short *) nulval, (short *) array, anynul, status); } else if (datatype == TUINT) { if (nulval == 0) ffgpvuk(fptr, 1, firstelem, nelem, 0, (unsigned int *) array, anynul, status); else ffgpvuk(fptr, 1, firstelem, nelem, *(unsigned int *) nulval, (unsigned int *) array, anynul, status); } else if (datatype == TINT) { if (nulval == 0) ffgpvk(fptr, 1, firstelem, nelem, 0, (int *) array, anynul, status); else ffgpvk(fptr, 1, firstelem, nelem, *(int *) nulval, (int *) array, anynul, status); } else if (datatype == TULONG) { if (nulval == 0) ffgpvuj(fptr, 1, firstelem, nelem, 0, (unsigned long *) array, anynul, status); else ffgpvuj(fptr, 1, firstelem, nelem, *(unsigned long *) nulval, (unsigned long *) array, anynul, status); } else if (datatype == TLONG) { if (nulval == 0) ffgpvj(fptr, 1, firstelem, nelem, 0, (long *) array, anynul, status); else ffgpvj(fptr, 1, firstelem, nelem, *(long *) nulval, (long *) array, anynul, status); } else if (datatype == TULONGLONG) { if (nulval == 0) ffgpvujj(fptr, 1, firstelem, nelem, 0, (ULONGLONG *) array, anynul, status); else ffgpvujj(fptr, 1, firstelem, nelem, *(ULONGLONG *) nulval, (ULONGLONG *) array, anynul, status); } else if (datatype == TLONGLONG) { if (nulval == 0) ffgpvjj(fptr, 1, firstelem, nelem, 0, (LONGLONG *) array, anynul, status); else ffgpvjj(fptr, 1, firstelem, nelem, *(LONGLONG *) nulval, (LONGLONG *) array, anynul, status); } else if (datatype == TFLOAT) { if (nulval == 0) ffgpve(fptr, 1, firstelem, nelem, 0, (float *) array, anynul, status); else ffgpve(fptr, 1, firstelem, nelem, *(float *) nulval, (float *) array, anynul, status); } else if (datatype == TDOUBLE) { if (nulval == 0) ffgpvd(fptr, 1, firstelem, nelem, 0, (double *) array, anynul, status); else { ffgpvd(fptr, 1, firstelem, nelem, *(double *) nulval, (double *) array, anynul, status); } } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgpf( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ void *array, /* O - array of values that are returned */ char *nullarray, /* O - array of null value flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). The nullarray values will = 1 if the corresponding array value is null. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (datatype == TBYTE) { ffgpfb(fptr, 1, firstelem, nelem, (unsigned char *) array, nullarray, anynul, status); } else if (datatype == TSBYTE) { ffgpfsb(fptr, 1, firstelem, nelem, (signed char *) array, nullarray, anynul, status); } else if (datatype == TUSHORT) { ffgpfui(fptr, 1, firstelem, nelem, (unsigned short *) array, nullarray, anynul, status); } else if (datatype == TSHORT) { ffgpfi(fptr, 1, firstelem, nelem, (short *) array, nullarray, anynul, status); } else if (datatype == TUINT) { ffgpfuk(fptr, 1, firstelem, nelem, (unsigned int *) array, nullarray, anynul, status); } else if (datatype == TINT) { ffgpfk(fptr, 1, firstelem, nelem, (int *) array, nullarray, anynul, status); } else if (datatype == TULONG) { ffgpfuj(fptr, 1, firstelem, nelem, (unsigned long *) array, nullarray, anynul, status); } else if (datatype == TLONG) { ffgpfj(fptr, 1, firstelem, nelem, (long *) array, nullarray, anynul, status); } else if (datatype == TULONGLONG) { ffgpfujj(fptr, 1, firstelem, nelem, (ULONGLONG *) array, nullarray, anynul, status); } else if (datatype == TLONGLONG) { ffgpfjj(fptr, 1, firstelem, nelem, (LONGLONG *) array, nullarray, anynul, status); } else if (datatype == TFLOAT) { ffgpfe(fptr, 1, firstelem, nelem, (float *) array, nullarray, anynul, status); } else if (datatype == TDOUBLE) { ffgpfd(fptr, 1, firstelem, nelem, (double *) array, nullarray, anynul, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgcv( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ void *nulval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a table column. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of true if any pixels are undefined. */ { char cdummy[2]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (datatype == TBIT) { ffgcx(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status); } else if (datatype == TBYTE) { if (nulval == 0) ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (unsigned char *) array, cdummy, anynul, status); else ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(unsigned char *) nulval, (unsigned char *) array, cdummy, anynul, status); } else if (datatype == TSBYTE) { if (nulval == 0) ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (signed char *) array, cdummy, anynul, status); else ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(signed char *) nulval, (signed char *) array, cdummy, anynul, status); } else if (datatype == TUSHORT) { if (nulval == 0) ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (unsigned short *) array, cdummy, anynul, status); else ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(unsigned short *) nulval, (unsigned short *) array, cdummy, anynul, status); } else if (datatype == TSHORT) { if (nulval == 0) ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (short *) array, cdummy, anynul, status); else ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(short *) nulval, (short *) array, cdummy, anynul, status); } else if (datatype == TUINT) { if (nulval == 0) ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (unsigned int *) array, cdummy, anynul, status); else ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(unsigned int *) nulval, (unsigned int *) array, cdummy, anynul, status); } else if (datatype == TINT) { if (nulval == 0) ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (int *) array, cdummy, anynul, status); else ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(int *) nulval, (int *) array, cdummy, anynul, status); } else if (datatype == TULONG) { if (nulval == 0) ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (unsigned long *) array, cdummy, anynul, status); else ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(unsigned long *) nulval, (unsigned long *) array, cdummy, anynul, status); } else if (datatype == TLONG) { if (nulval == 0) ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (long *) array, cdummy, anynul, status); else ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(long *) nulval, (long *) array, cdummy, anynul, status); } else if (datatype == TULONGLONG) { if (nulval == 0) ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (ULONGLONG *) array, cdummy, anynul, status); else ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(ULONGLONG *) nulval, (ULONGLONG *) array, cdummy, anynul, status); } else if (datatype == TLONGLONG) { if (nulval == 0) ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0, (LONGLONG *) array, cdummy, anynul, status); else ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(LONGLONG *) nulval, (LONGLONG *) array, cdummy, anynul, status); } else if (datatype == TFLOAT) { if (nulval == 0) ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0., (float *) array, cdummy, anynul, status); else ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(float *) nulval,(float *) array, cdummy, anynul, status); } else if (datatype == TDOUBLE) { if (nulval == 0) ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0., (double *) array, cdummy, anynul, status); else ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(double *) nulval, (double *) array, cdummy, anynul, status); } else if (datatype == TCOMPLEX) { if (nulval == 0) ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 1, 1, 0., (float *) array, cdummy, anynul, status); else ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 1, 1, *(float *) nulval, (float *) array, cdummy, anynul, status); } else if (datatype == TDBLCOMPLEX) { if (nulval == 0) ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 1, 1, 0., (double *) array, cdummy, anynul, status); else ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 1, 1, *(double *) nulval, (double *) array, cdummy, anynul, status); } else if (datatype == TLOGICAL) { if (nulval == 0) ffgcll(fptr, colnum, firstrow, firstelem, nelem, 1, 0, (char *) array, cdummy, anynul, status); else ffgcll(fptr, colnum, firstrow, firstelem, nelem, 1, *(char *) nulval, (char *) array, cdummy, anynul, status); } else if (datatype == TSTRING) { if (nulval == 0) { cdummy[0] = '\0'; ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, cdummy, (char **) array, cdummy, anynul, status); } else ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, (char *) nulval, (char **) array, cdummy, anynul, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgcvn( fitsfile *fptr, /* I - FITS file pointer */ int ncols, /* I - number of columns to read */ int *datatype, /* I - datatypes of the values */ int *colnum, /* I - columns numbers to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG nrows, /* I - number of rows to read */ void **nulval, /* I - array of pointers to values for undefined pixels */ void **array, /* O - array of pointers to values that are returned */ int *anynul, /* O - anynul[i] set to 1 if any values in column i are null; else 0 */ int *status) /* IO - error status */ /* Read arrays of values from NCOLS table columns. This is an optimization to read all columns in one pass through the table. The datatypes of the input arrays are defined by the 3rd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements for column i will be set equal to *(nulval[i]), unless nulval[i]=0 in which case no checking for undefined values will be performed. anynul[i] is returned with a value of true if any pixels in column i are undefined. */ { LONGLONG ntotrows, ndone, nread, currow; long nrowbuf; LONGLONG *repeats = 0; size_t sizes[255] = {0}; int icol; sizes[TBYTE] = sizes[TSBYTE] = sizes[TLOGICAL] = sizeof(char); sizes[TUSHORT] = sizes[TSHORT] = sizeof(short int); sizes[TINT] = sizes[TUINT] = sizeof(int); sizes[TLONG] = sizes[TULONG] = sizeof(long int); sizes[TLONGLONG] = sizes[TULONGLONG] = sizeof(LONGLONG); sizes[TFLOAT] = sizeof(float); sizes[TDOUBLE] = sizeof(double); sizes[TDBLCOMPLEX] = 2*sizeof(double); if (*status > 0) return(*status); if (ncols <= 0) return (*status=0); repeats = malloc(sizeof(LONGLONG)*ncols); if (repeats == 0) return (*status=MEMORY_ALLOCATION); fits_get_num_rowsll(fptr, &ntotrows, status); fits_get_rowsize(fptr, &nrowbuf, status); /* Retrieve column repeats */ for (icol = 0; (icol < ncols) && (icol < 1000); icol++) { int typecode; LONGLONG repeat, width; fits_get_coltypell(fptr, colnum[icol], &typecode, &repeat, &width, status); repeats[icol] = repeat; if (datatype[icol] == TBIT || datatype[icol] == TSTRING || sizes[datatype[icol]] == 0) { ffpmsg("Cannot read from TBIT or TSTRING datatypes (ffgcvn)"); *status = BAD_DATATYPE; } if (typecode < 0) { ffpmsg("Cannot read from variable-length data (ffgcvn)"); *status = BAD_DIMEN; } if (*status) break; } if (*status) { free(repeats); return *status; } /* Optimize for 1 column */ if (ncols == 1) { fits_read_col(fptr, datatype[0], colnum[0], firstrow, 1, nrows*repeats[0], nulval[0], array[0], anynul ? &(anynul[0]) : 0, status); free(repeats); return *status; } /* Scan through file, in chunks of nrowbuf */ currow = firstrow; ndone = 0; while (ndone < nrows) { int icol; nread = (nrows-ndone); /* Number of rows to read (not elements) */ if (nread > nrowbuf) nread = nrowbuf; for (icol=0; icol 0) /* inherit input status value if > 0 */ return(*status); if (datatype == TBIT) { ffgcx(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status); } else if (datatype == TBYTE) { ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (unsigned char ) nulval, (unsigned char *) array, nullarray, anynul, status); } else if (datatype == TSBYTE) { ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (signed char ) nulval, (signed char *) array, nullarray, anynul, status); } else if (datatype == TUSHORT) { ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (unsigned short ) nulval, (unsigned short *) array, nullarray, anynul, status); } else if (datatype == TSHORT) { ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (short ) nulval, (short *) array, nullarray, anynul, status); } else if (datatype == TUINT) { ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (unsigned int ) nulval, (unsigned int *) array, nullarray, anynul, status); } else if (datatype == TINT) { ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (int ) nulval, (int *) array, nullarray, anynul, status); } else if (datatype == TULONG) { ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (unsigned long ) nulval, (unsigned long *) array, nullarray, anynul, status); } else if (datatype == TLONG) { ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (long ) nulval, (long *) array, nullarray, anynul, status); } else if (datatype == TULONGLONG) { ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (ULONGLONG ) nulval, (ULONGLONG *) array, nullarray, anynul, status); } else if (datatype == TLONGLONG) { ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (LONGLONG ) nulval, (LONGLONG *) array, nullarray, anynul, status); } else if (datatype == TFLOAT) { ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (float ) nulval,(float *) array, nullarray, anynul, status); } else if (datatype == TDOUBLE) { ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 2, nulval, (double *) array, nullarray, anynul, status); } else if (datatype == TCOMPLEX) { ffgcfc(fptr, colnum, firstrow, firstelem, nelem, (float *) array, nullarray, anynul, status); } else if (datatype == TDBLCOMPLEX) { ffgcfm(fptr, colnum, firstrow, firstelem, nelem, (double *) array, nullarray, anynul, status); } else if (datatype == TLOGICAL) { ffgcll(fptr, colnum, firstrow, firstelem, nelem, 2, (char ) nulval, (char *) array, nullarray, anynul, status); } else if (datatype == TSTRING) { ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, cnulval, (char **) array, nullarray, anynul, status); } else *status = BAD_DATATYPE; return(*status); } cfitsio-4.3.1/eval_defs.h0000644000225700000360000001360114335036354014555 0ustar cagordonlhea#include #include #include #include #if defined(__sgi) || defined(__hpux) #include #endif #ifdef sparc #include #endif #include "fitsio2.h" #define MAXDIMS 5 #define MAXSUBS 10 #define MAXVARNAME 80 #define CONST_OP -1000 #define pERROR -1 #define MAX_STRLEN 256 #define MAX_STRLEN_S "255" typedef struct ParseData_struct ParseData; typedef void* yyscan_t; #ifndef FFBISON #include "eval_tab.h" #endif typedef struct { char name[MAXVARNAME+1]; int type; long nelem; int naxis; long naxes[MAXDIMS]; char *undef; void *data; } DataInfo; typedef struct { long nelem; int naxis; long naxes[MAXDIMS]; char *undef; union { double dbl; long lng; char log; char str[MAX_STRLEN]; double *dblptr; long *lngptr; char *logptr; char **strptr; void *ptr; } data; } lval; typedef struct Node { int operation; void (*DoOp)(ParseData *, struct Node *this); int nSubNodes; int SubNodes[MAXSUBS]; int type; lval value; } Node; struct ParseData_struct { fitsfile *def_fptr; int (*getData)( ParseData *, char *dataName, void *dataValue ); int (*loadData)( ParseData *, int varNum, long fRow, long nRows, void *data, char *undef ); int compressed; int timeCol; int parCol; int valCol; char *expr; int index; int is_eobuf; Node *Nodes; int nNodes; int nNodesAlloc; int resultNode; long firstRow; long nRows; int nCols; long nElements; int nAxis; long nAxes[MAXDIMS]; iteratorCol *colData; DataInfo *varData; PixelFilter *pixFilter; long firstDataRow; long nDataRows; long totalRows; long nPrevDataRows; int datatype; int hdutype; int status; }; typedef enum { rnd_fct = 1001, sum_fct, nelem_fct, sin_fct, cos_fct, tan_fct, asin_fct, acos_fct, atan_fct, sinh_fct, cosh_fct, tanh_fct, exp_fct, log_fct, log10_fct, sqrt_fct, abs_fct, atan2_fct, ceil_fct, floor_fct, round_fct, min1_fct, min2_fct, max1_fct, max2_fct, near_fct, circle_fct, box_fct, elps_fct, isnull_fct, defnull_fct, gtifilt_fct, regfilt_fct, ifthenelse_fct, row_fct, null_fct, median_fct, average_fct, stddev_fct, nonnull_fct, angsep_fct, gasrnd_fct, poirnd_fct, strmid_fct, strpos_fct, setnull_fct, gtiover_fct, gtifind_fct, elemnum_fct, axiselem_fct, array_fct } funcOp; typedef struct parseInfo_struct parseInfo; struct ParseStatusVariables { /* These variables were 'static' in fits_parse_workfn() */ void *Data, *Null; int datasize; long lastRow, repeat, resDataSize; LONGLONG jnull; parseInfo *userInfo; long zeros[4]; }; struct parseInfo_struct { int datatype; /* Data type to cast parse results into for user */ void *dataPtr; /* Pointer to array of results, NULL if to use iterCol */ void *nullPtr; /* Pointer to nulval, use zero if NULL */ long maxRows; /* Max No. of rows to process, -1=all, 0=1 iteration */ int anyNull; /* Flag indicating at least 1 undef value encountered */ ParseData *parseData; /* Pointer to parser configuration */ struct ParseStatusVariables parseVariables; }; #ifdef __cplusplus extern "C" { #endif /* Not sure why this is needed but it is */ #define YYSTYPE FITS_PARSER_YYSTYPE /* How ParseData is accessed from the lexer, i.e. by yyextra */ #define YY_EXTRA_TYPE ParseData * int fits_parser_yyparse(yyscan_t yyscaner, ParseData *lParse); int fits_parser_yylex(FITS_PARSER_YYSTYPE *, yyscan_t yyscanner); void fits_parser_yyrestart(FILE*, yyscan_t yyscanner); int fits_parser_yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); int fits_parser_yylex_destroy (yyscan_t scanner); void Evaluate_Parser( ParseData *lParse, long firstRow, long nRows ); int fits_parser_allocateCol( ParseData *lParse, int nCol, int *status ); int fits_parser_set_temporary_col(ParseData *lParse, parseInfo *Info, long int nrows, void *nulval, int *status); #ifdef __cplusplus } #endif cfitsio-4.3.1/fits_hdecompress.c0000644000225700000360000017352013472024437016170 0ustar cagordonlhea/* ######################################################################### These routines to apply the H-compress decompression algorithm to a 2-D Fits image were written by R. White at the STScI and were obtained from the STScI at http://www.stsci.edu/software/hcompress.html This source file is a concatination of the following sources files in the original distribution hinv.c hsmooth.c undigitize.c decode.c dodecode.c qtree_decode.c qread.c bit_input.c The following modifications have been made to the original code: - commented out redundant "include" statements - added the nextchar global variable - changed all the 'extern' declarations to 'static', since all the routines are in the same source file - changed the first parameter in decode (and in lower level routines from a file stream to a char array - modified the myread routine, and lower level byte reading routines, to copy the input bytes to a char array, instead of reading them from a file stream - changed the function declarations to the more modern ANSI C style - changed calls to printf and perror to call the CFITSIO ffpmsg routine - replace "exit" statements with "return" statements ############################################################################ */ #include #include #include #include #include "fitsio2.h" /* WDP added test to see if min and max are already defined */ #ifndef min #define min(a,b) (((a)<(b))?(a):(b)) #endif #ifndef max #define max(a,b) (((a)>(b))?(a):(b)) #endif static long nextchar; static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale); static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale); static int hinv(int a[], int nx, int ny, int smooth ,int scale); static int hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale); static void undigitize(int a[], int nx, int ny, int scale); static void undigitize64(LONGLONG a[], int nx, int ny, int scale); static void unshuffle(int a[], int n, int n2, int tmp[]); static void unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]); static void hsmooth(int a[], int nxtop, int nytop, int ny, int scale); static void hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale); static void qread(unsigned char *infile,char *a, int n); static int readint(unsigned char *infile); static LONGLONG readlonglong(unsigned char *infile); static int dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]); static int dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]); static int qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes); static int qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes); static void start_inputing_bits(void); static int input_bit(unsigned char *infile); static int input_nbits(unsigned char *infile, int n); /* make input_nybble a separate routine, for added effiency */ /* #define input_nybble(infile) input_nbits(infile,4) */ static int input_nybble(unsigned char *infile); static int input_nnybble(unsigned char *infile, int n, unsigned char *array); static void qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]); static void qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit); static void qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit); static void qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n); static void read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit); static void read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit); static int input_huffman(unsigned char *infile); /* ---------------------------------------------------------------------- */ int fits_hdecompress(unsigned char *input, int smooth, int *a, int *ny, int *nx, int *scale, int *status) { /* decompress the input byte stream using the H-compress algorithm input - input array of compressed bytes a - pre-allocated array to hold the output uncompressed image nx - returned X axis size ny - returned Y axis size NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat; if (*status > 0) return(*status); /* decode the input array */ FFLOCK; /* decode uses the nextchar global variable */ stat = decode(input, a, nx, ny, scale); FFUNLOCK; *status = stat; if (stat) return(*status); /* * Un-Digitize */ undigitize(a, *nx, *ny, *scale); /* * Inverse H-transform */ stat = hinv(a, *nx, *ny, smooth, *scale); *status = stat; return(*status); } /* ---------------------------------------------------------------------- */ int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *ny, int *nx, int *scale, int *status) { /* decompress the input byte stream using the H-compress algorithm input - input array of compressed bytes a - pre-allocated array to hold the output uncompressed image nx - returned X axis size ny - returned Y axis size NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat, *iarray, ii, nval; if (*status > 0) return(*status); /* decode the input array */ FFLOCK; /* decode uses the nextchar global variable */ stat = decode64(input, a, nx, ny, scale); FFUNLOCK; *status = stat; if (stat) return(*status); /* * Un-Digitize */ undigitize64(a, *nx, *ny, *scale); /* * Inverse H-transform */ stat = hinv64(a, *nx, *ny, smooth, *scale); *status = stat; /* pack the I*8 values back into an I*4 array */ iarray = (int *) a; nval = (*nx) * (*ny); for (ii = 0; ii < nval; ii++) iarray[ii] = (int) a[ii]; return(*status); } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* hinv.c Inverse H-transform of NX x NY integer image * * Programmer: R. White Date: 23 July 1993 */ /* ############################################################################ */ static int hinv(int a[], int nx, int ny, int smooth ,int scale) /* int smooth; 0 for no smoothing, else smooth during inversion int scale; used if smoothing is specified */ { int nmax, log2n, i, j, k; int nxtop,nytop,nxf,nyf,c; int oddx,oddy; int shift, bit0, bit1, bit2, mask0, mask1, mask2, prnd0, prnd1, prnd2, nrnd0, nrnd1, nrnd2, lowbit0, lowbit1; int h0, hx, hy, hc; int s10, s00; int *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> 1; prnd1 = bit1 >> 1; prnd2 = bit2 >> 1; nrnd0 = prnd0 - 1; nrnd1 = prnd1 - 1; nrnd2 = prnd2 - 1; /* * round h0 to multiple of bit2 */ a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2; /* * do log2n expansions * * We're indexing a as a 2-D array with dimensions (nx,ny). */ nxtop = 1; nytop = 1; nxf = nx; nyf = ny; c = 1<=0; k--) { /* * this somewhat cryptic code generates the sequence * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n */ c = c>>1; nxtop = nxtop<<1; nytop = nytop<<1; if (nxf <= c) { nxtop -= 1; } else { nxf -= c; } if (nyf <= c) { nytop -= 1; } else { nyf -= c; } /* * double shift and fix nrnd0 (because prnd0=0) on last pass */ if (k == 0) { nrnd0 = 0; shift = 2; } /* * unshuffle in each dimension to interleave coefficients */ for (i = 0; i= 0) ? prnd1 : nrnd1)) & mask1; hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1; hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0; /* * propagate bit0 of hc to hx,hy */ lowbit0 = hc & bit0; hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0); hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0); /* * Propagate bits 0 and 1 of hc,hx,hy to h0. * This could be simplified if we assume h0>0, but then * the inversion would not be lossless for images with * negative pixels. */ lowbit1 = (hc ^ hx ^ hy) & bit1; h0 = (h0 >= 0) ? (h0 + lowbit0 - lowbit1) : (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1))); /* * Divide sums by 2 (4 last time) */ a[s10+1] = (h0 + hx + hy + hc) >> shift; a[s10 ] = (h0 + hx - hy - hc) >> shift; a[s00+1] = (h0 - hx + hy - hc) >> shift; a[s00 ] = (h0 - hx - hy + hc) >> shift; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = a[s00 ]; hx = a[s10 ]; hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1; lowbit1 = hx & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s10 ] = (h0 + hx) >> shift; a[s00 ] = (h0 - hx) >> shift; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = ny*i; for (j = 0; j= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1; lowbit1 = hy & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s00+1] = (h0 + hy) >> shift; a[s00 ] = (h0 - hy) >> shift; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00 ]; a[s00 ] = h0 >> shift; } } /* * divide all the masks and rounding values by 2 */ bit2 = bit1; bit1 = bit0; bit0 = bit0 >> 1; mask1 = mask0; mask0 = mask0 >> 1; prnd1 = prnd0; prnd0 = prnd0 >> 1; nrnd1 = nrnd0; nrnd0 = prnd0 - 1; } free(tmp); return(0); } /* ############################################################################ */ static int hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale) /* int smooth; 0 for no smoothing, else smooth during inversion int scale; used if smoothing is specified */ { int nmax, log2n, i, j, k; int nxtop,nytop,nxf,nyf,c; int oddx,oddy; int shift; LONGLONG mask0, mask1, mask2, prnd0, prnd1, prnd2, bit0, bit1, bit2; LONGLONG nrnd0, nrnd1, nrnd2, lowbit0, lowbit1; LONGLONG h0, hx, hy, hc; int s10, s00; LONGLONG *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> 1; prnd1 = bit1 >> 1; prnd2 = bit2 >> 1; nrnd0 = prnd0 - 1; nrnd1 = prnd1 - 1; nrnd2 = prnd2 - 1; /* * round h0 to multiple of bit2 */ a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2; /* * do log2n expansions * * We're indexing a as a 2-D array with dimensions (nx,ny). */ nxtop = 1; nytop = 1; nxf = nx; nyf = ny; c = 1<=0; k--) { /* * this somewhat cryptic code generates the sequence * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n */ c = c>>1; nxtop = nxtop<<1; nytop = nytop<<1; if (nxf <= c) { nxtop -= 1; } else { nxf -= c; } if (nyf <= c) { nytop -= 1; } else { nyf -= c; } /* * double shift and fix nrnd0 (because prnd0=0) on last pass */ if (k == 0) { nrnd0 = 0; shift = 2; } /* * unshuffle in each dimension to interleave coefficients */ for (i = 0; i= 0) ? prnd1 : nrnd1)) & mask1; hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1; hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0; /* * propagate bit0 of hc to hx,hy */ lowbit0 = hc & bit0; hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0); hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0); /* * Propagate bits 0 and 1 of hc,hx,hy to h0. * This could be simplified if we assume h0>0, but then * the inversion would not be lossless for images with * negative pixels. */ lowbit1 = (hc ^ hx ^ hy) & bit1; h0 = (h0 >= 0) ? (h0 + lowbit0 - lowbit1) : (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1))); /* * Divide sums by 2 (4 last time) */ a[s10+1] = (h0 + hx + hy + hc) >> shift; a[s10 ] = (h0 + hx - hy - hc) >> shift; a[s00+1] = (h0 - hx + hy - hc) >> shift; a[s00 ] = (h0 - hx - hy + hc) >> shift; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = a[s00 ]; hx = a[s10 ]; hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1; lowbit1 = hx & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s10 ] = (h0 + hx) >> shift; a[s00 ] = (h0 - hx) >> shift; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = ny*i; for (j = 0; j= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1; lowbit1 = hy & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s00+1] = (h0 + hy) >> shift; a[s00 ] = (h0 - hy) >> shift; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00 ]; a[s00 ] = h0 >> shift; } } /* * divide all the masks and rounding values by 2 */ bit2 = bit1; bit1 = bit0; bit0 = bit0 >> 1; mask1 = mask0; mask0 = mask0 >> 1; prnd1 = prnd0; prnd0 = prnd0 >> 1; nrnd1 = nrnd0; nrnd0 = prnd0 - 1; } free(tmp); return(0); } /* ############################################################################ */ static void unshuffle(int a[], int n, int n2, int tmp[]) /* int a[]; array to shuffle int n; number of elements to shuffle int n2; second dimension int tmp[]; scratch storage */ { int i; int nhalf; int *p1, *p2, *pt; /* * copy 2nd half of array to tmp */ nhalf = (n+1)>>1; pt = tmp; p1 = &a[n2*nhalf]; /* pointer to a[i] */ for (i=nhalf; i= 0; i--) { *p1 = *p2; p2 -= n2; p1 -= (n2+n2); } /* * now distribute 2nd half of array (in tmp) to odd elements */ pt = tmp; p1 = &a[n2]; /* pointer to a[i] */ for (i=1; i>1; pt = tmp; p1 = &a[n2*nhalf]; /* pointer to a[i] */ for (i=nhalf; i= 0; i--) { *p1 = *p2; p2 -= n2; p1 -= (n2+n2); } /* * now distribute 2nd half of array (in tmp) to odd elements */ pt = tmp; p1 = &a[n2]; /* pointer to a[i] */ for (i=1; i> 1); if (smax <= 0) return; ny2 = ny << 1; /* * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which * only (nxtop,nytop) are used. The coefficients on the edge of the * array are not adjusted (which is why the loops below start at 2 * instead of 0 and end at nxtop-2 instead of nxtop.) */ /* * Adjust x difference hx */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 8. */ s = diff-(a[s10]<<3); s = (s>=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s10] = a[s10]+s; } s00 += 2; s10 += 2; } } /* * Adjust y difference hy */ for (i = 0; i=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s00+1] = a[s00+1]+s; } s00 += 2; s10 += 2; } } /* * Adjust curvature difference hc */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 64. */ s = diff-(a[s10+1]<<6); s = (s>=0) ? (s>>6) : ((s+63)>>6) ; s = max( min(s, smax), -smax); a[s10+1] = a[s10+1]+s; } s00 += 2; s10 += 2; } } } /* ############################################################################ */ static void hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale) /* LONGLONG a[]; array of H-transform coefficients int nxtop,nytop; size of coefficient block to use int ny; actual 1st dimension of array int scale; truncation scale factor that was used */ { int i, j; int ny2, s10, s00; LONGLONG hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2, diff, dmax, dmin, s, smax, m1, m2; /* * Maximum change in coefficients is determined by scale factor. * Since we rounded during division (see digitize.c), the biggest * permitted change is scale/2. */ smax = (scale >> 1); if (smax <= 0) return; ny2 = ny << 1; /* * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which * only (nxtop,nytop) are used. The coefficients on the edge of the * array are not adjusted (which is why the loops below start at 2 * instead of 0 and end at nxtop-2 instead of nxtop.) */ /* * Adjust x difference hx */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 8. */ s = diff-(a[s10]<<3); s = (s>=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s10] = a[s10]+s; } s00 += 2; s10 += 2; } } /* * Adjust y difference hy */ for (i = 0; i=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s00+1] = a[s00+1]+s; } s00 += 2; s10 += 2; } } /* * Adjust curvature difference hc */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 64. */ s = diff-(a[s10+1]<<6); s = (s>=0) ? (s>>6) : ((s+63)>>6) ; s = max( min(s, smax), -smax); a[s10+1] = a[s10+1]+s; } s00 += 2; s10 += 2; } } } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* undigitize.c undigitize H-transform * * Programmer: R. White Date: 9 May 1991 */ /* ############################################################################ */ static void undigitize(int a[], int nx, int ny, int scale) { int *p; /* * multiply by scale */ if (scale <= 1) return; for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale; } /* ############################################################################ */ static void undigitize64(LONGLONG a[], int nx, int ny, int scale) { LONGLONG *p, scale64; /* * multiply by scale */ if (scale <= 1) return; scale64 = (LONGLONG) scale; /* use a 64-bit int for efficiency in the big loop */ for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale64; } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* decode.c read codes from infile and construct array * * Programmer: R. White Date: 2 February 1994 */ static char code_magic[2] = { (char)0xDD, (char)0x99 }; /* ############################################################################ */ static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale) /* char *infile; input file int *a; address of output array [nx][ny] int *nx,*ny; size of output array int *scale; scale factor for digitization */ { LONGLONG sumall; int stat; unsigned char nbitplanes[3]; char tmagic[2]; /* initialize the byte read position to the beginning of the array */; nextchar = 0; /* * File starts either with special 2-byte magic code or with * FITS keyword "SIMPLE =" */ qread(infile, tmagic, sizeof(tmagic)); /* * check for correct magic code value */ if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) { ffpmsg("bad file format"); return(DATA_DECOMPRESSION_ERR); } *nx =readint(infile); /* x size of image */ *ny =readint(infile); /* y size of image */ *scale=readint(infile); /* scale factor for digitization */ /* sum of all pixels */ sumall=readlonglong(infile); /* # bits in quadrants */ qread(infile, (char *) nbitplanes, sizeof(nbitplanes)); stat = dodecode(infile, a, *nx, *ny, nbitplanes); /* * put sum of all pixels back into pixel 0 */ a[0] = (int) sumall; return(stat); } /* ############################################################################ */ static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale) /* char *infile; input file LONGLONG *a; address of output array [nx][ny] int *nx,*ny; size of output array int *scale; scale factor for digitization */ { int stat; LONGLONG sumall; unsigned char nbitplanes[3]; char tmagic[2]; /* initialize the byte read position to the beginning of the array */; nextchar = 0; /* * File starts either with special 2-byte magic code or with * FITS keyword "SIMPLE =" */ qread(infile, tmagic, sizeof(tmagic)); /* * check for correct magic code value */ if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) { ffpmsg("bad file format"); return(DATA_DECOMPRESSION_ERR); } *nx =readint(infile); /* x size of image */ *ny =readint(infile); /* y size of image */ *scale=readint(infile); /* scale factor for digitization */ /* sum of all pixels */ sumall=readlonglong(infile); /* # bits in quadrants */ qread(infile, (char *) nbitplanes, sizeof(nbitplanes)); stat = dodecode64(infile, a, *nx, *ny, nbitplanes); /* * put sum of all pixels back into pixel 0 */ a[0] = sumall; return(stat); } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* dodecode.c Decode stream of characters on infile and return array * * This version encodes the different quadrants separately * * Programmer: R. White Date: 9 May 1991 */ /* ############################################################################ */ static int dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]) /* int a[]; int nx,ny; Array dimensions are [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ { int i, nel, nx2, ny2, stat; nel = nx*ny; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * initialize a to zero */ for (i=0; inqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * Was bitplane was quadtree-coded or written directly? */ b = input_nybble(infile); if(b == 0) { /* * bit map was written directly */ read_bdirect(infile,a,n,nqx,nqy,scratch,bit); } else if (b != 0xf) { ffpmsg("qtree_decode: bad format code"); return(DATA_DECOMPRESSION_ERR); } else { /* * bitmap was quadtree-coded, do log2n expansions * * read first code */ scratch[0] = input_huffman(infile); /* * now do log2n expansions, reading codes from file as necessary */ nx = 1; ny = 1; nfx = nqx; nfy = nqy; c = 1<>1; nx = nx<<1; ny = ny<<1; if (nfx <= c) { nx -= 1; } else { nfx -= c; } if (nfy <= c) { ny -= 1; } else { nfy -= c; } qtree_expand(infile,scratch,nx,ny,scratch); } /* * now copy last set of 4-bit codes to bitplane bit of array a */ qtree_bitins(scratch,nqx,nqy,a,n,bit); } } free(scratch); return(0); } /* ############################################################################ */ static int qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes) /* char *infile; LONGLONG a[]; a is 2-D array with dimensions (n,n) int n; length of full row in a int nqx; partial length of row to decode int nqy; partial length of column (<=n) int nbitplanes; number of bitplanes to decode */ { int log2n, k, bit, b, nqmax; int nx,ny,nfx,nfy,c; int nqx2, nqy2; unsigned char *scratch; /* * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 */ nqmax = (nqx>nqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * Was bitplane was quadtree-coded or written directly? */ b = input_nybble(infile); if(b == 0) { /* * bit map was written directly */ read_bdirect64(infile,a,n,nqx,nqy,scratch,bit); } else if (b != 0xf) { ffpmsg("qtree_decode64: bad format code"); return(DATA_DECOMPRESSION_ERR); } else { /* * bitmap was quadtree-coded, do log2n expansions * * read first code */ scratch[0] = input_huffman(infile); /* * now do log2n expansions, reading codes from file as necessary */ nx = 1; ny = 1; nfx = nqx; nfy = nqy; c = 1<>1; nx = nx<<1; ny = ny<<1; if (nfx <= c) { nx -= 1; } else { nfx -= c; } if (nfy <= c) { ny -= 1; } else { nfy -= c; } qtree_expand(infile,scratch,nx,ny,scratch); } /* * now copy last set of 4-bit codes to bitplane bit of array a */ qtree_bitins64(scratch,nqx,nqy,a,n,bit); } } free(scratch); return(0); } /* ############################################################################ */ /* * do one quadtree expansion step on array a[(nqx+1)/2,(nqy+1)/2] * results put into b[nqx,nqy] (which may be the same as a) */ static void qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]) { int i; /* * first copy a to b, expanding each 4-bit value */ qtree_copy(a,nx,ny,b,ny); /* * now read new 4-bit values into b for each non-zero element */ for (i = nx*ny-1; i >= 0; i--) { if (b[i]) b[i] = input_huffman(infile); } } /* ############################################################################ */ /* * copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding * each value to 2x2 pixels * a,b may be same array */ static void qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n) /* int n; declared y dimension of b */ { int i, j, k, nx2, ny2; int s00, s10; /* * first copy 4-bit values to b * start at end in case a,b are same array */ nx2 = (nx+1)/2; ny2 = (ny+1)/2; k = ny2*(nx2-1)+ny2-1; /* k is index of a[i,j] */ for (i = nx2-1; i >= 0; i--) { s00 = 2*(n*i+ny2-1); /* s00 is index of b[2*i,2*j] */ for (j = ny2-1; j >= 0; j--) { b[s00] = a[k]; k -= 1; s00 -= 2; } } /* * now expand each 2x2 block */ for (i = 0; i>1) & 1; b[s00+1] = (b[s00]>>2) & 1; b[s00 ] = (b[s00]>>3) & 1; */ s00 += 2; s10 += 2; } if (j < ny) { /* * row size is odd, do last element in row * s00+1, s10+1 are off edge */ /* not worth converting this to use 16 case statements */ b[s10 ] = (b[s00]>>1) & 1; b[s00 ] = (b[s00]>>3) & 1; } } if (i < nx) { /* * column size is odd, do last row * s10, s10+1 are off edge */ s00 = n*i; for (j = 0; j>2) & 1; b[s00 ] = (b[s00]>>3) & 1; s00 += 2; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ /* not worth converting this to use 16 case statements */ b[s00 ] = (b[s00]>>3) & 1; } } } /* ############################################################################ */ /* * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding * each value to 2x2 pixels and inserting into bitplane BIT of B. * A,B may NOT be same array (it wouldn't make sense to be inserting * bits into the same array anyway.) */ static void qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit) /* int n; declared y dimension of b */ { int i, j, k; int s00; int plane_val; plane_val = 1 << bit; /* * expand each 2x2 block */ k = 0; /* k is index of a[i/2,j/2] */ for (i = 0; i>1) & 1) << bit; b[s00+1] |= ((a[k]>>2) & 1) << bit; b[s00 ] |= ((a[k]>>3) & 1) << bit; */ s00 += 2; /* s10 += 2; */ k += 1; } if (j < ny) { /* * row size is odd, do last element in row * s00+1, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): b[s00+n ] |= plane_val; break; case(3): b[s00+n ] |= plane_val; break; case(4): break; case(5): break; case(6): b[s00+n ] |= plane_val; break; case(7): b[s00+n ] |= plane_val; break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(11): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(15): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; } /* b[s10 ] |= ((a[k]>>1) & 1) << bit; b[s00 ] |= ((a[k]>>3) & 1) << bit; */ k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10, s10+1 are off edge */ s00 = n*i; for (j = 0; j>2) & 1) << bit; b[s00 ] |= ((a[k]>>3) & 1) << bit; */ s00 += 2; k += 1; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): break; case(3): break; case(4): break; case(5): break; case(6): break; case(7): break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00 ] |= plane_val; break; case(11): b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00 ] |= plane_val; break; case(15): b[s00 ] |= plane_val; break; } /* b[s00 ] |= ((a[k]>>3) & 1) << bit; */ k += 1; } } } /* ############################################################################ */ /* * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding * each value to 2x2 pixels and inserting into bitplane BIT of B. * A,B may NOT be same array (it wouldn't make sense to be inserting * bits into the same array anyway.) */ static void qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit) /* int n; declared y dimension of b */ { int i, j, k; int s00; LONGLONG plane_val; plane_val = ((LONGLONG) 1) << bit; /* * expand each 2x2 block */ k = 0; /* k is index of a[i/2,j/2] */ for (i = 0; i>1) & 1) << bit; b[s00+1] |= ((((LONGLONG)a[k])>>2) & 1) << bit; b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ s00 += 2; /* s10 += 2; */ k += 1; } if (j < ny) { /* * row size is odd, do last element in row * s00+1, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): b[s00+n ] |= plane_val; break; case(3): b[s00+n ] |= plane_val; break; case(4): break; case(5): break; case(6): b[s00+n ] |= plane_val; break; case(7): b[s00+n ] |= plane_val; break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(11): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(15): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; } /* b[s10 ] |= ((((LONGLONG)a[k])>>1) & 1) << bit; b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10, s10+1 are off edge */ s00 = n*i; for (j = 0; j>2) & 1) << bit; b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ s00 += 2; k += 1; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): break; case(3): break; case(4): break; case(5): break; case(6): break; case(7): break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00 ] |= plane_val; break; case(11): b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00 ] |= plane_val; break; case(15): b[s00 ] |= plane_val; break; } /* b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ k += 1; } } } /* ############################################################################ */ static void read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit) { /* * read bit image packed 4 pixels/nybble */ /* int i; for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { scratch[i] = input_nybble(infile); } */ input_nnybble(infile, ((nqx+1)/2) * ((nqy+1)/2), scratch); /* * insert in bitplane BIT of image A */ qtree_bitins(scratch,nqx,nqy,a,n,bit); } /* ############################################################################ */ static void read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit) { /* * read bit image packed 4 pixels/nybble */ /* int i; for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { scratch[i] = input_nybble(infile); } */ input_nnybble(infile, ((nqx+1)/2) * ((nqy+1)/2), scratch); /* * insert in bitplane BIT of image A */ qtree_bitins64(scratch,nqx,nqy,a,n,bit); } /* ############################################################################ */ /* * Huffman decoding for fixed codes * * Coded values range from 0-15 * * Huffman code values (hex): * * 3e, 00, 01, 08, 02, 09, 1a, 1b, * 03, 1c, 0a, 1d, 0b, 1e, 3f, 0c * * and number of bits in each code: * * 6, 3, 3, 4, 3, 4, 5, 5, * 3, 5, 4, 5, 4, 5, 6, 4 */ static int input_huffman(unsigned char *infile) { int c; /* * get first 3 bits to start */ c = input_nbits(infile,3); if (c < 4) { /* * this is all we need * return 1,2,4,8 for c=0,1,2,3 */ return(1<>bits_to_go) & 1); } /* ############################################################################ */ /* INPUT N BITS (N must be <= 8) */ static int input_nbits(unsigned char *infile, int n) { /* AND mask for retreiving the right-most n bits */ static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; if (bits_to_go < n) { /* * need another byte's worth of bits */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; bits_to_go += 8; } /* * now pick off the first n bits */ bits_to_go -= n; /* there was a slight gain in speed by replacing the following line */ /* return( (buffer2>>bits_to_go) & ((1<>bits_to_go) & (*(mask+n)) ); } /* ############################################################################ */ /* INPUT 4 BITS */ static int input_nybble(unsigned char *infile) { if (bits_to_go < 4) { /* * need another byte's worth of bits */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; bits_to_go += 8; } /* * now pick off the first 4 bits */ bits_to_go -= 4; return( (buffer2>>bits_to_go) & 15 ); } /* ############################################################################ */ /* INPUT array of 4 BITS */ static int input_nnybble(unsigned char *infile, int n, unsigned char array[]) { /* copy n 4-bit nybbles from infile to the lower 4 bits of array */ int ii, kk, shift1, shift2; /* forcing byte alignment doesn;t help, and even makes it go slightly slower if (bits_to_go != 8) input_nbits(infile, bits_to_go); */ if (n == 1) { array[0] = input_nybble(infile); return(0); } if (bits_to_go == 8) { /* already have 2 full nybbles in buffer2, so backspace the infile array to reuse last char */ nextchar--; bits_to_go = 0; } /* bits_to_go now has a value in the range 0 - 7. After adding */ /* another byte, bits_to_go effectively will be in range 8 - 15 */ shift1 = bits_to_go + 4; /* shift1 will be in range 4 - 11 */ shift2 = bits_to_go; /* shift2 will be in range 0 - 7 */ kk = 0; /* special case */ if (bits_to_go == 0) { for (ii = 0; ii < n/2; ii++) { /* * refill the buffer with next byte */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; array[kk] = (int) ((buffer2>>4) & 15); array[kk + 1] = (int) ((buffer2) & 15); /* no shift required */ kk += 2; } } else { for (ii = 0; ii < n/2; ii++) { /* * refill the buffer with next byte */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; array[kk] = (int) ((buffer2>>shift1) & 15); array[kk + 1] = (int) ((buffer2>>shift2) & 15); kk += 2; } } if (ii * 2 != n) { /* have to read last odd byte */ array[n-1] = input_nybble(infile); } return( (buffer2>>bits_to_go) & 15 ); } cfitsio-4.3.1/iter_b.fit0000644000225700000360000143660013472024437014435 0ustar cagordonlheaSIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT Contact the NASA Science Office of Standards and Technology for the COMMENT FITS Definition document #100 and other FITS information. END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 4021 / width of table in bytes NAXIS2 = 100 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 3 / number of fields in each row TTYPE1 = 'Avalue ' / label for field 1 TFORM1 = '20A ' / data format of field: ASCII Character TTYPE2 = 'Lvalue ' / label for field 2 TFORM2 = '1L ' / data format of field: 1-byte LOGICAL TUNIT2 = 'm**2 ' / physical unit of field TTYPE3 = 'Evalue ' / label for field 3 TFORM3 = '1000E ' / data format of field: 4-byte REAL TUNIT3 = 'cm ' / physical unit of field EXTNAME = 'iter_test' / name of this binary table extension END changed to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to false Fchanged to true Tchanged to true Tchanged to true Tchanged to true Tchanged to true Tcfitsio-4.3.1/makefile.vcc0000644000225700000360000004317013472024437014732 0ustar cagordonlhea# Microsoft Developer Studio Generated NMAKE File, Based on cfitsio.dsp !IF "$(CFG)" == "" CFG=Win32 Release !MESSAGE No configuration specified. Defaulting to Win32 Release. !ENDIF !IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "cfitsio.mak" CFG="Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "Win32 Release" OUTDIR=. INTDIR=.\Release # Begin Custom Macros OutDir=. # End Custom Macros ALL : "$(OUTDIR)\cfitsio.dll" CLEAN : -@erase "$(INTDIR)\buffers.obj" -@erase "$(INTDIR)\cfileio.obj" -@erase "$(INTDIR)\checksum.obj" -@erase "$(INTDIR)\drvrfile.obj" -@erase "$(INTDIR)\drvrmem.obj" -@erase "$(INTDIR)\editcol.obj" -@erase "$(INTDIR)\edithdu.obj" -@erase "$(INTDIR)\eval_f.obj" -@erase "$(INTDIR)\eval_l.obj" -@erase "$(INTDIR)\eval_y.obj" -@erase "$(INTDIR)\fitscore.obj" -@erase "$(INTDIR)\f77_wrap1.obj" -@erase "$(INTDIR)\f77_wrap2.obj" -@erase "$(INTDIR)\f77_wrap3.obj" -@erase "$(INTDIR)\f77_wrap4.obj" -@erase "$(INTDIR)\getcol.obj" -@erase "$(INTDIR)\getcolb.obj" -@erase "$(INTDIR)\getcolsb.obj" -@erase "$(INTDIR)\getcold.obj" -@erase "$(INTDIR)\getcole.obj" -@erase "$(INTDIR)\getcoli.obj" -@erase "$(INTDIR)\getcolj.obj" -@erase "$(INTDIR)\getcolk.obj" -@erase "$(INTDIR)\getcoll.obj" -@erase "$(INTDIR)\getcols.obj" -@erase "$(INTDIR)\getcolui.obj" -@erase "$(INTDIR)\getcoluj.obj" -@erase "$(INTDIR)\getcoluk.obj" -@erase "$(INTDIR)\getkey.obj" -@erase "$(INTDIR)\group.obj" -@erase "$(INTDIR)\grparser.obj" -@erase "$(INTDIR)\histo.obj" -@erase "$(INTDIR)\iraffits.obj" -@erase "$(INTDIR)\modkey.obj" -@erase "$(INTDIR)\putcol.obj" -@erase "$(INTDIR)\putcolb.obj" -@erase "$(INTDIR)\putcolsb.obj" -@erase "$(INTDIR)\putcold.obj" -@erase "$(INTDIR)\putcole.obj" -@erase "$(INTDIR)\putcoli.obj" -@erase "$(INTDIR)\putcolj.obj" -@erase "$(INTDIR)\putcolk.obj" -@erase "$(INTDIR)\putcoll.obj" -@erase "$(INTDIR)\putcols.obj" -@erase "$(INTDIR)\putcolu.obj" -@erase "$(INTDIR)\putcolui.obj" -@erase "$(INTDIR)\putcoluj.obj" -@erase "$(INTDIR)\putcoluk.obj" -@erase "$(INTDIR)\putkey.obj" -@erase "$(INTDIR)\region.obj" -@erase "$(INTDIR)\scalnull.obj" -@erase "$(INTDIR)\swapproc.obj" -@erase "$(INTDIR)\wcssub.obj" -@erase "$(INTDIR)\wcsutil.obj" -@erase "$(INTDIR)\imcompress.obj" -@erase "$(INTDIR)\ricecomp.obj" -@erase "$(INTDIR)\quantize.obj" -@erase "$(INTDIR)\pliocomp.obj" -@erase "$(INTDIR)\fits_hcompress.obj" -@erase "$(INTDIR)\fits_hdecompress.obj" -@erase "$(INTDIR)\zuncompress.obj" -@erase "$(INTDIR)\zcompress.obj" -@erase "$(INTDIR)\adler32.obj" -@erase "$(INTDIR)\crc32.obj" -@erase "$(INTDIR)\inffast.obj" -@erase "$(INTDIR)\inftrees.obj" -@erase "$(INTDIR)\trees.obj" -@erase "$(INTDIR)\zutil.obj" -@erase "$(INTDIR)\deflate.obj" -@erase "$(INTDIR)\infback.obj" -@erase "$(INTDIR)\inflate.obj" -@erase "$(INTDIR)\uncompr.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "$(OUTDIR)\cfitsio.dll" -@erase "$(OUTDIR)\cfitsio.exp" -@erase "$(OUTDIR)\cfitsio.lib" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" "$(INTDIR)" : if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CFITSIO_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"$(INTDIR)\cfitsio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\cfitsio.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\cfitsio.pdb" /machine:I386 /def:".\cfitsio.def" /out:"$(OUTDIR)\cfitsio.dll" /implib:"$(OUTDIR)\cfitsio.lib" DEF_FILE= ".\cfitsio.def" LINK32_OBJS= \ "$(INTDIR)\buffers.obj" \ "$(INTDIR)\cfileio.obj" \ "$(INTDIR)\checksum.obj" \ "$(INTDIR)\drvrfile.obj" \ "$(INTDIR)\drvrmem.obj" \ "$(INTDIR)\editcol.obj" \ "$(INTDIR)\edithdu.obj" \ "$(INTDIR)\eval_f.obj" \ "$(INTDIR)\eval_l.obj" \ "$(INTDIR)\eval_y.obj" \ "$(INTDIR)\fitscore.obj" \ "$(INTDIR)\f77_wrap1.obj" \ "$(INTDIR)\f77_wrap2.obj" \ "$(INTDIR)\f77_wrap3.obj" \ "$(INTDIR)\f77_wrap4.obj" \ "$(INTDIR)\getcol.obj" \ "$(INTDIR)\getcolb.obj" \ "$(INTDIR)\getcolsb.obj" \ "$(INTDIR)\getcold.obj" \ "$(INTDIR)\getcole.obj" \ "$(INTDIR)\getcoli.obj" \ "$(INTDIR)\getcolj.obj" \ "$(INTDIR)\getcolk.obj" \ "$(INTDIR)\getcoll.obj" \ "$(INTDIR)\getcols.obj" \ "$(INTDIR)\getcolui.obj" \ "$(INTDIR)\getcoluj.obj" \ "$(INTDIR)\getcoluk.obj" \ "$(INTDIR)\getkey.obj" \ "$(INTDIR)\group.obj" \ "$(INTDIR)\grparser.obj" \ "$(INTDIR)\histo.obj" \ "$(INTDIR)\iraffits.obj" \ "$(INTDIR)\modkey.obj" \ "$(INTDIR)\putcol.obj" \ "$(INTDIR)\putcolb.obj" \ "$(INTDIR)\putcolsb.obj" \ "$(INTDIR)\putcold.obj" \ "$(INTDIR)\putcole.obj" \ "$(INTDIR)\putcoli.obj" \ "$(INTDIR)\putcolj.obj" \ "$(INTDIR)\putcolk.obj" \ "$(INTDIR)\putcoll.obj" \ "$(INTDIR)\putcols.obj" \ "$(INTDIR)\putcolu.obj" \ "$(INTDIR)\putcolui.obj" \ "$(INTDIR)\putcoluj.obj" \ "$(INTDIR)\putcoluk.obj" \ "$(INTDIR)\putkey.obj" \ "$(INTDIR)\region.obj" \ "$(INTDIR)\scalnull.obj" \ "$(INTDIR)\swapproc.obj" \ "$(INTDIR)\wcssub.obj" \ "$(INTDIR)\wcsutil.obj" \ "$(INTDIR)\imcompress.obj" \ "$(INTDIR)\ricecomp.obj" \ "$(INTDIR)\quantize.obj" \ "$(INTDIR)\pliocomp.obj" \ "$(INTDIR)\fits_hcompress.obj" \ "$(INTDIR)\fits_hdecompress.obj" \ "$(INTDIR)\zuncompress.obj" \ "$(INTDIR)\zcompress.obj" \ "$(INTDIR)\adler32.obj" \ "$(INTDIR)\crc32.obj" \ "$(INTDIR)\inffast.obj" \ "$(INTDIR)\inftrees.obj" \ "$(INTDIR)\trees.obj" \ "$(INTDIR)\zutil.obj" \ "$(INTDIR)\deflate.obj" \ "$(INTDIR)\infback.obj" \ "$(INTDIR)\inflate.obj" \ "$(INTDIR)\uncompr.obj" "$(OUTDIR)\cfitsio.dll" : $(LINK32_OBJS) WINDUMP windumpexts -o $(DEF_FILE) cfitsio.dll $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ELSEIF "$(CFG)" == "Win32 Debug" OUTDIR=. INTDIR=.\Debug # Begin Custom Macros OutDir=. # End Custom Macros ALL : "$(OUTDIR)\cfitsio.dll" CLEAN : -@erase "$(INTDIR)\buffers.obj" -@erase "$(INTDIR)\cfileio.obj" -@erase "$(INTDIR)\checksum.obj" -@erase "$(INTDIR)\drvrfile.obj" -@erase "$(INTDIR)\drvrmem.obj" -@erase "$(INTDIR)\editcol.obj" -@erase "$(INTDIR)\edithdu.obj" -@erase "$(INTDIR)\eval_f.obj" -@erase "$(INTDIR)\eval_l.obj" -@erase "$(INTDIR)\eval_y.obj" -@erase "$(INTDIR)\fitscore.obj" -@erase "$(INTDIR)\f77_wrap1.obj" -@erase "$(INTDIR)\f77_wrap2.obj" -@erase "$(INTDIR)\f77_wrap3.obj" -@erase "$(INTDIR)\f77_wrap4.obj" -@erase "$(INTDIR)\getcol.obj" -@erase "$(INTDIR)\getcolb.obj" -@erase "$(INTDIR)\getcolsb.obj" -@erase "$(INTDIR)\getcold.obj" -@erase "$(INTDIR)\getcole.obj" -@erase "$(INTDIR)\getcoli.obj" -@erase "$(INTDIR)\getcolj.obj" -@erase "$(INTDIR)\getcolk.obj" -@erase "$(INTDIR)\getcoll.obj" -@erase "$(INTDIR)\getcols.obj" -@erase "$(INTDIR)\getcolui.obj" -@erase "$(INTDIR)\getcoluj.obj" -@erase "$(INTDIR)\getcoluk.obj" -@erase "$(INTDIR)\getkey.obj" -@erase "$(INTDIR)\group.obj" -@erase "$(INTDIR)\grparser.obj" -@erase "$(INTDIR)\histo.obj" -@erase "$(INTDIR)\iraffits.obj" -@erase "$(INTDIR)\modkey.obj" -@erase "$(INTDIR)\putcol.obj" -@erase "$(INTDIR)\putcolb.obj" -@erase "$(INTDIR)\putcolsb.obj" -@erase "$(INTDIR)\putcold.obj" -@erase "$(INTDIR)\putcole.obj" -@erase "$(INTDIR)\putcoli.obj" -@erase "$(INTDIR)\putcolj.obj" -@erase "$(INTDIR)\putcolk.obj" -@erase "$(INTDIR)\putcoll.obj" -@erase "$(INTDIR)\putcols.obj" -@erase "$(INTDIR)\putcolu.obj" -@erase "$(INTDIR)\putcolui.obj" -@erase "$(INTDIR)\putcoluj.obj" -@erase "$(INTDIR)\putcoluk.obj" -@erase "$(INTDIR)\putkey.obj" -@erase "$(INTDIR)\region.obj" -@erase "$(INTDIR)\scalnull.obj" -@erase "$(INTDIR)\swapproc.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(INTDIR)\wcssub.obj" -@erase "$(INTDIR)\wcsutil.obj" -@erase "$(INTDIR)\imcompress.obj" -@erase "$(INTDIR)\ricecomp.obj" -@erase "$(INTDIR)\quantize.obj" -@erase "$(INTDIR)\pliocomp.obj" -@erase "$(INTDIR)\fits_hcompress.obj" -@erase "$(INTDIR)\fits_hdecompress.obj" -@erase "$(INTDIR)\zuncompress.obj" -@erase "$(INTDIR)\zcompress.obj" -@erase "$(INTDIR)\adler32.obj" -@erase "$(INTDIR)\crc32.obj" -@erase "$(INTDIR)\inffast.obj" -@erase "$(INTDIR)\inftrees.obj" -@erase "$(INTDIR)\trees.obj" -@erase "$(INTDIR)\zutil.obj" -@erase "$(INTDIR)\deflate.obj" -@erase "$(INTDIR)\infback.obj" -@erase "$(INTDIR)\inflate.obj" -@erase "$(INTDIR)\uncompr.obj" -@erase "$(OUTDIR)\cfitsio.dll" -@erase "$(OUTDIR)\cfitsio.exp" -@erase "$(OUTDIR)\cfitsio.ilk" -@erase "$(OUTDIR)\cfitsio.lib" -@erase "$(OUTDIR)\cfitsio.pdb" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" "$(INTDIR)" : if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /D "__WIN32__" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CFITSIO_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"$(INTDIR)\cfitsio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\cfitsio.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\cfitsio.pdb" /debug /machine:I386 /def:".\cfitsio.def" /out:"$(OUTDIR)\cfitsio.dll" /implib:"$(OUTDIR)\cfitsio.lib" /pdbtype:sept DEF_FILE= ".\cfitsio.def" LINK32_OBJS= \ "$(INTDIR)\buffers.obj" \ "$(INTDIR)\cfileio.obj" \ "$(INTDIR)\checksum.obj" \ "$(INTDIR)\drvrfile.obj" \ "$(INTDIR)\drvrmem.obj" \ "$(INTDIR)\editcol.obj" \ "$(INTDIR)\edithdu.obj" \ "$(INTDIR)\eval_f.obj" \ "$(INTDIR)\eval_l.obj" \ "$(INTDIR)\eval_y.obj" \ "$(INTDIR)\fitscore.obj" \ "$(INTDIR)\f77_wrap1.obj" \ "$(INTDIR)\f77_wrap2.obj" \ "$(INTDIR)\f77_wrap3.obj" \ "$(INTDIR)\f77_wrap4.obj" \ "$(INTDIR)\getcol.obj" \ "$(INTDIR)\getcolb.obj" \ "$(INTDIR)\getcolsb.obj" \ "$(INTDIR)\getcold.obj" \ "$(INTDIR)\getcole.obj" \ "$(INTDIR)\getcoli.obj" \ "$(INTDIR)\getcolj.obj" \ "$(INTDIR)\getcolk.obj" \ "$(INTDIR)\getcoll.obj" \ "$(INTDIR)\getcols.obj" \ "$(INTDIR)\getcolui.obj" \ "$(INTDIR)\getcoluj.obj" \ "$(INTDIR)\getcoluk.obj" \ "$(INTDIR)\getkey.obj" \ "$(INTDIR)\group.obj" \ "$(INTDIR)\grparser.obj" \ "$(INTDIR)\histo.obj" \ "$(INTDIR)\iraffits.obj" \ "$(INTDIR)\modkey.obj" \ "$(INTDIR)\putcol.obj" \ "$(INTDIR)\putcolb.obj" \ "$(INTDIR)\putcolsb.obj" \ "$(INTDIR)\putcold.obj" \ "$(INTDIR)\putcole.obj" \ "$(INTDIR)\putcoli.obj" \ "$(INTDIR)\putcolj.obj" \ "$(INTDIR)\putcolk.obj" \ "$(INTDIR)\putcoll.obj" \ "$(INTDIR)\putcols.obj" \ "$(INTDIR)\putcolu.obj" \ "$(INTDIR)\putcolui.obj" \ "$(INTDIR)\putcoluj.obj" \ "$(INTDIR)\putcoluk.obj" \ "$(INTDIR)\putkey.obj" \ "$(INTDIR)\region.obj" \ "$(INTDIR)\scalnull.obj" \ "$(INTDIR)\swapproc.obj" \ "$(INTDIR)\wcssub.obj" \ "$(INTDIR)\wcsutil.obj" \ "$(INTDIR)\imcompress.obj" \ "$(INTDIR)\ricecomp.obj" \ "$(INTDIR)\quantize.obj" \ "$(INTDIR)\pliocomp.obj" \ "$(INTDIR)\fits_hcompress.obj" \ "$(INTDIR)\fits_hdecompress.obj" \ "$(INTDIR)\zuncompress.obj" \ "$(INTDIR)\zcompress.obj" \ "$(INTDIR)\adler32.obj" \ "$(INTDIR)\crc32.obj" \ "$(INTDIR)\inffast.obj" \ "$(INTDIR)\inftrees.obj" \ "$(INTDIR)\trees.obj" \ "$(INTDIR)\zutil.obj" \ "$(INTDIR)\deflate.obj" \ "$(INTDIR)\infback.obj" \ "$(INTDIR)\inflate.obj" \ "$(INTDIR)\uncompr.obj" "$(OUTDIR)\cfitsio.dll" : $(LINK32_OBJS) WINDUMP windumpexts -o $(DEF_FILE) cfitsio.dll $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("cfitsio.dep") !INCLUDE "cfitsio.dep" !ELSE !MESSAGE Warning: cannot find "cfitsio.dep" !ENDIF !ENDIF !IF "$(CFG)" == "Win32 Release" || "$(CFG)" == "Win32 Debug" SOURCE=.\buffers.c "$(INTDIR)\buffers.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\cfileio.c "$(INTDIR)\cfileio.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\checksum.c "$(INTDIR)\checksum.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\drvrfile.c "$(INTDIR)\drvrfile.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\drvrmem.c "$(INTDIR)\drvrmem.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\editcol.c "$(INTDIR)\editcol.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\edithdu.c "$(INTDIR)\edithdu.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\eval_f.c "$(INTDIR)\eval_f.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\eval_l.c "$(INTDIR)\eval_l.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\eval_y.c "$(INTDIR)\eval_y.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\fitscore.c "$(INTDIR)\fitscore.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\f77_wrap1.c "$(INTDIR)\f77_wrap1.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\f77_wrap2.c "$(INTDIR)\f77_wrap2.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\f77_wrap3.c "$(INTDIR)\f77_wrap3.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\f77_wrap4.c "$(INTDIR)\f77_wrap4.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcol.c "$(INTDIR)\getcol.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcolb.c "$(INTDIR)\getcolb.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcolsb.c "$(INTDIR)\getcolsb.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcold.c "$(INTDIR)\getcold.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcole.c "$(INTDIR)\getcole.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcoli.c "$(INTDIR)\getcoli.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcolj.c "$(INTDIR)\getcolj.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcolk.c "$(INTDIR)\getcolk.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcoll.c "$(INTDIR)\getcoll.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcols.c "$(INTDIR)\getcols.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcolui.c "$(INTDIR)\getcolui.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcoluj.c "$(INTDIR)\getcoluj.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getcoluk.c "$(INTDIR)\getcoluk.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\getkey.c "$(INTDIR)\getkey.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\group.c "$(INTDIR)\group.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\grparser.c "$(INTDIR)\grparser.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\histo.c "$(INTDIR)\histo.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\iraffits.c "$(INTDIR)\iraffits.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\modkey.c "$(INTDIR)\modkey.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcol.c "$(INTDIR)\putcol.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcolb.c "$(INTDIR)\putcolb.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcolsb.c "$(INTDIR)\putcolsb.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcold.c "$(INTDIR)\putcold.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcole.c "$(INTDIR)\putcole.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcoli.c "$(INTDIR)\putcoli.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcolj.c "$(INTDIR)\putcolj.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcolk.c "$(INTDIR)\putcolk.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcoll.c "$(INTDIR)\putcoll.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcols.c "$(INTDIR)\putcols.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcolu.c "$(INTDIR)\putcolu.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcolui.c "$(INTDIR)\putcolui.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcoluj.c "$(INTDIR)\putcoluj.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putcoluk.c "$(INTDIR)\putcoluk.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\putkey.c "$(INTDIR)\putkey.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\region.c "$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\scalnull.c "$(INTDIR)\scalnull.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\swapproc.c "$(INTDIR)\swapproc.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\wcssub.c "$(INTDIR)\wcssub.obj" : $(SOURCE) "$(INTDIR)" SOURCE=.\wcsutil.c "$(INTDIR)\wcsutil.obj" : $(SOURCE) "$(INTDIR)" SOURCE=imcompress.c "$(INTDIR)\imcompress.obj" : $(SOURCE) "$(INTDIR)" SOURCE=ricecomp.c "$(INTDIR)\ricecomp.obj" : $(SOURCE) "$(INTDIR)" SOURCE=quantize.c "$(INTDIR)\quantize.obj" : $(SOURCE) "$(INTDIR)" SOURCE=pliocomp.c "$(INTDIR)\pliocomp.obj" : $(SOURCE) "$(INTDIR)" SOURCE=fits_hcompress.c "$(INTDIR)\fits_hcompress.obj" : $(SOURCE) "$(INTDIR)" SOURCE=fits_hdecompress.c "$(INTDIR)\fits_hdecompress.obj" : $(SOURCE) "$(INTDIR)" SOURCE=zuncompress.c "$(INTDIR)\zuncompress.obj" : $(SOURCE) "$(INTDIR)" SOURCE=zcompress.c "$(INTDIR)\zcompress.obj" : $(SOURCE) "$(INTDIR)" SOURCE=adler32.c "$(INTDIR)\adler32.obj" : $(SOURCE) "$(INTDIR)" SOURCE=crc32.c "$(INTDIR)\crc32.obj" : $(SOURCE) "$(INTDIR)" SOURCE=inffast.c "$(INTDIR)\inffast.obj" : $(SOURCE) "$(INTDIR)" SOURCE=inftrees.c "$(INTDIR)\inftrees.obj" : $(SOURCE) "$(INTDIR)" SOURCE=trees.c "$(INTDIR)\trees.obj" : $(SOURCE) "$(INTDIR)" SOURCE=zutil.c "$(INTDIR)\zutil.obj" : $(SOURCE) "$(INTDIR)" SOURCE=deflate.c "$(INTDIR)\deflate.obj" : $(SOURCE) "$(INTDIR)" SOURCE=infback.c "$(INTDIR)\infback.obj" : $(SOURCE) "$(INTDIR)" SOURCE=inflate.c "$(INTDIR)\inflate.obj" : $(SOURCE) "$(INTDIR)" SOURCE=uncompr.c "$(INTDIR)\uncompr.obj" : $(SOURCE) "$(INTDIR)" !ENDIF $(DEF_FILE): WINDUMP: nmake -f winDumpExts.mak cfitsio-4.3.1/fits_hcompress.c0000644000225700000360000013375213472024437015662 0ustar cagordonlhea/* ######################################################################### These routines to apply the H-compress compression algorithm to a 2-D Fits image were written by R. White at the STScI and were obtained from the STScI at http://www.stsci.edu/software/hcompress.html This source file is a concatination of the following sources files in the original distribution htrans.c digitize.c encode.c qwrite.c doencode.c bit_output.c qtree_encode.c The following modifications have been made to the original code: - commented out redundant "include" statements - added the noutchar global variable - changed all the 'extern' declarations to 'static', since all the routines are in the same source file - changed the first parameter in encode (and in lower level routines from a file stream to a char array - modifid the encode routine to return the size of the compressed array of bytes - changed calls to printf and perror to call the CFITSIO ffpmsg routine - modified the mywrite routine, and lower level byte writing routines, to copy the output bytes to a char array, instead of writing them to a file stream - replace "exit" statements with "return" statements - changed the function declarations to the more modern ANSI C style ############################################################################ */ #include #include #include #include #include "fitsio2.h" static long noutchar; static long noutmax; static int htrans(int a[],int nx,int ny); static void digitize(int a[], int nx, int ny, int scale); static int encode(char *outfile, long *nlen, int a[], int nx, int ny, int scale); static void shuffle(int a[], int n, int n2, int tmp[]); static int htrans64(LONGLONG a[],int nx,int ny); static void digitize64(LONGLONG a[], int nx, int ny, int scale); static int encode64(char *outfile, long *nlen, LONGLONG a[], int nx, int ny, int scale); static void shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]); static void writeint(char *outfile, int a); static void writelonglong(char *outfile, LONGLONG a); static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]); static int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]); static int qwrite(char *file, char buffer[], int n); static int qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes); static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes); static void start_outputing_bits(void); static void done_outputing_bits(char *outfile); static void output_nbits(char *outfile, int bits, int n); static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit); static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit); static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]); static int bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax); static void write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit); static void write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit); /* #define output_nybble(outfile,c) output_nbits(outfile,c,4) */ static void output_nybble(char *outfile, int bits); static void output_nnybble(char *outfile, int n, unsigned char array[]); #define output_huffman(outfile,c) output_nbits(outfile,code[c],ncode[c]) /* ---------------------------------------------------------------------- */ int fits_hcompress(int *a, int ny, int nx, int scale, char *output, long *nbytes, int *status) { /* compress the input image using the H-compress algorithm a - input image array nx - size of X axis of image ny - size of Y axis of image scale - quantization scale factor. Larger values results in more (lossy) compression scale = 0 does lossless compression output - pre-allocated array to hold the output compressed stream of bytes nbyts - input value = size of the output buffer; returned value = size of the compressed byte stream, in bytes NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat; if (*status > 0) return(*status); /* H-transform */ stat = htrans(a, nx, ny); if (stat) { *status = stat; return(*status); } /* digitize */ digitize(a, nx, ny, scale); /* encode and write to output array */ FFLOCK; noutmax = *nbytes; /* input value is the allocated size of the array */ *nbytes = 0; /* reset */ stat = encode(output, nbytes, a, nx, ny, scale); FFUNLOCK; *status = stat; return(*status); } /* ---------------------------------------------------------------------- */ int fits_hcompress64(LONGLONG *a, int ny, int nx, int scale, char *output, long *nbytes, int *status) { /* compress the input image using the H-compress algorithm a - input image array nx - size of X axis of image ny - size of Y axis of image scale - quantization scale factor. Larger values results in more (lossy) compression scale = 0 does lossless compression output - pre-allocated array to hold the output compressed stream of bytes nbyts - size of the compressed byte stream, in bytes NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat; if (*status > 0) return(*status); /* H-transform */ stat = htrans64(a, nx, ny); if (stat) { *status = stat; return(*status); } /* digitize */ digitize64(a, nx, ny, scale); /* encode and write to output array */ FFLOCK; noutmax = *nbytes; /* input value is the allocated size of the array */ *nbytes = 0; /* reset */ stat = encode64(output, nbytes, a, nx, ny, scale); FFUNLOCK; *status = stat; return(*status); } /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* htrans.c H-transform of NX x NY integer image * * Programmer: R. White Date: 11 May 1992 */ /* ######################################################################### */ static int htrans(int a[],int nx,int ny) { int nmax, log2n, h0, hx, hy, hc, nxtop, nytop, i, j, k; int oddx, oddy; int shift, mask, mask2, prnd, prnd2, nrnd2; int s10, s00; int *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> shift; hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift; hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift; hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift; /* * Throw away the 2 bottom bits of h0, bottom bit of hx,hy. * To get rounding to be same for positive and negative * numbers, nrnd2 = prnd2 - 1. */ a[s10+1] = hc; a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = (a[s10] + a[s00]) << (1-shift); hx = (a[s10] - a[s00]) << (1-shift); a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 1; s10 += 1; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = i*ny; for (j = 0; j=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00] << (2-shift); a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; } } /* * now shuffle in each dimension to group coefficients by order */ for (i = 0; i>1; nytop = (nytop+1)>>1; /* * divisor doubles after first reduction */ shift = 1; /* * masks, rounding values double after each iteration */ mask = mask2; prnd = prnd2; mask2 = mask2 << 1; prnd2 = prnd2 << 1; nrnd2 = prnd2 - 1; } free(tmp); return(0); } /* ######################################################################### */ static int htrans64(LONGLONG a[],int nx,int ny) { int nmax, log2n, nxtop, nytop, i, j, k; int oddx, oddy; int shift; int s10, s00; LONGLONG h0, hx, hy, hc, prnd, prnd2, nrnd2, mask, mask2; LONGLONG *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> shift; hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift; hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift; hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift; /* * Throw away the 2 bottom bits of h0, bottom bit of hx,hy. * To get rounding to be same for positive and negative * numbers, nrnd2 = prnd2 - 1. */ a[s10+1] = hc; a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = (a[s10] + a[s00]) << (1-shift); hx = (a[s10] - a[s00]) << (1-shift); a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 1; s10 += 1; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = i*ny; for (j = 0; j=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00] << (2-shift); a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; } } /* * now shuffle in each dimension to group coefficients by order */ for (i = 0; i>1; nytop = (nytop+1)>>1; /* * divisor doubles after first reduction */ shift = 1; /* * masks, rounding values double after each iteration */ mask = mask2; prnd = prnd2; mask2 = mask2 << 1; prnd2 = prnd2 << 1; nrnd2 = prnd2 - 1; } free(tmp); return(0); } /* ######################################################################### */ static void shuffle(int a[], int n, int n2, int tmp[]) { /* int a[]; array to shuffle int n; number of elements to shuffle int n2; second dimension int tmp[]; scratch storage */ int i; int *p1, *p2, *pt; /* * copy odd elements to tmp */ pt = tmp; p1 = &a[n2]; for (i=1; i < n; i += 2) { *pt = *p1; pt += 1; p1 += (n2+n2); } /* * compress even elements into first half of A */ p1 = &a[n2]; p2 = &a[n2+n2]; for (i=2; i0) ? (*p+d) : (*p-d))/scale; } /* ######################################################################### */ static void digitize64(LONGLONG a[], int nx, int ny, int scale) { LONGLONG d, *p, scale64; /* * round to multiple of scale */ if (scale <= 1) return; d=(scale+1)/2-1; scale64 = scale; /* use a 64-bit int for efficiency in the big loop */ for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale64; } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* encode.c encode H-transform and write to outfile * * Programmer: R. White Date: 2 February 1994 */ static char code_magic[2] = { (char)0xDD, (char)0x99 }; /* ######################################################################### */ static int encode(char *outfile, long *nlength, int a[], int nx, int ny, int scale) { /* FILE *outfile; - change outfile to a char array */ /* long * nlength returned length (in bytes) of the encoded array) int a[]; input H-transform array (nx,ny) int nx,ny; size of H-transform array int scale; scale factor for digitization */ int nel, nx2, ny2, i, j, k, q, vmax[3], nsign, bits_to_go; unsigned char nbitplanes[3]; unsigned char *signbits; int stat; noutchar = 0; /* initialize the number of compressed bytes that have been written */ nel = nx*ny; /* * write magic value */ qwrite(outfile, code_magic, sizeof(code_magic)); writeint(outfile, nx); /* size of image */ writeint(outfile, ny); writeint(outfile, scale); /* scale factor for digitization */ /* * write first value of A (sum of all pixels -- the only value * which does not compress well) */ writelonglong(outfile, (LONGLONG) a[0]); a[0] = 0; /* * allocate array for sign bits and save values, 8 per byte (initialize to all zeros) */ signbits = (unsigned char *) calloc(1, (nel+7)/8); if (signbits == (unsigned char *) NULL) { ffpmsg("encode: insufficient memory"); return(DATA_COMPRESSION_ERR); } nsign = 0; bits_to_go = 8; /* signbits[0] = 0; */ for (i=0; i 0) { /* * positive element, put zero at end of buffer */ signbits[nsign] <<= 1; bits_to_go -= 1; } else if (a[i] < 0) { /* * negative element, shift in a one */ signbits[nsign] <<= 1; signbits[nsign] |= 1; bits_to_go -= 1; /* * replace a by absolute value */ a[i] = -a[i]; } if (bits_to_go == 0) { /* * filled up this byte, go to the next one */ bits_to_go = 8; nsign += 1; /* signbits[nsign] = 0; */ } } if (bits_to_go != 8) { /* * some bits in last element * move bits in last byte to bottom and increment nsign */ signbits[nsign] <<= bits_to_go; nsign += 1; } /* * calculate number of bit planes for 3 quadrants * * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, */ for (q=0; q<3; q++) { vmax[q] = 0; } /* * get maximum absolute value in each quadrant */ nx2 = (nx+1)/2; ny2 = (ny+1)/2; j=0; /* column counter */ k=0; /* row counter */ for (i=0; i=ny2) + (k>=nx2); if (vmax[q] < a[i]) vmax[q] = a[i]; if (++j >= ny) { j = 0; k += 1; } } /* * now calculate number of bits for each quadrant */ /* this is a more efficient way to do this, */ for (q = 0; q < 3; q++) { for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; } /* for (q = 0; q < 3; q++) { nbitplanes[q] = (int) (log((float) (vmax[q]+1))/log(2.0)+0.5); if ( (vmax[q]+1) > (1< 0) { if ( 0 == qwrite(outfile, (char *) signbits, nsign)) { free(signbits); *nlength = noutchar; ffpmsg("encode: output buffer too small"); return(DATA_COMPRESSION_ERR); } } free(signbits); *nlength = noutchar; if (noutchar >= noutmax) { ffpmsg("encode: output buffer too small"); return(DATA_COMPRESSION_ERR); } return(stat); } /* ######################################################################### */ static int encode64(char *outfile, long *nlength, LONGLONG a[], int nx, int ny, int scale) { /* FILE *outfile; - change outfile to a char array */ /* long * nlength returned length (in bytes) of the encoded array) LONGLONG a[]; input H-transform array (nx,ny) int nx,ny; size of H-transform array int scale; scale factor for digitization */ int nel, nx2, ny2, i, j, k, q, nsign, bits_to_go; LONGLONG vmax[3]; unsigned char nbitplanes[3]; unsigned char *signbits; int stat; noutchar = 0; /* initialize the number of compressed bytes that have been written */ nel = nx*ny; /* * write magic value */ qwrite(outfile, code_magic, sizeof(code_magic)); writeint(outfile, nx); /* size of image */ writeint(outfile, ny); writeint(outfile, scale); /* scale factor for digitization */ /* * write first value of A (sum of all pixels -- the only value * which does not compress well) */ writelonglong(outfile, a[0]); a[0] = 0; /* * allocate array for sign bits and save values, 8 per byte */ signbits = (unsigned char *) calloc(1, (nel+7)/8); if (signbits == (unsigned char *) NULL) { ffpmsg("encode64: insufficient memory"); return(DATA_COMPRESSION_ERR); } nsign = 0; bits_to_go = 8; /* signbits[0] = 0; */ for (i=0; i 0) { /* * positive element, put zero at end of buffer */ signbits[nsign] <<= 1; bits_to_go -= 1; } else if (a[i] < 0) { /* * negative element, shift in a one */ signbits[nsign] <<= 1; signbits[nsign] |= 1; bits_to_go -= 1; /* * replace a by absolute value */ a[i] = -a[i]; } if (bits_to_go == 0) { /* * filled up this byte, go to the next one */ bits_to_go = 8; nsign += 1; /* signbits[nsign] = 0; */ } } if (bits_to_go != 8) { /* * some bits in last element * move bits in last byte to bottom and increment nsign */ signbits[nsign] <<= bits_to_go; nsign += 1; } /* * calculate number of bit planes for 3 quadrants * * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, */ for (q=0; q<3; q++) { vmax[q] = 0; } /* * get maximum absolute value in each quadrant */ nx2 = (nx+1)/2; ny2 = (ny+1)/2; j=0; /* column counter */ k=0; /* row counter */ for (i=0; i=ny2) + (k>=nx2); if (vmax[q] < a[i]) vmax[q] = a[i]; if (++j >= ny) { j = 0; k += 1; } } /* * now calculate number of bits for each quadrant */ /* this is a more efficient way to do this, */ for (q = 0; q < 3; q++) { for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; } /* for (q = 0; q < 3; q++) { nbitplanes[q] = log((float) (vmax[q]+1))/log(2.0)+0.5; if ( (vmax[q]+1) > (((LONGLONG) 1)< 0) { if ( 0 == qwrite(outfile, (char *) signbits, nsign)) { free(signbits); *nlength = noutchar; ffpmsg("encode: output buffer too small"); return(DATA_COMPRESSION_ERR); } } free(signbits); *nlength = noutchar; if (noutchar >= noutmax) { ffpmsg("encode64: output buffer too small"); return(DATA_COMPRESSION_ERR); } return(stat); } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* qwrite.c Write binary data * * Programmer: R. White Date: 11 March 1991 */ /* ######################################################################### */ static void writeint(char *outfile, int a) { int i; unsigned char b[4]; /* Write integer A one byte at a time to outfile. * * This is portable from Vax to Sun since it eliminates the * need for byte-swapping. */ for (i=3; i>=0; i--) { b[i] = a & 0x000000ff; a >>= 8; } for (i=0; i<4; i++) qwrite(outfile, (char *) &b[i],1); } /* ######################################################################### */ static void writelonglong(char *outfile, LONGLONG a) { int i; unsigned char b[8]; /* Write integer A one byte at a time to outfile. * * This is portable from Vax to Sun since it eliminates the * need for byte-swapping. */ for (i=7; i>=0; i--) { b[i] = (unsigned char) (a & 0x000000ff); a >>= 8; } for (i=0; i<8; i++) qwrite(outfile, (char *) &b[i],1); } /* ######################################################################### */ static int qwrite(char *file, char buffer[], int n){ /* * write n bytes from buffer into file * returns number of bytes read (=n) if successful, <=0 if not */ if (noutchar + n > noutmax) return(0); /* buffer overflow */ memcpy(&file[noutchar], buffer, n); noutchar += n; return(n); } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* doencode.c Encode 2-D array and write stream of characters on outfile * * This version assumes that A is positive. * * Programmer: R. White Date: 7 May 1991 */ /* ######################################################################### */ static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]) { /* char *outfile; output data stream int a[]; Array of values to encode int nx,ny; Array dimensions [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ int nx2, ny2, stat; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * Initialize bit output */ start_outputing_bits(); /* * write out the bit planes for each quadrant */ stat = qtree_encode(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); if (!stat) stat = qtree_encode(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); if (!stat) stat = qtree_encode(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); if (!stat) stat = qtree_encode(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); /* * Add zero as an EOF symbol */ output_nybble(outfile, 0); done_outputing_bits(outfile); return(stat); } /* ######################################################################### */ static int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]) { /* char *outfile; output data stream LONGLONG a[]; Array of values to encode int nx,ny; Array dimensions [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ int nx2, ny2, stat; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * Initialize bit output */ start_outputing_bits(); /* * write out the bit planes for each quadrant */ stat = qtree_encode64(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); if (!stat) stat = qtree_encode64(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); if (!stat) stat = qtree_encode64(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); if (!stat) stat = qtree_encode64(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); /* * Add zero as an EOF symbol */ output_nybble(outfile, 0); done_outputing_bits(outfile); return(stat); } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* BIT OUTPUT ROUTINES */ static LONGLONG bitcount; /* THE BIT BUFFER */ static int buffer2; /* Bits buffered for output */ static int bits_to_go2; /* Number of bits free in buffer */ /* ######################################################################### */ /* INITIALIZE FOR BIT OUTPUT */ static void start_outputing_bits(void) { buffer2 = 0; /* Buffer is empty to start */ bits_to_go2 = 8; /* with */ bitcount = 0; } /* ######################################################################### */ /* OUTPUT N BITS (N must be <= 8) */ static void output_nbits(char *outfile, int bits, int n) { /* AND mask for the right-most n bits */ static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; /* * insert bits at end of buffer */ buffer2 <<= n; /* buffer2 |= ( bits & ((1<>(-bits_to_go2)) & 0xff); if (noutchar < noutmax) noutchar++; bits_to_go2 += 8; } bitcount += n; } /* ######################################################################### */ /* OUTPUT a 4 bit nybble */ static void output_nybble(char *outfile, int bits) { /* * insert 4 bits at end of buffer */ buffer2 = (buffer2<<4) | ( bits & 15 ); bits_to_go2 -= 4; if (bits_to_go2 <= 0) { /* * buffer2 full, put out top 8 bits */ outfile[noutchar] = ((buffer2>>(-bits_to_go2)) & 0xff); if (noutchar < noutmax) noutchar++; bits_to_go2 += 8; } bitcount += 4; } /* ############################################################################ */ /* OUTPUT array of 4 BITS */ static void output_nnybble(char *outfile, int n, unsigned char array[]) { /* pack the 4 lower bits in each element of the array into the outfile array */ int ii, jj, kk = 0, shift; if (n == 1) { output_nybble(outfile, (int) array[0]); return; } /* forcing byte alignment doesn;t help, and even makes it go slightly slower if (bits_to_go2 != 8) output_nbits(outfile, kk, bits_to_go2); */ if (bits_to_go2 <= 4) { /* just room for 1 nybble; write it out separately */ output_nybble(outfile, array[0]); kk++; /* index to next array element */ if (n == 2) /* only 1 more nybble to write out */ { output_nybble(outfile, (int) array[1]); return; } } /* bits_to_go2 is now in the range 5 - 8 */ shift = 8 - bits_to_go2; /* now write out pairs of nybbles; this does not affect value of bits_to_go2 */ jj = (n - kk) / 2; if (bits_to_go2 == 8) { /* special case if nybbles are aligned on byte boundary */ /* this actually seems to make very little differnece in speed */ buffer2 = 0; for (ii = 0; ii < jj; ii++) { outfile[noutchar] = ((array[kk] & 15)<<4) | (array[kk+1] & 15); kk += 2; noutchar++; } } else { for (ii = 0; ii < jj; ii++) { buffer2 = (buffer2<<8) | ((array[kk] & 15)<<4) | (array[kk+1] & 15); kk += 2; /* buffer2 full, put out top 8 bits */ outfile[noutchar] = ((buffer2>>shift) & 0xff); noutchar++; } } bitcount += (8 * (ii - 1)); /* write out last odd nybble, if present */ if (kk != n) output_nybble(outfile, (int) array[n - 1]); return; } /* ######################################################################### */ /* FLUSH OUT THE LAST BITS */ static void done_outputing_bits(char *outfile) { if(bits_to_go2 < 8) { /* putc(buffer2<nqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * initial bit buffer */ b = 0; bitbuffer = 0; bits_to_go3 = 0; /* * on first pass copy A to scratch array */ qtree_onebit(a,n,nqx,nqy,scratch,bit); nx = (nqx+1)>>1; ny = (nqy+1)>>1; /* * copy non-zero values to output buffer, which will be written * in reverse order */ if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { /* * quadtree is expanding data, * change warning code and just fill buffer with bit-map */ write_bdirect(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } /* * do log2n reductions */ for (k = 1; k>1; ny = (ny+1)>>1; if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { write_bdirect(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } } /* * OK, we've got the code in buffer * Write quadtree warning code, then write buffer in reverse order */ output_nybble(outfile,0xF); if (b==0) { if (bits_to_go3>0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<=0; i--) { output_nbits(outfile,buffer[i],8); } } bitplane_done: ; } free(buffer); free(scratch); return(0); } /* ######################################################################### */ static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes) { /* LONGLONG a[]; int n; physical dimension of row in a int nqx; length of row int nqy; length of column (<=n) int nbitplanes; number of bit planes to output */ int log2n, i, k, bit, b, nqmax, nqx2, nqy2, nx, ny; int bmax; /* this potentially needs to be made a 64-bit int to support large arrays */ unsigned char *scratch, *buffer; /* * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 */ nqmax = (nqx>nqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * initial bit buffer */ b = 0; bitbuffer = 0; bits_to_go3 = 0; /* * on first pass copy A to scratch array */ qtree_onebit64(a,n,nqx,nqy,scratch,bit); nx = (nqx+1)>>1; ny = (nqy+1)>>1; /* * copy non-zero values to output buffer, which will be written * in reverse order */ if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { /* * quadtree is expanding data, * change warning code and just fill buffer with bit-map */ write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } /* * do log2n reductions */ for (k = 1; k>1; ny = (ny+1)>>1; if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } } /* * OK, we've got the code in buffer * Write quadtree warning code, then write buffer in reverse order */ output_nybble(outfile,0xF); if (b==0) { if (bits_to_go3>0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<=0; i--) { output_nbits(outfile,buffer[i],8); } } bitplane_done: ; } free(buffer); free(scratch); return(0); } /* ######################################################################### */ /* * copy non-zero codes from array to buffer */ static int bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax) { int i; for (i = 0; i < n; i++) { if (a[i] != 0) { /* * add Huffman code for a[i] to buffer */ bitbuffer |= code[a[i]] << bits_to_go3; bits_to_go3 += ncode[a[i]]; if (bits_to_go3 >= 8) { buffer[*b] = bitbuffer & 0xFF; *b += 1; /* * return warning code if we fill buffer */ if (*b >= bmax) return(1); bitbuffer >>= 8; bits_to_go3 -= 8; } } } return(0); } /* ######################################################################### */ /* * Do first quadtree reduction step on bit BIT of array A. * Results put into B. * */ static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit) { int i, j, k; int b0, b1, b2, b3; int s10, s00; /* * use selected bit to get amount to shift */ b0 = 1<> bit; k += 1; s00 += 2; s10 += 2; } if (j < ny) { /* * row size is odd, do last element in row * s00+1,s10+1 are off edge */ b[k] = ( ((a[s10 ]<<1) & b1) | ((a[s00 ]<<3) & b3) ) >> bit; k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10,s10+1 are off edge */ s00 = n*i; for (j = 0; j> bit; k += 1; s00 += 2; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ b[k] = ( ((a[s00 ]<<3) & b3) ) >> bit; k += 1; } } } /* ######################################################################### */ /* * Do first quadtree reduction step on bit BIT of array A. * Results put into B. * */ static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit) { int i, j, k; LONGLONG b0, b1, b2, b3; int s10, s00; /* * use selected bit to get amount to shift */ b0 = ((LONGLONG) 1)<> bit); k += 1; s00 += 2; s10 += 2; } if (j < ny) { /* * row size is odd, do last element in row * s00+1,s10+1 are off edge */ b[k] = (unsigned char) (( ((a[s10 ]<<1) & b1) | ((a[s00 ]<<3) & b3) ) >> bit); k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10,s10+1 are off edge */ s00 = n*i; for (j = 0; j> bit); k += 1; s00 += 2; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ b[k] = (unsigned char) (( ((a[s00 ]<<3) & b3) ) >> bit); k += 1; } } } /* ######################################################################### */ /* * do one quadtree reduction step on array a * results put into b (which may be the same as a) */ static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]) { int i, j, k; int s10, s00; k = 0; /* k is index of b[i/2,j/2] */ for (i = 0; i. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, especially those whose name start with YY_ or yy_. They are private implementation details that can be changed or removed. */ #ifndef YY_FITS_PARSER_YY_EVAL_TAB_H_INCLUDED # define YY_FITS_PARSER_YY_EVAL_TAB_H_INCLUDED /* Debug traces. */ #ifndef FITS_PARSER_YYDEBUG # if defined YYDEBUG #if YYDEBUG # define FITS_PARSER_YYDEBUG 1 # else # define FITS_PARSER_YYDEBUG 0 # endif # else /* ! defined YYDEBUG */ # define FITS_PARSER_YYDEBUG 0 # endif /* ! defined YYDEBUG */ #endif /* ! defined FITS_PARSER_YYDEBUG */ #if FITS_PARSER_YYDEBUG extern int fits_parser_yydebug; #endif /* Token kinds. */ #ifndef FITS_PARSER_YYTOKENTYPE # define FITS_PARSER_YYTOKENTYPE enum fits_parser_yytokentype { FITS_PARSER_YYEMPTY = -2, FITS_PARSER_YYEOF = 0, /* "end of file" */ FITS_PARSER_YYerror = 256, /* error */ FITS_PARSER_YYUNDEF = 257, /* "invalid token" */ BOOLEAN = 258, /* BOOLEAN */ LONG = 259, /* LONG */ DOUBLE = 260, /* DOUBLE */ STRING = 261, /* STRING */ BITSTR = 262, /* BITSTR */ FUNCTION = 263, /* FUNCTION */ BFUNCTION = 264, /* BFUNCTION */ IFUNCTION = 265, /* IFUNCTION */ GTIFILTER = 266, /* GTIFILTER */ GTIOVERLAP = 267, /* GTIOVERLAP */ GTIFIND = 268, /* GTIFIND */ REGFILTER = 269, /* REGFILTER */ COLUMN = 270, /* COLUMN */ BCOLUMN = 271, /* BCOLUMN */ SCOLUMN = 272, /* SCOLUMN */ BITCOL = 273, /* BITCOL */ ROWREF = 274, /* ROWREF */ NULLREF = 275, /* NULLREF */ SNULLREF = 276, /* SNULLREF */ OR = 277, /* OR */ AND = 278, /* AND */ EQ = 279, /* EQ */ NE = 280, /* NE */ GT = 281, /* GT */ LT = 282, /* LT */ LTE = 283, /* LTE */ GTE = 284, /* GTE */ XOR = 285, /* XOR */ POWER = 286, /* POWER */ NOT = 287, /* NOT */ INTCAST = 288, /* INTCAST */ FLTCAST = 289, /* FLTCAST */ UMINUS = 290, /* UMINUS */ ACCUM = 291, /* ACCUM */ DIFF = 292 /* DIFF */ }; typedef enum fits_parser_yytokentype fits_parser_yytoken_kind_t; #endif /* Value type. */ #if ! defined FITS_PARSER_YYSTYPE && ! defined FITS_PARSER_YYSTYPE_IS_DECLARED union FITS_PARSER_YYSTYPE { #line 212 "eval.y" int Node; /* Index of Node */ double dbl; /* real value */ long lng; /* integer value */ char log; /* logical value */ char str[MAX_STRLEN]; /* string value */ #line 117 "eval_tab.h" }; typedef union FITS_PARSER_YYSTYPE FITS_PARSER_YYSTYPE; # define FITS_PARSER_YYSTYPE_IS_TRIVIAL 1 # define FITS_PARSER_YYSTYPE_IS_DECLARED 1 #endif int fits_parser_yyparse (yyscan_t scanner, ParseData *lParse); #endif /* !YY_FITS_PARSER_YY_EVAL_TAB_H_INCLUDED */ cfitsio-4.3.1/Makefile.in0000644000225700000360000001366014335036354014526 0ustar cagordonlhea# # Makefile for cfitsio library: # # Oct-96 : original version by # # JDD/WDP # NASA GSFC # Oct 1996 # # 25-Jan-01 : removed conditional drvrsmem.c compilation because this # is now handled within the source file itself. # 09-Mar-98 : modified to conditionally compile drvrsmem.c. Also # changes to target all (deleted clean), added DEFS, LIBS, added # DEFS to .c.o, added SOURCES_SHMEM and MY_SHMEM, expanded getcol* # and putcol* in SOURCES, modified OBJECTS, mv changed to /bin/mv # (to bypass aliasing), cp changed to /bin/cp, add smem and # testprog targets. See also changes and comments in configure.in # Default library name: PACKAGE = cfitsio # CFITSIO version numbers: CFITSIO_MAJOR = @CFITSIO_MAJOR@ CFITSIO_MINOR = @CFITSIO_MINOR@ CFITSIO_MICRO = @CFITSIO_MICRO@ CFITSIO_SONAME = @CFITSIO_SONAME@ prefix = @prefix@ exec_prefix = @exec_prefix@ CFITSIO_BIN = ${DESTDIR}@bindir@ CFITSIO_LIB = ${DESTDIR}@libdir@ CFITSIO_INCLUDE = ${DESTDIR}@includedir@ INSTALL_DIRS = ${DESTDIR}@INSTALL_ROOT@ ${CFITSIO_INCLUDE} ${CFITSIO_LIB} ${CFITSIO_LIB}/pkgconfig SHELL = /bin/sh ARCHIVE = @ARCHIVE@ RANLIB = @RANLIB@ CC = @CC@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ SSE_FLAGS = @SSE_FLAGS@ FC = @FC@ LDFLAGS = @LDFLAGS@ LDFLAGS_BIN = @LDFLAGS_BIN@ DEFS = @DEFS@ LIBS = @LIBS@ LIBS_CURL = @LIBS_CURL@ FLEX = flex BISON = bison SHLIB_LD = @SHLIB_LD@ SHLIB_SUFFIX = @SHLIB_SUFFIX@ CFITSIO_SHLIB = @CFITSIO_SHLIB@ CFITSIO_SHLIB_SONAME = @CFITSIO_SHLIB_SONAME@ CORE_SOURCES = buffers.c cfileio.c checksum.c drvrfile.c drvrmem.c \ drvrnet.c drvrsmem.c editcol.c edithdu.c eval_l.c \ eval_y.c eval_f.c fitscore.c getcol.c getcolb.c getcold.c getcole.c \ getcoli.c getcolj.c getcolk.c getcoll.c getcols.c getcolsb.c \ getcoluk.c getcolui.c getcoluj.c getkey.c group.c grparser.c \ histo.c iraffits.c \ modkey.c putcol.c putcolb.c putcold.c putcole.c putcoli.c \ putcolj.c putcolk.c putcoluk.c putcoll.c putcols.c putcolsb.c \ putcolu.c putcolui.c putcoluj.c putkey.c region.c scalnull.c \ swapproc.c wcssub.c wcsutil.c imcompress.c quantize.c ricecomp.c \ pliocomp.c fits_hcompress.c fits_hdecompress.c \ simplerng.c @GSIFTP_SRC@ ZLIB_SOURCES = zcompress.c zuncompress.c SOURCES = ${CORE_SOURCES} ${ZLIB_SOURCES} @F77_WRAPPERS@ OBJECTS = ${SOURCES:.c=.o} CORE_OBJECTS = ${CORE_SOURCES:.c=.o} ${ZLIB_SOURCES:.c=.o} FITSIO_SRC = f77_wrap1.c f77_wrap2.c f77_wrap3.c f77_wrap4.c # ============ description of all targets ============= # - <<-- ignore error code all: @if [ "x${FC}" = x ]; then \ ${MAKE} all-nofitsio; \ else \ ${MAKE} stand_alone; \ fi all-nofitsio: ${MAKE} stand_alone "FITSIO_SRC=" stand_alone: lib${PACKAGE}.a shared lib${PACKAGE}.a: ${OBJECTS} ${ARCHIVE} $@ ${OBJECTS}; \ ${RANLIB} $@; shared: lib${PACKAGE}${SHLIB_SUFFIX} lib${PACKAGE}${SHLIB_SUFFIX}: ${OBJECTS} ${SHLIB_LD} ${LDFLAGS} -o ${CFITSIO_SHLIB} ${OBJECTS} -lm ${LIBS_CURL} ${LIBS} @if [ "x${CFITSIO_SHLIB_SONAME}" != x ]; then \ ln -sf ${CFITSIO_SHLIB} ${CFITSIO_SHLIB_SONAME}; \ ln -sf ${CFITSIO_SHLIB_SONAME} $@; \ fi install: lib${PACKAGE}.a ${INSTALL_DIRS} @for lib in lib${PACKAGE}.a lib${PACKAGE}${SHLIB_SUFFIX} \ ${CFITSIO_SHLIB} ${CFITSIO_SHLIB_SONAME}; do \ if [ -f $$lib ]; then \ echo "/bin/rm -f ${CFITSIO_LIB}/$$lib"; \ /bin/rm -f ${CFITSIO_LIB}/$$lib; \ echo "/bin/cp -a $$lib ${CFITSIO_LIB}"; \ /bin/cp -a $$lib ${CFITSIO_LIB}; \ fi; \ done /bin/cp fitsio.h fitsio2.h longnam.h drvrsmem.h ${CFITSIO_INCLUDE} /bin/cp cfitsio.pc ${CFITSIO_LIB}/pkgconfig @for task in ${FPACK_UTILS} ${UTILS}; do \ if [ -f $$task ]; then \ if [ ! -d ${CFITSIO_BIN} ]; then mkdir -p ${CFITSIO_BIN}; fi; \ echo "/bin/cp $$task ${CFITSIO_BIN}"; \ /bin/cp $$task ${CFITSIO_BIN}; \ fi; \ done .c.o: ${CC} -c -o ${ #include #include #include #define get_char() get_byte() /* gzip.h -- common declarations for all gzip modules */ #define OF(args) args typedef void *voidp; #define memzero(s, n) memset ((voidp)(s), 0, (n)) typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; /* private version of MIN function */ #define MINZIP(a,b) ((a) <= (b) ? (a) : (b)) /* Return codes from gzip */ #define OK 0 #define ERROR 1 #define COMPRESSED 1 #define DEFLATED 8 #define INBUFSIZ 0x8000 /* input buffer size */ #define INBUF_EXTRA 64 /* required by unlzw() */ #define OUTBUFSIZ 16384 /* output buffer size */ #define OUTBUF_EXTRA 2048 /* required by unlzw() */ #define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ #define WSIZE 0x8000 /* window size--must be a power of two, and */ #define DECLARE(type, array, size) type array[size] #define tab_suffix window #define tab_prefix prev /* hash link (see deflate.c) */ #define head (prev+WSIZE) /* hash head (see deflate.c) */ #define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */ #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) /* Diagnostic functions */ # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) /* lzw.h -- define the lzw functions. */ #ifndef BITS # define BITS 16 #endif #define INIT_BITS 9 /* Initial number of bits per code */ #define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ #define BLOCK_MODE 0x80 #define LZW_RESERVED 0x60 /* reserved bits */ #define CLEAR 256 /* flush the dictionary */ #define FIRST (CLEAR+1) /* first free entry */ /* prototypes */ #define local static void ffpmsg(const char *err_message); local int fill_inbuf OF((int eof_ok)); local void write_buf OF((voidp buf, unsigned cnt)); local void error OF((char *m)); local int unlzw OF((FILE *in, FILE *out)); typedef int file_t; /* Do not use stdio */ int (*work) OF((FILE *infile, FILE *outfile)) = unlzw; /* function to call */ local void error OF((char *m)); /* global buffers */ static DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); static DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); static DECLARE(ush, d_buf, DIST_BUFSIZE); static DECLARE(uch, window, 2L*WSIZE); #ifndef MAXSEG_64K static DECLARE(ush, tab_prefix, 1L< 0) return(*status); /* save input parameters into global variables */ ifname[0] = '\0'; strncat(ifname, filename, 127); ifd = indiskfile; memptr = (void **) buffptr; memsize = buffsize; realloc_fn = mem_realloc; /* clear input and output buffers */ insize = inptr = 0; bytes_in = bytes_out = 0L; magic[0] = (char)get_byte(); magic[1] = (char)get_byte(); if (memcmp(magic, LZW_MAGIC, 2) != 0) { error("ERROR: input .Z file is in unrecognized compression format.\n"); return(-1); } work = unlzw; method = COMPRESSED; last_member = 1; /* do the uncompression */ if ((*work)(ifd, ofd) != OK) { method = -1; /* force cleanup */ *status = 414; /* report some sort of decompression error */ } if (filesize) *filesize = bytes_out; return(*status); } /*=========================================================================*/ /*=========================================================================*/ /* this marks the begining of the original file 'unlzw.c' */ /*=========================================================================*/ /*=========================================================================*/ /* unlzw.c -- decompress files in LZW format. * The code in this file is directly derived from the public domain 'compress' * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, * Ken Turkowski, Dave Mack and Peter Jannesen. */ typedef unsigned char char_type; typedef long code_int; typedef unsigned long count_int; typedef unsigned short count_short; typedef unsigned long cmp_code_int; #define MAXCODE(n) (1L << (n)) #ifndef REGISTERS # define REGISTERS 2 #endif #define REG1 #define REG2 #define REG3 #define REG4 #define REG5 #define REG6 #define REG7 #define REG8 #define REG9 #define REG10 #define REG11 #define REG12 #define REG13 #define REG14 #define REG15 #define REG16 #if REGISTERS >= 1 # undef REG1 # define REG1 register #endif #if REGISTERS >= 2 # undef REG2 # define REG2 register #endif #if REGISTERS >= 3 # undef REG3 # define REG3 register #endif #if REGISTERS >= 4 # undef REG4 # define REG4 register #endif #if REGISTERS >= 5 # undef REG5 # define REG5 register #endif #if REGISTERS >= 6 # undef REG6 # define REG6 register #endif #if REGISTERS >= 7 # undef REG7 # define REG7 register #endif #if REGISTERS >= 8 # undef REG8 # define REG8 register #endif #if REGISTERS >= 9 # undef REG9 # define REG9 register #endif #if REGISTERS >= 10 # undef REG10 # define REG10 register #endif #if REGISTERS >= 11 # undef REG11 # define REG11 register #endif #if REGISTERS >= 12 # undef REG12 # define REG12 register #endif #if REGISTERS >= 13 # undef REG13 # define REG13 register #endif #if REGISTERS >= 14 # undef REG14 # define REG14 register #endif #if REGISTERS >= 15 # undef REG15 # define REG15 register #endif #if REGISTERS >= 16 # undef REG16 # define REG16 register #endif #ifndef BYTEORDER # define BYTEORDER 0000 #endif #ifndef NOALLIGN # define NOALLIGN 0 #endif union bytes { long word; struct { #if BYTEORDER == 4321 char_type b1; char_type b2; char_type b3; char_type b4; #else #if BYTEORDER == 1234 char_type b4; char_type b3; char_type b2; char_type b1; #else # undef BYTEORDER int dummy; #endif #endif } bytes; }; #if BYTEORDER == 4321 && NOALLIGN == 1 # define input(b,o,c,n,m){ \ (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \ (o) += (n); \ } #else # define input(b,o,c,n,m){ \ REG1 char_type *p = &(b)[(o)>>3]; \ (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \ ((long)(p[2])<<16))>>((o)&0x7))&(m); \ (o) += (n); \ } #endif #ifndef MAXSEG_64K /* DECLARE(ush, tab_prefix, (1<>1] # define clear_tab_prefixof() \ memzero(tab_prefix0, 128), \ memzero(tab_prefix1, 128); #endif #define de_stack ((char_type *)(&d_buf[DIST_BUFSIZE-1])) #define tab_suffixof(i) tab_suffix[i] int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */ /* ============================================================================ * Decompress in to out. This routine adapts to the codes in the * file building the "string" table on-the-fly; requiring no table to * be stored in the compressed file. * IN assertions: the buffer inbuf contains already the beginning of * the compressed data, from offsets iptr to insize-1 included. * The magic header has already been checked and skipped. * bytes_in and bytes_out have been initialized. */ local int unlzw(FILE *in, FILE *out) /* input and output file descriptors */ { REG2 char_type *stackp; REG3 code_int code; REG4 int finchar; REG5 code_int oldcode; REG6 code_int incode; REG7 long inbits; REG8 long posbits; REG9 int outpos; /* REG10 int insize; (global) */ REG11 unsigned bitmask; REG12 code_int free_ent; REG13 code_int maxcode; REG14 code_int maxmaxcode; REG15 int n_bits; REG16 int rsize; ofd = out; #ifdef MAXSEG_64K tab_prefix[0] = tab_prefix0; tab_prefix[1] = tab_prefix1; #endif maxbits = get_byte(); block_mode = maxbits & BLOCK_MODE; if ((maxbits & LZW_RESERVED) != 0) { error( "warning, unknown flags in unlzw decompression"); } maxbits &= BIT_MASK; maxmaxcode = MAXCODE(maxbits); if (maxbits > BITS) { error("compressed with too many bits; cannot handle file"); exit_code = ERROR; return ERROR; } rsize = insize; maxcode = MAXCODE(n_bits = INIT_BITS)-1; bitmask = (1<= 0 ; --code) { tab_suffixof(code) = (char_type)code; } do { REG1 int i; int e; int o; resetbuf: e = insize-(o = (posbits>>3)); for (i = 0 ; i < e ; ++i) { inbuf[i] = inbuf[i+o]; } insize = e; posbits = 0; if (insize < INBUF_EXTRA) { /* modified to use fread instead of read - WDP 10/22/97 */ /* if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) { */ if ((rsize = fread((char*)inbuf+insize, 1, INBUFSIZ, in)) == EOF) { error("unexpected end of file"); exit_code = ERROR; return ERROR; } insize += rsize; bytes_in += (ulg)rsize; } inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 : ((long)insize<<3)-(n_bits-1)); while (inbits > posbits) { if (free_ent > maxcode) { posbits = ((posbits-1) + ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3))); ++n_bits; if (n_bits == maxbits) { maxcode = maxmaxcode; } else { maxcode = MAXCODE(n_bits)-1; } bitmask = (1<= 256) { error("corrupt input."); exit_code = ERROR; return ERROR; } outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code)); continue; } if (code == CLEAR && block_mode) { clear_tab_prefixof(); free_ent = FIRST - 1; posbits = ((posbits-1) + ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3))); maxcode = MAXCODE(n_bits = INIT_BITS)-1; bitmask = (1<= free_ent) { /* Special case for KwKwK string. */ if (code > free_ent) { if (outpos > 0) { write_buf((char*)outbuf, outpos); bytes_out += (ulg)outpos; } error("corrupt input."); exit_code = ERROR; return ERROR; } *--stackp = (char_type)finchar; code = oldcode; } while ((cmp_code_int)code >= (cmp_code_int)256) { /* Generate output characters in reverse order */ *--stackp = tab_suffixof(code); code = tab_prefixof(code); } *--stackp = (char_type)(finchar = tab_suffixof(code)); /* And put them out in forward order */ { /* REG1 int i; already defined above (WDP) */ if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) { do { if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos; if (i > 0) { memcpy(outbuf+outpos, stackp, i); outpos += i; } if (outpos >= OUTBUFSIZ) { write_buf((char*)outbuf, outpos); bytes_out += (ulg)outpos; outpos = 0; } stackp+= i; } while ((i = (de_stack-stackp)) > 0); } else { memcpy(outbuf+outpos, stackp, i); outpos += i; } } if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */ tab_prefixof(code) = (unsigned short)oldcode; tab_suffixof(code) = (char_type)finchar; free_ent = code+1; } oldcode = incode; /* Remember previous code. */ } } while (rsize != 0); if (outpos > 0) { write_buf((char*)outbuf, outpos); bytes_out += (ulg)outpos; } return OK; } /* ========================================================================*/ /* this marks the start of the code from 'util.c' */ local int fill_inbuf(int eof_ok) /* set if EOF acceptable as a result */ { int len; /* Read as much as possible from file */ insize = 0; do { len = fread((char*)inbuf+insize, 1, INBUFSIZ-insize, ifd); if (len == 0 || len == EOF) break; insize += len; } while (insize < INBUFSIZ); if (insize == 0) { if (eof_ok) return EOF; error("unexpected end of file"); exit_code = ERROR; return ERROR; } bytes_in += (ulg)insize; inptr = 1; return inbuf[0]; } /* =========================================================================== */ local void write_buf(voidp buf, unsigned cnt) /* copy buffer into memory; allocate more memory if required*/ { if (!realloc_fn) { /* append buffer to file */ /* added 'unsigned' to get rid of compiler warning (WDP 1/1/99) */ if ((unsigned long) fwrite(buf, 1, cnt, ofd) != cnt) { error ("failed to write buffer to uncompressed output file (write_buf)"); exit_code = ERROR; return; } } else { /* get more memory if current buffer is too small */ if (bytes_out + cnt > *memsize) { *memptr = realloc_fn(*memptr, bytes_out + cnt); *memsize = bytes_out + cnt; /* new memory buffer size */ if (!(*memptr)) { error("malloc failed while uncompressing (write_buf)"); exit_code = ERROR; return; } } /* copy into memory buffer */ memcpy((char *) *memptr + bytes_out, (char *) buf, cnt); } } /* ======================================================================== */ local void error(char *m) /* Error handler */ { ffpmsg(ifname); ffpmsg(m); } cfitsio-4.3.1/imcompress.c0000644000225700000360000135071314214470324015005 0ustar cagordonlhea# include # include # include # include # include # include # include "fitsio2.h" #define NULL_VALUE -2147483647 /* value used to represent undefined pixels */ #define ZERO_VALUE -2147483646 /* value used to represent zero-valued pixels */ /* nearest integer function */ # define NINT(x) ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5)) /* special quantize level value indicates that floating point image pixels */ /* should not be quantized and instead losslessly compressed (with GZIP) */ #define NO_QUANTIZE 9999 /* string array for storing the individual column compression stats */ char results[999][30]; float *fits_rand_value = 0; int imcomp_write_nocompress_tile(fitsfile *outfptr, long row, int datatype, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int *status); int imcomp_convert_tile_tshort(fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, double actual_bzero, int *intlength, int *status); int imcomp_convert_tile_tushort(fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status); int imcomp_convert_tile_tint(fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status); int imcomp_convert_tile_tuint(fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status); int imcomp_convert_tile_tbyte(fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status); int imcomp_convert_tile_tsbyte(fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status); int imcomp_convert_tile_tfloat(fitsfile *outfptr, long row, void *tiledata, long tilelen, long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero,int *status); int imcomp_convert_tile_tdouble(fitsfile *outfptr, long row, void *tiledata, long tilelen, long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero, int *status); static int unquantize_i1r4(long row, unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - which subtractive dither method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ float nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ float *output, /* O - array of converted pixels */ int *status); /* IO - error status */ static int unquantize_i2r4(long row, short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - which subtractive dither method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ float nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ float *output, /* O - array of converted pixels */ int *status); /* IO - error status */ static int unquantize_i4r4(long row, INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - which subtractive dither method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ float nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ float *output, /* O - array of converted pixels */ int *status); /* IO - error status */ static int unquantize_i1r8(long row, unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - which subtractive dither method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ double nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ double *output, /* O - array of converted pixels */ int *status); /* IO - error status */ static int unquantize_i2r8(long row, short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - which subtractive dither method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ double nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ double *output, /* O - array of converted pixels */ int *status); /* IO - error status */ static int unquantize_i4r8(long row, INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - which subtractive dither method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ double nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ double *output, /* O - array of converted pixels */ int *status); /* IO - error status */ static int imcomp_float2nan(float *indata, long tilelen, int *outdata, float nullflagval, int *status); static int imcomp_double2nan(double *indata, long tilelen, LONGLONG *outdata, double nullflagval, int *status); static int fits_read_write_compressed_img(fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the array to be returned */ LONGLONG *infpixel, /* I - 'bottom left corner' of the subsection */ LONGLONG *inlpixel, /* I - 'top right corner' of the subsection */ long *ininc, /* I - increment to be applied in each dimension */ int nullcheck, /* I - 0 for no null checking */ /* 1: set undefined pixels = nullval */ void *nullval, /* I - value for undefined pixels */ int *anynul, /* O - set to 1 if any values are null; else 0 */ fitsfile *outfptr, /* I - FITS file pointer */ int *status); static int fits_shuffle_8bytes(char *heap, LONGLONG length, int *status); static int fits_shuffle_4bytes(char *heap, LONGLONG length, int *status); static int fits_shuffle_2bytes(char *heap, LONGLONG length, int *status); static int fits_unshuffle_8bytes(char *heap, LONGLONG length, int *status); static int fits_unshuffle_4bytes(char *heap, LONGLONG length, int *status); static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status); static int fits_int_to_longlong_inplace(int *intarray, long length, int *status); static int fits_short_to_int_inplace(short *intarray, long length, int shift, int *status); static int fits_ushort_to_int_inplace(unsigned short *intarray, long length, int shift, int *status); static int fits_sbyte_to_int_inplace(signed char *intarray, long length, int *status); static int fits_ubyte_to_int_inplace(unsigned char *intarray, long length, int *status); static int fits_calc_tile_rows(long *tlpixel, long *tfpixel, int ndim, long *trowsize, long *ntrows, int *status); /* only used for diagnoitic purposes */ /* int fits_get_case(int *c1, int*c2, int*c3); */ /*---------------------------------------------------------------------------*/ int fits_init_randoms(void) { /* initialize an array of random numbers */ int ii; double a = 16807.0; double m = 2147483647.0; double temp, seed; FFLOCK; if (fits_rand_value) { FFUNLOCK; return(0); /* array is already initialized */ } /* allocate array for the random number sequence */ /* THIS MEMORY IS NEVER FREED */ fits_rand_value = calloc(N_RANDOM, sizeof(float)); if (!fits_rand_value) { FFUNLOCK; return(MEMORY_ALLOCATION); } /* We need a portable algorithm that anyone can use to generate this exact same sequence of random number. The C 'rand' function is not suitable because it is not available to Fortran or Java programmers. Instead, use a well known simple algorithm published here: "Random number generators: good ones are hard to find", Communications of the ACM, Volume 31 , Issue 10 (October 1988) Pages: 1192 - 1201 */ /* initialize the random numbers */ seed = 1; for (ii = 0; ii < N_RANDOM; ii++) { temp = a * seed; seed = temp -m * ((int) (temp / m) ); fits_rand_value[ii] = (float) (seed / m); } FFUNLOCK; /* IMPORTANT NOTE: the 10000th seed value must have the value 1043618065 if the algorithm has been implemented correctly */ if ( (int) seed != 1043618065) { ffpmsg("fits_init_randoms generated incorrect random number sequence"); return(1); } else { return(0); } } /*--------------------------------------------------------------------------*/ void bz_internal_error(int errcode) { /* external function declared by the bzip2 code in bzlib_private.h */ ffpmsg("bzip2 returned an internal error"); ffpmsg("This should never happen"); return; } /*--------------------------------------------------------------------------*/ int fits_set_compression_type(fitsfile *fptr, /* I - FITS file pointer */ int ctype, /* image compression type code; */ /* allowed values: RICE_1, GZIP_1, GZIP_2, PLIO_1, */ /* HCOMPRESS_1, BZIP2_1, and NOCOMPRESS */ int *status) /* IO - error status */ { /* This routine specifies the image compression algorithm that should be used when writing a FITS image. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ if (ctype != RICE_1 && ctype != GZIP_1 && ctype != GZIP_2 && ctype != PLIO_1 && ctype != HCOMPRESS_1 && ctype != BZIP2_1 && ctype != NOCOMPRESS && ctype != 0) { ffpmsg("unknown compression algorithm (fits_set_compression_type)"); *status = DATA_COMPRESSION_ERR; } else { (fptr->Fptr)->request_compress_type = ctype; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_tile_dim(fitsfile *fptr, /* I - FITS file pointer */ int ndim, /* number of dimensions in the compressed image */ long *dims, /* size of image compression tile in each dimension */ /* default tile size = (NAXIS1, 1, 1, ...) */ int *status) /* IO - error status */ { /* This routine specifies the size (dimension) of the image compression tiles that should be used when writing a FITS image. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ int ii; if (ndim < 0 || ndim > MAX_COMPRESS_DIM) { *status = BAD_DIMEN; ffpmsg("illegal number of tile dimensions (fits_set_tile_dim)"); return(*status); } for (ii = 0; ii < ndim; ii++) { (fptr->Fptr)->request_tilesize[ii] = dims[ii]; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_quantize_level(fitsfile *fptr, /* I - FITS file pointer */ float qlevel, /* floating point quantization level */ int *status) /* IO - error status */ { /* This routine specifies the value of the quantization level, q, that should be used when compressing floating point images. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ if (qlevel == 0.) { /* this means don't quantize the floating point values. Instead, */ /* the floating point values will be losslessly compressed */ (fptr->Fptr)->request_quantize_level = NO_QUANTIZE; } else { (fptr->Fptr)->request_quantize_level = qlevel; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_quantize_method(fitsfile *fptr, /* I - FITS file pointer */ int method, /* quantization method */ int *status) /* IO - error status */ { /* This routine specifies what type of dithering (randomization) should be performed when quantizing floating point images to integer prior to compression. A value of -1 means do no dithering. A value of 0 means use the default SUBTRACTIVE_DITHER_1 (which is equivalent to dither = 1). A value of 2 means use SUBTRACTIVE_DITHER_2. */ if (method < -1 || method > 2) { ffpmsg("illegal dithering value (fits_set_quantize_method)"); *status = DATA_COMPRESSION_ERR; } else { if (method == 0) method = 1; (fptr->Fptr)->request_quantize_method = method; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_quantize_dither(fitsfile *fptr, /* I - FITS file pointer */ int dither, /* dither type */ int *status) /* IO - error status */ { /* the name of this routine has changed. This is kept here only for backwards compatibility for any software that may be calling the old routine. */ fits_set_quantize_method(fptr, dither, status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_dither_seed(fitsfile *fptr, /* I - FITS file pointer */ int seed, /* random dithering seed value (1 to 10000) */ int *status) /* IO - error status */ { /* This routine specifies the value of the offset that should be applied when calculating the random dithering when quantizing floating point iamges. A random offset should be applied to each image to avoid quantization effects when taking the difference of 2 images, or co-adding a set of images. Without this random offset, the corresponding pixel in every image will have exactly the same dithering. offset = 0 means use the default random dithering based on system time offset = negative means randomly chose dithering based on 1st tile checksum offset = [1 - 10000] means use that particular dithering pattern */ /* if positive, ensure that the value is in the range 1 to 10000 */ if (seed > 10000) { ffpmsg("illegal dithering seed value (fits_set_dither_seed)"); *status = DATA_COMPRESSION_ERR; } else { (fptr->Fptr)->request_dither_seed = seed; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_dither_offset(fitsfile *fptr, /* I - FITS file pointer */ int offset, /* random dithering offset value (1 to 10000) */ int *status) /* IO - error status */ { /* The name of this routine has changed. This is kept just for backwards compatibility with any software that calls the old name */ fits_set_dither_seed(fptr, offset, status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_noise_bits(fitsfile *fptr, /* I - FITS file pointer */ int noisebits, /* noise_bits parameter value */ /* (default = 4) */ int *status) /* IO - error status */ { /* ******************************************************************** ******************************************************************** THIS ROUTINE IS PROVIDED ONLY FOR BACKWARDS COMPATIBILITY; ALL NEW SOFTWARE SHOULD CALL fits_set_quantize_level INSTEAD ******************************************************************** ******************************************************************** This routine specifies the value of the noice_bits parameter that should be used when compressing floating point images. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. Feb 2008: the "noisebits" parameter has been replaced with the more general "quantize level" parameter. */ float qlevel; if (noisebits < 1 || noisebits > 16) { *status = DATA_COMPRESSION_ERR; ffpmsg("illegal number of noise bits (fits_set_noise_bits)"); return(*status); } qlevel = (float) pow (2., (double)noisebits); fits_set_quantize_level(fptr, qlevel, status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_hcomp_scale(fitsfile *fptr, /* I - FITS file pointer */ float scale, /* hcompress scale parameter value */ /* (default = 0.) */ int *status) /* IO - error status */ { /* This routine specifies the value of the hcompress scale parameter. */ (fptr->Fptr)->request_hcomp_scale = scale; return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_hcomp_smooth(fitsfile *fptr, /* I - FITS file pointer */ int smooth, /* hcompress smooth parameter value */ /* if scale > 1 and smooth != 0, then */ /* the image will be smoothed when it is */ /* decompressed to remove some of the */ /* 'blockiness' in the image produced */ /* by the lossy compression */ int *status) /* IO - error status */ { /* This routine specifies the value of the hcompress scale parameter. */ (fptr->Fptr)->request_hcomp_smooth = smooth; return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_lossy_int(fitsfile *fptr, /* I - FITS file pointer */ int lossy_int, /* I - True (!= 0) or False (0) */ int *status) /* IO - error status */ { /* This routine specifies whether images with integer pixel values should quantized and compressed the same way float images are compressed. The default is to not do this, and instead apply a lossless compression algorithm to integer images. */ (fptr->Fptr)->request_lossy_int_compress = lossy_int; return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_huge_hdu(fitsfile *fptr, /* I - FITS file pointer */ int huge, /* I - True (!= 0) or False (0) */ int *status) /* IO - error status */ { /* This routine specifies whether the HDU that is being compressed is so large (i.e., > 4 GB) that the 'Q' type variable length array columns should be used rather than the normal 'P' type. The allows the heap pointers to be stored as 64-bit quantities, rather than just 32-bits. */ (fptr->Fptr)->request_huge_hdu = huge; return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_compression_type(fitsfile *fptr, /* I - FITS file pointer */ int *ctype, /* image compression type code; */ /* allowed values: */ /* RICE_1, GZIP_1, GZIP_2, PLIO_1, HCOMPRESS_1, BZIP2_1 */ int *status) /* IO - error status */ { /* This routine returns the image compression algorithm that should be used when writing a FITS image. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ *ctype = (fptr->Fptr)->request_compress_type; if (*ctype != RICE_1 && *ctype != GZIP_1 && *ctype != GZIP_2 && *ctype != PLIO_1 && *ctype != HCOMPRESS_1 && *ctype != BZIP2_1 && *ctype != NOCOMPRESS && *ctype != 0 ) { ffpmsg("unknown compression algorithm (fits_get_compression_type)"); *status = DATA_COMPRESSION_ERR; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_tile_dim(fitsfile *fptr, /* I - FITS file pointer */ int ndim, /* number of dimensions in the compressed image */ long *dims, /* size of image compression tile in each dimension */ /* default tile size = (NAXIS1, 1, 1, ...) */ int *status) /* IO - error status */ { /* This routine returns the size (dimension) of the image compression tiles that should be used when writing a FITS image. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ int ii; if (ndim < 0 || ndim > MAX_COMPRESS_DIM) { *status = BAD_DIMEN; ffpmsg("illegal number of tile dimensions (fits_get_tile_dim)"); return(*status); } for (ii = 0; ii < ndim; ii++) { dims[ii] = (fptr->Fptr)->request_tilesize[ii]; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_unset_compression_param( fitsfile *fptr, int *status) { int ii; (fptr->Fptr)->compress_type = 0; (fptr->Fptr)->quantize_level = 0; (fptr->Fptr)->quantize_method = 0; (fptr->Fptr)->dither_seed = 0; (fptr->Fptr)->hcomp_scale = 0; for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { (fptr->Fptr)->tilesize[ii] = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_unset_compression_request( fitsfile *fptr, int *status) { int ii; (fptr->Fptr)->request_compress_type = 0; (fptr->Fptr)->request_quantize_level = 0; (fptr->Fptr)->request_quantize_method = 0; (fptr->Fptr)->request_dither_seed = 0; (fptr->Fptr)->request_hcomp_scale = 0; (fptr->Fptr)->request_lossy_int_compress = 0; (fptr->Fptr)->request_huge_hdu = 0; for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { (fptr->Fptr)->request_tilesize[ii] = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_set_compression_pref( fitsfile *infptr, fitsfile *outfptr, int *status) { /* Set the preference for various compression options, based on keywords in the input file that provide guidance about how the HDU should be compressed when written to the output file. */ int ii, naxis, nkeys, comptype; int ivalue; long tiledim[6]= {1,1,1,1,1,1}; char card[FLEN_CARD], value[FLEN_VALUE]; double qvalue; float hscale; LONGLONG datastart, dataend; if (*status > 0) return(*status); /* check the size of the HDU that is to be compressed */ fits_get_hduaddrll(infptr, NULL, &datastart, &dataend, status); if ( (LONGLONG)(dataend - datastart) > UINT32_MAX) { /* use 64-bit '1Q' variable length columns instead of '1P' columns */ /* for large files, in case the heap size becomes larger than 2**32 bytes*/ fits_set_huge_hdu(outfptr, 1, status); } fits_get_hdrspace(infptr, &nkeys, NULL, status); /* look for a image compression directive keywords (begin with 'FZ') */ for (ii = 2; ii <= nkeys; ii++) { fits_read_record(infptr, ii, card, status); if (!strncmp(card, "FZ", 2) ){ /* get the keyword value string */ fits_parse_value(card, value, NULL, status); if (!strncmp(card+2, "ALGOR", 5) ) { /* set the desired compression algorithm */ /* allowed values: RICE_1, GZIP_1, GZIP_2, PLIO_1, */ /* HCOMPRESS_1, BZIP2_1, and NOCOMPRESS */ if (!fits_strncasecmp(value, "'RICE_1", 7) ) { comptype = RICE_1; } else if (!fits_strncasecmp(value, "'GZIP_1", 7) ) { comptype = GZIP_1; } else if (!fits_strncasecmp(value, "'GZIP_2", 7) ) { comptype = GZIP_2; } else if (!fits_strncasecmp(value, "'PLIO_1", 7) ) { comptype = PLIO_1; } else if (!fits_strncasecmp(value, "'HCOMPRESS_1", 12) ) { comptype = HCOMPRESS_1; } else if (!fits_strncasecmp(value, "'NONE", 5) ) { comptype = NOCOMPRESS; } else { ffpmsg("Unknown FZALGOR keyword compression algorithm:"); ffpmsg(value); return(*status = DATA_COMPRESSION_ERR); } fits_set_compression_type (outfptr, comptype, status); } else if (!strncmp(card+2, "TILE ", 6) ) { if (!fits_strncasecmp(value, "'row", 4) ) { tiledim[0] = -1; } else if (!fits_strncasecmp(value, "'whole", 6) ) { tiledim[0] = -1; tiledim[1] = -1; tiledim[2] = -1; } else { ffdtdm(infptr, value, 0,6, &naxis, tiledim, status); } /* set the desired tile size */ fits_set_tile_dim (outfptr, 6, tiledim, status); } else if (!strncmp(card+2, "QVALUE", 6) ) { /* set the desired Q quantization value */ qvalue = atof(value); fits_set_quantize_level (outfptr, (float) qvalue, status); } else if (!strncmp(card+2, "QMETHD", 6) ) { if (!fits_strncasecmp(value, "'no_dither", 10) ) { ivalue = -1; /* just quantize, with no dithering */ } else if (!fits_strncasecmp(value, "'subtractive_dither_1", 21) ) { ivalue = SUBTRACTIVE_DITHER_1; /* use subtractive dithering */ } else if (!fits_strncasecmp(value, "'subtractive_dither_2", 21) ) { ivalue = SUBTRACTIVE_DITHER_2; /* dither, except preserve zero-valued pixels */ } else { ffpmsg("Unknown value for FZQUANT keyword: (set_compression_pref)"); ffpmsg(value); return(*status = DATA_COMPRESSION_ERR); } fits_set_quantize_method(outfptr, ivalue, status); } else if (!strncmp(card+2, "DTHRSD", 6) ) { if (!fits_strncasecmp(value, "'checksum", 9) ) { ivalue = -1; /* use checksum of first tile */ } else if (!fits_strncasecmp(value, "'clock", 6) ) { ivalue = 0; /* set dithering seed based on system clock */ } else { /* read integer value */ if (*value == '\'') ivalue = (int) atol(value+1); /* allow for leading quote character */ else ivalue = (int) atol(value); if (ivalue < 1 || ivalue > 10000) { ffpmsg("Invalid value for FZDTHRSD keyword: (set_compression_pref)"); ffpmsg(value); return(*status = DATA_COMPRESSION_ERR); } } /* set the desired dithering */ fits_set_dither_seed(outfptr, ivalue, status); } else if (!strncmp(card+2, "I2F", 3) ) { /* set whether to convert integers to float then use lossy compression */ if (!fits_strcasecmp(value, "t") ) { fits_set_lossy_int (outfptr, 1, status); } else if (!fits_strcasecmp(value, "f") ) { fits_set_lossy_int (outfptr, 0, status); } else { ffpmsg("Unknown value for FZI2F keyword: (set_compression_pref)"); ffpmsg(value); return(*status = DATA_COMPRESSION_ERR); } } else if (!strncmp(card+2, "HSCALE ", 6) ) { /* set the desired Hcompress scale value */ hscale = (float) atof(value); fits_set_hcomp_scale (outfptr, hscale, status); } } } return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_noise_bits(fitsfile *fptr, /* I - FITS file pointer */ int *noisebits, /* noise_bits parameter value */ /* (default = 4) */ int *status) /* IO - error status */ { /* ******************************************************************** ******************************************************************** THIS ROUTINE IS PROVIDED ONLY FOR BACKWARDS COMPATIBILITY; ALL NEW SOFTWARE SHOULD CALL fits_set_quantize_level INSTEAD ******************************************************************** ******************************************************************** This routine returns the value of the noice_bits parameter that should be used when compressing floating point images. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. Feb 2008: code changed to use the more general "quantize level" parameter rather than the "noise bits" parameter. If quantize level is greater than zero, then the previous noisebits parameter is approximately given by noise bits = natural logarithm (quantize level) / natural log (2) This result is rounded to the nearest integer. */ double qlevel; qlevel = (fptr->Fptr)->request_quantize_level; if (qlevel > 0. && qlevel < 65537. ) *noisebits = (int) ((log(qlevel) / log(2.0)) + 0.5); else *noisebits = 0; return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_quantize_level(fitsfile *fptr, /* I - FITS file pointer */ float *qlevel, /* quantize level parameter value */ int *status) /* IO - error status */ { /* This routine returns the value of the noice_bits parameter that should be used when compressing floating point images. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ if ((fptr->Fptr)->request_quantize_level == NO_QUANTIZE) { *qlevel = 0; } else { *qlevel = (fptr->Fptr)->request_quantize_level; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_dither_seed(fitsfile *fptr, /* I - FITS file pointer */ int *offset, /* dithering offset parameter value */ int *status) /* IO - error status */ { /* This routine returns the value of the dithering offset parameter that is used when compressing floating point images. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ *offset = (fptr->Fptr)->request_dither_seed; return(*status); }/*--------------------------------------------------------------------------*/ int fits_get_hcomp_scale(fitsfile *fptr, /* I - FITS file pointer */ float *scale, /* Hcompress scale parameter value */ int *status) /* IO - error status */ { /* This routine returns the value of the noice_bits parameter that should be used when compressing floating point images. The image is divided into tiles, and each tile is compressed and stored in a row of at variable length binary table column. */ *scale = (fptr->Fptr)->request_hcomp_scale; return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_hcomp_smooth(fitsfile *fptr, /* I - FITS file pointer */ int *smooth, /* Hcompress smooth parameter value */ int *status) /* IO - error status */ { *smooth = (fptr->Fptr)->request_hcomp_smooth; return(*status); } /*--------------------------------------------------------------------------*/ int fits_img_compress(fitsfile *infptr, /* pointer to image to be compressed */ fitsfile *outfptr, /* empty HDU for output compressed image */ int *status) /* IO - error status */ /* This routine initializes the output table, copies all the keywords, and loops through the input image, compressing the data and writing the compressed tiles to the output table. This is a high level routine that is called by the fpack and funpack FITS compression utilities. */ { int bitpix, naxis; long naxes[MAX_COMPRESS_DIM]; /* int c1, c2, c3; */ if (*status > 0) return(*status); /* get datatype and size of input image */ if (fits_get_img_param(infptr, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, status) > 0) return(*status); if (naxis < 1 || naxis > MAX_COMPRESS_DIM) { ffpmsg("Image cannot be compressed: NAXIS out of range"); return(*status = BAD_NAXIS); } /* create a new empty HDU in the output file now, before setting the */ /* compression preferences. This HDU will become a binary table that */ /* contains the compressed image. If necessary, create a dummy primary */ /* array, which much precede the binary table extension. */ ffcrhd(outfptr, status); /* this does nothing if the output file is empty */ if ((outfptr->Fptr)->curhdu == 0) /* have to create dummy primary array */ { ffcrim(outfptr, 16, 0, NULL, status); ffcrhd(outfptr, status); } else { /* unset any compress parameter preferences that may have been set when closing the previous HDU in the output file */ fits_unset_compression_param(outfptr, status); } /* set any compress parameter preferences as given in the input file */ fits_set_compression_pref(infptr, outfptr, status); /* special case: the quantization level is not given by a keyword in */ /* the HDU header, so we have to explicitly copy the requested value */ /* to the actual value */ /* do this in imcomp_get_compressed_image_par, instead if ( (outfptr->Fptr)->request_quantize_level != 0.) (outfptr->Fptr)->quantize_level = (outfptr->Fptr)->request_quantize_level; */ /* if requested, treat integer images same as a float image. */ /* Then the pixels will be quantized (lossy algorithm) to achieve */ /* higher amounts of compression than with lossless algorithms */ if ( (outfptr->Fptr)->request_lossy_int_compress != 0 && bitpix > 0) bitpix = FLOAT_IMG; /* compress integer images as if float */ /* initialize output table */ if (imcomp_init_table(outfptr, bitpix, naxis, naxes, 0, status) > 0) return (*status); /* Copy the image header keywords to the table header. */ if (imcomp_copy_img2comp(infptr, outfptr, status) > 0) return (*status); /* turn off any intensity scaling (defined by BSCALE and BZERO */ /* keywords) so that unscaled values will be read by CFITSIO */ /* (except if quantizing an int image, same as a float image) */ if ( (outfptr->Fptr)->request_lossy_int_compress == 0 && bitpix > 0) ffpscl(infptr, 1.0, 0.0, status); /* force a rescan of the output file keywords, so that */ /* the compression parameters will be copied to the internal */ /* fitsfile structure used by CFITSIO */ ffrdef(outfptr, status); /* turn off any intensity scaling (defined by BSCALE and BZERO */ /* keywords) so that unscaled values will be written by CFITSIO */ /* (except if quantizing an int image, same as a float image) */ if ( (outfptr->Fptr)->request_lossy_int_compress == 0 && bitpix > 0) ffpscl(outfptr, 1.0, 0.0, status); /* Read each image tile, compress, and write to a table row. */ imcomp_compress_image (infptr, outfptr, status); /* force another rescan of the output file keywords, to */ /* update PCOUNT and TFORMn = '1PB(iii)' keyword values. */ ffrdef(outfptr, status); /* unset any previously set compress parameter preferences */ fits_unset_compression_request(outfptr, status); /* fits_get_case(&c1, &c2, &c3); printf("c1, c2, c3 = %d, %d, %d\n", c1, c2, c3); */ return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_init_table(fitsfile *outfptr, int inbitpix, int naxis, long *naxes, int writebitpix, /* write the ZBITPIX, ZNAXIS, and ZNAXES keyword? */ int *status) /* create a BINTABLE extension for the output compressed image. */ { char keyname[FLEN_KEYWORD], zcmptype[12]; int ii, remain, ndiv, addToDim, ncols, bitpix; long nrows; char *ttype[] = {"COMPRESSED_DATA", "ZSCALE", "ZZERO"}; char *tform[3]; char tf0[4], tf1[4], tf2[4]; char *tunit[] = {"\0", "\0", "\0" }; char comm[FLEN_COMMENT]; long actual_tilesize[MAX_COMPRESS_DIM]; /* Actual size to use for tiles */ int is_primary=0; /* Is this attempting to write to the primary? */ int nQualifyDims=0; /* For Hcompress, number of image dimensions with required pixels. */ int noHigherDims=1; /* Set to true if all tile dims other than x are size 1. */ int firstDim=-1, secondDim=-1; /* Indices of first and second tiles dimensions with width > 1 */ if (*status > 0) return(*status); /* check for special case of losslessly compressing floating point */ /* images. Only compression algorithm that supports this is GZIP */ if ( (inbitpix < 0) && ((outfptr->Fptr)->request_quantize_level == NO_QUANTIZE) ) { if (((outfptr->Fptr)->request_compress_type != GZIP_1) && ((outfptr->Fptr)->request_compress_type != GZIP_2)) { ffpmsg("Lossless compression of floating point images must use GZIP (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } } /* set default compression parameter values, if undefined */ if ( (outfptr->Fptr)->request_compress_type == 0) { /* use RICE_1 by default */ (outfptr->Fptr)->request_compress_type = RICE_1; } if (inbitpix < 0 && (outfptr->Fptr)->request_quantize_level != NO_QUANTIZE) { /* set defaults for quantizing floating point images */ if ( (outfptr->Fptr)->request_quantize_method == 0) { /* set default dithering method */ (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1; } if ( (outfptr->Fptr)->request_quantize_level == 0) { if ((outfptr->Fptr)->request_quantize_method == NO_DITHER) { /* must use finer quantization if no dithering is done */ (outfptr->Fptr)->request_quantize_level = 16; } else { (outfptr->Fptr)->request_quantize_level = 4; } } } /* special case: the quantization level is not given by a keyword in */ /* the HDU header, so we have to explicitly copy the requested value */ /* to the actual value */ /* do this in imcomp_get_compressed_image_par, instead if ( (outfptr->Fptr)->request_quantize_level != 0.) (outfptr->Fptr)->quantize_level = (outfptr->Fptr)->request_quantize_level; */ /* test for the 2 special cases that represent unsigned integers */ if (inbitpix == USHORT_IMG) bitpix = SHORT_IMG; else if (inbitpix == ULONG_IMG) bitpix = LONG_IMG; else if (inbitpix == SBYTE_IMG) bitpix = BYTE_IMG; else bitpix = inbitpix; /* reset default tile dimensions too if required */ memcpy(actual_tilesize, outfptr->Fptr->request_tilesize, MAX_COMPRESS_DIM * sizeof(long)); if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1) { /* Tiles must ultimately have 2 (and only 2) dimensions, each with at least 4 pixels. First catch the case where the image itself won't allow this. */ if (naxis < 2 ) { ffpmsg("Hcompress cannot be used with 1-dimensional images (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } for (ii=0; ii= 4) ++nQualifyDims; } if (nQualifyDims < 2) { ffpmsg("Hcompress minimum image dimension is 4 pixels (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } /* Handle 2 special cases for backwards compatibility. 1) If both X and Y tile dims are set to full size, ignore any other requested dimensions and just set their sizes to 1. 2) If X is full size and all the rest are size 1, attempt to find a reasonable size for Y. All other 1-D tile specifications will be rejected. */ for (ii=1; ii 3) { actual_tilesize[1] = 16; } else if (naxes[1] % 24 == 0 || naxes[1] % 24 > 3) { actual_tilesize[1] = 24; } else if (naxes[1] % 20 == 0 || naxes[1] % 20 > 3) { actual_tilesize[1] = 20; } else if (naxes[1] % 30 == 0 || naxes[1] % 30 > 3) { actual_tilesize[1] = 30; } else if (naxes[1] % 28 == 0 || naxes[1] % 28 > 3) { actual_tilesize[1] = 28; } else if (naxes[1] % 26 == 0 || naxes[1] % 26 > 3) { actual_tilesize[1] = 26; } else if (naxes[1] % 22 == 0 || naxes[1] % 22 > 3) { actual_tilesize[1] = 22; } else if (naxes[1] % 18 == 0 || naxes[1] % 18 > 3) { actual_tilesize[1] = 18; } else if (naxes[1] % 14 == 0 || naxes[1] % 14 > 3) { actual_tilesize[1] = 14; } else { actual_tilesize[1] = 17; } } } else { if (actual_tilesize[0] <= 0) actual_tilesize[0] = naxes[0]; for (ii=1; ii 1) { if (firstDim < 0) firstDim = ii; else if (secondDim < 0) secondDim = ii; else { ffpmsg("Hcompress tiles can only have 2 dimensions (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } } } if (firstDim < 0 || secondDim < 0) { ffpmsg("Hcompress tiles must have 2 dimensions (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } if (actual_tilesize[firstDim] < 4 || actual_tilesize[secondDim] < 4) { ffpmsg("Hcompress minimum tile dimension is 4 pixels (imcomp_init_table)"); return (*status = DATA_COMPRESSION_ERR); } /* check if requested tile size causes the last tile to to have less than 4 pixels */ remain = naxes[firstDim] % (actual_tilesize[firstDim]); /* 1st dimension */ if (remain > 0 && remain < 4) { ndiv = naxes[firstDim]/actual_tilesize[firstDim]; /* integer truncation is intentional */ addToDim = ceil((double)remain/ndiv); (actual_tilesize[firstDim]) += addToDim; /* increase tile size */ remain = naxes[firstDim] % (actual_tilesize[firstDim]); if (remain > 0 && remain < 4) { ffpmsg("Last tile along 1st dimension has less than 4 pixels (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } } remain = naxes[secondDim] % (actual_tilesize[secondDim]); /* 2nd dimension */ if (remain > 0 && remain < 4) { ndiv = naxes[secondDim]/actual_tilesize[secondDim]; /* integer truncation is intentional */ addToDim = ceil((double)remain/ndiv); (actual_tilesize[secondDim]) += addToDim; /* increase tile size */ remain = naxes[secondDim] % (actual_tilesize[secondDim]); if (remain > 0 && remain < 4) { ffpmsg("Last tile along 2nd dimension has less than 4 pixels (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } } } /* end, if HCOMPRESS_1 */ for (ii = 0; ii < naxis; ii++) { if (ii == 0) { /* first axis is different */ if (actual_tilesize[ii] <= 0) { actual_tilesize[ii] = naxes[ii]; } } else { if (actual_tilesize[ii] < 0) { actual_tilesize[ii] = naxes[ii]; /* negative value maean use whole length */ } else if (actual_tilesize[ii] == 0) { actual_tilesize[ii] = 1; /* zero value means use default value = 1 */ } } } /* ---- set up array of TFORM strings -------------------------------*/ if ( (outfptr->Fptr)->request_huge_hdu != 0) { strcpy(tf0, "1QB"); } else { strcpy(tf0, "1PB"); } strcpy(tf1, "1D"); strcpy(tf2, "1D"); tform[0] = tf0; tform[1] = tf1; tform[2] = tf2; /* calculate number of rows in output table */ nrows = 1; for (ii = 0; ii < naxis; ii++) { nrows = nrows * ((naxes[ii] - 1)/ (actual_tilesize[ii]) + 1); } /* determine the default number of columns in the output table */ if (bitpix < 0 && (outfptr->Fptr)->request_quantize_level != NO_QUANTIZE) ncols = 3; /* quantized and scaled floating point image */ else ncols = 1; /* default table has just one 'COMPRESSED_DATA' column */ if ((outfptr->Fptr)->request_compress_type == RICE_1) { strcpy(zcmptype, "RICE_1"); } else if ((outfptr->Fptr)->request_compress_type == GZIP_1) { strcpy(zcmptype, "GZIP_1"); } else if ((outfptr->Fptr)->request_compress_type == GZIP_2) { strcpy(zcmptype, "GZIP_2"); } else if ((outfptr->Fptr)->request_compress_type == BZIP2_1) { strcpy(zcmptype, "BZIP2_1"); } else if ((outfptr->Fptr)->request_compress_type == PLIO_1) { strcpy(zcmptype, "PLIO_1"); /* the PLIO compression algorithm outputs short integers, not bytes */ if ( (outfptr->Fptr)->request_huge_hdu != 0) { strcpy(tform[0], "1QI"); } else { strcpy(tform[0], "1PI"); } } else if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1) { strcpy(zcmptype, "HCOMPRESS_1"); } else if ((outfptr->Fptr)->request_compress_type == NOCOMPRESS) { strcpy(zcmptype, "NOCOMPRESS"); } else { ffpmsg("unknown compression type (imcomp_init_table)"); return(*status = DATA_COMPRESSION_ERR); } /* If attempting to write compressed image to primary, the call to ffcrtb will increment Fptr->curhdu to 1. Therefore we need to test now for setting is_primary */ is_primary = (outfptr->Fptr->curhdu == 0); /* create the bintable extension to contain the compressed image */ ffcrtb(outfptr, BINARY_TBL, nrows, ncols, ttype, tform, tunit, 0, status); /* Add standard header keywords. */ ffpkyl (outfptr, "ZIMAGE", 1, "extension contains compressed image", status); if (writebitpix) { /* write the keywords defining the datatype and dimensions of */ /* the uncompressed image. If not, these keywords will be */ /* copied later from the input uncompressed image */ if (is_primary) ffpkyl (outfptr, "ZSIMPLE", 1, "file does conform to FITS standard", status); ffpkyj (outfptr, "ZBITPIX", bitpix, "data type of original image", status); ffpkyj (outfptr, "ZNAXIS", naxis, "dimension of original image", status); for (ii = 0; ii < naxis; ii++) { snprintf (keyname, FLEN_KEYWORD,"ZNAXIS%d", ii+1); ffpkyj (outfptr, keyname, naxes[ii], "length of original image axis", status); } } for (ii = 0; ii < naxis; ii++) { snprintf (keyname, FLEN_KEYWORD,"ZTILE%d", ii+1); ffpkyj (outfptr, keyname, actual_tilesize[ii], "size of tiles to be compressed", status); } if (bitpix < 0) { if ((outfptr->Fptr)->request_quantize_level == NO_QUANTIZE) { ffpkys(outfptr, "ZQUANTIZ", "NONE", "Lossless compression without quantization", status); } else { /* Unless dithering has been specifically turned off by setting */ /* request_quantize_method = -1, use dithering by default */ /* when quantizing floating point images. */ if ( (outfptr->Fptr)->request_quantize_method == 0) (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1; /* HCompress must not use SUBTRACTIVE_DITHER_2. If user is requesting this, assign SUBTRACTIVE_DITHER_1 instead. */ if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_2 && !(strcmp(zcmptype,"HCOMPRESS_1"))) { (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1; fprintf(stderr,"Warning: CFITSIO does not allow subtractive_dither_2 when using Hcompress algorithm.\nWill use subtractive_dither_1 instead.\n"); } if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_1) { ffpkys(outfptr, "ZQUANTIZ", "SUBTRACTIVE_DITHER_1", "Pixel Quantization Algorithm", status); /* also write the associated ZDITHER0 keyword with a default value */ /* which may get updated later. */ ffpky(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->request_dither_seed), "dithering offset when quantizing floats", status); } else if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_2) { ffpkys(outfptr, "ZQUANTIZ", "SUBTRACTIVE_DITHER_2", "Pixel Quantization Algorithm", status); /* also write the associated ZDITHER0 keyword with a default value */ /* which may get updated later. */ ffpky(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->request_dither_seed), "dithering offset when quantizing floats", status); if (!strcmp(zcmptype, "RICE_1")) { /* when using this new dithering method, change the compression type */ /* to an alias, so that old versions of funpack will not be able to */ /* created a corrupted uncompressed image. */ /* ******* can remove this cludge after about June 2015, after most old versions of fpack are gone */ strcpy(zcmptype, "RICE_ONE"); } } else if ((outfptr->Fptr)->request_quantize_method == NO_DITHER) { ffpkys(outfptr, "ZQUANTIZ", "NO_DITHER", "No dithering during quantization", status); } } } ffpkys (outfptr, "ZCMPTYPE", zcmptype, "compression algorithm", status); /* write any algorithm-specific keywords */ if ((outfptr->Fptr)->request_compress_type == RICE_1) { ffpkys (outfptr, "ZNAME1", "BLOCKSIZE", "compression block size", status); /* for now at least, the block size is always 32 */ ffpkyj (outfptr, "ZVAL1", 32, "pixels per block", status); ffpkys (outfptr, "ZNAME2", "BYTEPIX", "bytes per pixel (1, 2, 4, or 8)", status); if (bitpix == BYTE_IMG) ffpkyj (outfptr, "ZVAL2", 1, "bytes per pixel (1, 2, 4, or 8)", status); else if (bitpix == SHORT_IMG) ffpkyj (outfptr, "ZVAL2", 2, "bytes per pixel (1, 2, 4, or 8)", status); else ffpkyj (outfptr, "ZVAL2", 4, "bytes per pixel (1, 2, 4, or 8)", status); } else if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1) { ffpkys (outfptr, "ZNAME1", "SCALE", "HCOMPRESS scale factor", status); ffpkye (outfptr, "ZVAL1", (outfptr->Fptr)->request_hcomp_scale, 7, "HCOMPRESS scale factor", status); ffpkys (outfptr, "ZNAME2", "SMOOTH", "HCOMPRESS smooth option", status); ffpkyj (outfptr, "ZVAL2", (long) (outfptr->Fptr)->request_hcomp_smooth, "HCOMPRESS smooth option", status); } /* Write the BSCALE and BZERO keywords, if an unsigned integer image */ if (inbitpix == USHORT_IMG) { strcpy(comm, "offset data range to that of unsigned short"); ffpkyg(outfptr, "BZERO", 32768., 0, comm, status); strcpy(comm, "default scaling factor"); ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status); } else if (inbitpix == SBYTE_IMG) { strcpy(comm, "offset data range to that of signed byte"); ffpkyg(outfptr, "BZERO", -128., 0, comm, status); strcpy(comm, "default scaling factor"); ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status); } else if (inbitpix == ULONG_IMG) { strcpy(comm, "offset data range to that of unsigned long"); ffpkyg(outfptr, "BZERO", 2147483648., 0, comm, status); strcpy(comm, "default scaling factor"); ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status); } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_calc_max_elem (int comptype, int nx, int zbitpix, int blocksize) /* This function returns the maximum number of bytes in a compressed image line. nx = maximum number of pixels in a tile blocksize is only relevant for RICE compression */ { if (comptype == RICE_1) { if (zbitpix == 16) return (sizeof(short) * nx + nx / blocksize + 2 + 4); else return (sizeof(float) * nx + nx / blocksize + 2 + 4); } else if ((comptype == GZIP_1) || (comptype == GZIP_2)) { /* gzip usually compressed by at least a factor of 2 for I*4 images */ /* and somewhat less for I*2 images */ /* If this size turns out to be too small, then the gzip */ /* compression routine will allocate more space as required */ /* to be on the safe size, allocate buffer same size as input */ if (zbitpix == 16) return(nx * 2); else if (zbitpix == 8) return(nx); else return(nx * 4); } else if (comptype == BZIP2_1) { /* To guarantee that the compressed data will fit, allocate an output buffer of size 1% larger than the uncompressed data, plus 600 bytes */ return((int) (nx * 1.01 * zbitpix / 8. + 601.)); } else if (comptype == HCOMPRESS_1) { /* Imperical evidence suggests in the worst case, the compressed stream could be up to 10% larger than the original image. Add 26 byte overhead, only significant for very small tiles Possible improvement: may need to allow a larger size for 32-bit images */ if (zbitpix == 16 || zbitpix == 8) return( (int) (nx * 2.2 + 26)); /* will be compressing 16-bit int array */ else return( (int) (nx * 4.4 + 26)); /* will be compressing 32-bit int array */ } else return(nx * sizeof(int)); } /*--------------------------------------------------------------------------*/ int imcomp_compress_image (fitsfile *infptr, fitsfile *outfptr, int *status) /* This routine does the following: - reads an image one tile at a time - if it is a float or double image, then it tries to quantize the pixels into scaled integers. - it then compressess the integer pixels, or if the it was not possible to quantize the floating point pixels, then it losslessly compresses them with gzip - writes the compressed byte stream to the output FITS file */ { double *tiledata; int anynul, gotnulls = 0, datatype; long ii, row; int naxis; double dummy = 0., dblnull = DOUBLENULLVALUE; float fltnull = FLOATNULLVALUE; long maxtilelen, tilelen, incre[] = {1, 1, 1, 1, 1, 1}; long naxes[MAX_COMPRESS_DIM], fpixel[MAX_COMPRESS_DIM]; long lpixel[MAX_COMPRESS_DIM], tile[MAX_COMPRESS_DIM]; long tilesize[MAX_COMPRESS_DIM]; long i0, i1, i2, i3, i4, i5, trowsize, ntrows; char card[FLEN_CARD]; if (*status > 0) return(*status); maxtilelen = (outfptr->Fptr)->maxtilelen; /* Allocate buffer to hold 1 tile of data; size depends on which compression algorithm is used: Rice and GZIP will compress byte, short, or int arrays without conversion. PLIO requires 4-byte int values, so byte and short arrays must be converted to int. HCompress internally converts byte or short values to ints, and converts int values to 8-byte longlong integers. */ if ((outfptr->Fptr)->zbitpix == FLOAT_IMG) { datatype = TFLOAT; if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) { /* need twice as much scratch space (8 bytes per pixel) */ tiledata = (double*) malloc (maxtilelen * 2 *sizeof (float)); } else { tiledata = (double*) malloc (maxtilelen * sizeof (float)); } } else if ((outfptr->Fptr)->zbitpix == DOUBLE_IMG) { datatype = TDOUBLE; tiledata = (double*) malloc (maxtilelen * sizeof (double)); } else if ((outfptr->Fptr)->zbitpix == SHORT_IMG) { datatype = TSHORT; if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1 || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 || (outfptr->Fptr)->compress_type == NOCOMPRESS) { /* only need buffer of I*2 pixels for gzip, bzip2, and Rice */ tiledata = (double*) malloc (maxtilelen * sizeof (short)); } else { /* need buffer of I*4 pixels for Hcompress and PLIO */ tiledata = (double*) malloc (maxtilelen * sizeof (int)); } } else if ((outfptr->Fptr)->zbitpix == BYTE_IMG) { datatype = TBYTE; if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == BZIP2_1 || (outfptr->Fptr)->compress_type == GZIP_1 || (outfptr->Fptr)->compress_type == GZIP_2) { /* only need buffer of I*1 pixels for gzip, bzip2, and Rice */ tiledata = (double*) malloc (maxtilelen); } else { /* need buffer of I*4 pixels for Hcompress and PLIO */ tiledata = (double*) malloc (maxtilelen * sizeof (int)); } } else if ((outfptr->Fptr)->zbitpix == LONG_IMG) { datatype = TINT; if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) { /* need twice as much scratch space (8 bytes per pixel) */ tiledata = (double*) malloc (maxtilelen * 2 * sizeof (int)); } else { /* only need buffer of I*4 pixels for gzip, bzip2, Rice, and PLIO */ tiledata = (double*) malloc (maxtilelen * sizeof (int)); } } else { ffpmsg("Bad image datatype. (imcomp_compress_image)"); return (*status = MEMORY_ALLOCATION); } if (tiledata == NULL) { ffpmsg("Out of memory. (imcomp_compress_image)"); return (*status = MEMORY_ALLOCATION); } /* calculate size of tile in each dimension */ naxis = (outfptr->Fptr)->zndim; for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { if (ii < naxis) { naxes[ii] = (outfptr->Fptr)->znaxis[ii]; tilesize[ii] = (outfptr->Fptr)->tilesize[ii]; } else { naxes[ii] = 1; tilesize[ii] = 1; } } row = 1; /* set up big loop over up to 6 dimensions */ for (i5 = 1; i5 <= naxes[5]; i5 += tilesize[5]) { fpixel[5] = i5; lpixel[5] = minvalue(i5 + tilesize[5] - 1, naxes[5]); tile[5] = lpixel[5] - fpixel[5] + 1; for (i4 = 1; i4 <= naxes[4]; i4 += tilesize[4]) { fpixel[4] = i4; lpixel[4] = minvalue(i4 + tilesize[4] - 1, naxes[4]); tile[4] = lpixel[4] - fpixel[4] + 1; for (i3 = 1; i3 <= naxes[3]; i3 += tilesize[3]) { fpixel[3] = i3; lpixel[3] = minvalue(i3 + tilesize[3] - 1, naxes[3]); tile[3] = lpixel[3] - fpixel[3] + 1; for (i2 = 1; i2 <= naxes[2]; i2 += tilesize[2]) { fpixel[2] = i2; lpixel[2] = minvalue(i2 + tilesize[2] - 1, naxes[2]); tile[2] = lpixel[2] - fpixel[2] + 1; for (i1 = 1; i1 <= naxes[1]; i1 += tilesize[1]) { fpixel[1] = i1; lpixel[1] = minvalue(i1 + tilesize[1] - 1, naxes[1]); tile[1] = lpixel[1] - fpixel[1] + 1; for (i0 = 1; i0 <= naxes[0]; i0 += tilesize[0]) { fpixel[0] = i0; lpixel[0] = minvalue(i0 + tilesize[0] - 1, naxes[0]); tile[0] = lpixel[0] - fpixel[0] + 1; /* number of pixels in this tile */ tilelen = tile[0]; for (ii = 1; ii < naxis; ii++) { tilelen *= tile[ii]; } /* read next tile of data from image */ anynul = 0; if (datatype == TFLOAT) { ffgsve(infptr, 1, naxis, naxes, fpixel, lpixel, incre, FLOATNULLVALUE, (float *) tiledata, &anynul, status); } else if (datatype == TDOUBLE) { ffgsvd(infptr, 1, naxis, naxes, fpixel, lpixel, incre, DOUBLENULLVALUE, tiledata, &anynul, status); } else if (datatype == TINT) { ffgsvk(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 0, (int *) tiledata, &anynul, status); } else if (datatype == TSHORT) { ffgsvi(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 0, (short *) tiledata, &anynul, status); } else if (datatype == TBYTE) { ffgsvb(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 0, (unsigned char *) tiledata, &anynul, status); } else { ffpmsg("Error bad datatype of image tile to compress"); free(tiledata); return (*status); } /* now compress the tile, and write to row of binary table */ /* NOTE: we don't have to worry about the presence of null values in the array if it is an integer array: the null value is simply encoded in the compressed array just like any other pixel value. If it is a floating point array, then we need to check for null only if the anynul parameter returned a true value when reading the tile */ /* Collapse sizes of higher dimension tiles into 2 dimensional equivalents needed by the quantizing algorithms for floating point types */ fits_calc_tile_rows(lpixel, fpixel, naxis, &trowsize, &ntrows, status); if (anynul && datatype == TFLOAT) { imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen, trowsize, ntrows, 1, &fltnull, status); } else if (anynul && datatype == TDOUBLE) { imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen, trowsize, ntrows, 1, &dblnull, status); } else { imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen, trowsize, ntrows, 0, &dummy, status); } /* set flag if we found any null values */ if (anynul) gotnulls = 1; /* check for any error in the previous operations */ if (*status > 0) { ffpmsg("Error writing compressed image to table"); free(tiledata); return (*status); } row++; } } } } } } free (tiledata); /* finished with this buffer */ /* insert ZBLANK keyword if necessary; only for TFLOAT or TDOUBLE images */ if (gotnulls) { ffgcrd(outfptr, "ZCMPTYPE", card, status); ffikyj(outfptr, "ZBLANK", COMPRESS_NULL_VALUE, "null value in the compressed integer array", status); } return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_compress_tile (fitsfile *outfptr, long row, /* tile number = row in the binary table that holds the compressed data */ int datatype, void *tiledata, long tilelen, long tilenx, long tileny, int nullcheck, void *nullflagval, int *status) /* This is the main compression routine. This routine does the following to the input tile of pixels: - if it is a float or double image, then it quantizes the pixels - compresses the integer pixel values - writes the compressed byte stream to the FITS file. If the tile cannot be quantized than the raw float or double values are losslessly compressed with gzip and then written to the output table. This input array may be modified by this routine. If the array is of type TINT or TFLOAT, and the compression type is HCOMPRESS, then it must have been allocated to be twice as large (8 bytes per pixel) to provide scratch space. Note that this routine does not fully support the implicit datatype conversion that is supported when writing to normal FITS images. The datatype of the input array must have the same datatype (either signed or unsigned) as the output (compressed) FITS image in some cases. */ { int *idata; /* quantized integer data */ int cn_zblank, zbitpix, nullval; int flag = 1; /* true by default; only = 0 if float data couldn't be quantized */ int intlength; /* size of integers to be compressed */ double scale, zero, actual_bzero; long ii; size_t clen; /* size of cbuf */ short *cbuf; /* compressed data */ int nelem = 0; /* number of bytes */ int tilecol; size_t gzip_nelem = 0; unsigned int bzlen; int ihcompscale; float hcompscale; double noise2, noise3, noise5; double bscale[1] = {1.}, bzero[1] = {0.}; /* scaling parameters */ long hcomp_len; LONGLONG *lldata; if (*status > 0) return(*status); /* check for special case of losslessly compressing floating point */ /* images. Only compression algorithm that supports this is GZIP */ if ( (outfptr->Fptr)->quantize_level == NO_QUANTIZE) { if (((outfptr->Fptr)->compress_type != GZIP_1) && ((outfptr->Fptr)->compress_type != GZIP_2)) { switch (datatype) { case TFLOAT: case TDOUBLE: case TCOMPLEX: case TDBLCOMPLEX: ffpmsg("Lossless compression of floating point images must use GZIP (imcomp_compress_tile)"); return(*status = DATA_COMPRESSION_ERR); default: break; } } } /* free the previously saved tile if the input tile is for the same row */ if ((outfptr->Fptr)->tilerow) { /* has the tile cache been allocated? */ /* calculate the column bin of the compressed tile */ tilecol = (row - 1) % ((long)(((outfptr->Fptr)->znaxis[0] - 1) / ((outfptr->Fptr)->tilesize[0])) + 1); if ((outfptr->Fptr)->tilerow[tilecol] == row) { if (((outfptr->Fptr)->tiledata)[tilecol]) { free(((outfptr->Fptr)->tiledata)[tilecol]); } if (((outfptr->Fptr)->tilenullarray)[tilecol]) { free(((outfptr->Fptr)->tilenullarray)[tilecol]); } ((outfptr->Fptr)->tiledata)[tilecol] = 0; ((outfptr->Fptr)->tilenullarray)[tilecol] = 0; (outfptr->Fptr)->tilerow[tilecol] = 0; (outfptr->Fptr)->tiledatasize[tilecol] = 0; (outfptr->Fptr)->tiletype[tilecol] = 0; (outfptr->Fptr)->tileanynull[tilecol] = 0; } } if ( (outfptr->Fptr)->compress_type == NOCOMPRESS) { /* Special case when using NOCOMPRESS for diagnostic purposes in fpack */ if (imcomp_write_nocompress_tile(outfptr, row, datatype, tiledata, tilelen, nullcheck, nullflagval, status) > 0) { return(*status); } return(*status); } /* =========================================================================== */ /* initialize various parameters */ idata = (int *) tiledata; /* may overwrite the input tiledata in place */ /* zbitpix is the BITPIX keyword value in the uncompressed FITS image */ zbitpix = (outfptr->Fptr)->zbitpix; /* if the tile/image has an integer datatype, see if a null value has */ /* been defined (with the BLANK keyword in a normal FITS image). */ /* If so, and if the input tile array also contains null pixels, */ /* (represented by pixels that have a value = nullflagval) then */ /* any pixels whose value = nullflagval, must be set to the value = nullval */ /* before the pixel array is compressed. These null pixel values must */ /* not be inverse scaled by the BSCALE/BZERO values, if present. */ cn_zblank = (outfptr->Fptr)->cn_zblank; nullval = (outfptr->Fptr)->zblank; if (zbitpix > 0 && cn_zblank != -1) /* If the integer image has no defined null */ nullcheck = 0; /* value, then don't bother checking input array for nulls. */ /* if the BSCALE and BZERO keywords exist, then the input values must */ /* be inverse scaled by this factor, before the values are compressed. */ /* (The program may have turned off scaling, which over rides the keywords) */ scale = (outfptr->Fptr)->cn_bscale; zero = (outfptr->Fptr)->cn_bzero; actual_bzero = (outfptr->Fptr)->cn_actual_bzero; /* =========================================================================== */ /* prepare the tile of pixel values for compression */ if (datatype == TSHORT) { imcomp_convert_tile_tshort(outfptr, tiledata, tilelen, nullcheck, nullflagval, nullval, zbitpix, scale, zero, actual_bzero, &intlength, status); } else if (datatype == TUSHORT) { imcomp_convert_tile_tushort(outfptr, tiledata, tilelen, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, status); } else if (datatype == TBYTE) { imcomp_convert_tile_tbyte(outfptr, tiledata, tilelen, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, status); } else if (datatype == TSBYTE) { imcomp_convert_tile_tsbyte(outfptr, tiledata, tilelen, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, status); } else if (datatype == TINT) { imcomp_convert_tile_tint(outfptr, tiledata, tilelen, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, status); } else if (datatype == TUINT) { imcomp_convert_tile_tuint(outfptr, tiledata, tilelen, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, status); } else if (datatype == TLONG && sizeof(long) == 8) { ffpmsg("Integer*8 Long datatype is not supported when writing to compressed images"); return(*status = BAD_DATATYPE); } else if (datatype == TULONG && sizeof(long) == 8) { ffpmsg("Unsigned integer*8 datatype is not supported when writing to compressed images"); return(*status = BAD_DATATYPE); } else if (datatype == TFLOAT) { imcomp_convert_tile_tfloat(outfptr, row, tiledata, tilelen, tilenx, tileny, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, &flag, bscale, bzero, status); } else if (datatype == TDOUBLE) { imcomp_convert_tile_tdouble(outfptr, row, tiledata, tilelen, tilenx, tileny, nullcheck, nullflagval, nullval, zbitpix, scale, zero, &intlength, &flag, bscale, bzero, status); } else { ffpmsg("unsupported image datatype (imcomp_compress_tile)"); return(*status = BAD_DATATYPE); } if (*status > 0) return(*status); /* return if error occurs */ /* =========================================================================== */ if (flag) /* now compress the integer data array */ { /* allocate buffer for the compressed tile bytes */ clen = (outfptr->Fptr)->maxelem; cbuf = (short *) calloc (clen, sizeof (unsigned char)); if (cbuf == NULL) { ffpmsg("Memory allocation failure. (imcomp_compress_tile)"); return (*status = MEMORY_ALLOCATION); } /* =========================================================================== */ if ( (outfptr->Fptr)->compress_type == RICE_1) { if (intlength == 2) { nelem = fits_rcomp_short ((short *)idata, tilelen, (unsigned char *) cbuf, clen, (outfptr->Fptr)->rice_blocksize); } else if (intlength == 1) { nelem = fits_rcomp_byte ((signed char *)idata, tilelen, (unsigned char *) cbuf, clen, (outfptr->Fptr)->rice_blocksize); } else { nelem = fits_rcomp (idata, tilelen, (unsigned char *) cbuf, clen, (outfptr->Fptr)->rice_blocksize); } if (nelem < 0) /* data compression error condition */ { free (cbuf); ffpmsg("error Rice compressing image tile (imcomp_compress_tile)"); return (*status = DATA_COMPRESSION_ERR); } /* Write the compressed byte stream. */ ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1, nelem, (unsigned char *) cbuf, status); } /* =========================================================================== */ else if ( (outfptr->Fptr)->compress_type == PLIO_1) { for (ii = 0; ii < tilelen; ii++) { if (idata[ii] < 0 || idata[ii] > 16777215) { /* plio algorithn only supports positive 24 bit ints */ ffpmsg("data out of range for PLIO compression (0 - 2**24)"); return(*status = DATA_COMPRESSION_ERR); } } nelem = pl_p2li (idata, 1, cbuf, tilelen); if (nelem < 0) /* data compression error condition */ { free (cbuf); ffpmsg("error PLIO compressing image tile (imcomp_compress_tile)"); return (*status = DATA_COMPRESSION_ERR); } /* Write the compressed byte stream. */ ffpcli(outfptr, (outfptr->Fptr)->cn_compressed, row, 1, nelem, cbuf, status); } /* =========================================================================== */ else if ( ((outfptr->Fptr)->compress_type == GZIP_1) || ((outfptr->Fptr)->compress_type == GZIP_2) ) { if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE && datatype == TFLOAT) { /* Special case of losslessly compressing floating point pixels with GZIP */ /* In this case we compress the input tile array directly */ #if BYTESWAPPED ffswap4((int*) tiledata, tilelen); #endif if ( (outfptr->Fptr)->compress_type == GZIP_2 ) fits_shuffle_4bytes((char *) tiledata, tilelen, status); compress2mem_from_mem((char *) tiledata, tilelen * sizeof(float), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE && datatype == TDOUBLE) { /* Special case of losslessly compressing double pixels with GZIP */ /* In this case we compress the input tile array directly */ #if BYTESWAPPED ffswap8((double *) tiledata, tilelen); #endif if ( (outfptr->Fptr)->compress_type == GZIP_2 ) fits_shuffle_8bytes((char *) tiledata, tilelen, status); compress2mem_from_mem((char *) tiledata, tilelen * sizeof(double), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } else { /* compress the integer idata array */ #if BYTESWAPPED if (intlength == 2) ffswap2((short *) idata, tilelen); else if (intlength == 4) ffswap4(idata, tilelen); #endif if (intlength == 2) { if ( (outfptr->Fptr)->compress_type == GZIP_2 ) fits_shuffle_2bytes((char *) tiledata, tilelen, status); compress2mem_from_mem((char *) idata, tilelen * sizeof(short), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } else if (intlength == 1) { compress2mem_from_mem((char *) idata, tilelen * sizeof(unsigned char), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } else { if ( (outfptr->Fptr)->compress_type == GZIP_2 ) fits_shuffle_4bytes((char *) tiledata, tilelen, status); compress2mem_from_mem((char *) idata, tilelen * sizeof(int), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } } /* Write the compressed byte stream. */ ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1, gzip_nelem, (unsigned char *) cbuf, status); /* =========================================================================== */ } else if ( (outfptr->Fptr)->compress_type == BZIP2_1) { #if BYTESWAPPED if (intlength == 2) ffswap2((short *) idata, tilelen); else if (intlength == 4) ffswap4(idata, tilelen); #endif bzlen = (unsigned int) clen; /* call bzip2 with blocksize = 900K, verbosity = 0, and default workfactor */ /* bzip2 is not supported in the public release. This is only for test purposes. if (BZ2_bzBuffToBuffCompress( (char *) cbuf, &bzlen, (char *) idata, (unsigned int) (tilelen * intlength), 9, 0, 0) ) */ { ffpmsg("bzip2 compression error"); return(*status = DATA_COMPRESSION_ERR); } /* Write the compressed byte stream. */ ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1, bzlen, (unsigned char *) cbuf, status); /* =========================================================================== */ } else if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) { /* if hcompscale is positive, then we have to multiply the value by the RMS background noise to get the absolute scale value. If negative, then it gives the absolute scale value directly. */ hcompscale = (outfptr->Fptr)->hcomp_scale; if (hcompscale > 0.) { fits_img_stats_int(idata, tilenx, tileny, nullcheck, nullval, 0,0,0,0,0,0,&noise2,&noise3,&noise5,status); /* use the minimum of the 3 noise estimates */ if (noise2 != 0. && noise2 < noise3) noise3 = noise2; if (noise5 != 0. && noise5 < noise3) noise3 = noise5; hcompscale = (float) (hcompscale * noise3); } else if (hcompscale < 0.) { hcompscale = hcompscale * -1.0F; } ihcompscale = (int) (hcompscale + 0.5); hcomp_len = clen; /* allocated size of the buffer */ if (zbitpix == BYTE_IMG || zbitpix == SHORT_IMG) { fits_hcompress(idata, tilenx, tileny, ihcompscale, (char *) cbuf, &hcomp_len, status); } else { /* have to convert idata to an I*8 array, in place */ /* idata must have been allocated large enough to do this */ fits_int_to_longlong_inplace(idata, tilelen, status); lldata = (LONGLONG *) idata; fits_hcompress64(lldata, tilenx, tileny, ihcompscale, (char *) cbuf, &hcomp_len, status); } /* Write the compressed byte stream. */ ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1, hcomp_len, (unsigned char *) cbuf, status); } /* =========================================================================== */ if ((outfptr->Fptr)->cn_zscale > 0) { /* write the linear scaling parameters for this tile */ ffpcld (outfptr, (outfptr->Fptr)->cn_zscale, row, 1, 1, bscale, status); ffpcld (outfptr, (outfptr->Fptr)->cn_zzero, row, 1, 1, bzero, status); } free(cbuf); /* finished with this buffer */ /* =========================================================================== */ } else { /* if flag == 0., floating point data couldn't be quantized */ /* losslessly compress the data with gzip. */ /* if gzip2 compressed data column doesn't exist, create it */ if ((outfptr->Fptr)->cn_gzip_data < 1) { if ( (outfptr->Fptr)->request_huge_hdu != 0) { fits_insert_col(outfptr, 999, "GZIP_COMPRESSED_DATA", "1QB", status); } else { fits_insert_col(outfptr, 999, "GZIP_COMPRESSED_DATA", "1PB", status); } if (*status <= 0) /* save the number of this column */ ffgcno(outfptr, CASEINSEN, "GZIP_COMPRESSED_DATA", &(outfptr->Fptr)->cn_gzip_data, status); } if (datatype == TFLOAT) { /* allocate buffer for the compressed tile bytes */ /* make it 10% larger than the original uncompressed data */ clen = (size_t) (tilelen * sizeof(float) * 1.1); cbuf = (short *) calloc (clen, sizeof (unsigned char)); if (cbuf == NULL) { ffpmsg("Memory allocation error. (imcomp_compress_tile)"); return (*status = MEMORY_ALLOCATION); } /* convert null values to NaNs in place, if necessary */ if (nullcheck == 1) { imcomp_float2nan((float *) tiledata, tilelen, (int *) tiledata, *(float *) (nullflagval), status); } #if BYTESWAPPED ffswap4((int*) tiledata, tilelen); #endif compress2mem_from_mem((char *) tiledata, tilelen * sizeof(float), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } else { /* datatype == TDOUBLE */ /* allocate buffer for the compressed tile bytes */ /* make it 10% larger than the original uncompressed data */ clen = (size_t) (tilelen * sizeof(double) * 1.1); cbuf = (short *) calloc (clen, sizeof (unsigned char)); if (cbuf == NULL) { ffpmsg("Memory allocation error. (imcomp_compress_tile)"); return (*status = MEMORY_ALLOCATION); } /* convert null values to NaNs in place, if necessary */ if (nullcheck == 1) { imcomp_double2nan((double *) tiledata, tilelen, (LONGLONG *) tiledata, *(double *) (nullflagval), status); } #if BYTESWAPPED ffswap8((double*) tiledata, tilelen); #endif compress2mem_from_mem((char *) tiledata, tilelen * sizeof(double), (char **) &cbuf, &clen, realloc, &gzip_nelem, status); } /* Write the compressed byte stream. */ ffpclb(outfptr, (outfptr->Fptr)->cn_gzip_data, row, 1, gzip_nelem, (unsigned char *) cbuf, status); free(cbuf); /* finished with this buffer */ } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_write_nocompress_tile(fitsfile *outfptr, long row, int datatype, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int *status) { char coltype[4]; /* Write the uncompressed image tile pixels to the tile-compressed image file. */ /* This is a special case when using NOCOMPRESS for diagnostic purposes in fpack. */ /* Currently, this only supports a limited number of data types and */ /* does not fully support null-valued pixels in the image. */ if ((outfptr->Fptr)->cn_uncompressed < 1) { /* uncompressed data column doesn't exist, so append new column to table */ if (datatype == TSHORT) { strcpy(coltype, "1PI"); } else if (datatype == TINT) { strcpy(coltype, "1PJ"); } else if (datatype == TFLOAT) { strcpy(coltype, "1QE"); } else { ffpmsg("NOCOMPRESSION option only supported for int*2, int*4, and float*4 images"); return(*status = DATA_COMPRESSION_ERR); } fits_insert_col(outfptr, 999, "UNCOMPRESSED_DATA", coltype, status); /* create column */ } fits_get_colnum(outfptr, CASEINSEN, "UNCOMPRESSED_DATA", &(outfptr->Fptr)->cn_uncompressed, status); /* save col. num. */ fits_write_col(outfptr, datatype, (outfptr->Fptr)->cn_uncompressed, row, 1, tilelen, tiledata, status); /* write the tile data */ return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tshort( fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, double actual_bzero, int *intlength, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input integer*2 tile array in place to 4 or 8-byte ints for compression, */ /* If needed, convert 4 or 8-byte ints and do null value substitution. */ /* Note that the calling routine must have allocated the input array big enough */ /* to be able to do this. */ short *sbuff; int flagval, *idata; long ii; /* We only support writing this integer*2 tile data to a FITS image with BITPIX = 16 and with BZERO = 0 and BSCALE = 1. */ if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 0.0) { ffpmsg("Datatype conversion/scaling is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } sbuff = (short *) tiledata; idata = (int *) tiledata; if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1 || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) { /* don't have to convert to int if using gzip, bzip2 or Rice compression */ *intlength = 2; if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(short *) (nullflagval); if (flagval != nullval) { for (ii = tilelen - 1; ii >= 0; ii--) { if (sbuff[ii] == (short) flagval) sbuff[ii] = (short) nullval; } } } } else if ((outfptr->Fptr)->compress_type == HCOMPRESS_1) { /* have to convert to int if using HCOMPRESS */ *intlength = 4; if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(short *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (sbuff[ii] == (short) flagval) idata[ii] = nullval; else idata[ii] = (int) sbuff[ii]; } } else { /* just do the data type conversion to int */ /* have to convert sbuff to an I*4 array, in place */ /* sbuff must have been allocated large enough to do this */ fits_short_to_int_inplace(sbuff, tilelen, 0, status); } } else { /* have to convert to int if using PLIO */ *intlength = 4; if (zero == 0. && actual_bzero == 32768.) { /* Here we are compressing unsigned 16-bit integers that have */ /* been offset by -32768 using the standard FITS convention. */ /* Since PLIO cannot deal with negative values, we must apply */ /* the shift of 32786 to the values to make them all positive. */ /* The inverse negative shift will be applied in */ /* imcomp_decompress_tile when reading the compressed tile. */ if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(short *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (sbuff[ii] == (short) flagval) idata[ii] = nullval; else idata[ii] = (int) sbuff[ii] + 32768; } } else { /* have to convert sbuff to an I*4 array, in place */ /* sbuff must have been allocated large enough to do this */ fits_short_to_int_inplace(sbuff, tilelen, 32768, status); } } else { /* This is not an unsigned 16-bit integer array, so process normally */ if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(short *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (sbuff[ii] == (short) flagval) idata[ii] = nullval; else idata[ii] = (int) sbuff[ii]; } } else { /* just do the data type conversion to int */ /* have to convert sbuff to an I*4 array, in place */ /* sbuff must have been allocated large enough to do this */ fits_short_to_int_inplace(sbuff, tilelen, 0, status); } } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tushort( fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input unsigned integer*2 tile array in place to 4 or 8-byte ints for compression, */ /* If needed, convert 4 or 8-byte ints and do null value substitution. */ /* Note that the calling routine must have allocated the input array big enough */ /* to be able to do this. */ unsigned short *usbuff; short *sbuff; int flagval, *idata; long ii; /* datatype of input array is unsigned short. We only support writing this datatype to a FITS image with BITPIX = 16 and with BZERO = 0 and BSCALE = 32768. */ if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 32768.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } usbuff = (unsigned short *) tiledata; sbuff = (short *) tiledata; idata = (int *) tiledata; if ((outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1 || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1) { /* don't have to convert to int if using gzip, bzip2, or Rice compression */ *intlength = 2; /* offset the unsigned value by -32768 to a signed short value. */ /* It is more efficient to do this by just flipping the most significant of the 16 bits */ if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(unsigned short *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (usbuff[ii] == (unsigned short) flagval) sbuff[ii] = (short) nullval; else usbuff[ii] = (usbuff[ii]) ^ 0x8000; } } else { /* just offset the pixel values by 32768 (by flipping the MSB */ for (ii = tilelen - 1; ii >= 0; ii--) usbuff[ii] = (usbuff[ii]) ^ 0x8000; } } else { /* have to convert to int if using HCOMPRESS or PLIO */ *intlength = 4; if (nullcheck == 1) { /* offset the pixel values by 32768, and */ /* reset pixels equal to flagval to nullval */ flagval = *(unsigned short *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (usbuff[ii] == (unsigned short) flagval) idata[ii] = nullval; else idata[ii] = ((int) usbuff[ii]) - 32768; } } else { /* just do the data type conversion to int */ /* for HCOMPRESS we need to simply subtract 32768 */ /* for PLIO, have to convert usbuff to an I*4 array, in place */ /* usbuff must have been allocated large enough to do this */ if ((outfptr->Fptr)->compress_type == HCOMPRESS_1) { fits_ushort_to_int_inplace(usbuff, tilelen, -32768, status); } else { fits_ushort_to_int_inplace(usbuff, tilelen, 0, status); } } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tint( fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input integer tile array in place to 4 or 8-byte ints for compression, */ /* If needed, do null value substitution. */ int flagval, *idata; long ii; /* datatype of input array is int. We only support writing this datatype to a FITS image with BITPIX = 32 and with BZERO = 0 and BSCALE = 1. */ if (zbitpix != LONG_IMG || scale != 1.0 || zero != 0.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } idata = (int *) tiledata; *intlength = 4; if (nullcheck == 1) { /* no datatype conversion is required for any of the compression algorithms, except possibly for HCOMPRESS (to I*8), which is handled later. Just reset pixels equal to flagval to the FITS null value */ flagval = *(int *) (nullflagval); if (flagval != nullval) { for (ii = tilelen - 1; ii >= 0; ii--) { if (idata[ii] == flagval) idata[ii] = nullval; } } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tuint( fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input unsigned integer tile array in place to 4 or 8-byte ints for compression, */ /* If needed, do null value substitution. */ int *idata; unsigned int *uintbuff, uintflagval; long ii; /* datatype of input array is unsigned int. We only support writing this datatype to a FITS image with BITPIX = 32 and with BZERO = 0 and BSCALE = 2147483648. */ if (zbitpix != LONG_IMG || scale != 1.0 || zero != 2147483648.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } *intlength = 4; idata = (int *) tiledata; uintbuff = (unsigned int *) tiledata; /* offset the unsigned value by -2147483648 to a signed int value. */ /* It is more efficient to do this by just flipping the most significant of the 32 bits */ if (nullcheck == 1) { /* reset pixels equal to flagval to nullval and */ /* offset the other pixel values (by flipping the MSB) */ uintflagval = *(unsigned int *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (uintbuff[ii] == uintflagval) idata[ii] = nullval; else uintbuff[ii] = (uintbuff[ii]) ^ 0x80000000; } } else { /* just offset the pixel values (by flipping the MSB) */ for (ii = tilelen - 1; ii >= 0; ii--) uintbuff[ii] = (uintbuff[ii]) ^ 0x80000000; } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tbyte( fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input unsigned integer*1 tile array in place to 4 or 8-byte ints for compression, */ /* If needed, convert 4 or 8-byte ints and do null value substitution. */ /* Note that the calling routine must have allocated the input array big enough */ /* to be able to do this. */ int flagval, *idata; long ii; unsigned char *usbbuff; /* datatype of input array is unsigned byte. We only support writing this datatype to a FITS image with BITPIX = 8 and with BZERO = 0 and BSCALE = 1. */ if (zbitpix != BYTE_IMG || scale != 1.0 || zero != 0.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } idata = (int *) tiledata; usbbuff = (unsigned char *) tiledata; if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1 || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) { /* don't have to convert to int if using gzip, bzip2, or Rice compression */ *intlength = 1; if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(unsigned char *) (nullflagval); if (flagval != nullval) { for (ii = tilelen - 1; ii >= 0; ii--) { if (usbbuff[ii] == (unsigned char) flagval) usbbuff[ii] = (unsigned char) nullval; } } } } else { /* have to convert to int if using HCOMPRESS or PLIO */ *intlength = 4; if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(unsigned char *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (usbbuff[ii] == (unsigned char) flagval) idata[ii] = nullval; else idata[ii] = (int) usbbuff[ii]; } } else { /* just do the data type conversion to int */ /* have to convert usbbuff to an I*4 array, in place */ /* usbbuff must have been allocated large enough to do this */ fits_ubyte_to_int_inplace(usbbuff, tilelen, status); } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tsbyte( fitsfile *outfptr, void *tiledata, long tilelen, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input integer*1 tile array in place to 4 or 8-byte ints for compression, */ /* If needed, convert 4 or 8-byte ints and do null value substitution. */ /* Note that the calling routine must have allocated the input array big enough */ /* to be able to do this. */ int flagval, *idata; long ii; signed char *sbbuff; /* datatype of input array is signed byte. We only support writing this datatype to a FITS image with BITPIX = 8 and with BZERO = 0 and BSCALE = -128. */ if (zbitpix != BYTE_IMG|| scale != 1.0 || zero != -128.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } idata = (int *) tiledata; sbbuff = (signed char *) tiledata; if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1 || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) { /* don't have to convert to int if using gzip, bzip2 or Rice compression */ *intlength = 1; if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ /* offset the other pixel values (by flipping the MSB) */ flagval = *(signed char *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (sbbuff[ii] == (signed char) flagval) sbbuff[ii] = (signed char) nullval; else sbbuff[ii] = (sbbuff[ii]) ^ 0x80; } } else { /* just offset the pixel values (by flipping the MSB) */ for (ii = tilelen - 1; ii >= 0; ii--) sbbuff[ii] = (sbbuff[ii]) ^ 0x80; } } else { /* have to convert to int if using HCOMPRESS or PLIO */ *intlength = 4; if (nullcheck == 1) { /* reset pixels equal to flagval to the FITS null value, prior to compression */ flagval = *(signed char *) (nullflagval); for (ii = tilelen - 1; ii >= 0; ii--) { if (sbbuff[ii] == (signed char) flagval) idata[ii] = nullval; else idata[ii] = ((int) sbbuff[ii]) + 128; } } else { /* just do the data type conversion to int */ /* have to convert sbbuff to an I*4 array, in place */ /* sbbuff must have been allocated large enough to do this */ fits_sbyte_to_int_inplace(sbbuff, tilelen, status); } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tfloat( fitsfile *outfptr, long row, void *tiledata, long tilelen, long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input float tile array in place to 4 or 8-byte ints for compression, */ /* If needed, convert 4 or 8-byte ints and do null value substitution. */ /* Note that the calling routine must have allocated the input array big enough */ /* to be able to do this. */ int *idata; long irow, ii; float floatnull; unsigned char *usbbuff; unsigned long dithersum; int iminval = 0, imaxval = 0; /* min and max quantized integers */ /* datatype of input array is double. We only support writing this datatype to a FITS image with BITPIX = -64 or -32, except we also support the special case where BITPIX = 32 and BZERO = 0 and BSCALE = 1. */ if ((zbitpix != LONG_IMG && zbitpix != DOUBLE_IMG && zbitpix != FLOAT_IMG) || scale != 1.0 || zero != 0.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } *intlength = 4; idata = (int *) tiledata; /* if the tile-compressed table contains zscale and zzero columns */ /* then scale and quantize the input floating point data. */ if ((outfptr->Fptr)->cn_zscale > 0) { /* quantize the float values into integers */ if (nullcheck == 1) floatnull = *(float *) (nullflagval); else floatnull = FLOATNULLVALUE; /* NaNs are represented by this, by default */ if ((outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 || (outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) { /* see if the dithering offset value needs to be initialized */ if ((outfptr->Fptr)->request_dither_seed == 0 && (outfptr->Fptr)->dither_seed == 0) { /* This means randomly choose the dithering offset based on the system time. */ /* The offset will have a value between 1 and 10000, inclusive. */ /* The time function returns an integer value that is incremented each second. */ /* The clock function returns the elapsed CPU time, in integer CLOCKS_PER_SEC units. */ /* The CPU time returned by clock is typically (on linux PC) only good to 0.01 sec */ /* Summing the 2 quantities may help avoid cases where 2 executions of the program */ /* (perhaps in a multithreaded environoment) end up with exactly the same dither seed */ /* value. The sum is incremented by the current HDU number in the file to provide */ /* further randomization. This randomization is desireable if multiple compressed */ /* images will be summed (or differenced). In such cases, the benefits of dithering */ /* may be lost if all the images use exactly the same sequence of random numbers when */ /* calculating the dithering offsets. */ (outfptr->Fptr)->dither_seed = (( (int)time(NULL) + ( (int) clock() / (int) (CLOCKS_PER_SEC / 100)) + (outfptr->Fptr)->curhdu) % 10000) + 1; /* update the header keyword with this new value */ fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), NULL, status); } else if ((outfptr->Fptr)->request_dither_seed < 0 && (outfptr->Fptr)->dither_seed < 0) { /* this means randomly choose the dithering offset based on some hash function */ /* of the first input tile of data to be quantized and compressed. This ensures that */ /* the same offset value is used for a given image every time it is compressed. */ usbbuff = (unsigned char *) tiledata; dithersum = 0; for (ii = 0; ii < 4 * tilelen; ii++) { dithersum += usbbuff[ii]; /* doesn't matter if there is an integer overflow */ } (outfptr->Fptr)->dither_seed = ((int) (dithersum % 10000)) + 1; /* update the header keyword with this new value */ fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), NULL, status); } /* subtract 1 to convert from 1-based to 0-based element number */ irow = row + (outfptr->Fptr)->dither_seed - 1; /* dither the quantized values */ } else if ((outfptr->Fptr)->quantize_method == -1) { irow = 0; /* do not dither the quantized values */ } else { ffpmsg("Unknown dithering method."); ffpmsg("May need to install a newer version of CFITSIO."); return(*status = DATA_COMPRESSION_ERR); } *flag = fits_quantize_float (irow, (float *) tiledata, tilenx, tileny, nullcheck, floatnull, (outfptr->Fptr)->quantize_level, (outfptr->Fptr)->quantize_method, idata, bscale, bzero, &iminval, &imaxval); if (*flag > 1) return(*status = *flag); } else if ((outfptr->Fptr)->quantize_level != NO_QUANTIZE) { /* if floating point pixels are not being losslessly compressed, then */ /* input float data is implicitly converted (truncated) to integers */ if ((scale != 1. || zero != 0.)) /* must scale the values */ imcomp_nullscalefloats((float *) tiledata, tilelen, idata, scale, zero, nullcheck, *(float *) (nullflagval), nullval, status); else imcomp_nullfloats((float *) tiledata, tilelen, idata, nullcheck, *(float *) (nullflagval), nullval, status); } else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE) { /* just convert null values to NaNs in place, if necessary, then do lossless gzip compression */ if (nullcheck == 1) { imcomp_float2nan((float *) tiledata, tilelen, (int *) tiledata, *(float *) (nullflagval), status); } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_convert_tile_tdouble( fitsfile *outfptr, long row, void *tiledata, long tilelen, long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero, int *status) { /* Prepare the input tile array of pixels for compression. */ /* Convert input double tile array in place to 4-byte ints for compression, */ /* If needed, convert 4 or 8-byte ints and do null value substitution. */ /* Note that the calling routine must have allocated the input array big enough */ /* to be able to do this. */ int *idata; long irow, ii; double doublenull; unsigned char *usbbuff; unsigned long dithersum; int iminval = 0, imaxval = 0; /* min and max quantized integers */ /* datatype of input array is double. We only support writing this datatype to a FITS image with BITPIX = -64 or -32, except we also support the special case where BITPIX = 32 and BZERO = 0 and BSCALE = 1. */ if ((zbitpix != LONG_IMG && zbitpix != DOUBLE_IMG && zbitpix != FLOAT_IMG) || scale != 1.0 || zero != 0.) { ffpmsg("Implicit datatype conversion is not supported when writing to compressed images"); return(*status = DATA_COMPRESSION_ERR); } *intlength = 4; idata = (int *) tiledata; /* if the tile-compressed table contains zscale and zzero columns */ /* then scale and quantize the input floating point data. */ /* Otherwise, just truncate the floats to integers. */ if ((outfptr->Fptr)->cn_zscale > 0) { if (nullcheck == 1) doublenull = *(double *) (nullflagval); else doublenull = DOUBLENULLVALUE; /* quantize the double values into integers */ if ((outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 || (outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) { /* see if the dithering offset value needs to be initialized (see above) */ if ((outfptr->Fptr)->request_dither_seed == 0 && (outfptr->Fptr)->dither_seed == 0) { (outfptr->Fptr)->dither_seed = (( (int)time(NULL) + ( (int) clock() / (int) (CLOCKS_PER_SEC / 100)) + (outfptr->Fptr)->curhdu) % 10000) + 1; /* update the header keyword with this new value */ fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), NULL, status); } else if ((outfptr->Fptr)->request_dither_seed < 0 && (outfptr->Fptr)->dither_seed < 0) { usbbuff = (unsigned char *) tiledata; dithersum = 0; for (ii = 0; ii < 8 * tilelen; ii++) { dithersum += usbbuff[ii]; } (outfptr->Fptr)->dither_seed = ((int) (dithersum % 10000)) + 1; /* update the header keyword with this new value */ fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), NULL, status); } irow = row + (outfptr->Fptr)->dither_seed - 1; /* dither the quantized values */ } else if ((outfptr->Fptr)->quantize_method == -1) { irow = 0; /* do not dither the quantized values */ } else { ffpmsg("Unknown subtractive dithering method."); ffpmsg("May need to install a newer version of CFITSIO."); return(*status = DATA_COMPRESSION_ERR); } *flag = fits_quantize_double (irow, (double *) tiledata, tilenx, tileny, nullcheck, doublenull, (outfptr->Fptr)->quantize_level, (outfptr->Fptr)->quantize_method, idata, bscale, bzero, &iminval, &imaxval); if (*flag > 1) return(*status = *flag); } else if ((outfptr->Fptr)->quantize_level != NO_QUANTIZE) { /* if floating point pixels are not being losslessly compressed, then */ /* input float data is implicitly converted (truncated) to integers */ if ((scale != 1. || zero != 0.)) /* must scale the values */ imcomp_nullscaledoubles((double *) tiledata, tilelen, idata, scale, zero, nullcheck, *(double *) (nullflagval), nullval, status); else imcomp_nulldoubles((double *) tiledata, tilelen, idata, nullcheck, *(double *) (nullflagval), nullval, status); } else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE) { /* just convert null values to NaNs in place, if necessary, then do lossless gzip compression */ if (nullcheck == 1) { imcomp_double2nan((double *) tiledata, tilelen, (LONGLONG *) tiledata, *(double *) (nullflagval), status); } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullscale( int *idata, long tilelen, int nullflagval, int nullval, double scale, double zero, int *status) /* do null value substitution AND scaling of the integer array. If array value = nullflagval, then set the value to nullval. Otherwise, inverse scale the integer value. */ { long ii; double dvalue; for (ii=0; ii < tilelen; ii++) { if (idata[ii] == nullflagval) idata[ii] = nullval; else { dvalue = (idata[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullvalues( int *idata, long tilelen, int nullflagval, int nullval, int *status) /* do null value substitution. If array value = nullflagval, then set the value to nullval. */ { long ii; for (ii=0; ii < tilelen; ii++) { if (idata[ii] == nullflagval) idata[ii] = nullval; } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_scalevalues( int *idata, long tilelen, double scale, double zero, int *status) /* do inverse scaling the integer values. */ { long ii; double dvalue; for (ii=0; ii < tilelen; ii++) { dvalue = (idata[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullscalei2( short *idata, long tilelen, short nullflagval, short nullval, double scale, double zero, int *status) /* do null value substitution AND scaling of the integer array. If array value = nullflagval, then set the value to nullval. Otherwise, inverse scale the integer value. */ { long ii; double dvalue; for (ii=0; ii < tilelen; ii++) { if (idata[ii] == nullflagval) idata[ii] = nullval; else { dvalue = (idata[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; idata[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; idata[ii] = SHRT_MAX; } else { if (dvalue >= 0) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullvaluesi2( short *idata, long tilelen, short nullflagval, short nullval, int *status) /* do null value substitution. If array value = nullflagval, then set the value to nullval. */ { long ii; for (ii=0; ii < tilelen; ii++) { if (idata[ii] == nullflagval) idata[ii] = nullval; } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_scalevaluesi2( short *idata, long tilelen, double scale, double zero, int *status) /* do inverse scaling the integer values. */ { long ii; double dvalue; for (ii=0; ii < tilelen; ii++) { dvalue = (idata[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; idata[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; idata[ii] = SHRT_MAX; } else { if (dvalue >= 0) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullfloats( float *fdata, long tilelen, int *idata, int nullcheck, float nullflagval, int nullval, int *status) /* do null value substitution of the float array. If array value = nullflagval, then set the output value to FLOATNULLVALUE. */ { long ii; double dvalue; if (nullcheck == 1) /* must check for null values */ { for (ii=0; ii < tilelen; ii++) { if (fdata[ii] == nullflagval) idata[ii] = nullval; else { dvalue = fdata[ii]; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } } else /* don't have to worry about null values */ { for (ii=0; ii < tilelen; ii++) { dvalue = fdata[ii]; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullscalefloats( float *fdata, long tilelen, int *idata, double scale, double zero, int nullcheck, float nullflagval, int nullval, int *status) /* do null value substitution of the float array. If array value = nullflagval, then set the output value to FLOATNULLVALUE. Otherwise, inverse scale the integer value. */ { long ii; double dvalue; if (nullcheck == 1) /* must check for null values */ { for (ii=0; ii < tilelen; ii++) { if (fdata[ii] == nullflagval) idata[ii] = nullval; else { dvalue = (fdata[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0.) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } } else /* don't have to worry about null values */ { for (ii=0; ii < tilelen; ii++) { dvalue = (fdata[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0.) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nulldoubles( double *fdata, long tilelen, int *idata, int nullcheck, double nullflagval, int nullval, int *status) /* do null value substitution of the float array. If array value = nullflagval, then set the output value to FLOATNULLVALUE. Otherwise, inverse scale the integer value. */ { long ii; double dvalue; if (nullcheck == 1) /* must check for null values */ { for (ii=0; ii < tilelen; ii++) { if (fdata[ii] == nullflagval) idata[ii] = nullval; else { dvalue = fdata[ii]; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0.) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } } else /* don't have to worry about null values */ { for (ii=0; ii < tilelen; ii++) { dvalue = fdata[ii]; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0.) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } return(*status); } /*---------------------------------------------------------------------------*/ int imcomp_nullscaledoubles( double *fdata, long tilelen, int *idata, double scale, double zero, int nullcheck, double nullflagval, int nullval, int *status) /* do null value substitution of the float array. If array value = nullflagval, then set the output value to FLOATNULLVALUE. Otherwise, inverse scale the integer value. */ { long ii; double dvalue; if (nullcheck == 1) /* must check for null values */ { for (ii=0; ii < tilelen; ii++) { if (fdata[ii] == nullflagval) idata[ii] = nullval; else { dvalue = (fdata[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0.) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } } else /* don't have to worry about null values */ { for (ii=0; ii < tilelen; ii++) { dvalue = (fdata[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; idata[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; idata[ii] = INT32_MAX; } else { if (dvalue >= 0.) idata[ii] = (int) (dvalue + .5); else idata[ii] = (int) (dvalue - .5); } } } return(*status); } /*---------------------------------------------------------------------------*/ int fits_write_compressed_img(fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the array to be written */ long *infpixel, /* I - 'bottom left corner' of the subsection */ long *inlpixel, /* I - 'top right corner' of the subsection */ int nullcheck, /* I - 0 for no null checking */ /* 1: pixels that are = nullval will be */ /* written with the FITS null pixel value */ /* (floating point arrays only) */ void *array, /* I - array of values to be written */ void *nullval, /* I - undefined pixel value */ int *status) /* IO - error status */ /* Write a section of a compressed image. */ { int tiledim[MAX_COMPRESS_DIM]; long naxis[MAX_COMPRESS_DIM]; long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM]; long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM]; long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM]; long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp; long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM]; long i5, i4, i3, i2, i1, i0, irow, trowsize, ntrows; int ii, ndim, pixlen, tilenul; int tstatus, buffpixsiz; void *buffer; char *bnullarray = 0, card[FLEN_CARD]; if (*status > 0) return(*status); if (!fits_is_compressed_image(fptr, status) ) { ffpmsg("CHDU is not a compressed image (fits_write_compressed_img)"); return(*status = DATA_COMPRESSION_ERR); } /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); /* ===================================================================== */ if (datatype == TSHORT || datatype == TUSHORT) { pixlen = sizeof(short); } else if (datatype == TINT || datatype == TUINT) { pixlen = sizeof(int); } else if (datatype == TBYTE || datatype == TSBYTE) { pixlen = 1; } else if (datatype == TLONG || datatype == TULONG) { pixlen = sizeof(long); } else if (datatype == TFLOAT) { pixlen = sizeof(float); } else if (datatype == TDOUBLE) { pixlen = sizeof(double); } else { ffpmsg("unsupported datatype for compressing image"); return(*status = BAD_DATATYPE); } /* ===================================================================== */ /* allocate scratch space for processing one tile of the image */ buffpixsiz = pixlen; /* this is the minimum pixel size */ if ( (fptr->Fptr)->compress_type == HCOMPRESS_1) { /* need 4 or 8 bytes per pixel */ if ((fptr->Fptr)->zbitpix == BYTE_IMG || (fptr->Fptr)->zbitpix == SHORT_IMG ) buffpixsiz = maxvalue(buffpixsiz, 4); else buffpixsiz = 8; } else if ( (fptr->Fptr)->compress_type == PLIO_1) { /* need 4 bytes per pixel */ buffpixsiz = maxvalue(buffpixsiz, 4); } else if ( (fptr->Fptr)->compress_type == RICE_1 || (fptr->Fptr)->compress_type == GZIP_1 || (fptr->Fptr)->compress_type == GZIP_2 || (fptr->Fptr)->compress_type == BZIP2_1) { /* need 1, 2, or 4 bytes per pixel */ if ((fptr->Fptr)->zbitpix == BYTE_IMG) buffpixsiz = maxvalue(buffpixsiz, 1); else if ((fptr->Fptr)->zbitpix == SHORT_IMG) buffpixsiz = maxvalue(buffpixsiz, 2); else buffpixsiz = maxvalue(buffpixsiz, 4); } else { ffpmsg("unsupported image compression algorithm"); return(*status = BAD_DATATYPE); } /* cast to double to force alignment on 8-byte addresses */ buffer = (double *) calloc ((fptr->Fptr)->maxtilelen, buffpixsiz); if (buffer == NULL) { ffpmsg("Out of memory (fits_write_compress_img)"); return (*status = MEMORY_ALLOCATION); } /* ===================================================================== */ /* initialize all the arrays */ for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { naxis[ii] = 1; tiledim[ii] = 1; tilesize[ii] = 1; ftile[ii] = 1; ltile[ii] = 1; rowdim[ii] = 1; } ndim = (fptr->Fptr)->zndim; ntemp = 1; for (ii = 0; ii < ndim; ii++) { fpixel[ii] = infpixel[ii]; lpixel[ii] = inlpixel[ii]; /* calc number of tiles in each dimension, and tile containing */ /* the first and last pixel we want to read in each dimension */ naxis[ii] = (fptr->Fptr)->znaxis[ii]; if (fpixel[ii] < 1) { free(buffer); return(*status = BAD_PIX_NUM); } tilesize[ii] = (fptr->Fptr)->tilesize[ii]; tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1; ftile[ii] = (fpixel[ii] - 1) / tilesize[ii] + 1; ltile[ii] = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, tiledim[ii]); rowdim[ii] = ntemp; /* total tiles in each dimension */ ntemp *= tiledim[ii]; } /* support up to 6 dimensions for now */ /* tfpixel and tlpixel are the first and last image pixels */ /* along each dimension of the compression tile */ for (i5 = ftile[5]; i5 <= ltile[5]; i5++) { tfpixel[5] = (i5 - 1) * tilesize[5] + 1; tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, naxis[5]); thistilesize[5] = tlpixel[5] - tfpixel[5] + 1; offset[5] = (i5 - 1) * rowdim[5]; for (i4 = ftile[4]; i4 <= ltile[4]; i4++) { tfpixel[4] = (i4 - 1) * tilesize[4] + 1; tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, naxis[4]); thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1); offset[4] = (i4 - 1) * rowdim[4] + offset[5]; for (i3 = ftile[3]; i3 <= ltile[3]; i3++) { tfpixel[3] = (i3 - 1) * tilesize[3] + 1; tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, naxis[3]); thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1); offset[3] = (i3 - 1) * rowdim[3] + offset[4]; for (i2 = ftile[2]; i2 <= ltile[2]; i2++) { tfpixel[2] = (i2 - 1) * tilesize[2] + 1; tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, naxis[2]); thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1); offset[2] = (i2 - 1) * rowdim[2] + offset[3]; for (i1 = ftile[1]; i1 <= ltile[1]; i1++) { tfpixel[1] = (i1 - 1) * tilesize[1] + 1; tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, naxis[1]); thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1); offset[1] = (i1 - 1) * rowdim[1] + offset[2]; for (i0 = ftile[0]; i0 <= ltile[0]; i0++) { tfpixel[0] = (i0 - 1) * tilesize[0] + 1; tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, naxis[0]); thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1); /* calculate row of table containing this tile */ irow = i0 + offset[1]; /* read and uncompress this row (tile) of the table */ /* also do type conversion and undefined pixel substitution */ /* at this point */ imcomp_decompress_tile(fptr, irow, thistilesize[0], datatype, nullcheck, nullval, buffer, bnullarray, &tilenul, status); if (*status == NO_COMPRESSED_TILE) { /* tile doesn't exist, so initialize to zero */ memset(buffer, 0, pixlen * thistilesize[0]); *status = 0; } /* copy the intersecting pixels to this tile from the input */ imcomp_merge_overlap(buffer, pixlen, ndim, tfpixel, tlpixel, bnullarray, array, fpixel, lpixel, nullcheck, status); /* Collapse sizes of higher dimension tiles into 2 dimensional equivalents needed by the quantizing algorithms for floating point types */ fits_calc_tile_rows(tlpixel, tfpixel, ndim, &trowsize, &ntrows, status); /* compress the tile again, and write it back to the FITS file */ imcomp_compress_tile (fptr, irow, datatype, buffer, thistilesize[0], trowsize, ntrows, nullcheck, nullval, status); } } } } } } free(buffer); if ((fptr->Fptr)->zbitpix < 0 && nullcheck != 0) { /* This is a floating point FITS image with possible null values. It is too messy to test if any null values are actually written, so just assume so. We need to make sure that the ZBLANK keyword is present in the compressed image header. If it is not there then we need to insert the keyword. */ tstatus = 0; ffgcrd(fptr, "ZBLANK", card, &tstatus); if (tstatus) { /* have to insert the ZBLANK keyword */ ffgcrd(fptr, "ZCMPTYPE", card, status); ffikyj(fptr, "ZBLANK", COMPRESS_NULL_VALUE, "null value in the compressed integer array", status); /* set this value into the internal structure; it is used if */ /* the program reads back the values from the array */ (fptr->Fptr)->zblank = COMPRESS_NULL_VALUE; (fptr->Fptr)->cn_zblank = -1; /* flag for a constant ZBLANK */ } } return(*status); } /*--------------------------------------------------------------------------*/ int fits_write_compressed_pixels(fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the array to be written */ LONGLONG fpixel, /* I - 'first pixel to write */ LONGLONG npixel, /* I - number of pixels to write */ int nullcheck, /* I - 0 for no null checking */ /* 1: pixels that are = nullval will be */ /* written with the FITS null pixel value */ /* (floating point arrays only) */ void *array, /* I - array of values to write */ void *nullval, /* I - value used to represent undefined pixels*/ int *status) /* IO - error status */ /* Write a consecutive set of pixels to a compressed image. This routine interpretes the n-dimensional image as a long one-dimensional array. This is actually a rather inconvenient way to write compressed images in general, and could be rather inefficient if the requested pixels to be written are located in many different image compression tiles. The general strategy used here is to write the requested pixels in blocks that correspond to rectangular image sections. */ { int naxis, ii, bytesperpixel; long naxes[MAX_COMPRESS_DIM], nread; LONGLONG tfirst, tlast, last0, last1, dimsize[MAX_COMPRESS_DIM]; long nplane, firstcoord[MAX_COMPRESS_DIM], lastcoord[MAX_COMPRESS_DIM]; char *arrayptr; if (*status > 0) return(*status); arrayptr = (char *) array; /* get size of array pixels, in bytes */ bytesperpixel = ffpxsz(datatype); for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { naxes[ii] = 1; firstcoord[ii] = 0; lastcoord[ii] = 0; } /* determine the dimensions of the image to be written */ ffgidm(fptr, &naxis, status); ffgisz(fptr, MAX_COMPRESS_DIM, naxes, status); /* calc the cumulative number of pixels in each successive dimension */ dimsize[0] = 1; for (ii = 1; ii < MAX_COMPRESS_DIM; ii++) dimsize[ii] = dimsize[ii - 1] * naxes[ii - 1]; /* determine the coordinate of the first and last pixel in the image */ /* Use zero based indexes here */ tfirst = fpixel - 1; tlast = tfirst + npixel - 1; for (ii = naxis - 1; ii >= 0; ii--) { firstcoord[ii] = (long) (tfirst / dimsize[ii]); lastcoord[ii] = (long) (tlast / dimsize[ii]); tfirst = tfirst - firstcoord[ii] * dimsize[ii]; tlast = tlast - lastcoord[ii] * dimsize[ii]; } /* to simplify things, treat 1-D, 2-D, and 3-D images as separate cases */ if (naxis == 1) { /* Simple: just write the requested range of pixels */ firstcoord[0] = firstcoord[0] + 1; lastcoord[0] = lastcoord[0] + 1; fits_write_compressed_img(fptr, datatype, firstcoord, lastcoord, nullcheck, array, nullval, status); return(*status); } else if (naxis == 2) { nplane = 0; /* write 1st (and only) plane of the image */ fits_write_compressed_img_plane(fptr, datatype, bytesperpixel, nplane, firstcoord, lastcoord, naxes, nullcheck, array, nullval, &nread, status); } else if (naxis == 3) { /* test for special case: writing an integral number of planes */ if (firstcoord[0] == 0 && firstcoord[1] == 0 && lastcoord[0] == naxes[0] - 1 && lastcoord[1] == naxes[1] - 1) { for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { /* convert from zero base to 1 base */ (firstcoord[ii])++; (lastcoord[ii])++; } /* we can write the contiguous block of pixels in one go */ fits_write_compressed_img(fptr, datatype, firstcoord, lastcoord, nullcheck, array, nullval, status); return(*status); } /* save last coordinate in temporary variables */ last0 = lastcoord[0]; last1 = lastcoord[1]; if (firstcoord[2] < lastcoord[2]) { /* we will write up to the last pixel in all but the last plane */ lastcoord[0] = naxes[0] - 1; lastcoord[1] = naxes[1] - 1; } /* write one plane of the cube at a time, for simplicity */ for (nplane = firstcoord[2]; nplane <= lastcoord[2]; nplane++) { if (nplane == lastcoord[2]) { lastcoord[0] = (long) last0; lastcoord[1] = (long) last1; } fits_write_compressed_img_plane(fptr, datatype, bytesperpixel, nplane, firstcoord, lastcoord, naxes, nullcheck, arrayptr, nullval, &nread, status); /* for all subsequent planes, we start with the first pixel */ firstcoord[0] = 0; firstcoord[1] = 0; /* increment pointers to next elements to be written */ arrayptr = arrayptr + nread * bytesperpixel; } } else { ffpmsg("only 1D, 2D, or 3D images are currently supported"); return(*status = DATA_COMPRESSION_ERR); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_write_compressed_img_plane(fitsfile *fptr, /* I - FITS file */ int datatype, /* I - datatype of the array to be written */ int bytesperpixel, /* I - number of bytes per pixel in array */ long nplane, /* I - which plane of the cube to write */ long *firstcoord, /* I coordinate of first pixel to write */ long *lastcoord, /* I coordinate of last pixel to write */ long *naxes, /* I size of each image dimension */ int nullcheck, /* I - 0 for no null checking */ /* 1: pixels that are = nullval will be */ /* written with the FITS null pixel value */ /* (floating point arrays only) */ void *array, /* I - array of values that are written */ void *nullval, /* I - value for undefined pixels */ long *nread, /* O - total number of pixels written */ int *status) /* IO - error status */ /* in general we have to write the first partial row of the image, followed by the middle complete rows, followed by the last partial row of the image. If the first or last rows are complete, then write them at the same time as all the middle rows. */ { /* bottom left coord. and top right coord. */ long blc[MAX_COMPRESS_DIM], trc[MAX_COMPRESS_DIM]; char *arrayptr; *nread = 0; arrayptr = (char *) array; blc[2] = nplane + 1; trc[2] = nplane + 1; if (firstcoord[0] != 0) { /* have to read a partial first row */ blc[0] = firstcoord[0] + 1; blc[1] = firstcoord[1] + 1; trc[1] = blc[1]; if (lastcoord[1] == firstcoord[1]) trc[0] = lastcoord[0] + 1; /* 1st and last pixels in same row */ else trc[0] = naxes[0]; /* read entire rest of the row */ fits_write_compressed_img(fptr, datatype, blc, trc, nullcheck, arrayptr, nullval, status); *nread = *nread + trc[0] - blc[0] + 1; if (lastcoord[1] == firstcoord[1]) { return(*status); /* finished */ } /* set starting coord to beginning of next line */ firstcoord[0] = 0; firstcoord[1] += 1; arrayptr = arrayptr + (trc[0] - blc[0] + 1) * bytesperpixel; } /* write contiguous complete rows of the image, if any */ blc[0] = 1; blc[1] = firstcoord[1] + 1; trc[0] = naxes[0]; if (lastcoord[0] + 1 == naxes[0]) { /* can write the last complete row, too */ trc[1] = lastcoord[1] + 1; } else { /* last row is incomplete; have to read it separately */ trc[1] = lastcoord[1]; } if (trc[1] >= blc[1]) /* must have at least one whole line to read */ { fits_write_compressed_img(fptr, datatype, blc, trc, nullcheck, arrayptr, nullval, status); *nread = *nread + (trc[1] - blc[1] + 1) * naxes[0]; if (lastcoord[1] + 1 == trc[1]) return(*status); /* finished */ /* increment pointers for the last partial row */ arrayptr = arrayptr + (trc[1] - blc[1] + 1) * naxes[0] * bytesperpixel; } if (trc[1] == lastcoord[1] + 1) return(*status); /* all done */ /* set starting and ending coord to last line */ trc[0] = lastcoord[0] + 1; trc[1] = lastcoord[1] + 1; blc[1] = trc[1]; fits_write_compressed_img(fptr, datatype, blc, trc, nullcheck, arrayptr, nullval, status); *nread = *nread + trc[0] - blc[0] + 1; return(*status); } /* ######################################################################## */ /* ### Image Decompression Routines ### */ /* ######################################################################## */ /*--------------------------------------------------------------------------*/ int fits_img_decompress (fitsfile *infptr, /* image (bintable) to uncompress */ fitsfile *outfptr, /* empty HDU for output uncompressed image */ int *status) /* IO - error status */ /* This routine decompresses the whole image and writes it to the output file. */ { int ii, datatype = 0; int nullcheck, anynul; LONGLONG fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM]; long inc[MAX_COMPRESS_DIM]; long imgsize; float *nulladdr, fnulval; double dnulval; if (fits_img_decompress_header(infptr, outfptr, status) > 0) { return (*status); } /* force a rescan of the output header keywords, then reset the scaling */ /* in case the BSCALE and BZERO keywords are present, so that the */ /* decompressed values won't be scaled when written to the output image */ ffrdef(outfptr, status); ffpscl(outfptr, 1.0, 0.0, status); ffpscl(infptr, 1.0, 0.0, status); /* initialize; no null checking is needed for integer images */ nullcheck = 0; nulladdr = &fnulval; /* determine datatype for image */ if ((infptr->Fptr)->zbitpix == BYTE_IMG) { datatype = TBYTE; } else if ((infptr->Fptr)->zbitpix == SHORT_IMG) { datatype = TSHORT; } else if ((infptr->Fptr)->zbitpix == LONG_IMG) { datatype = TINT; } else if ((infptr->Fptr)->zbitpix == FLOAT_IMG) { /* In the case of float images we must check for NaNs */ nullcheck = 1; fnulval = FLOATNULLVALUE; nulladdr = &fnulval; datatype = TFLOAT; } else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG) { /* In the case of double images we must check for NaNs */ nullcheck = 1; dnulval = DOUBLENULLVALUE; nulladdr = (float *) &dnulval; datatype = TDOUBLE; } /* calculate size of the image (in pixels) */ imgsize = 1; for (ii = 0; ii < (infptr->Fptr)->zndim; ii++) { imgsize *= (infptr->Fptr)->znaxis[ii]; fpixel[ii] = 1; /* Set first and last pixel to */ lpixel[ii] = (infptr->Fptr)->znaxis[ii]; /* include the entire image. */ inc[ii] = 1; } /* uncompress the input image and write to output image, one tile at a time */ fits_read_write_compressed_img(infptr, datatype, fpixel, lpixel, inc, nullcheck, nulladdr, &anynul, outfptr, status); return (*status); } /*--------------------------------------------------------------------------*/ int fits_decompress_img (fitsfile *infptr, /* image (bintable) to uncompress */ fitsfile *outfptr, /* empty HDU for output uncompressed image */ int *status) /* IO - error status */ /* THIS IS AN OBSOLETE ROUTINE. USE fits_img_decompress instead!!! This routine decompresses the whole image and writes it to the output file. */ { double *data; int ii, datatype = 0, byte_per_pix = 0; int nullcheck, anynul; LONGLONG fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM]; long inc[MAX_COMPRESS_DIM]; long imgsize, memsize; float *nulladdr, fnulval; double dnulval; if (*status > 0) return(*status); if (!fits_is_compressed_image(infptr, status) ) { ffpmsg("CHDU is not a compressed image (fits_decompress_img)"); return(*status = DATA_DECOMPRESSION_ERR); } /* create an empty output image with the correct dimensions */ if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, (infptr->Fptr)->znaxis, status) > 0) { ffpmsg("error creating output decompressed image HDU"); return (*status); } /* Copy the table header to the image header. */ if (imcomp_copy_imheader(infptr, outfptr, status) > 0) { ffpmsg("error copying header of compressed image"); return (*status); } /* force a rescan of the output header keywords, then reset the scaling */ /* in case the BSCALE and BZERO keywords are present, so that the */ /* decompressed values won't be scaled when written to the output image */ ffrdef(outfptr, status); ffpscl(outfptr, 1.0, 0.0, status); ffpscl(infptr, 1.0, 0.0, status); /* initialize; no null checking is needed for integer images */ nullcheck = 0; nulladdr = &fnulval; /* determine datatype for image */ if ((infptr->Fptr)->zbitpix == BYTE_IMG) { datatype = TBYTE; byte_per_pix = 1; } else if ((infptr->Fptr)->zbitpix == SHORT_IMG) { datatype = TSHORT; byte_per_pix = sizeof(short); } else if ((infptr->Fptr)->zbitpix == LONG_IMG) { datatype = TINT; byte_per_pix = sizeof(int); } else if ((infptr->Fptr)->zbitpix == FLOAT_IMG) { /* In the case of float images we must check for NaNs */ nullcheck = 1; fnulval = FLOATNULLVALUE; nulladdr = &fnulval; datatype = TFLOAT; byte_per_pix = sizeof(float); } else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG) { /* In the case of double images we must check for NaNs */ nullcheck = 1; dnulval = DOUBLENULLVALUE; nulladdr = (float *) &dnulval; datatype = TDOUBLE; byte_per_pix = sizeof(double); } /* calculate size of the image (in pixels) */ imgsize = 1; for (ii = 0; ii < (infptr->Fptr)->zndim; ii++) { imgsize *= (infptr->Fptr)->znaxis[ii]; fpixel[ii] = 1; /* Set first and last pixel to */ lpixel[ii] = (infptr->Fptr)->znaxis[ii]; /* include the entire image. */ inc[ii] = 1; } /* Calc equivalent number of double pixels same size as whole the image. */ /* We use double datatype to force the memory to be aligned properly */ memsize = ((imgsize * byte_per_pix) - 1) / sizeof(double) + 1; /* allocate memory for the image */ data = (double*) calloc (memsize, sizeof(double)); if (!data) { ffpmsg("Couldn't allocate memory for the uncompressed image"); return(*status = MEMORY_ALLOCATION); } /* uncompress the entire image into memory */ /* This routine should be enhanced sometime to only need enough */ /* memory to uncompress one tile at a time. */ fits_read_compressed_img(infptr, datatype, fpixel, lpixel, inc, nullcheck, nulladdr, data, NULL, &anynul, status); /* write the image to the output file */ if (anynul) fits_write_imgnull(outfptr, datatype, 1, imgsize, data, nulladdr, status); else fits_write_img(outfptr, datatype, 1, imgsize, data, status); free(data); return (*status); } /*--------------------------------------------------------------------------*/ int fits_img_decompress_header(fitsfile *infptr, /* image (bintable) to uncompress */ fitsfile *outfptr, /* empty HDU for output uncompressed image */ int *status) /* IO - error status */ /* This routine reads the header of the input tile compressed image and converts it to that of a standard uncompress FITS image. */ { int writeprime = 0; int hdupos, inhdupos, numkeys; int nullprime = 0, copyprime = 0, norec = 0, tstatus; char card[FLEN_CARD]; int ii, naxis, bitpix; long naxes[MAX_COMPRESS_DIM]; if (*status > 0) return(*status); else if (*status == -1) { *status = 0; writeprime = 1; } if (!fits_is_compressed_image(infptr, status) ) { ffpmsg("CHDU is not a compressed image (fits_img_decompress)"); return(*status = DATA_DECOMPRESSION_ERR); } /* get information about the state of the output file; does it already */ /* contain any keywords and HDUs? */ fits_get_hdu_num(infptr, &inhdupos); /* Get the current output HDU position */ fits_get_hdu_num(outfptr, &hdupos); /* Get the current output HDU position */ fits_get_hdrspace(outfptr, &numkeys, 0, status); /* Was the input compressed HDU originally the primary array image? */ tstatus = 0; if (!fits_read_card(infptr, "ZSIMPLE", card, &tstatus)) { /* yes, input HDU was a primary array (not an IMAGE extension) */ /* Now determine if we can uncompress it into the primary array of */ /* the output file. This is only possible if the output file */ /* currently only contains a null primary array, with no addition */ /* header keywords and with no following extension in the FITS file. */ if (hdupos == 1) { /* are we positioned at the primary array? */ if (numkeys == 0) { /* primary HDU is completely empty */ nullprime = 1; } else { fits_get_img_param(outfptr, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, status); if (naxis == 0) { /* is this a null image? */ nullprime = 1; if (inhdupos == 2) /* must be at the first extension */ copyprime = 1; } } } } if (nullprime) { /* We will delete the existing keywords in the null primary array and uncompress the input image into the primary array of the output. Some of these keywords may be added back to the uncompressed image header later. */ for (ii = numkeys; ii > 0; ii--) fits_delete_record(outfptr, ii, status); } else { /* if the ZTENSION keyword doesn't exist, then we have to write the required keywords manually */ tstatus = 0; if (fits_read_card(infptr, "ZTENSION", card, &tstatus)) { /* create an empty output image with the correct dimensions */ if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, (infptr->Fptr)->znaxis, status) > 0) { ffpmsg("error creating output decompressed image HDU"); return (*status); } norec = 1; /* the required keywords have already been written */ } else { /* the input compressed image does have ZTENSION keyword */ if (writeprime) { /* convert the image extension to a primary array */ /* have to write the required keywords manually */ /* create an empty output image with the correct dimensions */ if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, (infptr->Fptr)->znaxis, status) > 0) { ffpmsg("error creating output decompressed image HDU"); return (*status); } norec = 1; /* the required keywords have already been written */ } else { /* write the input compressed image to an image extension */ if (numkeys == 0) { /* the output file is currently completely empty */ /* In this case, the input is a compressed IMAGE extension. */ /* Since the uncompressed output file is currently completely empty, */ /* we need to write a null primary array before uncompressing the */ /* image extension */ ffcrim(outfptr, 8, 0, naxes, status); /* naxes is not used */ /* now create the empty extension to uncompress into */ if (fits_create_hdu(outfptr, status) > 0) { ffpmsg("error creating output decompressed image HDU"); return (*status); } } else { /* just create a new empty extension, then copy all the required */ /* keywords into it. */ fits_create_hdu(outfptr, status); } } } } if (*status > 0) { ffpmsg("error creating output decompressed image HDU"); return (*status); } /* Copy the table header to the image header. */ if (imcomp_copy_comp2img(infptr, outfptr, norec, status) > 0) { ffpmsg("error copying header keywords from compressed image"); } if (copyprime) { /* append any unexpected keywords from the primary array. This includes any keywords except SIMPLE, BITPIX, NAXIS, EXTEND, COMMENT, HISTORY, CHECKSUM, and DATASUM. */ fits_movabs_hdu(infptr, 1, NULL, status); /* move to primary array */ /* do this so that any new keywords get written before any blank keywords that may have been appended by imcomp_copy_comp2img */ fits_set_hdustruc(outfptr, status); if (imcomp_copy_prime2img(infptr, outfptr, status) > 0) { ffpmsg("error copying primary keywords from compressed file"); } fits_movabs_hdu(infptr, 2, NULL, status); /* move back to where we were */ } return (*status); } /*---------------------------------------------------------------------------*/ int fits_read_compressed_img(fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the array to be returned */ LONGLONG *infpixel, /* I - 'bottom left corner' of the subsection */ LONGLONG *inlpixel, /* I - 'top right corner' of the subsection */ long *ininc, /* I - increment to be applied in each dimension */ int nullcheck, /* I - 0 for no null checking */ /* 1: set undefined pixels = nullval */ /* 2: set nullarray=1 for undefined pixels */ void *nullval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ char *nullarray, /* O - array of flags = 1 if nullcheck = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a section of a compressed image; Note: lpixel may be larger than the size of the uncompressed image. Only the pixels within the image will be returned. */ { long naxis[MAX_COMPRESS_DIM], tiledim[MAX_COMPRESS_DIM]; long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM]; long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM]; long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM]; long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp; long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM]; long inc[MAX_COMPRESS_DIM]; long i5, i4, i3, i2, i1, i0, irow; int ii, ndim, pixlen, tilenul=0; void *buffer; char *bnullarray = 0; double testnullval = 0.; if (*status > 0) return(*status); if (!fits_is_compressed_image(fptr, status) ) { ffpmsg("CHDU is not a compressed image (fits_read_compressed_img)"); return(*status = DATA_DECOMPRESSION_ERR); } /* get temporary space for uncompressing one image tile */ if (datatype == TSHORT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (short)); pixlen = sizeof(short); if (nullval) testnullval = *(short *) nullval; } else if (datatype == TINT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (int)); pixlen = sizeof(int); if (nullval) testnullval = *(int *) nullval; } else if (datatype == TLONG) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (long)); pixlen = sizeof(long); if (nullval) testnullval = *(long *) nullval; } else if (datatype == TFLOAT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (float)); pixlen = sizeof(float); if (nullval) testnullval = *(float *) nullval; } else if (datatype == TDOUBLE) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (double)); pixlen = sizeof(double); if (nullval) testnullval = *(double *) nullval; } else if (datatype == TUSHORT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned short)); pixlen = sizeof(short); if (nullval) testnullval = *(unsigned short *) nullval; } else if (datatype == TUINT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned int)); pixlen = sizeof(int); if (nullval) testnullval = *(unsigned int *) nullval; } else if (datatype == TULONG) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned long)); pixlen = sizeof(long); if (nullval) testnullval = *(unsigned long *) nullval; } else if (datatype == TBYTE || datatype == TSBYTE) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (char)); pixlen = 1; if (nullval) testnullval = *(unsigned char *) nullval; } else { ffpmsg("unsupported datatype for uncompressing image"); return(*status = BAD_DATATYPE); } /* If nullcheck ==1 and nullval == 0, then this means that the */ /* calling routine does not want to check for null pixels in the array */ if (nullcheck == 1 && testnullval == 0.) nullcheck = 0; if (buffer == NULL) { ffpmsg("Out of memory (fits_read_compress_img)"); return (*status = MEMORY_ALLOCATION); } /* allocate memory for a null flag array, if needed */ if (nullcheck == 2) { bnullarray = calloc ((fptr->Fptr)->maxtilelen, sizeof (char)); if (bnullarray == NULL) { ffpmsg("Out of memory (fits_read_compress_img)"); free(buffer); return (*status = MEMORY_ALLOCATION); } } /* initialize all the arrays */ for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { naxis[ii] = 1; tiledim[ii] = 1; tilesize[ii] = 1; ftile[ii] = 1; ltile[ii] = 1; rowdim[ii] = 1; } ndim = (fptr->Fptr)->zndim; ntemp = 1; for (ii = 0; ii < ndim; ii++) { /* support for mirror-reversed image sections */ if (infpixel[ii] <= inlpixel[ii]) { fpixel[ii] = (long) infpixel[ii]; lpixel[ii] = (long) inlpixel[ii]; inc[ii] = ininc[ii]; } else { fpixel[ii] = (long) inlpixel[ii]; lpixel[ii] = (long) infpixel[ii]; inc[ii] = -ininc[ii]; } /* calc number of tiles in each dimension, and tile containing */ /* the first and last pixel we want to read in each dimension */ naxis[ii] = (fptr->Fptr)->znaxis[ii]; if (fpixel[ii] < 1) { if (nullcheck == 2) { free(bnullarray); } free(buffer); return(*status = BAD_PIX_NUM); } tilesize[ii] = (fptr->Fptr)->tilesize[ii]; tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1; ftile[ii] = (fpixel[ii] - 1) / tilesize[ii] + 1; ltile[ii] = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, tiledim[ii]); rowdim[ii] = ntemp; /* total tiles in each dimension */ ntemp *= tiledim[ii]; } if (anynul) *anynul = 0; /* initialize */ /* support up to 6 dimensions for now */ /* tfpixel and tlpixel are the first and last image pixels */ /* along each dimension of the compression tile */ for (i5 = ftile[5]; i5 <= ltile[5]; i5++) { tfpixel[5] = (i5 - 1) * tilesize[5] + 1; tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, naxis[5]); thistilesize[5] = tlpixel[5] - tfpixel[5] + 1; offset[5] = (i5 - 1) * rowdim[5]; for (i4 = ftile[4]; i4 <= ltile[4]; i4++) { tfpixel[4] = (i4 - 1) * tilesize[4] + 1; tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, naxis[4]); thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1); offset[4] = (i4 - 1) * rowdim[4] + offset[5]; for (i3 = ftile[3]; i3 <= ltile[3]; i3++) { tfpixel[3] = (i3 - 1) * tilesize[3] + 1; tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, naxis[3]); thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1); offset[3] = (i3 - 1) * rowdim[3] + offset[4]; for (i2 = ftile[2]; i2 <= ltile[2]; i2++) { tfpixel[2] = (i2 - 1) * tilesize[2] + 1; tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, naxis[2]); thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1); offset[2] = (i2 - 1) * rowdim[2] + offset[3]; for (i1 = ftile[1]; i1 <= ltile[1]; i1++) { tfpixel[1] = (i1 - 1) * tilesize[1] + 1; tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, naxis[1]); thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1); offset[1] = (i1 - 1) * rowdim[1] + offset[2]; for (i0 = ftile[0]; i0 <= ltile[0]; i0++) { tfpixel[0] = (i0 - 1) * tilesize[0] + 1; tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, naxis[0]); thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1); /* calculate row of table containing this tile */ irow = i0 + offset[1]; /* printf("row %d, %d %d, %d %d, %d %d; %d\n", irow, tfpixel[0],tlpixel[0],tfpixel[1],tlpixel[1],tfpixel[2],tlpixel[2], thistilesize[0]); */ /* test if there are any intersecting pixels in this tile and the output image */ if (imcomp_test_overlap(ndim, tfpixel, tlpixel, fpixel, lpixel, inc, status)) { /* read and uncompress this row (tile) of the table */ /* also do type conversion and undefined pixel substitution */ /* at this point */ imcomp_decompress_tile(fptr, irow, thistilesize[0], datatype, nullcheck, nullval, buffer, bnullarray, &tilenul, status); if (tilenul && anynul) *anynul = 1; /* there are null pixels */ /* printf(" pixlen=%d, ndim=%d, %d %d %d, %d %d %d, %d %d %d\n", pixlen, ndim, fpixel[0],lpixel[0],inc[0],fpixel[1],lpixel[1],inc[1], fpixel[2],lpixel[2],inc[2]); */ /* copy the intersecting pixels from this tile to the output */ imcomp_copy_overlap(buffer, pixlen, ndim, tfpixel, tlpixel, bnullarray, array, fpixel, lpixel, inc, nullcheck, nullarray, status); } } } } } } } if (nullcheck == 2) { free(bnullarray); } free(buffer); return(*status); } /*---------------------------------------------------------------------------*/ int fits_read_write_compressed_img(fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the array to be returned */ LONGLONG *infpixel, /* I - 'bottom left corner' of the subsection */ LONGLONG *inlpixel, /* I - 'top right corner' of the subsection */ long *ininc, /* I - increment to be applied in each dimension */ int nullcheck, /* I - 0 for no null checking */ /* 1: set undefined pixels = nullval */ void *nullval, /* I - value for undefined pixels */ int *anynul, /* O - set to 1 if any values are null; else 0 */ fitsfile *outfptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* This is similar to fits_read_compressed_img, except that it writes the pixels to the output image, on a tile by tile basis instead of returning the array. */ { long naxis[MAX_COMPRESS_DIM], tiledim[MAX_COMPRESS_DIM]; long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM]; long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM]; long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM]; long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp; long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM]; long inc[MAX_COMPRESS_DIM]; long i5, i4, i3, i2, i1, i0, irow; int ii, ndim, tilenul; void *buffer; char *bnullarray = 0, *cnull; LONGLONG firstelem; if (*status > 0) return(*status); if (!fits_is_compressed_image(fptr, status) ) { ffpmsg("CHDU is not a compressed image (fits_read_compressed_img)"); return(*status = DATA_DECOMPRESSION_ERR); } cnull = (char *) nullval; /* used to test if the nullval = 0 */ /* get temporary space for uncompressing one image tile */ /* If nullval == 0, then this means that the */ /* calling routine does not want to check for null pixels in the array */ if (datatype == TSHORT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (short)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 ) { nullcheck = 0; } } } else if (datatype == TINT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (int)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) { nullcheck = 0; } } } else if (datatype == TLONG) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (long)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) { nullcheck = 0; } } } else if (datatype == TFLOAT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (float)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) { nullcheck = 0; } } } else if (datatype == TDOUBLE) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (double)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 && cnull[4] == 0 && cnull[5] == 0 && cnull[6] == 0 && cnull[7] == 0 ) { nullcheck = 0; } } } else if (datatype == TUSHORT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned short)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 ){ nullcheck = 0; } } } else if (datatype == TUINT) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned int)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ){ nullcheck = 0; } } } else if (datatype == TULONG) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned long)); if (cnull) { if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ){ nullcheck = 0; } } } else if (datatype == TBYTE || datatype == TSBYTE) { buffer = malloc ((fptr->Fptr)->maxtilelen * sizeof (char)); if (cnull) { if (cnull[0] == 0){ nullcheck = 0; } } } else { ffpmsg("unsupported datatype for uncompressing image"); return(*status = BAD_DATATYPE); } if (buffer == NULL) { ffpmsg("Out of memory (fits_read_compress_img)"); return (*status = MEMORY_ALLOCATION); } /* initialize all the arrays */ for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { naxis[ii] = 1; tiledim[ii] = 1; tilesize[ii] = 1; ftile[ii] = 1; ltile[ii] = 1; rowdim[ii] = 1; } ndim = (fptr->Fptr)->zndim; ntemp = 1; for (ii = 0; ii < ndim; ii++) { /* support for mirror-reversed image sections */ if (infpixel[ii] <= inlpixel[ii]) { fpixel[ii] = (long) infpixel[ii]; lpixel[ii] = (long) inlpixel[ii]; inc[ii] = ininc[ii]; } else { fpixel[ii] = (long) inlpixel[ii]; lpixel[ii] = (long) infpixel[ii]; inc[ii] = -ininc[ii]; } /* calc number of tiles in each dimension, and tile containing */ /* the first and last pixel we want to read in each dimension */ naxis[ii] = (fptr->Fptr)->znaxis[ii]; if (fpixel[ii] < 1) { free(buffer); return(*status = BAD_PIX_NUM); } tilesize[ii] = (fptr->Fptr)->tilesize[ii]; tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1; ftile[ii] = (fpixel[ii] - 1) / tilesize[ii] + 1; ltile[ii] = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, tiledim[ii]); rowdim[ii] = ntemp; /* total tiles in each dimension */ ntemp *= tiledim[ii]; } if (anynul) *anynul = 0; /* initialize */ firstelem = 1; /* support up to 6 dimensions for now */ /* tfpixel and tlpixel are the first and last image pixels */ /* along each dimension of the compression tile */ for (i5 = ftile[5]; i5 <= ltile[5]; i5++) { tfpixel[5] = (i5 - 1) * tilesize[5] + 1; tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, naxis[5]); thistilesize[5] = tlpixel[5] - tfpixel[5] + 1; offset[5] = (i5 - 1) * rowdim[5]; for (i4 = ftile[4]; i4 <= ltile[4]; i4++) { tfpixel[4] = (i4 - 1) * tilesize[4] + 1; tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, naxis[4]); thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1); offset[4] = (i4 - 1) * rowdim[4] + offset[5]; for (i3 = ftile[3]; i3 <= ltile[3]; i3++) { tfpixel[3] = (i3 - 1) * tilesize[3] + 1; tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, naxis[3]); thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1); offset[3] = (i3 - 1) * rowdim[3] + offset[4]; for (i2 = ftile[2]; i2 <= ltile[2]; i2++) { tfpixel[2] = (i2 - 1) * tilesize[2] + 1; tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, naxis[2]); thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1); offset[2] = (i2 - 1) * rowdim[2] + offset[3]; for (i1 = ftile[1]; i1 <= ltile[1]; i1++) { tfpixel[1] = (i1 - 1) * tilesize[1] + 1; tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, naxis[1]); thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1); offset[1] = (i1 - 1) * rowdim[1] + offset[2]; for (i0 = ftile[0]; i0 <= ltile[0]; i0++) { tfpixel[0] = (i0 - 1) * tilesize[0] + 1; tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, naxis[0]); thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1); /* calculate row of table containing this tile */ irow = i0 + offset[1]; /* read and uncompress this row (tile) of the table */ /* also do type conversion and undefined pixel substitution */ /* at this point */ imcomp_decompress_tile(fptr, irow, thistilesize[0], datatype, nullcheck, nullval, buffer, bnullarray, &tilenul, status); /* write the image to the output file */ if (tilenul && anynul) { /* this assumes that the tiled pixels are in the same order as in the uncompressed FITS image. This is not necessarily the case, but it almost alway is in practice. Note that null checking is not performed for integer images, so this could only be a problem for tile compressed floating point images that use an unconventional tiling pattern. */ fits_write_imgnull(outfptr, datatype, firstelem, thistilesize[0], buffer, nullval, status); } else { fits_write_subset(outfptr, datatype, tfpixel, tlpixel, buffer, status); } firstelem += thistilesize[0]; } } } } } } free(buffer); return(*status); } /*--------------------------------------------------------------------------*/ int fits_read_compressed_pixels(fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the array to be returned */ LONGLONG fpixel, /* I - 'first pixel to read */ LONGLONG npixel, /* I - number of pixels to read */ int nullcheck, /* I - 0 for no null checking */ /* 1: set undefined pixels = nullval */ /* 2: set nullarray=1 for undefined pixels */ void *nullval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ char *nullarray, /* O - array of flags = 1 if nullcheck = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a consecutive set of pixels from a compressed image. This routine interpretes the n-dimensional image as a long one-dimensional array. This is actually a rather inconvenient way to read compressed images in general, and could be rather inefficient if the requested pixels to be read are located in many different image compression tiles. The general strategy used here is to read the requested pixels in blocks that correspond to rectangular image sections. */ { int naxis, ii, bytesperpixel, planenul; long naxes[MAX_COMPRESS_DIM], nread; long nplane, inc[MAX_COMPRESS_DIM]; LONGLONG tfirst, tlast, last0, last1, dimsize[MAX_COMPRESS_DIM]; LONGLONG firstcoord[MAX_COMPRESS_DIM], lastcoord[MAX_COMPRESS_DIM]; char *arrayptr, *nullarrayptr; if (*status > 0) return(*status); arrayptr = (char *) array; nullarrayptr = nullarray; /* get size of array pixels, in bytes */ bytesperpixel = ffpxsz(datatype); for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { naxes[ii] = 1; firstcoord[ii] = 0; lastcoord[ii] = 0; inc[ii] = 1; } /* determine the dimensions of the image to be read */ ffgidm(fptr, &naxis, status); ffgisz(fptr, MAX_COMPRESS_DIM, naxes, status); /* calc the cumulative number of pixels in each successive dimension */ dimsize[0] = 1; for (ii = 1; ii < MAX_COMPRESS_DIM; ii++) dimsize[ii] = dimsize[ii - 1] * naxes[ii - 1]; /* determine the coordinate of the first and last pixel in the image */ /* Use zero based indexes here */ tfirst = fpixel - 1; tlast = tfirst + npixel - 1; for (ii = naxis - 1; ii >= 0; ii--) { firstcoord[ii] = tfirst / dimsize[ii]; lastcoord[ii] = tlast / dimsize[ii]; tfirst = tfirst - firstcoord[ii] * dimsize[ii]; tlast = tlast - lastcoord[ii] * dimsize[ii]; } /* to simplify things, treat 1-D, 2-D, and 3-D images as separate cases */ if (naxis == 1) { /* Simple: just read the requested range of pixels */ firstcoord[0] = firstcoord[0] + 1; lastcoord[0] = lastcoord[0] + 1; fits_read_compressed_img(fptr, datatype, firstcoord, lastcoord, inc, nullcheck, nullval, array, nullarray, anynul, status); return(*status); } else if (naxis == 2) { nplane = 0; /* read 1st (and only) plane of the image */ fits_read_compressed_img_plane(fptr, datatype, bytesperpixel, nplane, firstcoord, lastcoord, inc, naxes, nullcheck, nullval, array, nullarray, anynul, &nread, status); } else if (naxis == 3) { /* test for special case: reading an integral number of planes */ if (firstcoord[0] == 0 && firstcoord[1] == 0 && lastcoord[0] == naxes[0] - 1 && lastcoord[1] == naxes[1] - 1) { for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { /* convert from zero base to 1 base */ (firstcoord[ii])++; (lastcoord[ii])++; } /* we can read the contiguous block of pixels in one go */ fits_read_compressed_img(fptr, datatype, firstcoord, lastcoord, inc, nullcheck, nullval, array, nullarray, anynul, status); return(*status); } if (anynul) *anynul = 0; /* initialize */ /* save last coordinate in temporary variables */ last0 = lastcoord[0]; last1 = lastcoord[1]; if (firstcoord[2] < lastcoord[2]) { /* we will read up to the last pixel in all but the last plane */ lastcoord[0] = naxes[0] - 1; lastcoord[1] = naxes[1] - 1; } /* read one plane of the cube at a time, for simplicity */ for (nplane = (long) firstcoord[2]; nplane <= lastcoord[2]; nplane++) { if (nplane == lastcoord[2]) { lastcoord[0] = last0; lastcoord[1] = last1; } fits_read_compressed_img_plane(fptr, datatype, bytesperpixel, nplane, firstcoord, lastcoord, inc, naxes, nullcheck, nullval, arrayptr, nullarrayptr, &planenul, &nread, status); if (planenul && anynul) *anynul = 1; /* there are null pixels */ /* for all subsequent planes, we start with the first pixel */ firstcoord[0] = 0; firstcoord[1] = 0; /* increment pointers to next elements to be read */ arrayptr = arrayptr + nread * bytesperpixel; if (nullarrayptr && (nullcheck == 2) ) nullarrayptr = nullarrayptr + nread; } } else { ffpmsg("only 1D, 2D, or 3D images are currently supported"); return(*status = DATA_DECOMPRESSION_ERR); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_read_compressed_img_plane(fitsfile *fptr, /* I - FITS file */ int datatype, /* I - datatype of the array to be returned */ int bytesperpixel, /* I - number of bytes per pixel in array */ long nplane, /* I - which plane of the cube to read */ LONGLONG *firstcoord, /* coordinate of first pixel to read */ LONGLONG *lastcoord, /* coordinate of last pixel to read */ long *inc, /* increment of pixels to read */ long *naxes, /* size of each image dimension */ int nullcheck, /* I - 0 for no null checking */ /* 1: set undefined pixels = nullval */ /* 2: set nullarray=1 for undefined pixels */ void *nullval, /* I - value for undefined pixels */ void *array, /* O - array of values that are returned */ char *nullarray, /* O - array of flags = 1 if nullcheck = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ long *nread, /* O - total number of pixels read and returned*/ int *status) /* IO - error status */ /* in general we have to read the first partial row of the image, followed by the middle complete rows, followed by the last partial row of the image. If the first or last rows are complete, then read them at the same time as all the middle rows. */ { /* bottom left coord. and top right coord. */ LONGLONG blc[MAX_COMPRESS_DIM], trc[MAX_COMPRESS_DIM]; char *arrayptr, *nullarrayptr; int tnull; if (anynul) *anynul = 0; *nread = 0; arrayptr = (char *) array; nullarrayptr = nullarray; blc[2] = nplane + 1; trc[2] = nplane + 1; if (firstcoord[0] != 0) { /* have to read a partial first row */ blc[0] = firstcoord[0] + 1; blc[1] = firstcoord[1] + 1; trc[1] = blc[1]; if (lastcoord[1] == firstcoord[1]) trc[0] = lastcoord[0] + 1; /* 1st and last pixels in same row */ else trc[0] = naxes[0]; /* read entire rest of the row */ fits_read_compressed_img(fptr, datatype, blc, trc, inc, nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status); *nread = *nread + (long) (trc[0] - blc[0] + 1); if (tnull && anynul) *anynul = 1; /* there are null pixels */ if (lastcoord[1] == firstcoord[1]) { return(*status); /* finished */ } /* set starting coord to beginning of next line */ firstcoord[0] = 0; firstcoord[1] += 1; arrayptr = arrayptr + (trc[0] - blc[0] + 1) * bytesperpixel; if (nullarrayptr && (nullcheck == 2) ) nullarrayptr = nullarrayptr + (trc[0] - blc[0] + 1); } /* read contiguous complete rows of the image, if any */ blc[0] = 1; blc[1] = firstcoord[1] + 1; trc[0] = naxes[0]; if (lastcoord[0] + 1 == naxes[0]) { /* can read the last complete row, too */ trc[1] = lastcoord[1] + 1; } else { /* last row is incomplete; have to read it separately */ trc[1] = lastcoord[1]; } if (trc[1] >= blc[1]) /* must have at least one whole line to read */ { fits_read_compressed_img(fptr, datatype, blc, trc, inc, nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status); *nread = *nread + (long) ((trc[1] - blc[1] + 1) * naxes[0]); if (tnull && anynul) *anynul = 1; if (lastcoord[1] + 1 == trc[1]) return(*status); /* finished */ /* increment pointers for the last partial row */ arrayptr = arrayptr + (trc[1] - blc[1] + 1) * naxes[0] * bytesperpixel; if (nullarrayptr && (nullcheck == 2) ) nullarrayptr = nullarrayptr + (trc[1] - blc[1] + 1) * naxes[0]; } if (trc[1] == lastcoord[1] + 1) return(*status); /* all done */ /* set starting and ending coord to last line */ trc[0] = lastcoord[0] + 1; trc[1] = lastcoord[1] + 1; blc[1] = trc[1]; fits_read_compressed_img(fptr, datatype, blc, trc, inc, nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status); if (tnull && anynul) *anynul = 1; *nread = *nread + (long) (trc[0] - blc[0] + 1); return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_get_compressed_image_par(fitsfile *infptr, int *status) /* This routine reads keywords from a BINTABLE extension containing a compressed image. */ { char keyword[FLEN_KEYWORD]; char value[FLEN_VALUE]; int ii, tstatus, tstatus2, doffset, oldFormat=0, colNum=0; long expect_nrows, maxtilelen; if (*status > 0) return(*status); /* Copy relevant header keyword values to structure */ if (ffgky (infptr, TSTRING, "ZCMPTYPE", value, NULL, status) > 0) { ffpmsg("required ZCMPTYPE compression keyword not found in"); ffpmsg(" imcomp_get_compressed_image_par"); return(*status); } (infptr->Fptr)->zcmptype[0] = '\0'; strncat((infptr->Fptr)->zcmptype, value, 11); if (!FSTRCMP(value, "RICE_1") || !FSTRCMP(value, "RICE_ONE") ) (infptr->Fptr)->compress_type = RICE_1; else if (!FSTRCMP(value, "HCOMPRESS_1") ) (infptr->Fptr)->compress_type = HCOMPRESS_1; else if (!FSTRCMP(value, "GZIP_1") ) (infptr->Fptr)->compress_type = GZIP_1; else if (!FSTRCMP(value, "GZIP_2") ) (infptr->Fptr)->compress_type = GZIP_2; else if (!FSTRCMP(value, "BZIP2_1") ) (infptr->Fptr)->compress_type = BZIP2_1; else if (!FSTRCMP(value, "PLIO_1") ) (infptr->Fptr)->compress_type = PLIO_1; else if (!FSTRCMP(value, "NOCOMPRESS") ) (infptr->Fptr)->compress_type = NOCOMPRESS; else { ffpmsg("Unknown image compression type:"); ffpmsg(value); return (*status = DATA_DECOMPRESSION_ERR); } if (ffgky (infptr, TINT, "ZBITPIX", &(infptr->Fptr)->zbitpix, NULL, status) > 0) { ffpmsg("required ZBITPIX compression keyword not found"); return(*status); } /* If ZZERO and ZSCALE columns don't exist for floating-point types, assume there is NO quantization. Treat exactly as if it had ZQUANTIZ='NONE'. This is true regardless of whether or not file has a ZQUANTIZ keyword. */ tstatus=0; tstatus2=0; if ((infptr->Fptr->zbitpix < 0) && (fits_get_colnum(infptr,CASEINSEN,"ZZERO",&colNum,&tstatus) == COL_NOT_FOUND) && (fits_get_colnum(infptr,CASEINSEN,"ZSCALE",&colNum,&tstatus2) == COL_NOT_FOUND)) { (infptr->Fptr)->quantize_level = NO_QUANTIZE; } else { /* get the floating point to integer quantization type, if present. */ /* FITS files produced before 2009 will not have this keyword */ tstatus = 0; if (ffgky(infptr, TSTRING, "ZQUANTIZ", value, NULL, &tstatus) > 0) { (infptr->Fptr)->quantize_method = 0; (infptr->Fptr)->quantize_level = 0; } else { if (!FSTRCMP(value, "NONE") ) { (infptr->Fptr)->quantize_level = NO_QUANTIZE; } else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_1") ) (infptr->Fptr)->quantize_method = SUBTRACTIVE_DITHER_1; else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_2") ) (infptr->Fptr)->quantize_method = SUBTRACTIVE_DITHER_2; else if (!FSTRCMP(value, "NO_DITHER") ) (infptr->Fptr)->quantize_method = NO_DITHER; else (infptr->Fptr)->quantize_method = 0; } } /* get the floating point quantization dithering offset, if present. */ /* FITS files produced before October 2009 will not have this keyword */ tstatus = 0; if (ffgky(infptr, TINT, "ZDITHER0", &doffset, NULL, &tstatus) > 0) { /* by default start with 1st element of random sequence */ (infptr->Fptr)->dither_seed = 1; } else { (infptr->Fptr)->dither_seed = doffset; } if (ffgky (infptr,TINT, "ZNAXIS", &(infptr->Fptr)->zndim, NULL, status) > 0) { ffpmsg("required ZNAXIS compression keyword not found"); return(*status); } if ((infptr->Fptr)->zndim < 1) { ffpmsg("Compressed image has no data (ZNAXIS < 1)"); return (*status = BAD_NAXIS); } if ((infptr->Fptr)->zndim > MAX_COMPRESS_DIM) { ffpmsg("Compressed image has too many dimensions"); return(*status = BAD_NAXIS); } expect_nrows = 1; maxtilelen = 1; for (ii = 0; ii < (infptr->Fptr)->zndim; ii++) { /* get image size */ snprintf (keyword, FLEN_KEYWORD,"ZNAXIS%d", ii+1); ffgky (infptr, TLONG,keyword, &(infptr->Fptr)->znaxis[ii],NULL,status); if (*status > 0) { ffpmsg("required ZNAXISn compression keyword not found"); return(*status); } /* get compression tile size */ snprintf (keyword, FLEN_KEYWORD,"ZTILE%d", ii+1); /* set default tile size in case keywords are not present */ if (ii == 0) (infptr->Fptr)->tilesize[0] = (infptr->Fptr)->znaxis[0]; else (infptr->Fptr)->tilesize[ii] = 1; tstatus = 0; ffgky (infptr, TLONG, keyword, &(infptr->Fptr)->tilesize[ii], NULL, &tstatus); expect_nrows *= (((infptr->Fptr)->znaxis[ii] - 1) / (infptr->Fptr)->tilesize[ii]+ 1); maxtilelen *= (infptr->Fptr)->tilesize[ii]; } /* check number of rows */ if (expect_nrows != (infptr->Fptr)->numrows) { ffpmsg( "number of table rows != the number of tiles in compressed image"); return (*status = DATA_DECOMPRESSION_ERR); } /* read any algorithm specific parameters */ if ((infptr->Fptr)->compress_type == RICE_1 ) { if (ffgky(infptr, TINT,"ZVAL1", &(infptr->Fptr)->rice_blocksize, NULL, status) > 0) { ffpmsg("required ZVAL1 compression keyword not found"); return(*status); } tstatus = 0; /* First check for very old files, where ZVAL2 wasn't yet designated for bytepix */ if (!ffgky(infptr, TSTRING, "ZNAME2", value, NULL, &tstatus) && !FSTRCMP(value, "NOISEBIT")) { oldFormat = 1; } tstatus = 0; if (oldFormat || ffgky(infptr, TINT,"ZVAL2", &(infptr->Fptr)->rice_bytepix, NULL, &tstatus) > 0) { (infptr->Fptr)->rice_bytepix = 4; /* default value */ } if ((infptr->Fptr)->rice_blocksize < 16 && (infptr->Fptr)->rice_bytepix > 8) { /* values are reversed */ tstatus = (infptr->Fptr)->rice_bytepix; (infptr->Fptr)->rice_bytepix = (infptr->Fptr)->rice_blocksize; (infptr->Fptr)->rice_blocksize = tstatus; } } else if ((infptr->Fptr)->compress_type == HCOMPRESS_1 ) { if (ffgky(infptr, TFLOAT,"ZVAL1", &(infptr->Fptr)->hcomp_scale, NULL, status) > 0) { ffpmsg("required ZVAL1 compression keyword not found"); return(*status); } tstatus = 0; ffgky(infptr, TINT,"ZVAL2", &(infptr->Fptr)->hcomp_smooth, NULL, &tstatus); } /* store number of pixels in each compression tile, */ /* and max size of the compressed tile buffer */ (infptr->Fptr)->maxtilelen = maxtilelen; (infptr->Fptr)->maxelem = imcomp_calc_max_elem ((infptr->Fptr)->compress_type, maxtilelen, (infptr->Fptr)->zbitpix, (infptr->Fptr)->rice_blocksize); /* Get Column numbers. */ if (ffgcno(infptr, CASEINSEN, "COMPRESSED_DATA", &(infptr->Fptr)->cn_compressed, status) > 0) { ffpmsg("couldn't find COMPRESSED_DATA column (fits_get_compressed_img_par)"); return(*status = DATA_DECOMPRESSION_ERR); } ffpmrk(); /* put mark on message stack; erase any messages after this */ tstatus = 0; ffgcno(infptr,CASEINSEN, "UNCOMPRESSED_DATA", &(infptr->Fptr)->cn_uncompressed, &tstatus); tstatus = 0; ffgcno(infptr,CASEINSEN, "GZIP_COMPRESSED_DATA", &(infptr->Fptr)->cn_gzip_data, &tstatus); tstatus = 0; if (ffgcno(infptr, CASEINSEN, "ZSCALE", &(infptr->Fptr)->cn_zscale, &tstatus) > 0) { /* CMPSCALE column doesn't exist; see if there is a keyword */ tstatus = 0; if (ffgky(infptr, TDOUBLE, "ZSCALE", &(infptr->Fptr)->zscale, NULL, &tstatus) <= 0) (infptr->Fptr)->cn_zscale = -1; /* flag for a constant ZSCALE */ } tstatus = 0; if (ffgcno(infptr, CASEINSEN, "ZZERO", &(infptr->Fptr)->cn_zzero, &tstatus) > 0) { /* CMPZERO column doesn't exist; see if there is a keyword */ tstatus = 0; if (ffgky(infptr, TDOUBLE, "ZZERO", &(infptr->Fptr)->zzero, NULL, &tstatus) <= 0) (infptr->Fptr)->cn_zzero = -1; /* flag for a constant ZZERO */ } tstatus = 0; if (ffgcno(infptr, CASEINSEN, "ZBLANK", &(infptr->Fptr)->cn_zblank, &tstatus) > 0) { /* ZBLANK column doesn't exist; see if there is a keyword */ tstatus = 0; if (ffgky(infptr, TINT, "ZBLANK", &(infptr->Fptr)->zblank, NULL, &tstatus) <= 0) { (infptr->Fptr)->cn_zblank = -1; /* flag for a constant ZBLANK */ } else { /* ZBLANK keyword doesn't exist; see if there is a BLANK keyword */ tstatus = 0; if (ffgky(infptr, TINT, "BLANK", &(infptr->Fptr)->zblank, NULL, &tstatus) <= 0) (infptr->Fptr)->cn_zblank = -1; /* flag for a constant ZBLANK */ } } /* read the conventional BSCALE and BZERO scaling keywords, if present */ tstatus = 0; if (ffgky (infptr, TDOUBLE, "BSCALE", &(infptr->Fptr)->cn_bscale, NULL, &tstatus) > 0) { (infptr->Fptr)->cn_bscale = 1.0; } tstatus = 0; if (ffgky (infptr, TDOUBLE, "BZERO", &(infptr->Fptr)->cn_bzero, NULL, &tstatus) > 0) { (infptr->Fptr)->cn_bzero = 0.0; (infptr->Fptr)->cn_actual_bzero = 0.0; } else { (infptr->Fptr)->cn_actual_bzero = (infptr->Fptr)->cn_bzero; } /* special case: the quantization level is not given by a keyword in */ /* the HDU header, so we have to explicitly copy the requested value */ /* to the actual value */ if ( (infptr->Fptr)->request_quantize_level != 0.) (infptr->Fptr)->quantize_level = (infptr->Fptr)->request_quantize_level; ffcmrk(); /* clear any spurious error messages, back to the mark */ return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_copy_imheader(fitsfile *infptr, fitsfile *outfptr, int *status) /* This routine reads the header keywords from the input image and copies them to the output image; the manditory structural keywords and the checksum keywords are not copied. If the DATE keyword is copied, then it is updated with the current date and time. */ { int nkeys, ii, keyclass; char card[FLEN_CARD]; /* a header record */ if (*status > 0) return(*status); ffghsp(infptr, &nkeys, NULL, status); /* get number of keywords in image */ for (ii = 5; ii <= nkeys; ii++) /* skip the first 4 keywords */ { ffgrec(infptr, ii, card, status); keyclass = ffgkcl(card); /* Get the type/class of keyword */ /* don't copy structural keywords or checksum keywords */ if ((keyclass <= TYP_CMPRS_KEY) || (keyclass == TYP_CKSUM_KEY)) continue; if (FSTRNCMP(card, "DATE ", 5) == 0) /* write current date */ { ffpdat(outfptr, status); } else if (FSTRNCMP(card, "EXTNAME ", 8) == 0) { /* don't copy default EXTNAME keyword from a compressed image */ if (FSTRNCMP(card, "EXTNAME = 'COMPRESSED_IMAGE'", 28)) { /* if EXTNAME keyword already exists, overwrite it */ /* otherwise append a new EXTNAME keyword */ ffucrd(outfptr, "EXTNAME", card, status); } } else { /* just copy the keyword to the output header */ ffprec (outfptr, card, status); } if (*status > 0) return (*status); } return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_copy_img2comp(fitsfile *infptr, fitsfile *outfptr, int *status) /* This routine copies the header keywords from the uncompressed input image and to the compressed image (in a binary table) */ { char card[FLEN_CARD], card2[FLEN_CARD]; /* a header record */ int nkeys, nmore, ii, jj, tstatus, bitpix; /* tile compressed image keyword translation table */ /* INPUT OUTPUT */ /* 01234567 01234567 */ char *patterns[][2] = {{"SIMPLE", "ZSIMPLE" }, {"XTENSION", "ZTENSION" }, {"BITPIX", "ZBITPIX" }, {"NAXIS", "ZNAXIS" }, {"NAXISm", "ZNAXISm" }, {"EXTEND", "ZEXTEND" }, {"BLOCKED", "ZBLOCKED"}, {"PCOUNT", "ZPCOUNT" }, {"GCOUNT", "ZGCOUNT" }, {"CHECKSUM","ZHECKSUM"}, /* save original checksums */ {"DATASUM", "ZDATASUM"}, {"*", "+" }}; /* copy all other keywords */ int npat; if (*status > 0) return(*status); /* write a default EXTNAME keyword if it doesn't exist in input file*/ fits_read_card(infptr, "EXTNAME", card, status); if (*status) { *status = 0; strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE'"); fits_write_record(outfptr, card, status); } /* copy all the keywords from the input file to the output */ npat = sizeof(patterns)/sizeof(patterns[0][0])/2; fits_translate_keywords(infptr, outfptr, 1, patterns, npat, 0, 0, 0, status); if ( (outfptr->Fptr)->request_lossy_int_compress != 0) { /* request was made to compress integer images as if they had float pixels. */ /* If input image has positive bitpix value, then reset the output ZBITPIX */ /* value to -32. */ fits_read_key(infptr, TINT, "BITPIX", &bitpix, NULL, status); if (*status <= 0 && bitpix > 0) { fits_modify_key_lng(outfptr, "ZBITPIX", -32, NULL, status); /* also delete the BSCALE, BZERO, and BLANK keywords */ tstatus = 0; fits_delete_key(outfptr, "BSCALE", &tstatus); tstatus = 0; fits_delete_key(outfptr, "BZERO", &tstatus); tstatus = 0; fits_delete_key(outfptr, "BLANK", &tstatus); } } /* For compatibility with software that uses an older version of CFITSIO, we must make certain that the new ZQUANTIZ keyword, if it exists, must occur after the other peudo-required keywords (e.g., ZSIMPLE, ZBITPIX, etc.). Do this by trying to delete the keyword. If that succeeds (and thus the keyword did exist) then rewrite the keyword at the end of header. In principle this should not be necessary once all software has upgraded to a newer version of CFITSIO (version number greater than 3.181, newer than August 2009). Do the same for the new ZDITHER0 keyword. */ tstatus = 0; if (fits_read_card(outfptr, "ZQUANTIZ", card, &tstatus) == 0) { fits_delete_key(outfptr, "ZQUANTIZ", status); /* rewrite the deleted keyword at the end of the header */ fits_write_record(outfptr, card, status); /* write some associated HISTORY keywords */ fits_parse_value(card, card2, NULL, status); if (fits_strncasecmp(card2, "'NONE", 5) ) { /* the value is not 'NONE' */ fits_write_history(outfptr, "Image was compressed by CFITSIO using scaled integer quantization:", status); snprintf(card2, FLEN_CARD," q = %f / quantized level scaling parameter", (outfptr->Fptr)->request_quantize_level); fits_write_history(outfptr, card2, status); fits_write_history(outfptr, card+10, status); } } tstatus = 0; if (fits_read_card(outfptr, "ZDITHER0", card, &tstatus) == 0) { fits_delete_key(outfptr, "ZDITHER0", status); /* rewrite the deleted keyword at the end of the header */ fits_write_record(outfptr, card, status); } ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords in image */ nmore = nmore / 36; /* how many completely empty header blocks are there? */ /* preserve the same number of spare header blocks in the output header */ for (jj = 0; jj < nmore; jj++) for (ii = 0; ii < 36; ii++) fits_write_record(outfptr, " ", status); return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_copy_comp2img(fitsfile *infptr, fitsfile *outfptr, int norec, int *status) /* This routine copies the header keywords from the compressed input image and to the uncompressed image (in a binary table) */ { char card[FLEN_CARD]; /* a header record */ char *patterns[40][2]; char negative[] = "-"; int ii,jj, npat, nreq, nsp, tstatus = 0; int nkeys, nmore; /* tile compressed image keyword translation table */ /* INPUT OUTPUT */ /* 01234567 01234567 */ /* only translate these if required keywords not already written */ char *reqkeys[][2] = { {"ZSIMPLE", "SIMPLE" }, {"ZTENSION", "XTENSION"}, {"ZBITPIX", "BITPIX" }, {"ZNAXIS", "NAXIS" }, {"ZNAXISm", "NAXISm" }, {"ZEXTEND", "EXTEND" }, {"ZBLOCKED", "BLOCKED"}, {"ZPCOUNT", "PCOUNT" }, {"ZGCOUNT", "GCOUNT" }, {"ZHECKSUM", "CHECKSUM"}, /* restore original checksums */ {"ZDATASUM", "DATASUM"}}; /* other special keywords */ char *spkeys[][2] = { {"XTENSION", "-" }, {"BITPIX", "-" }, {"NAXIS", "-" }, {"NAXISm", "-" }, {"PCOUNT", "-" }, {"GCOUNT", "-" }, {"TFIELDS", "-" }, {"TTYPEm", "-" }, {"TFORMm", "-" }, {"THEAP", "-" }, {"ZIMAGE", "-" }, {"ZQUANTIZ", "-" }, {"ZDITHER0", "-" }, {"ZTILEm", "-" }, {"ZCMPTYPE", "-" }, {"ZBLANK", "-" }, {"ZNAMEm", "-" }, {"ZVALm", "-" }, {"CHECKSUM","-" }, /* delete checksums */ {"DATASUM", "-" }, {"EXTNAME", "+" }, /* we may change this, below */ {"*", "+" }}; if (*status > 0) return(*status); nreq = sizeof(reqkeys)/sizeof(reqkeys[0][0])/2; nsp = sizeof(spkeys)/sizeof(spkeys[0][0])/2; /* construct translation patterns */ for (ii = 0; ii < nreq; ii++) { patterns[ii][0] = reqkeys[ii][0]; if (norec) patterns[ii][1] = negative; else patterns[ii][1] = reqkeys[ii][1]; } for (ii = 0; ii < nsp; ii++) { patterns[ii+nreq][0] = spkeys[ii][0]; patterns[ii+nreq][1] = spkeys[ii][1]; } npat = nreq + nsp; /* see if the EXTNAME keyword should be copied or not */ fits_read_card(infptr, "EXTNAME", card, &tstatus); if (tstatus == 0) { if (!strncmp(card, "EXTNAME = 'COMPRESSED_IMAGE'", 28)) patterns[npat-2][1] = negative; } /* translate and copy the keywords from the input file to the output */ fits_translate_keywords(infptr, outfptr, 1, patterns, npat, 0, 0, 0, status); ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords in image */ nmore = nmore / 36; /* how many completely empty header blocks are there? */ /* preserve the same number of spare header blocks in the output header */ for (jj = 0; jj < nmore; jj++) for (ii = 0; ii < 36; ii++) fits_write_record(outfptr, " ", status); return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_copy_prime2img(fitsfile *infptr, fitsfile *outfptr, int *status) /* This routine copies any unexpected keywords from the primary array of the compressed input image into the header of the uncompressed image (which is the primary array of the output file). */ { int nsp; /* keywords that will not be copied */ char *spkeys[][2] = { {"SIMPLE", "-" }, {"BITPIX", "-" }, {"NAXIS", "-" }, {"NAXISm", "-" }, {"PCOUNT", "-" }, {"EXTEND", "-" }, {"GCOUNT", "-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"EXTNAME", "-" }, {"HISTORY", "-" }, {"COMMENT", "-" }, {"*", "+" }}; if (*status > 0) return(*status); nsp = sizeof(spkeys)/sizeof(spkeys[0][0])/2; /* translate and copy the keywords from the input file to the output */ fits_translate_keywords(infptr, outfptr, 1, spkeys, nsp, 0, 0, 0, status); return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_decompress_tile (fitsfile *infptr, int nrow, /* I - row of table to read and uncompress */ int tilelen, /* I - number of pixels in the tile */ int datatype, /* I - datatype to be returned in 'buffer' */ int nullcheck, /* I - 0 for no null checking */ void *nulval, /* I - value to be used for undefined pixels */ void *buffer, /* O - buffer for returned decompressed values */ char *bnullarray, /* O - buffer for returned null flags */ int *anynul, /* O - any null values returned? */ int *status) /* This routine decompresses one tile of the image */ { int *idata = 0; int tiledatatype, pixlen = 0; /* uncompressed integer data */ size_t idatalen, tilebytesize; int ii, tnull; /* value in the data which represents nulls */ unsigned char *cbuf; /* compressed data */ unsigned char charnull = 0; short snull = 0; int blocksize, ntilebins, tilecol = 0; float fnulval=0; float *tempfloat = 0; double *tempdouble = 0; double dnulval=0; double bscale, bzero, actual_bzero, dummy = 0; /* scaling parameters */ long tilesize; /* number of bytes */ int smooth, nx, ny, scale; /* hcompress parameters */ LONGLONG nelemll = 0, offset = 0; if (*status > 0) return(*status); /* **************************************************************** */ /* allocate pointers to array of cached uncompressed tiles, if not already done */ if ((infptr->Fptr)->tilerow == 0) { /* calculate number of column bins of compressed tile */ ntilebins = (((infptr->Fptr)->znaxis[0] - 1) / ((infptr->Fptr)->tilesize[0])) + 1; if ((infptr->Fptr)->znaxis[0] != (infptr->Fptr)->tilesize[0] || (infptr->Fptr)->tilesize[1] != 1 ) { /* don't cache the tile if only single row of the image */ (infptr->Fptr)->tilerow = (int *) calloc (ntilebins, sizeof(int)); (infptr->Fptr)->tiledata = (void**) calloc (ntilebins, sizeof(void*)); (infptr->Fptr)->tilenullarray = (void **) calloc (ntilebins, sizeof(char*)); (infptr->Fptr)->tiledatasize = (long *) calloc (ntilebins, sizeof(long)); (infptr->Fptr)->tiletype = (int *) calloc (ntilebins, sizeof(int)); (infptr->Fptr)->tileanynull = (int *) calloc (ntilebins, sizeof(int)); } } /* **************************************************************** */ /* check if this tile was cached; if so, just copy it out */ if ((infptr->Fptr)->tilerow) { /* calculate the column bin of the compressed tile */ tilecol = (nrow - 1) % ((long)(((infptr->Fptr)->znaxis[0] - 1) / ((infptr->Fptr)->tilesize[0])) + 1); if (nrow == (infptr->Fptr)->tilerow[tilecol] && datatype == (infptr->Fptr)->tiletype[tilecol] ) { memcpy(buffer, ((infptr->Fptr)->tiledata)[tilecol], (infptr->Fptr)->tiledatasize[tilecol]); if (nullcheck == 2) memcpy(bnullarray, (infptr->Fptr)->tilenullarray[tilecol], tilelen); *anynul = (infptr->Fptr)->tileanynull[tilecol]; return(*status); } } /* **************************************************************** */ /* get length of the compressed byte stream */ ffgdesll (infptr, (infptr->Fptr)->cn_compressed, nrow, &nelemll, &offset, status); /* EOF error here indicates that this tile has not yet been written */ if (*status == END_OF_FILE) return(*status = NO_COMPRESSED_TILE); /* **************************************************************** */ if (nelemll == 0) /* special case: tile was not compressed normally */ { if ((infptr->Fptr)->cn_uncompressed >= 1 ) { /* This option of writing the uncompressed floating point data */ /* to the tile compressed file was used until about May 2011. */ /* This was replaced by the more efficient option of gzipping the */ /* floating point data before writing it to the tile-compressed file */ /* no compressed data, so simply read the uncompressed data */ /* directly from the UNCOMPRESSED_DATA column */ ffgdesll (infptr, (infptr->Fptr)->cn_uncompressed, nrow, &nelemll, &offset, status); if (nelemll == 0 && offset == 0) /* this should never happen */ return (*status = NO_COMPRESSED_TILE); if (nullcheck <= 1) { /* set any null values in the array = nulval */ fits_read_col(infptr, datatype, (infptr->Fptr)->cn_uncompressed, nrow, 1, (long) nelemll, nulval, buffer, anynul, status); } else { /* set the bnullarray = 1 for any null values in the array */ fits_read_colnull(infptr, datatype, (infptr->Fptr)->cn_uncompressed, nrow, 1, (long) nelemll, buffer, bnullarray, anynul, status); } } else if ((infptr->Fptr)->cn_gzip_data >= 1) { /* This is the newer option, that was introduced in May 2011 */ /* floating point data was not quantized, so read the losslessly */ /* compressed data from the GZIP_COMPRESSED_DATA column */ ffgdesll (infptr, (infptr->Fptr)->cn_gzip_data, nrow, &nelemll, &offset, status); if (nelemll == 0 && offset == 0) /* this should never happen */ return (*status = NO_COMPRESSED_TILE); /* allocate memory for the compressed tile of data */ cbuf = (unsigned char *) malloc ((long) nelemll); if (cbuf == NULL) { ffpmsg("error allocating memory for gzipped tile (imcomp_decompress_tile)"); return (*status = MEMORY_ALLOCATION); } /* read array of compressed bytes */ if (fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_gzip_data, nrow, 1, (long) nelemll, &charnull, cbuf, NULL, status) > 0) { ffpmsg("error reading compressed byte stream from binary table"); free (cbuf); return (*status); } /* size of the returned (uncompressed) data buffer, in bytes */ if ((infptr->Fptr)->zbitpix == FLOAT_IMG) { idatalen = tilelen * sizeof(float); } else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG) { idatalen = tilelen * sizeof(double); } else { /* this should never happen! */ ffpmsg("incompatible data type in gzipped floating-point tile-compressed image"); free (cbuf); return (*status = DATA_DECOMPRESSION_ERR); } /* Do not allow image float/doubles into int arrays */ if (datatype != TFLOAT && datatype != TDOUBLE) { ffpmsg("attempting to read compressed float or double image into incompatible data type"); free(cbuf); return (*status = DATA_DECOMPRESSION_ERR); } if (datatype == TFLOAT && (infptr->Fptr)->zbitpix == DOUBLE_IMG) { tempdouble = (double*)malloc(idatalen); if (tempdouble == NULL) { ffpmsg("Memory allocation failure for tempdouble. (imcomp_decompress_tile)"); free (cbuf); return (*status = MEMORY_ALLOCATION); } /* uncompress the data into temp buffer */ if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll, (char **) &tempdouble, &idatalen, NULL, &tilebytesize, status)) { ffpmsg("failed to gunzip the image tile"); free (tempdouble); free (cbuf); return (*status); } } else if (datatype == TDOUBLE && (infptr->Fptr)->zbitpix == FLOAT_IMG) { /* have to allocat a temporary buffer for the uncompressed data in the */ /* case where a gzipped "float" tile is returned as a "double" array */ tempfloat = (float*) malloc (idatalen); if (tempfloat == NULL) { ffpmsg("Memory allocation failure for tempfloat. (imcomp_decompress_tile)"); free (cbuf); return (*status = MEMORY_ALLOCATION); } /* uncompress the data into temp buffer */ if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll, (char **) &tempfloat, &idatalen, NULL, &tilebytesize, status)) { ffpmsg("failed to gunzip the image tile"); free (tempfloat); free (cbuf); return (*status); } } else { /* uncompress the data directly into the output buffer in all other cases */ if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll, (char **) &buffer, &idatalen, NULL, &tilebytesize, status)) { ffpmsg("failed to gunzip the image tile"); free (cbuf); return (*status); } } free(cbuf); /* do byte swapping and null value substitution for the tile of pixels */ if (tilebytesize == 4 * tilelen) { /* float pixels */ #if BYTESWAPPED if (tempfloat) ffswap4((int *) tempfloat, tilelen); else ffswap4((int *) buffer, tilelen); #endif if (datatype == TFLOAT) { if (nulval) { fnulval = *(float *) nulval; } fffr4r4((float *) buffer, (long) tilelen, 1., 0., nullcheck, fnulval, bnullarray, anynul, (float *) buffer, status); } else if (datatype == TDOUBLE) { if (nulval) { dnulval = *(double *) nulval; } /* note that the R*4 data are in the tempfloat array in this case */ fffr4r8((float *) tempfloat, (long) tilelen, 1., 0., nullcheck, dnulval, bnullarray, anynul, (double *) buffer, status); free(tempfloat); } else { ffpmsg("implicit data type conversion is not supported for gzipped image tiles"); return (*status = DATA_DECOMPRESSION_ERR); } } else if (tilebytesize == 8 * tilelen) { /* double pixels */ #if BYTESWAPPED if (tempdouble) ffswap8((double *) tempdouble, tilelen); else ffswap8((double *) buffer, tilelen); #endif if (datatype == TFLOAT) { if (nulval) { fnulval = *(float *) nulval; } fffr8r4((double *) tempdouble, (long) tilelen, 1., 0., nullcheck, fnulval, bnullarray, anynul, (float *) buffer, status); free(tempdouble); tempdouble=0; } else if (datatype == TDOUBLE) { if (nulval) { dnulval = *(double *) nulval; } fffr8r8((double *) buffer, (long) tilelen, 1., 0., nullcheck, dnulval, bnullarray, anynul, (double *) buffer, status); } else { ffpmsg("implicit data type conversion is not supported in tile-compressed images"); return (*status = DATA_DECOMPRESSION_ERR); } } else { ffpmsg("error: uncompressed tile has wrong size"); return (*status = DATA_DECOMPRESSION_ERR); } /* end of special case of losslessly gzipping a floating-point image tile */ } else { /* this should never happen */ *status = NO_COMPRESSED_TILE; } return(*status); } /* **************************************************************** */ /* deal with the normal case of a compressed tile of pixels */ if (nullcheck == 2) { for (ii = 0; ii < tilelen; ii++) /* initialize the null flage array */ bnullarray[ii] = 0; } if (anynul) *anynul = 0; /* get linear scaling and offset values, if they exist */ actual_bzero = (infptr->Fptr)->cn_actual_bzero; if ((infptr->Fptr)->cn_zscale == 0) { /* set default scaling, if scaling is not defined */ bscale = 1.; bzero = 0.; } else if ((infptr->Fptr)->cn_zscale == -1) { bscale = (infptr->Fptr)->zscale; bzero = (infptr->Fptr)->zzero; } else { /* read the linear scale and offset values for this row */ ffgcvd (infptr, (infptr->Fptr)->cn_zscale, nrow, 1, 1, 0., &bscale, NULL, status); ffgcvd (infptr, (infptr->Fptr)->cn_zzero, nrow, 1, 1, 0., &bzero, NULL, status); if (*status > 0) { ffpmsg("error reading scaling factor and offset for compressed tile"); return (*status); } /* test if floating-point FITS image also has non-default BSCALE and */ /* BZERO keywords. If so, we have to combine the 2 linear scaling factors. */ if ( ((infptr->Fptr)->zbitpix == FLOAT_IMG || (infptr->Fptr)->zbitpix == DOUBLE_IMG ) && ((infptr->Fptr)->cn_bscale != 1.0 || (infptr->Fptr)->cn_bzero != 0.0 ) ) { bscale = bscale * (infptr->Fptr)->cn_bscale; bzero = bzero * (infptr->Fptr)->cn_bscale + (infptr->Fptr)->cn_bzero; } } if (bscale == 1.0 && bzero == 0.0 ) { /* if no other scaling has been specified, try using the values given by the BSCALE and BZERO keywords, if any */ bscale = (infptr->Fptr)->cn_bscale; bzero = (infptr->Fptr)->cn_bzero; } /* ************************************************************* */ /* get the value used to represent nulls in the int array */ if ((infptr->Fptr)->cn_zblank == 0) { nullcheck = 0; /* no null value; don't check for nulls */ } else if ((infptr->Fptr)->cn_zblank == -1) { tnull = (infptr->Fptr)->zblank; /* use the the ZBLANK keyword */ } else { /* read the null value for this row */ ffgcvk (infptr, (infptr->Fptr)->cn_zblank, nrow, 1, 1, 0, &tnull, NULL, status); if (*status > 0) { ffpmsg("error reading null value for compressed tile"); return (*status); } } /* ************************************************************* */ /* allocate memory for the uncompressed array of tile integers */ /* The size depends on the datatype and the compression type. */ if ((infptr->Fptr)->compress_type == HCOMPRESS_1 && ((infptr->Fptr)->zbitpix != BYTE_IMG && (infptr->Fptr)->zbitpix != SHORT_IMG) ) { idatalen = tilelen * sizeof(LONGLONG); /* 8 bytes per pixel */ } else if ( (infptr->Fptr)->compress_type == RICE_1 && (infptr->Fptr)->zbitpix == BYTE_IMG && (infptr->Fptr)->rice_bytepix == 1) { idatalen = tilelen * sizeof(char); /* 1 byte per pixel */ } else if ( ( (infptr->Fptr)->compress_type == GZIP_1 || (infptr->Fptr)->compress_type == GZIP_2 || (infptr->Fptr)->compress_type == BZIP2_1 ) && (infptr->Fptr)->zbitpix == BYTE_IMG ) { idatalen = tilelen * sizeof(char); /* 1 byte per pixel */ } else if ( (infptr->Fptr)->compress_type == RICE_1 && (infptr->Fptr)->zbitpix == SHORT_IMG && (infptr->Fptr)->rice_bytepix == 2) { idatalen = tilelen * sizeof(short); /* 2 bytes per pixel */ } else if ( ( (infptr->Fptr)->compress_type == GZIP_1 || (infptr->Fptr)->compress_type == GZIP_2 || (infptr->Fptr)->compress_type == BZIP2_1 ) && (infptr->Fptr)->zbitpix == SHORT_IMG ) { idatalen = tilelen * sizeof(short); /* 2 bytes per pixel */ } else if ( ( (infptr->Fptr)->compress_type == GZIP_1 || (infptr->Fptr)->compress_type == GZIP_2 || (infptr->Fptr)->compress_type == BZIP2_1 ) && (infptr->Fptr)->zbitpix == DOUBLE_IMG ) { idatalen = tilelen * sizeof(double); /* 8 bytes per pixel */ } else { idatalen = tilelen * sizeof(int); /* all other cases have int pixels */ } idata = (int*) malloc (idatalen); if (idata == NULL) { ffpmsg("Memory allocation failure for idata. (imcomp_decompress_tile)"); return (*status = MEMORY_ALLOCATION); } /* ************************************************************* */ /* allocate memory for the compressed bytes */ if ((infptr->Fptr)->compress_type == PLIO_1) { cbuf = (unsigned char *) malloc ((long) nelemll * sizeof (short)); } else { cbuf = (unsigned char *) malloc ((long) nelemll); } if (cbuf == NULL) { ffpmsg("Out of memory for cbuf. (imcomp_decompress_tile)"); free(idata); return (*status = MEMORY_ALLOCATION); } /* ************************************************************* */ /* read the compressed bytes from the FITS file */ if ((infptr->Fptr)->compress_type == PLIO_1) { fits_read_col(infptr, TSHORT, (infptr->Fptr)->cn_compressed, nrow, 1, (long) nelemll, &snull, (short *) cbuf, NULL, status); } else { fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_compressed, nrow, 1, (long) nelemll, &charnull, cbuf, NULL, status); } if (*status > 0) { ffpmsg("error reading compressed byte stream from binary table"); free (cbuf); free(idata); return (*status); } /* ************************************************************* */ /* call the algorithm-specific code to uncompress the tile */ if ((infptr->Fptr)->compress_type == RICE_1) { blocksize = (infptr->Fptr)->rice_blocksize; if ((infptr->Fptr)->rice_bytepix == 1 ) { *status = fits_rdecomp_byte (cbuf, (long) nelemll, (unsigned char *)idata, tilelen, blocksize); tiledatatype = TBYTE; } else if ((infptr->Fptr)->rice_bytepix == 2 ) { *status = fits_rdecomp_short (cbuf, (long) nelemll, (unsigned short *)idata, tilelen, blocksize); tiledatatype = TSHORT; } else { *status = fits_rdecomp (cbuf, (long) nelemll, (unsigned int *)idata, tilelen, blocksize); tiledatatype = TINT; } /* ************************************************************* */ } else if ((infptr->Fptr)->compress_type == HCOMPRESS_1) { smooth = (infptr->Fptr)->hcomp_smooth; if ( ((infptr->Fptr)->zbitpix == BYTE_IMG || (infptr->Fptr)->zbitpix == SHORT_IMG)) { *status = fits_hdecompress(cbuf, smooth, idata, &nx, &ny, &scale, status); } else { /* zbitpix = LONG_IMG (32) */ /* idata must have been allocated twice as large for this to work */ *status = fits_hdecompress64(cbuf, smooth, (LONGLONG *) idata, &nx, &ny, &scale, status); } tiledatatype = TINT; /* ************************************************************* */ } else if ((infptr->Fptr)->compress_type == PLIO_1) { pl_l2pi ((short *) cbuf, 1, idata, tilelen); /* uncompress the data */ tiledatatype = TINT; /* ************************************************************* */ } else if ( ((infptr->Fptr)->compress_type == GZIP_1) || ((infptr->Fptr)->compress_type == GZIP_2) ) { uncompress2mem_from_mem ((char *)cbuf, (long) nelemll, (char **) &idata, &idatalen, realloc, &tilebytesize, status); /* determine the data type of the uncompressed array, and */ /* do byte unshuffling and unswapping if needed */ if (tilebytesize == (size_t) (tilelen * 2)) { /* this is a short I*2 array */ tiledatatype = TSHORT; if ( (infptr->Fptr)->compress_type == GZIP_2 ) fits_unshuffle_2bytes((char *) idata, tilelen, status); #if BYTESWAPPED ffswap2((short *) idata, tilelen); #endif } else if (tilebytesize == (size_t) (tilelen * 4)) { /* this is a int I*4 array (or maybe R*4) */ tiledatatype = TINT; if ( (infptr->Fptr)->compress_type == GZIP_2 ) fits_unshuffle_4bytes((char *) idata, tilelen, status); #if BYTESWAPPED ffswap4(idata, tilelen); #endif } else if (tilebytesize == (size_t) (tilelen * 8)) { /* this is a R*8 double array */ tiledatatype = TDOUBLE; if ( (infptr->Fptr)->compress_type == GZIP_2 ) fits_unshuffle_8bytes((char *) idata, tilelen, status); #if BYTESWAPPED ffswap8((double *) idata, tilelen); #endif } else if (tilebytesize == (size_t) tilelen) { /* this is an unsigned char I*1 array */ tiledatatype = TBYTE; } else { ffpmsg("error: uncompressed tile has wrong size"); free(idata); return (*status = DATA_DECOMPRESSION_ERR); } /* ************************************************************* */ } else if ((infptr->Fptr)->compress_type == BZIP2_1) { /* BZIP2 is not supported in the public release; this is only for test purposes if (BZ2_bzBuffToBuffDecompress ((char *) idata, &idatalen, (char *)cbuf, (unsigned int) nelemll, 0, 0) ) */ { ffpmsg("bzip2 decompression error"); free(idata); free (cbuf); return (*status = DATA_DECOMPRESSION_ERR); } if ((infptr->Fptr)->zbitpix == BYTE_IMG) { tiledatatype = TBYTE; } else if ((infptr->Fptr)->zbitpix == SHORT_IMG) { tiledatatype = TSHORT; #if BYTESWAPPED ffswap2((short *) idata, tilelen); #endif } else { tiledatatype = TINT; #if BYTESWAPPED ffswap4(idata, tilelen); #endif } /* ************************************************************* */ } else { ffpmsg("unknown compression algorithm"); free(idata); return (*status = DATA_DECOMPRESSION_ERR); } free(cbuf); if (*status) { /* error uncompressing the tile */ free(idata); return (*status); } /* ************************************************************* */ /* copy the uncompressed tile data to the output buffer, doing */ /* null checking, datatype conversion and linear scaling, if necessary */ if (nulval == 0) nulval = &dummy; /* set address to dummy value */ if (datatype == TSHORT) { pixlen = sizeof(short); if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4i2((float *) idata, tilelen, bscale, bzero, nullcheck, *(short *) nulval, bnullarray, anynul, (short *) buffer, status); } else { fffr8i2((double *) idata, tilelen, bscale, bzero, nullcheck, *(short *) nulval, bnullarray, anynul, (short *) buffer, status); } } else if (tiledatatype == TINT) { if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4i2(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, *(short *) nulval, bnullarray, anynul, (short *) buffer, status); } else { fffi4i2(idata, tilelen, bscale, bzero, nullcheck, tnull, *(short *) nulval, bnullarray, anynul, (short *) buffer, status); /* Hcompress is a special case: ignore any numerical overflow errors that may have occurred during the integer*4 to integer*2 convertion. Overflows can happen when a lossy Hcompress algorithm is invoked (with a non-zero scale factor). The fffi4i2 routine clips the returned values to be within the legal I*2 range, so all we need to is to reset the error status to zero. */ if ((infptr->Fptr)->compress_type == HCOMPRESS_1) { if ((*status == NUM_OVERFLOW) || (*status == OVERFLOW_ERR)) *status = 0; } } } else if (tiledatatype == TSHORT) { fffi2i2((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(short *) nulval, bnullarray, anynul, (short *) buffer, status); } else if (tiledatatype == TBYTE) { fffi1i2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(short *) nulval, bnullarray, anynul, (short *) buffer, status); } } else if (datatype == TINT) { pixlen = sizeof(int); if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4int((float *) idata, tilelen, bscale, bzero, nullcheck, *(int *) nulval, bnullarray, anynul, (int *) buffer, status); } else { fffr8int((double *) idata, tilelen, bscale, bzero, nullcheck, *(int *) nulval, bnullarray, anynul, (int *) buffer, status); } } else if (tiledatatype == TINT) if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4int(idata, (long) tilelen, bscale, bzero - 32768., nullcheck, tnull, *(int *) nulval, bnullarray, anynul, (int *) buffer, status); } else { fffi4int(idata, (long) tilelen, bscale, bzero, nullcheck, tnull, *(int *) nulval, bnullarray, anynul, (int *) buffer, status); } else if (tiledatatype == TSHORT) fffi2int((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(int *) nulval, bnullarray, anynul, (int *) buffer, status); else if (tiledatatype == TBYTE) fffi1int((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(int *) nulval, bnullarray, anynul, (int *) buffer, status); } else if (datatype == TLONG) { pixlen = sizeof(long); if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4i4((float *) idata, tilelen, bscale, bzero, nullcheck, *(long *) nulval, bnullarray, anynul, (long *) buffer, status); } else { fffr8i4((double *) idata, tilelen, bscale, bzero, nullcheck, *(long *) nulval, bnullarray, anynul, (long *) buffer, status); } } else if (tiledatatype == TINT) if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4i4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, *(long *) nulval, bnullarray, anynul, (long *) buffer, status); } else { fffi4i4(idata, tilelen, bscale, bzero, nullcheck, tnull, *(long *) nulval, bnullarray, anynul, (long *) buffer, status); } else if (tiledatatype == TSHORT) fffi2i4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(long *) nulval, bnullarray, anynul, (long *) buffer, status); else if (tiledatatype == TBYTE) fffi1i4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(long *) nulval, bnullarray, anynul, (long *) buffer, status); } else if (datatype == TFLOAT) { pixlen = sizeof(float); if (nulval) { fnulval = *(float *) nulval; } if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4r4((float *) idata, tilelen, bscale, bzero, nullcheck, fnulval, bnullarray, anynul, (float *) buffer, status); } else { fffr8r4((double *) idata, tilelen, bscale, bzero, nullcheck, fnulval, bnullarray, anynul, (float *) buffer, status); } } else if ((infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 || (infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) { /* use the new dithering algorithm (introduced in July 2009) */ if (tiledatatype == TINT) unquantize_i4r4(nrow + (infptr->Fptr)->dither_seed - 1, idata, tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, tnull, fnulval, bnullarray, anynul, (float *) buffer, status); else if (tiledatatype == TSHORT) unquantize_i2r4(nrow + (infptr->Fptr)->dither_seed - 1, (short *)idata, tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (short) tnull, fnulval, bnullarray, anynul, (float *) buffer, status); else if (tiledatatype == TBYTE) unquantize_i1r4(nrow + (infptr->Fptr)->dither_seed - 1, (unsigned char *)idata, tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (unsigned char) tnull, fnulval, bnullarray, anynul, (float *) buffer, status); } else { /* use the old "round to nearest level" quantization algorithm */ if (tiledatatype == TINT) if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4r4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, fnulval, bnullarray, anynul, (float *) buffer, status); } else { fffi4r4(idata, tilelen, bscale, bzero, nullcheck, tnull, fnulval, bnullarray, anynul, (float *) buffer, status); } else if (tiledatatype == TSHORT) fffi2r4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, fnulval, bnullarray, anynul, (float *) buffer, status); else if (tiledatatype == TBYTE) fffi1r4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, fnulval, bnullarray, anynul, (float *) buffer, status); } } else if (datatype == TDOUBLE) { pixlen = sizeof(double); if (nulval) { dnulval = *(double *) nulval; } if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4r8((float *) idata, tilelen, bscale, bzero, nullcheck, dnulval, bnullarray, anynul, (double *) buffer, status); } else { fffr8r8((double *) idata, tilelen, bscale, bzero, nullcheck, dnulval, bnullarray, anynul, (double *) buffer, status); } } else if ((infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 || (infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) { /* use the new dithering algorithm (introduced in July 2009) */ if (tiledatatype == TINT) unquantize_i4r8(nrow + (infptr->Fptr)->dither_seed - 1, idata, tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, tnull, dnulval, bnullarray, anynul, (double *) buffer, status); else if (tiledatatype == TSHORT) unquantize_i2r8(nrow + (infptr->Fptr)->dither_seed - 1, (short *)idata, tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (short) tnull, dnulval, bnullarray, anynul, (double *) buffer, status); else if (tiledatatype == TBYTE) unquantize_i1r8(nrow + (infptr->Fptr)->dither_seed - 1, (unsigned char *)idata, tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (unsigned char) tnull, dnulval, bnullarray, anynul, (double *) buffer, status); } else { /* use the old "round to nearest level" quantization algorithm */ if (tiledatatype == TINT) { if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4r8(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, dnulval, bnullarray, anynul, (double *) buffer, status); } else { fffi4r8(idata, tilelen, bscale, bzero, nullcheck, tnull, dnulval, bnullarray, anynul, (double *) buffer, status); } } else if (tiledatatype == TSHORT) { fffi2r8((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, dnulval, bnullarray, anynul, (double *) buffer, status); } else if (tiledatatype == TBYTE) fffi1r8((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, dnulval, bnullarray, anynul, (double *) buffer, status); } } else if (datatype == TBYTE) { pixlen = sizeof(char); if (tiledatatype == TINT) fffi4i1(idata, tilelen, bscale, bzero, nullcheck, tnull, *(unsigned char *) nulval, bnullarray, anynul, (unsigned char *) buffer, status); else if (tiledatatype == TSHORT) fffi2i1((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(unsigned char *) nulval, bnullarray, anynul, (unsigned char *) buffer, status); else if (tiledatatype == TBYTE) fffi1i1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(unsigned char *) nulval, bnullarray, anynul, (unsigned char *) buffer, status); } else if (datatype == TSBYTE) { pixlen = sizeof(char); if (tiledatatype == TINT) fffi4s1(idata, tilelen, bscale, bzero, nullcheck, tnull, *(signed char *) nulval, bnullarray, anynul, (signed char *) buffer, status); else if (tiledatatype == TSHORT) fffi2s1((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(signed char *) nulval, bnullarray, anynul, (signed char *) buffer, status); else if (tiledatatype == TBYTE) fffi1s1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(signed char *) nulval, bnullarray, anynul, (signed char *) buffer, status); } else if (datatype == TUSHORT) { pixlen = sizeof(short); if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4u2((float *) idata, tilelen, bscale, bzero, nullcheck, *(unsigned short *) nulval, bnullarray, anynul, (unsigned short *) buffer, status); } else { fffr8u2((double *) idata, tilelen, bscale, bzero, nullcheck, *(unsigned short *) nulval, bnullarray, anynul, (unsigned short *) buffer, status); } } else if (tiledatatype == TINT) if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4u2(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, *(unsigned short *) nulval, bnullarray, anynul, (unsigned short *) buffer, status); } else { fffi4u2(idata, tilelen, bscale, bzero, nullcheck, tnull, *(unsigned short *) nulval, bnullarray, anynul, (unsigned short *) buffer, status); } else if (tiledatatype == TSHORT) fffi2u2((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(unsigned short *) nulval, bnullarray, anynul, (unsigned short *) buffer, status); else if (tiledatatype == TBYTE) fffi1u2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(unsigned short *) nulval, bnullarray, anynul, (unsigned short *) buffer, status); } else if (datatype == TUINT) { pixlen = sizeof(int); if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4uint((float *) idata, tilelen, bscale, bzero, nullcheck, *(unsigned int *) nulval, bnullarray, anynul, (unsigned int *) buffer, status); } else { fffr8uint((double *) idata, tilelen, bscale, bzero, nullcheck, *(unsigned int *) nulval, bnullarray, anynul, (unsigned int *) buffer, status); } } else if (tiledatatype == TINT) if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4uint(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, *(unsigned int *) nulval, bnullarray, anynul, (unsigned int *) buffer, status); } else { fffi4uint(idata, tilelen, bscale, bzero, nullcheck, tnull, *(unsigned int *) nulval, bnullarray, anynul, (unsigned int *) buffer, status); } else if (tiledatatype == TSHORT) fffi2uint((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(unsigned int *) nulval, bnullarray, anynul, (unsigned int *) buffer, status); else if (tiledatatype == TBYTE) fffi1uint((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(unsigned int *) nulval, bnullarray, anynul, (unsigned int *) buffer, status); } else if (datatype == TULONG) { pixlen = sizeof(long); if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) { /* the floating point pixels were losselessly compressed with GZIP */ /* Just have to copy the values to the output array */ if (tiledatatype == TINT) { fffr4u4((float *) idata, tilelen, bscale, bzero, nullcheck, *(unsigned long *) nulval, bnullarray, anynul, (unsigned long *) buffer, status); } else { fffr8u4((double *) idata, tilelen, bscale, bzero, nullcheck, *(unsigned long *) nulval, bnullarray, anynul, (unsigned long *) buffer, status); } } else if (tiledatatype == TINT) if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) { /* special case where unsigned 16-bit integers have been */ /* offset by +32768 when using PLIO */ fffi4u4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull, *(unsigned long *) nulval, bnullarray, anynul, (unsigned long *) buffer, status); } else { fffi4u4(idata, tilelen, bscale, bzero, nullcheck, tnull, *(unsigned long *) nulval, bnullarray, anynul, (unsigned long *) buffer, status); } else if (tiledatatype == TSHORT) fffi2u4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull, *(unsigned long *) nulval, bnullarray, anynul, (unsigned long *) buffer, status); else if (tiledatatype == TBYTE) fffi1u4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull, *(unsigned long *) nulval, bnullarray, anynul, (unsigned long *) buffer, status); } else *status = BAD_DATATYPE; free(idata); /* don't need the uncompressed tile any more */ /* **************************************************************** */ /* cache the tile, in case the application wants it again */ /* Don't cache the tile if tile is a single row of the image; it is less likely that the cache will be used in this cases, so it is not worth the time and the memory overheads. */ if ((infptr->Fptr)->tilerow) { /* make sure cache has been allocated */ if ((infptr->Fptr)->znaxis[0] != (infptr->Fptr)->tilesize[0] || (infptr->Fptr)->tilesize[1] != 1 ) { tilesize = pixlen * tilelen; /* check that tile size/type has not changed */ if (tilesize != (infptr->Fptr)->tiledatasize[tilecol] || datatype != (infptr->Fptr)->tiletype[tilecol] ) { if (((infptr->Fptr)->tiledata)[tilecol]) { free(((infptr->Fptr)->tiledata)[tilecol]); } if (((infptr->Fptr)->tilenullarray)[tilecol]) { free(((infptr->Fptr)->tilenullarray)[tilecol]); } ((infptr->Fptr)->tilenullarray)[tilecol] = 0; ((infptr->Fptr)->tilerow)[tilecol] = 0; ((infptr->Fptr)->tiledatasize)[tilecol] = 0; ((infptr->Fptr)->tiletype)[tilecol] = 0; /* allocate new array(s) */ ((infptr->Fptr)->tiledata)[tilecol] = malloc(tilesize); if (((infptr->Fptr)->tiledata)[tilecol] == 0) return (*status); if (nullcheck == 2) { /* also need array of null pixel flags */ (infptr->Fptr)->tilenullarray[tilecol] = malloc(tilelen); if ((infptr->Fptr)->tilenullarray[tilecol] == 0) return (*status); } (infptr->Fptr)->tiledatasize[tilecol] = tilesize; (infptr->Fptr)->tiletype[tilecol] = datatype; } /* copy the tile array(s) into cache buffer */ memcpy((infptr->Fptr)->tiledata[tilecol], buffer, tilesize); if (nullcheck == 2) { if ((infptr->Fptr)->tilenullarray == 0) { (infptr->Fptr)->tilenullarray[tilecol] = malloc(tilelen); } memcpy((infptr->Fptr)->tilenullarray[tilecol], bnullarray, tilelen); } (infptr->Fptr)->tilerow[tilecol] = nrow; (infptr->Fptr)->tileanynull[tilecol] = *anynul; } } return (*status); } /*--------------------------------------------------------------------------*/ int imcomp_test_overlap ( int ndim, /* I - number of dimension in the tile and image */ long *tfpixel, /* I - first pixel number in each dim. of the tile */ long *tlpixel, /* I - last pixel number in each dim. of the tile */ long *fpixel, /* I - first pixel number in each dim. of the image */ long *lpixel, /* I - last pixel number in each dim. of the image */ long *ininc, /* I - increment to be applied in each image dimen. */ int *status) /* test if there are any intersecting pixels between this tile and the section of the image defined by fixel, lpixel, ininc. */ { long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */ /* output image, allowing for inc factor */ long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */ /* tile, array; inc factor is not relevant */ long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */ /* allowing for inc factor */ long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */ /* allowing for inc factor */ long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */ /* allowing for inc factor */ long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */ int ii; long tf, tl; if (*status > 0) return(*status); /* ------------------------------------------------------------ */ /* calc amount of overlap in each dimension; if there is zero */ /* overlap in any dimension then just return */ /* ------------------------------------------------------------ */ for (ii = 0; ii < ndim; ii++) { if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii]) return(0); /* there are no overlapping pixels */ inc[ii] = ininc[ii]; /* calc dimensions of the output image section */ imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1; if (imgdim[ii] < 1) { *status = NEG_AXIS; return(0); } /* calc dimensions of the tile */ tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1; if (tiledim[ii] < 1) { *status = NEG_AXIS; return(0); } if (ii > 0) tiledim[ii] *= tiledim[ii - 1]; /* product of dimensions */ /* first and last pixels in image that overlap with the tile, 0 base */ tf = tfpixel[ii] - 1; tl = tlpixel[ii] - 1; /* skip this plane if it falls in the cracks of the subsampled image */ while ((tf-(fpixel[ii] - 1)) % labs(inc[ii])) { tf++; if (tf > tl) return(0); /* no overlapping pixels */ } while ((tl-(fpixel[ii] - 1)) % labs(inc[ii])) { tl--; if (tf > tl) return(0); /* no overlapping pixels */ } imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0); imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) , imgdim[ii] - 1); /* first pixel in the tile that overlaps with the image (0 base) */ tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0); while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii])) { (tilefpix[ii])++; if (tilefpix[ii] >= tiledim[ii]) return(0); /* no overlapping pixels */ } if (ii > 0) imgdim[ii] *= imgdim[ii - 1]; /* product of dimensions */ } return(1); /* there appears to be intersecting pixels */ } /*--------------------------------------------------------------------------*/ int imcomp_copy_overlap ( char *tile, /* I - multi dimensional array of tile pixels */ int pixlen, /* I - number of bytes in each tile or image pixel */ int ndim, /* I - number of dimension in the tile and image */ long *tfpixel, /* I - first pixel number in each dim. of the tile */ long *tlpixel, /* I - last pixel number in each dim. of the tile */ char *bnullarray, /* I - array of null flags; used if nullcheck = 2 */ char *image, /* O - multi dimensional output image */ long *fpixel, /* I - first pixel number in each dim. of the image */ long *lpixel, /* I - last pixel number in each dim. of the image */ long *ininc, /* I - increment to be applied in each image dimen. */ int nullcheck, /* I - 0, 1: do nothing; 2: set nullarray for nulls */ char *nullarray, int *status) /* copy the intersecting pixels from a decompressed tile to the output image. Both the tile and the image must have the same number of dimensions. */ { long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */ /* output image, allowing for inc factor */ long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */ /* tile, array; inc factor is not relevant */ long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */ /* allowing for inc factor */ long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */ /* allowing for inc factor */ long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */ /* allowing for inc factor */ long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */ long i1, i2, i3, i4; /* offset along each axis of the image */ long it1, it2, it3, it4; long im1, im2, im3, im4; /* offset to image pixel, allowing for inc */ long ipos, tf, tl; long t2, t3, t4; /* offset along each axis of the tile */ long tilepix, imgpix, tilepixbyte, imgpixbyte; int ii, overlap_bytes, overlap_flags; if (*status > 0) return(*status); for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { /* set default values for higher dimensions */ inc[ii] = 1; imgdim[ii] = 1; tiledim[ii] = 1; imgfpix[ii] = 0; imglpix[ii] = 0; tilefpix[ii] = 0; } /* ------------------------------------------------------------ */ /* calc amount of overlap in each dimension; if there is zero */ /* overlap in any dimension then just return */ /* ------------------------------------------------------------ */ for (ii = 0; ii < ndim; ii++) { if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii]) return(*status); /* there are no overlapping pixels */ inc[ii] = ininc[ii]; /* calc dimensions of the output image section */ imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1; if (imgdim[ii] < 1) return(*status = NEG_AXIS); /* calc dimensions of the tile */ tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1; if (tiledim[ii] < 1) return(*status = NEG_AXIS); if (ii > 0) tiledim[ii] *= tiledim[ii - 1]; /* product of dimensions */ /* first and last pixels in image that overlap with the tile, 0 base */ tf = tfpixel[ii] - 1; tl = tlpixel[ii] - 1; /* skip this plane if it falls in the cracks of the subsampled image */ while ((tf-(fpixel[ii] - 1)) % labs(inc[ii])) { tf++; if (tf > tl) return(*status); /* no overlapping pixels */ } while ((tl-(fpixel[ii] - 1)) % labs(inc[ii])) { tl--; if (tf > tl) return(*status); /* no overlapping pixels */ } imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0); imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) , imgdim[ii] - 1); /* first pixel in the tile that overlaps with the image (0 base) */ tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0); while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii])) { (tilefpix[ii])++; if (tilefpix[ii] >= tiledim[ii]) return(*status); /* no overlapping pixels */ } /* printf("ii tfpixel, tlpixel %d %d %d \n",ii, tfpixel[ii], tlpixel[ii]); printf("ii, tf, tl, imgfpix,imglpix, tilefpix %d %d %d %d %d %d\n",ii, tf,tl,imgfpix[ii], imglpix[ii],tilefpix[ii]); */ if (ii > 0) imgdim[ii] *= imgdim[ii - 1]; /* product of dimensions */ } /* ---------------------------------------------------------------- */ /* calc number of pixels in each row (first dimension) that overlap */ /* multiply by pixlen to get number of bytes to copy in each loop */ /* ---------------------------------------------------------------- */ if (inc[0] != 1) overlap_flags = 1; /* can only copy 1 pixel at a time */ else overlap_flags = imglpix[0] - imgfpix[0] + 1; /* can copy whole row */ overlap_bytes = overlap_flags * pixlen; /* support up to 5 dimensions for now */ for (i4 = 0, it4=0; i4 <= imglpix[4] - imgfpix[4]; i4++, it4++) { /* increment plane if it falls in the cracks of the subsampled image */ while (ndim > 4 && (tfpixel[4] + tilefpix[4] - fpixel[4] + it4) % labs(inc[4]) != 0) it4++; /* offset to start of hypercube */ if (inc[4] > 0) im4 = (i4 + imgfpix[4]) * imgdim[3]; else im4 = imgdim[4] - (i4 + 1 + imgfpix[4]) * imgdim[3]; t4 = (tilefpix[4] + it4) * tiledim[3]; for (i3 = 0, it3=0; i3 <= imglpix[3] - imgfpix[3]; i3++, it3++) { /* increment plane if it falls in the cracks of the subsampled image */ while (ndim > 3 && (tfpixel[3] + tilefpix[3] - fpixel[3] + it3) % labs(inc[3]) != 0) it3++; /* offset to start of cube */ if (inc[3] > 0) im3 = (i3 + imgfpix[3]) * imgdim[2] + im4; else im3 = imgdim[3] - (i3 + 1 + imgfpix[3]) * imgdim[2] + im4; t3 = (tilefpix[3] + it3) * tiledim[2] + t4; /* loop through planes of the image */ for (i2 = 0, it2=0; i2 <= imglpix[2] - imgfpix[2]; i2++, it2++) { /* incre plane if it falls in the cracks of the subsampled image */ while (ndim > 2 && (tfpixel[2] + tilefpix[2] - fpixel[2] + it2) % labs(inc[2]) != 0) it2++; /* offset to start of plane */ if (inc[2] > 0) im2 = (i2 + imgfpix[2]) * imgdim[1] + im3; else im2 = imgdim[2] - (i2 + 1 + imgfpix[2]) * imgdim[1] + im3; t2 = (tilefpix[2] + it2) * tiledim[1] + t3; /* loop through rows of the image */ for (i1 = 0, it1=0; i1 <= imglpix[1] - imgfpix[1]; i1++, it1++) { /* incre row if it falls in the cracks of the subsampled image */ while (ndim > 1 && (tfpixel[1] + tilefpix[1] - fpixel[1] + it1) % labs(inc[1]) != 0) it1++; /* calc position of first pixel in tile to be copied */ tilepix = tilefpix[0] + (tilefpix[1] + it1) * tiledim[0] + t2; /* offset to start of row */ if (inc[1] > 0) im1 = (i1 + imgfpix[1]) * imgdim[0] + im2; else im1 = imgdim[1] - (i1 + 1 + imgfpix[1]) * imgdim[0] + im2; /* printf("inc = %d %d %d %d\n",inc[0],inc[1],inc[2],inc[3]); printf("im1,im2,im3,im4 = %d %d %d %d\n",im1,im2,im3,im4); */ /* offset to byte within the row */ if (inc[0] > 0) imgpix = imgfpix[0] + im1; else imgpix = imgdim[0] - 1 - imgfpix[0] + im1; /* printf("tilefpix0,1, imgfpix1, it1, inc1, t2= %d %d %d %d %d %d\n", tilefpix[0],tilefpix[1],imgfpix[1],it1,inc[1], t2); printf("i1, it1, tilepix, imgpix %d %d %d %d \n", i1, it1, tilepix, imgpix); */ /* loop over pixels along one row of the image */ for (ipos = imgfpix[0]; ipos <= imglpix[0]; ipos += overlap_flags) { if (nullcheck == 2) { /* copy overlapping null flags from tile to image */ memcpy(nullarray + imgpix, bnullarray + tilepix, overlap_flags); } /* convert from image pixel to byte offset */ tilepixbyte = tilepix * pixlen; imgpixbyte = imgpix * pixlen; /* printf(" tilepix, tilepixbyte, imgpix, imgpixbyte= %d %d %d %d\n", tilepix, tilepixbyte, imgpix, imgpixbyte); */ /* copy overlapping row of pixels from tile to image */ memcpy(image + imgpixbyte, tile + tilepixbyte, overlap_bytes); tilepix += (overlap_flags * labs(inc[0])); if (inc[0] > 0) imgpix += overlap_flags; else imgpix -= overlap_flags; } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int imcomp_merge_overlap ( char *tile, /* O - multi dimensional array of tile pixels */ int pixlen, /* I - number of bytes in each tile or image pixel */ int ndim, /* I - number of dimension in the tile and image */ long *tfpixel, /* I - first pixel number in each dim. of the tile */ long *tlpixel, /* I - last pixel number in each dim. of the tile */ char *bnullarray, /* I - array of null flags; used if nullcheck = 2 */ char *image, /* I - multi dimensional output image */ long *fpixel, /* I - first pixel number in each dim. of the image */ long *lpixel, /* I - last pixel number in each dim. of the image */ int nullcheck, /* I - 0, 1: do nothing; 2: set nullarray for nulls */ int *status) /* Similar to imcomp_copy_overlap, except it copies the overlapping pixels from the 'image' to the 'tile'. */ { long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */ /* output image, allowing for inc factor */ long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */ /* tile, array; inc factor is not relevant */ long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */ /* allowing for inc factor */ long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */ /* allowing for inc factor */ long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */ /* allowing for inc factor */ long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */ long i1, i2, i3, i4; /* offset along each axis of the image */ long it1, it2, it3, it4; long im1, im2, im3, im4; /* offset to image pixel, allowing for inc */ long ipos, tf, tl; long t2, t3, t4; /* offset along each axis of the tile */ long tilepix, imgpix, tilepixbyte, imgpixbyte; int ii, overlap_bytes, overlap_flags; if (*status > 0) return(*status); for (ii = 0; ii < MAX_COMPRESS_DIM; ii++) { /* set default values for higher dimensions */ inc[ii] = 1; imgdim[ii] = 1; tiledim[ii] = 1; imgfpix[ii] = 0; imglpix[ii] = 0; tilefpix[ii] = 0; } /* ------------------------------------------------------------ */ /* calc amount of overlap in each dimension; if there is zero */ /* overlap in any dimension then just return */ /* ------------------------------------------------------------ */ for (ii = 0; ii < ndim; ii++) { if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii]) return(*status); /* there are no overlapping pixels */ /* calc dimensions of the output image section */ imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1; if (imgdim[ii] < 1) return(*status = NEG_AXIS); /* calc dimensions of the tile */ tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1; if (tiledim[ii] < 1) return(*status = NEG_AXIS); if (ii > 0) tiledim[ii] *= tiledim[ii - 1]; /* product of dimensions */ /* first and last pixels in image that overlap with the tile, 0 base */ tf = tfpixel[ii] - 1; tl = tlpixel[ii] - 1; /* skip this plane if it falls in the cracks of the subsampled image */ while ((tf-(fpixel[ii] - 1)) % labs(inc[ii])) { tf++; if (tf > tl) return(*status); /* no overlapping pixels */ } while ((tl-(fpixel[ii] - 1)) % labs(inc[ii])) { tl--; if (tf > tl) return(*status); /* no overlapping pixels */ } imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0); imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) , imgdim[ii] - 1); /* first pixel in the tile that overlaps with the image (0 base) */ tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0); while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii])) { (tilefpix[ii])++; if (tilefpix[ii] >= tiledim[ii]) return(*status); /* no overlapping pixels */ } /* printf("ii tfpixel, tlpixel %d %d %d \n",ii, tfpixel[ii], tlpixel[ii]); printf("ii, tf, tl, imgfpix,imglpix, tilefpix %d %d %d %d %d %d\n",ii, tf,tl,imgfpix[ii], imglpix[ii],tilefpix[ii]); */ if (ii > 0) imgdim[ii] *= imgdim[ii - 1]; /* product of dimensions */ } /* ---------------------------------------------------------------- */ /* calc number of pixels in each row (first dimension) that overlap */ /* multiply by pixlen to get number of bytes to copy in each loop */ /* ---------------------------------------------------------------- */ if (inc[0] != 1) overlap_flags = 1; /* can only copy 1 pixel at a time */ else overlap_flags = imglpix[0] - imgfpix[0] + 1; /* can copy whole row */ overlap_bytes = overlap_flags * pixlen; /* support up to 5 dimensions for now */ for (i4 = 0, it4=0; i4 <= imglpix[4] - imgfpix[4]; i4++, it4++) { /* increment plane if it falls in the cracks of the subsampled image */ while (ndim > 4 && (tfpixel[4] + tilefpix[4] - fpixel[4] + it4) % labs(inc[4]) != 0) it4++; /* offset to start of hypercube */ if (inc[4] > 0) im4 = (i4 + imgfpix[4]) * imgdim[3]; else im4 = imgdim[4] - (i4 + 1 + imgfpix[4]) * imgdim[3]; t4 = (tilefpix[4] + it4) * tiledim[3]; for (i3 = 0, it3=0; i3 <= imglpix[3] - imgfpix[3]; i3++, it3++) { /* increment plane if it falls in the cracks of the subsampled image */ while (ndim > 3 && (tfpixel[3] + tilefpix[3] - fpixel[3] + it3) % labs(inc[3]) != 0) it3++; /* offset to start of cube */ if (inc[3] > 0) im3 = (i3 + imgfpix[3]) * imgdim[2] + im4; else im3 = imgdim[3] - (i3 + 1 + imgfpix[3]) * imgdim[2] + im4; t3 = (tilefpix[3] + it3) * tiledim[2] + t4; /* loop through planes of the image */ for (i2 = 0, it2=0; i2 <= imglpix[2] - imgfpix[2]; i2++, it2++) { /* incre plane if it falls in the cracks of the subsampled image */ while (ndim > 2 && (tfpixel[2] + tilefpix[2] - fpixel[2] + it2) % labs(inc[2]) != 0) it2++; /* offset to start of plane */ if (inc[2] > 0) im2 = (i2 + imgfpix[2]) * imgdim[1] + im3; else im2 = imgdim[2] - (i2 + 1 + imgfpix[2]) * imgdim[1] + im3; t2 = (tilefpix[2] + it2) * tiledim[1] + t3; /* loop through rows of the image */ for (i1 = 0, it1=0; i1 <= imglpix[1] - imgfpix[1]; i1++, it1++) { /* incre row if it falls in the cracks of the subsampled image */ while (ndim > 1 && (tfpixel[1] + tilefpix[1] - fpixel[1] + it1) % labs(inc[1]) != 0) it1++; /* calc position of first pixel in tile to be copied */ tilepix = tilefpix[0] + (tilefpix[1] + it1) * tiledim[0] + t2; /* offset to start of row */ if (inc[1] > 0) im1 = (i1 + imgfpix[1]) * imgdim[0] + im2; else im1 = imgdim[1] - (i1 + 1 + imgfpix[1]) * imgdim[0] + im2; /* printf("inc = %d %d %d %d\n",inc[0],inc[1],inc[2],inc[3]); printf("im1,im2,im3,im4 = %d %d %d %d\n",im1,im2,im3,im4); */ /* offset to byte within the row */ if (inc[0] > 0) imgpix = imgfpix[0] + im1; else imgpix = imgdim[0] - 1 - imgfpix[0] + im1; /* printf("tilefpix0,1, imgfpix1, it1, inc1, t2= %d %d %d %d %d %d\n", tilefpix[0],tilefpix[1],imgfpix[1],it1,inc[1], t2); printf("i1, it1, tilepix, imgpix %d %d %d %d \n", i1, it1, tilepix, imgpix); */ /* loop over pixels along one row of the image */ for (ipos = imgfpix[0]; ipos <= imglpix[0]; ipos += overlap_flags) { /* convert from image pixel to byte offset */ tilepixbyte = tilepix * pixlen; imgpixbyte = imgpix * pixlen; /* printf(" tilepix, tilepixbyte, imgpix, imgpixbyte= %d %d %d %d\n", tilepix, tilepixbyte, imgpix, imgpixbyte); */ /* copy overlapping row of pixels from image to tile */ memcpy(tile + tilepixbyte, image + imgpixbyte, overlap_bytes); tilepix += (overlap_flags * labs(inc[0])); if (inc[0] > 0) imgpix += overlap_flags; else imgpix -= overlap_flags; } } } } } return(*status); } /*--------------------------------------------------------------------------*/ static int unquantize_i1r4(long row, /* tile number = row number in table */ unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - dithering method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ float nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ float *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Unquantize byte values into the scaled floating point values */ { long ii; int nextrand, iseed; if (!fits_rand_value) if (fits_init_randoms()) return(MEMORY_ALLOCATION); /* initialize the index to the next random number in the list */ iseed = (int) ((row - 1) % N_RANDOM); nextrand = (int) (fits_rand_value[iseed] * 500); if (nullcheck == 0) /* no null checking required */ { for (ii = 0; ii < ntodo; ii++) { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } else /* must check for null values */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); } nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } return(*status); } /*--------------------------------------------------------------------------*/ static int unquantize_i2r4(long row, /* seed for random values */ short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - dithering method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ float nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ float *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Unquantize short integer values into the scaled floating point values */ { long ii; int nextrand, iseed; if (!fits_rand_value) if (fits_init_randoms()) return(MEMORY_ALLOCATION); /* initialize the index to the next random number in the list */ iseed = (int) ((row - 1) % N_RANDOM); nextrand = (int) (fits_rand_value[iseed] * 500); if (nullcheck == 0) /* no null checking required */ { for (ii = 0; ii < ntodo; ii++) { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } else /* must check for null values */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); } nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } return(*status); } /*--------------------------------------------------------------------------*/ static int unquantize_i4r4(long row, /* tile number = row number in table */ INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - dithering method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ float nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ float *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Unquantize int integer values into the scaled floating point values */ { long ii; int nextrand, iseed; if (fits_rand_value == 0) if (fits_init_randoms()) return(MEMORY_ALLOCATION); /* initialize the index to the next random number in the list */ iseed = (int) ((row - 1) % N_RANDOM); nextrand = (int) (fits_rand_value[iseed] * 500); if (nullcheck == 0) /* no null checking required */ { for (ii = 0; ii < ntodo; ii++) { if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } else /* must check for null values */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); } nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } return(*status); } /*--------------------------------------------------------------------------*/ static int unquantize_i1r8(long row, /* tile number = row number in table */ unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - dithering method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ double nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ double *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Unquantize byte values into the scaled floating point values */ { long ii; int nextrand, iseed; if (!fits_rand_value) if (fits_init_randoms()) return(MEMORY_ALLOCATION); /* initialize the index to the next random number in the list */ iseed = (int) ((row - 1) % N_RANDOM); nextrand = (int) (fits_rand_value[iseed] * 500); if (nullcheck == 0) /* no null checking required */ { for (ii = 0; ii < ntodo; ii++) { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } else /* must check for null values */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); } nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } return(*status); } /*--------------------------------------------------------------------------*/ static int unquantize_i2r8(long row, /* tile number = row number in table */ short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - dithering method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ double nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ double *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Unquantize short integer values into the scaled floating point values */ { long ii; int nextrand, iseed; if (!fits_rand_value) if (fits_init_randoms()) return(MEMORY_ALLOCATION); /* initialize the index to the next random number in the list */ iseed = (int) ((row - 1) % N_RANDOM); nextrand = (int) (fits_rand_value[iseed] * 500); if (nullcheck == 0) /* no null checking required */ { for (ii = 0; ii < ntodo; ii++) { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } else /* must check for null values */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { /* if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else */ output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); } nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } return(*status); } /*--------------------------------------------------------------------------*/ static int unquantize_i4r8(long row, /* tile number = row number in table */ INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int dither_method, /* I - dithering method to use */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ double nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ double *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Unquantize int integer values into the scaled floating point values */ { long ii; int nextrand, iseed; if (fits_rand_value == 0) if (fits_init_randoms()) return(MEMORY_ALLOCATION); /* initialize the index to the next random number in the list */ iseed = (int) ((row - 1) % N_RANDOM); nextrand = (int) (fits_rand_value[iseed] * 500); if (nullcheck == 0) /* no null checking required */ { for (ii = 0; ii < ntodo; ii++) { if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } else /* must check for null values */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE) output[ii] = 0.0; else output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero); } nextrand++; if (nextrand == N_RANDOM) { iseed++; if (iseed == N_RANDOM) iseed = 0; nextrand = (int) (fits_rand_value[iseed] * 500); } } } return(*status); } /*--------------------------------------------------------------------------*/ static int imcomp_float2nan(float *indata, long tilelen, int *outdata, float nullflagval, int *status) /* convert pixels that are equal to nullflag to NaNs. Note that indata and outdata point to the same location. */ { int ii; for (ii = 0; ii < tilelen; ii++) { if (indata[ii] == nullflagval) outdata[ii] = -1; /* integer -1 has the same bit pattern as a real*4 NaN */ } return(*status); } /*--------------------------------------------------------------------------*/ static int imcomp_double2nan(double *indata, long tilelen, LONGLONG *outdata, double nullflagval, int *status) /* convert pixels that are equal to nullflag to NaNs. Note that indata and outdata point to the same location. */ { int ii; for (ii = 0; ii < tilelen; ii++) { if (indata[ii] == nullflagval) outdata[ii] = -1; /* integer -1 has the same bit pattern as a real*8 NaN */ } return(*status); } /* ======================================================================= */ /* TABLE COMPRESSION ROUTINES */ /* =-====================================================================== */ /*--------------------------------------------------------------------------*/ int fits_compress_table(fitsfile *infptr, fitsfile *outfptr, int *status) /* Compress the input FITS Binary Table. First divide the table into equal sized chunks (analogous to image tiles) where all the contain the same number of rows (except perhaps for the last chunk which may contain fewer rows). The chunks should not be too large to copy into memory (currently, about 100 MB max seems a reasonable size). Then, on a chunk by piece basis, do the following: 1. Transpose the table from its original row-major order, into column-major order. All the bytes for each column are then continuous. In addition, the bytes within each table element may be shuffled so that the most significant byte of every element occurs first in the array, followed by the next most significant byte, and so on to the least significant byte. Byte shuffling often improves the gzip compression of floating-point arrays. 2. Compress the contiguous array of bytes in each column using the specified compression method. If no method is specifed, then a default method for that data type is chosen. 3. Store the compressed stream of bytes into a column that has the same name as in the input table, but which has a variable-length array data type (1QB). The output table will contain one row for each piece of the original table. 4. If the input table contain variable-length arrays, then each VLA is compressed individually, and written to the heap in the output table. Note that the output table will contain 2 sets of pointers for each VLA column. The first set contains the pointers to the uncompressed VLAs from the input table and the second is the set of pointers to the compressed VLAs in the output table. The latter set of pointers is used to reconstruct table when it is uncompressed, so that the heap has exactly the same structure as in the original file. The 2 sets of pointers are concatinated together, compressed with gzip, and written to the output table. When reading the compressed table, the only VLA that is directly visible is this compressed array of descriptors. One has to uncompress this array to be able to to read all the descriptors to the individual VLAs in the column. */ { long maxchunksize = 10000000; /* default value for the size of each chunk of the table */ char *cm_buffer; /* memory buffer for the transposed, Column-Major, chunk of the table */ LONGLONG cm_colstart[1000]; /* starting offset of each column in the cm_buffer */ LONGLONG rm_repeat[1000]; /* repeat count of each column in the input row-major table */ LONGLONG rm_colwidth[999]; /* width in bytes of each column in the input row-major table */ LONGLONG cm_repeat[999]; /* total number of elements in each column of the transposed column-major table */ int coltype[999]; /* data type code for each column */ int compalgor[999], default_algor = 0; /* compression algorithm to be applied to each column */ float cratio[999]; /* compression ratio for each column (for diagnostic purposes) */ float compressed_size, uncompressed_size, tot_compressed_size, tot_uncompressed_size; LONGLONG nrows, firstrow; LONGLONG headstart, datastart, dataend, startbyte, jj, kk, naxis1; LONGLONG vlalen, vlamemlen, vlastart, bytepos; long repeat, width, nchunks, rowspertile, lastrows; int ii, ll, ncols, hdutype, ltrue = 1, print_report = 0, tstatus; char *cptr, keyname[9], tform[40], *cdescript; char comm[FLEN_COMMENT], keyvalue[FLEN_VALUE], *cvlamem, tempstring[FLEN_VALUE], card[FLEN_CARD]; LONGLONG *descriptors, *outdescript, *vlamem; int *pdescriptors; size_t dlen, datasize, compmemlen; /* ================================================================================== */ /* perform initial sanity checks */ /* ================================================================================== */ /* special input flag value that means print out diagnostics */ if (*status == -999) { print_report = 1; *status = 0; } if (*status > 0) return(*status); fits_get_hdu_type(infptr, &hdutype, status); if (hdutype != BINARY_TBL) { *status = NOT_BTABLE; return(*status); } if (infptr == outfptr) { ffpmsg("Cannot compress table 'in place' (fits_compress_table)"); ffpmsg(" outfptr cannot be the same as infptr."); *status = DATA_COMPRESSION_ERR; return(*status); } /* get dimensions of the table */ fits_get_num_rowsll(infptr, &nrows, status); fits_get_num_cols(infptr, &ncols, status); fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status); /* get offset to the start of the data and total size of the table (including the heap) */ fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status); if (*status > 0) return(*status); tstatus = 0; if (!fits_read_key(infptr, TSTRING, "FZALGOR", tempstring, NULL, &tstatus)) { if (!fits_strcasecmp(tempstring, "NONE")) { default_algor = NOCOMPRESS; } else if (!fits_strcasecmp(tempstring, "GZIP") || !fits_strcasecmp(tempstring, "GZIP_1")) { default_algor = GZIP_1; } else if (!fits_strcasecmp(tempstring, "GZIP_2")) { default_algor = GZIP_2; } else if (!fits_strcasecmp(tempstring, "RICE_1")) { default_algor = RICE_1; } else { ffpmsg("FZALGOR specifies unsupported table compression algorithm:"); ffpmsg(tempstring); *status = DATA_COMPRESSION_ERR; return(*status); } } /* just copy the HDU verbatim if the table has 0 columns or rows or if the table */ /* is less than 5760 bytes (2 blocks) in size, or compression directive keyword = "NONE" */ if (nrows < 1 || ncols < 1 || (dataend - datastart) < 5760 || default_algor == NOCOMPRESS) { fits_copy_hdu (infptr, outfptr, 0, status); return(*status); } /* Check if the chunk size has been specified with the FZTILELN keyword. */ /* If not, calculate a default number of rows per chunck, */ tstatus = 0; if (fits_read_key(infptr, TLONG, "FZTILELN", &rowspertile, NULL, &tstatus)) { rowspertile = (long) (maxchunksize / naxis1); } if (rowspertile < 1) rowspertile = 1; if (rowspertile > nrows) rowspertile = (long) nrows; nchunks = (long) ((nrows - 1) / rowspertile + 1); /* total number of chunks */ lastrows = (long) (nrows - ((nchunks - 1) * rowspertile)); /* number of rows in last chunk */ /* allocate space for the transposed, column-major chunk of the table */ cm_buffer = calloc((size_t) naxis1, (size_t) rowspertile); if (!cm_buffer) { ffpmsg("Could not allocate cm_buffer for transposed table"); *status = MEMORY_ALLOCATION; return(*status); } /* ================================================================================== */ /* Construct the header of the output compressed table */ /* ================================================================================== */ fits_copy_header(infptr, outfptr, status); /* start with verbatim copy of the input header */ fits_write_key(outfptr, TLOGICAL, "ZTABLE", <rue, "this is a compressed table", status); fits_write_key(outfptr, TLONG, "ZTILELEN", &rowspertile, "number of rows in each tile", status); fits_read_card(outfptr, "NAXIS1", card, status); /* copy NAXIS1 to ZNAXIS1 */ strncpy(card, "ZNAXIS1", 7); fits_write_record(outfptr, card, status); fits_read_card(outfptr, "NAXIS2", card, status); /* copy NAXIS2 to ZNAXIS2 */ strncpy(card, "ZNAXIS2", 7); fits_write_record(outfptr, card, status); fits_read_card(outfptr, "PCOUNT", card, status); /* copy PCOUNT to ZPCOUNT */ strncpy(card, "ZPCOUNT", 7); fits_write_record(outfptr, card, status); fits_modify_key_lng(outfptr, "NAXIS2", nchunks, "&", status); /* 1 row per chunk */ fits_modify_key_lng(outfptr, "NAXIS1", ncols * 16, "&", status); /* 16 bytes for each 1QB column */ fits_modify_key_lng(outfptr, "PCOUNT", 0L, "&", status); /* reset PCOUNT to 0 */ /* rename the Checksum keywords, if they exist */ tstatus = 0; fits_modify_name(outfptr, "CHECKSUM", "ZHECKSUM", &tstatus); tstatus = 0; fits_modify_name(outfptr, "DATASUM", "ZDATASUM", &tstatus); /* ================================================================================== */ /* Now loop over each column of the input table: write the column-specific keywords */ /* and determine which compression algorithm to use. */ /* Also calculate various offsets to the start of the column data in both the */ /* original row-major table and in the transposed column-major form of the table. */ /* ================================================================================== */ cm_colstart[0] = 0; for (ii = 0; ii < ncols; ii++) { /* get the structural parameters of the original uncompressed column */ fits_make_keyn("TFORM", ii+1, keyname, status); fits_read_key(outfptr, TSTRING, keyname, tform, comm, status); fits_binary_tform(tform, coltype+ii, &repeat, &width, status); /* get the repeat count and the width */ /* preserve the original TFORM value and comment string in a ZFORMn keyword */ fits_read_card(outfptr, keyname, card, status); card[0] = 'Z'; fits_write_record(outfptr, card, status); /* All columns in the compressed table will have a variable-length array type. */ fits_modify_key_str(outfptr, keyname, "1QB", "&", status); /* Use 'Q' pointers (64-bit) */ /* deal with special cases: bit, string, and variable length array columns */ if (coltype[ii] == TBIT) { repeat = (repeat + 7) / 8; /* convert from bits to equivalent number of bytes */ } else if (coltype[ii] == TSTRING) { width = 1; /* ignore the optional 'w' in 'rAw' format */ } else if (coltype[ii] < 0) { /* pointer to variable length array */ if (strchr(tform,'Q') ) { width = 16; /* 'Q' descriptor has 64-bit pointers */ } else { width = 8; /* 'P' descriptor has 32-bit pointers */ } repeat = 1; } rm_repeat[ii] = repeat; rm_colwidth[ii] = repeat * width; /* column width (in bytes)in the input table */ /* starting offset of each field in the OUTPUT transposed column-major table */ cm_colstart[ii + 1] = cm_colstart[ii] + rm_colwidth[ii] * rowspertile; /* total number of elements in each column of the transposed column-major table */ cm_repeat[ii] = rm_repeat[ii] * rowspertile; compalgor[ii] = default_algor; /* initialize the column compression algorithm to the default */ /* check if a compression method has been specified for this column */ fits_make_keyn("FZALG", ii+1, keyname, status); tstatus = 0; if (!fits_read_key(outfptr, TSTRING, keyname, tempstring, NULL, &tstatus)) { if (!fits_strcasecmp(tempstring, "GZIP") || !fits_strcasecmp(tempstring, "GZIP_1")) { compalgor[ii] = GZIP_1; } else if (!fits_strcasecmp(tempstring, "GZIP_2")) { compalgor[ii] = GZIP_2; } else if (!fits_strcasecmp(tempstring, "RICE_1")) { compalgor[ii] = RICE_1; } else { ffpmsg("Unsupported table compression algorithm specification."); ffpmsg(keyname); ffpmsg(tempstring); *status = DATA_COMPRESSION_ERR; free(cm_buffer); return(*status); } } /* do sanity check of the requested algorithm and override if necessary */ if ( abs(coltype[ii]) == TLOGICAL || abs(coltype[ii]) == TBIT || abs(coltype[ii]) == TSTRING) { if (compalgor[ii] != GZIP_1) { compalgor[ii] = GZIP_1; } } else if ( abs(coltype[ii]) == TCOMPLEX || abs(coltype[ii]) == TDBLCOMPLEX || abs(coltype[ii]) == TFLOAT || abs(coltype[ii]) == TDOUBLE || abs(coltype[ii]) == TLONGLONG ) { if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2) { compalgor[ii] = GZIP_2; /* gzip_2 usually works better gzip_1 */ } } else if ( abs(coltype[ii]) == TSHORT ) { if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2 && compalgor[ii] != RICE_1) { compalgor[ii] = GZIP_2; /* gzip_2 usually works better rice_1 */ } } else if ( abs(coltype[ii]) == TLONG ) { if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2 && compalgor[ii] != RICE_1) { compalgor[ii] = RICE_1; } } else if ( abs(coltype[ii]) == TBYTE ) { if (compalgor[ii] != GZIP_1 && compalgor[ii] != RICE_1 ) { compalgor[ii] = GZIP_1; } } } /* end of loop over columns */ /* ================================================================================== */ /* now process each chunk of the table, in turn */ /* ================================================================================== */ tot_uncompressed_size = 0.; tot_compressed_size = 0; firstrow = 1; for (ll = 0; ll < nchunks; ll++) { if (ll == nchunks - 1) { /* the last chunk may have fewer rows */ rowspertile = lastrows; for (ii = 0; ii < ncols; ii++) { cm_colstart[ii + 1] = cm_colstart[ii] + (rm_colwidth[ii] * rowspertile); cm_repeat[ii] = rm_repeat[ii] * rowspertile; } } /* move to the start of the chunk in the input table */ ffmbyt(infptr, datastart, 0, status); /* ================================================================================*/ /* First, transpose this chunck from row-major order to column-major order */ /* At the same time, shuffle the bytes in each datum, if doing GZIP_2 compression */ /* ================================================================================*/ for (jj = 0; jj < rowspertile; jj++) { /* loop over rows */ for (ii = 0; ii < ncols; ii++) { /* loop over columns */ if (rm_repeat[ii] > 0) { /* skip virtual columns that have 0 elements */ kk = 0; /* if the GZIP_2 compression algorithm is used, shuffle the bytes */ if (coltype[ii] == TSHORT && compalgor[ii] == GZIP_2) { while(kk < rm_colwidth[ii]) { cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/2); ffgbyt(infptr, 1, cptr, status); /* get 1st byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 2nd byte */ kk += 2; } } else if ((coltype[ii] == TFLOAT || coltype[ii] == TLONG) && compalgor[ii] == GZIP_2) { while(kk < rm_colwidth[ii]) { cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/4); ffgbyt(infptr, 1, cptr, status); /* get 1st byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 2nd byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 3rd byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 4th byte */ kk += 4; } } else if ( (coltype[ii] == TDOUBLE || coltype[ii] == TLONGLONG) && compalgor[ii] == GZIP_2) { while(kk < rm_colwidth[ii]) { cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/8); ffgbyt(infptr, 1, cptr, status); /* get 1st byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 2nd byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 3rd byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 4th byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 5th byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 6th byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 7th byte */ cptr += cm_repeat[ii]; ffgbyt(infptr, 1, cptr, status); /* get 8th byte */ kk += 8; } } else { /* all other cases: don't shuffle the bytes; simply transpose the column */ cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_colwidth[ii])); /* addr to copy to */ startbyte = (infptr->Fptr)->bytepos; /* save the starting byte location */ ffgbyt(infptr, rm_colwidth[ii], cptr, status); /* copy all the bytes */ if (rm_colwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */ ffmbyt(infptr, startbyte + rm_colwidth[ii], 0, status); } } /* end of test of coltypee */ } /* end of not virtual column */ } /* end of loop over columns */ } /* end of loop over rows */ /* ================================================================================*/ /* now compress each column in the transposed chunk of the table */ /* ================================================================================*/ fits_set_hdustruc(outfptr, status); /* initialize structures in the output table */ for (ii = 0; ii < ncols; ii++) { /* loop over columns */ /* initialize the diagnostic compression results string */ snprintf(results[ii],30,"%3d %3d %3d ", ii+1, coltype[ii], compalgor[ii]); cratio[ii] = 0; if (rm_repeat[ii] > 0) { /* skip virtual columns with zero width */ if (coltype[ii] < 0) { /* this is a variable length array (VLA) column */ /*=========================================================================*/ /* variable-length array columns are a complicated special case */ /*=========================================================================*/ /* allocate memory to hold all the VLA descriptors from the input table, plus */ /* room to hold the descriptors to the compressed VLAs in the output table */ /* In total, there will be 2 descriptors for each row in this chunk */ uncompressed_size = 0.; compressed_size = 0; datasize = (size_t) (cm_colstart[ii + 1] - cm_colstart[ii]); /* size of input descriptors */ cdescript = calloc(datasize + (rowspertile * 16), 1); /* room for both descriptors */ if (!cdescript) { ffpmsg("Could not allocate buffer for descriptors"); *status = MEMORY_ALLOCATION; free(cm_buffer); return(*status); } /* copy the input descriptors to this array */ memcpy(cdescript, &cm_buffer[cm_colstart[ii]], datasize); #if BYTESWAPPED /* byte-swap the integer values into the native machine representation */ if (rm_colwidth[ii] == 16) { ffswap8((double *) cdescript, rowspertile * 2); } else { ffswap4((int *) cdescript, rowspertile * 2); } #endif descriptors = (LONGLONG *) cdescript; /* use this for Q type descriptors */ pdescriptors = (int *) cdescript; /* use this instead for or P type descriptors */ /* pointer to the 2nd set of descriptors */ outdescript = (LONGLONG *) (cdescript + datasize); /* this is a LONGLONG pointer */ for (jj = 0; jj < rowspertile; jj++) { /* loop to compress each VLA in turn */ if (rm_colwidth[ii] == 16) { /* if Q pointers */ vlalen = descriptors[jj * 2]; vlastart = descriptors[(jj * 2) + 1]; } else { /* if P pointers */ vlalen = (LONGLONG) pdescriptors[jj * 2]; vlastart = (LONGLONG) pdescriptors[(jj * 2) + 1]; } if (vlalen > 0) { /* skip zero-length VLAs */ vlamemlen = vlalen * (int) (-coltype[ii] / 10); vlamem = (LONGLONG *) malloc((size_t) vlamemlen); /* memory for the input uncompressed VLA */ if (!vlamem) { ffpmsg("Could not allocate buffer for VLA"); *status = MEMORY_ALLOCATION; free(cdescript); free(cm_buffer); return(*status); } compmemlen = (size_t) (vlalen * ((LONGLONG) (-coltype[ii] / 10)) * 1.5); if (compmemlen < 100) compmemlen = 100; cvlamem = malloc(compmemlen); /* memory for the output compressed VLA */ if (!cvlamem) { ffpmsg("Could not allocate buffer for compressed data"); *status = MEMORY_ALLOCATION; free(vlamem); free(cdescript); free(cm_buffer); return(*status); } /* read the raw bytes directly from the heap, without any byte-swapping or null value detection */ bytepos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + vlastart; ffmbyt(infptr, bytepos, REPORT_EOF, status); ffgbyt(infptr, vlamemlen, vlamem, status); /* read the bytes */ uncompressed_size += vlamemlen; /* total size of the uncompressed VLAs */ tot_uncompressed_size += vlamemlen; /* total size of the uncompressed file */ /* compress the VLA with the appropriate algorithm */ if (compalgor[ii] == RICE_1) { if (-coltype[ii] == TSHORT) { #if BYTESWAPPED ffswap2((short *) (vlamem), (long) vlalen); #endif dlen = fits_rcomp_short ((short *)(vlamem), (int) vlalen, (unsigned char *) cvlamem, (int) compmemlen, 32); } else if (-coltype[ii] == TLONG) { #if BYTESWAPPED ffswap4((int *) (vlamem), (long) vlalen); #endif dlen = fits_rcomp ((int *)(vlamem), (int) vlalen, (unsigned char *) cvlamem, (int) compmemlen, 32); } else if (-coltype[ii] == TBYTE) { dlen = fits_rcomp_byte ((signed char *)(vlamem), (int) vlalen, (unsigned char *) cvlamem, (int) compmemlen, 32); } else { /* this should not happen */ ffpmsg(" Error: cannot compress this column type with the RICE algorithm"); free(vlamem); free(cdescript); free(cm_buffer); free(cvlamem); *status = DATA_COMPRESSION_ERR; return(*status); } } else if (compalgor[ii] == GZIP_1 || compalgor[ii] == GZIP_2){ if (compalgor[ii] == GZIP_2 ) { /* shuffle the bytes before gzipping them */ if ( (int) (-coltype[ii] / 10) == 2) { fits_shuffle_2bytes((char *) vlamem, vlalen, status); } else if ( (int) (-coltype[ii] / 10) == 4) { fits_shuffle_4bytes((char *) vlamem, vlalen, status); } else if ( (int) (-coltype[ii] / 10) == 8) { fits_shuffle_8bytes((char *) vlamem, vlalen, status); } } /*: gzip compress the array of bytes */ compress2mem_from_mem( (char *) vlamem, (size_t) vlamemlen, &cvlamem, &compmemlen, realloc, &dlen, status); } else { /* this should not happen */ ffpmsg(" Error: unknown compression algorithm"); free(vlamem); free(cdescript); free(cm_buffer); free(cvlamem); *status = DATA_COMPRESSION_ERR; return(*status); } /* write the compressed array to the output table, but... */ /* We use a trick of always writing the array to the same row of the output table */ /* and then copy the descriptor into the array of descriptors that we allocated. */ /* First, reset the descriptor */ fits_write_descript(outfptr, ii+1, ll+1, 0, 0, status); /* write the compressed VLA if it is smaller than the original, else write */ /* the uncompressed array */ fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status); /* turn off any data scaling, first */ if (dlen < vlamemlen) { fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status); compressed_size += dlen; /* total size of the compressed VLAs */ tot_compressed_size += dlen; /* total size of the compressed file */ } else { if ( -coltype[ii] != TBYTE && compalgor[ii] != GZIP_1) { /* it is probably faster to reread the raw bytes, rather than unshuffle or unswap them */ bytepos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + vlastart; ffmbyt(infptr, bytepos, REPORT_EOF, status); ffgbyt(infptr, vlamemlen, vlamem, status); /* read the bytes */ } fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, vlamemlen, vlamem, status); compressed_size += vlamemlen; /* total size of the compressed VLAs */ tot_compressed_size += vlamemlen; /* total size of the compressed file */ } /* read back the descriptor and save it in the array of descriptors */ fits_read_descriptll(outfptr, ii + 1, ll + 1, outdescript+(jj*2), outdescript+(jj*2)+1, status); free(cvlamem); free(vlamem); } /* end of vlalen > 0 */ } /* end of loop over rows */ if (compressed_size != 0) cratio[ii] = uncompressed_size / compressed_size; snprintf(tempstring,FLEN_VALUE," r=%6.2f",cratio[ii]); strncat(results[ii],tempstring, 29-strlen(results[ii])); /* now we just have to compress the array of descriptors (both input and output) */ /* and write them to the output table. */ /* allocate memory for the compressed descriptors */ cvlamem = malloc(datasize + (rowspertile * 16) ); if (!cvlamem) { ffpmsg("Could not allocate buffer for compressed data"); *status = MEMORY_ALLOCATION; free(cdescript); free(cm_buffer); return(*status); } #if BYTESWAPPED /* byte swap the input and output descriptors */ if (rm_colwidth[ii] == 16) { ffswap8((double *) cdescript, rowspertile * 2); } else { ffswap4((int *) cdescript, rowspertile * 2); } ffswap8((double *) outdescript, rowspertile * 2); #endif /* compress the array contain both sets of descriptors */ compress2mem_from_mem((char *) cdescript, datasize + (rowspertile * 16), &cvlamem, &datasize, realloc, &dlen, status); free(cdescript); /* write the compressed descriptors to the output column */ fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status); /* turn off any data scaling, first */ fits_write_descript(outfptr, ii+1, ll+1, 0, 0, status); /* First, reset the descriptor */ fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status); free(cvlamem); if (ll == 0) { /* only write the ZCTYPn keyword once, while processing the first column */ fits_make_keyn("ZCTYP", ii+1, keyname, status); if (compalgor[ii] == RICE_1) { strcpy(keyvalue, "RICE_1"); } else if (compalgor[ii] == GZIP_2) { strcpy(keyvalue, "GZIP_2"); } else { strcpy(keyvalue, "GZIP_1"); } fits_write_key(outfptr, TSTRING, keyname, keyvalue, "compression algorithm for column", status); } continue; /* jump to end of loop, to go to next column */ } /* end of VLA case */ /* ================================================================================*/ /* deal with all the normal fixed-length columns here */ /* ================================================================================*/ /* allocate memory for the compressed data */ datasize = (size_t) (cm_colstart[ii + 1] - cm_colstart[ii]); cvlamem = malloc(datasize*2); tot_uncompressed_size += datasize; if (!cvlamem) { ffpmsg("Could not allocate buffer for compressed data"); *status = MEMORY_ALLOCATION; free(cm_buffer); return(*status); } if (compalgor[ii] == RICE_1) { if (coltype[ii] == TSHORT) { #if BYTESWAPPED ffswap2((short *) (cm_buffer + cm_colstart[ii]), datasize / 2); #endif dlen = fits_rcomp_short ((short *)(cm_buffer + cm_colstart[ii]), datasize / 2, (unsigned char *) cvlamem, datasize * 2, 32); } else if (coltype[ii] == TLONG) { #if BYTESWAPPED ffswap4((int *) (cm_buffer + cm_colstart[ii]), datasize / 4); #endif dlen = fits_rcomp ((int *)(cm_buffer + cm_colstart[ii]), datasize / 4, (unsigned char *) cvlamem, datasize * 2, 32); } else if (coltype[ii] == TBYTE) { dlen = fits_rcomp_byte ((signed char *)(cm_buffer + cm_colstart[ii]), datasize, (unsigned char *) cvlamem, datasize * 2, 32); } else { /* this should not happen */ ffpmsg(" Error: cannot compress this column type with the RICE algorthm"); free(cvlamem); free(cm_buffer); *status = DATA_COMPRESSION_ERR; return(*status); } } else { /* all other cases: gzip compress the column (bytes may have been shuffled previously) */ compress2mem_from_mem(cm_buffer + cm_colstart[ii], datasize, &cvlamem, &datasize, realloc, &dlen, status); } if (ll == 0) { /* only write the ZCTYPn keyword once, while processing the first column */ fits_make_keyn("ZCTYP", ii+1, keyname, status); if (compalgor[ii] == RICE_1) { strcpy(keyvalue, "RICE_1"); } else if (compalgor[ii] == GZIP_2) { strcpy(keyvalue, "GZIP_2"); } else { strcpy(keyvalue, "GZIP_1"); } fits_write_key(outfptr, TSTRING, keyname, keyvalue, "compression algorithm for column", status); } /* write the compressed data to the output column */ fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status); /* turn off any data scaling, first */ fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status); tot_compressed_size += dlen; free(cvlamem); /* don't need the compressed data any more */ /* create diagnostic messages */ if (dlen != 0) cratio[ii] = (float) datasize / (float) dlen; /* compression ratio of the column */ snprintf(tempstring,FLEN_VALUE," r=%6.2f",cratio[ii]); strncat(results[ii],tempstring,29-strlen(results[ii])); } /* end of not a virtual column */ } /* end of loop over columns */ datastart += (rowspertile * naxis1); /* increment to start of next chunk */ firstrow += rowspertile; /* increment first row in next chunk */ if (print_report) { printf("\nChunk = %d\n",ll+1); for (ii = 0; ii < ncols; ii++) { printf("%s\n", results[ii]); } } } /* end of loop over chunks of the table */ /* =================================================================================*/ /* all done; just clean up and return */ /* ================================================================================*/ free(cm_buffer); fits_set_hdustruc(outfptr, status); /* reset internal structures */ if (print_report) { if (tot_compressed_size != 0) printf("\nTotal data size (MB) %.3f -> %.3f, ratio = %.3f\n", tot_uncompressed_size/1000000., tot_compressed_size/1000000., tot_uncompressed_size/tot_compressed_size); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status) /* Uncompress the table that was compressed with fits_compress_table */ { char colcode[999]; /* column data type code character */ char coltype[999]; /* column data type numeric code value */ char *cm_buffer; /* memory buffer for the transposed, Column-Major, chunk of the table */ char *rm_buffer; /* memory buffer for the original, Row-Major, chunk of the table */ LONGLONG nrows, rmajor_colwidth[999], rmajor_colstart[1000], cmajor_colstart[1000]; LONGLONG cmajor_repeat[999], rmajor_repeat[999], cmajor_bytespan[999], kk; LONGLONG headstart, datastart = 0, dataend, rowsremain, *descript, *qdescript = 0; LONGLONG rowstart, cvlalen, cvlastart, vlalen, vlastart; long repeat, width, vla_repeat, vla_address, rowspertile, ntile; int ncols, hdutype, inttype, anynull, tstatus, zctype[999], addspace = 0, *pdescript = 0; char *cptr, keyname[9], tform[40]; long pcount, zheapptr, naxis1, naxis2, ii, jj; char *ptr, comm[FLEN_COMMENT], zvalue[FLEN_VALUE], *uncompressed_vla = 0, *compressed_vla; char card[FLEN_CARD]; size_t dlen, fullsize, cm_size, bytepos, vlamemlen; /* ================================================================================== */ /* perform initial sanity checks */ /* ================================================================================== */ if (*status > 0) return(*status); fits_get_hdu_type(infptr, &hdutype, status); if (hdutype != BINARY_TBL) { ffpmsg("This is not a binary table, so cannot uncompress it!"); *status = NOT_BTABLE; return(*status); } if (fits_read_key(infptr, TLOGICAL, "ZTABLE", &tstatus, NULL, status)) { /* just copy the HDU if the table is not compressed */ if (infptr != outfptr) { fits_copy_hdu (infptr, outfptr, 0, status); } return(*status); } fits_get_num_rowsll(infptr, &nrows, status); fits_get_num_cols(infptr, &ncols, status); if ((ncols < 1)) { /* just copy the HDU if the table does not have more than 0 columns */ if (infptr != outfptr) { fits_copy_hdu (infptr, outfptr, 0, status); } return(*status); } fits_read_key(infptr, TLONG, "ZTILELEN", &rowspertile, comm, status); if (*status > 0) { ffpmsg("Could not find the required ZTILELEN keyword"); *status = DATA_DECOMPRESSION_ERR; return(*status); } /**** get size of the uncompressed table */ fits_read_key(infptr, TLONG, "ZNAXIS1", &naxis1, comm, status); if (*status > 0) { ffpmsg("Could not find the required ZNAXIS1 keyword"); *status = DATA_DECOMPRESSION_ERR; return(*status); } fits_read_key(infptr, TLONG, "ZNAXIS2", &naxis2, comm, status); if (*status > 0) { ffpmsg("Could not find the required ZNAXIS2 keyword"); *status = DATA_DECOMPRESSION_ERR; return(*status); } /* silently ignore illegal ZTILELEN value if too large */ if (rowspertile > naxis2) rowspertile = naxis2; fits_read_key(infptr, TLONG, "ZPCOUNT", &pcount, comm, status); if (*status > 0) { ffpmsg("Could not find the required ZPCOUNT keyword"); *status = DATA_DECOMPRESSION_ERR; return(*status); } tstatus = 0; fits_read_key(infptr, TLONG, "ZHEAPPTR", &zheapptr, comm, &tstatus); if (tstatus > 0) { zheapptr = 0; /* uncompressed table has no heap */ } /* ================================================================================== */ /* copy of the input header, then recreate the uncompressed table keywords */ /* ================================================================================== */ fits_copy_header(infptr, outfptr, status); /* reset the NAXIS1, NAXIS2. and PCOUNT keywords to the original */ fits_read_card(outfptr, "ZNAXIS1", card, status); strncpy(card, "NAXIS1 ", 7); fits_update_card(outfptr, "NAXIS1", card, status); fits_read_card(outfptr, "ZNAXIS2", card, status); strncpy(card, "NAXIS2 ", 7); fits_update_card(outfptr, "NAXIS2", card, status); fits_read_card(outfptr, "ZPCOUNT", card, status); strncpy(card, "PCOUNT ", 7); fits_update_card(outfptr, "PCOUNT", card, status); fits_delete_key(outfptr, "ZTABLE", status); fits_delete_key(outfptr, "ZTILELEN", status); fits_delete_key(outfptr, "ZNAXIS1", status); fits_delete_key(outfptr, "ZNAXIS2", status); fits_delete_key(outfptr, "ZPCOUNT", status); tstatus = 0; fits_delete_key(outfptr, "CHECKSUM", &tstatus); tstatus = 0; fits_delete_key(outfptr, "DATASUM", &tstatus); /* restore the Checksum keywords, if they exist */ tstatus = 0; fits_modify_name(outfptr, "ZHECKSUM", "CHECKSUM", &tstatus); tstatus = 0; fits_modify_name(outfptr, "ZDATASUM", "DATASUM", &tstatus); /* ================================================================================== */ /* determine compression paramters for each column and write column-specific keywords */ /* ================================================================================== */ for (ii = 0; ii < ncols; ii++) { /* get the original column type, repeat count, and unit width */ fits_make_keyn("ZFORM", ii+1, keyname, status); fits_read_key(infptr, TSTRING, keyname, tform, comm, status); /* restore the original TFORM value and comment */ fits_read_card(outfptr, keyname, card, status); card[0] = 'T'; keyname[0] = 'T'; fits_update_card(outfptr, keyname, card, status); /* now delete the ZFORM keyword */ keyname[0] = 'Z'; fits_delete_key(outfptr, keyname, status); cptr = tform; while(isdigit(*cptr)) cptr++; colcode[ii] = *cptr; /* save the column type code */ fits_binary_tform(tform, &inttype, &repeat, &width, status); coltype[ii] = inttype; /* deal with special cases */ if (abs(coltype[ii]) == TBIT) { repeat = (repeat + 7) / 8 ; /* convert from bits to bytes */ } else if (abs(coltype[ii]) == TSTRING) { width = 1; } else if (coltype[ii] < 0) { /* pointer to variable length array */ if (colcode[ii] == 'P') width = 8; /* this is a 'P' column */ else width = 16; /* this is a 'Q' not a 'P' column */ addspace += 16; /* need space for a second set of Q pointers for this column */ } rmajor_repeat[ii] = repeat; /* width (in bytes) of each field in the row-major table */ rmajor_colwidth[ii] = rmajor_repeat[ii] * width; /* construct the ZCTYPn keyword name then read the keyword */ fits_make_keyn("ZCTYP", ii+1, keyname, status); tstatus = 0; fits_read_key(infptr, TSTRING, keyname, zvalue, NULL, &tstatus); if (tstatus) { zctype[ii] = GZIP_2; } else { if (!strcmp(zvalue, "GZIP_2")) { zctype[ii] = GZIP_2; } else if (!strcmp(zvalue, "GZIP_1")) { zctype[ii] = GZIP_1; } else if (!strcmp(zvalue, "RICE_1")) { zctype[ii] = RICE_1; } else { ffpmsg("Unrecognized ZCTYPn keyword compression code:"); ffpmsg(zvalue); *status = DATA_DECOMPRESSION_ERR; return(*status); } /* delete this keyword from the uncompressed header */ fits_delete_key(outfptr, keyname, status); } } /* rescan header keywords to reset internal table structure parameters */ fits_set_hdustruc(outfptr, status); /* ================================================================================== */ /* allocate memory for the transposed and untransposed tile of the table */ /* ================================================================================== */ fullsize = naxis1 * rowspertile; cm_size = fullsize + (addspace * rowspertile); cm_buffer = malloc(cm_size); if (!cm_buffer) { ffpmsg("Could not allocate buffer for transformed column-major table"); *status = MEMORY_ALLOCATION; return(*status); } rm_buffer = malloc(fullsize); if (!rm_buffer) { ffpmsg("Could not allocate buffer for untransformed row-major table"); *status = MEMORY_ALLOCATION; free(cm_buffer); return(*status); } /* ================================================================================== */ /* Main loop over all the tiles */ /* ================================================================================== */ rowsremain = naxis2; rowstart = 1; ntile = 0; while(rowsremain) { /* ================================================================================== */ /* loop over each column: read and uncompress the bytes */ /* ================================================================================== */ ntile++; rmajor_colstart[0] = 0; cmajor_colstart[0] = 0; for (ii = 0; ii < ncols; ii++) { cmajor_repeat[ii] = rmajor_repeat[ii] * rowspertile; /* starting offset of each field in the column-major table */ if (coltype[ii] > 0) { /* normal fixed length column */ cmajor_colstart[ii + 1] = cmajor_colstart[ii] + rmajor_colwidth[ii] * rowspertile; } else { /* VLA column: reserve space for the 2nd set of Q pointers */ cmajor_colstart[ii + 1] = cmajor_colstart[ii] + (rmajor_colwidth[ii] + 16) * rowspertile; } /* length of each sequence of bytes, after sorting them in signicant order */ cmajor_bytespan[ii] = (rmajor_repeat[ii] * rowspertile); /* starting offset of each field in the row-major table */ rmajor_colstart[ii + 1] = rmajor_colstart[ii] + rmajor_colwidth[ii]; if (rmajor_repeat[ii] > 0) { /* ignore columns with 0 elements */ /* read compressed bytes from input table */ fits_read_descript(infptr, ii + 1, ntile, &vla_repeat, &vla_address, status); /* allocate memory and read in the compressed bytes */ ptr = malloc(vla_repeat); if (!ptr) { ffpmsg("Could not allocate buffer for uncompressed bytes"); *status = MEMORY_ALLOCATION; free(rm_buffer); free(cm_buffer); return(*status); } fits_set_tscale(infptr, ii + 1, 1.0, 0.0, status); /* turn off any data scaling, first */ fits_read_col_byt(infptr, ii + 1, ntile, 1, vla_repeat, 0, (unsigned char *) ptr, &anynull, status); cptr = cm_buffer + cmajor_colstart[ii]; /* size in bytes of the uncompressed column of bytes */ fullsize = (size_t) (cmajor_colstart[ii+1] - cmajor_colstart[ii]); switch (colcode[ii]) { case 'I': if (zctype[ii] == RICE_1) { dlen = fits_rdecomp_short((unsigned char *)ptr, vla_repeat, (unsigned short *)cptr, fullsize / 2, 32); #if BYTESWAPPED ffswap2((short *) cptr, fullsize / 2); #endif } else { /* gunzip the data into the correct location */ uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status); } break; case 'J': if (zctype[ii] == RICE_1) { dlen = fits_rdecomp ((unsigned char *) ptr, vla_repeat, (unsigned int *)cptr, fullsize / 4, 32); #if BYTESWAPPED ffswap4((int *) cptr, fullsize / 4); #endif } else { /* gunzip the data into the correct location */ uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status); } break; case 'B': if (zctype[ii] == RICE_1) { dlen = fits_rdecomp_byte ((unsigned char *) ptr, vla_repeat, (unsigned char *)cptr, fullsize, 32); } else { /* gunzip the data into the correct location */ uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status); } break; default: /* all variable length array columns are included in this case */ /* gunzip the data into the correct location in the full table buffer */ uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status); } /* end of switch block */ free(ptr); } /* end of rmajor_repeat > 0 */ } /* end of loop over columns */ /* now transpose the rows and columns (from cm_buffer to rm_buffer) */ /* move each byte, in turn, from the cm_buffer to the appropriate place in the rm_buffer */ for (ii = 0; ii < ncols; ii++) { /* loop over columns */ ptr = (char *) (cm_buffer + cmajor_colstart[ii]); /* initialize ptr to start of the column in the cm_buffer */ if (rmajor_repeat[ii] > 0) { /* skip columns with zero elements */ if (coltype[ii] > 0) { /* normal fixed length array columns */ if (zctype[ii] == GZIP_2) { /* need to unshuffle the bytes */ /* recombine the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */ switch (colcode[ii]) { case 'I': /* get the 1st byte of each I*2 value */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols])); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 2; } } /* get the 2nd byte of each I*2 value */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 2; } } break; case 'J': case 'E': /* get the 1st byte of each 4-byte value */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols])); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 4; } } /* get the 2nd byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 4; } } /* get the 3rd byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 2); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 4; } } /* get the 4th byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 3); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 4; } } break; case 'D': case 'K': /* get the 1st byte of each 8-byte value */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols])); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 2nd byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 3rd byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 2); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 4th byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 3); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 5th byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 4); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 6th byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 5); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 7th byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 6); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } /* get the 8th byte */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 7); for (kk = 0; kk < rmajor_repeat[ii]; kk++) { *cptr = *ptr; /* copy 1 byte */ ptr++; cptr += 8; } } break; default: /* should never get here */ ffpmsg("Error: unexpected attempt to use GZIP_2 to compress a column unsuitable data type"); *status = DATA_DECOMPRESSION_ERR; free(rm_buffer); free(cm_buffer); return(*status); } /* end of switch for shuffling the bytes*/ } else { /* not GZIP_2, don't have to shuffle bytes, so just transpose the rows and columns */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output table */ cptr = rm_buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]); /* addr to copy to */ memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]); ptr += (rmajor_colwidth[ii]); } } } else { /* transpose the variable length array pointers */ for (jj = 0; jj < rowspertile; jj++) { /* loop over number of rows in the output uncompressed table */ cptr = rm_buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]); /* addr to copy to */ memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]); ptr += (rmajor_colwidth[ii]); } if (rmajor_colwidth[ii] == 8 ) { /* these are P-type descriptors */ pdescript = (int *) (cm_buffer + cmajor_colstart[ii]); #if BYTESWAPPED ffswap4((int *) pdescript, rowspertile * 2); /* byte-swap the descriptor */ #endif } else if (rmajor_colwidth[ii] == 16 ) { /* these are Q-type descriptors */ qdescript = (LONGLONG *) (cm_buffer + cmajor_colstart[ii]); #if BYTESWAPPED ffswap8((double *) qdescript, rowspertile * 2); /* byte-swap the descriptor */ #endif } else { /* this should never happen */ ffpmsg("Error: Descriptor column is neither 8 nor 16 bytes wide"); free(rm_buffer); free(cm_buffer); *status = DATA_DECOMPRESSION_ERR; return(*status); } /* First, set pointer to the Q descriptors, and byte-swap them, if needed */ descript = (LONGLONG*) (cm_buffer + cmajor_colstart[ii] + (rmajor_colwidth[ii] * rowspertile)); #if BYTESWAPPED /* byte-swap the descriptor */ ffswap8((double *) descript, rowspertile * 2); #endif /* now uncompress all the individual VLAs, and */ /* write them to their original location in the uncompressed file */ for (jj = 0; jj < rowspertile; jj++) { /* loop over rows */ /* get the size and location of the compressed VLA in the compressed table */ cvlalen = descript[jj * 2]; cvlastart = descript[(jj * 2) + 1]; if (cvlalen > 0 ) { /* get the size and location to write the uncompressed VLA in the uncompressed table */ if (rmajor_colwidth[ii] == 8 ) { vlalen = pdescript[jj * 2]; vlastart = pdescript[(jj * 2) + 1]; } else { vlalen = qdescript[jj * 2]; vlastart = qdescript[(jj * 2) + 1]; } vlamemlen = (size_t) (vlalen * (-coltype[ii] / 10)); /* size of the uncompressed VLA, in bytes */ /* allocate memory for the compressed vla */ compressed_vla = malloc( (size_t) cvlalen); if (!compressed_vla) { ffpmsg("Could not allocate buffer for compressed VLA"); free(rm_buffer); free(cm_buffer); *status = MEMORY_ALLOCATION; return(*status); } /* read the compressed VLA from the heap in the input compressed table */ bytepos = (size_t) ((infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + cvlastart); ffmbyt(infptr, bytepos, REPORT_EOF, status); ffgbyt(infptr, cvlalen, compressed_vla, status); /* read the bytes */ /* if the VLA couldn't be compressed, just copy it directly to the output uncompressed table */ if (cvlalen == vlamemlen ) { bytepos = (size_t) ((outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + vlastart); ffmbyt(outfptr, bytepos, IGNORE_EOF, status); ffpbyt(outfptr, cvlalen, compressed_vla, status); /* write the bytes */ } else { /* uncompress the VLA */ /* allocate memory for the uncompressed VLA */ uncompressed_vla = malloc(vlamemlen); if (!uncompressed_vla) { ffpmsg("Could not allocate buffer for uncompressed VLA"); *status = MEMORY_ALLOCATION; free(compressed_vla); free(rm_buffer); free(cm_buffer); return(*status); } /* uncompress the VLA with the appropriate algorithm */ if (zctype[ii] == RICE_1) { if (-coltype[ii] == TSHORT) { dlen = fits_rdecomp_short((unsigned char *) compressed_vla, (int) cvlalen, (unsigned short *)uncompressed_vla, (int) vlalen, 32); #if BYTESWAPPED ffswap2((short *) uncompressed_vla, (long) vlalen); #endif } else if (-coltype[ii] == TLONG) { dlen = fits_rdecomp((unsigned char *) compressed_vla, (int) cvlalen, (unsigned int *)uncompressed_vla, (int) vlalen, 32); #if BYTESWAPPED ffswap4((int *) uncompressed_vla, (long) vlalen); #endif } else if (-coltype[ii] == TBYTE) { dlen = fits_rdecomp_byte((unsigned char *) compressed_vla, (int) cvlalen, (unsigned char *) uncompressed_vla, (int) vlalen, 32); } else { /* this should not happen */ ffpmsg(" Error: cannot uncompress this column type with the RICE algorithm"); *status = DATA_DECOMPRESSION_ERR; free(uncompressed_vla); free(compressed_vla); free(rm_buffer); free(cm_buffer); return(*status); } } else if (zctype[ii] == GZIP_1 || zctype[ii] == GZIP_2){ /*: gzip uncompress the array of bytes */ uncompress2mem_from_mem( compressed_vla, (size_t) cvlalen, &uncompressed_vla, &vlamemlen, realloc, &vlamemlen, status); if (zctype[ii] == GZIP_2 ) { /* unshuffle the bytes after ungzipping them */ if ( (int) (-coltype[ii] / 10) == 2) { fits_unshuffle_2bytes((char *) uncompressed_vla, vlalen, status); } else if ( (int) (-coltype[ii] / 10) == 4) { fits_unshuffle_4bytes((char *) uncompressed_vla, vlalen, status); } else if ( (int) (-coltype[ii] / 10) == 8) { fits_unshuffle_8bytes((char *) uncompressed_vla, vlalen, status); } } } else { /* this should not happen */ ffpmsg(" Error: unknown compression algorithm"); free(uncompressed_vla); free(compressed_vla); free(rm_buffer); free(cm_buffer); *status = DATA_COMPRESSION_ERR; return(*status); } bytepos = (size_t) ((outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + vlastart); ffmbyt(outfptr, bytepos, IGNORE_EOF, status); ffpbyt(outfptr, vlamemlen, uncompressed_vla, status); /* write the bytes */ free(uncompressed_vla); } /* end of uncompress VLA */ free(compressed_vla); } /* end of vlalen > 0 */ } /* end of loop over rowspertile */ } /* end of variable length array section*/ } /* end of if column repeat > 0 */ } /* end of ncols loop */ /* copy the buffer of data to the output data unit */ if (datastart == 0) fits_get_hduaddrll(outfptr, &headstart, &datastart, &dataend, status); ffmbyt(outfptr, datastart, 1, status); ffpbyt(outfptr, naxis1 * rowspertile, rm_buffer, status); /* increment pointers for next tile */ rowstart += rowspertile; rowsremain -= rowspertile; datastart += (naxis1 * rowspertile); if (rowspertile > rowsremain) rowspertile = (long) rowsremain; } /* end of while rows still remain */ free(rm_buffer); free(cm_buffer); /* reset internal table structure parameters */ fits_set_hdustruc(outfptr, status); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_shuffle_2bytes(char *heap, LONGLONG length, int *status) /* shuffle the bytes in an array of 2-byte integers in the heap */ { LONGLONG ii; char *ptr, *cptr, *heapptr; ptr = malloc((size_t) (length * 2)); heapptr = heap; cptr = ptr; for (ii = 0; ii < length; ii++) { *cptr = *heapptr; heapptr++; *(cptr + length) = *heapptr; heapptr++; cptr++; } memcpy(heap, ptr, (size_t) (length * 2)); free(ptr); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_shuffle_4bytes(char *heap, LONGLONG length, int *status) /* shuffle the bytes in an array of 4-byte integers or floats */ { LONGLONG ii; char *ptr, *cptr, *heapptr; ptr = malloc((size_t) (length * 4)); if (!ptr) { ffpmsg("malloc failed\n"); return(*status); } heapptr = heap; cptr = ptr; for (ii = 0; ii < length; ii++) { *cptr = *heapptr; heapptr++; *(cptr + length) = *heapptr; heapptr++; *(cptr + (length * 2)) = *heapptr; heapptr++; *(cptr + (length * 3)) = *heapptr; heapptr++; cptr++; } memcpy(heap, ptr, (size_t) (length * 4)); free(ptr); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_shuffle_8bytes(char *heap, LONGLONG length, int *status) /* shuffle the bytes in an array of 8-byte integers or doubles in the heap */ { LONGLONG ii; char *ptr, *cptr, *heapptr; ptr = calloc(1, (size_t) (length * 8)); heapptr = heap; /* for some bizarre reason this loop fails to compile under OpenSolaris using the proprietary SunStudioExpress C compiler; use the following equivalent loop instead. cptr = ptr; for (ii = 0; ii < length; ii++) { *cptr = *heapptr; heapptr++; *(cptr + length) = *heapptr; heapptr++; *(cptr + (length * 2)) = *heapptr; heapptr++; *(cptr + (length * 3)) = *heapptr; heapptr++; *(cptr + (length * 4)) = *heapptr; heapptr++; *(cptr + (length * 5)) = *heapptr; heapptr++; *(cptr + (length * 6)) = *heapptr; heapptr++; *(cptr + (length * 7)) = *heapptr; heapptr++; cptr++; } */ for (ii = 0; ii < length; ii++) { cptr = ptr + ii; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; cptr += length; *cptr = *heapptr; heapptr++; } memcpy(heap, ptr, (size_t) (length * 8)); free(ptr); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status) /* unshuffle the bytes in an array of 2-byte integers */ { LONGLONG ii; char *ptr, *cptr, *heapptr; ptr = malloc((size_t) (length * 2)); heapptr = heap + (2 * length) - 1; cptr = ptr + (2 * length) - 1; for (ii = 0; ii < length; ii++) { *cptr = *heapptr; cptr--; *cptr = *(heapptr - length); cptr--; heapptr--; } memcpy(heap, ptr, (size_t) (length * 2)); free(ptr); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_unshuffle_4bytes(char *heap, LONGLONG length, int *status) /* unshuffle the bytes in an array of 4-byte integers or floats */ { LONGLONG ii; char *ptr, *cptr, *heapptr; ptr = malloc((size_t) (length * 4)); heapptr = heap + (4 * length) -1; cptr = ptr + (4 * length) -1; for (ii = 0; ii < length; ii++) { *cptr = *heapptr; cptr--; *cptr = *(heapptr - length); cptr--; *cptr = *(heapptr - (2 * length)); cptr--; *cptr = *(heapptr - (3 * length)); cptr--; heapptr--; } memcpy(heap, ptr, (size_t) (length * 4)); free(ptr); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_unshuffle_8bytes(char *heap, LONGLONG length, int *status) /* unshuffle the bytes in an array of 8-byte integers or doubles */ { LONGLONG ii; char *ptr, *cptr, *heapptr; ptr = malloc((size_t) (length * 8)); heapptr = heap + (8 * length) - 1; cptr = ptr + (8 * length) -1; for (ii = 0; ii < length; ii++) { *cptr = *heapptr; cptr--; *cptr = *(heapptr - length); cptr--; *cptr = *(heapptr - (2 * length)); cptr--; *cptr = *(heapptr - (3 * length)); cptr--; *cptr = *(heapptr - (4 * length)); cptr--; *cptr = *(heapptr - (5 * length)); cptr--; *cptr = *(heapptr - (6 * length)); cptr--; *cptr = *(heapptr - (7 * length)); cptr--; heapptr--; } memcpy(heap, ptr, (size_t) (length * 8)); free(ptr); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_int_to_longlong_inplace(int *intarray, long length, int *status) /* convert the input array of 32-bit integers into an array of 64-bit integers, in place. This will overwrite the input array with the new longer array starting at the same memory location. Note that aliasing the same memory location with pointers of different datatypes is not allowed in strict ANSI C99, however it is used here for efficency. In principle, one could simply copy the input array in reverse order to the output array, but this only works if the compiler performs the operation in strict order. Certain compiler optimization techniques may vioate this assumption. Therefore, we first copy a section of the input array to a temporary intermediate array, before copying the longer datatype values back to the original array. */ { LONGLONG *longlongarray, *aliasarray; long ii, ntodo, firstelem, nmax = 10000; if (*status > 0) return(*status); ntodo = nmax; if (length < nmax) ntodo = length; firstelem = length - ntodo; /* first element to be converted */ longlongarray = (LONGLONG *) malloc(ntodo * sizeof(LONGLONG)); if (longlongarray == NULL) { ffpmsg("Out of memory. (fits_int_to_longlong_inplace)"); return (*status = MEMORY_ALLOCATION); } aliasarray = (LONGLONG *) intarray; /* alias pointer to the input array */ while (ntodo > 0) { /* do datatype conversion into temp array */ for (ii = 0; ii < ntodo; ii++) { longlongarray[ii] = intarray[ii + firstelem]; } /* copy temp array back to alias */ memcpy(&(aliasarray[firstelem]), longlongarray, ntodo * 8); if (firstelem == 0) { /* we are all done */ ntodo = 0; } else { /* recalculate ntodo and firstelem for next loop */ if (firstelem > nmax) { firstelem -= nmax; } else { ntodo = firstelem; firstelem = 0; } } } free(longlongarray); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_short_to_int_inplace(short *shortarray, long length, int shift, int *status) /* convert the input array of 16-bit integers into an array of 32-bit integers, in place. This will overwrite the input array with the new longer array starting at the same memory location. Note that aliasing the same memory location with pointers of different datatypes is not allowed in strict ANSI C99, however it is used here for efficency. In principle, one could simply copy the input array in reverse order to the output array, but this only works if the compiler performs the operation in strict order. Certain compiler optimization techniques may vioate this assumption. Therefore, we first copy a section of the input array to a temporary intermediate array, before copying the longer datatype values back to the original array. */ { int *intarray, *aliasarray; long ii, ntodo, firstelem, nmax = 10000; if (*status > 0) return(*status); ntodo = nmax; if (length < nmax) ntodo = length; firstelem = length - ntodo; /* first element to be converted */ intarray = (int *) malloc(ntodo * sizeof(int)); if (intarray == NULL) { ffpmsg("Out of memory. (fits_short_to_int_inplace)"); return (*status = MEMORY_ALLOCATION); } aliasarray = (int *) shortarray; /* alias pointer to the input array */ while (ntodo > 0) { /* do datatype conversion into temp array */ for (ii = 0; ii < ntodo; ii++) { intarray[ii] = (int)(shortarray[ii + firstelem]) + shift; } /* copy temp array back to alias */ memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4); if (firstelem == 0) { /* we are all done */ ntodo = 0; } else { /* recalculate ntodo and firstelem for next loop */ if (firstelem > nmax) { firstelem -= nmax; } else { ntodo = firstelem; firstelem = 0; } } } free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_ushort_to_int_inplace(unsigned short *ushortarray, long length, int shift, int *status) /* convert the input array of 16-bit unsigned integers into an array of 32-bit integers, in place. This will overwrite the input array with the new longer array starting at the same memory location. Note that aliasing the same memory location with pointers of different datatypes is not allowed in strict ANSI C99, however it is used here for efficency. In principle, one could simply copy the input array in reverse order to the output array, but this only works if the compiler performs the operation in strict order. Certain compiler optimization techniques may vioate this assumption. Therefore, we first copy a section of the input array to a temporary intermediate array, before copying the longer datatype values back to the original array. */ { int *intarray, *aliasarray; long ii, ntodo, firstelem, nmax = 10000; if (*status > 0) return(*status); ntodo = nmax; if (length < nmax) ntodo = length; firstelem = length - ntodo; /* first element to be converted */ intarray = (int *) malloc(ntodo * sizeof(int)); if (intarray == NULL) { ffpmsg("Out of memory. (fits_ushort_to_int_inplace)"); return (*status = MEMORY_ALLOCATION); } aliasarray = (int *) ushortarray; /* alias pointer to the input array */ while (ntodo > 0) { /* do datatype conversion into temp array */ for (ii = 0; ii < ntodo; ii++) { intarray[ii] = (int)(ushortarray[ii + firstelem]) + shift; } /* copy temp array back to alias */ memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4); if (firstelem == 0) { /* we are all done */ ntodo = 0; } else { /* recalculate ntodo and firstelem for next loop */ if (firstelem > nmax) { firstelem -= nmax; } else { ntodo = firstelem; firstelem = 0; } } } free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_ubyte_to_int_inplace(unsigned char *ubytearray, long length, int *status) /* convert the input array of 8-bit unsigned integers into an array of 32-bit integers, in place. This will overwrite the input array with the new longer array starting at the same memory location. Note that aliasing the same memory location with pointers of different datatypes is not allowed in strict ANSI C99, however it is used here for efficency. In principle, one could simply copy the input array in reverse order to the output array, but this only works if the compiler performs the operation in strict order. Certain compiler optimization techniques may vioate this assumption. Therefore, we first copy a section of the input array to a temporary intermediate array, before copying the longer datatype values back to the original array. */ { int *intarray, *aliasarray; long ii, ntodo, firstelem, nmax = 10000; if (*status > 0) return(*status); ntodo = nmax; if (length < nmax) ntodo = length; firstelem = length - ntodo; /* first element to be converted */ intarray = (int *) malloc(ntodo * sizeof(int)); if (intarray == NULL) { ffpmsg("Out of memory. (fits_ubyte_to_int_inplace)"); return (*status = MEMORY_ALLOCATION); } aliasarray = (int *) ubytearray; /* alias pointer to the input array */ while (ntodo > 0) { /* do datatype conversion into temp array */ for (ii = 0; ii < ntodo; ii++) { intarray[ii] = ubytearray[ii + firstelem]; } /* copy temp array back to alias */ memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4); if (firstelem == 0) { /* we are all done */ ntodo = 0; } else { /* recalculate ntodo and firstelem for next loop */ if (firstelem > nmax) { firstelem -= nmax; } else { ntodo = firstelem; firstelem = 0; } } } free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ static int fits_sbyte_to_int_inplace(signed char *sbytearray, long length, int *status) /* convert the input array of 8-bit signed integers into an array of 32-bit integers, in place. This will overwrite the input array with the new longer array starting at the same memory location. Note that aliasing the same memory location with pointers of different datatypes is not allowed in strict ANSI C99, however it is used here for efficency. In principle, one could simply copy the input array in reverse order to the output array, but this only works if the compiler performs the operation in strict order. Certain compiler optimization techniques may vioate this assumption. Therefore, we first copy a section of the input array to a temporary intermediate array, before copying the longer datatype values back to the original array. */ /* !!!!!!!!!!!!!!!!! NOTE THAT THIS IS A SPECIALIZED ROUTINE THAT ADDS AN OFFSET OF 128 TO THE ARRAY VALUES !!!!!!!!!!!!!!!!! */ { int *intarray, *aliasarray; long ii, ntodo, firstelem, nmax = 10000; if (*status > 0) return(*status); ntodo = nmax; if (length < nmax) ntodo = length; firstelem = length - ntodo; /* first element to be converted */ intarray = (int *) malloc(ntodo * sizeof(int)); if (intarray == NULL) { ffpmsg("Out of memory. (fits_sbyte_to_int_inplace)"); return (*status = MEMORY_ALLOCATION); } aliasarray = (int *) sbytearray; /* alias pointer to the input array */ while (ntodo > 0) { /* do datatype conversion into temp array */ for (ii = 0; ii < ntodo; ii++) { intarray[ii] = sbytearray[ii + firstelem] + 128; /* !! Note the offset !! */ } /* copy temp array back to alias */ memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4); if (firstelem == 0) { /* we are all done */ ntodo = 0; } else { /* recalculate ntodo and firstelem for next loop */ if (firstelem > nmax) { firstelem -= nmax; } else { ntodo = firstelem; firstelem = 0; } } } free(intarray); return(*status); } int fits_calc_tile_rows(long *tlpixel, long *tfpixel, int ndim, long *trowsize, long *ntrows, int *status) { /* The quantizing algorithms treat all N-dimensional tiles as if they were 2 dimensions (trowsize * ntrows). This sets trowsize to the first dimensional size encountered that's > 1 (typically the X dimension). ntrows will then be the product of the remaining dimensional sizes. Examples: Tile = (5,4,1,3): trowsize=5, ntrows=12 Tile = (1,1,5): trowsize=5, ntrows=1 */ int ii; long np; if (*status) return (*status); *trowsize = 0; *ntrows = 1; for (ii=0; ii 1) { if (!(*trowsize)) *trowsize = np; else *ntrows *= np; } } if (!(*trowsize)) { /* Should only get here for the unusual case of all tile dimensions having size = 1 */ *trowsize = 1; } return (*status); } cfitsio-4.3.1/cfitsio_mac.sit.hqx0000644000225700000360000005550613472024437016266 0ustar cagordonlhea(This file must be converted with BinHex 4.0) :$f0QDA4cD@pIE@&M,R0TG!"6594%8dP8)3#3"%11!*!%4HY6593K!!%!!%11FNa KG3*6!*!$&ZlZ)#!,BfCTG(0TEepYB@-!N"AR#BB"&J!9!U)"eJ#3!`-!N!q'!!! $([q3"!2JYCR`K,@Cp[N!N!8"mK%!N!C$#2r`rrJ!!-0!!!"0Y`!0$N0'DA4cD@p 38%-ZE@0`!*!4Da3*KJ#3$aB!!$i$!*!$&[q3"%e08(*$9dP&!3#[H%fHYCRfmJ# 3"3(U0!#3"Md0!!"9XJ#3"[8H"[LUJEpCRC+&h2,Qp5XR2!PhHq4S2H%,ApKQqmJ LNkpp8AlddNfr[1A)MP#1Tai![I"-haEmadlZiRN5eLh2&pPQYb@hMpc#pMQahU[ MjF@A)`YEb',mbF)EN!#&l)[`r)9RmFZHm#-lbAEK#qr)l6MKLpjbR($&#Ur-Vr0 fK0r#Ma`RA-)l22Q&,13AFTY-&L1cK5jN"9K($6SEG(C1mZ4R0R4JEhDp%a[NjC! $GhCHIV6,b@DM((4ffHR#LbqH!ph[phRj4[C&&ShX)r[YiRdmbHkebmMq[(KN$cV cFa#2l)[X86b,,-plB#b!Vl2VCAikk,fqbH,(bq[*l53meJ,!&[`"jhIkI5f1'd% 3,!Q#dUUJp-!lJY+$p5"BH5ma(bKeP6LDVcDZZdeKNN4a8UiQm9CAbqCLA5QIqP[ XPi0Jl8H#i"hHrpUqXi,J3lqkj2T6Yh"H2r[XNdTd(rB03A$L`5"Bk[dc2RMIZPh "b@rE'34[ackdki2h"FF(`H@c#NqI)P4GS[!F,Pp*9ei&5TqF6!e5'Z+9D"fM`h3 SKb"@J#a`!MD',FIf`[E'9Q$lB2YLqf(lBdr#RS`GJ$d&1a!l&(XDGKKf1,B5HcV f$1`)l*RBNGLcX'GMcm'HKld!Hb&f0$D-(B3GV&F8@iSYXeH9XJm!'S'I``l"RSX p(cX+1aCEK4f((@pf`QYP)SqYmP[j5"8[%qfa(pAKIHX%hY3A6jljZ2T8+l$Y9P+ 9ZSABJ5Ud2KH'fm*+)da6PhC[$C1M&eJq8#d2EIU0kPcTFK1[N!#9EL'@!Z3P+,c -9icR6L[c8`j9I`iR[I25%D#SDkA4H$YaNp&-Gc1XG32c$IHfjC@#kiCLM)K%k9U d0C!!+Y"B$PJ09iKRp+T'ImNm&#%J!p"afpL5RV[@,,R`mrF[ZH#ElqrD[qq5V[h AhHR6KErIYIm6PcaA6"*I""A*,da(Ij9Gqfr-+elX!'`CYKcE#pX2#j!!mKDmMrF f[!P[`aGVCh(5hqLkFX8[lETZ[FY'fki@68BZ'4rrPF(qU1%Ur52RpBmU,(M&e-r [ZMjp9qrk4M`40Y,amE22fMMRMCjalUk29a)ACUirLCZM'DkYiq-#6)e-2)$BNji $[H19,-l5)CG-ZI*`jkGdGbVIp'Te-(q&F1rJqXfekDJZ"VeXY&TjXIkPJR"+B'p X,f`j0LE!&GXAfcq[XZ"cN!$HrL9`cYkY)A1@E%VP'l5+hlRcbk0[mTDf2KX`YaX e[DrL-$5@ED`1G2ZkcR%$Fa@`J+rA8&Ll`)9ePk4(B5"I%%P5e4$j5bD8ZL99"C' %"%)')C`36FJTK2"&@%JPj,)HqlYBb1JU,136iJN"K@"#6L'VI1!b4*@kJP$@BGG L4Gh4a",#Z4rl8L`BHMX@BVS-#r0EJEd4Za,lHpJef*Z`P0R0f&Z`eGL*@0jl&aD -K&[`XMABGGK*f-RBLl$)*TGJT`JBa8l$6XI1`0CLRiqGLGf"[3%,JGq$I3N@rVF HHkYa$AMM[GJAB+r&3Z`KlK"pb2NXib@3!(k)1%)!K2[P15X)"&GM)IQ)!4"pq!T #!&`#-@!$&R5![%2Qlm4HJpf%I4lfaGM0@05cV9J)r6EXE1`Fl+ABZGKjf-Z`ml% ,X*GM&f,"JLZ`,m3ZaYiPU$4)UGRfhGJP@0',!Vq$[4Ul&,YDF#,f+Zc[B+r%hS0 YCr+j6bUTE-2`KTkK[Zkqc5UCjSmUeDA%`6[rejF4)l,TiR`brVA3*Hm,%a+b-,* 3m2Vmm)Grm!5eR`CPMk%khMkK4`-Vr9'@4R'j@Uf8aebD5H$HN!#%3R@q1)AA(!- ,*PeY!S[6i&1kHG`*(+DSEhGqHe)rN3YqQb2j1!RK3Fcr%)dV5eHAPR@*'(UI%,* )f"hrVb$680&UjfB4V1HqC*df[aL&i!5iCF2hhkV$Xr!4rp,Nc`R6Uq!!q&D2TeQ B,2,38L0LY!''CqYC[k2Ei6&eaif6jJX[#J$6`Cm+2mfIND*raNQlmN!cYD6qDhR iehPEAiE`T##&'[YlPQU9DGfVFiN+aG3d"p9Cr"U,Il(jejT5GAfZ@k+UQ[MRfAQ c2FC,l,`Pec"4*3dBEV-mfqdq1r+cj1VIXf&dS&`T9q*@'MGFZEpRl,pCY8HMYE" hS,I"43%j5H+E+PXTX"5C[L@5"*hjT*ck(p+-T'pPA6eAME"lC``ZA"'DN9&,k4l 3V35k$q"r4B!'5-[V2ffqh+G,[2'9A[C+-mQ4Hce6diRfMY3c"p(TcH-lB&51Ndq [$2IfR9iq[EGRV)IMSS(+Q"TA(#UI-kB[e`fL%R@hP1SR6VjaNXdRhjpH,Bp,dX- 85VFXPH*+Ve+iDrm(e&0&Ve"NH8pG[9G[aNDV88Xp2hqKFUUVaZSTqNGXbG"!4Xq 8bTZ'GimiHUU8),CXb,ASJe,U*bV2S1[LSrHS&biT)+AqS0jakVLrZJPI4G4Sb2F KI(e'Ym6dEDP[iqYl396Ar5"4rBELEIL#kKRV6eqQj!ZUEqNNA2)f3I8iREc$9HK &#UVhD8!MdYX%2iA[&-[h-AbRCT8ahLri(A`$XmE&p*Q&T$F-LPS9hLDN(V6"PDa ",eG)Z[q3!%E()H'(e&meY,&XP$Z&e&pfQ[Lcq2i3hl$H*#3qp(Pm`mH5N!#qYG" Am9@Z)&"m2m3RI@k)kQ(eJCh4UMYU+kbqY4'4VK%i6Ve5CrSqeV#8FGk"12VGk!r $pa!(5f(#AqC!2adqDY(fiN@NcG"I4`Pc2VpVrar!jb2U@EXJ1+&1r868mdCr(MR S4k1h$YmIF"MYm5$bjrM'H$b)2)"[V-H$b02iUM`H409R0XlM395pGH-p(N69qcA "id&8Me[Ym5#UrVf*(JqLYq#VmAJ3r5+q54i2SUV,b4i2BY+4,[*i%"0ZAHca)#E "i"+2"c(edNhap4h6@dleH"$6@dlcH"#l(Crdl9&rXDrMQf(jrN8BD2#J4$ed-cd HP+JAF*E(Ja,9j@b2"bAUmC[MmD"%IAQAHM`S89h1pAK3mL9mmc`HP$b+lc+2"k8 5$HCl2#K92b5pGG,69kSq3hVXj+e,e50*Vaep[26@JFY5ck9-Cp#pGb+2P0l"'5b @[X(5KcR6FbFpJDA2F1DY"&r+K$(df8Q2AjNN#RV[D)AQE[4,#T%S8lI3e4Hj5kR 4-Y@Pp!U'`BNbeHAbJ@DEZLN6hUqSELU$ifArJ1rDLi,cHEpb[HA+4PY[@*lhGPD [8FYJZIM%kNEj21URA2fAer@A"lKRZCT**#re9hiG[M8HrmVr'YpDMhrPUX[Vam+ %ZLNAaXM!MNTk+hZT6h$pU-Y)dNYeZD'-8hc8aNBh'X*EHUQ2%8iL$6Qpe)F)&i" Z[)8$[!2I"cR3qiM[#3kf@kUh-'EEijG)[ZNYE"A9X6Fb@1qmVr06Tk9I`3FhZQ& UEINqI25GlR`m&i&k#f0f5C38hr[`lHETjEkpralI(QT,F+Zh4QcFL'STp95KZVa THQd2H&#KZYbl*48Z93J,ETDL+6lHlKDAPDRV#YAPmrhp+X4ME[AhUp#dNaHdfa( [A[(2q&iS495S%lfKYjhILAMR2Z*aq`+5L`pFS2F5HJ@hi!haJ@(dkq*l0`GkGI( "AH"Sq,l,!Ei$(D-h&@k)MjjFqPcaJ5P`,RcdfG)ELZr9(+K(I1!@ICriU(AH&Kr FL$jKB)aq9[J12VJ42Dri`$,H#Kq#*Afdq(kI!p0,m,fI`rhQq`+(9jM[D3k[p,l qkUGpPIRJ%16(4mm`Ei@2IPfCQ+*pVqG!MH0$#RfYq6l2!4c$pkmFb!-9T5rh!I2 "Ym"Y69(PS&[6a8H0[G&m$h*iNrR!@VJN[Up`J"FE1!m%0jZ2AQ[i1$kDcmL2Mcj TX!iIp3b'ib2[@mhh%3j[-aqm"$b"*S0rEcFII2%GjU-Iq*hQJr[#FI"4jqmb(hF $0r"pQ!1F%4riqV$hR5)qqKlc`6RIDcl`'mc%4rr`RjL2HRl%I0bCZXEhF3l`1(` #[`(K#45(RZX2Q)qHG$J&2[UBVAapUM$ecmd(VX%&m&&,F(Cme"rk!ckd"pj6[S' 5T)R&"pHKM["4hr"@I1!([!mI[%dQlfJIZ)$QJ)qhi`haJAr`GhcJabHmEj!!qVi rD6l`$jc("liqEMjkh)@(D"pi*ra%qkM$6jX2[Jk'ii0,`8IN'b`"L9Kmp,6rMIR SdIjEmr&qi"Xqm)Lh`NHGJ+[ii)*Ip,iK`Sm[Q3m0!Nk+$rjNCh)-%Ik"DILS[kq D$hcL,[LS5HS1hcFiJ#(b$C@fK#D!$r`!Zr$4RdiHI25pIp0mF",d%(aJ)PL"MjV mP[QHj2"YlcY0'XChc%G0`hI``5HrCcii#6`,(aJRlGRDalYc&rQ'5926ij6%"ip mbRa`EMJ12ZB4r,2ji#(8*Mk`$#d#(l8"*XJhA'm2VmG(EF&Pm-(RIQ3qCK[)j#E YJdZBKS2!,i06RZ3hR$VaY-&+HR)BCD0pdVR!U!cY%rk[V(HP%TkZE,j&*4LJV21 m%La6[PFR8+BfY1iRhqQ3!"5PZ32iC,k#XZ&"Ti-V5[L-6rLRm[e$J90d*p-E&$K &8kUBJB#21m%aj6Z$'+8q&(`bld'*fq)6,UM8RB42hPjTlJ3qiA)U*d[L%kaAiT, i"&18Y"hj4R"rTEN(q%6c8MD$B!6m@`N(m%R6K4)1ia0m9H+-q)5V+"0J4i#$5V- Em%QY+XePN!$[61+91#!qi@G+I!fID"h+jPbF#6iTm3Km`Tq8G#eme"ED*Ml"%@A khdMH9jRq0e,eD[@rNHKH-J(0q!5cPI!"Rf#U-[e[*&a#L42K%ka4QVdKheR5)Uh qGaEDJM,plbcTY,U[4Ac#GC8d"(c#Se6HkL)q`@@Pq4[bRDekdYd[iT2l+'N#q%5 I8MB)kQc9+0SJ2Z($5[-hm)&2k$Ri")Z9jQl)G`ieVc4r!jr-he$5ar#*0UE`Dap B`P`1I033A!DIm#*Pc86RJ*8UEp!@D96U5QPZ"ci4UT4`(KmD0CS92Z(j5T`&Rr! pC6hIjm)IP'CNb(FH'+5N1H160e,Lb2L%IfZY'jr`HbAZL8riZC)`KSpDK,2J%`k JT2R)GciiSU6riC2l+r%&I05LkB31R)NHSD6ri411UU6ri42HSU6rbAH"-"KHJ%p U3%Nc`3IfS2rK%ae(L8[L%be!5DI&*aa5D9B)2[#-H4hbA3Jf+Fe9`3G1S,AL%`e 'LI2L%ae%5EI%*aa4L8[L!hIYh+C4F!1PH5li`(+d3Aab0bAY!Kpe3lm"2Y%[P$J M2Z'd5[UEI+-e$3JY!TpJNl*T1+1&$I!eI+*Y+G2r4ZXH9[mE$3G@T[q0d6fXrMG '2!$p%"mD-9S%2UN6C3eBBlL2N[D,$fjN1pI(L"m`4`DID!R+QN2'S%FScB("ar[ "fI%*MeALJ2L%[bPV[KX,$e(LFIJ%aj8d0(b#IFSDmmH#"8VD&$jk)Y#kmFPE+-e N`5HkQa*ra`GqfbEqX@J$b[5rX@J0b[5rXA"eCIVI@''`eIr'`L&eMiCm9A!YCIT I&Ca%QIjA*IbcqPq9"K0BrDq+qP5Qre@T&Uhq9i@ZSdcrUd,E8UEr9D'c+02rUX4 6VIih6K1BV2ih$JkM62mETlYDr@mFpDa-raY(,QAkhcLpYpAraSN6@2e[($aFQIi h(XkQ62mE,jjKpEra`L5VrifRaT6TIq24pC6TIq24UT6TIq24!*6TIq09deErQb# 1CI@r#F*1Urp08(eBr@q#kX2UIa1)9kEr64"rYIVI"(36CITIYDCH@[f['JkT62q VKQmSdrqUK3G@rkY@69MpVaTG6jRq9bd-X2TIY6LheImQ`Vf9kAm6iA[+p,q*F!p PqYp%m@1Vrde869[pEb*kRc,pEk,iK0Ar*UVQV2jA)kjMpEmDiBI9rfVJ)FVd[aV a4D[reBMh@2f[4M9YpEmD0#aPqPm01SXbr@q5F06UIj2%JDcq0dPFfHTrNm"LCIV I*1'heImQkAj@rjXNc,$khb6d(@Akhf6a2k[r6BDl+Y2r*N[RX2VIC$#DbCY1Q3r PUGI)m,#a8r0&eSpX0(SE@2U'3ph*@k+**%a%KDVl"`Elb$c1cZ2Y2-(1ARb0R6I Cq@)lAf,R+ADHDZGTGTjZjaPfVVAc6$[2X[0X1mqamk9fRQ[RHADqc-lclEc!cTI EHD'G&pQjbXjAf(Q*RCIDq8SlAfARCADqfXlAf(QjR9IBq9SlVl6c+MZ[Y[0eGUk cmaSlVlAcHMY[X20'R4QRD2eEl,c9cY[X[(fKRS1[ca[ejqI&[%PGB)%ZZdBr1rG I5+G1BX"G+P[)XT6EZCHGbaDbPLe9`a@6MlL#66"J)8(jm[PHGbm&F`R9mMIP+G6 199HAPTr8cMVT@ppq8Y6+bT16mQpH03NBV@I5Bq8CNqdX16B3XA9FTSpccS'T%Dd 6a6TlfeeId-ZiA,F#p%CIKPll'2SfFYB3,HI`iJ#3!-`NXe%!81m40qN5ekU4Bcd c8mf`B!e[$H-fRA!IC'YVU"C)YdX4Y03&l6V*83$Z@a"ea3aSG0B-SN-(%cXH1`& EMDh"EX*HM,d%1`A,hJ(6X01a-l#ef*PBV@1*RB1p&$XA1`pl'ABqGJ(fFZa#l#* X&IB+l",X8Zb9f+Z`bl"ABkr",XHZ`&k,ABPGK9f0[3jEKef$ABYGMpf!hBMG)U! AZ`flAB43E"!E`SDa6F``*bPZAcaQVT!!#f(B[NrMM8l@TEAGAJP@lE`m1'lANU" mmEU6ejkQMR$h,Iph+Fb86idDE*i)l`JB3"QDfphM1@``eKN`"GY&mECQP3(DCC& 5D)qPlCDf@YTMDBZP(CD''0TZDBHPcC!!pN,D#QQ*T4@@&PKDAfPjTG@9&PGD@fP TTC@9'U$eN!#@3eS0D6'N$C2f5pSZDEHNMC-f6GSYDE1N[C)f6pSiDDpNE!MM3KJ 63SXPVC@d90*+53XPVC1d60)U5BXNVC'dJc*+K"%LM!jKC!JYXE6#dJ*,kbXYYE6 -d[T+bbZYVV6FdP*,UbXYN!#d2Y,b5,XVEDkdYp,@5MXVEDbdVp+f5VXUEDUdjY) @56XNEC!!M$pTfN(&@aQ#m3@-,@"F!@-6')[!Z!*[0aA'%M#1J$%%6EZQ-&l!@qH "-3+-9fKDhB(fFpV1D6HRcCcfGGV6D61R[CbfFYVED9rheQI`eQ9)VXS!2D)Yh&[ c)ENq"'h`Y(V6iZfY'q'Y%m+S$'3e2BP8V,GALaf*%Grki0Lq,ibZB'3&SbVS&'0 -"H-T["eJ[,8N''-!@$-@JE%(b48I'*X!BKpDpB%a!i`AS(Z-F3+-%8#@C)3!S`- B'F#S!-E)b2JBhHl2k"K'aL!m-'U'N6'-LQ&8#Qh"Y-VbCV6MmfkdS20fM)TK4)b -2p(M0'3X$+-dp!J0aX)`GS*DCK3-)f!BrF,)&aReSXF2b,JE4Q``@S14'S`BB*` 'Bc4S#kFGR$C`fVpTqkEPR*CbfVjTpkE0QjCd@XYT+DIeR(C[fVaTlkDYQhCZfVK ThkCYQhCY@YTT@DGGQcCYfV0TbkBGQcCXfU0TLkBGQMCSfTpT[DDeQ[CRfTjTGkB eQaCV@UYT`DEYQACRfTaTEkDYQACQfTKTAkCYQGCZ@VGT@kCGQ6CPfT0T5kBGQI% XM'9K(!)M@4M&`SJA4VJ`LS84,)aHB33-ia-BmD&l4aM43#XiidBBad(E-f-!"(F CYm*S$dCk-'k&-5Z-@'$%#U09'+R#+"9'U$#HJ6%bM2aJe!FM2KM"`(J2aRS`KS2 a'icGB0`')cdBfF'i$FCX-&k$N4q-lQ#X"b-f'+h"5!e'D6"#Jp%CM-aJ9!BM-KL 0`8J-4Q%`!S24&ibmB03&Bd)BFm&i#mCD--j#Ml&Jc)q-pp%M*aMY`dJI4J8a#SL 42ScbBB32Sd!BT`'2BI3'A)C4([!B4[N``SIa'A!D'G[$'"BpIS@a2B`'J'm`USI a#Y!#16#+4ir!B2b#m"l'XM#1K6%AM',4)eJB9F#S%PVA'Bh*q!hDj)@6-)U#F4' -L@!m"+-X'%R"+!T'9M!QJ[%3M)@JCB!a%)arB1`$iaiBmm!S$%CG-1D"m3k-G@# F!f-F[2%0MS)2rM2k16(CU!5M$ZalURYfpJNEUH*SqmBHf[c'ai8a"rBp!lkHEL0 b('hI1*(94Pbiim#q*lma1hZhM8&cXRdZXadr4,pU@[Y"cm$pfHF%DFjdKFb`pkU MH5Upr4`8A5*Lk$Uid6E,1l"-95+9lNcSbD1l&hVbk!k(RMad39aEj+&,BQq4Kmk *L88H1JPULMad)H`UmS#TZiXmG#rX+I,3q6#Tb%2Aa13L$jd9&a9jk,kiZ-K$KmB P44kk0kB8HHM`Q&VNS3YN@T%(pA9kNBFZNKP&(MT0DSXmG+2-,2,3XA*VNBHZPPP &(P6&'iSmG-IX,2,33I1#)JmG0V1,2(6Kc#Rbd+PcDC'(ETkj44kkIHB9HHJ)ZUc )3pI3r#)2R88,LMadF&eHj+(lDf'4Kik3!%9&(VU1VLMbd('fZ-K$pp4Y44kkS*B 8HHKkfeINSIYNDC'(lT8VLcaddYeHj+(ElUSL$aej0aGjk0DlXmK$4ppG44kkrZi ZmY!CH-qL!Zpp1)m$k(2,,8VMVYR"bUf`E&rk5br5U1BQAcTK2PdCMSIkG-p8)c- bjAMD2(-r@##5KrlrB88HCJ--,r)`,f$S5hRL%'TA(kdXmM"[B0P,#N3b$l-)4QR 2S)C)rGPamcS2X`Xb(45qdkcjSdUeC*C2I2eV58KIXPRcCmI5+Mh3CXfIG41G+4C b[90jDUXa2G"QcCrYH@Z,@I1RVUd9AS,IiES$rAh-QMm,`MCeDYEmf65c$(ABV2Q M5P&UpaiDCXY4qmfD2lZA9EAbMelcCdCBQfDjd-H8Cee@4CN+D6C"T4YC6aG"Q+H 1VrNcJRZIiHm6*PE2Zj!![[Z`9$lQBB$'c"SC5CjbZcGpj9,cBFhaJ)",$hjBXaA S,qpI+KhhY1@4qSbSpTLE)HH)HX6T-jHHqmJ'lR1"ca04Qa4c0)3$4$5MK(NDV!M %h)l4j)RCIHbD$a(09V"V2N4jUm!j0,a('5GjTZ8KMQi%ZqC$9!SMA5Tb[qK[Fjp URbHUf5,-jC!![[@SjT6B04qLQJNa5H9[lc0jZU3kL!QrQ0NKq@*kViZe"T(N'6C rlfEFNf92jAh#c,[XUcc"rGH[mrH4&GGNKGLeE[N'YhepVpX@eIapYZIe,HjebeN Kad5Z@miU30C9ASNEF9)UYHV+)b[Ul$dRMbJID'ec#@X,LDpda)80bl-Z8jkkLBC EXE&GCmhA4G'-d'9"11d'aK4AbXT%UK6QH(Cp[4)hfkrMjV@0b,@bJGi961rDcCS lXeTCFZQ+8LPeqEh&bIX3*50jBqrUl8X5(N&#PV'5d2C5+9QQ2(YQF1[Vl-iI41T K%I8!CkJ-6JM[,j@@hZTakR+Rp`rZrkMLi5M%rq@K(LQTXbYmrEbalHXRF+IU4ee @ZTcYa9E6ec4HGj-mebQ2HNrT[F69-4,[qHCESac1JPY&JL9[U'JJYpPhNLR"68K !2ekU*mqK32Y5YrCiYEF%U01"(lX%aMBjLp4R*pNh`(30PeNVqUmqGdeMJ92P@c! kd,GbS*@jT-95Al0QfNK(khkiq@VR0pIjY+2FM'e&iecl[[c1GCd,"mD#ffkfMC) 8qiia14*5-KdCH0SC+frl@([P,BpFP8rm(FSSViUK[JdE%D*Z'4dE1CAckk[9@0, C"dHLZPUX2a%kl@SAH)KiE[AerSCfPJXm-6DN84Q"JpSQ9'jBK[Dj#ch[&,@&LAp 8lm!Bm@TYlq#`KV60MQSCpe)M[8QX)@+VMP[B86XFjF-0p8j!iDhj!%1plia#STD MhRp+aTd0+G[H4M,q6-4ZZbr22Se8X$[8l-[($EJS0[6dR@N*mTQ&,ZeH9@khca( )&Fh1,rU-*iM1(j,2lY6PJ2X!"6TZG2q(E"AUT-1&a'E9UmHM9T4&B52Dm6pXmMR GI[8iC(KVe++jcK&4)rqjDh-kU20,l1cUU&J&S'Y,NL-pCA4+Z`+kd`k[e@4fDY9 ITCT'6b33P,D5rpVVblAb49JC)0Qc[@[,$lZfDCD3!,"d,lF$i6[3TY'FiaGhFXj -3XQ0Gfhph#C5KrYfp4Uhh"3qedCcjh-AFYaqhLL9%`q%m4Q2IYS@bTEa'BrqK4E I&CmGRr(S*br4q)bcY1f$Zf4m4T!!@BP#V3bj!PPGCT!!Gq6EQ'AYYDYAEf9)bDL ddqUZaFh9l55ZGfTCZRTVIAVefGeRVkl(YA4ef)jX-A$(b'IQ*0#r`jb%dNAZjL3 X'"eF'fahbA4D(Xh#9Me-kVBjlFf+VD`Q$[cF`Gl!ejF[F'(G*BZ83BQ2#c'2#h@ eiG(bD+IGC[bdbidpq,J3@V4ZVNU*HP30AC!!YQJKMpZQIk*PZd!rIc#!hJ0EG*2 Y8dQSV9aF+Cp66Q28RiZLlr8DKK8Xakl!ASYGL9f&ABfp$PZ(AB0GLef2hB$GL0f #hBVGKQ8VRZkEHTY!R)JJp2SpXXefX*0H[dFZCqX5[pI[NI6HP6Gmqm'hD'GDPhU [RkYQ9T[$p3X1Imhf(T*pJ4CqDpeKIK!F[PGl8l[-2KI[,#Dhh+5q30IVmj9XcI3 $@9+,N!$C!i0p$0,SBqHqkdFfDP012R856DqTE#(,8QlRAREZ[C!!Y@bTfJ2T$Z3 +*'!e06p"qI,4YQ2B!QQm&(+(@&qL8E$KhlIcAIlX[F@*"-,iGaGYLdh6jh`Crfl feVCEDbrS0,)Sk)m54KiXF9009J!-V2AA&'@NFU#Tm8'bfrCP`9"edf(hM,$4L1- @-k@fY)1K6HA+kXUCCrT%bmV9-+f&MGblf1d)URhpKe1R(S#eZH81@q*0FG+SGpH J,22,P@lb92D(Umk0aYI8hpV08qLiaCe@&M8G`5DN,Y[#1CjVp1&FmK`YYf$1L9l AMaa,"SBhEPB@(CYk&aN%%9Kl0++T,NJ5Ih[VY'q29qcdY"PXVJchca@!MN[8Jdj UAiX,aPm[lY@#`2U`jKCH2&N-bDcQ2Ef)KZH63Y22P`UDh6-@V"ebbC3V$a2EN!" 4JJpNE,f'9aT0"4N[1hZa908hKc5PS6UD3jV5m)V0)C12EQMSqldCDC*NpNZ62l) M39)TIE%[QG!2@p1CR+3$9k"Yl54Mf$E&mQadYHQddm5eVKjPYEKKRShe$KiZXPB UcYTJbPQdFDbCmi#9aT0)XfR1ml`jcqBj6q)@2)Eal*P2ZFGbERDAiYJDeleM4mF H`$Ki!12K!Bb("c!HEQ-mA-CiH!$M5Gb#"c!HRYYk%XRe8iM,[!"iZUf6Cpqe2@c $AGILZUQ@GV*)3EZT-JRDJ+ZTiRHT$,R,MYT032r5@U--6QT)mV*Hf!ae(BENlA5 T(LBp#kQfNfCaXhb4Zh4lR066S+G@)j-JrHiYD6!@JTk3!+IG@G5D5Z&5d#Tj*Zf GdBNDGE5mh8QB"VhD%(5$5mSqCm$c"KD`P*ab6HeH&LBYIj'P9Dkic6@#JC(bF"Z XPh9hGJE',q*CV6qHPRHVMHYZ[@[P[TP4UN@rYV,iT54,2#SZ)5,Q[$2HbXUAPV$ B@`Yc5pab3a*hfX+(RHd`59dLZ,SaE)a2(R*S!-0"a@k-+"KG90ZR*l$LZMlCPJM qV'ZV%rEK%Dh6HREj))Y'*0f8K*1UD(&Yi8SEQ9qB`!J5l(468BbN%E$F!JUl1S+ SJeLmYPCl'EhhcXc-KrVS[56Z*$9A(NXF,3,a!VEF5aI2R%Bm33%Q+R46F`&-GM5 L@'jahG!*bAU,5Q!RLhhDU'@p[B1$clrAaM"apHITLeP@T#',af*p)XK9#+'9Ifl ,!MAF5E+YFEB`rm660dl+P3VcbCUSJ59,KYkYPRh@1`ehlEr`9XkX64S*MKr@-Y1 X@LS,C1L2*F'paJ9@5#eTD#eUXk5dV-L[2`4X6`9Kr9E@M1@l&mZJ8li(X$*QS%6 $%Gk,VE#iMf,l((`NU(2q'VE[a&Dj!XpLq`9[r$Xp)rGRK9KmJr,he-0EP0C326R 1%bVT)U`25`i@+QIe9h`XhbdM$A3q9RJG'2bH4LbShm)hU*dV,@SA"ePK9IYHcQ' )q@4PRm#E'r"bmE(dh'RXc5ip)HTfI-0q0MLCqP*I`$GF1l'+lh-F+VQS[*&kc0H DZYV@Lch$"#-'3Bm)lRJ,F8(G8eCFr3&E!J@erLUV`C+$qM[,Vd`De*,KCr[pMi* kVA1#%fqLI64i&Ejc[4i8[)EcHGVi6AbmdrPqilIJjr"GB(Ik,!G@A-A(ficLIP* 6`Ar$0pSM48Je1FDV6b&KJeh*0D5&jKP2MBmPbPNi(jrFd9[*0E5$`i5HUXC5K+l %9leqFideB%-I%,B)S5I(UcR8j*X3"CCSa-3NeB[ihXlC6UB+#4XZ#Zii$8`+I4E IaG5(e&Y)Up8bAS)FRq%`KIH6@JSpM'qUAi3PT(I9qTMiRZ6!Zq%$5eL&&VJ$5r4 VL!p-B@PkI&,EHM&kI+a$5`hL3beP$9amV"2,%[2iZ!q,bZ160pI,b10MZA8@MXF (AK+,$qaKFAKm9"M,`H0l)3I`#KmeEAZ-`X*1&RR(pcS1LmhhS'%b[SFiX*`l2M# *"GcaIB3$li!2!'@4GRaIi-#bl2LqaB&Da[F$$Lbp$J@J2X!FI'!Sq)N2hX##k[M !!TC3adFGk0%KiZ-GHA0ma,!`1Mj'V0Q&Db,##4BrahFA"`hfiJ-EE$Y,4'r-dZI ihX@"2LamImV"$Lk*h-2"-*(!mF)!kJZI`%)!h0'qTcR!Ck!c[+XGp4CP[9h0Ar# "`CBb4B9jGP1qU0E,K52J!hGXNdj8p8mM'6lUdfUe8G@2V!QXIEb['Bm51%&[FC2 jL,'E@dA&NfifhpdFU!YmVq"JPGbS10UYjRXV"pEfaFGUZq!'2M$b0[0pR)-G2K- 94YT9L+1UHcJ1[LFi[-Kmm"+`@VkBq-mGjQ0GAeB3aXGk[#mf(eJ'4Z'MYPRY&aq e4#hMidej6hcFl4lc`32fQimhVMFIY8iX2YB2&PkNIAr&!5k'MbfU`%0m2q4`RrF j,MkNqG%LL(i%[P%(pMh926[lK(%(4pXh&M'Q#4I'(0Mh$$cXG1-@MVC[($*'%bl FF@$INpqBREhli+*ZZ2#bI*ZR"Pai+AcKEE1cepkjL"XU1'G(HTYQ'HI+jjiEkHf H(c9C0fRp@$*UXSl4cmP4NhA@`Z8dqDaZ1NVVVGSb5(kf2dVRS6*HhM@h3'YUXmC i9XP$i,e&([TrlL[bX*lKX0IbR&K4I!kBmI41ZB(6hQJX2F"TmT(KA6CSpT!!"Ki DTqR(0-2fc)3Y%jFFf*@)5)hY5S5PKddP3QfACb+!k9kqemliLNFN*RfCN!$8[#m 6XLaUMHKa8N&lejahj,f)Q$96Fcb+M0p,ABV3YMFM029Q"(L[j$EkJX'*'q,@XI( 3DQLSZJK!ac$MPQ6`90fV$FMpr&bSiaq0,02EEC[RFr`HYF2[YaP"Z8rQI2+`(6P U'qQ2jR8FZXHmVFPN0rECGf@`f)*0&CYRGE`q&Sq1f)bXirGBfVGjV(YLBGHFjLm eCEEYdrIBQ$ArVrMe2CL5r&bpkRX8X*1TZ-9[q8"9Drhm&Mp!i194fqD9(ApA'4& YCeJGVrZGD@)c[SlIJfp8V3&,2[kZqKjk*YlaHaKqcqcE0VScC2%*TV0JD0!Qhq@ qaLR3"epqdH#2%1E`2C`"$'AKq4Iq'$NEaPQhISi+TP2!cY3SlSjlR(rQBJ(hk(b 3!*rHS`1!Ihk2)T)IZBFXd["rY@qBkI&kKERVHa4HSf(UH[ipGM#)f"&`Ml@[[Qc aA4P&k0fM(BPqHSmGVl,6iV['lq%%B1lk(VZF6DEmcHHHB0`bK,KVL%VMV2r@EeI @@56J(RbM+**Rhj@4UVibIc"*E2%*jZkSB+C1!14d+b$9SDpVKTEl3p14Tfelq@F dRG`ph#DUmc%Y*PXG[p"LZZja9)[TZXG4,DEl(NHdQ1)ph!YD60Ylr%U,b6hX-eT -m4j(YCLfDra5LqQkac%YjZ"&A!4D6'F1ZkG(amF5(m@lTKIpD2kF(jT1&SKqSHR N%GmCS1N8aelfV`aZY&Rj[rRSVh&2G&'i!lSIA#IG"PZ1-5rTHU@c+0(lf[$&'BT lSQ[KHUemHI`cpcL1`('QA'$FrriHlT[ZKpf,!Bb'PfE[FHH8&lUbddAp(ia!,Y* 4dFFB3GFpMM+#VRXF4I,ZHaa"mZ)pMQP9EIIiP9D9Hj!!Cj!!XhL2SmMCGSeI)QI A2BjT93F[%Vp(3Bk4HqKT#Zdjc$hd+R,CMdZX5ifmjr1i!638IBr#i'4INFJMQYa $9R&T[mI#LDdr[SGlGUTjFY&!GmVRSTYUIZ)10-f'lCG9[M0B%1@PC('jb4BXPb0 V62mNAeJj##l)8YH6JqdZQ8l,SeRBUSG*rG!+km6+hLakRf`4GkkRdD1ZlT*&bU$ %ai@Sa`AGdV@NdaEAF,Qa"amA3MNZ10b3!+$Kmh%KY[MXp$`VRlK@#Z#%Gf%R@2M !#@E#BUNR[K(kL&kLA$-LGK9hc(d+@0JD4Uh&RUT3aS[%1&ic[d9m5Vq)1b921FH ZEH-PLVNP`iXm[6QH9Z6T`h&SNBFK3*9&R[iFVhiT6hbVHiNkLH10Vp@&5$kIi6# S9'V9e8NY[X&C0@3D6@JP[L%0laZV0icJ8k8P'j3(Rm3a*@EBdVk'DkB-[5*SmhR ,H[XUSkA5H@[bqlcZQT-ICjPLh[BRXrrbR[RhNErXZlH@5YIZprF1RM`lqp4Q3Xr %MX5HK@AKBZEMMH$jcV(h18re+IB-,$1&,X"HL"f&(8fH-CDR#MX11ail!FZFQSR B'ZcTj*PNH5l#ASaP`#*,)c""4pifm'lXD[*iGF'XYKAB99LQK6-CD41@'YK-RLf @"dD`(FXXTaZ`G+%c*BJ"3#[*XmIbh)6GLi9C#Xr81&CLY4NQ6kRP!EGX5@YX!RF UX1"+Ar,dXcc81h8f!(X+pP6X308f45jj"PZHSF)YXFa"C-)4%hpRBDGJTj0RYZ@ j&(X*PL%YFl(cX-`eBi,b![*S("!I`iHZ`#l'-U0a+IC+l&ABUH4CCRQZ`5iAAL5 "5*Vf`cNJbDXE[(MYRH!&G6!02"J[j%TZ0a,2drMa5)(JjV1#kkkrPraPj"'mN6a 5%HSA5mHVU'kE9I`$`L2UMI[GAb*4iMl[2QFbrfl$Ip[Xi92LI4iiDal2IR$l[q2 C!ffl$r([1aS[q9qQr2(h14$r6VZIi1*69j)RD(Pi3M#!HZ(p)PerqYAbrqZ"pN0 acXqHR,jKG!#&EPXD0eajU02)SV@96TV&cI*&lY,YF9*2AdJa[9Cc+(Z,`Qc,Lr& ,3rS!GjG(ACC&VDNA8ma'%U`F#Y[YPa2-k%50HVP[*NYJcFha6!QSMHYZ[@Zp($i c5K%Jec8RT$kfjE"#69[dSL6HkQVCLf@LUA&Fh-aQ@"BQVCIIZ,Cr5+T8Fq6FNI* `1iZDdBlrZ*ZH#E1`Nl8l,ck1$XmrRSkrDZL&8,q68`TmQfZmN!$%m[RfelFTfTq ITX"m#40H,''rVl!Y@MSQXU'j!M(p,,N#N!#qQBlAed*&4`C8`[cMqb*L@l6hH[C FQ52Ur)LpV9-*UpG-(i0d%Z3!RHJ11#G"(X`*cd%jd9NJpi*c'1"PD#N8,lDeb(9 4j!%m%Am3[h4m-hJ6Pi0ZSV2!(3r12PJVD"0BJ'a5G!#fRb$hh&Q`pS)lbc3$e&j X'UEMJCPbb%%dd6Q!*VSGRSR2JV-AR(R+*$#RJZ@e1Q'B"$NB*VS$KNQ3!)GK`R- `6(3@KVhJA(el'9U+`S[0&88HKK2a"h&*acI$-(%j'#Bk#m2ai1b$YF)`J38B*N8 ($2X*FXqGK@%[Z,0--c$XaDCK1"kB+BFF$"1GJf'Lff'Bq#`-Hm'CTmc#m1bHX@- `6))F$"2G!F-Nb--`i6NB*MS,`ej`VVkp$#e&iFAQLL)2`iRiJlLNijYKQ,JF$"1 GKH&iF2E"@Q'B`!)-Nk)$K[d%ZHI1`V!Ah&QQ'4MfBY-`(!r-P%-1KSR1`6$4l6" -I"D'[H$-8ak!i4jCULK-p8K6AH*88CiU#&5(*+T1NDSJ8h8,9Ge598kX+XT9Km@ P(RQT4f!U5%b(4+C1Q5N[0"@NTU,B9*5EHU5IS[M6)rpd#8"&#DJJ!Kf5J6U&S)) 8e#d'GFY"18'S+!NG&R"k**`H%DFJia`5FMUPR,bB8j!!FiU#6P(5kC&ALJ*,Mm6 5*E)8CCD#d(*)DZN8@`Tb5lIJdLfjj%5ASZab@#6TN8PkK*+#9(*),1Q85r+#58% b+BSQ4GQNd-a4E1I)0h4d0bJ8@K3kQa3+E3S&GEbSMqF9mQl&Yk$jGUUq"Gfh)$F @"FHmj0JYS49%Y%iC,5ZN0DmEPqCF,6P5T+XP342VDXR43,YD-U4i9dZ#*2(+a+F )35D*,CG-H%Hp0*!!Veb+1,&T6@(S9dYSLRqe*%K#86Dqp3RR,L33-'T*IS$GY@4 *%V0-I&FKqY3X%`ihbmEQLc6&cPS5T1KC-X&5Pc)IDfFmPB609l%aP5J,N!#T,1d SQ8U8JmT8QLaHTV*N3$1G*&Z`k8c09C[1d9+H$F@9!p,Q2+eSfT!!j`#NTZ+cZ*V +NJ(A!dQk(VJ&CP-*1V%fP5S$Z1NN4iUi$AV61CV`pd##BK&NN6L9*3[(5pU1$@, *e3('ITSX&2XjfS(B6j1$B6p*&S6p("N)ENb4VGh'2-f9fjLKT5b6TC5$hR5@9Z" 0CMN!Zhjd&R6p("R)E8T4H03@Z2A$1m(@6j5"fXB8KiUe$@BE-c5"E&0ijl0R!GE 2NB9AM`l2G"1GU5QAP$dbYZDB29CpK9$VkTXIYUBk)A1m-aPQaV9M[,e40XlRk*! !9aSeYCB859%Y%cpVTZC!,e(6mLr[bfqCm#k@e&jrU83(Lr!!l@bYa(5D6$Nf-,K m6EBNkQEUqHT-jFQ8D$T*4jfQXa@*EkCLI8"YVpFNJ@bYeLE1dPUVM8NbPCSN![N k2C!!TNMVmMAUCmP8D'1+M[TXc0A*PlTVFffYpTp5!CPke!,5("%-b(4)-b"2Mfa !QL0!3kCZMF(,dX0F[93GaHJPkDR(3hT$)P%"Qh5LGY9"ef%"HXR4)dk3!1B35-I cG1JBm5cG*A-%p-Pd60JJea'1i'IU+F9Z[F6,FK4iZP36,dP11)PRk+UH([Q%0$d #*@N1XbB5G4-R,mY4lZ5PkbUFBMr3NVL6e&aj,('-`Zc3LKCh@S$R3E%(AM#R%8m !)Ch0,2J1*q,G1K+P1(cf&3r+,Le2QHjSq1RYZaieV6GdC22jErCG@m5*PPGY&)U 2hE[V44XjHMVAXYlH`F(RRmq%0(&e%jALj5DNLB1EU!DqE@*5h0U%T'ZL-Fc5Da1 9T0+*L"4l5B5e[E62RK-"(ZlDPfpJaFQJ11fb3BEY'ZF"[QILNM`X%G(mDUfeR!K 0[CT(Xha[kJe6p-Q%T+L5#@QN45BS5B%5%@QkN`KYHc1Ip53#@SRIaM"ap9FJe-4 hL%FQ48ie-[%GFT&*NGH*6)+F3'6L1e'q-8H,HQ45C'@M4(L1YLGbG(+$4*i@HTU )cPGYZi58c("3X,!CQN8M%eR38%b5V0#4##q@5MH05Z6*P8UVpZ'(jUSSThDBq*c -BH,Ep3f6)5YX*-)l&Be%RN1&NT%m%Y%(Ud(QDVF6!F)lH3!CmM5!m%i@3)Cf%N" mRJ-3AU!!U45Y$)!-13,J4HG"c8Y4+&8[6@ZPHX'j3Zh!rN5#0ZMA#9U3!*r!)[# 6)iIlAR5K3RT3hdZ6VC!!JjJIMmc@6Kla#Fm$2Z%GH%q#(0ald3@dpp,de%F@kle JV`UF5CqkYUj&(,HQfC&Y*BDcbH-T1iPVh+PS2PXTaK6AZ)1R@XAK(1,BcY(r2[A (@Lc4h#rdMr0aRbG1hd2ZPi`V[B`P"HcpNR'Vf1kap-&QPZpiP0bNmX-FRLD1R3r mZ0$6(#UE@ASNRp*D"[DGN[IVp4AZFN'cR4k*@r)P&MqFhmbQMVa6@&XqpZAH[,G r[jRD&Z,6cDc"HbAM*[`CprZckL$cQ82Iiqhe0TAb$IiDKe(YK+e$3RGp"KpE9FT h$aZaK!Gmh2YlP-2Q1eHA0h%2[4IID"phhkFiR1RMIU)FGLAr)GTUXFc(rGd`2MD [*0rM(1l0im,R2S52E5cPZeml,mccq4l8FMKX)mQ9EeqS*hq,K'dIeM+9YLlpZ-M 0(2CCAITaBH'%9cGqA&5EC`keZ[(MpYdbAamIdhD6GSZ2I3r1emFfE9eTGiLkij6 jqRMdER`,I0aGfJV5eXG,@IBaS+dhLI[#I(eFYaiI'e-5pr@jqJMYH4)I@e6+GlH fac6e%4j66E+GTP6kcSmXe)'r(QL81SlAJ4mArZK#25AcIA#K2[bi'2H,eiFI0dL EE*Vk#&qKQVEiqe%``pC(q'HZ*X$Z$R'UDXM84rJbl49P0h9mA*KNkL0mP6E*[0& i!29UkL0mm4I`X8%RqIjk(Mp'DKm0kJ+mCpF*@aq[%TEFl12k#*pUmVLq2a$'[F4 `p`dFH[Zi4l3Tk*hfVYqIbpG[ac*m$rLiJF*eQqq*hIM),eqrlmlIljZ2iRZ2MqZ [c8C0[RklKB[[pA&pYEQRHHr!pi9re"h[)AK[hcY`81rdQ)ql6(R0H`Iq4MjUJAZ `SjTjlm"REX)((`'R(jkrhkHI`XHpL101jRiUqD3+eF60qrVmrCl8Qhl-lXe@4HC qUNGepR'lamUjq`9M[4re5(f$8qCq`6F+Ym!%q9CqFqjq`HekXdrjZ$fU$h1ri)l 2iK-HT2%*(Q0`)R,5,q$lQ[%RkRb`MhZ0DSLkNqq2`0Q5YSm,kLfqlH2HIJHBGV+ 2Up,Z(YraeiL#0j9rjH0@LdYqeqjh,cEQmH16fZ6dHmEcK'F%l"jVK5AJ!h(ic(Y (hUQY8rr*iUM4#Rq2KiAh6eUp2U6,QlK(YENV03,ZISR$&"rhT,C#IFTi*29XlK' jm6&m2c4FNHeFe8-qVYHr%N#0JarJE#prMbm+qm!Vm!Rq8HAcVEJ0(cRPZi8kL&4 ph$4aPAme(JchXMMp0['-Ic-H`#DTDqcHi-(6aVHNEVckZ&YFlNIfIY5cVBpc2SE [aclZC'fiqL&r[fq)GpUY5%qqKhFGk11qqNrc&,C#m3rkHfb$0hLVcFD%XjCrI"q I-ZifK)e6JeB(Ei&2H#[6KS9h&PGQ82G+'#*IL6BZ+S1AJcXq[jQ+$K%U+epXpkr aCNVEbI*dXMeV++qRf1i9TjVq!-6GKkq[MkZ(@bYK[RbIH"rjq[ZiNm!QTBeQ`8Z iKHB0XGhh8@2+0Q)j9CaEmiEBqjk&HbPY2-XlNIF-Rkm5,&$'ef2S&UEqBVY[)*F b[PkLYp4i'G[p1Ef0jHX$a&%d(XGfGm(2e&NqVPceq6`Ipa%`5)%cZQlJ*b90pLT ,e)Cq*p&[!KpUKNGhAbX4(cEhVYr-9VNUhrK9q,&XH4YHjq1Q28#FfE&CR3l[-$J GfhX&@mFUEE[+m`S1'Cb1lAN%A&6#4[P1S`i-6XIfDQPETHeKjCXcAkreer2f#Vp q$lQIVBrkc@b4Ue4he-dr(-+Rf0irr#*aXTbXcJIqDGb0lGd%cLREb(B''mmDr)l Y$H"-5Y[CNNq`bZ"hE1m0ZJFEfa)(cl6hH#Am4QQ,@qLmE'aVm$Zfjbkp"j[Gb[F DX0$L5[e[`Qf8YYQ&(m#A0*l&pYccF@'-LGXXc$"i8lm6V85*Ji$Im(jlMhI`4SS Dj(XGA-6JI@c2RGmLMXf#jAX6ZSc&TrSEU3QPlAQTErL$a[[BRZpG54akMRbRL0F Ch0Vr-&LSE11AQ2L*`DhpGi%T5TbD1RMPI2fK"5MHAlp6R0r(p[kPhS-YGZ8E*Yc 4r##fG`IF58PMNDm@hF6`JpMH')kUT)2"ekN6c3pLHem(Pe2DJ"IHrm3KIL$i)4L Pa#APfiM@B[L"h%0d,28QidrS$JCIpcm+*e$D(*JiH*jp[dAS@1TYaZGiAiYc`IZ *XlVA32&JJkreTm+TP1PHmm!2Lkre[`kI8kClKD89fAZ-q50mFKGJlA,UfI$Df0j 2#!2Bh&MLVJ)$,&lZ[d[Da'Gph%e`"3m[[k)D%icPQi9qjZ(PD186rBV[IYl9`m[ TUPIi(Hq"eQMIqir&rG!*LB2[fATpC!mqZ$rm$lbf1,G!R"`p3Ei9UN@,Pkq(f`@ NGj%2($&iZIpCm$)JIB!ikX2HBk5`!&iXheid#3m[2kbDrRXIYdFkVF@jkQ[*`CE $8$MZBqYl`+IaIGR(E8AImI"bJIL0h8`iV$UhpbMrAAaImA%28cm@,qY6m@2"+,l h``-p[(`[R&qCRMTEqT("brTedP$J&q#Ik+mHAMi'Pe@fi9G)R0lJCAdGV89*2k3 1@1h-eTr@@RKciQK0X2AhQ',3#H@l9RU"`F[pMdQMK0m"0E)KQBHA&G*DV)Dm5hU (aFYDD3bm!lL1CQ$`X[l0dNVJ0I+pkX[cH$Ri6`K!db$IQqIamR%d+D80RAQR""q Y[dEB)abCEr!#AXj%Te&k%rPZ%kjB[0`RIX`fd2!Ep%',Pj23m*9d@RJ'HN1*jrF 2`1(9Z)rl!,JFbHXlF0a"Z*Db4@0,a31Y(V!6M&#f#QaIEE&XiL)R`&'9l8Sd8"K QimD+hjKGM03PB*9h[he`"LAq+mGedS00A138DPMC)T,$a5[X[GmRhQ#hqjUR,C* Yh2IJR-TfcC`R,,4a6iQAQ&fE9%6GH[Hq(Crb1U[DaqE0hVfMD!E+G0D9iZ[fr5k rN6LVXki8cl$hqaal-bRMlCY9ccEZafJJbVDT'b3F2kNC(qfV#1FiC2@5Z&lqr`d !"8PMEfi0D@p38%-ZE@0`!*!4H$-*KJ#3$iB!!$q)!*!$&J#3"'PMEfj038063!# eQI#%YCR`K!!!!HB!N!B"&3#3""F@!*!)JE)4!!JF[-XKL%Vqkr)IQ(qRr&[Nla6 hDYcMFCFjq"YaTmHeLN[2GdpFcRaEjcXYAk0m21qMq8VPh6[[,ARVj-h+FeLHar* XRZHi20im2E`Aj5RJ6I0HR2Y9EqIFjhU,j8l,I9eZP$XeGilF20HCZF[QV*!!Frm F0q9-c,&GMVGcP-Pa@1aj14V(GSQp1qE4f25BR@-hL'NEFkrRVTMdQ%GLYiSj-,D qXmMT%0kG+6`p!r+B3c"H,b-CF*54$%p[fY"-D$T(Emh-i#$Rk@eK'$HR8'ZQ(!T cYqY-%A+HIQQ%K@(XR2`ZdLmbcpr'-b3U-8II58AYQIfMclTCrUa,aK5GkLJ8DZY dYLC!(J4+k5cqV!ZZX3#3!`d0$&*&384045j0B@028f0`!*!4KZB*KJ#3$Mi$!!" $(J#3!aErN!4849K8G(4iG!%!VZP",E@CpXm!!!'X!!!%5`#3!md!!!*C*YQfB3# 3"M&!%3!)(1ad#')JLFI%1Rb*Jij4$SQpPB0bK,62fc8T)G'Ij216P-l"P'KkQ)V "9!65Xe)GTD5H!!J3)B2Y3fARKLIIKp0[UTHYN!"1TZXCRhC&(mcFBpDR'HL$*'B bTRkDJEjBKM3rJcd9[(l15!U(i9GF#&#aYR)HIf+0dbT$lV2bl"JXUUC$EZHE"al 2iakBaArh`'Q21'8UXp'm)bLH6D%Jj*ZT4*peCGa0ec5-ImP4+,3"j!m%ZqTYqZ6 3G)IlBUBS06Yib'K"cmeeX!8+SJ#!)!1BM"JC-!+`$L,X(*!!!I2)5Sk5@mQapmK 4)jc-'!()lfAi9c`$q#LHiJRk%3`%F23LI'9'RJd))mKJ"$&X*HX$!2R!j-"86Di hP&T,(j5qZD143lS3BL2ThP2PI'XI5AP$NipTUQ[5Y8[4mDG"DGPqH44E5H18D(G GRYhHlZ5J4h+q)$f2NA("kX4KNAR[25[cBc!alGMBre3)MJ2G"UBhKAa3RC@#L!k YLdqqiJYGlkUJ`N*eRJ92AV,"NXVII@4++M3fa6*3F@STdf5#C'1L-A!6e&"Bmk- i@SYrMNqP%#KPLKKmkB3@RNJV6mT!k,10E!"'#$la2"5TmcHT!P5IN3-mIH58Q96 #$lKPhbr8+NLf&J("!%4ND4QlQ0dA*j@UqNA-l&mPQMPd'+DhCae+d4&89pQj2k, C$*%#4#&Sih`6FaYB&mlVIM,@B(82mSImU#!"I(BSTA4f0&K[0Bhpe#"`31l*&!Q GjeQd21Fj9$,cK*Z5-6*A$6f@S"H0)mXXp68BV-T,`8&6,QpI3ZUC1dK"1cN)G&H &59X*!0YIFKAPj&eMT@k&q-$'e8kVj0K(+E'e@DqffpAjf3A41$Y%i#mMa'&E0V( @dUZSC--2ZAjm2YUCDYGEa'#3!%!*lImdGq`IE-J"rMa-*q8HPC2dkekJ#P#K3!U 6KaS80)bpFKkS&H0D+KTFM!Makqek*cDEeIVmVlaVp`MSlqK9EiHF[1p`(jN120# 90cC%kk9BRkifTk[eqXJhZ,jECVAm"V`IMITMrqNXlklhKl[p$@hPqZ48LRmK)3Y MCQPdFfP[AfeKB`#3&JQ'!4B!&3+L!GB!N!-"!!!rL!#3"aB!N!1'!!!$([q3"!2 JYCR`K,@Cp[N!N!8"mK%!N!C#Q2r`rrJ!!-0!!!!3DBZi!!!: cfitsio-4.3.1/drvrgsiftp.h0000644000225700000360000000142313472024437015016 0ustar cagordonlhea#ifndef _GSIFTP_H #define _GSIFTP_H int gsiftp_init(void); int gsiftp_setoptions(int options); int gsiftp_getoptions(int *options); int gsiftp_getversion(int *version); int gsiftp_shutdown(void); int gsiftp_checkfile(char *urltype, char *infile, char *outfile); int gsiftp_open(char *filename, int rwmode, int *driverhandle); int gsiftp_create(char *filename, int *driverhandle); int gsiftp_truncate(int driverhandle, LONGLONG filesize); int gsiftp_size(int driverhandle, LONGLONG *filesize); int gsiftp_close(int driverhandle); int gsiftp_remove(char *filename); int gsiftp_flush(int driverhandle); int gsiftp_seek(int driverhandle, LONGLONG offset); int gsiftp_read (int driverhandle, void *buffer, long nbytes); int gsiftp_write(int driverhandle, void *buffer, long nbytes); #endif cfitsio-4.3.1/cookbook.f0000644000225700000360000007277614214470324014446 0ustar cagordonlhea program main C This is the FITSIO cookbook program that contains an annotated listing of C various computer programs that read and write files in FITS format C using the FITSIO subroutine interface. These examples are C working programs which users may adapt and modify for their own C purposes. This Cookbook serves as a companion to the FITSIO User's C Guide that provides more complete documentation on all the C available FITSIO subroutines. C Call each subroutine in turn: call writeimage call writeascii call writebintable call copyhdu call selectrows call readheader call readimage call readtable print * print *,"All the fitsio cookbook routines ran successfully." end C ************************************************************************* subroutine writeimage C Create a FITS primary array containing a 2-D image integer status,unit,blocksize,bitpix,naxis,naxes(2) integer i,j,group,fpixel,nelements,array(300,200) character filename*80 logical simple,extend C The STATUS parameter must be initialized before using FITSIO. A C positive value of STATUS is returned whenever a serious error occurs. C FITSIO uses an `inherited status' convention, which means that if a C subroutine is called with a positive input value of STATUS, then the C subroutine will exit immediately, preserving the status value. For C simplicity, this program only checks the status value at the end of C the program, but it is usually better practice to check the status C value more frequently. status=0 C Name of the FITS file to be created: filename='ATESTFILEZ.FITS' C Delete the file if it already exists, so we can then recreate it. C The deletefile subroutine is listed at the end of this file. call deletefile(filename,status) C Get an unused Logical Unit Number to use to open the FITS file. C This routine is not required; programmers can choose any unused C unit number to open the file. call ftgiou(unit,status) C Create the new empty FITS file. The blocksize parameter is a C historical artifact and the value is ignored by FITSIO. blocksize=1 call ftinit(unit,filename,blocksize,status) C Initialize parameters about the FITS image. C BITPIX = 16 means that the image pixels will consist of 16-bit C integers. The size of the image is given by the NAXES values. C The EXTEND = TRUE parameter indicates that the FITS file C may contain extensions following the primary array. simple=.true. bitpix=16 naxis=2 naxes(1)=300 naxes(2)=200 extend=.true. C Write the required header keywords to the file call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) C Initialize the values in the image with a linear ramp function do j=1,naxes(2) do i=1,naxes(1) array(i,j)=i - 1 +j - 1 end do end do C Write the array to the FITS file. C The last letter of the subroutine name defines the datatype of the C array argument; in this case the 'J' indicates that the array has an C integer*4 datatype. ('I' = I*2, 'E' = Real*4, 'D' = Real*8). C The 2D array is treated as a single 1-D array with NAXIS1 * NAXIS2 C total number of pixels. GROUP is seldom used parameter that should C almost always be set = 1. group=1 fpixel=1 nelements=naxes(1)*naxes(2) call ftpprj(unit,group,fpixel,nelements,array,status) C Write another optional keyword to the header C The keyword record will look like this in the FITS file: C C EXPOSURE= 1500 / Total Exposure Time C call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any errors, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine writeascii C Create an ASCII table containing 3 columns and 6 rows. For convenience, C the ASCII table extension is appended to the FITS image file created C previously by the WRITEIMAGE subroutine. integer status,unit,readwrite,blocksize,tfields,nrows,rowlen integer nspace,tbcol(3),diameter(6), colnum,frow,felem real density(6) character filename*40,extname*16 character*16 ttype(3),tform(3),tunit(3),name(6) data ttype/'Planet','Diameter','Density'/ data tform/'A8','I6','F4.2'/ data tunit/' ','km','g/cm'/ data name/'Mercury','Venus','Earth','Mars','Jupiter','Saturn'/ data diameter/4880,12112,12742,6800,143000,121000/ data density/5.1,5.3,5.52,3.94,1.33,0.69/ C The STATUS parameter must always be initialized. status=0 C Name of the FITS file to append the ASCII table to: filename='ATESTFILEZ.FITS' C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file with write access. C (readwrite = 0 would open the file with readonly access). readwrite=1 call ftopen(unit,filename,readwrite,blocksize,status) C FTCRHD creates a new empty FITS extension following the current C extension and moves to it. In this case, FITSIO was initially C positioned on the primary array when the FITS file was first opened, so C FTCRHD appends an empty extension and moves to it. All future FITSIO C calls then operate on the new extension (which will be an ASCII C table). call ftcrhd(unit,status) C define parameters for the ASCII table (see the above data statements) tfields=3 nrows=6 extname='PLANETS_ASCII' C FTGABC is a convenient subroutine for calculating the total width of C the table and the starting position of each column in an ASCII table. C Any number of blank spaces (including zero) may be inserted between C each column of the table, as specified by the NSPACE parameter. nspace=1 call ftgabc(tfields,tform,nspace,rowlen,tbcol,status) C FTPHTB writes all the required header keywords which define the C structure of the ASCII table. NROWS and TFIELDS give the number of C rows and columns in the table, and the TTYPE, TBCOL, TFORM, and TUNIT C arrays give the column name, starting position, format, and units, C respectively of each column. The values of the ROWLEN and TBCOL parameters C were previously calculated by the FTGABC routine. call ftphtb(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit, & extname,status) C Write names to the first column, diameters to 2nd col., and density to 3rd C FTPCLS writes the string values to the NAME column (column 1) of the C table. The FTPCLJ and FTPCLE routines write the diameter (integer) and C density (real) value to the 2nd and 3rd columns. The FITSIO routines C are column oriented, so it is usually easier to read or write data in a C table in a column by column order rather than row by row. frow=1 felem=1 colnum=1 call ftpcls(unit,colnum,frow,felem,nrows,name,status) colnum=2 call ftpclj(unit,colnum,frow,felem,nrows,diameter,status) colnum=3 call ftpcle(unit,colnum,frow,felem,nrows,density,status) C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine writebintable C This routine creates a FITS binary table, or BINTABLE, containing C 3 columns and 6 rows. This routine is nearly identical to the C previous WRITEASCII routine, except that the call to FTGABC is not C needed, and FTPHBN is called rather than FTPHTB to write the C required header keywords. integer status,unit,readwrite,blocksize,hdutype,tfields,nrows integer varidat,diameter(6), colnum,frow,felem real density(6) character filename*40,extname*16 character*16 ttype(3),tform(3),tunit(3),name(6) data ttype/'Planet','Diameter','Density'/ data tform/'8A','1J','1E'/ data tunit/' ','km','g/cm'/ data name/'Mercury','Venus','Earth','Mars','Jupiter','Saturn'/ data diameter/4880,12112,12742,6800,143000,121000/ data density/5.1,5.3,5.52,3.94,1.33,0.69/ C The STATUS parameter must always be initialized. status=0 C Name of the FITS file to append the ASCII table to: filename='ATESTFILEZ.FITS' C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file, with write access. readwrite=1 call ftopen(unit,filename,readwrite,blocksize,status) C Move to the last (2nd) HDU in the file (the ASCII table). call ftmahd(unit,2,hdutype,status) C Append/create a new empty HDU onto the end of the file and move to it. call ftcrhd(unit,status) C Define parameters for the binary table (see the above data statements) tfields=3 nrows=6 extname='PLANETS_BINARY' varidat=0 C FTPHBN writes all the required header keywords which define the C structure of the binary table. NROWS and TFIELDS gives the number of C rows and columns in the table, and the TTYPE, TFORM, and TUNIT arrays C give the column name, format, and units, respectively of each column. call ftphbn(unit,nrows,tfields,ttype,tform,tunit, & extname,varidat,status) C Write names to the first column, diameters to 2nd col., and density to 3rd C FTPCLS writes the string values to the NAME column (column 1) of the C table. The FTPCLJ and FTPCLE routines write the diameter (integer) and C density (real) value to the 2nd and 3rd columns. The FITSIO routines C are column oriented, so it is usually easier to read or write data in a C table in a column by column order rather than row by row. Note that C the identical subroutine calls are used to write to either ASCII or C binary FITS tables. frow=1 felem=1 colnum=1 call ftpcls(unit,colnum,frow,felem,nrows,name,status) colnum=2 call ftpclj(unit,colnum,frow,felem,nrows,diameter,status) colnum=3 call ftpcle(unit,colnum,frow,felem,nrows,density,status) C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine copyhdu C Copy the 1st and 3rd HDUs from the input file to a new FITS file integer status,inunit,outunit,readwrite,blocksize,morekeys,hdutype character infilename*40,outfilename*40 C The STATUS parameter must always be initialized. status=0 C Name of the FITS files: infilename='ATESTFILEZ.FITS' outfilename='BTESTFILEZ.FITS' C Delete the file if it already exists, so we can then recreate it C The deletefile subroutine is listed at the end of this file. call deletefile(outfilename,status) C Get unused Logical Unit Numbers to use to open the FITS files. call ftgiou(inunit,status) call ftgiou(outunit,status) C Open the input FITS file, with readonly access readwrite=0 call ftopen(inunit,infilename,readwrite,blocksize,status) C Create the new empty FITS file (value of blocksize is ignored) blocksize=1 call ftinit(outunit,outfilename,blocksize,status) C FTCOPY copies the current HDU from the input FITS file to the output C file. The MOREKEY parameter allows one to reserve space for additional C header keywords when the HDU is created. FITSIO will automatically C insert more header space if required, so programmers do not have to C reserve space ahead of time, although it is more efficient to do so if C it is known that more keywords will be appended to the header. morekeys=0 call ftcopy(inunit,outunit,morekeys,status) C Append/create a new empty extension on the end of the output file call ftcrhd(outunit,status) C Skip to the 3rd extension in the input file which in this case C is the binary table created by the previous WRITEBINARY routine. call ftmahd(inunit,3,hdutype,status) C FTCOPY now copies the binary table from the input FITS file C to the output file. call ftcopy(inunit,outunit,morekeys,status) C The FITS files must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. C Giving -1 for the value of the first argument causes all previously C allocated unit numbers to be released. call ftclos(inunit, status) call ftclos(outunit, status) call ftfiou(-1, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine selectrows C This routine copies selected rows from an input table into a new output C FITS table. In this example all the rows in the input table that have C a value of the DENSITY column less that 3.0 are copied to the output C table. This program illustrates several generally useful techniques, C including: C how to locate the end of a FITS file C how to create a table when the total number of rows in the table C is not known until the table is completed C how to efficiently copy entire rows from one table to another. integer status,inunit,outunit,readwrite,blocksize,hdutype integer nkeys,nspace,naxes(2),nfound,colnum,frow,felem integer noutrows,irow,temp(100),i real nullval,density(6) character infilename*40,outfilename*40,record*80 logical exact,anynulls C The STATUS parameter must always be initialized. status=0 C Names of the FITS files: infilename='ATESTFILEZ.FITS' outfilename='BTESTFILEZ.FITS' C Get unused Logical Unit Numbers to use to open the FITS files. call ftgiou(inunit,status) call ftgiou(outunit,status) C The input FITS file is opened with READONLY access, and the output C FITS file is opened with WRITE access. readwrite=0 call ftopen(inunit,infilename,readwrite,blocksize,status) readwrite=1 call ftopen(outunit,outfilename,readwrite,blocksize,status) C move to the 3rd HDU in the input file (a binary table in this case) call ftmahd(inunit,3,hdutype,status) C This do-loop illustrates how to move to the last extension in any FITS C file. The call to FTMRHD moves one extension at a time through the C FITS file until an `End-of-file' status value (= 107) is returned. do while (status .eq. 0) call ftmrhd(outunit,1,hdutype,status) end do C After locating the end of the FITS file, it is necessary to reset the C status value to zero and also clear the internal error message stack C in FITSIO. The previous `End-of-file' error will have produced C an unimportant message on the error stack which can be cleared with C the call to the FTCMSG routine (which has no arguments). if (status .eq. 107)then status=0 call ftcmsg end if C Create a new empty extension in the output file. call ftcrhd(outunit,status) C Find the number of keywords in the input table header. call ftghsp(inunit,nkeys,nspace,status) C This do-loop of calls to FTGREC and FTPREC copies all the keywords from C the input to the output FITS file. Notice that the specified number C of rows in the output table, as given by the NAXIS2 keyword, will be C incorrect. This value will be modified later after it is known how many C rows will be in the table, so it does not matter how many rows are specified C initially. do i=1,nkeys call ftgrec(inunit,i,record,status) call ftprec(outunit,record,status) end do C FTGKNJ is used to get the value of the NAXIS1 and NAXIS2 keywords, C which define the width of the table in bytes, and the number of C rows in the table. call ftgknj(inunit,'NAXIS',1,2,naxes,nfound,status) C FTGCNO gets the column number of the `DENSITY' column; the column C number is needed when reading the data in the column. The EXACT C parameter determines whether or not the match to the column names C will be case sensitive. exact=.false. call ftgcno(inunit,exact,'DENSITY',colnum,status) C FTGCVE reads all 6 rows of data in the `DENSITY' column. The number C of rows in the table is given by NAXES(2). Any null values in the C table will be returned with the corresponding value set to -99 C (= the value of NULLVAL). The ANYNULLS parameter will be set to TRUE C if any null values were found while reading the data values in the table. frow=1 felem=1 nullval=-99. call ftgcve(inunit,colnum,frow,felem,naxes(2),nullval, & density,anynulls,status) C If the density is less than 3.0, copy the row to the output table. C FTGTBB and FTPTBB are low-level routines to read and write, respectively, C a specified number of bytes in the table, starting at the specified C row number and beginning byte within the row. These routines do C not do any interpretation of the bytes, and simply pass them to or C from the FITS file without any modification. This is a faster C way of transferring large chunks of data from one FITS file to another, C than reading and then writing each column of data individually. C In this case an entire row of bytes (the row length is specified C by the naxes(1) parameter) is transferred. The datatype of the C buffer array (TEMP in this case) is immaterial so long as it is C declared large enough to hold the required number of bytes. noutrows=0 do irow=1,naxes(2) if (density(irow) .lt. 3.0)then noutrows=noutrows+1 call ftgtbb(inunit,irow,1,naxes(1),temp,status) call ftptbb(outunit,noutrows,1,naxes(1),temp,status) end if end do C Update the NAXIS2 keyword with the correct no. of rows in the output file. C After all the rows have been written to the output table, the C FTMKYJ routine is used to overwrite the NAXIS2 keyword value with C the correct number of rows. Specifying `\&' for the comment string C tells FITSIO to keep the current comment string in the keyword and C only modify the value. Because the total number of rows in the table C was unknown when the table was first created, any value (including 0) C could have been used for the initial NAXIS2 keyword value. call ftmkyj(outunit,'NAXIS2',noutrows,'&',status) C The FITS files must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(inunit, status) call ftclos(outunit, status) call ftfiou(-1, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine readheader C Print out all the header keywords in all extensions of a FITS file integer status,unit,readwrite,blocksize,nkeys,nspace,hdutype,i,j character filename*80,record*80 C The STATUS parameter must always be initialized. status=0 C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C name of FITS file filename='ATESTFILEZ.FITS' C open the FITS file, with read-only access. The returned BLOCKSIZE C parameter is obsolete and should be ignored. readwrite=0 call ftopen(unit,filename,readwrite,blocksize,status) j = 0 100 continue j = j + 1 print *,'Header listing for HDU', j C The FTGHSP subroutine returns the number of existing keywords in the C current header data unit (CHDU), not counting the required END keyword, call ftghsp(unit,nkeys,nspace,status) C Read each 80-character keyword record, and print it out. do i = 1, nkeys call ftgrec(unit,i,record,status) print *,record end do C Print out an END record, and a blank line to mark the end of the header. if (status .eq. 0)then print *,'END' print *,' ' end if C Try moving to the next extension in the FITS file, if it exists. C The FTMRHD subroutine attempts to move to the next HDU, as specified by C the second parameter. This subroutine moves by a relative number of C HDUs from the current HDU. The related FTMAHD routine may be used to C move to an absolute HDU number in the FITS file. If the end-of-file is C encountered when trying to move to the specified extension, then a C status = 107 is returned. call ftmrhd(unit,1,hdutype,status) if (status .eq. 0)then C success, so jump back and print out keywords in this extension go to 100 else if (status .eq. 107)then C hit end of file, so quit status=0 end if C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine readimage C Read a FITS image and determine the minimum and maximum pixel value. C Rather than reading the entire image in C at once (which could require a very large array), the image is read C in pieces, 100 pixels at a time. integer status,unit,readwrite,blocksize,naxes(2),nfound integer group,firstpix,nbuffer,npixels,i real datamin,datamax,nullval,buffer(100) logical anynull character filename*80 C The STATUS parameter must always be initialized. status=0 C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file previously created by WRITEIMAGE filename='ATESTFILEZ.FITS' readwrite=0 call ftopen(unit,filename,readwrite,blocksize,status) C Determine the size of the image. call ftgknj(unit,'NAXIS',1,2,naxes,nfound,status) C Check that it found both NAXIS1 and NAXIS2 keywords. if (nfound .ne. 2)then print *,'READIMAGE failed to read the NAXISn keywords.' return end if C Initialize variables npixels=naxes(1)*naxes(2) group=1 firstpix=1 nullval=-999 datamin=1.0E30 datamax=-1.0E30 do while (npixels .gt. 0) C read up to 100 pixels at a time nbuffer=min(100,npixels) call ftgpve(unit,group,firstpix,nbuffer,nullval, & buffer,anynull,status) C find the min and max values do i=1,nbuffer datamin=min(datamin,buffer(i)) datamax=max(datamax,buffer(i)) end do C increment pointers and loop back to read the next group of pixels npixels=npixels-nbuffer firstpix=firstpix+nbuffer end do print * print *,'Min and max image pixels = ',datamin,datamax C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine readtable C Read and print data values from an ASCII or binary table C This example reads and prints out all the data in the ASCII and C the binary tables that were previously created by WRITEASCII and C WRITEBINTABLE. Note that the exact same FITSIO routines are C used to read both types of tables. integer status,unit,readwrite,blocksize,hdutype,ntable integer felem,nelems,nullj,diameter,nfound,irow,colnum real nulle,density(1) character filename*40,nullstr*1,name*8,ttype(3)*10 logical anynull C The STATUS parameter must always be initialized. status=0 C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file previously created by WRITEIMAGE filename='ATESTFILEZ.FITS' readwrite=0 call ftopen(unit,filename,readwrite,blocksize,status) C Loop twice, first reading the ASCII table, then the binary table do ntable=2,3 C Move to the next extension call ftmahd(unit,ntable,hdutype,status) print *,' ' if (hdutype .eq. 1)then print *,'Reading ASCII table in HDU ',ntable else if (hdutype .eq. 2)then print *,'Reading binary table in HDU ',ntable end if C Read the TTYPEn keywords, which give the names of the columns call ftgkns(unit,'TTYPE',1,3,ttype,nfound,status) write(*,2000)ttype 2000 format(2x,"Row ",3a10) C Read the data, one row at a time, and print them out felem=1 nelems=1 nullstr=' ' nullj=0 nulle=0. do irow=1,6 C FTGCVS reads the NAMES from the first column of the table. colnum=1 call ftgcvs(unit,colnum,irow,felem,nelems,nullstr,name, & anynull,status) C FTGCVJ reads the DIAMETER values from the second column. colnum=2 call ftgcvj(unit,colnum,irow,felem,nelems,nullj,diameter, & anynull,status) C FTGCVE reads the DENSITY values from the third column. colnum=3 call ftgcve(unit,colnum,irow,felem,nelems,nulle,density, & anynull,status) write(*,2001)irow,name,diameter,density 2001 format(i5,a10,i10,f10.2) end do end do C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine printerror(status) C This subroutine prints out the descriptive text corresponding to the C error status value and prints out the contents of the internal C error message stack generated by FITSIO whenever an error occurs. integer status character errtext*30,errmessage*80 C Check if status is OK (no error); if so, simply return if (status .le. 0)return C The FTGERR subroutine returns a descriptive 30-character text string that C corresponds to the integer error status number. A complete list of all C the error numbers can be found in the back of the FITSIO User's Guide. call ftgerr(status,errtext) print *,'FITSIO Error Status =',status,': ',errtext C FITSIO usually generates an internal stack of error messages whenever C an error occurs. These messages provide much more information on the C cause of the problem than can be provided by the single integer error C status value. The FTGMSG subroutine retrieves the oldest message from C the stack and shifts any remaining messages on the stack down one C position. FTGMSG is called repeatedly until a blank message is C returned, which indicates that the stack is empty. Each error message C may be up to 80 characters in length. Another subroutine, called C FTCMSG, is available to simply clear the whole error message stack in C cases where one is not interested in the contents. call ftgmsg(errmessage) do while (errmessage .ne. ' ') print *,errmessage call ftgmsg(errmessage) end do end C ************************************************************************* subroutine deletefile(filename,status) C A simple little routine to delete a FITS file integer status,unit,blocksize character*(*) filename C Simply return if status is greater than zero if (status .gt. 0)return C Get an unused Logical Unit Number to use to open the FITS file call ftgiou(unit,status) C Try to open the file, to see if it exists call ftopen(unit,filename,1,blocksize,status) if (status .eq. 0)then C file was opened; so now delete it call ftdelt(unit,status) else if (status .eq. 103)then C file doesn't exist, so just reset status to zero and clear errors status=0 call ftcmsg else C there was some other error opening the file; delete the file anyway status=0 call ftcmsg call ftdelt(unit,status) end if C Free the unit number for later reuse call ftfiou(unit, status) end cfitsio-4.3.1/edithdu.c0000644000225700000360000007772713640736632014275 0ustar cagordonlhea/* This file, edithdu.c, contains the FITSIO routines related to */ /* copying, inserting, or deleting HDUs in a FITS file */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffcopy(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int morekeys, /* I - reserve space in output header */ int *status) /* IO - error status */ /* copy the CHDU from infptr to the CHDU of outfptr. This will also allocate space in the output header for MOREKY keywords */ { int nspace; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); if (ffcphd(infptr, outfptr, status) > 0) /* copy the header keywords */ return(*status); if (morekeys > 0) { ffhdef(outfptr, morekeys, status); /* reserve space for more keywords */ } else { if (ffghsp(infptr, NULL, &nspace, status) > 0) /* get existing space */ return(*status); if (nspace > 0) { ffhdef(outfptr, nspace, status); /* preserve same amount of space */ if (nspace >= 35) { /* There is at least 1 full empty FITS block in the header. */ /* Physically write the END keyword at the beginning of the */ /* last block to preserve this extra space now rather than */ /* later. This is needed by the stream: driver which cannot */ /* seek back to the header to write the END keyword later. */ ffwend(outfptr, status); } } } ffcpdt(infptr, outfptr, status); /* now copy the data unit */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcpfl(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int previous, /* I - copy any previous HDUs? */ int current, /* I - copy the current HDU? */ int following, /* I - copy any following HDUs? */ int *status) /* IO - error status */ /* copy all or part of the input file to the output file. */ { int hdunum, ii; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); ffghdn(infptr, &hdunum); if (previous) { /* copy any previous HDUs */ for (ii=1; ii < hdunum; ii++) { ffmahd(infptr, ii, NULL, status); ffcopy(infptr, outfptr, 0, status); } } if (current && (*status <= 0) ) { /* copy current HDU */ ffmahd(infptr, hdunum, NULL, status); ffcopy(infptr, outfptr, 0, status); } if (following && (*status <= 0) ) { /* copy any remaining HDUs */ ii = hdunum + 1; while (1) { if (ffmahd(infptr, ii, NULL, status) ) { /* reset expected end of file status */ if (*status == END_OF_FILE) *status = 0; break; } if (ffcopy(infptr, outfptr, 0, status)) break; /* quit on unexpected error */ ii++; } } ffmahd(infptr, hdunum, NULL, status); /* restore initial position */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcphd(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int *status) /* IO - error status */ /* copy the header keywords from infptr to outfptr. */ { int nkeys, ii, inPrim = 0, outPrim = 0; long naxis, naxes[1]; char *card, comm[FLEN_COMMENT]; char *tmpbuff; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); /* set the input pointer to the correct HDU */ if (infptr->HDUposition != (infptr->Fptr)->curhdu) ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); if (ffghsp(infptr, &nkeys, NULL, status) > 0) /* get no. of keywords */ return(*status); /* create a memory buffer to hold the header records */ tmpbuff = (char*) malloc(nkeys*FLEN_CARD*sizeof(char)); if (!tmpbuff) return(*status = MEMORY_ALLOCATION); /* read all of the header records in the input HDU */ for (ii = 0; ii < nkeys; ii++) ffgrec(infptr, ii+1, tmpbuff + (ii * FLEN_CARD), status); if (infptr->HDUposition == 0) /* set flag if this is the Primary HDU */ inPrim = 1; /* if input is an image hdu, get the number of axes */ naxis = -1; /* negative if HDU is a table */ if ((infptr->Fptr)->hdutype == IMAGE_HDU) ffgkyj(infptr, "NAXIS", &naxis, NULL, status); /* set the output pointer to the correct HDU */ if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); /* check if output header is empty; if not create new empty HDU */ if ((outfptr->Fptr)->headend != (outfptr->Fptr)->headstart[(outfptr->Fptr)->curhdu] ) ffcrhd(outfptr, status); if (outfptr->HDUposition == 0) { if (naxis < 0) { /* the input HDU is a table, so we have to create */ /* a dummy Primary array before copying it to the output */ ffcrim(outfptr, 8, 0, naxes, status); ffcrhd(outfptr, status); /* create new empty HDU */ } else { /* set flag that this is the Primary HDU */ outPrim = 1; } } if (*status > 0) /* check for errors before proceeding */ { free(tmpbuff); return(*status); } if ( inPrim == 1 && outPrim == 0 ) { /* copying from primary array to image extension */ strcpy(comm, "IMAGE extension"); ffpkys(outfptr, "XTENSION", "IMAGE", comm, status); /* copy BITPIX through NAXISn keywords */ for (ii = 1; ii < 3 + naxis; ii++) { card = tmpbuff + (ii * FLEN_CARD); ffprec(outfptr, card, status); } strcpy(comm, "number of random group parameters"); ffpkyj(outfptr, "PCOUNT", 0, comm, status); strcpy(comm, "number of random groups"); ffpkyj(outfptr, "GCOUNT", 1, comm, status); /* copy remaining keywords, excluding EXTEND, and reference COMMENT keywords */ for (ii = 3 + naxis ; ii < nkeys; ii++) { card = tmpbuff+(ii * FLEN_CARD); if (FSTRNCMP(card, "EXTEND ", 8) && FSTRNCMP(card, "COMMENT FITS (Flexible Image Transport System) format is", 58) && FSTRNCMP(card, "COMMENT and Astrophysics', volume 376, page 3", 47) ) { ffprec(outfptr, card, status); } } } else if ( inPrim == 0 && outPrim == 1 ) { /* copying between image extension and primary array */ strcpy(comm, "file does conform to FITS standard"); ffpkyl(outfptr, "SIMPLE", TRUE, comm, status); /* copy BITPIX through NAXISn keywords */ for (ii = 1; ii < 3 + naxis; ii++) { card = tmpbuff + (ii * FLEN_CARD); ffprec(outfptr, card, status); } /* add the EXTEND keyword */ strcpy(comm, "FITS dataset may contain extensions"); ffpkyl(outfptr, "EXTEND", TRUE, comm, status); /* write standard block of self-documentating comments */ ffprec(outfptr, "COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy", status); ffprec(outfptr, "COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H", status); /* copy remaining keywords, excluding pcount, gcount */ for (ii = 3 + naxis; ii < nkeys; ii++) { card = tmpbuff+(ii * FLEN_CARD); if (FSTRNCMP(card, "PCOUNT ", 8) && FSTRNCMP(card, "GCOUNT ", 8)) { ffprec(outfptr, card, status); } } } else { /* input and output HDUs are same type; simply copy all keywords */ for (ii = 0; ii < nkeys; ii++) { card = tmpbuff+(ii * FLEN_CARD); ffprec(outfptr, card, status); } } free(tmpbuff); return(*status); } /*--------------------------------------------------------------------------*/ int ffcpht(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ LONGLONG firstrow, /* I - number of first row to copy (1 based) */ LONGLONG nrows, /* I - number of rows to copy */ int *status) /* IO - error status */ /* Copy the table structure from an existing table HDU, but only copy a limited row range. All header keywords from the input table are copied directly, but NAXSI2 and PCOUNT are set to their correct values. */ { if (*status > 0) return(*status); /* Copy the header only */ ffcphd(infptr, outfptr, status); /* Note that we now have a copied header that describes the table, and that is the current header, but the original number of table rows and heap area sizes are still there. */ /* Zero out the size-related keywords */ if (! *status ) { ffukyj(outfptr,"NAXIS2",0,0,status); /* NAXIS2 = 0 */ ffukyj(outfptr,"PCOUNT",0,0,status); /* PCOUNT = 0 */ /* Update the internal structure variables within CFITSIO now that we have a valid table header */ ffrdef(outfptr,status); } /* OK now that we have a pristine HDU, copy the requested rows */ if (! *status && nrows > 0) { ffcprw(infptr, outfptr, firstrow, nrows, status); } return (*status); } /*--------------------------------------------------------------------------*/ int ffcpdt(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int *status) /* IO - error status */ { /* copy the data unit from the CHDU of infptr to the CHDU of outfptr. This will overwrite any data already in the outfptr CHDU. */ long nb, ii; LONGLONG indatastart, indataend, outdatastart; char buffer[2880]; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); ffghadll(infptr, NULL, &indatastart, &indataend, status); ffghadll(outfptr, NULL, &outdatastart, NULL, status); /* Calculate the number of blocks to be copied */ nb = (long) ((indataend - indatastart) / 2880); if (nb > 0) { if (infptr->Fptr == outfptr->Fptr) { /* copying between 2 HDUs in the SAME file */ for (ii = 0; ii < nb; ii++) { ffmbyt(infptr, indatastart, REPORT_EOF, status); ffgbyt(infptr, 2880L, buffer, status); /* read input block */ ffmbyt(outfptr, outdatastart, IGNORE_EOF, status); ffpbyt(outfptr, 2880L, buffer, status); /* write output block */ indatastart += 2880; /* move address */ outdatastart += 2880; /* move address */ } } else { /* copying between HDUs in separate files */ /* move to the initial copy position in each of the files */ ffmbyt(infptr, indatastart, REPORT_EOF, status); ffmbyt(outfptr, outdatastart, IGNORE_EOF, status); for (ii = 0; ii < nb; ii++) { ffgbyt(infptr, 2880L, buffer, status); /* read input block */ ffpbyt(outfptr, 2880L, buffer, status); /* write output block */ } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffwrhdu(fitsfile *infptr, /* I - FITS file pointer to input file */ FILE *outstream, /* I - stream to write HDU to */ int *status) /* IO - error status */ { /* write the data unit from the CHDU of infptr to the output file stream */ long nb, ii; LONGLONG hdustart, hduend; char buffer[2880]; if (*status > 0) return(*status); ffghadll(infptr, &hdustart, NULL, &hduend, status); nb = (long) ((hduend - hdustart) / 2880); /* number of blocks to copy */ if (nb > 0) { /* move to the start of the HDU */ ffmbyt(infptr, hdustart, REPORT_EOF, status); for (ii = 0; ii < nb; ii++) { ffgbyt(infptr, 2880L, buffer, status); /* read input block */ fwrite(buffer, 1, 2880, outstream ); /* write to output stream */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffiimg(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ long *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* insert an IMAGE extension following the current HDU */ { LONGLONG tnaxes[99]; int ii; if (*status > 0) return(*status); if (naxis > 99) { ffpmsg("NAXIS value is too large (>99) (ffiimg)"); return(*status = 212); } for (ii = 0; (ii < naxis); ii++) tnaxes[ii] = naxes[ii]; ffiimgll(fptr, bitpix, naxis, tnaxes, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffiimgll(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ LONGLONG *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* insert an IMAGE extension following the current HDU */ { int bytlen, nexthdu, maxhdu, ii, onaxis; long nblocks; LONGLONG npixels, newstart, datasize; char errmsg[FLEN_ERRMSG], card[FLEN_CARD], naxiskey[FLEN_KEYWORD]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); maxhdu = (fptr->Fptr)->maxhdu; if (*status != PREPEND_PRIMARY) { /* if the current header is completely empty ... */ if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) /* or, if we are at the end of the file, ... */ || ( (((fptr->Fptr)->curhdu) == maxhdu ) && ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) { /* then simply append new image extension */ ffcrimll(fptr, bitpix, naxis, naxes, status); return(*status); } } if (bitpix == 8) bytlen = 1; else if (bitpix == 16) bytlen = 2; else if (bitpix == 32 || bitpix == -32) bytlen = 4; else if (bitpix == 64 || bitpix == -64) bytlen = 8; else { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for BITPIX keyword: %d", bitpix); ffpmsg(errmsg); return(*status = BAD_BITPIX); /* illegal bitpix value */ } if (naxis < 0 || naxis > 999) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for NAXIS keyword: %d", naxis); ffpmsg(errmsg); return(*status = BAD_NAXIS); } for (ii = 0; ii < naxis; ii++) { if (naxes[ii] < 0) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for NAXIS%d keyword: %ld", ii + 1, (long) naxes[ii]); ffpmsg(errmsg); return(*status = BAD_NAXES); } } /* calculate number of pixels in the image */ if (naxis == 0) npixels = 0; else npixels = naxes[0]; for (ii = 1; ii < naxis; ii++) npixels = npixels * naxes[ii]; datasize = npixels * bytlen; /* size of image in bytes */ nblocks = (long) (((datasize + 2879) / 2880) + 1); /* +1 for the header */ if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ { /* close the CHDU */ ffrdef(fptr, status); /* scan header to redefine structure */ ffpdfl(fptr, status); /* insure correct data file values */ } else return(*status = READONLY_FILE); if (*status == PREPEND_PRIMARY) { /* inserting a new primary array; the current primary */ /* array must be transformed into an image extension. */ *status = 0; ffmahd(fptr, 1, NULL, status); /* move to the primary array */ ffgidm(fptr, &onaxis, status); if (onaxis > 0) ffkeyn("NAXIS",onaxis, naxiskey, status); else strcpy(naxiskey, "NAXIS"); ffgcrd(fptr, naxiskey, card, status); /* read last NAXIS keyword */ ffikyj(fptr, "PCOUNT", 0, "required keyword", status); /* add PCOUNT and */ ffikyj(fptr, "GCOUNT", 1, "required keyword", status); /* GCOUNT keywords */ if (*status > 0) return(*status); if (ffdkey(fptr, "EXTEND", status) ) /* delete the EXTEND keyword */ *status = 0; /* redefine internal structure for this HDU */ ffrdef(fptr, status); /* insert space for the primary array */ if (ffiblk(fptr, nblocks, -1, status) > 0) /* insert the blocks */ return(*status); nexthdu = 0; /* number of the new hdu */ newstart = 0; /* starting addr of HDU */ } else { nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ (fptr->Fptr)->hdutype = IMAGE_HDU; /* so that correct fill value is used */ /* ffiblk also increments headstart for all following HDUs */ if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ return(*status); } ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ if (nexthdu == 0) (fptr->Fptr)->headstart[1] = nblocks * 2880; /* start of the old Primary array */ (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ /* set default parameters for this new empty HDU */ (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + 2880; (fptr->Fptr)->hdutype = IMAGE_HDU; /* might need to be reset... */ /* write the required header keywords */ ffphprll(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status); /* redefine internal structure for this HDU */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffitab(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of row in the table */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ long *tbcol, /* I - byte offset in row to each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnmx, /* I - value of EXTNAME keyword, if any */ int *status) /* IO - error status */ /* insert an ASCII table extension following the current HDU */ { int nexthdu, maxhdu, ii, nunit, nhead, ncols, gotmem = 0; long nblocks, rowlen; LONGLONG datasize, newstart; char errmsg[FLEN_ERRMSG], extnm[FLEN_VALUE]; if (*status > 0) return(*status); extnm[0] = '\0'; if (extnmx) strncat(extnm, extnmx, FLEN_VALUE-1); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); maxhdu = (fptr->Fptr)->maxhdu; /* if the current header is completely empty ... */ if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) /* or, if we are at the end of the file, ... */ || ( (((fptr->Fptr)->curhdu) == maxhdu ) && ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) { /* then simply append new image extension */ ffcrtb(fptr, ASCII_TBL, naxis2, tfields, ttype, tform, tunit, extnm, status); return(*status); } if (naxis1 < 0) return(*status = NEG_WIDTH); else if (naxis2 < 0) return(*status = NEG_ROWS); else if (tfields < 0 || tfields > 999) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for TFIELDS keyword: %d", tfields); ffpmsg(errmsg); return(*status = BAD_TFIELDS); } /* count number of optional TUNIT keywords to be written */ nunit = 0; for (ii = 0; ii < tfields; ii++) { if (tunit && *tunit && *tunit[ii]) nunit++; } if (*extnm) nunit++; /* add one for the EXTNAME keyword */ rowlen = (long) naxis1; if (!tbcol || !tbcol[0] || (!naxis1 && tfields)) /* spacing not defined? */ { /* allocate mem for tbcol; malloc may have problems allocating small */ /* arrays, so allocate at least 20 bytes */ ncols = maxvalue(5, tfields); tbcol = (long *) calloc(ncols, sizeof(long)); if (tbcol) { gotmem = 1; /* calculate width of a row and starting position of each column. */ /* Each column will be separated by 1 blank space */ ffgabc(tfields, tform, 1, &rowlen, tbcol, status); } } nhead = (9 + (3 * tfields) + nunit + 35) / 36; /* no. of header blocks */ datasize = (LONGLONG)rowlen * naxis2; /* size of table in bytes */ nblocks = (long) (((datasize + 2879) / 2880) + nhead); /* size of HDU */ if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ { /* close the CHDU */ ffrdef(fptr, status); /* scan header to redefine structure */ ffpdfl(fptr, status); /* insure correct data file values */ } else return(*status = READONLY_FILE); nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ (fptr->Fptr)->hdutype = ASCII_TBL; /* so that correct fill value is used */ /* ffiblk also increments headstart for all following HDUs */ if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ { if (gotmem) free(tbcol); return(*status); } ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ /* set default parameters for this new empty HDU */ (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + (nhead * 2880); (fptr->Fptr)->hdutype = ASCII_TBL; /* might need to be reset... */ /* write the required header keywords */ ffphtb(fptr, rowlen, naxis2, tfields, ttype, tbcol, tform, tunit, extnm, status); if (gotmem) free(tbcol); /* redefine internal structure for this HDU */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffibin(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnmx, /* I - value of EXTNAME keyword, if any */ LONGLONG pcount, /* I - size of special data area (heap) */ int *status) /* IO - error status */ /* insert a Binary table extension following the current HDU */ { int nexthdu, maxhdu, ii, nunit, nhead, datacode; LONGLONG naxis1; long nblocks, repeat, width; LONGLONG datasize, newstart; char errmsg[FLEN_ERRMSG], extnm[FLEN_VALUE]; if (*status > 0) return(*status); extnm[0] = '\0'; if (extnmx) strncat(extnm, extnmx, FLEN_VALUE-1); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); maxhdu = (fptr->Fptr)->maxhdu; /* if the current header is completely empty ... */ if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) /* or, if we are at the end of the file, ... */ || ( (((fptr->Fptr)->curhdu) == maxhdu ) && ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) { /* then simply append new image extension */ ffcrtb(fptr, BINARY_TBL, naxis2, tfields, ttype, tform, tunit, extnm, status); return(*status); } if (naxis2 < 0) return(*status = NEG_ROWS); else if (tfields < 0 || tfields > 999) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for TFIELDS keyword: %d", tfields); ffpmsg(errmsg); return(*status = BAD_TFIELDS); } /* count number of optional TUNIT keywords to be written */ nunit = 0; for (ii = 0; ii < tfields; ii++) { if (tunit && *tunit && *tunit[ii]) nunit++; } if (*extnm) nunit++; /* add one for the EXTNAME keyword */ nhead = (9 + (2 * tfields) + nunit + 35) / 36; /* no. of header blocks */ /* calculate total width of the table */ naxis1 = 0; for (ii = 0; ii < tfields; ii++) { ffbnfm(tform[ii], &datacode, &repeat, &width, status); if (datacode == TBIT) naxis1 = naxis1 + ((repeat + 7) / 8); else if (datacode == TSTRING) naxis1 += repeat; else naxis1 = naxis1 + (repeat * width); } datasize = ((LONGLONG)naxis1 * naxis2) + pcount; /* size of table in bytes */ nblocks = (long) ((datasize + 2879) / 2880) + nhead; /* size of HDU */ if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ { /* close the CHDU */ ffrdef(fptr, status); /* scan header to redefine structure */ ffpdfl(fptr, status); /* insure correct data file values */ } else return(*status = READONLY_FILE); nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ (fptr->Fptr)->hdutype = BINARY_TBL; /* so that correct fill value is used */ /* ffiblk also increments headstart for all following HDUs */ if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ return(*status); ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ /* set default parameters for this new empty HDU */ (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + (nhead * 2880); (fptr->Fptr)->hdutype = BINARY_TBL; /* might need to be reset... */ /* write the required header keywords. This will write PCOUNT = 0 */ /* so that the variable length data will be written at the right place */ ffphbn(fptr, naxis2, tfields, ttype, tform, tunit, extnm, pcount, status); /* redefine internal structure for this HDU (with PCOUNT = 0) */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdhdu(fitsfile *fptr, /* I - FITS file pointer */ int *hdutype, /* O - type of the new CHDU after deletion */ int *status) /* IO - error status */ /* Delete the CHDU. If the CHDU is the primary array, then replace the HDU with an empty primary array with no data. Return the type of the new CHDU after the old CHDU is deleted. */ { int tmptype = 0; long nblocks, ii, naxes[1]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->curhdu == 0) /* replace primary array with null image */ { /* ignore any existing keywords */ (fptr->Fptr)->headend = 0; (fptr->Fptr)->nextkey = 0; /* write default primary array header */ ffphpr(fptr,1,8,0,naxes,0,1,1,status); /* calc number of blocks to delete (leave just 1 block) */ nblocks = (long) (( (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1] - 2880 ) / 2880); /* ffdblk also updates the starting address of all following HDUs */ if (nblocks > 0) { if (ffdblk(fptr, nblocks, status) > 0) /* delete the HDU */ return(*status); } /* this might not be necessary, but is doesn't hurt */ (fptr->Fptr)->datastart = DATA_UNDEFINED; ffrdef(fptr, status); /* reinitialize the primary array */ } else { /* calc number of blocks to delete */ nblocks = (long) (( (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1] - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) / 2880); /* ffdblk also updates the starting address of all following HDUs */ if (ffdblk(fptr, nblocks, status) > 0) /* delete the HDU */ return(*status); /* delete the CHDU from the list of HDUs */ for (ii = (fptr->Fptr)->curhdu + 1; ii <= (fptr->Fptr)->maxhdu; ii++) (fptr->Fptr)->headstart[ii] = (fptr->Fptr)->headstart[ii + 1]; (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] = 0; ((fptr->Fptr)->maxhdu)--; /* decrement the known number of HDUs */ if (ffrhdu(fptr, &tmptype, status) > 0) /* initialize next HDU */ { /* failed (end of file?), so move back one HDU */ *status = 0; ffcmsg(); /* clear extraneous error messages */ ffgext(fptr, ((fptr->Fptr)->curhdu) - 1, &tmptype, status); } } if (hdutype) *hdutype = tmptype; return(*status); } cfitsio-4.3.1/putcoll.c0000644000225700000360000003315513472024437014310 0ustar cagordonlhea/* This file, putcoll.c, contains routines that write data elements to */ /* a FITS image or table, with logical datatype. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffpcll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ char *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of logical values to a column in the current FITS HDU. */ { int tcode, maxelem, hdutype; long twidth, incre; LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull; double scale, zero; char tform[20], ctrue = 'T', cfalse = 'F'; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ if (*status > 0) /* inherit input status value if > 0 */ return(*status); /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); if (tcode != TLOGICAL) return(*status = NOT_LOGICAL_COL); /*---------------------------------------------------------------------*/ /* Now write the logical values one at a time to the FITS column. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to write */ next = 0; /* next element in array to be written */ rownum = 0; /* row number, relative to firstrow */ while (remain) { wrtptr = startpos + (rowlen * rownum) + (elemnum * incre); ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */ if (array[next]) ffpbyt(fptr, 1, &ctrue, status); else ffpbyt(fptr, 1, &cfalse, status); if (*status > 0) /* test for error during previous write operation */ { snprintf(message,FLEN_ERRMSG, "Error writing element %.0f of input array of logicals (ffpcll).", (double) (next+1)); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain--; if (remain) { next++; elemnum++; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpcnl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ char *array, /* I - array of values to write */ char nulvalue, /* I - array flagging undefined pixels if true */ int *status) /* IO - error status */ /* Write an array of elements to the specified column of a table. Any input pixels flagged as null will be replaced by the appropriate null value in the output FITS file. */ { tcolumn *colptr; LONGLONG ngood = 0, nbad = 0, ii; LONGLONG repeat, first, fstelm, fstrow; int tcode; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode > 0) repeat = colptr->trepeat; /* repeat count for this column */ else repeat = firstelem -1 + nelem; /* variable length arrays */ /* first write the whole input vector, then go back and fill in the nulls */ if (ffpcll(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) return(*status); /* absolute element number in the column */ first = (firstrow - 1) * repeat + firstelem; for (ii = 0; ii < nelem; ii++) { if (array[ii] != nulvalue) /* is this a good pixel? */ { if (nbad) /* write previous string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0) return(*status); nbad=0; } ngood = ngood +1; /* the consecutive number of good pixels */ } else { if (ngood) /* write previous string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ /* good values have already been written if (ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status) > 0) return(*status); */ ngood=0; } nbad = nbad +1; /* the consecutive number of bad pixels */ } } /* finished loop; now just write the last set of pixels */ if (ngood) /* write last string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ /* these have already been written ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status); */ } else if (nbad) /* write last string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ ffpclu(fptr, colnum, fstrow, fstelm, nbad, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpclx( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG frow, /* I - first row to write (1 = 1st row) */ long fbit, /* I - first bit to write (1 = 1st) */ long nbit, /* I - number of bits to write */ char *larray, /* I - array of logicals corresponding to bits */ int *status) /* IO - error status */ /* write an array of logical values to a specified bit or byte column of the binary table. If larray is TRUE, then the corresponding bit is set to 1, otherwise it is set to 0. The binary table column being written to must have datatype 'B' or 'X'. */ { LONGLONG offset, bstart, repeat, rowlen, elemnum, rstart, estart, tnull; long fbyte, lbyte, nbyte, bitloc, ndone; long ii, twidth, incre; int tcode, descrp, maxelem, hdutype; double dummyd; char tform[12], snull[12]; unsigned char cbuff; static unsigned char onbit[8] = {128, 64, 32, 16, 8, 4, 2, 1}; static unsigned char offbit[8] = {127, 191, 223, 239, 247, 251, 253, 254}; LONGLONG heapoffset, lrepeat; tcolumn *colptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check input parameters */ if (nbit < 1) return(*status); else if (frow < 1) return(*status = BAD_ROW_NUM); else if (fbit < 1) return(*status = BAD_ELEM_NUM); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); fbyte = (fbit + 7) / 8; lbyte = (fbit + nbit + 6) / 8; nbyte = lbyte - fbyte +1; /* Save the current heapsize; ffgcprll will increment the value if */ /* we are writing to a variable length column. */ offset = (fptr->Fptr)->heapsize; /* call ffgcprll in case we are writing beyond the current end of */ /* the table; it will allocate more space and shift any following */ /* HDU's. Otherwise, we have little use for most of the returned */ /* parameters, therefore just use dummy parameters. */ if (ffgcprll( fptr, colnum, frow, fbyte, nbyte, 1, &dummyd, &dummyd, tform, &twidth, &tcode, &maxelem, &bstart, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); bitloc = fbit - 1 - ((fbit - 1) / 8 * 8); ndone = 0; rstart = frow - 1; estart = fbyte - 1; colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (abs(tcode) > TBYTE) return(*status = NOT_LOGICAL_COL); /* not correct datatype column */ if (tcode > 0) { descrp = FALSE; /* not a variable length descriptor column */ repeat = colptr->trepeat; if (tcode == TBIT) repeat = (repeat + 7) / 8; /* convert from bits to bytes */ if (fbyte > repeat) return(*status = BAD_ELEM_NUM); /* calc the i/o pointer location to start of sequence of pixels */ bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) + colptr->tbcol + estart; } else { descrp = TRUE; /* a variable length descriptor column */ /* only bit arrays (tform = 'X') are supported for variable */ /* length arrays. REPEAT is the number of BITS in the array. */ repeat = fbit + nbit -1; /* write the number of elements and the starting offset. */ /* Note: ffgcprll previous wrote the descripter, but with the */ /* wrong repeat value (gave bytes instead of bits). */ /* Make sure to not change the current heap offset value! */ if (tcode == -TBIT) { ffgdesll(fptr, colnum, frow, &lrepeat, &heapoffset, status); ffpdes( fptr, colnum, frow, (long) repeat, heapoffset, status); } /* Calc the i/o pointer location to start of sequence of pixels. */ /* ffgcprll has already calculated a value for bstart that */ /* points to the first element of the vector; we just have to */ /* increment it to point to the first element we want to write to. */ /* Note: ffgcprll also already updated the size of the heap, so we */ /* don't have to do that again here. */ bstart += estart; } /* move the i/o pointer to the start of the pixel sequence */ ffmbyt(fptr, bstart, IGNORE_EOF, status); /* read the next byte (we may only be modifying some of the bits) */ while (1) { if (ffgbyt(fptr, 1, &cbuff, status) == END_OF_FILE) { /* hit end of file trying to read the byte, so just set byte = 0 */ *status = 0; cbuff = 0; } /* move back, to be able to overwrite the byte */ ffmbyt(fptr, bstart, IGNORE_EOF, status); for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++) { if(larray[ndone]) cbuff = cbuff | onbit[ii]; else cbuff = cbuff & offbit[ii]; } ffpbyt(fptr, 1, &cbuff, status); /* write the modified byte */ if (ndone == nbit) /* finished all the bits */ return(*status); /* not done, so get the next byte */ bstart++; if (!descrp) { estart++; if (estart == repeat) { /* move the i/o pointer to the next row of pixels */ estart = 0; rstart = rstart + 1; bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) + colptr->tbcol; ffmbyt(fptr, bstart, IGNORE_EOF, status); } } bitloc = 0; } } cfitsio-4.3.1/putkey.c0000644000225700000360000035760114523006234014145 0ustar cagordonlhea/* This file, putkey.c, contains routines that write keywords to */ /* a FITS header. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include /* stddef.h is apparently needed to define size_t */ #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffcrim(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ long *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* create an IMAGE extension following the current HDU. If the current HDU is empty (contains no header keywords), then simply write the required image (or primary array) keywords to the current HDU. */ { if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* create new extension if current header is not empty */ if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) ffcrhd(fptr, status); /* write the required header keywords */ ffphpr(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffcrimll(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ LONGLONG *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* create an IMAGE extension following the current HDU. If the current HDU is empty (contains no header keywords), then simply write the required image (or primary array) keywords to the current HDU. */ { if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* create new extension if current header is not empty */ if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) ffcrhd(fptr, status); /* write the required header keywords */ ffphprll(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffcrtb(fitsfile *fptr, /* I - FITS file pointer */ int tbltype, /* I - type of table to create */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnm, /* I - value of EXTNAME keyword, if any */ int *status) /* IO - error status */ /* Create a table extension in a FITS file. */ { LONGLONG naxis1 = 0; long *tbcol = 0; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* create new extension if current header is not empty */ if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) ffcrhd(fptr, status); if ((fptr->Fptr)->curhdu == 0) /* have to create dummy primary array */ { ffcrim(fptr, 16, 0, tbcol, status); ffcrhd(fptr, status); } if (tbltype == BINARY_TBL) { /* write the required header keywords. This will write PCOUNT = 0 */ ffphbn(fptr, naxis2, tfields, ttype, tform, tunit, extnm, 0, status); } else if (tbltype == ASCII_TBL) { /* write the required header keywords */ /* default values for naxis1 and tbcol will be calculated */ ffphtb(fptr, naxis1, naxis2, tfields, ttype, tbcol, tform, tunit, extnm, status); } else *status = NOT_TABLE; return(*status); } /*-------------------------------------------------------------------------*/ int ffpktp(fitsfile *fptr, /* I - FITS file pointer */ const char *filename, /* I - name of template file */ int *status) /* IO - error status */ /* read keywords from template file and append to the FITS file */ { FILE *diskfile; char card[FLEN_CARD], template[161]; char keyname[FLEN_KEYWORD], newname[FLEN_KEYWORD]; int keytype; size_t slen; if (*status > 0) /* inherit input status value if > 0 */ return(*status); diskfile = fopen(filename,"r"); if (!diskfile) /* couldn't open file */ { ffpmsg("ffpktp could not open the following template file:"); ffpmsg(filename); return(*status = FILE_NOT_OPENED); } while (fgets(template, 160, diskfile) ) /* get next template line */ { template[160] = '\0'; /* make sure string is terminated */ slen = strlen(template); /* get string length */ template[slen - 1] = '\0'; /* over write the 'newline' char */ if (ffgthd(template, card, &keytype, status) > 0) /* parse template */ break; strncpy(keyname, card, 8); keyname[8] = '\0'; if (keytype == -2) /* rename the card */ { strncpy(newname, &card[40], 8); newname[8] = '\0'; ffmnam(fptr, keyname, newname, status); } else if (keytype == -1) /* delete the card */ { ffdkey(fptr, keyname, status); } else if (keytype == 0) /* update the card */ { ffucrd(fptr, keyname, card, status); } else if (keytype == 1) /* append the card */ { ffprec(fptr, card, status); } else /* END card; stop here */ { break; } } fclose(diskfile); /* close the template file */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpky( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ const char *keyname,/* I - name of keyword to write */ void *value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes a keyword value with the datatype specified by the 2nd argument. */ { char errmsg[FLEN_ERRMSG]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (datatype == TSTRING) { ffpkys(fptr, keyname, (char *) value, comm, status); } else if (datatype == TBYTE) { ffpkyj(fptr, keyname, (LONGLONG) *(unsigned char *) value, comm, status); } else if (datatype == TSBYTE) { ffpkyj(fptr, keyname, (LONGLONG) *(signed char *) value, comm, status); } else if (datatype == TUSHORT) { ffpkyj(fptr, keyname, (LONGLONG) *(unsigned short *) value, comm, status); } else if (datatype == TSHORT) { ffpkyj(fptr, keyname, (LONGLONG) *(short *) value, comm, status); } else if (datatype == TUINT) { ffpkyg(fptr, keyname, (double) *(unsigned int *) value, 0, comm, status); } else if (datatype == TINT) { ffpkyj(fptr, keyname, (LONGLONG) *(int *) value, comm, status); } else if (datatype == TLOGICAL) { ffpkyl(fptr, keyname, *(int *) value, comm, status); } else if (datatype == TULONG) { ffpkyuj(fptr, keyname, (ULONGLONG) *(unsigned long *) value, comm, status); } else if (datatype == TULONGLONG) { ffpkyuj(fptr, keyname, (ULONGLONG) *(ULONGLONG *) value, comm, status); } else if (datatype == TLONG) { ffpkyj(fptr, keyname, (LONGLONG) *(long *) value, comm, status); } else if (datatype == TLONGLONG) { ffpkyj(fptr, keyname, *(LONGLONG *) value, comm, status); } else if (datatype == TFLOAT) { ffpkye(fptr, keyname, *(float *) value, -7, comm, status); } else if (datatype == TDOUBLE) { ffpkyd(fptr, keyname, *(double *) value, -15, comm, status); } else if (datatype == TCOMPLEX) { ffpkyc(fptr, keyname, (float *) value, -7, comm, status); } else if (datatype == TDBLCOMPLEX) { ffpkym(fptr, keyname, (double *) value, -15, comm, status); } else { snprintf(errmsg, FLEN_ERRMSG,"Bad keyword datatype code: %d (ffpky)", datatype); ffpmsg(errmsg); *status = BAD_DATATYPE; } return(*status); } /*-------------------------------------------------------------------------*/ int ffprec(fitsfile *fptr, /* I - FITS file pointer */ const char *card, /* I - string to be written */ int *status) /* IO - error status */ /* write a keyword record (80 bytes long) to the end of the header */ { char tcard[FLEN_CARD]; size_t len, ii; long nblocks; int keylength; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ( ((fptr->Fptr)->datastart - (fptr->Fptr)->headend) == 80) /* no room */ { nblocks = 1; if (ffiblk(fptr, nblocks, 0, status) > 0) /* insert 2880-byte block */ return(*status); } strncpy(tcard,card,80); tcard[80] = '\0'; len = strlen(tcard); /* silently replace any illegal characters with a space */ for (ii=0; ii < len; ii++) if (tcard[ii] < ' ' || tcard[ii] > 126) tcard[ii] = ' '; for (ii=len; ii < 80; ii++) /* fill card with spaces if necessary */ tcard[ii] = ' '; keylength = strcspn(tcard, "="); /* support for free-format keywords */ if (keylength == 80) keylength = 8; /* test for the common commentary keywords which by definition have 8-char names */ if ( !fits_strncasecmp( "COMMENT ", tcard, 8) || !fits_strncasecmp( "HISTORY ", tcard, 8) || !fits_strncasecmp( " ", tcard, 8) || !fits_strncasecmp( "CONTINUE", tcard, 8) ) keylength = 8; for (ii=0; ii < keylength; ii++) /* make sure keyword name is uppercase */ tcard[ii] = toupper(tcard[ii]); fftkey(tcard, status); /* test keyword name contains legal chars */ /* no need to do this any more, since any illegal characters have been removed fftrec(tcard, status); */ /* test rest of keyword for legal chars */ ffmbyt(fptr, (fptr->Fptr)->headend, IGNORE_EOF, status); /* move to end */ ffpbyt(fptr, 80, tcard, status); /* write the 80 byte card */ if (*status <= 0) (fptr->Fptr)->headend += 80; /* update end-of-header position */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyu( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) a null-valued keyword and comment into the FITS header. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); strcpy(valstring," "); /* create a dummy value string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword */ ffprec(fptr, card, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpkys( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ const char *value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. The value string will be truncated at 68 characters which is the maximum length that will fit on a single FITS keyword. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffs2c(value, valstring, status); /* put quotes around the string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword */ ffprec(fptr, card, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpkls( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ const char *value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ { if (*status > 0) return(*status); fits_make_longstr_key_util(fptr, keyname, value, comm, -1, status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_make_longstr_key_util( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ const char *value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int position, /* I - position to insert (-1 for end) */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. This routine is a modified version of ffpkys which supports the HEASARC long string convention and can write arbitrarily long string keyword values. The value is continued over multiple keywords that have the name CONTINUE without an equal sign in column 9 of the card. This routine also supports simple string keywords which are less than 75 characters in length. */ { char valstring[FLEN_CARD], comstring[FLEN_CARD]; /* give tmpkeyname same size restriction as in ffmkky */ char card[FLEN_CARD], tmpkeyname[FLEN_KEYWORD]; char tstring[FLEN_CARD], *cptr; int next, remainval, remaincom, vlen, nquote, nchar; int namelen, finalnamelen, maxvalchars; int contin, tstatus=-1, nocomment=0, ichar, addline=1; int spaceForComments=0, processingComment=0, nblanks=0, allInOne=0; /* This setting is arbitrary */ int fixedSpaceForComments = 50; if (*status > 0) /* inherit input status value if > 0 */ return(*status); remainval = strlen(value); if (comm) remaincom = strlen(comm); else remaincom = 0; tmpkeyname[0] = '\0'; cptr = keyname; while(*cptr == ' ') /* skip over leading spaces in name */ cptr++; strncpy(tmpkeyname, cptr, FLEN_KEYWORD-1); tmpkeyname[FLEN_KEYWORD-1] = '\0'; namelen = strlen(tmpkeyname); if (namelen) /* skip trailing spaces in name */ { cptr = tmpkeyname + namelen - 1; while (*cptr == ' ') { *cptr = '\0'; cptr--; } namelen = strlen(tmpkeyname); } /* First determine final length of keyword. ffmkky may prepend "HIERARCH " to it, and we need to determine that now using the same criteria as ffmkky. */ if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) ) { /* This a normal 8-character FITS keyword. ffmkky will pad it to 8 if necessary, and add "= ". */ finalnamelen = 10; /* 2 additional chars are needed for opening/closing quotes. */ maxvalchars = (FLEN_CARD-1) - finalnamelen - 2; } else { if (namelen && ((FSTRNCMP(tmpkeyname, "HIERARCH ", 9) == 0) || (FSTRNCMP(tmpkeyname, "hierarch ", 9) == 0)) ) { /* We have an explicitly marked long keyword, so HIERARCH will not be prepended. However it can then have " = " or "= ", depending on size of value string. For now, assume "= ". If we're here, must have 75 > namelen > 9. */ finalnamelen = namelen + 2; } else { /* ffmkky is going to prepend "HIERARCH " to the keyword, and " = " or "= ". */ finalnamelen = namelen + 11; if (finalnamelen > FLEN_CARD-1) { ffpmsg("The following keyword is too long to fit on a card in ffpkls:"); ffpmsg(keyname); return(*status = BAD_KEYCHAR); } } maxvalchars = (FLEN_CARD-1) - finalnamelen - 2; } contin = 0; next = 0; /* pointer to next character to write */ while (addline) { if (processingComment) { if (remaincom > (fixedSpaceForComments-3)) { strcpy(valstring,"'&'"); nblanks = (FLEN_CARD-1) - fixedSpaceForComments - 13; memset(&valstring[3], 32, nblanks); valstring[nblanks+3] = '\0'; } else { strcpy(valstring,"''"); nblanks = (FLEN_CARD-1) - fixedSpaceForComments - 12; memset(&valstring[2], 32, nblanks); valstring[nblanks+2] = '\0'; } nchar = minvalue(remaincom, fixedSpaceForComments-3); strncpy(comstring, &comm[next], nchar); comstring[nchar] = '\0'; next += nchar; remaincom -= nchar; } else { vlen = strlen(&value[next]); nquote = 0; for (ichar=0; ichar nchar))) { nchar -= 1; /* outputting one less character now */ if (valstring[vlen-2] != '\'') valstring[vlen-2] = '&'; /* overwrite last char with & */ else { /* last char was a pair of single quotes, so over write both */ valstring[vlen-3] = '&'; valstring[vlen-1] = '\0'; } } else if ( /* Cases where '&' should be appended to valstring rather than overwritten. This would mostly be due to the inclusion of a comment string requiring additional lines. But there's also the obscure case where the last character that can fit happened to be a single quote. Since this was removed with the earlier 'nchar = minvlaue()' test, the valstring must be continued even though it's one space short of filling this line. We then append it with a '&'. */ (spaceForComments && nchar < remainval) || (remaincom && (spaceForComments < fixedSpaceForComments || spaceForComments < remaincom))) { valstring[vlen-1] = '&'; valstring[vlen] = '\''; valstring[vlen+1] = '\0'; vlen+=1; } } if (allInOne) { nocomment=0; /* The allInOne test ensures that comm length will fit within FLEN_CARD buffer size */ if (comm) strcpy(comstring, comm); else comstring[0]='\0'; /* Ensure that loop exits after this iteration */ remainval=0; remaincom=0; } else if (remainval > nchar) { nocomment = 1; remainval -= nchar; next += nchar; maxvalchars = (FLEN_CARD-1) - 12; } else { /* We've reached the end of val input. Now switch to writing comment (if any). This block can only be reached once. */ /* Do not write comments on this line if fewer than fixedSpaceForComments are available for the comment string and " / ". */ nocomment = 1; remainval = 0; next = 0; processingComment = 1; if (remaincom && spaceForComments >= fixedSpaceForComments) { nocomment = 0; nchar = minvalue(remaincom, fixedSpaceForComments-3); strncpy(comstring, comm, nchar); comstring[nchar] = '\0'; next = nchar; remaincom -= nchar; } } } /* end if processing valstring and not comment */ if (contin) /* This is a CONTINUEd keyword */ { if (nocomment) { ffmkky("CONTINUE", valstring, NULL, card, status); /* make keyword w/o comment */ } else { ffmkky("CONTINUE", valstring, comstring, card, status); /* make keyword */ } strncpy(&card[8], " ", 2); /* overwrite the '=' */ } else { if (nocomment) ffmkky(keyname, valstring, NULL, card, status); /* make keyword */ else ffmkky(keyname, valstring, comstring, card, status); /* make keyword */ } if (position < 0) ffprec(fptr, card, status); /* write the keyword */ else { ffirec(fptr, position, card, status); /* insert the keyword */ ++position; } contin = 1; nocomment = 0; addline = (int)(remainval > 0 || remaincom > 0); } return(*status); } /*--------------------------------------------------------------------------*/ int ffplsw( fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Write the LONGSTRN keyword and a series of related COMMENT keywords which document that this FITS header may contain long string keyword values which are continued over multiple keywords using the HEASARC long string keyword convention. If the LONGSTRN keyword already exists then this routine simple returns without doing anything. */ { char valstring[FLEN_VALUE], comm[FLEN_COMMENT]; int tstatus; if (*status > 0) /* inherit input status value if > 0 */ return(*status); tstatus = 0; if (ffgkys(fptr, "LONGSTRN", valstring, comm, &tstatus) == 0) return(*status); /* keyword already exists, so just return */ ffpkys(fptr, "LONGSTRN", "OGIP 1.0", "The HEASARC Long String Convention may be used.", status); ffpcom(fptr, " This FITS file may contain long string keyword values that are", status); ffpcom(fptr, " continued over multiple keywords. The HEASARC convention uses the &", status); ffpcom(fptr, " character at the end of each substring which is then continued", status); ffpcom(fptr, " on the next keyword which has the name CONTINUE.", status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyl( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ int value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Values equal to 0 will result in a False FITS keyword; any other non-zero value will result in a True FITS keyword. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffl2c(value, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ LONGLONG value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an integer keyword value. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffi2c(value, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyuj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ ULONGLONG value, /* I - keyword value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an integer keyword value. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffu2c(value, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyf( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ float value, /* I - keyword value */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes a fixed float keyword value. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffr2f(value, decim, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkye( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ float value, /* I - keyword value */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an exponential float keyword value. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffr2e(value, decim, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyg( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ double value, /* I - keyword value */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes a fixed double keyword value.*/ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffd2f(value, decim, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyd( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ double value, /* I - keyword value */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an exponential double keyword value.*/ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffd2e(value, decim, valstring, status); /* convert to formatted string */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyc( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ float *value, /* I - keyword value (real, imaginary) */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an complex float keyword value. Format = (realvalue, imagvalue) */ { char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); strcpy(valstring, "(" ); ffr2e(value[0], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkyc)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ", "); ffr2e(value[1], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkyc)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ")"); ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkym( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ double *value, /* I - keyword value (real, imaginary) */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an complex double keyword value. Format = (realvalue, imagvalue) */ { char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); strcpy(valstring, "(" ); ffd2e(value[0], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkym)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ", "); ffd2e(value[1], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkym)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ")"); ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkfc( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ float *value, /* I - keyword value (real, imaginary) */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an complex float keyword value. Format = (realvalue, imagvalue) */ { char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); strcpy(valstring, "(" ); ffr2f(value[0], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkfc)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ", "); ffr2f(value[1], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkfc)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ")"); ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkfm( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ double *value, /* I - keyword value (real, imaginary) */ int decim, /* I - number of decimal places to display */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) the keyword, value and comment into the FITS header. Writes an complex double keyword value. Format = (realvalue, imagvalue) */ { char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE]; char card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); strcpy(valstring, "(" ); ffd2f(value[0], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+2 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkfm)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ", "); ffd2f(value[1], decim, tmpstring, status); /* convert to string */ if (strlen(valstring)+strlen(tmpstring)+1 > FLEN_VALUE-1) { ffpmsg("Error converting complex to string (ffpkfm)"); return(*status=BAD_F2C); } strcat(valstring, tmpstring); strcat(valstring, ")"); ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*--------------------------------------------------------------------------*/ int ffpkyt( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname,/* I - name of keyword to write */ long intval, /* I - integer part of value */ double fraction, /* I - fractional part of value */ const char *comm, /* I - keyword comment */ int *status) /* IO - error status */ /* Write (put) a 'triple' precision keyword where the integer and fractional parts of the value are passed in separate parameters to increase the total amount of numerical precision. */ { char valstring[FLEN_VALUE]; char card[FLEN_CARD]; char fstring[20], *cptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (fraction > 1. || fraction < 0.) { ffpmsg("fraction must be between 0. and 1. (ffpkyt)"); return(*status = BAD_F2C); } ffi2c(intval, valstring, status); /* convert integer to string */ ffd2f(fraction, 16, fstring, status); /* convert to 16 decimal string */ cptr = strchr(fstring, '.'); /* find the decimal point */ if (strlen(valstring)+strlen(cptr) > FLEN_VALUE-1) { ffpmsg("converted numerical string too long"); return(*status=BAD_F2C); } strcat(valstring, cptr); /* append the fraction to the integer */ ffmkky(keyname, valstring, comm, card, status); /* construct the keyword*/ ffprec(fptr, card, status); /* write the keyword*/ return(*status); } /*-----------------------------------------------------------------*/ int ffpcom( fitsfile *fptr, /* I - FITS file pointer */ const char *comm, /* I - comment string */ int *status) /* IO - error status */ /* Write 1 or more COMMENT keywords. If the comment string is too long to fit on a single keyword (72 chars) then it will automatically be continued on multiple CONTINUE keywords. */ { char card[FLEN_CARD]; int len, ii; if (*status > 0) /* inherit input status value if > 0 */ return(*status); len = strlen(comm); ii = 0; for (; len > 0; len -= 72) { strcpy(card, "COMMENT "); strncat(card, &comm[ii], 72); ffprec(fptr, card, status); ii += 72; } return(*status); } /*-----------------------------------------------------------------*/ int ffphis( fitsfile *fptr, /* I - FITS file pointer */ const char *history, /* I - history string */ int *status) /* IO - error status */ /* Write 1 or more HISTORY keywords. If the history string is too long to fit on a single keyword (72 chars) then it will automatically be continued on multiple HISTORY keywords. */ { char card[FLEN_CARD]; int len, ii; if (*status > 0) /* inherit input status value if > 0 */ return(*status); len = strlen(history); ii = 0; for (; len > 0; len -= 72) { strcpy(card, "HISTORY "); strncat(card, &history[ii], 72); ffprec(fptr, card, status); ii += 72; } return(*status); } /*-----------------------------------------------------------------*/ int ffpdat( fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Write the DATE keyword into the FITS header. If the keyword already exists then the date will simply be updated in the existing keyword. */ { int timeref; char date[30], tmzone[10], card[FLEN_CARD]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); ffgstm(date, &timeref, status); if (timeref) /* GMT not available on this machine */ strcpy(tmzone, " Local"); else strcpy(tmzone, " UT"); strcpy(card, "DATE = '"); strcat(card, date); strcat(card, "' / file creation date (YYYY-MM-DDThh:mm:ss"); strcat(card, tmzone); strcat(card, ")"); ffucrd(fptr, "DATE", card, status); return(*status); } /*-------------------------------------------------------------------*/ int ffverifydate(int year, /* I - year (0 - 9999) */ int month, /* I - month (1 - 12) */ int day, /* I - day (1 - 31) */ int *status) /* IO - error status */ /* Verify that the date is valid */ { int ndays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; char errmsg[FLEN_ERRMSG]; if (year < 0 || year > 9999) { snprintf(errmsg, FLEN_ERRMSG, "input year value = %d is out of range 0 - 9999", year); ffpmsg(errmsg); return(*status = BAD_DATE); } else if (month < 1 || month > 12) { snprintf(errmsg, FLEN_ERRMSG, "input month value = %d is out of range 1 - 12", month); ffpmsg(errmsg); return(*status = BAD_DATE); } if (ndays[month] == 31) { if (day < 1 || day > 31) { snprintf(errmsg, FLEN_ERRMSG, "input day value = %d is out of range 1 - 31 for month %d", day, month); ffpmsg(errmsg); return(*status = BAD_DATE); } } else if (ndays[month] == 30) { if (day < 1 || day > 30) { snprintf(errmsg, FLEN_ERRMSG, "input day value = %d is out of range 1 - 30 for month %d", day, month); ffpmsg(errmsg); return(*status = BAD_DATE); } } else { if (day < 1 || day > 28) { if (day == 29) { /* year is a leap year if it is divisible by 4 but not by 100, except years divisible by 400 are leap years */ if ((year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0) return (*status); snprintf(errmsg, FLEN_ERRMSG, "input day value = %d is out of range 1 - 28 for February %d (not leap year)", day, year); ffpmsg(errmsg); } else { snprintf(errmsg, FLEN_ERRMSG, "input day value = %d is out of range 1 - 28 (or 29) for February", day); ffpmsg(errmsg); } return(*status = BAD_DATE); } } return(*status); } /*-----------------------------------------------------------------*/ int ffgstm( char *timestr, /* O - returned system date and time string */ int *timeref, /* O - GMT = 0, Local time = 1 */ int *status) /* IO - error status */ /* Returns the current date and time in format 'yyyy-mm-ddThh:mm:ss'. */ { time_t tp; struct tm *ptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); time(&tp); ptr = gmtime(&tp); /* get GMT (= UTC) time */ if (timeref) { if (ptr) *timeref = 0; /* returning GMT */ else *timeref = 1; /* returning local time */ } if (!ptr) /* GMT not available on this machine */ ptr = localtime(&tp); strftime(timestr, 25, "%Y-%m-%dT%H:%M:%S", ptr); return(*status); } /*-----------------------------------------------------------------*/ int ffdt2s(int year, /* I - year (0 - 9999) */ int month, /* I - month (1 - 12) */ int day, /* I - day (1 - 31) */ char *datestr, /* O - date string: "YYYY-MM-DD" */ int *status) /* IO - error status */ /* Construct a date character string */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); *datestr = '\0'; if (ffverifydate(year, month, day, status) > 0) { ffpmsg("invalid date (ffdt2s)"); return(*status); } if (year >= 1900 && year <= 1998) /* use old 'dd/mm/yy' format */ sprintf(datestr, "%.2d/%.2d/%.2d", day, month, year - 1900); else /* use the new 'YYYY-MM-DD' format */ sprintf(datestr, "%.4d-%.2d-%.2d", year, month, day); return(*status); } /*-----------------------------------------------------------------*/ int ffs2dt(char *datestr, /* I - date string: "YYYY-MM-DD" or "dd/mm/yy" */ int *year, /* O - year (0 - 9999) */ int *month, /* O - month (1 - 12) */ int *day, /* O - day (1 - 31) */ int *status) /* IO - error status */ /* Parse a date character string into year, month, and day values */ { int slen, lyear, lmonth, lday; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (year) *year = 0; if (month) *month = 0; if (day) *day = 0; if (!datestr) { ffpmsg("error: null input date string (ffs2dt)"); return(*status = BAD_DATE); /* Null datestr pointer ??? */ } slen = strlen(datestr); if (slen == 8 && datestr[2] == '/' && datestr[5] == '/') { if (isdigit((int) datestr[0]) && isdigit((int) datestr[1]) && isdigit((int) datestr[3]) && isdigit((int) datestr[4]) && isdigit((int) datestr[6]) && isdigit((int) datestr[7]) ) { /* this is an old format string: "dd/mm/yy" */ lyear = atoi(&datestr[6]) + 1900; lmonth = atoi(&datestr[3]); lday = atoi(datestr); if (year) *year = lyear; if (month) *month = lmonth; if (day) *day = lday; } else { ffpmsg("input date string has illegal format (ffs2dt):"); ffpmsg(datestr); return(*status = BAD_DATE); } } else if (slen >= 10 && datestr[4] == '-' && datestr[7] == '-') { if (isdigit((int) datestr[0]) && isdigit((int) datestr[1]) && isdigit((int) datestr[2]) && isdigit((int) datestr[3]) && isdigit((int) datestr[5]) && isdigit((int) datestr[6]) && isdigit((int) datestr[8]) && isdigit((int) datestr[9]) ) { if (slen > 10 && datestr[10] != 'T') { ffpmsg("input date string has illegal format (ffs2dt):"); ffpmsg(datestr); return(*status = BAD_DATE); } /* this is a new format string: "yyyy-mm-dd" */ lyear = atoi(datestr); lmonth = atoi(&datestr[5]); lday = atoi(&datestr[8]); if (year) *year = lyear; if (month) *month = lmonth; if (day) *day = lday; } else { ffpmsg("input date string has illegal format (ffs2dt):"); ffpmsg(datestr); return(*status = BAD_DATE); } } else { ffpmsg("input date string has illegal format (ffs2dt):"); ffpmsg(datestr); return(*status = BAD_DATE); } if (ffverifydate(lyear, lmonth, lday, status) > 0) { ffpmsg("invalid date (ffs2dt)"); } return(*status); } /*-----------------------------------------------------------------*/ int fftm2s(int year, /* I - year (0 - 9999) */ int month, /* I - month (1 - 12) */ int day, /* I - day (1 - 31) */ int hour, /* I - hour (0 - 23) */ int minute, /* I - minute (0 - 59) */ double second, /* I - second (0. - 60.9999999) */ int decimals, /* I - number of decimal points to write */ char *datestr, /* O - date string: "YYYY-MM-DDThh:mm:ss.ddd" */ /* or "hh:mm:ss.ddd" if year, month day = 0 */ int *status) /* IO - error status */ /* Construct a date and time character string */ { int width; char errmsg[FLEN_ERRMSG]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); *datestr='\0'; if (year != 0 || month != 0 || day !=0) { if (ffverifydate(year, month, day, status) > 0) { ffpmsg("invalid date (fftm2s)"); return(*status); } } if (hour < 0 || hour > 23) { snprintf(errmsg, FLEN_ERRMSG, "input hour value is out of range 0 - 23: %d (fftm2s)", hour); ffpmsg(errmsg); return(*status = BAD_DATE); } else if (minute < 0 || minute > 59) { snprintf(errmsg, FLEN_ERRMSG, "input minute value is out of range 0 - 59: %d (fftm2s)", minute); ffpmsg(errmsg); return(*status = BAD_DATE); } else if (second < 0. || second >= 61) { snprintf(errmsg, FLEN_ERRMSG, "input second value is out of range 0 - 60.999: %f (fftm2s)", second); ffpmsg(errmsg); return(*status = BAD_DATE); } else if (decimals > 25) { snprintf(errmsg, FLEN_ERRMSG, "input decimals value is out of range 0 - 25: %d (fftm2s)", decimals); ffpmsg(errmsg); return(*status = BAD_DATE); } if (decimals == 0) width = 2; else width = decimals + 3; if (decimals < 0) { /* a negative decimals value means return only the date, not time */ sprintf(datestr, "%.4d-%.2d-%.2d", year, month, day); } else if (year == 0 && month == 0 && day == 0) { /* return only the time, not the date */ sprintf(datestr, "%.2d:%.2d:%0*.*f", hour, minute, width, decimals, second); } else { /* return both the time and date */ sprintf(datestr, "%.4d-%.2d-%.2dT%.2d:%.2d:%0*.*f", year, month, day, hour, minute, width, decimals, second); } return(*status); } /*-----------------------------------------------------------------*/ int ffs2tm(char *datestr, /* I - date string: "YYYY-MM-DD" */ /* or "YYYY-MM-DDThh:mm:ss.ddd" */ /* or "dd/mm/yy" */ int *year, /* O - year (0 - 9999) */ int *month, /* O - month (1 - 12) */ int *day, /* O - day (1 - 31) */ int *hour, /* I - hour (0 - 23) */ int *minute, /* I - minute (0 - 59) */ double *second, /* I - second (0. - 60.9999999) */ int *status) /* IO - error status */ /* Parse a date character string into date and time values */ { int slen; char errmsg[FLEN_ERRMSG]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (year) *year = 0; if (month) *month = 0; if (day) *day = 0; if (hour) *hour = 0; if (minute) *minute = 0; if (second) *second = 0.; if (!datestr) { ffpmsg("error: null input date string (ffs2tm)"); return(*status = BAD_DATE); /* Null datestr pointer ??? */ } if (datestr[2] == '/' || datestr[4] == '-') { /* Parse the year, month, and date */ if (ffs2dt(datestr, year, month, day, status) > 0) return(*status); slen = strlen(datestr); if (slen == 8 || slen == 10) return(*status); /* OK, no time fields */ else if (slen < 19) { ffpmsg("input date string has illegal format:"); ffpmsg(datestr); return(*status = BAD_DATE); } else if (datestr[10] == 'T') { if (datestr[13] == ':' && datestr[16] == ':') { if (isdigit((int) datestr[11]) && isdigit((int) datestr[12]) && isdigit((int) datestr[14]) && isdigit((int) datestr[15]) && isdigit((int) datestr[17]) && isdigit((int) datestr[18]) ) { if (slen > 19 && datestr[19] != '.') { ffpmsg("input date string has illegal format:"); ffpmsg(datestr); return(*status = BAD_DATE); } /* this is a new format string: "yyyy-mm-ddThh:mm:ss.dddd" */ if (hour) *hour = atoi(&datestr[11]); if (minute) *minute = atoi(&datestr[14]); if (second) *second = atof(&datestr[17]); } else { ffpmsg("input date string has illegal format:"); ffpmsg(datestr); return(*status = BAD_DATE); } } else { ffpmsg("input date string has illegal format:"); ffpmsg(datestr); return(*status = BAD_DATE); } } } else /* no date fields */ { if (datestr[2] == ':' && datestr[5] == ':') /* time string */ { if (isdigit((int) datestr[0]) && isdigit((int) datestr[1]) && isdigit((int) datestr[3]) && isdigit((int) datestr[4]) && isdigit((int) datestr[6]) && isdigit((int) datestr[7]) ) { /* this is a time string: "hh:mm:ss.dddd" */ if (hour) *hour = atoi(&datestr[0]); if (minute) *minute = atoi(&datestr[3]); if (second) *second = atof(&datestr[6]); } else { ffpmsg("input date string has illegal format:"); ffpmsg(datestr); return(*status = BAD_DATE); } } else { ffpmsg("input date string has illegal format:"); ffpmsg(datestr); return(*status = BAD_DATE); } } if (hour) if (*hour < 0 || *hour > 23) { snprintf(errmsg,FLEN_ERRMSG, "hour value is out of range 0 - 23: %d (ffs2tm)", *hour); ffpmsg(errmsg); return(*status = BAD_DATE); } if (minute) if (*minute < 0 || *minute > 59) { snprintf(errmsg, FLEN_ERRMSG, "minute value is out of range 0 - 59: %d (ffs2tm)", *minute); ffpmsg(errmsg); return(*status = BAD_DATE); } if (second) if (*second < 0 || *second >= 61.) { snprintf(errmsg, FLEN_ERRMSG, "second value is out of range 0 - 60.9999: %f (ffs2tm)", *second); ffpmsg(errmsg); return(*status = BAD_DATE); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsdt( int *day, int *month, int *year, int *status ) { /* This routine is included for backward compatibility with the Fortran FITSIO library. ffgsdt : Get current System DaTe (GMT if available) Return integer values of the day, month, and year Function parameters: day Day of the month month Numerical month (1=Jan, etc.) year Year (1999, 2000, etc.) status output error status */ time_t now; struct tm *date; now = time( NULL ); date = gmtime(&now); /* get GMT (= UTC) time */ if (!date) /* GMT not available on this machine */ { date = localtime(&now); } *day = date->tm_mday; *month = date->tm_mon + 1; *year = date->tm_year + 1900; /* tm_year is defined as years since 1900 */ return( *status ); } /*--------------------------------------------------------------------------*/ int ffpkns( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ char *value[], /* I - array of pointers to keyword values */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Writes string keywords. The value strings will be truncated at 68 characters, and the HEASARC long string keyword convention is not supported by this routine. */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkys(fptr, keyname, value[ii], tcomment, status); else ffpkys(fptr, keyname, value[ii], comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpknl( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ int *value, /* I - array of keyword values */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Writes logical keywords Values equal to zero will be written as a False FITS keyword value; any other non-zero value will result in a True FITS keyword. */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkyl(fptr, keyname, value[ii], tcomment, status); else ffpkyl(fptr, keyname, value[ii], comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpknj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ long *value, /* I - array of keyword values */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Write integer keywords */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkyj(fptr, keyname, value[ii], tcomment, status); else ffpkyj(fptr, keyname, value[ii], comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpknjj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ LONGLONG *value, /* I - array of keyword values */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Write integer keywords */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkyj(fptr, keyname, value[ii], tcomment, status); else ffpkyj(fptr, keyname, value[ii], comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpknf( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ float *value, /* I - array of keyword values */ int decim, /* I - number of decimals to display */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Writes fixed float values. */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkyf(fptr, keyname, value[ii], decim, tcomment, status); else ffpkyf(fptr, keyname, value[ii], decim, comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpkne( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ float *value, /* I - array of keyword values */ int decim, /* I - number of decimals to display */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Writes exponential float values. */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkye(fptr, keyname, value[ii], decim, tcomment, status); else ffpkye(fptr, keyname, value[ii], decim, comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpkng( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ double *value, /* I - array of keyword values */ int decim, /* I - number of decimals to display */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Writes fixed double values. */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkyg(fptr, keyname, value[ii], decim, tcomment, status); else ffpkyg(fptr, keyname, value[ii], decim, comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffpknd( fitsfile *fptr, /* I - FITS file pointer */ const char *keyroot, /* I - root name of keywords to write */ int nstart, /* I - starting index number */ int nkey, /* I - number of keywords to write */ double *value, /* I - array of keyword values */ int decim, /* I - number of decimals to display */ char *comm[], /* I - array of pointers to keyword comment */ int *status) /* IO - error status */ /* Write (put) an indexed array of keywords with index numbers between NSTART and (NSTART + NKEY -1) inclusive. Writes exponential double values. */ { char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT]; int ii, jj, repeat, len; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* check if first comment string is to be repeated for all the keywords */ /* by looking to see if the last non-blank character is a '&' char */ repeat = 0; if (comm) { len = strlen(comm[0]); while (len > 0 && comm[0][len - 1] == ' ') len--; /* ignore trailing blanks */ if (len > 0 && comm[0][len - 1] == '&') { len = minvalue(len, FLEN_COMMENT); tcomment[0] = '\0'; strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */ repeat = 1; } } else { repeat = 1; tcomment[0] = '\0'; } for (ii=0, jj=nstart; ii < nkey; ii++, jj++) { ffkeyn(keyroot, jj, keyname, status); if (repeat) ffpkyd(fptr, keyname, value[ii], decim, tcomment, status); else ffpkyd(fptr, keyname, value[ii], decim, comm[ii], status); if (*status > 0) return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffptdm( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int naxis, /* I - number of axes in the data array */ long naxes[], /* I - length of each data axis */ int *status) /* IO - error status */ /* write the TDIMnnn keyword describing the dimensionality of a column */ { char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE], comm[FLEN_COMMENT]; char value[80], message[FLEN_ERRMSG]; int ii; long totalpix = 1, repeat; tcolumn *colptr; if (*status > 0) return(*status); if (colnum < 1 || colnum > 999) { ffpmsg("column number is out of range 1 - 999 (ffptdm)"); return(*status = BAD_COL_NUM); } if (naxis < 1) { ffpmsg("naxis is less than 1 (ffptdm)"); return(*status = BAD_DIMEN); } /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ( (fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg( "Error: The TDIMn keyword is only allowed in BINTABLE extensions (ffptdm)"); return(*status = NOT_BTABLE); } strcpy(tdimstr, "("); /* start constructing the TDIM value */ for (ii = 0; ii < naxis; ii++) { if (ii > 0) strcat(tdimstr, ","); /* append the comma separator */ if (naxes[ii] < 0) { ffpmsg("one or more TDIM values are less than 0 (ffptdm)"); return(*status = BAD_TDIM); } snprintf(value, 80,"%ld", naxes[ii]); /* This will either be followed by a ',' or ')'. */ if (strlen(tdimstr)+strlen(value)+1 > FLEN_VALUE-1) { ffpmsg("TDIM string too long (ffptdm)"); return(*status = BAD_TDIM); } strcat(tdimstr, value); /* append the axis size */ totalpix *= naxes[ii]; } colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* point to the specified column number */ if ((long) colptr->trepeat != totalpix) { /* There is an apparent inconsistency between TDIMn and TFORMn. */ /* The colptr->trepeat value may be out of date, so re-read */ /* the TFORMn keyword to be sure. */ ffkeyn("TFORM", colnum, keyname, status); /* construct TFORMn name */ ffgkys(fptr, keyname, value, NULL, status); /* read TFORMn keyword */ ffbnfm(value, NULL, &repeat, NULL, status); /* parse the repeat count */ if (*status > 0 || repeat != totalpix) { snprintf(message,FLEN_ERRMSG, "column vector length, %ld, does not equal TDIMn array size, %ld", (long) colptr->trepeat, totalpix); ffpmsg(message); return(*status = BAD_TDIM); } } strcat(tdimstr, ")" ); /* append the closing parenthesis */ strcpy(comm, "size of the multidimensional array"); ffkeyn("TDIM", colnum, keyname, status); /* construct TDIMn name */ ffpkys(fptr, keyname, tdimstr, comm, status); /* write the keyword */ return(*status); } /*--------------------------------------------------------------------------*/ int ffptdmll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int naxis, /* I - number of axes in the data array */ LONGLONG naxes[], /* I - length of each data axis */ int *status) /* IO - error status */ /* write the TDIMnnn keyword describing the dimensionality of a column */ { char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE], comm[FLEN_COMMENT]; char value[80], message[81]; int ii; LONGLONG totalpix = 1, repeat; tcolumn *colptr; if (*status > 0) return(*status); if (colnum < 1 || colnum > 999) { ffpmsg("column number is out of range 1 - 999 (ffptdm)"); return(*status = BAD_COL_NUM); } if (naxis < 1) { ffpmsg("naxis is less than 1 (ffptdm)"); return(*status = BAD_DIMEN); } /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ( (fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg( "Error: The TDIMn keyword is only allowed in BINTABLE extensions (ffptdm)"); return(*status = NOT_BTABLE); } strcpy(tdimstr, "("); /* start constructing the TDIM value */ for (ii = 0; ii < naxis; ii++) { if (ii > 0) strcat(tdimstr, ","); /* append the comma separator */ if (naxes[ii] < 0) { ffpmsg("one or more TDIM values are less than 0 (ffptdm)"); return(*status = BAD_TDIM); } /* cast to double because the 64-bit int conversion character in */ /* sprintf is platform dependent ( %lld, %ld, %I64d ) */ snprintf(value, 80, "%.0f", (double) naxes[ii]); if (strlen(tdimstr)+strlen(value)+1 > FLEN_VALUE-1) { ffpmsg("TDIM string too long (ffptdmll)"); return(*status = BAD_TDIM); } strcat(tdimstr, value); /* append the axis size */ totalpix *= naxes[ii]; } colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* point to the specified column number */ if ( colptr->trepeat != totalpix) { /* There is an apparent inconsistency between TDIMn and TFORMn. */ /* The colptr->trepeat value may be out of date, so re-read */ /* the TFORMn keyword to be sure. */ ffkeyn("TFORM", colnum, keyname, status); /* construct TFORMn name */ ffgkys(fptr, keyname, value, NULL, status); /* read TFORMn keyword */ ffbnfmll(value, NULL, &repeat, NULL, status); /* parse the repeat count */ if (*status > 0 || repeat != totalpix) { snprintf(message,FLEN_ERRMSG, "column vector length, %.0f, does not equal TDIMn array size, %.0f", (double) (colptr->trepeat), (double) totalpix); ffpmsg(message); return(*status = BAD_TDIM); } } strcat(tdimstr, ")" ); /* append the closing parenthesis */ strcpy(comm, "size of the multidimensional array"); ffkeyn("TDIM", colnum, keyname, status); /* construct TDIMn name */ ffpkys(fptr, keyname, tdimstr, comm, status); /* write the keyword */ return(*status); } /*--------------------------------------------------------------------------*/ int ffphps( fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - number of bits per data value pixel */ int naxis, /* I - number of axes in the data array */ long naxes[], /* I - length of each data axis */ int *status) /* IO - error status */ /* write STANDARD set of required primary header keywords */ { int simple = 1; /* does file conform to FITS standard? 1/0 */ long pcount = 0; /* number of group parameters (usually 0) */ long gcount = 1; /* number of random groups (usually 1 or 0) */ int extend = 1; /* may FITS file have extensions? */ ffphpr(fptr, simple, bitpix, naxis, naxes, pcount, gcount, extend, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffphpsll( fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - number of bits per data value pixel */ int naxis, /* I - number of axes in the data array */ LONGLONG naxes[], /* I - length of each data axis */ int *status) /* IO - error status */ /* write STANDARD set of required primary header keywords */ { int simple = 1; /* does file conform to FITS standard? 1/0 */ LONGLONG pcount = 0; /* number of group parameters (usually 0) */ LONGLONG gcount = 1; /* number of random groups (usually 1 or 0) */ int extend = 1; /* may FITS file have extensions? */ ffphprll(fptr, simple, bitpix, naxis, naxes, pcount, gcount, extend, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffphpr( fitsfile *fptr, /* I - FITS file pointer */ int simple, /* I - does file conform to FITS standard? 1/0 */ int bitpix, /* I - number of bits per data value pixel */ int naxis, /* I - number of axes in the data array */ long naxes[], /* I - length of each data axis */ LONGLONG pcount, /* I - number of group parameters (usually 0) */ LONGLONG gcount, /* I - number of random groups (usually 1 or 0) */ int extend, /* I - may FITS file have extensions? */ int *status) /* IO - error status */ /* write required primary header keywords */ { int ii; LONGLONG naxesll[20]; for (ii = 0; (ii < naxis) && (ii < 20); ii++) naxesll[ii] = naxes[ii]; ffphprll(fptr, simple, bitpix, naxis, naxesll, pcount, gcount, extend, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffphprll( fitsfile *fptr, /* I - FITS file pointer */ int simple, /* I - does file conform to FITS standard? 1/0 */ int bitpix, /* I - number of bits per data value pixel */ int naxis, /* I - number of axes in the data array */ LONGLONG naxes[], /* I - length of each data axis */ LONGLONG pcount, /* I - number of group parameters (usually 0) */ LONGLONG gcount, /* I - number of random groups (usually 1 or 0) */ int extend, /* I - may FITS file have extensions? */ int *status) /* IO - error status */ /* write required primary header keywords */ { int ii; long longbitpix, tnaxes[20]; char name[FLEN_KEYWORD], comm[FLEN_COMMENT], message[FLEN_ERRMSG]; char card[FLEN_CARD]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) return(*status = HEADER_NOT_EMPTY); if (naxis != 0) /* never try to compress a null image */ { if ( (fptr->Fptr)->request_compress_type ) { for (ii = 0; ii < naxis; ii++) tnaxes[ii] = (long) naxes[ii]; /* write header for a compressed image */ imcomp_init_table(fptr, bitpix, naxis, tnaxes, 1, status); return(*status); } } if ((fptr->Fptr)->curhdu == 0) { /* write primary array header */ if (simple) strcpy(comm, "file does conform to FITS standard"); else strcpy(comm, "file does not conform to FITS standard"); ffpkyl(fptr, "SIMPLE", simple, comm, status); } else { /* write IMAGE extension header */ strcpy(comm, "IMAGE extension"); ffpkys(fptr, "XTENSION", "IMAGE", comm, status); } longbitpix = bitpix; /* test for the 3 special cases that represent unsigned integers */ if (longbitpix == USHORT_IMG) longbitpix = SHORT_IMG; else if (longbitpix == ULONG_IMG) longbitpix = LONG_IMG; else if (longbitpix == ULONGLONG_IMG) longbitpix = LONGLONG_IMG; else if (longbitpix == SBYTE_IMG) longbitpix = BYTE_IMG; if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG && longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG) { snprintf(message,FLEN_ERRMSG, "Illegal value for BITPIX keyword: %d", bitpix); ffpmsg(message); return(*status = BAD_BITPIX); } strcpy(comm, "number of bits per data pixel"); if (ffpkyj(fptr, "BITPIX", longbitpix, comm, status) > 0) return(*status); if (naxis < 0 || naxis > 999) { snprintf(message,FLEN_ERRMSG, "Illegal value for NAXIS keyword: %d", naxis); ffpmsg(message); return(*status = BAD_NAXIS); } strcpy(comm, "number of data axes"); ffpkyj(fptr, "NAXIS", naxis, comm, status); strcpy(comm, "length of data axis "); for (ii = 0; ii < naxis; ii++) { if (naxes[ii] < 0) { snprintf(message,FLEN_ERRMSG, "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii])); ffpmsg(message); return(*status = BAD_NAXES); } snprintf(&comm[20], FLEN_COMMENT-20,"%d", ii + 1); ffkeyn("NAXIS", ii + 1, name, status); ffpkyj(fptr, name, naxes[ii], comm, status); } if ((fptr->Fptr)->curhdu == 0) /* the primary array */ { if (extend) { /* only write EXTEND keyword if value = true */ strcpy(comm, "FITS dataset may contain extensions"); ffpkyl(fptr, "EXTEND", extend, comm, status); } if (pcount < 0) { ffpmsg("pcount value is less than 0"); return(*status = BAD_PCOUNT); } else if (gcount < 1) { ffpmsg("gcount value is less than 1"); return(*status = BAD_GCOUNT); } else if (pcount > 0 || gcount > 1) { /* only write these keyword if non-standard values */ strcpy(comm, "random group records are present"); ffpkyl(fptr, "GROUPS", 1, comm, status); strcpy(comm, "number of random group parameters"); ffpkyj(fptr, "PCOUNT", pcount, comm, status); strcpy(comm, "number of random groups"); ffpkyj(fptr, "GCOUNT", gcount, comm, status); } /* write standard block of self-documentating comments */ ffprec(fptr, "COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy", status); ffprec(fptr, "COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H", status); } else /* an IMAGE extension */ { /* image extension; cannot have random groups */ if (pcount != 0) { ffpmsg("image extensions must have pcount = 0"); *status = BAD_PCOUNT; } else if (gcount != 1) { ffpmsg("image extensions must have gcount = 1"); *status = BAD_GCOUNT; } else { strcpy(comm, "required keyword; must = 0"); ffpkyj(fptr, "PCOUNT", 0, comm, status); strcpy(comm, "required keyword; must = 1"); ffpkyj(fptr, "GCOUNT", 1, comm, status); } } /* Write the BSCALE and BZERO keywords, if an unsigned integer image */ if (bitpix == USHORT_IMG) { strcpy(comm, "offset data range to that of unsigned short"); ffpkyg(fptr, "BZERO", 32768., 0, comm, status); strcpy(comm, "default scaling factor"); ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status); } else if (bitpix == ULONG_IMG) { strcpy(comm, "offset data range to that of unsigned long"); ffpkyg(fptr, "BZERO", 2147483648., 0, comm, status); strcpy(comm, "default scaling factor"); ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status); } else if (bitpix == ULONGLONG_IMG) { strcpy(card,"BZERO = 9223372036854775808 / offset data range to that of unsigned long long"); ffprec(fptr, card, status); strcpy(comm, "default scaling factor"); ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status); } else if (bitpix == SBYTE_IMG) { strcpy(comm, "offset data range to that of signed byte"); ffpkyg(fptr, "BZERO", -128., 0, comm, status); strcpy(comm, "default scaling factor"); ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffphtb(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of row in the table */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ long *tbcol, /* I - byte offset in row to each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnmx, /* I - value of EXTNAME keyword, if any */ int *status) /* IO - error status */ /* Put required Header keywords into the ASCII TaBle: */ { int ii, ncols, gotmem = 0; long rowlen; /* must be 'long' because it is passed to ffgabc */ char tfmt[30], name[FLEN_KEYWORD], comm[FLEN_COMMENT], extnm[FLEN_VALUE]; if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (*status > 0) return(*status); else if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) return(*status = HEADER_NOT_EMPTY); else if (naxis1 < 0) return(*status = NEG_WIDTH); else if (naxis2 < 0) return(*status = NEG_ROWS); else if (tfields < 0 || tfields > 999) return(*status = BAD_TFIELDS); extnm[0] = '\0'; if (extnmx) strncat(extnm, extnmx, FLEN_VALUE-1); rowlen = (long) naxis1; if (!tbcol || !tbcol[0] || (!naxis1 && tfields)) /* spacing not defined? */ { /* allocate mem for tbcol; malloc can have problems allocating small */ /* arrays, so allocate at least 20 bytes */ ncols = maxvalue(5, tfields); tbcol = (long *) calloc(ncols, sizeof(long)); if (tbcol) { gotmem = 1; /* calculate width of a row and starting position of each column. */ /* Each column will be separated by 1 blank space */ ffgabc(tfields, tform, 1, &rowlen, tbcol, status); } } ffpkys(fptr, "XTENSION", "TABLE", "ASCII table extension", status); ffpkyj(fptr, "BITPIX", 8, "8-bit ASCII characters", status); ffpkyj(fptr, "NAXIS", 2, "2-dimensional ASCII table", status); ffpkyj(fptr, "NAXIS1", rowlen, "width of table in characters", status); ffpkyj(fptr, "NAXIS2", naxis2, "number of rows in table", status); ffpkyj(fptr, "PCOUNT", 0, "no group parameters (required keyword)", status); ffpkyj(fptr, "GCOUNT", 1, "one data group (required keyword)", status); ffpkyj(fptr, "TFIELDS", tfields, "number of fields in each row", status); for (ii = 0; ii < tfields; ii++) /* loop over every column */ { if ( *(ttype[ii]) ) /* optional TTYPEn keyword */ { snprintf(comm, FLEN_COMMENT,"label for field %3d", ii + 1); ffkeyn("TTYPE", ii + 1, name, status); ffpkys(fptr, name, ttype[ii], comm, status); } if (tbcol[ii] < 1 || tbcol[ii] > rowlen) *status = BAD_TBCOL; snprintf(comm, FLEN_COMMENT,"beginning column of field %3d", ii + 1); ffkeyn("TBCOL", ii + 1, name, status); ffpkyj(fptr, name, tbcol[ii], comm, status); if (strlen(tform[ii]) > 29) { ffpmsg("Error: ASCII table TFORM code is too long (ffphtb)"); *status = BAD_TFORM; break; } strcpy(tfmt, tform[ii]); /* required TFORMn keyword */ ffupch(tfmt); ffkeyn("TFORM", ii + 1, name, status); ffpkys(fptr, name, tfmt, "Fortran-77 format of field", status); if (tunit) { if (tunit[ii] && *(tunit[ii]) ) /* optional TUNITn keyword */ { ffkeyn("TUNIT", ii + 1, name, status); ffpkys(fptr, name, tunit[ii], "physical unit of field", status) ; } } if (*status > 0) break; /* abort loop on error */ } if (extnm[0]) /* optional EXTNAME keyword */ ffpkys(fptr, "EXTNAME", extnm, "name of this ASCII table extension", status); if (*status > 0) ffpmsg("Failed to write ASCII table header keywords (ffphtb)"); if (gotmem) free(tbcol); return(*status); } /*--------------------------------------------------------------------------*/ int ffphbn(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnmx, /* I - value of EXTNAME keyword, if any */ LONGLONG pcount, /* I - size of the variable length heap area */ int *status) /* IO - error status */ /* Put required Header keywords into the Binary Table: */ { int ii, datatype, iread = 0; long repeat, width; LONGLONG naxis1; char tfmt[30], name[FLEN_KEYWORD], comm[FLEN_COMMENT], extnm[FLEN_VALUE]; char *cptr, card[FLEN_CARD]; tcolumn *colptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) return(*status = HEADER_NOT_EMPTY); else if (naxis2 < 0) return(*status = NEG_ROWS); else if (pcount < 0) return(*status = BAD_PCOUNT); else if (tfields < 0 || tfields > 999) return(*status = BAD_TFIELDS); extnm[0] = '\0'; if (extnmx) strncat(extnm, extnmx, FLEN_VALUE-1); ffpkys(fptr, "XTENSION", "BINTABLE", "binary table extension", status); ffpkyj(fptr, "BITPIX", 8, "8-bit bytes", status); ffpkyj(fptr, "NAXIS", 2, "2-dimensional binary table", status); naxis1 = 0; for (ii = 0; ii < tfields; ii++) /* sum the width of each field */ { ffbnfm(tform[ii], &datatype, &repeat, &width, status); if (datatype == TSTRING) naxis1 += repeat; /* one byte per char */ else if (datatype == TBIT) naxis1 += (repeat + 7) / 8; else if (datatype > 0) naxis1 += repeat * (datatype / 10); else if (tform[ii][0] == 'P' || tform[ii][1] == 'P'|| tform[ii][0] == 'p' || tform[ii][1] == 'p') /* this is a 'P' variable length descriptor (neg. datatype) */ naxis1 += 8; else /* this is a 'Q' variable length descriptor (neg. datatype) */ naxis1 += 16; if (*status > 0) break; /* abort loop on error */ } ffpkyj(fptr, "NAXIS1", naxis1, "width of table in bytes", status); ffpkyj(fptr, "NAXIS2", naxis2, "number of rows in table", status); /* the initial value of PCOUNT (= size of the variable length array heap) should always be zero. If any variable length data is written, then the value of PCOUNT will be updated when the HDU is closed */ ffpkyj(fptr, "PCOUNT", 0, "size of special data area", status); ffpkyj(fptr, "GCOUNT", 1, "one data group (required keyword)", status); ffpkyj(fptr, "TFIELDS", tfields, "number of fields in each row", status); for (ii = 0; ii < tfields; ii++) /* loop over every column */ { if ( *(ttype[ii]) ) /* optional TTYPEn keyword */ { snprintf(comm, FLEN_COMMENT,"label for field %3d", ii + 1); ffkeyn("TTYPE", ii + 1, name, status); ffpkys(fptr, name, ttype[ii], comm, status); } if (strlen(tform[ii]) > 29) { ffpmsg("Error: BIN table TFORM code is too long (ffphbn)"); *status = BAD_TFORM; break; } strcpy(tfmt, tform[ii]); /* required TFORMn keyword */ ffupch(tfmt); ffkeyn("TFORM", ii + 1, name, status); strcpy(comm, "data format of field"); ffbnfm(tfmt, &datatype, &repeat, &width, status); if (datatype == TSTRING) { strcat(comm, ": ASCII Character"); /* Do sanity check to see if an ASCII table format was used, */ /* e.g., 'A8' instead of '8A', or a bad unit width eg '8A9'. */ /* Don't want to return an error status, so write error into */ /* the keyword comment. */ cptr = strchr(tfmt,'A'); cptr++; if (cptr) iread = sscanf(cptr,"%ld", &width); if (iread == 1 && (width > repeat)) { if (repeat == 1) strcpy(comm, "ERROR?? USING ASCII TABLE SYNTAX BY MISTAKE??"); else strcpy(comm, "rAw FORMAT ERROR! UNIT WIDTH w > COLUMN WIDTH r"); } } else if (datatype == TBIT) strcat(comm, ": BIT"); else if (datatype == TBYTE) strcat(comm, ": BYTE"); else if (datatype == TLOGICAL) strcat(comm, ": 1-byte LOGICAL"); else if (datatype == TSHORT) strcat(comm, ": 2-byte INTEGER"); else if (datatype == TUSHORT) strcat(comm, ": 2-byte INTEGER"); else if (datatype == TLONG) strcat(comm, ": 4-byte INTEGER"); else if (datatype == TLONGLONG) strcat(comm, ": 8-byte INTEGER"); else if (datatype == TULONG) strcat(comm, ": 4-byte INTEGER"); else if (datatype == TULONGLONG) strcat(comm, ": 8-byte INTEGER"); else if (datatype == TFLOAT) strcat(comm, ": 4-byte REAL"); else if (datatype == TDOUBLE) strcat(comm, ": 8-byte DOUBLE"); else if (datatype == TCOMPLEX) strcat(comm, ": COMPLEX"); else if (datatype == TDBLCOMPLEX) strcat(comm, ": DOUBLE COMPLEX"); else if (datatype < 0) strcat(comm, ": variable length array"); if (abs(datatype) == TSBYTE) /* signed bytes */ { /* Replace the 'S' with an 'B' in the TFORMn code */ cptr = tfmt; while (*cptr != 'S') cptr++; *cptr = 'B'; ffpkys(fptr, name, tfmt, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", ii + 1, name, status); strcpy(comm, "offset for signed bytes"); ffpkyg(fptr, name, -128., 0, comm, status); ffkeyn("TSCAL", ii + 1, name, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, name, 1., 0, comm, status); } else if (abs(datatype) == TUSHORT) { /* Replace the 'U' with an 'I' in the TFORMn code */ cptr = tfmt; while (*cptr != 'U') cptr++; *cptr = 'I'; ffpkys(fptr, name, tfmt, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", ii + 1, name, status); strcpy(comm, "offset for unsigned integers"); ffpkyg(fptr, name, 32768., 0, comm, status); ffkeyn("TSCAL", ii + 1, name, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, name, 1., 0, comm, status); } else if (abs(datatype) == TULONG) { /* Replace the 'V' with an 'J' in the TFORMn code */ cptr = tfmt; while (*cptr != 'V') cptr++; *cptr = 'J'; ffpkys(fptr, name, tfmt, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", ii + 1, name, status); strcpy(comm, "offset for unsigned integers"); ffpkyg(fptr, name, 2147483648., 0, comm, status); ffkeyn("TSCAL", ii + 1, name, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, name, 1., 0, comm, status); } else if (abs(datatype) == TULONGLONG) { /* Replace the 'W' with an 'K' in the TFORMn code */ cptr = tfmt; while (*cptr != 'W') cptr++; *cptr = 'K'; ffpkys(fptr, name, tfmt, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", ii + 1, card, status); strcat(card, " "); /* make sure name is >= 8 chars long */ *(card+8) = '\0'; strcat(card, "= 9223372036854775808 / offset for unsigned integers"); fits_write_record(fptr, card, status); ffkeyn("TSCAL", ii + 1, name, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, name, 1., 0, comm, status); } else { ffpkys(fptr, name, tfmt, comm, status); } if (tunit) { if (tunit[ii] && *(tunit[ii]) ) /* optional TUNITn keyword */ { ffkeyn("TUNIT", ii + 1, name, status); ffpkys(fptr, name, tunit[ii], "physical unit of field", status); } } if (*status > 0) break; /* abort loop on error */ } if (extnm[0]) /* optional EXTNAME keyword */ ffpkys(fptr, "EXTNAME", extnm, "name of this binary table extension", status); if (*status > 0) ffpmsg("Failed to write binary table header keywords (ffphbn)"); return(*status); } /*--------------------------------------------------------------------------*/ int ffphext(fitsfile *fptr, /* I - FITS file pointer */ const char *xtensionx, /* I - value for the XTENSION keyword */ int bitpix, /* I - value for the BIXPIX keyword */ int naxis, /* I - value for the NAXIS keyword */ long naxes[], /* I - value for the NAXISn keywords */ LONGLONG pcount, /* I - value for the PCOUNT keyword */ LONGLONG gcount, /* I - value for the GCOUNT keyword */ int *status) /* IO - error status */ /* Put required Header keywords into a conforming extension: */ { char message[FLEN_ERRMSG],comm[81], name[20], xtension[FLEN_VALUE]; int ii; if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (*status > 0) return(*status); else if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) return(*status = HEADER_NOT_EMPTY); if (naxis < 0 || naxis > 999) { snprintf(message,FLEN_ERRMSG, "Illegal value for NAXIS keyword: %d", naxis); ffpmsg(message); return(*status = BAD_NAXIS); } xtension[0] = '\0'; strncat(xtension, xtensionx, FLEN_VALUE-1); ffpkys(fptr, "XTENSION", xtension, "extension type", status); ffpkyj(fptr, "BITPIX", bitpix, "number of bits per data pixel", status); ffpkyj(fptr, "NAXIS", naxis, "number of data axes", status); strcpy(comm, "length of data axis "); for (ii = 0; ii < naxis; ii++) { if (naxes[ii] < 0) { snprintf(message,FLEN_ERRMSG, "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii])); ffpmsg(message); return(*status = BAD_NAXES); } snprintf(&comm[20], 61, "%d", ii + 1); ffkeyn("NAXIS", ii + 1, name, status); ffpkyj(fptr, name, naxes[ii], comm, status); } ffpkyj(fptr, "PCOUNT", pcount, " ", status); ffpkyj(fptr, "GCOUNT", gcount, " ", status); if (*status > 0) ffpmsg("Failed to write extension header keywords (ffphext)"); return(*status); } /*--------------------------------------------------------------------------*/ int ffi2c(LONGLONG ival, /* I - value to be converted to a string */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status */ /* convert value to a null-terminated formatted string. */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); cval[0] = '\0'; #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ if (sprintf(cval, "%I64d", ival) < 0) #elif (USE_LL_SUFFIX == 1) if (sprintf(cval, "%lld", ival) < 0) #else if (sprintf(cval, "%ld", ival) < 0) #endif { ffpmsg("Error in ffi2c converting integer to string"); *status = BAD_I2C; } return(*status); } /*--------------------------------------------------------------------------*/ int ffu2c(ULONGLONG ival, /* I - value to be converted to a string */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status */ /* convert value to a null-terminated formatted string. */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); cval[0] = '\0'; #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ if (sprintf(cval, "%I64u", ival) < 0) #elif (USE_LL_SUFFIX == 1) if (sprintf(cval, "%llu", ival) < 0) #else if (sprintf(cval, "%lu", ival) < 0) #endif { ffpmsg("Error in ffu2c converting integer to string"); *status = BAD_I2C; } return(*status); } /*--------------------------------------------------------------------------*/ int ffl2c(int lval, /* I - value to be converted to a string */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status ) */ /* convert logical value to a null-terminated formatted string. If the input value == 0, then the output character is the letter F, else the output character is the letter T. The output string is null terminated. */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (lval) strcpy(cval,"T"); else strcpy(cval,"F"); return(*status); } /*--------------------------------------------------------------------------*/ int ffs2c(const char *instr, /* I - null terminated input string */ char *outstr, /* O - null terminated quoted output string */ int *status) /* IO - error status */ /* convert an input string to a quoted string. Leading spaces are significant. FITS string keyword values must be at least 8 chars long so pad out string with spaces if necessary. (*** This 8 char requirement is now obsolete. See ffs2c_nopad for an alternative ***) Example: km/s ==> 'km/s ' Single quote characters in the input string will be replace by two single quote characters. e.g., o'brian ==> 'o''brian' */ { size_t len, ii, jj; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (!instr) /* a null input pointer?? */ { strcpy(outstr, "''"); /* a null FITS string */ return(*status); } outstr[0] = '\''; /* start output string with a quote */ len = strlen(instr); if (len > 68) len = 68; /* limit input string to 68 chars */ for (ii=0, jj=1; ii < len && jj < 69; ii++, jj++) { outstr[jj] = instr[ii]; /* copy each char from input to output */ if (instr[ii] == '\'') { jj++; outstr[jj]='\''; /* duplicate any apostrophies in the input */ } } for (; jj < 9; jj++) /* pad string so it is at least 8 chars long */ outstr[jj] = ' '; if (jj == 70) /* only occurs if the last char of string was a quote */ outstr[69] = '\0'; else { outstr[jj] = '\''; /* append closing quote character */ outstr[jj+1] = '\0'; /* terminate the string */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffs2c_nopad(const char *instr, /* I - null terminated input string */ char *outstr, /* O - null terminated quoted output string */ int *status) /* IO - error status */ /* This performs identically to ffs2c except that it won't pad output strings to make them a minimum of 8 chars long. The requirement that FITS keyword string values be 8 characters is now obsolete (except for "XTENSION" keyword), but for backwards compatibility we'll keep ffs2c the way it is. A better solution would be to add another argument to ffs2c for 'pad' or 'nopad', but it is called from many other places in Heasoft outside of CFITSIO. */ { size_t len, ii, jj; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (!instr) /* a null input pointer?? */ { strcpy(outstr, "''"); /* a null FITS string */ return(*status); } outstr[0] = '\''; /* start output string with a quote */ len = strlen(instr); if (len > 68) len = 68; /* limit input string to 68 chars */ for (ii=0, jj=1; ii < len && jj < 69; ii++, jj++) { outstr[jj] = instr[ii]; /* copy each char from input to output */ if (instr[ii] == '\'') { jj++; outstr[jj]='\''; /* duplicate any apostrophies in the input */ } } if (jj == 70) /* only occurs if the last char of string was a quote */ outstr[69] = '\0'; else { outstr[jj] = '\''; /* append closing quote character */ outstr[jj+1] = '\0'; /* terminate the string */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffr2f(float fval, /* I - value to be converted to a string */ int decim, /* I - number of decimal places to display */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status */ /* convert float value to a null-terminated F format string */ { char *cptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); cval[0] = '\0'; if (decim < 0) { ffpmsg("Error in ffr2f: no. of decimal places < 0"); return(*status = BAD_DECIM); } if (snprintf(cval, FLEN_VALUE,"%.*f", decim, fval) < 0) { ffpmsg("Error in ffr2f converting float to string"); *status = BAD_F2C; } /* replace comma with a period (e.g. in French locale) */ if ( (cptr = strchr(cval, ','))) *cptr = '.'; /* test if output string is 'NaN', 'INDEF', or 'INF' */ if (strchr(cval, 'N')) { ffpmsg("Error in ffr2f: float value is a NaN or INDEF"); *status = BAD_F2C; } return(*status); } /*--------------------------------------------------------------------------*/ int ffr2e(float fval, /* I - value to be converted to a string */ int decim, /* I - number of decimal places to display */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status */ /* convert float value to a null-terminated exponential format string */ { char *cptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); cval[0] = '\0'; if (decim < 0) { /* use G format if decim is negative */ if ( snprintf(cval, FLEN_VALUE,"%.*G", -decim, fval) < 0) { ffpmsg("Error in ffr2e converting float to string"); *status = BAD_F2C; } else { /* test if E format was used, and there is no displayed decimal */ /* If locale is French, decimal will be a comma. So look for that too. */ if ( !strchr(cval, '.') && !strchr(cval, ',') && strchr(cval,'E') ) { /* reformat value with a decimal point and single zero */ if ( snprintf(cval, FLEN_VALUE,"%.1E", fval) < 0) { ffpmsg("Error in ffr2e converting float to string"); *status = BAD_F2C; } /* convert French locale comma to a decimal point.*/ if ((cptr = strchr(cval, ','))) *cptr = '.'; return(*status); } } } else { if ( snprintf(cval, FLEN_VALUE,"%.*E", decim, fval) < 0) { ffpmsg("Error in ffr2e converting float to string"); *status = BAD_F2C; } } if (*status <= 0) { /* replace comma with a period (e.g. in French locale) */ if ( (cptr = strchr(cval, ','))) *cptr = '.'; /* test if output string is 'NaN', 'INDEF', or 'INF' */ if (strchr(cval, 'N')) { ffpmsg("Error in ffr2e: float value is a NaN or INDEF"); *status = BAD_F2C; } else if ( !strchr(cval, '.') && !strchr(cval,'E') && strlen(cval) < FLEN_VALUE-1 ) { /* add decimal point if necessary to distinquish from integer */ strcat(cval, "."); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffd2f(double dval, /* I - value to be converted to a string */ int decim, /* I - number of decimal places to display */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status */ /* convert double value to a null-terminated F format string */ { char *cptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); cval[0] = '\0'; if (decim < 0) { ffpmsg("Error in ffd2f: no. of decimal places < 0"); return(*status = BAD_DECIM); } if (snprintf(cval, FLEN_VALUE,"%.*f", decim, dval) < 0) { ffpmsg("Error in ffd2f converting double to string"); *status = BAD_F2C; } /* replace comma with a period (e.g. in French locale) */ if ( (cptr = strchr(cval, ','))) *cptr = '.'; /* test if output string is 'NaN', 'INDEF', or 'INF' */ if (strchr(cval, 'N')) { ffpmsg("Error in ffd2f: double value is a NaN or INDEF"); *status = BAD_F2C; } return(*status); } /*--------------------------------------------------------------------------*/ int ffd2e(double dval, /* I - value to be converted to a string */ int decim, /* I - number of decimal places to display */ char *cval, /* O - character string representation of the value */ int *status) /* IO - error status */ /* convert double value to a null-terminated exponential format string. */ { char *cptr; if (*status > 0) /* inherit input status value if > 0 */ return(*status); cval[0] = '\0'; if (decim < 0) { /* use G format if decim is negative */ if ( snprintf(cval, FLEN_VALUE,"%.*G", -decim, dval) < 0) { ffpmsg("Error in ffd2e converting float to string"); *status = BAD_F2C; } else { /* test if E format was used, and there is no displayed decimal */ /* If locale is French, decimal will be a comma. So look for that too. */ if ( !strchr(cval, '.') && !strchr(cval, ',') && strchr(cval,'E') ) { /* reformat value with a decimal point and single zero */ if ( snprintf(cval, FLEN_VALUE,"%.1E", dval) < 0) { ffpmsg("Error in ffd2e converting float to string"); *status = BAD_F2C; } /* convert French locale comma to a decimal point.*/ if ((cptr = strchr(cval, ','))) *cptr = '.'; return(*status); } } } else { if ( snprintf(cval, FLEN_VALUE,"%.*E", decim, dval) < 0) { ffpmsg("Error in ffd2e converting float to string"); *status = BAD_F2C; } } if (*status <= 0) { /* replace comma with a period (e.g. in French locale) */ if ( (cptr = strchr(cval, ','))) *cptr = '.'; /* test if output string is 'NaN', 'INDEF', or 'INF' */ if (strchr(cval, 'N')) { ffpmsg("Error in ffd2e: double value is a NaN or INDEF"); *status = BAD_F2C; } else if ( !strchr(cval, '.') && !strchr(cval,'E') && strlen(cval) < FLEN_VALUE-1) { /* add decimal point if necessary to distinquish from integer */ strcat(cval, "."); } } return(*status); } cfitsio-4.3.1/getcolj.c0000644000225700000360000044140113472024437014252 0ustar cagordonlhea/* This file, getcolj.c, contains routines that read data elements from */ /* a FITS image or table, with long data type. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgpvj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long nulval, /* I - value for undefined pixels */ long *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; char cdummy; int nullcheck = 1; long nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclj(fptr, 2, row, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpfj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long *array, /* O - array of values that are returned */ char *nularray, /* O - array of null pixel flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any undefined pixels in the returned array will be set = 0 and the corresponding nularray value will be set = 1. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; int nullcheck = 2; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem, nullcheck, NULL, array, nularray, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclj(fptr, 2, row, firstelem, nelem, 1, 2, 0L, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg2dj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ long *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { /* call the 3D reading routine, with the 3rd dimension = 1 */ ffg3dj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg3dj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ long *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 3-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { long tablerow, ii, jj; char cdummy; int nullcheck = 1; long inc[] = {1,1,1}; LONGLONG fpixel[] = {1,1,1}, nfits, narray; LONGLONG lpixel[3], nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = ncols; lpixel[1] = nrows; lpixel[2] = naxis3; nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TLONG, fpixel, lpixel, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so read all at once */ ffgclj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to read */ narray = 0; /* next pixel in output array to be filled */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* reading naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffgclj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval, &array[narray], &cdummy, anynul, status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsvj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ long nulval, /* I - value to set undefined pixels */ long *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dir[9]; long nelem, nultyp, ninc, numcol; LONGLONG felem, dsize[10], blcll[9], trcll[9]; int hdutype, anyf; char ldummy, msg[FLEN_ERRMSG]; int nullcheck = 1; long nullvalue; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TLONG, blcll, trcll, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 1; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; dir[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { if (hdutype == IMAGE_HDU) { dir[ii] = -1; } else { snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; dsize[ii] = dsize[ii] * dir[ii]; } dsize[naxis] = dsize[naxis] * dir[naxis]; if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1; ninc = incr[0] * dir[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8]) { for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7]) { for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6]) { for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5]) { for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4]) { for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3]) { for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2]) { for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1]) { felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] + (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] + (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8]; if ( ffgclj(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &ldummy, &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsfj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ long *array, /* O - array to be filled and returned */ char *flagval, /* O - set to 1 if corresponding value is null */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dsize[10]; LONGLONG blcll[9], trcll[9]; long felem, nelem, nultyp, ninc, numcol; long nulval = 0; int hdutype, anyf; char msg[FLEN_ERRMSG]; int nullcheck = 2; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } fits_read_compressed_img(fptr, TLONG, blcll, trcll, inc, nullcheck, NULL, array, flagval, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 2; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; } if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0] - str[0]) / inc[0] + 1; ninc = incr[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8]) { for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7]) { for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6]) { for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5]) { for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4]) { for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3]) { for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2]) { for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1]) { felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] + (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] + (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8]; if ( ffgclj(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &flagval[i0], &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffggpj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long firstelem, /* I - first vector element to read (1 = 1st) */ long nelem, /* I - number of values to read */ long *array, /* O - array of values that are returned */ int *status) /* IO - error status */ /* Read an array of group parameters from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). */ { long row; int idummy; char cdummy; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclj(fptr, 1, row, firstelem, nelem, 1, 1, 0L, array, &cdummy, &idummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcvj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long nulval, /* I - value for null pixels */ long *array, /* O - array of values that are read */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = 0 in which case no checks for undefined pixels will be made. */ { char cdummy; ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long *array, /* O - array of values that are read */ char *nularray, /* O - array of flags: 1 if null pixel; else 0 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Nularray will be set = 1 if the corresponding array pixel is undefined, otherwise nularray will = 0. */ { long dummy = 0; ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgclj( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long elemincre, /* I - pixel increment; e.g., 2 = every other */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ long nulval, /* I - value for null pixels if nultyp = 1 */ long *array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer be a virtual column in a 1 or more grouped FITS primary array or image extension. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The output array of values will be converted from the datatype of the column and will be scaled by the FITS TSCALn and TZEROn values if necessary. */ { double scale, zero, power = 1., dtemp; int tcode, maxelem2, hdutype, xcode, decimals; long twidth, incre; long ii, xwidth, ntodo; int convert, nulcheck, readcheck = 0; LONGLONG repeat, startpos, elemnum, readptr, tnull; LONGLONG rowlen, rownum, remain, next, rowincre, maxelem; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value if reading from ASCII table */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (elemincre < 0) readcheck = -1; /* don't do range checking in this case */ if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero, tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 ) return(*status); maxelem = maxelem2; incre *= elemincre; /* multiply incre to just get every nth pixel */ if (tcode == TSTRING) /* setup for ASCII tables */ { /* get the number of implied decimal places if no explicit decmal point */ ffasfm(tform, &xcode, &xwidth, &decimals, status); for(ii = 0; ii < decimals; ii++) power *= 10.; } /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (tcode%10 == 1 && /* if reading an integer column, and */ tnull == NULL_UNDEFINED) /* if a null value is not defined, */ nulcheck = 0; /* then do not check for null values. */ else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TBYTE && (tnull > 255 || tnull < 0) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED) nulcheck = 0; /*----------------------------------------------------------------------*/ /* If FITS column and output data array have same datatype, then we do */ /* not need to use a temporary buffer to store intermediate datatype. */ /*----------------------------------------------------------------------*/ convert = 1; if ((tcode == TLONG) && (LONGSIZE == 32)) /* Special Case: */ { /* no type convertion required, so read */ /* data directly into output buffer. */ if (nelem < (LONGLONG)INT32_MAX/4) { maxelem = nelem; } else { maxelem = INT32_MAX/4; } if (nulcheck == 0 && scale == 1. && zero == 0. ) convert = 0; /* no need to scale data or find nulls */ } /*---------------------------------------------------------------------*/ /* Now read the pixels from the FITS column. If the column does not */ /* have the same datatype as the output array, then we have to read */ /* the raw values into a temporary buffer (of limited size). In */ /* the case of a vector colum read only 1 vector of values at a time */ /* then skip to the next row if more values need to be read. */ /* After reading the raw values, then call the fffXXYY routine to (1) */ /* test for undefined values, (2) convert the datatype if necessary, */ /* and (3) scale the values by the FITS TSCALn and TZEROn linear */ /* scaling parameters. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to read */ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to read at one time to the number that will fit in the buffer or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); if (elemincre >= 0) { ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1)); } else { ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1)); } readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre)); switch (tcode) { case (TLONG): if (LONGSIZE == 32) { ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next], status); if (convert) fffi4i4((INT32BIT *) &array[next], ntodo, scale, zero, nulcheck, (INT32BIT) tnull, nulval, &nularray[next], anynul, &array[next], status); } else { /* case where sizeof(long) = 8 */ ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer, status); if (convert) fffi4i4((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, (INT32BIT) tnull, nulval, &nularray[next], anynul, &array[next], status); } break; case (TLONGLONG): ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status); fffi8i4((LONGLONG *) buffer, ntodo, scale, zero, nulcheck, tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TBYTE): ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer, status); fffi1i4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, (unsigned char) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TSHORT): ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status); fffi2i4((short *) buffer, ntodo, scale, zero, nulcheck, (short) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TFLOAT): ffgr4b(fptr, readptr, ntodo, incre, (float *) buffer, status); fffr4i4((float *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TDOUBLE): ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status); fffr8i4((double *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TSTRING): ffmbyt(fptr, readptr, REPORT_EOF, status); if (incre == twidth) /* contiguous bytes */ ffgbyt(fptr, ntodo * twidth, buffer, status); else ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); fffstri4((char *) buffer, ntodo, scale, zero, twidth, power, nulcheck, snull, nulval, &nularray[next], anynul, &array[next], status); break; default: /* error trap for invalid column format */ snprintf(message, FLEN_ERRMSG, "Cannot read numbers from column %d which has format %s", colnum, tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; if (hdutype > 0) snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from column %d (ffgclj).", dtemp+1., dtemp+ntodo, colnum); else snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from image (ffgclj).", dtemp+1., dtemp+ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum = elemnum + (ntodo * elemincre); if (elemnum >= repeat) /* completed a row; start on later row */ { rowincre = elemnum / repeat; rownum += rowincre; elemnum = elemnum - (rowincre * repeat); } else if (elemnum < 0) /* completed a row; start on a previous row */ { rowincre = (-elemnum - 1) / repeat + 1; rownum -= rowincre; elemnum = (rowincre * repeat) + elemnum; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while reading FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int fffi1i4(unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) output[ii] = (long) input[ii]; /* copy input to output */ } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (long) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi2i4(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) output[ii] = (long) input[ii]; /* copy input to output */ } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (long) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi4i4(INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { output[ii] = (long) input[ii]; /* copy input to output */ } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi8i4(LONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG tnull, /* I - value of FITS TNULLn keyword if any */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; ULONGLONG ulltemp; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > LONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else { output[ii] = (long) ulltemp; } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < LONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (input[ii] > LONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > LONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else { output[ii] = (long) ulltemp; } } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < LONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (input[ii] > LONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr4i4(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (input[ii] > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (input[ii] > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (zero > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr8i4(double *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (input[ii] > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (input[ii] > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (zero > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffstri4(char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ long twidth, /* I - width of each substring of chars */ double implipower, /* I - power of 10 of implied decimal */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ char *snull, /* I - value of FITS null string, if any */ long nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ long *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to snull. If nullcheck= 0, then no special checking for nulls is performed. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { int nullen; long ii; double dvalue; char *cstring, message[FLEN_ERRMSG]; char *cptr, *tpos; char tempstore, chrzero = '0'; double val, power; int exponent, sign, esign, decpt; nullen = strlen(snull); cptr = input; /* pointer to start of input string */ for (ii = 0; ii < ntodo; ii++) { cstring = cptr; /* temporarily insert a null terminator at end of the string */ tpos = cptr + twidth; tempstore = *tpos; *tpos = 0; /* check if null value is defined, and if the */ /* column string is identical to the null string */ if (snull[0] != ASCII_NULL_UNDEFINED && !strncmp(snull, cptr, nullen) ) { if (nullcheck) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } cptr += twidth; } else { /* value is not the null value, so decode it */ /* remove any embedded blank characters from the string */ decpt = 0; sign = 1; val = 0.; power = 1.; exponent = 0; esign = 1; while (*cptr == ' ') /* skip leading blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for leading sign */ { if (*cptr == '-') sign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and value */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } if (*cptr == '.' || *cptr == ',') /* check for decimal point */ { decpt = 1; /* set flag to show there was a decimal point */ cptr++; while (*cptr == ' ') /* skip any blanks */ cptr++; while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ power = power * 10.; cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } } if (*cptr == 'E' || *cptr == 'D') /* check for exponent */ { cptr++; while (*cptr == ' ') /* skip blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for exponent sign */ { if (*cptr == '-') esign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and exp */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { exponent = exponent * 10 + *cptr - chrzero; /* accumulate exp */ cptr++; while (*cptr == ' ') /* skip embedded blanks */ cptr++; } } if (*cptr != 0) /* should end up at the null terminator */ { snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table"); ffpmsg(message); snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring); ffpmsg(message); /* restore the char that was overwritten by the null */ *tpos = tempstore; return(*status = BAD_C2D); } if (!decpt) /* if no explicit decimal, use implied */ power = implipower; dvalue = (sign * val / power) * pow(10., (double) (esign * exponent)); dvalue = dvalue * scale + zero; /* apply the scaling */ if (dvalue < DLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONG_MIN; } else if (dvalue > DLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONG_MAX; } else output[ii] = (long) dvalue; } /* restore the char that was overwritten by the null */ *tpos = tempstore; } return(*status); } /* ======================================================================== */ /* the following routines support the 'long long' data type */ /* ======================================================================== */ /*--------------------------------------------------------------------------*/ int ffgpvjj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ LONGLONG nulval, /* I - value for undefined pixels */ LONGLONG *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; char cdummy; int nullcheck = 1; LONGLONG nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgcljj(fptr, 2, row, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpfjj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ LONGLONG *array, /* O - array of values that are returned */ char *nularray, /* O - array of null pixel flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any undefined pixels in the returned array will be set = 0 and the corresponding nularray value will be set = 1. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; int nullcheck = 2; LONGLONG dummy = 0; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem, nullcheck, NULL, array, nularray, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgcljj(fptr, 2, row, firstelem, nelem, 1, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg2djj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG nulval ,/* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG *array,/* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { /* call the 3D reading routine, with the 3rd dimension = 1 */ ffg3djj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg3djj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ LONGLONG *array,/* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 3-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { long tablerow, ii, jj; char cdummy; int nullcheck = 1; long inc[] = {1,1,1}; LONGLONG fpixel[] = {1,1,1}, nfits, narray; LONGLONG lpixel[3]; LONGLONG nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = ncols; lpixel[1] = nrows; lpixel[2] = naxis3; nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TLONGLONG, fpixel, lpixel, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so read all at once */ ffgcljj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to read */ narray = 0; /* next pixel in output array to be filled */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* reading naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffgcljj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval, &array[narray], &cdummy, anynul, status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsvjj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ LONGLONG nulval,/* I - value to set undefined pixels */ LONGLONG *array,/* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dir[9]; long nelem, nultyp, ninc, numcol; LONGLONG felem, dsize[10], blcll[9], trcll[9]; int hdutype, anyf; char ldummy, msg[FLEN_ERRMSG]; int nullcheck = 1; LONGLONG nullvalue; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TLONGLONG, blcll, trcll, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 1; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; dir[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { if (hdutype == IMAGE_HDU) { dir[ii] = -1; } else { snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; dsize[ii] = dsize[ii] * dir[ii]; } dsize[naxis] = dsize[naxis] * dir[naxis]; if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1; ninc = incr[0] * dir[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8]) { for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7]) { for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6]) { for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5]) { for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4]) { for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3]) { for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2]) { for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1]) { felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] + (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] + (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8]; if ( ffgcljj(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &ldummy, &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsfjj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ LONGLONG *array,/* O - array to be filled and returned */ char *flagval, /* O - set to 1 if corresponding value is null */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dsize[10]; LONGLONG blcll[9], trcll[9]; long felem, nelem, nultyp, ninc, numcol; LONGLONG nulval = 0; int hdutype, anyf; char msg[FLEN_ERRMSG]; int nullcheck = 2; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } fits_read_compressed_img(fptr, TLONGLONG, blcll, trcll, inc, nullcheck, NULL, array, flagval, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 2; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; } if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0] - str[0]) / inc[0] + 1; ninc = incr[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8]) { for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7]) { for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6]) { for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5]) { for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4]) { for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3]) { for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2]) { for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1]) { felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] + (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] + (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8]; if ( ffgcljj(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &flagval[i0], &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffggpjj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long firstelem, /* I - first vector element to read (1 = 1st) */ long nelem, /* I - number of values to read */ LONGLONG *array, /* O - array of values that are returned */ int *status) /* IO - error status */ /* Read an array of group parameters from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). */ { long row; int idummy; char cdummy; LONGLONG dummy = 0; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgcljj(fptr, 1, row, firstelem, nelem, 1, 1, dummy, array, &cdummy, &idummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcvjj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ LONGLONG nulval, /* I - value for null pixels */ LONGLONG *array, /* O - array of values that are read */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = 0 in which case no checks for undefined pixels will be made. */ { char cdummy; ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfjj(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ LONGLONG *array, /* O - array of values that are read */ char *nularray, /* O - array of flags: 1 if null pixel; else 0 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Nularray will be set = 1 if the corresponding array pixel is undefined, otherwise nularray will = 0. */ { LONGLONG dummy = 0; ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcljj( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long elemincre, /* I - pixel increment; e.g., 2 = every other */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ LONGLONG nulval, /* I - value for null pixels if nultyp = 1 */ LONGLONG *array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer be a virtual column in a 1 or more grouped FITS primary array or image extension. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The output array of values will be converted from the datatype of the column and will be scaled by the FITS TSCALn and TZEROn values if necessary. */ { double scale, zero, power = 1., dtemp; int tcode, maxelem2, hdutype, xcode, decimals; long twidth, incre; long ii, xwidth, ntodo; int convert, nulcheck, readcheck = 0; LONGLONG repeat, startpos, elemnum, readptr, tnull; LONGLONG rowlen, rownum, remain, next, rowincre, maxelem; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value if reading from ASCII table */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (elemincre < 0) readcheck = -1; /* don't do range checking in this case */ if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero, tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 ) return(*status); maxelem = maxelem2; incre *= elemincre; /* multiply incre to just get every nth pixel */ if (tcode == TSTRING) /* setup for ASCII tables */ { /* get the number of implied decimal places if no explicit decmal point */ ffasfm(tform, &xcode, &xwidth, &decimals, status); for(ii = 0; ii < decimals; ii++) power *= 10.; } /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (tcode%10 == 1 && /* if reading an integer column, and */ tnull == NULL_UNDEFINED) /* if a null value is not defined, */ nulcheck = 0; /* then do not check for null values. */ else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TBYTE && (tnull > 255 || tnull < 0) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED) nulcheck = 0; /*----------------------------------------------------------------------*/ /* If FITS column and output data array have same datatype, then we do */ /* not need to use a temporary buffer to store intermediate datatype. */ /*----------------------------------------------------------------------*/ convert = 1; if (tcode == TLONGLONG) /* Special Case: */ { /* no type convertion required, so read */ /* data directly into output buffer. */ if (nelem < (LONGLONG)INT32_MAX/8) { maxelem = nelem; } else { maxelem = INT32_MAX/8; } if (nulcheck == 0 && scale == 1. && zero == 0.) convert = 0; /* no need to scale data or find nulls */ } /*---------------------------------------------------------------------*/ /* Now read the pixels from the FITS column. If the column does not */ /* have the same datatype as the output array, then we have to read */ /* the raw values into a temporary buffer (of limited size). In */ /* the case of a vector colum read only 1 vector of values at a time */ /* then skip to the next row if more values need to be read. */ /* After reading the raw values, then call the fffXXYY routine to (1) */ /* test for undefined values, (2) convert the datatype if necessary, */ /* and (3) scale the values by the FITS TSCALn and TZEROn linear */ /* scaling parameters. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to read */ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to read at one time to the number that will fit in the buffer or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); if (elemincre >= 0) { ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1)); } else { ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1)); } readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre)); switch (tcode) { case (TLONGLONG): ffgi8b(fptr, readptr, ntodo, incre, (long *) &array[next], status); if (convert) fffi8i8((LONGLONG *) &array[next], ntodo, scale, zero, nulcheck, tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TLONG): ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer, status); fffi4i8((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, (INT32BIT) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TBYTE): ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer, status); fffi1i8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, (unsigned char) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TSHORT): ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status); fffi2i8((short *) buffer, ntodo, scale, zero, nulcheck, (short) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TFLOAT): ffgr4b(fptr, readptr, ntodo, incre, (float *) buffer, status); fffr4i8((float *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TDOUBLE): ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status); fffr8i8((double *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TSTRING): ffmbyt(fptr, readptr, REPORT_EOF, status); if (incre == twidth) /* contiguous bytes */ ffgbyt(fptr, ntodo * twidth, buffer, status); else ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); fffstri8((char *) buffer, ntodo, scale, zero, twidth, power, nulcheck, snull, nulval, &nularray[next], anynul, &array[next], status); break; default: /* error trap for invalid column format */ snprintf(message,FLEN_ERRMSG, "Cannot read numbers from column %d which has format %s", colnum, tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; if (hdutype > 0) snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from column %d (ffgclj).", dtemp+1., dtemp+ntodo, colnum); else snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from image (ffgclj).", dtemp+1., dtemp+ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum = elemnum + (ntodo * elemincre); if (elemnum >= repeat) /* completed a row; start on later row */ { rowincre = elemnum / repeat; rownum += rowincre; elemnum = elemnum - (rowincre * repeat); } else if (elemnum < 0) /* completed a row; start on a previous row */ { rowincre = (-elemnum - 1) / repeat + 1; rownum -= rowincre; elemnum = (rowincre * repeat) + elemnum; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while reading FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int fffi1i8(unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) output[ii] = (LONGLONG) input[ii]; /* copy input to output */ } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (LONGLONG) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi2i8(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) output[ii] = (LONGLONG) input[ii]; /* copy input to output */ } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (LONGLONG) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi4i8(INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) output[ii] = (LONGLONG) input[ii]; /* copy input to output */ } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (LONGLONG) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi8i8(LONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG tnull, /* I - value of FITS TNULLn keyword if any */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; ULONGLONG ulltemp; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > LONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { output[ii] = (LONGLONG) ulltemp; } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { output[ii] = input[ii]; /* copy input to output */ } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > LONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { output[ii] = (LONGLONG) ulltemp; } } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr4i8(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (input[ii] > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (input[ii] > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (zero > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr8i8(double *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (input[ii] > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (input[ii] > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (zero > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffstri8(char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ long twidth, /* I - width of each substring of chars */ double implipower, /* I - power of 10 of implied decimal */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ char *snull, /* I - value of FITS null string, if any */ LONGLONG nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ LONGLONG *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to snull. If nullcheck= 0, then no special checking for nulls is performed. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { int nullen; long ii; double dvalue; char *cstring, message[FLEN_ERRMSG]; char *cptr, *tpos; char tempstore, chrzero = '0'; double val, power; int exponent, sign, esign, decpt; nullen = strlen(snull); cptr = input; /* pointer to start of input string */ for (ii = 0; ii < ntodo; ii++) { cstring = cptr; /* temporarily insert a null terminator at end of the string */ tpos = cptr + twidth; tempstore = *tpos; *tpos = 0; /* check if null value is defined, and if the */ /* column string is identical to the null string */ if (snull[0] != ASCII_NULL_UNDEFINED && !strncmp(snull, cptr, nullen) ) { if (nullcheck) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } cptr += twidth; } else { /* value is not the null value, so decode it */ /* remove any embedded blank characters from the string */ decpt = 0; sign = 1; val = 0.; power = 1.; exponent = 0; esign = 1; while (*cptr == ' ') /* skip leading blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for leading sign */ { if (*cptr == '-') sign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and value */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } if (*cptr == '.' || *cptr == ',') /* check for decimal point */ { decpt = 1; /* set flag to show there was a decimal point */ cptr++; while (*cptr == ' ') /* skip any blanks */ cptr++; while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ power = power * 10.; cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } } if (*cptr == 'E' || *cptr == 'D') /* check for exponent */ { cptr++; while (*cptr == ' ') /* skip blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for exponent sign */ { if (*cptr == '-') esign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and exp */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { exponent = exponent * 10 + *cptr - chrzero; /* accumulate exp */ cptr++; while (*cptr == ' ') /* skip embedded blanks */ cptr++; } } if (*cptr != 0) /* should end up at the null terminator */ { snprintf(message, FLEN_ERRMSG, "Cannot read number from ASCII table"); ffpmsg(message); snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring); ffpmsg(message); /* restore the char that was overwritten by the null */ *tpos = tempstore; return(*status = BAD_C2D); } if (!decpt) /* if no explicit decimal, use implied */ power = implipower; dvalue = (sign * val / power) * pow(10., (double) (esign * exponent)); dvalue = dvalue * scale + zero; /* apply the scaling */ if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else output[ii] = (LONGLONG) dvalue; } /* restore the char that was overwritten by the null */ *tpos = tempstore; } return(*status); } cfitsio-4.3.1/testprog.tpt0000644000225700000360000000061413472024437015054 0ustar cagordonlheatmpcard1 1001 this is the 1st template card tmpcard2 ABCD this is the 2nd template card tmpcard3 1001.23 this is the 3rd template card tmpcard4 1001.45 this is the 4rd template card comment this is the 5th template card history this is the 6th template card tmpcard7 = / comment for null keyword -tmpcard1 tmpcarda change the name of tmpcard1 -tmpcard4 end junk will be ignored cfitsio-4.3.1/grparser.c0000644000225700000360000013236513717263734014465 0ustar cagordonlhea/* T E M P L A T E P A R S E R ============================= by Jerzy.Borkowski@obs.unige.ch Integral Science Data Center ch. d'Ecogia 16 1290 Versoix Switzerland 14-Oct-98: initial release 16-Oct-98: code cleanup, #include included, now gcc -Wall prints no warnings during compilation. Bugfix: now one can specify additional columns in group HDU. Autoindexing also works in this situation (colunms are number from 7 however). 17-Oct-98: bugfix: complex keywords were incorrectly written (was TCOMPLEX should be TDBLCOMPLEX). 20-Oct-98: bugfix: parser was writing EXTNAME twice, when first HDU in template is defined with XTENSION IMAGE then parser creates now dummy PHDU, SIMPLE T is now allowed only at most once and in first HDU only. WARNING: one should not define EXTNAME keyword for GROUP HDUs, as they have them already defined by parser (EXTNAME = GROUPING). Parser accepts EXTNAME oin GROUP HDU definition, but in this case multiple EXTNAME keywords will present in HDU header. 23-Oct-98: bugfix: unnecessary space was written to FITS file for blank keywords. 24-Oct-98: syntax change: empty lines and lines with only whitespaces are written to FITS files as blank keywords (if inside group/hdu definition). Previously lines had to have at least 8 spaces. Please note, that due to pecularities of CFITSIO if the last keyword(s) defined for given HDU are blank keywords consisting of only 80 spaces, then (some of) those keywords may be silently deleted by CFITSIO. 13-Nov-98: bugfix: parser was writing GRPNAME twice. Parser still creates GRPNAME keywords for GROUP HDU's which do not specify them. However, values (of form DEFAULT_GROUP_XXX) are assigned not necessarily in order HDUs appear in template file, but rather in order parser completes their creation in FITS file. Also, when including files, if fopen fails, parser tries to open file with a name = directory_of_top_level file + name of file to be included, as long as name of file to be included does not specify absolute pathname. 16-Nov-98: bugfix to bugfix from 13-Nov-98 19-Nov-98: EXTVER keyword is now automatically assigned value by parser. 17-Dev-98: 2 new things added: 1st: CFITSIO_INCLUDE_FILES environment variable can contain a colon separated list of directories to look for when looking for template include files (and master template also). 2nd: it is now possible to append template to nonempty FITS. file. fitsfile *ff no longer needs to point to an empty FITS file with 0 HDUs in it. All data written by parser will simple be appended at the end of file. 22-Jan-99: changes to parser: when in append mode parser initially scans all existing HDUs to built a list of already used EXTNAME/EXTVERs 22-Jan-99: Bruce O'Neel, bugfix : TLONG should always reference long type variable on OSF/Alpha and on 64-bit archs in general 20-Jun-2002 Wm Pence, added support for the HIERARCH keyword convention in which keyword names can effectively be longer than 8 characters. Example: HIERARCH LongKeywordName = 'value' / comment 30-Jan-2003 Wm Pence, bugfix: ngp_read_xtension was testing for "ASCIITABLE" instead of "TABLE" as the XTENSION value of an ASCII table, and it did not allow for optional trailing spaces in the "IMAGE" or "TABLE" string. 16-Dec-2003 James Peachey: ngp_keyword_all_write was modified to apply comments from the template file to the output file in the case of reserved keywords (e.g. tform#, ttype# etcetera). */ #include #include #ifdef sparc #include #include #endif #include #include "fitsio2.h" #include "grparser.h" NGP_RAW_LINE ngp_curline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 }; NGP_RAW_LINE ngp_prevline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 }; int ngp_inclevel = 0; /* number of included files, 1 - means mean file */ int ngp_grplevel = 0; /* group nesting level, 0 - means no grouping */ FILE *ngp_fp[NGP_MAX_INCLUDE]; /* stack of included file handles */ int ngp_keyidx = NGP_TOKEN_UNKNOWN; /* index of token in current line */ NGP_TOKEN ngp_linkey; /* keyword after line analyze */ char ngp_master_dir[NGP_MAX_FNAME]; /* directory of top level include file */ NGP_TKDEF ngp_tkdef[] = /* tokens recognized by parser */ { { "\\INCLUDE", NGP_TOKEN_INCLUDE }, { "\\GROUP", NGP_TOKEN_GROUP }, { "\\END", NGP_TOKEN_END }, { "XTENSION", NGP_TOKEN_XTENSION }, { "SIMPLE", NGP_TOKEN_SIMPLE }, { NULL, NGP_TOKEN_UNKNOWN } }; int master_grp_idx = 1; /* current unnamed group in object */ int ngp_extver_tab_size = 0; NGP_EXTVER_TAB *ngp_extver_tab = NULL; int ngp_get_extver(char *extname, int *version) { NGP_EXTVER_TAB *p; char *p2; int i; if ((NULL == extname) || (NULL == version)) return(NGP_BAD_ARG); if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG); if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG); for (i=0; i 0)) return(NGP_BAD_ARG); if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG); for (i=0; i ngp_extver_tab[i].version) ngp_extver_tab[i].version = version; return(NGP_OK); } } if (NULL == ngp_extver_tab) { p = (NGP_EXTVER_TAB *)ngp_alloc(sizeof(NGP_EXTVER_TAB)); } else { p = (NGP_EXTVER_TAB *)ngp_realloc(ngp_extver_tab, (ngp_extver_tab_size + 1) * sizeof(NGP_EXTVER_TAB)); } if (NULL == p) return(NGP_NO_MEMORY); p2 = ngp_alloc(strlen(extname) + 1); if (NULL == p2) { ngp_free(p); return(NGP_NO_MEMORY); } strcpy(p2, extname); ngp_extver_tab = p; ngp_extver_tab[ngp_extver_tab_size].extname = p2; ngp_extver_tab[ngp_extver_tab_size].version = version; ngp_extver_tab_size++; return(NGP_OK); } int ngp_delete_extver_tab(void) { int i; if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG); if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG); if ((NULL == ngp_extver_tab) && (0 == ngp_extver_tab_size)) return(NGP_OK); for (i=0; i allocsize) { p2 = (char *)ngp_realloc(*p, alen); /* realloc buffer, if there is need */ if (NULL == p2) { r = NGP_NO_MEMORY; break; } *p = p2; allocsize = alen; } (*p)[llen - 1] = c; /* copy character to buffer */ } llen++; /* place for terminating \0 */ if (llen != allocsize) { p2 = (char *)ngp_realloc(*p, llen); if (NULL == p2) r = NGP_NO_MEMORY; else { *p = p2; (*p)[llen - 1] = 0; /* copy \0 to buffer */ } } else { (*p)[llen - 1] = 0; /* necessary when line read was empty */ } if ((NGP_EOF != r) && (NGP_OK != r)) /* in case of errors free resources */ { ngp_free(*p); *p = NULL; } return(r); /* return status code */ } /* free current line structure */ int ngp_free_line(void) { if (NULL != ngp_curline.line) { ngp_free(ngp_curline.line); ngp_curline.line = NULL; ngp_curline.name = NULL; ngp_curline.value = NULL; ngp_curline.comment = NULL; ngp_curline.type = NGP_TTYPE_UNKNOWN; ngp_curline.format = NGP_FORMAT_OK; ngp_curline.flags = 0; } return(NGP_OK); } /* free cached line structure */ int ngp_free_prevline(void) { if (NULL != ngp_prevline.line) { ngp_free(ngp_prevline.line); ngp_prevline.line = NULL; ngp_prevline.name = NULL; ngp_prevline.value = NULL; ngp_prevline.comment = NULL; ngp_prevline.type = NGP_TTYPE_UNKNOWN; ngp_prevline.format = NGP_FORMAT_OK; ngp_prevline.flags = 0; } return(NGP_OK); } /* read one line */ int ngp_read_line_buffered(FILE *fp) { ngp_free_line(); /* first free current line (if any) */ if (NULL != ngp_prevline.line) /* if cached, return cached line */ { ngp_curline = ngp_prevline; ngp_prevline.line = NULL; ngp_prevline.name = NULL; ngp_prevline.value = NULL; ngp_prevline.comment = NULL; ngp_prevline.type = NGP_TTYPE_UNKNOWN; ngp_prevline.format = NGP_FORMAT_OK; ngp_prevline.flags = 0; ngp_curline.flags = NGP_LINE_REREAD; return(NGP_OK); } ngp_curline.flags = 0; /* if not cached really read line from file */ return(ngp_line_from_file(fp, &(ngp_curline.line))); } /* unread line */ int ngp_unread_line(void) { if (NULL == ngp_curline.line) /* nothing to unread */ return(NGP_EMPTY_CURLINE); if (NULL != ngp_prevline.line) /* we cannot unread line twice */ return(NGP_UNREAD_QUEUE_FULL); ngp_prevline = ngp_curline; ngp_curline.line = NULL; return(NGP_OK); } /* a first guess line decomposition */ int ngp_extract_tokens(NGP_RAW_LINE *cl) { char *p, *s; int cl_flags, i; p = cl->line; /* start from beginning of line */ if (NULL == p) return(NGP_NUL_PTR); cl->name = cl->value = cl->comment = NULL; cl->type = NGP_TTYPE_UNKNOWN; cl->format = NGP_FORMAT_OK; cl_flags = 0; for (i=0;; i++) /* if 8 spaces at beginning then line is comment */ { if ((0 == *p) || ('\n' == *p)) { /* if line has only blanks -> write blank keyword */ cl->line[0] = 0; /* create empty name (0 length string) */ cl->comment = cl->name = cl->line; cl->type = NGP_TTYPE_RAW; /* signal write unformatted to FITS file */ return(NGP_OK); } if ((' ' != *p) && ('\t' != *p)) break; if (i >= 7) { cl->comment = p + 1; for (s = cl->comment;; s++) /* filter out any EOS characters in comment */ { if ('\n' == *s) *s = 0; if (0 == *s) break; } cl->line[0] = 0; /* create empty name (0 length string) */ cl->name = cl->line; cl->type = NGP_TTYPE_RAW; return(NGP_OK); } p++; } cl->name = p; for (;;) /* we need to find 1st whitespace */ { if ((0 == *p) || ('\n' == *p)) { *p = 0; break; } /* from Richard Mathar, 2002-05-03, add 10 lines: if upper/lowercase HIERARCH followed also by an equal sign... */ if( fits_strncasecmp("HIERARCH",p,strlen("HIERARCH")) == 0 ) { char * const eqsi=strchr(p,'=') ; if( eqsi ) { cl_flags |= NGP_FOUND_EQUAL_SIGN ; p=eqsi ; break ; } } if ((' ' == *p) || ('\t' == *p)) break; if ('=' == *p) { cl_flags |= NGP_FOUND_EQUAL_SIGN; break; } p++; } if (*p) *(p++) = 0; /* found end of keyname so terminate string with zero */ if ((!fits_strcasecmp("HISTORY", cl->name)) || (!fits_strcasecmp("COMMENT", cl->name)) || (!fits_strcasecmp("CONTINUE", cl->name))) { cl->comment = p; for (s = cl->comment;; s++) /* filter out any EOS characters in comment */ { if ('\n' == *s) *s = 0; if (0 == *s) break; } cl->type = NGP_TTYPE_RAW; return(NGP_OK); } if (!fits_strcasecmp("\\INCLUDE", cl->name)) { for (;; p++) if ((' ' != *p) && ('\t' != *p)) break; /* skip whitespace */ cl->value = p; for (s = cl->value;; s++) /* filter out any EOS characters */ { if ('\n' == *s) *s = 0; if (0 == *s) break; } cl->type = NGP_TTYPE_UNKNOWN; return(NGP_OK); } for (;; p++) { if ((0 == *p) || ('\n' == *p)) return(NGP_OK); /* test if at end of string */ if ((' ' == *p) || ('\t' == *p)) continue; /* skip whitespace */ if (cl_flags & NGP_FOUND_EQUAL_SIGN) break; if ('=' != *p) break; /* ignore initial equal sign */ cl_flags |= NGP_FOUND_EQUAL_SIGN; } if ('/' == *p) /* no value specified, comment only */ { p++; if ((' ' == *p) || ('\t' == *p)) p++; cl->comment = p; for (s = cl->comment;; s++) /* filter out any EOS characters in comment */ { if ('\n' == *s) *s = 0; if (0 == *s) break; } return(NGP_OK); } if ('\'' == *p) /* we have found string within quotes */ { cl->value = s = ++p; /* set pointer to beginning of that string */ cl->type = NGP_TTYPE_STRING; /* signal that it is of string type */ for (;;) /* analyze it */ { if ((0 == *p) || ('\n' == *p)) /* end of line -> end of string */ { *s = 0; return(NGP_OK); } if ('\'' == *p) /* we have found doublequote */ { if ((0 == p[1]) || ('\n' == p[1]))/* doublequote is the last character in line */ { *s = 0; return(NGP_OK); } if (('\t' == p[1]) || (' ' == p[1])) /* duoblequote was string terminator */ { *s = 0; p++; break; } if ('\'' == p[1]) p++; /* doublequote is inside string, convert "" -> " */ } *(s++) = *(p++); /* compact string in place, necess. by "" -> " conversion */ } } else /* regular token */ { cl->value = p; /* set pointer to token */ cl->type = NGP_TTYPE_UNKNOWN; /* we dont know type at the moment */ for (;; p++) /* we need to find 1st whitespace */ { if ((0 == *p) || ('\n' == *p)) { *p = 0; return(NGP_OK); } if ((' ' == *p) || ('\t' == *p)) break; } if (*p) *(p++) = 0; /* found so terminate string with zero */ } for (;; p++) { if ((0 == *p) || ('\n' == *p)) return(NGP_OK); /* test if at end of string */ if ((' ' != *p) && ('\t' != *p)) break; /* skip whitespace */ } if ('/' == *p) /* no value specified, comment only */ { p++; if ((' ' == *p) || ('\t' == *p)) p++; cl->comment = p; for (s = cl->comment;; s++) /* filter out any EOS characters in comment */ { if ('\n' == *s) *s = 0; if (0 == *s) break; } return(NGP_OK); } cl->format = NGP_FORMAT_ERROR; return(NGP_OK); /* too many tokens ... */ } /* try to open include file. If open fails and fname does not specify absolute pathname, try to open fname in any directory specified in CFITSIO_INCLUDE_FILES environment variable. Finally try to open fname relative to ngp_master_dir, which is directory of top level include file */ int ngp_include_file(char *fname) /* try to open include file */ { char *p, *p2, *cp, *envar, envfiles[NGP_MAX_ENVFILES]; char *saveptr; if (NULL == fname) return(NGP_NUL_PTR); if (ngp_inclevel >= NGP_MAX_INCLUDE) /* too many include files */ return(NGP_INC_NESTING); if (NULL == (ngp_fp[ngp_inclevel] = fopen(fname, "r"))) { /* if simple open failed .. */ envar = getenv("CFITSIO_INCLUDE_FILES"); /* scan env. variable, and retry to open */ if (NULL != envar) /* is env. variable defined ? */ { strncpy(envfiles, envar, NGP_MAX_ENVFILES - 1); envfiles[NGP_MAX_ENVFILES - 1] = 0; /* copy search path to local variable, env. is fragile */ for (p2 = ffstrtok(envfiles, ":",&saveptr); NULL != p2; p2 = ffstrtok(NULL, ":",&saveptr)) { cp = (char *)ngp_alloc(strlen(fname) + strlen(p2) + 2); if (NULL == cp) return(NGP_NO_MEMORY); strcpy(cp, p2); #ifdef MSDOS strcat(cp, "\\"); /* abs. pathname for MSDOS */ #else strcat(cp, "/"); /* and for unix */ #endif strcat(cp, fname); ngp_fp[ngp_inclevel] = fopen(cp, "r"); ngp_free(cp); if (NULL != ngp_fp[ngp_inclevel]) break; } } if (NULL == ngp_fp[ngp_inclevel]) /* finally try to open relative to top level */ { #ifdef MSDOS if ('\\' == fname[0]) return(NGP_ERR_FOPEN); /* abs. pathname for MSDOS, does not support C:\\PATH */ #else if ('/' == fname[0]) return(NGP_ERR_FOPEN); /* and for unix */ #endif if (0 == ngp_master_dir[0]) return(NGP_ERR_FOPEN); p = ngp_alloc(strlen(fname) + strlen(ngp_master_dir) + 1); if (NULL == p) return(NGP_NO_MEMORY); strcpy(p, ngp_master_dir); /* construct composite pathname */ strcat(p, fname); /* comp = master + fname */ ngp_fp[ngp_inclevel] = fopen(p, "r");/* try to open composite */ ngp_free(p); /* we don't need buffer anymore */ if (NULL == ngp_fp[ngp_inclevel]) return(NGP_ERR_FOPEN); /* fail if error */ } } ngp_inclevel++; return(NGP_OK); } /* read line in the intelligent way. All \INCLUDE directives are handled, empty and comment line skipped. If this function returns NGP_OK, than decomposed line (name, type, value in proper type and comment) are stored in ngp_linkey structure. ignore_blank_lines parameter is zero when parser is inside GROUP or HDU definition. Nonzero otherwise. */ int ngp_read_line(int ignore_blank_lines) { int r, nc, savec; unsigned k; if (ngp_inclevel <= 0) /* do some sanity checking first */ { ngp_keyidx = NGP_TOKEN_EOF; /* no parents, so report error */ return(NGP_OK); } if (ngp_inclevel > NGP_MAX_INCLUDE) return(NGP_INC_NESTING); if (NULL == ngp_fp[ngp_inclevel - 1]) return(NGP_NUL_PTR); for (;;) { switch (r = ngp_read_line_buffered(ngp_fp[ngp_inclevel - 1])) { case NGP_EOF: ngp_inclevel--; /* end of file, revert to parent */ if (ngp_fp[ngp_inclevel]) /* we can close old file */ fclose(ngp_fp[ngp_inclevel]); ngp_fp[ngp_inclevel] = NULL; if (ngp_inclevel <= 0) { ngp_keyidx = NGP_TOKEN_EOF; /* no parents, so report error */ return(NGP_OK); } continue; case NGP_OK: if (ngp_curline.flags & NGP_LINE_REREAD) return(r); break; default: return(r); } switch (ngp_curline.line[0]) { case 0: if (0 == ignore_blank_lines) break; /* ignore empty lines if told so */ case '#': continue; /* ignore comment lines */ } r = ngp_extract_tokens(&ngp_curline); /* analyse line, extract tokens and comment */ if (NGP_OK != r) return(r); if (NULL == ngp_curline.name) continue; /* skip lines consisting only of whitespaces */ for (k = 0; k < strlen(ngp_curline.name); k++) { if ((ngp_curline.name[k] >= 'a') && (ngp_curline.name[k] <= 'z')) ngp_curline.name[k] += 'A' - 'a'; /* force keyword to be upper case */ if (k == 7) break; /* only first 8 chars are required to be upper case */ } for (k=0;; k++) /* find index of keyword in keyword table */ { if (NGP_TOKEN_UNKNOWN == ngp_tkdef[k].code) break; if (0 == strcmp(ngp_curline.name, ngp_tkdef[k].name)) break; } ngp_keyidx = ngp_tkdef[k].code; /* save this index, grammar parser will need this */ if (NGP_TOKEN_INCLUDE == ngp_keyidx) /* if this is \INCLUDE keyword, try to include file */ { if (NGP_OK != (r = ngp_include_file(ngp_curline.value))) return(r); continue; /* and read next line */ } ngp_linkey.type = NGP_TTYPE_UNKNOWN; /* now, get the keyword type, it's a long story ... */ if (NULL != ngp_curline.value) /* if no value given signal it */ { if (NGP_TTYPE_STRING == ngp_curline.type) /* string type test */ { ngp_linkey.type = NGP_TTYPE_STRING; ngp_linkey.value.s = ngp_curline.value; } if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* bool type test */ { if ((!fits_strcasecmp("T", ngp_curline.value)) || (!fits_strcasecmp("F", ngp_curline.value))) { ngp_linkey.type = NGP_TTYPE_BOOL; ngp_linkey.value.b = (fits_strcasecmp("T", ngp_curline.value) ? 0 : 1); } } if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* complex type test */ { if (2 == sscanf(ngp_curline.value, "(%lg,%lg)%n", &(ngp_linkey.value.c.re), &(ngp_linkey.value.c.im), &nc)) { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc]) || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc])) { ngp_linkey.type = NGP_TTYPE_COMPLEX; } } } if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* real type test */ { if (strchr(ngp_curline.value, '.') && (1 == sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc))) { if ('D' == ngp_curline.value[nc]) { /* test if template used a 'D' rather than an 'E' as the exponent character (added by WDP in 12/2010) */ savec = nc; ngp_curline.value[nc] = 'E'; sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc); if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc]) || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc])) { ngp_linkey.type = NGP_TTYPE_REAL; } else { /* no, this is not a real value */ ngp_curline.value[savec] = 'D'; /* restore the original D character */ } } else { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc]) || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc])) { ngp_linkey.type = NGP_TTYPE_REAL; } } } } if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* integer type test */ { if (1 == sscanf(ngp_curline.value, "%d%n", &(ngp_linkey.value.i), &nc)) { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc]) || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc])) { ngp_linkey.type = NGP_TTYPE_INT; } } } if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* force string type */ { ngp_linkey.type = NGP_TTYPE_STRING; ngp_linkey.value.s = ngp_curline.value; } } else { if (NGP_TTYPE_RAW == ngp_curline.type) ngp_linkey.type = NGP_TTYPE_RAW; else ngp_linkey.type = NGP_TTYPE_NULL; } if (NULL != ngp_curline.comment) { strncpy(ngp_linkey.comment, ngp_curline.comment, NGP_MAX_COMMENT); /* store comment */ ngp_linkey.comment[NGP_MAX_COMMENT - 1] = 0; } else { ngp_linkey.comment[0] = 0; } strncpy(ngp_linkey.name, ngp_curline.name, NGP_MAX_NAME); /* and keyword's name */ ngp_linkey.name[NGP_MAX_NAME - 1] = 0; if (strlen(ngp_linkey.name) > FLEN_KEYWORD) /* WDP: 20-Jun-2002: mod to support HIERARCH */ { return(NGP_BAD_ARG); /* cfitsio does not allow names > 8 chars */ } return(NGP_OK); /* we have valid non empty line, so return success */ } } /* check whether keyword can be written as is */ int ngp_keyword_is_write(NGP_TOKEN *ngp_tok) { int i, j, l, spc; /* indexed variables not to write */ static char *nm[] = { "NAXIS", "TFORM", "TTYPE", NULL } ; /* non indexed variables not allowed to write */ static char *nmni[] = { "SIMPLE", "XTENSION", "BITPIX", "NAXIS", "PCOUNT", "GCOUNT", "TFIELDS", "THEAP", "EXTEND", "EXTVER", NULL } ; if (NULL == ngp_tok) return(NGP_NUL_PTR); for (j = 0; ; j++) /* first check non indexed */ { if (NULL == nmni[j]) break; if (0 == strcmp(nmni[j], ngp_tok->name)) return(NGP_BAD_ARG); } for (j = 0; ; j++) /* now check indexed */ { if (NULL == nm[j]) return(NGP_OK); l = strlen(nm[j]); if ((l < 1) || (l > 5)) continue; if (0 == strncmp(nm[j], ngp_tok->name, l)) break; } if ((ngp_tok->name[l] < '1') || (ngp_tok->name[l] > '9')) return(NGP_OK); spc = 0; for (i = l + 1; i < 8; i++) { if (spc) { if (' ' != ngp_tok->name[i]) return(NGP_OK); } else { if ((ngp_tok->name[i] >= '0') && (ngp_tok->name[i] <= '9')) continue; if (' ' == ngp_tok->name[i]) { spc = 1; continue; } if (0 == ngp_tok->name[i]) break; return(NGP_OK); } } return(NGP_BAD_ARG); } /* write (almost) all keywords from given HDU to disk */ int ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode) { int i, r, ib; char buf[200]; long l; if (NULL == ngph) return(NGP_NUL_PTR); if (NULL == ffp) return(NGP_NUL_PTR); r = NGP_OK; for (i=0; itokcnt; i++) { r = ngp_keyword_is_write(&(ngph->tok[i])); if ((NGP_REALLY_ALL & mode) || (NGP_OK == r)) { switch (ngph->tok[i].type) { case NGP_TTYPE_BOOL: ib = ngph->tok[i].value.b; fits_write_key(ffp, TLOGICAL, ngph->tok[i].name, &ib, ngph->tok[i].comment, &r); break; case NGP_TTYPE_STRING: fits_write_key_longstr(ffp, ngph->tok[i].name, ngph->tok[i].value.s, ngph->tok[i].comment, &r); break; case NGP_TTYPE_INT: l = ngph->tok[i].value.i; /* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */ fits_write_key(ffp, TLONG, ngph->tok[i].name, &l, ngph->tok[i].comment, &r); break; case NGP_TTYPE_REAL: fits_write_key(ffp, TDOUBLE, ngph->tok[i].name, &(ngph->tok[i].value.d), ngph->tok[i].comment, &r); break; case NGP_TTYPE_COMPLEX: fits_write_key(ffp, TDBLCOMPLEX, ngph->tok[i].name, &(ngph->tok[i].value.c), ngph->tok[i].comment, &r); break; case NGP_TTYPE_NULL: fits_write_key_null(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r); break; case NGP_TTYPE_RAW: if (0 == strcmp("HISTORY", ngph->tok[i].name)) { fits_write_history(ffp, ngph->tok[i].comment, &r); break; } if (0 == strcmp("COMMENT", ngph->tok[i].name)) { fits_write_comment(ffp, ngph->tok[i].comment, &r); break; } snprintf(buf,200, "%-8.8s%s", ngph->tok[i].name, ngph->tok[i].comment); fits_write_record(ffp, buf, &r); break; } } else if (NGP_BAD_ARG == r) /* enhancement 10 dec 2003, James Peachey: template comments replace defaults */ { r = NGP_OK; /* update comments of special keywords like TFORM */ if (ngph->tok[i].comment && *ngph->tok[i].comment) /* do not update with a blank comment */ { fits_modify_comment(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r); } } else /* other problem, typically a blank token */ { r = NGP_OK; /* skip this token, but continue */ } if (r) return(r); } fits_set_hdustruc(ffp, &r); /* resync cfitsio */ return(r); } /* init HDU structure */ int ngp_hdu_init(NGP_HDU *ngph) { if (NULL == ngph) return(NGP_NUL_PTR); ngph->tok = NULL; ngph->tokcnt = 0; return(NGP_OK); } /* clear HDU structure */ int ngp_hdu_clear(NGP_HDU *ngph) { int i; if (NULL == ngph) return(NGP_NUL_PTR); for (i=0; itokcnt; i++) { if (NGP_TTYPE_STRING == ngph->tok[i].type) if (NULL != ngph->tok[i].value.s) { ngp_free(ngph->tok[i].value.s); ngph->tok[i].value.s = NULL; } } if (NULL != ngph->tok) ngp_free(ngph->tok); ngph->tok = NULL; ngph->tokcnt = 0; return(NGP_OK); } /* insert new token to HDU structure */ int ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok) { NGP_TOKEN *tkp; if (NULL == ngph) return(NGP_NUL_PTR); if (NULL == newtok) return(NGP_NUL_PTR); if (0 == ngph->tokcnt) tkp = (NGP_TOKEN *)ngp_alloc((ngph->tokcnt + 1) * sizeof(NGP_TOKEN)); else tkp = (NGP_TOKEN *)ngp_realloc(ngph->tok, (ngph->tokcnt + 1) * sizeof(NGP_TOKEN)); if (NULL == tkp) return(NGP_NO_MEMORY); ngph->tok = tkp; ngph->tok[ngph->tokcnt] = *newtok; if (NGP_TTYPE_STRING == newtok->type) { if (NULL != newtok->value.s) { ngph->tok[ngph->tokcnt].value.s = (char *)ngp_alloc(1 + strlen(newtok->value.s)); if (NULL == ngph->tok[ngph->tokcnt].value.s) return(NGP_NO_MEMORY); strcpy(ngph->tok[ngph->tokcnt].value.s, newtok->value.s); } } ngph->tokcnt++; return(NGP_OK); } int ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol) { int r, i, j, exitflg, ngph_i; char *my_tform, *my_ttype; char ngph_ctmp; if (NULL == ff) return(NGP_NUL_PTR); if (NULL == ngph) return(NGP_NUL_PTR); if (0 == ngph->tokcnt) return(NGP_OK); /* nothing to do ! */ r = NGP_OK; exitflg = 0; for (j=aftercol; jtok[i].name, "TFORM%d%c", &ngph_i, &ngph_ctmp)) { if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1))) { my_tform = ngph->tok[i].value.s; } } else if (1 == sscanf(ngph->tok[i].name, "TTYPE%d%c", &ngph_i, &ngph_ctmp)) { if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1))) { my_ttype = ngph->tok[i].value.s; } } if ((NULL != my_tform) && (my_ttype[0])) break; if (i < (ngph->tokcnt - 1)) continue; exitflg = 1; break; } if ((NGP_OK == r) && (NULL != my_tform)) fits_insert_col(ff, j + 1, my_ttype, my_tform, &r); if ((NGP_OK != r) || exitflg) break; } return(r); } /* read complete HDU */ int ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode) { int r, exflg, l, my_hn, tmp0, incrementor_index, i, j; int ngph_dim, ngph_bitpix, ngph_node_type, my_version; char incrementor_name[NGP_MAX_STRING], ngph_ctmp; char *ngph_extname = 0; long ngph_size[NGP_MAX_ARRAY_DIM]; NGP_HDU ngph; long lv; incrementor_name[0] = 0; /* signal no keyword+'#' found yet */ incrementor_index = 0; if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r); if (NGP_OK != (r = ngp_read_line(0))) return(r); /* EOF always means error here */ switch (NGP_XTENSION_SIMPLE & simple_mode) { case 0: if (NGP_TOKEN_XTENSION != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT); break; default: if (NGP_TOKEN_SIMPLE != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT); break; } if (NGP_OK != (r = ngp_hdu_insert_token(&ngph, &ngp_linkey))) return(r); for (;;) { if (NGP_OK != (r = ngp_read_line(0))) return(r); /* EOF always means error here */ exflg = 0; switch (ngp_keyidx) { case NGP_TOKEN_SIMPLE: r = NGP_TOKEN_NOT_EXPECT; break; case NGP_TOKEN_END: case NGP_TOKEN_XTENSION: case NGP_TOKEN_GROUP: r = ngp_unread_line(); /* WARNING - not break here .... */ case NGP_TOKEN_EOF: exflg = 1; break; default: l = strlen(ngp_linkey.name); if ((l >= 2) && (l <= 6)) { if ('#' == ngp_linkey.name[l - 1]) { if (0 == incrementor_name[0]) { memcpy(incrementor_name, ngp_linkey.name, l - 1); incrementor_name[l - 1] = 0; } if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1))) { incrementor_index++; } snprintf(ngp_linkey.name + l - 1, NGP_MAX_NAME-l+1,"%d", incrementor_index); } } r = ngp_hdu_insert_token(&ngph, &ngp_linkey); break; } if ((NGP_OK != r) || exflg) break; } if (NGP_OK == r) { /* we should scan keywords, and calculate HDU's */ /* structure ourselves .... */ ngph_node_type = NGP_NODE_INVALID; /* init variables */ ngph_bitpix = 0; ngph_extname = NULL; for (i=0; i=1) && (j <= NGP_MAX_ARRAY_DIM)) { ngph_size[j - 1] = ngph.tok[i].value.i; } } } switch (ngph_node_type) { case NGP_NODE_IMAGE: if (NGP_XTENSION_FIRST == ((NGP_XTENSION_FIRST | NGP_XTENSION_SIMPLE) & simple_mode)) { /* if caller signals that this is 1st HDU in file */ /* and it is IMAGE defined with XTENSION, then we */ /* need create dummy Primary HDU */ fits_create_img(ff, 16, 0, NULL, &r); } /* create image */ fits_create_img(ff, ngph_bitpix, ngph_dim, ngph_size, &r); /* update keywords */ if (NGP_OK == r) r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY); break; case NGP_NODE_ATABLE: case NGP_NODE_BTABLE: /* create table, 0 rows and 0 columns for the moment */ fits_create_tbl(ff, ((NGP_NODE_ATABLE == ngph_node_type) ? ASCII_TBL : BINARY_TBL), 0, 0, NULL, NULL, NULL, NULL, &r); if (NGP_OK != r) break; /* add columns ... */ r = ngp_append_columns(ff, &ngph, 0); if (NGP_OK != r) break; /* add remaining keywords */ r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY); if (NGP_OK != r) break; /* if requested add rows */ if (ngph_size[1] > 0) fits_insert_rows(ff, 0, ngph_size[1], &r); break; default: r = NGP_BAD_ARG; break; } } if ((NGP_OK == r) && (NULL != ngph_extname)) { r = ngp_get_extver(ngph_extname, &my_version); /* write correct ext version number */ lv = my_version; /* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */ fits_write_key(ff, TLONG, "EXTVER", &lv, "auto assigned by template parser", &r); } if (NGP_OK == r) { if (parent_hn > 0) { fits_get_hdu_num(ff, &my_hn); fits_movabs_hdu(ff, parent_hn, &tmp0, &r); /* link us to parent */ fits_add_group_member(ff, NULL, my_hn, &r); fits_movabs_hdu(ff, my_hn, &tmp0, &r); if (NGP_OK != r) return(r); } } if (NGP_OK != r) /* in case of error - delete hdu */ { tmp0 = 0; fits_delete_hdu(ff, NULL, &tmp0); } ngp_hdu_clear(&ngph); return(r); } /* read complete GROUP */ int ngp_read_group(fitsfile *ff, char *grpname, int parent_hn) { int r, exitflg, l, my_hn, tmp0, incrementor_index; char grnm[NGP_MAX_STRING]; /* keyword holding group name */ char incrementor_name[NGP_MAX_STRING]; NGP_HDU ngph; incrementor_name[0] = 0; /* signal no keyword+'#' found yet */ incrementor_index = 6; /* first 6 cols are used by group */ ngp_grplevel++; if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r); r = NGP_OK; if (NGP_OK != (r = fits_create_group(ff, grpname, GT_ID_ALL_URI, &r))) return(r); fits_get_hdu_num(ff, &my_hn); if (parent_hn > 0) { fits_movabs_hdu(ff, parent_hn, &tmp0, &r); /* link us to parent */ fits_add_group_member(ff, NULL, my_hn, &r); fits_movabs_hdu(ff, my_hn, &tmp0, &r); if (NGP_OK != r) return(r); } for (exitflg = 0; 0 == exitflg;) { if (NGP_OK != (r = ngp_read_line(0))) break; /* EOF always means error here */ switch (ngp_keyidx) { case NGP_TOKEN_SIMPLE: case NGP_TOKEN_EOF: r = NGP_TOKEN_NOT_EXPECT; break; case NGP_TOKEN_END: ngp_grplevel--; exitflg = 1; break; case NGP_TOKEN_GROUP: if (NGP_TTYPE_STRING == ngp_linkey.type) { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING); } else { snprintf(grnm, NGP_MAX_STRING,"DEFAULT_GROUP_%d", master_grp_idx++); } grnm[NGP_MAX_STRING - 1] = 0; r = ngp_read_group(ff, grnm, my_hn); break; /* we can have many subsequent GROUP defs */ case NGP_TOKEN_XTENSION: r = ngp_unread_line(); if (NGP_OK != r) break; r = ngp_read_xtension(ff, my_hn, 0); break; /* we can have many subsequent HDU defs */ default: l = strlen(ngp_linkey.name); if ((l >= 2) && (l <= 6)) { if ('#' == ngp_linkey.name[l - 1]) { if (0 == incrementor_name[0]) { memcpy(incrementor_name, ngp_linkey.name, l - 1); incrementor_name[l - 1] = 0; } if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1))) { incrementor_index++; } snprintf(ngp_linkey.name + l - 1, NGP_MAX_NAME-l+1,"%d", incrementor_index); } } r = ngp_hdu_insert_token(&ngph, &ngp_linkey); break; /* here we can add keyword */ } if (NGP_OK != r) break; } fits_movabs_hdu(ff, my_hn, &tmp0, &r); /* back to our HDU */ if (NGP_OK == r) /* create additional columns, if requested */ r = ngp_append_columns(ff, &ngph, 6); if (NGP_OK == r) /* and write keywords */ r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY); if (NGP_OK != r) /* delete group in case of error */ { tmp0 = 0; fits_remove_group(ff, OPT_RM_GPT, &tmp0); } ngp_hdu_clear(&ngph); /* we are done with this HDU, so delete it */ return(r); } /* top level API functions */ /* read whole template. ff should point to the opened empty fits file. */ int fits_execute_template(fitsfile *ff, char *ngp_template, int *status) { int r, exit_flg, first_extension, i, my_hn, tmp0, keys_exist, more_keys, used_ver; char grnm[NGP_MAX_STRING], used_name[NGP_MAX_STRING]; long luv; if (NULL == status) return(NGP_NUL_PTR); if (NGP_OK != *status) return(*status); /* This function uses many global variables (local to this file) and therefore is not thread-safe. */ FFLOCK; if ((NULL == ff) || (NULL == ngp_template)) { *status = NGP_NUL_PTR; FFUNLOCK; return(*status); } ngp_inclevel = 0; /* initialize things, not all should be zero */ ngp_grplevel = 0; master_grp_idx = 1; exit_flg = 0; ngp_master_dir[0] = 0; /* this should be before 1st call to ngp_include_file */ first_extension = 1; /* we need to create PHDU */ if (NGP_OK != (r = ngp_delete_extver_tab())) { *status = r; FFUNLOCK; return(r); } fits_get_hdu_num(ff, &my_hn); /* our HDU position */ if (my_hn <= 1) /* check whether we really need to create PHDU */ { fits_movabs_hdu(ff, 1, &tmp0, status); fits_get_hdrspace(ff, &keys_exist, &more_keys, status); fits_movabs_hdu(ff, my_hn, &tmp0, status); if (NGP_OK != *status) /* error here means file is corrupted */ { FFUNLOCK; return(*status); } if (keys_exist > 0) first_extension = 0; /* if keywords exist assume PHDU already exist */ } else { first_extension = 0; /* PHDU (followed by 1+ extensions) exist */ for (i = 2; i<= my_hn; i++) { *status = NGP_OK; fits_movabs_hdu(ff, 1, &tmp0, status); if (NGP_OK != *status) break; fits_read_key(ff, TSTRING, "EXTNAME", used_name, NULL, status); if (NGP_OK != *status) continue; fits_read_key(ff, TLONG, "EXTVER", &luv, NULL, status); used_ver = luv; /* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */ if (VALUE_UNDEFINED == *status) { used_ver = 1; *status = NGP_OK; } if (NGP_OK == *status) *status = ngp_set_extver(used_name, used_ver); } fits_movabs_hdu(ff, my_hn, &tmp0, status); } if (NGP_OK != *status) { FFUNLOCK; return(*status); } if (NGP_OK != (*status = ngp_include_file(ngp_template))) { FFUNLOCK; return(*status); } for (i = strlen(ngp_template) - 1; i >= 0; i--) /* strlen is > 0, otherwise fopen failed */ { #ifdef MSDOS if ('\\' == ngp_template[i]) break; #else if ('/' == ngp_template[i]) break; #endif } i++; if (i > (NGP_MAX_FNAME - 1)) i = NGP_MAX_FNAME - 1; if (i > 0) { memcpy(ngp_master_dir, ngp_template, i); ngp_master_dir[i] = 0; } for (;;) { if (NGP_OK != (r = ngp_read_line(1))) break; /* EOF always means error here */ switch (ngp_keyidx) { case NGP_TOKEN_SIMPLE: if (0 == first_extension) /* simple only allowed in first HDU */ { r = NGP_TOKEN_NOT_EXPECT; break; } if (NGP_OK != (r = ngp_unread_line())) break; r = ngp_read_xtension(ff, 0, NGP_XTENSION_SIMPLE | NGP_XTENSION_FIRST); first_extension = 0; break; case NGP_TOKEN_XTENSION: if (NGP_OK != (r = ngp_unread_line())) break; r = ngp_read_xtension(ff, 0, (first_extension ? NGP_XTENSION_FIRST : 0)); first_extension = 0; break; case NGP_TOKEN_GROUP: if (NGP_TTYPE_STRING == ngp_linkey.type) { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING); } else { snprintf(grnm,NGP_MAX_STRING, "DEFAULT_GROUP_%d", master_grp_idx++); } grnm[NGP_MAX_STRING - 1] = 0; r = ngp_read_group(ff, grnm, 0); first_extension = 0; break; case NGP_TOKEN_EOF: exit_flg = 1; break; default: r = NGP_TOKEN_NOT_EXPECT; break; } if (exit_flg || (NGP_OK != r)) break; } /* all top level HDUs up to faulty one are left intact in case of i/o error. It is up to the caller to call fits_close_file or fits_delete_file when this function returns error. */ ngp_free_line(); /* deallocate last line (if any) */ ngp_free_prevline(); /* deallocate cached line (if any) */ ngp_delete_extver_tab(); /* delete extver table (if present), error ignored */ *status = r; FFUNLOCK; return(r); } cfitsio-4.3.1/eval_f.c0000644000225700000360000031356114335036354014064 0ustar cagordonlhea/************************************************************************/ /* */ /* CFITSIO Lexical Parser */ /* */ /* This file is one of 3 files containing code which parses an */ /* arithmetic expression and evaluates it in the context of an input */ /* FITS file table extension. The CFITSIO lexical parser is divided */ /* into the following 3 parts/files: the CFITSIO "front-end", */ /* eval_f.c, contains the interface between the user/CFITSIO and the */ /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ /* input string and parses it into tokens and identifies the FITS */ /* information required to evaluate the expression (ie, keywords and */ /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ /* receives the FLEX output and determines and performs the actual */ /* operations. The files eval_l.c and eval_y.c are produced from */ /* running flex and bison on the files eval.l and eval.y, respectively. */ /* (flex and bison are available from any GNU archive: see www.gnu.org) */ /* */ /* The grammar rules, rather than evaluating the expression in situ, */ /* builds a tree, or Nodal, structure mapping out the order of */ /* operations and expression dependencies. This "compilation" process */ /* allows for much faster processing of multiple rows. This technique */ /* was developed by Uwe Lammers of the XMM Science Analysis System, */ /* although the CFITSIO implementation is entirely code original. */ /* */ /* */ /* Modification History: */ /* */ /* Kent Blackburn c1992 Original parser code developed for the */ /* FTOOLS software package, in particular, */ /* the fselect task. */ /* Kent Blackburn c1995 BIT column support added */ /* Peter D Wilson Feb 1998 Vector column support added */ /* Peter D Wilson May 1998 Ported to CFITSIO library. User */ /* interface routines written, in essence */ /* making fselect, fcalc, and maketime */ /* capabilities available to all tools */ /* via single function calls. */ /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ /* create a run-time evaluation tree, */ /* inspired by the work of Uwe Lammers, */ /* resulting in a speed increase of */ /* 10-100 times. */ /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ /* allowing a purely vector-based usage */ /* Peter D Wilson Aug 1999 Add row-offset capability */ /* Peter D Wilson Sep 1999 Add row-range capability to ffcalc_rng */ /* */ /************************************************************************/ #include #include #include "eval_defs.h" #include "region.h" /* Internal routines needed to allow the evaluator to operate on FITS data */ static void Setup_DataArrays( ParseData *lParse, int nCols, iteratorCol *cols, long fRow, long nRows ); static int find_column( ParseData *lParse, char *colName, void *itslval ); static int find_keywd ( ParseData *lParse, char *key, void *itslval ); static int load_column( ParseData *lParse, int varNum, long fRow, long nRows, void *data, char *undef ); static int DEBUG_PIXFILTER; #define FREE(x) { if (x) free(x); else printf("invalid free(" #x ") at %s:%d\n", __FILE__, __LINE__); } /*---------------------------------------------------------------------------*/ int fffrow( fitsfile *fptr, /* I - Input FITS file */ char *expr, /* I - Boolean expression */ long firstrow, /* I - First row of table to eval */ long nrows, /* I - Number of rows to evaluate */ long *n_good_rows, /* O - Number of rows eval to True */ char *row_status, /* O - Array of boolean results */ int *status ) /* O - Error status */ /* */ /* Evaluate a boolean expression using the indicated rows, returning an */ /* array of flags indicating which rows evaluated to TRUE/FALSE */ /*---------------------------------------------------------------------------*/ { parseInfo Info; int naxis, constant; long nelem, naxes[MAXDIMS], elem; char result; ParseData lParse; if( *status ) return( *status ); memset(&Info, 0, sizeof(Info)); if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, &lParse, status ) ) { ffcprs(&lParse); return( *status ); } if( nelem<0 ) { constant = 1; nelem = -nelem; } else constant = 0; if( Info.datatype!=TLOGICAL || nelem!=1 ) { ffcprs(&lParse); ffpmsg("Expression does not evaluate to a logical scalar."); return( *status = PARSE_BAD_TYPE ); } if( constant ) { /* No need to call parser... have result from ffiprs */ result = lParse.Nodes[lParse.resultNode].value.data.log; *n_good_rows = nrows; for( elem=0; elem1 ? firstrow : 1); Info.dataPtr = row_status; Info.nullPtr = NULL; Info.maxRows = nrows; Info.parseData = &lParse; if( ffiter( lParse.nCols, lParse.colData, firstrow-1, 0, fits_parser_workfn, (void*)&Info, status ) == -1 ) *status = 0; /* -1 indicates exitted without error before end... OK */ if( *status ) { /***********************/ /* Error... Do nothing */ /***********************/ } else { /***********************************/ /* Count number of good rows found */ /***********************************/ *n_good_rows = 0L; for( elem=0; elemHDUposition != (infptr->Fptr)->curhdu ) ffmahd( infptr, (infptr->HDUposition) + 1, NULL, status ); if( *status ) { ffcprs(&lParse); return( *status ); } inExt.rowLength = (long) (infptr->Fptr)->rowlength; inExt.numRows = (infptr->Fptr)->numrows; inExt.heapSize = (infptr->Fptr)->heapsize; if( inExt.numRows == 0 ) { /* Nothing to copy */ ffcprs(&lParse); return( *status ); } if( outfptr->HDUposition != (outfptr->Fptr)->curhdu ) ffmahd( outfptr, (outfptr->HDUposition) + 1, NULL, status ); if( (outfptr->Fptr)->datastart < 0 ) ffrdef( outfptr, status ); if( *status ) { ffcprs(&lParse); return( *status ); } outExt.rowLength = (long) (outfptr->Fptr)->rowlength; outExt.numRows = (outfptr->Fptr)->numrows; if( !outExt.numRows ) (outfptr->Fptr)->heapsize = 0L; outExt.heapSize = (outfptr->Fptr)->heapsize; if( inExt.rowLength != outExt.rowLength ) { ffpmsg("Output table has different row length from input"); ffcprs(&lParse); return( *status = PARSE_BAD_OUTPUT ); } /***********************************/ /* Fill out Info data for parser */ /***********************************/ Info.dataPtr = (char *)malloc( (size_t) ((inExt.numRows + 1) * sizeof(char)) ); Info.nullPtr = NULL; Info.maxRows = (long) inExt.numRows; Info.parseData = &lParse; if( !Info.dataPtr ) { ffpmsg("Unable to allocate memory for row selection"); ffcprs(&lParse); return( *status = MEMORY_ALLOCATION ); } /* make sure array is zero terminated */ ((char*)Info.dataPtr)[inExt.numRows] = 0; if( constant ) { /* Set all rows to the same value from constant result */ result = lParse.Nodes[lParse.resultNode].value.data.log; for( ntodo = 0; ntodo 1) ffirow( outfptr, outExt.numRows, nGood, status ); } do { if( ((char*)Info.dataPtr)[inloc-1] ) { ffgtbb( infptr, inloc, 1L, rdlen, buffer+rdlen*nbuff, status ); nbuff++; if( nbuff==maxrows ) { ffptbb( outfptr, outloc, 1L, rdlen*nbuff, buffer, status ); outloc += nbuff; nbuff = 0; } } inloc++; } while( !*status && inloc<=inExt.numRows ); if( nbuff ) { ffptbb( outfptr, outloc, 1L, rdlen*nbuff, buffer, status ); outloc += nbuff; } if( infptr==outfptr ) { if( outloc<=inExt.numRows ) ffdrow( infptr, outloc, inExt.numRows-outloc+1, status ); } else if( inExt.heapSize && nGood ) { /* Copy heap, if it exists and at least one row copied */ /********************************************************/ /* Get location information from the output extension */ /********************************************************/ if( outfptr->HDUposition != (outfptr->Fptr)->curhdu ) ffmahd( outfptr, (outfptr->HDUposition) + 1, NULL, status ); outExt.dataStart = (outfptr->Fptr)->datastart; outExt.heapStart = (outfptr->Fptr)->heapstart; /*************************************************/ /* Insert more space into outfptr if necessary */ /*************************************************/ hsize = outExt.heapStart + outExt.heapSize; freespace = (long) (( ( (hsize + 2879) / 2880) * 2880) - hsize); ntodo = inExt.heapSize; if ( (freespace - ntodo) < 0) { /* not enough existing space? */ ntodo = (ntodo - freespace + 2879) / 2880; /* number of blocks */ ffiblk(outfptr, (long) ntodo, 1, status); /* insert the blocks */ } ffukyj( outfptr, "PCOUNT", inExt.heapSize+outExt.heapSize, NULL, status ); /*******************************************************/ /* Get location information from the input extension */ /*******************************************************/ if( infptr->HDUposition != (infptr->Fptr)->curhdu ) ffmahd( infptr, (infptr->HDUposition) + 1, NULL, status ); inExt.dataStart = (infptr->Fptr)->datastart; inExt.heapStart = (infptr->Fptr)->heapstart; /**********************************/ /* Finally copy heap to outfptr */ /**********************************/ ntodo = inExt.heapSize; inbyteloc = inExt.heapStart + inExt.dataStart; outbyteloc = outExt.heapStart + outExt.dataStart + outExt.heapSize; while ( ntodo && !*status ) { rdlen = (long) minvalue(ntodo,500000); ffmbyt( infptr, inbyteloc, REPORT_EOF, status ); ffgbyt( infptr, rdlen, buffer, status ); ffmbyt( outfptr, outbyteloc, IGNORE_EOF, status ); ffpbyt( outfptr, rdlen, buffer, status ); inbyteloc += rdlen; outbyteloc += rdlen; ntodo -= rdlen; } /***********************************************************/ /* But must update DES if data is being appended to a */ /* pre-existing heap space. Edit each new entry in file */ /***********************************************************/ if( outExt.heapSize ) { LONGLONG repeat, offset, j; int i; for( i=1; i<=(outfptr->Fptr)->tfield; i++ ) { if( (outfptr->Fptr)->tableptr[i-1].tdatatype<0 ) { for( j=outExt.numRows+1; j<=outExt.numRows+nGood; j++ ) { ffgdesll( outfptr, i, j, &repeat, &offset, status ); offset += outExt.heapSize; ffpdes( outfptr, i, j, repeat, offset, status ); } } } } } /* End of HEAP copy */ FREE(buffer); } FREE(Info.dataPtr); ffcprs(&lParse); ffcmph(outfptr, status); /* compress heap, deleting any orphaned data */ return(*status); } /*---------------------------------------------------------------------------*/ int ffcrow( fitsfile *fptr, /* I - Input FITS file */ int datatype, /* I - Datatype to return results as */ char *expr, /* I - Arithmetic expression */ long firstrow, /* I - First row to evaluate */ long nelements, /* I - Number of elements to return */ void *nulval, /* I - Ptr to value to use as UNDEF */ void *array, /* O - Array of results */ int *anynul, /* O - Were any UNDEFs encountered? */ int *status ) /* O - Error status */ /* */ /* Calculate an expression for the indicated rows of a table, returning */ /* the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If */ /* nulval==NULL, UNDEFs will be zeroed out. For vector results, the number */ /* of elements returned may be less than nelements if nelements is not an */ /* even multiple of the result dimension. Call fftexp to obtain the */ /* dimensions of the results. */ /*---------------------------------------------------------------------------*/ { parseInfo Info; int naxis; long nelem1, naxes[MAXDIMS]; ParseData lParse; if( *status ) return( *status ); memset(&Info, 0, sizeof(Info)); if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem1, &naxis, naxes, &lParse, status ) ) { ffcprs(&lParse); return( *status ); } if( nelem1<0 ) nelem1 = - nelem1; if( nelements1 ? firstrow : 1); if( datatype ) Info.datatype = datatype; Info.dataPtr = array; Info.nullPtr = nulval; Info.maxRows = nelements / nelem1; Info.parseData = &lParse; if( ffiter( lParse.nCols, lParse.colData, firstrow-1, 0, fits_parser_workfn, (void*)&Info, status ) == -1 ) *status=0; /* -1 indicates exitted without error before end... OK */ *anynul = Info.anyNull; ffcprs(&lParse); return( *status ); } /*--------------------------------------------------------------------------*/ int ffcalc( fitsfile *infptr, /* I - Input FITS file */ char *expr, /* I - Arithmetic expression */ fitsfile *outfptr, /* I - Output fits file */ char *parName, /* I - Name of output parameter */ char *parInfo, /* I - Extra information on parameter */ int *status ) /* O - Error status */ /* */ /* Evaluate an expression for all rows of a table. Call ffcalc_rng with */ /* a row range of 1-MAX. */ { long start=1, end=LONG_MAX; return ffcalc_rng( infptr, expr, outfptr, parName, parInfo, 1, &start, &end, status ); } /*--------------------------------------------------------------------------*/ int ffcalc_rng( fitsfile *infptr, /* I - Input FITS file */ char *expr, /* I - Arithmetic expression */ fitsfile *outfptr, /* I - Output fits file */ char *parName, /* I - Name of output parameter */ char *parInfo, /* I - Extra information on parameter */ int nRngs, /* I - Row range info */ long *start, /* I - Row range info */ long *end, /* I - Row range info */ int *status ) /* O - Error status */ /* */ /* Evaluate an expression using the data in the input FITS file and place */ /* the results into either a column or keyword in the output fits file, */ /* depending on the value of parName (keywords normally prefixed with '#') */ /* and whether the expression evaluates to a constant or a table column. */ /* The logic is as follows: */ /* (1) If a column exists with name, parName, put results there. */ /* (2) If parName starts with '#', as in #NAXIS, put result there, */ /* with parInfo used as the comment. If expression does not evaluate */ /* to a constant, flag an error. */ /* (3) If a keyword exists with name, parName, and expression is a */ /* constant, put result there, using parInfo as the new comment. */ /* (4) Else, create a new column with name parName and TFORM parInfo. */ /* If parInfo is NULL, use a default data type for the column. */ /*--------------------------------------------------------------------------*/ { parseInfo Info; int naxis, constant, typecode, newNullKwd=0; long nelem, naxes[MAXDIMS], repeat, width; int col_cnt, colNo; Node *result; char card[81], tform[16], nullKwd[9], tdimKwd[9]; ParseData lParse; if( *status ) return( *status ); memset(&Info, 0, sizeof(Info)); if( ffiprs( infptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, &lParse, status ) ) { ffcprs(&lParse); return( *status ); } if( nelem<0 ) { constant = 1; nelem = -nelem; } else constant = 0; Info.parseData = &lParse; /* Case (1): If column exists put it there */ colNo = 0; if( ffgcno( outfptr, CASEINSEN, parName, &colNo, status )==COL_NOT_FOUND ) { /* Output column doesn't exist. Test for keyword. */ /* Case (2): Does parName indicate result should be put into keyword */ *status = 0; if( parName[0]=='#' ) { if( ! constant ) { ffcprs(&lParse); ffpmsg( "Cannot put tabular result into keyword (ffcalc)" ); return( *status = PARSE_BAD_TYPE ); } parName++; /* Advance past '#' */ if ( (fits_strcasecmp(parName,"HISTORY") == 0 || fits_strcasecmp(parName,"COMMENT") == 0) && Info.datatype != TSTRING ) { ffcprs(&lParse); ffpmsg( "HISTORY and COMMENT values must be strings (ffcalc)" ); return( *status = PARSE_BAD_TYPE ); } } else if( constant ) { /* Case (3): Does a keyword named parName already exist */ if( ffgcrd( outfptr, parName, card, status )==KEY_NO_EXIST ) { colNo = -1; } else if( *status ) { ffcprs(&lParse); return( *status ); } } else colNo = -1; if( colNo<0 ) { /* Case (4): Create new column */ *status = 0; ffgncl( outfptr, &colNo, status ); colNo++; if( parInfo==NULL || *parInfo=='\0' ) { /* Figure out best default column type */ if( lParse.hdutype==BINARY_TBL ) { snprintf(tform,15,"%ld",nelem); switch( Info.datatype ) { case TLOGICAL: strcat(tform,"L"); break; case TLONG: strcat(tform,"J"); break; case TDOUBLE: strcat(tform,"D"); break; case TSTRING: strcat(tform,"A"); break; case TBIT: strcat(tform,"X"); break; case TLONGLONG: strcat(tform,"K"); break; } } else { switch( Info.datatype ) { case TLOGICAL: ffcprs(&lParse); ffpmsg("Cannot create LOGICAL column in ASCII table"); return( *status = NOT_BTABLE ); case TLONG: strcpy(tform,"I11"); break; case TDOUBLE: strcpy(tform,"D23.15"); break; case TSTRING: case TBIT: snprintf(tform,16,"A%ld",nelem); break; } } parInfo = tform; } else if( !(isdigit((int) *parInfo)) && lParse.hdutype==BINARY_TBL ) { if( Info.datatype==TBIT && *parInfo=='B' ) nelem = (nelem+7)/8; snprintf(tform,16,"%ld%s",nelem,parInfo); parInfo = tform; } fficol( outfptr, colNo, parName, parInfo, status ); if( naxis>1 ) ffptdm( outfptr, colNo, naxis, naxes, status ); /* Setup TNULLn keyword in case NULLs are encountered */ ffkeyn("TNULL", colNo, nullKwd, status); if( ffgcrd( outfptr, nullKwd, card, status )==KEY_NO_EXIST ) { *status = 0; if( lParse.hdutype==BINARY_TBL ) { LONGLONG nullVal=0; fits_binary_tform( parInfo, &typecode, &repeat, &width, status ); if( typecode==TBYTE ) nullVal = UCHAR_MAX; else if( typecode==TSHORT ) nullVal = SHRT_MIN; else if( typecode==TINT ) nullVal = INT_MIN; else if( typecode==TLONG ) { if (sizeof(long) == 8 && sizeof(int) == 4) nullVal = INT_MIN; else nullVal = LONG_MIN; } else if( typecode==TLONGLONG ) nullVal = LONGLONG_MIN; if( nullVal ) { ffpkyj( outfptr, nullKwd, nullVal, "Null value", status ); fits_set_btblnull( outfptr, colNo, nullVal, status ); newNullKwd = 1; } } else if( lParse.hdutype==ASCII_TBL ) { ffpkys( outfptr, nullKwd, "NULL", "Null value string", status ); fits_set_atblnull( outfptr, colNo, "NULL", status ); newNullKwd = 1; } } } } else if( *status ) { ffcprs(&lParse); return( *status ); } else { /********************************************************/ /* Check if a TDIM keyword should be written/updated. */ /********************************************************/ ffkeyn("TDIM", colNo, tdimKwd, status); ffgcrd( outfptr, tdimKwd, card, status ); if( *status==0 ) { /* TDIM exists, so update it with result's dimension */ ffptdm( outfptr, colNo, naxis, naxes, status ); } else if( *status==KEY_NO_EXIST ) { /* TDIM does not exist, so clear error stack and */ /* write a TDIM only if result is multi-dimensional */ *status = 0; ffcmsg(); if( naxis>1 ) ffptdm( outfptr, colNo, naxis, naxes, status ); } if( *status ) { /* Either some other error happened in ffgcrd */ /* or one happened in ffptdm */ ffcprs(&lParse); return( *status ); } } if( colNo>0 ) { /* Output column exists (now)... put results into it */ int anyNull = 0; int nPerLp, i; long totaln; ffgkyj(infptr, "NAXIS2", &totaln, 0, status); /*************************************/ /* Create new iterator Output Column */ /*************************************/ col_cnt = lParse.nCols; if( fits_parser_allocateCol( &lParse, col_cnt, status ) ) { ffcprs(&lParse); return( *status ); } fits_iter_set_by_num( lParse.colData+col_cnt, outfptr, colNo, 0, OutputCol ); lParse.nCols++; for( i=0; i= 10) && (nRngs == 1) && (start[0] == 1) && (end[0] == totaln)) nPerLp = 0; else nPerLp = Info.maxRows; if( ffiter( lParse.nCols, lParse.colData, start[i]-1, nPerLp, fits_parser_workfn, (void*)&Info, status ) == -1 ) *status = 0; else if( *status ) { ffcprs(&lParse); return( *status ); } if( Info.anyNull ) anyNull = 1; } if( newNullKwd && !anyNull ) { ffdkey( outfptr, nullKwd, status ); } } else { /* Put constant result into keyword */ result = lParse.Nodes + lParse.resultNode; switch( Info.datatype ) { case TDOUBLE: ffukyd( outfptr, parName, result->value.data.dbl, 15, parInfo, status ); break; case TLONG: ffukyj( outfptr, parName, result->value.data.lng, parInfo, status ); break; case TLOGICAL: ffukyl( outfptr, parName, result->value.data.log, parInfo, status ); break; case TBIT: case TSTRING: if (fits_strcasecmp(parName,"HISTORY") == 0) { ffphis( outfptr, result->value.data.str, status); } else if (fits_strcasecmp(parName,"COMMENT") == 0) { ffpcom( outfptr, result->value.data.str, status); } else { ffukys( outfptr, parName, result->value.data.str, parInfo, status ); } break; } } ffcprs(&lParse); return( *status ); } /*--------------------------------------------------------------------------*/ int fftexp( fitsfile *fptr, /* I - Input FITS file */ char *expr, /* I - Arithmetic expression */ int maxdim, /* I - Max Dimension of naxes */ int *datatype, /* O - Data type of result */ long *nelem, /* O - Vector length of result */ int *naxis, /* O - # of dimensions of result */ long *naxes, /* O - Size of each dimension */ int *status ) /* O - Error status */ /* */ /* Evaluate the given expression and return information on the result. */ /*--------------------------------------------------------------------------*/ { ParseData lParse; ffiprs( fptr, 0, expr, maxdim, datatype, nelem, naxis, naxes, &lParse, status ); ffcprs(&lParse); return( *status ); } /*--------------------------------------------------------------------------*/ int ffiprs( fitsfile *fptr, /* I - Input FITS file */ int compressed, /* I - Is FITS file hkunexpanded? */ char *expr, /* I - Arithmetic expression */ int maxdim, /* I - Max Dimension of naxes */ int *datatype, /* O - Data type of result */ long *nelem, /* O - Vector length of result */ int *naxis, /* O - # of dimensions of result */ long *naxes, /* O - Size of each dimension */ ParseData *lParse, /* O - parser status */ int *status ) /* O - Error status */ /* */ /* Initialize the parser and determine what type of result the expression */ /* produces. */ /*--------------------------------------------------------------------------*/ { Node *result; int i,lexpr, tstatus = 0; int xaxis, bitpix; long xaxes[9]; yyscan_t yylex_scanner; /* Used internally by FLEX lexer */ PixelFilter *pixFilter = 0; if( *status ) return( *status ); /* make sure all internal structures for this HDU are current */ if ( ffrdef(fptr, status) ) return(*status); /* Initialize the Parser structure */ /* Unfortunately we need to preserve the pixFilter value since it is pre-set when ffiprs() is called */ pixFilter = lParse->pixFilter; memset(lParse, 0, sizeof(*lParse)); lParse->pixFilter = pixFilter; lParse->def_fptr = fptr; lParse->compressed = compressed; lParse->nCols = 0; lParse->colData = NULL; lParse->varData = NULL; lParse->getData = find_column; lParse->loadData = load_column; lParse->Nodes = NULL; lParse->nNodesAlloc= 0; lParse->nNodes = 0; lParse->hdutype = 0; lParse->status = 0; fits_get_hdu_type(fptr, &(lParse->hdutype), status ); if (lParse->hdutype == IMAGE_HDU) { fits_get_img_param(fptr, 9, &bitpix, &xaxis, xaxes, status); if (*status) { ffpmsg("ffiprs: unable to get image dimensions"); return( *status ); } lParse->totalRows = xaxis > 0 ? 1 : 0; for (i = 0; i < xaxis; ++i) lParse->totalRows *= xaxes[i]; if (DEBUG_PIXFILTER) printf("naxis=%d, lParse->totalRows=%ld\n", xaxis, lParse->totalRows); } else if( ffgkyj(fptr, "NAXIS2", &lParse->totalRows, 0, &tstatus) ) { /* this might be a 1D or null image with no NAXIS2 keyword */ lParse->totalRows = 0; } /* Copy expression into parser... read from file if necessary */ if( expr[0]=='@' ) { if( ffimport_file( expr+1, &lParse->expr, status ) ) return( *status ); lexpr = strlen(lParse->expr); } else { lexpr = strlen(expr); lParse->expr = (char*)malloc( (2+lexpr)*sizeof(char)); strcpy(lParse->expr,expr); } strcat(lParse->expr + lexpr,"\n"); lParse->index = 0; lParse->is_eobuf = 0; /* Parse the expression, building the Nodes and determing */ /* which columns are needed and what data type is returned */ fits_parser_yylex_init_extra(lParse, &yylex_scanner); fits_parser_yyrestart(NULL, yylex_scanner); *status = fits_parser_yyparse(yylex_scanner, lParse); fits_parser_yylex_destroy(yylex_scanner); if( *status ) return( *status = PARSE_SYNTAX_ERR ); /* Check results */ *status = lParse->status; if( *status ) return(*status); if( !lParse->nNodes ) { ffpmsg("Blank expression"); return( *status = PARSE_SYNTAX_ERR ); } if( !lParse->nCols ) { lParse->colData = (iteratorCol *) malloc(sizeof(iteratorCol)); if (lParse->colData == 0) { ffpmsg("memory allocation failed (ffiprs)"); return( *status = MEMORY_ALLOCATION ); } /* This allows iterator to know value of */ /* fptr when no columns are referenced */ memset(lParse->colData, 0, sizeof(iteratorCol)); lParse->colData[0].fptr = fptr; } result = lParse->Nodes + lParse->resultNode; *naxis = lParse->nAxis = result->value.naxis; *nelem = lParse->nElements = result->value.nelem; for( i=0; i<*naxis && inAxes[i] = result->value.naxes[i]; switch( result->type ) { case BOOLEAN: *datatype = TLOGICAL; break; case LONG: *datatype = TLONG; break; case DOUBLE: *datatype = TDOUBLE; break; case BITSTR: *datatype = TBIT; break; case STRING: *datatype = TSTRING; break; default: *datatype = 0; ffpmsg("Bad return data type"); *status = lParse->status = PARSE_BAD_TYPE; break; } lParse->datatype = *datatype; FREE(lParse->expr); if( result->operation==CONST_OP ) *nelem = - *nelem; return(*status); } /*--------------------------------------------------------------------------*/ void ffcprs( ParseData *lParse ) /* */ /* Clear the parser, making it ready to accept a new expression. */ /*--------------------------------------------------------------------------*/ { int col, node, i; if( lParse->nCols > 0 ) { FREE( lParse->colData ); for( col=0; colnCols; col++ ) { if( lParse->varData[col].undef == NULL ) continue; if( lParse->varData[col].type == BITSTR ) FREE( ((char**)lParse->varData[col].data)[0] ); free( lParse->varData[col].undef ); } FREE( lParse->varData ); lParse->nCols = 0; } else if ( lParse->colData ) { /* Special case if colData needed to be created with no columns */ FREE( lParse->colData ); } if( lParse->nNodes > 0 ) { node = lParse->nNodes; while( node-- ) { if( lParse->Nodes[node].operation==gtifilt_fct ) { i = lParse->Nodes[node].SubNodes[0]; if (lParse->Nodes[ i ].value.data.ptr) FREE( lParse->Nodes[ i ].value.data.ptr ); } else if( lParse->Nodes[node].operation==regfilt_fct ) { i = lParse->Nodes[node].SubNodes[0]; fits_free_region( (SAORegion *)lParse->Nodes[ i ].value.data.ptr ); } } lParse->nNodes = 0; } if( lParse->Nodes ) free( lParse->Nodes ); lParse->Nodes = NULL; lParse->hdutype = ANY_HDU; lParse->pixFilter = 0; lParse->nDataRows = lParse->nPrevDataRows = 0; } /*---------------------------------------------------------------------------*/ int fits_parser_workfn( long totalrows, /* I - Total rows to be processed */ long offset, /* I - Number of rows skipped at start*/ long firstrow, /* I - First row of this iteration */ long nrows, /* I - Number of rows in this iter */ int nCols, /* I - Number of columns in use */ iteratorCol *colData, /* IO- Column information/data */ void *userPtr ) /* I - Data handling instructions */ /* */ /* Iterator work function which calls the parser and copies the results */ /* into either an OutputCol or a data pointer supplied in the userPtr */ /* structure. */ /*---------------------------------------------------------------------------*/ { int status, constant=0, anyNullThisTime=0; long jj, kk, idx, remain, ntodo; Node *result; iteratorCol * outcol; ParseData *lParse = ((parseInfo*)userPtr)->parseData; struct ParseStatusVariables *pv = &( ((parseInfo*)userPtr)->parseVariables ); void *Data0 = 0; /* declare variables static to preserve their values between calls */ long zeros[4] = {0,0,0,0}; if (DEBUG_PIXFILTER) printf("fits_parser_workfn(total=%ld, offset=%ld, first=%ld, rows=%ld, cols=%d)\n", totalrows, offset, firstrow, nrows, nCols); /*--------------------------------------------------------*/ /* Initialization procedures: execute on the first call */ /*--------------------------------------------------------*/ outcol = colData + (nCols - 1); if (firstrow == offset+1) { (pv->userInfo) = (parseInfo*)userPtr; (pv->userInfo)->anyNull = 0; /* Unfortunately there are two copies of the iterator columns, one inside the parser and one outside maintained by the higher level. (This could happen if the histogramming routines are binning multiple columns, and so there are multiple parsers being managed at one time.) Upon the first call we make sure they match */ for (jj = 0; jjcolData[jj].repeat = colData[jj].repeat; } if( (pv->userInfo)->maxRows>0 ) (pv->userInfo)->maxRows = minvalue(totalrows,(pv->userInfo)->maxRows); else if( (pv->userInfo)->maxRows<0 ) (pv->userInfo)->maxRows = totalrows; else (pv->userInfo)->maxRows = nrows; (pv->lastRow) = firstrow + (pv->userInfo)->maxRows - 1; /* dataPtr == NULL indicates an iterator-derived column, which means that the first value will be a null value and the remaining values will be the where the outputs are placed */ if( (pv->userInfo)->dataPtr==NULL ) { if( outcol->iotype == InputCol ) { ffpmsg("Output column for parser results not found!"); return( PARSE_NO_OUTPUT ); } /* Data gets set later */ (pv->Null) = outcol->array; (pv->userInfo)->datatype = outcol->datatype; /* Check for a TNULL/BLANK keyword for output column/image */ status = 0; (pv->jnull) = 0; if (lParse->hdutype == IMAGE_HDU) { if (lParse->pixFilter->blank) (pv->jnull) = (LONGLONG) lParse->pixFilter->blank; } else { if (outcol->iotype != TemporaryCol) { ffgknjj( outcol->fptr, "TNULL", outcol->colnum, 1, &(pv->jnull), (int*)&jj, &status ); } if( status==BAD_INTKEY || outcol->iotype == TemporaryCol) { /* Probably ASCII table with text TNULL keyword */ switch( (pv->userInfo)->datatype ) { case TSHORT: (pv->jnull) = (LONGLONG) SHRT_MIN; break; case TINT: (pv->jnull) = (LONGLONG) INT_MIN; break; case TLONG: (pv->jnull) = (LONGLONG) LONG_MIN; break; } } } (pv->repeat) = outcol->repeat; /* if (DEBUG_PIXFILTER) printf("fits_parser_workfn: using null value %ld\n", (pv->jnull)); */ } else { /* This clause applies if the user is passing user-allocated data arrays, which is where the data will be placed. This means they should also be passing null values */ (pv->Data) = (pv->userInfo)->dataPtr; (pv->Null) = ((pv->userInfo)->nullPtr ? (pv->userInfo)->nullPtr : zeros); (pv->repeat) = lParse->Nodes[lParse->resultNode].value.nelem; } /* Determine the size of each element of the returned result */ switch( (pv->userInfo)->datatype ) { case TBIT: /* Fall through to TBYTE */ case TLOGICAL: /* Fall through to TBYTE */ case TBYTE: (pv->datasize) = sizeof(char); break; case TSHORT: (pv->datasize) = sizeof(short); break; case TINT: (pv->datasize) = sizeof(int); break; case TLONG: (pv->datasize) = sizeof(long); break; case TLONGLONG: (pv->datasize) = sizeof(LONGLONG); break; case TFLOAT: (pv->datasize) = sizeof(float); break; case TDOUBLE: (pv->datasize) = sizeof(double); break; case TSTRING: (pv->datasize) = sizeof(char*); break; } /* Determine the size of each element of the calculated result */ /* (only matters for numeric/logical data) */ switch( lParse->Nodes[lParse->resultNode].type ) { case BOOLEAN: (pv->resDataSize) = sizeof(char); break; case LONG: (pv->resDataSize) = sizeof(long); break; case DOUBLE: (pv->resDataSize) = sizeof(double); break; } } /*-------------------------------------------*/ /* Main loop: process all the rows of data */ /*-------------------------------------------*/ /* If writing to output column, set first element to appropriate */ /* null value. If no NULLs encounter, zero out before returning. */ /* if (DEBUG_PIXFILTER) printf("fits_parser_workfn: using null value %ld\n", (pv->jnull)); */ if( (pv->userInfo)->dataPtr == NULL ) { /* First, reset Data pointer to start of output array, plus 1 because the 0th element is the null value (cute undocumented feature of the iterator!) */ (pv->Data) = (char*) outcol->array + (pv->datasize); /* A TemporaryCol with null value specified explicitly */ if (outcol->iotype == TemporaryCol && (pv->userInfo)->nullPtr) { pv->Null = (pv->userInfo)->nullPtr; } else { /* ... or an OutputCol or TemporaryCol with no explicit null */ switch( (pv->userInfo)->datatype ) { case TLOGICAL: *(char *)(pv->Null) = 'U'; break; case TBYTE: *(char *)(pv->Null) = (char )(pv->jnull); break; case TSHORT: *(short *)(pv->Null) = (short)(pv->jnull); break; case TINT: *(int *)(pv->Null) = (int )(pv->jnull); break; case TLONG: *(long *)(pv->Null) = (long )(pv->jnull); break; case TLONGLONG: *(LONGLONG *)(pv->Null) = (LONGLONG )(pv->jnull); break; case TFLOAT: *(float *)(pv->Null) = FLOATNULLVALUE; break; case TDOUBLE: *(double*)(pv->Null) = DOUBLENULLVALUE; break; case TSTRING: (*(char **)(pv->Null))[0] = '\1'; (*(char **)(pv->Null))[1] = '\0'; break; } } } /* Alter nrows in case calling routine didn't want to do all rows */ Data0 = pv->Data; /* Record starting point */ nrows = minvalue(nrows,(pv->lastRow)-firstrow+1); Setup_DataArrays( lParse, nCols, colData, firstrow, nrows ); /* Parser allocates arrays for each column and calculation it performs. */ /* Limit number of rows processed during each pass to reduce memory */ /* requirements... In most cases, iterator will limit rows to less */ /* than 10000 rows per iteration, so this is really only relevant for */ /* hk-compressed files which must be decompressed in memory and sent */ /* whole to fits_parser_workfn in a single iteration. */ remain = nrows; while( remain ) { ntodo = minvalue(remain,10000); Evaluate_Parser ( lParse, firstrow, ntodo ); if( lParse->status ) break; firstrow += ntodo; remain -= ntodo; /* Copy results into data array */ result = lParse->Nodes + lParse->resultNode; if( result->operation==CONST_OP ) constant = 1; switch( result->type ) { case BOOLEAN: case LONG: case DOUBLE: if( constant ) { char undef=0; for( kk=0; kkrepeat); jj++ ) ffcvtn( lParse->datatype, &(result->value.data), &undef, result->value.nelem /* 1 */, (pv->userInfo)->datatype, (pv->Null), (char*)(pv->Data) + (kk*(pv->repeat)+jj)*(pv->datasize), &anyNullThisTime, &lParse->status ); } else { if ( (pv->repeat) == result->value.nelem ) { ffcvtn( lParse->datatype, result->value.data.ptr, result->value.undef, result->value.nelem*ntodo, (pv->userInfo)->datatype, (pv->Null), (pv->Data), &anyNullThisTime, &lParse->status ); } else if( result->value.nelem == 1 ) { for( kk=0; kkrepeat); jj++ ) { ffcvtn( lParse->datatype, (char*)result->value.data.ptr + kk*(pv->resDataSize), (char*)result->value.undef + kk, 1, (pv->userInfo)->datatype, (pv->Null), (char*)(pv->Data) + (kk*(pv->repeat)+jj)*(pv->datasize), &anyNullThisTime, &lParse->status ); } } else { int nCopy; nCopy = minvalue( (pv->repeat), result->value.nelem ); for( kk=0; kkdatatype, (char*)result->value.data.ptr + kk*result->value.nelem*(pv->resDataSize), (char*)result->value.undef + kk*result->value.nelem, nCopy, (pv->userInfo)->datatype, (pv->Null), (char*)(pv->Data) + (kk*(pv->repeat))*(pv->datasize), &anyNullThisTime, &lParse->status ); if( nCopy < (pv->repeat) ) { memset( (char*)(pv->Data) + (kk*(pv->repeat)+nCopy)*(pv->datasize), 0, ((pv->repeat)-nCopy)*(pv->datasize)); } } } if( result->operation>0 ) { FREE( result->value.data.ptr ); } } if( lParse->status==OVERFLOW_ERR ) { lParse->status = NUM_OVERFLOW; ffpmsg("Numerical overflow while converting expression to necessary datatype"); } break; case BITSTR: switch( (pv->userInfo)->datatype ) { case TBYTE: idx = -1; for( kk=0; kkvalue.nelem; jj++ ) { if( jj%8 == 0 ) ((char*)(pv->Data))[++idx] = 0; if( constant ) { if( result->value.data.str[jj]=='1' ) ((char*)(pv->Data))[idx] |= 128>>(jj%8); } else { if( result->value.data.strptr[kk][jj]=='1' ) ((char*)(pv->Data))[idx] |= 128>>(jj%8); } } } break; case TBIT: case TLOGICAL: if( constant ) { for( kk=0; kkvalue.nelem; jj++ ) { ((char*)(pv->Data))[ jj+kk*result->value.nelem ] = ( result->value.data.str[jj]=='1' ); } } else { for( kk=0; kkvalue.nelem; jj++ ) { ((char*)(pv->Data))[ jj+kk*result->value.nelem ] = ( result->value.data.strptr[kk][jj]=='1' ); } } break; case TSTRING: if( constant ) { for( jj=0; jjData))[jj], result->value.data.str ); } } else { for( jj=0; jjData))[jj], result->value.data.strptr[jj] ); } } break; default: ffpmsg("Cannot convert bit expression to desired type."); lParse->status = PARSE_BAD_TYPE; break; } if( result->operation>0 ) { FREE( result->value.data.strptr[0] ); FREE( result->value.data.strptr ); } break; case STRING: if( (pv->userInfo)->datatype==TSTRING ) { if( constant ) { for( jj=0; jjData))[jj], result->value.data.str ); } else { for( jj=0; jjvalue.undef[jj] ) { anyNullThisTime = 1; strcpy( ((char**)(pv->Data))[jj], *(char **)(pv->Null) ); } else { strcpy( ((char**)(pv->Data))[jj], result->value.data.strptr[jj] ); } } } else { ffpmsg("Cannot convert string expression to desired type."); lParse->status = PARSE_BAD_TYPE; } if( result->operation>0 ) { FREE( result->value.data.strptr[0] ); FREE( result->value.data.strptr ); } break; } if( lParse->status ) break; /* Increment Data to point to where the next block should go */ if( result->type==BITSTR && (pv->userInfo)->datatype==TBYTE ) (pv->Data) = (char*)(pv->Data) + (pv->datasize) * ( (result->value.nelem+7)/8 ) * ntodo; else if( result->type==STRING ) (pv->Data) = (char*)(pv->Data) + (pv->datasize) * ntodo; else (pv->Data) = (char*)(pv->Data) + (pv->datasize) * ntodo * (pv->repeat); } /* If a TemporaryCol output is used, we want to inform the caller what the null value is expected to be */ if (pv->Null != outcol->array && (Data0) == (char*) outcol->array + (pv->datasize)) { if( (pv->userInfo)->datatype == TSTRING ) memcpy( outcol->array, *(char **)(pv->Null), 2 ); else memcpy( outcol->array, (pv->Null), (pv->datasize) ); } /* If no NULLs encountered during this pass, set Null value to */ /* zero to make the writing of the output column data faster */ if( anyNullThisTime ) (pv->userInfo)->anyNull = 1; else if( pv->Null == outcol->array ) { if( (pv->userInfo)->datatype == TSTRING ) memcpy( *(char **)(pv->Null), zeros, 2 ); else memcpy( (pv->Null), zeros, (pv->datasize) ); } /*-------------------------------------------------------*/ /* Clean up procedures: after processing all the rows */ /*-------------------------------------------------------*/ /* if the calling routine specified that only a limited number */ /* of rows in the table should be processed, return a value of -1 */ /* once all the rows have been done, if no other error occurred. */ if (lParse->hdutype != IMAGE_HDU && firstrow - 1 == (pv->lastRow)) { if (!lParse->status && (pv->userInfo)->maxRowsstatus); /* return successful status */ } static void Setup_DataArrays( ParseData *lParse, int nCols, iteratorCol *cols, long fRow, long nRows ) /***********************************************************************/ /* Setup the varData array in gParse to contain the fits column data. */ /* Then, allocate and initialize the necessary UNDEF arrays for each */ /* column used by the parser. */ /***********************************************************************/ { int i; long nelem, len, row, idx; char **bitStrs; char **sptr; char *barray; long *iarray; double *rarray; char msg[80]; int do_realloc = 0; lParse->firstDataRow = fRow; lParse->nDataRows = nRows; /* Only perform reallocations if the number of rows changed */ if (lParse->nPrevDataRows != nRows) do_realloc = 1; /* Resize and fill in UNDEF arrays for each column */ for( i=0; ivarData + i; if( icol->iotype == OutputCol || icol->iotype == TemporaryCol ) continue; nelem = varData->nelem; len = nelem * nRows; switch ( varData->type ) { case BITSTR: /* No need for UNDEF array, but must make string DATA array */ len = (nelem+1)*nRows; /* Count '\0' */ bitStrs = (char**)varData->data; if (do_realloc) { if( bitStrs ) FREE( bitStrs[0] ); free( bitStrs ); bitStrs = (char**)malloc( nRows*sizeof(char*) ); if( bitStrs==NULL ) { varData->data = varData->undef = NULL; lParse->status = MEMORY_ALLOCATION; break; } bitStrs[0] = (char*)malloc( len*sizeof(char) ); if( bitStrs[0]==NULL ) { free( bitStrs ); varData->data = varData->undef = NULL; lParse->status = MEMORY_ALLOCATION; break; } } for( row=0; rowarray)[idx] & (1<<(7-len%8)) ) bitStrs[row][len] = '1'; else bitStrs[row][len] = '0'; if( len%8==7 ) idx++; } bitStrs[row][len] = '\0'; } varData->undef = (char*)bitStrs; varData->data = (char*)bitStrs; break; case STRING: sptr = (char**)icol->array; if (do_realloc) { if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( nRows*sizeof(char) ); if( varData->undef==NULL ) { lParse->status = MEMORY_ALLOCATION; break; } } row = nRows; while( row-- ) varData->undef[row] = ( **sptr != '\0' && FSTRCMP( sptr[0], sptr[row+1] )==0 ); varData->data = sptr + 1; break; case BOOLEAN: barray = (char*)icol->array; if (do_realloc) { if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( len*sizeof(char) ); if( varData->undef==NULL ) { lParse->status = MEMORY_ALLOCATION; break; } } while( len-- ) { varData->undef[len] = ( barray[0]!=0 && barray[0]==barray[len+1] ); } varData->data = barray + 1; break; case LONG: iarray = (long*)icol->array; if (do_realloc) { if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( len*sizeof(char) ); if( varData->undef==NULL ) { lParse->status = MEMORY_ALLOCATION; break; } } while( len-- ) { varData->undef[len] = ( iarray[0]!=0L && iarray[0]==iarray[len+1] ); } varData->data = iarray + 1; break; case DOUBLE: rarray = (double*)icol->array; if (do_realloc) { if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( len*sizeof(char) ); if( varData->undef==NULL ) { lParse->status = MEMORY_ALLOCATION; break; } } while( len-- ) { varData->undef[len] = ( rarray[0]!=0.0 && rarray[0]==rarray[len+1]); } varData->data = rarray + 1; break; default: snprintf(msg, 80, "SetupDataArrays, unhandled type %d\n", varData->type); ffpmsg(msg); } if( lParse->status ) { /* Deallocate NULL arrays of previous columns */ while( i-- ) { varData = lParse->varData + i; if( varData->type==BITSTR ) FREE( ((char**)varData->data)[0] ); FREE( varData->undef ); varData->undef = NULL; } lParse->nPrevDataRows = 0; return; } } lParse->nPrevDataRows = nRows; } /*--------------------------------------------------------------------------*/ int ffcvtn( int inputType, /* I - Data type of input array */ void *input, /* I - Input array of type inputType */ char *undef, /* I - Array of flags indicating UNDEF elems */ long ntodo, /* I - Number of elements to process */ int outputType, /* I - Data type of output array */ void *nulval, /* I - Ptr to value to use for UNDEF elements */ void *output, /* O - Output array of type outputType */ int *anynull, /* O - Any nulls flagged? */ int *status ) /* O - Error status */ /* */ /* Convert an array of any input data type to an array of any output */ /* data type, using an array of UNDEF flags to assign nulvals to */ /*--------------------------------------------------------------------------*/ { long i; switch( outputType ) { case TLOGICAL: switch( inputType ) { case TLOGICAL: case TBYTE: for( i=0; i UCHAR_MAX ) { *status = OVERFLOW_ERR; ((unsigned char*)output)[i] = UCHAR_MAX; } else ((unsigned char*)output)[i] = (unsigned char) ((long*)input)[i]; } } return( *status ); case TFLOAT: fffr4i1((float*)input,ntodo,1.,0.,0,0,NULL,NULL, (unsigned char*)output,status); break; case TDOUBLE: fffr8i1((double*)input,ntodo,1.,0.,0,0,NULL,NULL, (unsigned char*)output,status); break; default: *status = BAD_DATATYPE; break; } for(i=0;i SHRT_MAX ) { *status = OVERFLOW_ERR; ((short*)output)[i] = SHRT_MAX; } else ((short*)output)[i] = (short) ((long*)input)[i]; } } return( *status ); case TFLOAT: fffr4i2((float*)input,ntodo,1.,0.,0,0,NULL,NULL, (short*)output,status); break; case TDOUBLE: fffr8i2((double*)input,ntodo,1.,0.,0,0,NULL,NULL, (short*)output,status); break; default: *status = BAD_DATATYPE; break; } for(i=0;inCols; if( fits_parser_allocateCol( lParse, col_cnt, status ) ) return *status; /* Set important variables for TemporaryCol where calculated results end up */ fits_iter_set_by_num( &(lParse->colData[col_cnt]), 0, 0, TDOUBLE, TemporaryCol); lParse->colData[col_cnt].repeat = lParse->nElements; Info->dataPtr = NULL; Info->nullPtr = nulval; Info->maxRows = nrows; Info->parseData = lParse; lParse->nCols ++; return 0; } /*---------------------------------------------------------------------------*/ int fits_uncompress_hkdata( ParseData *lParse, fitsfile *fptr, long ntimes, double *times, int *status ) /* */ /* description */ /*---------------------------------------------------------------------------*/ { char parName[256], *sPtr[1], found[1000]; int parNo, anynul; long naxis2, row, currelem; double currtime, newtime; sPtr[0] = parName; currelem = 0; currtime = -1e38; parNo=lParse->nCols; while( parNo-- ) found[parNo] = 0; if( ffgkyj( fptr, "NAXIS2", &naxis2, NULL, status ) ) return( *status ); for( row=1; row<=naxis2; row++ ) { if( ffgcvd( fptr, lParse->timeCol, row, 1L, 1L, 0.0, &newtime, &anynul, status ) ) return( *status ); if( newtime != currtime ) { /* New time encountered... propogate parameters to next row */ if( currelem==ntimes ) { ffpmsg("Found more unique time stamps than caller indicated"); return( *status = PARSE_BAD_COL ); } times[currelem++] = currtime = newtime; parNo = lParse->nCols; while( parNo-- ) { switch( lParse->colData[parNo].datatype ) { case TLONG: ((long*)lParse->colData[parNo].array)[currelem] = ((long*)lParse->colData[parNo].array)[currelem-1]; break; case TDOUBLE: ((double*)lParse->colData[parNo].array)[currelem] = ((double*)lParse->colData[parNo].array)[currelem-1]; break; case TSTRING: strcpy( ((char **)lParse->colData[parNo].array)[currelem], ((char **)lParse->colData[parNo].array)[currelem-1] ); break; } } } if( ffgcvs( fptr, lParse->parCol, row, 1L, 1L, "", sPtr, &anynul, status ) ) return( *status ); parNo = lParse->nCols; while( parNo-- ) if( !fits_strcasecmp( parName, lParse->varData[parNo].name ) ) break; if( parNo>=0 ) { found[parNo] = 1; /* Flag this parameter as found */ switch( lParse->colData[parNo].datatype ) { case TLONG: ffgcvj( fptr, lParse->valCol, row, 1L, 1L, ((long*)lParse->colData[parNo].array)[0], ((long*)lParse->colData[parNo].array)+currelem, &anynul, status ); break; case TDOUBLE: ffgcvd( fptr, lParse->valCol, row, 1L, 1L, ((double*)lParse->colData[parNo].array)[0], ((double*)lParse->colData[parNo].array)+currelem, &anynul, status ); break; case TSTRING: ffgcvs( fptr, lParse->valCol, row, 1L, 1L, ((char**)lParse->colData[parNo].array)[0], ((char**)lParse->colData[parNo].array)+currelem, &anynul, status ); break; } if( *status ) return( *status ); } } if( currelemnCols; while( parNo-- ) if( !found[parNo] ) { snprintf( parName, 256, "Parameter not found: %-30s", lParse->varData[parNo].name ); ffpmsg( parName ); *status = PARSE_SYNTAX_ERR; } return( *status ); } typedef struct { long *prownum; ParseData *lParse; } ffffrw_workdata; /*---------------------------------------------------------------------------*/ int ffffrw( fitsfile *fptr, /* I - Input FITS file */ char *expr, /* I - Boolean expression */ long *rownum, /* O - First row of table to eval to T */ int *status ) /* O - Error status */ /* */ /* Evaluate a boolean expression, returning the row number of the first */ /* row which evaluates to TRUE */ /*---------------------------------------------------------------------------*/ { int naxis, constant, dtype; long nelem, naxes[MAXDIMS]; char result; ParseData lParse; if( *status ) return( *status ); if( ffiprs( fptr, 0, expr, MAXDIMS, &dtype, &nelem, &naxis, naxes, &lParse, status ) ) { ffcprs(&lParse); return( *status ); } if( nelem<0 ) { constant = 1; nelem = -nelem; } else constant = 0; if( dtype!=TLOGICAL || nelem!=1 ) { ffcprs(&lParse); ffpmsg("Expression does not evaluate to a logical scalar."); return( *status = PARSE_BAD_TYPE ); } *rownum = 0; if( constant ) { /* No need to call parser... have result from ffiprs */ result = lParse.Nodes[lParse.resultNode].value.data.log; if( result ) { /* Make sure there is at least 1 row in table */ ffgnrw( fptr, &nelem, status ); if( nelem ) *rownum = 1; } } else { ffffrw_workdata workData; workData.prownum = rownum; workData.lParse = &lParse; if( ffiter( lParse.nCols, lParse.colData, 0, 0, ffffrw_work, (void*)&workData, status ) == -1 ) *status = 0; /* -1 indicates exitted without error before end... OK */ } ffcprs(&lParse); return(*status); } /*---------------------------------------------------------------------------*/ int ffffrw_work(long totalrows, /* I - Total rows to be processed */ long offset, /* I - Number of rows skipped at start*/ long firstrow, /* I - First row of this iteration */ long nrows, /* I - Number of rows in this iter */ int nCols, /* I - Number of columns in use */ iteratorCol *colData, /* IO- Column information/data */ void *userPtr ) /* I - Data handling instructions */ /* */ /* Iterator work function which calls the parser and searches for the */ /* first row which evaluates to TRUE. */ /*---------------------------------------------------------------------------*/ { long idx; Node *result; ffffrw_workdata *workData = userPtr; ParseData *lParse = workData->lParse; Evaluate_Parser( lParse, firstrow, nrows ); if( !lParse->status ) { result = lParse->Nodes + lParse->resultNode; if( result->operation==CONST_OP ) { if( result->value.data.log ) { *(workData->prownum) = firstrow; return( -1 ); } } else { for( idx=0; idxvalue.data.logptr[idx] && !result->value.undef[idx] ) { *(workData->prownum) = firstrow + idx;; return( -1 ); } } } return( lParse->status ); } static int set_image_col_types (ParseData *lParse, fitsfile * fptr, const char * name, int bitpix, DataInfo * varInfo, iteratorCol *colIter) { int istatus; double tscale, tzero; char temp[80]; switch (bitpix) { case BYTE_IMG: case SHORT_IMG: case LONG_IMG: istatus = 0; if (fits_read_key(fptr, TDOUBLE, "BZERO", &tzero, NULL, &istatus)) tzero = 0.0; istatus = 0; if (fits_read_key(fptr, TDOUBLE, "BSCALE", &tscale, NULL, &istatus)) tscale = 1.0; if (tscale == 1.0 && (tzero == 0.0 || tzero == 32768.0 )) { varInfo->type = LONG; colIter->datatype = TLONG; } else { varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; if (DEBUG_PIXFILTER) printf("use DOUBLE for %s with BSCALE=%g/BZERO=%g\n", name, tscale, tzero); } break; case LONGLONG_IMG: case FLOAT_IMG: case DOUBLE_IMG: varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; break; default: snprintf(temp, 80,"set_image_col_types: unrecognized image bitpix [%d]\n", bitpix); ffpmsg(temp); return lParse->status = PARSE_BAD_TYPE; } return 0; } /************************************************************************* Functions used by the evaluator to access FITS data (find_column, find_keywd, fits_parser_allocateCol, load_column) *************************************************************************/ static int find_column( ParseData *lParse, char *colName, void *itslval ) { FITS_PARSER_YYSTYPE *thelval = (FITS_PARSER_YYSTYPE*)itslval; int col_cnt, status; int colnum, typecode, type; long repeat, width; fitsfile *fptr; char temp[80]; double tzero,tscale; int istatus; DataInfo *varInfo; iteratorCol *colIter; if (DEBUG_PIXFILTER) printf("find_column(%s)\n", colName); if( *colName == '#' ) return( find_keywd( lParse, colName + 1, itslval ) ); fptr = lParse->def_fptr; status = 0; col_cnt = lParse->nCols; if (lParse->hdutype == IMAGE_HDU) { int i; if (!lParse->pixFilter) { lParse->status = COL_NOT_FOUND; ffpmsg("find_column: IMAGE_HDU but no PixelFilter"); return pERROR; } colnum = -1; for (i = 0; i < lParse->pixFilter->count; ++i) { if (!fits_strcasecmp(colName, lParse->pixFilter->tag[i])) colnum = i; } if (colnum < 0) { snprintf(temp, 80, "find_column: PixelFilter tag %s not found", colName); ffpmsg(temp); lParse->status = COL_NOT_FOUND; return pERROR; } if( fits_parser_allocateCol( lParse, col_cnt, &lParse->status ) ) return pERROR; varInfo = lParse->varData + col_cnt; colIter = lParse->colData + col_cnt; fptr = lParse->pixFilter->ifptr[colnum]; fits_get_img_param(fptr, MAXDIMS, &typecode, /* actually bitpix */ &varInfo->naxis, &varInfo->naxes[0], &status); varInfo->nelem = 1; type = COLUMN; if (set_image_col_types(lParse, fptr, colName, typecode, varInfo, colIter)) return pERROR; colIter->fptr = fptr; colIter->iotype = InputCol; } else { /* HDU holds a table */ if( lParse->compressed ) colnum = lParse->valCol; else if( fits_get_colnum( fptr, CASEINSEN, colName, &colnum, &status ) ) { if( status == COL_NOT_FOUND ) { type = find_keywd( lParse, colName, itslval ); if( type != pERROR ) ffcmsg(); return( type ); } lParse->status = status; return pERROR; } if( fits_get_coltype( fptr, colnum, &typecode, &repeat, &width, &status ) ) { lParse->status = status; return pERROR; } if( fits_parser_allocateCol( lParse, col_cnt, &lParse->status ) ) return pERROR; varInfo = lParse->varData + col_cnt; colIter = lParse->colData + col_cnt; fits_iter_set_by_num( colIter, fptr, colnum, 0, InputCol ); } /* Make sure we don't overflow variable name array */ strncpy(varInfo->name,colName,MAXVARNAME); varInfo->name[MAXVARNAME] = '\0'; if (lParse->hdutype != IMAGE_HDU) { switch( typecode ) { case TBIT: varInfo->type = BITSTR; colIter->datatype = TBYTE; type = BITCOL; break; case TBYTE: case TSHORT: case TLONG: /* The datatype of column with TZERO and TSCALE keywords might be float or double. */ snprintf(temp,80,"TZERO%d",colnum); istatus = 0; if(fits_read_key(fptr,TDOUBLE,temp,&tzero,NULL,&istatus)) { tzero = 0.0; } snprintf(temp,80,"TSCAL%d",colnum); istatus = 0; if(fits_read_key(fptr,TDOUBLE,temp,&tscale,NULL,&istatus)) { tscale = 1.0; } if (tscale == 1.0 && (tzero == 0.0 || tzero == 32768.0 )) { varInfo->type = LONG; colIter->datatype = TLONG; /* Reading an unsigned long column as a long can cause overflow errors. Treat the column as a double instead. } else if (tscale == 1.0 && tzero == 2147483648.0 ) { varInfo->type = LONG; colIter->datatype = TULONG; */ } else { varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; } type = COLUMN; break; /* For now, treat 8-byte integer columns as type double. This can lose precision, so the better long term solution will be to add support for TLONGLONG as a separate datatype. */ case TLONGLONG: case TFLOAT: case TDOUBLE: varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; type = COLUMN; break; case TLOGICAL: varInfo->type = BOOLEAN; colIter->datatype = TLOGICAL; type = BCOLUMN; break; case TSTRING: varInfo->type = STRING; colIter->datatype = TSTRING; type = SCOLUMN; if ( width >= MAX_STRLEN ) { snprintf(temp, 80, "column %d is wider than maximum %d characters", colnum, MAX_STRLEN-1); ffpmsg(temp); lParse->status = PARSE_LRG_VECTOR; return pERROR; } if( lParse->hdutype == ASCII_TBL ) repeat = width; break; default: if (typecode < 0) { snprintf(temp, 80,"variable-length array columns are not supported. typecode = %d", typecode); ffpmsg(temp); } lParse->status = PARSE_BAD_TYPE; return pERROR; } varInfo->nelem = repeat; colIter->repeat = 0; /* ffiter() will fill in this value */ if( repeat>1 && typecode!=TSTRING ) { if( fits_read_tdim( fptr, colnum, MAXDIMS, &varInfo->naxis, &varInfo->naxes[0], &status ) ) { lParse->status = status; return pERROR; } } else { varInfo->naxis = 1; varInfo->naxes[0] = 1; } } lParse->nCols++; thelval->lng = col_cnt; return( type ); } static int find_keywd(ParseData *lParse, char *keyname, void *itslval ) { FITS_PARSER_YYSTYPE *thelval = (FITS_PARSER_YYSTYPE*)itslval; int status, type; char keyvalue[FLEN_VALUE], dtype; fitsfile *fptr; double rval; int bval; long ival; status = 0; fptr = lParse->def_fptr; if( fits_read_keyword( fptr, keyname, keyvalue, NULL, &status ) ) { if( status == KEY_NO_EXIST ) { /* Do this since ffgkey doesn't put an error message on stack */ snprintf(keyvalue,FLEN_VALUE, "ffgkey could not find keyword: %s",keyname); ffpmsg(keyvalue); } lParse->status = status; return( pERROR ); } if( fits_get_keytype( keyvalue, &dtype, &status ) ) { lParse->status = status; return( pERROR ); } /* Read appropriate value type and set to CONST_OP */ switch( dtype ) { case 'C': fits_read_key_str( fptr, keyname, keyvalue, NULL, &status ); type = STRING; strcpy( thelval->str , keyvalue ); break; case 'L': fits_read_key_log( fptr, keyname, &bval, NULL, &status ); type = BOOLEAN; thelval->log = bval; break; case 'I': fits_read_key_lng( fptr, keyname, &ival, NULL, &status ); type = LONG; thelval->lng = ival; break; case 'F': fits_read_key_dbl( fptr, keyname, &rval, NULL, &status ); type = DOUBLE; thelval->dbl = rval; break; default: type = pERROR; break; } if( status ) { lParse->status=status; return pERROR; } return( type ); } /* Allocates parser iterator column storage for 25 columns *more* than nCols */ int fits_parser_allocateCol( ParseData *lParse, int nCol, int *status ) { if( (nCol%25)==0 ) { lParse->colData = (iteratorCol*) fits_recalloc( lParse->colData, nCol, nCol+25, sizeof(iteratorCol) ); lParse->varData = (DataInfo *) fits_recalloc( lParse->varData, nCol, nCol+25, sizeof(DataInfo) ); memset( (lParse->colData + nCol), 0x00, sizeof(iteratorCol)*25 ); memset( (lParse->varData + nCol), 0x00, sizeof(DataInfo)*25 ); if( lParse->colData == NULL || lParse->varData == NULL ) { if( lParse->colData ) free(lParse->colData); if( lParse->varData ) free(lParse->varData); lParse->colData = NULL; lParse->varData = NULL; return( *status = MEMORY_ALLOCATION ); } } lParse->varData[nCol].data = NULL; lParse->varData[nCol].undef = NULL; return 0; } static int load_column( ParseData *lParse, int varNum, long fRow, long nRows, void *data, char *undef ) { iteratorCol *var; long nelem,nbytes,row,len,idx; char **bitStrs, msg[80]; unsigned char *bytes; int status = 0, anynul; var = lParse->colData+varNum; if (lParse->hdutype == IMAGE_HDU) { /* This test would need to be on a per varNum basis to support * cross HDU operations */ fits_read_imgnull(var->fptr, var->datatype, fRow, nRows, data, undef, &anynul, &status); if (DEBUG_PIXFILTER) printf("load_column: IMAGE_HDU fRow=%ld, nRows=%ld => %d\n", fRow, nRows, status); } else { nelem = nRows * var->repeat; switch( var->datatype ) { case TBYTE: nbytes = ((var->repeat+7)/8) * nRows; bytes = (unsigned char *)malloc( nbytes * sizeof(char) ); ffgcvb(var->fptr, var->colnum, fRow, 1L, nbytes, 0, bytes, &anynul, &status); nelem = var->repeat; bitStrs = (char **)data; for( row=0; rowfptr, var->colnum, fRow, 1L, nRows, (char **)data, undef, &anynul, &status); break; case TLOGICAL: ffgcfl(var->fptr, var->colnum, fRow, 1L, nelem, (char *)data, undef, &anynul, &status); break; case TLONG: ffgcfj(var->fptr, var->colnum, fRow, 1L, nelem, (long *)data, undef, &anynul, &status); break; case TDOUBLE: ffgcfd(var->fptr, var->colnum, fRow, 1L, nelem, (double *)data, undef, &anynul, &status); break; default: snprintf(msg,80,"load_column: unexpected datatype %d", var->datatype); ffpmsg(msg); } } if( status ) { lParse->status = status; return pERROR; } return 0; } /*--------------------------------------------------------------------------*/ int fits_pixel_filter (PixelFilter * filter, int * status) /* Evaluate an expression using the data in the input FITS file(s) */ /*--------------------------------------------------------------------------*/ { parseInfo Info = { 0 }; int naxis, bitpix; long nelem, naxes[MAXDIMS]; int col_cnt; Node *result; int datatype; fitsfile * infptr; fitsfile * outfptr; char * DEFAULT_TAGS[] = { "X" }; char msg[256]; int writeBlankKwd = 0; /* write BLANK if any output nulls? */ ParseData lParse; DEBUG_PIXFILTER = getenv("DEBUG_PIXFILTER") ? 1 : 0; memset(&Info, 0, sizeof(Info)); if (*status) return (*status); if (!filter->tag || !filter->tag[0] || !filter->tag[0][0]) { filter->tag = DEFAULT_TAGS; if (DEBUG_PIXFILTER) printf("using default tag '%s'\n", filter->tag[0]); } infptr = filter->ifptr[0]; outfptr = filter->ofptr; lParse.pixFilter = filter; if (ffiprs(infptr, 0, filter->expression, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, &lParse, status)) { goto CLEANUP; } if (nelem < 0) { nelem = -nelem; } { /* validate result type */ const char * type = 0; switch (Info.datatype) { case TLOGICAL: type = "LOGICAL"; break; case TLONG: type = "LONG"; break; case TDOUBLE: type = "DOUBLE"; break; case TSTRING: type = "STRING"; *status = pERROR; ffpmsg("pixel_filter: cannot have string image"); case TBIT: type = "BIT"; if (DEBUG_PIXFILTER) printf("hmm, image from bits?\n"); break; default: type = "UNKNOWN?!"; *status = pERROR; ffpmsg("pixel_filter: unexpected result datatype"); } if (DEBUG_PIXFILTER) printf("result type is %s [%d]\n", type, Info.datatype); if (*status) goto CLEANUP; } if (fits_get_img_param(infptr, MAXDIMS, &bitpix, &naxis, &naxes[0], status)) { ffpmsg("pixel_filter: unable to read input image parameters"); goto CLEANUP; } if (DEBUG_PIXFILTER) printf("input bitpix %d\n", bitpix); if (Info.datatype == TDOUBLE) { /* for floating point expressions, set the default output image to bitpix = -32 (float) unless the default is already a double */ if (bitpix != DOUBLE_IMG) bitpix = FLOAT_IMG; } /* override output image bitpix if specified by caller */ if (filter->bitpix) bitpix = filter->bitpix; if (DEBUG_PIXFILTER) printf("output bitpix %d\n", bitpix); if (fits_create_img(outfptr, bitpix, naxis, naxes, status)) { ffpmsg("pixel_filter: unable to create output image"); goto CLEANUP; } /* transfer keycards */ { int i, ncards, more; if (fits_get_hdrspace(infptr, &ncards, &more, status)) { ffpmsg("pixel_filter: unable to determine number of keycards"); goto CLEANUP; } for (i = 1; i <= ncards; ++i) { int keyclass; char card[FLEN_CARD]; if (fits_read_record(infptr, i, card, status)) { snprintf(msg, 256,"pixel_filter: unable to read keycard %d", i); ffpmsg(msg); goto CLEANUP; } keyclass = fits_get_keyclass(card); if (keyclass == TYP_STRUC_KEY) { /* output structure defined by fits_create_img */ } else if (keyclass == TYP_COMM_KEY && i < 12) { /* assume this is one of the FITS standard comments */ } else if (keyclass == TYP_NULL_KEY && bitpix < 0) { /* do not transfer BLANK to real output image */ } else if (keyclass == TYP_SCAL_KEY && bitpix < 0) { /* do not transfer BZERO, BSCALE to real output image */ } else if (fits_write_record(outfptr, card, status)) { snprintf(msg,256, "pixel_filter: unable to write keycard '%s' [%d]\n", card, *status); ffpmsg(msg); goto CLEANUP; } } } switch (bitpix) { case BYTE_IMG: datatype = TLONG; Info.datatype = TBYTE; break; case SHORT_IMG: datatype = TLONG; Info.datatype = TSHORT; break; case LONG_IMG: datatype = TLONG; Info.datatype = TLONG; break; case FLOAT_IMG: datatype = TDOUBLE; Info.datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; Info.datatype = TDOUBLE; break; default: snprintf(msg, 256,"pixel_filter: unexpected output bitpix %d\n", bitpix); ffpmsg(msg); *status = pERROR; goto CLEANUP; } if (bitpix > 0) { /* arrange for NULLs in output */ long nullVal = filter->blank; if (!filter->blank) { int tstatus = 0; if (fits_read_key_lng(infptr, "BLANK", &nullVal, 0, &tstatus)) { writeBlankKwd = 1; if (bitpix == BYTE_IMG) nullVal = UCHAR_MAX; else if (bitpix == SHORT_IMG) nullVal = SHRT_MIN; else if (bitpix == LONG_IMG) { if (sizeof(long) == 8 && sizeof(int) == 4) nullVal = INT_MIN; else nullVal = LONG_MIN; } else printf("unhandled positive output BITPIX %d\n", bitpix); } filter->blank = nullVal; } fits_set_imgnull(outfptr, filter->blank, status); if (DEBUG_PIXFILTER) printf("using blank %ld\n", nullVal); } if (!filter->keyword[0]) { iteratorCol * colIter; DataInfo * varInfo; /*************************************/ /* Create new iterator Output Column */ /*************************************/ col_cnt = lParse.nCols; if (fits_parser_allocateCol(&lParse, col_cnt, status)) goto CLEANUP; lParse.nCols++; colIter = &lParse.colData[col_cnt]; colIter->fptr = filter->ofptr; colIter->iotype = OutputCol; varInfo = &lParse.varData[col_cnt]; set_image_col_types(&lParse, colIter->fptr, "CREATED", bitpix, varInfo, colIter); Info.maxRows = -1; Info.parseData = &lParse; if (ffiter(lParse.nCols, lParse.colData, 0, 0, fits_parser_workfn, &Info, status) == -1) *status = 0; else if (*status) goto CLEANUP; if (Info.anyNull) { if (writeBlankKwd) { fits_update_key_lng(outfptr, "BLANK", filter->blank, "NULL pixel value", status); if (*status) ffpmsg("pixel_filter: unable to write BLANK keyword"); if (DEBUG_PIXFILTER) { printf("output has NULLs\n"); printf("wrote blank [%d]\n", *status); } } } else if (bitpix > 0) /* never used a null */ if (fits_set_imgnull(outfptr, -1234554321, status)) ffpmsg("pixel_filter: unable to reset imgnull"); } else { /* Put constant result into keyword */ char * parName = filter->keyword; char * parInfo = filter->comment; result = lParse.Nodes + lParse.resultNode; switch (Info.datatype) { case TDOUBLE: ffukyd(outfptr, parName, result->value.data.dbl, 15, parInfo, status); break; case TLONG: ffukyj(outfptr, parName, result->value.data.lng, parInfo, status); break; case TLOGICAL: ffukyl(outfptr, parName, result->value.data.log, parInfo, status); break; case TBIT: case TSTRING: ffukys(outfptr, parName, result->value.data.str, parInfo, status); break; default: snprintf(msg, 256,"pixel_filter: unexpected constant result type [%d]\n", Info.datatype); ffpmsg(msg); } } CLEANUP: ffcprs(&lParse); return (*status); } cfitsio-4.3.1/drvrnet.c0000644000225700000360000037223514456514035014320 0ustar cagordonlhea/* This file, drvrhttp.c contains driver routines for http, ftp and root files. */ /* This file was written by Bruce O'Neel at the ISDC, Switzerland */ /* The FITSIO software is maintained by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* Notes on the drivers: The ftp driver uses passive mode exclusivly. If your remote system can't deal with passive mode then it'll fail. Since Netscape Navigator uses passive mode as well there shouldn't be too many ftp servers which have problems. The http driver works properly with 301 and 302 redirects. For many more gory details see http://www.w3c.org/Protocols/rfc2068/rfc2068. The only catch to the 301/302 redirects is that they have to redirect to another http:// url. If not, things would have to change a lot in cfitsio and this was thought to be too difficult. Redirects look like 301 Moved Permanently

Moved Permanently

The document has moved here.

This redirect was from apache 1.2.5 but most of the other servers produce something very similiar. The parser for the redirects finds the first anchor tag in the body and goes there. If that wasn't what was intended by the remote system then hopefully the error stack, which includes notes about the redirect will help the user fix the problem. **************************************************************** Note added in 2017: The redirect format shown above is actually preceded by 2 lines that look like HTTP/1.1 302 Found LOCATION: http://heasarc.gsfc.nasa.gov/FTP/software/ftools/release/other/image.fits.gz The CFITSIO parser now looks for the "Location:" string, not the html tag. **************************************************************** Root protocal doesn't have any real docs, so, the emperical docs are as follows. First, you must use a slightly modified rootd server. The modifications include implimentation of the stat command which returns the size of the remote file. Without that it's impossible for cfitsio to work properly since fitsfiles don't include any information about the size of the files in the headers. The rootd server closes the connections on any errors, including reading beyond the end of the file or seeking beyond the end of the file. The rootd:// driver doesn't reopen a closed connection, if the connection is closed you're pretty much done. The messages are of the form All binary information is transfered in network format, so use htonl and ntohl to convert back and forth. :== 4 byte length, in network format, the len doesn't include the length of :== one of the message opcodes below, 4 bytes, network format :== depends on opcode The response is of the same form with the same opcode sent. Success is indicated by being 0. Root is a NFSish protocol where each read/write includes the byte offset to read or write to. As a result, seeks will always succeed in the driver even if they would cause a fatal error when you try to read because you're beyond the end of the file. There is file locking on the host such that you need to possibly create /usr/tmp/rootdtab on the host system. There is one file per socket connection, though the rootd daemon can support multiple files open at once. The messages are sent in the following order: ROOTD_USER - user name, is the user name, trailing null is sent though it's not required it seems. A ROOTD_AUTH message is returned with any sort of error meaning that the user name is wrong. ROOTD_PASS - password, ones complemented, stored in . Once again the trailing null is sent. Once again a ROOTD_AUTH message is returned ROOTD_OPEN - includes filename and one of {create|update|read} as the file mode. ~ seems to be dealt with as the username's login directory. A ROOTD_OPEN message is returned. Once the file is opened any of the following can be sent: ROOTD_STAT - file status and size returns a message where is the file length in bytes ROOTD_FLUSH - flushes the file, not sure this has any real effect on the daemon since the daemon uses open/read/write/close rather than the buffered fopen/fread/fwrite/fclose. ROOTD_GET - on send includes a text message of offset and length to get. Return is a status message first with a status value, then, the raw bytes for the length that you requested. It's an error to seek or read past the end of the file, and, the rootd daemon exits and won't respond anymore. Ie, don't do this. ROOTD_PUT - on send includes a text message of offset and length to put. Then send the raw bytes you want to write. Then recieve a status message When you are finished then you send the message: ROOTD_CLOSE - closes the file Once the file is closed then the socket is closed. Revision 1.56 2000/01/04 11:58:31 oneel Updates so that compressed network files are dealt with regardless of their file names and/or mime types. Revision 1.55 2000/01/04 10:52:40 oneel cfitsio 2.034 Revision 1.51 1999/08/10 12:13:40 oneel Make the http code a bit less picky about the types of files it uncompresses. Now it also uncompresses files which end in .Z or .gz. Revision 1.50 1999/08/04 12:38:46 oneel Don's 2.0.32 patch with dal 1.3 Revision 1.39 1998/12/02 15:31:33 oneel Updates to drvrnet.c so that less compiler warnings would be generated. Fixes the signal handling. Revision 1.38 1998/11/23 10:03:24 oneel Added in a useragent string, as suggested by: Tim Kimball Data Systems Division kimball@stsci.edu 410-338-4417 Space Telescope Science Institute http://www.stsci.edu/~kimball/ 3700 San Martin Drive http://archive.stsci.edu/ Baltimore MD 21218 USA http://faxafloi.stsci.edu:4547/ */ #ifdef HAVE_NET_SERVICES #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFITSIO_HAVE_CURL #include #endif #if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) #include #endif #include #include #include "fitsio2.h" static jmp_buf env; /* holds the jump buffer for setjmp/longjmp pairs */ static void signal_handler(int sig); /* Network routine error codes */ #define NET_OK 0 #define NOT_INET_ADDRESS -1000 #define UNKNOWN_INET_HOST -1001 #define CONNECTION_ERROR -1002 /* Network routine constants */ #define NET_DEFAULT 0 #define NET_OOB 1 #define NET_PEEK 2 /* local defines and variables */ #define MAXLEN 1200 #define SHORTLEN 100 static char netoutfile[MAXLEN]; #define ROOTD_USER 2000 /*user id follows */ #define ROOTD_PASS 2001 /*passwd follows */ #define ROOTD_AUTH 2002 /*authorization status (to client) */ #define ROOTD_FSTAT 2003 /*filename follows */ #define ROOTD_OPEN 2004 /*filename follows + mode */ #define ROOTD_PUT 2005 /*offset, number of bytes and buffer */ #define ROOTD_GET 2006 /*offset, number of bytes */ #define ROOTD_FLUSH 2007 /*flush file */ #define ROOTD_CLOSE 2008 /*close file */ #define ROOTD_STAT 2009 /*return rootd statistics */ #define ROOTD_ACK 2010 /*acknowledgement (all OK) */ #define ROOTD_ERR 2011 /*error code and message follow */ typedef struct /* structure containing disk file structure */ { int sock; LONGLONG currentpos; } rootdriver; typedef struct /* simple mem struct for receiving files from curl */ { char *memory; size_t size; } curlmembuf; static rootdriver handleTable[NMAXFILES]; /* allocate diskfile handle tables */ /* static prototypes */ static int NET_TcpConnect(char *hostname, int port); static int NET_SendRaw(int sock, const void *buf, int length, int opt); static int NET_RecvRaw(int sock, void *buffer, int length); static int NET_ParseUrl(const char *url, char *proto, char *host, int *port, char *fn); static int CreateSocketAddress(struct sockaddr_in *sockaddrPtr, char *host,int port); static int ftp_status(FILE *ftp, char *statusstr); static int http_open_network(char *url, FILE **httpfile, char *contentencoding, char *contenttype, int *contentlength); static int https_open_network(char *filename, curlmembuf* buffer); static int ftp_open_network(char *url, FILE **ftpfile, FILE **command, int *sock); static int ftps_open_network(char *filename, curlmembuf* buffer); static int ftp_file_exist(char *url); static int root_send_buffer(int sock, int op, char *buffer, int buflen); static int root_recv_buffer(int sock, int *op, char *buffer,int buflen); static int root_openfile(char *filename, char *rwmode, int *sock); static int encode64(unsigned s_len, char *src, unsigned d_len, char *dst); static int ssl_get_with_curl(char *url, curlmembuf* buffer, char* username, char* password); static size_t curlToMemCallback(void *buffer, size_t size, size_t nmemb, void *userp); static int curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); /***************************/ /* Static variables */ static int closehttpfile; static int closememfile; static int closefdiskfile; static int closediskfile; static int closefile; static int closeoutfile; static int closecommandfile; static int closeftpfile; static FILE *diskfile; static FILE *outfile; static int curl_verbose=0; static int show_fits_download_progress=0; static unsigned int net_timeout = 360; /* in seconds */ /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The file is uncompressed if necessary */ int http_open(char *filename, int rwmode, int *handle) { FILE *httpfile; char contentencoding[SHORTLEN], contenttype[SHORTLEN]; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int contentlength; int status; char firstchar; closehttpfile = 0; closememfile = 0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open http:// type file with READWRITE access"); ffpmsg(" Specify an outfile for r/w access (http_open)"); goto error; } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); snprintf(errorstr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errorstr); ffpmsg(" (multiplied x10 for files requiring uncompression)"); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); goto error; } (void) signal(SIGALRM, signal_handler); /* Open the network connection */ if (http_open_network(filename,&httpfile, contentencoding, contenttype, &contentlength)) { alarm(0); ffpmsg("Unable to open http file (http_open):"); ffpmsg(filename); goto error; } closehttpfile++; /* Create the memory file */ if ((status = mem_create(filename,handle))) { ffpmsg("Unable to create memory file (http_open)"); goto error; } closememfile++; /* Now, what do we do with the file */ /* Check to see what the first character is */ firstchar = fgetc(httpfile); ungetc(firstchar,httpfile); if (!strcmp(contentencoding,"x-gzip") || !strcmp(contentencoding,"x-compress") || !strcmp(contenttype, "application/x-gzip") || !strcmp(contenttype, "application/gzip") || !strcmp(contenttype, "application/gzip-compressed") || !strcmp(contenttype, "application/gzipped") || !strcmp(contenttype, "application/x-compress") || !strcmp(contenttype, "application/x-compressed") || strstr(filename,".gz") || strstr(filename,".Z") || ('\037' == firstchar)) { /* do the compress dance, which is the same as the gzip dance */ /* Using the cfitsio routine */ status = 0; /* Ok, this is a tough case, let's be arbritary and say 10*net_timeout, Given the choices for nettimeout above they'll probaby ^C before, but it's always worth a shot*/ alarm(net_timeout*10); status = mem_uncompress2mem(filename, httpfile, *handle); alarm(0); if (status) { ffpmsg("Error writing compressed memory file (http_open)"); ffpmsg(filename); goto error; } } else { /* It's not compressed, bad choice, but we'll copy it anyway */ if (contentlength % 2880) { snprintf(errorstr,MAXLEN,"Content-Length not a multiple of 2880 (http_open) %d", contentlength); ffpmsg(errorstr); } /* write a memory file */ alarm(net_timeout); while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { alarm(0); /* cancel alarm */ status = mem_write(*handle,recbuf,len); if (status) { ffpmsg("Error copying http file into memory (http_open)"); ffpmsg(filename); goto error; } alarm(net_timeout); /* rearm the alarm */ } } fclose(httpfile); signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closehttpfile) { fclose(httpfile); } if (closememfile) { mem_close_free(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The file must be compressed and is copied (still compressed) to disk first. The compressed disk file is then uncompressed into memory (READONLY). */ int http_compress_open(char *url, int rwmode, int *handle) { FILE *httpfile; char contentencoding[SHORTLEN], contenttype[SHORTLEN]; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int contentlength; int ii, flen, status; char firstchar; closehttpfile = 0; closediskfile = 0; closefdiskfile = 0; closememfile = 0; flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, should set the netoufile first otherwise we don't know where to write the output file */ ffpmsg ("Output file not set, shouldn't have happened (http_compress_open)"); goto error; } if (rwmode != 0) { ffpmsg("Can't open compressed http:// type file with READWRITE access"); ffpmsg(" Specify an UNCOMPRESSED outfile (http_compress_open)"); goto error; } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); snprintf(errorstr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errorstr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); goto error; } signal(SIGALRM, signal_handler); /* Open the http connectin */ alarm(net_timeout); if ((status = http_open_network(url,&httpfile, contentencoding, contenttype, &contentlength))) { alarm(0); ffpmsg("Unable to open http file (http_compress_open)"); ffpmsg(url); goto error; } closehttpfile++; /* Better be compressed */ firstchar = fgetc(httpfile); ungetc(firstchar,httpfile); if (!strcmp(contentencoding,"x-gzip") || !strcmp(contentencoding,"x-compress") || !strcmp(contenttype, "application/x-gzip") || !strcmp(contenttype, "application/gzip") || !strcmp(contenttype, "application/gzip-compressed") || !strcmp(contenttype, "application/gzipped") || !strcmp(contenttype, "application/x-compress") || !strcmp(contenttype, "application/x-compressed") || ('\037' == firstchar)) { if (*netoutfile == '!') { /* user wants to clobber file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } /* Create the new file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output disk file (http_compress_open):"); ffpmsg(netoutfile); goto error; } closediskfile++; /* write a file */ alarm(net_timeout); while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing disk file (http_compres_open)"); ffpmsg(netoutfile); goto error; } alarm(net_timeout); } file_close(*handle); fclose(httpfile); closehttpfile--; closediskfile--; /* File is on disk, let's uncompress it into memory */ if (NULL == (diskfile = fopen(netoutfile,"r"))) { ffpmsg("Unable to reopen disk file (http_compress_open)"); ffpmsg(netoutfile); goto error; } closefdiskfile++; /* Create the memory handle to hold it */ if ((status = mem_create(url,handle))) { ffpmsg("Unable to create memory file (http_compress_open)"); goto error; } closememfile++; /* Uncompress it */ status = 0; status = mem_uncompress2mem(url,diskfile,*handle); fclose(diskfile); closefdiskfile--; if (status) { ffpmsg("Error uncompressing disk file to memory (http_compress_open)"); ffpmsg(netoutfile); goto error; } } else { /* Opps, this should not have happened */ ffpmsg("Can only have compressed files here (http_compress_open)"); goto error; } signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closehttpfile) { fclose(httpfile); } if (closefdiskfile) { fclose(diskfile); } if (closememfile) { mem_close_free(*handle); } if (closediskfile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a file handle with a copy of the URL in filename. The http file is copied to disk first. If it's compressed then it is uncompressed when copying to the disk */ int http_file_open(char *url, int rwmode, int *handle) { FILE *httpfile; char contentencoding[SHORTLEN], contenttype[SHORTLEN]; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int contentlength; int ii, flen, status; char firstchar; /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( http_open(url, READONLY, handle) ); } closehttpfile = 0; closefile = 0; closeoutfile = 0; flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, we need to know where to write the file */ ffpmsg("Output file not set, shouldn't have happened (http_file_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); snprintf(errorstr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errorstr); ffpmsg(" (multiplied x10 for files requiring uncompression)"); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); goto error; } signal(SIGALRM, signal_handler); /* Open the network connection */ alarm(net_timeout); if ((status = http_open_network(url,&httpfile, contentencoding, contenttype, &contentlength))) { alarm(0); ffpmsg("Unable to open http file (http_file_open)"); ffpmsg(url); goto error; } closehttpfile++; if (*netoutfile == '!') { /* user wants to clobber disk file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } firstchar = fgetc(httpfile); ungetc(firstchar,httpfile); if (!strcmp(contentencoding,"x-gzip") || !strcmp(contentencoding,"x-compress") || !strcmp(contenttype, "application/x-gzip") || !strcmp(contenttype, "application/gzip") || !strcmp(contenttype, "application/gzip-compressed") || !strcmp(contenttype, "application/gzipped") || !strcmp(contenttype, "application/x-compress") || !strcmp(contenttype, "application/x-compressed") || ('\037' == firstchar)) { /* to make this more cfitsioish we use the file driver calls to create the disk file */ /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (http_file_open)"); ffpmsg(netoutfile); goto error; } file_close(*handle); if (NULL == (outfile = fopen(netoutfile,"w"))) { ffpmsg("Unable to reopen the output file (http_file_open)"); ffpmsg(netoutfile); goto error; } closeoutfile++; status = 0; /* Ok, this is a tough case, let's be arbritary and say 10*net_timeout, Given the choices for nettimeout above they'll probaby ^C before, but it's always worth a shot*/ alarm(net_timeout*10); status = uncompress2file(url,httpfile,outfile,&status); alarm(0); if (status) { ffpmsg("Error uncompressing http file to disk file (http_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } fclose(outfile); closeoutfile--; } else { /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (http_file_open)"); ffpmsg(netoutfile); goto error; } /* Give a warning message. This could just be bad padding at the end so don't treat it like an error. */ closefile++; if (contentlength % 2880) { snprintf(errorstr, MAXLEN, "Content-Length not a multiple of 2880 (http_file_open) %d", contentlength); ffpmsg(errorstr); } /* write a file */ alarm(net_timeout); while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error copying http file to disk file (http_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } } file_close(*handle); closefile--; } fclose(httpfile); closehttpfile--; signal(SIGALRM, SIG_DFL); alarm(0); return file_open(netoutfile,rwmode,handle); error: alarm(0); /* clear it */ if (closehttpfile) { fclose(httpfile); } if (closeoutfile) { fclose(outfile); } if (closefile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This is the guts of the code to get a file via http. url is the input url httpfile is set to be the file connected to the socket which you can read the file from contentencoding is the mime type of the file, returned if the http server returns it contentlength is the length of the file, returned if the http server returns it */ static int http_open_network(char *url, FILE **httpfile, char *contentencoding, char *contenttype, int *contentlength) { int status; int sock; int tmpint; char recbuf[MAXLEN]; char tmpstr[MAXLEN]; char tmpstr1[SHORTLEN]; char tmpstr2[MAXLEN]; char errorstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char userpass[MAXLEN]; char fn[MAXLEN]; char turl[MAXLEN]; char *scratchstr; char *scratchstr2; char *saveptr; int port; float version; char pproto[SHORTLEN]; char phost[SHORTLEN]; /* address of the proxy server */ int pport; /* port number of the proxy server */ char pfn[MAXLEN]; char *proxy; /* URL of the proxy server */ /* Parse the URL apart again */ strcpy(turl,"http://"); strncat(turl,url,MAXLEN - 8); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (http_open) %s",url); ffpmsg(errorstr); return (FILE_NOT_OPENED); } /* Do we have a user:password combo ? */ strcpy(userpass, url); if ((scratchstr = strchr(userpass, '@')) != NULL) { *scratchstr = '\0'; } else { strcpy(userpass, ""); } /* Ph. Prugniel 2003/04/03 Are we using a proxy? We use a proxy if the environment variable "http_proxy" is set to an address, eg. http://wwwcache.nottingham.ac.uk:3128 ("http_proxy" is also used by wget) */ proxy = getenv("http_proxy"); /* Connect to the remote host */ if (proxy) { if (NET_ParseUrl(proxy,pproto,phost,&pport,pfn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (http_open) %s",proxy); ffpmsg(errorstr); return (FILE_NOT_OPENED); } sock = NET_TcpConnect(phost,pport); } else { sock = NET_TcpConnect(host,port); } if (sock < 0) { if (proxy) { ffpmsg("Couldn't connect to host via proxy server (http_open_network)"); ffpmsg(proxy); } return (FILE_NOT_OPENED); } /* Make the socket a stdio file */ if (NULL == (*httpfile = fdopen(sock,"r"))) { ffpmsg ("fdopen failed to convert socket to file (http_open_network)"); close(sock); return (FILE_NOT_OPENED); } /* Send the GET request to the remote server */ /* Ph. Prugniel 2003/04/03 One must add the Host: command because of HTTP 1.1 servers (ie. virtual hosts) */ if (proxy) { snprintf(tmpstr,MAXLEN,"GET http://%s:%-d%s HTTP/1.0\r\n",host,port,fn); } else { snprintf(tmpstr,MAXLEN,"GET %s HTTP/1.0\r\n",fn); } if (strcmp(userpass, "")) { encode64(strlen(userpass), userpass, MAXLEN, tmpstr2); snprintf(tmpstr1, SHORTLEN,"Authorization: Basic %s\r\n", tmpstr2); if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) { fclose(*httpfile); *httpfile=0; return (FILE_NOT_OPENED); } strcat(tmpstr,tmpstr1); } /* snprintf(tmpstr1,SHORTLEN,"User-Agent: HEASARC/CFITSIO/%-8.4f\r\n",ffvers(&version)); */ /* snprintf(tmpstr1,SHORTLEN,"User-Agent: CFITSIO/HEASARC/%-8.4f\r\n",ffvers(&version)); */ snprintf(tmpstr1,SHORTLEN,"User-Agent: FITSIO/HEASARC/%-8.4f\r\n",ffvers(&version)); if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) { fclose(*httpfile); *httpfile=0; return (FILE_NOT_OPENED); } strcat(tmpstr,tmpstr1); /* HTTP 1.1 servers require the following 'Host: ' string */ snprintf(tmpstr1,SHORTLEN,"Host: %s:%-d\r\n\r\n",host,port); if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) { fclose(*httpfile); *httpfile=0; return (FILE_NOT_OPENED); } strcat(tmpstr,tmpstr1); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); /* read the header */ if (!(fgets(recbuf,MAXLEN,*httpfile))) { snprintf (errorstr,MAXLEN,"http header short (http_open_network) %s",recbuf); ffpmsg(errorstr); fclose(*httpfile); *httpfile=0; return (FILE_NOT_OPENED); } *contentlength = 0; contentencoding[0] = '\0'; contenttype[0] = '\0'; /* Our choices are 200, ok, 302, temporary redirect, or 301 perm redirect */ sscanf(recbuf,"%s %d",tmpstr,&status); if (status != 200){ if (status == 301 || status == 302) { /* got a redirect */ /* if (status == 302) { ffpmsg("Note: Web server replied with a temporary redirect from"); } else { ffpmsg("Note: Web server replied with a redirect from"); } ffpmsg(turl); */ /* now, let's not write the most sophisticated parser here */ while (fgets(recbuf,MAXLEN,*httpfile)) { scratchstr = strstr(recbuf,"Location: "); if (scratchstr != NULL) { /* Ok, we found the Location line which gives the redirected URL */ /* skip the "Location: " charactrers */ scratchstr += 10; /* strip off any end-of-line characters */ tmpint = strlen(scratchstr); if (scratchstr[tmpint-1] == '\r') scratchstr[tmpint-1] = '\0'; tmpint = strlen(scratchstr); if (scratchstr[tmpint-1] == '\n') scratchstr[tmpint-1] = '\0'; tmpint = strlen(scratchstr); if (scratchstr[tmpint-1] == '\r') scratchstr[tmpint-1] = '\0'; /* ffpmsg("to:"); ffpmsg(scratchstr); ffpmsg(" "); */ scratchstr2 = strstr(scratchstr,"http://"); if (scratchstr2 != NULL) { /* Ok, we found the HTTP redirection is to another HTTP URL. */ /* We can handle this case directly, here */ /* skip the "http://" characters */ scratchstr2 += 7; strcpy(turl, scratchstr2); fclose (*httpfile); *httpfile=0; /* note the recursive call to itself */ return http_open_network(turl,httpfile, contentencoding, contenttype, contentlength); } /* It was not a HTTP to HTTP redirection, so see if it HTTP to FTP */ scratchstr2 = strstr(scratchstr,"ftp://"); if (scratchstr2 != NULL) { /* Ok, we found the HTTP redirection is to a FTP URL. */ /* skip the "ftp://" characters */ scratchstr2 += 6; /* return the new URL string, and set contentencoding to "ftp" as a flag to the http_checkfile routine */ if (strlen(scratchstr2) > FLEN_FILENAME-1) { ffpmsg("Error: redirected url string too long (http_open_network)"); fclose(*httpfile); *httpfile=0; return URL_PARSE_ERROR; } strcpy(url, scratchstr2); strcpy(contentencoding,"ftp://"); fclose (*httpfile); *httpfile=0; return 0; } /* Now check for HTTP to HTTPS redirection. */ scratchstr2 = strstr(scratchstr,"https://"); if (scratchstr2 != NULL) { /* skip the "https://" characters */ scratchstr2 += 8; /* return the new URL string, and set contentencoding to "https" as a flag to the http_checkfile routine */ if (strlen(scratchstr2) > FLEN_FILENAME-1) { ffpmsg("Error: redirected url string too long (http_open_network)"); fclose(*httpfile); return URL_PARSE_ERROR; } strcpy(url, scratchstr2); strcpy(contentencoding,"https://"); fclose(*httpfile); *httpfile=0; return 0; } } } /* if we get here then we couldnt' decide the redirect */ ffpmsg("but we were unable to find the redirected url in the servers response"); } /* error. could not open the http file */ fclose(*httpfile); *httpfile=0; return (FILE_NOT_OPENED); } /* from here the first word holds the keyword we want */ /* so, read the rest of the header */ while (fgets(recbuf,MAXLEN,*httpfile)) { /* Blank line ends the header */ if (*recbuf == '\r') break; if (strlen(recbuf) > 3) { recbuf[strlen(recbuf)-1] = '\0'; recbuf[strlen(recbuf)-1] = '\0'; } sscanf(recbuf,"%s %d",tmpstr,&tmpint); /* Did we get a content-length header ? */ if (!strcmp(tmpstr,"Content-Length:")) { *contentlength = tmpint; } /* Did we get the content-encoding header ? */ if (!strcmp(tmpstr,"Content-Encoding:")) { if (NULL != (scratchstr = strstr(recbuf,":"))) { /* Found the : */ scratchstr++; /* skip the : */ scratchstr++; /* skip the extra space */ if (strlen(scratchstr) > SHORTLEN-1) { ffpmsg("Error: content-encoding string too long (http_open_network)"); fclose(*httpfile); *httpfile=0; return URL_PARSE_ERROR; } strcpy(contentencoding,scratchstr); } } /* Did we get the content-type header ? */ if (!strcmp(tmpstr,"Content-Type:")) { if (NULL != (scratchstr = strstr(recbuf,":"))) { /* Found the : */ scratchstr++; /* skip the : */ scratchstr++; /* skip the extra space */ if (strlen(scratchstr) > SHORTLEN-1) { ffpmsg("Error: content-type string too long (http_open_network)"); fclose(*httpfile); *httpfile=0; return URL_PARSE_ERROR; } strcpy(contenttype,scratchstr); } } } /* we're done, so return */ return 0; } /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The curl library called from https_open_network will perform file uncompression if necessary. */ int https_open(char *filename, int rwmode, int *handle) { curlmembuf inmem; char errStr[MAXLEN]; int status=0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open https:// type file with READWRITE access"); ffpmsg(" Specify an outfile for r/w access (https_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (https_open)"); snprintf(errStr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errStr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(net_timeout); if (https_open_network(filename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read https file into memory (https_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); /* We now have the file transfered from the https server into the inmem.memory buffer. Now transfer that into a FITS memory file. */ if ((status = mem_create(filename, handle))) { ffpmsg("Unable to create memory file (https_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } /* Check for gzip magic number */ if (inmem.size >= 2 && (unsigned char) inmem.memory[0] == 0x1f && (unsigned char) inmem.memory[1] == 0x8b) { LONGLONG fitsfilesize = 0; /* Uncompress from memory to memfile */ status = mem_zuncompress_and_write(*handle, inmem.memory, inmem.size); mem_size(*handle, &fitsfilesize); if ((fitsfilesize > 0) && (fitsfilesize % 2880)) { snprintf(errStr,MAXLEN,"Uncompressed file length not a multiple of 2880 (https_open) %lld", fitsfilesize); ffpmsg(errStr); } } else { if (inmem.size % 2880) { snprintf(errStr,MAXLEN,"Content-Length not a multiple of 2880 (https_open) %zu", inmem.size); ffpmsg(errStr); } /* Straight copy of data */ status = mem_write(*handle, inmem.memory, inmem.size); } if (status) { ffpmsg("Error copying https file into memory (https_open)"); ffpmsg(filename); free(inmem.memory); mem_close_free(*handle); return (FILE_NOT_OPENED); } free(inmem.memory); return mem_seek(*handle, 0); } /*--------------------------------------------------------------------------*/ int https_file_open(char *filename, int rwmode, int *handle) { int ii, flen; char errStr[MAXLEN]; curlmembuf inmem; /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( https_open(filename, READONLY, handle) ); } flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, we need to know where to write the file */ ffpmsg("Output file not set, shouldn't have happened (https_file_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (https_file_open)"); snprintf(errStr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errStr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(net_timeout); if (https_open_network(filename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read https file into memory (https_file_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); if (*netoutfile == '!') { /* user wants to clobber disk file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ file_remove(netoutfile); } /* Create the output file */ if (file_create(netoutfile,handle)) { ffpmsg("Unable to create output file (https_file_open)"); ffpmsg(netoutfile); free(inmem.memory); return (FILE_NOT_OPENED); } if (inmem.size % 2880) { snprintf(errStr, MAXLEN, "Content-Length not a multiple of 2880 (https_file_open) %zu", inmem.size); ffpmsg(errStr); } if (file_write(*handle, inmem.memory, inmem.size)) { ffpmsg("Error copying https file to disk file (https_file_open)"); ffpmsg(filename); ffpmsg(netoutfile); free(inmem.memory); file_close(*handle); return (FILE_NOT_OPENED); } free(inmem.memory); file_close(*handle); return file_open(netoutfile, rwmode, handle); } /*--------------------------------------------------------------------------*/ /* Callback function curl library uses during https connection to transfer server file into memory */ size_t curlToMemCallback(void *buffer, size_t size, size_t nmemb, void *userp) { curlmembuf* inmem = (curlmembuf* )userp; size_t transferSize = size*nmemb; if (!inmem->size) { /* First time through - initialize with malloc */ inmem->memory = (char *)malloc(transferSize); } else inmem->memory = realloc(inmem->memory, inmem->size+transferSize); if (inmem->memory == NULL) { ffpmsg("realloc error - not enough memory (curlToMemCallback)\n"); return 0; } memcpy(&(inmem->memory[inmem->size]), buffer, transferSize); inmem->size += transferSize; return transferSize; } /*--------------------------------------------------------------------------*/ /* Callback function for displaying status bar during download */ int curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { int i, fullBar = 50, nToDisplay = 0; int percent = 0; double fracCompleted = 0.0; char *urlname=0; static int isComplete = 0; static int isFirst = 1; /* isFirst is true the very first time this is entered. Afterwards it should get reset to true when isComplete is first detected to have toggled from true to false. */ if (dltotal == 0.0) { if (isComplete) isFirst = 1; isComplete = 0; return 0; } fracCompleted = dlnow/dltotal; percent = (int)ceil(fracCompleted*100.0 - 0.5); if (isComplete && percent < 100) isFirst = 1; if (!isComplete || percent < 100) { if (isFirst) { urlname = (char *)clientp; if (urlname) { fprintf(stderr,"Downloading "); fprintf(stderr,"%s",urlname); fprintf(stderr,"...\n"); } isFirst = 0; } isComplete = (percent >= 100) ? 1 : 0; nToDisplay = (int)ceil(fracCompleted*fullBar - 0.5); /* Can dlnow ever be > dltotal? Just in case... */ if (nToDisplay > fullBar) nToDisplay = fullBar; fprintf(stderr,"%3d%% [",percent); for (i=0; i 0) net_timeout = (unsigned int)sec; return (int)net_timeout; } /*--------------------------------------------------------------------------*/ int ftps_open(char *filename, int rwmode, int *handle) { curlmembuf inmem; char errStr[MAXLEN]; char localFilename[MAXLEN]; /* may have .gz or .Z appended in ftps_open_network.*/ unsigned char firstByte=0,secondByte=0; int status=0; FILE *compressedFile=0; strcpy(localFilename,filename); /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open ftps:// type file with READWRITE access"); ffpmsg(" Specify an outfile for r/w access (ftps_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (ftps_open)"); snprintf(errStr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errStr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(net_timeout); if (ftps_open_network(localFilename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read ftps file into memory (ftps_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); if (strcmp(localFilename, filename)) { /* ftps_open_network has already checked that this is safe to copy into string of size FLEN_FILENAME */ strcpy(filename, localFilename); } /* We now have the file transfered from the ftps server into the inmem.memory buffer. Now transfer that into a FITS memory file. */ if ((status = mem_create(filename, handle))) { ffpmsg("Unable to create memory file (ftps_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } if (inmem.size > 1) { firstByte = (unsigned char)inmem.memory[0]; secondByte = (unsigned char)inmem.memory[1]; } if (firstByte == 0x1f && secondByte == 0x8b || strstr(localFilename,".Z")) { #ifdef HAVE_FMEMOPEN compressedFile = fmemopen(inmem.memory, inmem.size, "r"); #endif if (!compressedFile) { ffpmsg("Error creating file in memory (ftps_open)"); free(inmem.memory); return(FILE_NOT_OPENED); } if(mem_uncompress2mem(localFilename,compressedFile,*handle)) { ffpmsg("Error writing compressed memory file (ftps_open)"); ffpmsg(filename); fclose(compressedFile); free(inmem.memory); return(FILE_NOT_OPENED); } fclose(compressedFile); } else { if (inmem.size % 2880) { snprintf(errStr,MAXLEN,"Content-Length not a multiple of 2880 (ftps_open) %zu", inmem.size); ffpmsg(errStr); } status = mem_write(*handle, inmem.memory, inmem.size); if (status) { ffpmsg("Error copying https file into memory (ftps_open)"); ffpmsg(filename); free(inmem.memory); mem_close_free(*handle); return (FILE_NOT_OPENED); } } free(inmem.memory); return mem_seek(*handle, 0); } /*--------------------------------------------------------------------------*/ int ftps_file_open(char *filename, int rwmode, int *handle) { int ii, flen, status=0; char errStr[MAXLEN]; char localFilename[MAXLEN]; /* may have .gz or .Z appended */ unsigned char firstByte=0,secondByte=0; curlmembuf inmem; FILE *compressedInFile=0; strcpy(localFilename, filename); /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( ftps_open(filename, READONLY, handle) ); } flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, we need to know where to write the file */ ffpmsg("Output file not set, shouldn't have happened (ftps_file_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (ftps_file_open)"); snprintf(errStr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errStr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(net_timeout); if (ftps_open_network(localFilename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read ftps file into memory (ftps_file_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); if (strstr(localFilename, ".Z")) { ffpmsg(".Z decompression not supported for file output (ftps_file_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } if (strcmp(localFilename, filename)) { /* ftps_open_network has already checked that this is safe to copy into string of size FLEN_FILENAME */ strcpy(filename, localFilename); } if (*netoutfile == '!') { /* user wants to clobber disk file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ file_remove(netoutfile); } /* Create the output file */ if (file_create(netoutfile,handle)) { ffpmsg("Unable to create output file (ftps_file_open)"); ffpmsg(netoutfile); free(inmem.memory); return (FILE_NOT_OPENED); } if (inmem.size > 1) { firstByte = (unsigned char)inmem.memory[0]; secondByte = (unsigned char)inmem.memory[1]; } if (firstByte == 0x1f && secondByte == 0x8b) { /* Doing a file create/close/reopen to mimic the procedure in ftp_file_open. The earlier call to file_create ensures that checking is performed for the Hera case. */ file_close(*handle); /* Reopen with direct call to fopen to set the outfile pointer */ outfile = fopen(netoutfile,"w"); if (!outfile) { ffpmsg("Unable to reopen the output file (ftps_file_open)"); ffpmsg(netoutfile); free(inmem.memory); return(FILE_NOT_OPENED); } #ifdef HAVE_FMEMOPEN compressedInFile = fmemopen(inmem.memory, inmem.size, "r"); #endif if (!compressedInFile) { ffpmsg("Error creating compressed file in memory (ftps_file_open)"); free(inmem.memory); fclose(outfile); return(FILE_NOT_OPENED); } if (uncompress2file(filename, compressedInFile, outfile, &status)) { ffpmsg("Unable to uncompress the output file (ftps_file_open)"); ffpmsg(filename); ffpmsg(netoutfile); fclose(outfile); fclose(compressedInFile); free(inmem.memory); return(FILE_NOT_OPENED); } fclose(outfile); fclose(compressedInFile); } else { if (inmem.size % 2880) { snprintf(errStr, MAXLEN, "Content-Length not a multiple of 2880 (ftps_file_open) %zu", inmem.size); ffpmsg(errStr); } if (file_write(*handle, inmem.memory, inmem.size)) { ffpmsg("Error copying ftps file to disk file (ftps_file_open)"); ffpmsg(filename); ffpmsg(netoutfile); free(inmem.memory); file_close(*handle); return (FILE_NOT_OPENED); } file_close(*handle); } free(inmem.memory); return file_open(netoutfile, rwmode, handle); } /*--------------------------------------------------------------------------*/ int ftps_compress_open(char *filename, int rwmode, int *handle) { int ii, flen, status=0; char errStr[MAXLEN]; char localFilename[MAXLEN]; /* may have .gz or .Z appended */ unsigned char firstByte=0,secondByte=0; curlmembuf inmem; FILE *compressedInFile=0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Compressed files must be r/o"); return (FILE_NOT_OPENED); } strcpy(localFilename, filename); flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, we need to know where to write the file */ ffpmsg("Output file not set, shouldn't have happened (ftps_compress_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (ftps_compress_open)"); snprintf(errStr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errStr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(net_timeout); if (ftps_open_network(localFilename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read ftps file into memory (ftps_compress_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); if (strcmp(localFilename, filename)) { /* ftps_open_network has already checked that this is safe to copy into string of size FLEN_FILENAME */ strcpy(filename, localFilename); } if (inmem.size > 1) { firstByte = (unsigned char)inmem.memory[0]; secondByte = (unsigned char)inmem.memory[1]; } if ((firstByte == 0x1f && secondByte == 0x8b) || strstr(localFilename,".gz") || strstr(localFilename,".Z")) { if (*netoutfile == '!') { /* user wants to clobber disk file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ file_remove(netoutfile); } /* Create the output file */ if (file_create(netoutfile,handle)) { ffpmsg("Unable to create output file (ftps_compress_open)"); ffpmsg(netoutfile); free(inmem.memory); return (FILE_NOT_OPENED); } if (file_write(*handle, inmem.memory, inmem.size)) { ffpmsg("Error copying ftps file to disk file (ftps_file_open)"); ffpmsg(filename); ffpmsg(netoutfile); free(inmem.memory); file_close(*handle); return (FILE_NOT_OPENED); } file_close(*handle); /* File is on disk, let's uncompress it into memory */ if (NULL == (diskfile = fopen(netoutfile,"r"))) { ffpmsg("Unable to reopen disk file (ftps_compress_open)"); ffpmsg(netoutfile); free(inmem.memory); return (FILE_NOT_OPENED); } if ((status = mem_create(localFilename,handle))) { ffpmsg("Unable to create memory file (ftps_compress_open)"); ffpmsg(localFilename); free(inmem.memory); fclose(diskfile); diskfile=0; return (FILE_NOT_OPENED); } status = mem_uncompress2mem(localFilename,diskfile,*handle); fclose(diskfile); diskfile=0; if (status) { ffpmsg("Error writing compressed memory file (ftps_compress_open)"); free(inmem.memory); mem_close_free(*handle); return (FILE_NOT_OPENED); } } else { ffpmsg("Cannot write uncompressed infile to compressed outfile (ftps_compress_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } free(inmem.memory); return mem_seek(*handle,0); } /*--------------------------------------------------------------------------*/ int ftps_open_network(char *filename, curlmembuf* buffer) { char agentStr[SHORTLEN]; char url[MAXLEN]; char tmphost[SHORTLEN]; /* work array for separating user/pass/host names */ char *username=0; char *password=0; char *hostname=0; char *dirpath=0; char *strptr=0; float version=0.0; int iDirpath=0, len=0, origLen=0; int status=0; strcpy(url,"ftp://"); /* The filename may already contain a username and password, as indicated by a '@' within the host part of the name (which we'll define as the substring before the first '/'). If not, we'll set a default username:password */ len = strlen(filename); for (iDirpath=0; iDirpath SHORTLEN-1) { ffpmsg("Host name is too long in URL (ftps_open_network)"); return (FILE_NOT_OPENED); } strncpy(tmphost, filename, iDirpath); dirpath = &filename[iDirpath]; tmphost[iDirpath]='\0'; /* There could be more than one '@' since they can also exist in the username or password. Find the right-most '@' and assume that it delimits the host name. */ hostname = strrchr(tmphost, '@'); if (hostname) { *hostname = '\0'; ++hostname; /* Assume first occurrence of ':' is indicative of password delimiter. */ password = strchr(tmphost, ':'); if (password) { *password = '\0'; ++password; } username = tmphost; } else hostname = tmphost; if (!username || strlen(username)==0) username = "anonymous"; if (!password || strlen(password)==0) { snprintf(agentStr,SHORTLEN,"User-Agent: FITSIO/HEASARC/%-8.4f",ffvers(&version)); password = agentStr; } /* url may eventually have .gz or .Z appended to it */ if (strlen(url) + strlen(hostname) + strlen(dirpath) > MAXLEN-4) { ffpmsg("Full URL name is too long (ftps_open_network)"); return (FILE_NOT_OPENED); } strcat(url, hostname); strcat(url, dirpath); /* printf("url = %s\n",url); printf("username = %s\n",username); printf("password = %s\n",password); printf("hostname = %s\n",hostname); */ origLen = strlen(url); status = ssl_get_with_curl(url, buffer, username, password); /* If original url has .gz or .Z appended, do the same to the original filename. Note that url also differs from original filename at this point, since filename may have included username@password (which url would not). */ len = strlen(url); if ((len-origLen) == 2 || (len-origLen) == 3) { if (strlen(filename) > FLEN_FILENAME - 4) { ffpmsg("Filename is too long to append compression ext (ftps_open_network)"); /* buffer memory must be freed by calling routine */ return (FILE_NOT_OPENED); } strptr = url + origLen; strcat(filename, strptr); } return status; } /*--------------------------------------------------------------------------*/ /* Function to perform common curl interfacing for https or ftps transfers */ int ssl_get_with_curl(char *url, curlmembuf* buffer, char* username, char* password) { /* These settings will force libcurl to perform host and peer authentication. If it fails, this routine will try again without authentication (unless user forbids this via CFITSIO_VERIFY_HTTPS environment variable). */ long verifyPeer = 1; long verifyHost = 2; char errStr[MAXLEN]; char agentStr[MAXLEN]; float version=0.0; char *tmpUrl=0; char *verify=0; int isFtp = (strstr(url,"ftp://") != NULL); int experimentWithCompression = (!strstr(url,".gz") && !strstr(url,".Z") && !strstr(url,"?")); int notFound=1; #ifdef CFITSIO_HAVE_CURL CURL *curl=0; CURLcode res; char curlErrBuf[CURL_ERROR_SIZE]; if (strstr(url,".Z") && !isFtp) { ffpmsg("x-compress .Z format not currently supported with curl https transfers"); return(FILE_NOT_OPENED); } /* Will ASSUME curl_global_init has been called by this point. It is not thread-safe to call it here. */ curl = curl_easy_init(); res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verifyPeer); if (res != CURLE_OK) { ffpmsg("ERROR: CFITSIO was built with a libcurl library that "); ffpmsg("does not have SSL support, and therefore can't perform https or ftps transfers."); return (FILE_NOT_OPENED); } curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verifyHost); curl_easy_setopt(curl, CURLOPT_VERBOSE, (long)curl_verbose); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlToMemCallback); snprintf(agentStr,MAXLEN,"FITSIO/HEASARC/%-8.4f",ffvers(&version)); curl_easy_setopt(curl, CURLOPT_USERAGENT,agentStr); buffer->memory = 0; /* malloc/realloc will grow this in the callback function */ buffer->size = 0; curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)buffer); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlErrBuf); curlErrBuf[0]=0; /* This is needed for easy_perform to return an error whenever http server returns an error >= 400, ie. if it can't find the requested file. */ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); /* This turns on automatic decompression for all recognized types. */ curl_easy_setopt(curl, CURLOPT_ENCODING, ""); /* tmpUrl should be large enough to accomodate original url + ".gz" */ tmpUrl = (char *)malloc(strlen(url)+4); strcpy(tmpUrl, url); if (show_fits_download_progress) { curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curlProgressCallback); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, tmpUrl); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); } else curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); /* USESSL only necessary for ftps, though it may not hurt anything if it were also set for https. */ if (isFtp) { curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); if (username) curl_easy_setopt(curl, CURLOPT_USERNAME, username); if (password) curl_easy_setopt(curl, CURLOPT_PASSWORD, password); } /* Unless url already contains a .gz, .Z or '?' (probably from a cgi script), first try with .gz appended. */ if (experimentWithCompression) strcat(tmpUrl, ".gz"); /* First attempt: verification on */ curl_easy_setopt(curl, CURLOPT_URL, tmpUrl); res = curl_easy_perform(curl); if (res != CURLE_OK && res != CURLE_HTTP_RETURNED_ERROR && res != CURLE_REMOTE_FILE_NOT_FOUND) { /* CURLE_HTTP_RETURNED_ERROR is what gets returned if HTTP server returns an error code >= 400. CURLE_REMOTE_FILE_NOT_FOUND may be returned by an ftp server. If these are not causing this error, assume it is a verification issue. Try again with verification removed, unless user disallowed it via environment variable. */ verify = getenv("CFITSIO_VERIFY_HTTPS"); if (verify) { if (verify[0] == 'T' || verify[0] == 't') { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(tmpUrl); return (FILE_NOT_OPENED); } } verifyPeer = 0; verifyHost = 0; curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verifyPeer); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verifyHost); /* Second attempt: no verification, .gz appended */ res = curl_easy_perform(curl); if (res != CURLE_OK) { if (isFtp && experimentWithCompression) { strcpy(tmpUrl, url); strcat(tmpUrl, ".Z"); curl_easy_setopt(curl, CURLOPT_URL, tmpUrl); /* For ftps, make another attempt with .Z */ res = curl_easy_perform(curl); if (res == CURLE_OK) { /* Success, but should still warn */ fprintf(stderr, "Warning: Unable to perform SSL verification on https transfer from: %s\n", tmpUrl); notFound=0; } } /* If we've been appending .gz or .Z, try a final time without. */ if (experimentWithCompression && notFound) { strcpy(tmpUrl, url); curl_easy_setopt(curl, CURLOPT_URL, tmpUrl); /* attempt with no verification, no .gz or .Z appended */ res = curl_easy_perform(curl); if (res != CURLE_OK) { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(tmpUrl); return (FILE_NOT_OPENED); } else /* Success, but should still warn */ fprintf(stderr, "Warning: Unable to perform SSL verification on https transfer from: %s\n", tmpUrl); } else if (notFound) { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(tmpUrl); return (FILE_NOT_OPENED); } } else /* Success, but still issue warning */ fprintf(stderr, "Warning: Unable to perform SSL verification on https transfer from: %s\n", tmpUrl); } else if (res == CURLE_HTTP_RETURNED_ERROR || res == CURLE_REMOTE_FILE_NOT_FOUND) { /* .gz extension failed and verification isn't the problem. No need to relax peer/host checking */ /* Unless url already contained a .gz, .Z or '?' (probably from a cgi script), try again with original url unappended (but first try .Z if this is ftps). */ if (experimentWithCompression) { if (isFtp) { strcpy(tmpUrl, url); strcat(tmpUrl, ".Z"); curl_easy_setopt(curl, CURLOPT_URL, tmpUrl); res = curl_easy_perform(curl); if (res == CURLE_OK) notFound = 0; } if (notFound) { strcpy(tmpUrl, url); curl_easy_setopt(curl, CURLOPT_URL, tmpUrl); res = curl_easy_perform(curl); if (res != CURLE_OK) { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(tmpUrl); return (FILE_NOT_OPENED); } } } else { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(tmpUrl); return (FILE_NOT_OPENED); } } /* If we made it here, assume tmpUrl was successful. Calling routines must make sure url can hold up to 3 extra chars */ strcpy(url, tmpUrl); free(tmpUrl); curl_easy_cleanup(curl); #else ffpmsg("ERROR: This CFITSIO build was not compiled with the libcurl library package "); ffpmsg("and therefore it cannot perform HTTPS or FTPS connections."); return (FILE_NOT_OPENED); #endif return 0; } /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The file is uncompressed if necessary */ int ftp_open(char *filename, int rwmode, int *handle) { FILE *ftpfile; FILE *command; int sock; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int status; char firstchar; closememfile = 0; closecommandfile = 0; closeftpfile = 0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open ftp:// type file with READWRITE access"); ffpmsg("Specify an outfile for r/w access (ftp_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (ftp_open)"); snprintf(errorstr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errorstr); ffpmsg(" (multiplied x10 for files requiring uncompression)"); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); goto error; } signal(SIGALRM, signal_handler); /* Open the ftp connetion. ftpfile is connected to the file port, command is connected to port 21. sock is the socket on port 21 */ if (strlen(filename) > MAXLEN - 4) { ffpmsg("filename too long (ftp_open)"); ffpmsg(filename); goto error; } alarm(net_timeout); if (ftp_open_network(filename,&ftpfile,&command,&sock)) { alarm(0); ffpmsg("Unable to open following ftp file (ftp_open):"); ffpmsg(filename); goto error; } closeftpfile++; closecommandfile++; /* create the memory file */ if ((status = mem_create(filename,handle))) { ffpmsg ("Could not create memory file to passive port (ftp_open)"); ffpmsg(filename); goto error; } closememfile++; /* This isn't quite right, it'll fail if the file has .gzabc at the end for instance */ /* Decide if the file is compressed */ firstchar = fgetc(ftpfile); ungetc(firstchar,ftpfile); if (strstr(filename,".gz") || strstr(filename,".Z") || ('\037' == firstchar)) { status = 0; /* A bit arbritary really, the user will probably hit ^C */ alarm(net_timeout*10); status = mem_uncompress2mem(filename, ftpfile, *handle); alarm(0); if (status) { ffpmsg("Error writing compressed memory file (ftp_open)"); ffpmsg(filename); goto error; } } else { /* write a memory file */ alarm(net_timeout); while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { alarm(0); status = mem_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing memory file (http_open)"); ffpmsg(filename); goto error; } alarm(net_timeout); } } /* close and clean up */ fclose(ftpfile); closeftpfile--; fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); closecommandfile--; signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closecommandfile) { fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); } if (closeftpfile) { fclose(ftpfile); } if (closememfile) { mem_close_free(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a file handle with a copy of the URL in filename. The file must be uncompressed and is copied to disk first */ int ftp_file_open(char *url, int rwmode, int *handle) { FILE *ftpfile; FILE *command; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int sock; int ii, flen, status; char firstchar; /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( ftp_open(url, READONLY, handle) ); } closeftpfile = 0; closecommandfile = 0; closefile = 0; closeoutfile = 0; /* cfileio made a mistake, need to know where to write the output file */ flen = strlen(netoutfile); if (!flen) { ffpmsg("Output file not set, shouldn't have happened (ftp_file_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (ftp_file_open)"); snprintf(errorstr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errorstr); ffpmsg(" (multiplied x10 for files requiring uncompression)"); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); goto error; } signal(SIGALRM, signal_handler); /* open the network connection to url. ftpfile holds the connection to the input file, command holds the connection to port 21, and sock is the socket connected to port 21 */ alarm(net_timeout); if ((status = ftp_open_network(url,&ftpfile,&command,&sock))) { alarm(0); ffpmsg("Unable to open http file (ftp_file_open)"); ffpmsg(url); goto error; } closeftpfile++; closecommandfile++; if (*netoutfile == '!') { /* user wants to clobber file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } /* Now, what do we do with the file */ firstchar = fgetc(ftpfile); ungetc(firstchar,ftpfile); if (strstr(url,".gz") || strstr(url,".Z") || ('\037' == firstchar)) { /* to make this more cfitsioish we use the file driver calls to create the file */ /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (ftp_file_open)"); ffpmsg(netoutfile); goto error; } file_close(*handle); if (NULL == (outfile = fopen(netoutfile,"w"))) { ffpmsg("Unable to reopen the output file (ftp_file_open)"); ffpmsg(netoutfile); goto error; } closeoutfile++; status = 0; /* Ok, this is a tough case, let's be arbritary and say 10*net_timeout, Given the choices for nettimeout above they'll probaby ^C before, but it's always worth a shot*/ alarm(net_timeout*10); status = uncompress2file(url,ftpfile,outfile,&status); alarm(0); if (status) { ffpmsg("Unable to uncompress the output file (ftp_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } fclose(outfile); closeoutfile--; } else { /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (ftp_file_open)"); ffpmsg(netoutfile); goto error; } closefile++; /* write a file */ alarm(net_timeout); while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing file (ftp_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } alarm(net_timeout); } file_close(*handle); } fclose(ftpfile); closeftpfile--; fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); closecommandfile--; signal(SIGALRM, SIG_DFL); alarm(0); return file_open(netoutfile,rwmode,handle); error: alarm(0); /* clear it */ if (closeftpfile) { fclose(ftpfile); } if (closecommandfile) { fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); } if (closeoutfile) { fclose(outfile); } if (closefile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a memory handle with a copy of the URL in filename. The file must be compressed and is copied to disk first */ int ftp_compress_open(char *url, int rwmode, int *handle) { FILE *ftpfile; FILE *command; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int ii, flen, status; int sock; char firstchar; closeftpfile = 0; closecommandfile = 0; closememfile = 0; closefdiskfile = 0; closediskfile = 0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Compressed files must be r/o"); return (FILE_NOT_OPENED); } /* Need to know where to write the output file */ flen = strlen(netoutfile); if (!flen) { ffpmsg( "Output file not set, shouldn't have happened (ftp_compress_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (ftp_compress_open)"); snprintf(errorstr, MAXLEN, "Download timeout exceeded: %d seconds",net_timeout); ffpmsg(errorstr); ffpmsg(" Timeout may be adjusted with fits_set_timeout"); goto error; } signal(SIGALRM, signal_handler); /* Open the network connection to url, ftpfile is connected to the file port, command is connected to port 21. sock is for writing to port 21 */ alarm(net_timeout); if ((status = ftp_open_network(url,&ftpfile,&command,&sock))) { alarm(0); ffpmsg("Unable to open ftp file (ftp_compress_open)"); ffpmsg(url); goto error; } closeftpfile++; closecommandfile++; /* Now, what do we do with the file */ firstchar = fgetc(ftpfile); ungetc(firstchar,ftpfile); if (strstr(url,".gz") || strstr(url,".Z") || ('\037' == firstchar)) { if (*netoutfile == '!') { /* user wants to clobber file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (ftp_compress_open)"); ffpmsg(netoutfile); goto error; } closediskfile++; /* write a file */ alarm(net_timeout); while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing file (ftp_compres_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } alarm(net_timeout); } file_close(*handle); closediskfile--; fclose(ftpfile); closeftpfile--; /* Close down the ftp connection */ fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); closecommandfile--; /* File is on disk, let's uncompress it into memory */ if (NULL == (diskfile = fopen(netoutfile,"r"))) { ffpmsg("Unable to reopen disk file (ftp_compress_open)"); ffpmsg(netoutfile); return (FILE_NOT_OPENED); } closefdiskfile++; if ((status = mem_create(url,handle))) { ffpmsg("Unable to create memory file (ftp_compress_open)"); ffpmsg(url); goto error; } closememfile++; status = 0; status = mem_uncompress2mem(url,diskfile,*handle); fclose(diskfile); closefdiskfile--; if (status) { ffpmsg("Error writing compressed memory file (ftp_compress_open)"); goto error; } } else { /* Opps, this should not have happened */ ffpmsg("Can only compressed files here (ftp_compress_open)"); goto error; } signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closeftpfile) { fclose(ftpfile); } if (closecommandfile) { fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); } if (closefdiskfile) { fclose(diskfile); } if (closememfile) { mem_close_free(*handle); } if (closediskfile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* Open a ftp connection to filename (really a URL), return ftpfile set to the file connection, and command set to the control connection, with sock also set to the control connection */ static int ftp_open_network(char *filename, FILE **ftpfile, FILE **command, int *sock) { int status; int sock1; int tmpint; char recbuf[MAXLEN]; char errorstr[MAXLEN]; char tmpstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char agentStr[SHORTLEN]; char *newhost; char *username; char *password; char fn[MAXLEN]; char *newfn; char *passive; char *tstr; char *saveptr; char ip[SHORTLEN]; char turl[MAXLEN]; int port; int ii,tryingtologin = 1; float version=0.0; /* parse the URL */ if (strlen(filename) > MAXLEN - 7) { ffpmsg("ftp filename is too long (ftp_open_network)"); return (FILE_NOT_OPENED); } strcpy(turl,"ftp://"); strcat(turl,filename); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (ftp_open) %s",filename); ffpmsg(errorstr); return (FILE_NOT_OPENED); } port = 21; /* We might have a user name. If not, set defaults for username and password */ username = "anonymous"; snprintf(agentStr,SHORTLEN,"User-Agent: FITSIO/HEASARC/%-8.4f",ffvers(&version)); password = agentStr; /* is there an @ sign */ if (NULL != (newhost = strrchr(host,'@'))) { *newhost = '\0'; /* make it a null, */ newhost++; /* Now newhost points to the host name and host points to the user name, password combo */ username = host; /* is there a : for a password */ if (NULL != strchr(username,':')) { password = strchr(username,':'); *password = '\0'; password++; } } else { newhost = host; } for (ii = 0; ii < 10; ii++) { /* make up to 10 attempts to log in */ /* Connect to the host on the required port */ *sock = NET_TcpConnect(newhost,port); /* convert it to a stdio file */ if (NULL == (*command = fdopen(*sock,"r"))) { ffpmsg ("fdopen failed to convert socket to stdio file (ftp_open_netowrk)"); return (FILE_NOT_OPENED); } /* Wait for the 220 response */ if (ftp_status(*command,"220 ")) { fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); /* ffpmsg("sleeping for 5 in ftp_open_network, then try again"); */ sleep (5); /* take a nap and hope ftp server sorts itself out in the meantime */ } else { tryingtologin = 0; break; } } if (tryingtologin) { /* the 10 attempts were not successful */ ffpmsg ("error connecting to remote server, no 220 seen (ftp_open_network)"); return (FILE_NOT_OPENED); } /* Send the user name and wait for the right response */ snprintf(tmpstr,MAXLEN,"USER %s\r\n",username); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"331 ")) { ffpmsg ("USER error no 331 seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Send the password and wait for the right response */ snprintf(tmpstr,MAXLEN,"PASS %s\r\n",password); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"230 ")) { ffpmsg ("PASS error, no 230 seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* now do the cwd command */ newfn = strrchr(fn,'/'); if (newfn == NULL) { strcpy(tmpstr,"CWD /\r\n"); newfn = fn; } else { *newfn = '\0'; newfn++; if (strlen(fn) == 0) { strcpy(tmpstr,"CWD /\r\n"); } else { /* remove the leading slash */ if (fn[0] == '/') { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",&fn[1]); } else { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",fn); } } } status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"250 ")) { ffpmsg ("CWD error, no 250 seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } if (!strlen(newfn)) { ffpmsg("Null file name (ftp_open)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Always use binary mode */ snprintf(tmpstr,MAXLEN,"TYPE I\r\n"); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"200 ")) { ffpmsg ("TYPE I error, 200 not seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } status = NET_SendRaw(*sock,"PASV\r\n",6,NET_DEFAULT); if (!(fgets(recbuf,MAXLEN,*command))) { ffpmsg ("PASV error (ftp_open)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Passive mode response looks like 227 Entering Passive Mode (129,194,67,8,210,80) */ if (recbuf[0] == '2' && recbuf[1] == '2' && recbuf[2] == '7') { /* got a good passive mode response, find the opening ( */ if (!(passive = strchr(recbuf,'('))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } *passive = '\0'; passive++; ip[0] = '\0'; /* Messy parsing of response from PASV *command */ if (!(tstr = ffstrtok(passive,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcpy(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcat(ip,tstr); /* Done the ip number, now do the port # */ if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } sscanf(tstr,"%d",&port); port *= 256; if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } sscanf(tstr,"%d",&tmpint); port += tmpint; if (!strlen(newfn)) { ffpmsg("Null file name (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Connect to the data port */ sock1 = NET_TcpConnect(ip,port); if (NULL == (*ftpfile = fdopen(sock1,"r"))) { ffpmsg ("Could not connect to passive port (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Send the retrieve command */ snprintf(tmpstr,MAXLEN,"RETR %s\r\n",newfn); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"150 ")) { fclose(*ftpfile); NET_SendRaw(sock1,"QUIT\r\n",6,NET_DEFAULT); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } return 0; /* successfully opened the ftp file */ } /* no passive mode */ fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* Open a ftp connection to see if the file exists (return 1) or not (return 0) */ int ftp_file_exist(char *filename) { FILE *ftpfile; FILE *command; int sock; int status; int sock1; int tmpint; char recbuf[MAXLEN]; char errorstr[MAXLEN]; char tmpstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char *newhost; char *username; char *password; char fn[MAXLEN]; char *newfn; char *passive; char *tstr; char *saveptr; char ip[SHORTLEN]; char turl[MAXLEN]; int port; int ii, tryingtologin = 1; /* parse the URL */ if (strlen(filename) > MAXLEN - 7) { ffpmsg("ftp filename is too long (ftp_file_exist)"); return 0; } strcpy(turl,"ftp://"); strcat(turl,filename); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (ftp_file_exist) %s",filename); ffpmsg(errorstr); return 0; } port = 21; /* we might have a user name */ username = "anonymous"; password = "user@host.com"; /* is there an @ sign */ if (NULL != (newhost = strrchr(host,'@'))) { *newhost = '\0'; /* make it a null, */ newhost++; /* Now newhost points to the host name and host points to the user name, password combo */ username = host; /* is there a : for a password */ if (NULL != strchr(username,':')) { password = strchr(username,':'); *password = '\0'; password++; } } else { newhost = host; } for (ii = 0; ii < 10; ii++) { /* make up to 10 attempts to log in */ /* Connect to the host on the required port */ sock = NET_TcpConnect(newhost,port); /* convert it to a stdio file */ if (NULL == (command = fdopen(sock,"r"))) { ffpmsg ("Failed to convert socket to stdio file (ftp_file_exist)"); return 0; } /* Wait for the 220 response */ if (ftp_status(command,"220")) { ffpmsg ("error connecting to remote server, no 220 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); /* ffpmsg("sleeping for 5 in ftp_file_exist, then try again"); */ sleep (5); /* take a nap and hope ftp server sorts itself out in the meantime */ } else { tryingtologin = 0; break; } } if (tryingtologin) { /* the 10 attempts were not successful */ ffpmsg ("error connecting to remote server, no 220 seen (ftp_open_network)"); return (0); } /* Send the user name and wait for the right response */ snprintf(tmpstr,MAXLEN,"USER %s\r\n",username); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); /* If command is refused due to the connection requiring SSL (ie. an fpts connection), this is where it will first be detected by way of a 550 error code. */ status = ftp_status(command,"331 "); if (status == 550) { ffpmsg ("Server is requesting SSL, will switch to ftps (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return -1; } else if (status) { ffpmsg ("USER error no 331 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Send the password and wait for the right response */ snprintf(tmpstr,MAXLEN,"PASS %s\r\n",password); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"230 ")) { ffpmsg ("PASS error, no 230 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* now do the cwd command */ newfn = strrchr(fn,'/'); if (newfn == NULL) { strcpy(tmpstr,"CWD /\r\n"); newfn = fn; } else { *newfn = '\0'; newfn++; if (strlen(fn) == 0) { strcpy(tmpstr,"CWD /\r\n"); } else { /* remove the leading slash */ if (fn[0] == '/') { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",&fn[1]); } else { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",fn); } } } status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"250 ")) { ffpmsg ("CWD error, no 250 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } if (!strlen(newfn)) { ffpmsg("Null file name (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Always use binary mode */ snprintf(tmpstr,MAXLEN,"TYPE I\r\n"); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"200 ")) { ffpmsg ("TYPE I error, 200 not seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } status = NET_SendRaw(sock,"PASV\r\n",6,NET_DEFAULT); if (!(fgets(recbuf,MAXLEN,command))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Passive mode response looks like 227 Entering Passive Mode (129,194,67,8,210,80) */ if (recbuf[0] == '2' && recbuf[1] == '2' && recbuf[2] == '7') { /* got a good passive mode response, find the opening ( */ if (!(passive = strchr(recbuf,'('))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } *passive = '\0'; passive++; ip[0] = '\0'; /* Messy parsing of response from PASV command */ if (!(tstr = ffstrtok(passive,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcpy(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcat(ip,tstr); /* Done the ip number, now do the port # */ if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } sscanf(tstr,"%d",&port); port *= 256; if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } sscanf(tstr,"%d",&tmpint); port += tmpint; if (!strlen(newfn)) { ffpmsg("Null file name (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Connect to the data port */ sock1 = NET_TcpConnect(ip,port); if (NULL == (ftpfile = fdopen(sock1,"r"))) { ffpmsg ("Could not connect to passive port (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Send the retrieve command */ snprintf(tmpstr,MAXLEN,"RETR %s\r\n",newfn); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"150 ")) { fclose(ftpfile); NET_SendRaw(sock1,"QUIT\r\n",6,NET_DEFAULT); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* if we got here then the file probably exists */ fclose(ftpfile); NET_SendRaw(sock1,"QUIT\r\n",6,NET_DEFAULT); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 1; } /* no passive mode */ fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /*--------------------------------------------------------------------------*/ /* return a socket which results from connection to hostname on port port */ int NET_TcpConnect(char *hostname, int port) { /* Connect to hostname on port */ struct sockaddr_in sockaddr; int sock; int stat; int val = 1; CreateSocketAddress(&sockaddr,hostname,port); /* Create socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ffpmsg("ERROR: NET_TcpConnect can't create socket"); return CONNECTION_ERROR; } if ((stat = connect(sock, (struct sockaddr*) &sockaddr, sizeof(sockaddr))) < 0) { close(sock); /* perror("NET_Tcpconnect - Connection error"); ffpmsg("Can't connect to host, connection error"); */ return CONNECTION_ERROR; } setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(val)); val = 65536; setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, sizeof(val)); setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, sizeof(val)); return sock; } /*--------------------------------------------------------------------------*/ /* Write len bytes from buffer to socket sock */ static int NET_SendRaw(int sock, const void *buffer, int length, int opt) { char * buf = (char *) buffer; int flag; int n, nsent = 0; switch (opt) { case NET_DEFAULT: flag = 0; break; case NET_OOB: flag = MSG_OOB; break; case NET_PEEK: default: flag = 0; break; } if (sock < 0) return -1; for (n = 0; n < length; n += nsent) { if ((nsent = send(sock, buf+n, length-n, flag)) <= 0) { return nsent; } } return n; } /*--------------------------------------------------------------------------*/ static int NET_RecvRaw(int sock, void *buffer, int length) { /* Receive exactly length bytes into buffer. Returns number of bytes */ /* received. Returns -1 in case of error. */ int nrecv, n; char *buf = (char *)buffer; if (sock < 0) return -1; for (n = 0; n < length; n += nrecv) { while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 && errno == EINTR) errno = 0; /* probably a SIGCLD that was caught */ if (nrecv < 0) return nrecv; else if (nrecv == 0) break; /*/ EOF */ } return n; } /*--------------------------------------------------------------------------*/ /* Yet Another URL Parser url - input url proto - input protocol host - output host port - output port fn - output filename */ static int NET_ParseUrl(const char *url, char *proto, char *host, int *port, char *fn) { /* parses urls into their bits */ /* returns 1 if error, else 0 */ char *urlcopy, *urlcopyorig; char *ptrstr; char *thost; int isftp = 0; /* figure out if there is a http: or ftp: */ urlcopyorig = urlcopy = (char *) malloc(strlen(url)+1); strcpy(urlcopy,url); /* set some defaults */ *port = 80; strcpy(proto,"http:"); strcpy(host,"localhost"); strcpy(fn,"/"); ptrstr = strstr(urlcopy,"http:"); if (ptrstr == NULL) { /* Nope, not http: */ ptrstr = strstr(urlcopy,"root:"); if (ptrstr == NULL) { /* Nope, not root either */ ptrstr = strstr(urlcopy,"ftp:"); if (ptrstr != NULL) { if (ptrstr == urlcopy) { strcpy(proto,"ftp:"); *port = 21; isftp++; urlcopy += 4; /* move past ftp: */ } else { /* not at the beginning, bad url */ free(urlcopyorig); return 1; } } } else { if (ptrstr == urlcopy) { urlcopy += 5; /* move past root: */ } else { /* not at the beginning, bad url */ free(urlcopyorig); return 1; } } } else { if (ptrstr == urlcopy) { urlcopy += 5; /* move past http: */ } else { free(urlcopyorig); return 1; } } /* got the protocol */ /* get the hostname */ if (urlcopy[0] == '/' && urlcopy[1] == '/') { /* we have a hostname */ urlcopy += 2; /* move past the // */ } /* do this only if http */ if (!strcmp(proto,"http:")) { /* Move past any user:password */ if ((thost = strchr(urlcopy, '@')) != NULL) urlcopy = thost+1; if (strlen(urlcopy) > SHORTLEN-1) { free(urlcopyorig); return 1; } strcpy(host,urlcopy); thost = host; while (*urlcopy != '/' && *urlcopy != ':' && *urlcopy) { thost++; urlcopy++; } /* we should either be at the end of the string, have a /, or have a : */ *thost = '\0'; if (*urlcopy == ':') { /* follows a port number */ urlcopy++; sscanf(urlcopy,"%d",port); while (*urlcopy != '/' && *urlcopy) urlcopy++; /* step to the */ } } else { /* do this for ftp */ if (strlen(urlcopy) > SHORTLEN-1) { free(urlcopyorig); return 1; } strcpy(host,urlcopy); thost = host; while (*urlcopy != '/' && *urlcopy) { thost++; urlcopy++; } *thost = '\0'; /* Now, we should either be at the end of the string, or have a / */ } /* Now the rest is a fn */ if (*urlcopy) { if (strlen(urlcopy) > MAXLEN-1) { free(urlcopyorig); return 1; } strcpy(fn,urlcopy); } free(urlcopyorig); return 0; } /*--------------------------------------------------------------------------*/ int http_checkfile (char *urltype, char *infile, char *outfile1) { /* Small helper functions to set the netoutfile static string */ /* Called by cfileio after parsing the output file off of the input file url */ char newinfile[MAXLEN]; FILE *httpfile=0; char contentencoding[MAXLEN], contenttype[MAXLEN]; int contentlength; int foundfile = 0; int status=0; /* set defaults */ strcpy(urltype,"http://"); if (strlen(outfile1)) { /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } } if (strstr(infile, "?")) { /* Special case where infile name contains a "?". */ /* This is probably a CGI string; no point in testing if it exists */ /* so just set urltype and netoutfile if necessary, then return */ if (strlen(outfile1)) { /* was an outfile specified? */ strcpy(urltype,"httpfile://"); /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } } return 0; /* case where infile name contains "?" */ } /* If the specified infile file name does not contain a .gz or .Z suffix, then first test if a .gz compressed version of the file exists, and if not then test if a .Z version of the file exists. (because it will be much faster to read the compressed file). If the compressed files do not exist, then finally just open the infile name exactly as specified. */ if (!strstr(infile,".gz") && (!strstr(infile,".Z"))) { /* The infile string does not contain the name of a compressed file. */ /* Fisrt, look for a .gz compressed version of the file. */ if (strlen(infile) + 3 > MAXLEN-1) { return URL_PARSE_ERROR; } strcpy(newinfile,infile); strcat(newinfile,".gz"); status = http_open_network(newinfile,&httpfile, contentencoding, contenttype, &contentlength); if (!status) { if (!strcmp(contentencoding, "ftp://")) { /* this is a signal from http_open_network that indicates that */ /* the http server returned a 301 or 302 redirect to a FTP URL. */ /* Check that the file exists, because redirect many not be reliable */ if (ftp_file_exist(newinfile)>0) { /* The ftp .gz compressed file is there, all is good! */ strcpy(urltype, "ftp://"); if (strlen(newinfile) > FLEN_FILENAME-1) { return URL_PARSE_ERROR; } strcpy(infile,newinfile); if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ } else { /* input file is compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"ftpcompress://"); } else { strcpy(urltype,"ftpfile://"); } } } return 0; /* found the .gz compressed ftp file */ } /* fall through to here if ftp redirect does not exist */ } else if (!strcmp(contentencoding, "https://")) { /* the http server returned a 301 or 302 redirect to an HTTPS URL. */ https_checkfile(urltype, infile, outfile1); /* For https we're not testing for compressed extensions at this stage. It will all be done in https_open_network. Therefore leave infile alone and do immediate return. */ return 0; } else { /* found the http .gz compressed file */ if (httpfile) fclose(httpfile); foundfile = 1; if (strlen(newinfile) > FLEN_FILENAME-1) { return URL_PARSE_ERROR; } strcpy(infile,newinfile); } } else if (status != FILE_NOT_OPENED) { /* Some other error occured aside from not finding file, such as a url parsing error. Don't continue trying with other extensions. */ return status; } if (!foundfile) { /* did not find .gz compressed version of the file, so look for .Z file. */ if (strlen(infile+2) > MAXLEN-1) { return URL_PARSE_ERROR; } strcpy(newinfile,infile); strcat(newinfile,".Z"); if (!http_open_network(newinfile,&httpfile, contentencoding, contenttype, &contentlength)) { if (!strcmp(contentencoding, "ftp://")) { /* this is a signal from http_open_network that indicates that */ /* the http server returned a 301 or 302 redirect to a FTP URL. */ /* Check that the file exists, because redirect many not be reliable */ if (ftp_file_exist(newinfile)>0) { /* The ftp .Z compressed file is there, all is good! */ strcpy(urltype, "ftp://"); if (strlen(newinfile) > FLEN_FILENAME-1) { return URL_PARSE_ERROR; } strcpy(infile,newinfile); if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ } else { /* input file is compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"ftpcompress://"); } else { strcpy(urltype,"ftpfile://"); } } } return 0; /* found the .Z compressed ftp file */ } /* fall through to here if ftp redirect does not exist */ } else { /* found the http .Z compressed file */ if (httpfile) fclose(httpfile); foundfile = 1; if (strlen(newinfile) > FLEN_FILENAME-1) { return URL_PARSE_ERROR; } strcpy(infile,newinfile); } } } } /* end of case where infile does not contain .gz or .Z */ if (!foundfile) { /* look for the base file.name */ strcpy(newinfile,infile); if (!http_open_network(newinfile,&httpfile, contentencoding, contenttype, &contentlength)) { if (!strcmp(contentencoding, "ftp://")) { /* this is a signal from http_open_network that indicates that */ /* the http server returned a 301 or 302 redirect to a FTP URL. */ /* Check that the file exists, because redirect many not be reliable */ if (ftp_file_exist(newinfile)>0) { /* The ftp file is there, all is good! */ strcpy(urltype, "ftp://"); if (strlen(newinfile) > FLEN_FILENAME-1) { return URL_PARSE_ERROR; } strcpy(infile,newinfile); if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ return 0; } else { /* input file is not compressed */ strcpy(urltype,"ftpfile://"); } } return 0; /* found the ftp file */ } /* fall through to here if ftp redirect does not exist */ } else if (!strcmp(contentencoding, "https://")) { /* the http server returned a 301 or 302 redirect to an HTTPS URL. */ https_checkfile(urltype, infile, outfile1); /* For https we're not testing for compressed extensions at this stage. It will all be done in https_open_network. Therefore leave infile alone and do immediate return. */ return 0; } else { /* found the base named file */ if (httpfile) fclose(httpfile); foundfile = 1; if (strlen(newinfile) > FLEN_FILENAME-1) { return URL_PARSE_ERROR; } strcpy(infile,newinfile); } } } if (!foundfile) { return (FILE_NOT_OPENED); } if (strlen(outfile1)) { /* there is an output file */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the http file and or the output file are compressed or not. */ strcpy(urltype, "httpmem://"); /* use special driver */ return 0; } if (strstr(infile, "?")) { /* file name contains a '?' so probably a cgi string; */ strcpy(urltype,"httpfile://"); return 0; } if (strstr(infile,".gz") || (strstr(infile,".Z"))) { /* It's compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"httpcompress://"); } else { strcpy(urltype,"httpfile://"); } } else { strcpy(urltype,"httpfile://"); } } return 0; } /*--------------------------------------------------------------------------*/ int https_checkfile (char *urltype, char *infile, char *outfile1) { /* set default */ strcpy(urltype,"https://"); if (strlen(outfile1)) { /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } if (!strncmp(outfile1, "mem:", 4)) strcpy(urltype,"httpsmem://"); else strcpy(urltype,"httpsfile://"); } return 0; } /*--------------------------------------------------------------------------*/ int ftps_checkfile (char *urltype, char *infile, char *outfile1) { strcpy(urltype,"ftps://"); if (strlen(outfile1)) { /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } if (!strncmp(outfile1, "mem:", 4)) strcpy(urltype,"ftpsmem://"); else { if (strstr(outfile1,".gz") || strstr(outfile1,".Z")) { /* Note that for Curl dependent handlers, we can't check at this point if infile will have a .gz or .Z appended. If it does not, the ftpscompress 'open' handler will fail.*/ strcpy(urltype,"ftpscompress://"); } else strcpy(urltype,"ftpsfile://"); } } return 0; } /*--------------------------------------------------------------------------*/ int ftp_checkfile (char *urltype, char *infile, char *outfile1) { char newinfile[MAXLEN]; FILE *ftpfile; FILE *command; int sock; int foundfile = 0; int status=0; /* Small helper functions to set the netoutfile static string */ /* default to ftp:// if no outfile specified */ strcpy(urltype,"ftp://"); if (!strstr(infile,".gz") && (!strstr(infile,".Z"))) { /* The infile string does not contain the name of a compressed file. */ /* Fisrt, look for a .gz compressed version of the file. */ if (strlen(infile)+3 > MAXLEN-1) { return URL_PARSE_ERROR; } strcpy(newinfile,infile); strcat(newinfile,".gz"); /* look for .gz version of the file */ status = ftp_file_exist(newinfile); if (status > 0) { foundfile = 1; if (strlen(newinfile) > FLEN_FILENAME-1) return URL_PARSE_ERROR; strcpy(infile,newinfile); } else if (status < 0) { /* Server is demanding an SSL connection. Change urltype and exit. */ ftps_checkfile(urltype, infile, outfile1); return 0; } if (!foundfile) { if (strlen(infile)+2 > MAXLEN-1) { return URL_PARSE_ERROR; } strcpy(newinfile,infile); strcat(newinfile,".Z"); /* look for .Z version of the file */ if (ftp_file_exist(newinfile)) { foundfile = 1; if (strlen(newinfile) > FLEN_FILENAME-1) return URL_PARSE_ERROR; strcpy(infile,newinfile); } } } if (!foundfile) { strcpy(newinfile,infile); /* look for the base file */ status = ftp_file_exist(newinfile); if (status > 0) { foundfile = 1; if (strlen(newinfile) > FLEN_FILENAME-1) return URL_PARSE_ERROR; strcpy(infile,newinfile); } else if (status < 0) { /* Server is demanding an SSL connection. Change urltype and exit. */ ftps_checkfile(urltype, infile, outfile1); return 0; } } if (!foundfile) { return (FILE_NOT_OPENED); } if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) strcpy(netoutfile,outfile1+7); else strcpy(netoutfile,outfile1); if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ return 0; } if (strstr(infile,".gz") || (strstr(infile,".Z"))) { /* input file is compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"ftpcompress://"); } else { strcpy(urltype,"ftpfile://"); } } else { strcpy(urltype,"ftpfile://"); } } return 0; } /*--------------------------------------------------------------------------*/ /* A small helper function to wait for a particular status on the ftp connectino */ static int ftp_status(FILE *ftp, char *statusstr) { /* read through until we find a string beginning with statusstr */ /* This needs a timeout */ /* Modified 2/19 to return the numerical value of the returned status when it differs from the requested status. */ char recbuf[MAXLEN], errorstr[SHORTLEN]; int len, ftpcode=0; len = strlen(statusstr); while (1) { if (!(fgets(recbuf,MAXLEN,ftp))) { snprintf(errorstr,SHORTLEN,"ERROR: ftp_status wants %s but fgets returned 0",statusstr); ffpmsg(errorstr); return 1; /* error reading */ } recbuf[len] = '\0'; /* make it short */ if (!strcmp(recbuf,statusstr)) { return 0; /* we're ok */ } if (recbuf[0] > '3') { /* oh well, some sort of error. */ snprintf(errorstr,SHORTLEN,"ERROR ftp_status wants %s but got %s", statusstr, recbuf); ffpmsg(errorstr); /* Return the numerical code, if string can be converted to int. But must not return 0 from here. */ ftpcode = atoi(recbuf); return ftpcode ? ftpcode : 1; } snprintf(errorstr,SHORTLEN,"ERROR ftp_status wants %s but got unexpected %s", statusstr, recbuf); ffpmsg(errorstr); } } /* *---------------------------------------------------------------------- * * CreateSocketAddress -- * * This function initializes a sockaddr structure for a host and port. * * Results: * 1 if the host was valid, 0 if the host could not be converted to * an IP address. * * Side effects: * Fills in the *sockaddrPtr structure. * *---------------------------------------------------------------------- */ static int CreateSocketAddress( struct sockaddr_in *sockaddrPtr, /* Socket address */ char *host, /* Host. NULL implies INADDR_ANY */ int port) /* Port number */ { struct hostent *hostent; /* Host database entry */ struct in_addr addr; /* For 64/32 bit madness */ char localhost[MAXLEN]; strcpy(localhost,host); memset((void *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); sockaddrPtr->sin_family = AF_INET; sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF)); if (host == NULL) { addr.s_addr = INADDR_ANY; } else { addr.s_addr = inet_addr(localhost); if (addr.s_addr == 0xFFFFFFFF) { hostent = gethostbyname(localhost); if (hostent != NULL) { memcpy((void *) &addr, (void *) hostent->h_addr_list[0], (size_t) hostent->h_length); } else { #ifdef EHOSTUNREACH errno = EHOSTUNREACH; #else #ifdef ENXIO errno = ENXIO; #endif #endif return 0; /* error */ } } } /* * NOTE: On 64 bit machines the assignment below is rumored to not * do the right thing. Please report errors related to this if you * observe incorrect behavior on 64 bit machines such as DEC Alphas. * Should we modify this code to do an explicit memcpy? */ sockaddrPtr->sin_addr.s_addr = addr.s_addr; return 1; /* Success. */ } /* Signal handler for timeouts */ static void signal_handler(int sig) { switch (sig) { case SIGALRM: /* process for alarm */ longjmp(env,sig); default: { /* Hmm, shouldn't have happend */ exit(sig); } } } /**************************************************************/ /* Root driver */ /*--------------------------------------------------------------------------*/ int root_init(void) { int ii; for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ { handleTable[ii].sock = 0; handleTable[ii].currentpos = 0; } return(0); } /*--------------------------------------------------------------------------*/ int root_setoptions(int options) { /* do something with the options argument, to stop compiler warning */ options = 0; return(options); } /*--------------------------------------------------------------------------*/ int root_getoptions(int *options) { *options = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_getversion(int *version) { *version = 10; return(0); } /*--------------------------------------------------------------------------*/ int root_shutdown(void) { return(0); } /*--------------------------------------------------------------------------*/ int root_open(char *url, int rwmode, int *handle) { int ii, status; int sock; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].sock == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /*open the file */ if (rwmode) { status = root_openfile(url, "update", &sock); } else { status = root_openfile(url, "read", &sock); } if (status) return(status); handleTable[ii].sock = sock; handleTable[ii].currentpos = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_create(char *filename, int *handle) { int ii, status; int sock; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].sock == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /*open the file */ status = root_openfile(filename, "create", &sock); if (status) { ffpmsg("Unable to create file"); return(status); } handleTable[ii].sock = sock; handleTable[ii].currentpos = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_size(int handle, LONGLONG *filesize) /* return the size of the file in bytes */ { int sock; int offset; int status; int op; sock = handleTable[handle].sock; status = root_send_buffer(sock,ROOTD_STAT,NULL,0); status = root_recv_buffer(sock,&op,(char *)&offset, 4); *filesize = (LONGLONG) ntohl(offset); return(0); } /*--------------------------------------------------------------------------*/ int root_close(int handle) /* close the file */ { int status; int sock; sock = handleTable[handle].sock; status = root_send_buffer(sock,ROOTD_CLOSE,NULL,0); close(sock); handleTable[handle].sock = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_flush(int handle) /* flush the file */ { int status; int sock; sock = handleTable[handle].sock; status = root_send_buffer(sock,ROOTD_FLUSH,NULL,0); return(0); } /*--------------------------------------------------------------------------*/ int root_seek(int handle, LONGLONG offset) /* seek to position relative to start of the file */ { handleTable[handle].currentpos = offset; return(0); } /*--------------------------------------------------------------------------*/ int root_read(int hdl, void *buffer, long nbytes) /* read bytes from the current position in the file */ { char msg[SHORTLEN]; int op; int status; int astat; /* we presume here that the file position will never be > 2**31 = 2.1GB */ snprintf(msg,SHORTLEN,"%ld %ld ",(long) handleTable[hdl].currentpos,nbytes); status = root_send_buffer(handleTable[hdl].sock,ROOTD_GET,msg,strlen(msg)); if ((unsigned) status != strlen(msg)) { return (READ_ERROR); } astat = 0; status = root_recv_buffer(handleTable[hdl].sock,&op,(char *) &astat,4); if (astat != 0) { return (READ_ERROR); } status = NET_RecvRaw(handleTable[hdl].sock,buffer,nbytes); if (status != nbytes) { return (READ_ERROR); } handleTable[hdl].currentpos += nbytes; return(0); } /*--------------------------------------------------------------------------*/ int root_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { char msg[SHORTLEN]; int len; int sock; int status; int astat; int op; sock = handleTable[hdl].sock; /* we presume here that the file position will never be > 2**31 = 2.1GB */ snprintf(msg,SHORTLEN,"%ld %ld ",(long) handleTable[hdl].currentpos,nbytes); len = strlen(msg); status = root_send_buffer(sock,ROOTD_PUT,msg,len+1); if (status != len+1) { return (WRITE_ERROR); } status = NET_SendRaw(sock,buffer,nbytes,NET_DEFAULT); if (status != nbytes) { return (WRITE_ERROR); } astat = 0; status = root_recv_buffer(handleTable[hdl].sock,&op,(char *) &astat,4); if (astat != 0) { return (WRITE_ERROR); } handleTable[hdl].currentpos += nbytes; return(0); } /*--------------------------------------------------------------------------*/ int root_openfile(char *url, char *rwmode, int *sock) /* lowest level routine to physically open a root file */ { int status; char recbuf[MAXLEN]; char errorstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char fn[MAXLEN]; char turl[MAXLEN]; int port; int op; int ii; int authstat; /* Parse the URL apart again */ if (strlen(url)+7 > MAXLEN-1) { ffpmsg("Error: url too long"); return(FILE_NOT_OPENED); } strcpy(turl,"root://"); strcat(turl,url); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (root_open) %s",url); ffpmsg(errorstr); return (FILE_NOT_OPENED); } /* Connect to the remote host */ *sock = NET_TcpConnect(host,port); if (*sock < 0) { ffpmsg("Couldn't connect to host (root_openfile)"); return (FILE_NOT_OPENED); } /* get the username */ if (NULL != getenv("ROOTUSERNAME")) { if (strlen(getenv("ROOTUSERNAME")) > MAXLEN-1) { ffpmsg("root user name too long (root_openfile)"); return (FILE_NOT_OPENED); } strcpy(recbuf,getenv("ROOTUSERNAME")); } else { printf("Username: "); fgets(recbuf,MAXLEN,stdin); recbuf[strlen(recbuf)-1] = '\0'; } status = root_send_buffer(*sock, ROOTD_USER, recbuf,strlen(recbuf)); if (status < 0) { ffpmsg("error talking to remote system on username "); return (FILE_NOT_OPENED); } status = root_recv_buffer(*sock,&op,(char *)&authstat,4); if (!status) { ffpmsg("error talking to remote system on username"); return (FILE_NOT_OPENED); } if (op != ROOTD_AUTH) { ffpmsg("ERROR on ROOTD_USER"); ffpmsg(recbuf); return (FILE_NOT_OPENED); } /* now the password */ if (NULL != getenv("ROOTPASSWORD")) { if (strlen(getenv("ROOTPASSWORD")) > MAXLEN-1) { ffpmsg("root password too long (root_openfile)"); return (FILE_NOT_OPENED); } strcpy(recbuf,getenv("ROOTPASSWORD")); } else { printf("Password: "); fgets(recbuf,MAXLEN,stdin); recbuf[strlen(recbuf)-1] = '\0'; } /* ones complement the password */ for (ii=0;(unsigned) ii MAXLEN-1) { ffpmsg("root file name too long (root_openfile)"); return (FILE_NOT_OPENED); } strcpy(recbuf,fn); strcat(recbuf," "); strcat(recbuf,rwmode); status = root_send_buffer(*sock, ROOTD_OPEN, recbuf, strlen(recbuf)); if (status < 0) { ffpmsg("error talking to remote system on open "); return (FILE_NOT_OPENED); } status = root_recv_buffer(*sock,&op,(char *)&authstat,4); if (status < 0) { ffpmsg("error talking to remote system on open"); return (FILE_NOT_OPENED); } if ((op != ROOTD_OPEN) && (authstat != 0)) { ffpmsg("ERROR on ROOTD_OPEN"); ffpmsg(recbuf); return (FILE_NOT_OPENED); } return 0; } static int root_send_buffer(int sock, int op, char *buffer, int buflen) { /* send a buffer, the form is includes the 4 bytes for the op, the length bytes (4) are implicit if buffer is null don't send it, not everything needs something sent */ int len; int status; int hdr[2]; len = 4; if (buffer != NULL) { len += buflen; } hdr[0] = htonl(len); hdr[1] = htonl(op); status = NET_SendRaw(sock,hdr,sizeof(hdr),NET_DEFAULT); if (status < 0) { return status; } if (buffer != NULL) { status = NET_SendRaw(sock,buffer,buflen,NET_DEFAULT); } return status; } static int root_recv_buffer(int sock, int *op, char *buffer, int buflen) { /* recv a buffer, the form is */ int recv1 = 0; int len; int status; char recbuf[MAXLEN]; status = NET_RecvRaw(sock,&len,4); if (status < 0) { return status; } recv1 += status; len = ntohl(len); /* ok, have the length, recive the operation */ len -= 4; status = NET_RecvRaw(sock,op,4); if (status < 0) { return status; } recv1 += status; *op = ntohl(*op); if (len > MAXLEN) { len = MAXLEN; } if (len > 0) { /* Get the rest of the message */ status = NET_RecvRaw(sock,recbuf,len); if (len > buflen) { len = buflen; } memcpy(buffer,recbuf,len); if (status < 0) { return status; } } recv1 += status; return recv1; } /*****************************************************************************/ /* Encode a string into MIME Base64 format string */ static int encode64(unsigned s_len, char *src, unsigned d_len, char *dst) { static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "+/"; unsigned triad; for (triad = 0; triad < s_len; triad += 3) { unsigned long int sr; unsigned byte; for (byte = 0; (byte<3) && (triad+byte #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffppx( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ long *firstpix, /* I - coord of first pixel to write(1 based) */ LONGLONG nelem, /* I - number of values to write */ void *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of pixels to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine is simillar to ffppr, except it supports writing to large images with more than 2**31 pixels. */ { int naxis, ii; long group = 1; LONGLONG firstelem, dimsize = 1, naxes[9]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgiszll(fptr, 9, naxes, status); firstelem = 0; for (ii=0; ii < naxis; ii++) { firstelem += ((firstpix[ii] - 1) * dimsize); dimsize *= naxes[ii]; } firstelem++; if (datatype == TBYTE) { ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status); } else if (datatype == TSBYTE) { ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status); } else if (datatype == TUSHORT) { ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array, status); } else if (datatype == TSHORT) { ffppri(fptr, group, firstelem, nelem, (short *) array, status); } else if (datatype == TUINT) { ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status); } else if (datatype == TINT) { ffpprk(fptr, group, firstelem, nelem, (int *) array, status); } else if (datatype == TULONG) { ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status); } else if (datatype == TLONG) { ffpprj(fptr, group, firstelem, nelem, (long *) array, status); } else if (datatype == TULONGLONG) { ffpprujj(fptr, group, firstelem, nelem, (ULONGLONG *) array, status); } else if (datatype == TLONGLONG) { ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status); } else if (datatype == TFLOAT) { ffppre(fptr, group, firstelem, nelem, (float *) array, status); } else if (datatype == TDOUBLE) { ffpprd(fptr, group, firstelem, nelem, (double *) array, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffppxll( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG *firstpix, /* I - coord of first pixel to write(1 based) */ LONGLONG nelem, /* I - number of values to write */ void *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of pixels to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine is simillar to ffppr, except it supports writing to large images with more than 2**31 pixels. */ { int naxis, ii; long group = 1; LONGLONG firstelem, dimsize = 1, naxes[9]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgiszll(fptr, 9, naxes, status); firstelem = 0; for (ii=0; ii < naxis; ii++) { firstelem += ((firstpix[ii] - 1) * dimsize); dimsize *= naxes[ii]; } firstelem++; if (datatype == TBYTE) { ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status); } else if (datatype == TSBYTE) { ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status); } else if (datatype == TUSHORT) { ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array, status); } else if (datatype == TSHORT) { ffppri(fptr, group, firstelem, nelem, (short *) array, status); } else if (datatype == TUINT) { ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status); } else if (datatype == TINT) { ffpprk(fptr, group, firstelem, nelem, (int *) array, status); } else if (datatype == TULONG) { ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status); } else if (datatype == TLONG) { ffpprj(fptr, group, firstelem, nelem, (long *) array, status); } else if (datatype == TULONGLONG) { ffpprujj(fptr, group, firstelem, nelem, (ULONGLONG *) array, status); } else if (datatype == TLONGLONG) { ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status); } else if (datatype == TFLOAT) { ffppre(fptr, group, firstelem, nelem, (float *) array, status); } else if (datatype == TDOUBLE) { ffpprd(fptr, group, firstelem, nelem, (double *) array, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffppxn( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ long *firstpix, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ void *array, /* I - array of values that are written */ void *nulval, /* I - pointer to the null value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine supports writing to large images with more than 2**31 pixels. */ { int naxis, ii; long group = 1; LONGLONG firstelem, dimsize = 1, naxes[9]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (nulval == NULL) /* null value not defined? */ { ffppx(fptr, datatype, firstpix, nelem, array, status); return(*status); } /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgiszll(fptr, 9, naxes, status); firstelem = 0; for (ii=0; ii < naxis; ii++) { firstelem += ((firstpix[ii] - 1) * dimsize); dimsize *= naxes[ii]; } firstelem++; if (datatype == TBYTE) { ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, *(unsigned char *) nulval, status); } else if (datatype == TSBYTE) { ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, *(signed char *) nulval, status); } else if (datatype == TUSHORT) { ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array, *(unsigned short *) nulval,status); } else if (datatype == TSHORT) { ffppni(fptr, group, firstelem, nelem, (short *) array, *(short *) nulval, status); } else if (datatype == TUINT) { ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array, *(unsigned int *) nulval, status); } else if (datatype == TINT) { ffppnk(fptr, group, firstelem, nelem, (int *) array, *(int *) nulval, status); } else if (datatype == TULONG) { ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array, *(unsigned long *) nulval,status); } else if (datatype == TLONG) { ffppnj(fptr, group, firstelem, nelem, (long *) array, *(long *) nulval, status); } else if (datatype == TULONGLONG) { ffppnujj(fptr, group, firstelem, nelem, (ULONGLONG *) array, *(ULONGLONG *) nulval, status); } else if (datatype == TLONGLONG) { ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array, *(LONGLONG *) nulval, status); } else if (datatype == TFLOAT) { ffppne(fptr, group, firstelem, nelem, (float *) array, *(float *) nulval, status); } else if (datatype == TDOUBLE) { ffppnd(fptr, group, firstelem, nelem, (double *) array, *(double *) nulval, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffppxnll( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG *firstpix, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ void *array, /* I - array of values that are written */ void *nulval, /* I - pointer to the null value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine supports writing to large images with more than 2**31 pixels. */ { int naxis, ii; long group = 1; LONGLONG firstelem, dimsize = 1, naxes[9]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (nulval == NULL) /* null value not defined? */ { ffppxll(fptr, datatype, firstpix, nelem, array, status); return(*status); } /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgiszll(fptr, 9, naxes, status); firstelem = 0; for (ii=0; ii < naxis; ii++) { firstelem += ((firstpix[ii] - 1) * dimsize); dimsize *= naxes[ii]; } firstelem++; if (datatype == TBYTE) { ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, *(unsigned char *) nulval, status); } else if (datatype == TSBYTE) { ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, *(signed char *) nulval, status); } else if (datatype == TUSHORT) { ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array, *(unsigned short *) nulval,status); } else if (datatype == TSHORT) { ffppni(fptr, group, firstelem, nelem, (short *) array, *(short *) nulval, status); } else if (datatype == TUINT) { ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array, *(unsigned int *) nulval, status); } else if (datatype == TINT) { ffppnk(fptr, group, firstelem, nelem, (int *) array, *(int *) nulval, status); } else if (datatype == TULONG) { ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array, *(unsigned long *) nulval,status); } else if (datatype == TLONG) { ffppnj(fptr, group, firstelem, nelem, (long *) array, *(long *) nulval, status); } else if (datatype == TULONGLONG) { ffppnujj(fptr, group, firstelem, nelem, (ULONGLONG *) array, *(ULONGLONG *) nulval, status); } else if (datatype == TLONGLONG) { ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array, *(LONGLONG *) nulval, status); } else if (datatype == TFLOAT) { ffppne(fptr, group, firstelem, nelem, (float *) array, *(float *) nulval, status); } else if (datatype == TDOUBLE) { ffppnd(fptr, group, firstelem, nelem, (double *) array, *(double *) nulval, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffppr( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ void *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long group = 1; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (datatype == TBYTE) { ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status); } else if (datatype == TSBYTE) { ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status); } else if (datatype == TUSHORT) { ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array, status); } else if (datatype == TSHORT) { ffppri(fptr, group, firstelem, nelem, (short *) array, status); } else if (datatype == TUINT) { ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status); } else if (datatype == TINT) { ffpprk(fptr, group, firstelem, nelem, (int *) array, status); } else if (datatype == TULONG) { ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status); } else if (datatype == TLONG) { ffpprj(fptr, group, firstelem, nelem, (long *) array, status); } else if (datatype == TULONGLONG) { ffpprujj(fptr, group, firstelem, nelem, (ULONGLONG *) array, status); } else if (datatype == TLONGLONG) { ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status); } else if (datatype == TFLOAT) { ffppre(fptr, group, firstelem, nelem, (float *) array, status); } else if (datatype == TDOUBLE) { ffpprd(fptr, group, firstelem, nelem, (double *) array, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffppn( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ void *array, /* I - array of values that are written */ void *nulval, /* I - pointer to the null value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long group = 1; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (nulval == NULL) /* null value not defined? */ { ffppr(fptr, datatype, firstelem, nelem, array, status); return(*status); } if (datatype == TBYTE) { ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, *(unsigned char *) nulval, status); } else if (datatype == TSBYTE) { ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, *(signed char *) nulval, status); } else if (datatype == TUSHORT) { ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array, *(unsigned short *) nulval,status); } else if (datatype == TSHORT) { ffppni(fptr, group, firstelem, nelem, (short *) array, *(short *) nulval, status); } else if (datatype == TUINT) { ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array, *(unsigned int *) nulval, status); } else if (datatype == TINT) { ffppnk(fptr, group, firstelem, nelem, (int *) array, *(int *) nulval, status); } else if (datatype == TULONG) { ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array, *(unsigned long *) nulval,status); } else if (datatype == TLONG) { ffppnj(fptr, group, firstelem, nelem, (long *) array, *(long *) nulval, status); } else if (datatype == TULONGLONG) { ffppnujj(fptr, group, firstelem, nelem, (ULONGLONG *) array, *(ULONGLONG *) nulval, status); } else if (datatype == TLONGLONG) { ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array, *(LONGLONG *) nulval, status); } else if (datatype == TFLOAT) { ffppne(fptr, group, firstelem, nelem, (float *) array, *(float *) nulval, status); } else if (datatype == TDOUBLE) { ffppnd(fptr, group, firstelem, nelem, (double *) array, *(double *) nulval, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffpss( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc , /* I - 'top right corner' of the subsection */ void *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write a section of values to the primary array. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). This routine supports writing to large images with more than 2**31 pixels. */ { int naxis; long naxes[9]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* get the size of the image */ ffgidm(fptr, &naxis, status); ffgisz(fptr, 9, naxes, status); if (datatype == TBYTE) { ffpssb(fptr, 1, naxis, naxes, blc, trc, (unsigned char *) array, status); } else if (datatype == TSBYTE) { ffpsssb(fptr, 1, naxis, naxes, blc, trc, (signed char *) array, status); } else if (datatype == TUSHORT) { ffpssui(fptr, 1, naxis, naxes, blc, trc, (unsigned short *) array, status); } else if (datatype == TSHORT) { ffpssi(fptr, 1, naxis, naxes, blc, trc, (short *) array, status); } else if (datatype == TUINT) { ffpssuk(fptr, 1, naxis, naxes, blc, trc, (unsigned int *) array, status); } else if (datatype == TINT) { ffpssk(fptr, 1, naxis, naxes, blc, trc, (int *) array, status); } else if (datatype == TULONG) { ffpssuj(fptr, 1, naxis, naxes, blc, trc, (unsigned long *) array, status); } else if (datatype == TLONG) { ffpssj(fptr, 1, naxis, naxes, blc, trc, (long *) array, status); } else if (datatype == TULONGLONG) { ffpssujj(fptr, 1, naxis, naxes, blc, trc, (ULONGLONG *) array, status); } else if (datatype == TLONGLONG) { ffpssjj(fptr, 1, naxis, naxes, blc, trc, (LONGLONG *) array, status); } else if (datatype == TFLOAT) { ffpsse(fptr, 1, naxis, naxes, blc, trc, (float *) array, status); } else if (datatype == TDOUBLE) { ffpssd(fptr, 1, naxis, naxes, blc, trc, (double *) array, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffpcl( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of elements to write */ void *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to a table column. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS column is not the same as the array being written). */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (datatype == TBIT) { ffpclx(fptr, colnum, firstrow, (long) firstelem, (long) nelem, (char *) array, status); } else if (datatype == TBYTE) { ffpclb(fptr, colnum, firstrow, firstelem, nelem, (unsigned char *) array, status); } else if (datatype == TSBYTE) { ffpclsb(fptr, colnum, firstrow, firstelem, nelem, (signed char *) array, status); } else if (datatype == TUSHORT) { ffpclui(fptr, colnum, firstrow, firstelem, nelem, (unsigned short *) array, status); } else if (datatype == TSHORT) { ffpcli(fptr, colnum, firstrow, firstelem, nelem, (short *) array, status); } else if (datatype == TUINT) { ffpcluk(fptr, colnum, firstrow, firstelem, nelem, (unsigned int *) array, status); } else if (datatype == TINT) { ffpclk(fptr, colnum, firstrow, firstelem, nelem, (int *) array, status); } else if (datatype == TULONG) { ffpcluj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array, status); } else if (datatype == TLONG) { ffpclj(fptr, colnum, firstrow, firstelem, nelem, (long *) array, status); } else if (datatype == TULONGLONG) { ffpclujj(fptr, colnum, firstrow, firstelem, nelem, (ULONGLONG *) array, status); } else if (datatype == TLONGLONG) { ffpcljj(fptr, colnum, firstrow, firstelem, nelem, (LONGLONG *) array, status); } else if (datatype == TFLOAT) { ffpcle(fptr, colnum, firstrow, firstelem, nelem, (float *) array, status); } else if (datatype == TDOUBLE) { ffpcld(fptr, colnum, firstrow, firstelem, nelem, (double *) array, status); } else if (datatype == TCOMPLEX) { ffpcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, (float *) array, status); } else if (datatype == TDBLCOMPLEX) { ffpcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, (double *) array, status); } else if (datatype == TLOGICAL) { ffpcll(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status); } else if (datatype == TSTRING) { ffpcls(fptr, colnum, firstrow, firstelem, nelem, (char **) array, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffpcn( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of elements to write */ void *array, /* I - array of values that are written */ void *nulval, /* I - pointer to the null value */ int *status) /* IO - error status */ /* Write an array of values to a table column. The datatype of the input array is defined by the 2nd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS column is not the same as the array being written). */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (nulval == NULL) /* null value not defined? */ { ffpcl(fptr, datatype, colnum, firstrow, firstelem, nelem, array, status); return(*status); } if (datatype == TBYTE) { ffpcnb(fptr, colnum, firstrow, firstelem, nelem, (unsigned char *) array, *(unsigned char *) nulval, status); } else if (datatype == TSBYTE) { ffpcnsb(fptr, colnum, firstrow, firstelem, nelem, (signed char *) array, *(signed char *) nulval, status); } else if (datatype == TUSHORT) { ffpcnui(fptr, colnum, firstrow, firstelem, nelem, (unsigned short *) array, *(unsigned short *) nulval, status); } else if (datatype == TSHORT) { ffpcni(fptr, colnum, firstrow, firstelem, nelem, (short *) array, *(unsigned short *) nulval, status); } else if (datatype == TUINT) { ffpcnuk(fptr, colnum, firstrow, firstelem, nelem, (unsigned int *) array, *(unsigned int *) nulval, status); } else if (datatype == TINT) { ffpcnk(fptr, colnum, firstrow, firstelem, nelem, (int *) array, *(int *) nulval, status); } else if (datatype == TULONG) { ffpcnuj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array, *(unsigned long *) nulval, status); } else if (datatype == TLONG) { ffpcnj(fptr, colnum, firstrow, firstelem, nelem, (long *) array, *(long *) nulval, status); } else if (datatype == TULONGLONG) { ffpcnujj(fptr, colnum, firstrow, firstelem, nelem, (ULONGLONG *) array, *(ULONGLONG *) nulval, status); } else if (datatype == TLONGLONG) { ffpcnjj(fptr, colnum, firstrow, firstelem, nelem, (LONGLONG *) array, *(LONGLONG *) nulval, status); } else if (datatype == TFLOAT) { ffpcne(fptr, colnum, firstrow, firstelem, nelem, (float *) array, *(float *) nulval, status); } else if (datatype == TDOUBLE) { ffpcnd(fptr, colnum, firstrow, firstelem, nelem, (double *) array, *(double *) nulval, status); } else if (datatype == TCOMPLEX) { ffpcne(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, (float *) array, *(float *) nulval, status); } else if (datatype == TDBLCOMPLEX) { ffpcnd(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, (double *) array, *(double *) nulval, status); } else if (datatype == TLOGICAL) { ffpcnl(fptr, colnum, firstrow, firstelem, nelem, (char *) array, *(char *) nulval, status); } else if (datatype == TSTRING) { ffpcns(fptr, colnum, firstrow, firstelem, nelem, (char **) array, (char *) nulval, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffpcln( fitsfile *fptr, /* I - FITS file pointer */ int ncols, /* I - number of columns to write */ int *datatype, /* I - datatypes of the values */ int *colnum, /* I - columns numbers to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG nrows, /* I - number of rows to write */ void **array, /* I - array of pointers to values to write */ void **nulval, /* I - array of pointers to values for undefined pixels */ int *status) /* IO - error status */ /* Write arrays of values to NCOLS table columns. This is an optimization to write all columns in one pass through the table. The datatypes of the input arrays are defined by the 3rd argument. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). Undefined elements for column i that are equal to *(nulval[i]) are set to the defined null value, unless nulval[i]=0, in which case no checking for undefined values will be performed. */ { LONGLONG ntotrows, ndone, nwrite, currow; long nrowbuf; LONGLONG *repeats = 0; size_t sizes[255] = {0}; int icol; sizes[TBYTE] = sizes[TSBYTE] = sizes[TLOGICAL] = sizeof(char); sizes[TUSHORT] = sizes[TSHORT] = sizeof(short int); sizes[TINT] = sizes[TUINT] = sizeof(int); sizes[TLONG] = sizes[TULONG] = sizeof(long int); sizes[TLONGLONG] = sizes[TULONGLONG] = sizeof(LONGLONG); sizes[TFLOAT] = sizeof(float); sizes[TDOUBLE] = sizeof(double); sizes[TDBLCOMPLEX] = 2*sizeof(double); if (*status > 0) return(*status); if (ncols <= 0) return (*status=0); repeats = malloc(sizeof(LONGLONG)*ncols); if (repeats == 0) return (*status=MEMORY_ALLOCATION); fits_get_num_rowsll(fptr, &ntotrows, status); fits_get_rowsize(fptr, &nrowbuf, status); /* Retrieve column repeats */ for (icol = 0; (icol < ncols) && (icol < 1000); icol++) { int typecode; LONGLONG repeat, width; fits_get_coltypell(fptr, colnum[icol], &typecode, &repeat, &width, status); repeats[icol] = repeat; if (datatype[icol] == TBIT || datatype[icol] == TSTRING || sizes[datatype[icol]] == 0) { ffpmsg("Cannot write to TBIT or TSTRING datatypes (ffpcln)"); *status = BAD_DATATYPE; } if (typecode < 0) { ffpmsg("Cannot write to variable-length data (ffpcln)"); *status = BAD_DIMEN; } if (*status) break; } if (*status) { free(repeats); return *status; } /* Optimize for 1 column */ if (ncols == 1) { fits_write_colnull(fptr, datatype[0], colnum[0], firstrow, 1, nrows*repeats[0], array[0], nulval[0], status); free(repeats); return *status; } /* Scan through file, in chunks of nrowbuf */ currow = firstrow; ndone = 0; while (ndone < nrows) { int icol; nwrite = (nrows-ndone); if (nwrite > nrowbuf) nwrite = nrowbuf; for (icol=0; icolfptr = fptr; strncpy(col->colname, colname,69); col->colname[69]=0; col->colnum = 0; /* set column number undefined since name is given */ col->datatype = datatype; col->iotype = iotype; return(0); } /*--------------------------------------------------------------------------*/ int fits_iter_set_by_num(iteratorCol *col, /* I - iterator column structure */ fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int datatype, /* I - column datatype */ int iotype) /* I - InputCol, InputOutputCol, or OutputCol */ /* set all the parameters for an iterator column, by column number */ { col->fptr = fptr; col->colnum = colnum; col->datatype = datatype; col->iotype = iotype; return(0); } /*--------------------------------------------------------------------------*/ int fits_iter_set_file(iteratorCol *col, /* I - iterator column structure */ fitsfile *fptr) /* I - FITS file pointer */ /* set iterator column parameter */ { col->fptr = fptr; return(0); } /*--------------------------------------------------------------------------*/ int fits_iter_set_colname(iteratorCol *col, /* I - iterator col structure */ char *colname) /* I - column name */ /* set iterator column parameter */ { strncpy(col->colname, colname,69); col->colname[69]=0; col->colnum = 0; /* set column number undefined since name is given */ return(0); } /*--------------------------------------------------------------------------*/ int fits_iter_set_colnum(iteratorCol *col, /* I - iterator column structure */ int colnum) /* I - column number */ /* set iterator column parameter */ { col->colnum = colnum; return(0); } /*--------------------------------------------------------------------------*/ int fits_iter_set_datatype(iteratorCol *col, /* I - iterator col structure */ int datatype) /* I - column datatype */ /* set iterator column parameter */ { col->datatype = datatype; return(0); } /*--------------------------------------------------------------------------*/ int fits_iter_set_iotype(iteratorCol *col, /* I - iterator column structure */ int iotype) /* I - InputCol, InputOutputCol, or OutputCol */ /* set iterator column parameter */ { col->iotype = iotype; return(0); } /*--------------------------------------------------------------------------*/ fitsfile * fits_iter_get_file(iteratorCol *col) /* I -iterator col structure */ /* get iterator column parameter */ { return(col->fptr); } /*--------------------------------------------------------------------------*/ char * fits_iter_get_colname(iteratorCol *col) /* I -iterator col structure */ /* get iterator column parameter */ { return(col->colname); } /*--------------------------------------------------------------------------*/ int fits_iter_get_colnum(iteratorCol *col) /* I - iterator column structure */ /* get iterator column parameter */ { return(col->colnum); } /*--------------------------------------------------------------------------*/ int fits_iter_get_datatype(iteratorCol *col) /* I - iterator col structure */ /* get iterator column parameter */ { return(col->datatype); } /*--------------------------------------------------------------------------*/ int fits_iter_get_iotype(iteratorCol *col) /* I - iterator column structure */ /* get iterator column parameter */ { return(col->iotype); } /*--------------------------------------------------------------------------*/ void * fits_iter_get_array(iteratorCol *col) /* I - iterator col structure */ /* get iterator column parameter */ { return(col->array); } /*--------------------------------------------------------------------------*/ long fits_iter_get_tlmin(iteratorCol *col) /* I - iterator column structure */ /* get iterator column parameter */ { return(col->tlmin); } /*--------------------------------------------------------------------------*/ long fits_iter_get_tlmax(iteratorCol *col) /* I - iterator column structure */ /* get iterator column parameter */ { return(col->tlmax); } /*--------------------------------------------------------------------------*/ long fits_iter_get_repeat(iteratorCol *col) /* I - iterator col structure */ /* get iterator column parameter */ { return(col->repeat); } /*--------------------------------------------------------------------------*/ char * fits_iter_get_tunit(iteratorCol *col) /* I - iterator col structure */ /* get iterator column parameter */ { return(col->tunit); } /*--------------------------------------------------------------------------*/ char * fits_iter_get_tdisp(iteratorCol *col) /* I -iterator col structure */ /* get iterator column parameter */ { return(col->tdisp); } /*--------------------------------------------------------------------------*/ int ffiter(int n_cols, iteratorCol *cols, long offset, long n_per_loop, int (*work_fn)(long total_n, long offset, long first_n, long n_values, int n_cols, iteratorCol *cols, void *userPointer), void *userPointer, int *status) /* The iterator function. This function will pass the specified columns from a FITS table or pixels from a FITS image to the user-supplied function. Depending on the size of the table or image, only a subset of the rows or pixels may be passed to the function on each call, in which case the function will be called multiple times until all the rows or pixels have been processed. */ { typedef struct /* structure to store the column null value */ { int nullsize; /* length of the null value, in bytes */ union { /* default null value for the column */ char *stringnull; unsigned char charnull; signed char scharnull; int intnull; short shortnull; long longnull; unsigned int uintnull; unsigned short ushortnull; unsigned long ulongnull; float floatnull; double doublenull; LONGLONG longlongnull; } null; } colNulls; void *dataptr, *defaultnull; colNulls *col; int ii, jj, tstatus, naxis, bitpix; int typecode, hdutype, jtype, type, anynul=0, nfiles, nbytes; long totaln, nleft, frow, felement, n_optimum, i_optimum, ntodo; long rept, rowrept, width, tnull, naxes[9] = {1,1,1,1,1,1,1,1,1}, groups; double zeros = 0.; char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], nullstr[FLEN_VALUE]; char **stringptr, *nullptr, *cptr; if (*status > 0) return(*status); if (n_cols < 0 || n_cols > 999 ) { ffpmsg("Illegal number of columms (ffiter)"); return(*status = BAD_COL_NUM); /* negative number of columns */ } /*------------------------------------------------------------*/ /* Make sure column numbers and datatypes are in legal range */ /* and column numbers and datatypes are legal. */ /* Also fill in other parameters in the column structure. */ /*------------------------------------------------------------*/ ffghdt(cols[0].fptr, &hdutype, status); /* type of first HDU */ for (jj = 0; jj < n_cols; jj++) { /* check that output datatype code value is legal */ type = cols[jj].datatype; /* Allow variable length arrays for InputCol and InputOutputCol columns, but not for OutputCol/TemporaryCol columns. Variable length arrays have a negative type code value. */ if ( !((cols[jj].iotype == OutputCol) || (cols[jj].iotype == TemporaryCol)) && (type<0)) { type*=-1; } /* TemporaryCol must have defined datatype and repeat */ if (cols[jj].iotype == TemporaryCol && (type <= 0 || cols[jj].repeat <= 0)) { snprintf(message,FLEN_ERRMSG, "TemporaryCol column must have defined datatype and repeat for column %d (ffiter)", jj + 1); ffpmsg(message); return(*status = BAD_DATATYPE); } /* Check for variable length or illegal data types */ if (type != 0 && type != TBYTE && type != TSBYTE && type != TLOGICAL && type != TSTRING && type != TSHORT && type != TINT && type != TLONG && type != TFLOAT && type != TDOUBLE && type != TCOMPLEX && type != TULONG && type != TUSHORT && type != TDBLCOMPLEX && type != TLONGLONG ) { if (type < 0) { snprintf(message,FLEN_ERRMSG, "Variable length array not allowed for output column number %d (ffiter)", jj + 1); } else { snprintf(message,FLEN_ERRMSG, "Illegal datatype for column number %d: %d (ffiter)", jj + 1, cols[jj].datatype); } ffpmsg(message); return(*status = BAD_DATATYPE); } /* initialize TLMINn, TLMAXn, column name, and display format */ cols[jj].tlmin = 0; cols[jj].tlmax = 0; cols[jj].tunit[0] = '\0'; cols[jj].tdisp[0] = '\0'; /* Determine HDU type of this table (or BINARY_TBL for TemporaryCol) */ if (cols[jj].iotype != TemporaryCol) { ffghdt(cols[jj].fptr, &jtype, status); /* get HDU type */ } else { hdutype = BINARY_TBL; } if (hdutype == IMAGE_HDU) /* operating on FITS images */ { if (jtype != IMAGE_HDU) { snprintf(message,FLEN_ERRMSG, "File %d not positioned to an image extension (ffiter)", jj + 1); return(*status = NOT_IMAGE); } /* since this is an image, set a dummy column number = 0 */ cols[jj].colnum = 0; strcpy(cols[jj].colname, "IMAGE"); /* dummy name for images */ tstatus = 0; ffgkys(cols[jj].fptr, "BUNIT", cols[jj].tunit, 0, &tstatus); if (cols[jj].iotype == TemporaryCol) { snprintf(message,FLEN_ERRMSG, "Column type TemporaryCol not permitted for IMAGE HDUs (ffiter)"); return(*status = BAD_DATATYPE); } } else /* operating on FITS tables */ { if (jtype == IMAGE_HDU) { snprintf(message,FLEN_ERRMSG, "File %d not positioned to a table extension (ffiter)", jj + 1); return(*status = NOT_TABLE); } if (cols[jj].iotype != TemporaryCol) { if (cols[jj].colnum < 1) { /* find the column number for the named column */ if (ffgcno(cols[jj].fptr, CASEINSEN, cols[jj].colname, &cols[jj].colnum, status) ) { snprintf(message,FLEN_ERRMSG, "Column '%s' not found for column number %d (ffiter)", cols[jj].colname, jj + 1); ffpmsg(message); return(*status); } } /* check that the column number is valid */ if (cols[jj].colnum < 1 || cols[jj].colnum > ((cols[jj].fptr)->Fptr)->tfield) { snprintf(message,FLEN_ERRMSG, "Column %d has illegal table position number: %d (ffiter)", jj + 1, cols[jj].colnum); ffpmsg(message); return(*status = BAD_COL_NUM); } /* look for column description keywords and update structure */ tstatus = 0; ffkeyn("TLMIN", cols[jj].colnum, keyname, &tstatus); ffgkyj(cols[jj].fptr, keyname, &cols[jj].tlmin, 0, &tstatus); tstatus = 0; ffkeyn("TLMAX", cols[jj].colnum, keyname, &tstatus); ffgkyj(cols[jj].fptr, keyname, &cols[jj].tlmax, 0, &tstatus); tstatus = 0; ffkeyn("TTYPE", cols[jj].colnum, keyname, &tstatus); ffgkys(cols[jj].fptr, keyname, cols[jj].colname, 0, &tstatus); if (tstatus) cols[jj].colname[0] = '\0'; tstatus = 0; ffkeyn("TUNIT", cols[jj].colnum, keyname, &tstatus); ffgkys(cols[jj].fptr, keyname, cols[jj].tunit, 0, &tstatus); tstatus = 0; ffkeyn("TDISP", cols[jj].colnum, keyname, &tstatus); ffgkys(cols[jj].fptr, keyname, cols[jj].tdisp, 0, &tstatus); } } } /* end of loop over all columns */ /*-----------------------------------------------------------------*/ /* use the first file to set the total number of values to process */ /*-----------------------------------------------------------------*/ offset = maxvalue(offset, 0L); /* make sure offset is legal */ felement = 0; if (hdutype == IMAGE_HDU) /* get total number of pixels in the image */ { fits_get_img_dim(cols[0].fptr, &naxis, status); fits_get_img_size(cols[0].fptr, 9, naxes, status); tstatus = 0; ffgkyj(cols[0].fptr, "GROUPS", &groups, NULL, &tstatus); if (!tstatus && groups && (naxis > 1) && (naxes[0] == 0) ) { /* this is a random groups file, with NAXIS1 = 0 */ /* Use GCOUNT, the number of groups, as the first multiplier */ /* to calculate the total number of pixels in all the groups. */ ffgkyj(cols[0].fptr, "GCOUNT", &totaln, NULL, status); } else { totaln = naxes[0]; } for (ii = 1; ii < naxis; ii++) totaln *= naxes[ii]; frow = 1; felement = 1 + offset; } else /* get total number or rows in the table */ { /* Note the maxvalue here is a special case to deal with how the calculator treats expressions that have NO referenced columns, just constants and other derivable values like #ROW. In that case, the calculator creates a cols[0].fptr even though there is no column for it, and the iterator is not meant to allocate any space, etc for the column. So the maxvalue() here assures that cols[0] is always checked, even if ncols==0, which is how the original logic worked. This is a bit dangerous in the sense that, what happens if the user passes a non-calculator input to this iterator, and has NOT set fptr to a legitimate FITS handle. Boom! */ for (jj=0; jj < maxvalue(n_cols,1); jj++) { if (cols[jj].iotype != TemporaryCol && cols[jj].fptr) { ffgkyj(cols[jj].fptr, "NAXIS2", &totaln, 0, status); frow = 1 + offset; felement = 1; break; } } if (felement != 1) { snprintf(message,FLEN_ERRMSG, "There must be at least one input or output column in iterator (ffiter)"); ffpmsg(message); return(*status = BAD_COL_NUM); } } /* adjust total by the input starting offset value */ totaln -= offset; totaln = maxvalue(totaln, 0L); /* don't allow negative number */ /*------------------------------------------------------------------*/ /* Determine number of values to pass to work function on each loop */ /*------------------------------------------------------------------*/ if (n_per_loop == 0) { /* Determine optimum number of values for each iteration. */ /* Look at all the fitsfile pointers to determine the number */ /* of unique files. */ nfiles = 1; n_optimum = 0; if (cols[0].iotype != TemporaryCol) ffgrsz(cols[0].fptr, &n_optimum, status); for (jj = 1; jj < n_cols; jj++) { if (cols[jj].iotype == TemporaryCol) continue; for (ii = 0; ii < jj; ii++) { if (cols[ii].fptr == cols[jj].fptr) break; } if (ii == jj) /* this is a new file */ { nfiles++; ffgrsz(cols[jj].fptr, &i_optimum, status); if (n_optimum == 0) { /* If first column is TemporaryCol */ n_optimum = i_optimum; } else { n_optimum = minvalue(n_optimum, i_optimum); } } } /* divid n_optimum by the number of files that will be processed */ n_optimum = n_optimum / nfiles; n_optimum = maxvalue(n_optimum, 1); } else if (n_per_loop < 0) /* must pass all the values at one time */ { n_optimum = totaln; } else /* calling routine specified how many values to pass at a time */ { n_optimum = minvalue(n_per_loop, totaln); } /*--------------------------------------*/ /* allocate work arrays for each column */ /* and determine the null pixel value */ /*--------------------------------------*/ col = calloc(n_cols, sizeof(colNulls) ); /* memory for the null values */ if (!col) { ffpmsg("ffiter failed to allocate memory for null values"); *status = MEMORY_ALLOCATION; /* memory allocation failed */ return(*status); } for (jj = 0; jj < n_cols; jj++) { /* get image or column datatype and vector length */ if (hdutype == IMAGE_HDU) /* get total number of pixels in the image */ { fits_get_img_type(cols[jj].fptr, &bitpix, status); switch(bitpix) { case BYTE_IMG: typecode = TBYTE; break; case SHORT_IMG: typecode = TSHORT; break; case LONG_IMG: typecode = TLONG; break; case FLOAT_IMG: typecode = TFLOAT; break; case DOUBLE_IMG: typecode = TDOUBLE; break; case LONGLONG_IMG: typecode = TLONGLONG; break; } } else if (cols[jj].iotype != TemporaryCol) { if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept, &width, status) > 0) goto cleanup; if (typecode < 0) { /* if any variable length arrays, then the */ n_optimum = 1; /* must process the table 1 row at a time */ /* Allow variable length arrays for InputCol and InputOutputCol columns, but not for OutputCol columns. Variable length arrays have a negative type code value. */ if (cols[jj].iotype == OutputCol) { snprintf(message,FLEN_ERRMSG, "Variable length array not allowed for output column number %d (ffiter)", jj + 1); ffpmsg(message); return(*status = BAD_DATATYPE); } } } else { /* TemporaryCol - datatype etc must be defined */ typecode = cols[jj].datatype; if (typecode <= 0 || typecode == TBIT || typecode == TSTRING) { snprintf(message,FLEN_ERRMSG, "Invalid typecode for temporary output column number %d (ffiter)", jj+1); ffpmsg(message); return(*status = BAD_DATATYPE); } rept = cols[jj].repeat; if (rept <= 0) { snprintf(message,FLEN_ERRMSG, "Invalid repeat (%ld) for temporary output column number %d (ffiter)", rept, jj+1); ffpmsg(message); return(*status = BAD_DIMEN); } } /* special case where sizeof(long) = 8: use TINT instead of TLONG */ if (abs(typecode) == TLONG && sizeof(long) == 8 && sizeof(int) == 4) { if(typecode<0) { typecode = -TINT; } else { typecode = TINT; } } /* Special case: interprete 'X' column as 'B' */ if (abs(typecode) == TBIT) { typecode = typecode / TBIT * TBYTE; rept = (rept + 7) / 8; } if (cols[jj].datatype == 0) /* output datatype not specified? */ { /* special case if sizeof(long) = 8: use TINT instead of TLONG */ if (abs(typecode) == TLONG && sizeof(long) == 8 && sizeof(int) == 4) cols[jj].datatype = TINT; else cols[jj].datatype = abs(typecode); } /* calc total number of elements to do on each iteration */ if (hdutype == IMAGE_HDU || cols[jj].datatype == TSTRING) { ntodo = n_optimum; cols[jj].repeat = 1; /* handle special case of a 0-width string column */ if (hdutype == BINARY_TBL && rept == 0) cols[jj].repeat = 0; /* get the BLANK keyword value, if it exists */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tstatus = 0; ffgkyj(cols[jj].fptr, "BLANK", &tnull, 0, &tstatus); if (tstatus) { tnull = 0L; /* no null values */ } } } else { if (typecode < 0) { /* get max size of the variable length vector; dont't trust the value given by the TFORM keyword */ rept = 1; for (ii = 0; ii < totaln; ii++) { ffgdes(cols[jj].fptr, cols[jj].colnum, frow + ii, &rowrept, NULL, status); rept = maxvalue(rept, rowrept); } } ntodo = n_optimum * rept; /* vector columns */ cols[jj].repeat = rept; /* get the TNULL keyword value, if it exists */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tstatus = 0; if (hdutype == ASCII_TBL) /* TNULLn value is a string */ { ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus); ffgkys(cols[jj].fptr, keyname, nullstr, 0, &tstatus); if (tstatus) { tnull = 0L; /* keyword doesn't exist; no null values */ } else { cptr = nullstr; while (*cptr == ' ') /* skip over leading blanks */ cptr++; if (*cptr == '\0') /* TNULLn is all blanks? */ tnull = LONG_MIN; else { /* attempt to read TNULLn string as an integer */ ffc2ii(nullstr, &tnull, &tstatus); if (tstatus) tnull = LONG_MIN; /* choose smallest value */ } /* to represent nulls */ } } else /* Binary table; TNULLn value is an integer */ { ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus); ffgkyj(cols[jj].fptr, keyname, &tnull, 0, &tstatus); if (tstatus) { tnull = 0L; /* keyword doesn't exist; no null values */ } else if (tnull == 0) { /* worst possible case: a value of 0 is used to */ /* represent nulls in the FITS file. We have to */ /* use a non-zero null value here (zero is used to */ /* mean there are no null values in the array) so we */ /* will use the smallest possible integer instead. */ tnull = LONG_MIN; /* choose smallest possible value */ } } } } /* Note that the data array starts with 2nd element; */ /* 1st element of the array gives the null data value */ switch (cols[jj].datatype) { case TBYTE: cols[jj].array = calloc(ntodo + 1, sizeof(char)); col[jj].nullsize = sizeof(char); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tnull = minvalue(tnull, 255); tnull = maxvalue(tnull, 0); col[jj].null.charnull = (unsigned char) tnull; } else { col[jj].null.charnull = (unsigned char) 255; /* use 255 as null */ } break; case TSBYTE: cols[jj].array = calloc(ntodo + 1, sizeof(char)); col[jj].nullsize = sizeof(char); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tnull = minvalue(tnull, 127); tnull = maxvalue(tnull, -128); col[jj].null.scharnull = (signed char) tnull; } else { col[jj].null.scharnull = (signed char) -128; /* use -128 null */ } break; case TSHORT: cols[jj].array = calloc(ntodo + 1, sizeof(short)); col[jj].nullsize = sizeof(short); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tnull = minvalue(tnull, SHRT_MAX); tnull = maxvalue(tnull, SHRT_MIN); col[jj].null.shortnull = (short) tnull; } else { col[jj].null.shortnull = SHRT_MIN; /* use minimum as null */ } break; case TUSHORT: cols[jj].array = calloc(ntodo + 1, sizeof(unsigned short)); col[jj].nullsize = sizeof(unsigned short); /* bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tnull = minvalue(tnull, (long) USHRT_MAX); tnull = maxvalue(tnull, 0); /* don't allow negative value */ col[jj].null.ushortnull = (unsigned short) tnull; } else { col[jj].null.ushortnull = USHRT_MAX; /* use maximum null */ } break; case TINT: cols[jj].array = calloc(sizeof(int), ntodo + 1); col[jj].nullsize = sizeof(int); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tnull = minvalue(tnull, INT_MAX); tnull = maxvalue(tnull, INT_MIN); col[jj].null.intnull = (int) tnull; } else { col[jj].null.intnull = INT_MIN; /* use minimum as null */ } break; case TUINT: cols[jj].array = calloc(ntodo + 1, sizeof(unsigned int)); col[jj].nullsize = sizeof(unsigned int); /* bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { tnull = minvalue(tnull, INT32_MAX); tnull = maxvalue(tnull, 0); col[jj].null.uintnull = (unsigned int) tnull; } else { col[jj].null.uintnull = UINT_MAX; /* use maximum as null */ } break; case TLONG: cols[jj].array = calloc(ntodo + 1, sizeof(long)); col[jj].nullsize = sizeof(long); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { col[jj].null.longnull = tnull; } else { col[jj].null.longnull = LONG_MIN; /* use minimum as null */ } break; case TULONG: cols[jj].array = calloc(ntodo + 1, sizeof(unsigned long)); col[jj].nullsize = sizeof(unsigned long); /* bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { if (tnull < 0) /* can't use a negative null value */ col[jj].null.ulongnull = LONG_MAX; else col[jj].null.ulongnull = (unsigned long) tnull; } else { col[jj].null.ulongnull = LONG_MAX; /* use maximum as null */ } break; case TFLOAT: cols[jj].array = calloc(ntodo + 1, sizeof(float)); col[jj].nullsize = sizeof(float); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { col[jj].null.floatnull = (float) tnull; } else { col[jj].null.floatnull = FLOATNULLVALUE; /* special value */ } break; case TCOMPLEX: cols[jj].array = calloc((ntodo * 2) + 1, sizeof(float)); col[jj].nullsize = sizeof(float); /* number of bytes per value */ col[jj].null.floatnull = FLOATNULLVALUE; /* special value */ break; case TDOUBLE: cols[jj].array = calloc(ntodo + 1, sizeof(double)); col[jj].nullsize = sizeof(double); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TINT || abs(typecode) == TLONGLONG) { col[jj].null.doublenull = (double) tnull; } else { col[jj].null.doublenull = DOUBLENULLVALUE; /* special value */ } break; case TDBLCOMPLEX: cols[jj].array = calloc((ntodo * 2) + 1, sizeof(double)); col[jj].nullsize = sizeof(double); /* number of bytes per value */ col[jj].null.doublenull = DOUBLENULLVALUE; /* special value */ break; case TSTRING: /* allocate array of pointers to all the strings */ if( hdutype==ASCII_TBL ) rept = width; stringptr = calloc((ntodo + 1) , sizeof(stringptr)); cols[jj].array = stringptr; col[jj].nullsize = rept + 1; /* number of bytes per value */ if (stringptr) { /* allocate string to store the null string value */ col[jj].null.stringnull = calloc(rept + 1, sizeof(char) ); if (rept > 0) col[jj].null.stringnull[1] = 1; /* to make sure string != 0 */ /* allocate big block for the array of table column strings */ stringptr[0] = calloc((ntodo + 1) * (rept + 1), sizeof(char) ); if (stringptr[0]) { for (ii = 1; ii <= ntodo; ii++) { /* pointer to each string */ stringptr[ii] = stringptr[ii - 1] + (rept + 1); } /* get the TNULL keyword value, if it exists */ tstatus = 0; ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus); ffgkys(cols[jj].fptr, keyname, nullstr, 0, &tstatus); if (!tstatus) strncat(col[jj].null.stringnull, nullstr, rept); } else { ffpmsg("ffiter failed to allocate memory arrays"); *status = MEMORY_ALLOCATION; /* memory allocation failed */ goto cleanup; } } break; case TLOGICAL: cols[jj].array = calloc(ntodo + 1, sizeof(char)); col[jj].nullsize = sizeof(char); /* number of bytes per value */ /* use value = 2 to flag null values in logical columns */ col[jj].null.charnull = 2; break; case TLONGLONG: cols[jj].array = calloc(ntodo + 1, sizeof(LONGLONG)); col[jj].nullsize = sizeof(LONGLONG); /* number of bytes per value */ if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG || abs(typecode) == TLONGLONG || abs(typecode) == TINT) { col[jj].null.longlongnull = tnull; } else { col[jj].null.longlongnull = LONGLONG_MIN; /* use minimum as null */ } break; default: snprintf(message,FLEN_ERRMSG, "Column %d datatype currently not supported: %d: (ffiter)", jj + 1, cols[jj].datatype); ffpmsg(message); *status = BAD_DATATYPE; goto cleanup; } /* end of switch block */ /* check that all the arrays were allocated successfully */ if (!cols[jj].array) { ffpmsg("ffiter failed to allocate memory arrays"); *status = MEMORY_ALLOCATION; /* memory allocation failed */ goto cleanup; } } /*--------------------------------------------------*/ /* main loop while there are values left to process */ /*--------------------------------------------------*/ nleft = totaln; while (nleft) { ntodo = minvalue(nleft, n_optimum); /* no. of values for this loop */ /* read input columns from FITS file(s) */ for (jj = 0; jj < n_cols; jj++) { if (cols[jj].iotype != OutputCol && cols[jj].iotype != TemporaryCol) { if (cols[jj].datatype == TSTRING) { stringptr = cols[jj].array; dataptr = stringptr + 1; defaultnull = col[jj].null.stringnull; /* ptr to the null value */ } else { dataptr = (char *) cols[jj].array + col[jj].nullsize; defaultnull = &col[jj].null.charnull; /* ptr to the null value */ } if (hdutype == IMAGE_HDU) { if (ffgpv(cols[jj].fptr, cols[jj].datatype, felement, cols[jj].repeat * ntodo, defaultnull, dataptr, &anynul, status) > 0) { break; } } else { if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0) goto cleanup; if (typecode<0) { /* get size of the variable length vector */ ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status); } if (ffgcv(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow, felement, cols[jj].repeat * ntodo, defaultnull, dataptr, &anynul, status) > 0) { break; } } /* copy the appropriate null value into first array element */ if (anynul) /* are there any nulls in the data? */ { if (cols[jj].datatype == TSTRING) { stringptr = cols[jj].array; memcpy(*stringptr, col[jj].null.stringnull, col[jj].nullsize); } else { memcpy(cols[jj].array, defaultnull, col[jj].nullsize); } } else /* no null values so copy zero into first element */ { if (cols[jj].datatype == TSTRING) { stringptr = cols[jj].array; memset(*stringptr, 0, col[jj].nullsize); } else { memset(cols[jj].array, 0, col[jj].nullsize); } } } } if (*status > 0) break; /* looks like an error occurred; quit immediately */ /* call work function */ if (hdutype == IMAGE_HDU) *status = work_fn(totaln, offset, felement, ntodo, n_cols, cols, userPointer); else *status = work_fn(totaln, offset, frow, ntodo, n_cols, cols, userPointer); if (*status > 0 || *status < -1 ) break; /* looks like an error occurred; quit immediately */ /* write output columns before quiting if status = -1 */ tstatus = 0; for (jj = 0; jj < n_cols; jj++) { if (cols[jj].iotype != InputCol && cols[jj].iotype != TemporaryCol) { if (cols[jj].datatype == TSTRING) { stringptr = cols[jj].array; dataptr = stringptr + 1; nullptr = *stringptr; nbytes = 2; } else { dataptr = (char *) cols[jj].array + col[jj].nullsize; nullptr = (char *) cols[jj].array; nbytes = col[jj].nullsize; } if (memcmp(nullptr, &zeros, nbytes) ) { /* null value flag not zero; must check for and write nulls */ if (hdutype == IMAGE_HDU) { if (ffppn(cols[jj].fptr, cols[jj].datatype, felement, cols[jj].repeat * ntodo, dataptr, nullptr, &tstatus) > 0) break; } else { if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0) goto cleanup; if (typecode<0) /* variable length array colum */ { ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status); } if (ffpcn(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow, felement, cols[jj].repeat * ntodo, dataptr, nullptr, &tstatus) > 0) break; } } else { /* no null values; just write the array */ if (hdutype == IMAGE_HDU) { if (ffppr(cols[jj].fptr, cols[jj].datatype, felement, cols[jj].repeat * ntodo, dataptr, &tstatus) > 0) break; } else { if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0) goto cleanup; if (typecode<0) /* variable length array column */ { ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status); } if (ffpcl(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow, felement, cols[jj].repeat * ntodo, dataptr, &tstatus) > 0) break; } } } } if (*status == 0) *status = tstatus; /* propagate any error status from the writes */ if (*status) break; /* exit on any error */ nleft -= ntodo; if (hdutype == IMAGE_HDU) felement += ntodo; else frow += ntodo; } cleanup: /*----------------------------------*/ /* free work arrays for the columns */ /*----------------------------------*/ for (jj = 0; jj < n_cols; jj++) { if (cols[jj].datatype == TSTRING) { if (cols[jj].array) { stringptr = cols[jj].array; free(*stringptr); /* free the block of strings */ free(col[jj].null.stringnull); /* free the null string */ } } if (cols[jj].array) free(cols[jj].array); /* memory for the array of values from the col */ } free(col); /* the structure containing the null values */ return(*status); } cfitsio-4.3.1/README.win0000644000225700000360000002040614075614240014126 0ustar cagordonlheaInstructions on building and using CFITSIO on Windows platforms for C programmers using Microsoft Visual Studio or Borland C++. These instructions for building the CFITSIO library under Windows use the CMake build system that is available from http://www.cmake.org. =============================================================================== 1. Build the CFITSIO dll library a. If CMAKE is not already installed on your machine, download it from http://www.cmake.org. It is recommended that you choose the "Add CMake to the system PATH for current user" option during the installation setup process for convenience when running CMake later on. b. Install ZLIB: The compression library "zlib" is required in order to build CFITSIO. Visit their site at https://zlib.net to download the latest distribution. Unpack it, then build and install it from a parallel directory, for example: mkdir zlib.build cd zlib.build cmake ..\zlib-1.2.11 -DCMAKE_INSTALL_PREFIX=c:\Users\myname\zlib cmake --build . --config Release cmake --install . The cmake comands below will use the path "c:\Users\myname\zlib" as an example for the installed zlib location. c. Unzip the CFITSIO .zip file (e.g. cfit-4.0.0.zip) that was obtained from the CFITSIO Web site (http://heasarc.gsfc.nasa.gov/fitsio). This will create a new \cfitsio-4.0.0 subdirectory that contains the source code and documentation files. It also contains a CMakeLists.txt file that will be used during the CMake build process. d. Open the Visual Studio Command Prompt window, likely using a desktop icon with this same name, (or the equivalent Borland command window) and cd (change directory) into the parent directory that is one level above the directory containing the CFITSIO source files that was created in the previous step. e. Create a new subdirectory (for example, "cfitsio.build"), and cd into it with the following commands: mkdir cfitsio.build cd cfitsio.build When using Visual Studio, all the files that are generated during the CMake process will be created in or under this subdirectory. f. Create the CMake files necessary for the build: To use the default Visual Studio compilers and architecture, simply run (for example): cmake ..\cfitsio-4.0.0 -DCMAKE_PREFIX_PATH=c:\Users\myname\zlib Alternatively, you can specify the name of a CMake Generator using the "-G" flag: cmake -G "" ..\cfitsio-4.0.0 -DCMAKE_PREFIX_PATH=c:\Users\myname\zlib Where the string "" designates your choice of compiler. Some possible options are: "Visual Studio 16 2019" "Visual Studio 16 2019" -A Win32 (for 32-bit builds) "Visual Studio 15 2017 Win64" "Visual Studio 15 2017" (for 32-bit builds) "Visual Studio 15 2017" -A Win32 (for 32-bit builds) "MinGW Makefiles" "Borland Makefiles" "NMake Makefiles" You can see a list of all the available CMake Generators by executing the command cmake /? Note that these names are case-sensitive and must be entered exactly as displayed. Note that the "..\cfitsio-4.0.0" argument gives the relative path to the directory that contains the CFITSIO source files and the CMakeLists.txt file. Some other optional flags are available to use during this step, using this format: cmake -G ..\cfitsio-4.0.0 -D

] [-O ] [-Z] -v \n");
        fp_msg ("more:   [-F] [-D] [-S] [-L] [-C] [-H] [-V] \n");
	return(0);
}

int fu_hint (void)
{
	fp_msg ("      `funpack -H' for help\n");
	return(0);
}

int fu_help (void)
{
fp_msg ("funpack, decompress fpacked files.  Version ");
fp_version ();
fu_usage ();
fp_msg ("\n");

fp_msg ("Flags must be separate and appear before filenames:\n");
fp_msg (" -E  Unpack only the list of HDU names or numbers in the file.\n");
fp_msg (" -P 
    Prepend 
 to create new output filenames.\n");
fp_msg (" -O    Specify full output file name.\n");
fp_msg (" -Z          Recompress the output file with host GZIP program.\n");
fp_msg (" -F          Overwrite input file by output file with same name.\n");
fp_msg (" -D          Delete input file after writing output.\n");
fp_msg (" -S          Output uncompressed file to STDOUT file stream.\n");
fp_msg (" -L          List contents, files unchanged.\n");

fp_msg (" -C          Don't update FITS checksum keywords.\n");

fp_msg (" -v          Verbose mode; list each file as it is processed.\n");
fp_msg (" -H          Show this message.\n");
fp_msg (" -V          Show version number.\n");

fp_msg (" \n       FITS files to unpack; enter '-' (a hyphen) to read from stdin.\n");
fp_msg (" Refer to the fpack User's Guide for more extensive help.\n");
	return(0);
}
cfitsio-4.3.1/swapproc.c0000644000225700000360000001702713472024437014464 0ustar  cagordonlhea/*  This file, swapproc.c, contains general utility routines that are      */
/*  used by other FITSIO routines to swap bytes.                           */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

/* The fast SSE2 and SSSE3 functions were provided by Julian Taylor, ESO */

#include 
#include 
#include "fitsio2.h"

/* bswap builtin is available since GCC 4.3 */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
#define HAVE_BSWAP
#endif

#ifdef __SSSE3__
#include 
/* swap 16 bytes according to mask, values must be 16 byte aligned */
static inline void swap_ssse3(char * values, __m128i mask)
{
    __m128i v = _mm_load_si128((__m128i *)values);
    __m128i s = _mm_shuffle_epi8(v, mask);
    _mm_store_si128((__m128i*)values, s);
}
#endif
#ifdef __SSE2__
#include 
/* swap 8 shorts, values must be 16 byte aligned
 * faster than ssse3 variant for shorts */
static inline void swap2_sse2(char * values)
{
    __m128i r1 = _mm_load_si128((__m128i *)values);
    __m128i r2 = r1;
    r1 = _mm_srli_epi16(r1, 8);
    r2 = _mm_slli_epi16(r2, 8);
    r1 = _mm_or_si128(r1, r2);
    _mm_store_si128((__m128i*)values, r1);
}
/* the three shuffles required for 4 and 8 byte variants make
 * SSE2 slower than bswap */


/* get number of elements to peel to reach alignment */
static inline size_t get_peel(void * addr, size_t esize, size_t nvals,
                              size_t alignment)
{
    const size_t offset = (size_t)addr % alignment;
    size_t peel = offset ? (alignment - offset) / esize : 0;
    peel = nvals < peel ? nvals : peel;
    return peel;
}
#endif

/*--------------------------------------------------------------------------*/
static void ffswap2_slow(short *svalues, long nvals)
{
    register long ii;
    unsigned short * usvalues;

    usvalues = (unsigned short *) svalues;

    for (ii = 0; ii < nvals; ii++)
    {
        usvalues[ii] = (usvalues[ii]>>8) | (usvalues[ii]<<8);
    }
}
/*--------------------------------------------------------------------------*/
#if __SSE2__
void ffswap2(short *svalues,  /* IO - pointer to shorts to be swapped    */
             long nvals)     /* I  - number of shorts to be swapped     */
/*
  swap the bytes in the input short integers: ( 0 1 -> 1 0 )
*/
{
    if ((long)svalues % 2 != 0) { /* should not happen */
        ffswap2_slow(svalues, nvals);
        return;
    }

    long ii;
    size_t peel = get_peel((void*)&svalues[0], sizeof(svalues[0]), nvals, 16);

    ffswap2_slow(svalues, peel);
    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 8); ii+=8) {
        swap2_sse2((char*)&svalues[ii]);
    }
    ffswap2_slow(&svalues[ii], nvals - ii);
}
#else
void ffswap2(short *svalues,  /* IO - pointer to shorts to be swapped    */
             long nvals)     /* I  - number of shorts to be swapped     */
/*
  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
*/
{
    ffswap2_slow(svalues, nvals);
}
#endif
/*--------------------------------------------------------------------------*/
static void ffswap4_slow(INT32BIT *ivalues, long nvals)
{
    register long ii;

#if defined(HAVE_BSWAP)
    for (ii = 0; ii < nvals; ii++)
    {
        ivalues[ii] = __builtin_bswap32(ivalues[ii]);
    }
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
    /* intrinsic byte swapping function in Microsoft Visual C++ 8.0 and later */
    unsigned int* uivalues = (unsigned int *) ivalues;

    /* intrinsic byte swapping function in Microsoft Visual C++ */
    for (ii = 0; ii < nvals; ii++)
    {
        uivalues[ii] = _byteswap_ulong(uivalues[ii]);
    }
#else
    char *cvalues, tmp;

    for (ii = 0; ii < nvals; ii++)
    {
        cvalues = (char *)&ivalues[ii];
        tmp = cvalues[0];
        cvalues[0] = cvalues[3];
        cvalues[3] = tmp;
        tmp = cvalues[1];
        cvalues[1] = cvalues[2];
        cvalues[2] = tmp;
    }
#endif
}
/*--------------------------------------------------------------------------*/
#ifdef __SSSE3__
void ffswap4(INT32BIT *ivalues,  /* IO - pointer to INT*4 to be swapped    */
                 long nvals)     /* I  - number of floats to be swapped     */
/*
  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
*/
{
    if ((long)ivalues % 4 != 0) { /* should not happen */
        ffswap4_slow(ivalues, nvals);
        return;
    }

    long ii;
    const __m128i cmask4 = _mm_set_epi8(12, 13, 14, 15,
                                        8, 9, 10, 11,
                                        4, 5, 6, 7,
                                        0, 1, 2 ,3);
    size_t peel = get_peel((void*)&ivalues[0], sizeof(ivalues[0]), nvals, 16);
    ffswap4_slow(ivalues, peel);
    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 4); ii+=4) {
        swap_ssse3((char*)&ivalues[ii], cmask4);
    }
    ffswap4_slow(&ivalues[ii], nvals - ii);
}
#else
void ffswap4(INT32BIT *ivalues,  /* IO - pointer to INT*4 to be swapped    */
                 long nvals)     /* I  - number of floats to be swapped     */
/*
  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
*/
{
    ffswap4_slow(ivalues, nvals);
}
#endif
/*--------------------------------------------------------------------------*/
static void ffswap8_slow(double *dvalues, long nvals)
{
    register long ii;
#ifdef HAVE_BSWAP
    LONGLONG * llvalues = (LONGLONG*)dvalues;

    for (ii = 0; ii < nvals; ii++) {
        llvalues[ii] = __builtin_bswap64(llvalues[ii]);
    }
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
    /* intrinsic byte swapping function in Microsoft Visual C++ 8.0 and later */
    unsigned __int64 * llvalues = (unsigned __int64 *) dvalues;

    for (ii = 0; ii < nvals; ii++)
    {
        llvalues[ii] = _byteswap_uint64(llvalues[ii]);
    }
#else
    register char *cvalues;
    register char temp;

    cvalues = (char *) dvalues;      /* copy the pointer value */

    for (ii = 0; ii < nvals*8; ii += 8)
    {
        temp = cvalues[ii];
        cvalues[ii] = cvalues[ii+7];
        cvalues[ii+7] = temp;

        temp = cvalues[ii+1];
        cvalues[ii+1] = cvalues[ii+6];
        cvalues[ii+6] = temp;

        temp = cvalues[ii+2];
        cvalues[ii+2] = cvalues[ii+5];
        cvalues[ii+5] = temp;

        temp = cvalues[ii+3];
        cvalues[ii+3] = cvalues[ii+4];
        cvalues[ii+4] = temp;
    }
#endif
}
/*--------------------------------------------------------------------------*/
#ifdef __SSSE3__
void ffswap8(double *dvalues,  /* IO - pointer to doubles to be swapped     */
             long nvals)       /* I  - number of doubles to be swapped      */
/*
  swap the bytes in the input doubles: ( 01234567  -> 76543210 )
*/
{
    if ((long)dvalues % 8 != 0) { /* should not happen on amd64 */
        ffswap8_slow(dvalues, nvals);
        return;
    }

    long ii;
    const __m128i cmask8 = _mm_set_epi8(8, 9, 10, 11, 12, 13, 14, 15,
                                        0, 1, 2 ,3, 4, 5, 6, 7);
    size_t peel = get_peel((void*)&dvalues[0], sizeof(dvalues[0]), nvals, 16);
    ffswap8_slow(dvalues, peel);
    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 2); ii+=2) {
        swap_ssse3((char*)&dvalues[ii], cmask8);
    }
    ffswap8_slow(&dvalues[ii], nvals - ii);
}
#else
void ffswap8(double *dvalues,  /* IO - pointer to doubles to be swapped     */
             long nvals)       /* I  - number of doubles to be swapped      */
/*
  swap the bytes in the input doubles: ( 01234567  -> 76543210 )
*/
{
    ffswap8_slow(dvalues, nvals);
}
#endif
cfitsio-4.3.1/iter_c.fit0000644000225700000360000026400013472024437014426 0ustar  cagordonlheaSIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT   Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT   Contact the NASA Science Office of Standards and Technology for the   COMMENT   FITS Definition document #100 and other FITS information.             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'  /  FITS 3D BINARY TABLE                                   BITPIX  =                    8  /  Binary data                                  NAXIS   =                    2  /  Table is a matrix                            NAXIS1  =                   16 /  Width of table in bytes                       NAXIS2  =                 5000 /  Number of entries in table                    PCOUNT  =                    0  /  Random parameter count                       GCOUNT  =                    1  /  Group count                                  TFIELDS =                    5 /  Number of fields in each row                  EXTNAME = 'EVENTS  '  /  Table name                                             EXTVER  =                    1  /  Version number of table                      TFORM1  = '1I      '  /  Data type for field                                    TTYPE1  = 'X       '  /  Label for field                                        TUNIT1  = '        '  /  Physical units for field                               TFORM2  = '1I      '  /  Data type for field                                    TTYPE2  = 'Y       '  /  Label for field                                        TUNIT2  = '        '  /  Physical units for field                               TFORM3  = '1I      '  /  Data type for field                                    TTYPE3  = 'PHA     '  /  Label for field                                        TUNIT3  = '        '  /  Physical units for field                               TFORM4  = '1D      '  /  Data type for field                                    TTYPE4  = 'TIME    '  /  Label for field                                        TUNIT4  = '        '  /  Physical units for field                               TFORM5  = '1I      '  /  Data type for field                                    TTYPE5  = 'DY      '  /  Label for field                                        TUNIT5  = '        '  /  Physical units for field                               TLMIN1  =                    1                                                  TLMAX1  =                15360                                                  TLMIN2  =                    1                                                  TLMAX2  =                15360                                                  NAXLEN  =                    2  /  Number of QPOE axes                          AXLEN1  =                15360  /  Dim. of qpoe axis 1                          AXLEN2  =                15360  /  Dim. of qpoe axis 2                          TELESCOP= 'ROSAT   '  /  telescope (mission) name                               INSTRUME= 'PSPC    '  /  instrument (detector) name                             RADECSYS= 'FK5     '  /  WCS for this file (e.g. Fk4)                           EQUINOX =           2.000000E3  /  equinox (epoch) for WCS                      CTYPE1  = 'RA---TAN'  /  axis type for dim. 1 (e.g. RA---TAN)                   CTYPE2  = 'DEC--TAN'  /  axis type for dim. 2 (e.g. DEC--TAN)                   CRVAL1  =           8.588000E1  /  sky coord of 1st axis (deg.)                 CRVAL2  =           6.926986E1  /  sky coord of 2nd axis (deg.)                 CDELT1  =         -1.388889E-4  /  x degrees per pixel                          CDELT2  =          1.388889E-4  /  y degrees per pixel                          CRPIX1  =           7.680000E3  /  x pixel of tangent plane direction           CRPIX2  =           7.680000E3  /  y pixel of tangent plane direction           CROTA2  =           0.000000E0  /  rotation angle (degrees)                     MJD-OBS =           4.905444E4  /  MJD of start of obs.                         DATE-OBS= '08/03/93'  /  date of observation start                              TIME-OBS= '10:30:32'  /  time of observation start                              DATE-END= '11/03/93'  /  date of observation end                                TIME-END= '05:02:18'  /  time of observation end                                XS-OBSID= 'US800282P.N1    '  /  observation ID                                 XS-SEQPI= 'ROTS, DR., ARNOLD,H.                                           '  /  XS-SUBIN=                    2  /  subinstrument id                             XS-OBSV =               800282  /  observer id                                  XS-CNTRY= 'USA     '  /  country where data was processed                       XS-FILTR=                    0  /  filter id: 0=none, 1=PSPC boron              XS-MODE =                    1  /  pointing mode: 1=point,2=slew,3=scan         XS-DANG =           0.000000E0  /  detector roll angle (degrees)                XS-MJDRD=                48043  /  integer portion of mjd for SC clock start    XS-MJDRF= 8.797453703700740E-1  /  fractional portion of mjd for SC clock start XS-EVREF=                    0  /  day offset from mjdrday to evenr start times XS-TBASE=  0.000000000000000E0  /  seconds from s/c clock start to obs start    XS-ONTI =  1.476600000000000E4  /  on time (seconds)                            XS-LIVTI=  1.476600000000000E4  /  live time (seconds)                          XS-DTCOR=           1.000000E0  /  dead time correction                         XS-BKDEN=           0.000000E0  /  bkgd density cts/arcmin**2                   XS-MINLT=           0.000000E0  /  min live time factor                         XS-MAXLT=           0.000000E0  /  max live time factor                         XS-XAOPT=           0.000000E0  /  avg. opt. axis x in degrees from tangent planXS-YAOPT=           0.000000E0  /  avg. opt. axis y in degrees from tangent planXS-XAOFF=           0.000000E0  /  avg x aspect offset (degrees)                XS-YAOFF=           0.000000E0  /  avg y aspect offset (degrees)                XS-RAROT=           0.000000E0  /  avg aspect rotation (degrees)                XS-XARMS=           0.000000E0  /  avg x aspect RMS (arcsec)                    XS-YARMS=           0.000000E0  /  avg y aspect RMS (arcsec)                    XS-RARMS=           0.000000E0  /  avg aspect rotation RMS (degrees)            XS-RAPT =           8.588000E1  /  nominal right ascension (degrees)            XS-DECPT=           6.926986E1  /  nominal declination (degrees)                XS-XPT  =                 4096  /  target pointing direction (pixels)           XS-YPT  =                 4096  /  target pointing direction (pixels)           XS-XDET =                 8192  /  x dimen. of detector                         XS-YDET =                 8192  /  y dimen. of detector                         XS-FOV  =                    0  /  field of view (degrees)                      XS-INPXX=          2.595021E-4  /  original degrees per pixel                   XS-INPXY=          2.595021E-4  /  original degrees per pixel                   XS-XDOPT=           4.119000E3  /  detector opt. axis x in detector pixels      XS-YDOPT=           3.929000E3  /  detector opt. axis y in detector pixels      XS-CHANS=                  256  /  pha channels                                 TDISP4  = 'I12     '                                                            HISTORY   modified by pence on Thu Apr 24 15:04:08 EDT 1997                     HISTORY   modified by pence on Thu Apr 24 15:07:24 EDT 1997                     TDISP5  = 'I4      '                                                            HISTORY   modified by pence on Thu Apr 24 16:06:08 EDT 1997                     HISTORY   File modified by user 'pence' with fv  on 97-11-25T14:34:58           HISTORY   File modified by user 'pence' with fv  on 98-01-12T14:03:09           HISTORY   File modified by user 'pence' with fv  on 98-02-06T15:18:24           END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             óµA”ÑU=àq1±&ØA”ÑUAÀ	=#t6A”ÑVo€ö(²RA”ÑX/@¸)P#½FA”ÑX‰@Y[	ƒA”ÑXÕÀê
,~A”ÑY” @ SÁ?A”ÑZ¢ W^A”ÑZÄ€Ó},ŸaA”ÑZï@¨LzA”Ñ[":$÷A”Ñ^àNr€A”Ñ_MÀuëA”Ñ_†@˜'êìnA”Ñ`g@
÷ 	NA”Ñ`§àç$þA”Ñaƒ@ª°*Ÿ	A”Ña¡¢+91í2A”Ña¦À©%	¢A”Ñb tB( A”ÑbD@	Ñ*vhA”ÑbÐ I X,4A”ÑbÛ@O¤®A”Ñc7e$¬.+A”Ñc] 3	OA”ÑdW2+ý©
A”Ñd†€¹*2ÊIA”Ñd¦ C	é )A”Ñd×`ö[#A”Ñf$à™&•^A”Ñf® M
ƒA”ÑgoÀÙ“ÑxA”ÑgÀ å!%ÚA”ÑjS-`hA”ÑkàÄ\×
A”Ñk|À"0ç$SA”Ñl€@
Œ?-aTA”Ñl×@à f)ü
A”Ñm~às1\#âA”Ñm¨`
Á äA”Ñmà`-V%ÍA”Ñnü œ
½¿A”Ñq×`¶5í	A”Ñr{€©Ê“-A”ÑrÆàæ#*)ë
A”ÑrÛ Ps	€A”Ñsg€›'Ú 
A”ÑtìÅyA”Ñu@ PwXA”Ñv`à#cA”Ñyã@3+ËKA”Ñ{/ §!” \/A”Ñ{Q@
u,D
bA”Ñ{`÷
Ä:
A”Ñ{ó@g"Ç'*%A”Ñ|À	ÄM*¨SA”Ñ} 	'2^Q
A”Ñ}s f ›“A”Ñ~0`×"0YA”Ñ~ØÀêŠ
eA”ÑÀë%ÄDIA”Ñ`!v3A”Ñ}ÀT"»-A”Ñ­€½î*¼	A”Ñ€þ X,AN
A”Ñ„¿`ƒ($_A”Ñ„Éà
î¬éOA”Ñ„Ü`ëi:A”Ñ…Ï v*¦-DA”ц´€
 ç0A”цï Ûy	A”чÀš§	A”чL ƒ$¨)oA”ч™À)¢-bA”чæ@
ÝA”шâà(
Z(A”Ñ‹&@+ A”ÑŒý 	¬#±kA”Ñ/91Ö
A”ÑŽh ‚¥¹4A”ÑŽo 'ASA”Ñ޾,/B%vA”Ñ–à	íÙ3œA”Ñji!?åA”Ѥ€ë{+×A”ÑÀf."D:A”Ñê ¼l3A”Ñõ€üP'×	A”Ñ‘®`
Ð1°
A”Ñ’k DÝzA”Ñ”&…=A”Ñ•‹ vy# 
A”Ñ–@
Q3&A”Ñ–ˆÀ	h'À3&0A”Ñ–À
á(A”Ñ™àA/ÑÄA”Ñš€¡ï! ~A”Ñš: 
Öˆ‹A”Ñš¬@èSA”Ñ›& ˜	V2A”Ñžy *Ì&8A”ÑŸ‘@ØÍZA”Ñ v`#
YÁ¡A”Ñ£L€”S×A”Ñ£a@çA”Ѥ€Í1,PA”Ѥn ’/3xwA”ѤÉÍ7 PA”ѥ꠿*E	A”Ѧ« <3ŠëA”ѧ ¸ÊpA”ѧ=`?&ÒA”ѧÝ@zÊ–A”Ѩ\€h0¢¥A”ѨŒ 
õ“#ë?A”Ѩɠ
(U+DA”Ñ©b*:BA”Ñ©Ýà¢$$A”Ñ©à-3DÙA”ѪLÔ*[3'
A”Ѫ¡Ú³}zA”ÑÃl`
$s
ØA”Ñŵà—Ÿ.Å^A”ÑÅØà
§$_'A”ÑÈç mF1A”ÑÊ’€žÿ+ŠA”ÑË`O&¿A”ÑËÖ s
ã7A”ÑËýà×"™A”ÑÍJ@/ P4ˆEA”ÑÍ»`ì
¸
A”ÑÎÀàË+à
A”ÑÎá`×þ'È
A”ÑÏú€
Û/Ù
A”ÑЛÀÐÍA”ÑÑh ð#
A”ÑÒàß+Ì"SEA”ÑÒ ©©A”ÑÒ« ø/Ž 35A”ÑÒÂÀ•	¾)7ÛA”ÑÓïà	áÐ4¦A”ÑÔ4 ®ln	A”ÑÔ:@2%åõ
A”ÑÔZ 
?aÄFA”ÑÔi€”.]´FA”ÑÕ*€

 JA”ÑÕn`äÚ-§
A”ÑÖ`æ+ŠXA”ÑÖU`¥v A”ÑÖìW ŠA”Ñ×,à4`!A”Ñ©@"ÝdA”Ñ« C(ØjA”ѰÀ%,·&¨A”Ñæ€	>¤%L
Aӄo@
¿¥AA”ÑÀ"!!®#A”Ѳ
3$À
A”Ñý`H/™&XA”Ñ 	h(-3ŠA”Ñ- ¢-øA”Ñ[À“,˜A”Ñc`+%$A”ÑúÀÇ4ïSA”Ñ-zâ3â
A”ÑË 0(Õ%A”ÑÛÀ
J	]{A”Ñ €y!7ÂA”Ñ‘ \'È
A”ÑÌ`	}&ø&|A”Ñù 	¥&,Ô	A”Ñ	ë`eç9A”Ñ
—`d%x.A”Ñà"±*WA”Ñp€Õˆ}A”Ñ5`õâ(ÛA”ÑO€È+ÌŠ9A”ÑXÀ|"rAA”Ñy€Å\'«„A”Ñ7@	ÿÁ%
Aӄ
€^
™
8A”Ñe ‚)0ñA”Ѽ ÷31«A”ѯWA”Ñ‚ 
ó"
ØA”Ѱ€¤
RÕA”Ñ€<°s-A”ÑÃ`A °cA”Ñ`L2‹ªA”Ñ@
,º'B@A”Ñ?à,	ðA”ÑÄ`uþ(-A”Ñ×@
…;A”ÑûIãwA”ÑC !% A”Ñmq%§,d+A”Ñq –÷
A”Ñè ,1{—
A”ÑÕ`xv-tA”Ñk@k'£*ÒA”Ñ4`Pc-sA”Ñ ò m!IŸSA”Ñ!¼àh!ü`
A”Ñ!í`÷CÖA”Ñ!òÂ$ÖÔA”Ñ"Š¢%,
+A”Ñ#PÀkó;1A”Ñ$.€æ"¼6A”Ñ$•àl!H
A”Ñ&- g%àA”Ñ'ý@
‡4`PA”Ñ(Z@Ú_¨A”Ñ(È )-(”%A”Ñ)P€	¶	…A”Ñ)w,)œ¶A”Ñ)ì`
ª>ŒA”Ñ*A ©±¦A”Ñ,*@f€°
A”Ñ-I#ê{]A”Ñ-í@_t÷
A”Ñ.Ö yçn;A”Ñ/O Šb6œ	A”Ñ/‹ ….'A”Ñ/öü4²vA”Ñ4S`†·/A”Ñ5€ú%;A”Ñ5à
Ôû¾4A”Ñ5./«ëA”Ñ5¹ ¤%{­A”Ñ6ˆ`¹!A”Ñ6ï`
R×3ÏA”Ñ7_ÿ0r
A”Ñ7µàûr!mA”Ñ8@
Ü>iA”Ñ9ƒ`Û/ŒÞWA”Ñ:f W·fA”Ñ;" y Ç"A”Ñ;:€ñé
‹
A”Ñ;S ³.b!Ð"A”Ñ;c`Æþ )eA”Ñ>@
ç)î"t{A”Ñ>à°íÑ-A”Ñ?=`ù	N&D5A”Ñ?g xb§0A”Ñ?å @Eï	A”Ñ?ùÀ¿Ü PA”Ñ@'à‰Ç$üTA”Ñ@V Ù.þVOA”Ñ@à Ë¢•
A”Ñ@ú`ˆ×ÓA”ÑAW`s!È·A”ÑBÖ e,£s*A”ÑCX wæ1Ù
A”ÑCi€ñ$ùZ$A”ÑC— D
_(UA”ÑDî€
QJëA”ÑE& —wA”ÑFÙ(%Ü'A”ÑF÷ b
1)Õ2A”ÑG
à	^
^nA”ÑG;à¹-+§A”ÑHÀ¢ÎÎA”ÑJ€àóþ–GA”ÑJ› ®#$ÑA”ÑJ±@h1"%œ
A”ÑJú@	¡0"sA”ÑMo 
€3à›A”ÑNq ÏÜA”ÑOø’/ñjA”ÑPc D#;(e
A”ÑQ@ïâ-¡A”ÑQ¨à\4d
A”ÑQþ |eA”ÑR)`G
èA”ÑR- “8,dA”ÑR3$x­3A”ÑTÉàŽ&¸&A”ÑV‚ 
*È
BAA”ÑWdÀù£× A”ÑW@óù3ëjA”ÑY8àÇ1m ¼A”ÑYóÀ?!ÃÎ
A”Ñ\÷ (4Ì	A”Ñ]Π³FPTA”Ñ^+Àû4È	A”Ñ^é@)1¹* 	A”Ñ_“`ú)*¥>A”Ñ`¾àF.ö{OA”Ñ`àëæ#¬JA”ÑaŽ*˜7A”Ñb÷*4^ƒA”Ñb,`š,ã4A”Ñb¯@W´A”Ñeà¢Z'Ý&A”Ñeà
–ªf§A”Ñe1À}!ø'jA”Ñe¸€	“
”
A”Ñeá ™1Ö+ˆA”ÑfAà'~A”ÑfI÷!w	A”ÑfrÌ“õA”Ñgˆ†(mA”Ñh@	u	-¯EA”ÑhD¡.‚©6A”ÑiÀ
	ÂØA”Ñjj€À~ÜA”Ñjí #lÁPA”Ñjô³(›"jHA”Ñk â*~JA”ÑkáÀ‚!ù1`A”Ñkè@Jð#\8A”Ñlà
\Ü1A”ÑlH@.ë%A”ÑnÜ€y/’/
A”Ño@Á%C#²A”Ño3`eA$»rA”ÑpSXöA”Ñq€0÷ænA”Ñq5À)I	’A”Ñq“@Ä2A”Ñr2Àü6:A”Ñr·à[Äâ™A”ÑtÀ’%û+VA”Ñt¡N3žA”Ñtì ©
A”Ñu’@ýG Š
A”Ñu•€í'–!ô{A”Ñvg 7A”Ñv€-!Ë7A”Ñv­ —í%tA”Ñx뀫'å4 A”Ñy“@ˆ¥1-A”Ñzl`&) ¦A”Ñz­
t#¿A”ÑzÇ Ç(Ÿ3A”ÑzàÀm"Ô*A”Ñ{>À&BA”Ñ{lÀê6‚	A”Ñ}ïÀ(„"iA”Ñ~àÿ%€_	A”Ñ~@Û)i%QA”Ñ~æ 
Yª4pA”Ñ~þ :&ûA”Ñ€‘@!:÷	A”Ñ€˜à¹Á)‹A”Ñà	ù1ý!A”ÑL?Þ3A”Ñ €™
.	A”Ñ‚BàÖA”Ñ‚Àý$Ÿ1f7A”Ñ‚á`2'“ùA”уI€UØ>A”у €$ž!A”Ñ…{À
üÁLA”Ñ…” ÛA4JLA”Ñ…ä ¾sA”цNàdK?A”ц»€Ð
ë,|LA”ш5ÀA2ú(†A”ÑŒá&.!ç,A”ÑŒîà1gA”Ñ*@¨!’6–A”ÑŽU ¢
<A”ÑŽàÈ 3A”ÑQ ¡--f
A”Ñ‹ ä&˜E
A”Ñ£àI2V(ÈA”Ѩ2±%ÛA”Ñ‘µ€	™$C5Ê
A”Ñ’ÿ ìÎìA”Ñ“D M-!WA”Ñ”‰ 
Š6~ A”Ñ”ýy¤	A”Ñ–Iì!=9A”Ñ–‹ 1¬ÓA”Ñ–½ 
ò©
m
A”Ñ™a€
+ðA”Ñ™÷ à |mA”Ñš~`
÷'¦³A”Ñšé€<HjA”Ñœo Ì 4ÓA”щ€±ÍA”Ñšà(×!© A”ÑÝ 
Ú&2"vA”Ñž¿ !)˜$ýA”Ñžå 
™-ˆA”ÑžúàTÔ
A”ÑŸC ´°A”Ñ¢Y€ÏA”Ñ¢mÀÆËA”Ñ¢™€dY.òA”Ñ£
 }]A”Ñ£
à5ÓtA”Ñ£¬@¨A”Ѥ–@ï,˜ìA”Ñ¥ A-¦&f	A”Ñ¥£à	£'œ0ž	A”Ñ¥Ë@ˆYA”ѦʀtÖ#¹A”Ѧí 
Tò!A”ѧ¢
†4!	A”ѧ½ «1ì!Y	A”Ѩ$àL#¬A”ѨC
s'y#UA”Ѩ{@Ÿ,
NA”Ñ©|`±s
Ñ
A”Ñ©àÛ´&×A”Ѫà
÷ Ä6A”Ñ«ààSR":A”Ѭ 
+#Ó3A”Ѭ¬€my·A”Ñ¬Ü )åõA”Ѭú 6v"‘%A”Ñ­ 
4"Â#2A”Ñ®€÷çüA”Ñ®tÀÁ}("ŠA”Ñ®àÀ	°A”ѱdŽbB
A”Ѳ„ <.IÃSA”ѲÜlî|A”Ñ´°À£í)A”Ñ´ú jÌn
A”ѵ6@m.™A”ѵj §
÷
A”ѵØ`BØA”ѵí`|¤hA”Ѷ#à“Úa&A”ѹ Œ‹ÁA”ѹ !÷5ÄA”ѹ£à&'–3QA”Ѻò %.xÍ
A”Ѽ‰`{(ú¢VA”ѽpà5š%˜A”ѽè`	®	“{ A”ѽö ’ª%y-A”ѾO¯)ŽbA”ѾS€0*f'
PA”ÑÀ:€	‰,6VA”ÑÃDÀÉ@(A”ÑßÀ&œA”ÑÅÓ`!2æ!r	A”ÑÆ'`-^/5A”ÑÇkÀ
''-A”ÑÈ	 
Ôs	íA”ÑÉ â_$K[A”ÑÉž“	ŽÂA”ÑÉ·`ë%5 A”ÑÉÍ`
‰B5ßA”ÑÊ3€ò“!A”ÑÊe 
¦4û-A”ÑÊàŒŒA”ÑËÀ
œ%LA”ÑϧB†MA”ÑÐ`Ø&˜õA”ÑÐ]€©k)A”ÑÑÖ€Y, A”ÑÓiÀ
9-åA”ÑÓûà1—9A”ÑÕ Î;)»A”ÑÕÜ@	‹x A”ÑÖ¸àí ÿ	A”ÑÖð`6´!A”Ñ×T :©A”Ñ×\ 7t(A”ÑØXÀȬ!´	A”ÑØ•`’é–A”ÑØï€$
1)VA”ÑÙ`
&bpA”ÑÙÿ@z0z+A”ÑÚ\à##èA”ÑÜS@«",6HŸA”ÑÜ~€ð#;.#A”ÑÜÚ 73¦m%A”ÑÝž`Tj$©A”ÑÝÊ@@) 
A”ÑÞX€
e˜ |
A”ÑÞƒà
¾ÇA”ÑÞ¨à€`4!-A”ÑÞÌ`! ûàoA”Ñ߀ëp.A”Ñß @mú#˜A”Ñái@
X"§*A”Ñ㈠¤!9!OA”Ñå9 
J-~1FA”Ñåg`ü»
D.A”Ñåà®u1jA”ÑåìÀ?)’!–'A”Ñæ€ŽÒñ
A”ÑæKà‘†Ñ	A”Ñæ™à*(ó&¦A”Ñç¶`	å™6ã%A”ÑêJ F!Ê$¿
A”Ñì€P3¤ºA”ÑíJ€åA”Ñî( Q5*2A”ÑîŽA]A”Ñ𢠌ü6A”ÑñÀ@0
‰,÷A”ÑñÏ€<4î‡A”ÑôÝ€
ž¡A”Ñôà (­%oA”Ñ÷i€u!E5ò+A”Ñ÷p`3L	Õ	A”Ñø5@Ú!A”Ñø|@
ã™-­A”Ñù`T^A”ÑùßL.[)A	A”ÑûWÀ<  *
A”Ñü§ —[ÕA”ÑüÀàÞ'Ë
Ê
A”Ñþ;àѧ!5A”ÑþýÀ
ò¯5e:A”ÑÿI`–Ä‡A”Ñ #@¬#V+uA”Ñ ­@­¼*A”Ñ Ï "ÄPA”Ñ ê Ó!	=A”Ñ è ’""VRA”Ñ 4@
S
–#¶A”Ñ 	â€
.¬þ6A”Ñ 
s€œ§îIA”Ñ Š %7|=A”Ñ Ÿ C/

A”Ñ ¼`ô.8€
A”Ñ Ú 
caA”Ñ âàÆ,.A”Ñ 
ÓàuM&¢A”Ñ 
ý &	û*8A”Ñ € 	ºç
A”Ñ  €àXA”Ñ ¬à§&¿DA”Ñ ®à | A”Ñ Là–½A”Ñ Mà[(®"5A”Ñ ÛàS õA”Ñ ® ´,¯CA”Ñ ¬ ¬
"Ï~A”Ñ ³
î3úB5A”Ñ ´`¹îÇDA”Ñ Å€¡U!¾
A”Ñ   §0é.éA”Ñ 3@s!A”Ñ `@
¢#ô&A”Ñ ÂkSè
A”Ñ è ?QÆA”Ñ ñà
‡1òA”Ñ  >0ŸŸ	A”Ñ hà˜©$[A”Ñ Æ`ܸ'(A”Ñ C5ËA”Ñ U Ç)È
[A”Ñ ¾ù,$ýA”Ñ ú!ÚA”Ñ O€¤(2¡A”Ñ !­“«A”Ñ #Àu("A”Ñ #`
”]A”Ñ %Ý`¡Ä5Ÿ	A”Ñ &ÞÀ æíA”Ñ 't€=!ýÏA”Ñ ' ¦‡A”Ñ (€	*©eAA”Ñ (:`¹(E  A”Ñ (‚`
7*«A”Ñ (§àÞ'»UA”Ñ )
+!EA”Ñ +€ 
¥ávjA”Ñ +±j#}$A”Ñ +À op6A”Ñ +Ð § ø6¾
A”Ñ ,*`Ü',@A”Ñ ,Å@Q$1ÓA”Ñ -`?'a1KA”Ñ -Y h1ò±A”Ñ .b`”AÎ~A”Ñ .`Ñ!å
=A”Ñ .Ÿ ï‰A”Ñ /# þÄ	A”Ñ /Ë*£ú'A”Ñ 0Ä ƒ%’A”Ñ 1;€MÊ‚KA”Ñ 2:@>']ÎA”Ñ 3SÀ	%&VA”Ñ 3Œ@
Ã? NA”Ñ 3”à~ª:A”Ñ 4¡@ª%Ž(uFA”Ñ 4¹ 	:—+A”Ñ 4àÀœ ÔYA”Ñ 8Àz6C6A”Ñ 8}X@&
A”Ñ :îÀ
Þ]¼AA”Ñ <á`Ç0h,oA”Ñ >? ˆö ¾A”Ñ ? r.–A”Ñ A7 ó+uGA”Ñ AÆ Z$ª&w
Aӄ BG 
_9
©PA”Ñ C€Óv@A”Ñ Cµ@åa„A”Ñ D„€¢&¿úA”Ñ E1ú™#Š>A”Ñ H* 
¹
#A”Ñ HeÀ³»øA”Ñ J{À¢ŸxA”Ñ JÔ@*%jZA”Ñ K­`§%¡-^*A”Ñ MÎ`«W4æÜA”Ñ Mã É][A”Ñ N`j­¢A”Ñ N? 5¿ãA”Ñ NX@|
Ã*£A”Ñ P`	rŒ&È`A”Ñ Q˜ .Z¨JA”Ñ R™=
R7A”Ñ S@¥\.÷A”Ñ S¯`e$?SA”Ñ TÛ Äì6W>A”Ñ TçÀÕKÎ
A”Ñ TéÀLÑA”Ñ U2 ç»_A”Ñ V¾ 2 [.{SA”Ñ Wàbó qA”Ñ X Ì£EA”Ñ X  ÷ú/TA”Ñ Y€½ A”Ñ Z
`gù,ŒA”Ñ Z—€SZ ÞA”Ñ \c€À6JA”Ñ ]`ÔH}A”Ñ ]€˜	ÕäA”Ñ _%`Ä%
A”Ñ _–@`?EA”Ñ `FÀ0)f	A”Ñ `³²Ü(A”Ñ b,@¶2¢$m*A”Ñ cŸ
¾0¢«A”Ñ da ü
Z1A”Ñ eSà?
‰!A”Ñ e» 
K°A”Ñ e ?-ž±0A”Ñ eîð$CpA”Ñ g4ÀÞ$¤ùA”Ñ gˆà
æ+ÆA”Ñ h p:­A”Ñ h¢€'/ô!¯A”Ñ iÀ]ç5¶)A”Ñ iÀ4
›öA”Ñ jJ o"j4òA”Ñ kÓ Þ!zA”Ñ kØq]KÞA”Ñ l  Ë#ƒ0NA”Ñ mÌÀH)PY
A”Ñ n€·*£¤A”Ñ pÒ`I‹-ZJA”Ñ qØ@–&I/A”Ñ r+@s!o2õ(A”Ñ rÀ,5A”Ñ uÀà
ü	‚&„.A”Ñ uß õ' 	A”Ñ v8€ÇƒuÎA”Ñ v· ‚f¶
A”Ñ vÙî“"ŠdA”Ñ w˜à
h+™e°A”Ñ w¸ù  $?A”Ñ yÍÀë¢(éA”Ñ {
€
¾3f?A”Ñ {à 
„$Õ
A”Ñ |Ÿ€6Ä©A”Ñ €“`a&Ð'*A”Ñ >@
(J a*A”Ñ ‚.`
‹-¦)wA”Ñ ƒ`i
Î*ÅA”Ñ ƒ>€	|%$³A”Ñ „H 
2I#òA”Ñ „Œà—ð
™A”Ñ †k€‘!T4­A”Ñ ‡l@"óA”Ñ ˆàA”Ñ ‰íÙ
HA”Ñ Š- Y3KA”Ñ ŠI *(|.`"A”Ñ ‹äàΦA”Ñ ŒTO
g(CA”Ñ ŒÖ ÿ.`A”Ñ ¯àè"É4-A”Ñ Ž†@U£ÚA”Ñ Žú@¤¾ñ®A”Ñ !À%ó‘A”Ñ ‘Z`ì0q	,A”Ñ ‘ëàà_8A”Ñ ’*`H2™+­
A”Ñ ”ÍàþÏ(áSA”Ñ •÷ 	ê'f$¸A”Ñ –vàR"îA”Ñ –à
&V6iA”Ñ –÷àv-×A”Ñ —Ò j	¿A”Ñ ™`Ì+)5A”Ñ ™à
H"´	+A”Ñ œ`I>#ŸA”Ñ œ0 ]"þsA”Ñ œæ |"$A”Ñ `öJA”Ñ ;`›+
“A”Ñ A 0/¥
A”Ñ Ÿl€F%£*ÅvA”Ñ ¡* 7ÓáA”Ñ ¡Ä@¦r/v
A”Ñ £¥àþGA”Ñ £Î §!½OA”Ñ ¥±à½&—4â A”Ñ ¥Ó Ês"Y1A”Ñ ¥í@

#Ë
A”Ñ ¦Àµ!Oe
A”Ñ ¦m
@
QA”Ñ ¦è ¿'@+gA”Ñ §àÍ+þ&—Ê*DA”Ñ ©º 	úàA”Ñ ©È@}2Iœ	A”Ñ ©ðàe€"A”Ñ ªÀ
ž-ÚÝA”Ñ ª—à’!àˆA”Ñ ¬Öàî9-	A”Ñ ¬í€ç5d#A”Ñ ®€­('.˜A”Ñ ¯Z ï%ÁA”Ñ ¯jÀt"¢ _A”Ñ ¯Ñ
ó5PA”Ñ ¯ú@
}ŽE
A”Ñ °§ÀTh„A”Ñ ±X@
Ð!'A”Ñ ²=À±)Ñ!#)A”Ñ ³và
&&‚(%A”Ñ ´ 	›ÿ0%7A”Ñ ´U€RÂ
•!A”Ñ ´{f!TA”Ñ ´Œ 
®&¶ê0A”Ñ ´•€<ò/A”Ñ ¶`àÎ`3A”Ñ ¶kà0Œ$D A”Ñ ¶s
,Š2x	A”Ñ ¸ûÀÈ‹¢FA”Ñ ¹%à®f	/A”Ñ ¹+€'ƒA”Ñ ¹êÀFr(ï	A”Ñ º÷à
ú&yµA”Ñ ¼€ã6ššFA”Ñ ¼Làß*›
A”Ñ ½?àY¿
ÝRA”Ñ ½ºÀÃ0‰A”Ñ ½ý µõ#hA”Ñ ¾nà
 bA”Ñ ¾¶`N0ú";A”Ñ ¿øà2%5E$A”Ñ ÂéàÒ5A”Ñ ÂïÀ„1µ)šA”Ñ ÃQÀ= ¸
?CA”Ñ ÃÂ`G.‚!ŸvA”Ñ Å† « ×!Z4A”Ñ Åº@
’,A$A”Ñ ÆPÀ`†%%
A”Ñ ÆW@Y¨"A”Ñ Æéà
IP=A”Ñ Èp ¢ oó9A”Ñ Êq U/MøA”Ñ Ë©`,'%A”Ñ ËÑ@‹lÃA”Ñ Ì@#-¸,.
A”Ñ Ì„`"t	ç{A”Ñ ÌÌ€ù-v9A”Ñ ÎÒ D*p:A”Ñ ÏÈ/¦9A”Ñ Ð@` ˜!ÍA”Ñ ÐF€
Î1¦(ÙA”Ñ Ðþ@ªDA”Ñ Óq N!fXA”Ñ ÓŠ@`"r÷A”Ñ Óª N&u*lA”Ñ Ô³ u,)U	A”Ñ ÕÃ`	Ž#=hA”Ñ ×'àl)A”Ñ ×ë€ó4õA”Ñ Ù¹@£ô*¡A”Ñ Ú€Ó$hA”Ñ Û€ò/êë
A”Ñ ÜÉ C™]A”Ñ Üò`!;¨A”Ñ Ý(@#.*ÁtA”Ñ Ý¸€ß2"A”Ñ Þ@Iö
A”Ñ Þt`ð Ž-A”Ñ Þžj2…"
A”Ñ Þ¯ :	È5A”Ñ ß4ÖÍA”Ñ àV 1!Ô!
A”Ñ à†à
ºO
§@A”Ñ á±àæ'	'A”Ñ á² 3: âA”Ñ â`Ù4û+l
A”Ñ ä~%0J ËA”Ñ æ?À
©"‚`A”Ñ ç­À
°)È¢A”Ñ çÁ•0!A”Ñ èç _nôÕA”Ñ ê5ê!£	A”Ñ ê4P–!WA”Ñ êKÀ§ O8A”Ñ ë5 Ãá
A”Ñ ì³@Ú#'HA”Ñ ìµ€w
1‹
A”Ñ ìí*ë	vA”Ñ ín Í$o4A”Ñ î­ t3?A”Ñ îâ`rŒgA”Ñ ïG‰ê(¡A”Ñ ïOÀ
6³A”Ñ ñ;À4->?A”Ñ ñ@àyð02QA”Ñ ñ‹à¡æ(¬A”Ñ ñ`	êÐ(=
A”Ñ óä@
ï	'yA”Ñ óø ¸6Ã#A”Ñ õL ê#†ÄA”Ñ õ’À
ðÉ,¾1A”Ñ ÷Œ ï$A”Ñ øà
)â-A”Ñ ù5 
91/ÜA”Ñ ú`ò1à$¥@A”Ñ ú}€
ù)?/ñA”Ñ û p&—*ÌA”Ñ û] S(þXA”Ñ û¨às]ÙCA”Ñ üH`!(Ô%ÿA”Ñ üÚ€
Â:1¢A”Ñ ý[ ß"è£)A”Ñ ýs€Ø*ú5¯A”Ñ þ@JH1TA”Ñ þy@%A6}KA”Ñ þÔàõ(…A”Ñ þÖ@͇ݧA”Ñ ÿ¯@v	3~
A”Ñ ÿü ‘T1/A”Ñ!c â*îA”Ñ!¨ Ã~
A”Ñ!Ê 5Æ65A”Ñ!jàôT19
A”Ñ!Í`þ•/i=A”Ñ!
@séŠ1A”Ñ!F 0t*A”Ñ!ä`	$\
A”Ñ!	Tа'A”Ñ!	à/(ç)A”Ñ!mÀßðA”Ñ!ñ@·%€Ú=A”Ñ!þà	4ï ¨A”Ñ! ùɶA”Ñ!™ÀŸé(ê;A”Ñ!@
)	ŠA”Ñ!Àó ŽÄ
A”Ñ!ý?‹ÌA”Ñ! ¶%Ç,ê
A”Ñ!Y@L,‹~A”Ñ!7ÀÕ(×_A”Ñ!-€:+ÁA”Ñ!> ™$A”Ñ!V ‹0×DA”Ñ!î€
ËöÕA”Ñ!
@Y
E
Ö
A”Ñ!NÀÍF!	A”Ñ!Å€¶ô5(A”Ñ!-@&)A”Ñ!6@	^*4æA”Ñ!UàÒU!œ
A”Ñ!m¾-§ó	A”Ñ!mà
Ç4ŠåA”Ñ!кúIA”Ñ! Š`Û6žN%A”Ñ!!àó+è3–A”Ñ!!R`mG)\A”Ñ!"SàIr2vA”Ñ!"Ç€Æc ×A”Ñ!"È`¨5:	A”Ñ!#3 }¥lA”Ñ!'	€.½8A”Ñ!'- jˆ‰NA”Ñ!'½À·58A”Ñ!(c Y
#$A”Ñ!)= 
è%¢&ñA”Ñ!)F€
…0‘
SA”Ñ!*, .Ód
A”Ñ!-+~+¢A”Ñ!-¦|"
A”Ñ!-á`¡-o)	A”Ñ!.Šàóß.A”Ñ!.®€€)¦/«	A”Ñ!/Àª0ñ#ýA”Ñ!0zÑ"A”Ñ!1.@!1–
A”Ñ!1=À×s*A”Ñ!1øà½"†?RA”Ñ!2<V›A”Ñ!2Ë T#~A”Ñ!3 
€.Ó%A”Ñ!3¶ òÁ3ÐA”Ñ!4N@ô	)A”Ñ!4l1ñ%-
A”Ñ!4Ðà
Ì$$!cA”Ñ!4ñ 
”ÐÉA”Ñ!5‘`E¹.%QA”Ñ!5×€¥s2&GA”Ñ!6\Àù (kA”Ñ!6Ž
l],A”Ñ!6±@Á)(
A”Ñ!7R–8F
A”Ñ!8@ýÞ7&	A”Ñ!8m€Ú&ù6A”Ñ!8³`*Ê$àA”Ñ!8Ê 1zA”Ñ!9ÿ@à!ç,kA”Ñ!:u@Ø/F33A”Ñ!:—~2.4A”Ñ!:á 'Ú0Ú
A”Ñ!;$@# Z‰A”Ñ!< )ŠÁgA”Ñ!<þàÁ&d7]A”Ñ!=e Æ.jV	A”Ñ!=ˆ
*5A”Ñ!=ûá#"L	A”Ñ!?…€
-¸"–
A”Ñ!@M€
5¯àA”Ñ!@Áàö-Î
A”Ñ!@Ò å0ÚA”Ñ!AGà));îA”Ñ!D ]!J	¼A”Ñ!DŸ€\ÑüA”Ñ!DÙ`Ô/!@A”Ñ!F` V"2A”Ñ!FÂàF#+#0OA”Ñ!G(¶ Z\A”Ñ!GE`K((RA”Ñ!HEâA”Ñ!H’ ã.‚7	A”Ñ!I /H¨RA”Ñ!J
@4E1¸A”Ñ!J9À]	á,/A”Ñ!L d$,QA”Ñ!LSàQ!7òA”Ñ!Ld€ò%b!A”Ñ!L} 
¶qÚTA”Ñ!M@.*µ•…A”Ñ!M¿ J%(-wA”Ñ!Nfà%õ
A”Ñ!N›K1ÂãA”Ñ!Ov½R1VA”Ñ!Q Ì!‰2A”Ñ!Qh ì#I'£
A”Ñ!Sz€
[:	µA”Ñ!V# L3Ë úA”Ñ!V þ,
:A”Ñ!WzÀ1!(…A”Ñ!W©	 )¯5A”Ñ!WÏ@¢7ê ‘A”Ñ!W÷€ü­ MA”Ñ!X4€Ú3“µA”Ñ!YÀ¿)û#!'A”Ñ!Z€e4--ç
A”Ñ!Zu`!Ÿ
°A”Ñ![FœA”Ñ![À2£âA”Ñ!\)àïÍ-õ	A”Ñ!]a P0erA”Ñ!]r î(A”Ñ!^aÀ,W,dA”Ñ!^q@X"	A”Ñ!^¨`à'@A”Ñ!a.€
ã&2»A”Ñ!a8@ÑOfaA”Ñ!a³@‹
˜zA”Ñ!aú r]Ó	A”Ñ!c8Àh5ñˆA”Ñ!cOÀÜ- zA”Ñ!cd€‰-ÁA”Ñ!d ÏŒ$ÁA”Ñ!dÆ
•'²5ÂA”Ñ!e¤¡4Á%ŸA”Ñ!f!À
%Ñ+•sA”Ñ!fÔ@'
`#|	Aӄ!g|`
Ñè*˜A”Ñ!gªÀf) $;A”Ñ!gÉ Û%ÞM®A”Ñ!güÀ5Þ-/A”Ñ!h¡ zØPA”Ñ!háàv6à]A”Ñ!ià6ö6A”Ñ!iE œ!EŽA”Ñ!j
àš-„‘A”Ñ!j7 Rˆ1ô"A”Ñ!j:€(‘)‡
A”Ñ!ji@	!Z,?A”Ñ!jÀ
! !A”Ñ!krà„Çð	A”Ñ!k÷[V=A”Ñ!mµ-‚FA”Ñ!m@à“
Ÿ
A”Ñ!mgàï!EŠA”Ñ!m €Z‡A”Ñ!o`Àº„øBA”Ñ!o†#3Ž DA”Ñ!o´`
mLõA”Ñ!rbÀØð,«A”Ñ!r@)ÍPA”Ñ!rî %6A”Ñ!s B±3A”Ñ!sT€S!ã!/3A”Ñ!s‘ 
í6ù£A”Ñ!tŠ 
•	h$ÂA”Ñ!uâ`
b='&(A”Ñ!vî@gS,%
A”Ñ!w€h#c/ÞA”Ñ!y`	ÉA”Ñ!y=€'%a8
A”Ñ!yØ`Š(çA”Ñ!z,€djú#A”Ñ!zr Ï
)43A”Ñ!{.à
Ì·
aAӄ!~
 õLKA”Ñ!~— þ0\ã
A”Ñ! ^µ	A”Ñ!1`«,çA”Ñ!n@yP
ÉA”Ñ!Èy5-'A”Ñ!€“À—2êNA”Ñ!
 
º*A%ÖBA”Ñ!#l1û
A”Ñ!3ÀA7¿$ô6A”Ñ!A 
»1SA”Ñ!Ð@•  FA”Ñ!‚‡“
ãA”Ñ!„UÀÁ+,€A”Ñ!„Á´#XA”Ñ!†C`
§	(MA”Ñ!†œ€
Ô«"¥A”Ñ!†ê±xíA”Ñ!ˆJÀ{ï3]A”Ñ!ˆ› »ØC0A”Ñ!ˆ«€70¶^A”Ñ!ˆÓ_$Ó¦A”Ñ!‰1@½.hÜ A”Ñ!ŠJ #7
ŠA”Ñ!ŠkÀôsÓ`A”Ñ!Š… 3.R%}A”Ñ!Šþ
þ*@(A”Ñ!‹y`@2Î"Ö	A”Ñ!‹¯@(#ï8]	A”Ñ!ŒzÀ…0Ô13A”Ñ!ŒÚàŸ(ª1íA”Ñ!
 °XS
A”Ñ!x@„mìA”Ñ!“ v" A”Ñ!Ž:Àk'sÖA”Ñ!Ža€ü/¶bCA”Ñ!%À8^A”Ñ!@!"ÝA”Ñ!‘ àØ3-¦A”Ñ!“S@K
A”Ñ!”–@ò,½á]A”Ñ!”˜`®3A”Ñ!”€ð†!öA”Ñ!–#
ÒJ7“A”Ñ!—›@G#µ/,A”Ñ!—è 6!wA”Ñ!—ò€µM7A”Ñ!˜8àuf*-A”Ñ!˜Ü@	á’4¹ÇA”Ñ!™ œ9"5A”Ñ!™Ëb-L#¼A”Ñ!™ïT
»	A”Ñ!šV@¶"qA”Ñ!šz@Ã0‹F
A”Ñ!šîà‰¬xA”Ñ!µe Œ&66ÏA”Ñ!¶ŠQ"íO2A”Ñ!¶‹ D*B!²A”Ñ!¶È 
UÐA”Ñ!¶Ï`lðBA”Ñ!·Àÿ@A”Ñ!·x€¶A”Ñ!·™à
Ÿ&×IA”Ñ!·þÀ/( $A”Ñ!¸XÐ
˜
A”Ñ!¹ W,Ô,9A”Ñ!º Ì÷*ÃFA”Ñ!º‡`
#%0fA”Ñ!º¶@ÍÇ­A”Ñ!¼?ÀF2*yA”Ñ!¼ÿ€Z
$"ÉA”Ñ!½@@b£…A”Ñ!ÀjÍÃA”Ñ!À¶ ÃÍ£lA”Ñ!ÚÀ'¹­A”Ñ!Ä?`ÿjA”Ñ!Äd Î"ÚlA”Ñ!Ä÷ 
ü/sA”Ñ!Å`«6+ &(A”Ñ!ÆVÀ
ˆ1ï-H¼A”Ñ!Ç> Ç!sA”Ñ!È+àõ~»)]-A”Ñ!Ü_ 
R-¦,žA”Ñ!Ü›€g IöA”Ñ!Üà G8A”Ñ!Ý ?#CJA”Ñ!Ý^@Ú+2A”Ñ!ÞÞ@X AA”Ñ!áµ ‚à¥A”Ñ!áÁà>1
A”Ñ!â>@4¼y ÛÞ	A”Ñ!ëP ¸%.THA”Ñ!ì#àø-qA”Ñ!ì© ‹+
qZA”Ñ!ì¬àb2çùA”Ñ!ìÚàÛ+/.¡1A”Ñ!î]@€µ"áA”Ñ!îÏÀ4«$íA”Ñ!îØ€$&¢ÝA”Ñ!ïY h½8ÑA”Ñ!ñs`Æ%³	ÓA”Ñ!ñéÀgÞ
Ï9A”Ñ!òO@Ц,A”Ñ!ò’`¯?*iA”Ñ!òž	À,X+	A”Ñ!óA@Q+¨ã
A”Ñ!óΠû*p¢
A”Ñ!óï »"	%o|A”Ñ!ô ês,çA”Ñ!ö“`	%,	A”Ñ!ùt@EÉ5A”Ñ!ú×€Q©,@A”Ñ!û
à	& ë8áÇA”Ñ!û†`£
o7A”Ñ!û‹À½6aBA”Ñ!û˜€Î
*q
A”Ñ!üé 	nÚª
A”Ñ!ý<@ü2ØA”Ñ!ý¦@­0¹ ˜¤A”Ñ!ýæ@
²+`!˜A”Ñ!ÿÕ 
vÃ$ùA”Ñ"i 
”	±åA”Ñ"€7.è	A”Ñ"Ÿ'«!=-A”Ñ"W
Û
/‚A”Ñ"Šà¼êjA”Ñ"À€u4bA”Ñ"ZàÔ& ¥2A”Ñ"¨€F'ñA”Ñ"
Ô®*¨NA”Ñ"	/`	[
VA”Ñ"	 (ê/‰	A”Ñ"
C@1
Ð'(A”Ñ"
8 _:"ŽA”Ñ"
w@ˆ-™(~A”Ñ"
È 	°ƒ,º
A”Ñ" b1ì”+A”Ñ"M…&¹*A”Ñ"+ ã.Ÿ(cA”Ñ"Ô	±6¹$õkA”Ñ"|8.‡A”Ñ"¦`Ç.ç&
A”Ñ"Û€tô
GNA”Ñ"Ä q!µYA”Ñ"@&$F7¾
A”Ñ"ï »RA”Ñ"tÀ
*wA”Ñ"ð@Ó/f(vA”Ñ"h 	ŸLA”Ñ"¯Àç3›A”Ñ"À%f(þ&A”Ñ"& 	æ!‹çA”Ñ"j |˜1åA”Ñ"{`´¤‰A”Ñ"‡@ݵ(c
Aӄ"@	%8
ÆA”Ñ"§f ©kA”Ñ" ?  8A”Ñ"ÝÀéö6ìA”Ñ" Wñ}A”Ñ"˜àv.50A”Ñ") )YÀ
A”Ñ"Ç`(\ A”Ñ"Ê Ì'áA”Ñ" é€{)i&hA”Ñ"#*€ÔwMA”Ñ"$= ;5ù^A”Ñ"$ O<k	A”Ñ"$¦àà& 
A”Ñ"%4$K93A”Ñ"%æ`ç¼+ÆA”Ñ"%ë€	>
$~	Aӄ"&R
 ƒ
A”Ñ"&r`Õ+ÓL	A”Ñ"&é q4¿)ìA”Ñ"'‚ ‘73EA”Ñ"'«€"ÑsA”Ñ"'þÀóf+›JA”Ñ"(	°3g"]A”Ñ"(-à>(ƒ4EYA”Ñ"(‹½j&A”Ñ"(Ò ú%¸7è
A”Ñ"(Ó@õ	*$[*`â$ö)DA”Ñ">Á ({q
A”Ñ">Äà¢ûA”Ñ"?µÃ%>-A”Ñ"@oà€Ý
+OA”Ñ"Bàk*#3A”Ñ"BYà**H0A”Ñ"CÀà)Ü^"A”Ñ"C¶`ƒ"bA”Ñ"D@ $÷5'5A”Ñ"D†ƒÂ"˜DA”Ñ"DÐ@Jù'eA”Ñ"F@T
A/(A”Ñ"GÈ`&ÒÏA”Ñ"HÀç#±:A”Ñ"Inàf!?!CA”Ñ"IÛàa`!A”Ñ"K€ 7)·A”Ñ"K 
çÎÅ/A”Ñ"LW ±& ˜A”Ñ"M4 R ø¾KA”Ñ"M¶ r+,+qA”Ñ"NàC-t2GA”Ñ"NŒ ,v2'A”Ñ"P1Á4ðA”Ñ"QV€/Ÿ=]A”Ñ"Q¸ÀŽ"ï3^A”Ñ"Rã}!8fA”Ñ"T 1+çGA”Ñ"UÀ@	›3"³A”Ñ"V€–&*A”Ñ"Vl€ý™)AA”Ñ"V­à
›¶LJA”Ñ"WqÀ_^0Í	A”Ñ"X<€)á7„A”Ñ"Xœ â
­0$EA”Ñ"Y[€_3+A”Ñ"Z"Àž,{5m…A”Ñ"ZÕ@Ùä6Ä
A”Ñ"[Ý@Ô*¤)3A”Ñ"]·€	sl»\A”Ñ"^Þ@•#gA”Ñ"_‘
zq'_A”Ñ"`€ %!„$r^A”Ñ"`€z'a_3A”Ñ"` )5F:
A”Ñ"`© k!>F$A”Ñ"a3à!šiA”Ñ"aø@Rÿ"†A”Ñ"b4 M)½ËA”Ñ"bs`Ñ/›šA”Ñ"c&@ÉU7A”Ñ"c4`÷Ux6A”Ñ"dãÀ[$R
A”Ñ"e@å) ÕA”Ñ"e *}'lcA”Ñ"ežÀ·ú/d
A”Ñ"fX`c0Ð
A”Ñ"gQ@Qc‰A”Ñ"h
iO0›A”Ñ"h€€%¦0Q#A”Ñ"h! ê»!!_A”Ñ"h³ ~jA”Ñ"hΠ¿'\y	A”Ñ"hÏQ(Ü	âA”Ñ"jCÀ0£A”Ñ"n\àn
¢ ÀA”Ñ"oà~%÷
A”Ñ"ob 2ìë-A”Ñ"oŸ`&2°IA”Ñ"o°`Ö

!A”Ñ"puû"Í7×A”Ñ"q£ 	…^A”Ñ"rÆ (eŠA”Ñ"r×àAß6
A”Ñ"u{ N+H þA”Ñ"vd 
¶Î…MA”Ñ"vÐà@÷7áA”Ñ"w!@n:6A”Ñ"y€r35A”Ñ"z` õS½
A”Ñ"~Xà‡|3ŠjA”Ñ"p€“ÄA”Ñ"  >$FëA”Ñ"€-Ï=A”Ñ"‚4ÀþêA”Ñ"ƒˆ€ÖäÇA”Ñ"ƒ— 	âÛA”Ñ"ƒµÀž&ø*eA”Ñ"…æ`æ'š.3(Ëì{A”Ñ"¡•@¯ôìA”Ñ"¢ê .
A”Ñ"£ø õ2±­>A”Ñ"¤àÝ Î'A”Ñ"¤.€
ëBqA”Ñ"§FÀ¦0`&H
A”Ñ"§K@
{ ¶bA”Ñ"ªKà5è%/gA”Ñ"ªV€¿
BA”Ñ"¬& †ÖŠ6A”Ñ"®ÓÀT4ç¦7A”Ñ"¯l w0“$9
A”Ñ"¯¬€‹8SA”Ñ"°A@G%ÎA”Ñ"°Œ (''Ï,A”Ñ"°Ë¸
˜àA”Ñ"±*`t3)>A”Ñ"±µ
â'àA”Ñ"²d`¢<.õ1A”Ñ"²ß È/"ù+A”Ñ"³§àI+ÒaA”Ñ"³Ìæ(O,á	A”Ñ"´» aÂ+oJA”Ñ"µ‹ 	I BCA”Ñ"·	Àa0NA”Ñ"·`9!ƒ$ÕA”Ñ"·à	6zÒ A”Ñ"·@ U'¨ìA”Ñ"¸ p²	A”Ñ"¸-€Â7"ýA”Ñ"¸ÿ
²CƒA”Ñ"¹Î€‚
if
A”Ñ"º`¼"])B	A”Ñ"»L@	 1RA”Ñ"¼Ý@}0|(9
A”Ñ"½ÍÀ	c+S	ZA”Ñ"¾K`‰9A”Ñ"¾„HjÖA”Ñ"¾™ P-7TA”Ñ"¿g`j!èTA”Ñ"Àx`…$
.QA”Ñ"À‘@Ó3<
A”Ñ"ÀÄ`h »¾A”Ñ"Á«€õ‹¼A”Ñ"Áó ô5|mA”Ñ"Ä2À
Æ ¼A”Ñ"ÄÊ`é4{!I
A”Ñ"ÄÜ€×û.,TA”Ñ"Å› 3í"A”Ñ"Æ+€o )œA”Ñ"Ær¡ ¢&ûA”Ñ"Æç`
ç%7{LA”Ñ"Çá€(\ì
A”Ñ"ÈEàÑ&±|	A”Ñ"ÉþÀ&/ø*†A”Ñ"Ê' )ö2(A”Ñ"Ê@`n(̺A”Ñ"Êt[%ß	A”Ñ"Ê~  ªŸA”Ñ"Ê„€Ð%t:A”Ñ"Ê¢ B&®1A”Ñ"ʹ`:
åA”Ñ"Ëà#ÚZA”Ñ"ÌÑÀK4VWA”Ñ"Í@—­-
A”Ñ"Ï?À) ¡A”Ñ"Ïø ô
}ËRA”Ñ"Ѐì<#ÊA”Ñ"Ñ 
DëëA”Ñ"Ñ|Ž0i
A”Ñ"Ñ­€PëÂA”Ñ"Ò9´$»S*A”Ñ"Òú ¹4H)ŽA”Ñ"Óœ j™i@A”Ñ"Õ›¹ŽA”Ñ"Ö1 „
ÙTA”Ñ"Ö@îÝ
JA”Ñ"×ÂÀí
GA”Ñ"ׯ@χ’$A”Ñ"Ø+àvçä8A”Ñ"ذ`.+A”Ñ"Øþ i(ÈmA”Ñ"Ù‚ÀÁ÷(ÐA”Ñ"Ú

%)¯ëDA”Ñ"Úý¦!‘A”Ñ"Û·àÅ%€àA”Ñ"Ûäào"à<A”Ñ"Ü`àOP)A”Ñ"Üm 	;6A”Ñ"Ü–€tæRCA”Ñ"ß)A”Ñ"á@iaúA”Ñ"á ü(É427A”Ñ"åš@YVŽA”Ñ"æÛ@¤/V'ÀA”Ñ"æã 	›!Þ
A”Ñ"çä2,+A”Ñ"ë5à	ÓΣA”Ñ"ëV e"j
PA”Ñ"ì÷àbŸqA”Ñ"í€ú&( ³A”Ñ"î¯à
Úæ.A”Ñ"îâ(Ã
W	A”Ñ"îïÀtð5¼A”Ñ"ï< *"ö!1A”Ñ"ï¥à
“p
A”Ñ"ðÇ@_!
h
A”Ñ"ñä@_$EâA”Ñ"ò—¡# Z-A”Ñ"õ€¿/‘6A”Ñ"ø} /‹ÁA”Ñ"øƒÀv7±A”Ñ"øøà€(ï
A”Ñ"øû€i! CA”Ñ"ùŒà103A”Ñ"ù¨`É%ìA”Ñ"ùÅÀ<AA”Ñ"ùüà$0/Ê
A”Ñ"úç%3&FA”Ñ"ú¸€=)»A”Ñ"û€O0H1ÈWA”Ñ"ûAà,(;A”Ñ"û×à
Ü"ú
;A”Ñ"üL`öïA”Ñ"üj 1/B>A”Ñ"ýk@9-¡&46A”Ñ"ýäà
z)/#jA”Ñ"ÿ‘ 5+?A”Ñ#œ /A”Ñ#c@Æ"×
A”Ñ#]à
2ª5×+A”Ñ#í@##ÝŒ5A”Ñ#|@Y=A”Ñ#â@Ù°
ÕA”Ñ#á€éú+A”Ñ#Ä€	ÀéA”Ñ#	O@âs4bA”Ñ#	o@w_ÐA”Ñ#	ð€ù%A”Ñ#
kÀGA”Ñ#`aª)àNA”Ñ#9`
`"¢3èšA”Ñ#NàÃ¥ƒA”Ñ#5àú0ùA”Ñ#°@÷#«2ZA”Ñ#>`ˆ…‚pA”Ñ#P š%ÍA”Ñ#|*úA”Ñ#à9 @ Ç	A”Ñ#.DsA”Ñ# 
þ"(A”Ñ#j@
Æ)£)A”Ñ#¯`ö(™
A”Ñ#Å ÞL2/	A”Ñ#Àæy;
A”Ñ#iÀýš)A”Ñ#@	¿,0ÃA”Ñ#1€ä#õ'IA”Ñ#t
b^7ÐA”Ñ#À€V«ž"A”Ñ#/à½2±^A”Ñ#H€<(ÀÆA”Ñ#)`	#qê‰A”Ñ#“ Ð0²#A”Ñ#n Ò%×5A”Ñ#†@
ñ
ÈA”Ñ#—€ÆB&ý'A”Ñ#o`
öU4ýA”Ñ#ï@V\:A”Ñ#ñÀ6× A”Ñ#öÀ
ð ,A”Ñ# ä ž1P)ôA”Ñ# ñÀ6+S2L€A”Ñ#!
.‡áA”Ñ#!~@×
05A”Ñ#"NÀý-/XVA”Ñ#"`’,q0A”Ñ#"À>ã
š.A”Ñ##
R$X#$AA”Ñ##€ $i‹
A”Ñ#$ʽ67A”Ñ#$’€5+ÙWA”Ñ#$éà±Q%™A”Ñ#'“@1k%
A”Ñ#(ä@
Ê$A”Ñ#*ìz Ý01
A”Ñ#,eàÇ(O×
A”Ñ#-ßB-Ç(^‚A”Ñ#.À	8%=#A”Ñ#/F`À£A”Ñ#/p`ª1$ðA”Ñ#0Å`
Ý#‘1É
A”Ñ#1 Å0#:A”Ñ#1èÀÌï'4€‚'È-Ê
A”Ñ#>½À¡0â
AA”Ñ#?€r#7	A”Ñ#@_ g¢2ûA”Ñ#@b Š#­5"A”Ñ#BÂàñïú
A”Ñ#BØàŒÒ A”Ñ#C´&ÍA”Ñ#D  
Òi. A”Ñ#FgÀ.3ç¨PA”Ñ#Fˆ€ˆ,Æ,þA”Ñ#F Ãe![0A”Ñ#FÇÀ¤1$A”Ñ#G?MÇ…A”Ñ#Gý`¸*A”Ñ#H±àM-@$=
A”Ñ#J`d!J wA”Ñ#Jm@0pA”Ñ#K@è3)%A”Ñ#Kcà	Ç“2ÏA”Ñ#L£ Ž+ä*A”Ñ#Mr26ûA”Ñ#Mx€¡»A”Ñ#M” ¯¿2A”Ñ#N×€Ü6„ì¶A”Ñ#O©à%`×A”Ñ#Oéœ#qþuA”Ñ#Oñ@·.µÁ2A”Ñ#P¥ š3ñùA”Ñ#Qh 
F H'µA”Ñ#Q`
?á+Æ
A”Ñ#R@E#A	A”Ñ#Tà
µÐöA”Ñ#T7`&#cA”Ñ#TE€Q/«*êA”Ñ#T¬`¯05þ"A”Ñ#T®`+'Å	A”Ñ#Uhà	œ*>)A”Ñ#Uš @Ì(Ø A”Ñ#U¶À
› ­
§A”Ñ#V  ÒM3A”Ñ#VßàFà	A”Ñ#WÂ`S(Ÿ
 1A”Ñ#X3 §z/ÈA”Ñ#Xvë/y
A”Ñ#XÍà,)é&ƒ†A”Ñ#YV 
U
”A”Ñ#]¶ ik—.A”Ñ#_€Ã2÷%ÒA”Ñ#_À
1#o'…A”Ñ#_Æ 
%ÏéA”Ñ#`qà0N++A”Ñ#`Ë |xµA”Ñ#aù€%o–A”Ñ#b¿ Ë$©+»	A”Ñ#c¸ ÔT#AA”Ñ#cÎà¬"í}A”Ñ#dà8	™(JA”Ñ#fù€(&…">
A”Ñ#h•àÅuA”Ñ#hº€b!c!eA”Ñ#iTà
'"A”Ñ#kà	ý%‡vA”Ñ#l¦—‹ÈA”Ñ#l±m$BRA”Ñ#m…Ú%rºKA”Ñ#m™8 òA”Ñ#n® –ÊA”Ñ#oMàÄ,÷ ¾A”Ñ#oŽ`
2¦%Ç
A”Ñ#pR $2¶¶A”Ñ#p•YA”Ñ#q!`Ï)¸-A”Ñ#s`ÈnŒÌA”Ñ#sz@H¹7d
A”Ñ#tp j¤mA”Ñ#u1€"âA”Ñ#u„€>}$xA”Ñ#u¥ò-*[7A”Ñ#uÛ€³÷!Á
Aӄ#v
 Ü4‡+A”Ñ#x?@d"8 aA”Ñ#xvà7m#vGA”Ñ#x©à'"Ú6Ã
A”Ñ#y€!— ;A”Ñ#y-€(*ÐA”Ñ#y‡`	\,Î7A”Ñ#yËÀ#
¶#A”Ñ#z´
­-æ1¡^A”Ñ#|P`"ñ*ÏA”Ñ# àˆ)mWA”Ñ# Õ/!MA”Ñ#yÀÁò$30A”Ñ#‚”à%:.ªA”Ñ#‚¢à.…
A”Ñ#‚¶À£d*	A”Ñ#ƒ`	£5ìA”Ñ#ƒf@ 0E"^A”Ñ#ƒl€èœA”Ñ#„A@>.H(2A”Ñ#…`õ%1ÐOA”Ñ#‡ž`r0(~A”Ñ#‡¥€ç
8/A”Ñ#ˆ@	7;`
A”Ñ#ˆ¨à	_
A”Ñ#‰[ ¯"(ÝA”Ñ#‰¥ 	n+å8A”Ñ#‹CÀG.·#
A”Ñ#‹P@û/A”Ñ#‹Ú@C!Ÿ2A”Ñ#Œe Ô'2ºA”Ñ#ŒÉ€‡Ÿ(’A”Ñ#Œÿà	ò.8+úA”Ñ#6€ã
A”Ñ#ñ ¢3!6A”Ñ#E€ž/Ÿ
A”Ñ#m Ò(~ãA”Ñ#“H`¢®\A”Ñ#•À.äA”Ñ#•²@ð
•A”Ñ#•ßËF5ZA”Ñ#–†`OG"A”Ñ#—o€
n!@&R
A”Ñ#˜•@
Î'Ë&fÖA”Ñ#™/`
f	Ù9A”Ñ#™Æ@£"*ÄA”Ñ#šR€	x¼A”Ñ#›Ò@”¸ÅA”Ñ#›ð@îýrA”Ñ#œÀ¿^A”Ñ#œûÀV.àA”Ñ#a ;1¬A”Ñ#Ô ë/!Ã:A”Ñ#ž n!ÑÜA”Ñ#ž]`$º0Ö.A”Ñ#žº€&¿A”Ñ#Ÿ@W’|A”Ñ#Ÿ¦@Ð3*SA”Ñ#ŸÜÀ	(
)¯qA”Ñ#¡2ÀŸ*
A”Ñ#¢Høp-[A”Ñ#¢‡@ˆ
[+ºA”Ñ#¢Ó@	.R/Ä
A”Ñ#£| A/*Î6A”Ñ#¤5 ¢!0A”Ñ#¤ËÀS/ƒß
A”Ñ#¥“ÀÐ	Œw
A”Ñ#§Ý ¾¢@A”Ñ#ª!@D+%
A”Ñ#«Ù 
â^À²A”Ñ#¬Nà7eáA”Ñ#¬d »0AA”Ñ#¬n ÿ-´›A”Ñ#­ô ·3Úô
A”Ñ#¯@¤0–ØA”Ñ#°, ®øýA”Ñ#±1€oi’	A”Ñ#±j€¤)Ã+A”Ñ#²‡ÀÉ/A”Ñ#´š«%»7‚èA”Ñ#µ®À\Ý5:A”Ñ#¶, I¶ëA”Ñ#¶Ù `V4°A”Ñ#¶ý anA”Ñ#ºI€Žf	-A”Ñ#º”àm
ŠA”Ñ#¼È 3(ÔA”Ñ#¼÷àô.ËŸ
A”Ñ#½D Y"ô(A”Ñ#¾É€	²æ&;.A”Ñ#¿‚ 
Ý!ù,å
A”Ñ#¿¡€3h"ïA”Ñ#Á¤ 
]"Ë7A”Ñ#Áä`Â6%heA”Ñ#Â2àdaãA”Ñ#Ã,À)feA”Ñ#ÄWæ1òA”Ñ#Å^€Uí0Ñ	A”Ñ#ÅÞ`þÁA”Ñ#ǽàäX6A”Ñ#Ê
Àí)¬A.A”Ñ#Ê- *W%%
A”Ñ#ʘà
Ø£2#}A”Ñ#ËJ 0¶pXA”Ñ#ËWÀpΆ
A”Ñ#Ë£b‰µ
A”Ñ#Ì~à”)ðŸA”Ñ#ÌÕx	A”Ñ#Ìê ,‘-ÚA”Ñ#ÍÀ%b	,
A”Ñ#Í× #Y+mA”Ñ#Î2 â–#;(A”Ñ#Îå»ÙqâA”Ñ#Ï ¦F)‰PA”Ñ#Ïpà
+++Ç
A”Ñ#ÏàE3•ÖA”Ñ#ÐQ ¾-daA”Ñ#ÑN@–Q·A”Ñ#ÑÄ`ÞÉ1Ü
A”Ñ#Ò# ´1æA”Ñ#Ò¡½!xA”Ñ#Ò¤ 
ïþA”Ñ#ÓŽ€Þ*À3V	A”Ñ#Ô<€@y·+A”Ñ#Ô¶ %2¡A”Ñ#Ø.àï"µ}A”Ñ#Ømàs
ù±'A”Ñ#Øœ7·
A”Ñ#Øä Ò-9²A”Ñ#Úd i{º×A”Ñ#ÛDÀ‡†*
A”Ñ#Û¦1Â-~'A”Ñ#Ý€,'(:A”Ñ#ÞI@	Q¥ ®A”Ñ#ßÀS.¸A”Ñ#à-`³¨$ÇA”Ñ#àrÀÜ5¥$|A”Ñ#â°`
Å	•(xA”Ñ#âúà
Ö(:$‰A”Ñ#âý;¿%|$A”Ñ#ã+ £€¦A”Ñ#ãjÀæ*'PA”Ñ#㜠	¦%̶A”Ñ#äkµxÔA”Ñ#åË@ë•%A”Ñ#ç¤À°5	¥+A”Ñ#ç­`	)ò®A”Ñ#èë 
´)Ì •-A”Ñ#é7€
;5A”Ñ#é[X°A”Ñ#éÕ@œÙŒ]A”Ñ#ë…@	
ÚÌA”Ñ#ëžÀOk0A”Ñ#ëÄ`&		!Ò
A”Ñ#ì+@a&ü
žXA”Ñ#ìE &Ã[A”Ñ#ìq`c* A”Ñ#íD
8$Ë1?
A”Ñ#íÙ  "£7
A”Ñ#îÆ §é$XA”Ñ#ïà
6tÛA”Ñ#ðS@€)0£A”Ñ#ñYµ2eAA”Ñ#ñz€x!€A”Ñ#ñÿ@'Þ!ùA”Ñ#ò.À”[A”Ñ#ò® Ú8ßGA”Ñ#óÙ"«A”Ñ#óý*qA”Ñ#ôÝ 	©+…$ïA”Ñ#ôÞ€
Ë$HÈA”Ñ#ôö`S,ž&{*A”Ñ#ö 	è(ˆ
Ÿ
A”Ñ#öq ]×™A”Ñ$˜  y+Ä@A”Ñ$ÊÀ² 
¦A”Ñ$ÀXVŽ2A”Ñ$ÀË6DA”Ñ$f€
!6PXA”Ñ$ª ~0Ç"ÞA”Ñ$œ@ˆGÙA”Ñ$`.-!
A”Ñ$¢àn‚4A”Ñ$ðý¨&AAA”ÑS´` 
ò
OA”ÑSµ/ X³ ŸA”ÑSµh <%P7 -A”ÑSµÜ@É4¹%%A”ÑS·'
È*! A”ÑS·8 Ö›YA”ÑS·§ Çö-Š
A”ÑS¸@Ù&—3A”ÑS¸–À ú§PA”ÑS¸ü@¼,4	A”ÑSº_€T+?QA”ÑS»Sà¯Q!uA”ÑS»‘`7À2A”ÑS¼eÀ:'·?A”ÑS¼o 
âíA”ÑS¼¯@†&{"A”ÑS½ü@ú"ÌvA”ÑS¿J`ë>AA”ÑS¿yàÔ±&k
A”ÑS¿í`r-ŽA”ÑS¿òÀ	±.ÝA”ÑSÀ !Ë0ÙA”ÑS #Ö‡A”ÑSÊ 'ö4¥jA”ÑSá€@7Š

A”ÑSÄ@Ó$
A”ÑSÅ@©Ï–7A”ÑSÆ€œ/æ1GA”ÑSÆÙÀ±	ÛþA”ÑSÇ> AtýOA”ÑSÇ•`'
•%¼
A”ÑSÇÄ Ö8ÒÍA”ÑSÈ1 
iÏA”ÑSÊB€7pA”ÑSËÀŽ3Î'ö)A”ÑSÌ®à	Zîq
A”ÑSÍ´ -D#b
A”ÑSÎë (Ù²#A”ÑSÐà÷@A”ÑSÐo`
+H&WA”ÑSе`
±Û„A”ÑSÐà@w19"A”ÑSÑ–ÀGA”ÑSÓN@V3"TA”ÑSÓd`f!lA”ÑSÓoÀõ'Ì:A”ÑSÓ ®D NA”ÑSÔ CÉ"‚A”ÑSÔ=€
Õm"-A”ÑSÕŠ 
ÝŒ HA”ÑT.! U{	"
A”ÑT.I€Õ#è"{A”ÑT/ýà
PTóA”ÑT1/Š$`÷A”ÑT1F ­ï|A”ÑT2”àržk
A”ÑT37@`"Ð,ï
A”ÑT3`Ðwè|A”ÑT3¶@RvÑ/A”ÑT5°à.+Ä2A”ÑT5Ý —
@$®A”ÑT6³@
•"´é%A”ÑT6³à)f —ƒA”ÑT7ªÀ1XlA”ÑT7åÀÄ ¸A”ÑT9 š(	Š?A”ÑT9c ]ö	A”ÑT9| äŸ#%TA”ÑT:
á/¯9
A”ÑT:{@A(|/bA”ÑT:½€3?+$A”ÑT:ÖàÝ•"ÍlA”ÑT=×`
õ“ØA”ÑT=ã#‡A”ÑT=õ€.@1è	A”ÑT>š@¨&à
A”ÑT>· F¹"ZA”ÑT?À
é~]A”ÑT?ÏÀi$*ÄA”ÑT?éàê!A”ÑT@Ê@‰ñ1˜A”ÑTC¿@‚ü
A”ÑTD] ÊH(A”ÑTEÌà½(Ô *eA”ÑTEáÀL2(ä
A”ÑTFÌà×$– ¼A”ÑTG& ;4÷zA”ÑTGà¶6f&×RA”ÑTG»@	ü¿-kA”ÑTGãÀ¥åÕ*A”ÑTHÀ+ÊA”ÑTH€€_$XÎ
A”ÑTI€@½ö%¯A”ÑTIò`j-Û%×	A”ÑTJÀ
ÿS7¾LA”ÑTJŒàVÜ21 A”ÑTJ§ ŠÏ—A”ÑTK: Ñc	A”ÑTKU § î"A”ÑTK^€
º
Õ½A”ÑTKë ½	—Š>A”ÑTKë@“".4A”ÑTMj 7C0MA”ÑTN? ÜÝ60çA”ÑTQ\àÑ*!
A”ÑTRƒàq#øŽ	A”ÑTR¤`Ä2ˆ%¸A”ÑTSYÀ
Ñ%5ZA”ÑTSå~(¼
AӄTTO@
ë5a	A”ÑTTÈ`é1“A”ÑTUˆ@;..1A”ÑTVÀàG"‚íA”ÑTW.€ÍŸö
A”ÑTW?€ûd]A”ÑTWo I4Ö]A”ÑTW—`V4¡<A”ÑTWÜ %5wÂA”ÑTX¹ ÷'ðA”ÑTXÆ@%59¼A”ÑTXÛ /Ì!]A”ÑTYJ`£4.6A”ÑTYP ø r—A”ÑTYu@Óø&·[A”ÑTYx`U*ÏŒA”ÑTZ`˜WúQA”ÑT[7àè.|%¬	A”ÑT[ù2ÕA”ÑT\n˜T%ÐA”ÑT\ò`œ+¡5A”ÑT]N`é§/A”ÑT]©àKŸ/A”ÑT^’ Ý,•ØA”ÑT^¶ ®1÷œ'A”ÑT^ÕG!ßA”ÑT_kM1A”ÑT_‡¼4±-AA”ÑTbÀ´$þ#œA”ÑTbk`·ú5‹GA”ÑTb´@3\¡
A”ÑTcàã#.-Â)A”ÑTc¬ jÝ*1A”ÑTcЀ	Ç'ö(;A”ÑTcß`
‹žIA”ÑTdÈ@ÅA”ÑTe.`®ÙËA”ÑTe<@(•
á-A”ÑTe@‚$iA”ÑTeà
¨&«&Œ
A”ÑTf0#A”ÑTfa2|C¬A”ÑTgŽ ¹‡VA”ÑThç ó!‰A”ÑTi³F&ø8g
A”ÑTiä`‹(â#:
A”ÑTj­àµ+'‹mA”ÑTjÑ ƒ+º$1	A”ÑTjØ`	,t.˜A”ÑTkG u'hOA”ÑTk À3&FA”ÑTlÎÀV&Ø)|	A”ÑTm@	~$ÈA”ÑTm!àQ3$) 2A”ÑTm5@ÿs£A”ÑTn4àÄ $ÕA”ÑTnÐ »ä=A”ÑTo	àP
´A”ÑTpâÀu
|.fA”ÑTqR@JÒÒ1A”ÑTqUÀЏ4A”ÑTrË@.&	Ý	A”ÑTrÑÀê#A”ÑTs%À¢%ö	±A”ÑTsâ€v6W!5A”ÑTt‹à
.1 ¿A”ÑTt 
»	!&öOA”ÑTtø`~%šA”ÑTvvײ*ôA”ÑTv— 	ª/î
A”ÑTy³ 7¬Â:A”ÑTyÓ b&A”ÑTz<àÓ'µxA”ÑTz¯àÄ-xA”ÑT~+E5‡&iA”ÑT~Ñ€
La1ø
A”ÑT a ßA”ÑT€ö à+A”ÑT¯€	öÝ%A”ÑT‚ÇŸA”ÑT‚äàñU(aNA”ÑT„ _	‚
A”ÑT„o 
/5ä5A”ÑT„ç)«#ÉA”ÑT…^ 
v14$×A”ÑT…b€]w zA”ÑT†­0öW
A”ÑT‡Ñ@D#ˆA”ÑTˆÕ€
+sð[A”ÑTŠ
Àe4ç-]'A”ÑTŠyÀ[zA”ÑTŠ¡€áY	Ã/A”ÑT‹Š 6+ßA”ÑT‹Ã€	X!8'XA”ÑTŒ*`
é5SédA”ÑTŒ2 »¾+zA”ÑTŒô€	Ú0•%,A”ÑT™€4*îlA”ÑT¶@”19
¼A”ÑTÊ£!Ç"’2A”ÑT‘«`
hg2lA”ÑT’Ààšd'öA”ÑT“e,ˆ!	A”ÑT“£à
•‚/qA”ÑT•9à=i
“A”ÑT•=àb.ÈFKA”ÑT•K@J¤®mA”ÑT•á@‰1gA”ÑT–K€˜;,p&A”ÑT–u Y«FA”ÑT–úÀû$…A”ÑT—ÀŸ5ÌA”ÑT—à'.-¬	A”ÑT™[€/!ŠA”ÑT™ÃÀ°
¡gA”ÑTšøàD!Ñ-ÑA”ÑT›( g‹ÑA”ÑT›/ .,“!A”ÑT›\@al)ÃA”ÑTœ4 
#(¹/s
A”ÑTœÄ`%(x7A”ÑT« !*‹$A”ÑTž
C+RA”ÑTŸš`ߨ!Ó@A”ÑT jÀ
ã%é
cA”ÑT ½`Ä'Ð-A”ÑT Ì5!¼$A”ÑT¡w #ûA”ÑT¢d
tCiA”ÑT£Ò€£2âA”ÑT£Ó ÆvNA”ÑT£ýàØ2|6A”ÑT¤÷`N4ì%HA”ÑT¥Ì@
Ü9%.A”ÑT¦À
("6A”ÑT§– Ÿ+øˆA”ÑT§ÛÀ&'A”ÑT¨8 Io
A”ÑT¨Uà~#÷$E
A”ÑT¨€X]P	A”ÑT¨”Ào³!ü=A”ÑT¨Ÿ †E#3A”ÑT¨Ú€
;4ñÓA”ÑT©ž'?/ÿbA”ÑT©C€ë,XxEA”ÑTª
8i&™&A”ÑTª)àÍê	.EA”ÑTª’ ¶‚+HA”ÑTª¯ 	•	.ðA”ÑTªéàpÐ)A”ÑT­€žÈ¸oA”ÑT®|Àì"ò7A”ÑT®Ö 
í
Þ"DGA”ÑT¯“ÀË"A”ÑT°« ¦2ïJPA”ÑT± /„æA”ÑT³` É%­ƒA”ÑT³‘ÀÁ%ÞËTA”ÑT³ç`¸!Â&A”ÑT´Uàh0*š
A”ÑT´`1-åBA”ÑT´°@²!ãµA”ÑT´ì€¶#r#lA”ÑTµ8ÀË
ÂA”ÑT¶€é)úA”ÑT¶X`	Žö"vHA”ÑT¶{À¦ LA”ÑT¸9`Å×}*A”ÑT¸|àK'ÿ8FA”ÑT¸¥HÁA”ÑT»å Bµ®A”ÑT¼~`s0ÌA”ÑT½À
ó$ûCA”ÑT¾È€³,"	²
A”ÑT¿~Àü0»`A”ÑT¿ù€‚5)Y?A”ÑTÂC E*Ê0
A”ÑTÂä`™*°cA”ÑTÃ`,¤&ÊA”ÑTÅŽ %6~A”ÑTÆ6 ß#5qA”ÑTÈ æ½#žA”ÑTÈ'`
	ÀA”ÑTȨ€Œf+KNA”ÑTÈ÷@	1H,ÙA”ÑTÌ `z#*
A”ÑTÍ!
ºk&ÛA”ÑTÍK@â1¸A”ÑTÎÄ@Fð¿A”ÑTÏ 10€äA”ÑTÐ{@£&¶
X!A”ÑTЀ€TÀ!A”ÑTÒªÀFÓ¾A”ÑTÒÉ€£.#"W
A”ÑTÓJà½(É0…MA”ÑTÓl€}&™	åA”ÑTÔ,`+-2#Ú:A”ÑTÔ  ü8!à7A”ÑTÔÂ`™.s²,A”ÑTÕyàs]6QA”ÑTÕ€`5½-€7A”ÑTÖe€¶‡#Á	A”ÑTÖ´€
£Ý3A”ÑTÖØigßA”ÑT×/ 2±3A”ÑT×/@r*·ÝPA”ÑT×çÀ*òA”ÑT×ñ@Ó46´A”ÑTØ\€.1-,hA”ÑTÙ6‚#¡A”ÑTÙw 
¦5` A”ÑTÛ™À
†}$ûA”ÑTÛë`
Š–õA”ÑTܱ ¦î)A”ÑTÜù€øƒ0ÏA”ÑTÝD  $OL5A”ÑTÝ–àâ Œ+A”ÑTÞ¦À¤4#•A”ÑTß`¼
ù(bA”ÑTßE€á
´+ùA”ÑTßX€	”/3A”ÑTáÎÀö0ÚEA”ÑTáÝ15;‡A”ÑTâä9'ØA”ÑTãh 
öw5¹A”ÑTãØ€9o;A”ÑTäšà¤³.A”ÑTä­€:!û-ÀA”ÑTäæÀS)î(ÊA”ÑTæ¸	…3ÝÀA”ÑT盀*“,Ú A”ÑTçû QÝIA”ÑTèÀH)(Þ
A”ÑTê		„(h!ƒ
A”ÑTê
x5+PA”ÑTê@	6,å‚A”ÑTë/€áÔ"Ú
A”ÑTíS ®˜-KA”ÑTí¡@w#9-
A”ÑTíò <|"IA”ÑTîL`\a%OA”ÑTîÆ`84ó#H#A”ÑTðÀÐ*Á!¶
A”ÑTð‚@
8	0"A”ÑTðê ß%'’	A”ÑTðñ 
j.ZVA”ÑTñ| »)À	A”ÑTó2à	¤{78,A”ÑTó¢ ¬´-0
A”ÑTôG@Æ.z
¹A”ÑTôc@=¿Ñ9A”ÑTôêàùŸ °A”ÑTþ`

†OA”ÑTþoTjN	A”ÑTþp`ø%*A”ÑTþw 5Ô{A”ÑTÿ}À”+?!ì/A”ÑTÿÜà
&ý$A”ÑTÿñ Vð
*A”ÑUA@Ã-á¯,A”ÑU€$CA”ÑU& Ð+’ê
A”ÑUp #«,£\A”ÑUœ Â#q7.PA”ÑUt ( ’$Æ
A”ÑU„:…A”ÑUb`XA”ÑUiàu
­-æA”ÑUÀOÁVA”ÑUß ©éÄsA”ÑU«Ã&¸µA”ÑU	à;Ç(øA”ÑU	|À
\_»A”ÑU
.๥
AӄU
:`E$N'AӄU
Ë î	`'¦A”ÑU ÜÈ#¾
A”ÑUSÀ
#)<%A”ÑU€yRŒA”ÑULG!1	A”ÑUÛÀ&*A”ÑU
à˰ž4A”ÑU
. %"ã#ò5A”ÑU
w g!9NAӄU
¦Àü@+A”ÑU
Î`ô5ïø
A”ÑU@`®1/
A”ÑUŠ	Ý
†A”ÑUÕ€6ló
A”ÑU¡ ‡	ScA”ÑUGàù,”–
A”ÑUŒÀ0ñA”ÑU, Ñ/SÐBA”ÑUÊj»/FA”ÑU{Àí+ðóA”ÑUØ€A%d#efA”ÑUð ‹¬.ðA”ÑU„Æ'Ë(JA”ÑU 	ͺÁA”ÑU=Å ŠæjA”ÑUg`—+œ2$A”ÑUÅ W ,A”ÑUÑÛ˜ò(A”ÑU>€±²$éA”ÑU­`5.;A”ÑUà@ä7,4A”ÑU$¿G(A”ÑU‘`ª8"l¦A”ÑUÍÀ
ó-2ò
A”ÑU,`6~Ô	A”ÑU	@m%V.A”ÑUr`
7Ç6d
A”ÑU`.'=ÎA”ÑU:€Þ(q©rA”ÑUjÀ3&¢" sA”ÑUã@
"#èÙA”ÑU8à )ê/üA”ÑU’+ZA”ÑUó 	€¸A”ÑU!³à<®)A”ÑU!ôà*)©!ºA”ÑU"UÀ
*§)WA”ÑU#	 
V€(ÀA”ÑU#`
a è18A”ÑU#Š€g4€B
A”ÑU#±©v2ƒ!A”ÑU#ð v!0ŠA”ÑU%ËvR*A”ÑU%ÀHÅ8¼A”ÑU%ò`".R*OA”ÑU%õ`S!T/8A”ÑU&n lÜ)S
A”ÑU(6 	Ã.øü	A”ÑU(ƒ’#O"‰A”ÑU*'
¶/A”ÑU*Ò€?.+5A”ÑU+£Àë­ÛA”ÑU,. J€!A”ÑU,6G6s7A”ÑU,O
ª&ñ÷A”ÑU,à}
@A”ÑU- ù,ÂA”ÑU-=àì @7À@A”ÑU-¤Àñ¶;A”ÑU.! óB-ñA”ÑU05àS)VA”ÑU0—À
$	ÅfA”ÑU0Ú@H&dµA”ÑU2>€*)Wß
A”ÑU2UÝ7'•
A”ÑU2Ö ¶Éo	A”ÑU3] x*16NA”ÑU4	 %žBA”ÑU5KàBÈ"A”ÑU5V€
Œ"§A”ÑU5Ï€a% A”ÑU6:@Ó£)dA”ÑU7¤`
p*>ÏA”ÑU7ÄÁ,û)0A”ÑU8:À÷+‡2†A”ÑU8l )”A”ÑU9Ê`J$’)ÒA”ÑU:ÿÀ	8A”ÑU;%À1ÆL
A”ÑU<š€x$&àA”ÑU=ˆ`
§-˜A”ÑU>Tà˜‡*ÏA”ÑU?) ä
~A”ÑU?CŒ'?
A”ÑU?… DÄ
QA”ÑU?¤ %Ñ)Ó A”ÑU?¯	-ý$àA”ÑU?Ç€/%„A”ÑU?ꀪ!32 8A”ÑU@à×,â(ÓaA”ÑUA4 	#,õ1TA”ÑUBI`›#Æ A”ÑUBËÀeÎúA”ÑUC- /ÒmGA”ÑUC©àÔ(¨'©
A”ÑUCÔ€	ý:.
A”ÑUCí )ê	mA”ÑUGŒÀèZ:"A”ÑUGà>80…A”ÑUH@
µ,ÈA”ÑUH÷ í{%.A”ÑUI$À[8-,A”ÑUI2À(uÃA”ÑUI>à˜[A”ÑUIZàÜ[
A”ÑUI[ S™
A”ÑUJ, É0ª*P	A”ÑUJ¸ 3 !'A”ÑUJ¿ ÜÊ+tA”ÑUKy`‚-ÝŒxA”ÑUL®™ü#=A”ÑUM 
‰ pWRA”ÑUM Ç2ßUA”ÑUM-ÀZê¢lA”ÑUMÔ@¢4)ÌA”ÑUN¿+ !{A”ÑUO] £#7}&A”ÑUOÜ`n3|	A”ÑUPk`…Dô/A”ÑUQ
 °EšAA”ÑUQ†à9
$ª'A”ÑUQž€Š3b!”A”ÑUQ¯`š%°˜*A”ÑUR`à5Ðy(A”ÑUR¦`$#8A”ÑUSC é, _qA”ÑUSï ÂJ™$A”ÑUTËÜ"w&§A”ÑUTÜà
×P{0A”ÑUU ô¼&º
A”ÑUUˆ ­W5#A”ÑUU¸ý/DsA”ÑUV€¯ —
A”ÑUVFÌ—l4A”ÑUWªà1!…"<	A”ÑUXV€
=˜+'A”ÑUXy	!2S*A”ÑUX¶ ¦(4$A”ÑUX ß"2A”ÑUYÖ€m e2‹
A”ÑU[là.è­A”ÑU[Ë`é"ØA”ÑU\àH.ÃñA”ÑU\­`$|1Œ
A”ÑU\å`ê	I%}fA”ÑU\ó@Ù&
©/¬#‘|A”ÑU^ò€º
Q,;A”ÑU^ó 		ÛA”ÑU_4À5¼2©
A”ÑU_‡ @5
SA”ÑU_ð€71Æ[A”ÑUat 
&éQ8A”ÑUaìÀË"j
½A”ÑUc8 ¬,È\A”ÑUc”àØ3($ 
A”ÑUdSà
õ0¯¤A”ÑUdsÀ¼
ïUA”ÑUdÖ€!×30!A”ÑUe ,²æA”ÑUeà !Ï!$)A”ÑUe- 
Ç©AA”ÑUfT Ñy4)A”ÑUfm s
Ç
§6A”ÑUgWD
ÐÝA”ÑUh(`KV*²A”ÑUho 	â7ñ ˜
A”ÑUix Ô)%	/A”ÑUjK`!Ê&J
A”ÑUjß '2pbA”ÑUlZ %@A”ÑUloà¸é'NA”ÑUluà
í3ã¦
A”ÑUm4 °8¤NOA”ÑU©A 	&µÊ(A”ÑUª„àÏ
ÖHA”ÑUªÊà,2¹
A”ÑU«AŸ/@ßA”ÑU«JÀÍÜ(µA”ÑU«Ç@	ÜTMAA”ÑU¬úàÅ7&†A”ÑU­Ž2Ó+)A”ÑU®@SÃ
.A”ÑU®Ú@u©%8A”ÑU¯Ðàô4m@5A”ÑU°-À³ó*KA”ÑU°Ã€	¹IA”ÑU±¨€lYA”ÑU²€“.ÿA”ÑU³ÀkA”ÑU³`y&d ÎA”ÑU³a
…3ð,f	A”ÑU´F —ú$¬A”ÑU¶Ô`˜
A”ÑU·z@»Å
"A”ÑU¸?èF/`	A”ÑU¹L`C-C"­
A”ÑU¹y !{;A”ÑU¹„ [OåRA”ÑU¹ÆV‹"b8A”ÑUºS`
)ûÑA”ÑUº¬ ¿
A”ÑUºÝ`i 0ûA”ÑU¼OÀÒ L5A”ÑU¼œ@o¹
A”ÑU¼· ì
1?A”ÑU½ï`7
sª^A”ÑU¾Ü ( ( 	A”ÑU¿À
Û
¹0É?A”ÑU¿ÀÀ]*o
A”ÑU¿ÏɃ5†A”ÑUÀ¡àZ€*=	A”ÑUÂJ@	±q2—A”ÑUà ”
±A”ÑUÃn`!”A”ÑUæ Ä#A5–A”ÑUÃÔÀš1¸aMA”ÑUÄ« 
ž³2%A”ÑUÆ /-D3A”ÑUÆH`ŽŽ$PA”ÑUÇIÀ;(Ÿ+mA”ÑUǼ@µ!	îA”ÑUÈàq!×,Ú	A”ÑUÈq€S6_&N	A”ÑUÈÒ`	ª*âç(A”ÑUÉp`}Ë#·A”ÑUÊ 
¿
‘A”ÑUÊ@9=!^YA”ÑUÊ6€j p*àA”ÑUË sœ'6FA”ÑUË< 
ä.à(pA”ÑU˯Àñ«³	A”ÑUËÜ ¥Î$UA”ÑUÌyà!$ý˜3A”ÑUÌ× p‚%ÚA”ÑUÌà H5kjA”ÑUÍñÀ‘$ÊA”ÑU·@ßBÐ
A”ÑU΢€¾&Ü’A”ÑUÎÊÀàq0A”ÑUÎï Ø--"VA”ÑUÏY G«)ÄA”ÑUÏÈà
w/ˆO7A”ÑUÏÔ`2r+JA”ÑUÐÀ7
|ÂA”ÑUÑs€Í*kÙA”ÑUÑ… j,/tA”ÑUÑŒ€Z+%_A”ÑUÑÖða')=A”ÑUÒ’€
yÕ0=A”ÑUÓÌ	´¡ A”ÑUÓ~`{½%¾8A”ÑUÓ¡`
p 'A”ÑUÕ-à3:;6A”ÑUÕ2àCÏ0A”ÑUÕHà.2Ù A”ÑUÕo@¸
ýçA”ÑU×±à7ÌA”ÑUØ€äWB?A”ÑUÙ·à5
A”ÑUÚN`9ç6qfA”ÑUÚˆ Û†
ïA”ÑUÛC€Â†Z&A”ÑUÜ8 Ô0üSA”ÑUßr@p!ä1³ÑA”ÑUß÷À´ ´3ˆA”ÑUàí Ì$P#ÏA”ÑUã‚`öíA”ÑUåРG<UA”ÑUåë€Á*Ù
`
A”ÑUç{ˆ!û"­A”ÑUç®`°Á2A”ÑUçÿ`Í$¯/A”ÑUè®à¶
ÊA”ÑUé©`»Y%l	A”ÑUêôÑ#—4`	A”ÑUê÷@,(ùAA”ÑUëº
(èRGA”ÑUë¿à܉¸ÁA”ÑUí'	[ A”ÑUíÀÎ¹G	A”ÑUí> ÿ2­"
A”ÑUíEæYA”ÑUíÂ`Œ
‹)AA”ÑUî„ 
Q#M0"A”ÑUñ q!A”ÑUòÐ '›1A”ÑUóV`f4fÃWA”ÑUõ@†!ªùRA”ÑUõx`…CÃA”ÑU÷Z MA”ÑUùxÀBø`1A”ÑUûØ€m+;
A”ÑUüO€sÅ.µ‚A”ÑUüÍ9 ®-	
A”ÑUüæ€:"ïiA”ÑUüñÀk$A”ÑUýB
HðHA”ÑUÿ«€ñ0HA”ÑUÿÚ€V
A”ÑUÿÝ€ØRñA”ÑVg Çù6ˆA”ÑVå —*¾H	A”ÑV'@(þ,_A”ÑV° (ó.B	A”ÑV÷À

A”ÑVÁ@cƒ$dA”ÑVÇ@©,+
4A”ÑVn›¸ ‹1A”ÑV`ÝmÕA”ÑV¶ ›c2A”ÑVô Õ
µ)Ñ
A”ÑVøÀ	û Æ£ÔA”ÑV	
€t/7bA”ÑV	³—*l/äA”ÑV
˜ &"I6A”ÑV
Õ`
1*O"ó	A”ÑV„@-Q·A”ÑV³Àü¥'A”ÑVú ±è-I	A”ÑV
q`I‘
AӄV
ª`0I)!A”ÑV@0§(
A”ÑVh€
m ½(WA”ÑVl 	Ò+»1A”ÑV®`? ·A”ÑVC %3,N1A”ÑVX€XœñA”ÑVö`iîAlA”ÑVÀŽå&ñA”ÑV¥ 
Ä
ü$A”ÑVª 
-#¥A”ÑVœà
½*—7A”ÑV@€»wö
A”ÑV)`'7	òA”ÑV¸ „-é ‹6A”ÑV‡ 
#B©A”ÑV]à)2´'cA”ÑVd@	4!M-A”ÑVЀ$߯MA”ÑVZ€~!7ò;A”ÑV¯€%e	*A”ÑV	½>4A”ÑVe€X/AA”ÑVÀ¦'€2,.A”ÑV[1A”ÑV3`!&Ã#b@A”ÑVƒàþ(1ùA”ÑV·€'0’{A”ÑV³§SA”ÑVé J5gA”ÑVÿà8(jA”ÑVF`X÷A”ÑVa`…/È óA”ÑV¯`É$ò%_A”ÑVð /ëAA”ÑV ã@w#2èA”ÑV ûÀíü|ÜA”ÑV!:`À|¿KA”ÑV"I^%[(œA”ÑV"‹À	H÷"'?A”ÑV$* 
¡»'¥A”ÑV$ 
F$œ
A”ÑV%Dào©$^	A”ÑV%tà;"JA”ÑV%‚À
Š'¥$
‡A”ÑV%ûÀ”1´	A”ÑV&À‹e'±âA”ÑV'O`
`3P]A”ÑV(Àߤ5¦A”ÑV)P@Q¬,A”ÑV)e Çô4¯A”ÑV)³à¥+àeA”ÑV*yà»(1wA”ÑV*«àaP{A”ÑV+J€#$§”A”ÑV+ò€¥Ÿ%A”ÑV,-@܇3ÓÀA”ÑV,ˆà¼tA”ÑV,Õ@J&"ÀA”ÑV-C€
;º4ó
A”ÑV.U ;òÊ-A”ÑV/«àü 
éA”ÑV0€][-*A”ÑV0¹ ŒºA”ÑV1˜`
‘A”ÑV2: ·"£â:A”ÑV2? 
z$œ	A”ÑV2dáâ¸?A”ÑV3 P.þÌA”ÑV3¸ í¥1A”ÑV3ÿàÎ'½Y
A”ÑV4vÀO_A”ÑV5Ò`
Î#¢A”ÑV5ëÀü	g®	A”ÑV6Š,ÿNA”ÑV8àŸ11&ÖA”ÑV9«€	…–
õA”ÑV9ßà3*ùA”ÑV:.	n$K2§	A”ÑV:2€ò"	A”ÑV:Ô Ð$&
A”ÑV;· ;0Ù"Æ6A”ÑV;Éà²!L%ìA”ÑV;ó 
â-+¸´A”ÑV<ð€$*›æA”ÑV>@¼)DA”ÑV>¶ 	¡ý B
A”ÑV?é»#ÿ!A”ÑV?À`¬,A”ÑV?% x-N0€	A”ÑV?kÀ“YA”ÑV?
$­
A”ÑV?×`í
èA”ÑV@&@d)à3•A”ÑV@eQ	šPA”ÑV@Ì@!fwUA”ÑV@ßànú-Ü	A”ÑVA@@p#ÿ$A”ÑVB@:-wA”ÑVB-`x
LA”ÑVB@€t?m+A”ÑVCEÀ(³"ëA”ÑVCË@(Q+KA”ÑVDÐ œ+1LA”ÑVE€B¾HA”ÑVEÀàrq3LA”ÑVEø "
‚A”ÑVF´`f.ÍA”ÑVGÄ€“+ó
’A”ÑVGù€Ï'2"lA”ÑVH `›*?A”ÑVJÄ »#>=A”ÑVK´@
#„
ÇA”ÑVL!@%
¾A”ÑVLk á<c-A”ÑVMZÀ¬&,A”ÑVO=`I&L3A-A”ÑVO¸ n*Ê.U
A”ÑVOø€ÌÕ&òA”ÑVP~@,p
-A”ÑVQ	@["k0A”ÑVQ2`J>.ÃA”ÑVQQ@š*2A”ÑVQãÀ	5%!îA”ÑVST`Ïà*{A”ÑVUQ 	Ä"s)A”ÑVVÿ 	«"I	A”ÑVWÀÌ¿0A”ÑVWr@ê¢A”ÑVW¹ µ"(•A”ÑVWÉ º ·A”ÑVX2à
õEJ.A”ÑVXÛ@0%A”ÑVY ^œÊ,A”ÑVZaÀìNA”ÑVZË ©)Ã$ÈA”ÑV[=`
ã6&²A”ÑV[ô€	.@îA”ÑV\@[ã*;NA”ÑV\ð€£Ò!WA”ÑV]; 
t*Â*'A”ÑV]>@öþ_A”ÑV^à&&*@A”ÑV^k€	bþbA”ÑV^{ E…†CA”ÑV^» Ô.¹A”ÑV^¿e0÷/—	A”ÑV_ÐÀµ Ý3A”ÑV`VÉh=A”ÑV`´€X\ü7A”ÑVaK M+Ã,eTA”ÑVa‡ °“$jA”ÑVa”à
Ï"iA”ÑVbRÀ
Žð.A”ÑVbs`-!K Ú4A”ÑVc
h?:A”ÑVc} ƒ)u2/
A”ÑVcй;l
AӄVe
ÀÎ(",gA”ÑVe0 Þ&˜¹A”ÑVfàq^A”ÑVfà”'ÞÔ‘A”ÑVf[À*'ÎöA”ÑVftôq&A”ÑVf¨ ™@6	A”ÑVh[à²	¢ù	A”ÑVh… 6##1A
A”ÑVh™ ‹ø
rA”ÑViŸ`%A”ÑVj«€gÉ2ÙA”ÑVj½À˜1-,›A”ÑVjÄ@:2D u;A”ÑVk,à¢0ÎA”ÑVkc`âë’A”ÑVkº`¥3A”ÑVl¡àC')&A”ÑVl´ 	ÿ"&lA”ÑVnK@
Q…A”ÑVn¨@²A”ÑVo€%ïz
A”ÑVp 7"D ›A”ÑVpÊ
i;)?"A”ÑVpÎà	B¥ 1+A”ÑVqLàã.ÂpA”ÑVr1@
U/¹‘A”ÑVr× Î1m*ò	A”ÑVuU`
„(ZA”ÑVuà
l‚A
A”ÑVuÄ Ò2vA”ÑVv~àd¥*"‰A”ÑVwm 	!ï).
A”ÑVxä 	¹2:%5A”ÑVz 
"I,[A”ÑVz„`G1¼1A”ÑVz˜À{#ì5´	A”ÑV{Và

Á'A”ÑV{÷ 
6A”ÑV|4 j%W	•UA”ÑV|F€u.”kA”ÑV~	 ü.7yêA”ÑV~ã ˆo aA”ÑV~øÀ³ ¢!
A”ÑV€ú Ä.Ä49A”ÑV€ü d#d+Ð[A”ÑVŒ`S(ø	A”ÑVÀ5!©
?
A”ÑV‚ J4tIMA”ÑVƒIM$9$È0A”ÑVªØ€©"s’*A”ÑV¬T@ïV)¹A”ÑV¬tÀ	¥ /dA”ÑV® ‡m31A”ÑV®«€íÑ!“JA”ÑV®±
º
éA”ÑV¯àŸ!FA”ÑV°Z€
*ª®A”ÑV±&à€)v
A”ÑV²€	‰e¼DA”ÑV²`@€0A”ÑV³ŽÀ@/d ÁA”ÑV´£Àtô#'A”ÑV´Ñ 
P!˜RA”ÑVµdÀ*ûdA”ÑVµà`3GÕA”ÑVµú 
BzšA”ÑV¶q €*a1	A”ÑV¶æ`IÞA”ÑV·!€P£:A”ÑV·² ö¡ªA”ÑV·³ÀX¬2»A”ÑV¹³À'JA”ÑV»Ê2ü'
A”ÑV½,àj&o%ž
A”ÑVÀS€
W)[jA”ÑVÀ…Àwä1¿:A”ÑVÀÁ #á	A”ÑVÁNà("î0qA”ÑVÁl@ÆmóA”ÑVÁ¾@ª
•ÞA”ÑVÂë€tkA”ÑVÃ^€$4c":A”ÑVÃg^	×,A”ÑVì CÄòA”ÑVÄ´€¥Ä+šA”ÑVŘ`¢ mA”ÑVÅ¥à¡4Ä$PA”ÑVÅñ 
à‹E€A”ÑVƆ@>)l1
A”ÑVÆÛ`
d‰A”ÑVÇ€'
Øð2A”ÑVÇX€s̺DA”ÑVÈ¡@.F$A”ÑVÉ`
¶0Ê5AA”ÑVÌ4ÀF-0³A”ÑVÍ,`(,,½A”ÑVÝŽ€MêúA”ÑVÞL
·5‚$ÛeA”ÑVÞt	Ü%ÃâA”ÑVÞé`^Û0A”ÑVß¹à%0Õ%’2A”ÑVßÉà	½5)¤A”ÑVຠÔ A”ÑVàÔcVA”ÑVá`¶,,ý
A”ÑVáÒ@{6yºA”ÑVâ
 Ð
ýŒ)A”ÑVâ„à¤h4ÄA”ÑVã, +h0×A”ÑVã™à´N$#A”ÑVä§`"üA”ÑVäÛ tÏäA”ÑVäö v)+A”ÑVå µ¸-¶A”ÑVå|àõ–RA”ÑVæ3~J•¤A”ÑVæÕàrºî¾A”ÑVç(àÜ!a$²A”ÑVç„à
'†èA”ÑV甀C"
A”ÑVçõ`ø/æ#A\A”ÑVèÀ!ßXA”ÑVé, Bè¸	A”ÑWm`š!Ø31*A”ÑWàB"91
AӄWY@E
V"m?A”ÑW¾
}%DA”ÑWÜÀÐ"Í
A”ÑW™ "B	A”ÑW :)I+nA”ÑWfàø0÷)%A”ÑW˜@È4qéA”ÑWÌ`f13ÇA”ÑW€
C2£ÈA”ÑW@@Rû&ÃA”ÑWB€
”!ØA”ÑW  ¡±2A”ÑWþ±¾)H8A”ÑW5 ¢B1A”ÑWn ]Z!?A”ÑWÌ 
'•Ö	A”ÑWï j 7
žA”ÑWj@U.À+ÛOA”ÑWÀm¥*;7A”ÑW 	…öj'A”ÑWg Ž$ÈH
A”ÑW¯@Q"=,lA”ÑWöÑÒ	}A”ÑWz ¨µc
A”ÑW @Ë(LƒÜA”ÑWË`$ô	ñA”ÑWãà)ÛA”ÑW €é#"³!A”ÑW!Lê+%ÔA”ÑW#­`R3
µA”ÑW& $!%0?A”ÑW&- Ô°5¡A”ÑW&†€D
F
ìA”ÑW'¶@÷^4’
A”ÑW'ôÀ-µuA”ÑW)ûà.+Õ
A”ÑW*HÀ°Ñ)¹3A”ÑW+ìàÀ/!NA”ÑW,i&©÷A”ÑW--÷DI6A”ÑW-Î;$9šA”ÑW/D !Ö%îA”ÑW0ê
B,kK(A”ÑW1 f4i}A”ÑW2- ú A”ÑW2‘(Š19A”ÑW3`ßÏ”A”ÑW3 Ã,o÷A”ÑW3¢ Ã%j.«?A”ÑW4¯Àf Ç"9A”ÑW4´@b3˜(ÄA”ÑW5@Áˆ3	A”ÑW5ëàêä!ú"A”ÑW6@ ¯/°	A”ÑW6Ó ‚3öLA”ÑW7; /$·AA”ÑW7Œà´Æ	…;A”ÑW8‡`Š!T;=A”ÑW8à
ÖÓ:YA”ÑW;û`¢0Ó"ÕgA”ÑW<Ó 
54úwA”ÑW=þ€¦¿AA”ÑW>q0-Ã	A”ÑW>N@E ³A”ÑW>œ€×Y)q3A”ÑW@a ÆÚ)PA”ÑW@…@	í²0Ï8A”ÑW@µ@Uº~A”ÑWA8 Gþ2¬A”ÑWA<ào&ï$'	A”ÑWAe
ã$BÖA”ÑWAo ¨$kA”ÑWAË<¤%,A”ÑWB½ 1 c B	A”ÑWBð`
R6A”ÑWCŒ o'£/Ø
A”ÑWDyàž	ãLA”ÑWDÈ 
ì&|(A”ÑWDúà0u,gA”ÑWE€õ*WäA”ÑWEw€ŽªA”ÑWE¾ ï	KA”ÑWEê`"4QA”ÑWF`Š"!e&A”ÑWFê@œ&	*ƒA”ÑWG@Š/;ŸA”ÑWH4I=A”ÑWHœ`
Ï*#>A”ÑWHý@()ÐÊ?A”ÑWI§ ó%>A”ÑWJ3`º+A%JA”ÑWJ>àl+á(¡$A”ÑWJç 5Å4åA”ÑWJì ¡ÜsA”ÑWLt`˜+>+ÌA”ÑWMàŽ¼#¸5A”ÑWN`~3ž JIA”ÑWNË€6P!4A”ÑWNÛÀ
wŠXA”ÑWOj@¶ñ4Q}A”ÑWPdÀÎ$9~9A”ÑWQ0 F ÃA”ÑWQr€ç+0
b.A”ÑWQw@¼#ª´A”ÑWRƒµ&,ÕqA”ÑWR¯@
¹ò"aA”ÑWSA ð
)ðA”ÑWTC	+‚ŠBA”ÑWU|`3¹A”ÑWWÙ 4"ç+A”ÑWX&€iZ£A”ÑWX=@ïzÃkA”ÑWX«À
ÇÍA”ÑWX¬ —”)üYA”ÑWY!À‡B"vA”ÑWZ9
~)Â9A”ÑW[€˜ H'EvA”ÑW[!@	Š'(r
A”ÑW\€ˆ"9Õ	A”ÑW\ ×$$÷A”ÑW\¬à
!þ–A”ÑW]¿ s&ZA”ÑW^è`D­,Ï*A”ÑW^þ`È oHA”ÑW`L`Y&##A”ÑWa g3%Ó.A”ÑWaÉ@ä2A”ÑWe¾€*‚ÂA”ÑWfÆ€S¯=A”ÑWg`µ"ô7A”ÑWgX øÓ,§-A”ÑWg`às%™!ê	A”ÑWh»À
$
A”ÑWhï Ü,rGA”ÑWi*ßvA”ÑWiË`¸öµ(A”ÑWjcà&,	$UA”ÑWjx`)&]£A”ÑWk(€Á"*"A”ÑWkŸ•Ü	TwA”ÑWlø v}!CA”ÑWp 
4z%à1A”ÑWpü๯
Ä#A”ÑWq
  Ã?8A”ÑWrK Ì
G$MA”ÑWs¨@)-¥A”ÑWt@1fA”ÑWt( $RTwA”ÑWtM›!#ÇA”ÑWtš@LB*A”ÑWu ‰C	Ã@A”ÑWu Z}÷A”ÑWv@¤ TãQA”ÑWw|Àˆ*ýÔA”ÑWw÷`Âa5A”ÑWy€ i'ÔÞ3A”ÑWy‹ÀÔ®A”ÑWy¦ ÖE
A”ÑWy€~4-7A”ÑWyì $!Ø]A”ÑW{L@
Ϫ;A”ÑW{àÀ
¾òA”ÑW{óà1V%^$A”ÑW|Ï@	ˆ$ÂsA”ÑW}x€Å û
-
A”ÑW~ QŠ"GA”ÑWÿ 
~1ü'Õ	A”ÑW€ .ì
AGA”ÑW€o cÂÃA”ÑW€ÿ€[	­)EA”ÑW 	§&Ô{A”ÑWFà
Ç	k+»A”ÑW„@Y,¯0n%A”ÑW„, ã"2&n;A”ÑW„Y 	Ë-&A”ÑW†PÀ«V08A”ÑW†ãŸ!'=iA”ÑW†û€	mù,Å
A”ÑW‡” `+$A”ÑW‡½@¹.5
¨A”ÑW‡îé¼vA”ÑWˆÁà¨-XåA”ÑW‰› a'tE $Ò­A”ÑW¬£@+'A”ÑW­€è+Ê1/
A”ÑW®
Œ"×ýA”ÑW®G P$e2.	A”ÑW®§@nˆ×YA”ÑW®½ ‚~
A”ÑW¯ã ˜2râA”ÑW°Ÿ@/"fáA”ÑW²G@{ó*3A”ÑW³*ÀÛ-
[´A”ÑW´Í€Ñß&l
A”ÑWµe 9åA”ÑWµÁ 0|…A”ÑWµÓ€°+ˆ(átA”ÑW¶@ÿ”+¢
A”ÑW¶i ÜFA”ÑW·€ÂÚ4WA”ÑW¸ç`)
FÐA”ÑW»1€hê£FA”ÑW¼añÝ5‡A”ÑW¼„44íS$A”ÑW¼´`ÖÝ1ˆA”ÑW½ÀqcMA”ÑW½VÀ„f«A”ÑW½` œòí±A”ÑW½eàŠüÐA”ÑW¿ÉÒ‹A”ÑWÀ@ÿ$¢.MA”ÑWÀàƒÎlA”ÑWÀb`T,é©
A”ÑWÀ²`Õ#h! A”ÑWÀå˜™™ A”ÑWÁaàZ”- &A”ÑWÁÓ}-f'4A”ÑWÀ±w1lA”ÑWÃÏà1î‘A”ÑWÃß 9bÇA”ÑWÄ)@@^ÕA”ÑWÅ`²™ÿ
A”ÑWÆ]€è¶A”ÑWÆØàk*s#A”ÑWÇ'@èI
+
A”ÑWÈI@G•6A”ÑWÊc@že#Ã\A”ÑWÊe@""³A”ÑWËÂà
q0Š*kA”ÑWÌY`ð Ï,Î6A”ÑWÍF€Šˆ"ÎHA”ÑWÍÏ
}û™fA”ÑWÎ!@x£)eA”ÑWÏE ¥¥+RA”ÑWÏË`	íA”ÑWÏå€M F%>FA”ÑWÐÑ 
™
].w	A”ÑWÒ/ è"‘2—	A”ÑWÒ5€^2Œ1,A”ÑWÒqàh!ÚX0A”ÑWÒïÀ!®0zrA”ÑWÓ÷ Œq(EA”ÑWÔ€	˜-D.—A”ÑWÔàèe 3
A”ÑWÔ9`
äª!’.A”ÑWÔ€ 
^
˜A”ÑWÕ ‹2…ËA”ÑWÕAà‹IZA”ÑWÖ@çŸ(^
A”ÑWÖ:`	Ð'¸5A”ÑWÖ‡ C3QA”ÑWÖÃD2
$îA”ÑW×\à	Ê'H2"A”ÑW×zÀdDA”ÑW×Þ@å¹%	
A”ÑW×ø€
Ï5±-A”ÑWØ·`
03
‡'A”ÑWÙ
“)Æ+kA”ÑWÙ1`Í/%
A”ÑWÙU 	â"Ÿ1†A”ÑWÙ” ó}/B	A”ÑWÚ )
Þ›
A”ÑWÚÚƒ.A”ÑWÜr€
W
A”ÑWÜrÀ#
6DA”ÑWÝN€íÔA”ÑWÝn@° 64ÒA”ÑWÞæ`V/¡,«0A”ÑWß Ò/ 
A”ÑWà3à0Ú‹5A”ÑWàïÀÅ1J,>A”ÑWá@ö.\A”ÑWá”
DŠA”ÑWâMàŠ£A”ÑWâU ÷*.r
A”ÑWâð2©2âdA”ÑWãp@è*1<A”ÑWãs ¬*áWqA”ÑWä"@s%+"qA”ÑWäK`Ûõ×A”ÑWå9À£ƒ2ºA”ÑWæŽàû+>A”ÑWæ™à÷³™
A”ÑWæ¯`*;$¢2A”ÑWæ×à±+ºZ
A”ÑWé9¿ã
ªA”ÑWê@äV<	A”ÑWê˜àÙ%­bA”ÑWë°ÀÝ$D'¾	A”ÑWí
	kA”ÑWí$ ´»´A”ÑWí5`(â3U	A”ÑWíVà¯'•-E
A”ÑWíu ü(¢2'	A”ÑWí“ TÏ*ÒA”ÑWî Ç'¾¯:A”ÑWîš
¾sñA”ÑWï@€"-mA”ÑWïÉà7$°RA”ÑWñwÀ¿Ë
83A”ÑWñ–@~ã‰pA”ÑWòr¿-å
A”ÑWôSàpüA”ÑWô”`i*?A”ÑWõ* Û"e4™0A”ÑWõI€d'Ÿ%A”ÑWö˜#JA”ÑW÷»`5	Ò"ëA”ÑWø 
+!3ÒA”ÑWùàŒƒJ.A”ÑWù Ð-Ò¼/A”ÑWù†`³%ÌFA”ÑWùâ€
îž\A”ÑWý¢ V°%VA”ÑWýÄ`[*À*A”ÑWþÌà
æ/ñ A”ÑX¼àJ)êA”ÑX+`
›ù7A”ÑXl€–583A”ÑX£`È&{ÚA”ÑXô æ/ÈX9A”ÑXÿ Ý2w"*A”ÑX \†áA”ÑXl`½P A”ÑX¯ ²e÷A”ÑXè »1ÞA”ÑX	 E,B1Œ
A”ÑX	¨ ˆ1(yA”ÑX
­ ê
A”ÑXp #–	”SA”ÑX
- (P+ØA”ÑX
õÀÎ&gA”ÑX ™ž&A”ÑX†@äÊ&ÚA”ÑXH 
›YJA”ÑXz v{+ŽA”ÑX’ »*œ.¥A”ÑX³@1ï%;A”ÑXö@>ó"	A”ÑX5àwÌõ
A”ÑXbà²âA”ÑXl€ß<*Ÿ	A”ÑX–€•'Œ"#EA”ÑXÓ@&º&—A”ÑX"À	µq
C\A”ÑXK á"§$A”ÑXi`R0dA”ÑX±à	«)ÀA”ÑX²àm¥A”ÑXùÀŸ*“"A”ÑX3àE™ÍA”ÑX @³	
oA”ÑX®œx#A”ÑX¾ h
YWA”ÑX€l%S
AӄXc
Ü 7A”ÑXg ±!gh*A”ÑX®Àé2ù²sA”ÑX\ÀÙ4@
A”ÑXn@’#v('A”ÑXx€	5w¥A”ÑXª€ï ³2A”ÑXá€ÿ)Ç)^A”ÑXç +"æ'Q
A”ÑXÖ`	‘#˜
A”ÑX'`~z7UÃA”ÑX~JÀ(PA”ÑX°@°N–	A”ÑX“ Lç+?³A”ÑX×`5÷¶BA”ÑX ½`âu³$A”ÑX à ­¬'E_A”ÑX! 
¼#îs	A”ÑX"ñ@Ré.ñA”ÑX# ¥
h‰
A”ÑX#¾`0¹%׃A”ÑX%W ¥1A”ÑX%ñ@¯1ª$¨#A”ÑX&x
4%-ÌA”ÑX&£ ú!K}A”ÑX&®€(—GA”ÑX&Þ`	k+S	A”ÑX(và	$R! A”ÑX(‡ ‹-‡UA”ÑX(ŽàÓ–»A”ÑX)× Ö0O'–2A”ÑX+ð€½
I.ÚnA”ÑX,} ü',1¡A”ÑX,ËÀèÃ!
A”ÑX-@© ’
BA”ÑX- ŸèxA”ÑX.@è$( ÑA”ÑX0L€
Vû	A”ÑX0V€% yA”ÑX0²€u‰#ñ^A”ÑX2M¾
+âA”ÑX2S &
-A”ÑX3s,˜!-
A”ÑX3–`b#ƒ–A”ÑX3À
¼§£A”ÑX4I@´$åA”ÑX4›@µ#º4:A”ÑX4¶€¾.“-yA”ÑX5À¼ëA”ÑX5Aä.í¬A”ÑX5~fpÁ1A”ÑX5–`îê7éÖA”ÑX7ï@Ä3åA”ÑX8^	,jA”ÑX8W@¹"B$A”ÑX8Z 3 Þ5A”ÑX93@€,¢çA”ÑX9Æ€%·"A”ÑX:g Ò%åA”ÑX=z@´ ·
˜	A”ÑX=‚sfA”ÑX>c ›DÙA”ÑX?»ð›&ÇA”ÑXA (j
°'A”ÑXAV€¢-¬A”ÑXAg`>Þ¶A”ÑXDGàä)
A”ÑXEw€U‹'yA”ÑXF˜'O4?·A”ÑXG6Œ
A”ÑXG$`ý÷0LA”ÑXGm ¨
©+‚
A”ÑXGùÖ*\Y
AӄXI
€*_5*A”ÑXI– ½#QA”ÑXJÑà
lß1^NA”ÑXKH V!A”ÑXKJ`
<EA”ÑXKz (hA”ÑXLœ€\
n(dA”ÑXLº@
Z)3IA”ÑXLÖ /!A”ÑXM6Àl&î!A”ÑXMÕ w#>&ªA”ÑXN`
!(î
A”ÑXN•€û¸
7A”ÑXOjÀ™1:ÿA”ÑXQ`Ã
RéA”ÑXQ5¬
	A”ÑXQL¿ŽA
A”ÑXR/À‰"°ÜA”ÑXRD€-#ÙA”ÑXRvÀÄ#Ò&‹,A”ÑXRê`
î.A”ÑXTºy ;A”ÑXTâ@E3rA”ÑXU ð 7nA”ÑXU“`!.åA”ÑXVÏÀl/1'
A”ÑXXÁdüÃA”ÑXZ™€P"4#A”ÑX[ w%. A”ÑX[¦À¿"õ0A”ÑX\(à1!9UA”ÑX\{@8*£1ÅA”ÑX]5`Ä2¾è?A”ÑX]ñÀž n+oA”ÑX^Š€µ4b#¦A”ÑX^ÂÀ
¾3
2A”ÑX^Ø`°2Ã%ÏA”ÑX_h@	¯&	„LA”ÑX_Î@t5ÁA”ÑX`~@Å
Â¥A”ÑX`ˆÐ)Ö!¦A”ÑX`–@e{*â
A”ÑXbAÀò2)SA”ÑXb`v)Ø1&>#u$A”ÑXo®à£íA”ÑXpÁýì)ˆA”ÑXtY	z!Ó!:A”ÑXu6@
$ÏvA”ÑXu¼àq_A”ÑXvàÿøÚ1A”ÑXw= ‹	Z±ÔA”ÑXwµ Ø'Y$v
A”ÑXx=€.kA”ÑXylÀ5˜Æ-A”ÑXyø@|YèA”ÑXz`/q$,A”ÑXz À
¿*Î
A”ÑXz¡à	u%¬dA”ÑXzÍ 5¸ oA”ÑXzúŽT^A”ÑX|c é EA”ÑX|‡€f¤2¿A”ÑX}ä`$3Ê	A”ÑX~
 k"’#<
A”ÑX~ž€õa,@ZA”ÑX~¼@«,˜³A”ÑX~È ¼fyA”ÑX~ìÀNd2pA”ÑX"@¯~ ŸA”ÑX€Àà=@ŠA”ÑXàâØA”ÑXd &™A”ÑX‚À‚
¯*!A”ÑX‚†	œhAA”ÑXƒÇ =xbjA”ÑXƒÕÀtô .A”ÑXƒÛÀ*%{4A”ÑXƒë J#H(ŠA”ÑX„@	*P-ÏA”ÑX„f@ä)â
A”ÑX„Û`ÈŸÖA”ÑX…€%$"FA”ÑX…`ÙA”ÑX… ±9+~A”ÑX†À®2"µA”ÑXˆ†@ø4‹ [A”ÑX‰o`z2÷
A”ÑXŠl€íA”ÑX‹@S&vÙA”ÑX‹©)žfA”ÑXŒ 	B}üA”ÑXŒ+`ÛÌÑ A”ÑXŒlàb?70A”ÑXŒ¼ N4'LŒA”ÑXŽl`Ì3PTA”ÑXŽƒ`*+{A”ÑXŽñ€˜%þ^A”ÑXŽùà
Ú"A”ÑX@Ã4^"A”ÑX ~ÙA”ÑX$ ‚Ž*A”ÑX-@÷!”Æ7A”ÑX¦ààºþ,A”ÑX‘ ÇÜ#¦/A”ÑX‘ 
?	`'bA”ÑX’8àÑ2ÎA”ÑX’Ú`<.dÜA”ÑX“{àBF)BA”ÑX“ `	a+ò"A”ÑX”½”'FA”ÑX”’à
Š"HA”ÑX”ܶ)K>A”ÑX•)€û
Í
"	A”ÑX– š*	ÐFA”ÑX– `O
&ßA”ÑX–$ ÷x,ð#A”ÑX˜@ûûeOA”ÑXš}àr+þ!|A”ÑXšàS,tO	A”ÑX›ø€?3

A”ÑXÏ€õ-VAA”ÑXžàæ’3IKA”ÑXž( ]"}.CA”ÑXŸX ;7{	A”ÑXŸr€Šc05,A”ÑX X`<·/Ý
A”ÑX¡€Ê`
>BA”ÑX¡— Ë…6u-A”ÑX£AÀ-e—
A”ÑX£[€’ý_KA”ÑX£‚ ‡!Hn1A”ÑX£Š`Üjƒ
A”ÑX¥-@/!ÃtXA”ÑX¥I€Ò,•é3A”ÑX¥V@úü~A”ÑX¥c€áO“A”ÑX¥† Å%ª%å5A”ÑX¥à€
R4úA”ÑX§ö D*7¸ÎA”ÑX¨µ@\1Õ„A”ÑXª,¹A”ÑX­aÀ-¼YA”ÑX­iµ=-
A”ÑX®Ç Èç2zA”ÑX¯#À­"âA”ÑX¯ƒ`Ó+ÅñA”ÑX±"à;b	×	A”ÑX±H T~ÚA”ÑX´1À>"ä3*A”ÑX´Jàn)­$¸A”ÑX´œ
¿Â‹A”ÑX´Ä Á¼
‰
A”ÑXµƒ ’ô,=4A”ÑXµ£@ÉŽ€
A”ÑXµÉ ©¹A”ÑX¶ Ä¥/$A”ÑX¶` *:Û	A”ÑXºÚàÖ¸1€A”ÑX»3 ..WsA”ÑX»¬b1è A”ÑX»ïà-u c	A”ÑX¼[ÀÝ¡ÊA”ÑX¼gŒ"&û
A”ÑX¼ôà	ýÍ.ÂA”ÑX½@¤£
úA”ÑX½ÂÀŒ'Ž+”àA”ÑXŹ =í=CA”ÑXÇÀ`»èA”ÑXÇø ”&)íA”ÑXÉ&À: Ü73¬A”ÑXÊT€t«*æHA”ÑXʪà	uNËA”ÑXÊÊ Q*•"nA”ÑXË`C¢
A”ÑXÌ8 +
ñÿAA”ÑXÌD@`+"A”ÑX̨`\0$"+A”ÑXÌÜ Ð)þA”ÑXÍ &·WA”ÑXÎî`Ÿ"ç!A”ÑXÏG à$q4'A”ÑXÐ/`å0§.n	A”ÑXЪD,±A”ÑXÑâ`A(¾A”ÑXÒ
€	b¡
A”ÑXÔ‡€
'/‰A”ÑXÖ€:*qA”ÑXÖh _5z%?>A”ÑXÖw 	èh"A”ÑX×)`
"#³'ÃNA”ÑXØ	#Ó..A”ÑXØ7 7‹j	A”ÑXØ_@'Ð-KA”ÑXØÖ`q'<™A”ÑXØðÀ”)àþA”ÑXÙ-À!@A”ÑXÙA@O%å-«A”ÑXÚ Lf‡ÏA”ÑXÚaŒ&˜lA”ÑXÚÙq(|<A”ÑXÛ(‘¸&+A”ÑXÛ‹`j6«ÁA”ÑXÛ±€	…ÒA”ÑXܨ ->,A”ÑXÜï@'L$NA”ÑXÜøÀ6,“.§?A”ÑXÝP`i.ŸÂ
A”ÑXݵ ä„1äA”ÑXÝñ€1%lA”ÑXÞn`˜ðYA”ÑXÞ¦À)!•#ëA”ÑXߞྨ%>A”ÑXß° Á§A”ÑXßÓ€’2üA”ÑXßéÀì!_A”ÑXàC@Ür€A”ÑXàf Ö ¥61A”ÑXá¤À àw"A”ÑXã*`:–‹&A”ÑXãV ¥
'ÃjA”ÑXã©€ž#_r
A”ÑXäà;2&#€A”ÑXä #2m	A”ÑXä6 ô
ÍA”ÑXä: s
®ìA”ÑXäZ@zê#A”ÑXä@¤%ÐA”ÑXå#€##9A”ÑXåÁ€a6ýA”ÑXåú`³3¦A”ÑXç  7=1|A”ÑXè@:Ž$A”ÑXèvà3Ý"A”ÑXèÉ€(-Û/ÓA”ÑXêoàÀ"CcA”ÑXêÄà#&,3¡A”ÑXêÝà'³2e
A”ÑXëÀRy;A”ÑXìnÀa';A”ÑXí• —ÅA”ÑXíïà_«3ÙA”ÑXî* è «=A”ÑXïf „,JA”ÑXïÑ€é+]A”ÑXðÀµ†AA”ÑXðµ€´Û$¡A”ÑXñ4@QA”ÑXó> ûž&A”ÑXó¬`ì
*	A”ÑXôÀ	—‘
A”ÑXöÀó"ƒ7A”ÑXöNÀ… HA”ÑXöi`/6€JZA”ÑXö’`
 8Þ?A”ÑX÷a (î!A”ÑX÷Öà2#!‰7A”ÑXù‘Àü)î%A”ÑXùö
¸*"ª	A”ÑXûÔ N%A”ÑXþ Ö
&A”ÑXþ6 ü0;'×A”ÑXþP€ép
A”ÑXÿ@õÚ30	A”ÑYB	#^)A”ÑYë!DA”ÑY ‘¸OA”ÑY—@}¨
¹A”ÑY× ¿´,{A”ÑY<àµ
c0A”ÑYL"XA”ÑY	D`µQ H
A”ÑY	zÀ2}RA”ÑY
= k1%6A”ÑY
Ó€
M\FA”ÑYGÞ]èeA”ÑYè`T(H
AӄY
n`9ÓA”ÑY
Ý ×
,/ A”ÑY`Ã+()1A”ÑYà
.&£A”ÑYpð%$'A”ÑY‡ ¾$Û7¼A”ÑY÷@z
 'pTA”ÑY–À!#1QA”ÑY9@§+šA”ÑY‰@•“iA”ÑYÅ`ƒ$¿=A”ÑYóਠÊA”ÑY
ô)'3eA”ÑYö@7$Á*AA”ÑY{€2+i&bA”ÑYâ@
þ%™%A”ÑY=w)
ÞA”ÑY¶ Í$ê!ì8A”ÑYíÃ3A”ÑY[@ù:
?A”ÑYÊàº+)ÂA”ÑYG@BEPA”ÑY)`í8A”ÑYFàÕ¢+’A”ÑYª`|
0 0QA”ÑY,€ )1A”ÑYR 
4
é,ó
A”ÑYº@0'¯âA”ÑYÅ ]4	)ûA”ÑYÒ@¨®‘A”ÑY" ª3W
A”ÑY"™`S%¢ A”ÑY#`m‡A”ÑY$:Àu*EA”ÑY$Èà	€$»2A”ÑY$Í 9!•A”ÑY%¬ %„	›A”ÑY%Ïà´È75A”ÑY%ç`)zMA”ÑY&=€ÿ!/'èA”ÑY&è 	ј2—&A”ÑY&õ c)45qA”ÑY' +sø
A”ÑY' Á$† »
AӄY'f
t›-°A”ÑY(ÀÇ2˜'A”ÑY)`	H%*!w¿A”ÑY)! 
	W&#A”ÑY)nà´„]ÏA”ÑY*­ …=aA”ÑY,€€ò11-oA”ÑY-Q@!VÁ+A”ÑY-ÿ@ !(
A”ÑY/¤à
…+,¿1A”ÑY1f mÂA”ÑY1 ¹	þ[A”ÑY1Ü`èA”ÑY2“@24¸
AӄY3
 2 A”ÑY3' ”~*A”ÑY3¹ 	
" 	A”ÑY4.@Ô©÷A”ÑY4¡À
7¸^
A”ÑY6œ@
¯I!½A”ÑY7~ 
x¨6ÙcA”ÑY7‰wôA”ÑY7­`ó
É,Î
A”ÑY8·€ŸA”ÑY9¢ .+ôJA”ÑY:»@O![,A”ÑY;`<ÿ'#A”ÑY;xàgÛRA”ÑY;Š÷Î
A”ÑY;¬€¹s#‹A”ÑY<¯@¼!S·A”ÑY<ÐÀr$™6PA”ÑY=y )#rA”ÑY=€ Ð8,DA”ÑY=ê Û0v+QA”ÑY>ôà7-)@A”ÑY?B 	ˆ#ž#A”ÑY?t€¼î)A”ÑY?ì€lá!¢A”ÑY@þ@
hÁ&8A”ÑYAZ@À-ðA”ÑYC0Àh+rA”ÑYC@þÊ8A”ÑYC…çŽÛ`A”ÑYD C!f‘-A”ÑYDÁ`,%¥FA”ÑYEJàâ(Ý1
A”ÑYF ž(tŽA”ÑYFYÀt`A”ÑYF¹ ¢±½QA”ÑYF퀛ä!ÅIA”ÑYG€I’)A”ÑYHh#
,­A”ÑYHÛ€B1²(ÕA”ÑYI~¾4ÍA”ÑYI`s•#A”ÑYI¯ #,ˆA”ÑYJó`Wï	A”ÑYK]€	Ù2A”ÑYLs`N	yA”ÑYM„ ðþ,A”ÑYP`Z%·É)A”ÑYQPà:"1,A”ÑYQ“ 7Þ'A”ÑYR·@(/?"-A”ÑYRé /ëé)A”ÑYS`ðó!¨LA”ÑYSÀ Ý&n=
A”ÑYT°@e;5lËA”ÑY™ O'7A”ÑY™ éµA”ÑY™ì ÃÍA”ÑYšˆQi+OA”ÑY›%‰yA”ÑY›@Y'-–vA”ÑY›Ú`µ`/dA”ÑYP`XB/A”ÑY^€Í4-A”ÑYž rÜÃ.A”ÑYžøà//-šA”ÑYŸI€±½¸A”ÑYŸ•€ô6ç#Á
A”ÑY úàDêA”ÑY¡Aà‰)×3	A”ÑY¡†àz$Î6ƒ6A”ÑY¡Ý tÞ
A”ÑY¡îaGA”ÑY¢K ÂË&A”ÑY£Ê$ãQA”ÑY£ÿ ¾#ƒA”ÑY¤€ÓA”ÑY¥)ÀžºA”ÑY¥;/‚!ÈA”ÑY¥‰`
z¯iwA”ÑY¦y µ.².3
A”ÑY¦Ÿ@ù.A.øA”ÑY¦¡€–T$v-A”ÑY¦ª@
s²%
A”ÑY§ 
!c 
A”ÑY§Àº
j(}
A”ÑY§9æ&/
A”ÑY§d€+4é+ª A”ÑY¨®€ú ¼ÂA”ÑY©1`²("«,A”ÑY©‹ î+ŠA”ÑYª;@R&É5OA”ÑYªi€¡%HÝA”ÑY«d€2	óg
A”ÑY¬QÀä+øéA”ÑY¬³`—
ô%¶HA”ÑY¬ò P\ E
A”ÑY®`”°+ÆA”ÑY¯´ â©!ÌEA”ÑY¯Þà¢ÔªA”ÑY°¢à}ÃÂ]A”ÑY±þ`Â
-(A”ÑY²~àB(A”ÑY³u ßË/A”ÑY´
 ps(SA”ÑY´, 
“@-Æ>A”ÑY´Ü@3ØMA”ÑYµå€^íŠA”ÑY¶XÀ3)9¿A”ÑY· ‡%ï!A”ÑY·±:Å$Í	A”ÑY¸Î`ã3â?A”ÑY¸ûàS/	-RA”ÑY¹  ÷%.5QA”ÑY¹’‰6K(ËA”ÑY¹ý v$öA”ÑY½`“%A¦5A”ÑY¾"àH A”ÑY¿= ™%!µ	A”ÑYÀ
3#D(A”ÑYà  	ì#øA”ÑYÃåÀ
k*ÚA”ÑYÃó Û
Ñ,(A”ÑYÄ5€ñIŽA”ÑYÄâ@rÎÅ A”ÑYÄëÀè »°
A”ÑYÆ) !0¼RA”ÑYÆV Z	'A”ÑYÆÆ@©-2)A”ÑYÇ`t1ârA”ÑYÇ Á.|àA”ÑYǹÀ
¬Ì7:A”ÑYȳ +!
-A”ÑYÈ÷Ú
ú/4A”ÑYÈþ`QîaA”ÑYÉ.@؈A”ÑYÉV¨a6cA”ÑYÊJ 2*ö¡	A”ÑYÊç§'Ò´A”ÑY˵ ËÓA”ÑYÌ ¿y*:A”ÑY̱ 
!
Å/¯
AӄY폈?
/.A”ÑYÌê þ5*Ñ:A”ÑYÍm€~)’!kA”ÑY̓â'ràA”ÑYÍ„ «dªA”ÑYÍ»€Û'HiA”ÑYÎK@aø)üLA”ÑYÏ#`	q d^A”ÑYÏe Ú")lA”ÑYω 5î A”ÑYÏ“ êe.'A”ÑY϶àÁ_$œA”ÑYÑs «,ÓA”ÑYÒd ô
,KA”ÑYÓðÙ%mA”ÑYÓaà

Q!¶A”ÑYÔPàB&íÌA”ÑYÔ`f$Ú¢A”ÑYÕC@ÒLcA”ÑYÕ²¦4÷A”ÑYÖ[`ÆA”ÑYÖeÀŠ<Ð
A”ÑYÖÞ€Ø+$
ØA”ÑYÖá }Z8/A”ÑYØù@Ó3;‰0A”ÑYÙ%€).\"à‘A”ÑYÙ{€	A”ÑYÚ Â
ò
„A”ÑYÚMÀãü2A”ÑYÜ5€û)jA”ÑYÝ<`	â;"×A”ÑYÞQà
µu,mlA”ÑYÞÕ&‘5»A”ÑYßB€UBý6A”ÑY߸@Ñ"دA”ÑYà@Ç%$ÚA”ÑYá+€›ÄA”ÑYá\ ·"½ß!A”ÑYã: Y%¡A”ÑYä¯t)ƒòA”ÑYäÀ³Ã#F/A”ÑYäÅÀ
>*AA”ÑYç#`o.œ=qA”ÑYç- þ )ÀA”ÑYçz 	H—³A”ÑYèM&•@-A”ÑYè} „-ð	A”ÑYê#à&&]A”ÑYê… ¤%¡ÐA”ÑYê¯àº÷ª
A”ÑYêÅ!Ü)–	A”ÑYë 	0,¢A”ÑYìàßý,ŠæA”ÑYì
Þ/0´A”ÑYì)$ `*g%A”ÑYîÀï8"oA”ÑYîÇ 
w/&Ù:A”ÑYïs ¬3!x)A”ÑY3*«
YA”ÑYï¾`Õ"±,Õ2A”ÑYðÄ@…
øgA”ÑYðüà¶	€	A”ÑYñbà
“4A”ÑYñl $&ÆH
A”ÑYñ«Õ!¼A”ÑYñÊ hßA”ÑYñØh ­&¨
A”ÑYñïà
ì†x"A”ÑYò@A"¨
â=A”ÑYó瀚£-A”ÑYõÍ@† –A”ÑYö16
á,]UA”ÑYöSÀï$r(îŽA”ÑYøH 	ƒ)DA”ÑYø`1î HuA”ÑYù^ %§*NA”ÑYùæ	âÍ8KA”ÑYù÷À	A”ÑYúË@—ÄËA”ÑYûz€_u$A”ÑYû”À	sñ	A”ÑYü‚àg$ÆA”ÑYýKÏX"¸A”ÑYýTÀ
V‡	A”ÑYþˆàX±/)A”ÑYþâÀ×g/…A”ÑYÿƒÀ0)Æ#¦
A”ÑYÿÉ€—'ôA”ÑYÿÿÀ
ü6*%A”ÑZS€­
^A”ÑZJ‡*A”ÑZgÀ
S„ødA”ÑZ`Àˆ*JW
A”ÑZÁ@û`xA”ÑZo€óÝA”ÑZUÀU5w!),A”ÑZœ »3A”ÑZ ?e2ë
A”ÑZ›À€á-A”ÑZ	W`£æ BA”ÑZ	Š€Ú!$UA”ÑZ	¬€	C)õIA”ÑZ
™€
V°A”ÑZ
Ä@9#Å4¶A”ÑZ`@O4Ø
AӄZiێ
4“A”ÑZé@›$c2
A”ÑZôl&v+‚A”ÑZ
ê@‰#VRA”ÑZþ
"6™÷A”ÑZ ´,@áA”ÑZ"tè
u4A”ÑZb`n„*dµA”ÑZ˜@	7+ëƒA”ÑZ¸`¯ù!hA”ÑZc€5 J åA”ÑZ˜À¸!ñA”ÑZ0
í##¶A”ÑZv`Á L%3DA”ÑZ
@Æ4ï9
A”ÑZÀš )NA”ÑZ,À¥!v×A”ÑZ• "9§¬A”ÑZ®ÀY3%SA”ÑZ"`E •èA”ÑZ¸[*«
A”ÑZš·#†#ìA”ÑZøHG&A”ÑZ; i!–)0	A”ÑZ\à	–½´äA”ÑZg Kì7îA”ÑZx€(öÍA”ÑZ}€Æ$:.c!A”ÑZÆ­(¤ß}A”ÑZí ó1J.‘	A”ÑZÝÀÜ/Ž2Õ-A”ÑZ€¯7	™A”ÑZ: /NÇ
A”ÑZœàè.®	A”ÑZÎ »"ëíA”ÑZO3¶øA”ÑZ®Â+
4V A”ÑZé`$ÊO!A”ÑZú€Én0A”ÑZ€ÉIaA”ÑZ 
àSs1¨A”ÑZ SÀD$9'I9A”ÑZ"à
y,h+A”ÑZ"ÀÀ)Á.JiA”ÑZ"§@q%ûB2A”ÑZ"ÍàÄ'L	’A”ÑZ#Cà HÄA”ÑZ#Ô`÷!#½FA”ÑZ$
m5¶A”ÑZ&Ô ‚CŸ	A”ÑZ(äóq39A”ÑZ)yæ*	-A”ÑZ)Þ@3•lA”ÑZ*R€C
f!A”ÑZ*º€C
î#p7A”ÑZ+` 
É
[A”ÑZ+{À¼»"l\A”ÑZ+© ÖÖ1ZtA”ÑZ,ý òøA”ÑZ-@Ï*¨—A”ÑZ-g éõ#e
A”ÑZ.˜
Š	1)¢A”ÑZ/Z 
ÃHÅA”ÑZ1QÀs  7A”ÑZ5| Z*Ÿ1¿	A”ÑZ5øà›&¥A”ÑZ6àLg
|A”ÑZ6‹àIÑ)­A”ÑZ6›À
d0DA”ÑZ7” Ñ
1A”ÑZ7í`&×!¶A”ÑZ8!Û 89eŠA”ÑZ8OÀþ9A”ÑZ8– ®*¦à1A”ÑZ8è@1	9%²A”ÑZ9`âc+l8A”ÑZ9V@â0Ó¶A”ÑZ9ö(~A”ÑZ:Àc$¢+©A”ÑZ;V 2#¼>FA”ÑZ;’ !“…A”ÑZÀ.Ü+VA”ÑZA	 Ñ2K!LA”ÑZAk`ù*ä´%A”ÑZA«€#Ì
ÉA”ÑZB¼à+(. A”ÑZCï@1#A”ÑZDþà!H)«A”ÑZG/`ªÎ\A”ÑZGª@)^|A”ÑZH.`ØÚ)/aA”ÑZH’à	ý'éèA”ÑZH•À<2+ÂA”ÑZH÷àG)66{A”ÑZI,à:"ä1õA”ÑZI“ üÅ–A”ÑZK“ E-,ÅA”ÑZKÎ`+8#Ò
A”ÑZLF ê'A”ÑZLNàí¿A”ÑZN! ö&O#¤A”ÑZN[@nÈåA”ÑZN ¦ }7—A”ÑZQF$”+ÖA”ÑZR¥`	4ÁA”ÑZRø€-$3óA”ÑZS_`Å"Ü5UA”ÑZS£ 8/.2ÖƒA”ÑZTl€Þ*/~‚A”ÑZUà
3~¿ A”ÑZV:@u7/sfA”ÑZVFà¬à1OA”ÑZVXà‰&A–	A”ÑZWU€7™A”ÑZW»@Ö	E#A”ÑZWÃÀ‰Ÿ$ú
A”ÑZWä $¥fA”ÑZX `¬
ÕØA”ÑZX3 +9ÅBA”ÑZXÕ€î&ŠA”ÑZY³€r#1/ðA”ÑZYÁ€_	XA”ÑZYÅ€¹L2[A”ÑZZ* j.2&A”ÑZ[b Þƒ-—8A”ÑZ[k/ÍÏ4A”ÑZ[  ¦-Û
UAӄZ\ʊ#d
A”ÑZ\”À
=#^
A”ÑZ\²Àj
Ý%j
A”ÑZ]M ã2$LA”ÑZ]xÀz
œ>A”ÑZ]Ê€ê(&„A”ÑZ]Êà
Ò&Ç;A”ÑZ]Ö Ý!ê+ÿ A”ÑZ^ F'¼(xfA”ÑZ_Þ€	ÖÃ/§
A”ÑZ`iàY3z*[A”ÑZaf`1/ŒA”ÑZa¡ R¹Ò­A”ÑZb#@üzärA”ÑZbÍ@DKWA”ÑZcoà¥4L'ŽA”ÑZcƒ	¤M8™:A”ÑZd'`Ø™SA”ÑZde@Ê]A”ÑZdh )A”ÑZdž@þ
»(ÊRA”ÑZdÓ {$'
A”ÑZdû
¸#¥œ
A”ÑZe« Q*F*‰
A”ÑZf)àžÐ,v}A”ÑZfßàI*«
A”ÑZh€ó%S¸"A”ÑZh– R S'A”ÑZi ¡4&­	A”ÑZiÇ b!iÄdA”ÑZjtB*P#A”ÑZjC€	y#ùˆA”ÑZjZàø$·8A”ÑZjÅ€À$C6;+A”ÑZk ¾ÎA”ÑZk* Ê(»
A”ÑZkHà+ô#œ	A”ÑZk¢à;¹»æA”ÑZl< „"A”ÑZmö eÓ%>A”ÑZo á53˜A”ÑZoÀä01
A”ÑZoâ Øu,áA”ÑZpH€ž&	ÈA”ÑZp`€5'fGA”ÑZq9@íPHA”ÑZquà*m4S
A”ÑZr׎3í&A”ÑZsd`
„/áJ	A”ÑZt ñËDA”ÑZuxÀV$Q$6A”ÑZv?€›)Ó÷VA”ÑZvKàTÉ¿A”ÑZv_†“#¶A”ÑZvË 
½Œ
A”ÑZw7@úž/`A”ÑZxD@¥+Ô;A”ÑZy% Ñ T,cA”ÑZyÊ`B//CA”ÑZyæ â0«+‘A”ÑZz-@Ê!Q*ËA”ÑZ{F 	5A4A”ÑZ|I4
1˜A”ÑZ|\cº+oA”ÑZ|î`	•8²!·A”ÑZ}R ˜)N!èA”ÑZ}lÀ
YICA”ÑZ}v`.sÑA”ÑZ~™ ›	O, A”ÑZ7`	°$`,znA”ÑZ­à$ü¡¡A”ÑZ·ÀÛQÃA”ÑZçÀ¤!ædA”ÑZ€SÀöï3A”ÑZ€§€sй	A”ÑZ‚ÚàÈhA”ÑZ„k€á5"W?A”ÑZ„Ï AÍ%,A”ÑZ„çÀŒ*ú/mA”ÑZ…fŸ' A”ÑZ…`0þ…
A”ÑZ…Â@×$"ÓA”ÑZ†E€
-
Œ%'$A”ÑZ†nÀ
[AwA”ÑZ‡ #ú#Ž5A”ÑZ‡qà
…+Œ'þA”ÑZˆÀ
ÑwA”ÑZŠî€¨šA”ÑZ‹ð@ó'Ä04A”ÑZŒ ÞÞéA”ÑZŒí@Êì'~A”ÑZ¯@Ž^#L
A”ÑZa€
pà8¼A”ÑZ¢à*$âA”ÑZÆ`J#(&òA”ÑZNàÒA”ÑZ”; 3$±+÷A”ÑZ”\ÀSß1ŠA”ÑZ–—`Z9?gA”ÑZ—ZÀ¡/‚%A”ÑZ˜ {›ãA”ÑZ˜]À(Ï(ÔA”ÑZ™·@	È®)
A”ÑZšàD¸¡A”ÑZš™à>"ý0A”ÑZ›ª@_•¼A”ÑZœ_À	+O¹A”ÑZœ‰/˜+ñ	A”ÑZœ¶ Â
Ø)sA”ÑZœí€ "(œ	A”ÑZ†€%
ZA”ÑZÃàš/ç>A”ÑZž*2¬¦A”ÑZŸ® îLVA”ÑZ¡Ë€É½n-A”ÑZ¢ ¹)ø#ÓA”ÑZ¢p€h&&A”ÑZ¢½ i	é)¦9A”ÑZ¢ãÚ'A”ÑZ£U A-¸A”ÑZ£…À³ß%y	A”ÑZ£ù`ß¼bOA”ÑZ¤UÀõ3´PA”ÑZ¤©à‰&Á$œA”ÑZ¥-
5UA”ÑZ¥´ ™$×
A”ÑZ§‰@,Ë@
A”ÑZ¨F@'*ë
A”ÑZ¨H`E4N,.A”ÑZ¨ƒ@fs&×A”ÑZ¨‘€ô&ÿA”ÑZ©] ´5Ø#
A”ÑZ©j ,%0<
A”ÑZª# 
p.b1A”ÑZ«EÀŽ•)ÄA”ÑZ¬ªà	ç"â/A”ÑZ¬Ö@Ó%¼0QA”ÑZ­ !Â!9}A”ÑZ®u@G‹#|
A”ÑZ®Š 
y)b%A”ÑZ®£@ФlA”ÑZ®ñ€Û!7iA”ÑZ°ZS/&)A”ÑZ± è0=2ó&A”ÑZ²+@"Mg#A”ÑZ²àV'‘ÿA”ÑZ²å€
àÝA”ÑZ³_à¤
A”ÑZ³z€I7A”ÑZ³¤È'î*L	A”ÑZµ9@	(‚ _A”ÑZ¶?À^1EA”ÑZ¸Œ 6Šh!A”ÑZ¹Ù`-,ÒÊ=A”ÑZ¹ù Å#ÿ'yA”ÑZº_ 
Ø7eëA”ÑZº€"­JA”ÑZº’ 
'±7?A”ÑZ»cÀ>
¢$¥A”ÑZ»Ë€
—0(ÆA”ÑZ¼ƒ`‡t8ïA”ÑZ½)À¯
èA”ÑZ½²@Î- 	A”ÑZ½åÀs™›A”ÑZ¾V€h„A”ÑZ¿tiA”ÑZ¿Ëà•`+vA”ÑZÁ7 	³% þèA”ÑZÁ…à=9;~	A”ÑZÁ“ ”+$ÎA”ÑZÁ¢ ß³!ü“A”ÑZÁð « odA”ÑZ‚ÀÜ!\Â
A”ÑZÂ…@Â'y,¨A”ÑZ¬àäGaA”ÑZÃïàÑæ*r
A”ÑZÄnÀ	î'!
	A”ÑZÄÍÀï1ºuA”ÑZÄ× ÿ0 Y
A”ÑZÆ*` ë3¢EA”ÑZƪ`	F
A”ÑZÈEàcfitsio-4.3.1/cfitsio-config.cmake.in0000644000225700000360000000247314456514035016774 0ustar  cagordonlhea#@PACKAGE_INIT@

#set_and_check (CFITSIO_INCLUDE_DIRS "@PACKAGE_CFITSIO_INCLUDE_DIRS@")

#include ("${CMAKE_CURRENT_LIST_DIR}/cfitsioTargets.cmake")

# - Config file for the MyLib package
# It defines the following variables
#  MYLIB_INCLUDE_DIRS - include directories for MyLib
#  MYLIB_LIBRARIES    - libraries to link against
#  MYLIB_EXECUTABLE   - the bar executable

# Compute paths
#get_filename_component(CFITSIO_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
#set(CFITSIO_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")

# These are IMPORTED targets created by ${LIB_NAME}Targets.cmake
#set(CFITSIO_LIBRARIES ${LIB_NAME})

# Our library dependencies (contains definitions for IMPORTED targets)
#if(NOT TARGET ${LIB_NAME} AND NOT CFITSIO_BINARY_DIR)
#  include("${CFITSIO_CMAKE_DIR}/cfitsio-targets.cmake")
#endif()

# Compute installation prefix relative to this file.
get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_prefix "${_dir}/../.." ABSOLUTE)

# Import the targets.
include("${_prefix}/lib/cmake/cfitsio/cfitsio-targets.cmake")

# Report other information.
set(cfitsio_INCLUDE_DIRS "${_prefix}/include/cfitsio-@version@")

# Our library dependencies (contains definitions for IMPORTED targets)
if(NOT TARGET ${LIB_NAME}::${LIB_NAME})
  include("${CFITSIO_CMAKE_DIR}/cfitsio-targets.cmake")
endif()
cfitsio-4.3.1/grparser.h0000644000225700000360000001313513472024437014454 0ustar  cagordonlhea/*		T E M P L A T E   P A R S E R   H E A D E R   F I L E
		=====================================================

		by Jerzy.Borkowski@obs.unige.ch

		Integral Science Data Center
		ch. d'Ecogia 16
		1290 Versoix
		Switzerland

14-Oct-98: initial release
16-Oct-98: reference to fitsio.h removed, also removed strings after #endif
		directives to make gcc -Wall not to complain
20-Oct-98: added declarations NGP_XTENSION_SIMPLE and NGP_XTENSION_FIRST
24-Oct-98: prototype of ngp_read_line() function updated.
22-Jan-99: prototype for ngp_set_extver() function added.
20-Jun-2002 Wm Pence, added support for the HIERARCH keyword convention
            (changed NGP_MAX_NAME from (20) to FLEN_KEYWORD)
*/

#ifndef	GRPARSER_H_INCLUDED
#define	GRPARSER_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

	/* error codes  - now defined in fitsio.h */

	/* common constants definitions */

#define	NGP_ALLOCCHUNK		(1000)
#define	NGP_MAX_INCLUDE		(10)			/* include file nesting limit */
#define	NGP_MAX_COMMENT		(80)			/* max size for comment */
#define	NGP_MAX_NAME		FLEN_KEYWORD		/* max size for KEYWORD (FITS limits it to 8 chars) */
                                                        /* except HIERARCH can have longer effective keyword names */
#define	NGP_MAX_STRING		(80)			/* max size for various strings */
#define	NGP_MAX_ARRAY_DIM	(999)			/* max. number of dimensions in array */
#define NGP_MAX_FNAME           (1000)                  /* max size of combined path+fname */
#define	NGP_MAX_ENVFILES	(10000)			/* max size of CFITSIO_INCLUDE_FILES env. variable */

#define	NGP_TOKEN_UNKNOWN	(-1)			/* token type unknown */
#define	NGP_TOKEN_INCLUDE	(0)			/* \INCLUDE token */
#define	NGP_TOKEN_GROUP		(1)			/* \GROUP token */
#define	NGP_TOKEN_END		(2)			/* \END token */
#define	NGP_TOKEN_XTENSION	(3)			/* XTENSION token */
#define	NGP_TOKEN_SIMPLE	(4)			/* SIMPLE token */
#define	NGP_TOKEN_EOF		(5)			/* End Of File pseudo token */

#define	NGP_TTYPE_UNKNOWN	(0)			/* undef (yet) token type - invalid to print/write to disk */
#define	NGP_TTYPE_BOOL		(1)			/* boolean, it is 'T' or 'F' */
#define	NGP_TTYPE_STRING	(2)			/* something withing "" or starting with letter */
#define	NGP_TTYPE_INT		(3)			/* starting with digit and not with '.' */
#define	NGP_TTYPE_REAL		(4)			/* digits + '.' */
#define	NGP_TTYPE_COMPLEX	(5)			/* 2 reals, separated with ',' */
#define	NGP_TTYPE_NULL		(6)			/* NULL token, format is : NAME = / comment */
#define	NGP_TTYPE_RAW		(7)			/* HISTORY/COMMENT/8SPACES + comment string without / */

#define	NGP_FOUND_EQUAL_SIGN	(1)			/* line contains '=' after keyword name */

#define	NGP_FORMAT_OK		(0)			/* line format OK */
#define	NGP_FORMAT_ERROR	(1)			/* line format error */

#define	NGP_NODE_INVALID	(0)			/* default node type - invalid (to catch errors) */
#define	NGP_NODE_IMAGE		(1)			/* IMAGE type */
#define	NGP_NODE_ATABLE		(2)			/* ASCII table type */
#define	NGP_NODE_BTABLE		(3)			/* BINARY table type */

#define	NGP_NON_SYSTEM_ONLY	(0)			/* save all keywords except NAXIS,BITPIX,etc.. */
#define	NGP_REALLY_ALL		(1)			/* save really all keywords */

#define	NGP_XTENSION_SIMPLE	(1)			/* HDU defined with SIMPLE T */
#define	NGP_XTENSION_FIRST	(2)			/* this is first extension in template */

#define	NGP_LINE_REREAD		(1)			/* reread line */

#define	NGP_BITPIX_INVALID	(-12345)		/* default BITPIX (to catch errors) */

	/* common macro definitions */

#ifdef	NGP_PARSER_DEBUG_MALLOC

#define	ngp_alloc(x)		dal_malloc(x)
#define	ngp_free(x)		dal_free(x)
#define	ngp_realloc(x,y)	dal_realloc(x,y)

#else

#define	ngp_alloc(x)		malloc(x)
#define	ngp_free(x)		free(x)
#define	ngp_realloc(x,y)	realloc(x,y)

#endif

	/* type definitions */

typedef struct NGP_RAW_LINE_STRUCT
      {	char	*line;
	char	*name;
	char	*value;
	int	type;
	char	*comment;
	int	format;
	int	flags;
      } NGP_RAW_LINE;


typedef union NGP_TOKVAL_UNION
      {	char	*s;		/* space allocated separately, be careful !!! */
	char	b;
	int	i;
	double	d;
	struct NGP_COMPLEX_STRUCT
	 { double re;
	   double im;
	 } c;			/* complex value */
      } NGP_TOKVAL;


typedef struct NGP_TOKEN_STRUCT
      { int		type;
        char		name[NGP_MAX_NAME];
        NGP_TOKVAL	value;
        char		comment[NGP_MAX_COMMENT];
      } NGP_TOKEN;


typedef struct NGP_HDU_STRUCT
      {	int		tokcnt;
        NGP_TOKEN	*tok;
      } NGP_HDU;


typedef struct NGP_TKDEF_STRUCT
      {	char	*name;
	int	code;
      } NGP_TKDEF;


typedef struct NGP_EXTVER_TAB_STRUCT
      {	char	*extname;
	int	version;
      } NGP_EXTVER_TAB;


	/* globally visible variables declarations */

extern	NGP_RAW_LINE	ngp_curline;
extern	NGP_RAW_LINE	ngp_prevline;

extern	int		ngp_extver_tab_size;
extern	NGP_EXTVER_TAB	*ngp_extver_tab;


	/* globally visible functions declarations */

int	ngp_get_extver(char *extname, int *version);
int	ngp_set_extver(char *extname, int version);
int	ngp_delete_extver_tab(void);
int	ngp_line_from_file(FILE *fp, char **p);
int	ngp_free_line(void);
int	ngp_free_prevline(void);
int	ngp_read_line_buffered(FILE *fp);
int	ngp_unread_line(void);
int	ngp_extract_tokens(NGP_RAW_LINE *cl);
int	ngp_include_file(char *fname);
int	ngp_read_line(int ignore_blank_lines);
int	ngp_keyword_is_write(NGP_TOKEN *ngp_tok);
int     ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode);
int	ngp_hdu_init(NGP_HDU *ngph);
int	ngp_hdu_clear(NGP_HDU *ngph);
int	ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok);
int	ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol);
int	ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode);
int	ngp_read_group(fitsfile *ff, char *grpname, int parent_hn);

		/* top level API function - now defined in fitsio.h */

#ifdef __cplusplus
}
#endif

#endif
cfitsio-4.3.1/getcoluj.c0000644000225700000360000044147113472024437014446 0ustar  cagordonlhea/*  This file, getcoluj.c, contains routines that read data elements from  */
/*  a FITS image or table, with unsigned long data type.                   */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned long  nulval,     /* I - value for undefined pixels              */
   unsigned long  *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    unsigned long nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned long  *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluj(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2duj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned long  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
  unsigned long  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3duj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3duj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned long  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
  unsigned long  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    unsigned long nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TULONG, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcluj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcluj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvuj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned long nulval,    /* I - value to set undefined pixels             */
  unsigned long *array,    /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    unsigned long nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvuj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvuj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfuj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned long *array,    /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    unsigned long nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpuj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
   unsigned long  *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluj(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned long  nulval,     /* I - value for null pixels                   */
  unsigned long *array,      /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned long  *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    unsigned long dummy = 0;

    ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcluj(fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
   unsigned long  nulval,     /* I - value for null pixels if nultyp = 1     */
   unsigned long  *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int nulcheck;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    if ((tcode == TLONG) && (LONGSIZE == 32))  /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/4) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONG):
	      if (LONGSIZE == 32) {
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
                       status);
                fffi4u4((INT32BIT *) &array[next], ntodo, scale, zero,
                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
                         anynul, &array[next], status);
	      } else { /* case where sizeof(long) = 8 */
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4u4((INT32BIT *) buffer, ntodo, scale, zero,
                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
                         anynul, &array[next], status);
	      }


                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8u4( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1u4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2u4((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4u4((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8u4((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstru4((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message,FLEN_ERRMSG, 
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcluj).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcluj).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1u4(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (unsigned long) input[ii];  /* copy input */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2u4(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4u4(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 2147483648.)
        {       
           /* Instead of adding 2147483648, it is more efficient */
           /* to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
               output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
	    }
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned long) input[ii]; /* copy input */
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 2147483648.) 
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                   output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
            }
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned long) input[ii]; /* copy input */
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8u4(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    ULONGLONG ulltemp;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero ==  9223372036854775808.)
        {       
            /* The column we read contains unsigned long long values. */
            /* Instead of adding 9223372036854775808, it is more efficient */
            /* and more precise to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
 
                ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);

                if (ulltemp > ULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) ulltemp;
            }
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > ULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero ==  9223372036854775808.)
        {       
            /* The column we read contains unsigned long long values. */
            /* Instead of adding 9223372036854775808, it is more efficient */
            /* and more precise to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
 
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);

                    if (ulltemp > ULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
		    {
                        output[ii] = (unsigned long) ulltemp;
		    }
                }
            }
        }
        else if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > ULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4u4(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                      output[ii] = (unsigned long) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8u4(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                      output[ii] = (unsigned long) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstru4(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DULONG_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 0;
        }
        else if (dvalue > DULONG_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = ULONG_MAX;
        }
        else
            output[ii] = (unsigned long) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}

/* ======================================================================== */
/*      the following routines support the 'long long' data type            */
/* ======================================================================== */

/*--------------------------------------------------------------------------*/
int ffgpvujj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            ULONGLONG  nulval, /* I - value for undefined pixels              */
            ULONGLONG  *array, /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    ULONGLONG nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TULONGLONG, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclujj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfujj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            ULONGLONG  *array, /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;
    ULONGLONG dummy = 0;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TULONGLONG, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclujj(fptr, 2, row, firstelem, nelem, 1, 2, dummy,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2dujj(fitsfile *fptr, /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           ULONGLONG nulval ,/* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           ULONGLONG  *array,/* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3dujj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3dujj(fitsfile *fptr, /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           ULONGLONG nulval, /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           ULONGLONG  *array,/* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    ULONGLONG nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TULONGLONG, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgclujj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgclujj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvujj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           ULONGLONG nulval,/* I - value to set undefined pixels             */
           ULONGLONG *array,/* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    ULONGLONG nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG, "NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TULONGLONG, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgclujj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfujj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           ULONGLONG *array,/* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    ULONGLONG nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

         fits_read_compressed_img(fptr, TULONGLONG, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvujj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgclujj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpujj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            ULONGLONG  *array, /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    ULONGLONG dummy = 0;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclujj(fptr, 1, row, firstelem, nelem, 1, 1, dummy,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvujj(fitsfile *fptr,  /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           ULONGLONG  nulval, /* I - value for null pixels                   */
           ULONGLONG *array,  /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfujj(fitsfile *fptr,  /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           ULONGLONG  *array, /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    ULONGLONG dummy = 0;

    ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgclujj( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            ULONGLONG  nulval, /* I - value for null pixels if nultyp = 1     */
            ULONGLONG  *array, /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[81];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    convert = 1;

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) &array[next],
                       status);
                fffi8u8((LONGLONG *) &array[next], ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                           anynul, &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4u8((INT32BIT *) buffer, ntodo, scale, zero, 
                        nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
                        anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1u8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2u8((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4u8((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8u8((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstru8((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, 81, 
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message, 81,
            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message, 81,
            "Error reading elements %.0f thru %.0f from image (ffgclj).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1u8(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
	    {
	        if (input[ii] < 0) 
		{
                   *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
		else
		{
                    output[ii] = (ULONGLONG) input[ii];  /* copy input to output */
		}
	    }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (ULONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else if (input[ii] < 0) 
		{
                   *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
		else
                    output[ii] = (ULONGLONG) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2u8(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
	    {
	        if (input[ii] < 0) 
		{
                   *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
		else
		{
                    output[ii] = (ULONGLONG) input[ii];   /* copy input to output */
                }
	    }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (LONGLONG) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4u8(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
	    {
	        if (input[ii] < 0) 
		{
                   *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
		else
		{
                   output[ii] = (ULONGLONG) input[ii];   /* copy input to output */
		}
	    }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
	        else if (input[ii] < 0) 
		{
                   *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
		{
                    output[ii] = (ULONGLONG) input[ii];
		}
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8u8(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero ==  9223372036854775808.)
        {       
            /* The column we read contains unsigned long long values. */
            /* Instead of adding 9223372036854775808, it is more efficient */
            /* and more precise to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
                output[ii] = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
            }
        }
        else        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
	    {
	    	if (input[ii] < 0) 
		{
                   *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
		else
		{
                    output[ii] =  input[ii];   /* copy input to output */
		}
	    }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (ULONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero ==  9223372036854775808.)
        {       
            /* The column we read contains unsigned long long values. */
            /* Instead of adding 9223372036854775808, it is more efficient */
            /* and more precise to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {

                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                   output[ii] = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
                }
            }
        }
        else if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
		{
 	    	    if (input[ii] < 0) 
		    {
                       *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
		    else
		    {
                        output[ii] =  input[ii];   /* copy input to output */
		    }
		}
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4u8(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (ULONGLONG) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (ULONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8u8(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (ULONGLONG) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT64_MAX;
                }
                else
                    output[ii] = (ULONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT64_MAX;
                    }
                    else
                        output[ii] = (ULONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstru8(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            ULONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[81];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')    /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          sprintf(message, "Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, 81, "Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < 0)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 0;
        }
        else if (dvalue > DULONGLONG_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = UINT64_MAX;
        }
        else
            output[ii] = (ULONGLONG) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio-4.3.1/iter_a.f0000644000225700000360000001533213472024437014071 0ustar  cagordonlhea      program f77iterate_a

      external flux_rate
      integer ncols
      parameter (ncols=3)
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), offset, rows_per_loop, status
      character*70 colname(ncols)
      integer iunit, blocksize
      character*80 fname

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------


      iunit = 15

      units(1) = iunit
      units(2) = iunit
      units(3) = iunit

C open the file
      fname = 'iter_a.fit'
      call ftopen(iunit,fname,1,blocksize,status)

C move to the HDU containing the rate table
      call ftmnhd(iunit, BINARY_TBL, 'RATE', 0, status)

C Select iotypes for column data
      iotype(1) = InputCol
      iotype(2) = InputCol
      iotype(3) = OutputCol

C Select desired datatypes for column data
      datatype(1) = TINT
      datatype(2) = TFLOAT
      datatype(3) = TFLOAT

C find the column number corresponding to each column
      call ftgcno( iunit, 0, 'counts', colnum(1), status )
      call ftgcno( iunit, 0, 'time', colnum(2), status )
      call ftgcno( iunit, 0, 'rate', colnum(3), status )

C use default optimum number of rows
      rows_per_loop = 0
      offset = 0

C apply the rate function to each row of the table
      print *, 'Calling iterator function...', status

C although colname is not being used, still need to send a string
C array in the function
      call ftiter( ncols, units, colnum, colname, datatype, iotype,
     &      offset, rows_per_loop, flux_rate, 3, status )

      call ftclos(iunit, status)
      stop
      end

C***************************************************************************
C   Sample iterator function that calculates the output flux 'rate' column
C   by dividing the input 'counts' by the 'time' column.
C   It also applies a constant deadtime correction factor if the 'deadtime'
C   keyword exists.  Finally, this creates or updates the 'LIVETIME'
C   keyword with the sum of all the individual integration times.
C***************************************************************************
      subroutine flux_rate(totalrows, offset, firstrow, nrows, ncols,
     &     units, colnum, datatype, iotype, repeat, status, userData,
     &     counts, interval, rate )

      integer totalrows, offset, firstrow, nrows, ncols
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), repeat(ncols)
      integer userData

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      integer counts(*)
      real interval(*),rate(*)

      integer ii, status
      character*80 comment

C**********************************************************************
C  must preserve these values between calls
      real deadtime, livetime
      common /fluxblock/ deadtime, livetime
C**********************************************************************

      if (status .ne. 0) return

C    --------------------------------------------------------
C      Initialization procedures: execute on the first call  
C    --------------------------------------------------------
      if (firstrow .eq. 1) then
         if (ncols .ne. 3) then
C     wrong number of columns
            status = -1
            return
         endif

         if (datatype(1).ne.TINT .or. datatype(2).ne.TFLOAT .or.
     &        datatype(3).ne.TFLOAT ) then
C     bad data type
            status = -2
            return
         endif

C     try to get the deadtime keyword value
         call ftgkye( units(1), 'DEADTIME', deadtime, comment, status )

         if (status.ne.0) then
C     default deadtime if keyword doesn't exist
            deadtime = 1.0
            status = 0
         elseif (deadtime .lt. 0.0 .or. deadtime .gt. 1.0) then
C     bad deadtime value
            status = -3
            return
         endif

         print *, 'deadtime = ', deadtime

         livetime = 0.0
      endif

C    --------------------------------------------
C      Main loop: process all the rows of data
C    --------------------------------------------
      
C     NOTE: 1st element of array is the null pixel value!
C     Loop over elements 2 to nrows+1, not 1 to nrows.
      
C     this version ignores null values

C     set the output null value to zero to ignore nulls */
      rate(1) = 0.0
      do 10 ii = 2,nrows+1
         if ( interval(ii) .gt. 0.0) then
           rate(ii) = counts(ii) / interval(ii) / deadtime
           livetime = livetime + interval(ii)
        else
C     Nonsensical negative time interval
           status = -3
           return
        endif
 10   continue

C    -------------------------------------------------------
C      Clean up procedures:  after processing all the rows  
C    -------------------------------------------------------

      if (firstrow + nrows - 1 .eq. totalrows) then
C     update the LIVETIME keyword value

         call ftukye( units(1),'LIVETIME', livetime, 3,
     &        'total integration time', status )
         print *,'livetime = ', livetime

      endif
 
      return
      end
cfitsio-4.3.1/region.c0000644000225700000360000016003714075614240014106 0ustar  cagordonlhea#include 
#include 
#include 
#include 
#include 
#include "fitsio2.h"
#include "region.h"
static int Pt_in_Poly( double x, double y, int nPts, double *Pts );

/*---------------------------------------------------------------------------*/
int fits_read_rgnfile( const char *filename,
            WCSdata    *wcs,
            SAORegion  **Rgn,
            int        *status )
/*  Read regions from either a FITS or ASCII region file and return the information     */
/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
/*  region coordinates to pixels.  Return an error if region is in degrees   */
/*  but no WCS data is provided.                                             */
/*---------------------------------------------------------------------------*/
{
  fitsfile *fptr;
  int tstatus = 0;

  if( *status ) return( *status );

  /* try to open as a FITS file - if that doesn't work treat as an ASCII file */

  fits_write_errmark();
  if ( ffopen(&fptr, filename, READONLY, &tstatus) ) {
    fits_clear_errmark();
    fits_read_ascii_region(filename, wcs, Rgn, status);
  } else {
    fits_read_fits_region(fptr, wcs, Rgn, status);
  }

  return(*status);

}
/*---------------------------------------------------------------------------*/
int fits_read_ascii_region( const char *filename,
			    WCSdata    *wcs,
			    SAORegion  **Rgn,
			    int        *status )
/*  Read regions from a SAO-style region file and return the information     */
/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
/*  region coordinates to pixels.  Return an error if region is in degrees   */
/*  but no WCS data is provided.                                             */
/*---------------------------------------------------------------------------*/
{
   char     *currLine;
   char     *namePtr, *paramPtr, *currLoc;
   char     *pX, *pY, *endp;
   long     allocLen, lineLen, hh, mm, dd;
   double   *coords, X, Y, x, y, ss, div, xsave= 0., ysave= 0.;
   int      nParams, nCoords, negdec;
   int      i, done;
   FILE     *rgnFile;
   coordFmt cFmt;
   SAORegion *aRgn;
   RgnShape *newShape, *tmpShape;

   if( *status ) return( *status );

   aRgn = (SAORegion *)malloc( sizeof(SAORegion) );
   if( ! aRgn ) {
      ffpmsg("Couldn't allocate memory to hold Region file contents.");
      return(*status = MEMORY_ALLOCATION );
   }
   aRgn->nShapes    =    0;
   aRgn->Shapes     = NULL;
   if( wcs && wcs->exists )
      aRgn->wcs = *wcs;
   else
      aRgn->wcs.exists = 0;

   cFmt = pixel_fmt; /* set default format */

   /*  Allocate Line Buffer  */

   allocLen = 512;
   currLine = (char *)malloc( allocLen * sizeof(char) );
   if( !currLine ) {
      free( aRgn );
      ffpmsg("Couldn't allocate memory to hold Region file contents.");
      return(*status = MEMORY_ALLOCATION );
   }

   /*  Open Region File  */

   if( (rgnFile = fopen( filename, "r" ))==NULL ) {
      snprintf(currLine,allocLen,"Could not open Region file %s.",filename);
      ffpmsg( currLine );
      free( currLine );
      free( aRgn );
      return( *status = FILE_NOT_OPENED );
   }
   
   /*  Read in file, line by line  */
   /*  First, set error status in case file is empty */ 
   *status = FILE_NOT_OPENED;

   while( fgets(currLine,allocLen,rgnFile) != NULL ) {

      /* reset status if we got here */
      *status = 0;

      /*  Make sure we have a full line of text  */

      lineLen = strlen(currLine);
      while( lineLen==allocLen-1 && currLine[lineLen-1]!='\n' ) {
         currLoc = (char *)realloc( currLine, 2 * allocLen * sizeof(char) );
         if( !currLoc ) {
            ffpmsg("Couldn't allocate memory to hold Region file contents.");
            *status = MEMORY_ALLOCATION;
            goto error;
         } else {
            currLine = currLoc;
         }
         fgets( currLine+lineLen, allocLen+1, rgnFile );
         allocLen += allocLen;
         lineLen  += strlen(currLine+lineLen);
      }

      currLoc = currLine;
      if( *currLoc == '#' ) {

         /*  Look to see if it is followed by a format statement...  */
         /*  if not skip line                                        */

         currLoc++;
         while( isspace(*currLoc) ) currLoc++;
         if( !fits_strncasecmp( currLoc, "format:", 7 ) ) {
            if( aRgn->nShapes ) {
               ffpmsg("Format code encountered after reading 1 or more shapes.");
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
            currLoc += 7;
            while( isspace(*currLoc) ) currLoc++;
            if( !fits_strncasecmp( currLoc, "pixel", 5 ) ) {
               cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( currLoc, "degree", 6 ) ) {
               cFmt = degree_fmt;
            } else if( !fits_strncasecmp( currLoc, "hhmmss", 6 ) ) {
               cFmt = hhmmss_fmt;
            } else if( !fits_strncasecmp( currLoc, "hms", 3 ) ) {
               cFmt = hhmmss_fmt;
            } else {
               ffpmsg("Unknown format code encountered in region file.");
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
         }

      } else if( !fits_strncasecmp( currLoc, "glob", 4 ) ) {
		  /* skip lines that begin with the word 'global' */

      } else {

         while( *currLoc != '\0' ) {

            namePtr  = currLoc;
            paramPtr = NULL;
            nParams  = 1;

            /*  Search for closing parenthesis  */

            done = 0;
            while( !done && !*status && *currLoc ) {
               switch (*currLoc) {
               case '(':
                  *currLoc = '\0';
                  currLoc++;
                  if( paramPtr )   /* Can't have two '(' in a region! */
                     *status = 1;
                  else
                     paramPtr = currLoc;
                  break;
               case ')':
                  *currLoc = '\0';
                  currLoc++;
                  if( !paramPtr )  /* Can't have a ')' without a '(' first */
                     *status = 1;
                  else
                     done = 1;
                  break;
               case '#':
               case '\n':
                  *currLoc = '\0';
                  if( !paramPtr )  /* Allow for a blank line */
                     done = 1;
                  break;
               case ':':  
                  currLoc++;
                  if ( paramPtr ) cFmt = hhmmss_fmt; /* set format if parameter has : */
                  break;
               case 'd':
                  currLoc++;
                  if ( paramPtr ) cFmt = degree_fmt; /* set format if parameter has d */  
                  break;
               case ',':
                  nParams++;  /* Fall through to default */
               default:
                  currLoc++;
                  break;
               }
            }
            if( *status || !done ) {
               ffpmsg( "Error reading Region file" );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }

            /*  Skip white space in region name  */

            while( isspace(*namePtr) ) namePtr++;

            /*  Was this a blank line? Or the end of the current one  */

            if( ! *namePtr && ! paramPtr ) continue;

            /*  Check for format code at beginning of the line */

            if( !fits_strncasecmp( namePtr, "image;", 6 ) ) {
				namePtr += 6;
				cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( namePtr, "physical;", 9 ) ) {
                                namePtr += 9;
                                cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( namePtr, "linear;", 7 ) ) {
                                namePtr += 7;
                                cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( namePtr, "fk4;", 4 ) ) {
				namePtr += 4;
				cFmt = degree_fmt;
            } else if( !fits_strncasecmp( namePtr, "fk5;", 4 ) ) {
				namePtr += 4;
				cFmt = degree_fmt;
            } else if( !fits_strncasecmp( namePtr, "icrs;", 5 ) ) {
				namePtr += 5;
				cFmt = degree_fmt;

            /* the following 5 cases support region files created by POW 
	       (or ds9 Version 4.x) which
               may have lines containing  only a format code, not followed
               by a ';' (and with no region specifier on the line).  We use
               the 'continue' statement to jump to the end of the loop and
               then continue reading the next line of the region file. */

            } else if( !fits_strncasecmp( namePtr, "fk5", 3 ) ) {
				cFmt = degree_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "fk4", 3 ) ) {
				cFmt = degree_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "icrs", 4 ) ) {
				cFmt = degree_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "image", 5 ) ) {
				cFmt = pixel_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "physical", 8 ) ) {
				cFmt = pixel_fmt;
                                continue;  /* supports POW region file format */


            } else if( !fits_strncasecmp( namePtr, "galactic;", 9 ) ) {
               ffpmsg( "Galactic region coordinates not supported" );
               ffpmsg( namePtr );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            } else if( !fits_strncasecmp( namePtr, "ecliptic;", 9 ) ) {
               ffpmsg( "ecliptic region coordinates not supported" );
               ffpmsg( namePtr );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }

            /**************************************************/
            /*  We've apparently found a region... Set it up  */
            /**************************************************/

            if( !(aRgn->nShapes % 10) ) {
               if( aRgn->Shapes )
                  tmpShape = (RgnShape *)realloc( aRgn->Shapes,
                                                  (10+aRgn->nShapes)
                                                  * sizeof(RgnShape) );
               else
                  tmpShape = (RgnShape *) malloc( 10 * sizeof(RgnShape) );
               if( tmpShape ) {
                  aRgn->Shapes = tmpShape;
               } else {
                  ffpmsg( "Failed to allocate memory for Region data");
                  *status = MEMORY_ALLOCATION;
                  goto error;
               }

            }
            newShape        = &aRgn->Shapes[aRgn->nShapes++];
            newShape->sign  = 1;
            newShape->shape = point_rgn;
	    for (i=0; i<8; i++) newShape->param.gen.p[i] = 0.0;
	    newShape->param.gen.a = 0.0;
	    newShape->param.gen.b = 0.0;
	    newShape->param.gen.sinT = 0.0;
	    newShape->param.gen.cosT = 0.0;

            while( isspace(*namePtr) ) namePtr++;
            
			/*  Check for the shape's sign  */

            if( *namePtr=='+' ) {
               namePtr++;
            } else if( *namePtr=='-' ) {
               namePtr++;
               newShape->sign = 0;
            }

            /* Skip white space in region name */

            while( isspace(*namePtr) ) namePtr++;
            if( *namePtr=='\0' ) {
               ffpmsg( "Error reading Region file" );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
            lineLen = strlen( namePtr ) - 1;
            while( isspace(namePtr[lineLen]) ) namePtr[lineLen--] = '\0';

            /*  Now identify the region  */

            if(        !fits_strcasecmp( namePtr, "circle"  ) ) {
               newShape->shape = circle_rgn;
               if( nParams != 3 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "annulus" ) ) {
               newShape->shape = annulus_rgn;
               if( nParams != 4 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "ellipse" ) ) {
               if( nParams < 4 || nParams > 8 ) {
                  *status = PARSE_SYNTAX_ERR;
	       } else if ( nParams < 6 ) {
		 newShape->shape = ellipse_rgn;
		 newShape->param.gen.p[4] = 0.0;
	       } else {
		 newShape->shape = elliptannulus_rgn;
		 newShape->param.gen.p[6] = 0.0;
		 newShape->param.gen.p[7] = 0.0;
	       }
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "elliptannulus" ) ) {
               newShape->shape = elliptannulus_rgn;
               if( !( nParams==8 || nParams==6 ) )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[6] = 0.0;
               newShape->param.gen.p[7] = 0.0;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "box"    ) 
                    || !fits_strcasecmp( namePtr, "rotbox" ) ) {
	       if( nParams < 4 || nParams > 8 ) {
		 *status = PARSE_SYNTAX_ERR;
	       } else if ( nParams < 6 ) {
		 newShape->shape = box_rgn;
		 newShape->param.gen.p[4] = 0.0;
	       } else {
		  newShape->shape = boxannulus_rgn;
		  newShape->param.gen.p[6] = 0.0;
		  newShape->param.gen.p[7] = 0.0;
	       }
	       nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "rectangle"    )
                    || !fits_strcasecmp( namePtr, "rotrectangle" ) ) {
               newShape->shape = rectangle_rgn;
               if( nParams < 4 || nParams > 5 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[4] = 0.0;
               nCoords = 4;
            } else if( !fits_strcasecmp( namePtr, "diamond"    )
                    || !fits_strcasecmp( namePtr, "rotdiamond" )
                    || !fits_strcasecmp( namePtr, "rhombus"    )
                    || !fits_strcasecmp( namePtr, "rotrhombus" ) ) {
               newShape->shape = diamond_rgn;
               if( nParams < 4 || nParams > 5 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[4] = 0.0;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "sector"  )
                    || !fits_strcasecmp( namePtr, "pie"     ) ) {
               newShape->shape = sector_rgn;
               if( nParams != 4 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "point"   ) ) {
               newShape->shape = point_rgn;
               if( nParams != 2 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "line"    ) ) {
               newShape->shape = line_rgn;
               if( nParams != 4 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 4;
            } else if( !fits_strcasecmp( namePtr, "polygon" ) ) {
               newShape->shape = poly_rgn;
               if( nParams < 6 || (nParams&1) )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = nParams;
            } else if( !fits_strcasecmp( namePtr, "panda" ) ) {
               newShape->shape = panda_rgn;
               if( nParams != 8 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "epanda" ) ) {
               newShape->shape = epanda_rgn;
               if( nParams < 10 || nParams > 11 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[10] = 0.0;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "bpanda" ) ) {
               newShape->shape = bpanda_rgn;
               if( nParams < 10 || nParams > 11 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[10] = 0.0;
               nCoords = 2;
            } else {
               ffpmsg( "Unrecognized region found in region file:" );
               ffpmsg( namePtr );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
            if( *status ) {
               ffpmsg( "Wrong number of parameters found for region" );
               ffpmsg( namePtr );
               goto error;
            }

            /*  Parse Parameter string... convert to pixels if necessary  */

            if( newShape->shape==poly_rgn ) {
               newShape->param.poly.Pts = (double *)malloc( nParams
                                                            * sizeof(double) );
               if( !newShape->param.poly.Pts ) {
                  ffpmsg(
                      "Could not allocate memory to hold polygon parameters" );
                  *status = MEMORY_ALLOCATION;
                  goto error;
               }
               newShape->param.poly.nPts = nParams;
               coords = newShape->param.poly.Pts;
            } else
               coords = newShape->param.gen.p;

            /*  Parse the initial "WCS?" coordinates  */
            for( i=0; iexists ) {
                     ffpmsg("WCS information needed to convert region coordinates.");
                     *status = NO_WCS_KEY;
                     goto error;
                  }
                  
                  if( ffxypx(  X,  Y, wcs->xrefval, wcs->yrefval,
                                      wcs->xrefpix, wcs->yrefpix,
                                      wcs->xinc,    wcs->yinc,
                                      wcs->rot,     wcs->type,
                              &x, &y, status ) ) {
                     ffpmsg("Error converting region to pixel coordinates.");
                     goto error;
                  }
                  X = x; Y = y;
               }
               coords[i]   = X;
               coords[i+1] = Y;

            }

            /*  Read in remaining parameters...  */

            for( ; ixrefval, wcs->yrefval,
			       wcs->xrefpix, wcs->yrefpix,
			       wcs->xinc,    wcs->yinc,
			       wcs->rot,     wcs->type,
                               &x, &y, status ) ) {
		     ffpmsg("Error converting region to pixel coordinates.");
		     goto error;
		  }
		 
		  coords[i] = sqrt( pow(x-coords[0],2) + pow(y-coords[1],2) );

               }
            }

	    /* special case for elliptannulus and boxannulus if only one angle
	       was given */

	    if ( (newShape->shape == elliptannulus_rgn || 
		  newShape->shape == boxannulus_rgn ) && nParams == 7 ) {
	      coords[7] = coords[6];
	    }

            /* Also, correct the position angle for any WCS rotation:  */
            /*    If regions are specified in WCS coordintes, then the angles */
            /*    are relative to the WCS system, not the pixel X,Y system */

	    if( cFmt!=pixel_fmt ) {	    
	      switch( newShape->shape ) {
	      case sector_rgn:
	      case panda_rgn:
		coords[2] += (wcs->rot);
		coords[3] += (wcs->rot);
		break;
	      case box_rgn:
	      case rectangle_rgn:
	      case diamond_rgn:
	      case ellipse_rgn:
		coords[4] += (wcs->rot);
		break;
	      case boxannulus_rgn:
	      case elliptannulus_rgn:
		coords[6] += (wcs->rot);
		coords[7] += (wcs->rot);
		break;
	      case epanda_rgn:
	      case bpanda_rgn:
		coords[2] += (wcs->rot);
		coords[3] += (wcs->rot);
		coords[10] += (wcs->rot);
              default:
                break;
	      }
	    }

	    /* do some precalculations to speed up tests */

	    fits_setup_shape(newShape);

         }  /* End of while( *currLoc ) */
/*
  if (coords)printf("%.8f %.8f %.8f %.8f %.8f\n",
   coords[0],coords[1],coords[2],coords[3],coords[4]); 
*/
      }  /* End of if...else parse line */
   }   /* End of while( fgets(rgnFile) ) */

   /* set up component numbers */

   fits_set_region_components( aRgn );

error:

   if( *status ) {
      fits_free_region( aRgn );
   } else {
      *Rgn = aRgn;
   }

   fclose( rgnFile );
   free( currLine );

   return( *status );
}

/*---------------------------------------------------------------------------*/
int fits_in_region( double    X,
            double    Y,
            SAORegion *Rgn )
/*  Test if the given point is within the region described by Rgn.  X and    */
/*  Y are in pixel coordinates.                                              */
/*---------------------------------------------------------------------------*/
{
   double x, y, dx, dy, xprime, yprime, r, th;
   RgnShape *Shapes;
   int i, cur_comp;
   int result, comp_result;

   Shapes = Rgn->Shapes;

   result = 0;
   comp_result = 0;
   cur_comp = Rgn->Shapes[0].comp;

   for( i=0; inShapes; i++, Shapes++ ) {

     /* if this region has a different component number to the last one  */
     /*	then replace the accumulated selection logical with the union of */
     /*	the current logical and the total logical. Reinitialize the      */
     /* temporary logical.                                               */

     if ( i==0 || Shapes->comp != cur_comp ) {
       result = result || comp_result;
       cur_comp = Shapes->comp;
       /* if an excluded region is given first, then implicitly   */
       /* assume a previous shape that includes the entire image. */
       comp_result = !Shapes->sign;
     }

    /* only need to test if  */
    /*   the point is not already included and this is an include region, */
    /* or the point is included and this is an excluded region */

    if ( (!comp_result && Shapes->sign) || (comp_result && !Shapes->sign) ) { 

      comp_result = 1;

      switch( Shapes->shape ) {

      case box_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = 0.5 * Shapes->param.gen.p[2];
         dy = 0.5 * Shapes->param.gen.p[3];
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
            comp_result = 0;
         break;

      case boxannulus_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = 0.5 * Shapes->param.gen.p[4];
         dy = 0.5 * Shapes->param.gen.p[5];
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) ) {
	   comp_result = 0;
	 } else {
	   /* Repeat test for inner box */
	   x =  xprime * Shapes->param.gen.b + yprime * Shapes->param.gen.a;
	   y = -xprime * Shapes->param.gen.a + yprime * Shapes->param.gen.b;
	   
	   dx = 0.5 * Shapes->param.gen.p[2];
	   dy = 0.5 * Shapes->param.gen.p[3];
	   if( (x >= -dx) && (x <= dx) && (y >= -dy) && (y <= dy) )
	     comp_result = 0;
	 }
         break;

      case rectangle_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[5];
         yprime = Y - Shapes->param.gen.p[6];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = Shapes->param.gen.a;
         dy = Shapes->param.gen.b;
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
            comp_result = 0;
         break;

      case diamond_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = 0.5 * Shapes->param.gen.p[2];
         dy = 0.5 * Shapes->param.gen.p[3];
         r  = fabs(x/dx) + fabs(y/dy);
         if( r > 1 )
            comp_result = 0;
         break;

      case circle_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         r  = x*x + y*y;
         if ( r > Shapes->param.gen.a )
            comp_result = 0;
         break;

      case annulus_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         r = x*x + y*y;
         if ( r < Shapes->param.gen.a || r > Shapes->param.gen.b )
            comp_result = 0;
         break;

      case sector_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         if( x || y ) {
            r = atan2( y, x ) * RadToDeg;
            if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
               if( r < Shapes->param.gen.p[2] || r > Shapes->param.gen.p[3] )
                  comp_result = 0;
            } else {
               if( r < Shapes->param.gen.p[2] && r > Shapes->param.gen.p[3] )
                  comp_result = 0;
            }
         }
         break;

      case ellipse_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         x /= Shapes->param.gen.p[2];
         y /= Shapes->param.gen.p[3];
         r = x*x + y*y;
         if( r>1.0 )
            comp_result = 0;
         break;

      case elliptannulus_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to outer ellipse's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         x /= Shapes->param.gen.p[4];
         y /= Shapes->param.gen.p[5];
         r = x*x + y*y;
         if( r>1.0 )
            comp_result = 0;
         else {
            /*  Repeat test for inner ellipse  */
            x =  xprime * Shapes->param.gen.b + yprime * Shapes->param.gen.a;
            y = -xprime * Shapes->param.gen.a + yprime * Shapes->param.gen.b;

            x /= Shapes->param.gen.p[2];
            y /= Shapes->param.gen.p[3];
            r = x*x + y*y;
            if( r<1.0 )
               comp_result = 0;
         }
         break;

      case line_rgn:
         /*  Shift origin to first point of line  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to line's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         if( (y < -0.5) || (y >= 0.5) || (x < -0.5)
             || (x >= Shapes->param.gen.a) )
            comp_result = 0;
         break;

      case point_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         if ( (x<-0.5) || (x>=0.5) || (y<-0.5) || (y>=0.5) )
            comp_result = 0;
         break;

      case poly_rgn:
         if( Xxmin || X>Shapes->xmax
             || Yymin || Y>Shapes->ymax )
            comp_result = 0;
         else
            comp_result = Pt_in_Poly( X, Y, Shapes->param.poly.nPts,
                                       Shapes->param.poly.Pts );
         break;

      case panda_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         r = x*x + y*y;
         if ( r < Shapes->param.gen.a || r > Shapes->param.gen.b ) {
	   comp_result = 0;
	 } else {
	   if( x || y ) {
	     th = atan2( y, x ) * RadToDeg;
	     if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
               if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
		 comp_result = 0;
	     } else {
               if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
		 comp_result = 0;
	     }
	   }
         }
         break;

      case epanda_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
	 xprime = x;
	 yprime = y;

	 /* outer region test */
         x = xprime/Shapes->param.gen.p[7];
         y = yprime/Shapes->param.gen.p[8];
         r = x*x + y*y;
	 if ( r>1.0 )
	   comp_result = 0;
	 else {
	   /* inner region test */
	   x = xprime/Shapes->param.gen.p[5];
	   y = yprime/Shapes->param.gen.p[6];
	   r = x*x + y*y;
	   if ( r<1.0 )
	     comp_result = 0;
	   else {
	     /* angle test */
	     if( xprime || yprime ) {
	       th = atan2( yprime, xprime ) * RadToDeg;
	       if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
		 if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       } else {
		 if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       }
	     }
	   }
	 }
         break;

      case bpanda_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

	 /* outer box test */
         dx = 0.5 * Shapes->param.gen.p[7];
         dy = 0.5 * Shapes->param.gen.p[8];
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
	   comp_result = 0;
	 else {
	   /* inner box test */
	   dx = 0.5 * Shapes->param.gen.p[5];
	   dy = 0.5 * Shapes->param.gen.p[6];
	   if( (x >= -dx) && (x <= dx) && (y >= -dy) && (y <= dy) )
	     comp_result = 0;
	   else {
	     /* angle test */
	     if( x || y ) {
	       th = atan2( y, x ) * RadToDeg;
	       if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
		 if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       } else {
		 if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       }
	     }
	   }
	 }
         break;
      }

      if( !Shapes->sign ) comp_result = !comp_result;

     } 

   }

   result = result || comp_result;
   
   return( result );
}

/*---------------------------------------------------------------------------*/
void fits_free_region( SAORegion *Rgn )
/*   Free up memory allocated to hold the region data.                       
   This is more complicated for the case of polygons, which may be sharing
   points arrays due to shallow copying (in fits_set_region_components) of
   'exluded' regions.  We must ensure that these arrays are only freed once.       

/*---------------------------------------------------------------------------*/
{
   int i,j;
   
   int nFreedPoly=0;
   int nPolyArraySize=10;
   double **freedPolyPtrs=0;
   double *ptsToFree=0;
   int isAlreadyFreed=0;
   
   freedPolyPtrs = (double**)malloc(nPolyArraySize*sizeof(double*));

   for( i=0; inShapes; i++ )
      if( Rgn->Shapes[i].shape == poly_rgn )
      {
         /* No shared arrays for 'include' polygons */
         if (Rgn->Shapes[i].sign)
            free(Rgn->Shapes[i].param.poly.Pts);
         else
         {
            ptsToFree = Rgn->Shapes[i].param.poly.Pts;
            isAlreadyFreed = 0;
            for (j=0; jShapes )
      free( Rgn->Shapes );
   free( Rgn );
   
   free(freedPolyPtrs);
}

/*---------------------------------------------------------------------------*/
static int Pt_in_Poly( double x,
                       double y,
                       int nPts,
                       double *Pts )
/*  Internal routine for testing whether the coordinate x,y is within the    */
/*  polygon region traced out by the array Pts.                              */
/*---------------------------------------------------------------------------*/
{
   int i, j, flag=0;
   double prevX, prevY;
   double nextX, nextY;
   double dx, dy, Dy;

   nextX = Pts[nPts-2];
   nextY = Pts[nPts-1];

   for( i=0; iprevY && y>=nextY) || (yprevX && x>=nextX) )
         continue;
      
      /* Check to see if x,y lies right on the segment */

      if( x>=prevX || x>nextX ) {
         dy = y - prevY;
         Dy = nextY - prevY;

         if( fabs(Dy)<1e-10 ) {
            if( fabs(dy)<1e-10 )
               return( 1 );
            else
               continue;
         }

         dx = prevX + ( (nextX-prevX)/(Dy) ) * dy - x;
         if( dx < -1e-10 )
            continue;
         if( dx <  1e-10 )
            return( 1 );
      }

      /* There is an intersection! Make sure it isn't a V point.  */

      if( y != prevY ) {
         flag = 1 - flag;
      } else {
         j = i+1;  /* Point to Y component */
         do {
            if( j>1 )
               j -= 2;
            else
               j = nPts-1;
         } while( y == Pts[j] );

         if( (nextY-y)*(y-Pts[j]) > 0 )
            flag = 1-flag;
      }

   }
   return( flag );
}
/*---------------------------------------------------------------------------*/
void fits_set_region_components ( SAORegion *aRgn )
{
/* 
   Internal routine to turn a collection of regions read from an ascii file into
   the more complex structure that is allowed by the FITS REGION extension with
   multiple components. Regions are anded within components and ored between them
   ie for a pixel to be selected it must be selected by at least one component
   and to be selected by a component it must be selected by all that component's
   shapes.

   The algorithm is to replicate every exclude region after every include
   region before it in the list. eg reg1, reg2, -reg3, reg4, -reg5 becomes
   (reg1, -reg3, -reg5), (reg2, -reg5, -reg3), (reg4, -reg5) where the
   parentheses designate components.
*/

  int i, j, k, icomp;

/* loop round shapes */

  i = 0;
  while ( inShapes ) {

    /* first do the case of an exclude region */

    if ( !aRgn->Shapes[i].sign ) {

      /* we need to run back through the list copying the current shape as
	 required. start by findin the first include shape before this exclude */

      j = i-1;
      while ( j > 0 && !aRgn->Shapes[j].sign ) j--;

      /* then go back one more shape */

      j--;

      /* and loop back through the regions */

      while ( j >= 0 ) {

	/* if this is an include region then insert a copy of the exclude
	   region immediately after it */
           
        /* Note that this makes shallow copies of a polygon's dynamically
        allocated Pts array -- the memory is shared.  This must be checked
        when freeing in fits_free_region. */

	if ( aRgn->Shapes[j].sign ) {

	  aRgn->Shapes = (RgnShape *) realloc (aRgn->Shapes,(1+aRgn->nShapes)*sizeof(RgnShape));
	  aRgn->nShapes++;
	  for (k=aRgn->nShapes-1; k>j+1; k--) aRgn->Shapes[k] = aRgn->Shapes[k-1];

	  i++;
	  aRgn->Shapes[j+1] = aRgn->Shapes[i];

	}

	j--;

      }

    }

    i++;

  }

  /* now set the component numbers */

  icomp = 0;
  for ( i=0; inShapes; i++ ) {
    if ( aRgn->Shapes[i].sign ) icomp++;
    aRgn->Shapes[i].comp = icomp;

    /*
    printf("i = %d, shape = %d, sign = %d, comp = %d\n", i, aRgn->Shapes[i].shape, aRgn->Shapes[i].sign, aRgn->Shapes[i].comp);
    */

  }

  return;

}

/*---------------------------------------------------------------------------*/
void fits_setup_shape ( RgnShape *newShape)
{
/* Perform some useful calculations now to speed up filter later             */

  double X, Y, R;
  double *coords;
  int i;

  if ( newShape->shape == poly_rgn ) {
    coords = newShape->param.poly.Pts;
  } else {
    coords = newShape->param.gen.p;
  }

  switch( newShape->shape ) {
  case circle_rgn:
    newShape->param.gen.a = coords[2] * coords[2];
    break;
  case annulus_rgn:
    newShape->param.gen.a = coords[2] * coords[2];
    newShape->param.gen.b = coords[3] * coords[3];
    break;
  case sector_rgn:
    while( coords[2]> 180.0 ) coords[2] -= 360.0;
    while( coords[2]<=-180.0 ) coords[2] += 360.0;
    while( coords[3]> 180.0 ) coords[3] -= 360.0;
    while( coords[3]<=-180.0 ) coords[3] += 360.0;
    break;
  case ellipse_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    break;
  case elliptannulus_rgn:
    newShape->param.gen.a    = sin( myPI * (coords[6] / 180.0) );
    newShape->param.gen.b    = cos( myPI * (coords[6] / 180.0) );
    newShape->param.gen.sinT = sin( myPI * (coords[7] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[7] / 180.0) );
    break;
  case box_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    break;
  case boxannulus_rgn:
    newShape->param.gen.a    = sin( myPI * (coords[6] / 180.0) );
    newShape->param.gen.b    = cos( myPI * (coords[6] / 180.0) );
    newShape->param.gen.sinT = sin( myPI * (coords[7] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[7] / 180.0) );
    break;
  case rectangle_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    X = 0.5 * ( coords[2]-coords[0] );
    Y = 0.5 * ( coords[3]-coords[1] );
    newShape->param.gen.a = fabs( X * newShape->param.gen.cosT
				  + Y * newShape->param.gen.sinT );
    newShape->param.gen.b = fabs( Y * newShape->param.gen.cosT
				  - X * newShape->param.gen.sinT );
    newShape->param.gen.p[5] = 0.5 * ( coords[2]+coords[0] );
    newShape->param.gen.p[6] = 0.5 * ( coords[3]+coords[1] );
    break;
  case diamond_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    break;
  case line_rgn:
    X = coords[2] - coords[0];
    Y = coords[3] - coords[1];
    R = sqrt( X*X + Y*Y );
    newShape->param.gen.sinT = ( R ? Y/R : 0.0 );
    newShape->param.gen.cosT = ( R ? X/R : 1.0 );
    newShape->param.gen.a    = R + 0.5;
    break;
  case panda_rgn:
    while( coords[2]> 180.0 ) coords[2] -= 360.0;
    while( coords[2]<=-180.0 ) coords[2] += 360.0;
    while( coords[3]> 180.0 ) coords[3] -= 360.0;
    while( coords[3]<=-180.0 ) coords[3] += 360.0;
    newShape->param.gen.a = newShape->param.gen.p[5]*newShape->param.gen.p[5];
    newShape->param.gen.b = newShape->param.gen.p[6]*newShape->param.gen.p[6];
    break;
  case epanda_rgn:
  case bpanda_rgn:
    while( coords[2]> 180.0 ) coords[2] -= 360.0;
    while( coords[2]<=-180.0 ) coords[2] += 360.0;
    while( coords[3]> 180.0 ) coords[3] -= 360.0;
    while( coords[3]<=-180.0 ) coords[3] += 360.0;
    newShape->param.gen.sinT = sin( myPI * (coords[10] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[10] / 180.0) );
    break;
  default:
    break;
  }

  /*  Set the xmin, xmax, ymin, ymax elements of the RgnShape structure */

  /* For everything which has first two parameters as center position just */
  /* find a circle that encompasses the region and use it to set the       */
  /* bounding box                                                          */

  R = -1.0;

  switch ( newShape->shape ) {

  case circle_rgn:
    R = coords[2];
    break;

  case annulus_rgn:
    R = coords[3];
    break;

  case ellipse_rgn:
    if ( coords[2] > coords[3] ) {
      R = coords[2];
    } else {
      R = coords[3];
    }
    break;

  case elliptannulus_rgn:
    if ( coords[4] > coords[5] ) {
      R = coords[4];
    } else {
      R = coords[5];
    }
    break;

  case box_rgn:
    R = sqrt(coords[2]*coords[2]+
	     coords[3]*coords[3])/2.0;
    break;

  case boxannulus_rgn:
    R = sqrt(coords[4]*coords[5]+
	     coords[4]*coords[5])/2.0;
    break;

  case diamond_rgn:
    if ( coords[2] > coords[3] ) {
      R = coords[2]/2.0;
    } else {
      R = coords[3]/2.0;
    }
    break;
    
  case point_rgn:
    R = 1.0;
    break;

  case panda_rgn:
    R = coords[6];
    break;

  case epanda_rgn:
    if ( coords[7] > coords[8] ) {
      R = coords[7];
    } else {
      R = coords[8];
    }
    break;

  case bpanda_rgn:
    R = sqrt(coords[7]*coords[8]+
	     coords[7]*coords[8])/2.0;
    break;

  default:
    break;
  }

  if ( R > 0.0 ) {

    newShape->xmin = coords[0] - R;
    newShape->xmax = coords[0] + R;
    newShape->ymin = coords[1] - R;
    newShape->ymax = coords[1] + R;

    return;

  }

  /* Now do the rest of the shapes that require individual methods */

  switch ( newShape->shape ) {

  case rectangle_rgn:
    R = sqrt((coords[5]-coords[0])*(coords[5]-coords[0])+
	     (coords[6]-coords[1])*(coords[6]-coords[1]));
    newShape->xmin = coords[5] - R;
    newShape->xmax = coords[5] + R;
    newShape->ymin = coords[6] - R;
    newShape->ymax = coords[6] + R;
    break;

  case poly_rgn:
    newShape->xmin = coords[0];
    newShape->xmax = coords[0];
    newShape->ymin = coords[1];
    newShape->ymax = coords[1];
    for( i=2; i < newShape->param.poly.nPts; ) {
      if( newShape->xmin > coords[i] ) /* Min X */
	newShape->xmin = coords[i];
      if( newShape->xmax < coords[i] ) /* Max X */
	newShape->xmax = coords[i];
      i++;
      if( newShape->ymin > coords[i] ) /* Min Y */
	newShape->ymin = coords[i];
      if( newShape->ymax < coords[i] ) /* Max Y */
	newShape->ymax = coords[i];
      i++;
    }
    break;

  case line_rgn:
    if ( coords[0] > coords[2] ) {
      newShape->xmin = coords[2];
      newShape->xmax = coords[0];
    } else {
      newShape->xmin = coords[0];
      newShape->xmax = coords[2];
    }
    if ( coords[1] > coords[3] ) {
      newShape->ymin = coords[3];
      newShape->ymax = coords[1];
    } else {
      newShape->ymin = coords[1];
      newShape->ymax = coords[3];
    }

    break;

    /* sector doesn't have min and max so indicate by setting max < min */

  case sector_rgn:
    newShape->xmin = 1.0;
    newShape->xmax = -1.0;
    newShape->ymin = 1.0;
    newShape->ymax = -1.0;
    break;

  default:
    break;
  }

  return;

}

/*---------------------------------------------------------------------------*/
int fits_read_fits_region ( fitsfile *fptr, 
			    WCSdata *wcs, 
			    SAORegion **Rgn, 
			    int *status)
/*  Read regions from a FITS region extension and return the information     */
/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
/*  region coordinates to pixels.  Return an error if region is in degrees   */
/*  but no WCS data is provided.                                             */
/*---------------------------------------------------------------------------*/
{

  int i, j, icol[6], idum, anynul, npos;
  int dotransform, got_component = 1, tstatus;
  long icsize[6];
  double X, Y, Theta, Xsave = 0, Ysave = 0, Xpos, Ypos;
  double *coords;
  char *cvalue, *cvalue2;
  char comment[FLEN_COMMENT];
  char colname[6][FLEN_VALUE] = {"X", "Y", "SHAPE", "R", "ROTANG", "COMPONENT"};
  char shapename[17][FLEN_VALUE] = {"POINT","CIRCLE","ELLIPSE","ANNULUS",
				    "ELLIPTANNULUS","BOX","ROTBOX","BOXANNULUS",
				    "RECTANGLE","ROTRECTANGLE","POLYGON","PIE",
				    "SECTOR","DIAMOND","RHOMBUS","ROTDIAMOND",
				    "ROTRHOMBUS"};
  int shapetype[17] = {point_rgn, circle_rgn, ellipse_rgn, annulus_rgn, 
		       elliptannulus_rgn, box_rgn, box_rgn, boxannulus_rgn, 
		       rectangle_rgn, rectangle_rgn, poly_rgn, sector_rgn, 
		       sector_rgn, diamond_rgn, diamond_rgn, diamond_rgn, 
		       diamond_rgn};
  SAORegion *aRgn;
  RgnShape *newShape;
  WCSdata *regwcs = 0;

  if ( *status ) return( *status );

  aRgn = (SAORegion *)malloc( sizeof(SAORegion) );
  if( ! aRgn ) {
    ffpmsg("Couldn't allocate memory to hold Region file contents.");
    return(*status = MEMORY_ALLOCATION );
  }
  aRgn->nShapes    =    0;
  aRgn->Shapes     = NULL;
  if( wcs && wcs->exists )
    aRgn->wcs = *wcs;
  else
    aRgn->wcs.exists = 0;

  /* See if we are already positioned to a region extension, else */
  /* move to the REGION extension (file is already open). */

  tstatus = 0;
  for (i=0; i<5; i++) {
    ffgcno(fptr, CASEINSEN, colname[i], &icol[i], &tstatus);
  }

  if (tstatus) {
    /* couldn't find the required columns, so search for "REGION" extension */
    if ( ffmnhd(fptr, BINARY_TBL, "REGION", 1, status) ) {
      ffpmsg("Could not move to REGION extension.");
      goto error;
    }
  }

  /* get the number of shapes and allocate memory */

  if ( ffgky(fptr, TINT, "NAXIS2", &aRgn->nShapes, comment, status) ) {
    ffpmsg("Could not read NAXIS2 keyword.");
    goto error;
  }

  aRgn->Shapes = (RgnShape *) malloc(aRgn->nShapes * sizeof(RgnShape));
  if ( !aRgn->Shapes ) {
    ffpmsg( "Failed to allocate memory for Region data");
    *status = MEMORY_ALLOCATION;
    goto error;
  }

  /* get the required column numbers */

  for (i=0; i<5; i++) {
    if ( ffgcno(fptr, CASEINSEN, colname[i], &icol[i], status) ) {
      ffpmsg("Could not find column.");
      goto error;
    }
  }

  /* try to get the optional column numbers */

  if ( ffgcno(fptr, CASEINSEN, colname[5], &icol[5], status) ) {
       got_component = 0;
  }

  /* if there was input WCS then read the WCS info for the region in case they */
  /* are different and we have to transform */

  dotransform = 0;
  if ( aRgn->wcs.exists ) {
    regwcs = (WCSdata *) malloc ( sizeof(WCSdata) );
    if ( !regwcs ) {
      ffpmsg( "Failed to allocate memory for Region WCS data");
      *status = MEMORY_ALLOCATION;
      goto error;
    }

    regwcs->exists = 1;
    if ( ffgtcs(fptr, icol[0], icol[1], ®wcs->xrefval,  ®wcs->yrefval,
		®wcs->xrefpix, ®wcs->yrefpix, ®wcs->xinc, ®wcs->yinc,
		®wcs->rot, regwcs->type, status) ) {
      regwcs->exists = 0;
      *status = 0;
    }

    if ( regwcs->exists && wcs->exists ) {
      if ( fabs(regwcs->xrefval-wcs->xrefval) > 1.0e-6 ||
	   fabs(regwcs->yrefval-wcs->yrefval) > 1.0e-6 ||
	   fabs(regwcs->xrefpix-wcs->xrefpix) > 1.0e-6 ||
	   fabs(regwcs->yrefpix-wcs->yrefpix) > 1.0e-6 ||
	   fabs(regwcs->xinc-wcs->xinc) > 1.0e-6 ||
	   fabs(regwcs->yinc-wcs->yinc) > 1.0e-6 ||
	   fabs(regwcs->rot-wcs->rot) > 1.0e-6 ||
	   !strcmp(regwcs->type,wcs->type) ) dotransform = 1;
    }
  }

  /* get the sizes of the X, Y, R, and ROTANG vectors */

  for (i=0; i<6; i++) {
    if ( ffgtdm(fptr, icol[i], 1, &idum, &icsize[i], status) ) {
      ffpmsg("Could not find vector size of column.");
      goto error;
    }
  }

  cvalue = (char *) malloc ((FLEN_VALUE+1)*sizeof(char));

  /* loop over the shapes - note 1-based counting for rows in FITS files */

  for (i=1; i<=aRgn->nShapes; i++) {

    newShape = &aRgn->Shapes[i-1];
    for (j=0; j<8; j++) newShape->param.gen.p[j] = 0.0;
    newShape->param.gen.a = 0.0;
    newShape->param.gen.b = 0.0;
    newShape->param.gen.sinT = 0.0;
    newShape->param.gen.cosT = 0.0;

    /* get the shape */

    if ( ffgcvs(fptr, icol[2], i, 1, 1, " ", &cvalue, &anynul, status) ) {
      ffpmsg("Could not read shape.");
      goto error;
    }

    /* set include or exclude */

    newShape->sign = 1;
    cvalue2 = cvalue;
    if ( !strncmp(cvalue,"!",1) ) {
      newShape->sign = 0;
      cvalue2++;
    }

    /* set the shape type */

    for (j=0; j<17; j++) {
      if ( !strcmp(cvalue2, shapename[j]) ) newShape->shape = shapetype[j];
    }

    /* allocate memory for polygon case and set coords pointer */

    if ( newShape->shape == poly_rgn ) {
      newShape->param.poly.Pts = (double *) calloc (2*icsize[0], sizeof(double));
      if ( !newShape->param.poly.Pts ) {
	ffpmsg("Could not allocate memory to hold polygon parameters" );
	*status = MEMORY_ALLOCATION;
	goto error;
      }
      newShape->param.poly.nPts = 2*icsize[0];
      coords = newShape->param.poly.Pts;
    } else {
      coords = newShape->param.gen.p;
    }


  /* read X and Y. Polygon and Rectangle require special cases */

    npos = 1;
    if ( newShape->shape == poly_rgn ) npos = newShape->param.poly.nPts/2;
    if ( newShape->shape == rectangle_rgn ) npos = 2;

    for (j=0; jparam.poly.nPts = npos * 2;
	break;
      }
      coords++;
      
      if ( ffgcvd(fptr, icol[1], i, j+1, 1, DOUBLENULLVALUE, coords, &anynul, status) ) {
	ffpmsg("Failed to read Y column for polygon region");
	goto error;
      }
      if (*coords == DOUBLENULLVALUE) { /* check for null value end of array marker */
        npos = j;
	newShape->param.poly.nPts = npos * 2;
        coords--;
	break;
      }
      coords++;
 
      if (j == 0) {  /* save the first X and Y coordinate */
        Xsave = *(coords - 2);
	Ysave = *(coords - 1);
      } else if ((Xsave == *(coords - 2)) && (Ysave == *(coords - 1)) ) {
        /* if point has same coordinate as first point, this marks the end of the array */
        npos = j + 1;
	newShape->param.poly.nPts = npos * 2;
	break;
      }
    }

    /* transform positions if the region and input wcs differ */

    if ( dotransform ) {

      coords -= npos*2;
      Xsave = coords[0];
      Ysave = coords[1];
      for (j=0; jxrefval, regwcs->yrefval, regwcs->xrefpix,
	       regwcs->yrefpix, regwcs->xinc, regwcs->yinc, regwcs->rot,
	       regwcs->type, &Xpos, &Ypos, status);
	ffxypx(Xpos, Ypos, wcs->xrefval, wcs->yrefval, wcs->xrefpix,
	       wcs->yrefpix, wcs->xinc, wcs->yinc, wcs->rot,
	       wcs->type, &coords[2*j], &coords[2*j+1], status);
	if ( *status ) {
	  ffpmsg("Failed to transform coordinates");
	  goto error;
	}
      }
      coords += npos*2;
    }

  /* read R. Circle requires one number; Box, Diamond, Ellipse, Annulus, Sector 
     and Panda two; Boxannulus and Elliptannulus four; Point, Rectangle and 
     Polygon none. */

    npos = 0;
    switch ( newShape->shape ) {
    case circle_rgn: 
      npos = 1;
      break;
    case box_rgn:
    case diamond_rgn:
    case ellipse_rgn:
    case annulus_rgn:
    case sector_rgn:
      npos = 2;
      break;
    case boxannulus_rgn:
    case elliptannulus_rgn:
      npos = 4;
      break;
    default:
      break;
    }

    if ( npos > 0 ) {
      if ( ffgcvd(fptr, icol[3], i, 1, npos, 0.0, coords, &anynul, status) ) {
	ffpmsg("Failed to read R column for region");
	goto error;
      }

    /* transform lengths if the region and input wcs differ */

      if ( dotransform ) {
	for (j=0; jxrefval, regwcs->yrefval, regwcs->xrefpix,
		 regwcs->yrefpix, regwcs->xinc, regwcs->yinc, regwcs->rot,
		 regwcs->type, &Xpos, &Ypos, status);
	  ffxypx(Xpos, Ypos, wcs->xrefval, wcs->yrefval, wcs->xrefpix,
		 wcs->yrefpix, wcs->xinc, wcs->yinc, wcs->rot,
		 wcs->type, &X, &Y, status);
	  if ( *status ) {
	    ffpmsg("Failed to transform coordinates");
	    goto error;
	  }
	  *(coords++) = sqrt(pow(X-newShape->param.gen.p[0],2)+pow(Y-newShape->param.gen.p[1],2));
	}
      } else {
	coords += npos;
      }
    }

  /* read ROTANG. Requires two values for Boxannulus, Elliptannulus, Sector, 
     Panda; one for Box, Diamond, Ellipse; and none for Circle, Point, Annulus, 
     Rectangle, Polygon */

    npos = 0;
    switch ( newShape->shape ) {
    case box_rgn:
    case diamond_rgn:
    case ellipse_rgn:
      npos = 1;
      break;
    case boxannulus_rgn:
    case elliptannulus_rgn:
    case sector_rgn:
      npos = 2;
      break;
    default:
     break;
    }

    if ( npos > 0 ) {
      if ( ffgcvd(fptr, icol[4], i, 1, npos, 0.0, coords, &anynul, status) ) {
	ffpmsg("Failed to read ROTANG column for region");
	goto error;
      }

    /* transform angles if the region and input wcs differ */

      if ( dotransform ) {
	Theta = (wcs->rot) - (regwcs->rot);
	for (j=0; jcomp, &anynul, status) ) {
        ffpmsg("Failed to read COMPONENT column for region");
        goto error;
      }
    } else {
      newShape->comp = 1;
    }


    /* do some precalculations to speed up tests */

    fits_setup_shape(newShape);

    /* end loop over shapes */

  }

error:

   if( *status )
      fits_free_region( aRgn );
   else
      *Rgn = aRgn;

   ffclos(fptr, status);

   return( *status );
}

cfitsio-4.3.1/getcoli.c0000644000225700000360000022220513472024437014250 0ustar  cagordonlhea/*  This file, getcoli.c, contains routines that read data elements from   */
/*  a FITS image or table, with short datatype.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvi( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            short nulval,     /* I - value for undefined pixels              */
            short *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    short nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */
        fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcli(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfi( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            short *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcli(fptr, 2, row, firstelem, nelem, 1, 2, 0,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2di(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           short nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           short *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3di(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3di(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           short nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           short *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    LONGLONG nfits, narray;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1};
    LONGLONG lpixel[3];
    short nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TSHORT, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcli(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcli(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvi(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           short nulval,   /* I - value to set undefined pixels             */
           short *array,   /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    short nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg,FLEN_ERRMSG, "NAXIS = %d in call to ffgsvi is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TSHORT, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);

        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvi: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgcli(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfi(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           short *array,   /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    short nulval = 0;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvi is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TSHORT, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvi: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcli(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpi( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            short *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcli(fptr, 1, row, firstelem, nelem, 1, 1, 0,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvi(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           short nulval,     /* I - value for null pixels                   */
           short *array,     /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfi(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           short *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    short dummy = 0;

    ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcli( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            short nulval,     /* I - value for null pixels if nultyp = 1     */
            short *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TSHORT) /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/2) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/2;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, &array[next], status);
                if (convert)
                    fffi2i2(&array[next], ntodo, scale, zero, nulcheck, 
                           (short) tnull, nulval, &nularray[next], anynul, 
                           &array[next], status);
                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8i2( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                      status);
                fffi1i2((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
                    &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4i2((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4i2((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8i2((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstri2((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcli).",
              dtemp+1, dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcli).",
              dtemp+1, dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0) /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1i2(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (short) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2i2(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            memmove(output, input, ntodo * sizeof(short) );
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4i2(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < SHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > SHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < SHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > SHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8i2(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    ULONGLONG ulltemp;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero ==  9223372036854775808.)
        {       
            /* The column we read contains unsigned long long values. */
            /* Instead of adding 9223372036854775808, it is more efficient */
            /* and more precise to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
 
                ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);

                if (ulltemp > SHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
		{
                    output[ii] = (short) ulltemp;
		}
            }
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < SHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > SHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero ==  9223372036854775808.)
        {       
            /* The column we read contains unsigned long long values. */
            /* Instead of subtracting 9223372036854775808, it is more efficient */
            /* and more precise to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
 
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
		{
                    ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);

                    if (ulltemp > SHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
		    {
                        output[ii] = (short) ulltemp;
		    }
                }
            }
        }
        else if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < SHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > SHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4i2(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (zero > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8i2(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (zero > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstri2(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DSHRT_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = SHRT_MIN;
        }
        else if (dvalue > DSHRT_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = SHRT_MAX;
        }
        else
            output[ii] = (short) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio-4.3.1/configure0000755000225700000360000063361714523040557014401 0ustar  cagordonlhea#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71.
#
#
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
# Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else $as_nop
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" ""	$as_nl"

PS1='$ '
PS2='> '
PS4='+ '

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi


# Use a proper internal environment variable to ensure we don't fall
  # into an infinite loop, continuously re-executing ourselves.
  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
    _as_can_reexec=no; export _as_can_reexec;
    # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
  fi
  # We don't want this to propagate to other subprocesses.
          { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
  as_bourne_compatible="as_nop=:
if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '\${1+\"\$@\"}'='\"\$@\"'
  setopt NO_GLOB_SUBST
else \$as_nop
  case \`(set -o) 2>/dev/null\` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi
"
  as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }

exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" )
then :

else \$as_nop
  exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
blah=\$(echo \$(echo blah))
test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
  if (eval "$as_required") 2>/dev/null
then :
  as_have_required=yes
else $as_nop
  as_have_required=no
fi
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
then :

else $as_nop
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
  as_found=:
  case $as_dir in #(
	 /*)
	   for as_base in sh bash ksh sh5; do
	     # Try only shells that exist, to save several forks.
	     as_shell=$as_dir$as_base
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$as_shell as_have_required=yes
		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
then :
  break 2
fi
fi
	   done;;
       esac
  as_found=false
done
IFS=$as_save_IFS
if $as_found
then :

else $as_nop
  if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$SHELL as_have_required=yes
fi
fi


      if test "x$CONFIG_SHELL" != x
then :
  export CONFIG_SHELL
             # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    if test x$as_have_required = xno
then :
  printf "%s\n" "$0: This script requires a shell more modern than all"
  printf "%s\n" "$0: the shells that I found on your system."
  if test ${ZSH_VERSION+y} ; then
    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
  else
    printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
  fi
  exit 1
fi
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS

## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit
# as_fn_nop
# ---------
# Do nothing but, unlike ":", preserve the value of $?.
as_fn_nop ()
{
  return $?
}
as_nop=as_fn_nop

# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
      test -d "$as_dir" && break
    done
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"


} # as_fn_mkdir_p

# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else $as_nop
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else $as_nop
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith

# as_fn_nop
# ---------
# Do nothing but, unlike ":", preserve the value of $?.
as_fn_nop ()
{
  return $?
}
as_nop=as_fn_nop
# as_fn_nop
# ---------
# Do nothing but, unlike ":", preserve the value of $?.
as_fn_nop ()
{
  return $?
}
as_nop=as_fn_nop

# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error

if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits


  as_lineno_1=$LINENO as_lineno_1a=$LINENO
  as_lineno_2=$LINENO as_lineno_2a=$LINENO
  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
  sed -n '
    p
    /[$]LINENO/=
  ' <$as_myself |
    sed '
      s/[$]LINENO.*/&-/
      t lineno
      b
      :lineno
      N
      :loop
      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
      t loop
      s/-\n.*//
    ' >$as_me.lineno &&
  chmod +x "$as_me.lineno" ||
    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }

  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
  # already done that, so ensure we don't try to do so again and fall
  # in an infinite loop.  This has already happened in practice.
  _as_can_reexec=no; export _as_can_reexec
  # Don't try to exec as it changes $[0], causing all sort of problems
  # (the dirname of $[0] is not the place where we might find the
  # original and so on.  Autoconf is especially sensitive to this).
  . "./$as_me.lineno"
  # Exit status is that of the last command.
  exit
}


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'


rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null

if mkdir -p . 2>/dev/null; then
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi

as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


test -n "$DJDIR" || exec 7<&0 &1

# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`

#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=

# Identity of this package.
PACKAGE_NAME=''
PACKAGE_TARNAME=''
PACKAGE_VERSION=''
PACKAGE_STRING=''
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

ac_unique_file="fitscore.c"
# Factoring default headers for most tests.
ac_includes_default="\
#include 
#ifdef HAVE_STDIO_H
# include 
#endif
#ifdef HAVE_STDLIB_H
# include 
#endif
#ifdef HAVE_STRING_H
# include 
#endif
#ifdef HAVE_INTTYPES_H
# include 
#endif
#ifdef HAVE_STDINT_H
# include 
#endif
#ifdef HAVE_STRINGS_H
# include 
#endif
#ifdef HAVE_SYS_TYPES_H
# include 
#endif
#ifdef HAVE_SYS_STAT_H
# include 
#endif
#ifdef HAVE_UNISTD_H
# include 
#endif"

ac_header_c_list=
ac_default_prefix=`pwd`
ac_subst_vars='LTLIBOBJS
LIBOBJS
my_shmem
LDFLAGS_BIN
F77_WRAPPERS
CFITSIO_SHLIB_SONAME
CFITSIO_SHLIB
SHLIB_SUFFIX
SHLIB_LD
LIBPRE
ARCH
LIBS_CURL
CURLCONFIG
GCCVERSION
SSE_FLAGS
RANLIB
ARCHIVE
AR
FC
INSTALL_ROOT
GSIFTP_SRC
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
CFITSIO_SONAME
CFITSIO_MICRO
CFITSIO_MINOR
CFITSIO_MAJOR
target_os
target_vendor
target_cpu
target
host_os
host_vendor
host_cpu
host
build_os
build_vendor
build_cpu
build
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_curl
enable_reentrant
enable_sse2
enable_ssse3
enable_symbols
enable_hera
with_bzip2
with_gsiftp
with_gsiftp_flavour
with_zlib_check
'
      ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS'


# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE

# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'

ac_prev=
ac_dashdash=
for ac_option
do
  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
    eval $ac_prev=\$ac_option
    ac_prev=
    continue
  fi

  case $ac_option in
  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
  *=)   ac_optarg= ;;
  *)    ac_optarg=yes ;;
  esac

  case $ac_dashdash$ac_option in
  --)
    ac_dashdash=yes ;;

  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
    bindir=$ac_optarg ;;

  -build | --build | --buil | --bui | --bu)
    ac_prev=build_alias ;;
  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
    build_alias=$ac_optarg ;;

  -cache-file | --cache-file | --cache-fil | --cache-fi \
  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
    ac_prev=cache_file ;;
  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
    cache_file=$ac_optarg ;;

  --config-cache | -C)
    cache_file=config.cache ;;

  -datadir | --datadir | --datadi | --datad)
    ac_prev=datadir ;;
  -datadir=* | --datadir=* | --datadi=* | --datad=*)
    datadir=$ac_optarg ;;

  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
  | --dataroo | --dataro | --datar)
    ac_prev=datarootdir ;;
  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
    datarootdir=$ac_optarg ;;

  -disable-* | --disable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval enable_$ac_useropt=no ;;

  -docdir | --docdir | --docdi | --doc | --do)
    ac_prev=docdir ;;
  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
    docdir=$ac_optarg ;;

  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
    ac_prev=dvidir ;;
  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
    dvidir=$ac_optarg ;;

  -enable-* | --enable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval enable_$ac_useropt=\$ac_optarg ;;

  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
  | --exec | --exe | --ex)
    ac_prev=exec_prefix ;;
  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
  | --exec=* | --exe=* | --ex=*)
    exec_prefix=$ac_optarg ;;

  -gas | --gas | --ga | --g)
    # Obsolete; use --with-gas.
    with_gas=yes ;;

  -help | --help | --hel | --he | -h)
    ac_init_help=long ;;
  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
    ac_init_help=recursive ;;
  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
    ac_init_help=short ;;

  -host | --host | --hos | --ho)
    ac_prev=host_alias ;;
  -host=* | --host=* | --hos=* | --ho=*)
    host_alias=$ac_optarg ;;

  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
    ac_prev=htmldir ;;
  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
  | --ht=*)
    htmldir=$ac_optarg ;;

  -includedir | --includedir | --includedi | --included | --include \
  | --includ | --inclu | --incl | --inc)
    ac_prev=includedir ;;
  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
  | --includ=* | --inclu=* | --incl=* | --inc=*)
    includedir=$ac_optarg ;;

  -infodir | --infodir | --infodi | --infod | --info | --inf)
    ac_prev=infodir ;;
  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
    infodir=$ac_optarg ;;

  -libdir | --libdir | --libdi | --libd)
    ac_prev=libdir ;;
  -libdir=* | --libdir=* | --libdi=* | --libd=*)
    libdir=$ac_optarg ;;

  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
  | --libexe | --libex | --libe)
    ac_prev=libexecdir ;;
  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
  | --libexe=* | --libex=* | --libe=*)
    libexecdir=$ac_optarg ;;

  -localedir | --localedir | --localedi | --localed | --locale)
    ac_prev=localedir ;;
  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
    localedir=$ac_optarg ;;

  -localstatedir | --localstatedir | --localstatedi | --localstated \
  | --localstate | --localstat | --localsta | --localst | --locals)
    ac_prev=localstatedir ;;
  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
    localstatedir=$ac_optarg ;;

  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
    ac_prev=mandir ;;
  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
    mandir=$ac_optarg ;;

  -nfp | --nfp | --nf)
    # Obsolete; use --without-fp.
    with_fp=no ;;

  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c | -n)
    no_create=yes ;;

  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
    no_recursion=yes ;;

  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
  | --oldin | --oldi | --old | --ol | --o)
    ac_prev=oldincludedir ;;
  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
    oldincludedir=$ac_optarg ;;

  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
    ac_prev=prefix ;;
  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
    prefix=$ac_optarg ;;

  -program-prefix | --program-prefix | --program-prefi | --program-pref \
  | --program-pre | --program-pr | --program-p)
    ac_prev=program_prefix ;;
  -program-prefix=* | --program-prefix=* | --program-prefi=* \
  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
    program_prefix=$ac_optarg ;;

  -program-suffix | --program-suffix | --program-suffi | --program-suff \
  | --program-suf | --program-su | --program-s)
    ac_prev=program_suffix ;;
  -program-suffix=* | --program-suffix=* | --program-suffi=* \
  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
    program_suffix=$ac_optarg ;;

  -program-transform-name | --program-transform-name \
  | --program-transform-nam | --program-transform-na \
  | --program-transform-n | --program-transform- \
  | --program-transform | --program-transfor \
  | --program-transfo | --program-transf \
  | --program-trans | --program-tran \
  | --progr-tra | --program-tr | --program-t)
    ac_prev=program_transform_name ;;
  -program-transform-name=* | --program-transform-name=* \
  | --program-transform-nam=* | --program-transform-na=* \
  | --program-transform-n=* | --program-transform-=* \
  | --program-transform=* | --program-transfor=* \
  | --program-transfo=* | --program-transf=* \
  | --program-trans=* | --program-tran=* \
  | --progr-tra=* | --program-tr=* | --program-t=*)
    program_transform_name=$ac_optarg ;;

  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
    ac_prev=pdfdir ;;
  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
    pdfdir=$ac_optarg ;;

  -psdir | --psdir | --psdi | --psd | --ps)
    ac_prev=psdir ;;
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -runstatedir | --runstatedir | --runstatedi | --runstated \
  | --runstate | --runstat | --runsta | --runst | --runs \
  | --run | --ru | --r)
    ac_prev=runstatedir ;;
  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
  | --run=* | --ru=* | --r=*)
    runstatedir=$ac_optarg ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

  -sharedstatedir | --sharedstatedir | --sharedstatedi \
  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
  | --sharedst | --shareds | --shared | --share | --shar \
  | --sha | --sh)
    ac_prev=sharedstatedir ;;
  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
  | --sha=* | --sh=*)
    sharedstatedir=$ac_optarg ;;

  -site | --site | --sit)
    ac_prev=site ;;
  -site=* | --site=* | --sit=*)
    site=$ac_optarg ;;

  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
    ac_prev=srcdir ;;
  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
    srcdir=$ac_optarg ;;

  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
  | --syscon | --sysco | --sysc | --sys | --sy)
    ac_prev=sysconfdir ;;
  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
    sysconfdir=$ac_optarg ;;

  -target | --target | --targe | --targ | --tar | --ta | --t)
    ac_prev=target_alias ;;
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target_alias=$ac_optarg ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers | -V)
    ac_init_version=: ;;

  -with-* | --with-*)
    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=\$ac_optarg ;;

  -without-* | --without-*)
    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=no ;;

  --x)
    # Obsolete; use --with-x.
    with_x=yes ;;

  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
  | --x-incl | --x-inc | --x-in | --x-i)
    ac_prev=x_includes ;;
  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
    x_includes=$ac_optarg ;;

  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries=$ac_optarg ;;

  -*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
    ;;

  *=*)
    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
    # Reject names that are not valid shell variable names.
    case $ac_envvar in #(
      '' | [0-9]* | *[!_$as_cr_alnum]* )
      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
    esac
    eval $ac_envvar=\$ac_optarg
    export $ac_envvar ;;

  *)
    # FIXME: should be removed in autoconf 3.0.
    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
    ;;

  esac
done

if test -n "$ac_prev"; then
  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
  as_fn_error $? "missing argument to $ac_option"
fi

if test -n "$ac_unrecognized_opts"; then
  case $enable_option_checking in
    no) ;;
    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
  esac
fi

# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir runstatedir
do
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
  esac
  # Be sure to have absolute directory names.
  case $ac_val in
    [\\/$]* | ?:[\\/]* )  continue;;
    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
  esac
  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done

# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias

# FIXME: To remove some day.
if test "x$host_alias" != x; then
  if test "x$build_alias" = x; then
    cross_compiling=maybe
  elif test "x$build_alias" != "x$host_alias"; then
    cross_compiling=yes
  fi
fi

ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-

test "$silent" = yes && exec 6>/dev/null


ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
  as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
  as_fn_error $? "pwd does not report name of working directory"


# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then the parent directory.
  ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_myself" : 'X\(//\)[^/]' \| \
	 X"$as_myself" : 'X\(//\)$' \| \
	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_myself" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
  srcdir=$ac_confdir
  if test ! -r "$srcdir/$ac_unique_file"; then
    srcdir=..
  fi
else
  ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
	pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
  srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
case $srcdir in
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
esac
for ac_var in $ac_precious_vars; do
  eval ac_env_${ac_var}_set=\${${ac_var}+set}
  eval ac_env_${ac_var}_value=\$${ac_var}
  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
  eval ac_cv_env_${ac_var}_value=\$${ac_var}
done

#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures this package to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit
  -q, --quiet, --silent   do not print \`checking ...' messages
      --cache-file=FILE   cache test results in FILE [disabled]
  -C, --config-cache      alias for \`--cache-file=config.cache'
  -n, --no-create         do not create output files
      --srcdir=DIR        find the sources in DIR [configure dir or \`..']

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]

By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
  --mandir=DIR            man documentation [DATAROOTDIR/man]
  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
  --htmldir=DIR           html documentation [DOCDIR]
  --dvidir=DIR            dvi documentation [DOCDIR]
  --pdfdir=DIR            pdf documentation [DOCDIR]
  --psdir=DIR             ps documentation [DOCDIR]
_ACEOF

  cat <<\_ACEOF

System types:
  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  --target=TARGET   configure for building compilers for TARGET [HOST]
_ACEOF
fi

if test -n "$ac_init_help"; then

  cat <<\_ACEOF

Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --disable-curl          Disable linking with the curl library. Disables
                          remote file i/o support
  --enable-reentrant      Enable reentrant multithreading
  --enable-sse2           Enable use of instructions in the SSE2 extended
                          instruction set
  --enable-ssse3          Enable use of instructions in the SSSE3 extended
                          instruction set
  --enable-symbols        Enable debugging symbols by turning optimization off
  --enable-hera           Build for HERA (ASD use only)

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-bzip2[=PATH]     Enable bzip2 support. Optional path to the location
                          of include/bzlib.h and lib/libbz2
  --with-gsiftp[=PATH]    Enable Globus Toolkit gsiftp protocol support
  --with-gsiftp-flavour[=PATH]
                          Define Globus Toolkit gsiftp protocol flavour
  --without-zlib-check    Disable check for zlib compression library e.g. for
                          cross-compilers

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L if you have libraries in a
              nonstandard directory 
  LIBS        libraries to pass to the linker, e.g. -l
  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I if
              you have headers in a nonstandard directory 

Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.

Report bugs to the package provider.
_ACEOF
ac_status=$?
fi

if test "$ac_init_help" = "recursive"; then
  # If there are subdirs, report their specific --help.
  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
    test -d "$ac_dir" ||
      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
      continue
    ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # We are building in place.
    ac_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    ac_abs_top_srcdir=$ac_pwd ;;
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix

    cd "$ac_dir" || { ac_status=$?; continue; }
    # Check for configure.gnu first; this name is used for a wrapper for
    # Metaconfig's "Configure" on case-insensitive file systems.
    if test -f "$ac_srcdir/configure.gnu"; then
      echo &&
      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
    elif test -f "$ac_srcdir/configure"; then
      echo &&
      $SHELL "$ac_srcdir/configure" --help=recursive
    else
      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi || ac_status=$?
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
configure
generated by GNU Autoconf 2.71

Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit
fi

## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##

# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext conftest.beam
  if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest.$ac_objext
then :
  ac_retval=0
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_compile

# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest$ac_exeext && {
	 test "$cross_compiling" = yes ||
	 test -x conftest$ac_exeext
       }
then :
  ac_retval=0
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
fi
  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
  # interfere with the next link command; also delete a directory that is
  # left behind by Apple's compiler.  We do this before executing the actions.
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_link

# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$3=yes"
else $as_nop
  eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_compile

# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
/* Define $2 to an innocuous variant, in case  declares $2.
   For example, HP-UX 11i  declares gettimeofday.  */
#define $2 innocuous_$2

/* System header to define __stub macros and hopefully few prototypes,
   which can conflict with char $2 (); below.  */

#include 
#undef $2

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
#ifdef __cplusplus
extern "C"
#endif
char $2 ();
/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif

int
main (void)
{
return $2 ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  eval "$3=yes"
else $as_nop
  eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_func
ac_configure_args_raw=
for ac_arg
do
  case $ac_arg in
  *\'*)
    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
  esac
  as_fn_append ac_configure_args_raw " '$ac_arg'"
done

case $ac_configure_args_raw in
  *$as_nl*)
    ac_safe_unquote= ;;
  *)
    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
    ac_unsafe_a="$ac_unsafe_z#~"
    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
esac

cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by $as_me, which was
generated by GNU Autoconf 2.71.  Invocation command line was

  $ $0$ac_configure_args_raw

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##

hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`

/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`

/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`

_ASUNAME

as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    printf "%s\n" "PATH: $as_dir"
  done
IFS=$as_save_IFS

} >&5

cat >&5 <<_ACEOF


## ----------- ##
## Core tests. ##
## ----------- ##

_ACEOF


# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_must_keep_next=false
for ac_pass in 1 2
do
  for ac_arg
  do
    case $ac_arg in
    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
    | -silent | --silent | --silen | --sile | --sil)
      continue ;;
    *\'*)
      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    esac
    case $ac_pass in
    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
    2)
      as_fn_append ac_configure_args1 " '$ac_arg'"
      if test $ac_must_keep_next = true; then
	ac_must_keep_next=false # Got value, back to normal.
      else
	case $ac_arg in
	  *=* | --config-cache | -C | -disable-* | --disable-* \
	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
	  | -with-* | --with-* | -without-* | --without-* | --x)
	    case "$ac_configure_args0 " in
	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
	    esac
	    ;;
	  -* ) ac_must_keep_next=true ;;
	esac
      fi
      as_fn_append ac_configure_args " '$ac_arg'"
      ;;
    esac
  done
done
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}

# When interrupted or exit'd, cleanup temporary files, and complete
# config.log.  We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
  # Sanitize IFS.
  IFS=" ""	$as_nl"
  # Save into config.log some information that might help in debugging.
  {
    echo

    printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
    echo
    # The following way of writing the cache mishandles newlines in values,
(
  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done
  (set) 2>&1 |
    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      sed -n \
	"s/'\''/'\''\\\\'\'''\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
      ;; #(
    *)
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
)
    echo

    printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
    echo
    for ac_var in $ac_subst_vars
    do
      eval ac_val=\$$ac_var
      case $ac_val in
      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      printf "%s\n" "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
      echo
      for ac_var in $ac_subst_files
      do
	eval ac_val=\$$ac_var
	case $ac_val in
	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	printf "%s\n" "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
      echo
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      printf "%s\n" "$as_me: caught signal $ac_signal"
    printf "%s\n" "$as_me: exit $exit_status"
  } >&5
  rm -f core *.core core.conftest.* &&
    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
    exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h

printf "%s\n" "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.

printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h

printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h

printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h

printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h

printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h

printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h


# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
if test -n "$CONFIG_SITE"; then
  ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi

for ac_site_file in $ac_site_files
do
  case $ac_site_file in #(
  */*) :
     ;; #(
  *) :
    ac_site_file=./$ac_site_file ;;
esac
  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
    sed 's/^/| /' "$ac_site_file" >&5
    . "$ac_site_file" \
      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
  fi
done

if test -r "$cache_file"; then
  # Some versions of bash will fail to source /dev/null (special files
  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
    case $cache_file in
      [\\/]* | ?:[\\/]* ) . "$cache_file";;
      *)                      . "./$cache_file";;
    esac
  fi
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
  >$cache_file
fi

# Test code for whether the C compiler supports C89 (global declarations)
ac_c_conftest_c89_globals='
/* Does the compiler advertise C89 conformance?
   Do not test the value of __STDC__, because some compilers set it to 0
   while being otherwise adequately conformant. */
#if !defined __STDC__
# error "Compiler does not advertise C89 conformance"
#endif

#include 
#include 
struct stat;
/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
struct buf { int x; };
struct buf * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
     char **p;
     int i;
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not \xHH hex character constants.
   These do not provoke an error unfortunately, instead are silently treated
   as an "x".  The following induces an error, until -std is added to get
   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
   array size at least.  It is necessary to write \x00 == 0 to get something
   that is true only with -std.  */
int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];

/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
   inside strings and character constants.  */
#define FOO(x) '\''x'\''
int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
               int, int);'

# Test code for whether the C compiler supports C89 (body of main).
ac_c_conftest_c89_main='
ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
'

# Test code for whether the C compiler supports C99 (global declarations)
ac_c_conftest_c99_globals='
// Does the compiler advertise C99 conformance?
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# error "Compiler does not advertise C99 conformance"
#endif

#include 
extern int puts (const char *);
extern int printf (const char *, ...);
extern int dprintf (int, const char *, ...);
extern void *malloc (size_t);

// Check varargs macros.  These examples are taken from C99 6.10.3.5.
// dprintf is used instead of fprintf to avoid needing to declare
// FILE and stderr.
#define debug(...) dprintf (2, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
  int x = 1234;
  int y = 5678;
  debug ("Flag");
  debug ("X = %d\n", x);
  showlist (The first, second, and third items.);
  report (x>y, "x is %d but y is %d", x, y);
}

// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
  #error "your preprocessor is broken"
#endif
#if BIG_OK
#else
  #error "your preprocessor is broken"
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;

struct incomplete_array
{
  int datasize;
  double data[];
};

struct named_init {
  int number;
  const wchar_t *name;
  double average;
};

typedef const char *ccp;

static inline int
test_restrict (ccp restrict text)
{
  // See if C++-style comments work.
  // Iterate through items via the restricted pointer.
  // Also check for declarations in for loops.
  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
    continue;
  return 0;
}

// Check varargs and va_copy.
static bool
test_varargs (const char *format, ...)
{
  va_list args;
  va_start (args, format);
  va_list args_copy;
  va_copy (args_copy, args);

  const char *str = "";
  int number = 0;
  float fnumber = 0;

  while (*format)
    {
      switch (*format++)
	{
	case '\''s'\'': // string
	  str = va_arg (args_copy, const char *);
	  break;
	case '\''d'\'': // int
	  number = va_arg (args_copy, int);
	  break;
	case '\''f'\'': // float
	  fnumber = va_arg (args_copy, double);
	  break;
	default:
	  break;
	}
    }
  va_end (args_copy);
  va_end (args);

  return *str && number && fnumber;
}
'

# Test code for whether the C compiler supports C99 (body of main).
ac_c_conftest_c99_main='
  // Check bool.
  _Bool success = false;
  success |= (argc != 0);

  // Check restrict.
  if (test_restrict ("String literal") == 0)
    success = true;
  char *restrict newvar = "Another string";

  // Check varargs.
  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
  test_varargs_macros ();

  // Check flexible array members.
  struct incomplete_array *ia =
    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
  ia->datasize = 10;
  for (int i = 0; i < ia->datasize; ++i)
    ia->data[i] = i * 1.234;

  // Check named initializers.
  struct named_init ni = {
    .number = 34,
    .name = L"Test wide string",
    .average = 543.34343,
  };

  ni.number = 58;

  int dynamic_array[ni.number];
  dynamic_array[0] = argv[0][0];
  dynamic_array[ni.number - 1] = 543;

  // work around unused variable warnings
  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
	 || dynamic_array[ni.number - 1] != 543);
'

# Test code for whether the C compiler supports C11 (global declarations)
ac_c_conftest_c11_globals='
// Does the compiler advertise C11 conformance?
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
# error "Compiler does not advertise C11 conformance"
#endif

// Check _Alignas.
char _Alignas (double) aligned_as_double;
char _Alignas (0) no_special_alignment;
extern char aligned_as_int;
char _Alignas (0) _Alignas (int) aligned_as_int;

// Check _Alignof.
enum
{
  int_alignment = _Alignof (int),
  int_array_alignment = _Alignof (int[100]),
  char_alignment = _Alignof (char)
};
_Static_assert (0 < -_Alignof (int), "_Alignof is signed");

// Check _Noreturn.
int _Noreturn does_not_return (void) { for (;;) continue; }

// Check _Static_assert.
struct test_static_assert
{
  int x;
  _Static_assert (sizeof (int) <= sizeof (long int),
                  "_Static_assert does not work in struct");
  long int y;
};

// Check UTF-8 literals.
#define u8 syntax error!
char const utf8_literal[] = u8"happens to be ASCII" "another string";

// Check duplicate typedefs.
typedef long *long_ptr;
typedef long int *long_ptr;
typedef long_ptr long_ptr;

// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
struct anonymous
{
  union {
    struct { int i; int j; };
    struct { int k; long int l; } w;
  };
  int m;
} v1;
'

# Test code for whether the C compiler supports C11 (body of main).
ac_c_conftest_c11_main='
  _Static_assert ((offsetof (struct anonymous, i)
		   == offsetof (struct anonymous, w.k)),
		  "Anonymous union alignment botch");
  v1.i = 2;
  v1.w.k = 5;
  ok |= v1.i != 5;
'

# Test code for whether the C compiler supports C11 (complete).
ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}
${ac_c_conftest_c11_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  ${ac_c_conftest_c11_main}
  return ok;
}
"

# Test code for whether the C compiler supports C99 (complete).
ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  return ok;
}
"

# Test code for whether the C compiler supports C89 (complete).
ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  return ok;
}
"

as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"

# Auxiliary files required by this configure script.
ac_aux_files="config.guess config.sub"

# Locations in which to look for auxiliary files.
ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."

# Search for a directory containing all of the required auxiliary files,
# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
# If we don't find one directory that contains all the files we need,
# we report the set of missing files from the *first* directory in
# $ac_aux_dir_candidates and give up.
ac_missing_aux_files=""
ac_first_candidate=:
printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in $ac_aux_dir_candidates
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
  as_found=:

  printf "%s\n" "$as_me:${as_lineno-$LINENO}:  trying $as_dir" >&5
  ac_aux_dir_found=yes
  ac_install_sh=
  for ac_aux in $ac_aux_files
  do
    # As a special case, if "install-sh" is required, that requirement
    # can be satisfied by any of "install-sh", "install.sh", or "shtool",
    # and $ac_install_sh is set appropriately for whichever one is found.
    if test x"$ac_aux" = x"install-sh"
    then
      if test -f "${as_dir}install-sh"; then
        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install-sh found" >&5
        ac_install_sh="${as_dir}install-sh -c"
      elif test -f "${as_dir}install.sh"; then
        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install.sh found" >&5
        ac_install_sh="${as_dir}install.sh -c"
      elif test -f "${as_dir}shtool"; then
        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}shtool found" >&5
        ac_install_sh="${as_dir}shtool install -c"
      else
        ac_aux_dir_found=no
        if $ac_first_candidate; then
          ac_missing_aux_files="${ac_missing_aux_files} install-sh"
        else
          break
        fi
      fi
    else
      if test -f "${as_dir}${ac_aux}"; then
        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}${ac_aux} found" >&5
      else
        ac_aux_dir_found=no
        if $ac_first_candidate; then
          ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
        else
          break
        fi
      fi
    fi
  done
  if test "$ac_aux_dir_found" = yes; then
    ac_aux_dir="$as_dir"
    break
  fi
  ac_first_candidate=false

  as_found=false
done
IFS=$as_save_IFS
if $as_found
then :

else $as_nop
  as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
fi


# These three variables are undocumented and unsupported,
# and are intended to be withdrawn in a future Autoconf release.
# They can cause serious problems if a builder's source tree is in a directory
# whose full name contains unusual characters.
if test -f "${ac_aux_dir}config.guess"; then
  ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
fi
if test -f "${ac_aux_dir}config.sub"; then
  ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
fi
if test -f "$ac_aux_dir/configure"; then
  ac_configure="$SHELL ${ac_aux_dir}configure"
fi

# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
  eval ac_old_set=\$ac_cv_env_${ac_var}_set
  eval ac_new_set=\$ac_env_${ac_var}_set
  eval ac_old_val=\$ac_cv_env_${ac_var}_value
  eval ac_new_val=\$ac_env_${ac_var}_value
  case $ac_old_set,$ac_new_set in
    set,)
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,set)
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,);;
    *)
      if test "x$ac_old_val" != "x$ac_new_val"; then
	# differences in whitespace do not lead to failure.
	ac_old_val_w=`echo x $ac_old_val`
	ac_new_val_w=`echo x $ac_new_val`
	if test "$ac_old_val_w" != "$ac_new_val_w"; then
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
	  ac_cache_corrupted=:
	else
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
	  eval $ac_var=\$ac_old_val
	fi
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
printf "%s\n" "$as_me:   former value:  \`$ac_old_val'" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
printf "%s\n" "$as_me:   current value: \`$ac_new_val'" >&2;}
      fi;;
  esac
  # Pass precious variables to config.status.
  if test "$ac_new_set" = set; then
    case $ac_new_val in
    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *) ac_arg=$ac_var=$ac_new_val ;;
    esac
    case " $ac_configure_args " in
      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
    esac
  fi
done
if $ac_cache_corrupted; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
	    and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu






  # Make sure we can run config.sub.
$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
  as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
printf %s "checking build system type... " >&6; }
if test ${ac_cv_build+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
  ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
  as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5

fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_build
shift
build_cpu=$1
build_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
build_os=$*
IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac


{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
printf %s "checking host system type... " >&6; }
if test ${ac_cv_host+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test "x$host_alias" = x; then
  ac_cv_host=$ac_cv_build
else
  ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi

fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_host
shift
host_cpu=$1
host_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
host_os=$*
IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac


{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
printf %s "checking target system type... " >&6; }
if test ${ac_cv_target+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test "x$target_alias" = x; then
  ac_cv_target=$ac_cv_host
else
  ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
fi

fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
printf "%s\n" "$ac_cv_target" >&6; }
case $ac_cv_target in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
esac
target=$ac_cv_target
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_target
shift
target_cpu=$1
target_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
target_os=$*
IFS=$ac_save_IFS
case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac


# The aliases save the names the user supplied, while $host etc.
# will get canonicalized.
test -n "$target_alias" &&
  test "$program_prefix$program_suffix$program_transform_name" = \
    NONENONEs,x,x, &&
  program_prefix=${target_alias}-

#--------------------------------------------------------------------
# CFITSIO Version Numbers:
#--------------------------------------------------------------------
CFITSIO_MAJOR=4

CFITSIO_MINOR=3

CFITSIO_MICRO=1

# Increment soname each time the interface changes:
CFITSIO_SONAME=10


#--------------------------------------------------------------------
# System type
#--------------------------------------------------------------------

case $host in
    *cygwin*)
	ARCH="cygwin"
	EXT="cygwin"
	;;
    *apple-darwin*)
	# Darwin can be powerpc, i386, or x86_64
	ARCH=`uname -p`
	EXT="darwin"
	;;
    *freebsd*)
	ARCH="linux"
	EXT="lnx"
	;;
    *haiku*)
        # Haiku can be arm, i386, or x86_64
        ARCH=`uname -p`
        EXT="haiku"
        ;;
    *hpux*)
	ARCH="hp"
	EXT="hpu"
	;;
    *irix*)
	ARCH="sgi"
	EXT="sgi"
	;;
    *linux*)
	ARCH="linux"
	EXT="lnx"
	;;
    *mingw32*)
	#ARCH=""
	EXT="mingw32"
	;;
    *osf1*)
	ARCH="alpha"
	EXT="osf"
	;;
    *solaris*)
	ARCH="solaris"
	EXT="sol"
	;;
    *ultrix*)
	ARCH="dec"
	EXT="dec"
	;;
    *)
	echo "cfitsio: == Don't know what to do with $host"
	;;
esac

#--------------------------------------------------------------------
# Try first to find a proprietary C compiler, then gcc
#--------------------------------------------------------------------
# This section needs to precede the command options since e.g. the
# bzip2 CHECK_LIB test needs a compiler and in the process sets "CC"
# if it isn't already set.

if test "x$CC" = x; then
  # Prefer clang on Darwin:
  if test "x$EXT" = xdarwin; then
    for ac_prog in clang
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  test -n "$CC" && break
done

    echo "Gabba Hey!: EXT=$EXT and CC=$CC"
  else
    if test "x$EXT" != xcygwin && test "x$EXT" != xlnx && test "x$EXT" != xmingw32; then
      for ac_prog in cc
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  test -n "$CC" && break
done

    fi
  fi
fi









ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}gcc"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="gcc"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

if test -z "$CC"; then
          if test -n "$ac_tool_prefix"; then
    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}cc"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  fi
fi
if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
       ac_prog_rejected=yes
       continue
     fi
    ac_cv_prog_CC="cc"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# != 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
  fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  for ac_prog in cl.exe
  do
    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


    test -n "$CC" && break
  done
fi
if test -z "$CC"; then
  ac_ct_CC=$CC
  for ac_prog in cl.exe
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  test -n "$ac_ct_CC" && break
done

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
fi

fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
set dummy ${ac_tool_prefix}clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "clang", so it can be a program name with args.
set dummy clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

fi


test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }

# Provide some information about the compiler.
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion -version; do
  { { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    sed '10a\
... rest of stderr output deleted ...
         10q' conftest.err >conftest.er1
    cat conftest.er1 >&5
  fi
  rm -f conftest.er1 conftest.err
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
done

cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
printf %s "checking whether the C compiler works... " >&6; }
ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`

# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"

ac_rmfiles=
for ac_file in $ac_files
do
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
  esac
done
rm -f $ac_rmfiles

if { { ac_try="$ac_link_default"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link_default") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile.  We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
	;;
    [ab].out )
	# We found the default executable, but exeext='' is most
	# certainly right.
	break;;
    *.* )
	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
	then :; else
	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	fi
	# We set ac_cv_exeext here because the later test for it is not
	# safe: cross compilers may not add the suffix if given an `-o'
	# argument, so we may need to know it at that point already.
	# Even if this section looks crufty: it has the advantage of
	# actually working.
	break;;
    * )
	break;;
  esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=

else $as_nop
  ac_file=''
fi
if test -z "$ac_file"
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
printf %s "checking for C compiler default output file name... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext

rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
for ac_file in conftest.exe conftest conftest.*; do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	  break;;
    * ) break;;
  esac
done
else $as_nop
  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
printf "%s\n" "$ac_cv_exeext" >&6; }

rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 
int
main (void)
{
FILE *f = fopen ("conftest.out", "w");
 return ferror (f) || fclose (f) != 0;

  ;
  return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run.  If not, either
# the compiler is broken, or we cross compile.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
  { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
  if { ac_try='./conftest$ac_cv_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }; then
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
    fi
  fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
printf "%s\n" "$cross_compiling" >&6; }

rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
printf %s "checking for suffix of object files... " >&6; }
if test ${ac_cv_objext+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  for ac_file in conftest.o conftest.obj conftest.*; do
  test -f "$ac_file" || continue;
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
       break;;
  esac
done
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_compiler_gnu=yes
else $as_nop
  ac_compiler_gnu=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu

fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
ac_compiler_gnu=$ac_cv_c_compiler_gnu

if test $ac_compiler_gnu = yes; then
  GCC=yes
else
  GCC=
fi
ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_save_c_werror_flag=$ac_c_werror_flag
   ac_c_werror_flag=yes
   ac_cv_prog_cc_g=no
   CFLAGS="-g"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
else $as_nop
  CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

else $as_nop
  ac_c_werror_flag=$ac_save_c_werror_flag
	 CFLAGS="-g"
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
if test $ac_test_CFLAGS; then
  CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi
else
  if test "$GCC" = yes; then
    CFLAGS="-O2"
  else
    CFLAGS=
  fi
fi
ac_prog_cc_stdc=no
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c11_program
_ACEOF
for ac_arg in '' -std=gnu11
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c11=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c11" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi

if test "x$ac_cv_prog_cc_c11" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else $as_nop
  if test "x$ac_cv_prog_cc_c11" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
     CC="$CC $ac_cv_prog_cc_c11"
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
  ac_prog_cc_stdc=c11
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c99_program
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi

if test "x$ac_cv_prog_cc_c99" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else $as_nop
  if test "x$ac_cv_prog_cc_c99" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
     CC="$CC $ac_cv_prog_cc_c99"
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
  ac_prog_cc_stdc=c99
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c89_program
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi

if test "x$ac_cv_prog_cc_c89" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else $as_nop
  if test "x$ac_cv_prog_cc_c89" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
     CC="$CC $ac_cv_prog_cc_c89"
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
  ac_prog_cc_stdc=c89
fi
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


#--------------------------------------------------------------------
# Command options
#--------------------------------------------------------------------

ADD_CURL=yes
# Check whether --enable-curl was given.
if test ${enable_curl+y}
then :
  enableval=$enable_curl;  if test $enableval = no; then ADD_CURL=no; fi

fi

if test "x$ADD_CURL" = xno; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Not linking with curl for remote file i/o support" >&5
printf "%s\n" "$as_me: WARNING: Not linking with curl for remote file i/o support" >&2;}
fi

# Check whether --enable-reentrant was given.
if test ${enable_reentrant+y}
then :
  enableval=$enable_reentrant;  if test $enableval = yes; then BUILD_REENTRANT=yes; fi

fi


SSE_FLAGS=""
# Check whether --enable-sse2 was given.
if test ${enable_sse2+y}
then :
  enableval=$enable_sse2;  if test $enableval = yes; then SSE_FLAGS="-msse2"; fi

fi


# Check whether --enable-ssse3 was given.
if test ${enable_ssse3+y}
then :
  enableval=$enable_ssse3;  if test $enableval = yes; then SSE_FLAGS="$SSE_FLAGS -mssse3"; fi

fi


SYMBOLS=""
# Check whether --enable-symbols was given.
if test ${enable_symbols+y}
then :
  enableval=$enable_symbols;  if test $enableval = yes; then SYMBOLS=yes; fi

fi


# Define BUILD_HERA when building for HERA project to activate code in
# drvrfile.c (by way of fitsio2.h):
# Check whether --enable-hera was given.
if test ${enable_hera+y}
then :
  enableval=$enable_hera;  if test $enableval = yes; then BUILD_HERA=yes; fi

fi

if test "x$BUILD_HERA" = xyes; then
  printf "%s\n" "#define BUILD_HERA 1" >>confdefs.h

fi

# Optional support for bzip2 compression:

ac_header= ac_cache=
for ac_item in $ac_header_c_list
do
  if test $ac_cache; then
    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
      printf "%s\n" "#define $ac_item 1" >> confdefs.h
    fi
    ac_header= ac_cache=
  elif test $ac_header; then
    ac_cache=$ac_item
  else
    ac_header=$ac_item
  fi
done








if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
then :

printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h

fi

# Check whether --with-bzip2 was given.
if test ${with_bzip2+y}
then :
  withval=$with_bzip2;  if test "x$withval" != "xno"; then
        if test "x$withval" = "xyes" ; then
            { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lbz2" >&5
printf %s "checking for main in -lbz2... " >&6; }
if test ${ac_cv_lib_bz2_main+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_check_lib_save_LIBS=$LIBS
LIBS="-lbz2  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */


int
main (void)
{
return main ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_bz2_main=yes
else $as_nop
  ac_cv_lib_bz2_main=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_main" >&5
printf "%s\n" "$ac_cv_lib_bz2_main" >&6; }
if test "x$ac_cv_lib_bz2_main" = xyes
then :
  printf "%s\n" "#define HAVE_LIBBZ2 1" >>confdefs.h

  LIBS="-lbz2 $LIBS"

else $as_nop
  as_fn_error $? "Unable to locate bz2 library needed when enabling bzip2 support; try specifying the path" "$LINENO" 5
fi

        else
            BZIP2_PATH="${withval}"
        fi
               for ac_header in bzlib.h
do :
  ac_fn_c_check_header_compile "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default"
if test "x$ac_cv_header_bzlib_h" = xyes
then :
  printf "%s\n" "#define HAVE_BZLIB_H 1" >>confdefs.h

printf "%s\n" "#define HAVE_BZIP2 1" >>confdefs.h

fi

done
    fi


fi


# Optional Globus Toolkit support:

# Check whether --with-gsiftp was given.
if test ${with_gsiftp+y}
then :
  withval=$with_gsiftp;  if test "x$withval" != "xno"; then
        if test "x$withval" != "xyes" ; then
            GSIFTP_PATH="${withval}"
        fi

printf "%s\n" "#define HAVE_GSIFTP 1" >>confdefs.h

        USE_GSIFTP=yes
    fi


fi

# GSIFTP source code (optional):
if test "x$USE_GSIFTP" = xyes; then
   GSIFTP_SRC="drvrgsiftp.c"
else
   GSIFTP_SRC=""
fi



# Check whether --with-gsiftp-flavour was given.
if test ${with_gsiftp_flavour+y}
then :
  withval=$with_gsiftp_flavour;  if test "x$withval" != "xno"; then
        if test "x$withval" != "xyes" ; then
            GSIFTP_FLAVOUR="${withval}"
        fi

printf "%s\n" "#define GSIFTP_FLAVOUR 1" >>confdefs.h

    fi


fi


# Optionally disable check for zlib:
ZLIB_CHECK=yes

# Check whether --with-zlib-check was given.
if test ${with_zlib_check+y}
then :
  withval=$with_zlib_check;  if test "x$withval" = "xno"; then
       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cfitsio: ZLIB is required!" >&5
printf "%s\n" "$as_me: WARNING: cfitsio: ZLIB is required!" >&2;}
       ZLIB_CHECK=no
    fi


fi


#--------------------------------------------------------------------
# Check for install location prefix
#--------------------------------------------------------------------



# make will complain about duplicate targets for the install directories
# if prefix == exec_prefix
INSTALL_ROOT='${prefix}'

test "$exec_prefix" != NONE -a "$prefix" != "$exec_prefix" \
  && INSTALL_ROOT="$INSTALL_ROOT "'${exec_prefix}'

#-------------------------------------------------------------------------------
# Handle --enable-symbols=yes
#-------------------------------------------------------------------------------

# Remove existing/default optimization:
if test "x$SYMBOLS" = "xyes"; then

   COPT_DEFAULT=`echo $CFLAGS | tr " " "\012" | grep "^-O[0-9]"`

   CFLAGS=`echo $CFLAGS | sed "s:$COPT_DEFAULT::g"`
fi

#-------------------------------------------------------------------------------

LDFLAGS="$CFLAGS"
LDFLAGS_BIN="$LDFLAGS"

if test "x$FC" = "xnone" ; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: cfitsio: == Fortran compiler search has been overridden" >&5
printf "%s\n" "$as_me: cfitsio: == Fortran compiler search has been overridden" >&6;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: cfitsio: == Cfitsio will be built without Fortran wrapper support" >&5
printf "%s\n" "$as_me: cfitsio: == Cfitsio will be built without Fortran wrapper support" >&6;}
  FC=
  F77_WRAPPERS=
else
  for ac_prog in gfortran g95 g77 f77 ifort f95 f90 xlf cf77 gf77 af77 ncf f2c
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_FC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$FC"; then
  ac_cv_prog_FC="$FC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_FC="$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
FC=$ac_cv_prog_FC
if test -n "$FC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FC" >&5
printf "%s\n" "$FC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  test -n "$FC" && break
done
test -n "$FC" || FC="notfound"

  if test $FC = 'notfound' ; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cfitsio: == No acceptable Fortran compiler found in \$PATH" >&5
printf "%s\n" "$as_me: WARNING: cfitsio: == No acceptable Fortran compiler found in \$PATH" >&2;}
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: cfitsio: == Adding wrapper support for GNU Fortran by default" >&5
printf "%s\n" "$as_me: cfitsio: == Adding wrapper support for GNU Fortran by default" >&6;}
    CFORTRANFLAGS="-Dg77Fortran"
    F77_WRAPPERS="\${FITSIO_SRC}"
  else
    CFORTRANFLAGS=
    F77_WRAPPERS="\${FITSIO_SRC}"
    echo $ac_n "checking whether we are using GNU Fortran""... $ac_c" 1>&6
    if test `$FC --version -c < /dev/null 2> /dev/null | grep -c GNU` -gt 0 -o \
            `$FC --version -c < /dev/null 2> /dev/null | grep -ic egcs` -gt 0
    then
      echo "$ac_t""yes" 1>&6
      echo $ac_n "cfitsio: == Adding wrapper support for GNU Fortran""... $ac_c" 1>&6
      CFORTRANFLAGS="-Dg77Fortran"
      echo "$ac_t"" done" 1>&6
    else
      echo "$ac_t""no" 1>&6
      if test $FC = 'f2c' ; then
        echo $ac_n "cfitsio: == Adding wrapper support for f2c""... $ac_c" 1>&6
        CFORTRANFLAGS="-Df2cFortran"
        echo "$ac_t"" done" 1>&6
      fi
    fi
  fi
fi

# ar & ranlib required
#---------------------
# Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$AR"; then
  ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_AR="ar"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

  test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="noar"
fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


if test $AR = noar; then
  as_fn_error $? "ar not found in your \$PATH. See your sysdamin." "$LINENO" 5
fi
ARCHIVE="$AR rv"


if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RANLIB+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_RANLIB"; then
  ac_ct_RANLIB=$RANLIB
  # Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RANLIB+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_RANLIB"; then
  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_RANLIB="ranlib"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_RANLIB" = x; then
    RANLIB=":"
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    RANLIB=$ac_ct_RANLIB
  fi
else
  RANLIB="$ac_cv_prog_RANLIB"
fi


       for ac_header in stdlib.h string.h math.h limits.h
do :
  as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"
then :
  cat >>confdefs.h <<_ACEOF
#define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
 ANSI_HEADER=yes
else $as_nop
  ANSI_HEADER=no
fi

done
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{
void d( int , double)
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  PROTO=yes
else $as_nop
  PROTO=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test $ANSI_HEADER = no -o $PROTO = no; then
     echo "   *********** WARNING: CFITSIO CONFIGURE FAILURE ************  "
     echo "cfitsio: ANSI C environment NOT found. Aborting cfitsio configure."
     if test $ANSI_HEADER = no; then
        echo "cfitsio: You're missing a needed ANSI header file."
     fi
     if test $PROTO = no; then
        echo "cfitsio: Your compiler can't do ANSI function prototypes."
     fi
     echo "cfitsio: You need an ANSI C compiler and all ANSI trappings"
     echo "cfitsio: to build cfitsio.   "
     echo "     *******************************************************  "
     exit 0;
fi

if test "x$SSE_FLAGS" != x; then
    SAVE_CFLAGS="$CFLAGS"
    CFLAGS="$CFLAGS $SSE_FLAGS"
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts $SSE_FLAGS" >&5
printf %s "checking whether $CC accepts $SSE_FLAGS... " >&6; }
    ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  c_has_option=yes
else $as_nop
  c_has_option=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $c_has_option" >&5
printf "%s\n" "$c_has_option" >&6; }
    ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu

    if test "$c_has_option" = no; then SSE_FLAGS=""; fi
    CFLAGS="$SAVE_CFLAGS"
fi


CFLAGS="$CFLAGS"
LIBPRE=""

case $host in
    *cygwin*)
	CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS"
        # LDFLAGS used by utilities:
        LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}"
	;;
    *apple-darwin*)

        case $host in
            *darwin[56789]*)
                ;;
            *)

#                # Build for i386 & x86_64 architectures on Darwin 10.x or newer:
#                echo "int main(){return(0);}" > /tmp/$$.c
#                $CC -v -o /tmp/$$.out /tmp/$$.c 2> /tmp/$$.log
#                if test `cat /tmp/$$.log | grep -ci 'LLVM'` -ne 0; then APPLEXCODE="yes"; fi
#                if test "x$APPLEXCODE" = xyes; then
#                  # Flags for building Universal binaries:
#                  C_UNIV_SWITCH="-arch i386 -arch x86_64"
#                  CFLAGS="$CFLAGS $C_UNIV_SWITCH"
#                fi
                # LDFLAGS used by utilities:
                LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}"
                ;;
        esac
        # For large file support (but may break Absoft compilers):
        printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h

        printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h

	;;
    *haiku*)
        # For large file support:
        printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h

        printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h

        ;;
    *hpux*)
	if test "x$CFORTRANFLAGS" = x ; then
		CFORTRANFLAGS="-Dappendus"
	fi
	CFLAGS="$CFLAGS -DPG_PPU"
	LIBPRE="-Wl,"
	;;
    *irix*)
	CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS"
	RANLIB="touch"
	;;
    *linux*)
        # For large file support:
        printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h

        printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h

        # LDFLAGS used by utilities:
        LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}"
	;;
    *mingw32*)
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for large file support" >&5
printf %s "checking for large file support... " >&6; }
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 
int
main (void)
{
_FILE_OFFSET_BITS_SET_FSEEKO
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

            printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h

            printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h

            { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
        ;;
    *solaris*)
        if test "x$CFORTRANFLAGS" = x ; then
                CFORTRANFLAGS="-Dsolaris"
        fi
        # We need libm on Solaris:
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for frexp in -lm" >&5
printf %s "checking for frexp in -lm... " >&6; }
if test ${ac_cv_lib_m_frexp+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_check_lib_save_LIBS=$LIBS
LIBS="-lm  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
char frexp ();
int
main (void)
{
return frexp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_m_frexp=yes
else $as_nop
  ac_cv_lib_m_frexp=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_frexp" >&5
printf "%s\n" "$ac_cv_lib_m_frexp" >&6; }
if test "x$ac_cv_lib_m_frexp" = xyes
then :
  printf "%s\n" "#define HAVE_LIBM 1" >>confdefs.h

  LIBS="-lm $LIBS"

fi

        # For large file support:
        printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h

        printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h

	;;
    *)
		echo "cfitsio: == Don't know what do do with $host"
	;;
esac

CFLAGS="$CFLAGS $CFORTRANFLAGS"

case $GCC in
	yes)
		GCCVERSION="`$CC -dumpversion 2>&1`"
		echo "cfitsio: == Using $CC version $GCCVERSION"


		gcc_test=`echo $GCCVERSION | grep -c '2\.[45678]'`

		if test $gcc_test -gt 0
		then

		    CFLAGS=`echo $CFLAGS | sed 's:-O[^ ]* *::'`

		    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: This gcc is pretty old. Disabling optimization to be safe." >&5
printf "%s\n" "$as_me: WARNING: This gcc is pretty old. Disabling optimization to be safe." >&2;}
		fi
		;;
	no)
		echo "cfitsio: Old CFLAGS is $CFLAGS"
		CFLAGS=`echo $CFLAGS | sed -e "s/-g/-O/"`
		case $host in
		    *solaris*)

			if test `echo $CFLAGS | grep -c fast` -gt 0
			then
			   echo "cfitsio: Replacing -fast with -O3"
			   CFLAGS=`echo $CFLAGS | sed 's:-fast:-O3:'`
			fi

         		CFLAGS="$CFLAGS -DHAVE_ALLOCA_H -DHAVE_POSIX_SIGNALS"
			;;
		    *)
			echo "== No special changes for $host"
			;;
		esac
		echo "New CFLAGS is $CFLAGS"
		;;
	*)
		# Don't do anything now
		;;
esac

# Shared library section
#-------------------------------------------------------------------------------
SHLIB_LD=:
SHLIB_SUFFIX=".so"
CFITSIO_SHLIB=""
CFITSIO_SHLIB_SONAME=""
lhea_shlib_cflags=
case $EXT in
  cygwin|mingw32)
    SHLIB_LD="$CC -shared"
    SHLIB_SUFFIX=".dll"
    ;;
  darwin)

    SHLIB_SUFFIX=".dylib"
    CFITSIO_SHLIB="lib\${PACKAGE}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}.\${CFITSIO_MICRO}\${SHLIB_SUFFIX}"
    CFITSIO_SHLIB_SONAME="lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX}"
    case $host in
        *darwin[56789]*)
            SHLIB_LD="$CC -dynamiclib -install_name lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}.\${CFITSIO_MICRO}"
            ;;
        *)
            # Build 'Universal' binaries (i386 & x86_64 architectures) and
            # use rpath token on Darwin 10.x or newer:
            SHLIB_LD="$CC -dynamiclib $C_UNIV_SWITCH -headerpad_max_install_names -install_name @rpath/lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}.\${CFITSIO_MICRO}"
            ;;
    esac

    lhea_shlib_cflags="-fPIC -fno-common"
    ;;
  haiku)
    SHLIB_LD=":"
    CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}.\${CFITSIO_MICRO}"
    CFITSIO_SHLIB_SONAME="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}"
    ;;
  hpu)
    SHLIB_LD="ld -b"
    SHLIB_SUFFIX=".sl"
    ;;
  lnx)
    SHLIB_LD=":"
    CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}.\${CFITSIO_MICRO}"
    CFITSIO_SHLIB_SONAME="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}"
    ;;
  osf)
    SHLIB_LD="ld -shared -expect_unresolved '*'"
    LD_FLAGS="-taso"
    ;;
  sol)
    SHLIB_LD="/usr/ccs/bin/ld -G"
    lhea_shlib_cflags="-KPIC"
    ;;
  sgi)
    SHLIB_LD="ld -shared -rdata_shared"
    ;;
  *)
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Unable to determine how to make a shared library" >&5
printf "%s\n" "$as_me: WARNING: Unable to determine how to make a shared library" >&2;}
    ;;
esac
# Darwin uses gcc (=cc), but needs different flags (see above)
if test "x$EXT" != xdarwin && test "x$EXT" != xcygwin && test "x$EXT" != xmingw32; then
  if test "x$GCC" = xyes; then
    SHLIB_LD="$CC -shared -Wl,-soname,lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}"
    lhea_shlib_cflags='-fPIC'
  fi
fi
if test "x$lhea_shlib_cflags" != x; then
  CFLAGS="$CFLAGS $lhea_shlib_cflags"
fi
# Set shared library name for cases in which we aren't setting a 'soname':
if test "x$CFITSIO_SHLIB" = x; then CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}"; fi

# Curl library (will be pulled in to the shared CFITSIO library):
# ---------------------------------------------------------------
CURL_INC=""
CURL_LIB=""
CURL_LIB_PATH=""
if test "x$ADD_CURL" = xyes; then
  # Use curl-config to get compiler & linker flags, if available.
  # (and prefer /usr/bin/curl-config)
  # Extract the first word of "curl-config", so it can be a program name with args.
set dummy curl-config; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_path_CURLCONFIG+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  case $CURLCONFIG in
  [\\/]* | ?:[\\/]*)
  ac_cv_path_CURLCONFIG="$CURLCONFIG" # Let the user override the test with a path.
  ;;
  *)
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /usr/bin$PATH_SEPARATOR$PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_path_CURLCONFIG="$as_dir$ac_word$ac_exec_ext"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

  ;;
esac
fi
CURLCONFIG=$ac_cv_path_CURLCONFIG
if test -n "$CURLCONFIG"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CURLCONFIG" >&5
printf "%s\n" "$CURLCONFIG" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  if test "x$CURLCONFIG" != x; then
    CURL_LIB=`$CURLCONFIG --libs`
    CURL_INC=`$CURLCONFIG --cflags`
    if test "x$CURL_LIB" != x; then
      LIBS_CURL="$CURL_LIB"
      # Mac OS: For third-party curl-config, acquire an rpath:
      if test `echo $host | grep -c apple-darwin` -ne 0 -a `echo $CURL_LIB | grep -c "^-L"` -gt 0; then
        CURL_LIB_PATH=`echo ${CURL_LIB} | tr " " "\012" | grep "^-L" | tr "\012" " " | sed 's:-L::' | sed 's: $::'`
        if test "x$CURL_LIB_PATH" != x; then
          LIBS_CURL="-Wl,-rpath,$CURL_LIB_PATH $CURL_LIB"
        fi
      fi
      if test `echo $host | grep -c cygwin` -ne 0 -o `echo $host | grep -c mingw32` -ne 0; then
          LIBS="$CURL_LIB $LIBS"
      fi
      printf "%s\n" "#define CFITSIO_HAVE_CURL 1" >>confdefs.h

    fi
    if test "x$CURL_INC" != x; then
      CFLAGS="$CURL_INC $CFLAGS"
    fi
  # No curl-config:
  else
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: curl-config not found. Disabling curl support." >&5
printf "%s\n" "$as_me: WARNING: curl-config not found. Disabling curl support." >&2;}
  # Incomplete stubs for possible future use:
  #  AC_CHECK_LIB([curl],[main],[],
  #       [AC_MSG_WARN(Not building curl support for CFITSIO)])
  #  AC_CHECK_HEADER(curl.h,[])
  fi
fi


# ZLIB (required):
if test "x$ZLIB_CHECK" = xyes; then
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5
printf %s "checking for inflateEnd in -lz... " >&6; }
if test ${ac_cv_lib_z_inflateEnd+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_check_lib_save_LIBS=$LIBS
LIBS="-lz  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
char inflateEnd ();
int
main (void)
{
return inflateEnd ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_z_inflateEnd=yes
else $as_nop
  ac_cv_lib_z_inflateEnd=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5
printf "%s\n" "$ac_cv_lib_z_inflateEnd" >&6; }
if test "x$ac_cv_lib_z_inflateEnd" = xyes
then :
  printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h

  LIBS="-lz $LIBS"

else $as_nop
  as_fn_error $? "Unable to locate zlib compression library" "$LINENO" 5
fi

fi

# GSIFTP flags:
if test "x$GSIFTP_PATH" != x -a "x$GSIFTP_FLAVOUR" != x; then
   CFLAGS="$CFLAGS -I${GSIFTP_PATH}/include/${GSIFTP_FLAVOUR}"
   LIBS="$LIBS -L${GSIFTP_PATH}/lib -lglobus_ftp_client_${GSIFTP_FLAVOUR}"
fi

# BZIP2 flags:
if test "x$BZIP2_PATH" != x; then
   CFLAGS="$CFLAGS -I${BZIP2_PATH}/include"
   LIBS="$LIBS -L${BZIP2_PATH}/lib -lbz2"
fi




# ================= test for the unix ftruncate function ================

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ftruncate works" >&5
printf %s "checking whether ftruncate works... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 

int
main (void)
{

ftruncate(0, 0);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :

printf "%s\n" "#define HAVE_FTRUNCATE 1" >>confdefs.h

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext

# ---------------------------------------------------------
# some systems define long long for 64-bit ints
# ---------------------------------------------------------

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether long long is defined" >&5
printf %s "checking whether long long is defined... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 

int
main (void)
{

long long filler;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

printf "%s\n" "#define HAVE_LONGLONG 1" >>confdefs.h

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

# ==================== SHARED MEMORY DRIVER SECTION =======================
#
# 09-Mar-98 : modified by JB/ISDC
# 3 checks added to support autoconfiguration of shared memory
# driver. First generic check is made whether shared memory is supported
# at all, then 2 more specific checks are made (architecture dependent).
# Currently tested on : sparc-solaris, intel-linux, sgi-irix, dec-alpha-osf

# -------------------------------------------------------------------------
# check is System V IPC is supported on this machine
# -------------------------------------------------------------------------

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether system V style IPC services are supported" >&5
printf %s "checking whether system V style IPC services are supported... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 
#include 
#include 

int
main (void)
{

shmat(0, 0, 0);
shmdt(0);
shmget(0, 0, 0);
semget(0, 0, 0);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :

printf "%s\n" "#define HAVE_SHMEM_SERVICES 1" >>confdefs.h

my_shmem=\${SOURCES_SHMEM}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext



# -------------------------------------------------------------------------
# some systems define flock_t, for others we have to define it ourselves
# -------------------------------------------------------------------------

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether flock_t is defined in sys/fcntl.h" >&5
printf %s "checking whether flock_t is defined in sys/fcntl.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 

int
main (void)
{

flock_t filler;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

printf "%s\n" "#define HAVE_FLOCK_T 1" >>confdefs.h

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

if test "$HAVE_FLOCK_T" != 1; then
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether flock_t is defined in sys/flock.h" >&5
printf %s "checking whether flock_t is defined in sys/flock.h... " >&6; }
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 

int
main (void)
{

   flock_t filler;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

   printf "%s\n" "#define HAVE_FLOCK_T 1" >>confdefs.h

   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi

# ------------------------------------------------------------------------------
# Define _REENTRANT & add -lpthread to LIBS if reentrant multithreading enabled:
# ------------------------------------------------------------------------------
if test "x$BUILD_REENTRANT" = xyes; then
  printf "%s\n" "#define _REENTRANT 1" >>confdefs.h

  printf "%s\n" "#define _XOPEN_SOURCE 700" >>confdefs.h

  # Additional definition needed to get 'union semun' when using
  # _XOPEN_SOURCE on a Mac:
  if test "x$EXT" = xdarwin; then
    printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h

  fi
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
printf %s "checking for main in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread_main+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */


int
main (void)
{
return main ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthread_main=yes
else $as_nop
  ac_cv_lib_pthread_main=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
printf "%s\n" "$ac_cv_lib_pthread_main" >&6; }
if test "x$ac_cv_lib_pthread_main" = xyes
then :
  printf "%s\n" "#define HAVE_LIBPTHREAD 1" >>confdefs.h

  LIBS="-lpthread $LIBS"

else $as_nop
  as_fn_error $? "Unable to locate pthread library needed when enabling reentrant multithreading" "$LINENO" 5
fi

fi

# -------------------------------------------------------------------------
# there are some idiosyncrasies with semun defs (used in semxxx). Solaris
# does not define it at all
# -------------------------------------------------------------------------

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether union semun is defined" >&5
printf %s "checking whether union semun is defined... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include 
#include 
#include 

int
main (void)
{

union semun filler;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

printf "%s\n" "#define HAVE_UNION_SEMUN 1" >>confdefs.h

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

# -------------------------------------------------------------------------
# fmemopen is not available on e.g. older Macs:
# -------------------------------------------------------------------------

ac_fn_c_check_func "$LINENO" "fmemopen" "ac_cv_func_fmemopen"
if test "x$ac_cv_func_fmemopen" = xyes
then :
  printf "%s\n" "#define HAVE_FMEMOPEN 1" >>confdefs.h

else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Disabling support for compressed files via FTPS" >&5
printf "%s\n" "$as_me: WARNING: Disabling support for compressed files via FTPS" >&2;}
fi


# ==================== END OF SHARED MEMORY DRIVER SECTION ================
# ================= test for the unix networking functions ================

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
printf %s "checking for library containing gethostbyname... " >&6; }
if test ${ac_cv_search_gethostbyname+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
char gethostbyname ();
int
main (void)
{
return gethostbyname ();
  ;
  return 0;
}
_ACEOF
for ac_lib in '' nsl network
do
  if test -z "$ac_lib"; then
    ac_res="none required"
  else
    ac_res=-l$ac_lib
    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
  fi
  if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_search_gethostbyname=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext
  if test ${ac_cv_search_gethostbyname+y}
then :
  break
fi
done
if test ${ac_cv_search_gethostbyname+y}
then :

else $as_nop
  ac_cv_search_gethostbyname=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
printf "%s\n" "$ac_cv_search_gethostbyname" >&6; }
ac_res=$ac_cv_search_gethostbyname
if test "$ac_res" != no
then :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
  cfitsio_have_nsl=1
else $as_nop
  cfitsio_have_nsl=0
fi

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing connect" >&5
printf %s "checking for library containing connect... " >&6; }
if test ${ac_cv_search_connect+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
char connect ();
int
main (void)
{
return connect ();
  ;
  return 0;
}
_ACEOF
for ac_lib in '' socket network
do
  if test -z "$ac_lib"; then
    ac_res="none required"
  else
    ac_res=-l$ac_lib
    LIBS="-l$ac_lib -lnsl $ac_func_search_save_LIBS"
  fi
  if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_search_connect=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext
  if test ${ac_cv_search_connect+y}
then :
  break
fi
done
if test ${ac_cv_search_connect+y}
then :

else $as_nop
  ac_cv_search_connect=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_connect" >&5
printf "%s\n" "$ac_cv_search_connect" >&6; }
ac_res=$ac_cv_search_connect
if test "$ac_res" != no
then :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
  cfitsio_have_socket=1
else $as_nop
  cfitsio_have_socket=0
fi


if test "$cfitsio_have_nsl" = 1 -a "$cfitsio_have_socket" = 1; then
   printf "%s\n" "#define HAVE_NET_SERVICES 1" >>confdefs.h

fi

# ==================== END OF unix networking SECTION ================

ac_config_files="$ac_config_files Makefile"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# following values.

_ACEOF

# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done

  (set) 2>&1 |
    case $as_nl`(ac_space=' '; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      # `set' does not quote correctly, so add quotes: double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \.
      sed -n \
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;; #(
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
) |
  sed '
     /^ac_cv_env_/b end
     t clear
     :clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
     t end
     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     :end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
  if test -w "$cache_file"; then
    if test "x$cache_file" != "x/dev/null"; then
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
      if test ! -f "$cache_file" || test -h "$cache_file"; then
	cat confcache >"$cache_file"
      else
        case $cache_file in #(
        */* | ?:*)
	  mv -f confcache "$cache_file"$$ &&
	  mv -f "$cache_file"$$ "$cache_file" ;; #(
        *)
	  mv -f confcache "$cache_file" ;;
	esac
      fi
    fi
  else
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
  fi
fi
rm -f confcache

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then branch to the quote section.  Otherwise,
# look for a macro that doesn't take arguments.
ac_script='
:mline
/\\$/{
 N
 s,\\\n,,
 b mline
}
t clear
:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
	g
	s/^\n//
	s/\n/ /g
	p
}
'
DEFS=`sed -n "$ac_script" confdefs.h`


ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
  # 1. Remove the extension, and $U if already installed.
  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
  #    will be set to the directory where LIBOBJS objects are built.
  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs

LTLIBOBJS=$ac_ltlibobjs



: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.

debug=false
ac_cs_recheck=false
ac_cs_silent=false

SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else $as_nop
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" ""	$as_nl"

PS1='$ '
PS2='> '
PS4='+ '

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi



# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error



# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit

# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset

# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else $as_nop
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else $as_nop
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith


if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null


# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
      test -d "$as_dir" && break
    done
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"


} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi


# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by $as_me, which was
generated by GNU Autoconf 2.71.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

on `(hostname || uname -n) 2>/dev/null | sed 1q`
"

_ACEOF

case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac



cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
from templates according to the current configuration.  Unless the files
and actions are specified as TAGs, all are instantiated by default.

Usage: $0 [OPTION]... [TAG]...

  -h, --help       print this help, then exit
  -V, --version    print version number and configuration settings, then exit
      --config     print configuration, then exit
  -q, --quiet, --silent
                   do not print progress messages
  -d, --debug      don't remove temporary files
      --recheck    update $as_me by reconfiguring in the same conditions
      --file=FILE[:TEMPLATE]
                   instantiate the configuration file FILE

Configuration files:
$config_files

Report bugs to the package provider."

_ACEOF
ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.71,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

ac_pwd='$ac_pwd'
srcdir='$srcdir'
test -n "\$AWK" || AWK=awk
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
  case $1 in
  --*=?*)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
    ac_shift=:
    ;;
  --*=)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=
    ac_shift=:
    ;;
  *)
    ac_option=$1
    ac_optarg=$2
    ac_shift=shift
    ;;
  esac

  case $ac_option in
  # Handling of the options.
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    ac_cs_recheck=: ;;
  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    printf "%s\n" "$ac_cs_config"; exit ;;
  --debug | --debu | --deb | --de | --d | -d )
    debug=: ;;
  --file | --fil | --fi | --f )
    $ac_shift
    case $ac_optarg in
    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    '') as_fn_error $? "missing file argument" ;;
    esac
    as_fn_append CONFIG_FILES " '$ac_optarg'"
    ac_need_defaults=false;;
  --he | --h |  --help | --hel | -h )
    printf "%s\n" "$ac_cs_usage"; exit ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil | --si | --s)
    ac_cs_silent=: ;;

  # This is an error.
  -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;

  *) as_fn_append ac_config_targets " $1"
     ac_need_defaults=false ;;

  esac
  shift
done

ac_configure_extra_args=

if $ac_cs_silent; then
  exec 6>/dev/null
  ac_configure_extra_args="$ac_configure_extra_args --silent"
fi

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  shift
  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
  CONFIG_SHELL='$SHELL'
  export CONFIG_SHELL
  exec "\$@"
fi

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
  printf "%s\n" "$ac_log"
} >&5

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1

# Handling of arguments.
for ac_config_target in $ac_config_targets
do
  case $ac_config_target in
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
  esac
done


# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
  tmp= ac_tmp=
  trap 'exit_status=$?
  : "${ac_tmp:=$tmp}"
  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
  trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.

{
  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
  test -d "$tmp"
}  ||
{
  tmp=./conf$$-$RANDOM
  (umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp

# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
if test -n "$CONFIG_FILES"; then


ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
  eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
  ac_cs_awk_cr='\\r'
else
  ac_cs_awk_cr=$ac_cr
fi

echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF


{
  echo "cat >conf$$subs.awk <<_ACEOF" &&
  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
  echo "_ACEOF"
} >conf$$subs.sh ||
  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
  . ./conf$$subs.sh ||
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5

  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
  if test $ac_delim_n = $ac_delim_num; then
    break
  elif $ac_last_try; then
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
  else
    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
  fi
done
rm -f conf$$subs.sh

cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s/'"$ac_delim"'$//
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t delim
' >$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
  for (key in S) S_is_set[key] = 1
  FS = ""

}
{
  line = $ 0
  nfields = split(line, field, "@")
  substed = 0
  len = length(field[1])
  for (i = 2; i < nfields; i++) {
    key = field[i]
    keylen = length(key)
    if (S_is_set[key]) {
      value = S[key]
      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
      len += length(value) + length(field[++i])
      substed = 1
    } else
      len += 1 + keylen
  }

  print line
}

_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
  cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF

# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
h
s///
s/^/:/
s/[	 ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
x
s/\(=[	 ]*\).*/\1/
G
s/\n//
s/^[^=]*=[	 ]*$//
}'
fi

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"


eval set X "  :F $CONFIG_FILES      "
shift
for ac_tag
do
  case $ac_tag in
  :[FHLC]) ac_mode=$ac_tag; continue;;
  esac
  case $ac_mode$ac_tag in
  :[FHL]*:*);;
  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
  :[FH]-) ac_tag=-:-;;
  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
  esac
  ac_save_IFS=$IFS
  IFS=:
  set x $ac_tag
  IFS=$ac_save_IFS
  shift
  ac_file=$1
  shift

  case $ac_mode in
  :L) ac_source=$1;;
  :[FH])
    ac_file_inputs=
    for ac_f
    do
      case $ac_f in
      -) ac_f="$ac_tmp/stdin";;
      *) # Look for the file first in the build tree, then in the source tree
	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
	 # because $ac_f cannot contain `:'.
	 test -f "$ac_f" ||
	   case $ac_f in
	   [\\/$]*) false;;
	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
	   esac ||
	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
      esac
      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      as_fn_append ac_file_inputs " '$ac_f'"
    done

    # Let's still pretend it is `configure' which instantiates (i.e., don't
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
printf "%s\n" "$as_me: creating $ac_file" >&6;}
    fi
    # Neutralize special characters interpreted by sed in replacement strings.
    case $configure_input in #(
    *\&* | *\|* | *\\* )
       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
       sed 's/[\\\\&|]/\\\\&/g'`;; #(
    *) ac_sed_conf_input=$configure_input;;
    esac

    case $ac_tag in
    *:-:* | *:-) cat >"$ac_tmp/stdin" \
      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
    esac
    ;;
  esac

  ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
  as_dir="$ac_dir"; as_fn_mkdir_p
  ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # We are building in place.
    ac_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    ac_abs_top_srcdir=$ac_pwd ;;
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix


  case $ac_mode in
  :F)
  #
  # CONFIG_FILE
  #

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
  p
  q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_datarootdir_hack='
  s&@datadir@&$datadir&g
  s&@docdir@&$docdir&g
  s&@infodir@&$infodir&g
  s&@localedir@&$localedir&g
  s&@mandir@&$mandir&g
  s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF

# Neutralize VPATH when `$srcdir' = `.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5

test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
      "$ac_tmp/out"`; test -z "$ac_out"; } &&
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&5
printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&2;}

  rm -f "$ac_tmp/stdin"
  case $ac_file in
  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
  esac \
  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 ;;



  esac

done # for ac_tag


as_fn_exit 0
_ACEOF
ac_clean_files=$ac_clean_files_save

test $ac_write_fail = 0 ||
  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5


# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded.  So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status.  When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
  ac_cs_success=:
  ac_config_status_args=
  test "$silent" = yes &&
    ac_config_status_args="$ac_config_status_args --quiet"
  exec 5>/dev/null
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi

ac_config_files="$ac_config_files cfitsio.pc"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# following values.

_ACEOF

# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done

  (set) 2>&1 |
    case $as_nl`(ac_space=' '; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      # `set' does not quote correctly, so add quotes: double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \.
      sed -n \
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;; #(
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
) |
  sed '
     /^ac_cv_env_/b end
     t clear
     :clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
     t end
     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     :end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
  if test -w "$cache_file"; then
    if test "x$cache_file" != "x/dev/null"; then
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
      if test ! -f "$cache_file" || test -h "$cache_file"; then
	cat confcache >"$cache_file"
      else
        case $cache_file in #(
        */* | ?:*)
	  mv -f confcache "$cache_file"$$ &&
	  mv -f "$cache_file"$$ "$cache_file" ;; #(
        *)
	  mv -f confcache "$cache_file" ;;
	esac
      fi
    fi
  else
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
  fi
fi
rm -f confcache

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then branch to the quote section.  Otherwise,
# look for a macro that doesn't take arguments.
ac_script='
:mline
/\\$/{
 N
 s,\\\n,,
 b mline
}
t clear
:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
	g
	s/^\n//
	s/\n/ /g
	p
}
'
DEFS=`sed -n "$ac_script" confdefs.h`


ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
  # 1. Remove the extension, and $U if already installed.
  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
  #    will be set to the directory where LIBOBJS objects are built.
  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs

LTLIBOBJS=$ac_ltlibobjs



: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.

debug=false
ac_cs_recheck=false
ac_cs_silent=false

SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else $as_nop
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" ""	$as_nl"

PS1='$ '
PS2='> '
PS4='+ '

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi



# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error



# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit

# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset

# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else $as_nop
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else $as_nop
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith


if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null


# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
      test -d "$as_dir" && break
    done
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"


} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi


# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by $as_me, which was
generated by GNU Autoconf 2.71.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

on `(hostname || uname -n) 2>/dev/null | sed 1q`
"

_ACEOF

case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac



cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
from templates according to the current configuration.  Unless the files
and actions are specified as TAGs, all are instantiated by default.

Usage: $0 [OPTION]... [TAG]...

  -h, --help       print this help, then exit
  -V, --version    print version number and configuration settings, then exit
      --config     print configuration, then exit
  -q, --quiet, --silent
                   do not print progress messages
  -d, --debug      don't remove temporary files
      --recheck    update $as_me by reconfiguring in the same conditions
      --file=FILE[:TEMPLATE]
                   instantiate the configuration file FILE

Configuration files:
$config_files

Report bugs to the package provider."

_ACEOF
ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.71,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

ac_pwd='$ac_pwd'
srcdir='$srcdir'
test -n "\$AWK" || AWK=awk
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
  case $1 in
  --*=?*)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
    ac_shift=:
    ;;
  --*=)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=
    ac_shift=:
    ;;
  *)
    ac_option=$1
    ac_optarg=$2
    ac_shift=shift
    ;;
  esac

  case $ac_option in
  # Handling of the options.
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    ac_cs_recheck=: ;;
  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    printf "%s\n" "$ac_cs_config"; exit ;;
  --debug | --debu | --deb | --de | --d | -d )
    debug=: ;;
  --file | --fil | --fi | --f )
    $ac_shift
    case $ac_optarg in
    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    '') as_fn_error $? "missing file argument" ;;
    esac
    as_fn_append CONFIG_FILES " '$ac_optarg'"
    ac_need_defaults=false;;
  --he | --h |  --help | --hel | -h )
    printf "%s\n" "$ac_cs_usage"; exit ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil | --si | --s)
    ac_cs_silent=: ;;

  # This is an error.
  -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;

  *) as_fn_append ac_config_targets " $1"
     ac_need_defaults=false ;;

  esac
  shift
done

ac_configure_extra_args=

if $ac_cs_silent; then
  exec 6>/dev/null
  ac_configure_extra_args="$ac_configure_extra_args --silent"
fi

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  shift
  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
  CONFIG_SHELL='$SHELL'
  export CONFIG_SHELL
  exec "\$@"
fi

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
  printf "%s\n" "$ac_log"
} >&5

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1

# Handling of arguments.
for ac_config_target in $ac_config_targets
do
  case $ac_config_target in
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    "cfitsio.pc") CONFIG_FILES="$CONFIG_FILES cfitsio.pc" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
  esac
done


# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
  tmp= ac_tmp=
  trap 'exit_status=$?
  : "${ac_tmp:=$tmp}"
  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
  trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.

{
  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
  test -d "$tmp"
}  ||
{
  tmp=./conf$$-$RANDOM
  (umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp

# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
if test -n "$CONFIG_FILES"; then


ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
  eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
  ac_cs_awk_cr='\\r'
else
  ac_cs_awk_cr=$ac_cr
fi

echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF


{
  echo "cat >conf$$subs.awk <<_ACEOF" &&
  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
  echo "_ACEOF"
} >conf$$subs.sh ||
  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
  . ./conf$$subs.sh ||
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5

  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
  if test $ac_delim_n = $ac_delim_num; then
    break
  elif $ac_last_try; then
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
  else
    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
  fi
done
rm -f conf$$subs.sh

cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s/'"$ac_delim"'$//
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t delim
' >$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
  for (key in S) S_is_set[key] = 1
  FS = ""

}
{
  line = $ 0
  nfields = split(line, field, "@")
  substed = 0
  len = length(field[1])
  for (i = 2; i < nfields; i++) {
    key = field[i]
    keylen = length(key)
    if (S_is_set[key]) {
      value = S[key]
      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
      len += length(value) + length(field[++i])
      substed = 1
    } else
      len += 1 + keylen
  }

  print line
}

_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
  cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF

# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
h
s///
s/^/:/
s/[	 ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
x
s/\(=[	 ]*\).*/\1/
G
s/\n//
s/^[^=]*=[	 ]*$//
}'
fi

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"


eval set X "  :F $CONFIG_FILES      "
shift
for ac_tag
do
  case $ac_tag in
  :[FHLC]) ac_mode=$ac_tag; continue;;
  esac
  case $ac_mode$ac_tag in
  :[FHL]*:*);;
  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
  :[FH]-) ac_tag=-:-;;
  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
  esac
  ac_save_IFS=$IFS
  IFS=:
  set x $ac_tag
  IFS=$ac_save_IFS
  shift
  ac_file=$1
  shift

  case $ac_mode in
  :L) ac_source=$1;;
  :[FH])
    ac_file_inputs=
    for ac_f
    do
      case $ac_f in
      -) ac_f="$ac_tmp/stdin";;
      *) # Look for the file first in the build tree, then in the source tree
	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
	 # because $ac_f cannot contain `:'.
	 test -f "$ac_f" ||
	   case $ac_f in
	   [\\/$]*) false;;
	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
	   esac ||
	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
      esac
      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      as_fn_append ac_file_inputs " '$ac_f'"
    done

    # Let's still pretend it is `configure' which instantiates (i.e., don't
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
printf "%s\n" "$as_me: creating $ac_file" >&6;}
    fi
    # Neutralize special characters interpreted by sed in replacement strings.
    case $configure_input in #(
    *\&* | *\|* | *\\* )
       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
       sed 's/[\\\\&|]/\\\\&/g'`;; #(
    *) ac_sed_conf_input=$configure_input;;
    esac

    case $ac_tag in
    *:-:* | *:-) cat >"$ac_tmp/stdin" \
      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
    esac
    ;;
  esac

  ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
  as_dir="$ac_dir"; as_fn_mkdir_p
  ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # We are building in place.
    ac_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    ac_abs_top_srcdir=$ac_pwd ;;
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix


  case $ac_mode in
  :F)
  #
  # CONFIG_FILE
  #

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
  p
  q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_datarootdir_hack='
  s&@datadir@&$datadir&g
  s&@docdir@&$docdir&g
  s&@infodir@&$infodir&g
  s&@localedir@&$localedir&g
  s&@mandir@&$mandir&g
  s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF

# Neutralize VPATH when `$srcdir' = `.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5

test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
      "$ac_tmp/out"`; test -z "$ac_out"; } &&
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&5
printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&2;}

  rm -f "$ac_tmp/stdin"
  case $ac_file in
  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
  esac \
  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 ;;



  esac

done # for ac_tag


as_fn_exit 0
_ACEOF
ac_clean_files=$ac_clean_files_save

test $ac_write_fail = 0 ||
  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5


# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded.  So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status.  When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
  ac_cs_success=:
  ac_config_status_args=
  test "$silent" = yes &&
    ac_config_status_args="$ac_config_status_args --quiet"
  exec 5>/dev/null
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi



{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
printf "%s\n" "" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:     Congratulations, Makefile update was successful." >&5
printf "%s\n" "    Congratulations, Makefile update was successful." >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:     You may want to run make now." >&5
printf "%s\n" "    You may want to run make now." >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
printf "%s\n" "" >&6; }


cfitsio-4.3.1/iter_var.c0000644000225700000360000000636713472024437014446 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
  This program illustrates how to use the CFITSIO iterator function.
  It reads and modifies the input 'iter_a.fit' file by computing a
  value for the 'rate' column as a function of the values in the other
  'counts' and 'time' columns.
*/
main()
{
    extern flux_rate(); /* external work function is passed to the iterator */
    fitsfile *fptr;
    iteratorCol cols[3];  /* structure used by the iterator function */
    int n_cols;
    long rows_per_loop, offset;

    int status, nkeys, keypos, hdutype, ii, jj;
    char filename[]  = "vari.fits";     /* name of rate FITS file */

    status = 0; 

    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */

    /* move to the desired binary table extension */
    if (fits_movnam_hdu(fptr, BINARY_TBL, "COMPRESSED_IMAGE", 0, &status) )
        fits_report_error(stderr, status);    /* print out error messages */

    n_cols  = 1;   /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], fptr, "COMPRESSED_DATA", 0,  InputCol);

    rows_per_loop = 0;  /* use default optimum number of rows */
    offset = 0;         /* process all the rows */

    /* apply the rate function to each row of the table */
    printf("Calling iterator function...%d\n", status);

    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
                      flux_rate, 0L, &status);

    fits_close_file(fptr, &status);      /* all done */

    if (status)
        fits_report_error(stderr, status);  /* print out error messages */

    return(status);
}
/*--------------------------------------------------------------------------*/
int flux_rate(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *user_strct ) 

/*
   Sample iterator function that calculates the output flux 'rate' column
   by dividing the input 'counts' by the 'time' column.
   It also applies a constant deadtime correction factor if the 'deadtime'
   keyword exists.  Finally, this creates or updates the 'LIVETIME'
   keyword with the sum of all the individual integration times.
*/
{
    int ii, status = 0;
    long repeat;

    /* declare variables static to preserve their values between calls */
    static unsigned char *counts;

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {

printf("Datatype of column = %d\n",fits_iter_get_datatype(&cols[0]));

       /* assign the input pointers to the appropriate arrays and null ptrs*/
       counts       = (long *)  fits_iter_get_array(&cols[0]);

    }

    /*--------------------------------------------*/
    /*  Main loop: process all the rows of data */
    /*--------------------------------------------*/

    /*  NOTE: 1st element of array is the null pixel value!  */
    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */


    for (ii = 1; ii <= nrows; ii++)
    {
       repeat = fits_iter_get_repeat(&cols[0]);
       printf ("repeat = %d, %d\n",repeat, counts[1]);
       
    }


    return(0);  /* return successful status */
}
cfitsio-4.3.1/makepc.bat0000644000225700000360000000440313472024437014404 0ustar  cagordonlhearem:  this batch file builds the cfitsio library 
rem:  using the Borland C++ v4.5 or new free v5.5 compiler
rem:
bcc32 -c buffers.c
bcc32 -c cfileio.c
bcc32 -c checksum.c
bcc32 -c drvrfile.c
bcc32 -c drvrmem.c
bcc32 -c editcol.c
bcc32 -c edithdu.c
bcc32 -c eval_l.c
bcc32 -c eval_y.c
bcc32 -c eval_f.c
bcc32 -c fitscore.c
bcc32 -c getcol.c
bcc32 -c getcolb.c
bcc32 -c getcolsb.c
bcc32 -c getcoli.c
bcc32 -c getcolj.c
bcc32 -c getcolui.c
bcc32 -c getcoluj.c
bcc32 -c getcoluk.c
bcc32 -c getcolk.c
bcc32 -c getcole.c
bcc32 -c getcold.c
bcc32 -c getcoll.c
bcc32 -c getcols.c
bcc32 -c getkey.c
bcc32 -c group.c
bcc32 -c grparser.c
bcc32 -c histo.c
bcc32 -c iraffits.c
bcc32 -c modkey.c
bcc32 -c putcol.c
bcc32 -c putcolb.c
bcc32 -c putcolsb.c
bcc32 -c putcoli.c
bcc32 -c putcolj.c
bcc32 -c putcolui.c
bcc32 -c putcoluj.c
bcc32 -c putcoluk.c
bcc32 -c putcolk.c
bcc32 -c putcole.c
bcc32 -c putcold.c
bcc32 -c putcols.c
bcc32 -c putcoll.c
bcc32 -c putcolu.c
bcc32 -c putkey.c
bcc32 -c region.c
bcc32 -c scalnull.c
bcc32 -c swapproc.c
bcc32 -c wcsutil.c
bcc32 -c wcssub.c
bcc32 -c imcompress.c
bcc32 -c quantize.c
bcc32 -c ricecomp.c
bcc32 -c pliocomp.c
bcc32 -c fits_hcompress.c
bcc32 -c fits_hdecompress.c
bcc32 -c zuncompress.c
bcc32 -c zcompress.c
bcc32 -c adler32.c
bcc32 -c crc32.c
bcc32 -c inffast.c
bcc32 -c inftrees.c
bcc32 -c trees.c
bcc32 -c zutil.c
bcc32 -c deflate.c
bcc32 -c infback.c
bcc32 -c inflate.c
bcc32 -c uncompr.c
del cfitsio.lib
tlib cfitsio +buffers +cfileio +checksum +drvrfile +drvrmem 
tlib cfitsio +editcol +edithdu +eval_l +eval_y +eval_f +fitscore
tlib cfitsio +getcol +getcolb +getcolsb +getcoli +getcolj +getcolk +getcoluk 
tlib cfitsio +getcolui +getcoluj +getcole +getcold +getcoll +getcols
tlib cfitsio +getkey +group +grparser +histo +iraffits +modkey +putkey 
tlib cfitsio +putcol  +putcolb +putcoli +putcolj +putcolk +putcole +putcold
tlib cfitsio +putcoll +putcols +putcolu +putcolui +putcoluj +putcoluk
tlib cfitsio +region +scalnull +swapproc +wcsutil +wcssub +putcolsb
tlib cfitsio +imcompress +quantize +ricecomp +pliocomp
tlib cfitsio +fits_hcompress +fits_hdecompress
tlib cfitsio +zuncompress +zcompress +adler32 +crc32 +inffast
tlib cfitsio +inftrees +trees +zutil +deflate +infback +inflate +uncompr
bcc32 -f testprog.c cfitsio.lib
bcc32 -f cookbook.c cfitsio.lib

cfitsio-4.3.1/checksum.c0000644000225700000360000004230113472024437014421 0ustar  cagordonlhea/*  This file, checksum.c, contains the checksum-related routines in the   */
/*  FITSIO library.                                                        */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include "fitsio2.h"
/*------------------------------------------------------------------------*/
int ffcsum(fitsfile *fptr,      /* I - FITS file pointer                  */
           long nrec,           /* I - number of 2880-byte blocks to sum  */
           unsigned long *sum,  /* IO - accumulated checksum              */
           int *status)         /* IO - error status                      */
/*
    Calculate a 32-bit 1's complement checksum of the FITS 2880-byte blocks.
    This routine is based on the C algorithm developed by Rob
    Seaman at NOAO that was presented at the 1994 ADASS conference,  
    published in the Astronomical Society of the Pacific Conference Series.
    This uses a 32-bit 1's complement checksum in which the overflow bits
    are permuted back into the sum and therefore all bit positions are
    sampled evenly. 
*/
{
    long ii, jj;
    unsigned short sbuf[1440];
    unsigned long hi, lo, hicarry, locarry;

    if (*status > 0)
        return(*status);
  /*
    Sum the specified number of FITS 2880-byte records.  This assumes that
    the FITSIO file pointer points to the start of the records to be summed.
    Read each FITS block as 1440 short values (do byte swapping if needed).
  */
    for (jj = 0; jj < nrec; jj++)
    {
      ffgbyt(fptr, 2880, sbuf, status);

#if BYTESWAPPED

      ffswap2( (short *)sbuf, 1440); /* reverse order of bytes in each value */

#endif

      hi = (*sum >> 16);
      lo = *sum & 0xFFFF;

      for (ii = 0; ii < 1440; ii += 2)
      {
        hi += sbuf[ii];
        lo += sbuf[ii+1];
      }

      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;
      }

      *sum = (hi << 16) + lo;
    }
    return(*status);
}
/*-------------------------------------------------------------------------*/
void ffesum(unsigned long sum,  /* I - accumulated checksum                */
           int complm,          /* I - = 1 to encode complement of the sum */
           char *ascii)         /* O - 16-char ASCII encoded checksum      */
/*
    encode the 32 bit checksum by converting every 
    2 bits of each byte into an ASCII character (32 bit word encoded 
    as 16 character string).   Only ASCII letters and digits are used
    to encode the values (no ASCII punctuation characters).

    If complm=TRUE, then the complement of the sum will be encoded.

    This routine is based on the C algorithm developed by Rob
    Seaman at NOAO that was presented at the 1994 ADASS conference,
    published in the Astronomical Society of the Pacific Conference Series.
*/
{
    unsigned int exclude[13] = { 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
                                       0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60 };
    unsigned long mask[4] = { 0xff000000, 0xff0000, 0xff00, 0xff  };

    int offset = 0x30;     /* ASCII 0 (zero) */

    unsigned long value;
    int byte, quotient, remainder, ch[4], check, ii, jj, kk;
    char asc[32];

    if (complm)
        value = 0xFFFFFFFF - sum;   /* complement each bit of the value */
    else
        value = sum;

    for (ii = 0; ii < 4; ii++)
    {
        byte = (value & mask[ii]) >> (24 - (8 * ii));
        quotient = byte / 4 + offset;
        remainder = byte % 4;
        for (jj = 0; jj < 4; jj++)
            ch[jj] = quotient;

        ch[0] += remainder;

        for (check = 1; check;)   /* avoid ASCII  punctuation */
            for (check = 0, kk = 0; kk < 13; kk++)
                for (jj = 0; jj < 4; jj += 2)
                    if ((unsigned char) ch[jj] == exclude[kk] ||
                        (unsigned char) ch[jj+1] == exclude[kk])
                    {
                        ch[jj]++;
                        ch[jj+1]--;
                        check++;
                    }

        for (jj = 0; jj < 4; jj++)        /* assign the bytes */
            asc[4*jj+ii] = ch[jj];
    }

    for (ii = 0; ii < 16; ii++)       /* shift the bytes 1 to the right */
        ascii[ii] = asc[(ii+15)%16];

    ascii[16] = '\0';
}
/*-------------------------------------------------------------------------*/
unsigned long ffdsum(char *ascii,  /* I - 16-char ASCII encoded checksum   */
                     int complm,   /* I - =1 to decode complement of the   */
                     unsigned long *sum)  /* O - 32-bit checksum           */
/*
    decode the 16-char ASCII encoded checksum into an unsigned 32-bit long.
    If complm=TRUE, then the complement of the sum will be decoded.

    This routine is based on the C algorithm developed by Rob
    Seaman at NOAO that was presented at the 1994 ADASS conference,
    published in the Astronomical Society of the Pacific Conference Series.
*/
{
    char cbuf[16];
    unsigned long hi = 0, lo = 0, hicarry, locarry;
    int ii;

    /* remove the permuted FITS byte alignment and the ASCII 0 offset */
    for (ii = 0; ii < 16; ii++)
    {
        cbuf[ii] = ascii[(ii+1)%16];
        cbuf[ii] -= 0x30;
    }

    for (ii = 0; ii < 16; ii += 4)
    {
        hi += (cbuf[ii]   << 8) + cbuf[ii+1];
        lo += (cbuf[ii+2] << 8) + cbuf[ii+3];
    }

    hicarry = hi >> 16;
    locarry = lo >> 16;
    while (hicarry || locarry)
    {
        hi = (hi & 0xFFFF) + locarry;
        lo = (lo & 0xFFFF) + hicarry;
        hicarry = hi >> 16;
        locarry = lo >> 16;
    }

    *sum = (hi << 16) + lo;
    if (complm)
        *sum = 0xFFFFFFFF - *sum;   /* complement each bit of the value */

    return(*sum);
}
/*------------------------------------------------------------------------*/
int ffpcks(fitsfile *fptr,      /* I - FITS file pointer                  */
           int *status)         /* IO - error status                      */
/*
   Create or update the checksum keywords in the CHDU.  These keywords
   provide a checksum verification of the FITS HDU based on the ASCII
   coded 1's complement checksum algorithm developed by Rob Seaman at NOAO.
*/
{
    char datestr[20], checksum[FLEN_VALUE], datasum[FLEN_VALUE];
    char  comm[FLEN_COMMENT], chkcomm[FLEN_COMMENT], datacomm[FLEN_COMMENT];
    int tstatus;
    long nrec;
    LONGLONG headstart, datastart, dataend;
    unsigned long dsum, olddsum, sum;
    double tdouble;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* generate current date string and construct the keyword comments */
    ffgstm(datestr, NULL, status);
    strcpy(chkcomm, "HDU checksum updated ");
    strcat(chkcomm, datestr);
    strcpy(datacomm, "data unit checksum updated ");
    strcat(datacomm, datestr);

    /* write the CHECKSUM keyword if it does not exist */
    tstatus = *status;
    if (ffgkys(fptr, "CHECKSUM", checksum, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        strcpy(checksum, "0000000000000000");
        ffpkys(fptr, "CHECKSUM", checksum, chkcomm, status);
    }

    /* write the DATASUM keyword if it does not exist */
    tstatus = *status;
    if (ffgkys(fptr, "DATASUM", datasum, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        olddsum = 0;
        ffpkys(fptr, "DATASUM", "         0", datacomm, status);

        /* set the CHECKSUM keyword as undefined, if it isn't already */
        if (strcmp(checksum, "0000000000000000") )
        {
            strcpy(checksum, "0000000000000000");
            ffmkys(fptr, "CHECKSUM", checksum, chkcomm, status);
        }
    }
    else
    {
        /* decode the datasum into an unsigned long variable */

        /* olddsum = strtoul(datasum, 0, 10); doesn't work on SUN OS */

        tdouble = atof(datasum);
        olddsum = (unsigned long) tdouble;
    }

    /* close header: rewrite END keyword and following blank fill */
    /* and re-read the required keywords to determine the structure */
    if (ffrdef(fptr, status) > 0)
        return(*status);

    if ((fptr->Fptr)->heapsize > 0)
         ffuptf(fptr, status);  /* update the variable length TFORM values */

    /* write the correct data fill values, if they are not already correct */
    if (ffpdfl(fptr, status) > 0)
        return(*status);

    /* calc size of data unit, in FITS 2880-byte blocks */
    if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0)
        return(*status);

    nrec = (long) ((dataend - datastart) / 2880);
    dsum = 0;

    if (nrec > 0)
    {
        /* accumulate the 32-bit 1's complement checksum */
        ffmbyt(fptr, datastart, REPORT_EOF, status);
        if (ffcsum(fptr, nrec, &dsum, status) > 0)
            return(*status);
    }

    if (dsum != olddsum)
    {
        /* update the DATASUM keyword with the correct value */ 
        snprintf(datasum, FLEN_VALUE, "%lu", dsum);
        ffmkys(fptr, "DATASUM", datasum, datacomm, status);

        /* set the CHECKSUM keyword as undefined, if it isn't already */
        if (strcmp(checksum, "0000000000000000") )
        {
            strcpy(checksum, "0000000000000000");
            ffmkys(fptr, "CHECKSUM", checksum, chkcomm, status);
        }
    }        

    if (strcmp(checksum, "0000000000000000") )
    {
        /* check if CHECKSUM is still OK; move to the start of the header */
        ffmbyt(fptr, headstart, REPORT_EOF, status);

        /* accumulate the header checksum into the previous data checksum */
        nrec = (long) ((datastart - headstart) / 2880);
        sum = dsum;
        if (ffcsum(fptr, nrec, &sum, status) > 0)
            return(*status);

        if (sum == 0 || sum == 0xFFFFFFFF)
           return(*status);            /* CHECKSUM is correct */

        /* Zero the CHECKSUM and recompute the new value */
        ffmkys(fptr, "CHECKSUM", "0000000000000000", chkcomm, status);
    }

    /* move to the start of the header */
    ffmbyt(fptr, headstart, REPORT_EOF, status);

    /* accumulate the header checksum into the previous data checksum */
    nrec = (long) ((datastart - headstart) / 2880);
    sum = dsum;
    if (ffcsum(fptr, nrec, &sum, status) > 0)
           return(*status);

    /* encode the COMPLEMENT of the checksum into a 16-character string */
    ffesum(sum, TRUE, checksum);

    /* update the CHECKSUM keyword value with the new string */
    ffmkys(fptr, "CHECKSUM", checksum, "&", status);

    return(*status);
}
/*------------------------------------------------------------------------*/
int ffupck(fitsfile *fptr,      /* I - FITS file pointer                  */
           int *status)         /* IO - error status                      */
/*
   Update the CHECKSUM keyword value.  This assumes that the DATASUM
   keyword exists and has the correct value.
*/
{
    char datestr[20], chkcomm[FLEN_COMMENT], comm[FLEN_COMMENT];
    char checksum[FLEN_VALUE], datasum[FLEN_VALUE];
    int tstatus;
    long nrec;
    LONGLONG headstart, datastart, dataend;
    unsigned long sum, dsum;
    double tdouble;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* generate current date string and construct the keyword comments */
    ffgstm(datestr, NULL, status);
    strcpy(chkcomm, "HDU checksum updated ");
    strcat(chkcomm, datestr);

    /* get the DATASUM keyword and convert it to a unsigned long */
    if (ffgkys(fptr, "DATASUM", datasum, comm, status) == KEY_NO_EXIST)
    {
        ffpmsg("DATASUM keyword not found (ffupck");
        return(*status);
    }

    tdouble = atof(datasum); /* read as a double as a workaround */
    dsum = (unsigned long) tdouble;

    /* get size of the HDU */
    if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0)
        return(*status);

    /* get the checksum keyword, if it exists */
    tstatus = *status;
    if (ffgkys(fptr, "CHECKSUM", checksum, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        strcpy(checksum, "0000000000000000");
        ffpkys(fptr, "CHECKSUM", checksum, chkcomm, status);
    }
    else
    {
        /* check if CHECKSUM is still OK */
        /* rewrite END keyword and following blank fill */
        if (ffwend(fptr, status) > 0)
            return(*status);

        /* move to the start of the header */
        ffmbyt(fptr, headstart, REPORT_EOF, status);

        /* accumulate the header checksum into the previous data checksum */
        nrec = (long) ((datastart - headstart) / 2880);
        sum = dsum;
        if (ffcsum(fptr, nrec, &sum, status) > 0)
           return(*status);

        if (sum == 0 || sum == 0xFFFFFFFF)
           return(*status);    /* CHECKSUM is already correct */

        /* Zero the CHECKSUM and recompute the new value */
        ffmkys(fptr, "CHECKSUM", "0000000000000000", chkcomm, status);
    }

    /* move to the start of the header */
    ffmbyt(fptr, headstart, REPORT_EOF, status);

    /* accumulate the header checksum into the previous data checksum */
    nrec = (long) ((datastart - headstart) / 2880);
    sum = dsum;
    if (ffcsum(fptr, nrec, &sum, status) > 0)
           return(*status);

    /* encode the COMPLEMENT of the checksum into a 16-character string */
    ffesum(sum, TRUE, checksum);

    /* update the CHECKSUM keyword value with the new string */
    ffmkys(fptr, "CHECKSUM", checksum, "&", status);

    return(*status);
}
/*------------------------------------------------------------------------*/
int ffvcks(fitsfile *fptr,      /* I - FITS file pointer                  */
           int *datastatus,     /* O - data checksum status               */
           int *hdustatus,      /* O - hdu checksum status                */
                                /*     1  verification is correct         */
                                /*     0  checksum keyword is not present */
                                /*    -1 verification not correct         */
           int *status)         /* IO - error status                      */
/*
    Verify the HDU by comparing the value of the computed checksums against
    the values of the DATASUM and CHECKSUM keywords if they are present.
*/
{
    int tstatus;
    double tdouble;
    unsigned long datasum, hdusum, olddatasum;
    char chksum[FLEN_VALUE], comm[FLEN_COMMENT];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    *datastatus = -1;
    *hdustatus  = -1;

    tstatus = *status;
    if (ffgkys(fptr, "CHECKSUM", chksum, comm, status) == KEY_NO_EXIST)
    {
        *hdustatus = 0;             /* CHECKSUM keyword does not exist */
        *status = tstatus;
    }
    if (chksum[0] == '\0')
        *hdustatus = 0;    /* all blank checksum means it is undefined */

    if (ffgkys(fptr, "DATASUM", chksum, comm, status) == KEY_NO_EXIST)
    {
        *datastatus = 0;            /* DATASUM keyword does not exist */
        *status = tstatus;
    }
    if (chksum[0] == '\0')
        *datastatus = 0;    /* all blank checksum means it is undefined */

    if ( *status > 0 || (!(*hdustatus) && !(*datastatus)) )
        return(*status);            /* return if neither keywords exist */

    /* convert string to unsigned long */

    /* olddatasum = strtoul(chksum, 0, 10);  doesn't work w/ gcc on SUN OS */
    /* sscanf(chksum, "%u", &olddatasum);   doesn't work w/ cc on VAX/VMS */

    tdouble = atof(chksum); /* read as a double as a workaround */
    olddatasum = (unsigned long) tdouble;

    /*  calculate the data checksum and the HDU checksum */
    if (ffgcks(fptr, &datasum, &hdusum, status) > 0)
        return(*status);

    if (*datastatus)
        if (datasum == olddatasum)
            *datastatus = 1;

    if (*hdustatus)
        if (hdusum == 0 || hdusum == 0xFFFFFFFF)
            *hdustatus = 1;

    return(*status);
}
/*------------------------------------------------------------------------*/
int ffgcks(fitsfile *fptr,           /* I - FITS file pointer             */
           unsigned long *datasum,   /* O - data checksum                 */
           unsigned long *hdusum,    /* O - hdu checksum                  */
           int *status)              /* IO - error status                 */

    /* calculate the checksums of the data unit and the total HDU */
{
    long nrec;
    LONGLONG headstart, datastart, dataend;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* get size of the HDU */
    if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0)
        return(*status);

    nrec = (long) ((dataend - datastart) / 2880);

    *datasum = 0;

    if (nrec > 0)
    {
        /* accumulate the 32-bit 1's complement checksum */
        ffmbyt(fptr, datastart, REPORT_EOF, status);
        if (ffcsum(fptr, nrec, datasum, status) > 0)
            return(*status);
    }

    /* move to the start of the header and calc. size of header */
    ffmbyt(fptr, headstart, REPORT_EOF, status);
    nrec = (long) ((datastart - headstart) / 2880);

    /* accumulate the header checksum into the previous data checksum */
    *hdusum = *datasum;
    ffcsum(fptr, nrec, hdusum, status);

    return(*status);
}

cfitsio-4.3.1/simplerng.c0000644000225700000360000003314513472024437014625 0ustar  cagordonlhea/* 
   Simple Random Number Generators
       - getuniform - uniform deviate [0,1]
       - getnorm    - gaussian (normal) deviate (mean=0, stddev=1)
       - getpoisson - poisson deviate for given expected mean lambda

   This code is adapted from SimpleRNG by John D Cook, which is
   provided in the public domain.

   The original C++ code is found here:
   http://www.johndcook.com/cpp_random_number_generation.html

   This code has been modified in the following ways compared to the
   original.
     1. convert to C from C++
     2. keep only uniform, gaussian and poisson deviates
     3. state variables are module static instead of class variables
     4. provide an srand() equivalent to initialize the state
*/
#include 
#include 

#define PI 3.1415926535897932384626433832795

/* Use the standard system rand() library routine if it provides
   enough bits of information, since it probably has better randomness
   than the toy algorithm in this module. */
#if defined(RAND_MAX) && RAND_MAX > 1000000000
#define USE_SYSTEM_RAND
#endif

int simplerng_poisson_small(double lambda);
int simplerng_poisson_large(double lambda);
double simplerng_getuniform_pr(unsigned int *u, unsigned int *v);
unsigned int simplerng_getuint_pr(unsigned int *u, unsigned int *v);
double simplerng_logfactorial(int n);

/*
  These values are not magical, just the default values Marsaglia used.
  Any unit should work.
*/
static unsigned int m_u = 521288629, m_v = 362436069;

/* Set u and v state variables */
void simplerng_setstate(unsigned int u, unsigned int v)
{
    m_u = u;
    m_v = v;
}

/* Retrieve u and v state variables */
void simplerng_getstate(unsigned int *u, unsigned int *v)
{
    *u = m_u;
    *v = m_v;
}

/* srand() equivalent to seed the two state variables */
void simplerng_srand(unsigned int seed)
{
#ifdef USE_SYSTEM_RAND
  srand(seed);
#else
  simplerng_setstate(seed ^ 521288629, seed ^ 362436069);
#endif
}

/* Private routine to get uniform deviate */
double simplerng_getuniform_pr(unsigned int *u, unsigned int *v)
{
  /* 0 <= u <= 2^32 */
  unsigned int z = simplerng_getuint_pr(u, v);
  /* The magic number is 1/(2^32) and so result is positive and less than 1. */
  return z*2.328306435996595e-10;
}

/* Private routine to get unsigned integer */
/* Marsaglia multiply-with-carry algorithm (MWC) */
unsigned int simplerng_getuint_pr(unsigned int *u, unsigned int *v)
{
  *v = 36969*((*v) & 65535) + ((*v) >> 16);
  *u = 18000*((*u) & 65535) + ((*u) >> 16);
  return ((*v) << 16) + (*u);
}

/* Get uniform deviate [0,1] */
double simplerng_getuniform(void)
{
#ifdef USE_SYSTEM_RAND
  return rand()*(1.0 / ((double)RAND_MAX + 1));
#else
  return simplerng_getuniform_pr(&m_u, &m_v);
#endif
}

/* Get unsigned integer [0, UINT_MAX] */
unsigned int simplerng_getuint()
{
  /* WARNING: no option for calling rand() here.  Will need to provide
     a scalar to make the uint in the [0,UINT_MAX] range */
  return simplerng_getuint_pr(&m_u, &m_v);
}
    
/* Get normal (Gaussian) random sample with mean=0, stddev=1 */
double simplerng_getnorm()
{
  double u1, u2, r, theta;
  static int saved = 0;
  static double y;

  /* Since you get two deviates for "free" with each calculation, save
     one of them for later */

  if (saved == 0) {
    /* Use Box-Muller algorithm */
    u1 = simplerng_getuniform();
    u2 = simplerng_getuniform();
    r = sqrt( -2.0*log(u1) );
    theta = 2.0*PI*u2;
    /* save second value for next call */
    y = r*cos(theta);
    saved = 1;
    return r*sin(theta);

  } else {
    /* We already saved a value from the last call so use it */
    saved = 0;
    return y;
  }
}

/* Poisson deviate for expected mean value lambda.
   lambda should be in the range [0, infinity]
   
   For small lambda, a simple rejection method is used
   For large lambda, an approximation is used
*/
int simplerng_getpoisson(double lambda)
{
  if (lambda < 0) lambda = 0;
  return ((lambda < 15.0) 
	  ? simplerng_poisson_small(lambda) 
	  : simplerng_poisson_large(lambda));
}

int simplerng_poisson_small(double lambda)
{
  /* Algorithm due to Donald Knuth, 1969. */
  double p = 1.0, L = exp(-lambda);
  int k = 0;
  do {
    k++;
    p *= simplerng_getuniform();
  }
  while (p > L);
  return k - 1;
}

int simplerng_poisson_large(double lambda)
{
  /* "Rejection method PA" from "The Computer Generation of Poisson Random Variables" by A. C. Atkinson
     Journal of the Royal Statistical Society Series C (Applied Statistics) Vol. 28, No. 1. (1979)
     The article is on pages 29-35. The algorithm given here is on page 32. */
  static double beta, alpha, k;
  static double old_lambda = -999999.;

  if (lambda != old_lambda) {
    double c = 0.767 - 3.36/lambda;
    beta = PI/sqrt(3.0*lambda);
    alpha = beta*lambda;
    k = log(c) - lambda - log(beta);
    old_lambda = lambda;
  }

  for(;;) { /* forever */
    double u, x, v, y, temp, lhs, rhs;
    int n;

    u = simplerng_getuniform();
    x = (alpha - log((1.0 - u)/u))/beta;
    n = (int) floor(x + 0.5);
    if (n < 0) continue;

    v = simplerng_getuniform();
    y = alpha - beta*x;
    temp = 1.0 + exp(y);
    lhs = y + log(v/(temp*temp));
    rhs = k + n*log(lambda) - simplerng_logfactorial(n);
    if (lhs <= rhs) return n;
  }

}

/* Lookup table for log-gamma function */
static double lf[] = {
            0.000000000000000,
            0.000000000000000,
            0.693147180559945,
            1.791759469228055,
            3.178053830347946,
            4.787491742782046,
            6.579251212010101,
            8.525161361065415,
            10.604602902745251,
            12.801827480081469,
            15.104412573075516,
            17.502307845873887,
            19.987214495661885,
            22.552163853123421,
            25.191221182738683,
            27.899271383840894,
            30.671860106080675,
            33.505073450136891,
            36.395445208033053,
            39.339884187199495,
            42.335616460753485,
            45.380138898476908,
            48.471181351835227,
            51.606675567764377,
            54.784729398112319,
            58.003605222980518,
            61.261701761002001,
            64.557538627006323,
            67.889743137181526,
            71.257038967168000,
            74.658236348830158,
            78.092223553315307,
            81.557959456115029,
            85.054467017581516,
            88.580827542197682,
            92.136175603687079,
            95.719694542143202,
            99.330612454787428,
            102.968198614513810,
            106.631760260643450,
            110.320639714757390,
            114.034211781461690,
            117.771881399745060,
            121.533081515438640,
            125.317271149356880,
            129.123933639127240,
            132.952575035616290,
            136.802722637326350,
            140.673923648234250,
            144.565743946344900,
            148.477766951773020,
            152.409592584497350,
            156.360836303078800,
            160.331128216630930,
            164.320112263195170,
            168.327445448427650,
            172.352797139162820,
            176.395848406997370,
            180.456291417543780,
            184.533828861449510,
            188.628173423671600,
            192.739047287844900,
            196.866181672889980,
            201.009316399281570,
            205.168199482641200,
            209.342586752536820,
            213.532241494563270,
            217.736934113954250,
            221.956441819130360,
            226.190548323727570,
            230.439043565776930,
            234.701723442818260,
            238.978389561834350,
            243.268849002982730,
            247.572914096186910,
            251.890402209723190,
            256.221135550009480,
            260.564940971863220,
            264.921649798552780,
            269.291097651019810,
            273.673124285693690,
            278.067573440366120,
            282.474292687630400,
            286.893133295426990,
            291.323950094270290,
            295.766601350760600,
            300.220948647014100,
            304.686856765668720,
            309.164193580146900,
            313.652829949878990,
            318.152639620209300,
            322.663499126726210,
            327.185287703775200,
            331.717887196928470,
            336.261181979198450,
            340.815058870798960,
            345.379407062266860,
            349.954118040770250,
            354.539085519440790,
            359.134205369575340,
            363.739375555563470,
            368.354496072404690,
            372.979468885689020,
            377.614197873918670,
            382.258588773060010,
            386.912549123217560,
            391.575988217329610,
            396.248817051791490,
            400.930948278915760,
            405.622296161144900,
            410.322776526937280,
            415.032306728249580,
            419.750805599544780,
            424.478193418257090,
            429.214391866651570,
            433.959323995014870,
            438.712914186121170,
            443.475088120918940,
            448.245772745384610,
            453.024896238496130,
            457.812387981278110,
            462.608178526874890,
            467.412199571608080,
            472.224383926980520,
            477.044665492585580,
            481.872979229887900,
            486.709261136839360,
            491.553448223298010,
            496.405478487217580,
            501.265290891579240,
            506.132825342034830,
            511.008022665236070,
            515.890824587822520,
            520.781173716044240,
            525.679013515995050,
            530.584288294433580,
            535.496943180169520,
            540.416924105997740,
            545.344177791154950,
            550.278651724285620,
            555.220294146894960,
            560.169054037273100,
            565.124881094874350,
            570.087725725134190,
            575.057539024710200,
            580.034272767130800,
            585.017879388839220,
            590.008311975617860,
            595.005524249382010,
            600.009470555327430,
            605.020105849423770,
            610.037385686238740,
            615.061266207084940,
            620.091704128477430,
            625.128656730891070,
            630.172081847810200,
            635.221937855059760,
            640.278183660408100,
            645.340778693435030,
            650.409682895655240,
            655.484856710889060,
            660.566261075873510,
            665.653857411105950,
            670.747607611912710,
            675.847474039736880,
            680.953419513637530,
            686.065407301994010,
            691.183401114410800,
            696.307365093814040,
            701.437263808737160,
            706.573062245787470,
            711.714725802289990,
            716.862220279103440,
            722.015511873601330,
            727.174567172815840,
            732.339353146739310,
            737.509837141777440,
            742.685986874351220,
            747.867770424643370,
            753.055156230484160,
            758.248113081374300,
            763.446610112640200,
            768.650616799717000,
            773.860102952558460,
            779.075038710167410,
            784.295394535245690,
            789.521141208958970,
            794.752249825813460,
            799.988691788643450,
            805.230438803703120,
            810.477462875863580,
            815.729736303910160,
            820.987231675937890,
            826.249921864842800,
            831.517780023906310,
            836.790779582469900,
            842.068894241700490,
            847.352097970438420,
            852.640365001133090,
            857.933669825857460,
            863.231987192405430,
            868.535292100464630,
            873.843559797865740,
            879.156765776907600,
            884.474885770751830,
            889.797895749890240,
            895.125771918679900,
            900.458490711945270,
            905.796028791646340,
            911.138363043611210,
            916.485470574328820,
            921.837328707804890,
            927.193914982476710,
            932.555207148186240,
            937.921183163208070,
            943.291821191335660,
            948.667099599019820,
            954.046996952560450,
            959.431492015349480,
            964.820563745165940,
            970.214191291518320,
            975.612353993036210,
            981.015031374908400,
            986.422203146368590,
            991.833849198223450,
            997.249949600427840,
            1002.670484599700300,
            1008.095434617181700,
            1013.524780246136200,
            1018.958502249690200,
            1024.396581558613400,
            1029.838999269135500,
            1035.285736640801600,
            1040.736775094367400,
            1046.192096209724900,
            1051.651681723869200,
            1057.115513528895000,
            1062.583573670030100,
            1068.055844343701400,
            1073.532307895632800,
            1079.012946818975000,
            1084.497743752465600,
            1089.986681478622400,
            1095.479742921962700,
            1100.976911147256000,
            1106.478169357800900,
            1111.983500893733000,
            1117.492889230361000,
            1123.006317976526100,
            1128.523770872990800,
            1134.045231790853000,
            1139.570684729984800,
            1145.100113817496100,
            1150.633503306223700,
            1156.170837573242400,
};

double simplerng_logfactorial(int n)
{
  if (n < 0) return 0;
  if (n > 254) {
    double x = n + 1;
    return (x - 0.5)*log(x) - x + 0.5*log(2*PI) + 1.0/(12.0*x);
  }
  return lf[n];
}
cfitsio-4.3.1/putcols.c0000644000225700000360000002530013472024437014310 0ustar  cagordonlhea/*  This file, putcols.c, contains routines that write data elements to    */
/*  a FITS image or table, of type character string.                       */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include "fitsio2.h"
/*--------------------------------------------------------------------------*/
int ffpcls( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of strings to write              */
            char  **array,   /* I - array of pointers to strings            */
            int  *status)    /* IO - error status                           */
/*
  Write an array of string values to a column in the current FITS HDU.
*/
{
    int tcode, maxelem, hdutype, nchar;
    long twidth, incre;
    long ii, jj, ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], *blanks;
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */
    tcolumn *colptr;

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    char *buffer, *arrayptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
    {
        snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
                colnum);
        ffpmsg(message);
        return(*status = BAD_COL_NUM);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */
    tcode = colptr->tdatatype;

    if (tcode == -TSTRING) /* variable length column in a binary table? */
    {
      /* only write a single string; ignore value of firstelem */
      nchar = maxvalue(1,strlen(array[0])); /* will write at least 1 char */
                                          /* even if input string is null */

      if (ffgcprll( fptr, colnum, firstrow, 1, nchar, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
	
      /* simply move to write position, then write the string */
      ffmbyt(fptr, startpos, IGNORE_EOF, status); 
      ffpbyt(fptr, nchar, array[0], status);

      if (*status > 0)  /* test for error during previous write operation */
      {
         snprintf(message,FLEN_ERRMSG,
          "Error writing to variable length string column (ffpcls).");
         ffpmsg(message);
      }

      return(*status);
    }
    else if (tcode == TSTRING)
    {
      if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

      /* if string length is greater than a FITS block (2880 char) then must */
      /* only write 1 string at a time, to force writein by ffpbyt instead of */
      /* ffpbytoff (ffpbytoff can't handle this case) */
      if (twidth > IOBUFLEN) {
        maxelem = 1;
        incre = twidth;
        repeat = 1;
      }   

      blanks = (char *) malloc(twidth); /* string for blank fill values */
      if (!blanks)
      {
        ffpmsg("Could not allocate memory for string (ffpcls)");
        return(*status = ARRAY_TOO_BIG);
      }

      for (ii = 0; ii < twidth; ii++)
          blanks[ii] = ' ';          /* fill string with blanks */

      remain = nelem;           /* remaining number of values to write  */
    }
    else 
      return(*status = NOT_ASCII_COL);
 
    /*-------------------------------------------------------*/
    /*  Now write the strings to the FITS column.            */
    /*-------------------------------------------------------*/

    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
      /* limit the number of pixels to process at one time to the number that
         will fit in the buffer space or to the number of pixels that remain
         in the current vector, which ever is smaller.
      */
      ntodo = (long) minvalue(remain, maxelem);      
      ntodo = (long) minvalue(ntodo, (repeat - elemnum));

      wrtptr = startpos + (rownum * rowlen) + (elemnum * incre);
      ffmbyt(fptr, wrtptr, IGNORE_EOF, status);  /* move to write position */

      buffer = (char *) cbuff;

      /* copy the user's strings into the buffer */
      for (ii = 0; ii < ntodo; ii++)
      {
         arrayptr = array[next];

         for (jj = 0; jj < twidth; jj++)  /*  copy the string, char by char */
         {
            if (*arrayptr)
            {
              *buffer = *arrayptr;
              buffer++;
              arrayptr++;
            }
            else
              break;
         }

         for (;jj < twidth; jj++)    /* fill field with blanks, if needed */
         {
           *buffer = ' ';
           buffer++;
         }

         next++;
      }

      /* write the buffer full of strings to the FITS file */
      if (incre == twidth)
         ffpbyt(fptr, ntodo * twidth, cbuff, status);
      else
         ffpbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);

      if (*status > 0)  /* test for error during previous write operation */
      {
         snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcls).",
             (double) (next+1), (double) (next+ntodo));
         ffpmsg(message);

         if (blanks)
           free(blanks);

         return(*status);
      }

      /*--------------------------------------------*/
      /*  increment the counters for the next loop  */
      /*--------------------------------------------*/
      remain -= ntodo;
      if (remain)
      {
          elemnum += ntodo;
          if (elemnum == repeat)  /* completed a row; start on next row */
          {
              elemnum = 0;
              rownum++;
          }
       }
    }  /*  End of main while Loop  */

    if (blanks)
      free(blanks);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcns( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            char  **array,   /* I - array of values to write                */
            char  *nulvalue, /* I - string representing a null value        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels flagged as null will be replaced by the appropriate
  null value in the output FITS file. 
*/
{
    long repeat, width;
    LONGLONG ngood = 0, nbad = 0, ii;
    LONGLONG first, fstelm, fstrow;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    /* get the vector repeat length of the column */
    ffgtcl(fptr, colnum, NULL, &repeat, &width, status);

    if ((fptr->Fptr)->hdutype == BINARY_TBL)
        repeat = repeat / width;    /* convert from chars to unit strings */

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (strcmp(nulvalue, array[ii]))  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);
            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0)
                return(*status);

            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    return(*status);
}
cfitsio-4.3.1/install-sh0000755000225700000360000003471713472024437014473 0ustar  cagordonlhea#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2017-09-23.17; # UTC

# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.

tab='	'
nl='
'
IFS=" $tab$nl"

# Set DOITPROG to "echo" to test this script.

doit=${DOITPROG-}
doit_exec=${doit:-exec}

# Put in absolute file names if you don't have them in your path;
# or use environment vars.

chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}

posix_mkdir=

# Desired mode of installed file.
mode=0755

chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=

src=
dst=
dir_arg=
dst_arg=

copy_on_change=false
is_target_a_directory=possibly

usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
   or: $0 [OPTION]... SRCFILES... DIRECTORY
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
   or: $0 [OPTION]... -d DIRECTORIES...

In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.

Options:
     --help     display this help and exit.
     --version  display version info and exit.

  -c            (ignored)
  -C            install only if different (preserve the last data modification time)
  -d            create directories instead of installing files.
  -g GROUP      $chgrpprog installed files to GROUP.
  -m MODE       $chmodprog installed files to MODE.
  -o USER       $chownprog installed files to USER.
  -s            $stripprog installed files.
  -t DIRECTORY  install into DIRECTORY.
  -T            report an error if DSTFILE is a directory.

Environment variables override the default commands:
  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  RMPROG STRIPPROG
"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;

    -d) dir_arg=true;;

    -g) chgrpcmd="$chgrpprog $2"
        shift;;

    --help) echo "$usage"; exit $?;;

    -m) mode=$2
        case $mode in
          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
            echo "$0: invalid mode: $mode" >&2
            exit 1;;
        esac
        shift;;

    -o) chowncmd="$chownprog $2"
        shift;;

    -s) stripcmd=$stripprog;;

    -t)
        is_target_a_directory=always
        dst_arg=$2
        # Protect names problematic for 'test' and other utilities.
        case $dst_arg in
          -* | [=\(\)!]) dst_arg=./$dst_arg;;
        esac
        shift;;

    -T) is_target_a_directory=never;;

    --version) echo "$0 $scriptversion"; exit $?;;

    --) shift
        break;;

    -*) echo "$0: invalid option: $1" >&2
        exit 1;;

    *)  break;;
  esac
  shift
done

# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.

if test -n "$dir_arg"; then
  if test -n "$dst_arg"; then
    echo "$0: target directory not allowed when installing a directory." >&2
    exit 1
  fi
fi

if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
  # When -d is used, all remaining arguments are directories to create.
  # When -t is used, the destination is already specified.
  # Otherwise, the last argument is the destination.  Remove it from $@.
  for arg
  do
    if test -n "$dst_arg"; then
      # $@ is not empty: it contains at least $arg.
      set fnord "$@" "$dst_arg"
      shift # fnord
    fi
    shift # arg
    dst_arg=$arg
    # Protect names problematic for 'test' and other utilities.
    case $dst_arg in
      -* | [=\(\)!]) dst_arg=./$dst_arg;;
    esac
  done
fi

if test $# -eq 0; then
  if test -z "$dir_arg"; then
    echo "$0: no input file specified." >&2
    exit 1
  fi
  # It's OK to call 'install-sh -d' without argument.
  # This can happen when creating conditional directories.
  exit 0
fi

if test -z "$dir_arg"; then
  if test $# -gt 1 || test "$is_target_a_directory" = always; then
    if test ! -d "$dst_arg"; then
      echo "$0: $dst_arg: Is not a directory." >&2
      exit 1
    fi
  fi
fi

if test -z "$dir_arg"; then
  do_exit='(exit $ret); exit $ret'
  trap "ret=129; $do_exit" 1
  trap "ret=130; $do_exit" 2
  trap "ret=141; $do_exit" 13
  trap "ret=143; $do_exit" 15

  # Set umask so as not to create temps with too-generous modes.
  # However, 'strip' requires both read and write access to temps.
  case $mode in
    # Optimize common cases.
    *644) cp_umask=133;;
    *755) cp_umask=22;;

    *[0-7])
      if test -z "$stripcmd"; then
        u_plus_rw=
      else
        u_plus_rw='% 200'
      fi
      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
    *)
      if test -z "$stripcmd"; then
        u_plus_rw=
      else
        u_plus_rw=,u+rw
      fi
      cp_umask=$mode$u_plus_rw;;
  esac
fi

for src
do
  # Protect names problematic for 'test' and other utilities.
  case $src in
    -* | [=\(\)!]) src=./$src;;
  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?
  else

    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
    # might cause directories to be created, which would be especially bad
    # if $src (and thus $dsttmp) contains '*'.
    if test ! -f "$src" && test ! -d "$src"; then
      echo "$0: $src does not exist." >&2
      exit 1
    fi

    if test -z "$dst_arg"; then
      echo "$0: no destination specified." >&2
      exit 1
    fi
    dst=$dst_arg

    # If destination is a directory, append the input filename.
    if test -d "$dst"; then
      if test "$is_target_a_directory" = never; then
        echo "$0: $dst_arg: Is a directory" >&2
        exit 1
      fi
      dstdir=$dst
      dstbase=`basename "$src"`
      case $dst in
	*/) dst=$dst$dstbase;;
	*)  dst=$dst/$dstbase;;
      esac
      dstdir_status=0
    else
      dstdir=`dirname "$dst"`
      test -d "$dstdir"
      dstdir_status=$?
    fi
  fi

  case $dstdir in
    */) dstdirslash=$dstdir;;
    *)  dstdirslash=$dstdir/;;
  esac

  obsolete_mkdir_used=false

  if test $dstdir_status != 0; then
    case $posix_mkdir in
      '')
        # Create intermediate dirs using mode 755 as modified by the umask.
        # This is like FreeBSD 'install' as of 1997-10-28.
        umask=`umask`
        case $stripcmd.$umask in
          # Optimize common cases.
          *[2367][2367]) mkdir_umask=$umask;;
          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;

          *[0-7])
            mkdir_umask=`expr $umask + 22 \
              - $umask % 100 % 40 + $umask % 20 \
              - $umask % 10 % 4 + $umask % 2
            `;;
          *) mkdir_umask=$umask,go-w;;
        esac

        # With -d, create the new directory with the user-specified mode.
        # Otherwise, rely on $mkdir_umask.
        if test -n "$dir_arg"; then
          mkdir_mode=-m$mode
        else
          mkdir_mode=
        fi

        posix_mkdir=false
        case $umask in
          *[123567][0-7][0-7])
            # POSIX mkdir -p sets u+wx bits regardless of umask, which
            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
            ;;
          *)
            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0

            if (umask $mkdir_umask &&
                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
            then
              if test -z "$dir_arg" || {
                   # Check for POSIX incompatibilities with -m.
                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
                   # other-writable bit of parent directory when it shouldn't.
                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
                   case $ls_ld_tmpdir in
                     d????-?r-*) different_mode=700;;
                     d????-?--*) different_mode=755;;
                     *) false;;
                   esac &&
                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
                   }
                 }
              then posix_mkdir=:
              fi
              rmdir "$tmpdir/d" "$tmpdir"
            else
              # Remove any dirs left behind by ancient mkdir implementations.
              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
            fi
            trap '' 0;;
        esac;;
    esac

    if
      $posix_mkdir && (
        umask $mkdir_umask &&
        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
      )
    then :
    else

      # The umask is ridiculous, or mkdir does not conform to POSIX,
      # or it failed possibly due to a race condition.  Create the
      # directory the slow way, step by step, checking for races as we go.

      case $dstdir in
        /*) prefix='/';;
        [-=\(\)!]*) prefix='./';;
        *)  prefix='';;
      esac

      oIFS=$IFS
      IFS=/
      set -f
      set fnord $dstdir
      shift
      set +f
      IFS=$oIFS

      prefixes=

      for d
      do
        test X"$d" = X && continue

        prefix=$prefix$d
        if test -d "$prefix"; then
          prefixes=
        else
          if $posix_mkdir; then
            (umask=$mkdir_umask &&
             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
            # Don't fail if two instances are running concurrently.
            test -d "$prefix" || exit 1
          else
            case $prefix in
              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
              *) qprefix=$prefix;;
            esac
            prefixes="$prefixes '$qprefix'"
          fi
        fi
        prefix=$prefix/
      done

      if test -n "$prefixes"; then
        # Don't fail if two instances are running concurrently.
        (umask $mkdir_umask &&
         eval "\$doit_exec \$mkdirprog $prefixes") ||
          test -d "$dstdir" || exit 1
        obsolete_mkdir_used=true
      fi
    fi
  fi

  if test -n "$dir_arg"; then
    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
  else

    # Make a couple of temp file names in the proper directory.
    dsttmp=${dstdirslash}_inst.$$_
    rmtmp=${dstdirslash}_rm.$$_

    # Trap to clean up those temp files at exit.
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0

    # Copy the file name to the temp name.
    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&

    # and set any options; do chmod last to preserve setuid bits.
    #
    # If any of these fail, we abort the whole thing.  If we want to
    # ignore errors from any of these, just make sure not to ignore
    # errors from the above "$doit $cpprog $src $dsttmp" command.
    #
    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&

    # If -C, don't bother to copy if it wouldn't change the file.
    if $copy_on_change &&
       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
       set -f &&
       set X $old && old=:$2:$4:$5:$6 &&
       set X $new && new=:$2:$4:$5:$6 &&
       set +f &&
       test "$old" = "$new" &&
       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
    then
      rm -f "$dsttmp"
    else
      # Rename the file to the real destination.
      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||

      # The rename failed, perhaps because mv can't rename something else
      # to itself, or perhaps because mv is so ancient that it does not
      # support -f.
      {
        # Now remove or move aside any old file at destination location.
        # We try this two ways since rm can't unlink itself on some
        # systems and the destination file might be busy for other
        # reasons.  In this case, the final cleanup might fail but the new
        # file should still install successfully.
        {
          test ! -f "$dst" ||
          $doit $rmcmd -f "$dst" 2>/dev/null ||
          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
          } ||
          { echo "$0: cannot unlink or rename $dst" >&2
            (exit 1); exit 1
          }
        } &&

        # Now rename the file to the real destination.
        $doit $mvcmd "$dsttmp" "$dst"
      }
    fi || exit 1

    trap '' 0
  fi
done

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
cfitsio-4.3.1/eval_y.c0000644000225700000360000112444214456514035014107 0ustar  cagordonlhea/* A Bison parser, made by GNU Bison 3.8.  */

/* Bison implementation for Yacc-like parsers in C

   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
   Inc.

   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 .  */

/* As a special exception, you may create a larger work that contains
   part or all of the Bison parser skeleton and distribute that work
   under terms of your choice, so long as that work isn't itself a
   parser generator using the skeleton or a modified version thereof
   as a parser skeleton.  Alternatively, if you modify or redistribute
   the parser skeleton itself, you may (at your option) remove this
   special exception, which will cause the skeleton and the resulting
   Bison output files to be licensed under the GNU General Public
   License without this special exception.

   This special exception was added by the Free Software Foundation in
   version 2.2 of Bison.  */

/* C LALR(1) parser skeleton written by Richard Stallman, by
   simplifying the original so-called "semantic" parser.  */

/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
   especially those whose name start with YY_ or yy_.  They are
   private implementation details that can be changed or removed.  */

/* All symbols defined below should begin with yy or YY, to avoid
   infringing on user name space.  This should be done even for local
   variables, as they might otherwise be expanded by user macros.
   There are some unavoidable exceptions within include files to
   define necessary library symbols; they are noted "INFRINGES ON
   USER NAME SPACE" below.  */

/* Identify Bison output, and Bison version.  */
#define YYBISON 30800

/* Bison version string.  */
#define YYBISON_VERSION "3.8"

/* Skeleton name.  */
#define YYSKELETON_NAME "yacc.c"

/* Pure parsers.  */
#define YYPURE 2

/* Push parsers.  */
#define YYPUSH 0

/* Pull parsers.  */
#define YYPULL 1

/* Substitute the type names.  */
#define YYSTYPE         FITS_PARSER_YYSTYPE
/* Substitute the variable and function names.  */
#define yyparse         fits_parser_yyparse
#define yylex           fits_parser_yylex
#define yyerror         fits_parser_yyerror
#define yydebug         fits_parser_yydebug
#define yynerrs         fits_parser_yynerrs

/* First part of user prologue.  */
#line 16 "eval.y"

/* This file is one of 3 files containing code which parses an          */
/* arithmetic expression and evaluates it in the context of an input    */
/* FITS file table extension.  The CFITSIO lexical parser is divided    */
/* into the following 3 parts/files: the CFITSIO "front-end",           */
/* eval_f.c, contains the interface between the user/CFITSIO and the    */
/* real core of the parser; the FLEX interpreter, eval_l.c, takes the   */
/* input string and parses it into tokens and identifies the FITS       */
/* information required to evaluate the expression (ie, keywords and    */
/* columns); and, the BISON grammar and evaluation routines, eval_y.c,  */
/* receives the FLEX output and determines and performs the actual      */
/* operations.  The files eval_l.c and eval_y.c are produced from       */
/* running flex and bison on the files eval.l and eval.y, respectively. */
/* (flex and bison are available from any GNU archive: see www.gnu.org) */
/*                                                                      */
/* The grammar rules, rather than evaluating the expression in situ,    */
/* builds a tree, or Nodal, structure mapping out the order of          */
/* operations and expression dependencies.  This "compilation" process  */
/* allows for much faster processing of multiple rows.  This technique  */
/* was developed by Uwe Lammers of the XMM Science Analysis System,     */
/* although the CFITSIO implementation is entirely code original.       */
/*                                                                      */
/*                                                                      */
/* Modification History:                                                */
/*                                                                      */
/*   Kent Blackburn      c1992  Original parser code developed for the  */
/*                              FTOOLS software package, in particular, */
/*                              the fselect task.                       */
/*   Kent Blackburn      c1995  BIT column support added                */
/*   Peter D Wilson   Feb 1998  Vector column support added             */
/*   Peter D Wilson   May 1998  Ported to CFITSIO library.  User        */
/*                              interface routines written, in essence  */
/*                              making fselect, fcalc, and maketime     */
/*                              capabilities available to all tools     */
/*                              via single function calls.              */
/*   Peter D Wilson   Jun 1998  Major rewrite of parser core, so as to  */
/*                              create a run-time evaluation tree,      */
/*                              inspired by the work of Uwe Lammers,    */
/*                              resulting in a speed increase of        */
/*                              10-100 times.                           */
/*   Peter D Wilson   Jul 1998  gtifilter(a,b,c,d) function added       */
/*   Peter D Wilson   Aug 1998  regfilter(a,b,c,d) function added       */
/*   Peter D Wilson   Jul 1999  Make parser fitsfile-independent,       */
/*                              allowing a purely vector-based usage    */
/*  Craig B Markwardt Jun 2004  Add MEDIAN() function                   */
/*  Craig B Markwardt Jun 2004  Add SUM(), and MIN/MAX() for bit arrays */
/*  Craig B Markwardt Jun 2004  Allow subscripting of nX bit arrays     */
/*  Craig B Markwardt Jun 2004  Implement statistical functions         */
/*                              NVALID(), AVERAGE(), and STDDEV()       */
/*                              for integer and floating point vectors  */
/*  Craig B Markwardt Jun 2004  Use NULL values for range errors instead*/
/*                              of throwing a parse error               */
/*  Craig B Markwardt Oct 2004  Add ACCUM() and SEQDIFF() functions     */
/*  Craig B Markwardt Feb 2005  Add ANGSEP() function                   */
/*  Craig B Markwardt Aug 2005  CIRCLE, BOX, ELLIPSE, NEAR and REGFILTER*/
/*                              functions now accept vector arguments   */
/*  Craig B Markwardt Sum 2006  Add RANDOMN() and RANDOMP() functions   */
/*  Craig B Markwardt Mar 2007  Allow arguments to RANDOM and RANDOMN to*/
/*                              determine the output dimensions         */
/*  Craig B Markwardt Aug 2009  Add substring STRMID() and string search*/
/*                              STRSTR() functions; more overflow checks*/
/*  Craig B Markwardt Dec 2019  Add bit/hex/oct literal strings and     */
/*                              bitwise operatiosn between integers     */
/*  Craig B Markwardt Mar 2021  Add SETNULL() function                  */
/*                                                                      */
/************************************************************************/

#define  APPROX 1.0e-7
#include "eval_defs.h"
#include "region.h"
#include 

#include 

#ifndef alloca
#define alloca malloc
#endif

/* Random number generators for various distributions */
#include "simplerng.h"

   /*  Shrink the initial stack depth to keep local data <32K (mac limit)  */
   /*  yacc will allocate more space if needed, though.                    */
#define  YYINITDEPTH   100

/***************************************************************/
/*  Replace Bison's BACKUP macro with one that fixes a bug --  */
/*  must update state after popping the stack -- and allows    */
/*  popping multiple terms at one time.                        */
/***************************************************************/

#define YYNEWBACKUP(token, value)                               \
   do								\
     if (yychar == YYEMPTY )   					\
       { yychar = (token);                                      \
         memcpy( &yylval, &(value), sizeof(value) );            \
         yychar1 = YYTRANSLATE (yychar);			\
         while (yylen--) YYPOPSTACK;				\
         yystate = *yyssp;					\
         goto yybackup;						\
       }							\
     else							\
       { yyerror ("syntax error: cannot back up"); YYERROR; }	\
   while (0)

/***************************************************************/
/*  Useful macros for accessing/testing Nodes                  */
/***************************************************************/

#define TEST(a)        if( (a)<0 ) YYERROR
#define SIZE(a)        lParse->Nodes[ a ].value.nelem
#define TYPE(a)        lParse->Nodes[ a ].type
#define OPER(a)        lParse->Nodes[ a ].operation
#define PROMOTE(a,b)   if( TYPE(a) > TYPE(b) )                  \
                          b = New_Unary( lParse, TYPE(a), 0, b );       \
                       else if( TYPE(a) < TYPE(b) )             \
	                  a = New_Unary( lParse, TYPE(b), 0, a );

/*****  Internal functions  *****/

#ifdef __cplusplus
extern "C" {
#endif

static int  Alloc_Node    ( ParseData * );
static void Free_Last_Node( ParseData * );
static void Evaluate_Node ( ParseData *, int thisNode );

static int  New_Const ( ParseData *, int returnType, void *value, long len );
static int  New_Column( ParseData *, int ColNum );
static int  New_Offset( ParseData *, int ColNum, int offset );
static int  New_Unary ( ParseData *, int returnType, int Op, int Node1 );
static int  New_BinOp ( ParseData *, int returnType, int Node1, int Op, int Node2 );
static int  New_Func  ( ParseData *, int returnType, funcOp Op, int nNodes,
			int Node1, int Node2, int Node3, int Node4, 
			int Node5, int Node6, int Node7 );
static int  New_FuncSize( ParseData *, int returnType, funcOp Op, int nNodes,
			int Node1, int Node2, int Node3, int Node4, 
			  int Node5, int Node6, int Node7, int Size);
static int  New_Deref ( ParseData *, int Var,  int nDim,
			int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 );
static int  New_GTI   ( ParseData *, funcOp Op, char *fname, int Node1, int Node2, char *start, char *stop );
static int  New_REG   ( ParseData *, char *fname, int NodeX, int NodeY, char *colNames );
static int  New_Vector( ParseData *, int subNode );
static int  Close_Vec ( ParseData *, int vecNode );
static int  New_Array(  ParseData *, int valueNode, int dimNode );
static int  Locate_Col( ParseData *, Node *this );
static int  Test_Dims ( ParseData *, int Node1, int Node2 );
static void Copy_Dims ( ParseData *, int Node1, int Node2 );

static void Allocate_Ptrs( ParseData *, Node *this );
static void Do_Unary     ( ParseData *, Node *this );
static void Do_Offset    ( ParseData *, Node *this );
static void Do_BinOp_bit ( ParseData *, Node *this );
static void Do_BinOp_str ( ParseData *, Node *this );
static void Do_BinOp_log ( ParseData *, Node *this );
static void Do_BinOp_lng ( ParseData *, Node *this );
static void Do_BinOp_dbl ( ParseData *, Node *this );
static void Do_Func      ( ParseData *, Node *this );
static void Do_Deref     ( ParseData *, Node *this );
static void Do_GTI       ( ParseData *, Node *this );
static void Do_GTI_Over  ( ParseData *, Node *this );
static void Do_REG       ( ParseData *, Node *this );
static void Do_Vector    ( ParseData *, Node *this );
static void Do_Array     ( ParseData *, Node *this );

static long Search_GTI   ( double evtTime, long nGTI, double *start,
			   double *stop, int ordered, long *nextGTI );
static double GTI_Over(double evtStart, double evtStop,
		       long nGTI, double *start, double *stop,
		       long *gtiout);

static char  saobox (double xcen, double ycen, double xwid, double ywid,
		     double rot,  double xcol, double ycol);
static char  ellipse(double xcen, double ycen, double xrad, double yrad,
		     double rot, double xcol, double ycol);
static char  circle (double xcen, double ycen, double rad,
		     double xcol, double ycol);
static char  bnear  (double x, double y, double tolerance);
static char  bitcmp (char *bitstrm1, char *bitstrm2);
static char  bitlgte(char *bits1, int oper, char *bits2);

static void  bitand(char *result, char *bitstrm1, char *bitstrm2);
static void  bitor (char *result, char *bitstrm1, char *bitstrm2);
static void  bitnot(char *result, char *bits);
static int cstrmid(ParseData *lParse, char *dest_str, int dest_len,
		   char *src_str,  int src_len, int pos);

static void yyerror(yyscan_t scanner, ParseData *lParse, char *s);

#ifdef __cplusplus
    }
#endif


#line 273 "eval_y.c"

# ifndef YY_CAST
#  ifdef __cplusplus
#   define YY_CAST(Type, Val) static_cast (Val)
#   define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val)
#  else
#   define YY_CAST(Type, Val) ((Type) (Val))
#   define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
#  endif
# endif
# ifndef YY_NULLPTR
#  if defined __cplusplus
#   if 201103L <= __cplusplus
#    define YY_NULLPTR nullptr
#   else
#    define YY_NULLPTR 0
#   endif
#  else
#   define YY_NULLPTR ((void*)0)
#  endif
# endif

#include "eval_tab.h"
/* Symbol kind.  */
enum yysymbol_kind_t
{
  YYSYMBOL_YYEMPTY = -2,
  YYSYMBOL_YYEOF = 0,                      /* "end of file"  */
  YYSYMBOL_YYerror = 1,                    /* error  */
  YYSYMBOL_YYUNDEF = 2,                    /* "invalid token"  */
  YYSYMBOL_BOOLEAN = 3,                    /* BOOLEAN  */
  YYSYMBOL_LONG = 4,                       /* LONG  */
  YYSYMBOL_DOUBLE = 5,                     /* DOUBLE  */
  YYSYMBOL_STRING = 6,                     /* STRING  */
  YYSYMBOL_BITSTR = 7,                     /* BITSTR  */
  YYSYMBOL_FUNCTION = 8,                   /* FUNCTION  */
  YYSYMBOL_BFUNCTION = 9,                  /* BFUNCTION  */
  YYSYMBOL_IFUNCTION = 10,                 /* IFUNCTION  */
  YYSYMBOL_GTIFILTER = 11,                 /* GTIFILTER  */
  YYSYMBOL_GTIOVERLAP = 12,                /* GTIOVERLAP  */
  YYSYMBOL_GTIFIND = 13,                   /* GTIFIND  */
  YYSYMBOL_REGFILTER = 14,                 /* REGFILTER  */
  YYSYMBOL_COLUMN = 15,                    /* COLUMN  */
  YYSYMBOL_BCOLUMN = 16,                   /* BCOLUMN  */
  YYSYMBOL_SCOLUMN = 17,                   /* SCOLUMN  */
  YYSYMBOL_BITCOL = 18,                    /* BITCOL  */
  YYSYMBOL_ROWREF = 19,                    /* ROWREF  */
  YYSYMBOL_NULLREF = 20,                   /* NULLREF  */
  YYSYMBOL_SNULLREF = 21,                  /* SNULLREF  */
  YYSYMBOL_22_ = 22,                       /* ','  */
  YYSYMBOL_23_ = 23,                       /* '='  */
  YYSYMBOL_24_ = 24,                       /* ':'  */
  YYSYMBOL_25_ = 25,                       /* '{'  */
  YYSYMBOL_26_ = 26,                       /* '}'  */
  YYSYMBOL_27_ = 27,                       /* '?'  */
  YYSYMBOL_OR = 28,                        /* OR  */
  YYSYMBOL_AND = 29,                       /* AND  */
  YYSYMBOL_EQ = 30,                        /* EQ  */
  YYSYMBOL_NE = 31,                        /* NE  */
  YYSYMBOL_32_ = 32,                       /* '~'  */
  YYSYMBOL_GT = 33,                        /* GT  */
  YYSYMBOL_LT = 34,                        /* LT  */
  YYSYMBOL_LTE = 35,                       /* LTE  */
  YYSYMBOL_GTE = 36,                       /* GTE  */
  YYSYMBOL_37_ = 37,                       /* '+'  */
  YYSYMBOL_38_ = 38,                       /* '-'  */
  YYSYMBOL_39_ = 39,                       /* '%'  */
  YYSYMBOL_40_ = 40,                       /* '*'  */
  YYSYMBOL_41_ = 41,                       /* '/'  */
  YYSYMBOL_42_ = 42,                       /* '|'  */
  YYSYMBOL_43_ = 43,                       /* '&'  */
  YYSYMBOL_XOR = 44,                       /* XOR  */
  YYSYMBOL_POWER = 45,                     /* POWER  */
  YYSYMBOL_NOT = 46,                       /* NOT  */
  YYSYMBOL_INTCAST = 47,                   /* INTCAST  */
  YYSYMBOL_FLTCAST = 48,                   /* FLTCAST  */
  YYSYMBOL_UMINUS = 49,                    /* UMINUS  */
  YYSYMBOL_50_ = 50,                       /* '['  */
  YYSYMBOL_ACCUM = 51,                     /* ACCUM  */
  YYSYMBOL_DIFF = 52,                      /* DIFF  */
  YYSYMBOL_53_n_ = 53,                     /* '\n'  */
  YYSYMBOL_54_ = 54,                       /* ']'  */
  YYSYMBOL_55_ = 55,                       /* '('  */
  YYSYMBOL_56_ = 56,                       /* ')'  */
  YYSYMBOL_YYACCEPT = 57,                  /* $accept  */
  YYSYMBOL_lines = 58,                     /* lines  */
  YYSYMBOL_line = 59,                      /* line  */
  YYSYMBOL_bvector = 60,                   /* bvector  */
  YYSYMBOL_vector = 61,                    /* vector  */
  YYSYMBOL_expr = 62,                      /* expr  */
  YYSYMBOL_bexpr = 63,                     /* bexpr  */
  YYSYMBOL_bits = 64,                      /* bits  */
  YYSYMBOL_sexpr = 65                      /* sexpr  */
};
typedef enum yysymbol_kind_t yysymbol_kind_t;




#ifdef short
# undef short
#endif

/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
    and (if available)  are included
   so that the code can choose integer types of a good width.  */

#ifndef __PTRDIFF_MAX__
# include  /* INFRINGES ON USER NAME SPACE */
# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
#  include  /* INFRINGES ON USER NAME SPACE */
#  define YY_STDINT_H
# endif
#endif

/* Narrow types that promote to a signed type and that can represent a
   signed or unsigned integer of at least N bits.  In tables they can
   save space and decrease cache pressure.  Promoting to a signed type
   helps avoid bugs in integer arithmetic.  */

#ifdef __INT_LEAST8_MAX__
typedef __INT_LEAST8_TYPE__ yytype_int8;
#elif defined YY_STDINT_H
typedef int_least8_t yytype_int8;
#else
typedef signed char yytype_int8;
#endif

#ifdef __INT_LEAST16_MAX__
typedef __INT_LEAST16_TYPE__ yytype_int16;
#elif defined YY_STDINT_H
typedef int_least16_t yytype_int16;
#else
typedef short yytype_int16;
#endif

/* Work around bug in HP-UX 11.23, which defines these macros
   incorrectly for preprocessor constants.  This workaround can likely
   be removed in 2023, as HPE has promised support for HP-UX 11.23
   (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
   .  */
#ifdef __hpux
# undef UINT_LEAST8_MAX
# undef UINT_LEAST16_MAX
# define UINT_LEAST8_MAX 255
# define UINT_LEAST16_MAX 65535
#endif

#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
       && UINT_LEAST8_MAX <= INT_MAX)
typedef uint_least8_t yytype_uint8;
#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
typedef unsigned char yytype_uint8;
#else
typedef short yytype_uint8;
#endif

#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
typedef __UINT_LEAST16_TYPE__ yytype_uint16;
#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
       && UINT_LEAST16_MAX <= INT_MAX)
typedef uint_least16_t yytype_uint16;
#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
typedef unsigned short yytype_uint16;
#else
typedef int yytype_uint16;
#endif

#ifndef YYPTRDIFF_T
# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
#  define YYPTRDIFF_T __PTRDIFF_TYPE__
#  define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
# elif defined PTRDIFF_MAX
#  ifndef ptrdiff_t
#   include  /* INFRINGES ON USER NAME SPACE */
#  endif
#  define YYPTRDIFF_T ptrdiff_t
#  define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
# else
#  define YYPTRDIFF_T long
#  define YYPTRDIFF_MAXIMUM LONG_MAX
# endif
#endif

#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
#  define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
#  define YYSIZE_T size_t
# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
#  include  /* INFRINGES ON USER NAME SPACE */
#  define YYSIZE_T size_t
# else
#  define YYSIZE_T unsigned
# endif
#endif

#define YYSIZE_MAXIMUM                                  \
  YY_CAST (YYPTRDIFF_T,                                 \
           (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1)  \
            ? YYPTRDIFF_MAXIMUM                         \
            : YY_CAST (YYSIZE_T, -1)))

#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))


/* Stored state numbers (used for stacks). */
typedef yytype_int16 yy_state_t;

/* State numbers in computations.  */
typedef int yy_state_fast_t;

#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
#  if ENABLE_NLS
#   include  /* INFRINGES ON USER NAME SPACE */
#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
#  endif
# endif
# ifndef YY_
#  define YY_(Msgid) Msgid
# endif
#endif


#ifndef YY_ATTRIBUTE_PURE
# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
#  define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
#  define YY_ATTRIBUTE_PURE
# endif
#endif

#ifndef YY_ATTRIBUTE_UNUSED
# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
#  define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
# else
#  define YY_ATTRIBUTE_UNUSED
# endif
#endif

/* Suppress unused-variable warnings by "using" E.  */
#if ! defined lint || defined __GNUC__
# define YY_USE(E) ((void) (E))
#else
# define YY_USE(E) /* empty */
#endif

/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \
    _Pragma ("GCC diagnostic push")                                     \
    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
# else
#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \
    _Pragma ("GCC diagnostic push")                                     \
    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")              \
    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# endif
# define YY_IGNORE_MAYBE_UNINITIALIZED_END      \
    _Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
#endif
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif

#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
# define YY_IGNORE_USELESS_CAST_BEGIN                          \
    _Pragma ("GCC diagnostic push")                            \
    _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
# define YY_IGNORE_USELESS_CAST_END            \
    _Pragma ("GCC diagnostic pop")
#endif
#ifndef YY_IGNORE_USELESS_CAST_BEGIN
# define YY_IGNORE_USELESS_CAST_BEGIN
# define YY_IGNORE_USELESS_CAST_END
#endif


#define YY_ASSERT(E) ((void) (0 && (E)))

#if !defined yyoverflow

/* The parser invokes alloca or malloc; define the necessary symbols.  */

# ifdef YYSTACK_USE_ALLOCA
#  if YYSTACK_USE_ALLOCA
#   ifdef __GNUC__
#    define YYSTACK_ALLOC __builtin_alloca
#   elif defined __BUILTIN_VA_ARG_INCR
#    include  /* INFRINGES ON USER NAME SPACE */
#   elif defined _AIX
#    define YYSTACK_ALLOC __alloca
#   elif defined _MSC_VER
#    include  /* INFRINGES ON USER NAME SPACE */
#    define alloca _alloca
#   else
#    define YYSTACK_ALLOC alloca
#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
#     include  /* INFRINGES ON USER NAME SPACE */
      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
#     ifndef EXIT_SUCCESS
#      define EXIT_SUCCESS 0
#     endif
#    endif
#   endif
#  endif
# endif

# ifdef YYSTACK_ALLOC
   /* Pacify GCC's 'empty if-body' warning.  */
#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
#  ifndef YYSTACK_ALLOC_MAXIMUM
    /* The OS might guarantee only one guard page at the bottom of the stack,
       and a page size can be as small as 4096 bytes.  So we cannot safely
       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
       to allow for a few compiler-allocated temporary stack slots.  */
#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
#  endif
# else
#  define YYSTACK_ALLOC YYMALLOC
#  define YYSTACK_FREE YYFREE
#  ifndef YYSTACK_ALLOC_MAXIMUM
#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
#  endif
#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
       && ! ((defined YYMALLOC || defined malloc) \
             && (defined YYFREE || defined free)))
#   include  /* INFRINGES ON USER NAME SPACE */
#   ifndef EXIT_SUCCESS
#    define EXIT_SUCCESS 0
#   endif
#  endif
#  ifndef YYMALLOC
#   define YYMALLOC malloc
#   if ! defined malloc && ! defined EXIT_SUCCESS
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
#   endif
#  endif
#  ifndef YYFREE
#   define YYFREE free
#   if ! defined free && ! defined EXIT_SUCCESS
void free (void *); /* INFRINGES ON USER NAME SPACE */
#   endif
#  endif
# endif
#endif /* !defined yyoverflow */

#if (! defined yyoverflow \
     && (! defined __cplusplus \
         || (defined FITS_PARSER_YYSTYPE_IS_TRIVIAL && FITS_PARSER_YYSTYPE_IS_TRIVIAL)))

/* A type that is properly aligned for any stack member.  */
union yyalloc
{
  yy_state_t yyss_alloc;
  YYSTYPE yyvs_alloc;
};

/* The size of the maximum gap between one aligned stack and the next.  */
# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)

/* The size of an array large to enough to hold all stacks, each with
   N elements.  */
# define YYSTACK_BYTES(N) \
     ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
      + YYSTACK_GAP_MAXIMUM)

# define YYCOPY_NEEDED 1

/* Relocate STACK from its old location to the new one.  The
   local variables YYSIZE and YYSTACKSIZE give the old and new number of
   elements in the stack, and YYPTR gives the new location of the
   stack.  Advance YYPTR to a properly aligned location for the next
   stack.  */
# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
    do                                                                  \
      {                                                                 \
        YYPTRDIFF_T yynewbytes;                                         \
        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
        Stack = &yyptr->Stack_alloc;                                    \
        yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / YYSIZEOF (*yyptr);                        \
      }                                                                 \
    while (0)

#endif

#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
/* Copy COUNT objects from SRC to DST.  The source and destination do
   not overlap.  */
# ifndef YYCOPY
#  if defined __GNUC__ && 1 < __GNUC__
#   define YYCOPY(Dst, Src, Count) \
      __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
#  else
#   define YYCOPY(Dst, Src, Count)              \
      do                                        \
        {                                       \
          YYPTRDIFF_T yyi;                      \
          for (yyi = 0; yyi < (Count); yyi++)   \
            (Dst)[yyi] = (Src)[yyi];            \
        }                                       \
      while (0)
#  endif
# endif
#endif /* !YYCOPY_NEEDED */

/* YYFINAL -- State number of the termination state.  */
#define YYFINAL  2
/* YYLAST -- Last index in YYTABLE.  */
#define YYLAST   1776

/* YYNTOKENS -- Number of terminals.  */
#define YYNTOKENS  57
/* YYNNTS -- Number of nonterminals.  */
#define YYNNTS  9
/* YYNRULES -- Number of rules.  */
#define YYNRULES  135
/* YYNSTATES -- Number of states.  */
#define YYNSTATES  322

/* YYMAXUTOK -- Last valid token kind.  */
#define YYMAXUTOK   292


/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
   as returned by yylex, with out-of-bounds checking.  */
#define YYTRANSLATE(YYX)                                \
  (0 <= (YYX) && (YYX) <= YYMAXUTOK                     \
   ? YY_CAST (yysymbol_kind_t, yytranslate[YYX])        \
   : YYSYMBOL_YYUNDEF)

/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
   as returned by yylex.  */
static const yytype_int8 yytranslate[] =
{
       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      53,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,    39,    43,     2,
      55,    56,    40,    37,    22,    38,     2,    41,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,    24,     2,
       2,    23,     2,    27,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,    50,     2,    54,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,    25,    42,    26,    32,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
      15,    16,    17,    18,    19,    20,    21,    28,    29,    30,
      31,    33,    34,    35,    36,    44,    45,    46,    47,    48,
      49,    51,    52
};

#if FITS_PARSER_YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
static const yytype_int16 yyrline[] =
{
       0,   266,   266,   267,   270,   271,   277,   283,   289,   295,
     298,   300,   313,   315,   328,   339,   353,   357,   361,   365,
     367,   376,   379,   382,   391,   393,   395,   397,   399,   401,
     404,   408,   410,   412,   414,   423,   425,   427,   430,   433,
     436,   439,   442,   451,   460,   469,   472,   474,   476,   478,
     482,   486,   505,   524,   543,   554,   568,   617,   629,   660,
     774,   782,   885,   911,   914,   918,   920,   922,   924,   926,
     928,   930,   932,   934,   938,   940,   942,   951,   954,   957,
     960,   963,   966,   969,   972,   975,   978,   981,   984,   987,
     990,   993,   996,   999,  1002,  1005,  1008,  1010,  1012,  1014,
    1017,  1024,  1041,  1054,  1067,  1078,  1094,  1118,  1146,  1183,
    1187,  1191,  1194,  1200,  1204,  1208,  1211,  1216,  1220,  1223,
    1227,  1229,  1231,  1233,  1235,  1237,  1239,  1243,  1246,  1248,
    1257,  1259,  1261,  1270,  1289,  1308
};
#endif

/** Accessing symbol of state STATE.  */
#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])

#if FITS_PARSER_YYDEBUG || 0
/* The user-facing name of the symbol whose (internal) number is
   YYSYMBOL.  No bounds checking.  */
static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;

/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
static const char *const yytname[] =
{
  "\"end of file\"", "error", "\"invalid token\"", "BOOLEAN", "LONG",
  "DOUBLE", "STRING", "BITSTR", "FUNCTION", "BFUNCTION", "IFUNCTION",
  "GTIFILTER", "GTIOVERLAP", "GTIFIND", "REGFILTER", "COLUMN", "BCOLUMN",
  "SCOLUMN", "BITCOL", "ROWREF", "NULLREF", "SNULLREF", "','", "'='",
  "':'", "'{'", "'}'", "'?'", "OR", "AND", "EQ", "NE", "'~'", "GT", "LT",
  "LTE", "GTE", "'+'", "'-'", "'%'", "'*'", "'/'", "'|'", "'&'", "XOR",
  "POWER", "NOT", "INTCAST", "FLTCAST", "UMINUS", "'['", "ACCUM", "DIFF",
  "'\\n'", "']'", "'('", "')'", "$accept", "lines", "line", "bvector",
  "vector", "expr", "bexpr", "bits", "sexpr", YY_NULLPTR
};

static const char *
yysymbol_name (yysymbol_kind_t yysymbol)
{
  return yytname[yysymbol];
}
#endif

#define YYPACT_NINF (-41)

#define yypact_value_is_default(Yyn) \
  ((Yyn) == YYPACT_NINF)

#define YYTABLE_NINF (-1)

#define yytable_value_is_error(Yyn) \
  0

/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
   STATE-NUM.  */
static const yytype_int16 yypact[] =
{
     -41,   316,   -41,   -40,   -41,   -41,   -41,   -41,   -41,   369,
     423,   423,    -5,    15,    -4,    27,    36,    38,    40,    41,
     -41,   -41,   -41,   423,   423,   423,   423,   423,   423,   -41,
     423,   -41,    -7,    10,  1226,    81,  1646,    83,   -41,   -41,
     450,   116,   309,    12,   479,   185,   152,   222,  1593,  1673,
    1675,   -19,   -41,    13,   -18,   -41,     6,   423,   423,   423,
     423,  1593,  1673,  1684,    17,    17,    19,    24,    17,    19,
      17,    19,   710,  1253,  1611,   365,   423,   -41,   423,   -41,
     423,   423,   423,   423,   423,   423,   423,   423,   423,   423,
     423,   423,   423,   423,   423,   423,   423,   423,   -41,   423,
     423,   423,   423,   423,   423,   423,   -41,    -2,    -2,    -2,
      -2,    -2,    -2,    -2,    -2,    -2,   423,   -41,   423,   423,
     423,   423,   423,   423,   423,   -41,   423,   -41,   423,   -41,
     -41,   423,   -41,   423,   -41,   -41,   -41,   423,   423,   -41,
     423,   423,   -41,   423,   -41,  1455,  1478,  1501,  1524,   -41,
     -41,   -41,   -41,  1593,  1673,  1593,  1673,  1547,  1712,  1712,
    1712,  1726,  1726,  1726,  1726,   368,   368,   368,    28,    19,
      28,     5,     5,     5,     5,   851,  1570,   425,   260,   128,
     -20,    14,    14,    28,   876,    -2,    -2,   -25,   -25,   -25,
     -25,   -25,   -25,   -36,    24,    24,   901,   140,   140,    39,
      39,    39,    39,   -41,   508,   738,  1258,  1288,  1629,  1312,
    1638,   537,  1336,   566,  1360,   -41,   -41,   -41,   -41,   423,
     423,   -41,   423,   423,   423,   423,   -41,    24,   189,   423,
     -41,   423,   -41,   -41,   -41,   423,   -41,   423,   -41,    93,
     -41,   423,    94,   -41,   423,  1694,   926,  1694,  1673,  1694,
    1673,  1684,   951,   976,  1384,   766,   595,    79,   624,    80,
     653,   423,   -41,   423,   -41,   423,   -41,   423,   -41,   423,
     -41,   100,   101,   -41,   117,   118,   -41,  1001,  1026,  1051,
     794,  1408,    72,   111,    85,    99,   423,   -41,   423,   -41,
     423,   -41,   -41,   423,   -41,   129,   -41,   -41,  1076,  1101,
    1126,   682,   104,   423,   -41,   423,   -41,   423,   -41,   423,
     -41,   -41,  1151,  1176,  1201,  1432,   -41,   -41,   -41,   423,
     822,   -41
};

/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
   Performed when YYTABLE does not specify something else to do.  Zero
   means the default is an error.  */
static const yytype_uint8 yydefact[] =
{
       2,     0,     1,     0,    74,    31,    32,   127,    18,     0,
       0,     0,     0,     0,     0,     0,    33,    75,   128,    19,
      35,    36,   130,     0,     0,     0,     0,     0,     0,     4,
       0,     3,     0,     0,     0,     0,     0,     0,     9,    54,
       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
       0,     0,   109,     0,     0,   113,     0,     0,     0,     0,
       0,    12,    10,     0,    46,    47,   125,    29,    70,    71,
      72,    73,     0,     0,     0,     0,     0,    17,     0,    16,
       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
       0,     0,     0,     0,     0,     0,     0,     0,     5,     0,
       0,     0,     0,     0,     0,     0,     6,     0,     0,     0,
       0,     0,     0,     0,     0,     0,     0,     8,     0,     0,
       0,     0,     0,     0,     0,     7,     0,    59,     0,    55,
      58,     0,    57,     0,   102,   103,   104,     0,     0,   110,
       0,     0,   114,     0,   117,     0,     0,     0,     0,    48,
     126,    30,   131,    15,    11,    13,    14,     0,    88,    89,
      87,    83,    84,    86,    85,    38,    39,    37,    40,    49,
      41,    43,    42,    44,    45,     0,     0,     0,     0,    97,
      96,    98,    99,    50,     0,     0,     0,    77,    78,    81,
      79,    80,    82,    23,    22,    21,     0,    90,    91,    92,
      94,    95,    93,   132,     0,     0,     0,     0,     0,     0,
       0,     0,     0,     0,     0,    34,    76,   129,    20,     0,
       0,    65,     0,     0,     0,     0,   120,    29,     0,     0,
      24,     0,    61,    56,   105,     0,   134,     0,    60,     0,
     111,     0,     0,   115,     0,   100,     0,    51,    53,    52,
     101,   133,     0,     0,     0,     0,     0,     0,     0,     0,
       0,     0,    66,     0,   121,     0,    25,     0,   135,     0,
     106,     0,     0,    63,     0,     0,   118,     0,     0,     0,
       0,     0,     0,     0,     0,     0,     0,    67,     0,   122,
       0,    26,    62,     0,   112,     0,   116,   119,     0,     0,
       0,     0,     0,     0,    68,     0,   123,     0,    27,     0,
     107,    64,     0,     0,     0,     0,    69,   124,    28,     0,
       0,   108
};

/* YYPGOTO[NTERM-NUM].  */
static const yytype_int16 yypgoto[] =
{
     -41,   -41,   -41,   -41,   -41,    -1,   170,    96,    30
};

/* YYDEFGOTO[NTERM-NUM].  */
static const yytype_int8 yydefgoto[] =
{
       0,     1,    31,    32,    33,    48,    49,    46,    63
};

/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
   positive, shift that token.  If negative, reduce the rule whose
   number is the opposite.  If YYTABLE_NINF, syntax error.  */
static const yytype_int16 yytable[] =
{
      34,    51,    54,   138,   141,     8,   114,   115,    40,    44,
     102,   103,   113,    38,   116,    76,    19,   114,   115,    77,
     104,    53,    61,    64,    65,   116,    68,    70,   143,    72,
     105,    37,    78,    56,   131,   140,    79,   139,   142,    43,
      47,    50,   118,   119,   185,   120,   121,   122,   123,   124,
      96,    52,    55,   186,   104,    97,   145,   146,   147,   148,
      75,    57,   144,    58,   105,    59,    60,    97,   132,   105,
      93,    94,    95,    96,   116,   153,   124,   155,    97,   157,
     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
     168,   170,   171,   172,   173,   174,   175,    36,   176,   257,
     259,   271,   274,   183,   184,    42,   282,   283,    99,   100,
     101,   102,   103,   118,   119,   196,   120,   121,   122,   123,
     124,   104,    67,   284,   285,   204,    74,   205,   294,   178,
     207,   105,   209,   295,   106,   302,   125,   211,   128,   212,
     213,   296,   214,    99,   100,   101,   102,   103,   197,   198,
     199,   200,   201,   202,   203,   297,   104,   101,   102,   103,
     311,   208,     0,     0,     0,     0,   105,   210,   104,     0,
       0,    35,   129,   120,   121,   122,   123,   124,   105,    41,
      45,     0,   107,   108,     0,   109,   110,   111,   112,   113,
       0,     0,     0,    62,   114,   115,    66,    69,    71,     0,
      73,     0,   116,   187,   188,   189,   190,   191,   192,   193,
     194,   195,    99,   100,   101,   102,   103,     0,   245,   246,
       0,   247,   249,     0,   252,   104,   113,     0,   253,     0,
     254,   114,   115,     0,   255,   105,   256,     0,     0,   116,
     258,   135,     0,   260,     0,   151,   154,     0,   156,     0,
       0,     0,   118,   119,   251,   120,   121,   122,   123,   124,
     277,   169,   278,     0,   279,     0,   280,     0,   281,   177,
     179,   180,   181,   182,     0,     0,     0,     0,   136,     0,
       0,   227,   228,     0,   224,   298,     0,   299,     0,   300,
     118,   119,   301,   120,   121,   122,   123,   124,   206,     0,
       0,     0,   312,     0,   313,     0,   314,     0,   315,     0,
       0,     0,     0,     0,     0,     0,     2,     3,   320,     4,
       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
      15,    16,    17,    18,    19,    20,    21,    22,     0,   107,
     108,    23,   109,   110,   111,   112,   113,     0,     0,     0,
       0,   114,   115,    24,    25,     0,     0,     0,     0,   116,
       0,     0,    26,    27,    28,   130,     0,     0,     0,    29,
       0,    30,     4,     5,     6,     7,     8,     9,    10,    11,
      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
      22,     0,   248,   250,    23,   118,   119,     0,   120,   121,
     122,   123,   124,     0,     0,     0,    24,    25,    91,    92,
      93,    94,    95,    96,     0,    26,    27,    28,    97,     0,
       0,   152,     0,     0,    30,    39,     4,     5,     6,     7,
       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
      18,    19,    20,    21,    22,     0,     0,     0,    23,   223,
       0,     0,    99,   100,   101,   102,   103,     0,     0,     0,
      24,    25,     0,     0,     0,   104,     0,     0,     0,    26,
      27,    28,   126,    80,     0,   105,     0,     0,    30,     0,
      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
      91,    92,    93,    94,    95,    96,     0,     0,     0,     0,
      97,   133,    80,     0,     0,     0,   127,     0,     0,    81,
      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
      92,    93,    94,    95,    96,     0,     0,     0,     0,    97,
     231,    80,     0,     0,     0,   134,     0,     0,    81,    82,
      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
      93,    94,    95,    96,     0,     0,     0,     0,    97,   239,
      80,     0,     0,     0,   232,     0,     0,    81,    82,    83,
      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
      94,    95,    96,     0,     0,     0,     0,    97,   242,    80,
       0,     0,     0,   240,     0,     0,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,     0,     0,     0,    97,   269,    80,     0,
       0,     0,   243,     0,     0,    81,    82,    83,    84,    85,
      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
      96,     0,     0,     0,     0,    97,   272,    80,     0,     0,
       0,   270,     0,     0,    81,    82,    83,    84,    85,    86,
      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
       0,     0,     0,     0,    97,   275,    80,     0,     0,     0,
     273,     0,     0,    81,    82,    83,    84,    85,    86,    87,
      88,    89,    90,    91,    92,    93,    94,    95,    96,     0,
       0,     0,     0,    97,   309,    80,     0,     0,     0,   276,
       0,     0,    81,    82,    83,    84,    85,    86,    87,    88,
      89,    90,    91,    92,    93,    94,    95,    96,     0,     0,
       0,     0,    97,    80,     0,     0,     0,     0,   310,     0,
      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
      91,    92,    93,    94,    95,    96,     0,     0,     0,     0,
      97,    80,     0,     0,     0,     0,   149,     0,    81,    82,
      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
      93,    94,    95,    96,     0,     0,     0,     0,    97,    80,
       0,     0,     0,     0,   233,     0,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,     0,     0,     0,    97,    80,     0,     0,
       0,     0,   268,     0,    81,    82,    83,    84,    85,    86,
      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
       0,     0,     0,     0,    97,    80,     0,     0,     0,     0,
     292,     0,    81,    82,    83,    84,    85,    86,    87,    88,
      89,    90,    91,    92,    93,    94,    95,    96,     0,     0,
       0,     0,    97,   220,    80,     0,     0,     0,   321,     0,
       0,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,   225,    80,
       0,    97,     0,     0,     0,   221,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,   229,    80,     0,    97,     0,     0,     0,
     226,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,   261,    80,
       0,    97,     0,     0,     0,   230,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,   263,    80,     0,    97,     0,     0,     0,
     262,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,   265,    80,
       0,    97,     0,     0,     0,   264,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,   286,    80,     0,    97,     0,     0,     0,
     266,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,   288,    80,
       0,    97,     0,     0,     0,   287,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,   290,    80,     0,    97,     0,     0,     0,
     289,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,   303,    80,
       0,    97,     0,     0,     0,   291,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,   305,    80,     0,    97,     0,     0,     0,
     304,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,   307,    80,
       0,    97,     0,     0,     0,   306,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,     0,    80,     0,    97,     0,     0,     0,
     308,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,     0,    80,
       0,    97,     0,     0,     0,   316,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,     0,    80,     0,    97,     0,     0,     0,
     317,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,     0,     0,    80,
       0,    97,     0,     0,     0,   318,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,     0,     0,     0,    97,     0,     0,    98,
      99,   100,   101,   102,   103,    99,   100,   101,   102,   103,
       0,     0,     0,   104,     0,     0,     0,     0,   104,     0,
       0,     0,     0,   105,     0,     0,     0,     0,   105,   150,
     235,    80,     0,     0,   234,     0,     0,     0,    81,    82,
      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
      93,    94,    95,    96,   237,    80,     0,     0,    97,     0,
       0,     0,    81,    82,    83,    84,    85,    86,    87,    88,
      89,    90,    91,    92,    93,    94,    95,    96,   241,    80,
       0,     0,    97,     0,     0,     0,    81,    82,    83,    84,
      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
      95,    96,   244,    80,     0,     0,    97,     0,     0,     0,
      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
      91,    92,    93,    94,    95,    96,   267,    80,     0,     0,
      97,     0,     0,     0,    81,    82,    83,    84,    85,    86,
      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
     293,    80,     0,     0,    97,     0,     0,     0,    81,    82,
      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
      93,    94,    95,    96,   319,    80,     0,     0,    97,     0,
       0,     0,    81,    82,    83,    84,    85,    86,    87,    88,
      89,    90,    91,    92,    93,    94,    95,    96,    80,     0,
       0,   215,    97,     0,     0,    81,    82,    83,    84,    85,
      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
      96,    80,     0,     0,   216,    97,     0,     0,    81,    82,
      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
      93,    94,    95,    96,    80,     0,     0,   217,    97,     0,
       0,    81,    82,    83,    84,    85,    86,    87,    88,    89,
      90,    91,    92,    93,    94,    95,    96,    80,     0,     0,
     218,    97,     0,     0,    81,    82,    83,    84,    85,    86,
      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
      80,   219,     0,     0,    97,     0,     0,    81,    82,    83,
      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
      94,    95,    96,    80,   222,     0,     0,    97,     0,     0,
      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
      91,    92,    93,    94,    95,    96,    80,     0,     0,     0,
      97,     0,     0,    81,    82,    83,    84,    85,    86,    87,
      88,    89,    90,    91,    92,    93,    94,    95,    96,     0,
       0,   107,   108,    97,   109,   110,   111,   112,   113,     0,
       0,     0,     0,   114,   115,     0,     0,     0,     0,   118,
     119,   116,   120,   121,   122,   123,   124,   151,   118,   119,
       0,   120,   121,   122,   123,   124,   107,   108,     0,   109,
     110,   111,   112,   113,     0,   236,     0,     0,   114,   115,
       0,     0,     0,     0,   238,     0,   116,   137,     0,   117,
      99,   100,   101,   102,   103,   118,   119,     0,   120,   121,
     122,   123,   124,   104,   118,   119,     0,   120,   121,   122,
     123,   124,     0,   105,    81,    82,    83,    84,    85,    86,
      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
       0,     0,     0,     0,    97,    84,    85,    86,    87,    88,
      89,    90,    91,    92,    93,    94,    95,    96,     0,     0,
       0,     0,    97,    88,    89,    90,    91,    92,    93,    94,
      95,    96,     0,     0,     0,     0,    97
};

static const yytype_int16 yycheck[] =
{
       1,     6,     6,    22,    22,     7,    42,    43,     9,    10,
      30,    31,    37,    53,    50,    22,    18,    42,    43,    26,
      40,     6,    23,    24,    25,    50,    27,    28,    22,    30,
      50,     1,    22,     6,    22,    22,    26,    56,    56,     9,
      10,    11,    30,    31,    46,    33,    34,    35,    36,    37,
      45,    56,    56,    55,    40,    50,    57,    58,    59,    60,
      30,    25,    56,    25,    50,    25,    25,    50,    56,    50,
      42,    43,    44,    45,    50,    76,    37,    78,    50,    80,
      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
      91,    92,    93,    94,    95,    96,    97,     1,    99,     6,
       6,    22,    22,   104,   105,     9,     6,     6,    27,    28,
      29,    30,    31,    30,    31,   116,    33,    34,    35,    36,
      37,    40,    26,     6,     6,   126,    30,   128,    56,    99,
     131,    50,   133,    22,    53,     6,    53,   138,    22,   140,
     141,    56,   143,    27,    28,    29,    30,    31,   118,   119,
     120,   121,   122,   123,   124,    56,    40,    29,    30,    31,
      56,   131,    -1,    -1,    -1,    -1,    50,   137,    40,    -1,
      -1,     1,    56,    33,    34,    35,    36,    37,    50,     9,
      10,    -1,    30,    31,    -1,    33,    34,    35,    36,    37,
      -1,    -1,    -1,    23,    42,    43,    26,    27,    28,    -1,
      30,    -1,    50,   107,   108,   109,   110,   111,   112,   113,
     114,   115,    27,    28,    29,    30,    31,    -1,   219,   220,
      -1,   222,   223,    -1,   225,    40,    37,    -1,   229,    -1,
     231,    42,    43,    -1,   235,    50,   237,    -1,    -1,    50,
     241,    56,    -1,   244,    -1,    56,    76,    -1,    78,    -1,
      -1,    -1,    30,    31,   224,    33,    34,    35,    36,    37,
     261,    91,   263,    -1,   265,    -1,   267,    -1,   269,    99,
     100,   101,   102,   103,    -1,    -1,    -1,    -1,    56,    -1,
      -1,   185,   186,    -1,    24,   286,    -1,   288,    -1,   290,
      30,    31,   293,    33,    34,    35,    36,    37,   128,    -1,
      -1,    -1,   303,    -1,   305,    -1,   307,    -1,   309,    -1,
      -1,    -1,    -1,    -1,    -1,    -1,     0,     1,   319,     3,
       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
      14,    15,    16,    17,    18,    19,    20,    21,    -1,    30,
      31,    25,    33,    34,    35,    36,    37,    -1,    -1,    -1,
      -1,    42,    43,    37,    38,    -1,    -1,    -1,    -1,    50,
      -1,    -1,    46,    47,    48,    56,    -1,    -1,    -1,    53,
      -1,    55,     3,     4,     5,     6,     7,     8,     9,    10,
      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
      21,    -1,   222,   223,    25,    30,    31,    -1,    33,    34,
      35,    36,    37,    -1,    -1,    -1,    37,    38,    40,    41,
      42,    43,    44,    45,    -1,    46,    47,    48,    50,    -1,
      -1,    56,    -1,    -1,    55,    56,     3,     4,     5,     6,
       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
      17,    18,    19,    20,    21,    -1,    -1,    -1,    25,    24,
      -1,    -1,    27,    28,    29,    30,    31,    -1,    -1,    -1,
      37,    38,    -1,    -1,    -1,    40,    -1,    -1,    -1,    46,
      47,    48,    22,    23,    -1,    50,    -1,    -1,    55,    -1,
      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
      40,    41,    42,    43,    44,    45,    -1,    -1,    -1,    -1,
      50,    22,    23,    -1,    -1,    -1,    56,    -1,    -1,    30,
      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
      41,    42,    43,    44,    45,    -1,    -1,    -1,    -1,    50,
      22,    23,    -1,    -1,    -1,    56,    -1,    -1,    30,    31,
      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
      42,    43,    44,    45,    -1,    -1,    -1,    -1,    50,    22,
      23,    -1,    -1,    -1,    56,    -1,    -1,    30,    31,    32,
      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
      43,    44,    45,    -1,    -1,    -1,    -1,    50,    22,    23,
      -1,    -1,    -1,    56,    -1,    -1,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    -1,    -1,    -1,    50,    22,    23,    -1,
      -1,    -1,    56,    -1,    -1,    30,    31,    32,    33,    34,
      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
      45,    -1,    -1,    -1,    -1,    50,    22,    23,    -1,    -1,
      -1,    56,    -1,    -1,    30,    31,    32,    33,    34,    35,
      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
      -1,    -1,    -1,    -1,    50,    22,    23,    -1,    -1,    -1,
      56,    -1,    -1,    30,    31,    32,    33,    34,    35,    36,
      37,    38,    39,    40,    41,    42,    43,    44,    45,    -1,
      -1,    -1,    -1,    50,    22,    23,    -1,    -1,    -1,    56,
      -1,    -1,    30,    31,    32,    33,    34,    35,    36,    37,
      38,    39,    40,    41,    42,    43,    44,    45,    -1,    -1,
      -1,    -1,    50,    23,    -1,    -1,    -1,    -1,    56,    -1,
      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
      40,    41,    42,    43,    44,    45,    -1,    -1,    -1,    -1,
      50,    23,    -1,    -1,    -1,    -1,    56,    -1,    30,    31,
      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
      42,    43,    44,    45,    -1,    -1,    -1,    -1,    50,    23,
      -1,    -1,    -1,    -1,    56,    -1,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    -1,    -1,    -1,    50,    23,    -1,    -1,
      -1,    -1,    56,    -1,    30,    31,    32,    33,    34,    35,
      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
      -1,    -1,    -1,    -1,    50,    23,    -1,    -1,    -1,    -1,
      56,    -1,    30,    31,    32,    33,    34,    35,    36,    37,
      38,    39,    40,    41,    42,    43,    44,    45,    -1,    -1,
      -1,    -1,    50,    22,    23,    -1,    -1,    -1,    56,    -1,
      -1,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    22,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    22,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    22,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    22,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    22,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    22,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    22,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    22,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    22,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    22,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    22,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    -1,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    -1,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    -1,    23,    -1,    50,    -1,    -1,    -1,
      54,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    -1,    -1,    23,
      -1,    50,    -1,    -1,    -1,    54,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    -1,    -1,    -1,    50,    -1,    -1,    53,
      27,    28,    29,    30,    31,    27,    28,    29,    30,    31,
      -1,    -1,    -1,    40,    -1,    -1,    -1,    -1,    40,    -1,
      -1,    -1,    -1,    50,    -1,    -1,    -1,    -1,    50,    56,
      22,    23,    -1,    -1,    56,    -1,    -1,    -1,    30,    31,
      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
      42,    43,    44,    45,    22,    23,    -1,    -1,    50,    -1,
      -1,    -1,    30,    31,    32,    33,    34,    35,    36,    37,
      38,    39,    40,    41,    42,    43,    44,    45,    22,    23,
      -1,    -1,    50,    -1,    -1,    -1,    30,    31,    32,    33,
      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    22,    23,    -1,    -1,    50,    -1,    -1,    -1,
      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
      40,    41,    42,    43,    44,    45,    22,    23,    -1,    -1,
      50,    -1,    -1,    -1,    30,    31,    32,    33,    34,    35,
      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
      22,    23,    -1,    -1,    50,    -1,    -1,    -1,    30,    31,
      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
      42,    43,    44,    45,    22,    23,    -1,    -1,    50,    -1,
      -1,    -1,    30,    31,    32,    33,    34,    35,    36,    37,
      38,    39,    40,    41,    42,    43,    44,    45,    23,    -1,
      -1,    26,    50,    -1,    -1,    30,    31,    32,    33,    34,
      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
      45,    23,    -1,    -1,    26,    50,    -1,    -1,    30,    31,
      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
      42,    43,    44,    45,    23,    -1,    -1,    26,    50,    -1,
      -1,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    23,    -1,    -1,
      26,    50,    -1,    -1,    30,    31,    32,    33,    34,    35,
      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
      23,    24,    -1,    -1,    50,    -1,    -1,    30,    31,    32,
      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
      43,    44,    45,    23,    24,    -1,    -1,    50,    -1,    -1,
      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
      40,    41,    42,    43,    44,    45,    23,    -1,    -1,    -1,
      50,    -1,    -1,    30,    31,    32,    33,    34,    35,    36,
      37,    38,    39,    40,    41,    42,    43,    44,    45,    -1,
      -1,    30,    31,    50,    33,    34,    35,    36,    37,    -1,
      -1,    -1,    -1,    42,    43,    -1,    -1,    -1,    -1,    30,
      31,    50,    33,    34,    35,    36,    37,    56,    30,    31,
      -1,    33,    34,    35,    36,    37,    30,    31,    -1,    33,
      34,    35,    36,    37,    -1,    56,    -1,    -1,    42,    43,
      -1,    -1,    -1,    -1,    56,    -1,    50,    22,    -1,    53,
      27,    28,    29,    30,    31,    30,    31,    -1,    33,    34,
      35,    36,    37,    40,    30,    31,    -1,    33,    34,    35,
      36,    37,    -1,    50,    30,    31,    32,    33,    34,    35,
      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
      -1,    -1,    -1,    -1,    50,    33,    34,    35,    36,    37,
      38,    39,    40,    41,    42,    43,    44,    45,    -1,    -1,
      -1,    -1,    50,    37,    38,    39,    40,    41,    42,    43,
      44,    45,    -1,    -1,    -1,    -1,    50
};

/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
   state STATE-NUM.  */
static const yytype_int8 yystos[] =
{
       0,    58,     0,     1,     3,     4,     5,     6,     7,     8,
       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
      19,    20,    21,    25,    37,    38,    46,    47,    48,    53,
      55,    59,    60,    61,    62,    63,    64,    65,    53,    56,
      62,    63,    64,    65,    62,    63,    64,    65,    62,    63,
      65,     6,    56,     6,     6,    56,     6,    25,    25,    25,
      25,    62,    63,    65,    62,    62,    63,    64,    62,    63,
      62,    63,    62,    63,    64,    65,    22,    26,    22,    26,
      23,    30,    31,    32,    33,    34,    35,    36,    37,    38,
      39,    40,    41,    42,    43,    44,    45,    50,    53,    27,
      28,    29,    30,    31,    40,    50,    53,    30,    31,    33,
      34,    35,    36,    37,    42,    43,    50,    53,    30,    31,
      33,    34,    35,    36,    37,    53,    22,    56,    22,    56,
      56,    22,    56,    22,    56,    56,    56,    22,    22,    56,
      22,    22,    56,    22,    56,    62,    62,    62,    62,    56,
      56,    56,    56,    62,    63,    62,    63,    62,    62,    62,
      62,    62,    62,    62,    62,    62,    62,    62,    62,    63,
      62,    62,    62,    62,    62,    62,    62,    63,    65,    63,
      63,    63,    63,    62,    62,    46,    55,    64,    64,    64,
      64,    64,    64,    64,    64,    64,    62,    65,    65,    65,
      65,    65,    65,    65,    62,    62,    63,    62,    65,    62,
      65,    62,    62,    62,    62,    26,    26,    26,    26,    24,
      22,    54,    24,    24,    24,    22,    54,    64,    64,    22,
      54,    22,    56,    56,    56,    22,    56,    22,    56,    22,
      56,    22,    22,    56,    22,    62,    62,    62,    63,    62,
      63,    65,    62,    62,    62,    62,    62,     6,    62,     6,
      62,    22,    54,    22,    54,    22,    54,    22,    56,    22,
      56,    22,    22,    56,    22,    22,    56,    62,    62,    62,
      62,    62,     6,     6,     6,     6,    22,    54,    22,    54,
      22,    54,    56,    22,    56,    22,    56,    56,    62,    62,
      62,    62,     6,    22,    54,    22,    54,    22,    54,    22,
      56,    56,    62,    62,    62,    62,    54,    54,    54,    22,
      62,    56
};

/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM.  */
static const yytype_int8 yyr1[] =
{
       0,    57,    58,    58,    59,    59,    59,    59,    59,    59,
      60,    60,    61,    61,    61,    61,    62,    63,    64,    64,
      64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
      64,    62,    62,    62,    62,    62,    62,    62,    62,    62,
      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
      62,    62,    62,    62,    63,    63,    63,    63,    63,    63,
      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
      63,    63,    63,    63,    63,    63,    63,    65,    65,    65,
      65,    65,    65,    65,    65,    65
};

/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM.  */
static const yytype_int8 yyr2[] =
{
       0,     2,     0,     2,     1,     2,     2,     2,     2,     2,
       2,     3,     2,     3,     3,     3,     2,     2,     1,     1,
       4,     3,     3,     3,     4,     6,     8,    10,    12,     2,
       3,     1,     1,     1,     4,     1,     1,     3,     3,     3,
       3,     3,     3,     3,     3,     3,     2,     2,     3,     3,
       3,     5,     5,     5,     2,     3,     5,     3,     3,     3,
       5,     5,     9,     7,    11,     4,     6,     8,    10,    12,
       2,     2,     2,     2,     1,     1,     4,     3,     3,     3,
       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
       5,     5,     3,     3,     3,     5,     7,    11,    15,     2,
       3,     5,     9,     2,     3,     5,     9,     3,     7,     9,
       4,     6,     8,    10,    12,     2,     3,     1,     1,     4,
       1,     3,     3,     5,     5,     7
};


enum { YYENOMEM = -2 };

#define yyerrok         (yyerrstatus = 0)
#define yyclearin       (yychar = FITS_PARSER_YYEMPTY)

#define YYACCEPT        goto yyacceptlab
#define YYABORT         goto yyabortlab
#define YYERROR         goto yyerrorlab
#define YYNOMEM         goto yyexhaustedlab


#define YYRECOVERING()  (!!yyerrstatus)

#define YYBACKUP(Token, Value)                                    \
  do                                                              \
    if (yychar == FITS_PARSER_YYEMPTY)                                        \
      {                                                           \
        yychar = (Token);                                         \
        yylval = (Value);                                         \
        YYPOPSTACK (yylen);                                       \
        yystate = *yyssp;                                         \
        goto yybackup;                                            \
      }                                                           \
    else                                                          \
      {                                                           \
        yyerror (scanner, lParse, YY_("syntax error: cannot back up")); \
        YYERROR;                                                  \
      }                                                           \
  while (0)

/* Backward compatibility with an undocumented macro.
   Use FITS_PARSER_YYerror or FITS_PARSER_YYUNDEF. */
#define YYERRCODE FITS_PARSER_YYUNDEF


/* Enable debugging if requested.  */
#if FITS_PARSER_YYDEBUG

# ifndef YYFPRINTF
#  include  /* INFRINGES ON USER NAME SPACE */
#  define YYFPRINTF fprintf
# endif

# define YYDPRINTF(Args)                        \
do {                                            \
  if (yydebug)                                  \
    YYFPRINTF Args;                             \
} while (0)




# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)                    \
do {                                                                      \
  if (yydebug)                                                            \
    {                                                                     \
      YYFPRINTF (stderr, "%s ", Title);                                   \
      yy_symbol_print (stderr,                                            \
                  Kind, Value, scanner, lParse); \
      YYFPRINTF (stderr, "\n");                                           \
    }                                                                     \
} while (0)


/*-----------------------------------.
| Print this symbol's value on YYO.  |
`-----------------------------------*/

static void
yy_symbol_value_print (FILE *yyo,
                       yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t scanner, ParseData *lParse)
{
  FILE *yyoutput = yyo;
  YY_USE (yyoutput);
  YY_USE (scanner);
  YY_USE (lParse);
  if (!yyvaluep)
    return;
  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  YY_USE (yykind);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}


/*---------------------------.
| Print this symbol on YYO.  |
`---------------------------*/

static void
yy_symbol_print (FILE *yyo,
                 yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t scanner, ParseData *lParse)
{
  YYFPRINTF (yyo, "%s %s (",
             yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));

  yy_symbol_value_print (yyo, yykind, yyvaluep, scanner, lParse);
  YYFPRINTF (yyo, ")");
}

/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included).                                                   |
`------------------------------------------------------------------*/

static void
yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
{
  YYFPRINTF (stderr, "Stack now");
  for (; yybottom <= yytop; yybottom++)
    {
      int yybot = *yybottom;
      YYFPRINTF (stderr, " %d", yybot);
    }
  YYFPRINTF (stderr, "\n");
}

# define YY_STACK_PRINT(Bottom, Top)                            \
do {                                                            \
  if (yydebug)                                                  \
    yy_stack_print ((Bottom), (Top));                           \
} while (0)


/*------------------------------------------------.
| Report that the YYRULE is going to be reduced.  |
`------------------------------------------------*/

static void
yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
                 int yyrule, yyscan_t scanner, ParseData *lParse)
{
  int yylno = yyrline[yyrule];
  int yynrhs = yyr2[yyrule];
  int yyi;
  YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
             yyrule - 1, yylno);
  /* The symbols being reduced.  */
  for (yyi = 0; yyi < yynrhs; yyi++)
    {
      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
      yy_symbol_print (stderr,
                       YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
                       &yyvsp[(yyi + 1) - (yynrhs)], scanner, lParse);
      YYFPRINTF (stderr, "\n");
    }
}

# define YY_REDUCE_PRINT(Rule)          \
do {                                    \
  if (yydebug)                          \
    yy_reduce_print (yyssp, yyvsp, Rule, scanner, lParse); \
} while (0)

/* Nonzero means print parse trace.  It is left uninitialized so that
   multiple parsers can coexist.  */
int yydebug;
#else /* !FITS_PARSER_YYDEBUG */
# define YYDPRINTF(Args) ((void) 0)
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !FITS_PARSER_YYDEBUG */


/* YYINITDEPTH -- initial size of the parser's stacks.  */
#ifndef YYINITDEPTH
# define YYINITDEPTH 200
#endif

/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
   if the built-in stack extension method is used).

   Do not make this value too large; the results are undefined if
   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
   evaluated with infinite-precision integer arithmetic.  */

#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif






/*-----------------------------------------------.
| Release the memory associated to this symbol.  |
`-----------------------------------------------*/

static void
yydestruct (const char *yymsg,
            yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t scanner, ParseData *lParse)
{
  YY_USE (yyvaluep);
  YY_USE (scanner);
  YY_USE (lParse);
  if (!yymsg)
    yymsg = "Deleting";
  YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  YY_USE (yykind);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}






/*----------.
| yyparse.  |
`----------*/

int
yyparse (yyscan_t scanner, ParseData *lParse)
{
/* Lookahead token kind.  */
int yychar;


/* The semantic value of the lookahead symbol.  */
/* Default value used for initialization, for pacifying older GCCs
   or non-GCC compilers.  */
YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);

    /* Number of syntax errors so far.  */
    int yynerrs = 0;

    yy_state_fast_t yystate = 0;
    /* Number of tokens to shift before error messages enabled.  */
    int yyerrstatus = 0;

    /* Refer to the stacks through separate pointers, to allow yyoverflow
       to reallocate them elsewhere.  */

    /* Their size.  */
    YYPTRDIFF_T yystacksize = YYINITDEPTH;

    /* The state stack: array, bottom, top.  */
    yy_state_t yyssa[YYINITDEPTH];
    yy_state_t *yyss = yyssa;
    yy_state_t *yyssp = yyss;

    /* The semantic value stack: array, bottom, top.  */
    YYSTYPE yyvsa[YYINITDEPTH];
    YYSTYPE *yyvs = yyvsa;
    YYSTYPE *yyvsp = yyvs;

  int yyn;
  /* The return value of yyparse.  */
  int yyresult;
  /* Lookahead symbol kind.  */
  yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
  /* The variables used to return semantic value and location from the
     action routines.  */
  YYSTYPE yyval;



#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))

  /* The number of symbols on the RHS of the reduced rule.
     Keep to zero when no symbol should be popped.  */
  int yylen = 0;

  YYDPRINTF ((stderr, "Starting parse\n"));

  yychar = FITS_PARSER_YYEMPTY; /* Cause a token to be read.  */

  goto yysetstate;


/*------------------------------------------------------------.
| yynewstate -- push a new state, which is found in yystate.  |
`------------------------------------------------------------*/
yynewstate:
  /* In all cases, when you get here, the value and location stacks
     have just been pushed.  So pushing a state here evens the stacks.  */
  yyssp++;


/*--------------------------------------------------------------------.
| yysetstate -- set current state (the top of the stack) to yystate.  |
`--------------------------------------------------------------------*/
yysetstate:
  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
  YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
  YY_IGNORE_USELESS_CAST_BEGIN
  *yyssp = YY_CAST (yy_state_t, yystate);
  YY_IGNORE_USELESS_CAST_END
  YY_STACK_PRINT (yyss, yyssp);

  if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
    YYNOMEM;
#else
    {
      /* Get the current used size of the three stacks, in elements.  */
      YYPTRDIFF_T yysize = yyssp - yyss + 1;

# if defined yyoverflow
      {
        /* Give user a chance to reallocate the stack.  Use copies of
           these so that the &'s don't force the real ones into
           memory.  */
        yy_state_t *yyss1 = yyss;
        YYSTYPE *yyvs1 = yyvs;

        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
           conditional around just the two extra args, but that might
           be undefined if yyoverflow is a macro.  */
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * YYSIZEOF (*yyssp),
                    &yyvs1, yysize * YYSIZEOF (*yyvsp),
                    &yystacksize);
        yyss = yyss1;
        yyvs = yyvs1;
      }
# else /* defined YYSTACK_RELOCATE */
      /* Extend the stack our own way.  */
      if (YYMAXDEPTH <= yystacksize)
        YYNOMEM;
      yystacksize *= 2;
      if (YYMAXDEPTH < yystacksize)
        yystacksize = YYMAXDEPTH;

      {
        yy_state_t *yyss1 = yyss;
        union yyalloc *yyptr =
          YY_CAST (union yyalloc *,
                   YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
        if (! yyptr)
          YYNOMEM;
        YYSTACK_RELOCATE (yyss_alloc, yyss);
        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
#  undef YYSTACK_RELOCATE
        if (yyss1 != yyssa)
          YYSTACK_FREE (yyss1);
      }
# endif

      yyssp = yyss + yysize - 1;
      yyvsp = yyvs + yysize - 1;

      YY_IGNORE_USELESS_CAST_BEGIN
      YYDPRINTF ((stderr, "Stack size increased to %ld\n",
                  YY_CAST (long, yystacksize)));
      YY_IGNORE_USELESS_CAST_END

      if (yyss + yystacksize - 1 <= yyssp)
        YYABORT;
    }
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */


  if (yystate == YYFINAL)
    YYACCEPT;

  goto yybackup;


/*-----------.
| yybackup.  |
`-----------*/
yybackup:
  /* Do appropriate processing given the current state.  Read a
     lookahead token if we need one and don't already have one.  */

  /* First try to decide what to do without reference to lookahead token.  */
  yyn = yypact[yystate];
  if (yypact_value_is_default (yyn))
    goto yydefault;

  /* Not known => get a lookahead token if don't already have one.  */

  /* YYCHAR is either empty, or end-of-input, or a valid lookahead.  */
  if (yychar == FITS_PARSER_YYEMPTY)
    {
      YYDPRINTF ((stderr, "Reading a token\n"));
      yychar = yylex (&yylval, scanner);
    }

  if (yychar <= FITS_PARSER_YYEOF)
    {
      yychar = FITS_PARSER_YYEOF;
      yytoken = YYSYMBOL_YYEOF;
      YYDPRINTF ((stderr, "Now at end of input.\n"));
    }
  else if (yychar == FITS_PARSER_YYerror)
    {
      /* The scanner already issued an error message, process directly
         to error recovery.  But do not keep the error token as
         lookahead, it is too special and may lead us to an endless
         loop in error recovery. */
      yychar = FITS_PARSER_YYUNDEF;
      yytoken = YYSYMBOL_YYerror;
      goto yyerrlab1;
    }
  else
    {
      yytoken = YYTRANSLATE (yychar);
      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
    }

  /* If the proper action on seeing token YYTOKEN is to reduce or to
     detect an error, take that action.  */
  yyn += yytoken;
  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
    goto yydefault;
  yyn = yytable[yyn];
  if (yyn <= 0)
    {
      if (yytable_value_is_error (yyn))
        goto yyerrlab;
      yyn = -yyn;
      goto yyreduce;
    }

  /* Count tokens shifted since error; after three, turn off error
     status.  */
  if (yyerrstatus)
    yyerrstatus--;

  /* Shift the lookahead token.  */
  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
  yystate = yyn;
  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  *++yyvsp = yylval;
  YY_IGNORE_MAYBE_UNINITIALIZED_END

  /* Discard the shifted token.  */
  yychar = FITS_PARSER_YYEMPTY;
  goto yynewstate;


/*-----------------------------------------------------------.
| yydefault -- do the default action for the current state.  |
`-----------------------------------------------------------*/
yydefault:
  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;
  goto yyreduce;


/*-----------------------------.
| yyreduce -- do a reduction.  |
`-----------------------------*/
yyreduce:
  /* yyn is the number of a rule to reduce with.  */
  yylen = yyr2[yyn];

  /* If YYLEN is nonzero, implement the default value of the action:
     '$$ = $1'.

     Otherwise, the following line sets YYVAL to garbage.
     This behavior is undocumented and Bison
     users should not rely upon it.  Assigning to YYVAL
     unconditionally makes the parser a bit smaller, and it avoids a
     GCC warning that YYVAL may be used uninitialized.  */
  yyval = yyvsp[1-yylen];


  YY_REDUCE_PRINT (yyn);
  switch (yyn)
    {
  case 4: /* line: '\n'  */
#line 270 "eval.y"
                     {}
#line 1821 "eval_y.c"
    break;

  case 5: /* line: expr '\n'  */
#line 272 "eval.y"
                { if( (yyvsp[-1].Node)<0 ) {
		     yyerror(scanner, lParse, "Couldn't build node structure: out of memory?");
		     YYERROR;  }
                  lParse->resultNode = (yyvsp[-1].Node);
		}
#line 1831 "eval_y.c"
    break;

  case 6: /* line: bexpr '\n'  */
#line 278 "eval.y"
                { if( (yyvsp[-1].Node)<0 ) {
		     yyerror(scanner, lParse, "Couldn't build node structure: out of memory?");
		     YYERROR;  }
                  lParse->resultNode = (yyvsp[-1].Node);
		}
#line 1841 "eval_y.c"
    break;

  case 7: /* line: sexpr '\n'  */
#line 284 "eval.y"
                { if( (yyvsp[-1].Node)<0 ) {
		     yyerror(scanner, lParse, "Couldn't build node structure: out of memory?");
		     YYERROR;  } 
                  lParse->resultNode = (yyvsp[-1].Node);
		}
#line 1851 "eval_y.c"
    break;

  case 8: /* line: bits '\n'  */
#line 290 "eval.y"
                { if( (yyvsp[-1].Node)<0 ) {
		     yyerror(scanner, lParse, "Couldn't build node structure: out of memory?");
		     YYERROR;  }
                  lParse->resultNode = (yyvsp[-1].Node);
		}
#line 1861 "eval_y.c"
    break;

  case 9: /* line: error '\n'  */
#line 295 "eval.y"
                     {  yyerrok;  }
#line 1867 "eval_y.c"
    break;

  case 10: /* bvector: '{' bexpr  */
#line 299 "eval.y"
                { (yyval.Node) = New_Vector(lParse,  (yyvsp[0].Node) ); TEST((yyval.Node)); }
#line 1873 "eval_y.c"
    break;

  case 11: /* bvector: bvector ',' bexpr  */
#line 301 "eval.y"
                {
                  if( lParse->Nodes[(yyvsp[-2].Node)].nSubNodes >= MAXSUBS ) {
		     (yyvsp[-2].Node) = Close_Vec(lParse,  (yyvsp[-2].Node) ); TEST((yyvsp[-2].Node));
		     (yyval.Node) = New_Vector(lParse,  (yyvsp[-2].Node) ); TEST((yyval.Node));
                  } else {
                     (yyval.Node) = (yyvsp[-2].Node);
                  }
		  lParse->Nodes[(yyval.Node)].SubNodes[ lParse->Nodes[(yyval.Node)].nSubNodes++ ]
		     = (yyvsp[0].Node);
                }
#line 1888 "eval_y.c"
    break;

  case 12: /* vector: '{' expr  */
#line 314 "eval.y"
                { (yyval.Node) = New_Vector(lParse,  (yyvsp[0].Node) ); TEST((yyval.Node)); }
#line 1894 "eval_y.c"
    break;

  case 13: /* vector: vector ',' expr  */
#line 316 "eval.y"
                {
                  if( TYPE((yyvsp[-2].Node)) < TYPE((yyvsp[0].Node)) )
                     TYPE((yyvsp[-2].Node)) = TYPE((yyvsp[0].Node));
                  if( lParse->Nodes[(yyvsp[-2].Node)].nSubNodes >= MAXSUBS ) {
		     (yyvsp[-2].Node) = Close_Vec(lParse,  (yyvsp[-2].Node) ); TEST((yyvsp[-2].Node));
		     (yyval.Node) = New_Vector(lParse,  (yyvsp[-2].Node) ); TEST((yyval.Node));
                  } else {
                     (yyval.Node) = (yyvsp[-2].Node);
                  }
		  lParse->Nodes[(yyval.Node)].SubNodes[ lParse->Nodes[(yyval.Node)].nSubNodes++ ]
		     = (yyvsp[0].Node);
                }
#line 1911 "eval_y.c"
    break;

  case 14: /* vector: vector ',' bexpr  */
#line 329 "eval.y"
                {
                  if( lParse->Nodes[(yyvsp[-2].Node)].nSubNodes >= MAXSUBS ) {
		     (yyvsp[-2].Node) = Close_Vec(lParse,  (yyvsp[-2].Node) ); TEST((yyvsp[-2].Node));
		     (yyval.Node) = New_Vector(lParse,  (yyvsp[-2].Node) ); TEST((yyval.Node));
                  } else {
                     (yyval.Node) = (yyvsp[-2].Node);
                  }
		  lParse->Nodes[(yyval.Node)].SubNodes[ lParse->Nodes[(yyval.Node)].nSubNodes++ ]
		     = (yyvsp[0].Node);
                }
#line 1926 "eval_y.c"
    break;

  case 15: /* vector: bvector ',' expr  */
#line 340 "eval.y"
                {
                  TYPE((yyvsp[-2].Node)) = TYPE((yyvsp[0].Node));
                  if( lParse->Nodes[(yyvsp[-2].Node)].nSubNodes >= MAXSUBS ) {
		     (yyvsp[-2].Node) = Close_Vec(lParse,  (yyvsp[-2].Node) ); TEST((yyvsp[-2].Node));
		     (yyval.Node) = New_Vector(lParse,  (yyvsp[-2].Node) ); TEST((yyval.Node));
                  } else {
                     (yyval.Node) = (yyvsp[-2].Node);
                  }
		  lParse->Nodes[(yyval.Node)].SubNodes[ lParse->Nodes[(yyval.Node)].nSubNodes++ ]
		     = (yyvsp[0].Node);
                }
#line 1942 "eval_y.c"
    break;

  case 16: /* expr: vector '}'  */
#line 354 "eval.y"
                { (yyval.Node) = Close_Vec(lParse,  (yyvsp[-1].Node) ); TEST((yyval.Node)); }
#line 1948 "eval_y.c"
    break;

  case 17: /* bexpr: bvector '}'  */
#line 358 "eval.y"
                { (yyval.Node) = Close_Vec(lParse,  (yyvsp[-1].Node) ); TEST((yyval.Node)); }
#line 1954 "eval_y.c"
    break;

  case 18: /* bits: BITSTR  */
#line 362 "eval.y"
                {
                  (yyval.Node) = New_Const(lParse,  BITSTR, (yyvsp[0].str), strlen((yyvsp[0].str))+1 ); TEST((yyval.Node));
		  SIZE((yyval.Node)) = strlen((yyvsp[0].str)); }
#line 1962 "eval_y.c"
    break;

  case 19: /* bits: BITCOL  */
#line 366 "eval.y"
                { (yyval.Node) = New_Column(lParse,  (yyvsp[0].lng) ); TEST((yyval.Node)); }
#line 1968 "eval_y.c"
    break;

  case 20: /* bits: BITCOL '{' expr '}'  */
#line 368 "eval.y"
                {
                  if( TYPE((yyvsp[-1].Node)) != LONG
		      || OPER((yyvsp[-1].Node)) != CONST_OP ) {
		     yyerror(scanner, lParse, "Offset argument must be a constant integer");
		     YYERROR;
		  }
                  (yyval.Node) = New_Offset(lParse,  (yyvsp[-3].lng), (yyvsp[-1].Node) ); TEST((yyval.Node));
                }
#line 1981 "eval_y.c"
    break;

  case 21: /* bits: bits '&' bits  */
#line 377 "eval.y"
                { (yyval.Node) = New_BinOp(lParse,  BITSTR, (yyvsp[-2].Node), '&', (yyvsp[0].Node) ); TEST((yyval.Node));
                  SIZE((yyval.Node)) = ( SIZE((yyvsp[-2].Node))>SIZE((yyvsp[0].Node)) ? SIZE((yyvsp[-2].Node)) : SIZE((yyvsp[0].Node)) );  }
#line 1988 "eval_y.c"
    break;

  case 22: /* bits: bits '|' bits  */
#line 380 "eval.y"
                { (yyval.Node) = New_BinOp(lParse,  BITSTR, (yyvsp[-2].Node), '|', (yyvsp[0].Node) ); TEST((yyval.Node));
                  SIZE((yyval.Node)) = ( SIZE((yyvsp[-2].Node))>SIZE((yyvsp[0].Node)) ? SIZE((yyvsp[-2].Node)) : SIZE((yyvsp[0].Node)) );  }
#line 1995 "eval_y.c"
    break;

  case 23: /* bits: bits '+' bits  */
#line 383 "eval.y"
                { 
		  if (SIZE((yyvsp[-2].Node))+SIZE((yyvsp[0].Node)) >= MAX_STRLEN) {
		    yyerror(scanner, lParse, "Combined bit string size exceeds " MAX_STRLEN_S " bits");
		    YYERROR;
		  }
		  (yyval.Node) = New_BinOp(lParse,  BITSTR, (yyvsp[-2].Node), '+', (yyvsp[0].Node) ); TEST((yyval.Node));
                  SIZE((yyval.Node)) = SIZE((yyvsp[-2].Node)) + SIZE((yyvsp[0].Node)); 
		}
#line 2008 "eval_y.c"
    break;

  case 24: /* bits: bits '[' expr ']'  */
#line 392 "eval.y"
                { (yyval.Node) = New_Deref(lParse,  (yyvsp[-3].Node), 1, (yyvsp[-1].Node),  0,  0,  0,   0 ); TEST((yyval.Node)); }
#line 2014 "eval_y.c"
    break;

  case 25: /* bits: bits '[' expr ',' expr ']'  */
#line 394 "eval.y"
                { (yyval.Node) = New_Deref(lParse,  (yyvsp[-5].Node), 2, (yyvsp[-3].Node), (yyvsp[-1].Node),  0,  0,   0 ); TEST((yyval.Node)); }
#line 2020 "eval_y.c"
    break;

  case 26: /* bits: bits '[' expr ',' expr ',' expr ']'  */
#line 396 "eval.y"
                { (yyval.Node) = New_Deref(lParse,  (yyvsp[-7].Node), 3, (yyvsp[-5].Node), (yyvsp[-3].Node), (yyvsp[-1].Node),  0,   0 ); TEST((yyval.Node)); }
#line 2026 "eval_y.c"
    break;

  case 27: /* bits: bits '[' expr ',' expr ',' expr ',' expr ']'  */
#line 398 "eval.y"
                { (yyval.Node) = New_Deref(lParse,  (yyvsp[-9].Node), 4, (yyvsp[-7].Node), (yyvsp[-5].Node), (yyvsp[-3].Node), (yyvsp[-1].Node),   0 ); TEST((yyval.Node)); }
#line 2032 "eval_y.c"
    break;

  case 28: /* bits: bits '[' expr ',' expr ',' expr ',' expr ',' expr ']'  */
#line 400 "eval.y"
                { (yyval.Node) = New_Deref(lParse,  (yyvsp[-11].Node), 5, (yyvsp[-9].Node), (yyvsp[-7].Node), (yyvsp[-5].Node), (yyvsp[-3].Node), (yyvsp[-1].Node) ); TEST((yyval.Node)); }
#line 2038 "eval_y.c"
    break;

  case 29: /* bits: NOT bits  */
#line 402 "eval.y"
                { (yyval.Node) = New_Unary(lParse,  BITSTR, NOT, (yyvsp[0].Node) ); TEST((yyval.Node));     }
#line 2044 "eval_y.c"
    break;

  case 30: /* bits: '(' bits ')'  */
#line 405 "eval.y"
                { (yyval.Node) = (yyvsp[-1].Node); }
#line 2050 "eval_y.c"
    break;

  case 31: /* expr: LONG  */
#line 409 "eval.y"
                { (yyval.Node) = New_Const(lParse,  LONG,   &((yyvsp[0].lng)), sizeof(long)   ); TEST((yyval.Node)); }
#line 2056 "eval_y.c"
    break;

  case 32: /* expr: DOUBLE  */
#line 411 "eval.y"
                { (yyval.Node) = New_Const(lParse,  DOUBLE, &((yyvsp[0].dbl)), sizeof(double) ); TEST((yyval.Node)); }
#line 2062 "eval_y.c"
    break;

  case 33: /* expr: COLUMN  */
#line 413 "eval.y"
                { (yyval.Node) = New_Column(lParse,  (yyvsp[0].lng) ); TEST((yyval.Node)); }
#line 2068 "eval_y.c"
    break;

  case 34: /* expr: COLUMN '{' expr '}'  */
#line 415 "eval.y"
                {
                  if( TYPE((yyvsp[-1].Node)) != LONG
		      || OPER((yyvsp[-1].Node)) != CONST_OP ) {
		     yyerror(scanner, lParse, "Offset argument must be a constant integer");
		     YYERROR;
		  }
                  (yyval.Node) = New_Offset(lParse,  (yyvsp[-3].lng), (yyvsp[-1].Node) ); TEST((yyval.Node));
                }
#line 2081 "eval_y.c"
    break;

  case 35: /* expr: ROWREF  */
#line 424 "eval.y"
                { (yyval.Node) = New_Func(lParse,  LONG, row_fct,  0, 0, 0, 0, 0, 0, 0, 0 ); }
#line 2087 "eval_y.c"
    break;

  case 36: /* expr: NULLREF  */
#line 426 "eval.y"
                { (yyval.Node) = New_Func(lParse,  LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
#line 2093 "eval_y.c"
    break;

  case 37: /* expr: expr '%' expr  */
#line 428 "eval.y"
                { PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node)); (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '%', (yyvsp[0].Node) );
		  TEST((yyval.Node));                                                }
#line 2100 "eval_y.c"
    break;

  case 38: /* expr: expr '+' expr  */
#line 431 "eval.y"
                { PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node)); (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '+', (yyvsp[0].Node) );
		  TEST((yyval.Node));                                                }
#line 2107 "eval_y.c"
    break;

  case 39: /* expr: expr '-' expr  */
#line 434 "eval.y"
                { PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node)); (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '-', (yyvsp[0].Node) ); 
		  TEST((yyval.Node));                                                }
#line 2114 "eval_y.c"
    break;

  case 40: /* expr: expr '*' expr  */
#line 437 "eval.y"
                { PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node)); (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '*', (yyvsp[0].Node) ); 
		  TEST((yyval.Node));                                                }
#line 2121 "eval_y.c"
    break;

  case 41: /* expr: expr '/' expr  */
#line 440 "eval.y"
                { PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node)); (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '/', (yyvsp[0].Node) ); 
		  TEST((yyval.Node));                                                }
#line 2128 "eval_y.c"
    break;

  case 42: /* expr: expr '&' expr  */
#line 443 "eval.y"
                { 
                   if (TYPE((yyvsp[-2].Node)) != LONG ||
		       TYPE((yyvsp[0].Node)) != LONG) {
                     yyerror(scanner, lParse, "Bitwise operations with incompatible types; only (bit OP bit) and (int OP int) are allowed");
                      YYERROR;
                   }
                   (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '&', (yyvsp[0].Node) );
                }
#line 2141 "eval_y.c"
    break;

  case 43: /* expr: expr '|' expr  */
#line 452 "eval.y"
                { 
                   if (TYPE((yyvsp[-2].Node)) != LONG ||
		       TYPE((yyvsp[0].Node)) != LONG) {
                     yyerror(scanner, lParse, "Bitwise operations with incompatible types; only (bit OP bit) and (int OP int) are allowed");
                      YYERROR;
                   }
                   (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '|', (yyvsp[0].Node) );
                }
#line 2154 "eval_y.c"
    break;

  case 44: /* expr: expr XOR expr  */
#line 461 "eval.y"
                { 
                   if (TYPE((yyvsp[-2].Node)) != LONG ||
		       TYPE((yyvsp[0].Node)) != LONG) {
                     yyerror(scanner, lParse, "Bitwise operations with incompatible types; only (bit OP bit) and (int OP int) are allowed");
                      YYERROR;
                   }
                   (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '^', (yyvsp[0].Node) );
                }
#line 2167 "eval_y.c"
    break;

  case 45: /* expr: expr POWER expr  */
#line 470 "eval.y"
                { PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node)); (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), POWER, (yyvsp[0].Node) );
		  TEST((yyval.Node));                                                }
#line 2174 "eval_y.c"
    break;

  case 46: /* expr: '+' expr  */
#line 473 "eval.y"
                { (yyval.Node) = (yyvsp[0].Node); }
#line 2180 "eval_y.c"
    break;

  case 47: /* expr: '-' expr  */
#line 475 "eval.y"
                { (yyval.Node) = New_Unary(lParse,  TYPE((yyvsp[0].Node)), UMINUS, (yyvsp[0].Node) ); TEST((yyval.Node)); }
#line 2186 "eval_y.c"
    break;

  case 48: /* expr: '(' expr ')'  */
#line 477 "eval.y"
                { (yyval.Node) = (yyvsp[-1].Node); }
#line 2192 "eval_y.c"
    break;

  case 49: /* expr: expr '*' bexpr  */
#line 479 "eval.y"
                { (yyvsp[0].Node) = New_Unary(lParse,  TYPE((yyvsp[-2].Node)), 0, (yyvsp[0].Node) );
                  (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[-2].Node)), (yyvsp[-2].Node), '*', (yyvsp[0].Node) ); 
		  TEST((yyval.Node));                                }
#line 2200 "eval_y.c"
    break;

  case 50: /* expr: bexpr '*' expr  */
#line 483 "eval.y"
                { (yyvsp[-2].Node) = New_Unary(lParse,  TYPE((yyvsp[0].Node)), 0, (yyvsp[-2].Node) );
                  (yyval.Node) = New_BinOp(lParse,  TYPE((yyvsp[0].Node)), (yyvsp[-2].Node), '*', (yyvsp[0].Node) );
                  TEST((yyval.Node));                                }
#line 2208 "eval_y.c"
    break;

  case 51: /* expr: bexpr '?' expr ':' expr  */
#line 487 "eval.y"
                {
                  PROMOTE((yyvsp[-2].Node),(yyvsp[0].Node));
                  if( ! Test_Dims( lParse, (yyvsp[-2].Node),(yyvsp[0].Node)) ) {
                     yyerror(scanner, lParse, "Incompatible dimensions in '?:' arguments");
		     YYERROR;
                  }
                  (yyval.Node) = New_Func(lParse,  0, ifthenelse_fct, 3, (yyvsp[-2].Node), (yyvsp[0].Node), (yyvsp[-4].Node),
                                 0, 0, 0, 0 );
                  TEST((yyval.Node));
                  if( SIZE((yyvsp[-2].Node))Nodes[(yyvsp[-1].Node)].value.data.lng);
		       naxis = lParse->Nodes[(yyvsp[-3].Node)].value.naxis;

		       if (iaxis == 0)          iaxis = naxis;   /* NAXIS(V,0) = NAXIS */
		       else if (iaxis <= naxis) iaxis = lParse->Nodes[(yyvsp[-3].Node)].value.naxes[iaxis-1]; /* NAXIS(V,n) = NAXISn */
		       else                     iaxis = 1;       /* Out of bounds use 1 */

		       (yyval.Node) = New_Const(lParse,  LONG, &iaxis, sizeof(iaxis) );
		       TEST((yyval.Node));
		     }
		   } else if (FSTRCMP((yyvsp[-4].str),"ARRAY(") == 0) {  /* NAXES(bexpr,n) */
		     (yyval.Node) = New_Array(lParse, (yyvsp[-3].Node), (yyvsp[-1].Node));
		     TEST((yyval.Node));
		  } else {
                     yyerror(scanner, lParse, "Function(bool,expr) not supported");
		     YYERROR;
		  }
                  TEST((yyval.Node)); 
		}
#line 2363 "eval_y.c"
    break;

  case 57: /* expr: FUNCTION sexpr ')'  */
#line 618 "eval.y"
                { if (FSTRCMP((yyvsp[-2].str),"NELEM(") == 0) {
                     (yyval.Node) = New_Const(lParse,  LONG, &( SIZE((yyvsp[-1].Node)) ), sizeof(long) );
		  } else if (FSTRCMP((yyvsp[-2].str),"NVALID(") == 0) {
		     (yyval.Node) = New_Func(lParse,  LONG, nonnull_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		  } else {
                     yyerror(scanner, lParse, "Function(str) not supported");
		     YYERROR;
		  }
                  TEST((yyval.Node)); 
		}
#line 2379 "eval_y.c"
    break;

  case 58: /* expr: FUNCTION bits ')'  */
#line 630 "eval.y"
                { if (FSTRCMP((yyvsp[-2].str),"NELEM(") == 0) {
                     (yyval.Node) = New_Const(lParse,  LONG, &( SIZE((yyvsp[-1].Node)) ), sizeof(long) );
		} else if (FSTRCMP((yyvsp[-2].str),"NVALID(") == 0) { /* Bit arrays do not have NULL */
                     (yyval.Node) = New_Const(lParse,  LONG, &( SIZE((yyvsp[-1].Node)) ), sizeof(long) );
		} else if (FSTRCMP((yyvsp[-2].str),"SUM(") == 0) {
		     (yyval.Node) = New_Func(lParse,  LONG, sum_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		} else if (FSTRCMP((yyvsp[-2].str),"MIN(") == 0) {
		     (yyval.Node) = New_Func(lParse,  TYPE((yyvsp[-1].Node)),  /* Force 1D result */
				    min1_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     /* Note: $2 is a vector so the result can never
		        be a constant.  Therefore it will never be set
		        inside New_Func(), and it is safe to set SIZE() */
		     SIZE((yyval.Node)) = 1;
		} else if (FSTRCMP((yyvsp[-2].str),"ACCUM(") == 0) {
		    long zero = 0;
		    (yyval.Node) = New_BinOp(lParse,  LONG , (yyvsp[-1].Node), ACCUM, New_Const(lParse,  LONG, &zero, sizeof(zero) ));
		} else if (FSTRCMP((yyvsp[-2].str),"MAX(") == 0) {
		     (yyval.Node) = New_Func(lParse,  TYPE((yyvsp[-1].Node)),  /* Force 1D result */
				    max1_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     /* Note: $2 is a vector so the result can never
		        be a constant.  Therefore it will never be set
		        inside New_Func(), and it is safe to set SIZE() */
		     SIZE((yyval.Node)) = 1;
		} else {
                     yyerror(scanner, lParse, "Function(bits) not supported");
		     YYERROR;
		  }
                  TEST((yyval.Node)); 
		}
#line 2414 "eval_y.c"
    break;

  case 59: /* expr: FUNCTION expr ')'  */
#line 661 "eval.y"
                { if (FSTRCMP((yyvsp[-2].str),"SUM(") == 0)
		     (yyval.Node) = New_Func(lParse,  TYPE((yyvsp[-1].Node)), sum_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		  else if (FSTRCMP((yyvsp[-2].str),"AVERAGE(") == 0)
		     (yyval.Node) = New_Func(lParse,  DOUBLE, average_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		  else if (FSTRCMP((yyvsp[-2].str),"STDDEV(") == 0)
		     (yyval.Node) = New_Func(lParse,  DOUBLE, stddev_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		  else if (FSTRCMP((yyvsp[-2].str),"MEDIAN(") == 0)
		     (yyval.Node) = New_Func(lParse,  TYPE((yyvsp[-1].Node)), median_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		  else if (FSTRCMP((yyvsp[-2].str),"NELEM(") == 0)
                     (yyval.Node) = New_Const(lParse,  LONG, &( SIZE((yyvsp[-1].Node)) ), sizeof(long) );
		  else if (FSTRCMP((yyvsp[-2].str),"NVALID(") == 0)
		     (yyval.Node) = New_Func(lParse,  LONG, nonnull_fct, 1, (yyvsp[-1].Node),
				    0, 0, 0, 0, 0, 0 );
		  else if   ((FSTRCMP((yyvsp[-2].str),"ACCUM(") == 0) && (TYPE((yyvsp[-1].Node)) == LONG)) {
		    long zero = 0;
		    (yyval.Node) = New_BinOp(lParse,  LONG ,   (yyvsp[-1].Node), ACCUM, New_Const(lParse,  LONG,   &zero, sizeof(zero) ));
		  } else if ((FSTRCMP((yyvsp[-2].str),"ACCUM(") == 0) && (TYPE((yyvsp[-1].Node)) == DOUBLE)) {
		    double zero = 0;
		    (yyval.Node) = New_BinOp(lParse,  DOUBLE , (yyvsp[-1].Node), ACCUM, New_Const(lParse,  DOUBLE, &zero, sizeof(zero) ));
		  } else if ((FSTRCMP((yyvsp[-2].str),"SEQDIFF(") == 0) && (TYPE((yyvsp[-1].Node)) == LONG)) {
		    long zero = 0;
		    (yyval.Node) = New_BinOp(lParse,  LONG ,   (yyvsp[-1].Node), DIFF, New_Const(lParse,  LONG,   &zero, sizeof(zero) ));
		  } else if ((FSTRCMP((yyvsp[-2].str),"SEQDIFF(") == 0) && (TYPE((yyvsp[-1].Node)) == DOUBLE)) {
		    double zero = 0;
		    (yyval.Node) = New_BinOp(lParse,  DOUBLE , (yyvsp[-1].Node), DIFF, New_Const(lParse,  DOUBLE, &zero, sizeof(zero) ));
		  } else if (FSTRCMP((yyvsp[-2].str),"ABS(") == 0)
		     (yyval.Node) = New_Func(lParse,  0, abs_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
 		  else if (FSTRCMP((yyvsp[-2].str),"MIN(") == 0)
		     (yyval.Node) = New_Func(lParse,  TYPE((yyvsp[-1].Node)),  /* Force 1D result */
				    min1_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		  else if (FSTRCMP((yyvsp[-2].str),"MAX(") == 0)
		     (yyval.Node) = New_Func(lParse,  TYPE((yyvsp[-1].Node)),  /* Force 1D result */
				    max1_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		  else if (FSTRCMP((yyvsp[-2].str),"RANDOM(") == 0) { /* Vector RANDOM() */
                     (yyval.Node) = New_Func(lParse,  0, rnd_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     TEST((yyval.Node));
		     TYPE((yyval.Node)) = DOUBLE;
		  } else if (FSTRCMP((yyvsp[-2].str),"RANDOMN(") == 0) {
		     (yyval.Node) = New_Func(lParse,  0, gasrnd_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     TEST((yyval.Node));
		     TYPE((yyval.Node)) = DOUBLE;
		  } else if (FSTRCMP((yyvsp[-2].str),"ELEMENTNUM(") == 0) {
		     if (OPER((yyvsp[-1].Node)) == CONST_OP) {
		       long one = 1;
		       (yyval.Node) = New_Const(lParse,  LONG, &one, sizeof(one) );
		     } else {
		       (yyval.Node) = New_Func(lParse,  0, elemnum_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		       TEST((yyval.Node));
		       TYPE((yyval.Node)) = LONG;
		     }
		  } else if (FSTRCMP((yyvsp[-2].str),"NAXIS(") == 0) {  /* NAXIS(V) */
		     if (OPER((yyvsp[-1].Node)) == CONST_OP) { /* if V is constant, return 1 in every case */
		       long one = 1;
		       (yyval.Node) = New_Const(lParse,  LONG, &one, sizeof(one) );
		     } else {                    /* determine now the dimension of the expression */
		       long naxis = lParse->Nodes[(yyvsp[-1].Node)].value.naxis;

		       (yyval.Node) = New_Const(lParse,  LONG, &naxis, sizeof(naxis) );
		       TEST((yyval.Node));
		     }
                  } 
  		  else {  /*  These all take DOUBLE arguments  */
		     if( TYPE((yyvsp[-1].Node)) != DOUBLE ) (yyvsp[-1].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-1].Node) );
                     if (FSTRCMP((yyvsp[-2].str),"SIN(") == 0)
			(yyval.Node) = New_Func(lParse,  0, sin_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"COS(") == 0)
			(yyval.Node) = New_Func(lParse,  0, cos_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"TAN(") == 0)
			(yyval.Node) = New_Func(lParse,  0, tan_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"ARCSIN(") == 0
			      || FSTRCMP((yyvsp[-2].str),"ASIN(") == 0)
			(yyval.Node) = New_Func(lParse,  0, asin_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"ARCCOS(") == 0
			      || FSTRCMP((yyvsp[-2].str),"ACOS(") == 0)
			(yyval.Node) = New_Func(lParse,  0, acos_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"ARCTAN(") == 0
			      || FSTRCMP((yyvsp[-2].str),"ATAN(") == 0)
			(yyval.Node) = New_Func(lParse,  0, atan_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"SINH(") == 0)
			(yyval.Node) = New_Func(lParse,  0, sinh_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"COSH(") == 0)
			(yyval.Node) = New_Func(lParse,  0, cosh_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"TANH(") == 0)
			(yyval.Node) = New_Func(lParse,  0, tanh_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"EXP(") == 0)
			(yyval.Node) = New_Func(lParse,  0, exp_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"LOG(") == 0)
			(yyval.Node) = New_Func(lParse,  0, log_fct,  1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"LOG10(") == 0)
			(yyval.Node) = New_Func(lParse,  0, log10_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"SQRT(") == 0)
			(yyval.Node) = New_Func(lParse,  0, sqrt_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"ROUND(") == 0)
			(yyval.Node) = New_Func(lParse,  0, round_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"FLOOR(") == 0)
			(yyval.Node) = New_Func(lParse,  0, floor_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"CEIL(") == 0)
			(yyval.Node) = New_Func(lParse,  0, ceil_fct, 1, (yyvsp[-1].Node), 0, 0, 0, 0, 0, 0 );
		     else if (FSTRCMP((yyvsp[-2].str),"RANDOMP(") == 0) {
		       (yyval.Node) = New_Func(lParse,  0, poirnd_fct, 1, (yyvsp[-1].Node), 
				      0, 0, 0, 0, 0, 0 );
		       TYPE((yyval.Node)) = LONG;
		     } else {
			yyerror(scanner, lParse, "Function(expr) not supported");
			YYERROR;
		     }
		  }
                  TEST((yyval.Node)); 
                }
#line 2532 "eval_y.c"
    break;

  case 60: /* expr: IFUNCTION sexpr ',' sexpr ')'  */
#line 775 "eval.y"
                { 
		  if (FSTRCMP((yyvsp[-4].str),"STRSTR(") == 0) {
		    (yyval.Node) = New_Func(lParse,  LONG, strpos_fct, 2, (yyvsp[-3].Node), (yyvsp[-1].Node), 0, 
				   0, 0, 0, 0 );
		    TEST((yyval.Node));
		  }
                }
#line 2544 "eval_y.c"
    break;

  case 61: /* expr: FUNCTION expr ',' expr ')'  */
#line 783 "eval.y"
                { 
		   if (FSTRCMP((yyvsp[-4].str),"DEFNULL(") == 0) {
		      if( SIZE((yyvsp[-3].Node))>=SIZE((yyvsp[-1].Node)) && Test_Dims( lParse,  (yyvsp[-3].Node), (yyvsp[-1].Node) ) ) {
			 PROMOTE((yyvsp[-3].Node),(yyvsp[-1].Node));
			 (yyval.Node) = New_Func(lParse,  0, defnull_fct, 2, (yyvsp[-3].Node), (yyvsp[-1].Node), 0,
					0, 0, 0, 0 );
			 TEST((yyval.Node)); 
		      } else {
			 yyerror(scanner, lParse, "Dimensions of DEFNULL arguments "
				 "are not compatible");
			 YYERROR;
		      }
		   } else if (FSTRCMP((yyvsp[-4].str),"ARCTAN2(") == 0) {
		     if( TYPE((yyvsp[-3].Node)) != DOUBLE ) (yyvsp[-3].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-3].Node) );
		     if( TYPE((yyvsp[-1].Node)) != DOUBLE ) (yyvsp[-1].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-1].Node) );
		     if( Test_Dims( lParse,  (yyvsp[-3].Node), (yyvsp[-1].Node) ) ) {
			(yyval.Node) = New_Func(lParse,  0, atan2_fct, 2, (yyvsp[-3].Node), (yyvsp[-1].Node), 0, 0, 0, 0, 0 );
			TEST((yyval.Node)); 
			if( SIZE((yyvsp[-3].Node))Nodes[(yyvsp[-1].Node)].value.data.lng);
		       naxis = lParse->Nodes[(yyvsp[-3].Node)].value.naxis;

		       if (iaxis == 0)          iaxis = naxis;   /* NAXIS(V,0) = NAXIS */
		       else if (iaxis <= naxis) iaxis = lParse->Nodes[(yyvsp[-3].Node)].value.naxes[iaxis-1]; /* NAXIS(V,n) = NAXISn */
		       else                     iaxis = 1;       /* Out of bounds use 1 */

		       (yyval.Node) = New_Const(lParse,  LONG, &iaxis, sizeof(iaxis) );
		       TEST((yyval.Node));
		     }
		   } else if (FSTRCMP((yyvsp[-4].str),"ARRAY(") == 0) {  /* NAXES(expr,n) */
		     (yyval.Node) = New_Array(lParse, (yyvsp[-3].Node), (yyvsp[-1].Node));
		     TEST((yyval.Node));
		   } else {
		      yyerror(scanner, lParse, "Function(expr,expr) not supported");
		      YYERROR;
		   }
                }
#line 2651 "eval_y.c"
    break;

  case 62: /* expr: FUNCTION expr ',' expr ',' expr ',' expr ')'  */
#line 886 "eval.y"
                { 
		  if (FSTRCMP((yyvsp[-8].str),"ANGSEP(") == 0) {
		    if( TYPE((yyvsp[-7].Node)) != DOUBLE ) (yyvsp[-7].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-7].Node) );
		    if( TYPE((yyvsp[-5].Node)) != DOUBLE ) (yyvsp[-5].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-5].Node) );
		    if( TYPE((yyvsp[-3].Node)) != DOUBLE ) (yyvsp[-3].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-3].Node) );
		    if( TYPE((yyvsp[-1].Node)) != DOUBLE ) (yyvsp[-1].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-1].Node) );
		    if( Test_Dims( lParse,  (yyvsp[-7].Node), (yyvsp[-5].Node) ) && Test_Dims( lParse,  (yyvsp[-5].Node), (yyvsp[-3].Node) ) && 
			Test_Dims( lParse,  (yyvsp[-3].Node), (yyvsp[-1].Node) ) ) {
		      (yyval.Node) = New_Func(lParse,  0, angsep_fct, 4, (yyvsp[-7].Node), (yyvsp[-5].Node), (yyvsp[-3].Node), (yyvsp[-1].Node),0,0,0 );
		      TEST((yyval.Node)); 
		      if( SIZE((yyvsp[-7].Node))=SIZE((yyvsp[-1].Node)) && Test_Dims( lParse,  (yyvsp[-3].Node), (yyvsp[-1].Node) ) ) {
			 (yyval.Node) = New_Func(lParse,  0, defnull_fct, 2, (yyvsp[-3].Node), (yyvsp[-1].Node), 0,
					0, 0, 0, 0 );
			 TEST((yyval.Node)); 
		      } else {
			 yyerror(scanner, lParse, "Dimensions of DEFNULL arguments are not compatible");
			 YYERROR;
		      }
		   } else {
		      yyerror(scanner, lParse, "Boolean Function(expr,expr) not supported");
		      YYERROR;
		   }
		}
#line 3028 "eval_y.c"
    break;

  case 106: /* bexpr: BFUNCTION expr ',' expr ',' expr ')'  */
#line 1095 "eval.y"
                {
		   if( TYPE((yyvsp[-5].Node)) != DOUBLE ) (yyvsp[-5].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-5].Node) );
		   if( TYPE((yyvsp[-3].Node)) != DOUBLE ) (yyvsp[-3].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-3].Node) );
		   if( TYPE((yyvsp[-1].Node)) != DOUBLE ) (yyvsp[-1].Node) = New_Unary(lParse,  DOUBLE, 0, (yyvsp[-1].Node) );
		   if( ! (Test_Dims( lParse,  (yyvsp[-5].Node), (yyvsp[-3].Node) ) && Test_Dims( lParse,  (yyvsp[-3].Node), (yyvsp[-1].Node) ) ) ) {
		       yyerror(scanner, lParse, "Dimensions of NEAR arguments "
			       "are not compatible");
		       YYERROR;
		   } else {
		     if (FSTRCMP((yyvsp[-6].str),"NEAR(") == 0) {
		       (yyval.Node) = New_Func(lParse,  BOOLEAN, near_fct, 3, (yyvsp[-5].Node), (yyvsp[-3].Node), (yyvsp[-1].Node),
				      0, 0, 0, 0 );
		     } else {
		       yyerror(scanner, lParse, "Boolean Function not supported");
		       YYERROR;
		     }
		     TEST((yyval.Node)); 

		     if( SIZE((yyval.Node))= MAX_STRLEN) {
		    yyerror(scanner, lParse, "Combined string size exceeds " MAX_STRLEN_S " characters");
		    YYERROR;
		  }
		  (yyval.Node) = New_BinOp(lParse,  STRING, (yyvsp[-2].Node), '+', (yyvsp[0].Node) );  TEST((yyval.Node));
		  SIZE((yyval.Node)) = SIZE((yyvsp[-2].Node)) + SIZE((yyvsp[0].Node));
		}
#line 3303 "eval_y.c"
    break;

  case 133: /* sexpr: bexpr '?' sexpr ':' sexpr  */
#line 1271 "eval.y"
                {
		  int outSize;
                  if( SIZE((yyvsp[-4].Node))!=1 ) {
                     yyerror(scanner, lParse, "Cannot have a vector string column");
		     YYERROR;
                  }
		  /* Since the output can be calculated now, as a constant
		     scalar, we must precalculate the output size, in
		     order to avoid an overflow. */
		  outSize = SIZE((yyvsp[-2].Node));
		  if (SIZE((yyvsp[0].Node)) > outSize) outSize = SIZE((yyvsp[0].Node));
                  (yyval.Node) = New_FuncSize(lParse,  0, ifthenelse_fct, 3, (yyvsp[-2].Node), (yyvsp[0].Node), (yyvsp[-4].Node),
				     0, 0, 0, 0, outSize);
		  
                  TEST((yyval.Node));
                  if( SIZE((yyvsp[-2].Node)) outSize) outSize = SIZE((yyvsp[-1].Node));
		     
		     (yyval.Node) = New_FuncSize(lParse,  0, defnull_fct, 2, (yyvsp[-3].Node), (yyvsp[-1].Node), 0,
					0, 0, 0, 0, outSize );
		     TEST((yyval.Node)); 
		     if( SIZE((yyvsp[-1].Node))>SIZE((yyvsp[-3].Node)) ) SIZE((yyval.Node)) = SIZE((yyvsp[-1].Node));
		  } else {
		     yyerror(scanner, lParse, "Function(string,string) not supported");
		     YYERROR;
		  }
		}
#line 3348 "eval_y.c"
    break;

  case 135: /* sexpr: FUNCTION sexpr ',' expr ',' expr ')'  */
#line 1309 "eval.y"
                { 
		  if (FSTRCMP((yyvsp[-6].str),"STRMID(") == 0) {
		    int len;
		    if( TYPE((yyvsp[-3].Node)) != LONG || SIZE((yyvsp[-3].Node)) != 1 ||
			TYPE((yyvsp[-1].Node)) != LONG || SIZE((yyvsp[-1].Node)) != 1) {
		      yyerror(scanner, lParse, "When using STRMID(S,P,N), P and N must be integers (and not vector columns)");
		      YYERROR;
		    }
		    if (OPER((yyvsp[-1].Node)) == CONST_OP) {
		      /* Constant value: use that directly */
		      len = (lParse->Nodes[(yyvsp[-1].Node)].value.data.lng);
		    } else {
		      /* Variable value: use the maximum possible (from $2) */
		      len = SIZE((yyvsp[-5].Node));
		    }
		    if (len <= 0 || len >= MAX_STRLEN) {
		      yyerror(scanner, lParse, "STRMID(S,P,N), N must be 1-" MAX_STRLEN_S);
		      YYERROR;
		    }
		    (yyval.Node) = New_FuncSize(lParse,  0, strmid_fct, 3, (yyvsp[-5].Node), (yyvsp[-3].Node),(yyvsp[-1].Node),0,0,0,0,len);
		    TEST((yyval.Node));
		  } else {
		     yyerror(scanner, lParse, "Function(string,expr,expr) not supported");
		     YYERROR;
		  }
		}
#line 3379 "eval_y.c"
    break;


#line 3383 "eval_y.c"

      default: break;
    }
  /* User semantic actions sometimes alter yychar, and that requires
     that yytoken be updated with the new translation.  We take the
     approach of translating immediately before every use of yytoken.
     One alternative is translating here after every semantic action,
     but that translation would be missed if the semantic action invokes
     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
     incorrect destructor might then be invoked immediately.  In the
     case of YYERROR or YYBACKUP, subsequent parser actions might lead
     to an incorrect destructor call or verbose syntax error message
     before the lookahead is translated.  */
  YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);

  YYPOPSTACK (yylen);
  yylen = 0;

  *++yyvsp = yyval;

  /* Now 'shift' the result of the reduction.  Determine what state
     that goes to, based on the state we popped back to and the rule
     number reduced by.  */
  {
    const int yylhs = yyr1[yyn] - YYNTOKENS;
    const int yyi = yypgoto[yylhs] + *yyssp;
    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
               ? yytable[yyi]
               : yydefgoto[yylhs]);
  }

  goto yynewstate;


/*--------------------------------------.
| yyerrlab -- here on detecting error.  |
`--------------------------------------*/
yyerrlab:
  /* Make sure we have latest lookahead translation.  See comments at
     user semantic actions for why this is necessary.  */
  yytoken = yychar == FITS_PARSER_YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
  /* If not already recovering from an error, report this error.  */
  if (!yyerrstatus)
    {
      ++yynerrs;
      yyerror (scanner, lParse, YY_("syntax error"));
    }

  if (yyerrstatus == 3)
    {
      /* If just tried and failed to reuse lookahead token after an
         error, discard it.  */

      if (yychar <= FITS_PARSER_YYEOF)
        {
          /* Return failure if at end of input.  */
          if (yychar == FITS_PARSER_YYEOF)
            YYABORT;
        }
      else
        {
          yydestruct ("Error: discarding",
                      yytoken, &yylval, scanner, lParse);
          yychar = FITS_PARSER_YYEMPTY;
        }
    }

  /* Else will try to reuse lookahead token after shifting the error
     token.  */
  goto yyerrlab1;


/*---------------------------------------------------.
| yyerrorlab -- error raised explicitly by YYERROR.  |
`---------------------------------------------------*/
yyerrorlab:
  /* Pacify compilers when the user code never invokes YYERROR and the
     label yyerrorlab therefore never appears in user code.  */
  if (0)
    YYERROR;
  ++yynerrs;

  /* Do not reclaim the symbols of the rule whose action triggered
     this YYERROR.  */
  YYPOPSTACK (yylen);
  yylen = 0;
  YY_STACK_PRINT (yyss, yyssp);
  yystate = *yyssp;
  goto yyerrlab1;


/*-------------------------------------------------------------.
| yyerrlab1 -- common code for both syntax error and YYERROR.  |
`-------------------------------------------------------------*/
yyerrlab1:
  yyerrstatus = 3;      /* Each real token shifted decrements this.  */

  /* Pop stack until we find a state that shifts the error token.  */
  for (;;)
    {
      yyn = yypact[yystate];
      if (!yypact_value_is_default (yyn))
        {
          yyn += YYSYMBOL_YYerror;
          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
            {
              yyn = yytable[yyn];
              if (0 < yyn)
                break;
            }
        }

      /* Pop the current state because it cannot handle the error token.  */
      if (yyssp == yyss)
        YYABORT;


      yydestruct ("Error: popping",
                  YY_ACCESSING_SYMBOL (yystate), yyvsp, scanner, lParse);
      YYPOPSTACK (1);
      yystate = *yyssp;
      YY_STACK_PRINT (yyss, yyssp);
    }

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  *++yyvsp = yylval;
  YY_IGNORE_MAYBE_UNINITIALIZED_END


  /* Shift the error token.  */
  YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);

  yystate = yyn;
  goto yynewstate;


/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here.  |
`-------------------------------------*/
yyacceptlab:
  yyresult = 0;
  goto yyreturnlab;


/*-----------------------------------.
| yyabortlab -- YYABORT comes here.  |
`-----------------------------------*/
yyabortlab:
  yyresult = 1;
  goto yyreturnlab;


/*-----------------------------------------------------------.
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here.  |
`-----------------------------------------------------------*/
yyexhaustedlab:
  yyerror (scanner, lParse, YY_("memory exhausted"));
  yyresult = 2;
  goto yyreturnlab;


/*----------------------------------------------------------.
| yyreturnlab -- parsing is finished, clean up and return.  |
`----------------------------------------------------------*/
yyreturnlab:
  if (yychar != FITS_PARSER_YYEMPTY)
    {
      /* Make sure we have latest lookahead translation.  See comments at
         user semantic actions for why this is necessary.  */
      yytoken = YYTRANSLATE (yychar);
      yydestruct ("Cleanup: discarding lookahead",
                  yytoken, &yylval, scanner, lParse);
    }
  /* Do not reclaim the symbols of the rule whose action triggered
     this YYABORT or YYACCEPT.  */
  YYPOPSTACK (yylen);
  YY_STACK_PRINT (yyss, yyssp);
  while (yyssp != yyss)
    {
      yydestruct ("Cleanup: popping",
                  YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, scanner, lParse);
      YYPOPSTACK (1);
    }
#ifndef yyoverflow
  if (yyss != yyssa)
    YYSTACK_FREE (yyss);
#endif

  return yyresult;
}

#line 1338 "eval.y"


/*************************************************************************/
/*  Start of "New" routines which build the expression Nodal structure   */
/*************************************************************************/

static int Alloc_Node( ParseData *lParse )
{
                      /* Use this for allocation to guarantee *Nodes */
   Node *newNodePtr;  /* survives on failure, making it still valid  */
                      /* while working our way out of this error     */

   if( lParse->nNodes == lParse->nNodesAlloc ) {
      if( lParse->Nodes ) {
	 lParse->nNodesAlloc += lParse->nNodesAlloc;
	 newNodePtr = (Node *)realloc( lParse->Nodes,
				       sizeof(Node)*lParse->nNodesAlloc );
      } else {
	 lParse->nNodesAlloc = 100;
	 newNodePtr = (Node *)malloc ( sizeof(Node)*lParse->nNodesAlloc );
      }	 

      if( newNodePtr ) {
	 lParse->Nodes = newNodePtr;
      } else {
	 lParse->status = MEMORY_ALLOCATION;
	 return( -1 );
      }
   }

   return ( lParse->nNodes++ );
}

static void Free_Last_Node( ParseData *lParse )
{
   if( lParse->nNodes ) lParse->nNodes--;
}

static int New_Const( ParseData *lParse, int returnType, void *value, long len )
{
   Node *this;
   int n;

   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this             = lParse->Nodes + n;
      this->operation  = CONST_OP;             /* Flag a constant */
      this->DoOp       = NULL;
      this->nSubNodes  = 0;
      this->type       = returnType;
      memcpy( &(this->value.data), value, len );
      this->value.undef = NULL;
      this->value.nelem = 1;
      this->value.naxis = 1;
      this->value.naxes[0] = 1;
   }
   return(n);
}

static int New_Column( ParseData *lParse, int ColNum )
{
   Node *this;
   int  n, i;

   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this              = lParse->Nodes + n;
      this->operation   = -ColNum;
      this->DoOp        = NULL;
      this->nSubNodes   = 0;
      this->type        = lParse->varData[ColNum].type;
      this->value.nelem = lParse->varData[ColNum].nelem;
      this->value.naxis = lParse->varData[ColNum].naxis;
      for( i=0; ivarData[ColNum].naxis; i++ )
	 this->value.naxes[i] = lParse->varData[ColNum].naxes[i];
   }
   return(n);
}

static int New_Offset( ParseData *lParse, int ColNum, int offsetNode )
{
   Node *this;
   int  n, i, colNode;

   colNode = New_Column( lParse, ColNum );
   if( colNode<0 ) return(-1);

   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this              = lParse->Nodes + n;
      this->operation   = '{';
      this->DoOp        = Do_Offset;
      this->nSubNodes   = 2;
      this->SubNodes[0] = colNode;
      this->SubNodes[1] = offsetNode;
      this->type        = lParse->varData[ColNum].type;
      this->value.nelem = lParse->varData[ColNum].nelem;
      this->value.naxis = lParse->varData[ColNum].naxis;
      for( i=0; ivarData[ColNum].naxis; i++ )
	 this->value.naxes[i] = lParse->varData[ColNum].naxes[i];
   }
   return(n);
}

static int New_Unary( ParseData *lParse, int returnType, int Op, int Node1 )
{
   Node *this, *that;
   int  i,n;

   if( Node1<0 ) return(-1);
   that = lParse->Nodes + Node1;

   if( !Op ) Op = returnType;

   if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE  ) return( Node1 );
   if( (Op==LONG   || Op==INTCAST) && that->type==LONG    ) return( Node1 );
   if( (Op==BOOLEAN              ) && that->type==BOOLEAN ) return( Node1 );
   
   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this              = lParse->Nodes + n;
      this->operation   = Op;
      this->DoOp        = Do_Unary;
      this->nSubNodes   = 1;
      this->SubNodes[0] = Node1;
      this->type        = returnType;

      that              = lParse->Nodes + Node1; /* Reset in case .Nodes mv'd */
      this->value.nelem = that->value.nelem;
      this->value.naxis = that->value.naxis;
      for( i=0; ivalue.naxis; i++ )
	 this->value.naxes[i] = that->value.naxes[i];

      if( that->operation==CONST_OP ) this->DoOp( lParse, this );
   }
   return( n );
}

static int New_BinOp( ParseData *lParse, int returnType, int Node1, int Op, int Node2 )
{
   Node *this,*that1,*that2;
   int  n,i,constant;

   if( Node1<0 || Node2<0 ) return(-1);

   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this             = lParse->Nodes + n;
      this->operation  = Op;
      this->nSubNodes  = 2;
      this->SubNodes[0]= Node1;
      this->SubNodes[1]= Node2;
      this->type       = returnType;

      that1            = lParse->Nodes + Node1;
      that2            = lParse->Nodes + Node2;
      constant         = (that1->operation==CONST_OP
                          && that2->operation==CONST_OP);
      if( that1->type!=STRING && that1->type!=BITSTR )
	if( !Test_Dims( lParse, Node1, Node2 ) ) {
	    Free_Last_Node(lParse);
	    yyerror(0, lParse, "Array sizes/dims do not match for binary operator");
	    return(-1);
	 }
      if( that1->value.nelem == 1 ) that1 = that2;

      this->value.nelem = that1->value.nelem;
      this->value.naxis = that1->value.naxis;
      for( i=0; ivalue.naxis; i++ )
	 this->value.naxes[i] = that1->value.naxes[i];

      if ( Op == ACCUM && that1->type == BITSTR ) {
	/* ACCUM is rank-reducing on bit strings */
	this->value.nelem = 1;
	this->value.naxis = 1;
	this->value.naxes[0] = 1;
      }

      /*  Both subnodes should be of same time  */
      switch( that1->type ) {
      case BITSTR:  this->DoOp = Do_BinOp_bit;  break;
      case STRING:  this->DoOp = Do_BinOp_str;  break;
      case BOOLEAN: this->DoOp = Do_BinOp_log;  break;
      case LONG:    this->DoOp = Do_BinOp_lng;  break;
      case DOUBLE:  this->DoOp = Do_BinOp_dbl;  break;
      }
      if( constant ) this->DoOp( lParse, this );
   }
   return( n );
}

static int New_Func( ParseData *lParse,
		     int returnType, funcOp Op, int nNodes,
		     int Node1, int Node2, int Node3, int Node4, 
		     int Node5, int Node6, int Node7 )
{
  return New_FuncSize(lParse,
		      returnType, Op, nNodes,
		      Node1, Node2, Node3, Node4, 
		      Node5, Node6, Node7, 0);
}

static int New_FuncSize( ParseData *lParse,
			 int returnType, funcOp Op, int nNodes,
			 int Node1, int Node2, int Node3, int Node4, 
			 int Node5, int Node6, int Node7, int Size )
/* If returnType==0 , use Node1's type and vector sizes as returnType, */
/* else return a single value of type returnType                       */
{
   Node *this, *that;
   int  i,n,constant;

   if( Node1<0 || Node2<0 || Node3<0 || Node4<0 || 
       Node5<0 || Node6<0 || Node7<0 ) return(-1);

   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this              = lParse->Nodes + n;
      this->operation   = (int)Op;
      this->DoOp        = Do_Func;
      this->nSubNodes   = nNodes;
      this->SubNodes[0] = Node1;
      this->SubNodes[1] = Node2;
      this->SubNodes[2] = Node3;
      this->SubNodes[3] = Node4;
      this->SubNodes[4] = Node5;
      this->SubNodes[5] = Node6;
      this->SubNodes[6] = Node7;
      i = constant = nNodes;    /* Functions with zero params are not const */
      if (Op == poirnd_fct) constant = 0; /* Nor is Poisson deviate */

      while( i-- )
	constant = ( constant && OPER(this->SubNodes[i]) == CONST_OP );
      
      if( returnType ) {
	 this->type           = returnType;
	 this->value.nelem    = 1;
	 this->value.naxis    = 1;
	 this->value.naxes[0] = 1;
      } else {
	 that              = lParse->Nodes + Node1;
	 this->type        = that->type;
	 this->value.nelem = that->value.nelem;
	 this->value.naxis = that->value.naxis;
	 for( i=0; ivalue.naxis; i++ )
	    this->value.naxes[i] = that->value.naxes[i];
      }
      /* Force explicit size before evaluating */
      if (Size > 0) this->value.nelem = Size;

      if( constant ) this->DoOp( lParse, this );
   }
   return( n );
}

static int New_Deref( ParseData *lParse, int Var,  int nDim,
		      int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 )
{
   int n, idx, constant;
   long elem=0;
   Node *this, *theVar, *theDim[MAXDIMS];

   if( Var<0 || Dim1<0 || Dim2<0 || Dim3<0 || Dim4<0 || Dim5<0 ) return(-1);

   theVar = lParse->Nodes + Var;
   if( theVar->operation==CONST_OP || theVar->value.nelem==1 ) {
      yyerror(0, lParse, "Cannot index a scalar value");
      return(-1);
   }

   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this              = lParse->Nodes + n;
      this->nSubNodes   = nDim+1;
      theVar            = lParse->Nodes + (this->SubNodes[0]=Var);
      theDim[0]         = lParse->Nodes + (this->SubNodes[1]=Dim1);
      theDim[1]         = lParse->Nodes + (this->SubNodes[2]=Dim2);
      theDim[2]         = lParse->Nodes + (this->SubNodes[3]=Dim3);
      theDim[3]         = lParse->Nodes + (this->SubNodes[4]=Dim4);
      theDim[4]         = lParse->Nodes + (this->SubNodes[5]=Dim5);
      constant          = theVar->operation==CONST_OP;
      for( idx=0; idxoperation==CONST_OP);

      for( idx=0; idxvalue.nelem>1 ) {
	    Free_Last_Node(lParse);
	    yyerror(0, lParse, "Cannot use an array as an index value");
	    return(-1);
	 } else if( theDim[idx]->type!=LONG ) {
	    Free_Last_Node(lParse);
	    yyerror(0, lParse, "Index value must be an integer type");
	    return(-1);
	 }

      this->operation   = '[';
      this->DoOp        = Do_Deref;
      this->type        = theVar->type;

      if( theVar->value.naxis == nDim ) { /* All dimensions specified */
	 this->value.nelem    = 1;
	 this->value.naxis    = 1;
	 this->value.naxes[0] = 1;
      } else if( nDim==1 ) { /* Dereference only one dimension */
	 elem=1;
	 this->value.naxis = theVar->value.naxis-1;
	 for( idx=0; idxvalue.naxis; idx++ ) {
	    elem *= ( this->value.naxes[idx] = theVar->value.naxes[idx] );
	 }
	 this->value.nelem = elem;
      } else {
	 Free_Last_Node(lParse);
	 yyerror(0, lParse, "Must specify just one or all indices for vector");
	 return(-1);
      }
      if( constant ) this->DoOp( lParse, this );
   }
   return(n);
}

extern int fits_parser_yyGetVariable( ParseData *lParse, char *varName, YYSTYPE *varVal );

static int New_GTI( ParseData *lParse, funcOp Op, char *fname, int Node1, int Node2, char *start, char *stop )
{
   fitsfile *fptr;
   Node *this, *that0, *that1, *that2;
   int  type,i,n, startCol, stopCol, Node0;
   int  hdutype, hdunum, evthdu, samefile, extvers, movetotype, tstat;
   char extname[100];
   long nrows;
   double timeZeroI[2], timeZeroF[2], dt, timeSpan;
   char xcol[20], xexpr[20];
   YYSTYPE colVal;

   if( (Op == gtifilt_fct || Op == gtifind_fct) && Node1==-99 ) {
      type = fits_parser_yyGetVariable( lParse,  "TIME", &colVal );
      if( type==COLUMN ) {
	 Node1 = New_Column( lParse, (int)colVal.lng );
      } else {
	 yyerror(0, lParse, "Could not build TIME column for GTIFILTER/GTIFIND");
	 return(-1);
      }
   }

   if (Op == gtiover_fct) {
     if (Node1 == -99 || Node2 == -99) {
       yyerror(0, lParse, "startExpr and stopExpr values must be defined for GTIOVERLAP");
       return(-1);
     }
     /* Also case TIME_STOP to double precision */
     Node2 = New_Unary( lParse, DOUBLE, 0, Node2 );
     if (Node2 < 0) return(-1);

   }

   /* Type cast TIME to double precision */
   Node1 = New_Unary( lParse, DOUBLE, 0, Node1 );
   Node0 = Alloc_Node(lParse); /* This will hold the START/STOP times */
   if( Node1<0 || Node0<0 ) return(-1);

   /*  Record current HDU number in case we need to move within this file  */

   fptr = lParse->def_fptr;
   ffghdn( fptr, &evthdu );

   /*  Look for TIMEZERO keywords in current extension  */

   tstat = 0;
   if( ffgkyd( fptr, "TIMEZERO", timeZeroI, NULL, &tstat ) ) {
      tstat = 0;
      if( ffgkyd( fptr, "TIMEZERI", timeZeroI, NULL, &tstat ) ) {
	 timeZeroI[0] = timeZeroF[0] = 0.0;
      } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF, NULL, &tstat ) ) {
	 timeZeroF[0] = 0.0;
      }
   } else {
      timeZeroF[0] = 0.0;
   }

   /*  Resolve filename parameter  */

   switch( fname[0] ) {
   case '\0':
      samefile = 1;
      hdunum = 1;
      break;
   case '[':
      samefile = 1;
      i = 1;
      while( fname[i] != '\0' && fname[i] != ']' ) i++;
      if( fname[i] ) {
	 fname[i] = '\0';
	 fname++;
	 ffexts( fname, &hdunum, extname, &extvers, &movetotype,
		 xcol, xexpr, &lParse->status );
         if( *extname ) {
	    ffmnhd( fptr, movetotype, extname, extvers, &lParse->status );
	    ffghdn( fptr, &hdunum );
	 } else if( hdunum ) {
	    ffmahd( fptr, ++hdunum, &hdutype, &lParse->status );
	 } else if( !lParse->status ) {
	    yyerror(0, lParse, "Cannot use primary array for GTI filter");
	    return( -1 );
	 }
      } else {
	 yyerror(0, lParse, "File extension specifier lacks closing ']'");
	 return( -1 );
      }
      break;
   case '+':
      samefile = 1;
      hdunum = atoi( fname ) + 1;
      if( hdunum>1 )
	 ffmahd( fptr, hdunum, &hdutype, &lParse->status );
      else {
	 yyerror(0, lParse, "Cannot use primary array for GTI filter / GTIFIND");
	 return( -1 );
      }
      break;
   default:
      samefile = 0;
      if( ! ffopen( &fptr, fname, READONLY, &lParse->status ) )
	 ffghdn( fptr, &hdunum );
      break;
   }
   if( lParse->status ) return(-1);

   /*  If at primary, search for GTI extension  */

   if( hdunum==1 ) {
      while( 1 ) {
	 hdunum++;
	 if( ffmahd( fptr, hdunum, &hdutype, &lParse->status ) ) break;
	 if( hdutype==IMAGE_HDU ) continue;
	 tstat = 0;
	 if( ffgkys( fptr, "EXTNAME", extname, NULL, &tstat ) ) continue;
	 ffupch( extname );
	 if( strstr( extname, "GTI" ) ) break;
      }
      if( lParse->status ) {
	 if( lParse->status==END_OF_FILE )
	    yyerror(0, lParse, "GTI extension not found in this file");
	 return(-1);
      }
   }

   /*  Locate START/STOP Columns  */

   ffgcno( fptr, CASEINSEN, start, &startCol, &lParse->status );
   ffgcno( fptr, CASEINSEN, stop,  &stopCol,  &lParse->status );
   if( lParse->status ) return(-1);

   /*  Look for TIMEZERO keywords in GTI extension  */

   tstat = 0;
   if( ffgkyd( fptr, "TIMEZERO", timeZeroI+1, NULL, &tstat ) ) {
      tstat = 0;
      if( ffgkyd( fptr, "TIMEZERI", timeZeroI+1, NULL, &tstat ) ) {
	 timeZeroI[1] = timeZeroF[1] = 0.0;
      } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF+1, NULL, &tstat ) ) {
	 timeZeroF[1] = 0.0;
      }
   } else {
      timeZeroF[1] = 0.0;
   }

   n = Alloc_Node(lParse);
   if( n >= 0 ) {
      this                 = lParse->Nodes + n;
      this->SubNodes[1]    = Node1;
      this->operation      = (int) Op;
      if (Op == gtifilt_fct) {
	this->nSubNodes      = 2;
	this->DoOp           = Do_GTI;
	this->type           = BOOLEAN;
      } else if (Op == gtifind_fct) {
	this->nSubNodes      = 2;
	this->DoOp           = Do_GTI;
	this->type           = LONG;
      } else {
	this->nSubNodes      = 3;
	this->DoOp           = Do_GTI_Over;
	this->type           = DOUBLE;
      }
      that1                = lParse->Nodes + Node1;
      this->value.nelem    = that1->value.nelem;
      this->value.naxis    = that1->value.naxis;
      for( i=0; i < that1->value.naxis; i++ )
	 this->value.naxes[i] = that1->value.naxes[i];
      if (Op == gtiover_fct) {
	this->SubNodes[2]  = Node2;
	that2 = lParse->Nodes + Node2;
	if (that1->value.nelem != that2->value.nelem) {
	  yyerror(0, lParse, "Dimensions of TIME and TIME_STOP must match for GTIOVERLAP");
	  return(-1);
	}
      }

      /* Init START/STOP node to be treated as a "constant" */

      this->SubNodes[0]    = Node0;
      that0                = lParse->Nodes + Node0;
      that0->operation     = CONST_OP;
      that0->DoOp          = NULL;
      that0->value.data.ptr= NULL;

      /*  Read in START/STOP times  */

      if( ffgkyj( fptr, "NAXIS2", &nrows, NULL, &lParse->status ) )
	 return(-1);
      that0->value.nelem = nrows;
      if( nrows ) {

	 that0->value.data.dblptr = (double*)malloc( 2*nrows*sizeof(double) );
	 if( !that0->value.data.dblptr ) {
	    lParse->status = MEMORY_ALLOCATION;
	    return(-1);
	 }
	 
	 ffgcvd( fptr, startCol, 1L, 1L, nrows, 0.0,
		 that0->value.data.dblptr, &i, &lParse->status );
	 ffgcvd( fptr, stopCol, 1L, 1L, nrows, 0.0,
		 that0->value.data.dblptr+nrows, &i, &lParse->status );
	 if( lParse->status ) {
	    free( that0->value.data.dblptr );
	    return(-1);
	 }

	 /*  Test for fully time-ordered GTI... both START && STOP  */

	 that0->type = 1; /*  Assume yes  */
	 i = nrows;
	 while( --i )
	    if(    that0->value.data.dblptr[i-1]
                   >= that0->value.data.dblptr[i]
		|| that0->value.data.dblptr[i-1+nrows]
		   >= that0->value.data.dblptr[i+nrows] ) {
	       that0->type = 0;
	       break;
	    }

	 /* GTIOVERLAP() requires ordered GTI */
	 if (that0->type != 1 && Op == gtiover_fct) {
	   yyerror(0, lParse, "Input GTI must be time-ordered for GTIOVERLAP");
	   return(-1);
	 }
	 
	 /*  Handle TIMEZERO offset, if any  */
	 
	 dt = (timeZeroI[1] - timeZeroI[0]) + (timeZeroF[1] - timeZeroF[0]);
	 timeSpan = that0->value.data.dblptr[nrows+nrows-1]
	    - that0->value.data.dblptr[0];
	 if (timeSpan == 0) timeSpan = 1.0;
	 
	 if( fabs( dt / timeSpan ) > 1e-12 ) {
	    for( i=0; i<(nrows+nrows); i++ )
	       that0->value.data.dblptr[i] += dt;
	 }
      }
      /* If Node1 is constant (gtifilt_fct) or
	 Node1 and Node2 are constant (gtiover_fct), then evaluate now */
      if( OPER(Node1)==CONST_OP && (Op == gtifilt_fct || OPER(Node2)==CONST_OP)) {
	this->DoOp( lParse, this );
      }
   }

   if( samefile )
      ffmahd( fptr, evthdu, &hdutype, &lParse->status );
   else
      ffclos( fptr, &lParse->status );

   return( n );
}

static int New_REG( ParseData *lParse, char *fname, int NodeX, int NodeY, char *colNames )
{
   Node *this, *that0;
   int  type, n, Node0;
   int  Xcol, Ycol, tstat;
   WCSdata wcs;
   SAORegion *Rgn;
   char *cX, *cY;
   YYSTYPE colVal;

   if( NodeX==-99 ) {
      type = fits_parser_yyGetVariable( lParse,  "X", &colVal );
      if( type==COLUMN ) {
	 NodeX = New_Column( lParse, (int)colVal.lng );
      } else {
	 yyerror(0, lParse, "Could not build X column for REGFILTER");
	 return(-1);
      }
   }
   if( NodeY==-99 ) {
      type = fits_parser_yyGetVariable( lParse, "Y", &colVal );
      if( type==COLUMN ) {
 	 NodeY = New_Column( lParse, (int)colVal.lng );
      } else {
	 yyerror(0, lParse, "Could not build Y column for REGFILTER");
	 return(-1);
      }
   }
   NodeX = New_Unary( lParse, DOUBLE, 0, NodeX );
   NodeY = New_Unary( lParse, DOUBLE, 0, NodeY );
   Node0 = Alloc_Node(lParse); /* This will hold the Region Data */
   if( NodeX<0 || NodeY<0 || Node0<0 ) return(-1);

   if( ! (Test_Dims( lParse, NodeX, NodeY ) ) ) {
     yyerror(0, lParse, "Dimensions of REGFILTER arguments are not compatible");
     return (-1);
   }

   n = Alloc_Node(lParse);
   if( n >= 0 ) {
      this                 = lParse->Nodes + n;
      this->nSubNodes      = 3;
      this->SubNodes[0]    = Node0;
      this->SubNodes[1]    = NodeX;
      this->SubNodes[2]    = NodeY;
      this->operation      = (int)regfilt_fct;
      this->DoOp           = Do_REG;
      this->type           = BOOLEAN;
      this->value.nelem    = 1;
      this->value.naxis    = 1;
      this->value.naxes[0] = 1;
      
      Copy_Dims(lParse, n, NodeX);
      if( SIZE(NodeX)Nodes + Node0;
      that0->operation     = CONST_OP;
      that0->DoOp          = NULL;

      /*  Identify what columns to use for WCS information  */

      Xcol = Ycol = 0;
      if( *colNames ) {
	 /*  Use the column names in this string for WCS info  */
	 while( *colNames==' ' ) colNames++;
	 cX = cY = colNames;
	 while( *cY && *cY!=' ' && *cY!=',' ) cY++;
	 if( *cY )
	    *(cY++) = '\0';
	 while( *cY==' ' ) cY++;
	 if( !*cY ) {
	    yyerror(0, lParse, "Could not extract valid pair of column names from REGFILTER");
	    Free_Last_Node(lParse);
	    return( -1 );
	 }
	 fits_get_colnum( lParse->def_fptr, CASEINSEN, cX, &Xcol,
			  &lParse->status );
	 fits_get_colnum( lParse->def_fptr, CASEINSEN, cY, &Ycol,
			  &lParse->status );
	 if( lParse->status ) {
	    yyerror(0, lParse, "Could not locate columns indicated for WCS info");
	    Free_Last_Node(lParse);
	    return( -1 );
	 }

      } else {
	 /*  Try to find columns used in X/Y expressions  */
	 Xcol = Locate_Col( lParse, lParse->Nodes + NodeX );
	 Ycol = Locate_Col( lParse, lParse->Nodes + NodeY );
	 if( Xcol<0 || Ycol<0 ) {
	    yyerror(0, lParse, "Found multiple X/Y column references in REGFILTER");
	    Free_Last_Node(lParse);
	    return( -1 );
	 }
      }

      /*  Now, get the WCS info, if it exists, from the indicated columns  */
      wcs.exists = 0;
      if( Xcol>0 && Ycol>0 ) {
	 tstat = 0;
	 ffgtcs( lParse->def_fptr, Xcol, Ycol,
		 &wcs.xrefval, &wcs.yrefval,
		 &wcs.xrefpix, &wcs.yrefpix,
		 &wcs.xinc,    &wcs.yinc,
		 &wcs.rot,      wcs.type,
		 &tstat );
	 if( tstat==NO_WCS_KEY ) {
	    wcs.exists = 0;
	 } else if( tstat ) {
	    lParse->status = tstat;
	    Free_Last_Node(lParse);
	    return( -1 );
	 } else {
	    wcs.exists = 1;
	 }
      }

      /*  Read in Region file  */

      fits_read_rgnfile( fname, &wcs, &Rgn, &lParse->status );
      if( lParse->status ) {
	 Free_Last_Node(lParse);
	 return( -1 );
      }

      that0->value.data.ptr = Rgn;

      if( OPER(NodeX)==CONST_OP && OPER(NodeY)==CONST_OP )
	 this->DoOp( lParse, this );
   }

   return( n );
}

static int New_Vector( ParseData *lParse, int subNode )
{
   Node *this, *that;
   int n;

   n = Alloc_Node(lParse);
   if( n >= 0 ) {
      this              = lParse->Nodes + n;
      that              = lParse->Nodes + subNode;
      this->type        = that->type;
      this->nSubNodes   = 1;
      this->SubNodes[0] = subNode;
      this->operation   = '{';
      this->DoOp        = Do_Vector;
   }

   return( n );
}

static int Close_Vec( ParseData *lParse, int vecNode )
{
   Node *this;
   int n, nelem=0;

   this = lParse->Nodes + vecNode;
   for( n=0; n < this->nSubNodes; n++ ) {
      if( TYPE( this->SubNodes[n] ) != this->type ) {
	 this->SubNodes[n] = New_Unary( lParse, this->type, 0, this->SubNodes[n] );
	 if( this->SubNodes[n]<0 ) return(-1);
      }
      nelem += SIZE(this->SubNodes[n]);
   }
   this->value.naxis    = 1;
   this->value.nelem    = nelem;
   this->value.naxes[0] = nelem;

   return( vecNode );
}

static int New_Array( ParseData *lParse, int valueNode, int dimNode )
{
  Node *dims;
  long naxis, nelem;
  long naxes[MAXDIMS];
  Node *this;
  int  n,i;

   if( valueNode<0 || dimNode<0 ) return(-1);

   /* Check that dimensions are {a,b,c,d}
        - vector
	- every element is constant integer
	- 5 or fewer dimensions 
   */

   dims = &(lParse->Nodes[dimNode]);
   for (i=0; iNodes[dimNode].value.data.lng;

   } else if (OPER(dimNode) == '{') { /* ARRAY(V,{a,b,c,d,e}) up to 5 dimensions */
     if (dims->nSubNodes > MAXDIMS) {
       yyerror(0, lParse, "ARRAY(V,{...}) number of dimensions must not exceed 5");
       return (-1);
     }
     naxis = dims->nSubNodes;
     for (i=0; inSubNodes; i++) {
       if ( TYPE(dims->SubNodes[i]) != LONG ) {
	 dims->SubNodes[i] = New_Unary(lParse, LONG, 0, dims->SubNodes[i]);
	 if (dims->SubNodes[i] < 0) return (-1);
       }
       naxes[i] = lParse->Nodes[ dims->SubNodes[i] ].value.data.lng;
     }
   } else {
     yyerror(0, lParse, "ARRAY(V,dims) dims must be either integer or const vector");
     return (-1);
   }

   nelem = 1;
   for (i=0; i 1) {
     /* "reform" operation - do nothing */
   } else if (SIZE(valueNode) > 1 && nelem > 1) {
     yyerror(0, lParse, "ARRAY(V,d) mismatch between number of elements in V and d");
     return (-1);
   } else if (SIZE(valueNode) > 1) {
     yyerror(0, lParse, "ARRAY(V,n) value V must have vector dimension of 1");
     return (-1);
   }
   
   n = Alloc_Node(lParse);
   if( n>=0 ) {
      this             = lParse->Nodes + n;
      this->operation  = array_fct;
      this->nSubNodes  = 1;
      this->SubNodes[0]= valueNode;
      this->type       = TYPE(valueNode);

      this->value.nelem = nelem;
      this->value.naxis = naxis;
      for( i=0; ivalue.naxes[i] = naxes[i];

      this->DoOp = Do_Array;
   }
   return( n );
}

static int Locate_Col( ParseData *lParse, Node *this )
/*  Locate the TABLE column number of any columns in "this" calculation.  */
/*  Return ZERO if none found, or negative if more than 1 found.          */
{
   Node *that;
   int  i, col=0, newCol, nfound=0;
   
   if( this->nSubNodes==0
       && this->operation<=0 && this->operation!=CONST_OP )
      return lParse->colData[ - this->operation].colnum;

   for( i=0; inSubNodes; i++ ) {
      that = lParse->Nodes + this->SubNodes[i];
      if( that->operation>0 ) {
	 newCol = Locate_Col( lParse, that );
	 if( newCol<=0 ) {
	    nfound += -newCol;
	 } else {
	    if( !nfound ) {
	       col = newCol;
	       nfound++;
	    } else if( col != newCol ) {
	       nfound++;
	    }
	 }
      } else if( that->operation!=CONST_OP ) {
	 /*  Found a Column  */
	 newCol = lParse->colData[- that->operation].colnum;
	 if( !nfound ) {
	    col = newCol;
	    nfound++;
	 } else if( col != newCol ) {
	    nfound++;
	 }
      }
   }
   if( nfound!=1 )
      return( - nfound );
   else
      return( col );
}

static int Test_Dims( ParseData *lParse, int Node1, int Node2 )
{
   Node *that1, *that2;
   int valid, i;

   if( Node1<0 || Node2<0 ) return(0);

   that1 = lParse->Nodes + Node1;
   that2 = lParse->Nodes + Node2;

   if( that1->value.nelem==1 || that2->value.nelem==1 )
      valid = 1;
   else if( that1->type==that2->type
	    && that1->value.nelem==that2->value.nelem
	    && that1->value.naxis==that2->value.naxis ) {
      valid = 1;
      for( i=0; ivalue.naxis; i++ ) {
	 if( that1->value.naxes[i]!=that2->value.naxes[i] )
	    valid = 0;
      }
   } else
      valid = 0;
   return( valid );
}   

static void Copy_Dims( ParseData *lParse, int Node1, int Node2 )
{
   Node *that1, *that2;
   int i;

   if( Node1<0 || Node2<0 ) return;

   that1 = lParse->Nodes + Node1;
   that2 = lParse->Nodes + Node2;

   that1->value.nelem = that2->value.nelem;
   that1->value.naxis = that2->value.naxis;
   for( i=0; ivalue.naxis; i++ )
      that1->value.naxes[i] = that2->value.naxes[i];
}

/********************************************************************/
/*    Routines for actually evaluating the expression start here    */
/********************************************************************/

void Evaluate_Parser( ParseData *lParse, long firstRow, long nRows )
    /***********************************************************************/
    /*  Reset the parser for processing another batch of data...           */
    /*    firstRow:  Row number of the first element to evaluate           */
    /*    nRows:     Number of rows to be processed                        */
    /*  Initialize each COLUMN node so that its UNDEF and DATA pointers    */
    /*  point to the appropriate column arrays.                            */
    /*  Finally, call Evaluate_Node for final node.                        */
    /***********************************************************************/
{
   int     i, column;
   long    offset, rowOffset;
   static int rand_initialized = 0;

   /* Initialize the random number generator once and only once */
   if (rand_initialized == 0) {
     simplerng_srand( (unsigned int) time(NULL) );
     rand_initialized = 1;
   }

   lParse->firstRow = firstRow;
   lParse->nRows    = nRows;

   /*  Reset Column Nodes' pointers to point to right data and UNDEF arrays  */

   rowOffset = firstRow - lParse->firstDataRow;
   for( i=0; inNodes; i++ ) {
     if(    OPER(i) >  0 || OPER(i) == CONST_OP ) continue;

      column = -OPER(i);
      offset = lParse->varData[column].nelem * rowOffset;

      lParse->Nodes[i].value.undef = lParse->varData[column].undef + offset;

      switch( lParse->Nodes[i].type ) {
      case BITSTR:
	 lParse->Nodes[i].value.data.strptr =
	    (char**)lParse->varData[column].data + rowOffset;
	 lParse->Nodes[i].value.undef       = NULL;
	 break;
      case STRING:
	 lParse->Nodes[i].value.data.strptr = 
	    (char**)lParse->varData[column].data + rowOffset;
	 lParse->Nodes[i].value.undef = lParse->varData[column].undef + rowOffset;
	 break;
      case BOOLEAN:
	 lParse->Nodes[i].value.data.logptr = 
	    (char*)lParse->varData[column].data + offset;
	 break;
      case LONG:
	 lParse->Nodes[i].value.data.lngptr = 
	    (long*)lParse->varData[column].data + offset;
	 break;
      case DOUBLE:
	 lParse->Nodes[i].value.data.dblptr = 
	    (double*)lParse->varData[column].data + offset;
	 break;
      }
   }

   Evaluate_Node( lParse, lParse->resultNode );
}

static void Evaluate_Node( ParseData *lParse, int thisNode )
    /**********************************************************************/
    /*  Recursively evaluate thisNode's subNodes, then call one of the    */
    /*  Do_ functions pointed to by thisNode's DoOp element.      */
    /**********************************************************************/
{
   Node *this;
   int i;
   
   if( lParse->status ) return;

   this = lParse->Nodes + thisNode;
   if( this->operation>0 ) {  /* <=0 indicate constants and columns */
      i = this->nSubNodes;
      while( i-- ) {
	 Evaluate_Node( lParse, this->SubNodes[i] );
	 if( lParse->status ) return;
      }
      this->DoOp( lParse, this );
   }
}

static void Allocate_Ptrs( ParseData *lParse, Node *this )
{
   long elem, row, size;

   if( this->type==BITSTR || this->type==STRING ) {

      this->value.data.strptr = (char**)malloc( lParse->nRows
						* sizeof(char*) );
      if( this->value.data.strptr ) {
	 this->value.data.strptr[0] = (char*)malloc( lParse->nRows
						     * (this->value.nelem+2)
						     * sizeof(char) );
	 if( this->value.data.strptr[0] ) {
	    row = 0;
	    while( (++row)nRows ) {
	       this->value.data.strptr[row] =
		  this->value.data.strptr[row-1] + this->value.nelem+1;
	    }
	    if( this->type==STRING ) {
	       this->value.undef = this->value.data.strptr[row-1]
                                   + this->value.nelem+1;
	    } else {
	       this->value.undef = NULL;  /* BITSTRs don't use undef array */
	    }
	 } else {
	    lParse->status = MEMORY_ALLOCATION;
	    free( this->value.data.strptr );
	 }
      } else {
	 lParse->status = MEMORY_ALLOCATION;
      }

   } else {

      elem = this->value.nelem * lParse->nRows;
      switch( this->type ) {
      case DOUBLE:  size = sizeof( double ); break;
      case LONG:    size = sizeof( long   ); break;
      case BOOLEAN: size = sizeof( char   ); break;
      default:      size = 1;                break;
      }

      this->value.data.ptr = calloc(size+1, elem);

      if( this->value.data.ptr==NULL ) {
	 lParse->status = MEMORY_ALLOCATION;
      } else {
	 this->value.undef = (char *)this->value.data.ptr + elem*size;
      }
   }
}

static void Do_Unary( ParseData *lParse, Node *this )
{
   Node *that;
   long elem;

   that = lParse->Nodes + this->SubNodes[0];

   if( that->operation==CONST_OP ) {  /* Operating on a constant! */
      switch( this->operation ) {
      case DOUBLE:
      case FLTCAST:
	 if( that->type==LONG )
	    this->value.data.dbl = (double)that->value.data.lng;
	 else if( that->type==BOOLEAN )
	    this->value.data.dbl = ( that->value.data.log ? 1.0 : 0.0 );
	 break;
      case LONG:
      case INTCAST:
	 if( that->type==DOUBLE )
	    this->value.data.lng = (long)that->value.data.dbl;
	 else if( that->type==BOOLEAN )
	    this->value.data.lng = ( that->value.data.log ? 1L : 0L );
	 break;
      case BOOLEAN:
	 if( that->type==DOUBLE )
	    this->value.data.log = ( that->value.data.dbl != 0.0 );
	 else if( that->type==LONG )
	    this->value.data.log = ( that->value.data.lng != 0L );
	 break;
      case UMINUS:
	 if( that->type==DOUBLE )
	    this->value.data.dbl = - that->value.data.dbl;
	 else if( that->type==LONG )
	    this->value.data.lng = - that->value.data.lng;
	 break;
      case NOT:
	 if( that->type==BOOLEAN )
	    this->value.data.log = ( ! that->value.data.log );
	 else if( that->type==BITSTR )
	    bitnot( this->value.data.str, that->value.data.str );
	 break;
      }
      this->operation = CONST_OP;

   } else {

      Allocate_Ptrs( lParse, this );

      if( !lParse->status ) {

	 if( this->type!=BITSTR ) {
	    elem = lParse->nRows;
	    if( this->type!=STRING )
	       elem *= this->value.nelem;
	    while( elem-- )
	       this->value.undef[elem] = that->value.undef[elem];
	 }

	 elem = lParse->nRows * this->value.nelem;

	 switch( this->operation ) {

	 case BOOLEAN:
	    if( that->type==DOUBLE )
	       while( elem-- )
		  this->value.data.logptr[elem] =
		     ( that->value.data.dblptr[elem] != 0.0 );
	    else if( that->type==LONG )
	       while( elem-- )
		  this->value.data.logptr[elem] =
		     ( that->value.data.lngptr[elem] != 0L );
	    break;

	 case DOUBLE:
	 case FLTCAST:
	    if( that->type==LONG )
	       while( elem-- )
		  this->value.data.dblptr[elem] =
		     (double)that->value.data.lngptr[elem];
	    else if( that->type==BOOLEAN )
	       while( elem-- )
		  this->value.data.dblptr[elem] =
		     ( that->value.data.logptr[elem] ? 1.0 : 0.0 );
	    break;

	 case LONG:
	 case INTCAST:
	    if( that->type==DOUBLE )
	       while( elem-- )
		  this->value.data.lngptr[elem] =
		     (long)that->value.data.dblptr[elem];
	    else if( that->type==BOOLEAN )
	       while( elem-- )
		  this->value.data.lngptr[elem] =
		     ( that->value.data.logptr[elem] ? 1L : 0L );
	    break;

	 case UMINUS:
	    if( that->type==DOUBLE ) {
	       while( elem-- )
		  this->value.data.dblptr[elem] =
		     - that->value.data.dblptr[elem];
	    } else if( that->type==LONG ) {
	       while( elem-- )
		  this->value.data.lngptr[elem] =
		     - that->value.data.lngptr[elem];
	    }
	    break;

	 case NOT:
	    if( that->type==BOOLEAN ) {
	       while( elem-- )
		  this->value.data.logptr[elem] =
		     ( ! that->value.data.logptr[elem] );
	    } else if( that->type==BITSTR ) {
	       elem = lParse->nRows;
	       while( elem-- )
		  bitnot( this->value.data.strptr[elem],
			  that->value.data.strptr[elem] );
	    }
	    break;
	 }
      }
   }

   if( that->operation>0 ) {
      free( that->value.data.ptr );
   }
}

static void Do_Offset( ParseData *lParse, Node *this )
{
   Node *col;
   long fRow, nRowOverlap, nRowReload, rowOffset;
   long nelem, elem, offset, nRealElem;
   int status;

   col       = lParse->Nodes + this->SubNodes[0];
   rowOffset = lParse->Nodes[  this->SubNodes[1] ].value.data.lng;

   Allocate_Ptrs( lParse, this );

   fRow   = lParse->firstRow + rowOffset;
   if( this->type==STRING || this->type==BITSTR )
      nRealElem = 1;
   else
      nRealElem = this->value.nelem;

   nelem = nRealElem;

   if( fRow < lParse->firstDataRow ) {

      /* Must fill in data at start of array */

      nRowReload = lParse->firstDataRow - fRow;
      if( nRowReload > lParse->nRows ) nRowReload = lParse->nRows;
      nRowOverlap = lParse->nRows - nRowReload;

      offset = 0;

      /*  NULLify any values falling out of bounds  */

      while( fRow<1 && nRowReload>0 ) {
	 if( this->type == BITSTR ) {
	    nelem = this->value.nelem;
	    this->value.data.strptr[offset][ nelem ] = '\0';
	    while( nelem-- ) this->value.data.strptr[offset][nelem] = '0';
	    offset++;
	 } else {
	    while( nelem-- )
	       this->value.undef[offset++] = 1;
	 }
	 nelem = nRealElem;
	 fRow++;
	 nRowReload--;
      }

   } else if( fRow + lParse->nRows > lParse->firstDataRow + lParse->nDataRows ) {

      /* Must fill in data at end of array */

      nRowReload = (fRow+lParse->nRows) - (lParse->firstDataRow+lParse->nDataRows);
      if( nRowReload>lParse->nRows ) {
	 nRowReload = lParse->nRows;
      } else {
	 fRow = lParse->firstDataRow + lParse->nDataRows;
      }
      nRowOverlap = lParse->nRows - nRowReload;

      offset = nRowOverlap * nelem;

      /*  NULLify any values falling out of bounds  */

      elem = lParse->nRows * nelem;
      while( fRow+nRowReload>lParse->totalRows && nRowReload>0 ) {
	 if( this->type == BITSTR ) {
	    nelem = this->value.nelem;
	    elem--;
	    this->value.data.strptr[elem][ nelem ] = '\0';
	    while( nelem-- ) this->value.data.strptr[elem][nelem] = '0';
	 } else {
	    while( nelem-- )
	       this->value.undef[--elem] = 1;
	 }
	 nelem = nRealElem;
	 nRowReload--;
      }

   } else {

      nRowReload  = 0;
      nRowOverlap = lParse->nRows;
      offset      = 0;

   }

   if( nRowReload>0 ) {
      switch( this->type ) {
      case BITSTR:
      case STRING:
	 status = (*lParse->loadData)( lParse, -col->operation, fRow, nRowReload,
				      this->value.data.strptr+offset,
				      this->value.undef+offset );
	 break;
      case BOOLEAN:
	 status = (*lParse->loadData)( lParse, -col->operation, fRow, nRowReload,
				      this->value.data.logptr+offset,
				      this->value.undef+offset );
	 break;
      case LONG:
	 status = (*lParse->loadData)( lParse, -col->operation, fRow, nRowReload,
				      this->value.data.lngptr+offset,
				      this->value.undef+offset );
	 break;
      case DOUBLE:
	 status = (*lParse->loadData)( lParse, -col->operation, fRow, nRowReload,
				      this->value.data.dblptr+offset,
				      this->value.undef+offset );
	 break;
      }
   }

   /*  Now copy over the overlapping region, if any  */

   if( nRowOverlap <= 0 ) return;

   if( rowOffset>0 )
      elem = nRowOverlap * nelem;
   else
      elem = lParse->nRows * nelem;

   offset = nelem * rowOffset;
   while( nRowOverlap-- && !lParse->status ) {
      while( nelem-- && !lParse->status ) {
	 elem--;
	 if( this->type != BITSTR )
	    this->value.undef[elem] = col->value.undef[elem+offset];
	 switch( this->type ) {
	 case BITSTR:
	    strcpy( this->value.data.strptr[elem       ],
                     col->value.data.strptr[elem+offset] );
	    break;
	 case STRING:
	    strcpy( this->value.data.strptr[elem       ],
                     col->value.data.strptr[elem+offset] );
	    break;
	 case BOOLEAN:
	    this->value.data.logptr[elem] = col->value.data.logptr[elem+offset];
	    break;
	 case LONG:
	    this->value.data.lngptr[elem] = col->value.data.lngptr[elem+offset];
	    break;
	 case DOUBLE:
	    this->value.data.dblptr[elem] = col->value.data.dblptr[elem+offset];
	    break;
	 }
      }
      nelem = nRealElem;
   }
}

static void Do_BinOp_bit( ParseData *lParse, Node *this )
{
   Node *that1, *that2;
   char *sptr1=NULL, *sptr2=NULL;
   int  const1, const2;
   long rows;

   that1 = lParse->Nodes + this->SubNodes[0];
   that2 = lParse->Nodes + this->SubNodes[1];

   const1 = ( that1->operation==CONST_OP );
   const2 = ( that2->operation==CONST_OP );
   sptr1  = ( const1 ? that1->value.data.str : NULL );
   sptr2  = ( const2 ? that2->value.data.str : NULL );

   if( const1 && const2 ) {
      switch( this->operation ) {
      case NE:
	 this->value.data.log = !bitcmp( sptr1, sptr2 );
	 break;
      case EQ:
	 this->value.data.log =  bitcmp( sptr1, sptr2 );
	 break;
      case GT:
      case LT:
      case LTE:
      case GTE:
	 this->value.data.log = bitlgte( sptr1, this->operation, sptr2 );
	 break;
      case '|': 
	 bitor( this->value.data.str, sptr1, sptr2 );
	 break;
      case '&': 
	 bitand( this->value.data.str, sptr1, sptr2 );
	 break;
      case '+':
	 strcpy( this->value.data.str, sptr1 );
	 strcat( this->value.data.str, sptr2 );
	 break;
      case ACCUM:
	this->value.data.lng = 0;
	while( *sptr1 ) {
	  if ( *sptr1 == '1' ) this->value.data.lng ++;
	  sptr1 ++;
	}
	break;
	
      }
      this->operation = CONST_OP;

   } else {

      Allocate_Ptrs( lParse, this );
     
      if( !lParse->status ) {
	 rows  = lParse->nRows;
	 switch( this->operation ) {

	    /*  BITSTR comparisons  */

	 case NE:
	 case EQ:
	 case GT:
	 case LT:
	 case LTE:
	 case GTE:
	    while( rows-- ) {
	       if( !const1 )
		  sptr1 = that1->value.data.strptr[rows];
	       if( !const2 )
		  sptr2 = that2->value.data.strptr[rows];
	       switch( this->operation ) {
	       case NE:  this->value.data.logptr[rows] = 
                                                      !bitcmp( sptr1, sptr2 );
                         break;
	       case EQ:  this->value.data.logptr[rows] = 
                                                       bitcmp( sptr1, sptr2 );
                         break;
	       case GT:
	       case LT:
	       case LTE:
	       case GTE: this->value.data.logptr[rows] = 
                                     bitlgte( sptr1, this->operation, sptr2 );
	                 break;
	       }
	       this->value.undef[rows] = 0;
	    }
	    break;
	 
	    /*  BITSTR AND/ORs ...  no UNDEFS in or out */
      
	 case '|': 
	 case '&': 
	 case '+':
	    while( rows-- ) {
	       if( !const1 )
		  sptr1 = that1->value.data.strptr[rows];
	       if( !const2 )
		  sptr2 = that2->value.data.strptr[rows];
	       if( this->operation=='|' )
		  bitor(  this->value.data.strptr[rows], sptr1, sptr2 );
	       else if( this->operation=='&' )
		  bitand( this->value.data.strptr[rows], sptr1, sptr2 );
	       else {
		  strcpy( this->value.data.strptr[rows], sptr1 );
		  strcat( this->value.data.strptr[rows], sptr2 );
	       }
	    }
	    break;

	    /* Accumulate 1 bits */
	 case ACCUM:
	   { 
	     long i, previous, curr;

	     previous = that2->value.data.lng;
	     
	      /* Cumulative sum of this chunk */
	     for (i=0; ivalue.data.strptr[i];
	       for (curr = 0; *sptr1; sptr1 ++) {
		 if ( *sptr1 == '1' ) curr ++;
	       }
	       previous += curr;
	       this->value.data.lngptr[i] = previous;
	       this->value.undef[i] = 0;
	     }
	     
	      /* Store final cumulant for next pass */
	     that2->value.data.lng = previous;
	   }
	 }
      }
   }

   if( that1->operation>0 ) {
      free( that1->value.data.strptr[0] );
      free( that1->value.data.strptr    );
   }
   if( that2->operation>0 ) {
      free( that2->value.data.strptr[0] );
      free( that2->value.data.strptr    );
   }
}

static void Do_BinOp_str( ParseData *lParse, Node *this )
{
   Node *that1, *that2;
   char *sptr1, *sptr2, null1=0, null2=0;
   int const1, const2, val;
   long rows;

   that1 = lParse->Nodes + this->SubNodes[0];
   that2 = lParse->Nodes + this->SubNodes[1];

   const1 = ( that1->operation==CONST_OP );
   const2 = ( that2->operation==CONST_OP );
   sptr1  = ( const1 ? that1->value.data.str : NULL );
   sptr2  = ( const2 ? that2->value.data.str : NULL );

   if( const1 && const2 ) {  /*  Result is a constant  */
      switch( this->operation ) {

	 /*  Compare Strings  */

      case NE:
      case EQ:
	 val = ( FSTRCMP( sptr1, sptr2 ) == 0 );
	 this->value.data.log = ( this->operation==EQ ? val : !val );
	 break;
      case GT:
	 this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) > 0 );
	 break;
      case LT:
	 this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) < 0 );
	 break;
      case GTE:
	 this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) >= 0 );
	 break;
      case LTE:
	 this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) <= 0 );
	 break;

	 /*  Concat Strings  */

      case '+':
	 strcpy( this->value.data.str, sptr1 );
	 strcat( this->value.data.str, sptr2 );
	 break;
      }
      this->operation = CONST_OP;

   } else {  /*  Not a constant  */

     Allocate_Ptrs( lParse, this );

      if( !lParse->status ) {

	 rows = lParse->nRows;
	 switch( this->operation ) {

	    /*  Compare Strings  */

	 case NE:
	 case EQ:
	    while( rows-- ) {
	       if( !const1 ) null1 = that1->value.undef[rows];
	       if( !const2 ) null2 = that2->value.undef[rows];
	       this->value.undef[rows] = (null1 || null2);
	       if( ! this->value.undef[rows] ) {
		  if( !const1 ) sptr1  = that1->value.data.strptr[rows];
		  if( !const2 ) sptr2  = that2->value.data.strptr[rows];
		  val = ( FSTRCMP( sptr1, sptr2 ) == 0 );
		  this->value.data.logptr[rows] =
		     ( this->operation==EQ ? val : !val );
	       }
	    }
	    break;
	    
	 case GT:
	 case LT:
	    while( rows-- ) {
	       if( !const1 ) null1 = that1->value.undef[rows];
	       if( !const2 ) null2 = that2->value.undef[rows];
	       this->value.undef[rows] = (null1 || null2);
	       if( ! this->value.undef[rows] ) {
		  if( !const1 ) sptr1  = that1->value.data.strptr[rows];
		  if( !const2 ) sptr2  = that2->value.data.strptr[rows];
		  val = ( FSTRCMP( sptr1, sptr2 ) );
		  this->value.data.logptr[rows] =
		     ( this->operation==GT ? val>0 : val<0 );
	       }
	    }
	    break;

	 case GTE:
	 case LTE:
	    while( rows-- ) {
	       if( !const1 ) null1 = that1->value.undef[rows];
	       if( !const2 ) null2 = that2->value.undef[rows];
	       this->value.undef[rows] = (null1 || null2);
	       if( ! this->value.undef[rows] ) {
		  if( !const1 ) sptr1  = that1->value.data.strptr[rows];
		  if( !const2 ) sptr2  = that2->value.data.strptr[rows];
		  val = ( FSTRCMP( sptr1, sptr2 ) );
		  this->value.data.logptr[rows] =
		     ( this->operation==GTE ? val>=0 : val<=0 );
	       }
	    }
	    break;

	    /*  Concat Strings  */
	    
	 case '+':
	    while( rows-- ) {
	       if( !const1 ) null1 = that1->value.undef[rows];
	       if( !const2 ) null2 = that2->value.undef[rows];
	       this->value.undef[rows] = (null1 || null2);
	       if( ! this->value.undef[rows] ) {
		  if( !const1 ) sptr1  = that1->value.data.strptr[rows];
		  if( !const2 ) sptr2  = that2->value.data.strptr[rows];
		  strcpy( this->value.data.strptr[rows], sptr1 );
		  strcat( this->value.data.strptr[rows], sptr2 );
	       }
	    }
	    break;
	 }
      }
   }

   if( that1->operation>0 ) {
      free( that1->value.data.strptr[0] );
      free( that1->value.data.strptr );
   }
   if( that2->operation>0 ) {
      free( that2->value.data.strptr[0] );
      free( that2->value.data.strptr );
   }
}

static void Do_BinOp_log( ParseData *lParse, Node *this )
{
   Node *that1, *that2;
   int vector1, vector2;
   char val1=0, val2=0, null1=0, null2=0;
   long rows, nelem, elem;

   that1 = lParse->Nodes + this->SubNodes[0];
   that2 = lParse->Nodes + this->SubNodes[1];

   vector1 = ( that1->operation!=CONST_OP );
   if( vector1 )
      vector1 = that1->value.nelem;
   else {
      val1  = that1->value.data.log;
   }

   vector2 = ( that2->operation!=CONST_OP );
   if( vector2 )
      vector2 = that2->value.nelem;
   else {
      val2  = that2->value.data.log;
   }

   if( !vector1 && !vector2 ) {  /*  Result is a constant  */
      switch( this->operation ) {
      case OR:
	 this->value.data.log = (val1 || val2);
	 break;
      case AND:
	 this->value.data.log = (val1 && val2);
	 break;
      case EQ:
	 this->value.data.log = ( (val1 && val2) || (!val1 && !val2) );
	 break;
      case NE:
	 this->value.data.log = ( (val1 && !val2) || (!val1 && val2) );
	 break;
      case ACCUM:
	 this->value.data.lng = val1;
	 break;
      }
      this->operation=CONST_OP;
   } else if (this->operation == ACCUM) {
      long i, previous, curr;
      rows  = lParse->nRows;
      nelem = this->value.nelem;
      elem  = this->value.nelem * rows;
      
      Allocate_Ptrs( lParse, this );
      
      if( !lParse->status ) {
	previous = that2->value.data.lng;
	
	/* Cumulative sum of this chunk */
	for (i=0; ivalue.undef[i]) {
	    curr = that1->value.data.logptr[i];
	    previous += curr;
	  }
	  this->value.data.lngptr[i] = previous;
	  this->value.undef[i] = 0;
	}
	
	/* Store final cumulant for next pass */
	that2->value.data.lng = previous;
      }
      
   } else {
      rows  = lParse->nRows;
      nelem = this->value.nelem;
      elem  = this->value.nelem * rows;

      Allocate_Ptrs( lParse, this );

      if( !lParse->status ) {
	
	 if (this->operation == ACCUM) {
	   long i, previous, curr;
	   
	   previous = that2->value.data.lng;
	   
	   /* Cumulative sum of this chunk */
	   for (i=0; ivalue.undef[i]) {
	       curr = that1->value.data.logptr[i];
	       previous += curr;
	     }
	     this->value.data.lngptr[i] = previous;
	     this->value.undef[i] = 0;
	   }
	   
	   /* Store final cumulant for next pass */
	   that2->value.data.lng = previous;
	 }
	
	 while( rows-- ) {
	    while( nelem-- ) {
	       elem--;

	       if( vector1>1 ) {
		  val1  = that1->value.data.logptr[elem];
		  null1 = that1->value.undef[elem];
	       } else if( vector1 ) {
		  val1  = that1->value.data.logptr[rows];
		  null1 = that1->value.undef[rows];
	       }

	       if( vector2>1 ) {
		  val2  = that2->value.data.logptr[elem];
		  null2 = that2->value.undef[elem];
	       } else if( vector2 ) {
		  val2  = that2->value.data.logptr[rows];
		  null2 = that2->value.undef[rows];
	       }

	       this->value.undef[elem] = (null1 || null2);
	       switch( this->operation ) {

	       case OR:
		  /*  This is more complicated than others to suppress UNDEFs */
		  /*  in those cases where the other argument is DEF && TRUE  */

		  if( !null1 && !null2 ) {
		     this->value.data.logptr[elem] = (val1 || val2);
		  } else if( (null1 && !null2 && val2)
			     || ( !null1 && null2 && val1 ) ) {
		     this->value.data.logptr[elem] = 1;
		     this->value.undef[elem] = 0;
		  }
		  break;

	       case AND:
		  /*  This is more complicated than others to suppress UNDEFs */
		  /*  in those cases where the other argument is DEF && FALSE */

		  if( !null1 && !null2 ) {
		     this->value.data.logptr[elem] = (val1 && val2);
		  } else if( (null1 && !null2 && !val2)
			     || ( !null1 && null2 && !val1 ) ) {
		     this->value.data.logptr[elem] = 0;
		     this->value.undef[elem] = 0;
		  }
		  break;

	       case EQ:
		  this->value.data.logptr[elem] = 
		     ( (val1 && val2) || (!val1 && !val2) );
		  break;

	       case NE:
		  this->value.data.logptr[elem] =
		     ( (val1 && !val2) || (!val1 && val2) );
		  break;
	       }
	    }
	    nelem = this->value.nelem;
	 }
      }
   }

   if( that1->operation>0 ) {
      free( that1->value.data.ptr );
   }
   if( that2->operation>0 ) {
      free( that2->value.data.ptr );
   }
}

static void Do_BinOp_lng( ParseData *lParse, Node *this )
{
   Node *that1, *that2;
   int  vector1, vector2;
   long val1=0, val2=0;
   char null1=0, null2=0;
   long rows, nelem, elem;

   that1 = lParse->Nodes + this->SubNodes[0];
   that2 = lParse->Nodes + this->SubNodes[1];

   vector1 = ( that1->operation!=CONST_OP );
   if( vector1 )
      vector1 = that1->value.nelem;
   else {
      val1  = that1->value.data.lng;
   }

   vector2 = ( that2->operation!=CONST_OP );
   if( vector2 )
      vector2 = that2->value.nelem;
   else {
      val2  = that2->value.data.lng;
   }

   if( !vector1 && !vector2 ) {  /*  Result is a constant  */

      switch( this->operation ) {
      case '~':   /* Treat as == for LONGS */
      case EQ:    this->value.data.log = (val1 == val2);   break;
      case NE:    this->value.data.log = (val1 != val2);   break;
      case GT:    this->value.data.log = (val1 >  val2);   break;
      case LT:    this->value.data.log = (val1 <  val2);   break;
      case LTE:   this->value.data.log = (val1 <= val2);   break;
      case GTE:   this->value.data.log = (val1 >= val2);   break;

      case '+':   this->value.data.lng = (val1  + val2);   break;
      case '-':   this->value.data.lng = (val1  - val2);   break;
      case '*':   this->value.data.lng = (val1  * val2);   break;

      case '&':   this->value.data.lng = (val1  & val2);   break;
      case '|':   this->value.data.lng = (val1  | val2);   break;
      case '^':   this->value.data.lng = (val1  ^ val2);   break;

      case '%':
	 if( val2 ) this->value.data.lng = (val1 % val2);
	 else       yyerror(0, lParse, "Divide by Zero");
	 break;
      case '/': 
	 if( val2 ) this->value.data.lng = (val1 / val2); 
	 else       yyerror(0, lParse, "Divide by Zero");
	 break;
      case POWER:
	 this->value.data.lng = (long)pow((double)val1,(double)val2);
	 break;
      case ACCUM:
	 this->value.data.lng = val1;
	 break;
      case DIFF:
	 this->value.data.lng = 0;
	 break;
      }
      this->operation=CONST_OP;

   } else if ((this->operation == ACCUM) || (this->operation == DIFF)) {
      long i, previous, curr;
      long undef;
      rows  = lParse->nRows;
      nelem = this->value.nelem;
      elem  = this->value.nelem * rows;
      
      Allocate_Ptrs( lParse, this );
      
      if( !lParse->status ) {
	previous = that2->value.data.lng;
	undef    = (long) that2->value.undef;
	
	if (this->operation == ACCUM) {
	  /* Cumulative sum of this chunk */
	  for (i=0; ivalue.undef[i]) {
	      curr = that1->value.data.lngptr[i];
	      previous += curr;
	    }
	    this->value.data.lngptr[i] = previous;
	    this->value.undef[i] = 0;
	  }
	} else {
	  /* Sequential difference for this chunk */
	  for (i=0; ivalue.data.lngptr[i];
	    if (that1->value.undef[i] || undef) {
	      /* Either this, or previous, value was undefined */
	      this->value.data.lngptr[i] = 0;
	      this->value.undef[i] = 1;
	    } else {
	      /* Both defined, we are okay! */
	      this->value.data.lngptr[i] = curr - previous;
	      this->value.undef[i] = 0;
	    }

	    previous = curr;
	    undef = that1->value.undef[i];
	  }
	}	  
	
	/* Store final cumulant for next pass */
	that2->value.data.lng = previous;
	that2->value.undef    = (char *) undef; /* XXX evil, but no harm here */
      }
      
   } else {

      rows  = lParse->nRows;
      nelem = this->value.nelem;
      elem  = this->value.nelem * rows;

      Allocate_Ptrs( lParse, this );

      while( rows-- && !lParse->status ) {
	 while( nelem-- && !lParse->status ) {
	    elem--;

	    if( vector1>1 ) {
	       val1  = that1->value.data.lngptr[elem];
	       null1 = that1->value.undef[elem];
	    } else if( vector1 ) {
	       val1  = that1->value.data.lngptr[rows];
	       null1 = that1->value.undef[rows];
	    }

	    if( vector2>1 ) {
	       val2  = that2->value.data.lngptr[elem];
	       null2 = that2->value.undef[elem];
	    } else if( vector2 ) {
	       val2  = that2->value.data.lngptr[rows];
	       null2 = that2->value.undef[rows];
	    }

	    this->value.undef[elem] = (null1 || null2);
	    switch( this->operation ) {
	    case '~':   /* Treat as == for LONGS */
	    case EQ:   this->value.data.logptr[elem] = (val1 == val2);   break;
	    case NE:   this->value.data.logptr[elem] = (val1 != val2);   break;
	    case GT:   this->value.data.logptr[elem] = (val1 >  val2);   break;
	    case LT:   this->value.data.logptr[elem] = (val1 <  val2);   break;
	    case LTE:  this->value.data.logptr[elem] = (val1 <= val2);   break;
	    case GTE:  this->value.data.logptr[elem] = (val1 >= val2);   break;
	       
	    case '+':  this->value.data.lngptr[elem] = (val1  + val2);   break;
	    case '-':  this->value.data.lngptr[elem] = (val1  - val2);   break;
	    case '*':  this->value.data.lngptr[elem] = (val1  * val2);   break;

	    case '&':  this->value.data.lngptr[elem] = (val1  & val2);   break;
	    case '|':  this->value.data.lngptr[elem] = (val1  | val2);   break;
	    case '^':  this->value.data.lngptr[elem] = (val1  ^ val2);   break;

	    case '%':   
	       if( val2 ) this->value.data.lngptr[elem] = (val1 % val2);
	       else {
		 this->value.data.lngptr[elem] = 0;
		 this->value.undef[elem] = 1;
	       }
	       break;
	    case '/': 
	       if( val2 ) this->value.data.lngptr[elem] = (val1 / val2); 
	       else {
		 this->value.data.lngptr[elem] = 0;
		 this->value.undef[elem] = 1;
	       }
	       break;
	    case POWER:
	       this->value.data.lngptr[elem] = (long)pow((double)val1,(double)val2);
	       break;
	    }
	 }
	 nelem = this->value.nelem;
      }
   }

   if( that1->operation>0 ) {
      free( that1->value.data.ptr );
   }
   if( that2->operation>0 ) {
      free( that2->value.data.ptr );
   }
}

static void Do_BinOp_dbl( ParseData *lParse, Node *this )
{
   Node   *that1, *that2;
   int    vector1, vector2;
   double val1=0.0, val2=0.0;
   char   null1=0, null2=0;
   long   rows, nelem, elem;

   that1 = lParse->Nodes + this->SubNodes[0];
   that2 = lParse->Nodes + this->SubNodes[1];

   vector1 = ( that1->operation!=CONST_OP );
   if( vector1 )
      vector1 = that1->value.nelem;
   else {
      val1  = that1->value.data.dbl;
   }

   vector2 = ( that2->operation!=CONST_OP );
   if( vector2 )
      vector2 = that2->value.nelem;
   else {
      val2  = that2->value.data.dbl;
   } 

   if( !vector1 && !vector2 ) {  /*  Result is a constant  */

      switch( this->operation ) {
      case '~':   this->value.data.log = ( fabs(val1-val2) < APPROX );   break;
      case EQ:    this->value.data.log = (val1 == val2);   break;
      case NE:    this->value.data.log = (val1 != val2);   break;
      case GT:    this->value.data.log = (val1 >  val2);   break;
      case LT:    this->value.data.log = (val1 <  val2);   break;
      case LTE:   this->value.data.log = (val1 <= val2);   break;
      case GTE:   this->value.data.log = (val1 >= val2);   break;

      case '+':   this->value.data.dbl = (val1  + val2);   break;
      case '-':   this->value.data.dbl = (val1  - val2);   break;
      case '*':   this->value.data.dbl = (val1  * val2);   break;

      case '%':
	 if( val2 ) this->value.data.dbl = val1 - val2*((int)(val1/val2));
	 else       yyerror(0, lParse, "Divide by Zero");
	 break;
      case '/': 
	 if( val2 ) this->value.data.dbl = (val1 / val2); 
	 else       yyerror(0, lParse, "Divide by Zero");
	 break;
      case POWER:
	 this->value.data.dbl = (double)pow(val1,val2);
	 break;
      case ACCUM:
	 this->value.data.dbl = val1;
	 break;
      case DIFF:
	this->value.data.dbl = 0;
	 break;
      }
      this->operation=CONST_OP;

   } else if ((this->operation == ACCUM) || (this->operation == DIFF)) {
      long i;
      long undef;
      double previous, curr;
      rows  = lParse->nRows;
      nelem = this->value.nelem;
      elem  = this->value.nelem * rows;
      
      Allocate_Ptrs( lParse, this );
      
      if( !lParse->status ) {
	previous = that2->value.data.dbl;
	undef    = (long) that2->value.undef;
	
	if (this->operation == ACCUM) {
	  /* Cumulative sum of this chunk */
	  for (i=0; ivalue.undef[i]) {
	      curr = that1->value.data.dblptr[i];
	      previous += curr;
	    }
	    this->value.data.dblptr[i] = previous;
	    this->value.undef[i] = 0;
	  }
	} else {
	  /* Sequential difference for this chunk */
	  for (i=0; ivalue.data.dblptr[i];
	    if (that1->value.undef[i] || undef) {
	      /* Either this, or previous, value was undefined */
	      this->value.data.dblptr[i] = 0;
	      this->value.undef[i] = 1;
	    } else {
	      /* Both defined, we are okay! */
	      this->value.data.dblptr[i] = curr - previous;
	      this->value.undef[i] = 0;
	    }

	    previous = curr;
	    undef = that1->value.undef[i];
	  }
	}	  
	
	/* Store final cumulant for next pass */
	that2->value.data.dbl = previous;
	that2->value.undef    = (char *) undef; /* XXX evil, but no harm here */
      }
      
   } else {

      rows  = lParse->nRows;
      nelem = this->value.nelem;
      elem  = this->value.nelem * rows;

      Allocate_Ptrs( lParse, this );

      while( rows-- && !lParse->status ) {
	 while( nelem-- && !lParse->status ) {
	    elem--;

	    if( vector1>1 ) {
	       val1  = that1->value.data.dblptr[elem];
	       null1 = that1->value.undef[elem];
	    } else if( vector1 ) {
	       val1  = that1->value.data.dblptr[rows];
	       null1 = that1->value.undef[rows];
	    }

	    if( vector2>1 ) {
	       val2  = that2->value.data.dblptr[elem];
	       null2 = that2->value.undef[elem];
	    } else if( vector2 ) {
	       val2  = that2->value.data.dblptr[rows];
	       null2 = that2->value.undef[rows];
	    }

	    this->value.undef[elem] = (null1 || null2);
	    switch( this->operation ) {
	    case '~':   this->value.data.logptr[elem] =
                                          ( fabs(val1-val2) < APPROX );   break;
	    case EQ:    this->value.data.logptr[elem] = (val1 == val2);   break;
	    case NE:    this->value.data.logptr[elem] = (val1 != val2);   break;
	    case GT:    this->value.data.logptr[elem] = (val1 >  val2);   break;
	    case LT:    this->value.data.logptr[elem] = (val1 <  val2);   break;
	    case LTE:   this->value.data.logptr[elem] = (val1 <= val2);   break;
	    case GTE:   this->value.data.logptr[elem] = (val1 >= val2);   break;
	       
	    case '+':   this->value.data.dblptr[elem] = (val1  + val2);   break;
	    case '-':   this->value.data.dblptr[elem] = (val1  - val2);   break;
	    case '*':   this->value.data.dblptr[elem] = (val1  * val2);   break;

	    case '%':
	       if( val2 ) this->value.data.dblptr[elem] =
                                val1 - val2*((int)(val1/val2));
	       else {
		 this->value.data.dblptr[elem] = 0.0;
		 this->value.undef[elem] = 1;
	       }
	       break;
	    case '/': 
	       if( val2 ) this->value.data.dblptr[elem] = (val1 / val2); 
	       else {
		 this->value.data.dblptr[elem] = 0.0;
		 this->value.undef[elem] = 1;
	       }
	       break;
	    case POWER:
	       this->value.data.dblptr[elem] = (double)pow(val1,val2);
	       break;
	    }
	 }
	 nelem = this->value.nelem;
      }
   }

   if( that1->operation>0 ) {
      free( that1->value.data.ptr );
   }
   if( that2->operation>0 ) {
      free( that2->value.data.ptr );
   }
}

/*
 *  This Quickselect routine is based on the algorithm described in
 *  "Numerical recipes in C", Second Edition,
 *  Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
 *  This code by Nicolas Devillard - 1998. Public domain.
 * http://ndevilla.free.fr/median/median/src/quickselect.c
 */

#define ELEM_SWAP(a,b) { register long t=(a);(a)=(b);(b)=t; }

/* 
 * qselect_median_lng - select the median value of a long array
 *
 * This routine selects the median value of the long integer array
 * arr[].  If there are an even number of elements, the "lower median"
 * is selected.
 *
 * The array arr[] is scrambled, so users must operate on a scratch
 * array if they wish the values to be preserved.
 *
 * long arr[] - array of values
 * int n - number of elements in arr
 *
 * RETURNS: the lower median value of arr[]
 *
 */
long qselect_median_lng(long arr[], int n)
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {

        if (high <= low) { /* One element only */
	  return arr[median];	  
	}

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
	    return arr[median];
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP

#define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }

/* 
 * qselect_median_dbl - select the median value of a double array
 *
 * This routine selects the median value of the double array
 * arr[].  If there are an even number of elements, the "lower median"
 * is selected.
 *
 * The array arr[] is scrambled, so users must operate on a scratch
 * array if they wish the values to be preserved.
 *
 * double arr[] - array of values
 * int n - number of elements in arr
 *
 * RETURNS: the lower median value of arr[]
 *
 */
double qselect_median_dbl(double arr[], int n)
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {
        if (high <= low) { /* One element only */
            return arr[median] ;
	}

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
            return arr[median] ;
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP

/*
 * angsep_calc - compute angular separation between celestial coordinates
 *   
 * This routine computes the angular separation between to coordinates
 * on the celestial sphere (i.e. RA and Dec).  Note that all units are
 * in DEGREES, unlike the other trig functions in the calculator.
 *
 * double ra1, dec1 - RA and Dec of the first position in degrees
 * double ra2, dec2 - RA and Dec of the second position in degrees
 * 
 * RETURNS: (double) angular separation in degrees
 *
 */
double angsep_calc(double ra1, double dec1, double ra2, double dec2)
{
/*  double cd;  */
  static double deg = 0;
  double a, sdec, sra;
  
  if (deg == 0) deg = ((double)4)*atan((double)1)/((double)180);
  /* deg = 1.0; **** UNCOMMENT IF YOU WANT RADIANS */

  /* The algorithm is the law of Haversines.  This algorithm is
     stable even when the points are close together.  The normal
     Law of Cosines fails for angles around 0.1 arcsec. */

  sra  = sin( (ra2 - ra1)*deg / 2 );
  sdec = sin( (dec2 - dec1)*deg / 2);
  a = sdec*sdec + cos(dec1*deg)*cos(dec2*deg)*sra*sra;

  /* Sanity checking to avoid a range error in the sqrt()'s below */
  if (a < 0) { a = 0; }
  if (a > 1) { a = 1; }

  return 2.0*atan2(sqrt(a), sqrt(1.0 - a)) / deg;
}

static void Do_Func( ParseData *lParse, Node *this )
{
   Node *theParams[MAXSUBS];
   int  vector[MAXSUBS], allConst;
   lval pVals[MAXSUBS];
   char pNull[MAXSUBS];
   long   ival;
   double dval;
   int  i, valInit;
   long row, elem, nelem;

   i = this->nSubNodes;
   allConst = 1;
   while( i-- ) {
      theParams[i] = lParse->Nodes + this->SubNodes[i];
      vector[i]   = ( theParams[i]->operation!=CONST_OP );
      if( vector[i] ) {
	 allConst = 0;
	 vector[i] = theParams[i]->value.nelem;
      } else {
	 if( theParams[i]->type==DOUBLE ) {
	    pVals[i].data.dbl = theParams[i]->value.data.dbl;
	 } else if( theParams[i]->type==LONG ) {
	    pVals[i].data.lng = theParams[i]->value.data.lng;
	 } else if( theParams[i]->type==BOOLEAN ) {
	    pVals[i].data.log = theParams[i]->value.data.log;
	 } else
	    strcpy(pVals[i].data.str, theParams[i]->value.data.str);
	 pNull[i] = 0;
      }
   }

   if( this->nSubNodes==0 ) allConst = 0; /* These do produce scalars */
   /* Random numbers are *never* constant !! */
   if( this->operation == poirnd_fct ) allConst = 0;
   if( this->operation == gasrnd_fct ) allConst = 0;
   if( this->operation == rnd_fct ) allConst = 0;

   if( allConst ) {

      switch( this->operation ) {

	    /* Non-Trig single-argument functions */

	 case sum_fct:
	    if( theParams[0]->type==BOOLEAN )
	       this->value.data.lng = ( pVals[0].data.log ? 1 : 0 );
	    else if( theParams[0]->type==LONG )
	       this->value.data.lng = pVals[0].data.lng;
	    else if( theParams[0]->type==DOUBLE )
	       this->value.data.dbl = pVals[0].data.dbl;
	    else if( theParams[0]->type==BITSTR )
	      strcpy(this->value.data.str, pVals[0].data.str);
	    break;
         case average_fct:
	    if( theParams[0]->type==LONG )
	       this->value.data.dbl = pVals[0].data.lng;
	    else if( theParams[0]->type==DOUBLE )
	       this->value.data.dbl = pVals[0].data.dbl;
	    break;
         case stddev_fct:
	    this->value.data.dbl = 0;  /* Standard deviation of a constant = 0 */
	    break;
	 case median_fct:
	    if( theParams[0]->type==BOOLEAN )
	       this->value.data.lng = ( pVals[0].data.log ? 1 : 0 );
	    else if( theParams[0]->type==LONG )
	       this->value.data.lng = pVals[0].data.lng;
	    else
	       this->value.data.dbl = pVals[0].data.dbl;
	    break;

	 case poirnd_fct:
	    if( theParams[0]->type==DOUBLE )
	      this->value.data.lng = simplerng_getpoisson(pVals[0].data.dbl);
	    else
	      this->value.data.lng = simplerng_getpoisson(pVals[0].data.lng);
	    break;

	 case abs_fct:
	    if( theParams[0]->type==DOUBLE ) {
	       dval = pVals[0].data.dbl;
	       this->value.data.dbl = (dval>0.0 ? dval : -dval);
	    } else {
	       ival = pVals[0].data.lng;
	       this->value.data.lng = (ival> 0  ? ival : -ival);
	    }
	    break;

            /* Special Null-Handling Functions */

         case nonnull_fct:
	    this->value.data.lng = 1; /* Constants are always 1-element and defined */
	    break;
         case isnull_fct:  /* Constants are always defined */
	    this->value.data.log = 0;
	    break;
         case defnull_fct:
	    if( this->type==BOOLEAN )
	       this->value.data.log = pVals[0].data.log;
            else if( this->type==LONG )
	       this->value.data.lng = pVals[0].data.lng;
            else if( this->type==DOUBLE )
	       this->value.data.dbl = pVals[0].data.dbl;
            else if( this->type==STRING )
	       strcpy(this->value.data.str,pVals[0].data.str);
	    break;
        case setnull_fct: /* Only defined for numeric expressions */
            if( this->type==LONG )
 	      this->value.data.lng = pVals[0].data.lng;
            else if( this->type==DOUBLE )
	       this->value.data.dbl = pVals[0].data.dbl;
	    break;

	    /* Math functions with 1 double argument */

	 case sin_fct:
	    this->value.data.dbl = sin( pVals[0].data.dbl );
	    break;
	 case cos_fct:
	    this->value.data.dbl = cos( pVals[0].data.dbl );
	    break;
	 case tan_fct:
	    this->value.data.dbl = tan( pVals[0].data.dbl );
	    break;
	 case asin_fct:
	    dval = pVals[0].data.dbl;
	    if( dval<-1.0 || dval>1.0 )
	       yyerror(0, lParse, "Out of range argument to arcsin");
	    else
	       this->value.data.dbl = asin( dval );
	    break;
	 case acos_fct:
	    dval = pVals[0].data.dbl;
	    if( dval<-1.0 || dval>1.0 )
	       yyerror(0, lParse, "Out of range argument to arccos");
	    else
	       this->value.data.dbl = acos( dval );
	    break;
	 case atan_fct:
	    this->value.data.dbl = atan( pVals[0].data.dbl );
	    break;
	 case sinh_fct:
	    this->value.data.dbl = sinh( pVals[0].data.dbl );
	    break;
	 case cosh_fct:
	    this->value.data.dbl = cosh( pVals[0].data.dbl );
	    break;
	 case tanh_fct:
	    this->value.data.dbl = tanh( pVals[0].data.dbl );
	    break;
	 case exp_fct:
	    this->value.data.dbl = exp( pVals[0].data.dbl );
	    break;
	 case log_fct:
	    dval = pVals[0].data.dbl;
	    if( dval<=0.0 )
	       yyerror(0, lParse, "Out of range argument to log");
	    else
	       this->value.data.dbl = log( dval );
	    break;
	 case log10_fct:
	    dval = pVals[0].data.dbl;
	    if( dval<=0.0 )
	       yyerror(0, lParse, "Out of range argument to log10");
	    else
	       this->value.data.dbl = log10( dval );
	    break;
	 case sqrt_fct:
	    dval = pVals[0].data.dbl;
	    if( dval<0.0 )
	       yyerror(0, lParse, "Out of range argument to sqrt");
	    else
	       this->value.data.dbl = sqrt( dval );
	    break;
	 case ceil_fct:
	    this->value.data.dbl = ceil( pVals[0].data.dbl );
	    break;
	 case floor_fct:
	    this->value.data.dbl = floor( pVals[0].data.dbl );
	    break;
	 case round_fct:
	    this->value.data.dbl = floor( pVals[0].data.dbl + 0.5 );
	    break;

	    /* Two-argument Trig Functions */

	 case atan2_fct:
	    this->value.data.dbl =
	       atan2( pVals[0].data.dbl, pVals[1].data.dbl );
	    break;

	    /* Four-argument ANGSEP function */
         case angsep_fct:
	    this->value.data.dbl = 
	      angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl,
			  pVals[2].data.dbl, pVals[3].data.dbl);

	    /*  Min/Max functions taking 1 or 2 arguments  */

         case min1_fct:
	    /* No constant vectors! */
	    if( this->type == DOUBLE )
	       this->value.data.dbl = pVals[0].data.dbl;
	    else if( this->type == LONG )
	       this->value.data.lng = pVals[0].data.lng;
	    else if( this->type == BITSTR )
	      strcpy(this->value.data.str, pVals[0].data.str);
	    break;
         case min2_fct:
	    if( this->type == DOUBLE )
	       this->value.data.dbl =
		  minvalue( pVals[0].data.dbl, pVals[1].data.dbl );
	    else if( this->type == LONG )
	       this->value.data.lng =
		  minvalue( pVals[0].data.lng, pVals[1].data.lng );
	    break;
         case max1_fct:
	    /* No constant vectors! */
	    if( this->type == DOUBLE )
	       this->value.data.dbl = pVals[0].data.dbl;
	    else if( this->type == LONG )
	       this->value.data.lng = pVals[0].data.lng;
	    else if( this->type == BITSTR )
	      strcpy(this->value.data.str, pVals[0].data.str);
	    break;
         case max2_fct:
	    if( this->type == DOUBLE )
	       this->value.data.dbl =
		  maxvalue( pVals[0].data.dbl, pVals[1].data.dbl );
	    else if( this->type == LONG )
	       this->value.data.lng =
		  maxvalue( pVals[0].data.lng, pVals[1].data.lng );
	    break;

	    /* Boolean SAO region Functions... scalar or vector dbls */

	 case near_fct:
	    this->value.data.log = bnear( pVals[0].data.dbl, pVals[1].data.dbl,
					  pVals[2].data.dbl );
	    break;
	 case circle_fct:
	    this->value.data.log = circle( pVals[0].data.dbl, pVals[1].data.dbl,
					   pVals[2].data.dbl, pVals[3].data.dbl,
					   pVals[4].data.dbl );
	    break;
	 case box_fct:
	    this->value.data.log = saobox( pVals[0].data.dbl, pVals[1].data.dbl,
					   pVals[2].data.dbl, pVals[3].data.dbl,
					   pVals[4].data.dbl, pVals[5].data.dbl,
					   pVals[6].data.dbl );
	    break;
	 case elps_fct:
	    this->value.data.log =
                               ellipse( pVals[0].data.dbl, pVals[1].data.dbl,
					pVals[2].data.dbl, pVals[3].data.dbl,
					pVals[4].data.dbl, pVals[5].data.dbl,
					pVals[6].data.dbl );
	    break;

            /* C Conditional expression:  bool ? expr : expr */

         case ifthenelse_fct:
            switch( this->type ) {
            case BOOLEAN:
               this->value.data.log = ( pVals[2].data.log ?
                                        pVals[0].data.log : pVals[1].data.log );
               break;
            case LONG:
               this->value.data.lng = ( pVals[2].data.log ?
                                        pVals[0].data.lng : pVals[1].data.lng );
               break;
            case DOUBLE:
               this->value.data.dbl = ( pVals[2].data.log ?
                                        pVals[0].data.dbl : pVals[1].data.dbl );
               break;
            case STRING:
	       strcpy(this->value.data.str, ( pVals[2].data.log ?
                                              pVals[0].data.str :
                                              pVals[1].data.str ) );
               break;
            }
            break;

	    /* String functions */
         case strmid_fct:
	   cstrmid(lParse, 
		   this->value.data.str, this->value.nelem, 
		   pVals[0].data.str,    pVals[0].nelem,
		   pVals[1].data.lng);
	   break;
         case strpos_fct:
	   {
	     char *res = strstr(pVals[0].data.str, pVals[1].data.str);
	     if (res == NULL) {
	       this->value.data.lng = 0; 
	     } else {
	       this->value.data.lng = (res - pVals[0].data.str) + 1;
	     }
	     break;
	   }

      }
      this->operation = CONST_OP;

   } else {

     Allocate_Ptrs( lParse, this );

      row  = lParse->nRows;
      elem = row * this->value.nelem;

      if( !lParse->status ) {
	 switch( this->operation ) {

	    /* Special functions with no arguments */

	 case row_fct:
	    while( row-- ) {
	       this->value.data.lngptr[row] = lParse->firstRow + row;
	       this->value.undef[row] = 0;
	    }
	    break;
	 case null_fct:
            if( this->type==LONG ) {
               while( row-- ) {
                  this->value.data.lngptr[row] = 0;
                  this->value.undef[row] = 1;
               }
            } else if( this->type==STRING ) {
               while( row-- ) {
                  this->value.data.strptr[row][0] = '\0';
                  this->value.undef[row] = 1;
               }
            }
	    break;
	 case axiselem_fct:
	   {
	     long ielem;
	     long iaxis[MAXDIMS] = {1, 1, 1, 1, 1};
	     long ipos = pVals[1].data.lng - 1; /* This should be a constant long value */
	     int naxis = this->value.naxis;
	     int j;
	     if (ipos < 0 || ipos >= MAXDIMS) {
	         yyerror(0, lParse, "AXISELEM(V,n) n value exceeded maximum dimension");
		 free( this->value.data.ptr );
		 break;
	     }

	     for (ielem = 0; ielemvalue.data.lngptr[ielem] = iaxis[ipos];
	       this->value.undef[ielem] = 0;
	       iaxis[0]++;
	       for (j = 0; j < naxis; j++) {
		 if (iaxis[j] > this->value.naxes[j]) { 
		   iaxis[j] = 1; 
		   if (j < (naxis-1)) iaxis[j+1]++;
		 } else {
		   break;
		 }
	       }

	     }
	   }
	   break;
	 case elemnum_fct:
	   {
	     long ielem;
	     long elemnum = 1;
	     int j;

	     for (ielem = 0; ielemvalue.data.lngptr[ielem] = elemnum;
	       this->value.undef[ielem] = 0;
	       elemnum ++;
	       if (elemnum > this->value.nelem) elemnum = 1;
	     }
	   }
	   break;
	 case rnd_fct:
	   while( elem-- ) {
	     this->value.data.dblptr[elem] = simplerng_getuniform();
	     this->value.undef[elem] = 0;
	    }
	    break;

	 case gasrnd_fct:
	    while( elem-- ) {
	       this->value.data.dblptr[elem] = simplerng_getnorm();
	       this->value.undef[elem] = 0;
	    }
	    break;

	 case poirnd_fct:
	   if( theParams[0]->type==DOUBLE ) {
	      if (theParams[0]->operation == CONST_OP) {
		while( elem-- ) {
		  this->value.undef[elem] = (pVals[0].data.dbl < 0);
		  if (! this->value.undef[elem]) {
		    this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.dbl);
		  }
		} 
	      } else {
		while( elem-- ) {
		  this->value.undef[elem] = theParams[0]->value.undef[elem];
		  if (theParams[0]->value.data.dblptr[elem] < 0) 
		    this->value.undef[elem] = 1;
		  if (! this->value.undef[elem]) {
		    this->value.data.lngptr[elem] = 
		      simplerng_getpoisson(theParams[0]->value.data.dblptr[elem]);
		  }
		} /* while */
	      } /* ! CONST_OP */
	   } else {
	     /* LONG */
	      if (theParams[0]->operation == CONST_OP) {
		while( elem-- ) {
		  this->value.undef[elem] = (pVals[0].data.lng < 0);
		  if (! this->value.undef[elem]) {
		    this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.lng);
		  }
		} 
	      } else {
		while( elem-- ) {
		  this->value.undef[elem] = theParams[0]->value.undef[elem];
		  if (theParams[0]->value.data.lngptr[elem] < 0) 
		    this->value.undef[elem] = 1;
		  if (! this->value.undef[elem]) {
		    this->value.data.lngptr[elem] = 
		      simplerng_getpoisson(theParams[0]->value.data.lngptr[elem]);
		  }
		} /* while */
	      } /* ! CONST_OP */
	   } /* END LONG */
	   break;


	    /* Non-Trig single-argument functions */
	    
	 case sum_fct:
	    elem = row * theParams[0]->value.nelem;
	    if( theParams[0]->type==BOOLEAN ) {
	       while( row-- ) {
		  this->value.data.lngptr[row] = 0;
		  /* Default is UNDEF until a defined value is found */
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( ! theParams[0]->value.undef[elem] ) {
		       this->value.data.lngptr[row] +=
			 ( theParams[0]->value.data.logptr[elem] ? 1 : 0 );
		       this->value.undef[row] = 0;
		     }
		  }
	       }
	    } else if( theParams[0]->type==LONG ) {
	       while( row-- ) {
		  this->value.data.lngptr[row] = 0;
		  /* Default is UNDEF until a defined value is found */
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( ! theParams[0]->value.undef[elem] ) {
		       this->value.data.lngptr[row] +=
			 theParams[0]->value.data.lngptr[elem];
		       this->value.undef[row] = 0;
		     }
		  }
	       }		  
	    } else if( theParams[0]->type==DOUBLE ){
	       while( row-- ) {
		  this->value.data.dblptr[row] = 0.0;
		  /* Default is UNDEF until a defined value is found */
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( ! theParams[0]->value.undef[elem] ) {
		       this->value.data.dblptr[row] +=
			 theParams[0]->value.data.dblptr[elem];
		       this->value.undef[row] = 0;
		     }
		  }
	       }		  
	    } else { /* BITSTR */
	       nelem = theParams[0]->value.nelem;
	       while( row-- ) {
		  char *sptr1 = theParams[0]->value.data.strptr[row];
		  this->value.data.lngptr[row] = 0;
		  this->value.undef[row] = 0;
		  while (*sptr1) {
		    if (*sptr1 == '1') this->value.data.lngptr[row] ++;
		    sptr1++;
		  }
	       }		  
	    }
	    break;

	 case average_fct:
	    elem = row * theParams[0]->value.nelem;
	    if( theParams[0]->type==LONG ) {
	       while( row-- ) {
		  int count = 0;
		  this->value.data.dblptr[row] = 0;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if (theParams[0]->value.undef[elem] == 0) {
		       this->value.data.dblptr[row] +=
			 theParams[0]->value.data.lngptr[elem];
		       count ++;
		     }
		  }
		  if (count == 0) {
		    this->value.undef[row] = 1;
		  } else {
		    this->value.undef[row] = 0;
		    this->value.data.dblptr[row] /= count;
		  }
	       }		  
	    } else if( theParams[0]->type==DOUBLE ){
	       while( row-- ) {
		  int count = 0;
		  this->value.data.dblptr[row] = 0;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if (theParams[0]->value.undef[elem] == 0) {
		       this->value.data.dblptr[row] +=
			 theParams[0]->value.data.dblptr[elem];
		       count ++;
		     }
		  }
		  if (count == 0) {
		    this->value.undef[row] = 1;
		  } else {
		    this->value.undef[row] = 0;
		    this->value.data.dblptr[row] /= count;
		  }
	       }		  
	    }
	    break;
	 case stddev_fct:
	    elem = row * theParams[0]->value.nelem;
	    if( theParams[0]->type==LONG ) {

	       /* Compute the mean value */
	       while( row-- ) {
		  int count = 0;
		  double sum = 0, sum2 = 0;

		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if (theParams[0]->value.undef[elem] == 0) {
		       sum += theParams[0]->value.data.lngptr[elem];
		       count ++;
		     }
		  }
		  if (count > 1) {
		    sum /= count;

		    /* Compute the sum of squared deviations */
		    nelem = theParams[0]->value.nelem;
		    elem += nelem;  /* Reset elem for second pass */
		    while( nelem-- ) {
		      elem--;
		      if (theParams[0]->value.undef[elem] == 0) {
			double dx = (theParams[0]->value.data.lngptr[elem] - sum);
			sum2 += (dx*dx);
		      }
		    }

		    sum2 /= (double)count-1;

		    this->value.undef[row] = 0;
		    this->value.data.dblptr[row] = sqrt(sum2);
		  } else {
		    this->value.undef[row] = 0;       /* STDDEV => 0 */
		    this->value.data.dblptr[row] = 0;
		  }
	       }
	    } else if( theParams[0]->type==DOUBLE ){

	       /* Compute the mean value */
	       while( row-- ) {
		  int count = 0;
		  double sum = 0, sum2 = 0;

		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if (theParams[0]->value.undef[elem] == 0) {
		       sum += theParams[0]->value.data.dblptr[elem];
		       count ++;
		     }
		  }
		  if (count > 1) {
		    sum /= count;

		    /* Compute the sum of squared deviations */
		    nelem = theParams[0]->value.nelem;
		    elem += nelem;  /* Reset elem for second pass */
		    while( nelem-- ) {
		      elem--;
		      if (theParams[0]->value.undef[elem] == 0) {
			double dx = (theParams[0]->value.data.dblptr[elem] - sum);
			sum2 += (dx*dx);
		      }
		    }

		    sum2 /= (double)count-1;

		    this->value.undef[row] = 0;
		    this->value.data.dblptr[row] = sqrt(sum2);
		  } else {
		    this->value.undef[row] = 0;       /* STDDEV => 0 */
		    this->value.data.dblptr[row] = 0;
		  }
	       }
	    }
	    break;

	 case median_fct:
	   elem = row * theParams[0]->value.nelem;
	   nelem = theParams[0]->value.nelem;
	   if( theParams[0]->type==LONG ) {
	       long *dptr = theParams[0]->value.data.lngptr;
	       char *uptr = theParams[0]->value.undef;
	       long *mptr = (long *) malloc(sizeof(long)*nelem);
	       int irow;

	       /* Allocate temporary storage for this row, since the
                  quickselect function will scramble the contents */
	       if (mptr == 0) {
		 yyerror(0, lParse, "Could not allocate temporary memory in median function");
		 free( this->value.data.ptr );
		 break;
	       }

	       for (irow=0; irow 0) {
		    this->value.undef[irow] = 0;
		    this->value.data.lngptr[irow] = qselect_median_lng(mptr, nelem1);
		  } else {
		    this->value.undef[irow] = 1;
		    this->value.data.lngptr[irow] = 0;
		  }
		    
	       }		  

	       free(mptr);
	    } else {
	       double *dptr = theParams[0]->value.data.dblptr;
	       char   *uptr = theParams[0]->value.undef;
	       double *mptr = (double *) malloc(sizeof(double)*nelem);
	       int irow;

	       /* Allocate temporary storage for this row, since the
                  quickselect function will scramble the contents */
	       if (mptr == 0) {
		 yyerror(0, lParse, "Could not allocate temporary memory in median function");
		 free( this->value.data.ptr );
		 break;
	       }

	       for (irow=0; irow 0) {
		    this->value.undef[irow] = 0;
		    this->value.data.dblptr[irow] = qselect_median_dbl(mptr, nelem1);
		  } else {
		    this->value.undef[irow] = 1;
		    this->value.data.dblptr[irow] = 0;
		  }

	       }
	       free(mptr);
	    }
	    break;
	 case abs_fct:
	    if( theParams[0]->type==DOUBLE )
	       while( elem-- ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  this->value.data.dblptr[elem] = (dval>0.0 ? dval : -dval);
		  this->value.undef[elem] = theParams[0]->value.undef[elem];
	       }
	    else
	       while( elem-- ) {
		  ival = theParams[0]->value.data.lngptr[elem];
		  this->value.data.lngptr[elem] = (ival> 0  ? ival : -ival);
		  this->value.undef[elem] = theParams[0]->value.undef[elem];
	       }
	    break;

            /* Special Null-Handling Functions */

	 case nonnull_fct:
	   nelem = theParams[0]->value.nelem;
	   if ( theParams[0]->type==STRING ) nelem = 1;
	   elem = row * nelem;
	   while( row-- ) {
	     int nelem1 = nelem;

	     this->value.undef[row] = 0;        /* Initialize to 0 (defined) */
	     this->value.data.lngptr[row] = 0;
	     while( nelem1-- ) {	
	       elem --;
	       if ( theParams[0]->value.undef[elem] == 0 ) this->value.data.lngptr[row] ++;
	     }
	   }
	   break;
	 case isnull_fct:
	    if( theParams[0]->type==STRING ) elem = row;
	    while( elem-- ) {
	       this->value.data.logptr[elem] = theParams[0]->value.undef[elem];
	       this->value.undef[elem] = 0;
	    }
	    break;
         case defnull_fct:
	    switch( this->type ) {
	    case BOOLEAN:
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pNull[i] = theParams[i]->value.undef[elem];
			   pVals[i].data.log =
			      theParams[i]->value.data.logptr[elem];
			} else if( vector[i] ) {
			   pNull[i] = theParams[i]->value.undef[row];
			   pVals[i].data.log =
			      theParams[i]->value.data.logptr[row];
			}
		     if( pNull[0] ) {
			this->value.undef[elem] = pNull[1];
			this->value.data.logptr[elem] = pVals[1].data.log;
		     } else {
			this->value.undef[elem] = 0;
			this->value.data.logptr[elem] = pVals[0].data.log;
		     }
		  }
	       }
	       break;
	    case LONG:
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pNull[i] = theParams[i]->value.undef[elem];
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[elem];
			} else if( vector[i] ) {
			   pNull[i] = theParams[i]->value.undef[row];
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[row];
			}
		     if( pNull[0] ) {
			this->value.undef[elem] = pNull[1];
			this->value.data.lngptr[elem] = pVals[1].data.lng;
		     } else {
			this->value.undef[elem] = 0;
			this->value.data.lngptr[elem] = pVals[0].data.lng;
		     }
		  }
	       }
	       break;
	    case DOUBLE:
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pNull[i] = theParams[i]->value.undef[elem];
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[elem];
			} else if( vector[i] ) {
			   pNull[i] = theParams[i]->value.undef[row];
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[row];
			}
		     if( pNull[0] ) {
			this->value.undef[elem] = pNull[1];
			this->value.data.dblptr[elem] = pVals[1].data.dbl;
		     } else {
			this->value.undef[elem] = 0;
			this->value.data.dblptr[elem] = pVals[0].data.dbl;
		     }
		  }
	       }
	       break;
	    case STRING:
	       while( row-- ) {
		  i=2; while( i-- )
		     if( vector[i] ) {
			pNull[i] = theParams[i]->value.undef[row];
			strcpy(pVals[i].data.str,
			       theParams[i]->value.data.strptr[row]);
		     }
		  if( pNull[0] ) {
		     this->value.undef[row] = pNull[1];
		     strcpy(this->value.data.strptr[row],pVals[1].data.str);
		  } else {
		     this->value.undef[elem] = 0;
		     strcpy(this->value.data.strptr[row],pVals[0].data.str);
		  }
	       }
	    }
	    break;
         case setnull_fct:
	    switch( this->type ) {
	    case LONG:
	      while( elem-- ) {
		if ( theParams[1]->value.data.lng == 
		     theParams[0]->value.data.lngptr[elem] ) {
		  this->value.data.lngptr[elem] = 0;
		  this->value.undef[elem] = 1;
		} else {
		  this->value.data.lngptr[elem] = theParams[0]->value.data.lngptr[elem];
		  this->value.undef[elem] = theParams[0]->value.undef[elem];
		}
	      }
	      break;
	    case DOUBLE:
	      while( elem-- ) {
		if ( theParams[1]->value.data.dbl == 
		     theParams[0]->value.data.dblptr[elem] ) {
		  this->value.data.dblptr[elem] = 0;
		  this->value.undef[elem] = 1;
		} else {
		  this->value.data.dblptr[elem] = theParams[0]->value.data.dblptr[elem];
		  this->value.undef[elem] = theParams[0]->value.undef[elem];
		}
	      }
	      break;
	    }
	    break;

	    /* Math functions with 1 double argument */

	 case sin_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     sin( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case cos_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     cos( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case tan_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     tan( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case asin_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  if( dval<-1.0 || dval>1.0 ) {
		     this->value.data.dblptr[elem] = 0.0;
		     this->value.undef[elem] = 1;
		  } else
		     this->value.data.dblptr[elem] = asin( dval );
	       }
	    break;
	 case acos_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  if( dval<-1.0 || dval>1.0 ) {
		     this->value.data.dblptr[elem] = 0.0;
		     this->value.undef[elem] = 1;
		  } else
		     this->value.data.dblptr[elem] = acos( dval );
	       }
	    break;
	 case atan_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  this->value.data.dblptr[elem] = atan( dval );
	       }
	    break;
	 case sinh_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     sinh( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case cosh_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     cosh( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case tanh_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     tanh( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case exp_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  this->value.data.dblptr[elem] = exp( dval );
	       }
	    break;
	 case log_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  if( dval<=0.0 ) {
		     this->value.data.dblptr[elem] = 0.0;
		     this->value.undef[elem] = 1;
		  } else
		     this->value.data.dblptr[elem] = log( dval );
	       }
	    break;
	 case log10_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  if( dval<=0.0 ) {
		     this->value.data.dblptr[elem] = 0.0;
		     this->value.undef[elem] = 1;
		  } else
		     this->value.data.dblptr[elem] = log10( dval );
	       }
	    break;
	 case sqrt_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  dval = theParams[0]->value.data.dblptr[elem];
		  if( dval<0.0 ) {
		     this->value.data.dblptr[elem] = 0.0;
		     this->value.undef[elem] = 1;
		  } else
		     this->value.data.dblptr[elem] = sqrt( dval );
	       }
	    break;
	 case ceil_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     ceil( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case floor_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     floor( theParams[0]->value.data.dblptr[elem] );
	       }
	    break;
	 case round_fct:
	    while( elem-- )
	       if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
		  this->value.data.dblptr[elem] = 
		     floor( theParams[0]->value.data.dblptr[elem] + 0.5);
	       }
	    break;

	    /* Two-argument Trig Functions */
	    
	 case atan2_fct:
	    while( row-- ) {
	       nelem = this->value.nelem;
	       while( nelem-- ) {
		  elem--;
		  i=2; while( i-- )
		     if( vector[i]>1 ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[elem];
			pNull[i] = theParams[i]->value.undef[elem];
		     } else if( vector[i] ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[row];
			pNull[i] = theParams[i]->value.undef[row];
		     }
		  if( !(this->value.undef[elem] = (pNull[0] || pNull[1]) ) )
		     this->value.data.dblptr[elem] =
			atan2( pVals[0].data.dbl, pVals[1].data.dbl );
	       }
	    }
	    break;

	    /* Four-argument ANGSEP Function */
	    
	 case angsep_fct:
	    while( row-- ) {
	       nelem = this->value.nelem;
	       while( nelem-- ) {
		  elem--;
		  i=4; while( i-- )
		     if( vector[i]>1 ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[elem];
			pNull[i] = theParams[i]->value.undef[elem];
		     } else if( vector[i] ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[row];
			pNull[i] = theParams[i]->value.undef[row];
		     }
		  if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
						   pNull[2] || pNull[3]) ) )
		     this->value.data.dblptr[elem] =
		       angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl,
				   pVals[2].data.dbl, pVals[3].data.dbl);
	       }
	    }
	    break;



	    /*  Min/Max functions taking 1 or 2 arguments  */

         case min1_fct:
	    elem = row * theParams[0]->value.nelem;
	    if( this->type==LONG ) {
	       long minVal=0;
	       while( row-- ) {
		  valInit = 1;
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( !theParams[0]->value.undef[elem] ) {
		       if ( valInit ) {
			 valInit = 0;
			 minVal  = theParams[0]->value.data.lngptr[elem];
		       } else {
			 minVal  = minvalue( minVal,
					     theParams[0]->value.data.lngptr[elem] );
		       }
		       this->value.undef[row] = 0;
		     }
		  }  
		  this->value.data.lngptr[row] = minVal;
	       }		  
	    } else if( this->type==DOUBLE ) {
	       double minVal=0.0;
	       while( row-- ) {
		  valInit = 1;
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( !theParams[0]->value.undef[elem] ) {
		       if ( valInit ) {
			 valInit = 0;
			 minVal  = theParams[0]->value.data.dblptr[elem];
		       } else {
			 minVal  = minvalue( minVal,
					     theParams[0]->value.data.dblptr[elem] );
		       }
		       this->value.undef[row] = 0;
		     }
		  }  
		  this->value.data.dblptr[row] = minVal;
	       }		  
	    } else if( this->type==BITSTR ) {
	       char minVal;
	       while( row-- ) {
		  char *sptr1 = theParams[0]->value.data.strptr[row];
		  minVal = '1';
		  while (*sptr1) {
		    if (*sptr1 == '0') minVal = '0';
		    sptr1++;
		  }
		  this->value.data.strptr[row][0] = minVal;
		  this->value.data.strptr[row][1] = 0;     /* Null terminate */
	       }		  
	    }
	    break;
         case min2_fct:
	    if( this->type==LONG ) {
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( pNull[0] && pNull[1] ) {
		       this->value.undef[elem] = 1;
		       this->value.data.lngptr[elem] = 0;
		     } else if (pNull[0]) {
		       this->value.undef[elem] = 0;
		       this->value.data.lngptr[elem] = pVals[1].data.lng;
		     } else if (pNull[1]) {
		       this->value.undef[elem] = 0;
		       this->value.data.lngptr[elem] = pVals[0].data.lng;
		     } else {
		       this->value.undef[elem] = 0;
		       this->value.data.lngptr[elem] =
			 minvalue( pVals[0].data.lng, pVals[1].data.lng );
		     }
		  }
	       }
	    } else if( this->type==DOUBLE ) {
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( pNull[0] && pNull[1] ) {
		       this->value.undef[elem] = 1;
		       this->value.data.dblptr[elem] = 0;
		     } else if (pNull[0]) {
		       this->value.undef[elem] = 0;
		       this->value.data.dblptr[elem] = pVals[1].data.dbl;
		     } else if (pNull[1]) {
		       this->value.undef[elem] = 0;
		       this->value.data.dblptr[elem] = pVals[0].data.dbl;
		     } else {
		       this->value.undef[elem] = 0;
		       this->value.data.dblptr[elem] =
			 minvalue( pVals[0].data.dbl, pVals[1].data.dbl );
		     }
		  }
 	       }
	    }
	    break;

         case max1_fct:
	    elem = row * theParams[0]->value.nelem;
	    if( this->type==LONG ) {
	       long maxVal=0;
	       while( row-- ) {
		  valInit = 1;
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( !theParams[0]->value.undef[elem] ) {
		       if ( valInit ) {
			 valInit = 0;
			 maxVal  = theParams[0]->value.data.lngptr[elem];
		       } else {
			 maxVal  = maxvalue( maxVal,
					     theParams[0]->value.data.lngptr[elem] );
		       }
		       this->value.undef[row] = 0;
		     }
		  }
		  this->value.data.lngptr[row] = maxVal;
	       }		  
	    } else if( this->type==DOUBLE ) {
	       double maxVal=0.0;
	       while( row-- ) {
		  valInit = 1;
		  this->value.undef[row] = 1;
		  nelem = theParams[0]->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     if ( !theParams[0]->value.undef[elem] ) {
		       if ( valInit ) {
			 valInit = 0;
			 maxVal  = theParams[0]->value.data.dblptr[elem];
		       } else {
			 maxVal  = maxvalue( maxVal,
					     theParams[0]->value.data.dblptr[elem] );
		       }
		       this->value.undef[row] = 0;
		     }
		  }
		  this->value.data.dblptr[row] = maxVal;
	       }		  
	    } else if( this->type==BITSTR ) {
	       char maxVal;
	       while( row-- ) {
		  char *sptr1 = theParams[0]->value.data.strptr[row];
		  maxVal = '0';
		  while (*sptr1) {
		    if (*sptr1 == '1') maxVal = '1';
		    sptr1++;
		  }
		  this->value.data.strptr[row][0] = maxVal;
		  this->value.data.strptr[row][1] = 0;     /* Null terminate */
	       }		  
	    }
	    break;
         case max2_fct:
	    if( this->type==LONG ) {
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( pNull[0] && pNull[1] ) {
		       this->value.undef[elem] = 1;
		       this->value.data.lngptr[elem] = 0;
		     } else if (pNull[0]) {
		       this->value.undef[elem] = 0;
		       this->value.data.lngptr[elem] = pVals[1].data.lng;
		     } else if (pNull[1]) {
		       this->value.undef[elem] = 0;
		       this->value.data.lngptr[elem] = pVals[0].data.lng;
		     } else {
		       this->value.undef[elem] = 0;
		       this->value.data.lngptr[elem] =
			 maxvalue( pVals[0].data.lng, pVals[1].data.lng );
		     }
		  }
	       }
	    } else if( this->type==DOUBLE ) {
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( pNull[0] && pNull[1] ) {
		       this->value.undef[elem] = 1;
		       this->value.data.dblptr[elem] = 0;
		     } else if (pNull[0]) {
		       this->value.undef[elem] = 0;
		       this->value.data.dblptr[elem] = pVals[1].data.dbl;
		     } else if (pNull[1]) {
		       this->value.undef[elem] = 0;
		       this->value.data.dblptr[elem] = pVals[0].data.dbl;
		     } else {
		       this->value.undef[elem] = 0;
		       this->value.data.dblptr[elem] =
			 maxvalue( pVals[0].data.dbl, pVals[1].data.dbl );
		     }
		  }
	       }
	    }
	    break;

	    /* Boolean SAO region Functions... scalar or vector dbls */

	 case near_fct:
	    while( row-- ) {
	       nelem = this->value.nelem;
	       while( nelem-- ) {
		  elem--;
		  i=3; while( i-- )
		     if( vector[i]>1 ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[elem];
			pNull[i] = theParams[i]->value.undef[elem];
		     } else if( vector[i] ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[row];
			pNull[i] = theParams[i]->value.undef[row];
		     }
		  if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
						   pNull[2]) ) )
		    this->value.data.logptr[elem] =
		      bnear( pVals[0].data.dbl, pVals[1].data.dbl,
			     pVals[2].data.dbl );
	       }
	    }
	    break;

	 case circle_fct:
	    while( row-- ) {
	       nelem = this->value.nelem;
	       while( nelem-- ) {
		  elem--;
		  i=5; while( i-- )
		     if( vector[i]>1 ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[elem];
			pNull[i] = theParams[i]->value.undef[elem];
		     } else if( vector[i] ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[row];
			pNull[i] = theParams[i]->value.undef[row];
		     }
		  if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
						   pNull[2] || pNull[3] ||
						   pNull[4]) ) )
		    this->value.data.logptr[elem] =
		     circle( pVals[0].data.dbl, pVals[1].data.dbl,
			     pVals[2].data.dbl, pVals[3].data.dbl,
			     pVals[4].data.dbl );
	       }
	    }
	    break;

	 case box_fct:
	    while( row-- ) {
	       nelem = this->value.nelem;
	       while( nelem-- ) {
		  elem--;
		  i=7; while( i-- )
		     if( vector[i]>1 ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[elem];
			pNull[i] = theParams[i]->value.undef[elem];
		     } else if( vector[i] ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[row];
			pNull[i] = theParams[i]->value.undef[row];
		     }
		  if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
						   pNull[2] || pNull[3] ||
						   pNull[4] || pNull[5] ||
						   pNull[6] ) ) )
		    this->value.data.logptr[elem] =
		     saobox( pVals[0].data.dbl, pVals[1].data.dbl,
			     pVals[2].data.dbl, pVals[3].data.dbl,
			     pVals[4].data.dbl, pVals[5].data.dbl,
			     pVals[6].data.dbl );	
	       }
	    }
	    break;

	 case elps_fct:
	    while( row-- ) {
	       nelem = this->value.nelem;
	       while( nelem-- ) {
		  elem--;
		  i=7; while( i-- )
		     if( vector[i]>1 ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[elem];
			pNull[i] = theParams[i]->value.undef[elem];
		     } else if( vector[i] ) {
			pVals[i].data.dbl =
			   theParams[i]->value.data.dblptr[row];
			pNull[i] = theParams[i]->value.undef[row];
		     }
		  if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
						   pNull[2] || pNull[3] ||
						   pNull[4] || pNull[5] ||
						   pNull[6] ) ) )
		    this->value.data.logptr[elem] =
		     ellipse( pVals[0].data.dbl, pVals[1].data.dbl,
			      pVals[2].data.dbl, pVals[3].data.dbl,
			      pVals[4].data.dbl, pVals[5].data.dbl,
			      pVals[6].data.dbl );
	       }
	    }
	    break;

            /* C Conditional expression:  bool ? expr : expr */

         case ifthenelse_fct:
            switch( this->type ) {
            case BOOLEAN:
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
                     if( vector[2]>1 ) {
                        pVals[2].data.log =
                           theParams[2]->value.data.logptr[elem];
                        pNull[2] = theParams[2]->value.undef[elem];
                     } else if( vector[2] ) {
                        pVals[2].data.log =
                           theParams[2]->value.data.logptr[row];
                        pNull[2] = theParams[2]->value.undef[row];
                     }
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.log =
			      theParams[i]->value.data.logptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.log =
			      theParams[i]->value.data.logptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( !(this->value.undef[elem] = pNull[2]) ) {
                        if( pVals[2].data.log ) {
                           this->value.data.logptr[elem] = pVals[0].data.log;
                           this->value.undef[elem]       = pNull[0];
                        } else {
                           this->value.data.logptr[elem] = pVals[1].data.log;
                           this->value.undef[elem]       = pNull[1];
                        }
                     }
		  }
	       }
               break;
            case LONG:
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
                     if( vector[2]>1 ) {
                        pVals[2].data.log =
                           theParams[2]->value.data.logptr[elem];
                        pNull[2] = theParams[2]->value.undef[elem];
                     } else if( vector[2] ) {
                        pVals[2].data.log =
                           theParams[2]->value.data.logptr[row];
                        pNull[2] = theParams[2]->value.undef[row];
                     }
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.lng =
			      theParams[i]->value.data.lngptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( !(this->value.undef[elem] = pNull[2]) ) {
                        if( pVals[2].data.log ) {
                           this->value.data.lngptr[elem] = pVals[0].data.lng;
                           this->value.undef[elem]       = pNull[0];
                        } else {
                           this->value.data.lngptr[elem] = pVals[1].data.lng;
                           this->value.undef[elem]       = pNull[1];
                        }
                     }
		  }
	       }
               break;
            case DOUBLE:
	       while( row-- ) {
		  nelem = this->value.nelem;
		  while( nelem-- ) {
		     elem--;
                     if( vector[2]>1 ) {
                        pVals[2].data.log =
                           theParams[2]->value.data.logptr[elem];
                        pNull[2] = theParams[2]->value.undef[elem];
                     } else if( vector[2] ) {
                        pVals[2].data.log =
                           theParams[2]->value.data.logptr[row];
                        pNull[2] = theParams[2]->value.undef[row];
                     }
		     i=2; while( i-- )
			if( vector[i]>1 ) {
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[elem];
			   pNull[i] = theParams[i]->value.undef[elem];
			} else if( vector[i] ) {
			   pVals[i].data.dbl =
			      theParams[i]->value.data.dblptr[row];
			   pNull[i] = theParams[i]->value.undef[row];
			}
		     if( !(this->value.undef[elem] = pNull[2]) ) {
                        if( pVals[2].data.log ) {
                           this->value.data.dblptr[elem] = pVals[0].data.dbl;
                           this->value.undef[elem]       = pNull[0];
                        } else {
                           this->value.data.dblptr[elem] = pVals[1].data.dbl;
                           this->value.undef[elem]       = pNull[1];
                        }
                     }
		  }
	       }
               break;
            case STRING:
	       while( row-- ) {
                  if( vector[2] ) {
                     pVals[2].data.log = theParams[2]->value.data.logptr[row];
                     pNull[2] = theParams[2]->value.undef[row];
                  }
                  i=2; while( i-- )
                     if( vector[i] ) {
                        strcpy( pVals[i].data.str,
                                theParams[i]->value.data.strptr[row] );
                        pNull[i] = theParams[i]->value.undef[row];
                     }
                  if( !(this->value.undef[row] = pNull[2]) ) {
                     if( pVals[2].data.log ) {
                        strcpy( this->value.data.strptr[row],
                                pVals[0].data.str );
                        this->value.undef[row]       = pNull[0];
                     } else {
                        strcpy( this->value.data.strptr[row],
                                pVals[1].data.str );
                        this->value.undef[row]       = pNull[1];
                     }
                  } else {
                     this->value.data.strptr[row][0] = '\0';
                  }
	       }
               break;

            }
            break;

	    /* String functions */
            case strmid_fct:
	      {
		int strconst = theParams[0]->operation == CONST_OP;
		int posconst = theParams[1]->operation == CONST_OP;
		int lenconst = theParams[2]->operation == CONST_OP;
		int dest_len = this->value.nelem;
		int src_len  = theParams[0]->value.nelem;

		while (row--) {
		  int pos;
		  int len;
		  char *str;
		  int undef = 0;

		  if (posconst) {
		    pos = theParams[1]->value.data.lng;
		  } else {
		    pos = theParams[1]->value.data.lngptr[row];
		    if (theParams[1]->value.undef[row]) undef = 1;
		  }
		  if (strconst) {
		    str = theParams[0]->value.data.str;
		    if (src_len == 0) src_len = strlen(str);
		  } else {
		    str = theParams[0]->value.data.strptr[row];
		    if (theParams[0]->value.undef[row]) undef = 1;
		  }
		  if (lenconst) {
		    len = dest_len;
		  } else {
		    len = theParams[2]->value.data.lngptr[row];
		    if (theParams[2]->value.undef[row]) undef = 1;
		  }
		  this->value.data.strptr[row][0] = '\0';
		  if (pos == 0) undef = 1;
		  if (! undef ) {
		    if (cstrmid(lParse,
				this->value.data.strptr[row], len,
				str, src_len, pos) < 0) break;
		  }
		  this->value.undef[row] = undef;
		}
	      }		      
	      break;

	    /* String functions */
            case strpos_fct:
	      {
		int const1 = theParams[0]->operation == CONST_OP;
		int const2 = theParams[1]->operation == CONST_OP;

		while (row--) {
		  char *str1, *str2;
		  int undef = 0;

		  if (const1) {
		    str1 = theParams[0]->value.data.str;
		  } else {
		    str1 = theParams[0]->value.data.strptr[row];
		    if (theParams[0]->value.undef[row]) undef = 1;
		  }
		  if (const2) {
		    str2 = theParams[1]->value.data.str;
		  } else {
		    str2 = theParams[1]->value.data.strptr[row];
		    if (theParams[1]->value.undef[row]) undef = 1;
		  }
		  this->value.data.lngptr[row] = 0;
		  if (! undef ) {
		    char *res = strstr(str1, str2);
		    if (res == NULL) {
		      undef = 1;
		      this->value.data.lngptr[row] = 0; 
		    } else {
		      this->value.data.lngptr[row] = (res - str1) + 1;
		    }
		  }
		  this->value.undef[row] = undef;
		}
	      }
	      break;

		    
	 } /* End switch(this->operation) */
      } /* End if (!lParse->status) */
   } /* End non-constant operations */

   i = this->nSubNodes;
   while( i-- ) {
      if( theParams[i]->operation>0 ) {
	 /*  Currently only numeric params allowed  */
	 free( theParams[i]->value.data.ptr );
      }
   }
}

static void Do_Deref( ParseData *lParse, Node *this )
{
   Node *theVar, *theDims[MAXDIMS];
   int  isConst[MAXDIMS], allConst;
   long dimVals[MAXDIMS];
   int  i, nDims;
   long row, elem, dsize;

   theVar = lParse->Nodes + this->SubNodes[0];

   i = nDims = this->nSubNodes-1;
   allConst = 1;
   while( i-- ) {
      theDims[i] = lParse->Nodes + this->SubNodes[i+1];
      isConst[i] = ( theDims[i]->operation==CONST_OP );
      if( isConst[i] )
	 dimVals[i] = theDims[i]->value.data.lng;
      else
	 allConst = 0;
   }

   if( this->type==DOUBLE ) {
      dsize = sizeof( double );
   } else if( this->type==LONG ) {
      dsize = sizeof( long );
   } else if( this->type==BOOLEAN ) {
      dsize = sizeof( char );
   } else
      dsize = 0;

   Allocate_Ptrs( lParse, this );

   if( !lParse->status ) {

      if( allConst && theVar->value.naxis==nDims ) {

	 /* Dereference completely using constant indices */

	 elem = 0;
	 i    = nDims;
	 while( i-- ) {
	    if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break;
	    elem = theVar->value.naxes[i]*elem + dimVals[i]-1;
	 }
	 if( i<0 ) {
	    for( row=0; rownRows; row++ ) {
	       if( this->type==STRING )
		 this->value.undef[row] = theVar->value.undef[row];
	       else if( this->type==BITSTR ) 
		 this->value.undef;  /* Dummy - BITSTRs do not have undefs */
	       else 
		 this->value.undef[row] = theVar->value.undef[elem];

	       if( this->type==DOUBLE )
		  this->value.data.dblptr[row] = 
		     theVar->value.data.dblptr[elem];
	       else if( this->type==LONG )
		  this->value.data.lngptr[row] = 
		     theVar->value.data.lngptr[elem];
	       else if( this->type==BOOLEAN )
		  this->value.data.logptr[row] = 
		     theVar->value.data.logptr[elem];
	       else {
		 /* XXX Note, the below expression uses knowledge of
                    the layout of the string format, namely (nelem+1)
                    characters per string, followed by (nelem+1)
                    "undef" values. */
		  this->value.data.strptr[row][0] = 
		     theVar->value.data.strptr[0][elem+row];
		  this->value.data.strptr[row][1] = 0;  /* Null terminate */
	       }
	       elem += theVar->value.nelem;
	    }
	 } else {
	    yyerror(0, lParse, "Index out of range");
	    free( this->value.data.ptr );
	 }
	 
      } else if( allConst && nDims==1 ) {
	 
	 /* Reduce dimensions by 1, using a constant index */
	 
	 if( dimVals[0] < 1 ||
	     dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) {
	    yyerror(0, lParse, "Index out of range");
	    free( this->value.data.ptr );
	 } else if ( this->type == BITSTR || this->type == STRING ) {
	    elem = this->value.nelem * (dimVals[0]-1);
	    for( row=0; rownRows; row++ ) {
	      if (this->value.undef) 
		this->value.undef[row] = theVar->value.undef[row];
	      memcpy( (char*)this->value.data.strptr[0]
		      + row*sizeof(char)*(this->value.nelem+1),
		      (char*)theVar->value.data.strptr[0] + elem*sizeof(char),
		      this->value.nelem * sizeof(char) );
	      /* Null terminate */
	      this->value.data.strptr[row][this->value.nelem] = 0;
	      elem += theVar->value.nelem+1;
	    }	       
	 } else {
	    elem = this->value.nelem * (dimVals[0]-1);
	    for( row=0; rownRows; row++ ) {
	       memcpy( this->value.undef + row*this->value.nelem,
		       theVar->value.undef + elem,
		       this->value.nelem * sizeof(char) );
	       memcpy( (char*)this->value.data.ptr
		       + row*dsize*this->value.nelem,
		       (char*)theVar->value.data.ptr + elem*dsize,
		       this->value.nelem * dsize );
	       elem += theVar->value.nelem;
	    }	       
	 }
      
      } else if( theVar->value.naxis==nDims ) {

	 /* Dereference completely using an expression for the indices */

	 for( row=0; rownRows; row++ ) {

	    for( i=0; ivalue.undef[row] ) {
		     yyerror(0, lParse, "Null encountered as vector index");
		     free( this->value.data.ptr );
		     break;
		  } else
		     dimVals[i] = theDims[i]->value.data.lngptr[row];
	       }
	    }
	    if( lParse->status ) break;

	    elem = 0;
	    i    = nDims;
	    while( i-- ) {
	       if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break;
	       elem = theVar->value.naxes[i]*elem + dimVals[i]-1;
	    }
	    if( i<0 ) {
	       elem += row*theVar->value.nelem;

	       if( this->type==STRING )
		 this->value.undef[row] = theVar->value.undef[row];
	       else if( this->type==BITSTR ) 
		 this->value.undef;  /* Dummy - BITSTRs do not have undefs */
	       else 
		 this->value.undef[row] = theVar->value.undef[elem];

	       if( this->type==DOUBLE )
		  this->value.data.dblptr[row] = 
		     theVar->value.data.dblptr[elem];
	       else if( this->type==LONG )
		  this->value.data.lngptr[row] = 
		     theVar->value.data.lngptr[elem];
	       else if( this->type==BOOLEAN )
		  this->value.data.logptr[row] = 
		     theVar->value.data.logptr[elem];
	       else {
		 /* XXX Note, the below expression uses knowledge of
                    the layout of the string format, namely (nelem+1)
                    characters per string, followed by (nelem+1)
                    "undef" values. */
		  this->value.data.strptr[row][0] = 
		     theVar->value.data.strptr[0][elem+row];
		  this->value.data.strptr[row][1] = 0;  /* Null terminate */
	       }
	    } else {
	       yyerror(0, lParse, "Index out of range");
	       free( this->value.data.ptr );
	    }
	 }

      } else {

	 /* Reduce dimensions by 1, using a nonconstant expression */

	 for( row=0; rownRows; row++ ) {

	    /* Index cannot be a constant */

	    if( theDims[0]->value.undef[row] ) {
	       yyerror(0, lParse, "Null encountered as vector index");
	       free( this->value.data.ptr );
	       break;
	    } else
	       dimVals[0] = theDims[0]->value.data.lngptr[row];

	    if( dimVals[0] < 1 ||
		dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) {
	       yyerror(0, lParse, "Index out of range");
	       free( this->value.data.ptr );
	    } else if ( this->type == BITSTR || this->type == STRING ) {
	      elem = this->value.nelem * (dimVals[0]-1);
	      elem += row*(theVar->value.nelem+1);
	      if (this->value.undef) 
		this->value.undef[row] = theVar->value.undef[row];
	      memcpy( (char*)this->value.data.strptr[0]
		      + row*sizeof(char)*(this->value.nelem+1),
		      (char*)theVar->value.data.strptr[0] + elem*sizeof(char),
		      this->value.nelem * sizeof(char) );
	      /* Null terminate */
	      this->value.data.strptr[row][this->value.nelem] = 0;
	    } else {
	       elem  = this->value.nelem * (dimVals[0]-1);
	       elem += row*theVar->value.nelem;
	       memcpy( this->value.undef + row*this->value.nelem,
		       theVar->value.undef + elem,
		       this->value.nelem * sizeof(char) );
	       memcpy( (char*)this->value.data.ptr
		       + row*dsize*this->value.nelem,
		       (char*)theVar->value.data.ptr + elem*dsize,
		       this->value.nelem * dsize );
	    }
	 }
      }
   }

   if( theVar->operation>0 ) {
     if (theVar->type == STRING || theVar->type == BITSTR) 
       free(theVar->value.data.strptr[0] );
     else 
       free( theVar->value.data.ptr );
   }
   for( i=0; ioperation>0 ) {
	 free( theDims[i]->value.data.ptr );
      }
}

static void Do_GTI( ParseData *lParse, Node *this )
{
   Node *theExpr, *theTimes;
   double *start, *stop, *times;
   long elem, nGTI, gti;
   int ordered;
   int dorow = (this->operation == gtifind_fct);

   theTimes = lParse->Nodes + this->SubNodes[0];
   theExpr  = lParse->Nodes + this->SubNodes[1];

   nGTI    = theTimes->value.nelem;
   start   = theTimes->value.data.dblptr;
   stop    = theTimes->value.data.dblptr + nGTI;
   ordered = theTimes->type;

   if( theExpr->operation==CONST_OP ) {
      gti = Search_GTI( theExpr->value.data.dbl, nGTI, start, stop, ordered, 0 );
      if (dorow) {
	this->value.data.lng = (gti >= 0) ? (gti+1) : -1;
      } else {
	this->value.data.log = (gti>=0);
      }
      this->operation      = CONST_OP;

   } else {

      Allocate_Ptrs( lParse, this );

      times = theExpr->value.data.dblptr;
      if( !lParse->status ) {

	 elem = lParse->nRows * this->value.nelem;
	 if( nGTI ) {
	    gti = -1;
	    while( elem-- ) {
	       if( (this->value.undef[elem] = theExpr->value.undef[elem]) )
		  continue;

            /*  Before searching entire GTI, check the GTI found last time  */
	       if( gti<0 || times[elem]stop[gti] ) {
		 gti = Search_GTI( times[elem], nGTI, start, stop, ordered, 0 );
	       }
	       if (dorow) {
		 this->value.data.lngptr[elem] = ( gti >= 0 ) ? (gti + 1) : (-1);
		 this->value.undef[elem]  = ( gti >= 0 ) ? 0 : 1;
	       } else {
		 this->value.data.logptr[elem] = ( gti>=0 );
	       }
	    }
	 } else { /* nGTI == 0 */

	   if (dorow) { /* no good times so all values are undef */
	     while( elem-- ) {
	       this->value.undef[elem]       = 1;
	     }
	   } else {    /* no good times so all logicals are 0 */
	     while( elem-- ) {
	       this->value.data.logptr[elem] = 0;
	       this->value.undef[elem]       = 0;
	     }
	   }
	   
	 }
      }
   }

   if( theExpr->operation>0 )
      free( theExpr->value.data.ptr );
}

static void Do_GTI_Over( ParseData *lParse, Node *this )
{
   Node *theTimes, *theStart, *theStop;
   double *gtiStart, *gtiStop;
   double *evtStart, *evtStop;
   long elem, nGTI, gti, nextGTI;
   int ordered;

   theTimes = lParse->Nodes + this->SubNodes[0]; /* GTI times */
   theStop  = lParse->Nodes + this->SubNodes[2]; /* User start time */
   theStart = lParse->Nodes + this->SubNodes[1]; /* User stop time */

   nGTI     = theTimes->value.nelem;
   gtiStart = theTimes->value.data.dblptr;        /* GTI start */
   gtiStop  = theTimes->value.data.dblptr + nGTI; /* GTI stop */

   if( theStart->operation==CONST_OP && theStop->operation==CONST_OP) {

      this->value.data.dbl = 
	(GTI_Over( theStart->value.data.dbl, theStop->value.data.dbl,
		   nGTI, gtiStart, gtiStop, >i));
      this->operation      = CONST_OP;

   } else {
      char undefStart = 0, undefStop = 0; /* Input values are undef? */
      double uStart, uStop;       /* User start/stop values */
      if (theStart->operation==CONST_OP) uStart = theStart->value.data.dbl;
      if (theStop ->operation==CONST_OP) uStop  = theStop ->value.data.dbl;

      Allocate_Ptrs( lParse, this );

      evtStart = theStart->value.data.dblptr;
      evtStop  = theStop ->value.data.dblptr;
      if( !lParse->status ) {

	 elem = lParse->nRows * this->value.nelem;
	 if( nGTI ) {
	    double toverlap = 0.0;
	    gti = -1;
	    while( elem-- ) {
	      if (theStart->operation!=CONST_OP) {
		undefStart = theStart->value.undef[elem];
		uStart     = evtStart[elem];
	      }
	      if (theStop->operation!=CONST_OP) {
		undefStop  = theStop ->value.undef[elem];
		uStop      = evtStop[elem];
	      }
	      /* This works because at least one of the values is not const */
	      if( (this->value.undef[elem] = (undefStart||undefStop)) )
		  continue;

            /*  Before searching entire GTI, check the GTI found last time  */
	       if( gti<0 || 
		   uStartgtiStop[gti] ||
		   uStop gtiStop[gti]) {
		 /* Nope, need to recalculate */
		 toverlap = GTI_Over(uStart, uStop, 
				     nGTI, gtiStart, gtiStop, 
				     >i);
	       } else {
		 /* We are in same GTI, the overlap is just stop-start of user range */
		 toverlap = (uStop-uStart);
	       }

	       /* This works because at least one of the values is not const */
	       this->value.data.dblptr[elem] = toverlap;
	    }
	 } else
	    /* nGTI == 0; there is no overlap so set all values to 0.0 */
	    while( elem-- ) {
	       this->value.data.dblptr[elem] = 0.0;
	       this->value.undef[elem]       = 0;
	    }
      }
   }

   if( theStart->operation>0 ) {
     free( theStart->value.data.ptr );
   }
   if( theStop->operation>0 ) {
     free( theStop->value.data.ptr );
   }
}

static double GTI_Over(double evtStart, double evtStop,
		       long nGTI, double *start, double *stop,
		       long *gtiout)
{
  long gti1, gti2, nextGTI1, nextGTI2;
  long gti, nMax;
  double overlap = 0.0;

  *gtiout = -1L;
  /* Zero or negative bin size */
  if (evtStop <= evtStart) return 0.0;

  /* Locate adjacent GTIs for evtStart and evtStop */
  gti1 = Search_GTI(evtStart, nGTI, start, stop, 1, &nextGTI1);
  gti2 = Search_GTI(evtStop,  nGTI, start, stop, 1, &nextGTI2);

  /* evtStart is in gti1, we return that for future processing */
  if (gti1 >= 0) *gtiout = gti1;

  /* Both evtStart/evtStop are beyond the last GTI */
  if (nextGTI1 < 0 && nextGTI2 < 0) return 0.0;

  /* Both evtStart/evtStop are in the same gap between GTIs */
  if (gti1 < 0 && gti2 < 0 && nextGTI1 == nextGTI2) return 0.0;

  /* Both evtStart/evtStop are in the same GTI */
  if (gti1 >= 0 && gti1 == gti2) return (evtStop-evtStart);

  /* Count through the remaining GTIs; there will be at least one */
  /* The largest GTI to consider is either nextGTI2-1, if it exists,
     or nGTI-1 */
  if (nextGTI2 < 0) nMax = nGTI-1;
  else if (gti2 >= 0) nMax = nextGTI2;
  else nMax = nextGTI2-1;
  for (gti = nextGTI1; gti <= nMax; gti++) {
    double starti = start[gti], stopi = stop[gti];
    /* Trim the GTI by actual evtStart/Stop times */
    if (evtStart > starti) starti = evtStart;
    if (evtStop  < stopi ) stopi  = evtStop;
    overlap += (stopi - starti);
  }
    
  return overlap;
}

/*
 * Search_GTI - search GTI for requested evtTime
 * 
 * double evtTime - requested event time
 * long nGTI - number of entries in start[] and stop[]
 * double start[], stop[] - start and stop of each GTI
 * int ordered - set to 1 if time-ordered
 * long *nextGTI0 - upon return, *nextGTI0 is either
 *                   the GTI evtTime is inside
 *                   the next GTI if evtTime is not inside
 *                   -1L if there is no next GTI
 *                   not set if nextGTI0 is a null pointer
 *
 * NOTE: for *nextGTI to be well-defined, the GTI must
 *   be ordered.  This is true when called by Do_GTI.
 *
 * RETURNS: gti index that evtTime is located inside, or -1L
 */
static long Search_GTI( double evtTime, long nGTI, double *start,
			double *stop, int ordered, long *nextGTI0 )
{
   long gti, nextGTI = -1L, step;
                             
   if( ordered && nGTI>15 ) { /*  If time-ordered and lots of GTIs,   */
                              /*  use "FAST" Binary search algorithm  */
      if( evtTime>=start[0] && evtTime<=stop[nGTI-1] ) {
	 gti = step = (nGTI >> 1);
	 while(1) {
	    if( step>1L ) step >>= 1;
	    
	    if( evtTime>stop[gti] ) {
	       if( evtTime>=start[gti+1] )
		  gti += step;
	       else {
		  nextGTI = gti+1;
		  gti = -1L;
		  break;
	       }
	    } else if( evtTime evtTime) nextGTI = 0;
	 gti = -1L;
      }
      
   } else { /*  Use "SLOW" linear search.  Not required to be 
	        ordered, so we have to search the whole table
		no matter what.
	    */
      gti = nGTI;
      while( gti-- ) {
	if( stop[gti] >= evtTime ) nextGTI = gti;
	if( evtTime>=start[gti] && evtTime<=stop[gti] )
	    break;
      }
   }

   if (nextGTI >= nGTI) nextGTI = -1;
   if (nextGTI0) *nextGTI0 = nextGTI;

   return( gti );
}

static void Do_REG( ParseData *lParse, Node *this )
{
   Node *theRegion, *theX, *theY;
   double Xval=0.0, Yval=0.0;
   char   Xnull=0, Ynull=0;
   int    Xvector, Yvector;
   long   nelem, elem, rows;

   theRegion = lParse->Nodes + this->SubNodes[0];
   theX      = lParse->Nodes + this->SubNodes[1];
   theY      = lParse->Nodes + this->SubNodes[2];

   Xvector = ( theX->operation!=CONST_OP );
   if( Xvector )
      Xvector = theX->value.nelem;
   else {
      Xval  = theX->value.data.dbl;
   }

   Yvector = ( theY->operation!=CONST_OP );
   if( Yvector )
      Yvector = theY->value.nelem;
   else {
      Yval  = theY->value.data.dbl;
   } 

   if( !Xvector && !Yvector ) {

      this->value.data.log =
	 ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr )
	   != 0 );
      this->operation      = CONST_OP;

   } else {

      Allocate_Ptrs( lParse, this );

      if( !lParse->status ) {

	 rows  = lParse->nRows;
	 nelem = this->value.nelem;
	 elem  = rows*nelem;

	 while( rows-- ) {
	    while( nelem-- ) {
	       elem--;

	       if( Xvector>1 ) {
		  Xval  = theX->value.data.dblptr[elem];
		  Xnull = theX->value.undef[elem];
	       } else if( Xvector ) {
		  Xval  = theX->value.data.dblptr[rows];
		  Xnull = theX->value.undef[rows];
	       }

	       if( Yvector>1 ) {
		  Yval  = theY->value.data.dblptr[elem];
		  Ynull = theY->value.undef[elem];
	       } else if( Yvector ) {
		  Yval  = theY->value.data.dblptr[rows];
		  Ynull = theY->value.undef[rows];
	       }

	       this->value.undef[elem] = ( Xnull || Ynull );
	       if( this->value.undef[elem] )
		  continue;

	       this->value.data.logptr[elem] = 
		  ( fits_in_region( Xval, Yval,
				    (SAORegion *)theRegion->value.data.ptr )
		    != 0 );
	    }
	    nelem = this->value.nelem;
	 }
      }
   }

   if( theX->operation>0 )
      free( theX->value.data.ptr );
   if( theY->operation>0 )
      free( theY->value.data.ptr );
}

static void Do_Vector( ParseData *lParse, Node *this )
{
   Node *that;
   long row, elem, idx, jdx, offset=0;
   int node;

   Allocate_Ptrs( lParse, this );

   if( !lParse->status ) {

      for( node=0; nodenSubNodes; node++ ) {

	 that = lParse->Nodes + this->SubNodes[node];

	 if( that->operation == CONST_OP ) {

	    idx = lParse->nRows*this->value.nelem + offset;
	    while( (idx-=this->value.nelem)>=0 ) {
	       
	       this->value.undef[idx] = 0;

	       switch( this->type ) {
	       case BOOLEAN:
		  this->value.data.logptr[idx] = that->value.data.log;
		  break;
	       case LONG:
		  this->value.data.lngptr[idx] = that->value.data.lng;
		  break;
	       case DOUBLE:
		  this->value.data.dblptr[idx] = that->value.data.dbl;
		  break;
	       }
	    }
	    
	 } else {
	       
	    row  = lParse->nRows;
	    idx  = row * that->value.nelem;
	    while( row-- ) {
	       elem = that->value.nelem;
	       jdx = row*this->value.nelem + offset;
	       while( elem-- ) {
		  this->value.undef[jdx+elem] =
		     that->value.undef[--idx];

		  switch( this->type ) {
		  case BOOLEAN:
		     this->value.data.logptr[jdx+elem] =
			that->value.data.logptr[idx];
		     break;
		  case LONG:
		     this->value.data.lngptr[jdx+elem] =
			that->value.data.lngptr[idx];
		     break;
		  case DOUBLE:
		     this->value.data.dblptr[jdx+elem] =
			that->value.data.dblptr[idx];
		     break;
		  }
	       }
	    }
	 }
	 offset += that->value.nelem;
      }

   }

   for( node=0; node < this->nSubNodes; node++ )
     if( OPER(this->SubNodes[node])>0 )
       free( lParse->Nodes[this->SubNodes[node]].value.data.ptr );
}

static void Do_Array( ParseData *lParse, Node *this )
{
   Node *that;
   long row, elem, idx, jdx, offset=0;
   int node;

   Allocate_Ptrs( lParse, this );

   if( !lParse->status ) {

     /* This is the item to be replicated */
     that = lParse->Nodes + this->SubNodes[0];

     if( that->operation == CONST_OP ) {

       idx = lParse->nRows*this->value.nelem + offset;
       while( idx-- ) {

	 this->value.undef[idx] = 0;

	 switch( this->type ) {
	 case BOOLEAN:
	   this->value.data.logptr[idx] = that->value.data.log;
	   break;
	 case LONG:
	   this->value.data.lngptr[idx] = that->value.data.lng;
	   break;
	 case DOUBLE:
	   this->value.data.dblptr[idx] = that->value.data.dbl;
	   break;
	 }
       }

     } else if (that->value.nelem > 1) { /* array "REFORM" */
       /* Note that dimensions change but total number of elements is same,
	  so we just do a straight copy */
      
       idx = lParse->nRows*this->value.nelem;
       while( idx-- ) {

	 this->value.undef[idx] = that->value.undef[idx];

	 switch( this->type ) {
	 case BOOLEAN:
	   this->value.data.logptr[idx] = that->value.data.logptr[idx];
	   break;
	 case LONG:
	   this->value.data.lngptr[idx] = that->value.data.lngptr[idx];
	   break;
	 case DOUBLE:
	   this->value.data.dblptr[idx] = that->value.data.dblptr[idx];
	   break;
	 }
       }
       
     } else { /* Any promotion of scalar to vector/array */
       
       row  = lParse->nRows;
       idx  = row * this->value.nelem - 1;
       while( row-- ) {
	 elem = this->value.nelem;
	 while( elem-- ) {
	   this->value.undef[idx] = that->value.undef[row];

	   switch( this->type ) {
	   case BOOLEAN:
	     this->value.data.logptr[idx] = that->value.data.logptr[row];
	     break;
	   case LONG:
	     this->value.data.lngptr[idx] = that->value.data.lngptr[row];
	     break;
	   case DOUBLE:
	     this->value.data.dblptr[idx] = that->value.data.dblptr[row];
	     break;
	   }
	   idx--;
	 }
       }

     } /* not constant */

     if( OPER(this->SubNodes[0])>0 )
       free( lParse->Nodes[this->SubNodes[0]].value.data.ptr );

   }

}

/*****************************************************************************/
/*  Utility routines which perform the calculations on bits and SAO regions  */
/*****************************************************************************/

static char bitlgte(char *bits1, int oper, char *bits2)
{
 int val1, val2, nextbit;
 char result;
 int i, l1, l2, length, ldiff;
 char *stream=0;
 char chr1, chr2;

 l1 = strlen(bits1);
 l2 = strlen(bits2);
 length = (l1 > l2) ? l1 : l2;
 stream = (char *)malloc(sizeof(char)*(length+1));
 if (l1 < l2)
   {
    ldiff = l2 - l1;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l1--    ) stream[i++] = *(bits1++);
    stream[i] = '\0';
    bits1 = stream;
   }
 else if (l2 < l1)
   {
    ldiff = l1 - l2;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l2--    ) stream[i++] = *(bits2++);
    stream[i] = '\0';
    bits2 = stream;
   }

 val1 = val2 = 0;
 nextbit = 1;

 while( length-- )
    {
     chr1 = bits1[length];
     chr2 = bits2[length];
     if ((chr1 != 'x')&&(chr1 != 'X')&&(chr2 != 'x')&&(chr2 != 'X'))
       {
        if (chr1 == '1') val1 += nextbit;
        if (chr2 == '1') val2 += nextbit;
        nextbit *= 2;
       }
    }
 result = 0;
 switch (oper)
       {
        case LT:
             if (val1 < val2) result = 1;
             break;
        case LTE:
             if (val1 <= val2) result = 1;
             break;
        case GT:
             if (val1 > val2) result = 1;
             break;
        case GTE:
             if (val1 >= val2) result = 1;
             break;
       }
 free(stream);
 return (result);
}

static void bitand(char *result,char *bitstrm1,char *bitstrm2)
{
 int i, l1, l2, ldiff, largestStream;
 char *stream=0;
 char chr1, chr2;

 l1 = strlen(bitstrm1);
 l2 = strlen(bitstrm2);
 largestStream = (l1 > l2) ? l1 : l2;
 stream = (char *)malloc(sizeof(char)*(largestStream+1));
 if (l1 < l2)
   {
    ldiff = l2 - l1;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l1--    ) stream[i++] = *(bitstrm1++);
    stream[i] = '\0';
    bitstrm1 = stream;
   }
 else if (l2 < l1)
   {
    ldiff = l1 - l2;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l2--    ) stream[i++] = *(bitstrm2++);
    stream[i] = '\0';
    bitstrm2 = stream;
   }
 while ( (chr1 = *(bitstrm1++)) ) 
    {
       chr2 = *(bitstrm2++);
       if ((chr1 == 'x') || (chr2 == 'x'))
          *result = 'x';
       else if ((chr1 == '1') && (chr2 == '1'))
          *result = '1';
       else
          *result = '0';
       result++;
    }
 free(stream);
 *result = '\0';
}

static void bitor(char *result,char *bitstrm1,char *bitstrm2)
{
 int i, l1, l2, ldiff, largestStream;
 char *stream=0;
 char chr1, chr2;

 l1 = strlen(bitstrm1);
 l2 = strlen(bitstrm2);
 largestStream = (l1 > l2) ? l1 : l2;
 stream = (char *)malloc(sizeof(char)*(largestStream+1));
 if (l1 < l2)
   {
    ldiff = l2 - l1;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l1--    ) stream[i++] = *(bitstrm1++);
    stream[i] = '\0';
    bitstrm1 = stream;
   }
 else if (l2 < l1)
   {
    ldiff = l1 - l2;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l2--    ) stream[i++] = *(bitstrm2++);
    stream[i] = '\0';
    bitstrm2 = stream;
   }
 while ( (chr1 = *(bitstrm1++)) ) 
    {
       chr2 = *(bitstrm2++);
       if ((chr1 == '1') || (chr2 == '1'))
          *result = '1';
       else if ((chr1 == '0') || (chr2 == '0'))
          *result = '0';
       else
          *result = 'x';
       result++;
    }
 free(stream);
 *result = '\0';
}

static void bitnot(char *result,char *bits)
{
   int length;
   char chr;

   length = strlen(bits);
   while( length-- ) {
      chr = *(bits++);
      *(result++) = ( chr=='1' ? '0' : ( chr=='0' ? '1' : chr ) );
   }
   *result = '\0';
}

static char bitcmp(char *bitstrm1, char *bitstrm2)
{
 int i, l1, l2, ldiff, largestStream;
 char *stream=0;
 char chr1, chr2;

 l1 = strlen(bitstrm1);
 l2 = strlen(bitstrm2);
 largestStream = (l1 > l2) ? l1 : l2;
 stream = (char *)malloc(sizeof(char)*(largestStream+1));
 if (l1 < l2)
   {
    ldiff = l2 - l1;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l1--    ) stream[i++] = *(bitstrm1++);
    stream[i] = '\0';
    bitstrm1 = stream;
   }
 else if (l2 < l1)
   {
    ldiff = l1 - l2;
    i=0;
    while( ldiff-- ) stream[i++] = '0';
    while( l2--    ) stream[i++] = *(bitstrm2++);
    stream[i] = '\0';
    bitstrm2 = stream;
   }
 while( (chr1 = *(bitstrm1++)) )
    {
       chr2 = *(bitstrm2++);
       if ( ((chr1 == '0') && (chr2 == '1'))
	    || ((chr1 == '1') && (chr2 == '0')) )
       {
          free(stream);
	  return( 0 );
       }
    }
 free(stream);
 return( 1 );
}

static char bnear(double x, double y, double tolerance)
{
 if (fabs(x - y) < tolerance)
   return ( 1 );
 else
   return ( 0 );
}

static char saobox(double xcen, double ycen, double xwid, double ywid,
		   double rot,  double xcol, double ycol)
{
 double x,y,xprime,yprime,xmin,xmax,ymin,ymax,theta;

 theta = (rot / 180.0) * myPI;
 xprime = xcol - xcen;
 yprime = ycol - ycen;
 x =  xprime * cos(theta) + yprime * sin(theta);
 y = -xprime * sin(theta) + yprime * cos(theta);
 xmin = - 0.5 * xwid; xmax = 0.5 * xwid;
 ymin = - 0.5 * ywid; ymax = 0.5 * ywid;
 if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax))
   return ( 1 );
 else
   return ( 0 );
}

static char circle(double xcen, double ycen, double rad,
		   double xcol, double ycol)
{
 double r2,dx,dy,dlen;

 dx = xcol - xcen;
 dy = ycol - ycen;
 dx *= dx; dy *= dy;
 dlen = dx + dy;
 r2 = rad * rad;
 if (dlen <= r2)
   return ( 1 );
 else
   return ( 0 );
}

static char ellipse(double xcen, double ycen, double xrad, double yrad,
		    double rot, double xcol, double ycol)
{
 double x,y,xprime,yprime,dx,dy,dlen,theta;

 theta = (rot / 180.0) * myPI;
 xprime = xcol - xcen;
 yprime = ycol - ycen;
 x =  xprime * cos(theta) + yprime * sin(theta);
 y = -xprime * sin(theta) + yprime * cos(theta);
 dx = x / xrad; dy = y / yrad;
 dx *= dx; dy *= dy;
 dlen = dx + dy;
 if (dlen <= 1.0)
   return ( 1 );
 else
   return ( 0 );
}

/*
 * Extract substring
 */
 int cstrmid(ParseData *lParse, char *dest_str, int dest_len,
	    char *src_str,  int src_len,
	    int pos)
{
  /* char fill_char = ' '; */
  char fill_char = '\0';
  if (src_len == 0) { src_len = strlen(src_str); } /* .. if constant */

  /* Fill destination with blanks */
  if (pos < 0) { 
    yyerror(0, lParse, "STRMID(S,P,N) P must be 0 or greater");
    return -1;
  }
  if (pos > src_len || pos == 0) {
    /* pos==0: blank string requested */
    memset(dest_str, fill_char, dest_len);
  } else if (pos+dest_len > src_len) {
    /* Copy a subset */
    int nsub = src_len-pos+1;
    int npad = dest_len - nsub;
    memcpy(dest_str, src_str+pos-1, nsub);
    /* Fill remaining string with blanks */
    memset(dest_str+nsub, fill_char, npad);
  } else {
    /* Full string copy */
    memcpy(dest_str, src_str+pos-1, dest_len);
  }
  dest_str[dest_len] = '\0'; /* Null-terminate */

  return 0;
}


static void yyerror(yyscan_t scanner, ParseData *lParse, char *s)
{
    char msg[80];

    if( !lParse->status ) lParse->status = PARSE_SYNTAX_ERR;

    strncpy(msg, s, 80);
    msg[79] = '\0';
    ffpmsg(msg);
}
cfitsio-4.3.1/iter_c.c0000644000225700000360000001356713472024437014100 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
    This example program illustrates how to use the CFITSIO iterator function.

    This program creates a 2D histogram of the X and Y columns of an event
    list.  The 'main' routine just creates the empty new image, then executes
    the 'writehisto' work function by calling the CFITSIO iterator function.

    'writehisto' opens the FITS event list that contains the X and Y columns.
    It then calls a second work function, calchisto, (by recursively calling
    the CFITSIO iterator function) which actually computes the 2D histogram.
*/

/*   Globally defined parameters */

long xsize = 480; /* size of the histogram image */
long ysize = 480;
long xbinsize = 32;
long ybinsize = 32;

main()
{
    extern writehisto();  /* external work function passed to the iterator */
    extern long xsize, ysize;  /* size of image */

    fitsfile *fptr;
    iteratorCol cols[1];
    int n_cols, status = 0;
    long n_per_loop, offset, naxes[2];
    char filename[]  = "histoimg.fit";     /* name of FITS image */

    remove(filename);   /* delete previous version of the file if it exists */
    fits_create_file(&fptr, filename, &status);  /* create new output image */

    naxes[0] = xsize;
    naxes[1] = ysize;
    fits_create_img(fptr, LONG_IMG, 2, naxes, &status); /* create primary HDU */

    n_cols  = 1;   /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], fptr, " ", TLONG, OutputCol);

    n_per_loop = -1;  /* force whole array to be passed at one time */
    offset = 0;       /* don't skip over any pixels */

    /* execute the function to create and write the 2D histogram */
    printf("Calling writehisto iterator work function... %d\n", status);

    fits_iterate_data(n_cols, cols, offset, n_per_loop,
                      writehisto, 0L, &status);

    fits_close_file(fptr, &status);      /* all done; close the file */

    if (status)
        fits_report_error(stderr, status);  /* print out error messages */
    else
        printf("Program completed successfully.\n");

    return(status);
}
/*--------------------------------------------------------------------------*/
int writehisto(long totaln, long offset, long firstn, long nvalues,
             int narrays, iteratorCol *histo, void *userPointer)
/*
   Iterator work function that writes out the 2D histogram.
   The histogram values are calculated by another work function, calchisto.

   This routine is executed only once since nvalues was forced to = totaln.
*/
{
    extern calchisto();  /* external function called by the iterator */
    long *histogram;
    fitsfile *tblptr;
    iteratorCol cols[2];
    int n_cols, status = 0;
    long rows_per_loop, rowoffset;
    char filename[]  = "iter_c.fit";     /* name of FITS table */

    /* do sanity checking of input values */
    if (totaln != nvalues)
        return(-1);  /* whole image must be passed at one time */

    if (narrays != 1)
        return(-2);  /* number of images is incorrect */

    if (fits_iter_get_datatype(&histo[0]) != TLONG)
        return(-3);  /* input array has wrong data type */

    /* assign the FITS array pointer to the global histogram pointer */
    histogram = (long *) fits_iter_get_array(&histo[0]);

    /* open the file and move to the table containing the X and Y columns */
    fits_open_file(&tblptr, filename, READONLY, &status);
    fits_movnam_hdu(tblptr, BINARY_TBL, "EVENTS", 0, &status);
    if (status)
       return(status);
   
    n_cols = 2; /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], tblptr, "X", TLONG,  InputCol);
    fits_iter_set_by_name(&cols[1], tblptr, "Y", TLONG, InputCol);

    rows_per_loop = 0;  /* take default number of rows per interation */
    rowoffset = 0;     

    /* calculate the histogram */
    printf("Calling calchisto iterator work function... %d\n", status);

    fits_iterate_data(n_cols, cols, rowoffset, rows_per_loop,
                      calchisto, histogram, &status);

    fits_close_file(tblptr, &status);      /* all done */
    return(status);
}
/*--------------------------------------------------------------------------*/
int calchisto(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *userPointer)

/*
   Interator work function that calculates values for the 2D histogram.
*/
{
    extern long xsize, ysize, xbinsize, ybinsize;
    long ii, ihisto, xbin, ybin;
    static long *xcol, *ycol, *histogram;  /* static to preserve values */

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {
        /* do sanity checking of input values */
       if (ncols != 2)
         return(-3);  /* number of arrays is incorrect */

       if (fits_iter_get_datatype(&cols[0]) != TLONG ||
           fits_iter_get_datatype(&cols[1]) != TLONG)
         return(-4);  /* wrong datatypes */

       /* assign the input array points to the X and Y arrays */
       xcol = (long *) fits_iter_get_array(&cols[0]);
       ycol = (long *) fits_iter_get_array(&cols[1]);
       histogram = (long *) userPointer;

       /* initialize the histogram image pixels = 0 */
       for (ii = 0; ii <= xsize * ysize; ii++)
           histogram[ii] = 0L;
    }

    /*------------------------------------------------------------------*/
    /*  Main loop: increment the 2D histogram at position of each event */
    /*------------------------------------------------------------------*/

    for (ii = 1; ii <= nrows; ii++) 
    {
        xbin = xcol[ii] / xbinsize;
        ybin = ycol[ii] / ybinsize;

        ihisto = ( ybin * xsize ) + xbin + 1;
        histogram[ihisto]++;
    }

    return(0);
}

cfitsio-4.3.1/iter_b.f0000644000225700000360000001305713472024437014074 0ustar  cagordonlhea      program f77iterate_b

C     external work function is passed to the iterator
      external str_iter

      integer ncols
      parameter (ncols=2)
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), offset, rows_per_loop, status
      character*70 colname(ncols)

      integer iunit, blocksize
      character*80 fname

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      status = 0

      fname = 'iter_b.fit'
      iunit = 15

C     both columns are in the same FITS file
      units(1) = iunit
      units(2) = iunit

C     open the file and move to the correct extension
      call ftopen(iunit,fname,1,blocksize,status)
      call ftmnhd(iunit, BINARY_TBL, 'iter_test', 0, status)

C     define the desired columns by name
      colname(1) = 'Avalue'
      colname(2) = 'Lvalue'

C     leave column numbers undefined
      colnum(1) = 0
      colnum(2) = 0  

C     define the desired datatype for each column: TSTRING & TLOGICAL
      datatype(1) = TSTRING
      datatype(2) = TLOGICAL

C     define whether columns are input, input/output, or output only
C     Both in/out
      iotype(1) = InputOutputCol
      iotype(2) = InputOutputCol
 
C     use default optimum number of rows and process all the rows
      rows_per_loop = 0
      offset = 0

C     apply the  function to each row of the table
      print *,'Calling iterator function...', status

      call ftiter( ncols, units, colnum, colname, datatype, iotype,
     &      offset, rows_per_loop, str_iter, 0, status )

      call ftclos(iunit, status)

C     print out error messages if problem
      if (status.ne.0) call ftrprt('STDERR', status)
      stop
      end

C--------------------------------------------------------------------------
C
C   Sample iterator function.
C
C--------------------------------------------------------------------------
      subroutine str_iter(totalrows, offset, firstrow, nrows, ncols,
     &     units, colnum, datatype, iotype, repeat, status, 
     &     userData, stringCol, logicalCol )

      integer totalrows,offset,firstrow,nrows,ncols,status
      integer units(*),colnum(*),datatype(*),iotype(*),repeat(*)
      integer userData
      character*(*) stringCol(*)
      logical logicalCol(*)

      integer ii

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      if (status .ne. 0) return

C    --------------------------------------------------------
C      Initialization procedures: execute on the first call  
C    --------------------------------------------------------
      if (firstrow .eq. 1) then
         if (ncols .ne. 2) then
            status = -1
            return
         endif
         
         if (datatype(1).ne.TSTRING .or. datatype(2).ne.TLOGICAL) then
            status = -2
            return
         endif
         
         print *,'Total rows, No. rows = ',totalrows, nrows
         
      endif
      
C     -------------------------------------------
C       Main loop: process all the rows of data 
C     -------------------------------------------
      
C     NOTE: 1st element of array is the null pixel value!
C     Loop over elements 2 to nrows+1, not 1 to nrows.
      
      do 10 ii=2,nrows+1
         print *, stringCol(ii), logicalCol(ii)
         if( logicalCol(ii) ) then
            logicalCol(ii) = .false.
            stringCol(ii) = 'changed to false'
         else
            logicalCol(ii) = .true.
            stringCol(ii) = 'changed to true'
         endif
 10   continue
      
C     -------------------------------------------------------
C     Clean up procedures:  after processing all the rows  
C     -------------------------------------------------------
      
      if (firstrow + nrows - 1 .eq. totalrows) then
C     no action required in this case
      endif
      
      return
      end
      
cfitsio-4.3.1/eval.l0000644000225700000360000004132314335036354013562 0ustar  cagordonlhea/************************************************************************/
/*                                                                      */
/*                       CFITSIO Lexical Parser                         */
/*                                                                      */

/* This specifies a thread-safe reentrant version of lex functions */
%option reentrant
/* This specifies CFITSIO-unique names for lexer functions */
%option prefix="fits_parser_yy"
/* This facilitates calling between the Bison parser and this lexer */
%option bison-bridge

%{
/* This file is one of 3 files containing code which parses an          */
/* arithmetic expression and evaluates it in the context of an input    */
/* FITS file table extension.  The CFITSIO lexical parser is divided    */
/* into the following 3 parts/files: the CFITSIO "front-end",           */
/* eval_f.c, contains the interface between the user/CFITSIO and the    */
/* real core of the parser; the FLEX interpreter, eval_l.c, takes the   */
/* input string and parses it into tokens and identifies the FITS       */
/* information required to evaluate the expression (ie, keywords and    */
/* columns); and, the BISON grammar and evaluation routines, eval_y.c,  */
/* receives the FLEX output and determines and performs the actual      */
/* operations.  The files eval_l.c and eval_y.c are produced from       */
/* running flex and bison on the files eval.l and eval.y, respectively. */
/* (flex and bison are available from any GNU archive: see www.gnu.org) */
/*                                                                      */
/* The grammar rules, rather than evaluating the expression in situ,    */
/* builds a tree, or Nodal, structure mapping out the order of          */
/* operations and expression dependencies.  This "compilation" process  */
/* allows for much faster processing of multiple rows.  This technique  */
/* was developed by Uwe Lammers of the XMM Science Analysis System,     */
/* although the CFITSIO implementation is entirely code original.       */
/*                                                                      */
/*                                                                      */
/* Modification History:                                                */
/*                                                                      */
/*   Kent Blackburn      c1992  Original parser code developed for the  */
/*                              FTOOLS software package, in particular, */
/*                              the fselect task.                       */
/*   Kent Blackburn      c1995  BIT column support added                */
/*   Peter D Wilson   Feb 1998  Vector column support added             */
/*   Peter D Wilson   May 1998  Ported to CFITSIO library.  User        */
/*                              interface routines written, in essence  */
/*                              making fselect, fcalc, and maketime     */
/*                              capabilities available to all tools     */
/*                              via single function calls.              */
/*   Peter D Wilson   Jun 1998  Major rewrite of parser core, so as to  */
/*                              create a run-time evaluation tree,      */
/*                              inspired by the work of Uwe Lammers,    */
/*                              resulting in a speed increase of        */
/*                              10-100 times.                           */
/*   Peter D Wilson   Jul 1998  gtifilter(a,b,c,d) function added       */
/*   Peter D Wilson   Aug 1998  regfilter(a,b,c,d) function added       */
/*   Peter D Wilson   Jul 1999  Make parser fitsfile-independent,       */
/*                              allowing a purely vector-based usage    */
/*                                                                      */
/************************************************************************/

#include 
#include 
#include 
#ifdef sparc
#include 
#else
#include 
#endif
#include "eval_defs.h"
#include "eval_tab.h"

/* This is a shorthand accessor to get at the "extra" data inside the
   lexer, which in our case is the lParse (ParseData) structure */
#define yylParse (yyextra)

/*****  Internal functions  *****/

       int fits_parser_yyGetVariable( ParseData *lParse, char *varName, FITS_PARSER_YYSTYPE *varVal );

static int find_variable( ParseData *lParse, char *varName );
static int expr_read( ParseData *lParse, char *buf, int nbytes );

/*****  Definitions  *****/

#define YY_NO_UNPUT   /*  Don't include YYUNPUT function  */
#define YY_NEVER_INTERACTIVE 1

#define MAXCHR 256
#define MAXBIT 128

#define OCT_0 "000"
#define OCT_1 "001"
#define OCT_2 "010"
#define OCT_3 "011"
#define OCT_4 "100"
#define OCT_5 "101"
#define OCT_6 "110"
#define OCT_7 "111"
#define OCT_X "xxx"

#define HEX_0 "0000"
#define HEX_1 "0001"
#define HEX_2 "0010"
#define HEX_3 "0011"
#define HEX_4 "0100"
#define HEX_5 "0101"
#define HEX_6 "0110"
#define HEX_7 "0111"
#define HEX_8 "1000"
#define HEX_9 "1001"
#define HEX_A "1010"
#define HEX_B "1011"
#define HEX_C "1100"
#define HEX_D "1101"
#define HEX_E "1110"
#define HEX_F "1111"
#define HEX_X "xxxx"

/* 
   MJT - 13 June 1996
   read from buffer instead of stdin
   (as per old ftools.skel)
*/
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
        if ( (result = expr_read( yylParse, (char *) buf, max_size )) < 0 ) \
            YY_FATAL_ERROR( "read() in flex scanner failed" );

%}

bit		([bB][01xX]+)
oct		([oO][01234567xX]+)
hex		([hH][0123456789aAbBcCdDeEfFxX]+)
bitconst        (0b[01]+)
hexconst        (0x[0123456789aAbBcCdDeEfF]+)
octconst        (0o]+)
integer		[0-9]+
boolean         (t|f|T|F)
real		([0-9]*"."[0-9]+)|([0-9]*"."*[0-9]+[eEdD][+-]?[0-9]+)|([0-9]*".")
constant        ("#"[a-zA-Z0-9_]+)|("#""$"[^\n]*"$")
string		([\"][^\"\n]*[\"])|([\'][^\'\n]*[\'])
variable	([a-zA-Z_][a-zA-Z0-9_]*)|("$"[^$\n]*"$")
function	[a-zA-Z][a-zA-Z0-9]+"("
intcast		("(int)"|"(INT)")
fltcast		("(float)"|"(FLOAT)"|"(double)"|"(DOUBLE)")
power		("^"|"**")
not             ("!"|".not."|".NOT."|"not."|"NOT.")
or              ("||"|".or."|".OR."|"or."|"OR.")
and             ("&&"|".and."|".AND."|"and."|"AND.")
equal		("=="|".eq."|".EQ."|"eq."|"EQ.")
not_equal	("!="|".ne."|".NE."|"ne."|"NE.")
greater         (">"|".gt."|".GT."|"gt."|"GT.")
lesser          ("<"|".lt."|".LT."|"lt."|"LT.")
greater_eq	(">="|"=>"|".ge."|".GE."|"ge."|"GE.")
lesser_eq	("<="|"=<"|".le."|".LE."|"le."|"LE.")
xor             ("^^"|".xor."|".XOR.")
nl		\n

%%

[ \t]+     ;
{bit}		{
                  int len;
                  len = strlen(yytext);
		  while (yytext[len] == ' ')
			len--;
                  len = len - 1;
		  strncpy(yylval->str,&yytext[1],len);
		  yylval->str[len] = '\0';
		  return( BITSTR );
		}
{oct}		{
                  int len;
                  char tmpstring[256];
                  char bitstring[256];
                  len = strlen(yytext);
		  if (len >= 256) {
		    char errMsg[100];
		    yylParse->status = PARSE_SYNTAX_ERR;
		    strcpy (errMsg,"Bit string exceeds maximum length: '");
		    strncat(errMsg, &(yytext[0]), 20);
		    strcat (errMsg,"...'");
		    ffpmsg (errMsg);
		    len = 0;
		  } else {
		    while (yytext[len] == ' ')
		      len--;
		    len = len - 1;
		    strncpy(tmpstring,&yytext[1],len);
		  }
                  tmpstring[len] = '\0';
                  bitstring[0] = '\0';
		  len = 0;
                  while ( tmpstring[len] != '\0')
                       {
			switch ( tmpstring[len] )
			      {
			       case '0':
					strcat(bitstring,OCT_0);
					break;
			       case '1':
					strcat(bitstring,OCT_1);
					break;
			       case '2':
					strcat(bitstring,OCT_2);
					break;
			       case '3':
					strcat(bitstring,OCT_3);
					break;
			       case '4':
					strcat(bitstring,OCT_4);
					break;
			       case '5':
					strcat(bitstring,OCT_5);
					break;
			       case '6':
					strcat(bitstring,OCT_6);
					break;
			       case '7':
					strcat(bitstring,OCT_7);
					break;
			       case 'x':
			       case 'X':
					strcat(bitstring,OCT_X);
					break;
			      }
			len++;
                       }
                  strcpy( yylval->str, bitstring );
		  return( BITSTR );
		}
{hex}		{
                  int len;
                  char tmpstring[256];
                  char bitstring[256];
                  len = strlen(yytext);
		  if (len >= 256) {
		    char errMsg[100];
		    yylParse->status = PARSE_SYNTAX_ERR;
		    strcpy (errMsg,"Hex string exceeds maximum length: '");
		    strncat(errMsg, &(yytext[0]), 20);
		    strcat (errMsg,"...'");
		    ffpmsg (errMsg);
		    len = 0;
		  } else {
		    while (yytext[len] == ' ')
		      len--;
		    len = len - 1;
		    strncpy(tmpstring,&yytext[1],len);
		  }
                  tmpstring[len] = '\0';
                  bitstring[0] = '\0';
		  len = 0;
                  while ( tmpstring[len] != '\0')
                       {
			switch ( tmpstring[len] )
			      {
			       case '0':
					strcat(bitstring,HEX_0);
					break;
			       case '1':
					strcat(bitstring,HEX_1);
					break;
			       case '2':
					strcat(bitstring,HEX_2);
					break;
			       case '3':
					strcat(bitstring,HEX_3);
					break;
			       case '4':
					strcat(bitstring,HEX_4);
					break;
			       case '5':
					strcat(bitstring,HEX_5);
					break;
			       case '6':
					strcat(bitstring,HEX_6);
					break;
			       case '7':
					strcat(bitstring,HEX_7);
					break;
			       case '8':
					strcat(bitstring,HEX_8);
					break;
			       case '9':
					strcat(bitstring,HEX_9);
					break;
			       case 'a':
			       case 'A':
					strcat(bitstring,HEX_A);
					break;
			       case 'b':
			       case 'B':
					strcat(bitstring,HEX_B);
					break;
			       case 'c':
			       case 'C':
					strcat(bitstring,HEX_C);
					break;
			       case 'd':
			       case 'D':
					strcat(bitstring,HEX_D);
					break;
			       case 'e':
			       case 'E':
					strcat(bitstring,HEX_E);
					break;
			       case 'f':
			       case 'F':
					strcat(bitstring,HEX_F);
					break;
			       case 'x':
			       case 'X':
					strcat(bitstring,HEX_X);
					break;
			      }
			len++;
                       }

                  strcpy( yylval->str, bitstring );
		  return( BITSTR );
		}
{bitconst}      {
		  long int constval = 0;
		  char *p;
		  for (p = &(yytext[2]); *p; p++) {
		    constval = (constval << 1) | (*p == '1');
		  }
		  yylval->lng = constval;
		  return( LONG );
		}
{octconst}      {
		  long int constval = 0;
		  char *p;
		  for (p = &(yytext[2]); *p; p++) {
		    constval = (constval << 3) | (*p - '0');
		  }
		  yylval->lng = constval;
		  return( LONG );
		}
{hexconst}      {
		  long int constval = 0;
		  char *p;
		  for (p = &(yytext[2]); *p; p++) {
                    int v = (isdigit(*p) ? (*p - '0') : (*p - 'a' + 10));
                    constval = (constval << 4) | v;
		  }
		  yylval->lng = constval;
		  return( LONG );
		}

                  
{integer}	{
                  yylval->lng = atol(yytext);
		  return( LONG );
		}
{boolean}	{
                  if ((yytext[0] == 't') || (yytext[0] == 'T'))
		    yylval->log = 1;
		  else
		    yylval->log = 0;
		  return( BOOLEAN );
		}
{real}		{
                  yylval->dbl = atof(yytext);
		  return( DOUBLE );
		}
{constant}	{
                  if(        !fits_strcasecmp(yytext,"#PI") ) {
		     yylval->dbl = (double)(4) * atan((double)(1));
		     return( DOUBLE );
		  } else if( !fits_strcasecmp(yytext,"#E") ) {
		     yylval->dbl = exp((double)(1));
		     return( DOUBLE );
		  } else if( !fits_strcasecmp(yytext,"#DEG") ) {
		     yylval->dbl = ((double)4)*atan((double)1)/((double)180);
		     return( DOUBLE );
		  } else if( !fits_strcasecmp(yytext,"#ROW") ) {
		     return( ROWREF );
		  } else if( !fits_strcasecmp(yytext,"#NULL") ) {
		     return( NULLREF );
		  } else if( !fits_strcasecmp(yytext,"#SNULL") ) {
		     return( SNULLREF );
		  } else {
                     int len; 
		     int result;
                     if (yytext[1] == '$') {
                        len = strlen(yytext) - 3;
                        yylval->str[0]     = '#';
                        strncpy(yylval->str+1,&yytext[2],len);
                        yylval->str[len+1] = '\0';
                        yytext = yylval->str;
		     }
                     result = (*yylParse->getData)(yylParse, yytext, (yylval));
		     return result;
                  }
                }
{string}	{
                  int len;
                  len = strlen(yytext) - 2;
		  if (len >= MAX_STRLEN) {
		    char errMsg[100];
		    yylParse->status = PARSE_SYNTAX_ERR;
		    strcpy (errMsg,"String exceeds maximum length: '");
		    strncat(errMsg, &(yytext[1]), 20);
		    strcat (errMsg,"...'");
		    ffpmsg (errMsg);
		    len = 0;
		  } else {
		    strncpy(yylval->str,&yytext[1],len);
		  }
		  yylval->str[len] = '\0';
		  return( STRING );
		}
{variable}	{
		 int    len,type;

                 if (yytext[0] == '$') {
		    len = strlen(yytext) - 2;
		    strncpy(yylval->str,&yytext[1],len);
		    yylval->str[len] = '\0';
		    yytext = yylval->str;
		 } 
		 type = fits_parser_yyGetVariable(yylParse, yytext, (yylval));
		 return( type );
		}
{function}	{
                  char *fname;
		  int len=0;
                  fname = &(yylval->str[0]);
		  while( (fname[len]=toupper(yytext[len])) ) len++;

                  if(      FSTRCMP(fname,"BOX(")==0 
                        || FSTRCMP(fname,"CIRCLE(")==0 
                        || FSTRCMP(fname,"ELLIPSE(")==0 
                        || FSTRCMP(fname,"NEAR(")==0 
                        || FSTRCMP(fname,"ISNULL(")==0 
                         )
                     /* Return type is always boolean  */
		     return( BFUNCTION );

                  else if( FSTRCMP(fname,"GTIFILTER(")==0 )
                     return( GTIFILTER );

                  else if( FSTRCMP(fname,"GTIOVERLAP(")==0 )
                     return( GTIOVERLAP );

                  else if( FSTRCMP(fname,"GTIFIND(")==0 )
                     return( GTIFIND );

                  else if( FSTRCMP(fname,"REGFILTER(")==0 )
                     return( REGFILTER );

                  else if( FSTRCMP(fname,"STRSTR(")==0 )
                     return( IFUNCTION );  /* Returns integer */

                  else 
		     return( FUNCTION  );
		}
{intcast}	{ return( INTCAST ); }
{fltcast}	{ return( FLTCAST ); }
{power}		{ return( POWER   ); }
{not}		{ return( NOT     ); }
{or}		{ return( OR      ); }
{and}		{ return( AND     ); }
{equal}		{ return( EQ      ); }
{not_equal}	{ return( NE      ); }
{greater}	{ return( GT      ); }
{lesser}	{ return( LT      ); }
{greater_eq}	{ return( GTE     ); }
{lesser_eq}	{ return( LTE     ); }
{xor}           { return( XOR     ); }
{nl}		{ return( '\n'    ); }
.		{ return( yytext[0] ); }
%%

int yywrap(yyscan_t scanner)
{
  /* MJT -- 13 June 1996
     Supplied for compatibility with
     pre-2.5.1 versions of flex which
     do not recognize %option noyywrap 
  */
  return(1);
}

/* 
   expr_read is lifted from old ftools.skel. 
   Now we can use any version of flex with
   no .skel file necessary! MJT - 13 June 1996

   keep a memory of how many bytes have been
   read previously, so that an unlimited-sized
   buffer can be supported. PDW - 28 Feb 1998
*/

static int expr_read(ParseData *lParse, char *buf, int nbytes)
{
 int n;
 
 n = 0;
 if( !lParse->is_eobuf ) {
     do {
        buf[n++] = lParse->expr[lParse->index++];
       } while ((nexpr[lParse->index] != '\0'));
     if( lParse->expr[lParse->index] == '\0' ) lParse->is_eobuf = 1;
 }
 buf[n] = '\0';
 return(n);
}

int fits_parser_yyGetVariable( ParseData *lParse, char *varName, FITS_PARSER_YYSTYPE *thelval )
{
   int varNum, type;
   char errMsg[MAXVARNAME+25];

   varNum = find_variable( lParse, varName );
   if( varNum<0 ) {
      if( lParse->getData ) {
	 type = (*lParse->getData)( lParse, varName, thelval );
      } else {
	 type = pERROR;
	 lParse->status = PARSE_SYNTAX_ERR;
	 strcpy (errMsg,"Unable to find data: ");
	 strncat(errMsg, varName, MAXVARNAME);
	 ffpmsg (errMsg);
      }
   } else {
      /*  Convert variable type into expression type  */
      switch( lParse->varData[ varNum ].type ) {
      case LONG:
      case DOUBLE:   type =  COLUMN;  break;
      case BOOLEAN:  type = BCOLUMN;  break;
      case STRING:   type = SCOLUMN;  break;
      case BITSTR:   type =  BITCOL;  break;
      default:
	 type = pERROR;
	 lParse->status = PARSE_SYNTAX_ERR;
	 strcpy (errMsg,"Bad datatype for data: ");
	 strncat(errMsg, varName, MAXVARNAME);
	 ffpmsg (errMsg);
	 break;
      }
      thelval->lng = varNum;
   }
   return( type );
}

static int find_variable(ParseData *lParse, char *varName)
{
   int i;
 
   if( lParse->nCols )
      for( i=0; inCols; i++ ) {
         if( ! fits_strncasecmp(lParse->varData[i].name,varName,MAXVARNAME) ) {
            return( i );
         }
      }
   return( -1 );
}
cfitsio-4.3.1/docs/0000755000225700000360000000000014523044740013400 5ustar  cagordonlheacfitsio-4.3.1/docs/cfitsio.pdf0000644000225700000360000341417314456514035015554 0ustar  cagordonlhea%PDF-1.4
%Çì¢
5 0 obj
<>
stream
xœuTËŽ;Ý÷WÔŽ”D;NâxÉû!]Cñ€™a@bxóÿ÷8©î©á¡Ru¹Û9>>η‰"OäÏú=½ÜÝ:ÑéâÇŽ¦‹Ý·÷Íiýœ^NwöphSÊQ›ò´¿Šm*%GJÓþr÷:ÜŽ’ªJx0ã„F)×ðx^6÷ó’bR«^`?7æl›ý§°”£/¾t×Ò¨høá¦˜d	çó‚´Jb¾»m\ÍÂ
÷¨¨¸³(D'3Ç\µ´CKKá½Ûšj³ü¯tÛåÏ'ÕRÃ)òIIî ªQ‘â¡—l¹¦~u×äæÇˆ)‡³«Õ
Œ7û'VÖ˜¸d§µ´˜ÅÚ´”IM§ý(½Ý)5S”ÎŽj§ŒbJFâ˩Ē“„Ÿ~*g<~TŠ‰Æ‘ŠÔ†ÚÁHV“ðv¥ÄÕ«ÂvS¬ö²j‰Éx›ê‹kèqFSS´FVŽ4£©HÙ[
Ç1ft9¿t&ÈÄ@RÒpé‰JÞÀø9‚QÇæ”Q•ÐÂOWæZ›TîÝŽuBkFßI¦E8¦Aߨ¸þ
ˆ·/sÅŠúqžÁr-etuÑM¦Æ[‡QÐUM‡ï
³æ¼õ¿ŽøÖ	r
dhÀ[¿‹™("^Í#æÌÛJ‘rÌ3©¬
I(š3õ$ôÓ¡çX¨kŒ€[”–‹ñÊS‹+¤„ÑŽFÖ§T¥4p˜YÃŒÞïÚïæíã"TPñ7aü$E"­NröÔ­ „þ0ÄQim‘ïvžÛð>ó.EÈÚ Õ:—þ¦¹x’1›,Ó³<œáÌdê?oçÞÕâÿ>
stream
xœ+T0Ð3T0A(œË¥d®^Ìe ÎUÈe–T€Rɹ
N!@†F@=KKC…4.ˆNCs#sc=#…\®hLM#Ž
ñâr
á
BÞ*“endstream
endobj
18 0 obj
92
endobj
22 0 obj
<>
stream
xœíZÉr7½3ùˆ9R5“Á½;);q"Æ9Ø9ȤL±,Q¶äMŸîÆ6$Ge)–R,•Š$hÌð½~½€ª®åU‡ñur8úùO[ÍNF]5}qºXÅ—Éau\%TkåÕøí(,ä••á¶u¦Ž^ÕXÃ[)ŒwõëZÅ-¶^0á[-•¬?2Þ
çe½ÇØÝvÒ§ËBùrù„5¢•–ü3þö
î¦õ§Í-¼åÞWãg£ñO¯jÎ/`ÖýÂö$îïŽX#»¶ëŒ®§Ÿ&L‡áù“0È9LEûÊðÖxžñt„æØr΄­¹èoÝ(¥[¥ª†{xéDZ¢ë–	¼.mW߃m…k;®ëûnƒ5ºžÃõ=øð®)ÛÛúw¼™ÏLŠp‡{iêg0“ç§“Ì7º“ôðV…—ÞÈðÛsç]ýâ]5B`šFº„ö 
®¤ƒ!Ä—4i
¡.½[F]À‚(Üñz‡5˜¯ëOð)Ö¹éD4Ø’ðv4­G†ÇŒè+ê1²bçš—mâä@Û,\³Àà™wZÔ»0ƒ¶ÚK½34¶ÀåSÓ0fÃ4øŒ˜NæiñaÞc—¼%~@2c
T ãê;‚‰H%ZОAoÈVIoaX	dáÄ=ø8aÒÖïЭM0E>ÿÁ>ˆ®>-¤™±€ƒ@Ú0	âßð°[}èñÈËÖò¾lB‘¨­ëƒ*\x†Î‡"¾èa¦îHÈÏàžvü€K9‚}k¿áÿ.d‰\¹`I"‚
DXMT¢«,6*FÙi\õ?ÞCYØEb„äd1N`ŠãLÙGEw¨Þ:,yœEšò1êĽ…ŒBh6sLVO_Ïrô¥³œÌgÑËr"Ÿ1»AºR€@›¦¤s³ÅxP®}Çš¾Üp›0ù
}r;…!únÅ–Æ¥4HîÏOi.¥g:é™ä<éYŽmÿÂn0ñ®ÿJˆ#š_ÅFLHÓN‘à'à! –ÌÆr{‹óµ!§ï	P¡Æ*ÖiÆY¾^r܈õKøø€Ü	ZsKþŽ`t#ª
РRt2•É«Êéßà“Y´{YhÈSÁlÈS1óT’ûº3#¬]¸2¥®Ñ[toæYÉ›ï½M.‡ÏwaUðF÷ÅH;ɸ÷,ôH®÷19uT„¾ÀÆ(¶ò+¨›Î&Ô·pß¼jÈm«õY÷:cædhÄöCˆÂÉÛs¹	žm©¹B¢&L|+ñÿuΖ‘çlr¥Íjÿ.õ+	;)&qÁ–¨÷$9·¸o3B°[Óë/l\mŸmkB¯ÙúÉf*0¡ZiF&¡ A¬2…$–Diñó1U…}:àÔ†•f&‰I}KEìšñ¡vX%W?*Xeð­-mòÌRz–^q›g8Ÿû²'†-‡]ÌkcA+ä[—í$ÝDÞ—‰îd˜ºðàI,ÇPòÏ
¹7•e?•rÓ2éÚÀ•à6úñ݃µp`
	!_C*öœß„Ö4 h/¼Â[X=ØæWÏ÷/qV奤¿;«‰ò§—Z²´ ï…Öb8€jd¿¡ˆ]ȰÙÄy~ÈxM½ÊãpoZ·jíÌl÷úŠM˜„[w®ãa®*»“a(2I²ÝJÜÿ©
ªðiA<ž?ͧ´ûÁ|±JâœÛ¸ ½)ú«É³ZoonÆ3¾QÑ©–„5ǧÔñrÛRy£ðz¥“šäúÜ“µ^7ô«§¸9O	3—Ô³—ÂÖOãÞRsŒ±1$Fãµwñ&&Ò±’ÛdÒ U,Éë×uZB·ô4OF“˜É½fð˜zèPö®"_ê£3bã&È»¥úh5 ªõúè1ó1æ°‹ÂIÌ•zî,µ«c¢ÄÎrÈ?xúþ’ù®$Qó¸òMJ–1ÔªÐq`ŒîüSSý=ª÷Ru¯´HÊrk`'85Dy=©Îf°Ç‡¾WQÚsxL‚òldù‰ú&§_OäAD1ËÇ ¹ºš%¤\yùWäãÖÓÙpþ-P¯ç:ħ¤ëaoè„îl¢Á…[Þé$äl(3שÔß­BðEÉ…–
¡5—ïB)r‡y1Tij„/Õ8kåÍ~Y²ÛKqÈɤåÛÏÄñ¹¾
³6Ä{o4ƒÅ«½í
¾]´o­þ¥¿%ÒO58]ƒz®;G=˜GÐç!©|4ýÿÞï2,endstream
endobj
23 0 obj
1783
endobj
29 0 obj
<>
stream
xœí[IwG¾ûWè8sÐÐûtÙN$¶y9Xf
!¿>UÕËôl²¥‘±òxXÒ,Ý­ù¾ªúªºô~Æ*>cø/¼žœïÝ9¬gg÷Øìlïý§“³ðrr>»·€¸€#•cŽÏ¯öü|V‹Y-UÅÄlq¾÷[ñ¦Å_åœÿ¾øn‘<¿E1S1w-NáÊûånc\™âY9—•sƹâ)Ü¿hÎ<,ç"‹—•s‡	áçh/k.­«j3›KVÕÜ9?—*uQÁ(VÆ„«/päsfâÅ;´ø.Á/pR*zý§e
ÓÊâz£|*%¼Î¥2txQ
[9«Eñ†ÆQ$~6²x	o…¡oY\ÀËRà-ÜÁã‘N«âC9×ÅG¸Ž[åhJé¼i`ÑsÍ$Mo•ÉŽ\õäÎ‚˜Ic+Q»H„Ik
'”…€G'K3Ìãsî*Ù£AÝÐ`WäÑÏEZ,=ñ8³ÅLYã"ÔN=Ý[B‚5ADظ‘6ãÌå$ˆ÷ 	D›¶aAý¹–!#ÆÇ€*×ã˜I‘«¦sè.ŠSY‘£€á|¬yío€ÑR—C®/²²½4á‡}R
¼Ð¦ùâ}Ù[œúþ㪦	â·òÓã'%Í
që-úxÊO×'IûÊ,x\Æó oÃéã¸ïVÈñàUÎÄ«iÙ~æ NèÀEIIñf3øjµïõÊS29=B­ñÁ&>øÙFø >PJ‡@“êCbJʣĄVH’
c¨SðÀ㘃›A¦ƒH‡²ÑgÀˆ¢2	¶—‡ìš—¸IXqçP¨NuAUÚY*/HÃQ4Ü(XŠÚ/|xOPø3Âû>ò`?Õ6XÔ(Žèí3Òþð²”úœøÂ‹¯ðï‹ÆæO‚º«5EùÃ+aÜÏtß›åK/.¨F¢´®T|J2yß
ÖQ”tX¬iGM,"iéõ¬áêÊ;|<š„7~ׯ7áÍŸ“%äF‚G\™IˆÍp%e7ÎÞmBÖP›ÊÔÛ‰¤h’”QpŽaìÌ9F*ˆ†
=øpdSTÌÕLt™zš¶…g~ñB\N
Ùâ1|Ä"Ê室šÑwEÀ“
_æ¥7ó®I9ÞÄ/˜Š‰Šó‘ülñ˜HÅÛ‡ƒ‚jƒþ2TOO#nèè•—²?úà¦|ü¥¤»TVk;
IhÎÜäczc¿“TÒóÒqŸ§>¹	t:Ú‘/šæT”¢ ¼SÀÞ”z–y6ÚxĨL3pƒÏ~]ø¿˜Å´ÑBêŒâÎDœkn"Î;nÖ[ó
²®+6Vag@ÊŸÂíä“Ã$›‘l{ȬSX8ó¢bº};’&]Ѱ‹Ý$î*“†yLèX¾nÂÏI÷§”·UÒ”œÒƒ¥R˜}§”AÑÂHo>‰ÈÞ-iCÆðâQ<ôŠòyýoä[|ývd#–$,7~6”Ì„BÀ4ªig®”Œ¬Ç‡TSSߦ¤¦òMW?ï°:ßzïnXÀài×¼³AO´È%£ha….€omãö™óÄ=ÕuK®C‚¤Â(þ ÛvGC§ŒŸ>@ìp\↾bÒÚC`³M‘Tt›äM\GЍ;Êeƒ.¡î+C¢C²ò¸	KžÁ’Ï}2‹/Ñ
Û°;Áþ7òÍT†uÕbEÛxÅ ¡÷Ô^òèqÇ<I
,›Rņes>v[ä›âíÐ1TŸžlP=ÚüFTÁù„„°gÜaÀÕÆ-\^×Ù7ÍÄ[+÷£–A_tà¦
+îü†U¶#ÞQ=Væ°
'0ñ—©t|; ïzyc+#×Ý+‰›¬ÃÆÈ•6¯:xg%Ÿ¢Õƒ}$ÃËb÷eXyâò޾è$–m—$kÄN'‡Óa¶0[¶îY¶ï•圕j:ðùÅö,úFÓÞZ[òýC¼ Ôc§Þ›º3ZG»VfE€š³¸éŒ.Ÿý–w7M¾­¦XaÎfýÞÒè˸ý½Œu솳½<¾éXÍ	½ýð‹&†Ò@«W&{Û¯	ñ‰t°Ü¬vý·ñ¡¾èâYKìqÖü›Ÿá³¡DËø9.æÂQíÇ[-Û¬RlÒRס€nɶ±B­íçd#»·ä^7nÀ;wJ‘!¼
ÍM¨Æ-üé1Xs»Õn—[7Ȇ%Û²R}Ï	ô2·ÝDÜÃ?¬iß?xÚûMN]ƒX7^f*YœK»u7Ü6„Ý&Å9“çÂ(ÃÂ.‚Ÿ¥lôV‡súåRloÔ¬0òHÞUOîé0z@™í0t}ÿ6Rv³¢M1^iLá%ÃfXëçAÍ'¦Þ¾Cí5Ú°õân6¶¬ƒ:âðsØÅMíj¨ _ì—¸!ÂËr7éê7e“çõÚêtÒ­ßÐfú
m‹^\LûâÔ§`É|±Â«YísUÊfÓFæ[_žÞÇ’A2-ãŎ
Xš¥ßÿ}G²ç:ÊÑèÔØxÇ’){mlÛ ÀƒxÞÿ¶ùÁ'uÀX³,ÃÝN;àÄü‡’“ucÜ• ZùOWüš²×¶ö¨ýÛ/Dã4/eŒU.‡~x\f{•˘›Žþ&$´ûG®5ÛÔ9áÚeÀº
=Ì·‰eðµj·I,Ûf
ùòᇋ½_àß¿|¢Öendstream
endobj
30 0 obj
2393
endobj
36 0 obj
<>
stream
xœí[MsÛ6½kú#t$dˆoà˜4Nâ6MÒH™:=¸vãhÆV;Nãüúî.’H›2%[šv2±%@¾·o‹õ—qU²q…ÿÂïãóÑ£·f|z9ªÆ§£/#FÇá×ñùøÉ:-¥«O?ŒülløØYV|<=ý‘ýœ2{?^å<›â‡ƒ¼àÍ·I^貪Xeÿœþ£2žŽ*5/¹„§'0Ø·¼`ЗkìZH©JÇÇ…¨JÜó]t®²Ɩе⮬˜_Â'h?ÏS±ì3LšA·¿s™}Íü.„´ÙK\ÚÚ/ñÃWhä†PtûìOV™ìÐ_æ¥sÖjå"/TvÝ`8?	Þs÷À2ÈÞæE…ý·téÊ?8çÍ03¶8“Íë‹86¬F[Q:+áÙ
U	pñ£\i¹C¿
‚	ÅJ.\„ok
™…w*såYœIXTmJ¥p…—L#7q=8"*D'{Ÿ;¿¹hDvqv¸9@€I¤¶@&˜”ù'³ùQ ˆ$òEĘ\ç5È—ys½nDZ$B -ôWÔs6‡¾ïÄÇJ•5÷mÍ6?µL!ÞŽæð‰m|RoŸØTdtÄ,´äuVÀSçÞNæ9±^3‰Óhóx¾eaÙ^›0Þ¾`D!àUZ3è‚£‰ë‡'ð!Ûжä&µYí² RbÑ
lc/Hþˆ‚Dï‹c®0—}œç(pÐzŒøþˆqqõy6?ÅvAF³·]ÍmÖ—ÛÚ8×ßp;(þs4QÔãH?/ø‘ÅÞÝd¸\®À‘´*NLÿ«ñ@h
4šÔï³bM>;0•UáŒõŽ3¼ÃXU2 `«?èËp(qÏð"Hj—0Ú3‚ßÂÄUì7
$h3„ =ĤZejß. ¦	^œ5ƒô4‰”f[ô~{Ç…e)Ñ0Ì®)…‘]>_—J,«kÔnBˆ(¬(p3¯p³ð™}$ࣀguyˆŠ6EÇ99®ÐÎ7ÏsXYtü ¤ð熮 lÒÑ41d •½Ã€F*ݪT>îS4ƒñhx3j¡4ôþÃWŒð 8oX>4Êm·•ÿ9˜m$jŽFb¢`BD®V³áEÃ04’5i`¥%—yßopï€<ÊŠ—Ò¤Š¹tìA`+Ö4o€~êeÈzø²:VBø?å~ƒëãÿì]-µlê9£		Ï®±»"9æÇ&ωc{nö»¸TR­BX¶ïpuDBðÒ	Ia	Å
þ³¶h¨Þû¹Õhè|E¼ß¡A;2غ¾÷,î	¡§qâæÅÿ†ÞiËT¸xž;Ñnì¢~#_G¨!Ø#Zu´Ûq—ÏÑ›‚ñ'1±Ê~õqŽD3g 41ùåÕBú$Ú°ØÀ2;ƒßCäºRÈhù\—ó[­n]¬ºõNHC²’BÂDÿ)G0Åi:u!í™è8Ä’A7U
ú.Úï•¿ƒ'wÆ?Ú%+Þžäz*¥™“|œíN{s14fÔŒ˜î¥'><Ðb@žpñ]õì"ú€ï
fᄃt¸õs·¨ÙIærKÙÃ7Ë-;xa%"îààuÄ?q³}Ëÿeý¦p®>¦¢ƒ-MóÞà¾^þ{g°ÛØt;xu»À÷Š×6‚·tÈ0»—¨m<8„™R7o÷RØ]²£ÃûÚÓxvÝÀŽ©l<«¤,
óÎrÏøp'.*ÚTß_Ø.\íö
¶3{–îè{™½ið_qGY8áñÑy—ÝŸ
$À~ ·ð÷Û×'%.Oæý§:µ–€ý4x˜fí=ÿ$fàÒÝ2œÆ \´î
šô_¼¢W–à#{.é†7Í	Îô=:(…åÚg1þ‹eQá@•Vñ[„ôq.pNM'¶¾éoõ{½ƒfqDŸ&ÌÃÆ0%YÌCPðcý\ íµŸ¢Ey#&auÅ"R½‹/ ˜
æJŒ!­ÃuHš_à[$H“òñ«l×½5‚48ÓÀTüsˆ¯¸¤2üÈ}ŒÑ¦OÂìóè˜ho®W5Æ]Hk9ƺ:ÁZ&êó¼ÊQÖ±=@ˆÅIâïy¨uH„~¡zÕXUMÍ$¾|JØ$æ?l
†Òõqï~øõ
½³Å­Ð‡!º`%çGÅ­Ÿ|A—`þˆËþ^ÆÜÀ·Œl/úeíµýv£lTaé)6'‡û·•’†Ü
(×:Ö§£÷ͤ|pGû]CäCß኱X’:ãuiˆOBœÉ‡J„ë–Ïí"¶)n-A·çˆzb\Àö°o?QÞض“$ºùä âÎ}¢¨½ð
S»¡Øø„€}WðN…ò1þž³¤Pm~R¼YEµnÙìŒ
Õ|¤þ
ý•ÇçþøÇú
ùÉ5|Ÿç0ùñ(
ÕsKW2Ÿ®.ô…G‰Ÿ}‚Gì¨h㥕KìŽ	³å¨ÔÓœ|ÃQÅIáàÚa8@Ç-õß%*ì	c7F{¬ÓÔ]y’Ú«˜	÷-†¾)!xCˆÅ26«“´ò°$e¼Ö ¤¡ˆm×^Øžà:ÜÞ±*†wœ™´+o”CkDÎg
¾†}Ò%U¯Ñ¥ûÆÂð¤*œ¦ñìEÓ¶™~¼ñ›[ÜÓ_!„2ôøw”Ȉ™yÇÒ˜9‘-T2Ì£¤)/, ÆIw³;Ÿ”o Ž7AÐÁtô;üûµóedendstream
endobj
37 0 obj
2242
endobj
41 0 obj
<>
stream
xœí[[wÓF~Ïéð£ô ¡½kûƵÐR ÄíKOÒ$¤œ&v(ÚߙًV¶dKq;Ã	–¥ÝÑZß\¾™Y}˜T%›TøÏ_û¨Pa)oEqþîå Q«R©[ï€Û&5œ7ÀÀeƒu¨vJ¦Êº~oß;°o•rºÔ¾×tÕè­î+b¼>iª¬±ö·XÒ¥†+e.ΣˆeÂþ9wíB)öì@îh¶ïÉd+Ëà®AŽèÈ;"ÔÓ«Ð6죖’ѹð,UÕ[Ù¿uZ*Àƒ
¸…
0yÝÀhyÚÌÅž–¥‡NÞaÁÒ@Z
T5=Ʊ`j¹g¤›âz?‚®[Èá•óó¾·#b_w
জ¶RË,¶è=ѲU; ÔíÜoPMG(I-üoÝÙ‡ÒŽcÕ"E^·
{ë²7Ž[#ªÈÚÉìfi{Õc~Öôá·ŽÀcsÀ7V|ç¾:s¾„ð%‡K~\Äu‹Áïß2€ûWÆQM½ÿÁ[.ÛÛv%w{DU
eë ‚ª9²ö‘œª¬œvâ0À‹e—çG_ªÒut•8p
ïÏO]RG;…¥´%ÓáQ°èt>
stream
xœÝWÉr7½³òs3 ±­X);›Š9¥r`,šaUHÉ–œØþúôkÌ&[TÈŠ£JR¬á`°ô4ú½~èy]µ©ZüºûËíìd«õͬ­Ö³×3#ƒUw{¹­N<÷4¹Í¦Z¼š••¦Š¶ŠäšÖV‹íì'õ¥®:Çß÷Úªgº¶ãÓ…®CÓ¶¦M?/¾f«ÆN­:ëØðâ’ý®kÃsmP^ΖԎr“mUSÛD“s™j´W–¯†'’®=\j£zÂoø±ü-5¥¦5ŽÔ{¶¬ntMܾâe¯¸IÄc^}¥I^÷SVÚ©KöXÕÜû-6‚žzÖ¼ìVöbÔ¯¼Þ³í6ÉÇy/Ìíʾ­ÅBŒ%¬Gý"ßäLêT]Ýîü‡ÇDMNÞÊÈ/˜ò›.ž±ÅZŽBí[KÜtå6é¹·‰à’‰M}ü÷.:ÐâÃót”ÚÀWÖ^ðï|¬Mnì§à»üoÀ7DEÐþCÛ\À¿êãy‰xFAýÇ>؈:£'ØÐüK ¤üƒoøÌF„P14!æ¿Ç¨‡ÈÐÙè^5ð#!žñãs$±HÒ¬€@Ì5ÙÂQ¯g@>—6¨²Ó6°'–åˆúüGpÈs0£L.B`Ц”ÁŽpHn¸qYË9¹\Df02h‹HN§=DL7c3ä#EVÛþPˆ-ï)ôa˜¿Üs<©7~äÜ/ïÞ“ûa„Z΀Ò+#|€”#BêA–ÈuQ±å¯;”õ\³°D@!ý+D;òi‘qD?â0	÷RΈڇ,NýKóôH#…¹‰~OZ6ä#_mAþdΰO
Iü‰Ïe€™$>áøTLžâë[áÂV(Ã9±ùÀv7»5#˜$ñÕ`wÅk×PúeA¼ˆÆ&f…Î寄~ËF÷ Ç¡EÒbïï+mxW¶IŸp—:îš»2ÅÎ$Nr&|1ê¢4:~TI•NÞ,Î{vä;ž¸,j&Œ–“GñàÔS~\Nk˜%8_”Nìðà9ê	ØôÿIªEéL\ONkŸc©J½Hu–ö mG¤¥P¾q¼íjOÑ'4>Œ Ý=b¢øq·:é'2ÐÂôR£n&¥¡ûXòÿï…Éãj•;J«ž0xRYHRóɹÂÉþ²ääè"¡ŠHAØ2×NºÞAÛ­ÊGÌâ”§âTwóÅ#ÛRYvÊŬš"Ò>)QÃ^{	]•ºE*’Z¾rà3J§Ú”¾/v›â'\ÞÝôÉCΦ¡å÷:;„1„òµ„&‹cÝrÖÅóîK”BFÅåÔQxqÕ«ñMv%­·PÆh%Îb2¬\=òÐ2Ó-œ-f?ðïOw'%endstream
endobj
47 0 obj
1037
endobj
51 0 obj
<>
stream
xœM11…÷üŠŒíК´¥gWåEÍ&N'Áßo<¯(!>
stream
xœµ[[o·~‚þ¡/ÝSølx_²o±§.ÒU´@܇X’­4–å›’8¿¾sáÃ={%@a8>ç,w8œùøÍ…ÌÛS3ÛSƒê¿ç×'Ÿ~½œ¾|bN_ž¼=±ôð´þs~}úðäSgæ”\:={qÂ/ÚÓÅ&çærzv}òÍôh··³I!çéj·w³sÖûéÛ™MŽ)y;½©?7}ØÙ9¸’Êt	ŸŠ7i™Þíö~Yf,Êò>[÷Ÿ³¿òôa^òbqúçàK>=ûòäìßLOàµÙæÅ¤éõΕ9ºìI¾ËÅ£P3›J™n`ú<'ÜtZ…lm(Ó-}4)¦é^òÑ{×_ÿUNÙ˜¯Ã@»$[`yGÔ³aö!9T/y|fE=¢âl˜æ›£µ¾Ðò¢	³	Óg }6sÌÓC\G)K K€)#Ø
À—LYÀPnÆÙóô
•PÕé︼쌋qúaçalòQ
­’ìOqdö`jù#¬)ÅSä5Y˜‹)ds?.
|¦Ç;ÆwÓ~{ºÛ'þ
:¹a)h>7½‡¯à2c2€žäÙ€1®a
ð=‚Ñ}šKŽQ“è×ðÆ[xãr¦ýηŸÁsðüÀäŠòôu|@¡%/àI˜ hýô
d œç8
i~úðGÒñ~{Á*ÆO¤ßnñ­;ŠÙ®Ά+L‰–…®á7,ÛTıœËÚÖeØ7ÑÙìTâB/}z‰ÓçÕLJ²42AOíQUhÄGË+ûÞ„UçÁŒÎ‘À°íGÝ_ø¶Î	Hø¤
A‹ÁëdïÙHQïb!º˜«öî%?ÆÑÉjÞ‡—*@ƒf^Úç{±ÌÞú9FÜâh gÁVÕ™~PwOò¯{ïБ§¸nnÀU¾ÜEa`Žg»ìq

q¸J: yñc$$•@sÖ?¢ïqÁÒH6PÅkä
6ɳ³œlô¦é„<ÀMÔ"†·f0ŸÏ¼Î(,˜ì£ Kñ6ÔíÉ:JÉz
p^V<„äMìY€‡30•yŒzÂÊ‹®dU\ðX]€^gõáHÖCÏ­žŠ‡,ÃëzØR^sŽuFö,âS¿àþ‰j³0Âxɰd¯üù°û4)o¿¡Ër[VãÔŒ¢œà"=?'B¨¡°`‰#ÐS7¤¾
–qÇGAGPÝüâå7+çN–‚õD*h@CYRÜ[tÃÐ*®µ¬c+(ú§1Ú‰â÷FTr$wF7Ìíпw1z!{ÖW å©À-¼2úhõ#—Úð¥Wôwï9ޱÑÈW3ϱ²ò…ÇÆPN†¿½—ØÂhŒE®›¾–RKÓ(Ÿ£Ó.dÖ¤¥i¬2,ñ4~ë ¡åŠ1ŒyR‡h‹Ÿß‹ÏC4ESµu¨Ñe³¥ýô¨räÇy“Ó¶2`ï<á˜LyÛýÙ/9†Ö¹'R¸^o	ÆÅ›Äì›	—§äÚjíPó=¥RMM5ð+¹ÑŠG|iþpäÊFmÏ{ÒT=Ž£îüˆ¼·E¸ôß!¬PŽåÕîC2„¥6ß'»IhôÀD’dð!xïÑ(øëâÒ/¦g5 ¹ŸÁÂÊÎ$¢¾«°J³ÛHÁ8ËØÈsX¢½W ‹ÍQƒ(„;AÄæQœx»W ª^8lt©•†p‰‹³û
zB’”'q ¢ÔêÍ3Ê´ñ—8ž*¹¥—
*ÞV^_ïz7=èû½¥]è4\Äm«-‚è¨cbª1Z½OzŠ1P*^x‰ÕÆr‡GõB¥Oñ°™üKTûóŽ\¨38$Â
QúNz¸G’ܨ1#ª‰V¬e@-宑æ-UóD‰Ì¡Ê˜)Dg©4
‹¡0zt]ÖETD³ým‡ÙnS0ÝðåsdIG+þU@Â…Þ#6¿ÒMµÒô8Nüâ	¤cK÷lx7¤C$ºÕÎÀµúQ‘²¿éë :òA.µjÅÂp1sn©zí×C¡ÔÉ®KUE’8´¼â“^ˆý L ‹”ðó²¬VsÖ©.ªnÅÇ^QIMÉ«âÁ‘ü®Pså6Ó麰šaØö¼‘íÊYh%¡°•qÍ€ô\Ø€’q2¡-=ܳí—Lʨ˜£~†áØpØ„ÑûN888£«cRkÛ€ý{Új9Tâ²0ꤾóek7
]“¼ª»}•ìCíåõ.ŽØ¬"„§sÙì\Û[§wæ…òÒغñCõ0ç4¨¬`1§íˆÙ(nV;D™£/l\TØrï^­ðÒFGŸÞTð¿2¶ª¦Ô>q<ô¾z3†Qfm¯®ÅÖuÌ@ô«¾'ŒØKnYÈćÄîºò[esÛ¥*§á
9á3ø~
x¾à±øîŸ»
žfœ1œòlc<ý¡2½g"þbèJóiÍ–¿çb­|Øý󔨅£õ.™fSì'=Áè}xF2Øk©ËÝ+o`Œ¬^Á?`ßÛ«¡cš~6u7š8*åtÀCϘJ¿öÝ[Œ9·½Vépî>ÕÖiï5WVòäâû³RÔyŒ’Tñ©¼»”­fžãú°·ýÈîÕx½cJ‚,àWS¹è~§W‚1¤Òoi&‹6zk2†ÔøªÓšdXËàšNÔì×WŽŽ‹ØEà3Ë5É)Û'`-ÛM“1kŒìåã‘û¨³Ü2lLÖƒ¿ßEª~‡"G%ZP9iÍ'çÅ7üt‰ô.¡ó^’Þón:>§\ê²Öý7ŒiI±êÒ]ͤ†³ç¸m}€Qçxô_“ª’}Õ9Àbùë¦Å#œŠYŠm¡ÛžWw‰¸:´ÏU?æÅ"û—’S|…TǤÐì*c¶F[TyW|¾TƒgÝ+?"z ø´Iè¿Zª0ÜèÊ7Î=H¤?“3©sÌâ‘{Ûž©ŽM±ž/੦Õtúެo'Þ_5í#(«k®íz‡x;Ö!e#/fúj×}ïÄëõì¤ôˆÉWU­ùÔ”Ät<¢ŸëI´Ú<¡•‚Ä\º×QâN×”²u‰Ü‘\æÔ:uÉvu¾Mwuʪ`‡ê¨ûL'×~¨¨†JLn?ð†WÞ­šÕT¹qK³Kúiè-l‚xݹ‹µ!Ikw¸s‘mO‘[e†»¦žî‰Ù{Pm§£Â¥§ÌcõÕHYš¬zX§cóFTëû.É#tˆoCpÂZ™?ã
ï‘(¢=îÕÇ«\îsGÀÏKOµu·Y.®BõF.F7mèøs¸Ïá:ëT7~VÄs25Ýu1¦8"w‘µê}׎½ ´#Ž «M6Ĉ¸ƒ0é
+õKͤ¹wó¿ªeó½*¡·…ÞÖ>W|Ö´*ô Ö­JùùVõµçøÊÉ¢;bÛÜ,¤š\íÂFÅîü–V«4ÇgrÁ©öf#–vßDµúT£ÜX1:±TLT»Â#VýÑà*¨ÖQ$öÎÕf‘¢)Ðõú¢WM•Ò\ëdF}%¡Ù¾‘ï=
Ÿøf™YÊPGc	K;.õ
a­±"5†Í†Ñƹ.Ò~±­øJÇ
á:Õñ\1%•+â…Ë}¬ÉÀ¢‚ †”>µRÁmè5Ôå?mý“¥õOäÈrUF‘ü?9wÅnR*Ôí~Ô™u8H«™•>ÆS4ǾjÜBÂÀ(=³BÀðWʪÞýù0ŸâeJßIa¬#þÁ®÷W°*A“±“RÝõïŸÒàßOa<¥¦´É)ôõ5솓Š=dú”ýÿ·±Úù¼Þ,Y¥
++¸¹ç[CXlízý•¢h{põ´
m
÷늙J…¦äXrÈ­¨’<¹%^°u*¯\?õë#ç®4€12ÿÿ’O½†t¼?ò­zä#ƒœ\!êiµ\ňƒk©Û®
·Tü#¾Ý›ñº´¿u.‡ã¡^2¬Ã€Y{[#’$óç“ÖQˆh‘§-Ûé«åÑ5-c¡ºž®lµªv"Óö»ã²_Œk·êÕµõ=‹ÜÇ……nÝ[w Ï:L™)„wÝ)•‘·ýGu…ý?æÅáA*Ý6çk1£Å9õºÜkOž®˜‚2Xø	fn]Ïû{v©,Tù 	x®*qZ›B3
3xñÝDºÎö†®ƒBImrÀXï˜àÔùK©E–þôu—}Á§
xA_ë¤Fðœn‰Q)Òå_Ãc›rXR—›ÅŸ}½”o³¶H—}Kùc¦ž&	·ÉÖ’«].ÙÕQÞú\œ¯ƒûõ…x½«hØiwÆ(ü9?œüµ£	•
ÔêjN»sÐY¥K5£Q¥2'‰«óCý¿ÆMH}q•È窗†Â°vµ;«s‰ƒ‹.ñ=‡ßtºr@G0ƒÌ"§/Cý,§Çw\ç¨MÇvƒµ×#­+~èr!Òí
cçù®ÝlMûÐÉŒÃ`k°7Þ¬8ÜöÛ‡’1úz«¹ósóØ94ãu„–}ŠñþÄ\瀶q•À]¾!ËM€ÏÏNþþ7Âh»endstream
endobj
57 0 obj
3919
endobj
61 0 obj
<>
stream
xœå\Ys·±~×UÝßÀ7ŸsËg4Øfñ›%±ËŽ›©¤*¾U—&µ•H‘¶[þõA¯hsH*¹o)—(qƒ¥Ñøºûë†>w2Âü÷ùÕƒGßÏ'Ï^?Ož=øù×'ü×ùÕÉg§¹óùɰޫ;9}ú€¾t'³?™CFrzõà;¿Oÿ{úUnœmí×u˜bþàô"7ú|ˆ»?íݰ®K\wŸîýî»ýÁïNóóa]œvá÷ï÷‡\~2ïÜ>í†ýaž—üQØ}	¯ÿ¼ÇOB~2­kn<´õ»oK?_ìå_Í­?/­ÍXØÙ·åUî—Ö0»†ƒOaXNaf·®´”çù³Ýýq½ä^Ýîøõ‘þÀvOàÇüx-ÿ¢Æ¿À¯çðc€Ïò„@6Ë„
©ÍÓòð\åá+}x¶õùÙ~ÉÿHnÆ!è™çz?ë’Æ°{§¯•×OõáìgŽLÏ^—†/ôáµ>aº0¤	”äë§ÿóì¯H…¥c²Ä.UbÏTl(¢÷võüåùoKHZ‰Ø®õÙ»Òð‘ŠíõÆÂØÞ¨Ø~Ýð}øD>ÚÚú:àâïû9¯¶¤=ч˜†%¬ á.ë9ª7ÍW{?ãÁtþ~ÞÜîíþ0åùFœ@žOÈÃû‚þlü"Œù3—à•àÎãY~
x>ò.÷"r»‹ü¹Oùsš6Îò9ü8“9ŸçÇðêÊìGd	¸Jw°ÝYvã8•\æÕŸíA´~	ôÜusp±<»ÆßQúì9	6‹(àZ?/XõlB$Ô2ð÷I×{Å3¿¬ùÝ
‚å7°Îó}˜²
-ëîå>Z–>&Ù¡|à”|žü6Ï´«oµXéíźzØÝ°ÂP®4SÃåpȧ?‚f¡8°këß'Ôå0£fÁ¶ƒLBÒ_E'Ž2@øFœ§_—ÿ79kÙŸö^7憾‡Ç_ð&5y™ßFÛ	ÂÐùø~SdÅ~=.ý|º7Ó˜ðøˆYšÈì}²m\6ÎÞˆi9ß×XU`ìPþ´aƒ^mõøt#¯í|äá¥öSó¼4|²ÑPwáN–ÑÑF¢®¢ú>æ¡"¨Z¿Ò¯¤¤#qƒ)âÁÿcÖtƒš/èØáÌb$PuÅ>ðBá)*xL^ΑQcÖñ˜Vœ‡"<¿TǧØEÀpŠú–ï¡Ã1¸ë€Ò÷y·ƒÇ™N4Ê´¤³#@ýª‹°LL€ç%t0â¹ÅÅá'ŠDŠ7ÐEÌÓH΋=’}t§/.
¨½@ë&/²ÊF€˜ížÒ6ä.LWÏÍÀy`5~s6Ë(e¯ôeŒ%7EÌ”õh¦$ ©
`¶Þ¥bvQzoÅ~½a¥‘Í"ÄZƒ¬*¤„*$"d26¢c¦6øÊœqBŸ €Bÿ—¯G3Ä~‰yˆ\÷)™ÉTZ¨"CŒJh
tKŒëdgc·T;3‚ÑÀ{c•Èz¡e^ã­Zæüiçt_¾,Ë1AÂØy?-Ñ9XfšœÅÉ|ÞÁÎòñ	N7ª°[ñÎZbhE®®Á˜\ØË	lúl!ÛLæ‰èÑÛÊ@“8ꞃT:刎@䇯‹Ç”b
ÖwË¢÷xÔÑ<ÿ·qA#'b
[ÖÐ¹ÅøOµ!¤~nÊú?Ù²•ó¬z¢¯7çMëõz££ó­o^YíÜè½<4–õš*?¯›áÅ–Éê2,*šÜÕä#
wì•l–§Í93Þt9,°	oåKx½ð¶cXØ݆=tW#ÚªÞ5çEдx¦&F=«UyñQ~8F5°Žla𤼠qRíÉgn`tËnª³š52›•?]BIK1¸µoá”V_ãéÚ¿ë=E	¹«ü¹àIŒêX]Ô~_^ó+rÌòÇÊÃôGå=g¯
Z£]\(*71aVä—0¯gòD}ëQ¹#@k4ˤ.c:e¶f­¨6sã¢j£Òasæɱáàð-Ór:Ž¢ýx;LI£‡D&hÏØÂÓ=¸uð­“ûB$ ÈdB ØF„ö€ýâ]ãÆ]35’?ï'¸Nqˆ}Yà-…g ÁY1Ùûf×ú=¶±²QÞ(bզ߲ŽÀ=âwB’_œu•ÒP¢µ“ã5lïa™ÍÖÊB—Z2©èëù?~Yaî<‘n½«¸šËÿU†j0Å
šúkYÔó:~ £³Ü|~=¸ª$û÷°Ì!ÔUµîºh·W±¼»¤I$ûuQmàM±ëaAÊ.z
ÛcÌ‹m"¨\¦ãF4‚¡gÀ¨tcã±ñwMüqVõ¡³¼—JÑ´*eí¸ZŽ”·Ì/bœ#+ª™ËÛjä+žcY €9þö%âM(ŽR“LEí€ý€7wøNbÊo%ðòöf# !HóxåµK„Zs^bpÒ/Vël©PÀÏtAÙ7 rV¤D5¦YHi1~T–@$ÿ¾´ïzÚ¶è²»‘iç¶„•ü-ãN\ï+^£ÀL‹¯y­àúüm/l/›ºÞ¾VùþZõŽ”=eL´õ“u;$´<Ó¿Ê8óö…hÙ5ÒÕ &Sðäe^w)¨
äÿØ^X‰.“‚J=ƒÅ’18TFªr¨¨áôô¢TOAûB>Ï%þ²Îjü4UŒ{ÃÎpp«…#‡XpL¤8¶è-..qí½i3ÒHÒ%ìëíÖVãO-ú¾aE^Õ¶³$&”–s¸íc˺oáÇX7ÓSñ»u)Æî`º“	ã|ÅmLF6rÜ#bN?áùþº¥a}eþ`e5;¬bÒ̱¶‘rùaÑ|=,>x̵çÂ⑃NO[1Ì­Ñ™÷ÖzZvÔÆ÷|NÜÑÕø¶ÍZÍZÅŽde~š2ÿ¾YTØï&K]l‹ÉÊü‹ÜÑFrCS,°È´ÿ‡d‘¶2í×[ºÜ/mýrââÕÈשœ8šÝwÙH3°—9’saÝ…¬ÝÎÏÃst—ͦ[RŽ0@Ó€¹ÅqX–à=“„ÙCÅ,Ÿúf@p‘‡3¤…/©×N¨ó™-ÓEùæ
ŸÏÛUþÆMKD´Æ–+ÐLyLÇ<ÛÂû8Ù0L!m±‰ŒÖ²PYFÄ‚ïd	­w·Š_§AdŸ/Gu)²Ó79]‰ÙòKT°ºcÖu¡²€iüâÛXçá¦hS›Hn¯•nÀú¹E1,†´¡¶ƒÒöm,½Ãe“ýj!l\CWÎ\´Cêk¬sµ{LÐõIpÃEÁFå&ÔŒKêFš5
>¨fÝ#'Ã9Ô:Y†	±#Œ²á"ëðâž'DJÜ¡ï!ί_0ýª„6+­µ†¬žü«+à&9Í¡¢rÙo9A4uTd€	¿Òb¸dOèáç…ÅlàCJ.¦¥. ç¯6F§ÑW]ÌõUµÇB¹B4âÕQ%•‘2iÀñ¨™|ªêjҪ쨇ö‚ÓÆæê¨WPCš#•H$og—GjÙjΫ}³Á^uz”8`ÀèíÃmöÇ{IùâÊk¬²þ”O+
´.äd÷üˆs–ß…^tøQZ{ž%{=÷±s~"¥ƒŸfå­Ï9ºj|µJdð‡›xŸj´]^*³º67y`ãV*^ˆÏ¨¿K‘ &àÍžR¡8JF—³dr(›É®ÈÄG¹)°©¤~‘9/y4³æïö‚„â‰NT˜4Û‘æâq‘nÑ-.&ùž‚àL^átôù&.1ðÅ—Öä&6HfŸrTÍI¹D1R²S*"À{ùÏÊ-sïÛJÏœ Q|k£Xýi ÔÑlÈB½NóRJc˜a¼0>¦ÈK’q—,áÙÝv)7“4‘Ó¸¥xœ&ãîâéžTéºAJºYÕ<ã‘Ù”Ãݪ”´®­(vÅL˜¢Æ<6¹Êû9òQʧ:¦9r@ð%§¹äK/¡ï•b°6œFúì~eRàJ®FxV•¼4Ær»6>tJÒš:[a–Ø™¯oðQ«IÂ7Mب!p\)Ä/¾cAûŠyÃæ5
ód¡Ø=çªô3µ6q¥”÷ÑJ—õÿ“Ƨ(aUÉÜ{…´¹ÛÁn
àÂkÔª6s»„§›®¹¼7e‰ÑÏ}é#«â%2,]ÝfCaº
µ*û‰w'ý}ö³Ê¥Põ›M¬é—è£PS…~!i½j¦^y•ÀÁˆû×Óhõ)Iáõ”êùÇüÏ€ô!¹Ø_ÄFœP^­là–ÙZpž>Y”ó¼ðf.ùuäD*SêèÜååÚd…%ÃܺãÙ̼R›†—Ò;:ï«*Lå¯È«mªY¥b÷¦8ô‚³ª˜>$|èi;®3hÒN/™Ór˜ëo¢­6v·rÏ+*8įãJ¹ÖµÌk)¿µê=Þ&Ì’{é=öZLìØ x-Þ•™˜âÝ?ò&ë¥Éàz¯KØpº_Bq6þKIFˆfº)ìOEyLA·¡¸|š*U(®ªVé*aLYÍ]Uý¿"”k¨E[>ÞsÝ÷´U
ÇBX6Y/†'ÒSΡ4ºyªÌA(µnº–&R¨tʬçË}wqIx8\ÇQ£àìTßÔDUT'mÊC¹Ón+Nš8Qåväèêßc¦¬BèŠßîÀB M¸Ã¬t0dÉŠ§­Í—”—0Vé¸WÒ†e®¿”Û,Ó‘êa®;FIÕ~ÐÑTìÀL7Ù©ÉÜ»dµX}1àêü‰¤\¼ï…;·½D4Ï€Téá»5tV“†¯
ç(â2ˆ[¯Т
pÁ
â_OâÚqàØ2mÕ§•ª‚²û{þþ›ü7ü5~¬¶`‹ŸTWÚÑÞ<–"R
[éÂg]<‚DlB·ÍD©ÊÖéž‚÷Rê~ÄÜàNlÒæy‹c4w'í°G‡jûºŠ5©8F1˜kbÇ­3s€bž¦~«\ãööBÞúˆÐ}4!ç»)Å •Öd! ¦r›ç’eÐ]xC	]ÁM°4TÙc6>t‰\M–\]ïn/à`ÖÔ_CcÊÂ\°™ÞVüœä¡ó‰UsôÕ¿À#p‰§PÓ¯}V¹[ýèÊeï{ݱË_Y¨Ò`*•¸?5(i*B—Pê6†ÍL
¦ ÿ#Š#»bÀI>ÖêüžÍÂ]{ëÎVr4Ť’°Èǧþ’ÿû'Ê9Ýoendstream
endobj
62 0 obj
5010
endobj
68 0 obj
<>
stream
xœ­\YwÇγÂÐ[îäp/3Ý=[Þ6Çòäcg{Ðf €„q~}ºÖ®ê™+c'ÇÇBºÓÓ[UõÕÒ÷ÇÃv×¶ðÿ{þæàÁ_ÆÃçïÚÃç?tøðÿ9sxt’Ä.²›Û¹;<ùá€ÞìÇp8Æ´kÃáÉ›ƒ¿oº¦ßìš°‰øïvœæÝ<
›‡Mì7šmÚü~|™[|Õ„)?ëÃæ»&m¾h¶aó)üø$ÿõ¤‰›ã&ìæyÊ/ç;ø5ÍùEùíúyÖl‡ž|ž'×;¹4„ݧwr‘§”§m¶ôá6¶»±›gzö6w°ù©Ùö›Ë<ì6{žÿ½Î“Ól#=~™'û:ÿ-ÞåOç1O!nnrãðü>ëp™·ð÷;X4Æ~¡OüžíÚ¶k'ê@¿/¹ï‹ÜÏÛ5²Nx"£ÃÜò°ÐK‡¯ÁD¯òF„„Ïÿ_«–dz2¿šwaêmG«¼jÂ@"ÑQ®Ø»0æ½Õ
=…·ZÜ„ò¯Ò°§Qaãæ,ÙÙô‚ûtš[ÜÀÃcàbNyþ-mß<ÍoŒ´©Œ1S¯Ð2¯¬ÏŸŒ#íÙmh éü/ÀcÜ
6
›÷MsÏ4´ºÕwh6¢bå•Ükê`Ú,NžóêRþ³ïªïÉ67îPØšK^ÔyǼ­	U$¦—‡¹†'¸Ç@ƒóI‘êë&â¦vب+QL=¾çD”UJDQ±6ÿØäwþ:ç‚NÈ÷¹íýܤpkÊùy˜`³‡úуÜÝ>{œ-ì_Gg÷
†Ó¯d3…™„„ÃàÒx¹¦)5ô¨áõëô`æ#w*ÊôÕ/†Ü8΢y@†óC²8ŸÃ³»Pƽ-úR$Mz.¯¹ÃÉvP”„Ì*
ÁuæUœñ‰¨~^Ø*núWcÚ<yÀiÉÝe¥~¦cà“¯ô	ê–,•«Ÿ'Z÷™l"L%pbŠ.Ð6"žž
Žá…$|ýÐvB½º	âØ çÔÙ€ªCGÒc@LO4ÙO?Ÿ‰TZIãîÒ
U Ÿè¨@£2ɦFƒžU¿5“)B;‹t·„_HAô'÷§¡›íáä})¬ª7²ÿEº`#Ûwd	;
rå!cNìaCãoSkB*Z½G*À—ë²|rÚKÇ7’KL¸-|Î|ÈÖìT”4ä’ÆÈ4¡\/Š!ˆhGX!ŠÑÊs
wu—ùòG°F»cêô}	ÄÏõ€â¡Åé t¾=Íji;~O‚!½vÓ$zuCëÌš¥öÆLúº¬ÖÙ9Ñ€5Pº·&jD°òÎÙªb§”È$TLÚp’7ŸâÔ´£s1Mî\”Ñ”
i)ÚëL#m‹G/!1HRàu!¯óÔÇ%ð3]‘ì¶¡ŸqïœPYA™mJÁP4¦aè2.	í$z¤Š‚ï›T88ík"FfÐ:5È?Â@‡).”À@Cƒ£
q§…&@Ÿ¯`WÎT)Y½¦¸SÔºÂ=@#Oúú¶\TâYÑ#6éC´H–
»4Ý‘4Žk•ºlˆù1+Jp®¿Y¥ÆHV‰­MðùÁ„9¡ª™	™aŸØ&‘rá¦x0;F4aåÀ­ÌbžËGVW²¡&‰|	\Ù?n2r4(K¹Ð ¦ÌoʹSB¢7Ÿ³&€ ûä-R	Â}T¿œ5–?ÈiA2—MQ!ß·j÷¹Dpº”ªmw!‰nU³ÕiœZ€£Ülj¬q>(	qÅŽÜ–áý°•¡¢
E5/Vð=hþl ]o{ÙÌŸÐoùl€¾)ygU’Ȥê6Oª ¢ ʸKª\Žä~$pÉ|Ô#RüðH[‡BèàÂÔe·®¨€¥f5êöwÁ1³±·úËгåumÉÂÚœ-¤€Ge†]d«";¡=ØàØÇ*z{Qvѱ|ÀEë/Wõþ§e¸T:»'âè!.Þ:A\)os`Ðb®ì_Ut,•fÖÆM„•>ÖÓjpR6ýÃT/ztÏb¡	Á¨ß0þzæ¿7¬ÆG©:2>ØëR£'HZ§¿Þ>S'M}E
‘ü¨¹µK<_8¦ß³µzÍ( „T‚ýWEU8l’ú©èUí=z¥@Æ’¥õ	3}~JÏ€aY.1u¤¼å5Ìvr§™èV`“×AƒLÑCX‘êS›Ùz°¸BKè ÃLŠ.ùÍ=ªW>-
T)/Án²Ž­…LŠÌ[;Ú‹¥ÍPŠÊÄÏð°¿ÕðViá\˜4ÃÂgžÓJ›Ê…kñÆí™Pu&$檇3oÛ)œâ«¦Ig3Þi°òŠF¡PG†b½f§:‹‚%¹ o;Ö€™}ÜKÒBèmFc½Hé/ˆbîõ€Ãj–&pȳޜ㰸Rþg¨„´Po—âÿ!r*Ù§¾êåš<ÒС·ˆ3º MDŇEœûX"4ù—Ãb£bØåo!4ð[vIO©Q˜y‚/ŒÖnqû3EC£BÐøuñ‰WØdçÞ>©§ø«ü\ÚBe>în
Î[ŽŒºL!§™˜ÇFd‚ãªs[! $ é^!ÈÏáñ*X_Ã[xÈNƒ5Eœ;Œ¥›Ö5Zló¤¡57Úb …^VoõÂŒ¤Úbw©9a³X CQñ_²žmÑÉ8gZèäLÐZ(„r_XÓ8"n/Ù%ÏÐå?ŒoÙÉíwYËäX•¸â“e€ñ[è(¡ÍùCËâ5`x†S»åÓ*ý\XŸd¦&bäÿ/Ó-iiÇPé°²Lköxü¹X\ëcéX·L–DýŸ0i,XKòéÉòЌŽÃ4гé2*ÓÙ«Ôm*Ì hÔý¢³„Û¢€ нLNiØB¦'m½MF,«>Jp­ˆpoéX=““x•ŒÔ@ueÏrÙMÝŒqåØàe“¼ØÒ…ofpäû±	ye¬ý– f|†˜iD½"n$®Wr‰"%'Y!u 
ð;~bÁäªq« ½9N¨úc»®úùÝZõ)}žÑ=YÀ¶<P\ÐNV‰àx3A³~ÏnÓzÂÅ&^wRI¡qî*­´ºŠ{Ú¯:Ž”Œ
@'œ)v–ÄÆÍ‘sé¸Cž,œ[ŽœÌh”Ïoºc+•}¸°ŽÜÃ}µ¯T{f˜Ã
Å,ÀÇòg©éKªC	ƒë©wGµŠ›òñÖÂ¥9J%è IôàÇM†Š·Âür2ÉÙ å/¬¥¤iÝnT
Ýű•ÔÒ‘,Œ¡ŠIJ²£­"߇…óê$|°’0åPJ˜¦Ý”:SŸ\8îhQ?X­SRÔr¶IÐLüt¦+ñÝSºÌmXíBkíMÁŠ70 w+µ7Üa€vb%à]~`±˜sæ#Ä©[)-µI,u@%²¯•(µ
†Þ¡'¡T1YË`kCŒï©¡*³Æê©A“ðéÉÁ7?æ;àý˜-øâaÚÝ0Æn UyþæàèéÁƒ§Ç‡7?Ý^<øî°;xðü8úúQþçé'‡¿;øôéá7{¯âøÛ.r'LsÞtf×Mt‡,©Nq9ß·+NU¬È'·wäSHÔŽHeQ«¶¶ÙZ26sJ‹0³¥ìÃZp,›Ýz¯åȉ@ZJ©2¾
\¾ÂÛõ¢[Ö-ÐÐm›öQ‚…令À»8¾@¶@8épÜ(¼r°N
;ʘk7z:–ðÆ+ÿ
ASnïà ܌eƒŽCz“ÆúAÛæî¼Úà,ÒX×!8îű3†;~ÎÖÙPJ*·E«dïØ«§ÞªKGø¤å$¯\…ÒÞ½ºË?ú¥Så°Šú.±O±¡ÖkªÂg¸${€4v2›Cçx…³q+	feGq½HÝ•«¹¬â¢Þ¢í©YËb¸ÊŸT3h΀žI*ʲ4{Äš@¼F“AÐ3ÅëàaãK¯°~ÕQIQd­¦-é^ÜhÉb.!I’Tn&ïÓ ‹¢ê…@´LãÏZ©&xDGê¬1ÅY”­ÍêxÔ˜þÀÒïÉYø’SQØ“lÑ¢Z=‘—•¶yáGFLÍú0!¿¥øµ)8«JwLLÁ\C{Òh)ï‘	±Sºvì
´U®‰QµµTgCô¨';fÝŒ“hòÄJ_u騀¼©ì…ÝÁHЉJL#’ûBÜ\­ò¸.6óÑJÁ™¡$Ñ‘¤°L·¿l+PÑŒ}ªøHê6Ö"4×EC„K¿yRÖ“¸v:çîÛ¡GÌ÷ Lå"ÜI}ÖÒ9u~MfZaRˆèÖ)º*VL÷É”¿l·Õ²¾ù·†ÉÙÃ/öÌ—N%WBÓ£§õÒèõÚoÛÄrwêòéB&¬ Z8Ha®õ0¹êÅ\£¼¿ìÜ,•¤™¡,¶cZ­lg§…#p‹lëæ³¦.ìXT¨õ^Ûêõ>ªã+¦>]Ï2ˆ„zÇ]*¾•.}+M_X]EˆçE|FÑÖȈõõj˺"ã±áQ™°‘x¥YLmæVÎd¨“0[“ÅzÜ’2ÅWDX©(¤O5gï«~a«ðÑ·”ì9ƒr¦O¾æ¿Uš¥’ªžŒå²×lÒD^å¾ÞY½u«°}‹dûŽtË…TlM„q:¯}Q^¤Ë3GKÊ÷{½7e¾= ˆÿƒænlh††pø]IÊU2§ÍD}^KFù+(7°KíQ˽^líma¬nU²l[Œ/—‰,ÁZÞß×W£ô"p	IU~µÜÍ!Ð	øCvæØâ–$NL@^¾Žp¦Jt°3Uª#Y¹fƒ÷‡Nk.©E멊Þ÷¾$ÜØÞ±nv2<îëé†+^ƒåÒXž‡¾?t=EÄ#®ÊÌT™|O¢{ÊR¯<þ™(
«BvhAx¥a*&D­—ä±ËG”ΗC”6É2WÂ7ƒ~(¾<Þ3¹SÈ?prå¾6ëJ	ò@;O‰s;’uìkù
ˆP¥û÷±Â÷ãÒôÝŸèžô‚­Ð») Çõ‚®\ÑÄÚïc0œÌ×Zÿ:CÉ|»4£¥r«¨rÞWª/ç$¢[ÜqgloÚÅH‰¤oYÑžßÃóÖô¶Rù\…nô¨»´™ÆŽCÅ+ˤ7ŽÔžù›BþŽ›e
‰#Â_;ë&û¯ä©Ý<Ÿ;–‚àÞü6J(.>ƒd9VLœêu”+0„£òrø&dœ$v íXq´\âÚCK~88Ô[W}âB¦‹L_h·ª”^zg–B™n‡ÕßS !Ö¸ÿ\îlЬÌO‚'ò)Ù"ÖƒœQ:Á9ýƒŠb:cV}¥“'K´vP­¬ÒA/²z¦úÎ{Ç’®1ˆX\ÐÙÜežÙ*X`·Tsj
æà¥€nrPô,n>¶u5P4z¢|u’|Xl§jç‡Ü´sæ’(ñÄd†ö\%Þ­1¢U¡,µM÷éâVפÍTb²@ü²atžÔW%Ô6¾hp5ˆù’ö|QF@gF+wìÓr.Å­ím¡Y!µâèØ‹t«!†r04€¹(‘òÌR8g´f¢®-bP‚o8àrâ»
’&½ô"#”yXàÔYÞXºßñmc¹ù•:¹w?¯i¨³mdú®™K1üº›Ç¡„ʶ•o9Pç—Úe	œÉ÷HKÕòÓ­üa¥›|Þó<¡Cx2Ö$ÇÚÊvÒ_šÕ;©a᜻*i¾‚Êù“…M/+æ‘èÙ–\•Ý÷Å=ÆþÅoŒR×S¿ @Õ­/1+6ž”¬¶Ü‘䛾o¬),a˜qµúK§ƒ‹/F)·½²šýM\>S@iT“s˜hûæà¿›áãgendstream
endobj
69 0 obj
5548
endobj
73 0 obj
<>
stream
xœ­ZmsÇþ®ü‰«|ñ®KwÙyÛÉ7!	#N8T’DâÅU€°1¡\þóé—陞½=,R)
tÚéé—§ŸîéãçÕ°1«ÿäŸ×ïŽþòdZ½þx4¬^ý|dèå*ÿ¸~·º·ƒÆÂ“M’Yí^ñN³šìjr~3ØÕîÝÑ?:߇í¾ƒÕÎèÕ6¥ÍèaÃîökß=ìÍ&¥èSwÒÛîq¿¶Ýžo†Áø±;Çߟôkç<™:Ó‡nÓ¯§)Â&×]àëmO[<S‚ÕÎâZÛ=ªrÎzùt«Oëju	{T_\¶!®Œß8?Z4amX»a3™”ØV„ÉÚÙM0Æ%ðÁÚ;ÁâîDo‚Ñw/áý4‚î5ï“^À378º·p|´ëc÷÷8oÁ3¿ÂûÁÛ»OõáŸz·	£w+نŋ/vßf'ß‚Û>ôvËlè~ź_úuè~g¼†wozÐs0ÎÂQk?€âØý³ë¹ë}¿aûzDG
¤ÄØýÿyoQÆGtÝ|ò²÷Ý
~øľè-y‹B=öŽE•ZèP¸AI~H¨/EyðL0‚¿âs\]÷Ÿpbœë
È1U$½oXokqIŽ4Hpi€_ÔÁY{²%\÷Úm1XpzÚÆ°1Ö†—Üè¹Ñ2ð¢w‘_|Æpˆ‘h<âÿ
R¤á'xÿÒ;+e$ÖL»¾î¨ö‘#àq$e1u!†ei[öóh!ö}yÂÜDÁÃãß(TTØp’¬Å-kƒ¨D@ï<Ýö´;DŒ–-ä較HУ÷äºaDÍÖÎN¤äGN|Ìô…C
«¤0Ž`Â40bk$áaÂÏûñwû“ÂI7YIqÆO’õ²®ˆ!ØÁù	FgA3JÀ5”d‹çoËù$<ó–A˜üÆGÁàûcN8	\ÕŽâu<^!7|Z€uMÀÉ—8DK=¼‹|™Ð>´â¯¾^r,€ƒˆëoê:„,rγ,åf„åZḏr!Ev^!{­hÀ
âÇ@±¥·`ÞH[Êú/’¥Cp''Š5SXQ'>ïSTú‰x&ÛäOröñàF’xUbYðWÖŠH7Rê‹>9SœG.ñw ÈŒØ]†Ü¸±rÍñh(jê#Y„5z‚¿Ç¨×éEâÈ0MT¢ò±
zü¢V…mX™5$qfšÇ=ÔcªnêÄ-¥:Ñ?
qCAXNËJ*/s…,ÀrY!›c"*b‘%Ø@²((ˆ{ž”zÅ	΄X]¤Ýf"XJÖQ”-¦¯{ÑP®‘¸„Šõ§L5$½Å‹¤Oм”«c„ÃxlGW‚½Ÿ{0ŒÌÁ¤4‚÷0³
VøÞ¨è+HT*©œÕfV~ýž‹8¬z
8õ>W¶j½©¨½]æK%»«­€¯¤À	ùÅ4gré›
ô RM„»ÁóZ¼É.ä>N—¸±€Vc…²gv2Pz×ììÕ¤Qa&hãÏ~‚—óâTÕþšäfȑΙ»nçEíZüƒ2òâ&6õ-뻈ú/’­tó…ÐL/ö˵ŒÚ±‚öDBJÁXíqBB©ÿ·|'1¼íƒ®~”ò
‹d$„_)tÒÔ^9S» -nÕïÙ¥ûÉÌÈ„È?ÜyøNC5îx¡ÚKÏ¿/?¯Î|‚ü+KC);¾¤Y\ãF&ˆ·«î¾„‘–ýØÊ')¸#xÚ!z¸À}Ì÷:¾©¡,!Žg¥Ì]TÐ’sýëÚMC÷MoU‡ƒÂG¢ŒþôðGö†,ßµwO2¦–X¼N†@ ¨'`«ð¶TæÐXG=Q]f#¦¢±±ùŒ.™]SQÒhôõ>+‹Þ”õå8ÓýÃÛ .е3ÂÕgìÇ$I“oÐä‘¶yÊ’Z¶ÒÁ¦ úÑñç¿Ëå\"›=ü´vUôðŒ£ç"Ær°/³âªfõÄ1¢(à©q‘›™]_Oú4°ŠM¤¼ìƒP÷cÅŠïB뙨’	È‚A_JƒämÕmªü¹ß†HMˆu\Çv‹;åÄÄD}ÛöºÇµ×­Cˆkr2Òî6—óÇVÌw÷€ËNE—<"˜$Žy`•¾ˆÇ¥©ÝV¥ctLä5.²!ŠâuÞš@æ41Ñ	ŸÅmû¹I9ØÅ¸q˜¼)Æ`‘-ù´„‰AxÆ›`u·mÔ1Z.Á›¨‡˜Š%J…¥3•{Wü¬dCËÆYf€Çy é9ß(îà;ÚÛ3lŽyB–*r.ôJû!E,à—ÈȬ¼‰jZ}®•U4¹€EÀl[Š>¦sHѶ¢¢“Ù/³6’[ÿeÖNMê>”ÌÒ3¤¢·ËélTŒëtë4Qa­#e…,…†y¹5%À…½˜àçuŒÍ>2ªÖ]l±çLš@3Þ4mÓ¤JžÆUª´–*×ÙSÆÛÿ™ìUFó=y*špë<‡Âs±¯F½t“_ÓV¡Œ\¾bNá…Æ3^ÜîÙº¸ãɚ7·¹Ú´Ä»áÍ'çõ‘E±¤˜µ@Å„*=EFÄK$Sh©‡)IÄþ¨M\y8¯é³¨'¶ßæÍkn>z!‘Iƒø¦a5=g=x„TÆ»`…°žg½¼^,¥ÜžÌ,ÜW­#°Îˆš[ÏýðÐ	ܰı¶·£4äªÒ̬y©½êpgIGß³¸Ê<4¤’æ”Û©´1¥s~.‚|S ÊàÅ;G˜E·Þö
a%GÔlÛ‘Âй,–&‚nK#;¦J~_˜‡üqDñxæÃ¶¥mËQ©vBꌥØi\⊉zoaÛÜïÛz%W{¹-5Œ”c_[ŠeLTLmæH*:w^Ò’ò®ô2až¿WœQ”™
8
…<‡˜WîMQ³H<éMÆÎî®mkî•Я刃ƒ4SÄ.…Ó]Ãm÷]{óÈóROÚ¸!ZÇ*®J‹SŸåÜXÇ„Û<ÓðêûŸÚŠ<c_K³è4W)ƇìõÆ,íý~C•/ÓpÏ©^ðï×íYü5Š)ó,Ñe?£¢	÷B§sÇ Gßíßi’ÍQ¸3“Û\Ç$D. —³¤U-û‹FJû8Hö$u_[ã}4ì·Åõ.Twð³ÄUwÏuùÈ37üÿ!©Zï¸*eÎÁ c‰*—á:rtƒ¹wr1•‰†Kï6‰oAw®‹8^Nƒž—è
›Ü‚òNhŒœ{XF3o§Õz²¡³¹ŒÉÃìÜåΧo˜Ù€R¡)æÐ¡O©4aM±øÒÔBöµö™@å´ôŸOéVêO¾0ùÏÛò´ŸÒH¾SÖ‰Ò´§WÍøiöEÖ¿~þ3ÿ¯´óÝÑðç¿”
ñendstream
endobj
74 0 obj
2917
endobj
78 0 obj
<>
stream
xœ¥ZYo7~ü#æÍÝI¦Å«y,Ébd‘Ý`7J°€c ²$K‚­#–äµóëSbO¥ 0<êa“źXõUq~Û¨IoþËO®ÿ6çwjs~ðÛ¦—›üçäjóÍLˆ£&ïß½>à…zÌÆ3¥ÍÑÕÁ‹áïãVOÊ»‡‹qk&c´µÃñ¨&gï­nóp2Ãý¨'g’OÃ<%«|Þ[Âd€€AZÖFm^ý“·wSˆAãöó<9›âæèûƒ£Ïò¾Öø‘‚š’ö	É£ʦ< gsp_“.‘•š‡k`ÑE­]Α3YoÚÌz­üì‘(r`´ììðíˆ;%ãõðL˜tôÖG$lH:?6
bÂHLOz¾Ç©!ï$[¯Úª"a¢.Ã!7|Ä….c‹Æ´›¬ó5æ-RÒEcD›ƒÓn˜F3ÍZÛ4h «M˜€‡oÇDÃð€T­3 šKšª@oëÓéòµŽÔYInŠ6€:ͤÀâÙ9ø=ê3¸¶¬ƒlïÊNÚ€
pªMÉ¡¬(¶FkÂCQ°4鵞’Jä0ì£S*âƒerAöœµ”
hO–´h!ÃS~„)ðN«Èƒ?àl5œŒn¸ïøvuÐ1ûá¾Â¦
Vòlt2ã§gt,ÜQk„g_3‡¤fëÊØl˜ NEØ„|z"ö€+îqO‡LÆTYáP–ÙhZ|‡:J	TÓ‚Þfä ZâîŒ&pêgøÌKÜ š6~
ÏŸpZøËˆü¢Š<0‰Š·6LÎax8:…ˆpÍ
4†$Cæ`æE„M¨ó$"NA¯ò²
3ŸÕ5™¹üº²èEƒ‚F_yl;§åå
Q¤´g!t]7G1¶EŽ-Øtöʰ8?Zk´áð5Pÿü?„~†¿ÿªäÁg¬¤´;ôðLÍO`vRëÌÀëØXê¬a+Ó<úà‰V¡áÙ"Dh[ÌP|0°K´.’Õ—v´–ùnv|ä®ðx1ßÂO.óºòŸˆ£>ÅtäõóääÇäà0í÷Mư²yˆÆèZd¹š{ÏV3¹›þêÀi¦ÑÐÛ1ëî&›‚ÊõНµ§U;­K€vfyŽ–aO¬¨Q¸™ŽSfžIKÿljÄ9¾@(>!sŽu
}M´=íßðŸ¶ü.Óâ#næ°£|X&MIA®ž{ÔÎå¤ÔÅФ±èK¾Æ+a[\Œ»ÔÈ…L¾j>~¨Yº,Ϻ`~¥rröH±øÁ=ÎT¤Šè6Yq(@ÊL „K¶Ð9î¬H舠–¢‹uX­‰ô—-ü9§7	ŸÓJ”9¿Ë’£"ñmóܹ>dIÁeóbÇŒ0¥º­8QÓ	ŽüG>˜9L2RÎ7·˜Ñt;Â2YÁd˜œl›ˆÞèþœX_­[s€Lì…&°?TæÈÃlòy"îGŠ‘S„»åÛªþ,¨›ÂK¥,#KE,@hž	±@™²
± šS?0>(DÄÑ»Ã&Ì˸ɤá'
Á­AºÉ‡-‰#€Ot6›×Âί?⊌ÝN‚ˆI^Ð(&CxUEï0H…aŸÀgÃú€¼ïV¡/âiÐÃf8€&©ç/{TV.YJÉÐC¾¾*ž’‰oF;2.É …B:2õÓX¬JFÇ2ùÞè%Õï…ûSÒÐ«Š…„oÁ:<ócŠ·eWÚþ˜û[qo¥zç)x¥!>P˜ÏÛW˜æ)bÆ·©·ˆvà㦔vx—ø`ud)³¡Àô@À/ðû¶~ÜV
e¢ Ã/>4¹¿¬ƒ‡mð¾·Áwuð¼>­­„.¥4RÕ÷e}¤t`àµÄ’—:ë•HùYت—'Þ­]Ì4æ°}š_Y¾OÝÍ}þ4swò •lJåEˆX¹õʇûªªëMÖ#Ô	ßÖͧ
Å<ÿyÝéjÍgßtÜADGKî/Ö½[é´
¶=	ÂÒ#J2É>Æ#Rq9I‘꺔}aoÁ¨p|ÓN¢3(ô]‘ήG‹&ÈmÙ<,–ã v"žÞvÇ¡BEþVbUSãÛNM–	uÛ…|êk W0Bݯ‰Y„D%Ó¯(¿ÝJÈëZöĹZb†Ñviêfµ¢äjíÙ9éõCó¾ëì41ì¶;º&&«¢w½ÎÍ´/³hP%Ú‘Jnƹkï¸ýtBD8k[+¨ö%‘¨h.=nve—uæ^³‹k#•’}•M¹’ÿENFB•n!‚ˆ4ûœ6á@¦¦0§âRõµ|ö®aRÔ&ÒÙR­)J³³ŒÅ~¢¿´Ï§´Ï§SB'ìõ«ðãÓk+LMçùòá=¥êÄ- ©¶Õ¹q°/ç‰9±~ú¤){†„=9T ¦OŒÀ;J>8¬^47/Ä(ö­‹Õ*Ž+^³zÎa‹Üe)âì¶n‹£a¯…úüá±^‹JÓN÷[»Öµ@ÄC~)ÎB{q¼ÒSmƒÊ޽V{¹
ÂІ6÷Td7×*G'¡ï—®¶TKï¼onR#ßS÷ã}Mž—„šê–{à¸P1V›Ö÷NsBùûõ|!¾ÞàuUp
?R<‚Tî¢(qñv]m‚Tüí˜ôToØèrƒÛsµ+}¼‚±ŠÉ¾XoNé0i”«¯T¾âëAtÕ¿ÐœŠŒú¾”h"u}©Âô‡úúË6Ø9k%»¨oulkÞŽ+ÞÉž
ïSe]§¬ÚɫɄíeÇã’9ò…ÙÖÐM²ëAwЫîD€VèIܹì÷'ÝÒŸ+¼·˜`™ø¹•mP1þû"ü™Øeæ%næ,©±š“œ¿Ún‹û¿¾YÉX¿¢²húÔ„S»à$"
EK
o³Nó½eÒIä²¢ð2)G]Œè弿×!]Æ'å'’|•4S
þè"¼ßÍsò©1Ýò•ïν«ŸkÖË}õCá¶Eãû€¢òÓR]ÎT·/Šz$Ñ Bün—¾ù޹l»Šï…?‹î{eÿ†½)Ì“¯ÅƘ¹u%ÚýR9™ÖÅ=uuüÞLBÝ0-ОÀ2t „uð…ôŒ#NÐÌ
(/úvHMK-ŠÅ§%r$Êìi¬•ÞÓŠù-_	ïÞ÷)ÏíàwÕežûÄtÙqñâ—ï³¹÷øu‹¯–UÒC´|}x<Úü«—÷ãL ÀÕ_±”t/ï…Ëï«PÅ}>#ßGÀzùùÃáŠ. éÎZù©ÁõX©°z•/D—¿Ù9“UH;¡¯¦/rÌÅŸrÉkþ¹‚}bY­ê¼žœSaƒAÁV¸=§þqtðø÷ñ
€0endstream
endobj
79 0 obj
3092
endobj
83 0 obj
<>
stream
xœ½\YoÇÎ3‘±ð‹wïj¦»çòC˧9–eޯФ(B¼ÄC
“?Ÿ®³«gz—”b†—»3=}T}õUUOµÞ,êu³¨á?þ{p¶÷èy¿8¾Þ«Ç{oö¼¹à?g‹Çû±Aãâ•õXÍbÿå=Ù,z·è}X×n±¶÷ÏeWµÿÚÿ[l훬õØÆÖû‡±ÅçÕ*,¿©šõ8a\~V¹å³jå–ûpýËj%7žW+ï›u]÷KWµËu¼ãÜoRñvc›V5õñzû{ìöëØƒë×uÓâØUº8´‹ßZ‡OÃãØa—|ÿ«ÊÇoÞsGñIMâ¸?T«.ÞrŽî|ÝǶ_>…ßxñq%ýÀ¡uKäŸWC·Æéþ\9’Sç­œVM߯‡°XùzÝ7ãH"ûkµjã…qô ¿|ðq³‹ã5Ësøù>Nàã>náã
>Žâúpè~¹‚ßøñŠïp§ðó2~ÐÄrulj­›.j9ŠŒ&Òˆã·Ë3鯵qº	•wSáH6ñ69£¹·0¹6=ÛÂŒ»å5ò¨
´¼tJª	Àc—pí¦â‰ŸD]ÃÕs~Øû(ï&,7vùf @ç þ„vÐÛà±»ñ‰fD9ÄâÕE]œâ¸±]Ì/ßö>%µ6ã:ÚÃÓ½ý¿ü“0©
å¿U‹]à”až/[M=`·poUy™~àÆ€æºkQ¦xkƒËvqm£‹Wã¤]& +߃õš(\?ÅÿW¾œØ—ÊT¿ÀÀQ]dåÇÇÎÚØ¢(Pžª?ÃÇqŪ5b>¢@ëhÐ_U2ÛÒa¡„Ü“¤8°ÀÐZUÊ,ârtf¯Ôli…qÁ5ˆe ?#G¨énX`C«<ŽÖƒùâZ¨K»s	~þPfAØ<Ñ€­…
¡1]œâ4dñðÀJ~V,ƒUã×-X ŠB­J“VtÃbûQ4†­@'Çb±\´¶H+ÁÕ“	r±6·ß: l?Šÿ¨näÏËí"€²v㵂:]$qYCc}«O2¸ÜòW3Èn•!ª_w(´ë€´h\	T¼øœ"ò‹„¸¤sUÞÑ'¸‹¤î X½¢˜?BûVIŽIàË¡ÀvÙqì{·ü„y0Î-'#~xNI|lpUÀª2Sp”ÀØ6ŽÑòA°µã@bšÓµ'·ªx€ …VTØåŒ];"w<”±3u
PÒ`!™8×»=°SBŠA®"¿¡×†ú^Ç
DíSzu½GFÜTɽ¥AâífJ˜Ó´ŠÓ-ü	ÏZv}½›Åª—	Q70sˆb,ò¸¯
óÛô€,Md>ô=¹¶ÛΦÂ$tã˜ÂÊ‹%çB`ݨC€âyôèPy/ÐÁ™ßAKÅÖ;`e´˜¨ù2¡&ã´Ðc(EâÄÒÝ8M¥X¾Ë)–“üas¸ö;ÀÔ~føùŸ*ÌÄgLÁÁ³„:"r	¸‚>œŒ8Ó†=…YŒttæ)è;¨û
–c™<¨
ôÓö-zÀ m™Üö	ŠФ±86áOpG¤¢Øé€›3!£·}å\˜&J¸cé伨Èx™ä™àq€bMf%aï1nˆEp-Þ:Ý ÔǬÀE¢ múÄÀÊW2&ìãXŒ
îã"¡Ž
·¹JÍ7ÑëDé]ZHs1³L†ÄÔvp%hž€
/^j¢Ï\¦Nï—MIŠ3'Áî…b'»èÖ€Þjˆ0»LY‚*ÿ†ÌFH3l
t£rx_ÓV¹{ÊS‘,)ãÊÐÄ÷~5xN½"RÉ/˜¥^kÊán‹H?Ó-ü`&§eAä̛ǖ€
œú;˜€ð^ì0ã=×N‘žQÞ—0µ[ºü¤76¿õU1±1Ta#@À3á12(šºJ¯@vŠxçðåVfº.÷µWD¼¿ÎP”	YVCt=:ËÀ)5îs²É:l§”8!ga+ʇ\QÂ
Ãæ‘šOéê.ž@ó÷ƒÒ€(
“¥nk>*Û6C$âkÂÄÀÃŒÐ5ä÷fÒrm”4O¬£ÇÉ“¼Ef`v“~¦Ž2]š:G»nu¨°–´#b¸Ž“R×éoßÓrMAh£ñÛ¬#¶¤43]ü·šÿ,þ.aCþ¿ƒ‰Q‚”2Ùô™“"Snh¹Iºs8¡Uî]%jpãPÈDû9ò•˜%8l²+^ÓP5dPÆÉL«Ç7À
·‚½LͶëÚ×-n@Ìb>7zÔßû¦Ì°<Þ¶ê$½§dׯ›®É(åŽö [J&ëN·Ê„_)CbêØ«(3ËÅËò=”b*›Ü—¯q/ÄôhðXÚ¬¡’ϘûÏl<Îdiñ¹Ë²;ŒºeÉòöI³æ%_	”ESÇÎã_L1²}"שHP¬¯+Ø“„­;ñ]aö›¾ô©Þd¼5žCDÊÖ¦	{ÔjNüe[DK;ǶÐ1ÞòcÊ=(ȵKƒ
#

ØÙŠ
´’Év9ÜšÍS­ŒsORâ8 õnÒn“qjrYÖLâ¯>(.Ùñ¬8àç&ùÕAÚcj¦}ãi„j§?ôìÜaªG‚Sj&¨*àíö¿#•ÆðwÌT;3©©–1AXAÌ÷S%]¿J6yoÓ½W®Ž+Þ²m©dVf(‰¾¬8F=Ù¤…N0xƒ/`Jœd‰T§q?êV·¯5>œt›ü¾úA°\°mê“*½C`f%yÉžDF5Éä.%RK€€¡«Ý»»B˜cŒi©‰töºÂ¿œ\y‹!ío²uô°®lŠ‘RôÁ=ÛlÉŠò,œÄÇ	åRªUÉP$¹wäšâf÷¹¤ü&íGZ(úz˜™àvÀn™Œi…†ßõ |Ï%®1/8&[A0ErT	œœ%Õë>Å›J¨ÑÄ|à™gïP’Œo+~§óŠl_~!ƒ|¹¿÷ýÞ›…÷¸×^/"
‹à#Ćø·‰–àµóã'{ž|»¸¹º=Ú{ôÓ¢Ù{ô
|<~öyüóä‹ÅŸö¾|²øþ=_I‡@Ž?޳v½—þà7´å•ŒÑ•vÀJÆ~¶’gÕݘWÞky³Í.5eBh6!ó@œ½¿åM}Iåuÿ	sÖ€I·
Ó$Ò~D1†Ð:öi}D~D	›¿­ZÀ—Ýü+nبÅJ;г}Ã0ÛYŸïƒº–#]³*ðƒ»íÚóûù
gò>½dRöé–wþ°³Bz³Þ€¡Þ¡ÆÌ°K
ÂõÃGëj´O˜½ïÇ;¯awgD%âïKŠÑ¸X@v'VmCÛ1'zñ%w‰ž'åËJ)·üºtÿÖFG¦ˆ@.ÂlŒàÎJ^esÂõHzJ9ÉS›*Za)IQÄ¥Þ¿²{*rñ¸4æ&]ÔÙá«{±z{ï¬5#y]fæäA¬8ñº'}©Ä[mþÉ%+	1›]¢Àƒ’.’ïÒ˜%|lðëo rÄFFnõþu	PfÇÝ€ÁL
¦«FÛW.0Ùæ¼"Cí©/8ÊÀksIF}ï¤Ç©ZE¾PoÔ>¨µ)^J;¨Bç\>ÄÓO»l–URøMÒHFá×;1_Ùɶ–²ëRË´„ƒ‚N¶`¸8Ñ»ìuSZ²Ý»¥‹gbW­‰Š9ÕÙ èÕ›Lé`þGªŸQ— õ
·í^WR`µÉ±aø÷K<)­÷:
Y4χ˸È#W¥1Ó˜§¥Ù½(=^ìóî('1Ýf°’ÙœÌô
Ê4¼Î-ØÅÍì
žŸÐû3UµÐ»5J4óÓDç6?±Z¦¨å–Œh“-aNr7¶¹emJÏdÞêüº3Qf÷óÒ$Þ%=¼-ÝOÊ+ùE®Q†Á6»#¥·íÚfÊæñmäîñyxü~ä~ @0h}Áp”؋ԖlB©ÓXj•@Tþ®¤ê"$qßf-EW%Å>AäõD'¦”yn[›1ïûÈËV¨ð×ìÝ¥Eë„죉*„äor®>Š1Ý­š¶„|_ŸHKOÅ“¿,-7$©]”¤vœÜnËõ‡¹Ñd‘‰·éÜ0[)^#U0fÜS
¬×M<2ï”üˆa«M†QÌi†'#9q[ØCH{ÒÖ›Üc'W~`JØìµLÚËÎö4*¿--í ¤­¢ŽË¦,·©ôêƒX˜8°¿OâI”¹²”Ãü&‰èæR¥pžKá4ƒŽñçi²)‡º¿x<¥Àoaô%¬î­Éìptý|‡`¶9-“™ïH»gs’´[,ð[B‰+&QÂi¥ZvŠo¦Ú˜q2ÅI‚ʸ©q“fùs‰\nI‡¯Jö•yìy¼‘–ƻϙ¤–&Òy¿ýf—37>8ã¸Ø€¨otÃÓD‹×¹…AÙè
ûdÞØÅA•jøT?î’‡äˆîhÞZ”Ä;OµË/ÒÜÕ‹OÓÅ'zñqºø\/~¦ßž§Û	*¿¦‹Ïì3rq_/~adX¿¶À±«æª—ã’>“’'Ì–„–Ë]v^—ûê¥%¸žgTJݨˆ-aǸת´„N£dE7	Ü÷DlWs	e—i5—%±]íiiÌD¼Ÿˆ§¦ÝÀYŸ÷tX2ÒIoêAØ]cв’´w©Õ¼öÿ„5ÇU<ëéa=‡Cðn®$çòµý`Žy‡²:[|I‡,›v~б¥`R«å©ä^N.&¥‡(ëT•e°‘ÕüJ9CGï¼äeÛâì³CŠxœ
±Ç«{ðÀ¬G íÈgêähÀÉQC0`.2ã29桼¹s”¬¾ÃÔæ`ñZ¯…dyM#ì¾â?…Å ižE{®Ð´{eøæ÷CFS±œZ=×1u
¥Šô/°è;ÃÏ•–;„­å‹9ª‹›nþ^åMî@©óP¨s CòpÂþ¹Öõí*khúî™÷Pg“æ’ߘSüPÌ€VJÆ•ÒþÙ™L‚ñ¤†O5#RŒ§
mª5:ƒæ&·¬Œ!&çŠù¤S¹¢—j¶X”¹µz`~™-xZ^
ŽÓsM†Wóâ,×ò<©6¡_ûü”Aþ Ô-î(“YÊ1‚дЧ9F ^ž¥öMÅÿÌãªE¯óÄǸÝsÇž/àK§“?á¶[þ5ÿΡ?Â’I•æSûQÀÆ
˯?$ÚœZRÅ¥­tÒdÌ•Žªs‘§Tu“ê
m¸ÎÒCåHzBf(+ØzH˜
¤Fœ9®<¯Âá*Ýü0Aj’Ÿ|çõæô<ÿ–Z=+ËÞ}XOÔ}T™rÑÙy#~fR¹ý™,‚J
ó錷kMödâ	Ý3çÓçÇõ›¿ßûšßâendstream
endobj
84 0 obj
4513
endobj
88 0 obj
<>
stream
xœµ[YoGžg+?â*š·G¹M×ÒKåa$ $a€“L”̃ÁfIÀÄÎ2¿~ÎZuª»¯±‘"d|ow-§Îò­üvÓµnÓá?ùýìÍÁÍÇãæÅ¯ÝæÅÁÛG/7òëÙ›ÍíCivòõ~ý
Æ~Ñì‚ëÛ”"¿øžÁØ<óÛû8Žßnâöq³sÛ[
¾šb‚¯Ó;Œnû½>ûïá¿Zç-µqðíôcÓã˜?Ü…®]Jü·øö޾í\¿=FjOàÙsØ—‡³ÁÑ.àyÛu®›¶¯Úó&l?ÁY|Ú#$¶¿"ݸÀ9¿ÆEÏ`çøØÖÛÏ›äðÃ@/Þ5»žÖ£¸×)Ò°kîç¶Ï`-|ŠÛâ~~ÊÔx~rKíô;²3/ôKŸÂ¤öLŒ^žÉéÞñ¬yª|øé´
ÇÍ §F®ú)´Á+«‘˜¢Ò:ÃÙ#‘†4óF¯ä$È! ªs±ûX89ÅLŸØ€ÔŦÂ:Èîqô$1r’‡Ó¶º‚Šæ¼Q‰¾4sä8~{x'ó?'V„ :J`æi3Ϥ7óR0áÅÎ…¶ÐB”%H	1 ˆ>üÉÊRAÓ&^T%F/$"VEAGbК°³œ‡ rŽáÊrÆMQ?­¬£ðŽÆáç8n¤ýó\üɆsL{¢‰nÜÚ­Ú†•ƒíD>¿—3’>¥Ø†>©B¡T@*9•Gd\¹WTí!î˹©â8ãzç-óaBG\±«b¾Æ3N¤„Eõð¨-‰Ö‰­8³)åË´Ÿ›@\©'¿e¥‘“Öôiâs£äÁzbçÄÖßž´e"ÀJãUÁ$ºPiˆ2$Vçá÷31F†šÑM¤¤q/Õ†Ÿ5Ä—ð‘ZÃ<Žô¸’ Šì°°~EšaBô,œþVR½Š^ë웬`qRýš« ‰ª$j„¨
zè;|]äm†å©'¢Çäò–ÔZÄùâo
£‹ÿDúðø.‘ åø}\9>œÝ¢o§¨Zv£^Øðbd½ºA¹‹½	Ÿ²¡¡îÁÎ:Z?¢!*jõQ/y±âHQY²ß5zœÏŽ·û_5—_VÜôWQAæL
wóaàÙËú@Šw©3"º„éÐ0à%)qâÀ…	Šž)¡‚!Ü?8üç¼&(XIT—L\€wÔÄinöä'Ù)§‚ÑD\f)D£¸8)î‡~RåôE™¥Ì̓C¤oÈ1XWÊÆtOâ2r¾Pîlbƒ} Xcà‘=°€†1 âœJ™À/tm/uß!öê{øøÂ+¹´GmœL—°Œa*^Ñ/žn@¥E'Ÿ}4ßІž¨9@›!ˆa.G¬1Uâ8æ¢Ú¢ÄMjܾ#EÑ\j€ßà¬Ð¬9®2Ùž¾‹YMdy'bjUܼè9ü½ñ’d–üÌ[£žg­@š~#lBx—(’$\gBºKbÄ}«faäW¿!X¾b÷¢¤Òî%: Ýx$šÓµ>:U*Ep˜4Ú0ÂÆ˜TœPÀΞ~RK$þ'£?g|†e`•ÐyB”f¹˜Y	ÀË,ueÄxÉ
jäh¹ÆFÕ’¡'Yg8¹šÛüíàî½Í×{K¢5ëµ$Švq›¾¹*ŠaÕïÔ,*•k%lÓÔ
‹‚.ÚGzÐÙ™‹êÕŸ9Gô—d¨œÁ-ìqg}ã(7XØ>+>´«Õ¼«j˜	[§ÊUXß÷9Í>n=ÅÒÛwVˆØq"€üÒ$±ÀÈ™DPi=ÕÚÑ#Ü…2„°ý	]ቀÝ9*Þ—\$.{¾–¸"³¢Ì‰k$¶ÈlPéB1𜉆û…®‘ëÁV­´þÚ-Ë&årFçæÌC4»7›žUµã"Aƒ‚\!	¶,!>(v)`©ËJ…FfY¼NH¢¯¤U|,õn½²¼âñN8Qû´’I«ò싃öãˆó]8SêPuÿ*q䦶™Ú~b !U!‘Küoðd%û'SãZÉú üôà|7ÿês{Œbês¿’b±þ,ŽÊ·ª)}W““v/u¹yÅÃ÷kÖ6™ÌtåÚRDÑ%Šœ	òp\½ŒñÌé^{Š0ŒxîUínÊÍ S+ª–ײ¢}ÈI×`“®:jŒChý"j4¹Â Á“O\'\øÀ
—BÞ‹IX-Â@1iQ¥V0>Õ”îSo……û­DRÒÀÊèj0é'Fmôé’R·¹3G!ñ1/2,ˆNŠE>³“é^ÜÁ¹à8Ê÷5Â$
ÄqÒ{©E¿+|.{¬ê–O¬[¹4ÃêâØIˆÕ&¼8çø0Ì¿˜#öÎ\ߘp´!@ެ¨-mnßbT™#…Ü§šº¢„Â¸^Lü=/Â)š]d…ªüçH•“ëõ¢FjSÏQgêÖŠs¶ŒE[ÇBËù–ÕɈö´¢§1qñ³ôÊ¥pr‹Mžûáªz¶Txǘ¹À<ç'ÊS[ß÷OáÓ
OY+§ÜìmcU&Á¦˜r_œ¸é¦Ò3Ô)ï
	œ¹
µÖc¥¶ðèIi]棪¡I‹‡`$\”eÖ?Ó±),®Á-emÖ^t§çÑ¢ŒËµ<"äœÓnÄî™ñïƒ-ºÌÚõ~.ŒCSër?ÿ˜ñ›-|d,##©ë£‚Ù¨ð6ÑYI“w²þ.çËÇ×Í–CÉ–¿C2BL]upJùò@©gÎX…DÓë©p	‚	#×Ñ §	í"žid+Ïï®=õWÈ»oIatCÁ+›ë•N‘Æ-èþ#)Ôö3øj,ö¾4äAT‹²„¯BñžÕAä¥XsýÆyoª»—öûM}H!¢ÀHpöÄígù¨§ÅÀ¤ç¤a	]‘U‹ã\ƒPc‘ÔÌ6=熙°ˆž“Ø"–ag½mÐ,²#$ ¿Ä½"œƒðÕ”P§%zšÕ[8‘꣮f¸Ä÷Öå8<íõ:b>u¦¦œyªý€©è‚ÇÏr¥ÁôÛÜQ 0 èÌÚžF[pçËSeŸ¦eÖaÂqê£N}n]ÍnÕµh¢ÏkQqy‡ˆâ# ¾„^Ù×£Í9':ÇjÕ›ÞFÚ.s͆Ž&†¡«Î)‘”&óPPUÆÞI’Õ£iÁÎt².H[a_GV3>õASâ)Êì0xHa¡býUÿR$Ò^Ñ$Â1T§É×nTj¨••gatïná0Æy¥‚h^b4£ÂÑ‘ù˜Ä/ï Î4ªÉÍ©Œ»*†°O-pŒ†¤]Žƒ«|ç«Z½‹XsÃ7ŠŠ¬]ôtË¢Kˆý¼ê§åI•Ý8Ó¹÷ôJQ§vu“JN¹¼¯tÅ*¹ñš×óû±øýR`iÓ±>¦'®Æ8h,0ù„áD×#Æ¡è.Àgsw¨l@^¾ï tÁnD'ã‡Æc_êÿß5±dĘˆy_‚¼Æèªû#;Vîr7ÜK$‡–
,ÇFúPuW–ÄK4Xèÿ†¸i5I4ª‹†í9¡3ƒ^ªïÏIÌ+©U;”Õëk’:¨ÏïHi\·?/Éù79ù8ÕCÿo;ò—V[ÞÉí­¾—¥×Õ*ÈØå†dÕê,Ž~CP]Yý¤Y¶âN˜1Uó¸N°=_.µÙ]‹føÓt§`øÝ’ø´Ô¨±†XœÍê-ø!7¼úv~µBLIwP>†Š÷¾Ü!´,Þs;ïm‡ŒR’Ð\¢í¶¶ìèQ+Šð+Ú"B
ÓjŸŽ
¹6Ñåî|®ú¢ÐZ‰^/·p¤²¸xø‹äGªæbµ½Ùæ[4ÒØZöÖó¾xPòCµŒ¬î0pk~_$-¦ 1|ô.ç=û£éÍ­6¸Ï!÷^¶ö¢˜Ôþ$Ê>
stream
xœµ[ioÇÍç~Ä~°¡À;œéžÓHŽ3-[¢q`S$E2æ%‘é_Ÿ®««z¦—GdÃðr·§Ï:^U½½_Ve½¬à?þ»wºØzÝ/¯Õòpñ~QãÃ%ÿÙ;]>ß	jZʱëåλ¬—½[ö¾)+·Ü9]ük5í¿wþzû:é=¶¡÷Î~èñE±nV_u9ŽC3®žnõm±v«hÿ²X˃×ÅÚûº¬ª~åŠvU†'Îá!Í×¶û³b¬hŽm˜í›0íßÂ®/«ºÅaªºéÂÒ.|kކƱÃ)ùù‹Â‡oÞóDa¤‡.aÝ7źœ£'¯`úзö«—ðŸ2lzwpD^ñu1t%n÷Ÿ…#9uÞÊi]÷¡ï°\ûªìëq$‘}R¬[W­ö‚ðÑ¢X†Õ5ü>€+ø€Ÿ°v½º€Ÿ—ðq‡ðQò`ËÖ¾l;PÙËÅΟâü'Ðå>Îàãgl}üJŸYŽ}8fO;~'ÓÒ0ØÎ†'£Æcm<[ñÛ‰>Ö‰Þj£,96«ÝÜ ‹Øx¤Úóm<±[š/tws·ÚøylüonÌ/±q/7ÑunG[¶ìú1Ù&¨ÖèõrÃúlkðÿ(U’…¦~¿va`™ëÆ•u4Qô¼ ÜænÚýöº€¥XÉÁJMOætýÂRmXª
+µôc7|9
½ºwŠ£ŽÈçê0
úÞÀÈ“àÛû°JŸÌ´v4wÔi/¬[ivaÞ°«º	.RÜVø0ñ†¦~"KÁ,݈‡Ia—ÐLÜIO*à˜,O>¸,Ûã–áçÒ–o‡s t_õ¥wµ@æ“ìxkY%û¡B»ƒsŸ‰	Á³µÁ}²pÔ:ÍÑ®>ÀœÇVõáô¾ŽRå°6|߆‡ŽpÀ«°m›¦€ÛíXã\‰ùŽØ—ywY¸õót¢k´*7à±bU¤ßµÊèTÑebº(VžžMõ  Çzˆo«VQ‡ÔŽÀÔDZï¯èÁÒ<žÄ$ò…#}¨Q°lX+¨p2(˜°j€¥ìˆ}
Å+M†jƒeòH´3ÚY;êyÑ>@
a†	ªyÙØÇÌ$a¬ø  0ûUPRSét8+hõ½˜ ô…P1öè`°ì/ø0TšøÖE#ú¡ ‰À6Ä.,†Â™ªj„çAt}OÊž-ž!¢6PƱ¡îR@:'³Ö4bu©C±IÍ03ºä!Í	³âÏÑêawCëªa[2r
x€Úlxœë#b´Mg°Xbê¬~<²±\lQm`,:ö›ˆl~²ÐOEwp¼?ë½®ÅÀÁzÚ´aÔ„”OY¥Sã¢aøè<µ½S›Qé„,$°{H"kŸ±Eß“A!‚žé&`c‘¡#ÆR)O2w-ò>ó&[q‚‰Z5¬B˜¬[“Œ6j_Î%;ÞUc'wÓ@ïÖœ¥>C3
·ÒO­8±Äб¶éš	®m‚±y¨|b±
2P_;4öÙ9+j"ü‚JÀÒN!'ÜE
­Ã3;‚³:ššD„±¥Ä„ÏÁ³Ù,#†¬Kèâ0®½‹ã¢&–
qªO
Ýì½Ñ(>	hP.4#"­iå´Ñ3Ê©Ø9,7¾BÀ˜AX0Ç`2d]]Ùwb`q#(Dý­þIØjsÙGwPšÕu÷É›rL(xb8›XƒÉìRÃ5û;¤z~ÍK£ã¯,ÚˆWxÎÏ ¬&éòA|Óâ¹¾ÉL”aY?5,.¦S`årGŒ„*¦@房ÝéTaf/ûÉéH¾âÜÞ3ljdË¢AŒ±gi
Gh9(ãèYfÌ¡fH€³ßH2ÒÐN¶ÂÊø}[1;„´k“JgNâ(>!žÜøQ‚¾q˜nQò1t
å"I°¡Ä'D‘I$’$Wo]ÈÉO¤ž)ƒ"8,IXD¶¾3PŸÍõnC¤„±nBbk@v­cºªüLJ ž[Ñb†S&¥’ùB5Ug«#©ràÐi¡³ŸT€o
sãzC»¢Œ@®Çš}†š<™-’'”Úáá×Þª±ÙŠjPºihÂÎT£°¡Ž“ŒUl€É³"C±"2ü’ÔÞBŠlR˜Ðß§%3‹!–ãñ0%1x·L	Öeø_ÌÓ6ŒHèøD“ìçPëùF't–&[Ñš\O¥ÓfU«eX—ãÔ÷5‹ÑDHÍä„5©·÷Íæ+Ó¦ÅH„ùA’TjsÆ?‰äʔꑙ¹kËü¨ä«êŒœa—MÁžÁ~4UŘc&w#/yXGawC‡“|_º‹§¤[tßqs"ßy¬Ç&ÖôxÐèqïÁbod¦¢Ü:˜A1Y¯
È#¦)¼5ñA 1‚k[È*ø!aLö,%5$€®“’P!ÅoÕ(Ö¦|sK·!7w–ì|¹çN«êH@
*Ñгld5ªqHÌ÷±L•ðã1"jIaF>Š¡lŒp®§è’@ãÕ^aJÌ”žƒÉŒ› ܮ㦵%Ü{ÆÝÝÌŒ6ÂêU4®¦©ó4IPgƒÎ¢]2)B²õb5mL5ð•†W%ÝÎ)³Â›œy[LˆdQÙPjæÏ].€ñìѺàà)dÝÞ¦T!NEô¥±ÏؘáƒTE©
º¡ôÅÞm°˜½£´F<œ³µ†U7¹2aE[Å(ýÌn³&+WóȽ6ùЛMË‚âö“Weä6³n'îe³?>g
~ó’Âfìrg¯×·ò…MP¥4ëZ$E©)!ý/ì;º`½å«—	Ì…´ç§¹Ï&õŸ¼3ð+…Ó¹³ønñ~é}ÙᛤAÜÃÒ
A˜þmà5ȽÓÅóíÅÖö×ËëË›ƒÅÖ?–õbë+øxþíáÏö_—X|¹½üî‘/­Bî[wKȬdž^\=“4eòÌS²9@b½¬/åm.ìZÓG‰ àBGÿ½EwÙC?Îd@æ?Û¶‡¼Ì4à½ØÆˆ@ïïã'³hß›dIˆ#•èwì…æb²•¼.LŽ•â|.¡¸GK›.Iò,ç;+“¸–3EZ(}¡ÕOcO¼3Q®ßÖ¼,Œü®àGüDhcŒ2¯–š·jOí¦q~×r”¤nw±Ý‡Úx/r	OŠÆV¹í™T¿ŽÏŸËõQcf=H¶'ƒ®rÏ÷rÛ?Ó¯Êgã;SÌ€ÒÛ>$¥Õ”`Ln¿dåQcÂÈ›k»Ú¡
[ßuÈäȧ{²®·¯füsãè+ug~ÂögæFÆa¬Y…K–bHœ~Î
¿læn†³çSó_ËZç­žáãmJ4yhÒõB1$\Ö¹÷¢"ÖÞf•7étleæùä(M¹¯þÿΈ—“ýüF¤a/{Ow‘Sþ^Î׳ÿÆA×±Pu1¿ÑÓÙM©wcç	eíc/±²	®‚Zÿ“̪0·UñPÅÜ~OG]''ݼB|}2d\!Yš`ô‡ÔtŽ&·Èy¯|8ÍíâUl|jÅ-Wý*î_r yœð. ØÏ8­¡ö³a—Ðê1ð~fÍlž>A[sºÍQgš›dBîÒû¦l&x®N
„og2°KWïWö¥¸R“÷ÑU镞9z*¤šÄ'û‚î˫ԯH6¥8sWÍbûijz$‚l¤=Oss’§? \Û͹¨X0'T¤Ñ¤Îݘ8‰c&»Ê‚ãå‘Î39ž^ÉJ§Ç—ƒ$~ËX ñM‹‰½»ÊË?ÎXÛ·BT?FþLߨ¹»÷Û{{˶~´qGœaMbȘŠ=½fœ‡'ι‡ŠüŠü¾üéã‘Z3ûÒÖÃMë\ÁëRý-A	w]|iðæ¾hw–lÅøRß-þaĺÐendstream
endobj
94 0 obj
3957
endobj
98 0 obj
<>
stream
xœÍ\Y7’žç¶Da^\e¸JÉ+“9زdkíéY/0^`[j]ÐÑmImþýÆI™YÝj-,·ª2“L2ü"â‹`ý²n3àòï£W'w~œ6Oßž›§'¿œ8º¹‘½Ú|u
Wó0»Íé“né6“ßL!¿9}uò¯­ß¥íaç·þÝOy>ÌyÜþu·÷Ûøç;¸ù—Ý>ÖoßìöÁ‡yÛïñÚ»àÃ0Û¿ãsßì<ÜËÐÉ»½Û~	-þ¶ð€sÛ@Ó8Ò~ÚQ—Ÿóö›~‹=g|t{¿ß/]ÑËéèb´
ñØ"Žÿ}úg˜µóvÖqô‡æ}zsw‰ŸÉ0ìù™}“›g~ÔïÜ!MÑEÎ!9fÑÞ9?ÆHâ9$ŸsÜ>§ûà0`¨/A=`ŒøuD±¹ò
uÈ()x
iÛèè%>wYokûGÐ%Þ·ôý>›^@8~ÎÔ~¤ÛOp¤–ÐÌHôoÎÉSg ðƒ…¦ð KpwOŽ
¸å3ž…ý>R‹ìHËo£Æ~ÌôÒC|„†ÀcAáúͪÐïwyäÑ~ƒŒôÊ·µS”ó¯ewâ·ÒÝKlè}¦Á{\Jøè<‹Œ”†‡­y›ÎÁôPJS3T¸ë=¾†1'g$ˆOÔæØož°×íUi&cAùêE§§ÿad~ÂëA—ÕÛNë§sx#ô4Måµí]8¤Aå†Jr«?³^=Ä(#\9Ø<õK¼JBCÝÂ9|ªº{.mA,¢gÚö¬:Dm{Ø%6EYŠ€ÍÇ3Q^~ìùan{ÁAZ.Ð wq ÷·ÿÜé‚ÒÓØìßô^XïЭ·³ß‹ãÌ€Ì# iqH¸[–Z¯3~Eºü¤ŠŠSm^ƒÁ-5êÓÕÓY¢–•¤ËØÿª@(»pÏÄ€3‰š«³fÏW”fM¹þ¾b|!ªàu8åqR1œ'éWš3O—p‚„ÂZ®ÝÚu“X¤j HEåµý—îª"¶/7ϱO¯ÄëºårªkvpŸ.EÖT|A}1æ³ïUô…0Ÿ‘Ö¦Q¡5ÕºÔ¹ã׌Q?=…>?\ÀîMnˆ`½êYÕË5ˆ°¨h%œÑ”gFdQÈøHcv<†ªÎíj
%©^"ÓyuYZêD¬ž5@YTpäÒâ>w.-H6"’DÏ^Ù©JM´
G7©”}&Kh­îK\ÿD=| Šç>Ê*yÒÓs:7ú›;ü­Â®NõÚ¶Úk·/YÍÃ0²ü¼ÝUAGKzã
oOºê6Iã*È$>Ìl¾'wo“øó®
æ¬Ñ°s•B†)èk_Vª5­hôs¤!,»¡±…®q–öä•'4…Hʸùi'†5@eµØˆ]¬n5«ŒDe©íÁ‘ÉAŸn¾Ákl†îC‡¤·ßósVJÔ§d¿Ý5ÁFiâQ~bÝÕÐøTtè‘xž™°<²Æ¸“`»”]TÔ;IÂ/ž½[¨–xh!òVò4~G‘iSçJ\³¶ÁCs£ì(\„«ºî¼é8œóìYµyͪ+XvÿIŸ*Ó?äFŽKÕ³þšÌ¬Å­Ÿv±ú>¤.Åðο­+©Ë¨Ñ€Ur¸$øṲ̂m
€Ä‚jˆ×fõõ_ù¢@‘
Ëí(¤H‹$6š¦ ËP–&°ÝÆ®
¤óɱ„¥4üwÇtßÏÇ 5BTªjseB)ï­Ù/Òj4³l%×/õšy¼hl«ßDrª¯¬Ë¤íŸ0xB˜Ú.™øa¦CˆËehN{7D[¾Û©bzmÊ­k.–&ŒÁÇo“Ǿt$‘6Râx4U³v®†°
X«\ª±ÂaàìÏ*RPýÙÙÍ¡,o5n3ÊcB\êxp%¤MéVQ'€„´ð‘Ö¿¨#j'èŽlÂ7ÆFŠ"êhâµØ[C•G+øb—6@—ÚÅÒ£ë<|lI´>™1ÊUýžï4²ÐG¦jApŒJ<ïÞËg®€U†'K_}w”aô­ÛnÃ8Qb=¾¨M›Rp¤8Í4›FÑñ×]*……³ê@¨MöшïèðӾ݇•ÐQ&*ιዲº–p¶´ï¸ïU"dÝŠŸº‹jQá´¤BŸéæÏº§´ÁZÀøZà0ç¨uÍ_·a@m+Ö’2q”é\là#+#ùO¸ÓhVÃ!x7†Âþ-¹G!m˜ý›‚‹Êþe©p{“Åö/ÏJþaùÆ|Èi”—9v0ˆ`xÐï8zÅU¥_®°’•©ÜãºD˜ËÔ’–Úºò áö4:ð~#z^Ÿ«wÏe@iÞÞC/ÐMH€mt0^@Ù[ë¼ys±)G•"vn˜W~Ïà³é“î™nÁõ úkô(£²ýÂÊÆó´åFVbÝX¯ÑÍœICÛØ'Ž3mHë¹áŽ#£”ìêœ"À"™7Çuv3")¹ÆõÄ<0u½†3þn¥™p†`¬íªseª%9·;:Ž|GÞÕ^XÏÞq¶œ®z^‚%/i´tN|Ò¹­F÷‘Ø´ÉNM|¤¹GiÄytT¾Ç9#ôÏÍÃ*„èÈÕó‘¡¹ÄNŠ.ã(<ͱu_íüÌFêJÝS¥È!æ-º ¦¨˜©â܈þ¤Á‘“q©vÅÉň¢ý‹³¯+m
–¬jc¶x¥Œ…€ø)g¶‚}²€Þ¨¶å¸QÁ3k˜À¾n3Ñ Rc#…jAö+Q¾	¶à]†bªÒ)^
`„C®Š¡«þk	å…¦S§¦5]ÆÓí{™£µ\`{E“ñ&å½[•÷~ÑN…™€Öo&l—–Š8rGB2šëü\Có UŸÙÃýœš5ÐTBµû\8YGà@MÝvì&¯Záñjo%4|Ê,vy4#S–úë]ÄéÝ;=ùáä—M”'6 ®¼ñ㦼‰`>>cÂõ«'wümóîÍÕã“;?mÜÉoñÏWßß…|½ùÃɽ›Ž&c[Ð×d¬‡H`„·$0‘œýÑd`îáäîUUÿ®%0ì£_îêC´´ž6€[K4öN·-ƒ§ÇK@S;hö
'”0ô–,DŒ¼cO«ª=«òÏÓd0MŒXÂ2þ†GqZ³Ùa­Å”iQ‚Íeükï«RŒGöŠåòÝ¡1*„A¡ɇj-»ÐOÂÆc
¬AtíÒ‡–ºÿ“ú‰ch´¼$Ê[‡²-ÿû:àŸ;øç}OŒ›P!ÏñއG€ØÆLäìñû^.r;מ©V
søî¾jÕ›òàãzñq¹øÚzÑzñí\o×7¾+qöŬq2fš‚¦›ö‡÷BGF¬¹[û*´b#¿Ä r`é\•0Cj»dhﺉpaÁ%úT<œ;®â‹›à{Λ‘ŽýýðÅM€/^k`t?[Ž	Ãß}l8(ߌ­€ŽZ#“"~б÷˜Èq¡Ðc¢Í^sƒ¿îåIwt'JбRvÓ°JØOh!W`òL-RZùehÞp¼„¾ICóEön>Ö\ÇHi£ÉR8=Ân
¨`tê×\¶Ýò"ç¾ær±ÆnÅûb€¹¾I®`Ü^8ŒÛÑ4—²(ëöBlÞjá3í—×
&âQϴ΃·tšfÆ´’Q2³™ûà«		%Ê«Q|ÓxdÁß/Ɉ©„ä])`¥wr²Ù•Ø…Œ)P€d²MWméH]Ú6™^‘ÿ¨{øaÚÉ‹W´\ÕI-<+i‹iìÐq±,”n@Ñ|ÖY½þD¸TüHç”^­0Ëe¾‹º›”–Ñ^#yª.Jm^Ë-Ò¢Á}ŒFfª#Í–þVÓå9
xi^r[eîÝc]z㙀–óhkýJþíôeCi/˜žÖ4¢ æ¹‹;VÓ¥J E·ÚíjqvòdT÷ó€!p|c¦ABwCΨ~	[IS¢jf*-×2AXo&dz_%¢6%OM&¦²eãÀX&ˇR~Ô†êAê’–ëP=ÀÆô¨nDŠbóm*ÜœuQ:0
ÐJÊuiËÕÞ¹ÃT"*E›¨‡B¡I‘Uε…¤rhø.ô™,Yë5Ñ-W‹nEš¾ÁŸÅ«‰>] ¢´;¦[2éÁ®¡/íöä±,!Dé6Mî+Mˆh`ýùZˆìOŠF˜$øh*æmÏçõJm*%Œ’N
I*çÇrD«;Ë@e¯c(>ß8–¯q¼]$Z˜
ê'Ù#b~>Ćút#ß¹  )3ßû¸`æÞQ.ôƒç£Üìf‹mÿF9t+d£5?2¬.3vÜÓÐed['NqÄ•XÜæHßG)PJG š¢bQ4žöò@L!ÈéTD—3Jñúœ‘8PFĵq•s[TçRJ!®
ì!ÓÞÈ4n K+“+<¤6ãíÞ•¿gÜ;VlS·¸·0HÞrª`°€}©ù9….c+-¥!Ô£-'§*Ö‰¸싺Á¾ºeBGí’9„Õéž±{ÀªFÕ
KRÀunà¯7×6T?Úw•_©'m†F½( ¨NQ¾…tœ/FÙ¿rF—~>äø©^3ÂĦÄoæ?,è\øzBÎÕ²JÝmÎ
¯ê•Ÿ¹6Ö๡[äÚÊ©ˆŒ(ž”s}X4aö™Ç-vs†5[× çâ×fШ®És;³¬Ëãžk$ñúy
£n
~Ëꕃ€¥~¤8lèæz¸­s²BÃgÞ™úPÉ7áàZ”aÉ[Ù¼˜{‘_ÐÉâ›”
AP«¥ö©R|Èʦ±|-„¬©13d3Ê”hæ‡5^Y»}Øñ©l¤·IµêïO¬eÁJ©‰Ió•’8¬¶"Q)ë£YUóË’µ|¿ƒ?Üm9 °vž‰‘6`½m«ÿõ%TS?÷eÚ&b	
١3>
stream
xœ½[io7Ýσýƒ,t;šv“;àäƒíȱ'vlÉÂkdeit$’F–4–ì`ÿûÖÁâÑMÍHNvxÔãX,>¾:zònZjZâöïîÉäþËvzp1)§“wESûg÷dúh(
-E_öjº½?á™jÚêi[™¢ÔÓí“ÉëLåuVæõ›íï`F¥¢}
3¶÷`Ôã|f²§¹*ú¾3}ö0×Ù‹|¦³mlßÌgÒñ2ŸU•*ʲÍ4. Gë:Yt«pøÃ¼/YÆJûÄ~t[”ª¦¥LKkxª5ÍÆú¾!‘¶ÿI^ÁSUYA0³Â!°î«|Ö@—ÖÜóÅÃXUeÏð;5>ÊE*ˆ£Ü¢]ñeÞ5©ûÏ\³bËÎÐP³ª,ZÕ÷l¯3X5;Ïgu¶3À?ú²' JÙÜžü8y7­ª¢¡“½tS¥tS4Ý´-«ÿÂA?ÚšÜßú~zy¾œOîÿGwІ0#ÁWÔ“A÷;ŠºnªdwÁ‘…¦ûÒŽC24NWÅûiÜ*M#º7d(pÛP(ë<ª‰øZÚ¸º'‚ûkFÄèÄCç2²ódÐʺoŠZN,‚fÍ1Úz®=	¨íYaÈ"HZºs1eù—Ϩº7<Ì3J¶lÚ7.J÷`´]»/qeYß[; f­€H3F¨Q01Š#t1UI޳¶2ª¿E$o*MVæ¨"ˆÜ%\CIFùá]ÓLYN#„lﺥºÉ6ðú–N>'Ý0}9T¡>Îî¹¶2ä™Í͂düŽ5»Jf4ˆt§ÃODüDlâ¡ü"å‹çÑRÌŸ û%:L tÇs¾@9HXÜwÎ+«Uª®rMlg|àºg7oa	U&PUB_£tËî)¥mŽÂzåmx‘]Äa³:ñjsÁÍFN±Ù€i	Ý3ÆÆ,ÑW.8M„±çiÌa‚3β‹"g™pCŠ¥Û¢ÚÀ=fH«ûIJX‡å”±·‹Á¦¹©ÔŬaü;&&q^sÖÕVIìðcKm.§ƒq¿¹d°ÏÛQ‰BWBý‹ùx²©¢Ú•µ•¯tY±þÁA7| è(cqÃç}7ü2*¿p–0Eäðg(Ðk‚÷ñû=¤KI¡}uAÌðÎ5.}ã‘k<÷s׸Çʽu
dŒzŸšÈÃIŠS¤³TÿÂ5øF¿‡߈ÜÝ·T÷ò:/ÑÌažr\†¶+záG>f4=8'Áø?gËW/¶}ë«Ñ||ާ,vÏ7ÝwLZ¼Ltpº¡æ_}æ¶Þé*ìÿ°Íd£gŒåň"0ñ®}DZE¡é;º8÷Ïb$â‰d࣡°–PÇ=÷<*ü/R(;õ^ð<:uHˆlâHñÉSŸ[|MÞ¸Žè"(½¹Õa„µ°µ¬R ¶´ìdZˆÿbÑ[Ù\ÚQ¸ñqãN
¾ûcL!€‹”ÌTcçȆ|è–ôX‹¨B¦ï®Vþx?ðîünž-Œ
Y—z1»	‘Ñ÷‹äÆ.Ù.D>+`ßßþÜ[ýšK¬.¤éqÇ_uƒÇ˜D|Ÿç6ãg©Ð)°	:ÚPbýY
w%í§Ž2éÑŠÕs‚%½I¼F¨fǯ>_­ÑNªq™’N±qàŒǧtoñ=‰Tm}1î<	ŒJÅeX<¦C¼+O¾iÈÇü¾žrY×™nYÛa²÷x4Z„wùÒ±ôH¹WóÂÒ)°·’€¹+/øÛþ,Å?øÆoS÷Í›~ä/®ñEJf€ƒŸBÄŒÅaKϯ\ýŸ§"`úèäÆaz²L»!”Æ`M¹¾™¥Zñ¶@#f—¨ ²yw ùãˆ2YÃø,uÿ£.$=g“•¬‡þ‚«Ö;r`>v½##¨t¤ôÞN\wÛÇ9XEܶ’ùIñÒUêô¢•$Þÿ85)YàŠ?ÙÝM…zy<ó‹îG· XJ‚ ÝPkr5x8ÿc¯aˆsN×7IF"w&&gê’ò¤´J07Œ?öè¸ÅïýnßÍ[úxÜöÇÖ^_-íÃâX™ér°ÿ
þa$^Öèm¥hýÔ5>÷>d
^G»·omºvè•»N]㤤ÿÛë®;•–R®cœ3¿,Ä^äóèZЕ«š.ÿ-GÓp,:š€Ç(Ñÿœôãä¿3.vÊendstream
endobj
104 0 obj
3523
endobj
108 0 obj
<>
stream
xœ…TM‹Û0½ûWèT¤P)ú°,‰žZX
eKÛàÃB·,!»I›&k¯=ô¿w$ëÃ&.Åx,¿™Ñ¼Ñûq&÷W|îNÕzcС¯8:T/•N»úÐB€€0Ç@í¾32U3.Q{ª¾cI4fDâ&<©±Ž9ÛàB%¾ü=ÜŸ‰Â_=pë
¸T­õnˆ’ŒsÓà/„Öø#‘Ì9{l1?B?ÚOÀKÈ)¯ZÆ-PkŽpšÒh‹QÅ™Î	{`ƒÞ¼zÓƒ2BàÿºóæÙ›sòâ'o‚wŸƒ9.xïqrãKÚzì ãØÞ[è¶ÑKü&ûûâ/IÛ%p(`!}Oòò¡4bñ:ƒ+Bµäáìw|.;—ˆ@KZxYͤüÏk¿-'ôX–±@­lˆå.X•€u^zá¤a"ès[µ«ÿ)ÔåC¿d™ºüƒŸ²£›ÇZ•]_­Çiv»‰–Z˜(åò&Û%pX:ç¹x‚K
Žeñ.KuÌà¯ÙÀ$ñŠ¸ÃµÄÛ.åÿ‚…ã»*Ø]ÏSÔ‹¨”aN¦Ïò4›–Éܦü~v`iy¸J‹±µóGoÿ=C4Ö§B1ÝøŸ•§Q†%LÇ0mJù®ÇqÐ܆ŸXŸ#·ó¯xˆ#F™›Q9/š
µ%ñŠkgÇâ¢û¦­¾Áõ[Ð+eendstream
endobj
109 0 obj
527
endobj
113 0 obj
<>
stream
xœU;oC!…w~…G<@±¹@“*}©êã–¥ª:%J¦;DýÿRm.‘Z1|Îù\ x‚ kÔÃbnæçàl.†º£Ø51KÇ×P	ÚɬI‚ÂPâäC[Ì—%L–1}·'IDú—¨Ií(®[t“}@òµn¦j·Èö
Û¦ý=º«0£‹‘|E¡Ö‹Â\E\	"Ó_ûkXJ{콸ø@©‚¢)Ëh–]âžÖ	µæŽúFÙÅ8@’Œj‘¹è²HÌ«òªxñR´ÏzîÍ^9zAug}â˜8ã&û~ÝOdý§}3ï²~Ó¾QHendstream
endobj
114 0 obj
241
endobj
118 0 obj
<>
stream
xœ½Z[“ÝÄ~ßP•¿°oH	Ghn’†TCAB‰—‡N^{m(ÛÇÆWœ_Ÿ¾ÏŒ¤½Ø¤R[»{Ž4š™îþºûëýr:îtÄùïÉÉÇÿœO¾8Ožürâèæ©ü»÷äô³3°œúq˜&?ž=8áÝéìO'ï‡|zöää‡îóþà†qŠËÒýÔüཡ»Ûø¤i
®{&—³ï^önˆ>O¹»€O9ŒÓÜ=ïažœ+„ÅùŸý…—üÌ—Oiˆ!/§gßœœýá‡îS|,
KXº/a1·Œ>NÝ×p>Ï¡;£Uç+ÜÆ¡ð%»î;\aN“£uÇ!»)çîg;-㘺'øÑå%:Ø"pór=˜wæ<¨jÈcæ­åÁM£×­ÁÒ•1Áľ{«çeÇ?z˜6v÷à÷eèþÓ>uGx³tá+^~ÝE°Þ»GÐÛ2uç8=ìŠã¸¼NΦ° ‹¡ÌBC_ƒô6þ
ÎëqmÏ´MØüwŽe¸ÀEá‚K¸X”“Ëšø„¯Þ«d|ï•mògw²9Z,ºçqº…ì¦3£öðq°æm~
÷ôAŠã8„	Pxv ÷¸7
éì'ø»ï{½X݇á27m‹l3ƒB#ÛN0ržÙ,E,\ê>*«<:Ï¬8l&°U÷¥Éø´X¯\üÉ–0=;\I.Â3±“32ûAŸF•D'ÀOJè¨Ò<`9‚޽'«€Òw!Áå‚—`‡°Ü]Á!JŽŸ	p¬ñCD/${`}àdOPŽ€²E‹„àXªß×)‘6ˆ»ÓéŲú-ƒæ.Á¾Óë#¡ckº¤À"D<õÖŠj¯HùC>碫d&ËðÅÊ
ð‰QûÈVï™JAÔ¢’âÐR1)…±Ð—∼q–¥
âhú¶dŠÝ0Éw¸%‹¾ÆuèÊ[®@pC²SØ£§d¬
•+„ÌyÕzRUþŠå¬øÔÒúS¨?y-®‹5†ªJö‚Y¶¹_#ŽÅZ	¬UŒÕå]%³.E`Í.£S´4ÝÒ“x
@Z\}·­DB»)Ϊíb¬nr¹I<ù=-ñ0:Î\µ<оµTø Æ€¦hñÚ¨ýLñW´…RDB4z“/	wäHiÌö(+*Ñœ|µ;È	€Ò[xIúÄ>›®„•ô•q?bÖÄ,‡ø©ç¹ø¶L(®A¨±'H£ÅDŒY!Úþ`¾°ž/Τæ+)%n™vznR‚Ÿ¤Ø¹]iu‚®Pò=ÞøÝ&d”ÂE?rU¯,¿×Ý–" 8HÓ•Tƒ2j¬(¨eúš0”íR	ân¥…SÈ4†F™N7…š-@_Ÿ€ÃèûÊëX܇%™E!SÝ";/yS¬‘a
Ù¯Ò¢d	d"ÄêTcâ|“ªh´§Ý!züõ£%!Õ´éÕBkEf•°ƒhÊÞŒ°¬#p®XÎV#%ïËjübIq“UsJc‘
ºÌ¶u†­‘EÌhÇ+Ʊœ©
‘ç3¼lºK¢‹[wž+_¬kvü¡É tUÖ>µ¨]ª=(„%7u9K¼Z›PÏÂÅj6ztò@a”šjÃä`’•K®ÑýX£t§ m¥óÕ´‚Û[{¾)¾LK$C˜3äæÁ‡’xCXûÙôÑÚœLq›Ã!ºôt× ñ8!jŸµÝ¯ùˆxGå®MQL¹¾J¸í)tÙüAº’&¬Ì[:“[ý€IL?ÔòŸ¹_iåÝsmøÞ¢ŸlÏÆ›ª#¤ù]Nuª²x c7,’ûÀâ³>ÞÕôm£ÿßàA²ÈQ⣛Jôð—¢"8;'6T3ý?¡ÂjÝ­fü¨É“”§êµ g%ЯºyUG¥iñ!¢¼[å‹+È‹ŽMM›¾’ôR‚»A3eâÍS5¨ßÕ´Ô²t“R°¾±WÅJÉ"duhc‘Qu²[ÌxJ£4ñ™ô½_ul9.Ù©*ÚöuE*>Äǹö#ÊqË›XJ[{'lZ÷»ELÌ=¡àsÑu×Û³5´g|¬Ð”,ã%no_½dƒXÉ;…†­:ìÄ7åî_q†/ðÏ¿ðÏ·ø_¥éþ&7ÒÈüçÏð1pDݸŒ£­ ÞÊ+‹4Æ|\†ßãM¸Ï»~ŒŸ<–‹à‘B+s×AÞ'²ûÏíâÏ
U•‹›Óy‹ºü’‰‡ä«ûÆþ4¨¤
2¬üÛ$1{€L‹öØK`-ÜæPˆ^òlÜGµ^uä[»ø¦.wôâórñ¾J3S ²´¯÷q¥1Wš{Š‚:âw¯÷xl_í¾Wy7Cø<@¦æ
x¸˜úâìäðó_!èHendstream
endobj
119 0 obj
3628
endobj
125 0 obj
<>
stream
xœ½\[Å~_YÉ_Ø7¦#OÓ]U}CâD`^$P)k/¾Èxg±½Ç>u®uNO÷ì¬!2žé©ë¹~çÒþå´©ÛÓþ㿽8ùð»áôÉ«“æôÉÉ/'-þxÊ=zqúéYІü¤žš©=={|B3ÛÓ!œ1ÕM8={qòÏM[u›Tuÿ:û{ž[;#LcÝõyÒÙEø×j›6_Tm=Mcš6ŸTaómµ
›³ü¼nš6õ›ÏàûwÕ6Æ6?61¯]WÛ6„)ÏÊS¶1ŒuÓÆÍçUÌ#bL›/gk܇é=Nÿ–—k`Ë6Œ4öë*À÷±l'¿Óü­·|‰mlê¡&ºì·yZmûÍOy»1ÏË=¯bÈßÓæm>òæ×*ºiún³Ë·xYm»ÍEžÕ¹ÇÍ%Ì=Ï?¼Èóáä-Î|•¿åýàððC‡¼v`Í8
øËCøŸh÷	(7×°â|‡Ó›×¯»ãgy̘дxØG°r&X¤kœËáã|ÇÂ_^Áä1¯6?gÞÁ­ðOàyÈkÑd|vQ΋ñsÙ[§Â:oáù€ËÂÐ]\ˆ±«Ã0‰è\V¡2Ä|,a¬ù,Ï¿d¢æíùÐ!ºÊñ…½![ôƒ#EHu}fá†fiC‘ÔÙ6/yÇ!1)œwÌöX[‹ýdn‘X
£fXšHŒ¦“CÐ5AÀ¸)âž ú=ÝèÁKXîKêl–Jô–±§=¯ÊIwêÌʾùl-JtyÈŒh(ÓÂ]U„m
*lzÌ!Ø#zÕ+æé%€¨,8m-Üs{ÎÀƒ‡Am/cÌ2rkÚ®Þ‘§7v³,YF–­i8ïl`jÑ,¸TÞÚ©1cfˆ‡Õ5fpG¼LÀÂD$eF‘,´‘¡œ±{-G·U3•wºK‘3¶N¬ƒ}ï”К’bïV­¬ýzo¤yHà%ÅZÊù´}®¬€KÒÄF£ èn:„ËJÜ3fSWÇ™ð±k06×ël;¡30^' ^z6“Oœ6t™dáD$+Õ¡ŠœË]°b±gdI·pBXÇ@/l\5wÊÏ—?_èÏän™Þ2Ç»´ÏñH¶¤,n$ç>·X%æ0‰‘b€K’]vÑQýpœpö#6‚wd¹ò«à{H"ŸËà80<Ï\ËøºÄ‰u¤+çTĽ§¸ Ùû[Êùwu@œ×ÒU~c¬—÷Eg0îJB‡K[ïÎkndŵ¢f]ï²ÍÒâÁ0’bÁV|q´ç€Ðáù1q"iÀ¨”jö„Ð*_…öº°¾­!`)˜uœ²1¢èP¹øÆx"`T3±»Ÿ#ÿ‰òï¼Àg…;÷4¬ÿ[ÞûŽF2§×MÆþ]Õñç£7kú:㊜´B¦‡bG¼^ˆ"Úà/rìЭZo£qC»©CÎÁÅÅ}a°‡¡7®ï,Ø	ؾØ
ºb¯EwöNËJ×Ì4CÎFqur(²¶)à|]–¨ð=EŽÑéA([_JLê={ô8È&RÐ,ÝãoB=ֈʄsO‰¯®6ä(AëF†ç$^YT¼¬}Ññi,çAfVêÛU´	Ç%¬îëLŸçXôK3ÈV~ÀhÜå”Ä£v,\xcïgpØ8Ò%ha(,zI@èvLÞV4I¬ûhÓ>4LÍbI9°8^°N³1™	x2»€tܾH•=‡FÂS1W"P
œàYo­q4ê54x)ØŽÍôÁôfÁRÌerJ½FÀdøYŽð
ÜÊ„
†’N …¬,6Kð\>Ι™¯¢­K;ÔŽFAäÌ.QÔ4Nj»íc™mÎ|µ& ^uØ‘öÉ:91hGùL†2*ûÁ6™¸’i­ê’Ó\C7³gÝyÞVš´vŒdëta}ôÏðœ‚yÍï¹3ë
ÂÏDð$G±z°½ó0é’§’úâkÿ•@&¬ìäVsÙFÍ’†ÁÆAmÑ'g2è	óð¤§èã:vÊêBÉ „NÞ¤–ðÏ÷͉%Ë÷q‘qÒì©&|&’ÕE‚–d¶æÍg8TQ/{ÍÔC2MÅÇúÔšcóEÙçÏUNƒÆIÙ%“*!œ$w¦0»Ÿ&͉¯„ßš½W¸-ë¬99¨AŒígmŠ“÷û‰.-ë*¹:äñßô$ÀQD6´‚ˆØ²("Ú'¾I%Y ƒ?‘Ëä×B«âK@o»Èvòæø&ÿ‡ÝTW‚&
uø¤ï…–º¹)3ÐÌ.(&£Ôìf)HÖMdu£áš×ùsNödËÄ
*ž…ôMÆA"ÐwãìÍÓ2ÜD»)G±
e´MP%J	;Ã$y•PµJPåsލě4F…+–1”ÙUûq:nÞÒy€g¶p¦¾`: „í¢Ãk9GÉࣶêbPœá¡SÊ4ãå„„a©'˜E½èëÌWfôIõ%‰8辪ÿʈs*p‰ÏDÍsH…rÃ(BI8¤p mMňi9äÅ“ÁeR‡Kãq|)Q ¢Yí	Cp"‡7f«)¡$žs›FB߀
®€–ÔŠã¾Îãàº×{€4ÝzS’7¾AªQH\ð»jÄBE»ù±âJümÜ_PÁ4[ “ü+¨|ÁàY«®ýë“Õü@”B'™µ7ŒÖ¤‘mVD¡^oߊ˜,“G»,g
‘Ä£,•Ͳ‘'áèE¢ÊoL;ð¯ä8éÖ j)‚ÖK
Ǩ²§T¡$Ø'gà±â«“³¿Ì{!¦ ñ ÕKP]kÐ(?PA]j¢Æ}˜Üð´04Ì#àÃ4ø;™xºö}龫dšK52ù½’Í«Säò/#ÿáR=-óÐäÉãöõ¨âiœwOhI
D>Û¿ño¤½Ç!µ/ªcèf¯zñ¶79ŒÝ¼ŠîB?º5ŠgKÈ0÷RëÍjÒÚ—¥DC‰É‚–ØæDçäl¦h&q’Qø^Í &02ÃbqÍÛX$tiêÄó².MÊ }c £S½˜ïMÝúMÈ&èaQSˆÍ!"‹¡‰ô+&0À¼õÃr
‚ÒÜš1‚–ÔL×à1´e2ÓPºJ”Dú5E#o`ñp׬òÔ¬­Q×&*‚-œÐ·ˆ2KÝWpt¬ƒI䄱¹Ió·‡7Ý* ¶†¾¿¹Ãæ{º¢†aV}é(Ç H„*V~ؽ<¨Œ§‘f& ÇZ	ŽºŒLÄVÇÛdxÂm3+Ì
·H³!3zJÁP½—GçÓhu¯¤‹É!B2H+{p²f/àMl"š]&–"k̈ )YE±–|Þ^öXìfY툽ЅÛÌÚpÙIeÕeŽÿYºŽg}Êù#ÀS>Þ§•)¹PK0~ýb€à»…øùNá祉ƈ|£ÒÈ,iŽc85Ö%môx´BrSÂæ ƒ?ÊwDh!jî©·
ºØzÿº«ƒ#’¤¸uaøVåa,IHZCëûùbÂ)ÃrØ=ï6\ɺ㻊rqSRÍjf}qœ\ò`w5ÛHWñQ“ÐN¶Ò „Ù6?³Ì!ÑË™ ½š•æ¦mOY¨íRȽ·)w´Í”L¶ÖM9ms‹n¶”ã‚Õ]5 ê˜Â¿ÿ˜"ÉŃ—Ù4u§Nk­'®¤HôÐ:ãlÕé.QCò=.8=#½(&ó[™ÿq‚ðæB¢ã6[P6
ÕÃI«¬H54-ôú,kÔõµ2Q%Q6Ų÷,mWºá}îVÔR?aºÌ‹zÍ"‹Ý†`r¦ÇeÈFÁ ?Tlï—{¾+þr)]±Ü
æ%n{‹©–¤õ¶Yú@Ü–cMÿ>-Këæ9ÓÒ0çzæ(]§8»uÓ/Žî=OkL.t¢Þdó•Ì357dªh?úa³&¨Ç*—s@ˆq:0YUàý™Ü±Ên9
p×ÒW+´ÆœŠ½R|E¬¥±Ò¡"ÒvU¦{Ͻ†ôÃj”Z)(HwÐÀƒî¿m‡Eÿ‚å]›®Ã'Ï*©ß;1¦¨C*ïÍ,Ôü÷!™&ºT§Áa¬Ï3[
zºOÈZb´óª³–¯tÉ+2ˆó¡DÊYÝuVÃÞËyÕØÃó#ñ¸‹
jí‚îÁ®T³‚—BÄ6·³
“³LúT‘ÃW3‡øA)T”n¯j‡™×Ÿ˜cûÆzt/Ì}	$%¡|ßTüš]É0]¹-0ŒÖEõ„Ê@Mµap~!„˜?•¤
Ã7e8Ь¥—œ>VJrZ	îâ‘ÐSù½q駯¢HPÆéh$4… dR1ÖBåÎXÏ5¡•
•f¯·°|­%®æínÊ4;wÏMg³hlÀ>g+ßšbí1E˜p Â;0·°Î¨ñ)…J¹ûåÄÆØÿ.®ÍËÜF¹^›ë{ù'RWä>Ì~˜Ò(éq ¡$	þšvâAMc³åÿÒÜ@¢Ðáÿ~¬ø=bc„/ÙOyŒ±d9–-—õo);¿`táÛYas¿„n»œ-4š»ûÉØ;»&½PŠôo,“Ó¹©¤rØQRÞïs fý]4*ÀûNEßž=SÙZ^ðY€ªYë¡w:‹S))ÝΆõ$\íΦôk†¥œÅy§l9XFµÔÉŸ°ÿVAäMÆì¤d˜½'Ÿ7t€ü¢qi?oK€%ï„S÷‹y•ØõâÍìºñïK£}µuêÏŠÕ¡¼EiŒ±AÀŒ«ü¾*
®ú"xØçšn
­°û—G“((vAìõ0‰` Oï¡ï»’Q©ö…–@þ•€òž¼H£Bl £êÁŸ
	¥š+x6›CâÔG÷ï?¤¦Vtò´*]Öºàk}xU~¤?,?Ô‡…@Ï–zUÖúðIyøja¡GnŽ[¨(ógOS†qfšÙkW>¾Ñ‹Š—lض2hÛß×nÒC*bþêÆãr•€­o$‡zL³Ö8-¬Ìú;ÄPî½SÅRÿmÞjrg%Üìœïî|9¤”éÃ"hw¯#ìõ„˜ÞÊ÷-€SóWb2¨%
†=w¯Õ ;Õè^?;;ùGþï¿‚ïendstream
endobj
126 0 obj
4522
endobj
130 0 obj
<>
stream
xœåZYoÇÎóB?b‘`¤Œ4øP£•R‡A‘pîÑPOúÁ)Æà½”Ãn¦Ô$ý4¬K3*‡FÛeðBûá1Ìs~i^+¤DªqrÀ´áNœ¦5òŒ^ipJ¢Æ£ÐÕ(Œö:µ	©@NHµõÍ”KÜT+é´ç–
9Zð™¿Z(˜bÞyd*-"Í¡°-¬oAj6þØ…—S¥a‚z4BÕQû¶OÀò„6d=œˆÑZѲy¶9°GŽ‚GòK'‘‰ôSbp¹'ápú8’Xd’ÂÀ݈Î( jBÊö 74@€üt¡îl2¼!.šv€nœ|?hì>Ó£„teçt(d¶av‹÷A©ï`GVí… ok8¹+âB0Vëp’‰Ü…-Ìœ¦º^[˜§iŸ8‰ÍìUÃeŽ[^eFÅÉ@LÛ˜·‡Sâ–QeH”5ÿ*Ä,¹
™°L\XJ=Z'TdB‡„e!""Ôé¡ g3_*?º)Lqòïpò1>Îð±‡|\ãc?.½´"¿Å÷yøUÃen;ÇLjdÍè)ʲÐA†é l’¼‘Ÿ¸Ë)AK*Áê–"XHÆÓT‚¡Á4­“qˆYC+ô´¨UØ¸ôå¨Q¿É‡h÷`åÄe¥®”æ<ê»NØCb‘Ó†Ôfô§ÉÚ	¹N:6Ò°ÎTZ¼#”Û÷Ñ{ÜL$+~'Ri=Q™™t]Tªà™ù½®ƒÈ'Cƒheþ	Êóf¡âÂeðÃxBâs_ÛÒܤ<ÄŽVyö^ 3 ‚mIЦ±
¥jíð¯µÙˆNâϺ.PTVpd;žàˆÃ¼fõõScÙ´Ã~·aU‘æýh~Qâ‰Ã(ŽäÖÐdC5îÃl<ºî¥v~'NJÆr;!¸©ÉC”ÔÛy¢¶ï°›õÅ /Ò0.€WG¯k–òMoV*æ1Hº`²¬HGc
²ˆÐЀ
¸•V¤Ì¸¢k5:²PöO`_q
e¯tZˆD7|öûEËĦ†>?(ÂÃÐPüAžg‘b¸áó-‡^³	•Ôˆ6cÊAI!i«Æ·,²2¨-H²X„ƒäçñT– £	®A›’E{»»UNq°Iw˜G Û– ÈO²†à2:»8ÆÉ€ô=7L±=ôÉT€<Úƒ¡f-È`2⪡%¤AþãUÞb·]¬5Ÿá×
ÀÚIÑÐÑI	`<ð´hûÊqF=Ç à1,‰ãUK´¤ó5VR{Ñq‘¸I—@·5n V7Nl“:z!k»j‹,ž¢ln6w˜6¤ˆ›žjaÄzèÐçDßjA‹%ã)¦£7v©ô]gÞTeLh÷BX‹T÷€¾Q‹Œ~´`¤e±¦áY¸ª¿’èǦŒØIòqœÒQP1Ãe‹u^PüœùžôˆS	#ƧIˆUˆsÒÇs˜º˜ç~ªÝ€.,fî®1ÖËÖlVá^ríQÇI{ÕÿNΨ32¦b?
õà1k‰¾„A)Á[3Q§e#E¦Ù’‘Š’×ôwÆQ	Q«0D†£ëZá
€™Ni{I \¦w™²Ûó­<æ§žR‘^VYÒQ/Ó:c¶ÍäÖá[bTë77ÌšªÍ’7Jˆ0"ÃîdÄ\r<ƒ4Kó.ÜÂú´@Íf‘˜^WRÊ;Z•·úÑm¹.2åájödöz®õè¨øìösÐW̬ þ¥´{;³»;ßί.®fw˜ËÙÝ?âãÞw÷áß΃ùofwæO¶–ÙÚôël˜ŒB
ƒÁìJ?&¥äH}¦G`^V]KÔxý‘}ô‘°¬µNYú±H©aØ&اŒ¶)ë‘Qª'« ™LW“
˜©Í£][ÕHu‘ŽñCW&U	½S»îÜRUÓšœzÛ†OÆqÚ¿V%³Dïg…%M1%ñ"Æ-èw7j1äR£Í%À­%]⇡'•1ý‘	[æ­x;“J4fÍBèÉx¸ãBJ+6›	âà‡šœÓ[Ûbˆ•ØÓZ±:´7)u)"Ö´}ÿ&¢IÝì¶ÕÙ¨^ýœ-›NiVŲk¯>ñþÉ—j,Ûî‚®XRõÄ(cʸLU˜!²QèxSU<ÍÊ\êg×MôÐn/±t	§É6-ÛÊÎF®BÙƒF òûŹmf…Ýg™-¹ð“zF.LEZ–࣓係…ƒ&ecÇåÙ- zã-eFG6âfòµMð%£bùéB‹ÈÙjòy•‰íá,¹Q0Ýw©#­WM­ˆ™_vhW¤T•s¬¶Bi<h[…r?ÎÇX"I~¾÷=”1ËY¿ˆu)à·Ø´Ix&»¨s}§¡ÑËÒ®ºM¬*{Ó´³ú7U|KùîÔŠ,:¾RžzU&Wn£ªQ´î•%G“S]*ž´õc︭ÜK­Š¢;¡èâòû…*¦kxå(±à6µÁT+%•àj€Z{@)gˆbùXry¢Šz1Q‚Ýf]ó,•_êe²Ÿs¦˜•œápQ¿µKQ#`Ý¿WØ*¶´뀇ùAµSÅW"&«YY£ª;¬ÝŸòÕŽWTé]מÄè%¸.`ó³órë×;„ ¤äåïSyŠnt×[4Öîoè˜|ÝMwÔ|·˜4ûkËоM¹<:“ %2ÿyŒ¦[ðìp0´¡+å)O\³4kÑóæ•#¦¥I'º³åÆµÂÆyÚ8¤
ÛY
Ãñº¾.ª¶.¿E!xZuŸÑú­õ2íØ^cÀK±#°ºÂ>¤ëj:ï7‹x}]z	4î¨éòúËxÃýbÁwØxøäiTº“W9ªu‚ÑÄ*AÛïæÆ“2ò¤NnÜ[”[·ÜXnØëÕ¹û0Ùi!«éGuPýƽÞFõ؇vºèQü¶Î¸ñ܈²M7ÿ,˪/ö³¤Êg™éñ&¿Š"}ˆ¿äÍþ?©wgs1zø6~ˆ®>†n27ŠB®Ê¶Hònnü"5JS9¦Š?äœÔlåþ³ÜxØÀQïyn|Qö„¬Žñ@Ñò㺺{V„Önu	
ÒŒ§ãþ»ù•äÆF5~àtK2ûsîø>~À¦ÃS|<Ûaéë€aÊó@”Ÿ7ïåþ²Ò*7>+ê|Ô#¤˜¹ýž]¿`Blm:w‹È_É OS7ÊO­QÍb¤!ß§q
¢íV>sYþr=Šüš í¤òÇ×°iVPµÿºêŠø¸9uñÉ(Z¼?09úÞŠ€eצC·©ÏÙõÅGñ‰«žiÕ¿H”p©
ÁN»¯]1_ñZº
…ÇÎS®è¼b–JxLŠnJZ³Mmn	(³ÍšB±õ×HÙ$þ§\ÀýÜÿ¨¬´“W¥ñYÏY<.9èaè¢ÁXÕÊf£œË‚
.».“ª²©Ãv¾“âF²L³ÿ+äY2ÉŸ¬²?yV€¡}À¸ÌýWµ,{îâºGW]Œü\0’ìÈTJùqÎ(q÷FÓ2ù˜)¡ãnä (¾b¼¤°©dÍ»©;öø_æSB&ê<÷²H±›0w‘Ñ	Ö¦.›±ÞY{¼^bÏ=ëRp}Ü£®9CÅž.{5€÷Hâ«IkîG×á4pá²îË.ß<µ¾´cýöóØþ÷ýJâgˆ+Í’\XH©mþáÉì?€$jÈendstream
endobj
131 0 obj
3366
endobj
135 0 obj
<>
stream
xœíks7ð{~…gú3S'ÝKÇL?äE›641ÓÒÒé„!Òüûj¥[íʧóÙŽRÊdæ¢Ó­^ûÞÕúC/‰E/¿úÿéùƃ£²7o$½ÑƇ
a>öê§ç½­¡R÷ÄUR‰ÞðÕ†)z¥ì•i'²7<ßø3ý<*úù_ßõˆTðRÊ8-ô á™Üî²è§¾ˆ«JeU´Ù—Ña £!ôïöøá¨?He'"‹2=w¬¿HYéN@©Œ“¤,¢'0üÇ~ªß„€Á	€©Ì
}	¯ª`­=XõqÆçR豃4Sq¥JÝD˜§î³ÞÑóWU¡÷°¯ûðÀil×qk²”EÊ11ðRôi—¢ª,FÞë•£xœÃ㥞ž”Ñ»ú=µ0#ý°ç›Àëk
˜Tð…<ÅÉ,à'xã´	œ¯p£ñ”ðIjSM¹Gßw]çun†:·]§ž(«”n+³%ÛyAï]çgo#uç{ꜸÎ7-Ù…„9§;6~¿t—Ôyá:?†ÌôÏØøˆoÈjfÌÏ?"uòè­wBl^Ûf–ªèÊÛ6ÙÖÎx)ÇÌ	5Ïi2¶Ä˜š±kÂN5«§±ê
dLJ›ŽN;ë2šáPÀl)e×;Ô×s4Éô)¤#•}‰AE6?¿V9÷D+$ål#3™hAþÙª™ƒÈU¯ó·#Á<ÀF	iøG+å€ßè¿Y	FR¹ÎíõEH4&(¹™±
ý;
… 	?g¤ýß„ IÕ¾ÍùÒ#©¯”ﻎžJ[HzŽál•Ð#7§Áë2Qàré±€¡ÚÃ^û,$fà:_P'!HcEäy{¦l!¤£tÜI¤ï;|?FfnãrY$ÆÕKŒìÀ·ù
ß3ñø AV•F)n\ÖAò
€`†¾ÉinQ4Ò`
xwgÙ_5Ôý
ÙqD}ÐÓõ)N>öÇ‘NC«Cœ††UÎLý»âQ›ÍÉξñÈ’öÒºëyKt×/CÞç$k&%à{}ÖØ)Ω[ÈØqlò[¾¼î¶0L"Ç0ÌÔd³¤¬r7°á~}

ÿ¯3Œá”¬Š3Ùùqä*¸ÆNï;ãFA`…^­aãI¿ÃáÁ^ÄZ#òÀ3DÍvÞíLסÐÙ9óY8š?ãÌq4û¶A\Þx®“ÅÆ|%\~e1~Ó†èÙ_p4 ¨PRãMäGØ<£ÎC®‹K•›ûw‚dIA/öÇΰm›;t²Ý©ã	怲ta_Ȥ¼šŽ\¦¦b@´d…RÑ=náp“÷ÐnÌðݺ£Ý53–™¨ ÐŽY;Ñá|}ñràk/{<ÓåÒÆ;-rã`¶·Ömré.ذ†1›5Þ½ò»î}ƒur£É‹~ÆT6ò<šm'¤Ó»¬Å*Õ—Ìg/B»»r:7ô7Û$°!‰YïeÞ“¯ÃCR¤ÈAwëî/ƺƒ ¢cæcÔ¬zÇ0³íDZÆÕìÐí|Ð=g‘Á^èªcâÑ`óŽî–oŽáÝáÆ¯úï_8¿^òendstream
endobj
136 0 obj
2369
endobj
140 0 obj
<>
stream
xœÕYmSÛ8þž_‘™ûpv§v-[~ë7BK'@RnMxéLZ`ø÷§]I»2V J¹aF8+iµûì«ìïý$ýþÌÿɬ÷j·ìŸ,zIÿ¤÷½'p²oþMfý7cµ Š×I-úããžÞ)úeÚ/3'i<ëýÈ0â0
þʪŽëªa$ƒ06Ã(
Æðk/ŒŠ8IDRiâNei'"ÖCÃHÄu]Éš÷m+ÆÌÀî’ÀE8Lÿ¿WÒŠÔ•VæeœTJàñT		•a®™»0’2‹ªeI\ŠºÖ~S²SŽ`8†ásCË“
õÃï0l°­N Ä¢Î”FAFÄDé˜Èˆ¯ˆøBqK…ƒ.ˆ¨ÎI
uÄ‚ˆ_˜xâ[yDD%º¬+õ\¡Ø­•K°T¡ˆàwšßçyEÌX²ñ,õ=’"‹óÜ`Ô¿èÙïè|pˆ`X"2Ä)ý¥àñöS^yFÄó¢E%Ò&¢ï‡hGG0ìСàƒÁ[5E`É_ŠàW"žñÊ9£ZJñd˜ðÑDžc˜VÏ'<=)`¥,…ë…ÞÏÓ2˜u\#¦§hØ\@ 4M‘²àªi =©1Ñ£aXš';ƒ¿¯aøFÌŽXé‰Oé©o%ç»[ìÌg–úÚÊ!Q³ÖAç¬ù…ËÞ±¨¿ò¹ÁÒM#VÐãÛW:ìˆú©á[Îùw›}þ‚i3YÇU"lYœèy™U®²_½Ì®ùño;jxNdùGPòºêRL©ŽâO­5TP¬ÁZ¢fÓ¤Í'îˆÜŽAŠÎ¡LÆ•<å•?3‘½pÉÛW•bC|ÙŠÜ÷÷‹ÜHˆXö#™˜ÂàCyUý•΋ÖI›ÁÆÑSaœé ž’qt€^RèbÈs Q¬åAZ®9NÕØi7»Ä64X¼ÛZNžúVÍ9g¾€¿ôùI3Á—îvëfsŸ6WŒ?÷<ë<ï4!?¿ÆÈÕ–¥Ô|¯°ÂpÙ‚aÍ–A}ø~~
MF^"’´05;Äf$eB=Á"žû¼~ÆÄCßÊk¨|§…jͳ•›t”Í̾IÄ-ÞÄìß2qhÐQǯ²…µÕšœöm€ïÀæ2Í~“¬1¦L72ÖwXƒ•Üc%.kKÜNªµN„ãºÆŸ}!{ôp¸î…gùmë¶š'Þþò¥;)LÍ·bõæöØ>ô9áµ/àŸjk!¤y6£;W×…
”-íWYéjæÓ”ÕŸ0ñÔ—ïâœæíh6õˆ€vÚŒvwÇqÌqßÝÈ“UT©Ì!X2ŒÌ©În”ÏC²Ë”‡¦C—Üsk;#skIÀWÕ'{¯˜øx.|öâ>¦ÙÙ:¶¦mN›x¹beÛØ¯-ñ¡Ån@usìÐMŒú'„ˆ
¡ýþÏ×§´?<#YêGôå®»:˜{yMh·½’²CY\i7.
Ú¶4yz1ôîéhVf$Ëœ²Æ“Y»ª[¬êË”#Ê”'dÕ	eƯlZÎtó¿íæðÅ8ŠMŸXäwMõÊtë¦mï-+NâÝ ù5ž¹ÁíMgémW>£}ÖÖÎ{ï<Þë
¯œzã©o“÷­÷¾ÁÛá:a_7ƒõ‰ÖcSURÍÒ!oP*Ù°§ûж^O²U޹ï:¡)á7]miœW'…\Wf\„7↽L?"Y—ì‚D´šý¸¡Øøhñ*wö8¾Ã-7’ïj¸:óåžyÛ‰«Òáäܼ9¥|nDF;\8w=Z]ß رî¡OS}à¿8ì7ÜH/¶®*”íl¬gj–>&¢`¢ð­d"¦úêGÆÄ‚ˆÝ[ýu5â+Í(tjäjHœÅYPV%zÍOÆ;íSû¸Kw{{šÛ„ˆ‰ü–®ð1ízØXÌ(Wœ¸×™ó&lfÓùy椅éÌX
#ON
:±Ó‡U¯‡ÍÓŒ³B—:àåÎQïýr°x´Ú€eñXÔGà­¬o¾M±#ˆîÁ€ßuþ¦#?¬<-ýù§¥¾ÓÒî§} ØÝ´!ï×-{ÝÞ‘É0·lOc—rË
V‘¤7>6>@Œm’`ÐTzË"î‘Þ“ÅIJï5œÃo|Ñê ª¹NrØæÅéÐHd›+ƒº Ô‹²»ó1U_#tø£É>ɯ~ÖͬvfóΗEw™È<\J
ÔŒâÕ^õ2øÈó¿Õ,eÍRW³á¸÷‡úû‹=?endstream
endobj
141 0 obj
1732
endobj
145 0 obj
<>
stream
xœÍ[YoÇ~§…ü¾i'ðNúœéÉ›K¶YNlÚ`¹KŠ”I.MŠ:þ}êè£z’Š%# DîöôQ]õÕ=úm_µz_áOü»¹ØûË·ýþ‹›=µÿbï·=M÷ãŸÍÅþß`‚60ÒjÐû'{¼Rï÷f¿·®UfÿàbïÇ•nü*4þçƒÀ
«å
cLk;Xt°…‰oÖnõe£ÛanX}Ö˜Õ?›µYàø“f|Û¬­Q­Ònå`ïž3ÀCœ^&YÓ*Õw«opù…oZãb…S´	tÂ×Á¯¡Ÿ¾ÂSŸ7¸Þ
k×Ö…v=|Ls¾Ïiöç°ÿ0t@Ãüú¥mxè»fíaJßæDØ×®µ®3ȈuäÄÚª¶×ÃÀqÀß;¸g§y­í°2pEmú¶sÀ/Õv¶·ðüN€Í\üy ¼
>~tPuôì°ºl¬nµVzõ
î`Øà:œkT£qæV‡ðÉ*kýjËÛk8´<†Ýmß·Îõp{Ó¥E~€ÝAÎÀ‰‡|Žc¦9€´KÚу[ÑÝ”6’ ŸV´Ü¯Ù¹ÎE2µ÷†ôjèŦ?5i³¸†gfí³½ƒ?ÿȨ:mÖ\ií£_m·Ú5D^G_Žáß|Að¨€:íiÊ	|4%£¶Þ	¦˜oËJà–ç_¸åe"TÚÒqÉäèã”ÆøÞÑ—k<žðy[C²0ƒç¿J(?Dâ©È÷yWZÜ.Ó>…i6ÐÍñJtŠ)ä‚ðà3-Ð‰Ý ñ^Ù7½mûPÖ…¤Ú—üt'˜hQ|8`‚{âàN‡ƒ=ˆŸâäóx:ܪ<ØE6Tƒ§ù,¤aˆn¼Yg*áWRÕ»EñŠëxÇ5ï;4wÙŠ=D|•m×wÈxúú
š¼ˆ!þáÅaÑñ®	¢Á ]óˆØg°Ì+$›×]df#6i»cœhöSiÈ’‘ÈÞïˆ>m$ü¢ñ´Q¯ê'¶g’ÞÁ³I2EKðp÷†Æ‹™xJO‡^¢š+2®#Lß:ㄎh9g(KP¢‹óÊ’0V „Fª„ޤ8,É-óK©Ág³•{Ôžì~Ž@2«\4@
l²xå—»¢âi⇟6†ÑÃ×"ôø!ðíxãI ‘'Î&	9fQ´>+R¢gÐ+I«´8R^§ÉòlšÌçøÌ‡ÉÑyàEƒ8tlòèˆ<§J˜‚à bî1w &³f:2iŒŸ ’ç§+äPùçl¼Y¼qp«_É[*ÓIï²Þ­Þ"Y82¸Y>E¯þÓHð½Í;PI+—OÉŠ½«0*ÌÔã%ù‘ù™x°ÈÀ‚9€>D²çyÑ1©'à-¢ÍóÉç$>éôÒüÖ©¦íÑ49©þãydu*€¢šˆ«œ5ª?ÁL˜
yNè% ñ,1hyú†a£ 
3	9H_ñdhÖz”ó@Ògpʦ±è ,
ác…_càBR=•XòÂà-·lP.XùŠäU“5ä%lpð[Âr4Â)²elðÍjû‚4\¥£jK’° f0Ô¡¯dcD,ƒ\tt¹6{$RníH`GÙl¼Ãm.œøD!
²Â˜)F³#N6æE1èÄã:€F4ÀW¯åä«U¤ƒÂÇÕ¶æ”a„–P5¾öDàüBöU€ÅéI'âȪFô­Ó.É—ÑekpÍ"©Æ¥×?¤˜p—¨ûçDž»W1ªpcÓ% ùÔC•T¦¢Ÿ‘vÜtÉhÅÐè1_&üC&A>odhÏ·}œb@?ŠwðŽžíl²e›ÔCV\µqªC’t)^2ë–̺7¤KKiÝ5JåßQ*qËR\©k0OpW¶›ÑzùlxÊÚ™E¯K6Š÷²¸‹
ä !¨³2Ko„€È²{JGuR€¶¥ÈÃŽ¡Ñôw]ÔQR÷˜8„%hØÞdsƒ«=iÁBÂèy$¼°í†™(ê’Äô²*UUIf:#¦šw ƒsNµ9ª„HˆrÂ9	-MBfO£ âD/S£°ÀÕЂ	$Î)¯µnlɲ=a¤ÐUj’“ë˜,‘£1ž1_›Ž]}µg‹²P|ØTaPÌr-ìVú§Æ)p3,Óº@IÇÇ‚36Ç
>eƒ"›Ê!
À»lº'ªpÈC©>Å\Ë8†±¬(¥1Ú.;áÞÉf"fÞŠ¤"§iiŸq™ÀxKœžÂ²$ì~”‡#Ãð.%Ór,/z6û€K;.²`	E
wù€`svÎ(}ÊÕ¼0U¡“Éèà¤%fç•£89×LWVˆLѸˆu¶(jšet•kO;VKηÒY¿])Ú׵ˢ×lo±ÀD“ª…ÖWqoΞrÞL•d¥ðI”…®ZgÈÆî*àÌÔíˆßèÌôl<Mvʺëd« âEáÂÔæYކÞª¼+›/¾cm¿ªT;Šo‚ZY×xòäèí,-8›ɃÐPÜRq9vdŒM3pôu:XrTãh|ƒ;X’÷¼ëLc7,Q´k©biV
2?î/zZbÆ!åL?Æ¥0ƒ{s[1O›€%Æ®“}˜Ëòqƒ…žýmjkĶǀØO»_R¤µÁA<“;2¥sƒ†ú^ôaYQ“f:“dž͖«"½ë!Ž}`«21v‹téÑÁ”‡Ge—óܤ9æ&
 öÞ¶OÜdæ[7(Ï%Ь1T¹†á€ûTwQ˜avÖ/µpŒ²I,_7œ-VqH„;:l?ªR¡Oz¸u÷ÚXQn&)x.Çœob=WgE7®—%£rcLí¤†¦ls¤f\¡\Ê)¬ðò"…P80}H=×à¡Îõº£*T2¿}ëBNFÏ'åÊX›†¶C¿Ò‰–Oy,¬ì¦vþ±^œ˜[Ûàר½Â`e•ìa*™aNgZÑó]ë|#ôŠbý¿â}©0ëûœ;ýBëÄ®|‘z²·žóÁ®@cƒ¸‚)¶”rÈ„Éĸ>…ÎA¢”91?ÓXE´·h“ÏbýñPЬtíù㵦Ö;ªäM¬Åv²ÜAï‘Lª€xäš‹ £OèïÂE%›ËDáRðéÔÓâš\!r’º’ë«Æû&æ´ñ¶µ¯Ö$»ª1ÀE;n@ßÑn¤2ºó0“š ËAÂ约±‹U
ír÷ßÃP£X°Äš83‡’A›:VÈ¢*ËaUlˆE5×\÷›Ã+®—#©Šù‚Æœþlò»»ún"ÇœmÓÌÙ±­,"N±#+é*E‚X	l¹J.‹þX¸ÃFÔBŸZœ(F¾rm¨d|fró&¦}š‹v7Fd“~ŽÍ}Y#1S™=ÓÇŠú¬éÃÖe¬¨‰Ps'Öò^›èеô|Ô`ÞÆ"Œ	Ì8\K¦ÒîW/9/§(¶X8³‰åWAØFxò+KÜm#Z´,´©`γ×zh
d›¼ÃÆq¬`^<„$¦Enøå‡….¦Þ3t1!äÎa­ìf`x¤¬¢ÌÒÙ†ä	ÎJ‡SdÄô]å‰ï¶MO?‰&È¥«(ü%+ºo—$ÚâF!3÷úÑ«'U£ß†ÜÜ+¤Œ^Ì)ejŒTs¬Ä›
º–Ö¢ãà£MЍ*•&àˆè'5ôæšÅc¥WùÅ“¬ôW“x 6åœlßre¸®u:`òŒ{`­tU‡ßÚè“Åè÷THKlê¬,Ô±ø¨¦Y¥9R}`å£ %OÙ¤^!HE
Šr°íG-ÈßB~ÃDÔîX2åD埲N¼EÆ©œ5Ÿ0uø
Â=±…¼ö|ð{Y-Cé(ÿÐà—PëüFnÔqÉ|ìk÷BÛÁÁÎ;–¦âòRò¤“ÿ§½–º|Lá²â&¯)OÞ7\æZ\w·|
½¢åD%5§0€jcá/Ö°—ó2¯~Œ<+UØü{˪¶Õ%üý„úWñ¾*©ÙË"áøRuúG%§Q‘)փȘ«~‰ÊQMt.µcŽ*ÿÞ0%É?¥ˆ°XVe>Ôæ­F˜É—¯\‰5 ú,uŸúTâZŠ‹¹xø [oÖò;Ó\>^É=¦2W(YÉ}U¯âŠwâM|i©4&s²GqŸèu#uG1¨ñmï™Úãuÿšjc•UÀ¿!/y¥yÑ3t6êát ¦ëQéªüøº)ïR¬µ"!­>oÖì[(ZKô%” Ùqíçy^^=)ï|™ŽŒÉsÒÁø->ù¯¿Šƒñ´5N¨ñÔu9í®9é´¥-êÓ~Á	˜€ü˜#NèáÈø(ŠÈêç¼Õtý»Ñú£²þ6‹ê&“rVôòE¼¬ófÄNˆè6½+UZ|ËŒü%XèËX°]G…ùôX{¬UÅïg	T÷Õr£ú&ìtij³Â³ò|—·º®ö÷zˆ
R?{Û·À'Jw•,‰çƒ˜‡²ôT&þª£Ò;¢¦·V³jT·ùo?+©Z3#$þÐ+ÔSa3§p€ÙÝÕ̆Ìü¦,wïŸxwVón¬,¿~`¸,݉\Ê`?ôe0õKu]éü~-Þ¥zþ1ˆÊ”œd”
JŽ%¸ŠøGÁ]ö9	…³oËI%º›ÅÖñÜà«9aVGº'rpjèçxs¶€qÚâôYŠïIí‡Nîñ‡òžcïál˜Š„ðVPÄ”ÜüɃÅt2lj·sÙæÁõÜ`‘÷fŽQK²\Æ:™cÎõÝË_•˜äCŠÍÀ’ØÅ‚‰Ó4$÷4\>Js$y±…}%rd0GéçE·E¼ô|—¬%“|4‡9À•Ë	ßünæƒ/‹ÿ¸žO½8óC
m
Í÷Ò\GoªúJ‚ÛŠ¨$ÁÛ2z4q*×ǹKQàœW‚NzüâÿYпÓtœÌì.ȼXÀ¥?†Æ¤-T…y¿ÊW€¡ŠN/ÿgýï@Î:îTWƒ	K›&UV®ŠØÜl2nªÿ¯:‹!Ä”RݯÍið¦$Âÿ]Í­r¸–À§$Dx½ÔûZŠDÅë¹çå¾·s*!ÐO5Ý=9Øûüü7Mø&endstream
endobj
146 0 obj
4230
endobj
150 0 obj
<>
stream
xœí\é“·Ïçÿˆ)§RL¦i}%•ã„øbM’ŠSöÂKe/vlÿ÷Ñ»¤§nõì.¶+WŠ¢éé–ÔÒ;~ïÐoVMmV
üáŸïÝýª_½ºØkV¯öÞì|¹âž¯îí‡΄'õØŒfµÿrzšUoW½óucWûÇ{ÿ\ûª]ו];üwÓc=ÝúÓÊ­¿?ïW¿Þ‡ËÃjcןÃÝgÕÆÙ¡nš›|þ>]@ƒ'áïëÆ´á¹©Çqð#¶ú$¼p]xàÖO+c«A7ùªÚ4pkì@_‚QïU~ý¨ÚH›0„
ßíÃh®‡›.´›0ÁÁÁ€V~†Yþ#ŽýE6αû×þ_•ŒÕTòms„Úßâ˜@”±j©açtÃD4Ym\S÷f©Ç·a~ë—py
—Â%Ìјõsøy—³ðý.ŒÔjÞ˜¶ká76:•–ÔšÃÌSŽâÃéaøDÛaåýú¼ôþ >É´É‚9ÃDòå‘¿®g"'ñ6’£evòê6¾ñø	
‹a ÒV>
»¶ÌՠòxëÑV“Côù™Ñàã¡ '‚Kí"$d<€cjàµ7À[>ƒ³J‚A¶,H6h"H™´×‘¥á'hκv[>á Sš†ò¦_RÀBS@™dêܘó¥jÎIo£ÐOÝ)Ä1Ç~Á²K…ùÐ@Cµª83:Îu…ê„'f¥²ØÅ†º0@à¤Bƒ)fÛ!Ãìrc{C9ŽLŸìМÛ,ZèÖD÷ÄMC-…>CRyT©Èçuåßv0ZÙài¦-8;Ì-µW	ßûÐ`DÃ!fGu?KÈö‡T°Q¾èÙ“ÙD¶\â—Ã8#‹€Œy8híR(Gƒ‘X0×ÒàˆlemoµÉ³}¯ÐÿE¼¨/ÀZ€?=4LRα¢âxM¦ÁÊ×ÌÝUÆDSÕE¶‘­‘£#!ö„£¸¿€Þix÷DLvò3`í#©f^ÀÆÄ¦rÉ—ŒmZt~2|oÁ·d	;ÌŸ\ß¡®`ëÄ‘asž{6Гpç’ma@W”–èÁÞ
q;—óiä?HÊH¡ÚV&òÜœ{1öµ±1,.lqßU™Ks(äcïE>|«R‹µ3,p…¦†TxÛ¼bÂÍIñ|ÑuwM‡ÁäÒG’€B‡LÈ}Räb6s+wCåŒ ·CŠö×w,«%{oÃî$Ãç?K`Hç
TÓP@µôJgÅ0–—4z	ð*¥£—LæÄvìì•I/˜~
ôTx?Í´øÒxAïŒ8Ôìo4ÐIòèd&Ä‹’Ó.î/‡v°…hIį	ÁÐz–"PÍšÞ°/´å©”õÂA‡Rîö)V:æðqT

‚A^"DÓ ‚ÇÐ0Üû *_içbw
+
‚½¬­;É{ȶìùá‚[R”+\¾;•$+Ɖߥä†ò™Aƒ> +èHÈ$PƒídÈ÷´•áø9‹íÛ$HÛ8 )Ý*YF®Púˆ¯3=z@-Bè`G‰œ[…‹}ž¬/lJÿYØøHmnÃã”a)67*;Áßã¢aFo`ºoE¶ƒRÙ&ḵæ8Ö^$M;mʎů²
ÐOÌänæŸÒÛì™$‘2)¤<µ»©ðÂDßSxÅ

~º
ˆå¹ÖÔeI(L1K8ªdòŒÓ2¬NˆÈI(s#:˜áN†v5§3±Êb4Yë<-râàü+êW¶JÛ6¥AÚÄ?NS z5˜¡•ÌpÌÉž‡aÔ«MÊ|Ì$1q$xÍÙ^ tƒ¾ k&!Ägs}LFm¦ÑdžøPËgÿ0DRªµŠ0·ÕÜÞ&Η|òLìípÕˆ§§FZŠ	ÆðÛ +=êèD #(‹Q–ä²ë"–]¾§År˜l1%¦Ž(¯ñìÙ ·]óÆô’oƒÜL]Ør‚ñYÇQœ[*Êã_…?d™º‹˜%%/H¾z9'<‰²æy†sZ1 ØïB,Wܘåx1q2,xÃë>ù<“·Ôôó.ÏûEèãjªÝÐÇ–G¹1›	ߌÀÈØwäã,K×%‹¢ò;uÈÛî'AàÀ:t’Ö§ZœÎókž,ªÙ\ZU€èi£õë´ÈÛ™º(w6„Éòæ®þã*0ÙEÑÞÓD—d,ÿž"6»I}µÝ+ȈBµWLÉžþ¨Jã&ûRiX•³X—šÃÛÆÜ"€µÉ‘$?fÙÅñ­rqüħéM=ÛÊFa,„àâ.€MÄ‘´gJ"ÝÉ[“ØéÚR-Ç,2#?ïúHØQ÷5{q]=%7n»ajÞË_šÔR¤–̨SN¥RT•ÚÜ&žü,RÆ4ÈݸoÖ•SÛvÄ ´m!äR^M7©”ìÉCDâ´VÐãëDˆ;¬#=ªTˆS81CPÊâ@vÇpÈÞ¢Û¥SðÁ¼gGÃHÈ,j^
BãFLªˆ Ý§¡î#0]ÿ“1’yHPëJ0†»z_TTû*8CÙnt׿%7 žÆÃ\hxHùØëévËï2á¢sáÉr0!KgtƼƒ5Þ¿ÄEÞo(nb³þ²PSWLgã“oªðsaäs½G°ˆ}AB$-eq'û˜“¤G÷Aª±ìo÷Þér¼=À6ÇVSØÞGë\E?¤GÂrÍ.FtŽ0Ñ#ȤH\“oƒËǧ0¬SˆXçâA~ŒUÒš—æ¨Ì6;V¢œTO–9ô´ºÜà=åh%|q‹«¤Z*t¿ÍÅ`òO¡š\§¸R¢ã„pD¦ã¼G“ÌÙ–“hX&ß'@BŠº|Ӛݖ«Ò°¼Oƾ±aƒNb‰çbÇÝ‚w':ë}S×YÔý¸«ôlGT ì-û>÷5Üõ·,Ká kÊ0Š¢¨0‘­OVæsXhHQ/vGžg§Äá¿d©ç™YÐcñ``:ö÷¾Ü{³r®îðG Û°2½w 害áù§Bî=Ü»ûðñêòü틽»[™½»˽/î‡~²úÍÞƒ‡«ÒHƒ¯í{´pö$¯½”³'f00h¡Ô¤œÚCÐ'9-ù¾ò)Õ$Iµ[Ì	d±ŠXšYÚšŽª:Ç­è ÎYY“òá8œ¿f”j)ìU0'mÓ$“”é1ºÆå~RE?èÌ×íô”÷6>(Fe´´
}?®¸ðRíiÌ"B1P\!8¡±ÊGU8¨TU¥M~«6F¨Š¥¯‹{g®otüu³\–£j)Ü•ŒZßM«ân˜kã½SA7NP&Ù‚ßsD1Ô6©+“>4䩸·Y0ñC¾˜!‘O|g7)ƒ±ÌØï®Ìˆ­2jx.€Ž†¾ìû›ÌLÓ¯
Ko±ÿ}ÃjÈXÍ™¥JÌÔŒˆ–R]f(ˆYŸð®Ú»Š6‡(ßó?:	µËUH­S~K(µ;1‰¢³«F.f5è‡ÈK3èc
"	¥X{ž@äÑr–óijb±£è‰ÂL
&	vPNo±”¶ø\(,im•G˜UôìÄÅ6JP'7ç1P…BHìA†“>
stream
xœÍ\YÇ‘ÞçYÁ¿a?°K˜næY‡
?˜-q!Y‡+c%ÃqxÁä¯¡Å¿gFVU÷¹Ö ØÓ]UyEDF|qd½:v;ìàÿ}øâèö÷Ãñ“7GîøÉÑ«#7ùÏÃÇwNË>”+»ÉMþøôñµôÇC8bÚ¹p|úâèÇMèòÆuù¯§ÿUZDo[„v±/NÏ˃ŸuÛ´ù²ó»iÓ´ùc6ßvÛ°9…ëw»­Üø¾ÛÆàvΧM*}ïʦr¯Űsnè7ß@ó/ºX~y<âÈ#|Ýø9öæÛ=õÏ´ÏÁ—¶Û˜ÆÝ4å«<ó@oãÓŸ—þ§©/s¸?¿‚é†.Ýï¶¹<2(ÑGK‰-“b›Ò.ŒÎE~[FÞ<‚çðñ>—~\™Í7?màÂø¸e^åßàçWúñ7}þ“|ÐÃ÷àç_
•ƾt›6€ßå##‘óÆë“?ue%DXDv!NãñÖÇ]ÎåN§z	ðñD[¯Üؼƒ3]á•>üæ3àø0•èpÅgzÿ­Î»Ôäâó:éM½ú©^}³ÖÓk½ø¬^¼Ð‹OêE _ý½|’l•&aØy?M«Œ|#?Tìa×üûP%Œ®~Z¯6´ão¯ëígzñ¢^¬0B´vê€øÑ•QGQáf  ì‹.º²þ2"©b¸öš(StgéZ~Jd©‹Y½-D›xg]@3gàQ(Ó{×å¢ÇÊÙ+Ó>ÁjR_IB.µså'ÛM‚tKågö¦7_&E+½•®c‹a ±7‹ÞàZÉ	}µL¡‘»Áoît(m=™O0ih|ÀæäÄÛ=cç f¡ŸP¢¡Õÿïî5™'ðt%£¤’Mc1uxDé6X€>«ãb2p€!=°ÏÓ´;7ÿ(AY¡¾õ…»(lÅ'6âsœLàÆ¬‡éöôx`Ù^˜`)ͪ8"åî®3™ƒ‘
’IØFµq’D…¢’’¨ü"‡SÕÈ·Š#À>»,š\.ð« 
æi݈¨	BFÑ[Ì
HÊ>êG/2¤r	zZL%ä(Vc¤~Þù»ä-{Nò.S¾°z&Àcò¸Zš©(³«*Ì;øéƪ»PdÒ[?íXÄ*“̓	–?&@ž±á„Ó‚Ja€œ2-¯-ðHþ36'-n„¿asÕQ8”’OuÌæ
#ž1+.ÎtaUnaÚŒ8ÊQV|&.C™ÌàåÎæº›^’0LyƒÈ$a(M›¿w`âEÜ"4³¨Æ·åkÝÅa¬ûñPÕ5ìÔªµîâÚèYN©Ïè4Ý_@¬Y¢­Þ©MY³”ÌÔh•ìÆ>«Íy*VåJ,ØSÜ
ª#{
ý³ê¥ªo˜cg²}ˆÄB°íDîm\‚$ëÁ ŸXoL×ã%°‰qI‘j
}Õ&¤jõlÅŠŽÊ“*K3yßeüÿ—òýés°JkÎ#š1_–Tt%iÄøòƒ+­-x¯I[Wª¨ªihÑ]\ELòDÚ˜£r{­ÉyZÛÊÂ[DdPt	åõ<3‚b¾ºL Þ©!<%FI
ÄÖ5Ù¨82âFyìðÀßì¥tªc,
È?ãÝ¥!rA}­UºSüš'Pm­Á1EÜùF‘åT. ¾àAZÌ#Ê-fÕÿgj¦ª¦MëYàAÖTÅiÕ]Zy0·uqì-å0ä™ÂTA
„Zøó fèßÔGëϬNk0–‰n™0­ž0Í6_dç|Î×ÇÖs¦kÅ Ö°+'°
o>­¶SDñá”Õ0”Us‚„¦QÌcD6XÀÖ˜ÝY¤É©XZDµ®×…ÎmòE]ëœ.}ë½òòz	±—¥åI¤pAªZÐ>¢á#ÅX®™§v™ØLF×àwêý1XãÇ®Zsù¼#­4ÍÍjeCQÆi-…
w‘ŸE®XàÕkCëÁ¬_êð*ÅŽTqJ.Ô觘WnjqrqÇ««­°^€~¹´:‰\î¼×Í[™ÖjÔS¢‡ÌU"·šLÖZáB÷®%ŒbÞùjaÍu*ìÜÐ\ÙR¦¾T.š™­xa³à3F–Zf4HÕ¦d¦w€dOŽ6{‹ì´ñJöZ9~^ÈâZ¤€´fY`Z§ØÒºª`.#›£™š¹îjtdaû'+ù×GvxbÜôŒ]&"L䯰'’¼ÛüôZ$㬕ŽYàÌìÒ/ÑÄwv£gÞç
'0¡~ŽnÌâÝ'oî?\ÁA¤†"V«ÐH‚1VQ®Ãxq´A¨§kQ
Åϸ®õý<ê%”YíÜ'ª9PdÀž„Áºé¹
q©¡R1AC15CÓøÙrsÎ÷b¨­HÞ}3—aó¼š/í²ÍœTアΠÎÜÖ•‡{Ù2yDÇ\6Ö½W4cÂËî”8ºJ«8­ .˜[í³ÎZL^—¸Ól‹Á?ktûûñ¸€¸Bî@Yj¶÷ ÙÍT×<$xv—½S¹¶õ¾ð¼§\Xé¢8ÅÀkùú²ùZÿè0Û ]½FËšÝHp¤'Øð¸+ˆ<ÿ-Oí³¹Lý€yù”Æ‘üö]áÙ„*̧Ó÷)SSK{z´ìGÀ~a7ô~ÂxÄ!½Ã¹Û…0º²ƒ.`«ù@ÄreOEnãÂÈ]æÑöÃ!#Ç¢Ý0ò]t)Ø¡Ï1PºÒ $ƒ«4_n~Ã{˜ô8úŒù<˜kðv®L”XÞZ5:I þ‘#´û½rvù¡œ˜É†±:Ý¢³4TÈ™ÓÂ\£[/ÑÄkÍ3DFÙ‘“]†»Î<¼ó‡ºZ v[2 IÊÆØm¸à”Œ!шG_u‚‰]°ÝŠ}Õ‹uƒš°°ÉO„Ò@V³Ý[àÞ:1ã0ä€^L“šÄÚ‹}L£×o53T“"-p«füÞÀŽRZ¥(¡mTÜK ›˜¨©DÛê÷×DZÿÕ/ó€;¿©täK5G>“Åè%¦¿prUôØÃü8ÿfbWL’ =¹±¿7Q …Úeµ{p‹nЙÄ3±g9±7
o¡:‹s£b|Ãõ7Œ,NãÍ#‹8‰#ÅoñqãJ¥L±e¡í;É@7䯧쨖f!N©à÷´„F˜yÂ÷á6¹ØŸXÿ<›ALêgìK¸=ÍuÞªœ¥~ZâˆÄªúÃ0åkô¹Ve;u­æŠ0¢3/æ²®i°ÁêCÑÃVÛ±g`1>Û·BËŽ­k5b4…FÕâbÉö2æ?ULÞ’’×4Þ Êëi"[Q’@èZ™0NÌóä†ZIê®-ñˆ™2g¡Î„Я-Ñ€X.<Ø”i@ž•­­ËèÛ"…Ç) Ä¨­Îø2RÎÌúE­ÉJÐ|MXïÉg¶ÙN¦³ÅØ[ÕÜù?	Xáá%¶ÂQüžÂµm¤–ÁÏbŸ-t<Óh¯7UñUÑ3ê¬~eÍ$âÑê§Âçy¨¯ª{E){=Ÿë›ÖÔÍ" ÒÞB¿^@>ú¸ËU˜ÎYN]äÄ#]þÍJ>ÕDT¦™j±&”Çüë?FOG³-F;¤®š|¯¼µt
‰­nÞš®ÊÖ¹…Jž©ÎãËNë~0´©*&r÷ô軣WÇ1îz¬/³ƒ+º;”¿SÎð÷á‹£;÷Žnßûúøíë«GG·8öG·¿„;ß~VþÜûüø?ŽîÞ;þî‹ÎƒÇâ;È.ºž
Ïq¹Z™ôÊ‚~X
S1ÏÇ!o[í©¢ýš“Ï^ùÍ4¡ £1/ŠödšB:(ævvÏô‡¹BÂÈáÀ+ð
Ù…,6GÅ̃ΔÃ&–Ž ¥50-FeËÃö›ƒsQ„CVDþH›êÇÒI¦Âq¾ózc,o¢ÙF⤸H#éuW~žPP¶÷ÚÂ(î¶‹ShvÀǤÄ)ò_Óäq·m‘´áš´.$IHQ
¦b¶)’aba£§šWZ«"”bœ]M^n¾á}wó¢×T<¢yëg¦QƒªÛlà +ñ•©ŽGÒHu\ÛÒ)©õ³Ææ~ƒ‘é´Í\f™N컼ëÓ£“ò¬™,¤ì• çÝJ‹r)û8P©×+•H›ÒAµ©ûòP锵4\Ô2]ºÌfÊÑÖ‰Ï:Ì3£| …8×U‰ò=#c$ãH…ÜF‹Ï¹ØcðTVx_ œa•Ä"´£ŽÀcDOœÅÖñ/|m¢ÉºY$ÁfºVj_Z^“ò:äêJˆÈ~9€vR¤:ÈöÊE7¼¹Ž±˜&¨.«Ž¢fÖst&Jû¤Ã$Ù[H‡ªý_AïWr‡Ô¨™Lô=X£~Õn}^äÿäŒÚ~,}–JŒù±T
4L¹•öa)Ös ë+#‘Aw·1­Ã
@•ð°…Þ˦ä+µ–+9xdÉ4s
¹²àUbËØ¾D¶ô›÷è`Aº©æá	Åл]‚œÈdUlZ#¡	u?”õžŠ4Šý«ÈsÖ[$»JMéJ•8æ‚ó¨Ö€ÂýmµA?iúúRMÈ?¬Öð×Q+‚¢¤^âlãMK<¥4\Aº|GŠTè6¹qUdõ¹¶œ^Â5b&–uP‹Ða)xƱ¦—œ®Iµ‰½G ~Iûd:šš9.Vm®Õè”-Óé,ËAË'„zm5ÌáB§…å–ê:cÍ4è#é­ˆ÷Z'ÎŽÄ>T”#Àû0hٔг-YoªLLWÒ¯µÒå’±¨ö_ùУ3v’Њ>µÙ+ß×)Ê–¶žã¥¦ê	ƒ™F㊄&Sü»ÃY56Û x,iJÃâ"Viº´èÀ1Ü'ržÌñ¿$*ÆëoÝk<¾>·¾ÒàTƒh
úÜ
¨6PD&<žtŸW&_K?p-–ß0Ë+}ˆzÆÁøø¸˜Ä§|4$y0±íSqÐs)Y¨¦]ZÄRMšsVŠ`*mÌ“Ž«£{ÈoéèÉq÷û*j2úÛ3²êiÐmÏ}¿S/bew87£éV}Xª,a@ŒV'­†IørŽ’¥ÔY-ÒßYµ§U÷oÔd2ߦjsé§óˆ{|uîeæ«kögY¬5õ¢Q*^þÙZŠ™Íg˜CDfð¤Žáæ››”²vƒÖœP|f^€NU¢;øA_s¢Gy±¼¼ßSXHøã1éAWŸ×•ùö‘15™¶ ­9]‹kjU¿­áÜMÜï­£g‹+^ÙÃz¨ž~[žÝ—ŒÑ²ˆú)Â;ÏøÇ÷€€†û*'M%;ö%%ñ†å$®jjíp͈H átæéªl²ÏÞ° Ü×9œ5èÒ,Þž[Â*3Øëçůè5;TsdŸ$oUÊVb[ÅÎs»Õ'
FÆ@PìÁÃy©©£Š4L?ÅTßõ`¢€œ‘£t8£Ëòç;sTèsìø@¦Ä‡…ÈF,wrª*ä
ò>~÷OíâÄ8Þ$ï©(MòœfØdй®ïcc’âûþ®Ûóš¦~8ÞBQËð²ÔôVŸúò›'z_^wGè=1z‡O}ãÐÛNßëtÕÉë|êmó~úúž÷õâz±¾®ÉÕÛN/þµ^lÞ¾£BLQ g:{˜˜§(Ð…Nì—v­¸ª\áŽk“°!?]_t¥„ú½ÎCËwGÿaQàendstream
endobj
156 0 obj
5266
endobj
160 0 obj
<>
stream
xœÝ[YÜÆÎóÀ?bà‡h(x(öÁˆ,[²7°"[ÛIdÁÙK»Š÷vw,)ÿ{êèªî&9{%@—Ó죺꫓Í×óª4ó
ÿ…¿»Ç³{OÚùÁù¬šÌ^Ï=œ‡?»Çóû+èà´”}Õ›ùêÅŒGšykç­óeeç«ãÙ³…/êEYØðwÙv}ÙwÍâi±l?@ûwÅ2\K¿xRt
t¨íbU,seß»ÅÃÂ5eUµô'¦¬LM3üþãtÐÃTÝbçúºpøÓÀCSt¾_<(–rûNÐÐÔÔgXá̲±ÉXÒà"0lñ…N‰ã’¹hO×\ÞÒ†÷¿økXGø†iû±öùêOÀicSNûº-«˜½Ú[`¬)jîØ¸´ãÒ[[¶Í|骲5}ÏŽ`ùÅ)^NðrP,k[ÁbÿÞÆË[¼ìÃ…·qŽ?ŸáÅà¥ÂËs¼|t÷vÂyÜâˆÇ]‚„Ouô:6¾ÒFYW=1á…6¾Œ=ÏÒÅ¥ñB÷cãQÚîŽãã„Ä“+‡KãñTc~1EÜgÒˆ¢¨ï•ÖWÖ
*²¾Déû-³ŽußqGbø…Šã"å¥Ã§Â»Ïᤋð#©|æÕe¿­î>JöeJmX%?' °„eš‰±S¨@UÙ4•^2æà¬/„Þæ¹ÎúþÜ
`âå"øç/)`	‹á÷ó¯4õ«)Ôœå°hjÔ10"òüi|þ6>ŽO´q#5[z÷(>þ:…ÖÆ'±qU¡	NàÿÄ’‰Íørh‹×SxûLLŶ6¾Ë毫ç
Õiì#jP‡Âí@… °);?pco2Œ–{WÐ= UubàŸ÷…\nqˆÁË>·õ´éz±ÓöxŽ,—[üV8K›žLÙ>„0o1<ÂǺŒ–: Ø;;^¬îÇÜ`ÛPWqš$QËäÂ3œó¢PPxìäkZ`Ë›«y#á<Ú÷\Ã0ä׃ÕìûÙë9„™
E¯„usgL[ún^[¤®Ã`øþÖìÞÖ£ùÅÙzvï§¹™Ýû/÷¿ûþl}5ÿÃìÁÖüûr.	”Ñ,ÂX¦tžƒå]ÞIM[Â-§{ÜL°1Û@°oË:'yˆå@Ä×äÒAàÿs„
ºÆ-¾Äxûa!#	’dú¾éûóŒû=FÈ8qaŠßÄø‘jc‰ºØÀÝfcã¡®£Ø·Y£L‹ÒtÂæú¶M ¼HGm[#{r+ó+k‹GÓa€LËøTp½uí@[«òþU¢î§ò€~áþJÈÚ¶•ÆÓ²‚kZ-&*-L¦z”ËA/°H¥ëN€355E—b,ø¿¹î ÌaƒJeѪ5¬Èh	ééAA–éÈçF®âÆ]° ¬°6ä}p`4üEöÚ¢‡F¢
"ûœ‰…Qè8ÕiYÊ7q4þE?Ðs‰ÉÖVLÃ’œ‹òOÚ_,È-+
{ÈQÞ<¬V	#ÃNh`Z±÷Câ({ÒÇ	À2Ùçº.Æ7–ÃÆlÛÀõþƒw Kï}GÛ¡Œõ0w”¡ÀÇ©µM¥vD³Ñ–˜rÁ¦›ƒ“nÊîýÙHw—)m¨ G\3¦7=›F+ý¾	µ•C­N	=ÛVQ?×™Ã	ÞˆÅP÷äÚF;€GáÔž”IÛUŠ­¹Lq-XVÔ… ¸¶aÓx3DQ'£ŸäåÕ`aHê{BXª·.3´¢	¬¾©¥$"Z¬—4¨´Irèà
’Æ·mÙ´}¦ò°áŽL)vn8éhmâöÇÔœ²x¦M~ªˆÒ‘ò +·¶Çœ^Ó{?-ÇcÛ¨LÚ.×Kèé÷󔢇 ˆöHMÙÒÛ–KLü½ÎUIÀï´ŽÐö>8b…—ISŽ}·ƒÍË`«(·É]jÛIl_ƒáޏô€‘!W‚)œóÉ][&cs²²Ý£˜a7Ç`îÕ§€‹[ê-ùÁÅT²ñ$vSÄ» ø0!J¼Éí}

pã:?E„§Ñå WŸã¦cd'ѱp×µœßŠ$HÂU1±­À^ƒ•õ-­Í{´¶ØÖà2¥ùOBbëÀ^7€^ÒÌè;à7ÿ#ÀµH]´\&IdNE8íâï֥ĭ1UÀcYY*Í›“ƒÚ|É9ôZIYAVí‘lNkâwpçF­¦ä}ȦL×\ëÉ[îfÚ*©„øU6C¢ݦØšH¨çÆØ1(@c›lô=‰Þ?=˜_Û¥\¼^j“8²IúkÓ›Am-Ee#…«-vÐ×vÌí(†ÊÂ'_9$><Ä6K¶-«*TŽÚ®0¢4´ºM¡Á0z1Aè¹vN¾ûzú
ëú‘Ú{f%ŒySU7Ž
]o4ÛŽ©X‰gLŸB8‚ªLŒ¾‡•ºý´=s’DwÏZ™p˜5’ec‡H¼º78——4×rß·ÅßhtÆvÉj°W“y'¹ÿü­¨¯6bÍìáˆ3Aªö¥Ön¿Þ°²äJÕɧL…#¦›G¾Š,
˜4ìvÕ €€™éê;ŠôUtèp¤+7Ú[ä¥ÑÞNŒ-œ§ÇòmÙmorº'Ñ‘r"J¸ R)9ª³¥"hœß$]?vLÃ-FÒ-’
g%ìQ9†K©Ûq*/!ßµ ßÏ.™39"Å•qº¢%šŠK—ãÕ™Jƒ5ÒŽjÐdÖü8a車
°Ër•¾[)•é†L˹™ÕaŠ{™è;å&œï,~*¼&¯äçé$¾ØèÕ,ãD²ïÍçðP,¦
´)cX1»V\]tTÊâòaÜ“d‰GŠ®FÖq~-‘êqÇŒ3Tð:Ÿ•ðdì¥ÄùÔ£Fpá~w>JàcìÂȽåž0ú#Õ· _k@> )­Öɫޭ¡[Ma«`áÖ“¿oª¨MÜ%Å~2^ͦ*¯×³©›Ë™ºì²çŸ…×âKï®^øH—Ú65p™‘b¸ò‹Ë
Ü@@SˆÅ=ikËcó¬·,Ì…"*"ñÜqz+\6.	Z±þ,ùÞ´=ò†íQ–»&Ï“Åg’u?óâ~c`;¨u0r‹%˜;‹wXt49Þ‚}QÔa0`fñ'"—¼àá{©‘
ã±uj(23u¢‚‹Ü	µ}
Ë5Ž©Ë„`à.wôÁ:í‚™é“x¼)#*.-­9yh•²_2« êÖªælÚHž±Qt<8£i3Fbô(±¥ó†Ö–:ÔUñìíÍ‚«À<)RÕdTat“];0ŠBžþˆôˆ·tõ
pä5zR5έ•–ƒqµ%åW0±½f½¹w›¶Î=%L®<5g‘’¼HÀ[tæØæ@îL/»Ï.+0u|`c$X”ûÒRÅ—·ûk}¥fíÓÂNù_íÈ9g'~Ö…z£C›ñìÙ> “i{|†“:rN8žŠº§žzÇSnç¯:4õLÞUñq¥Ï³Ã„ÏßÝp[/µöa*€…œ-ÝÇûß‚ž‚ä-d4ÑQÜ>%ÖÉcµðἫž?ãSeÉQÄxîî(ì}ÓaÐüÔåxÛùéÏ+N<DsÅ)ó3}ü&Ù
Ï…o>":yÔüMºCß·ƒ@ïýD£,ÑïNqa½aÎëàqWU_tBäFšô¶“¬Ùd—œ­¥áÏ…ýÙõuÌ*5ú—J◩ƈÑ+8—„]×-!÷´ånØb”Æ·WÀádŠÜhy¢Näd1‡SQ»à-$^8¿ô½;ÜÓ[95´ÙøýKxÌ\WeÑÅÎJ§.E¬ûÑÌÄ“ý"½áé֞ÙæNI‚Ò&‰½|5ÅÃdúí”dy¾iŒããów—Ë`7cw4†rÄy=µfžhŠ~‘GF©B½Üv¥Là)â^@ÀÈ¢úAM'£*ý„ͼÛŒe’Ç›ù®ê0]"3_t8ù ã_ü'êÓ—S¦ç(6Æï"Ì”:t›ùìy>·a>ÁËmæôÙœrTü÷Ì'2|ÂpὪ±WÐãë/IüüåãLC!ï¦Gü¸a„­2ŸŒøéÆ#žNø=5榢Ä,Q†h}j’Oö£&Jš„‰;
.¬O¥þ0ÞnŹV݃xû˜TË‹~13m%ö2§0²C—ø‡e˜þæf@Ãh’ƒK‘4vêŸP-K¨ŸƒÀ‘dzžŸ™JÇæKdrO¶<ýñÜø»k9Ê?ARgj+yá9ü^G=—|$—ûÑŠNGŽý[ô:{ö’ô6øëÔÐhßLÙš³)Ñ	Š©º«pX<U
Ï]ù!ˆ3ð}g¸!¶75•L§Ê¾â¢s+ßÏþ
F’¿°endstream
endobj
161 0 obj
3873
endobj
165 0 obj
<>
stream
xœÝ[[“·ÎóÆ?bžÂ´‹iZ·nuQy0bŒmXâŠí”³ì½Ìî»kÌ¿ÎEGR·föåJR³=jµZ:ç;ß¹HóvѵjÑÁ?þ»{²uïù°8<ßê‡[o·Þ\ðŸÝ“ŃíÐAéÐҎݨÛ[ô¤Zz1Ûvz±}²õÓR7þÿkûëð„QùZëÖôá¡í½Ðña³²Ë¯ÕŽ£·ãò‹F/¿kVz¹
íšU¼ñ¼Yݵ²KÆníÇpº§NF·]7ôËoáñ¿5&|S
î ‹ÒßðM£á«ï³«'ðÖg
<ï´
Ï®Œõíè‡pû¼”ÛØûË0þ8öaàëSøˆÃPÓ‹fåB—aÐ$‰Þä’X)ïÛÎ.V¦k5Ž$‘‹ðæå|ÃÇ~ø U¼†¯{ðq†í`rýò¯áÒÀâÌÒ„[ðeZ׃"žnmþÓò
<±gðq)ãÂ×ð6Õ™™
ÕÁ­û<’æsÁàA~‘ÑßÅÙ.w¤~ýE:cÛ+øÀµü¼”¥†IF!_H÷w©ñnÐgïB³^>ûOÒýgÒøEj|.ÿLi6Ûrõ Ý~*ðÊÑ#âNkS:“Æ÷©ñ<Üu# 1[ÑAêy,û©ñµ4î­3ï"õú.3aî7 A£\«m49™™ËŸ?(V—Öø|½'…6øF_i7´Þ/V<1€pv\‚ “Nøï5œ¦Æi<ÉW8UXç—‘ÆóÚ˜;µÆËšÄnäòþdѾí}§+=´JŒ÷,îó°8ä*Ð`Ëã¥;5¢	£@ŽØ\@¿—µÅ§9§ÆÃZÏýD0^zô¨ßw5iœ×à{f³Æ£â͸¨À jâýÝ|Ð9ü/Ü¥5Æ9}žîß[£@£=é%ñßëIy‘A8uchQH‚ºÃé¯!Àw%^HÿùtX7T˜”50©§×u_æ»Ï³ÄåX­:§ýÓùb;|#:#ÚžÝÉÇýøøõBöÉ”º¯ú“3ӻ‡§™ÈûeêùB¿JßJãóÔ¸ÝTXã
Lf&–,´dEòÊ®cf¬iURZçZòyatw³Ñ3ÛLKš;…ýÂàÖ}?¶vbY7Å™IW™wj+ÉD’¸ÿCUâã«@ô``›ÿ4§‚Èvݬ`4W2ê§ö
	ØÚ1/¡IÚÛù]›ÏÞ-}A6ÓÅ\ÓHhrSg ×;ƒÿ"ò{"ÏÖð\tžÿ—…ï0\ÀœCÛªA1k|`‡ï«ÄÐë0e¶C4»|Ü0#£©J¢µü&¦ßõAWÎÀif¯Ãì/i:¥ç,ÚPÂæ½Ç8H¢q:Â…Å" =·=®}7Œu–^òZO»KsKøwèø’Û·V¼ö&uï†nÿZÊäæN’ŸÖ(çqÁðÔRʸ“ž¸h’ýÀª•íqÊ`½Bê‡ò
ßyŒ7ÆR
™‡†|!oÅ;YîÙΨX´âõ•Ø{zB]7Z€äÆ*X~m‚fA[@±ï
ͽ‹zr9F@¡½E'âyC½I·±ûY¼! Ä&Ât”BO0Ñ‘¡Ž“baŒÃªÊ›L'0é=F	¦PnÙ‡ÿ«øªW0K@ÈÒxÃMïáêÐuPc
ùŠ×*ÙU_·2ƒZ Ki<•zW1‹¼=A	Gy\¦ÅwG<¼’1ãØ<áëi£Áœ©B^˜¾¡ÖΩFØkàRÍ¡	£dyìͦ®Ñcp¦°
ÌSø-¢¨zôàÆéfÛн–-0DŽÀ9ûXS°Â@:¦`z û ÑÜÛ® ºØ‡ý&Ž5ÇçQà*½ÆÊ
ÁŒë‰}£²Ƙ³ìšôÅzTst!…xbÐN­½ÊмVÅz´8ƒWqXÆ>7ЇeÂyU8ÕEäÅ}‰šh¹%5E%}
²îT½ÐIT”Ñå_(*«Yƒºœu¡"ûüFÓx	ªRl#ÿõá¿a¡ZVa?®qNaœ[‘"}lfM~/WšÎéÑFmz‚¥ƒžyýTð*>JħlÍq_¥E£ú£6¢¨¿§GE]¾Âmüt¢árÒ…¡……dÓILǘÁ•˜
~9²X5+Ò°rá{—)íDù8¼{ìêHïФ½Å§ÂWk±%c‡Ð¸!PAü‰Ÿk	\·@@B¹W*ƒ|0ÄE]‹WgîºClOJØq*qЛ"»#ÄS6Æx¶ñâÊç¢6„?èÝŒè¨[‡@}3˜‡@¼ÈÒ1UC ðaÓ˜Yâ¿a¤a*`ã#B Àð¹Òyø“OK™î³Ø Ï…_‡³è^	Æpyå44	•› ×öÊ^ˆ¢-ª#ºqÒÉ\Gpá˜ûEâyÐd¼¬à0ç”ÿXÞ‰+1¨HŸ“§
Uë(6ûcì“' JM2™h1!Ÿ×nùHü‚ó3˜Î£í­ï·Þ.«{Ü.³ö凮íý"D‘üÝ=ÙzðdëÞ“oï.÷·îý°P[÷¾‚ß=ž|¹øÓÖ£'‹ïo¸3­‚͇Œ‚UC›Ó3[¢Z;Y­œþ#&«•oûb²	ÊAw±RX¦˜5p±vqáñ!jj’¡j'1>‰;Mèn$3Uãî:ÑÁA	ìñ†.E;$›©·¸FÙ×FöŽýq¾`'¦ ØÐèXˆ±ñ¨à~”HÇ9cæAíLå;'É;5fáhÛðîÀ¼mCº¥©ZxÅ„pÒêÖBÕG¶!{wƒU˜;´N)3'¿RJØÙå—MÀ²ºÃ\CþÒ+Œ]tbFƒ²Ït#J—¯°šg¬tuáà[\¸|êÍ`(Ú†yRBg!“9Â¥B–ò{zÜÇ
¥zËï´Ô"§†Ô´M~0½ã7<ÝN£G1ˆà〩g‘¡t\tŠ¿ag†¤y±¹¡›£‰ATs@U&h‹¡¥Ýék…e“Ú¯FvëÉQ]}@U¯`!kün^mg”\·!þöt%	$+DÀG…òÁÞ²…&*Œ¼Šß)Áû+'Á´£3š¸‰]ÉÄ*Y>¤òQ.Sbœ“aå[ʶø¼hAtqwïZDe°Cƒ,©¿k(çÇ¿°êœûL°tƒ»Ö¹a
ãåpb»a\ÔHr—¼FÜ6àí2î7;Ëâ­çèTŸMPÌfÀãÀ!ʬa§ô¯1_`Ä¡DJÎ;æ*—QR;É“0W:¼ƸîÇßG²,¬Q5䦔9dØ»›*C5•sðŽ…
?”Û6câÅ5°I>gÒ=6¨ä²¡ÆtNàt¾«¢Ae&Ç$";¡¢,d‡jÉí]6“D îõÄ@›2Œúîu6?K·k_Ü0ãšúõÜ;Ú‚Ñì„ÕZ¤I%ÁMÚgþ×ÐA"O*ø¯ Í¤kƒ7Æâ!4wÇó³6ì/³ð×RÐYø,žž¢T—œ8Çj(:µ—±!רB¢( _ÄgQqM2Ša<;	 K6ô~Vþ¶\Ϩl”ñ­ŽFXqR) ÃnúŠsFP)’ÕqäˆÂ”Ë딋ø]ŸEN‡p‘A:3Ñxcƒß¢MÚ .Ùõ/ݘ…úÛhoŸ2aªïs ¥šŸÆu¥Û¹·áTÄMŠ,®²œLE\o&Òõì¡ÓÁÞØE)”áIV1t	v§1¢Œ·cÒ¿¹ è)Êã1%2Té’YßeÜo¹ßðÙ-s³àÃVÌN}Q½¢ó>äÄDû>dzµ"¬keŸ·‘¨´ùDb> !¥×À•€R.ÆÊ¨ˆI4)N}MžÂÕj?§Q:*ï:!þuò°CÙ…AR˜“}±1çþÇ¡­P8²¼r9
ØH™óò¸+#0g'.Û¬ Yœ¸Ä“]Ý€cÆ>Æ<6‡sáø„—¸®· åËHãâBl%ÂÖ¨ºvu†Ç§sÊùÝ$bãÃ~åë)ͤ¸z¬…6Ñî97ˆ™d?Î-ª²hblâ{. OQ8y/ØàÂc€kãly’N¹,ƉúqSŽZ*+Ûgò~8³í}LK9„%<VD"<˃ëSÐôTÎŒÅÛQ|bXtaObçè9@˜Åc0EÈè,½˜ò˜¥,Œöü¡.ÁçHâ©Töýnò:ô`©Ü¸}E/f°ìÍG$²lEÕ½¿$Íï·þ°½óendstream
endobj
166 0 obj
4456
endobj
170 0 obj
<>
stream
xœå\YoÇÎ3aä7,—Ã;š¾æH[¶bŲd‹´
A@‘4%X$e‰´¬üút]ÝÕ³=ËU #	«Ý™>«¿º«ùóªkͪƒüÿÉÅÁÇÃêüÕA·:?øùÀàËÿwr±úè(6p&>i§n2«£¨§Y
v58ßvvutqðýÚ7aÝ6vÝãÿ›aœÚiì×÷›]Þ¸õðå|à£»ÍÆÓ·£fã¬ÅÆ7nh»nè×6Sߌ.>6þܸb§oã$q0ÓNÓè§õ'ñ•³mgù>6òúëF5”¯›M_ׇ͆WYöüÇÑßãÖÕ[÷!.oŒ»?:;¶q§®	ÐpÃo6®k3MÔà:nûe³	ëãØòæyóüW¼>k<¼³“‰K÷Øô)´8‹ÏFƒÔ஑$Hƒ×±[­Ãú=hùkÜsEª™n\oâ0Ï#}à1Nxgæ±íd±ó/£'
Î]Íú*6Ä	ãéð7,´ëb;8ãy…ÇÒ¾cðž\gá÷úIc{ZúXjÑ1‘ÒFÏtÝ1í0´‰Ès¢À„Ðvyï.â;8±øwüŒpÏb›K"޵Оú^ú†Øm¬Ð/6áò✦¯øi?ö«‡×Ìžh£À•Ñàâ1=I3B;F‡´û	p_Z]D‘qmè߀0L6oÉ.Ñi"Iç¹±™yžf¬ÄW„ñÞiŒ}&þ?©Oàã
|\Ç<ÂoØ¡u°8îúKw}ÆË³FÓq2S†Ä+ÚH×ç	j€¹A$œA8Øú*þîÒÇ„r«À™ítº¦A€b
úIlx™ ‹t|Î'¹©Ž›R”p+Ö$k7¾@r†7ÀxT
Ÿù×QÝ9¯2
½ 86È”.€Ðô&àØ‘±"_·¶3rD_5,%Gd/£À´_ƒ±³Ý‹Ü3>»!l†i¤‘_7†c†$ìéDuÀyTS:Wg3õ´8ƒgl¦¥Ú?åf&ELçHBBOèÒÌ“ry¯ä3Pgôo/à@Ø£€S›ðyç°# ;æ-ǯY'1áwˆø]r2jT ³™ÚÈöŽÞÿ~ýMãE*¢‡ÕˆdCÉÑ“E _ψ ÀùÀÙŒ•{èŠd[Cûi^·6³úÓO8wÓå9Þ£¹jÜH›†#ÒMËaY¤Ì’蘡™3Ø€suÁ–‰ôh§ÒÄÂààRDò_ˆý|!öH¶^ß@4À>®À‚£A´yÖÑÅ&w#bY+(‚(€{ÇÒpü¹aÉHÆ%C›¢ô¦‰/?€vìa'˜]¡T}…•?}ª6{B‹ÓõÉz;Ý;럕	ÌÚ~P¿½HQv¬í\#Na@9£ý
u²q˯ɲÍϲU®,r
žHƒã,YóW…D‹¶÷%¸EJÙ–´3+sDß,(dÌ8ûÜd}à,o×õt樸áÑŠrbÓˆ¸ö^(¡PÀëó|¢"ìŒ$°pÌf'tL&(+‡‘í[±ANE¸ †nÄC"ŸX‘~b;§UÏŽŸDÛÔ†$Û”Q¬D gÀfjާ3À.˜wÊ^†GlSk‰@z£=%þÆd
Y†Tbó¦†i¢.žÑ.
Nžø‚Ö-…R£”rå	á!+yËJµ‚O<¹äþdaU•x'p5E,*X¼Suno[/s?»<ýÞœ>»<×"gîGX¦>ö£©é̽œLyWŠ>ßùv˜›u…ügæ~Ÿi_¦ýÌœÌÞ 5'r¢·
ÈÌÀ:½~}fWA|š}»÷Ô1:?&AyU8Ñi@‰¾$½<3õ\Ã9’°»þÌ¥‹vôirl:T ®3yE§4A×Mj±YTºìÒZ)çCYiO³¦$v39O”ë“ÄÞKwËTÕ0ƒê›ƒQ´ûwA—Ýl—Gâv±^À§„ÜŠ[ñP¬‡Ô/žŠé<`íî,~ª
ý&=|æQ^懧°37,Á;¤ûÝÄ	BhgPo¬ÇÔÐÜBèߊŽÂ#÷Òûûy¤£ôðG2¤¯¶rœžj7B‘]rRÌKÝ]xÿýüþ7;™¯ÓÉ`“¯¸
h¹+>¸íxþ¯ù€h5@¬t{yå7ÅÑâÎF
~楫…¯ÞZR^毤GÝèÀÞe=ºxânWÚ/ï’;‰ž¢¬ÀŽjRÑýÐ9õª¦ÁŠxA턯e(WbϽïÛtì{`…·vA‡üMòIÝBáãoq	Ýн$ÿ/‚ãnzw/r?=<ÊkúàQÇY
là‹dⱆèÓ†²…èÏcñ©ºt¡ƒqCÉá"ׄ«Ìakɦ›É¤3P¤ºDŠvRñ DmÐ}èºcªÁž\¤í8.$3ÕŠ[‘‚‘“}'µ¤Þ©;œ„I’Ä7¦
ƒ7XÒÕcÜ´îãP&Šú«5ºÖÚ±‹¢û¢éZÓO.ÊÚ0·ó¦G»u&ÂùÛ	¬e\ÔC0ÛFÛX¸k}ˆ›âÎâ@s”/ê¼F¾±¥ïÁ6‹´1ã8©º¸üˆ^ÊhGIu®X…W\ßÝ8jüßôÔ—]]úM\6Õm„1¹â2z3a?‚?´ìºÖYÓ;Y³-þ¼ãš˜ŽˆHJ±Ì#Ù€ ˜ýžun«jݶËܬ‘¬zYáfû<Î3fZIÜ¥ÒïS\!iªJFéCâ%º|Ö?'§0wÕÔ‘…GøCCW< w½>¤¨†Ã3”’гC*6±X}ÌÞoÝ2¸¨fÈ•<ŽN‰©Þ
uS½US½¼[¤%”82…ÕåBݯtéÍÞÆÕ`t54ÝhcÜz1öŠ»È<ý–µ¨£ëXÍúv’rÌådÅÍMÉz‰XêŸ]’m®úÒò>¥¤hé¶ÒÜÖ+ŽfÆáÌ·N&ãŠ6¾÷E‹WO´Ñ-ãNDîÁRÜ‡ÑøbgØ.NqÿŽ’¥H^·
[†é¾*•S.ßÀ‰MÊËC®k+SIpB!šßü(6›Ë~Úi¢¡}ŒÏWÂç3•¯8¿…UŸ1¤|Á⬢œ§äÒîˆWí0
Ý@·8f×Á¶<
¹âõNìFR[~È/À^UÙIGOswöIV4ºž¯Mv	3¹Y(4LqU‡ã¬ÌSÙ‘ê^AHÖÐy“LØÄÐl°E@±ÄÐÞɱU*ñT"ÁˆX-ý±¾ßô;& «çý¬²÷׆ªT§%rõnôóÕ\¹ÍÝS-^ꄉ#Ò
H¶’Y0¿±Äœ
T*–+°Þ¦Ã\Îk¨nÑKùuq[þLæ·ÿœ[ƒ±ÉÆ>¬°Kp¹#ï‘d{úR
Ì¢ Ð¨Äûé4ª6¤âYˆZ·è*Ö‘äéÀVÀðŠ/Îï+©tÝRP~v¿颕Õ[{†,ˆ¥¨A¹fÞY¬[ùmålÕhGbo‘
ézO*³çk‡ŽÜÉÊݧz2ãséOœfvé6\ިܾ™(€v )ðÈS$+p«?Mr™ÃÀ‰™gõÝ­\y‚/p¿3O•¨ØÎ3«Z.~±[©@$Ì…†³Œåëxjaå½-·æiÞ6“M¬ZšcÈiŽý‡”°~ÒYŽÜéyÊäÌÇeîs.ë¨g–îÒc,À„mÿLÅxu”dÛ}TÀÓLY¦!BºrÁy·sém7,ÞˆÎÁS刑e·Dy(oèÏ@€³#’+®BàhiͲ|4M)•cvcçš.b—–y)rgÖ…Âi¬}pKb–"KfoW×rî@ÓœYHXÞd%m 
‰ûX•¥û+¡<”¤ëçÌHÙ.ÂÏ$µDÖ>jØ]E7öÃä{•Õ	¾›*ñÁ{'_¸jò‡X DÀP6‚|…L8dY]Nÿ.™)ñH)[]ÄÁ(vL0ú.@ÎQãÍrÆU¨K,cˆ9¼—V
ÅÏc_eRߨ·Æ‘¸¦3‡ü˃Î9!³endstream
endobj
171 0 obj
4920
endobj
175 0 obj
<>
stream
xœ½\Y“·‘Þç1D¿¹Û«)ÎBņL™Zsƒ’,r$oØÚˆå%ÒaÎ"9’µ¿~‘¨Bu)“¡§»
G"‘ÈãËDÿ¸³á?þûäòìöƒi÷üíÙ¸{~öã™Á—;þóärwç"706?æq6»‹Ψ§ÙMv79?Œvwqyö·½=„½?„ÿ¹ø¯ÜÃÝÃZ;¸˜;]<Í
??œûýŸf˜çäçývÿçùÝ_Àó»‡syñàpîì8ŒÆÃ¸û!¿±vÎ/¡ymäì0ŽSÜ
Ýÿóàò7c óMŒM8×_STŸîÁ¬_ °&÷=w>
sšòGiómy­ÿ˜ÇŸç˜i¸_ïÃ?2=zx8¹É4YâDË»sfʇÉÌ3qäÝÁí_ÎãþÙÁï2ìþQ^ò›±••ø,Œ°áSž#‡Bbð55|m²î÷ù£ñã÷ûÒà‹,‘õlñËúð¡àq’"òþ¥¦I>+¿?T"W	¸S<¬½>/ÿPÞ/ïÖ‘þ=´£寵ÃÝòðA}øµ<ìp†ä愜å„g&OmÀóJ$¢=Ͱ)°ùÑa2dôµ]­ëÈ;ÈßÊ>PDká{¥ÉB®€À….0—X$¡h§rNg¢ˆdâ}îÄkÑôpð
kq=ZøzzåÑ·…ùŸ]–˜F½uYf‹o±ôRë*°Þ»gßœý¸Ëf9¢s›Ï~ÚÙ)»U>íBn³¯|çÞÙí{_îÞ½¹~vvû/;svûOðÏ?žÿÜûãîßÎîÞÛ}óž~´ð0Á<ƒKäL/” ½MkÊÇO@k–¿ õñBk·ç6³1~üÀýp1ûméã¯ÑÅ8$ÿëöÃ¥ñ“ÈŽK~°Z;<íì	ê2} «ÑÚɪNÞÂ&‚g´:yÚo)Ví‰ÖF¤Â³·l«
³€a„Àó“ÑŠóÅz*2“Æ"7Z­õ¿yð_PUeýîµJEÂD‰Qû-¸UÐp½s{WÃeýD%‰*ʆš"ŸKò¡)š±ÓeÞ<®†”ÓHÔœð|šèÅ}up‰(ËA­döê
ÁÀ
b”µÝ5›F²±¹LÉkáÇ3dBíà½XÐKíº«ˆMä€
Ý>ƒ4±
oíVφ¶¶’ý5‰qí–p ³òP=‰Yz…­¹´4ƒ’ïú>{eh„àïg¯Í®±Ü­(2Å1ˆ×2S¢W"ߣ¸Ã9ü
x.F<¤ºI.b4½-by”`Ô°-•`—ÂíN¤ÝˆØp,„bÐ
%"‹9g=—Ï©õ°üL£
ÕÏÐ+g	zIA@V´ˆÑn¸s5…HCr'B\´Û6\Ía06sž<ô‹F=$öÂþÜZDÒ¤çýóÏÍ<°NûËÁWøtä<D¡jØs}ˆ±•ñʧB_ª_õ®r–;’+×t|š[8åδÞo˜¾•,˜¦Î^·Vé‰_`®qQ;J`f3c“9¢7Îp&iEΣU¾1ÿQ–Ü(r$Aú±Ð
Ž‚ÝZ®Rí÷_8gDJý)!…U‚vq#–•¼„Öü‰»\\îrŒ¹Z'Z³Òé[§G:ø“³P¹(b¦“Œë
ä­'߬…Ù“žîˆã5Úð¸ŒÝÐ1±e3’Ës$À3Cc4jSö¨b‰»vóÎA!%ÙÇbR#Õ˜‰	Ë/î”ýmðÄ´-BM?kKÄBŽ6jNý"æl
Þ PØô¹,±µO
 "œgl½â»À:b†Ðšè°ÿCö:oŽÉ’kA¼b¨•
	xo‚_î
A)«ðŪìTœ³MA“VE³œö‘\'ô5²t†%ܪ¡Ñ§'X@
l¼ígÊ1Ú÷ÙòBñ±¢}Æ!¿ñùh'[€	+qÖ6}Ñã!üèôòÎ;Q‹œàqj­
ô÷Gê\ü$ë³Y‹ø%ûß§B|JCbjH½,$jµÅy×¼dß:ý’W-öïV	ßðHE4‚¢êa¼ï	cø	}ž˜HœŠôU´,¦DËáW[Lô¹ÉAKLØ_;§ì¢‘²‡ðlypZ#Æ1¯	a0i#ô?,H5¥Ù7rú`pº.¹	§PCþ'QBXS\›ó³aËîȟ‡41áx™÷Êcºj¶»'[-@ÅAþM;Êïmæu*žD‹oœ*›:ý"?+àæÅóܪѮÇÄ	a®ÁÖ€~Lé&0@[ kìYpÆi;µ§…l]y9a‰¢Âøæî¸Øvv«¤×Ñ’zŒéTøÈ9hÒs([Ù™¯8f!E”5a&Ñ`ܶF
½ÍB4[3'¼KʈŠêôD-Üêåú®d7ÒÊMúîA ªÍqìª	‰Y­~SV\(<›«ò–â¶
ê'Ú+g	fˆº”åpà¡ÂèsTV2sy¤vÅÌ8ñï©àëVðßšïÖWõaS'S·
YÒô«YÎ?¸ü¤æö¯®‡QéßUQKÝ€qômE‹·dtþEU-3ß7©jÁ¼• ¯lñÆ¢ºae¢£m“–<×ÉÊiÈgÛ#®·ò;ÔÚ¬+[òz}RFŽhJ7Ò›ëoôìÛ‰zoÉ@þ«Zh­öxXL§¼ 8w§‚2*ÙOZîx}C1­ëj”Þ|<ŒCɘ6h@ñáÞIàã®ý ‘tD*F4ÛÚGãzËÙ¡†HSPÅ’äåù‹û`cì&Â¥•´½è%Ê®¸)×f½·`:¬×p›fëH=È4 dÛ躸LÈ‘•Ç)æ@PRôSH%²Áh :Ö=ŠÍÛÊÓ¢jÐÔz[,÷·X0äñ,èÕnÅÝÅý³‹ßýmïfKä¶C0ÆÍû”©3v"¹p¹Ÿõ3™úøºùåcA‘¡Þ`“M9â12ì”yrÌæ¶­›rü'XOާ³…w)ë¹Ì
3Gþ0!¤íRŽ^ƒªL&Pæ©ØaŠf†ì`ž?M.¢ÂªlTî3zr&7¤9ì¿;d'(e—L¿•×u–:ô[ ÑY]虬¼qš'ánSdÁÍ ú¡nûaµE¸“·³$ᇻüó³Ávû)·XïN~”Á.ëÖ´Ú
Ыx“µy»Q¸6<«–¾;³3ßÀzƾV¹™ªEE²jyŠÁB?V'M™×Ff™ñ¢ZPq4	R>®|oTCêôVS"@âKò‰áˆÝ4bÊÔ
­®ÝÙ…›­+éÅÍíbáM‘x½(ŒXÑ©Ö-Ò¦l2¿½®â÷îò	çÓþGÐQ×ÕÔq\“åÝeT}Bø#|u¨qºÚ¶sµ,åQíÂâçÆŽä9ëÑ\öùádÕê<@+ìÔÂCWrbÄ)qzÉÙ”Y-B‹ü?U­ƒƒJ´.ÃR`¨>çMySA'e· §‘(µ†Êhb_•Tt;­¸Ä¡dÿFÉ‹náï0ÀQÿJĉbî´rˆ~ùCa±ª²èÕ“€DyeWÁ_wfá¢ÿÈžKàzu#³(±¨p”—ù¥…Ð
–?qƤw›D-ñ}ÝgƒFk¾-ò»ðÔqÃË©oÑé*7®ÅE¥zb—²z×©àž¾“ìq´¹3»‚µG•¯ÃHÅ6dÆ•p­F+Ù›*Ö®ÓN—¸²öˆGÈUxÈÖ·ÇùÊWâ;X_ã>¶°3K^cHEÃEß/iŠcõÑuR ö›”–Gºžr²¼<’çÚOò|rL¸jû&’ÈEàïˆ+.&ŒÒ|q("&÷s98UMB´´ˆün 0Ù+l¼üÇôÌ¡	èçÆEïšu7LøžÒÇ)=Xå:¡WÒE#EqRÿ‘jý‡22?"ÔÕËm¢‰ý0°zUë©î a1É*ôÄò‘~2C$O™	À—›ÕT½•3¦Ô¶NGÊW|Å‘mkÿck¸¥b3&mWëµ"òß`Àêx@®œ
®yëàÙšöíMÎM<ª¿b1ùŠ“Xq›¶eAÔ)7MôòJƒ=ž¡»	¾w¹¡ñ‚ÆÊp‰d®5ÎNé¬\žcWÞ
‚6Õ!ÞØpÏðß’¡naÈÐEÉ*%*SåN‘›’.úRP&„Œõ‚‘h¥YY¾†ÀãyW%úÛhŸñ„2`Ú¬	€ÊtðÛ>X™5ÂòŽ`ÐÇðâIG}µqFO+ÍKµ$8A[•ÀÕA×)õ”ìDUŒÇë è´ppSÐõÖRÉ[ªÄZ0–:¨<ÚH$ÒzCe$[ÝC¤´5qQˆ7yt]Øð7w®ó/"¦ª@2°t‘J¦,ÄúMÍ””ÞL‚µ9U³µ(iÄR§¢^„.;I4÷ã"5e=S'ó·H1´…`ßVÞ±q—xm­Dݬð$eójÓÎLY>b5Á`íh`žrÝéd±rÛ®A1©}|Z
œîÔ*ÕM%oiJù¡[\F:QçÃu4}
qâi>œÝ)…OÂî|öSKj-.¨Î
J²ƒƒîKM‡HÞP¡v=d	町PûõÚÁ‘TéÈe#;¦Þ•Mtmf¢Oç~9^¤èHµŠ€Qà}+5º÷à"|wÈçõ
姤ô!T%Xm€ƒd1’R;±2¤=`]õXRpǯ½l|Ñì	âD‘÷2¿ëçÞÅtBÏÃh·BAÀ‚-˜*¸Àü‹Ÿ2[•\=îç€ÈK¹®¤úÚ;[,WÄ6+äW}ô)ê˜zË7›cg’ö(ËѺ^EKJ¯i5åã"dòÍÙÿš¿üendstream
endobj
176 0 obj
5241
endobj
180 0 obj
<>
stream
xœí\[sGæYäGœâÎRÖfç²7xJHC	ð€)%[±%Y¶còNÏî¬tÅ•Šu´gv¦§§¯_÷èõ®kÝ®ƒÿøçÙ«£ÿ0î.Þu»‹£×G¿Üñ³W»OÒ€àÒ“vîf·;y~DoºÝèwcˆmçw'¯Žþ²M¿o¿Ÿñçñ8Íí<
ûO›c¿ÿCsìÒ?Á¥G½ßÿ¾9Žð,¤ë÷_5ÇÃþ¤™B;ÏÁí?jæ.ýšÆü1Í÷ŒöjœÃ×Ó×~ÿÌúÇ&=˜§8Ã"ò‡÷0Q(—^ùçÁ/pî_Û·’yöv"Kóè4‡ý燴C³ø@ÿ|Ô$":ç§ý¯šÐvs¸L„ÏC±a7ãàý/Ò00ûߦ‘é›ažÿzò›Äç-ÿc?¶Ý”Žàä<±Ý'v÷MO§‹mˆƒ‡qÇ<ð8tíèæ™ÆÇ´í~Œ.Âaµ½saNGvìœÛ!&"Ó^Ü4öû[ØV×wSññZ_OÃÔ·ŸOËúÄ·iÒ.úyÚŸ¦O¡KgÁÏÂöïòÀ7éõqH„éh§±ÒX~'úýK¢mòòŠK´=KÇÁ¥¹åeïó+Wyà9|=µcÍÚ/ìDéûÐ}ÏûgÞcœgùØ'ÊÊÝŽc›XšN>Î0ø´8QÔy¤¨kCârˆüÙ»!í]É»À©ú‰VŸUiÖ¯2MÌ8g˜pÂ×éÑ×0ã”$̇šD„$Ÿüô/(èÏš˜æÀSë‘ûoÓ‚óˆÂsxô¡º¥…‘7Ò5;TZÅý/ÓAÏP]@dA<»‰þžxê‹]§™ßÁ4oEÞ/<”	‚K§Üu#
‡g:߃Çðk:ª+Ü)ÁðëÜ!±ð¾¯kÞÒ—@Ç›¬ˆ:5¼_®”ÌRòMÓØï |yGô“C—˜?8Ñ3ÞâóÇ÷ŸÈ®68°<‰Pç!jH–hîgxŒë½¡cIôâá“1yAlFÙB&$yd2cAe„gæ‘ÏáWX¡¿gJ˜…iðy(lûXö}ìBú	Ö¶ŒQ©‚¯ÒdrŒr.ÁG<	a–‹6•"ÖÑ3 U6B…’rÆÓÁû×|ò<ÇYc¥×ï)žðXFÔ{–`nÒ0¶züJ‚Èì}BH¢³võbS`pN9×±b?}òƒÁ‹Y`¨YÚ2 +Ђð(Ÿ,ž^"‘ÝÐó,Ê<'‹N8F·“ì[^Àçy=NS$y¸Q¹…¡óÜ;X;Œä ¾Qq†wÎóyq`¸w¨VHÖ5‰ˆªQƘ)(bý<ožÜ
Çÿ	®Vz
O.ùÄiïÉ…‹†EfˆQËš1ÛÐOxûFÎɽ0âÍBðJϨÜC£6`P"âyÓºzŽlÿ²mJC"Z·K:1ÒÙñ c³ƒ$\'zx3°6ü¯œþAÑKÖeŠ"z,ÊjÎKÔ+—Kûb¬W;5ùQ–ƒ´Dtƒ©ÕÙÔ-Û¯ç™Á×FÏ“NéU~yRÀXÌqO‚E[.mðưë\ä¢Á´Z"ÝÓ›¶|tWH~@ºP¸ÖxòÃC°~ا
@ WP¹¾„ùÓ"½'7õdŸ>â	®ÞÂ?otá¿Á¯ï™2;§oo
•Ç éŸk}v›Ùy®aiyšÍÏM~ø¶ö~˜Øÿiq¬ÇFøáyñR
Áí¬ß¿©­tZ{ø.?ÌLyÒÀ¤3þ¤GdaÛaê*ËòîJ'yËÇaÿ£´;Œ&ŒÐéÛ3i3öáY&ñ¬F÷m—Ï,¯`/ïõÁ‹<êR¾,^޾¯M}i·¸~x•^ðLÓ‘e"ùþ[}øÞ*å¢Õê§å¯óAí®OQQ{×»c?Òa]+ÏÁ8ᡊ*¥´Äiòò}¨½qžâ¿ nFæÿG£ÊgU	Jî2Eo”g§òIWÄo“´¢—ÂÅVЧæîÿŠ÷¿¬xËÔ‘–šÎ &ì5æâ!ä„.m²õE¼ksË£´"ó)ß™;,·ôs÷€|.I&P°áèeåÍè=rº`"bÄx €Gß4Ás( ‘8’–îqè2É økh{ïl&iŠŸ=’´JÌ,!Y’:ŠàèÞh×cðÇÑQŽÜj±7‡2 ~9ƒ4ÁSfþ0K6pš£¢ý˜ç7ÃfɈ¥•ÐTô²'â¢sìmzXÄg’•
“Ú¨$=ž»JE—‘Rý"1Àõ&™zÚL@ƒØCÆš…Â	€‰#®f«)b¯›?æ#YÀlhŽ4	”íõ}ådº'´åƒd1:rɰ…oÝ 2wÍ ,nBOªR‰á_ÔÒº[¤£»K¶tuÃfxß“àÂè,§yð»b>°#nˆ·M¡·M2m,
™Òžä@ªc’mB²Šõ±nºVQ‹”:ˆƒÜ,$³6
;2èû|‚ØÈRÍ{Ñ;ôÙìÆ(’]XÊ*áÜBDOS·Šˆÿbˆ0· 5VYucÖ–§šˆªší‘òb«Ÿ¬±¦$äo|v7º1œ‰Ù‘ó3µãáCFýÞíе‹ÑÉéž1û&lWØÌÔ¥óXc=‚NöfÃk*›¡
¢Žˆf2»n
­Ù¶ÒÏ*W*÷V-Ø{5$¾(r>Õ%ø
©~…ö¨Bª2°#%H¤_C"Ч03K_– ˜àñ5öšBVׯÀC›è(0€Í—rõÞ%m(¸)Ca{²²C#ŸÑTb.RÄ-G þN4Z‘,Öü˜"••4Å.0N¡Äæz‡[Œ÷»ÊS„"Ý,àñ?«2‰ìM–‘lýó|UmØ9’áÚ•
¸‘¹Q† «²E!IÑGFY68´n@­-pJß0*¤‡.¡‘ÎÅ¢‹ÿ‡\œ‰Q
	1,‰iõÈ‘.-gtˆ#ó¾Ó#V!+xä0v[袗ðTbÙ¸§fì!¶×˜†igò¨ÿ1K&ïAíô:¥xì‘oÜ7Ñ‚aÑã‹KØ’+`
HU:Âe¡=œus~¨$E£«‡&lßà»ñŽà'°µŒUÌl#J?v¨èáP€¨v1“h¤1_VåÊ~€<ß4PLC	9eaó‰£"mȃÁÄ„KêÁƒ[Àý·º‘ Ì[9UÐhør‚Â=Ì<‚w¶6ÿËF$RöÎ¥z	ŠÒ|šÄ"bÁQL\i3-I ¥ñ2B$i)Ùùü5Ÿ‚ßh÷…ÔêPI&¼Ø Ô+¬ˆèq«Á›¼¥ˆÅΖ 8K:—µg?-Ë_¸Ü:–…ÅÁÎ'Ê$zsWwR‚´IbÚÁÊ—¼¹ðèùT.ˆˆã–!¸Ñ$6e4´(ÐAª=tèï­Èå)mPø!d[¦õešdTÎVΖ‘mŽ…YRIšŠGC|Äñ0!ñë܆Ûº(õãÒ{‘౿§ªP´˜R‡ °‡µ9Q¥×±|ÉÈlWýŒÓ6ɺÁDÆOÅšq¸59#PÄ	žxÖ¡G+{%®]†ð³¥¨‰–q\xDÏ	Ç2,åÁ$Ìþ~ªFV|ÓŒå4püPOî!EL̺³C¡,ü:3µe’Њ`kiò=>R’ø» (bË÷œ°îü]Tsé³cöêkæŇR
"vd¨‚öФ¡tgløí2š&¹
™žzïpeä,™®S¤ñ>ùä¶P…SljD…GAÅéÃ[XÁׯÇVäÄLW‘}6VZ¶j¤jà%‰X>LÁ™üˆ#„7ºN!fËm\çQžMÂŽiu1½Àþ”ޝì;Lýw›HiC¬6·<8¿³
C¿BÔ²ë.|½6Å
YÌ‹EãQ"wé—¬G*ýäÈjQý·‚-u[…D–WÙ„	Î$r^㡊¿« ·CC´ÜÞ‚›o*À·FtF˜½öù=
»¦›5QP£²ê6*ƒDë)¨:)3c™ž¾¤Ö ÀÉ¡ç¨ðš´ï€PVHvJmRÜ«ÆSYC¡I#~Æ»ÕSdVöî9zF¯K¾_ÌJ l SyXhO«Ì‘ù49»Ì°8Uê½"‰c¦T ›®s?pN«^<jô÷¦§‚#~¼aK‹ªžì»Ä ’ˆ„¡§Î.Å+jZøJ?rÁñŠ'pö½©ÕÍ]Ip@ÊM+YÚY,Õ¯
uuŽu˲ÛB¾½T°Z*‰Æw´Æ“=ÛÛ®ÕÞNé.ý,$V µ¤Ðu 7¨¾R7lÂK‘>VÂ\YIïf…±Ó•£¾Ø*$aÉ	J¤?T³
óŠœ(Í+K‚`²*6,2Ái¿s7ªëµ8Lä>a£cpØè(=Ž(c(Ã=l¸ÚµµÎ\È][‘Z‹7û˜qCM[¼ÛÊ[¦.:|×……‰+	
èHöácá!sŽ‹:[Ù%jú뙂íkœ¢fBÜüüï÷žž³8ÌP9“8µ´›Ì€M‘Òí¦KïICb¤¶þl…ð^5~Fc¶H$qâ¼Ì'.ºã1eË9TŠ˜^(ûb¤++jû¥€eLPA¯´öܸ‡–è‹Ôe|
=^3¥¬ã²þC@	*,£`fµL–ôÞ€HIÙ¢n-4¥¨±‡ø~^ÄÑSš].ãaŠVˆR¢BQmò«>yÚliœ‚»|‹h~±È°4EëŒ,†µ±h›JÃÔÛI’†FGEЪô‹»yŇ²P÷cÒÌœ]v1K?=9úòèõ.ÉË€WÌÒyM»d4B§s„Ÿg¯Ž>~|ôáãÏwooß=;úðÏ;wôá¯áŸ¿øEúñø“ÝŽ>}¼ûró6[Ù%·Ù 
7¤U 
¤mªX³f«_ˆA•æ¤Õxóêû¦9‚® ú~C(Ã\ôTKy‹´â0½ÁÑâE¬ž°Õ¸¯.úˆô—:d+î¹Â«÷ΘՇHÙeeYHYD¶rŸ¾Ëóæ\íŽÀ²R†8Í”úÂÐh0c\Æ@ž¢÷b¾Í©~	=èíÖ$‚!»Ö¯aímÝê!§Kr
iÉô=êÖí…°LýB¹¤ïe›ÈÉõ@Ü÷NäÂXYÊX
‹×ºàÊI‘^ÐSö'A
1Íöu/„û5˜¤|£:ºíQ×#ØùudTÈ'kœtÑQU»VîGR“{žbnF®ÝDuú¬ƒ;©¬î‡ÂÒÛ|%õßîæq¯7'Ÿ6zÏô¥~›¯Ã˱ë‡/·½OÁˆùÞ\%Í×6óMHÿñz©‡VÙØº)ƒPäFóénÐmü-ÝàÞ;½½<Ó÷\¯xÒ0î?n°¦×WyoN®·*¤ñ6óBýŒ-´íž·FM%;`?ùbmq›Vî«Þ}»ô¾ô>ƒôÉÜ›YÉ•P5¹3¥ºÜh‡iï
&5©ŽyúNjA­4™¾öe<·–Zr¼b/‘ÚÛ©Ú·ªE9ÓpqÎe¥™Ë¯ëµKQ£^Ú^Nw¾ò §2¯v¥H
ZÔZt9î”ÜHp²‰š,ÎÛ%Eû ‚Ë¿,Ó/:>ôL’DNFì§z÷\Z–§Km téHýG› %{n¹ACnïenêð^5q.™#/s¸—F–ÐrŽMw‚ˉ•"µËà7D<8vNÄ}k¨#\ö„5ìZÈÁí?—5ÐJt~-5(ÔŠ÷E2pJ)ýhš$p¯|ÿµŽæ/Sáÿ±·ÜfßÄL•ÅE=ãŸ^QŸúœ3hàtéÛ/ÊìíÉ^?nÉä“F‡@w&¶­fÌ…“ùQ;"4l”¿ž‚Auq¸|üiæ5Ì?ÇܸèÈ>
stream
xœ½\Y“ÇqöóZáß°oœ¶1Í®£¯pø¤(Ñ©UèAt„]PàXIø×»òªÊ¬®ž¥¸»3Ýuf~™ùeVýx9ôîr€ÿøçõË‹O¿›/Ÿ¾½.Ÿ^üxáðËKþqýòòó«ô€óé“~Vwyõýé.g9‡ØþòêåÅß¾S7þÏÕ¥7‚Óoxïû0¥—®nÒƒ_tÇxøªsýº.q=|Öùߺ£?\Áç_vGùâ»îüÐ.bj»Oßx¿¦/áñòPðý0ÌÓáxý?»þr^àçìáëÎßˤ~{½þwïÞ¥w!.ýºÌéWyæ/ùk|ú÷©ýuÒ¾„?ÿÿ“fè£?wÇ1=2ÏžV®ݑ—â†~vëJ+ò®‡gÝq:êÌŸïáÙWð?l^Ú°¸KÀÏÓ¯ÞcG©Çà«ùR# GÙ‡Çмüš¦iÀŸ¯:óá~šJ]àOœlóƒôöêqo~†}~&Í^Ã’¬«[ÓG°à>=Ã*²†3ÆÆn»0Óƒ?ÁÚÁ»z¥pÚ«K«rÄ…ü!Í›¥Ö&­$Œ3Â
Ê缎qÄ-Ç?€?áIXˆô+íæSYð'¹h³´T>‡ö¦9ýè
xîU*Y!zf|”)]èÇ	ÔfžÆ‘÷9Œ$ZÎ@ÔGÍc?Ü®Rp aa
øÚ‹Žö¥á)Û	ÓZz˜±µg²¤Ð,Èç˜zü—û&oHÑ·0Zý,ØÏ\Ú€-ƒgau]ÀÖWRýÛ΋úÞA¤9ЬGBDbYz”ŽŠ“DÅ~‰N$Jt˜<
¤«U§Oiìzco²Ò|B¯®«7ºšò`6Ü(Æä'@ÅÑ8l€ Û¡JúfàÒÒ0H%–yLËáHÔ?uçêÎtžÅŽÖÅn\—
ÊH¼ÓœÜ±™DÃãàP
XwƒÜ0åQ%ŒxTÔ'µè°Å×ÒA<ö¼üFâ'XÚíi£^j•ÆÉ§·@Ò—	e
wìVÜbâë¼~‚¿£/€úºd‘Ülj˜|‹ò!˜[Tl‹Çm%Iý²ˆ âXý,š‚2Öq2ÍZ!Ê\ÓFÃ\W—YôVu¦zŸg§0šœ¿UZ`÷¼ACê|
-¬ËC‹ê•gÚðÃå·"ç,q8‹s°j¿¢ƒte”Ê톱ŒIV
zH:C2’™Q2”í¦š?¼$À/µà±`J$`Ì'›ÜdûÚ“V¹µOóúãÅÕ¿þü
P	çжôNMÚÁÂ(ÞË·žf,:åIcþ·óv°€CnÎ♜£ŽÇ†H›OÿN/oZ‚b“¹íàÀtÄJxàùCY×¼¢Œã2Ün,k
Ñïú‰žñ~‚Òr/juZCE[~)äÈ›gô6ùCíj~MËö¼žà²¨O€k x‹Ó%Ë ÝUÑXmt5x‰Šiò‰³Û@@h	­¤@&ÏÙ\_vÉöŽhð\úT岋a[&6lÇIã§Ù7Á„iAIYMëò&ºÖeW!øß÷Ù6Àïô;?ϋޘ%å‰a0ò` ògxø!ãîÒ/Cö¾·ÇâB¼ÀiäC^ª²eÖW|i]Êò%¹²._pËb’;(½zê•,ສìç9õuÍ­?IÓµ8»Uñ!d?ÈÏVg¦ìà¸E |`@{áǂՂà¨(µYˆž`h=›R-ì/ââ¿ìî
m	6šÞ<Ø<Â
<·Ýgšm÷u§ðŽ,6Œ9€,8oPpr°•
ö°¡Ÿ¤h±rà»/âP[×úl%*Ë­NM±È€¸u&àX3ï"«Ö	CŽÂÄ+`¡éŠ”N‚YŒÜ¿ƒ-ûºCŒ pÞ·pQì%ØÉ+%™<\Ö•G¤rtÈÀ,£D„YQÁªƒô)yC¿1 ¹°l½Z?7'ƒËŽÙ^þ(»

yT3)‚±oäõ<4qfDùýXyy
âÁpÈ8âVŒ9àQEŠý½æ7ŸÖ¶T@Uþ"Žè
ÙØÃf_	ò/ÙT¶bÕQ¶q·¼Lž¨xÁ#OÒ"›È‡!ÿ¢±+ú Ä@­áaB{xŽ1îÖ4‚¹XâÂVàp0#4p¼}›C™1Á[™8n;ÆÅoq,j÷Xt†Ád1‹C/²	'…p£hÚ8kø•PBhÑÆW2¢(f¶œl²ð3pì´$°@v?ÃjÚø²%…ΧCqx韫W‹Ú&2g‰³¶r¤CùųBC‰c57Â;ÎYµ{Ü]|ÞcMšXÇwb‰ÃBx‹H¤ô³bmâ`ÂôlkhÂ…<:;,É“Þå_ï§h¬æÓ°#}ÖZ¡Çò–â[P®¼5¢Cwø÷)y«'7Ú¹Žÿó0®Ùò½Ï±ºvè2˜D1-E‹ÕÅu÷²µbdöÁï^É5W^ijò€¢JC¤Å¤Y(’óV
„E7ŠŠÖã<›s·6ý9¶2vÀkc”EãØ`™©K>„uÙrGKaéT¬ÿ(Ó×Ù6ÅÊ·«RÐMëb„YÂ'Íøý_z\ñªâ>Fñ”j÷‘Ÿ«Sâê@yZ+2kY´b?-9ùÀäG‘jË›‡¸f¦Qѧ9øÛ¸‘%Âh°–¾íB~ ¨¥;BŒ¿(ÂgUþÒQ*¥ÄÜ,Q4e¸ÏžápT=Èó^ñBz&4ÄyO‹»‘%ødÉìÐŒî=â&¢È_;$¥6NÐÙ¶>å‘¢”æQfOôgø, é5‚m-ï™ÛŽ0?`ñT2n#—²¹ƒžáÉTø8  ¨¹LïÂ4€4	>Pø	`”ÉŽMhPû×OÙ©Oâ÷U¥2„@’Þ—(ò¶pZ&ÛÄ‘¬í»Ž«qF¹ZF#GxìÖŸŒó&•bXyCY¶Ï	
CÊᕪúC…/˜ôvS¿I˱綱Ìn”8:XÇ’²@­ÜI~6"D¥’ï‘‘W4Œ¡=à—uÞæÓÄÅæþ9ÔšÈ	\÷Ó$å_ 
K”]N3©¼ïªH‡˜¬´%ƒë}[U‰@,¡Ê/*%×*À8b¨Å S­S¬9nÚ'²)h DĈ­Âò’ÅÃEB«E}µ8†‚´,‚žÑ•\ _dÃF«(o²z¤K×%1,”ÏΊ*HØRyÆh¦1ÇÜVÎl˪çÉ Ëå9¤U˜ã×e+I0I¢+[6¨²ŽŸåÁ
ZHž”ŸSTÁ¶ÛC¡÷0‘Õ|_¶	—:²‹…·òçºæš’žëmÆÜ”‹µÅ(6 2Ÿª£I‚ß4Šq‰´£ZÅD¹Æ`ž«-S-ŠHAû¿„2£¹”;™m[Û
²cJ|–!VF$''Œ5E—^h@Ð<Z^gv†0h?#|‡3$tßKö$Èç)œá•&iÙ„Ãì`” ‡
Óܸ‹—¸¾ÿ€ãccmœºu;nt^‚Ý…We³Åqåj¡=§jÞ‰¥À‰l!h‰ºÂÓ˼ÉÄ@Û4geY4“’DwpGl5sÆ”ªÀ-í<ä|œT‰)v
…žÊ"«ò®£ËŠ$4„t$öv%שU–5k¹­%Å:„‡jcÎ6ÿK
ËèÕé
Ê”ðL´eŲ¡Ï6,ª£Ø$:×{	•ºè•˜Sž°Ë*Ó쬜5âä€s|*0¦û-‡-È5³8R™Z%3­wñ”¹¬ëÒƒ«ó.o°×ڋɃÍiâ畺§>C,=¸êSåSoKhs¾º‘ük8¬Â–¬Þë.gäŃ}”<9rëÖÖIÇ­ §i­*’yÂtI¿!é°P«¶ ¥KIY¿åÑNK1åŸ3™¸Ö†ó%!\ö}nl¤‘‹ùjbó/kØf©ŒÛi ¶P„uÍuµPre]›Ý0¹¬:Q7©(D'êlŠniòY¦îJÑmåó‹Oök_뢋L7P½‚ëÍ;ëv·LÍ‹kLáIÆZg¼€b#ÃÊåM¤¬rÚȧœÚjÕM¿*é>½“XxÍ;™F:ÍÌ“ÜB^­¾§`À)cÇ
¨4›L1èkC$Ui-©äxhÐçòÔÒŠÉcêgÇŠ
Ê噯¿ó,S:æå¶a¥¾¼ºøöâÇË„¯NJ±Örˆlú¦	ꆯ_^|þðâÓ‡__¾{óþÉŧ½tŸ~ÿûüO_¤ùO_>¼üöžç €$ž°›ÞóY¨ÝZŸ¸?Ú°Œ¿ÉhS\¿ØÑJ26 §c: 8º*ãuW…¼jëNÕU8Ià*Ì÷;΀„ùúÄŠ°aVíUyˆO†
éîÒPê‡B¥ä/uûq.íPGc^i ƒŸºÜ!"t
§Ã¿Á›”çCq–Ó>«˜ng"rè(þ|ĪX8ñÈW,ï&n+ø)¶0oYYÝ“æˆØ&ºÕè]Xs‹
únj(áÓ^2W1÷‹v*VCîÚ¢ãa©Ì~&¹¹êK¨Õ–¢1Þ÷­ÍßøÒhK$Nœ÷
ËÚÓa19ðÁ–id‡æiQ[Ü=U”<óÞ¹N[z.nS¡÷5³Ø\ǸËÚJWÒ]®ï¥Ø‘\3Ôå¸Ê¡¬ÜL×Hø¹~²â!Káª	XL²þ:jWlÇ 2½¡qP
.	XI[‹õ“‘›XV2$ÆåÂ?”käºS	N\ùV:’¿¸;X*\b0ƒr²W×Uo±P%•Н{N¬ò°IæÉÛhk`{ÕUÊßÝV2a§¤&aæj‹¶*_õ^~ÅìÐRûPù#Zê9õ¶¸ÔÏØÑšê:ï¿9Qéw‡]Âòéã?Bá¼·Ã?A)ÑÛ2Ô¿¶ü	½&I¶\üà(ý´G€‹Öï…ŸÊ#À"*_gù+‘V›cÀv³9qXl2î„ðR}âR¬®
§ªr	5”BÍry]YŠ49ã-¿f¦¤Rq "xõ:{It	(ØH´ÄU·9©´Ýàüm—sPÂËTqXƒª›ÌÄ™Ä6;ëà¹Ø$ÂÙé!üòu!‡R‘À¿D„BñkÑ
"dÆ8«2Lh
¹LÒ«Œi«à'ˆ§ \§¾”¤K…Š£×"7
Æ>u>_Óç_Ïä
è”õ\ÔpÖ\†*q{&ŽfN~	94¬Å¿}‘=CÔÕ‘a$ж²]T»±]w™oöM-ÃÔÊßC$µÒ±öÏdA禿ÚzûõúébñÅúÈcÎóûç²uP´äÓåÅç~ŒçÖ’á©2àÊ­’Šðnn(9=–‚¡"­[¿¨ÂŸm>ßðcÌFÜ?žá*ØŠ™•àB²Ù£–8¤ª6¹yb,%påþŒ,•Tu^øªŠ	ªøÒ:agjÜl®ïßœæ7 P‘©e,ÊV¾­:>Çã­]PZº0.LÞä´
ƒZÀÊÀQ2Á'Î7saâ¦fßžMS<Ù Üa벋%G$˱Åäç½}EŸfŽÎVt3üüXΖOÁvLJŸúéïæ ü’äê·í’š·£ÕÔŠÞÌ!:Þ€öY^þ²&ý¯Ø°°ÌXå½Èì/'7¬©V;.=p-ÐpÄ/õ¾©œŶ	ɳß@¸b²	€;jå—®?Bdb>ß¿1úÓ.ן]¹Ü¬åS)mú‹üÂ)fà,õ¡59¨[p™dôÎZ/űÕÍLÛïª/TúŠÌ¹S&dxSH.Þ¥;qJzÏåt¥ÓIÑG¶'«7„u²eÈ[€¦
£˜1Ñ^•é£GR”$4‡^÷(óež¼.;AËû:>ê­%è¶HÝ6µ:PÖó™’SI+5øLf&}®ª£ØÍÑÁ{åƒÊ6Guh6»‚ÂqÒÀ䀪°jL¦Àç„óî=xÔhjf‚çsÏþ‰3ß<[­YUîÌ‹‰·Ìe/%•"ÓMö7¶–Õº±T—Ê™d>óÊ¿Þï€e<㮚ȗx•´@ayÔCXò~BÐ>ôt“Ý£ÂÌ?˜ë„Àä‡Ûæ‡ùÀóÞ½-¢¶¥Ä
/„æ&àËMX}M‡‘þüJ§‰Êõ"ËH3‚ø>…«DâD%J6ÀÓ燩Ò^¶A³ôú޶VÙ¿—B©ëg¬ ,žsÉåýΞn4ÙT8ß䨠)ÜvtDúR˜E¦€*Þy
½Á†ÁùÔm&«lá‹\gl“cŸ@K¯:¨õÞ—f[©µâaÄ5Oýœët1ÇÆßÃ#Q˯7½Z]޼¡±}?·zÀ‡Ð«xµ=lz¸ º„¹´'j}Bu07øÌå<[Ùr証¶7Ûë•tfú†éÞ5Þ[LðÐÁàn~Ĭ¼<Åwª欹ñê²
ïûáfr~F(âppùéG¬§q¯IÝìWÿœ$]T„üMæÏÙÞ}UpZùÅÂ^?Ô·%mJ6®W•üH +4[‰¥r¦ˆºÒ.ÞKUUwÿ½ÜÂ›dŒ…ÒÓñ ˆH֫䦨بvóýyy–˜’iRÑ%Œ"šSÔðçºÒ9ÿ`²*gÅ—Ô÷|>äxÌÅÔűÖoQÀk¡°D¥¾½‹± *}Å`ªNjêÕéŸR\¥<«>gˆZW‚±|Ù²\°±{^Ù”Oã™|J‚}ÃgÊ@—Y{Ï
Þ§ª¢ղˆ\ó¸[ˆ-çåFe÷R**ÅyHqŠÕÜ([ÅÛçv¯pÙ£;‘ØÖ±ªœ'Q3­¾5äô°S8‘0n-£¾œëè[Êq—eÉ2€…øˆDdj¿_"þp¿Î0rV?ö8A&Í8ϱK>Åã—»ü@ÙŸíÙ>>ë¯tlÑ@M\ª§¯»M™Økã#°ä§1Þž]ãMN)û»~ݹ	RfaJbµ½ñ«c¥¡«j¥ÜMR|ñ¿3OÏÝ1uO]§ùZªÎ+¶ïôK¸¿ªÀÔegùžö\õ¡—ï­È–×»sŸ#_Áœi‘[í¢Êåα˜Ìöù×û 
(d7[è£ÝRsÜ$ªKy®zå96tGiM²o/þÏoendstream
endobj
186 0 obj
6147
endobj
190 0 obj
<>
stream
xœ½\Û’Åõóšÿ¼1C0­®[wµýÄE„å0ؘ%øa¥]IØÒî‚0þzWÞª²º«gfKhgzºë’•u2ódV·é;³éá?þûìõÙ£Œ›oÎúÍ‹³ïÎþ¸á?Ï^o>Ût§ïÞÉТO¿Ä€Ï¦¦å—4$hÉp§éó¸ýdÄ4Æ'¥Ohîô÷™fäÛ·Ê$øû¿Îÿ’dg¬–c×Ç$¾óË$2›Ä4îܸç_ö®ïF3MtÃW;¿}	¿J®S÷“Ù~¿Ûü~‘ž¾,ù6	øî}‘î‹=óyúHܤ›_§ocê%Ý|m¥aMnûã.85ˆ7CSðå)4÷*}¹¢&§8òW/]…íH2
Ô÷<·„ÿ\ìܘº2Óögh'
ظí;2-h𒇓ڇ^ÓoÔgâ3žíuu¾
‡f§Q$âtÆtf9³¤Ü8¡’À×7øjˆ%ÍÀ9éÄp›-£Å²ðüù›z¶\,-Üe5Éý•î#Üdðë³ülyâZZKKÝòTAÑØˆjÃÝ×…¶"ÌÄúߤ‡¸o@+ï`mJŽõD™–Tì×2Ýæq	YkÊÈn‚Ç,zP¬iÂ]“¸BýL·xm¦@~û§Ô8*‚[êp­½©PRüá&
?BG¤-jÝ®égµ›h—C{ ¸¢•¬ø"Õ­±Ð©è	dj'×yQ$oo&ÜLpçMVJÕP¹\VîŠÄ·üTpî.뜷«/–&Hª$¹(mý·èÉÕ±Z½1àê¥å	U«VºäÖQÃH¨`aŠ$•Æú&MYµâÁòÚO[þÇÅÁÑÁ}ý„겑þÊíú†¦´Ð®‡9ØÆsï¬Åµ‚	6ACÑá&ïA±'‚$Ü7Ðá%7‡Ã˜—º+ß[Ba¤#Õ
ÝdE·ù0•ž–ŠŒ_n.€ÞÖÜÂø§içc{\ärñFä‘áQ4G@Ñ8œ¼jçÓõ`h½ojJ–8µÑº…!lâ`E£P
5f¡|Ë(÷*µú¼ëò®F,ƒñ„)÷í\#P19<FÁ?'[_¶'hˆ,àò¡ ¸©§°=r’w0Ô˜•%ë2«Òµ˜´¼¨‘‹¿ÁܲQóÕSµs/¥jݱc^Âl²w×Hø7ÁÙ?𼲟ñRwmÂªRÛ÷¡©g.Šrtm•€G€¯ñ×±ŠC@ ³Ä¢¨õô YºqÃ

p‰q¶X5nÉø=íˆr"x@¬+²£q$ÅÀe–¢¬Ð5­ôµš­¤s·ye4m@{§²[o*?òñùÙçgßmœëô¾ÓTãÆÂÎâfðiCÙÎü‡OÎ=ùts÷ýWg¾Ú˜³G†>üûGéÏ“7¿;{üdóùª£_;«âèÛ´úÑC7]?³¿€åõA¦-þ›2L³Õ óv*²ÄeS[–æ–äŽ+Z¤v$²S Cî}ܤ5HÀaa,{Gl¢4Χˆ#ŒÞà#]0ÆM):’k&
Ì8p1S@’Ôg’#ýÚÔ¦MÃ}…õÓˆ›¦÷ŽÆÌ×n[7‚F©)ç’1IK`b&Í;‰ Ži·éWé©q0"aŸ†nG–yºÑYÕ+àã˜Ô
êâK€|î6`¨%W/Ò­ÉxØ´;RÈ9öf¤0bµ‡7ZŒ£úÎÚØ»H1—¦Ûrƒ„gùf‰VæfŠçÒŠ»RTe0ªúëÙù{_S`ùIÚƒ‡bЈñ!~ÅpÒ!
¡íPöU密Âö³ØßÉÑs 0­¯vÅeUºQÆÍù¥Ç#‘R×^2`)«Á0$ºÀÿg[ŒŸøðâ-SÛiÙkú=!2+¶²oL.Qq†yY€œaüKò(÷î¹³5Ïlo俢öä²s“×S…ì°¿ÒßÉ
’#îæ}¿±éÀYÖþ	A¢h-a,´Ë ..ëÞ[9 ×åGµ$vû>4ˆZ•hOΧF1«"ÅŠ=e­6{¯6Ì:Î3“Ë]¼ÀÂ*
aUbÔ¡yÕŽÏÂL%`ª†dWÀúhãš*šBù¤jãÈÆF%÷ˆˆqÛÿ0zØ™~…¢FfCx)¶všdíÊËŽ=ÂùBI¤éÚ+¦¡Æ±6z8æOXÚaZ@9]âW‰aáEÃ’lG\YmÙñœ‚ŽÁÑykÏ™sk˜q‚­mÅ»ÉþW¬Qm?GR³»Ê^Kú®ÃѰ­,Ü&ˆ}‰Å_ ¾‚Ø+J6©ÂþÈx7™Ê,¨Íé–ÅS«¬ËA´ÖïµBÕFëVè¶½°h{kºÑöîSn·ÔÕ,“)³_劙³¥ l–&]
Y(@åš6…¼KPÉƲÜjPÊ
uZ/,HG11oüìQ©y=Úµ+)Žû‹µ#l7!.¡ŸR?=™=(XVc=eSŽ9	~rÁe1SzôVüúЯ‘S|Áׄ°àr¶}AIÍÇ‘¥ý½`"?H7‚÷ƒ™÷ϨôôÀLÛŠ\Å÷—”O\CÜ‹òþm½¼Võ}Í„¹Bö÷%¨–³q¯òB!rìP]%ùÕ>~¦½A©ŠÀü]/ó
¶
(y»„ét‡Kê »÷Rwï‚¿Üó´*$÷¥f¨•²j"´AW°Ø‡Q)LZëÐÚÇ©JÈÚÖ¿Ú¦ÛˆLƒæ4LS‹Bã_:€#J•Êšu'ëÙ/lºŠ‹&Q„YÊ+øÈ{3 =P¶ôðQ©ª'ªK‰V‚”_9*%&*mlti̯•r'•æÆiE3ÖçéÝ«~ÎòŽZË/éÜ…õ±a—ý4GòåbC©(ø',¶
¸ƒ«Å–>îá‚pÌ
O…u¨$ÝnäKWò+¾ÚIРCày¨!qPh‡¼UÁK{&3Mg‚žfª(ÊÔxÑ
i~¶÷U¬Ñ>½Dlä:^J]F‰VÑN±[I~]‹çc&°ætoµ²C|³Õç9îè‡föTž¸wæ
I_SeUŽfÞz:!HÄéV’…P‰)GÉÎrÍ
ù‘é¹ht®ÒÈý É–“[e†bèyšFÙn…!Ö%‡@ßÌŠ®ä8tWñ7¥ÓÃÃje‘‡Ê·!n,}?`i9ðfÎè§ó\[~±(Í¢CRcÃÃ~
À immpUÖRñ7h ÚQ#­ˆNNv2¹[9Ÿr(šÎ¨?ªÃ2õîÕ¹#P}½«ód’ºlSJÑÞ2e;#õå!á .²Ã/ÚšËûˆ…”÷&פþdÌçU¹Ú¬tSJê<½¨Lª‰˜5ÿoiOÉÎ
x6a-Ц’œ„EYGåiòµ\8:]Zµv\ògb×ì$Ø„1é«èäÅÙ<6ð'‰“2ŒnϨZ!8—:Œ¿“,Žq°ÙÖ9Õ¶vV­ŽY½àv[¦®:7~b›W²®Ù‡9b9§ýNÄ&»@'lµ„éÇ
墓DÒ}XyÐtVÓrê4Щù˜Ã³…îÌå8H!Ó2ú{™ªøB^`É¢kSÄDê¨ÜÔ_Z`¸(áh6§Kb¢?¬úªæè‚fÌú7K"-õ®î½Åðã¤kýY?]E“ÎV¥Æ×Ù@TG)¨‚…ëYF)ý–Ë­g&†­-æ—l~ïâ±m¶Â•z×gQ篓0;Þ5¼a¡wàÞæ.‘-æ­.þ¶äq×B.aÜæÅŽLªJkk]ÁyäçBF÷NrRƒ´8)1;)Jó®*Œ½bb¦:\³†Ä`ʧ¼R‚ã—ô³É¥±¯
Ð0ªîà¼Àe±¡9lã—},3E¶lô“8´‘ŠsÚGÚôQº8èð}jáT³JI"ª’U•Õ§(jÀÁš)8GǾ„‘ÔÆ/­ÎÂÍ©TÐ(ç,QU-«ÕÄæòéÊJ	$jò³EÁ
êÍÙB÷ÏN`?*†=ûŠö\®gEÌTö¹J—ç·Sè
Ý+4Þ/r`Ü$sXbÙ,[æ,ЬZйá|«ãjÕÛGTä^VZÐ"Ó9T€òIEαÜË×GêǦØì³ÉÂ9×þò7߃ˆç6^Jm >ÐÃu-P;}aŠ-PIk®E&¶ËS¤¥zû½¶ÂÖ5K`ô@xcŒ
qÁi–+ŠcµDÁJ®¹Ž²ê­x\¸ËW•4|{$­©Îæír9¹&uíx°¢\hޱ~‹‰¼BCJ¨>WüìÆkI* b–àŠ‹¾„K±Ü"‚DÞ‹Gov3'ê{Ú÷*`nˆ}GHC`…ísHÜPµÊÝÆÊ¼Ù[–:ŽÑS‹Xvõ4ç¶~”wQIöÂ*Õ’ê$™©:ð’Vì}‘ñê›ehØueƒ¬¼:RŸÒÀãÑR}'¥3ÅÜë‹ðçnÒZõ¬Íš”ÑKŒÑüÔ4R»¼^Ë•Ã~ùع²Œ’gž›ÅxWù{ÌÐ`•ãß™?ƵΩ‹B™hÈÃiX¬Ù•õnÙí¢E§o)‚(µ—¯y 2ÿ:T+ž/#¯à†¶ŒIPϵSÕŽªT²#'q'†U
²}­´¹|‹®²8X’-Ž4=•+'bóÕ+g¤Þƒ’FÑQc/Žaá?ÅNjß[ªnž‹ÎæDX\b#u\~·Ãgð³Üw¶Næ1«ò#ºê†«p,ý)ÙUíç±B¯‘"œ£>¼œàÌ*¤lÂjþÀb|àÖNœäÕb-C‰É5‡	[ÈõF«zkGXÐa†D·ÕvZÃW]I7¨t‰'ÕÐ¥êøg'é
ÕoëòùögÿÞÕg«s&¯ÑЧg&Ϙp®bö–‡ÏøY.!°üê­¹q¶I&'æ°Ã¬Ò\U<é3N¢]š¹ªÞ±–ß`æùÄ7’O[óäU™U¥–¿Åb×uÎL×¹aÉaÒ‚õו^§éºl°/9{Ùσ‡Š÷ʪèå4³V¿åÃ=²Ü©£`
¿Ƽ¬•>TPR;A§l™—Çaù-ÇŽÃòÛzŠ¡£ôíÞÑx0R+G"¹Éc…ïåÕ´ÄÁx(—ˆ³!
†³*!Ìœ}~öy6ÛÎendstream
endobj
191 0 obj
5476
endobj
195 0 obj
<>
stream
xœµ\[sŵ>Ï
?BoìMYãéë̤ê<ÄŸ §HUȃ°ŒLlI6’óëÓëÚ«ç²%R”ðÞ{zzúòõZߺͻã¾sÇ=üÇÿ¾¸8zü×áøüú¨?>?zwäðâ1ÿóââøÉóÒÀùòK7õ“;~þÝÝéŽ<„ØõþøùÅÑ?v~Ÿvã>ýóùÿ•;‚³wxï»ËMÏÏJÃ÷'q÷éÞuÓ4Æi÷‡½ßýeâwÏá÷Oö'rá¯û“àû®wqKß]¹âýT.BóÚ(ø®ï‡¼ûnÿÓ>”oÎÁÍ=4q~Ä'|¶÷ðuÌæÓ3xêç{¸?yWî=	qì¦q(¥Íßô2¶þcéšrÃ'ðõÏð?é†~új’J“að´㱋]ˆÙÃBœðJœ„¾Ü4тIJiˆež]yZr.L;§¿ù2YrY‡Ý×0©<„©»Wåa¥__Öàe¹kÈ¥Ñî²Laè»0N»xôÓØ¶,×C—SÜ=-Ë\DzVßÓSG÷CS—ãî´üJ»7¥áè;Ÿ&˜›\®÷ü›1!§Ú}Ú]áøÓwßÁ¹Ì:ò˜Â¨£‡žÌM<¦ÁãÞô÷cFFçó4$Np
Ae
½K	v¥ïbê§¡lv6%;«kÁàÜÎÒ2e;Õ×ð¬²ÉMöç«}H¸„»ŸJÿ9LcÌuÚÞöh×ÜÖ?=ÿ脌›ò¿	RZ¸B?¹Ú.àNØã¾/÷éXžÚS&wãF–'ÄŒPš \Ø8GâüJ7¯|Aò,HCQôÐàh®Dq'=‚Ô§•¹+Ñl/x³óØlZ‰VêêžÛ§‡31ñy<Â,Jé€â^Æžšp'±wKkorŽ„ÉÍ	ÔŸÙÖiªÞ³vkY÷ÙÐG•ò٦õºFº­» Ü4 gΛh+JWtB—HæéŸ±¤óËVÒYó öäçûpï«6Fo«è‚k0—ÛE‘€K Š¢Ÿõnhy…."uÛ
Zc>Þ'eÎs;Ž-Üx®-Úà†3–F¹QŠÆ>¡O’´ý§{pûFpè¢@ô®‚Œ· 4%kíÊœ°DНz¶%Œã‘Š«®Êzqáq V`è+{ŽÈnbÙñyRÑÍàhƒ93Î…<ÐáO­lá‘BfŠˆ19½tÇ{š
Ñ…L£#¶Jê;Õ]G§aê™=!Ûb*¸åÀýXÁ|R²Çe@‰Èê£êOı,IY°ÿ…ǒî¯Õàj•v]òõn*¤	ÜPᵩÄ>u(,ÆhÇ5@ŸY7‚Wùßô
 Ê¢JÅ
žæ
3•' ²-÷œ,Ç@d_ÁÛðáÛ9ªŸ<†
§àæ!ppÞºà¥k+_J7ŠßohCŸq##æ 7ÝÄ|ì¥høKŒ¤uÿIň)¬nÀC¬‘×À*
—ï2ªF´äZ-k¼\#œ\«käâ
c©îô*ô»}ELž¬F1]Í<ñ¾Ï¶êµmJ¡=½‡fðb®öx…qj\óLï6à¦Ñ+¹\È
ƒÉu¡òý¹Z§ÆóV°¨÷ÚûqÅ‹.ru¡=av9Ý%ÌŒ±3YÕŠð”Pq"“heõ9ñã_ðnüH2cÕ"üÝGkæÜS\	-òc£#Äצi¶A"™ñ¢ÿMœã@Nt"ZCDF‘ÖS¢ëì.zØdÑoÑX‡2‹»´­h9NÉÿ*­1Äçöb¤è©qÞÍ=|´•~‚Lç­ã›¦ÝŠ¥_Xñyä±mв8n±Ð‹|¯þ.8H5êm-ãHÀ…ëúÖN‚¹³•b‰„Bë3/ÈG؈4ž{"Î,;äNÙ…cèÊZñNDvAÔ6h—¨¶"“Ë|]ÀÍ^NåŠs$ï&À?}Ú”+ØÚßA’Wº[£ùqKÊ%³T‡ñ1׿5 ¸âè•h‘Ö j¬ŸùFcª°‡Öp‡U}¢¿Ã?†IUkI3«ÐÏ.,\®AŒäOç"êY7-Ðk<²Â÷½Lq9‚…	êk¾¬Îä-ÖÈÁ•;HBš‡õVâø°F+‘úUÁD¾ÂpP0áÆx½ÆNìCõ€ž½•¡†\×ìÀ¢™¶ZqCwU\LUÈBä vJÖe!E÷5رÅRRT-û›SÕ‘‹L'ŽÏ͘Q5¯,ð#´YdcÓÃ@BÞòIJ¯uËT	y+2,îeìjžp`ÇM`Ã
þé>ÍUåŒ	ð,éáδ{§N-“e N£Ü/bVIµÞgÙQCpûÆQ©DÈdʽ"¶S÷Ýô	¦uòGÊž±ßNN÷Mncäaèï›°À…‰Ý­²4Ó!¬èôÖ "iy5”sÏÜ•Š˜ŒK{bfñq€¸–àú«,ɲYvËY}¼Ñrænæ©7
j4ën»=Ã=T”Ås˜WÒOŠDn[–É¡Òøè‹½	«Íü§¸½FËżb4ÉnÇ ÞÞ‡rrX÷öc# €œŽUHn¦öqXgJ®óݨL}žþä÷šqøkÒŸHÀ˜•ñ¨ØDiǃ4LRð~kÏMøA®×·¹jªé…:‰Dc7’¯À˜rzã–D÷É´k¼çœô’+Ó¤—Yº0›Ž÷Ífƒíì=
¯šB§pcw¼¤8úz6Ô'ìÆœ¶~&+¯•Ÿ{›„÷Fh9Âþ¥ªyNí0‘›òí~E:F$–›¯å.Ø4Œ…·½E`OnÐû:Ö™¿FÍÖmMCX“vs3®ì§Íâ­úÁp(PæÁ¦CÂ˰Ë].+Ø—5)rl.hÆ*Ã=²×c_
7$eUB³<çë•8 M*hRKe
æQjÕóŠÜ‹ßB0‘ù”M?3Ý8—EmrCª‚$O!Ør¶háâTy×2Q’ô}¬þf“÷vZÞ9*Qà*2¥½­ÀP_©“ÁЧ?)35ìŠÒѰÆK­úC&| Sâ€e¿)ѩÅc,Ñ@%¼eë]£ù0Õ$,ÒºTC»_¯È™qã¬ZMu?3@]Âp²„Må±!N?
):àÉ`V.r-W§j‘Öü˜©W¯Ç5yuÅÓXÓÐèaI^‡<ºÖ¿tÆnk‘âgêÅÌËøNuíOÈYMÏ–Yì·«ìë[Ùf9æå*R¡èFµÌZ­øª>Æ-Qâje ÑŒ-tªAë*Ö4ú£þù‰¬H èEx¸ËUC—¥Å$ÁÃQFößò…´YÅa)îN«í5«H6βNñkÑ”<6kÈwzkÑ|Mm˜T¶5Á[…Ë\:ÖÔ¯(5vë)/ãù^¦BÌrp0±Æ+2¬çO&+¡ÈÀØæ6Gõ²-Ë•33kG Ö&ôM¤‹y”m¦wUº™ò-þU{4.
Õr¹_I)¸wlª½h²­@ÛÌ„EMtÓõT«é¥œ„1+l-J¶{'鯇+ZC­hý++‡àš‚T.þÜ8Hñç¨Õ§ž£Õ¡_ZÆ”mªþ„’ÐõúT¨Üí’G)e…HßEŠŠLõ(Òb’—ÄÖ:ÖÚìJ§gJH¯aœP¶ÊE5cøN¯¥'¡ùV6£fÝ5nÇÖÅ>^Ô5’
ÏiìSéÑÕ¤¤æ¸|î=?
Ëò
4‘'7OËÞ¬ÖÛH
M¼C÷(']MÍæ”Ïiª!½U­H:*WäøYÑ!gÍÑ
Ák*²ÖÞ·„³É9,÷›™3­†…W½3Z£u;°Ö™$¤§J§ABˆª}¤bRýÞª!‚¡×÷÷zrñ"'/Zv`¸¼©´„†¿«t–¶bçì£1ŒØK–ªG¬-[‚Ÿç7d¡ÚL¾þ^“ûme·Ô
”S­Ž;ë²Ó´‹Ÿ…R¥›ªÊ	ß›9«Jžë~³¢^¿õƒÕ/Tաݶ´¨Oò‹³]S@4e¥q*kržfµ úˆÚQGîrÍ9»"óu©'mmÌJèªMÑ@ÀM(x¹éÓ½X(÷ÈëöAÝÌÆA¸R"É+øíVZ,Ï­A@í³rx¤Ä쩬>ß;!¯›`„X¼Iòa•»×®ôÙ^«M$¤âÓf¥—ÚýqÏÙÈè6"k´=ìø€Ãu«fÑ,´^?Ðö߈¹ê‹~ÓºQ6™!™·É6ÊyJäpìx—¿G´Gœ5°,U½Ag!ü¼êViz·Vî©§ZÄ<ÏK€Rb±µÿÃXEë°KË"F‰Üói_K¡÷š_³&ð•0O0K\~zJ®NƒqRJ¦üîüëk²Ã·*•ß7J…AVv¼ÆH%?dRûKr$pÚ'ÉT
²
´ß5jšª5b\tÌû¸áKZmØÑ#!&4l[ì°“*Ä,ˆz‰…VãaYŒ—Ûí¨¸m–½”Òø‘T •óÔªÑNã_’‡}É@…‡|g’v*äúáÆ‘æm¦ðÝDý^ó»kt¢‘¿ÍÔ!«¶œjI8óÞ$™ÌÆ%MeƼŠZ25ýf¯m!Á'P¹Q–õzäÊNŒÄ³3VÎ%m¢ê&ir%ÔÎÓlñua¼`ÉR¹…G‚KÕ@zÃ_*ÿ¦ßÐø<˜]Í­o¹ªR­4£^:rc-²iœ¹ä©ï5%À4K}º³·‰Ô)±#:š—T=áʤVGÛj3ÄSaˆO&KœÃSÁ×ú=
Ô:É%‹FAXÂM…ÊۥʓîñNž`«ßnõ”5Ù|Z÷¶V-ª¨8”Fºxê\S,]B›0þtÊ8fãÿ}»×lí¦0&{üÿÔæiŒÅÍèZ¯¬ä™´BRì7xT&U󧂘'ðujŠ+²–lÛ—)aL?¹$g.[dß0·®i$©–Ä
ý¯…A&•~9w@•+y˜ºçÆGòö­„]·Ã¸ð’ÈÊ¡9mÖÍ‚ÑÐ9¯0Z3w`/¬´¡!þg"ðm–c
…
aºî¼,sëä-;›‰µ2þVö­%Ç*AoòýY2aù”„Ñw'ûjÆ™p
*ÇàCþyâ¾µ)î±–ó`@q­þì|?‹ù/$Ø¢LØê~4ŠR¯#¼‰Sö]ßFú¤Êß™nÜùu—Ù–+ì½×pq£4窱¬AW2N¿
ÉDR—ëÅ{iŒ€
ГæÝ²‹Tµ0«PÒtÆn¬8¸U±Â•K‹â‘Hï©êpµ²-™ªExš¾_³M 0®#‰3Mð–%¼RzGu0¯éËïÍøä¾=õ»M埼õc	|YCßü ã;ß'[N3¯¡Wk‰/“ëERåIö›Ó#©Mj5Y’@‰n.3‚.ù”CÃüÆ…)ʆ†¾´éË£5Ãendstream
endobj
196 0 obj
5841
endobj
200 0 obj
<>
stream
xœ½[iÜÆÍçA€ü…ù&ÒÈPìƒd3@>heIÙ@‡ea#V€¬´º 펮Ց_Ÿ:ºª»IÎrd²†d³Ù]ýêÕ«êÖÛuÛ˜u‹ÿÅ¿Ÿœ¬®ÿ8¬Ÿ¿_µëç«·+C×ñ¯''ëƒ-4pî4c;šõöÙŠß4ëÁ®ç›Ö®·'«ß*_wUSÛÊÀߎ~oBkšÖtÕÍzã«Ûµ«ë­¶xõS½é›¶5mà›ê3¦COøæ¿êMWÝ‚'¾>ºê.Þ¤'÷RgÁÁ33V7ê±å¾¥C_ݯ¡Ë1ø‘:ý÷öŸ0cóÉønhÚóÙÃ,Œ{¬;l¸‰O6®m3ŽÜ`
Þàø>À^ÂlñÆ)Þ€é]_óüi¸éÁ:xýÚaÛÓÚBƒÐÙêßø-<Lp$½§·Þã,°{|¼Ck`?ðÄw^ð§Ìðü̯a„h`S=­}uá}0ï{þ,Œ#5yß~ŠßîÈÐOàütöÍ¿ŽÃÁ.ßa?¬o_=z‡qŒÏáOövÖ÷5xS£‰]Û5¦Û_{¼yk»z¸z»v®é	gß„µ}ÛØ°Z74}@Ø®®Þ[xwötuý—µY]ÿþïà‡›ð×á÷ë?­n®î…t‰´cÓYüLãÕw“Ao(˜~¬þt¡ºS‹}nárÝ&ƒ:1HxÅ{'æ;ßℾõÄÌÞç‹hÙõ`ý8V?ÃڤɡÛ">|œÝ5¸f+`¹E­©þC«B~äB‡ŸÞ×t=’ÅE‹Ú€¦èÇÖ¢~+“ßX7Âw`ÍÏFQŽºxåŒróß~˜íf‹Q>:½-þ›±é-¡Øý#ï‚ý#lz3ùAí'1 ú;þêN?¤@TA­"7EB|ŠqÂg¬ã³NÆZG5øQî~ÞG¯¼fÞáÓŽÂϧÚ~e'ìõ*¾„ùÞE2ÃË)‹5:ô‡00m
ƒkËgi„ú‘tC&÷òªÇêc2ð“Ã`¡°^`ÒÏmù2’+˜Ý
¹ªu\Öð(7›Ëü™gcÀxfqnÄÙÓì"#¤_ú»û866º{îEŸÇh©K(Ç1lúL4bH€¥°øGÙÓ|BLàlðB–m¨>ÖNãRÇÊâ³óÌÛ>
[µx«§õÆÏðÒSÿQ«ˆY'h=LyØñ¯h«@¯ÏB*Ž?s,àxÆëMp®g‚µ÷â&ÁmjG/ëøŠÈ9Õÿ,/ãwº‘¤D9€£¸’좜‡^ÁŒºCoûV*:'üék©]‚ÃqòŽOÉD¼bXyÝ|d&Ñs›âRQÐe8I’ñ¯¤|]Ëk´PKjTQ…*Ÿ%ö<–UóA6!Ïël€.)–\?®›ÓVç²õƒ§ò ¯(Òå±\$ŸeQ¼wæJ†)E$#*€õT‚ŠÎB”ú›Ü_býŠÎ–ð™ÐTý€mnâïŽÞ!så"‰cƒxþ.%í	‘FKŽýs	Íô¦8:ÙÏ8•≋â4K.Š”]²5jývÎÖä¬%E§{v*]Gš#ö1ÜãN‡},ÆNM&Á$‹RŠ¿ð]+;YbH§Îäž[ä!P<­kŠ(º•2²œ!òe?/¸„öœØ9Œ”•díÒ²ñÃ	aÇc;[¡±Õ
†‚e¾B}Rèà|Énèó(ýB˜Í"ºK)Y»üÈòà¦R‘·¯Êø8…/yGªÅ§€«5©LËHs¾îènÀŸ_ë¸=F±ÿ4ùÚ+)ŽÑ&da¨Oú.Yý8	 ˆ—î ;&‡~–`²Òö;v"Ž„.ÀŒâ×4Påü'[õ¹äší4x3Ò‹Å1é˜wWÚøž´Ü"ÚZ‡™}¥Æ‰O¢àå©•hšmÙÎvkñ¬a±•,…³¿Ðlû	²µdÒº˜Õwi§KÎÜy³~s¸´6|EÜ9/ÏÈ™;-Ú,°sSFÑ])=$n*m•Ùi¬IžÊt'Ü%çAã6Ò“9Ü$çfáòõLGJó]²Óå¾x™}©pÓ®›#—b-r^«å|ž ·:íä(Ò¨±ì§\«õŒBy›ª’ñÄP?¸ùÆæL†ué=~A\nÿžDò7ùQMµ>u–æ9/ßÅ„9¤Ý!d*x¤-òeÊôêÊÙÆ@̬h>Wÿ‘oœnendstream
endobj
201 0 obj
3651
endobj
205 0 obj
<>
stream
xœM¹nÃ0†w=GqJR²%=Œè•TŠN)šÉCÐ÷J:qÿÿHA È@vNq7»‹mý#Ø»ƒãE„SØÍpÕÕÀ¢Ø¨1ôow$Š@I9’@ŸÝ‡O8xÂá³?(‘øœ‘˜F…ú—¯1d‡[«¹ùKÿŠA|·þ„a¶’P$Î>ë쨊HSÑìÿ¦$‘¨ŒþÅð[LZ1Lfa©Ë†'+ëx–ÝÛÖg4~V6¤\c«EÓÕóþ'/îßÚ¨o˜¬|´ksl½aÔRŠØOLÝmôüÛÙKÔendstream
endobj
206 0 obj
229
endobj
210 0 obj
<>
stream
xœ¥Z[o%5~øyÛsi|o›$@ŒÄjÑîÎä
Vì0É$#&—¹˜ýõ[—]îî“I!à¤Û].W•¿úªì7Çf²Çÿ©ÿquôåÓùøâÝ‘9¾8zsdéåqýß‹«ãoOa@>vfJÉ¥ãÓ—Gü¡=žÝqrn*ǧWG?í¾ÛŸØÉ¤óîrâ&ç¬÷»ç{3™Sòvw[·{¿·Sp%•Ý9ü*Þ¤y÷vâçyr  ¢,ï³uÿ9ý;O¦9ϧq
¾äãÓ~þÓî[˜Á–4‡“¡
±À\ïp._\	»Wø3ecâîN3;V×»4ûÝ”i÷€ßðð””‹Í»gð>d“b{Ÿ¼Ûý“eÙ¨^ï]™"|F+t¹xXà	ˆŸ/´D3›Jٽğ³K¹t½³
A«èAÔ9Êë¿{ŠÖJsÌ»TÅÎÉ–Ý]׊çÊðQ]«5TÁ÷|&*XŸÆϦµ|=Sضe²É8±-! 7¦OA±ÉX4¤ŸáèFoŸï#z7MÆX“A\v Æyw†Cðoœ>¥‘Dþ
#òTÀv2À{ˆ0ʸäO|È4ë¯2×;4X)9’‚n%}"K¾!w8„ J–F]+5`ùò̇„
ô±mVÏ/¾C#<Ù;œ0S86Ì3øCW#ÂyRƒfWZžïÑÚSI°wNÏ`üå¹
ŒUq8_t]“s1ÕKŒ0z„«â¡Úf®ö/Ùã8ø=)è+ñ¼¡ I‰Ö­<
€€ú¢Ð8v68-ÂóyæHô3I{
o^³D¶ÙzÒæ/‹jËû».îº
í9Ah¦“j§ë§q§£¹0 P1tîu5¯Ïì"ú_µ®à…ÒÖí>àÈHfjA€ÿžõ­úbÉT8Ù
~eX$¾F‰4¶Kfs4|6ƒ=`#ÿaÑ‚[ù%ÑWWÝ$7c ££Š§Ù‡`“÷rÕZÏXý5À5ÖÀ–Ñ(Q,)E‹Ò3î]×¶2Ú®`, Í½µÓÜB…á>E•ÆW†Þ“ùª2×ݳg*äõ[ñ¾ð,ãþ@0‰œº¶
glÎq»‹]Žìúò(ÜêÚ)ÜüЈL°mÌÜ6Gqb“xLÆÍ)Áçc¢0»’gïÄøÉ4”ÔP‰®cÕQ>'òõq1rŒ¨%MfÒ*.¢°†8-å	à z\‹ïó¾èûÆCê^b-Å‘‰“	G+Ø%‘N2þ¹Pù¶CÂ*GÄeXE^Œàxýó&EôfØŒ‡?)-Cúu™ñ2£6’äb^ÄìíV¬Šs\±-0®˜° Išc˜¼¥(ãÍmÅšOÃz=#
¹Å¯Û¶ÅŒ0*Ó(yLVÅ?HüUË+©\3ø'oÖ?3À¨04¸ænõ‘H&UA*ŠÏžt©??ì	|à"Îg3ã×D„¬i7¶'8¹,³fjçã.»à-ŒÖXëéö÷½wu*¯wa$à¹Þ0•"¬Ó={¬Úä^¦Ñ˜•%Ã`V+R0R‡
ë-ïø…"aLE²[Ù¨Bʪ;Pè8«²-£°åÑÞSZé€9ŠÚ;²5ÎF7ð¨¯8BNd	'+´-„ÌûúÇýÂf£ ¹ë¡Ñ|Ëç.Fq²$- ËîŽàM{-ÎRкˆþ¯@1CFÂ/¾ÖS^ \3fùúAå,o#Ô²À!ÕHRƬâ(ï*œ»©¡ù¥fYU´*’ÁbÕÎZû³¹Êà0üQÔèµõêÇèQ› Ð“7ûÌ»LÌõ!ÂЫ)ÒVS;¹¾­°kɧ¤éI^v¸K¥í…kqjŠ4>#¦FÓµpÈÁ×2xBÝX|«J_÷bà~ì£hŠ™œüÉ¥wƒ|øzÏ/ñîVÂŒ	¥K-n:â vVÕ˘üy?àCuØ.óQS½®¹M=ºìëüy×ÂâKôóÅY²ÿ¡l®j¡±¸:”Û)=*æwÿBW6t±§(ó&{VÃ1,ØRXÑZÑ0e2RÉC€¾²‡ ÅGÏϘ/ ª—hÐËùºÆŽÃÒ3URéÊìïåÒãBô;Òd.Þ+S„
ë¥ÎÓ)bã7îÁYWÊœETý›álZauÖÛ.q8D\át{uZ
†â5nU3¯y³ñª¼{ƒ¶Ÿ1¨H¼k¯7!yî£÷¼jþyO5UqŽ1òS¶	)$älÑj¤7%ôzû·=¶‡LŠºfâ`¤M)¾UÒ·¯já*|FUÞ•Ï,«ï$Y¡«é>r7âT)wŸ£tŒËK¶Ï F”ÁüØ"‚úHi[ͽas4–ž*øâŒˆ:µ›æÆvšu~Ê
¿U·šnyŠÔ“aZ¬f¯Õ+ë>Ä3©2Hç‚Õ‰=ƒ@MÖlϯøã§gnî©ÎÈMgÅët"›î¹ÆÊÜõ3‡k>Z¯ÓÕ€sZrßXŽ[ˆ·œ¿2ÀV,*‡ÝíçK+ŒÎNÞ–Í rÚ0'H}W4/V’¡»œº¥ ëÁ’*)+l&«&ml]†ž Àßh0¨é[@|ÖbhhzéJœæ¥bHq€‚¡äi-·4q§ZÆ`»]œ´nWÇ!^õfŽqk3'nÿÉç)Rx]+x,‡C«U’|»?@Ašp×hàХ厈=ÄFïYc]&•¿ÖBÓCÚÜYµÞ …TuT‹ûÞPèë+úî0l”èñÁÕ– Ìcâ1Q#¹ZþFl¶’|‚±å™}Ustšr‹Æf†¸µÁgKÛà†»žÿ[Ø3Ö_™ú÷Ým†"qq˜0v(·˜ÚY­ÚL/tÒɃ/ƒîiª4ÞEÂYZMåd•±Î?ÐUO›9þ	<|N˜.¦ê
I:ºË\I”ØúŒ!©þ{»¨cfr4&úÚSm™zØh?ªñB…æ ùP-§úˆ:o¥àÙ<¦ý‡Zlf¨^ϦÑZ]ZòÁàÌXÚª¼.[b pûô9Ô诖!äM>O‡QœC*¬J
ÉI¸Î>KY`½šïMCÿ»±–{Ý8Ya}̃r†ÓVŸÈŸÇ®K-Ê`b¥ëc#,ö.©ô΂q«N«¯-Ç„‹¨Ö&¨±HmÿJ¶Æ^“naõ&ŒÃe#â¼nÚ(‘áý‰œ½vY‚ñR´êÈv~9”g­™/åb0aèCÅ-ÖH×#bGNI^¥ù¡×Ô°#éƒIªÇqس)w¬²ÔÄírÈî°*»¬H6–¬®*åÞ‡,¡tçØáãnÑŒl¡¦.Œ,퇤Ál׃y¼ØÒíW;„ñb˜9hç¶mpí¼[ 8nñ›¬Œm¦”ï•I(]sª@òÎrÝg¿ŸT>E+IAÊ‚óÊ¡6&¼Æ±aYçŒy]ÁNmWWž^	h(Œh2–æjVí1–â­[9²ÀU
ñS—ͽE‚¯9ûp`
†J`£n	ù”^ß‹¾ªÑeV¶€74©ú64!-¸`œŸƒ¥îÁ­õegAª…ÌŸÐX0¥Ÿ=]|:ÁgüÞÉp@3—†^•$²	Ó`yXdã3ݼ‚›cÚ}÷Iá#Úx«ÒäáçMS¦Þ7
q±6
=<‡_®>r–\*ãèUœ,T»OqUJ‘*<æ GöÏ_ñò3סõõ9<ÄEìÈ'k79è61X«Ä~ïÕî7opbA„ÀW7êSL›IÛ•î±a¬ÜwISzºúˆÙ
2[àµT¤Z©‹ÌeNhà­t‡í%úm܉@ç9/Çzÿ“hÔGt;2·“žŽ²m©ª4m¬ïŒë=>>p¯©«vÑÔjlÐúó»^&=ÙKÎ.·Ÿž5;ÐŒel–·LríM6e«=95é¶åâ´gY^µ-ž¼Ž3*€°€`‚dÚß¹x>ÁX9!yÑñ-„—í!Æi–ûÿ¼àr@ÞþÒþ|+ÿi`T‡õç]<ü¥ÿ¬×õ ô­ºöI¯ýpõ‘í'§÷~ô¡¨
‰Œs-…¥º¿
TH:Ým±ó÷õ†Ïm'߈ ífĈj8šPÁðöÌ1f5Õ6ÐDéó¯ÚnÁóaë6+fyÙòÀ}8$ÅɇÇõ¾|ÝN„°ï°Q~J§%ù2Þ¾<|«\QìÚFæûIù“qkæ[pôbO”Røoµzé'‰–‰‡;¡^qòË뺭Ÿ@skÃÊÓPæF¼äÃ\p9û—\B¶“Üù»Ö-¸C¿Œ,’P«V‰¦¤VÅ#£B-anåf1kn²9x™³:–€N(Ô¥å½v˶¯oÕ;°™Õ‰±
[Ù@ÖõÏknÍËí"Kª=¨?”7ù}åß®ìÚo
<}/	8:°ßÈ+,³øïOþ
ÿüÅp¶endstream
endobj
211 0 obj
3826
endobj
217 0 obj
<>
stream
xœíZYoÇÎóB?bwí°ïé~H€H‘`Nl)òÅ]‘‚x‰—¥Ÿ:úœ’+Ù”ó@XÎôQ]]ýÕWÕ5ú8½œüÿœÌvÞóÃË™˜Î>Î$uÎ㟃“ùó= ´ôA9ß{7ã™r>¨ù M/Ô|ïdöŸ…îìBuö¿{ßÃ-›ƒë•‡I{+ø¢[šÅwìCð&,þÚ©ÅOÝR-ö°ýe·Loº¥Ö²bXXÝwËaðЧÏ;CÓþÙ-ô+µØ-Ó^à4Ý?ðJ¯:…=Þá ¸
N¬çüs”î…´<è
)Á…€J)T•Q$J	ƒ…%´¥UàM‡µV GÃpÒµGá©ÿ_ ‹VIR#6æiPͼaPlÉÖöKiB/Ì|©E?ÈØ¢0g±£œÃúžöÁbW¦çîöø€Y°ý(f9ìxò6ijJ:=ÀnŒ^dÁ:qÑ¢8ñ7€ó@$nÎãú°$nÚ/Þƒ§eÙjŠù¯‹kÔßNñáðNÞ¨OîˆG°PPæž,çæy°GnÆUÏ@%\ÙËbª«íæèM&IÀQw†{ø‚¢°3!7EK±•д×ФnQ-þŒsJ[ˆ2wŸµ‰ÃWh†L%ÿ´S°¦·ºŒË£D:ÕÚÏ‚)+y«Ø†›[òî–VëÐMq“pz:›jN5ׯ/~MvÆ%àÜâyheèÜ=é´v/I‹:D^àKUw>›1Ú©Z|€Á°a<°Kvý‰®wŽ+ƒKfúÜœû.ºŠÓ­«ØÞëàÁWTïðöÿ÷ÛA¼[H¢ˆ{®ðç2ƒê|½`“-é„4ž˜æŽuêåÁ4î$	“.wDD;°”Xß•æÆj›Eè¶"þ¼È­eèQnÜ/qo°öÓÜ¿nú‹Ò©ñ—{5‰O?w¹Ÿ-¯Lky‰°³ÛLQºÓS|gšÑ)†˜,°p–NÁ}Í|ÛñâíP(Ü€¼™$yT¡šƒT븑^m¤9>X…kº‚ø3Ö1—ÛÆÚg„õ¼_´Å~”_®™Ø€ee¶+¢Ñ¢È\Î5ÔUÖ6ù‰4®¸î¥…hý
†…Y”ºŸ§øPØk0¢jS͉[uÊyjsó­^<½¼C‘)æ	z”!Dþ£Æ‘¦ë"6©‹ÜͶGMkšÍ£Æ8;:̺tˆ')®¢$ÐåI
åÓBòB«¨'Wr\
‰#aە×S¦„AùøÉ}]ÔÈŠ^&¬å«œÉdÇe€P¢‘KŽ~Ñ´Ijöí("Jã1IÐèµÖ£ƒê[AJ§o²¿qÇyY·Ö¸¢»eÚ0á̦ÀÒ@ÿ^múŸ5·øŸÃ¬X8.ÑÐE‚‡crÊa„­:xúŠÿ"‹T9ÑiZ
¤¨ãŒ†jæÔ.…á—Íõ"ÙÙí±I~yƒ<|–ïŠB$™hÛh|ž%\äÁ%†åàÌ?iœC²9úo„å!ϧ¯&Ãò«2t77þP_â,¼Ã˜*,_–þ«©°¼ž
ð'¹ñiRYéªöå‰Æë©•1¤sëݽ$Rf«ˆÞ$ífàtëID#)€B^îÍ^Ï>ÎõŽ.—àà~.!Ó?›[„¨ñxW}¾;ÛÙýûüêâz=Ûù÷\Îv¾ÃŸç?½€?»›ÿiörwþúï±``.ÓKÏwYJsïQ·+jÁ¥ý7PÔú~hm3ÎQãÛÌ?
|00 ÔIG‰ñ–%æV°çÄ,-FÁ¼ÂEJ	_ßVA–›¨,Ý›N[2±rÖ®¸JMàŽêþªK¹DŠçé"ß(¨#`nsW¦BAp
ðM°Æ~Š.v·ªÄÀ<ƒX4€ø´¦HWÝý&¢ǘÁŽò˜-FÓ;À¢»øÄ¢0Õ²Ò÷.€0oáS6ù\o×Óˆ}åÁõs¨VÏ{|Fbë31ŽOGPËŒ~÷ÁÙ’¦&r[Oo1ãKÁ–£à¬a\Y¥I²MðMÆúκ²~„rµJnŠIÓÕ+OÌ©`¾þøôž¼ç ûHñeuz4oÙ8M´½t9MLÙŸ~Cò¯!ï=›}*ákÜË
R掮Éî)Ì'˜Ë6ºô9I;Ãל÷ž’|×8/§ŽZ¨rªleoð>ÞÆ‚QúVÔJµTø¬J€ŽÌmDà ÐÞwóÜ›\ØŒ}ó ©7PƇîz'šCG®6…(U¡òîN2æW©~jV•emßmQwƒ¨19‘½5`hol1r.©-¡Êê¶´>‹4i‚zXºˆÖ1ø*ZW‚iý¡õT‚h½Ös“Ösö’<+r	T÷dC‘nGî9*D–ºìgœ"‰‹¦ìE¨l]A1È•SµZzë2ûÙÄë¯$5
4Õãpk®öŸ¨fr²’´ÐJx5@´b²Ó\ØÁ%æè•ŸàHËa2àQ0}{7*ÓUñ^vK¯Ï9^qùûÄ~ã]<ÅôTIÑØp7ÝÞ>J÷äR§¤õD&ªrÃ4ktò±jM“‘'0|›K÷¯ù]†¬›:x¾¶êª¾Ÿ^¹÷yYøùTº‘2qõ¾©S™evéeUOš®^gèý0Û{úõ:ÀŸãl—¼ó±ÐÁ7µÐ`–üeËjͤAîûˆòÕÙyƒ˜X@UÕ#ávžÍv²·¤eè ½•R‡…¯•àË‹Íx'õdÃMTôJy¡9ë•óÂâUR÷^[~OÂDP¬gÊ£O¬ø=æKo-}!’½´³õãf
N*I‚t%¶œIû^øÙÄ#‘9q"Ú5n^é1º0Jê¨	®Zº'ÅO”T…œNnUKÂëzU'§o’¹$‘ê¤Øó©*D¨†óc8,ãW)¡ç€몮®´›ÛHÎ]á.cEæØ¯øÂHŽuž½ä4;HžÆƒ“#ÑwE¸rÞçÖçÝD=ñ´A5&ßJèQ0&©ŸƒPÝ‘uCþîÈ?ïÒî6J‘U•óY,ÂÌâÌGS¥Ì‹Â=O§6ݘë®MW2Kº¸nT2óÀ÷SÓ«ã-ýgS5Ú³)RYOnþ/Lû÷-ø´¡¹j>íëZq[û-Ó(ƒôDÚ\×Ð¥wK`-™¿åþž_µ'L}H Ù`äãÚxÛÊbí÷xÅijÜp…Ìé®ðè
í
ÍzÝ–ëWS&>Ÿ°Ý#Àþ‡>
stream
xœÅ]Y“G’Þç6~D¿Q5KG^û $4bŒÑJ#fgÖ$™-tC#t#1üû
¿"Ü##««ÑÂÚ˜èªÊÌÈ8<Ü?ÿÜ=æ·ÓnïN;øÿ={yr÷oãéÅ›“îôâä·‡OùÏÙËÓ{Ò
Á¥_ös7»ÓGÏNèIw:úÓ1Ä}çO½<ùqÓoûÍ~ë7ÿîÆiÞÏÓ°ùz6¶;¿y´ÝÅÍÛ]þë¦ráávçöó<Åys.×°ùbúÍ—ðþs¿Ü”Ú€\jšóýæo[zhÚü'Üû÷­ÜŠïÄ—|›z¶lÃûŸý%
Ðy=ÀØûnJc|tžÆÒxÒpã.úy?ÅÓ]èö£›gº_ò¼têiúS.n~Io½JÏ¿LýLv~J÷ŒÃæ<Ý÷õé×o^Á÷ÇéÆ×Û]ð‰§Û¸y»Å¿Ðvàz†4ˆ(màpÕál¦ŸR`˜ó¸¹”ãmo H=þ\:\9l
n†þàÛî¦ïa´p	šQõ`“7Ï:KÃüF™|xùHÃ|‘ž~“óëçiß2ñï·iºæ©÷jü©qîð¥—ð.êéÛ4ÊÔtúô\’â7·òðª<í{Pæåœ:ß¹æò-q …*í?Þ†4Ð)ãw’¾I­
fçBú»õû¶‡iïcþ;YÇ4-¡‡F”™gðd{ç@r}Ú~óUºeäùávêAìãæ¿áÞnóÓF¢K
ü´M¿FœBlð5Ü4â0R£tÙùI·šï¤·è[”µa穹ÏýMóU^ìèÅü-é8yRÞ%°!P?`exQ"®„Ⱦ¬çSBj÷ˆL=&¦{zçóvICˆJXÞ¢P…˜¾G'ReöRš7©©ÆJâª ìýš˜…@bvi:ØD^X¾‚b"ýC9é牺	۾̉¹š­üÜw_Q6OÒÇ™tÜä|ã+ý+O4|8/Jë´1£Òz–µÇ•Ù¡I½š-	V`O¶žeç–<ïé÷d(êBÔc^ù(Çh²6„ÅÁ=bfFáGXÐ`(P uÊJîœh‰!ýŠ‚Ð¹}Œ"FíÝl-}oöTìQÊÛ²2Q£Ö^ÿ"ó–äzplôÌËm2/i¦œ]F-¯„Þ5ňFgµ–"?\*˜»Áô°e¡)zZ@­GèènT÷¬ãµ‘ãѦÛìK&ÇV_&¬­;~€þx#ÑÒ?k`úßÂň²©¬^¾á€FαQ˜Ëj`¯’ªu¼"õÝã¦/âì"
_îØì™†$Æ"¿Æõl¶B—šòYüj-ž1¿Å˜QC¨@•lóu@SŒªîlªAC•´ýbL«Í¯VüP>²¤ÄË–}a„Z>î˽EÀôcoËÇ7åã¿—Ç‚‘Ë[%e:ìÃP«;ÞK}kŒ°&ažÔjTTÐ5^«™Ò?{sõêñÍùæ_Nÿ´:9ÅýИ҆̔éf\B-3±s¢+lÅÛ*ˆvÐÑùÅÆ,€Nv§ˆ½Ú£ò½GÕë$AóZ¦ë¾#œì@tCÖÀ-…ÖZ#ÂÞOÿïbøcyL5ö{ó—‹Æà1ÕØÏ×2`_)\ú-9!¬Ô×»eèTьӛËÍOãrÕÑz¥÷þ*]û/z¦UÖ•’Ì	¦)ÇéŸÖ·ú6ù׬ÄÆ€*û? 3ßyÛ:aÿµU~Ÿ|üvÛ6bM¡0‹ À⸉ý±‡'þÔöÈ@Ø»Åg½ÿèäû“ßNSôkÓ;§SÆq§ÓÁþ&7ùÞƒ“»þzúöõ»§'wÿqêNî~ÿÜûîËôçÁW§ÿvrÿÁé÷«.´q¡]Â}CÚnãD>ô
X[ïç&yúýÆýMWÏEÅ Xþ
B¤­¹(¥l¥
ò»Ôz¨sÒ˜èÓJç½Ôj€ ©øÎãóF;¾ÃJ/_-ïZê€ýúôS
î@Â+H,Â0ûá3ôuìøè¾~„‡½Ã%¶ˆðròcŠK^®¾*já-¬yÇÓÜtÓFÆ.f^Ÿè±çù>áhzíGf¡ÔݽÚ*‡üýÑ¥Iw•EÀíñ®è"ô€`1Á‘BÑ·`„Ðë-¢Ž3Zã¶M8×J!¬»£ÜjÌÀl5Zr«\T€N¯öCD¿‡—Í÷sWø¡+û‡ËËã³?ÝÙî^DêÀ
¢ÊÅËHW4OÑïÓVDB+#h4øbQÕ»Íü@¯ qÊ-ø²_¶ÞŠˆàÅê¶+™£±±k· ûpþÀ®öÛéŠ
ºsKùõaœqyÍB°¤Èr fÒn0¼ÂÔeg0ÆÜÕž¬Õ…øB†„w‰>ŸŒ…C;‘–vH~ca„ø¦0’c}„ÍÉ£ë\yrFÀUw“ž Ùñû>¯l˜ôÅŸ~"*ßœÇ0ø!ÏRÙ
2K–6ÄU²DÒL¼ãû‚lž·xf^y”¾©Ñ,×È㳪g¡xý¿œÜ1¢éÁË£Ÿ†(˜™à3&¤³Òú€«Vøk«óܰP	SdôK^Ü7´.0»Jn~¹ygXò§Øvîó8ã+ð¼.‹<Ê’/3
P{v³à`¤Ÿ§#³À™=j—³m`ø\uAógŠt\:òøZظJ$²…
£–­°EåíÔ+…B£Û”›eÄ·íõ´ã±–G<š£Ä&4)Fø^Ò·=Q€í}`ûÐÏÇãzÀ¨Ñnþt¸¾ƒíØ:÷íâÍOÞÕíÝ`ºz®vsú:â(ÌD½èddÍÜÅ:ŽO¨M–Æñ ž@N–n,£›ãxß÷€‰?õ¼†´‡§?$¡÷zøÉ{š&¤œé«q:Ö•ƒp,áÇø¤ûҋƃêqèP¨Àãݤ
ª°ƒCu«‚CWͨ)hVƒ7Šøú~Ø(:#ýV60¨Æî~ÃA»¿th‰š–ÐA¹H-€ú/Lç{ñÝgª5áÌž.V÷øÃ³Ñ“LúúMfc¾Ê‹–‡2¬úaÂ)aÛ#€¯eÀÏ)áÂhóÞ¯ê|è9X­Ñ5wòºö,¼Ù¦
2ë)¦W;t샵EX‰+ˆá]-x¥{Œ>èA†h4¼†{xÊ#—Áö3»¢uÎy³Š®329®q„cˆž×0LcêÄ%Q,„–³t(éh‘?%¨Â(ctNrØí…¸äý*Ä3…ÑÌcú®NØž|Í¢Ó'#–E§Û#6©tâdÏÆŽF
—	™(éÁ¤þ¬ùÍèfìïð²9pI‚*¥d´š¢ÒwÒy«b Àœê?ÓØ!Ìu‰(ÃÇl¨7aˆpR‚DaS:ÚòÉ4eØìYèâŠFƒ+€=y¢m…Ϭ¶jS”·ãÌ•	#ä¸/a&™¼*·ç5.]|½1Çoò f¬ÈP”//"`Y‚’dص xþ'],Ëÿd0yƒ©Ç¸6·¡}B´*’÷g£¬˜VR‚}Žó¥yî
 -}¼±Î'áŠ0‚Ðs®ÉÌÖ"Ns82¾Àþ[œ9ÔÙ—tÀùÀD”{[Ìê‚9™¹T_d£q/и¢ùoso
;£"•8²òqQ°òS£pçèÀÖByJ0,dy’”ÊoeÇwïrHb%EÌîh§eà	ÄÑaí“yÉòõCzM·Ÿ†uZÒ¼ÆÏÐÕaØ{ÓSPZI2‚‰ÜÄ‹ÝØoð~ê…ê¡yØ?¶
	ۄϱ
€ëlO+ý%T¡Z‹ë´~
Ó»åhG26YB‹ë5_ßsѹÏ2…ÌFÍj·¸âv¯‘0ü½Ž¨ãt¯K屌 /déÇ:…~”èÞyúilû¬—“íŽ×cVŽJ®“ V¢SÃë}1¥â¥íKÖÔ­2¼¶Ç6UX{¡Ö8QjÍ7C3³óÜô´€zkמ„}&·4Ñf6T*‰Ÿ{¦Ð&/¢ð«†ncstêz‹\]K×$¿døýNÁeâãŽ#M‘Ë8’ÍæIçl-½$ËhXÍ„&JV\ß*O-
"Sá
(FY=.Þœ}2Ø€„~c ®å¤ãW(7¿Âï¶ÈcÉ[¢Ö'p;Ðl¢rŸ˜Àð–\ÞðüíˆxáS÷tHóg»jà½Ù…ëç#
q&t×Rˆß”$Ÿ¥°0ïÒÊYÖxL0·¡¦L\›5‚;Æg¸*iQ‡÷š„_~òqùxÛ }…¡¢‡ïrCÉ3†±ƒ³Ã<\­l<&+FZtæžÑ¬‚úzlÒ|×BKì¿’.`º¨µ~Êá…Íxe–7š:›Ð‘¾c9Ž©êÙç$-“îîaßg–kfÝ‘«ìÁ/œ{M€Æq¶¹=#ñM•N‰)áWÙ0³å+Ö>¤ÙUE,à¹À†5#Ç
‘ºr‘ðE²'½j‰'ÛöS× /='lúË2W_o…‘–Y>!W&јDL,ð+$wÄÜæ©‚]-QQ4¸X&‹œ‡±L#WIU+¨	IFóÝÝ5™ì+Ë,Í”Ÿwó$Xw m\ò}òo9/À+?ÿQì‚PŸlícGX«¤J†£ç–d9 %ß!9ù«Â4(WÉÇòE®2¥,Æ
…A\ñ )Œ~AYd&t=Ðbd‚»Ð€ÎÂ=žåÒ¡çʉ‹Áä’	¢Úwû:VÈê5hA”sNon®¿zS;	xÞ¥¬)c)«÷â–7‰DIyÛNšÈeyÒ–)ÆÓbM¶¢×Ë+ds©Ún#iÞ
y‗œ§#0ªÌ—"&šäÜx%û’Å"’%W߈¬Fí Ûº·¾ÈK6B•ZÖ)¢!yÎôc <0žb½+å(¹@Ä.~&bIS%‡òÜ’Á7Q*ï)sšíœªc)5¬µó¨ëÆÅ2­%ß]__àc\Ôø&ÍŽ˜'Üâ9¡eTYù™sä¬ù{~ÊÁšKýªfñ½pYcYhÑ$|=f1Ø‘ÄÇ>ëoiß
’zÊèÃ{.Ëw.ŠÙñ8Aàb8”ÊòôrïH«4LU-g} …û£"º‚ÛŒ¿¦Ò¥òòä¬$ƺÚUÑàÚRµ)méƒíxŸ=mˆéTŽÞ¹RŲÒgÛEñîÛ%ªÞPq7EW’ô¸ù4WGç{~´LÏ&NÚ¢|°–¤u	ªM…Z¤v.sèPofRž;
¬üMìëk¡‡_Õ!éÁÙ¾KB[q"è€Ér{¥ßa¥¤&ì¡£>«8M¹(~ǸÑj‰ è©ÄFó¶œÆ¤°^ïáWšã'&m k昗ڌþç¯#Þ±¤#²)v(Ò…,Ó~(¡{¸WÛ\åVUåó»žðT¿e
ߌ¯·3­:3ØÞY Ã£°†«*·ž†Ê­“Rk•¸{‘»ÝÐSJêÒ]jH¹”Dƒî»>¯‘uÔ¯¶
á2‰¸ü±Éœbr•G}(–Q¬’…[º¾B€»Mö¿‚êªñY.;*‡Ò4ŽÄ0(DaÑ\üUý‚=»æ¤‰ÙçGåó_ÓâŠ+–+ŒgÒ œå 
8°\)Ùmì~y‰ãt=yÚ¤ŽÿÈœ8Æcú~gÿC~ý™Hòy£nýÌ©Âã…rÕMi>ÿmLDÚ4®¶‘PNÑ[
”3=–:D&޼ìN	ˆ¤º~Ý0ŠÀ˜:fšò)*ø©r•¸2kuñé*¤e!Î-!ö|Í9%ç$L°…¨ˆSW‘tY Lö@Í–&ä-¹Ê0”Üg$ân³jž†VÍ2g*Ï-š¶ªˆŽÜqðÕ9<ºiÅÖŒ ZÓ´(œgjÔ 9£ƾŒ}<¬|°·V÷æâ‘ 9óƒx$'™Ã²ôK´,Ç«e´ûChYš«‰Ó8-Ç^º»-ÃdBõ´säÄk±sý"–Y…D+Ý…ctUª|Mî£äe?_§éY}ÔÂ">'í¦@\ž3@ÞÚukšÍuÚ*ÑZ=(lž­‘‚@èñ‘bpwÖ'o¯±B0äSÚDìYmaÎèwýŒ<ùØN¥ø^¶Þ÷fˆ
ÔÕ!Ù¬øSg†,˜ÓGßõuÞO~¢(µÜKœT¤Ïj–ïí:ü¢ã*¹·‘ñDÕzw«3Ú—…ã%LHu,,V¦6-¾Wlåszgç²Áê§j¿Ý´R4ô&‰æcg¾•sýÆìGÚ¸‡²«ýPër/)¿ åQÝI%$Q-L9ïR#Ê\×G·†/#Þâsé³qõPÁi©‡åß
ˆ7¨;挩uˆT•GB|Vó(æÕd~ƒ·Z~ó>G”?ÊynöFé¼wôn®ÿ±¨Âl%bR×èbÂ*HºrÖ¬ Nšn4ˆÿ÷å$(>qùI¾§bù/×.\ð	0¬›Õü¿ÆaeE蔯D9ƒ4£ÉÊ7£Rr}ð¸ï:Aì‚e¬yªhw3œ,Lÿ¿WNQ“ÀTÆ’ÕÖ¨ïæ˜Ã>ªÎíÖ@F=R1k—,`s­žn,U,¦+çÔ/O¨RSxÌVŽl)ù#ä­”(¼ªˆSÈ´MÅÉ?-昩ÔÕƒxn$F Ù§úô§Çµ)~Ìóʯ¾³åÃ]&…ë1ƒÂ?}…bI3Zt!†úµ±œÑ>
stream
xœí\Y·~Wô#ÖyÑ´ 7¾Ø€l؉ƒN¼AlXF°Ú•µ‚¥]Y‡¯_ÖÉ"›½Gâ	’fØl²È*ÖñUq¾;ê?üÿé‹;ïþu:zúúNôôÎww><âÿN_}xœ:8ŸZK¿¸£ãoîЛîhòGSˆ‡Þ¿¸óÕ.tÃ.vÃ×Ç¿OoW¼1?§—ŽÏRǺ}Üý®s‡e™ã²{ØùÝgÝÞýãn/þÚíCp‡¾ŸvCûÐí§iNÏÂîÃ.âkŸwû1=÷~÷i~í#x-–y¢™>é<<™GèijÀ‹ö?§w|8ôn Nê°ce—ˆò@ãÇ4¢s©saÀYÒ7Gè‚Oã„Ô=Àèa†Áåùß-}?x‡dp£ÎˆÓ$Ò†ôÞ4yÚÉrï÷..‡>íC˜Ü²ÐŽÂË'i‹^¤éwO€†‰–øS¢ywÑù	Hò»7]À~?Bó=è·àöžvzİ;‡· ËKÚZ×ÏøÖ“´ã¯ÒÇÝ7°7é©Û]¦¾ð 8Ò	}&¦W.‰(aº{žˆ…áÒ°4çôyÞAxø:󿔦†ñÝvÏÒë8޾-0ÑÌ=âG /F¤H»Ó؉ÑD_^Ã[!ë9nÉîn[ï—xðQ„–¨Ö—ïªäÁƒ7*b‰væê+`ð²Î#úÂS$·ñ50<ñ¨‡·Ÿ…UI>òÂ0’½C‡r±gêön&úþžvé\vv¢÷x.‰—Äh}:Zš€Ç‰(?;œ óQ® ýiúC<€ç#²ìDº—ðñ©e/7â˺Õ',7=°¹à7vy¬ÛežÔ$Bqk”Ñ}¿f²_ˆz””óÎé
·Ðy0#Ââ€X æy‡›º,À0€0:‘#Çy+ÒìÀðˆ[*!À`é4¥½`ºÐƒÊ`A™¸×‰ wXz²¸ä¶3xE%+š‡SøI",¥*Ësš•
Э«Û'U6Œ Äa‘pÖõ ˜cDY'ÞòÈûà|¢¬=ãcŸN˜«}q3øì-¨|€•ÏE9¡QTÇfI¡—Â0#KÏd ÃkœµRv+Q4ô2ÚúdÉ@BEžªU¬øÃ8-"+Fľ…ެ´„/•»+æ$
‘®oJq;U1ÈœeÝ+jæQ§OÞëØzŒ¡°Bfúp˜†eVÉFAåšþy¡ŠÎ6Ò„â˜Ô&õæÂJ¹óWðÕÁ?½~zþñÒFýú¼°ÚrcîéôÓ{ÝçeŠÉÃhŒ“_ùZ[Ö3­z°ê?Ü9¾ÿÕîpžu^u¿ŸÔr©.ƒÍ'¨¢#`×7ôlpQ•¤Ò‚†D+ýýѨýÜžÌÖ„'¢}\üŒ6í{‘)¤R÷­Ø4luH¬Öb3&*4/Õ(­<õQ)VŠø”å>F5’m“ç,–SYýtnTnX:
æ„°òŽh(Ù2)£EƒóÙÈ‹O
‹Ú.UÌjÁ¸?àУ¿&L¥YÏ*/luŽpÙ¥îüÑ}øˆÛíõkíÐj×Oà2¶ì=L0DõÑP—Æ	ÒHnÁÂ4ÕX$gìÑÍa£Æ¿®=²aÁSb$ì¤t©Sm¹N‹£ùñȰÕÁeº°)a8Yüw%l/\Kpü¡äÃ	Kd›ÆE;»6o³âWbÑ6ÇÄ^·²Íºµ¯)0Jö¿t+¢ª¶£^‰1îȾäôYn|®OrãA›ï¼ÑÆ×¹ñ«Ö@ßÛFþtqÍ@_[Ó$§],íqÑwïèó7ùù3m¬T;5þ&í~O€ÄgÚøijô=Jóûécèñ¸æç¿Ë#=¤1Ì`0¥ÕÛ(}î{Ë8‡8o[×U¼;·‰1úç{•e–3qÚóÁÊgg%rÖèîK†€pPa(Œl²â²~ä¢ë{ž¥œ”8ø·`ÎsÇâ¼ðX¡!jõÇô0¯˜áQ• ¿v.X¤ÍÙ0bLbB
àˆ4à0³“mÜr˜.‘jð¨çx<àãϲ:ýZ}\Õ
'è)=Ò2»3NF±:W­Žå¥Y©¨ëÚ-1±[Ÿu•Cm|×=S"ƒhÅ´/1ŠY-Ä‚3û¿#ïœCôÕá‰CE†°‹‘|vcœ°#€[ÁLÇÛ`˜bQâD‰ß5’†ç|gܤÏ`D|'bKàËOÝŒˆŠ¯ Näóªƒb¨3öZvЂ(#>|€Èˆ0TgüqgÑEÜ2ù2Oß²ùÓËÌ4YNÚ`$+¾¡N”Ÿ—ë€.$jæ
¼$Ä+mêòõWrô
4„„Õ
X}#ÑÓqàò˜AVNè-2ö^åDµ¶û¦Þ°àÞÉ“·œùo·âò±4ãfPƒÈ‹<·Áò°û mxªË¼
À¥7ÐN'ˆddOí°q8IÃúœ€$ºi°»V|žDL¥çwU(ÅAVóp#'0.ªý*'P£h§†h}éùkÐPDÜE‘Ïe2F•Šäã—‚¦M¶!¯Rq.;^ÃBn)Þ0ôb%ÆQcÜт㥩T¬áæ›2ÂqB÷±»K„tL	ö”Œ³G=¤"·ÇR¿˜ÉS_*ºÌ26+~Aä«òO4lÉ)ïP.LGp‹gŠüÄV=1‘ïxᲸX,µ‰ÜîPáA"#€;R¼«1ˆŒïWQ©¯³ÿÃ~_‘ŠËéa.–‘—&èǶ¥¶p3²XärÎÌ ï•(âŒÖSZɃøÁæq/¾™V%Tf'ýìÔÇ™AH¦¾À„G~î›jÆOnë¸ûq@q­Ù²J?ú䲓勵5°¡Ë…ìžÕÇ¢AÊÀÍrc‚:àýµ­%í±„ ë¿cöB”»xïbµ
Ä›“Û¼
Çê~`àȪ­2!82°V*Jô¬ÓÌO¡™§]á:HFîV	a˜š4M†|›K>µagZ}iæ2쬘2íâóî:Ĺt/Ðòe¿&ðôêß:9’½yÞz%;1¯:”Àè g'ºÑô5æá0©†±ªulí&x5PAñ?çÜ5!š†o÷*ûvO
®™Õ¶ååaèÆŠGyXÐ;Ë€<"7qÞýºés¾Éœ¬èªúr_Óá¢I¸™M¤ã&HŽ7HŽÔQĤݘë(>á˜Ä$%Tš'DŒ'¿®|@¡fVŠZsÑæp’‡P[\Bfh2%O
AúEqÕHúsyÁhÈÂð«&õC
€.£,®p¸²&Hr ¹zÆ8UJ§òÀo‘±G~m¦ì8éIûÒ-˜¢˜t³†mß¡‚ÛhU¥…×Ê+“dÉ)†¦&q¥{~þ‹ã¼[ÊblÌ%«§¿håõ¿,O*·¾Ÿ[s>ÿÝ>Tµ×y{¿𧙦ªšÈÚeýA
Ä;å2'ƒÕzDY™*Nc‰ƒXž‹ì
–ÅJmWRD
§rBu-²üŠ(¢ÜR®k+¤ªÂdŸâ”¡ökÔ8É®²j°uZcÄ3!ô_€¦tër‰‰<Æ/¡g¸œb>å=»ÀI;ž@S•6
O
Õ£ƒ\ä…þæ!Ú3“~BóÛ’GZ}ô³â\ª=åyÆR8ŒtÉx‹.ÅWC
ÕH—Œ¯K¢n'žb™ÖRÇWùIÏœ
øƒd´˜õ‚m’ñÃm½LñíñCž°ïp71¥ÊÉÀiÜÙd`†uúq]Ø	ï2>¿A˳—ç
’]ÈI‰ìíÁ*µ¼Q
߬´]fS×J¸ÚóK™†p˜¼± bÒ¨ÊÇ+ã¡L•¡6Ã2jËÊ@Ë×¢Žvذˆ}‰àRpšå£’ïŸóÜ;Iú?Ì*CR‘ÔôœbGW¢á†+35bOçlÞªÖâ§kÕ’‚ôk‹SŠ:séjʼ?‡	(ð¾ku¿˜U®u©­Ò,"8ÇÀ§Z
³|qâe&xSŽß`'-¯¿}
ãË6…+^Ö ‹h¡Ú:Û¼Q³Ê„—ö7L
M±µ~”¢Í`T
nÐÙŒS˜Ê[hcb.嘃¸g5±ÆêD]¤Ó˜tÖLÓéT¦žð•òQááÁ«ã«a.vúž(Ð>¤uC}é®ßëMýÞMDØh‰K¼£É\„ΰî=ÔÆ§*ˆ—²£µ Iõò%l×ÅŠ¾g»=rJÞtÔêv.î×|×è“R"VŸÄœYkèÍëêÇ›ìpœJ)šrEq6xþ)gË),-UˆÄ“ì
‘žqUSå»2ÛcÿÊHjíGERc7îÄӠ£ñœ-”¦²Äx“|v®b˜XQ_iä¶dôªªOÁ‘¯4wF7qá-ªTLE	qQ“°v‡¥6YIëÀÚ1â‰$L%`ÎgßÔì
ÔÈ‘ûxk¶•)³jÒ“"ÕEy+ôÁJçL„	æ›!š…N~™(ÖK!usN•
pÉiÑÃé»vùë@}ìå²vñöd¯·´îÔÇ×o×ೡNÉÈ=z¡ÚŒ·½d€]¹	«3·Ô¿j m”Á¹ƒŸ–	«ýÇâ¾K¹Ý+Ê‘ÿ_¡ÚÂ"N´~ýGg¡O¥ÀHãLºå]¬å2.s	@®qŠÜø¦€ö|úìûPioÄ"ª•(Ê*â®…¬–Wß×>/³ZLòÔ©Íøf.ƒ+³çŠgSñZOs\±èç-8ü¢5æ‹®÷@ÍÊBuHÐ&7÷Ó0ü~×€€òŽ´ßÀ­ç3n³WÖ$‘vzAñ?(sg:JàÛÛ øa'^¾›Ë›zÖþz±Í{ó©ýo•ÚÕ-Û,ÅVs>$Ó{ãÆ«·ºó+è!ö„MVÐÃBQ…ªªÞÛxŸK`õ²š[#C™Æˆ£QÛI±p×*…RÖÛŒŠ‡R´];1X–{þÔ“ØÊ0yY¹S9G-y«iŒUAN?Èú²éè±nÓÑ3!¤Iop‚<À»ØB{„ÒcgïæÈ%™§Ê9‚m¼•W[žx‹.RI^HU¢›{ÊQŸæl휔?¤®	uù2×bîD¾ÓáÍAþ1Û@)Nê«ÇѾâCa†ÆDµÇI†ÿV÷ðÕlax)²áÚs…D+‘2,E’ º7^fŸÀ!ì1iTü-îAHê’¸ïÒ\Î%piæ–Ì©¨x¬ãã
Aga£õ—AH-lræÌ~1¨[™”C–ôfDíSð=÷£' õO
à^Úú"K‚ê‚6‘!¼à²®vR]´u6+¡¤ÔGdʵ‡‚ó‚4,“T Æ^w¦©R5^¥Ð6öÙÖ€Ø.TäÀâŸf~CŠd‰œ1оI´u	¸,0ñ´©.Â,ÁKÓ1”g#X¤}Ýê½½Yqr¯F)ÒÕAóZ´Ý4Wy3²@ ÏX‘-ƒ"9Õ@Ï\)~§½yŒ+ÿ
Ê~ªmo4Ò‹Ëi¼¬ÖÅ{!«LÁb;E¦é"tú¶ú½s9^šÀ(îLb4âìr²H³CÆ«®~Ÿš|-pL3 7$räò(ƒº”ÊPË­Y¾„–‰/•Ë®nòK‰{ã²–EW¿I¢`W~‹–˜Sµü!ú޾:«Ñúuû£_[ÕgË"V÷i2øµ
¹K €­ ù
…#&¿`±•ìný DXãH”H¦º{Ó%l6KãÞ†“wVÀâÚ|ií]s]­‘
g´Dß«êê{tï™È3õ&‹‚¯ò\yôðæ_L»GÚÕx°'ûâzìôK}Iﯺ‘L;âêßí¸âdò/xÔÕ¦÷:ýýÍ2:Nx©ôÁ/ÿp¢­RñRÜhòç˜ì–Ó5Mí~ÃÃ’âë}»íVN˜ï·:«”´„{à÷è¹ìøH…ñ׈,ÊÐMEi)Âë	Z7¯D)N8MUµ‘3\ÆÓãŒá5i³ÚÙSÍ]ÜãÐ2rQ¨7Ôj|C2D«_—,«±6ªÊÖ×øÒ`ÿ´ª”G`¢Èfú±°â,•Ha$Gð¦JŒ3oF¶5i%Ý7	ê&J
ãê2Ò¶ÞRñ9(Êýññ¿¤?ÿÁà’ðendstream
endobj
228 0 obj
4922
endobj
232 0 obj
<>
stream
xœÕ\[sݶî³’qÞ|˜±(I0IjgìN.«$í$TÑ‘%MtóEvÝ__ì
Ø%y¤“LÜ´“‰E .»‹o¯Ð‹US·«þãŸÇ—{φÕ髽fuº÷b¯ÅÆÿ8¾\}z˜:ø6½©ÇflW‡Ï÷èËv5¸ÕàCݸÕáåÞ÷ë®êÖuåÖîq¬ÇدŸ¤Wª°þ¦Ú÷>ÖãèןT¾[ÿ©ÚôÏãj¿Mïc×­öûºiÚ&£wÝúYå¡Ñ·ë¯ ï7i´CxxZí»õ—é·ù×ÎýãðÏiÕ­Ó«ÝP71-üp“‹L†ŽûÁu«}ßÔC;ŽÔg»)Ëy]ùõyšî:}x•^¯ÒÃEzÿ¿«bŸ6Û¹õÃôY ]ÂgÐó$½k|Ý´êËË´;¹ÅÖ6à¸Ïá±Iíéô0†ô
ðƒ&¢ÂÂpfKuJ{	©KX(Ôä¹ß™¬â5ÌÔ¥—=îíôS_¿¾….¯
iaþ
¯«iËP×e­Ú+Ï}¥w®¿8«€è>}›VØ‘WÙ¤.õ–¾L-é±k®	Ù»>®zÕ1µvéq|ÓÑ©1Ú¦½¥¾ê›³<"q!=\¹¼”iÞBs›~épwÔLäå.(I²«ýô³ëá`Àæ€×‰Ü~ yW¡ÄÁÙø)µ$z7CŸ‰¸&$gÚ,rçC¡oæCÄ÷WÄuøõFˀ͸6;L¸mö÷ÓHkbeþ)¿®|DJÈ´ýúæö(qÓñSC‡Ÿ£(åV\"¿J™Hª³GDøtB2Óô"/€/M‹ó0—Ίð©*¬.¼ä£ç=žoù ¦òŸ&7ã97z,fðЖÁFRÒ^PJº1Ò–ŽX®éH‹pø{K}7¬?K-ˆ}ˆ‚’¾GÞ+:€!ß5xê™W>ô(rÈ?d4WÄ£á•tƒÕùHã8όϰøìJäê-ÕáäÛÅàã*ã™N¨Á@,ÖDî-0P?±ŠqÌwqˆyÈӤ3©Gäaé¼oŠ`Àª‡iª·EÔÎùL\°VK(c³'Â
[…¶eŠuÓ´$ìÑÔ AÊKÚ†C%ãAÀèSÚ˜Á<×Ì•Q„“¢W¼VuJ¯`wß!“ÌAå!àsØÊür#';u¢,ë×/À¹)¹ÇQÁ;%’¹±Îè†Ò†@“ÁðÑÔÝë-’3ŸVAÄèAÔÖÞ‰¡Àg0ÖºùiYOÈúDƒ*„……tãDi"ÌÌ@c7vJ€à¨#ƒ{³Ù@@?Wöf4‘oIY¬¸ÊXa…R7
Á¿	Ò²2IÓlLeƒ•å-Ù`Âc0ä+ó$b¼U™ñ¢ÚÞ“,IbRº	ž!ÇRûÏ"]€Iê0µï
;6lÔz4±b}CVì²0‹`Ÿ°n4¹þÝ-Ú–Mné~\¡l\4ˆÔ“,R2•ÀCjS·fôhgôžèG޲ѯp(Qz’Ó“liw½2´éÛ°ÞbKóò­œ‘ù5U¤i£­/Cž=€Ï*1•Î+%¾d(|ÉçÙèø©iÝMm&Ü&r;	<ØÁH¨–°ònÂ-±§'Þœï"’H.ââ}‡ïŽè‘õ1¶.ÑIÁ(²R]"MÐ9ÒBnŒ‘¬—†Ãè³Dø‰c8µÂ~9j†È¢„•Ù>{ÉÂ$GûW[ÐD離¯HL]ñ¹§a÷“xGppôC1E³•ËhFš
™$Èñøpï뽫´û£	âªõ=Œ·ê›dnºÁŒOŸî<ýbõúåíÉÞÁw«vïà	üóé_þ”~<}´úÃÞã§«¯·:lÈ@mh궇iêd¶c°c	àyûZû±¼÷µΉ^ëF¬}<?ç¦*2k÷Û™
êzª!ä1,ã´LL,)9åGê<µ½]·dû³´}h–RæÙJbš®ïŸÄ>$/ÿ^iȧpûz‡!©÷¾Þ¡¯Y¯a?“{*šWFA  h/ç½¥U9ÙÙYT>¢þ1bá²c¤/ŠI’ÇfuÁš$’­Zíµvè	ˆ-Æ~b€à¹¸-@„X	pìz_XÎèfÖêÌ[X<íÇoJ¸Æhïå¸ñ`XlÁÞ Œ†ÞÐÆL?ÚêpåC~wh†{//>ÑÞDcÈüë¬OJш[­BGd NMpæÆ˜Ä|i$x ‚ˆdûy	`ÿƒêwÍaZ´µ5¶ ~ˆvî¾Í.Q<ßö(¦ÏDí÷mYðLsœÅÀô1‰f69˜Ô"3ˆú‰G]ˆEïf,ï)̵‹è)°%_À»qºÌsvv†ÚgËóJ6úŽ>KGúyùJŒ®a¬Åo'ž*w™‚PÙÄŽ‚›#ñL-"àò´|¶d¤J¼˜6çÁÉZ£¼5#³ã¬<`Œ±ä)(þ7)Ü“ù–ÅLLÕ@D»絇â	I†Œ­*ž ³8‘y
T¢ä…— .·“hr–ObNQ,ÂÚ>ˆÅ
ìÿpœ‘4²5c=g°utÖ[ÊKt.›û$8-nlÀèÉ]Êf@O>‹~A“
‰$h•©ƒ-ÝXˆƒVjg"C»‘	^@Å€†Ï!´ˆx%;‰49A6A]"ümõƒg.h+"©ÌÚÁ‚!?æ³°ûÊ/eÙ’;7Bf*†J.Ø›áéÀïÊ1pÞ˜Ýعø?’…ÊÐçN8ucbë³Ë“Ë)ŒZd[©(Ÿ7.‡ø—<é–y(Š»ð5$Emmfý>æÆˆ¿ãŒ«m&±¢î$›ãÛæ>'K2Ãr
…wÏ)OÍ=óO {vÆdºlüñQê0a;xöÝ	—pškt/1­rÆŸCÓãœPÁ§,6΄Ü_Jj´ÃiŽIZåŠÜ\Xßr°i)÷Z‚‹·4;JÜXL%r1y“Åá­’fƒÈré0àÁÁ°ÏØ„êPrµ9û´|ˆLt’HÖNp7‡à–d6º$ä»1C(}`­F›–·yÚÆNf]ЀIý¦CýIläZÊ’Æk´˜ ‘Ò(üI)g¬Í0ª´°/»5 öŽY÷ßjœAc&vwŠZ²‰¦pŠÑØ šdfˆþWWlѦ+"—WêdM2I]KÜ“Ð)ª÷)Y¹ö`oÏÀžÜ©×‹–l¤ÌÌ—ÕÄÏ#£Üí¢ùï4ô¬éi­¿8bäÏÒá5ôÞuažûbéHz‚3%û޳,Ù6üàDìCEe€M?K­²<:Žù]ZÜd×ÒBÉEǧw]$ånTlÉJûUjñ»èF ÉPPžt++LÖ’µ	©	¯Q‰V1Ì`_É#{Suó“·KãqÌÕuÝ]ºLzÿS
†.V¨`¿¥ÝZ\²–š²å‚δ…aÈJcrcö3¦‚9{ëZŠz`Îíœ_"™S?¯ÖBbâαC­ÅD9Ïýàì£ß×iר^*àtœ_^h%¸_Ì"øô‡õÒ·çùåëòòÕÝ=/*]ð‰nl·þhé››¥Ñ_æ—éw
¥4ÿH‹,“\•…?Ò»Rí¥¼F½Tʪì¡ÓGH‚ñiP“Ž«s+Z×ø_ÍïMfðE~zm˜žéå§Lï12yÓ7š	òòBÓ[HûžÃ'uõ?Íø9·_•ׄñ³hTó@žÞü°S°èh0A¡âúÀÞÐÇ	Ö¤àKªÑ/w}[¬›ƒÔã+4"ñÝ%C
&’†\o’f"ä+õaiUàhÄ6éNŒ@Á°Bü˪"Öç©KXÛ*Ø2–gþ]UwYZ©àEbF×»RDŠû=—“y\í²þË›oÜx6q_WXä•kódõD&ýæz®f¥áµˆ&ÛPWÄ2øú=d[ÙC=Þ¬Øñy®A»`ú=†Æ¹0_J)éÑ%%w_|K"‡â‹Xž;ü—ÕæYcâ0G¹³Ä‡<ÓðôMž`Qå¥ÒšWz¸÷ ¿¡æô’(‘ö3ÄÒ±»@û|‰"'†8¶Ð"ëåâGy£#øSKC‰ ÄV¥9t8f;è÷mènÔz¾ó[Ê£à0wÞüòx©‡û¿“ÇÝ•ºBÁË¥—›™”³²ðªâëw7ZK·_-i·ðÏË,i?æ~àx*Ž ïâÔMÐÜ»Õð{‹¿Öa}ü æ¼]þÂ0™_¾3«ŸdÔsYÊ–Íý®wð,®’7íCï²ñ
ò—ôþ˜‹.™xÝ·‰’Ú®»¶õãÚ'uß&PìÃúIÕÔƒk†¦M–\ò±»DŠky£«}3&/Ùmì:È!'+!¾ïäÑ\=ôiXXhÒû®í=üûXûLÂ4mvƒ¥t1Ðö|h{ªãm‚k1¨닎HIÍ<üõðKÖ¸OÌù|ïð£ïmÎM"†Ú{®ƒå`S"$囟ó‘4%ܸ¥~+SÀåâzÏA³¥/LÔg>fEL‘mìUU¶Šyª1÷e¼GÓ:?.(}“GË¡L“v	 ‰­r5–‹Â9ZLì˜ï&¨‚7U¢¼œ­¶S|9ÙO;°¹þv'÷í,TI2‘sCËÕ+鯵ºŽ i‡lºPÐWÝN¾byƒAgaB×7ó\~KWäl.?ŒKyü@Õ;äña3 ®FãNò7a(¨ãÖB	Eº”²1ʾF(jmrº².Aæâ=™$™ë"ÚŽö’Jg]WÓ¬‡Éž9¬!…ôY3Êõ’2Â%Ü·À‹Ú‹9݈ôÍP»Y롘	¾ä=Lìù”is9P¨Ë¸Ú¾MìÂéZ~çm}žxù%WÊi‹1®)	¡ò ÞÝÍëc¤ÁZ‘–+3QÇàM÷¬vÓâüéBvp$[p$Ü~Ü¿½ï+ÅV¥hDM=)(ucºøé›NÐ/¬ÚÄhÀu€û:_“¥ÜÀˆÅú¢P ËmG…l““ùUÝrï¨Ñµ)¹îª&kÒàùfÙuÓ¤,–­Sb¡Àº_Ú)ëøÎdÛ³„¨häûC'	`¹û) ŸÕÅ¥¡·ƒ¨+*ÅZËétïðÄn½Hk«	LáGàZb˜Q]¤]VFò®®ò½½O*¾c'd-quK–/ã¦-s°ä½æ·Ö‚éÂÖk×¾ƒ×nZWã¨Hõ”§Y<¹D,ÕIñ’þ#ø¢•[ô2Ø)ôw6©ÚE–Ty9«ÊÝ2¾¾¡{’cV‰™ùØfˆdboÏlIEÓ¹ý@§]²bó»Î!g«j¼Ñ‹"n5ltw"¸nˆVÀ¯—Ùz22±¬{ºD*òøEè2Òß·05—K¸—üÈQ§cšEñªìð$ˆzˇ™&•:¶q–ÔÍÕ=,6ªÆÇ#¥ž?×sЭf#ƒR¬ÿþ’„®:4Ìj”|'ñà.X™îÊr‘¶×³©öß*­ïT@bã_dj>¦]Þ;˜)Mû¶B	q-FÛùñ‡=´©þó‚´”7#2ÿ%^úÃ÷Ô’èëè„k)2	Z^•­u Ð‰hâ‘͘ÿ”‚PëÌbo>û6TÑéôœ˷f‡ÞlµÏ.ËÜöÀ¯£ÚCQV¤iËõ¼=1úeðS:ÀŠ%º† c«*é&í´¤yßuŠ÷‹7¤éÚ,^ËW÷\íý¡–)òÁÚAªø’ÒØ|!ìë½ÿ‰3±dendstream
endobj
233 0 obj
4800
endobj
237 0 obj
<>
stream
xœíioǵŸ…þ~370×;÷Lˆ7qQ§‰£ô@SŠeÙn#J±¤Øþ÷}Çœ{PT,9mQÉÝ9Þ¼ûšWC/Vþ‹ŸÏN¯Ãú“N®¿ê6r}ˆÏu›ôâi·QJôÃàÖÖî»sÞ©õÃNÓ´oº…÷R®—iŸâ4Õïx§ßußx‹ƒâ.8±žóG˜#U?þìh ¬l”DpiaE!`ð ehø%´ÅJIXGÁp…«+‹§÷ß,Ã`¤ 0âü#m ˜çœdL¶¸ßúA¯6jè1zèy8ÁÿÏáÿ9ï²Sôã`r–Ôëï;i1F®ßÁC«™¿Nƒ/`{ÜóÑáÁ×?®‡–(
€ú•pfè­_¹A9üÆyøøàÁã'«Ë×WÏüy%|~õ)|<þlõ«ƒGW_ß©XkܦWÌWx¨38à)€L'C´
ß¼Z¿”áQ—‡Þß=ðRÊ^Ùø‹Âc€b„W0¸ß­ÓÏïºô
8Ü{‡¾Dª<‡#›ÀßñÏUfxX¾!%¢Ey¦,ÎWHYbä
Úñˆq˜„Y#ƒ„?^#K8’›jØQ§\a§ñ;TÞüĬîmîX_ìDAÃ{ƒò¨	„€ÑË1ø„ði|‚0 û–Š'YvQÒ`1XøóüìÑ.†5ƒw‚æFHÔmÍ¿€~ÖU"¿¾ßœj„>ŒE½‰Â›k+86èT c`Yl8ø•
ƒÄÏ;“G…°®,Ó|>âOTÁ@ÝG
¤¥ñYVfx¬§а ÖMê~YFKFâ®$á¼Y:P’Ö|,OŒIÂáéç'Ùrá1÷8˜ó¢×à`°iVŒlÍp0d®ßTІä?)T”J}ó“*kÇ8)ªµßIÚÛÐê½dÕQm³µEU­êÄ4òeÖR8òñƪíŒ'Æ—¨Ð’9õvv>㳚6‚÷6ûeJNT×äg(]æ‘"‘N ‚I‘˜à‹°¦B#YEÚˆ<ëi6Do-xTTЦÕÐ4
±X»¼êøÄ?às>ñ÷ø,/xveú’˜ï²Ù9C@-‚kÂOéY_ Ñg¬gÐj‚#?Ë62ðÉS s—œzz‰iRR5FŠñÛŽ ~Eà ®e Er^i jKæ×³¾C³š.„Eê„’–-œs^¨]vX«!Ë‚ÝÔh‰l7ÒÀ\Ã`‘˜&qbй*µµOóÛe<ðPì:òTVÛø†TÏ#ßömÿÒEÿûOÉÛ}šüP¹þW§˜1É£yÓÉÈS™¢ÈA6dxŒ&?¾HœŸÇ&޳žßZ4*(GlA%‡˜VA˜¢q¿—>}Ec¬iÞµq‹N‰¿”Ö½+üÅLŸ&>C/¾…Š"%ÎyQNÙà8‚÷eŽ8Ð ?™øN›´«KÐ=MØÔÃ@âýòh’…Ãh[ðbYij”´¢¡dRP¥â%ù®S¥rÂÊ0r<©˜mvŒQ"ž™%ҹİ¡ql+íñš‘˜!‰)!—”–Y¤=*Á 3WG{R6ŠÐ&zm™êp80n‘èÈ•~HÛ°p%]âñ5qi1@•Ž™Ÿ–@NëûyKך™e«PŸ^eÉÒ¶í¤C2³¥”®bà±@èŸ[::i^ä4Ó¸Dw	+Ú‘ØÂ3Ñ‚)1‰hEþQKÛÊ¿ÔQ'ÀkCûÏEi
$ƒ¦´"#òÛ˜c¨rŸíˆ?Æ"c;ŒE0η´MovùE×9r È>.t§ðêÁ÷R×ð¢^ù–ô
 Ø‘Ò}S”YÍ:ï걞HÐ*Î+œ^	"©i~œÅ¡ïbƪ&ƒ<ä1A_Ö™¯0AœŠ`D ö@EÄoP,ˆ‡˜¥þ?)§ú	3üA–¤Ñ8’M”"ÞÅhÏ’ðÓC¥+¥SÒ¦6Cüð8?$¾c.©•s0›1ü<û¢}Ô@ä›!¦ü(¿>oça…
)z•ßlîæàEL'•‡•†‡4ªcõaQÅZõºM?ª‘žÞç‡Wͤøð]yxž>Ïß ÞÜ`÷‹¹Žš‡ÕéÓ×8K+O¹"ò&SYºÛâ×בò‘n…__ÿ÷òëvŽÏòÃŸê ´â´üÇŒŸÿ3(x"ç¶ßŸK·YµžÞ—noÈ¥µcýŸ­U+²½ËÏXWŽ¥žÍñäQ
"à” +üó¼Œ|;·{‘¦£9
ü,î-“ÞÎqo+¡ék¥‘Íèx(’VZÕîÈ)ô•Jž`¼?DqM¡’”‰÷ŸOÁ•jœçÙCÉ*Rvj®¨$ÀÂ1t,t¥ò@åéÉ´ä¯ðuô¡/cÀˆŸœ¯Øhí£^Le'ZíBŒøßRX„‹)×\@Q¤¼Ó‹E”h-hÅ+LÓð>ÚÔÓUÄü
Å})Àᕦú£æ¤O©ÐİO£sá«h¨ªÔjJ4i”Ê¡p88€?™“M¼§)^q‹ªJET*1ÂeÉìh
S
F9ýƒA\sÖæ«œT<øÄ‡.ÏbꓳL1£OSHÇ)IôëR¾Û¦g)L|“a hKRؘ"ÀŠÓrΆâv;¡”ÆTmªæ¢ÖT’¤
ú2oº\0^
ò'Xrœ™BA à?kËkÛPâKñȈÓS¾,B‚+çTFÂ	’@ª“¥JÛ9fB†OÔ|¹ž›¸«åuƽ›äÒû]޵®Ï,à¦:
i“ˆÉ*e³nk8ët‚ôÓT‚p9/ŸSò’™`#
CNÙâ˜P1—Ф…‰†öA&’"ócE܆+İDlÉ5zNt›™ô8ãZr	6¤ï~œ¶«R1©¡vÃB¼0XŠô	§-ñ¤©cmÔ°¤2ž·Ø¥©"ØÖüZ{¾‚“îK+XµM+¦=S¹bÕ—3‘:³èÖrT󹨒¼`eò³SQmö·52V)—ÈÕ†(sjš!b•7Ÿ¨^÷*° Õ{d*^t)Ô»LN4¯p•ëjpãXÓRÚ!Õy×1Ÿõ°‹/vMpóKÆ·¨mçœòÖ·šM÷+GÇ’¿Îû•ºW„ö&û¥ÞÓ·$Ûôz®x´¿©´!)NE1Ó:«ÜkâgôCtÏ*-ál¶W°Õ5¥ŸÒÎ3ênKîáÔe©-–|\„Šîá¥*íj¿'c`IsßÔú3¹@ΉþZ²ìè.^SÅ>ÏGf¢ò$cãQz‹ÚÎpÅ2·$U¯¹›5h8HL³7šMÌŰöP‘ÛgX‰g=:›I£J.DÕÔø¢Ï"W¾ŠºrÐj·¾ž—x×fuæêŠ’W¹Æ¹œgò‰kŸ¼‚ÜÓ5ÞGP3æ¯h—¨”"û
¦uYwT?Ø}Øáùgg:q9‡nz9
PoÉ0µö§ÜX,í-y,»2>/vëðí²=ú€Ÿmnb2iõ]䤉Ø3ÒtBZÅ1¿m#_;›»Øßh‰üm—dY+̇‰Ýyú}rôÜ´]¢:Ö4Ï‹ªÅ£Þ–ï«häZRƒl¶¼¢Wû‰xÊ€„qÝ›ºOÇçyÇóm/Ê–\¨¡•;T1eëßÄÖJ%|вäÅR›GÑïÿ<ö+ìè«t[«¤¶wÛW©ìaª¶’úH!wP?³9T‚FrÞõ!$†^*4Yj¦ŵ|ŽÔ2ZúË­€r
€šHí^½–Aºrðn”»þàK¶O
Ù{7V‘wmýhÈ»lPžï–]c/ÿ7ò_¼~vKAZ	üÍ^F˜t
ê9gÅ#Àj2 É¤ËMbÒ†Ñ}d
Ë<M°´vb‚aÈ$ýSÙ,élÏ%2¨Ò
SƒŠKìaP¥Æ•¦-JêG%çàU'×£vTJêH/J&²Ðѧ¶0
N¢û,ªQº¦“ÙYÆÖÄ”?Êö’—c·¼Ä^ÑH†q*®š§¹ëpwæö4’¦é9;KØž
™˜û\Ø·ºÁ´‘aèÇwv1„N°j/lIÍÍbô“ügšÁ©æifÂLš­èÃ	¹èNšm#°4ì!Þë$ÏÈÁãO蟦èr\,¸‡3E
T¥1‘nõnWÜìTïdåªƪüCîƒ%ùëÃ㪂)½Ñz!ìr£|ª>¡*@Ÿ0˜™¼-ÂNxü|Ž ¬_*PsW“&ר¡Ìgoݼ&Áã‡~&ìøra¦û.giü0»z–j"päJÝŒTÕ̶»Å?Bç²ÄyÊçæùaZò3ê·œ²q©rÕ¬‰ÀÌð^)ÏúÆeÌö$JçËêŸk0bG00Û¡`â_ÍqÉÈǯ#°´ß=<½šjÊZóðqZÍs/SE?D Ï:UU”¶%Áƒù{ÜI1mr}.Ý­$@OÙuÉÙx®0¥Þæ—Õœ™<-U_–5n’¥»ÂÒÚ
4©iˆµàþ™RpâJh-󜼣
™ ‡¢Î'¸ŒÛÏ´«ÇJѬöà,ZÉ“Ri9H{Þ«tÐ~ZêŒÖŠÖj˜¥¾å݅ʼnÇ´wJPê­Q.1Mxì
3_ñÖ¾N}¦ræØÎÜgfI¾IUW¬üº}*†òÆ÷HŸVYÑ*tgþq•›¹™žÜ*„|¯2tÅ4‚‰Æ­LAìä¬x,¬ïÉf…–ÙÌeC–uÓž¬Ü°“Í’îÂ+ñÆÞ@/ÿL³·ÉÉÈÇ(f˜IXÕ׫öTG^ã°Ç‰beç7]0µ•kï?Ì\2Èæ6™8Bå>±Q
+u»JW,4º7k¼†LžîùÒÏÈJí¾‚‘®xìꑈÇh¨öd¢ïÑ;S+œú‚}F¶tå^TBvTVdsòuÒ–?Wé’7M¾î®År.”úúàß&•endstream
endobj
238 0 obj
3878
endobj
242 0 obj
<>
stream
xœí[ûo·þ]ð! ?øÖÈm–¯%Y 	Ò&A^mÐT†Q$E¡H–,D>)’e×ýëËyñ±»§;Å)êEùŽÏ!gøÍ7CÞ/‡C¯øÿ=yyðÑ÷þðüö`8ûcg–E¹>‰â½ÿ#ÀÒU•ëNÃA6
¼·ž¯:³z‘ð	m%ЪOÞAYÒ•£?ÏSѦӌ¬°¯Òg
ðùº×»Á´/¡1v„ɨ2Ïè‡ÕlÇW2K¡©=A0€ÞGÐí2ÍX	{œ¦¸-«`Þs‘º@»˜›Ä•Ý;ú OÃ!±:"üýÖæN+4|0*›ƒ¯P“§ãð¹BðÙâ¬F{I`G±XÐ
LC›ÕŸ²6¿ƒuÅ8F¤1æ߉¦¡M¯}”í/.$}tJW.ÿ˜I˜M
¢ðoiÁ÷9áBÓȪ«Y¯Ýw©©¼‰,”|Gi’,O>ncØ„„ÆïÆo2P•&ÏD¦ÆËˆÈ{·o–â«f¸`½ ýEnóU‘ñÛ\ø9z"4ôÁÌb\YPÁÏjö÷0–2–ð­ºð±”õfFclâä3R†©‰
OY²“$‰>Òç+¤Å©¡š£Lp*\6×ÂX¿„Ëñ˜õIµY0(®ñËœÕbøµA¿S¨å†j1è\°›ÁíÌ ˜~ˆì0uÅIÏŠK»^ØØU·ðeãÖ Ébäqå,Û—™FÖ	Ë~*D89!LB£D7†¢:ºtÔxÈæ{ƼRlÊ$¦±ÉCbø[‚Æäæ*ÕÑà¨s—Ë1Jåx=ш Ñvvø-g*Sáí{
óÚ>ÞĈ&WÛ5NH4²L„Ìè’ƒ¸.Þ×Vú+®ê€{!Búª‚ñȃ”˜ÝXÚÉ·B@´Äè=-fÙBªà™”d¶™í¶Ú×”x­­)e»¸Äÿ1懣ÓF¡ÆjÃæ]rà†¶Wç6ÂØÅû€G˜3Ø>só«¶hÓ ²Õe“dº§È–F¢ŒYN8£QQ*LhLé'|vÑ)Oë~”ÕÂÖ“©¡Žª²îŸ2§ä4ÓCl(u,·’Ÿª_]å,q9ÁDID8B’´%¸ØMAÉSJj¦%Cžf¢%MD<Óï)NY"¦ËÙ1Ø‚à%Cg‰ôp¦såè[RÊ~ÞŒ,pyÉÂÃ;‚£ßÃähòrÜç¿à7dˆâ}bœ7Ì.Ó.UñþŒY.^›,1Ë÷ƒOþoýÓÆ¿ßÜ3îÅ=?Ã|¥À™ÛA¡vš`ÛE,cBW"iNüÊǸµÛ>!²óx4ÕN:gCÂTéSÈœœÑLˆéUuܯ:Sñ"„‡sv[aÓ¨è¨ÔŒsüK+ž`Ÿõˆˆ‡}Q§E)Ê«+¬³Úæ4ä´lfÕRÒº“S~Téˆ'ùQ3nƹN–3ú¨»Õ¿™ñ¸¦†ÿ²3QnB6²ê.!]<âÌ,ˆUÄ›°f 2H°w·šèì}®rö?uä(³®šÁ<á	2E(ܯ
(`Èû
‚2dÉLÝ/L©Ê&!NUËw$VY¯¤Ñé>ÈôaPb>›b]縵[ƒœÏV±Me@ ™Š“·æÇ+‚ÏžªjºÚHî£(ÀÕé {¹/›­©õ>rTÁ©¡œÒÚ+}7Ë—5h‚€j¼dÍÙHŸÒA¼Î­«ý¦àš»V£À¦£Ñͦ»v»ÕËÈ´•™å£tÍ×E#¼úsºdžt’íþy—߸ÈI3eæˆä„7}“ëï¹$ÍAÈý+­7bÜm}tÅ×J´°–$$ÜdÐxÅI’†7VøC‰Ö l@3|I,GOóËÎdÐÂP0:¹Ì³°·•À¸*cý\{݉8¹ø´Øåâ
™Ï®‘œ—³m°ÆpÄœéør҇Ú¡~L$¹ ÜçÞÜ6¹ãlKY•y?UmWu,ÿ3ß[.9Î
>æ—¬‘1ŒŸ§_îƒÎÙ/åñùÈ}¤2/+9‚ùà"ñâ%Á‹¢1Æ2'iÉëïtwäØMü \”§ªXÌø‰9™:MînSsˆ¥r$
Mm—ÂBe6KÕ’2S[.$®ËÄW áÄMÞL¸lJFM£©Z¿’={˜¡ä\Àð3Úð1o-IŠ%°+•—éI5„æpФ’M|Ñž^,P¤¡5`Dê‡>ØŠæŒ9Ý7Ì‘,u0÷1ܽsh˜>ƒdܲaJmk˜:(4×߯0Ë»Î5oÄüÅ˜*?4ºÇTåyOîB9°Yú«ØÍ× )1¨;ñ$Þ!¨ì¤Ç&R>Ÿïä‰FJîʳ]^^œJ¤·ðîT“ÏãGN°D‰_”-ïp˜,¹úÎohÈðÚ‰c§m~uP=ÁÆ­‹1~ì·§zåÅ-A]èÊt!Ø0fZàAvǰ›nîxñjmšI6,
ÌȤI¯QyL?e¿0øÊ–Žz§ñ™¼ÑÆöü bñU”pÙ9g=ça_çÙt”ßáÐ
Á7ý`RÔ&‚A
å·òÿ|Vr‹
0…ÏyðSò[0úk60Û‡ êW}’Ï,šÅytëÑU¥é«Öó/™À*9â­÷çð(\+L,Y[Xуs%}y™?µ—èy—Mu‰îûɳ¦~šæ<­»ÎK6mšæ,§àÝÒœr“V÷“ä&6LZpºpÇZª©Êã­êEWÉ?à¡Ò,Y“¹;ê6Wi‡*Wé’ÿpM&SìR&®l:¤*Ìv8øÖ¦{?ª4E÷ÉçGÉì„\I5(!@®Þ4*0cc«ê·ðƒŒìà!¿‰#¤c@±>;åQÉ•6«ïA8k•›‰aµH¡Fxö!Ã<뢂Âj¼Za ëœÔSq®U#6•9Š0weèÒ§Œ³)ÕE®[X Ñj4n)
lø|{pô䇯M[¹ì£Ô¯²å‚ÿ®½-ÎO.`ø°6¹ºêrPà9µ!Iœ½íBriܤª¤˜m½äC‡7ÅéÉ;1eé(ãKô±b;Kï@ÓŒ9¨‰SÂÚ<®¦$Ö"ÿÛ|‡üÀ$¾ä…bF¥!:òÑ6™•æ›iŒLؾiÌyC=à`UqF¹8–Çg5¢æ_jÕQ¶?…Øõl'>G÷0˰p	-CìaøåGªPÔêª+ª…Ìß–è„­Y˜Áï MïÖŽËH“(iÙŸd¾ú˜›ñðöi’Ô+æuÒ!¹	x;bª‡ü›:ÅXgóxÁmDÃ^V‘k~ÄAóð~1Nˆº5a€²9Ÿòû™’cñjJv'¡ksß̱¸àŸ@Ôâ?ì…yòÛ‘-–&!V“î)G;yœ¤àwÀ)ZÎï£wø3›mÏ0öTdZÚL‰òŽ¡½M*dõ¼ïEA¯ê¡}¨uҼѩ‚²Bg¹C¹‘¼,¹…­ñõgvsÈ^èž\<˜â¨rJC™üµV58¾Ö€D‹áò`QY
ƒ’”ßgŽ6Àµtý6Sn«‰ÅªÔë5a°¼Éˆ¦Ñ-€32êúz‹•üz›×¤mŽé`ëèRcž¨¦o'wµñ°"\«[ÙB1ºb8|ãP/]Úà'v$Ágx^×Õ6:°É†´V¶&D‰üÀ´>Üd°¢Â”"?¤j4V½½’ÅÆ*†±ñµ„,&t™$5Œ¯ÕVÎE#9\¸wbÀÈ6 m%G&ÒäE½Á-¼Ïè0ÍCû(ï¿È	†DêÅòvX²u“‘l«þU¡ZÝŸp)¶T‚öj¨‰Ÿm¯ù·vK—%‡ÜÒ0XôçGIÿýH퀉endstream
endobj
243 0 obj
3950
endobj
247 0 obj
<>
stream
xœí[YoÇÎ3£±oÚ¼£éc®IŽ­Äwè8†4)S‚ÄC%ëß§Îîê9¨•l902wgú¨®ó«êÚ§›¦v›ÿ“¿Çg·¿î7§ÏšÍéÁÓG/7òçølsç8Oê±Ýæð§žé6½ßô!Ößž|¿
U»ªö߇ƒÁ3ú®öL:óôWù	§5‹Sä{ÜÁ¸ýò'à™=Ÿ®ù
…$>¡ð¼¥ç47|Ï"Ñ	K1aϳܮ’œÁ@ó^‰¸·›QkÖPšiýã
¹îGX5:U؇Ê,f¯HÑDÜyAßb¹Ó•ötðV)Äi—yQá,­2fÜâ2ö¡ªð\Ǽ`þoLspäq: w·qÙß”Ô!vÊ…({Û¡™#3¬ì­Ãç!~ (O+þ{Î{:Ð8ܤ:7W¢Ê;Òã¤ÑÝõ*{âà	m$ÛÃø5‘ÑÆU?¢»Ïê—(:ç5®Sýƒï-°ÐSZîØjÍIb¯î:ºüöèT¯ú¤Ü¡EpÅ+1¦ãDèhF‰\A2V4ƒÅàAšär†`àuòZ¯*5½0t‡Åß©´DC
kÒ¥ÀǾð\TNT§gµiÇÏ|O‡ÒCQ☾:xºOÝQµ8|%÷R*æ*©Î9P¢÷O«s­l3'õ§¦¤'É7]eSËI6à;²u€3ƒE€©xÔ
º`E?fÄñHX&éêÄ}âÖƒ¥qh=~æh_ðÆ‹¾†St7SÒ˜dLéI:Ë)ÏD³{
]H|Gžª9dÏ=±²‡£±ñ޵ëÔ~/²‡Sõ?Íx•íÃxÞȡȌÏN‚#?ÙÏ=˜Á™­óâ·Çc€œ¶ól©q$ñL"‹D¯äãÄ—Óv¨GjCnð
)Ò˪E$ÕFqá⪌°xGþ.Îo¿«ÖÍÜu`(u0fx¶î$xØÆ× TÄYÈÖiƒ¿mQº‚6âÛ¿*ψ0*‚Pç	ÿhPCÑ&MN ©5‰ãWç6 4žäƒ‹qÍm°ÄFdPÉÕàävQ 
b)!1}Wº%Òî¾ô
.’;Yr2]:\	oØÂÆ’ƒ	]‚ÕÃü”£;C:‚®!ª)ç¹'iÔõíJĵ¡.zÔš2Ø­baÌb×c©Ç¶õ¨˜Fa@:üôàðÖ÷îì Ak€8Ô0@æÓmãü±ïÛ­Î; Âh~¡„Þ ÐÀ‹}DÉ@®‘5‘Ï@HK=C6õ¾õ˜9V:Lwbí"øYª‹ˆ
@}× øAoûQ2Xžá3T!t‡ƒ«[È~Ì:vÓ+ÿßw=ç£|¦¼o>ƒsuˆà˜àÍŒYáùòŸ9誰”>zèýDú˜Ò©
eó!Ùwì>´Û7HWÇ’†Ÿ!?QÕ
5f$ÛöEÚÔ3„÷?㶢ijHWĵ¡ÙËÀØg=…í¶º”Í¢Bï\ Òù$£[ۺɿÏ=pÁ$韧<þ›Ø5ä·Êa¥~O4ªáô‡Š,/åÙL»ÜÀîò^q,%ê!\wã“W‚­8EÕDŒ—å¸	>ÁÏ’ 
œ—e‚ƒÜÅíÛ‘>fuJžöìkÒ~T+Œ¦ˆ¶Z‚_úø0	¸Šð3¦pôEd3Qa`hÙë•^Ov0Pö¿·>y„mƒ¢“ªÈ^}îžÑç9£Iœ1#‹pÕÐWUYp=$Y‘hÄEºHøèC>&†Ã]’¾Ë	’†·6^—I+Þ%“n{3ÇæœMœE!«DrÌR‡^« ^pnôO܈`QâÖT1eÃUò1†'ˆs!€ë¤ÜýÄ’¤¸2pŠü6•2І3+Þ|R ’ܹîd„4y~"“_ãä>GK¬‘Ç	éÄÒ$¡ÆXV>©Äo4ã¾/’ò)F!XÑùÁÔpÎd`¢ÂYL¿”ó’p¨p%«ŒBwÎ?,²¾œ²„Ï´ñUªAjZMG.ÑÆ¢EwmiÑ¢&¬°©(fs$mûÖgŒX.rfR®¸L.PýcjÔaŠcšFš8s]“²Î´Hƒš„C&ÊF^kÔRg ©¦2
pRÔš…zF”ì‹Î•æjEàdOc¿¸£w©Ï¨®Ñ¹ã%¯&æ¬-³Ìs)ó¸v‘b‰st°ÒEYƒ´Š *HY}Ž6¿A‹Ú”¡‚*ý§Rö-X.~%øžÖžd÷¬l:!‰1)*+…Q†}Š^k붉¢óó8ÚkRæå]†>†RÎV¡³¦¤"ã D4À8œ	úÉ
—µ§TÙHš–"hÀThê·nZŒ
VÊâÀ¬*)V+e9SéÁ
 JBêrö:	tú5gR](oH }ÇLO‹=poÃ~¡Iûñ“—ž¦‡óÃLÊeF=|Æ;ŸÒHï獵1´åO„¶¶áÜæVz}YÎÃÓm? É†¾¡ERb¡´†ÞJï—1òðõÒä‡?§‡ì	ÌFò(‹ã 5‘}I*ŒÎtNçñs’”ÆíCˆ9¼€cÀÂ<%뇔 —¯fóq¦IF?¦91ä	žœºÇ;C,/àRþ—¦ÆX¹™¦Æ®M9Ñ»Œ:7É?L“°(—cÊ n7¿‘(|®™JÃ1¸¨…/äºHÊ‚V*b'1›z4|¡à(HÑ?'¬8ˆHdI6a¢·òÐWbæ3ebvPŽúÊø)žDÃk8=^Ë\¤×'˳µÂ¼—ÍÅ5@Ú±îýÔÓÛ¼ÑÞN¨rM
–}Ázr±ù»ã`Iz¤ÌîØi7|e¬øË5+µÊn÷ˉõ¦@‚^×ÍKⲚ½èVr5ãQûG’†)&yÉ4¤{–â¾RV~Ãy "ÛU'PÍ·.*p“{ŠåËR¶×&c:« œáž8éÒêS7«£ž¥Ö;RU£¬„Ìœ\“)k0t¦2ì­^MÑBçˬL‰¬(}'—Z/>®(âá
5½ý_à=¾a&—-&z4lCùñu âK.¾}ˆ“±^ÑõkPÜwiK TÚ\¾K•µicJ‘sôÜPóoƒOF×ÓN”ÜDó	ßh×,¤ZíXCòo¸nÛˆ.›YT¸ÒD£oˆŽ†¸´H‡m¼És6ÊÖ¥
L$eäè;¾ß ß°ˆ
öcýÊJ,ûX×øØæg-Ë%”bGmNc“â{ô=ôL¤Ž¾“̆v.åN»¤ÉT´1ÝEŸ¥Í©ŸJ§óNn¹ÅYEUË"ç¡Ç›)ó½DNI˜HínÖ—EJv¥%óÒeLPbõ˜‰äš›Ð*¾4‘@‡¸,Œ¹rí<ëñÑr÷J2GUxÊþ&ãX5
ï	(¨•©qÆB^m<êý¥búÇ\N“\>"Ûå-Äàƒrð¦Ù.Us{ò/„s\ûÑ7ÉsoÌ0).˜Ôò|½‰ŒêJ8²EO^”ûà$PoØYÿÐt骳®ìËš4XœpZª°e§këÓš…b˜|fÄk¦ÓrÖ£aƒ¢T2³¼8ÈãUËkôʈmA¥ï	$0˜’HÂÒ–0­%º({¡nªß/Ç(¶íÚñ@·'qV½e_ÞN"ÜqhÉ\±­×ÓNE
AªšÉ"¾5ý|’n1Ò™ÂZ‹Ÿaz›€J«i¯¯KX(,¥{­Ûнœt½÷M½Ì>ÕWEëíºš´ªí0Ñ[€çT·%Ï¢/r
G
Þ§rÖòŃ€â¥Ì'uo^§¥‘o$ëÈÝaPÕ^¦g	Xë…½Ïe03cϾIºG|Çã€Å>Ô¼”1ݰŽóד”©¸kLá!¥õˆâw!šÉê›{vRJ®½I¶»Ä囯”Èu}íJlþЖm~r-,]_æ–†!mY¯÷ib¤%‡®(+ýY¸Žöm«°d↺ýz-ôbr½€+Éå°ïZòGL*ÂÇ=0EƨÏœ5tsÇ棹0OcS,o(pRjYߤl}¥ÔÔjÇ6æ)e™3Ös©Êš}GùâÊm©Þ8#Îhòµqh(‰—Kó1]š'g¸¯‰ªÛ©ÃSu¢ú©Àì¤BØ¿^tvK×…`nÊ:§{`ÉÎUJ¶_Iÿ¡å÷c:Ù»G^Þ6·f¾‘¼Ç¬YýX;o¡Ý5F 2M]ýj[¸ÜÊÇÅð,eDÍ,N˜(TkýºØÚzjrhßÉ·¥Ë)aÁ:æ‹#ÞfW„¶ºkæëÔ7ðoW…·Ï$Ú@EþõVÂ8pª±ÚŽd`ˆ5Ð+“™è¡ökÂk!Ê	La—l›F2 ÔlÆÜm©<{ûvRqW%Žh(›×%ùP­ùA‹*:î1rÝü>Ù¬H`¦0‡˜‹–	ªáÁJï”ú©“iSÉ¿(NSu;ºŒ`ÿˆ?lkL½ªŒšÑE¾¤K%‡²þa^íÍ•	вÛ?`Æf˜ÿ¶I£À4é74¥•\æÜEÂ+í%I½/	;ŠuLݺV£×¬vCÀ¦³"´F¯²ò\ú<5]Ú®¥|ô¸oUtOGYéÀ/ƒÁi%?êSY*hQk/G’”–Óa¯Û9iÓþÑZ©öI¬v3Ü\éc]„$ª\X>"d:䜪â–y¾vM¶Fy&ÀÉ=¿širÁv5!t–20—ëƒOþ’~sfn¤yËÔí¸GE©lÜü“„FYgÁ£+q
–KÅ*Ÿe±–dM{é§ò0ÇR.ÎjZ_#§å{‹;S@©VXÉAûÕîüiç
#å_99™u‡k=v~QwuHPwu}PO½x¬/jmà:A<·í.7€˜¾ƒÔm0ëú°U÷Üõñ¦–†“ô¾è]¸ö¡é¹4Wtvp¥ë8=41G–Xà&ѹÛÉùqg×Ó!½/÷Ò»Ã<õ»ôðËüð#ᨾiúxYBû7žä§WM¦9æƒ4‰c	¸¸i(¡Ö£‡I'‡ù1cˆÂ×%5Võùì}2Œkk[t…_ö°puëžvª¯]ú}ûûµÐ@m¶Ì›g2øíû·Þ |ÿËþ­=l©á¾Ñ÷cKººØÒ»˜öË¥‘…ù,t”ÑÖœ%½ôý±½HF»X
k²)»\ª™ÚrºM¶ƒz÷E…¿¥jÎ
Ÿ©§¯Wé-™ÔodMÇ%%É|N÷7ÃëÜ\yòóùuÌçxe¤><™í·X‹“@7yºW'ã.Éú½iîó™Ð÷Fj‹!ïÙïVWßpœe=ÈÜàÝ7Ú¹ˆPÞJ9é"髃ÿëëšendstream
endobj
248 0 obj
4570
endobj
252 0 obj
<>
stream
xœí\YoÇÎ3ã±»Šv5}ÌLŒ<ÄG`%>b›†ÄA‘)ˆ"u²•_Ÿ®«»z¦gZœÀ0`‘3}×W_]ÃW‹fc
üÇÿž¾8zôM¿¸xsÔ,.Ž^|¹àN_,>:Ž
œ‰O6C3˜ÅñÓ#êi½]ôÎo»8~qô¯e»j—›•]züw݇a3„nùY|ôéjm—‰?|²òð‹ÙCðÃò›ÕÚyƒÍþ¾Z{j÷ÏØîû•ë7Mӵ˯àylgbßµƒ§o`cC9ö£8÷÷«²ÁchpÌÃ;ïx‹p&øn%K†ØåKZ¸¼øvµîâ’¬ý÷ñßâ‘«Ä·qa!žÊñY<	W1¬Zjh½n¸æ–k×lz3ÒÁÕF5ífèâñò°x
çqw'qü³¸ëñèNâ&Ê¡é—o`á·+·|½Z·Ëgq×qÙË‹ØaŸ¾]µÐ®ëqˆ«øú^Ø2Þà—ÏWÎâ³w0áO+;ÀØÝò&öÁq¡­‹k4Nq†‹ ÷Ð7."ö2†f€ÇðkpÐÚ;·¹Í%­"¾haräé}±BÜRöS¦­–ã>„õ¸ÚÛ³
aÜ Çª'cv]q@4ã9ó0¤c¶°Î€»ƒç­±“E¶8½ép¡rXôòÎ$ŽÖ[„-Ÿ®³r62úem§+¤ñ$•ñEüÕ9?Jǵ›^۾ߴí°XÇSkU¸yèɇgã"ØÖÚõÑT;XXŽëJ!ün€E¥åè…¨ñQk@ÄÃòAÌt¿Dâh} -¼”·xܰù6à0b+I;Áû¸¾C]WˆÂ/Ó¾„¥ÀqÛî[¢™:>û&#üÁäš°ñ%%Ò)Z;œ	'zJ‹‹KÂ߸¶C8gñlz<›çDl¥Ê=††(sð…2óš&´I;ÚkEë§´Wè;âÞ˜oé×™à	-Ó4WØ)5ˆËó¾AݪÊ>žJ\{Ü„€Æ;]9–°‰‡½8ZŸ’û9¼ÛQª÷ÒèÇ0,Zƒ/g¬A¶ŸB7ƒòÐÀJo…?ó££7“ˆ=2Â?X‡Ó²ì.3¤`­H»-*õP˜`´Ä•”À-œLcâb¢ØîñäCÛÕJ$3d¨•øÊPâ3í,ð*#&n¤$•?‚䈰ùSQá+fâ( ‚:Øî`7løZŸSäåPÌÕUë‘ôŸ¶°€ßX}–Ž£ðñLi!R‡5H¢¬–œ”]†ÎxP»I­,MHgCƒC)YïäÏüò²&öð•p§o“ž?[öåœOÑ´IƒA¦gœl55O3‘+¨dpdST§dµ8oüÁ³U)Mí±ä¦
dpXp¡+DÒw"’‚žoxgrŒ úžÎ·°LIПÁžO‹ñ
¦;8<# 117‘žšódE–"é	Ö
ôp»ñ	5Û\±ysm-÷8ºÁÁ„Í(=Ÿ¢+ùflþöñcôøÙ‰(|ÚoÉB[|aÐð†Â“–XøÞ‰œ„»‘‡~XÅfèI†¤FIÇvIy,k5){«}ܘř=‰ãj5²kùED¸Æ'°ðaÉ	mõµL‡hÙÛ¯t¤CŸ‘Ř
Waã§jh~/LõŽFŒÞ7P IG^üœuTîNcF6£9DáÖιϸñ’¤”÷œ¥Ðoà¯ø°•|×â3qQH,Ùu–…ce/ÈÍÒ³§¤#¢ÎSåÆÉå¸b¶Æ9 VH+à†)¢9º‹,Íõ(ï8vg}I§ÌËT	¯ic–=µ´èüJZÒ¡Q+:9±†M"¶'Úº°#.sâï¦5*³ˆ§ŸÄ<„—Å<¥•{RrhÉ×ÁÀ9…ŽòMr˜pk"¢G{I¶ŸaÒ:òã>H’Ϻa—1£ãŒŒe{7ãe ©³Cß±[T=è`1›âö‹ú	í΢˜ØHëQP»‚y¢õˆ0¶$¶MºRñtEY#P%
ÿݦ
#©-dŠˆï-GoDdÖSDÆÑ“¯§h•~š°èÅWPy?I›.ékÖBFÍîKËØ¶3V16’QoÛ’²<K…(ˆ¸³Ÿ£ UŸc´}2P˜+ðÑð‹I¨äü>xr­/ŒWÍÎùSñØ’Õã4²Ù°—»B9F–õŵ /¦p¥DrÐäe&“ÒëN#Gj&õ^vƒrðÁ_£¿±Ÿa4å°Âü²C….*Š<%BËæ;<S¨ö
ž×H¦LzcÑÉ…ž·¾0jñwd¬Qâg"?,.è;Iâ’Éð”§×áâºÛJTN~[”H²·r†!÷lÕJIÝçÒ¯º‚ß^z{Ÿk¹
ÄÍÄŒé`
#$ö1}’­p'•j¦w’âp(‡BÎÝW@à(w
:~ß
G(`þÒH­ÆóCŒq%¨© i’Ždú~Óg%ûñäG¤„¡Z¸(·’“²7Óû
E7Þr:¤Î%˜žÓƒñF’@‡ãšhõ…»	Yû]ùz¾ì ßf½XJ‘bJ¥éötq™çÛ2x×îÉ#5~êòåÑýÇøº˜s³¦á=ZÛáðÈÙ“"ÈÈPï`÷UgŠ˜©W&,ƒkâˆcm’É—³)å-¨YhëP),T‘‚ê[¸LL̽oÄxñ.GÞ	ikÇXrGY©Ç'×)yze;WøâŠ8Åõ	¡ŠÒPPq[”IeÂðöÏ$翈õÓâ`öq„ë÷7¡/ýv؋΄ƒ3C¥WÊ¡½¡ËF}oÇ[VîÌeé0Ky'NÞÐÍ-Áz[ Uz]Âc¨
iè㇞ƒ†rc	P¼çJŽë|L.)Á¥ï)0¿zJ5¤è8Àû‰¡“dôÔБ$'ÖFo8¿&!¥„CÕen¨¦yž)§ÚÐL4µFg°¤VáTa*?ã4’-Mw4èñA€î‰h'QsKÏ+pvÀå•‹ª:‘hYå8Ï>ÍX¨‰*œª‰ë=ñØ¥Û0—Ñ™-ÚéžÅR)±œ.ýØàµ™ké‚pKvÞ¶’¡Ö1`¾c+JŽŠÁ‘i‰‹ðL¼†Ð¾d¹®¸o,Ìñ´pšÌ¼0"TŠöUAL"6al¨p-n*Øö‚GÞSf$ôGû­Uè®Ú‘çHlRdX-ɇT³»ªaêwK™—\¥dkªpGöÎv;-j¢¿N2]sé-¾Ò–ëg“kÀðÆÙï“Ñ‚%%À¨j»CH ¹ð’–R¾ö>`‚@±xŽ’úµ7µ;T	3â<ç:¼Âms,,AÎÌ$Ôî…vÞh˜gŸ5W¨5³Y[AêöèPZRgŠÜs@ÝéUœJ]u*û-©T#Ör™BaT]Ä\É ™øÀha÷¶‘Zàõ±nGù)]8š]÷Ø)û;©ü1·ûEȤð>eÚT'eÛœÉ
¦|]2í·W.ƒ©ÝøëJ‚CðyÖЇ>_’Íùôøèë£W‹HÍ~ŒG
ßõÑ^†…룻|ÛôÑã£G¿Xܾ¾;?zôýÂ=úþ÷Ñ?>Žÿ<þdñ‡£O/¾žýîiô9÷ä{¥`.ÎÖñ·OõÔì	¿ù'Ù˜Li—K[~ø#ŒË5͇¸Î‰zO)ÑšíÜ÷Ë
9à5K$Kç铹ʼΨ×EJ•Ça嬶>Y”Ó•ò#Åq]Çîü¾kUÐXä÷ÙÜ‘ßÏåðä]G•ÌuiEm=yF[ËÂkKI©H}TdVXêZ•%%Ž9mÒl&úsù
ñÂØ³{ôMçŠ×LNÁ×kF%ažh@Þ°•ÀÞÀþPtì?¯À²xÆôŸ=OÏÞ•ád‚ç<žœÁmjý:?¼RÔœ^ÓÇ*Û=Š+µJû©èñ"=|®sºëŒÀÉ,hnãS3ÉtÆèi=>Œdõ⊷ß6äè>
stream
xœí\Ys·Î3£±UyðŽÊ;3ƒyˆS–-—•8Ž:GÙ®EJ¤ŠÇR)Kÿ>}hÌA.iË~I¥qW£ûC£/äÕª©ÍªÁÿÈ¿‡ç{¾éWǯ÷šÕñÞ«=C+ùçð|õx:_ê¡ÌjÿÅ4«Þ®zçëÆ®öÏ÷¾_ûª]7Uûãþ_a„3ň¾«m€AûGÐñ“jãןW¦†à‡õÇ•]Umìz¿?©6±á›j㜩›¦_·0w]mú>@›[?®<
û¶ÚtÐníúiö	sõz^é³ÊbKè°“¬‚õ˜ÀëêÆ´ÜéËŠ:Â,C7H”ErÛÁŒÆ@çÆ®¥Uà—ñvtÎÂ<º;œÝœ<¶´4Mk
‘!ÓŠ´Ö¸¾·ÌÉ’÷ㇺñ«kêÞsô,; £ºõs`Í1pë%Ìw»¼`™&äoÇÐ?4@¦_o¡ïNã×W•[Ÿ`—çø
6l“ß~}}⟰ÎÑ­_gFnù+ƒ©p]Ããqì6‚0B«‡\có³$IՂ˼ª6
þ46pOüxQÙùèiÊ€ý‡õiå,µ¾ƒÖ?WV8‚;b‰tßX2~»,™F]˜J¡Ùµ­P
vèjáK|ƒ±ìç,IqFÿ…V„ ÇަŒ<`b<üleŽ8b¢fÐàÕ“Äš$=£lÅ7,¬BžíÂ4B/nmÃ{Û Û2nq"qðÉ|*XZð[
{>¦#j×Â⦧öKœ†øÊ¬¤­ÛÐʶô'gâQ\ŽúV®ƒ&30)¸vÀ#h“,§8ñ`vÂ	Ï^ÇR‹+1§p¹nÀ&’r’ïN`€ÊH2”VAÉx!™‡#IÖ–ì)ëಜh7¬zdKÁ[r£E2åHÖ9L*ÂÏSýP%D€Bõ¶#´)mt’ôSeIM§	UÈVoI_e…AK\çî\‡	M¬´¦(;ÊÃàP5t
qîçYÀÅÍŒ4°¢ÔOZþÞw¤ø’‰¬VßwC ï‚Eï¸ïe†´ÀkœÍŠzÕw
mI¥-
Þ2B”±Ê;O§P㟧½Ž‚Jˆ‡À“]4¾c7."é¥@øÞ¬ßT-^OöA»f¨mºáP×ÓëBÓÆ2ƒ­eþ¶„ŸŒ-¯N†’óóÚˆ,â
§è‰
f–­EvR‚¢!¨È>Jõ“w™E^ñ+ºÆHÑ•†§F˜8èûQGCâ‰ÍÄs¹D^…â8Jû‚3z¬§‹åκ§c.©K«Ô
ã+,ÒBl@ßâfÙì|Á+þ>À?½_&ãÖõØñQƒI>ÛäÐ;#¼FU*Ëk›LUÖÜnVà¶_ØY©«hê¾™¹5/DÍŠ½‡?åt”,ºÌ¸Ê¨¿RZËŠ¡Ä]TEž–@†‘!íxÙ̸‹GC‹-±ˆPáâÕêæEJ3FÛ³°:-'(nÅ¢Ä)Áä.œèÙíªo"vѼcŸ¤s¥OÒÖ¬apJ\m’Sòw‰A"Z3aˆ7nAÊH’¼òñ'Ê™ˆ#0Ò=9jˆ÷õ†Hi@õ:bû#XÊ6Ê8|‘ñxœ>þ¤Aª&U–Œ…¿q+¥´A=lÆ›àѯˆ3!¸…„|˜š/Ëq´¥#Hôej¹ÈD*ž*ؤöwsƒ®ÓGu&Q…¬@>‚Ià‡©ëIîz i¦ygØUöŒÒÇ;ìî¡æ§j—s¯óGäÁéF[¦QžpBÞFOKŒ¾“©	™ÀîG™Ý· óôfÁNЙ.ºÿ£sއ…HâÇ‹9Li•¬ÀK$…v:ˆŸ^Ññ¦èÁyVðAª!}QÚmÝwÁ¤O‹3ëÈsÍjÁnļËìÓix/S>’éCòUÖš¾J<ì 4ft•´•›†Á½3 ;ÄôÀ]á>&ÇÑÌ})·0IWÜ[Ž[nÜ|¡kK<`:o£ŸÙðld×sâF·TVìl§¬ª-I%;©ÊÛ¼bB_e7S̨¦À_6óÐ(Z¤¨ØjÇ”]Й‘U¢s>?ìL¶"û1®ðŽMOäpŒ´y_O"§¶½ÁŠ+mrŠ“jµÉ~Æ&T¢á8âf!?쌖}ߢÚOˆŒ´À᾿°@[ÚÈ"]Án´¿mä¸?BÜö†Nû”Ù¶}KrAŸØt#tα8HNGrf‚¸‰P?
x$ÃôÙlyïàÚåÐ3²»ïˆrBB'
˜°ùâ·MÉK‰ý)+R±žo"ñŽ]ëÉY>RÊ$JëP(±ãöÑUx1þõi@Yt
Í7Ñ21w[F¢ÌE7Ò‰jÇ{›00U£d0¼æŒMv=«ÀWúËóÏädrXUÇŒ²~ÒäóóœE‚ž}Œ;”ЉÁS	q;?™WÐß“·]*¯ñÞO^eà¨b¡‹B´¢¼º“ë'©”ŽÅì
1MÉöŒ¼÷Qð|”=a·{h¢O\KÄž¿
szÅŸf÷… ¯ÁéØÛ2V|¤ŸàvÁ¡ŽY•¤|W…ž7‰ %ß*êÅ„™®(æ¯(I_ÙÔV'Ñ: “Hf‡tì²ÒbÆo£’œâ͹)Þ$ØÁ9N³‰ò˜Þ˜#ñÉÐeú.Y¢Eã}/殄™OÔ̯•,º—’ÃJŠ	ç?#…KkÞ	ö106Ø"kˆwtÇÓ-f\ß
YÒJ}Ä\§@ªÀ!e9û0§X„¥yÁ"ÆÖ§[µ²Ée¥šBdÃ8û#&G¡Ø‚B§"t£ˆ
**•P‰[jZ!aLJU@iÃçúÇ•Rpè5Žì¢"ö_Š,y("HÑå(èV›æÏiešp>ÅmÆN…"¡°÷5Kš@Z`ž%£kŽùA¢ú3®ÇFZÃZÌöÚTÇã†Óp‹nÐÐbVf]Xëí%YÇö^KÈ—È=Ð=¬n™×¸½Qø’îo?5‘¯åÊÐ)ë£xölŸmciW}Ã~îíaQÞ)[ƒ··ÔLLðÂë‹ÙèHM’nXÿMŠcìú?…}²¿÷õÞ«hàŽêq@|aªÕ ê-à£XÞóøéÞ£§_]ýtý|ïÑ¿VfïÑçø?¿úþyúéê{Ož®¾¾céš8W©
ÿ䳂Õ.Ëôu bºß€¾.`•Œ"PÕý;ÑúT
n:*öiš”PÇæ C°ðNêõÙ>8A:¥«š„š*¸ßs)‡Z)cꙿò†KÐU©X3og`)+{ëT¸½‹ñl8j9A ¼”ìþcmÎ¦Ê ¢“ѧú‘´qZy×¥0οO™µqEè&\Ç7™}iÆÈ¹ª$QÉËåÂú{ Ê*j•ø6뎡¯?Æ~èÉùŽëˆ^U\²»&åÝ·ÉjuêùrÐ
ü•Tx¦¡h8Ç›b±8ËÜd›Ø«‰ØF³[cLÍV†5FË9”Âû%	© _¦áÁ\}ä\¤ßh·3Q\2Êwœ¨Œ‘ª]r’‚–<®ÞX7ºÃÿ‰àË*ò¢·,|I>’#÷Ï
¹¤aÀ”ã°6©£ÍØ«ÓG—-;e°?c†«õ£9ËäÇl5oçl¦gsvé¬	t&vçäýrÎÚTÉød’‘M_[²ƒ~ÓBj¸N‹ÄI}ß6v÷ˆ”é—-÷l#ÿž¥O÷ñ~Í:8ûGlxß§ìd–»³ üŠ¢F…%£¯;•EM¬|çkG²/4D¿“•O¯­RR%Zè1É™bêRmë­Oy‚T£`8‚{Ëûoìî/=¼árW¹œpYѰ¥QÅ)”vü:íSXâ;œ¥S†Ìä•Á6NL6²Ç×a¦ˆ÷éÜ¿Xƒ¸Ûd@]ðm«¤Ô±LÔ´ãGDÊ
š\¹ÀÚ®ãš]òÛ "T£„¤d¥'ÆS#.L=Ðõ=Õ±t7çQãå×Ö­ç0ó¡lª¿‰~”NWSÈ‹2Ú)—+ý£@ÞDT$kWÙBVr#ˆÉnTN˜”–h“­f•zP¦|¢ŠŒú‘ÑÓØdADËIDÅ[žÄFï$ËW7KùQÀèR‚Œx?-×éÊçRð‡rhÙÅ ¦x^Ò÷"²=•89¬J ŸUqªôÔR@ñ­ð„ð9ÿ4aê»ÌâM›˜æ~ZU!ɘ̄˜¹2’2R%ùϺnzòásu¼xÚj/}UôË_É!²È߯ð‰2ÍyV),Weº)Ö}ì 9d¼M/Š–Ÿ%ÑË—®4ØÙ¥½LÇkc_…n(Òâ¶:‡¿µ˜SIÑÒsG¶¼•ðŠÒü›+÷B¼ñqéäÎ…9üÜâ¦R®X•…%–‹úƒš3C8ÄñMÕœHWêøÅïë–®ŸTÝ€ú/;¨ÓB›6Œs‰…êfÞ¯DÍÕòéwT*~¤Ñͦ¼ÓòÊšêœQÒÙ9´ïíóøü¶nÏÇÇ÷@³‰¥šºÅ†ÁçæE¶{rmŽ‘_jÊz±lÄꊅ±Übù–ãÌÉ<Ø,??SŠ|áåWgwUvm.|0EqbÊñ§ŒºÒÕh”ÚšÄR³ž áNݹ7D'ç¡jäÔ…˜Û~“ÞQ´@»Yñ” )¸c5N3ÕN:±<ÿ6JµcëêŸ‰³•ÚªB0.EÀ#–=銧ÑÓþn˜1HT™æ¡xäÿ@[{íúXŠlï{)жT â'ϳÑFêÇ~nâ×snåÒ0¾õàk(WßIÐ}»ðfµ|oÖ…º|Â8Š5Åøôì
)C°<±åäÒ’V*žÇò&Ç7œOöC*MŽªiÙù\²…[—
0äŠ>Šw©—m0m,¨`Ÿ·eŒšª„
|¶®„¾Å‹uvhz´Üáý•`èx'9øÚ’³|.ñ¼	0o(‰0&`)Ä{&܆ں©£˜ñöå>¡²wCôÝŠ¨r‰Ê×{ÿ¬4endstream
endobj
258 0 obj
4424
endobj
262 0 obj
<>
stream
xœíkoÕµŸ-~ÄJýÀNäÏ}Ì‹ŠV¤H‚£•ª2v^Jì˜$NH}ÏóÞsgfíQ¡áݹsïy¿'?­šÚ­üO>O÷îö«G/÷šÕ£½ŸöÝ\ÉÇñéêæ!,®Ôc3ºÕáÃ=~Ò­z¿êC¬¿:<Ýû׺­Úu]ùu¤ÏM?Œõ8të/àÒ­jãןÀ—O«ˆ?\=ŽC×w«MˆŽ–ý³ÚD^÷=¬»_…¾nš®]×aƒg7¯:úÝàÎåÞpöýª\pÊö!Ù! aàîU
-¤Gî0àzã»jÓHÞÿûð@ç-Ib€
@•àRÀU-.ÜD?ÖC\mBS÷nyò˜7tͰ~ ¿¨6-|ÙD°õl’®ùvíñ¨Ýôz9®Ÿˆ¸îUè÷	¬ŽŒ£l÷î]À1¸rë'ðÄ^Áå/Íà—ÇgüúƒbéË„;"rëpïÛ½ŸV!Ô±ëaå;Gx÷
0¦PšnÞÞ;¸ýÕêÕ‹‹{÷Wnïàüsó›¿ÃÇíOWÚ»u{õíVI+ɪ’æ;°ÃcêÀ†ÄCt;BH¿f	“HU³Œ‘âÖáO¸s®ü%ª¾ÅGFÁõ1P
	IdÃBqÞéHwfWá¨ØbÞÃ]Ÿ!X¦‡>N‡瑽Æ]b·þ¡…Û+°w¾3;(Cy—Gx@»~ÊÒ=³×Û´×›Ê#f£E‚r‚DǾ§Ss”‡bo’f×µ5¨ýd´íPñQšQú³LmâÐèw&ÔÉ‚”ÿþ´#QFEŽ8¶UÎ\ß¶uVÝØx”·ßJÎ\?Ô£_u`ºúÈ‚–¹ï; Ö¯_WÁg\”åÛuÄ…~{ؽ#´°¿³’úhEØâ€21^¢3O*ŸlQcþø–Rå—(ˆ?Ι՛8zÒ«tòã¬>p&Û¨‡øµ#•-׉Œý>D°ÁÁÀ·Ö£‡@ÓÙÈ÷ø˜qt%2œh²ì•J„xàæ#9„ZöGîÎD„†ªŠÚaYhôóe…òÀèDu
yÝI¡Rê P¥ÚqàÅBgö*v‘éñúʼË*¬öV)ÏØñÇH¾dÿË’¥2¥ñ&-g¢ÄõîÜ£Ìøùv;¸?²1t$:oÐÑ)uÑúyQy:Z@÷;ÇtmGLîÆÕ^É€ð…‘UˆiRN樠ÀxÆé9\}\ávÃ0‚u0À–:k‡Ÿ3‘—L»Š¶€ƒ¢xS$â·8‡$„ñ*m®’Šè’øO
JJÈnËXá$à+¾q²&m—ï®hÅg	ÊÛÙf%üƒ³ŽÔjb#Œ‡À„
¤‚,>Y¹€™F˜ádÞî:î·ÀB3”Ì™Qhž’ðøÑj*yË«¥Ç€—x„oÀû¡q¼ËwªªC»	ÔB@¡ïÑWûÙ‘][©¼ƒ#C3Rx(L
=+
<Ðk³Øfê`ž°,Ì1‚t‘œƒDáÇ`Ø‘bH<̡ć26üX´âbâyÎìa
ƒu\qH² Xãp3aÚHßL@ÔA±"*o¨Àðµu~Q^!B1>âÚ45B»%(Cª¿ù”l&J÷p–¥‚HâÎ`à:*=ÊFOVIRƒúƒFvuÙ
ˆânPK‘áª,$§‰‘¬%¾O‘ôàR\  @&r¶™3¢[rh†gòŽÉbЗÿŠ‹OÃÛ·‹þ›64<*̽‘btðœ›}•ó•îtKó3cöqÓ–žý"Á~»Èß”G橯Ùs_÷Ê×ÝŠ"xSÑ}Ô¡¤ŽÈ[6ŒoÐøÇÈÀSVÓÆõ¿4gã"àÍC„31#c(‚pµlWâ¬@íÌIv™Ç¯Øã1¥q«IäÎ5¼P
=ížØÿ¼vÙÏVÚV.Áy¼§‰HmüÚÎ5^L˜éd ¿Ü;¼±”†o|ïÖ
…¹Eá ëC•5NK³Eº7QXháÝö•:¦v»jpÊúħ , E”5«éélƒÎ5žÃ#;NøòƒÇLZ2FMJÌâ1AhܲÏê5„`‹í1:Dü0Hè¿5JÒmù_F[
ø”l
žK9t¶ÙâÿŒÍžˆ†Î3ãŒ/Ó1Ý„ôöìLb!âʾ$ãb6¯öŒaªÈ×PC9öǪ™Ú€c
¸Ô6ÏqþÐe×£Á>Ú1é²¹QQÎQæúo(Jûä•Ȉ娕
D'&úsf‰z2ãPE½ú6;”~j¹0jv‘¨b²·B
Ô›«½õËA¾	~
Ù3	¢`^Zÿ]¢F0S|\¿Šô9 ò>ÅÁeçÁ8Á3qv
4c,P—Û‰k“T¸²àüÄQ‘‹ä"å¨ÿàÏÇøÙ@¤À2;/áÅhðGN °¶ÕðnõIÞè¤ðrÑç‹ùÈW6¹2a¿‡ïØ(µåf
­Åy{ãÇ›–ÂNdÞ>/Ÿ#÷e!%ë›Ñ+¸†vg&7O÷—.fãRpÖlŸI0§Ë~®÷åÝÛˆÉ&¥¾!ào¤‹7–Žüy	âg¶zi©9A9ÞÙJæxý*çcÅÿØnK‘¨*)G¢…½Ç3ÇI(D¦ÞH·3¢GI„$9ÞÏÏ]ý¥ûO¯°ö&S¬ S/>rד^÷3ó‹KâBN¿Öºû&iä.uÙ®aŽÙ,ês¯Kš¾*o±s¨´Þ/Œá{—„ÔPïõ’h–gfO’KÈ|‰åI~ã½åù£Zž÷ææ×57¾	×67ý¤?tã´¤øi2K´ø­Šl©=)
¹s!}°Õäº#›RF²2¸QâA+#fÍ\FX¬+€¿±mP?¸;¬p< m=…–!ÖHûºO±ÅH×5”eÕUÑgßÃþq~Ù÷4­áö~ÄÉ–PXU	ׇ>bRÔÔýÐ{H 95Ȥ¥­ˆc½o=kZ?Ô}è I½=Z‡t 6˜ê.Ô¶OWÏ Síú–Bïê×îâJ!Ó-N¼Ð¥²+Ød',`05<]€¥-SÑG¡#ò$Gá¸*,
Î`±I,)Ùýjô¹dÁ%à÷ P°¢ölvH[–5©]…ÈÃ3EF“v–úåyêMjI“Ó´Ò¤ùÄ9Ñ8Ç,n´©JÞ_ÀÕ]ËUêhjgV+áEâ·4Â|ª•ç¢7æ{uʼn8ÜMUNx„»Ò}Ý&Š`qÔÚVÊÞõŠa"-\lA!¢`ESú»WÙèØQAðÅ<¸H›çUò2Áè&²¡ãˆ#õŸÞàµÝ:o¡ÉÕ¼Ù>±EÉVÑÚ`mu¡MN©pÃM<[Ð-ú›zâPÒ|y€‹$<gø½OÕß0.Ȧ‘9˜}Ag‹-ðN‹:¸wØ»¢—pš5ºê°[Ç(Êô?1˜ª+COÂ×;Úûƒ…J‹T))i«¶÷ÔÂÙ©»ÞÍç/ÞE4¤&Ã'jL Ï£_VXl/5 Ÿ”±fuøìõJ‡ Ý™iÎJB!5,dlšIv…ícn¨§ò\ßE‰¸ÊÖáÄ“ˆÉRk«–	0À;RCÌœBX±ô¾e8BÿÖBl7R!Öº´—
îÂAÌmî6´R`#¼.™~î&à$úÓF£?B6‚\W(
	ŽMzn‘jÔmé±F¶–KZ®(
µ›óLD6g@žkOQÒáé8ë=!ÅÇ@‹&EØ!õ—§¾«0’$OÀ÷½¨uK°ICFoɲá‰uŒÎTn[žpɽÔÒ«Fš/ؽok¼s»¤¤ãÎEÚ%£…²…ñïÖaƒÒ,1Æ¥]²ô¡ÐŒµD1”ÑEG±“ï8aÕ^—B‰D{X²“½óÛ»í¢‡=Ëdv¬Yòí˜}œ9‡¨ôC¸¦œz&îyym:Gç|¨[—uow‘Fð12âýŠ—ÁI0—§fcåh¼>¯TˆpT uö*»Xpkás;Få1pÓ;ŸH‘¾¤xéÊóv§õÒ"lJ{4‹#1ñ	Éî8Ѽ›Àìï«<ïÙ¥pw@I N
gøe`£»ûf–Óó4ô”#Q}†rU—´Ç$:Nf9zGaÔä3Ðq§œÙŸî«¤†IlìÀqÒàÐ%|âG”i+Y}‡mRŒ,åÕâšÍî÷Ò„*î$_·ž¶/#e²™jŸ?&’36‰¾žàÛòjƒ'fÓæ}†š…Uû¾¥þ‰ba7]r¦‰rJ×x>±YŠf^‘a hðR×X¥mwzy‘í¨^¢§Yb8ÿ2Ó6ž\Y;	Tu¬R½EaĽõ5ϧ‘¯ÍKb\—32õ~”¿â°‰4ÓÛaå°ßö¡
†›Æ 3·€#Ö9ñ\t
¬1Mž®eì¥æ¡'½EÛ9u	¦‹;·4iÚ¥)ù‹IlÒvƒ–ßm† 8*jæ…²›ý£G0NÔÐhÿOð(NÌ`^è–c‡°^
y~4)BÕ0­·Ž÷ŒÃ•3*zZØ}ØhõDˆÙt¶Ø'RK¤ûm‘±§Îý‚´¬Uìóèz’ÅÝ¢BLFF‡Â¦)öÖª¯‰Ð…:“Rµ—$´ÒÊÞe A+6fŽÒtl¿ºLU#Ym×ÛLËl›°›OÓ‘x’Ë]çb¶b틉*æªD›óIv3»¢þÈsö2‘,댙’ÏUŽuokχÐÔÎSw>^»<þ&•Žó’\#/Z¹(.z©./ÆÏÓŧ͆ÿçv|n÷-Ö½/¾]B<·´Ÿ2´×ê=­ZæÈ³%àN/‡ãÓtñ0?ó}ºøM¾xIÇE0Óˆ{]@¯0Ó»°@ëp2êûéÉÄÆ4eÞ¿˜µÍ>
stream
xœíZÛnÇ}'òû¦C;šéËL·ØŽŒ$€âD¡qP»’HHäR$7áŸO]úR=3»\RR,!‚j¶ïUuºêtu¿[´M·hñ_øu~ôäù°x}}Ô.^½;ê¨rþ[/¾=†‚’Æ·¾[¿:âžÝbP‹A›¦U‹ãó£T¦¶•ªí?ÿ=tWôúF9èt¼††ßÕKSý¾îïñÕ7µªþ\/UuŒåOëe¬x^/µîš¶*c7õrÔéêÛÚP·¿ÖËꕪþ»}‡ÝtãÝÀ3}_+¬q=6
³`GÙçè£tÓv–ý©¦†0Šï½ÇE)\.Fõ0b×AãVÃ"´¥YàWgzl¨µ‚q44×8ºv8x¬ÿÖÒ¶Vu´ŒP˜f¤i`iú
ƒbM–º_vÆ7­Y,uÛ÷¬Ñ-Šs	sûjŸ' ®›ZW/a@ÏbáÏS¬ƒ2ÝâÔ®úwmQOÖP‡·°‚ml=°ì¯±‡¦+PüÊÏaà Tñùj/jÕãÏf„aÐ<}õÖдÂk\™§±^a»–ì
‹Dt“•¾©µ¢nÁÕϵò‹žú_Âh©Î`|1þÄe´–L¥¤8¬kÔ³nÛ¦o»Ñ[ÄCKЃvÁNÿIÀq¯==ü¼IC±ªÇ¸€:oȱö4Á5z…8ðÞv
ÄJMð’-à]ŸD"Í:’à2
‹À¶c]¤êu‚-å^FÁ—€hÛã^FùOH$ÂE´ÝϨEz5Gosàœ¬¶­ÑÂv­—Ç0q6@­ò–ÔÆ0ÎÖEysãœü
d$OjžI‘;O³¾È2²£Y÷ŒËðXÓ0¶!Pq‹ #V€zg [çÛ$ò„AÙ¹¦@9á¡Éi#L¡VLk”Ù]Ë:‰·ÓŒl´ª5®Æ>EII Ðç&”¿¤hµà2„ f½cyÁ69/¡O%ÆE²#`]M4 
K²E¨in?Bl6$¡þ\}©Y^iv_8Pš‰|¦Y"8Œ¥Áq.l‘ÑsÃ3CÀ™¹Er´oPM¯KÇo§Ayà7›.mÔ3ÔÚG¶ˆxØž8×àth®0û¿ð'îcZ¤h‚¢sí¡]øy›*h’-þy›¡Ÿf “WO`~Õ
Q_åf—©ðM.¼M…ÛTˆ’£ÁÈVÂå§
§.%ãÞ×eÅÛ m=aç«T}Yö#<
Á#¬RÍ©ô(¢9ihȉ8/Sám.¼H…'…+*æ¯Çyô‡¬c•[nRáùŽ)§‹»™[ÇoÙ g©î"w`û*—^
ðÓh'%¿ÉŸ[öp°º>…ÝëÜ맺ÅR÷{Ä)؇]">€ÿ6A÷-)v´’iõ®= àZÇ€Û·¶ÞiÇÙÿ×áÉseЏ ÕÚ2.èZÏ ˆxl¦ù[ífZIx1Ú’<4øe8]pÄå3A$x¸@Cç…¥QÌéÜ…ÇžêŒñ,R¤§âhe4ŸKBÄ4Z	ÅÉŒNjâ°D£>¯·¡«þNsï&¥£3‚¡À(ÎÊB¶áÝÚy IÂ߯Ã{SkcF!–h‚ !‚Lý)KO*š("Ez†DEÆVPì™ßJ˜Þ¦FvÔ
‡Ó`NtO–kÏѨ@¬L>5$«áØ—±W¡¹Ï!° «&ÏP“\šø_Ô´¦Ã=+bùÛk²³r]còQ2Š`úx(Ô	:à«àgËm‘>®j–AZú$@@Vwñ+±±‹_*?4ÊŒýÈç—Ù©£ÎŒž›Ä™ÌÀc©nÓ¤{ˆåŽÿs#–¿nË
õÓø·Eì…ø“|NR?28Õê°ÓÔø,öå&›Ôíö!¶;›ÑÐç°;ijmrᕤvŸÀ¦ÌÈ4š'=šy83Òã<*üþùh(ßÔ¾M9lÌ"¾Êr„…$%1û6›^š'%ºe¢$“§‡%NÃü!Ü÷³éàIìo99é‰î¨¶yÔçIJåq°£dï\Úˆ$%¢Ú6U‹À“t™.3¤|oÈS฿]§\d8Ó ‰î´C~ä#³
¡v¦qH›úÆ	TÈikhú“I$7:‡} „ï0&
=sª»ÙXÔg˜ãQ­ØÊRâIÁ²ÞLRí:’|)úó5Ì’Û‹A¾ÎA)>Õ!í;LÓ¨¶Lß
~„4Û)”.H^1CÃŒ.gG•¦8øˆ°™Œû”L‚[V¤…Ý+Ž[ÙrkXGœp|sÐäd¨Hª£S´ Œs÷¿5àD*Oü£´­ô@ñvç4Ré°¢x6KéìÇuJ½‹þt˜‹w;©<¬SyŽ.Ô•BÞ àÛÉÓèù$kðgŒ_Ãn{Ëð%tzוVæ<ù^kä ï¼2bð´ò¼-ïæÝ`öO4¾ßÖÞŒUÚïtqaˆàâîôV;ù>ØæcsýµŒé¹Ö¸,tXÆx=Gin>	ÞõYðû|ghIç=‹»·³¡*'ˆ0 M.HzøÖìF7y¸Û][æoJšˆßÜ•8H6¡ë{iRÃSÖ‡™£í0j†BSâE/r;“IžDšð‹§ç{M¶yÔ€¦ˆ±¬´IxÍÐcoã¨ÛÌr8ö,ôÀŽBzËt"„äÀG	ªÈ-Z‹W9o,	¦‘Ûʼ Ø'óA
ñ<<ADê öô¸	"–<æ{@@ñ‡‰¬c_[¬7zF›So:«óúm	‘T¹ç¢={á¸ÿåËÖ|ž¦²U]¤)ÖñrÕß#Mq5w³ú$Âå{æÁNædÌc—u|ô)Çæþ Øüc^ö8ë&/¼8J'_î(‡lñ(wŸc§„sê>=aº„æ}åîèê¹·tŒ2&ŒrJrjíÛòBç4ÄcÛ˜|6Ë+cèeŽ–ÙÝÞPËðDIRëór_‘sT÷8:K=Mj™Föìä(×ût_1t)I€(í-¹Úùû;«#6ØÞ´Ó_1›b®Ú4÷¤“Àñå_ÏÉ U®ùF+ñ—´,b4Ý–)…™KÇ€J¯v²û¼
ÿTãÒÓÔB˜I(|P˜‡ß¦À‰ËÄ·YŠß'IªXáø+€ƒ¤(ãm‘ªT¬ç=O>C‹âÙg—õ¼ïíU¸›æÉ¦|ªO.@ÍçÀÛ:¾-xacì&b;	ñ(>—ÌÂͼ]ò#bÅ× ™¡áNnRºül»ýdH^îÞTŽ[¦ç•ÝÃpf)ù}¬/Š—A¸iމî@U"âw\û/ß2÷OÉ]=͉§½,ú–ÜÞG|õ³Jµ‰‚ñSƒŸõ¾’ÉÝz7ýúò¬ç“¦bÒÙ§;ã?=Ø‘T0az8ˆ
>ã]ÆÏ.º2ª±k)CNowõXEÖøÙ{ß÷Ì;âAtÜ1ö“"™¸Âc—ëxaM™y~;öÊ£©g½ŒÁ}Ø}€t(ÅÈMò2gik¦'„ÂËìxÿ pvÈÓÚózfôâ‹ëù^bü^>=>úüû/ÕˆJendstream
endobj
268 0 obj
2887
endobj
272 0 obj
<>
stream
xœí[ëoÇÿn¡þ
þ–»ˆ»ì¼vg>$RJ’6U-qšT$j/`Æp(ùë{žóØÝkÒ‡*„}=»3sæÌï¼ÏýùpèÍá€ÿä÷ÉÙÁí»ÓᣗÃᣃŸ=<”_'g‡¿?‚œ‘>
É=<à™æp²‡“óý`ÎîmB6}gå÷vŠ©OqÜü¹ÛÚÍÝnk6Ÿã§/;·ù¸Ã‘8õƒñnó·në\ê‡a’ð*ýø¸KÃ╯»­ÇÇÎxæò¢ðÐààÓh6СOá]ŸGühú”¢O›ï;ýt„~Š«|»ÓmG^“6ú
&Û“#Þ†³}›{"ænçpùíoÛE?×E«}q}˜jíGÆ[3Ö`IÞ퀟ör]à­¯_ÜÊ›[7ô“I‰'Äέ­jBŸF¸$Yö».ÙÍ‹n6´Wpà@!Ñ!ñÏSdŽy8¸	›çø÷igG8‚ݼÁ›y‰'Ãé'ßOáõq û¾Àןñ1
,©»¼Ä]<þR^¼Ò+ÊÔâ",])N°l1Xoð–ž®LT؇Ñ5š¼÷~°Ô¾í=óç¯(hâ6_à´MŒ£;øççøã Ý|ØmcB6§É/ÚBaŸêºDÊñ6|tqÿ^~þ¤9¡Þ.ƒ/óà²Ùy|QÞ¼Ÿ—ÁWyð¸>Å•³À¼²üóš¿:ø ît0f¦ÞÆ0f§Þd»ùyƒ Ã}ƒItVR;eÐU;þÿ|?^´¯àþüôIM‰Cäȃ‹¼S{X?‘¯í@{óü‡ê’Á‹2ø,¾Êƒd•à3ž¯ÕË?lpëödEëTžÊyas3?~ÞÎ#Ü*W|’Ÿœ"ë×V7×°T®ðÍÚ×PWæÜ*«¿«l]euàŠt<ÎÏŸ5“Q7knWÏ+òVF/¡ÂÌß]sÝÿüSG÷_4Eº–wHŽ7kªí¨Ö“±mG²:êp‰2w¸ØÙ[±Ì¢ÁWõéhf¾Ö-qøÕý³ãyü@#¿Tvj©ßÇ#m™
ÔÔyaüﱉB%=±’¯”ô/]px`u®,ϯÖdưO\÷ÊÒ>NWˆÆ	S3áYéݨ|ÆÚÈïú”¦Iø¿Çxlmšá}ß{cðc—ß{Ø(¹,Ž.ãÇÇ‘Žq™Ž;[¡"¶g{uœwê0ügê¸óÆŒÉàî·×qÏÖtíë÷£ã#¾Ðk¨¿™"«4ê´}úœ`{3f'øm4!xø>F¾/`@G
{bÀ?iU·¬v]΃©ßº8ìQk¡uGÈY™©:ÐTŒ1ÒL†¤å(G"Èû1‘Ë^ŵÏUMŸ±°‡϶‹¾{®î4M‰ö¹ŸƒldUÌ­,Õgö+ñ¹SL§Ä.Ð%‚­1ÙÒÆ&à¶Ë±8ñ«ÚqÇÜGct?G«HöäiGÁ«s^"Ï8‘©0¨=sü­ÌFs‘èQÖì(¢ÉIÀ¡ûŸ.Õ¯Ä-¡q¶¼CКCþvå1wn¤ újøPéÈjék¼­Q|FJž‚÷®m	D|994ƒƒdˆ„P&ûègPöLÐl„Åw`s—2Yû>KåE9è5r*»=Fs-mS-îBâ]²D‹8öMF•Aô³@“ˆ1x¶É¨%ØÁƒ­$OðÊR¾d<]Ñj„Äo©Ë9õ¾ä¦­¨a†&ʵã°ÿöl˜h.˜ÔdÌ`'³r…Öã¦æZj¢&ç¡f˜‘aãÊiUò™Éå4Æ:7ã?Á\f#9Ê¥\èiAW¹e•¸¾d׈T”»GEà%áBÙc•Éó\\ÞNy
¬Î^õZ	Z—(ß©&¾Ø„‘Á4:ˆ=áÜpRû2–|/«5Ôºv %PuÊ¥À8º€kçY½gŸì;Ù[Ü\vë}¦"K9©'œ*!ôXmc†nVMtzNÿ‰Ûîz›tœ5"`S“k"ñE;yEâ¶âÀUHCm;¡åHŽ«BÞTîó›ËlœPpµA6´Z©	K–Prh6,3tÖ±}¸Žs„:
çž³ä୴̶tã*šËÍfAô×¢eaÄO™2If‘·Ÿð«ÈÌËiyI\Q픲÷šIòlW‹~]k®sŒ[.Ü^TŽfz'Ãd¦58¨î
éÞ}Õƒ2U½µg+r šçu×R­ÈÄR“òE~у¤X¯óì/…)'$JH´Rg­ÒzÕ—˜_æ[ŸYê‘K'IN÷Áž‚Ô*QšŽø ãú£©ŽúH¡)Z¼^gKy ç/BÇý9â*N
ƒç´ÀN“D9¬ž'E«XšÆNr"á…,àÑãFU	çÕ$Á®^mÍžìO„†ß.I°/6aÄ*I›"®ô÷rÒÅJúw2ƒ›Þ"ö^M=.cý2Ø&eÕN•OÏÜ}ß|úuñó$½ÁŒÒDúó²ŒÒ®žzYšùÿYó·Éäüo ée~ðâmÑ´zòÿµhºâ8ëx4Ãп?·ïÆCaœm[ñ¦Êy‡þš<œl"Œ0ô´©Ð»•๗ãƒIC$óŒ¯FLH¡ÁLÎN@§íÁYw¡~“²g¡Á»ý}}Ch–âžc\p$&d%¯°6‰&é‘]ô~Â:îÐ[î\Ü|‰gG~ÂÇèÚÙir›? {Fo#599ˆLú0xfJìCÆè¬5ä¶
Þ‘·hûi4)ò=9ð™ÉÀŸ0£«}ž¹†’Q>MCÕíLö×r‡íQ0ß[ªS]”­˜k\µQE	“7€Û+49禵Œ-8ŽLûG7ï5n.¡ÿßzö='×êjUžà]›i“ÌÆ(âD[)ùSJoÞM…aÑNÝÓìƒkˆ÷“rРù¿§ÛDC«R“tiÞL]Ȫ¸õ††Ný¥äK>À5˜&_+¾6ÕÄáÖJ¦±1HH/ñþ®-ûR%Ž›IJ…«j&ÉI%Ô?ÂrŸäpä[ÜÝ&›±KÏO>ë4LíxG%ÿ†bÊjÓ6/Ê¥Ræ[å¥V¼jsAƒÓ²Í×
Ü–°-‘%ÔCrõTã‚aNæåt-¦QM¨{Ϫ$«Ü.ÅÝnÓ©#i^EZƒhÝ0Õ ××yåµN<ŒK8¦^ÀÁT‚U¬iB+oöX²¼c?•F§††óбr–*;P‰´•2¸=xÓæ¥Ý,ä­%íDâAµ[EÔ’”ÁÀOùk´ü«æ® Wnó׌­yÞÆ(Ú›4Ì2¶ÉeÄSi÷UÖSê,Rõ­–ãë|—M©4y5
zrñ’h³ÉîÃe§âB5êøRQ½a†€ýeò*·è?o ©Q¾¡J  D«ïv¢9=wpÓÏò•gå€jAÓfÚl§H©\VñËrAÎ@”‡ª,êùTûUNw­moµëÒR5pÜ“>¬z/H—Ì2£uA‹ÍÆLËå1ZhWKûD­I
hÒú£^6ÿJ±w·ù‰½W/IKKå©Zƒ”V“6Ë<f?¦ypv¥T蔞Ê^K\™ö5>¶H“‡
¯6gÎÍ:ã*T]k«Ì*–E2µÈY¥‡Q£‡”5úòVs‘ìpGÍ÷ö}q§<ÕâŒ@ŠøÐb
!">uÿ³Y=éWÄ‚^7ÇPŒ£ÊI×Ó¬¿šÊji£‰cíIº#ªzK›}¥£aªvŽÚš0³¿7o—qÃN‚û¸ÊƒÚÚƒ*š˜Ûx³a(gåEÛÝøTб’Ìc.æ¤ù±šÎ\qêÂŒ7²W
ȵdqElë‘À§è5Rn­¤‚sÁ®1­t@Û 2#£ªâÍ@ü°4tÔ‚¸nvÎ^’FöƒÓ<®m;×RÑ=-	µ5eSÅ Æ“~š©éäXnŠÂY½©§u¯7†=0
–¥MH'ÓèhFU&•rÝe^™'Ò“Y”âFý•NÎ;JvÔpQ“1Wì§p˳Öt­²¹§–¯`ŸCFöÍ^ӽ×YÇ#%vêjqã;1kÜÒ/!èŠ;ÙܸÙ·ñ^å¹;Ç}*¨vµé|­ô‘•b„+ÿ®(q-GÌ-§4	Šn«¾‚T\)LŸzK!¬„þ«ô:I¡À@°£ñôt€ÒUˆlr‹•Çãõ<ÎÈÕ/z at4{•%<´ëz[¼¶¨<‹•öH¶Gh=3²Ã“á´}9¹ÑD#PñÔϲþVXÆ3‡<˜âPY»¡ü˜i Sè«æÛdXêÈŠkÅܺ|R…ĺ:h’«î§«âõÈâz§œg)¹êóäo¼ewZžHìChµú¼Ë€Àƒª˜¿F¤îˆ—Ìè£ ±×N†6/¢Ýr­ÞÚ\µ>ljf©×©-"ßqñ•ŽÕˆ]é5AŠ
àÞðW”gÞWbÌã×RŽÆ½a„ÖQßZ.¤sÒ&ön\hï,ª8Ýr'@mûª,³ßÓߢKax
05Æ}qÒËÁÑêì«Ï\•57õ?%í}@ hK•0 Õä€Î6£nˆ˜ï³Ž¢s?wÖ6h\à–ð›œøÕï;2}WÔ”Å>ähÁ‚­FýÇåZKbðk¥*Û¼ þUé
ZÜêâS½xÅÑ¥µË›M‘„mÒÓcáõ­¾÷I'Íü—j7myù©ÎÁ—CR_ÞW
3h…6q•„ÍØÚª'¹ÞY«N8íV:VΙ›§ÍDí
¢·×f馺EÈ*üõl—öYs­zUN¤G¤rN|ÎÉ=h7V²—+„{Uˆ5ûFp´ .à÷®°Û¡³ôc¦ÚÖr|Ã[ÁÚfÂöA›ªk¢˜[“K‹‡ñéÑÁ_àß¿Óò^¯endstream
endobj
273 0 obj
4138
endobj
277 0 obj
<>
stream
xœí\ésÇÏgÅÄ~óÅÓ×Ìtª’*À€IÙÆ6¸r9åÈUˆÃæ¯Ï;û˜™•V°“¸(¡Ýéëõë_¿{ôlÕµfÕá?ùýðxïÚ×Ãêðl¯[î=Û3Ô¸’_W7@cáI»hV~Øã‘f5ØÕà|ÛÙՃ㽬}ðçŸþ#œ©F}kGôà:Þl6~ýicÚG××»þ²ÙØõ|~«ÙhÃ×ÍÆ9Óvݰ0wÛl†a„6·¾Ñxv¿ÙôÐníúnv‡¹6ޝt»±Ø2öØIVÁå˜{0ƺ¶3;}ÑPG˜%ö1"QÉAbl3;D¸@«À7ã{ì蜅ytw8»qrmÿhéº`
‘!ÓŠ´`Ü0XædÍû°rãºv012GiOqO€6ò/˜ñŸíó^4NÃìc°ëŸ`;ë§ÐX:öFúõÇðÕGüŽ-<ò9ÐCŽ¡‘zá\øZ\èé@Îrœ,RËCø9‚å?b’<¶ãQÂÂ8÷m2½~$zKZ¹Ç>6òfàY|M7ìƒvÌTœÂàpŒ'ÐÌWÂ~°7äÌIc{žà%¶>G¯並½béÁ¶‚3øèÇdòpÆÄ¬çx´1ƒÏà0b4‘ÈfôàT¡cn!=Ñ}TÐä€tÅ,pO`Bs##=Õ$:ø 1t´Ä}"]\`?N½™®q°i‚éèòJÈ…°a@=^q䯩n™ˆúÄô>Ð 8W]Fj¦~ÈIü9màZ¼FÐò¶‰,=q"¾ã¯š€—N\Ïàe&»þ°£Šgø£Lø[*SYr'6DM	ÝdH[x«á’ƒ”¡Ví
l¦ïߤŽ[ÆáI(ÝÎw­³FQ—&s9“ô€!‘OÚB»!«§YØ”2­3_ã3ìy/K>t'ñjCBi£ä:B)¤xêfOòd2OWJ8f±oÅ'ƒú†%îÎGè×;zý']d§25wÁùGŸÏ:ëŒj°Em»|â]ŸÇ|hºWw£©øZ€«•
ÁàëmúÅÕ?¡‹šÆyÚxĸ@þ$aõ)òt¤ÅU/‡í㺬 D¤:[ȦZ®bÏZ °P)µ ;XJmt=FY‹ºÃG$XF
‘®=>B!7ô¥„uÃ’†ìTÅmÒK(ûH3ü@3¶*4tS•˜>_ÃŒ&	º<ïD»Àä•­Q
áÎ}œª#¡Uª‹P+
7xR•ß®³&dÑR#ŠZÇ-“‚=ÑoŒ	à³3QAñ}RtÅÌñŒ“GLZ,Q›&ùNf=ü«ÊÓ°þ÷
2¢^Ã¥A˜û|`ìß6Ä[ i, ‹'øû¹âÙ#Û«e©꨷&øúøùÈæBkå@T&\Κ{€ùϱªÀŠšcÇÓ¸ïí²n˜k!n1|„Qƒ}¿¨Aëf WûžežòíÀ–—bèÄ6‰Ž´´°/Ë‹‚,d2k¿PåÈ–ˆ¨ä#šØ#äj÷˜øJs½£	²˜ªaI›ò.³Ý_ØÞדºCa+o)lx·µª,9>A²	þŽÜ›­ù¸|O¼
x>X:lx*€«ax¾æœO×›.’‰ZÉy[µeƒëûZJªAE¦”õÔE†ð:qB0(êFõÅIéÎpÂVtgz]Éy•‡,|ú69z	äBêíFuÙT°Ü—iáz\dF“aÓ6â Y_9HLÁÆ¢›Ô&Ä4nÉ™2@‚AȽӨCÖœi­<ü”ò¦ŠñnÁµ"–GÑéä7ñ	àrϰ7¡âˆœ€<¸òþÞ
‹0"î\¹q¾:+¨AÉ–Ü2%HÔD 6L9
5SXe§`(	T‘ÞÓš>‹8ó‘THÜ‹vPá#ØL~®DyD1
õ9ÉßéÖYÑøËâ†Î™X&÷£/-¥³lŒ‹X¬Å^:ãHRÇ;UUSü„®SMµ?>&$tQÝÛÄq;½aKw›QΜs–`͆0&÷±±q(Þé+{ÈMc¨k¥q€–5””:”­ËvÑ—ù©š>ÚíÒvèÍ	Ü„gÏR&3Ù›6d“¨:x?¢ýg*¥†þ)¬ÇL©´XX‘H÷Z¸+´ÿCJN°2Ž…´Z3±gšCb§[ö¾Ú{¶-ÔS69®ŒfÇUá$k÷nÜÝ»v÷óÕ‹ç/í]ûËÊì]ûÿ»ñåMøu÷“ÕïönÝ]}uÉ`Ÿ%áq•ÖJ¼êsÜø:²V×#ìŒ:öاί-Ý^Œ‰áƶîÉðÆ÷¿'k
:&K›b;ã¶×˳ç8¸|Ì­»—­kû÷¿[×
­¿ÔnìÔ¾ÝnçqÖü[¹à-	Ýû炇eZS.¨L@6`¨°BŸöÝF^”Œ¡´j
»óÉ
°iS¼ ÇÖ÷̇AA0ÛP÷_œÕÆ›±µg‹nú~J€P<Äqì®2¬;GÆ@±$ß
/á"Ø;8ÓGƒ’î½IÐÃÁÂ2cÛ÷[î‡ëJ¯|£
pÈ0|ˆ9¸¥ªÐFæFᘩzZ2Í «á+诱“jF“'†-×b‰Ö?%—m<8CáH¢åÇdãd£&k³§¥…Fã:3,šRêpwÒ°r>š­ÆƯ:/zÛŽc›ìÅI(Œ
˜„¡°Öp!Ø.3;´«YæÆd–e•{§¶ÅÑVŸ·²Ör@›ãÎ9Ö-F›ZétˆéàžR|'‡»öO+ÊE±ÀiYÈŒ“6s73mªôs2Žæ:V^”=[Ï_c;ŬÐ}´íjí«_ˆî1ðåv)ñ4$¸²o8qÌ$…TçŒëÓŒ=EØLT©Úuê]‰ÓP…j5wòdž0ŒÙ’eí,¨©Æ–ûÛsýúRÊ÷8%ÅÜeë-¬‘柇´NòBsAÔq.æíÂ#]HqÕD$($”¤S•aJRšùœœˆ&XÐèáã×we61åß§Ó{øm1t¾¨6°Ck;;ì}=™ã¤ff†Ä‰í¬Û÷)Úº
³½ELÙ~L^eé\
%ì€ÍžƒºÅ<Å%æmˆ«=œC¦RËwÒFžš‚S¸/èÛÇ™Du¡B’ˆ0²o¶ˆ1;t$Pw3©$Mwe“]±OU²UíëF¡¼Ö•¾’ê‹TPRåýC.]ñ).é\ifPˆ>²~,§Tâa.Oà$Ž«ìàÇjl!8vt$/,.j«
ŒB?â\$CãɇyåÎ)8)Õ;÷x©¡Q¡£"=a¨ËêXò/$‡3¢¼¸l-1uH,›–ÂêuAÂõ‘µÂ~Ó(ŽLƒ¥ˆ%»“`‹¢T +ß§@ŽCÄõÚ±ßM°]ûºwUÁÛ®õ0IC8BeŒ(DÌÃF¥ä!•AÉI}‡_1CåÖïRçcm-:S—ŸDãsÌw@„Çõ5Ìvi=“ÈÅDGùáAzø¢
8ZøŒucµŸv3Ý
>«žm„†«y%5?­ÇáU¡x¬D«ÿ„QÓŽ&á'™Ö‚¡WRû÷¥Ç:ß­7Ûõé!/}‰õΪö|áæ_æ‡ùÀ)“}›Äf;|øP¿gøßËÔïÕõ?-±ÑÖR
o…¶G» ­Œý†¶wˆ¶yÔ£k1•`öÒYÐÁÌÊg&u“Çè‹£ƒ7IC9ÎIÝÌÁÜ`Ô¤RéÁ¥A•'ÏÞVê1›“ÙX"¼¨‹‡n{C(µLˆÔdùÆ-ÚH«ÜAQ¦™HµšuêÐÊV¾jSS*N¿’´ì¥ölýüšÆ¿Øm9óU¤Ôg†JI.ÜÊÖžœŸ›Øeéd2¦nçå Ó*ò]SÌŒKpf[Wˆêþæ;Ëa=Ç—Ò‘¨+u¨¢Dâ/‰®£º"†¡ÔjÑA²æú¸=4v1‚¤ö-Ä)ò.×Oä¤÷$Û¬X
UNU
%‡fQ´	³v*¿fj„¡.FQ¥…û¨ÅþbÅ›3RÜBç@™µr£Ë˜HçwܸŽ=t‘?\î]Èq&ynš ’=ζ©–î‚Û\‹"-Ó™óÈšv3kú²ö_å–mTÚ#V|Xõ lõ\ÂLèÚ·1Mÿ;MÓ“ZúðÇ%¢PóW¹9öc”ž¥Ö7Í;ði2)o~VæEç˜-œý%£ñ`	1Çb|D‘â	¢Â®'©ëiîz’˜‰¼Ýû¨Y¬.ÿN[i‹½	²e}LÙÖ¤ž>FO0ŒOi ,ÇUøMB8&ÁQ+/þÔuøG0´frõnʇ\‘2}hVc(1+ïÉ”5o­Ó¬¼²¯ý|9˹ïäqHu@û'—i‚´D”ç—Jvx¿•^‚ÏÅ/­¾IÏSáŸ7•Xâ‰åðŪ-#k1’†eÅXÜxî{PÅ º^…ò´°xµJC€ü7'ˆ})Ä”áwÒ`®ßUCêë{&¦˜÷´âˆ_lÔ 3ú·ÒyæZÉïMÐUi¬¯"ø¥DD{–yùÉV¹ørz¿2N	"T™SpNÿóTm“éàK à@^˱bÚaùF’ßkl£7Ó¬3ß1ÓõÅðEÁcž"Wß.ý
ˆs²$2U’Å@¡-Í_{¤óÉ×-¥RäÜS%B~‰ö4/±TÕQ€2eÖ©૽ÿ³/àsendstream
endobj
278 0 obj
4081
endobj
282 0 obj
<>
stream
xœí[[ݶ~_äGì›Y¼H¢
$€Ó8iÚÔi
’"	‚µ×Þ]xoYßÿ}93œáPâ¹ÄIŠ>†Ïž#Q$çþÍpôËaךÃþ¥¿O/î?O_t‡§¿¼y˜þ<½<üô(p&^i§n2‡GÏèIs8ÚÃÑù¶³‡G—?¬ú¦_µM×c˜Ú)«5k»zܬÍêKøöÏÆ­4p%Œmg¼[ý§Y;7µ]7¦q(~jíOGŒ5V3Ö÷‘%!òöè$òÓǵ"/iààôÀµ÷};„õëÚÑL=p7¶º‚Wͺ7ìlõ~Ÿ§‹nõ2~_~†ŸOáã>žÁDZŒÃŸ?Ë`œà>N#e ¹È‘ûqÛá
4*~³@g”úS¹x›/žËÅK¹äÙø¨X×öèóã*Î	ÜJE¾q‘¶í'’×]ø·oø9Ù[Ý‹sw¤QyWWy«ŠƒO4Ôýtñ¦Fß»|W
Ñv¯t%÷óýwµå3!rñ:Ìsž¢¸päÝÚFŽk»&_VIú„wôö*ä…	VÍû¹»¾o-«û+ºë£1ó××ù<öǦP¥µC­jmÇÖüÏ-#iaüð#˜ù„6¢tøÃíDIW¾-l§ŸÂŸ¶óA¶ó•\ü:|$¿ÈwŒsn´0µ3eb3½.Hw¥¡Ýø©õž
gc››Óo4²û­/‘®Gº\-¾™¾À½§Q… y£ÜMc¢Y½—,á†ãxã
~zTÉ+ÌëN(‚š¸aÉôž5žÀžñò5=MÓ€=Ú‘‡giôÑf{Ôûˆ@‰`ÄþöÐÒ#h)ŽÚßGf‰JÙh¾XÖiyÄf0}}ݸ1’ÓÛÕ[˜×1YÐÀ®q–fR;Ä­xTòœ„o
8¸ÄCµÍ'-˜ imÞ:p×LÈÎWfC~¶!7’í³Æš7€ŠØâÁ¥ñ·¼ÈuÚ¹èhsÁ£Çòž£}Ù‚TAç®E!Î%©¥É”‰¿KÌïq‡¡O Hqëû	4AúÙæÐþ+ñã…Ý/ñA&ï&jÁ”øVW:çÊûð®h–VgŽ…RG˜
œ4cÆi<<úêàèî:ϲy€c™rìNÒU˜8ÿm“©Wûòq0rö&l|§îÏ4¨é8Ts¼MËÄë*Ü1ÚyÜ;D”)“x›Œœ3¨W0KTºcÞÂ5ƒ3lá¤é=!ÇuãhÌ5Ä¥²Ã!Um‰ê&gï-°AI‘DQøv¡.@“MjÝ‘âjsIÛÕÅ31R,"=‘M¼‘ßdáTn£Å%æþˆ}0¯C¼€ò¶€û‡>kû¸ú.ÒDŽü¸8¢ _4Žf:£íDϱ@Žq8%fÀ-%%õl@Õ=O¶oœÈõÅ“gyGúÚ /)ò@2FÇðÄÒc;œ3ξM3Ñ_›¡µaÕ‚m&÷¨­íÍ#^B@B›´ ÃI‰5¹^ƼáN†¼2iDÿEäB´
ý\átÛâ9º‘p
àZב$´Ç’Î'ÕRÕV®›¥^yÜ*V>ƺŒÃÂPKºTÇù
j%Ð\:†ÂD´…vTC¹›"ÁÖ¤‰œh7Î7˜á¦¾8	0± HÙÙÍô„h*3dòuz¾ëQ¦¨Á9.°µ£3‚ÇÉá?²X“—TÊïÄ+Ä "ÂQîô„å„“ãfØi§à[
ËÂiÓ%gϡṥ,‘†)<ŒÃ	²§ªåÞk
Pãá’ø‘D<Ï)#,Yí)¨^þ¡¦8Ð(N;@z ô‚é"¸ónB/Æê›¬p“úv°‚ß¡¿Z¡˜¥ãY Ž„]XkP».Æës;ˆ›¿a¹²åè¡ñæÆ`"N ÙUöP•4CBñHµ‚Î'⨞GTÃÓFèBÑô6"Dçƒ Ä*˜8‡Ž€£-üJ„èÉ«/ä5ÆÈR øD¶>¸º-º~’Ø[	à)S؂Ǯˆ†¶45	¥e_&Ð
y›¬»°¹‘1fé„y˜"Ža\?àœ&ÒÃê‘ýí’ž0¢tÈÂìß™ªÒÌ$ÕÍùSF…Èö‘Ë>…_5)p³›tÞ$¬á–ÒQî+
Kæ’HãvÙJÒ„²!QÌloÜáÜëJû_l=)Çß8|&ÒúvL¸à2áBÓZ)ög!¦è0ؼ}£ÑÜ;ÉΛÅèÈpÞ…‹ãUÕñºÌ[ˆz¥Z:à.Â#éUÝ­—[Jhé,•i‡× Çy¬Ô°ÏʱQŸ»÷qÈ8ù.®¸ˆûpsŸr2äÒ”ÍÜ$-"/ÿ¾‰¢‚-·!·&F3‰'¡0èTóÁÀ˜“7„ÂÛmH-(=<â«Â‚©V¦BÇtäÖûuš‹DVÒÙ³Ò÷SF\ /E²•`ÿõ+œÑ°< *J—öHZC”رÆ]ª¨%‹ÈÒwlÒ•ˆ/.l}Ž®Àuï%”ˆ‹³$ÌNÅÎ(£%H\À\Ú°XU±0ÎÃ.qr9eQ¦T EÌÊ;œ°ô_,†\êY„R		˜ÓhRj
€ì‚pÈ·¬\§X
ó
ÀØpò›"(j½.Œ<«ÔK˜éQÚ3
ª¥¦â*–s=ÁF•H+ý¦¢¬Ãr²ÏŽI
O´W­"y°š@áD¥<ñ9©M0’ë[‹Â$àYÊïç‰Æh6qš¶Þ†36Ì"—,”oD®ñIv?6ÐQIu·×)‹5ê`"íyGI*>n§ì•¬þÅçCºLØÇ0Í„Ód—„njäE¥N‹pIêÁR×õ•”Ï"u¥OZø;Ö"Ζ,ƒµë^z8¶ÉÉÆÇpÕ©ˆLùM¼³oy!>`1“ßs«¦G1oLŠù™èÉUM]§	7Œ½Ž˜™Æ\—Å>åº^$¯4¶ÖM¬Es
7K‰éÜV±H®8ΊL+«h=î»Æ˜¡ÈÜêMÓ;T1–Ð9ÍQø"¨t<ŒosR¹H«ðxS®))]Šl10âQ-7Îèƒ'–¡EÞ£Ž9Jõ$¬w¹@ÆEgêÞ€7XV†KxOµÁ§±Úe\´ÁÈÜ6„Îü¶s~@ptÔ
”©¹ýö2Mû«sÔSÏt·÷·Ìw×r«…«œÎãYuŒ#wåΔÄ'Éçô| ŸÇTÏáÕ	quä…&¬<ÞV­&¯åâ«Ú|7µ•ouï'²ÎÜqVkO¹­5²<ÕÙÚ²F	ìRÓµÜÇE1笹ÎÅO)êE¿“aÔmõ¡·ù¡«‚cj+êè?MPxh{;;ŸäþŽRé“pH‡^%Íbq(%º‹Ð™t
¿V»t|”2Z9·éô{µé|×L6ŸÝ¥s;î˜Q½ ’Ö¦Ãà29åBî•FZ:±º¾“ŠpŒ7œòÙË8‰^ˬK\Gʽ.ˆöü¶j:0ÖcRY–‰™ôêbŸý2£Ý£œµ~“Ê€tò&^ŸÌ«2Wof=»:Â@‰´`cóР-KA>rO•oÊ<:WsÒtÁéW¥D]ÔoºÐÎ[|€ß’M`Â@g
Òb]í®¡®0#?²û4u®¼!4IsŽ¡m¯-–i “¼šE™·8#V«qõÍÎòêùJIqµl,)h½À£f—6“²ÞÊ9Qjâ:uv÷rêÃÅ:T+.-ÅSÎä°hy¢²6GÙµ%EW¥ºœ!)áò¡7óDØsŸ]ˆëŒZü¼J:3+þðþ«§ÑHKѽB´—~¼¦]VÊr¹Á“®Ï›ôÁ‘ä)Ô­T9	ÓY™8žh™í£«Ñ^“åX6"à‚¦˜´çûÍIë>¡½@“‡HK³Œ0ñ‰`Ågið¾}Í7µ˜&³ÿQ0î÷hY>Ùx«ß×ß‚–PoG~•­
O¾ÓK.A¦®²úE±znÝÑÊ|‘!Ú=tVÐ5}&ïÏ@:GðïøÀËBiÙ‡©ÿ9á#ÂV·ü¡²ˆ÷"_ªèÌ2£ÿKà5üàeûÍnΧ¢Ìâ`{Vf8E9AÁ&„7B_=mÂÎåͽ°aDôa©¤t'£HÞ"{)cƒp'£‹tüáQÝà[úp©œͨ*íZi­âЊòtÞƒíÖ1&Â[[Ðóø=¡z›^^c¶L{?ð†dY¢L<ýÙïpÞ¶Žâžw÷¶œ„¨çP¥?NR}?—¥H?p¿ÃÚ
¨_öÁ'nÆá#r§
óøØª@Ð#yå2€Â‹pr ·;ˆú‘‹ Š.4PU›1IŠúrÆ;PSg™K¸eP?Q$Õê1lÉvõCüßÅI~‚VS¨ôØ#>âŽú!lë’"øjç'çAÃ'4‘n¸áÞÍÜ®ÒoÑì!NÒëCwަZ…
4¢Ñ
rb	ÇÔª3‡ûs76phÊ[=Ò´èÃQ½9$=$Jø—ʶ*›¨‚#̉(dº§ÔÒ[êº)T=Í
®ÇsÀ/†p7G—»óÎé˜Ún»ÎÍ[pt÷Ë2K­l¸(Ü„ƒ³†Éä×\fÝ­œbPÕ^£3攑jy6›O»E%Â.|ƒÔ6¦mà׸õ<Œ§Æ·ŒC–ßÐq·_~;„õTóì:'e'\(	îý’µêE5°ßÞoÍ19'ûsAy*ÕU”•ÅW;$Àø±Ä\gìzu†~ö‚cjåQ¡¡\à:zdW컡­}›PîàQÆ› ½t¨´‹ºâÜå”n#GÁãÍ¨Š–ÊÚ\ö\4\ÅDÊJ'µQÎÔ±˜üKÑ̲>9v›lv´[tÉ…N4RÄR´SP0<1Ë¥NP'PDþ¼AÇ¡äT}Ñ
ór94 ëÌ}<ÔÊ·D–9[A2tŽ\V¯ºKϳW^t³„	æÆ±èàx­5%½dÃØS¤ ô3ëãGYSk‘ù$oê‰v¢{“×êgº¦5†{µ>ø*³À/Àù`Ô^ýlÜ–K‚ß6E.Á'´¨¶Ê¬€,°BŽ}Ê(©ÞŸ•KT(võ”-åoLnz%lŸ¦"ª{ÔÛ©·­¸‹³÷¥w)^`¸ÓÍj{õc³~æÒ5vobGúĘ^î¾%zð¸àVµ°õ³“ Ù{§”â=<:øwü÷_>
stream
xœí\éoÜÆïç­ÿˆýæ¥á¥8É!Šˆc'qš:Ž£¢)’ ØH¶$D’evüßwÞ59»ZÙ²[ÔA`‰âÜïýæÝÌ«yS«yÿñsÙγ~~p1kæ³W3…sþµw2°ë;(íßÔC3¨ùî‹Tó^Ï{cëFÏwOf?-lÕ.ºªýe÷?¨lDßÕÚùA»û¾ãÕÒ.¾®T=΋Ï+½xZ-õbÞ?ª–Òð¬Z£ê¦é­Ÿ»®–}ï|›Y<¨,û¡Zv¾]ëÅã8ìfêÁõ´Ò—•†×A'^¦c¾óc´©ÕR§'vô³Ý0À¦4l6£;?£R¾scü&L‹«ø¿”í £1ÚÏc|w³“Kû?ü^š¦Õ
·Á/ʸŒßZëÇõ½&Jæ´_*;Ô/MS÷jˆ¢g~ÙÕ-^zJù¹N+Ýy´zqéguéöeer"h§+?âÜ/J?V•顯Z¼õç]\@çç0‹C Ùsã'î Iȇëû6»Øóÿ`y˜ôú\MX›?ê¾÷ç—0ô‰9´ÈŸÐZ©¤òR^/åÁ„gâ«8ä
vR™fñk$ìOýsz†(»x]µ€ž®ãChû¼~˜Æ·uJ ü&rN}ŒÿèÔÎæ+ùSz6z0%cÎáqZ¥qøe@j|ò[äΧ°E€Ël’Î/¡q'¾<—$0OÀÆF<ð29þ–rà¥G|ÛÁ]‡sߊÀi‚p15’Œ&{á'Ó
7º‚G‹W8òJ{RYÕaÇkl„UÖ¾.`âÆ &f}‰õ·ð°#ý±,ìŽ{¼$àCð½°A‚Â`L€Â}ßß’
+ñŀഓÿ²½æøcÌé	Ô®’É„Ep8¨`
á´ÁA$„ðÂq•€jeèd+]a«–d1/‚Ž×F8É¡Níàèl£+‰t#A{]šß€±šá’1$<'ÅØÚ#{¡á‚4
p8eìòÑîìûÙ«¹W"ª:OG7×þuçæ]ßuµu 9<ží<þûüòüêùlçŸs5Ûù~wô‚ô(´œÆ%ôÚí«¬}ÓË·¥ƒ?O õ¼¸mŸaÌixyà÷r¹Çm ëQ¬¨¡øåq¾ºC9ùmxù]ìù$¼ü*¾¼¾§§gJÁ|ix´Þvc­ïm:+‚ø¤8æ4޹Œo/âãýðHzÕ«ƒÎŽäàC`5Ø‹Á§a»`»¤v'«€úó”±É`q(‹7*ræbk„\e‡â—`6ñã_òãɵöVÏG»Ú|§Žù’{·ƒh|—.ÈøéÞúÛ¼wr—oS>À]¾Ñå1ï*7ø«pë£×º…¨ooOD´úSµ
®ìG‘8ÿU&1ú‰ñ~fA’OWVüa!ܾ…Àsû×?Ÿ‘:>›zİq)»¢\•4æë–Šìú,Þ·ëPû©‰¤)ÝPNu(Þò9]3õ'hžÿw¹õ‡ó_¶qþrCÈí<Ó6‹ÄX¯ŒI蹄}eJùåÍ$èÀùABŸÀìN}ƒ2`ŸBz¶ÇS¸³!ù 9(aæp®õr*‹âiG—z¼‚øÓ•,œë“¨íKÜÜ4X«{J‰`„hçYj†`Ü*ÍDÀèŽL›r¸6Àá1”³ÎAŒi‰á2:0v,ç!ê<¨
Áw‹„pžøFÝ{	ÿz"¯MÄ rÿ‚aCƒé‹9b¬Í(áff£gÍÛ3ãk§APjA÷½Ü8œEv=ƒ&2-bd
‰MG™¦^kÇYœ”ÃÙ¦ƒŒQGèÒcTøTþÚ—ÅÚůa1-dô;05ä&¿é­ÏC
2|ƒÁ€üM¢Ú˜g{Sé$ý…ÕûûÆíM7à)C’#`a×ãöè(å½=£Ð$+ÂÌŒ˜H¢ùØç4þe(Žò/ˆŠžÛëRN°W?	†§@ÝDiÐÏCB”É“&xÛ¹r(Ò­k3ºév žÂ%wuH,`†€SÊ“ïnEéѶÁf¼
Ê:y)jèŠõ(ÆøŠÅåtK"þçsZ®Í%‚¤BÀëÑöÚ4ì“ÇYÎZ4º€–¸\” |õð Ö0wƂΆ²<.‰¥6M<•Òº­ÂË/iÝä®Ö"7%‘LäF3DsWÞ,ÃŒZf=Xž»ýc7JEá…¹Üܦo	ÌÍâ.IBW„JžÐ5í€T˜¤gBÂoªcÅ?Êh-Dw¹/K“-€@"JOr²­é×¥ÌåVºv´*ׯ¬ðnÜ	êOn„ŒGµWÜ_lVÎÜv—“—}Š¡‘¼]ÅSãÄ{ƒÂ
Fµ‚7 Ž:„¬è¾YŒžQ­Í|#·‹„øs¢RA÷sôYJ½åÄe_H\–Ò¢-¢àRžcUoZ0ˆÓ"VF0ó›\“ÌrJ[0qŒí$Y:B–¦…r+‰ÜB6¼ïqzÝÏê9
/*ϼ/L¬´%'føÎŸFƒŒ„Mô lfúmB2hkQ¬ð¢bªÀdÑ0Ctb¶1í1k®´Kx,R]¾Ò4º6àØ„eŒ“e±nÅ	…8 Ð蛢Ǵ!hùÿá~Gj•^t±Šîw$ÔžúQÇk¶“¸áÓ—¹oYôÂÉ,D盯Þg‚`—R«à¦zy|¯8ëetþWÅ\M†A_,¾Úà ïSq©@Tàn+ÿô™ZûQ'
(Ôí¡kÒº°¨Ì¥ËÔÒЈé¼2EöA—
$6ØE±Ë­y1Øû¡¬ýQìŠeIÒ˜íi;–¶q!KÎ?Tz
:¹ÁG8!/Í›/Rï	êÈ¿'»Ê캕ÐÜ]ë)ba†Cs»Eã¤K
ÃÔe>pÒ(ꕬ„TÀ£rÂM
Ÿòz7ßIÍE }Y{k’4×QbU¨G[4dŒ:ŠŠÉ&ÚÉŒ²&spb‘Õ8aÓÕDUjµÙXg²¤X=Fýmx3Þïrd°j,Ù8b2DØÁlè>i>j(Ò™GÜîP‘iØëš0Ìh‹>\ɰkŒ„èÔÕˆ1“$ Š”Vå΃Á
¸6ZZÀ®C
4YNâ~´X[ŠÞrÑ#¡³ç
¶„.2I*ÞÀFl
‘Qm©£ª¶ ÌDÞAoV„Ùý×…;§^á`ØÓ½ÞåÃ!Ts©¤ƒ²g™™¼>ÜõÈ[®¼ÉRıN¢‡Tº;@%\Ìщɘ–ØFV§!UÕ ,ÖTûb¡òØj'ލ÷¶`Aï0Y<órr†ÇÌå×
ïú&¯—%Á_á´Td|¯ZSµêbµóÜ¡CºD1uâsò"eŸ“ïnÞ(Ž£n°ñL0ÓÛ±¿1.ÿ—
œ†‘ܵ±´Æã}ò%bÀ2'Éiæ
”º1¦µâÆDëÍ:ö`L)q-é’´"!Æ´ÜyŠRô Ð¤ìïVi€%ݪæðwá!½(™©íÉ»OŒË4ù‹å¥– kÂ}?ƒÚ5q‹®ábMÆòDLþIïA©Or¤[—Ÿ.8îØÊ~üÆZJ¬·bAçNs_=οÄÅ’
’8‡ô!|(üc¥	²Ì$xǶ™A^H‚=+ÉŒmÉðŸü?°
©BäiÄ|1ãZÓX\ptÂ9ü¥ªiæ0É&>ɾ¯þ1ü•øÔX¼£ÈzÅzl¿®r,LÙ*ºFçUåóBqõà¦çݘ¨KOÓ|mj¤bË2v|ˆ\•Ñ-4AQ¾ŒI4Ì%Š1*@9Œ€46Æ/6*¥Á–àÑïàÑz÷&ÛøùõÙ¹¥h5¶äHq~ݨÂWÒƒ[L—“`báÓm-}£71JÀ
Mò‰ Š1ÚXïdÃÇÆà1`nN$‡xÄI‡kQxÞi
vÏÎ\¦‰½+„WûfmF˜>2?sˆÉ²
zGÀ9
ÈùÏÌéÄ:>3èõ%tf°¹¸q%pñ¹·—A,X÷!4„ó\RÄk¢¶i1Æ\–*ÉGô¤ÊåJ)q\bjlõ3¦\`ïdhK™dèh¹šDq•ÍqÅ—wŠ+=XÙ´|=ý¦
=	L©TUȤ_ËmÇUésûiR"‹»Á ´¢’ˆ¡Ô‘ñ¾ÞO Ji¥®{Dèè‚w%¼7¤#H^q‘ð].€êGU&IP>Ñ.5UµCP$FáâÝ‹ïÚaZŠPèT9Z6rHËÎ	‰JE%A¥RL`g³ô‹T§¬ùÿ-Àr>
stream
xœí\[“µ~ßâGlù%3[>ãÑef4¤BUÆ$E€˜¥(RdÙ«Ë{9Þµó룾I­¹¬×vÌqQ¬ÏÑh¤VwëëVwë<Ûm³ÛÂüïáÅ΃ÇÃîéÍN»{ºólÇàÃ]þçðb÷/û±ƒ3±¥ÛÑìîŸìЛfw°»ƒóMkw÷/vþUuuW5µ­züw3„±C_ýµÞØêﵫþ\»®iÛ¾«Åoëó.~ªë¯¾„?Ðí+èÿ¸Þèb«¯ëMbWÓ;Q›fƒÿ½ÿ·H£±šFß
M"™ûG‘4Iê:n¼›àw7®m3ŽÔa<˳ÇïÆWÀä×õ¦«n`ÚçØ'u•­GòñùUœáE~ÿy\ȓȋKà¸öð¾7ÄŸa.xxŽÿÇqxè_„!†Íð58É[誃8×em{øb«—5.	à;8å‘b-
#øCm‰ªØÍ·©ÚBPõ°y@¶3 5Y­:dBÏh°ø «>­-ˆ„¤ÎÒ‰¼¾;cëE _; ¯ÅÕàòãàmg Í
ñ£óêµ’g0x\I+îbÇa qˆ›MkúHŸrkèTÙb
´m}õSÝw=cEšš…¨?¼qM׃îÃz@ü'Q£ÇUb¯ŠåœNóŒ6ìF‡õ}U;’
tI:ð}€Ïb»•v%…'$1pbib/|¸ˆZÌL(”
¾\“.ÄïÕiìúiuV´×:“»ã‰îe…Æï=ªÑ„Sj8ஃEXa-ÑC‹Ü)¹Iráýã¬ÉÜI‚Õ}XeÜS†v=¾ÒL]Õ"%QâÞŽÔ%^.êR7Z5p䜓Y6ŒÀ‰®ú¾nd_ÚñŒ;еຟ²nE	=aÓŸâÇ.fºª…Ö[¯H‡\pë¯h7êÜ­ƒv ×GòLq]À§?
ãƒÃÚõg¹ËaM\½Éø¢éF¤Œ·OœyàÞ>x'ÚêyT ü)áRk›¡7¢rÀ³Þ£ðNòft@’æe†ŸĕǗã+Îu¨ÞÛô˜!T-TwÆc‡ºEf„Ÿ(c‚œm»êGPgP‘~
_¼Þ¿¶EwÚ½°Kio^	†Düpb8D墩÷}‹ì_°¢Ž•x…
”º¡xÁ¤
;
“š1bjQiqÆ8œtV)¼¦O¸u Bô`L´}@!|ÙÒÜQ™îêùˆ£ŽÃú¦6™À,>K&O¶ê[*Œí^KY¼E†®(Kåfœ‚92¼aèû‘.í¯ØqKDÃ5—ˆ&23¯,(^¹¤Z¹’ÄOq鸩WëA1A\HçÁ÷b\ÂQøwbi<Àv˜à‹Ç'Ž |„f¨scÖ«¬È¸#ƒýF¼Uò|ÉP€Í§w#9¦FŒçÑ£&ÿ¶wڿݘ®	.28ú#M2ô @N›Î ¹À]LO`
¨4ððõš6ô0;þ£[y:G%ó#¡ÿƒ8¶mi\‘§©ï67þ’J¸3âgð½KŠÜØL	¦·oÊçLu׎¨{éñ¶|—wŸ;Fs™t™‰ŒÝM‹0…ë§çÅóÛ_æÆmj>ÊŠp©·‘ž>zh„6îïÖ'{±øÖe~ëyn½Éïú÷JtÂY1ïg>qïßïàÏWi-
÷Ã^Ú$/D•’†ò.8ÏZS}DÚþIê¶Ÿiú.5~•òÖƒ’¢Rœk­œÒx°¤M÷™è°®·²Égº\47¾XÑïÝç¼yõ^‘/f‘ƒG«¥kCÓ‡6J7žåL:£¿[xc±Ã	2S ›íÅ;£âmúôÿ‹€oC¹§èéo…•
‘òqÞû#`ôlBÀ;àfjýß¡¥™ùüïÑò=Z¾9Z–J¸‰žqÓµi¾×ÅΓbuN¦Åï'ß{ŠïÄSÌØ÷QÖÑ;ÃàAÚ#×ZΙúxÜ•ÇgK u½$½Ëb×ga.¨5tœ?~9*¹ývà
µ:_|¶Š"àß*º‰	%íÛx—'Kì^õ.½ï]¾÷.+ï2™è÷û;GØ­/"’¾mZDÜ‘4µ«ÚÚ-%èMJÎcú‚¿[
ÄbJÒ€( Ô‘Ô(Ž)uÉ1÷+>•|Š{cðÝ"ýPä8êìÃýÎéIoZ^¦Ÿdà)̘RÈ!у0oų¦´rNëeü-‚+µGî¹2¿z•§>Èiú”þˆ»@çÛ²îÖEïGeÝ![|Í9•vç%ÎùÄC~
R	]œq\êXð"…û}Ûb.mõ…2³îSî yj)-CqO@y*ñõ†êܰ˜‚ò—\°ò‘h°Ö„ꆶú,Åì?I‰•oà‘ÅƒŽ¤Û;)†ƒšSî˜LË´©jLLêê	r?K…sf³šz$̃f=u=åVßUu)ÖªüÍ–Õch\N~êŽÙR%#œ;a&ü±Æt*¥¸Ï…/ÃjþIòÕS•Y’_¦ŠŽŸk‹”«ŒÑQΊÜIW˜òRY¤FÅu¹bBmДMÚfác*ìM-”š³9K•;E¢•f29Ë™ªj¤ÚÆÁ,¾¿Ô-VÔÌ“ 8ä
Õs=öXŠe)eœ6‡Ô7	™jk^°bŒÍЋ^Fño¾¥Äü0"t³¿–Å™·°·!tË9K‘>’Wz¥$âþmR…íÈ£œ·MYì¸ùpô‚S]Â	IK1…Ê1&,œvhï’ììl‘ì–`¾©Ž7X× yØgçUб¡ly “*ÐÁË}ιê¾éRáMš«oÄ|²8Ó§¼Õ‹,’¡8(êû~–åYîpLà&^l!fgb6™àŒ)bW`§LNã"K̘ºz%ÎÒvMFh»XÛT˜"×"ÛÅ:`BÜtY&N÷è’ï22 µEõB¶&@ èjòSî_§Ê-øÙ#A’ØÕX±v-!ä$í½æ-	_^-F
F)CRЂY1rֳN
N<ÓQáëŠ^Šñº—=
)¥bSõq‚úä–L«ý–ãŽXoÐNj6¾£Ú­\¡ð0«n…	ï¶âyóƾƱ<ù"°\˜ìÃØK&¥‚0›Ú-+SܨÉüH¿{\<Æ“kÃÑ0E™tÛSï•]àë7qÝÚ&	zûGIÓZ]ÔWù·¬Ê€ã-Š·àé÷‡ôÆEy6†`ŧ~¡ôi>•Õ/Ëø²‡Ò·±¿58•Ü.
¨T"…±ÞUH*³öDÅL•à”„rrµ)&”ÆÅžùÜ}<=[+&¾Xb÷ÉËÊ(šŠ"P™ÑB–<œÅ3~.M©Öu¥Ãs:ž
2
g`E¡¬:h¾ƒ`CØ®®ó½¥]Ö÷Môÿ|+»¬‹GµnŸ6n̦3&ÚÌ>¢‰¨Ý{@Ù¶±6´q苺mL?ÆD¤È6Ñ…’×Å¿m›Þ
ñX™„ÏÇQ¿ÂtÑ}AF:UêX_9¢-mgMï:þõß¡	‚ÇB£vÁk7½_Š•D‡˜BØŸïìïqÀäÓhÐv SÆB®FÀ¡öTú­¬†ø¢ª8<×Ás
/”§ú9v_Ô‡mñQ{µ8^²5°m‹.ÞÜô[²Uªðs­@ýŒ{m G÷†(/йTR¼âãø\B|µ`¼®¹4«ÍÁqòt5©¸ALõ’#ÂoôV»Ë)ôcæÙb=ðRù.Šäªvìù«ãQ#Ç"¤}7¦K®&ŒûÙNÎTO¾ z PÊi;Ž;ÍÔÍmò²ÄÁò|paw†
&é†ÊØcŒdrZ„`:ÆS¸(]>ÍH™çK ‰2난øçÚ¥=B2óQ^«˜‡+KãTíÔÂNSÔ$©È¯ì”o.ê%˜qÄãð7uQ(Î5»>©ÍÊ19ˆoó+² ¹jÝ P/FxäÌÌ‹ì¨Èöeá®ÒJf¥à}.À>\aG¯Qø|qˆû§ý©BN-©Œ·|_$5Á½‚›c0Ù¯ÐlõµŠ!æ^ÿÌMh§3]í(Ýú¹o–6é²iYÀ
î=©Ú·µÏW.™ò“¦ô¹¢é:L±vŒ¾†¥¸Ë]Å=Ö̵HÞÜ	
y)êæÍò-‰hòÏ!з­Uá›írÝg”e™¯²WMÒ,oÛ’óôš‹æßê™\®Ý
~9š"›z€Y'½âòìH¾³×¯g&M}[	݃#ì0Jð_º‡Áõ&ÀMÆöÖ+Óé´Î=)‘éa-|Kë*ç3uD^ºoÅ’œŸãnÍtHÞ9Lgp¥ó;wiÑyÍEèkáÌŒÁ	—)Ý%\Ý,b¬Ž®ŠÕ¤ëHé¦!È–‚Á	¦¬†sâi­e‹
³S‡vJÎüfåJ¦3cj²Q@å!Ÿ±Cc¬ñ¾®…±^+ngúª8¡XÝ«YN`h[Û6„Ç¥K•Oêªë†éµresT|° ±Õc6•B’‹r!'ñ@!…"”µï—él§*(eØWÿ©­²†¾úCÍ¡TÊ® j‚ÔÁy2SgE|èÐç^¼.W˜Jg•Aœ@´¼‹¾çK6i…–>©íÔSsc™•+žYïfAêaUŸ†¢§×¨ÞÌZQ¦#vOF?òõOÙs¡Õ“å!~ât1J0Ó¹cÊE:…åuŽzfýX·n±5‘\³éÔ¥5=iXOXË@å ®´xÆ•ˆ§ôî)¼=äð¥;e—L2w+)î"ûÄ÷Éßä··“«žÄ‡=gS1÷±Dîs(Ó”ÎÓü:°r¡8ìŸoÕ‰µ`{!hú;ÝÓÖ·ü¯¡÷Ó‰—ßæ+Ÿ	ÃÊ(€äºÐçíq§=–`ƒLBJ­im¾¹«µ&qŸ_8,ói"B‘Î\åƒÁT|	d°ÅßTÐ2g߸¶!C`—‰aK‰ëŸZJ‰€ñÏ,t>	P*¿~T6@*a^¡0Ž‹1Y'÷ý}'wÉ-Ô-`©¢‘ŒšÄêÊC	§ø[
.”ŽšºÌqMÚGY…æZË×ÚïpX•®ù×`V౑ú¯ˆÇ,eJÏ\[é™N ô{-BÁÁˇû;ÿˆÿýq9endstream
endobj
293 0 obj
4269
endobj
297 0 obj
<>
stream
xœµ][“5’Þ熘ýó2}68‡*Iu›‰}XfðÌöîDÌzÚ´±	pÛØnƒùõ«¼*S¥:}{‚°Ý}N•.©Tæ—_¦ÄOçÝ¡?ïà?þ÷Ûgg3?yuÖ?9ûé¬Ç/ÏùŸoŸò ?ЇüÉaé–þüÁwgôf>…ó)¦CÎ<;ûß‹´.æÝðþ3¿{÷Æ4œ_zp•üt·OŸïúòÌi¹ø]¸øj·àóÏv{ùâ›Ý>ÆþÐuÓÅÛ>ìöÓ4çïâÅ'»„¯ÝßíÇü}÷ÊkŸÂkñ°Ìõô—]€oæâ^àEûÎåwB’›}¿e©`T#.I¢ÔŽôã’š‹ ç~lëYìò£cj{fð4|žWöBŠ ðÈšÕh;¿¸àiô Þ0§C…y!ü­ó†‹Xª$‡„ƃÕÇdµâÚ ³L“ÝÞB‹Yefܬh¼)DK^”WEÞü ‹k#iEù¦tœrZ@)E3º¬/¡Ê‘PPã†e&Ù\‘•ÀÆÑ‹XÁ¤ш5ïúž|*"…ÇRê¶6ydNœ1ˆ¸¬»ëošÞ‚ÒÒ¼†Hã¬Ö–»Í“U˜¾¡#xšI#xGBb#4ˆê¶¨²½†ÑN¹™Ð0żûN1Åyp ìû--{¡¾(ƒ2aŸzùhßïŠ%.Ú(RÈ«÷ó.û*ò¨×¤PŒ`¥[Kªlˆ:%¢‚‚ÆÐúàÆ?¸-ÿ˜Ûü8?	>„Ør42øØ$\”ïMV¡Kyà1
½ñ|ÁŒYLÛ4­GYhûgξ>ûé<ûã±UÙ|úe8Ìóù8f¿šÿÍPí“{gßûòüõË›Çgÿý¼?ûøsøë“¯>ÍÿÜûóù¿œ}vïüë;¸OJ¹›pÊ©á}ÂÛÑè¥NÁ(çÛÝ’zÀÓõ>0NvöG ãÚú.Â6¶~økOÄ™¾øŽ¬Xþ²ìn/~Á«‹s‰¯/ÌPsz¸4hs›FŸ‰Çn›NØjÚ¬"‹Ë¤ÆýZŸ-ºíš=ue|:yáÐ+渢ÀŽ4¨Áoˆ§;æ5æÝP™[µF§áÅ8Í>gÉZC
»[íq˜Šo™ÏcA·h›»‘V¯eOÑZÇi@;÷	ûëÊv˘µ”/LeÖ¹<Òê̇8ÊêÔžC@«ð¸ÚE,52b)nITÉz’)ãöò>[á”úÊkÃ+Ð[µÃ°Åç°uòö¬~A׸·£ø`î†Ý9Ê ¶º
oßìÞfÜß3V{Tt‡U1j^AkŠñXcѲÅÀ¦ð¯K5€Ô·€²£[>Þ`£•ý58k0n~Š{&ÒPÅj:0É@úîP룲!¨áÐE|µÅŸ­&ûAöò/(	&5)RÛˆs%|ua2…~¨ÇRãŸÐF³øóWã·Š¤)1ÜØ4‰rëc2ØäØ$hl¢¦ëˆ¸;2M!¤óf'_†ÐPåRH!-$‡}#ÐT^¥p7ˆK=EÓG¶zœ»Ã7l<¡n—dV ‚tEÖž°UÅâ¥Ð!Ô‚o¿£_Éæ.œ³wï-6ä·½š)$í“õË"Tœ/uí€÷ÈäNÿªŸ}//8΢¿hÀÒ€mV»êµ(ñÅÔá܈/\D+“õ	φû]\k^ €l^YD€ŠqŸ)ø¨`¦8ÿã÷Ö#èРV¬¡	ز*WKC_æ/ZÓ˜BUõ;dçB¯Í¶sC…Éè'ª‘Ù"JØ8c¼
³Ô HvdvX6.¯üݮš•àY¸‡ZËV](¬!Q‡>Ó¾C†¬#f°Í¤¸p‚䪔¢X Fн1á²u+rä%‘‹ðØ"¦·`Œò2/%¨V™W_	—hˆ§t*/	g†:˳±Î4Y«î²°
üÒawk=‚ÞÀœ³
ÃqU†âì™|¾³;½Zׯ¶=$ l"4`£ý;)IOîë‘~ª{Ù[ð£†WÄJC—&€x.Q iY0¬"@×È㑼ér~KeMtX¶vÑ: ”FìLµ€•é{7MÅì9Æ­FÝ!O@Ð༴‘4ä8QÃå´éã¡AÀZpå)ù}JÊF²5"×mÒ&ŸÃˆÈ/Þ¶A¶Ù0ØõqÂð¼­Üb†ÅãÊ·ZDàÚÒŒaÀI¾°_ëÓÚ…©÷š(Ó"*>«¼€Øúg`¶pnHŠ‘Q’áHŸ¹ŽÓâ?hjØL˜‰€n"¨ú\—f©¯¾j\.¾ÝrkåÒ²‘©v7=B+ÆÙ ª8vÊÚ6u]€¸‰¦¶ òµÈ¹/¨iÀ…ß³¾+¿ëiŠ'è`R7±uÂ9oS	nEƒèeÂñÆn‘uê	3Áÿ2zQ8?-1¾ò	S†cå”
qG‡Ü’ kL¼,Å«•~(FåøELOµÞˆ	3½Ì+ûHá\VÕ£ãš)Kø¥±­ŸÅÔäi‘Óâ ¼0!7»â)AÆQr	»Íô¾Õ3%mÁÑÎÔÛ";àY36y$oɈd»„^âiqh6G†R•ü“,ôuùÈèiÒÏçÉ«H›iÛ¾TÉ/óž3~‘âtxÚ³à8’ÌæñIÊ ¦S=Š ¶_{–‰wİ—Tàˆæ#·˜ŽDŒ¢ê¬Õ¾ÊN‰æ
wëw”1%¢›™Û¿Ê;ÿ€/Є~µ›ñ;¤x°/P
Td*™	fàÿ%¹0Ž­­’BÛ
ÖùâKéò+®JÒ†?#s–P§¥œÈþ¨9¨ÝÒú]±ÝžÛL­ÎüŽÖGåP4í¦Â¥kƒ_32<±uŽwk5u!aÛ	ÂÓ*‹ÁáטæRþ¥^X`öø‚"ÜV	~	
ÃVY-µJïâªâ Ìv–
“Ù0–<£‡Fa¤‡/ Ç{œÈZágòõw;ñoH‡Ì‚ݯ®BºôªDn-ì´ìÇÙ—b”¬±S“9”º Ä€º©Òc¡¥ÿQRa¼=%@¦y{xš:‘8ÿB§Ù8@]4Óúýk7Ÿ§qš ’ÖïéæFJë÷;-Ä:Ùu[ k
”Ö™Ó¼z3;—Q-†ªÄWÉJŽ¥`¬Í»oo»‘X]V¦qtžÈçZ‚ª5gÏjkk¥8–>!Tبà°®‹‡P2.G51Ëà˜Ê­óút~Än5B6ÔY
˜l™Z˜‰P¾‹¾ù6gEšßš¾æð3¥s¨øšH]Cáì>TsÉÉî}œU›,¼ôÿª+,Jà ~[¸fC¾hzŽ?¯Xm®Ã6÷Ôî5{„Þ,"øun–g+!ê«ÿI·ÕTD=äêv®JÙÊ4½#+™üÛw®ï
Mñd1õŽßŠçÖs^è0Jsb‹·çÆVk=÷+Ö^Nñä¬}Чp ö„Òj¦ÏK§ë
ºLGéVG”ú¤ÎTˆœt‡¢«	jšM
dG«óD\Lî¼Áð¾ò¤¢5Z¢~´zëØF4‰áâïš>Z¼Í]—²yÆ*­b9b{=â”ùFÜÐŽqêÕdÕÇŸYü¢,¢V€§—í7Q¨z
‚-*§Ìl•êPáâ/­Téö%aΛ9•ââ+&Ì'ü²gY‰VùS_sç꣱@ñ×qým¬Ôf‰—GL‚×dN—v*Û*–µkè©:ð”SX2]o‡?ÏM:–Y	æ^O¦ŠU¹ïÃâãlYGÄ¡T§ÀFì
hs‰¦zFA£Ë‹j‡_÷òÚ8‡|6ê}­QDXªM\}D»¾1€€èÁp§ ß1ͧDñ¦êjí1¥Ö>Ź*^ãm€Ñÿ’êA)°&Š¡¯wÍê!’Oåá©JÆ®‹MÎÕ¤•æh^¢Êw0ë\ŠnŠ•YÑÌR*\)«2"°îP˓ǡj:lœï”4ÕS¿­øuñöH\‘yû™†ƒ*šaE³;ÙŽ§SqÿÈXNº?P¼5(ó–NÒóv8´›È@%]Ðó’¯ç~W÷™ÊºbÓe¢4=Ôö¬:á~rôA'¿Ç†‚Î+vFxF3¡¦õ›º#¢]YLéQe%Eýþ¶+NÍ))á—]Ugl‚¾•æHYÎ\ò(fŽN^W¯aF¬××/c
z8Àoád|î'Q?™üûs¸ÕƒW¤±„T×Åß4W¯ZªïjÀûRÛÖ'ÕN©ª¢Czc]µû#£4abŒÝÓŠx=óõ{U!ºÚæMµ‹:
‰íü4B33}k&O;•dLbÙ/ˆ	†Ë6nqë¾*õ/|ñ @K“¹–»Zk!w¯Â
ý±zË6b‡€UÖRs?¢·n`REâ½&®š—L^U"üŒnsSVé´„I^¸ñ6´œkhÕ<úJ¡D%•iço8õ¾&"¨Ø¥M(ɵ5ï§Òð·倇
å	96,ØÇ4å<·ùqÏN|2çÊ7rM¹µ}š(Íþ³¼±²x¹F?jMéDÁ–ݦ÷.®°×úܱ†-Á©ôïþà­¡Ä?tß+<ýuê¤Z^×?A&Л¾Æ#™Þ°TçžW™ÞЯ܎kÒ+–³7z£+o¤øð+¡*a¬Ê2aÀ<˜ Ö=l+o^6³ûÀ ­PAIuʨÑÇø«ÂÊ¡FŠ-J5pÙtóž›T0ÕñÝäöñ”sxÏ4`ˆe—»Z:§w$%oh›‡‘¶O¤Zê±SÑÓ	Ù˜+ÅW^ÇW^hü0wjE®˜ü«N’:ïõ‚’3
×Ç)Ó»Ö*2£„ì÷ܳ„ÃaRÞW¹¥uJü†­þIÙWó†Ã¨Œ¨‘¥†á;Ì6òyƒ÷¨IžÆ){CÅ	Ø}˜m(«ÇlœOÖc÷æø޼jíÁöŒeö€¼mjèMz‡´uÂŽ‚¾¥N¹Ó4=4ÿ®sC‚4k]v
”Êÿs÷HÁuSù5h¦9áa®h5W©¢EÙÖß-Ï—ÑiŒÓ+h
IQpmøÄ¯^JHA³ôÚ£ €ƒð¿²¹È1ʶûҀ͞#ŒilB¾Ÿ|’%àDêÇÞçØ›\`¸¿ßI¹¼¹b•ñ6ž°"˜úãzŒû¢Ž.c×#Æg.w¹Õól뼬ŒÓü˜f—“âZÖ÷œ“RS°}O—ÎÇæf^ÝÍf4?™+×@˜¢îšÒªN©ª’ô’=Ùˆ’U¿Sg•,K½F¢þHWå…x5¬f•û*Œfé¨êµÍ¢³2ÜÚ×ÂbÓ¡ÓÖ^Sãr‡Ç+uiË¢çŽê“‰7vÕëbÕ¸ªTjÐ_®VÛ*7iU×Ýr“e9¾cð»ˆê]lšú<É‘´'ƒÞ;¦«¤Gè­‰6ù¤ƒfG³ø5ø5wµˆK¬Ï2+ÃOê²T	ÊÐ(Û”qlëpŽèoÒBœ¬u÷e®s	¥´rÌå*pû|sƒÉIü;ü1Ë—»
;{ØQ4ï±Ë(ùk]h«ß~ûÂ%ÍOÈ´'Ë	»W¬}«tÎïͧw›'˜a,¸%:…n'_2Ë%h²¨¾žÒxL«r𳻸tu}˸Q¶ïÇY¢<¾²ïhÈ”‘Þb†Ñ‰bÝ×*
uM`ÂeBWilq›I˘
…3~t«J3"Ž««4iöÍdkE+œxäÙrƒÀ-©§”ÜUºëû~ÐÊÈ 7N!5"z,[X¤”ª“Éб{‚JZç%Z¢ˆÓð©Ê³
]ÁF.j4–£HJӔ»Á!¸¶ ¨‘·Õé8½Š!ÉEmDÞö†fP5îd‹çÞÛá#`ÉdÖö¨|âÓU>êé¾×Á§ÌîƒÈ)ž“ŽYêÙJŽ7o…1•ˆ¦[„æ’bˆHzJ‚{‘+8®lÌÀ:&µ¦Ýäx¥¥#ª|Å¡Sgo”ïeÿ­GAÁ@_ëG1ûîÕit+EØŽ?ðéu¡q•½©F]Îཆ;º>̘ÿý®åüä é;¹—l«¸'›©¶ÌÅ‹RçlN}i25ÏÓã2 ¡ž£ã?pbP4ûÿÙåà×&–ñ‚Fè…T‹ÃÅÓòë6åZåS°›üa¦DNYÑ”‰ÀM™ßÝ>)¨˜VǾÍ]‰®›:W®É·¿W’ø
bŽYåÊ௄ºŽ·®Ý…ãF1Ū–xÐôæMm#Ù>ÚR´hˆX²ÔSWÏÓhÜ<_#óغHtE¨£§ŠÓžr™&+¤	ÒÔ	ò‹½N.½µÄmÊL¹ƒžonwq„Ö(÷åÂÁ݇öCåüF£,?è•}ªÖ²þž]¨½vÜÙK_déRËA¸·}%¥!ß÷Eóöÿ+pëõXÈj8º­wøÕ>ñÈ´‚é%ÒEWªeª:49¬uR zJŤqxT6i¬S}“±
ì_
÷ŽÙá˜-*Ïl²oxæ{F¹™LÎr˜­3µ†íSP·×qÑ-uŠ\ß¹t‘Ê(û‹f­âÑô¤cð<Ú×gÿ‡Ö?šendstream
endobj
298 0 obj
6371
endobj
302 0 obj
<>
stream
xœ½]Y“E’Þç›ßЦ§ª5u‘y=Ì00h†CbXÛa¤nI°ƒº%8æ×oøî‘‘Õ%	ÖÆFÝ]•§‡û矻/λCÞÁÿøçå³³÷¾šÎŸþxÖ?={qÖã—çüãòÙùò±ÏŸ–néÏ<9£7ûó)œO1ºpþàÙÙ?wÃ~Øöa7âÏ‹i^Ë<îîí/Âî³}ܽ¿Ã¡ëÆa÷×ü×Gû‹˜bþ{Ú}¸¿H»Ïáxìxþ«ýE„ÝýýňÿäGûn¦æðá¿ïûòÌiùŸËcìƒc¦C7ça>¸ÊCKyHË~€/ø›‹Ø¦~Y臹Õ9¿½ÄÝÐÁ³<ºüá°û!Oè‡üÉ2àPá#üî&ÿòªŒêz¦ÝOÐHÀFàë'ù¹®+íÁ£}þ&?„ßÿ”'ûÌîûÜÇuië)<Ѻ^›	y)¡÷ü5‚¯=¦ç`¡…Üô=ç?a”Oóÿá‰%¿Ò»_`Åøµ½a]ÀW¢ç–yÀ?aÄó„Âql»ËüÚ
Í^ºyNca÷r1`ÃùUÞ”ü+,wì†Ã˜dà‘+ì»Ìå¦,ýwÚ`~¾M#nÀs_À¹Ô/nöqÎ¥¸ûy±Óh^Ë#Š=ô Û¨ìjÎÝË,Zò4ÆÀ«}'\Vœiy–ë	­HŠ3>QFXCÈg—ä"oáðÀÊ<ÐýáˆËŒ{^Äñ$ÉI]kþ•[IÝ‚Û[eåU7–÷7èmDA’]6ûh6^Ð}ƒ.s!Áäqê((W<ˆÜëüÆ©Œ"!4¨HÓ|òg	×ðÏ–Åcx$âÔ¨§pð©ŸóSÁ>ƒ{ŠÏ‘ÎyÅ{‘Bøò]‘inmQI8’~ÀÁ_îã¿ÌFBx’Cîeš‚œ±Ô'³×70R:–m!£‰ð
²bˆ1ÙSK‹:™Ïþº¿@áí³¸ÂbE“D¹–™æúó~ÀƒT›½%`…²_Y?={ðŸÿÜ}œ¥„yÈÒ&‚"GÒFÏAlhcáQzD¶å'x®Ã-…öPk£Œß½?éÜͬqDqp/¿Ý‰œýâNFÞ•ÜÃÒ/ðQfÜ*üö!ìöõ®sœ:è¹é{E6`¼v_”Oq„ÿmvØæŸá×½¡Ä<Î ÝÒA=3Î(—ú@°8ßîe¢È3Jc×9‘ÆWVº 9²Õ¡“9DÇ¢øŠüG#cu.âÜy‰¬*oÊèŸíèÔ›ÐêÎ3­.îó¼ûö[>ÚôŒìµÓ‘2¶;ldeŽ^Éñè(f<3Q-	ÒGùX¢€Â‰¬AË©VE¶u–Ç¡œå´{$â]ŠÊ’Áö5²?+ûJ£jÛJ«Bè´¡3~úëCœðÉ]=—¡þ
ˆT4ÎÌ1Ÿæq4§Ö­|QpVÏZØpSÖþQ9¼Ia/³ÝÈwʯ-ƒ$³KÊÙZkÐÈ	ðËX	­ÑuÏ‹S´6½¸çå›+=¡þ”vÕèYnÅPÖÅëDk@fOÝ»ú´Ûâï+´õn?ˆLQ¤%w\»K!צÂð=ñì®åYÖB$]Ó!ŽVº!žçæ\Ïu%Þ“Ù-'C!BÏãí˜*¤‚X°‡]+–Ë+œ¼†¿‡ýžMÛu-L¸^‘=\~Iþ^‘(ÐûãàÁ«­È{­½ˆË)p6‘k¤ªÌ›¬8Š^Q•yÉþ*»k%3—„o`{ÎB‡,àžFÔqqŒè^XHÓ(à‡T·“#œ÷µLÔsnªèÑXAùŽ"HD 9Hkí#Ä(#7jÊhMò¬?Þ‹$¨ƒÅï±›Uô‰7‚€"Æé‘Gúˆ±Í`¶Ñ4ˆÊÃ.MÈ*àdnî󬽡{÷xo¨˜;à_tø@óˆx¢ßù0(™¦
íiñrÄ !åÇ'á)ÐüëühOû¾›F=ö¨Z¶_'Wáq…¸YK}Ä^d€ÖlLž9…Ša³–ɦ†˜9dÂÐ+b_¢·.¼ýY½&Dýî›=Èö¸,mµtMéºÅ¼îµN¶OxBO(cÇÅ ¦¾Y
wAÊC–VÖV´6Þô92ŒÔ
ã’
Íð±±"Eݼ5›–}e}»aPŒj<â`ÅaÌ Óq›‹ þ}ÀEº2Sk)ƒÃ%¹"¦ÁyµŽTߤ²u66ÏCïBÃLA:§MÛ6ª€¿¡²dþü{è»ÕÚ¢âMí–h_ Xsœh¸‰i2º;O(°9“¸ÑZ¸¥$ZMk„ë3•¥"á|R9.aÑxÿ“FB‰Œ´Žaþ¥I•åÃ:'"*‚—j÷¡§ê%\á\K|4”p“Ñy:ÏKŠF0M…1T"ÉJ=![B¼W®ÆƒLcB¿S{Ò6“µV>@L¨5tñ†ñ(ÝŠë˜N$SskΈ•»wÚjlÓ˜ˆ«•5bþæê•…B=Àn3Ì,Ђc$Huä|d™n!*œ•\ÈÜÉm-dÎq*|ÿf¹uFQ$’¹³¨DÉÝ)¤ösiG^É™ÛFO,-w‰åe‡ã^d!ù©¥ËûÒS6á!òÒ«½$_Ñ-¶x)”-Йþ|!K:ÕNž(‹…d`]©øÒ¬.Nâ÷¦Á¨C6‰¸kžµI®3g£”:0å¼=¼|
–Þ3§çXÃ_òsUÉFšf}Ý2M*4Žr@¢¦Å–§„ÜôïOƒ™‰ Ÿ³%Vń܊ÿqu{ßDÙÐkO„6TPò k°õÕÑã¯kkäÍ4q‚ùÙ¯yÿÖÈ7ð×[8a1D–
ì…kµºHhÞK(¡ÆH'EØ<ûÞh±Â]Qh
V¸Æg©#kê‰ñ8÷e¨J¸¤ge6F"é¿Þ7¢¤)ÙÆÙ2©<óôw"Õ¯)^‘¢‡%-ªàW=Œ¤A”+$]±ºÄ[$€»·Ò‚NH„5½rvôª¿ºǬr À«¬Û9R‹«Æ·<î‡gš¶)ŠURŠ‹ß6™WÒÙÚ÷/<Æ÷ê{]ÛC	œd“e§â%*ÅG1ŠÞ¶7ºîâ![ÃhdIòOæaÃ#¤O8]"ÎeuQ\¾ËYñ¶iÍ	–m1‡¡
|R¦jÍäEQÐ+¨nò(|>”ð¸WlDS7Õù,Ú&›È¸–7‡ ú¡m2ï2©°Ä¢.äEc:™{‚vPk]‹0‰vàgë`¬…œx°Œý¢îòöÞÔêŒ\4C K?š=LWcº[DýB’0Z yë“ó}<¾oëÖ<”:ŠÁy4˜Û¶eðz׿/*ã,ÿ©´è	yGzHOåâ(ú<¿ƒr¸D”QáS{8WD•­¯¼˜Èõ¦^„–pV/¦Vþ<×ô
RôÊ騃È=lìã§HO”PΊ¿*Î#²{Õàwr' ‘°Ë?ÁiH3AÂcÁ$öµóBÄÆWŽI•½=ö5`ò¹>²ÝxR\æôÙÄS¢W_'㇗âu~Ò`Ò-ú»úIq<É¥hÅ$.•‰Ê®¨›Þ¢
Ð÷
N<1;¯üØ;ª9“qd$FÜG=	lƒöÉ>E;ö‚ü¯‘^lÓ!•äŠK}Õ°dÈtôñv~Äøé|Ð&]ÚpXñ°Ì«üŽ„Û°ësÓïí);©!óÏhºÞ^VŽs‹€¨Í	)pXs“U 6`VÆÎ8{¥mÆg
ó¬ý>1*®ã¿@hŸ
ˆ0¾ÊÅXàzGž†$?ÖÅp™j£ÍûÜ3’°uvbI^cÄLˆp Q`ÃaX–ØÚ¸ðH„äw	ø®sapéÀ!³i7e€>mµüV$Ð0­‡­RÈ!aŒfë”‚Ñ Ž"EaÖéaa
WŠÉ™•mÉ®ÞÛÌkAuJ#.èûÖkK±Ç3É	­jt°r»5¸É€ù`vQŸPKk¥Ç#³QïÏtIïS‡ÕtQ|²]sé’|ëfß&AÑ4˜yÁCž$Ÿ¦)bPÀ:zÒ€M®k
šBb=Bš—×8Õ!:¦þLŠ	£Mú±–§¤-o©æl?/êÅ'›€nôò𿆩¦¹ÚÖ%.#ÚD^Éf]×ÌÙ°dPSK}X¥¶¹ñ©;…l½ÕVíÚo‘«X,ac/T«<1¤bz
³î®ÊÆ#µ¸•¢Y{¹j£oÆÝ-ÃBGøïŒ}E/õâW¤T¨7grbŠŒ¦¹Ü/°ôH(-rK²äUätà6
]ÁÞÈÌ
ÎNlàwºýLµ/ãaД¿+væi•©•GÝ£|
Èv©ó^)™ˆ :&ufl¿©Àz‚=£i´ùASqŽÇR¶t£ç–æù[Ÿ+žÐÐÖJÇ)>0Xp,œ…“LøßÜa–\˜Ê>¿*R¬;\“Jå(­òžY¶ —fß8úÑ%&¯ÈÚ°T&²ÈH¢¤®úºÆì´š+­Š’;å½µ*Œ¢¼—f¸ŽÐ;镜ž#|\Aë0’ÓzÕÖ€BA@JJ>*ÊÍù$‚¼dk¾êF˜‹©äöÓ„¢TRGᑚår †D.Û·‰J
UåÇ0ût+žBE´3³ßBÖeiïaº¦•êàÈ[6°ÂbÝ(5«„å
-ƒßXVjø·Mþ-j¢TO€²¢£Š’­rè1^ï¿åÎ"ÉÒV†Ÿ++•í}ÚŠBÚø:D¦ì$ö.ø 6×rTi<&.Îç",Á܃â·åÕ7étÎ쪘­V}¥!˜
Ë/áÄe›2K+ן„"Õ*w›”Ÿ`É)H”Ò®&Ê@W0?´2]~–œf%~ÄMZù~.’i|¿f'“‘ê¶Ö‘Sñ6•Á¥ɲˆ4$ A“0³N=´dg!hY®B¿G­2¡†d£V(;1P¢%}*{:›ˆi,óëh)Úº%ó…s>V ò"$r22oó壥¶šämœû
aaú޶K¢ßÅu9FU@_ÓJ¸
ËÄí8H~ ÒŒ>N¤Í4£“¶ôyRY¡n¥û{4‚N©&ÁrÄšRž³×^«Yœ«\Þªö€Õ
sÝd÷Mœkä1«(ÅÌ'¦aXs#á5£:ò«iƒcP]üÍÞßC€Ðqi´y|EœÊíI<Œ263 ¸\À	gÝ©+ŠTBpzMóB@F¸¢ØY·rX–3ð‹ytª\.WH
¬p›1‰šŸvήœiNÿߤdÞbp Æe&É[M»œ…ƒ	T‡Væ›ls/Þ²–;ûàÞÙ{÷>;ÿéå«Çgï}sÞŸ½÷	üóÁæ÷þrþgÝ;ÿróª‹\5Äc:ÙdÍ|ÛÌ_ö[EýŸäú¨**Ûœ@
Óÿ£'qðêí w‡ñAGÜâû¨.j®¢®ý×cqŲÝU`Z¥kó:û4,…qpéÊ-¡ck`….à(BHz–›~V²E[³¹ý¼Ì(Oã8ÁÏ?j;úì‚èåÆåI¾nŽ?Nšÿøñ‡”?ÝJ“k©µZ–¶ý`'n½GÇIÁ&LX¹ —˜´cws„Íû_d\k¸Ôgi¦·r=QË­¬ÊLW+]²…ëôSVìXbˆxHd冠ØÖ‡"ÒÖrÛ9Ö1¬2΃tÁµÝNl!þq$ž¢[û†·V¦ñ5÷¢Þ1“ˆqÅ ­[Šß`\Ý“é:zx©ŒOЕˆ'SÎtSÚ”æá²…¦¼x_ EUÔúÕKÍÂ<Ù'Ià?O	c$-ë]ÕŸ¨ÐJ–­ä¤±­Ú£”æ&:2lž(¡¾;”B')[ïXWȦ¢M[û¬}hx¡Bw·}HìFwÕTU̶º,í¥ÖeÚZñØQù/ÚAMAÑÁÏ·GSyÅïŽWö™ˆ[”owK$ŒÏŠSYǰT	ó‘µç³ÒŒu:-,Ä:VÏ$­îJW4MÀ\e
!ò¢µo¦»tò…¥À¼Âô.¿Ï‡7÷!¼Õf¢Js©³Ô Y ”m4›âT+«š+npfâ§­0Á=0¾-Ä×Xw1„>»R—þýú•šiò;ú¬Ñ>,½\øâš”·Œ¯ã tÙáÍ
ôÙZÿ¡J¶1@7‡ä=ÎN´^î¶?Ò§	o;ýÇ;ôÜ×z·i&™½Þ;ehÅüˆe¶¼–ÑœµRIp]ÔÎ;ð`UW¿]×gn˜„J®s\®Ÿ;ñ¥¸Ñáví†}´¦…RŽ>WÑÞf-†®ÿÿØVHOs-…|°ê+GZ¼¢s]b1ÇX	½ð«ÄÀGšÌ".Šî‰9d„oÿ¬½ºªÒÝ”—äÓê±aTdHE¹Ä¡Ù<©&F¾Ú^½ øçX#l?D宂Ii”D|S_ÔoØ+ò£Ї¢ì·Šs	Xéuzˆ4ÍZo	Â8ÕP{.MÂ×`p_PÝt¢šM´¢ˆ&ø'ž0ÚôÓÒÀh9¼™ÐàC)˜ÿ¼—Ì“º,i(Yêî›ï¨r6–˜Ÿ¸a¸zýP{ð7ìi`<,šÄQ‘9ݧ	ª•Zã;nøÕ[ên3BT£YÖ«;fT¹à©óœ„dRƽÞ[éê9]žË4ï4ùÚ¨¾/äÒ›d‚Ô©÷?¸Ôb¿ªRtõÆ—%üH¡d tWå„ü‹D€L~ͳ’C{Ô(Е‘R’§Þ(•ºpÄë”K‹%ý–K9Ÿ³•j¢ÌÐÛ€7á2Ö³4šÉ™¿RjÖ
úð
"oº›Èƒø»‡=œÖ!¡Ç&\‰˜r¿
duêTo“ïZ~¥ßXBòšæ‹3“báa¶êT”BèE‰µ;;ÿÐÇêMɧËßI›ðˆÜê›Ì”¹v]µãVÍÎÚ§·Ù!JR2¹;º&|.(¯´|½Û,Õ•UÜê’l¸móÝšvï(µPL'üo¦¦ÕG¿q;•Mû+‡R:%Kº,b¿ÛIÆ‹¤–K±)˜ç’i·‡%ã·²&øŸ!HöžêwnÙil¶y£¦fX'ë®›øÅÑ”ÿ¶DÀû…¦ÍQªg6+d*o“WbË«{ ŒôR]%¬ç;:¦z©¯}+׿j›ãS—^ùT5‡]\aœôÊ7«¬1…àëèK°&˜Ùfï‰#D¼ðZ¡Áž‹ÔQ~=zT·ášƒró[ÕâbÈ|
Yœ¹*;P™xyöN1ºÿjä¯iøʈ0ΟŠñ*	F8Z¦Ç†ÖŒrN]›ÚbE'_‘ÔðsÆYУå^]JåÔS%M™V@_“ÕÆp“è²”+"]Q€ÜôÜþ¯šHNXáÅŠ[úõžn“³A$"œ9jšÌH¹]›—5E`´Ù”,i¢nŽÝK0–ûg›ÖSòOWP‹b5ïaGLÄH×¼ÜQ+wñ"((¨#Ué‘+4^ãð#W`^íG°ZªGL"šç¼áhÓUSå^ëu66ùòìÿËÅ ¢endstream
endobj
303 0 obj
6492
endobj
307 0 obj
<>
stream
xœå[Yo7ÞçA~Ä={œœ¶–ÍkÛ¯Ôl…§=i:ïÚÆíô[¦ §­aß&Ê9/í¥ó¢¬Ü ß3hWéꮢĨڮX–vp¡-ºÂ]ì_¥©a ÖÊ®£íp
«ë§þ?,-EQ©ÉðaGÜÆ’VÙyM£'cÞÏ=+çºÈ›²ëGKËž?3;»*ìÞÆ‘uÆŸÚ5gçŽYeÑÎm—n³g™žíÙ½,å³-Ë×¶¯Ñ³À¦]ž]bÚH=¶s:ìÙ´ÿÃ*Û°ÊgË(ü븼C“ZØV+q];o®L‡8pÃÂRA‚nÝb÷‘íÙ†ÑÕø0NÈ#Žá/ßd—êb ä…ÖÒÙ0eß’¿•taò¶(	¼aù#Ø»Eö¾>[EªFOñ–A~8âYÆ'¤öE9±ŸG팇Ӓ¥m\º£ÔJ®w
'5P!6	VŽa$ ·Œ :6¯"83'ÖÌ­6T5ØÏ!'7u®f«Xeо“!_€|]†”@\(ÈbŠU#á1·¡¸xEvÃ>@C”‡®6<¸6vb+ðíNìf6§FâQLÄ	ÖQ½d(p‘#rЙhTç
o­ë>Nccçö÷$>ü·³ÔkmMK‘›/T#w£éDçv
§¡qÉgý|Î.'ô”íП3I©”'*Bd›‡&fµÌ`
³‡àœž&_í}!Q•¹‘—YfRgoB΂¥Ø'Ìxó¾=äÜ"‡ÞCÑr$Ç~yå¡q'j$!—¡¿àþ"4>àÆ±‘h‚ìJÛcâ.:tv®ï„ûÎSÖñT‚7€nšK6‡eD¡$Ö£è8b+}ýä,FUåŠÆV´i´À¼ç“XiÁÛŠÐÜ)Æ8eth_Á	³“ÄÒ/,p÷ÈJg|Øå0â.B/·	²OòõCªqŸ™=*øñYÿñ
Z:t’èô0ÔÑ”õb™>C_RTœ¢F_ïаæ?(Þ`5ÛŒH²+%>qHÎR2Ží[€E
(ÉåÏS4ñJž‡•Sn/uÞ]>÷/ÙÃÄ ìÉv¡<)k4¦³jKvBLÊ#(bXÝ(ëKz!è3¥w@ÝÄwBa*ÕƒñÀãîøŸà2IWWºÜÂmÒ€—í£\•6&q	ô·:ÛŠµû©ŠÚ])—à3â>ˆ)¶ÃL4âVDâŠ#«t”àc/gP„lÉ¡jtvÜë¬]¸±ëJÝÇøš¤
†9Cð\¢)d]„}½z™ŽŽ3¼WçvšÚs)24¸½èÂe7’J±ÃZÛ~ÖP§*šsCgäkµ–™õŸr;Õßæ<Ö¿#MFEÕJ<©´DsZ•EpÅ»nùX#ï+«+ªÖ*æÒP?³ÊÜî5Û)7½f[l3åÛ×ÏÜØ’â\bÅêYÀJRþNènÝè;væ$ôW¡/S\b~ž§°à@ýýÀúZÎï¤ÄŸ¼=ñ&á²pǬy±†I	öüù}PµÊa××g(ø|eU™ë:†«Sªäu¯Š)F3'¾ÿ“#èÆI‹Tªaßëh
w8òêÍßOÎ_ö•ºW/ÏyÄ^þ$ðnÈâ<Õø–-¯ˆíùÑDh~R®É°ƒ±d"7ÊÜ	`Z÷üùeiŸ¹ówä‘hùKU¤3çÞËÛHÀˆ·Ú^Ä“öRPèGÛ.¤P³‡„åvÄyXØÇHÀwÄhòlÖÿŸ°å©ÿ™©¿¾† šG´Ü5¾”6ø0=àÐ#Þ0v>bS~ãÛ‚E¿‚ýÁ}CãzÄGß(žCŸÈ‘þ›ÈUF‰`j|寕ÄBâÕ„ŸíVS)Ëöƽ”7!Ù´k¹`yo\5¶^(vhú¥V—Þ;Ä
‹ÞµÐ‚Þ›½I¾>Šî™¤r*Í#´‹8¦ÀbP³²Àú®[xcex
ZãÇ\‘cˆß>†¶i—½kÛARbGI|ì 2?I¥.¼Óˆ¬ü C¡ê\õ½Íh̽V]'»ã1Ù‘˜$1—	kê9Mç¼Ôˆöx’4¢é
Säu/·ª|i¦.k4ƒPº
yÝPRòÐ¥Á,/ÔvmˆR£¨Ð¦4\^s
È2·Tçª{®À-Û×¹ª® 
¤~ÅdØ
—ֹ˥	u,]R{PkÇi˜BÌèSéYìTh®¸ÊÚ¾þ¨Íµx/ÄMu‰‚áZ-Ì…Ì”¯	<%»P¢@ÇXšTi–[Êv°Ä0Áá¢~el\±ÄÕo@áÓõÉëÉÉTë¼Æ¢è¹ÉÛ©iT	éQU$e6&W&W^LÏNÏ·&ÿ3-'ŸÁÇãWOì?+¿Nÿ1yº2}ý…õצ©rc¦Xä[»ìMYª4¢póȯJÈ×’j¦Tè­I%Á{Bá·hrZ:7Š«©ãm«k(> ¿üˆç*%†™­«×†4IëŠEý3‘)J4 Q},Õ‰êÖ½ê–%Ò%5Û+ÚSw»:èÒò7ÔASµwN™< êÞêO|¸ÝRS	ÄTß™%é+ýúð‚o-	tPÿìë”Üaã87’®ªBí|ßL’;÷Rè5ùÂï‡~úä¸\Ú¨ðNhIÅn2!;ÆÅÏréÊÁEÈþlðÃ	ä–v®!ªçóÚrÊÇQ££’Õ+1Œ;UªÇW(©' ¥D`½-U(Û&Iî ÁcåÍÀ.r?düÄð¡Bç‘w08´·ÑQÆ.CF*à#¶CT€Ðî˨ܥ˜«ð@¬ñ†·eF¨ô‹Ã2 '£F…‰?d‘OØGYxŠåï¡óœŒ«äaUåÓæý€À—.ƒÀüÆ¿nÐEm´—g]½?wkb¸ÐsEÙ½³_ú&/èIË#¿A­úxas£0?cñ†UoÞ–ÎÃB`7¸qäü.ܶBï;º:]³4Z¾e
¯­âÒð9Zwæ°±ø€²mÓï5g>Íò4ɽýKã
®n¯yÛǧHä7¡ü¦0ZÂäy}ý·Bÿ@SVpïñHû‘”¸TS9w[õª¯ú¤´œ4‘½×òôuÿ|0-õ¢ì鎌n	}q&ß\o¯S¦¾F ’ÈE#“WFƒ?ØøÖpá7¦E
½‘䇑q>Æ7îp¦ìÇ¡òÄA{õ®M¢–2.k%$\\
Ì®»o`ºÓÄ1ü-3.ãr•ˆ½ÓÞEIÛë§w}£ÈàD†Ìâ¬É,^ë¯Åô•ŠRæåd„ßøA6íâþPÚæ¾ÆPþ€ì^–üÙJ2Îòâb©Ø”Ð’IÃeZÒæF€w–ô«aw•)½ÙÙ‡Xû.ö½X²EJÚcï-¾‘¥ù÷ØÍÎþ7Øm[°E4#pÈ;
ãhîu" ó…B²)_8Ø­û«0ܺêŒâ'ã?“è½Ë¼U*Q¶ûµ1TÕÿÍËoŸÛRœ	o¥£%¥²Œ‘»#YžØÈÔÕ]™£Ôò×?»ø¹¯¯ê¶7¦N”‘Ü]<Ž|,í Ä5¶îÅø]Xvú{"Nv–ö–î&½¼ú-Sðø,Ù7<âá(zܲI8je‘šx+ýfàÁ÷¤×“ÿëvLÃendstream
endobj
308 0 obj
3755
endobj
312 0 obj
<>
stream
xœíksÇ1Ÿÿˆ+á–â–Ǿp¹R<
1`®"¤HBRE:’p̯ÏtÏLwÏî¬îxH¶S)ŠÕÝ<û5Ý=ݽ÷nV•jVÁ¿ðwëpãê“v¶{¼QÍv7Þm(윅?[‡³›n€Q®¥ì«^Í6ßlø™jÖêYklYéÙæáÆ?æuQÏËBÏü»h»¾ì»f~¯XèùƒÂ̯¦.«ª©ç?¸o·‹…±Æ}oç7‹…ÿöÆ?)
†èùÓbÑàÃ
UUç—ÃÁUö}gûnþÝÁ¨´„ÑÖmYuÌÍíš*j?°1ràÂj]¶Ílaª²U}ï'œ8èæ{ð؇Çq±¨uå èæoàû<ÞÃcË=25߉«±Â‰Kxàb;4p7|Õ½#Ð{˜Ó9Zù9~Ð!÷¿’3cãN˜Ô[\Þ÷0•¿–pÕFá°G¼Ò’?$ˇÆ÷Üx’àê?m;Nô­¾ÎÃñ†x¡#j|•[ý˜¯0mN¸u/>ZÓ"žIíü8•„0¶/ë&JÆ2 ~ÜçyÁ³múK.L«KÛÍʸ¥á<ÀÒ‰ÔʆÞxñÙ'©8&¤_Ư^°÷%Iá) Ç,	/
nþn 
•)bDQ¨ûn•:9¦ž£ÈD¢?26Òîu
°j<˨pdŽg|Bã¿Rã^n¤8@'##Q³šäßæa'!%ódÜJ¥ƒæÏÓˆ¼hz…Fxî'0yÚ&[%˜MÀ”B¡©ëRW*JÍ^«TPÀ	§-(eg„zåŒ!½ÁKšLW*­ÎQÃlE$j<ÙbZ¹ãAŽw Æ:‚Ù8¡€: |×¥€¾Tû|’)Bj:«ÃäÛÊÉ_öÄMh<¯\ª²#·$ÕR=#LÏ«QëÀºåÕ“—¿kª“.XxÃ1áSÃ'
ÙxÒ1	OÖâèžT¹uÞç9±ã"£±Û£dÒXÉ^Éyƒ¿§ðèZ;Õ3ÐCÉìc%Cú%%V¸ƒÅ›Wxìçø.˜ð2wÔKÖÍYµ3•Ì	)Æ&kþ`ªµê‚´/¿•#Ë¡ÜY¬œ#c…ŽÐ
®_Aqá)éûŒ@&Vµ?gkçQ…eÍX»œ žÐŒÄù	½ÛÔ‹ZðÏ}cý·äÄóÑófªd#»¬/ç•ïbyE¸Ï’ðñ.˜›/öás‚ù®ˆ!€W’¯Rb?Ò´—+|ø¹F9åâG
9!ÖQCþÑ\üËðä¢bcy0>]û{kÀ¯.hÿ¿,®#Iܭܤ,5HQAP+:üíD¨ò"iT_ãî+×eC¦#ô;…u'ŵñàDµÝÞ5¢Ú@üƒ]	ƒ>¾Á¸’È£µC^#Õl‹	„-·t-a\â¤0¸ô²Ð-~‰kjÜÚqo[Û¡ÿ»!ü>,ã70×ò
½`÷‘ŸoêÆÑApÓjÀU÷ªa'Ø­1¾4r÷Em‘&#,
#êa†=ß Çµã?ÄyÈÿ®éàšüIäé\bc,Èwím[¤|t«Á]¿öâú©Ö€?¬l›ù¥À…ÓZG*Z·B­üW±
O>)øØÅ61ïÜAœL¨fþ|Îý˜Ì„à~{sãñÆ»™1eƒ	&7ª›ÕÚÍ×î/0Äv¯ºqoãê½³“÷§;W™©«wáqãÑM÷çÞ­Ù_6nß›=žÌe¥"sY"±ü­KÕù„–rX_)´¿Ý8VAªS!‘õ„m5"N˜í/ñç…‡ª0QkU6!/§
§0,ЦÖ^Ì»Ý>he­-›€ÚõV'P«ueÐPÝ-ôDžâÒÝ ]8‰“6ª÷$:_œ´“¤!JîÆ×áIZƶ*€G¬`î÷ø;àëÖ4F]Û&çŽQ¯À­r©,;œ€Öm†ÛéfР˜¸#SÌ(xÔ»HÎäΟ¹¤À} NŠu¤›mëƒ1[¤r¾@
:zÜæW"4Âw€ÿÝ^0©Šî””¤PtËÀÚÊùW˜¨Ñ€ðÄ=šHºÒØœ¡SïËOTÕ 	Â)F¢IüÙáq¦E´½{gÇmçÀÑç§kmß@ýŠíº²k¼®½EêAGìn€ZšÃiÊVhÓσÚçÎ&€µøV:UN¹vÃ{*ñÁ
'x,Ñmá"ô°c=¾©Ú/ h[·€ý¹y2
ú_`»±–°JM[ôÊ“æü¡Õ®Íõh5±hÑþ¾k²æ™Äfœ”idZ§@/ðLŸ¡}Æ*>Ä”®o}›·Îï„Å„u0®.ÈF‡’µ;Î&3g35jF)¤ Ú*áT¸P­JãëM sàz¼¨¾òi¯ƒÃ5²¶Ãk$Ïìu¸J:>
lépµÔØŽ
Ó1´ÑE3Ú"Óÿíî÷¸¬_-¬ÆmÂĘ7Ïñrkʶî§.·¸®ÁRµ6½Æ˜ßæÖ§£#‚þa@Ö·Þ'†gÓ"¹W,,.¼PVËø¢‘F¼‡à:!
ç0A6oϨ­dSߌÄ€“h9.,§=*’ü(eQ|Æ“«iEñU•j™¬Ú–Ê%“gâ=Džå ÙØÁ÷½‡ÏR{Ƀ«]€<8¡@fÞJH€œ~Jô¹A‹o’œ\ºIHÖωœŽÝ-©0xÅØ}7'EOrMž^´ËRô„xF¢nv“Ÿpãuj¼™ƒ“?„QÝ8ÅÛS*oJ•JÔk»Z‘¤ 	|9âØ»	n‚SúÇC<¥n¥òö„$,#y7éxþ”pbþc°{&Ø&~&E™‰?æ¬Ëѳ”—ÓS¡øp‘”#†aUî,æLJÏÎC¢pz£O *~ùÎ+\Ñ_*òoët~Ákaãü¹¯îäªJeÿ8}ó‚³åþ]§xí‡=·1Ž¢¦þ]Né¦å÷™DøÊW}þVŒ9|—¤ýfj~þ\–'kdÀ
Eåã·ºz0#u;’·ü)úIŸT[+Ì>ä„è€9wšÌbœ²õ×þaáùÖ‡h&n6¡°A‘m…[•¸ iwcßÙŒ½×|‡¡zˆÁ8ê.‡LÂëpÄ4¶F^Xb°!òÓ,]+.kI΢©üí‹nÑ˰۞¶AÐËÀ ùc>ÒO±|D€‹(<Š¡üa:-$";5xmšŠý[Iˆ†tâîø,½¥ðð¯V!L–áo«âwŠxe‘¿˜?à”…ÿ|ó´ýÀ”"uè%g)czEaÒ;y§P6‡<3½ŽÓwTˆÓù°à)ÕÁLDsÊf#FÞÙhZ_ý´N"°óæaE"0˜g‘\c‰',I2CpÃ{Y
jй`ŠC<V„g˜÷°kz {?ÄD"¶½¢]†¬ÐZ,&£`ªÃ~2êØÿ!zÅqë-b_ðÎÓ4j¸V‚8rMÙR¼ÏœËõ¢à}C1ºnлªPQŸ-7™%ëUM¬0*
c'"/s›1þ=Ž UÏ×ðNÉlRõᘡsG¤'‚q8Óó*+'â™&¦Dzv,_04B@
ʇ­Ì¤` øökD¹G°ÿ,‰ƒY^yyš¤ú+–¿Aà0L§ÀwLÊûðaoV„C†)&ûWÿb,ò0 1Œ9̆#ÜĸžÏäø ‚Œ&û×ðQ˜N‡YÏØúC‰6£²:Ýšln㕈<ËrÁÈ•‘ Û9.\4>—¿v˜^’Œ2>ÆS„Ö´¤ÿêOI¹ãpJ(ßpÖ¦¥§Ô‚Ž[G9Þõ’!JW¢d¬Tº×ò!Üäá
Ȥpõ3*¢ùå¬þô—“.ì´}|QX«úsA_>
stream
xœíZYoG~ׯà›f“™î¹³Ø‡8ˆw$q"iÅ:~ I]™CE–}ªªªži‘²,oC0L
û¬®úꫪ¾e5ÊðŸý;[|}Tλƒlt~ðî@QçÈþ™-GÏO`€ÒÐ2i³VNÎÌL5ªõ¨Î‹I¦G'˃×I™–‰NË7'?ÀŒ\3êj¢˜t2‡ß¥ã"ùwª&mÛmòmª“_Ò±NN°ýûtì:ŽÒqž«I–Õ´ö$×u}yò<-hÚq:® _ëä%Oû§å“¶©ÍN/R=M…ƒì.8QÎyst>ÉTiýœÒ@X¥­Ú…Ò(
£+XQ)œå D^Ò.ðMÌs
ëä0<ÇÕówýÿY²¬ÔŠÄ°~GÚD+a^]k£ÉP÷c«ÊqžMjÕ¶F£ß¢ø
‰ßáKøžLAgXu5è£LNAoïáÔGƒ®ŒUÖÐØS[Qk²A’5<‡ÿôÅÍÒš¶šÁj¼‰¦ÕçÐ]T°Y•BÓeJÂ8à\ñ*Õ0¦Umr‹Ò:ñsšÐ»·­™¿Bap&îq_æøávÓ%L¬’4+ߦh¥’ì,`™bˆT­n›‰Çä¨PŠ$WµÃ£oI_$*Hhí‰+’,yZDpEªU kVÑ!ÌÙ¬Òt;n§mÌk³ ï²¶Æ@æšÌÂÆØŠ—{ 8ðècsö1 ¸¬ÐQ¿%iN«Âü¢iª½ò×1~7úø-ÅiéÛhÓ”m\4aâlxaÑf„¥P¦v¸ø}«Ðó3-àpRÔ)7`‹¦‡*³Œ˜$4PQÁ³*ÌÑ;‚Åh%Ã% éÖµP¹9,Xx`dycôÀ&!ázGæ^£9³(C¾m¿A¹›waåjUØhvjDd$¿§%Ò¢ÑvÍàñ±Ç Œ”mcNs/$¸UÑò’Ôlœ†ƒêd?i9/rRaoŽ'+kkyhÏçÌ7Ï;Ë	š=vdQìBÊS$6.x ®Ó¼6$FÜã$³YéÜAî°›8Ò'H¹iŸ¥˜ÂÅ-ݲ‡ëä›ÔŒ*†ÙeœW`ÍL™ÍšVež$†2ê?Ö†W@d„/:p™˜Ó@<[r†—~ F:ú«è5nÇvmw k?{Ëg¾ñ’¾ñÔ?MöÌÙúÆ×2ÙwíS¨bÛ¸‘žé;nì|ãnÖµ19E%£X¡ÔñÚo\ØÒ·"Ϥ‘¤ÛRµPn!Ñ8—**fSû"ÐV™5ß@G®)!á7±=;©®¡YXï+‹…Œé<&Çf·©/¤U‹Ö¤=Ù\ëObìÎ[»GôûRjoÅs«}–[CýÀd•§þ‹Á²EÞn5ãBn{:3é›ïÚÃÉY@æ”ÁÔùž®'3aMèa3È[¤¦¸hom#ÌßÄrãQa¶•N)`¢t–›cê'îyî)*L%uò/ßÿ?îéáÆ7¾ñ00S`%_Q|^®Ú/µÃáÇES¹eŸH¬¾ütAó®:óüÒ#zbÍî©çǃ“¯^?€N,­’H‘L
ÑÇØ]Ke”	™
|‡.¢–ZìÞê4Ôú_/ä‰IbO´МÍ/¡%M ê€c§6§ŠrøFU¦IÊT‹x§m°3»‹fŠ3ö“}‚N£}ÎHødÔ V.1¡YÂÊGÛSkEV“ÂÖ’‚9—¹ñk˜[ª¡k±šf謦a#Ï™á4|<ÈÃó§äq3°*•”fXÆÃ2I®qÏȧ<åo‘§ÜeE×ÿ_÷ØàP1 ?Ч«À³Ý£½M+Ëà’dH&dѰ° æ4BÇä¨;Ê”â‰$‘$Ž™$þAêNÞù†C•½…«yàˆE&Ekx‰#‘¥Á!šâÿJ;G1[ͤ}¿8ÚqÝÏØîd0<²Kž9"z»x¬âòŸÝäñŒÝ=šÏ"0Á}·÷â\ŠñÁ÷LÓˆ§_Æôºry}ÏA5.\rV$ÿ4ÎÈ(û‰‡Çh3d'wA›|½ÃÇ'²ÑW\GMïÀd¤’]̉6\XtALhò"rAwŸ[9fó+gSo%—írh kŸš±eÏ…ïî‚tUÆÜ¼ˆ)}óžË¶ñÜXâ*†šË˜e·ŒŠùîý¦l7n¼……Þ*‡"ç1Ïå|ÇÚUˆ æo¡j†¥µsqrR8JaêÎFePíü•±—n¥Yí–rl„Žõ¹Œ©.šul®ë4â&½À²«’d}ßâ[_á9›0frä’¹È1¼KÎH«w/-r¾ÀÚ˸öþjêLkÚÖv°#TWìrdúã}*M‘+”韒I®­B†ŠŽÒ‹˜×MvÏÙ.?ýËž›Dž$k	”éo(ííÎЩ‚F|ÛO?#ºƒ>£1tcž ~HŠ5Ô0þª ®H3¢9Ô2Æ
ÂMÝ5\SßéSB!–zBG4º£÷@²]0Ã.Xùo}•–5jX§ùâ{ÃÅkoôž,=6çÿp—NÎcûWMûˆ÷‰:‡°g/ÖŸÜ_{	nÞTIdÛû&æq]lŽÈ™ß†V!rÁ‚<
•=?pO}šå³¬®ê¡ðñ¤ð™ÛvÞû¢õQÂvˆºíyÌ-'¡žâtZ=8˜zþôŃ"ßQr¼°ƒÃj‹súa÷7±ÆRÎÙy ÅHÄv©ê}ûhXjß6oü@PJÛ(ŸÏí°ø'Mòí)2Œc¿œÓ÷¾e K½÷ö	R4‹„­b¨Þº’ù.õÈ»;(Kö
ã”?¬«wŸQ²É}µ¯‹rz²ŒYy&'¹Ð¸·—Ž"ë…N<ÌWÝ[Vb9“¤>¥™7¯7<ÙÊûþRâC2¼ÕÊÛ`“h5Ðï_)ƒÂßwÄ?1ƒ¼…Öøs;ôB¡ÒžÉãň˽­^IÐåý8ÁYk)tåèÜdAQ.x¥ki­!°?êzp¨î¨×zÍ«ä…ïÉýüúþ8È8?Od¬Ÿ"ã—Å‹÷ˆœÇž?ûo¯ý{œá?ãkÁÅEpÏëBîз„K°§'ÿÓ+’¡ï‰B™Íó>¶{´6YÅ\w3þ-×&ñ2bÉ5¤£HlíxlçëŒVGÊNqGã‹©@ù÷M½{TñK†~i‚AÙ\']Z~àõ9^Œ7Mߟü
ÿþÀ%O:endstream
endobj
318 0 obj
2586
endobj
322 0 obj
<>
stream
xœ½\éoGrÏg‚Èß@äKÞ3üFÓ×`}m8v¼Ö"YHƆ—DFI‹¢eí_Ÿ:ºª«gú‘”“]çõQ]U]ǯjøóQß¹£ÿË?Oß<ùÃxôêö ?zuðó£/òÓ·G_<ƒÁÁ“nîgwôìåÏtG£?CìzôìíÁóMÚ¦M·õ›‘~îÆiîæiØüý¸Ý
›/·»¸yºÝÁ”yŽ>ú^Ç|ÿ€_o¾ØÒ`~Žßÿa;]ïbØü	GÍ]ß›gÛ)À
	‡8˜7ÅgÂw.›oqþ׸£ÇA°DÀAaÚ|´üQ§<ˤñn0C¾@Âa1ïzöoÀç-b‚&`ų³|ü°MŽ|6ǰVèCH›«2ë¿ï»0!svÀ°yŒãæ’¶íÏCÃ<ÇÇä7ç8ˆKÈsx£K›k:pšâæ®Ìy_Ã2.drpöUùúŽƒ›§Íív'ðn©%‹RøöàÙgÏY–¨pç B·(T$gö¤0p,¤$!
(Y×O@íŽûê¤[ÞàœÅOiêKäLs´=z€-¨´ô;Ž=†/ëÑáà‰~¥ÕQ3êü¸ù€tÒÜhàeÖØó,Ü¡E®¦ãqòµ,‹“gù=öŽn×)LÄG :6RìQÁá»<
YúÔEÑfÿÐ#ÍC½ç1®
üÕÉ|“­¾¡!!äÛ„²ÈwñGš#Ö ¡ŽžlB –Áͬω®lært¼]¹Û"0ºDñæ#ª	Íù	Ï´ãCí@i@C…gCyã„<2EÌVr‰å»ÌWŒú“&’0þzQ²CO²ÊäÀ•'>è0š:ÓT•õ=×[°G¤ªƒ¯h?f<>¼-	ey§Ç6_˜K•çŸã²L®ŠR‰Œ08mñwâ$1ä=óåæ„‘ííÒ?
ÀX'ZSéyiÅ´”(Óqly)ÃEh|x–\foF…å—T>H=Ü6s:ß;YÜp-xäyãØœï䔤Fižø°tÐë¼
±eØôìq–›;/6éL›/w)ØÓÑʼnu¢’ÁpjDÞÈB×rÓÊè°YèàÌ÷³6_¬ˆ~
Òú°ï)Êœ¯*þ
~0&+êí2Éà³PµLÅß(ÿÕ`p´ð´èí÷hX-.³¥º¨ŽwIÇÂ@Z·Pv¼+v¨X’Sµ0MÕC÷¡®‹²v‘\É		nt}$%çóeBƒ÷9ÛÞóVgeÁs¥†|{™ã¬–™
µq{+V&«Å#ŒÿÎÀËC…Íÿà8äÞOÐàèL§^fÃxµõxŸ-ad³ô8cäÝÎi…¬ ˜žLDêÅГø¾é"‡Zçòõ 4g&}ÀxÎwàP˜;0ö£Yé4n*ŒRÄ“§8ðQ}´¹?Pʰ
ŸÕmC!€¼nF+”¯É—ª畳Çə籄0cP—‚'Ëx¬%98Þ>¸'%Ê)òߤ„T{}œ_A8+;²RM”‹ùUº¬/é4kwŠR—[˜ÌÜîÈB2u˜;P[Åx)ÍîLPR¼R1?&0^\~`ÛÈ÷¢£ì1£Ÿ)½+ƒ‹B‹,Qœ?ÂÉqRerÃÓVvEᡸLÀºqéÐÎ$DɈÃÛm ˆ‚	” 1³ðCT—Eϲï ”
‡KžÆ<kû{:2=K
/ª‚&2M×ÐÀ¸òŠšû‘S.·Šã}â´{¥[~r⇭~‹z?³ºËø"—_5Wj…ÙWEæjÎ%!Íî¾
t|Žòê°½CÙOûƒ}?ö”'ËxœO@Áej‘e‡¡J®:²Àž,ñd7lVA„¦ZâÛ~w9èÅg‡E-šûzÅy¡@Aä#ÑZ“™ïï¸LâîͱªÜ- mÐ¥JJ–ôË6T»qø>
ƒbwö0dDü’¦RP³¬È"Û¦Ù õhñé×Ï~8øù‘tªjÀ¤é(zOÉRœ@ÎaŸ¾=øâéÁ“§ÿ~ôþÝÝùÁ“ÿAWq&¥@n©ÊA²’R6ö&?})î쪕=¦ŸŸ *\fMZ…{]†%K‹…EZE(Ît{!üuúŠij®ØZ>2t´dy5R"p㺩öc§™¬Ò}¹ÄU­8FÔš}Ϧž“/¿¤®«)k̾Ra™w›ãÑ¢¶@DæJaE
qu¢ŸcŽè†f0~,Å‚•nˆ{ƽEÓaTXúBwöè&
PÚ‘K
«¨ëªTDñ—ɇ6yàêýH«·eµÜçŒIÕ¡/T®¶kTÀ¸¬

xÿpUèA˜T¾ÏhãÙ>Ó/²ÑáC4\˜å뢤ÀF
†5•ÏA6E•nÝòÃU7
œU:*ÚW\ªß¶)õÁ™j (ƒNl¯Ð^ëêŸFèΠéUåÃ:’Žk1‹F‹ªôE­¥ÎÝ¡›¬¹ÑãÔž¿Ú*·„k8¼ö¡ñ6ǃN£
Ám§¤Ë¼Ì¢Ù"O®c3¦.$åæü}yøðH8É»“FBõ«>¼,‹è}yHܘ²ÜÃ~6œ02¾,UëóŠ?òñÌnN1AðåÖ² PSLŠPܵ®ýŽÔŒöYEØâ#ŽýXžÖ‚ÏËØŸ*.u$§<,éª\è-Qª&Ö·÷ªt×µ¾‘I~Žÿü”Õ/bëÑ4êŠæÌe¢9òZÝîZ¢ºl|®ªµ‘bIsMOÇyKÏÌ–M|k§¯éxè&–Ýo›*pÜ|zW)¿È¼a‘ö²
d×O=Ä|~2^Ú?¾ʹvNƒ¹eé;ƒ¹âL«BŽwø2u¦xbT¸„JïIÃÈE‡B‹{ªRƒ¯°Î¼Ü1ϵ%[çl1jÕüKAå¤(IÝÞØH­Sc(Ì™º‚„7š'}¬zûŒc}ÅÁüá/¨œ¹lÒ`4䚤I2¯ë8A$5¥*q“mZÜl
ÖBêÔqÁyI¬pç‰ùQÛ/x£ œÏq¯RÁ2˜‹ju
ó‹)6³i“·âè’{&Ò˜ÚeøìZ,bT¦.Ðç.¿}ØKUb_umÜk£wŽþŠïËifò¦eÌ4-²z?ÜãÞZðň¿gШòhºlª>Ý÷ûÔßÖW£˜m¶\†x£x×T—ïŠd÷Z#”®QÊ‚‰®¡¨Œ–ž>7äÔiG‰E×øhµ2é›=ïH“Åc™Ò柸âs\ÔÞF+~àšŸÄC2ðù•
¹Ÿt]§Ç7µQ–anCjb;
-+I¡=Öj½Â{}Ÿ(¸¹ªyV¨šé‘/-JÜ–“}°ÛÅ%À?ÎÃY£ƒZ÷ïûbtª.³‹Œ9p¤îlB3dãs×M@9–m¹@n^×&ˆªºš¯¥±èÔk£€ë¥îmÐy‰÷—#£å%ªÍ¶Eô‡bÓ±éêÔò4ßÖàÖZûB’¶N#qÎQl·z­r»,M{Âò’Å”ð‹‰“þóÛÒ°6ô ˜•{:ˆßùéÈûaøëv͸X8E‹íáàÕi,’E]^D’‘W]!ð8‹ŒôõC­¦ð/¬‘¿ˆ\#žåa
C懈BòÇÆ'ƒѨõ§½xâ[/ž\óXˆz†üJÈägÔ¯üšÈ[°QFªm…iêÆ™_ÈÀ?¯1Òë0pð¸nô1M²&ío^l)Kñë(CÏïÆvCÄHø²PjÀmGØvÀ¿vµ#‚»ªF(­íŘB¬0ë{.Àv׸°iÏ/ç½îòû­YsýÞ7¡Ýv¯DwjŽ<÷u§f) ¦/1å}¯ÞbÏ+¿fY9¨½ÎOþ:BÁ„°‹U±Èç2ü#ÞsáPuÿ‹Å±N€	2änp^öeÖKÓM¨êôí®¬3ÃSÍpä$¯xiÏЋi¶Y½YŠlÎxá¤;RVV-J•:½¶¤ÿüOM/Ô÷ŠmÙ‰£ô×ÒêC­¹umPá¿e0rZa%‰½ØZ`×Oé¯N£mvÃ?!:ô ^âë:“Â|ü7'ÚMLaê•‘¡k÷’X¶rVû¾Ñä ŠD¼üÿ¡¶ù¯´‡éGaÍÐ|e¸Ô!2«§Ø`uùCܹ|ÏKRšJüpð¿ûê	endstream
endobj
323 0 obj
5132
endobj
327 0 obj
<>
stream
xœå\ëoÅïg‹?âJ|ÀåÞìÎÌÎî´‚ŠAHjD+¨¨±ƒƒšØy™”þõóœ3»{}o	U+$ÇÞçyþÎcyºj7ݪ…ÿøß“Ç7çíêìàéA‡/WüÏÉãÕÍ£< sùÉ&µ©[ýx@3»ÕàVƒ›Ö­Ž|{Ø7ýahú¿}–gø®š1Äó¤£Ó<ðV³‡Ÿ6Ý&¥1¤ÃwøU³v‡Gðüãf-/î7kï»MÛ¸ö¦YØßùÛMÀiiÖ1¿wîðN™v¦ùMÚ铯Á›1 Þ&Ú9_æ9ÎoÚ®§Aw˜WI1%8”ƒãÀa\Ì+v]Üú|ßã.ù¯.Dè½Ëëø<ÜÃê~„Ååý×ù,mÛ»ÁuGÜ&­Ïó†Á%kÚ¯»6mX­}»º”ˆ¢á:2QŽ3N‰(];â£gp¤¯v‘ßþ˜ÿ‰ú¢ñ23‰™bŸÁ"?ÀóGùL°Ä¦á³D_Ÿ¥ßŒ>ù0~ƶ£Ãü”W;<‡/òUº„ƒméÍøñh›ÏØ~žÁúö{]á~<®Ã…òUò—¼TàÂéðFÞ/ÓEö£9ù7áÿ™>ú-ì܉•¹-vîwºýmÎâ].–”ê¿ÕºÝ¸ïBå@3zòHûì@}/>Æ5~Éõgo›€?Œ¢n7s>Œi¤Ê¡»Ø.9óµ;tô'y*àx|	ïWä‰	G7pA¯cÒªƒ%=ò1
Èpý˜ÿAr”b=¬‘à‚)Ðßðâq¡,4“k0LqQ!	­§WºÅã/IçÀ°šƒ¯¸@/·ÓÃÁ}7nœOB`˜œÐÆ{BX/š"ˆˆ›Æ„›Í×a`û™*…n‰w¸3~¢pïA_ ÿøö†L¼®9Ž™¤¨O§3Њù65NôÜòƒÉLˆ/+'#SPæžä	CL&d(¿€ˆªïÃøˆã¨HQ·øò·CßÑœéf즵Y¸f²µ_ìšßm?XÅ>!*òNÌâ¬yO?¶$SÀÄGx±èÈôDúZ1²‚ynÈ‹ €ùa5²„dÆ®cMdñòºHy
'),‡¿~ÆÈcLÞL½Çòhç^–Èãa‘ž24ëroþäcòv$It”$µZ°3ˆJÛŽñ>(I‹‰3¡1ÑTfî´p…¤´~YR\òS–5QmÀi†¹e"ɯيF4yx&VÄOh‡AhQð ÿÑ(Ð"AK.%‘9†Uø°™£`‚ægÀµ”úŽ”$®e^]Ö6 b:žÉ!b
Í)ϱJDÃ&š„ôíŒ,έ¹1$/t“Úò L<,±*l|)Ž*“"R8ùD¡º^cW%6ë«^ŒsÙS¾ña¬Ãþêu˜ë¼ c+*Á¾‰—3®ÈwýüàèÚ·”u0·E!‚DAP¶\^#!ÀŒ¯»Ã['‡£¶X7ÚȘ48£òD¨^Ù=RŠÚ,ú,á/(Ã[”V¯¤ê	°uW«'ŒûW¦4æ„ð
('èËŽûn ÕÉ@=v¢;Û„¡{á'B[mº`È|œPchÌL,ü1	Qer.ɇEüpZ¥‚Ör«Z~¤0mØùóp¢ÀàT_¹Ä7¨µ$ÓN^kèzn<ü3ÈuºL>áôªï¦e\ÉÓ‰2WR%2tiØ®øé‘ú‰Ì©¼‘Œ‚m‘Cò=bæ+`/Qu†€¬2ÍŠî2X7nž¢[ºmç’Ta”“›T![ÌSQkq8¼õ~ùì°ZÙLîª0Y˰ö½‹È'Áá¶ý¾€Ð€Õ..â¸%¤¢¶[oŸwþG^$ò=†~YÎgúÀ§gð¸Çuý©’àÀ(Š’éò°ò®ß_doIF@*âð+Ã?ß9jÑúEàlè>^Dà)¨èeŠFû
Œy€H‰+‚†qÒ^¶¢6É
‘ºRªœGA­£®3:˜ãyxÅc.¼†ÕrÈœ:¦eÃL”ÑÞd@Û«½ÉB—E«G*¹Éa^_2BÛ±{mÉH6 5¢áLjHW­Áy¥g¬ˆu@Ê׮ÈWر]W9‹ï’'YrWqî¬\W˜Þ
¸Â~!b ´…%ÐÔu°ÓXÇ)Ú„wŒýfè–Ѳš©ƒñ"SI'愉Î9Š=N8]$	–›\Hâ“:š+±P
þ=¨©d†~Ôq»×
\‚Ü‚EÛ|fBˆc
½Å„˜jÏ6ÍÓ…±ÝOÞÔ‡aŸ}öÅþíÕ+‰Šxñq˜|
hp–¡Il ¥¶ä{tøôÐ0_|@ß<ìiÝB¢\œ	SÓ‚GSPòc>?úÔE^WVß±úAtŠV¼†®—l¨z²Ê÷PÂŽ¢p,ŠÈHÍÌÙ#·Ë±òÄÆH³”ÖºÀu)åj¨ð Q>>:¸wðtåý&bÕ?Ó|Ì¡WÙ›´ðïÉホwnÜùbõâÙ僃߬ºƒŸÂ›_ÝÊÿÜùhõ‡ƒï¬î½bƒàæ!æmÚM¨ÉàncJö-ÿöcÆ6mÂ[8f9з§üº)é*Îe݃ã~ME~0gÀ˜*Aé ”¡òÖnT/"’&ÞteŠý¢î€)ljÑ%J˜¬ûT›.çzJ¶5ßVÒÈêµ9š$Y®Ýa'‰5¼QïôÖÀ”üBsgîH¤BӢП¥Ó´š2ïGO+^”<Ú;2‹iG²á¢™›Ì*M±˜3
|üÉT¡tÛÄÚ,0uæN;y1³ÛdoãÆµjo¯¨h´œ‚ñíb[(›ˆ†gGŒÊ(¹J:ÖÙçs;
8_áFLPLƒØðÒ5jÃ+Ý'9þ	þ¨X1þs}žBuèÊ”V¶š`7D<óv,5´*Îdä_ÙUÇξ¶µÍ¡í˜ÿò­Ç7h´²m„bWÞgÜkWè"roáœPkêsî0¯nkÛÒ€œ©;Ÿ<ÈDÂ˱scIÇúWŸf±Ê˜Ÿ+rèz*S­)ÎžÔÆeÊŸ&¦ØèBÐäÓ8Ã.îläÕ3°_A…+ɤáÙÕ¤‰Mc¤å%KŸhâU„³ÜÔÐAÝ.Ü™•’ølDÇÆi¶%ÈZ™`[²ëòþ•´tqDˆáAÞ˜ô§6oÙ®1nÕÑâœÏº~@‹ò†Ï2|nÁ¢˜Ó~ÒPgXn‚õýH2ŠEFM
‘EËŒï™b£*yÎÊÅåÄ÷P…ÊÇÔfÅ¥ÔA"žÏ^wŒ†–Ë‘â5¦ÀÄæ ÓFG•LÂJ£æUͽ„B|ìS‘Ò40º[@¡#´¡,ˆ_p’:P¸˜²qºÊ= ©Ð„Y‰çKgŒïPc‹¨$C‰N“
Õ±K<×Ráqˆ.%$¦á^€g*çkKIç·É¤OÈz)ƒ®MÝ4Ó HÂ$ÃÑÐH=€SD;òãä˜åÊo†’]ÀÑÿ„Ѱgÿ›ñœ¢ˆrF“Ôi‹p9lñГݙB÷ØÀª$.4ñÅD—šfAE«l
îwéîÛ‹tjÏb‰[ûµÆžÔe˜“M~¯Îë]
‚¥ëÐô
>Øñ°\Lg’Úк(j‰ÍçmÞ/êÞ%zXçôfžæÚf÷J#éþÝ‘†ƒu÷¥-”Omœü
òzÅnÈñdã0±¡‹Ò{Md–äóØ’„ßb&×64â´înUcV
O™Üˆ^õWèÇùVýx›»ÿ×ú±ÇAZòWi
Hÿ²¦/j
w‚å(«‹&«^9ï6aÖ‹·MyvZsáød7Óh¿ØZÂçØ­âí÷jŠÖÐT: P;Y·½“AÒ@ÇŒ?¨j)ó¥o	wÇHHȨqåÿçÆ;ù&ùC­&‘„I#X§Ž˜¦F·gœh3hÖÊIMl`®¦€ð´ª*>ldM0é¦dI ËeûÜÍм@ОJÝRRìçû,È5@ýÊÖÂåñ}=—ç¸OT°•ùøîÌ¡üÊßáIxÀ…Á.#¤i¦ñ‡Iƒ@Ç̓È1,m—.˜…ãÖóïÆ	š¼­·IoÑ¡£ÄóœÖ{0®BD)‘­›³;•Rnë8¦YÜH.¡g.+š6ÅñÉO·152¡1´‰ŒÕnuD€Ú òcng µpðùÏ~Dàm¾4Ü6Oï›Ôœ6oÞn$/
3:t¼ËK}š‡i—C›3ïKæ€îPÙ#ÉQ&†·§NkªâÑç§^F9øØ5q¿‚td	'FfñÜNF•ŒçM%.j:£!Îj©Û÷fcÚJkI޵ÍÄ
ÉìïE4MTwYaóôÒ¤Úé“,ÍÁÊ
ÝŽ2ðsövý&ªÀ˜„˯w¥©bÛxŒ²4€Å¬¤Fø%_öÞ®?¾UÞ€2ãh:Wm:M@î’)üÐR÷‰¾ý[S>ov–õËBD¼±…ÔúÒ4ô㚸ä‹~!¿*|šJÌ_e*…£V„|^}`Íbù…R?à–õ]^ÒnÕ	ù\Õ'ÊÚ¥Ü;Õ‹P"²Nø¸šuóro6ŠRVÉ•lØ$Èà®”:â-íP+ø\„Zp§¼Ä8òtRÓcã߇ym¿ë5	ŠåÑ:I¯˜Šߣ¯{Z‡b%ctÜU]®“-LݹöKÚç1mN¡îª Fƒ75‘Þ]é™6»9óäÁ€u‚/õ°Û-ìšÛåO,<êÎŤú‰Å0W•Æ;uþÔʽ\H×k“jÝá­m³&_ß›‚Å{y÷Ï@Ÿ ™ÔSáóh‡mR¾à8ml
H²Ù!`„|FX¡äË•¸Åph³µIþ§;zi©¸ì'FKU[=žô¸IÔû&âÔ´™”¦Ò¾p¸+¤àþÁä”늰aÜÿAu
‡€Ð§þÿ8ÈGYüÿ7ÂÌâ¼Å]°·a©¡;Îâz_¾cdt
„‘oÔ!ôªéÐM幉Â|E¨±Rx|7)`“9í¡ÃÛDú]-oEÝŶÈ
û]åÊêl°£„È7Š„ Ÿ'”йx“¨”…ÙÆ$ò™1Žá(l	¦î¦ô«˜ü¿?r,^)‰êy®X˜Ž?¿•·¬LjmìÕ¤4–mÇôÛA#ï5¥yïà?k“Ñendstream
endobj
328 0 obj
4318
endobj
332 0 obj
<>
stream
xœí\ëoÅïg—?â~˽(w³óÜ]!*’@ª„G0ª(T±Á‰plÇ@ú×wÎkæÌ>î½i¡5ªhìÝÙ™3ç}~sÆ/WmcV-üÿ=yqtçI·:»>jWgG/¾\ñ?'/VwÓgÒ“fh³:þþˆ¾4«Î®:ç›Ö®Ž_}½›°n6vÝá¿Û®š¡ëÒ£/6Û¸þp³õ뇛múdœÁm›Ç|’þ»—¹¯×w78˜žÃû'›¾kZãÝú+54mÛ­7½K3bÒw½àËôÎø¸~ß߇-JS8äúõ§@Ë—ù“c&VK_È ±âø”·Ÿþƒ[o‡¦÷«­k›Î
8I;ºLƒÎÓ7À‰2 Ô¬/€YñÞ|›†]3{/^m=ÿž|v
Ô¸2¼5^ÞÊž§åþ•–VßÊôÈ
š)ë[i0|p±±‘øšÖ¦ÙoÁˆ~ýÓ&Ç#ùãfðøå)»û.-w›…d‚Ì×§H Pl¸æp­óšèi£±À©W°dDÓÜ$rbBëAp¡—`¹k»&D‘Eb/ì´ëh7‰fßöH
SÈ:";u¸P3øô£xI|ù¶°>¿ä¡j¬Ï6¸áŸeUq{ƒ
¶å]lKÿ€]Áf~å|F«Á`¶“
™‰ΑXáŵh{\Ç´¢Oÿm“ö hà=¨ŽqÈ@½™´šªòÌùˆ¿Š†¨…ðPiÜ!‚µJëæX¶Ò+¶€d(¸J¾8i2$ã{ø’¨R
t%½CrÐ8bªé›!ýêøÑÑñ»_“©+n&m²®GgÒÍ»¹‚ò¾€mIÄ6$äJŒ‡‹âhÉtØ€º]æÌ¶„›‡ÇðkÏD{Òœ»‘‡xAÚÉ8¾Y'
Øô(Ž¡¦ŒÜæÖ¬œ‹jŸ¨,n(þ,m©'»Jµ§0	†qÞ¨TYÄá²*Ñ’ÆïÐ7XôÁïÃÔMzóÍFwßÓB>‘ßBêÒ‹çm£…0€ÛD屋f<ËZ>uð(ЫüÕ
ØLóJÜeÂò¾3@EÞìd°Š8æ¢üŽ,ï8 O©Í³‘'§Ý¡¡÷Éžä´øŽíÕ<ˆùˆ§}šý%JSœyðì½GÿÅA
_6óñ0ºÁ{”Ëùu¯ªFÀ¯•ÛpU_™àg„ø#IÞhèQ›þ»—¾¸Å£(ÚO<	úÐD+:ƒ)CÎhéY¿‚9eQS®·OCG<@qD”"AæÞöÙ¢D+Ѭ:ôÐÙõ +aàhšâmæ4‰<í´v@`€Ö­ûDüm¦‚³9NßvºvÈÉäØíHb"y)áX¡å‡´O…û*ÆY²ŸWäl¬m¤
„”!w¡nÊ	J4aôàÅ(ŠNã›Nã_³ÆÏ¾%ËP¥ö3Jê½­}ƒo©(ç(@¼0‹zƒiW÷IG)ÚDíh*@´£Rú(iˆÔ·­v ´®—üG¦-ƒï»ºÈ%¼³ßɬ£tOÍWÊzˆ”Í
tSaxŒó†îÉÜãM	ÌBÀ‚KcöÇk+€…”\‚ë
l 1 «CTÇÛ&¶f>gCyá¢at&da-³‰m‘üiáIuÊCh·/õ[¹ž¢3
åë¬k䘘ðå|Ç™Pòåi@ü¥Ëu<¸Œ¥I»®÷mé×mÕñÅsÊ‹)ÑÄPÐ8D áZB„tHNŸê¬9
"ÎØœ´éØLGŒ˜H’–Kf“ž :T#•¹ÜË’aÕPTë0ÌËÒ9J†dñ7¥šòêVÁ–aùì¤DÑÑá<›ÄL/>ì~ƒ^K	ˆæÏå É$XJý2°¶1Û4æï»“£Z¿ánorÒÇ9üè´oŒÏ<3ìbÃl)”Æ´MTØž:§ÍÛe¨ÝJˆ•D'EÇ
6´‹0¡mƒ9qâjõ8 oÈåcköyˆHŠ:N*\8à^œ’´Ñ©z×r9ZN¸àçAŠ¿­a9lZ:ç©N*–œVÅ•åsUzg³«‹•âÑ)dרº|Ä›™J¼Ðçh0n\•]_æLvšåVI§C³_^ý²Âhކ«¬3^fÄ˹¾Š)‚ÊQḃ’¸å:®hÍ%Ö{rr£³¡9“OáåU	üãˆvrÚÍÅÓ¨î'·
tÖ„aœEJD^±¬Olâl+È…è5k`,?ð‘ÿÂ9@Uå/¾Sa¥0|9‡	ÕêÓºlkÜæ|O¶&»î}~ôr•\YÄn©$É~eïW>&	Äš¯î><ºóðñêÕ7ßÝùÛÊÝùþïîg¦Þ[ýéèþÃÕç‹YuC’4fYÓÁáQZ¦1Ô›
¨e´L¢ƒHÿ? 1	Øk
©•gk*$ˆòù–AÅ*“G1)/´¤E£¥£RcˆžYª½`á_daöP¨þÁ¸e¥]‚å$,Ãâ,*Z3:€ä8Mo-°É\øõøŒ@1 «–²›ý>Œ4€ðê¡1å #WÔ–:;ò/ûp¹kîg()¬ëU
Ø‹2©×‰S×ĘÅ-ÎnQ#n¤ää>®à43zÕ|KèñiZ†AÈáRA5‘ŸS0×/9¬¡È^€~‰xž¬Ì
“C‚Ëâü9 Ï€ÒQ±xÈÄ@Î!ZC1ÛÕj5FWÆ«dë¶ e}®Biô¸}†w['9•/çi2ÏÄøüœúæÜˆƒàf2§œ
Í–1L›Ïœ´/(y
®"œ×ŽÖq}¸K;¸qT7MQ8&¯Æ"!IE•O¥¾£>KÕlDÙO«ú r¾o³[('Š¥ƒj+ŸScîFZÐ83Ìø`#)Q>wå)¿ýhÍÞu†ÞÈùT-pèÛö]®99j§Ù‡çV<•ÎèÖ*3±	Ó7TpHC
îâBú8dO³AäƒQš-艗ã|;ê±[jÓ(x"]nXØ
ÕÚ£"rÌ,‡øX*º
Õú %1m%jþ½¨Ê}fRžÐg`†zªåh½ä´âcòÊÝÚq!	
âP`r
|_S•ª½e!*PqÍ,ä=­×¨õn\S;•²3z˜ýPp*yœ„këùRΦ5Dê¹Uz\?ªÒëWäc SYè܆ù$„R†š‚f=ÌÔ¹°S
 ÛÆà1Ѩ­›@-CÉF*@ŽX±ÃZÊ„þ“ö¼‘#óXŽíŒpŒUäZIŸZκ™WùÄ©
Ñ©j¢B“¹ªžöAa%ÚÏV‹Œ§|)­\otï
\ƒÀö†jAضêøÛlÈKÓðA|SÈùBLgGÖÌ&г’Áú™·´‰D¹dˆC–(5ר¦/ho}@jH1”c:NyIÒ¦¯Ò¼Ÿñ]
\Øy¨·‹]ý´s'¼ ìNd„¬Z
Æx?6±ïH	%ò>YÀvC}tºkÍON•¼†ã¦©Åö“‹b(Í^Ìf–•——\jä)°‚8ŠxU8útc‡Ä¦¡½ãK5Ñéq›‚nï’COk7&_žyA˜C•Ù x‰£7 ò¨'į…!UôŸl°ãiëp4ß¾æ¤ÚFÈÄÖw Àjqªš3ý}9┇ç•;Ij4L+¿YÃzõ&èëëúÅ9Ó…•aÒ«wóë«ú;ðîI´›¤
sB¤b`¡÷²¼?Ÿûè&?T¶Á{ 3I“r/î¾EßãÜëüðJ£JòðD#còðt£€ñŠ&jà:ŸÛÝE~x&õФ«ÕáGè1ºš<¥DVoOÆÞF‡š.¦4:4<ÏêwÁ,¢HÎ?ÝTÚù,ËUz—´5¤ü®làº"ª5Ó‡7åa±è³)øƒˆ0ÙûïdŒ¬þÐlÕQÿÏ¢kÿiªuÏõ¶ßšëïa®òûOËûOòÃÊÃ¥‘òãG2)Ú•: š5m:1JÃýJÝiÚcã£7›‘ùœ%‘@ŸÃ=MLóô…Xð~àùÊáBûùüõ¥x†¬èlP3aú@Pôòåܾ_/‡ê,Ì·¶ÿÿª‹·ÿc‡jÛºßÕ4g,\¼›Ø•Vl«‡ÄnïÞÆî·±ûmì6Th[_ÚЋˆ£*´ýÆÍý­€Â=õå+;rÀ—á8‚ò½ÖªáàT÷ŽÒ
AKI,¹é&ì¼&k«+DÒ*¤n•î½9ÝàµDKã’Æ‹ÕÉÿŒ)ÃÚyK	ïÑš	­ãÉè¯WÄÆÅ™îÛ=×hš‡ÎGÝ7YùoVŒp2Œ¿‹Ê0äæ 7ê•´C€fƒ­’]›{+Pk@U1ýkLsþV1Ë4ÎSëBõ0ŠÎ.“zm ¿9©Ñ4¡&µXG†m÷´¹¹n] »œõ«zQ`ˆº/-ÈW[Sò¾ÅAîä©{ Ú} ¾Ý’MäÕêïÌ(Û·°A'Üèô]NîÄ	ˆ‹†úúYrhLTÁÈyjÌ,Íåì\äP½\;­|aG—ßüæ8Þ~Üšý›)	ª©M«Î¦ÓâËëÞ>3½á¤>7‰ãQÂgõYd’ÒamÅ·Ù1õåPÁÒ‰åU5¹Y€[@:š(ËçèëK{Õ-Áf¤Ý×RËF€võ·pã£éšñYÒéÈ«d„®¤Aâ—o)d\…ŽY‘ë¥ßôΕ@ðè¤>?ú7&H2:endstream
endobj
333 0 obj
4679
endobj
337 0 obj
<>
stream
xœí[YoGÞçÁbüí´áiu±ÎÆ"ÄGŽ{µðƒ²F–„è°uÄv~ý’¬»§ç°Þ80<š©®ƒÅ"YüHöÛi׊iGÿÂ߃³ÉÎ3;=ºštÓ£ÉÛ‰à‡Óðçàlzo;À–¶ïz1Ý{=ñ#ÅÔÂÔJÕv0Ý;›¼˜éFÏL£ÞûGHQ°¦‡ƒöØñ~3W³ïÑö½Sýìëf?6s˜íQûÃf“³{âaÿiæŸÌvó°û4L¶½³~¥o 'ÎP§°

,Ç<Á1 ÛNhßéqÃq–Þô=Dg;w‰šWÁ_Bê(%à<»Kš]:š<>ÿ/ÒÒu“ÓŠ¼’¦qœµà9idÉɹ0ªun:—]kEß{Žžà²³sú¸ÆÑ¢g&½¦ß'¡Qήh;¸ ˜½¤ŸGôq˜žrÛ}\ÐÇiÝy‘¦¢YfoB—È×ýÔûCn|™ßåÆ“Ô¸Hß®óãcdŠF¶ˆÙî:Þƒïõ:÷:J¹q1²1ð;ñiŽ'¦
É*1ì§m¡æ}U?8
lÒ]ÏÒq'=~S»¤ŸwCG”ؼÓóLdq:éùE~~:6è&5žåF\Iõ¨Ù¿qR”štÓ¢wJö/ŸÉUn|s»ÓLC†©Õ$u}AÎUõŒ¾*Tœý¥ÖÀøõ*÷ý©i¼¾€ªô
”äó'mL
£é{,jÉH0T¤ñxø
W—´¬¡SÖ¬h°¡Çô€4IÐ#0ø@ƒï~Ö1f¯ð1Ë…áù.ý$PhÙHžÉcUâù½¥¦_	ñìPp{Q☎ÅmTøâ{€#ù¾ù¡Éj‰Ÿýç¥-¢ÒC×D/ËÐ]êl˜>>r–rÒÍ^«¥4×t<	«±FC¡TŒru§ªÕ¥ ë¸¯ã%ÖŸï3“$ó‹3ÍgÏ"Ÿ¢ÖZ¿[ÞiVÌ,EÇi²rH¢g¬c ‘ÔÖ$aá}Ö÷ïè¾ñC‹¯Ì2Cg'™8ß·´F¡´I^oÁ;Lü›¤ë=14²™þUðŽP™}ÕA¯³Cmn8-\¢8c‡Ï~¦þÞ)£o©ëMH×™ì³\ä—%T™´Kºzþ¶ΕùmË͈øxû‹vžHËÚÍJZzì`P:fß4ØÖ	kK/²…N€C%ò‹8Mͼ‘…$k±B¢£k›q_!Xº»ð®ÑÆÜÂÙ»LÎÞ~rç^¦Îù2ç	Ð0)çu|'»<±ë1Oìl¥'¦ÔŸÑÛ´ÒYz^x6ï×ûdõJš<êæ­|¾âyöØßopï&‹ÎP·ÖtÂn½Ó&âË#öÝùÖº“Yðò^£”æ]™d¯q—¹˜k÷04¢w¾z[ìZã:¼¼Ñî‹OAQ«XAŒOƒŠáInt6¨W!®§åFÿüàçS¹t†ˆãµ@ç?¾Mó,?ˆŠ´Y=S?f¿«Z.a7…F„Õ´Ânf+ìö€Q’
Þ):Zé½XÚ´ŽX¡p¡-9_o²“]‰¾ÏGÚô[9ÒÔ¯p¦’3ÄÏãòÞ3! ,él:1EÄ0Z¹Ù?ñgî ðAþßÅ'PüF†‡^<Ù¯:Éþ‹÷£GÕ%¤FÔjÇ|)Ðt¨Ñ‡IÈXÛAƽ,æ±J@9y²-K1€ËÁ›"#£4¶ˆJ
­.’÷ê§IÐö·4Kš/\¦uƒÛlPg	é<2-ñtq,ãp:Hµ÷}…ùP]àÜ,%¸åSaX²
vÚjèÍAˆk{à+i²y$JºŽ—_öÊä•J”¨/‹1\R­S"JT)í²,-
¡]!-û5"§Ÿé³xÕ^šùrŸbšeí¢PNŸ [†•Ë£„‚;ÃÝ6¢Ä"–;Œ¨Mù0fÖn…U©BLëp!hÍ'<ŠÁV—¯hñžp!h‘—¸LÏWœ\Á@-qd£ÝŠ˜n²t9Û•…· 81L@‡
|7
Å‹ÈR°Ý*›ÅŒîíÇ"øÀï€ça“µàð=tœ<£|¶[ÅÀpß8T‹ÔAS‡½ˆÛdV•ÇèủR4BÎþîBv‚Hý÷&O'o§R¶†sGÈ27‰6Þ¹©RèïÁÙäÞîdg÷‡éõåÍádçùTLv¾£{?ÞÇ?»¦›<Ü>ýÈ4 i‘—ÁECª*	m’×j"µÓ‘ÙU¹Ö²®
ëPBÓ-€Í"›œÊm9·“pN;ØlFÓÛÄ
þH“AÊñ˜§T…?<º“ÜxÖ¬õœ/Ó·»yöÿS0Uly	MÉŒ¦*öxT*ٺ ó˜Þ›G¦8‘˜z?JÀJdÅ‘ËNýÌød/ÂVóî7E·¶Ÿ[hã/«ðEZ…//Þô[·[Å[ž7=äøù™ä9+Q!
•¯X
žðž•0ŒÆNŒ®\côÆ©&Á{¾ü$d󿀇ýk£	“ü×›"-Ç…xT4‚6¤GÚ¯
Ê9[PŠfsñ¨j±†ˆ·!ý/ã/ˆÂ-{JïFY.Ð4Âɸŀ@A¡A*2ÕÜÊnwqóòs%7WøO£6Rã“Üóqjü67nîY#½-”kÜ!-=â¤]Ñ
6.×»lT³¡}¢vífHn¦üíÀx¯|}ÑèŽï^†x}4ûB(ðÎ9ñŤ\¦4èòç×é®Ççjý]"Ã{^ôU«!5k|(-צÈTÌ—>oTv°#=BåY‹„ÆÀ¿Ŭº—2Z'\Õ½d–´%,OQ‡(
íÖáv¾¿|…íÚêVÓ÷ÌEÐÇa®1¨ª=ò¯q„²ÎaÂjù¼Á8J‰„w¨ñIÎ{Ž´1›”p‡é¼¯ý#cÎBR~áÑ^%ddýBRªJI€ñíq“_%ᤈ©	ã÷@ÀvK§THqœá_س×m—ɤ”‰~¿$lߊ±íûôšö.sׄ„S=ý–46ÆëJ‹lT]×¼.ƒî·C<Ñ_ˆ+”\/6Àõú Âzuâ´€xU¶Ìˆæ9£å´@fùb™§ôA‘aiý „>ÖC³¾ž×2Äm¤€‚c	MÊdª™×Úe:”eÉ—ñ®Ï;WE«‚"©†5æÛ ãŸw"&­æ&7Búpêy”ƒPÖRH&k.,Ta¬>¤ô;¨¥ì;]‡0¬6Yw¬Ä«œp^ixXR–‘–Ø÷Ö—å‡÷ÆK?Vl¬¦;Ù+¦IY“«ÈT%#à˽ùÐ>
stream
xœí[ëo·ïg!Ä}Ë­á[-»Ë-Ðõ#µ¿b+MÒ¦HI–Ȓ✓ø¿ï¼Hw÷¤“ä¸)±ö–äp8ó›áìù㢩͢ÁÿäïÁ›Ýçýâø§fq¼ó㎡ƅü9x³¸³œ7õÐf±÷r‡GšEo½óuc{ovþµl«vYWvÙÓßU†zÝò¯ðêEµê–w«•_>¬V0dœ¡GÛ¤>Oàÿ{ðÊuؼ¼SQg~íÏ«Ð×ñnù
öê¦é—{Up@¡Å.Æ?àHh3¾[>Âñ÷qF‹€„ÃN.,Ÿ"/_¦!{ÂÏ#b2Ĭý÷ÞßAÆj9ø
 нCY>,;®¼êà+×Ô½î@“¼b‚¦	Ë#øíZbì”ÏÛjÕ.B&ÖØB‹]bËÈâÿëÊÑÈ6@{˃Î`êw™0vy
ÝO¡
ÖÑ÷–ç‚vÓÍRĆ~Àü¾ó$Û'I< 7‹c-ÈÍ–÷WÐùòÑ/àY8EÊ?eá!=lCÖò,ÈÙϤ$CKé	²×sË/(.d§u$	E8ÑÚ¯P(r×´uß™¨Œb¶Ó¨Äå1óøÜy	öYW‰¯°ªÅõ-
ñ·Á.?'úÎ	jžW«‡2dHá2K°±!J°"©nÐh5q
+ãê¶C³Ú›Æ‘†,QÊQÒ
ÔìÛŒƒ¬…?S±åÙL)õ`A	0`Å(Ò}æ¦%h&çøÐ_¹!ñ>Q'13ÕXcsM„6bZ𗆣æH"{
û
EÅm_»Œ˜¸ÐlSZí¢ÆDÅýy@˰scŒ!ÜR‹ˆ&šã1ü<ªJªËo—	ƒ¹
ê±8ÖÛˆ¿@ÞñSø‰g‡€â’@íxeú5ðÿmƒÏVž­¼_"œ<#Ýo+xq½&:ðž
± ,
paÃF::—†^6 ¦h8@Ó–Px‘O‚Nnêêæ¡jÓÛU;€öÀ,Dv`™¡¢‡76‚¢@.5¹rgÛ±›*¼g©W`Ø¡-4­8ªC¨´™}BË`†å{äü}3”~Hl@àŽÚGh‘3‡P(ÀrPi—öI"P@
TU¿òéT´á´!ÏËby”.)‰ü0£‚ÝúŠõq˜ä†´OWKXšúx7$Ð?ø÷øˆfKzuÁ\²oQ+DëØ%Ÿ"C†¯h‘(3]hˆÞ¾~_N6Þ’—¼ë-NýDE`~j
0­lÖ-²C©tz³N
ÖÁ‘®ã%áu¡Çr+¦”>z‡zü߼ľxj4­\×ÐaûkÇa2‰“ô´NO75ŽÃkGÚðþ0Ž?Œã†ÆQÛ¸m!ôs_¦‹ì§Þ¸£÷õÊ”qtü»0 ƒÔò*3¹¯»GàÞš[Nî¹IRñ剶ª‹Lé¶à¦LÀtjЗ͠8›%¸?÷òÝœM ù‘ƒø¨„aÊt~<ž$¢åº|m^|¿ÌêÚdLœ~'[È…à›õpΦ*.p©oÏLJò´Zµ	ÔÊò®í^¯À–Þ'…6}×&´‹ìn†x¥îô4¶ïÿ¿üßÖ^þˆa.7²ÝçÖßÄ®·µëFŸÄ¶rsÅ7ø~Ðs1ç×墈¤$g–Ò>1›·±2bÛTOÁ&É'(WÔ!â•Íк0⵺2ª‰ä*å´$j(—CÙºfÂí÷E2+¥“ßã€ËS«.4D«v)£ušSb¯%iäTÒ¨fÝÄ”v«R8£*ã1U@‚=¥þîæ4äÓ*¦p¸(‹eÖ/áÿÇ(¸§´%í(E4[›I­ÈÙ4œP»XÉÎpÂñ
‰¥ÆÆ^Q¦Â²jtšF2š&u`u5œKÉEtÜÙ¸½IÓZŠL5ñ²—'œ³ÇCK[|àZû®áž“,¤bá$±™k'Θºµª;›éãU{ÕË]Êìs-5¯à	3w3Žžft¤^ärÒ‡„“¬©üèéé2FàÂbHŒždeIT¡£Má2·‚n[¾š’…«ÊA‚ý×Hú†Ü|r£2…ÊqÏVNZœ%hKè™|Zçãuž¹Š«Î¸Ç*Ã%øT+÷*r‘´,CËÖÖ'h¡Üzt2³ Îep8¶PåGYòÇ_R>w”û7ÑoÅÃÜPNƒïÕ\îy1ç¥?*Ôk9¯LŒ©:+ÒÉqQ*ƒ@_Äçϱ²‰Þ‡Õ¤:šm¥öÆ•!Xû60{ŠÖZ¥ÙˆœåêãÔ‹	û…_2örO7QùI6?å èÉ…¥Ghà³*œýŠ.&~аïvªJ%Ü™ÙÊ”®ÙFD’„Ÿa£g#{qŸT0>vRnž²5ÓºXªacÕ&lº¶,e	nÈ–ZÚÖ©’ñZæGæ;Þ/Fž£eq%ÙT“
OöTùø‡vZŠEïqÓqðšÂ-M¼$«ÎÁhÝo±ô§œ
”&þN¹>ôd½'ǬÜ)—_[UùOnQÚBÏ‹Ûæ&X´|bdSi«Ã}"\ÑMu¸Ý©Õw´EÎsPV]Ûi=›p7Gº6¤2¬
¦­Ô‰iúgŠÙ¬ñt¿tïQ
ÞoyÒ/õû¼¢SkÎrÇçˆþÇ•æ
G-AŒFÐ?ߤ=ìYÅýb–^fȇ1¾ ÏzŸÙñ´!«Ã\Ðao
&ÿã›:‡Ö‚ÿHeáóÔ^ä*`Æo‹/lK¯æÓ$´ºò8óUª:4,PU.ÇÀ½7¼ø{ñð%}¥<‹‚»¨çD+©Ë£¢9²Ìýòì3}s(òõ¦8ÿã„zU¢Â˜Ä¹¹™q\QW*ÛÁQt¤¨×RWA¨zû
ÐI(@Ó6}K!¡v /1OHŸ |–Ñ3Ï”äÊ‚w—mÅH„þ…%’„3½êˆ¢xTö¦ˆp–BÜ‚,dì;Ãs†öÜA‘û¦s®zRmv3'N9(Ý¢tîó¡¤+çæ¶-c€ss˜l£“Za˪ùÁ\¦&gï&I5÷ñê—¥WsÝC¥|Oæ½K/UŒGEŠž,u‹
Šå—œ”[<ÉË÷ù幊ôœ-‚>lUµ¹hΗs‹»a’ßBeâ	ÞÆt#¯;Jjg˜Ji†uº®¤¦–¸¡ÀUZ)À{x¨»Ð˜›ç¦¯…ÿk9˜ÃÏõ•XÜûxFpÙL§sâšóóÙÝëàýÖœ)#xŸ^žç—Gzv¥Áyät^E`g68ÿÎÿ¬£²rvƒõôF”à 6tã‚燲½mëBWÞ{«mqDÖ•ÆOKë9ÎöÌq”™¼5Ç]vÛë9¿úQ-3nŸI±£Wß[THÆŽß²0â‡ÚÙQÀã¶*ŒP´…w’¼u´‹:箯öåç\ç½×üFy¥x5è(ŸÅg&¤ ï^úöÍ! úrOù^9Æps–ÂØ"q0:>ëQ÷÷v¾Øùqá\ÝÑ
5ˆ³Ãˆ»}Xì…€Þî<ÜÙ}øx±~ûîhg÷«…ÙÙ}€ÿÜyvþ<¼·øÓÎý‡‹/6^†‰[.ÃÙ0`í¦©½\ˆËÂEÉ‘þR¥äÛ^Œ¦• îGÉ9ÕT¦ÛXª–“aEÊ
Ɇ~¢ÑZ²^Eî_ª'êì6)š*8ãdUʀѵ…q‰Ò€CJ"Õã3á‹H¹œE.ªN7̾fS|P”u$K®dÓ{ùšIðƒŽ™Ón6X®1¹“sµRÜœR‹ÅžÁ:ÍæDÅrNGQŠ)Ì•ƒÿ#¯Êcå—eSYÜŸÊ-¡†3\ãÛù°;¨–¢® O‰KÞœ“VÃøÒU±Wû5"Wå¾0ªæû\±( n-Zæ:ÏÝ,ŠkUîí¦8/|„™Så“ü©c×4†~·!)ÏW1ò½6„SÌæ£Êñæ#H‚¼ìè”yºuE
•“ÊÛ«Üeö>ÊôHzR<ú}3à¡“¢Þè‚	gÌc3V¸dQ0žïjî—\Há@iptÁ× †¯ºôfPwïp÷iâZÝzÒ‘¬k%És‚ù
ƒûd÷xd
§+–qâ•éëö›¹Ý0w+·8¬Ky÷7Ý—Õž÷<*-Þ	,¨}ìÆwY•/iÅ
­<Õšæë…
ÞD­QîH÷?MµÚ8Òë¼úÏ‚ÖÅÎfJ'Ët:¾ìt—#(Ø–úx¨˜ÃkUMʰŽ>]4TÛM‘ÌŽÝãñ
Yú¦Û$$À>Õ4Ûe>\x.Íþ]EÇ$¦ÊêXUÅÞðÇËy5®þ·*t›z,±Òݰ˜hK9sºæ.NŸéšÔð'…9^Ý¢ó1H퇘ðš¶*ÐÚÓ‰“-/®»âš¹$×)(ÌÖÿË}aƒÓ×I–!Ù¡>8 .T^´ç—’’ñHÆ5¶’e~±ó_ÊÛPendstream
endobj
343 0 obj
3828
endobj
347 0 obj
<>
stream
xœí[ùÅþ}Ãñ~ã
òO_s("7DŽIÌF ²–·^ÛÊ^ìÁBþúÔWÕçL¿·¶	ˆD–û¦Ï꺺êëîW]«Vþù¿Û³ƒ‡O†ÕóëƒnõüàÇÅ•+ÿg{¶úð(M%íÔMjuxr =ÕjЫÁضӫóƒo×®që±qßþ•zUôúVÔéð˜~ÔlìúóFµÓ4ÚiýA£×o6z}ˆòOšM¨xÒlŒQm×
Ç’¶Ä˜âÕ)èžÒë[Ôœe¾íú¦1ÔhcÆŽ¾@õ3TwÜ—›£âR¸«ºež(Ô P­`ð¬__'NÆê#ꊺ¥’Håsžœ{¢Õ
>Ñ*æ—N•©).)H–tÃ
4"‘úi3AL½ãnW{b¥‰CÆ
¨È¨F³…Ï@OcÛGÕ=›&Ö­“4»ŸÈÒ§SšY
í0–y4hVᛨ†/¢ÖF""o¤ü2±û6‚MN–rÄä…
ÕÿB0åŽ}5Ö¹ñÝf»6õž5«u^‰®¡  ÃŒ$=»þ~NXðS9^é1šbA;YðC¤‡±x„Wò95û˜*É0r9´
k¿¢U¹i\>:8|ï[1ðÍ»/µõE±Žµã¥Ì£ÉH1Âó ¤ PtѬ=ÕÚ3ñl×Ú±,J3[\¶R?½f±©’_2‰¶ÌPÎ+³ÌÂ|1s]Ľ°þìy5;	Zšl›ŠDÃmÛ'Ñh5p§Â’ˆZ’ˆxï»HÁõ`v(whyfwYª2¥N½ïPMÒ#ËÚÆÂœ9Ò¡ä/ünçóÚÕ“ÿþ®™i>P*þv	°÷”ÿ#Ëë˜)3ã½=2G/Qíµ>“EÙ±ôðÌeìÄ
?lEhù(ÆQ'ø´Þ§Ì]šï»]{ÊNÌçqÜ‚/š¬Ë3!;ÇRýaºØ„æúäïà›­ªðËÔŒ7ÝÐêNÕÛ%J^{Rva™#j¨&è}h^SUO—
¶oœå
:,§É.u+˜±©’ƪ–ÀÊÞ
+y^\+	Zœ“ …¹FÀŸNÕÇåÌIöñ·Ñcá»]ÿLª­¨û¿#ÿ•wpA¬µÙˆlf€eº²TòàÉQ©)2åÔ•þð"QÓPŠ2ö{7V
¥“Oº–Ð ³çä h³`GŽ¿Øp'ùí[|ܱV
±8ðôÙy*åm[q°tXÞ¬Å`29¹Ô]‹vð*JÇÂZÀq)âI	|¿I›?$Ùõ˜µÄù¨¡5sѬ¥YA¸AŽnc‘º/<š¢ï:-wß‹äpê;|àeØé½&ôaã~ø¤7eØêÚÑ}+!ëÆ°9CÍœ’¸®Mj {,xYÐS|nñ?ÐÆnŠmfÒ˜g§‘­à!­;7ض±íe­ð´0rM¿i—6Nš¸™,½¯Ë
°¼s˜ï{±æ<4Œ¤øu#h…lÃ*R›—‰ÜbÂPXmy…&!Zjhuojã]Öf¾Š¿˜ÚÉËXx^ô	B®Öok$ÖZ&:ÏvÌžJ³éÇ©\2ûŠSrêo)oÛæ~NÔl´½M¥™3{0Û-h?qz檆°j«ã½.ÊÆ—ÍLâ4×J¬þ"šŸ0Þ«iQðQ­0[k²P¸ÿóÏåª5ò
ì‘äpT–²þ–öÏ}í(ù.œ€éâÒ¨ê
¶5Ý»Þí
¢ßzƒ·ÞàWxk¶R5‹ó¥©gÊõÀkíË{}I
œöZ÷³Tø47Œ}‰~ÇþqüÎÃ'Ú!ˆ¥8ˆý1™²©ál¯L°î²”ˆ‡‘Êåá~€N’¿"r•/Á6”„\ß¿ÛH¼5º^
€J"”ˆê'†!HžÀÌÍÆGMßHÓÌ>}CÇV¬ÃcCç!
Ÿ#³•iã‹ð܈Ld"3ÐãyFØSšóPFœP»½ú@ÕŒÀt%w‡.ŒOšôNÌá2¨Î'_a°¬†ÆáœÕæScÊè,%”˜0‹þ_¤è?%&Aºòé7Cl’0Z¶]rµ†ÅþŠ`„î_ˆ0¥€}>-Ý"óÉ’Í—eÂP‡xýh»ç¬÷Y’Ö{åÚ‰*ìİ6â#ôÔÊk´Š˜Hrä]49÷œ´WáªRÇuÙ€ö«]$º¢¹®çÑw’d<î +)s’€"†ìÙÀ9”ˆ‹ð0ìRF€˜0ãûÁŠŒÇ38¿»Ä3l-õÓV¼­gú†x×>nÊC¼«2컫lU×ÞeØBr™9ƒZ¬ïÕ<‘åĶ‘\*˜ýú9–ÚìD!`oÛw’—ü®Mø9Þí3)÷—Pò³>Õ’åXbb®“Gø¹éÖ*ËÎàž›`¨ïZ”~Ä` °ó&*O¹›Ó÷A1æG¢¬c1ð|nRw­=e†O’x&¿¡š~h-?‰ķŠãg½2ªe•†ïƒ1##îª5¤$® éž?*OnâûÇmý´‘Ðtô˜á88ÛÕÁ8·©:œ`G|ÞaòCq9Á5iöÅ[bçÉ®˜ÆK±YÜä+ûàøû¾ðü	ʼnÚ$Îrç«x"ñþVÍgñ{ŠÇHåFä³|ïWós#¾CðvË–ÏðÓß½-V¯²ÌžØb$ŸåçõËÏ“âsÈ´õýß1ÝT.Óf³ñ©ËK:šîÔû­sã9P&SቆéÈ…xü÷ºüÝ@ÛÙËßcd$ðã›É¦ƒèp´3?å†À±3Îã$܇6iE¬[NÒî¥&¸)†à;4ÁÎ$ßË]Û,ÜñzÆV'B[]ûüœ™~‹¶ÑÂÒÉuq£ŸßaéêpÌ—ð6hWàÅ3¦ç9åm÷ú˯+1¢5åºâý“úÉ éaéä¿K®ÑWÆõÂ…å¡áâÔÛñâæ„gÔQþr(¨)Z·mRŽx;^Ó<úöt^+çwjSºN#·÷w{¤ÇÅ“ÉoâWvšÂŽF{™•û_ˆfM­ÍŸ·yO»Ó™¼õBÍ9Ì÷æÇ9øq^ÔÃà¡—c4Ûxµb锎“SâVòãËÔ¼Ö1{Š—€ßä‚‚3–Š•]{ZìIFœ÷½þÅÄçbI¤þzUñÆÇçÛË7>©›ž¹]·=v]ökÈÔ±<|Í^ëÌnæx=
ŸåI|¸=á=£ß#>9<øýûQòá³endstream
endobj
348 0 obj
3713
endobj
352 0 obj
<>
stream
xœ­\[“Ç‘~g	ÿb_8­Õ´».}[?a$do°xW ðzÍFìHH 0Ì Œõï]y­¬êê>…Bf¦/uÉÊÊüòˬþáÞл{üÇ?¿ysç·_Î÷^¾»3Ü{yç‡;oÞãß¼¹÷ûgéàÒ•~VwïÙwwèMwoö÷æûÁß{öæÎ_Oc7žúΟfüy5/k¿.ÓéAºô´»šN»«xúcw•^Y×àðW?è3OÒ¿ÏÒ¥0ÁíÓï;|˜®Ãý/»eîÃé/ðÔÚÃ|zÖ-!µ0Â#.½·ÄÞL÷\œNáýÏ¡G¥&<–ÓŸ`,_é+ÏxhÔ[zCnÀÀScÞÿß³ÿHrpÞÊ!Ži@Kų<ýµáÁ+¾s†~vëJÀ$~A¼ïÂé6=ý&ìt~ß§»ß¤a%ò”{×éÁyE±¤?'’ÂÏi”§·éÎ/„Ó·ð«KmDlü¦óIæï]ðén<ýØ]§wyrÐ%=z]™á¥wÐ,‚ÇæQÐSnà»t
žuø.^JñÐæB¥±‡iÝ>Ö-
ÅQ½
-Âk‹È$‚øÊk[jÕ„@Ô~û´*¼,0êõšzi²ÔÆXJm$¹è„Ýéù©“±°dhùSÇÞà¦óËéy­CO4L˜ì²¤>|êLšx¥¯ãâÀ˸°t+Ïêh£Œ6`žÊ!s[+Žñ;ªä*-è8ÁÖ¹€Á`àÝ8ÑÖEyÝåu`ÉBL#"‚”îÒÀݰ Xd¥“ªŸ¾ÖýÞþÚctj¸¿„ÕøÏ®èþ›è,®×‡Î³ªÊá°`â<а
ÿbÕÔÜk³y«…	L©•O®xJz³Ì¸ù§`e×už½½ú¥±pê¿Àá†OŸvžTˆ'[Üàà¶ÿÒQ£àH}z)Í£ñâÓ¬>õòhðÊìPêWþЩéà	áÓ“Ë6&»uT¿?èŸò(ÉìòË,ƒ)„m!vœE™V^fX.Š<;{ZW~E6ôcR´%öQAÇŸòËéáôÛèy…Fo»øJŸ‚Îø×Ý.uÁ©ÓÒh°<üvŽ›+fù[tºÐ\É'ã²}ÀÜd`¿ Zzg¹Ó¸¾åÙÂÁ´úó#ƒÜÔGÁ­jTâ§áü?»À¨þU±8÷㻸…ÂÐdu5fP—°Ùk4@Ò ôGfã(þø¯¼Œµ"ýOgmS²ŽÖsр欟 oóËÚaêJ–â°/Ÿ„ïÖ>IüñgŸü7Ò-!ÉÐ/QœÊ•„×WVùs
‚ëý<Ÿ>‘‘KkŸÀcäãÕ `õ§
7ýghrd<£’š[
40¤‚ø0F4õ«À8°ˆ@`8æ	;àÆü‚~Ó'Ø··káœÎ×eøR$?,cï³ßþ‡C}ãxHŽüšõê^pçÆ“0£¹hDÒÂg0ã°qÃF$É
}ÈJ«‚™¶_Ú}‘÷wÞùù·‰|
㋈€h¾E@Á*‚ä¸Ù…„(|Ø
C@Í,„ŸÂ’¬—ªe¿Ñù†-4\M–ôú*¸IUü–ÛspK-‚W@í„Aäf?bXLF³ÖA]Ðo÷b›°³‡IÏX«!â5¦^«’þ÷ô!U`mÏî€Í«_D;j†â
Ø)k!LßÇÁ™À#‡¹=m÷`p¥wm¸€ ¾¡[Á‘MáH%Õд©à+tŸ¶ažkV64›½X-~ÕÒÐÃÆÄCEI*;ñ.[Å€³œ&&„€ûRæIj{>Gü$6dµ‡á)èCDŽ	ïþÓ÷ê;Z*øŽé©5Ó$(FZô'
î 뵿§Î<]1Q
Ý–W0/èz¤ùò¶qâiê¯E8f‚¶cñ&ìÓûéÏìFÁ¿ƒNyœõpžp7®¸­Z4…èŽx>ÞIéKK$cµ„´Åb¯\Òo»1oPCHéD­a弡©¤aÖÄÆ2Qcƒz!G #V+ypÔ’™Í{áÚÈl療$Üð_[+`κÜ@hT‘ýS8 ,¡­J#^£ŽƒôØëihˆj
C½Çð稷tɨO>¢d°¹¢e¶âªÐdD»¶’+­3º?\ðï¿&Šoƒ$gµÛ—›«´À¨0ßhÚ¢/¨‰®ÄíZLÆþwSÿêWb%Jû™Õ:b’jÑB$l‰G“…«às›÷EÃnS”׌/ŒÉÁ-ò»leÎ×B\M÷ݨ3²óöcž·âkòüGÑL‰
ÕReÎÎ(q̘`iâ	³µÉ¡ŽN£WhÊþ
1™¸Õ)ª[Í}¦É•]®~SÙg¨òª£Ÿ´Tø£v@.Á•ۗ,1J_Ùcì›,Oذ¨v”mod,Tgò!
¨~K–«Â»/ZžùaöÌš’(J†¢%ÁPíb!´àœ” ìëÐ5Ï^ön‡FÚwQ­É°Šš5Uê*Tøßèš½²ÞÆ Þƒ…ôs—¬]U=à¬ý^©pis€Ì0Õr4û%\´]È<À)L¡ŒiiÅ’Ý=L‚ Æ}
šwóZRTG(bk­¤ôÍ®HƒM÷ÑÏS²,òØ})-0†‹ºÞ%(«¡yC7à ]§õ2ëÀ…";ƒ^Ç~ôCÑ<ŹhäT<ã#Å
”Î/Æ9aÂïwð笆aËä‚ew¦¹’Ç•’BkÐô÷RÂgB×àÊN1®4®rŸim•«@´ººZÌ
kÂö$ûpò“k¬"€‘—’ âÜ»ÉîU
!JR£èGØ1Ð1P` ]
%©¥'&Oe’r•	–zë
_Ë!Õ™Üí4–’åxëzÃmUsƒ›ës˜Ÿ„YóeŸ2ç“Jo>†ý@0Se·!IþÕ;‹A1õåÞcÙ{ô¿Y9°TžÎ§I©zŸsH $qNVƒ²±e‚r1¬Î2-ëÅÇžO™ëªÂꔑLy÷˜Qd6É–Ay	kºZÑĤÉ=.*› ¢@lÏd5y£©?pì†ó5K«&êl.U|û¡JU+fhJº° ¬Y4e
?«3n¼Ã]YfJŒ#%*·Æ°
Ç~±¼¾lKˆo°œx{H‘{s.€Fçþßn¬l‘ø=ãÓQ‡äòݻلÝì¨îJÑûÞѪRηRA÷;Å´/ùh'¸¦Úbů–:ØEL#j/ÔŠ'Œ‹–¨lQn¼t®¹©‚…â)`u†Ó’ðQ‹k(S?¶5\§-•	Ûè*Ž5ê¼_Ãå¨u<å³gÏŠIX	âòQC¡
ßvW$#ö›Ä¡pÜa¬Ó`/>QTa_H“%h‚ ^ÒëŠJhê •¶ƒ+°Y/iXZNEûW"‡íq½ÍÑMªàM¼Ç66UËa'á~5Rà‰YÍãÈÑêA}”Ñ`–Ïä°6h\[à
…ïöWŒ¶¬r(NÏïEU¸#s›â¦'}”Á5ᱸð+Dµep~dsc¿T6w7Žúó‹n}Õ´,‚tÒ„—…¦Þ–Ý4έœj‰ÊÄäÐ+c>j|@3¿¿¡Œ9zø±àµ@µåõí¡1<­0SSU5¿T‡ªã²4Þ>ŸR¶Äœu´Û^re´A4¦bE£Å5TCbcÿ)ÊŽ¹ö{×]RÿTØr¸%Ðäo”(+Ǹú-ݯ¦»öTK¦´š;5Íwmd\YU*Ü>—*Iá“„A¼ÐmB××~¾a¾Â%&‹ãmœº¼­I™ªzÙQ.£ŽÓ%íR‘©;
ïYCæ¿‹íl‘@ÓÉä(®ÅcóÞÄg¶¾¸]›Aÿ)?™SjMgþƒ†K­øŽ‘œôüÑr|‹ÄZ1ɦ´}*s­ß÷9NbˆÌG15Ü:mh!^ ¤Yêm8Ê64•ӰgOu”ÈΗv”I&­ïJVØÍÈážëšÄpy†?ûs·úB	íÐwyÒŵj'ÌF©
%”'ÉŸâÖü›±Þ3û•Äé…Ë„zP4œÓ‚"¥+ªÌ6t5™¸\–ñ‹âÊz"Vºêƒðu*9i é>8GíLÆ|k+$¬vëNbL1æn*%R]‚FùþÜÑ
–tÀBsÒ¡=ˆó‰|ªÓÆ÷ÞµRn'›¿ÍæâkÙ"Ç>Ù
uIÀ'PX{ö,»X¬Õ
Ì@–üQ÷˜ÈÆ"9šnY3Ç6/rîøð°îGŸmaUW0ØÛ]ȘPÕPt“KºÕøIh“:_5—­@%‡©BÂÔÇû7.¦Hüš_v*ã.‰ásãHSßÙ"É){3™‚„&ª©_nâÌ¡“ù&“õÁ…Ü1ƒÈb F	´² j9¶Å9—ò,“BÆ|ž6šC|pà_!Ç[ZÃè–.XàÜœS7´K«áÚðR(<
çA}ìDK\9hxšÞ_CFš\:˜Êöt(·^kÖºXrZŽIM­ÞHÜ7¿bH‰ßž	JrµlœçÚ?l,L&ùUÖ­WÂÆ ½““k"‰2*(j*⩪Q0‹áóW2€ åï/XÃ…É>n,²±0ûYG±s…U©>§ðšì0ÕÊWçàå+|œ{ÏÕË1T9(D7[ä,g‘‰šëy«ˆÑ|©Íˆæ‚ʹ_ÏJaŸš[=>úèæÔ–=烇 øÜÎ52$Æ7” §ßÕyÌéI]T”>Óa$›Í©u®êG(¼,ëðMA{éÇL
¹åbéij¦‰Ä¬mÍf2N—|×
rsú‘‡%G(Fë±ûûgSƤ1òUJŠÙ¤ÓÆI{$Ù&üD]Xw”Ñ[éeQ*¦Û{5Àn¬ Ú'*«Ê_žsiÓŠ00I}‡ùß’Ö‘Áçöppø™'üà“N?ã…j•ÏɯLXÃj¢—ò¶ah \„¹R¾âüÛÍiíÙ×\ÇLç¤vIcînxãh'ñÂc?)0+È•uØ×óヸˀ†ãnaòm•„q'o‹oË1â_ÁF>°ƒtÐa9§€íçvqÊÛã
z©ÓË®²8¿k2ìø¹ÙOÓÜ¢#v,‚±²8Œ–ˆŽioÀXÛÁJ¡Â.0§œ
Î{[È›¼ eìñqƒ¦Èõ
ýœ³Y„$TU¾Sj˦„•ÚƒUúu¦CX¥AZAãÂm-ع¬¡¬ÒuýhõQ!–Hƒ³‚)7õR¯:gŠCÃFLTèK‰5ü"e/á<€L«ªúÎ}Ð' ³±žá?(A{Võ¦<´È8Y.gz+3C÷Fè¾”¶ÑpÉ¢æože‹}#*ì÷/8ù¯ÅÅí£€ºd›˜ñ§
Ö:£´«(OîåíÐõù³;ÿþû'	-‹¶endstream
endobj
353 0 obj
5753
endobj
357 0 obj
<>
stream
xœí\ëo·ïgÕÄ¡_zkøÖ»$÷U âØI\¤y¸
Š"Gò‘dY~÷¯ï<Éá.ï$9²Aùn—‡3¿’3÷|ÕÔíªÁÿä߃㽛÷†Õã{ÍêñÞó½–^®äŸƒãÕ­}hÐ:xROÍÔ®öíqÏv5¸ÕàCݸÕþñÞë¾êÖMÕý¸ÿèáÛ¬ÇÐ×n„Nû‡Ðð³jÖ_Vm=Mc˜ÖŸVnýmµqë}|~§Úè‹{ÕÆû¶nšaÝíºÚÃïüúV¨Û¿ªMï[ßMÝ>Ãn¾žÆGú¼røf챑Œ‚mŸo óuÓvÜè늕©Ÿ&dÊ!;ÈŒëbÛBãÆ¾£Qà[zlè½:š{¤îG$®ï¿^š¦s-±!ãˆ4°ÖA¿ap,É\öåÆ7õÐNKôNç(àÿ/€Ê4‘Ø‚œ^WÞч3 ¼~‡mh¢ðìÈû¼BÇ8a`©]ŸÀ'˜ÝSxƒ[ät\¿¬üú	6|ˆ¯Ó³@äåÀ¼{ƒ’FЈé>!b@Óõ°>ŒËŒÓñõºêpõúžGîp
/ÒŠÝ@R@e
‘͆ÐŽ–ñjzŸÂÓ‰H¢Àµ
ÅíÆ®v¡UMŇBŸU~`æi~/f}­£"±ÇÀøIÔMò.÷4u­Svååc$
êhº*O+Õ ºÓJ‰ªØõâþ°hªÞ‰(2ÕL@'€4ôõ“øz‰M@àM3Lœ¢6*†
¨y×££4>q€}ILè©HDÙàuO†ú?vôñPñׂ@Oô
Ùñò—•û¨ˆrta©÷+]‚º"Ûi§8ÿjoÿúlõ¢
«÷Ö°Àú[œ©¬ü#V
þàdI Lû'üúÿœåMpÖüö 6~†_”*	þ­àoɶۦ­‡^9ÈgJª‡š“”dj'9´á
icl@ÌÆO#­õqåP/ú¤ûÒjãІ"HX}ÚªÔ¦€jñ }4V§šOö¡ƒˆmfÚ)zGýZ;έäMÎ'*‰ôAÅZGZF5é@(ˆàÂ¥@†“Ýä–‡76m¼yÞ¨•‘ùPVïÄ|ºid¢(Jkâž(4u°xÒ9™=-‹Â6˜¿$A“B™‰>Ъ#ÈwiÞ‡l˜ 4›!,ǵ´Àž‚w
,žÌVÈ,ñáýû4Ñ£Ȭ”VõW ¶þK²øÙÊÿThFž²«òÁ!™æÒÌŽšC<%Gê¦Á žp~8yb.RDñýeéè7Ö U-E]žŒ¼\QIÆŽ‡<æí
H£»A(?O5±Ãç•*ªÆ)~äÚ%‚ȱYGÑÆú¯t¬(ä_%Üý³ÈÖõSRp^ŸÀPc8‚k»Œ/Y@8Ù´qXÉçª&EX¹D€‰3ošiæ®Mtû Ê|n-)^z–ú	²‘ rdÃÈšæRËŒ%º+p
D"*ÆCv¦=ˆC_Q'Hõ8lû!†r?n‰Í|Sò7—âV?æMÕ|"¿Ë è2ÎàaÑ6sÄÛ\wîý‚Eßmq´¼8)‰½±3ÈØ¥…×w/k1¶ÈÃCyHðC©ë~˜Æ×ø„1'–©JL
˗ãÚo
2˜cLðªcþ-ÿÜþö¥s‹ÂÍî¾bÚ¾1Ûú»¯1œïï~†4[¿ÁIŸl5 ßÓÖë¤4‰¤æGÙR%¿(ù„¾‡¥öå9ßŇÙ¯à.ÎÈyóÌwæ %¤U§¶Í³)A›j¿—ÓÏŸÞÅ6|zSù¾;¾“Ì!l|1ÓÆËmhCÌÒ]/©ËY6÷¥[7ÓÛ+d¢¨*	^—Ø=²ì\ôˆâ*€vq0Ü›÷\ÈnðR-€f„¦nƦåN®*§Åtõd2s0
îðz…îñ8'饘~z;6q6jÌØ'X—i¾¯êéJFo}?‘~³é‚ò	ïÂk¼µj'úØ…˜–1L|Óó\âý gxäéi‹´¹¡9?ݦjaœ¥htÓ–§3„xsÞ˜Íù»˜É8»{ðr¯¿ºË=H­±M‚HÒÍcžP“ZàªõÈÀP¼»Ž
åÚzª}?O\[äÂ¬úr|á*>¶ñné.»éƒÕúyy3]ºBvë¿"
Ÿ_?œñ³Íá)]#cß)èºhNrö4~™7“g÷t´¸sÕé™M¾Ð”¡šÆäêè]u£8¹O7Õ6;J_Ê:Æ9·fÓÇ&=ËÈ«’§ãXÎÜÖôÆ8¯A3©Òpuæ´)«C2ÅÜk©&”ïYñ&4îžDE²3µ"ÀpÒ
ªôÏ2_B–øÅÉ)ébͲì:\pi÷}Ä0Õ½”‡™g`vï\ ‘b¶Æø³äDãªñ¢ö1'Xó:7Kõñ3K£nE2d`ø¿Ž>òn¬Ã¾£Í|Êj;YüË”†ýÇ$xI¡„ä¹ä9¦Ýú;~¨Ãõ,s7µÖ¥DpS¤xƒ¯Õ%W®»{›nëmâ\D!Mã•<­ø\ó0ÿÖê4óD
áxçÈÁé…é'žø˜.¨ézË$kÉ|¯,z‘û»– l–Þ°•Ü–làvØž&Î0Õ›”LbdÏs˜clPÆbaǺJúxž¾Ðº9ÉX³±–YìòxóKçAdvÁÐ2É£üèaŠñÝaR½Z‘K¦”ÛÅè;6#gR;²qÕøäšœÒCö舥1*7ùª/+Ÿ–GIÒgJ©æÆ1©¬4žm(1’¸)fpbV:G*—pÖ“´y27g	OÛ%„/„A§ªïous$Þ–/U¥èŒ§v‹:,ì€øÆV|hêûk.KýE¢(ÌÝ,=PC¢f8d¶f‘àaÚ©:‘iž‹YYÞ»)#­@`Å8o3Hiò“a[Ó’§^*‚yÐ(®€ƒ"…¿‡2ÅYwÄù‚kHuAúZ ¹¬Vj‡‡þR°2ßæö9>ù~k†¿`¢¦'Æz7±%a¨›ú·¯#ïxÓòÔvbùÀ®ÛF“K¬jŽy—¥©º(èɬëD§1 ×sÂù³j~ÁæEéƒî…„sl&›?ï¶m‡íÔs1H&ÚP´nSpƒ-
å—Òâ
ä< íð¼lƒ¬ÉjŸ„Â4'¼–vñ åSÞÑÙƒMÜ]îÇgwS—V£¿hd‡³ª®.„4Á~Ôs[³²Zˆ€¦Ýúm[Ö(-)Ò‚è¸%™Ö‘Wév&Óž]Vø¡E"›Y±ÁЪ8–„QÍ%Z®3’`ŽIöµT¿ØxoG`ÇÅ7\p—»mhÔFv°¦ÐÉxF	DuÌÅ£Ë{WçxÌRyž¼=ÉÐÝÔgG&‚v߈ u:6„Þ® 	'(ÂáXr¬½³¥js.ž/ƒAZ…ü–rvœ–•ZZ Ù9NJ/ƒ”ƽÖ‰c´)2P9;Öã‰N†Å\Mñ«†“näóü.© ›Ã
¤T³á†¼VžpøR'Z$¡Qp1øQ"8•aXœ´!¨#K_·³ô2å4l-¸är½´’BzhÍìCäaVív^g*ßèÊŒ2õ¿çä_!Q
ãÞ uƒ•…´f³8Ð!+|ʧ. .‚cŽ\d9-ƾ¤óR¹ùyŽžêáìsEÓs<¯vid‡Ÿ I¿dÛJÙÔd×b¬‹M@Î
‹5F!(ýÙ!ÜmvÝJ…¡!¡‹‡S±šOg¿ѵ©Ó<—cFê!§.­˜KjxRÀƒX¤Û¸Ë‚ż¯³°á•:s=ÈŽt›i±¬Ø‹žg˜Ÿ´”fËk~mªÉgVn*³StTïçGgÙQòA6èú×\+±?ÅŸÁ[ÁçZ,*ŸÒÕ‹½±ÐÅVwö÷¾Û{¾òžB±f*2®üÔ{¼ÃnDXðïÁñÞ­»{7ïþsõòìÕý›ÿ^µ{7¿Ä?·¾ýþ¹{{õ§½;wWß]òWvÑÚÀ€½Áö™ôí >øL‡™¢ÙLfG‚ÆñeÚâŸ=n]6Ì!¬pü0$Íœ]é˜<ù‹tÝëÍ/™#áÇâÌùA
bpÐóFá6…¢õræG~ÒÒ	zÈm&ø¤èXûåQSág"ÌU¦l벂pã)cPg#;9ù"9ýy	ü™«6Ûj•4ƒÙ©*‘¯6»Ð&öë¿m«Û킈¾Ac©f±p*c]qÙLÛõô{ôFS"mfõcýJ»Éhßíý/C¢endstream
endobj
358 0 obj
4529
endobj
362 0 obj
<>
stream
xœí\éo\·ïgÕÄ¢_²kxŸ¯w @Ñ:±i[E‘ÆA*K²ltµ’eÉGÿúÎÁ!‡ïd;qж0,­xg~œ‡ûrQWfQã¿øûàdçî£vqüj§^ï¼Ü1T¹ˆ¿N÷ö 3PRõuo{Ïv¸§Y´vÑ:_Õv±w²óÃ2¬Â²ZÙeK¿×m×W}×,ÿEWëfùùjí—WkèÒ÷ÎÐG[§6_Ãÿ/ È5X½¼·¢Æ\ŽõV][ÕÆ»å÷ت¯êº]î­:#lb _ç{ì	uÆ7˯°ÿ}œÑb#Âa#×-¿AZþšºìEÒx6è!H8fí{>«ùàÔ+öaù
,Û¬7lœn¸ö5,Ê.Ö®®ZÓ÷ÜhpË7ø£Â'0kh,‘kðÇþ؇¸"³Ü¬ÖÁ0[_`ÍHFJáï‹Ôè(OžK!’j\”àW;{·Xþ}–¦/ñï#üñ¶¤é0UÅ/RÅIž²Xï;”£jùñË@ÚwKÚ3í»BÓ~¤i~>ÚMþ45ÚŸ¢îE.ܦÂ㸸º[ž¥ÂÓÜòêË:îÏ®ã~Z¯HÜ&l5#2'eðL~äÒCÝ̲¿øß\öƒÙe?(W—Q{.©wËß3
—©þUžîHB+Zýn*|“[VŦ½Œê5/áY,„Xr<µØ¢û¸ð`Šá[]­–áûþðªþ´à*íãžY2ªÏ$_äÂ;È‘þ°Z­lŠ^øÑƒ½8Ê<¹Ÿ”ì“¶‡©tÊh¬-TÚÚ-Ö6TÞõƒ7hž³µ15NèQÎH¬¢pº¶Z"­Áu;êD­Zã`ýa)¶±Ø
K"jk`°‹•ÆØFS⇘zŠÖÄà´]œ
$ÑuÉí4)H*ÖôL¬)pÙ⇾…É
¶k—ïVÎÒTÈÀÎ,_¯Úö†)ƒñ†Z¨1Aж¤sÑà4Zä»íëÊ‹mFº[ô+º	b›šVqÂqÎth[Kž¬,â«mˆ^ÍÇÞÊvet1\QM]ÀÓy
C“¿BÔGçä{wD“ðë¼ÏòÌÇP‰¿/V
—¸úÆÀÖ¼Òu²ä¸`Í}K|'³»‚Ï´œëÈæ-–¡I·ž¶~tÖ‡sÖ¸#‡6.³ Šinõ¤½Œ#Åu;çH±$¢ó’³òr躗ÊN3e#™:ËZñ9Ø›ž”0¡ÎI˜éP wÑÝD™†+èïQår0£ÜŸg`áøÆái‘å­˜
ïkZtç“8È¥5´¼¿2X°Ù)V¦ÍôÙ ZÌÚ´€#ZÐÞXMùµ ÊHƒE6Y]©TAÄ~$¤Ô	Œï	DEë©…?c¸kë± f‘©ôJt¨`Pý 7²Ög÷=2‚ˆ®i²ËG‚Á²ÐD_Áf„ ±¸(0Œ‡b“´Q<=û[Yè…!ªÐaC”¶Æ“'dV³É-Ô%IùŸ0ÚòwH3ŸnHøLˆ†žf<‰9i¨Ù&Ùt6H’͉òàÄoµÆ¡MPþÌÔË	Å‚¼(½Rë$Í%
GdÖá`Ñ4à¬óY€¸3
èm“álD³å3úZ–ZÚCŠ=ì*èOòyœÕRHà³h2C Ð …216üm•X °eÑñàI×xz+¸y‡ý=Ÿ¼¾¤2ÄÝë£ÇuÊÛ`BmÉ老ò¶ g®ÜšÖ³«?Ôldïmë†.\¹¿ÂÆ‹¹m¾°²já¤x³àÞ"#@(‚A®=ËJòÖÊHæŽÌvŽâ×IõyœU¥Vë[Ûåσ•¨9±q%jvW½a–¦Yûìû¼HXƒü¬Áa„ÌÇ€•8QÇÈïØ?à´×=µ…9]útƒrNôDÏž,X?%bíöYÏÀŒ‹Sñ{çâv†þ–´TšBpýÕ´¤Zp-’7^PaâY@–¼1Ü~ì×Éjž+í'ñ
O/Ú.KsDãN‹E­;eŸ]a0íhe·ŽG]“éRèÖF?Ÿ”åW:ŠÙQšº³Ñì„=&_˜3˜	ü"öÆ«h…"ˆ‡îY*«Ü³Ãä{
¢Šôç»LlŽfäðÁSø¯tÊ@¦…‡Œ¶*b¯v³G–—6Fs¥.JqãC;6Å7^_çúL»
Ùª¶ÏHÚ‚Ÿéž‘	8Û®‚S<ÿÛÊ%M#Ñ\§C?›?-AÉ»Åàq•#–c7*äòZ¯c·.Kþù€Ê|^S›H* Âòvª>+ûÑšîĆEü©¡	‡§"HW^ô;1ÔÔ…kgÏñ+jÚLuʱ¹RCSü©kñ¢"Ö“ë¿N…ráõ-EØeÈMEÍ%NõªXTn@fΡI_Ÿæ>o
ò…Q_åÒ’*éV.àÚ¶Îü@òÇ‘¼¾“Ò‰T'æ Rß|ƒL¦˜,sz\T爴`>Ë}:TýjÀQöǾHõ{¹þûTøm.¼/QLOÛê
è©Èæë©-²Ñ{ó‘DìbË;|™Wð@6ÅuÛïv1”Rê"õwºt„êËI¤ÜÉèÅhPM@×kÆ`ÄÁö'!z9ê†m8ö¼\3ñ),Dú2!­F‹.KOVÃÕi¾jП4©åÈ|¤­õóñóñßd>hÍ¥‡ôZ_Æp|¬ÎΘ~>Õé<_£ÝÜXm®¥n\ý®Ø]“R&f7d©Ïƒ"ˆ¶é(UX–)Å^Z”í¯lMàDméÌaðîñ“X”W‘ó°2!¯'ÄõŸ|™¼¹.x¢UxZ7>o˜Ã©­uqMaÞ…ÙšP!7'äºufŽ(”žL:[sz÷´IæäÓƒóbyÓ6lh@G|üâ\v%†(+¸|¤¢¿}”²Ò}=¬â¬ vüýH"µ×N“TXŒ±ÊŸUôÙs¿éÉa¬óQÆÛb‚IU?rs6.”øë©ý»º…1U‚¥Ø“k^¨óUDgÀ踩ëºÁœÍºê\ÛÂí¸Ø¶[c¡sau_ß7´Õ^[­8Pòxe«¦¥ÐžcZïA8Pgû&6o1Ö¦‚ê33`ÈÆw=`Óœ§ŠDjÛU­Gû㪾u=î˜8Z£j¡Óçv­Wí6yL5é¥ôæê`ŒÝÔ^H­£é@$â5¬³àCn‘†U#¨E1Í΄ȉΣMåÁa*Ìh¶’¦©/ùRˆt9˜wT
ñâ(蛫‹2ÞêNÖVµ
#‚g	•ÁèáÅ]G·4æLÆNÏ\lã½"ïLnÝð†¯OÕÍZ+]´äËËc¯!*%ô[Ü‹	’&Ô‚x’_·•{xéŽ÷!´#‰—ñ_(‘ë@ˆÆx‹×$
 îV¾B(nW«Zî6…ÔâÖ¨¸õÔÍ|axß
â£\ªÉ{8uç&·‚±
‰W]¿ª”‘HtÊan•®¼í¦|Ç·ä<èUÕ\ãV”jpSr®D OWÆ9]3w[Jæ}ºÒ‘Tøµ›˜÷0´¼NÄ<¥âºåôTßÿ«ì©§õ>$ŸöHd*Îþ¦ØÁê>„ì
°ªí{u«J*ÇzJÂ_ž˜ðóI\hÍã®öŦ®Ò½}a1¾óxcŠ„Zy. ¢Ô…]êÏÞTdÂ(hä§474ãœd^f•ƒê¬gÌ!°púš/…ä¶>aí¦$9"µ%ܥĒdÓñ@(s¤†e15dº	Z{Ï)¶
ÞÉ„C™úD4(¶J™T¨ó^’Y§51'‚ÔÅEl©˜HãüH$“FØbõü€ªiÀd49¨üzK‰+ã<‘\’¡&¹:nñÚ4toˆÃW€µ„WäDyˆÔIB0bÊœ(2eQÅ)±(ãjÖUrY×e†nä¤ÜøšQBÚÛ
PÒ1u
LÚ19oVV%	ò›–”ÖKƒÄ¢()gµH-]´‚«/!fäÇüiI…èØévPÒp»NåáÊÈq³àx«}La)W#R•¤åøç\^@Ï*G¦
Y0:­rSÚ"+—·K'Ö̘Ýæ‰TV5a†ÔˆÌ¡RÍýƒŸ!Y–£Üÿ‹ÏÕä->²ïFÃ))‚ÕÍ×qϤða,§çXZ´Î&PÒ„ŸAÛ†
çD’øY¡†RžççöÃP•èt5pyY‡¯1I3lÃz^3åÏ€EºP
5Ôn¼U\L^aü³!m+g’!}Ïý ÜÍŠlˆPZ‡Sé†Ù’” `t:æ9~„Œ8~SÈD‚b*\iS'8îóÛ³µ¬¹Ôl¡ˆ'Ls$(ÙŒèÍt–[ä‚묧˜"¹0ä\BNMLhIÚÈcæâܤ¥|$ÍÏ›ðû–FK4ÞæýUʤļ¾?r‚QoðôáÇÉfè†õ5¹aE‘Ú¥K7Q©(Ÿ'gñ*o
Yób58+p>fq1#®JÙš3jyãnâ&~&)q¼úR1½g–RÌN¢*´pñ%KÇ­ìü
d¥òÚÞª„¾$q°ô¸èUÇ0WU?Ä@:Ê?Ê:þºç
çì|Á’JÞ”Q†¹ÕŠÍOE|çØ@ëI±Åh{×ÒÓ”" ­À…ó&éµÂc“§S(šQY2IzÓ¯0ÀUvi^ËóвpÀ.&âëtD9+ž
jòBd§Iº

W*)Ðn…‚BsÓ‰RSó“I§á)¥røŒd?žT:CuðF»l‰òmÖrJ°]M冋k¬Š¤]ÉɃ›sÚÞãÁ—£ ªÅý,ÆÝvúàÿ¸ó !µy¿ì6+7X40 z9C>'&ÍNFðO?`\}m$ò!BîãœÑžT7W%¯×¿Ô¿63ÊÂ[>O¸&$'eš‰.€˜'š	*©·‡’⟑†Šn«Mnuà…ѯPž—ðJ'pËv(¨½éH[G•æëžB€O΋(Í1ë_sêt©½òÞ™x¸Qžvt¤5Ę LØîß³êçF¬Ò"ÆçâvžC5*˜1JuêÊ7)y+ù;Ô·< Û]cI?ço’PꞎLª>—vìÍæ!UFròÔCÄ<"ô5äÕåG„” |oç»—ç(¡º^ºø™osLÀÞá7yÜ{¸s÷á_ç—G;wÿ¶0;w¿Ä÷¾ý~=übñ›ûßÍ~ËÇ@3Äoùpm[‹ÓT¶áoú@0;=}<¼ŠbП„b_{ Ø$c:VIoKÝÀ[Òï²§?¼pHGZ?ëÓY»ü°7ÂŽ¾.Ť§ùv"–éÉ\ò¤®ÙPÉÕ¯$ÆÏo´ÑøˆCX7ß_s¹ð`|:| @¹ðêÍß{ç¥äZê—óRÒM:7~³z¿¼”\XæäáæòR>A–£©9úù!9W*óãm*<›ºkW)“_­³ŽóD™o/¦Æ,/º¯áð8ÏàætlgF—*—£L§Sb|CÎ2d6.FÝñ@vÛ„ÂcMpì2Ñ9㼆H:~ÅÇíkÙ*…?]-•É\¢É¯!DâXûDssŽ/§xCú˜ŒÎw;ÿsªîlendstream
endobj
363 0 obj
4573
endobj
367 0 obj
<>
stream
xœí\[oÝÆîóÄúCCç˜Ü]’K-P§6¢"÷*èCRŠdKBu‹dÙq}wn»³äòèÈ‘>d‰ÜËìÌìÌ7æ—e½i–5üÇÿ],ž}ß/OnõòdñË¢Á—Kþçèbùü hLx²ê¡Y¼^ÐÌfÙ›eoݦ6˃‹Å«®jW¦jÿuð÷0Ã6ÙŒ¾Û&‡ŸWk·ú¢j6ÃàݰúkeVßVk³:€ç/ªµ¼ø¾Z[Ûlêº_µaíMµî{ÞÙÕóÊá´Të.¼7fµŸ¦}Óìfð=íô²2ðÆw0ˆw‰zÎ7aޱ›ºiiÐ×«Ý0QÈbLVlš0¸¶Ûâ.á¯Æu0ÐZÖ±a¸…Õ­‡Ååý–ºnMƒdðø#nHkü¾7ÄIã4'×Ìʵ­7}3ÄQSY<TX¨âa¾¿¬ìê,ls	‡?†·«7áÙ)üý
(ï׺Õøû&±º‚ÞÀÈyƒ¯*Û‡q­Y½cN‰¼®ž’8šÚã>G,8Ø^XÛâÀÛÄôÃ
÷‡
NPïžMžYgÓ¸1±ñ@×ðã~ÁpôðöçðëÔ²×ƇS„Å®ÂÆça¬D\&òàѯZÏËTeêWØûªΛ!ˆ£F=$ÎfÂ3C»±f¹6ݦ³ƒ§Ñgaw$o›éx
ŸñCäŸÿßðgz‹ó@–£4øFæÒ*8Ÿ3øR€äz¼E«gaSã"4ÿuV|x¾‹‘áwPÎu¸&-h ô§UNû›8û6q?‚ŒÛz@µ{__çóð,{A µñ['5"õðp>4(OãÃWiä¯ñáuéŒ{LQ˜þ—ðk¸ ©óø^1õ2><‘c8µçMyU`¡š~—^ŒQr¾L£”=ÕüUïc
OÕŽ<ÍöS•	xb–‚°(ñLµíNv	ÍÞÛª¥Ë¯1›¼ìžx-—Õ×[.ª¡t9iüwÓÅ?ÃtÙ	¤çmÁ°‘åñ`dZœúדÍ9¤5¢M‚Å~2ĨWÕ†;Î묯çŒW_ó6­ØjࢭýÆG'
$ñ×uôø†£ZïI|Èt²ÿƒöx`Gf%ó	 IW(ðÌŸQûžÆ!0­åëI°ÞEÒ§´å^…Þ-Ä~ÓÌÄQ` ìu]™ŽÄñDØãÅËüU+œ=zp·Ü+ºààúï‘hÜ¿´k*"V;Åëd”¼¼A3õD«ÀŸÂ†
°…|!hG÷ó›·™S»Èv¥xÔŒ„‡jpŽ-Jaëb­Ózö‚_Ã!ÞW¸œG{ëj‡;•u@–¼dÖzW¨ÉLWY¶—irSF{ щP‰Z±<(ï³ÊÄK^“,Q±èÆÙ%%pÈ‘¿I4µÃi—GòÔ„IQÃᙈ7
 Ær`AçÔÑäOÙÀÐÜlð?É•vL^4†#•¡+<Ã	¬æpÏ’dn°a.` žízvPâºý™¥h›­©ÉBhccßͬQÁUݽF%œ(>.¨cNHÚé±HÚªÏd°øü¹É‚€Àà†¨äK†ñ*(AgÁ¶h6²%WÆÐÿHákºëks(Â|A¡Tøã>±GÏën*S±Á{{ðð¿ÅÞ2ÌK€Ï"‚K`U¡<°Óxû`šC›Ño¬·ÕŽhkX{Àš8’è‹ø5BW7x¼0iÌY˦®82¡P"C¿«ÛESXﺴs†w@ÙÄû ”ÝÔ8&”µv=žw[iº<7„Ë*6kØë܆ûQ¯·Éò›àv½˜š
žã.ÏðH£ß:…©5%)‚~ѯevE–!¹‘%1¾Éck0§Ò»:Ñ¿r¢'ÈȺväú!p+]1â[Vø¬”a˜
MQ±åŧ
“ò!j©ËS˜æ1¦ŠÚǪtµ€'1zPµ«%ýTå#X‡‚qœzVíÜ@ùjbjvCMí€ðÆe;œ
ì&П×^:I€3&t±þÙsÁp:ðÒ¨»œ"\1,|»±ÇÏ=6J‡Z¿êØZjÓ\ÀœßB¤ ÑA¼Ñê#½ÎtNvH.ÿ¨–žƒ©ûN¯µ1^Tˆ€oBŠwÕ¥&ˆo)a$hÜ&b„½si¸A–b©˜k‚íõ¤+Z˜Ä­ÿ‘8RA[MlÜ`Ø~ÌcCH2•¹µ3Å5óA¤qæN\‘)HšAŸßéRB'¯‚´TÒÈa)sÄèÒŠ
æpUÇkÁø>Úš{œµ­ù|yÎ[”h—Çp¸Õ2C$¤2—8\²
úŠðxQTçbÄVVÔ¾¨¨ÊƒtÒ$ZjGZù u%µëêÔvIhšÏ£ufOÒªãêTxFåûÈÙAÔI2©RåÙ¤'‘æÌîã`Ö2ÈÞ@걡N2®‘IE7²a~ÖdF©P¦²V<²L|´Ü(±&9×ÿ#ïëR¼_2BðÖ8­,ÎÅ«=Yà%q¬KÉ\Ä>5Ý¡ÖðÈq 8—‚ƒ€\$Yfç“G2Tßg©/V"š x€™šX,ææ×ì«CŸmÙTÙ`,;—œ#%áFAo`žŸ…xš<‘îÖsšÛæ+å9Ërâ"ßÎèp^¼GÊóðl‡¤ã?rvez2ñ1Ç,7™®*šYOð_´'%-3# Å¦–­pö²×Y>'Ë‘œ×“þž’ê/ÇA1bö=Hù+j§
ßÅÊÙët²™˜vÓt1ãx§Í†kÈ߈¿ÄÆô6®n¢©IÅ]טFÌRîçF·ILxˆ3†y˜×Êû:N*N[óArƒr$µp¹5„™cµXð`±cñ iRÇÖ-ŒàB2aˆ—3˜õ»Úx6Scr(s“M§±Dj49b`{[UÈ,_"¹Žåqr7‡Ò.$øÛîsH‡¬)ÝÆv*’²Ü«¤î·®k,ÐŒ“ᨶVé²VY!ƒ_Kƒ†o‹
\Øf’fǹ½ÒZ5ÎXæSnI•qÕâ!á•Ò´–˜£>¿,?ÛTL¨©kΩã¤+
YÈäIÛb²zëLQ3Û§ÑdJ>¤¾/ªÅºÔI–é-–7F˜)j,ܽÖg”Ó›’rb¥¦ÛÉa• ŽjÕN°QØØg•ÚÆŠ½kó¦q38«ÒAŽ'싲BIC;üœ5IÖ~S.èä²rǘʣ“–ªx‚|Æ´õjÒ«&µ6*Ý£[Ó.Z5ÙàtqÃ}²VÁ‚ûTIK7ÿuÊÚ\QÛ´±?Æ¥¾;«ç0ÌëÛÄïv¤ypDðw»šE2U|ÄÜãQmV;at´%Œä€ N.>jÐH¥R0äP€Hɸ\‚å(ëö¦ÐYbÛ™ ÉìëwÉ™ûdbMA½%ÛaUi¤N_#%OT,Ãc>¤A3m…6eHÏSØ‹Óù`,¤Ç¤ÔÓ,Ú‡›„ê5×s­L–ïù˜[¬”Ù…QOd
Ù9·TZ`'3Ç™®ìvt?rÿCŸí“þ‰†´)÷ž «
üeœ ›ÐxÇF`­5‚º\}^ÿ1éùghº  ê	žNŒà¤ÕßìEk•b±«êž(H¨‘ƒËìj]ªr^€{XâWù³®€¾,t£ƒ¯u–9¢t0H.uñ+»¦JÛÓ“˜Œa‚§Be
ËÍÃ!_UNGj]×vm§b¨J’=J1ô.þ™Ê.o$FE½ð=Z¿m}®©ÔW,ÍWC£Ì>eŸë'ûDë1j…øÓT{_ÑVSUU%xÛYjå¨c.EÞ]\ö"(Åè¼°ŠÆ§5ã¶ÔâÓ¨ÙQxÄ)ÒyÃGÛÏ´…4}n=~X×ÔØRñÁŸ·m« ç?~ˆå
üµXïsáDZþñ“Ûn§‚ßA–n„ØŒ‰—ô¯îþÍú~%ËØ‘Ð_Çü4w“¢Ô5)[YÊMŒbKeøÄØLv-Ç;IÉ!ç7Á[’}Íò[ÉYÆï˜"&§?ϘŮ¼=Ž*[Uu‰¡³¸{ƱXðN¾è
óŒëŒÃ¤S<^P’ÍYÞ»•o¨S|cöoÜŽÉ3aqþ]”4^:õ‰›*7H^\§.˪
œá'î±O•Ê&ãHO¤¥«> ¨SkX½¾ŽÄ–2'wÙ“oôÓ7¬žÀ·ú8?ë`”$÷~2½'nÀtGÙžQþû™·|4—TÂ-ÊߤÙôyÞ˜ÒØqÛ1ã,Æøóÿ[‚‡´#ÇóÃG)9ªÊ•yhÇñAëÑ:Õt·UösHb÷qWɧ™º/O9Û“Ýþ×;#ÐÑ7]ç~¢ýðïPõw¨ú
UE™
ÐôRsoª9%•׺Õ,îÞi™D¯.éY‰¤Û’>ÜèRÙ\q[: ?„¤ó¢`?¬ûÄ…üåâàéãøab<ŸŠÉ¤+?²‡wñ-ƱÁý»Åÿ:Ï©endstream
endobj
368 0 obj
4354
endobj
372 0 obj
<>
stream
xœí\é\EßÏ#þˆŸúEé—W×;Vb%Y‘U KÊ™DdŽLgÈñׯr•ëuuχ„P’îzõ\.ÛeÿìróbѵfÑáñßÃÓ½;_‹“õ^·8Ù{±gèá"þsxº¸»œ‘vê&³Ø²ÇošÅ`ƒómgû§{ß/C–mc—ý»Æ©Æ~ù!}Õ¬úåGÍÊ/ï7+xešœ¡¶Ks>ƒ?ÃëññònC“yŸÙŒCÛï–ßᬩíºa¹ßŒ(œbà½ÑOø&<3¾_>À÷ïáŠ'	‡“ܸ|ˆ¼|^Ù¬ñjð†<@Ƙµ?ìÿä`¬–ƒÀТØ?‚í÷°mמh½ž¸Š3W®k3MüÂиUÚ©™F²÷«Ÿ›à—açÀÞ
¿¼lÜòv7"~}ŠÏplìHŠ'0íYƒœ…q¿<ƒv<¿¾†­./ð¥Ëfhhw¯>"‘s vÆëu†Y8ÃWp9d*À*Á0·8Œ_GG€9о×áSØ#®™"¢kÜ·^_×V…Å@Kdô&îÇlÇ
ŠØu¶5a‘"U"ñ&2—¸ñ~ÊCÎù(ba,²ÏjäS‹Æ5ßø,…ÔóFæ¨Ýò(±ÅðJlÊc)
ö¤‘H²f+ÀH¢L—ÿ“_›Ž£Ê¹¼Dï:MÁØòL‚—IÙh¼èðÐC±ùö£r]|&<¶Šh<ñ›
9yÎä•§ Óh`Çv›wGO˜Dq$‡'§uDB““Sä<{Øè’\)p -ßÌ:zÜR—h~¢™£¶Ã¥
ãAÞqá%Îû1ØøÝ‘)u0ù6~Åin˜Xq.ÐÜ3±'¢7ìì´Î:ƒ@Üú{
”¨€¾ÕÐ *P|­¸3€¶×zW`;á`€ƒÚQ¨¬è }3ÑP$üä%þµNõÇ4v,øëiìušŒá“,u$óXÞ\—àIO²È_ªørʺ,|FxZúz8ò«9ûÉÝêÏ#¿¡cK¸•_”ï]â×Ûq"˜ßazòT‹šÎ$=‘¼Ñvh
T=Kƒg…ˆDGí<®‘?ʃ™Òi&ÿ¯¬ŒëVºU#š·üòšÁ7ù£Ú³’	|càXŸçÑóüñŒÑ‹wmÊ`N
9ç‰sú€$4QµêiÁ@èL‘,*ÄD¡ë«=Ϋ½./×Åjq.cÄ:~æ&É<ÏÓÑÄÝÚŽÜ­4ø¸“ÙéCí!F”Ñ 5Y•8ÄÃ:øÖ˜iù	Fa§I¨ßkÀΣû~‰Ï{?LþlMG9¨më-ŠbÉààð|0j7Š~Á d[a–_âJÆf(–Jb‰œ Þ ä(ÕùŽ#áóÈ}-߇8ïûööo}Ïuˆ”ÃÛ@öö„í–£Ðs
Pp$^±ü­ÎÀù0Jöt¦‡Á=Åu	ž=Š)fJo8N¢3+Ñ”e®b(P
I=ÑVÝÓ9³Í~¥övOµƒM<ækõl\çß”x
ûOFÔ°#9‰!4žB<Æ žý¶e\H)GÉpFŒ¡^&Ð%%¢ šÃDET›sÅÓÂÆAÃÊc˜%—á"åÔHÁŸõÒ>Î\ Yà2XdUÇzÒyžŠ /!À¤4]‡6T…FÞ˜GãL„§š„4eªb,פÊ*ÄãÿUM	­–âªÍð7r‡†
˜&v/Öå¸9Op*\¦B™ÊgR-„k};ú
†ì3jœUã+
4š•©ˆ*ÓuÆqHéußÅ£¯sl}jlÔ2ï¹8JèúPØ‘óðÜú%]Å+„¥”…«Ž¤•LÖN Æô)Ðj9>}Q´£aKŽ4ðû:ºˆy…†Þ6ž2šädçc4(]eÁ•Ñ À&F”¢ëÙ‡°Äe‘,íqL‡r`0¶¥<ÈlX5¨Üžs|n*+à ËÇ+-ýLjÆHïRð³.%„gRr©ä†e!€‚?7Jì*Ë~“APqHqÃÛIh¼íä ‹ã<çµ·T—µµ9®F[ k»â¬
€ÿUæ'«â%EÇÁN’Vo¸4½µèWåˆ}€kÄIJßÞä-Wí|ôZ…ÌÌ6#aü»‡YiôeC
¬•àk¼©2~è#&¾§("wÊ+Ùåb`*ìáLUì Ý_S˜ä¾¶Õ_ÌÉÓÊNh0ƒ%^HôDâ½e¢/¤7ðØ2΂ƒÄWN¸ÌO±<<ÙMoåe|°•YòÛŸã"_ªò°ºiú7[¾MVô®ýò}XH®Â>m¤`„·Cð1Ö5\/ññvϵq.0Š–Ëôç}¾ÂZ	'¥ê’{$ºhyÕX4›>dĆ·2ä9}ÑDžQÄbIrýD²AYñÓJÄC7»«ÊzH€$=;"0Lê—r`º=›^/Zü˜ëW!àiW3ƒÊmYªt|„’
`õjtRg‚¼É§T»ÀÄýÖ°àÂD'^›ºÀÊsG,&Þ¯ò}‘2~7p],…‚ê%Tá²H’Œ	k|÷O¼Ï2ôÔË#œ„\Å+/8S!Gõ-»g˜}¿ÆËàÿ¡”nç죸*Œ•Âý†ŒE½,!Â@t®¢—wô”àSOùÙf͑ꫣB6QÊR}Tá‡"#½ˆâA½§œ¨,~œ&BXgè§p3YíÜåÆœÜ‰[Ó‹Ñôâù'ÿªHÇT´R…p¥²>]»¿RïAZ’ï/mªÉÄ$cë’?ï”ïÝãŒíüªBMF—öí–¹)ÞØ°9ìȨ€ãIÆsW/+¼íçwêðB_ñû¶ž½r¶áºtq¨Í¶éZŽÙ4¿‘~ëvƒR¬m%OGØsÀ¸²‰ º6tÝXâ–„Çm·ÚT`ŽÊsÓTCÎt7&S…‰¸ñéÚ,"pOa¡8‚³B@¯cC­RJíjàSÔüi’âýlrùö“]°|ûT¨P3H3Sa¿vÓ×»|í™\ä8öMmcia§ÁN‘oLi忯Ðç’Û3)vÛŽS[»F§ýs\5íåSýœµ/‡£ö7ãËÅluûË;MJ±[Âf qcO®q'bÙlŸcˆ,–¾aVd.”KÝ»ó“„aº’eÍnkb¤ŠaþÑ£&êóýì–˜ÈÕÝÜH}†š8aâ¬æHòOb¬(Ôw\%+íB’	½F›{/
wW<º²¸'£®D^WðxŠjër;µÍRŒÆÞªeÄseÖ´&•·×1$u}Ê»#ï[æ˜ÉÔ
èb¹åsXu¥5o4ŠÄ9Ùl
É+e­vI7\ÚhÍ”èú/\g9ž‘„F1šR
åÅ]J—\Úô¨s¦LVkÝ–ŽkáïfὑýŲÀµöGRxÌzj]²§-öÈjzY»PKjb:«tæ‘\Ñ”NMíô
ª–'É)UZÆ”¹±×u	é®&¤€~ÞDght÷j&£iÞU§š¿4ô{‡\OÐô˜›¹7Ò®©Kâ©—täîH¿úŽ«6©¢6©XÎÝŽºÙö×äªÒHøm»Åóõ0Cƒˆãâ7ù€?>Ke…æà¯UÑhÇ,–§TC½ø’XNUå,—¾fu¡r“ª¿·d“>F•(soK—K´ÚNÂi5~vdò‰saV
‘ÐV÷¬@¤ô$ðô­é+ÀSößý"L‰;F÷^/“2¯d´áÖËîˆ?™ÉyÓQíϵϭ—Ÿbü&8Å¥p>ü‹ˆâJ‚ƒž¨Ïà ”7ŠŽŽä@æ×&n°•.7Ož®ïÇîfn§g\Oq¼»ÀjùŒÁÇ{:Uî:(ô_vZ¤RAT¨ª†ï*šŒ|}sQÓ5©Ou+ã:Të(LêzOäp[ܧð~Q}Ìûí•U¿þÂ%B`Ôº†˜:é8µY«ž]ÀbJ°d[s¬œ[Õ~]sìa#­yÏÓWzp ¯%¬IçE0Ž-¿Ïì¥Ù?……Ð}gæÿ~¢£Ú,¯Õ‘É=Œ|_À<^ʧVZboîñ½”M.ÿ	QjMq¿¾õ–z>á\]Ûzk:²ìŽOnÅ~HÃ?ÒãÁ‡yp•›[/š|sRéˆ-›<7ûu/¥7Õ«ççHÞD§_i¨½tU[ïH)þ*Þ¿ªeåý‹›Ë‚•øƒãªò³òŸæ?”¿ý˜ùœ»>¢æ¶â­aç•áXÇì·	&븪ѻøÃ­#WÃÅü.vBÆ1ŒeY“]þ°ËNø•¾›$<¬¼È:½Mñ¤°?QrúGÙÎ68&a}]{þ¶vY›±ÊÄI6¨ãšA)$ón~¢ÞîO›˜`7(Ýÿ_xü¹wçfVü&Fý-­†„öSÍÁ¼Iƒ¯j4/k™àš-ñZçpššª:ÕK^ä„ÜÇ]§\ý4MõÇí4Œœ+ümØý‚ô#Á„í†Qºú¿
ãÏi×z;*ÙëÛ2át3²ËˆBØøß>
stream
xœí[YoÇ~ç¯ ò´#hWÓ×±lC
”8q(Ø$$W< ^IQò¯O×ÑÝÕ3=»Ë¥$'€ hIöY]WW}Õûûn½P»5ü㟇ç;O~nw¯wêÝãßwvîòÃóÝïöü¥}Ë¢¯{µ»w´C3Õn«w[cµÞÝ;ßy5k*7³•{³÷7?èlFÛ,tç'í-ýÀ§ÕÜΞUjÑ÷íg­ôìŸÕ\Ïö ý‡j:~®æÆ¨E]·3ç×^Tó¶í|Ÿ™}WYœöïjÞø~­gÏÓ´§0Í,ú®¥~¬4ôt
â]`¢œó“Ÿ£Í¢VŽý£Â~•¾é{ J9@ŒnüŠJùÁµñD‡»ø¿”m` 1Ú¯cüp«›ý/=-uí´B2¸1îˆÛxÒœŸ×¶š8ÙÉɹ²~ÕfwnêE«úž8zê·]ÀÇŸ­zdÒ#øû>.áãŽã7T4ð>Îáã±ßµ©aÎìIã';]ûƒX ßÿ:›û~SXù0ó+æ¦õoSã¹ÜÔùM@˜«G¤Æ·±ñ}j¼ŽžrÛwþ÷ÎHr¨5
¬ÄoÓqRãiZóBÒ9Þ}™ˆ”úŸÄ_AR^#\¶ðbgïÑ+d1Ù}ÌxRÅÆ}øø(‰4x:‰z7É–<
§ºŒGsê:©EýKbæéi£ý4=©ÎIš~RÚ(‰ù&5&:S#ë†õ¦¶ŸÞö­wN¶~L¿ž¦i×Ì	Oõ¤|A¨GÁH²û’D3{ËØ‹vg$v¼Ijû(ªšb‘Ϭ›jB²CaœwRÉß\
UŠZLº-Å2MÊ•†mîF
Xèœç卵ƒrA‡_7‘t^YÒo¥¤A–¦—Ѥ¼ç0h­Æ~iñçÔo'þ$´«´ÚÕ7ño/~×w_RüløF²ùºÄª?²›"j‡‚dCí¸+­»,yÚ“)AóÚ÷Ùérà߄Ǟºz„ËMj¼pî™& ø­ëtЀ³Œ|ÒRã•–YO~§…½Ä¥¶Ñ¥ÃcWh!Ñšû¡épïšGÚy{_Wþ“BKm³ÐÒÇòBJˆ-UŒ-uÅ£I€R Ó_ú(ýªÒ
УfŸüIºÏwS`
™bOq6¸ÿ·õÐøóCå ÞöÁü¾_ç×éœFúk‡J÷®24Ö¯­¼2kˆ^‡ãzKؔóGY ƒcαÇ/k¤è§2ºøo‹T,Ãàzz…VÁÚu=½Hì€E “NégYŽWåLÓ[<æ)ª©î=‹µ
¦SajÖqÑvê—¾ˆ™YWãb#áÄBŒöó9Y¦îÇDJßUÒ%{ô]#OÄB|xµ®û¤°9ó::@thº³‹Æª%°,tÛå:Ö¡Ð}mÐyEû*Ï}nƒ¼Çá<à0ÃÌã Uû¬:]ƒÎ¥ a ŸŸZÓ¢-bŽ™-Ú8ôkwÐmgøß/iî	Dµ7öÞ­H‹KˆÕ4¯UÓZøq2ÞÖ1Ÿ¶}Ð1<ím”P„y›äöë7­‘Ôw”ëvFHîSL—ÙN;›ÙiX¸Ó¶³×³*yé°Æ¢ÒÈ^øùŒ§Aû€\Òÿ_c6ýœ3g&üq¥Iiøxù=¾G¨€ÁÅ¦ç˜ÜÏþ^™` %°£¡À§àÇZ!€ŠÁÝ¡>Di¢rhô¼¶£8)
.BÛ Ó*‡1J
šÀ	¢ré²^gÆ:aLƒÝfÛŒÝ&Ü6cíbïdl²Ú|!žÑÅꯢx#QšÜ‰Àiƒm–=…°}b
™Û`°')©°ÆäÖð,Øݵ…%ÖlIW.ž"÷3àF®œ¹Oàȉ}C0£]HÓ£‡q·áÎBA0¦-:‹(àšq½ØtsÒ†"&L
·—.)9‚¸ËØåq¸6×£ö\›Ñ5R/ÙàpCüF×
Ç^p©	‡3RyÝ®HÍEî2pÆ~¦Co‰§ÓRfÉû/¸ö‘ë“1’4È
×kP8dîv~©zLÈY×㎟¼§.˜&û–ÈJ–{pûf¢i‡ë+h„¥k«CyË¿T†±Qœ
~	.¢É«ä*`Up)Êâ!>H(ÜN|ÅÁs\„èjIWI­šèÝ‚‘û kñ®¿o‚Úd†®[8òä>g]à‚ÔiŒ$â$<AŠœLÛ
œÙI¦Epsw9.ý®Å0¬m•â.ò>tÐðn‹aeÌ/øXþ.˱mSkÃÑŠqJŒ@A8nÉ/Ycörl‹›<
"Ÿ‚¯Eq#âÝ[ëé $²‰Ê3ÅO`iÊå1nùAéDšxF·"DjûväS„œˆ­zpŸÕd9k¢^Q$…MhâšB$*g¬Œ3åMEGÈue£‰=Š·|r/WÜ¢3Þyåé`1÷<ŠÆMÈ3‰ñ¿UY
p(¨ã*L£Á#Zršç²:ËŸZ rñ1Â1¼v|+¦¶™Gö&0¿ضìáLŽríĉä¯"Í`©ˆÎ8gËèÌó:“`ºËÒ‰>”(-z];(‡ð†Å•Òž·Ùòüyû¿Oý/sØúsäÂ-ÚÆûó’#+)J‘×Äç§ÝäÃsfo€‡}uŽ_N0wŒÐ&°õ&Ue¶å=”*ÖØéûœýÈÅwÌy6Q¸ç&‹Pcn&;8Íx”Œj{Wbü§ØxWEµp¹FDEÈr¿´R¤YËMO³peA©(¥¼6(Ô1ÔÆ´tS±|‰Ú`âÐÇÒôuµÁÉ2³`ÊÍŠo“XîÏê{ÔÈ­Âù3]@ÑAm‹ü_ÇÀ-KôÞ¢}*ëv@~€ÇŠf!`û¼¸.LTÕ˜™m+Á
aïu"äÆŸRãœäZÑû‹ß3e^nk<‹hLÎÿº’
ŠÎ}Û[OjW+ŠÓtmè¦5Áö˜“bTH ùN+€Ö®NÐp”#ëC¨l‚É*N6nSyÆðUO9I–|š¾F^mŽPþ©ÖuÉ‹ô%ü««·„=ú~ºàðfì)yyÎÀ—Ùé°³b§ŒC aÀ
H]Û^f‘+ö¡°ªé)E_Æ­Y-ØIiÄq^¡Ͱú¹ÏIy†>‰\Âf-Aˆœo·\›ÒÇ“ÕwÃö<Ìð¤¾ø²Œ)zµÚ¢ùÀt=ÙÇYkQã25´Æ¢¯»‹àV5lüÇ…3T.h™Ð#8+çª{sÎÎŽQŒŽeœFÞÁ/F¹CÌÚð›ÁUož.É61î÷¸Œ€óI´~0èKŸ§·~…M0S:ظ8}˜˜(Täy[ãè]Tù‘·±!<`©d%,{“|V› Ö[ä³w1€NC0lþ-DÑQ19”¾Ž½'UþÌguÅß•µî=ãí½SWª¬Óµ2HŸâÍfV?6yž¢¾¿pú”Eè—žœUã °¯Üó%`á×Oî¹þÉUŠIìF¹ÛK'ÅX°£0ST
=C=Èó/ˆ§ò¯ÒêPåP.”¥áèÚm‘hY;ý¤&’<™ŠÁöP4,¿W0dí!òü@g¤|­[ØT…žÊÒ°jŽñ¨ˆë³GKiêiE©pÅu«nT8Û„ä†?Júœ¿†¦âp\X丼];WAH˜¦Ñ€”ð¼'À5ñ©FV“Å
	(¦Û‡üÈPîÁ‰1j;½Ùxý>,›¥ç‘yÇh貺#«ö„Ù.Ñ/ø™Q3xTBgácѳŸv2±¼/Ê븎€‘ l®Sö	B•b{óÙÅßлíÅÿyЄövþåÿýDHñZendstream
endobj
378 0 obj
3499
endobj
382 0 obj
<>
stream
xœí\Yo7~ò#„}ÙiÃÓnžÝ½‹`‘Ä1â¬ãìÚJ°A,tY2,Í(:,;¿~ëàQìæÈ’í yX–Fì&Y¬úê"‹óëvתíÿ…ßû§[žõÛG[ÝöÑÖ¯[Šn‡_û§Û_îÀFAK;v£ÚÞy¹Å=Õv¯·{cÛNoïœný¼p[´^ô{Ùc;~ñ4í4K»xÜ,õâI³Tí8vä¿éÉOÍÒèšÍâYcð¹Q‹ïñIÙù)üõ5~xÞ,ý/;ßeJKʬëÛnâv€ „Qü¢¶òÅexsiº¶WãÈ\cj£*׎V†ý²±‹W@É
¨öcÛ)»¸lÌâhZB[ß-Þ4ÎÀâ]ì
'ðò?µ‹xcðø°¤fƒ„Ç~q†?h€KxâFb¼
½”¢öð!NºîÃDk9ó)p
Ùò !/‹÷‘¥§AèÁѳ¸FžŸ7K&2ÍuÈÔŽ£Ím’dúŒ=.²˜Ó‹ë™kº®õ‘•G0-Í‚óŸ"9±b7¶Ãã8¥¡Í DÔ¸x‡“AóÐÃàqYëÈHÙˆô@“Ö™òžs•ä—Í_èuñF@~D1Æfäâ¬G8†ž¸Â¥ä½½T¦uˆZ*rWHkÃu#E–«ÜâÅ"Š>ðŽXÎrÇÄŠ
|ýÂ)Tßz3Û;O¶vîýÌÖª€}qhàÅ‹0Õôlìi¾7ÑF˜æÃ‰×ãB„Ô"d­! ÓH‘%ìhBÅDÓ¸8Á~Ð9¾6šÉ¡DaiçqXœ.&)À¾:àІ$ÌïòcMºÄ‚„^•Я䵄e!+õèÛ!™ŒU$$ÖÄ|@dÀ>©®cnBÉW!ÂÑàÿH&¿~9bDTîteŒ
%ÉĤ,ÃúJ0Ö£1ï=Ø@¬È>Ó Jиd“Nè. h)S.4ùƒ“FCˆÞ%„ïN#zõ­f|þf”áçI$ø -×|ê¨ÓQ"žyS¸"Óé¶÷Û`6Ú1¹¢Wh*p8¥Sló_â߯B£!ÖñøÿÅ?ƒu¯ñrŒÇnYx€Ÿñ¢zñü@âPÒ)Ïpqha°OË<{àe9b&î$LoÇžŒô½ôø,NÍýÎñOðBºѼ,¤'ÐÅéŽLÎcú¸XÂ/pÖȆ³ôÚ:S“×·ª‘x˜:Ý܇)N˜ws§½Ôx’ÃHà¯Óó*‡ŽÃð :ÿáõìÖè=Ȳþ)®ÍÇRx¹ø1ÐaÍ@ð
­‡a4ÝËMÒÇ aÖdb6"«&UöÑ÷
h‰.—…¤“]7’~ý9„¼NWµ‘Îrã•\-„ø(5>Îoî¤ÆçYÜ™dƒeáhòƒÒ¨¥—Ô’ÕJ앲̌¤¶·AV
8îmÅqPSŠª¦äÆw¹ñLÊ("èeMÄçy!wb]hü[–‘J>¿y?oÒs]}¾Ì­&ÔYíîg)ëQq½Æèq³D7Šq•ÌùÛŠýF	öèEn-ÁU
ñ§©q¯ÆÍóÌͬ0/ó,YokÝ/jj°ªYÚãÒ¨׌jahdô?CÅy±dvLNŽz:{%\BÝÔÍ‚$¹NÒ<ŠëÖ²iN©’HwîŽð¢ÆŸßäÐltíDzoa{é…îô²qÉv@tÙÝì7*!‰m?IõDòÁkà°‹egï Žû5ã—ǯêè*«ãj³CtÜͬøy­WÄ»LɉěØd˜K´‡B÷Ï#³éÓ%o³HKŧòF	¿LaÌ:*¢ˆXr0¼N²Ý“OxBe;p&r/éóii¢W	ÞÝY~¯j¬|U“t)~²l£ýuïM
1".¾*Ð']+	Ý¡$*mtýÃ(»‰)öy©Z•R®ãLÖ4!fq²rÞÝ”e¾Ì€~oè¦øã SráÿÐùƒ S¦VŸ:9ÈÏöá¢)ô"Ÿ(ÛÔµWÃÃ*»ÈÛ!yé'5	óÅÙÒiN=É-e8Œ`ÝŽƒè¬ØYý从OXxGr!F*×}ŠYúO ¨9{«iôQ6×RzóNBÛ›Š](ý`êåôrƒD+	ÔDÃ	Àˆ%6?ÊŸdIŸ[¿`Å÷¾í“âïäÇOs§fCM>þ(GMÝÄb„¯1?Ã
Å2†¥vý|o¶6¤
mÎûRå•|!òûˆQ†]
VàoX ‚s°³“J }ÝÄýŠm'SajѶ¢mØÛêÆë+Þ¥Æëš=ïA—‹çqÂMÁ¼Ü¸½I|(©È©u§ø´
Ò'U£`¹Ÿý¸¨ódëö£ÁcÒÏšÚÁÈ;q"ú?,ç›q1‹FXųš³dsŸ2Há+Ußy_:ü‘ÚøÁ.§Li)
w¾´§C•›"ËqŠDãq»â"ɯÈñ‚8óæ.9¿ë Såð¨PßV¦k	Šy¢øª&ž2OÌv"î+îÖ¤{^“é»gˆ4¸Üá¯zʹ|޳|>çU69¾Öf@ˆV‚‘ënÞú¶4å%U.Ÿ×&ÎðûØ]¹;„FÊÑ3T§Ñ7"î®H‡7OuZ4Š8H ‹%e&NTŸË5“Ìå!®ÀRlv£~U¥³iyAtýfFtcÝãT7mŠ
½¹¬ªÕAM‹( êÚ&¬	ß]ÂB%Ä¢jgpZzqAöIÑ-òöîrË?ÌÕHz¿Ðì¼j²9`±þ‰6ZE"2÷{¥á«èÛy†z2&ºÅùゾ½Ç™ÝÉÎr‰˜,¿˜µ”â;è™É¯k>]¸´âl®fliÃçq
RGµÆj¨Z@*jé«B‰ø"¶»˜Ép®eÝÂ’ÆwË8JpšsÊ1”ʼnWlÌËûµ¦[e¼çËà »§©±ŒˆC£ˆQ8Ö7àoYuΛOr	ÆdGá*=Eª‡me[c½¦r­¹L«T|¬[T­ë-°§mtë”2ãb¢•î[OE”­uóT=ÔY=""èÅJ‘àS7ö¡
?]6Ƶvtœ#Xã9.žáck•.ÆùÈ)«¼ã¬òãë\ÔHšßµF+o\ZĪÎÑú .´C§bbáðeÕÀ°¨´kÓ÷ÀþaÞ¬{‡/,Ú¶@í£xÖ;ËÂçƒéUÒtx½ø
ëŽ:ÓãÞ§n=t‚§Ð2ôS;=´ÚšT¼kû¡‡Ï°Õ@W=01íꀬgX¥ìè±)Ó™^½ÄçÞ"2_e‚VôØ(&¬çy@‰]­,B(-8•jºhin佫µ(8[7 ¨©rk•«¶Ðº„¢?ª«’*¦¦J©XÃê-Õq6eX,íP\`¬D=-Lá´>Š(æk.ý4ý«h}.›Ã™båXÑ»ïê©û
UYA4…j®×•.Q„6­œ¥e»"™gZ}t^‚€vZvúU®ýU¥sZ-B—qô`±Ò¹EšivY]Š™EË€¢°ó!-¬óÃâ‹fìàýxiQJÃ~×HS–[îɼŽU ï¸¢ã¡¨Ã
eÁ¡ÐÎ8K›™W©”»â;¡<ѰnBy¤Í­i<±¢ìÙq)t.¸›Ê V&"o†%Bl7ý¡óÆL
•9~®&ó =(Nç*è	ŹÞÑð_Ø‹…º©îG¯¼õ×PT
×*)ƒgߨ\ãhãéVçZN`ñ•3cß]Ùn(à»#F&èð´ÐöZâ„?åÑ
#ÛÑþÒ{Ê[RcY¡ºËµ÷ËÈÒ;’,V™—LC‹ÂZÇšt䨆5|E€ª¯‘Ö~˜™B–t ¸,tä³PÛýºŠÁÈaÔÖsÊæ5ï–Ü æàÑxÄ,ØA=òj#‘C?­Åñ/y5…uÁ%Œ<üo
+gC6äÒú5߈L+¼3ÈݬfHéÀ´ˆF±é°Æò®C	¯S•ëL&a‚·yóAK¸ FˆWh¦`Ùpýˆ2k£aæÐ“ù¥Øç0\·§™
É<¥µÆš`múh#´sm(„ó©8;z¾xB{¶(,ê±<-®,ø¼0¥&•õÙ*–ȺtsVŽÓõ|êÊ•c9ôn“Msž†çd`V3„ks°®zàh*‘Ç–ÍgQxcz†VýÙ	]Àjß·VÄ;fühÙQàœéîG¸$Á“ÙòªGìËÀZÄŽÉaû¦vUiÎg
ïÞE˜YK§7»y²ì	Ä–D@:#¡ð³ÌµÒèMKû}òœÊ´\óX–›3–˜a¹¨ÕtÓÁ×êøIß:70ÐÀ“¨jû'þxžçºáêë€/#mlѵ©ŽìÀr¼²ŽD^ˆžÚTgñXÄʶõËF%~ÑÄþAÉé°O+qÊu^ñ³/pD
e&dÛpÙ9+ÜZy„$5Êxî{tÚÆ¥Xkñ¯†¯»ñ•µï}—îÑ=¶§|½
ïDñÙ’¬oà’^K­É)zš÷ºËp	!zœu>%	çäUÊ¡ƒ‹b^IL¢ä“·
o}“Dñ0±ë‡ÔÖ⋜2)
%oCöQâê™m.¼÷ÆÛ§Æl~Îv1° 4Œ×¸Y|Š|ÀêÂ`ðÅÊ€—¸½ïw³?*Â|k’+JÂÄ7 Ë’Áoÿ醃µ:h°—åtæe³‘r`îò¯yÄŒ:…“0Œ¯#Ü֘߂íZosØW"¾×ˆðÍÒd0¯,¹}:dX£)°xÍWÆ#Æy—z‡f°E#¯ë†u–HŠx‰~oÈ#ç®0eª¨¸=ç	»2Œ	J¿'<!Ý®×Iw³BŸÅ.t-1í®Y¾E¹—HÁ}Z‡×ç—x®>(̓î…A;Ån÷0¤EäžçŽ÷wÓí^fö	íWiÞ"fâš2­³K±Éö±Ñr¸Ež³ˆhöò}N2YUÇS*aË„‰:J†3oëXÚKÛd«'˜">$ÜÆN÷Ïž7|KN¶ýÇp­6¬¦ô4KÏL˜!‘
HDž~Ùä4:¢+ì¡qþ†€Øùi2E´Ó›{Š*/Ø©79ç}_¤÷®Æðß6é*}ñ½áö¸@gÌ׊UŒš–þMÍä‹Xs8â²­¶ÒMø-ÚÃlVѧš¾ ßEŸœãÍ©®
.òÆpýWy™=æL!Û"+¬é<É€èˆC¡Ü«T…؉V»9¤7aà êØg“
©Âêнe±—iLԾـɘß¹ Ö9•ct(ñ’ö8lÌòèöt¶Æ•ù~²åžD¼Ó];ä^ÓSq‰ºü>twšÏBÔ­¾ÈƒÒá"(áŸHd¹ù»1ò.ÿ$F
Ûô½/¶éÁ`O2׆›}ÚtÎÍÇ.·ËéãNñ­rúž¿Ö£¾a9UŸäçJ¨“™w]«ÓfQ:1­ðmGÒшÜ"‘Ãbü>tæ	c³í6cÅÛ_%7$6Eqž¢&ö\’wÃפ½—¼?ã:ŽÞS:àÜ\)ƒû»t|:ruL"3BA€·)ƒy[1ºEþš¹’†üÌøæl¿@ ›ýú4d¥,‹C±HiT[hvq3tðæÉŠ2Éݦ@…#!6Ó^òÙζª yC–N²9»ebœbK\ý×;[ÿ†ÿ‰ãendstream
endobj
383 0 obj
4575
endobj
387 0 obj
<>
stream
xœå[YoÇ~gü#ø¸#h×Óçô H€Xv'Hœ8t^â  HŠÄCE)ò¯O]]Ý=;³\RÊÉÝ™>ª«ªëûªºõæ°ß˜ÃÿÉß“«ƒ/¿ÏoúÃóƒ7†^ÊŸ“«Ã¯Ž ±ðd3ö£9ÿ¦[çßwkç̦ï‡U€±7Ýz¼s«¯:OÝþÜ­#¼·võméö»¹Í˜žé×Å7)b#™;Ö}¾ƒ>Ömz¸Ñ:j£ŒqQ(‹â 06ˆÆ@ãÞ.Ð,ðÍøˆ
³0ŽƒæGw	ÏïYú>XCbÈC‘¦ÑôËšlu¿6~ÜôþpíúÍ`Æ‘5úãªs«—0Â~Î@9ø÷)ÈGX8¾z_=ió´¾@
œá²©ôü~IÝa	‘ºQ›cPý-[bLaõ>Ž8J¤‰ðçšFY]ô¢èø˜¸Ñ)ŽóÁz|‚ô&â¸ÙØä›œÐ¨,W"YQM¦,ÂÝ€\oAWÔó¼e”ø†z¦Õ«Î±R>Âl«ñu€Ó5møV³“¾ïúPÌÃÙÕ}uâÑehÌD2Á,bSX¥µ¸*yƒÓ^¡kÿ8¿z­æ¦	؛ߩ˖OKÃ;}†f7‰®q×ûÍî~âSoxQ/a^2̰f$Ë£cð›wøë–eƒeý¿~À_oÛ&¸.~{¢/ðë«<®Åá2ý€KW_Â| Jžû¼(óZž”‡¯ôá­>$SÁgôý5ìÂƤ›`=]ö®_\ÊB?ÒŽ¢¯_·ýhÙO¥!ì›_ÂGÛÓ ÜàºÈZ)ôÉŒØÕ¨ÇsïÊÃb°³|d[ßÚØoœ»ˆaÕ`;788¶÷†@D«E¿
‰w)::†4oïiï4‘„ºm¦éÙï4ªâÈ¿‡ÕŒ‚÷Ø}°×=Œå—÷Í-ûÛmŠ|Y´¯aÞ$š!‡²ü¶úX¶^Å4 œ£Bp«ûvVîÁjCÃfÏú-;¸4T½zÌ
ð!&@±0H´ðjy£‹.ÅÆuI»*,|TTÝ&ßè¶ÂÒ3€v»mÐ6ÿ@ÛàrÑaÉèè„ã@îŒë#5 ¥ÆžäÌö‘0çéÁ)¯Ô€q>bÓHÝI‘@dÛv£¡q1ø«ô:8>Å­2²
Ýqo
«’pþ"£M>0Ó°8	õRQÔÚ(N2„O'²2œ?ß1R€ŒZßÉÎáP˜ÎC¤XòZ-O—f{b¼E$J¸ltÛób¦!¼Ee¦一xt„G»1Ñf|QC4)
Š9/©ÌEÎ#«&çÑ`ÃJYljÁ®;ò؈ZY{7d;où	>‚^Þ²,
u]^£MП"íÌ¿PÇ))H;=ÖSÜðÐè†[.翨CŸhê•bH§pìÁbïÊÒÄ Á’A¦Ñ¥,¸œd3wÊ^_Q&
&ý€»4»YC<¼GrKþÅKËûÄ7Û¤4òÌLØï-‰^XéN"@þ:	RÏ&ë0”›‘H-YGë8h”ÂI¤
¬™b¶¡Ç1!ü€ûZ{1^yf¨–à¼Á,!‹•1ÔÌÍ̬–sæM ¿‘©ç|(?EpäYrT7q_~º^&z€ë	¶7“
ê zwJ€PÙ¸	¦lOù™[f{¼mîc{wúðuyX¸ä«e¶§ôÿÍöÔÐn/¶÷$kƒfƒ<-Bu
–‹k}a{Ì£ ¥%?—pa¹s¤
“¡ûª!õqeË~‹ã6±bfú¤H[qŽ&–#Î%™ëܲ7õ9…nÄ¥ˆ
žêTç»S %Br̪¢6‹b©iáS˜‡Z F†²uåᢴjÁÞCU†fË5IÂ1™n±áU¯´+
sïs˜SÅ~Ñò´KLbóe(zG.sòÕ»jü·Ü
ál›ê‡™À˜š=‚·|vKuE))Vý+jIM9)aúd€Šd%gMILbn0a_ìÎQЧrÂÒê`8„ƒÏY“µ²×”ÀV¡kÀxÚqa¿†WeV€×ØSؘ«¯ìàÛyÐf¨d7rεGETë”÷¦™Ÿè	Qö9ð‰Ì­rO¢¯£¦fYئLá÷`ÇyŸ”,ˆ='Lr5ki})°1¶ždûÙ{*¡gñILj"X¼®!FoÒ¶Zok‡=„âVB½C>øñ.£Ks
±[uÅ–{!¨	^,Ÿ$ætFÊé7]Sr$Úëðü (ø«À^&iRcÇ›ì||+CÏ=gþrA#°lYáû”Ô?éîĹ2†w™"LØAÈ™"8$žŠ–~Ü&%êﮞyþhB©ù_ψsä‡çs-Ïj4àrŽ,\תaIý£ÈmØòðjBEò™åg[—¡Âe{•ª,.þsÒ)©÷Iip!ÑñšÖŸ–^ÛÔcBH®JÛ§
!oÓ4ÿžÝO”õ’×7Š7§·tÞ1Kv<¬÷]{±%ìEvè]sªJ±ÇäÜÚúQèÎÚ†qóˆ"£ÃŽš‚•Ò÷LAñ¦LYÍnøÞdÉ÷&â45¤“™Â‘ë6÷>äÌ!tƒ…@PFw1Æ®D/%‘—rWB¤¯N:lŒzÑu¢ysk…ÉŸ&'€IVë14þœ?Qƒ
ËJW¢Ð±§RåNÖC)$Bø…âÚkéd·d›ÜìyÃÅÞµ%q@ê‹TaÕwÂ('滦;*Sr²¬¬”AK¡t—-ƨ7©>J­"L܉J<õä¦ç×239ñò]†us‘*ìw½;ÂìFÝ3íBX‹Iiÿ²Kô^Œ=óô;ºá×*þiàK]ݵ4ÌoZ>QKã¾´¶P‰›¶ì/gVÊØÈ‡gýÍ-Ñm¬}Û€Ùvò|[›¬¤T3[ŽÐW?¯©ÏžétÜa¾–3Š
_Rt_ þ£ðTA÷utß'°ç˜nG³?4m~@íãÅÊ­© %k©@«\ŒR¦^p¥¹×FÄ“’()U?—él˜Qæ¶õqÄônŸ·ÃR5&uŇãŽ(ãáØSjt$† ú‰(Ôܾƒ€ý”x"DÐ[jœÝ¥GB/§1
ôNô'ÐÃç8Ÿ~ä0èXޱ3wœpžÀÕâÓ²+îÅȪÙ¥T
h|²Wï4¾×ol¡ÑÛ;o+ínËÞè&Þwf_³å³<ãšÃR
ñ¾ººz6Sø®œrZrhþÏ,÷òx}-5‰óäìKÎî'-ùÂŽÿn¢õñLåóiýÃHC¦;ptC-oÝ£ð‰Y°,Õæ³ò°aõ
 MÛêYî^RrzïH)	f3½ÔËŒ¤Ð£©ûT²¼cÕqQÃKUœðï§ÿjÃ…¹Gû¶RÙ䛣ƒ?Á¿¬(à]endstream
endobj
388 0 obj
3403
endobj
392 0 obj
<>
stream
xœÝ[[oÜÆî³±o^¦^šs!9S š8IÄIã((‚¤Hl­-•,ÇZÛõ¿ï¹Ì™9Cr¥•ƒAa¬¼Kçr®ß¹ð×UךU‡ÿÒÿ'G÷«Ó«£nuzôë‘¡›«ôßÉÅê“cà\icÍêøÙ?iV£]η]_ý¸î›~Ý6vèÿÍbðþ.7¿~Ðlìú«fcÚƒü›îüÐlœá²[?jÞwfý
Þ©þ~}†_¾k6ÿ¿„«wæû±ílîx`#cÓóÀ°20qß[·I7®kG#ï›
¥ëºеÁ# Ì/Û±_[8‰±¾µq}e­·ÃúqãÚ8ö]ï`ÛíàC´ë§p¾Ðµ®·êþ‹Æ¶Ã8X»ÞÂí1´£wxV8í»0®Ÿ—µ.à©óT@ ïáþ81²VŒ^?u^¾ª«»Æö­B¬ßáº]ÛÃSpãã`ח긯i½Ý³Á™¶e€žÁë+øæ|ýìÐÚÐÁ×¯ŽŽ?þ‘9{¼¤cOð¾Â&pû–>—ë·8ôyƒdÛm×™.¬Oa¤ƒƯ_5›žz]nï—Ÿ€ƒO¤‚s=mè†áÔ4ÏU‘ß<–O;qüŽ%ˆH¾¢p!”žŸ¸BIƃ[<ƒ+óeŠXÞÀç@fXDñAYi‡ÃäßñP¤Ã–W@ÚÛlö¢yr<ô½¦/D°•´®ë`ç&mp—…+Ær¨>mz¡Ë*ºï}Ä[¤§<¦L“Î/S•ÓIÓ¡2á§}–GfJ@“ñO™ˆ#äF’lM6Ô©IcaD§>wQ-XLP„27@ÔО}׊éBÚƒZÞofÝ8¬ÿÞÄŽo¥r½_ÿ§q–¨êf@Ž-’f0"=©h½7MïpÞ6Êæk-¼Þ“Zï‹Xª9æb”6~Ãä=Rl¤m¡
úòs:#©›C
ËýóÜ';Ð"oìz“ùvÀ"€YüÏ»HÈÖA(|E)äó8Z–ÍŸÜhñµèk¼QZ¨•ÑqŒ–šÇȱÀнQÛ€cŤŒK‚–vI²ÄÇ%QÐ⩳í¢í‚V¹H…ï•~˜|6 HÓ¿ßÂâ(ä{Cä´èt¯uxã'ògÄü$	C¢ø8³ŒycI¡ybA~˜ýÚÈóéÊ¥|O¶YŒ7ýù›‘4H¼¡¬¦úŠ`aËÒKòã\‘Åj& Í0IC@ÚÈ[ÅUm#2|Ö¶EÙ	£Ÿ—8ç•L2E=éÞÛbvÏÊËXbüDPè\µ T†%™y𦨨}`½d¡5y‚bÄÆEtÏú©žnE5Ñû<¯xÁÚÛˆt‚—"-xGO¬‹XÛäýöz%ÅHY÷R™£¡¸Ûq¿éÉÆé9K‰#U´4m´rSy~ž…½œi‡&©AׯCc¿ß×îez¦ˆ)»xš	‘LE¥àî§EHZ|$ho]‰
Ïúx¶sk£¼erbtäÚ‰Ý)ºÐÁã©øþ"Ó@@…lôhú*Ë‚›±Ñ‘˜›±"I;†<£É“Mp²Ä>bÒ¥ŒfÍ©ÄxcÁ|–ƒ‰(mñ!vÀÏòÚ£:%£Èbl:º^ž¬F¨)Ð×üÉrÿ%
›	ÔC¤Ïk¶Kp¨ƒŠ,ïðbŠ P{Ž~¾[àg¦´7IðSâ%ÓÈʆÔfKF¢þæñ–[Â$KøY,ZE³C\Ÿ´6UÙ²|„_ˆ³¸¸ ë¤“Ä“?RfiÉÎÕ(ø±ˆêS‚ÍN¸Ô³Ú뤄P;EJך,_?šñm4Ô&áEe8Àóp4c½ŽfÀVY	eLã–À)™„ç‹FιÂM!K(…­2í‰v(.“B
V«0ÓI±\çÐ÷Ì’eUA5<Ì•õ­,æ9¯‰hwäˆÏ˼µKRþh"Xø
Sn«)çÑPøÅ éqå+Dð^ Ècëîç}Âæ>ôBË,=Y½›±UÔe_”QÙ{Ú. ¦¹Y’¬‘"òH™ôš ÆöhþȅYnåiÖaU”TÃ
‘„Q­Ì®ats×0³òhzS &°C”ø7»Dââ݆‚&¤ë[Å×ðX'ÇBœÜ8š%<ôÍCÍô©ÃäkK'™{<
Ús$
оœiKVÚ¸ˆÚŽEmÌ`Ty¶œ‡ÐF¦Po™Ç#R)Bä1¶	cñ­‹ÑubŒøÀÏA'9ì,¿8Ýú·2s‹Ú,H“Òô`	‹'	šBÕ¤ÛhÉVù¯$ƒ®¿PŒ¢Hn¼“X8퀂H­3aŒ@@˜ÜsÄ¿î îU„_Œˆ
ŒŠêƒÁü`hÐRœŸn¥3ð'd)ºä+lا
û,{€ènµa/€”zŽJƒ~U£7±¤³ž§‹d®Ó2?ãÏSÖ3¹û³!‘SƒwyÜE·eøµ)Fh“í{¾x/_TV­èÌiþvUno²I!”)I!à>æJkë¤ßôŽÍÀßà«í–éð±Þ2Ÿ¾›ÆñÔv‘š”—ù⋥ß•‹85ê-A„å‡ôöøþ»:&Þj£Uí¼#H{‹é¯–ö¼ÈÅ×åâU9å<”XÖ4¢uĤ"–ö¶ÐĦncw$çˆû!‰öCÊk#­ª¤Ö×ÓXMsv¶7#;Ï'Ræ WÖâwKˆPÜ
ã2}U~MùjÛe©žLò£œ²¤ä•ÂÑU‘ŠEjlM©ËœÌÀ]½Yȶ'JyF¯+¯p1ä‰Õö¤ª±œ3aâ,šØ"ÏñN£±?vWà)°† •èd@Î.ùÁ–KuùéJæ4dy[ª–ñó{ù;{2”lÃqîÒÌrú’üˆs—gžr†8³AÄÉXÓQ8¬Ú;´|•`ÄÐY!ätì]zÄ¡ñq¼-šŽÄWÁ¹]¹_šHÆ$ó‹….yõþ€ÉtñXÒå.	wœ$  «æŒu©Üë8l‚~9;ÍZ¸Ž^õTÙ¤Ÿ’WôÌ©‡Æ
è¯fµIxçi^JŽƒwÅ^`­¦ý\_U-¥.®él‰×v]GÝ»),K¥Ãz£Ò_Î8Ú‚¸9ÃF|R/‚ù©æ‘=”xu–™IßçšejÌ`À6)¡Ñøn¨bîk&ø»x‹D#›IX5˜‰ÊÓq>pb–ã„)‡ÉT¬±ÀXZÙÒ'´zxÚ"¥’– Ív‹ø#t¹†XAð$ý	dH=å
óŸ*•ìV§•¸XUíÈE¾tHËHÚÍ4ƲÚ¬ÊÊš	¢Rƒ×%X©?µÓB…”¢æq”¥Z*÷—o“è._cuMC'¹&áŽê˜‚T<+Ê›w‚(*©ñœ”Ÿ¤ä÷÷$®‰Œs~cê¿d½¦üv~ÜÃï´“,¢o*.£U9„á~œgKû%ö&Dû;Åɉ¿Ü22´CPÕ[G¥Å@H°ânŠ*Pí¤¨ŒÂ	?;>úöè×Uê$èVpþ°ò}ô¸ŒÃå|ÀžÇOÝ{ðpµ{õúéѽ­ÌѽàŸOþù)ü÷àþêOGŸ=X}»·râúR?¤l<.ÓšÀ=‘tغ{ªÊ»~œ˜‘Å‘u·SVC߇åî»Åqi+±¹¤qz¹ho´R|Ü”ìíÌrÍ9Ôr&MšÖ÷´Œ-8ÕÒdñ~º“6pˆþ¤‡Àø‚ªÞÉ׸–!­­pm&©#TÎó=ËÏ*ìj åõ9_7ٲ嶋wy+‚Åu²4¤DÐÂY)ʸ”;3p}VOtXÖu»„‰ëÌ3m{”ÌõI¾w¦¹ª1ez `ðíÒÈÝØ_Dë…n(û§_va¨DÏä1‹Q€bù!)eÿ;Ä’=~\PŒVVO=róΔì´(˵¬'¬ög—ƒù=9»ß€ì>@f™Zí8½Ü©¶”CRË©ßNÙ"\«›í¦©èÌ«Ša¨b;îÍEÎ<^×—›S;”zê¨.„Ý©'Çd&Õ;ò5*ÿãGÖtoR?Í4ïk•{çM.ª$FD~XDhy¤>Üig¦ë­œ`Ö]'‘iˆDz¸QãdÅ!Õº)w…aŸ®‘ATáºðJähr\9o~@­D,gB¹&…‚R¯Š‡=ÞG2¥b-û¿¹jáRèon•dG"æ
ÝJba(mí;”G£íåy«Å>Ò7ö$gœ!aEh£´Øip‘ÔÀD¨À½ŒKçÑ¡S^¿¿÷3Ü˹ùRhÈýoC;ZxÐ}'Ý«Ùæ¾ÜóÈ¥vLy²Ì‘žšn’J5:¼,®âÀdÃB{e2>|ÆçÌûÊfYã½Ñ__ÞƒPöþE7±ìeYÕ3}'ÅŒ]n•©j8.8ëlIÙ’”B‹™3ôK†+YŠ™árì˜÷¾Xp-È›ú¶ £È†S[Ýêì´•úúz•àþIFBµÛ£èX“|oq¹óoåîý¼vù6ó‰Ë “{£‰¿1W¿Ëw/nðwé±[!üIŽýÿ	áß4SYþ²Ìóì}>§¿qÒâYTÕ¤œþu³<¯Ä°VY½	 Gÿ¤\=¯°“²×ÂS¶ë}_’|'e¦Ëj«¥)Ho+eÛIóL-ç‚l³äœˆtµR/IÒtž¥[„’
ÎþøqÙ¯ÌXyyõì¦stú&[PY½µ“󡛥=û®t^ácܦ;möóïË¢gŒs—â'î¼.ÈøÉ|p`&V&òG)«_d“1¸:
Âü…·¼­æ”æØš>{ºÓDYãjü,/Ÿ½cbY¿ö€>p5'©ïxÅN±ür2œpä¾é\ó—O&êçoÐiÕË&	`_ÿÊIzWÏ”—TýªÊÉu6>T$}ë—Ö‹›fÇx¯.¡yÎæ·wgø#5’Ä뛃qg(Ï·ˆéT°¾àë>§W²ókmvÚ6ékaá•.ŒùÛ\ê]x!'·œO@!ám•>
stream
xœíÛn$GõÝâ#,ñÀôÂôv×¥«:R‚’(	°8‚ˆ È;ö®WxÖŽ½ëìòõœk]º{Æ3!¼ ´òìLuÕ©Suî—þþ´kûÓÿÉÿ›íÉÓgáôåýIwúòäû“žžÊ›íé'g0¡70ÒŽÝØŸž½8á•ýi0§Áº¶3§gÛ“¿¯†Æ¯bãÿqöXaûjEZaÑÙLü´Y»ÕçMߎctãêãÆ¬þÔ¬ÍêÇ?kÖúàY³¶¶o».¬<Àn›užÙÕ'£eiÖ<7fõû¼ìS\fÛ1Þé·Á'qÀI².,×üÖÛv½çI_54 ŒÃ8"RÑAdÌû&w°žv_½p¢µàX˜nº\Ÿ
¸t7=¡!ƒiGÚPó°.Ã79Øò&×ýàÚO×¶kC?Ž|£¯`ÛÕküx«û‘.éþ~%ƒvuÇ
ûÕwú“Üá‡Áü8×<ù>Åéã^Vè½^¤ÙoÒ "oà;⸆Ûòò	"ûí
—oðãJ7äÕw‚<€|²Ÿ	ò¿‚»Qü#a::6ÏÑ,îæIzþ>?¿Lƒçyð.
Â.¾‰¿ÍÏov,’Á«‹$,Ö"ÇÕ¨
e;G«dÝÀïp+"*ph-½ð)ŠHd˜YÈŒƒ¯¾73,„"U¨Åk²$¼ÙÕz6«çð•„72¨Gg“Њ2WiÇ<ÙÒÚ{'âq×Ô‰q=i.gGáF¤Ø5ltAÑO„J¶ 2ð"À1VÂÖ'"Ö¤Ce±×‹ ­ã3
ÁÚ¡Ìœ$ï2s¥™‰á…x	D³3´%AÀ-³tÍ:O\[°6ß²;õ­—ô¯+yôi•Jnúj.ÚÀß0“kmÞ×ÉÞ‘D25Pš:TFnõÐxK_Îåöß.çÐ#ñtÁ×ôÀp‰Ÿr ‚¦š®"{Cg*¸ä†Dšÿ_iVÅYÄÄ9r¸Úä!&HõÁ“Ò®´Qèj	G ÀMIÎáúD¼l-Ø$MÀÑñ‚鋚SG÷¢°½Vò#ÀÐgH½S‚(y6säYo¤*Ž^žÿ‚…E@?m*.ËŒ@ô‘~±7¿ãZ@®Þ%A#Œ2ÁÜA9è›äJ~û}“\,üµNDürá[~ú›DÍü
±G›åˆM"Фb”ÏÉ(Ï«xã÷MD}Eâb„KèÄ%^ÕKÅcO‚[Š»r>²‡¸,é±#Ú¼o¬IƇf¡w2Žzz«š'KwMäbn%Îa$Ž(MfvÇUÔa¨$5±âéæÈæ”’
qðD2c?ÕȺ#Ø´;
æØÑzÌdÅÒ8DUNÒ8(‰‘±Y¶t™ K²>â3—|N‡fòãé"]gaêTÚåÚnÉ5Í5`V/JÜÞÕP’º™j›Š¦ÄT½tŽ®oŠ«…RM"A ¯2¨j	Èbýß±øÚVz!º%ÙãK3ðOd°2Šð}„xIÑQ”›ú@u›¹		‘
Zô¦¶ejmß•§ŸÄòI0
í'kÍ^˱³o#:sh&‡ˆÿ”Áó›´"KÀ!ÁsŽ·Íÿƒçÿ©àùªÂ_Ãà·ÕýäèI¾89{²ƒ5Ÿ(åÇ)Â^
aáÊ™ðúøùó4ýº"žR'ßÉýq7䢤¸C›âp:Ü/÷|i°¸Å,œè­ñW–ÿxÚƒNðÞp~7U$òÀe1J2W	´SÔÂÖ| y°{#Åȯ|ýöN³^ç‹“Ö2?|wâ8\ú’…ùç—
׸ƒÙ=ü=¿ò2Þ5œ«_X¡º²NoeåqL B&õ:¹sê۫׿?dy™üBzJci,;ê÷	Êx—.ð}Bãm7±sEØúP†óà>û˜Ä` ñÑÄë%³vÕÏ~ãÃ’¯z·ä"¾ÚáÀä¾ø“®,P™ƒç_›ÑäÌŠÆÅ¡Ó˜UYŽY7¶Ös“@x#öW´‚ë¸B^¥aÝ$ïÂ	¬\RE‹yÃcËVP=Ê‚zOJš+¹kÈC˜ë«Â#‚ËxüM&¨YOÚpX}œr>·bCCVpUŠ%kŸ:sWªM¸óœ )Ôã
_U•z(ùsê\Þ \˜&Iê<Š–‰P7G?ËVY”qh½™$QRÆ>ÕˆRV•3Ê h9íJ6sÆ[Æk¦”+>E垯™¿CÈ€…ß±/”kC­j‰p¬óm*Ÿû¦¦Aá\Mb]Ûç «fSAk¡JΉub¬`Óå2£¦Ñ¶E›~RAØ-fuõÁ0S&f{žQ¸®r…»l–ßÌÄR<$ýMšü‚Ô-‰ö~#ñƒÚ‚bÊe2•f•y[…‚Æ…r³YŠÛ4¸]RÑ/kK1Ï<\-Ù…»%»°h‰
»ðÝ£˜k2ìA¦ÔjQ’±ýÄé«—äÜa!¬ûÒûÆK%¤°²IJbÅèn‹¤ù&»Ö9:¦B)Ò o8¤p~5©#9ñ‹%GÈQ± ’t»§I8DNw¹KDø[~(ÍöJ¡Ý¦ä;qF6§ïå©‹\ÊÏ¢4¼Mƒ·yp“¯xé*	‹™µBst5ÿ—™µìŸR
î8ößÊ¥U4á†83\N*~ûÊZNÂ<ƒm¥|2/•uL‚Ãá5 ïغ‹sUæs†ïMe:MŠZ3†Ôår=qU·KˆqlûÜ€µ몿И¶A$ä´}Áqû‘>›÷8‘uJÕãSn(¾Eàç]G¶è\²È’>Ü,6‹…Þ¶ä‹‚Þ\½5Ù‡[V‹RqÏ«tYâ@O¸ŸÅ¯êŠe^OÈ[•½/”–‰ÕSw8D³OØCcYð©^Šñ&vOD»³Ú¾ÕÁJÙÅJ ²ûw•O1/EÒeSÖù¾ˆv—Úu–²L¹ì®‰‘Àì&âcÁ,r+ê²Ëݤ¥LB™?ŸKXˆ?«°º¥l^"ꕼ‚!ØR‚“ưG(š°^¤+5  Mu‡•ë¹À@hDê×Ò23PÖiNxׄKåˆï"7!žZ@”½Q°ÂÄç–Kðâ­"®ÕY#Áž¦d³Åó/RÍatLI+EmGã†ël›ôu†ó"Wßf~ý#<©oqôꇬåÜud—ò…ÂNÊ÷Ñ“ðþJïÈmǤz3xsÝ»~Ö;À:oäfЬóæU|V·
"œî‹^¨Ã݈‡[Xl³A¯LU‚´í\hœ‰›rÿóY(rê/s?“ˆmÖ^6/—^ÿȹKP:Úeå·fõ‰eŽVƒ`æŒéz0ŽŽFi““<ÄDK!`ņ$Ú€ñ‡É¦žT7M’ÿ¤¯B¤äÛW³È9IÌ÷㋯ù}†Å”ãÌò´?¬HMÄQ‹æÙûèÈ$îGÐbZ"‹ÐMy.—»ªðÿUj#*ÙÏQc´)ÿ¿#mQ•N(Q`lkâ´Ë‡ÉF¥×=
‰oË-3ÂÔàQ1¢ß	Š|Ú0Iäɇš==N­–f
³l¡ŽŠO¢Ò6Ä0JÛÉ6|()j¦ùIe¶À	IäÖ•±u’2µþNïÌäNÌâ)2¾ã–Å‚ùñµ6&îyÑt¬ï„žpªk<àfÔ…=O%]4ܱãêKf-pcÒX7qäFøÂÆ×™Z~
és"ÉkÎ\.¸B‹µ¹ìŠºX0”²#Y+žyÆn®[¬I|`ÕlÏ&Çù;ýñ¢É‹Þ¯êÂaúgà×Ê–¸º­ ÷ߊ7Òä­.zLÞ%›	ˆÔü÷_„‚¤ë õ•Lº¬³°ÓåÌ#(~ækS¦©b)Mô–ùȱ/(ž{Sï‹:ÍË÷J:0«$]§«EœÎQÚíÔ
Ïxî(ñj $nÐr8äñ¼Øpm‚ôE-)[»ØÒ¡©ú1u§`y`nûļW5®úÈ&ïñ¡Jààæÿ"Ï={,†hâô,täÌB[ê6X *•»•—8“ÝþIc/Æ6×PÙýÄž‘
ÀÉTu\ìxîçNµ–úS4¢ŠF¸ë¸BëÍnÒ:Í?H•öN“…Åäª
“k¬îÑÌyNÖ­Y’Ã{>Ó1¤¿`û$!w©Çi5E)5hz*=†
mÞCy—ïî'ËEÑY˜ï«Èfª]>2øºÜzt‡ìvéRÞT]èM=¬¶¬Wïê7Õ·.³M(Žðnñ­ÍMJ¿j‘&#ÌÏÎNþÿþ
Cendstream
endobj
398 0 obj
4104
endobj
402 0 obj
<>
stream
xœÕ[[oÝÆî³ÐqÞzhäPÜÉe€H\Q‘:‰«¢h“4ÐÅ‘RÉ’-YvÜ_ß™ÙY^ŽŽ|y(K¹Ü™ùæÂW«¦6«þ¥ß'/ööŸõ«³Û½fu¶÷jÏàÃUúuòbõåaàL¼SÍ`V‡¿ìÑ›fÕÛUï|ÝØÕዽÖmÕ®ëÊ®þÞôa¨‡Ð­ÿoV¿>¨6výMµ1õ0?ÐßøäŸÕÆÙ>Þvëg•ƒçά¿…'åËOã_OàâoÕ¦ûéð/‘2c5e¾íë&DâO#A]$d¨Zh½¸I#7®©{3ôB[¹¹YM[]Üeš_¿„—‘ž_ãÿ×@wÛ®â¥ïpã·@éëÊ­oªM‹ã®à¥³8ÂuuÓôë“ʯ¯#‘W½MÃ*5š/âxÓ|ÙGÊã¥Z‰é¸ÍÌ’\$Á
¿À`‹â´°Æ‹HŒŽ<„܇C~\WpaЗ6­_¿‹sÓ®a% 怕á|êzg³ëß3gžÓFÀù5×6ø:ôóVdßÀŸ-NÁ¼‚™ïˆ!Öêù®_MÇ‹Ï§û„}ù$œ+˜HL&¸¸g~Y¬ä§=cúžøþøаSv—‡%fÁ–7¶wu·ÚW· V¸qÍ¡ÄûÈ?‹’t¸ñ‹ÊYúÛv},šón8h	mÛ ~¼¨,8oÔqMtv¶Ã‘f¢oðªO„‚ÙòêåSËk)ÚIdÓ.¯Ó‘3¡¶Î\;:sÅáñC‡'&ß…y†#©ÎeÑ6&
n‰¡§ùdíW-Û.{‚BÕà5:wcÑ
 …èk}hј£/é&þâ9‘?„ï1‰¢–×ôCÏbi ½:U8‡…t–ˆj̪'ž—(3JºÂˆ_“›ZžíXf‚qinw!~ü–X§Go˜×Ù+v!wÎ'·N»-ŒRC¢RðP9e¼ÅÚ[µíÄh:ð€¶aåè'Bˆ~³wøè‡l;Ҭɂ8gQÍ
’†Ú„š…±üª·Ñ&û«s”×µé|gp÷@“äÞ˜_T¬að^ ½ëÇð‹@ÍÆøVë¢Z®E)ÆáñÍ€oþ"ÄâqÔSÏk6pŸOç	¶µqèàÒìöÜàÄidÄ}1¹BqñO‡2PÂב†"®¤a¢Oì>ÒˆPma•Ú	6²DEÖ6\짦ÕZWMë@ã#¸8çÇô7Ê||ôà™ˆð7¬
€Á¸c.\’Œu0@,JžX4`«ÅÌ–,ºfxØå®#øÍ¶ôŒÏïe¸2S§…Õ
.¢4TØH@žH±±în‰›DóÓ&H‘—–E{h¬þtl—£bL’NÆtãP*¾TZ‘?BàÀÜ¢ÌÆ‘RBw	^¼a§‰³†À«$­ý%½	¨Lì-ºóþ	h	È,ð×=--Ú©|¹²L‰(FÖBæb™äTÁ=RëEB
œqfcÅŒüi¶b)§ÀÌC¤	ÔD+›ãçŒÌÒ±‰ñî,Dgaj(_ª Å[E1ù[⨗÷Û´ò`¦Ä´;¸[öqΛP>`©±#–ÉAˆ3Yd’e¿Ä3àé×R!¢Ï&‰Tm0u!`H9¥ª×:ghÔ(ƒv㜴–j¨ã	årg¨M‘tTÔ·•
4£(åee5Z(³‘δcP?)ýŽœâƒIì(GÖôˆ‹›iæ!§ûy•²¦³GJ(7£#ƒ‚xWœÑ+Ôm·þ~øñ“üy\¤ˆ/ ùíбàÜéL€þ­ÿ˜É÷òè'¹úŒ’ Úl~Íï\Vºî‘nZ¹Yç›ÅëÓÓ|k a°{¿…ò©O9˜GÊôþ̃,㘨âæ(n¸äî7g3Ã?ùB™á6Þ…Âm‰ÙŒ˜ú(¨Ö)4Ûõ.8QJ¿”]>-߬9éÏÏË
]`}P
tó¾3ÑÍ…juàd£	—ru·S¹ú°
‡œ©£Õ›œšL™÷âXˆJBë¿o¡¦Ó4]›ë	’]Â	Sç+ÝÌœ1¡ÑIÙúŠM-›ŽyNƦ(€ò2˜2X\ÝæŠ.z‘âšãJæ¢d†þ¯}ihâ¤rwÀdŽÓHüœ
r°|™Ó83ÁˆòY>ÀKíL¼ƒÌæ Ðélv¨ˆ´‹œOYºašnEs®t1ºÀ#;*ÎO4	ÝvWj“%'¸“F#wÖ*ýÑ«–j3½r„¬çôÊœè4®àÜ`±Ö1Ï9›ÙƬöã¤Xñ-Q,Èt{
Áà2ZPòR“s°¡™”:	m1¿’K®³àÁ5¡dX¬$Q_¬h	¯ýYî=×Ö7áî~@ƒ‘¼%˜¹ÁÈØaMjGͰÞë¹f¦¨
LFös˜ù”f>Î|÷$=Ÿ3ÃÀ§& 	{tïüºÝd»AÏÀiŠñO±”ðJíŒ9‰¸ÛùQq“/ï[F,j¤þš^÷ÃFÓ§:
ÜØ^9”)÷›Rî'S‘£ïQä‘)÷ˆûfN'ï-nCÕÀGs/Í-z:‘g\ôSÈ3‡æ3Ágµ&DPãG¡ÿŒ`ûùÜBQAñ´…µ·½U°‹::™|X}\—瓊0Oš‡XyÛ£mN>s”ò*æX§Pø
Ff›•¦V(Ììƒc¥ÏÕA,ü,ÙÝlcFSEíi”êhuµ=§~¬! ŠrýnäØŽ&!åPíL¹‡ëÃ3ÞÕ7^WÓ\tRaa¢JoŒÅ±TV=.êq}3›PõÒHù€”Ûà_ ,ìvñ Qeæj­
L9™`6SS—“ÒFl–R¾®Ú2Ÿ7Egà’é˜É‰T…Ø1à{œõä«*õ(H¿-`ån ݦÝà“oWv˜Ø½ &ÜàÔ>3„M-ŒÙÐà»s¨6Inª¯ð2¹#ÜM‰1whTP7f&{ã¥Á	jBg/5Íh[Q|X8·Pjm[ÈôˆF
^„ûÄÅ©Z—†)
à7ebki†ën4^é¥Î?éî<¥ª6—
mnÆa¥¢Y$y@F-màãVöÐÚaMÀ.X;î5ŒÌÒÂóÄå¢#c•˜1£q÷fâA	ÌHƒ’FCé—aµM±eâ½ÈÀš²~¨s¦Ó¤A?tÊ>¸Æì(UÍÖØN‹²Í%gMjf  HZ†'“p‡ŒÖ¯ÿK
†ZY®“B
tØ„+~{õ®¬ãÄ)È-å¼§›`-ìfÈÇ~Zµ¶Üã6¾ªÐžç
µI¡pÛ¥óÛ%3ƒ.þQ2¡;•×b¸*Ú–eÑÜþ‘]È@ÀÕÄ?á“a–ã@!7ƒéâ¯UÅÞõPŸH)÷v‚ÍVÅ¢bFÛS—âSòzñðEÅ`õ**a}A¶z 6bªbÌ´’n©Rss÷º4|>ç‹‹H»];dèlKù¸D{isv8§rD
afS&Ì+˜6w¥fØ,*tšz7¢›ÍÃô]éÔ“0¹#|X0T¼ô2ЧC£0v‘ÚQ
sl¿fõǤ?´™›.25w(fÂÁWÖŠaÏ60Bdv#x;M—±ÉqKÔ.ÐébŽ}T ®ò9›´ÿÒî\ê†Æ3
Qœt–D
zšraWFBÊeÏ;>[)•V´‡ªŒ­jZVŒ9w’Ædr…äo)èúJ¸?ãþP†)€[IúþæxþÌIÜ\j£‘075µ@nÐj…åKÂ-*÷´ŒT(VX…
úT9ÅÙØ[^´dRÍŸ²H	k÷Ó¾)ájþOÉb1I&AüÒ’a(>-’´©
|„õ'TsÉà9¸YxîüUXâF×]G%§—›T%WJß#ë…£ï*n&¸”¬—4*ˆ?L÷.R!?YNxå¬âlë‚^ýÐÜæÿM²+—û–s]9mvÊu}Wa‚Ù¶Y±%mÒ}s_Ö²R»2¸u±”
¯ÕÒ4T'A•WHè<œ‚,Tãàä×S3ÞìëËð€ìc[w’áâÍt /v o&U+ÚÚb–í)N™¢z\;C+nB•Ýô)‚Þ:ýCš·"ÚpÝÈ·Î|àºa÷ʦIÊöOe,:©ßìg[Ú5ÊÍÙWùh—Ý_ߦÀ}ìSÆm„·$º@±ª³.d³úÚ»Aç³²‹C¦ôeª†ŠµX-Ýß$‘•gÈOU}V‚ÕY]×cêõþ¦SÞs鈿®R>?tšôEÔiç}
ø`®¬þ&%¬;•uòayXJ5g«Ò÷?[>ÙY*õcYþæ*{ÿQ[•íD992×1ÕŒæ?¢x%h¦ûZjcÓÌ;[ÿÆ ‚RýPŒ)63ÅTÕ}5ínÙ¥²v¦1Å}d±Nzm$r¥†°¢5SÅv†Jçd’x#cÀÎÀ‹¥é°Ñ³ÿDõYnLÛÛÜ·úl“Y&)s_UpÏK’¸©ðýà–Âw³Åb
¸jÄø™×÷{ÿè;“”endstream
endobj
403 0 obj
4340
endobj
407 0 obj
<>
stream
xœí[[oÉ~÷¯°òÂàœ¾ÍôD"RØÝd‰È²aiW!ŠˆmÛ\þ}êÒUÝ=—ã1ÂyЇsúZ]]]ßWÕÍ»Ãvg[ü“þ=>?øæixöá =<;xw`¨ò0ýs|~øð%»¡ÌáÑ‹îi{{Ø;¿kíáÑùÁ?6}6mþyôèáLÕ£ïv6B§£høm³õ›³†è‡Í»ù©ÙÚÍ–ßl¥âi³uÎìÚ¶ß{×lû>BÛ_7ÎRÙgPÍæ·ÆЮ›KþÕh+è7¶=†¿eƒnsçïêVW
*ؘÍGlÅø3ºÍþ~Ê¢/g,:šˆöHÂCEØ|j‰ÚÑJÞ@·Rk­øÙFúa‹lr $REûá”:Åiƒê¶1î:Q.IΓÀ‘ôsܸlÁ;–IµŽ_@
iû¯Ô>Oµ•ìQëoQnóíf‚±ª>g0賆–M“ã$¹wÂbGSÌŒÛpŽV¦ì<~JrÑØû,®}kû~çìáB@#%$Y/³Ø¥dip„=è¦S"£“·-;ì%;g>Š«ìËø¬]œdhÏhâKümi¬=–Ðz’([‚˜¨¶*4CãÒ<‘Ìd€v[éhȪÝ$pq0K íÄå¼Ãå|¡ßà`ž»b»HùbY—Øâ7w@ 8¾¥ññ'l¹ˆ†ç¨í¨a¶——jåžòˆmGVžçŽÁ‘hÜ5@òòiI‰¾Ò¡Œžéob±lJi½dKaˆ¼ll‹ÇÑ[2çÒ3È´è’¨üBüÕ	lÜN±ÿÒ	•F&@6»Øãú TGäÁ³M¦&à¡n¡²zY#ú•%ÿRÀË‚šž†ž5犉.Ó’
ñlÕ94ˆÌT{lÓL C${ÅM@“òým.Ðáô¸3aÁœ’
G+~«øUX®ÎötoâÏvMÁÎU èlÜ93
:õ>¯`Z3NÌ@«ÅUp
Ê@À:üþ|‹xÈãR--Œk?icj‚»€k¢&>2b}SÙ–¦á¦/²þßjá‡\˜=ÖB:õð½>à”¶¸É[2\–5®†¼«mt)ÜMÝBhÙ)þ…]ζÔê®~Êbç–oráG-<Í…4_$åký˹‘Þ'ÉàpÜÑ
™9Ö‡s:ç…^é·ûyôWZx‘ûFrwn£®ÊÝŸ~Ì…©@!p±©ú|ÙÑ.ƒåúNvÙ€_j8\M›/3ª£÷«·p‹ÇìR¼ëQz,õ­)M“¸´RÇ.ä36fD¦“£P{^n`(©y]:2Eö($^ÃêÐôèšü”‚jȣ͒ƒ¾+ɃiÜÅŠ¤Í‘PïÙM‡·pL	¼gÒ¿à
½»7ô6…&p<Ö@#­*ÖÂáÁÖÆø×ˆ†]ˆ¦Ë³âñ@ØÞ­bU¶hà?fM:Z	³6k¶EG¿!ôÚÎ#^½3(÷$jŠØ{¨ý«m–6Ë6dw]GìtÜx%oÑ}ñV²&L!õóZy(\D`š 0­¬̤½A©ÀµýŠ$®LS<ÑÀ6Ñ/^]
<ŒÛÍcüÀoóòC}ÿµááÉçE&‘ªCtÎ=ûÓÒ/‘JÎ'›•1v(mXË\Ž„Ñè 7{Ø|št%7cýÇÚ»1
#_hcO&'–*¹ˆQ€4®LzÙhRMî$\ËhTžww¯
mdâÞÏÞ«à(	;a:	 ®æŒ&'/Žº.Ž`)OéÉ
‹AmbÓ³Ô<Ç‹¢ëûL˶i!h8Þ‹óI;ê<;¸Ld9rÊÓÙĀмCèñÖ0îÑá£âЛ@#´`ŒÛ,üÅïXå™WIUH½ú¢IÑ›¬SÊSè?ÒÖb´ö£zž?§‚ßõ]ðȸqpZ—¦w©s:k²eKäéèÅè‡~‘ÛkÈñ¹2Ê×5/ÖŸÜ9Cdrl˜’Lnžg@z_—#-1b·‚_Êš”»ñêÛ­inf¸‘	s^Ôç9zø|Nê¼hØk?p¼–Yîå#­)%Qc¾k©ñ-ÒñÛTêk/äx	çYÈ?Â2z(®ª¥”)(n¬ó#ó˜
q&{¿&Xºý !RÖŽ¾Î†Áì:Žtœ1^0·/ØhS8h–ÈÌ(yfJ8>¯€žšè¥Šÿƒ¾?¹{ÁÆ5ü“S±â±¥µDNée÷^çÚùãçä-¿‡C2ÒúÁˆú—¨ÄÁœ#%n0Ý‹\ ÅPd©`S^ôý1ãï˜s”@·¬Ò·e˜@áØ(õZdoeh¤ï—bΜÉëËHÂ蔣±±JÙMgÊ`¯µ	ê
œI3	4„Ù¤Ô“e\ùw&zeÀH^d®ªdœër–=FÌV!™±Á-ä—'¸¿”'ÓðoÁRRí\Û¯²Sßg£šÚ)¥ÇÀíî§!‰kÔìéõ/lbm¿ëôL?ª™ü”—Â7²q¼õíÛ¼Š¹”'°ih¹†
hÕÈ4c!ÿV`GNéÒo7`44%Ýàl^G32£(ÀeåWÑŒkos<â½Ò“K]»2†^U5ƒ*UÎQêßÌHÅEf2|7e¯ç†þÜÌ…õÔè«bhAs¾jæÍÞJæÍ÷	I57&N9ÇDV’Á¾§œZ‹•¾‹û°Ò®Î>è"t¿zúº€ 	"¡;"¤g—3AH\‰¬–ìh•&œ²zZÖÖN.#™ûÙ]TÅÏáRøV&¹ÔEŒœZÊ᡺n?ÁcN¸êzø´Ö+f"<^ùúÒÔò¦¾¾+	Ä(GIG[§è-}‚ãa˜‡¸Éõ—u}È6Aý^@¶db‘€[H/‹‡Sy}‘{ً̘Ý4yþ{øÕÓâ!‹GÅC‘_å-ËÔä@ìàAÝ#úk;_Àjx3ï½¾:_HYvïé¯ƒà‹µ¸rÝÝW½¦Ä}R©õR®³ÀÃýqà:àË!b6绩êÆI€ïÿ8¼‡óÝ-â°»‡¿#xÔ”à®H”ž³©Ø¢fFŽRÐõDœVÒ%™úØŽ’äiŠdµtœ¸Pº¢´7ÝK­
¨-ðÀå4¶yã»|%‡”ÀÌá3Ø–ñ™³Óf熡„àØC³¦¤€\’ “¦Ã˜Û.b--Ñ~ѽ	+ÐïRáok1§T;˜ÅçJÔ¼À[yУ÷ERzd{ü†o„Ò›1r¹¦%jTž-ÇŠVüŒÕùôp
Ÿ *™¼’ãeç÷0òÊ8,ú"Ï„à„àÏÇÙ¤ְ‹ÇŸ¨WÐH2?ª¼Ã¸ŠÏ}ù|½¦q:Í/Íx–4Ú‹Ò§¦nøäÇÉÍ@ˆ…ÝŒŒnÝK:Ç7(7yyR¸þ>$)¡&yã 6œt×£·<.ð¥;Ýò<®6ËÄš÷\êð8"ØÈèb澕îãÞ¤[PÊ×É%Æà2=+¼dª¼Ñ‹ôŠà÷ǯ	ÀÉ-ÝS˜€×q}…9Sâr5M Aù•üäg?+ñœ”ý§¹„·‹DÆ»›?â©yžmWð¦ð£4÷Jjq2îŸ+k˜½@ 1ü/ÞѬK‰/Çòþ8D{)‡0üfôÚÃ
¤bÞç{»ßçóÆ+Ó°m™™G¡fÈáÌHŠU¼Äú}œÄbÜÇIÉP\[^CL¼º^ž—)…—9^DZ)埀OCtϨ·`vè(×Y9õÅw1à—b?Úsì¦ÉîÈ[9goøó¼q­¾åt}—ŽÞªnÛ	·“¯{do$xõ ~Ž{êMÐ4«sÆc U¾¨Ü¾3èEªg¬é}B[rj%¹Á¦ÖZ…~Lø¹2Â5¥ß²­MŸGøÖ’¤ò´?qX^ÿ_Ï£@4áàT7üøJ=“²ùÎi
5ù>
stream
xœµ[[SÜÈ~§öGð8“bÛݾíéJ’°!À29{*ÅB$²Kåß©oRÛòx˜e+c÷E-©¥ORÛó÷zšdë)þsϮמTë÷kéúÅÚßk™é\wήןÏa€Ê %iÒ&[ŸX³3³õ*_¯”NÒ|}~½ößQ1.FÉ8Õæï¤ª›¤©ËÑ!4ÍÇ=ÚOòÑÎx’%MSëÆ>›ž“ñDå4«ÑÁXa¿ÊF{ØOÞ…§-¼™'åÿæ¿gYÎ9ÓE•¤507?†*`$v`©øÀ‰ÎëD¯OTšTYÓØñ°‚á2ÃË+¸$išV3¸˜!¿EÓŒ>äx©ðR†ñõxR¤µ‘çkh¼…F-MK6²R¨ÐS•ЈBd*)JÔöÎÚü‰cw/»Ž5Õ8q4	ŒexÑrå‘E¿†
Ý%5j.Œnê$ÍtK˜<5yh̤éUMquw§©»â
RF¢ÛIVþ¶ÜD`±ÜÝ•½Üi&ËMÒä4©‘(5’‚+>ÝÝ5=äÞÁË^,÷Ën¶e…&[h‚AÐbÆz•S‘_–ºÓ©%Ž-­cdâlÒÈÒª”[Èo$Gu9î“­;§”˜#Ž%›dw…¤™4šãn%Üšd
àVš åIU4u$=º¬½G„,ž>T»±mztíʶÁ¶Sè¼™›kÜ\õulÿBÒ¥àÛ¿Á4ä6­m»!}ËY¬ÊÜ
€eW¿ðQ94pbUi8Áq†Œa	0û™Y>¿…7–ÙÏ0ö›09@®#a­\aaø}*KÓÊRЕ¡pjt„šÎÁ…µj|H8÷úª"-Xr†¯¹ªrREeÌFREnQD…ALÇh#Ès0æˆödì̓†GÈ
l‰ëG9y³ÄÄO	QWryS&%VU£y\¡YÜàX.ÀòP Æö †{«”wøxa-É÷¾ƒ=7ØôþÄË7C×¥ÑöSãÆf;ôùÆUh¼¡Æˆ¨oü¿p|Ì¡£ø$DH”óÏòp†—K¼œ†ÉwNnãMÐóÝwƒ9NÈœÈ.šÃèÿX)¼èŒW¯Ç'À9õŸJ²ˆ‚€È„ïÞ ˜Ô§´.#¬ÿ}h¼ˆˆÚlE?€è½´S§Rã7j$«úsÜÂÃ\G–i¥2;áaxUŒ•„ YÈú OË"t.­šÌ…sE˜U§F²3˜€X„‡²^]Úƒ^‹†Û4,¸Àc @@;ÈÄ0]zðÂYçþáÎNO3ÆÈÁ­‡o3’è2C¯[‘yæÖžjÍHÑ›¼%#jQ¥*=:ÍÝSnŽ3±ËX7%$@W§¹7G¯.æ[ìÎŒ—8”€æ”ë‘ãÚ¥0˜áí‹øÿv¬êÑXËAŸÓ¾GÔ›îò)@¼¬…gn|1º·ºœèyèߦþ¹Di;4‹”¨b|FýÇùYh4ÓmÔ[eúÈÈ–Äè\Ò­¹Ù§Ò£‰g`ÍU²ý=Û¯!dLièkºekmÒØ(7™äŒ4EÓ„—Á4ö—‡Dn?4ÎDÖ©Ÿq&RŠN8J/mÌn¤—ø â88†8~&™ÄÙ²-.Úü’=oIî²Ùc¯6?®M&ì‰ä8[öJ”˜½MCãžÄÝ¥‘nüíݾ¡[‰–âR½ê4Zñ³ÈfÛ¸Ÿ§c_ÇS¢OéûeT=ðrÑ×à¡ÿ®§:ðÕ…ÆP›4‹ê#€|#í3²9éôÓ#
o;QäOŸª¤n0ýgŠ`µ­ßë¨öÆþ¤Ý•ܱÓhZkKMÞªy¿:IÊÏ%•‰;zÃGúH0d/‡¬1BkÞJV+¬[,'Qh‡Œ’VÆ/Eö©ƶí DûÈž·"û†Ê
¢ôVRKPöZóí™›%çRVÂäíÚòP>xŽ´oÁb7î^…©€?HÄÈ?õ{‘Ò*~/ïýŠ~?hHËø}ëÑ~Ål,`#ˆò1Z^Ô+; ,ˆ¾}ö£XI1ð	6«.¤ÆèÍ7Gº§Ï¦©Îro(O¥•gŸ¥õÄÃßK2úý‘ÛÒ¯Ì1­)Iñ}¶­UOƪÕ.èKWóµ{£mÕêß{IÌ ßÇ®îïdø”‘2+9–ëëuÊÅ<“á«Îô´bg¿I¹ÁD¢É^ëÌdæü®V=“¨oEÎâÙQÅ	o”¨›â4/“"Ne™oE3ò­V+`¬Å N>øeKÄJó·Ïi,ñ`ÏŽ¬Kž™Ÿx½	—þ³Rcªe1	«Ò%>µ‰‡Y’øÍß\2ši[Ù‰Ÿ9Ûú
%×ggòŸÈíႪ0é—½»²ëÓ´¡]ѽ»"~ ·-í
!Èg¸KúQëVÀ¶.‹—ô½îgj$m2¾ì‰öÃŽÇýb‹DÏ«$ËSå÷ê‘~äô)´ƒgAágóñþtüã)}å&þÚ‰(+³¢OE¼U3¯8“Ô$濲{"Mãlö”¶æk¿Ã¿ÿoÁêendstream
endobj
413 0 obj
3221
endobj
417 0 obj
<>
stream
xœå\YoÇÎ3£±oÞ1ÌÕô13=Àò©À‡lËðC)‘„%‘E+ú÷é:»zvfw%YF€À°DÍÑGUuÕW_Õð·U»q«þã¿OŸÝýaXßµ«ó£ßŽÞ\ñ_§ÏV÷æœÏW6c;ºÕÃ'Gô¦[
~5„¸iýêá³£®‡¦[û¦û×Ãä7‚«ÞúOù¥‡gùÁO›ã¸þªq›qLq\ÒøõƒæØ¯ÂõÏ›c¹ñCs‚Û´í°îòØ›æxR¾Ö÷šˆ¯ýØ÷ù¾÷ëûåµOáµ°Ó@3}Ñx¸“zxˆgí;ßåw|Ø´®£‡¾mðÁ<ÊØ#,ÊÃr`1¾Ï#:—nC^Dèp–ü/{x0ŸÇ	ùñ£‡ƒËýŸòZÚ¶ó—ÁuFœ&/­Ëï
ƒ'Iúh%yÌ¢<ífpãHuMX÷M &ÊR±?hò;ãè»õI–æ‹<Íú&|œ×ÜÆõË<ƈ…þ×–Ö4,¯/šíbÀÍ (Ößä>€g{|ö¼{™_xNJqùZž~J¦{§J9Ïw®_}Úx;õiVñU¾—oáþ³ü2ë1Ïè&®Ÿ€’p +Ù”y	“‚9àvEá:?¾b–mé\WM.XpOb¸=‚à²]àËW
È=´nÓõ"k\±ÎQÿÞÅ®¯õ"«$æËó¢±Ü8º<¨lîÂŽHb‹“©®Õ–pEt­²v‡ÁšjÖ1˜Kr>eUó¤°S\}ð«ã¬‚®‡Ó;>mÂ@‚BRƒ@—`^yC¸Iïñã&áz¥ƒ,þãZ_ÆkgùÚ˜—“·?¦I¼(l¸ÌZÃ7n`”¥¬ªy§@SúŒÃ—Ç`ðlº\çÑdÏd_ÆvcëÅžA„]#w øl78,Ì7¢'`›>ö‰uFˉë`œ®>¼V¸;7›–îŸç™Ka‹h`fäp<Š
ЮÇèíÃðœ§qµhi(¼õsM怳zVLN¶EŽÀ˜eõŒg›êÔ¦º1ÑVÙ$PóY|•‡Z'¬^ÄœzÝGB9j™¼PxëpÑ»µ×;¢Q–\DH£Â¢-’û‹rjK Û¦;[OÄsqV/Q\|äȠ¦bP{\!8Á%Û™x[Óö#¨C²q9` #8ÏÎ<>k0é`œn(‡÷¼
üOŠ3g²h1^Í™'OÃ6…Û¬ýÔ	Çøÿª	|_5^k„•Å®G[ú½é0vD}ñVt|ž¬E}ÈÚ"À!:Ū“è( è·d~EÅ‹~%.8”ür‡¡¥¶u«e°›31o@túÌC‘Š›¼•`ýöF±ÿšC`^³Â
‰u°Áh¬>nÖ²›~F¡<u>²Ùà2D?¢ñ?"sj‡"Ö| Îyšß	n¥PÛZÝŒ
‘ž»%Yßkxh=¼›Ú#‰E
_ Ã×2ˆÐf¥Dî*rŒRÑ×ÞM\8ŠÀ€58hA´qL{Á)Á“ûb=lA}ùaÓ0–ìC%óIÆÁdŠrB.a¥àvaôÎ8:Zù%_ÄÐÍÖóoøç#½‹ïÀpTA¤¡‡ñ]>0òHL@Žãúnž/£*¸Îhï‘^|^.–'‹£“Ë?@®øËæ<…?.d©Åûµ”^|¨ûÔµê34ù?ð÷²ê˹ªi`•„Ü­¯í	•‹§Özåâ™þô¸Ü†xðºup6W°™.žÃêGt0ÚÍmÏ>»¤“js|%2¾Õ̯ʓ—ôcFݰG3‹qöf¿ü,è»Û]&w?c̬ßUòISÙç­Þý¥ÉR(I›OJ>ßNÓ®?ÿ¤ðݧEOåøx<>ÞþèêO[ÇIÅûrœ¾Öûß•ûßêÅ/ËÅýOÒ˜éO;xòc}òäêGC;%EŒ‹gÉ?
šÌÜbBb·IaL“èTÈðTHt5[¢…¡BýÚÂgˆÙ2¶dØ¢<—}?—:kðDX­/AþŽÂ}Æ¥a.ë•1÷0+ÁŸÛˬ Yx—EïJ&AksšF@*52#cç»ÌÝ	ü7Ú}D@tŒø#ž•Þ G¡‹ïsÒÄïfäÚc"æ-¹qQ§ g2ÕœÖ÷­›Ø*3:š+¸sPvc†ž°©ä	eƒòÏr™æÁŽ£†Ž²>0ý6âñ°¦–ÉšZ©?$©­Ð}ÒXoÓº øS9‘)8˜ƒ¡lsܸnÜJ7`ÐàÎ*2̪œçu’
e(VŸR-|6,ñQåGÓôróÔwQk îœÝ¾*6uY3/rJ;¯c¦$ñn›Õ€Œu鈖HH‹n;|½RœðlR9*“Åši„@ž)ÿyÂ/gç÷ËI.*®«¢çÚ É½¸µ)•¦íñ6=:xà#·í‚™àIêùÜiÞ‘«B0JJBÃÆyg³Ð'´OÈ1ç, ˜
lbÂ?Åã†F]¹>hJ‚ª6´D‡³¸*â]02Ò¼9‹×^–ΰ²ÇíÜô	ä¶ärç8 Þ­ááŸr¾?îU¯Ð†çØù†4Gv°ØynÕïæ?˜X¢A”¡±4P#Û‘ÑWµJ×јܰ”Ôç2åB¤9v°r
Kª&eDÆøl‰;ÑõùáFÔÜaPØT^wíwÀ±@ˤÄ)©e©²2‚)ñ°;€U±ÖÑxŽ+ñRlf@÷‚ÏÇm*£Ä:óë¿€tê0Ž>8ò|{½
Ÿ¦àHËD‘«¶†nÓl#䯉ó)vÊT¢õ	#†9˜°BG…%Õ„u„ùZ®`Àï’1¦IѨvIl[§*Å!m¤²,¶©Te¦<…£
“²‰ØO¨‚¼ÓÁx­æöÐó;¶…‹2Qôf´ë@,6„GIgùSÙÌÇ
U’aÕ¸®”¥îæ@ÆÃn`ŸÃúgv²*“„d€ZÝ»lr?m]ø	9ç½Õe1v2ЉÅÓEŤ~Fk³QñN±…ç3·U•Ý$ÌÍ)ÔšïiuËÞ
ò–@+,qêg"Ñœª#3ˆ„v°ä“·×:ü,õ
õø/E-•j‰È&á²ñvѤ›×Mâ奉)]	\üÐb«„Fȃò4s1{‚P(hG¥áì¢á5K{;‚ˆ6˜EkHëFª¸){‡r3ï§ö=p4I2ó<$E§œ7¸ŠÜArŠ“ÕìÙïîuV}g¥ÌŠ#'khñXas§Í
r¯UŠEwÇѲ`%X,ãú¸p7œ»x€Gã(bÄö°îùÚ6Ãó	µ¢Oš±µ*,’õšh`QÒƒh
Í·©?Åë¦$¥Û8Yò®ü¸TVfO¨Íf(•½7hX —2PÖ¯ è¬ñÙÖTõ§\
¾eèamƒ
VRÉË~%ù02b×;}ÝÔã|è‰](+—ê]ߢ5Ù%‘/]\'E”%~0s"‘cŠS³÷Ë2o;“Kü²”’Ùs,R?à¾w±Ð¥4]ß"/1‚À±éßѱù,£ÄOyUÐŒ†qô®AÀ@Ð;ÔvvMTç¥d°‹j#À1ñ9HÛxÅÑoi/Ë•›Ð’¤)yßTk1jï6CŸò{iØ.?fa&¨Á¹QƒòcÚW~ĶtñàÚgR^òõ[®A)1Î@ûgÕ;T•ªsz4¾¯™:RÈšxõ	`'ôWñÛݺÀ¤Á¦N“ö”ñO^Â'¥0§FñL
¾e®ÁŒðˆPiM×™$Z‘ÚÌ+°^'¦XS¢¶2ƒ"yϽ·ÉÇYï[hŽ¥’jH‰Ý=ÝØP³ªœ|Åé…¤Pw§ùaÔ€§•¥¶Õ¯#ja‡ƒšm½òwG™[9ÒÅÒu´fƒýóØÉW
|¢<Wø Aà)*&}Æ(*ýu~€¡Ç7ïn„ö|ðX6åŸã·¨ªí³PÅ¢1Š_iƒâ+d2“¥Çú5
Y|ñ‰‘…ü
[‡qmc0;ÊMœíÒ¢ëˆÇ,+4A
¿~¢=¯‚>
stream
xœÍ\ûÅþýÂq¿±ƒ¼Ãôk¦)‘œò0G$:ßù%sgccÿ÷ézuW÷ÌìíFŠ{»=ý®ê¯¾ªêñϧCoNøÿ^\|ü`:}òúd8}ròó‰Á‡§üçâêôÏg©‚3©¤Ÿ‡Ùœž=>¡–æt²§“óý`OÏ®N¾ß….ìúÎî"þÝOqîç8î¾MEgÝÞï¾èöv÷U·7ý˜gô~?ãB·{>úa0f÷#ü|	çðñJžîÁÇÒ‚*cÙUnñSn–ªXØ´S©ŽŸÆTßî>NãÛǦöKµ'¹Pµ}š/s!,ܦﰾ½q}AT°Ðv0ô|<•™PëW¼ðÔåGyÍyòT§¬ŸÞKÓžczwJ­ÓŽÂ¶]äêOË,ëq†¹ŒÇq¨ðb£¦^æÂ{Ü|˜P4Tx]j*ù•îŸW[Í…ïªFË—•ëÑÓäýõÚ@çk…oJ!7ò.î~è*Á¶ª¿O'Ñ¡¤Ó§y"IãáI %»tŒ<¯ÇöÿMKÁ¹]uq!(]ÙŒ$ùǤ€iïq,½²Q©ƒs0VLkLÑ»FaaÝÀ‚ŒhZ¨O1œßp4ú>©KZ¦í­oõš‹0È`$šwŸ'¤K­`“²ÐßÁž¼‘§#ŠªÂ6[¨s-Öîª&C³Án"ûF
yUÈ+ÊÆkˆX~”QJ&, ÍÏ²Ž›pŒ5.ãËn[ƒ"¼ß‰Ng]û7T¹G’B?"ù5R–9wmNÚÜóJ\—¼¹ó¼û0M¿´øL¨ÄÊB1ÅtÎója#foktt`ï„Üë=¡1|ÐÆø–ÓáJ¤5´$TDXžÅëÂw.+ÞcŠ _=h¤wDn2ìps˜4J;€Õ…‘ðcÀ›ÌÆPˆ
@+> À…͵0KSÔ£9Îù4†‰¶Lɦ筲ý*ÚóXÃÝ·¼‡RM)2O¤IéÀfÝH'RÝÜ›LDáf¦£ï;£ÚØ9«QíeÑ`÷tÌ´]•ÑÔÄÁ(?i:v=”M'Æ„QÃæ7@@稈)<\cá–˜:êÔ©8„À O†‘ì1­›qa1Úð»èoîß"‚3 Ü
;ØB‘…HÚåÅyhÀÉ5¬™]åeV:œ-7¹Ϙ’½]»nú?/Ç’Ë,XD¼ Àâ9Ô3:‡ù0B¯‡
Úª˜ÇXà†Í­yàåocþ
K­ñi¹Óe“-I’öÊ.6‡±Œ%ü,@lƒÕx_ÈoÒ¨“u¦!–ˆF:lŸç-ú¢ù³Â¿_lÊÓPûTÙT/v NäŸN¨qàJÐ|2Vj­#YœO™ì¨U`dák»–.í·³
Ͱùš@ŸÑ+I.¸€,5™#)ì×Ùmšìð‚<÷8øÖ$×F‹pzÀ?‹SƈËeÏ‹™n°™é"`ØÉ6Ò¶Ñ´î­@%FÄ!Ë1íÁfóíО@G²i• nÞ	Hå€=hˆÄš2fG‹WvÐG¥9P5c(GI +÷FR•¢(£:»âÚy‡VmËøÔcuìtmÞ£¢“
“ÎËÊn¦ä•¥õ…©ŒÏ­Ô
oµ™ZP+ºVš.Ý-Yáàw¦¬‘
k?DÝêì.¹†0òk…B7QáK6N…!a™w„®…«=‡*ê0Fy$B€(?º$wŒú3ÍFLæS§Ö¼1-Q`˜$pPø‹ÙO˜pçé°^%ærhé©XýkÞµy3á1P;UüRE@=ršÄ“ÿþ¾(–¤Ë· YŒU¸äZ¯6Ü2¤)	¬ã™µa:p™9M:%žr‹Æ8|,Œ­»»É1±Â¿Ñß…Xû"OX¥1âe,ÏÐ3„(PåeE	Ÿ©DM̉G<¬(ã²Õ5t	"³ÙÞN$,jưs(Å4„VÆÃ"å}Œû-ŽÙj¬–8}:á§4U(¼TAÜ:s½NgN±iÀ­®²Ž,\ƒkâm6lt7½¯c;ØS°B>pT¨¬X„§û.P‡çïnÁÓ÷8ðT‰„™ø(¦ø„‹‚kÝ&«køœ`ÛEl‘
¥„¦5sê€3«ó½V}JÛØ|èì°ÛoÆ|”l>Ã
ùI3Z	l›˜+G7'´ÖÔÂB˜lMúé²{~ƒLoð¯]ÈD›Uù†CóA.Tç./k qÆ"÷š5a.ͼÆömVLB0cã—èËd^Ÿ«nf4ö6f
µÐs™1ZÈES΃Êš¹ØDlc5(ª¡çžoâ(Ò²×?0Ì1¸öË››:ÅuY¢Euøpô©jÍÄxé”BK“ËD‡í-ïí’ºdÉß“ø].;FôÂ`ôi¨lºº¦‘G
t:f¸qÔöÀåKâ¬âUª\Óœ‡Ë%J&Þx2^G¸Šk€»Sî‰^Ý_Ó«[—·.-dË£nårLÔ	{^ÈÍ)>œ÷P7ä"%\r´Zª›rX®³~‰Ôæö*_{§x£c¿vÑV:Æ5ÛÙg=qªñ¦¡…ËÙß”_„ëÛùE‰Úâ³nÝyÇT4þXš&ÌÅÏ›A¹àp½„	À;Et_ï¤xã~<¤UÀ׺x—©Á”8”(æò4Æ~ë2k(ï¾èé¶B¦tcÉ%пÛ-»HaZŸ*U*
˜iÅ¢¦Ó¸2I £V )yТ?[«Qæ×Qq¹ô~~åAø§8ZËø7‚,‚Þv®Y_ŠÁEWIíeòú–×ÚwS*ÃÉf®6ŠfÍQBMjÚ¯2“ë2PãES‚¶êœWaúÙÔ<Þß¶âbŒYh_(uÌ´¶ê:ròÎAD¼E/zÛVùƒ2æ]"²tc*ôÆ61µEЪ	Jä·q¦Í¨¿ŸrØ©î€ÓôjHÙ;;}•“Wtªvàà*æâ•àµõE§Ñé¸é±·‚_. ÕPSÁE Ó	ØŸ…{Y„é['Íg'm?¿F'ú
gÃû
Åãë§·ÄÈ´%#H{„?+à‰½ÕE›Žêõ(uŸoç÷w@LÈžðïÁÌ¥v~é©yGÙ&OUKxÞɹ@hwÕ;«ürqz:cÂØl¾žZXº‚årjYX^~U/Ÿ¯–!_TD…°Ð|ÖòÛ\®ù öUY°‰UϤï;þÿut¸w¼¯8ù›› aò›SÓ<¸Í~ä}㪣æù­«Â 3z‰,éföxîÔ%a·³r©§À0ê‹Mù.R’¥²guÜ©°+çUÞ./gE½Æþ¨¼ßý|­ûw¹ð­Žï¬¿Ñðõ/Àf¼rTŸâ¿г»}Ì쇫½ò>þMQ‘(5þ«"‘úýuœõŒ/PQ¿½_¿ò/=¼Z”FtØt¿R÷Ñb|ëËÏt'\ËcX%X|¼ ¥÷ËW2(Þ:•aù´Ñ%±ØÖwUH†›!´Ãûx½¦oמo
ÅüdM!~ÝPg’GóïÈœoþ·–…kJøh­Š/¥¦e_tDUˆ2?ÓÊ’K·d™u¤ˆü%ÍÏÎNþ™þûÄ—·endstream
endobj
423 0 obj
4361
endobj
427 0 obj
<>
stream
xœå[Ys·~gùG°*Ú‰µ£sÄ•[GÙŽ%9s¸l?P¤E2â.i‘”ät7ݘÁ.)‰N§TZîbp4º?ô…žŸw›ºÝmà_ü{°Ú¹÷¬ß=ºØivv~Þiñánüs°Úýb/thMh©Çflw÷^îÐÈv·7»½uucv÷V;ß/úÊ/\åÜû:Œ°m6¢ïj3„A{‡¡ãýjé_Vm=ŽƒŸWfñmµ4‹=hX-ùÁ³jim[7M¿ðaîºZöýžÙÅ•ÃaÏ«ež³øJ†Ý‡a¶‡žVzTx2tÐ)®õ˜§aŒ±uÓzêô¤ÂŽa–±G Ê9@ŒéÂŒm:76a=®~µ®ƒŽÖš0
Ý-Ìn˜œŸÿ-ÐÒ4Þ´HFlL+â24Æõ½!NvVsr	+V.mS÷í8G—aÙEödF_éaòvñS˜2îþ´Ôx©}3"·¥ñXzÂóvDö¿*ÍôKj|+g©ñµ4ÂJ
èmz~R¢),ïM³™¦“Ôx©oÝb÷¥ç*Ûgœó¥<Ñ_]Ü*[Ÿ;L˜[K³øuO&{.“å3ð×}é{Xì ˆ¬S_@‰¯û®i»Ý¥éë6¡¢!@À¼qïç2ÁyI†ÂºÃ›£á~zþ¹<–ȶ/Rãe¶©9„£!gqÎ íë¨{”žçR‰·""Ðë
¼d
ÛÍÈQì]ív—áhûÔ)HïöÙ¡æ›Z_È‚u©ç¥0StZ`Î6A’¢Þ=ìZ-ÿnÃqžkƒ»…³’ŽETåCó6[Šû^三Zä*;*Š«uüpk@1=«áQäçQ-E%]<±¯Kšû³
Ö„á(ª{qANK>(5^–Æ ] Y9”¯7Ÿ)>3,ÆîC{#?0™²¢;-b²Î,Ë4&[vø€RLü3D(=®,ÅXßÀ‡Š±bÕ6ÃâO
aŒt,@|&D%ƒ’mà‡TüV:߀“ðk-ƒ‚çf]~tØŸ†Éz‚
Ûy®+x~!Ô]VJÇ„Ãá¥Hr$ó7•‡p¯ë°¯8u´ËÒçð‹ŽZOÕ”N[)ì|Jçml‚bŽŒ-“1l¦[ñ%DªG•‡gÁl€þ\/ÇyƇþƒˆó+àûøK°ø»vº-ˆ•ÍpnðÔÝ#¥Žá‚˜Š!ÿÝN<n<©ÊÖz®OŽJ¯?P©ýjd×
}e҃Ϙ)¾Ò~;ø¨Ó¤]•ï0T¯¦ÃHý&&6žÛ¼õEÇ&öeICÉ~öK<Üù(-yV¢ªàAWîUÑxü"Šå=(pXüpÆâHŸá'§ ,˜$â5qÝǘ'ì×ÀGL˜	œW@ýxç·"€[råsÒØ•]NåÍœeÃ MëÆpxXŸ­eÐe¶Á‚ÿ{-mkô¬¹Íß ̆A_™ýàH ÄÎBütBø‚
ª)øÉjì	þžh¾›ª<Ï yQòY	I?•´þu”\2êYf`ûæ6‹ÛÏþé¿™˜N3|Îé}uýY|]ȡ޺x,V%
‘œIÐ3”ŸoR¥-û‘hUØñèaŠEÅð§äˆ%»ÿ6þÖ¾þiW0#?8.m¾K[NL¼·âýÈôÞm°W™l`㶇ßÉ­–M}êdºîPoäѳg.aË022j°ß3/fÊ7²ÂÌœ‹O_}´ïjÿOl|U©ßš%æ›M–™UÐUa˜sk+_³Òú)º	®	<4ì&ÜÉ[|˜[¦?ãYÎV'8_&uš£ÛÞ&“²1`¶xˆgOI@ÌÖyÆm.åvU¯¢ìUø/Ñ2Yö×å}¤çêEœá‡r0>§~){T%:Ée箿+á®4us™§’çùíI3^+â'%?ÎD)»…Ì';+å–JÍ~‘—Ò_‹Fx(=ïgÀœúênzy¥`õ$Áêq„íÔcŠ9>¾Î‡id!eFŒË2#ÖÕÒãK3ÖÃд´¢© ¬´¥ÜX›*öª2E~„’JXa>ÒG1Ó;hxb&éUe
扂@@ÌDð¥ !†S„<åƒ0ãSM\k4–œ20¯7’1:“ÅÔº)qÇÈyœ <¿ƒk2ë)xÁ]Tn
º`n¬Ç.găš“1—D:¤ì`ï)I–eÄ.	Sl}
1Ãxxè¨ñûV§ÄâJÁ,§ëÔªB¬c5È60ê–£ìÒs%].SÁGžycæ7>ÍâÖj\•H¢UšVzžRâniÛ¶öS?eIÁÕI€¨Á.¥+!Ÿ6¶7yB˜OÛ¶D}®îÜ:ý3£•…¼Y‹W@;]üzC€Ÿ¸(~dôv|=D{Hý2~aŸ„¦¤TÓ`Ê´ZÉ´ñœjƯ2Õ.r³ƒÈv­IGF(€øZŒJÒá츶Ãi²Àm÷çñàZ”IUAq]Fá•B-iG¹z49瑼é•e
“9ß×±RÅ
ÖW0;ññEÍââÁñ&ãþô³¤g˜Æ#N–:³ÈpY`ÌÐjÑ:çjºÚq‚jÉúƒ
‚^ºnˆŽ:®¬	ÁÁqP7D¸ßñ¡-Ö8r•Mkj—”|âŽð9ÊO¤M×aîQ_5é«Àe"äD1èL7ÜiQu ݹêØRÛýÜz á°™@õõÇŠB7°$EHÏæÒƒ–õäæïy"J@EwÔÊ­i6ªÐ™‚'Ó;ÉömÖJüS1XœÏ¨€AU”,#Ì9™5ë>é•a¨MR, 2 tÀóSÈlpd¥S«nÿDuk+ï s;ìׯinÈ#HñªŒd»ëj¨òÜ`q×Ó¢˜±M´¸gyÅMƒï9 ÏO2‡É%(I·‚Ö¸xLr¬Ð
ãh…	pMšƒ®÷Eä?¦¦ÊŽÁ]:JÚt,~XTâÆ›ÅPÑ+ZpÏM¦nSd¼q'û9H$šsÁMÒäÓ¶“"–pº‡È¶
b~¢ —;£€ãÁmZºÚͼ¥ˆÜgŽ4ïÔ5Eñ	üV>
Kjt¨ç?á8ÐêHÜXßÛ%£ÒØ’ZŠÔJ@(ó€I2¢
á`Œ\‰´Uî®%ÛiÄIˆJÅad²Í]‰§)†¹9"j‡¤is»;Á*lƒM˜q­@jËÑÆ=4¬³Šú…ä’®Æ]º¿Ê´ÐØ¢Šzv:ëNæ5CŠt´±ÀŠdÜÏ)ž0í!·g.xUÎõÀÑû±X åÕX§°–*y&°ðXüø.•+:ÿ¡˜¤²¦°)ÇÙ;%Jöü|‡çZ-Bá&=S5§û˜]ePiÚ¹²èãÁ
ŒÁL][GÐûº€
Û]ˆ%Ä"µ7¶¬¿3È”"0y˜µ.ƒ¯.SGü¶Ö1ÌTÞ0ZÓf\´X²‘A¤æz%õ¦Bóâ,û૯TôDÞJ7fÎ2v8uÃgéŒïæ‘V2ÔÀ–±ÏVíÜH0Ñw5]ê+*†”Sf´ÍÃïlÞÉ3ž¸uâ·DÒ%ãÙ1-¦¼‘É™l”Þ‚&ðFEÚD/ÀöÑlôA©ýâðõ£~‘áy$„ÂÏ÷6;ÊA²=Y—·Åp>SjÊòÄ]åªD;«³(£X~”Ç›øÃ1•ЕÒÖ¦{ˆä~œÂIö]c@眭Òõ)"3ó£SRFù¹û©ìHÙ2Џ‡ºëG3'jƒ‹´ÈÞ%”ÄÔOžŸ3VL²íé¶”¯¹gEh?¸T'f’µ”K;O•ÏÂyl´%ä$EÖ]—íRŽΡMBIdp…íú^&²¹)¢?Vú0<Ú.`ÓÒ6C¦kcv®ñê},M:#rTºN¼TÃm¾eXbPe@žßIPÂ5§ÜáÜÍ-¨˜+ü>–÷ýXÑ÷&Lßﲩ¡­Mó-Ê£Zsú¤g¶$ñГÍÑéJ×¹$ötí(òâü.)‘Òˆƒ%—'%~{‰Ðq8âöV0Ü»‘ùqýXs2.‘h3Á&Ïc,£ÅàÖ*LP$Nb¯IV0›*kÇk" aï›Úzø9—[Ü	½uÁ;Qþ¨” Ç̦™XiHÃ
›8F‡ÚE~ÆB¬÷qt#áóK,GŸ::ÙcWhCÍ":a¦bR´œê8¡Sq0y_qÊd(f™þI\›Y”HÄ·%=Çr=“!­ñÎ’:Ï:~+&ß&OV!5£w©Kðh,E MJž³W¾‰Ùêk7.c£ç{RAanJçw«t¸9ƒÍ	@LbÈä˨¿õ]¼kÐ>ËðE †µf_üKÊ–RÉ—kHåÕ|Äú¨bÅÄQ©Q
$Ôkow¥FFª¬_Wå2‹y£ê)/<ÊãC®1ñy¹6ìK‰ÌU‰NU}r•/eïŪŸ,^É+m¨Î[QTYmгŠBb¢ÖüXQòbïæ/Ó¦×&jÌÊÇRŠïÿ«j²Wϸé8*^çš³ŠR®œ9ßÔß%Ì^DCÏàÔfaª¼æ¹°ì¤ø8Ι›–Õ\GW¯ù[bSTÌï.!lŽøß'ÎøõÛÄYV«•^)ú•€6GW®¯~- íoÑb“:õÃÜÞ`‰1—ò›ÅrÌ‹íâÍ«õE…oÏ]~ÅåvE~Mš‡[µI*òù@?ÜÛùkø÷oØ£^ºendstream
endobj
428 0 obj
4130
endobj
432 0 obj
<>
stream
xœÕ[ëo·ïçû+êß:¾Õ.É}°AP$iÚ¨ÍË©Š¢pŒ@ÒI²é$ëáÄè?_ÎÃîrï$Ë®>ÝqùÎüæEξžWe=¯à_ø{t>Ûý±›Ÿ^Ϫùéìõ¬Æ‡óðçè|þžë k×RÚÊÖóý“™YÏ;5ï´)+5ß?Ÿ=[4E³(µèñï²ëmiûvñ/×´_,Íb¯XªÅ7Ų.­íõ¿ñÉŠ¥VkÖ‹
Ïu½øž¤ƒ¿s¿¾‚/ÿ,–íóý¿;Êj%)3MWV½#nåê!Ž(ß±Õ²ãÒTuY·ó¥®Ê®¶Öøc±lTµXº?®ÈY;Ê·ðq‡î£¬ªº^ÃÏ+×±²®¡[\Àï_Vuƒ¿}O7…‚;V¸AMmqb~~Eƒ®á/xЕ\{ºåV±ñ%÷<Í5ÞÄÆëØ©uÙ´ ºofûŸ-þ<Úúì÷ÿ–É>‚ß/àã 0 LŽ?rËË
`ÕÇ£U/âªg´4pØqô 6â3ðׄÁôu#{‡À¸Á² ^Ÿä˜u•al·ïf:ŠÏ_ðóƒÌEãv¦ë°ß7‹Ëœø¯7U4&ßžðì7röÆiYUµ€8A±˜¾ÝKê_ŽZ%ûž¾ºa _徃f-#Ò@Å~ÙÑjåñ„ØÆm/>%껼>ÅÆ·¬·92¿O¸‘{ž±"Èá^è '™^ý2×óFö“$`³;¶f€Ú ¯›…YÒx™PJò¼Itph?Ý<¥3ŠÎ+m{/±—Îè:iÝã
¯@0ð[õ¨–ޏÖÿî‚Ùm FÝ ðÀ®iƒÅÃíë=Dømqhl[ØaÕûvœÂ|ªA&
F6
AdT`
sÆs×õ†%qš·.LÍÝ`_qrç·Ð(ve‹÷Fñ¯…¶w-pV
7
C~sž·ƒžá’É>sCÇe
î6Fd©¾Æ¶¸¾(t'hñ®©Ž_`b²À‚~±ãz´_‚Çž•¼íìxqÕO	ûz¸3üïÚ5R˜AÃQ¡ûÁTYk×îÿ–µ!HØ)€×ºV¥‹ ‚¯þiQ0pji
éà¾(ÐWû³§³×s­L!Yš²Ÿ­tiúy[÷
Ü¿‹i¾Ø›íî};¿¹º=žíþ{^Ïv¿†/~øÒýÙûËü³¯öæO'ãT+(Þ1έ[¥+;ãCž7E¬2ÈàÞ-Ë’V¸!PÁ¾Ã¾À‚ŸŠ¸ÝO‡-š™›BØÚñ<„aÿ€;;”Ò»NåÛPÕt[Œ±„þ— Ò¦CeÛU81#™ÂþvH;ÇpBËáÈ„àÉzuB튿$háXh†Ÿ½ÆiØ×Úà˜H¢Â-€5ÆÐQ(ÎÀ£Èºð°uÁªi,ý.v¾ˆ2Ž
ƒt›~`j<œk¬Áì´ö~—”r'ØC«	`¹—Qh¸MÖ0Þz‹Ÿ¢Ï–{«ÅãUœ,Ø´e lˆ¬yÁ–‡ì¥#øÄ‡WMàN©®yÐ)£DÚלE÷fâŽÍ{W­‚KûŒk–%¸\‹£AD@"iãŸØªuA p(ãg["È;Œ4ÐoµžÀkˆ€
6]Ž}‚Œ)´woÁOüZ(›x’ý™ñLâ©‘ø¹“ö^1¥ƒ)zÃÀ8¢iˆ
ˆFö~ÊáÅ…«×:ÕÑ}yøwΰü¥JDïý>8:â@&òÄþ/Ã:)˜A¢ÿEeN$ª»¨m€iíÕ¹Ï^¼ÑK]YÑ77ÆKþ#Œ‘[È)ÿŒ‹ÈÔ#Oôš²‰Aà^Ô¨ÐÊ™¨úyÿs á#Ì–ês÷ëÛÈCa—w|îK˜ÿÆï0º‹6‚Z/Sm
^HÞø;y.»l€àÔPhSœaªMºhÂá`µP.@*>L~ÉÑC›Dº@"Bø¦ÚÇ™¯b´}L±¶Y·›ãÎ^
ï¨@$Í,¸òˆÒîd,©k.3cð¾‹ÑªÛ¯«ºìµ%eõÎÔ^m¦fןíT¸/ê6Öô"fIv—Ä2¤ßÐcÅaK¢ø°ÑªÖQÊáÉQü¶G"çñüÓhç˲¢[/G!ýˆNˆü³¤e«…gCâÏ×l?¶*ÌHUdI3"®Û_³‘# À›YÀ8è1­ÔQÛÈ·X/¨Ë@Uð¡lõcÒeT‘°Þ¸@Ë6XÑë0ª"Ç×,~Ôݳbè’ Æ™DPÜ´Œw@c`»-©Mo2jcǺ¦’ðm¤NŽ"ÉC¶š<¤‹Íï¿B*Øé4H’FLAââ¤:ÊÄ:=å" ç`KÍË£©[G{þ†,.›Ä\«Ä9ŠïŒCŠÏac½™UluãùPgJó¿SNGùd.fî ®®Ã”x*Gꪘ1?$ÈX<+|Âö¼ðß!Ixì~HC	:y>?@„]`Hj´¤†Êt‰—³ÕØøôtŠM0@ôñ1s%8Q²¤Ø‘dqüaÜANæIÊ6>r‰‘%ØÉŠù[8©ŒÖGLTŒòÂCW	Æ}…s	o¹‹÷»Q\º×*.³ç‘èܲ?üõÞ>Ž}»­Cˆx¯TÜM¨ÃÊUÝÆÜÑúÃúÚ*圆ЬëèÂÞu
ÙºDaËi®ƒ(èšâ°ž¶síL7‡­Î8ÛúàÀ1wæõe4IT
÷A£3/²¹o=¿!Ú‹[]ñ4&MÌBåÚóq€8¤§¥&,™ç·ñ¥³gÁ4%Á#I•œrÓXn®¢ðt-GDMïq3©e
C1hh¤4”Ðê/õ"|ŸEÕ§CÔ¡§Š^r¼<ñ«Q¾>yJX×­-û~îÀ`KõáN	kU•º…eJÓúcBóðÙI¬1-X|»ðF©ò ÕmM™ƒ¯ÚŸ‘ÔÁk´Uæt.h¡1>gÛ¼„ëµID¡Û4¦ÆÅÀ±`$¥Ž—]žâdnàZ0
2M;qn”iƒÎ޲dãO¯cÆ$\EÐbÑReKßé¦uérûáÅkZ8ΕâÝ|ƒ¶¨ÉBŸ
&Âõ@Ÿ
Þd G½ûkûÒÜC;ž¡`ÔÉœÁ$œEÈÑ%ëÈæ‡‘›áEN7Àü	[‰	·´ä^E„MnºŸÀ•ô;xJq•qÚ.rç›A×4 ¸ÚÑó!¯ñt×—½eJm¶:‚p€‘‡÷ˆ±p®¦R#€Ñ[^…fT’·€Ž.8{ŽWïTC5(Vûë™—¡Q‹*„ŸcÛU±”õ;XKqFmtëBu8lSYƸ8fÅ?-¨ƒ^—ÁÆš˜MŒ‹†|µDõ?Zì2)u
ÅF`ˆá^שðn|ü˜K3ö¸vh髉’Â	‘˜qJ*+{°¢Å¤Åã‹b
.®9媑DZqwS•ÕN`
Ì-‰1žè”ºmÌ$;¾±ãbbç¡ñ2WsÃ;ã’§‹Þl)hÉ•<­¸(éÙNO¸È+ªgr†Z‚©
Tº$8MªZñ7
¸¸Îq‘˂θèHbôž°TïéP¬¶ÊINTÈ]Sm‘³^$sÕ•é§™Î2O˜²UP¹¢2#Œ“ GÔ^ä8³­ êáõX¢ÌF“¼XæµEß/ã“„"«K¥Ïé›ï¬˜šç±ñIÆÁz¦k1¶[Ìláas‰:K}Z˜¾zvÓšÐX°´”SM5q©JÒר“cžwnÈ*)}å\_?Œ³º‘eáyn7٪ÜA½fƒ:åˆ$<#}Ùøb=…L0¶ôUõ]=qÖhòV'”OÖToPø÷É>2„Ysq-{Ž)^I L¹]QX8ÍxŒÆÞ¤±ÚYŽ9"Ò÷Ãáæ]‰ºòG9U}Ä4¾Oîë˜Þäzžå sÌæ!ÅVÇš	EÕÌÇ#ýûDQ)Kn«ﶈ•Þ`ƒi?&Eá]sÙ&Œ *y‘,b…qÌìÃ4jéž…”Y_ÒÊã1HV[œÄFGîò§GYÙ>âõÞ	ˆ÷+Ó®ì;{3'ë…–¬Ó=ÃÏ1:IB6×?ïj£¶äÙ
_äĵ«œ0³IĤU	´¾W›È—Köicùa «¼-èßs£x÷7낲ÑÞs;ä“C·ÜÞŒTÆ¿(.®g¾.DIe¨¼¤w½Úxo¦ºjq‡÷ݪ¤7iNpzÑEQ
¤põ¡ÜqÐy\ÚV÷zå&©ëÝCõj<ÓåÝìo{½i|¥1Kâ/¾ÏZ¸ÙeéJXdíp×Q}DRkïqˆ¢z5h¢ÂØ×ŸªáU_R!5* EB¶¡üvE÷¡ÒÚOÊì†ÕT3nFÅ›CþE3ï%‡âÖX€ÛâPöØš†¯ûÄ;MQà¶öݨª…—«á™|ÍáÞõFII+×­%oÁ5BXŒz¨;ö€Þ2¯à)ÛÁk ?‚¹X¢Â‚Ÿø†#åo²hècPü+%r°ËêV¿‘ðþÞv?ý;\9³endstream
endobj
433 0 obj
3862
endobj
437 0 obj
<>
stream
xœÕZmo7þî_!äKv}Ñz—/û‚Ã}HlM›¤¾XmÚk‹ÂqìØe«’’"8ô¿gHÎ%­,¸Â€,Ír†çÃáþ1(‹jPŸû>Þ;xÝÞÏöÊÁû½?ö*|8pÿÎǃg#3 †RteW
F—{–³4bÐHU”b0ïýœ5¹Îê\ÿ:úÆpÈ*âhêB´†iôÎ<̇*û:¯Š®kU—=ÍEv’E6úq>ô^çC)«¢,›LÙE>lšÖ<“Ù³\!Ûi>¬Ís!²çÌvl²èÚÆÎôU.àI[à 70†<ß!‹²ÒvЫ)]ÝuJ#j#±ªÌàRRã,æW¥j(¥0r¤.AºlA¸þ½ÁR–ZTÃiFœÆ@Ó†¯i„Õd-CM+-Y†²,šªë¬FÏÍ´Ù|œÁÇÔˆ¥‘Þfûð{BOæ°&3k…ß²7Zf·ð1ƒŸáãWÿÍަš:û—n&3ü—˜o^Ɉ8bâ)™ø”ˆ/èÛmJУy0
Sžm#Ú‰øÊÆØ)û+žE5fpv@Ä}§ÊJÍYæ
 ¿K˜Ú¯Ê¸„ º-ôUv–Z%EÈsf1Ó©7k“}àüõ3ý“©wKˆ0vÆ`öyÀ}|CY—E«Cãøº†œàh•ÐÖÿ!=Â1Š1¾¬áhTµ0¡+ìïgð|˜¬¥5Äbl­ Ò];½Øí¯Àõ=ñ¾‚'ÏÝ㸀Y,3óõÀµËCñ/ècó4^É·»‚9"†—¤™WëÁy6M"3þ\ð|ËÄT«w†…âÜKØÖ5Ã:œÌ~‚“õ°Ég~"æïî ÛÚ¯zÉ~kSC¹‹âÝãpwÄë(c9âY*·]ø¼Pe7áHÿü-ƒÄ#MZÑe‡éjŸˆ÷×1ª÷l{æM¦7ÙDÉT6I"¤ü`Ý~ƒ¬Ì&/øHσ½î:Ŷ¯:¬ÁVÙž6’-•ÜÇ
Ö+¹¯ô€…›Ôùæä°ht˜^ìfû7DªŸS§}S¢}HÅèg"þÙÛal4ïɬ«>&\¯«4áIÞP ¬#ŸQ¸pí¾÷@tÜWQë=´¯cFݰ	³ýNâüñňz{ÔJD;+êwb8¡)7ÀâœDƒŸ¿‡|÷V#bGéíQ_Ç3â@Éã:ú!h¼
"ØÑÕ†ÍæôžàN\úð²Úé{Û’F/žÈ:; z×i4úKÃâSdŸìN£ƒÚó)ÁÚÚóߤ-cV+êM¤­EæcRcP‘sƒä/&>ñÄžQhŸR+ð©ì%¡Ü•ùÏH™¯…Š{_MQAÉ8MÑbM‘ˬʥåXèTRGe”·ÐÔ-6Ç$
«ƒæaUbD˜“‹@ú<ÇÆ˜hž]àç´ÖT¦¢’Â|WPEA%àˆSkS?i+û],·iŒ÷¬˜[¨‘ÝRC‘îy
ºªìkieK8î”åÜG4Òà°¯³1‹Y`ùphm›.9grM/Ã/ –pf;VeY4ÂëwnÑzæ%Ø™
è“mBÍÚ	µ8íÀ;û4¢]“5ÂFW+ê²Ë°lÅÙDmðãÄ?¸¢éFý‘ðà`öÄcl€‰®*T»ÐûÚ 4V¾.ô§e]aUŽ=æ+öX4W•D—¢Ÿ 0lJUãWT:­ÿS޽d%ÑPЧU‡‘Öœ¯Ð¡Îùôu•=³-šNcçWuˆó܈¸þUkðçe§‘ÒBœDõ	¼æ%43H8khÁ‹¦`È9.,º2¸#‘Ð_h­[œE¤F×ïíÆÆôj ëK<@µ	·A…vM Ô
 ý`û÷-*ß…ÝgºpÓª(`<УV1çD¸È!mù6vä’–cÇBf“ý”¯ðÊ)ÛÈ£ì•CdӻƀÌêÔ-^y\B–&°íƒ	û1 …1BQ%³˜£þ²G^RjŸDt'$ÌV>à²"ÈE‹éÍðÕʯó‹•NxGí
),üt¢õ4¶‚9{ËÈàWmëbYp¡!ß6h¡P7¡J)Û·67¸ÊÑnCç¹t’®|ì@ß¾h¶	G4u`è°¯¬SÞú,Þ¶qbî$ÊX¿ó›ÝÂVÑV¸.6$ùûØ­ºƒr@gCÏú­»Æ¦Àƒ{­ðžï%ipÏ÷È-É:Ïïãw›J›ì[ùôpëµ “ß…ÀsÞ¶Mº°;¿†æˆwƒkL7nßmÕÂænSžilu&¥
÷—xWñëZÎÆ­•²nM‰ ÀW¢(v{2˜§õ)SP¾qü­-VÀ<
òúL¤ð:T¯T…žþwgw%||ÐÊÈOÉDSeooAÔ%Œ•¸YõF©ðzR9(övMpYÊÞã¬í‘A˜u"(Q†!éJÅ2‘š8ol¢²‹CvÞ䘮Gœë[\XlJ¦6ñ›Ø'–®ŒÍPÕr\6_S…?çvá%vð~x–G§Z¤MéPÀwÆ7žF`w·Œlè'VËíê)ƒ»Sžþ—,<ÄÐ9 RY„}Y?¾qx|?3PE´_…~‚×k*Ý„}Ž_M¤›ñIjÜ#Úç|#iC—-Á<”ä'LJâ9?FâQRo\
ÆàRÔÛ~]£>hOÜ_ͰQãB°(_a,êj¬ÿ]ß­P+û‰'òõÈœ¯¾î«uPu"DE ài¢óD¬=Á‚^Ë=µÉpŠÎÙ½\kšRüùÆ<àux›2Á˜ˆoãjŽ*LÏž4k¤·…—5ैi¼P¼ÌRá}Éu4À³]¹iÍ+ߥÓFoì„®øEÞÛ±ŽÀùªM¥û›d¯†·cD®ºó_{¼:ƒ5…9'*ö?‚>û¨wŒÕÍ’Ã-8Q aÆ]Ð5ïæX(Cº·^±¿û;åVÆ?tS7[$Šƒ’xɳ$Ýiœ²lò…„ˆ–Wà$Å3G.#²ÐÖ™š¯>y[þÚ/\lª
޽uÿvýJ.8	=NÅÚcÎÌ©qØè?¥Fݤ\å‚c;é«òM"H¦Éà›ñØ9U!«3òbñruy÷‚Š—í7ÛháO’ôÈ “%³kôVŽ'ž¥,Êñd¤ë”C¼ÛÑ™xØyÙc¦&ܰ]c™JÔe~¤ZQè¸névîÍ”ÈÃú.eÇÍ'YvpÑ“|-ç}”ƒVì¤(½yøÊ‡³PfºwNJ–s·ë—{—2Vð:ê4eÖH1	³&³É—σ’oÓV•*Þ¯Yk7Ù­
¹ebäÁUùlîà‡Uaiá‰eTo,œ2ÈD’ü×_ò)c˜Òn2ö)‰Ïã`˜ÓOaÚMÑàˆß11ˆ¨Z¾vîVŸP–‰S¶_U®öþmþþù]¼endstream
endobj
438 0 obj
2634
endobj
442 0 obj
<>
stream
xœí\ësÅÏg…?âŠ/ÜR¾óÎc_I…”Á&8Œ(*%K¶ä`[¶,ù‘¿>ÓÏéÙ‡NŽ
	)Š2ºÛíéþõcº{îÙªÞºU
ÿñßÃÇ{×ïv«ãç{õêxïٞÛ+þsøxõñ~\º²êÁ­öìÑ“nÕùUâ¶ö«ýÇ{߯›ªYo+¿îñï¦ë‡íзëoÓ¥ýj×·«_^mÜvú8Ðw¼ój|—.‡õÝ*ÀýàÖ_Âòá;éÛ-øðMµiÜÿ{¢ÌyKYlºmÝ'âöA]"$ý£>Ú¹	õ¶sÃ@ø*À¿¹™ÎúU•ž߬ÒügÕ¦Y?šî§EôéN߬ÏÓ<'‰D½–ö0Ñþ®=MÿÛÖµ«ûõ|?OcºY…óÀÃ8«>qL³Ô.®«¸>M¯}Rù^…Ãa6‡Ôè#ųƒKϹ0ÍúQº·ŸgI	ƒGÒaò0°Ç÷!!§Uèèe/AÏàX€£Ï`ô€kœŽ†yôÎŽD5‰50°Úðö’•x£ƒàu0¿£YÒƒ°àœó°€Ä¸ÄH ¨ë°vû¬,I’>		xcñå{‡Øy¾g4&‘úÎ\„‘i*\/àï³÷¬ÈLOš…S¸ô’ê€8›—u²'íÖŸV€Èºm?~ üøW‰*|úqºÎ²•A²a`¤nU¶`¡=.ŒI'LÕÛ^Ua;{\v=¬ÿÓ8Íûéå!ýS™¡eƒ×:r·né+<
T÷ÅØ!}{_˜
àNlÈN°=’†ôä̃àÎ#úG衵!zš¡§%Šj 6.2jJu°†Ob2›%
hwD“óè\Tl#;F
!âóh¦XÛòkOÖª0“n÷;áÞ+x¾Á™w6—¾s ÏÕÖa}a"èý 8;9Da\dT­·V	gnPc?H\00(yçûrE’´¬ô!&¸e¸ fÀ0ÚJ+2‘¯ÐRßÒ½¤e`´cƒ‹‹ß42Èìd$Ä€øGuʨL¶Šw¤ÑÎo‘IP»S_û@b„GðEçPy˜k#±ª¢‡žlx%Q똤º…
·IPï{$}î-ñí×ÖduidÂH
|í *>f|ŠcJÎg/“p€NMùÑXûÛ5ÖÈ:ê¨J[dñ¼‘áÅ9sÖvO‡°Eåéÿ,¸â%•öå :^ù.[û™ÁSØ#‚;ÑåÉ	ˆ{Âár_ø•´¿”!Ï—æGµ,oŠô‘?Å­ëÆ˜u$\t,æTˆ) Šàk)8U49¢âRž6:ÉèxuÜ@EŠ6Æ´Õ„aõLÕ‚*@ÿ{3þæH8åB.ª¢dãsX„Cúäi8zðò”Ä^Çlohi¥aR.eé³dÉ¡´˜Âà7ý$ÞÝ…¦6ât¤‡}•Å6èë2‹Y®¹hÌË‹*øLªÀó)¡I&ÿF&âù@e \”×£u…½2híPÚ"Áh\¦¦<©E‹/κOðònë£Ë®Kæ"ÂHö4c¢Jˆ>jŒÙJ½G©KtýD ÓÄ‚ÙÇ'¦ÎŒ¹°d~Á:óR¬þ'mzˆF…ˆ•†Àª®g`5ëyŠH—o«^çУmÐ$½7‚è=ÎWTGj§Tµ¸9µRï“tP0ì\7…H[ÀÑà'š@x+ÑÚ	ÍÈ2½nüBhd†‘xƒx{³ã¿7ÞÁûÓ !à̰vù5øØ±_zãPkKAÃõ»m(Ó+ÛàÒ”«´½Ù2ka}`eG “î€éEnÕ?ÁWP_L[ â]dÝ=ÓÁ:õ1‰­îzzU¨õU4ܘ³<Ç˹‹Çùâk½z¨ŸN,ÇÃcO¢úÐ^´xòÎGzña¾˜Ùq®Ÿ’Œ›š\ÔçzñËü̽ø·|q÷È8™*0 _±î·ÛFC–rEòñeA=î•BÏDÛ¥=Éý°øvèlv€™ì8½?!E6eC‡Zð‘^å¨e؆qVfµêÅø_±‰3hdè^c6;+îÓbw"äYe°•Kç‹få-®¦ÏI˜ÚI’¯Ñ¼3’ò3¯fIš%¹”ÃŒ„Ï3&W)[ˆhN¶0
˜
V¨F°Ha“`á»­ÓLñ¯j̦6â[¸tñ:Êåm­[15‹'÷¯bò:ô…ÿã&c‘û,ßœíù1xaÛÇQXý¼_ÂWýj¦ñ]°x{—A3ùÃÏ=ÅÿؘÎádD'å·Ð¶ÛÖF‡Pz»JoŸ˜dÔÂhëëÖ?C¢Õ¤	h+1cR–ã")>ã†ÉŒ`Æœ)§pLI\Ìošü—Ëq8§	¸íHvSq…{çè$]<<r ëwsLJ¢ÙUDGöu{ø3Ì9ëHµ‰ý‚EZ˜ÄÂ0F’–C¶å{³‰tÛ)‚©€Í•ÕGæf,dËä¸$^ÃÊaŠÆzµSåíÙMÍšÛ¶ýxg‡uc( ßDv$ÆqVeñÒD¶$…¨ˆuÞß•EˆvœPÏþפÓNÔ-lÕ77˱­ÿM¹XÃÉÛæ2Gò&„`2/Š™t„Z.˜Šží2©@_É„¨9ÃI«Ç~qC3zÔÁ›Š—o+-*±ÞЛ5´"C©%xIý‚ì£Iä¤]‚IJ¹š’‹¼÷g^^iû®4âÿ ÆÂ:ªÆqc$ÚzÎE—uu4î~ÛQ,fÔç©°¦Aá5Š'?¢?WˆÀù~é32§K!Áf%gýEÖ|yŒøC
c¯<%T‹Nw“½…B£tTL¸ÔA`º(áyâ B œð‚“€Þ˜ÚùÂIO	›zòýú_éMšª†¨ÛSº3¿rb¨`¼;l¾a7ª¥b¾”,(U5˜Ì»ï­2ÏǪ™Ú³s#ý»[á¡õÔíÓc-c¿ê*Ø\F×81ž˜‚I«˜W‘iY,O6$ŽÁIJ^£7ÅJ
¹qRº‚Q
®\·+*øX
žQzNEöY%Ù3»*¹–ÖÆüÞ’H<:”š’{Ͼ`wŒ"\¬1`08)=qYŒ<îÆs2ð0kD~ÉQ¥©EŽ6Kúh¼C¶Ӡጞ.ë¥óÀ[g»X|V[¿~Q5A»w¤çë^ZzÒèÆÞ\»bt£	£™ýÓ8‹;Ià2 Ñãqº¸ˆ0ÐétsF\øv!¸` a‰êD+P¯ܶì$"ÄÌõPúx&C¢/Ûå°~÷žòèwOùž²Ùå)1>Öćܯ¢OƒÙQ5¶,9¡i
ŒƒZÊRE«`“Ï£âmÕ]‚ßìÉîšš/TEÑ2#Ú}•wGÍ_@}; mi1ÒSÀ_N»PLS[ÓPÁÅši2{Ý6ùEâWVJ‹2¦s1›™²_l©°®m{uݸÁhTœ[øš&¨]7ÞPa-ü@0M,¦«©´|~èsˆzUí¯`„HÃaÑ®Ø9´ÒÈŠà0[ùsÁc×-KÛå@ÍtF{ÛétÖøq‹&44г€iÕÆ;¦îÿ‘éz@p?é[ò—‹­OÔ¢rþÈèj2óFÒƒdÄ먈5µÚïÄGL-¸Uj#õËJ%ô;)«Ss(κÇèãÄ–HÞ㞨?…ë™`\v\5…ÞdÄa¥9Ièð,^ë…˜Šè£p#r{ÒÄ›EÓ³¬ô]íÔu¯IUm¥RtöPºç
à&–$7µ'ûgRÏ3›`šæ² ùÐòáðDl1@Am›â(}c^z”§ü®‚¿m‚ÚI6>%Q¶ZÏÕxZciOД#›ñè8n)кc¿ú\Û3TÿE^ä½âÄÒÀuƹ~
ßsº£è2[¶‰Úåmtã&4ƒìEåÂ|Ê$xm[EÈÅh
y#ÖCÂÚUtæYûLüµš©8–£t`4ÉáÙLñ,E3™/Û-Ì™%öŠ¢á†¨ß•
*÷Æ¢œ>ÐÍÅhœ–1“Ðêþ¨»bqy¯Àéûi+
²ëâ)¤á‘gÒ¡m£Zô>/ø¤Õm΋öŽ˜¶=?Œ=>p¹ýŠ‘‚T§Â9,L7ÂÐy0hªÖ¼ŸÁ€œS0MõÐöd:÷¯Ü¿Ã]]bHÍsS€q]£{PòFòÉy|PWXº°yÿêÜøsš´çðÑs.è˜m%ÂYvÌü&Ù§ÕõŒy’Ýê CçU¡‰ªÀnÓ`üB&½ªˆ¯kZM)=U™³N(2XDA쑌ƒª¹J¦Áyx98—;Ðï	%™Ý(†ë3[ù܇±YÒÏYÆãêç`}¥•RAü³Êå¾hìˆE"VÄ	qwõ‡l(²9Sòñ3}E®zR'ðž;\I«r—¯Šô‘}ÜÆ˜üÀ¢ß5‹¥ ¡EÊ‹¶iØÇãô`œCÎdè–gt:è>£Ö!Š””9j`,©Ý`2›ÿÄ•¶Åšé`(w
óX¨Ã8ú–}µÙ¦;wUȳyj¥†ƒ˜'–…éµ²fCÌnÂ5³_3GCÈJÿp&{çQn\vŒÜLkd|"O¦KK{
¿¯”œ•¶Z×Lš$žæ¼LN^ÆœHÞýrªÊþÌìøÜlcÊv¡ºÁIßæã$J…O’›3ƒ.©¶J’Tv,h|ÝŽN›Ÿ86aln$í©öbqkOŽ+âv²Fcqjq£Ë–`.@
ÑoËJ¿a|Nvtüé ]6ú¿Æ9玣h"÷Mçõ¸¢ nuÈÈ

ö	mÝÖ÷ãj}¦aÓæJ3g]³T^ÙÄœ’.æ”Ç|ÜQ{åîbƒö=ÖŒíOšÊ}D™ï¢Al“/1¹Æç϶3æ›sî)+úáFN/~Ÿ/þhÂÒš´+œû*Ÿæûù¡²—‡:t,¡lòn>…Ü`<ç)ùiîâEÁ¼üqÒ,ùS¾ûb¶éÑdÒQ{Úµ¢;(¹ùvÇ»Ϋ‰ð±õŒˆ¾7'æûY¢³ýU9ðy>ËÝÿR‡Tœã¼¼
ïÍõ?”ús¶¬?fe¹ÁèO.~üõ'óëdNÎ~ןߠþL
`)ÔÀªlYÿjwÕ¿¾«-(‡–NmcÿÓôtþ©’or<ƒ¿¤(¸¦´ÏìV_NœJ!;õÚ¢Z¢¨4'G!%»{-šÝ¬",èÖþÞ×{ÏV)¤hñWYRœÙ¯|ÛDœOábÛü||{ïúí/Vçg÷÷®·r{×?ƒÿ}üÕ'éÏ훫?ìݺ½úzñ`F\ã€ñmÒ‘tBú
›¥ÀŠâ­ÕßÑb0rÒ½QåAÈèåd…އ¶”ÂéO	:©E–'+%"gÊÊ ˜O|ò/0̪i¦#‘ŽaNZ$0ö(f2éR\UI
®ÞUi£"|‹%¦¢"ˆ:ïÚD[z
>íjcgIlªœWäE,¼µöÈ‚2‚~!‡âµÀñdTËãas>Sßý+ä©'²LôÔiYv'Mº<ËvÈÚ–õs£ã%6kÒÏÿ ÆÙiËZgóþUÎaÂÈIº<—œŽíÉp¾¦tVÆe;I}Öx¸röi{VñÓúôƒ))`¿Ã‹˜¯ ¤™é×xNÌóùŒ­ï¥ž±ÕüÖ„H>…Í;òï™*šºáx™	sø¢~5$`Ä_΂¹!&¿³iE県Ì8'vu¤jÉ>ÆYÙ1þÁ°<Ž“h”¾Þû7Kædendstream
endobj
443 0 obj
4835
endobj
447 0 obj
<>
stream
xœUPKOÃ0¾÷Wä˜b»Iš#›†€N!´±©‡
Mü~ì¶ë†"9Ê÷°¿x¯¼åå÷r[]Í“Ú*¯6Õ¾‚ŽTõܪIa #.ûª¬«Þ	*¡JT;ªl«7LÐ	ïåžÿ):lØTV,œ[ë[.ç¦ÎúÚ ~2u|f쉘KÎû¤÷vƦÔ0GzbêÎöbldQßmS±‘ËMê'ݦ‰"¦ˆñÒóÈ$ç!ô¢Ó	¹KŽ9K(”8#w`±'A¡›Â/¨£‰ûËIºS#ÍOü+gñ> t1pœØáh})a¿ÉH—›´Ã*-y— ç~£-Õ;)GvCî–´–w;€¤òúc$ëŸ?R¾Æ²ÅÇ‘ý¼Bz¡¥þŽÂo?ì¹ÁÕ\˜*ÿš•ê™Ï–¸†™endstream
endobj
448 0 obj
337
endobj
452 0 obj
<>
stream
xœµ[[o·î³¤á¼ùœ"Zó¾Ü>:mP
Ò$*ú¨-Ëv[’#;Nþ}97r¸—£ãÄEÑXÚå’Ãá73ßÌPovf°;ÿã/_Ÿ=üfܽ¸;3»goÎ,¾Üñ?—¯w.Ê€¼sfHÉ¥ÝÅó3úÐîF·KÎ
ÓîâõÙwûÏçv0)ä¼y8wƒsÖûý“ƒLŽ)y»¿åǓۿ=Ø!¸)Mû«òÓäM÷?Îý8®L`.ï³uÿ¾ø-†1–q~Ê»‹¿Ÿ]üñ»ýÎ:NÁ•uͲµ¦-“ÙÊ(˜wiôû/Ê›iÿ¸(?—‡2Aá[š +ï“wû¯`.;بÂ\ž<¬T&Ÿpf˜lš¦²qPGœ²mCo`z;&;Ñfó=5¹¡|“÷ïpy“bÚ_7I.Ëç¾”5sùé{9ekOSÙ)}äÊ1‘Ú¬+ç8Lf"½Meã”ÞœT‚„0¦lðøýíÁÆX»¿+«ÀL¹8ûúìÍÎû!áÑŸ‡!ï¬5Óó.š<QHŸ=|üåîíï®ÎþkgÏþþó蟗ÿy÷»³¿<Þ}½	²^\AY9ÎÁ'Xfð„´ï 
Ð|=Æ¢ë(¶Å
1˜ÿwq¨Y‹ût*"X„”‹zóþy@9òóÊ.¿_ø˲'{¼)ß”‡ ø”>ºæÏËQ}ç÷Å¡`|ÊñìèL¿…yüÊ›‚Нàx.y¯Pe7?–÷‰?•‘8÷3ÂB€cÉ—5ŠË˃¤$#~_½ôøXæòû×€JçŠöA8B”Ý”—‘
ÀöžÃ¯¾/`t1ÍŸÑtŒKêÙeý©,
«#€@–ûþïT
"ÍîâYÑû5©Ö¹ýY4à9(¯¨§mV‚—Ì\V~A£uû_D@XôÜó5awný#ø%XUöÓPz^ŽŸà»ÛúŸWZõø©ÌmÓþ?åÑûƒËEÎHXÀY~Å?(²˜€:?EÆâŽûC!Xâd {"”!cZ}(18ªÎ_¶§ªÐr¿DÞÁ”¹®‡nMg4ó\¦N|2Õ@ßÐ}O“[b
¾…qײfÞèuù”1üU"€àmsB‰
²ª£|
å´Œ‰âýSçü}N¸£çMÛæpu”¬á@”Ð^¾œÁ““ÉJïha€qû¢LE÷Ý{¬§GpëÌÉÉÀ>9òùBªãU=‚ŠQÖDç!àz)ÏG *žYˆ¸/¥aØ
E$1Jï}ådåQf•ÌÏÍÅþ…„Ž&Epb4°)í&æÕè]
›øPÁ¸êœXå_UI–09 %¸DÀiŽž-k£NU·ÙoÕi=L¥IEEe’à•„ø0ál}bC\™}MÐú5CŒ4ÐCLèQî,$˜ñƒ˜Q‚š™ZÍŠø#`·Æ£èpFµ}¦ÕŶu"%®°@`òÒ‹Fµ/5ÖlŽYÅ«¡¾4™"2ÒîFç„ñX¯¡lBkxËp‹š€ÕÑКë¤T´.Ïô:À°(6xåúXØÇ9àíÎ#–_“r€?5\)ƒ©¢ü¢9>_¼fÏŠgUÞÞE>`Åf\·7o«½9ˆPÞŽÿjNÄ@ÒôÐÌe¶˜wÛ¾eGY´GH\cÎE
¡WAGÓ„|déØxÍ85‰ì¨@À$·mRË,OÌÄóËq¤­hðÈ­íC·ñŒÓ5‡Áû	Óгß8yTÝz¬ü–^@FIÐqª5,ùi‰%L÷ÁÓZŽoðüòàyf°r›{²t³•Y*æxbʦ U?}ÂÑš&žûÓ`í:u;ÅU¹¥Ã¥B\Tnú_ÞóZÑ¢O™TT„0ƒu¶´T¿[+q<á³knʺ™·Âù0Õ!¯îjÒÁ˯å3äñŽ{äa®y£ØDAPý§ðR²C
:˜’\N"½GtX2Y]z‚B|^sØe9¡æšrXOÚTÊÅàÁ==Ì#!Õ¢¥ÉêºÃ&ZºÀÜ‘=‘nì3‰9	n³ø!{{Â3EѶ9¾"UĈ\÷Þ	¥Ðj„üˆ8à–c졳D„â&óˆ	þé#yM†m¿»’Œ^sS«Gvy$S¥‡Z`ê‚©OÕÿߊ$ý¹	á$ôè8åqN'Ø) ²óXYóTmLrˆõpÌ	K¾˜ïnKL
lÝŒ2q	¸BöyO$޳E3‰ÇMƒu‹«³@.û/CJ*›á³…Ú €E¹a
T­ÞÁ¦\ò’™“[d^ëaOÓ­‡u)Ä1§Ã÷®¬æ›€hZŸx·}j¸È
›ÿ“—jRÅ©!E×YÚÈ(í’« ,¾ÌÌi*Üh—×”>ÐÞì4Ô–ÏfºcC+,Ö½ÿBµ aµXÍ$BW…;̬†Ýï4§«	¹³Embuª†R™iv@_í˜i¬d`Οš}IY1ÕfbŠrbŠ ìÏUùÓÁÃH:¾¡U’!ô¯Ê㊊ÿ…䨑ZçwÐ,È[Œ”Ù–ã¸wŒ´Îr(ÖDïÊäÉX"Æôe?FKGo%Wµ“vU:´¨íS2-@8äÖàã)%hùrÕ¹K†½¨ñßOt-åQÇ‹ÑÁ4Dü*ÞÔ6\¤¹Û®Ç¡è¸,Ûúç¡+#/óîJê?6¡€jGžf%©&
sÜqïÇk7­˜Œ«\´®n:šjùèÓ°—ÕÂ…8aMW½[ûâ§CºÈBõ^}vD>ælžk –ˆäã¸ZŸ©>¿¾¨ò×þÉZ Nu‹žÊK§µZ%°‰ß
C…XT úÆñ6Ä9HY69ÂûpÕ#푱ÀÍê·Å¤h¸Ý9©B|r?úÿtpr-ÂèÎý¹ƒÞpÞƒ#¶ÓDúù·m~CcX‹(4 û4¤:Rû^Bƈ˜¨8Vµ–˜ÔUDÙ˜úÆÝ­UË{Ú™&êayQû1q£2ä¹Sµ„)¯q{™è²W'uæÑi*S(5PÎ{Ì>ÅÊÑÒÄ4=„Ejãk²÷=²y³—}çŸL{†¢®£F‚Îûrvä:ì§÷\ª9±È«=‘zyQ‹µxº*:J¨ç5ÑÜ,²㈷n8 )ñûÿÖ£—ÆË[b´P¼ª¢ÌRy;õ‡âs#$æ†[ª±È}9ró&âì
Ðǧ_²£ú
¼Ñµâží{¸i%¬(Ø¡ÏøÕZ¨öµJÅ•íÎÏô½i5)lõAU{»
¨Ú–“2\K>8Ó—SS-[á_O«,UZl5$eÁr¼•Øß8ú8:êõu¿(ÆÉéÉÊÝ)=ι¸?eÏ*ßÖ‹Þi^*¨AbhÅl}à”^;*âÎI|—×1»ªž¦þÅFk즹VUè(š7ëßÕõ+F„R×Ö«/ûÞªmnOÕ&7/cêî°xjÊOóƒ¾ó-w›#ÍØ5oÝV”žãñú$1—ÅÇúõæ
4]ûøÌŽˆô1N³ª¤þ£­ÐŽÄ¥%“nÍÅ}ú¦&„‘B•;Ôîûe~^©¬}êXûÔAýÐ
¹úšïZµ‘eý .ŸóØåÚ<ÿÝUÇÈÈáÄÁ»û®ý`%$*ÉYˆÇp模ŽüNò+§,s­yr+ÖëçÌõöì3…Û•²7LñâÐÚý›5Ô>/EuœrݶäÌ'_µuÙÖx\Ó+rq.O‹ŒàŠ5[p	ˆ
戓+’ìÅG'½¬ä€ÎžÀÄ[x¬ÉÇåAu™ÔAÝŠ	E–7\vú‚¹Ëtç§»ÏY$&•Â*L65ªØÕýÖú<éío€¨]ÿUóP×6‹Ô¸F'ß}ý^…£+Ú¢ÜåjaQA\•ûÊÝFP›⮘¨&¶5¾R¸±L;QÔÄ¿íüúì¨	¡endstream
endobj
453 0 obj
4032
endobj
457 0 obj
<>
stream
xœµ\Yo%G~wFâ/øÛ£ÜN×ÒÝU  
"‘ñ ä±glo†ùóÔÙªNu×½ö
E$¾Ý]ÛY¾³?½9àþïÙÍÑgßÌÇGÃñÅÑG_óÎnŽÿp’>06=éãÍñÉ›#iŽg{<;ßöøäæè»MèÆÍÐÿ<ùsáL5"Œ½OcNÎÓwŸw[¿ùSgúƒ›ßwvóu·µ›xþE·•ßt[çL?ófJS÷éµ1½¤/Ë_Ї1Zšû…7aÚ|™çý¶ÛâOóUcÒóG.½š"NgÓª£5°…Ò>CZ<Ì#N˜>0~Âix˜Úî;—þëœßü=î¯틇¨•på¯Ê«ô%-L4¬©¾%"nÝÐÏ&F¢åUšû!M˜öz
'ò¸þÌû®s›·ÝvÜ<ÂÑÏ:Oð>~
ßø=¼¼K$¾í씎8ÒàÓôæ¿…!òìt›8lúaÆÍ}ú3Â4ÎAªy`„I«yZvk†òâv?–ß—°í
w€ƒð_§›áLܼO|ĉÒ×}ƒTH«N›s˜ÆæIáÇoá˜À­rÛhçéO
t„;ÙÄ¿ƒa1šéy«(L
DQfJ€÷ÌæS~áFÜ"àëü
®ø$1FïBÙÅMúzåe"µ¢8ƒŠHóX«&| ÙŸ,ñ’E@Þ¦°™y¶@‹­ck\?N à@ØCÞláhEiup‘`Ôäñ¨B’€ ä÷$°Àô1¶™îLaúrç…Š¸w7¤1r>I”
™ž´<È9óé·›ž
å|ÿƒ©¦XçDÇmþë=NvôªÖµÚ%툜´ ‚¸ôÑŒ§XëÂâlåü¾îHì˜åå-|BâÃÔ‰FɼÇÁÕ„j0Ó•Lä1ó$¡X.H9ÓÄRh‹Ë2y€'yPu·‚HMÖ9FE@oQ *Qó“fÁ>‘"‘Oöu5©|RÏ¿¼üŽ,²cÄA¬[^¡|&Å9¨Š)ö>»ÇgðX;
Q±œô¼Ò\øî‚f¶SlŸÁΆFeÊýØ|ïJÒäôVs®ÀÊ­>XB¹z	b`šÃ"“*¬š„'gD_F1¯ÿç~rQÔ±¹ÿŒgŒÅ¡@B0v‰>¼‡a@k§\‚ì“°f}
 /²æ2“vÃ<	½3êÑgçLðhø@’)*
¿ä´ð÷óÌ-ûÀ€ÈQ[­fž¥5³T,+—÷Áô0Cú)«”Ûh·ÀV¬3ˆš§•j{Ày³P¼¶!bèðŒ©‡Xì	|Í0Xé”÷
2v²	<îé3Dû4ÝDº`¡‹Qüè>	'ª G£yz©l<ÓÅh7s-pâu~›GfÿÓ{£Zj¶¡6&w•¤ÔÓk¤º¯I^ùGìý$„fl‚O2Áú_–+ÏA&Hx Kl•ö?AcÓîì…ÿÊÉàu²H/µ_¼
öJ‰šéçŒpS!}9ÊéySŒU2¿È8|Üæ×([1µŸp[½m(€8Eèjĸ« †ÍÍVÜ’áEk³cˆrÈø;%ÅÉnbò:–°nF´°éO¶u•ÙZˆŒâ¬uGÖé¬]&Lî÷º6T¾&{Ú©¼zZ!ϽXÜH†C9ÆMq”2G2•Ô¶«PåªX¥YÃF‚%oçŠÞ•XБÒv]\<”…™ñÄ¢1‡=†ì}ÉΆٶà:}ë\¢¼ýÐ&IÉ$X&G¾_4ÚJ²VåÅÂ}\¢¢Ì{$ù›Êd»”m,õÈ:;e·¼±A	 C(uËäd‚[¤XøQZ;ÅÖ…B×#Ó(§pñ˜,f´5ÊR–Ck6LÖ/ê4¯TØN9#¨’¾±xÏІÉrf`÷FKÀÈ)\œë^œiˆXpC#Æ4íœâH¦”­/¹Ê±÷¥ZDV›#£qaZ,n}ZSUYÄ_çtÊhaÊ\i怒ïÙCâ>çöµ÷c=åÖ>ŠÍ	B¢@3çذS—sdâ°`5,‘ÈÛœ½|’‹I䊆ãNÿ¯‘¿Sv8ûûKÝH´éÓ;wˆúÀBŸd—ö9s°ù;ò–ìë­Ç䳞Rºz‡^³Ù/¤¥EÙ~ìFÌ£–C?ªä—øºeö0=_gµG1/ºbVÊÇË.³À{
œã>틦Tî["vŸ
˲¡x ºP׈[žñŠ}› *.•H«Ö!¦"Yër—ÝZG+pi‹”‡RG€%2,™b¥u#@Ȩ¬€K=‰¹´„*‡~QÛϔۡ3¡ÐAN÷íZ–§i¯,眻ì<زÁ£²½Óì*æ^ÅH^Ò˜)¿$\u¬»–°[”^ô£ˆ$BCñs`¶r1VEøœ©qæŒuTTh¯]UÝ7˜óCˆè¶ˆ^ºh_f—3„$«]vTÓylyÕ,DÃ~ï&áIÑI9h"Ý	S8NФJÏÈl
ùwIÚóŒ6£JÂ$3Ô‡‚Ø!­b÷TíMëqu£h-ºˆ¡N:M9 °6,#½­<r’dØì,•38ÍÉË"Gº)+}²…Ê­ÞâŽÆúO±žµ=bÎv¤ Ù»Ài)v×uc6üt¦wö¬_ÈTjBz˜C„$^Žˆr0“®ôUrNôɾy̆å°v''VÛŒmmð\£¾VW-¥»jo'UnÚ˜µ3Eûăœh&s$¢k&s¸!ꣴPälªžN¥1k;á÷Ò]Ëp‡gZ7Üß.„cO{¼”#së•rSÛ§Ú)1íºŠˆKKÚn/ÌÓ\Òeœ5M)ð³ÔCîeW·pëö=P4³G'˜n®ÄhêÉÎ[4Jl2W++vÀÌ5û8)SWû)/`×f*_ï!*fW¬¦Üíâú"²£¾mEkKKaÌêu‰{b4šþ÷jŒR­úÖѤ>×wÜÂó¨ÃÃâØŒSÚØžëGzª¦½Às®]Œ:d[Áó34P$ɩְ†x2ô!£§iso¢Ï¶Ø•
úö®[B²˜?•5ryV·J´öfØ*»Ï,	Úe·n\X¹I¼F¶6†ËܵŠÙaÝu]ÆJrzgŠaezªî”bñ0Í6²v %ÂÏ*½”-×ÝM_w(Þ­$²JÈJ^êC—¯UœR	v5§‚@’ðòQªE9…½ªYŽ3º¡gÃжõr³BµÒÀÝ‘E­s¢%[ýËtÙ¶[eGàÀÊ ú9ËÞ~˜K+vBÈž:Ùu÷cãê²~‰ »îÔ©œðÊÞ§wž»7ø{ï?Ù
mn‡gR·5áA5Ô=·dXlžøZNi,nðT9Õ`öä¡l8<µèSWg>Tù¬2>Î?á7RÞõήŠF5Zùßéç^¢°X\”²ËAý­>nqO_{“O^°ðÆ-‹Iž¢~+7}3Ùm}å!J{fúØe¿ñ¶š3s@²ë°5î“ä‚hêàdÆÒö­ÖÔ6Ç‚kªÃÏSh«»0øjin÷~Á·9YƒŠ§™SM<©ã‡ÉSÂçK©Ó§ì
§Ó~žðz¨ëªóOÉw3qÏ5úä}Õ
1»ù†â€çǨT&ÉT {¥œruEzOÜJW›W>úþ^åOL•—Ï»Ð7çÛíó•—[ÞÕ×érå›×éKÔ¤îÔRÙ~¶ëÊûô»HôªNÊT®ùذ†`È,ÒÆï45Y—¥—Ó÷+ÈD§]º°ü0½ú$ËÁP¡%W 
“J¸‚R ŸäD¬–½F	.Ïåê`IjàE¬Ò·û°»PlëB¤,އÿ?$èí1I;c#þԗڥÔ>i˧äï}§ÓÖÓÎ2MõŸ,ZËâ,‘íÿc½¨Ö›{í½Q*§ªrÈ!.@¶PÙ»¢“î¸Ãº.ýíåÒ2çöÌH±tu½•«ÍÕå§1ßέnçØ'.&²è¾ý±ä¾Ö5§U£.ûª.KµâÕ½ÆÊªö(b_œý-ýó?AÈ7Fendstream
endobj
458 0 obj
4516
endobj
462 0 obj
<>
stream
xœå\YsÜÆ~Wü#øæ]•¸ä'[vÊNR¶#S•JY.‡â%Æ$—IÙN*ÿ=Ó×L0À.¥ÊSJ%æìþútãíA]™ƒþñïã«GO_tç·êƒóGo|xÀ¿Ž¯¾8
œ	wª¡ÌÁáÙ#êi:{Ð9_ÕöàðêÑ«vݬªµ]ü½éú¡úvu¸ÞøÕ×áþWës¦»úf½±ô Ü„[½V/Âåêó5vkøñwðãu¬ë~õ·µëâM³ú3<	+¨»Õׯ	¾s}»–QŸCc'žñéO‡
»3VïÎ7]U÷aƒ‡'aS}ØLØ4Üð“««Î5À¡ß¬7íê4Œ&¼[»Õ6ô‚ßGá÷eXÎ5<žMU›ŸÿáÖsºöØú°*G¡ç»õ†­]¿úvŒ qçV'Ò0h`þ{‡¤‡?q´ÐÒ6Ãê®oÅar:÷nõý¨lš×wë¶-q#NÁ}l_¯n²…ÂÅUxÀ\àéN@DÛ[!-l¥mC5а­WçáïûÉè´š¡ïÂÀj˜Âë+Ømx±ªáhV#§à‰švao]³z¿FX
œb£p=¨ž©Ë)’1Ü-óc†l€>"à^
ÂëDL=6ÆUMbdÙÓÜP#€t0È1,7ts°zŽ€G€a¤ l…ûA[Û ü ü¯i-&ü
K¸r]ƒBô	4Çp‘‚_7x…	ÞdÛf»ÄÅ(…n¾¦Ù5]”Rrƒ‰àÍ$ pk0C×zÔ$KgÐmÀ-(¡@¼
måqGLÖ0ú
\B‡vØO/24ÉÍ×ÜÍ!!û@YÓΡ‡öfq‘‚ÂF5ŽôÂyˆÚ¡1JÇò©á=Ès@hgE¢¤
ŒH˜Cš êš¡'Ò;‰uó	š/éH*lŒÚDðú©\¯<\oIKìуTÁèÇë$P—0Y˜È.àŠk˜UcXYzðëÚöÄå­ìÜ,‚ˆú Œ¨ÇZ‹„
‰i†*Èí_>þ1˜5˜Ñ·½,%‘î.ܤ!Þ‡¶M¿,мXßQ?am®þo¡èJœ_ÆTZ
ž2×|;D¹„¾m€Š„õ.õ–ÏyÌÐlüF¦ý’÷Ú7KBë['²‰”ArrꬩlÔß@Æa{0?®ŒÚѰ
žQ„#ItÍÀ
©µ­OÖÓB÷ž©/„ú”çFݘ«—K¦<Œ’‡Â÷Ž3eÏ›Ìõý	Á’¦¯ÙLÛq,p‚F
¨:ÐÂŒB—ÒqAy¾IÆ!Áq$…©ïul¢0:b¼EŸÏõN«_‹hgȱb‡ÍçŠ]kÔ£L$߉ØkàjÛá’³MºBÿ~ÓmƒŠúBý9Òt2†b÷Ô¬²R¢1f¸UÞHÓZ³âEL†òÑ2>sEk%¯ÂÕmd#8Û¦>ä/ æ÷¢«Ù9§gñ!‚e…x&…G‘HæÀ±üdF¿ìÛöF¶8îŽiÙ ¶™=ôöÆö¤¶x·¹Þ‚¦–R#×Õä¥^™™<¢”@ÖQJÜÚÃììpnCÔkÂÃcŒMr,Õ	ûÝeÙÿË\Q˜9g3k=‰È…_p„G;¸æÖ™&Óö:Tb/àÚ®Ìë’õè£å…‘úõœ+Z°‹´Wîä›*ÓÊb* =-8ŸéžêwKDcNiLX¤!âæŒÒ&“‰‘+µy¢ºŽ4ð,bð= Hw$÷º:ìŠé±Éåâ0Ø»rd0¶‚™r`–à8™ŸžžÝGã±	îcv’€ë[r’£´âÇ–ySÇÈ--"ʦž:Ì,2ƿۥ6êd€j;âPÜŠD)´I	µ‚pÂOY&Ç@ÉãÞF¯Þ¢ØƒÄgQä3¢ÓÓ­Ó‡5aIÖ×Ñ%+Âøw‰ÓÓU˜®©I×Á"¨õ;Vc¼c~`jg
«§ð÷cP®µp{¶£HÁ]ºLÏßÅ+p¼’aM€v(ÍÀJf“„\ÙGy~Ÿßåö3Ω#ËIË­nérí³0HZ^Ïì3FF…1Á®¤èd—¥I®HýyWÅã7ƒýo½¹<£Kïú	Ó šÒV!_»š	ô×ãt÷i¼$å„KÍUÓ¿ÃÎ00ì*¶žz/F3‡“ßCºGOO™†ä‰HWW\x‚Èo_3ʆޖøpQPBÕ	ñ5!ê6íçBs_ºÞ”&¹ca¼ÂÑ6tVמSnþ¼ÜrqH-N7Ot'ħ³U›|¿»"¾žqî.À'¸7¾¶-h1”ѯºÐtêÞeŒÌn¤yÒ5«ÏÐwnrtp‡çèš%Û߯g©O£@…M˜ÇÃïÒ[_Çç_¦ç/ôÅu‰_G%Æ_ë›Ó휋@˜åEöƒÖt¹æ&gªK/@TÖ–Ó»ª‹1é;¡’׫.k©ó|](.‹úˆfÊýô‹L#OF=MhJ»]‚à1¶+ƒç!=7è†]/·|=cɤ{ÆVÑ»—ž¥ç¯ãÍËÒœŸ•æK~å7qFùæó_“„?I±Û‡ŒþÝhw`Zn>_V?ODÝŽc!Ðxzµ<ÅÍR^A
·ɹ¹LäYòR°z½¶v£ÀÞVî#`2º:-ç h}]Œ ¦vÿªt³èß’))ZLó‰ªIVá(?±/É#9Mb¯ç›®ì¬šËD =cøuÎü~I
òŒ0Ñ4UÌòȤOù´dŠC[Eúg{á§Ïƒª÷Qÿ &:açæ±vwœÒÏGÑZ¡êí$rÿøJ\bø»‹+	^ï²AËðb…¨ì×QÆÙ3'wÍ?ç¿(üñHï'æg>ŒRb?
ã¨Y^ÃÙŠ«CÇ—‘Ëh|ΙË"úÊõP\¾[ârÈbˆyT¢ýïIöv;ו]‡äyÎßÉœÅsž¢©œª¨ZÏ~Tblάi¤t[dærÞ¼,ðÒøjì_
;€àž¦)ß–´^¾âòñ;y¼S9&¾*Ñí¼D@‚~À­%¥vݦøÞ­%øºu!·5õ¹—%ŽŸÏ‘Š¡—ìÓ܉Ê4¾Éƒ9ÚÃýNúáÁ€{R
Í•§|¤i¤¡…”¡aQ¡úʈ#i¶ßþ‡QÏû?â°aæhâ>2&—Ò3g¦¶í‚“-lêr¥})ï%í‹\.¥®K]•3x[RéïJ¬MxžÈ¬Œù©éËxóÛt3…*‡¤örÃÁ”H§)/S×|¹<ÌÖ¦M6ZÑaæûeÌÌD´Ùs§K.—^«LÀz®©XTÛE-ùFâzž”x”-x*4‡¬Ÿ÷Í—lŽËçISl×ÑÂvÂ[9Z¨;U6fOš9Üÿ! ¥÷§kñ²“×µ÷žÇ?/™µ´ÆR‚~ŒIGcºKJ™“—åðªÕ×㼯˜‚_ÂËûñQ6t–d©òV.$£ÕfÉ3®èÕuÌ
̲Gó^ã4%•q$9Uð{’)‚YðF¥ö›“”#=A–€gùÈØömålz¥Ã~)™ÖYÆ–EÎöÅ2KK)RðÌ·*d›'€“LTvåI!…Y]Jv‘ì¯Î¨Ü•Ÿ²Å\Víœ1Irïì|Tè¿}̘wÎf	%œÅ1JZrmÌ@:fðqÊÑ7Íj”^YRˆá³ÊÀšT#46 ;’•MåúÃQ;üšRvߤ¬€mþ—™½¼6,O# ›„9¦Qn’D7]žº¬‹/H¹–²ü%×¶%BLò(ƒñ‰m°$Åç¶‹Ý“™"šÆVyZß>…4à>´TÝ™%å6=O•ôû´ZŒ31Ûª\Jæ©f¡*…c•¹µt×Ä!R$É•®ó]LÕLÚâ& ñ—ŠrP&:O]—¸SNÓv\Ç’¿yÓbJ…b¥Ë9·Di]¢È¿²âw„
×»ó8t˜>ÎÙîê9ø¤Í<Äñ!÷S;àŠ=Ûõ(Qå]7J¶m¦Eá
ô(â
£¤:%yí+"âËç©ÿ±¶–òÀJƒ}ªSÕàYü4Ô,i›Â>1\à#³&wTbdÄ…ªÉbÞéÁ¥(©¡
·Q]@ÁÄÐÐ%) 2!ØýÐeNo!C®Ë×±X¥ÈùŒ„ðËѳ¸y¯Þ³í[³¸áž*^œzÑPɦY°'vØŸEà¶K1è›l²:1ò¹ñ¼@üíý«vAÔV´O"<™L	ÏU•容ÔÊÕT\P*¼U$GQâ¡Ö¤O–¤`|8£/«Ó¬ª
M$Þ(YUµà_°ƒID€Á„9¸¹¬Ty«›²A*ù‘#I~õ4Ä¿Ël¦LîÎh²"E}'l© k¿%Xl]”˜¡(Òiî#]}6(OÍËANØ`x. Ì•û­þ¡O’ ñÌ(ÂãÓ5&ûÂ:?*4”Íîy<Ä»„$R}J”L{0³ÔžVÉmvÖa ,¦Ã{ЖêÞ‘ÙnÛä]¥‚Uq®pžÕdjw)Q0PÛX%gŽœfÙ„sSoƦ*I˜ð5Ü΀gÒIJ‹úÇúj(Ô„ÓéL;7v2NÙ§>T
üCÊw
)ªl[~F©9Jb_þÔÖó¨ÃÇëFÞµ¯Ú>¥&Î;æ\T”•(<…cèÆovè¢7†AþQ¬çšT³™¢øa)mõ1²AÕ}ïOQÌUô©q߹“£k_Ûœó¬…å{rœèM^Š8È7›¼*)í7ÉžÍØpú^@ÁÑ'(ºÕçñ#:è?çè8OL‚˾˫´'20úˆ¥HmV_†õ8„†}kñué"ÊÁ­ä qUFxÞÄSì|wf°
ñäöVYÃëA>±„ùíZn'}MâoµKãàóDÀ÷à3«ø?¨7`hæ=ôiN¸Ý\ƒÍØÉOм‹²äʶw£sŒ>·#Ϋ
ø$„dx$·Oùîøé!ßÖS3âY!,}ÂDÒƒ<<ïb©9ôÏùoñäÓ#lÙ|ä´uÚD.O®]KïÓ&¯ip½ßTE;ÙuúÚ4»ðí—ñ‰d(’—ºéUdFºQŠŠÝ²n©W+>¬Xžá÷“äÍ”ñCÖÞÈ6øñS>¯ÖaŠŠSúl…ñÑ+éÓ<¾p4™ŸO˜FŠ>?Âõ××øx3‡®eÃzÊvCelpeøþ/a8¾œl;T.näžkãU4šêÅ÷mi8q	Ùè¨îB|]˜…·r*(øêðÑ_ÿÿ¤ûÕTendstream
endobj
463 0 obj
4798
endobj
467 0 obj
<>
stream
xœµ\[$G±~_Y:aÞè²ÜMå­. ó°€
F{Œ„0‚Ùõ°òîŒÍzlþ<׌ÌÊîéY°ížª¼F~ñÅ¥øöb<¸‹þÇÿ}þúÉO?›/nÞ</nž|ûÄáËþÏó׿¸Ì
œÏO븺‹Ë¯žPOw1û‹9ÄÃè/._?ùónÒÎé/—¿Í=‚«z,ésŸËëÜî—Ã>î~3¸Ãº.qÝ=üîÓaïw—ðüÃa//>ö!¸Ã8λ)}Èo¼_óKjYFø®«§±?<¼Y¦ÝÇ:îçÃÿ”>¿Ï}\þcYµQȯ¦‡óyÖä,a„Î/yKž|™˜¸8á0ÜÍ,÷£!äÿ†w_äÍýn uq3Îüûò*·¤‰I†µÔ÷$Ä}³[W’åË<ö-lí«<êî.‹éÃ>í^Ã_Wù¯ï†€màMnÇ‹–[ïq!žQ€~ŠØŠ=”Ðø&Œ#õš>¬(ó§ÐÛÀ¢”û)V£ªúŽAK[æ'"+G‘›[Œ¸S`š©„½Œ@Ld¨+zŒl×î;µpóî¶–Ÿ=ÏÁ¨:ÀeEˉ´Ï†N¡ž£«f@µ‰Åb=²â®µ®àç
B9änõõn@U+@É§™,c]mÉ»¯U#3lÏ>—*-èþÜÈù!
Æ„Rz@ƒ’¦]CÅüJNæYÔ-7VžÚákj ÁÊŽSmBÍ6·Ç¼’‘yÀ‡ñëx&m%ö¾&µÎWt)¸éÆ)"\A°YIY™©bN/Ð
wÁ[Ë[ì}S@d_çõhüCº¡ÀjÞªé}CSå§
`;ò°Éâ©5åFÕÁ‰¿Gö‡Ü0¸œp¦ṙFç
XD§°‰5;‹åÉÀ¬Ö9b¿Z·K¢£ï@Œ#(HˆÉ¯ULŠÀŽP¢\£’ }½ÚkÖvÓaômФÁÝp€Ÿ™nÿ\Ép\}¥„k:m’ÿAw0ë긨yã縑qòÌ®•pÊš$±U|-©¾"¥Ç¾8®ç-(žEç…pSxò¤C(nÂàˆ2«µgëÛ(d5‚§f›ùŠg{;,<G~úÙráâ!3v‘ÂŒ:Š~òäòý?ï¦ÁÒÜ4HÎ…uç³8]f¾ÙùÆh¦Ÿ–1ø|ųË2‡üâxð™e†Á0ÆŒšÜÀæÉ­È=òѤqåþÙ’&n0<2= {I‡%óÆ_
c6]kž–»Gˆ}½ÄõŽuZÒTσݳL>JϨaÉ.oä¶ü|c.s˜ìBÊè´¤´Ø>½kE†—ê‚`ÒªaÐÖ3Ó+Â*ö.=MÀüsÚ30Â÷¬2ÍÆÓÂáU¡…im鈺}¯æY×\´©u}'Ñ꽞ø:+H£Öî:6öE'ºÒº¶óF‹ýf€ËA‰p…Þ?&.œ½¨7å•ÚûWlPÿ2ZoÅl	¤¤!üþ—²æ•
˜:&.Êè.;„EJàÅ'}ÜÄ@Ó¹1OX}nZÜåØÇ-â'së0¹®m<;ID9˜a’—5‹H;õ°z4½5 <á£Ý—;mÕó•ßëy•Gêí3{Œ/Žw-˜>_´!V/7Â"²ôjâö‚­äsàŠ8‹‰€‰•SG±Ø«[޶»Bg8Q ‘$–Cb©ŸÕzªNgA;—ð"ˆíøm¢}]ÍÆAþÇgçG`‰Â˜i›Ì
ç4Ìr2·%døó:ŠL¶cœö•XL@âîoUh¸ò-ߪàúaá›v?ቚ¼ô=…î…bTº6ñd#:ËÊH@®dx”¾_KªG=,ÉçZô|SÍñ­€‰ç…YfëßjjÆ‹¹²q%oÎU²|: oY6‡ÌºÉäÿ$³ÞäâóOhÌÀzŸ}RZhzÚÄ	EÊe’å¥"&z¡4^ZnAà~(¤ZûÀ|ñ+ïHcÍG.i¯zf—ÀHÐë–l|Úæf%ÃsLÂ{‘ÚÞçQwžˆ­êkØ<ºÕÈÛEÁÍf“›ŽXØà[5Ûtäop.ø#¹§™E6p|Tµ†öÔ¥Õ¡Í)»ŽÁµdX±Ü†‘¶q<š(Ë”ž²Þðç
;¹Kæû"ì¢Aj»Õ„™{›êS7œ¾IIÌ–_ФÁÑs¾Í|m4šfjyµVCóÒM<Ñ€4OÈ @äß‚ž»*Åä¼ ÜFߢè>†;ÐÖÍ2z€™ˆÉÝÊôc.·î03¦È!ûÊ\•¾`.^©yįŒ%ôäå"hxø(óq\ 0bc8E$Ô¬‘ËŒÕ@}Ç¡Ù5å—ø˜Ò¶§&ÚS7ÎÛ­¤’¦ìfêƒr³\Îé<5º„ÿFl©á”)©RŸŽ¨ÑnG"¬À¹ÙÚá¿þ¤µBŸäA±ëœìkÈjÄ à4Æ%ˆnˆ|×ê¢wÏÂqÊlðÄÔoÁÜÛV±‚ž\JáV¤gÍîÈ—
ã5HýV¼”R0ʾ5µmä0AÓPìJœÊ¨Æím)ÁÅêÞ„Q8ÿO}ÁDŒ„’=/wKÕrÂÅäfhÃf¢H"%u·4néy!U˜ãGAûuÉ­hþ8iŽÌ)Sœ‚:;cE":¤MòŸª5R‰+åRµ±ìœ
”
Ò»X¯&‘ncô£ÚåÁlÂ!Õ©°‹pø•‚ç6áòÕ×ETm ªÙ^oD³B	ŸeÒ³žœj59Ò³ÿIº®¸u»\QÏ
LdxéØÝ9’cÜW¡$Þ[}‹l¬L²›^
-úé³~Û‰‚=ø2`Žåh gâB•£ñ+ui+QÍ|åxûù•µ—¦1[1êИ1*äåÄwåÀ33þ1{åšµ\MԧΫP“5x“•ë]E­q’$ÒRC;wü¶ÆBz‹SrbF,ù`(,vV‰d!NnR­¥LU@A‚!H*ívé\ï|ûdÓÍ
¶ÐµÁ|tÛäÌ÷bïñR5YÁ**>ÏèLÅqõzLQÍV¡ž(	’
Ã¥J*³ú–ÀÏÏŠî¨N”‘yjÖQjP|þk=ÿ¶Ã'"Zžì×utì—å
ÔéckA/¼Ö9xt¿€m•Š~賆§ÑnÛXÄkE­`º˜¢,’ùlXØ4bkªeÀ¿¿Ð†Gúa‚Ôiçju*9#(Y‹Oˆ3âd¨ÑÉ:Hjú ÀHšº‰´uýÑNZn.OçáPÑ,ËAAS/3º	Õ‰yú+½Îækƒ/äkƒÖ–àÐõ=‡Cú¤aÍðw(ÓÔº¶Wg?S#µ¦™«- Ú÷Tõ' dJ%µ¶a4Óú›aô¸_=%.Ã%¿zÙš‚’GëVtòr¡Ý?%BÙ+Ȳ¸ƒ‡oŠyÊh ¯¼œc4ÒªC¨øÜ1£ñž0{ížØ\À޶|dÿתò~:½ñ¤™ÛR»ôµÃÔ§b*{²	:Y¢ÜËàŸk$~ÇAf8I¸"—¨€¿°ŽårÀ’ßk<|É®ÎF`•_åöŠy‘@ä:"‘9úyOÿ>rÕ)§¿‡)®.~”Ô0zÞUûÉŒ«µJ9ãÅ×™ 3ÆÙŸ'áÅÌœyNzà,“¸–ÿ_ Á¤&/øS¾5÷"eîb듃8¯Eºñ¯€È„еäý/‰\°!c‘ëã«Ú­/‡Ü–¹”mJêLÕÕtÕEŽî”l™æ“^à ¡vuyñTl+&ÿ¨oÉbšäÌ˃Fº‰¸àGIÝ*>“ð 5îÎÆ®cšÙF˜ ¡LzDÓýiÖž>ÊØ!8ã¬"=“X'û~C	aã^j 	Ø$˜µ"tmkç«Cç@®|šTº1rzÉ¥æêš<=ö#%(ø8ì nš…áÐé§6¼ËK«äÄRØâ³æHZÇjí1Ò‹‘ÒFÑíN·MÛt£Fî;ÇÙO¸mëJà¤
MöݸÝjJŒÛצXŸÈ:**¼¬1;Ê”bù–r>x bu’ý)Ç·miŸ”uôòÿË/d9Á®Uø¦¸ -ß*¦j[Ã¥V®TÉhÅÆÖi>RójLÕ•_Y­«¸,¦y´LÓ¬k	QV¢õ®@F¬NÞn¶Ø÷jÕwüêƒÊBdåù꣮³
¤­¿$Ú0•Ú³ø™xS¨\ÿÀQ|…=}ÒMŽ>Âñ_òC<í_ë $Ä,²öòÌ4¾®ßâ¯Ìœö…Àš0yT<ê‘…ê¾ZøŸõoéáÛò°,=c)«™ï»:˜{b¼ï¬Æ2-‹ÚÞ¾~’}ïëÃëF¿jV‹†÷ÕPJ()W7šØŸ‘Ú
÷Á´‹>ýjó3úö°lÞÈÝÄ–¸­–\­-³ƒ•á–	@0¿‘–àߟV¡-|¢]ð_ h‰.Ïœ¯ë àÂÝß/üÁˆ¥Œ¯ËÃ,Äø:ò{Ïj¤çæüÈwæzi•6>›³¾ïðEo©Ÿöðsì^œ}ª™?z¶DËôG¡.«•äÛåX¢Ë=|Üoú¬¬X®?ûŽ]š1¾SÅÚmek$:°ñÆTwèVpVý…T~“«0%6¸|¸~^Õ-ºS ßÖcëV9VæN
Ió&E)p‘ŒI®‹T´däT‰T?)}*ôø„(š´/Ÿü!ÿï?°¿Eendstream
endobj
468 0 obj
4643
endobj
472 0 obj
<>
stream
xœ½\K“¹qöy´aÿ…>vKêbáU…
…Z‰+Ñ!KZ‰,†œÙÆ’3ä’4wå?oäH P=ÓâJ¡ÐN³º
$2¿üò~·³áü÷囋'šw7ï/ÆÝÍÅ»ƒ_îøÏË7»/Ÿ§œIW†e\Ìîù7ô¤ÙÍv7;?Œv÷üÍÅï§CØ»wø÷8ÇeXâ´ÿÍÁíÿ+]~v8Úý¯~ÿ>üþƒ—~Ÿ¾ÃK>›†qŒû¯øažö8ýþOéoáBÉËý·O0‚üû÷ù›ß¤Ûí”þa÷ÏáñßæožÂ+~ƒïƯŸ–1Ò‹Ìþ—œyà¯óÒƒ0ƒ¯îN+ƒU•·þ
îÃ'ph|,û?Ïÿ#‰ÑX-FæaŒI’ϯ’ôb’Z’œÜ8ê;ÞÃ<íŽ.ý1ËBOü[¹»ÚôîáqšÆ½Q]¦Ò^\‚0Ó›MØÿ¬*¤ºýÛôq!‘ß§_¥¥Ý@ˆ xì:íÜwp¿ÇûáÒ}yOßò.n†Ëqÿƒì
û
<áÒ»ýþ}‘z+Ýa=ü1M6ýÓÚýËôÊü\¦`&ïËFÂ]0v5]zæ2¯$=›?ܰ’žåk01zæ^Vò&í"o4‹Žnxu©ÛyÜdDÊ4,XxàE-Ѳ¬E=ÓR`PO¯x	bKÇý-5¡ù¼Ì·À(¯Ó„ËHjŠweQ¼Ú)ƒk|CËK—ðE7‡ ^l¶¯uvÍîhÝàÏÑ9˜ÁOÞƒ\㦹DT6KûÒ¶—×è>·€~Áßÿ=8TÚöŸãPYoe_E¢VÔ˜7»ÀýFï‡è²qY`J3q÷ïQ…a˜O`Èð;âž‘2ð*åÅÉ\ã"q‚Íûn´.®2Me‰s;•vp½“@¼ˆºÒõY3@O®	O—h÷ÝgÐj´ãm~¦óýዌÆF¥ ¯Y–ç-¦ÿ!}›Ç‚WxÁü°úýõ Àꎼ¼cH˜ÀµÀ*q`¤×øR‚ôÆJư%¤@ߌÃí¼:“6ùm½W¤—d·ýfì7_†÷Ýóî“v´0%ôVðV\6‡+qssÙ¼{-ÎVŸÁ§ƒ¤‘¢¾-^©ØÇ¬`~‚îeµ›&/†|¶Éã°<$;cã
äâÓÊìLoO’ñÖ£Õá#Éeƒ„Oüaº_Ðúü¸Ô"ñx{–Í{c¡ÙÐ<µ[›‘X¿Þ $ãª}‡·„+Ÿ1-Gè¸2d »²&+ØÛmÁöxb׎ëÒ-Åëw}P¨Âû:7‹£7’eó¼Ñ´ÃiúÚVlm%	HA&B5l( OÆvÒ&"Ú„xKƒûqÂ(¯ÄÜÑÛ`Ê/{§ý2;)'ë|Ã*“;úiÄW ?„ɃÌè!Û1‹ØÌêßáÛìÒNØ•3ÐH,›~'gªòÕ¯¢\Bˆ“#Z¦…ø5!|æ›°
€×0IsU„å’	K¹ò±rP$,Q¡FYhaµÐÛo*‹Å 	c`3ËFw´>œ0GÛ±Fk‰ä¢±fY7¡©e
Zm5£Ta´G;²À7ÿZxš`\ÎúøÃ!²‚–ØíH´Ä:ÇÄæ±Zb]QQ0(Ÿk
@Tìb‡)‡+Åeâ5kJôËFwÂë+]³h3.+AÒ³š.c 5ÜÎAkÛ{’†‚Zëé-ç ê¯¾Æ¢•ç_\fDs
µ¡‰‹Eye¸¦[`ØJÞŠË3ÓõfÊ#eŽ2/ÈQÖ,ÇÜ@Äå<†àRÞ-äÕÀuˆñâ´Æ~ÔK‚)`Ú•®½>I•í¹‚»lÓw:ä[tÌrœ2û‚¦¬€¥E–îpnØÓ’:ÐÙ“½bJ³î5ÏÍ”ˆhê5½Ö|sÈŽÉMËF(l`*iôäÑžµCuaÁ­n h²Æ:6‘d¸…
ú¨¬”,IŸ&"-­áZ`úkÍò´gx©‰Vߊ'ø(còz9–NZe
¡‚,ÀM¥B±ÒƒiÔG­r6YÆåY°ŸÑån-8/ÏÎ}å™´oã©ÌnéûFZf9"šb¸Ie"yƒ¬2 ÇÅžÚû*®À†ÁšÄB)Ðöã}ŸaK@»É‘ECòPã-&šÚ ¦ƒt?~,)¯>à; š0š„D#ë.AãßÀü›žð-‚°SÄŸXb›­Ò8÷¼³¾ð›.%MwÕæ¹¬¶g$ì‘h£Ä
qª½I:ŽbðËtNÐH†èU´—&~2dX(;ÇÄGP„¸¯#†4Dí1Ò”qik¹òa9Í¢°c·qÂ5n!DQxÀÓç__¼Û%K˜0©Œ7îŒI¦ÈA·æ#äÈ¿|vñäÙî>|÷ñúâÉ_væâÉoá?_þñWéϳ_ïþåâé³Ý×›ùóF]9nÌSL¯L¤º¤¾Ú€.lÏ„íÿ	ó
‰3Õóm2ËaÛš“×s·5£zf–…‚OD(y:_=/`äàö8¡Vg
§ >2Ý"/‘î–×jo
c†Y_Å»
}+È(4ÝÎÜËv®f]E“nŠ˜kò¥ˆ—·Û0piݵHÇìz³‡4unŠåñ¶²rl¢¬ÒNö¸›ò†B}ĉI›!ÖÏ„‡þ†…w± W“J,xÂìÜwB¶£ÁFõÏû>/
c`Ï0 À¥K•lUuò^8ïsŒÉfðNåLµ™3A¾³á÷léJïÏè[à‹‚Écñ1˜ëµ*µSÛðåñ솶T Àk}.¢©ÚsΊ¼Çø=$`O@t¦tqœÊäY†çŸLP¼6xÞžªvpÅP}1lm”ë£vÆH­øâPø…N1ŠçZËI°öiÑ¥½éW˜ÆÁM²éÏKzÚµŒ«§Þd†¤””SS™A=º9E=ªi¦.@äÚ`?¥‡R|èqê@5\†ÂÕo–¡¼îúÙ(
äžÛW‘gÍMAeuN^oŸšÂãÌ¡©íEðý”’¯y!-A‚£•†¸¢Ø¡‘¹ Jòr“7»¶Œyb*Y|!Q°b¢1èŧ«HRÝ5PÒ
X¿ëÞ:&–qU.^§‹ódÇy¿.7Þõn„ÍMgF wI=CRÒM2',¯ÍƒŸàX޼#Vúœç˜håfòèh£m¡Õòê·åkØèÏO!	kã袺·Lð;ŒÚ‚¢Bz|d/—þbΦ"M3­#:—ˆP„]˜ƒÈÞ¨æöFŒ3TËYLƪ1Ë3½l´)
È»˜óÊ¥–á2@‰w{-–¥Õf¥ÏQ¸LÔÓ«ä”+ÏÏ6'0²eO‹ò³›­9€ØR>+¹ïæ©“d[‰&³«ŸGAçZÔQ‡ŠIıvÌ÷„mÝX–ùÜ·¨ôè?7T$dUˉÀÓ”×SåÒOõKKo,³­e}B÷¤B7 LýJön᣿êQ^ˆo¹,ÇEÝ4G.®å–YŽSÒ?oiÁB}cÜ Ió¸‘àšÛ²á¸~ÜÒ›†žéïêÃ×Åye¼jªjLšß×ð¦:–&ÑK¡É¤nÄ%Ë	–aÚ––*©†µ=iÿuX
²‡ˆmq´?þTh×5¦:eÛ<
´¨FÛsk¢@ojoWe lÍšIìT¥7ÚóÒ	ü–5"Ò­wîÊÛá»PµDñÒTª‹ñ×VÐ#3`UJkH‚Uúɺ˜êG‡¤égð.´°½I£ÿèpÿ$FœÝ@1êðý“ETá¨ta7ÍU¼BŒ½@Sn0ÏU•¹:À±>jšu­þꪚÞݦÏÉ(iåÃ4>ÿ­%ÉΧ¦D«6ñ[Ý–™È@XµPUà³NÝ0Þ§f‚þošUî½.ö÷CL¨øSÙ¤|jðDÝ#·™8|9(Ò„ßbgyy» ¹Hù9¦—²å®(}tR
çý³Œuä'IL5¾	׉ö¬¸Ÿƒ>€‘†7‡\ÿ^áÅH3
^pÖ¬‹XU/(#«Ýk
(ÌeK›óI›©‘t}%ÿÙG•ð”íRµô"sŸˆÉJÎÞIµvÇy”Û2ß{…ÆÀ½B}]ÄÕù
гãBÝFJGoŸ3Ä:áa]ûÔ^7ž^•Žê†:N„5†PêDRÁ“½„¼¹DšÒ¯¨‚ô%
Kw~‹½ÛŠÛúV§™70.PÞîø^ÎàVCg›Ù¹&¥¦¡w>!'`HÍI½N™5z?›úÍ«®óÜý¶•yBÙöõîÇ©.	¥­{Tšî´|Vóž«Ý²ìí° 0ìCJ¢m	Qx)œ:V4,ï™äÔôô}É}ožpº±âñ¤|ù‹*¹Ï?&ñÈüT}ÄžæXuäI•ÈÆUñ±Û—%“:q´…ÍÐŒå¨Qr­æ z…èµÇ.¶×Unœ/K¿ª¡Ær6ÄR¿
m¸ßà¡Ìh Þ6©Œ
‡µÏ/Â`¹~ Ÿf™ˆ" 0¿&¨Y¢šï”êóK.HLP¨~Ò£NjÊiude³WâSñMsõs—ñøÓp¶
Älh1eþëa€Œ®þy•#©j€¤æK×)ŠK¶”VY[ü¨:
«~Ò@ÔZèÅΗ¥æ×êrc
†®~­³í9¸¥9Ú'aâC¼„\$7ÜM(øQf‡Mܾ£ž%·µXÉbÁIü†þózÇEä×>˜†ƒ|nÛOê¤ù¦Iï¯ùÇyIi¤y,‰-ÞnjÀÏ«…×uÉ1ÉPzêTÇ"›¢Öan(šj$˜ÓNGzÞæ„¥ü¾†$à3Ôp3Ë·’Cù؈:˜uöªJ;à/”’´·¬v~LD÷×eM©Û꼡íU¹§‰ðÔÇðKž£-þy/N²ÓAæm'[ÞJy­e˜ke\õt%|N(6'
è#˜œùqÔWu—8w¶Š,êNšžW}U­Ô{HT”3øå?4íV¼ÂÁ´C$‰HÊ]Ÿ³õVõc¶Vš‡bš­éô¶éKªýØt•çóG½ì·èxG¤P¼óe®š8¯çÚ‰Æ`°S4ŒCOù¹ª`»AZ3?KÃPÛpoÏc3{%?N£ò!˜hð¶!ÌQYÑ
ü‰Ôþºtžl”áUo+R®kÈÏæ<º‰»&fÎÕâ'"Éžð’DYõ|=€-6ЭOÒB Ž`éùç©G¿S;¯„CÊÁ›ÉÔMYLÓüÀ‰y2©L7Øpÿ’Lò³W«`¿œSÄ#__ü?tF
ßendstream
endobj
473 0 obj
5280
endobj
477 0 obj
<>
stream
xœ­\kGÕþnåGì7fgèºtu7HH!$¼¼‰A Áz7¾(ö®ãµ1á×SçZ§ª«gg-díîLw]OËs.å.†£»àÿ½zýèg_MÏï
ÏýðÈáËþsõúâWOrçó“ã2,îâɳGÔÓ]Lþb
ñ8ø‹'¯}³›÷ã.îÇ¿?ùÿÜ#¸ªÇ<cîóä:·ûlˆ»ÿÛ»ã²ÌqÙ}º÷»?î~÷ž¾?È‹¯ö‡Üq¦]ÊCóï—ü’Z–>§†Ëâiì/öÞÌi÷[÷ëý¿JŸ/s—¿Ì‹6
ùUZp8Ÿg½ƒ%ÐÁù9¯sΓÏÓˆæ.&†»™å~±ùoq÷ç¼¹?ìi]ÜÅÌ„3Y^å–41Ѱ¦úˆxÃqrËB´¼ƒ¾ÛÇÝÛýaܽÌ3ÝfR½‡Íâ«WùÉy˜vãî^@óç¹v¹ÜëÓÜjÞ½Û‡ÝùRÞ0ô&_°/ü\ÃÛ1o#à„Ï sĽ¿Ã½;WF‰3Îý¾ãœÐ£ZÀk 	vʇÇòz¾Ð^‡…Ç[ÔS]b«¼¬)/zÜ^ÇSØ,•(ñbÄÃpL —{Ãïþ•F©úÆHëý
³ÁDù‘Ç¡¥sLÁžc^ü˜'“=n£^–ïèc3RŸŸþã¾¶ß•§oËÇËU[øø]éfƽ¾¯Ûeéöí®<þv¯Ÿ»Ìò©ºtqpvïiï@Ù;Þ@l{¿”O?‘G@ÏaVÞóÄìp!à±Þ W1kåEþGˆ“xÁœ@%Ä݇¢L¡ó+üÉËÚÒù¾©6Ïm͸Fy_ òp³X¤Æš‚ÇÿÚ/#L©f>Ëx)ü1-6ù£á#ñžEîn¹‘ž¹XY¯Ôê’f(R-À	*A¡U•6Z
ËùYƒ·t‚ð¾ÇÍa!—Ó3–sˬ%™z5ñÚúÐ^™|œ$ô˜E±Ï}¬>ƒBÉÄÊ0dŠŒý¢ØÀ5=jƒ¥GÁ¶*Æyïº:‚¡G…Pfs깂Š‚¡ct(<`†EuÁ8fØZçD¦tÃ
‚×åôpzÖg¡‘„˜•k7Z¶:Ž“Êϲ¥`ECÝt^_ëkV[H•ZkmZ¯È–‰±™¢¹Ö]Æ“ïzöØù¶tV£ÁÆøº6k«Ñ±)u×+
ºO%F’*˜Súˆ4Øæ
@³}æŒj?‡Ä2CL
T­då¶@äa»ü?¦¶’f,rRu¨5R·¡n!bÔ@dŒ^qãAÛ¨ƒ5Ä8’ïNVucž#¢ÔL‡ºì–c¬%¨Q¶SjM$"õÖ”†i±L±ÅÄScx´‡‚dØ4Æ¡B«ØPl A›<«AˆbùÎdQb¸,_ê	@¬œpÀâgâÊ4óº-Ï‚ ¦Ä›U,À°ÃÚùc˜é£\V§xØà\Ð6"´r¶=¤HmBMÀÈ[š7^¡¦(€·ÞíÄÏØA;iw»	(×p¤Œc¼Å-(Yyî·ëˆV"®:É:ßVÞ!;
ÛO¾Ò Á)NY"Ç: ±¾&uÇ)•x•òÑS™8»œìS|/Þd£û2“Uë]!÷’¬ÒlóÊ×…!ŠˆJ’{?e§&ÜçΚx*my­òî¼qà‰R«9õ:·ýMŽ^2/â{¶©Ñ¹u¸‚C‡âíúÚÛ
Û)o·àk^Bœ‚ÅKfɆ·„'AÁ`ˆsé6N/,Ó÷Ù^Òi+ЬÖ$d¡ÀÝœ ^Fo<&ÅufmïX÷¹•Ó+qÜnò
=>2ÈO33e)ï› ©[>ryª²œÏ9Ú©Sk¿kcÉÊ«Ÿ
NŸ£}?

ÍoG8`ÅЂÓ^Ñ
ÅZšìS3÷æè„	T°žùcÂçUbµ™ªÊD—GúG+ëøOÈÂgû¹¤ñbήÃwª»•l@ÔÜÙVÉÂSÍ[ÛPx~Ù›±Çî‚ÀCn¹‰Ôfû?é7t.¶c²ÃÅ(J¯ïøQa“>Ó`=».nðaðÓ90/V‡ll¥:ýÚÎÏ`èLÍ<»»Ûf7¨äÕ?¼¶cê$’uÞá¼Æ>Šº;Ïó„?ú»R<ò%*èeÜ}º_kWµÌËC Gþ•­Ô¿ì¯ýSy	­>çä·즡•fúu^8&`¤_íq•¦x†JTVk™t-ãj-âbí;ØlÞ<*¼Q[44»MÄép—NÆaÁh’žg±q—V'˜\âƒ/¦>}Ä’-³EV	Ùb&UQß¾ÅÄ»³:&4µ³Í”³€ˆºxºY2ŠéQëKÖ€„Iœo"gÝaˆÐ¤’K®ˆ÷²^ÕŸ™€·ØV³§2#×4ÎÅŸXÄ'	+{Ñ:ò\œ……’URŨ5B¿Ô–óXžRCn¢€»œËsYäT¹¼ÂZLßQè›"z5i­]â(—Â+){X²ú®Âýøª5g?U±}F‡	‹`ˆ~…1@ Ü‚íK`+½(’Ø…Jÿ;ÿµ6wH§š+OU©Öàø"#PÓüøŠs¥ZÜ£®oÚ˜\î¹,Æx¬@é&zjÁµ4SßQÜ=vÖ'š¤Ô›©µÒ”ì7ö Ÿ)ÈÙ~4¬­È1y@•÷*]Î}Í,òŽ0d‘{]³˜šÜˆÁx°k·à#rÂÞ–ÌíY¤£WeÑœ
æËcœÑ²™ÈGaΫ¸p‰¢õf¥¦¹ô¢WåCûߨò|ͪÎ~uq½)þTÛС%ázj$štjxƯÕ
íìO¶æ‚ÒgoâÚgT+ýÉ@A²jŸ¡ä ¶”s"4yj¤hÔ±cV^]ä’¸Óå@}lNJmî×zÊR¥+o~¾G<~‡H3kï“Þ-|¡A³Á+ŽŠpZûK^#†‰X‹[_*’UUŽ+~8„òJÆ2zq#>_¨4!aNÜk§Ëâùüú×0
•L¾8uÆ=–ŠÁ«¾4¼yÉM¹¢mb§Ý€f’èHÐûA*KÆèr˜xlXÜV5]kF–ƒÛæÉUÕàñvß„dWÉò‚|üLÃ;|pÍúy"Óè¿›Ú>)(7¦/(„*:(ÿgù¯ùç'ìGeÙ¨býX±Ùß´ûõÆYe°ìåOõR7Rü‡ª¶2hF¤XJ_72”dà œ[˜Þ5YT­;_¿ïé×dðR¼*rï°íw÷0@ΨûEIš°øÁé]WI*Ábu¤µÂÚ’áFkK¦…dE.ëzh€6FÐøóù#ØLQ•jˆDx‰Z9r¸ã²NWq¸á‚@Ã>®ª4Ë»ºÌÍ'ëÕ
µ¬æS”鮨bM¦¨lmÞ¬[q-[9?'ðÚÞ+ÀÀ8$3@zA†@ì7 ®Ã gHêðý2?tw_RŒÜ4/N¿¸åq¡lswœÆ…¶—øá÷å¡Ó‡æ>BQÓ7¸`ŸJ«fÝGN¦Ø»å¨÷¼nyk[Úšóü=ú{÷xêرä·(ª#þbŠ‹ÓH΄þ(ЭDV
L^U½
®²qm‚«.O„Èã^Õœˆ9ö½j©SZ8²Æ½OÁ“;j¢ÈµÌ]ØÐIIì/VÙÉýE¸ÚÕæþlL÷hƒ®TëR­	«_UkJÐFR-z*78ÃêÓ>?6qv-Áãe°Ádñ³Ü§ÉWfƒr£*x£—sžD޼Jhhè™ÎQ½ôÎjéXvŒî¼\16áO@š7ÉP¹|bÑÂ\ÒŠŠ\B¥¤¶9Èrù çi±nã&ÊhÌ6…Uª•Lê« H¡ÂQ^L.gýdC•j Ûl½·$qï›áP_)à­ÔlõT¬ùMÑMù/e²›Ò¾˜œ*žµ‰wÐÕ&

C±ð+ãÝcpŒëŸ´ÉØå¨·ª²Ðm0ªT¶o˜Ÿæ..-°w¿äÖ—«b1;i\ÁRg"E•Žs´LÓNŠd*ÒnÕ6i"ÿtf6Ú²JsÑÍA8¹_³M
ikýmYΘ•îñ|˜yê¾\¬¯üÙk†zqV<
„q&¨"{Hó!+.õ­.+¶FR1ú¢dùZH¥dC)œ%K‘ùMÞÅRÛÞ,/âF|•£-álx˜ü‹öþ"†¡7üÒ£@Ôù"[Á“=]ʼn²~’›))ûuãyÐÜã8:–]Ìòä<€äÝgûá˜ÂéÊ[j™…øu~èÒü¦ÕçÑ}æÎWØX dÔg˜äª„¢Ç4*å,” ý<£SÈ}îÀTf÷*®åÉ‹žO:ÎQ*å²êó×ïç!ÈËGeÖ·7x³yu—£æ¿ÎẔ̌ģËûW°Ž1÷!¯ßÓÖ\Ц7-ØÍž€"½.3›]ôàcäB맦Di!t!Êbž…AW×÷l È2¼b¯Á•‹g1ªèñy:VÅÀf.	¬÷¼5›œ™iŠøÉHÎÃX ]3™_ùºmI¾ë¡‘Óö.$­á-Ç|XŒ\§¿Wà6•ú‰n&­jæé⑯@g¿„aUDßfeÜÖÔ4IA“Óª#åMEC%ÿ wJOµlƒ/˜iÖÿì{BŒ×H”x3—ú¯ûXñº8HÄðnzáòа\>°ßJÖh‹ÃÃHþþ?9L¡£Î7½·[ѽCä*¹r—îܪ±d+.úqõ¤W?Ûz¬¸tùX­ç‰zYn!1¶×5‘ã³¢ôƒ«!I÷âf*¡ÿêRQw]âª~D‰`çr®\Fÿ_^ÐE°ÖÇTꔿùV<ª,¦e*ŒX«aöfz^q	$«YU1uIІkJú“«‘h,5½‹ßb¶ÓÅTç]q…°®.åý›Ëú·{IänßÚ~\éD%A7ÁÛí& åL÷Mu–uÅseùvulqµlK¼4AkmË,ÏkÅí¦SyXŠõñï¨H¶T+$RmGRU¤BY³’ráÀN*•'±õ"r¤R5«ª‘¢Üº¥#x¯Jç@
rrW¯¶_"çš4ãWamÛá_›¨În^ñ­*×T¸f^ku© aû:òS³6.ûZéÔ™ãŽ-sS£Š÷ŇN¤—±¸N¤Ÿ½^lä§µÂ-Pž§Ö_UÆ™s&5êu¬_£ûXÐßßœ?p¡°&­_îË5bHþ¬.7ÿ=À‰c@þOô°Å«¦pÓÃÚ,±…ÜAÓSê®í%L¨]kWÉè‚?NÉT×+ûIHR/¾‰@c®ææ’ 8òBÉ"ÜíMä»›^ wòLCóü¢Œ÷Š›èÿ=´Óæõ‹T’pë üFôÄÞͳiø™}ö€KˆiÜýT[]õR¯ÊÃǽ xdzӫ½ë%LËWv_)‹0¿7½íq¼;Ã^_]f’÷¿¨ÒŸ?yô§üSÝŒendstream
endobj
478 0 obj
5054
endobj
482 0 obj
<>
stream
xœåZëSÛFÿî¿Âß*ebE÷Òcò©e’™vhC‰û©éPׯà©	Ø´ü÷ÝÝ{
¦gdiooïî·Û[és?ÏX?Ç?ó;^ôÞ—ý³ë^Þ?ë}î1j웟ñ¢ÿÃJVç5ë§=Ý“õKÞ/…ÌrÞ.z¿'Eª’,剤ßAYÕY]ÉA:ɼüœŠä(ðä0°¬®+Y'ïðyˆ­p'8Ër¦°'?âåc:(°Yp„–óžE	ÏR3ÙîVæ1Ü&ß§4¾2ÍÔñå0Þ
d•nù-µ‰›Äþk	¤âT²<çüáO	ã!$R•Y^*Ã	 Q*Uš±!ã@J•U ò¬du­;Ì`bÉ^Vé@±šÖ:Åç™!Šä.0>cÉI³á/Wx9±|DÓÌ+×0ÆË/s3bZŠFŽ{á‰^ħÄSg
ÁúîÔ7_¥À˪*¹òÍË´Däz¾ºù l¶D˜¡T’4õÊÇœ–ø°Ë+²‹±k?-FWhy¹…øG¥¨ZÁTÆ¥Õù"ǧÔß¿u·Øy`zx™±]±ƒuÌPû†:óÔ†ö=ªjkžqš‰µƒƒX³Öþ–šG´ª20ЋÆl-šãŽÛâh¤Žú–¬Àéï°7|õLœàeäºbj¹õÄ˨i6ÔÚvÕS§A窱½Bý‡j­ÐϤöéB=ΟïÓê$>ÇÄۈǡÚE/ž9/&Úvêþê½xpão{ñ³:ð_Feæq¯·âéfûöÄ(ç<\›Êë`SçÀŒµxBN,ô_^Ô‡lŒ‰L˜È¢Ú Ï]ŒuÉBEcßÙ?•î…³JÖò
_q7w0:Ëyñ¬ždîYHs+QW/»½kœ§ô'YWή­Oún»×ã*ªùv*j¦±v®d#‰	xߌ½9†¼"<8Â	“k‡ª3©1婈FAc5ântF‡ÙUо")˜ŠKø‚ä‚ÂûŸpàŦq*éùÑœôÅ0«ä;ìQFÈs×ú`ÌÀŽ.ð¸Ž]Qú,Õˆ"d^Ó‰ÚÜѬ0sF½ÅЧZ‚326…€dˆ¿#	í9T@¸I•À	jñs˜ÈÚr0I›âcÞ-åT§ÏJÎ,š(çרž%Ì
!©YM‹áHAÐtµ¼Uj{œÛZ‚Ž·g¡8+Y„*ó1B+ãTb1ÌKZ¯QÒšóý‚>k7…±É3®ïº.Kî4¢y´ƒ—,“’iW`“&6ˆ†J©F²&VcKck„¸\ŒÔäÛÂ2]–¡½T(º½´2©›µ,?kRíÜØî•î—C¢0ñsña€„VÚH—¡múÄ0$Kg&$RšY™YP
tN΢ÕævÁ:ƒ$Bh¤"^@››}Í$;Ðí±;äY,…BøIöïÙ*¶Ø-k€d íæÓe Í¸lO˜äwexTR"ÿ?iÉYWZòðÊÃV‡t2^Ö]*°yH‡
|jcéO“°tÂÿë%‘ß³Š×Fó~P¿‘"Ô˽‡•ž Þ¸õÎŒ=CpÅP‰ÝmGŽš¯
λg¾¾â5wx_ˆ,ÞO
òÊ…`ÿ¶$°Ñ‹m
sÈR6VʶaÜá(ÕÛxsûw?à}^L¯s4ØF³ªm"°Åôj´»—!{ˆÖ±¨ó«Â;€ô$_PD¼Ü¤[å4Æ2ÖÒăjiôuˆ­	¦«ú£|òÑ×Ĉø¸©Ê¦L™§»'ðSɨ4VÕ¬'øÒZü+¬¼²"\à媣-`nŸD‡É4먠` óÆç‘ì*tƒ\ØO
·@ìdL¯RClj´Ÿ£…½íÆ4ëœ6|5ðÀˆ­²âfTAèÄJOÛŒ6O¼‰9Mõ}'0ïF@ÀZê}/rž2Ùk[ ¸K~s«¼Ã`Sl–qôK´†@a«èÀM‡´gñ–¶ü¢&^[>î­c˜DËÂG±XÚ¥¦M‚B'm©¸†wÃÞ¯ð÷Àendstream
endobj
483 0 obj
1709
endobj
487 0 obj
<>
stream
xœURËNÃ0¼û+|´+b¼vìØâ¨ DK1§Âµ¥ê¡E}À÷³§N«HkíÌÎìÄÉŽk\ÓÓó
»ž6|u`š¯ØŽAKòî˜oø]Â0ˆ¨¨#ðôͲxcxck¥
O6A:á¥ûLO¨°p¡NÕ¨Iœ»—U-$¨CÅ­4b"+#áCYˆ©¬¬¥uC¶B!cLD2OöÃ<£ÉÞ#iˆ	^<ß7YµíI3F
`b²HùØÚÜêPM0s\×âÔ¾µédgqGÒâim-Þñå^dÎÕIÎ6µ›Ç=…“yq¾CoÏï°ðÊ×¼²Z5c¾Ì?t?TÖT²r:*
N¨ÿ¥r ²¤µ¸ÄžÚI§;ÝÔºÐÛ<pÙƒû^ò‚UÎÓ¿ðÌÒ`–ãl© ‹ún6g:t _ÅêxöCææbÉ0±W|þ3’%endstream
endobj
488 0 obj
353
endobj
492 0 obj
<>
stream
xœ½[YsÇγʕßpß<“òz›¥'³Å$àä¢Rv„„A#lþ}ÎÒ}úô,’(ã…t5KwŸý;Ëýeg:»3ø/ý>~}pëñ¸;ýõÀìN~9°ts—~¿ÞÝ>„¦3Ý0¸awøó¿hw£Û
ÎuqwøúàÇæN»·Â45/ڽ뜳Þ7G­éÌÔƒ·ÍEº]ó®µ]pqˆÍsø½Ææm»÷ãØ9X`ĵ¼Ÿ¬ûÏá?yûÐÓhqû¾ï‚ÓîðáÁáß~lž¶Ñu&Úæ
lìh-eºh‡›3Üt˜Œé›ÜÀÑtXï†ÑÃk{7u!¯0بW8Á«“ú¡yY;§«vhDÊû8Y¢ËMÑYDÌ8…æIyÿ¾àˆ¡ù?ú3ÃEã°+à'×¼ÆBGÛ¤“æç•z)$sŸéÜÿúMÉ=gý	YrCþàý@
D+ôa 1^Áu"ä>éÍgÈ–KœVå:ñ»yãó²éÒñ;ªÞ<Ãà¯pÉÐ"x&~C¾GQt×gÅΜÎÛáÝ×…Ñx÷þ£ ÃDdå5OÒ"ÓX6MæGzd˜gV£Ì'b
ý@RH®@¡Oôçó²zœ©¥C§§ð†ëá4DvRÀ¢ŠÈ™òíQ«’€\,©fYCñS›Øú)jU«6DË_ÆzÆ| 5#o…ìH„:òÂ^¼üƒãߣۙv@_Àµèv:››»09+..˜%Š2‹M!kð?,;2°¬·#iF-Ådónr(›bŸe7I»F(*,gÁmN˜Dþ*kaj­½Y;ÀÅF
ÁÈK¼ð6®¹& Œô§°"qS¥3RûÊám#oï‹ù%¥#YÖD&A­Žìõ•ûãCLÉ”ØqxŠ·(ÉèYÉ’åÓóÎQi9éWf
*C
äͶwÐŽ!6Ée•ÌÛEæIfoÔ‘ôNtŒxV9œdb0Ë}!ýA‰y‡…=OÊÆÅ;µ~„G: ª6<î		…z½ث必;Ã$´áùÆx.:§°(nŸ&æÒ³¢u.+ÝåZ|Çó£À3f3bÂDëÔGÍŠLÃs¢ÆÌÒÚ§¥W{áv^¤Mh×NTdlí¹–
x )òcŒNî¯h››y3KÒ6ð#WÛ7ÅÇÁ”ÄFØ&yiÖ)T.ïˆM?5pí)(oò¤háO-¯ƒÎ‰vÃmkéÈÖkÐÛ¥S¾`Ćj†~«ÂuÇ·z“ÃéB
ä(.¡C¼Ù‰H½¢é¦)«×]¸þ-.ãéß´J£ê:‚"å²Ä¥â.f±T ˆéIÆ%À:1x—2®ˆsŽg¢”V ;•qWêÃÄÖê3ÇPÓr]@’g°é3¢2ÈÑØ÷˜>$3÷BYÛÈ]<†õ‘!=³µpùYPÛ‰ðQhþ©
;ÃÇÊßÃ-I'i‰G Gy	zâ8Êô^Ñ’»x"³‚›R(ó¶bå RJfähª°«ãžO¾ûD1¶%{Ïäs“ò…RÓMZ99’V\Ц¨8ùœØO'?"
5,Ÿöç™ÊtŸ}^]_TQTƒwÔ‚ÉÙ‘Ðâ:e­¯<Š#Ù6²€Ýþ^¥!ôa2:E¢'وߋ*Í€–¸A»*íÌÊòZ„Z˜]`•0^¿â/÷’ XÀZ-Bóe›*ƒ×i´…|}ot£3žù£ûüìcØSí›Û°dŠ{`²¡|€6CyÒú!`ËS™„tšDNéjIõ€¡ë‡å(§|$/ö¼•‹¯Ò“†Ä¶|òlíâ3¹øVGÛbGêS‰–é"²J´+Wo*¶2öÎ?ðÈŽÜžùô±ÌW%Uä‡îê·óq/åâiáPáåËò乿¥2%$ì+MSocÒ´=ºÜ=ƒe%‹#9<žÎLälbÏÐæDHzŸ?ñ‹g«‹ú†èÅéER/*Aæ£þ ÷»rÿ_úbfÍ“+e®õäìZ&¬ÿ¹X{ý\üïšî—‹BÜZk/Ö9°i>jë| TIëŠå	ÂékÈß¡/æ¤@åB
±@Z8TÉ©·ýÌo¦5nR¥Ê•‚?V¥òÁKÅMj6ˆS¤k¯Rù¡ïzAíø.Õ{êlPN…‰ ®çPë0††
x´Lõ™AÂßb~ÙÊ…óŠ*4νyÙ‰}º.Wd6Ð"©Ø@T×aQä›ô¥¨ˆ”<‰‘®íHÁ¦¿ç
Ñ¢¢Ê¥˜æ/@§ÊU¤ƒ¯)èᦿ;8¦â— è?+‡R¸¨J·f5ªŒLA /–š%è”›[ðþÿ¬ìj³®uTY™#“¾
Yß:ô¨5ðϼäè?ú@n«ç@u>ªf¹Vo}ËúT×N× ü¦6êñ•íð»¯ÌíÚ¬XDÞnBíU¹=y'ÍR:@<8æjç²æÜsõáB §cXíz®äe[c ÐäpÒqC-½2'=ûi
Kú¾Àˆ!¬`ÄÐ_‹ü
ƒ'Å“š;N÷b7ˆžÌËÍy\ô˜!㢼™TaÀ+ÚE½ÑÅ;"±ö\k(7#ËIÁ™PЕrÌ%¢™)<Ñ>
AŠYÊ^óÈT‘“5.îlç4¥”¤©¸ª:@Sσ*ôds.QˆLè2=O t6ä_ÃÁ4ï¹z€pÅpÒ•À*ô–á&/Õ¦„ÇnÌûyr|MNÔ7O]iã5åéžç¨¬µÓŸZžÆ¾mÓùTž¾þ›~ûØ’ßð8vì»)TÇþXÓñÑdõ4ݳh`Ï`JöJyò4`ŠC©§åÒXú¦·–¢ùíÙWv^òü°<°ðñ9í^O}}ôºu„ðœß¢í“i ü>̾¤‘¿uÕq£ébØW'+R¯þia-Ü(,Y+}BYvÚ†ÉÎ2K%HÍ×pTHuŠ\¬±\4=*Æýl%{Ðe'ùöP¹‘ï©pãÂ.ëAFôåÛh<Éký²êjh$”;@üw9ó¿þ›J‹CäAŠ4?õÚ¶JÑrŒ<£cc•—‹/¿ú+bg¼‚Üûm¾!=«E=4%¡Lé²ñ"CV³¯JÍzVõd–ÌnM›qr#DVÈZ a´Ý¸@†ù â'G’+•Ü
àÆKÂBÍÈÀ–üò÷ÿ‹!Ð)endstream
endobj
493 0 obj
4199
endobj
497 0 obj
<>
stream
xœí\YoWvÎ3ãÑ@Ô-¨[u—Ú$e+ÖÈ–90&ã  š¥‘DÙZíüúœýž[UÍEû!"›Uu·³ŸïœêŸVÍ.¬ü'¿÷¯Žî>îWçošÕùÑOGn®ä×þÕêÞ1<"\ÙÍVÇOxdXõqÕ§¼kâêøÕÑ_ÖæÅÿÿ}üŸ0"…jDv̓ŽOáÁ/6Û¼þÃ&ìÆqÈãúóM\³ÙÆõ1^¿¿ÙêÇ›mŠÍ®	yÝÃÜ;¸ã7×ßoR¿~„Ã3aýuó%Œ{´Ä#ý±k`ŽŸmð±x.¯”at»Ú‰ºFØDZ·Ùvp5ÆõŸ7p¥icp×ê1qý\4áÔið;ù“w£à¨?1h8Lܸ¾LК@‰´òj›š]Æ‘	‹›YŸÁÉ^Â,ø{ÿßm}>ŃÀ”C¿~±I|ÿ¤ÞÇ
µiºvý¨üÖÅgñT¡ÖoaXƒDOëWðq}¤‡IÚˆƒSñóú	|Ä9z\~ÇWy'?ã
{ÙÒ{Üß©n7ððÃú)|Äõ/ûÀÅB ºÃ	øæ3
âaô👟 ð2þ9¤õ…_¬ámíñ@ñÄóè¡ñ)ÇŒ‘Å)Þ0`ê[äÐ;`"ÈÌ@føØ†¸~Ǽ0™8g±Íi ƒ‡ñ¬
Jup3<³!gLà<¯+‹|ìíÒçÂäƒ	™à¼þÑæ‘cé¾N„¤p3¥¼ÞêÊxÔ­œu“´ª³Yeóú‡õFHú¶60ÑdÊ0]ΆÃ.6±§9è$?lX#D(U ÎÈÄcVcÈ?™Þ—Û@3\“g”…[þð¿0¿l†§o‰ÅS‰Á­Õ-xBSÄn&ÅÅh<4Æ<Ô™î«v:½ƒ“¶4¶˜3gUŠûQH¾Ð¨ôÊ×ãÍ€û1`ZpÞ8š:"oÁX ’	oQ—NjxÁjÚÒnÚ@r²ƒŠŽc;Õö!WÚ®Ó £H$d{$í8ð.E¸ÉŒŒ¤—E%SG”7‚ãþœ©¨…]•qº—ô®4Üxü%®£ejãWMäPÚiÕðÜÓìÆþ×Õf'FDvŒ‘Ù°'hZ¹ëñœo[íA¢ÞLãÅôì6DÉÐïéÔ×GÇ·ÿÂÒþÌÓeû°¾%‡¨Ì¥(J$BßRYëx•Ù"Ý›(l^WA®ìvz´øS»Ý‹ugÊÆÄ§¢l¢¬{šFDÅ“à’š"”[èÎXHKÆ]>òå)n
íLXöY}'RÌ;î:2Nå qè¨K¶ö„MW4’žñÇÁywâ)Ùðêè´ígÓ¶b³Åÿ9›m_qt~ZçŒøëʈ‹é¦C×zZ)fh+Wö ð™Œ‹Ù¼Ú3¦©"‚Zls&Q\±¨½±%6ì7Žt=“o»ÆîŠë¡;o%vkzçFnÃãh¸!üw¥;ä•ȈŸ¨s9eÑÉ&PÿTX¢žÌ9TQ¯¾-¥ŸZ.ŒZÀ£½7ªñºØÕR Þ\íml¯
þ²Ç×Xªøäu@p¨Q#ÌåP53	èK@£Å)çÁ?Æ\üÂ|޼Ôå6BâZ“Š*Gñ«Åk¦ü„‰¡¥_ÛbxÀfiÜY9õBÈçlÇ…Šy˜F}æ½:Uì¶œfÏâöþ?¦uÃGP¹æÁ§“µÀ  ÷•ˆ}l"Á9²HBÌ®¶>$A‚ƒYýH9a‘ÏÓ ùŽU–*+Piñ¿Ýyæ*·©EíËËnRq¶d0jÏ}÷q—ꜫÝ
	N¹…ZD´¥ˆw½mÃXú\.’”uþÿ|†?D‡uÔGøá7ú0‰ì“»ZÁ”m§‹ðüoë/9*ض"õöõ8ÚÈy¤ç¹Ý¹(s¼°û¯ËýýÒÅ¢þíÝôòé]¹]è[ÊC'®i[4§Ä4>mD¨6Û.Þ^Zò祿,ŸWÔœm·4rDr
*¹åõ£¬)!®_¦¥XQÙ̱â¿Á\‰#޽IΉHIÅÔÛv»ôÄäìÌ„íNwÕîo/Ýᬹ·…bzñb×]ému¿œc~ñý’¸[6åÙšö@#ùݳáÒqjš¾Û\G½çGÀ¸®ïˆwIz
òtIHõ>,‰æ3»xêÑÛñr2—'g–Ç,ûß-ÏÿcË“óß-Ï߯òÜ}s8¤¼Kl‰ZV+Ò¦¸IKÐ.æbè$b4À€Þ:{õš‚_NŸ^o€«ª\”ïœáXO‚·þc#0$Íû]y.>Â<} .®Vc#:=çÈ‘‚8
¾zSŸ¢¶†DãsŸáXÍðt÷ŒH”èÙÍ€cÎ5ÜŸ€Å^JT‰Ç{IÝЕ*
+<ƒ`9Ìd`R	ÿZ¥äjåöÞÅæEw)+ë¹éefÚãÇ‚ûqã¬5Ã	áÜN!ˆï7ýH”É´Hq6±ïžæìÿú¸ƒ9&Ñ£FËO)/!ò/B¶Q0kž”’)jë:ÆO,8šQ]òUˆk;ä¿NˆA 1›ÅøHÂ]¨ô,§„Z¯d¨Éñù0[ð7ÀÄ•棈Ò’8[6£–h¾ò"gU[h\é™r´–+Ÿöˆ
ùâi5ƒˆ–2¸2+‚!ôŒ|ôtÌ‚-WÛØ¢5a"»Iæ12 ãìît¡T@æä@™@e£ãtÞ°dKÑÛ±Î";‚4}	BOj3Kô.œ•©°Gú6ÎàÚi¹¼†ELí@ŽÇ4¡ÆÄfHÕ[‘®qg0“i£Œ@X	|†CðqK8^¶paÉwã„Ͳkeµ³0.	Š^¢iõáŒçDèé0°Z‹ž±6EÅòj1…ÇÊîr(£rïâ°R?zp¬«$¢Õ"å²yHcCðÔåž‚•p¸$k^5è›õV/o@=hãŸ[ùç®Eû-`úé.ê°&nòJÂèø²mN¨ŠtyÚQY	,Oç
UíÚ@Æ;,ƒŽ¾r]l†íí Þ(L/öGÕ»ÍÎâ·Y›W¹Í›FFÔ26ó§eç\”¢Ã¡å¤&ÇyÒ•0=b¶WµæD¡N‰’gRÈr	vª¯3Oëy- Õ¥næk,n«"ÆÁzO&“dÚG/!³“õj‚¶®ñòŠ×´ÆØ¤OΑßX¸_¢ºñQ3h—(¾³ç\e¸ë†&üÚ|“ÿ¡ÿ-òÍKÉÀ“*íhöÿ¸”¾=YJ+ÞøéžnßhÍføýS½ú/fp÷ñ°‚¨.å.’le0^ÄÓ4:ü¥KÙöÌ#Èä®
„*Õbu„ô,‘Bu,A_Ò“
ا˜´M]‘À17m‡>}¢j„Îuð»Dv¥ÉqÄÚ?ÌÞ€Ö¡zàêçõ’â¤Ð€«CFKÐìº4X†ѰëÁ><Æ™rºv;d&]ʡ˺xHó%ñv9å[ĵS]j—òB0!LÅI!™R)Rß,/ÌCÓÈ-4„.¨á@)%j™Â1e’¨Ò2E-ÇåÎ¥aJÚXìêHàÇÌÛÆÈvø€yŒØWãû€öÒ"&pA™—¬yËZ\+yÏ´Ô{ÑÉ.X×ób×òZjޱúZ8üàú6€9#U¨ªêSqÓÅ“ÂI˜Fš,¥5¶Sç8T+,þ„uœ†3sÐ9©©¼£xˆx.ÕzL¥§
™f°XÖI•|*hêà«ÀÆçÄAŸîùæ'Ÿœ°sW¼3 J~†¥¶¾™xÙúD‘â<^¿Ö5"̲% %€ô]ŠØÕ·d౪öÈzw¾ÇÝJ;´Ãc‹ÒŽÛ
©Ÿr2SôøÁç›ad±›ö-–ù$hØÊyê¸K±íÑd‰»9^²Ö®ŠÉNà9¾~½ZŽÖþŒ“0èDÝœ¶UíÅJ]XhŒ\«è—%VZF¸ùÅ›&•XõÔ’÷Žb¢ªê°h™E”øX}i¸”Ž$§®®!ÐòU{“liÞqC–ˆ¼g)/Eãʧª€#Ò¡½!°°0×áK3.)hΓiÜà²R™Ûµ„©¹áSÖææ½Ók9M§;Ðn.Ÿ`J;û¡y\È %⿆T òx2;H"áÊ}]I–ÙÕçi&-¢‡`i±aÑòŠ’Þ°Ðm‹ëQ:©pMº¶öÖÕCÔ0í?Xʶúð‚Æd›4²1†BˆVoAT
VâÚí9ßHဂ¾‘‘¶IºcÃGû3džSÇŒf&	{_Ô"ÞãLC„)º4˶ž(hô’IßCÜ}.ŽFÆzᆶJEý1²tšˆÏZä´çh†Zh(@<Òþ9A²ÅÀ娮óì(&›Ùgz¿ð¬Xª¥”‰Íx©73W|0ÄTÚZjÖÀ&šp£Ø–:A›þúá5Ÿ±x%
¥´ñÌC[6(	¨X¡zSªØN’Ùq	 d•"sÅéG­@6Î…Ík¡ðH©³Ô±e,Nù°DFTié0‚)1	IWô¯,5Ò/IÊEÅí¸à%À—ê0D®°o<Ä+£js±TIVóQ[Ãñ
'Õ1Îáš…w7íQHE¤~R_ô½÷\ŠüÑ™¡hèWí‹f°YrhB
ŸŸU˜X±
¸ÿûÇGßý´ëÞÑ{Æ@¯asŸwqX…nìðÍ„ý«£{Žî>x¸z÷æýÙÑÝïWáèîðǽo¾€_¾\ýÃÑý«ooøJsl¤,³¿Öl/™¡@Þ`×ÜØo¾ÁîýþÜû
íáíõc»~‡ía¿HM¿‚§™©Ô~DÒ¼ëÑk7–Ô¢—øíOˆ¶©ï®yÂîðv‡¦ÿ=ä%
ÓëLsú]È9ö—)¢ßh¤>ÌÔN™Kj2¤c6Sc·2-ì`”ªÏ¤ë(ß½4ûç>ìrž:÷Ëò<ñé–;	ØDF43ÂfÉÃ5È Ïb¦îöò2–kˆÊ-ã§ö¢VŠ;~‹súu&¿ô5dƒL5i(Vc“l±îÄG,õ^\úÍõ^ŒnÀi,Y@1È“ˆÂò’3A挵Ø`7)=qæ„›)òàÀãË!Ь¸ò<»íð¤¤uÒ‹5ÁÓøè5¤qyB¯È‚’M_ÊŽýìU×®) ¯¾oì’LCá5(`D1p¤¡B»¶s·kdžߺ0©fÚ5]
‹LEá
kRÆëNÕnåÉŸó}õASLu‡qø×Ïæ«Ï•«Z:ŠÓéLÖ7Dý7=,žWMàå	ûšü:+%ð²~dBkœ)¤¨mÚ5ʆw̾ r*BŒg§ŠõAEc󬴜ɸ¡Iš–öÄ`L+“jàÁªËKÇ9Ã2ê/9€âÈ­!ô5—1uѬ(\)ÏRBPQ[n¦¤	1W¦ÂÔ/ütÞSUuž‚X¯œÁU:@1¤Ÿ-ÙK{+3”B^I­j±*…(eû]0¶ð½	Ü‹˜,5%Ýõ„q`4’¾Ûä•×û² ÷;F:|eûœ<¸ÖúÐ1öh–Š{’Ý8/î¹yÒ–H)x °ùc…׺тÈ_¸¹¡_ô¿Ü3y{âÚ_C3rOÂM›Ú‘“rڛʭÑy¹¹ŽÃä`µÉšö´$“€÷ZX”»˜|!´`¨f‘:gëñ¥-¾uóvpg“V¤v¼Æ;3Z…‡ŸøÀKk‰sÇëÜò¬nÖ£‡fän±»ŸVôå‡dÒpÍJúœ!ï&¯À<«]—aÇD",z…Al0¸0GêµÃHöÍ4,‘f©¥×/‹h‡I¼ï,“tãÏ„­þíe‡4•›¥ø[í‡u%M
ÉM+^	zÝð¿ ²«FõÝ×àÿ…#oYà8·³ZW÷Ä/íçYòOø
40mCû-Æ10ŒÖH-H¢k“ÀYJ‹T9h“
XVˆUUÂ2ö]w˜ôˆ˜—F@[q_µ˜h}xÞÔ/¶·ò3­Æí¢%ÈßýGíendstream
endobj
498 0 obj
5144
endobj
502 0 obj
<>
stream
xœí\ëo·ïçCпá¾åÖÈ­—}}h<[·i;*â )
[’%5–%ëa[ÿ}çÁ!‡{<ë$Ÿ¬ÝÝr¹äpæÇß‡\¿ž7µ™7ø/|ïÏ>éçç³f~0{=3ts¾vç_ì@g ¤›ÑÌw^ÌøI3ïí¼w¾nì|çxö¯E_µ‹º²CßKc½©³ø±Zv‹¯«¥]|‹ßT®ncËÊ-¾¬–~ñ=~|îT´f¼[|W°6Ó³_UKg»ÅO•ëù)hÖ¹¶‡~ñ¤r¦G7pSÿ¬ðjð#4—º¹2Öþ{ço0¼_yü
ÀèóBåW|ío+;@‰éêØ4ÔŧÐ:)æ+(ÿ/ࡾ·É–Ž|%`ÈÀZ¸¨DŠÔ>ʳ'’Ô4áj€¦x!ªÁ°"}ÀptNÉÇPítMÛÔ~˜/«Ûg,B7ÃL˜¢CGÓÔ	’¸þ{má¢OæYM›Zz‚*£i³Ù1R?ÒV-µdPU6ê—$¥ö]¦Ô0ÊÏà)V|2Ù¡L
4¯q$w~ÕÖšYÔ&6Ns/CI˜`0 *a`xã%ýñàa »Ðݳ`‰Ý
Uë˜÷Vèâ2k0Â’¥—m5FrͨGÇ&D¤g/¼¨#ZU8ŒÍÉ(`doªÖ‘ÎDäKUK:I¨$¤„ñRÚqàa	»v•ãZš
dˆ×hÇKÑ<ôN|ÞÆîÙXdÇ…pgÀîÈ+œ'¢fpŒíȠ݈
Ü>àZÇðù.¢ñDÏÕnŽ!¶áÒõfyqìˆ
æÛ‘9'¤Ø¡˜(brýHœ÷B8›XDlä?Æ~ `×™›{©dÝ·Ø,XP·ŒOqt+œ”@ÜGzr·#@ò¬KqN9ˆœèÅwÄ`—•ð`#L?ÈÛåÑ«zGs_¨À[²±ÂXбâãœ&÷¸M±ë튖i-ƒÃËS¬B|F	`îw8ŠIóë|WôÇêk/ÊFÁ‘§y‚O!’¼'®^RµòÓ	Ç€°ÉÉ6/
+WÐ?AYÔ8áÈD>¤¦*Ms	ð58Ìœ€"P‚Ž…ïåÒzºd*OãÒTÎLpLçÍHÙØP¸C®½<ä dÍ¥"í¤%ïEFÀtg~.]ïÎȧ~µL±æN–èR ð=E‚Úm`ÆÖ€tc†Ý{F±Ú†âî¨^»5d°¿E¼åÑMgN5ydÙ4ð¢Ïèڌƀ¯!2 ëÌâ9†hÎaÆ4vp{aì -Mfn,¢)âR@†—ƒcjéSó9ÒJî;ùvF+²ì—²ø¢4Åh?¤ÔOŒëØ»~O+xäiµvuám3b¸Ù¡ƒ¼ÃÕN{ï±›ºåÕc÷~$ËØþ¶^b1b÷$XÙLâ¿'9)ÿ™éÁÄÑnZí°•¬äùÇèÖÌA=]ÀözÕa-þÅø@e¹c«3Qúž@ž5Ex´6ߦ3¤õUG+ˆÐ¶£¢.짦!Ϊ@¬° žviƒÄ¾¡iôˆCŒOiñ%¾¬GzæñÀ ÍJO×F…ܧÈCh@[dº&²Û͉S+qõh*¯8vKN­:
?¢¯Y¥'ËQЂGݧ*Y=ê[YJƒ¼±¾1ÿCn$y¨¨C¤³51âcô-£k•ž!;‘pÏðZÛÞ
:‰|
¥®HÍ(¸È–ŽgK
úƒÂ8/×áÁxÂC2pœ9÷æ	6«ëRÕÙZ·, ËáWŒúÂßUÃñØMÞée$*È0£l?Œ¤)¤˜ä¥A--™½‚JÀf4LYë6“ôaÛÜY²)å{Z\Mc¤cöÑ'7½ô”&lsÊÂR¢EbÔÿ
fP$¢!C®+ÑPÐÄk1'#•‹Z¡ß$Ï6Ö“­¡J›8æe@Î@›Dl YïÁÊgO²„.žÁœlu˜±æ$pç´¿^š¶·˜ìuQ˜#D!’;š­E.Aƒðô$Ûç?x‰óŒ¦. >0¾äôÄq¬|oì2Ôåã,á
-Ù“I¡Û(0(¨Ä£T¸Ï3Þ·'ê8	~Y`×ùÈâÓúÆË0¼¶áyú Þ>ÍŸ#=|*‚þÌØSh^ªÕE(|ž
_ÆÂýÔʃXø.Õ<Ó5¥0iêžÀËÈëòKdäáv„»Ú¢pÊvmÝwé&3f/BE%VIÍLå£|wiÄR°ßQ¬‚KÖ±'Ƽ­ZÀÜ·QÉi*<ÒæN*aÁÚ;SêòUi2)Dߨw•æçiêHé•–_6r{.‰ü̱±äóúfØ8‹µ/²SðÃZ Å'SÛYš8I“J¾“’~’í÷Rá…FÉ*
ösÛ!ÁW°“bé$Òy©£g¥ÂËT˜Xý—J~†H|VcæKmÜÿ‹£HMKá›Ò4;ÓjYõ'j×exÀínÅï$j»O”$;,‘®‚óõš[e…ñW¶øMû>ùy3:c,y#$àêÝ0UáUÉ*uUgEÂ3¿{Ãß½áïÞð~¼áÃ'ÖgË(ßÔ
yÇle+W:yƒÇ°N°ë_Âö
J`9ß7M]³÷çx]-»×Ö¬fR>ˆ[×§R~8°O6´§oÊèGu\ÚbÛXu7¤e'¨”£?
Yµ]À›Ê_ÐB5ßÕŽ	Ú,±Ïš‚%î„Îç1%•Î6©ç<vr&£Þð´‹ãÓ/2 O÷°-Vº.±UHYK’V:Ìö
u™‰£|í³pbËö¾&øe.á°s¶•fÛ!"{{®ÎkÙÞU’‡²i/¢ÊvÍâ)~™˜¥LYÊèúÅÏé6D:yBê,žTK<ú5;,>Ç"Ì`ySí('wÄÔ”ÛÂ)	T·ïqõ}–9Å1…Y’(ŒÈ¦•õÊ«‹á³¼eèÓ†“V~öñ,\xF¥!£+çilÃUÚ駱žtQùºÒQ,ö<†ò¡ÂT»Â=%° IéfLCdz`˜J/1²âÚlC{­˜!"ñ,¥ÔމNºÝþ³½¿’€Å$â$¯	£Dm©äw¶±(9Ûæ·Qiü@ªW‰C”÷¨=žT›'ȲxœÐò<ŒÝ¥œ»æì·4ãQ*e/:ñ9lÔ"ÛŠ­4º'–ä‡qW qä$º«OW…Œ83g¢cŽ*ƒécº‹aq>cžrÙ÷Ì4;6’L·w]X±¼Ï1zÏŽ13¹l¢á‰ˆÖ/g|l“e«-Ÿ<ˆ(O¹bþÒw5ŸLIѵX8
ŽË9>練×nçº'-~›;ÝÎu}‡ÍC7²{*ÄŠÛUëåpüGolk¯ÅSjo×o†7m[w/Çø8Ó^ܨެ$§it¾pr2Üø$^èm	Eòå¡öýø1áp0ôº“
mM}ã´dír쨽°õòYÓ¶@8ÆN§^òïRï¦ó
ÉìDp StÎêHp<ñ·r²Áò)ñ÷è(¾^=CŽ=Þ2ÜÇd}îù.61…Çïo¯ì¢°<ßö^ÙÅûs–÷™©¼n5ŸÒ?ÅCž2¡Èu^ݦQÌl:^zÜ{v³_ÚþöÙU†[•0|aü²ºƒ„áæJ¹‡„áe3'	iL¯Ë(JÂÐt²ÈP©Å<µ)MmœQÜx"OÆÉæ¦yÔÔâM-qVšºùÔ
˪ͷC~ëùÌÂnÆy2>¥O’ߟҌNÀm”Ò¤üLzÈë¸#½0D@ñáD¯ÎPYH
N2Š6Æ-!è{S§wSnWpï&¾ÙBäÞÑg
¼dŒëÕ¼Ñ^Áa:2[îµñåÉr/¼8Á
p¾Òb,´wªO[ûp„î)>ÇɤÕÅA˯áý,uºõA¢Ê¼”ê|Nioƒƒp¾ga‚Ò`KyÏì{K„œNÂqGÎ%…—&6Ã"0o†MöºRv"—\ù­Ž»‚Ÿ‹a×HaWˆŠ¡×ÛR,±W „•Ð+ê‡C¯5©.^k½[]dÙÆYeð÷Rm‘Â2WVˆ’>ÐÑ&¹ÏJ´™o¡®2àt»÷CŹZ#ÎF[ºÊ]#ùò‹N˜å›¸y´1ÙĽÃá¯Zã4ªó“`‡IkQe!FÁÿ¸&‘TèTL»6’Š‹©og;n`æ|?–†b›àóÊ[±í}„.w¼$:-µy®¹ÕŽ|±w¹•u/Îû/Û
\ôHı1SÜy‘@wi¿ùq™ÿ˜qYŒE&oÉS޲KaHŸ§‰C,Í .JAÇúÿÖ Ôfñ½ÄiôºŸ?oêìEx¦¥ÈIÇY“÷Чï/H(Kï
Ù._1 •
ÃüDûê[ø-½Rr‹
¦ô¸½íCRekb/­E;ºBT·iŒ–<ÉU‰rÞe“›òÁgÿÓÀöóendstream
endobj
503 0 obj
3690
endobj
507 0 obj
<>
stream
xœµTÛnÛ0}÷Wè‘
bMÛ²^ì`ºvë<ú‡,I»M“&Ýü}IÅ–,$P¤ƒZ>ä!iÚ÷L
Å$]í}2Ï^\Xv½Î$»Îî3嬽MæìuƒJ#"œtŠ5WÙŽ©˜ÕÌšBHÍšyö/AòòGóF%ŒR	Y#©™bàžðŽ+á\]8xÅ5|乆†ðÏ;ÇÏ–Bª,æèÑÚ¡¾rcáœÂ1FÁiä¼Eú|‰óΉ9*Š•¦tqœDÚY¯'}'-iD	56aà3Ï+Dµ†oYjÕÃRކHTTÔPjS÷;ùø=Ö	±ÎpžŽ‰KäY«w­L ¹R•°ËV9·ì%`M˜’Yù†’+øI·df˜WÖÂÕlèy¢×!zˆ1Êù˜4åÑ4(ô܆pŸÒáÙÂ6€Ë¹à:‚öWø;ÿ"ú“ÞÿYsÀUŒœð*‚8>”Ó·äŽmgû—vºcÚOwL¢c+3ä$~‰JK…b+#ÊŠ>7{_™¶l”9·zñ ¡úQ"7d|Èÿ}ý}5–¼‰à¦¯Fáj<×Ï· ½Bwœ¤Kéß>Ã:Z´“6­ÚIm¹t5kN³fð™W!ð¡S“~žÒ—2ð‹Ì¸]ÏQ%
aqèÍWœFð!€¿ûÙž–ø'‰Õ
ý†Í±#ŽÍož²Týøê›”ïNëÖšöà]«›ß>Í û!ïćÂ&xï%GK™FMö	¯GD¢£âendstream
endobj
508 0 obj
595
endobj
512 0 obj
<>
stream
xœ½[YsGÞg-?b‚—Ù°š®£««vŸ8
°1ÈWx÷AXâ’l³¿~󬣧{ä „FÓ]ÕYY_e~yôÛUß™Uÿä÷ÑÉÞ'ãêÅû½~õbïíž¡‹+ùut²ºu7Ä•í»lXü²ÇÍj´«`m—V'{?¯ooöM×ãúåfßvÖçÖ‡›¾ëã‚3ë7òu²ë³é¼M!­áSr}×ï6ûn;DœË¹hì¾âÇûnŒ£ÁÇCç]Š«ƒ‡{ÿüy}g5½7ë_ñSˆ}?À¬û°À±1á¼}—LH	¤A‡Âè·>ë£ë;—\ÉûÎGc|ªg;ÝàœÍD³þ
Å¥³þ¿M~°±~ØkœËŒÁ¤õ9MÛ‡!€òÇê	§åÛ8¯í\0ë'¨¥0Qæ-z™7¤EPÈ%Sd*{¥Z0.Úõ{¼Öè«ÔXØã.õ‰uš:z«:=Øì{ÜEœÂÓPœË…Ô¥Ö¿ÀGc?t}oúO„àÆ³I,H;ð—0ÒŃFÐÜ*³ôózãb×ïÖÀ
©šG\hB&q“£Á-‰†³ÂM(ˆ©í{Kª$ÏyÒ”üú5‘R„gæË8ô
~eYtiz—}D™#-e}oƒzHƒ"át<‡#ñ€p‘" 	5ŠÓø°~ÊkÁA÷7zýÎF/‡—`J…|‡CS?¾Hpayw×_ `Ž”„‚«òAÖçyÌq~ε2útæ2*,DØ™~JB¯¯Ã¼77t*÷e­ûÆuÀç—|céþcÝ¥CÞQ°åàg7“¯á¾Fvô ¯qŽ~`ó›†.»ð“ìŽË—/Ÿm:=©¾Œ² ža3Apèwøß•¿ßoÌܮޡú|ñIIRrõÀ;©±Uí8d ߨ}ôàyͨ7GÎgÈ`Mõ¥¬Y.ƒt*¬%sËpÛ1^“ç#9¢3u<„§³MMèžÍ»/F4¯àÒÒ'H=<°±¨gK“¸D4@ æ½CGG,®à‰EЇHq”@8@ã+KÜS0)–Ï£(-„!@\ÖÍ“»"¡Ðû0oí·¨’hHøL>ª¤læ[âÁY³!’û_fûx..šmÕ°Lê}åæx§ÐJâ6íòíqµ™…‡èª#qF1beð-99«EªQô”Áåž©oKÅj
ž'þù¦Þ¤<}_§c”ÉŠ[j¬L°x$âað“9ñb°à¹(ŽŸ`/›X­·96÷¨üAcVQ×É$bÁd¬IÀçåˆÐöØÌç"ÇÓr÷÷¼þÖº*¼¦A‹·&³ž\vfÒu6 [×íaÆûÊ×AyƒPÛEÛ„Ø%ÞÊLëM>¿ml˜ÎQLÎjô‰`M1\ÏGrMa@ä?€È.—c9Ùø˜#Q¤æðçõֽΧ«œ9^¶qµDE§"Õ‚YU¨‰cb§¯½tˆJ ç(ϲ@<Ñú€÷!Ä­UDªÌŸ1ÜI”ÓâhË%óÃýÔè9Óg(…TÅâÈ?1š“(+×:b•Õfd“W1Ô3<œx8Õ&c®b¨oñçzþkrJSÛÄmà#	Y‹Z·šU‹"ïnåÁi)Y$u¦¶%s=a‹.úl±—iàþÝi\…¶_fø„R¿<.Dñ!¼poñשJ¹~Eü&EWAàC¶C Ø@)¾ûÊ,é™K™ò¤Ã°u~Q¿@¶R²æÖ;gІJΚÄÀg;KÖ$)}XpIžCäaN“3 ÒŒ“%r€UL¬²sì6'Q LAyÛâ_fú¸mªKHOüHJ®Cd †$¥ún°U²“÷M?Nä’ \i˯§›6“Yö’[‰¼dÁÃGL9‡eþ©€®bdQ‚‰«¨‹Wš‚¤Ì‘ {l€­`ÈÀvdæÕÑF¼ÂÑ×ÙÐ	J:¼Ï¼§]f“løRº™hN`è	še·1}ØGšvÎÕ¡¤ùûlzC±2Sø[»~›L‹ò-®‰nÄs†óëMI)åÊÌ3³9Ý>‡­½>,OÿÌ0sǹÜz›e§ÔW+q*Sb5ÍÃä3K'F¹-ÝrL¡†Ò
™ÆgôØAó	l(N*{ÀWAw÷`"ÀOùÎ|mÆHiÉl¼Ý††|Ѩ•µ3j­òÞM™G¨äN£yÈ”3¿ìmg†¤HªjÙœ/ÊÖº@’1Åðušñ"ÖŒAæû…‘w±…Y}OQÓÑ¢$·¯FÛ•¢D˜Íªˆ[d
l“÷×C	Æ?Ÿàål&=óádñ
V²[bÑÎõÎ9•›‘ô^S¦à¤(G5þ½\Ü[ÜÈN5—¨Öz"/š•sá”:TMuÞG;¢‹ñµÝ"¯k‡”,>o`¬\  eý¨> R~ôÞ¡´iG6žX²8õAÉ$Öž8,í»±øµ.dœ¦-ÿD1,	J[0xŽ>±nI53\"|¦ÀP+e‡ÿŒ$qW(NãþºÿÂ%Ç)<ŸƒÐsŪԷÀxû?àâ#ÀMnÁMô°Jß=ØûvïíÊ9JJ÷+0®6^ظ²Žü>:Ù»õ`ïÆƒG«³wçÇ{7~X™½÷ñ¿[oïwVÛ»û`õíb‡G›®ÕP->¦óû<~܈?¸[6õkøîi|ÏoŠFñ&\.Æ?†ì£¬^7¢šð‘‚¨V‡’³E­ØÆW­ä|½o´RxÉÍ¥5éÚ-û¬Ï¼v¡l¯~í.&yL^û÷yíÕ*j2]ŠÌÄ&¾)G«ÁDÜÖIýç­|œ/¬”¡û(e²g[¥<–•VÆYÍV¦TriY)lc¼ó8{ë˜?ÕpXl´Q®p…†à)QÛÃ09ƒ’Ñj—Å ²ðxƒkÅ#‹&†¾B3n"s«™ÈEþü,ø¿d{lÛõ?œ5ÙÔ\ssCõTÃ\#£ÕW6µÐ©¢Ü$_Þ3¿–==ùÀ3ö½±¦žãkXËuoÂRà–B÷å°õ›}bÌg)Â0IO:²\CnYRi‰ët&§Üc¨Ã8í_âлdÐ53Ósn¸é<²)^&Å““s±ýv^Iriò 75mé€~¢©e:P¥B«á“‰w¸V›XƒMü'йËqqìœàl§I¾ßhªçnÉú<ÁÙGªH~JÞ’¥J[&8å¬UíR3æúJª_cRÏ–åµ¾!g)Ïó’àƒÞéaªbMß™¥]ŒÕNV_(ûd—«6Œ’·
*tN"g;LLÕµµuXÛ‘Ù6½q½Ÿ^&¡Ì™ ¬ïBîªTòàª÷†GU©ÌIkoÀRºs’×ÓEÉÏ{9‰9%OKFöÚ|cD]¥¹æh±-ä´[Vm»§:<-…`C¤w@½À¥¶Ð1Cî3ècS‰œ7‹wì¸0)'Ôûx)_ vö†CÒ:¹¥Ãeo¸Wn¨šØªö)C“¼º¸e>óT—(T£DËy[Z¦Rq#¯DrÒ°9MW·`ëžó>©V=%¦c5/ü}GfJNŒ€NJ&
>'ò„˜vƒQ'+m}êÇ2w¥rîr;ÑéXø
~®—â¦ó¹>v«^œíèª$•v"Ž›E	¢ëNE;ð}X!8Ô•RóW1ÑÚ©iž{]§ŽZÌÜ«	ç¶25*-
UW“Cv
“î̱ŸXjz:èy7Ž¨Ý‰²Gqè\nr;ÏÔõŽ=ÙÀùTàö¾ÃªHêD64‚[ P36íÁÍ^H¦ª±º;ZÉÈb’Šëòi›3˜”\"õ[m$Ý—µ·öó@¦JÅ|;¦“s‰MÊߺÛyõ…&3­U›Mm¶¼ƒÒÛ´Ól›7¥’MB¯€½e®nu}ÿQP3fPaŠtà†›0.„ësY"+©°qPv¡:…áQ»ˆ‘P¥†Ç1”Ú|ÝŸáªaÁæJ›Žk“•…%Š·óÕ³E¤Ö>ËMõ¹ðÐ4 fƒw©Ò4mâô¦ª"óÞ3®=!Hw½#T8ZÝR£¦äßRñÕ¦¸º?LY"*—hèÑX’WH¶¡¹´è¥Ò“k:ÏÅn›ûuŠ)Q=vFõ;
ô@UC·£±²ä󢫴ïqT&LQ¨‘&»ò»Ç3€+RH밌Ƕ¤Ep'DM]³¨¦5hµ¯“‚biFñ¾E¦žJîeË£í^ò‡VqÈ›žÞ)ûX;yf_½V6µ >•×Ë–Y)µ–ÇòŽAâ]ÞñŽÁ%òF"¢F¥±rÂcé¨lÛÚI“¬•fÒv‘üĆgr©xÖ€fõ?kÀØ\ì*ýa÷4üîãÕ–þFÛÑS¶K9­g—SÂ_pÈóY«{~ø+[Ô,ûBå­YügÃíâÚhœ›¤ÿ}Ùm`>c	€¶ßlx)÷W71U	¯sRÓÔÃö°d7OËðJ5¿ílgþ7Óy¢FІ™F8„ú¦­¸ÜÒ6ðvN¦d	5Î-¹«pô“ƒ9мŒe5›%á+Ÿ·r•i¸âÂ
™œäµpó™²ð‘_cú¬iG•â+Vˆ‹#FÓE!Órò*·ÿ…´çõÃeªÍåå¶Ùõ[°tyÅëõøú‰¯Ö+…ÕlvÖWµ ~ÅBb=¼²2L?eÃTõØ’ŽµÞm{P¤_!%ésK-v6.´²o÷þy™Åendstream
endobj
513 0 obj
4525
endobj
519 0 obj
<>
stream
xœíksÅ1ŸÿˆûxGqë×Î©JNAFT>@*%$[vÀ–°eùõéÇÅç6ÛüâÉfktßõÊ®¬ÝÁ­#¼“×áp
˜ÓãßJZøÉÆh\ÁŒwñM×à¦|ÛÒ$³þd£qLÒ:=¬ú·:úë
>sZüé×´ð ‡õ_aµOpµï<®o̧õác<
Φ3}µÙ:˜ç½fÜ¶ÔØ&änMßy#ãøóáÉøË›1^®ôèôäË“WÆtQ¶+¥È>¬|o|7dŸ<|üùêæõÛ§'ÿ¾R'?Å>øâCøñø£ÕN=^}y ó(=t–¶éóÏg.b†Iõþ& ­
#†QBo/ßn7<É­ßn¶ÃúŽù^üÿãÏÿÀ‘ŸÂhÌðÏ+¤"ÒÀÚ_áäÓÀÌ1*â
d¼pÀ	¿hÞæÚ‚¶ÆuÎ7Æ3w=Ç·¸Ëk ýrTHQ X|cœÇ¿ëó«
Ó®€ã^á/W°‚˜
£|:H™Ð‚†Ì©[øÔúAyñtƒ7½§kˆc/ÒrÁ®Ú8C¿ ðøî­˜œ³ÛnÍ ;V[;Í«‘žó¶0{™‘GIk©>¬¯q’ˆÎy‰ƒX¸boÂãðÜxmhZðšHèx¯åZ3až6¹bÂóêέ¿ƒ	o#ãú9aq±!üMWž
¸¡]ÿ¼Ñ±Ž¯}+2åßÔ†;Ÿóì-tÖÔ~Ê‘^yt¬ÚL$Ö|lS¾®ó<³Š÷´îÛŽcfM<˜2T ¾Ç™†žý\ežå¦ÈAXI‘˜kLà$£ˆnÌ7‰ÊùE¡µ"Tß5ü[¸8-ád«Lç†>1Û§0ì#@O"l`úv
Tÿã%czýüÄÿIV(G#Î2­/p–Ê—±A¤&RõeÆ^´ô\²@
Q—V±{­_¢ŽàC#i_nt’o#ž|»ônUWmªÂÈÏÊÉœ7£ã‹­ÒУfÓ…åc ÌCn=	–g,+¬ê†ÂŒ‚¾¯
µÎP•žòÒñ¨7U!¾‹Gsð8ÑTçÖ‘‹êÉz§ºVƒÒO=Y:ka›¾s–õS=-žï:I_³þ¡†“,퀶¨ìŽ
´ë-Þ	ôí—X'ãx$ýJWÏšzõ\ÌòYË·êAÒÀÌ_È–ËæE4+ç-¢ähæÝ*‰QAhà›·-Þx¾ƒ?}‡/—·žì¢£îzØV½S‘’ÈûwË‚D‹,¤Q`‘¶	•ζµŽÅd«ð…Š&¸nh)n3ÎF•+Õ£u<± 5Jø‡3Ö‹?+8+à_p!TJ¬ºåí¢—jýû(éˆÆ<²ý„j©¼*÷³•M	TV·EI’p·ß!È@†z2[Kï!ÙhE:Å(·d²Zy^¤LZï¢1òÁÀ"ó¸U{EQEˆ¦IÒP¸ñ÷‰ƒÉÎ
=ë¡ç•]ò«!Ï!Ÿ‡°5”¯a^jfˆ™2ëØ‘åa¶<ž•+FÜ Í²	c‘Ü7ƒË{Ñ6Í]™jk@þ!’„$íÆ*6ñã¶aÓ­c¸è½Êq]ÕršŽ†~Q÷‰sÍ`H_ÌXËæ”f}}ÁAŒz?æ3ƒ%½UD6b
G1ì¬&ظ5µòù[_	xi@T¹Èv|6·³%—.(šªŽ.Æ=½Åáôm‘äÆNø•V¨›^µëûjȆÃwÏH|=Ϊ13‘ž­Â(¹dS¾pçä(ÑŒåÌéQ¡%¦i˜<±ˆ’X'wåjW5H†€U„É%…àMãž1Ç[®éáhÌœù6c¨£q¬ÜÈúOÖqž†ÀÖ‘áiIH‡!Ëá9L&>a°•uçl	3÷$çIR
Yä’U—pðÉ"‰u`63‹o˜s’ÍÚYê5œUë†åw¦ÕtÀzºZ-S6nÝÄí¿Hª3‰äGüY ’¬Ìû,ÝÛB<˜qB¨NâEù'‰ŠgŸÒvNgö«~±5†œ²C„vFôÈQLñrT£Jt›2Ee¡d‹c©™op¤‡œtÅXØa†³‹ŒNÜEh…Úœ1±#^TýM
æá£°¦:|çs²9Hòð	Z±ƒFÏêÎëÞ¬N?;9}ç›u7LIEÃ;öj\+`âp°6ÔðSó‡»èú€Ü–'½Å÷Æb åºþú‚—
Ä2ù!jn°Y…Áäñ†$$¼´“œÃ‘j d¤é¤EÁþunýZ«òî.”ÝqÒ§·Z™éæøú)<ôƒŠù¼ïŒVƒI!bp-„ý7Ëúè3zÔÆÌ;ÑG!#É)QìÃæñY¾Ñ¤ÑkŒí¢ÊŠ=…×Ö!;Ìî̦%Bê<¸eEb’VJу>E?c‘ƒ	ÓÀ	@egü0oÅãœÆT’ö/†ªí™:-…¸?.÷KDÄO“=;UpýU²,àxÕwÏÇ"tûÖdʲkj‡·&PèÛKž	ð¼ÚÈÁIF塼ÈéÜ`U8CG•Aua~BLü€qˆ©ÿz¤AÎ8¾ÂlÖs¸ìzýM#²`áè¯f‘.µÊl2¶‹dBƒO/±‡r{6¦×·ð¤rÍÉ*•à•%s¾†—>É¿`Ó™e0*_ÃêŸ3F‹eô(ŸÇ «Bà„EÁ˜Yæ¶ÚÚŒ1š[ØxT&ZÚ26cZ³øÁ{ìW†9Åšl`yúš0"¯¶–?‰ÚTnÂéôò­LhTÉŽ«Ò½²Z°ºÏvÉ(¸“vßW^Ø^‘Kº(/¬.öG1ÔV¬±'´Ê0Î=@ß瘔v$§³Y©m¾>ù,HzŒÆ–ÄH:ÔžI+áð¾¯3mÍíž"÷˵#ìön€Ÿ!5úg=àm€mB	ÿQâó#©°æ!Œ½¿ayÕBø¾lË‘_§†{A¡Sµ¹ðëM[ð8ÁI—fÉøb2æ\j0%,™9L„k‹½ÉY¿5ÍjmR¼Ö¤dRQª(H¨5ÊJD䱨ÁÛ•‡Õñ ¶ª¿­Eq !”䥺‡9—Æo:G²Wu11u51]¥^õ‡ŸJ¢¿XØÜcæÈ¢¥¤žEþ
	ïu"ü!2H÷ö>°‹Š(܉þ£Ö÷¡í1¹#!ü"—‡$™ÿU­Š°ÔýcäÄe=›ãlböVöºÈ§9Ÿò`·(PC d”€VúˆÉ(.-²ƒêÂвÂ2lÁR†öè°R»M*"\¦þèò[?sù­7ôðËocuæ‹1äãÉTÅl4ÍÇ»ˆæ 1`2ÙãÓÇ´ŠçXç6)âÀBÓ÷ £Ý€3JDäÃCà¦ûÀ&\x£hg¬bz.‹¼1×›±»‹/c÷ U¦·ÃVƒ0{\Ê;K)U
Œâbµ¸et22¯¢¾“²vÔ~—Ñž5®
G­…4‡‰¸O.†Üó®P¹÷!æ±[Eì§Õ»; ¢'µulhÁ¼Š®v™±|¹2·‰w7Œ%Ò†£Ò‹79|Qnаc¢®MÔ—'9’€P\ÚjÈÏÞß)YŒÁ´åÆy$…A5Ò+ÞëÆ;ñ¨CŒɶ†ß`À™¼$ÞêŸøç9þó:GR)ôÎãèÏ–Á—eÜUªö¤¢ëJö<Ä`o_öã9"L|YÞÔ‡çåáëò²eð;ÖPO\Âíø4]®u’/~Hໞ+%Þ)¯¯ÛytœwÓ@"˶†mjEç%--Yð"¢Þéáu#KÀ¥<¬ä~Z~{·®þBrCÍÛŠ^ÎàÈRò†":?Eû/Î
G~YÌÈÎ?£uÓß
Ï;õé›f@NƒŸMžâ¯o9ªŠ*Æ7u†SŒSUä¾Y¾¦Ü6ýë2V¹à”Â29¬«Ê½áZ/Ë—ùŒËö¯´ÞYãŠÇþ%©9JOcEÅÏÏ62=.s×QMãXÌ1ú#¥Tñ8"’™‹8fWà]ÕhD}ê­ù®ùNQËE#ašàÌåÄÿÁ	.®3–ªAÔÚ6ÊÒP¤í™äÒ¥@ÚŒƒXïoÄ·œÒÕL=)ú£Mf˜Þ梻Ñó|˜ö‚s]%JUØ´%ƒyºZ÷}–¸0‚Ù¯6¼È!Á>¦Hº””ÚµÙ'Ž…#ðl	£Oœ–.4—­9VÚ8O©1‹¤,™Q˜\ø\ÄÂS*ÏÏ¢ýÜxÛ|¦åšû¿P„ä¹²-ÍE{¥P5—ΧPe½üDÈPÊÊîŸMÕF“±5•+&,gÜæJÅ̰;C’œÏÒqjÝ¡·Ø×s—Ò«õƒ³j¦Rp‹¬ôAWâtQ^u§Œ*†“1;¸oFU–†'ø—KÃóÇ/Ù´é 
òµ½¯(×e%Zªp Y1s¨!bÈ×:«œG%	KößUñ{Œ…*+b—s¨ù‹æ« "¼gŽq@þÔjfáöÛ)ß|ZCÜ‚2¡˜çRYµGõÛåP©„„ɾIÔmË<|œV¼<75„öã›q	æbUG½w•±bJ]Mßψ†dí-‚Z¤—R`¹'‘¹m)yŠ·e6qš•ÜURCøåGQC¯ê­iŽT´csÏjŠ6š™öNùS@²;¦çÏùS…ûtêNùÓ£CHùÓÂÃò§Çó§
€»ó§“Šñß}dúQ¿ÃJT,ÒÎßa˜A=:„œA•þePÝ”A½ýsõèrUBø;Ë 6ìA5ʧâž[3¨. «±ƒÅ1?çðyüæz\ϳ#
Rõ>@®³
hRÕÏ]ûÞŽ®|ΛÕamÏñªó¦àÔÞIx(á¡âpdá1Ë/·JŽûahkÆ}—¬)fKí=&ÓÐ;cÊä0Íœ”SvFÊËW-—䥸öjäî€H7ƒˆNnG²lòéí¬Ÿ0ͦb(¨h™M;ÒbÒKÇ;Õ ×ú}°=3ª@ Ôkzèªß0†üöËØ`Œû€P³)* ¼KFÕ)¾HdžÖY¼Hؼ5UĒ⣎âÜ–H%M1Wן^ìŽîG=ÙOžð¢ƒ!¶I|}_£?;~&µNySò§¯ËàãfRk†®&à&™Téþ?“úÿLêl&µ\.³&µ´æI)Nì©aܧ`«õpÐ×°FÉGâW.”m¥m(úŸrÿÎy†¹x›Ì«vÝA_£ëaGz!å–¬Y›ÞÊ`ßp¼Ð‡Î‚]U[ùl¸+Çe“ím;„äîlÏÑ›¥î£l<üºï‚x™ô	öoËNóXÖ~ÚuƒÂY%?!Ì«Üöæ–Ž7É0WNÛcE+äÚ¦td\ФíðŠ}D«W°­u¯&7%‰_™±ôT(±ìa(±Ç”Ì¡ðÃSŒ‘“Xӕߊ,D¾ø¥2£M=ïȵ©ŽQæÁ«ü)îñó†ú]”ÄKSÙ¿ðeûˆ|ç«7¯MˆÔfKq)¡Ì©‘}Z—LºKð‡ùÆõÓãàñL'Kò%èI®9I^îÖ¹3@#Ú½ÊÛ Bµ,=.’kÃQéT8—³ì©å•l&UµwÍ?§^<¸€³T»°÷÷ºf‡èÏý	ªýÉÙŸ^ôx˜s溙NlÆp#¶¶iiÞÕF6¢ú Iž(gôJŒäÏÙ9qUXÍsjƒdZ$Z1¦í)²Sf§…¾4u˜~²=•!ä¥rK ÜúHçæ¸ù;!Þ×R¬®°¡.á#.PZì#
JI++…»ÚÖ‘\–ÜOE¦œ’Ìf‘&[Úø c•+A›—Æ\ajQN$kŽØ‚!e&·µS\u¨¼«æé¢”›Wtɑ鄑VTåJ®â-c&ì$»×ˆÖˆÈšx›|mM™aÌåðs«MtßD¥÷&ÄêïË…F1X±QïYzÒ7¢åSYsÜ»Kôüj«ºnJ.»6‹~^?c˜Dœ®ß¤öž{šæ.S™æç3õ
÷±þ ²;7f²¶yX5OQ¦iFS:Íq:¶¤ ’W¯¹ˆ¦3·ò¬)µK‚¿`÷Gt=„+%"[jÒ§øû:=&u;šik,ý+ãâ¬iYm§ÔЭ´"Â37t‡|†NJzW‘UîßvžÚ‰^»Âš³šÐFŠèÞ*¡Ã’¨c"©Q‹¢¶¬¢‡<¸#~æ¶•ežqp‡µ¬áN«2ñ]u‘Omw­Üÿhoµi7¡Ú³PS‹¯€²­WZR/´ÒÍ/§MQ’‡»»e÷n[ž¬=eSË f¬(Ú»µ¿®GÚAm¥†(èl«@b—‰Ž¢a$êFE–#þbô’=êäMnà—'ÿ4VRiendstream
endobj
520 0 obj
5230
endobj
524 0 obj
<>
stream
xœí\i·Íç…Ä Ÿfm«yu“À²Yïlq`ÈZ]°¤]ërüïSb7{¦gå1’ 0¼Úí³HÖñêU±ÜôÚôø_ü÷ዳÛߌ›'¯ÏúÍ“³ÏÜľØÜ¹€Œ‚#]èƒÚ\<>ã;ÕfÔ›ÑØ®×›‹gÿØúÛv;½UôïùèCü°½·3ÛovFo¿ÜÛí_à‚¯vçªÁÛ°½¿;×Û/àØ½Ý¹1¾ëûq{±óîtzûœ¸³³ÛÏÊ
wá:«éÁðPÆ¿ŸÅƒfû~Àû•Ú~‡>ÄOñǃ|óüñ|—/¦c¯ðÇþx‹?®aŒ#&loÃû@”ô>¾~Ó8j˜§'ùà›rða>ø4ÄÁjøÇt®Lç\ZÜ·[|g=¾ûu}âyßõ¡ë•Û~˜Çô8J]D‰cº#	#‰ÿ,Ÿ~Y$ÓYFòªœ¿Êß–ƒ×­1ÿœ–ÓÊiUPmÿP¦ôLÊ©çãÁ­ƒBТßîÒ¯¬tÚVJ†fha´ï¬	žÆîLK—•ë.^TæoÀ`¤vû‚•LæZ$ÞÚ†ñfGª8Ð1í`ªN²ƒ«Ê‹ª¦zOz¢ ý]òåvûA9
s¯ã¨éÌ%>yÜ~¿Ó[õÏx}ƒÃ·f%äWWzòz|ñ‹¡ñlĨVƒÿQ¶<è\ÿ=^ú|§åqź—ÉJ廓ÌFˆvÅ×ò[¯e1ïpÓå	¿.Óðf—–šÆƒJf=‰„¢–Á\Ɖ
мÎ'ÊPè+¾)=Ÿ#ÅÿQ.‡®Î‰ÃðP/ñ4?†Šã³dõçFé®¶ú=:`4ëÀ¶wÔ,\Ò qòÓDãq4q…3é·Ÿ‚@Ÿì8 ­` ¹€çËNJ`zËï}!­¼žx*Ì·¬’¤ø‹¸%¨÷‹Þ+²¼H9èüCø§ùƒ¤ÛhŸº§‘Í”D >”o‹d¢î½a
¡¹M‚^K»z¶pà¤Ve½ðñ?pœó¦¬™|úãz’ò•Ô£=­ÜnŒŠëfÔdáâišÔ8SƒNºB!]qÉ]‘%ÀúÊ•è`(ìS¥Þ,¹’!¤öª6@ü|=_¶à [q0ŽqŃ‚& i	Ѓ¬#á9~”é]§2”ã{›anå[Y‘Ä{£]–%¾…Xe¤Œa†i8]8pkIÃCÅH,üœ]|ãï«ÈzTûá•^RiCÄ0oÃéœB%ð5ËNRw4Ë¢Y»öW
Q¼–¢!é“í©mB3uhꩯ6†’¼§õ6¡1¦V›+«c$Lh'̽tMÜ”…úD‚kZS0h9éØ¾Çˆð1ê>G3GóËjÑ)TÌaûÞalwÒÒ°û£Š³Ñô9ƒI^sºó•8Òò[K†©[r1y4vdò¼;¼eS¨	šT4ÓÀ)^2ÓœV»ä³à“
”~ô=-øZ½Â°ï<˜±>¡šƒ˜Öâkº~¨M0ó6m|¢1èÓ¨!'®å[‚'éWt·Á’ZÏÍç%®„¦“W»Ö°¤Vi2”…ȆÁÇ1æËÛ#¦°=ó7ÍP[Â_ÔDb{úV|ÅLBÆq0^„«ØÖÞ'GFEOšMz(<	ލ”"‰È¨,šð,79dt#…qY¦Ö¤Ü™¨š@H‘ X’~ûªà—QSДÌÚË,CQIXö™‰&Iëœ\M•ÐTþÅéä_fü;h¹G7SS¡7 à_e²ýEf×ßýJü«|°@—ÿx¾%´ à¯[d÷­(¸€ÿZÝ­¢Õ)ÈsÓ;Ì0z¦w1û#½¿.ö½jßhs$`ï*ÚÌ Ì”!⪢Í*ÂŒ®˜²îF-°îÄ;.;ñyz¢°îFϺ³‡I¤ù•<“¥|«)Óì&ÂE«CһŠ'
Þ(\/ßH1hfÃ{PðÆ ¾“I8ƒ$ñ{ë)öˆZWQì1E›Qì·Ø‘WðgÓMÈœûóˆï°pQò§?GùÀ¨?xÏuŸ#¬õ×pÕ%kg¾cOìZe†R£‚‡Ž0p¶uE„–è“J2yÉIÄØŒÑÖ)Js8Ñ‚ i
ÃÈë&þ£ZO%Š)Ö™2õ<ššiÑó¢ŠQEo•ñ.
ñå´(²h¡#ɘ¸‘œêàz~~YŸT¢è™z—yaÈ%¥µÌg‡žJ„]HîÎáæ¡ê€c39¨Qj DY€Y|KŒnŸ0I«N`«2Ac
yHªªij¹n (;ŠGWW¼SHØAÿ	yx€íáß”ØNyø³ $ø¢´`Ei‹SKëCí¶´¹¥Õ÷~êÌ)â'„{]Õ‹añCškµýØM+ï&ZØú@P{ÊW-R†UÕBOè`mTÓVëœ?eõÂ@¯éL.Þı}œD]”2ëö©¥ät%åb °kú Iè0&Ì͵DFéä¾?ÃÅEI(§Z$Þ-ùi•ðC—
šóÚ‘œÖri@¤/çX3]©-câºeÁ€
±.äã²û.ž{è÷Y„v¸—Ñ0]1EÃÚ1ˆ^çòÁ”âŸÂù'ŠK»ØƒyÌÉq¥@‚rÁAeÎK»Õö‹Éšn!Y±Vˆqj)gßÁO+%YÊDI—Úe°G¬ˆÑÞ‡&Ò®ÔŽI;+Fœª¯Uú™à¦Š¨Ùmß/2ãšÍHñ È7q{&ٺń{U³àð÷Q¸'¾»fÀù=6(Ÿ~‘ÖªRMC[¥:VA+‚«~nÅq€ÒH{(9Üm¨;hIpF½TšeBÿ»ËÀ›0¿äšå¥}?°nQ†±'}ÙPáŸ&u-è
ûÈ33<ËðѳÉwnœZV§<x…¬éꩊYKå:_Ölºdë¤òäp[M¬‹(~-Ÿvó‘ú.§‰ö3®¯¹¤nºe=¯“‹"¹y’lÇÝ`szy½Vc%˜Üd1Ϫ’N®q¨›ÆelÞEckÃ_BájÎƘ¨7¬.FŸÅ•.“¯­#/c ìÉ®"5U¬B?'عŠ
¤šèäÁ¦‹šÐ)îX¸ù•$È00­öE~èU¤©b7§œ«P~«tBþ$º€¹üH*¬–0tòŸÌÜi´Þ¨Yµ3µJQ@½‰3¿ æö§u¦à³Í°Ábé©
ŽúÓN.k–¢V¾”´geŸ’àX
Ó>›5*í¢ºfU5*·>N­ißÖ}¨p‚¶ƒe…æv…5†‘ŒtùY¬ ñêqBœbm=øA0F1,ä]¶›‚[®€coTþµ¬ždB’*Ù,’EÂüq—<åý”pv™ÛçMNpÌi;…æäeO 0Mä{)«÷¢r˜FQÕvPG;ä \5›ž†fO¤8'™P½”41îåt޲øTc2üfOXŸÀs­âG.k‹•©\g¤{ð
òuDol ˆëZö,TmãœÂ/ Úܶ‡•bö5Ì/Õß1Gà÷ÞåwÚÿv•ÊÒMøD®·g½EwÏYXtp“o¥L}ª‚{™ŒÊS˜iÕÝÓPÊ5ÏZemQo^ù<d1Díüª\õ¶5's"Þ\– õÜ_¹oÍó‘=°®{ßâiŒ¢Ö/.Hå_Öxêbe9“ûñ&$Ì…jÌ»FQºÖüaU³Àç±#‡ì
Ž6§
sLȀ݋ED¤=‡¡¸
íPß²Ua¾9¯ŽpÇmÈkí¼ñf<½”Zµ–—M­ŽeãÝ|O.ýRm+!èpÀ5œTŠrÅà&
o)Ó¹Šè˜õTfžf¶ý®wãéÕ˜ÉT˜^ö±‹^°œ‡-#‰ß|£uþ†]"¼½jèÉm–JÙ±F”í1êÚ®Øè`X½ÀÁ§Ž“㨈cÂuÓÂ:÷ëPsܰ­Úñ(ü‘³îÈqKt\Åîhòø&—ØÕŽc›+®|orÑü0…×1|ÍÜ–÷¥ƒµAŒ”¦\Ù¼Äk«X0€ìEã&®“næqè8à5ùy§}°WXg®{YÞñW’wtÝ8TòÇ^¦õï¸4{šy©ÉA­Kc4•ˆ‡}$QíRäŽG£úå'u[E›S;Æøâ¯íV]4®62{LKŒÐn¿ÁÄϯٵ§FŠ8uJ’²ˆïäàí×LÛá+1–,ö•ñE‹¼ñþ¨>vd ’Rî~B%E‹²¡³Ã{Y”§=­'ÖëN›° ð—¹DõW"4Ú6•Z)ÖØ”CÒvÁô¾ý|V6¦¯SbÜ8éùÒþºÀÕ«&M*‚OTßx"+q,x¿äqÖ^ÑײÅx3	CèVâæ4‘ƒc·¢ë»iý?%ÖíRen3ïǺÉ%2õÇ+¹§1¬/VRêBXÛ5ëK)CÿÅьչ¡¬Þ c¹
¯Ð²\uÔ¶¼D¬Ÿ`ÛÐŒV £¿@WtÅ)Ñ®¿¨SCfÒÐOz¯®þ²¿éÉ"É`íÿI†÷%Zóü?M2Œ«H†ß‚±å]	/vU$’=¾¿M=Q5Á@x€A_ÑleÇ9ƒžš­VšÃpwõ"•€û£ºÌ¹ô/öމv€EQÓ¾­¾äˆ{Úà
½n3×qò”0Èøº†¸²)¥±ù uÕD8¡ÆçÔÇÍûT½ˆýuòùŽ X?NR°±ÅÌ6Ÿ}?miƒ^YÕæRJÜó)ž}PN|Ï×ûªZ
¡«rú¤ù¸gü
¼&çW“h-¡ýžf ;~zqµQ¸UFŠ»¼S‹ÔÒÉÈíÁ&øT©ŠºœëUÓ*—²2ëËÑÝ2˜âr´Jß9H¯[Ú6ÉØ·À¥Ý¦Tƒ¯i®¶»[eAåÉÅ™ç¹SGûË`RÅ.€¤ÞÄ÷f³Ê©ãê6ü–Y¢‹g\Zú¢Ö8pÍ_ÔŠOKßBóßK "ìèŽÿª–¥~'µ^sÉÕª.ò·7›ð¦l´mÀèT•{û²³®™K~>ùðF&¼m¦·¥CN‹ÐU%RËð»ÙL¢3Ý;%沑•°-w>ÇiÆ4[:“OÂÝò‡½ñÈñ¾8‚}j@‰b¡ð°è†¹Ôê
˜tà§1 –ž°¿´dÇï,EPb%‰ßßG­¹EùÔbâM”ªÄ,ÞÉ*Bù)ùdÚŒ”“+XûôÉëÛûö(QµaÈIpön#7,ßxc<*WJ0ó¬ŠvÁЮ„h˜+?†‰‹Ì;kâ>íÝ7«gvÌpÿÂÚHxE]ˆJ)ÊFÊÓgfà5±•¾÷|FBÑç\N-¦V4)BÊ%uÝÃ7*m§ÕZü¡”)¡»Ë£ëÝ©²”Y£»ö÷ýjÓÁ6Îøå¦•—üàÜ~©ÄÁ«BÍ\V!KYkãh¶•êbo¯dú—C$½PÍL_‹_í™—Ð&ûJ<Ìd¡À\.£ŸôYè_®<)_Ûܯž4h=?†ÅìÇÛŒˆ?ª#³HÛ
ˆ~›gl»ég½¥Ó·×ä}Ã’5þ‹øªú[†ô©£önƒj­Ú—¤áX—!B ªÖ¶‡fZ[¥ 4ÚZ‰ÒËâRËþZÞmêdE é¼ý¦Ú[Çø5í’uò.—§™’¶!wWU}Ô¶å3¦M`Óä)…ªc˜àØÊ¶’
vu›]÷¡8ÞÚ Å'j§ß™)^K¸¦T¶‹;g £é.Ó®¥Â¤­á”åÜC$r™‚Ò×gÿBj¬endstream
endobj
525 0 obj
5088
endobj
529 0 obj
<>
stream
xœÍ[YoÜF~ü#ô84<4ûâñÙ$›Ý…÷r”ÅÉb!K–åµuIJœøßo]]ÝM6¥å€„Öì«ê몯ªš?v­9ìð?ù÷äâàéóáðÕÍAwøêàÇC埓‹Ã?ÁÆÂvê&sxtvÀ-Íá`çÛÎ]|¿™š°ñMøÏÑ_ …3E‹Á´®‡FG§ðâ—ÍÖoþÔ˜všF?m¾hìæÍÖnŽðþ×Í6>xÞlíÚÎøÍ}·ðÄÚ	fÿœ^ÿû€6þ6v¤ŽŸ7Îbn>jÖŸ´¼ÔS“g0,5r›o‹ïŒ½ôÓA¯Oo×à½`
Í_þ”Ž{Ûoþ½}ƒ½ðlÀ>ð‰[éã(Ýü3.[Óš¾m¶Ú
ƒeÙö.—íÖI¸u];˜ib¿†a7—xy­
JÍmÎð÷k¹é67pÁÍæ¿øó/Wx¹ÀË5^ŽõÁûòåWxy§-n¥…`¦ ®§0¨ëtPnx†Bbq¾Ò›ïÓͽy¡7qÅþÆ…mkCpÃþ°Á1Ë%që›òÁ[¼¼„	u(5lëüÏâ:u*²¦'°’i é¿ÖÇ—i¦™Lk“&™ðÍ뢑Ü|"“L|žußHó.;=®Ý¼M7“¶h⟌'ë<Á–v$n;´£›F÷Ø8~{f@ߨÙÚÿj¦díQŒVd3õ„¹ðf„	ºÍy³íQ-w‡á—/Û~‚¥7°ŸW°ñµ/¸ø1ö‰å
Þ@d¡%]So}ê߽Ň×xá·=îk‹ˆ€÷±}”gؼÀ×ÞÂkÙ</¤»žº[L›[ãÜO±Ï@ï_¥{/´U”LÇS=Ëуmi¾íGý›@­ï‹¸Ž7l½ø@ï ŠPb[XBøÜ€D®%vq®BÂÎpÇ¢@øÅó–oÕd{¿æ»n$ó8çQLbò.2íΠУ€ÓcêòFM+Jdk{×úÎÌìÂqœÀK´¼,¼wÁÿQ3´tº úr-»0’P±b•èu´D
Žr) ©Çæø3¤¿e£äQ ¦P˜%^Q—r_ðK»Èùž`·+†
qTqL‹w7ËŠà5Ú쀠+݇÷ÙØ÷ºLòT‡¯ìûŽ“9°ó¤ø—<'Ô#mõ_¦`D
	kg%r_“\m†Uˆ'	$\f}âÏ*ÊÒ8´¤£Š%A 
Ñú	 ØrÝò° L÷IɸŒqˆRMë¼bž:œÛÌiCO‰œ¼ÿWøÛ‘–ÀÓ‰.Œ;»ù	º0–úO&ˆ°±¶›¸t¸LÔ‰˜OgºÒ˜¨
ÅIÖîBKF`ÄWCnk²V‡v¥Î
ûªID#ÖKké:G¦¦À*ÊYߎ^
âkÙ€] é~`®5º¹
Á÷%tžèSÞÔq|íŠm€3èh<ª!ªB3s— †¥ìîƒá̸¸ÒŒÉ¾ÉÈÞF«@þ{²„•+¾¦v#«s©5˜MTí	tC–nn¾Ð:ñÛI1Ӝߥý
ã;"Ð	ºQd›•˸œÇqnürQÑZ|gW,Q.i
æ(€úiÑpŒÀnlýѲp±iƒ¡p×áVæfÉmPl4P&ƒ‡B‰òúB}F;‰ÇÁ­d5r%ÄH~bõà½c_Ós~½Oì3¬Z'bË]‘A\ÔÌh¸a$Jšnftœ³EOá|®+™úƒl‰ë'‰Ïv°'hÙúŽ3‘Žg	·Z?ðÆ?ôЫHc_eòV.ØÅÑI»ÄS*9>F|¼v•%T8}å8à«óûäÕå	îL©f5볜ñÙîÒó‹ˆAÓX‹•t­eˆ›	¢Œ&ê*gcJ&ÊÌdæM~ˬœ…º_ù1•³P>gÔQÁSVŠx"üsJ§=¬!R°_ML˜%/¤„V¤M¾c’‡ÉïøÌ¶\p“ÓT‡†Â|0s†ïå\R±)݄θ_'’ç{¤Ò‰¨ÈXôÉ´]
Ãn…0—¤ÎÝmw(í»x\…ÁÇA,Ð6µù)ù—V¼ËÁͨ€Q==Ò2;§J÷é8ƒ]ïgûw°g“gZ2¥ÙS½õø”@äŒYø,ÃSjçÄ¡«‡«v>’9rHºêXb‡E¾K
^¿Sé)¯‹äàȃHÉ-:
„µä4VœmƒÍM!a,€¯aÞ55F‘@æÍ¾MQݼd‘›%„ÆU7XÄ­<ÅÒ¸¨¹Ås•Ù™ÆÄs›±“/BõÃê[®ÄcÓS z ©Úè3c(Çê±ÌãFâKº(“iÕ­V²£8Ê-’X¸=³/dfyLlÂgINéž	ëÝÄ„fÙO¬yÂCÿ€šwT+
 uRÚ›—Eú¤V¨È
Í]:ÁZ`ÿ‚žii_yÌ6V™|:Þ!'Yæ‰ú §ÊD½ŸthšB(#öÙþŽë]k& ç@,x[œj_Ö‘Ð@+¹: ¾çAçCqf/ÌjÉàÐbáDrÑg@T³~º}_“ò©â9óSj¬¼at:z9™õ«\Y¾êúÄ+
‹´‡
rey!?'©©Ó”ÑÖVY‹HkÔ`í”áÐïú6ìT/•ÏÂøå˜ÜWd‚Ûƒ½È#ðŒúÍ£}ØÉtðúžì×LU`Záqe‘e¨³$K·Prb”œñÝ	Šs}~Zœf^ŽtU[N6ÒçœÞúD2"ã¡ñ-X1[$D`;û±3ñã7Ó†ÃhØUm0ÆMÊàîöø§…-c¬),SlD§@Á®J¥aÛ!L›¿âòû¨(èÒ¶Co&üNÿˆm	ت]Ÿ?F4a5pÂÄ)ÌÄ{
£dzÎwÞ²…Ã)–ÅÌS—7X;‚@­w¡–!VM§Q¥Úlv:†J ¯ƒk>
stream
xœÍ\koÜÆígÕ?b¿u7èÒœ9àqœ&.êÄqÔES²l+F­Gb)ÿ}ïcwÈáŠ+yƒ"ˆ%‘Ù;3gîãÜKþ¼jµjñ¿ðóôüèá‹~uöþ¨]ý|¤èæ*ü8=_=>†FÁ•fhµ:~sÄOªU¯W½±M«WÇçGÿ^û[7½ÖôsÛû¡|·þjcÖ/6F¯¿ÝlíúïÐàùfk¬†›nýn~¹ÙjúåñÆâªoxš)êžÇ«FÅNb›cüó)vð
t,þ~³íš¶Õú?Ç…	(-'`]ß´æpü
ä@^·qÜP[ÙpZnMÛôjø½1µ^•k†#tâ«õk˜Ò5LíÄYÿ²ÙºõÌÊ· š§?á×|
&·u‡+£ù‘ó†Uôú%4੾£>¡+ÓëKý
Þ¡[ë3ø“ÁëôüþóÃj(’Z*-à)ò7\C’ã-¬á鯀ƒðRl’‹ûuÚ‰'‹Ml»Ï¸lqø(5Š„ýç	¦NqB¯*ƒ	_¦§>àà8‹³Õ8:äMþõ*îâ¬Î°­ÇUÀ5׃·BeU3²„°¨0ä^¡^¤‰å]÷
.cãá‰p:™hè-\
†RZÓž:Aƒ:d&…m
;05dÙâÈÎQg
OŠæfðÜ´ýÐóÌß"ÌÐ%BEçï)iŸ·á¢!Éxy~Ä?Ï‚wL=Üà?ç•Æhòi¹ÉUž·ž%°uº¥±ùy1í³tQlìEºx–.ÒÞÂïè*–ç	pºÏŒŸ~_Þx¦çPn?‰³â6Wé¹ë45Ôªá}v™Þ¥–—3BÃ|	QŸ¤‹¹e^È×µ‹/%ÂãÅ_ä¤âm’Îãešàd kš«â}q/\<©]¼)v2\¤M¿V=zXmØÎDi¹ô|dŸB8'Ai€ïl¬Ýé»·¬”¢Û¥’ç;ñåf|úÒQ=ã.Yg¤s8r,pR`ûùä*Z
ᓇ‰–>yë“bÉgˆDMÏf¨'ܧÀ#ÎF*T'{e¸	IW†U5j´¬ÙçâÅ5uíyÉJoúàEœ˜‹Þê?ìÿ¬yôAç[-F¶fÜ{T€à)̺÷°?»÷Ø!ÂñÍ1pDúQ¸ø¿á³oð¨xµ)ö‹cü”
z€—§¡Uò³öA¦f‹ƒÅKþ-œˆ"$¯G|/¶ý$è4ÉÒî™n´ýaJØ›î7‡K޽jú¤;.âj~Øø€×¹øÃðnäõÞ!úºŒA‡`ôð)DÉ¡ýù2µCËFöûZ—ÒU[¾“ò”‘×'5Kj=¯‰°JábŠôü|¤‡ óƒ©÷¢ý;	–º³™&I-o&ÏãCè¾€Lc¿^“‡À¥lŽ]ú“Íg—¬/¨?â¶È“35Æ9é’àR“pžC§;†‹snJ‹ù‚ÄŸ£`ï–$Ð3;våö#3ß¼3Œ¤=‡sÝú´ð! ŒìSÍ1ÊeXžŸ$1‚Ì;¶YNnËéµ9Ø6¾Õ#*¾ðpB©¯þ@š‚nÅ9‡y2&ì»Z<Øõ´Ùõx°î[G¶X„#{†Ú­c‡x
/7ì/ãú[ØŠÐaŒ	{GË(&d.uh´Ñø¶²ÃAæ\\gòv²ËÂÅ‹lf⯹X±ÃÉ™ûÆŠŒ¢0½‰‘«úIÞ·êÏæ>…ÞË0Ðàyêú j(õÖ(r÷W¢¶l””žÍÑT±‚7Q—íÀ…™ÌhG‹é
7!›³Rœ£ö¾ì0$¶‡9~Śɵi…Ciðir?%“gs°¤eÒàDQîªmÂh¬oX¼þöµ-¢VúSPg¾O0ÓÉC~èûªÒ½ÆoÞð˜LŒFbQxMÓ G5sRÄøS¸ä)oá@ÄÌ­%œU#Ö‚‹Y%%;"ÄÆxfÂÞ]øâÜ•…êÎ†Šæë&†
ÃyÏYÉ"âó)mýÑ:…%ueik´[PJe$§¦#²Ñ„	|"”¤ß8M9ôŒŒK‘•“)ÐË).]ùuãP?t$7‚—ˆ(ú4$´álSrày<¢¸z_}wôóʘ¦£Š)Xn¿ãÐ7Þ¯l?Ḟž=~zôðé³Õõ/7¯þs¥Ž~ÿ<~þüxúdõ‡£/Ÿ®¾›-Îù­¡8Ëô
]g¦Ñh=KŠæ‹ k˜Æ¼°ØF{xamª«õóŠ2’ÒoUìŠú%C+"#Ñ-ÍÕ$
$—´V ƒn†ÖMRèfŒœÑ¹ˆ œ£–’Sr㣾My“¤»(ìD9F(ЮVCäŠz%Ìqð·‚"×äÝìňÂ#3ÆTðº7‹!ªÑc«šî€ÇRšn…†½¿3â15ßý²Â°
Y¿I«ûy`IŸðÎî¨ÏC伊…c'í‚»sDgD3a7ÔôThç“óp¹ëºça" E4°$vcGרQ†¢€½oKÈ{•Jª°÷ŠÅW˜|Í9“›ý‚b\;ÎZÀoª)qiÁã8÷ÐëÚ;K(?´´ [{]+Ë«¨òwT3Øsncè½Ê>âUôo¹&.бV¯Dx¢Råö}–¼¼¢læöaï“{CÈîw|„Uã\ÒÓWž¬ò|!hdÖçN‡±9«xk ¨í$%"ýûßósÔ3Øl‡úÞäóé¦` ÑM<4ù|ºù?$ŸÇÏ…SÓAêõZœfl?"-¾“k5‰\äZG4Àt/
>SyU±žw¦¸kÃÞÙ†K%³í1ÛDz|ÎçPí"³ÖD-½‰j"Ïr—Cqþ„È	Ï&:g!ËÝϹé}‚™¬ïÎfîÃ4ÕXIß–FcÂJ†ïø^ÓÛm£R¯òŠƒÉ¯8ŒE¼½>€¹05ª}JÔ‰&¢¼&‹aÉR+y–ê‡=´Sk4^½Xu¾”ƒÊ™‘|YÉC
}¢n
Úç¶*4"7¥Ursh	cWëú±öVK)Sò<㙕ãüEyÛ»Iy×tBkíY¨fC–£$­ó0òKâ+JYˆÞQ¸ŒõÃÞ	Ïç&
¸¼ˆ Kµé‰~º¥hÍv>3:)¦mBdmKÞ>»Èj‘ÂC÷iœ•Þ©iBÛUê?lÇQP•
“{;.Œ²=3J!°ˆT_f»–@’ëâ§iëøý§i©%ìeŸ`sûYÌ3ÁÞ?Ê~ë#^[¼2	q8rÞq>ái¸í\ÃNNå=®à·æˆ‘-k9\(ܪˆ&Pª¢…œÒ†Þõƒ«?dä¯7r&Æo&Enz^>§‰™8¸|°IàJù$áÕ˜}â:h™.Çè…zâ=ãiÏêOtžJeB˜wB1XLS,¶ÂÒ=×­ã2êSŒýg*0,$O~‹$“Å$J«ÿ>9¢m?ÄÃYÎíUZÈ×÷ÃHÃÆ^Ÿ´viS²§µ
—á±ÇØ“ÑË,NL3
**e{Žj–2-ÃHøi;,8w¥¨†qMoïL´tŠ¨Ïƒ‹šÔÏûmzÏòèáÔ“%\^Ý3Y<õ¤ûv¯”l0’sî¼§î“'èZ‘ý»"3VK¸GÛ[i=Dú>F	¿¿KMsaÃ-˜Éý‡A™¦MñvM“ŽÑ­Á—Iõø²ZZ:¿»ÎèíôLï@Ïd®â$=œyò5¡o“(›jÐOïhf÷fo®+-ÅÞä+"¹,¢@îpŽ ^n$´œ×‘å|ldÏjG&¹ì­%„唲×ßùÏ•süŽDÄ­ŠGâuºò<„g`\GÈÊî&Ý¥w*ê—€%ó­âƒ§[Ãcvû}]âœÍ+è¯_cvœ ²H~)Ï+ë󵟣[4½\1áÅtJ'?J1÷bÐ~t‹ÕjW]¨úªS4Ð#¿ÁÕ…ÆÏWÆk?rÁƨœ_èüZO!dÆí—l¤’Ãø>¾äYBuL4Ǿkb™á²JEêS«_é(Š	oQ)[ø‹1û”-†Ú¯XŸ8û½’C1¡N¹5"p“L„EÜrÓs)ЮwƒcS¥bvÓy­šQz4až¥ÙŒeŽ·§Yÿ^+ƒ!f*ñöR…9œGXkˆ6‰Œ¼qH;Љ½ojC
Œ†/Þ6p…'Dš©hÚIãt\QVw¢Äɺ‘
%Néë
Ì )“¾¶á¢»H˜_?ñÈßyGÕº'¿‚Ö寵>Ö@åyÜT`ª¡:Ý­?
5«,Z©€öda”RþS`a`˜ÆØ”™VÈÅ̈ˆ³¿ƒlxFt!eÊñ}?Âð‹
Àü_I§¢í™/89_UP§o±@ÃôŠmRÿãpQ’ýãÀ^“&Û^æºwïæÜ‘®½î]ªC’ÚÞ%½ªÔeÙn|-ÂìüJúËÔE4¡¢|Bÿpýü Α`8·›Âõ€µÉמ^E%Í7’×ô‘4ñ1TzYrŸêÌ©Ýä£9â#PÌ%€
	DÖä`/KëÎk1¼Æc{°R.æcáß½ùI•Ë3¹¯UA­ê4uqXA-DN-Í,Ñã´¿/Ð×åo‘-¬³´&k˜)¥Yè™É·‰"‚‹¬åìÈfŽ•EÁMx×\8†Ùå“õŽ
ìK¡nŒnêÉæ}£Ÿ[?‹`}*^M•óáõК;ŸÔâΖ½ÅÜ¡Å9Jê­T¦O•°œ“á˜ÍŒ[`¤èL|wô?õŒÎendstream
endobj
535 0 obj
4649
endobj
539 0 obj
<>
stream
xœ…RÉNÃ0½ç+|´Qãz‰íø‚¨bb)á±´)ÐßÏŒãÚ	‹P$Ç~3ïÍ̳߈à’üâÿ¡-ÆSGëBEñVÈ$ñ÷Вݤ„{á%iæEÇ”Ä)âtÅ…"M[\QÏµÌÜ4GÀÐrÀp’k¤æ÷XYÑ&¹÷uåéSôŒ•Š6ˆOX¹	LY©•àBV´m¥<{äÜ>A
à>
stream
xœµ[[sÇγâqÞ8›BËÜw&)?b*¤;Uœ”0¢Häÿúôez¶gw¸8.—Ñ9»sééùºûëž9¯wf´;ƒÿÕ¿§/î<œvÏޙݳ£×G–^îêŸÓ—»»'Ð ïœSriwòÃw´»Éí’scÙ¼<úno8¶£I!çýùpìFç¬÷ûǃMŽ)y»¿ª‹Û¿ì\Ieÿ>oÒ´ÿq8öÓ4: àXÞgëþsò7ž>ŒSž,Nã|É»“/NþðÝþ̲µ¡ÐyŒ©DöV8_¦ý)Lá£÷nÿ%HÙ˜‚¡¸±€\óSÕà—ÖKÆÊ¹ìÏPHGBÒ‚½K“ßß°AqÉî@ƒÑæýNh½S±¹
iRLºÁ×8˜mÔ_
®Œº‘’\.¾[Ìø¹ØTÊþü8¹”KhËÉV-—û¥Xވ΢úSÊa‰‚Ùɺi=ËXg”B^Íïµ@o°…/>xÞ+ë…Ç8 Ÿøí%<»†‘±…ÉÔ“Ç¢‰Næè4¦žKÖY°{æ® §Ï,6FO\á4+¾ø	F¡"‚÷ž¿Ã©Á&ÌD’׎°ä8‚ó_¨NXK¬íäLì%ª†Ê	?ÖõCü->:7/ꌕi@	³Æ.y^6ýd(ゥò‚­ƒÞP.øÒ´	c«÷óÔ´{·±9mm+7¿F=–2Mކ3¨Tü(9o-ŸÊÆ÷›8÷–.²•ÒM	Q%CÕWÝ[?ƈþU¨·Ûµî¶8ù¦:ÛW„aŸ#”‚'Ež~Âõ-nïUÂ
_Ò!œðÙÅà4l.ëÔÇô™§øiˆñ<(	öÂÏdRøG½ÃÍ÷,e36𸤣_ÙÀ»!'\|Þ`“¥¡UŒð‚QÜ5…S¶JZ¾A9B Åƒ>Žç¨º}2| F¸¾à”°âD°I€U]ÊV 5@PC.^#:£u³xGW’õÇ"dE#i‰Ð˜Ð!¢²pž×mÃÃÏ¿ÔmAü9Ö˜öe´}ØOœŠ]±„N³Y\¦.¹ió8Þ%7s…wåim¦öB°…žËd1ïY¥s-ÙÙÖ¥Ì/Ч¹ÿ‹^‡Ñ{ý]â€{ÙØ…-Ë)GŽç>˜{v]°hîñ¦ˆa<-è“Aæ
%Ö§çó¢:R’#¼°¾·¼Ÿ‚¦àŒ& Ò±ö¦Wí¡ ç´
񸛤
Í@d!™F¡âjžêh;òb.uÀ…—‘•H‰¾¼÷²Ñ«9¶Ã5­.”Ï;ºŠäÞti¬Ú´Æ­f
0"IöÓà«õ’7CÚ$^}§q–g0÷9AªØ2 ÆpÞ»#@l8ÄοoÈÙ´ÀR\³É‹aÞÄgÏÄíW'3#ä5q@àz.«À¼EfHÌoчLã>Úè,ÚÉnÿç`¦‡VoSL\©ÞMÅñn]¤ö‘#ïì V Ÿ×Æg™®¿´Ñ—±/¬ýP§ãÐRà<@²å09+l¹
SS€æc´Ö—½µ[†¬ã½ä>˜?H­²P†{„¬(û#bÀΣnüœ3À³.xØÌ6ÊxØuèosŒ˜JÀæÉ§¨?>…^S²Zßà´À¤“'ö)Ò¡‡8lóq vMiB°)g2ÒÃ*	Îÿj~½9|SØhŒ¤,m)³²0'1`‘ÔeÆÉ$l‚]?vS¬j=ÐlÀˆƒï3䥠™ÖUS@ŽäD5Su„”õGLf
|D‹…$,`h¡Ožò\Ðé¤zzÃí°™D¡/C«©Þåk§dŒÕµëyįžÎÏ’ŒÿÐYP5Ÿgè
É÷áílF)'8â—dmÄ‚SYÊ",ÏAª9h¾&õJÆÙÍÌ|Cµ%y®,èJ¹ôÞŽ‚ÇqÓÒÜÔW™¢#°y²èÿ&$à Õ	¹nä{M¹‹èý•[È[G •—š=â(ÁQÆíÄûã°m.‰{3õ	WÀPc½š’_õgYÎgUe´ñØî‹“£oŽ^ï '*ތіqRÐtKAwÝyð÷ÝÛ¯ŸÝùvgîüÿ¹û{ðçÁ_v¿;úâÁe¢lkÈZpk§MâbÑ%çFŠ—“R‹,]~{QA#!w¢*ü£>C$¸¶RFµ%ò †Øä-hÝuk\i×[ØÇ%—¤4‹©Áu«,(W21±âVœ¤LÄI„½¼JÞ¬ÓŠbiÊ'“¼ã‰bšŽk©4y›‘AS¼ÇùûPä/ÙæPÃ-i¬
œm“$-’Ò-pa—÷ºy‹ÂOzžm¦ÅhŰßu,sï4¥9ÏV)¨Î
Ê1ÄI‚ùNôpi¢ïøºm}£‚bï·á‹åÄLS
=“Òÿ£ø}eökBrA‚v~HaU|z‹y»9DˆCæšT_ÍÒäôs˜µŒ)bÀ·Í©˜„¢Ääªwý¾Ì0ˆAâªúQ›¾ÆVc‰yÿ[ZteyaŠäbUÞ>óÔÈ€›’$'KÏZ—Ó;Ös±§Žx¤öúMD oFTxsuµ6žõ.›Š Í™Ö×”}Iæ
p£1RXÛqÈqÊeV„0I›—ÈŸ´s"ʡޕú…Órî«<þ%­ØÝ2ƒ×±®	ž»mâ¥ݲ+&†©P1±Ú¯´Y8€CœTiÉ™b³a#Í;YÕ[Ü=®«ë=J«Ãœ1‘AU{ÑnÝ’–KYÕH‰äbðUµabd!º¾¤VÛÞ®£­Ò´dvF#€Í$øÇÍZDVIGðie¬öÆPR3·›#¯ÂÞ‡øÍü§¢Kʆ>4Š‚˜†¶APÙ²0NÝŒqÒ‚Í÷ª^9R¯>‘óÆ5ÂJᑲ¼X·ÞÏרn´WÒµoW7ÌÁ„¢ñâ6]{Èžàs*ê;/Ϻ4¾ÅÀe£eâ§›dœ0O7;:áýœå¬>±iJ¹ÆÀEïñ$_Ĩ!zü{X{ÃqŽ3ýTYí¼]ç˜6é#3×ñ¯V¸°BTá¥Øy­™¬#ÝÆ‚:3¦»ÓÐר>R–µ…ÉÐZßsÉA…¼
FÄKØ((fó¬–ùÚ„·<9íד–~Yª}Nù7œ²a‹[­`aÝõü‚®HXØ8£©¶O±Ñ—%Y{˜FØð²Ò‘ïõ->1޶‰[bÅ+Ä´ûZ¬Õ±¨²8w&àØ¬Û®Sqè-ØHmª1˃V]ö‘gÏøG)K’>×'Ι°žnqøZº]ht2rÙCß3Q‡`)¢.gxgn¨ÞHv8˜|ÊYŸ(z.{Ý…F(‡çJhsýé{ÛÛ·Šy—?ŽÁ[FcužÂ¡l†eɪZ¥ZG¼‘ï,áº)dC[gŸ‹c>8&Ÿ äo³€°®ƒmq~׈óòØ^.Ÿˆ“P7¸úáȘu‹îªZ@vy^­¶¼Ù0²?¥D&æ¤ÝqnÃÄe¯Dþ‘T[]_RÙ ø÷	kƒèi¶ØœÔ‘žT—Ç©åaMàC·6Z™é«ƒí¿ðtÓDg½óû«Y܃§õh0µJ4Ú¥SÇd
3´çªõå¢*sïM¤ˆ˜ø•½é¬/NP®IžôJ)Xä<ÒÁ¹þo„‡þda‘î¼9”~Ñe¡jέhyJY^¿8Ÿi7_´¬¨–¸à¯r!Ž4(a—¾`ݽP™Å4gp-(dÄÔpÉ%ª‚ÒٰΗ/†e•Q‘ˆÊƒZj•~IGu…祀2ëW´]ä‰z퉭2ÓÈlã—âù¢ã’¹÷±§O†½ñ‚ Ìwp·s!¾TòQ'¶c-qù_ÒÒœ-¨x;’Ùì&U â+>	Ìk®T3ØTãF.{«®ÓÌl³‡Íf@NZ|Íjì/·k7r)±^Y^…¬:Ñžp¨I5–©.|]í»9UíÎ%äºÐ\)Ë!ÛtÙ¬²e(»ìEå7{+WkX«ÀRŸ±ŸRX¾]g¬\y.¹Ü¢ôB‘•S›/fÈíΙû¼«f͘t¡¯é(fòI7èhNuâþ\‘ÜL¬7ŠCç
[˜C¡13?”Y¾ññæFl~½‹:è½T¥*r“µó<ÕÉ\¹wÅè*jNоÔtÉñŽ'+àRi8ÉÌ‘~•·©·í—Gt|““¼¶’X…Â"¾~1ðÆz¶éôU»uZÌþª¨˜u£Ô†ž©¼\åàr7¥»â–k¦¯ÿáy	2·úåt?)ØÌÛ#ç™XTEvy{µ¬Vwžm4ǰÜñ'ê,‹nÑ,3.Þ¿ôËãNÐ$ì\3“Íe­æüÎâtCAä}õÌ™M‘îÞÐ
ÖQÞ.뙥ëŠ_æ²V.hÌÁN­æIwùÂò†ß›Yùýv,SR®™
Ó›¯ÙâЩˆ—tîý:Ä03úÀ•NÕjŸ]Ç2¹}¢œöÛR©ËMšk“µ–›¨]±Ðmþ®ä£˜‘ç’í{+'4}ÙúmJ»Å¢~lQ­•~:AhnÂm]ûë+ôo9×6Õe¨Ÿœ¨B2Úü[‘ØÈþZt¤lýÃ~ ñ	eõrî±5…®Áª|‹RÚOL¶éÐø›£ÿVÆRendstream
endobj
545 0 obj
4134
endobj
549 0 obj
<>
stream
xœí\YoÇÎ3ã±oÚÌÑô1—ƒð	+p|ÈÄê°D˜¢(‘´lýúÔÑÕ]ÝÓ³\Ò “ð¸;ÓguÕWgïëMךM‡ÿ…¿O^Ü{0nžŸt›ç¯½Ü„?O^n>~
Œ…'íÜÍfóð§îi6£ÝŒÎ·Ý<|yðývnúíÔôÿyøèáLÖÙÖÐéáShøIsè·_4¦çÉÏÛ»ý¦9´Û‡øü³æP^Öµé¹ÑW
5„QæÖCã>Àæ]gÑhÜ9X‰ãYà›ñ6tÎÂ8š;ÝM8¸¼kéºÞZFxg¤i`i=ôGË”œ¦ô¡1s;Øb;šyfŠôÛSüçz¤¡Ûþ„ßÃC·=ÇíÀ„fû#~}…ÿœá?ÏbgzñRžqcúš†:	oý8Àûy{惥È|Ü>	É_éäá³ÊCܬ…ϸ§C n? ßáæ~ØæK¸ˆ½Ïëkë»™Nò.~¿ÛœÅ~D7øÏû°“y¤å?‰¯_¥•žê¹ä¡ÐxU§éýQ|øFãiêLJ'5êœÖÆ|?=K¯i>Vcž.—<;Õ_íóéÊ ²Ï_j޳þj£òT}íAž5xÖÎÁr½@†b޳lÕÒéM¶,Å3$ovbžéç‰Ç;Lñ.gçEHpµ‹À§µ–o¯$ýR\ÕF#§ôWÊ£’ó*ë-žâÇK–";´C”¢óÔ	×¢¤äÞë35↡ýŽjÄE©±ãÆ…=ú¹H«wD6غ‡Õõ°,Æ]0pGGü1Ðv foñ™Íér-Ü;ÔÔÃö=lx:ÆéÓøçIIÃk`T<ÖÒ7þ9²±
´¦g½ïÿ<0Vˆ•g9Ú -‘¶‘x{¶`†\oyýU†Çn“ÛþÖLò«!K¦ëÑxà}¾ˆ*VxŽÆÃ·ÐNÑkó	‡½L=.šÄ~¼cÞ?îÉÒ2¦G=<щ¤fø
銣>‡ÿá/¼ðp6—±
vîõL¯ØÌ›hn§©ÐÇïj»a³Ï|{ðz'9å†Í´1è7L›ÁÌÿ‚!úñýƒ{÷ÿ¹¹xsùìàÞ¿6æàÞøÏÇß|îºùËÁg÷7ß^ÓH5fl'ÓLíÈvꓦʞ~}©~[ÿ,µïZ›-Uq½G®ñŽmÄ%Û“%ƒ‡M¢8Ñþähò›<‘‰_pËCg¸ñù™L‡ó$QGÀ“¹çuCà}äÓið,"J/hhZ,MuÔ8‚;¸îˆ9q|M“fç+`–<´ÓrØu¤;)`…d%NŠN34È%…g‚~HR³}›Æ©Ñ÷0?¬h7mþˆaÑF£ÑÂ~'/êÐ9«f{	‚LWØ%ÈŠ0·G÷Áx&Ý«@Ôx•cŒ'è;öKÐ	3Ø”†‰àr¢oð¥!E©üŠŸÍ¤ªósÑÈê­/˜* CsÓN5ä̹õh3Òåwàù:¢žÅCâà
aïà´ZhÂv­75yR‹|Ó;Åç¸Wã"ÒÃ^™ l¨6G¢ðµ7ëøŒÄ3–P{$Åõ4a»ˆEਠ_ƒ"¶Ê6sŒ'¦!µë…´NˆªìZÚ»†¸©è=›>Ïт̒¶õ½
DQ<èXÔ㩲¸©³ÒæýD­ÍSÇa‚tyÏR°-i÷X¸[ÄuD\½CqõÞ¯]x3•=ö#åN`/8•Iù'»`Uµx;̨Zúm{ªÅ£g7(eýĺ¥à­ð
úIƒ;áôÂ1Ÿ3u:èDÈžùv	[š…Í»yª™ˆ´¥iØ@‡Àê•(.äE¥ž†ÈnÕäÛ[Æ@'zVtbÌ-U$kx‰,1\+`ä».B§Ztަð˜¹*Þÿ•3AÆ®hD äa„ÿa$…8ñ$$Ô„Ò6 máèڌĶ‹þx8ôO¦xªÚ•qÒ'…sÙÃÐ…‡$ñÍ-ÖÔEv—+RÑBãÀ˜§⩨1¬Ð˜fšå'vÿQnœ
×@~ ¿FÛˆÿ‚!<:ç'øq$.@0^7zʌݤcg¤F5/Œ³aû7ìdÅ×¢ÙÉ×ba´†Ò
m«-A70"D^Å^³7Ú4&9PKo{ŽÃ:ÕiÖ謼ž×TÌÇš‰}[ô‡è˜Êı™è(ö~™­
5,¼Z4Cü(ƒéˆ=ð%­è)ä™›ñ^æåŠu•á‘ë9pºÔQaˋТÕúæy“ü³!ÁwáÑÙ&qšoM`Œ—ëø¨°EßÓñåAŠh^³€âfq’¡ÓÆ0eMKÔ@Dü£‘
ókØL±‡¶Åeu™	ÝœLDvtÌúüØÈò2ÑìZ—ReÕÔØÇŸ9-‘4ÎeaxK´(<{|ι4›’‡ø‚ÁêIͪb«Æ”&Mðø\0i3Ec÷ƒÛí¥JVyâÀþš:FE#>†F¸ÌóL}‰4à‘>Û8Æ%ÀÁ¿VÎ07Ücëfhc„S`ÐòÊY$Mw¥[²KD‰Lv)âp(ãxþ–ÑfÕ§[j£š1&¶
î­‚/g	$˜Ùò£8LdFz€ÑQ„àšÔd2µè™²jÄ>첺”‚ëV3*ÙêÃA~Wi¸„ö´4Ž3ßÁÂɽ¯j}0†uÙ™niV¯¨­2¹Àõ9Îpê8;XªiüAõCÌÃ#~툑.ƒ*DcØÁÒË7¥7+úë2p
`ÕÓD·8,®
PX˜GíæqÖŠªìRµkŸÇ”‹XŠbW)Go¾nØ3©g•'[Û`,½óûª«…Í!´¯fÐÉÚª‹²¸‹!àÄ-¡ÉÂB¦(M§ØÄcZ@L–kùÎT-g®vØ%5%蟞—Ïr$Öyáæ¸¸Z%ER¬mÈ¡êtDB‰²­Üaj\¹a{d–c¨ÉÂ?’ŸØ·t­¤«„©Û¦^4‰âÙ‡jeó\»h‹šÊ¨‹ø5Uåey‰¢ò>¹ˆÒR%8ùÕÊc=èÿuåÕ]\m¦ºò
ÁeVz˜—*üޱE‡¾‡na“üYøgQàŸEIJö+
t{bqM^ßS®¨À
Úà(…6aû³JÁÁQ#Ÿ²òòL^Rú>•È´’RŒö°…˜ìQÕƒ/ƒ¹?èâ€,XD!«5:[!Hã̯Ðñ„Ó¦R"˜¼‚`¦¹E•ˆÄ}D,…Eaé¹í÷6­K˜2² ‹9:PR¶‰õ˜ñˆ03ÎRg¢âë¤ÛÇ”f¤±ÿ½{f˜Äp”kÅ09¾øu‘9-tS–Ž‹õ±<W[.©!Š€‡’»ZЇÔúáö''y@'?Î×¾à•ÌézXÓc9†û2‡ýqÍÀY»ã’å=pλîa¦(Š¥¤‹ágµ°IŒ¿ÜVX3ßhš4…:ó8£
1ÉMë´Ù㦜T›jËMsª‡F¯F)Rç!Ú]‹ÿ0]Üß#µÜRÿ¨öðrÀÚ+å[gíßµTÛó6Žøcy-Õöã2eƒ9\‚£ÝÂNX(mK5MVO˜úåõS)Ðîœ3WÆœÛòþ–»dD½kú°µ“ßPq*<‡KwÝãá´IæÊ	o»~¥×¹°ˆz0MqqJ¥y’Ï—65,5³À‚Tw¬ø¼õÄYúHrJ…RØuÓ†n×äð³ŒVí©[E¡!w¢0Ðú	ÌQaÃɨRù4nã¾rds‡ÔNÌ‚>ЍæK~:…
ëÌL“ +Lý
8sætòâîªyñGãH°ðO‘‘ùtż±Ä²ÁÕ´þÊIàÀ›œÁ’ƒ°pª€>T“—dæn²%¯~¾Ñ'¹:M;XÚÜó'VolØPèµO£å·0c‰všKÇÌq¢Âó¨_âU%•Ãä´þtEÀ¡Ká.Õá×’cYð„FýÐݦulÕzF}ßvý6y˜q}øîÿ€è~ä+^»Tž…vDŠü&HV8]À/0ìÈ<³´˜;Äü>^–KU7ª2FÑVj÷±Ü{Ù	euY%›‡ñzÁË)C€Å=‰¬¤gíŠ?,µLð@è£U.Xét¶ÂJÞÎbž+ñEp¾tu¸¤'y0{äÞéOOó>ÅË_H˪ö¹±RÄ„c×FWÇ…Ÿ™z}œª@ÿË ©ãÍ„Eõ­
–þ±”OÖ(ÊÍ:c*¹=ô§.x‘ÁcPÚ)s¾ãõtê
ff-K¥¥J½óÊl?hR´ûÛƒÿ']Übendstream
endobj
550 0 obj
4892
endobj
554 0 obj
<>
stream
xœí\YoÇÎ3a8aß¼+hGÓÇL÷H2¬À·•äÁ6ŠE!I‰”eýût]ÝÕs,It†,ÍLOwuUõWçìóUÛ˜UÿñßÏöî}VO.öÚÕ“½ç{®ø¯ƒg«O¦Τ;ÍÐfõðhÞ4«`WÁù¦µ«‡Ïö~\›nÝlìÚàßÛ‡fˆýúó[?Ølíúáfë×?l¶ÎõMÛÆòàËÍÖ4Ãý°¾á­?Þ¸ný)¼ƒÿ»_¥9`“æ€él·þ~C/Åõ70öŠkâ"_'ʦsXûóÿ§
«7è»Ð´1íñá!ï+ý‘­¹õ¦oB¿Úº¶	fè?—ÑßÒ?aÏ{™öœÈX?&ž³>€ë“DêcÜ2"K¤ïÖ¯ýëóô$Â`—_Lƒ~Z§ÙÔÛ~ý—ô÷½D:ü¹›vmš¤[¥óÌKÿ8‡×ÆÃ݈³@UgËÐÝïð°zx.~ÚÈÕÝç£ðfkBãß–‹àz?u’VÆný4|
Ï‹
½„ëKú9œÊ„ÏÒ„ A±Ç]ÞÎvôêÌGµ§³
	Õ§“؆z&†ð6µøvîœ×Îoð‚¸týP-XñùZ†7.`¶žùV£!Iªn€=ÒR¦Ãý‚~Áþp¥§¬û‡0,§G¦¦:߀(œI,óÂù	*ÒÃÎXœæ|Ao,NÃëª@Æ“Ä]„0>»~‚'eAiœMtïHi¾H¶,L·b&·äñõ 
¼(±‹‚‘†Sà&ͪžâÆñ=ŒE¹Â©	KPÍÒ_ïÀØØšw¤²¹´quþŸæ6"F,l&¿x‹¸%42<ê{H7híÿÝrßxØP²½ÿýÞÝ;äƒÃì&€ _€sªžepÁóÄž‰Ôj&È<§kìò\}|òë
1bkýjkmã²sñ1ØAš^ôK¡芖A.#‡èQ]Öra ÷¡M£’©NoÑÌ
{Þ‡¨¶ýŠC‹P<÷z{>D:Ò8¯<¬ô¶K’”9±Gp#Ž›š¥Ø^Ë&Ʊ¢
Åy ‹”̆m¢·¢_ëAÐ}DûµO”“"½,øÏ#Ape-À0ÛŠ•¹ Ý
ƒQ7óRbˆ[/—7«È:ñ<ê”ì`k\ÓuC,AY°<äœú.´èIWúl9ß WcõÇG.
¼ü)¾)o/(oHÉW…Ûp]¡´§'%¹öÌôR¾)j¶Zd-ŠCéî
$;LÜ$`³M‡¥oMÎ$Ð+[‹«­yåÁçùòPŠò°‹;§K‰:ƒ°Ã²Hš1«LŠ
e|,.-Šû2߬UI6‰ªÔC({­<¼Ö#³^¬¥ò–bÖŽµâ¥é]öòöÙÂÀŸ‘A$nNw–§2iy‹©§±ÕaOƒÈ‹Ök%‡ÏF
À&Î
z°Õ$8é‡y‹t¬BE6@hß(¢P—¬¿¢ì¯‹R)[\¼ä–lÂq¥G@ÿ!?lû%é#käŠ.•Ñ
ÁpŒòhËðC˜ØGÊ¡«G¥4.f–*óÁJEÇF¶l,bê4$l%Ëw–e¥N¾%8«|„{;¬‚7'YîLYñ…£žƒkñRÉ	[yŠèŠ”Óþ<óªNœ`ŽvÿáÞw{ÏWΡ¦´«Äó¸r]ç“g½êÌÐ61Bâç“{÷|µº|ñòñÞ½­ÌÞ½/àŸ|ûiúëÁg«?íݰún1)4òº8)äºØÀ*±é9/Tè}PèýèUù˜¯sÊÄõU~å¾`¬Ï!"^F±¬ËÚňîÞT»*½õ­áhWGy‰×#ËÔ
èo †í“Ó/xÕ|ÙsK£»~dd§çU–‚Ldf<®ÒR~ÉyW›Ž¥³›_M‹ç)µ6µ‘Ž‚é‰8òiOµzcL7AÑœš‡P›ÛÚM‚ø¡—¦·0ÝW)MÉV:ô
¬ä˜e虵mdzÚó*¢­ÏkeIaæÞfÞû¾wu„núÆ{Ìöõ´ÊSà5ØVÀôt¶2é	am÷¸<'ñl»è)2ž>­B'ü2Oõ_Ê^^äÑI"ž]¬{‰Û*)•ÊôK³(ëžâ޹4ô¦Xa¦p‹øH[)ph(ë{ž>œlt抶†,x–w7m`ˆh¢ÿF8È/ZëÕ,¹ŠwvoõDÛØ’þÌ7_ç›çšNy¬(»I-¹›…¤§eäéÐyç¼3Š).P¥v~DçÆÅÆäƒ£è=ÑøVó#°ïœïÖdÉk/*…Jgܦ轆Ä;Y~=/þ5€ÇYãòÚa¤…1+ßN_ΉúŰ}"ðGs+Ÿ–›Zݦ?Ð4(Fßø,TŠ0åÀÕtÌH¼ÖfÅL:ùCZŸT*
Ï1òE5RtcrW)*(c!/Q)R߃O˜œ9c[÷ûañõÏñéœÜªŒ¾ï::€ß®YêÙ…®½úÍóéûÍÿ@ów€æÙ;øÍÿŸÐüŸ¢¹RÉóŠ9òÒo}\ÆÖtÕÚ…‹Öê5‹ñw2v_Öv™Ÿbr›{ëë2~â6Tê:~¿q³†SAÌŽo7ÖV¥asD×
uÁGôÐwÖ¡ýPòU1HÒg47Uõªú†%‚¼*uê:È„ØI0FanZí‹“–ƒ$('ö&-Ò«”WƒÌJ4Shç»Õä¾ÅÀðÕÆFš/'ò$}ÕE$è)cZ¶÷9¯ú˜¶èÔÙõ3*[„ný+õ†DW‡üu2ôŒ1”fS×yL3,%L‘G%E7%݉"6²›qB«\r&¾k?G6yZW§ºKÕî}À¹OT¿ÅD	Á5>¦»”Zß["ÈD’!³`{J-lk‘ÒäØ
ªzß”Ú6Mï+R«¹DJêFNö
pܰ0?ª ŠÒ7:UöÑ“':ó¸×窋ä7*¥Ætå0¬M9GÚÖP†¨êÝUÇa¶X!•U>š£T¸k=0B%³Øê$x¥€B•H¨À¼Þ`i,:)o}
"—!¼¯’Äéh{îx@–7÷¤Y	«º[&‹€Å„ZJï$cXÐÝ»]Ý/ÞlŸ6¥™z„Ø¿Â?ÝúßÈ@)[`ØHAm>üÙÙ-û1=´i…ŸÓߥù|œb¦…ÅZ~È95)/–AI¸–bF¹÷vI~Sî+¨~¬êªôçIž£$«‡¾ŒvŒ–oPŒ`¢$Ë©‘–s£E?Þ„ŽÂž‹UP.ÉiKœöңŕ;ÍÖù@–ubr}OtáÌ£…*¹?´RXñ®ˆí`ã0þc¨".Zráh½4·îÿ×ygP×¶Ùã8Ã^“Óð'l¥Ó9
á4’—´£È	€W{IïO!Š8ÜH~úˆ.ÁÞ³ë#\›u.õ¯Bw(5Òºå
Ôîç<:Ûpö]—ÛJ.Hܲ³	FÕݓى–5󈔰ԱÓe¬ñëºRn-AûZݪé›_xÿ‡ŠllšmsiVèÛ©êâ9Ú÷mµ[‡¤P°¥ÔkŽÜPø
¶¬’v)2
£i®r_7HÔ¬"ËøÓzF‹tŸlJ£ŽÐ_Œ‚n*ƒ,@7Ë\¼7Dm¬éýSþmc€LÇúí¦‡q{‚ˆ6v¨»×¨ƒÎ@>nÞðÜ)Äî¼t
%—›l05‚¡ê…%pÚÉÈ
MÈÑÖçñ#2d³@~`Ånê•ㆃ%zxXD<*ô…NûÈÇ¡¡sΪ\|"¿Æ‘QoV†!)óå¶Kòð¤ÁɹiizW“09žÜwc¤èuS÷¬nI?€ïE—9âëù•F»ªT	ý =-Yn)ý:ËÖ
ó™I
0ð9µÌhc,½ÊsWæVx4‰å° ksHˆ-ÖÝ¢ŒÛš‰QB¶lÂL½
Qº—€ x§µåðø7êŸ+‡Ô¡ï—:Hã”Ñ‘V¡ž’2¤ä¥òŠEÏ@K°#q”Œ`zøžë³•'ŸI”ð"t‡q/ã\Þ¿aVuCe¥&¤QiS+±Sm(FýVÔ‡Z"†ÙÝú«Z­Æz2ã(6SÇ ½roÅítG¡$¶°£™.?qT»aWg.*xm=ÁÎ’çq.g^’—/ÉÒ³-~3ºRËÅàn£s¨½M`/CFÐÊ?Í[Ϟܡc†œÐ„>CΡÄw»C"þ¦B¢ŽZ·Y5èã"æ©_
”°¯JžúCßU $±´l²F›W£Æ’5}}„,sC›£ßܽÊ1·jdÉNäÈÔI_‰ÍÍ*Æ	ª/
Fÿºé0nwyxiΤžn_¶•ç!Äg¯uIl˜ -¢|ÌÖ·nÆúçjJé>Žñ…{|Gé‘ÑW#™#0Xw=)V'7Ù_›Éãò[Š­£hmTÀéáÈ霫¤ú¾¤e3I9¢N;ªñEuÓV©Ýj÷¨V#øÐ
ñ†tŽ$ÌŒ×3Pú划þºBÆ9"é~G×ÒWg_ª†ËÔŸTZ7VAê@à\ÔTÇÜP´}¯? F¨¬¡´Šà¹SÁ1tÊj³F¼_§xTT¹{SRŽwÝðÆayLö@ðUå5±ÇhÄ^f¡"æˆ7 ÷h±uÓû¹ÎŒ&—|ì‘m°åé¯ñMoeIÅÐÂ9m)Ç›
Su`§®÷Z•bÊ™Gå"ÖŸNœŠáFéø“˜:u’TõðN|´žóàÞ+Ê96ƒav´t7…_¦Ô§ëx”zè<¨(ÝÑɱ¢”+o^h¯éÍ	Ì®XrBs]ô$ŸDÊæ¹¨<âœF‰\uÖÍýÎpþ'_²•?B¯¢2¯>Öž	Ñ—?fic‹ÿž茡eì×bwƒƒMÞÂ)ân)Mê82ûIƒMÎÅäLfº¬ì[uÒ–>´ÜHócs$I@UÛáÊÞ×j¢ió_éË{ÓïZRÓ·îxu’
™iµ®es&ÏóMÕ}:w³JÂÒòñk^ÌñpîfÝ•Í7±Ÿÿyƒ¦ºð¶Mur9±Îx•|Zj¬óü=`ñ{KÅP\jÈGJk_+ù,©©ÓÂsî(·H*?¤n@+¶)
i…ªMÉE¬JÓ2èsxר_KØYkeÆ×žFñF¸,¼+õ µ|c¢ÞåR8Ä¡fÚºûW’¢Émþ‘€⡾1Pj'a”ŒîMIF_çו>b×v(?2‡<Ã~t)§°9s4W~Yü5„#}¸Õ¯G8Ì]ÑO䨠«OŸ%åÃ’F––اb•“]ª“Ðï\¿©C}\
!Aýáçô§øóz®UPÒ¸ND¡=ÿnï¿N’^”endstream
endobj
555 0 obj
4438
endobj
559 0 obj
<>
stream
xœÕ\ëo·•ßÏÚÅþ
÷[ïº×ÃÇÌpZ @ÒĈ‹Ôm»h³(dɶÛ’¬Gœô¯/Ï‹<äðJ×.ÔtØ–f8äá9?ž7ó~Õoͪ‡ÿøß“wO¾›V¯oúÕëƒ÷_®øŸ“w«/Žâcã“íÜÏfuôꀾ4«É®&ç·½]½;øëÚtú§?ÿwôûø•3ÅWÎlÍ?<:ƒ×müúëÎlç9øyýyg×ê6v}Ï¿ê6òâ»nãâ‡}?­ç8÷6¾±vŽ/×ßw›‘¾QÃqÚgðfü~x–ßþ¥Û0Ú®¿ŒÓön;‡>yÚYFú©ÀÔ׌ßX·íÍ@ƒžw80Î2‘œ÷;Þ÷vŒ3÷.Râh•ø›ñ#tÎÆy\î`v`ryÿçHKßÖ ü0­ˆËDÒ†øÝ4Yât)Ÿ­ÙUÜâv2óL¿¯âÚóúeç×'ñÏyœï¿`—ðà4¾Ÿ-nž_Ä_ƒYßvn}FCâk§_0Ûôõa}¿ßÆ1Où6‚iqàqÝ»ø’yÏ£$½£&Ú|€aP2®/áw;
êÄ» ×}bñY"	¶K#=§BxŽØkòŽBd$(ñË.‹!nØ#jÀo×OÛ1’e~㑨kø,Ê"ÀÖqƒƒCj6΀èufýD‘6È‹^B‰0E5#Ðgý^ˆå´lþ¶SœÎ3ÇÍ̃±‰YôÁk:®ÞÕ&¢váL?øåÅàðáeDzÁ¢|gïñàâi:ËX‰ó¸¡!ÍTß$Çב}ÂAžÀäŒ1–aú†’€‰»aô4ö&Þ[XÓàšz=F™ñNo‡€yEÔD8ññÇA‚ºH ·ˆ€O8©ð¯~e! P?ÃÁöJ„—̉Ù	-ñè?6é/ò0áôLóg4äÁwI•И‹ü{~*3"Rx_ˆ”a´=–R:´—Œ}þ3cÝ0GÖ¹‰X&cpøØ
_§âC7NÈ€ÒŽ.pÓÐz€ø<l-q˜ÌÌK‰kô¹q^ê‹H6N[(·×zŠ3pxC!ÔÅi	øéƒHó#¢ì)¡&ª¹)ÙÉo2ò¾bƒ¾::øöàýÊ¹íˆÆ8ží°ò&BÁ†Õ8#(Úö/žê$V†…讬A1·Ý.Ô:ãÁÿ(õ`	$àÄW¡“£µg]‹¾Š¿³áb£;ºÊènûižV^4÷9|qÝ‚&µoišs~ˆ€fü
~MWÛ Àé-Bo¯Ó` ™þºM‹§·…¦Ùø	™°~‰°=@Ã^åayæÛüð¢1!4þ^EyþX'ð×YIœÕ> ?ƒ7™o•·º‚ž‚ƒódÖ¿ó8R„'éóLo¹¢íÑö|¦*•š)oÓË֜…ú’׊ºóÖç ø~VDÜ´Ö;n=¼Ë3H~èÒ¿)dòä;ë4ú¸ýЛŒÆÐ¹–¯h"ðá4°º9êÐñBrºÐr‚6eǤ7ã)|Cß?ì:ðãwÊ?Lß±
ôlóáGòÍ@K_–þ#Ì,Q©,4;³ ¥`æ;gÅŽzœòYploð×Wðk¿ÔýB©¦ÞÍDc?þ¾Î9ú`ù{š>Ä]¡ûˆŠÈË£>A•÷÷¤·U1$€aXFž•ÉåHü3à‰ÚjÐs•9’5äO)\iiRå
 µ“GÊ9âQ0ºv‚©t,ð=Oü6ií K6½ö4ö
|-úY
>vË™ì	W	‰÷wö.T°ãÙ·û±€·ã˜Ã;‘¸!‚–”ÏvXÿŠ=½Ñì{æÓ/Ï~•Ewµð~*WQy¤€br-£“NmÝ[twFäN)[ê „šðP %¨e=Z¿9ð_nÙìô-‘A~íó‡¯J·6{]Ðr8ËjBà%1o«´,, Á×â£ÿë¶A6SgŽSè…¸gi‰ñUÁ½O±`ÿ鄱;ƒá³®»‚eK…tÛz˜–±æ/—3˜÷Ê<í\öÊÑ#‡·§R’®XXLp›À<·ê…Êõ¦øÒ`ÄSeø‡ëä&‰k8î&ÓEçÐþÈ„`ª ³(I3{èdðeÇ[
,ÊÔg?½L*'“½àÖ$?Í;‹[âù©qËf…{àJÍb¢a¼_7¢Jsöó}Öé‡ÜQ©oÑ1êH­SZ-cb¬Ô20(Uq²Ig¥8¢!pŽºC¾î ±ÏCÖÌü,Þ¢R/j	:;¢¼[P-[BìÒ_‹‹ÊCTñL–[
jRÐc†ìÇ–ÁŒ(X؃jÍ,K¡Î;N ûÔ~¥›•’^ˆRí(®$ƒrs;-ò8첮̫µ–Õ!ÉUŽSôëø]xØ!„É¥n¬´ª¹†„Û+³bçÔ+•,ê(ư°ïR4£@G³X°R‡Wµ”}èl ©¤CÏÝYW%Á,üÓ†“ä¼G³-‰-Êï„ÐS¥½¡ž©êšiæHÆÍSêÉS¥.««Àþ–bb¥¸Œ~é1ê±4‰òUôÉqyN9 Ònu€¿fyUµÅ¦D2å‚f©–Éhk&ç°NªW`ØÏæèá›k@hgÌ ¯za™­ódÍ*	"ÛvÓ9øŒí£Ó­­)é,Ò ?t¶î†Bî†Û„þdX RŒ¨VD¸Ù/õl%±&Ÿ™×ØÉ9×cãÑ9çz\M1*g#Ûþ†>}[¹´oQŸÕ-8•ë“:“)ý^&¿¡Oq–Þ)Mirrj|¥°Ðóò*šâë-Ôxéô.s'=¨åWIÒ¦>c¥Jììо­üh’¯µùõÜ•ON;ûÈu„çYÀ¡8FANô|êC*±6ÝŽRL±„D¬ÈÄ…õ6¥S`huœMÔÌ„ûvÖ§Ó…V5yLJAž
oRã^pI#å»"®²ó]ª `[¹®»óZ‚	IKɪ3EçWþœÃP:Ï#]Ät	¨Â"Œ¥gWTMhÇ!Î7ÔCKw=öMNã¹"H©+lÙS£e¿¸ZÁý
‡Éa†¹…3ä.½£/ÕØe畟&CdRÅ´ã&j²öT¦X…ëé†LµÉ¬hž!!ó¦ãK”N®2äÚqÓíqX¦˜ÔC*
qÙ>&Ëdle˜XÐb>tØ6>sö¬Œea¬hˆú,ñ;¹-uq,R.ɦHÀ ² ´@<¦‡Ô>”SfKÞÊÎ龦eŒ‚
RUôûñaÆ0ãµEªGÌŠºÑÒ2ãvú”0#Ü:zt2#n
*[‡:ÝÒc
·õ7¬9Ÿ¾‡Ï	^W˜Š4²g ÜEIú»@ù}^¦Aå3H‡ë˜Ôrb§Å÷sfy
’_‡ØÇÚùâÒ†ç*ù¾	ÙO(`Ðåö3®±µã§”¬±€¾Ç&ÒZHi2—Á®·¸Ää«×
&ù|­Fï†t­¡ê`YçSBX©mºg)èúFëÞ5ÉeÑ@Å9Þ»ÀlÉ 'Ìâ¤:mW]PÎGjÇÕ¦ÊâØ8¼OŽsþO‰ÆµyõOëgïÆ6§Ô"•ZœÄkUA“ø(ÚåDö¥€çR{¥1ò*î¶{K´•žReÁq
ÀÙh¬Õ}—æ—ç©v{à6çÿ¦¶hUs¾ÃÒ€¿QU\‘`
DÀÇÂ[ºíŽÿi*P©"c
ng‡þ¹4ûTQx8)ˆÖx9$â.ÀÉG™zUèáXÕRfUjOJ9=ã Ñ¢¼#Ÿ«ô®Ýlc“kÆ0ÇUËw–V9V”¦á|ÑÒ¸-žÒˆB¥Ï1h`!êöƒSšàÞ;ùnìK¦Q´=ǨtlçÛjUØË¸ß¶òÿ:“tELÕ33Ž+õ¡{ß )ÕÿÁƒÿ}šNpS¥ú„¦"ãÁ¦G¦ç~Ká¨obi%p‘J³ïÜVú™n(¬Hö~^øŽÛÓ¨áÞÛÓnŸgìn¾“·Ô<œÞŠšT]Ð[8½ףó÷ùa¾0‘týÌIÒÔÏ\ÒŸ¾n^:ãŒ^îq¾*¿Ãâ‡ù2Âoi¿@_1éMÙvtÌ}êÿœ‹Ûp<˜¯æÓºî>?Ø­Þ”i&ål·L«õÇ”iŸÞÈM‘è×ý²‚ñÚÞÉ…3âÁón£þ9;—ÀLcQdq	é&‰îD¦H{rúªMÑÿ/4¾nÞ¼¨Ÿ/ñÍÉw÷ïù6_D)/ù`eT‚‘ðýV3
ÓoþE`endstream
endobj
560 0 obj
4772
endobj
564 0 obj
<>
stream
xœÍ[ÛnÇÍóƱo™1´ÃéÛ\ ¶eH†[
?ØC‘É€7“\)Ê×§.]ÝÕ3³$%[F`ˆ»;Ó÷®:uêtû—uÛ˜u‹ÿÅÏËÕÞË~}r»j×'«_V†^®ãÇáÅú‹}(à}òQ©à} `ú,ÕåU…Þ†|—&›<ú2ï÷mª”ÉûÃnÙ‡p‹z©W
^1ölâÈÈÂ8ð•½Ãh\€ïÆ‚¤§ž‡„P ‹-úÑeHyÏ:cãzCçú8?¬$»s‘çu‘ú(,<.Ù[uç:ö¤Ò¡T°Wð6ǘ²E4l©7Á s|äæ`àúvŠ`ÔVž:áŒFMÁ/‚š1(èx&då©d?=æ"°Ïêuž}D×õˆjWOUáÔÙI.+ÑlZüñ÷ƒŒå=ÇÀÁÉŠÍ`ŒQ„'X¢Hé'b¼³¾Éð_—¥ãJ ?h-•+a!ÖNÃäéþêÅê—µsMGt9¬­q‡u×A0d'_<_í=ÿÛúîf{¼ÚûamV{ÏðÏß	Ï¿ZÿaõôùúÅNæR†^a.ÖtÐm×Ù¦‹äåŠÃ¯žâHkGJÃ+€è	¬^Í»wk6q@Üú‘¬)»Õ,°&@·Žbãâ—¾ )#î¤j\†ã”í]ËBtù¶¹íËèt#îv›BZl6{æ5‰¶AÛ}c½™À!9ÐiF3qóF
tØl=Áæt««b$<ˆNGa2âªsL!44Aäz8hv1úLc$…YrºXÚa„ßÖ¥YõUOºK NXa—ðûšû“}i½ì˱FË‚èÄÝÆ°A+Ú%WH ïî(ë'å.Â!¯h	öL‡ÑSáã=ï,Ä1MæRÙŒ4Ù9½Šëã4=Ë+ °Ö dE´“Êaïl`ý þnCk^ü­ø7þÀ‡Ò‚vÜrGè¬Â§Ý(Mò›AÛÈVzŸI)Pú-ZÆÆvˆŠKÈŒ€@„DßïK\ë’'æc)8š Ü,0ú8'i
d˧-&ncOùäwˆæ€¢£†N6&žr	LdÏ ÞKX^LF-$¹¶ú
d{O€€01~ª©nLR;Wä&4ƒ1ñ´€ž­áNÎм.¡6Á(›;‹9¯ýÏéÅeY„^œÊO.|€ð“÷=è%&™\JÌYzxª]^^ç‡iDd/ðéÒª°çŸjøËK,¥lߘ”wÄôñÏ9Óà
n¶´°•ùªÂiI&«Ñs¾ƒ«áÚÔélEýŠx'ö4Y‘½—Ãڀф`É> vTÉÕ§eëMÛ˜@U`Y®ï¡;3lûPY0Cc}cG0S°HkÁ‡À[aŽm(µPu=²% S}@¬ÆÚƒ±5
(‡
®Òw-GÓahúa¨^AÙ¾÷à?wè?Gï<Ë
œç‘¨§B&dÃj}]¾é
·2’3+a˜Cï»A:êÇØb°ÎÉ@iöi"·¿@Yq€@ÒF|»ÚÿüÇŒ÷CјüYµ‚|AúKUÁAZŽD‘ä
ër:~É¿9'êZò¹T/'REÚìG¡	×Ȭ42´szê0‘mEʹ´cÐ97°`,~HRÐcÓŽ!+d‘À¤Ð’!ð”«ýž¯5}Ô”·^¢vIpõã,0íŸ$Ygqe°åàšLÂ%À,Ñ–"^ÍcÊQÜ–Vë’ÖóŒK¼KóÑ\Kí¹nÃχœY¿Î†¶•ÅÃD:;IYІ$ŠŸÔʸ%Ï[=)0gez4¡)5&“GÑfd}Œ§‹•kÜe€»49XB›vÉŠ„¹¨"Ѱ§Ìˆ‡ÉFåŸr°ëJKä(: ë9·RâsD;½/«
˜Q´öÑlƒüs,CJ—™Ð’È Äï&¸´¥•ECœˆ°_ÇQJm™I?ö‚’fY"Cñ©š4˜7$1BÔj¤_žÕ-­RZÇFò墤u½NÌ7É¢P)¤ŒÙz'Šu,‰.5º,*gC#BlzÂ%­!gE„cëLFø‡ü«`LJ8Ú!‰âÔw*pÍæÝuo¬a,$IFBLlGù Âå$f†©lzæó–,ÖÎQÝ€÷„ÂÊx'Tg†ºåÔ:–¬r‰qO$]6öcÍÄÚ%ªùŽ¦ÊœÛrž)Òb4æ¸þ?ºñ·ôO1a…—ƯŽÐÖpfËiì4—SK«’Õ¹¾éXˆX2@¤
¶Àíë	?þÛ†©Ž7[ý#®£¡lˆhJH?7¾1ac,eNÇ»y´€a‘(CM¹-Ì*[0^ùº+7´nœäFoY±äd@š8¢† ÿþ<ámJЄ¸±[y±+OPÒJ,3Iv%Po?2]€Áì–é'§e‚ÔŽùLñrì–uKGA«ÃÏëd[˜j9C”äWD†]á]#Œ¿m8¸M0OM¼«E5;’g\ø]Üóø"ím26Èß—ÐýFÙLz˜Qú¦HŽéUº-bƒƒ|H›Êó;-–#ÏC^þ÷¨`£ÅLò’ú’N¾gêL-")Cûέ(*y;÷;d9qšaœ%’’Ž‚&±3¥(aç	¤Ic?gtzÛê}ýà+8éÏØM3U9~4‰3;,‹T¬6¹ºE³.òRv”ФfA|ÆŠ¡&b9º9»\)ÆD¿Ãƒ3–1¦¢¯í˜oªlpéŠL:©ƒQ̵íÝ#+uemdøâ w°ï&Ú̼ÓwsT³r¼PüªžÜɃƴH‘÷0—Úy%Å{OWRÌ8Œøù©®¤xß7¾±ŸÆw|)9Ôñü6Äî±vÀÙ»ßa¬eÆP޵T(•¶ž'0Ó4É/ðâɲϡ=IžŠS|®ëÒm¸„ÙÚWä¾D©Ø%d½‹	@ÿ(jLSƒIXíxÙyr–T&9'Iµ2YØ}=ª2޶Œ÷ù“]6‚½À0ys'DFƼ{ Šò¿Ã@ÁÎÛb¤ÖRÄ%™Q^uäD¬ñ&ùaMb¤w9⦨cÀâ%ÙIdŒ–6[©yÊ<˼ƒæ˧’¸bä¦iñ¿srT\JÖH7á~|”…©àÇ6ìº8ZõžNx[FÈüý÷OmÔO“ö-^•¼ð¼V·pä ÍsÚ&^œîʽÑ/gb6˶½l™¬·Bp•3Næd¯unµñ]|m¦N,œ†9=KN“l&>Éš8‰W‰½¨Û¤RðÑc&YoÓÏ’¹ÖÏiÕ"-ˤØyO6sXàp­2ÅÜê£îà•ç]»2oËÿsÄwTìÙöI-âk¾žr—jè;Ç’ocÒYLJÓßœ‡*Å67œïOpEå¡Ùß~òÙßþV³/g•”<þÃR¡‚GiЍàŽ|
ý—<à3]\©àr½çó%Ñ#«äK·KS§+#Û‹Õÿ+`Àendstream
endobj
565 0 obj
3701
endobj
569 0 obj
<>
stream
xœåioÜÆµŸÿˆý¸4¼4ç"‡Z Žs¸Èé¨Ú¦dI–Ú’mI±“_ßwÌ›yCrµ’¥
ÃÒîpŽ7ᄄ·«®5«ÿ¥ß‡¯÷>V'ç{Ýêdïíž¡‡«ôëðõêÑ>L0FÚ±Íjÿù¯4«Á®çÛήö_ïýsmš°îà¿m¿öÿ
«œ©V9ÓšîÁäOš_јv£×7vým³±ë}ÿ´Ùȃ§ÍÆÁ®Ö#ìÝÂkGx¸þ¾Ùô¼FM§mŸà îø%~xRžþ£Ùœm×aÛεc¼ä³ÆâœØób‚‚P«¿5Öµ	<éë†&Â.cðоOqz×Ùv4&w q|
|3¾Ç‰ÎYØÇÁt‡»»ˆ›Ëó¿,]¬!0Ò`>‘ŽÐ¬˘Ž+ã[ç{‹ˆÞ$LÃ
ÛÁŒ##|\‡Á8´màF ÔÆ;´=’&Ûnèà¦k}茔‹¶uR`11³>ÄKÆÁõA>Ú¸>†]‡¶]Ÿ7›®uÖôpmøìúغÁÃ]áXï{gJˆ~}	—¸
p·öÖ¿dø¢]Ÿ–Çiû1êíùòÖk6³±«ý/÷öï#G:ž2á_À]\›XñóÆÁö`,¾{øèÖ/üÇÁÈ4ÖØÆ®KÓ”ãÄE£ƒ;…õGçHÞŠÐààP Þï‚sq§¥Ý+ŽSôÿ§Úõ=\öª±|4>Œ¸N2̵±/crŽL>/»ç9û;
ÆÝå9~ìæû¼é»§ÅGòå®BîåMOqü¨A8@ºõFp^í‹cËæfMx¼ÈIðyøŒ-t²ùÞáˆpD‚À$ÄU‰@ßtC;¢&‰ê¨EpŽò žWÁ…WcèÍ
¯
ÈXtE!zì*‚»¡å‡jÈ£¸£ZsCR;	ÓEšFF/n÷QÂq dv/»>ƒ_#jÊ^x°GRùõû„‚8÷˜fÓR7vĸsB^Å"ø-:"Á`ÓŠÎ ê	XÆ“Z›áÅY`=4öEé2k3˜KÌbMë£ð
²;
ÓГØB,8÷`ÞAdýšY@=ÖP”ý®½”Òþ"+åÇh|¦œe`‰ÂrRÚx\3ÁÂ’@NxÆ;šû2ݺ"äe©4ƒÈ­+:âñb\7Å´Àc¤[ŸÙ3Dm¢0|Jãøõƒ´^kÌ@²<¼ÐL“¯|æ¦DoþŒùêjn¬)ìBúiQ=“›n§9Ý×oãŸôTø§GÌÖ½ˆ@¦ÒBl<œZ‚‡ˆ0ó´ÌIxd%ïE›|ô¯\Ð+D¸Š> G@ÿ\£¯p)Ï'ÑiÞ-—a6Ëv‘L!…d‰ô`ý
±(=7d3ˆÏ‘l•êAeD’šX¬Ç3{悟¢‰B4ŠÝ"å‚	—±FQÆVNäG!ä”e#«´¬ÉèGÖ—DÙ¬HT¬ØØByô0„ðÁkÑ9¯HYXÆ”uÂÆàÀûïT6²EâQ9ÚõÏMp´J$âra
Ŭ–mø„™Ò¥j½DD9kØà9ÙNfûp¤mM÷ðiï´3µÃЉ»ùv&€g3Bü&ð™‚?á×üqœŸÒØüêïŸU‰ŒÑÄ=±é°~GÙNqÖó·'yð…ff„­LÔúkÅ™yêi|U9C¶uôê2—åù›<ø¦žåÁweð"žãž£ºÄË2ëU<.ƒçˆK} "ɉºN `Ê£ë/ëÛòѰ$€¹RÞq~úHö¬`:-£çeTMø•?z5Ô?6ùsR{}ìć"RLØ&cI?x•xÇ£è'ÜÏßÔëPÄÐŒŠIÙüQÂjãÕÕd?I÷ìx÷/k•Á#
ðœÖW³ÂaíþVÀ-1úÅÒàm#åcµDÔÐ	ÝOÂï3‹¡ÖÉ;ü´^âzøá‡@Lò°0ó-uà\ѼBÅhÃD1*†©tÎ\ñ)†xWa4oÄ2Ô™KkN* ä‚ ßHM¦Á‰êà¨Ý4|ûCUÏ—yÒ7à¯ó ÒÁ»g’P‚áþ#•ÔÈÙïy
´ÛT™baô|65„Ä
=øC¢wÞ-n5U vÊ üù¾ö`ßã–œÜů¯+µD¹±@ÃÐ"²m²cŸê ùÉžr(Q‡ãã«èOˆ%Ý®XwÌNE1õ|Ï1 ä$.æ šílh‡0
	$Úö–b‹’;ã¨n„<ïÓU—£[ÜîÎŽ0
áœgy¹
Þ/„ˆ‘Àʇ%¡óótJ•+”ú:KQQ6±‡ H‚YüN¤¶™NÓ%ÂFx¢Êjù¡¤$†Ûz9c@! ‚1øû®.gÌÐFÇtíé³d1üvP}? â¸sPF[Š=cýÚ‹@“´˜MI°\&:JªÝ„’+[ʾ+…ÂósU5'ŵuõ€ÅEQ¸ ¥à²Ãl‹ÍÜ–Ýéûß)»s˜£–ãÊ
â¯?igµÄ>>¤5¯Jì.¹§/Pý«Ú}ÈöùC©°ú™X ßž±}¶©H‘t ²yJu+Ëö’ü;uqBy	v˜f¦9N.RÄ[ø"8’öç…R_Õw”‹	žbTX	©sôV4¶Me9ˆ/¦´Î<3êý˜rßê§©@žHàÖ	Z>Á^N%#:0=ê¦PInz|ÁƒÈ‘殲4X6•L^öÝÄU°C]ÊJeéIíò¤Qñ´øió.:DÚ\ù.»/ÔG¼cÝüq&Éic>?Ê+„ñ:«RÐÎ-Œuû²ÄZôñl.ÈÙ¥X!¡éq¹Cqê¥Àó®ë	Rú1=ysÔqɤx<<׊f^î@õl¢"[U¡ªï„ªVv&Ëí¸ ‡ wŒã¶v¹6rãÚ{Ivmccñ¡qÃ1æ“H”7ÔgSsGê•Ð*Êwœ3¿‰¢:ø}¥Ü;n	}jYÔ	ð4T•ߔۺËrù×Yý¶¨#¯&nóÙêÝ磌òì_å°2d‹qi·ì£¸ÁwÜ ±ãÀ-º‹Éc§>/bᤙվÈZm%¬Õ$• '‹ºH’cÖÊóKtõFôÌ/$Ò¾ßU™ìW›‰-™w'ZÁòƒ«2Îm©•¦µ3õèù†Ø&’Á“aÓCòCÙxõè8¨0R TªCd/ê îòÓª-ôvè¯FBu[¡&POE—Ê ©Ç\Æ_pb¼äbµƒˆÌ‚”ˆ3ºz®žj÷½ò‰\¦lª×‹!Œ8îUkÐ.CXž0·T]	KŒ_'ÍÔ³ÞªšÌ’‡Uu¿¹DJó¤„K›ÒûÓMm?ÛÚ‹.cY• •pÉõžläŸq›È®ËSì„}Œä>¦”t„r·äã‘» Ó±«ÝiÄH¡c$bœÝ"ùÆB'ô¹ž6¸Ì€køwi4Š$×ZíMnt%†^dêΘÃ)?ÏcŸ¦¤ÎoY»N×3ƒäÙÐÔK‰ž¼®:ë8O}cG+fÿ‹ÇýŽÕQêXº©]`jµ&
Ÿä0’u™Yyð?'zx!±*éÔNµ*.·µJóصÚ	Sƒ]¨4CáçÅOŒ¬iË[ÏÙu°rôÅi')Û¥¶¦d»œ”Ïœ4V¦?;ÜÎqߢ²ñ¢tÎ%™:*W%(r#â7+Ò½lŨÚÀI7® hWG> ›²ãŸú©ú¾j¨’¾0aÉëô8õ·N•%ç9ñõ.O.)0šG%Š“ë¥À^ê¥óÄ©œOS`Å‚Ü}
lWîëÙÒ%Êvo–®û¡ªÚR~Ü])-m3*¡öaéøB@u‘Û´â(@– ?nRcWäü¡SígÚ£¯©j^à'åGðe‹ŽR5ñ¥úwP”¹³~­Á¶®ÇÖ—Öü–¼ð­„B·¾ þw¶¾\[DêÖ—’C­Äæö]"ÿ¿bswÍ!×®…Þ,]®–.–‡±@‰nw‰ÙrÇÉ­¥kž°*ããk¦ž*ïœ.FºÔ:á½'ïÔ9ô£)gY"|ç9uÿ¬
PuÙ%Ù¬"¾g:ÎT]7sSªæ÷+ÿhæ)`N½º6UêuKNسÙþ­=ì¦>йY_e«¿Ì1IºÌÒÕmÉ	«ŠÿIzÉFÛ†™j»nˆ›ÐÃÜ‘ð…ΙD““Î:±_%YÐÏK/+q»…¼ð>%©èqTUг²dRØsÉîêDò”Ô›
[ß@¨ä)Æ+«üîmsÒc†bæL2Û@éÏœhލ¹w$]UÒ‹®l)!¨ÞHPWÝ@	¥>½%p½ýÓx•Ú¹ÌÁö:Jâƒ,9Ãø/ä7!ëבR2tkïÕ\ï
w¡¢Âñ(Ùd½ªêWãUmDK9n
ÚžgfB¡{AMC:°+¤>*ê NC¤šVOæLô•JmÛË—D’­¤Ö…Ü•ô“ÛÒº²Ð—eÃÙvVñÉ-wÓ—©wgU™Ï”!¯z­ø…ËË¢ªÌ3(çÌB.o))±³!1Í[~½n‘ŸoÜíÁ
—]œ2¤¸RÙYè¿Ñ‹—w2g;«:ýT’þuã(]´õúã²û‹¥éIªGg1B)UììJ­+Â/|úÉ›–3ý’Rí•SÞMGndÅJb.“ÕL¼9ÏÜ\iõãd¥µ˜ c‚ˆ°¼ŽY9b		[ëÂQ×t‹èUY§«/´:ËÅå´òòƒ¹ÜÆÅì¥rõ§6r»+|¥ìüêÖËG–Š©·7!O“úIqÒñňô‡/´­ö©î~&Y	x6Šœäâf‡8ä+ám¼Ei‚¤ƒU
;úmQoX!îz[´°JŸóµ»¥ÞõÐ$¯Ê·1¥Ìõsö†Ôß
¨ëÇ.ˆ³è-[À«Ý<Ûu3Ÿ‡ñX·@Sdäm¿Ø
{¯ðËR±RÙÑüJxºFÍ*?4¾ÖéaÐù¥
bWHàV¹ËÁè?ú(…Š'‹º¶/Òý|¯b¶¢3¶Ö@×öXX‹q¼»º$ÑZÊAI?ìT¯	:“©–kl…¼‡©î;†ûD[ƒ_E¥™JêÅûê‡%Ù•¿ pmÙ-Ž<2#jÔÊðJ[ÚÜžÛÁŠ¼Î‹[ÊvÌ{°B´5bÉêÿ~åi(•QÙ^5¥gù»½ÿZ¨{1endstream
endobj
570 0 obj
4502
endobj
574 0 obj
<>
stream
xœí\éÇuÏçþˆù8#pš]G_bÀ”i‹†%Yô
`Æ.wI.Â=DrEÉ}êõª»z8E%AÜ™êê:ÞûÕ»k~Ø´Û´ðÿ}v}òðé°yñæ¤Ý¼8ùáÄáÃ
ÿyv½ytš:—Zš©Üæôù	½é6ƒß!6­ßœ^Ÿüm;íºm³ó[÷Ã85ÓØo¿LM¿ÛÅíw»}c3MaûÛ]è¶_ìö‘þy¼Û»Ô>Æiû—ݾoÚÖµ#|¾Û>ÝxÜöèû]í><Ùíýöëômù¶÷ߟþ1­Úy»êع¦ÓÂO/Òb]Zd›þ»:ï£MŒ›}h›ÁMuºKãmÏR¯×»}‡®Ó¢¶—i7owô7=ñÝ€½J‹¹I_ãØ´®Û¾ƒU¾ÌûÇÏv¡§Í¼„÷¦ôhLÇ~“7r	ÃÐÓK~š^Ò¸1à«C‹¯Ý¦¯Ò¸÷°Ð´6ï§¥È2Z‡]žÃd’>­šq½GÀdçð6p?°‰WøÑa{ê Ç@Ã"F±™h)	äöSÛt^x‘ÚaêѬÞ¹€9`FXïáCØþ‚N>½Æ´Ž0›úÃ>‡Áo_0mhÔå.?&šF˜.
!„ÈÝ(Œó^øÓ{›¿÷v'$¿Ô6K:ˆ+ÞéÞ…¦ëá¤À†§¸\€mX«hƒ/?ïFܶß>HÝTÆžÀЉŽ@T^N¡Ç”è‘ì?„È[x/à{?"¶(ˆÌ(ŒœÐ¶´¢Ûò6­¡@´0QhBæ:ØÏ,¼í‘Is询 ø½RO7žs¤Õ“Œ¦oýBÛ A5"âUÑ©ÃÈ	{…GPøt¯,Â[n&zËÓ˜1¡Tr€Rm”‘ŸÓIŒaÄaˉø¸ ë@ƒG`âò·ª++"¬1lÝ4Îåèá	àƒ“܆c
<¾¯]¤èé»9ÛYÜìe_1Ìæ¾—ˆá¨:@`	54îaðE+8@‰„áñÝNeÒ^ÄoÚ
5ÞÊÑɧ*KX6Êw¨Á¾ðE¤'¿dVPÅDYp¾	½€ÌJùÄï÷¾ôǾMäX…è@Ù6YCИÜd¡‘†n—î	)ÞPHä±HòñsMr!’x“¥ÔBü…vËÐFþ%Ž„8€ÎTPü¸¸ËªÎÁ!L½zDC ‹ùXŠü‰1ÒäßÒ×ÞáP"0X)ºg’Cšù}K”ÑI8Qm%
Iês)ù‰ Z¼w‰
ka„Rë?ªÀzYìyÅJ/ëŸÈ€(Ô®a ì5AF©×Á×ñ€¨yCÚV­üê‚m¥pD.ØE$>¡†÷SÊ$:N…Ò/¨íVÊäU‹ÝÂW‡à(”Ú˜Ûf¶IñŒ„í_w±Ð,齬gæ,gnr¤¾°Ùâ,¾ aÎòÊÎEuß¶!˜%CÀˆâM(­2D"$~V@0/ˆûøôäÛ“6!4=Z߉}ã&Œ ÇM“¢ó#óžœ<|òÕæíëûË“‡ݸ“‡_Â?þüEúóäw›9yüdóíª¡_šÌbè'h7C7ÁÏŠ÷Õ¤R««ª‚Ëc(’ø’´=	?‹âÁ‹¥0²*q’êhÏèÒ´e1=6>L39
\ø	t¯9g}6‘oEsCË0¨Û’\ŠâØ
Ž)îÛBéû~BFÓ÷rJgþÅà‹ôPw¾ìnq–Ž
³Ò|PÙRÝX©}¢Ú‰Clú»ÅI]’>QÁtÄA£­o0‘ÐÖãÆ7D Öù÷ çFK–S¶½Ì|y."ÙɨìÉ#1Fg:“¤8”{¡E)²ÅW
t¤Å`u‚š.9ÉìKf¥ˆÿ
>1üú c/²€SQ
*Ù£†²R¦þç.ÚYD¹…Põ,´ßR	ƒîJBsbú«{êƒ<ÿ­}I{"$T†³AJn‰‹ë3ÊÔXbž90.q6ðdÞË3€Qðï´ëiòh±›ùði¬ÜCŸË¹	ãcÉp§FìЈÄÕ+n¨ÿi×ÿÐ7òw‹Vuþ‡±´¥
4·G2·¦©|‹ÓPW#ó®´ñ­5¶¤ñ\‘¢é3„fJ¬þ}ó•›Pj¼âõwí„ýs}|W¾‡Û{À“mò'}òM^ä×Úø‡Üøþžqñ¾ÖÆÛÜó6¾Ê—Úx“qu#’÷—\]Ú1òZéu“4¾Ë)†XWµå´>—8‡ù’Lãà›h=yîxQL/ï<È„}–;¼, %}_#q­Ÿ+œ}„¾?çÖ»‚#òño¹ï÷w¬Œ
éÀ÷q¦¤·z¸^ȪFÂe>IÏ,RÅÊþÃNÀׂïˆã,ÎÖóî2¯‹­qã÷–Ïq¢ØN^VIæŒCåå:îk0©JƒO°ÃÀŸjSÞ,€¯-F-¯e)¿!äÆ`ÂÌWÕQå<Œ“Åà›*Ϫ ½¯žƒ¿ïfÈÈOZÆiPû*óTçµÆ›bO…ÐÓôS	|zQ{ˆØį´ñb}ÎcŽÚBô,E,àÔyMÄ.”À\¨â³Ò¨ÈB+S³`-¤ Cù:3ü(¡ZîŒï‹ã®…JÏ éâ+eFz™0T‰%
nk½È=ï´ñY
´%*’KuWHsß¡+áJ9)btÌ.½3õŸT^>|êciEcãü̈îv¡–^tÉ©yÄKþŠZ›¢,AáCy”eú&´¦TW¼žÈÙŸ<ˆeæ!÷^<(I´eܾOb¹“°9ïÀ©»Läd­öqé.ÚœÑÒ)ãíiÈ]½lŽÑfr€ZܨAÃíwúZI†ç×hÜʱðæstÜøô•ÉàxÌøA‡a õbòBÙi|¶zPÝÄmL"OOs…ÃÔÄq&Ô0°ýœ¾LÑ
%߈o
n©÷ºp³dP½Äwc(’KGÿ3S2ESÔ,ƺ#º«KGEöQóŽú™F±y!ñµ•ûŠ€Î¸õ%”)£Ò‰Q„Leö”6NAv$*P#š$µ@Ì™¤Ã(†¾–³AÒW3‰eê«e^0ÅÉý†x[‹xÒµáÐ4ÇÛš>;úhî‡sÞqBŸÚŠ„
œ

×ptM:×ÓºIˆôâԶ鯲HZ•8‹tM’eµˆ‰óK
·ÔñÄé+,f¿$Pm¯f6ÈH	"û\{<">>=¡íô¬È(äµ
{]*"îªÎYˆ¥¬RõV5Dmq	iÁÀ!ÊÑ}@$:P¥Ã’ç˜*s¾äÓ][d–t$éÕRÞ%[|YóTÃ{¡sÆœÊu`ÌÿJäó3it¦æ†V`N
¬O
ÌYô4iöÉçj%a¤=èkµ ¬Í§ g¶‰ÿÕØrzK5Hȸ‚Ó0°	¶‚&îËå,´›RG‰$f§
\(gEäìQf"t]X
$κm2¤5бž‘ÔœèÈ­ØzÍç ¦7¬Ûpè ÀH»)à¿4×rx›` Hd¢ÅÒ/²»7Kñùˆ(üü|Ý&§){1@$Y£òÒ\¹`N8›h¸c¼Ñ¼§Š´w;?–Êý¢4z;a«q»Lm#ß”´FÐXrÄ­ý9-‹£dô¢f@˜pš‰û–_éõBÝñëÖ€&šÀ °%וŽÛ/„adÁ?cöh†Ô¿7”ò¶äéŒKXzë[U1 $°ìViº&g&Jj®	šqDY÷†Ÿæ~I6öàg$Üðdá\q€;)Åæ†Â×±LQ¸Pñ–jØJ×!¶Ès±ÕóhWðóçÜŠ6Ôp"™kѾÖJ¦ßîà¡ékËXõ•Ö“Zc‡ÑÐa¬Ñ{)'„Э9´¤‹[ y[¬°´¤!<‚µ{«p
9I¯©(V*§æm’Ì-êñ`Nþ–uCs¸!÷`qžbÏ6ÖÂ|V}VKlZ?3pYÉ”¾ÖZJÎuÍÒMYu~p4ÃU—ò€úýSÛr4öJÃZ ÀN¸=ˆÍy€7ÖY&þ'±ï‹zžïÆÝîj;ûiÏÇʆÃ3Uãl?Õ¦¯†o¹-2efb¹úËM²ð7²úñ3’› D>Çäþ7¥(þ[‡‚aš+;&<\ÝðqGİW?ýÿ±ùŽÍ/ïþ ÃU	=ÏâÙzº–¹À_?Xh£þ™TÕõGE³±Ø–4µç,à
aaű-lZX~‰ó	å¡,¦\º
ΛµdíˆE©Ž-þîpËqlg^¾š×|¶]ÅS‡‘qg_ªùÄ•L°Tž˜ ¯G
–Îj|1ìе$C
ŸRZ½©/'¢R®Y%“Æ\%È6T~¬™~˜9ÿ`©Oíjôr âñ/òÚ¾ÄÒ×λ´`i?MpÑŠ«°ÄäUŒ6L„f<þS¥‡ÆÙ‘mÕ+Ž%@µ(
ÚEŠ›Ýðb&Ž,èS¹X%¾@è*±B.íÎNª†…r—	$5¹ 3úIÃe@¬§ê«ºãÆËy
˜ðG°·Ù̓ѡº.©&ï‹È&ìÖêN©¾¾³òÀÜÙØöñ>©ô#pÄDzûãœ2ÞciRK¤Dû‚F„”5|¹ä.ºƒ(	gzçä”8 —Ü,‹áFdå×]û.¸fL1–ôéÊ–}×'#!M“EªZ–jÙ;»·¾Ò!9Ýý¯°ÒÑ7Iר•¾Ô,c†Ü¹…)Ȫɡ66r·MÓ#}:‘ð®aœx€¥l†ëHe„7ïb½¸rqm‹Õ«^ÙÒîìps¾àÀ²
øÈ[œSZõ†a#W»2ZcÇZä
ñ°%Ù5³%³ì¹e¯´¼½
3̯X`:pÌÉsZ·}Ò…õ=äs8Y…dˆ¾©åS4
u°4·®È¡æC-"Ä=?&ªšÌæ ÌëæâîK-•y-°pŒ³CÎfáe06òí‚ûüæ™àKg¡‹
T.Ô¡Ô|H©_`u­&pÚ¸Áj¾Àc¿\ØHÙF¹Fp(*Ë×±6fIœtC=ÂÔwe„‰_ÃV磟µºÌÙŽY…þÞ‹Î׿!\wä‚ZÍ’LëG
q|”L¬5Ežq˜¬ËUK/³ê®]ý,cÃM‘×ë×L˜%Þ/A
mùU»«l )R€Œ –gׯÞVàZ·(Ī\ùç
÷Ϋ†f‘B¸gmG×D^CÆ·Cõè®Jkqªg›õÖã»nÅ+t¡ažŸ(ÓBJPÔaÃâ¦`‘µ`ì–Ë«~÷`ì¬1$ÁûÉ/=ˆÒm°õ•I˜=yƒýG\ÀZ¹[@ü,á<›Æ‘~Ë_±"4‰±÷EZreœ‰=\ØáÖ‚‘¿ÐÕ€L‹çv)L‰¯H-gîSŸ×¾Ú3G‹.ça‰ÛÂ*Y–û=¯ªi%—*cø}¡šÏkëÏCŸÕËÀ7‚“žc`˰Dl²¯(´Ž
M<1mz *5­çB³+T“<$ÐÉSɱrõÉVDOQÙ6â2¦úÕ\\…Ï’•¯3žÈ,EL&j€µËèeC!TB®ôS³ÁWD"›>*Á(1¶¢ú¬F‡âÇ9*…pªÍ€ÿZµ¼E´alÍ7áÙD+gU/RÙËL-ÎîÆ›ËTòÛ(Y`Ýà²À¡ö#Ç·„Jž‡¬lªV’Úʪ†Ý¥DdkE½y†WKÛ~é]‡Öá´5[~£ð²+XÒñMåâGFw6•l\QÔÃÙIcâeÅ}ÅW².Öröh3/3y‹p†mù£,+?ÊPx}ób:¬¥sROfò…Ýwâ)5Ê¡T.ƒJ•­ú†ýû]ø–¡RépV˜¡TØk®Ðîû\©%¿…1·h·Ç—§¬×;ÂfQÁ¿çbz¾”}?ä.,ªkkû•¿ed‡ Õ™¤´.À-­28ÀàŠt0+ùkƬy)­ÿ•Ž¿f•V˜þm{]„D#„ÍFª „lý#E埠ôå°Û©¦]•x‘}Dò‘¹~‹ÇO‘'€¡…RÉ/®ç¾¿"/ÿ
‹×ðÒ·'ÿ¥›Iäendstream
endobj
575 0 obj
4719
endobj
579 0 obj
<>
stream
xœí[Ys·Î3ãÊoØÇ•v4¸N•e)¶âK–鲓8•’H‰dIQ­öŸíñHµ
zŒí½Ú?Ýû×Zun=ÀÛ¹ïÿFÕŒ2ªWîBç»]Ú©>ÆÑÆõG^?ì6z½í÷»M~ð¨Û8avO´ŽðpýM·ñŽŽ‡ü­ÓØgô<˜¸ 	Äè¯`Œ6ý wú²£Ž@%zà‡è>Âîà=PT
:81<üRÖcGc4Ð1ÐÝ u3"ñüü[àeœVÄFj,3Ò4Àšƒq!hÞioäNo”Š}ð+XbTŒ¼ã'0íú?ÞÀh…{hÖÏð÷Ij4ë׸˜P­ÿƒ?_áÇSüxŒ‡øñŸÒöSécmáû¸¾´õÀtá#ïêQéû´66rãYnÄ•ihÅl`+GEÕü°NÔëLçuûàEâÕ
‘Äv«<¾hÇÑBo§Ž jŸ—'_Uξ,ŸÔÆ÷÷Ì;s^ž<“¬çƧKûBÜ ±¿,w°âºåë'µ×»%&ž.±{×à‡]¿-ÏÏëóþjAËI;h‹oÕO:”5ž	=fûpYµÛ%XÉ__Õ¾?t¥inŒs½fõqq¼ñAø±œ†Úåis¸óOé©=íž8„y‚™ø/þ8‹ßþXÜy¤mã0Œ÷=úÕûqP<ÕØî;qþàxPåCä)ÑSž€sBEÐgw°\‡,{\<ÈúMg¨ÛöÇMó‘ú’îa_tÐYxh‰ˆ5ùgS=sr‰Kþ9Œ¤Ñ0QÙo3L7ÑÌÝqšÇ0'Š9‚ÓV¾;ÎŽ|x±/®ƒ	áö
Ñ<ët@Ùy:9#Ò™Oq˜¼bQ[ŸwFSÛ;ó zkó®þØéÈ$Ë®—Ÿ6†Ä›‚[Žy›µ¦'š&ç0[Úº*±3ñ8	d™lÙRrÑåŠ$F§t–5ô>(sÕŽ—uÖ,îC¦ZÇñak«qù¨Á“¢ Ù¸HäÓáœØÝ4"°„†¹ÊwÐ4ʆ¤‹Jû„[éÑ™?`$Bý¾üj÷
’éœ'uò„”|\ßí¬ì)t÷am%µþ(âC(ÆFmÑÏ«Ãc
\ÂÖ4šJïÆ…EeÍŠŽ!¥~Ilp
HOg5ÇTûŪö¢ã'?‰W=Ãí%;ï·ªIѦ©4ŠÙIý«´ˆEÁMš›Ý¼ñgø×+¤ÿçtüHäzD3a«:¥ÑÑ’ù(ç•vù DŸ î .’ÕQÏôRGŽjps¯«ÐžæÀó/äU„D³4g¨>«æƒ8Ȳՙ[`ZÝ0±À•4ÀÄë ÊÈɪ\&
ËâŒÕ%_’šà:t1X/pZSŒy6¾¤±x°Ad“3SåÊìóa\¡8ŽÛ¢`,õ«-Ú…+Vv2~«½Â5=cK„Þ†ðYЄ8‚%J;Xâ!/Ñz\fµ(ÍÉ2íldŒ·äEФf¤Šê‡[ïèïm<ã†ßÍZz!?²`.’K'Ñ^÷[fýX†B€Õ}BOìØæSVCc,.<Î
gˆ»"Ü`¥Q»ôË-ŸŒôY²ô l¥“P$”Û’
áTsnÙrñšZã•3nELžì¸Ú²r¦ñt @I´8$¸ÇY‚('ì€úcÚ$dÜTåHóβ¥ +‹Š¦r	êÔC$‡têÒ2® ¥|x1Ö@ƒÍÄe¸ˆ	Ñíb¬œDiÍJl™mn´`•–ür‚d¶02+èu‡dÏxs×T¶ß"U©²n‚Õt²Üɲ—Åçmm4Úå¥z-Tm/±µI$L¦o¤_dÏǰü<Á—ôˆ†ôÝ–“ëGp퓘á¡õëK¿)54Î6]¶1웇ãØÐ
Èn|o¤ýª4.ÅmÏšøè÷НÿÊɳ“Òá¬ò*6ôÖR¸Y©>^j¼¬Uh}•³HKã¶{µãýÒø°6>*÷kãÇ¥ñ£òm‰ N¦¿¤4î<WpZõš#RøN"°ƒÐ¯.Å«ÈõN)×Ö àÄx:ÄHh8¿¸Ó ¢ƒGÓ®ûàUÄŽÌÀÏ¢¾Ãø`ÉcøfàTщLmüT<ÊDG±jBÀ›}ÐC”˜‡IZͺÇß[ñ¥>âñ1ëÏ`=0š¬U~cèÇÑhŽóëà\àlâÊÝHP0»SØ€h2˜R†­UNt¼¬“£~”+;[âí5Nn´òÆ©€•qޤ̆VûŸïíßBi@g5ÖD$L›@°fÞ¬ƒ[+’À¥›¶Á¿1à¦ÁbÆ`цˆnÀ]Ó½N‹‡´g¶çÔ»Aèí±Ÿ×žp­£tR™œ A;¶Áì!MãKy:Ðt'•MI-€éIíazæ¶éq™Y]&Æ‚³MK)&R°íàK–21àÉÙàð«r0Xt¨áJ	tަₒŸº\´öŸ}ò–%Cƒõ‘”K©(S¹\¹Ñ`‡¼o”&—þEñ”XÜ@.Ñ>J²bóYSÉ­ÿèdx=p”uZÇyE9ðØ^‘nQ”»NT±•ÅÇlXNÁ…·1‡M
~É[Ø&Z°ø¥KOÀ”Zz' m°ž-ãˆËS«Þ2´6û2êyË¡¡“в²Èaï„įÒ›Lžq¾„3‡)+â3©ð.£ŽÄ¥$&	²ÝB”œÝðCJMó9)Djf?mÑÀ´Ët¬Ð3‚¨i6zç*†+I&	'Ñ03?‡–‡9»ÑI‹ºÁ<üÈ›‰³û@[R)朸Î뉛ŒÞ¦°G\Ñݤå¶Èrk´zX3+¬àñ
UŽ2(™]‚áI³¨a¸k£
2ÊS'Õ(Ê#d™B®޶@ª$†ÃÛ,‹‹2¢¸Èe…Çli9q¢³‰+E¶E¶4!E¢×ñRÀz–D;¨ÆÆÌ£ãëÃ]äGCg§fP΋Y‚Èb«c“‡á<¸ÐëdwheWF¶'2þ!oZ`ø=r,ûFü%¥¼»OZÆ’‘èE“4›Y9iàrrH…Lj"Aãkeã=)œ¿MòÍ”Çr¯9÷cLNINfÕ.'2©“É:@ 1«Îω¬Ù^Ã=/÷D˜
²Mi¡b9àí4þ̇†ãmçÐ…šËYïi­êĶ ÒðÃE
"o^œ½:‚¬ßëBåç4‚Ê´ &qia8ß4p´&[È_?p|_Äx*0ÚBH,Š†Ï—ß5ó·\Þ„Óù{„­2rœ3sèXµJ_GçIIì訲¥Ÿåù«ï£!§]OÒÓ4#à¶r
Wq®bwXc>ÄÌ’ÊmÃ&7Q“¹ä;Ïp£x2P%—Œ¬ŠëyNî(	€‰Kš,¿Ê»+Ðý—¢4Â5ÞŠ™3yWÌVÚšÑ.VDI#ˆ}=1G‡<Á¶Z©(TÃUMðš,ú6É7 ¦G5q{URê®&ã6E6¼ /Mô5‡-%	#·ÁÐ=9gGQpeÎLu,ËØ!’,ïǸŒo–Â4ù̪èóõiIcNvzHX¹|¯ÊÉ•:Á›¨¦«âM³`¶»TÓ…§èb’å‚nÓä–\ðìØ·²C»“5Nœ·|ëë#îB+î¼”f‡…¤Ë¦‘4HáW_Î.$
aÎÛ0¾Hw’ÕÏ~Ë@ªù’CF›Öæ(e4'ò•Õ-5ÈX'ÙÌHóúêQ™´˜ÌGÎä v$žX•£Âm*1¶žŠŠdµ†ºo3²½Ó"ß3÷¦2ˆßŽnMoüÿnv·:1;òF^…këÜã¥ûˆ¯·âÚj þ"Ï—0ú»%¹xáòdaý‚½ÛéÚ¢²¿ Kõš¡»§³9éð¾wN±NÑ!_|Ö
j
€Š2ð8ØõwÝ8æì¿ÕJfäSž~Œé¾ÛЋV4Þǵø@w«0Å=cóø/±ò3Â̺VÄDbúº±„ÏP˜QÐ|G4Gímrn‹
¤yX*TOpjŒKÁÐîE„ﺨë5§œñ
ºõ–IrMó;MFH›í/]dã:ÁÌ?“ \ºŠr’t—ÞimcÊ%¸6™q†MáRŽm#ÿ¼Ú\A7¾}ü!@õÝç‹/wd''ò¶âª¯ó·æ‹iôNb|ACåÉ¢¥‚Øòx›^ÑãU;^âœf’x³ºàÚKQzðC=ñ^®3Â#vx±H¤°ùzÈ`Ëvõ•Y~Q§×“Å«¿XÎîùuaD’é
âü4#®4i«Ÿ€™&0J—iäèæ[ÒûÈßwõ•jq~%(²3޶¡Þ°ÈÔŽCS=°¡EžWTG­Ïñ,G`v!a—¦¨_(2ß—i²¸ï,'òå¡d‚õÌ"œ$ðšTîd^fƒ–˜aß®ŸÒÌA^šÕåžAÛÅ"~½÷_p„–endstream
endobj
580 0 obj
4194
endobj
584 0 obj
<>
stream
xœíioÉ1Ÿ­ýï[Þ Þ0}ÌL¢DÚ{Ù,ìåˆ%`Lbcì5ì¯O]Ý]=‡ýÌ©HaûõY]wuU¿ç«¦6«ÿÉï½ã;?õ«'/všÕ“ç;†:WòkïxõÙ.pZê¡Ìj÷ñÏ4«Þ®zçëÆ®vwþ±ªv]Wvíè÷¦C=„nýsµéÖ?T»þ|^müú.þõ)Œý®Ú˜z‚¸íïÕ¦åq_TgÚº1íú›JæâŒ/*ر1¾ã¦Ÿ`˜‡%‚_ÿW¦Æ¿Á¸•ëa`ß­¿ÇvghMl5øÙáÆ.p÷_ªÆn‚ï>o;ð° µÿÜýPb¬F‰oMÝÀÊî>`ÂøßV-ÞxëkïW×Ô½t‰áyŸÂFç•£ÿ•_Ÿ@uu=†¦YŸðŸh=ƒõ/µ'•í`,.±ñ#œã´øq žà8œ€C©MG=G¤Ð"¡ó'xYÊ!’
L"àa×õo0'ȸØmèl"˜OàãPfH[WBånt¡-¡2Žèø[…v
ìÖ™ˆÿƒÄ#,oî3üha¶¥'‘®jZ:š!ò}ß¦Ó ilCãòä—È30º€-2OèT/¬§úž@`@D
ñÖ&žf@·Šj—ÙØY`V‘Ó¢±‡«¯P;ÁE¤AæÂ]~Űñ>¼ªB²@ãÐ~ˆ˜lØv´ú„W™ø¨øA…’H8=t‡Þ·´I×½8îÓÊíÍúëØ‡ós"3¯)`uxÊ(—D¤#a$(q‰Q€™]ù$‰4‚„ëu@´{‰h¤´@C!nZË`y&þ”+ðlAôÏ_$$—VT÷µîb23,DåvÒiä{Â6þq´¤ƒGõ@=/P°ð¥ÑHõ&é'•’üÄû™ÿ€ðñD5"É9ÎgÁ~tUKš…ü±ÂXBøu2“gÔtq_70pu|Üy°$äŸ`[‘éŒ(ûrwçÇç+çêŽL`8¬\jÕ†U×w]íZ´Ïîîܹ{ou~vq°sçÁÊìÜù|öÃçðëî«ßí|ywõ㢵+U{´v˜™·©M`‹·©äsdT,ÀX„÷pu	/RUQ!F&A¾ІÚÈ*m7(µO³*{‘Deñ„ÞÃû8¡o]íÚaL­û3O2}&
yùÁZ´éïü¡­ûÑ!2œŽX:‘,²+d~ “ÉC3‰Ôù÷µÿB’ÝÚ‘‰Iúü«—&Ûm²Ø=Û“®Ïæ‚æ8–Tˆò.ÃÆ!o’Aé¡4VÙ‚åÁ}z3Ò$´¹!‹“¤2;8_kAÛ!+{'ç좒µƒ!Ýøßh1_áZ—•Ô?#‹‚;"Å¢Ðû	…5úe³
¦s0ùX§´pfÐ=kA?‹gdƒ'ïuå@ Ö

ï’Åضë@ž$V¸ÌØP§bo/¢mÓú÷Û&Uð_íí>žPYƒ£ðÛ±ÝßBZ8v	$à!Æ7`0щƒˆes¤È©î™ýE<Ù»ŽØ7x†Ûkd£¦v*oÎòÔE!µÓE­á<ì?‘hèäІÎü8¹É…QæK{ŸèK
àË~•hp7{ˆJô~f/¼žÎÏ„[»î„Míy2!üåè°sš
˜ðèAwø¨k7¡;´iÍ@hÄszDäñùÿ…/ñÇY9iÀ½OÓ`âD
’ÅÁIÊz„rXßý\“öã93^OSãá\ã‹ÔHêþƶ4$¿¬qÏò4i¶î8’3´©ÞJݧå<:öm”O{’T˜|”úŸýÒxªÙ(6¾ÌG{í¯Ýé$õ?Ìý/ç¶ÏäT9R<žFæ5Œ-D˜8òÖ ç ?˜!ïHJþ¡¼™ã…wÍð“ðø/3Dvιۻ žÿ¼(ÎÇþR\´q`ˆ0²}mÒ
ÉûbÈîQK"c›7Eêô×Gz"ô]jü>¼Ÿ¿Îׄ5o&h#æ.$Í•’ÆÒãÔEá"7–©7–4ˆfÞ¹ =)™îô]Ù¢³E[ä]ô¬>¼ eÔ)NÎ×&§sâàµéÍE6šˆwoõbiö"Û–voÆD=L┤iÁ”õY\¨?Ò»¨"P;8Ò¨úiê
b=üŽ4Ê`F›ˆE¢Ÿ{ëš*ËÙ^Pi¼(0'ç¯Eïƒ9~9Ÿc×¼Óþ¢ó¶ôº
߆$"›vˆ<2§ƒÿàúð8gÅ‚ÿOŽÇG}9çâÄþRDi(UÇìØ$
)ÿ‘ýY›¿¹bµµ]p|Ô«õê[׫ö¤wÉÏœ*ЬU• Îáþ¥¦ò‡W {sšÿ¡ÎKzÊlÏ^Š-23eæ?)¸Ï›ÿ_5m±>"·]tM#Ó7éîcõT¨
}Ó›i¶)ŸÏqÃùYñ .ËB~ç'ë‹Ë\$YmCÜ .PR™s¬FÕu?ìTsí–_P‘ƒêE¾3Xg5Lë9(¡0˜ÙzŽûiU¤N®Á±$¼”"x>#éÅv×–ØÆ-š@8o˜­‹ò8Þ•uc®q9}Â>Ðñк˜¹*F}ùΔW!\0!àL^— á&ÜPÔ¨˜¦<€ì¡k¿\õ_y©‹ýq
§YûºOŽë§O;šQKšœSåMGÚü
Ýl’猙çJÈáœÙ¶¾M¸vBJªˆµ]™+ÖÞF,­ Š/½÷á4ÕË\ÄG.Ýè[\e¢3}1eë÷B·e‘7T	îÎ_&yÄŽ½ÊI%ßa²'JE•aàzL\ôD¤ÔgT§%éº6j*¬Wl˜Ýã°úÕ¦!ÕÓ*Ø7\:JyÅ‘ºBæKDqpš_‰ÁèHWI\çW.I{^Qú„d8>rgÁ\¤8.BÙ«8›£2$—­<ôd–>.L%ÕB$£ê¾^Þ‚Ÿø„¥Rš±ž
Ã,£÷çÈ9þŽDHü%•„"Š·3F3°Û*9&ŠÆ-O„gÈÁ³©¼-R–†F>ü#\ÙHEªl=ÖnÅdŠT1ëw>­Ê£KÕBĘÿÜà”(°i2µK–þˆdÇ4Ó¸‰Ù›<Ÿ9ò¥º¬ý)M£nᘭmkùS ½oué… ?3lLo?)ÀLIu*³¼d¥v®Ì@’ó]$ÍÄÍYViŽY“…æ…[¢c"²ˆd+¶UÊ_‘É¢;+üZµD²è0ˆ‘Ú¥Hò¥>8r‹)|ðFÝ;ŠhsGRœ8
k[Båk¥O²÷û¨ˆÙ‹h¶}é“·xp8h䛯‘—©ñ¨ˆÆfÛ|¼í°èDãa]^sx]¤"(ÅO³ª:hº¡Kª*
Ü/¶sngĪX®¼{ˆcÏfƒâ[°q¬öUÁ´£PY`(î—À‡ëƹ›£ë’H¦ø<03f‰ÚÓì!¬›hÞqÌ|Åqþ>åÖœ@=ž#©¢óñˆ¤¯u“3»ól8={Õ²ýΓº“¥±é΋3gÞ›\Òƒ_ªF™¦ËßSŽ|ñ»àÈÏÕ[î-GûF<°è·J˜\¬WƒÏGû×–à:ç
¢}—_¸,Dûv®p9Ò7APFúÆSã\´Ïî”Ç2IAe
jc°¯.>t°ïÒM]²š7õ¿J›{Êqu¼5ÊÆOcþЉ¹`¼ïf½ââ½È4æwXš,nÄ
ã~tP;{ "öÇzíÁ®¯ŽýAQø¤"©jZ9Á~OeßX¦yö{®ð>Mݯ.³V·:œ½9ˆón# Ønµ»­€V‘µó#[Ž[š¶ô¬kHïppO”ëÅEЊ…Ë6׫þ¦¢jqÍå}áÜ´ÒeNL8VAøë@®“ø!ó?¿SúLî%øÝ€ë›Pª°ÓøžËQüaäžÄ(ñM^cEsØ™âŽpòn-Æ"0Þ„QâµÊF”À‡€Ôšñ«*rCÔ0¨Tºa(_“YЇŽâÉ
†o›J»9ñ(Ó ýY¼Ô‘wGÂR~|0”D$å…H70Ð~~våô}qa‘¤í‡Œy…y3‹¯ÚT‘µsühuCãZö'ƒ29ðŽ*ìºÊñíx•-fqŒŽÔç^L‚`†¹+¸8k
ÅË®uÄŽû…^Ék¡›å{ý&¯D¶y±Pš^„è|À2FUûý‰ð‰yÂ7,ž}Ðd¿¥+YqÇ]_qîzs}Ìÿv¾X!Få£e¸9­¥¯¦G—¹Y_ü[kyœ×?&)3
	ðbêCkÆÈ8¹¾ú’	W0ñì†àõ.úáä$âéÒ›1e äZ>]eîø¦ˆ¢HAtBoG÷ÿø6 Ûù]¸þžtFLOø›s`2¿â—7`(ä[¾ú˜úÉ„‰ŽÐ¼¤5#Ö›6b]¼9sé'ËÎèÔ“ò,	ò2ŽåÜǼœ;D\©x¢Eh}Böø%Jcˆ«J¦ŽÓcìÖGzÇã(çu&®¶}ªTˆN“³…Ó¤*u|?‹-yÊÉ—l×ÿÑ—ƒÝˆ]¹«V›ãÜ›(Û×5ù4íó”ÿj²U›æ×®”ðk„šn!P¢Pæ{…Þ8É^ù¿P coì–¥\W3	¿.'n0cC½ª‡Q³wsdë8¤6ÀjvÙ“omy6μ3›
1ŠD™´M’—.¤/f9ÍaRéNÌÏ09Ò
ì¦gßhd;'ŽtlI€”‹ØåJZïá:R¥ïIº¤dMk06P|ÂiŒQ&u¯Ò‹`‰Y‚/bQa‹^´HmëÇRë9°b:ܪ¦+â')³>­â)¢8帎¸MqšåoP>
stream
xœí[YsÇÎ3*?X–±œkwg_\Y²MG²-š.¥§\	R¬€‡H"”þ}ú˜;0A¤E¥¸˜³§û›¯{=ïÇ¢–cÿÜ߃ÓÑön7>¾‰ññèýHRåØý98?ÛƒRAIÝ‹^Ž÷ŽFÜSŽ;5î´©…ïŽþ1‘U3ð¿­šîý½´ÌziYË:îBãoª©™|_ɺï­é'©Ôäçjª&{Xþ¢šúŠÝjª¡£ݤ‡±k¨Qª‡ÊÉ/Õ´å>IsvqÄ—ø°kÿ^Ml­&ÏaX¡ëÞ6ÜåÛJaÛrg’‚&Hzÿ}”®…l¸Ñ5„Qúä¡qw±¹ª…¥„ÆBƒ$šgoÒ´ØPkãhh®qtmqp_ÿ+È"D£$‰á
Ì4
ˆÖ@¿®S¬éÜ>S‰KScXbÝɾgÿ»Òj2«Ìäþ_Wzrú¼D\Á4Ðä òw¸nlxå´›–O`%œÂ:`©²hžvrˆõ' â*Ä–“ÕǵRYª9Ã&Ç8.QN.ð;É€Â{ö+݈ž„žWü•FMP¾«hH[x6’F¢y’já-–Í+–óGI2ŒÄ.Š$˜ó´~Œó¨E…jW½©ûh” g`çë(·ng/\½î%)0¶AÕ"lX8‰F7©õ¿­4ÔË®Kq²›(÷®	*¤™ü‹1e5êÈ5ý`ySÁî5˜hþÃLS·¬)¬µiqo3xÚ-&hfáQRW„­ÎAØÔV÷P¶ÆèAs†×0­d£¸æ?®‚U~ǯ7øq™7™áÕ¾
¯ýWoJpÕ¸6êk:X"(z&uP¶‡'oˆ‹Pø.Æ)ÎB!žq{åªúm‚sæKâÞWyÅÜ-¤!\7“­P}‘÷£µå¾5?E!…ßÅÂÛ[šÞ¤ÏÒÙ|ËóPx£u‘N
*J-|]Rvì4‹…óPx¸zNà°‚öÓ5°V
i•·2ÉðÑhë±ôc†ÿ8£ÍŽŒmü^ÿ*ƒ¼­[Ã0h<Ð÷%HÕdç­å”ƒ<ÐOŽuòÁâiÄnå]á"F3Ÿ”Z.My‹†³'fünËáìû±ð4ížÊÑ‘{Þ$Ø9‰e2¤{@äÚŠ:*¡ àt€i¿öH·©^[Áö©‰®ŠˆÜ”âãbÐ
ÛþVePÜÞU&#aÝÀÈÁ’©Š7•.…
@Ø=²˜[†2DðÈøÈ£ä‚š,À2¤Õà’ßc§{3)Øé‡JD”#虼Sj›Ì)ñ¶7h¾6Ù%!\8å8ª‡Ød
XÍ[
3ŸÃŒ¿¢±PuØ
Ç‹8çhGjÈ_zÉ´6>PòHnÒРI\«¦¤´7PñŽ!„0JŽ.úÌiXD…¹§@ø8Šã…cß­M™=<6REMq0ºÏÑ‘Ö
-ƒÂÊW!ÁPä…Á¾ep2ÍØ=Ío‡+þ€6DX¸ ‘J‚º`Lu"ÃjE¯q~¼7ÒKÓ+c¼¸\ª¦OCý¿«úwŸcOæþ¥Qeäu­ˆ_°~³¨–µºÏܸÕÇ^²óØÀ0lÑî
ñ×BAlŽ7Î**k´µ´Iøˆè™ccŒÓŽ&9¬ÆñÙæ¾Œ#HÐk·–È* „×È¢]C¾­5$ÓÛ86®‰Z6Ù"Âì"@ì"¢”'Œs7ï¡oÆá5åžðˆßÜöiHƒlW^Bá´QäL°v0†¾fd£³AÙX™p
•Ÿù°ô;à ÊÕ÷r‰a8‡հJ1â™'`ÛáB{…PI0³Fmü®»G}ÂæýÿzD'|<Œ-cy›\~9n>.E1˜¾Ì¼T7˜<~Ü|[•¸àÈ$ñh)A’ZÀ½}_3n›t+]æŽÕ9Oá[ˆÝÖŸómiÎëlΤ>щ@\<¾*ê!¢Ö4!jÚ*¶Ü#~(Ny•éÙµeΡµKniΜãwÉñRô}öA4ïÌošص¥qïyDcù$r+Z#£™—ºÆ€¹8óñFf^-·Å÷³ÒH‡K;$@ôa2Èìì`´™x™âc
Bâã'eWÇgóõÏ(ÖæÚSáéSž[|áßσ3Çwq:0§p|÷vkV øë‘2[W¯C•ƒ£‰ÿW’.0㬈€ÃSÉ|ìÑ%ï¬O¬1Õð2F,½y‚ÞÏ9kåù1¾eô÷ãælôUqðð°ŽŠDãÙν2uĽðšpŸMzÛÑssV3Áí}fOp}Yê~SDxΆMݵB.ÿzRÄk~œ†;ãØôû°³àü¸{HŽE¶é3Ø­’8ñW–ƒæE°mîw€£lÒþñ4%È!+&Bç¢øN¹|ƒ²0å3è“bÛå#Xª;ý1óN7JôƧ¡	L%ñGÄ{ÅTqèýRaî\!ú·â/Í­’Ãu%ô§ò:EãÜ{u÷’’gX+j‚S“'õÇ0›ó)w’Ñ?æMýž
Rú•”-DW—±ÃÝ86ê3sC÷qêOà`Ö[ñQiÎUî%ýö6¯2<yT÷RzÛûüÜËæ=ËÛµ<˃Þ3þÛòT>ÉyÏ#EþCÀ%Ó¯Ø„Ž¢]“—'ÂÞ͇”½yÜ=%Zñc°¬ß”›ÉBYƒ‡”¿1ú½SÌ}3ŒÖÈY¢ð%柭²nع/G{[·þ¼AÖ;ðm‚"—éüŒgEXðè!ü£œ¸¯G´áK¤ûåà}Œ,ŇS¶ëÖ ì¥`Èq¶ßªk6÷6Éz_ÉÞSÎ,ûBÞŸ#yÿO3öö®cR|¯“˜b@j"pÝÔª=æ¢KA9|u%j«»ÕÃbÕ5X,¥2µê'o*kH2
­ZáyCÝÛSV¼îD­*Eá´À yVI¥3˜E(êÎÂÚåZ"ƒ0·› QìZ[w¢ÁGSKÓ·*k¼¨TÝvòp„Ä:£j-7¿5¨>
stream
xœí\ësÅÏg•ÿˆûÆ]Ê·Þyìììªv‚I0`DQ»[²…b=lË2(}¦»§{zv÷Îg"…u7;;î_?¦»ç^-ÚÆ,Zø/ÿ=8Ý»ó°_]쵋£½W{.òŸƒÓÅGû©ƒ3©¥ÚÁ,öŸïÑ›fÑÛEï|ÓÚÅþéÞwËaÕ-›•]:ü»îãÐ1,¿Z­Ãò‹ÕÚ.ïÁ?¯Ö~y>ý%õýÇjmšaˆ~ ¶®Öõ»»Z;Ó5­é–Ÿ¬ò»ðÆÝUš±5>PÓÃÔͧ!¢_þFÆÆoS¿oV®Oû°üÚS?ƒcB«ï&v‘½âeìËúдüö‘´öñþ§‰$Æj’øÎ4!&ªì&J˜D6ý߯:êl½î¼Î½×®mz3ü’›9Ñ`‰ÄyèoVƒ]¾*§å½Y¹å³´)ÛÁ^––éû“4ñK yúÇ
é±_žÁ×CZ¿iãòÑŠˆï<@ÒžºAÿ`H‹_¬œÅ¶+ à+;QÏÓ,¸ŒC i*öØö¾:$qZÌg–ßÓ¸0eµº@#œç&$nÙô”!že4¤UÂ>ꇰëq¹©-fòz1­­³D¦€#Ÿ­l Æ7+ ¹k“÷‰Y/Ö%dFg&d¦O5	@@ïLyð	©©wL+q2›[^Ê`'+ø?÷ŽÄ©BW½FØp"FdMž÷5ïðÝÓô1µ:ç¸#:Ü<Ì`{k;˜&ÉêÚ¸¦(áNŸ–9akÑd¤Ò8lA~À‡DwßZH`2#À
m%baô`PôÒkÐ-­‘÷ >–ùîk=Ì{ˆ^DnVv
+5p#ìd÷âÔx‚–í<(Ë6 ¾ïQç­ó–GÝigÀ÷$5>DúVÞ$5¬x…ÀN‡ÛŸùN²°Ÿõ„7‰Stûí37ósšù£×0†0 0êBE!3Àƒh®À$Å„¿—8ÀkAÄö҄õXÓ|ÆÆ.ß²ºDú)ðÎÎyàØ!N3}˜U:ðÖÁ)á£8‰Þ¼)Þ“þPü‡Õ®(UñVù:kŽðqKÒq(
J®ä1!‡V_k ó,l£K1	€Ùn`+BRF½Ö.¾M¡cÅ_„ÑG”ÒHVHgÏàÅ7ñ),lú ½Ý„Á{k!¤™i¸²¶
Ū­ºÚnAG‹‹ºè&ê-¸ëbV´@R›Dº‡CvÞ¡ãÎÿƃÀž‚kdᾃ
Êþ’4&¿è
^"@yãY7€’팭­OáQT«°4
®ë7 ®¨ÇJåÍO‘Сo‘è
Òþ+£ÕñÂÑ{ u÷Ý‹‰UȤÙˌΩ@CI¼2Ê
UL4bÏFïçq‘Åa8ÐxcùNˆJËÃEÍX¤D‚œ·0$vhúX$È~™$«†vIÃB2%Tà˜Qœƒ—_ˆ=É«dŽóZMØh¥Ð(þ}*Hϳ¼²hßi;Èf¼ˆ÷åPÙœÑk­ÄµhÐ7鞬Bh‘|ßÊCB½&}©Ô]GÊÖ"»5E—'“˜_ÌaÑ5ÊëÑàí+ívÉŽ7V/@õƒýȉyæá‰¿¨‹ú¶q‘ŒîÔ„ÿMÊ1j¨9AÊàŠ9q89àv²¨6…c(¾*ŒŽ,²tOêÇÕ|¡hl¬­ƒó=t]îG*‰hP«$¥]í¾Áðe·˜¸³ržÒ_2•?êSMpE‡(gÚµª Œ¦a"ó\À«•¡–aíLñ["3§ÊZ!'‡Aµø©~r$`£¹xCùxK/]ΆИn` VÊÃ-Y|½ßêãäv']1
:˜WâÐ
‹t¾j<-éÄþ,;¹„àôÌ
íê_ðÎÚÕVHO_Hgl»’ÒÚwHË;iR׎¸ü¼rTsã‹Òx%ÒˆÔNŸ!8Q«ÇGK˜³Þ’¼­œätí€þÀŸåñËú=ÜûíÜ1qð@ž|¯¡¡ºÓ‡œlç™4^•Æ3¥°õQTÑVÏ£_goçzž”ÆK=%7✅f‡9m‹T*sh…5wήÜVMŒÀðaÁ[üv ~”–Mà×Kyб¨ìÕ5!¶ÉÛ¾1»9‘úN`«èx¤¡á{.a'j<›ëù¸@#I¤iñ8r-‰ü®4–9ÿ£'Ú °Þ±
úýì]iÜ/ï|+_”Æ{Yâ¯&ºœ›è]ý~²;!ÃTvAw]XÏâú¦ZÓXrƒÿíKîób&C¬’ÜCi|:'Z
ME\KÏçd¸¼~4ŒwŒtXŸÎAìqéêÿŸªIžé©e 2õÚ‘Wk¨ Õº&Ž!õ‡¢¹!EsBQïG÷÷îÜÿlñæõå³½;ß,ÌÞOàŸ¾ø8ý¹wñ§½{÷_n,ø¹S¹àטâ>išÆD*úE¾Ž\+¿y¡Þ†Y(dVë…V‚±y!á;ÞÀ¡l)TIt‹¹WSªÀÿÎ%ˆº,,§µ!péMå$ÚHþ<—oá™;-w£jM$Ò|hD°Vú3òg<8ÖÙ@½4ÐÐÊš4Ë »×E@jµD†j*àÃ5cÏB5ÇXS$›àÅw}Žs£‹¹![l¡n09©[mHU(9˜ÆŽò0·¸xPùtãÚ6Mi+Þb>Œïæ‹UnXË8+º¸
µ·î«³Ö1š¹ÚW¯Ì,ø¸)àRŠ‚u†T¢v«‚df£Ø9¨›±kƒ…Ê®_Jìàª@ðéoòó{¿Aƒ‰c´y¹!¾ý¥—›pGËÝM¹n† É•ÀiÊ7é±®`2šÃ{W²beÐF¬
†”H|žåØ…Žc.•o µžUe¡«Ïèù<ÏÕã'¹`IŽû*P…>ÀúL^QÑZ§çÊÁL—||†Rî+—žÐãêºNØÝBLŒÆÉ1vË­Ž/èÔ§F€W®ócºa}ý°ÝŸÀ»T^½é΋-õ¸¢øÒÆlkÎ^Â6ĬÏê“â.°Èd¶Aae…Ë–l;W€›*“ùN…ÈtèT^ƒŸ wÆ@°¹vö¡”È>àëCùà¦UÍ»¨ÕT&>ŠÍ Jö!uEª7©Èäûsà˜ mÜ42Vup‘’gÁè§ûÙ×}ûþCgbcã堊Я_ÐÜ¥á[œ¦iÃõ݇®ëÜÀj“J±õjwôµo‚œpáËÙjó1ã­.Ä|•°GýÑ•zêÑŸr´¿¢Û8r¨z66VÚ„§¯oFy]ÑóRŒ=Š«C–×ʥƢ¥ï›ß.½XC¢:¨Î
bn7Õ«št²…ãȯR¯Êuun¾dn6qôïE¡p­ÊÖ“™á'•­Ýï¯Pî:ëP™øó¹tà»Yù×1SȲCÉœ¤U[)l­
_·ÍÏ¿­ª¹wˆäx¢çñÚIر.MAèbf–_³æüCÚÀÿq¢Û]?Ñís6÷½ÝòÂdwfÄä(» 8g(]NêÁzò­9´•/“ëKŸnÕ•8ýpÄàÞ÷ç.8±%
Ë·Þ¼r^&YY”<ˆ õ}åúø$·ÂýÌÕFàdlJê²*¯HÓOøáR}‹
ë©(¬ñ”„IE[Uu ®æþ5¶°ÝÀ¿Ë!X‚ì§£•ÀKJ¨úÛÅ\@¿¤ò2’×®*.òPðÓ*Œ14Lµ,†ç¢â7<ÁWT)Dú°ææ~!#qŽùÎïdÉôó¨Ö«ß‹Ø¾!¨íÛ‰°Žb JG”›µÊÊl @À8[£<çó•„ÄtJQÕrJN‘ûU¿Á„¡‹/÷þúéïkendstream
endobj
595 0 obj
4277
endobj
599 0 obj
<>
stream
xœí[Ys·ÎóF•ß°oÙQi‡ƒs0I•eËe%vbËL¹ÙeS¼¤P<,’¢õïƒ>4ffÉ•+vÊ¥Òr4€îFz~\v­ZvðÿîŸ.vžôËãËE·<^ü¸PøpÉöO—wc¥cK;tƒZî-h¤ZözÙÛvz¹{ºxºR[uñhÜw»‰£ŒªFÕ*îÄÎ7k»ú¬Qí0;¬>jôêËf­W»Ðþ¨Y§O𵉻®_
‘vŸh=㫝›µ§1¢;’}@ñsøò¸<ýW³vÐ[¯>‰d;ÓÁÑO
}‚§Á¸
œ@Œþ{£MÛ)GþÖ`ÇHeðq=H÷	tï:í#E¥bçÎÄ•š%þRÖCGct¤cbwÔMâéù?âZºÎi…ËàÆ<#N—æâ¸¾×ÄéZ>k[Ó˸ŶWÃ@¿„WY½.¼ˆ¤Î`ƒÇ±Ùö°ˆÕüÞ‹\Æðå4.uuØXñI‚UqþÈ-dÔó8–Ù$Yç˜Tbñ!td‡H¨zmÀH4ýêf‚'/ñÿZ;`t(Ca¸Æ3 ð᳸þ”‡&5=.úzŠÙaÐ=†AG S$yN¼ÐÖÇžz2ìGì7 |ktRðózÏÕö“PÏ
”CIÇ
u¨[÷òÎKGØóAÚ–OŸŠ$•¸â5ž•«¬ÏϹ¸E¡V'¤wÁˆ9ÞdÕ½i4îË&8˜œŽô¨mPóÖ¼çuTuçÁÀÖA—“A)âÄWÞ“Bí5(§aNã
*_Ú’?íŽDH>Á¡‡Æõ¼{ê«d?1óÄ0c/Š2À¾ˆ‰‚0ÉvD}¢ÆmPÃÒØoìí¯Ån|‡¦`öðÉQ“z`b_ÚÏQ²mïURCàA‘q䃸W§ÔhPzÅfA}?oàãUÝ6BOOrgl{“ÐÓK‘˜ÉØùºÚ‰óëN¨ma%j<)g¹ñ²bºŽßÁwÏ­I<ÿvS×;ˣ僗¼×
ÈìûùñE=Yð€;F±ŸŸ/+úB˜.Ÿ._µV—
òY«;4º(-üxÓd(Ö묫¸‹À>P+ÂBнÖý²Èý9¹œæÆÓ¹ížmä&¬C­þLà.¦ÞßZ|¥ñºâ47~Û¤¯ìÉ,¬uߪ{}`ûð”OàTÕkžy‡Fã峎sãwEŒïa^ž–Æ2ß¿å$¬OQØß¬Ï¯ßúd÷
)æO«ÂÇ—™ä#`Cȧ”Î
Úœb²Y"Qç²
š܇¶D¿™ £¹#5k‚òógsƒùÛó¢ôüiÎ •áµÙCí
wR:(ϤLßJïaKãSш¡| ûŒ˜ˆåêÇÕzà«5‚æÎ´ÁþfAEt› íg0›É4̬½K¡§EÄâܜαî¥dr‘r.¸mtå—>轫|GÖ;}½žƒ¾Ñ~S®©m•kÚ¸w2äNøMÛ˜9Ð9P‰¯BÖ{Ai¸!E3qÆ›¤HÐÆ‚-TÛ>ÃÖn¶["bíÑøó,¡h†VQÐàOš‚…Ч¼Ä9òbRæŽô¦H Î‡Ê+4ÓB#€BR´idÁ‘<“€ˆ¥C”"D¨äTh¨»!ñ]짆1‚V Ÿ 7ìÚe(
Ï,9mê6ª2Óh€&µTM,ü?#üGF<¿ýõ;KÖ©´¶3¨qÌÛ)\…ÝÔ†+Ki EDu\{Ðú *¥³J#dzΎೋ„ô@8ìºo	%•ÃØµLÌj‹XbîšÕ!oNeÈ/£ŽðŒÖ„d`^X“hk+éQØ€ÿñ&ãyIôQZp'`ˆ‰@ö]Dkñ¢¢
+€© –Jg¬oßâ7¨OÅG˜Aë2ß.ŠaήîÙÀÍŒ…So¹²°˜¨ý	¦…(Ó’
;f÷5\RÃp}m©²b1ôL#ÎÓcç?Á8‹zøCÃ@Ìt–S¾ù#Œ2òž§1L^
 j }5Þöàd†`o)`ünºÄ9Š7E„\`ž"V ¸›ì¨ïЊ¾çLz0_´¯:+5=(/Š1“Ç‚ÌFœÌ­®¶ùZ‡-‚8±ë!]•5’QÀ@äo“¯-§	´/e%R‡Ìè)驱8ƕ͘“%	’nÜ’’ð²‚h£pÍG|8ƒÛ(Nd æå¢¸V‡¤)Åô{•ƒL0¹\g™Kâfä¡ð•t6«Zo­;Ùܧ[GÔšp˜ÖnS]¦•ۓɇíW›|¶QÐWÚ|HÊ€õBöðxämhà
@]L‡N:»‚,ýëäòàg04É%
`ž<Â[5BC)¬göÙéÌi#bl½/Î:À†'†>ežðÕïüµˆŽçÊùQ¤ú"8ç9Í|S¡
uÒ”€g‘{KV’ƒ‹ÒxÒL³®Ÿn,»?’Ká}§´9íb‹¨&Éÿ´gI´h"a¹Ñõ\òs4Ǩ:¿Ÿ$nw¥G³ÏKê%Ò SI>aw‘¯·4“}Édïtk“ª‹³ú`„™ÄÃíǘÉ×$Y3Q[(rž?®²°éÊö{Gqkžéû¡§m»­òÌoš<åª
ºžlt%xÛÃ$”?3$S\嚸>Ecöp8aU±Š)’Ç[á\¶’m+X½ìàK´]º’a†ŽÒ¿ù ‚KòqÚMJÎiÉÓŠfèÖ	¢[å:B‹£?%›5Äf¿¬©š
¬.VWùÜVcJ‚8.÷ò{ÒbÙŽ¥¨ZdÏe^Ê<Õ«o_Uθ&Ä«Nà ä†442è–3òèP92·º½gY¼nÖoÙ\9r=b{rîº$hÉ¿
á!Ýõì+-pJ?Šÿà€W“¸Û¬é›œ0U"ÔpoA‚2¨ßÙÝsáÕX©ÉâÛ•èr¤T.bi ó­f[‰QþUÊQçÏY؃Úl"ûGèÇÆ³³	gêv]z?«‚©:ÑäýÖyæÝÖOÜ ²Û-7,üªc S‹ºañŒ¹ÂM*Šã0Ìp„ÿ;3ª¼¢Cz¢öœ'J½¦“A‘<[IOÎ’WæýÆ•ÕàìBظ•xÂÑ?d¬…vŒeœ-¤È\!‰Hum*تà-ãÁ¸h©Àbu”µóã‚ÂØy³ùñšŸßƒâžäCÂq9-©¢õDcb¤fŠ´©Úú ŽˆZÆ1¢%avÆVºo¸Î¦%Y
GÉÃyÕŠí0(ï¶sLý€~d£ ÜüšÑƒd°¦å°©£ä¨Úq#Öjú€«9a0˶¶²Fw¥ŒI›XE˜YIÄ“êP6ÊÞ¶Öâ¶E‹82zT>ÈÐm¦.†È3¡,ˆ™¡ËœJqÍQœGÎV°¡Eùg*bÔ”'¼M°CîE'p 'ÐÔ©`yê[´èX÷}K½¨ðémía¹k†ŒÑtyQÔõ®ÛÜ—Üéÿ­R¥dh{sZ#îYKæy>GèøîÙr79ÝÆË*UK×íss–äv¶‚à°°®Æ¹Å¤)}ÜßêJ6‡w$ˆÓ¨î&Y¿Ó1ùµ$ˆEÇý»'ˆxq¢6ø¸QÀŸaºš¡{`èm—I£œ+Ý*&&âóH΢žæ"lAî Â{„ìó¯ƒIæx7­‰££ôó£¼|«$½¦b,E†ðµwáŠôaî‹VK †o$®Óm[)³®ë¿tܹ[b0ˆƒ{›ç½MžfpŽ-îŠâA™”8¤"ÿS6ƒÒr.µïÜ+·{Ù•I`—Ó‹â÷“C†^‰ ør|¦¨b†W”U·Òcgz¯‚ùKxÛ~´»øjñã2úc¯REΆeLˆäþZ)݆of=|¼ØyüÅòêÕõáb盥Zì|¿ü8þyüÉòw‹G—_½å[[:0[|øÅ­úÕƒ³l\hLA͇X¨Qði¹Ò-‡ðW¦/·°·^ænŽq´qøŽK…Ž}àçÝÇ­!Nq›W£¸N®û*µâ5.~a1Ïl¬Q;A*†²ïTd$óbŽÓU=Ñ”f2½W‘ÑϽñí<	KÍ‘sôÚŽê@^‰ ʼndýÏðYÊ^W¯qU›ÅçÞ›·B‹6*-5`–ÈËŸ‹x´o5†Ï»÷Ÿ–w"e
¸¶N”Õy!,Óȷ¸D’V¼5—bë)?ç7è&/ÝT¿„=0u°¹>F —d;àlÀ“?ÈÛ5J<Åël
ñ+èæraA4ÔÏÀ
ÖQ¹Ô)ß¼`øÀ·F¿ú±q·ã[~±,…(=Þ0#±íÊ&R Õ¿[i”ínñ.×ò0Ò€û®MkFnf›»†Qá#áG”¤·DA;b–“/—Å»o”Þp12ŽÍ)È¢—™ÓeF.-Ùp’;?Š#!¦º %Ì{ŒÂ)‡‹}3žVüÝØ'|Ó‹BˆBtêzÃ/²â-QA3
†k°’¢öˆËRI•Á„s&ÒFNt²fçnˆ½èQ©ºYuŸTôùi}Å<9›œáÝ¥ù_'‰Š`ø#¾ÀKDÊe¸¹º„A>#1€+ê›93.ÝSÍdjU…Äö1¶ÆÇÞúÝ„ÅÁ!±U¯£;‘s—çÑ«èé>mr¤nɧjàÈ×¾·QJa1¦_-þ†øµendstream
endobj
600 0 obj
3885
endobj
604 0 obj
<>
stream
xœí[Y“·~ßòà›9ªåhpÌæ%UN¤Š»Ç¡ËåH[6µ—6{Z»”¼ùõéGc\R–d••J	4€Fã믞5µš5øÇÿx¹÷øÛ~vz»×ÌN÷~ÞST9óÿ^Îþ¸£ ¤šAÍ–'{ÜRÍz=ë­=[^î=›U;¯+=7ôÿ¢wC=¸nþÏjÑÍ¿©zþÿùSµ°ó¿à§/@öëj¡êapvà²U‹–åžT£ÚºQíüËÊ·ÅO*±Q¶ã¢oAÌBÎοž©ðû¾2=öÝüïXrŠúÄR…ß
lWW5–Q¿¿ñ°¡çj}°ü+˜DiiÛªºs`•åXBøaam¥ðÂK/LS÷jB#Sêl0t`bß5iv…&½ÅOÇ•¿B›ÝÁ7§Éà+ø8(úH‚(óËšùye¸Ý=šäM¥˜U×ίAaêê¬Ô(tüeáïT@ÍÏ*ÔFw0Z«A	*U Uˆe/Y¨0´ª„/£Ý¿Ãš–F]U<„n7÷p›çT¢¦¨ÕgaêGØ@S’bPàdD{lqW¡ýM£ëÎsc9Š^%›<ŸW[Áܰ1‰ßö¹„=¸„¯ðÅ‹CÓÔä(àŠ¤yîS©¨»G%Râ&6‚± Ý*©Æaü´i˜kè{=?e”ÒŠ™NÍÊÔ-BŽ,Ö†7¦£5˜Ž=ãhÂ~Ò°hÏ+õËfÙ	‚(kæ•5Õ5S0Í/Ãz£Âê
Õ †ìcɜ̙=Ò´ðÁ/þÂÐØˆÆV
4Î	~?ó…1äú1V\…
ÒuðÂ?FáW±öÿ¹Žr ¹í[²òcô	ƒrÓ¡3Ù[BL(<Œ…8e
Ÿ‘jòÅ……\Œ§Ä­oóНo‹øƒUy«oòv4‰}/Hj®’’œç±þ8Õß—­c¡p#É=|±dÈP¿’еº!l”K†Â£X(¦ô‡´.Ûf÷HÚSÔûÂU©p
}#Q
ð+—sR Z_ÐL›€`ýÎ1¥c-û&%ý°“k§Êa‚"„kÊ.­{5È´Pc8@KÑL±ŽÁPTÎÓ~TÎGT'Þw8X œN†‡`ÔÓ	9¾pØ€o7Þ+ñëÁ‘²Âÿq.X{A1
0òC·šPa‰e´
ýüE
ÓØ3þ½J	EÌI<ÑÃÄ?R-Ž&wÔ×€9•Þ3–ðÚO÷S4zËH9Í“‰8õôyHlÔüu0Ö+ÂŒlÝ3£tÄ÷N(ã¥ÕŠ–B¼v”æÈȦ&Éö˜
<­^®bO)“¸ËÒž0÷¨|°@ŽhN¦0`;å(@Äs&ÅHë§dº6
F³–3žŸ¼—Re0¬i™Ñ…a»2së
ü‚0=ô¨Â,Š˜·Gß3‘G©épŒÎÏŠ¿‚ìÊ{ŸX5Œâ­#mE)åC)_Ãx阣ÄqÑÖÐÂLËÀȃD1Csa]`š¬Á„0XegU@˜kI˳YejÑ“+ó¶ÉÁPqƒû»Ñ^Ì?(ñºp80¸x“>SmvÆ5c&Ly0ãÌÏŒ.ÅH\[×ÓÈX‘<Ã㊧ºaóísTƒ»6e9ë„:”ŒFãŽLå	(8¼•¼——dÆ>ŸR¡˜w<%„¬).#á×S€ì¼P	¡±C³)àùýçØ.;ÞÉÈl‰150é¤D8¶µ¶]M#»‰ðRœl%%Ö7IcÈÈÓyl„†G‡’xTdNVâÃDpžR7'Y‹Œõç(ß|4¤™çà:ÀÒl'vdCIÎÐï8LŠçé`'®fŸLÀä!)ãfá(ÐÊàùàò?Í—cã 	Iª'aÑ6L¸ô.ð]ˆzåý@ùà´4×{rÜe³Ä+˶‚–¤µÈ¼7åÛy6¦7îãBüüU‰¥ìÈo­¡Á³ÖDîhÑ<ó€ˆ0À¶
D–ÅpD:á4¼ˆAðZMâ,tksåd|ôäjšæW2GØ­Mà¥5…iPÿFð_LnEüáAZÉ$ü–Œ™¾­Ûx,#‰·²¸	™d>rÒ8FÙ~#íü
Rü§#æaråsʰ¡ËO`K?ÿOá9&
‘äšn‡}wŒ"ž9ÂÈÚ@PãÉچTÉÒáB§T¶aPªC=ï¶Tá	ã*îbtÍ‚[tuÌ•&xLcÛv¡#˜ñ«bpÄçh÷w•(„hJ‰X8¢‰[šØ.„—²ª€E¸ñ'U1cÏâËda
¼ãxï{ÏnÑÊðqmH¢PÅSn,I¬Kz³]‘8
™ÎgJ?ã+‹¼añz`û¥@ŒšðR€®V•¼
p|õ˜¯·]œ—®î7_Dƒ}øk€ç©Kû»:œOW\‹t¹´ˆ6ÿSº17ç±ö>TÌŸùfÓ)"IБgDi/èë¯báiiÞw©ðU,< µØ±ÏRaºº/ÅK,¤.JR¿[°oñ]±—)‚Wc_P;݈Môx]’¶^Ë!ŽÚÆùøn᮳ÉÏ7¤IÂ혿º‡
V«•<.q"lßö@#ºH
X{=ï.sĽ!Cp-¹¿ßfÕkzþÇsú‹ÌšSÿ-:½`ÈÓÌ•ýb½uJW¸ÂÇÓxÿþä²E—}—©Í±ð›TøÔûÜ`Å@ëÒ@Û\úí¼÷¡0})9Ì]Ñ“?ž¥ú_JNº©§°ò)™zQj´Ÿ¨`˘G©ðE	miÌ÷C*Çbh‚ó¼Ç”èò4S"ßB˜Úáõ‰t~#ÒÙ–§IíCýa•Õ¬2Zº‰ÂyBŒ@´5{¨$¥1ŽW;=âJ¸ŒþøÃÄçJŽ7*þ¶I‘t÷Q7)‡%øÜénIíÐSÀÜ{=m£ÃÄÅ0xô§Jlè.aù,A]0…`Ëû‰¡ì~Q g>ž¤f‡	Œz8ˆÍ"åŽìã>ȸI¥m¯"_—Tº)²™z î!ÎÅ•ßs'éÝm	-ãô.þþ¯QîôW0¢àìѱy×'›x¡ÈGÐÓ1ìåIÓíøþºêxÕå_tE׎ãã×ðQêU¸4®G7EŸÅ²¨Iã½¾ßRq`|)„\|ôÂë{Žr»n|”µÍ¿H@MÇ'úR…
üËSÞœâã04Ä2½®|™MÃÚ=|eF뀗rù£Jù$eルp›…ýœ¼œ.ÜÇWš„ª·¦)^ÜÓC4M'çòùáË8Õäå*ÑPÜ1&^û•ßíž3„70£×æ‹×ú¥Ü…š­KôŠ6=¿½x‡Î:£Hy.’(òÿ'`¾ûÁÄ4JfCN•»+é±{á@„ø¹š”r0ç éjÕ©QØ,þÀÍ8Lùý ‡hë0 ØÚ;ÅP-šZ5äëuÕ€ßô=d¦Åºoç-øŸÒ¶Öþ^ÎÖÊ:¿~ì,=
©‡¾kø-Dïê¾íñgw¦6Ð×à%{‹4ÓÔ½ëµ5žlQp”.!zÝj»2T
¯ôºžØê;‹l|–´¾¢jC׬8¾£»mUC tm)–BpÐH‘˯÷–žÍ¿¯Ò-3Ó`$¤üeD¿Ë³ÎìE§iùÅè%§1òÑ¥ÕEåóÝm|zâ_˜LŸž䚬Éô×p'Òéù›Òâ§§©ÿïp®ÂŒóó<þAeU|ÍBkþžA\Éf1©~è]
&ùø:–±±t?uðÚBÐöåérïðç¿B
Իendstream
endobj
605 0 obj
3315
endobj
609 0 obj
<>
stream
xœí[é“ÇÏg…?B߬¡Ðìô13=IÙUÁ`³)Yœ(j‘X±f/v6ùëóŽ>gz´`’*S»R¯»ßû½£û½}3­J1­ðŸý½8ì=j§««I5]MÞLuNí¯ÅéôöZÊ®êÄôàhÂ3Å´•ÓVé²’ÓƒÓÉ“™(jú_õ³ƒ¿Â,%’YJ”¢‰Küm1׳{…(»Îènö—BÎs9;Àö»ÅÜu<*æ
&VU;ë€v	=RvÐ9û{1oxN4œÈîc#Rü?ì‡ÞóGËÙ [©²35Où®8Æ4<™vAD³„9R••¨yÐý‚•®ýÝG8¼ªd…€Á•‚(^¾	Ýà@¥$ÐQ0\!ue¸ë{©ªZ
Ú†mô+Ò2°µæµ­dNKsznY
G,[ÑuÌqQ(Ü&j@„V.x€ÙËBÏÛKX¿5¸Aø
;’ÃëBIòÇþRHlnêÙ9̸Dã4ƒ2Ò³wEM\fz'°ÿ5rõ%Œhpš™=È&”€éÇ0ä­kyÅmÉ|¤{môƒÖ?·M(ÉMHGz2HÁTtž%NL:ù°ø½AqÛ“Ieð0|ú§’@ióì3$ƒGomlcp'§²]I]¶žË§ D‹7 eE|VÈx®;˜…‘—ˆ†®«…´ta“¸?ãݘWþØžE:ÆÞ=-@jžùKø:²$+n{®ÄZORe0¡í#;ý‚Š„ÜDGž+úáx­ñpt.ÕÓ…&fœšòáó#{#)i<¶ª[R;u…4jâúÊN|çy†}‹s–ˆªŸyæQBô‹ÜB}äY}”iO#Ó9Wš‰GÇvrHœŠVµš«`Zœ~ÀÓqáê á#üZg	lc¥œd®jíyçÙ†x­øˆDî~8s߉ª‹Ù1©¯Ž¿`-3eCö¼M3zÞnMì\²è‚R {e´Œ72/p‰5|‘Ü^{…&7ÀÀÌÙ`›,³¼­sšÆW{F
•W7î2Z…
nf,ˆÙ×Þ„w¶ÔýNV÷îþ±õ‘8ëîÁäáäÍT©²¡(š©P­*™6
¸Gø
ÐíýÉÞþߦo/×/'{ÿ˜ŠÉÞ=üqûÁ·ðkÿÎô“»ûÓ‡;FGBƒ÷m`Y66B½¡í¼Shöãß98¤î£¡É¤z§èô»j
=5®4)·S〳µóŠøÕ¨¹²Ö·ï…QQÞØáVW–HéM¶s‡mÆPUlÝÓJð‡h¨…"Ø›¦‡Ö^Ö%ÄAÁ\:@¡›HlZ!ôy ±C/ü«×Ž…o½,nU ÿÍëN‚o6~u€è¿?âöP%ÙP!úµ$±¸EÑG„LÅÒ¦ND@b
eM„6ØRÕI/ísl«]Äç>ϼv6÷#[êÝàÇdâ¶ÁìØa`9&mTÀÖ¥QÀ!{©™OÇS ÝÁÓÖ¢£¥Ñþs²€˜Ç„ŸãW4>tJ:Iž;^»üÞw\yR—.êf{°˜
·ωⲕo|ßûÆ«ÄJøŒ!yjljóþiüì¸ãÄî¼®:²¾7}÷E:Î~Ëdzð=¯Â&ãáLRÉÁqf¹Æ3ßx˜D>!Ä–£þ
|”Õ6Û‘‡í¼Ë<	ëxe×HK³‡Û‰®>žóG
·µ±H/b
™$PJB¸·É¶Ó÷AÝ3YÀßLQvO_×¾—<ûìÏðƒ½§)S镲R.Œ‡1x«¥k,ÝKg²kYÖ0¶Þ¦úriy
ûYxí:q?\äv¿rh˜Î«„a±&{äúOrb>÷¿„Æcß@¹Â[TKÑÁeŽú:f^–ÐýŒdR6Ï‹áÆVÉ¥m“Ž\á9
ë0ò*Þ£S‰g¿zœUÞõ]œž$Ë`ú8Œ}›ð=²cÄÄ®ë]E{ G
/{ ®0îê‡úŒËþÔÛiút3WáœK
\$
í>k¸ ÈBî2lë«Íè‹ð±Šå9\=`à«°zPÝ£‘÷·&ìx¡£Æ«ÐxÎ5¦çˆÌ¸“àj W·’@ÝSŠ–H¸ljÈhä2z‘€,ÏN]än–fs`p”D†?÷©q6žgd9ÈÒ5Úc•šƒšö3†4^S<²¶%~d¢çùaqOˆ¸Ç›ƒ/qÏqÏÍwÏsÛîÐWÝr~GŒn©¯ýÛÅEÁ‰ìcgÎêŒÇE¥»2ySð‘‘[‡â£ špý ÐÈ?–€j¦F…<÷N-1V!{Ó¦!ë¾ÇÉ*ÛQNŠ9ëuÝ%cá=p
;ôÝÚ­ÞýH1ŠZÚ»Åw6|êIiƒ§Ì:ïl8ˆQn‚wøèî¶öIʼUªot”‘g#ˆ[Á™ŸäøY—¥o|‘3Í í‘Z^|ÍEÎô]„Ægáâµ…#q“t¸B9Sòd£¢ýø9k`–Ycu¦=ë¿MÓûÑïüb~Ç÷„©ÿòBã]wŒwAzCÚ»ÜÎNzûÙÍKîpSÏÜÉwõH¿ÍM½IÿÜñ¡
UliÒ›4¥ë>ꚇ°HMv_žÄ¼æýàû~SïûÆïCãõ#Q‰>¥Rº7ŠHdžÁ"*ΘjfÂÂÝžÓ¶TMiúïëŸF9%ÉÊê_¨å‡XTœÄšƒJPæßõßàØ5¿ ‹Ê¸„4'ÚKO°©P-ªžY&Óð“Mnø¼eÇ.9›(µiy_ÎA¥,f<ÅCÉm+dB]tE¥;”	Õ–á ûIíÏ?ý·¨à†
p°¢ˆ¦qŒÜŸæ2?¡¶¢G ¤äƒ´TPggÝqt_o4o/*½y§¼mÒ¾ºÄÉ(/´ö&L†ƒQÊ$?£Liè¤LìKš>ˆŒHe¬Eg’¼ÍiA•S2M­QÖPW!	EÇT펕Û+gÙ©èÓJÆ‘3fêI9ÝËà!Ð;ÃU>…Õ«Éá½(NÏ¥)H›¤tH¬¸¬­ÒbP—‹æâêBoF°á”I²zF‹Š1˜±|}“ü8—L£E9´ŒFµ#v©H=ßûÜ£UC£5ŒRäZ°(mé‚&£[²©ýÏÂ()l°0JʰJ
„IÈÈT6èJ»bH<æÝ†Ä£1(jh¹ÜËUdà͘›”24œ1%óLLÝ@âüjɹšS9Õ¡Tì’m¡UÓA*3¨Cº2-áìk\ÃÌ~bÿê¹}E¾‚Ðo*Ûî7­HЪA3"[“«H°´u	»Öš6²I˨<­+B2’T µ3<κ궔=G×.ÄNÏ•…²LZ¡òMOû-B©¹p&©X°D}Ý‚4d?ÆÍ‚£g3R36¦F*®ŒYûJ¡e1¬¨¹áÛ’³Ù”ý6N¹‰-YkTÙTT'PŒ
xdYhb¯ñq­“¬¹Ö©WyA¥kb¤ò"©,TZDUal0Gýªk´±0“N&hiT!4æ.*µöfE§Ï>BÛ*å‚‘!
‹pèŠL¹
CQxÎõ
\PœT*(^;ŒD';i+‰§ZGCðÃ".ãñVwe<¦~F„:< 	ØÁ½¶l0ÏÜŠ½ZE'¬¨(T¶íˆµJËÕgàêÎaì0¸y\2ñLÄóTvËB-N‚*æªüX
|$¸^Õ…pöUšOšÚ/ÏØÇ1™w1:©r¦wØÖ8üç&Ë…e8fDÊÎ-æ¥Ì+˜a=bâ5‡‘ŒˆÄ:ÕùÝÛ™ä3]½5>6]ZjI[–±#`¯jÊÚG÷™zTÕŸQ5U/ЬÓÜö?™Ê.ÇG¼SíZ®ØÖ´ëDÒh' {¤Ô%UxXxEù^Ù‹Æ#€){U¡>™¼Ãr¼„¯/öéu«Ú@,³éã¦çòw¦lìC¡º²ÑøÿM-וïítñÅ僛áeçKAWüzu]Æ'Ç·|Æ'¤ÐÓ7®?Ùe¥ëÎyUŒ¼!Á©©D¿h囀—4{¸lG?Þ¥OJ'þIéeቲ¨?[±²Î\Æ¢E•ÿ‹äܰúì³eä‚HÒrÙŒ›{ÝÞ"7ga¿EnNú?/Ú”G{Fîü¶ÿ$GÚ¿²÷Òbaå/vìw`Ǽ0#;†Wx®úÄܦõ,uŸÕ³ÆìÌ[¯À?oàXêQ~àsZµÝ¬è'µhÛdÔ‡e„Jn½gËÜßQŽ=[òS) û饲“§,[®xÙkþ"ÞÎñ¯£¶{š@P¨6\®ÿ£”d?62úŒ;ú÷‚|cP¥	‰&û*ÁOËáÙÈß;ùI¹ùSK{··„ôéáœü{4Úendstream
endobj
610 0 obj
3468
endobj
614 0 obj
<>
stream
xœí[YsÅ~WøzŠïP¾Ãô6ÓS©¢
‚+$@@EŒ+X‹eÅÚuÁʯÏY{¹3#K¶Wö8 ?8xí­o½ß]»®Ì8ò Ÿšà€îàWOaè)l¶AN±CÒV'Ðv_ûö«—HÔQãW—L‰6œz…<Ã×ã醎HíоÉãqˆ,Ë[õ(¤!¯s,ãWg°ž<ö´çyc‘@-,‹¤GyâCGÂ"þ=ÇpŸ—¸…‡Q¶&'¯2GM±÷S#pÉ®n ðøyµG.Î
#—Ö-ˆ:jùvÛ˜$sˆ‹ð&×îq¡<˜È£¤bÈ2ú
Œè‘—	V/X›¢+æÞ % /ýêçÆ’=Ÿ¶ÀEÇŽÔv_õ
`•a°@Ôa³²‘Ôn-§Y׆
…ò!å¸ÄUéëüàDU-üAzleëÒ3hä¦S4¸„NÇPŽ(/ú,±caÑDq>WQºž¬ÿAcs'­…Ó/yCË#RjK»éˆPü$á"ÀâóİH@$Áø@Èvåø€²%%t½*J€Øà<‡BZûL`"9}È‚E“ô™ä~¥Î/þp™åø")AV‡¬xà-Ù™ô®t&kÀ‚»0­Kîâå‚[£n3’‡ aH££ã0µÿƯ(Aâ0È~¡ÎqÇíàÁ7©ã:M£E/³ž¦Ñ0Ï=‰ì ÄvD÷=ËŽSã‹Üx“¯S#É>ãII¯ÃùÈ߯ˆúŒÉõ”§ržÐD×û©û²žGG{(AkRÏóÒåÃyIOKNŽS±PÏSãÓÜxV²O>=̫ȌÌL¾˜[ï˜Fᙜ“¹‘™»ffÈ9-‰ðc$e>œÛ}“÷«é˜™Äum-ôàŠ?z‡Á
eílçãAú°Ò	°'ÛÚh¶œŠ¥%J}¥<‰,õv_ð+³ü,ÙÚãsä¼Õ²”ŒÂ¾2›_VýSŽæÆMnÌöø}£Ùà㮀‚%{÷p€ØÁIMÉâÇf
(­ç„xªk£XÔM›íV=ø8ÃŽ«ÏÑgÙà-1\‰q¤kÛ~èLqN´#ŠÉ´ƒõ!’aB<‚£\ë`}Œ$à²âàÑ«t‰0Ö‰o¤%‰’2t[CjÔÇv-Ðå[ãÇÞVƒ7JÊ5ö÷´C¨¢“œS7€?Ù?zä$øBPÔ0¾ÀûݽÏvöÞ\À5Æhx¿Ñ$‡Ðld"kˆMRü#ç‚Ló–I¡ÏGòBðú~
ðdR‚+… Ð>rÒñ
#™Ä@Å4SØtLašbírEÌC¬ÖyÚ壄z9¦Ñä+¶ÒnM23* {S|p1§¡×cå
XCcÎó÷T2(àyÆëÂÅBÏSàO<4o½Ë‹“T¾ÍË$Ô¥Ì@Oä†'bÿánˆˆì—·åFHY½'úVp
ªÃ!΋$ºXJ¡Fhã\E4«„ú‚„pV	P¸¶õ±'µ\Ò~p„Ék íÃ@ÄL´'šƒžŸ+.øYW%S$šAÂ
ºfl¬ÔX׿f4}›`»š–—T(C@äJ•ªÀ2ŒŸü»/¨~C5"áUª~A’£í+ÖÊŠ¬Lt°:¨Õ~&»™÷”Ëj¹ƒ'ökí8bŽªõ‘ëKÞÚ°23³ÃÃ…_á4VÙÉ=òQ3wú§Ð^ö;TˆÊs¥¹rQâÖÈ´Çäð¼¿}éËm…ßNG'Z/ñ’]2
|#~lÓU=š*5QfRRƒ‡Fæµ¥p¸LoûœÀÔùvÎãtÕô[ÖJé€õU: g¨óÓ¸¹Xh`gT+90@Ò«Oefâ—ë(£¨Y»„.‰$t¦IjD]i8$M²>M’m%benuð³Ö¾[<ݬs=ž§pB)7ÕŽÓÒ*¬"€$p±'j)-‰ÐFef¡ TÅú4…Ïo`™ÅdpUxÙœúIäNRŽ“Ò·"Ç9ª±ð•L#gòÁÄÍuiÓIòvV®6ÍvšÅä-¹´ÿòv’zæÁû‹2çšf çsIÎY•P†0ú»¤‰“¼ì`a¤6æl«8Ò‡Y.¯;ÝÛ§&š–¡!✺ÏŠ‹,µïÄùøŽÃÝ:/~·t@Þx²ë·v1>0È]t1ÞX=‹.Æ[GÊ3	¬S¿ÑN£Ÿ.…KÓF¯¼œ‰¸‡¡%Þ½}£º@¬Q3úšÇID›'Ç'|Ú ¤|ìþ`LOù—ô?Ïa°®aFpˆý$­÷)’tf«Êkû­Ò%Zõ4ôš5MÝø]ti’QqN±\ÉÚfïíW]üÒ-בâÕ$Ç;æ wVÉwëâ°0|¬AŒE^+ÖÎ¥Rg©¤žÔ9³Fñí÷«Œ¹û;ÝIJÀidlí¤QfKAÑq*¾qÃ÷£?HUè¢r¸ÇìÖ5EÌÑ™È~ ëwXçŸB-éì“íååNqغxI	KIÁMQ–T)É9?ÍÞ_n‡<ã²tµ(uŠ`­Š”¤q´(Gqe*ÑbU·“ôÂN(³¼¥4[‚bFA–Vµ’Â4>]¿SÍ/D©,•Ô<•‚ \JŸ–­íR5U'ÇŽN¬¼"˜‘ïE!á2iúqI}³Z —È«½®àŪF'JÕ÷)`Œý¼JŠÞð¡êH•Šž	³'c4n¹L݇Ú£*õ/¹ D7Sc(+N"§e-ĹÆ/«I]¨9nÊÒR7’ÐJž…¦²ƒ—§Ûqž]f_#ùŽ×$%\°mǬ83Å^ÆÞpŽ/²‹)® ëT-ÊúyAXçaF•õðä­†ïIeyå%xÑ_ÔÖsÁ]Â’FÅ”¬H†À§®ëí‰ãú˜¡‹	ü'ÜqsK4“Û!ÈåPîs4Ž_)Ð)뜂2’)Ì—åïMO^|B•P±I%VМfÆJ¹²Š¡>½NÈÜ+÷x4S!ÍÚ2)]ªBY‹÷2'еú˜“ÄJc•R~ZÃ÷GŸ§åó§Gú,k/“û.VŽh¶†ì´z¬dåοþˆþh“ÒÚö–Â…¤—ÖÇI(´žo$¶Ã|ÿ±a&ù”uý«¶ç
+'ÜñGLm	[†Ž4IÜ
|¹_é‚
VÜh"›eȬkMz@sL¼ Ø+,ɯ¢²x%Aµ-;è­„Â.^[geeªÐSÊdJÏ…þ}1ȱTÞ&G-"ÈákŒt7õ
éÒdî¦!¡3Œï¯äQ=‚ˆ(	ï«Ç£¾·E•¨•O®ra6š­5¦m`Mº"â<&FEèv`„T;A­õÄËɳ?Ö&×I›Ê€v0…$sd)Ñ-ž«½åJ϶´b—,möÖÙÊ›ÃgsÁ`né"»ØkŽ”j²(»öS	㨅£ì\FGò~ YRy¡š1w…!à´pÿ4¼ã懼P¤Ûâü*ã‹<2Í`µF+tžpƒVÐèҎɕ֓„)ÿ¢|špXèTq»œ}~y\&Ðú”§Ýð9ÐNp`¨/ÇG#GºP¼¨-Ä:UôC£¡õo¿0LX›ÌKlx”åH~cêýƒck6Ñ6æE­mTÕòäs«ÐÚùê9m.¶v.ßý'FÒeÄá
¸^¿ ¨vUl«s…¥2ªà«;eô‚¸âˆÊmu÷‡ƒ^h…¡"Èø	AìÎ|Û—µÔýĺ‹IeµŒtŒ¦c*¾Ôhu‚¹µ0‚ Ñ$¯°­l9艛(µ¼ôT>5nY¿ÄiáéêàW:wÇ÷»ÌLˆ}˜ˆú¢(ra[W}´ì Šµ‘÷f4ãhÕ¾.$+×-ªÇ(%ÿ+I
cÅ¢xCHˆ¡Îhª	‹äoRfó3È
–3O	UÂGö¹Vþªx?S? "_dïã/h§{º·-ªðùžå	ÕþïxSó87æw7s{ñ•B1êtnÔ“ß/yÞò’ç§¹‘¯7å–…….J)ñ­q\T‡›­é”,Ñ–\Lù5íöCwðo’äj×ÖõT6Pе÷Õ$Ù8ó!èë&õÒ­ÕŸà—øß¶§gæ€x̯jþ§_§–>
stream
xœí[YsÇ~gùGà)ªÈÕε;û’*'V'Nâ0ôC"±l)E$HñR˜_Ÿ>æèÙ]€Ðᛥ	Î=Ý_w=3x;kj5kð_ø½<Ûy²ßÍN®všÙÉÎÛE•³ðky6ûÝ4PJê¾éÕìàx‡{ªY§g±u£gg;Ïæªrô_WîðàÏÐ˨¢—Qµj¡ãÁ4þ}µgçªTÝ÷ÞöóÏ+=ÿºÚÓó,ZíÅŠýjÏ@Ǧéæ=Œ]CÖ=TÎÿYíµÜG4§a¿ÄBñ+üðe®ýwµç°µžÃ6¦î½ã.¨4¶ñ-w¦UТ÷ß¡6u£7ú[E
a”¾…õиûؼit#*+1<ü¥l‹
Ñ0ŽæG7õßÀZšÆiEË…iFš–æ _×i–tk¤¤÷ú¶öÔ{¬;Õ÷,òçs˜x~Œ?^ãk\;Œ®æWeÅ)þx	S4=íöqª¾(û]⟻¡!hh™j^Á*ƒ@²9iiH.|“[¾L…w¹p•
¹ð,æ>»yô/RáAîó¯Tøu.|Š<üaÅD7SÝNíè4|GBäúU®©9…À5ó#¹úX¿Ì_ó‹YãÇ0­Ü\UˆÄ“ÓѶvSK¬жu×ÎöŽ®EcÅ6¨*Ô’¡Ýjt‹ò¬mª>ÇYg†DE0À©lßÑ®KCÜ»ù¬ù«¢~¬äë)…\¥ÂçUüH»Ô¾n}£f{º«UÂük¹Ü¸„ÒÄ߯
óÖR;êq‡?¾•À
âHógAvcø\H±­C/!ð¢Ðn(Üb¤ˆ¹ãT/Ðóßïa¤£\øbʲ˜œèã±xþ„“ç;f,\3–Ï2Ô…§x–?ÞLÛîN68+6?çnËM
#¦nleN‚‘¹Þ?xÜ-ùö]8 €^1ŠìaâÜJ@(¤@ÆØÏ*@ÙVÛ¤ƒ—|%p±(Gœ:c*Oe,yHâ"¡ôUöš(îpøelöi)Bâ&KW–8MÔc«HZŽùº¦•G¾#NøL‘+’¦„DÌøT/¨)S—§x™ZG;H²FžFg¨éôÔᫌQ5ÜíùeÁÒw³4(t§Q±Â5aÃ|üØÕ˜åKŨϋ’M·jâ|‹lÖˆSù¹Ói%`90tœôb2œƒw™–èß[K;’Œ¼Š5Ñ%uË#m¿UBF÷U(à Çhá	QÁ D…3ãÇEÂTÜ#G‚–w“h_9¸f1¨’©ê”uPzc'_ȽIÞˆ`ÇŽ…÷EãÈO_™I¹Z§›>y+·u> D›ârA9¶F[)Y7vBÁ£
Ë–»9xodEfˆ´®£O‘÷¡°þ˜Z<ªâ=	í¼ôBGXšåÄæk{s=w¿$mv2Ï0qUÉq´™¼£°y[÷¨ÿi©Z:«µãà↰HhëÇ>—¯%‡aNqÆJh€ŠvΔß§)«l ì‹cxKX[
†+ØJ‘­#ÞC^¶Dð»:Øx9˜¡›#œ0(„ö}Ó¾tÙÚ«‘ÓÑ=_“`‡ANì;ÓyO8Š‚–›î…½"”ÅS“¦ù@Ï¡{Gñm/MÖ7€i\þ…ðy2™‰`?o„&‘êi¾Ò9t܉g2ÒñkÏÄzˆbíÙ´h£"爅quAƒÔ´ä9˜\"3»ÁåJcæÿK#
ÂàyA´ÉÉ5í8¹¼óÍ4É6ŽD}“Pò™,/ð##€XåyÁl©"8Œ
®Ì†×£Ò
’H¥	ãØ¶Â!t3þ©Lù"a®²Ñvç•!Á³
Ónãð2"ld’\ÞÔNݰ3áw<ÓÈórwk\i&¿C…K<)ï„‹ÃFáiŠS0’k¼<1§á;Ȃ҄tb­ß°k/ï xdbt{×õÝßÞáó'¾¿¢Û»EjG7u[¼>œ|âsY¼TНOD&îŠN¦ž‰‹ËTxÈo¬6]æg]âíÞ›Jîç
Ϻr«Ó©V‡ëï“–î7­ã¾§Í7rJ£øbt‹95§¤ëî1'îEʳH!’xox-^>«÷yúŒ×¦![,
°ö8š$]ÞÄu2Nª¥G
ŸöÝñG[þi!Ò±OZ¾¸ê=)ì9hl;›ž¼ì†žçûÏ6vû+|ð#eáãŸ"D³Ü„Gi¯‹5Ýûö{3àÏv§låzÒvïùÎÀn¶Ý{^òo1ç'úNÀaéÓø“—bêø¬KTUyR,bøJÏ‘õào~ óþŠT
>¿´÷ú?!ªò𩌗ÑDïû©›õŸÍW¤<îv÷á+R?k—ûô`çðïÿb({Cendstream
endobj
620 0 obj
3395
endobj
624 0 obj
<>
stream
xœÍ\i“Åý¾æGì7OO«ëꮎ@Æ`°XÂÀáXíê
öBB`ù×»òªÊêcf´G’zªëÌÌÊ—/«šŽ»Öwðÿ{vyt÷ápüôåQwüôè‡#ƒ/ùŸ³Ëã{'©‚3©¤»ÑŸ<9¢–æx°ÇƒómgO.¾ÝŒMØ´Ýxüw;ıc¿ù¨ñ›¿5[ÓŽcôãæãÆm>m¶vóEªšÊwm×
©šà¡ß|ØŒÝæ¤‰.56ýܺÐm¾j¶ýæ¯ÍÖ§»¹_:Ì}’*Zè#¦*ò^|”^¸>¸Íד“©YxJsÖ¤ö>n¾œŒù¯Ü—êã>L"‰j´©~0¨WÓyØláe4VOòód`
w’ºH/ú;¶éM°¦j™d=ƒý÷ÉgI=Æjõø`Ú>&
œ'­˜¤
øãš@•ã±ñ­ó½…º[®¼u];˜q¤6cšY¼ñ Ï6ãÆ¤Õ­1I¼½OòèZÒ|ÇÍãô~èÍ7ïÁT·i9WåñqZËàR£ªÕijå:çÂæÇôÔy›ÚŸ¦šÑ¶¾7°p#o74§h7Ïñ©3V†„&O¡#ךèJõúfÔµ.Ædi<cà÷nñ½T¥Åu6/
UÕò;íಒà¢W³û/è.Fg“‹Ä.hÅ6uúeã’-tzÊ/ Ÿ.˜¡]&	š¡3à†f	Çe®ªíKÙYçܰd*.Éý£“;ß‚ÑùÍ3ØcÓ¦x	v˜tç;…Íu² Wé-˜iƒ:X#7ð]Ä-Æm}ª´õ&à~„æ/àgš«	i![—ʶ6ÒŽ?‡n ¿'`ú¸^S‡]×Ã`TÆÓƒYa74Û“ŸÈÕ`lœ4Îî4
}C÷›ùoáá”I[žf<é~E\’O›ºKB!ÀoÙºPó¦dq¡òt^7 ð¤·6ôF6#ú¯‰›AÉ£wßÀ*F^¸T¼†À¢Áè<ÌÊ“ÀJ•g¤kU
¹…
=iå,¿!©Ž­_²ÒÛ Ž¨ږʧäW¶²Òmšgè`Á¢ø®C,»µt¢@‚7Å´rY¶£¤âd«ÝºÑ¢•¡®J³s±Ä÷&/XA®QA7bjiO’žAJ¡	¹ÒBQ¢Í!›º²‹´v~‚Nà˜m²Î½º–ó€6?ÃûçÜXm°\Í/é0"O^SùyÑ&ïÙ¦q#Éü\6V!Ù¯!Ý+)OײkÎ3ôd@Vñ;©mÖ*kiýÔÀzŸ­òÕ‚-³zÛ£¹ñâÑÚ‹µ‰õÖ–—?t›{Ÿ‡„…@E£COñKòòÐêX:‚óÃÆÁNOxô€‚õ}·i³œ`Ë¢o’W2‰_® ¾Ò°8b?—	ÑØ	¸ŠþÆ=ˆKFFë¬]‡$ꃺС^es#ÿ.èL¦‡îÁ‰êƒ_T=ÄȼKP°ÅÖ<•Uˆ$Š<)2ø
÷Á¨Ì¬É}%†¤,H+‡V„„‘#!ð3½Áµ¾&ú@%hð¥ˆ*1›#ªÊ)v½_3Wå5š›bQíÁ%Þ¼>ƒNÓ‰«}rí{y÷·û°‘'àœÏÊàÀмXy_€]ƒ\’žwÁ²§	•§ñ>TÁš%®U?•í:ØíˆÞƒqLZ?_ðàïå²bSTº¯%“òC'žŠ½5ð
ÄIWÑ¯Í ‰–8hÌAÛ²‰º%̶•{QTG˜9PZ[ÅïÁèû‰/…)Bp_l©‚C‘Ê9ë,À2­pg	ŠÃÔ›-Èžì‹]û«ì:
h kÝáƒÀKص–1GáÂ)!•r(§t0XZ-‚èµ F¤:×ĦþœÎz³Ula¥òûQ;°½TÔªÍÜ®2‚Ãày)
Cq:$@²Çº‡<㵊÷JˆƒG‚\
ŸÎ$Fª´îúQêû£È¡ìûèë#ß~ÃpœõŽ.|Z«¶4DíÉ Æ]~Cûl:ûüóbì »†x{||BéÒ®Ÿ„Xì*~È=f'&¦wùÜ•¨`ÌþÝÓ˜›ð6Ù°¯q4kÙgɼû^ôN/‡3C/GÀiÛ˜é¢l¾E'Ç›µm8¿h½Nm¹§m¢å%gh·”aJaêæaŠ×Y"ˆ6KÕF¢«³˜HÐáSª
Í€	,ƒ+:‰CqóÔf®I5™øËì
ÝWÚK»Ê{Ħv„£±Jpoñ”lì¦A4¦p÷	ÄZ „½ëD:•]:¦ôÎvLªüsš{GžD\(:ºàë­l‡A±+v¬v°žŸafÞíáÅé‰w«©$’¯U1Pñ5?æhH…H@~ɉ$aKt}HEœÍnÎnìÎUGB¸ïör.gºÙ²$$íbŽŒþíδC€Nœe>3u/B§³
{]»˜
òÀ
Π×a9¤÷q³lK€>ÆáºotäRÅOh\ïb˜Šƒª8ÆAš§ë5Ñz¶_WRÕ¬Ñ(¿?iì$œ‘ÀþÅì3'{ætÞŽ#J+ïcåÌfŸ
àOÆ©»M¨ƒ8F€Œ›FARwM¨$ÇA GL&Ùu·ts·6enÞ›6*¹Ïîo:Ý^™ƒ}Û+ƒ@›Œ°š¹—2ÈavàÁ½áÊ?nÄ 2ÓÓsÅó,ÿs
Ób*kÜçE&$¿ÔVù#9˜[6!ŽL`½µOQ‰R\Ùf\€óVý
šdëx„ëìï|*h$ç•®Ñs°–èô8„èwMnpÊ.vã“;2®Ÿ%SãTÇ¢iKmÞ/â˜úet=N sxü Ì°…öï“ß‘!GŸíàD“Ô£ñ¸þ'š
TÄé²q]+É­b¥ÙÑðÜkËÊAÝb*ù¾$ÈK’ÀSòg•Ë©‚¥„Œ6S	SRDá÷—w’'E-ts1+GqùÄq0Ù»*˜Lbt#E“øÀ"ÜRH0”MÇï9RÜLsüüĉÒ[,{”_œ©(në0M‰l<Ò…»Àa:åß”IÜä—¥°ôw‘Ñs¦g#l:[DrÛéüô«2¯ÐÝɯoêv@u 
‚“¬Ïó›ë2ÉW¹ðQ)¼È…Kó"Ë3QÌ׈¦Âw7úÿt¡Ô|±Ô'Ž18ù¤¸;ê¥êU©ªçÎ’¬ºPúª<¾,á¸C¥ï99ò­C¨ìÙÞžaNkrpà
aÄ숲Há~?Q*!7é(ÓzZΧ•âä\>g9M’=‘šƒLìÑEŒ*3#×ÿ÷U
ˆ®ôÂT<ê”yohM¯Žz¡+’\;ž4mÖÎM°g~ G‰VC*²ÃzÕÇ7]ô‰%½U,¬nø ÊEÆŸêfíìÀÒFªhÇ;3*ƒÆàwPkðY“>Õ,ËU:
puØLó]>U¬µIm/³–%âÏWù-æŠi‘Ož(vfB‹ÜA´®éWW;7ê>c•\«D]Æær™$‡å;³p¥û¬"¹¶:¹WÏíäVðR'“#›õKnÄï"nu‹ÂÅnõÆ«p£!s#vÂ2õpe¤üëM.œ\4¨îCT€«o"âX!³¼®ð™n"ÕÄšÀz­B\ßz
q}vÁú4­D¶ùVK¦9pœ=ÚÙIêñMÑü³Ÿ¤Ø…-æÂE>>Ì}‚=`‡]F ùw'©‘Å,3ß?ix›“nKÀç}]4¹—êÒOÛ^+Îv~MW–xx+‡¢Ø¶FM°[}Œè dõåó…ëyõU;¶0™ô‘~	—Ä)±÷®O¾†·nÁ‘¶æ—f(T%Ã!‚äÛ]ÎluÈ]]
ØKÖ_z6¢L~2ýýM"¬Œ'nO583h\ð_ï
¦aÁý÷¶ÜÏo”I~‘?)…ûkú1_v*7lçÁO{BI™&ñ’2e´ŸˆeͧK…u²”1ÀÇý©Òlxþ—‰	ÐÑËÌ;2ßMÞÄꣅƒQÛ›åPá7Gyì²Aâ@FÉôåÇ’”¥ )C¤¼£•˜f,°#–>ÁÛ-'K?ŸF(qà‹u:ÿ÷hr$¬ñÛœ:¡ªH¨ðÙœè
Ó‹+YeÊ™¹úb¡£O–.ê–À”ó,ÎI:TIgl¥c©_=³Û>Ë=ñ¥`1À¯%M=ùø„³à‡}9rˆ”KaïDNóÏGÚù%$èÖÞÝâêѤŒú¦hò+êýz$¸ôôl	N^ .ãœî*8%bu¨VNõhˆI¶»õÞ"&ý'xá-`ièjHâLãŽ0“[\“sŸ@ÑÐÂ/ªSýؽñ7@·‚"þòdŽ Ò3|ÀÄ:øN¤&îH±í½>œ©Ÿ&‡õ÷ŠuZ»F1MÂò4ò÷Cø½àKf­(¦pl1
­›}‹ô¥k rýŽ$ËüqC¦:Ê-ãiñç
yÁÄv€òåÆ?6xËÿHh‡?‘BJ¹AIg3.·þF€‡´[Ø4Úÿÿ
 ¶Y„{>kÐjé:W­Øîº³¯àNÍn_çÉ[8¼óFážO}øO€×š_9æÚ*Dù"_iÕ ,e“Ã^^Gm)‡œõŠ1Fÿíäèé¿ÿ{endstream
endobj
625 0 obj
4213
endobj
629 0 obj
<>
stream
xœ½\û“·qÎÏ'ÿû›wU¼åà1TÊ©%9fÊzQLYŽíJŽGŠTDò(¤ò×§Ÿ@c³»G‹*•xwó@ãëî¯óÓ¦Û»M‡ÿÉÏËgwŒ›§×gÝæéÙOgŽnnäÇå‹Í½‡ð€ópeŸºä6¿?ã7Ýfô›1Ä}ç7_œýmëv=ýwý?þ¼\õVp{7À‹ÃßîÎãöO;·OiŠiûÉÎo¿ÞûíC¼þùî\o<Øx±ëÆm‚¶÷pÇû7·ßîÎ~Ç‚‡v<°õ0aãzÿ?A–®ë½#1äbÑzxo=ÏôìLŸ;—öã°!îG—ÏøÐíö%þóÞv8‡aû=þýƒ\Ûktè¶ÿ­nŸä»tíQþóQ~øynúÿy.ÿÄq€ûi{úQ´?~~Ó)/¾,olërëáwÓ9Ìn? îáàþ¾Å>ëÑðÛ×õç2¤¾K´’çÛ¯ê÷~Æ?ïȃ }?´„43y™ï_•ûÏìE¹=Å4µVîUî™/þ{¹xüIž†/Ü´${S.^4æœç`‚­2nÿ
~õÝÑ©ø¸\½®À_#(ûÅâªÌKy
—:„É Æßw•Ü}0m\܇8xÒù0ú}œ@çÓÞ‡4ñ;	¦£‹~ßÃŽLÛ¶¨óã~ î¡›W¿ßOÝàA;<ì—&\S·ŸÆ0ô0f|¿K#ïtöôó|ïºÉoÿ¯¼"íÀ6ŒsOLÓ“[ºÛ{?u0#´ÓýÆ…Š	D¢È¦ˆÚ¸Ò;íªs´@|ìܨ2EožûûÄ
@и›â0˜ûå·À§ýˆš‚ït tïA‰qæzî
¯$þ2ÞÔ¤c`Ýbì	åb‚6`?G˜wiؾÃ÷aì (°ð€rfJæ)«Sˆ–æ¸
ÁÎn‘ê%©â>ÅJ¨»ùþWÔ•‡uH¤J#á¹A€Î±z<À†c¸ÊŠrSd £‡”ÕYT¦è‰ë† –¯¶—ç¹÷ ºLöåÚ—';+jݹ‡½ƒ³
Òô(¢§ë&ÁËcßù…°”¦ŸÇkðÎc¶j¼ƒM „9þó-vHÏbCØ Âzñ•Þ…k¼§/J#ov=*ëÀO€º“TYשXÁEz!7"cÃ!̾¿sÿ/2€@»øËÄ—_Á÷&øc8,Þ¡„O0OÑ)LP'ôè5ª#½ˆM`íÁPHC( ÞÁ‡FÂú×ÙxÆ«à½Ìü·¿ËÆ•ln^DD³„~
zÅžç†uº:ž•#ýü‘D
!§Dš¬íÿ¹NÙÄ^ÁŤEÃ"zFlT\t#:ORàô¾Ä»Ž4ŠúúbÇ~.BÛ:Ð~îµÛ؉EVJ<îŠÛÐQú‘ÌÁ'ÙË#íÉ+‰Ï¾°ÆÇ¬2¶è}OóÖTƒØy™EØ_ðKÄuv„äh®zšK|Gu¹‹"œøæ›]à©!e¹.~žG¤íƒâˆÀ„ÁÎE»¦	!7»$/a(
ÿFæ»W½Ç}’Õ7m°ÐZ¾;ô›Xq¾çáþšâDÒ+GÓÅyÎŒ}çIó:i0¿d—µš9ôK^»\(!:NCO«Œú »>ôì3×þt•¸Ð±58Ú¨C Gp£Òs×ÜnøÇŠ>¿+ਠhf“:éÁ?Õ¥Æfû°D'–sÚÞÛEëè›öu¹Jù…qôÒª?¤uoÑ’äÕ&iqß…¡ã?p?²*ÇŒ[œñÿ«ZÖIU®@E<´ê¡G8í¯:7*]­®[E*éÚ®§b
¿´ª}6cÔë°†®J™`‹_ŠC4Ãÿ³5|бT_,á1Ë	°(¡`¶Áòlà ÒÔùHúxÄ¢/’|™lÍ÷YÙo‹|õpIÇN•§ÈŽ“Ñë±
g[ALár;ˆÀ¸Š…±¡ë'94ÅÐZ~ý\¼~^^Àáº'lRš(18¿ØôÀ‘u¥Zú¸¸5*K¹³ÌÆ^ƒ“¬V›«åÉe¦è§‘æÕhíh?ÕbúÑQÀk`Þ*¡»¥Å³›ké'§Nëƒ €–¬		(9ÍçÒÑù*£fß’œ¤üM¦­
aoð[ؽ".Aôê¥ú8Ä3{ñ„†¥v`!Ñ *x=ü ¶ÞOžD³ûX—½ÀO Fp)‡LÛãömíî²R!jðQÃðÑZŒ]±dFj…«+¤SÅéÅõ}ƒfB}‹ñšBdOðWº•Fp†^Õ0–ÍÆ2(4×èOPsê|Á6Eï~¹Ë£…6NdÎ*ø¬á¨Š;b°
çC÷.eG×¹`ÉÛ—o¸@᳂½Ê‹gìR6©8D74ÓØ ñŠîã² W"*OH¥
VtF6ZˆöußÔÆ"ãµPy]ËßSCh¼¾Ú0CÔ!F3P›ÀouÒB!§IJ%'ú¼Ù\ô×á£2jÃ=lad–KãÂÐkÀ¶PÛÊËâ¶+@3þ1OiÊúu¸\»#2ö\Ôf»¬ÀÒ„„¤yž\Ý:E‡‹©›Jˆú&‘SÕõ†WšmÚ‡ýb;œ€?
0º¬ÒÍ9˜[¿ûÏ}ŸêMlMÍ2^Î;þ|CÈ+.›"ïÜ’Xm°vJ´µ6+¶kþê‰ ÁHÁ6™oû‰}ýT©‹YÿüáÙ7g?m@¡Ê6Ànš6€gÃ~˜6}ž
ØüËg÷îŸÝ½ÿÅæõÏ7OÎîþeãÎîþ	ÿ¹÷õ§ðãþg›9ûüþæ›[&6Ð]N»Ùw'7ÚÒâ ×¥MŽÅß@ڤݬI»®¢Âøè=%“ãGöoÞhx°:ºØG·Ÿ>üè"Dsý°6:ãHÉò` ¯!Ïá?üúÎÍWˆØìѻنe©Ä~–å82ŹNjÐP!Àkê BødÉ€Œ~o¿ârt®n1or"òž[æG 3çºýsô;ƒûòˆ]ÒËuG•dÀ“í‹X?'hï§hÐE5ˆoT	_{ªd<ž#àJ Ì`®Ö‡ƒ­`¶m©‚æq_²_Ž~}ñC–³%–¦lÝ™­ÓWœluÔa?;<5µãQÙò¾öLDÛV‰z&§ÿ²3,wv\ñ0¬/‹Åz*B÷d˜*›ô¬„µÅÎ{hé3ösf3‡}àºbwØEFÙJ|U¹Dca8gîÉ+K§jC­€ÇÎÒ+!;4[ÆÅÍ£¾Ì»µá]kã¯òJ†e=)Z3˜¿HF~;åBjeA/šTt2Á.E¹rSAPíºÎùA߈(r\2ߟ‘ò1e,ÿHr!‘„ŒSÞ™8q˜‡êÙñ´!èy Ç’ÀDQPNe‹Ëû9O3K²ëcëÿ^©/*òY„¨ýáÄ®ªCOD4çF5G^	àá>øngð,ôÝö¯(K"j±¬'æ¥'2-G©pT{¶óåæiM˵hó‚äïg³álE‘©øÊ4ÎZƒ>E\LÆb5uÞd“,µê'ÖZ4Cóeïçñ1Ó1ò%1Fõ43Õ¨N¾MŸi®«&€gÌÄ yÎ$Ê„‰iQ[61y~@]f®Rvï}b™“@¬WÞ°:U¦hfŠf\.ê¾EÚ#WÔïI¡xf"¦ ã53KSQ’Ë$™ä|›ß¤;_å;¢q>³8ÙöÍyR,Í`G‚ç¼O¿Ý(kg=:³§ÍÖXÇ"i“«’|³Ø%©ú^ÎSeø95ÝDŒèYtÝQ‹Xø‘r€Gé0¢Yzƒê:»YÓ>dʛÒ-Ñ‚«|mÁMb.:ßT‚œ¬ä*£èw@Ä ÈΈR1X·ÕÍÒµI´îBy¤RßHdö<w±š' †°eÌQ¡v¾³ãÑF’ìXö…ÔÏw;Qeâ†\iì;JÑ¡² !ìèl®Šõì¼/«Š»b7VPã^mã½4ŽVÆ/³ýQJÈ/#åÉ/ËaÀgìxA7ÍOüïÎÔ-§™à+Æ*-F\j¦Ùa³imzÐ3b_x¦I‹h”âŠgóYõ¢Mq´!«r“XjÔ˜K”šŠO³]82|®JLàÓsI>V•˜bº,ŽyÈsquþªƒvDÄšý®àÕ¢u=\;£#Õ©´Òt£µµD¶áJßNF›Ñu®Š…ðV\ú;Ó­ü.òrÁwA7jâ*Ó
pÚï@Ý@fFõY¥Ë]Ì1BßQ£ÏôQѰ’s4DßU
°%÷Šƒ<Ïp è½«s<³˜d_•ªõ´tÒsÚ"«”*Ê0ƒß_öÊû%	b;}#„@ð$…r‡­œÙyºF@¸î…ªîMTv YæÌJ•³@M>©À;ù§x‰Ñ»Õÿ"˜Örd¸<S5¹úS›<6ÀŸªÀSŸ¦ÃÅw!qlz:[NãÑÂ)ËÖÊPëµeåó*ÑògJí±2°™4@CÝ"xíÜÉÂ8M±Î‚
¡b[³íKVöŸÑUCaKseÃHÍßv+Ô
±žÉ/µ­5î"S¸Øcªê`–à•+Áf)ñv,[b“[3¼ÇîðДjh#w{ìgz¥C«#×S˜“k…V‘KT’že²Q·¨¨uF×
ãÓЯ&gu,øÃÖQ¨œ-äÉ,4yZ)Ô\ç¤׿ŠúI°\D ©2uQuÉŒçB¦
ž<\Ê"²¯/->è*KÙ±áö\Ò—YVJÇÀ}õ‡Ü^ÖI
Im¾Âk#L)$Žibá+ÔÆˆõaô]žpP“aSm~Σ]ÌLÖ:}<á9‘NÞfφ¹yä·ñ‘g+bßÚía|æ’ßO0©vŒk©9´Ž\ûÜñ;3µîh‘¼ѶÎOÆU©¨Nñ%Ò–‚;÷ÕÓ$>dû欟ÐÂab¶)![ß›ëÞFV¬Ldã;³äw˜xcq²:H&äíΗÊ?»«5/yÂ×,¢y•Ê뇴ÁÈ'姦i¥ J„9¤zålW2 #×현{Cq?ætÑq™2~»?uk2zÖÐøº>øÈÔ @ç2#³ûïh?fkÖoà¬9VÕOF[ѯâöИjˆù«¾a<—ìO,Œ• õ]ÍË¿uûŽL…Tì4hÆg±€ØßG¥Ós,ÆA¦yM°ÉÕÇÎ%ìS7‡ÿ%ïTñ=O•ªŠI'ª!Ç‘TÞz²*UÉNgY$g'Îh´ËßËJÒtÔêÕ^r~ð`XÖ²Ìm'G`o‘œ²¯Æžåq¸j9„V­jÂÉùò´¹ÅÖhéÁûÑ™Ø4T Òzf%ÇÜU{ýb8ÊGOöÈøïGì[.	¨¬ùSqLnò;
Ôæå{œ8ìLšÇž’r™¨¢	ò5I[J^½Ô·,½
çÊ\›“–Ki¹:©º~g¸·²…’$ì–9,^»-'—¾J6d(•ëº%c\ÿ•J)w­C£Zry·tM¶þùìádzÒVÆõV}zbÌÖðáe¥#ÊòJ‚½*I¾š-°Sñq^ÊŒ Êòë:ÓÖ'ªxôqôøóƒÑƒƒÇŠG‡ýäsÅ#NÕs>ÝUäú›¢Å8BÌþ’§ë€V$¯hñ_æ£9¡hvʈDç‡î0¸cC‡ù¨Ú:ÕfœÇò6b˜åäF¶ðâõBÒ¤LöøñÕÜ–¶|3Ú'ß壟èN‰ö‚[RI(éíEÜz~ËJ°b‘åÈfäRz~¨¶³O¥|·³S7Ñ€_ÇÕ­’1sšrÜeŽ ëùpŠØCÓ½èø$J!‘N®Sm.É©®'•^-?¤“ŒUi˜È9;«¿rò‹ftŠØsÙ)?!¯n(guù—ĵ\[¬k/®YäÅëãp{-“0!b0$î<‚¼¬,n­S³m!éøÆÙQž…u‡ÇÎŽÊáÎc%fzl´›ÖŽê'dfGp¬ƒAJâ¸bo^—‚µ‹#ÝX*'ß—x÷ÌÝTŽWö8Þ›¸±jÊ0}š?ä%­X²Ðþdm“íkk,SfEa¤GGO¹!>Ƚt¸Hq¦¸!vk¥[;äó4øôË@´ZÈ!´X9€⸲ÐcÉi®Tj.ÚÓ”¨º\
žåͪó…hnEOQk•ÿd°°
m—u¬yà3#†Î²1U»g<ƒ’Ó¢ùèfõ"£#’ìðÈÇðowPýpÜI"VŸ(™§…°X«L5ó¦ua
„BøïÙ‰­™vÞÖ“êuJq)~ã —ÇWlõ]Ä-q¹ï«.æ·hsQóÖ!Ù3—f}™ŽHôý®Ïžf6MeKjLrÐÒNÎÝ~™¹Y?°Z¡Ù²a­r&W¢U[YuýUOK´Î¹Óò„Úü-øˆFƒ”»KúPíô^‡~”†•Ù8V¡8Ë-Øz™Lë‡7tcNšÞ°ôâ‚,;Z•¦¹ÛhÑãLæQ³®Á¬p‚qÄ×¹dc˜2ûŒ[F¨¦•^~ò¥qŽ‚6uêöZpp”ܤ<»ZGkÄžÕ'•Œ}ËÛUhT
ʧ>ªD•~UÁWqO•A¹Ñ]Â)S )'߬î\Ù*òþýÎr¾ÐTöݯg&õ=©Ü 䛳ÿHe¨endstream
endobj
630 0 obj
6250
endobj
634 0 obj
<>
stream
xœí\Ys·ÎóZ•ß°oÙQi‡ƒkŽJÙU>d[)Û’eºœDv9´H‘”—KŠåèß§4И%Y‡©\âî ÑÇ×Ý@ŸÌ›ÚÌü/~><™íÜïæ‡³f~8{23Ô9OæŸìÂg ¥šÁÌwÍøI3ïì¼s¾nì|÷dö`1TaQWvèsÙõC=ôíâ»jÙ.îUK»¸>­–~q¿}c¿ª–¦†ÞÜöÏjxÜgÕÒ™P7&,>¯÷îâ³0Ÿ³Üq/?}¾â ùýueñ¬ËܯúžðnñxÚ
uÓôСnð«±}ñýãjhà1ø†…fq	¸”áÞSõuå`>c`¸ºšÖ,¾¦ÛøœÇYëïiUÚ
íõ ¶ £ë,ÏŠKá¾…nXé7ܵ¾‹ûÀ-ÐóÓîßfn0ubÙÝQ¨‡¿F4M°†Ö‹wdUZ>/íÜ7VK;uß7F¦6°8þ)ã襦nûùÒ5ug†ÑÖ~«lÓÚ°8Å
àÚÝâiåZ–Äs”Øôô¨&nqPùÅî
ùãà™°x„¢6¤Eç¨Øv	ê„»Â\‹cØÄ5L‡ñ¨{0”ž9`uÁ)Ïp\œÈuÐd†Å3¤'Ù—Iö#±Æã,ÆSšD&ô4;޳fQãŽx’´"MŠƒÓˆ=yÊeéÏ^"éyÖ¯ß4)’øÝ4µO’>bÊöeÌHÞ9/‚üŽüÁ1O“I1­Í´FiõH.HD$„ÒhL+\·4™è龚F4ëFî^Ot#ÓG:KÝHã¿•Ùåá+è¡’^.ãÆ—ÆÕ¡EÐÁýk9û¨cGÂõuÖbNEÜ"Dµ¡'$Ø6ÇÁ8R	sÝH:ƒt¡Ç_©Å0À#£{Ó”Ú›•a¬¼>ŠýÇ…ŒÀÄÔÈ­·`ëàï³ÊvHcKJŒ,º½;ûvödî\ÝDƒ½÷sÐ¥-´€®¦GÄÿäÎlçÎ×ó§ç—³æf¶ó%þùäÞ§ðqç³ùŸf·ïÌ¿Ýê
J|oଭCæ-à~çÙ%üX1'qSqß'ÀΨŽYP@ÏñÔ@—í-qìRÄ?{‡Üv‹°½q¥ñŸ#ä
C0¶´/o™B‘EÝ3J¡Ùf…À½8uFº™Ávp`²j\W¶E€°j®^çñÓ’¤â64ÄCÒñ0ô¬ãcp-Ã*Ú¾c !¾ŒÕ9wcÔ!gÙÅöXÓ¢¹9gKüÄ™t‘ z:’-þ|‚³\Šé­ÈÏ–êÛ0‰ìgU@åhåËL¯‰VÆ+?„Hø
Ù‹!ž÷ÉyK.rÐŒ£¾ön ¥…G;$E3ŽÆ=\¥ÿ¢ÁL‡S؉ä-vH[þN˱ÒY¡€…ö†iË„ä6õ€œ÷îp¸µ.<ýRX°	©¤?É©ˆ£=-1Uäl{²:ôÖÉ;â#ÉX‰5Ì Žü:Ž;R˜Ù؇…M×0lGõ%kFBg¢ “Œ‡Æ–dŒ<¸	[UÂXÒ´
sˆS\zÙ®­]HêµNjy)ž(j‚s‰‘†ð|ñ!©Ý¢Ö[ÄÞ’¼±OEµ4޶œ]î©4ö<†~òi†“¾¿â~ ·@õ(Ãô)«$EŠ_QH uRøVBàV¬²]Çøˆ+úm``Ia~GÒ´;éÔâY·±I>Eu;-ÞÏŠR°­‘PØXÈ’¨h‰ÕÉa‘édEÀÂC§¸pB|]Äš¢Hs4{-ˆô¤Æ=ÆÓKÛ[RéhY¶Ã Æp¢Ey×÷H¾-Â_ÒС«]+
Š$F{­ylM¶ø_ÄbF§Ó‹£,ñÞ!Ò­;+ž|‹°¢tÈö¤‰g9ó¨œlž¼ccO›ïè§F™7Ce¹›LRÜpk[VEfP‰Ž›M…en c–ÐX”kkhf,€"„´-(<†h¯+43WƒUêã2×BdéìŠÚ×QÁûi
×0A³%Ái‡d¢ø©4Få5á1QÑ^™užà]"z^ô?‹6)¾¹å¼~ÒeÏ!N,ͺ»'Ow‚–Þe· ×õ´Ôtd¹iMHvë(Æœ
Äuf¤‹c¬'ªY¤…Ê::ÛpƒS¸*Lù¼!
 5í…ÇÒá[ð›áôЧïÚMÕ	,*ÓBò)P9Õ©|ÔÎâl	g«2Ny ËðJÔÐBŽIoóeÙéåØ3F…9oûT†J²­‰åèh¶¢.›ázššöfqj‘^œ»á¹¥8„ž h+ÛIJ¥2m	!žßARt=ƒ°Óîr¼#LÚf	¡aÝfDæGŽ˜@¢ù0öëÍñ¸¤DØèûhÉ>ªŽ¸ëg•³‚¢BlâQÛ1M%.›ñ %@ûŽÒ5è´táêÉbˆnüAóŸ¤DM¢:šBv×r&ÔûtF‡ÈÖ²0²¸ÓÄÅxÊxçÂ,ôŸ
:9É|²Ï8ú‰:±É‘NÚP	QÞÕŠüœ	ee#ì+ݵJ="~‚"§c!Ü;ê$3ýè\HûHzSR˜3LJ«¸
ú)0G†¿ï|Þ¤Ï麂ª˜´;£“vYAqd¤Þ1gÒ1Ÿr¼+N–àƒOëÔaATtGæÛ*Ñ'cùU?’Ú ³‹ZAŒ"j¥CTÚxNšY'hÂUÇ)üø6ªœÎHbd†ñS[¯c¥Ácí½`©ÜÔ¡60v@<Š;û¡¢ÚJº«Ž F¡ŒÓ Áƒ)@ò
p°ó4¼pqöÏ[Ôí…Bðï¢A
¦ýqòª
¤”xÖº‚gQÝ<ò,ÙÎ1n5­?à™$ÐNÙýqlä-3
?ãÏßðÏy97ɽÇi0ñÍ÷t0¶Ø\“àAŠ£ÁØx–Ïu`m¡ï6¢ôå˜æ„ªºc)
Í@ò»™ºÏÊçhs·â@:X—žu¦Lñk?õïýW5>ŸÚøAú†‡¿¸}•ïæg¾I_äÆëGúOÁ³Ž'xMQÙŹq5A±r|·d!³•$:Vqýˆzùz—!	L«õb·åC -Œ’6§ZO&Ç®óØ§¹õ¢ØIâXð?ý(RÆÛK´b¾pÄ4<_††Ã´›àˆáœkÝàËÖ7¾–™4Ê›WKgRÉ.‹MÅF
Rùë_Ëí2´xý©5ÀkãÞDÄŽøç—È‘ÍÝ Zu-™n^ïhËH6r
´6Ùv”Ÿ²¦ÝõÛ
þªéµºrúÕÔô‡WO¿ššþpbzt`d=xµçó™¤^H”~µa
j@²dô.Z•6ŸÂ¹¯0Z—w¨ÁUðY£rˆ2à—Icÿ)smgdµ;²ÚG%øg>/5ñVÒbúvY*0µýZöÊO¡ñ±-Y°nçÆ©nŒµLßO?ý¸"Ñ85ÏÁÔäû%MÞ Ï²wMNõ«ÙîÍ7áV³œnQn衞#ŸNÀÜY5¶"XèUzШ·o×{Nžç´£eP°µí'@á9жcS|õô£j^»ý»ÕuB¥Uüã;Î!^*OÆ9ŽÆsBñ>¿…h{Œ”^sÈT„*3WG?gá?H£Õ‰ÀsíH´çmÚwéìh3YOÄ
¯ñèˆs&÷ÊÏŽÔ)ü›>?*í/ÃYôóýùÑÿ|nñEÕzcYË“´Þ²ÐD¤ÿñ¿€FÈÕ¦WgÝø´Ue¯§øj
s_ã-˵	I®qõ¿¿ÆU½“kÁã/+梧C–ðÿ¸À©®“·¹ù5ÆQ	ð–xl[ЮIúÝÕ®ôÊÕ·³ÿž’endstream
endobj
635 0 obj
3609
endobj
639 0 obj
<>
stream
xœíÙrGð]ù½e—Bëc¯—T%R. F©Tb(b|È&’-,ðß§»çÖŽdÙH† •Ë’¶§§§§§Ï™Ù÷ݵÀ‰Ã<µÀ|‘×ð ‰WÕ~¾4ù3‡y~ùaŒü`1ùaŒü`y‡Š«+DåÒØî$AeB¢'³Tk¬h»,Bðè"..eLå5êO¤ÛU€kÄqäÞ¶º!îk‡»cP=ÁŠ|P,ª(Ñß (HwécQG§‰­Ó¯©y´ë%’ÃVóhx|çc [ÝwÈ0Öbc¬®ã½ß¥º¤\xtŽcÄN^I†2S0”Чhên·Ó°Ÿ¼J¬„¬ýZkò†Ú°‹¼!÷ö ”¬ëw©Cˆ°LÎ.æh¸")=¹t˜èéç80%=Ю>w˜Ï,ð¼h’Š´,d,jš«f³®÷ó“3·‰ö<³® dR÷QæÂˬ”3æ‚’/òŒ×3ùb0¼9Åû&sK-»ÙÜÀ¢\œ[NÒ ølbn‰¡\¢køæ6s–HkÙ]’‚;
䘚ià'<޹±‡†Y¥¼{ á´.ÖÅÛÁëÙ:ó‡Õ¾zh³/eª!±ÓÆÖâ,&ÌãÀŒ0ÍßàgýwH¥$Èšv}‚ ^.•Ká9¥,˜>©4
ACÈTð{¤V_ê´¥QÙ*z!	ùDÿ‚òD4M›Mb‚.“4yL/5yµî|ÇZÄòKkT¨¸}0êáJËÓÛ¥8&À´£üØ?ø˜7ózÖ#Óë÷ÃóTœå ëœyUutÃ2
¼Ž¹çʼDgù(pó'—éBû‹:ÇÇ(Ì1iÙíâ…ç§#Y‰ù¸¦¾b%3&êåSW-ÿÐvúT‚KtÁ®;zM:%&W‰^RsmkOå³”Lâ(œVчNGŒ'üÂþxyG|[´ëpÓ/}9翺-þ[x°íÿ"òÛ-þµnñL¤ò\ц–aÊ›opöuFúè@‘ð?ŠBƒðn¶q
nÃÿ‚@Ùx5[Ý-çÃï’ÍÙ_S¢aÓå[Ÿ®¯|G{“C=ÏÅý„úåšÐÞP£ÁâM•ŒÅœ­dœÊn+™m%s‹JfÆ-UÔX3¸ôWUg²ž³;´Í^úzà+–Y«èN]4+Æ)p€íæk_‘hÕØüäwþ¼¹ãåÍ\¿gxEŽ/âóX.QëõyŽ”áw{*«†ùh…1·Æ	FZѱ”º°òrµýë8‘š)…ö¹¥P«ôùÜzˆ¶a+éµN}⦊ã‡OS¹Øü:ÖŠ R½ý´ª"H/ûFAZA‹r„ÅE\¢"´m~°QùÁâ0ë7«»€qIý!-èµ,Õ€GaSu%É·Haöðä‹s*æt
áSw÷hìF›Ó-{)°
ï> >Õ¿l”ÁâK¥Çôª¶á
#ä‘çô^YÀFx-éÜœÍ1InQ_S*i¾t!J½ñ†Ì»cÓxFgƒTÓ5<㞥ªWÊ<îÑ
uöÜlÊèæ”½©’Rzo
M·f¼6W¹4âQj^5OñÚ g4Hª`Ü—;tF±×êÆy%/ªæï‘	<Ú¬“'Ä¢Ò½€§ÑÃwÝ IÍñrfäU ³¦#ÏÞ
Rs¡¼ÈG³VZ+Pš‡)Þ`k„ò,ú6Û©Ñ´¡tƒ=Å¥%ê`¶Çõñ*-òÌu4ÌH°ÐU{ºvYˆKiÎòj£ˆ]dSæ)ñ•Cn4ÉðlÕùÈ(ã…Îí7£áZ»ªÂ»Óä[ZÔRôM¾«zVQ´¨„wOoê”—×¼®ÁpÐ\LFq€ï¨‡VaÏxm!œ¼„¯KN¿Æn0â˵8’JÀÞ\œnʦÄIõ2¢…™õõý•ŒÓÌØy£2ê´ÞÑ9øÍoô¢“­eôªàgVfƒ0þŽmzæ¢óÛºdÙíTA²é°*ÇÚiFPµ³UWcÿ»Ó©»—dƒPg·%Ù¶$Û–d÷V’}¡—-÷;¿Ãßä#õendstream
endobj
640 0 obj
2333
endobj
644 0 obj
<>
stream
xœíÙr9òÝËGôUºÐU*éa&ÂGÌs,ë}`b¸ñà|00_¿yèìªv/0»¬ƒ ]%¥R©¼”•J½‰NÎþw6î>fûgb¶¿ñvCRç,üÙ=šÝÛ-¡¥óÂËÙöË
)gƒš
ÚtBͶ6ž5¾í›®U¥¿óÁùÎ;Ûü£Ûæ—v®šøó];7Í÷ø´°Û¹ì¼wÆsÛ¿ÚyÏp÷Û¹–}'dß¼„œÍ1üOŸ^Ÿ2ÐÐ7ÆM ñ¥2/ú&Ð fÝD_Qt±$×Ü¡IÎGqK.øëh·‹#?ÁÚ2×ë eìbó ¿ׯC™šVÍ?.¸ãóÑ©_3ÒÓ—Dz„¾vKÁš–&£B{
ë{ud3íý§ñ'q3ìó‰Eö‹ÆWqºúœuœ5&ä|jάdñãt¶|Å\ÈõôI쯕îÆü$fíð9I;¯sªöEÎ5až“Ÿ!ßP0FÒÕ$5"±˜'¤¼ä‹”n«2ˆ†‹U6ð$ReW¤ÐQñ¼÷ã:žàB&SèÚiÑ—¤Ð§SkU•¦æs¤ÖÎbŒÀÀ/RÛ^Bõ[ê}VÖçÁEí"{_•ÁJ%°ãä4ªÍq9´©£ãìבãçN‡¹™46VÕÙ0#«l˜ìzpló8]/¥ö…m@Bd©¼V
e<©pß9a±0Luƒ•Þ¡œdç
qÅ~ŠaŒÐšêèB÷J§š?ó€Gr”äðdÔ5q°2XÐ÷Xa¦”°7a}l§¬zªùD§w[Ø*±6’*êïZÑYmå`ÝYo=ZשÁ
b‰ð EÀê\sHðƒ‰tc9%ƒjÔ÷4ü”
%{9’
C§|ÁC7(ï3Ü‹<Íab:—hëûæ	6—1_‡òèaó˜óShŠKJÃè‚rf£PuV 4Ä?IdçûžTLÜÆ’Ra±<[t¨e²ãf5`M1jðß7 uÂô¸X¼ŒÁ‚ÊΩÉ2k€*Tc°ó@ ŸÖz BRå7€jÆ	Ï)Îé”ÇM>à<‚á=ÌÎ_OƒƒµjÌÏ‚à·*Ž'šÓ ¬kæè´¦SË>
Š<“ÀG¦rÈ
4>²L^)qü¨åâC´UMáE®×|É;GY§ÓÀU·'?…]E$öRZ1+®W_ÊFã¼TŒ|ÐV9ãéÊÑ0è
eóXíU*.¥.
ólÆX%º•(óȜո©Ò“Ø'©
˜Ê]½ÁjÌÈÉ£ÊÑZ¬Õ6ÆÓ&°…s8*!µ¼º(vU¦Š¢¿²n'<(êŠ5ÙV%b¥jZ¤$!A+¼†¼·r.œ{]dMw„¥²öª*¦j§䩾6|vRp=ušKéMßÅ:ö\¸ŒUར-?”L£é³ª¬»6&WUÝѱŠ*¢>
ú
—´'IîðÙAÁŸºHðÍÑg€1´Ô¥#ÖoèdSH¸âB!4ÃQµÊõö±Ž7?àeë(=%B¼ßj}}ƒ^SéñSt ¢WÀp¾çí~›h4¼¾B`ØDviÙ»¢^?¬$×ç÷¨Ña¾JeìÀµè¹¿@M‰ñïóŽy µÖT|äX” kb¼Ñ‰Ï¬˜Ú‰Á¸Úê©´F­ºR¡„TA¶-ÇLç‘•Jêxó¡T‰â¾GíævÉæ
að„H+Ũþ²«G£¿)íDyÒ½•TŠòW7t='4>	9ƒåyQi~l—	y=aïÒeŠ?ZEîËä=`‘ÇÂ×ãXiðÕ~¸I…!lÏWðÆÝâ«áRF °þ^GˆP](ý-®ÅË¢O˜ï·f¹9ª
iPS³Cæ¼"ƒ;Þ2ñºR'å5"N_‡ˆ½ñâ‡iW·{ÖoPx[Ýn°S£³ïIŽlwÂ{iR³F
ù&ÆUÅÑ1Æ_n¦ðøÝ昶òþEX¾\qOÂIÚäJ·7¡rorâÇ‚g£wmê«6i^ Ld;D«Áyy¾åk aÃ"NP±ª™Ú¯xÏðœ®C5ÚŠ!ÂmlçØaÙ¥ûÈÇûÚíjßñ>Ñ—§ñASÊ]ÕÒæ‹f,uer¤D;^ò”…jeÔ¤œ$Ÿ1r&Qie8böÛFT
YjúJ,·R@ÝQíâ³EÄå"iQæŸj£JFjUw)pž–?¤X.ÙõÅè÷ÉÝ-…ùòP¸–D÷[»/\ 2Krz‚nI'm4ß¡¤RÆâ¥--$±ÕïBâTÑö¤†®Åvð”œZf¿!e‚8èoû!ö¶¼Ûò·‹ y³Œc ‰íqg­Â¤‹¨^!NJ.R­õÓ®ì›ì'nSP£àã:{ȸ@5”ß¶T™@$mi|OäëUèÍ+eà ʰ˜]¶ÆMÍVÁiÞ;åO’÷‰icqï0†+ñ½º•VDÒ“w'Z¶³ävŠkeˆ¿U(h‹û.q'Þ³c…À“,ë¥ÙU^ÕË’·¹Òý´Â(ŠS©˜FºüTj?¥3S]gÇvc6³È¢½©SiG_¬¿›Ó…¹Ú¨8ˆÈYè"wµÛŽÓ¢tGÂǽ_þú2©ô3‘EžuòÈ)A.®(Mü–2–Ââ°m§$jœ¸-¾2ù*G:NS_'Y\Ì™‹dñÉ„ô–Ò¶=æ Fʼn\Á{÷fRÆ‹(Šh±£8о>
stream
xœí[Y·~_ù
ƒ¼xÚð´šW7û!âØI(v"o€ vì!í.¼‡¯®_ÖÁb±»gv$Y>’@ÐîL7Yd¬úªŠûdÕµfÕÁ?þ}rupïÁ°:{vЭΞ|¹â_'W«OÓcÓ“vìF³:|t@3Íj°«Áù¶³«Ã«ƒoÖ¦	ø?6á_‡N³œ©f9Óš>M<Q4&
î\Ú‰£UÒ7ã{èœMt\‹@<¿ÿ{ÚK×kpüPVÄeÒÖBš7–$Ý;-éélëã*±ØfIâ'iÙõ9ü8‚O‰nDn>‚ï×ðã~\OiU³~_¿çÑný1N¹ƒÍL“²@OåáEyøL>.‘~LJ`(¿¿.ïÑ`@÷N­ô¬zÏ–Þ.-ÿm“?‚$7fhmìÌjc‡Öˆè.D@jàû…H¨ü7|=ƒå->;†(½ÂaºõÓóCRrÚí½´hRe^”&>*ÜœÉÃãòðD/ÁE›>c›d¡‡³~»†5k–”
”—ÌWe;„‰2OYžÞ»4Zö{SÞ_.Mº•‡W•íøqH_üú“"®Bô¼=Ò{¶Ãí-šnáæUyøX>\\þ×¼]bù¢Ú“Z>zA±¡ú.9XTlãÖS«GÒ竬>aË-ÌsÄd„AJ1J[×òð,ˆWL>-#.ÿòpñø²÷9]Z¹íxÉx3\t'K+_nÑsvQムüþu%V©×ÞèZÎîýƒÃ¾¡Cy#Nêl¢ä%×þ\T{Y©6N4¿ŸÑþ >ÞtnH¦óÞ|¼mÿ³ññs¹Çߣs½‡bG§_“.rÐÀ»ì/þþ»Dø÷îËè¯Ê~¾”‡,ï™=Ðÿ\ÈÈë(&i+¡ kH$lÌIÕÑCCÁ
Ï®
ô„¹*ôÂ{ž¿á¾e„y‡ƒñK
6÷X_¥f>1†Á'9&'(Í6ŽFOí„ÿA/¬^H.“Ž}ÚJ»GQ¡ðSÂ\Þ¤ù1¼€)[¼RT„éÑ9]7¶‡ôס«“j‹ñ;Ǖžmpð@ü»!ŠKß4IzHådÌÏð5,.VîŒGMâp û8ÅçHÀ<9	;"pÆ;š÷=í¿ëzœ{
;§×H@¦0çÚK˜ Â¨,l±pEG)mCN¬ö²Ù«ÑØÈ“ÎXï°	KâM09¿—¦Àéè:dâµ¥Ôý×´®sòC X†\K>¯†¼j"˜¦ êáȹ൩2ÿ‘f6?QÒ1OÖLÎ9˜¸†G‘àçlø[âÅ£19’®˜~x´	¿Q
gD	‹)@5’
U¿þMzF°\N§'dÌEk¬V;’Í1y¡Œ›K§Îò¯àfïn]DéVNŠŸ½æ	lèèbÄ%ßc^æèy
ó{ô¦Ç_Á[s¬xÌàø|0q[F<øcŸ£¢
M_(LwúaÚÕyv†âÁ>„™¦ŽUôZ­(‘(GWñP•å¸=ï1¶}O±-%#b–½ùã¦Z«x‡#òЉÊŒE–€2+,Ã
c\ôCÂ8¢kåœT ;ÊnRªäTHÇzù2õ²±eÃ>kÖZFz{¯býähšDId…1”èôˆ°jÈNlæAÈÆÙ¡2=@SE:d¢ûuBô8ÕãD¥‚ ´êÙ€N¢BQ6ÔZR eˆESž‚ŸùEðaXˆ*–ë &oð”ÔA^^b„sŒÙH±»6c64pƮϧ·>À&Ñ9øœÕÑ
b&¡÷B½ÓFm»ÓF>Fµ¦:Úfþp€‹x¼ªÙdYÌdmZ$>Æ;,W¼%¨
èPý£±„±ÙdÒ€tÀ^Â/=&ë]5£p¼¥ŽXï).
Dʆˆ	WlO	bÄÕÅ<Ócüqfg“”'‰û”éh‚9VÉ,’QúäáÎ‡ù\ánÛÖd›Ùá%ÜH^{·d=f.’¿xQúhç…4¬tÒE¹yC^¨@ðÅ›¬[Á'ÂÙÌI]'éÄà/lÕǵ·aü™ÅʸZ"ŸK.B!•¦†-/ŸSÎí4Æ@ÁؾGx‘ «E²>¨–áŒR‹²³”`2ú—F¡ü[³RGwæ²ày‚ü
2ÂsëµÁcVÖK±,Ñ”X63怆â…/™bÆÖÊÕ[
‰sðTj®ñr1#å
AòPô‹Q›šŠž$ØyŠ{â
™šghâ.#¥Ýµ5‰ŽÕˆœ§GôDšH‰W©ŠSÀ4Ë/é×w#ãC<ôª˜ÇIŽjì$Ú]ó×%èã’ xUñ%›áB”©U[–8[H6W¿àñ°e
{%×ÒÁA̶²w&´q`ËÑqY$z³œAÔõ^ÕM€ut¼ËæRôZ>bT% |1¡gƒbwCÜÕî¦2†¹â±Ÿ€*ÆÆå%br]4ƒ>Tfi€Ô¥ëœžçšÐs¢’pÄÀh»ª-±%¶ÙRú™
‰þ.·•áØˆ±Ï;PL>–´sCŸr`5Ùª_䃂ºË’‹ƒ]¨¢ Õ=×q&á={±c¼bör'K¦¢„Up™Q‡2
Úy6{$dqî‘rà’8µ­^¤¡¯Tg‚oQ1x!%‚2ä¡ÔJºz./Ž8	ß§bPúªÆ|.K9ù—Q1¨Ä±³ORW©žÙOtgwEAdî÷ª(6Ã%•*…‚ñ¤¤àFJv2|Ò0Ö±ÒO^r#®7u%Õw's|ºÎÕK´qR5˜œ­D’ÒŽú}¿Œ!exG•ôE„hFX‹yš3Fâer®z3ƒYÓbĵb.Ö3
‹$lÆd\KfÏ%‚3"×nÜUhÈ£Yf0oŒÙ¼ÛùÙè¦Hþ
z&ÎWXÌSä–P™J@GßŪT¶^‡‰–Y×X+·F(îí+€jº©Çåšv1U`ºÆ¨	,ÉZR°ˆm®o$R'¤Dn`ÍçÔM5üB/{šœIæXÛùlˆ¯HªEÂ
[MmV¨àw†r'UÛ¹y¼¡âr zÞp^ã´DôýBmG¥*ï³{çÝ+²'¼ÈèY¡ÁœS4e÷SY7ÛÞLýfÒ¡SÁZýU]x÷l¡—á±nÄë!­’%Lú6ʲeªÚˆè3°:/n/§§Iœ_pìþáNÓJh‚—šÔ³ŠöUæ‘Û¶ù;Ð#öô%½ƒ-SU2kÈ!ÊÃíblõ—{Î_‹u}ž³ÊÌMíÆ€¢rJuÍFŽ`˜:¯*XZ
\ZäV„]‰¹:1à;ÀõÜa<ÃDZ¶†®õà:2j±w‘üñT\lxRÖÜmu±Œ7c§òàØŠVUëXÊ6ÉÕjQ:UË­;åªöˆdÛ0·Ƕ÷¨ô»`ìr_ÆW€v²Æ»®*¿:ÁîðãÝUû„ò†ò’S¾3ó¦]aìÌ_˧é´ãvÖíR*R#|Åœº¾“/)ñý¬ûW™ê]ä	õ†óÇ­cÕ–.C=/cÕöTÛXÝÁ:*cëûEÕuªä(´ˆ·xøÐëR9¶mЫº…d¶Ü¡2ýÏ&9«î3	ÓáÍî3mGñ¼\B Ãú»´hïrrT⎧nêó\Ÿâ$ué¥8¯`çŒÆŽ´Œû^[Ó2Æ7IËpÅÝiY´ó*mˆš™¤ãQ*™ÂšD4J\Uí
C›«ë‡nˆˆRæ%*Õ¥ÎÉyŠ·Ûn¢è"&ך0ªª0Eú,©]é±%C¦+k_ríW•·6u»
j½³®ÊUÃÛRƒ‡ÛRP¤„S’[“
Ýr
Ñcrý'Æ[Ë–ä\nÊm¡jÖ~ù¸ñ‹ÝñýÞú]Váñ²äÎvn®3Ó¾XWV)‘êÛÁê>Û5D?ë¹.¦Þå¡Òb!ô\þ(.ú-ŠóKßíßIÙ²mÝ“#¦kŸ¼£ƒæ_«ú¥øIÆøš~Ì9Nñ5ì(¶m¾!<¦Ô/éøN®Ìò)nàè‚‚¥¢ A-Bá¡ÜóPÞÖs77Âpó¦J6Ë-d²®¤}™¼^U¾à³
ñn0KéÒÌwäö¬„í‰~ f¯Vn¶šêT±-¢ÜýÖ}Þ÷gk?T¥ÆC—KŒ®æÕN¤®ý|œå‘£]•úsHË÷ÉýŽ*‚Í[ûP‹ëéØ<Ñ<7;¶Ý‚¢œÿeÆÂ¼ß·ÍØûq½\°LN Æ ŒG˳”Tnò±	|×B×[(ßšº8.É}G(S§ Ç%íb¤/¸ŸÁ0WS?<ø[ú÷.
çendstream
endobj
650 0 obj
3903
endobj
654 0 obj
<>
stream
xœí[[oG~·¢ý
£}êFL§ëÒ]U/‘’@V¡$K¼Š²E¾a“؃16,ûë÷\êrª»$!h!Æãºž:÷óUùùªïÔªÇñçÑÅÞ§ÝêôÅ^¿:Ý{¾§¨s]¬¾Ø‡FAKú VûOöx¦Z9½rÆv½^í_ì=jB;4]«›‘~®]ðcó}»›ïÚµnîãÇ—íÚ6ÇoŸÃØíZu!x¸í_ízàq÷ÚµQC׫¡ùª5Ü»sa=£¹ãó6M¦MÒÒ@SŠV4Èörä7-¯mFh0Í-M)½é[™ñ°õ¶uó#Ìz Ã\U‹A°N×÷ÊŽx$:ª1اa:}1¾ùéûgž²Ÿ94Ý/DÀaøêœþiÿkà¾Ò’ûvPÝèAûÇÀtÌÆÿÀ|<9xmmßi¿Z›¾s*žô¨k6øq
[©@œx‚¿?¦yx"ÕüŒ¿áÇ3ü¸ÀKü¸Â“z0~ãg¹÷ ΰn ø6zÒ¦<¾i’ °tœG*‡>JÝÉÝ—õ<:ìÝ8°wÍgðU÷´ØZWïÈElÊ2fõLÚð”†1WíHd–ÎÈ–ZžUóÏŠÚ5">thCžX‡Ž%v-ŽO: Ô)ž5Ê‚þó±+_²èEô8’ºÓŠØy‘ùx)4PE‡éxÇØ†Šo“`µïÙ¡Ð8\
÷ë!ÔŽ!9í”ô!‹m4ô“Dè1­µÕŒÎsÑjŠ¿
„ⳚÁ“=DÒΓ“Ân¢%¥½Ó®7ì† TcÒL7’ô’=$àÙÊ¥ú«2!ñØ¡e?¦]Ÿ4¿b†\’ArgQʵSƒhLlLì=-º“SCñíæÐî¶š½³ vP9ˆ¡dIŠB·`“žÌ!ëÉi;*’ÂÀ€!INŽÚ’`š(\™sÅ™BÎygå±ô(8Í›ìãPÃ_QÕ1,hãØË0ŠÒ|ElΑv:%kYj´‚$Ü!ÞM—çè©—	3½š¸4ËžÀ‘j¥c«€³¡"T¦ž×^«x¤zòœ*$‡E‹bÈœz1­ØP³µIó{pc‰ÕC¤16†=fiÖÛ[‘§ ùýZmŒ8:I¥DþuœœFñ'YEòhŠ|ŽB×2))»í5yÆâ2’‘c‚”üÌ ½ˆˆ
œ»¨œ‚(^l»§Z96‰õ8£ýP]ü‘ø)Wá£H¿OGg}3¹Z›3ª’7¥•PŠërê’7ú7fÙXŠCùKL‰Ñ¶Ä<>aßSTEº¬o°ºM©eEu>)n*o¶u„ìÕK…¸N‡­=VvT'
ðã$û8ˆ™1#V¬1z’tó:(Ë(c8[ÙlœÆ¸yR_G”*#¶Â…‡¶“Âc¤¨Î…‡jÍRy‚Y=
ü!ª˜؉ð”‰Y®Ôƒ6¥U~ ,p;µˆšÓCUaÒXÓ¹ÈóÈøT­ ¹Û’˜ax°œõÝX
*C•ûE>_poÊ¿E¶¶CùÐiŸ‹éq‚J­RB-äê»…ÚE$Çö®ÀÍvƒîÍ;#9µ!\æ864ø0>O¿éÜ›Àž]‘œÓÜx]ˇۑœìþÿx$çAîù¶ùMnü[i¼}¤
œ[n<-#¯ÞŒ]IÇ™_åo‰be?ŠJãÙ¤%NtwrdtØFHsªÉK™B}’ôuëXà„ájòÒ¸eú^T¤Æ±= ÂvÓt÷³¢ø7Ù_$]dFœæŽ“hh‰×¦že¼"(‘z
\ø²t m25Þ䯓%¸ðnÙíO‚(±\}aWC½ð[°çWÙm•!'•ÛÊîÄls[‚ZëÈç’ó¼è¸
Úü¶Žë=BЊøè¸>xÇ•Ãé[x+$jÁSI-}™zÞÁ=áòÖ%ŠL/5ñË;Ü£˜ròCë=KÊi«•¼]ˆw>pìú΀=™/YâE¤c¼ñ:ŒåÎâ²Ý¶q$1çAÎo5U§õ }¼]1!ÈÛ
”“sP	Ù÷y'B|œÞ‰`ªŒR-É—*ªgDB&°ê9PW¥ÑQ+ÊtÓˆT&..:Çßÿ//0%Üw,Î†e…/J‚cÇ7+¤ä:CF’INA<ï–#QªgÄ•æ«\YˆûlŸÖ|‹\fÔ#	ƒW|‹_Š—
¬Ç^\TCÐé./„iGÁÑ«yq¾Žì©}Yýà@7¶Í•_Ó<~³Jwð\ØIH1‚?ÉÆ÷÷â4ÔÁƒ¸8(ÅC4 WÅ«‹›Ì@)Xl	®†Ö$‚óW˜Iþˆj]½ ;v”à5Ë%¸+z8›<È©•úT·ŽÎÉZÀ•«†à&¯F„kâmPÄvjŒ¡ž—íÀPêAÍÙ)ªh,Þf*yù˜¨:òÒ„$øÜX&CñJP„É·&ëxH¬¤G›ÒµÝp“Z8èéùö‘ïDYÐ7×hsu2û„_`ÚpÏ—¼	“P»^ijç²ÊÄkQGH@á~Ÿ.¦¶]š	\S"îI$›Hi¯ÈÈ*ÈG¨AðQrˆ¨¿5ÍuºÏiTy6gw8q æm»õZëP ]ÖµúNî ‘KT¡ÆFŒp0çù¾\ÚïТP‚Ú†[ÒÖR…¦Vï!n ]«É]\
‡V“lÒ]Á‘Ñ5¥5ç·«Ã"²™Cl\®{¿…ôk‚¬Í¥ïQo†jÂòYï„æðõ…^·ÀÌ<²£¶Éß½V,/‹žåÊëçœ_ǹ»¢[¥H	ûùB®úg¢[·åÖKæ‡Ø,¥ôB¨¹<ú}‹;,þ˜R”¨…譨ݩ€{Â~Íh|p×g
žÔl8¡&½Ø‡ä+Zk¶W7T“NìQþUXò©dÒÈz½tØ»K:kñý‰ò¾Xœ™U/s¶¼8ª‰³j«œf‹ãæ´É.Ò#=XZg‘eñóxïñš%Úï&÷žJeO[/úÉÓb¼çyïyØiè¹<¤˜…›†akw^©0îIʼn˩‡WÚQfÅMÃD¬»(+]æ•ÄÐù¢5SæKqX›þÔ®fd!°}AXí$uzRÇÁ#!ÍÊ$P§¾›
«èùMÕÖüš¿	»ÿuI{~y³J-vÿ’-iËì¤]¿Èu„Êd`M°<¶/
½f¤$bµ;¼ÞpürE¾KòãÐã*ܵFJlD;nCK‚"œJ@êf,AôTEuþå&?[Vzñéi|ñEpó‹ôÒ*=ãŽË¨ä
Ú– ò²pFuþ}VG¯øÊ_iu}Æœñø½ËR4Œ‘Þ¼wÞN|]„‡S”¸†|0Š`z辩€zBävè[?h?+<ƒµ~¨±ËàbÏm¾IÐs™	R_ž„‰ÕÅ&™ÏÛ¬cÊ¢âï;¦ÏÕ$ÜR½ŠºŠù­ï6<ß9™øØèý–2›˜vÅ_EÞúsýh)8l+zìˆZv(zR]zkŸk8‘rT•’ˆBS×O7j·Ô=Ë?Ýä–?s8©
¹ÓB¥°)cOöÒ·×"o0	‰oCÃEPÊ~n«€²Ø·•@y,$ʪÇ×Ï*þYÛHèm­GH¯ÿŸë‘ªÌøX[|Ä>ÿ±Ïßµ¬˜‹µ`£KE…{·íK<¹Y2‚ÛÞ!ŠíwÁ_ߺŠa½ö–¿ŽÙ©ž¹¿¿÷ø÷_~\½öendstream
endobj
655 0 obj
3689
endobj
659 0 obj
<>
stream
xœí\[s·‘ÞgÚµ¿á¼ùŒK
n3ÀƒSeÅÎF[Ù$v”J*ñVŠe’Ф$Rrö×oß4ærHɉ³©”Cjf4º¿n4øz7ôf7àÿäç‹WG¿vgo†ÝÙÑë#C/wòãūݓgð±ð¤OC2»gßqK³›ìnr¾ìîÙ«£?ïMöþºðßÏþZ9Ó´r¦7#4|v
ÿ¼;öû_v¦O)ú´ÿ²³ûßvÇvÿŸÝçßvÇôOÐwo¬Mðrÿ»îxä6êsêö)>Ä…¿<­oÿÔüÚî¿‚n×§¸É/:‹ßÄ‘“4€jýhc]?˜Àýº£¡—4‚<Ôï·øù0Øz4>Hâxø—ñ#~蜅~|î°w±óüþ÷ Ë0kHyXF¤a@´í¦É²¦­×š>UÃûɤÄwãg‹	°„².è’Ý¿A=]À`·Û¿„Oû-ŽÏÊW¨£3ü‡~ÙñÏW0Gú媳#HÊÍ ½ƒ¡‡!Jc|½Äyšý5v*…8©¿>ÇQÊp'€àoðEé‹Ò¾¤ÏY’"úåÞáã;|æ%¿"ùI¬ïö¹#Q‚íËçØ;Ž,Áç+èý÷ÌßujÚ¦ÔOðo+h|‘bõÅ9/ÚÏÞ•ë3Pp@‹aYcTßœ—vEbÈ̃¬È~Ç™×Å©qQo—Øn¿×þåDé4$Ý¡ Aì}Ü$û€0#]|è¸æet.æ±£
XZç-mû‡Á*ø¼L¼BØÝ-ö>	˜3/ñcûy
ºçõà‰À4ªF¤ó3e8‹ÚwJî»½Å¢B³<[ÞIk¯ë¦b]žu¨>Ùê£k·zè£K‘öºð)øõ„èE“HJÒú…¼ÿK^éü¢~õæÞÕ˯ËÃ÷å·,-xÖ’6ÿÚ~Š¿zpE^\gôž6fÃÚJž´¢ç__6úÏߪ§­Ú¶`¯}°Œ­²Ïp†ÄhZ(¥ÌmùÅ¿*›*c­®¶¼¸êæm`€ÆÉ(@×÷'z…Þ0Ì?ßør¹ê'õáßô²â>fäU|+kQ
Ñíš82òÏà‡ﵘô4—ÀÅ>ÑOM TŸÑt·hÀ£k0,—›b´
°õÙðø'\n*éA4ŒÌšÄí†Öï’'C-ŽaÉ«h“Žl¨Nê¯Û”Êf<ϵ36ÕM¡x!’ó­lé3èé	H?QY.¢ó‹“#É¿œÓ8ëä…E•®¦˜Æ&ÅCe1½cÖåÀ8˜¬Þ
¾‡¡A…Ág|Š´I¢ÀÇÂï^óù¯:ÅÜQäܰGÙL6…¶j |>Cø
°¢¨úƒ	^D^O|%ÔH„V…ê53k¤ûÇVÈ}’3Ä“'^t­SuÁ;Y‘%iÃL™aèù!®#ì,ùÇÈX¹Y÷§
À"hbˬ,,Ý’YOFó£–¦1ùƒ_Pù8OlÛh¡ôü–€ýéÑ	-@™½K-ÐÔÑþ`A¡:7¯·hµÕ¯dTî«ïy1ÏΦ)/(ξ¶Ž+ÿzÅvYºîœX¯§ýƒ@—eÅÕNÔÍÐð“h;SŒ*Pb
´¤)#Кï	Å7yLg<‘ܾ¼"×B¹IF·A¯ÍTxú5èýÿÒBŠ‚±Úô•Þ7à ÅwÖÓÌ—|\zS7°ZSeªy°+± Žû±>ÓJ´Q–3œ{¨ÊF­F[%¾¨‹1„i.·Z[š™¤˜’yDA¬ÎšMË)°¼¯Ò^Ô`f´
éžnk†J3ðCv&U›~àXMzöB·ó´ô'?p¬=ph‘34Í(˹÷Fþà®UBâØø¤ŽÚä†Ö×:ÙöOYÍ|]ñàï;+ d_€V™<.~K¬Æ#re¹°ÕiúO™ÂØÔ›±ø¼º¤§,N_§D¿¾Lž¯šú«Î’f–	h³7UžÂ"RMp	ÏD,™{g¿ ŒÊ؈£­Ê,‹Û$Ú‰³•Ù…W^¤]f›.[¦Dit`ÔŽÏ$޳ü­ÇZ˜ïÊL¼×SÒ€Ù{»’FÄ—¥‘&B±ñ5eÉQ?FQ˜ƒiFiq"ôvœ_6üÄsÌM… Õ›!Ä+¥]O;Óƒ<™áçhh°»™ú‘Ñ…&4Ç}
M3#2¶º¦2›l€‚'ÑObU„
Îp;>[’ÿJ$;4†¡‚•ÏVÂ1KiG"äÈæüt˜–c8õãKtŸM¯Ð–Å´¼'阒XܽŽC‹UBRs²vèû;œÂ³¸!*§P49`Ô*»©µDÇií¼—Œ0ì(Ö·«aVÞ93-¼‘š¸³«‰†jh4ly8í
ÎëV×tøŽËþžùbåÜÀêôt¶÷B›UÐVugg—̬µ@ËÄj7iæIl‘
¾Ða‰îFt*B	j’ÚM[&¤‚œT9'M²œEœÅH|ZÌO¶0a"ë+û„óãªocÄGW¨qŽÎ`›×hm&kU2C&©Ã6‡'ƒÉì?QQß‹&Øþ¡&\fñN
žu¢Ù1JÔŠ‹—ÌŸ?¯ˆlûù¢`2òýÒ'¶Ìf”W2wX– QÔè5¥á¸yJ´~z_OLž##m}O¡²‰Ún–,Á4ÝZ²¤¤v‹Í©²ÄéÀ9p¶ïK´NÃO	‰ÖûG‹†àU3ŽLvS±CÃŽ‰¥	zRåéÚJœVx´±7èRaJ¦…Åü´OvŒÝ$Ec¢Ò!,JÂtÄ-&î‹§vç1ÃFòØøE|•O՗˾2grˆ¼J&8ÃAv³±%h_Oñ˜µôÎà«,Üú–_`Œá¥Wã7’€)Øm‚®NöÇ^LšM’ë'[Pd¤jP*lÐhzÇÕ ÑµùD–i=#-‘}e¼L©Öl¢ˆæâKª°ÇŒsV^]ûªÙ ±S<ÇÖV=ˆøœ°oÙêð§ÖË». Š?ͼn.!X¦'í!¯eùlº+’0W*"?Ï–3ÿYÛl*É~¸¹¹4D›%ºKÉB àÃ9j*y/ï¹§§Œ-cúBhbSÍ£)jÔ&9«+ FƒLd"ׄÕÉí6›ØDRÕ:¿:ÑÍ=4‹eò™ì˜)»U•x¼jÖžéîß;*T`?5+Á0¶´ ’Jë¤8¤e.1åÜC’„x98Óp9Sš‡ªÔ¨L†Nþî=yËå-¤">•Y5½*Ñ^ZªAz”€¹"•ñ][fÉBfB˜7ûÄ·†£õ5Y¤Ì½¶Ì2[;çÿ’íõÄ€\Òé`çÞmf~šÜ ”ÿHhåfA•d…衪ø+§ê{¥òI¬+9IåFò¢I´þqAÙƒà'ÃW¢ƒrõ’BDK‚¸1bû´‡¼£f¿~vôÍÑ똠‘ê=gÄ D‹;oGéÚÄõ¼œ5_ÄTªd½N'ßã¸sÙ¦¹sÞ:%J‹{r¬Ú3æO¶2¼%‚W|&çäàF©³û)uS:áÅ£Ö¢g½Å¡hštõ?ݱÓ\¶WfR+_æeÒu|<’öŸœq> V"OcË!$'^@°@ÊȽۊ±ŠÈy±LÉ•Œõ©¿®ù¶\]Á‡B«½®þTÏIrÐÏ—óáÀ_ZÈ•ºfBýY…‹ïWsUÅߌ0>k¾ù_½°2ïþ8ÏSÚRÛ^Ι…n«([;RWí¨Ôi°-7‘˜¥tà/s¬È(G¤‹Ö¬}½zr™TZ‚4njÒF¥[ßÔ›[9•ž]åv¢»¿JL†W±HÂ1Ë"έç*ð­,û&ðmdæçk6˜^.ëÿýT²a5TÒuEjXLÔ•ç§BSEãØ_­%D1}-Ä-	–b6åN›Ýöƒ¥,ÐVm3L+ö™Ñê‚Å
®ÖC¶•ê([JÛ5Æó…çŠr…Ôk‰ûK@©¬/dm´f¯¹¿Gg«ú
 ÎPUðU½©µhÉ–[EèÌð`ZÇi¡¸æ¡§ˆ)@ÇGáx‰({£kõñ²¸±ÜL[ågùzÎìOÞhêF¹é¥$õ¦W†_ëFçE˜iÐYU}Y§ºÖÓn£ªYe˜ò5Juy𲫑4‹ÊSá!¸KÚC¯+ËÜÖ‹
G¶ß½ÉÊ=ã•ëàç×µ·6úJBc‘tb4C'paÞÚ½D1£º=T ^±Ù?úÞ2Vî
fƒø‡¸I Ê	1çµ—¹ªe(+Œ¼R÷™¥É:@‡F±À嫦õg¾ìšë¤b¨Í¨¯€­UÌçI9Ï÷½žðœ†+5&´¯½ø“J"½€mÅ[åt¸N—ÓÑx>
stream
xœí\[s7ŽÞgíüˆSû’Ó.ãn’ÝÍÞT¶*‰íŒ·23¹(µµOeeÉ–•èâèbÇÿ~	€A6ûHòÌæe§¦2>îf“âòô¯«vÛ­Zø_üóè|ïñwãêäz¯]ìýº×áËUüãè|õÅA`»ðd;µS·:x½G_v«Ñ¬Fë¶­Yœïý¸žš~½mÌzÀ?7£Ÿ¶“Öß7›aýM³1ë§ð_6·~¿>c¿n6Ývš¼›èÙ_›MOãž4ÛõÛ¶ë×ÏKoàÛ0Ÿ5ôâó†?ÆExê@Ó4u8£5l¯Gþ¹¡¹íØõ
~’Þò¯ôÅwÃrƒYÿwø®oÞ¬F
ólÛ¶s°„¬ZïLøX¿þÐ÷ƒ|r ’šž&"3}ø9Žæoÿ¤ß-}×wÛÁ‡
88Bï‚°Mø/ü	ƒ7ñíÆ¶Û±›&’¾hLà¢×²†¶æ(0>>ïoA‚çl`£ÃÃ_÷ÃPëïn}ó*Œ?	ãÃøàFÁ×ðæX¹†O:\f~M…ÅNð›&NÿI‡¾¦	ß’ªŒÂ5è]X燿'E€ùæfu¸·áÙzâ€çný60çi ˜s¶
ÈÞÃ\v¤1"§~ý2|9OCørã:§Eb7“ßZÃ{ô#øSñyH”ƒt››†×
“Ñ}g„á0Ì”7œ&ül }¹!"€tœæ(
ýV>†­AJì"V­u‰‚d’^‰Jg
¹‰Ün:»í8ýÀô؉Ë(=¿~ßO¿@ÖïKB¿‚4âá
»CÑö…ó2â–Š¦E1m]드$pŸõ(ˆ¤>¬ÉŠœæñ–5Èš¹¯þò‚ìD8û¼‘Ö”ä!ÒOøÐÖ•–÷æ	Û~JŠÏÆŽo›˜ØD1È›ì­,qŠJgÛaëÄ#­õT	LÆ={Þ#½Ó²?V)Âa¤p	òÉ(Äㆱ*Îe€»VŸùU4ÉÞJÃ\9K´*`ä°Ÿ<	 jÌZG†·°w¢;n@þgºç>ìAv^Hy£iA»s›”ómˆôú2Í-›†ºãœÇõN1¤pÊá]ËyØ#4»6;9=Ï!gÃö&gQã_ÃÔ,
6›uMfÆ+åRçL˜`…XßJv^‹ë¸d¦2³ª-Ë‚aòb#wƒÀJ:oð´‚kó*Û¨6éX&‰’'y›ÙÎà
<:x”to(lðž±mÙ¨oP_¢/4Õ)Ù¾@’™,r-v^*ÕÂç¼ñp3¶¨$QL¶p“A*ÑÒÁ¦8ÄðúÿÏ,njî
Œï’f¿Ò
!Ú—¢ƒ0HdÕn0u¾3óyúFô\³ƒ€+zÚ¬’ÅXèûèPívp¬kß$¾ ~ácžý=XdäRE&¼íÁчMC	ÀŒ£„7$ý`•"þÆÛ]ªFÒH”¡qèG£¡`?S_ú·ÜÀ1]j…'²zôÿ2@£ðª7š…Ì„UCá
õ¶ÜÐ,†ƒÔ
b¯y°Æ>’rRÉÎl²d’ï'“P„WšÖý@ó@£ô?Mʦ0	!)¼©o"4X­&0ž`•ƒ†³5Ô6ÁÂn"¶Ñõ$^ôÒL·‘)Zè„ÿŠ),%‚ýzïàÑ€\-̉oŽdÎC™3ø¢¾%xåô^ëF…‚ÕaÉ¿..ùGùê·|ÉcyqDž¾£!@›<¦§:\IIÉFä.Oj¯øa””³IRÏr²ÙÏ„¦ßr)'I½Ž„R©X»‘/2âúM—d^Ê·ïb‘·]8þt‘ð§Bó[¦LfŽòN›{Z“wÊ
Ï´áØ¨èt¶	§9#
ƒsò‘\«Oþÿ°úÕ"«_å%u¼ÒlÙõ§¤d·ðûZ¾¹Æ§èžÉ—ï!ÛL»M±/~ø:>$tj.†“sÙçó‡G5!_è×)"Þ8LJ;õþ2“bßMx ÏjïÉ7éá~üsÉŠ\gë³ðž¦§¹ôà§Žë83Œeh°©»€÷*é”.ø^TgÈGOé¡	:ÏCd¸õy|áˆ8Îuz¢íï“€b
ýš¨É N!Éô·Y&˜ÌwMøQ()lMy^¬L˜0œ·mÌîÂn;•’+K2†Öº2(‚¿FÀqT>«šzª‡Û®(Öж˜fRíŠÔòJ’”ŽF,"B]ÄçC¬$o<–ÀÎòæCôx”Ÿ“ÍQq›é"Ç]Àh0n­BDržSšÇ8¹<»læ{IŽ`0ã¤
JŽ\ǘŒàC~ÅL¦ÏsÛ#)%¥òiG£‚°`Z‰¤Ë(föTŒųhL0¿-þX b@?ÛBrÓËÁˆ/󲉲ª—*b+·S]ckV-¤SD&QßN¥AïXûƒGŒ$“grQM&#¡<lÈ/§l†G3È%
s¯rr;ÉÞªjÀKV¯‹ÌðA`z/^¦Š©hÀ]%(äwTÀÃý‹J¬Ö—Œªþ@6+ø¦§²L_4vÕx‚–as~ˆ'çŠl–]òè„4Ó9ØVß”¤ô­šñoªid«´F»å·]™F³ß»ªÙ7£Ô«Í˜;C3vø÷r÷àù;€£hCô…h‚62>ΔX—ð.”U™Rhp.[`¬ý„§±5ÎÍ£q4S+Õxä–ð)ýÛ-Y"oK$£ *hm5ÍØfk£XÇ:ʪ„Dd:‡,sÐs¤ÚyQŠGQu˜5cIÊ„¹Ôœ«¢Ä«ÙO½Ô€»£0×[âT´pL9ìÀl+”…¦9¸ËŽ\èü\c01–%̽Kë&ÿp­³8³ZÒD…ø¢–4™„çãü¤~a'e·j¬jvOw~¸·%nþUàÀ7.Aè4Ñd&™	¢˜Ž*Èi¨ò|QŽÚD^SÕֽ׉¸òœ+Òg [jØiPÞ@AGжù	ŒtüÓB•‹ñùˆ‚­=‰ñù;8úÊ Rߺ-·-(”>%ÔMa£Ê¼ICX­Õ„*Ž¥“@XGg¹…C6|¿aº,
üÂ&ÎjÎÄS´Åú°dèzSáÀ·¥¡ãÑÓçmÝ¡9ÈçZW‚Ÿñ” øÃ¬µâ•àjA|Ïy.£°„L¢Ö Ã؆éν ¸
1 -R ¤
·5oÉñI<ÿv–áI¦J4 è¦—Ø<“©„K½?ýî\šÕ#Wu9П1A¨ïpïhüa&c’v,ì)åˆJCQk”auEÂEí(5¬ÙÔíÍ‚FóëZÄUS¢o,Û(–æY3u[]G7®èÕ
sÖk ·"²û“ Gc
šSsžA‚ˆŸr`ºŽðùetèd`’a«dê0ÌSyIÉ’dnl>4õí7†Òº/á'ÙÊZ¥øRk|ìÙ14`±ÓæNI®±ÜBÖWcd)¹OµÞè,Pau;â’B´Š¡,Æ`ÅÝ0—Ô€Àu¯-öBäá+lµ{_´ˆqÙQ%À/,t@$Fùȳ†M´ÿƾ'±*%¨»~˜Ñ‚–‘
ƒ!·õ?õRKHIe ¤š¹öp˜:é‘ú„cæ¼SÑ@ùR§ã5'šVzÖ:Jö;ʽ¸›M•-b4̹[>å;ŽãŒ	~fÔ¢2O“Ðh(N‡¦ÅOÓg—ͼäa‹	„tQàQÂg¢*yëwkc‹ÛG€”vºÜÖb/¨p¥½³Ô·ÒÏóû»ýdsƒkc¤£møÜÍ1æ·½Q–ÛÐîêË»Èdº»»M-Ò»
{Ȥû¤÷?Ià&â);ûr-´êËýjhÔ­!_sO£Ž
¼ o‹®¼ŽÎPSä¢Ë{Žb4ñð4)¶õ]¾U€æžä%…#"ûœH³³[’tÊk´z±}’óœ.¡µ4Ž!·©[ìÜE‰9¾”¥§à#ìp7”À2I@ùÚ8ߊ)¬RºÇÂJÇÞÛÄVܹËvã$éPž?x*˨-(í—|½(й+ívÞ¡{cHÞHë•.Bh#¦º’f
ƒUAg-LHG¶€7–ÏqP3¯\Ÿö;nôñVÕÂ
”ýĶÍCål‚™¬G*çôPºÙFˆµòt;–Äâ£Âñyk©ÿOiè‚átÓVì8fݧb5Sùð'ŽŽ©¨ŠoñÙQS);žéïøáq£Ê§ÉñëT:>«Å	×Âu·e7ÍyÜ@-ºïFU·~³3úìz“ŸÂjlesQ	;óJùuÞ“¬²ª&fºC¬7•¡$øj'»„©c¢J,.ÔÒ¶=g^.’‰v¨n’cXóqõÃÂÕ(¶12õW(›àñ±'¡'Ó@¢®È	ä)TÝÉÓÚ5Tãêñ¯m¦É‹áí“ÆIÈZ`«ˆ÷TEéR…§
JÆOD¥Ã¾iÚ£<â¨ì1F‡¬¦÷U§EÆÿã"ôý¬çNVÒjR€â,ËàÅ¥î–æ­À—H›kuÃ?ì(aÕçÑ/«pæÝgX“8ÎÝýûåhcý½"ÓÀ×ruÆ£›7ÂT"SïSD”W†j'Æ!vì0)åØnìÑ÷±'ЈÖ1³Q•£’–™”©”ru¯sw–Gê4Ù‰Q0%q,
ºb4IÇ–j	\Œw‘8½C~ýÎp³¼ïÕS%¼tÄ9U\:d!tp‚yn•ï?#€eñm|ø]³ÐÐwƯÿÔ(ñèVQ˜w(k3ŸAñÌb~Žæô÷“&Z%hý03Ü;Py•Ì¿”FPuï’»dTgú¼£&"Ãa¡™:À½ÑjÿËCs^çzç_æ¨n6°k„Hûy}¹~wŒo¼vÛqvãÕRÜ•Ýü-ÍIÍé)ÛóöîR2Tly•ð2]­}0 îh'"séí$C]^0-ƒóªD”Rß–Iä—úä^stmXYõråÔôý–ì*bz¿+oàë02•8ªõùFoºcÌÝ#¦Ÿº$—¥ðÖZÎÈéávºš¬™)¸&dbHðñjD†§ˆxñr16«ïðü#îÍ­1[ñ‚$€fÐÿ,@3‹¸šÙ’“¼*1oïp€j°Ñ)]4`Õì²%DI/x,n÷¬f+¡í$ÈÙY€&೓O”þÍß*M¥Ÿ­Duͺ7ƒ½×…a-Yœ‡ŸƒfyÏdB$­
±§ì„-–zz^{‘ƪT&åLU¼×Ñ¿¡Î¥àÍ‹ÉÅ®{hw'
ñ„4Šcæ„£_ºÔO›+õIi[Áø”LRÖÞã¦Ì6Ü-äªXAì‹+Ö¶ìî%,<ô[Õ6fb‚±¨Ô’älB/÷µÕÝW뀻® ‡x§ý<
6¶/Wàî‘[x1…x›¿òÓUÖµ´ÛåÙìó­šî¥u¾¤ñh·–å—<æXâ•ÞVàà?ðöË}ˆgFÞÞOìûÝçÍOÅJ£üA?%òªaﶪ%¥>Ð'90T5¤rëWÜŒK·“0T‹½tOHÑïg¥íäþ¥ÒdQÙŸ›ÚÈDνSuÞ«·ZÑz´çìšüqýÑé«PÕ·2pAsxÁý¦r0ô½6ž§J¸¶è|¢—v„äÉ@“	¶«;“¤sg3õU"“xÓÛŠÖZ²k@±ð¾ø‡Ê'7å8¾¨Â^. ¶
Ê™çÙKeìóîœ~þ-„—-Öyc2ÛË?F’ÿ;8¯.j%÷.?°ó”5îËÉË´A=ƒîÏøKmÎ/Zøáϵ‡ÉNW_ÿ,çhákVëŸõ<óãñª¢ÖǵG•癘Sš78ÿyý3òúû#/ü‡+¾Ýû_ð¤endstream
endobj
665 0 obj
5190
endobj
669 0 obj
<>
stream
xœí[Ys·~gùGðM»²v=¸æxHªœøL¹lǦ[å’–â!/)Ї,þûô43ØåRaÙŽ£r™šÅ
 ûC£ñ5æõ~³4û
þÿ]í}ô]·|µ×ìï½Þ3ôr?þ³:ÛÿÛT0J–C3˜ýƒ£=niö;»ß9¿lìþÁÙÞ333Ëÿ?=ø´r¦håÌÒ´Ððà*ÿ}¾ð³/æf9½fÏíìÛùÂΰüÓù"½øn¾pаiºÙ²—ðÆÚ^ξŸ/Zn£ª“Ø/±%~…_æ·ÿž/Ö¶³O@lã–C¸Égs‹uú–Ó(¨Õúhcݲ1+}=§Š eha<$÷;¬Þ4¶‰Æ@åÆÁH÷¿Œo±¢sä8¨îPºëQxzÿŒ¥i‚54ŒX(=R70´íºÎ²¦[§5½`}cöaŽËÎ«´áh þ|ŽCá¦ò"4ÃìŸ_àŸuzâêgò‚ª\Ë‹+ZÔâùÐc1©šßä÷ÿ’Âosá§Øq?ùÎrä©A9ô¼Nk‡UZª½8Àê1Ò’Õõ;ã‘-ãê¤vк¤Z„Ð|N{¼¡æÔøê˜u[ZÑ¿SïU¨¯k‹bÓyr—ÁÁ&¦@±ÃyRŽ‹²!o:Xêáïxœï‚sš„˜lÙÒévyc÷‡p÷?ÖŒšEhŽ…ÏåéV[
íhú^UTkádN¦ÑKåI
[W(§éhéËèzåðŽ^q°œGô˜¾é]‘ŠJŽi±‹7Rè ïwRœV%G©†ž<®Í"ýìR,™¼JÚÜHÏiC¶’ŽK1yÙ˜ïL.n…v‘ñ!,ðö|—ùdâ€
_JñN‹‚šøž÷Ì™ÐlÌèÃu³:¼–noJ¯#Xâôª$#~uBäF¼dmåzµ7mI}pžˆ:—8ÙEæT}ãËg¬×¼kZÚXÓñW7š}
1ýqEÜ‘|WâÂÔòÈ`5üåFÚ¯FŸ·ä;ÓIá¸ãêWGcUaUÓG?šÒó6ìHÁðªI ªñ1Ø}ä×
ýJùao9,PG˜‹2ñVL^ÂK}”s^°S–æðaæ"9ZÆ_ÍÈ¿†
ÅæÛ¹ZÓ¶¤e)t0ümQ­£“ä¦èÅŠˆxÙ—®&•é¯f
»Jiôx¾Ívm…|ÑR§Tj@˜)•
µR²¢k%
F·»ùÛŒL¦L7Cñ£ý¹µmA¸\DAWÚô7ÑÄqföÙ>
stream
xœí\[o·î³bô7œ7Ÿ5|Ö»$w—[ âÆN]¸¹¸
Ú4	Y¶e!²$ßâøß—såp/’l8MPAì.Ég¾¹nžošºÝ4ðÿ}ølïÖƒasôr¯Ùí=ßkñá†ÿ:|¶¹½Ÿ&ø6Ôc3¶›ý'{´²Ýn3øP7n³ÿlïÛíXuÛºrÛÿÞ
q¬ÇØoÿQíúí—ÕÎmïÀ©va{~}’æÞ¯vm=Ž1Œ4öïj×ѼO«o»ºi»íÝÊÓÓ}X›öóŽ|RÉb|‰lhÇwô.‘íÌÏ+ÚÛ÷iÀooW¸$?•_yŃ*éu½Û~“ÖuM"#zØÕ™IiŸºiÚÐÑð¨ÞÃ3—–ã·_}_ë’}åÐt'‘Ó¥ŸÃà¾ßÿ[â~ë,÷C×Ö}L°ÿ(1½MÌvé__u4Ù;ydzw¾©‡viQWù¥»Ç>Ý&oý Q´}œøsö”4¶‰
aûx}œH~•Æ"žmûSÕ!KhòIzøfÁê—0«Ç[x’~n_ÀŸ¥YÏàA®¥Eég“vv=1ö-¼ûUåá)‘^îÒï~ûÝV¯§—ÀíÁßßU4#ñ·~ûHÙœZg6ù!=ø—ÞȺ<î2p(ÜNö˜X²}˜ÞfœÎ„T¤g§Â1K4rZó}ë¡^뛞Û€iŸ€2Í‚õ©ŠØ×D§¼©†7d
ßqÿUèZóÀêtAoavèfDjäzF:å)ÝÄÊ)ÜNÚÀõpK»…$b­¯;<p®{è‘QÀ :JÿÂ[+‘döDhèp–p\ˆëd‚Ûžé$>gt’Ķg¦§G ¿òU~–Æú1ý.ah`kxÓsL%w’xòäÔFöxg=‰[¤à!°~ÁöÀ\—„ºS)Ñó²F2J€t݈ˆx$ô}Ú' /½L?¤á8¨< …1Q(†«_çÂq»ÑLŽDÀ#‘R¥aDɺp"…¨#÷
—Ýûò²aË&–WZHÌU$M@v½©‹0é%<>úéµÃ°FIÅì½…†pPøfúOOð3¤@Ä¿Àg#CãJQÁGòæ$‡ErƒV‘¨mëε"dûqž7ŽD%>^GÌtéï4ÔÁ%ñt‹„tÇ%†ÉËJøI:Û]$Ôûí=ï]ÚÄÐ\‚N:ç*T«l÷Š/–“€Žmðdx`^’ÿs؆UMë‘Üè#Âh Î`LL¡Ý¨ø×³Ê¡WhÁ‰Å ðÜR& i¥€JD·Ql娂’VL‰·íG4Æ+&§°˜$ižú—cI2&`óPƳÞó:Y’ ýP€ßäë¦×иI˜vt)X€ÎH9à6z×çu,>x¦mbxñŠÁ’kôd#ØÏ¾S›zEàŠÄ^n.´
Šæ\»WÝ4EÌ1â E‰WŠ‹?ªÄâ%„žá•À<U¾hSd¾DÜ7!lYG'@½ë¤V‚As©ŒquŠ1w+Ädn‹Îg­ÇÏâc QHÎõÞIOdà/ÞË€ˆÂàô…´VK
r™£G”ôåf%xCô—x£€Î·›T«¸hp	PrðU¬)<KiÚíǰxÀj³;`%Àw±¼?ûµ†OìjZˆ'~P„¸Á:ˆ’¤Ü×äé¨=Ù˜Ò9‚‡É¡C#ëpÉe¡G´thiÆZ£Â/[Öy²qH€Ømw:å¡N1ìÍé4›´©¾gS'"õHøUW}v~
]¥/Cç(ÁeÕ»¥H4ƒ…÷Y¹ °‹M‡Ž¢éÏÙ‘1ÃѸ®$øÇázùÞSÀ¼ 8übµÂX&+°ñ—y×a눚I(Äá&/H$c´~WYXø½É¿€5Ä”ŒÀb™r$,:Àw'A«O×3×!àÇ1Ù¹H|™
Œ5L¹G_òÀM^r°‘ˆ‹ˆA<ÿw<Æ´<ÍFˆ<:_ußQ£Ü{v¬ÔkwCpµl/9Â%þ8Ýbt"¶}vš€ID7s´Ý!è¦b×ãÜ}:“ë	e_³Tø@¢;?!@áSMä5D‚‹‚î>b„'ø„ äÍu÷µïÕ=®à˜}ò®eý?­æ±œ8¢&„yÝĸt-*ž@7m¤øÝk´’ao&?ÚÞh
I	Sb¼ÀÊGG1ägOòßfVÉdÈÌ•æ`> õiè>
ëÃ{dô^´¢²gO.áûžÀ¶G—v æwXUuÕ´
X(Hñ‰Ï{Ìlƒµí$ž¦|bÚfFË‹Ÿ¨6¼`aië˜í©KÛ¢8­Ù¤6 Mº¦ƒÆÁPœ+€í–8÷ݶð£™Æ©ÊÅÛf.B(<Ý<€‚Ñ…EF-E×à¹M@(Tø¹ï?>iÆ|‹—\S\GN'0õJ×_ÚxÌgð6Ö3v×®¶Ëò9ó õÍÉŠ¬¿µ8*ŠU2€®QšYÐ’_ó$Ú¢‚
qM‰aËT€ÆÄÖE½’8Ü:Œ™T£úÃ|†R|€Q?UÞ)Ç\޳$Rf9ðzŠìYŒ$w¥Mú²k¿,8
ùŒz9ÂDb6Ö_&ä]‡µ¾ŒyY>­=µŠjjh#nd¤¦g4§€BtJÿ%™™ rRæûz4'\5¡ìñÉäl·9Z¢HRiÃg"ÙÝ.1;­Ý3/f†,HvéÿÎT‘53ïÔ`CѪOEó!H„‡`÷Ž‹°Ü
Ù|š„Ifà?R–eîØrJý*Ž-$|É”wMã“èÑCma.(}XΡHbHB§®î-¢˜LH"7ú°e@¸”(Y𥹜!îð8ŠÔL".ÎöMòBkîv­‘6œ¤Ä•OXIºÀfíX'Ž˜XÄÞŽÜH3&DA „£1ÒaòyEÙÆT#•ÂJS Ôö«.Æ•„‰7ÏU#بæ@ÕÄ‚×
³û|¼³¿÷ÕÞóMŠXz¬Ö&0?$W;ÆMZ¬
>Û»}oïÖ½¿o^½xýxïÖ?7íÞ­¿Â·¿üKúëÞ§›?ìݹ·ùjµ0<) raØCÝû1½§©*Ï\‰u"3€¸_šH€7Wing•¼ÐöMíþä%îbwë–ìXå?Pƒþ–¼FÖAë7!½^‚ƒ2Bk¬g"ñ˜Òv9=˸Î;²û€<,Mæ¾w€"3©óˆKK&p@Ý_•¥ÂBØ9”zÍó-X±MêG=°ØÍB
OɪÌp]=çâÖ’uÙùm禆Ë(—"Ch¢z#&éZ¢¢×W“øªñ4WaŠUSQ<–ôrÎ[Q(=!-ÅóSI³&£zõÚP–<:dkƒžü挂N}Q>ai2€¤˜ó¾Ð¶!þµc¬',CwAÂ2Dµ4gœ]J{ÁÛ a'ý71Ë«w¥Q´ïÔ×€é}A`-µ1%Ò½gV‰ìJ÷ÇPê¥	6ŠDý­½/HÒMFH7$åOp—\~v1’ÿž¼¯k©ÕsKÇ<ˆõHÞú?õ}PÊ=d=8$GO&Ÿèƒ‡v¿.Vrxo¥÷q¢#;àŽtð0þ,ƒ¨iZaJôIâ¶›!ç̃>G×PÅý†>>/×áoòDL˜Ë“ÓL™aß¡‰'ôùÉÒ¢×:h”œ»‘šîëó/òóÏuð³~¾DÄH^ÛϾÑÁ/óà×h#èƒ%¡0ÎaõÛEqý q³Ñ‘ÉUÂCälîòŠ¡óðn¡38¯µõ}I'>Ù¶]®q£­;o@{Þ)¡J¡F›Cß²¾¿ÜT¶¦én³þvOs¦SãetÅòœÔ?LW¥!H}ƒSq¿ÉØ»8fgÄb¤`iíë2iIƒJšó°þMFòÐs´ºü–¡7s\öÈžåt3MÝ/–ŠõS–²iË—êY8qC\øjÂIN`\5Kã<³x×IPâU$ÕÛDòþ”K¦«¾ã²ëÛÖ{êašø}ðT„¬ˆÊæci¹sZ¤É¯õ=2‰¶g½›|tÑŸP󚯗?/œ¹ïÊò4?Z,Š;:æXÍxµE/	ÞÈç®È¢ÏpÝÑÁVºKm´ÁQyf"€I8:]«‘ñAî­ƒØÔ‘»ª5l²³ÐèßP½O…•?ŒL;.ï;àf@Ó”§³€á?£Ï9Ê1rRL1jý(žpXÜÔnаD£Áaßï)èoVPlRV´]'O.鸜4;ÎàK^7ÍíщKDš]Øç/±.)*Ó­õc™­‹ÉóÅnæ6¢µQíÈŠå‹·ÖTÜëNe’>³.®ÜÏ0ªqM†T•Ž…Ñø×…–JûÁwþÜÙéharª¼ Pî*ã`HÀȃ,c?jt~Zìó–X'Φ(ýhUóY®¦ß¯âùJ9šØŽtê~úÅÕã*h·d¯~An…dÃèà'Ù‡+HñBpµ|­ïèz©å/ôC2Sñ¡ø<8tnáBn~
aP=âêÈÝî¼Õ–·2ö_¾IÖÀ~¤¸˜+Yjn+3kx¸Ñk‹EGu…뜕,¥	tãzöÒ¬÷âßÅžŒ2c:óÇftšÒÆ-}Rä@1IGýÌ…M3ò̾ 	}F²™??¹âfɇâ×üc‘â~®hê€o(vUŽîrŠ
.°ÿ~ñEð¾‡úL–Þçn¾ÀÃrPëò£A#ÌLÏÑ誵šþJ¡jü%[%É“®9Ô¸ŸdfÂ@½`Wï—xT¦õ§aèïù¤÷É'½X¢ìÍ»P†)Ũ	Œ“¥
&7S@s†à|6J†—²I±nMü ‹¦¢tCü?ÿÈe«õÑ
}òDþ0’òXâ×o5ØÁÿ8g“BÖºÕÿoί¤Ês>á~¨¤CWË4_¢ÛåÖ¿çCúþợ
\]ÏÖð
1MB®à‚Ÿ†éïØ5‹¹Ò>^Rïßz¸Æÿ&Ðã¥ôPº„/í±Wþ«½ÿØð­endstream
endobj
675 0 obj
4747
endobj
679 0 obj
<>
stream
xœíUYoÔ0~ϯð£]×wâ$ŽE¨…%¼@QUí¥•v·´¥êßgÆI|°«J<¡*ÚÄžùfæ›ÃÞ"¸$Ÿá;ÝTÇ“†,ï*A–ÕM%ƒ’Ÿé†¼ì H¸^’nQõ–’4Š4Úp¡H·©¾QÉ,Uð3Ì~ïÞƒ•–…•–\:0ìf~ÅjCß1ɽo§/˜¢Y­h‡òVŠ	«5
ÑP¾9h”ò ¤ŸYíz›Üž¢=~ÀÅiÒ~eµE´¢¯Á­ÐÜ·¶7yÃbZ×!@f}6Js!m:c^¼>ÁïáB(¥°ÐÀD÷Q`'C Ö
üh€kô®[t>ê¿!¬’Æ ŒC fÁ®iT_i§óJ×ÞñÖ@[ GÞHïû’_PLøZáë'rï’Þ•Š5¾æBøíQTÿ(ínqûlB‡VQ³–CAn%vLÓiÔ_'ýzŸÑ}n’"ßÀÆ`gýyÒŸEáÛ$<Œö!»^°J¨Û¼@Y:)ûQx…q5²…{ÛqYBqi`N¾[†Ç1Ríx¤J>£ÁC’¦,ІÙqCcjbtòüÃÔ`·Â`fØM—¿
Äí0%ýTô™„íÕ8$ÃhdÎÚ¾ÂèØÇ;ÈÔ›E‘KŠ¹Û›!ò¡<ú{‡¯ö	ï÷‘¸`ã2”VµÜµB’Z5\Æ¸ŠµÌ(”ç1syY9Tu†¯Ë¸š—'x-VùaÝe».NŸq¯,zœZ¿·äË(œ%á|_‹H;1±B
ÖX—0|Ö·O7ÔÓ
õø
Y‡¿å@#|wÆ· j_]¼KþeCs6ÿÁ}wÒUŸàù3—$Cendstream
endobj
680 0 obj
650
endobj
684 0 obj
<>
stream
xœµZ[“ÕÆ~ߢ*aß8JùÈs•4yK\vÙ©Äq`ýdò€wñBXì€/ùõéëL¤s¼§(àHÍ¥ûë¯oúáÒþÒáùÿúÕÅÇæËÛ_¸ËÛ‹.<=¼”ÿ®_]þå
,—ÁӦ˫ï.øE9‡Ë)„±\^½ºøæðÉpô£›Ò²žÇ0†àc<<Üè–㱦øïz—	ÎŽÉeñ‡Wt·,É·±‡Çm¿¶í¾Bs˜KÛ¸L´,AÏå¤âðiŒi
(Ž)â|^Åááý<'Ÿ@ˆô+χqcö·2öq?ü½r>ü4D1E<s‚M£fp}Ð#<Æ¡KrsYà\v%C}<ügš@qSæýùP‹+¤¯èto€–r‡/à@‡+¼z<'¾„ýĘFç–ÿñú<+×opü—±,S<Ü
·—AXGÀi!‘eä1æˆgI(:OÃðâ5Îsƒÿàê:M8#΀MTŠGuÌ0EŠø*nÂÓÜ¿àÜx\ØøsL³î[§ÁÝz~
Ah‡ïàOõ+Іù°ÐÚÖ-¢}×5e
˜ŸDq#¯ttesñÞ€)â¸8Ó8”.—WsÁ¯Ú„ždÁ7qÖ· P؃˜Îº}P‡¼øÝˆ2fô]ä·xl>Ouhñ´Ÿ7ö	ªÙƒa½6›Ò{7mmÕ3ö(§=úHuÂ%$ ¤ù±)wVq²$ù9I	÷ZE“àáâ*H]`¨Ý:OÂDR¦m¾Tó8Ó݆I§_IC‚Ù5ßÀ-´<ýij[ΗŸÆèK¹<Ðè\fˆ]KÄŸ8XsÂEj”)±Q^Ë^á4ibÃÇsþjÈD•Š=ÒRÊh외zz;Tñ¤)Ñ”Í$qüõÀÀ+x+eV•@€”ŸQj2M-½Ù³œ…/~ä÷ñühj‰Æâ×X%°T¾™¥·›ñà“±ç+d!Á~öŒ¤Š˜9Hžã‰»	uÌÞ*uZ¶)ÙkoTaBp*ú¨¯#*Âô~:A­ÄÛ/ÿBVÁp”¸3ЏÅùóÖÄ31¿—45¾;mp6uf•Ú§Wpƒ$e•£KIp·÷úgUZ_4³»jb~Œ³â`¡Ð)ž6 ò¼ˆ”™
Ÿx4WÐtɦ히2üœÁñŠ`‰´Û&‚˦,˜Ü(Ò­¾(•ùÍ1ôwÈÍm鎑S`PÁ˜BrÄA÷c–"ÑÅ·

¡ð+’d ‹~P™P…¼í32L_[N5(Øjb‚¿2ASùªz厶ÐH”'™¨úg^PwU—Cÿ³AýYãÆÍ¼9Tf|ª?P6aªêû‚éLfZ*Ýô€¥ˆ‚·9kš/Áeöd¬{o?IK¥ªÇØÅÓ«Íz¸ÿCfÂÐÑ­v2Fôxãf9¸*ŽÔ¾
"X¹’.Ô5¸'‘pSõÂ!â”øµÛÙô;o0h‚jX¦ž /[[xÉšï„u²w–óñ•%"ùÅ,³a£U¬¬ó 	ÍÆã~h­­h(3Oä·Þ2t^;vZÇbUü©
9Ñ97al"¿™™»UÎÙä*Ö›º'KN‰ßpãM%6ÆŸ¡§Ÿ½H­:3k·Ñ„Ö¿–„RêVãebºi1¥ÉFŒ˜(Oa}­XãÅÀöTÍ/Ä4€3>bº©goñÊÏø$Ò“o;ØËmokl±‹yÁ¬€±e>5ÞÍÀ³ìÂ*B4½Úõ‰Ê	•ñÚ©R}:#è\×Ñ–Ö#Ò:A=šù„á­8_7Wg‚ì³Áш8±5„îú³vˆ¯ñäG¼¡ç¨ÎÑпeþŸPº8¢&®&ÝxJDUý=Beöóá±¾;žÈŽšƒÓ{¦*Íί#eÚEvL"Óì܆žñÕ¢d'd;åÞG’à*›½Å—"Ík2“ìý6ä ë’v¼óä`­WãG}jdx7ti
ïÁðìêžÛ/.žBíá6¡þ“A(zâßeÓ.$£€¶¸3Ὲ:˜@ ë«aÉ̱|QQŸ¤c¼˜J95\ù˜6Ü“LÀ+ÁK ãÇ’ÄÀÁtú©2oL´¡GL‘ŠX‰ÿ¹’ò‘Ï\.ªцaa©ÑãË!¼¿…Pí°¶Ú­… ƒ`²k|Še'>j½Õ˜nˆ•ú±O*(¥U²U«V•Ûš‘|_ýÝÙ¡ÄýhÚLQÇØ¤Ë\SgoìæÓïšØâ2C7˜ca7ÖzØŽ#21Œ1 “ª rÐïïÂen´N©p¸­¬xM‰:­ß…CµÞ"Yn—ùb:3܃tê‚®FŠº¾ísdH´*˜ÃC­ho'ò—w$È™=†H¤cW]ÍV
wäaÿ;!Æb«,{ik$úxá©X?G^ÚrŠ·¯® .†2_té3UÊÂѯ„LîíNF¶E÷6×Êšrž1m‡±[X\óÃ}༠U¸URD:ß/±Å†”kâcÈ…’=eÅ>5±¢h<,èâÊTÝ.:û*M˜]‡Ó0ñÊ÷¨Ð*Î[Æ	³·Hµ•qØæb*ãa	êfjö,ÖÙbª0·TÐf¾¦€&Ê…
U«$úVb	J÷ ÁUJÙV2uøCçÜ¿§&Œ;ËRJQïéœ(ͼk¬è½qœÂPÿQ#$½uk¤[K±VNLÉåó銼ieåä¿6É·`éÉpÀS~Rÿß«P¿jP âó§íš
Úi¢#Ü«©–Wîã•9÷±jäR°Ç†ñHZvi˜¸ÞA‡0SL¸ý|>>Œ„MË\H²&AA"tTì	âþXæ:d¡_-çÿ¶óRmV²©Ø½¶Ñ¹Š3VZ‰¾õ4öhocŠ#l­Q,àþN²æd®Ò<1½âX·ÙÕyuA?6Á@í¼¯V‡ù©ÒÄNBLNªœåª¢xžÕTŽÙ%*îOC2½ôûL¡q~™R……#Ç(Õ^ÄÒu­¢Û‹­Ã—ëNbÛ&$nUܤ¾NU1øÀô—éP(R©gÖ“ÉzAÚ/µ\LCåØlqæÇÐ7ðí:Šj¬uÛu~(»ò³ýTÆ?4²Ô}×"f½t%b&ËLUŸ÷íÿ‚îi3]µˆ.å:õ‡ô¨¶S!×Ti:¥“¨tÆ;ª«e.ol*j¶ÒÕœ¶»ˆ¾õàVmÞ$¬ºã³€?4Ðè\­øýª¸æ+Í¡¬u‹Q²TMȶþ¶{;°½%^[Ì{š:û†ê‡Ìw"Õ•×ozÚ	ΆøìÝÒªiÛ“‰AE*IQR”öjfлnå3-ß\]Sý˜¤ò‹–µ¥½ˆÑº|ZpŸ~l’"Ç—0SÍñZdvæÛ7ù‡÷ù¾ÌÕï¸öºX7O³©›ë7&R½¶ö¿‰@ÇZV½3¥õu
k1Xܧ®“¢vVÊo‡å܃ˆ«4@Ë0Z¾x¶SYÐ.@—jv™hrœbž­äöñ=e‹‹Í× â±#|Ö«å6Áu³Õo1<¸Ï~nñdàu1Û©¦¿×3uuퟩóJI³“•kïW«O¸À­Í¡ÙÝ¡\ÝKk‡(Š˜±}IÅZ(\‘‹àæ1Öo½<¼àof#þôêâŸðç¿©Øendstream
endobj
685 0 obj
3533
endobj
689 0 obj
<>
stream
xœÕ\YoÇ~Œä/ðM;€v5ÓÝs	ȃO$A,'2ã8°
„©#IY¤$Ë¿>]U]ÕU==Ë•¬S»3=}~õÕ9ûóQ»ëŽZø/ýûèüÖÝãÑ“«[íÑ“[?ßêðæQúçÑùÑgDZAçâ•ÝÜÎÝÑñã[ôdw4º£Ñ‡]뎎Ïoý°éš~ãâÿCÓÿtüçø”ïÌSó¼ë‡øàñilüy³
›?6Ýnž§0o>mÜæ¯ÍÖmŽáú—Í–o¸Ý<ÍøLèki7=ô?l¾m¶C¼êÜæŸ‹z×áÇÍð©ïGË·›¶Mëßúv7ÆÏ´
8×§±ËÍYüäBÂo^Ä^NâB¯ÿŸÅ%¼Š·û8ûiØøøÑÓ]hõž†G ‡0`“Oøšz¼ß<‹.àÎì7õq\Y\E×a³4*]x
MñA¸u½Ã8î&ñÚÀSØN…âC¯y©IqÔvƯ§pïº	x(oïò\ßÑpm;Æ1`?Ý·=0|.?Áüýæm㦸æ^=›×”Æ;;bW§rx´R™`8µ\5ùÆû}çâp[7ÁŠ Û‡ÅŸ®;WÃÁ
²ÇÔl´ó0=õ0ýÒL$!sioaÞááñüžáñê1aK¶iO¶È1„­Á}…äèà$ÐoÜW?£œ„ Lò»v¢‹ßÀÅ; t é@±‹Ø(Á:Ð
˜ÄÜœ—Óa©Ñá©ü@;)À W™žWš"yË
ô,`ÄX.Hì8?ý-1¢¨~"8{QBˆ»#¾Úò‚Mý<Ѻ¿jf’Bž¬£Óù%v€ë9×Î4£#©h	P``-‘æ%åøÈ®r˜xC†Åò¶'‚µ-È4,	Ža	¥9C£öù<÷ö²Ø8ìvô¥L|ƒÒVQ9¥çêHl{À¿-Q©Ùp£Î+â¸4ıàßÎ@"¼C¾(†–‘^fªy-ãhn©Dµ®Š(8Èø=è=áNXzŠÇâúqqÁ˜x×b¸©tmë¢ív†×6?n¹ÁRŸÓYoÝØiàaÃ54ÿ|*jË h‡™æi t›ÛЕßìqö¤š«§gû#„]Q[8|áisì
êðiòØuük‚×Ôíz·€lã)oí„\’¨#ÏÈ
3jÚÄr|\|Ø€ï!Î3[8Ló|çÇ&^ˆŠì MâÞ²Ÿ[}Ìç›Aµv
q/ê­
LŃñ¾ýu@¢‘P‚íLÉ_…
¶-AäÓ®éCN
?sþÑ&q¬gÍé’A³ƒ~£™Ú÷¶ø,öÁ
lžÅ 5e)ˆh§xTt;ëó1 d¾™áÄÜæg@økÆ*‹Ð'‰Ç¢¡*<&ì	D“Î`E‡3³~–ýŒîIeFbR.ÚÐ?,{Ð*ËX±½áÁ…9ZÃqìå¹ôd"0ÜK`
8¨åÂìbÉ£þï…ÖEû„~ÀÍy””˜ÑµMoÇ¡fÉjí˜OÏH:ŽOêŸ9­À‚L?jñ0’5h¬*ãS¤µ$†)3>Å0±ŽZ¬„¸«ÈâƒVÐÁ¥ÒéaHè™Ö¢‚„ÿÆýîQk½X±²ŒÅBÉ…‚7~K~UÛ¹BÑÂê3zÔæ^”…8ðèÛðI%£ŠkI©æž›°Å
,Ö‰)É$mHîd±â#é|:(0|’Xñ²¸R8p‡J6½Œ#‚)Ýhíl+#!Œ%÷œ$uÉÝØ#2
wƒE
òÐß…þ&¾”÷C9ë§„)p´ÁTM«VUwšç9‰°B—9ä	oíM,ô¦é=²ÕÉ?ÖPëƒf->7íŽÒ‘U,wBUZ®%&v™Lól+ƒBê(€¼w‘U˜öÇÙêJbn4ݺCÐ,XOÙö‘À'\|@ÃZðÍÉtb°'Ûˆ·ZrIÊ“÷ö@tñ)ÏL¹¥¥©]¢Œt_Ð¥
U>UñUH
›M[m³Ëü¤n¬!kjÅbHqcdhÑÖ[|šA¬à}E!€5µjè3©Á $<“˜Ì‰½=O†£Ú÷ÄDÒAŠOüˆZ‡õ èHü@AôBÛ‚K8J(PÝ1¸2ö­8ø"ÞUDŒ%ý
}zxaÒóâ¦QŒ±ØfX3Ì0n8õÙ"L’ùFp‹Ý‰M_‹Oœ¢çc.m;>cëâ«Ï£É6’ðX¶±¶¸w«æ8V&¼íæw­§y–ĽúËŒ²ù¦!¯Yô88Je„wƒ±­@)»¦|0ªd(î›ÚQtìh+€%Œüþ’ê©b}ùa¬„—Òœ$*b”
{>Æ|›µ)!cÞ¹qfhÔœ–Æ¥½R7CÐa[žÀå,ôÜY\ðÑÔ¹	™h„ üXøbÊŽª¢ŠÑ
B>9<š§•±”ëW¸yiK¬Iu¢ñæ‰N2I¤	Ü“¢9(Œ…Ôá°;vI¼GU³ô,=isHŽÆ_9$a¦Ò_’HÆ"ˆäaE†±\¢õEAN+ €#GÍmDLˆ‹vˆ,ª°›2ðxí!ìóíp±¢˜^à™qzMVÊ]âÿw
^I:]W8lîåÑ{cëè÷œ•¼ÉJÅIëD€EJˆy&ð‚ÿìÌ]<$<ÆZÒ':üfz¿‘Ò
KFsJUÞງ2JvÒ.Â\Øøé
¸¢í>(dõŽUñÀÅÄ{1÷á,æ6{”ð}*¹Ô¯€¤»º6ìK7ï:5ž¨ìnCKôiÐ4µz^Ä#+YÕç`“å.Ê
í,±šÌ¥]î^[{óã+¹§4
ÊÅ®F;¹ÛâM"ŸÃ³K¬ì28&ÄéìgJ†ß1ß‘ãc•©UEd
±lóYyrþÒYy}J,…ÔÚK}åav´†­ƒlñÈð}ªôh´nFX§nU4l‚6»:Ò.NsËjœožX½Óz²7(Áƒí”B4†
ø ‘ˆ>Ï´¹1;‰É.¼ÎF’µ j6Ù:GÅã#ïIuRppI½"8l=ÚKJô‘•
¦:•ƨ°{øÓÁî˜kÔÎeýÄk„WèÏ”ç'¿—î’ëu‚:ŒÅKEÑ@ÊmìILI@„kI©מõ礫ÞÝ
M9š©ônŸ£‚¹ô͸ís7ù·h(‡^äš5aׯ²TFKŠÄièö²âu0÷èÕp”m˜tM‰ìâ쇲Ad@ò`áõcHÙºP)fs€À¾Qq÷Âÿ)é¼ð¿8>¥é‘<)¤~]i°§P!%9Ní£f·ÏZp~^ð{¯+11ÂRD¿ª…épÜÎåz]ó¡fzR{E,²<¨Ð½¬"åSK…SEú>d›â˜4gëÊim âØO¼‡(•HŒ§8ÌJµ^ âÈèÑ_„¬$ƸJèÌÑBè¿Á¯ÁÔ"2›_WÌш£laåë`|€¶ý1J¾
+FÈqóWE´îG/3†ƒ–L¾ÆÊ¼¤üzʺ¤4a™èó£[ŸØmÌø’£þ«HÌmÒQÈsJ«ÿ.K~OàPòÃU`p:ØeýØk!dÙp¦“0Ž*„£0AEb6¤®B-~îv¡$ôµØ›.Ûq™ÚY“¡©L¼´UœýgY_X­¥‹á‰	³]ɤ ¤ªC£8)«båé<Ë ÚÐÝ`I¿—Û&º.üÏB5ÑEûŒ{#Ÿ.¤ÝuÞï+¹ÙM̸N.þ$-«¶Zð;7n«9ǶZÖþ®£ÊP›@ªä³w\,"äcY–ù9˜d-†ëᯀ¥ªÒÈa+—"6‹b(×a,—¼ˆÿmëú]£«ª²„Âd½ÛSþ£"4¡)h½òÅ#„÷°vy‚昇ßuý¬ˆƒí·ò;…:æÂP_°·òuèÛžªü²€¯©âÕÐs¶õ0nÿöñ#$q*¿Cƒo½,ü¾©8ÿZ¶«¿)Cô‡C¼°V uÕ×wò°ºx߀Êÿ6™äÙ¾à3ƒ$Õ¤߀̀T¡9/gòÔ–C»ôñ;.OÒaÉýºØGê?ÌfØ®(ú¢ªöà —™œ,q–Ø_!V&/ˆ¸,[Õ³Ëi2×Úè›rFÌ´2yË-SíRÎ1!nЬ/Q猶
ã ë—åc]6`|g{½¤m)ծlj­«¥Pfì´OžËÑIý:·¯*¢ñ¸¡¹É©µÌ•Ú\vV;¨ÆW9ƒ’¨Œ%LÁgEžªa"ÁLk"—KÎ!•C¨âÍ™L¤+D'Ê¥˜
Ñô,—_N£ÍC¹ÀÜq@’Ké¡C‹ß«/•MšT-"¤Ë€xUk…¢¡âÛ¡Pâ	|Ë¡†=Iz`Šæ¸Œ/¬EƒÓ'>]AõÖ}BîűîÆKw),Îaü¢ú\}g´‘(Îãøâû¹¼n«çtñ'EF»œÓ©ëÐNâa¤Øï¹±Y9ÊrŒ`í£å¶D~:Æ;ù•‡†nfRJ5×D¨¯š>kµÄ¦'Yè¡£3(â»¶T­ÛNg•B×.˜Ș8¬Û9SF†(¾R +	íâ WßX¾^ÓêÛ—yrk¬ˆén¦ÅØ1zLÁr,¥ž¼®2E|~bé¥v‘åò¬ÿ‚ßÿXü°bѧÁ£?Ù@á„К|a“t÷J†Nõ­¼•»rñ4<Ó¾Rv#1ÜjïH½FòLu¾°f¹¨´{“ˆ‡TwˆÌ™0ЋkƒŽ"k:H…çнõ¼3–_æ¾%ØHT8M³’†Ì­íH•¾hâÏÙ³U´øvâÈÖ<Ïm¯kBtKd¥&U "ç
½88Yeö‘
z—p]-¸ú#ÂI–j^wMuñÕöç“–$¸Õ•§|Ð’#µø(MmÝu=,®ðž‰è§B
Â4×{B
{ù¿Xãjw¡/^Õ.j’`j¸TÂ]‘ø+‘ÔÜðqCÞJÃ<Þ+­ó˜rß×	4–^ëysC/[6Ì«®ÒÉ!"8(ŠºˆTG3†KŽû6½ýõ÷Ʀöá]ç¹,»läU9õÖÜÞ×$ܾWÁØáO©þ(‚m)âÍL¤ø0ÇÞ‡néCRÄï#Ò>1|$‘þ ´í¥üÉûÿé늿ª‰ô]i˜í‡³Üð…ˆ´™ÎG‘ÔÈáÞÔvM®ôÓŠ:Žës‘GËQy-H.Åcµ9KáÓÛ¸	dI÷½˜N51:—KèjÏ©zbö?ÚºȔٙ¤+¾µú}Ÿ‹ÞIòi­äWÝ.ïÝÒߨZòu¢LùÜMñ“©*í\Äì—eŽÖr«a¥ÒÜãNx(Ic¡\ºd*H*Ô[`ˆJïÀ¥Ä}ó«£8PJ[lƒ5OGšãsS¯^i1ù&]nì÷
h¾N½foõ!å[¥¨o>öMSý£éÝ—äâûå» ‚¦dõ½@£¢+N³Ö)
¦>—yÛw¿9Ðy{ßÌ2/šiçLØtöøµàtl‡%6?ØÆ6Ë£’CPkSMÝDµ=èÔMïó«ik¥6óT‡gHvÈ!Qkœ!©dg¨ãØ•øøJD$‚¨¢Üh½…kßeíOÕÛ;N¿ðã×0Ë>ͲˆûãôÛáæ¥¿|Ó˜§}XË	!úÓ	Zô#`¿£Œ†K?YÃõ‚Äv‡¥qö”œýæ
…3{%RQê¤62XGúɄūŒâ^O\»
㼓Ȍ>
stream
xœÝ\YsE~÷Á_Ð̰žq×Ñ»l`°†µ…±x-Yö®,	ËòÁ¯ßʳ²º«G2A,Á¡ñLUuYy~™Í/{ÍÖí5ðÿûäÅ[÷ú½ã‹ÍÞñ_n8ìÜãž¼Øûb?
.µlÇft{ûOoГn¯÷{}ˆÛÆïí¿¸ñãÊ­ÛU“þ¶kß·ëÍиmãÚÕ·k?lÇ¡õ«©ó«õƯî­]3b'4}MØþÃ:þ¼ÿÏ´¦óvÍØºm7¤e÷y)Ÿþúu+ƒ;zC»
ÝÞ&4ÛÞ#=õ¡ŒîBqœôÆðÜ/Ö›°zOáãyúØ6s«øyÛ¢wõ
>.àãGàçßÖ›8tÛqŒpÀ@SÀÇq:jj†g¤g.rãO+muú­1ýkmýY[ktsqÜz¥Û§iCaX%Ò§	ý›vW§ëM‡g.
wÓÖÓZOR7=á;ºD N°¨Ð¶‰¼›g0)x¹ÏÓå¾Èû>H§?3B¦?Õéu2
ÀæR‹÷°UèŠÝê0ÍÐ%¦G"û}µ–Õž™çx=§lZ-mæåzӦ݄>ÍÔ·«7ðXD‚èa#<µ°o.bÔ߸°m;¸€…×_èýe’Dä€4f]šÒE¥ÍIzì(›;…QAΞ¾âþéô
bCmá·—ÃSÂ%ŽB1³ÂN4è*+ÇO—
ë’d[p¶·ëË–çP2Ò='l¢§…™êÑ5v^ ohb¢«Î6›¸ƒCˆDéýÔÃŽ­ó†1.u™¼ÂôlDò-¬\#ÇB¶iÇN§×z€NRÚãL°6môøsI®áÈ‹¨‹‚œž…YÎ	Npµsh;ž€)ìE›{C9jÜêßʧ—“K†ÝÃòIn¯)ùt€QržŸuÖ„•ðÙc–ž#"©$ ´ÜÖuFéïPQ¢`‘eIÁ8…GbQ£aփ™,…Ò÷àÆôÃȧé>@…”ŒTˆödäë¦ÏéB“Þñi­(zçiúÀ`¥	«>ð§×6¯ãn¦ö8Û¸OóE´vFiôµ‘¹ñgùVµ…]·ÑÚBß#ï_Óòõ6ƒ‘ÀÅË¢0ì¶’¡S9>UAC‘A9é­
µ¼S0¨#†9 uEYÏŒç1-Ø4lHˆgø¶
\ê*>CŠKÇ‘Ý#*ÏØYzthJEÓ7éš[õç¸/Œ
Rú\„m±÷…P¦)B+™&&ùýˆúîÑZîë¦lËÝ8½UÖÌåí?Œ*"è{½4Híißbg…CΦûú…ã
d`èxhé%Õƒ{œÙôlæÄt#rÜ¡ÞÖÄûʦ.3ïµcK&ûœu阈ÕSžËº,,[Þß•aM2vx2à”„S&ºÖÈ00K—]½·$ À•Þ:}ý`]šÝ"W³	¥Èf§s‡a‹9á‹E.jùÓá_ÁÏðßîÂÇ>|܇Õ²ð„Ðè‰6žåFðzºˆ†ížñxµ?±j‹†/¬>K_}ƒ¡a¿:Š_Uc¤‡¹õmÌß’}ˆcWñ×´J íòÈŽœ?îC´å“ÈNØ»1àZODKM§£5ŒèFÔ@~	ŽªœH–‘|7¢_:·T5ö}ǾDúÚü&_Õ´ñ©¯
¢óV(
”f>ü‚ç
¤£z	
ïpŸ3×ÖQ%Ž2dO÷P|YrGô—ô„ž/¸q¤…_¬=hÞ.ÂâϦŠP‹H˜p| ®Ñø‚ç¬/<ªÄa"þÅQ"îPÇz*©íÿˆÔ&ζî0zªÉ\e*ãxàšâéZ¤üvÒ¤‘H'n´Q%=`ÔÝ)ÝUj–¥„‚.Ý,#8
ñÜ]O£/6Ì.x¬2>¶bá‡ù":l32qÀ‘{<Cn;Û÷`2ƒÌ¡u$#‰·€·u&~„wï×ë/¥Óù/%Ô
½bëUųû$²†ÅD½‡4GÓŒ³Øhæ®ÑÀ¾p³MT+vÈAqØ*§°`0õ
o¡ÀQbÛ#Irã[ÕçÙjÏÍþ’÷ ¾©FÑ´/0£cÀ+ˆ1FIŠ7Ë!1ªä´^Ì».­„4`_­p™Nâ„Ǹìò•·qzåÑ ³PpÁ£Èž†›xšð\rýÀöbÄÆc‘	}
_ÁÓ—?ƒ¯ð6~?ϾÂ?ÈÈà g×L»8\ivéZ»úý¼B
Vl«YãRl3ÐŽî¨VÀ)ŠÎúE€JùÐUq©%p(ªš6¦qꯗªŽÐ9Æ`dØK(Ó¿´ü£—¦ƒË"©ð'ÂaÙì¦û91¨O0Ñ•¾Î%û@£AÓxWáF(–-c£¬¦æ\6¯´¿ƒö¦Àtw£^bâ^±^o·­/LoDP¯¯ ׆kbž­GôòÙ™,ºŽP'=÷(ú²T—Sæ2k³
¶P«TíS|à;`НÓüŸç(7.Nñ5aËÒ1Å@øÜ{;%P ¥4VÛÑ„(²Ø…Ù,…ídU63;³Å}#R…À‡¤×½è\𚆠O¦{*€€
šš˜(Ä2ý6ø[a>ÍXÁïfóÔÈ\0WâPˆ³{T¢C³ú6”±8X•Q2Èõè2"*·ÀÀºÕ&µ`ýŸ5©ìŒ^¬kP+¥‹é‰z0
Ì€:®Ï‘f_Ñø.nDÌ…3$X@
8ú…(!H™–9¢©@ã|¾ÎZɯnCG‹¤)UÒ$ß¶îs^Mé)AL(ÄôºPÉfSÏ;”`£(=LoyöÝ“‡úÍ—	;Lž¸Â‚0{qÁexiù²1Òüß­òxÊF3û„N
Oa`Og!'aˆÇÃõÛ<ÖÆç…ß)®Xe¹©ª0Ég¹5cûù!ƒ­4Úsã`Ÿ‘Æh½Áe”ß'êÞb0=e¸®tý@Ø®‰§‹!elÆ,Oót@0€¡ïLFÒ*ÃoÌy¾¡«2Fˆb@¸9™qSÀöL¶RFàDÕ…ì·ÙhŽr¾œ$–hŽ«:ÓvË® EL÷$à‘€Tæ9ª,‹äsøJÛ.ì¹dÁ|®_s·
jež6Еw)I:zõíë#÷óÀ2‡°á'JöþQoöŒï½õ
2 òƳâö³ò@NE¾lˆ½¹˜!SíYq%RóðI®Fp5bº¹æñ”MS"¬*ãl®ùªd-`·^¤T?(*wT`1=x/µÇâ ¹Að1ŽŸd4îT|“¬\{#x°p²bưsEoæëò°QvWï„Ahi|_6ƒÐ_¬-vG03Ž»3Û—©…´Pò‹ÚʦÀçÕÍEM÷pA×<¹@»wížÍ6Ô’yLíÐÂ;e2²°íš‘«ÿ;¬O>½«dÕ"mË\uVÞPFñ'ÕoååE|²ˆœ†Ã¼
¿X_Í“™æû|^»ƒÚÈw‚’öõþ—µû‘‡ÆXÂtŒ+—/ÿß&2Ó×Ú;÷¯Ÿ÷òç¡3¡ËšdXy˜3´Ñ(I„£3o^–¸­ßëD'f:¨äcLÍß™.˜¹ºšNø¦²sC¡csÉÌèëË÷kg}¢+/lL³§ºt¹3£¡dhÎ>½Íýw¬Á¢cky©Pa:ÓËÊ¢p°¯öoü+ý÷_¹lendstream
endobj
695 0 obj
4643
endobj
699 0 obj
<>
stream
xœí\ms·
þ®æGè[o;¹õ.É}˧4vÜ8“:®¥LÓ‰3YﵤSt'Ëþ÷%’o±w»é4Çò—IàÁ€\ù—ýª¬÷+øþ=¾Þ{ô²Û?_îUûç{¿ìÕøp?üs|½ÿÕ¡ïPßRÕPïžíÑÈz¿3ûueeö¯÷~šÕE33þo_4?~ëGÙ:5eÓú‡'¾óãbîfßu9½f.ÌìE17³Chÿº˜Ç/‹¹5UYÕåWþoéŸWû6ÙñÇ$+Š0³ç^ê“"|y’ßÇÍž¶¬*kÝì<ù~ø>Ö™rèúkê-Èogżõ­ÆÌþQÿ¡158,z‡£~,m¿µrûó°ÿ¹s¥é«šÔðw/xv?NáÇM1o`·U7[À÷[ùS×³Ëøuvî7:t~UvvGûUVUOcÞÁì¾L£W©Eô8d•úxatÙ·³×©ñŠ½ð¦¼ª:oÁøü	?ÿ!5~‘A%uWÖ­G˼¶eÓ=©à,­(ŸB.ø}®Œ/àÇ£ôã+¹rÚ,õ{*E[!÷.¶y­Íüj–>.
Psݹٽ\Xó\,”Ù¹D†¶SîøªA}SÙÙOéù7üüIjü!	º«H•Ù€—Üq‘&dýÌyÇIÎB³ùS!liSöÑ™¯4¥œ¦™ï&f†Îöþ¹˜:>ÈæŽ]/¥ZâóѤCsÆ6}Ò×I’ÐÖ
<à®·©ëifµ	|Wrüœ-ç¶ò¾âßÚ²ö$@*C’òŽO€ë}w/è3ø~å9äÔ“Öª°
(ÐúkD½,>ýܯ[äůü×#Ï‹K 1xFô†¦2IÜ
ñVí=:_“C tÓ¶A™aðóD¨¡?ë8ŽB¢b÷TC0@lƒéÁª=,Õz­ÑZWr‰07,/®IYLÎý_˜ø€TFÊÊE“ʦ¥…ïDÞ'~ÿhÝfC#ó¤YÁ¼µé½"ã¢&W…ÐBØì˜ökm‹ â?‚ñ†¾MË¢YÊMaZ‘œ-
˯¯>ZßYF©ó ¤TàVÔì–E*K¸ðS€ÉZT?È5ƒCÜ]f ¨!p8Uo`°5‚Õô5†°,èmaÂl#¨|i¨Q>L‡X'Ó{hÔ.ó„¬êð(¤çõ
à«þq@çÜt0ÿÀÆŽ^dš’Á^š-Ót0‘­	Ëø}QØŽ´ñNú”ÀÖ;¼"ض	K`ƒy…Ñ.Ñ+Zƒ<™HבODo$,€fº
7ŒfH’â'XØg
º£~TãAbºN¢óˆ6Ü5À4Ó‰³¤LòeOˆ L$Ýäa=@À‰a‚Òˆ÷MñÜ™ç‚JÚô©žk+HIÅ€¹£4‘ÞP9˘ÃÑš!³pgÅÚ6õÛA‹Ìà+‘aØTì	M…PœœvgŒöLéR°…hÚ"Â~#Ï.\ˆŽ0ÈNœTc-’
ÓŸ	#'²ÓTGTÀ4…²{43##mæ*<í׉„²ñA_Æìµ…ƒ/ñ““(( µ–3ãg‰#ÉYØ×ÊëœFûÆÇD–BÆì†)6~‘Bjæ1/|š>›Öð´v6:?m£8ÛÐÒ~%\’BFeÖ8, °ó
1:…â®ô%烴tsŠÛ÷)+à)“Ãò¯bL[ƒ·ÿ)Æ,‹€¨°K_Ê•O¾D¤ÀôŽân™˜æÎ®;ûZnƒ‚Ú]›q’sU§ÝNšÛ5
ŠÙnîÍÙØ–`h²d,.ä=<'C‚Ü5OhÚa|!ëÊ6¥kK<F®ÞÆDA±ÿ>e›=!-ükD@Êq¾3øe¼)°„ï­°²–ÏÔ†,Áï`‘^>n1"1¦XÌ$µIk!­kXhÄwÆ]¨«œ»F!ÔÕDºÛBhÛWÓ@
ý#\Mƒêܲ.eq®6È2ÆQ€øø.Ô:yþñ!>Ž Š'"=ˆ±³)SÚ–&M²3ôGHL)Kö`zh$)	ÆÓXHbYæðLÖæ—icèÛyv¨˜ìq­2¾EpÊr3ØžšMëÙðºp)jÈ¢—6À²@³2kÓ×[™Ìnä$k‰“RÂ6NÂùìåÏèü8w“˜oX`¿Žy1é°5Ú›“žXfWË9‰N.k¡•al~Ï8¼Õl².¬(¾2/Æ4Àt“3Ù—°Ùì°ã&’~:—(À¨+Ê!euwŽsC`Çœ÷…‡'”µÂˆ„yÞÅ
¤(lUÈYדf+æÖe¤Ê£e
`-‰ø@z‹€—-‚'zAÕIºKYbä"!nÁ;á_Éœc®óèe¿_»ÒºÖàV\€§²Ò&"©}AÛtÀU}j:P6uå=ÎøékgTtzè<’ž_᧺‡…˜²kkÊ›Ò
–¢UÙ÷Ö:ûjÊž|»êQ›']‡GëßíþiíŒÍÁÑU‚-Aa|¬æ;eÕ£«+	S’Q7õ䬓by4­«úx’§ôQÖÚÁÚ	„“9‹;_ÄŽ!Áñ¼rÁ]&§Ó¶sIX¡(ÕNÙÊ­³Ö$$rÈ,ááÕLɧÊ@€ð/d=¾b¼]YVôV™CŸ§F=3G¤­õ•¨ç߈s¼WFT¼ÜFÖûQè'
Õ)”9†>!ˆ:W6ð;J±¼Šr…"𮵮•ÙÛ2±Rͱ†9åJ“¡î4cM•[è«™×/jw…Â7ýEKf'Ûq¸Z$Ýj øyª–óµ-Á¿Ù;â(0Ñ™jZÁ.×ÛA9"˜åÞðñ„…ª¿î3Êáä5Ü$v¢qlü¹V ßd	²-mÿ°:«5•’T‹/&Œ;®Ä³ßn‹ùxÛËÀ<ÆÐBëí̳ո‹l/ã¾hç¡.Ûnè6‘ÄØ+™*Ê€
¨,LA*\iž$¸\†p%Ž2¤ÙœK¾û<Óφ=ßÂú1¦­£Ah+†’‹-¡F=D»ÖÕL0a=’<¦zxh)Ö“¯-Šxï¡Âž^²ìé&L¢Å¯}&œÑ/µþ^óeøuÙ˜.Ó Àô<í’¿—È·À“±ì(F0úÁÏï±"B·»t6ˆX(¿Ò,tÄk8֔øš"¤±/LüÊ«‚ú#iØ~7@¥XI§ŽÇ‘„ÏÍv>¾|7¾ã¹²¨i&Ï£EF…ï]¶ë•Öm¢¥EîK“i¾PY8êË`k²8ñ%Î_6{ÔkÍÖ”ïëT;ù†ƒáou@?ŽÓk0Z
ÁŠ‘ŠïxJ¹~
Ȇ]³î¶kÀûœ=EÛVtrÑó5?™Ÿ³Vï6›R\Üì~CËÛ@«ÚTÜhïžjm¼a œOòaÈk2í‹ ¬8g„ÅGW€ùÙ‡þ¶’¾Ê$õɪedzŠm&´í݉7ÿß~­Þ>,S®yGmµx]¿}˜ü¿D–«#KÖN꩜xcj“ßÊW·T	¡@|Ѐ”½¦'Âkü/Inµ•Üi8¹ÔÕ›òÜ£v.WÆgf¢Z\»N¼O—ƒø}¥uÞ ÿ.#µþqŠ,°–5Z…s‘C=G8áÔO½S¼Ö܈%½çá¿ÓKA5Ÿ7]iìèè:ù"»akûñEá,ê:ÕTYåÊì’^TNA5»ìyÞ7¢“?K‚#cɽÙãÎ2T(‘ö4³ëׇ{óþ
ütè×endstream
endobj
700 0 obj
4084
endobj
704 0 obj
<>
stream
xœÍ\[s·rÎ3K?bß´›Ò®·ÀUy8ö±ËJÙ'ö1ÏÅuœJI¤Dª"‘²(ÚÖ¿úŠÆÌ,Å8a*¥"¹;ƒ@÷×Ýzôóf8¸ÍÿøïÙÛ“§ž67'Ãæâäç‡77üçìíæóÓÚ ¸zåP†â6§¯NèI·™üf
ñ0øÍéÛ“lÝ.m‡úsØù­Ç¿û<¸ÃàÒö«]Ø>Ûíýö›ÝÞJɱl¿„ï§»}ÜþXø®¿ñï§ÿZ‡uÞ“;Œ¹Ž|zΣÁ(e—¨ñlã}ˆþãf†ÃäJ¡‡Îwû°}
¿nà×óúë0ÎmßÕ1aø<Ú/õ~kù¾Ý®}Ä’áòöW½¹öøÕnŸ†R—"n?i™\©_¿éZ/^´‹ï­trñ-Œ”%OføßÚý×zñC7¾>t£÷ë˜ÉÇe~Ý?ÏÓ›]
uÿ‡RÉÕç‹bȰ@rõMûøQ?»pH#(Û7'§ÿüí­n#LtûJe¼íúBÁ†ÉÜ¿î–PÖ½Íñe7…¶Z2Åwk#½_S¥¶m7kZAËvÝ}¨sxŽ/×è»õ²Úµ\üºõˆÆŽ0¥qû¤îàê|2Œ«
E-`9Ë€^oްı*y+T7Ïêß§U¢§0‚Çíé„öUÏ|7«‚ÔÑï­ZªÌuÆjÖ0âév!T‡1NE@^W7“ìç²8Ðíö…öM’Öfàn<­\3r~Äîè*¬P$ÅÅ/yûXç™êç:׈«P´mö(Ã;ííî©;Ý£­—¦‰d¨²Àìö2½½bÌò9=@ª‰ƒ8þ)Lª?àÐ^€ð‰VÆ%¼
ƒ¾%ïæQ1á‡×9¤Œj·®xˆºâoÉÄ-¨[U8ЯَBOæëaÇ:o\½–’“©±@%@»Ý¾FÃ0ŒÔÏC©-#ØÝpÈaòxðÖ†/OuöõQçjw!nÿT7âàëR"pkcÀ«Ã+œTÙê®ç)¢„a¨¬j5¥ÁÃzùécð]·uÏÆ)ÑÄËX/Û¯¡ÓP˜T•óaˆI>W¿:AœÆñà=øîõäGØ¿ªT¿ÕÙÔ©xO›Wxù®N
P–¤Îq”Ç£wÛ_àñâ\^¿­O¯–¯RÕxKVÿ°ïè+ÈÍh æUÈßÀîA¨И¿Þq †¿`†1 " bÀÖcU80þäRH>¿¢«#õLWAïL¹@Mã„júbW§¢=¥@V•ÐRX•Ùþ.°ïìÕ3
Ê|Î6Š-óônȲJqÛŸ¶ÒÁ_v"ÛŸqïKv>Ûàõ§ª›."Wµªä —ÌÇQDÇ‹p-P‚ÖFîöЧ:¬ôèë\¿‚‚Y°öp"bà’RDkHd±ŽÂÈzª^íÑyQWP1à6F^ô‰`‹ç†°•
»ÃOiG$$û”JPéRnê½§'HºÔ­‰A†/OO¾?ùyÂaÄì£J_±gÀÏ›
¥ü­ÉÌçÏNž>ûvóáýíË“§Û¸“§_ïϿû¢þyöÇÍ?|ùlóýÑD§7)ItÜ䱓Ê!EJvv\³+0âØñÊŒ~»°ücþÌ-R{ØQ‘VK­ki|Ñkön/¬£®î4"þåšqØÀ1‰ÎÉv@;ô9y“öhG«	Õ4ÒÞ›€¨Eßä“–&,Á÷¥¶Á_-€ýùŠ"bÀÒXFÉ­äa
.CíÏôâÓvñ©¬—‘`‹ŽoÖ.šüël3ÚL¬Ÿ¯Ž<#¯Ör¶s¦œÜ´>NË'~Á†Su¦mâ¡5tzÑkÃ|g´ëë£&›ÝUÃ}ƒ?ûèFÜL	Æabu_Àšê£3ù§ÆÒtñß å Ñó5|%_³èílBTíC½&@ZôQã +ùºŒ„¡g¼¡‘ñ,ÐQ;#Ñ ÀXØ:C%*©îl‰è"Ütp£º€`P\êË36¨¿Z	Yk¿…ÒPÍ%Pg«Êv~ÒõÂsFç9†×½ø
W-ÔèKw’;û¡µ4‹¾¹	9žiç®{‚qäDxúÐQ¦ÿÿeVÿ–Ç`Å!~‡4Z(¼uaF·iŽ­ö:EgOcm[Ç¿ÁÅH>ɲ‚·ãœV×IÙ~l±igñSr¹Ü#4=‚Š`—<¶¸¯¥¾’&	¨à^ÄURK0iL´Q¢fŽU°Nýª\`M”»£Õg´‰¾rfžl€fÂ:éÄDs€¢·
,o@ZgÛñ
Â#XTŸ‘`ðÀœ")p…c5 Ô¥·:e¸¬ɃEØH”ÀªF»|K3EÐq¬Zbðá;ØÂ “n`²ÒŽQ	Aƒ'Øc†!"4J„59cÄÆñ¾@ó¤[—M]„¶ðCãUÌme`Àsò‡õ”{¹Û,Ÿ.>9^_ìTxƒ#aî’	û‚	°‡1,C@2gTMáˆ&²l¤a¢Oa}šk\ýðq—9t}BÜ€¬=¬ x "–Q{Ÿ0T;S5"ñ$³iª'vÖ\Ðä›îhö‚²›Î[¢dÒ˜=€cñ5~Ã^ñUëÂÜ¡‡®9ÙíÏÜö*¦7ÏY–ê?ú¬Ùö±G¦Úëý"¨Þ0S )ƒ™ª¬$¨1;§V@Ã<<”,øŠEÙÌ€@Ñ œ¼àª\ˆÕÀ´AÔL©ÏãÆL$HwgÌóU[Ï&"­°”Ú¤¸¿6Ø0Ñ(¨$í’…ší5Jq¶#Î!’ZtÔ´$F*Q>‹¥Cç…ú³öºFØÉ?œsŸDÜßpÄ	±a2´LÏÑ¢"×"öÈöÔs‡ʨXÔF)Mm$
kÕ9ÞÁ»es?ÿ:O
hBKy®ûüò9RÚÊÑ{M#Þpg°nSºƒâØPÄå~§`UŸôf7¨¥™œ áDl%HÁ¨T¶jpÛ‡×ì=ø&G±{q_MŸ1åOã´·ÕsåþX¤ßÇiPúö4KÖÀc0~DX8vû˜ñVÔ„u:Ž”09H“á̵;@~7ðŠýg;˜Ñ$
cÙZGâú0ˆ®Ë÷nߌ"=ZG¶Ý"¨T35ùÕ"Ž)J‡vuÍBÉl2¯â”8Õ*™7¨ ¡wD/b"’QòS¾j¿kLAï5åGM­.ðH‚q„§Ù;(åu䄨·F‰iÙè-c”é\áÇ]dB¤\lôŠ’AŸñwWângÞ,Pâ2l¨sg±ÞDÒR<©©‚Î=ç¦þ9Næ±Ñ@lþ6ôñqá‘Ti%Laå~×I°rì£íÇYàÍKÛ%ÍÍæ®oü–ˆœ¯{¯ö’ð<+ÏÝ2%Mã˼®³6gçèÝÓ+âõ¢ ©ÙG޼‘<ϳtÅâaÞ ð½R!7ÚÌfl.°ŠÁ†¸…_Qubà%¼¥ÌSNp=Ð]³\ïõïƒyGó\
‰¸íÅ®³]µÇ @¡IÝŠC“dFÏFùƒ÷”sñZxŽãÛQHó4µ	|(SOðxfÌž·§ç'0sò޲У›E“LBª¶]ñÙGòXV	dè9*{Ÿ[¼Óâ%Íü츥ýÚþôÞÀvÂùzŠw ûGíú‹OÞIt‰%+qÙŒeõ4"yX£¼©TU¹‡;HÈ5æG:€„ü;ç<ªÊ_ë7)¢Z—4å¥T.éè@C¬¤fñÿ‚êš¼ƒC6>wúÖú_µàŒß‹¹,ùC~Ìiž{&SL6}KèRÃ$W“o'ŽâV¸Ä£¹§‚Ù”ˆÑ§u"H b~ðòúh†u–¡ÐFøx©:õ„1£k%+ÈÜŒ3¸"RÚFµâ»:Þ6ðË9(&ÝP؇ÍñÌÊ–…#ä¿a» ¤­u¡%T‡W›µ‘LuÇÚH=)3íÜáV¢•'œæä{'螜ñdIÝ™½—ášx?M*!„ƳÙõ"FâËÍs=ú¤Ç».8’)Èñü×zøÝÈEäˆØ“Í“ÚAÔHè=ȸ%†ÔâÅ2[jkA·eEU?Z73ØÄ©'4bž'2Ç‹DéÉñt&E›Î„iÐÔ©fª¯Ò-%F5E'‰Ÿ6Õ7$Ü»ïÝ@hÕfr/­‡vß5n…!>£:—JEÁÀԷÊĘºáV»bŸ}B—J•"×»EÉ,qlS%[¨ò428§ô-ånF
'À‰"´wA<ŠÚc©Ù¥7hPúE‹ÔØEBóãµWW²[²c¦–ÁÜ0 …÷zÎvðm”»H~Û3µ÷bš†õ1™Ø¬¢£¹S—Åñg‹_=}=—Õ·¼+Ë+çÉ:”¡b+ák¥4
¼,íb*Ieù>©XU<­{ee’øŸds³zõ$#&ÁhuëISržs¯[ÆÙw:!lÝ(±‚ÕÍ຦¡í4Ž“5Ç]˹ï„~«({ËÕq!h‰¾´õ5Â[ðC昃J^r+6	Qò«YÔC³‹Y9§j´ù¢™ëGÙ}]âØ˜­–>°?ÈEüu¦dÔÐz,§qOÛ©w¢ÊÛÁkà¸~n¥pÁ­‘QÝûeQq½6‹-ä0} R‚O{oŸî—óZW¾âí!¥ËG
*D]ÛVh¯œðŠ? ©	¢îuôàËP•„ؽª:^ôᥬ±åê$‹Àg	"z¨ÜÎqwA©”v£}joœË»ÄN`áµ_ï÷ˆcLB芛ÕÜÑtûhµE©Â_¶q:2ƒwåRðZj|}‰Í“q	X«Œ
Cì0ÊÒeÒÜ,üx³ª5‡)&‰y$aÏ‚7kšª¿IÒ)qb£-’çΞk¤➸Žp@\)鵊+µ!ñšûµ:7ëOÍïTŸù½5G&‡^³0»wñ6è¦I
ªtTŽZ0AªÛ7WØÁ>­`Õ·uiTNQ†®JþJꦰ;ék#L†•ËvœªÌº¾¿óŸ·3;òæðJ–}$)£üþ#H
¶z~%ÏD³tFâ©ÏvúNs›³íÞU‹‹ðÂGµÞê†ÒàbŒ‡ÉoÊt˜°Ðým;š4¥„]x¸.îè VþÁÅÓÁÍĽ\©ÖmŸMf¶ÇõÿÎíI®no~ðùBÔWÆ~¾-^–⬽“ÙŸ;ÎÕëlâÃÏ"‰ÿÝ“su§LÓê;é‘cæGÉzsW…€ÂÈ›GØÞsÍ΃qçàÿñ+Ñ'˜Û4Œýغ̱&ŠùáeN5ü‰½Ìëï½ê;
cá ã½ÀfþÛˆ8PM¢¬TXŠoù^™=\mNêPGvŧü@ïKêeò×G_¿Sj†É:é{©vù÷*¼
WÊ,•Ã)•ýk«p¶’õY·¬Öƒ>ÄÕó¤ø«Ëޱó2¢ïOþß²¤´endstream
endobj
705 0 obj
4927
endobj
709 0 obj
<>
stream
xœ­\[“ÜÄ~wRä/lå…QÊ£H}‘ZyBXªH…<¬wM½ÛçקϵO·¤ÙY (`f¤nuŸ>—ï|çh¿»úñb€øÿ×ÏüþÓùâé«ÃÅÓß=ñâÿïúùÅ{—ù†Ñå_úeXƋ˯ÐÈñbv³ýà..Ÿ?ø÷aìâÁç‡.þçò/y”«QËÒÇ)¼¼É7ÿ©;†Ã‡ÝØ/K
Ëá;ü£;ºÃ%üþAw”ŸvGï†~Οç>ôùªcþÍÞø…Î%S¸Ã'yÖ÷;þò>Ìó=áð¨óý0xÁ•á?ù\¿¤‡Á‚þ¦·ÁEóO‡Ïºã”uîð¯ÎåÑ8à²KG}Ñ9Ú~-´#ïÿè‡~ΟIóÄKže><Éë|šw÷užâE~þ'_‡T~{š·çÃU¾¿ßäïSÊw%ßþv›ïû*aÛþð¶ó{÷}Òá%ŽxV€_àÏa¦€Cñ7xÄ«"ñ<Ò'çˆW®ó¿¯Qbãˆ+þW¾Í_Þvi†“Kù‘º%ŸÞ0Ñ#aYèùa&N“ü
ÌÛ¥­¨¾ê@º~{—D™t€™6ðº“o0<ß•§
YÖ/`ë v·é!L*:á×pßK5S=ÓËyo°Û0‰T&7áš§Ä.ò| ÿyvr¦y쵎]-ÒÜeæ}HjuäGŸµ	L€‡bqÖ^J?aO“|øÛ’ñ¸ùþn›­‚ì
è3¸àq0\€µÑòœ	(û5|£¯Ä^ðF—VÒ-Ê¿,³Ùy3á»ðØdÙT9–žw휕&¡Üfw]tÿ	j•KS¿8Ñ*Ù×.jk¡Oaª€êºó3|`ÑÂ9¼,g_ιèÍ÷°8r<|yÐëpÅ͈™U‹úÀáIp8ðùz¥Ü}ÇA>ü.ÿÚxÁ|êtmYÌÃñÊßõ
j K	50.‰„…7¾èÜŒÎÔD‡²Í¦@vvÍúf\JÖŒ±¸£×¬d/è|©,ˆâË._êÅ«¦‹lKŒœªŸú†ì_?~pù;ˆ@Yׯ]ËŸ‡%ß™ýSß
}ò³›ãÁ™{øç9‹ÖçÅŒ9˜ei|"rùÐ`uåfpý@¯žäX3¤9à"ý4àž¯²8—9üI–CèmËoòOsD·â—)ÿ<ÙIŸÉeQö:~³óŠ@=Ì߃k™]p#/$…‰Ÿît¤yKý’uý×2å·¸Ñè¼7C²BÆ>LyÇoóå,GÚ†k´Ž”×Àx"~öä P©L³§ÏŸ³¬Íìe•[Ñ0»ˆA=ŽZæ’­ld¦v«H"Ó8 eÒ‰7d~¬zaÐ]ó(pûYianãòñ‰#j$*bãc œž®å~{6ÉÃ;Å×ã¾f?œ­!Ê2.e EÂcpÚ|µ'yÐÁWç¤^ᣲ®ËbÄŸá¨|ÒòwÚ#Ø‘Ý-Ê
ƒg>áQÝÜÊ3ÒøIä/Ï¿)®ŒíTäòku!@žÉµ3À‘äq´¡³'L¡ˆ`I¸Ãe§f4<ÃR|¤ÍÕññJþ¼Žra"wè¶Üg#dö1ªÆ!YçA§©NbZP@F¥võ™&ˆ”÷î
:¾í|Ê¢p	´†”KÁÎó0ÿÇϵVÕûµZ#Di>´÷Ì‹¢…KÞ/éQv¿¢FWp¹Ap™‡/« /ÇfBc¸X÷P‰c¯à©ù®ŒÄŸwhcÙ÷¿ÙBS¯ñPa¾Fh•&Áöê0'aÌ`WÀÆÙ©8/øí;ˆroŠÎÏ¢Ó¨'\¡òC˜*©bZÔ¼í³ÅJ
ýP
[w3U‰œÅá+,>¶B[íH<“ÀQ„TYfÍú¾fÈHà|¸¡ô&9½)¬tbçÑUˆÌPÔ·‚úŠe¹áEfu\é©\8ÏÕ Ø[û£Møò¼ò‰V±X&µ‹Z+Ì}Te’\³É¥­2¹–WçÊG*[0¹¦èñ7û	Ç›`õAš:¢j#ñ‘ptëf®yL•h	»!üÞ¸6V®i.) OüqcpGμ{gX‡U˜
ÌE×ËÂ2F+Z›|I8AxˆXúe@¹«mýJ…ÒžežjDµ3)ë›Î ¼³Vç¬ç†mÀ'n»Øê"tåLF&+6CøxÌ,:fÏ”£Ïy¯w%`´Wб’áœÙß'|Û+‡oÕÑ0÷Pœ¼*¤låN–ú–l¾]‡OÜz?oöĘˆ8ÙÄÈuj¶šÊ:æ†gt[œ’E¢dq.#Ñ
BŒÊy‰àÃRðvå©9¼“`ùiE@Ið|Å̵-®Õúo)Öâ£AdÅØ±L°ó!Lºd͉7üôF6VçSìÆ(ƒ­Ey>p¥‰Šž1-MõµÊ{UgK¥M´(ih«rÚ¨†ÄyEðPàVe̤ ®ð:T|‚Ǥ;¬(óhs¸&ÓYýX8tæý^~*iažj_~¯¤
ÚÂ3ëI·(ž‘ò›=úŠÚ†¹ŒúQxŒ}Jã.(ÂÙqÌû =ޟ ­R>+O°YÍnŠ“ybš$…ÚUJÂz'sŠøõš+£·6h𨧇Hþð^ÇDHÉ'7Ð# µÊoNëØâçá¬,ÐÀ‘zƒ©µ‚Z!lRaÃ+ÍÜAm‘¾‹•67©=L‚m'4$ðAšs¶[oI)'$Ô¦C²\çU°![¢CÔ¬Ô	jMrÐRXßVòªr²e+Uφ°âµ£qe*?Þ¬%²ky³28+i­½Þ”Öñ!eÒâ6Ì™¯#4¨:/eŒ|H~’ùdžcÆE‹_š±eÀ’~…g*À´)Íèxª¦ÖÌ+û¦&ÜÇø›œr]ÖÈNŠs¹êy£r®Ý8¸(å$ÚôNcu±·Ê/f
* dÌ野“¬+†STŸH3I eÁ‹3«ÂY=aÙ/^È+Æß~€#P郲BM·,õ#Ô‘‹'‹7ˆ#×ÉtQ{ æÓt‘‘øÝÞq‚Ú:Ý
f$Ã5})¨&É„øa3B=¯Ëž›ZåHáÃ$øAŒ22“Ú¤Œ@N§b´^RÙíPˆâi\¥6– @ˆyï±^gU»B€†2a³qg’žlOò¸
N[‰Ýݪ#¤ˆÚQ@1˜1ö?Þ)ÿèëLô¹l)ÖÎ7Fõm£¥„©1¦ÊF…ÏJ –`pïÄ¡µRéîH,
K¼q·BÊB»-vºHæÁu·æ¤IQ³³IU˜URvPiB¸”kòtM{¶Uv
^ND
")5¦SZ_ûBÜñFFêÀZ	ÕýGu³;ëŬûú'Z~œ¹-@¨˜iÓåÙ>G?éÿsÃÝŽ²ª
ŒNx5j˜ØæÈ´¡yκ£`§a(éר«z)ãáâY-¸à
’Œž¬$™æ'dÀùôKôOÑFë|AÚþ+F‚W%q3…4“*ë%IÝÊ©µQóüUWÖvù¡À/I5|ˆ
±ŽpL=®JêïJ«ýß2®©¢
“yg\Ë!tØé%°üÑFsè~*æ&D¢?Ë_£öòeT
”5ÜRuy
bM
wïl(¥úkÔnfø÷¯„!¬?¶l?w«s°Í¶ºBïà¸ÖX?Ìkâ‹a¥FÖ^h\®n…:ÃâË{yÖFÉŸ‹§û¡	ítS¡ÞSl mN
¾f4ZÎbÇçŸJ}”öø¬SNq‹e)|gÂó›uØÙ-¬Ø|‡¡Z
="Äx@¯³MÒ6UHçl&ÛFâÈ~‹6^{.n›‡dÛÐ'EÈ)ޣߠæø¤Zs‰“ôñM-5Z(ký³
ŽŠ
\ºRZÎJ7úÖ•JçUÇU¬† Ýï”Øc ¨–™eZõPmÚ6ÁçÛȉ¶'Ì*RjHÖrÚ¬Rël[=*¢Dˆaî‚R¼ÏÚ?}%é¤ezŠ¢l—*m.o€“t	«oûCy'c¨ÞI™zm¨Y*Ü
ëú¼ÀÒ¼ö’?Â=CSé7;Wïôe)1!øäL”ÇÖ`_ú,^S@2Aº0îèåZF…¦öœRο¥Í•‰´„¡Ön[z¦6`†ô#lR#!3@%H«S_Âý{•°—Æê†	9ë~“_Ðk(µ”ÂY`;’÷´OÒ‘	T×¾PÚ+ÎLÊä%QYÇî;z³éóÎ•ÖøF¹¢°Çœ’$l“ÿYÚ혗/Ï>ºÙ[äææA…v^•pãX‘¸WÍMt
ú®£»›©Yj\ñ<$‚
\ήº:$6çsÔUŒn*¢AŒsB^@rÈGâb”¯ïw€lg›˜À‚ÿÛ4Ñ<‡F{°ÊâÝAnÓ´›ÑŠ”gêóªñYÉštVgÚEÍÊ1æV3Ý4öªPyê[8É	åxVÔEÊK¬L>O¦è=íF ÊM¾ìæ¡q˵ù2ÒÓ«=/["P,{³žAçê4¬7µa£»dô©ùk6t³-ëº:ˆMdµêµ—z²EÖ™×€DUšáà%¿´rŸ5Bhjzy!Jwnð£øCÞhíwz0ÙÏÔeæ5l$9«»ä.׆5äÌu#ï·{`MÜvÙm¤¾¦zª/½UÕ	IÎ9í«sd?b±u:~¢¯ÔÝ(K‚ŸëÕGœ
V}¯´Iœ¯"ªÒô7–sß{Q-àñ¶ÑiÃy´¤¨ëÀ4m=d7la^™(jÍËüs1Y(r9É"±q{˜Ì§MÔåcyÑDç¢0kœÅœÅnÒiñ€°%„{M‹“#5d•íDÿxqÉBùp§^óÞ¬¾̦D!
ÞúS¼v:ói¦å®vÇŸŸ˜*E¼Y¤=ƒáåMÕÊæ°Ž_F“†“´~;È-äªjL–lÃŽ+:T$üI*az¡®ût¦‰àÞå€4#Ÿ¿¦þJ"¬üŸå%¢·I6 úMêÒpºD/3¥’ÛÂ(uØ5œ.Ÿ´Rñ\Å·×È»|+8È}9“an1禿Ûò|;·´ÓcÔPëb´¡<ôbJl®¤\çú_À=:­w¸GOE
ƒõ«?P Kv“–—r'¿±F­K‰ÁU‰ÒYÕê¼#ý¶¾Ë„H™d¸1nóõ OÛªwìp;ÁdúJ$’(X7°AÀ3ÏZ7]”:+›TL¡¶4yÍ%a.>
stream
xœÍ\[sÇÎ³ÂØÇ”w4Ó—™RyÇÆJaÛJR)Ç‚
—„äÏç\»OÏÌJ¢R)JÒnO_Ïùú܇7›®í7þ“¿O^ÿ0n.Þu›‹£7G==ÜÈŸ'/7÷O¡ƒï¡¥º©ßœ>=â‘ýft›Ñ‡¶s›Ó—G?mû&n;øi·uôw—º¾íú¸ýºñÛ“fç¶›]ßNS
Óö+ü~ÚìÂö¯0àQýàçÓ?À²½³Ë†Ø·C‚•OÏd5?ð—;§M3Äè°ïN:ï|׎ý4阜»ëºw
Ÿ»	„¶ÚµÉnŒ°óÒGšÇ4l쯇Ãú°ýöܺiûí+Óù6ašÂö¼c§1„íÛfçX§·ûÆ·Ó;·}Û¼«&x߸v£Ã™ü4@ó`'}¦Ïáñص_˜áoaQ¦·ÏËižBãè|¬fz¤vŒãöŽNú‚ÆDç½ì>ãb8óGxdpÎáhÚ}p¥ç»ÜÐ:àÿæôáÑéo~Úþ¾	ÌòGø‹>}|—få=6}‰˜8ɽ~lvÃö.nÙ––^4Hºˆ”€¸}—€zÐ
ÉFhI°wOˆG.ÁÈàiý;,TJc¿¸ýÛV8Áp¿;Á¹&žà
טèë3\ç¹€vúrÇ0]Ã\š;eêúpO}=!÷2
h"\‰Ž„û=kÀ¾­ÿqW¬A ÃÍ\2Q€U2éàˆ•8=ìf/DÀØ.îX}–Áµ	Ë·SžÃ¦"´£D'ÅÕ Gò4un£9
0oPÿGl@r¼*ô,«âÆŸ§ 9ø´Ýévñà;9ù®÷mŒSb@o_è.&1ùêGZB–ˆÃ|Dþ#V¨«§ùHÝ•€øØÑÃB/è4áAâà݆$U?µNqŽr	#С̔uÂHL£¯‚˜]&‚ì…¬¤È&¼ßb· ³\èuåàH›Ç8>ÑzSã©p½sá4ù—°·edã·´¸sÀ3½r
ÜVzC@4…ÈW×"šžÉ& 
¹§÷³àñ½£S+ÒqGãìRÏIW€ôªAÆ'}æ$—½zÜî!ÊDÝ#Or&›ïýöIF;ŽzÉÛöž¤¨Îù\¶¿'>ëE{.+åiËr8ó€ºϸ„‘(; –Ù|‚
·ý-ƒÁç| Ue3ðÅŽ¯ÝøþÜð9hÝLgƒ@¾»ãQhïeÚ=6u4Åi“<#î&ˆN(ÊÝ
DGÞÌ¢"/@< ï0xÍzÂmaþ|À¥"É9-÷öVðJÕeüဖ…%O÷>ã䘶¶BÕ¤-¥asq¸è”HÎÌ<˳œ35`·êŠEdAí5x4S	4ùܵœEíÅJ˜DÞw„­?â7Ô×(
6‰ägÆ‹IèAƒþD=tØ·hušÐhÄÀW˜epMk]êeÒ8è
ÈsqÊ8¿Frº>8ø…à\F†ÓÎ
|gž)öh`¬mq²rª.®#Ãm¦jŽTeæ©,“?6Þ…ýX.™iUk-–Á©_â–ðÈCA³•–°_"­è®UJèhN4
g¸Ã$GrÓiÿvÅÄ!dûÐxÚÏ{g`éÒ¤WÞÅŽÊ·	KV×ëBÜWBrpì]ô
“‘Î@–E¹ZŸ"­³CàWZÔrÙª.2äÝh"Xëý@ɰͮÿÇ‚Sj {tcÒúX‹y¥ø¥
€½
t¡sл˜¯€
~xaP§º^„;£ÇÈ
šEq@ ‚›ï‚b肹è=›µ/‡xËen,‰Æ`œ™²}$V¾_“xk«a;ÙÈŽ­1õQ:Ƕ࿛¸~;”;`Î…âPLRV—¤]~‚üùÎñ¨IhÙ†q{¯@ìüþL?;çÙG iw©2屚ôç´«â,¤íÁ±¨½µbuø°‹z¥µžd©1g†¾Î cÌàê:ejíKe½àq¼Yì½Q¸ƒLºù¨æ0)’°zÄŠ£Ÿ
…Á@K<‹ë‰ÜÒX4ÉC½.ˆ÷ý„çÇ|Ýñ4_}ôfã};Pè¦K›0Åê&‚]݆„‘û'GÇ'ßnÞ]½??:þ˦?:þÝô%ü9ùýæWG_l¾?%©ý_’€Ë
xŒ…Jtëz¨/Ë)î5äZ9%N
þͨïöÀíVÌI5YP>Dº„µPÀÀ˨zbL;{ñ#ë)üŠH
€¹P[ jéÞ¯*dŽîü­õæ!Q4Ì/µ}Õñû¥—“œËö/mæŽëBÁWBAø3Gƒ@g- |©ß”Bì!Ö¾ŽrÌPìfy­€añ
 ßô¿Æà‘Öü'JV?t—‘˜E—O¦s¦ÛÉr(¤}ŽËÝ"øT-³¦Cuƒñ€¦‰Å-åð[xsãŒUÓÌs¤¢Öù.¦Á"–S+Æ'kïltE5xUü‰ŽýˆÓ1¬|Õ@„áò99€¼x}”WvþgeðA숸ƒè»:p¾±Ÿ”ý‚W±àÝÒ±a(òX˜K.ßçKc¼ÎXD"Çžd{"²-£ËEª°q„àäbq&R•JŽ=Sœ‡ÍLYŒÝ)Z9XL©ðËÓäÖ#V¯ë×ܤ¡–…9ŠEwKbP‡Á–e…9ÎMÛçÍ-ÐøZ€^à3$Ëkåß]H)si]º‹L·á‚F¤)UAÃA¢ŸœGË!€³ŒÉ†ÏeA ­4
¸LÙ‚ÈbkHñà–;¤ûü[»Ðî·àã
f,8=ؑϲê;æ`œ‰gnHô«¡ç<
.Rd“Ûga殃I½/oqÃ2F!ÄÆ.ìïu­q0¢ØÚÓ²‡L±Å€+Êû×:·Ïþ\ˆ|—e¶Ex@ˆÀ6C¦äÞ4„ÞÊBø>¨Ý8»ŠX3Y›m,ÚDÌJrly<¹ÿuØ´rñ4f-æ¢üPÀŒ¶E€(=ê €†uh[Š¥²ÁY6BNY‡É8ÄšiIY¨±ä@%£õ”™Žg°¶³²îÙŠõuΛÆÇ„¥Í7‰‰©daø¯˜¹ÏQdªŠiš#ëØš5¤˜®QI€wG¬òŒó[]"Ä¥æ»ÞñXB0¼|›’QLJ—}AÆ÷6ÌT¸‹'º}¡v6×5´SŽïeì÷«q®9ªèpµ—•—„Ϋƒ@d„H²§ª¶h'Ň“5K™­M%‰sŸà("¸0SçFPvô0!ä”7N­CÒ4®#a™h³XØ´ZôXŒ»Œ™Aüf„Û>óùpè¦ï=lü4`Ðöó^ý€Ó{°¿W±Øsƒ­kq6“AÁ”Eö%æQƒãY^UãjÃ:›+R¤Ìv@(‹”«Ü›’_Qg¬“”(#™-¢š€ãǬZ,{ü˜]gó-¯5MÙ~o±à¹fᬿà
¬†U@/yüœ‹¹¬¢$gO(1Œi’™šZY~Ü«FNWbÔÝ"ôˆmD¦«û&Ú
Âæz
t쩼a®@/5šþB’+SŒ²¢‚ˆ4Þt:æ3ZkÇRï.õ€~w
!Øv	s)¬œr7æb2Å•À°™íy"Æ”	HeÒÛ­¢oJ¶“S½¬nİž|Ál¯Ü^Ÿ7ˆ>z0S´Thžá-ìÖPH´NEL¯=Ø5O9ú˜ Á,/¸°Xvåþ^Ñ6>MWúp äA#a$|7µÙ$úEZsÂ(ü Ý}F­9QÔÝ®MËÔœ@ý`œ;ŒïHà^Nû£†í†…LÑX9Í,½:~³6eP†Út鸹%7Oþäxæ–ƒ³`ª	°®‹Rlr€w‘Eüº*3»^•NžÙ¦ñóÆ0Fb;œÎϸŽüî­ò¼—æßVö É%öךl^Ú»HŒ?ÃýâÐøYЉövtÁq4¯k]OjW~t¸ð?,ö¬"*®R÷g®ÌE“úY‰jòf1­^P8cv9	ã¨Mej-êT€ë‡’©2PYké†g‰\TE¶Ìr¹«X|E ð—ú\¼iã¥U`†ï–ÆãÜx\¯šRéãw¹±-OrãùÚD—×y¶¶£«Z¥¶\ºYm„´açg›_E¬EÎÊǶt}—»îWgmiÕ‰Jµí_ùã*z»d*Ë«Gµ²Š
ö"©S$Ì‚¢_Ø®H¦¹A¤FÎÐå2äáÀB¿ÄåËòw|ê3–sû<@JŠå#t_›ñm^ðùÚvËÈ‹3ëåÊuNÁ›ˆÓ
×ï
Ä+ƒÐ·)dO½©Þ×ÕºÑù»_—RÐõ7+<%@(ß««XÅè*8ÎfA8éu2ïÁɃÛ8#|Þ•w|Wßœ›sÆdœk¬jŸ	(̧ª—Œ2íX‘mtäpV*-„ùzJpWÆåŸA‘WC/‚9TýøxzÅ/ƒ76ø»ì®àeZ5fójÅsZ{a韛,ŸõuÉÙ[§ÄLÚÑs)³ÝŠÒƒȇ^üóÕæÀ6ˆPŸ2ßýcgCÜendstream
endobj
715 0 obj
4644
endobj
719 0 obj
<>
stream
xœÝZûo$·
þÝȱ@b&ÈŽGymkHŠk^]4AÓì}Ù½]¯ã]ßÿû’”DQ;²×ç6iP^ÏèAIäGò£Ö?MêJMjüñg›“Ó7Ýdµ;©'«“ŸNuNüŸÙfòÇs 4´TC=¨ÉùòÄÍT“NO:c«ZOÎ7'ÿ(TÙ~uÙüóüO0˨dÖ0TMÏç0øórj‹¯KU
Co‡âU©‹ïÊ©.αýËr:Þ”S£ëªV–ä×ð[A¯¶
ÚäÀïYV¡‹oAê¥ù%50Æ_•¦ªkclñ
ö¼Æc¬®†~ i¸¡?ó0ì4(¿-þZN[hÕºø¡ÔðÐhEÎËÞÒ¬ïKíŽßyü©êûJµ“©©«táÔp‚‹-ìñc^N5ÀNÚbÇ4p°¤Ržn``=@CçÆÌðãÖÏLqÃrßãÇϾ†£²`…}”qÇýÛØ¿åF‰–€‘§ÜxGî¸q£ÌÓ\㜟6±;J¿Ëíc›l>J÷O—±ûšo^&½#ènÀmÚ¶yLAhm£ÛªµÜûØÆ¬{xÑÅ4Ù™tPIý°ÖWµ¨èªïkå„~UŠ´¿-i+
ØÛ$Õ„jö·øàMtªhàIŠûgsûú—Ì–mjvœ}˜lL‹ ²¸Jêvö=Ës
­zH#Çó·LJÄ0d<½õ¡ŽÜp£Š“r¹Ø×õÃö[&e[éw¨fŸ¼À9Òd£jgЄ¹có&ˆéØ¡¨0ƈYæ¢Æ}bШ<ÿ<,9S`DÎÙÕè4›’or›Ü¸1Yô‹-2ÁI.–Äû1OÈýÃË1*°•nÇ©K%9ÞE+íª‚P˜ù’i\œY†ç…¡ V6-ž?‰)z%ªWÿ„Š&IWs·JûPÚ„¢£Å	1Æt††©&VëèJ‡ÔE¹ª–õÐeÇr”ê-VtÃÐY›î@êF”ô¹M,¸ëôd,-7,ÞÔx›×bâ
ƒô¹[$d÷Qfª™íóKaY…ðb¾2ôkÍ2„2V5,ÀWǤ4øäô¨¶¡9$s¨>ºztÕËÖÛ+ì·&¬–y#Å\C”Z^-Ãk¦æN¬·7\ÙŽô‘AC®BñnLGY-qIÚŽŽà‹V2@Ó“?%_ÔŸï
\alÅÝʸÞã˜éŸ©¦ºë*£)t’R†ôÊçìHaOM¯|f†Ôô95._¯…ë†{×k&¶«À#›<Ûˆ1Z0Îlf<-3Q7Ž”-Ž¼Í¥ž|
Ý1­‹v–¤…@ÈuW©§n³YŒ#óŧüÔá‡J^Ý`Ím¯Xs[~Ф~“Kÿé…´mÐGÍǕƌ›Œ#	Y){ɽËé=¹g³˜—Ü|ç,”\‡#¿RÝ#¬î”ïš,ß^/sgô»„¨'#‡³{|ebº6\G1‡EUO^õÀ&¾®FÁð›^2å¾±Jõšß"ûœ—)›ŒuÄ[™~ ç='™1ÏôS.ÙÕļ‚ר[yÞ#)Ìö-]å$·ïbÉ'K†m®ñxýWû“Xý³¸ú£»«qœ	v‚ƒ¥ÿc6ùš5ßô,✳CWÓ•îý=ïGQã—ɱ8p¼>H›\HDjèÏóâýÈ?:=¸é{ú]î,»Ä‚£2âçÍÄÏPä—ç'ŸP)Fendstream
endobj
720 0 obj
2592
endobj
724 0 obj
<>
stream
xœ½\[sÜÆ±Î3ã±¥‡dqÊa.œ—D±(e;±ÍS9§’ÔMJ¢#êbIôåߟ¾ÎôX’rJ.Å]`0èééË×—áw»¡w»ÿÉïóç'÷¿švOßœ»§'ß8º¹“_çÏwNa@pp¥Ÿ‡ÙíNŸœð“n7ùÝb?øÝéó“ì]7îøé;¿ôû×nÜ?èâþpùëîöŸt‡üþÓ.ìv¿ÿ¬;¸~žsœñ–ßqðç0à“rï_§Bœ·„ÄÑõ)-§òþÀ?8ø waè'7Ï<è´;Äý%’qCßÂ+~¯zWS¤KWðúàÝ©~Kø¾¾†4Ò·×Ýa”Gq‚…™¾^àpü®8¸ö-̆/Âß/áþ};=«™e.œô9pœy^ÇirØ?ë86;Ÿ‘^eÙGÝaMòGo¸ÆådâüyÇËzQ/]	OáiÂ[ÓL䙸6÷eøêé³™†ÜûÂyZ/Í' ÅÍ@ËÁÙÅYÈÏüáVŽøÑãÊñ½1á‚#<2:/ÜvnZÜž€a4™Áú¦Ëò–ö±4Á—°ÿ_pä9ZãnžŒdKÖp¡*@a²Öh7aq!"K§ý½nTVãU°\BÉ!ÞÜÃ9&âýK–ˆG`]¢)Ip`·ñÌeIï±*ª„VxŒzÈ¿RÊ`ÑËèü\'¦—]àcHÀdG_ê²|1‡+™÷ßÀG™æ1_EµÂÑOp5‘T'$&2?€¤á-#²žDÎ¥Þ«ÄÑ[ÌëUEW~Ã4Ïf_òúìž÷L'¬fž&—p/PXK¿(‰ŽêEm­ÂdàêÂu:’¸mib6d´6’EË$ÁçÌ«ý–MTðŽJ"ôDå…6Õo!Ó]¤¶‚´Ïh†ÊÞQuž^ BcGÚžfÓ¢2!‘Ù@ø‰Í÷|eÀºM¾—¶€×„Fmnoi¾XÓÊ’½±5\$Ͱˆ"_Þ‘¶˜gÙ‚¥>G•'œ
øó
ïÖÔj£eëÊö€gBô°hoñ޵)/™¼cbA¯­bƒR°bë#C¥ÃPïõ9â×Ĉ6ø­Uë£JÄ“	ˆA/©TÕ®>…Ó)vª›«Ö])ð=’‡OŸ©›JÕÄ=¶RAB^hÞ9xÕ8zÄŸ~@ÜÝég'§ÿ…xåˆ~ÈŒÑÁÓCŸÃä§qï͹<Á:ã`:Ø£/ÐxØvBaeð[¼œ"â¼Çì~ž"ã‹4ó4¥%Fƒu‚k0i=¤9Áåd'½ÔÛ¸	àÞÀfÀô(BË^î>‡×8‹“P‘#	aÈ k!f˸+ZÛèC0Á~}L]<€òœ/˜¾è6îvHÂ
 ]X({È,tK»ØüÙiiJ‹ÚMNŒnìÁÂÍÆÒ˜*59‘~K@³¼*Zg€ÏË£RœfÕÕ03=K`æ§ý„åÿ»Ó‹/Ôþ(ËÏ‚¯H'ð•ì%g5vOÖ¬3ï4ïûßÇxÀíËjÌ\.LÅ8ñŠž³v›yìnW[Ê{Þ˜½zÁ%¶¦â+g2n1¨q+¦è©…ö¸Ådjã{²Fœ¼cå(ÀHìß™D_-Ýb™¾!܄ۯòˆ‰T¨cӃŮ7òÝ,u«åç,T)+ä¢R`œB“"žz‡€DöS™‰¬Ì·øßÛÊÿ+¸âï¼Ö4!s2süÇBÓ\•»`ãàÿßèºÍi†7õ}O¬¢
:;	Ä}t;Ÿ2…>òº\ÄxŒ¤‘÷ÊEóžËrqŒ®.~T.Þ·ŸÖùzñ^CGf¥ýÍoËų­‹×
†“‹dòùãïº-~h6ØÄÖ=¨ßò“k~ßÎ[ÂWO:‡È¡Aã¿ÅÇB›b­&—›³ÄAcó⟉Óý”ª‘ØHf&5FK+ægßdÔ½”6m€Db
‚¸3ˆ)‚èG-Þû'iËP,w»çßcƒÌ€(M`3V*þô<3I(ñ5ÑðJוÛ—/qV×¼H©þhŠœ|ˆÚ™¸*ˆ˜&äÉ2áÎf,ó?Çd5˜·±rXåÐûHdÀóAÅ9Íâ–9æVƒ–¹ÿ÷;¹ÿgüïÁßþ¿~¼ûÕÉ'w_­÷µÊ®õ>ŸámÙÁ{à×ü>/[ŽDÿOY‚úôûŸ;¬ ˆF«š|‡ë¼61h[Å‘ˆE>áæóÆ&¥&¯¥Â+&`¹Å¸ân«Ô‚Õ«…Ct,êÛ ^ñ”÷„ôõkà¢ÖY¥ùHp16ÚB ǃ8Öä^S±ù\ïQX‘·îê¤?1¾L‹@h*–¿D T¸”ZÈ´‰¿óíR}ÅßHÒÖ•µRÁ‰³!ÒßP+q[a$ZS2RþHšÄDB¼ªVv6*¡®Fþ¬›Sþ”4Ñxf„*URðkü®Hr#\QoŒ°õ’	Ðã×À<ú"iFðI¯LnLü²TÀ5®eIq•ÏC.Ø:•ÉU¬iiâÙ¨uð`4Þ"+ç‹DX`¼Þ”õiW$lµ•¤i}ˆ6_"=M‰d™2I%Yކeu7–$d˜xµ>tmmšMcIšü dÜÜ‹”ü½kó~œ‹'\$±JjÒdÌžâ¹”Wt1?W¶¤£-ò$ºŠAü¨yÿ-Lg“eˆ_>-+~XGðµP•ÛÊ¡OƒN¥TÞ-†ÔÉÞÅtz
5,•MÅ"1Ëî
ó;"	H7†MAIÓ×Í ÏN¬W?3*õ‘£Òb†7…®ÍÊT™;R@€EÏÛ#Ð÷PŒùR|¨D–/šàs3>MˆõFn˜°³&&k£Ÿ^•´Nñº>Âqç/sN·Äœ¶¢RF^ØeÂGIÀ¾K *e“›iCVƒÞlÀ°ŠX&¤¸X›n>‡E€ŸC­ mt&è}›c’bô"ÌË\¢T`Ï=nwìç&2_™¨hÛâàƒóLS[;&Ú>k¦Ô£²ÿ¢ óÏ:.vÅýÿâÃìþmÓ©µ“{íÒ÷S¬/½mÅUúe¥ÝLõ¬£7zõe‹ö8‚³JmÝØê6I„Ô>ï–Põcæ;ÖµIS§1û»½£mtÿa)€}Ÿ¬c;‰f*v·Ôol
RÁIVòS6Ø/¶6Á½©±¼ÜMUOÔIÜy…ˆ4¬Û»ÂBL=%å]ø6Ìó‚l¡çhÝ­gݤ@Òè&1SÒî3D…,;¦7ì¶Rª5û#7Û
ÒJʵx8$nB\
²–*—•÷yÇv™Ú"8º[t•=•®U^J[”Žæ4$^$#=paWñDw—Já²bœ’çØ2(Aàøí·E¥›±ÁÍ`É«Ÿá°¦¹ÿ²¹l´£Ì&”M$êåFòhj¶{
v3ãþý¥VB&Žá{z€o”[9Ò‡)ôùýÓáZŠ-­k=6¶&ï§á(Eü¨V+'9sþäõ©ìF˜Óö@½e‡ÂW/Jy8.¡¥–Ðè;®n]†5¥×¶Uv¡—õ…‹ãM¥PoCÓsԕƃb©¦
+ì7zW$´¨óûd–1„{Å'	muÐÖõ¶&m„kC	ª´‹è1\)@
¸‡±¤nno™kz¨[‚ "6BÞ!Rã.¯©íñô›áñYýxkàÆð4ô®ø]—‹wä¸ÉcPg›§GZ:7;ÐRš6
}Ô¶ù
¤ÔÃlpÍBîJ: é“—øž¼á¥O2Íë¼N8è{A’šÉšL8_ãÓŠÍ]ußÝOnët±a6VlÂ[^ÑÏñ#ÄÛSõ˜0~~%z1ؘ"›æ…E1ý§Ç©Å¦žøPæ[j3F}5Uøš6`³å¥ÆÐ‚˜U	0¤ܧ>X˜fãÃŒh°ý¶ÛAï†÷Ϭ8Ò‘ˬ­ZGÛA°Ñ¸r|!ù—‘ÑñÏW»Þo4@`t@9±¸ÿûµ|µJbÅCc¤¢ËøžÖ‘[G†¦fæ#^›mTÆÉE‰²ÕÉen#2ðÌœ.‘ë5åmº6¯Ù-êш&42ô¬­™Èµ¶g.ú;)Fówm¸’oîÝZ
.J;säë>\ÿuõB2v±»ÚØòNv2Ø	
‘€Æø>1¬Ã^;xMïò{Q&l±N¿ÀB"xâv!ÇbÒJ~)д­Fsî¹ÛÅžT×Ê•±µq4™õƒÜ?„É!Y­îm¦¾j(éLØq㔎Ä‘Cj£ÂÐTŽ0V¥‘ìûp4¡aÚ8{Bð²iÜð5Ò©¦N*7༩ZI“£ú$饴)!!~AÕH¨e®aÞ¶¬Ö\©˜¬©ÒUßvÝ'q¶_7šLǬà|žu ƒÈ&9ÿQÎrןͱ™–Õ£õª­ì~mñ•èl(
jMáÛ ÷w3éÝ>’൱”×@ê»('N¶ÏPC`¸õìôÞ­O|PHMŒV®®£«¸Z ìÈŸ¥¸Lùu%ù\$'§•¯ÐE‚yxÔ¦y×1P"ýFÌ9$ŒC§Ñx•":¦\=ѵD["¢Í—wyÇt€lEüÙ•‘Ëp•@“ý^cYvk›Ú9)½ne[Aïå0à‘‡Ò—àçx÷D™Ú„æìÁq±†¶µ†z»–§sSÓ¹0àé£6Å‹ô<3kιxgù]'E
¿ÂD±¬tØ¢¯¶ÎHZ)‰¤r‡8¹M»0=³W84ïÄ&Di§k¤¤[]Õôš/R]|SwŽžÕ–0<â8gí!«J‡Ï\Ô#ºòÉFP4³,§´C<Ç\(KªŒ?–$L#xºÇääõXzÛ€‰ßff™
œmŸP9õ«ç‘JËŽµ(_­l˜í‰œ¶(Í\Ë“à
f†I}n¸)©ùÃjG¤Ž"¨ÕèÑ¥Ÿ¾)Ù z²ø¦–qìüçî¤;·Œë¹Ôÿ$W¤'n7Þ¼ééÐÈ¢½Ã¶Ë.ŽÖ4'¨Âú´qÛ%$ÂÜš2âµÐ »áøÁ´h£ìd^Ú¤Ò½#*[ÒUyaûB
›Æg™^ºÛÉ€»7Ä*R|‚=Ë!ô±H
“s§uõRá«@ܵy*µ¤ŒYš'lD:«aÒÎØqåÝî58WÖÊPƒ¤62¨¡°\Ö.&MÎêù’*ÅÛOˆbç‹’oJ¾ë‘¹»Â0黆vsd
ƒŸÏÅàŽ÷ÿ€»ÅkáÓÿ‚èIû®œ`ÆsƉO0Ï}¦®ž`vý8E0{'ôýèØÆ@‡”ÑÍî0š"j›ïAåÙ¤¡Þ¥ ÇÕ "ŽXÖű93d®+úä2ʉï§S(óTLÆI#*Íþ*GB4pÎ[íaÐ5lþ“oT=kn{ªA´è]þ"F¬Ç™$Zh¤#²IÞî,$¨ã†1‘nÇ&P¹ñôGÜ¡å(N£oÏR®à󢑊υ–>¸88W(Ùüó	«ÜHÑËû5MÕvTÚÂ妟c+àܬžDvã
µ'öŒÝA͇^Û·’–>×à72‡·4«*&i(iÙ–úH‚rM¦ù\´üÒv¯GŽƒKãê>
stream
xœÕ\ÛrÇ‘}g0ü
ð“fšawUõ¥ôfYV¬7d{-Á±òJŽ0 WÄE¼X¢¿Þ•×Êì®@Ú»Áàè®®kÖÉ“§²çÇ“îØŸtðž_=zòõtrùæQwrùèÇG=Þ<áçW'ŸŸ–}(W޹ËýÉéóGôd2…“)¦cNN¯}·ë÷Ã.–ÿi?üõô?ËS±wOå|ÆòàéE)ü›ý!íþcßsžSÞýzvÿµ?„Ý)\ÿíþ 7¾ÞbèŽ]Ÿ°þ®ü?–»!õåš-ø­Ö%U„ÝJ­_ìù/ ¦¡”I»/÷ñØu1¦ÝïàÎWðQÊÄŽyÎøtè÷ZnF¨Ü}³?Œåj»¿ìCùe=>pºŸ>õí>ÐðÇh‡è§ñ8¦“CìŽS™š†«Rñî=|<‡—å£ÔÙ÷»Wðç3ø8º»»·ðñ¦|@#},S
óÿÕ£Ó_}·û%Ü»€3)JµÝW<ýäΧñn£»µ§Tø¾V·Ìƒ—rÊk¿¯¥_Tøv³>v—¾R¹RK³˜G3žÛzñ‰©q†Õì'ÓÊU-xkV
N©7ƒ¾¨ÏöS1¢¡[LàºÁ+­ç}«»/ïlðX>×ë#oëm;ÁRÏ¥^û‡$›õýÊM°ÕC˜Ž½í—-õ¢lƒÒŸ„S¶U×ÍeµÒîõþ0àõ³²Sßî¡SÊÀžéKh:¤Òašç>A—°>õ\e)‡Ý;¸5ÜÖ§ùZ)S6rÜcøûUiá^Ãç¨Cví +—t‡Zy»çáCçÎJ. \{Sqå‡r»Ë@ßïä9h4F¼Qê+=ì‡K‰ögXéŽÑô5í>+?ŸìaÎc—Žã,°ø¤Tüýz4–öv
=ŽW;þBQèÍbÎÓî©^„óÆ0Ö2{Ae¸+P_an§‰¾"쓇ç
ÄƒÍ“0³f‘ÎLt©¬§”ƒ2o÷²&/´=˜„ÏÂmÈ3MƯæÜáœýs6=—N:;ãåO}À弭ݽÑNÂÄÂÊ€M=®¬kÁ΀3?dºu:#Ÿ2úê”Ô[w‚ÉjäŒ
Mö@.»,GoÀS‡óÅ3UWZšv«Ï/³ÓãšyndªŸ±Ç¨î÷©Ô`ãŽë籘”År¾Âÿå.í½yâ»=Ššª<ìm¯ZE½vÁsTœê­VðšÏyèƒ.÷k˜Ül¦šb óAÝ$ý¡(“>;;ÀrP5M¸Š…O“@êQBç%>%Àìa ë„r~9Ÿq·àRÙjjn ¸‚Ó¸ÆééÒ¶ÞVô*Ä…Z.×Þš"z.èÒ„“iåcˆYlštO#¬âN€´ÕE†í+ë@«.å˜ÖO¡ÅˆSídeW×<õ9#Á䫺w
ØVÚ)…*™Ã;„ÇG4º¦¥VÑp½YéˆÁ`ÐOá•ëj8ÃÛø!v<’5‰«ºÀuª¦à¶[¤27Œ,kñ:¥Ç@‚b¨màóÆ´¼ÈæîcÛˆ>Õænmò`SÅ5ÿAùù7(˜Ó'±ž;An«‹+{:wP³4ª´­ê8:hf¸ËqX³,óùIiµ`8OöÎXyÎÀîËÐ.ŒÖ{:´rl§
ößKî7,x7"ÍøóžB´Õoñz)'Zt/\tøåœ­Q-ºF£ºˆÜM¥ëØ>ŠÓ‡­¡[3öþ‰¦½ðRO¯þì‡Æ‚uI¹â_–Å
é(3X©Æfjâá’ÍǹmH<¨AÓ•J§»ÑáÉzÕë]ÙòÆeA_sV³Å)œ‘évBíq€arˆÛtu7žÝV¦fM1°iÁxd’õLCWûžm˜u)é6ÇÒ#Ä-ùVMì“×}THàM,/(BK䢔qœYÆB?®S’­j.ûfoJ7µÒçÈ܈áSß ;ˆ‘¨º?+¹-5t¸b¾4H_˜žþÜÒ Ñ)–5b‹¦:ØJ)ê΂™;Äß‚ÚX(.Mì©çæºÀ2€vk¦Km‡ÉÓÐc…ÕêŒmÉv«Hº	›ô0ùFµ·j;7ˆ)B]QÏöÅ«ŠËÁðè	X˜)º/>c‡ål@‡ö&4†â7-ç­^î(#¾2H5›4=Œ-šÎUÀNþBÛúžLà>Êlàý£´-î„ñh×8%$¦}©KÃ,‡¨Y8ƬÔøÜ–®Â†áÕ°aa¯ ëÑXÀ6- ÐP9˜µiÚ2Ã0u8òeXª7ÞÙ¨Rêôáæ%–¾›2q£Éðð(“
•ÞÒ|çäÌKÍ	?Ì6€NǦTHbC¡e/7Íè+}8ݳgdʰøÊâ¼ÝYú0º˜WŠÙáZ ‚>n¨(*¥žL
™v÷¤œ“£-ÁQHbUì>aæt†°‘ºxŒÊaȪµt¼›§¥Á›]L|2…feÖ/êRWóy¹ÐbTú: L(W‡AðUõ_1{àºô!6‡PQ:|”€‚¦à@ì¦á×4¼¡ëÕ¸p´·‚øÐëÕ§µ2–2ÉvwBU™ ž'!†njÈT)÷[À±¶Ú:Am“Á•h«µ&–k\aè+…†{b5´¸Sþê îØîy%RHÛÊöÕ¿nñ*˜Ù‡¤c-·[c0Õ•½5¤YVÓÎ7mj °€"ÃT]8q,êùZrÕp¦“}˜·.LDH$¹Ôu+
,qd­ž„Ÿy˜ÙH,ÏMfÍ=œ™Ê5=eØ8¤Ü÷¯E÷̲MêáC…½h2ΤÊäÑrq™ë“؃öçCc/ó&mRÚaBB!¢‡CÊ]KGæòP©£hš¯%Ü@UOãï¢c,Ø}¿×îôÈ ¼ÏC›qK|—§íÀ/£¡.±8BÏ„
àSp}Œ"c¬Î8¨?·{ÇæõœÀt£}º3æ†\~°G®#Óª)|Ú,¼ÆØ)N¡0Š`½À3#Á¬=ØU_DgýXEJØÓñŽÌb+‡Q`a¹ÄIÙ'F
*kI
Ya§Qü!Çy±@¶Æúõ¡NîW˜×ò\¥œÅÊ´	REfs-bšG&ò‘{£Ýšx¹þ¦öYÔ£%+Ak"š!´†u—jA"×ybOõ€œrIGR1R #û›9Øp>,IÖ›¦ŽŽÿ¤üÿÀŠ}B§´*HkŸ“JFq§øÑÇ?t‡µ,˜RŠ‚?†Xú…EÍI‚8ã’ 7$Í^ÆJù(¢»r§¥„³WªÆnët¶T׆'”a«.ô)îÎnîýþú²ìHŒ²ªcÄzé¹áÙ3ìQ_UÒ·óVç5.e#)éaX@\³R«Y)ݱÐBž¯ÜZ&Ìu8ÃeCtÿ×°M½€ÆïÁªµÛž#wk)¡îܰ5#ÓrVcˬõ”ËÀWÛÎP’9×7̵€â´
+†û™sìÄçC‚à™ÂصôIÀ5ÓVokO\TÊçÔ/ÖÌËfŠO-W^}3_ì
##ð0½Á½Bn€Æñ%¬‰ͤ>kì¬ÀYa¸-•°~¸† ÔÐU¯ÓȈ®‹%…®cw‘öÇêôùÀ‹ŸEÇDò؃äØÔ¯k©VcMU#»õi¤aümÖXãŠ&7¢%£(ZõqHµ­lÂheöZ¦^aÂ3óy÷¹^\
W8
žÄëÁáó=§p½“50û´’‡…ˆ´Kjøw+Ð!|Ÿã<Ìô²ì‡T$—dmCM‰Áí£Ÿº^ÌÌq²’µE§(þÞ
–ŽkŠ“ö¼»þvËsÂdõ¿©•¯bOÒ¹7ó)njý­’Ƶú`“;6¼å+¿P;Ô\Ãz|ýÂú'6HãcpâÕÙ6ãFçõŒ5é‚'ŽG5À€!@Xå
åx‡šÓÑê l³›ný[Ýxì5©ðÞ´„Žç1
ÞA¢ð„n2
‚°–!yÃCŽÜ׸¸j3ð—@Ú¹´Ï©éfgPà½îÅ3áa†5œèlVt0Æ›êG•³Ã’]ðõÎB~’ugÓ“ÇÈGøã`ûjDݧeÀ^ÜåC/²LŠRÔ”¾ØüRG¦Ó$~Ôg¢¬¸a…r¼¯eÄåâþ+k+÷mæ!ï¡ídfòàóƒåŒŠbžkÔÕE«£-˜¾qÖ÷øò³!—>®íQNÉ•d}-4ÀDÐ$¿<æ€d¡mqÞzÍÒãŸÑÚ®Û À½[p?—E
ùWLåÄË6$QÍTè´€÷…èt?ÑA
´ÚN}`–°Hu€Æ¡¶u”§7Q³é/k¢~¿8ôv‡_Í0Ê·kÊÄbà¦6–çΆ6“ÀÌ™ºËì&UåÂ)PÌ"õŒ"äz8ì6¥&‰öÉæ1þ]"Ýæfë³ç9	YôËòjÙ­éôŒÅBv>ò=Ž…sØÐ÷ióœërKÐÒÉ2Á‡Y…AjÑœ	À:åJ_PJò†J;ßs™%gOÔQûQ7¤z	Þ—™Ü Éìùê[Ò„¡ôÂZ¶Ä#óÌfu*‰òÛŒÈ?¸wömڀɓ’ë8øú&Œîí'¾@QSÊ¿ÚÏézÙó‘þB§5eá|3“_|!ña6Háìi;.
fËù”Ü«€Õ¦$<ºbtµÈ&F‡iuL.™«‚ÓIeñ+l1ÖM¦T³oµAí>®©)rCí“w'5ùú¾µûCŸpÔ öne(ÊZ2@SÜ0˜wï†êH[HÍMäô9ûGÁéØm.'ZÈ}Xþ,(]5Û`;•7püŸžÖFW¨8Io\¢Z–¬Œª)«]f‹gÕ¬õšaŠX0]zô‰ã¸”ëîË(3áŽZ4¦(=–FÕð½¼€$¶ôd·«¦•ÃC-³¸‹æ[ŒëƒãgÔ/sʇ¬€»†ºUéŵžÒÀŸª¡@`ØÏxŽñlÖÜx_Ò:¦°ôCÎ
”„zOvvbÑlÐŒÖYœ~B?û«ªGB”êùCB…Bd•§×g‚§%-vC‰ä{+¥1`·!2Ì®ŒFq_žDR(œåW'oJ.ÈQË”éЫìEÉF“–D¬à!vEã_¿D²„yGÞ(	þ""Ëä­ÀIª¯<=6ä d§:È;EødõM†¢=U£®Rø+Å
]Aóf“'™ÂÙá­ºjý*Êu­sTnÝÅ.לI8Û0£q†›±²Í#tM>~l†Öcÿò†U郱-¬|Ç(aÞ1Jø®°‡7Æüß]¿§9 5ÒÒ+áYÓ’YhœwÚ£e?ðr[ø=îe®ÙŠm©”Qÿò¹rðó†8×ø3Ñ[ÆêŽôœ_bh@‘!ŸÁ#G~
ký½¹`k…)7k›¿•¦>ÛøÂ’0æ¿úò‡b(i‚̬¼›ðñtX|ýÄБ¹¾ÛË—w¼ÑÛ/«å×o¢¸öÙ=t63VOÞ×Rõë5žéEùNt‰ô*ÑKtü	Rþ{èÆè:­ŠÔi}9’¿£äAýcÊ×(Ù꣩Ó\|-%ðx÷ýþ·Lö¿{ ÿ[¡káÿÉÀV	Êü;bRÙ~ý€éƒJ£ø=97Zæ¬ÕI³X×zñ’Ö¥~ÍMõ»kÐ2”‹ºhFéÿxŸ×ßC3Ç$oEœ‰žQ@=ø]ªß7¥\	„Ž…D~Áõ!k¼×ûTO
Ã8¡7,ó~Cê×oCa¼¡‚¼Ñ¤ÜK‡DlsåHOÒ`³kRZ¹ßΙ_=AÞðiÈ•ø„±ê›ïÖtÒrÔÏÊm̬B>†ýMÈŒ?‡_«x­Ù'ž·ßGu­¦AB+˨/5?êIˆÕó%k<`”¹ÔÔóêŒS–_Ö£aXBy~üÇÓ›ìázبåÖøÒóÜ|-z¥VóWå%§@	ƾlÖmãi¾[oæ+Ú&'I‚ú¸Ê…Ù’Ge½5„Aò¦´û½{¡¾Ì	“™ú:9“ueŒùŠ(ÓvÅ€}aÖÑÀ(~{úèOåß?ˆ¥ùendstream
endobj
730 0 obj
5129
endobj
734 0 obj
<>
stream
xœÍ\mo9rþîóP>y:ðLšoÝÍîÃíeÛ`o7Éê·D¶lIXYÒZÞµ7È«ŠU,²ÙÒè6Ã’¦›Ý$‹ëå©âüx2ÌÉÿòï7ïŸýÿÍ'÷ÏÆ“‹g?>3xó$ÿzóþä‹ÓÔÀ™tåÇhNNß=£'ÍÉlOfç£=9}ÿì/;3„ݘþ»óø{¿Œæ0š°ûvØûÝŸÓõSøã_†½åOκݫÁí¾‚k_{sˆqñq÷eºåàƒÛ}“Zþ>ýÿÓ`áæ2áMŸ>,a÷ïƒßý1Ýü²<ú
<º¤»õ‹ÝU÷ù¯¯zÿ	5¥1õºzç¤ßôúMv÷ݰŸh†¾8ú•LEµü:ÓÆ1Xó×ÓN’7VKÞs˜æ˜¤zž%îÒÿ0h½çÛ{7f#µ‚÷Ƙ^:ï®’¤n`”çð>½Iò;K¯ø˜Öàís4~ÚÝÃPGœîuj
¡ü‡ÏoÓmðé™òFxz\°9¼3]w£Û}¿Ka›Ü43ØêçÁÁlç	_i§Ý»ô‹nߦ¶†}ؽ‰°èù4‡R„&ð(áäÓPÔâüîX‚®Ì+x2ÍÐL»Oƒ…Å¶tóCzæÍË8©S¯ö°°ìaø·4I’—yÒ(Œ4óôüBÈøB$û'¸pS .Ó(•Сó)‰áûA’v‘OÈÇ2˜ð8`d¥Ñ%	ßÒRÝó‚û´¼n†ÎÕ䌦ìÓ³ÁÐÇ72¾ò΂â‹°7î&Øõ,èp™. ’´bŽ1C2Ìè¹À;`öp	ÆÄ²‹¶ú:^‹yÝq‘ðÇÌ)-¸ÙýBý2²Õ0à	µ˜êÏŸD
X<¶Å”1ßÂgBÖ%ºÌjqxÑbgòH;î#@MS¯R
&¥FݸSa8„ *àœEø†›fÆûÂ.´é×ÛAÔ´•q–iA¼S €!_Óni¼§MéœÏ`q0Ô%6°K³
i.ólv¾ ·5c¾zÙk
ËGÃQûžWˆ-À<$	Äcˆ	ä#Œ烂¼KcÇ­¾ ŠIœ·„—eXá>¬âEØØq)àÑðªWvsLô¸Aq	®Eó“ Ý¢ôNFœOc‡ÝP-¿›=ê·3茨,c»è50FØƉF\pI‹~©ӛ²ÂsKÄjÜêIBë…
ˆô™í§ðéwCàQù‘¬ÆÏC=1–¬Úwµ™Y`ÞŽŸïÜ€TÔSO Æ„z¡+"œ¦Y1e 7VºGPåiÖ:îØËb2ÿѸäÄ–}ø¼ØA½'DVªÍ{zç
oý¯ô,\"¯¤^ÌlÞ{¼~¢¶bÌƦÉjc…Ž®í`¥$x€JåMŽY »‚²F[+œ]Us€¢F?dæ=n«e‚^Ïð¶y‘nÿ6ý‘ÞmI–X;d?M(¿õ’Ï#вq
iOÓ¡8¨4‚Ÿ3ÔæCÚ0Œ5mððiã…@±£xð0Èqe”HÜý†­c»ÛÙPËsa_ØM¢±oZ‹myÁ¥šcÉh3¶H+_¬ˆ_ù¿äÀ¨ÓÅß‘Ï÷‰A؇Hï”M¯Š-Åá!äÕ˜Ãàã­Šg”£ò*ˆ¥*ûÏÆ
°QûÖ»°ƒ£ù)£Ak¹óìú-s­åÖž†˜0;Þ
3º…dsTQ¹QPê­—‡'Ž'´P1ÚÒ40é8µØªw4íQV¶vïË‚gÄC ™FzƒnV«Ði›ŠW»£Äèúq Ê©ÖhlÖWlçÄÆðj©Ñ—õýkÞæ7•òu£x¢ÂÎ’ÞÓ&~5DCº˜ïJÛˆ›‹€s…(ùÈ eà|®‹+Ï`IÊŽ ÉUÜ›9xäwÇ»:AU	ŠÔÁHqüùì°Ý_à@zgàÇÈ?hÌòq÷×4—Ùvdžt{_{.¯ÊÅ÷rñm¹x#ï{ÏÜÊŽùb2¬>’I7z˜ÜrܸÆc°»^ŸŸ{ã¼.½–û¿”ûõCÁÒ¦=+÷?¬þ„½¥”wÁr&({PþúÙéß¿tdý|gé^V7Ôµ";›W׆	ìÇÎý?YÝwúâúñ³ÞB\õÆqQÞYÿ¶´¼ê
écoñÕë/ÊŠî³jM]xV­µ@”ù¡«jöª­3R;öy(µÁ…Y’¼Úì¾×MA߇.R¶´žåE5ö²ºˆ$ï4“ÿD ÐXl³4æ5˜a²³ÙŠä˜Ëäz„hÍ45óÅóR¢5Ò¡—óÆ3g:fê}biQd3•ðžÅqó­ßé-ñ¾–Vj÷;øwÿ™Zîù=/`&‘Bª©XŽð‰§<«ËÌg&¡Š—œa›¨Ñï}‘Ťœ_ÍÕnúZ°£Ÿ††%¤+Mà©—3›8ᣙMë‰Dn§©#±çÊí¶™·›³uS“Ôj|j“H{¯‚šz»	Uùšy˪àͺ¹0™*fÂ	V>ˆæ’§Ôçx½\á¹
/èõ°/‘$HáíâÍŠªU|­—¡´º‚Lq}*Y•Ä{œ9P#ª¨Q–ÙF G³õOÀ>"ôPyDöm•i*ñ'Q	YRë4#,Ô<åÀX˜¡Æ ¸Ð3feL¼¾\ !j|?ÄìÂܾ¦±¦ˆº´Z»Šh@‹1á…¼G˜þé“SJ=~¡âM”Z0O»Ñf¦5´9“S¸vE™=†è¼ÄàÎ硲ׯ&p²èIÄ8%'÷;yï|KG_è!bóÕ)œš–í¦’úH®øx’@í;Ux›<ɃM<(·Þ¯Ue35ÐRq@gCæJˆ”G,µ0	$C§BDeP¿ãEö5ˆsr²BæjòPz³“þËÖÇ{\Œ§™Š*ɧbº’m†¸³ö`5K*¥ð¦ÅKvƒ5Ëë^þ¥,ùp1Ýžº¹ÅœG™'ֹ͌Þ;},Û¨ì=\ëpÀpªµ“*§Ó\‘â¼VB!²««ÒòM®¹]Ïòêæ¬¡ØÙBã³´s
H	ºà¨vj¨ªLv¦·qGHªùcƒ(R48_3ŸA‡¾:ÑÚYÌ©”UJþ"±j3|›‡A“ï|f –FtS{•­
‰½úfØß²´˜^›ìËÚn–UïP¥ùé
•9:d;ßôÇ­Ö's ",qå”Gj¶ũˆ2RMdÑÞÓ”™™~£ØºØÆE‚€ØÓ€t‡(Oغh!—±#­6$ÃÑ̪ââûpQÜóÒF–ˆË‘ G¢ H&1]¶+çìVôöÚZ?Á!r•<=Å!Â
Žy:•W‡>EÜaŸ‰¯Í!ξ[×ÅE˜°Î×9&Ù›&»)§à')ï¨2ðBùq‰³Ÿ°6—“‹£*‚
`ñ" ¸\„uœ7	§®Ã”ùEÝäbµqY×Òîk’êÓle„y„Ý©ƒFW6ñÍNM¼iÄ•eÖ>mÓ¾uqYtø#ΫšECR¸ëhYaJï˜ýÚÀ¤Ÿ<:‡º¨o™ê!h-üƒÄJr*Ãs"{Ž)dw`Y×	µék§×é/þ^]yÜ rI£Ý\LñÚ,Î|Š@ØÆžUË1Û>ÚÚ'¯cœVj«ø«Óm k³Nv¥°§\Œ/Êk>Ìâgª™UdhgB …§ÒCŠÌj+hų0¯'w!OnÕ£Þ¤:h&ÓKC›y<ûqÇ&¦$1ÎÑEiM})ñ®ë©Ù°—ú•»h‹¡ïªFÓÂÁi5œ(†#•wƒ•¬ï,O¨`ÆÁ9„5·òì°ÎȸV%<~Ö„4A<«
žiÊ­«Ÿs(.îvËŒ¤2´wI>ˆ,énƒã*ÔGêXÒ	§¨R]²‹‡’œÎ“¯-Lo­×œYŽ)+Î,7ÆÊÂK¸T½óRà¾z=SchÏšb@׌QÜvI7¸@k91þlñ„^ê|Ž3‡&5Ì>‰a¤¿0oö̘¼Ÿ bP—+ž¶m@gÓ­§B¹ÑÛ¸PÆœ.V÷s-iNè§áC—{¸Æ¿Ì’©‹-¿ƤŽâaÙÒ›RiöãÁÌ£™IÏî0¥‘|JW'·˜‰2‚©S3žµ‡y2q!fBƒj Ãajäª-¿àJF¥.Â}R=¦ŒŠßïçÝ—°íÍ©{YœµF½è®:“MLÈè–Ùmw”«Y¢È,Nª©–~´KOaº‘ù÷ÙÎG¯î*¥:'˜5`Æã)ªèM
Ô·U‹õ†ó諘ÍÒVo¨h¤¡¢á¸wÛ¸érp*—ņ‹öU%n>É€ëÃ%]˜?ú1æúk¢uͯs´K‰~ž;E‰ŠW‡³*âDeô/ð Ö–2D¹£ÒÊ"PÊ"¯Í¦KŸi]³ö»5W岫-”…ñk&D|ñEí8ݨeÔÄ¥#A[µÖc”èˆke£/E7ò‘•\Ó+™.¾ÒOô„øÞœÏÀ™µÆ°9’…ÑM›z1©Kx¸"%Mì9¶›Kzê¸ÖT¤5VYÇœö`)£#
ä»-k¾y„6Œe"Yß}»Ó§ã”kN³®1Ç–³G»¶±J«µLØ0ÜÆ­Š‡Ø)oÜû5ãg‚8‡9Ïx´£Púà8A_Ûv}‚ vály.Ô®×-Å$ë¤@žÍ›€ ¶‚òöšs÷+;ÎW>ÝuhÓãÐæb¨<0jÔYñþaÛjGÛ¦ø^ѹŒ4oztSyÅ\Ÿº¬pØÅ+!ŸTé¿£@%ðþç“We«*RIqµ[kÜä´˜Îghm(H(¬kÿ;’[¥6?]Tk²NU\ÿÍ.Hk¾(™ê4¶G’-G¾+&"ÕD­¸nxV³¦ÈZÆ¢ºÖÅ 6ä8åÿŒÒç÷>È"'½¶yçÔyÙlãJ9©CÑëóëâ`¾œÊe"ž‚ü—åîØ¢)©PÍå(³(²t„mã,Z\j.StE<Ži§¡ôÛmWŽyÓ­ÛX£)¿ý¬xq]‹V²U¸W•¶Qo¨—tã;$Xƒ½$8Š#¨ÞŠ÷ì“ß_¨1ʉ&:<å•?Ö¸s7[72I³Ïó®©ôÇNJ‚¤­«<%«¨mN ªÓ»¢ÅÌÈa=&@j¯š
¬*³¹¶F}b‘ÍteM8"xÈnMåŒqØ}!ùÎYĬ–P›‚B­Öö€ì|‡ô¨Lÿÿ’ÛåÞ¦£œŒGCW1Sæé_)ÌçÜf>y×gmºYѱdn’¥EWN–Z«6MÙ¡Ýk¶v¬E஘U‰QÁá¸d3<µñØÃEdxÞ 9^ÌÐv>‡Iš‡Ïn7®d¯Ø‰°dIœ·`×õ½*µ>ÿÍõÆ z8_°ñY²3’˧úçæUÊéÿ³µÙÌ“­õ—€A,þŠäÝHáF.L«pćœ§¡5‡	¸Ø¦þΑ\ÍÆmU¥Z狞¸),â¹ùÕÈ,zt]fÀ{åë–†.ôR+W™KÖšHÚM[0%LYeYOâÈðTHÊs9I]„Ø­N[³µ¹ˆTâã·Öt¾àW¨Èʽ·ëÂ
-eŸ¹	f‰Aìá3ëµ—ÇÔIO%÷ݯ¿ÒÁtœ³uõLܲUä¯Ç~=»e(âj¾aàhb«xcFŽÙ-76ê	Äú,›åcG‘[Ưí&ÉØ+,¯]¾#Ê*·«­ü?Unk¶bG°§[u_‡Š=u:™¥µTÞ6]ï})Û´P/’˜Rg7à‰6Õº”s`¯ÅÕR±%5žåh?‹èËÓgÿšþý«Ú{Åendstream
endobj
735 0 obj
5410
endobj
739 0 obj
<>
stream
xœí\[Å~wòV¼0ƒ˜v×¥«»#å!	 ˆB`ˆB$Ö^{°w/8ö¯OkªîžÂ²v=Û]]]uÎwî§æÇ³¾sg=üãÿï?¹s÷«ñìêùþìêÎwÞ<ãÿî?9ûóyà|¾ÒÍýìÎÎÞ¡'ÝÙèÏÆ»ÞŸ?¹óïÛ»Ò~øÏù_óSÁUOÍs7¤üàùeü—ý!î>Û»nž§8ïþ´÷»/÷¿;‡ëŸìrã«ý!ø¾ë]ÄùûüÓå»>º|ÍüFç’)üî‹<ëÇ{þãc˜iÈcâîÓ}èú>„¸ûîü
~å1!únžf|ôw7ÌŸv_ï)_õ~÷¯½Ïïðóýñ©oöž¶_íÀû?„¾óg"®õÑÞ§<·v/óä»ç°œö‡Á§Ý÷y‡yÌW.%àO¡û?à}°Î×ô¼Üùƒ$KŸÙᣠ"o“_ü}~¿í±^|P.:½Ø•‹ÕãüéE¹ý|í™+½ø¦\üv§WO_’ßX|Œa²Ï¿Ø™'CÑòÒ½~^‹“‘ÊŒG
ÆÌXxLÀÞ8Íy€CÖñÕòç°Þçy6€Æ;ÊŰ{U†>¦Xß!Œ¡›Î.äeüòtˆÄûe7-€åîY†3‚ÁÅУ(~—'­ÐéPÂé"£T‰ÃÍ«<èMüAž(õ, DÓàkÇ…D¯©ôº¯Íã<ÊWÀ•ƒP<†G'q	O4€þ6Ð÷£]¼NºØ”7›²ÛZúLÊYy;Šs¾?íîeêÁ§1áŒ@Z&h~eÂeÀµ§õ×ÊXV°¸qê¢H~¸Sà”±;¦éaã3y²¼Ô;LØ~ˆŸÀüèŸ×fäPÖc² Ćy"êkX·…‚°|˜4aa öu"*¥Kb}T®À3@í“Ҳʕ,½ãeÅ4„³è×àG|´böG`,&Ô»27puÀ«DôüçZÅÌN
ï6ëÛí°¡ÇwÃ+ÿ›‡¶Õ7€š' ùnš–êV'‡™ž=ÒR^„ „3²6¸¦:s÷Â2ï	¯a¹€'V*óüÀlžGc®Õb”B@1(È]£©-o:y@°gôà^³Ñí|eiy7Àr–ÅÓŠýÃŒ»>Å~ÂaìûåZÄDÈlwwó-øy?_óÌÓ(LiÈÃ’B·Nš+Pßìë«W{?‘Öƒ·!Â~s@ ½Ò=“¸n†KÈŽŒžøF$²‚è
½3·;¯ d Õ%t%FN=-JÈÞÎü˜Eá{/Ú”&‹•vf2"ò‘ÉzªÀåI1¯ª1_ï'˜'¿È4ž‹ºÔõ‘•£M×fΰ5\è	§[:çq@KVDŸîžÝ?ÖN׳²£5N >Þ* tñhÏ ó`×3È>hÍÓ0y*‹4xðóP”g£a¬.@…7ÒÚ/Ú¤r¦N¼WFQŠüL„a}èµê<úì/ƒrŸ56ð©R8\Ø…ìÌ[»§¬|YîÁÜÐ)­ºNö}}´XºØƒÆÍHò=Ôf9OL¦¬ÀÙh£²Ò‡‹/-ÎYY•jKêY`v0ˆ3*'ŒˆˆJ)³j2ª¹27ð0 F0BÇ,a}P¼³Q@•"«q
×v-|e=D¶n¬œ±ÀîQ%˜ä!Œ© ¬X&œ¿GP\”Ç+{eæB÷§ˆúE‘yXeÞé1ß%…$yMâ8¾¦Dn
¿Ày7{¾guj¤X6Yøƒ¹®è|…ÊÐbî©Æ€¡5ŠnŽÙ3’DÁf´Õµ‚/ûCi ‡_ô.`°Æ{£wE•qlG,XK)0ê­¬XE`j%¡”)¼ñ®e®V)’:_(Å™œÂl–nãáT^IQªiÁ¿aÁNÄ~ßl=l–‰ì^æ	I´ÏZ;IÁ„iZcZ†´C­<­ÜÇbP°CÝø<—’ÿ¬ÀNµr«9†ü‚SÙ¯¹„#]dóÅYµW‘|§²ôEj‹Ä]ìl>5¨_ˆT±vì¼ìÚuYã·af!žÚêÙq°IC'7£R™
”"Úð§DÕæðÞ~Ý»úHÜg¤À2HC€+:›$¸êt› ÂÑ8Æ„ªÜÝ¥ÄëÉ&ÜæY˜ ˆNévžúU½(	ª&ÜæIk‹¥®8,{êQ_°²¶d%•M^TêR¥à†­æÓÍËJÈjÙˆBu‡§^DÄÌÓ8jê3:
r~Øcufb×Ùo‚ÌD°Itî¾¶mu¨*¹VÀ)~ñ3ñî¥ñBpî&ƒ‡\\¦8°WÀà¸ávÍ@Ù?®Ëtèc•})#*$â‚¢µl„cÑ–ßKz@ò\
¨PÁé‚
¨Ž&o²Ù‰y%ªÖàú$+[í2Çb0Ü´ÍvsRθ6yŒFtþ¨’ÙŠZ4n[%È3,“U®xO€WÒLDŒZ5ia­,RÝãúÓª¾UÉ‹TÚ©BÌveu¸bpëØþŠõEÑ€ŠÊÌÛ8QÊO·Æ2݆ÀDˆÞwiœÇw‘¸40B]$Ù–¼aV©šâWÞ;²Ë·òÒ„ð^<žôH2@¸ÉÕ§m.Œ½Šô@éÆaRw}›/â?ÅI'¹Ôa!ˆÚ¬?`H$bí‚–wÞ9íÍ	â×d¾«îl¦–14G܄ˢ[OƒéÔ»w)îZ©v¦œ"¯º
\Y9lÇ¡!Εó~Zʸ+¿æ”ô­zX¦É¨
i*ЈTRþ¬î~ÒѾÇDaSú•Ä?A‘,Þ‡µÁ„‘V§;ê¾Ô˜µïD(Ô¤t.i…%A½Ê#Z£+ul°ìd×ëmØÍ‹>!+¸‡c«‹@ô¿Ê”B¤ƒæÃÕ)Ñ(M„fÒÏ˲š¼`Ùÿ±±îÚmàºÈMm™—f‚<í,ÂÔá˜->B°‡õœG§çE*W™}]ÙÌVÊû×P`’-¯ƒJu5]…lŸWåçÖf…µf+t6"òIó*¶d~¯$ubÚŒ8ø,ÝÏ!xãâׯ1?ºè~£{}›ÁQG1è¼Ó‚ƒ•ïRNäh½®uÛ¢xÞ•O¨àSwFåø{E9³ºUO6n)f¹xµ‘ÉC }­â\Âh©¯B»S4‹£ŠÞVò¹¬¹ªÒˆÂ°n?3Ôkó€­w_¯D¬¼Þt[‰\ÛÆT
,Bgi„H%G¿â¾kZì¢=bÛ§°¢_R¬|¿ÚàO©²X£…Z]Ê
ÖƒÄ\v ­êšH^Y%ÃZJÂÎlºØÄ’¥IùZ¶ß¾’×öK}º¬7Mœ:ü¥&¸¯dÀÆ)¶°ù”ðï­tJ*éß·êKʶ¶,Üt4Ûƒ/õ»?ª(pí6Z›hÕü0O-0s©	TZR¿sŠøœx’ŠñS¿û±§‚Ó•²ç±M›M³Clë7•;ßã8awùvúX )!H?•¾2µ?0ò›úÇbs‹¼1¡lê†b
	­Kk鉹cGm_ì›öQÚöæ¯â²‘¸wìvå;-Ú]­­¶ú:U¦‘欤LÍ.(èSz6‚Ö0"G5áWl§Íö+ÖcoºúhÁ¤¦@Ta»¹—jÃå=)ÂñT㪠ÄÏ“&–®C-‹š®rëè/{Ë[_Ö—p	jV+Çè¬?9sÃù£;Šº¡…Ò”¹®‰$0þž¶)j²h½ç¬¹a›5z´ÌöL™0èJ‚ökcê¢ Ádº5{›åß7n}z£qpq½/ø•!Ï/^×]øÏ´´}âÁÞœž’½;€b=¦ÄCHiEõî~å¸G	1Ÿš… ïFÛÄòzý	6D·~Ö£Û—ó!2pã̉œô(\•Ûoôâ·;èÃrñø‘Ÿ£Á¤…߃賵¦\ÖÐ'‰%èMJÓÕ¡õÏ'§~ŘãÂÔG3õMd>­ïqCH=0mjK¿–ÚrÆòH®{vF¯™4}Pëñ⑆=nÝ]ë|úY¶ìôe3â†Ø&Î0hèÖZo/–Dí”p/eƒ‰õîpíÛìNªnøöî­ÙpÚbm}V—Y»çCÓÁhò\SªŽùTZm??ÉiBMÞÂÚ=¥ØÛ£
؆>ŒíñGµ‘Ôƒ’§ÓÕÔ “%YÉ5IÑÊV¯8>µDrÝf{~ KˆwÔØx#t£—_V\7:â¦ù<ØÈl«Á¿n‘»d¾”‚’‡oTèu*ïõÌÌÛžpÛ´Ì ¢Æá7Ëü‹[fóÕ†5¯Nô¸NÝ	}dà†é5_!PHºöµoi™§.eýmX‰™‘ùX7%Uß6¾/€Ó^'äÊŶ'—¿`ã¸pV›F _ÞR³X9Òл.¶gî4˦>¯¾“‚T“ya]&%lþ¦ŒÐ|GÖÄ¡úk¦Nzü¨âk©Ôåðp÷ÔF¨ÇÓb”Ôj:êëø²®îeÓ´UÝã4AeîcÂ;Ë«4gZÏsƒG¤œ=ر$e§E­öKGÂDEŽæx׿ùØzú´]CxЄ{•g@´sþh¦È=Ú©a™eQb|ì\	­¿–ðûJu
Pzœ…dP-ˬ}hu„Awi\Y#Ntzй±¹ÝS~dD¬8S+\¶¿M}}|‰3å´Ýe]ïX›L°‡ÍDÚ´ÇR@ÛE)bדmƒíG$Qæ”4ðHÚ|KƒÕu\§ÓcuïQð?”z¼|Ò^B4&p˜Eûܹs¢:æ¿(ã°Ã¶qÉüIMªUª.$iPóÑU®²!õZÞxëÑ•S<0VX¾8ëjâ¢êËô;[ò½˜wýF‚ª¦vV]õÆÏªæÄŽγ˜òÅ)¹v¢EÀM´Å·APBƒ¹,#ÊÉÅê;œX%5¬ÅÕ°TÆÐª¥ÅI#Gí«ÅêXÎ×éÑ*ýwsLY²–;ë¹$rh{ˆ-V°§q”S"ÜÚƒyu,¿vÀQO¶qÓò¨ˆœ@ÚÊ, ܶætåý­µ':ÓŸœßùgþ÷?½r_endstream
endobj
740 0 obj
4715
endobj
744 0 obj
<>
stream
xœÍ\[oÇ•ÞgB?b°/;xF]·îêûà[,-[¶ØØÀR$uA¤!Eж”_¿çZuª»‡¤dÄ	K=]÷Sß¹ŸÖ›U·s«ÿ“¿O_=ü~X=¿>êVÏÞ9j\É_§¯WŸC‡ààÍnìF·:~vÄ#Ýjð«!Ä]çWǯþ¶v›´îàÿÝÆ¯ý½ÍÛu.­7Û¸þr³õë¿lÂú	>||º»Ò‚§Î†.¥‹ÛcŽ#7ã°þf£/?Ýà|垺Dø‘ÓúÇM\?‚Æ/ëßàZóús\ï{h²íu'´ô70ú+âÚÒ§ø˜é±.oFÿˆ³C×n€Ýë†×v:líÿóñÿQ·DÉíút=>ZøØ$켕ÖmèvƒGîô+n÷%ìôý¿
c€öëx³Ùöë·@ÉøñÚ`sÎQ¾ÅQ§@%üýJfxÓÁü]—©éj³MëséƒcΡ½D|µÇÎð_tá5h`éqG‡
(Upå·¸Wzýà±£‹ÅEe·Úùg(¡©®+UñmÀѱÙOïh€é‡K^lŽ>§]ŽJä½lŒë>íŒt‰å,/pçØÀk<À߯½7-ž)3$šÏ?|!oqj=Ü‹Òl¦¹)/at‚žÃ@7…Û‰½½Í"ÒGû(•¤£¥ïT[Ît–PdëÂ.õÈÉH˜%½Ðκ@ï…ð=u@„а}Œ™n”øIŽé€ÊÚ9g¢²ç$=ßðU#Bº¯b…ÓôR¨)кÂܳ‚÷ …uÁ…>ÁáMólnd8OG*9pÞÌGÍAØt¢]ûÜ8h‚àLèüÂÐ'øÈ€Ãs•›(@rÈQÜÜ8ŽôÊ ƒ7QÐ±ßø×*e“‚Þdñe*@ˆ±²,Ê õ¢.WѶoÑÆ!´¥13]nŠ˜0·³
}& ®
f–VÀ]V|É»m:Ë­ÞŽ¥….‘ሮH_\öÅÔ€ðU¾Zä‘´ÊVÎÊŸà0<>SgÉ#-ø¨(ê8í½´GX¯ÇŠ(4퉑¼ŠAñ“*ôË/h+EOŒÁ§ÝªCÐø÷
ªÛn¨BL‰s3*pp–/½k”p¹'Ö>–†"ïãAñG'_?ÅŽº+ƒ+éx²%ÄO ¡€ð®bò
8ŽÉ1Òô´­`+`byBJ{2¢9UÄ)ùûPƒýÁÌa=žW.îBì=©q/
úë£ã? w»4Dc?¥î’ë@$˜ÞÑU,@šHwÍCï€!_oÀJëG0BpÖðpç¯ÊðxÁQµ‹!“’CØõ	í¨-B#;’Ò2†G»,TgQô
,4x—’—9£çŇÎ
Céé%º]²ëÒ·äúh¶¼gæ€Ïk×+º­äìáÊB¼wï‚ì÷¶¯s?gt¦ÉVâι̎딿2W
ÃXÎ>öfV{vÓù¼d‰
ÁpÕ+Dc²`MÅâG¸²½6£Äœ–˜ý|f)ú¤
1·hr1C«™âa©¤¸)èªZózäFFD€Í‘¡üòº±O¿<>úîèÍ*–ÈÜîÊ«à#\d^¥<æ]Îè=|öøèá㿬Þ^Ýœ=üqåŽ>Â?>{ò9üõø‹Õ}ùxõÝAÏ¢%½zhw‡—ÙEñ.n¥Ïá
§Þ£áüOßpqz»as×uDYýµ-{JFlŸ3ÀT¥<#œŒ¢…^•§U`.ˆ¸¦›] $ò˜4¦*68œ-Ú¹ªô}¯ÒWLÈÏÞ*õ"Éå„ô¨êEûK¥ÐK¡Òo¨S™-&"Ú¥Ò§@,š¡•Û4»<ÄÈò
§1$m¨«)LBH¨NXO]£ÄYµ-/Œït±	¹r¦Ú01ö­kT®p²C×N·2ˆÓºN•6b 2{ÏçL*Fhžõb œÛ-\2
1ˆ¸¨oT±Ü`olĉ¿1E–ñ6€à€h.ñ€¹Õ¨î+p8õ\yã… $+vŒwÊæóPæÕUmK¹oŸ¸ÅðÈÖÖ™èAµ$…ˆ0‡k,PNgl°Öï­f³Ø	ÆQk
'UÛ;3“×Å4_á‰Ø5ð¸¨L£ÙW©&æ…ð-ïÔUÉÅg`"0¶zãOOiõšÇ«ëæ ÒõÐícãÀíÒÉ:r~£ÐÒ{žáY翇Вƒß"´BJ4e¯~bA`¢CÏ¢}¦÷C↩.CqvдF÷낯|Š~p.9–!qJõzë:‚ÕµµHÉQµa¸“ì“üQ2‹Ôͬ´6\C&Æ–°ÆVˆÐ*ÈcsabQ‹¸.>Í5pŒE‚vØ5µ‰ëL¡¿cÁw
ƦY#U{qNÆ¥VsÉZb$rVÉÜ-¥}
ÅŠU?×ÞmêC¾ƒ®ßõ¡º™/æjÖã
	gÙÀXMLŒh0÷r35â )Hà™‰—›ø[²Ë,I5ÂÀrhl«GÜ– §ºn‘õ5D èv¸"4¡±Hz^&*¡-NAì|Ÿ»4‚áS
mñÞc—úÁF®.hΔ£¬˜ãÐk0£SK‘­kÜg€ó…(ÏÞõ!™@ÔEÙ)¢lsiýPgňcÚÁžƒ™ö—ÊCèíLê Ó~kl­©FÙ>"‡ÁÄÓI(¼×ѾZ+Ï9Ô°¿k †]ld‡ë–mŽ ÙM
pë¥5_€b£ßiQn#OÄF‰ýš0»ãL«;©ç}ìêT!™8pªb$/­ñb+£çIvµ‰½›Dî=k=íÓƒ¾»Hö´hg«Tw½Wª«•&qÿj-±íBm-:•I›	Å9O6µJ0‡{–DZ1"‹Rì¤Ê㮪#ë€Õ?>Ù¬¤mE¹j¾šqI5ÑŒ92™ÐkÒÒDš¼[”â
N03%IBÓqÂO?Áï'uΉ›ì•ö/"*acˆ2_è…uh(§’ç¢ü¿8¾µãÓ
FòØ _5%[ÄTò®X1Kª¤"×X݆M^±ŸàŠvó:~‹k²Ø š&whlG¹ñÿ„f0ßÂÛÔ0t±O%6(nÁ${Ùy1ü§ì,×ýÁøkð„ë6(:sxc+qÚä5òbçf¬r-e#Ò)´Þ Ýn&XŽÂ°çÐ×HÈÄÁ’ÙZ¯ùZ,º‘XÉ·f!Uã°™šˆç"§o	tÂçm‹<]ŠÇa眷&l¡ö÷I”›iÒÄŠð&«ªŒHO%#i…GSYÁVYCU5OÅ?›êC±áš€É’%,Ò‚¨Æö^ˆ›Uo¤»1ÈÎ|ß”¼ã™ÑÁ˜ÉÁJ¬_§Z¶xÔ{4 ›óÙ2ºþU¾5ÂÐHr~iØé^µ1zÇ¥zVÃl*'v“3­m.¥b ×T;¹Öò¢X+'áºØC¼‹ŠÝXGIøŠa¶Å”´m¥]­ÿ†œš[‚ŸA
ta<öZÿà~?aÐг8Ÿ7¥ñº‰«%7ªx-WTÚëÊØ³c&8±{מÏíõåÕÒœoËËåéõÒìû:æ¬îóÌnIÛ+"OêË›¥}Âêq8obªÚÊ£tÅ|ë9ã8%Ì™vÕà™ú‡¤oÙhâÑ€‰+>Óï„…Ø#/T	ÉCþ·nùqyù¤¾üYÈr‘ã»;QÓ\æB{…äeÍUÆ·ä”—Ï–^Ö1grƒ9µÄ0YÂù’WK¨¹¶‡›Õ̹g(o"K'3Ð(ZFX€ÍÛÚ÷E³}üÓL¼>ê°T‡ýÎ`º[L0ùÞƒ¦H圧_Y-¢Üžž--µYéÛŠåWKÛ«+½]Bæ•쉲{™ÀºQ}žì4÷aªñ\0õq8apðD­ý;ƒãIòõ’¤ùvû%ÙÝØM
Ž—öžSp;‰‘Î/÷Myy³$L®–n¼*–]CÙ"º9’òoÇo„H€©+/»Ú³+/?©/ïè	wã°`ë>ÆìðÐlʲïê4wu½\:ì»fEÃS‰	tàt}OÖ´~ß7¸ò­úÚe´…tØåžÂÏ¡Í?Û—`aº%‹yPz­ˆNú‰ŽoE!~ISݧ[ÁsY^š¼ÉBдjý]jô×4sÙŠíZèÔoÌI>p+ª”Ú}ÚiUiaîÊÛ†áIx™’³œ~°Geü±žÑsTäwo=‡"éÞ:&»ú¥ ÄÀ³¦"^nj\·Äme$Â1-”]kÕ¢F‹ñ5,"k¤z·2íÍÒ(”hËA3ZbEÂÞÎçeø<·UgÁ¶<ïIq4ÉzüPÚÂdZ4åYá×¼<Ê¿fíšøUê+¢Í[éÒæ?šÔ…7µúJÏ1©Êö£¯#›ô6é¶l ®eø³;Îu™´WÉ]Ž
Ó¥–ݰ"H3c%K5‘\Tèìɹ€_6\7Ó%û’ÓØAÊò]ôYyçò(>J˜ˆÅŒö“:í¦X©TKÄnQ×fû
£š:W_RV]¸º‘×óâÓçƒ5ØLÞ~ñS?ltÔ…2;4„äŬµUÄ
’åÔfs,€Ÿ°©\(:÷œï[®ºgSªÙÙÅt½ç+Ù—…i^6¡°²mþ"º~ê4¸ösà&óŒ_j¸~ñ316ɘ¸E¾u4b~Î+ÃMdè!®; åÈ¿[Ëeút€åBà{)ŒÀE¤zwM
Â$³÷ÌF_|©R­µ*§†“¨uòÕˆ2üTYý(‚mÑãú×èé¿£€ø½ËëTÓ=KVÖPkñ¢îø'*Dóð!
òO>L·¿¸+ø¸Ü©ß•lX¡áÛ|ôÌ6O£äp6HM5˜;h‘t²ùýŬµ#¤•NÃ%`õåµ*øœ•©”ºZ>~+ÝÚ²Z1¸îi]Éç#J“TnEÙÊ¢&Mæðâw¤¥ÌBËMOt¢8…OùgÔ鈹WúÝF1_lѲÁR*ûÔ,Ù–"ajóí\Ó¼žjES§Ò5™ºw˜jG`sqZ÷ÎßüÄßd<™2;dÏÔ	W×F2.îåä3»ƒõåí¿å¡ähÁe?jŠÅ7fP™ôýìwGÿX=cvendstream
endobj
745 0 obj
4824
endobj
749 0 obj
<>
stream
xœÍ\k“ܶ•ý®Í˜Úý æFÓK 	fË©²b+Ö–=ÎJc—R¶ªvôðHÏC%ýûÅ}â»glm’RIê&A<î=8÷ö›ƒvÛ´ð‡ÿ~vç?M§WwÚƒÓ;oîtxó€ÿ{~vpÿ86èúxe;·swpüÓz²;˜úƒÉùmÛŸÝùaÓ5ÃÆÅ¿¡žÿW|ÊuÙS󼯸àñ‹ØøOÍ¡ß|ÕtÛy~Þ|Þô›¿4‡ýæ®ÙÊGÍ¡ëÛmÛyì¿·ñnï»xÍ6|¢}Iýæ(öúEÃ_¾€ž†ØÆo4nÛ¶ÎùÍC¸ó5üÛ8ßoç0ãc0¡o´ÜtÐÿ¸yÜŽñjßoþÚôñÃÐwøÀq<>õ¤éiù¹Ðyý‡®ÝNñ3‰çú*v¹y'b‡Ý°9‰‹|×®`bñÛϱßk¸ò®qØrv›Ë8§9N`±	¶}ÛAø.žCSê¾þcà3ØJÇ6yEõ!JnÆF]‡WÎy&"^Ó·kéA¸ã‡)Êo°q’ØÍóøÚýŽõ›ð
ÁÓ¦1_Iƒ·0ˆ8Diô#tÝo>6 \ÔØv&&ò3ÏÏÌ‚‡Ãé¶Ýb(Àû a
›´|ÖôsìÆu xìzð#L²-®…‡¬¸7Íaèú`ú寇w‚3*›îÆ;>^:jø¼q#î7kÁ™±ßEÆK<ÈåPsع6Ø™ Ÿ7·N¿9Å-ÔoîÅåt‚áâ×â_ØaOãÿwÓ­Ï2°¨dP›¸\ò;híðA¦G}
A™¬;©Ñ…Í{Ø",ß1Î>NÍá.^Qã ãIÁcgÚu”(|ˆ2„›üñ#¨h!$Õà?'„´©ÛÁÙGXÏ
L´D“˜vCSÜ
m;šÙÈ6H|¡ŠÏ®AóÜ¿2
yÝo€+È”¯ÐÞ3ãÐ.ãúΗÚ=Èkšzƒ;¢n˜IKu}Jºö!Ñû=h0w7~‰bu@íc¶|äSG²¼àG£	À.—œè‘û6 ,R=#,Ùš/TßAÏ#nýLu¾(D "bH$ãÆ­ã¡y!¬
¦ðKãP7¾„_spÊ<ê}Æ!½P´ïÚÊãG±¼ ï t-‰!Á‚¢q	U¾#T}EV±”ÅÈŒVG‹èâjPŽÇ…ˆqJ­p®i=}‹›¥Þ'ÏQ$+ÊÙ­÷“†}cœÑ,ÏçÎ;Ñ·-"–×W×—OøvFEü4æiW¿‡}£Æ…‡¢†Ýî[:=iX} Ì6™ÕK¶Ì¤1Ãn£Êþ"@'¡Ò\½ŽwÚ­M0íŒAðG¸ÛI-!gô^ú1{–­ë¯ãf!ªÕ f,<7C¯Ã`ÊÙ%GÅ÷MOWk…ºrÇ!W.—„Þ¥¹LÅD„!c×Ò6¼½«Ô#-ÁFxVÀc8ç%ùi€`Gê‘¥9Ž™8qÉŸsàbƉ/Å3]úÅòýHï€O®°|ÿ–pÔÇ#˜â€]Ö|XènaŸ	[,Æâ$l‚‰|ïoTûŸ7.vßEËóg½†*EGŠÛøqêìOÉŒ=÷ð8c¿! 
“Œh=9¹ˆ™	Ø÷ý¨D‰hàU †1ï°ÝC‰0’¥2]ˆ(±#´m¦74c˜Káã$/%ÃÖ"‰¶s[å`Ê¡-¼ÈÍŠùxB1²eÁdnšÑ’%ª¢yÎÆmÛíW“FЉðË´ß'v|—ý‰Ž(	Õf‚ǧ5ÇÃïd²Œ›h¥97ÉÞ„¡ÅUªr£[ÒÎxã.£á#¿0®éÛ´	Ž Ç.çÔRÏ0§wp¿ÅqãmDàN]ÕåFx¸q®ÐOw8ÐÓÞIŸâÛåÑ™øn§;«ÖT<Ìèž"ü'Gþ¨&ø»œ·÷7<Ê57¶÷J&ê*õ~·éónÌ0}è³w|ð<)(Þ¥eWC¾ßF]ˆÎó°¥€
ûð \"6V9¸úS‡.¦¬‰´Œs»pF²˜LgÔH¦GÒÝÚ/옄^È;a–¯w…|»ˆˆ„ã*Ðü²ñè(´Ï|*Íó¢‘À´;;=f™d	Ì4÷sÂáÓÔ±Q²!øä5I`’E䤌aÝðU<¼î° Ñ‹=ƒh‚QÁtãwÆšÉ5Óý+ñ¥¯¥Ý’"8‹ë)A™	FÃ#a•Á¨ç#]Í-^É0Ÿe•?*±%%«'RŠ©/¤,€É`&­¿QºžÃ-L"Ï8B2O"/Õò5°~Zö)㌓›µŒƒxÍKÚb:’ôÅÌù½
&R~ÚϳÚIo/'ž%ô">t4aƒ£‚Þ{SqF$úÉhï‚Ë¢1îÕDs¾PN‚N‚Á]É|E's‹T‰ZwÉ‚$·íz“HòaP7اm9×!•m›ôzVê{hÉ=údQ
·Ñ›6	ÉâŒøÙ€ßy6'$ÃwØ9Âçd•oCŽã²ÊZÊŽìÆh64ZéUXRÙ“¬áeÆg-ÅL’ÆjÛõÚo]ûk÷Òõ–$µ×ÈŠr›ù*2Pg	ûHÊ4t)#£ŒzÊ´å£`Õ×Ö²²eU‰1Nd.^
+¼°g	
Koùeª-rK—סtÓÜÇ!K¿òBÖòWm*¯í,ž”~·H '¨›†e
 ­ÆsM#™£Îì{ÃB|r…«æÀeN7…‡í€ý0X;æk‘ë:ô“–†°Vý;ÄÂæžJxãuYºÊyŸo%¶÷Ö–ˆ¿P1-g¼‡©È‰þD%±Ò_Ìä»0S0¯Áo9œzê¾Lk*v˜¤À¯!`/½ªÛd¸Œ’eÍÇ9±ä¹y¤ÒF‘¯&«/šZxÛÇ[§JoçÊa¾œL^»Õª›1à.ôšùÎ"0¾þ,#ô_‡‰_7å‘“ié=C1Ħ£ÒF.Ž2ÀÉ:­9ñéšÌgbS+Í-]Æ'?£S¾û\3Í)=ÔÚÌö.¿èrVotÙQÅiÛˆá¬Þ¬h>“ØÀ¤ôã$šUହMî"À7?ÈÝ-×v¥ñ¹6YAtè6Oµ>vœ†{˜>~£ F0xt±þŽYùNï·é¡v÷ŧY­by„±*—%:°)6U\+~ŸÙX–ýµ×óŒïh³CcSßt%þ2Ž	‹r€!ã!÷O82–Í9¯ÕÒyr·Nä@X³'‘ÃåÛ¢À|"xS½éU’Ä$\>Eò‰}[ß•'ûd4$ï©fuZ2Z
á¤_ì}©ïœs¤ÒÉ>	‹ñ)´ËÓM£àÅ-•ì)ð:ÂB.›Euñ8‰£Ê&=ÞšÍIŸÜWÊðGÄGÂØ~Ö|ЄO%b=›í\ÑÂ¥â5@OÙ'èpk¼+®kI¤Àé­!`
u xÂ~Ó¤Ó•Lg¿æ‰’ð–Åz[X-Ì	‰Þö+¯³XÚOq¸÷ÂRÂ’wZ«P9ç!’”«^ˆ.þ%oR=Ûañäd£‡Ò{écM“ðY†nÖs—|úû\†Ò¥õe·÷B»mø¡z=oOÕXÎ;U#£Ø3Õ|ÄÐ(;eô?j\‹Å™y.\ŽnZP0Æ62b	
âì÷LµÓ¶Åɸå©Iëäʪ—´•Ò?»>„¬N®n#Cq‡©-ó€ürRúÅ
#'òÐõ4©-uœ4ö¼õ¢ª:PŽniy.;¸ÉIåE¸Ï¹É•³¸n$s¼r6ErÓÁwö`V‘ìÊ[bѶË	ßÞ^%Ì\¨6•sf¾v,Y¿ý”{$OÕ:ÃmÊPòV"óÌ…UçUR„ÓDQr툇£lY¢¤#<ÓA.óÚ™ŸÌ dà@Ësoµtû£lø½í
â8¸‡qæÊ©"ÏÊX;Ìí)T»ÙᦷzÒ(U;òcàžðx’޽Èɽe]/­•Cp¹©ž½Õ#$¸'WS=´Þ¾b…ËcÓ‹úF²s–zã:éŽïSêÃ_kÿúÒ©2™ b"—UQ_G`ì=žÑ%ãqÎÜâ$½({y$HG6X6xÊ­T:ðй%Èt§Œ(ŽFYža벂ÌÀ;Ée<Éfy‡›¾äS[ §‡Tä*í8ƾ7KÀLصÜYê4b§—E4BÎP'–$kùÝ´ä‰çlW‰£
;’Þƒ[„Mñq­O¥•Ë_#ÒØÒMìÏpH¹ŒÞøöyF#»Ëùëz¨è0eyB+sAYØ ,9slHòs\@Kr¹`´¨øÎÐÓÞŸ“#/Âmþ7a«x_ÅÀ5ý‚Î2·ˆ¾Ž@ñ¾°Áãô,‘2”pGÈËëÁv’ÑïHTË=zq°i=Zk!9O\³šZ¬³þuY@¹a4„Fœ¤Ìù3«‡–´vËï¥ÅP?Åx˜¦œÑXU\Åò‘3{E0Ìšˆ¸Í‘
IfC¥‚[1œôò¯>UT8ç,‘¥e¯6¯s¹­‡—FÒ»\|´QëÖæ´…)SíOZ–äZÔË$JdC\Q_—¿¥sO
Ñù»$µlXkÙšùØp¨2¨ó…‡;vÎ\ìÚ®YÈë·IÉÆê{¥³_wƒ Æ–Ò
FÈ_Ï,2äX0mûO†²­dA-å@™Ï䃙ƒx ÉÇH,bNæ/“âÜÅŒ_ºe‘OþÓi”•W‹2{%~02öàe =‚ìÙwêÉÙq@y/°/¶ÔcK•—9’t˜°«·šñrö¥=¨€¬'¬º¡`^ŽÂwâü#hTI„Ó6?pd&s&ˆeÁØ$jw…VnG|×%ä6öVÀá÷ª&>Œ[O*]+fÎR?®Å¤ñÁ,W²²ãuee3L;Ö)½­Ìæ5ëF™çïßó
Éý×S¦ËeÔË4
ðX>H‚½žûí>‰?™9l!«º'e•(J¥gyµ"{§ÜeÉlÎîI™=2ïkÕ&LwCAuø7(øtH–[
ô»#óh]pkn¾rV
hkñ€¤`HèLè.ÐÒ¯ïÿ;¿}³·Vˆ3¹IÁP7ßo*b5ðmìªú@ÅùÃT軈Kоâì±#%ZƒÍ¡£*“kLöEî¿H÷¿Òû_¤ûߥû–àõþÏv¶˜Lß×Dq®Ÿð¸ýŒÈ¾Ù_ÖfŸúÌ’æ•–AN7
Ä‹Þ)ÇňhšgókÙ‹]|7ß	¿¿·èZ|;ƪÿŠ"£C®¾LêO˾‚#jmqñYM=¿ä$FïqŸ¼Áèâujù.)åÚŽYU´\<å‡ðäünM?Ðû¦þ­^ü6]üZ/>Níœ4ím`°kŸ^=·‚" ÌæØÏ;‹+³|#hi{^Âg^ ù”ŽÙæ{ø?5t²ÀaÅ©eBþGlõ­ÁÄe
ç©v¿úÒC2ù¤zˆ©ãíBÏ…}'MœXEË<_éE£§«4Ï/õþ“tÿX/¥‹ŸëÅoÒÅ/yNóæ3¥‹QCô»YCùø}ƒ¹z”
/§¶wKìàHù+?ìÜKØéõ‘§@V~²Š€ºª‰?+‹‰¢þÄub%cÀ‘ '³{[Cî›Z÷IÚo³Ù‰¡š2Ó£ý'Ž9N}_Ò#YéoÅ‘mè@WŽÁv«g›îi»ž¿ÊpF£@DôÌãÍqcB4é³ÿ§R·Ár?TW1f‰z޲
Ïͱ/ùmŽÑüÆËQ‘Q¾aœûéãĤ:Í|¾xÚ~]E]ÉC4«<ýä^ð&/øµº=èæ@46äÇÞJçâ&s¿±Äåù€Ú-aiLnàÓìqTOó‡Õ™#%Ęj¼ð÷i¤lÁòiú“\ͼ¢lÖ¹aض5sfÜ›³ª+”¯ÅÈjÅœu¡ô¢Ÿ×–˜ëlFBÌý¹Øœ"_QPÜ£û£ÿFüöÛé†7Û«piAÌfZÛBâ#$,ÿÉ7nUè—5d\Õ‘ñ¸Tÿ#íð=geŒ}’-ÎôððV.2	T\‹sý)°ìwxhê~˜ij›šùI¨njJùqëÊßYzÍþɇ¼öfLY…×5í]åafÜG‚Ÿ.JH¾[Ûûjv㢶5W½»bß;`Â"–,6ùuUqJ†ƒ…ÞɾrͪB)m›çK›6f…ïߦ|Ëe*ܳ1sûòøÎÇ?ÿOºúŒendstream
endobj
750 0 obj
5432
endobj
754 0 obj
<>
stream
xœ½\YoÇ~'ô#çÁ»†v2}Ìå 9œ‰ƒÄò`‰ÌË<$ñß§Îîê™Þå!ÙHîöôUU_ÝS¥ŸöÛÆí·øOþŸïýúßÃþéÍ^»º÷Óž£‡ûòçø|ÿ÷Ð!8hi¦vrûoöx¤ÛüþbÓúýƒó½ïWnÝ­ZøiÖ~5ÒßÍØº¦uÝê¯ë_ýcV¿[‡®iÛ¾[ý¾}³Þ„àû°ún½éñ»_ýa½‰«üE£þ‰Ÿ¾]ûWƒ8o7;×ô#ìåàDÖð3­;î<î»Ø„Ø{컑ΛÐ6ƒ›&ãšnˆ.ÂÎéS7àþ›ÎµÓTlœ=€{iïÇ6Œ«ó5p¯Ÿ‚V‡Ð7´Ñ¯NÓD¯¨ÑQ‰‚ÇÑÇ	Z}3ônWÇ0i3xp0ߥ5/i¢nŒ«íúX£=‘ñ÷½ƒ¯¾Ænbœˆ•ïaœpu½Þàau‡Ì=Öœa¯±™¦°zmgÐöA(Øv¼Ž°~+û¾™ÆÎÓhˆÓ]àý+¹v²¯|¡ÌÍóЯa2œ¦ÀÎŽæ¡9NáÃ.­Ð?ö°âW7ÈieÔåˆ×òÞ>YL»âÃzúøw‰!²pì(&áy“Ì—Ó5²ØOÀÀ¨pzMsÑ\k6	ì+»ûÌ@Ún¶ðwûîIȼ’	;ÇT§Î¹Kžày2ÀZcbóáDø<²¬®ìFtpî]N(ãŽD¾au¯ÛDú7€M×£Z#nPi•Äwä ð—‡W "CÑó¥ˆ:ÑMÔFØ0ñNº¨è@;IWŠ9ä'­¶VÜp·Ö…Õ+E‚AI<ÕnùšpŽ'‰Y?¬yŸÈ#V—«žèê™,½DºH†±¥ÆÊÚ[¤‰n[ÃÔ„^±u‰ëŒ8|$äÜÄ8àÉÒ–ß
àâ…]À—	ùWrŽëâ¶&ƒ¹·,"&†-‰Ôœf€b¯Ö$ôNõ	wB}êÌÖ¶ÞáÁ«›FfÙ÷‰ïæ
DUÇKÁ¸–àÀN"f³‰æôÑwVÌJX×\k„I§lqÅdð„…dÀš¢:t(6
žü§"– ^&!ê뵯΄cˆÂ6zÀÜ›´K3°eìn$`J»n6iŠðHJ:‘ân+²²Þ[sáIr
©»Ôˆ|r5Öq±£š.pŠ¡ÝnHÀÞEzHB$·ðè·8–£‡q9£hï	&¥ûÉ'ÌÒÜô‹ü™q<¸Ø	vv´	E­kÓ×[Þ?Z8a9YhøJ0@¾k—¶·â_êÃÖ0Z™¶‰ž.Y¸nÛ…	9Ép·‘H¬ãTýæ8:…¢÷µE}P&c7§ÉDs!#D}Øa·Œã#QµýV9±ê,OXt¸™«Ô(»G©ŒÎf nø¥ÂOxP7ãIuI ")cdS¤Œ'§¹€Z'3s¨a®•ëWÙÇ"$8ò	ú²%"a÷Á¾¥•;µqÉàòJó©E5ÀN±'þ©Ç
†O“¯Ç`lBÉPõ-ɰtÂÈèÐb­P;U–Ž3ÜŠjˆÁ;)¤Yêàô^z~ˆš3á9Ƴ<Ùš'E¯ErÆ+âW?&[ú’œ(Î/áéWkþ«¸zËL`‚®d;}Ú<ÕÂÒ–íÉÖÙGT& qx‰_9P~À—F7-Â:8ñPÜr`.ÎVéÊèOQŽË£)Ò°Ý.bëEl¥†è%zò„Hš´!dâF·Á\…©
U"<9×øt„Äó‘chJ;ÜfO˜¥=Ñè:)ù€äuŸªÈœ
DÉDga™úmö–¼ô㼩ì‚Å—vªj{Ââð£&cfv\Gè‘­@WÚ7o

&C,è䄍ޝóÎÜNøÁ=óUn˜}³˜UŸ›³£¥¾‹ Þf™ÇÉ¿.ãu ’ã’´vÚˆ@ ˜|!²àQ÷)à%àÊ)lŒ×3ºl$8ˆdƒ —¸4û×zý؇âÔ5q”¨™’!=×c';Íwø õŽ,j}€ £Vß§ž5`=øÕá/úêS›OýÐó ½jD:$&áuvFm¬ö̯0¶áhj|i)0¥³vŠ ú¥eä[¹gÛtrÜΓvyPŸ?Ö–/{Æi p•ž¿ËÏ?šcvj>wèDÆØËÏ g>žZJP´ýQ ª„Ö1òé'c@¢J[ÉÝ&iR—Se¡åÛa‘〦fÒÆ§`äç'ùùEz~—ŸçK‡£š„®k8'ÄÇæ&À2r×"¹ñg‰åpŒ¨ .³ì–$&‚ÌJO1F»É­x`©ã. îÈ8Òp kXÉI=óD¤n²àÚÓCl³§­þ|a\áÏY•Ûà׫r2}•ÙM¾-¨òüª€€ÄÏ2dEظ ^פ÷¬é9®y—ÓÉCo ³P±¥—ÙØ^䨵uæMY¡ƒ&à4o++.3KúZ%·$ÍãO£?÷)ȸÍܦ¥÷ëœÁ†{åñ©xâ}˜G2õ}÷øƒ”‰ú5?œ»£äG5Îå · »z²ú¤Û¨wÖØ±]÷æmÙaÆ\í¸·í¼o†ÝÎPÙç—pzצv#‹èä>ÎP ZU&À:©Ùˆ5N¾®)dõdZ„Êj¡žÅèÏpÃð9íwį¿É× »N52ï®Ì jÑk}n}•[‹‹ï¥æ™Úüøåƒc´±µKFÊì­ßyÄH¾²\ºõÏyBÚåû¦OQSýøSÞ†¨-ÏG¬Yí·YÃ\». [µi§ý—ÀŒÌl›Uôj]ž¦¶“LÌ»+|:ª±¬P)£«G–óÚêOQmÃ{ilİ:ÊTß©Úy¦ëÚB§µÆ‹N*ä³BœxÆÝyÛ ²¹NŠ£’ä>'öÞ¥ÖîœvQWUõR4Üú,ùô»ùåny—o|– Èý’Áþ¾Ö+k¬ñg5±ªXòk#²ºùîé\¹kоݕ™K.–ï‘LY9ö=ëØk„½ý¹%½Ø»_ÀQ±Ì«'6!6&½¾MÖð¿ëXäëyÌ¿5 š”?­%yŠS¾ËNÅKùÃ2-?%ø.¥«xÉíÛž²âûö±U~tš1ê{~£ñ"åÛHfì™èÊŒeI³Pþñoʾ§¼ÞåPv1Ûåï)[üPrb¾7×ÄÕ b[x‚æ[zb“§læLSËOA#:´[S"§´ïHM0˜>)5)¦ìã Ç©+%Ts;0zædê”é£7W)oã¶.gèD[ÂbûDO.×E¶U”lnâô_`í?&þSN`êö˜ØªIœËä_Éšz1OæéÙ?ääÑ”GÍlˆüŒûU† mI§*Š(úœgT«sàôÑN36}L¨Ã|¹;â~N ÑôÀœ>g '0#.T­yO<©¢JÓÙ3(— B\΄4A+c<'émË’M"W$}ˆœqEÑ̲ìf¨gøI•àâS:ªK©UaHU_Z ðQª©KT4ˆäßÜVXªgñ š´ ¼TâÏËjû†R_€o8ô ê¶áe à(¡µŸZ,¿Sp,q.ÆøÒZÃB§úq¡OŒÁ™>ÎYô@yÍ#‹ :öz9‘Kì¦Nó!§†æìpMHgŠË+ž¢n@ªàÎ%É€Õ¬aI­åÍÛAT—‰ÁtÎá‹-…IÞÁE÷’HN.õ­®‡lÅ[CïwL&ii¯ ŸK¥$8³Ä5¨0ã°Õ…3'ØÚŒMLÖæ¨°Íc/{¯c`âT¹Cañ¸oÜlö?ì¤+>ˆEâÌ<³Š¯SË!Ã?Ô*±´¢Jí ‘5¿‚a8Ʊ`¤8ôSë× ï.‹"{d…Ç„ 1¸”¡…9”«$$¯Óô-,kñ²Jx'Š«=ªµ«d\ˆ‘z¤ÐsÝÙ‹’jûP¬p’BÈ-išš8 ±i›9]ì2•,Ê/\N|ŽEak%ÀQ{ñ¬‡O»ž°ò­<µudó¦zeNÜt áüÌ,m‰¯SdÅIZp§e{ZШg=„DqRéþPLÅÜå°à$Š”áopm$_?²–'ÃÓcᢘMBF4©K‚ßEeÁ ^úൔ™ÉmÅ|çâÏzó‚íÇu`#M#? gNª—·€”ai… û¤xc›¡r\¨P+´B2ªáT*ÕêRXâÜï\å¡J?ñjý– es:*²÷åŒö’5W‰OÛêËèùžy„Ê•²ÅSÑö¤yFUj®D媹²ðÈÕ‚i×}"H$$3¼~äŠ-M~^ ÚÔ{I %ãÃì~ýGµJç°£ž2¸A.FM%Èó„.e#O´XZOQ‹P(ªÕ"ly+–ÎO£¡”!ž-Pâ,1Ú3—¯XP²!…•’þÍÁÞ¿àßÿÍ×_Íendstream endobj 755 0 obj 4198 endobj 759 0 obj <> stream xœµ[[sÅ~wøªâÁ»ÀYvn{¡*I‘N‡`¥Jü K¶L°-Û’ŠÿžéÛLÏîì‘ ¡(ŽöÌôôt÷tÝÓûê ïÌAÿñ¿'Ïo}úÍxpvq«?8»õê–ÁøŸ“ç9ŒŒOº¹ŸÍÁá“[4ÓŒö`t¾ëíÁáó[ß5¦ ÿ÷mxxø·8Ë™bÖîj ¡9Gª!nŒ ˜1®¾sÃØMƒ‰bܹ(°ÑÍÈ´™lóŒØ7¶¹ùx7¹È“íÆÁÌ“¢£–$q•6ÅdÝ<~uëð#6—¨6RjAþX"'Csµ}ÜâÞÜÔã×—0î%iÍô0ؼ‹?!>âÈ70ê¨=nq»¡ÙE®£EMø\Œ+r3˜£Ã°^Ü{óL‡§ÀË R’ÉÀÃ%Z’1ÍS·5ˆÉ&žÁZñ|E¦Ÿ€¨q2ú>`X1ïÐb1rP¬eh,òxÎúÅ?ŽI•^t£èÐó=Í÷˜ƒÚ’ºp "¶™|Iè‘ÆÝ´µ{Ù¯•Çh‚¥î1?¦DÅy½s¶7"c…IíìDZ=…‘ ×IVeºdTÒi|Gk¬Ì(1àé¼e÷òv4ÏÁXZ´À;̦€ŸÝûãX׊ï.bÐîX±Ið°yk‚>Ú™ìb8E)ƒ®“•‹ÀÁ{f…=Oνb$Ö4OD=èD*Ö‚ÃÓ‘se¯í‘g£ŠNU¼²†¦ª˜çS<]… k‡´õÉÐÙÃDR#ZÅ]T¥b³(sÓÚ`‹ÈyQk$ã-|TüyDU¯;ž_ÊÀWýljŠ5$je…s±ž©øZ„ŽTòJE¯)E¯¥¿i ÃmÈÂåìô“ä>ÛÐüØ:‚"`¸x¡Gñbà»Ä€‚zT8ËòðÃÙ0=„ ¹xÂ=ºþsB*PÀb7‚>m· ¶‹Z‘¯ ÄoI<¿…mEç’O¿‚V–AÞa#Y®‹á° Cèˆö…&7ÆõÐɨ)yW8kƤ0³f]:¾ƒïc€ :G¹¤Â‹@’ùJØÈ´½½`ŇÂù m‘ì €VùCIº''L ´×Á‹\ ?'ƒ$Y­o´) õÀ8+]ˆÿ¿­/Ï· ¬táóˆXjÎ3=õB­8èK7ì0¼‡=QÊ# Sj.‚ïÛ$Ò¨S‹ô²¶ýõ¦h%¯F>-l0³€IþýUþýMüëyªî)äžS­¬[ÑC~ø$‹ô½Ô¨¬D龯u¡H6ökBÙôÇdÓˆoáJ¯X&n Öª›»ÁNnaçÇiäiæÇ|­ÞÖ‘-ÿÍzÒ´!ÒëVú6ýþEþ½Ø¤<ü:=<Ì ÿ±Ì‡øë»¬‡ŸÊ”;’½‘v\ó'ö/²ƒ?g‘?#'?5&qŒîhq˜Äw|–çïÒ„938×ÎùÃì”Êø5øUéý „'eö.€gƒ5§3™¨Ikò—5ž^ê3£é&¿–UäÓñ"{§ä=¡*òËç_P"Êd?u¹Þ?€ýšxTÛõ…Þµ¸ŸÂ²„ÑgUS?Ëgá“•#Êr~¶µ"‹æ¢&üËÌûïbeüG£v…²3ãØ1°Hfñ/Õ°ö g%#èøL×ö‹›zDÊGñÿÛ0Òh(nC®{ib ´å*'ƒ5A±ê«®{ óº*RÀ#*‰fG5êe*wQ¹•<Ãñ[—µ"§€¤ß$&T‰ TX¤Ð0w&Õ)_J9w ãÁ²ËåþÚ­Š¬º_5‰ƒŸ¡" HV¥f|‰‘seOÉ‹.6)”(ÕŒ+]ÛQ‹Šù²Lªsä‘ (“õ… $|†A6,àKHñ“S=ï<ûO›k–”½½Tbfgʲ¦JC’|çç‹›4ÆõÞPéZ®uN ùCƒy L„ºr½¡ª»$¢Ö‹õ—†åU‰j£FaUEömÎ(FKÁ¦ô¶c&ä¼(ÿÑŠX6 Rñ«*q¼É:®UCË<ŸULdBJ%±Ôeð>Cºö™.IÀoÞO;ËR‚¥ôÏ;ɉªzp^°[Õ¦äv/PáÔ2Ëüqy;W“¸ä½I)¥Œ’]zÏ z«Ž)CLq›ÒÕ9<ß(º k{®cØ}Èî/`¼wT°‰¿¥Â2ú°Ùn`ƒ¢’ü+𹺞 ÉÚpa.3ü¡ZCvæAÛaq;C©µw8hÃŒHV_ rÙÞrý·b¹tÖêEõ“6¿Me5¼nr}(G„nòm”5Ë¢¼. ÑÍãtg˜k X1S¶#ÆEí2\<ãNLÛ õûÙENÙµ‘T*שz‹)OÈ6N©dJ!ßÚ‰ù„`ù*ªè15±J}hi§Ù ¤›¼Eš/[]”ä‹ÛuµV³žs£uB.ßóê“/V§Ë#â)UÑ-.œ³‘³…Î.ªžEÏî³Z±§¸¢Ü)‡·rªÎK_™e©¯ˆ•ãZ›_nÝDcÎÓU_¹ºP5Äò¦.Tb&^îÇÛ ‹evt~˜]ÇmІ1lé¦g!å‚"ßçÒèâBwÂs7aêʽB'j ‚y6=,nÊ&)­Ÿí‰<¢èŸ‘S‡üGeB!ñQX¸€¿R&¬¾ê¾™ÍvŸÍp‚1ÓC‡ Z´Ë*6ü¨R¿¾qÖŸ€Çj“ïù°Dî·º“l=ÚŒp÷šÃö‡˜kx[¹ªVº©2ÖyA^P,ex©‡7'mñq/3iXs¦~[Ÿï½-¾ÛΦ8¿ÎS[ÖÓ‹¦!NKÉÚôÈ—€ ím~†œÕBFßü’ [çÔ÷Š å&ð1×™„á_A°!ö)QpéLJûÓåb[IgéÒˆ®’b’ã¾\@Ø8ÀÔs iÓª'‹ã>Ï4õ ~®9`Kž_1˜l¦ J²ä²¸`ìo0«>0†v2 < [-!£Y ºÎÁ<Ä5$<ö9’—Ò#õX”¤VEòqì|ÓÆAäº3Åd@ñ6×BÆ®ìØWÌ$žPgàì‹|«HjT2sF=Ð;‘Áõ~@a7aGñyʇ£EeÈȉ,¥6Dé‡HÃŽš^wf•ÍFØ h/4ÕàÁÞ»v‰Ö ÷¨¶òê]õNÐVÚQŽ ÒËäcÙÓÈ‚"N¯úï°tú1Ã.ör‰û®»AèLwÀµ¢HÑ®ú˜ ú¬Ë$ê8GÌð4;kn-Á›ü1ÀÎæÏ} [!‡=®+ëpHéSÃaòºBÅ ¡@—ÔN&[”C`È@‰oê¿Ñ8Ñ«®ˆE…Çpn)e-î‡Å3ý(¡ð¾r\åö~¬É4¢*€¦[o.‘³,»¾Öd»­ \çâ0ŠKÄ}“JzáÜ+Ž&5…%'9ö…u Ð6†NMpJò—þ†~K©ÉËBë 7 %NÕ||ÞÊç=øxÀà­ŸGti|­}µºèΗA?ç¨úazx??ü<=<Ê磊4¨®cÏ™ìïŒÝhõN¿s#o PÅpZçÎñ>O#ïï Ùx µUXíæk²Y¤^O½FÝaǵ´0uÕJþrwCÀ2肉¨æ÷ôÍ Ú¼àhÍãIâ7…„¶b*y›]õe¡ž>R ÒScòßÉëå²Â°ï¶ªxK‚6»®¥ŠÇv±ÃÎ.—ÎÖÂrýDâ픣“NMªoü w!(TvöfqC´¿ƒß0)/k’3ru¨n½™#7­ÐBžboRNÑ¥WýÍÒ/?™T6ØBÙX[ŸçüB^Y.Ä zX¾§Á`j†õ;6oS•ßlŒ”)”-ò%±}ÇÝ þòÖKÈò“RžÏàÓ¥º¿à[–½ÅÕKxŒ© zKFüWmªÁª§Õ£‰´¥ËK/Øõ["Õ»¸Î)ú+Y¾¾Z¿áÊ×Tö¼Å£d!µU¯«ùìå°l´2‚Š®ïcä‹àÔDAWzŽŠx«ú>~‘. W¾YBàŸÂ›·¥m/[DáëÂü„o+rPBÂFäáýôðóüð(=,"»ül¤ŠãR¥l¸»H±±Â¿/J†?‹¾›ª¨ŽJëï—2/§¤ì~;^’~ŸªP¹ÑhÁýÿ´!Vœ‚l¯&Iªorsѧ™¡­n9¥€/oý3þ÷?¸ª¾endstream endobj 760 0 obj 4385 endobj 764 0 obj <> stream xœí\ëoGÿ"ñ/XâCî¢ÜíÎcƒ„D --´#@i%œ81'Γ6ÿ=sžsfwÖ”/(²}ïî<Ïœó;ÏÉË“¡w'ü㿟Ýùà«ùäâõáäâÎË;_žðŸÇÏN>:Í ‚ËOú4$wrúôõt'³?™CìrúìÎÃëÆÃúΛÏÇepýàÆÃ/»c<ü~}Þ]ŸÒÓá¹í]8|Ùƒ_°Ý‡ùÑ—ùçWùQ˜r»pø-ôú¸;úÃ_ò‹?uaî‡ažh´¯òhÔ8?uñðIçaðe:|Væù¼[&êsªc厼v~¦4ë¯a zЧÃïáÅÇe ܶþ¤ yDçè>ÿ°KCîšÇ;Õf¸Æ/;îÿÍéo29·äŒ£ë§%Sôôœ©óOþ üö†~v)Q#ùi^j }Ê;}“Iø7XîxFËß/ó–¾=éâá ^&¤èužáG¯axñ&¿Ž_± _žÃ0çùlvX¯¡mÄ“z”?&¢*´|×K—gl÷F(U/q<܅ﯺãxÀ¥¼aÚ#ó f¢®ò6Î:l&§Líaºi§Ÿ?‡¯“Pª½–ËȆ|.““Ãx–—ÅÌÓ_äþ~î6ûz¬üÉû2 ƒã‘¾oóóÇyÆ¥pÓÇ]„ÞÖ$ a±LÁ0Òº¾ÍüÃíàíþä·ÀhxBüòŸÝ¼q¡Ðê­ÎOÊOè°‡!š‡×Ìm²ÿ£ ý8d`¨ÂH‚»ú¾ác ÊS.z|qD¢ƒ`¤§Œ¿2FÀ|.õyŠÏïœþôa–§ä€™¤s h„_ó9¯Ò2Ð'5:‹Š'¢(/åaÅÕÑEd™Âp lðåOØ7SÚ Xó&_ñw>(¤QɃtŽ¡âH\-o†ClŠûE&ÓBÛÞ ®‰D"‘‰·à™In!6•s„½2Vœ,‹ÌÊiåùŠSðŒ…'Gœu™>÷› <Ñö ÁîÇĺ•õ '@Çš¹…!éP/h$PÛ)˜¯—~™“ð×; [^3ªÛP:¹@ G¨|/Ïö0ÿ¼Ð¢sƒÃ/ SÞ-ÜÃbÍ/žWfˆ[šôŽ,ϾÉ-`%Ù™A9¤›¹ÿßÊÜ:(ã m¹ÆAÕÂÕSØ£ à´›jµúBU<ùðò>FŽñ‘+/G®úvð8ÙuGLÈJ!xáŠàa©Õ|$Þ¨˜ç’ÏJ¤À§€ä‚¯ e²è”tÁ k ˆç—üMÑÈ Zcœ ç3à79§ûàªô°çžywƱ>$b‹ðtÂW본”HŠ}ÀÞ?Z‘kŸ…ÑÒÖl|EŠïÈDª!l LD¯P“_\ DÄy¹íˆÇµ2Ê@]­È a‡ðÉãÖ}i‚,Ù0º¤užçqtªÉw±¡Ár€ýÆÃ×y ²ùAî?ðù뎄DÊFOãÖî$‚$’¼ aÂAjbÖï"bá… •¾&[æÑòUkvg¬-£î ?œÂU*N 9×!t5ÁX‰bÑä¯!Ä6’&µZf³T–Ë$©!ÍêŸ9â¬ðQ¥ÚÉÌðb3Ì·Ð`*ÍÅP|Z›Ook#f¸½âÆF?/L®0;’º|Ljšá.· ¸Ì!¢Jcdò Õbxt ÅÂåå,× OÓ\+Q÷Slø+¸GâhbD<öi¡R"¢ÄÀ!*RtÚ æŽ0£qŽ˜ÕÀí1µŒô¦…=Mj˰Åõ¬&0’H¸Ë<Û¯a4RÙ €ò/’ÊÚçâ3þHñ‰Ti1Å0¢ mߟ9hñH‡zÒþŒì1+[ÁÉ“e «õ#{3GÏ*ý|%"ŠzªkàÚÚ–FÀWÞ°§÷Ä ›¬@ß»I8í ’ÿ ñ-˜ÈÇJýórä?#°øà«)ØðÇÑOs¿ä3Ì:<).}òäù×wð+óÐd>ñ#Pã°À«#¿§æBƒã8,| ù œž¨Pæè‡’búT²+/*¢1#²b‚¾/ÃUéÉ+ýH~VZžêÃß—‡ŸéÃ?ÃD[?Ï{g îߣßú€ÝÉu^ë²"V^ÊÁÁã©¢–®?µhBüþ|K-^äEëá+&Ì2ÿ¨Éœãôý¤˜°¤›„ýû†°ûÿV ô½¯Û æ«ÿœšˆðWóÒæ¬Ú£§øƒï1ïtÔ÷¡tòVè$<ß…<þ¯“°5ÒBI¸½CìDÕkåó!Ûhèî籩¡ –nQÆ‘¨yƒ};ö5ŒM\¯ƒ Y(|ÿSL€ˆ1õGIàŠÆ½#ñê8~½µê‚¶ÙwG}Ž~?_¡ŽyIë:º­[yôžl‰´ª©@& ¦iêã ‘tëtšu^3ÉpIœ›`Ï2S¡¸à쨉)!†5æ¬;Ź=/>’Ï]ÊÛ’ dÚ×H¬ª¿»0þ}é^GÜÕÓgBÔ6ê'ùÐ1‹ƒ™¢èðÕ¾ÕýÊA˜,g©ñm XíxH¡Å̬––bñ"Wsp \‚šj䣮Éø×Ý–Óˆieù>UVÝc_öB*óÌxàiqƒËb%€{#ïygeE´Ÿ(Ò•‚Ë¡õê]òm¢R°êe@S×aôÁ¸¡ ý–ÈX̽ uj~_"Ò6›ÌH›¼Q§FLè%V&4Å+&ˆ›Xÿ²xMÅ̦ð%ï¶öõÕ/ºbù†@a‘Ìç…ÁÀ‰RÛÂVˆ¾—Øß ÝP§,ÄOÀpã®û4…Ú}½uŸ¾¯Û3B(‰A¸r…y1œeš6)F»­‚Í/¬Lþ¬ky0yÓž•ÈDŸ©ãñ´vNPéÂV`]æ-ªGŒ’Zc ¾‘g ŠÛeƒ6% j½Ö‡/+[²øFò0³“Ѩú´Ó§ßܨ<í¾‹òlkTýlaŽwœèœˆ¥6ø˜³pHLõ¯A4ÎÛ€)§ÌDW5²-gQ“êŒdͬS‡s­£]w ì›Øm@–?’öWÈÃn=¥ ŽË®¶3 ¦Ø¢c·‚LÓÐV²¸ÀD4Ó‹#òr\˜¿ì†~ s@c_f ^i‡·°ù¬³3G>Ë-Ý”‚Çv˜—~!Žœß™^èMpÓs~çÃoó ³°8Â÷óäº?C¿,Á{úA X6…yúqAœÏÇ6ºY sFë#A —ç/ e;zˆí"™§Œs©íh•@Ì”l» Œhín"(ûeíHa¤eÓh&¿[:™÷DæÜ!z’&îRöø\;·”cä9U©‘¶†…]2ÿk¨y ×¥Á¢aÚ+²‘$\˜f\5HtÍHåû¨yuž*54÷ÔBÌ!V&@]eæz.¥"ÍØOâ𕞭.“ã̇µKeVËdÇCsÔù~¿ Ç–(0Ej½¨.™zRRâ=âa3`¿bSêÕU©(~ªÈY*°Œ~Ü„+òCðR[gH)Lží~ÎPál)­yEàs“VÖºœ¹múäå6j[ü¸ªÂP““âTP5™šLXšv|[ÞëÌ•z,…9¶6”Ô@ERRÈkì¥JÕA.‹®©J cB °O&G»ÆåÒV¼ÅZ Zdhƒ¨]ï>P R4êSPÀsÉÒ¬+aÙQ2u§ùô¯ë29û™lOaÎQŠ–n±Á"—V>R. ¢dKg’ZÊ;Àó¨öº…±ïHÁJ’¹,”jPÁª&¬±S2)0µ£[3ΣÅ è´J™Êg›‡7,ÃEÝ °”Šu:·UDc†±ñ.!A Lló’qNA‡šì–Ÿ×Bq“ù€¥$é4¶¥|û¨3ÉYb±U¥ŒDHzOÀŽ~ªcU‘º ,E•:,U" §†Q¤Èb͉©–d¿”‡4µá/ºß+éôdïkºmÁ '¿÷^çW•)P^0Î%p¸ÑvØ9%aYûÅ´¹¶8©±ÓMz_ükú¥åÇ—T:=O̼Sr`/øå—b:¿¡ÎÞs.Yªñسi9Šì aŒi]{y!Ð!åk ÔÖNÙ-ÂØX†6Æ!Nå‰%-…ZúÉVBiµØÔªâb /µR\ŽðHÝy¥H»\®Z„ÑY$ç7ÖÊmŽLPߨ›.[AŠë:_p_«î€52U5`¥ ”æ,ÁÚT~qu¡ÒìˆK¯iÜC©çܘü0É€å ¬ë,d ÝÉ„T»{µ¨®l ‹ewVÜrKÀ"–K¸cµgøêÒHë–ÕæZ䇂 Š|'‘*¾i3§Þ—hC}U2VÑ\Þ]¬·Ž–=°«=Zu2›+[è¹|Ï(UX3QD†Û¨ŸE#•Œ£¹ð´)®(–±$m{B ‚°µèø*3~7 i©åžTÅå‹®µËJé¿ç‡Wž¼^A ˆYüY¾í·Bp.ÄØ‹Þ3ŒTØÅµn¸–Ȉ®ôY±üv¯e×Ýö W¤>}TE­,Ë-wnoðñ°A‹ "_t+ÿBPó M¶gç)™É:ÙÜw tãmNî±ÖÕ´ÛYÞ¥ɶ&L܉թûéÖÈ›„ILPÀ\r‹ªS=htu±Ý*œ¬½þ°uR£²Ë2¶Ã]"£æú·œÅÊ•~M#Iýœ¹©¾âsÓf;²IèÌE+¸•G_²½ÎuÝLÖQ› ?¦øë<"|„Už ÿ›‰â&¢{šÛÊ2Ñ%’4¼W@Bt¬ÑÌVÿßB"ê‹åË—@[Ðejäã¦mö­Ùn™kë.B{…lßδû– -¦~V´Ø+ü |ƒªbU÷P'?bpwïV1R 8ÍÐÔïRsÜ„U÷3•UPwS«4 Uò„.žÃr$i ŠJ+qaÊs¹¾É[Àn‡¹ñ¾g °®E\Î’x‡ÒÔ£“«Ž·Ëm‹a£ðörË˸IXóBÿcÈŸºâßКUY²‚¥‚Ò1ÓÚh-¯’$­Œñ ç_Óz0Ìö.ÀÑû´> 5¤vt­ŠTÎùøôÎò¿‹pÇendstream endobj 765 0 obj 4845 endobj 769 0 obj <> stream xœµ\Y·v~W Ü¿0AÔ¸;Å¥¶~pb–aûÞkOvF3’,XÒÈÖâ;ùõáYyÈbu·¼@Ô]Ud‘‡‡ßùÎÂþù¢?¸‹þðÿ×/îýÛ×ÓÅÓ×÷ú‹§÷~¾çðæÿwýââ?.ÓΧ+‡¥_ÜÅå“{ÔÒ]Lþb ñÐû‹Ë÷¾ß¹nØÅô×wÃÿ^~žZW´Z–Ã0¦†—7éáÿìöq÷YçË2Çe÷qçwëö~w ×t{¹ñu·¾?ô.bÿ}ú{Hw}téš}ð[íKºð»¯R¯ŸtüåèiHÏÄݧ]8ô}q÷î|ÿ¤gBô‡e^° èK} nèÜ}ÓíÇtÕûÝwOï°Áe7Glõmçiú¥Ðönò‡à/ö¡?LI$†g©ÁË4^ŸÄØÏ»7]Øý˜^°{œ®õéínØ]§ ܦi?O¾…{/Ò`ÒÓÎQˆà㸻Jå»SÃ×é ·ào:¾~ ׊4=ìAj3µÕG®»0&Q F#ƒ{ÑùÔÓ¥o&E2Íx8ãîCØŒ‹L²ÐŽo•Á]ñÀžÃ¥yõ,*Gz«ïU9êéÐZWsR ‰y$Ì©X|~ò±àvŠ -žf‚›ÓäyÀéé))àTéß#í%C:KÊÂÓ@e–™f£;¦_p§¼±‡iÂÔWÛI”Z>£}Ž×î ñ„¢?¹PaéqgéÈ4âêÿ Ðý¬óºn³GìàÀ^A¿ø†+fg„Y„¹_CFºˆ½|a Äæçñàeé¡K=àÑÉEà®w?ìô1ÈÁ®~ûð<znèˆ<œÆÚ;¸Üý<`„ Te6jxK(/æÞò§U3Ôš{ .‚a@i¯CÀ%¨‘-„‰'lT íÊxžR@U®?¶á¬dôä°ö»¿2 Oó °¯ÃycŒ œ¨MIÝU'V%ÞùÕxeMJ“òTËá¨ë¥,v½Q¢Öï~èôþ!Ó‘¾à#¡w‡/ö‰]Ís÷_„»UŒ/}γû„¥SÀ)lj÷l25$âãf g=éëî§.¨Üþ ÄC ,Šö†Uaûk׌ò©d"Å•ÜÌa«C£áC ÅjþWÅ1lŠ£Ü%øÊÁ’ hi÷>­gÂͰûç6Hú9(øx"ŒŸ¡'q?}ݧ§‘æ#]üRÇcüûð\Ô•UIך¯4 'ÈUj…ûâ½|ü‹é¤¥ó#™Æ?š¦wz$À »¤¾d¨†CœEtPF·än»Š±0 ƒEÜáèi®èÔ²Åiäöeîãan_, Ìt?íjp0£¹Sµã]>Çb— ¢1ŒíY¥åú˜ÿâÔ5Àöø(ÿ4«¸aÇÌ#ŠK÷/ —aÀxý¥µ#QN±óŒÚ¨<³îÒQ}ñ„›|!"rBQ„{`ßvøË™ÈÈÌKõÞŽKn–cÍÊzxÑ’GÖ¼„ÌNZ RéSV"qø†…¬ûW !Ö¢¥A¢kÝÔ=B |^~”N1;¦aÇè‚xÂÜBïQh¯J_,‰ú†°…ÌY P$@·û„`rGHÒ42Ãf²Û9³\¡[ìÈ&ÿ/ v€øŒ¾%\Kž;ðóÈ”K>\×,ï ´R\Ä á–%X5͈¤Ï2yNT4d5©¦ô–é‘ôÆ{H¥ 0›Öë”þ9SˆÊTf)«*¼ ‰y&¥/[=«dŠä9úð¬×ÄY¥ý¡‚}Q«MƒÝTÐçÉ1%¨!â‹wqËüDô0'#çÄ¿ão°®cvôcÈ)8´©Ùõ°T¯=‡ïŒsƒmœ™ã#‘[9ý»Ò Š6'q¡´L9–ƒrùQœ>YÁÛÜyŽ©>Šå»6.ø¿Mh{ï0ÿ>¦Mçe» ¬}KBå½ãÛÚC¬C¨͠ĢÊó2 Îûcò¨`%ÄÛäöÂ×÷þ½xý× yŽ¢äh¢ÜPQGKTö^Aóe6£O;Öè9ŠÆ½¯ÀÁž¶­kÙí¾ÓNeÔÔÇa¦ÿÈý>.¾Å3|ãWj8H?‡ƒ9¤Ž)†ˆ>Ê$é#èûÙý5_¡¶ó•±G vYŸîc„aÁ½Nä^Èȯ0ÆBDçEl¬ˆ8TÐÃÈ„a||nÎ a€ŠzÖÜH¶•Ë-ÄQQÏ·cÝVGÉ‚òàÎR–H±«¶²°?Ù"Fàçgº×`BžÚš=A\*ùÖÑÀÕÊe6´å¢'E™Æ÷ÝÅK,žÙŠbÞÔ7‰î‘wÄ`V ¤ü&A­sªP1FltÎ Ä@ÛµHF„u 7½c(÷⣜]×p?¡æÌw d7¸«kkg‹¬Æc|@‚ò쉀/®cÚj9u±¼¸ %• î;ãÙ¤›#nÌ sB©‘©¯Ó%pLj·<ý¡^iSn%dZQÙÑÄÅÉ(ϸ'qãª0žcƒ0Ã2Î$^Ùësß2ê¡´h79™P,Ùø>’zÞqœ1è»”uH`w˜që¾*XmfY­ N¬)(î¶ÙfϘsQ5\Í›<ï´µŠ±¸WÓÛ 6¹†1!þ§üžÇDRØáçõüY½§·uR€@hÊŽ%̃àeM‚q$}ÅŽÙÆ‰•%S™8 ä¨iø™ HÚüKéÈcÒ&uƒêšò1g˜eâÒâá°p`‹CNÖŠ´õñëç ϤCË¢wµxP·XY?)ü¥4<Òµ¸f ȵ/Ê\týÅjgTiÃ`ñ¬e+z)ùç¯e޳Ê^VóC ô¬*fƒpÃøF«rœˆ2T)ƒ3ʹJ$›áÅ X?.œ7á/´;ÝFÈÔ¯·:“\ìwb´yeuîÃPÊ É`W×-L~ÐØdßCŠI·â)²¨ÅöÖˆP—àÖ´4ŽüúíðLÉ•S—D*\"Íáê³(ŸwEÕÆmæ(ÕÆ&åÈxß´p¦`»RëÉJšd, ©”Q¶Ò™¯r¿¦ʰì 0V¡†¬38É’ËœanD›8>覃ÇB/î]þë÷»ÿéba„üB‰ˆVü«–÷˜b¥ì#{Ã6èÓ>' 7riF£V‚‹(Îé³]qµpûhâ r£€¤¥šø©ÆîV⊂÷Ñp™â#­¾ƒ‹ ›ûÅŠ­J g¤1q“ü¬£7ò zÿ’ãýÌû°ê¥×ÄËJÍ9˜CßÈJrÎã½¢;œŒaÞ„p€2õÔvÃZ1.‚+¢=Nªïô£YNk~¤Ð“wp w “´ü¬m_b¢çhlUÅ43cᕆÎ[5Ái«£u}c:)ôoGœøU! YBë½UYzÀ=M²4eÃ8H’&¹óÁfï×”g Àe·lÍä#3½Òa Èìo3||Vb‡ xQ`¸—Dg+©@õhåEÁÿ‡²ØøýbÒRÍ7Ά8¯ªâb#ÞØ®|(Ìœ ÜÕqA›i‰LCÍ£«øw,CØZå7Ö•XtÀìxš 8åöäU7±0þÓÞÏ Õâ»bó´Ëì ôE‰Í[ÃØ¼9»’ƈpìü\¨.Ã\±‘Ƕƒ&V쨃æ PHaÇIdÁS©iÉÈŸ£eTpä¶´l ÿÚæJ \Ç¡ä¯vuЬ£ï:Ò Ú™TEeÖÊòîˆy€DjÇ0˹VŒh›‚r|P¤IªWݲ \AÆ%U=ä2ÔšÌ šW³¶¯$ÂyÑ‹üÄ©ºÒŽUåsXVy<.‘k×Óÿ­ÉeÅŸ¦#ï*Ýš g/ÄPå3 ”Û[±IFüú`D~ðIa3¥à# bb¸ áí€J†„—«ø5´/MÔ'/€bŠ,¿o Ì7è/ŸDÊ_嬇Dؼ=±B.Þt˜C,ª î‰F¯Æã&¾¸È}ã–Ÿ„`˜£ƒ1pͪ-Snb5±¦RÙW1öühîT 9b ¾Ã©}ûΨÐóΆ¨¢’¾6ú¹¦“%,·!GMÖ²QYŠ× ʬtÎÏý–eÕ ÚÿXeF´#ÌR!Ì ˆÖI:¢dųÛÈÄk ž .Y ¶—À¨>¦‡¾L õôe‡uRu.CÀæ3Yêoò[L2ŠSN;Ÿ“¥ýý¬mj·ŠÈY.¶ zôºpëÔm­O}T©3K¾ÚÞB¦_/0Õ-‡1=kÅQÍw*Õä´§·ÙN~²û÷ïR$6†²FÌSJÞÇCœ–‰F ú`í@dÇÂ'<ÍžÔb[~è(H|ysT”Mþ>³ˆë cu‘Oæ_Qûk *± h•S¬('ßÀ`f.æ³¼ŒïßéÅ_í‚ÈÅ_òŽx_>aM¶ÐPHŸÁ? ÝçF—*8øõÐ÷?PH?ê½gyÀ¯õâ›S»û³…ÔøÝ‚ƒ©¡†éAÁ|lƒÂÙã,!ž2C?èA튎ÄD`‡BÉS=ç$3eã9“-C5•ß:ÂÙ=Ïï¸íªjÀø²-Xm0ÅVD›Æ+ ŠÁÄÛ^Øeá¢a‘wR7־ŅŠ?nEm %+§c•$$×) ¥²ì©ÁxÖa¡òÚÔS1¡z[†³ÃÒT*róÏHí|‘š-bªžßHƒD[å»J :;ö\\(RÙOÙvÕ¼JÂKÍ‚byó¬·7]‰èÖ+D§Ñ– ¥P„ñ+ó~žbBH/†ÇebJúÇÀ“Л©qvÔ¨Bêß1ùßÍÆäÏDäuð6JÍ%Å•IǺ"ŠŽc#%¿Iá&Ümçøá3aQÌBÁËï¿Ò*­;>øCÿ‡"³´¡:ÔÏQ¾ú×EšÇ>lp6DBƒ^‚nRÜk~›áùÖ±Z·æá1Ì]Ì$e–š4 ì°«ºÊR¦Ø×?µ\æ²b“g³NY—?yé0f™z'§{4’…J"~xpÙO9uˆÑÙº(¢ëÅ)êÚ[‘¨F¤lxþÁ(S6‡%M¬»‚~ˆ|™™×‡ b®"¡!J:À†Ë›É“cþ@lÖm§uã­£é;þ™©0bjSËÿøo𩸳*ã²Ê±® w"åï˜ÏJ³>‘JUHòÎsÂõ©œm) árHRÎgh”ªîö6Dj:iu:†{€£Ç=Õ >E9ù“,aœ°®DcˆªK;Ö®> stream xœí\mܶþ~0пp¨?x•fñEU£póân]·M.IÓØÎwñ9}çØÎÛ¿/ç•CI»·n‚ŠÀ›]J¤ÈáÌ3Ï G÷íq׺ãþãÿŸ=?zç£ñøâÕQw|qôí‘ËÇü¿³çÇïä‚Ë-íÔMîøäÉõtÇ£?Cl;|òüè‹kúM—ÿµ7ß·©smçúÍûÍ6nþ÷›­k§)ÅióI¾÷¯MØÊ£Ñ͹ÕÅ͇‡ÁÓ°¹Wžs¿Iõ9ѱrÇ.;ŸàVzêŸ` „}Ül‡ÍßáÂÝ2®ïþ° yDçè¶¿ÛL]îšÇ;ÑÛpŽîÿèäÏYœÎ[qÆÞµCÊ=9g)Æü/4=Ý<{ó6º¼<¼ ];ºi¢NÛ<ëͧðq>²€yn·ó7Æ…¶`£î¼Å÷߬:ÑýÐS;ÁD»êáÞ·1æa¶~j»0%zúodªõºà+̆ûôU7gùßU^ásxÖ òwùžß¥Íë¬ _e‘Mnóp“¿_5´aó}<öÙlûÍ VüöuÞ5ê7›Ü’ךe m´¦§ð3uy>_Mð9Í3x–»~GWãæÜÑ箇¼„Itx…›~„EÀåWE%ôAÜmØ\äYtª®,V•W-ú ã¦)OgÄ[^âÏÍ7´Nhè¦6ªfüì:?äŃü»¥_¿9ç±²Ü7>›Mêôˆ)â.’Ô÷:ÏV<ŽžæŒ—ò‚d†Oic¼Gù0þˆK¤ÆSÚE¹; ˜û–'¿UÕƒ5<=yÀ?Ø_XO‚Óþ楄ž°@–âa)!z0aÙ’z”0tù¶Å+ÛúŠî‡ÌVÁš/L÷¤£ øØºMžp*BfU3jU¯¾V…3˜B‚ßEuPÝq,V9™Ùl’W2« ¦(M?¶ .Ãd›Æi$q"̈~ûÜw÷ƒ<}˜Á}ò4á¤i XçëÜ>zQqß÷ g$ZìÏD}™áS1!3(Œ…sÈa’«(å¡2`îD“¡?œD ÛïÉK‹úqç]œg+5‰ÝÕcY€æ!ýD‘ÜÍò÷hA×!0¨_3ë"JåMüs@"[<॒!1ux€®ò$s¤ íé|(»•ÍãÔuqX÷”je¿*š¹…‹eò0¼}NÊŸ£µÉ+š é˜<òÓŠ²¹¸˜ß~¨¤™:£‘;§ ÌrYµ%v–ü« V™Ž8î·!¼EÝ¾Æ \òTºâsž d™Ô^¼R²L&ÖöŠwD5ePxB‹æ£¨7Â,›Å@sË]=¯‰1Õ<¶rtT{˜ü@õM#Àb ³¨EÔUŒY»0ßA’‰“z}š©“7q”v”`ƒ}ô!j § @©CyLNÉ/íî ÂÕ©R†ì0êÌöbÝQ}ÝÐÆg¬™ÓÁJ©ë’—Ø,j/¨b60‚€Êyß|J²(“+øÝáïTϨ,Øk"^2³¸äðY³MŒ‹MC,p}åúüDgm‡àA0LŸ"{¨9¯¼,Q‡ÏÊæ­ÖsòÚ˜éjн8ÇuL`lŠÌ2Í:q¶²»?j(ò¢€Ž1£ªåYb7È_‚uëzu^°iUýYµH5Jé&£&sVoÕ0Àœ›] QÙDˆ“YƒW‘rk| 7chñaož“G6³j åNšÈ_•Yíòh¿NÏV(³ìgGEA€>Öc™Õ,´ ÀCTxíÊ>X)åk¸¥xü9V¢ñÂbìö,qúu‰õ$w¨¼B! ®HLn®Ÿ†ézÌŠGH¿ÆóLLçeª¢¸ÈWôÄv]¿`*KkÈÓ¡„ê*xÒ¤q ò½Vã.%W[Œ¯lh[¹ø5¥y”ï€ do6ŽjÙIö§Eia‰”~ÅJmòà´Jn­«ì‰9,2 †•ÊZklW¿^rknÇñP숑>o0AÔ³†9€. /ç«°øÒæúÒ ap)íðÛïܰ (5!»†lŒt3ÏrˆÕ, –´çIöo›õUf—DÇ¥³§Ï’<ÅõÓ.É% ›ÁE.Âý<l¼äUx÷ OUÂPëQƒê|}®Æ(A[[’¥l!D ì§%ôégàUù·X@^ ÃmSÃÍ,„Z8x$à{—  üÛÐã\û°®UC üïwú kŽõÖ¥éÇøî¬vêøõƒ…O ´wuæÏ$„™ºA}"rùA™$×|qtF¥Ä›ôäÓÂÎð¸ßõi—ÇÎ|O.¥¹oó䀅ïäÞAºëñ 9ŒtZ°#Ì!wë Qå¨ ’ZÏÌá£9o>å”óãÈ•> ™š–'u20»T{¦y>£Ã+Gm³óMòÐUʇ¨ Æ ^2×1Ý 0™Æ}ý¬©ÁçÖ’öÐk#vpƒ’‰ˆœ$^—ÇâøL7T Êmk|I.“Â<þ:Vö&¤ááÃF³ 0Ø’]ø~óð%üø©I\ïòvã·àKK¼©lj’0%†®¹‡çÄ)|jcƒ­luü†8K^² JºÕ/åõųDgîªsVìÝlÂBDT––Ü%Ak«)ÄÞFÍA+yÃüüÿc “«DN@c ç€-„´ßZgœn­†È¹6b O4E_À>}ú`[ åæ×jT€™ÐnÖ< Á#§E½…DBþýÈÞcŸ–“¸ÛžÒ¶Úøy¹ó‘6~QÏLô¹-i­mÄÓиù—^ÿC¹þOmü]itÚøH×jš¶sÙIéJ*©%ÎŒzÏœÁSöJUKŽ¢l\lr Ñ«ê”"*äAÔ½&” @ü¢o¯"ƒÄÿ®w5…Ê&ü™§&Þ¸¢3&侘+0C]KÑ?-^p–C0ö#§+ü¬&MŒimÇzÏä²K¸Í½ÖØý*Vr;OÉSviÕ nkãuVô+è>ÖFŠæ ÉÞÐé~a9\Ñ'¡Ñ¼Ú(L^™©ôø¯B·krPë°7'0ó ©ÃÛžª“ïfÆJš[ŸL‰k0†]©2Öc ##òqvü(ºIó“¤NΨþ•ñ¾~fLÅCï:`IÖ),.ô1%x^ÛSÜÅ*â̲ÙyÆWýYjœb±D+3^-#Ök}Ö”,Ê>“AbZT˜;µÕÒWç Ã:Ü]¯W¶dý²*… ÷2=CkÎb«ZŸ÷Á…¬çš’’ª–Ú{-\tyªòõ˜”qÜ£T:æ ¤RDÕ7-ÅkæUŸ-k¨kµÏ@ ”²oü 1Ç’cèU»»éMö àêA&´ï(“ê 8¼_V—ΊÛö×®Q,ÞµªvçAP¨Ö6š¦Õ i7±.8¶^ÇsZÃŒIÂÔɃ § úJa©|1q­&¼µXÅPƒHU~nÏàà0Çþس$>j4¼im7çy©H·{0q¹þº­äÃ3¦‚²oœW?-“¹ö|ƒ sòQUÕÖî…¸©Væ¼Ö"´Ñ¡59§*A@x³,¨”†øîÁ˜Cæ%Lš®¼UÆß–¯Üš#®5ôÍ*¥Î•Sø_*$úP5D‹iŸ55¾XdéõäÜqM´pþ*UèLÉžöÇÍïé©Ë(.ƒÓ`äˆBÞÚ哯ŒÃE*oSmœì’²“Æ|‚C+•*Y6UaŠMº÷EÙ¹má³ü”VóÈïjåÔjÄPMìc4vªiã³f–ó”„ŸÏ”y]|S?u¾³Ð²tx¿<ÛÅqŠ‘mˆ3Ù€—kÅœÉr¬dXÖSØ YÉhi¸h˜vœ« ñ"ìÛˆ¥U“Ýì3Ç׬úÞܧ¾Ù¨Gs›f6‡íVº6rQÆjn ævñòÉ`ç€+‚€áSР4Ä-Ï lÒWÒK™sszi(ŽæH/iíÍþ*Ä:—G ÞÏ ƒæ§5Rþ£ÚÄZ-y•C–«8ôœÛ†1´%ò\yßMãç0ÀËhS¥Q@ÄâŸKÔMòþž/HÀüJ¯|]GÔxQÅ…ÁÁ3vå¡J!¹É§—D´<ùáf­?èƒ#ªö} \ÿIXK¼,çÚgq¢4åãµA/ö áÒÆ‰+œ{K½”êµ:n„FOÜëÓrÃ]ÊPɿ߯¼ý–/ÖônM#¾„;¢«qþ¯רŧÚz·ÜZ^(ý²4Þ©ÒÛ^?èõ§”½~Yµâü3¼#KIV¶¯$æäÕš2ô›ók³Tj²Ù03ƒÓÕœV äÍüª’¶¡[žJí%ËË´¨þ½¯ú'°ä‡nú•õïçë‡$ÒI¬(§„ŒÕž)ŠJɬ)çû+ʹ÷çøø>ÀÇ=m»){Õaòÿæ^èõOÊõÚx¯4žˆýPYîbÛί]Ž,¼ì`+ÖÍ«H÷xKƒ;àøÅ$v@¨ãiðÄ;F•˜Nª„²7èë¨ß”ò E7U¥‘üÂà!Q}é?iÕòxWçÌK(ƒ¤?ïÕ{\¶K@ªZÞ¾’רmµ8½z4/o”,G×·’p|ÂgÑü5‚Az.îV¢§›UôD;Ø|uMA#f˜ék)/é¡Õ7fF\3ÚpÒ!nä_#À¬ÿœDç¢3L\¢yenœáácí)鯯¡MqžËÖ6ûVÍFÊÃ]¿Ô踼ŠÅ(‰#!  —„èö”tºF›mj}(7+àáC¸æò÷‚œDjQÓ5É¢š™’"kz¾4•Ð0êw+Ëß ó”É(ìJ€óç•Á¶¾Ë-i »'GÿÈÿý'Îä9endstream endobj 775 0 obj 4486 endobj 779 0 obj <> stream xœíZûoIþ=º?"Ò2ëÙénjLJЊƒì‰å80ˆÓ.Z…8 yç±¹¿þªªÕí);¶ñžtÒ ÅŒ«»«»¿þêÕã¯Ûu¥¶küçÿß;ÙúáÍpûpºUon}ÝRÔ¸íÿÛ;ÙþÛ:( ’jTÔöø`ËTÛC½=4¶ªõöødë×B•MaÝßÇñßa”Q٨ѨjZ8ž@ç§åÀÏKUFOJ]¼.º£|§„†7åÀ躪•%ý5üUЪ­YÚñCÔTèâh}Vú/ÏPS}lñSiªº6Æ/°å%~@cu5êF4 ôKì†õ·ÅÛrЂTëâ_¥†‡F+0.;K£>”Úm?mà÷?0u5„g­õ3¨,öaz›jŠ]Øä'˜qê‡mqVš0Åui4u´#Bdöö@Pœ£†‹rÐhŠû¡#XÏh;u‹VuGrcŠœ›éæî`ïmìMò[œ 0ébâÖhIŽÿ_8JÑzh Ëüެ¢Q6'°jt Â_J+ÇI:˜~ ß.eµªL[Çq¸öd ¶8ÁÅ6„ËMD{핦õj„"Ï0öös"ÜQ“ëÜ5:îkú›‹»>Œpš‚^~-8ÔÒY6J‡3a@h[7Ž‹t<°C^žÊ±?,¤íЫÄ-‚.döp¨‹C„¡ƒ}„ö0ö*Ηì1u¦ÔêÁhÕU]·=PH‹Ž˜£*ÜF$†ÅGG‹·&Cü‹Š‡t?ZÙC6 (”V€pW«   î:Ÿe ÛúA¼kª&Æ»â÷?0¤bä5ÅüxˆࣅaÙïÁ®t›3¢Cþ,.öÚ745EIBŵó6à¦&ô÷bûYÖî…W,d·sÊÂ)ÎÔþ¿’ª žêKê·BûmÞ¤n}À‡„“(œÆ§ßJ0™1Ÿ2ƒžúÃ(<Êœ{'G’ðÕßd]9–Ñ£…Ðó™N†@Ïvœûv•ж÷2"ËöyH‘ñ;~ü˜±BQ¬ý?+":òï£t‡»¾ŒÂßYø£_ ,õ&¶æöýlщ”6 *€ÔöQŽ¥ç ±fâ Òt1–݆ŒõÐ3YÁ.Sì¢'ÅÇ=‘ŽâÂßÜüy !¾ÝÃg‘tO#é2W¤[Uÿ¤Û¤€97êüSîúŠ.S oðL"ãSŒx:Ñ ¼Ü?HeŒïðã~¼ˆ²{ÙÙÔþ_8›q¼ã^¯¢ð ÇÁÔ(µéÓdñòùĪ`6é):µOwx¹¢U•‰ï¯|Á‰éf¯mG°Î¤S†2葦6auÐZ_ü¬uûƒ˜ø Ü^s'-YÖ%)]-óï”ù£Æ° 8ƒƒþ*ai¶1äK{uuÅ÷”¯3®œ ­Ûjã)Ôtô·ïÿ&nß0 );pÓÃø$_ÿœäö0‚ ãMÏî¿–tìÒ]R%r;UdsÊ ·€v…zÓB±+ã|µÛhžˆ¹û0KÝ)ëe~wƒÓfVHÝ…;|8-ñÖKä%–âCECå8š=ë¬&hèH<‰Ãé¡bLã[ÊÜ™šÀßBÌ¿UInnL;ZpÓ¦LÝXÄUwi=æ6C+še 1=†V’¿Baø "ÓàŠur ’Üq`*”ÞEì OxŠÖÁáQ4 ºHm,vm’»Š³P ­V»&˜úªØ]u8ò<ØF5|婱ÿŠÇqÅÕcd•ó}ni¡:‚ðcÝFÒa†[Žª “ª¿ÊµT` ­d`A¦kã–ü+jÚóñ/mŸ;Ebä(ó}=ÆR ’Dð¤ÏÇr0ĪœËÀÅ\€§Ùt^xˉA–-¤©¥º$¤Ø´Ïšv¥9'¬é"¶ïJÉJH”M“É­Wæa2ñ_½äßÌ©™eÇY U˜j;C8ÞÚ9«8—ÒîyáN"ËàBÀ¿ ô t>¾ËlP?Óaá„Ë‘#¨sÔËPØô¢S†/Ù|•çøJðá*&!›0ªØn‚XQse™$šW)h³5V·ICY³°MÒdá ƒ¡A 'wHj¼³ì¤gʽ…u[j1Ø\¡.V¿ì˦}àagÏ»ó€¯Ã+™…¹û”h•‹–ûbužT̉²¤ï&Œe 0*Å~I‹<ã,ÆqæçPy¹ «xŒß×Ôà+4¯cÌS>‘„ï¢ð- ÁUC™t°ÀI)¸ÉcIx) §ëX`Rºe˜üÙèO|®¥\H;¼›¿k`Áד—'û«Œÿ~‡+”lÄoRýgx7…©¶MÙÿs/Ä£¥œõÐÌf}Ky„ÿ:nå9~}Â;àX«P\á‡bP†k6,“:>̧£ð;{‹mç _H=yxr‹™'H‹bÙLy×a¥Ð$íâ]ÓeF¹äj3€ô˜¸¿xQWÏsý‚o|ÄRßB†%`7kXÞ×0mÅlh^Þ)Ø×©Ô~ÃT`½à´îÝÊ´úÄ:NؽæÏ37Büu/ÍO¡÷¥ã ¨é €¶¦Ÿ ËI¾x‡7MqIBl·"ùµ|0XârOð`_D|nŨž¿T˜ò;Õ‰*ɉ»¶w?¿1'ßñÔf˜ 8·Pò¤SF)'_x_‘˜zbß÷3À%>ù?¸Ûùb#ŸJ¼;’à8 Å‘’íÈõ)'žË/D¬Ò®³öP¦õ­5`ç-»Ÿ±'M°Û\V¾V +^çÒô—Œ(+M`ø$"’¼ýÊ™^y-‹ÓµT·]H~èJZÝ1ã$F=ÞÒ¹¤éRòhùæûþ”éôˆìƒúR%‹à°fÂ_šÌ/°pY ¾‹&ÿMÌúïXÏ$õÉ  ¿÷Éý†P“;5ùþ*ñŠyN¾Ðƒ. äT¢qö ªï’woœÆ%©'¤÷¿¹vJ"‹®ŸË÷ïA]®Ý¤yéÜËÒÂWŒ)t»›Í3•v"Öm8Ÿ^)ÙðÂ{,L2ûï²|;¼çÝh¾àÐ T¬=OÁ½ðcž&™xú?¼ôí!&R‡Y2ÏØÅD=Dî»ìb‰[çuˆ-dŒIœºå0”Ô±‰a^³/H¤rßÄoæø‡ôœë ,vewêo—ß;±ý·sÕó¾•Èÿ& w8·Y龜Q‡µf}Sñq%iÿçî¨!¯…Ð/_ÜœH\% ^õÏV±Ú숷ëÕJZ?hõ+šüŽø¨G½™25Y«˜oœÖ­çÁ ®sÿ‘¿DÝoýþýMŠ‘endstream endobj 780 0 obj 2983 endobj 784 0 obj <> stream xœ­\iÇ‘ýÎÕ¬ °{¡.W^UYv±ôZ×Zky%6 X’C¹"9”8ÔñïqfdUVÏP0„¡ºëÈ#òe/"û‡‹qp#üÇÿòêÞᅳ/®ÞÞ/®îýpÏáÍ þß“WxX®\–qqŸÝ£7ÝÅì/æ‡Ñ_<|u;¦ÃXþ†£ÇÏ?Ÿòè†Ñ¥ÃWÇà†e îðåÑçaÉÉþv<…0ã8>9†ÃçÇ“?|qÌS¹’§xø.}u<9ºùçÒö§ðRÆ6¿>ž¦Ã_àFyZÏq9ü¼‡O—6KKŽßÅëŽËX^õÜ<Þø>ýùÈï÷ð¿ËŒ·3ŽÉ S.“~xÉå/=œ/\Bœ<<{â‡Oaf·,òŽÒ],"ÂOiA ÉË,w|:9¦2år/Æ2ÇëcHEÆn>ü\&žãàb(3;…"Â\æöB[y‰Ÿ\ö‡›òiŒ~ɇ§åÓ<¹òéGИƜäç¯Ëü‡–%® õ0¸Œb-W£›âáM¹š†<¦`šzMå9LÒôùA}ÉÜTî‡2’ æ•kœvÊ‘Ç/÷Ä_$éP’_Ü{øoßÔÄÃsXù§G|3ø„€¡¯~"lÝ^)óÆa“,Wž„¹úÏácÜØ)qÃSeÔéð DŒèÁ;°[FœÏàå– Ïá¯ü”‹ŸW(Æ 8Lƒ Ò%5 Ý<†þÊÊa/e"Ћ>ð\s7ËÄSy S}ö߇öÂ#¢¥ÿ:÷{'ÒDáÃ% £`à±JïWx7c‡¨á7GXšàç¡,ï”-´}Uþð KNdñ ´lpGÓ Å’ÑÀjxB= S»¦Ç@óìñ­—ðÖ\Æ5K‡¿%Ü>ô¸-dm¯ÌŽ¥ÿ#,IJ$ça'žÅ©,Hš@Ád`ÁKØvÊ(èqmU¦(Ò0á"½Õ2E)>)0þ¬XËÖQÆ®ù«¼ вӻ°ÂqA­ìmÅÒ;hø±ÎÔÜyʯû!ÌL2<5²,+þ3hA¨é¬[FF²ÛÌš#(ÿ8;Üšàù?êóO Pã2ø(€2Ð!Ñ^[`ÕUÄÕ Ðv}í½YoF€ÝÙ„ÀÊ~µ%ÄBj¤³«»­ {b•L‡´I·À»T(ðh¶¼´dš4C>FÝý*äXvË·?—2áFÄ®ÔóªÍ`ŒOŽK\i pE[¥C}s‹)¨Žx-ë§ÝÅÕÊÃS öÊsi³7 žŠC<=S}Êké&Žˆ[ìD6à‹¼•:}Ò¬ Z¬ùbH&g´WŒÇpý äèz¢VËŒ[—§?ùFcÁt¸)~ø§c"’ó¸… e{pyMð%šÛ×8_sõ®²¾_\ Vp4ÓVÃ=TI“ЏIV‚¼éÐ ,õ;ïD7@M6¡K¢Ý'kM5Ѓ‡Ý‚*ãú˜6KІ:„v9ìF¬`Ïêi.¿íM¼‚§Žzõïàà>8ƒìDñª*í«í3öZÖ׌íZÄPwaµx/޾Ud(VkN㗠ϖ㎻b·ôhP0á,ñ=5êa›o4àQ4ùVs}{¯vwžYEqøñÿJS¢îÃmÏâœXõntddÕo‹®*à<©¨ßðÚ±åØU³;eÄ_ãñˆ¶€XÈ•³~_•jéwDD²C^°™ k„Ï«£_hK4îaz^Ô$çÜѨҋÙR]Ù3Ó¼ê˜<êÏÊ×?êZýnn©yð5 $W­_×þW’6ù}øaïÞ Ú@J´ƒp 8R²*ž\«¦ºêƃ6* Q<Ê8Fö¾Î™\ó×b£Œ·¯Ë˜: ±YVN­^‚e/&Ab#t¹0]æFåqq;jh·jhÉJÂ+/ñ:Okqá¬ÎauC`Jƒ ¦KÁ̃©n‚ÕCºuú`@¹ý“tâníÐ׿=j/ŹL JÞºtÏ;F‘‘F3o‘¦Cé_Y¿hw(;&ôkŽ9‹uX[ QWÞá¼d¥.¿‰ øvµ›ÔÀ«-‚ú ,#t„C××Þ5ãÎûCƒõZn ]d ä—iP]­x϶s(:ZVÆAî]ßc6¶}r7õµË¹`â †ÆeìõøN iÑBSnmu*â°ý•êLÁ%ñ}ã':›,Gó«äEy{6Ñ“fgˆb3®ñÅ€( xE[ÒƒuhdiÅÍþþ<‡¼žoÉ÷´NûKV?En¹*$õ• ÚAÔ…< jÔmç±XhF$PòžÆWƺ[—"G«nªßSF†TØ,‰¯C¨þyÅåÙ¶=°ú€ÿÄ  Õ7÷… ¨!2_Pá°¾á;?É›õZ üîHªãAšôyDœþ;¬þ“˜œ…·î3)Sf³bZB¢ÂÁ³½\‡ˆ~^ÛðпÖ|'<,M ÿÙÄ&„Ÿ+áöÈ“b¼ÖÞ>9¥Ì7Ù®xVÖO‡ß“:û:ž_¾þ‘§š'%þ슶†LŒ0D<ÅÐ+«JýÅñâ˜ÓÙ±B=ãË ­´Ò4Øqw…4áî‘#ääNù½ Yˆ´ŽOޱ·v€8e¼»rYãŒb}·Šîe)¹—&˜K¤ŽÎj/ß.Ç™¢»ÓhÒ/Öédiøµy Qj`gÌXÈi¡PaOdÖP;0äï§Ö ÷0œå#ì°Ëú–ñw6}Ò°ÊlÑ-–d&Ùïðä‰õÜâ—FY€tR PԮɩ}†©=Ø…–ÍiˆœN”,y01òA“.Zv è6VÍÞ ¤·{ϲGÍBYX3ï#¤ÒR£ƒŸÄ]2k&KÄÿEî““0{7N޲Œ'cTe 7G~ïWv·½É5ŠÿsÝ2”Õ€oap0MYúL‰Ò”ܤ÷’ƒ¤)OãàÆ2`0KåóXÜî]idr˜ýœšgìgz$ß™³˜-°‡y#:2Åæ9¢;Sâ~½4EtÈý0ûèü(ð›§1’‡”]‘&¿ò+4˜³Ÿ ™PÞÿýð?EbáíP6Ù/úd/©èÁÅçŒbKŒòvÙ·\½P 5¾pH+èßEŸ²yîèÓ¾Æì(]ìá±ý on‹ñ."º) ë"¬A›…©þÀ/¤µ6ª—`[ÌO›|aÝ »„™’îë6µzh7B4~¼4¼ßÊ3šL‰ k¸oˆ‰–‡E¥?­•~ë*Ö(á$ƒã %кk¸Èâ\‘¿/M·€Îòs €+Pó0—)ÕkÀ“Å M­ZqMº–‹£—‰4ÞîÊÑÅÇJ—5í¬|¤vßp”ßm(i5= ò^ÈQܦrÆM »Îª’ÉõCÕä6iVæ°î‚/3,W2QgüA—ö .#‰#XŽüψ+&Cù§»SU<ÓÖ¡û-ÑÒÊR3OPUB!fHbM9ýÈÉkŠ‘gEÒCƶªW"øzZÕ˜Ä×Üá4­‘«$À6IèÜ~|Y±Ž‡ç Ŭk¢ß0ÿ„§lsˆ{ mñÝ`ÅŒàÏç—Óp0ˆ+¼óÁdôäÊÆßÿäè*3Ä."ök}íãê¤åšüSM„™=³(œ2ó2ç¶Ø$Ì’Ü¿Cݦڋˆ75{s+óå§Šfa»Þ­“8ê·¸eðÅSýÉqqDqçÆnëZ»5§³o½j€g9´x¥±½ø„­önX•T+c#'É$ßÝTKjT3ëº×/š«kðÏùM[Å' †þ¶D{Ø­ë­©:w µFžÍÅ.Ö/õ¶ôHZàÁ žÑ&UÕœ›ªpmF2³L?'ok+õ=–ZdEÔå&vލ¡Új«žwbê춪wåÐé†2 e]ea”°Ô½šÚï»`XÔjk$_[MNe«ÓŒ›|½ æ|ѳq¸Œ¸¤*'°â´Wõ÷233É»‰ÑÙÀ¹9Dm-j_­Ó\O™Ê<“²´ W´Iô Šè0OÚÑÜ~˜yÍ;÷ßÙaê—½ËPî•HÁÝ^™ Ç~VÚ™¼k-&Hƒ\Ò(Á'nוf2T,«r‚Æi—×´V3VtÕ&.Yv”X(øJwÊ-@ÀóS‹kí3¡…G¿­1Ä3pVÒ/ŸKª‹™˜ï£bٌ傒ˆBˆHêèΪ‚r8¸sÒ¸O‡-?»Y¹¾Z~\+ñ}&4ß!wW†v›g‡Ê* öìιõqȶ6~ güÄæHØGÐOk@“Ú=½.Ì–Š<[¸Ô”JðÙïéH=©gnJ#A™"'dµ§a­¶iŒ *Ê´ôÝÛÃú !äXD?Ö ­M¥ŽX·iѨŒªÏxéôå;_Õ s®:  Pj%Œxe{>§hÏ-\;¦äê¸#¤¶LhJ6ä¬5b¿‚w›âˆV!v‹Ú0ï ‹-‡®®µ Óm¶P?K{qfšJôê#ñÚùó¨E R0EGmAæ“=#ì(ªß¡Â„y¿mʹº#èät2¤5©Ë¢ÅÿR5R=Tªßõñªlíʲ^Ò€…ítD2…%Ææ·*zZxKMš c°tge&Û4 Ÿ7àBFw—˜°{{[ÝÊåì‹UUÊ~òà€ý ú‹â'gK³Ê*‹Ÿ!‘žtšêÉNE³hnbòzܕɰÕéwÓn'ýã-ÇZÓª†U¡kÊ÷vØ¿GO'ål‚™¼ÆUeá²rSn(§;¤Úmg`ó{Ø/¾xŸ}mÜ’îKE? ãâùT J.ì-ÎöXϵ-^…±ÿ‹´¹!r¥©fç‡m˜@ØeWËSPnÜÄB8XÂ|®e¨u^q[æ`%˜¦ê¼p ØóZJ* Ǧ²è€ <æ3ù9›¶N2ÕÃ_ª¨B}´iPÌÕ­mݯ£ß;Úhj”Ö%C«¢­ºõÈï†qº…,à§„dYȱ»;ò %ü#EŸ±GŽgX“HñäKLâÖG…¶üš]e­V‘Usi qÀéÖŽêò¡£_¬f™(W ¸æÄïê˜sSíÀ^s ëyý 6h”à¤ln,›~]'b«e¦š””ì/ý¼ÊºP­©¦~¢R7ú©ƒÆ‡cL‰ÙX¹íÚ[§Œˆ¦::)p¹HåJ-|úGÉ­‹*}œ‰ýãÛž~¹ã‘ §ÞÁ×S®¾²ô"ZwSj¼V’—(‘笮õW!ªqU^³ª-CΫføbj`ÝåIa„—j‡ö Ôúw”6~›Ö»gÁÛT£ÄLÒçd~I’Ö«cœJnyÁµ[þA/çÓp’öx@@s!‘ Qÿ_\ø…áz¨ŒÆjÍëeH½-a¯–)´:ªdY´øâ–âxSeôôNzn¬?µÅ6›™ øöÛ£nye÷ä½ü¢Nf×é£ÒÖ¿ÖÙ|N™ø–!Ü Qb.ëìjÇ|ZÈÍC‘Î lz|í7­?cÀõAÑ™'ÛŸ¾âR¡¶¢I±îgÞç§´6÷Ä!M·åÞ§~Y<-ñ•„¨’ÚÏ©ýÖ_êV~TƒÈÆ8²²Øàù‚¶‰)4?‘èàü¸ÏÔG'îÕ ì) ¢ÁžÑÊ ²k ó æáµP€ÁÃ7ðÒ{_Á?_Â?ƒÈÎÿ(ôK’¾ø]Eç7zñï͹y¾xU/Ö~ëí¹ÞþN.öܼ“N¿ÚÉÜçªß_’.§ÐŽÒ]ëÛpV¿j¥Ù³„9ªJM®£?.ŠJ­÷ÈÌÀÿ71S“ÝV}Öý¡!61¿VZž=*«-Æ&j¼f»•ò'¡l¤pM&€ÝD1 j˽L¨B)¹&×2ìôs¹&Õ :‹sg?¼÷¿å¿{À.> stream xœ½[{o·ÿ_è‡P]Ô½M}›%—û R·N¤-\'qUÔE€žg¡÷u’-A?{9C΃{<,Aõ—™ß<83¤^ïW¥Ù¯à¿øïñbïÓÝþl½WíÏö^ïü¸ÿ9^ìqà;ë[Ê¡ÌþÁÙ^iö;»ßÕ®¬ìþÁbïû‰)š‰óÿ·EóãÁßü¨Ú$£†¡lZ?ðàÄwþs1u“¿¦†Þ “'…|[LíäÚ¿,¦ôáE1­mUVÆáü•ÿ¿ô_­3¾Mw|ÉsÑvòÜÏú´ˆ?žÂLïã&_uYUuí&…/ÏàáûÔΖC?à0 èïÜ >Ö0;ùG1m}«µ“Ö¿4Öà€ƒ¢w8êeaûm­ÙŸš¾/M»?­«²óXÎüÄ“sxÌáq %<á±à¶ÒùÊ?üÚÆLÖðó{xü0çoà M¾Ç¿<Ò;y\LúCáùÌúvò[J#ÎZ_JkÉ3~»Ê}îÔL·þÈ­¥Tµ¦Æ”nj»²¯‡>`„z1÷ÈžzQzXCÀÒT X;YùWE€«÷5þ|ßñö‡ös?`éÃ…¼Ü;¹†Î°Œ„^Aئê#aî¾™\z4ýšuF¾õ_º~ò+5A`hƾ0: “T¦Å7^…qÐ šÖ¢Õê&&q{ë`.eίC@ØöMéz2;˜þ„5øŒð„šÀ-Cƒ5º*„cĦü<òܺÈÃB¦¥_ò&#N€“ÍR>¯dm(±Ø6øÙ D|ZÛ"û퀤ÉD¯¸'¯˜5ΈÒÔÔÞGC°Ð¬þ”ZÞÌTŒó†~‚Ö×9}ï½OgŃŒ¾XÞ<¹A‹ˆ›à <à¤KuÝ ´Q+lTñõ Òë•®aL+º ª¿Þ ð‚-×dDÀ½•ï>Lw­G ½ä”˜š¡Œ°á§ñÂÆušÇiëÆ°Ü?¥j9Œ¾`E¦ªìjÄîXMãûGz Ï`KöÃôG³©­CÞ ÿ8~Ws_Œjçeï}ÎHÎ0ö\;—¸r Ä&ã膶ž¨d0…ðU1ЖFàâ9METìå·EO”¼vÁ‰ÝÇNÐ¥1-$n¥QúS®Ó‡Ý:ºO10Úu–AÜœTaŽPÕ=¸]±¢ f!™FÖSÃf£žõÁÎrz¿ž%n9ÚÙ¡§9,ö¦hjà.,uy‚÷#ÚB`•Ïò±„õ€ Ñ$±ÄvC¯áqÍnè× †NeÚÛÿlªÝ„ìà_ ôßqc‰qòønôo¦r Q$#4.µäT¨@ rãké™Msn|«ƒ Œ¢S-tªé4?À+}.¯‘;çõ¨ò-þ„* A Ä$Ïö>‰hËn°ÖYSõ1™b÷‰¥æÂ¶Vä0ç"+‡gBÓANŸ{òܪúó(kid:Ú±^É÷üŸrã©4¾æÆÝ³UWE‘ÜFg^xÏv ïóDxOPNjý<)Ëb2tjŠ„C–Éiüê†=àmbõ”ôA¦³Ûeúõ™>ÎÉt&ƒ.s’™]åPñð ‰—LxŸÝ]ä_ïùc-rªÃi§S‚œ‚uÜg¨+Öÿ³µCÃ*_²ÒüFVz‘“æÏÜøsÎS*èD›N¤Ñ÷ìëÞ¥†³kPIn5 O6|!ú4fŒ³U.ø0o8K¶Y±i8çŒÜ2bj½%.Bã* ™S¢c£rÚßpãA†äÜ7˜ È- ï7^äli%7š&2›ûlYFS«ÑÆߦò¹“AE"}ã#µÒ'ñÿ£Ùä9<%eÇ®ßÌŒÝ@ÁãFrÀA,DÎ¥,‚÷k8S¦Èµ ©hiUPòK ‡—Öa«üðØ{ñYÿ2Ó6d÷”Šbq¦AíŠa™ žq=$õ8É”®ÄùÿÉå!€Ë>/ýצB±C"£¼>Û²¶äT`Íô ®p7Ud­"±1Ç‚\Ì9NáxŒ‚GLnMpuÎ\·XBX¥©L>ó²´@{œb…£r•²ÇØ7>á:†ÓENƒRp «5!¸NbäWRJ¡Œ¥éRE úƒŸe”)ó½HsÛPµhú4͵"Æ 7FÝ*S8˜˜§%êÙ†r‰ W«©dÔºL‘ŒÉ³?J+Áç¤RAP¦´&£¥ŒÛYÕ–œº%Y~Sk¶F¯ÌЩGŽ!µ³­V#2aLÄ^E“ň@ëmàa{J'ªth¸MýP!œ7BKæGÔÄjé4°9å ›«!œã†ÄÏ«²¸*2¯XÓ›Q…a•ä^» ¡ÜBy,³ÛƒÍ£º­¾ëQÚëü޽"AF‹™ß¨’Õô:ÃoÙ¹^s†i1â6³e¸§Ú1AÏã GØwd°´ù©4ª‹\[ 4Ñg*ø þÑK“u”ÙIhÑÕ²ܶœò èkŠÙaÆA”Ó|–XЍRPB «P_Î’ýš¦Gwœ™MÎî¸n*óí>:zK&õ–Œ;Û ]{QR…`貫[Õ ÙÃL”܉jB¬b‚I°Z³ÛÚº'³¦‚ #©©$Õjë†ûk ;Ü{k mHQÇ:[V.Ñ1uѸ›D#§íTÐÆ’¨H= Á6Á¦ÎÛ‚ÛÌöe¤H Ûº>z«¬cDy„0"NqÃ.ûB´”Äû"6Ô4(_@,u©>Õì  ô4Î:äbI{Šl‘QÓ\5$%.g\Œ¤Ò3jg…UU—cD©šˆîM§ouˆ|l,‘yW…šø I×Áù0gT´HE,»µâ¯£«%:YûidÕ S}p•Þ*ø?WºÞè3¦þšvøÙ×#áŽïŒÕåwgj\*ÕÉHG5}g+ÔH!U‡àb Ùݦí•ê¸&X`Æç‘ú ÑŸFS‡†^MÂüÝ6W¨Ó m·1ˆ‹‚ò{æÔaùots¶=Šñ»‰ ½† ©~šÎµ ñ˜‰»‰ªeÅ%áAe òæ vïÙT(ÙEÕÓš ?~“f×VÝc5›Ym¨}ÄD´*M”ñËJFvà+Õ¥c<„÷ Që£îRˆ3Ziä£ÄÖw®ÔVã•Ê-ÇêÖg>pr·Y Ç:Ä =µíµ‰¦sXaù=”mšJÕÖE&×?’F)_\æŠiÇü¦ªr繚CRJl¬ÝMÕ¨ ¦§ÊЋèÐkUu&/èCøyÌØ\¥°Œ 5–â>Ùã$ÇÛ\ãz ·›5F¨¶õÖÃ?ý8…&ætƒ~UÅ”*e <Õ· ó0§ç[fYûÄœ?ÀM=?Áp;ù)2»’:zX±¤¯Ø:†pdû†Çq†$½5•Ò[¥á²†®f ~X®‚Ñ‚óqŽé¬Jdqöu}ƒΤH¢êåˆ&}ë$ÝšUf¹_õ~ÞòýQPJ’­®ÏŠŒ^&:¦ð¨-|¥sªA¿Ÿ´ê2º‰P¼îƒÇX%ȉ 3r®«`ßTl*gx|gµP—ŽR` Åٚœ*î;¨ÐFçãC±j<©"žMõw=‘Oo…~Ég¡¿â/ËÔ÷É”+ÂßtöøïRÈ…ÿU®§àŸ=Rd$ŠßXÛï–Í­f¯6o!ïäõÑ­vã&~ßÑ«ärɾY<2í½á4¬Uô¾ÑÝmF¢Î¯¶É*!·ê­Ö«„ÛÍ=ï4§3G™=[Öžk©Ó߫îmo7#ψÉ_J(#sSBÙ¡Î÷Š‚Z¾ÎÍ~³ZÑ·Ë»µ¬ÈÞ¸Šgnx³i·-ûN©Wá1‰PMpr«4Ñ·lÕ—,¯kMY­!9á>o£äïÉ85²ç³Ó¤g) ÍsRQгÛ˜¦q*há÷BJ¿Æ{[wYmð˜Iï½JQÎE ó{›šØMjvv«s6³ô¢€Á4¥¤já‹;à>н”Š¿Îá¾ÍBȲÇÂÉM&B4OG‹Žv¬Ñ6õž/¶+ÍN´Â“Žªçl3޾lžãköþøfC9U^äÖY ¾;èÀ,®EóLRu%P´V÷v6²M$’ÇŸd–T;ÒHâª-0fÏî°gs1“ì½*]Çͧ´“Ëìgâvp÷»m8­‰Žïm3ÖöE´}¨˜’â¦'Çä»e^â¼´¥¸rÞ(l¡‚Wîõÿ6ü Ç»ìÔGÌš¸‡·Ü¶.¨ÜÃøýOGîA­÷PÖ3xEDi¢ªœkx©ñ-7ªOâCô³ƒºÏó"u§]Û1pµgèáæT Ë¨ý€ûá¯d^lGà'žè'1X¾Å¼Žö> bw»âóìe¿•î)û`(5Û·<ĸžÔÙ¼NÅlS&“,¯Ù’_Ñ ­a´Ðë\–x·éúí Ùû’0*Ù‚v›þ2 tÿ¨£‚GIoa”²ñ~–|FÌw+ ê®ÛwYהּ%õ¹‚À9ûš;²ÿ`Áë`‹]Õ}0'i)l{™ «¯ij°,$Fø6÷=[b^çzŽROSæUj—å`âýj ‰vήùMùÿE‘ñ»J‘ª’ñ.•Oš›dw´›Ôªçµn|©>¹Èâ{³³”æ]ÑÚqØx' ¼Ñ¾ßeIѦD?9¶!rŽõ ›aÁ3A¥®;n’çÄ6—èí$×Sµ³Ù2Á2GR¥KÚo£hdU QxË­iÊÚòúÙN]iÅ”&H¯;<`À€pš JE’šNùç)2š,f”“ÝÞyvé Êáàš–I¨ÏÞΞKI+)¤P¬w¢ÑAUõº–UU%¡—Y P¯úÈj¬¿qÖôj…W¡~i™E±_& çú5£s¬«ÐÉŸêfö~…Þ:'ˆ‹\ã2Dîhe½`öä<[КIL°ÎIDZ‡*в³·#JF ëè¼g³ƒÎ]Gå;§Bÿò`ï;ÿßÿZæÍÉendstream endobj 790 0 obj 3974 endobj 794 0 obj <> stream xœÕ\[s·•~WöG0ڗ鬦ݸôÍ[©”“M¶’rÉ^™›¸*ÞŠ”)W(R–([ʯ_œ+ÐÝ3C&/)­™î8øpÎw.˜ϺÖuðÿ{ùæÉg/Ƴë÷Oº³ë'?>qxóŒÿ¹|söÛóô@péJ;w³;;ÿþ µtg£?Cl;vþæÉ_w®éw]úkŸ~ÞOk;×ï^4ÁµóÜî«ÆOí<õ~÷—fÂØvݸûCvlö~÷e3 éÊ´;oöq÷{¸ô¢Ù;ºù<õýßÐhÂ>¿iöÃîk¸‘žƒÞ§8ï~íðéÔgêÉq[¼þE3w©©çîñÆWðéyÃíÿïüOiÆÎÛÇ޵Ô&}~ÅéolzxxÏw÷¡kG7ÏôvÿÆ÷*×÷iÂÃî%|ÿ!Íá¾ =‰àgx.½‡¡¼b¸¸»Kox›¾Î è%îÞ5û~w‘®§æx/¼‡6åñ}ú(7BÒlIdÿ•?#±¥  ¿€ï°4»¼…¡]Á5ظû6pñà‘1‘°qÎ÷tŠ °é-JbÒGŸþöÒˆ|hÝàDÜpã¶ñÉ˼&‡4ËëÔWþ†S‡9Dsñ#À£ë<Ž&ÝœÇÑÓÐó3¸ï Gƒ§ñ¨Þ«¤»¾ºq“ýÔLˆdq!󨻹õ5*äå—ïJäð •,|°“GxÀªÜy.íl#{ÏÜE¹1.Æ›ÆÏ´ _.Ö1øˆ"ùâ㈊Ët[Ån¥BqÐ=…G¬ËÿV'z×à°Ý¼û ö2trE{#҇ϓ`â´œ™b£ëÛ(Èøn'£ú®‘Oó¤^@¥èÖÒÁ¿lŒå¼xw8s]ž@êCFÊ’JSI²#Éï¾ñ ;&Æì´„À·ú–Ô-¼£wøBO‹E·Ì‹.µ÷—´¿q£²P {Ú~èZy½`ÊV0<î룸ñ>c–GL,p?‰>³JwÈ1‰^T«*šy©«¾nWJO‘Uöƒÿ¢Ð·q~šÇÏqð³˜]î„D +%¬ËO— zù k1*¬°lµÒQ…<ÀÄú©ÃÁƒÇ7BÏw²§¨+°“ú2á<ã¦Añ×o…²&ÆA*Ë·~RÞô-À‡AíÚÙFMágD'’k|枘&°5«D³‡"äëÂÉÑ8=Úâƒ:ÞA·Ä÷`^›cSFÈFÒ8«Ñ±[¦ ªPý^Ù6×í¿4êÿè<ÖQæígÚÃGUÍLy•YcKÜØOºr7î"òr1¡²bŒ@Ø/p›a#*æB>FÜ^K•$NŸ#Öoñn| ó>ó±6 §ëѾT½ö‰õKjáU¿¨æÍpVnpÃÆ³£ý—òµîo>©8l[ØkÕ‰Önš{±€ž¾‰¤Ñ0x`Ö7ôÇz„fWZ*Õ=Ú‹‹†þdK°°1ºÔ‡Lޱ/©«TɰЖˆÂˆ\p¢_±¾+šcíøyV…èìJ$”„sÐGKÍ1nÝ9`ö犊dÛ!ë‘ÔhÀF˜½#NòH» F²«öžn2ÔÅ:þ•½ºÊè“ ’gÖ™õKÒO(…ÒJYMy«ÒÏŽÜM(äeŒ®;ÇF¡\8eú!ª-S¸´ÜBOø«^ËJèVˆÏ°ÒsE"«TÓZb>,·ÒÇMÞ.ìj¿‡fÖ£#=Yé)Þ=cŸå2ñ2ÕŽm¯TûZ¦QìØ’CÚÖ1îÊU½cñ¸¸¥ÁhÑÜij*¤7~Ÿ‡a¸t&ú™U—¤ªˆ71±Æy–ê ½42a¯9 ˆ‰Þ>M—¾{'Œ€5ÕG4È»ÿ ºDº„qÑÕü*›é£>u6òÛÈ e÷ü©’ðgLoæ>kQõçø‰Œ&½QN‚º}Z²àÑoP81mÏÍZ@Q˜}oéŸc@2Œ7·j‹`ͽYÒ»…i*÷¢¸jJTîD¶ólº^gäèdŠfÕ¾iŒá²Ô’%_¡[Œ3˜k ³‹¼16U@iª°|wv@PÐbͧò+.À牷©]lšVz÷Ã,’è(ɰ®Î6È™èJVDÑ/T<ø#àQI¹D£ÓJ%üŠãß± 9þ½Îª *åÂñ¸×0Ä€T®\j&Éz 6Â")ÛŠf¥ˆÈð"îIW.³;l98N“, âšBOI‘m^kBQw%¼ØA ¿àË'ç¿ú+æE0 9ªLÅ Ä>MëEj£ŸéMŸ`d@€–Ýsh ”i™kéÅ2›ÿÓ}™âk…Oï‰þñúHûV7ˆ¹¦ÏQ>_p‘ã¶…)&‡`nãT„HiF=«¦ù¡Rì,òÏ›ªï"ÎI_D íë8½}P¨L«¹š«ì³– —†Ø ;8ÃRûm‚4öÖE¯i¾ñ²ÑL«anTêí“‘= °Ÿ–‰—yF$¸qÕá+%€4œ²dµj ~\ŽE}ŸÍÈÁÍôáMºû¬Y4ù ³ »SBø¥tbاz¨Â žVi•×¢š¼]j°¼/Cmr Íg¡z›ºãÚQÄpšvÔ è¶S§éŠKn¨R¤uD, 5c<œçd™oÒèe˜4|V!g¦¶fPÅJ߬EÇ%º˜·€9¾Ÿc/Bãfòâq¢Ï`Ü'»ÐDø|;*㳑Ô3±ÒG€Ñ°¼3gq÷çfîÌÓkî€,G/ßÓ˜Óeë—”g[j=TWêÜÙ@ª.»‰¤FD©QÎxk,Lt3Ó0#Ñè(¼ViíÛBñ\—ƒ®—ž¥ïWCOUZiÍŽ&Æ„X²émH“\rªŒ²%JT›€Q"+Œ# ¬Ìyô‡Ä‚e Ó¦ê)°q0¶éHÀå…Ÿ7EvGÞ‰ôf8¹ãˆyM\ÑLK\hÔ^åÜMŽÇO£òïØ5ÕbÕvuc#hì+ò«ü Æ©JµGQ²ð :˜Í†$›ò*«1·#ÎâìE2\âÖÍ¡¾‘ ÚA‹$L0.{"Á8¸È_Î >£8w ¨N%‘1‘¾$G5×­õ‹ –ä°6§(‘Òšþ›îED Œy¦ Û6΄áà ôÐ(^:»ú•°_¿24ÅIIogU¤­ "ìÉ0£Uú‚Lݱ(š³XSã{ƒñ›ƒZ‰¤nË‚-¥á#iGɨ!ET*7svHûÈñDaeïHG&°èô1t0íÖ‚Æè×E袎Ò^“£+ÏP£¨/“¢¾Õ Ô=±ôƒºkj ©Y?aê5‰¤>á|€ÖM˜ã}„g8 ËJ®9Ó»Ó;ý4ùEZÏgûN“N¡SiCɶFpUf"-36Žlb ÇE#Ã( ”îäŠòÑüÖÂ_®­u/u«„BCÈŸãî×Y#ýšˆ(XÎ$a°¦lÎr^ÀùJ7ÝXq^7EÙ‘Æ6‡\•äãZÔ¬rè6ÕZ´A€Ã…|º*lžÔYgä`K²zAâ-˜.B•àWsZ±¶o‚} ÚH̾ÉŸ”mD΄j5_=dLEŒ&cŽü7ÐÇGƒ›ÏŽòÀ#ψ€½Ì:©PêZÊ&ú¤•$@`Ïpa˜À…q³ïhG€bÐq§Z:Ö¯8Í0ˆ¢tv{üsêa9b…B¡úÙBxÖǾãÈ K•mmqa•­flþôâîTÊÅÕˆ1Ð"ŠÃ2P.!Žê{Ú@¡Ÿö} $}ÃTEeóohžZD¯ çÒd5dÈÑø)w9’U`cï9´ ÊҀĢ:dßœ°3®­©ŒTýSçL¤¤Ó$EM ¢HŸIöhÃèk±ûS¶êèþÊЙþŒ.æi¬ÔÓ ü²ÛµºèRÍ«]·ôq JÌè*Ú n}ÈOóÚ‰ª¦Sexí;²¼¦\Ö†RÐbÜG«‘•*S¢oYòï)jø)ß¾\¾» :ò/нcz0p£Î(Œ2ä¼™„w(B®EÇíJbCp“îê@ªYuX®ÕcéÎÖ\—X¹,¼cëK¢PfRÐÛsƒ°séÙÔJ–/*y’µ0›6·.¡u娈“,Ótµ¸i¦>N'Gç<ÛoÑrè·¹èÒ¶“²FxS×§žOÝC+"uPá)¾Z1¹·Â ò»P›¼F#}OÁ«LE«Ž®ÉøûħhÓ±v&˨ú‘2ußSLÊòcÄly®,Œ—îÇpbá$OÜèTd¸¾ÇZÙ,ÈÂÄ~/Ifp©C°+¾0Ä&ÍìÙÛ˜C¹†Z¢""-l&.’Dmw&Áº ~aø×Zߪ'…„GýMúãðÒ9ñГË×:@½<Ù^h›Š'Tr^¨ß—Õ‘Œ¼äðâšåc •S¼V‚”QÆS릟c¥%sÛë¦(íµX\YñQаø–÷Ë«âm]^B^}™E€OÁ_c?Ô”T’©\]³QkyÔ`ÖÉF ëƒ%±)•šX¶U\[«Z¬®Q`â‰%6R]øåfºìT¬ÙgžÛa<æÐë¬zËW‡E7—BÕù0k1Wê†Ç©1­Ïåq¯ž†ãTÎ1¼ä „ÏñáEp_<ž’¦ }Õ[Žøëa´¼Y¿!Ñï¾n&\®ˆßôŒ(m#¯§ ÉÓS¯WucxœÊ%/¤xd\d"^Ö”¶8uR ‚Ìßh ÞÖ“艕}£Î/•¿ll1Û|Q^¢‡ªK&9þ u6­æ|N¢HÚÃEE-³,އ†1F¢(c)öänûaFB9̲EÕþä¡G“†®DHzçƒDÏ1T•¾º•4}?¯YÜž›¢Ô·RL‹c(ïȤÀˆ–2´!ßÕ Æ áà0uÊÄîy.ú®9ûJ‚¤l¦N]Ÿ±Ç€,ï{òB´vx0û5|Ôˆ€4ê(æ¦\^1Nx§ SpEeDS^WÃñ²Ò¾Ýie‡“øBQ×ãß¶XKr$¶È'0wÖóÒ~MÄ«FW´$¢Ç9ƒ-{V©µ^§2óÜ¥ôÍKNÑR’¿íœ$Ñþõ¤»åg=¼;M6M JžZåcŽt„¶Òÿ6ðË{þ_KÀøFóŒwZ‚‡Õ ˜Ñ±çLéi]—úæ-ÚÛH/”ûœàŸWËÍõ4î4UZG-Ó¦M2ǧÇ:òp×Y¢˜äõ‚n{ö=IhQôVZ[o’¤Û뇩n]ÏÚH*¯i±V5úmü¬ iÅ2[G­q$býÎz¼nÎ2ƒÜWZäpc¤øÆ²z€I£ÕßK'ô>ÓCòŠT ¶- œsŠV¹;NËÖýc¾ª22u885iBÁ›¶ “«^šæ´Ÿ^À[)U%>LèÍÖS~·æk®#•!úâ¼'`ÅLƒÝ½6ð^dÆ5 .¨¡8 geÖܺ¯|3S6â¶éƒÍ³£lž U¾ÎµL›Nô ·ÀC¾±>ò1@Ûcšf*>!-d"h'’”Ôå°,&„¦Í“v5§•¥ÖFµi?`…¶ÿ±:SŠªHÊ1%Ǧä&øVßïÌïl•±ü{o Y«Ó’¥’ʶåJa ð$§vÓ4 ޱÆyQZrèp(—À¨ã#^wmÕ“ÄN+3Ê ‡³éPò‘)-M”"¨¨Í^‰=¨Ö ‡“G6^$¹\MÕß©¿š£-€0á~Syr¡åÀe®GØÔ…¤3…“ƒ*ºü[‡k’´¸Öœ(¯,­>UTIšz¥¼$Û¬dóU Çj¬Š+}Žž¬;^8RËmqÝÖd<ù§¦¯¹Þ2ØDJ¸þ7I'Þæ}ˆ,ò†!ˆÑYDk~G·²¾eð®ñÓ³Kõù•üHÄ|ࡳÖÅï£ôˆÛŽ"-¬p¶zÆKMüZv³¨ú»ÑZÈ>·Ì[(-S²pè„LbÛ¶ÈÛ §<¯·JŸädþ^“…ô*œËxnI–Þ?'uöÙ‹!ØŸÛ{—Æê’zK/ÕÂ=eèPõiËí}ßM¬»Páí{ßqu…ñdâ÷9]*¯×.¾Ó‹éå¾Ã¼˜†?³EÆ|ñ>_vNCCÔhÎlÌ?׋ç›=ÐèÞÈ.$…³Å”S 89ú«5“cšŸ1{·&†BÔr%B:ä®9áyc;_ö³&#Lxí]QÛíòÃ_êůòÅ/¶g*ÄüÁ ®þ»ý ?a×¹ mR·#‡e$ž¹ô(¾§l¡ºŽ\¹?ô¥!õdŸr1† ÁqŠy,·~5]W+å_¼£h~ùBâ]ÌBŽ_àâîå@þ¿±îâÅBé}¬4?E½sûý‚ÃÂÑÛT0I\±Zðo(AŒÛh„±$•Q›çæôb\»Øç‹­mn>94öøJÝlÃä¡f¯õ¢Ë§üÑï” `»¸Ê.ÄïÏŸüOúïÿ„Åã endstream endobj 795 0 obj 5285 endobj 799 0 obj <> stream xœ½[mo·îçC~ÄÁýÛÖ·^¾ì.™"(âØF\8nâ(HЦ-Î’,‘,;–bûßw^ÈápwO–Ú´0|:q¹$g8|æ™êͺkͺÃéçáùêÞ³q}òvÕ­OVoV†®ÓÃóõýè`,´´±‹f}ðbÅošõh×£ómg×ç«¿oLÓo<üMÿƒ¿À[ÎToÅØö¼xp¿l¶~óUcÚƒ›/»ù¦ÙÚͶ?l¶ùÁ³fël×vÆÓøüoá©õÚtÇe¬<„Ý<…Q4é—8R}üæQãÚ®sÎoã“'ø}œ·m ‘^Ã}-Ýð¡Ãñ‡ÍwÍv€Vk7k,|é­¡šàé­ËâN‹¿5½kAc[×µ#è‚Õð{xs„ÇøqƒƒÑÞ˜ÍkXІÍKi¼W4†ÒØL°õH¿”çÒø®Ùöã0`ÏCi¼*=Yzý¸|}U¾^ÂP]ºÉTù+Îe")Y½¦&;ç¯Þ…ÍóÅÙʸ¨dãÀ¤Ðþž¬þ´ù ?®ðãLVßühÈd®RŸ<à‘tR³¼Æ—• ¥gúoû8‚@ýæWiÜ•wΖ4 ¯›~ðõÞ¼]šèji$¦Ãׯ¤ñ)#šìªû¸ õ¶ÚÜÉ&àkóÁðëIµKSüØú¾ .8 €cù,|Óº@G§… ÉŒz˜Ãâà4¬·6€©z0¬žÛ¥ûŽZ숋õDˆLÊ¢Åõµ%}a žƒ™¹êi_°¾ÃWÏCãG5yÀ3äzÏc¾Ž<¾vÙÈvdÞÓ(´XüÕáVÆéŸÂ¯’¤ìûÄfÀÑá: cÝ)>8nPÕˆ•6d½Ãê”øg“ƒHª;i>€.Gôƒ¨•Q. o\6yw2p £jé u¡¥£V]Ÿ¬u>è±Ìû¢B„ÔçÑÏ/xpG§´kÜÈ'õsœ¢†'gÓ`¯±™æÄ‰Ð*?QÛè¬'ž“/‹²^Øø&Dh:b‚ J€í $Fq„êt\4€üïz44;?’὚ߎ~!k ƒ"ú‚½,ó&kq¿ˆ79Ù6ä<‡?¼,³/¾µÐ*ä5Š; ©]5“—Qu­ÉÍÜ­ž,5 cJÅ£¯KÔáRÞã‡É«ç÷_$‰L爋Êêß׫?ZäE…ºí“S±‡È^ö7S31óBÄtòþ8óBöç’Ï€Z'mG´¿é:eqx°ø[áÏncc¸ãKa–e…Šâ~ÀîtLÓÅΈ :=žƒ§é1Á ô•Ž1Ÿ:h‹„1|T3X‚®~¤Ž·ƒ.íç3jÈÛÉ•˜UÞñ-ЈØÀ ÊÐ5Dí[¢j4YDcêáõà4ÒÏ•Ÿç–»¸ÜN´Ð&(òíàűáü-1k:Õ\èd{?Yq≮4zq\–ƒàŽ˜ð@ €X<Õ?ùY×"ªéàHóû(•a_:éDÕ¾’b€»ý±xÑ4/låh;÷_Í››P+½Qåþ4!,Ä"Tú -ƒ¼¯ïFð¾×ѳý–F‘·[r’Îb&†a˜ÃºŸmË0UKN œŸ"²yH O•YW†Dçê\°òØ‘̱Ägï1x/¥#âµ;žxæ¤ rÞà„Þ)jÏQNøœwŽq—_Áu2[ Ê¿Vǽfhº’¬š®fß¶ð 3Õs‡ÀûõZ^y q-Ë|ÁO«6”–Ñin?m¡ŬO9Øðv9ˆ¸+Ä'+Œ@D™q‹!+仈% »9¤}Æ^ŠŠtç †¸gz¨]øOÚ;µå?£m yšA—]gs"3LBW»t}6ˆÉõQ"ƒ4éUŸ#¥›ÊÞdø˜â6´± ¾Ú–O~}Rw1šÙÿ Ó ìàT…*ä Àjˆ“¿+¶ð²ÃÌVU‚ ‘M=½Ã¾-oÏbçyóJSàZ¡l&‰]ÃXLA³÷™#DÀ꫟ƒ;«äs.•Íâ“nA]ìºþSàIóÿ hù“„‡òð÷8ÛUOA›B‰¤„̰8PÂf\FŒâòÎò‘D*À±±¦Ä««ÃZ…øˆ—8Ü ¦¥d"ÎXcšžÉW¸.1NÇãâ@]·H x•¤¿ëcgºƒOAˆ½)'é¡ÈQf2!h"³£€îÇi^Q¨Ã²zðÙD’l…Ê–;Œ‰ä’ p—03³|~ó»h÷‰KÏÅõ)I5mWåxèwnò<ɇN&æcÊ©iæÉZl;ÉÞ`ž܀ĵ¹o²­d¶ Dák\ yÔp£PÆÐÛÙ'ˆUi?±éÌPC™>C´Ü9QðIòãS¶’È[¯xËÛ*›dGWÙ-X¥‹d`ÚŽñéÃշ«7kçÚ C°eaíFk1ç‘xÃVž¯î?^Ý{üõúò—«ãÕ½Öfuï+ü¸ÿÍ—ðãñƒõïV¯¿½e Ê´4L R‡’ý%M'Á|u'†·W$o#Lò¿É;‹>F‹dÙ4k7÷Šk_b)ÚsU´çnFÔ-ð‹„|,‚85ëY¢Z”dO(TKë›b"Øq@¯ËYÒNÉ*»4Žróðx}Z™Ë0ö ÓØñ"ǹ½_†Ü¡W …ý” 8å./È—#í"?ŠºTÇ(aÊÇÑmô3$ß…4«ëf>r–*3óÒÀÌ÷0J0áêË$\­âã$û„U`ýƒkn~ÂvN 7Êô‚6Ëìeb¤|_ÌC[S1ÍŒpS<“Ðq£B<1f;šÓ»Ò¯P~ÖKõ3Þàzq@(®góñœHŠ2gH¿Šýæy>[N^p»lƒIÊÒ(‹tœSI:‹Q@Ž~Ý“º[,&¦Æ-•„1 ƔϿEr>¦­ÆÄ"Æ’^s)±¥g/•ÎÃ¥w(ù±?–µ«‹ˆ?4ŠX2BÒBw„oä¹1g¦ ÄlìP{ÂB) $Ð:ÊÃ~2y ‹'0Î~Ú«1ÂpG®jU•Æ}WÅ5bwèÏ‚PSü:KáÛ¡Û<’ƒö¸€‹ «¿K Ò%.bQ1²õÚíãÔ(dìkø:-òAƒfi ˆÃ, PúÐ!UѼ"î ¾½þ1W)Ã\ãܧÉ7[#û5º†“©ÉÐM‘èf&’u”%rÎf§5+­ÜÖ¼ÜuÅD5û ºÊÒëZ %¦rjëP'®®r¶XU?]o)¡ WjÚ8…6DÆÖqR+"´Ìei ì³)íc§ƒeÙlîRŒ;‰J¸Ü(y[Œ&”?khl í{Xv®MÓ ùý®_‡;É0² 5ãAìá;ÉË{I˜§¢¡JjÇeæR}ß¹’ÓAe zÚF‰ey×òéÞS›KÙ„}«Ÿ–ûJõ¸2•iº€r³¡¯¬§Nïô<±"7)g¦ GqU©›¨Éás|BÌ»-”¡<Õ ÄDö¦ÔO+ìPFXŠé(kÒq~ˆÆ¸‡ @üõvW¡3ù†ó€ÞrŠ¿¾¼ÄE°(Þ›ÃYî#þÒaaËìÛÑyá>=þ®hú©4~_ŸHã“E&ò^¾¡7®ï^y_*~$I)¹V7¨œºWÄÑsïØ_'X®jhÑŒ‚.“EwƒS¹–i;xã<|X>’Ƨ¥ñû%­ÕªÒùDnü°ÎŒ,êïP/¾PŤÄE¹7=)\Œz×7³riûV$Õïo§^¾à7¢áÍ5|ðÿÔðŒ0ö&óE9€TÑÂ;3äÏP„¹yŽé ©D ¹Ê@R»$S‡!¥!$#¡b44å”:ñ³æó"™²ú8IdÕŠ#ÉkXxfNÙ¥ÞKÔívÙ#"{XÀMtÌÜpHr’Ëw˜ÈÓ!‡{ `M¦ÂwyÊ%ݹOVËB0ï2sÁý <>mWà+½H ö\ƒÊؽ”ƒT¤ôŽðClnŠ?ß›€Š6!ËÅKbÊ®žW%ÒœžT2Ó8*#WÙnÇã.ïDv©×'¬ó›X!påRA¦–š-ÖÜR“„8X“R{n--%çA¼/ÉîêÒJìøÚÜû&UaIØ«'T8ž°e¯L SfŠÂìrȘ9ÚE\,eÀU{ÈT!iºœ^—%Ëá§Ù¶MÐ'±7Ѯ鯳ЮT ^ðEºÝpN™çÀPI,•ð†“ C¡f>¦¸å\¦sÊxê財ÛO ½¦™{¬¤q+·ØŽö²Êœ¥BMusèk¬¾§–µª bÊ®—8h¾rú½éXµ†]3­©t~®˜?/xU§Í¨j7¦ÛklîtEÜ(€T7,Õ½KØ]òNRjIø9Ä¥<ã,‡öÚÜ+–®ÛXª{ð hN«¤(áX’4{ªXù¤Ì2LmèýyÚ‚–¾ (RÙv¹Ê\’Q§«èÃüfæe²º¨°mâ(‘5*+*éÚKБq[åï¹ÚíäÜÕ-›¥¢ª¿,Û›åËùbDœ]Ä¡%Ó´É®âÄhŸJÛ›××pï= kü»˜¾·È䌺mh]Lsá_Á÷Ó{,=wm«ûªþÎ]‚”á4Ø!PŽûlFò貑ÛôWAÌáJA?cß¡6Lëz,ü ïŒa´Þ•Æ%.jǼøû7Zn9ñŸ^”K"/»‚è;3/Å£¹/Ü%cÅ<"ŸFé’©gºæâébÊF^ò1!WO Ó•Ò¨U×cƱM‘¡ÈÊ*}{J9…,.;—3GÎç'3€ñþ•¹/ÿÄÐÊú:÷•¤LE Vª;ä?ÊròJ‘Ú¥:’6ù»±:‘Ї*(µ¡Õ‰_ Ö›ª¸Áeú’þŽ×_coUBûhñ,Ýœ›ªÃR$F¶fò4»Üo|úTé! 0>êŠË 3…Ù™Šu Ùþ¾ì¤_î*°P‚î£\ÉE¹¨ïJP)%m¨îûíêß»9+ƒendstream endobj 800 0 obj 4086 endobj 804 0 obj <> stream xœ­ZYs·~gô#è{'ñNpàŠS%J%å’™å¤ÊÊEJ¤"‘ÔAêȯº 4fgwI9¥Òrg£¯àÍ¡õ¡‚åïÉÅÁO‡gïÔáÙÁ›‡åÏÉÅáwGy€Õ¹eL*éãç4SNæp²nTæðèâàוüJåÿã`ð»Æïë¨ô¨´_=¬S²zõh0qLÑ›Õ?‡µµÓ¨Ô´z0ØÕ_‡µYý4Ä[âêhX»ÕÐôxXkê|˜×þ LЏæÏÃ:¬þy¬]Z}ópt^3¯¤Ë\l¿?$•§š²øLަn•IÊbÈs£nª6~låÈ] ©¥…÷,´¸ùbc·ú”ÁL©ß§tsµ} ûéàè÷¿®®€M'ðqÝ3ñUáŸQÉÿ®jÏÔ¶3K4t¬ò*¡6®kãŸs£•q«'«ÚútPösý–üßÏË]û<:fÏQÏàãca™Õ.ËΗÖz°´ÿYOØ­¾ £n莥»˜{{¥Ûc:¢xF­KH°NÓhÁ¦×ÖŒ¾7âH¶kã&À¸¬˜>«¤µ4Á J]g€;¼zÃB\6}Ÿ»ÕëÜ{ʶw°&|¹ ðÚ\–†¿/òòWùû%¬‰c¿ÎÑ!0S‡q„“Ào3e4å-üŒHÁ¿à«BšaAXÇgRA&!à:»úP±(;…5λ]3ìÎ{Ѹ «¿k˜ýöu¨<¥§‘b0ɓьÀ±_âNËÎyƒ“æ#s»ÏËO“7ät@ïq…ìc2€¸ ŽŸDã9 ØÂkäв4¤Ï5.û*Dàƒ ^&eÖSxLEàF‹%À‰5³b]¡8’‘Ф¼Ry \æüDTÕ)/HrÊ#³[ã ̺LB-÷ƒHˆd¡Âd¿ «ÿžÃjS É üçR°Ê¢tž2aUAàP‰·èŽÕD1¬q2 Î8´ŒT›fƒ¿`¹hÙlX«„ñ8Ûv-D?:3=qÏyŸã|:Ò@;NìZˆù„©FÇ2JRH¹ÞC@"Sc(`·r¨p'UcØhdoáh[jIѺIB’¨÷ºÅdÅÔåuD¾ 6ú‰=÷‹RT̃c¡†å/¹Åù€\–*ð $„Çy ‘ß;OjqA^ßN¤´Ÿ ‡àµÓص³USàŠ ÜTClæþ"AXÚÊ ’Ë$À9?IÄEós.[{œÐH ÍôÄ ‹€\ˆe…Ê–bYÀ`«s“izgȾ·!]ö-N[ЊåG¬cž[똭“olM3}„íËÄ9¿=‚èÍn};ånTr4PÌêdÌE`öªØÄYáŸûìQ,AGª6׉3›˾Òi[ ^Š~ئ½¬!ä€*ƒƒ‰¼ q¦@bKglõGÒG3tj@Ë‘Ä.:C>'ÇR­Qâ e«î y4oýž k2º`.Ä8ÎÜuíœm"ã-£êvBç·¥í)p»s]°à‡’¾….SM,sm…)­Ü§*|QçMý…:·z0« IðE¼éáës´ªà¡N£5Êr¾r4D Lj˜ ¸Ü†Vúá67lÛׄãÀ}8¶Ç^Ú9#q_ ¬ Iº|$Ö)ñUÏjh6Òpá ÿfàÇäîüÒ„ç,=Vs°µe±mg'/F-ár 3Þ3ðT¹üev¯(0S„ã¿î‚ ¢LÕW4­*!µÕÐ @n9Ì;é—F‰ZTÝìÃî·o¬©DᘋS&6 ´ZVkiT˜8ç?ÂæßXž©9öɤc¨š Í%`d—Íñ“”M<òœB.±'&쨚›ÅxÝösÏEý<8'rŸ2*s8aíu^Ĉ<›*l9á´í fñ0LÌeY(kÂ%/~AþØªÑØ$Ñô´ ~ò¶ËΊJG ÝÖ· €*TW˜ABMªˆÿg€xÑÇ‹O;o\…cjB-& _[Èî³Îæb‡¹u€OæBµÎ’ÑBõ ØŽú{U:8­#˜+Ráî÷ s† @ kgØf<.ÛÉŠf“rtq{çz‘’K\Bl,CªR‚”ßáÿ× ­š’Ï ¦0sµ¬•Ì]†ýXÝ+PÒçãm9A‘L‹œ›ÈA(nE7KÓŠæ|Cžh£,©óá €BW¹x.KhMϸñ¬5f‚ó4Tóokÿ·­ê³X²\,±Ü¶èƒš«³ ¸™ƒÆ2 ` •뀪؟uª±ö?kýojãXʃÝQït*QŠÛ¨+é rä°TVBÈÂH”K4ˆ'¢Ê„1ÄUÁC‚Òæ+ü,nép=¤bðüâjÀÛ'ÓAqŒ¥RƒV=bÍžv±SK¾?©V×Û îm·nÖ¨¶8Ÿ‚5N¾BøâJÄÊiG¨`ª“Jô³ÊN#t„Ã+‘­'v>Iob:Ñåîº!©9a§Ó÷S˜ °”mœŸ@ª*c}QÅúµb5ÒÇ¥JÀÎV½Ò›}Ë"Ù²üûjl14—tCèí¶!Ÿ0-÷àáO»Ao_-z.ÍY¸ùÀ&ú¯wÛ¾ãì¹BÚvœÿÃĤg·ç=×ÛÏp;ìnÅæf@¯‹}ÔcC«BÔÄ!ÑWôtnœ_!p¨DZºaÝ œÂvk©WøÖÌ%ϲ­¡Ó²7°T$›gÙ`­ÑÏKÐ9|§18Fo$í9 Ÿ'Ç›XÙÝ 0.â²ë¬ofæ}KˆÄÁí¬*IIºñp— C$iY/¨À5op<=yEƒN»ÎgW‹3Jñs“çžîU$RÖê ³s<ߊH‚7W}&' j–ž±$áÇ=Yy¤z¶ò"$~2Ôx8ºš„ÿ·°£¤ tj%‰‚ð¯Ý€j—$°¾«kóü¢­¼q}ÓËDjË0œ‚† åíɹ„N¢¾DÙ”Ç>´T ˆqxC×—EH­ 3¶¸[aˆõ¾OÖ‡Jué”3ƒ]•œÍâg» ´g+_UWó]Qì.wê•Ë©ûì~(y{¤ä _U<†!¶/Ž?LyÔ˜©ï„75 µYuYº·zéäjLÌ÷$™:ÜJÄɬÛW0#-DÊ[Ò35;T`ÍÛçup—ë$äÄ%éwO¥ ‚%„œR‹"•ÐÐR*)á3¸eü,މJd÷*M%Cd…η\‹Ý¨á¹0aä½óæ€Ê å}ZöU^ðK;|óît#[¸ES‹%õGkÚ(éNýD¯f {þÓ†ÉQ–ûë^¬pZìd«Q³úArÞYߤòk0²/òJ¼)Y}D‹ã“!ªI£n¥©W¬‘B¥ \)à-/©¼2éÎùÏIY‡þ³ FÊåÒ-­GÒd' 6ŠÕðu»®—NBeúJÄ5Á,?¥­ªƒï4~·æÚñ*I¬`qGa]SORÊì â¼p"2W#žÆÄšë̯­&W/3'¸‚aY—YÂö­iÔݤ…÷Óm”újðµ¾êZƶ·¾º-S‚Ëïy +^ó|Ñ–»S/ž#¹Dðß—,ÙÓbè¾ç-Õ¶ L+!ÕûEòkâ<ÏÛÜWµñ¸5žÕÆwímØ—˜ýÝ¡të‡uÀÎbö”ØËÏØs9ŸYRØââï±ñµôXoX TBg~T‡—&æSÅgTÏ3\ó’l{!V/Ï» VÈWIŒ£Ñî¿¶Âóô fõògP3¾»±ú¨éjÿÔ Üì+Û•+QüãP‡äI6–"Ý+­¸]êoîOö–‰.Èn"®l—BΑP(­‚}\£ÍO–ö"8çÙȃ>Š(É‘, WñPgQzo0£‹J³]gV£Vˆ‰ ¾«Eyµ5Æ,¿ÉwcäwM +›µE[7f÷ò Ы}d€Š“ƒà<+Sþ"Fb9e$§ÛÖzKbS1“ã<ÏNu@Ve€šºÙMfc˜ðFfv.Ò ){ŸÌK©Èâ_2RŠmÒá’’w5”ÔíMÖ®›;¬¬N£|D'^al+4Ït0ê ƒ›Ýq˜Ðt¸T>Ä3²…ÀoÂ/lÊmãç^·à•e(ÏʳÌQ›%ž•|“X`3Ugž,ßá .Âcó¥}0ª7‘r4¶¼ wó‚űØMgq›• .s _Øù Ìây<ôí/ÑNòîÀeýÛƒ 0_4ªã•gïe½²U¤®ˆ0¦=e„,\Žˆ 7c ¡Ý¦Î0 5÷í®õ$|'‡µ3‚ðY=쵌„áKšð©Jô 6Ü»>…T8ãá’žUnn©´I7íñA¾ß›{uKÏ®Ò%d™ yø¨Ja¥ä˜„ˆºÛ» Q²—7 LøfÀ½4íyeP[±Ê–§t·Á*g—"û¦VP`łʚ3¢l³øª §Íê ˆ4Œl¥ %³*bN „2´lÌSJ¸²ÓÛT`&}â€5¢¬P¢·Õÿ‹®G ùúl^lk-fðûZ3+ÐÃ¥Š6ù¦ÓI~AÎÌVI6ÃÑ<:øGþ÷?·ë4endstream endobj 805 0 obj 3580 endobj 809 0 obj <> stream xœ¥\[Iv–üˆü#Z뇩´ºj3.™ii,áÛc1Œz£]?ôtƒ Ý ÐÀì¯ß8·ˆ‘‘ua„¨ÎÊK\Îý|çdývÖïÌYÿøïÕÛ{~2½úp¯?{uï·{/žñŸ«·gÿqo06žÙÍýlÎ.^Þ£'ÍÙdÏ&çw½=»x{ï¯Ó ›!þï»áÿ.þ'>åLñÔ<ï†1>xqoþ®ÛúÍwf7ÏÁÏ›ûÝüo·µ› 8ÿ°ÛÊ…'ÝÖÙ~×ãDZ7»xÕzÏ韧±d»yG}Ðñ—0Òïñ›ÿìÜ®ïó›ïáÊ#øˆ÷8ows˜ñ1XÐé6¸è`üqó´ÛŽñ¬µ›Ÿ;kð‹.x|êygiû%Ѷ¼ÿ­ëwS<&2¼ˆ«û7±y‡Ý¼ï¶žú+Â×qÄÛ¸éšÖôÎG"xâ™@ûý5_k|\¬«¼ƒ9ÞÄ?‘aÜ|†‡a’7ø?žŸ6¿Ä?sli¬Žq/†üˆÄ1gæû`áÂe¼ýmœ¾º¨¦Í5<S—=nq±iØ 0†û \°íÙ?u@x;JÎ`à«ø?=ã"Y€‚#HÖ@üÜÙÇî‡x M7ý©Ã ƒƒ`?Âp|ô±“õ§Qa>Ng‚]Üà¶qõ|˜Ç¾ƒ$À|Ìi²‰c|ÊžkqˆRxNâ¶åmo‹@%a÷q×D!xÙÿ*à™sXNÀíß =þ¿"£ài …‘ãøØeç¦øm°@‹”w#ÊZšKÎ^~Câ4±i0\ÛÛÎÎ0”)%ÐQœõIC‘€+ µðw!J0ðlæÌw`̲ä„£ÞëáÍUò–vÔwfÜ9+2·¾áëĶ¥ü3Ç3g÷²]]ܱð"¢¡Ù1ûÁ¡@½F¥gþÄiQœñ \¹Šëû‚,Ö“myÃØÐ­¤ŠÑRØà4pùÝ‚_$ó‰lz(¨KÑ›y l‰ìhQ[cƒTê\Iì‰ÎóÚaÆ-]–_IŠÐpLóÎm8öHU\(ïEUdøwÔ¡yR¢Él}K+g¢yz´Èv‚ý¢ì3Ùæi!H¶ÌwœÜ(v[JÝ»b˜÷pß<ÆŠY⋯˜×Åaý°l ɬ‘q!Ò qæ@bIöUxᆠǃӷÌÏ;<âZ6õb†˜¯X#£hü)>ŠQÂðñ({C®ù.}K&´¸¸ßnl†I“LZ‘ Û#¾% …Ó”9ïÁÈ*£â0 HÖžWŸ”éV«Á¯bißÓ½…ŒdFìnJf¤å¶ˆ¶Ci ­¶—· ™@—ˆŸNü[ôOÈkðIíò6 D”q•è\g¯Å¦AÍ’]c-o+Üjé®>K$âñµè°„®•ÑwZ1ÉÆ%C_Qihz(úH-úÁjŸWËxet’·÷…%“ÁáÁß º»#ïBDf{Mfúѽ‹ý+•x7̇rZ˜QŽË`+Â"ôP¾®”!/,ìœÍ]Z—ñ‹s µK Ç¿H (QÛ‹c,; <Êðt`‡ë‹£ Ìž'»t?ûlºC¯ü/’ •›v‚Ô ;ûÚ°0ô>y;6º$m«˜âÃ*\ËRW…t°ãÞ¢ªãD¥âÈ0æq˜,cBq µY’ÙÿMrÑ9ˆæÃŸEBìL2ã©BUz 7ÉH¿NîÒÜlPÙbv¿áão›ôà³ì…þÖŵ[ðAºª|Ôe:ù%Ÿ|ݺóNŸä£8äY‹Üy?>§Ã˜'áêätµ<>F•cDZ‰”5FÉDK#3¿O^ÉM™ûðý|@Þˆ),=§Öö_ùðaº¾NCg¢@÷¶MƼ°ë/óÉM¼à‚¯ˆ÷0>ÈÄû¾IÝÇj…›|ó:uI?2•ÙJ$ý˜DñVä³ýÔÃjŸÂ÷Ÿà㇓ÄîC¾úq?i®[ú^_úÕ÷:|‘Ÿù¤h9ÐÇ‹nud$—iÓØþ4Ÿ½h²èA“‡Ï¾šEÿôëÙ‰Æï/ó÷O‰So„Ù¾oã¦wÔGrD·þ°\¯W4¡ƒ"b£x«r†=ŽœLK󊇷-Æn['ïòÉ7éd<ò3E¥ŸZÂò¦õø‹–¬)R4¸r?3åQ>ûý‚ÅŒƒÈ¬/ÉR}ÐFÀ#¸7b®çb×éž§_Ç*E¬/-…ˆ‹bÄxÐòúÛ®¡Z7- Ö"YÝãá+/¡Tg}Ûróy±®uâxÚÚ£|+—ö3ô­wÉô¡.}£7Eª5ŒCÅ*´Št—Úƒ©Bõ”·Y²ó¼EnØ•\ÅãO-Ù¿jÙY¥Žïy§aR½iÔôp7Åð2Ò»ÖLYοYñ€Q3Ña¯ÒLxÝv‘Jž.(†ªË?åÃuÓ—b•R„¶fšvÁW©RæÂ»‚¶K2¼m̬yî¬ä•ØÓÂý-'Q:þ{aS ¦ZÉž,a§ê†ŸÛdQÊ©SyèŠX ÔÝöý"âÍifJT^œŽ‰ pÂû¹ˆîL¤«„Ô9ûœ(CàôÓVrË”bxN(o${*¥Ûû"¯÷#Zmï)÷Ú›ù‘mÁ-Jê= qýòÔ@ø?Ì2ÐÒŠÀ|PhW‘½Âÿßq<# ¾ëwÖ‹àgt'g$H6•µ@ôœâ\óªæáTÞOᘜUZ}yÄ`œ0?§ 3Þ3¡õ_ІKü%Õp€X¾øa˦æfH©f˜þ×"‘’fìðÌ=]7§¾FÉ «•ì…Rf;å :ÓÉlþ9­TRÝx6.vÞŒ°ž~'ÀîKø:7³æƒqƒÅ]elåFƒâå+¤b:<ÿŠÓùÈŽRœnŒ!3e)ø5L–u…œ ƒ›™ÜѰ— Arl@P2÷«z/ÏÁž*°€ €~ÎHî¯YMud‰B% +s©w ùÈȬ¥i„gµXèz!1hU±°7ЅסèÊ…W‘g ²‰ö]…PTä±tNmX¨Zl[<œÏ@m ýÉŪ\¼D«£‹,†Mlý Ö€í<¥*h3£t–æPÌ_wŒkÏêž,1Ú½ Æ’ª,QÖº0é4ãÎ^ꨆùâGáƒOU2sDÒÌåRµÀ~¸*¤®Æ#YTÊ´SQ^ddÊûîXŠþRô¤#}æ-È –Ú·Ýâˆàl²€+.“…}vƒ ržp¼Õɧ1ONƒ=΂Üu9hvnnp9PÞeFÄDË4ûš¥lT¾SÕ¸óDQw o>±Àí Wã"sÛÇôÜh³ù†"‰¼Ž–¦WªC‰Lj빸š!à´òÈJ (õlQP0P¾VnžÑX¹s!<-ãÄ ’vE¼ÝÒH¬±çÑÖ¸RÌf*Òh*kqò:6‰í³áèúø†‚0ë(Ç›žTá ,ü§¤f8ÏÒôd™’1"_Æv\jÛLqÌc=›ÒouV‘È®-ˆéZÐáIF+êPŠê{"Ú)5 ùžxÐ …ˆ6±Ã)q]ã Ï‘¥¢M•ŽbÖQ…@ßS¤Í:èc³-œÞ:4u -\+ú¼wôJ“yGÅäo8o8΄Ë!r ”­‰³4¡|ïNî­)UÁÍéqÜf¡¹ÈùVff¢GqXDÛ ±`µ2ÕNìŠPXŽP"ÚEzWDÈ`NoàJž’·\šµƒ NJã igŸÝF€T&y _gçE£ yÇ 02ò5u)9ÊÃ÷­‹6lt®«F„–4”­R„WcœƒýQ˜S yY’¿Õ©W!7E" ÈMyZ²ê¦¼Û »(@NC\œnXíó<¡8˜I!ýAÛ˜\”ŸrŸq'.x¾ìˆåcÖ E§®eOÒè4%-giBPú‘Â2‚:(zîeqj´©ù@fW'ÇlrTÛeê’P Y¤T2\y Î@`ÁU*Éš›ˆT‚þüŠ!ãÁ8x廉ÂWv·ZB¿3 ¡%RÚ(¶"6Åñ;8ñc'µ=#UÑaóïP¥#é»Äß ˆOZnâŠmÍ\tñÛŒC?^©n,O–Õ \Q?Z†)—Ag›hrA¥£Ú–†•Y·YýQÑnLW‹°”úÔ1 Ù@ƒ†¡È 1ñ«ÚcÇÂÀ°U?á|aV £’®WÚPÕúCÆ}D¤ÄS^ Ýúúní-ÎÎê–L‚TªFjÆ*È¢iý­ZÙJŸ æ°×1ê×Ç0DâÊ1³nOp£ÑÏØè[À»òÃóŽ!L´0va\€ã‰áè¬Þ³Ö…ÿWhî"0%|ô¤͆¾F¡A¬Ð܉‘ð|õm«³¯¹/C'"(™ª´Ý^–%f÷¨° RÛröžÐuàå¾¢¡•ôR;:¨i¶ç¢7· ¸¯i8Èì[¹Ë™«rª#„ÅM&·ÚŽËávðí—O<µÚæémš„(›Ñás !eⓀᑰª#ÃÕbKýR`ÜÔý¦ ¥HngCa¦Ä'Øè8Yp™Fìã-Ñ[ì0'±®j€ )Íñ¢÷…æìR¨5m|±$+º´¡Ò i1D@£«,/Œìꬲ±©ŒùÊ4#ļö®E(-×CF­$’ " ÿ)£ÑâéY<9Âsj”Åêï?$k­N>._-ƒ5f€(?¡¥™õ†›"ig­n>%!ÝÎØäË$sG/›å·Ò*¸÷\;VŸEPIÂtŽŠa+ɯµ´&mAq0A`ëÈ ä3õíJ>rŽ”Žh}õ{E¹ÁO„c¨vñw|³ ŸãŠ«@ƒy©ô~dž.'áÕÃåø™nÊ `Ù@¯üÉ£:{éiÎ&&ÁP’XÕ`÷àU¾ìú~É> ,së.:‰!Ó(ouì+éM£ .éÁ»S¡'´vŽ”)(óB6½í5%íGÑ fÃnÔf×3Î>86ÔAEÙàßZ”8ÎÏš!¨36ÑÄêÇ/“ ªZ´p¯%X–Ò¢ OEQБlêê88`B䟯Y‡­Y¾·©è$à.z°s)ˆ( üŠõ÷ŽÃÃF“PRxc˜ƒØ=L¾[(ˆöL’´ŽмVöà–õ:Dý,«?j’JÔªe¶âÇEsŒ>J@ï®x³ÙïiFm­7ë½EÅœ±äÕE!Çqoï|:4¹om‘D9ÂÀ ‰zzxý'¥•ÔÉó¯$q2û齿Éàš+oÝSåu0 ²©õC†+ å5ÕY¥×Hz&b2‘@mò¼õ;y#rŒÐÅðõf#6÷+Qd##‘€Ê~ <¼-8àË$ã1fK(Q†*+†+i¶¼ÃL"˜Àƒ'«ròüú'ºy´ ¦UWÊR.uðŠÓdM ¥e X5d4E] 7 Æ‘ä½ t‚Óq×§lUÛ©¥½4-H'äýÝ â§z¯öA‘E¨TÕ‘ „ j½. vgûŒ,¾”_Ç)K Ã.-ãk’¨Å¬Àoø•™\kÍ:ïBM¿l¡·Öµ‘>¨ƧßRiÙᄌ9rýS%k“do»ü=ý#8¡Øú¾ì â—zoÄ5†Ä¦OÁ늶sõÎ4Ó*GæB½nBn‚ßœ÷-Ó¾Ô´TÑ7¥:ÕN>¿sÐJÊÏY¢M ¢“!Eªr¸ŒÏï HlÀ§²¬•V¯QŒLmË}487[€ÄÀÒ“¦0±÷U çÄ€A'y²ùÒvÒäßIDF†ÊsçÁŽ^õÓ/Äa¶B£(ú¶ é¯þ Fþí©OÜ1¸$ „vxB9lÒ—P䯥• G]êe¬ÊéÞXiœÙoâ2®õEu5Cò–¯Ä<±:¿Ëÿ›Ó{³ ¡7ìZ(Å”âd²$4h–ëá¤@vŽÓÑ´x}¼HNókb[ˆ|Æ™;¾ вWOÀv!ÖÞíÆ‰—–0»ñä•M:õ"÷ôÓ=˜cóBèõÜ~F1‘€€å ¥äTAà`Ñ©ìl‹^f)qqƒÔϾí£l<ú¹ñ>ü:ÜùŠ€ØÑ«F‘Ã"ji¬ã¿¦[q´Ñ½/uú‡=…s¢QÜ÷vþFo¦dðÓoÈù61fàvÄ]RùÇâý@÷o:õÞ€¯,ê/ý¤KeÍTžpÈý gW³4ôLùг·˜‡*Pr+£Mx—=q4“ ö/îý%þûHf> stream xœµ\[ÇuòÈøG,lšŽ5ã®Kßä²ì(,)Ô*Ž!ëaÉåE0¹K…»²Aÿ=ç^§ª{†»¦ Úžéêêª:§¾óKÍwgý!œõøŸü}òêÁoMgÏß<èÏž?øîA ›gòçÉ«³Î¡A ðÍaé—pvþì?Φx6¥|èãÙù«_ïB7ìzøwè"]ºÞÏ}8ôaØ=êR8,K »Ï»8–yˆ»?uû”¦CßO»?ti÷Ý>î>íæ¾™wçÝ>ï~_=êöo~}ÿ;>4SŸ_vûq÷Þ€vØûœ—Ýïð9j }BOAž¥ïvKFéžn|ŽWŸuòü7çÿ 3ÑÏ8á0Î0éóK™èÀÄÆ{¹»Oýa ËÂÂ(—LS{ƒ/yÚåÝøw ^Á°q`0ÉKxw©Ù3x‚nÿo·v¯àÓfR¥—â¤\7²I#7‡OÇä´gL¨{|Ê7P3*²ØßKÖÔ÷¨úrÕÅ‘ˆôª‹ CSµhÕSL(j›nJ¨½•«hÀ»*Ê$ œFœïà£Ë'Yü”r¥Q8Ê%G׉P5c„bÒüîÅe™¦h».±nËGÑ3^ Ò³a™yA.H!@rŒÌ3n£™ó–EŽ‚Eý¹æ–¦û.©"Ù領›J„O‹œSbĶ? ˜É@zLŽ•*Èó4ú_µå'ZPxìø¢V?¤<ºØ±'·_ãKD4 Ò€°:\Dƒ͇¿.FåÏÖX-IïMI,ÎYñ›ÖÞ ‡ì ‚y”¿IþæòdÓÿÁ`ñù;{÷=ã_´iÁÕȪ eã2€½dË’""npª)² ɪ"’ðŸ•õU<°FM‰hˆæ#ø+º-9æÜ$,©`kMê7‹é®WEý»(—ñȲ‚˜ÉèºýÌakiñ)€4‹þ* ˆ#*Ë{´xDX2»ónN¼q´™¡ŽÖô5ÊÉ&Œ³#ú –lå> ´‡ËlL+º™5/ø×íáÈÖ Q›@'lÐe\' ú@» 4B‘]ZC' õ¹FöÌÖDIŽLÐÚÔ 1$O$à+µ•q–¹Í0\¶ôvû’Ð)͆ÑXϸÐãEux…ì%ú¹è¿æ!(š»Ñ\ªV@^°þuÙ3¦)dÊÖLà G®è^Ú Îó\k WÑÅ ãFÕŠ‚õ&¬ÑmqqãàÒ¼á.P>ôOD}°£¼—b»ƒÙó˜R“ïƒoµw1*Ðd@Kì xÂÈÿWÕ2Sg0úafkèO¹66w€~ÞW¸œ¨m4àB§1Öz57­3¼5ŠÁn¡Š+mö €ð ÈAÎÏ'Ð-z_J/³'8WìoôÖ¹iE*Hš0‡ÂKeæ5ìz&—¤;˜†ü¸,¤Üc¢ÀÑ…¡p̸\U= ÷䤲°(³žY~mìx„â{Õ u0´ È=h8¸–n“fws†}Z‰ËAzŽQÌ¡ð0µÑÏ3Apñ½p8²'}ÅÓž”—ŠÕÖfÍÙB+œÃyÊYY]5“õ$´q¼ƒa×5¨‘ å7 ä¼P[6x9¦d{%Xà=k@lsqÙ±b𔇢µG†¯ ¡U9Üe¥¨¨ iÙôcH¹iŠpó‹òü'Æ' ¥ Ç×б®Ð78¸E4D ˜y[Åÿ1øº³©[íº|>â`M-Ï+ 8ÏÊŠ1ˆÀ´‹¡6C‹ï|“¢*(Wûçó¯ ÌÕi‘k“‡EÜ8{2%yHº¥ó(룖ïÍ #:©?«ý[3ü‘Zz&ïË?'ZFÝ0óÌøi#ó0r,­'ñ´UW:gšõ,ÝU¦\Q_[Iùº<°bÈx©Sw‹÷^ÅÁEÆnØþ¢§{rÛû¹apf4­#1˜L[?x_÷cë‰"xìÜJ±ˆ22…•‹þÖõoΰÛrµR¢¤¬=<µ6 ƒ˜ŽŒ¼€"ÍÔËßV€4-1s_‡b¦¾à6wìË–¤?@»Û€ÓjNå9³le¿ÇY¹)v‡jt¡är¢`"7ÌÅé\ý¥chË÷Ëa’™Œ)R†¤á0XH济EPtШÞe‰z-MµyÂe-’–®Õfœ©F<ŰÒÎ(X•¦Þ™FÒ î®¦õ§Ø›äñ¼jkæÝ“¤“ŠK|gD—øca¤ý¸A¼úžˆ°WÐ~|Ôø‡¢·Û;f¤š]Åû”dx‰ Är’ä ¾EY“) n¹Y£ÉÌðŸØàÊ:Ô”FøuåÊaO}¿¨NEwjyH¿_K®ãØÊÓEsîe¨9+žà‹«S¢ndŽÒÈÛæVA¥ØiÒyÙª÷aÌi Õú`‚Êùr~÷­Qœ øIÞóY L‰p¤Å¤×¶qpޤP÷•¹¹k7`ÚFâr;µ/ø¢8ÂÇÜ0ÖŸþg—+pX<ûø®GlÜyTÊk8ª}ć)Q˜íOlS+h¦çÜv¸å§¹X€ÒKiÓ*øšþ|hÊFsn£¼ b"F…£åÄ^%OsŸãHÚ¥F/ÖF/Ǿý¾hÓg{Ém·÷1è›[WÜ#²­I©4œ¢!œÍ"“%‰D¯ÇúµOipÇÊ”bÖÑP^|Ô ÏéÊÌÖ˜•fÿ¹¤r âAl³ œN÷Í ˜Ò@QÿÿHºÛc¼PáÞ–Ìi™µ± ¾nú£‘4ÉÆDC}ìõ¢¤wÔ¯Ó¨¦Åv6 ¹xpƒKŠ/R ±±NUá‰9JózÃ5­m˜2 Ù c^eJ5¯²2+5iì$X;—Y,:ú>©‰«ˆ‹³Üä…ÉÉ‚·EzO*P’ˆÜ¶Yx-÷÷—ðȯáß/½(›rÞV•|6•±òù†bײ†$Ô„Ó¯1ËïaR¬ÄÒÇÁâM˜Pî„mïa©9þþéƒó¡4~–øÖ«Îççq'OÞáÂ|ŸЏrìñ)Z1ÎÔ’‚“Ygã‰Õ½ð6ã:«Èó¢{Cul;îÏÊôÖ‘Ïûó4ÐÐÇ裴c¡næyp$VfŸ!Åóg¤I{%5ß[(bt¡TîŸo¢‡!oI‘–o;щR@Ï`~Ô* ”^·àWo]IY$šár¬v Ê]ñœkø¬HºÌ—ÎD±ÛÖÇÍœeòp©©tÄÄ ª¥7X»ªÑµBÅïIeQHU‘A¬|†[• ÑéÜ2œ>k¶é¸¶þBOºØ4ÑœºXGÉ"óa3 ïZo­ƒÕ µ DaîžÍ=Ê÷-¾Ñë讃! èg$Nõ™±GÅ}B†â4Hæ]k)‹OÌ€bl4Ú5U”£ .ä”,d„ü%'ÛdǃÄ[œÁ8oV ˜Ç8Lw)%­f®¯!\uéJ¡ì†Ó†(Œ÷sÑ*¡¯¡^};|6æ#ÁÕðF‰ÔÕ4,³Mš¡R×{q­yÁhŽÖ­¯ò\•àÑ8 C®@QÃÙRÊs:ìÓ´IîàÆû%X£xõ·ÂÓ!nÐÄÊÞ!½Žäš„T-œzüƒêxâÔ·5<°Œ½¡7–ÎQÇG ߣtT¨$.Í×á^øòqRW þØ¢:h`ÃlªTz=Ëu£-ëÙ¤’¬ðÎX•âXè+(Õ9Â¥™U謱Ód¢6JDÑvIdöNuBJO wž9-óý+>5:1Êßð³T|~€ùÔÅ2¾ŽPc.:0õ—ªÊ²»}Yàigšˆ6ìÂ{†7·ã”[™>;t%®æôy‰cßÍ­šÛ8ù‘`¶Ò…™qŠåDu@¸š©þ8Ö­²7=“€%’29Éa”Þ3hï(.ë£Y5µK8ºŸHc}’3ÜW›+WÅ¿«ú@U›ÎrN›5ÊIJö¥‰ãsYh˜Úõi,yejùl¸M,ªàÝY¼HQ#¯Å?OþÅݸїz*”[úk²7#x‡Z\Ž'Žc1¶Bã\±Z‘‚ÄçbR­†ª:0a–¼©¸V¶±‘.‰™SYfä%™4¶fû†ÛÚ©“*u¡œ˜…½3»<ŽGéÛ`+r Qun,E)õõPa¹%“Il(ù•ÿ{,,Ñ´™Ä²W®Êöˆ2Iœ®4ï^xÂ>øâ*l…’'ô ÂЄú´6"á“}éN~€ 8¦Z{ïú·A²²„S•ýV…ììF]kòBW.³ÕY§¸&·8ö6{É›«,ksø#çÑŠè×®]ÇÝ:Š­MÇÖÖ¾Öp¯ãx‚ cª¶ÀK9™ñ…‰ü“ÒÍCûòÇòåÞ¾LåËŸôËíSàú–• ”t†«„i35Í’¢ÖíRÜJ pS\ñ4÷%Iañ‘>‰áªË¢ëƒ%.¦œ$‹dmu,¤Â Ñ*Ü¡Wh*NEßçTXÀíùœÐþÄ6È`>Ñì:ÇÊdÂócð¼&oŸ4ˆÇëÈ®íPúE«2ï£u1pXo#iªÇCŒÈnfü1[ƒrQt•ÓU. ZÛôµüë„d@lO[U²£Å'÷*´}ÒåàŠ>ôxN?4„C¥{­E´S!ÌR)|Rç;µZ¥\Ò×Rq¡U6-Ò%ÑÀ•Œ\Û1LSÕ\3UåÑâ@=Ó¨ªe"JªEhëúXšd® ÐoZ™ØÔÇ­Œ¹ØÇ|(2¯~Ê!º±Øºñl8>:Bôn¹;"9BÌÿ[ñ©O¢TžÈ/ -ÜJ •ªúrB«.åÊ”ÿªÃßþØËÿÄthÀ’ÆŠÐ’ÄCþJC¦~Çòs«¸25ÖÚ Ãáh¿D°Î H+Ž-×%Ü«ç}z‹Ýè(Ôš•M|Ã7Ñk¬¢ \mUr$ìVû:k¢9阦Å8yéìQßG$g1µD'–s²®¾ÊûÕs\¦±]r³ѧ;„òZ^ÃÎß#÷y¹ü”/1÷Uùöåò³rùci»ßlð“]n‘ôAÓØžrs¶ UˆfÅÚeE«M§#)©qeÄH!n ©ÓÔcÈ 8+nžy#ç†ëé^Ðÿ­> stream xœµ\[sG–~gý#¼ÐÅÒíÊ[U壗±wذh"f×ã@X" !ÛÄþùÉsÍ“UÕ­x‚ZÕYy9ùå9ß¹¤~9éw?üÿ«w÷¾|6žœ_ßëOÎïýrÏá—'üß«w'ÿuZ8_žìrŸÝÉéO÷èMw2ú“1Ä]ïONßÝûa㺴Iå¯ïÒ§ÿSÞ ®y+ç]Ê‹§g¥ñãn7îÜ.ç)æÍWß|ßmýæžÝmå‹gÝ6ø~×»ˆý÷åï®|ë£+Ïlÿk_Ò…ßü¥ôú§Žøô”J›¸ù¦ »¾!nžÀ7ßÂ?¥Mˆ~—§Œ¯Á„¾Ófðe€þ‡Íón;”§Þoþ·óåCò_8í¦ˆoý½ó´üéÄ•WRò°ú-/úÝX>“\·-Ñ÷ýK+Ÿû\^ˆ®¬±ßMaôcjÚØÏÔdòeN©ˆÁ•(3ýïòtìû˜ü檃Á|_äÄ]N›³òqœv¥ãSè,ûÔOãæMï]Yu*7¯KÓ©ß••ƒœÊÓ1ŽÃæ² ~7æ8l>Aï†}]¤ßOSyøÏ"ÌÝèc˯ÝPžö¥§¥Ï<†œ7oaø~—ÂXv¡ÌxŒ>ÙÑßÖ·uOo%B™“ß cYó9LÙí’̘ú­¬=&À_é² ßÌMÇ~_Oc¦Í¼ý¶ŽGï }´“4«¸¢}ò®utE{’üPD `øöÞéù`eÁ–š`|†“þúræú© 8aó[ç§‚\Ùó€Çå§ò±LÑêJóKè÷USe®Ð6ÑÃk#cŸøÒ z@|Ø|mÞ–>àyp®ÎºÁ.@î½ÇÃõBº=ã¹”naXx½Àçéj·Mo.`o/ághu]: ¯¸A´~ F½\ŠR9Ü}‘MSß óGtäH (~˜Ä;YkXþð銲›#õñ¡«mà}GèLö æî³.¼y ðJpQ .”JO§pÌŠ–)`ÄÑðŢ·1lY[ÿjq4ð)G¶ö&ò¶þ)ñöÁÄ?Bó„Ío)*þ1Ì §+ì¿ù½ìÓæ=4æ£Ýºkx:ô5ÂÏi:F® ï Ý ÆÏ´Ž>íÎÉRuF—N+L#žíãBàö LÔ$ú¼³8Pd¦ýk; %8 ~*`ª¸7¿£6ê‹Ö*’ñŒ£Wùq›kÞf’_9ó[ùæ žMéü‚·&»2 ßäÃ%Ÿ34µ­ ±“òDKÄ·a“U ó\jzttе1Èä=·ê§zÈ®¹‹ª¤Ê¦Å>°¸öîkäKkZˆ=‰!Ø“€"7gB:<Ý‹:ïR~‚ÂYíUŒe]øÂ ^ºR!3|Rñ~Zwé94õˆé B”ËÅL;ÁÔK9}fbkPYS@f‡u×ùDË” p.jë7¨™¨™€;"Í_ißÔI;˜ÑA¢º‰©”… ne‰­Z‹Eý‚›‚Çœsÿ¿‚filD íÃ~F´ŠØPá·æ)”åöcÔ‡ÎèÁ÷µÉ!-ÃàÔbDüŠ(RÉÔÀÉŒÔÖdŒÐÌR¹w‡÷ñ²JñUé.õ·(û¦ÆÊï1ðô˜žc‘=Ÿ]\Î?MhyÛùÿZx£î6þ JxH¥‡anáY; eY¡Ä'zRÆqߨm¤sù›’*ƒq—q7x¢¬õ¥ž)û"áA拺ƒ‡‘ˆLÑþL•úÜè VwÇžGúycwa:hlϰçqd fOõGÑ.lhõ­A(„Šôöf'!# ×”yÈ7áœx¾Ž´lÊOÿèÈ´F4 £ÓL¤LÛ.ˆ¥hA6Tt2 ]ð2}XŸu€†åqF®æì”MØTfBÌtØM‚ œfRL¢>rnÍŸh·È|¶Uµ†/Tt!ñغUÓ/µ‰ØìôhFp NÜŸš´zÈS ~½"_'Ëü¤±¤§×ÊwIÀƼ©‚Úax] ©@<ÀÌ~›aÐ.ÁÙ% §#“©AÙ êàõvTw\2ìÜPQaXæm(S<¤9¸É§„ZáÄ£’Óýl¦ ËÐUÑ ^ÔÂôfjTig,-Cp¿—RØöAdy»ŽEknu¤¾%<*ß¼¬€yÄ.*üD4¯o³VO­Zop ê#‘õYe1‘._±\)Z.Ù†-•AC¶é¯Rb…»¥iröõس11dHà3„,øQNû¹¿~œ*U‹Á¡ G ðLÁß:Œ«ÅèÅå…gòMç… d†¸Xûšéã„Ñ*µ˜‹,ÿ/Üðlaêø‹s梲J@L bÕ*M°ÔFð”Œc.õ<ûT½ËfÊ1¾–СÙ,Eô™v5 V“À@LŠ‚›¹a;³|XÑ9á|óŽû)”´€šNÏ)ƒlØEX#Ë–‰áp ̳Áòï¬íû,2æðÚlxmë‡Ò¨X›âI8£¶Mdy·üSãøã[ý¦…»ºbÁL÷nóCYf y¾k{£Ž~ª²{S?¾Õï_ë§ûÐ1:æ‡Êó®-¯½o"'в˜›Õ×ïëÃçõõS}øU}øLžÖ‡õáSýômýú¾22¹eȧõá÷úðq}h¾oG1ý(òwøÑe49?[O ¶›±Š›; 6;àM32{%›ŒŽ“+Èœ’?,>,þ½`yðo˃5°Ü2ä§åÁ–y ¾Xœ ؀ē¡ázGº|Õò{Ö£÷;ØC_¦âÜòX[uÑ•ný ú4w¸6ö|†e<ŸToi˜q"ï噲¶YŒu¡ÆÙºe Z×7ÑDÛ•õ±`åŸ[!Ž¦Â—0í…‰òžÖþ ;K£a°75¼j¦(BÈS]–šÊ†@ßmèõÂвUJ=oˆ¬PÆÆOòœõÆŸÁšÊ^N» S”Ô|Öaˆyð6øeéåy¥)æ›§•0C:t‡ùEö›Æ%ÍÝ@£ØÈ,o4ö•Òýh2Ù!Xµ~yVŸ—Oq¢ *{E-13¢bFL4ÐÎò @ sT‚3fºn›e§–Æ:ÇU„q@´0×8êcDÀ½´ÑŠÍ¸(é ‰ñŒ^ gÖN.ŸS?$Ö)™ ¨º®m¡ìI™œG+ÖÔâjN›×¿ºñõ¡²}ÄžlÈöÊÿ¬žš#¼ £Åg¢%!džBZS›*’`ªî=ÄüwXW£2Òd7V2,mγ÷JônÙý¸Ãá9TyU¡/!äO…*Ź5a"QÏÃfštV.¾²Àì° Žý´ŒòVѬ´FuÐ4‡}ªCówЃYÓÝõ ë'\}k ZF5ô°Ô/’üÙ¿qëMC¶Öò()ߢ%QÌ_âL?Aší9;ͪiÂy°“Ái¹Î%FŠ÷0(elz&~f9C§ Ì*¡Ž„ÁÓ¢R‰|077g)-Ò#0KÜeö“ FïuÃÉ.;­‚hë.ŠÎï\Êû¼â°£q  Y%ç%çlã ,ˆVG),Ä’µÁ«*õ9êh9qlêöU¿Q'Pê;S U³wqSp<Á´µóq´v ñl\EfKZUfKá}}Q·â½’ž¬Ì¢"†>Ôh!ß’Ò—Õ€q¥ð­Ã×°ó0¡ÅK¥qŽÉÍ~‚”ÿ³‚Õ3Ü¥ÅÕ釯ÈñÇìsðI‚E¼¥ux|MÚC(nm²-¼­Ò;žµ˜[3c8R“Æ®À“³›†¹`¿V˜|pF“$}}0ÉÏs­Ê'T..‡æ¸­6\½ p_0¬Š©ˆÕñSB˜ãg· ‰øb»™T›L¡Å•±Yr2þIË’Cµ6šIšeÐ(G.ü°•#ú?Ìsû(·ÉUTj…˜ìÆ‘ºo‰”fK$:I›.[ÁC›.Y”¦ÎtH´B±”×júRÎ+ˆÚw¦f‘8‹ûÆó2'h¯åÂJÚk½p&þ õÚ—v­šüÌ,­BK«Üæ@"*8Š $Ñh¤õº!Œ.ÞnñbÁÀE­æbACâ€GÛ}7C·ê‘ „‹Há#ræ•[Öì ͤ±*/S]l£F‰5dóØ :8ìýµ)Ój$9Â(»]ùø¢®”|œê™5½o4‰cV§²â)Ò¢…¶YÛ}e «Q’ä¥sŽëh¡úTŸ°”ÏeªçÓ’5©¡—”¶óm$i¥^µŸaùŽÎœT,´‹Át§5xlœ©¼‰JT¦Ñx˜åP ªß…%Åš­Ñ`¼É&Ïj‰õh°×¹ä2H@"4Ú‚»EÕרùÓúô[qíx…ËÊ£ö²ÂhètC×’ëÐßdŽp{!£Z~f!f6„V{¢çR7äú=F‰»ây¡ȡޑ²Òì‚Y‹V2M¤Õž™žÖßÂü¦JÉû°'bÊók4+ù„À‹µL„ý1.µŠÄ®P‘ƒû~g¯1Tû‡³Œ­´Ýa½c¤B¢u ”«ÇqÀÏfÊ$kÊŠÕ¨$/¢o[jhY†ð¸ÏdTêÍŒ^d=¢KAE°ä2|ÕüÂÛP¶ìb£µy?ÕAÓÆʈÁ<ì!«HuT}!jô—%}NBÒGò¥4ìÏ2õPMKgP}|F‘ c™1ßX&n•&D÷àLi‰ù™Ù.O>ÒæÿWò´µà§/§&wIZ„5IyÌ4 ½‘žd úqOÈÃ' y¬­æ¶Ø{›ÑŠ}²g´IMQ×ÅÕSú¹‰&N«v_L%7iÒ3½:5RIwÂ9© çùÌIðîJ®¬¶õC±è’ n-@ýøÏ+ Á¢!üç‘T$`åtÀƒÉ‡à;íóëúÚ÷”­E6ë÷Ï»•ªŒ¯ôá³µ ‹‡úé~3íqÕ¢ïëæûÔg Hà“Õ* +ð> HêµHÝ÷ eÍ«ÒȽ*™6Б„s{'%ö­ëoþ!Yä˜Ø–:z ê7öÚÀÂý@ JŒƒ‚ ©Çiï½£‰ŽªÕ‹+AZ3ÿê}×UÏ.µ×Zö W ô¦Ü˜XwLùDí¿ök\Ô™Âi£0¸!Ö_^+v¯1¿ˆÏêá®ÆtqÕ„¯,8KEchÉ›ø†F†q˜;,Í €¦Äñgáç¦>{veRRåÀé é=ŠÓTÄ3+ü^r:®i_ÂUÏÛ¡JîiÜùXo?$;ìÁ;Œ˜µ‹†Ä-‰B5>XpÑf[m̓õ|hnwJqy+ùlØèù­ô‰CªñâÛñtŸÕU?µ¾J¤øÓý×'…éŸÝÌÑ×O­ö<oQUf¥ bi ͨéÈ[CàþG­Î›ì-Äj’êpóÞÂCê7@*5«Z]IÄ–4©LÛëF1§ªfê'Vü{15/9ïÅ”½ðbÔÒqK¿¥% Ç®bˆ]x4]>Õ[™£”E¬çœp»qÕÿb‰(¸•+ž½ÚñæºPÐn8Ée›Ý_œeŠlå¸N­S棧0øa6]dƒÏ‘ç¿g?Ô™<’D äF[‡«²ñX–UíÑÜ%åÌ0Ê»d–ô´ ˆ1¸ÅÞí ào¶]ë’ºeº!Ïj`Ò¬`UK³œ"‡Ð¾P¤¾åäõ¦Ú¥ÝÛzs!öZk±ö»)$ ô9`È#'PÌýmžÅRÝa‚ËÕ.Í´c¦PW…—•R”,îÆztq5uf߸;¾•gñ5+okÕE[_hjgà^Lïæ‡3è4WöàúŒ±ÈS0£Å¶Š©9ütîÿv¡ù=RKóT(¾¾Ñce7xËã7ˆeà H0ap?ΫYö–ÔÜ!—éJþZaÏ’üäZ_xG®nžc´}`ÝD©7jI£-í}wµHRZcB¹3jüvÕ8r9ùÑÓ•ë¶I£nôj(,á?Vƒ õmXÆ )>it­¯ÕQÀ‘¸µ2FOöÇn➉_µ¦Å™"T“µ“sY•ã-e”0e:æ†YåC³«„˜UYÞ$4W "ÅÏØ¥•ßJ1ÃÏŒ›˜\0§lôÏUeû*…Ðó{‹]VÖáÅÇ áDs½°ö46à¶ítFLCJÀáj#§)ÎÁ[1e²MØÆØÞ•Cáf.&¾bº¨#|Iã[å«õŒ+N"‰ë–Û¥¢9†z=ðo ²—(-eMÕ-£;à ;l¯Ûƒ÷UƒXìäùLÞÃ,äËeöë¿Ú´žl«Úàš2Wõ¼¸ïÖœÅܦyL,n–Þjàv¦¬¿M¸½ŸE¶Éź—œL:tÍÀ«ú=¦ê‡ŠÖ|S3zÄ^ÓÞáP’8Z¼57LÑq »Z’oÁà×°À¿ø`Y±(}oê¯Riîhøµ WË.8·% „/ H¾Ë΋±VÀÁMŽ| ËT¡CÕm³r«­ ç˜û»AýS©± +s®¡-œÕA++ejøàYkü% êÁfLFÊo¢Â¤€¿Ë¯©Qú¯Oïýµüù›â”endstream endobj 820 0 obj 5319 endobj 824 0 obj <> stream xœå\IsÝÆ¾³ü#Xò ‚Y 98.Ù¥”e)òKÅU¶”h‘)‹‹-‰–üë3½ÍôóJò)å²D³ö|½}ÓЯÇ]kŽ;øÿ~quô·gãñÅë£îøâè×#ƒ/ù¯WÇÿØÄÎÄ'íÔMæxóòˆzšãÑη=Þ\ý°2M¿êâÿmcñgƒ?¯CgÚÎô«g3í49³zÒØÐN¡·«ÿ4kçÆ¶ëÆÕW[=jÖvõM†ø$¬6ÍÚ¯£gÍÚÐËoãØ_C§€c~׬‡ÕSxÛÁèÁO«/¡¶ŽcÆ‘ ÷Åç_4S»Z_<Ÿ¾m¸ÿO›Æ«wì{Ó!nzsÎíãÿ®é¡ñšß®]׎fš¨ÑYlpÝØ6VïaÍ$‡¯ãFóÜQ@Î.b7ñåã?ƒ]Ç?`ýQçðû«øöÇzôqØ[¾Ž¿Z³º…0çoÍ:ó¢ñ«·ñAÜÙ8ÚÕ«øHÚÀÀÁá#\\ …Æ )²ü9ð2¾&1âÛW¸âÕï°…Kxm®á¡‹<ÿJ·°ê‹ë‚5Áû×$˜AoÛÇ¥ÅA<Ê"u;k@Ä6ô­OòNË€¡â0Šâª±üà[xÃòšttŒ?`×.Îe æò$¿7…Ž÷ÅÏádnD¶°à?Ò«Ü(‘ë#,»!ÎCÛw(Z #qÓË|$tJ°‰É¡¦{Ú;ösưQú¥:ÃjæëÇf¶?Aí’FÂ},pÂm`Ù¢ýŒø¸2CIo®õo0›Ö¶ŸDi°ŸÉžE^Àõ¤£½,FúTì­˜Xb<š"À‚µýyš—Wa‡îÉ$‰q»|îw䑃SÏ4Rb‡¦Kij— ¤?píÓ»Cí­• I£4hs7iÉ/Nûå}8ð¸Ñò¶6Ôõ,hpœ5þ‘ýþ ö5àkÝwÓêüRv¢ö/ÓàôP顱ŸFÜ~´p½K$}¢]”ùMÉðì~H¡»íðáƒôð»Ü}“~‘>K7ùá—éá“ôÓ7ùõ=¥ŸÂ!S>ÉŸ¦‡_æ‡ÅDü“ÍOY4¨ÀÔ«Z­õF1TÌ‹ë§l^’V(Ï•^^¥Å°KŹ¡Ç¨Ï”ý™ë„k8-²`fÄe²MÖò tò…ý ŽØ35‰SbƒžÑ–p9Ë‘ø…²Dbs’᎛™0Ö‚7ioƒBú ›™¨QVÌ lx ãÙ¾Te¨<-6j‰ÌŒ±g3Ê©{4Ød}²-á- vP1VŠ¡Àzs° ¢ YZeáoÇþ¯f¶bÔÒû€ ÇÁ‰Qx¿1·aSƒS㽘š…#¿¥e€@Îjä`]¦/ã.a,"·L©X}ÞGæ.ÎØ¯Ö2˜_Ú”D¯dK—&',ðQ?Â(7CÅumgï@¢çX × Ú;akYÁ¡5v­MìF¡Ø!öqpõ:7–1 mß.pǪ&~ã‚W:õ¥×“Da“½Í£ ·Ç©)æñääwÈ· ŠfSuT”ˆ«“n¬º¸ƒ>Сë I~þó4Á¤TFN<´Ù:GÙ˜޽P.Ù˜]s\ã(üË’LBTÁ7.nähôˆL•7Mp”ƒ!énô(¢Á¢õwø¾D®o”¢]~’%÷³um"»è˜íDµúæhó—¹ïxÉj¹8ì[T 锲L­š…°Y9%«U9ê+<;%C3à/0+±ÊVr®Rªöh%/Äõ\} ³)ì$œL7¡e]ÚsÓïY9ªSŽo³Ä‹…„²ö1ƲÙt¦¼L¡+±°6Áë„m…ëܼ,ÈhãÚfÙ·ä6¸ ³;C‰ Žïr\]¨=yIã1CÚ­d‹Ø±0°LèÝî’‘ð.e«×YqÎòKêFx$•IËÆ"$_™e$0WO‡Ä)¨Lп“炳äšàPâòr‰ï”•Ø9Í"J•ösøí¡iʆ%˜€ÔÝúñÒ–ï/âDÚÎÚ*‰hÉæ ¸›aZFwÁ(ûjó¼I€D¥fýßÃúÂ⸻¡M0Ñw=BQG¬äa­-TçUf1y“²èÒ²”!ƒ·‰‹d\¼Köì6Ç7¤›Vs¤Ið¿Ë€)kè1ÙÙc§Pe,€1Á¡æ ¢Â~JÖL¢>ÜÍàŠÝH7ÆÐ“ÕŸäîs`š@¥rª;I|ΓӛEwÆf [Ý’#ÁÕ¡g‡·¾ÌqÜH‡’”X¢ 1¬YÙd Žô—šÆFÉB4äCÂÔÛ%ßQŠàI3[‚<ŒXF-–\1.=. Ž9Àõä–`ÅÌ,J|—m×ÌÜ],@»;§™«¨ tž†ÇBÐÔx’µõ];Ẕ}•$¹I¢¾KTÇo‰ùy#Ô3! aØÏ›È2_©¬¼B(åuzÿ&w?k"ߤ‡óÃwéám­Ð©Ot£»« bµCc†µ×=Ýð ¨øÑ» )™‚ÜAz:ºÎ µ¤brËrþʨOÓ2Ó#mKNI-àzàŽ#Ë׃÷tìCsº}#ØÂtÁ´óüè óäcyò‚Ì“?™'»‘yò'!óäd.YÈÁ´…},ï7&º€øXÒNS {’Oƒ[ 0Ü„´“ÝBv/î&#¹QAHò³­#î&$»”éÐÝ’Œ„ð§3š4öCØH¥ÒÅnŸÈHQê§$#åÒä¾d¤Äÿ.CSÅäÁ¸“ê•CÄÎÌ’Žá'=д“/RaÏ!SJIŠzUAQð‰JÒeGu Š(ËõòlaTññþnêÕ$Îì-‘¯›G÷xÕA„â*k—1÷ä^¤Ûì.ð¼=À0Ý ­³ú>OQDTÉiW]žp |ÚY7%‘^óHrÚmõg|5ð‰!W§F§âEœJ©*5(©’DŸUJ9U&¸Ìµ¥‡kÉåijdBPéÛ£üúqƒÙlçTÆø×üÚ¤‡-ŒÓÞàIç0ûÐò\‚#T¿¤[ÞsâUAAj¯âv&¿kÅIûe‚V®1Ý¢? UíáT¸7g]p¬™1JÖ&4i»4Wl~½GEˆ¾õ>× zfUù˜T–¦6MjxTÝN 0ùñ²€Cnœ5¶7À l~ÓðsSVeKC¼d¥©¡å}ò$Œ~¦œaãÐhm>0Dz¦Yï|ØsÑP´ÉA@}/Þwû¼¾›:[±Yˣ̬ùfÃ&ígù2mi¢<%…{‚E—ƒE[g-UýÝÖ‚4ÛÎ/™ {0´ˆÓ…Ö;IÈsTÿTÄ–€¯‘å®} Þ!ɽ·Ô˜Þ ?-Xª œÊºhXB5æôb„9ôÒ1§/'y®Í· NpòR…W7OÚÝGí>… è›r±ó eÞÄËâ´—Ó¥c¿÷R³ú}®ÊÔɽrë=Þý/óÿZI¿\Ê£u ³rt†Û8c}jµ2ÂÂ’Ïõ]ÎvNJ¼qI8øja œ#<4•T¶GrnÓw%µ[!bMmÙ'C¿Ž2ö}Q£äÊœ@ sß™Jï)~P- ›*fj†Œ‰ÄpíZþBЏ'º›†kF६­Wß<^vFG†U> ¼,ûaµðÖcn;-~öâŸ)ûÊpžq9Ä¿(3/VÉô— ýý>¥j¿Ã÷5Q }þzJÑ£ò} ɤô¼òéQ* 0ÄÝ’ü³ýÓ_ÑÑ u‘Å{–NŠW†0i9ûõÐÀØnï¶RJ…o-ìÛ+ÌAøóãô™‰G9ΈènηÖM™E"¦(Êî³"²?c¶|Ý‘ô7 aÏA¡™ï’¥C]ZDº×Lä噃7ÞFyÍœ°ŸU*×N‰‡4Žc ÍÅò‡š5Ëø‹ *"ã{è | ¥¤«”S®ßZ|kë…·ºw’)~´ú´ •Žhsl8@C¶ŧJq‹[(­D9fúÃÍÅó±¡>Îäwýñ6YŸü3VÕ0eÚ“ƒ®% |Q™Y ÏÁ´@ò°úþÈŸÀÀw/ppµÿxÆíèÆ¹_ý¿éÙO")Šüs]|å2ø%uÃY¦eÕAQí3w5ÑÔçµ²€ïšÌOáØx–gÏtaöŽ(¬ÓžÏîEE1ÒY\äûÚñÛ¨Œ{wvô®¶–Þ·B¬N]€ Éà²1ïRµSX|˜‹–k¹„ÿ½Î‹Âº l¤^È‚óнHLò·šqæ¹Î8ßèúzþt"«Ps« ±dW”ÅR(ïÕµî,.Cé­5êÞÌ >&¦ÁƒN΂WŸóWh·çi¾ú.;‘ §¹Šà oÜÛmW,ßkºD›ÂïÆËR”s©Œ-þ½„ï“7zšªO<Ðó@!þ3 s1pZ³|_nÇêM­:!eªÓ²EÕU$/—±•ÅÒtKεA}Qû *ƒÛ-$F”-ov5Úñxc·JÆÆ+AT¥~‰Ë«ü ’B¨Á ãóáæè_ñ¿ÿ—kŽ…endstream endobj 825 0 obj 4354 endobj 829 0 obj <> stream xœ­\[sÝÆ‘~W©ö7°ô’ƒ¬Œ¹äM»Nj½•³·b•“Ф.‰¤mQ–ö×gú:=À€¢l—Šâ!0—žžž¾|Ýs~8zw2À?þ}þîÁWOç“W?=N^=øá×'üëüÝÉœæÎç'ý2,îäôåêéNf2‡Øþäô݃ï®cþ‰ÝøÓÿν‚«z-K?N¹ãéEnüŸÝ1þ«sý²¤¸žtþð×îè§ðüÝQ^<íŽÁýà"Ž?äŸ>¿õÑåg¶áw:– áÉ£~Ýñ_ÃHcnêB? !ÄÃ7ðæÏð_n¢ï—´`7 è´¼ 0þtxÖ§üÔûÃóÎç£wØá´K{}×yZ~:q¹Ë8zXý‘— C?çÏÄ×óF Ã0ÁÒòçaÉ¢Ëkúf?Uû™š$Ÿiš2\Þ‰Lé³LÔ4þpƒ¦LçY^Æ2ƒ?¼Ïœé§,xSzÓûiˆ‡·y™ièÇä€ï±wq™üá2svHSô‡Wfz3Àµy|•‡˜S?çê2EsôÒWó¶|4ÔÐ)N‡ó^ô³™«Ôkô!äQyU†br-™~êãÉ韜þþ{Ü‹L s…Ãkøã2‹Cž#zØÚt8ÏÂûw™lü/?u]Q«e ‡‡ÐómçqVÅd¢¢óØòŸÅ0ÑLï;ð5rôép­óc7~*â ­aø}n{æ61Ë̲xšõº s–ÒÌ‹ŸAÎáµ/`ü³n3ä…,"êšxnì­,© ½ì€¹!¯IÏ+ò ŽÇ¼i›‡ŒÈÌŸàÝd"ó|ó쑞÷ðØOÞÂH’”Û†%wi“°ÿd³íd t•^–:yálæË\e K}w!Öx¤EóØ1,‰ÖЬyÃÛÆD"£`ÔsØ‚<½LCccÂ8!—a”Lg˜FäÐ[\N¦•ºŸó€"V4œßpšå¨q¹#}ÌšñUG3}èI4›œÒçwGçBÆYÉ)б²Ÿ>Év…Éá4¸Lh.óQCà£_\ï¼iÉ*zÌÛrjd,k×$R"ú)„³ Üœ&³[0ñG˜Dw<¼,Ô”?—Åôx­jYYA W/€ò×EBÚŸÏË02Óäfó 1{„‡:æÛJZKc8.@º#)ö€œLàSÊæb V“Ål Ò{d³S$V޼€/¼±oàO ´*7ÁÆ?dJ’˜GúT‡ Þ0 Q˜!o.õÓUy}¦+1’‡yš˜fÿï3«Qy…Ãc‰![G3´ôý¨oÊÃõ!tPOd›ûÝG· Âúž¦~\ˆy¤=~.=ÎõáO<¡]lDÏ2>Æ@JŸ>’)ãáüqIöãß;mܲ^ÇjÓ£ˆI­©ù}ž»©üÏí*?÷.dbéÎè<‡ÂY„ÅĈmá Ý@{PN-­à''J|*Ü‘1mA!þJÁ*‚Ôû„ ¯tF^$êŒÍ +Æ™¬–O©÷Q‘\KªŒ+'pÑ´è4?€›‘[»lUn+"MŠ1ñ¨×h–+mk^¼ë< …3CÛõÈýYÀŠ‹=D"g”¥2[þܨ%/ÆSFܳuÌTB£¨±*Ùîü"pk]&àšPèÙØÀÙÑ ‚9†„?oƒò®–-u’¬·„¶É¿JtBšðLiw #‹¾•[Ñá¥Í Áéæ|ñ,—daÁõ2³ k4¸Þ‹Œy1¶³iäãn¸:‰ÜƒkkÇ;!?5¬›a1D&µ—|™GäKÃfN O¡i4/i `0W¾:ql9ÉwB.Ô6ÍœÆxøCþ#QðÞ8„Nø}îH“ƒèßfrLßülDi“•ç MräF1nZ0Æ 7ñE%cº]Ÿ é|•xùÂ’™e!kÝ, iÞÕ>q$+WÑéYИˆÇ ¾.l{5¿R þûD÷ŒDËç¨IÝn••”„M=Mœà%ÐŒ*亥DŒ¯™­ø¬ë’ÆŸ²HÄHÜ­¼(Âd†ŠUC‘¨ÐªjÕƒšåµìŸ V;r£C¾²*às-=fuHD ×nÔ­- ­’Í.;{âAõAzU+Ÿs”æ;&‡‡³eZlmäŒXÔÚ¢|\É_¸0Ï;®÷dŒ”A²®v¦`VÙc!´Ae%AF3Š®­ßÄpVEl[œÐOê0€–‰$dle}FÊ0¸z¶€Ü4¡[¥¡„1TÐe@½ÏF ÙœºLµaXr+g•߯ìCˆèÐâ%6 øšè‡ÉxÔ[Æ/ xwµÄà7Zû,Ac´e¨"0lŒÝñŠj¸à´šƒ³²(WÖ~IPYlçÓ1€?C[4n’ÑL´é¯ˆVP²¡K!}e‡ˆ–< ®8VƒR¬"mDöd?rhÞ9»æá­£’”öU…cˆEx9‹[÷‡Ñ ÐgŠ„>ó¿Ê/‘üÜ7Ķþ&þ«$¦‘2ŅоÜ9!g …Nà µ Ÿ$Ê £ d–œ“¼ó‰>D³ öõiGz…lVW%€©¾ñî‚5¤Œµ”K\¡-bü¥7ˆúìC¼Ð=¼­\19FZØ Æ™\Ÿ’ˆ"0dl1c$<£à¯ÆWÜ(­›]GÑ|W…˜'ÝÊ-·‘¤º•ÔýuGî0ÖO¶oeÿää2Ü„k­}¦oa·^T¶ çüÐawQÏsqQ?ÀƒršÙù?EÁCW -K# £Šð‚ à)À‚à¥|Ý–kìÕÀÙo»PÀ“$RuïyBNZX±R^•»E¦Õ¢ÜÀì~`¥6÷³úåohq“*À@g¼ ¯EôGÝŽs,[YYìŽ÷×XÆMÏÛ" gíäG ón/ͺV¼èZ¤tÝ 5âp¾ekãu­Aþ½5yöì ¢kQºtD@]í EW$øÔ^—áWÚíÛÌÜ©Ž$VXFÆó _ ±#Ìü¦t8-ÎÅ3hæ ˜¾f.ý¨bTÙmæK9z"Íö’çELdn@/ý¢!W‹õºj¼¾(d¯¸z†¼ÆÃ[Æ•c7F£…n[zÓB åˆêȼXMñ›³Š pb%d«Ku÷K G'²±–=Odêg+ÀÚÖŽ´ñuf!;¨bÿÍb}‘œeÒœ²c¨ND½WA›~ÀÙþ×ü<¬,\%¨„7ãÁxYÏÝ—HU@«©áŒaº“†¡`6•ýöÌÂV”÷ÍX1WÐ?«~¯ˆéx½•«§ÄÊÑrŽY;°:Â}¼BHK+‚5ºX2;ºY~O8y_(Göä?ÇOZ¡ƒvÉœ~Ål„÷óŠ_6·WcMÆzÄs)0´ÑXNP ñMÍ~&!ÝjCD$D¶(£úC&]¤+V‡LÁŽŠxäl°ê³'¹;mK)½, ÷; ½IzðZæÃï(éý8(\Vc¡=hûœÛÆÁ¨§košjª U$›m\ûRjÜ)V:Æ™ì¬Fýh¸'÷7v+N‰ý¬Üq…™W¹ßw”1ñwAO4…ð ™™”X¡K+eçÙš 4—EŠlŒva'^Š0¼àvO3µúo=9N 2,•ÙâM6xäµ£5ÀóYÙ•:'û°mÜâ”ìZ‰õi¨$Â>§¶bZС«su¥y¯9.¬6pO:‘r³çö°Ù`n?‹]%N£‰‚ Š´ýuÅFΙÉVþ²ÙE…«JTG *6ü¨‚n–é»UbH< \{4"¨žE»Ug+²;× rfAOÉGÕh&‹EÎbœ5WšPŠh\B}Ê2- 4kÔÈq ݨ+ƒ†õXÑkP£•nÍÚh째N½ý²|k(™VQÊ2²\V³q›¾•ù4IÎ’­}T>ð7˜Äê_Ëûoõᳪ“dFŸß»/zÚÎ\Ž}‚,u®~ 2Ø‚ÄÜ}jjÂBª[Ð/ÄÒã'•è%'²ÂGŽ«-Þt%(ñ\šÄCëa Å4˜C†’bx%ºU•,FæB¢¨PÄyYêÈYýÜŵÕ%˜¼ÁDª`u}^ÃBÕ),’îhgypÖM³‰Y†òÔîÓ–“&ug8ÍI$/ˆH9wcVAÄ"Câ ’u®DszóŽtU‚ëÔᲑ,S7ÙÑU‘ òH,~Å÷µYþ!‘'Ĺ1™€D++aƤº—êµÏcü¤}?©ãfÒÞ­‹ª˜ëš¡†å4‘Œ¬5(s~W1ä)¬@5öÜT(?/lÌ†ÚØßQ”µ±f·ðÙÕ ¨ÍÿÞx0ϲÉ~®á? Ü_om|…­2˜ˆQĪfp“:‹%\šFLˆÿ? ßö +’ÛV¸l!­i)Ê\y—¨ÐRÈ(nŸ>?‘_f(«• kW‘!“«ñO÷”µiÔ$©² ©¡<2߸‹ÿ4¥-k¦iŠ«xc/Î qùçPL–$ÝØ.êc¬Ztƒ­hgabð[{ô‚*×ók–NB ²Ñ^ªhÍ6]9ˆF®C$ ¹¢Aâ¼VD2ŸM`N¥x¢xošð-îlëÜá9•—XÔ¿àVE*ZuÉ®Œ¼&DªEyVéœÕ,FG¶ó¨‘Ä OâvíÄ!ߘ´„TOûæÑä=Y¦~Šˆ˜F1/ŃÈ"}·¡›’vÚ˜ÓyØË’$bÅ">¿X<ò³´êôK3ÌK0•_jPuJš×5Εµä`1y9€N•ÉÛ¤¡öjmódõ3°Z1Y$y•˜áeôËk“m¸Ô‰aLKŽí±ÛÊ*›Ü°ÕYÄ„mÝ)ÈöŽ™ÈP?$:³›èÔî6fƪ²gU£ýŽC TDu&ˆ£½kh“×7èX˜w«NÜëŠÜ¾ò-$‚-É0­]Ü€‘ãbK©›5šÍ¥T³áöo 4Ç™7F4¥öŽ[~®²„»ïtJÛÇšÝ/3UXZðˆÜŠy·ËŒ¯ËöYg)›(7ôKm¸9 pÒÒXã½LNeÉ\”S9î$Î¥?t1}KÞ‹EÐÈgëÞÁè)zàJ&ÑI>ºqèÍɧäü‡Då,\÷¹ Ä—Ób#Êê?4â¡ÒæÌÅ‘;ÔŠˆàc>ÙKË€òÕÌÒñ£Æ'«|æÍÎL"h‰ZÒ*p"p‚Š~1æ“Võ(®å)N„Œ—3u„+‡ƒú~o]O…!ë2 )ôoë(ZBáH5:°i6†¯ª›ò”‚uØ0kj¬Âi“/aùgêô êKÓê®ë|Êï&Eû›ºZ2ÕéC÷\ÌB°e´7õ›2ZM³AÚ¥/VwÕ&Ztm¥6;ÙÚì³â\ m$€/Ú¢Ü0¸ì`#Ì 1‰oøOkñøËªÚ6©S‹”ã3dÄô­‰þ½õp¬F_ÈÕxþÛþÙï4hVý…µ9Cxã ~Rå"ÅÅÕY/)ŽL$•»áC• ˜ ¨p×!h×ÄeMßÛ²ÌDQ'~m©ÔZÐ’[]ÆQ4ÅÄp™o©J†bššÊ GqÙ&€•b¡’™·´Û€6rpkYðÒ꯮ޜé*âý¢UlF3tlp¬Q”ê*­º6·_”\$–ººÞË8÷\¥Ž[žL÷ þ€±.¸Ü4•tWºÃ4GÀ¨iQy‘kÈ*M.Ù‚nX3«y°êL¹@QÝŠù–t}˜o!K ‡µ¦Pï+¡lå}‘tš»¦Rçúh듆Ò[.º.Ðymn P±úÂ) 1hcïQôÇÓÿ›ÿý ï!ý˜endstream endobj 830 0 obj 5396 endobj 834 0 obj <> stream xœÕ\[sÇq~gô#PʃϪpV»3³—‘“Ú‘“¸T¦B±"²ì” @6@¼Š®üøL_§gwöeKv¥X$Îîܺ¿ùº§»?umÔÁþÿôõ£/ŸNGouG~xÔãÃ#þïôõѯž¥|Ÿ¾icû£g¯QËþhrG“m玞½~ôû]ß ».ým‡Ÿ{ü¼Ÿ»¾íúa÷´ñ}£ïwO7·qÜîûfïýÔvÝ´ûMãwÿÙìÝî›fÓ7óîY³»¯á«§Í¾§‡¿K}ÿ;4š±Ïïšý¸û¤÷ ÷9Äݯ¡¾úL=õÜ¿ÜÄ.5uÜ=>xŸ~×pûÿyöÛ´âÞÙ‡¡oÇ9-úÙ/t ¿ðòžŸî}×N}ŒôÒivçéïuš1üÿFz—y•¾8I­¯Ó2ÜÁwoÓsXTðéã°{Óì‡ÝYZ, ZÝÀj¡)tsžš÷!‰qÄ÷_¥»G‚7N+tv Ãp·ð- þ#´v(fîÙwEúNdv £Á(]À÷ôôÿÒÒô… FèÍv‘æ¸îÒE«"#Qâ»D릩U±[ÁùW~HpK‘9èy†ñaº}a8ßÅÔQX AÞ¾$8³Ò@cä~.RÿÐ ô>5Ž»Ï´i!¨€‚â¦$.3Ø>Nõõ^;ÐWo$•}faóp.i¡¤ßy÷vŒ à$6"lná〨û3¼ƒÏ.’»q@\xOp5n$À|‚—¡ƒK+ZçEî”Áá#lêQ—‘š&¦¾¢£J(ò{Žz…ñ^'=³œ`:¼ˆ ЧÒõ'x(Kù¸$O*ñ#`¦|Π¼É‹zYÀé¡éKâlBƒ3UWb@T¿³ïcËjBÒÑÕÁþMÝ_3°™"XP~÷y ®<¥ â‰Eú6ƆŸó|“îõTøÄãq’*bøá 5éºh·ë‡ýŸ1¨ç)÷({_A»y¼dj6à·7´ä ‚Ê’‰Hç#±10™svB8;"„8´!ˆÔïd‚WL Øá1ì´a¨+¤øÑ*ÇÙ‹ÐiêÁQ§ßÓ 'r]øùw<ÙÄ]&Ïiö¦9ð1¬|†€ý6‡Âü‰A•¥-6Žû’-–ÐÑŠžI‚·v¢D_¼®ÒÒ`¼%åŸåd|ÀNŒdM,}쑦>“¦äÏ ôCv&®ñoú~@Åáè§ìåÜ0†ªn ò>få!®Ï’|ö"?†üf—¤üV¨[?{Otgd.š„ì„®_ì1„K× TÌ~¸¡) ªÓ²¹ùQ£hœ\&ÍœITö<€œ¯””ÈMÀL¸{^åAÙ–rkàÜ•GIk+Ù¨î‘è±9#׊ـÊÍ¢ôl­ðýs>Pl›6‡æi‰6ñ/ëÆì=·¶¤•™HççyK•ÀdïQG4Ó€ŠÛA/£ÙKºU«Ç®ü æ»º7.}×LMFÑøÎMþ¹`­…CSÛpqB^žq¢ªã¥Ó¦¼¿/Ksh££ãyéGD}Eå'îAXʳ¥,¹´$ÞhêŒ\oDENÊó©da(Œ§ª~äA…¯`iFçyÅXÍYôŸª‰¾’äw¿"õ|ùtôö »w!µNGU8±&jÇ>¾çi„ôÏÒXòEÃÔ)PöC:à‚„Ÿë }–K‚ý@Ï_Øçø…=Nm?Í#È`÷/úÂzíÑ2=±¾G–¶öz§Ï¯òóõËóüeÂÿ€n Á¿ý!|O“Û nˆqýì°ì›añ­|¼È=\Y¾´ cL©Ðo=ûâ÷»o Yãh¶éß æÊóÜÞ•Ï“»ÿÂ> €Šü8Â6ú;ªècþÖ´:Ë>guÓO£ Ð@†<%šHšã…>ÕŒÃðÓJ¥m«ÏÛü¼ÍÏA}¶÷ØÓš.ÞÚýްG^“/ßTU}U“.t`´VÙXkýÀ»oŠÉtD† `˜!.Wj}ÊÛ ŽÇ{gi‰YÉf»P¥Ã ‡øÛv•¶ó4h3Np0Øý/î4æâ_Z.[ïÉ3»p£†õî<_‹> xzhèßVus¶êw¡ÝóÚ»¢¼_éÖK”1Lã´­™Ó{4Sþ½>?+ð”´B]DOÿa©ÁÜó–©4Zè±&$Õÿ&=~¬)¢:+«\²H“ò²-®sŽ?Kþ›Ú)Ü?¯-þx;ÝÇ’ÿÏTEïŠ~­x#¤B} „~ö?õÚŸJÖ³y¬RÇÞ—³‘Ëud»Qò>yœíÆÓæ G½Ë¶¼\_òBÈÒ×ÊÒ×¢êàNV‰4ÿ³.õÇ}çgŸDßvut"~ÈêÞé†+uÕL/_Ïtjú;êz)ÚE÷4útO£-¬¬}Èã̃oþ©ÖüñÆ”…$3TWùÒœ"JXË~ýn˹eFù9Ø#/ËZ ;R'Áu£«óú®]æI÷!½çÊò€ù± èq¹£Ð †–Ÿ7Ö;Nÿ¿àÏ8†hG RAØ’’‘&"±æ‡dP%¦qÒPädjOêXÇûâ`)! RŠ‚þÂÎwÔLgN¨-1Ãî—†mr⹤¥wÿl5B¢|HßNN‚æ”]Oé "FQ•b`«/UYŠðÊÜÆ¡üªƒèS©ºcŒ÷¤@$du¥òíÍ,eI† ,ÖáÇ3ÊšØâ/!ø> Ýõƒ”üœS™*¶Yá°Š0?,dåÒdÓw»ùÐ Jn$&ÁE?ObPaèJàåK-àC’lobK\p&6XĘ JpÆ¡;.€˜å¼û“¡)žÛ—eL#X·ŒÁØŽ6:¸â¦‹B]„ÑAúÍACò­†•1.Œä°m‹9ŽDCÉÑ-4„Úp›ÐâÇå€.1çV–Ÿƒá 1\j™Ñx,€CÊ3lhsŒÄq¢›0,c³ªxç.kàØê†¶Hc˜Ù㼇€½JCxJ'ûžÚ$°jé"a”Zˆ@ÑLÍÖ^جïB¥Ä{̨ü¦‰lÈ1êaÊ¡_’Å1ƒÍ‚Ž) ;®óÒªÅÍu,ä¹M.uvÙÒÙŸ ÕÁ8q5ÔµÌ)1ü¢½ea½Ãqó°†’hó•ø :ÿˉ‚ Û&QgAߢ>#L²gµLà>àRl ŠVÒB°zjÎÍ@‚³×X~'Å:5Sg+™²âÁˆ;¤Ï«ð¨®„a•v¯W‹¨\Í¡ù­ôƒI—¦m´­NYbî–¿ï†Uže@Øä†1ÔÔ’)_A ½ÃUTàù’ñ>K¥˜e%G&&\uiûþfbj[­ÑáèÇ5THÌ5ÆÑº=ä!m¹8QŽ,9À¨cÓ79Ï4Å÷ºñQ V䨩t˜ µ=¬w¥Øâخ͚e)LÔ¨žZ4ËÄ.^¸b±[¥óš$&8­äá$wÜR 0ëHNï÷ 8ÌcŒÖ7ÊÝNì bð¯õ£æeq™Ý•ž+Ù–y™Á×–úøŽœŸ—¶¨Ìw"G.¾ 41WŒ©¢ûn™»ùSÕ®d/ú…(»]Ö¨3üLì¯Ì×Eô¯¶S–œ/,aLö[æ#oÌ\A…ìÎQ½`¥èD¦hË­”–¸Ù¼û¢¶ª-í\Q—ÚCéé‹FëšÊbD]Rµ º1Ì™û>)üiAT^ÍžzGR?²U42uÛš@§1§ÑàÇÔ÷Mü.+U€ÐÚÍ}r=`’LŸz”ÏZAS÷@Å‚£Z#«˜ñSDê}! ÷ Ï—åI™@lMâRP0@ ¹òÆm gzŒx{’ë‘ì9ä\8Î,Ë]|ÐZñÚe|zX(úÐÅŸÚKøWOœZÐ-«e¼` I¶ÈÄK&¬dø¢+®9¨Å¤ÀÒù›®ß¤0ø5“ë›ÙÁp˜ƒ@”Y©% ÆÄ—˜ÇÅÔ†äÒÒmd*f‹#;¡Eìblƒ¹Üm RâõYebEqEk±‹[¢ýÒ°*œ.â Â,L„ddÅȱx@õi&`x¬,e¨‘$J6;l/¼E‚x—Ž WvÊ5µï>¾V©(¢a‹´®9"ß@ü‚3õž²ϾUâÖFsã`5!Š­ ®Mõ9-‘ôŽ«àÒ¾ŸâÊQ—b&uú„¦àuV >p­¼x\ hU°»öØÙ|¬GSih}Èù ùq½Ia¯ùÿÔq%€ÝùŽŒDœuót@lwήEYqǬ›ºç‹jq±Ä×GõãV´d ’Ì¥­yr˜S÷læÐâ‹\ÌÓì/æzÙírËÂ%›ë,GFbQ&·òzh @ ²ûŒ3 °_ JèªjãÉg’MP-g–dàÐÙ’°SŒ÷q›‹T­|ø: OŠoŽ,Éê¾YèRb[ú푎¥Û¯×NŠHfœ–þ•pPØŠ§Éøa7ÂÕbJ©7ß°g£¢¹$~íx Æ>åö…b1oâïë¾uùzLáÿ€^C´PA¤J´r–ä‚ÇÊ@e|ÐÀ©Õ…BPœ¹AŽ´f„3å¯ýûJƒ¹Ìkü½ ލ÷!-nµàÐÜ4‚¸îR×<8u®IN·– Sˆ ò^Ë›¼Ö‹M^Öê0aÌŒü>Öì¢a4¥8n›NoÆ-ñ›åM k}öàˆÖ¶ß°0O¼Ü{Z|©–¾pS[½-PÅ^­BØSlª~ *L¹x0ª®T‘˘d›“,×9:ù×Ý Dk0¤g[·ÇBQex/Ä^å¦ö˜¶ïU%ë3ž°U¤3ž¤#»NVO¸Ñ„ \zˆòÔÔwKÌãL\Abà:°}Æšúâöœ]mc_li·pÆ!{,'YYì Ÿ™ÐÓW9Ý”Ü/;¯$œÊ +y,7éhµ%·œ)Ò¥wú§Ú£›¦UŠEð%W*0+eOVê\‘uîÃýɾ4Ðê„÷—ìÛ û“Tº…8<½vËÂ}7=ÖP'wVPàÖÀTЙ¹"gÒ;®êÚÁ>T%ÝsÜàÕ3njØàt_äÞý?ÌB®owSëÅõ)â†þÊø•^¦5oÞ¥É÷L& ®,ïžhtÊl]ÊR¦ÃßÙûÆ+PUZL¯°ýñ“S¥Ù+5êÛÔN‚cü2awÏ<”óçÛ1ÞËQ2¯“ó4 LžÕGõû©›ÑŽË,(6µ“âLMmy(ó9ôIO)¡8ÊI§¨¿Ïâ.,Ü:ð ñ÷ô°Œ¿;ŠuÞ5E¨`û*ŸáKý¥&ñÞ³ÌêÓj6‘X7éÄÁc ¯Îä ™%Öe cÝÃäJ …|ï ,Ø­sD eu®ž5\¥ÝöÍÅ‘@RT–~Î>—¹¿HÁªi¹ÏÔQ‰Œ×1˜"·§ÒrY䟋®Oøi€È EQsÝŠ¹`±.(¾m*•·Ÿ7¦†Ö‡ÖÃo *YvsRróëfé® /A–ìÍôÀbØêëÓÚtra²¹9r\û2—Ÿ5•âb[›r?ÓÏóÚ4ntM-L»YWÝ苹ǶGô):o$~]+ ­ýäòt¨~³yU‰›Ú^£Óß‚µâçsÅÕfùÿUMVæ.×µ`±ÿI±˜8÷V‰ÅÃóÕËÛ€Ty了=«ÃTîH^߸´¸)cüÇüø£âã¬6Î¥Gðñ©>Œ|ùJ_ü£~g®,žé€[×–T,ÒÏmmf'æKy1k ¸¾%nl92.ÿB­bï-n5ðæ“ Åî“ç«í;¡u§ÐS±ÿlµºÙ€_?{ô_éÏÿWÛÓ¬endstream endobj 835 0 obj 5006 endobj 839 0 obj <> stream xœÝZûoÜÆþ]Å!ÒÐ1ÜåòUØFýLÜØ®k«Ä(N:IwÈé^FÑÿ½;»Ür¨“Ø­‹ 4oß;óÍ7ê·Iž©Iÿuÿîm}÷ºž®·òÉáÖo[ÊuNºöŽ&wì¥mKÖæ­šìlù™jRëI]˜,ד£­Ÿ•–Iiÿ¯ÒòýÎ_í¬B±Ym›••¸3·ƒ¥S“üª¬mÓ&R¼J§:Ùö'é4t¼N§…γ\·~nÿÏl¯6ʶÑoãZa ¼´«>N»a¥ÒŽ1ÉÓ´Èò¼(Lò zžÃÃŽ)ŒÎÚ¦uÓà@/â0è,`ý*y“N+Ûªuò.Õö¥ÔÊMØIãf½Mµ¿~UÐëOU]e•™LÉt“+/†oìÂÉ) (Õ¨±mj«†2/ƶÁ;†uNèɆº=a'8ð8nˆk¿e’†WS4vRXˆÈê_RйníoLý8Î!šxG—‡ÝÛ’žh¸:ì~W"*ÿ%ï°·µb“Y3Óu¦,åø#\vÑN¾ ˜¥ìèÊ™C)¼¸i–=D¢þ9,EÐúÁpBÓÔÁnÑbKÕ: ÕLú¹y qðK£ÌGs§’®×’ŸK̶-‘†ƒ@DfãÙ÷¨¬p\÷©íÞ#'›²Y®–ÂÏX+Rèº0mfL@'¿09 Ç”›Â9Œ ÃAkEÅS8ÓöÀ›GL,b¢ØüÜÞ4ß;—”´àú6U ‰s¹ ŠÏ³u8C² j³Ê¼’`6—°€k®Dü}"«,=* Ë-7@Á%Š…ÕÇ@!ÎíMûj p\HPXýßBÁœÃÏ‚ÆãE}æ8¸“[ë›×Ù-âÔ@ îÒ¶g“Òæ’L GÕÞÀ¿¿—ïÉ!ÐîI¸Øgr–õ|kçèI°ß:cZÆÞã ZÓB¬ âEã#‡F!3\ ãBœk\ì?”®¿/­´îÙ0Dá툺iLi“N>1ž§¹Z`‡ƒ36‰S°¥Ù µgwóÎYÕc#QðR\uÑ3A{Ä¢ê±1&DÎÐN™rb’ä8«ãR¸BˆL}›³ ‘$‡¨C+òÈ#+ Œ•B·ñ:¨¶“h,óè`Þ±qd0Ž‹!jÞü·|ǽÃg’µ-%¹Î$ 3ksÜÀ¸ìD"8‚Õµ´æ6þ‚ R ¯:×S“ÌiO´±®Ê2¯Q7•[ ë™Èqt2GÁX¢tŠ€÷Fÿ ;ðxçý9È¢³¼YÄÜ"ðTã ˜1×TPq3úDëòT•»u@àRÒÖZÒ+S;¾Û¥#ËBÙ÷Š»ˆ€<Aúi*ÛÏíY.&¥å¤„j3ÇÒÈsŒq¸—'0³ülžSDøÍz8ReEÈ)«Û}z9 PóñŒáÆD*ÒÀ±$½ó J4»Çw¯›‰RY[–ÚÕåjW.(ª¬‰1œJ§y¦r«v¨8Ú÷ÜúãÒÀJ¹Vëºdcè»Òè¶JêtªØ‘+ š¬®Ë²„<«›FWÆž»ÈÚº´ñú‘}+•6µEΪºÒÚÊ4nèir«š ¢&S¦­´Pa¦Mé¢éZg Þ§©Ý°6väç“¥Îa~e€´öS í¦1:‘Ù—y)5ò8<È„ 2\ï@Z½ÏfRÌõõÀ³Ã RÈ ¦u‹T¨»@AÇF©ž+‘m [ÂñÇ`´/ÁW:Űlsi™&4Þpe|ÑÑÉŸbüˆ«\aôy¿ç7üÖð(Ñûˆ¯é—ó1ÊݸÇ=Ä“Š5”õEª„Bœú<¾= ‘®ðvˆžt»’–¹ƒqFÛÒ‹jvÑlÊôH‚MrÀ >ê:ä+‚Ö±À…Û-éCQ;ˆáqÐxðxþ}ÈSü“†¬ôå— VVtJ]E ú›ƒPQÇ¥.ÚϦãMñÆ·w¾}ièáàõ’yRr4¿ÏÔbˆ^qÔïkp–JÎ7–Є¶Dba>ƒ\{†|D™ó¶¾À×(«ï±õ ÆHFô( /*0ÏÒ6ÇuAPȹ‚sÎæ†é‚{— ³ñ5¬5O|#«Ñ’tÖñÕQ“ÜñI‡cî9zÈQD*k!ܾ‹&‹&Mò Æåáúÿãv.~†»‰X2)?Ê¢1+Àó·²–¥–‹pú’}C-~P¼`§ ùÃ'Y1 `‡òé1ÞG~‰òŠa'}!Ò[cNu +íÎ9ó†ñ)_eù D~¹91"ßÚfcx ‚Y ÄÅSŠ £Û—£É–»ZVÒH©Ô8Ç´e9±…Õ\RÛ#_2D3#¤ùÿ! ’fˆt]ÿ«Þ<Â:ë}šïÀã!‰ÁÏáA¼ÔëØýã‡4B¥÷qÀ½Ø¨°ñ½ÃmýGªr1F¦ŠQ‚õÁ4X„L¡·Ï¿Dañª«ÛF/$¬¢%Ì‘D¨_JÓ÷$ž¡WùÞ7qÏW,²BH“p2Žâ_0*%¬9¬ˆô<£8ꃳ5£!h ÆKS²Dâ4ÆÜ“ˆ˜YIG^ãé¾hÜxËÏÓ»¢DHõé×!i&VOzDþs&½˜“<÷Â"ðW(ÈßiWäïw•VÂoÇWìšCåÍñîÛC=$%ðúÇþˆ­Ü „×—8ö1“Þ˜¿ú©óBþ¡?çóÔWcºÇ¿àáÒi—‚Çd< 5†"ùwêÓò¦(õWà@Äàé$(‚Ø2¯g €ÿ2´]Qü ÷“ħL›Ôå8Å%0»‰'ŠØ?•¸K(‡ßCA<¼xLx28kÍlc´oÄV9ÔE» ÔT"åh!뼩èù—T,zÉÓ4äÏî¬Ë’ãß8»šIŸ¯ãk`u£Í/Q èB²•Ñ’u—ìmB Ñ?ÿ0ô/‡èÃO½ÀnôoŸìlýÝþ÷;åÉhendstream endobj 840 0 obj 2670 endobj 844 0 obj <> stream xœÅ\[o·~ò#„ôÁ;…v2¼Í%E’ÂI]4—ÚšÖöƒ,Y’[Iëèb;-úßËs#g¸+ÙhQ–WyxÎÇï\Èõ/û]kö;øÃÿ_î}ñtØ?»ÙëöÏö~Ù3øpŸÿ9¾Üÿæ0vp&¶´S7™ýÃÓ=zÓìvp¾íìþáåÞó•iª‹ÛÆâg‹Ÿ×ÆzÓvfõMãWOšµ]ýÐÐßôËwÍÚù±Æaõc³ö«§ñwï„դ߳fÝ·]gºquûÀGßS÷ï¿x/ 9ÆŽ«¯ý´ú^ßXhûrf;àL0Áê'xð8ÊÌïþÆÇÞßÊ(ø¶ÝL]|Õ’DôúAæ~yøÇ¨D¹§!š ¬Þ×Þ¹Mç¹ñMjŒC†nŠŸ‡zÏ8Q0SüÅié^çè£w#t¶Ã±N‹¹äãEî›Gí׆Ðø§½Ãß>_]×Ô”W÷mm!µ%g5]çÇmMß* ÙÚŒÓþ:"Í$#>]Wgð&R"œÊ¯ ? p=«+üÙ¤î/›õä»vØ:jÎu¨ågZø%Ô:޵½jÄüÒ]~~]þµÆˆRmèhßÖÐvQN B¯Ñ°)fE©Æ ÖGë7°±¥Ãaþø$!ŒâÎêLÜ\€›0dTõ‡BóI~·ºIÆÙÀl;ˆ|å‹×l—!¢šÎõÐñ>¦çOòóïSãã]öã$Î|—º^²œbÚ7ò;ì±È{¸Ês^ª¶/ŽA »n*hªÛ3/ì(?UÛ_Y³Yº,÷Íž‘Æ3i äQo‘˜ã§é%lû~ä.?Ÿ€ôFè”÷ éëµ—61Ôªþ±E+Ôß+h_È͆ùX"þ§'— ®²ë†ü.­ø ‚|Z݇-t·tUsäÅ\•t—¶–Û]'*KÆ{Û}žz¿MG®Žúy–¶¤J߇~F•wkãºÆŸÇUìßãpn2•åÆª;Uß ½ hÛÅÖzW¥JÅ„ÇUÖÜdªxRõ·W ØÔ ck½Ä-G…–]œ¼²N~ÞD“.–q“!›­ø¦XæÎ½V†"Hmþ^’ý9ƒà¨©PÌIîúWù8nQ¨ J”K¼,„U‹•¾€Î ü㯽™–Ⱦ­ T¬s we“³*„63£¨AsÊÛˆ@;ÇÕÁ–Qa *‹N? owoç¶ù”š¸OSK;oj&ýˆ0XIµ+îü¿0ñÒol¶°ó–~å ØnËç%“ ÕUƒ^ØK­{I,Žôø‚‡Üøªf’i—¡KÕ«×,Ÿu[ì[Åùjcæ¼iØ;•>Ö_Ê;ˆ0<¼RÒðÏ»5°•—/U³Ñ‹ÔxW3EI†²MªÌ—GºÈö{UnX”¤˜ê¦¦ \ Ãæ¶0ñŒ.NjV«Hyg_›Tå éI°ž\mj8,ýõ®ô~«“¦rÒãŸf5¾^À‘,j<_(l[ä#Kú$þý”T¢¤¿/žŽû11s¾·TM1¦ìþÚw­K„hÓ†ÁG:ú(aµÁtÓ Oc›t0¶õPÊŠóMÓà!’žˆiç­ŸôÇês Ç¾o}ú’ÙA‡ÃÐzU¯®¬ Áòûf´é(¶5½Ù¶‹¦pêý3üF)¦ÁÏÅ);o#:»Ö ý‘…3V„3½Gá¦8Tð@¨Ò œÚ± Àð6†÷†B!ÓŽƒëƒ’ó³ü’zž$!Ñ­qê•M=ËQ«Ež'GF,»CÝ ëF¤†M@X€£ÉQåÖ˜‡A;tàêè)Žï\°<7¹ÄÏ!`é)ÈçÉm˜p0Õñ—ø(Že´ì˜Æãj°ž7(·™b’ê,ÎAîÃQªŃ˜CQí‘h dñ#Ns»ÈÛýë ß Z+‹™{Û£±…“¢c·³8j\J€M4¤·,f;Üe£ø,‘ÑÐ5§)nHT(°/fv#’v÷8M'OŸÛÔ0‹.“ÕTºLÔî¦Á5‡½Né `ÛÛ&Ñ=mè~Ü Ñð «®Ÿ¢¦mÙÕ¯0‘Ã>vÇæ8Up´[z™_æ\@ûaù¥¥_ã^,ìJŠKÛ2†àqs½‡÷F/’Ò0rBÏRzÂfÂ௄Á)*w4Â÷å™7‚ëRÁ£8‘Þ¥G0g‡sf›n–ëãxÃ9¯½s,[RвØLÐ{QyöɈÞÕ aGÜ•9W¼ôXbêæñÁrˆŠPˆî ÔW2Àmß;œaë8ãÌ”=â0QÔô—&Ñ%r’ý’ K”íºŽ~ ¡Î[¤„XFñÓv%`ø? /—5»EYˆFJhHt‡Ú1øj:b‰ñ>¹1H6c=¬´½Z–"*í(è!{ ï'Äÿ”ðœGA=ƒN=*ømz[ñÊ ‰¼y kŠá•¯y)Ý‘ÿŠN½³”×ñ ËÒµØÈ+JsL„˜X†ÍáljM¯XÆŽP/¤êdM¥;íVÅCúaâ:r¦'ß= ”L’Ña†3mãK‹ãàÙ)­¤Ê|‚wM@ôçq'˜EŒðºq}?Ф³ÑÆ®dBR€HL TC6Û!—3"6J‚CYÊðóC4ôèËõÒ(-Ü»~ÀfÚ5¼J3€‰Š7´ž’€`%€\!Âû¶Œ Z+1Ü×±ý”ê.y;ç9ÁQž**\Ã]ÇÂö áHµwçtçÀ°BIÅ}‚dæð6húŠC²ÓƯcÃS|ú­>'P”Ч’ã'¯ÖÃIm—O‘x2ý*mµ$בr³Ù)O±¸ëµ*ÓOqLÔ/=ÜeS¤å,”oTLÎú–ªÈÚr; ÒXhvt¨’ŸtŒéIòVÆ.µ±Kp»œc¢‹{$ï4ÏHg[oSP¬H˜ôΈƒ‡üôˆ6ÍÄ¡ä`7ö0‰"Çßà¬CÇPWŠ#hµ¾¢OB•I(û’.«S—ÈX\ŠÉ²Oý\“Gœ ‘eßf`a Ù®eø£¶½ï,îȪs«‘¸*E†ÉâNT»ç·Áä5=*G|À8¯«ä©ÂÇØ–§”ZY-´FWmzªr”lø®q6›àü<‹¯ƒÕH[q36dK¤–¨Hâ L/†‡·Nè6ÓÉ+IE`BDPcT¥ EPãºÌïê q³-ž?Á*}jtÛhÉ[¢¥JðCI —|³õœCì®–½§bL?MÌ<¸Ì’yÌ(Öö9¡S¹Ö‹Uã(:Ïh#¤Q‘€’!úð®–ì u¼É <>a;HF–êyˤ6@Ú[g¿'.[°RŒ Ú_4M®•G^[¢XxîŒ.Ü1zº¶×…0{”F¹ËÒñ²ÿ|„¼9n ¶k›ÔÛàÍ(³©3OJí,VákaKôÀ)‘“4h-;@ýØsD¿Nn‹ûpiÿ¦KW‡‘Hrp:à&Yxá{PŒ„HÊœmÏÎOÍv$äúÒäs¢È#e”2t í!qwA°äíâ`f¶ÉYPó:: 6JQÄPŒëTÉ)ÖÀBÙŽ=fÙ^âsç½,vS.-ƒšù„$H‡À»MZ<¥ºÕ*¼Å”¤¬ÖÁBœ¯Sà7KéV¦„hèƒLr*yÈLÔ'e™¯(*8CL =ôÊ;#.àÜÊ©/S·Ã2°ã¯ëF¨XpMŠI+q9•®Ö{"AªIç(ÿÄõH G _Ümp”%{¼âÙ£ˆ.WZ’\²1Tn*p¯%GG Īæ€D‡¹‰”C]ÇwqS¥d)EXJ‘=K!Jv JOW@|šL‡Æê`9£½ =K¤çœ8íòŵðoâì,Ár^±é¦Y.OŸÎ-ÎØÓ(‹):¬ñä“1 ðÃiždSVÉwåõ¬D€£wõäWïòyZ/ÉÒB¹¥^'#)Õ.½òÕÔÁ$žLÙÊ<$àe^äíQ·ѨÊqäå-•â©C_–/´_KÂæùb6¬Ò8ÛÏ„Ç1´ Ž/²õèøj%µ<'x°iL'éqÕÒWÅ4È–s]˜zñÌ*9ðÙf:4ŒöËØ»ÂtâIiñ%«¡WƒM<Ì<ßdê^5§ö;¼êhÊÚ•ÁÈd¥žb«ž£Dq`èd©ÔOëᾎ3ñ9F)cx±Ew’©ïr‘¼J¦Iw.Å0Š]}×%°Åñ³Êßçì @(\ÍÜ>n´I…ÖTÖá çþx<¤|'VI¢F2QåwNó-#b/EY·ŠfmЧAe¶v—Ž!˜èˆ³àGßK-$üŽ¢<| ô†ä×ç9G»#i{Û±lЬg¥e4·Éƒ=sxÞ; T`9·ÔYeÌÆÎéq5(N«WØ%3í8ªj¤Ì\ÙÉáZÓù#ÊN%âcÊ!(ƒK"PÕÚ2©ç]²ÕÝÙÑfŸþp„ÉîñCª(Áœ†º(IíÓR¾ P Š9“ëbü¥Ð/U)˜‰y–ò”Ú-†@ÜyÉ-Ù:ùs…IÜ®²ƒˆd)OHë;ò³ˆ’âÚzHUw˜ªƒh–﨔ð?t1¾ÁR1£rîV9SPW%²‡u íóæ_/´T­eÅc:Ò…Öæ£å2É’IÜÛî-aKŠŒ3( é;Q¨V<Àû!XõIg[@eW~ʱ—,(á%/ ^ű?'úêˆdæ÷Ým9É0n¥@2lùQJ³S”‘«§ ³œª˜°Ì 8÷µ-ÝL£ ›¥gN²?äèŽH¸œy7çš±8êTñÒ³´c1¿¤­½ü ßè±fi"ÓÞ¤¬äknõ¯² s;¼R !Êêßø-£€7gß!Õ|ÕÈ·Wò_J›l«„§üMµ/k—ëª_¹¹i*× ÿÙT®Eª«¾ùÎhyq~y‹ï«üU‡üå:uË:7Ê­ÛhÔ¿}Ìð»Æ,F—«š‡\äè3–×ÿ!Ø)çY^Æ–ÐWµþ®øJÈìÆêì‚»ºY¯îKª‹/SßÚÝ9ÜZP±ˆ8Ì)¢”ß]¨‡TÔ†Çw|Μ×A³§ä3Áw}™cð:EÊŽü:’G¦’;!2P>~Kñ_*¯*ïQP:^G0¶ŒåYÎÙušä`äÎ:q›âýÞ3¾cbú>L5¬b§›/HþšùDJßìé«q¸@p™ÇÌîŠ#5ukŽÏJìG;.k™åWvÒ!7Žì1M¥7éèG…©V.è«d¶ HäÍa¥!Œ@-Æ ­º EµëŽÊ£KŸ $˜cQ_ŽÆ÷JиSÝ£ëž:‰¥êõVüÒìÜxKŽù8È¢8ö¢Q‡qè¤8iŸÙE>4ÂÒé”nŽ8CßöÚvKU£Ë²³³Ú¬®ëë§+¹×qåT°–¢½,+gQå†tQbîË„¨¿êKA¬Wçt9b~ùMNذZ–ƒ¬>¨š—ƒÄµÿ€õº¯€¡‚½;~Q_þc( •Gi†öeª–øÙéìüVä}0 #Ã4o>}ßïèJ ÅS6¥j(„³¨ÂŒ³‡d§|–ªY'raÄSñå÷™ž–W˜dŽgi ùÏà„â¿-Ž@·U?«³äOXýãý?Ç?ÿÃçJýendstream endobj 845 0 obj 4477 endobj 849 0 obj <> stream xœå\Y“Ç~'ô#öm§LÓuuW¡ÉXa;$Ù–ÖÈ’…€E, įwåU•Uݽ³¬.+0ÓG™_ÞYóÃÑЛ£þðÿŸÝºóÅtt~yk8:¿õÃ-ƒ7ø¿‡ÏŽ>>I›®ôó0›£“Ç·èMs4Ù£Éù~°G'Ïn}½3]Ø…ô7váÛ“¿§·œ©Þšç>ŒéÅ“³ô🻽ßýµ3ýêìîŸÝÞîNàú_º½Üø¢Û;;ôƒñ8þþöé®õ&]ÓÞÏcÉv÷yõ^Ç_îÁH!=ãwŸt®çüîopçSø'=ã¼íç8ãk° ÏòcpÓÁøãîËn?¦«Öî¾êlú¬ÁNºèñ­û¥í×DÛóþ÷nè§ô™Èðªs»—Ý>ì~J‹¦4ƒÃké«q¸í×iÂÝ%,ñ<Kšð™'pC®™°;N“¿€k8ࣴïÇiÙø¯äËgðŽÅq¦¯‰¦OÓ»8ѳ4Ð1Ž»çðýBT;MÏ]«sšÎÁG¡xšÕÍ84Œ÷]ëZÍâîAgÇDß`i³6‘n³Ø ‚áØ?À$ÆFÍìOàÙ„<3î¾ïœÅ™~ê€ìÎL½ŒÀìÇÎΰÑw‰€Y—šq¥iGi\üúŠV1Ç …åùq÷fN<ñÞø˜¾¾ê„X@Æé7»|µ ѧϼvw;=ë#òx»å§ÖölÓny<Øà^v¸Od #lôÃ4È4!O5êQîã¤íÕ„_|ö›. Ö-ò (¥ðÅèù^áí#m÷„ü=ˆ&€º ƒá&Ÿ‰QÄø˜) €¿~uÕÍÿÀ*åúdp+0N L#^;FaE¬Ø´+P9F à>™°Û§ø— à é( AH³dTÐxõD½a4͈àÇå>ƒ89G§‡vnñˆÀ?øty™ÀA[Bl„9%S‹˜ßù¢``l@¸°ƒ(èˆZYià t®ÉÒƒ¡ÞˆÅ~ê’ü$==¦-Îi_¨f Æ"§áE&špT°`‚Z…> Ò#Q@:®èãqÁ‡àˆÊÈlÀ‘õkGxJhB?zAK¥×4&Ülò/~„fU¢¬K“†;¶@,ªæIy†ñMœ ø¶x4ø4!Ŧ•IË“ðÞC¹N€¢]×ÊØ‚ˆ©Íˆ€ÅqÔæM¢Òm0¿— Ï"ý2\.D~€~>.,œs#Âèoá1¨ Þ¢õO¸„ÅáÓõBžÎûxކ mQæW뼫yQÆ~L䯋<ìáÊÆ¹‚§žÉWq››!] x§¦m‰#ͼo²ÁN½X€€ |QÐ"Yà¤,’=q ¸R¯ù”Y'Þ²`iDŽä&õŒ2QÎOøê+r‘§aæBD¹fçÉyBÌy\!ñ¹¾–Œ2l vNÀ„–² †eiO“7ø%­ó ?b\* ¯ž6±%ñÚ(!#ÓPiDY¬):õ)ɰV]6¹ž&»Þ§dß+\:¶ÒZ²7Pк&(-s F+‰Rà ‚Ökñ Ò=›ÚÂTèÉ*)û–¤Ž §ôýmúI­Íèâe¹x™/~§th¥íy]¹úa¾ªÄ®¼_^º[n?ËOËÅ·kO>ÐKZ.ä²ð3©ß­í¼«àÑõêóž<™>3#³¿•û«¥f2CûD¹N{›ð±¦ 9ìH€×F†ïÂûVñ ‚(„m‰E_ÁíA>;í+Û©µ@i!¸Ýk‡Œ¨'íhrÜ)N<.x.Hh{e]Ú4ÃÓ´š6Ívp¡0jµJku\Lºsêcvût©ŒH¥R…r,Î%x¬uè4b>AœøqÄP¢òÚ²šcVL+ºxo<­l0¯Q”ù9pcÊ~P¥©Eש˜••(’ ö+¤‘k5¾—c(ÞÚ¶Ê Z©ÊjÛøñ,ïû;ÌǤŶ옄ìûÉÅ5«ž|Iº˜Õ{ã’±ºÊ‚m<]á‒8õÁªmØßÏE]Ì @ æÄ2IrcT¨Ùª!QÀ|3y¾å ÐØì"mjË]åÂÄ^úQ£«B°¢¿ÖÜAKµÌ‘ô†Øû;v8;’ju^jo6òPí[Q¡'ÉÊXÔ‘ŠGðìª%IžPP!()² ² ‹yìBÈ*öYÆ ãM†Yãt‰#uÑAîÀx'þN/Ä!»ÛŃæ-݇aZ‡Ê“5 Ü Z[rdJzïü#ßaMrz$k² ÇÙfdd–±B¤åÓ['jÕ ñðÖ®3nÙÓ!c$ÇËÕ\µ>ƒBÚ‘7‘œ$¹¡Œ…óêc5øTÎJW8gQe!s9ßøò96uà«‘¡œ`Vß%V+2L —¨´#“"©$|ïØØë¢ƒ„VkP$²Á9—W=ÆKó«UiæÜ6P1Ð>,À N®Ä¥Ž[ò܈²‘T¸—´¨œ©S{Ý&± ëqÑgÖàŠª §tXSœuš¤|+É” ›Î£²çDÁ jY޹*ÁñüZmë&55ŽG ¹×ùb{Ouv™È{@C¢˜Út{.§´@@MÚèd@×@i“¥5ssŸ ÔVœ®’×p¦¦„Úâ'ÊNä“Tºµú"ºŸÛU²9ç,¥›GœåÓF;š­”"5ÎDiq1"ÚŠ»¨} u"5³ºÂQ@lj+Ô°i_çl%ެȉª/TÙ ^2|MRófY2íÍy®›$üÄ]‹Ì÷'J©)C,S®[“;PœÍù¡¼ÆÆÀ¼Ð÷pI:+ oKeÛ—õ”=@ioñ#$à¿»p7À?þ±ª.ÐWÈô›ÁM»=½ñº[©‰<*…32û%èV¥Œ2ÒÓr14 ‰Zâ¸Õª†ºXž|]]”‘Þ¬Mÿtí¥\ ÁlЍMJ¨\—¦HÉ»ùŸBÓDI;$ýŽ”\­$ýú”¼ù2.iðŒÆ0†ßž†[56™éríþ»•éYqÜYߢ¢›ÿo „/aL®k„|ÿ¬lô\RÕWÅ&éZð‰ ÏûñiS«þh€ßT—þNl{^‰Vqãô‡¶q‡Hüë ®Ú³¢™j›x!OÂ4þ!yRÒÏa˜AÊoò8Ír¥Åù—!¿Â _ŽE_îËý{…Õ¥‹¥Šèäâùмè)Ûýs-9‘a’¨ÜÐ,M¨•"­e˜‹jÃBú'eÈ"Á³×‘£bmƈ©´?V;‰tlSÚÅðÆ'ËEV…‡RYõaVÔy_Wê×zzær¶óù I#ëa_~ˆgy>“Gp¥ŸKܪz/Wžý(.¸¯_‡¾mB¢6Gž/w^·…~žGÂ^ZÝ÷”4ó¡O$*¹†ëf¹$aKSSi‹ÁHÇÇù\쨲Y×8Ü‚óÙ­Ã =Ö(ÆÛ;|þàLbö*aÅ)N[AîGŒêZ‰IʆÛ|X)Ž»æ›|cö«%s©¿úê„(²­c#ö9”Ïõå˜% AÒp¸ëHJ˜&̺­Î6%EQª%\§È-ùÔ›¶[Dªmœ£$¡±õˆÒ¡Dé>³U4¨SVDˆe1SN¥¨ú`VKkP¢Î27”V ïUcQ-ó5àäU ˜jõ” Õó•”+wîHV‹k©KõæcÕͳuø[ÇG\ zææÀªèTR{[JJ‹F€1÷Š4Å@ÝT÷\ =›še‹I=S¯¶ -^›ò8(Œ$r[UËê` o©VUëj)+¤Éˆos°*éÉüÂ@N‹þ÷»cIuÐL¹h<ú J8æä¼ãÓlÐ&´â%§€ïeåf²"ÄnŸqØÝc5©£¶dlfWö’áò°£Æý¹¨/Ð~²/ªÙ~*æ̹]~¢s) vͤ¡9GB”C¨‰„pZ¯erÉÁYÁÙn¨ö"¼º¸i›ÎTæ‚íºVM 8ªª>!5%…i6 |*ÂåÕsíNòÕùÈ!Üã®âš>´†RçlÖnºß„N”>^uäУý Ui?ż•î8<ϺX²´ÄQ7^Ðñ¾Nñe—A¶Å¥Rv1ÔåULá2 J9¬y‰{Ç'ý*%Ï×VDi ‹}@¥›A ¤H*{ÝÓ;]КëS– ±ŸrÜgƒtÒ\û™\t½I µr.uó_Õ4´û ͪ§Ð Õ]Ò´kOÃN¤*´Ÿ)UÜt-?Õ‘dlÆó[ ƒ=»$F —«çÒúk ìÚ9nºø¾Ë'ÂDÉ•º:øÔn‚cÑØÆð]šä…—ú\–ð4t0ýºµP„¾×Íš4¬4WzÝ[‰–v0;ÕŒ“ÈÀ¾^ép¬òcκ¥yÞ8 (àØn"Z\ў H“ªë7C<ߺqÞ•îKߨQ!ÙOÔå~ùÉ”~_å<*¥*_¹¶Yœ®»Ô‡!ñì_Ž7Dc¶ìP­Aà¼ÉY³ZÝøñªâmÏ]^ÈJAô º„1GÕ ›#Ó´Ñ+éöeaË\¨`ÅÑN7 ,]á#^Õ™}O\‚7Wžiªõ¹°ì›çVVÿ‚¢ØR±Áï}¸PÜOÕ ê ƒh+¢¡k6Ñë9oÆêÇ»¦ÿHqó®ñ$!ÉRb™í-‡¥‰kúb‡hChÁsfké<=ÍݨØÜu™Ý̺SœµÙÒI‘V«Ìíž~ÂE¨:˜Z»W®{0UåF°knÎc­ä¼ÛhD—ß%YEòƒ Ù¿\´oñ§›PD’WF—ôçšÐö#Ö]MƒZî<úHºE§ÒÊQ¼ XE>TŒö±vúVŽßÈ/u‚ÍÎÈ5š’ñg5Š«èÕIBð1ß%þýµ~g€]‡;]hÙ“›ŽF¿å×Óo†Àä‚Üò£í:Ü6?Uá'É{¿·X÷päæºÐ.g®ËõZÃ*þɦӚÎyàØRŸeàcý"kõ»HY©ÔnYìc$2Á„ág¹yCƒ± ìrwýšJõáΦM÷òÃŒ9¹õ¯ôç¿Êjœ)endstream endobj 850 0 obj 4633 endobj 854 0 obj <> stream xœ½[ioÇýNøGð›wíxú˜Kжb;ˆÈ ÁŠ+’†É¥ÌKǯO×Õ]=Ó»KQN`h½ÛÓÓ]]õêÕ1Ã?ö›Úì7ðÿÿøbï‹§ýþéõ^³º÷ÇžÁ‹ûü¿ã‹ý¯ÃgÂH=6£Ù?<Ù£;Í~o÷{çëÆî^ìýº0U»h¿º²øÝâ÷¥±ÞÔY|UùÅ÷ÕÒ.~¬è_üñmµt~¨Ç¡_üT-ýâiøíàžvñÌû¥ZvuÓ˜fX†9ðÕw4ýÛÊÁO÷!ÇÁØaqPøêÇÅrù‡ÊÂÐÐå;Ûw‚ ?Ã…'Af¾÷kXgÿ]VÁ_8~PM¸Õ’DtúQö~yø ÃGZ£Ùøóeø¡Œ«ÛŒüϽÿ<|÷¶ &Q†pí-[L•´´ÁTpÞpp:3ªø lôÐA6» š{c7Hcq` GáËy˜Ø™ÅÛʶZîô8ë4\<«lG£r/Þw ÷Œ‹Ö8·À„°0œdp‹«p© ·Ž´Ö5ü p4æÑi£˜Ô æy˜‹]'`ÝÀÕ1\¥Uâ­ âÈ`ïD.çAÖnó¯àw<ÄZÿ 7X82¨ÙŽ®6ð)y‚݈»³’>£-<8ìÛ±ziÍU0d¸½ï-š»%À½ >>Jæ¡éWà¶ãØ4;ð58Mú¹®À›Ž*ÎúÍU ÷áÚà§7¿Iò€ a?’8-•æ&ÙA/KQ̰ގéQ€Ë®‚Y¼%9bo<žŒÌò=ÃÜo;¯ "T{Ynáö‹è h²kXmDK¿Šð|ƒà9pª°ìÖkÓ1däŒ ÃRp¢wŒ¾8¹çlL§XöFεs”ÉÏWy2,ªÕúrqÃ÷xä pNPº3èRÆcÆ+ÆŽ 2ƒ? ?âEÛÍ pñA1Í<‹«ˆ( ç±rÐkM¡5qBËNÒ*éX%ˆE—dràe$T87±ËÒ Mràcr»6Ò~açèZ¼FVtŸ†£ë›Å]Õ:Ü3 2Ú^ãlD"Óõ›x%¬r$äŠÑ 2‡&Ó’Uƒ­EÑš™\?FÞ\§)ÅÝw`ج züL±ÇSØÛnD÷Á§î‹ÐxM"},´Ïi® \Ú C$¿äh«¥{/In¸£iÅõ€çA­z©¡Ï¤…çÏ9 ég ›¯Rõˆ’Ÿp ¦±-•!˶ˆ•Ì‹Aò6­yŽÁ Ö½GÜ嬯ŴÄR&âhQƒ3Ì|YôT_“*”ƒ‚õ=E”Igî##Ãè7F\_‡¤—9ìzA§2‡HŽ*}ð(±€Ô9ðS†è[ {oM3bŽ5R4‘‘=G ½‚Òe”%ŒQ܆CÁ¡£â{îÐ ö ô Œ±‡šÈ©L lýâÅ(˜ò+Üðz“NSµ4„Ó¡íÒ Ž6×S& ºéXDvEž1*[Ìà.‘QâÍ#º2ý^9BM°&™ê (È*¹‘„áõXGñÜ:ƒ;å{ÑZ,¯ª}€íÞÎR\/ñ"‰búš‚à8]€¥À òûDê$xñq éØ$)OÔÙS dO¢ÄÉõE‘s!9^J rSkÇYv¡hDº1ƒÇÒ# l}nd „ „ Ã¥„Pvx½4ÆË·‘ÉàÂqåÀ¯ÍC À¢¾T[ƒía̺ÚFŒ•°ã£H„ÉÇ<’’χ¥Í„§òóÓò øïà° bfƒ]”V9Â|ÁHÈ¡CäÄ$Ùô€ à[¯Ó¢V±)gaª¤ã%Õ[h¸pŽÿÂýLG0Ýrbo'A‰Àò= @îà€:_Ð@F™[ d±í¥ÐÌ Î,m4@„w@W)¥ƒ¡rdÍêéGDÆ€FN(K¥ÂB²1ï ¥¥$„ÌgËÙ%—jóÒP¬R²¦JH‰x™©PÜVï÷¶È[ʉú•ãr'A7b!¦AÛeŠéYPHŽDaëá¾ÍOŽ-)½#(Í é®$çYqÚÅl¾P%)Åîui=¢flÍxdP¼«Üˆ h±Í|Ñ¢/:Ç—¸’xÕëÊ„7ÔÎÆBR qÙÂu¸…á\‰ÑY Â…ÞW¨7À¸®¤U@»-ƒK²QÑ‹c£‘âÜJËÀ¡ÖG‹®¨¨ÙŠçQÅjº<ìl ©cà‹û‰-Šj÷ÉLðVÓn&œKMÔhæŽÖÄûÊc8{dU]yDªá8ð£uQ€ÖÑqaJ­˜dâÆI8´ºÍÒ9Hßb‡ãÞUãp[$Ãn„£d6ç~€d8Ñ5b¬ÐA£u*hÜÚ^BzV.»®# êÅù9ùçÛ¡ÓnLîSÓõ‘s¯ü¸O)¸„x·¦EÝ€wq^&éqjLò´vÌÛi®sÒN#†b?œ´i! œ¥Ý>W¿W?±-2ñ*é›QBÉ|ß×)Ñc(Ѫ‡àÞaë`~‰’ |%&ÈRûO[IÞµYÚý»¼eÉEvÑW¹gF&_uFûªwCìl:#tV·1\uÝ,\yŽÃY»Á[7©“–]±ñƒR%çËjl6Aó6¦m7´•$ŠDÖ)53SC©÷-zóíˆÒºL† $ÌzҢ픶Øiî’—òàA£¡´Ö‡WðºÌ›õ ½§˜…¸̦$¤³²66óÑ,€9Ê1J5˜'ÐÏj0îšè6#7­Ž$·ð1H‰G–šP7¥ÀUÜ«RV.<„9“ÌÖM‘"Þ¨’±U*¸ü4GФ” ˆ©À¸>VT*Y{h”tÄÍ;ânbcaÊOb6µ<)Ÿý³ÁÓ%RÊ–þ^qšÄ¬o¹f “b¡sÎãÞ:bì°Ý˜ß‘¼3²%oajâÂIAb;ª®?ú©_RÓÁ)$i%Œ‡R5¾†)fCgCh}#RK¢ ô©óØÕ}; ”¢|×xİҘòµ¶Ø ß®´ñÚ2©ü›lQK„hâ`—f.ãà+ýfYªÁƒÜžÓà:ͼQa<- ^±¨S;é¬ â‘$T’–U‹ÉÜ£½£/5Mí'X¹Œ’@—•RŸ¤¬'i­Ã8øŒU€nPPÁŠÍL»c¥çÉÇ*;Š3ÏÓ×ÛbÐZµÝ£‘rùÛÙ¥d˜».©³ðêïªdBýÚ‹–”Ï3Xˆ±ïJ7ÇA%ñk]p êNJŠºJ*WP9Ë–"WÿO`ƒ èe¤¾«Ò¡œ$íw¢ë•f“ù¢¹ÁyðCA½Ä¥ä!71÷~Ûž<]´!Ï¢<Éàçi£³’•¯3×ÚW|NJNÓ¥DBãV´­î?a¶ߤќÅÄ žeÈÛã.deðÿž)çüqQÚó:1ÑÛ’fsþPDß:Ȭ§–Un'3'Zøú!éëuZ÷Ë´®Is»L¡1`•daWBÖ«’R’Sž•BÖ» L+ƒub¢C½’fªfÜŠÏO£Sù.óIp„Ûò˜1÷Ð"¨îHÓÁ”p9›å®4X ‡«­d÷âH>·Ga{…üäRø‡I|ΟÒè/éë¿Ó×§iî²ÎïEÕ¼OóÞÍs•ŠçŠÁëœ#>.ÚÜÄÁøZ­ŠÑÀ úàoðñ4þLٔϣ±Ÿ2=óàã4Ø òæ—XfÁ¸t- bãóšNKÀHh9ÞÐîJú–º]‘{pÕ¸*âæ&#±I€iÛô5û«”R²™»  qÔÜú~TZ_Oß ÝåOÉÌÊ[ÒàAæ7 $¢w…¬ËçÐ"&õª?j²~4#»MÑM…ލ›@.½-)"Ïjx¥ëÒž4W §oŒ¢…³mâŽ]´ÝH Ohʘ”šv¡ ðÑäu‰†8¨‚wÒfQ¯õeuÂùB\Fì˜õ»²S1T²IÖÚ^e$ë †¼@$zðWN"ö ëA0²‡wê-÷2$ÖÛ0£’ UKã /+þL"hРߥkIéÌGïUÏãîzöYJ!•ÚßÍtµ“0vñ)!7C»ÐÀîÂTfæÉì=ó¤« Ü ä@ŸsØyŒB|£­$rîv½{Î'÷/ž?ÌÞŸ”€mfRH]þGÛ“"Q,5 âì:N¶C&ñ ,$×±…º 2üeÉ.Ù_¸Ï³œÎ·ôRÚRTçþÓX5˜ RÌ>+ÍœT-œªýœF¿ãR¿WOLtòMêûˆË¸4¬ÙNÿêëY¦ŸyY™´! ¼{ôLwyÿóÝ›êC6òH6мï'ô! y]t«7É­®fj²zS—¿jãËl7åO÷þþû/‘ehËendstream endobj 855 0 obj 4186 endobj 859 0 obj <> stream xœµWmoI þž_±g»Ì˾V:GãT×Û“8>„¼©IJ’»öçŸgvgìI¢§ªÉÄöxÇöãg¼_™«DÚ¿á{²=¹¬“Åv$“ÅèëH9e2|M–ɯ( ’¼•­Jºù¨ß©’Z'µ)r©“n9º*-Eÿ2-?u¿Ã.£¢]m›—lì¦`ü"Í ñ[ªò¶mŠVüÊÐðµÉë²m’Ìȼ†\ôi¸ÇàD)q ‡°4•ø„‚¾T-œ¯³ ÿõã ¼Aá?A8Fá.ÑÑrÖÖà½$ê5¶6¿Êš,ô.FÝ£+>„RB­¤¬Ä”FʆO3—\VÜž©ÍYcÅ$ÏÛ#Û½p§“CáÑœ’(mh¯ƒŸ8³ƒð'|‡Âó ü(p™Ús´®¶ó %…YqÄÔ}AášÉRÔ6ˆLK™I¦ë\ä_±­¹qy²{ÖdãžÒ —öAú‹ý)íÇ™ý(ÂO)zc)z™ŒÀTÔ¶‘[`!¯¿D½Í•ƒnkhÞ.Ðâ}”>ù¶¥Š àõ9׺;&™d?î)m$¥;èS—DkUËXÉY/Ñ(±Æ|Ç~y†KÍJUj‹jL“«@çŸ|/4"óÏr¤Óç°¡®²›ì™2u^WIzÛº¾æ@· ‡Ä×ÙHKÿðй?Ä+{T7ø÷¬G¨a…çè¸mO3ïO«çLß)tKÓGœÂ[Þpñ‡@Š˜½{LÚ]TG(Ï6$®™§Œš†HlWh»emãêyÛ;Ö`ùuHh·x„<\{t^ptq”?é˜fŒ8ô¼´å2~Ëlà £ü²7•¿ÞðƲ)›²±Ç8 ¥ðT±aý’RÄ×ÌÞ 0@È¢00X ƒÀÿ0M‘.â1cŽà~`x˜Þ‘¾7ßQ,:ODcŽÊ˜ù,º¹ü汌ä³ÁÄ.¨ôDÙ@û@k¢¿æP±Â¦#ˆOêô¯ÒTð‹Îc<7?å.PO:hÎ]¤§°?wœp͵oy×p<êYŠŽoä¾l‘ïíÀº`Pµö×BAc'õœ°ÄÀÚú»”öšêNšxCh@èσ‘Œ~žá’ôÔI`z°½€ƒíÁr/« ΙÏj41û«ü3‡˜'d"e]?̛ó ¾# 2 ˆþ ÖÎUÅÍÒ¤÷Á¦Úª®íÌç¦Z¤ÿâ^ôf¶žD¢çw²V²zbÞ›Ù¾÷e}Ƕ×=a½2£ÕM4†‘Š ‹&øcÈ8|ENcß„f)Ó‚9—½{*ôÍ6ç’¿Ù6ù”œ0Wß2 E&Aä¡[®î./sNˆ¨:6Þ± ~ȇ!—öˆ/»Ñð÷Öh5êendstream endobj 860 0 obj 1188 endobj 864 0 obj <> stream xœµ[Y“Çöó†~ÄDø™iºÎ®’áH–´!K~€]®° @²üëgÝ=Ãr;;ÛGUVÖ—™_f/7ã`6#þ“ßgÏN®}3m½:7N^žº¹‘_gÏ6×Oᴱ㣛Ӈ'ü¢ÙLv­òæôÙÉÛ»½ÆèSÚ>Þíí`­qn{o7c 1:³}!—³Ý¾Þ™ÁÛóö|ËnŒÓö—ÝÞMÓ`aƒc9—ŒÕ¯Spÿ>ýKâ‡)M% að.§Íéí“ÓÜžîRbžŒº‡N ŽÛ>ÃiMNŸŒñyû/Æ4ŽDDÁC Q,›²Ã÷]LƒÓö3xɤÑú¸}R_jÞ×¹\ž¶¯ð²ËÞ[–ÖXÐäÇÌâæÁÄѪ¸wwUa¿}¾Û{XÙhH ú:Nx•oÿ†×,ã¶·`XêÞo¿Å‹nÈ)n?Ÿî,JãmQ- ãaQgð:è6Ð8÷vVé`pcèÂ9>䇜yz±<ð¸ÞD¡ \6žÄqpº§øDªo\àßÅ)_¡†sN>£Vnžž|}òrãÜ H{?¤³6!m˜&Ð+Âòú­“k·îl^ÿòæÁɵ»srísü¸þÏðëÖ§›?ܼµùú d{Õ+fqšÁ1nªç°¼!âþÿÿå̤ÔÊÛì´ß^EuO [×mZT~pQd°Iná¦ZØ­°}H(ùx¯wõq¼bþ0NáœGSpš,‰Âjk'pp;1àk 6 ŽæÛ±îíp ¬öw²ÄÑFTûÞ‚faé{@]häç°úûð^& y…ô­nû—ú¢|à|ODKç,ÐÖŒ—ÐÔ| ¥½Pý<ßY\½«–I£Ë0l2¦Qi§]šOV Ïáð ÃCaÁ>2à‡¬2!5-Ü 0®b—´›PŠHŽb¹åp;´í´+ŒŠ v#BŒ´ŠðlÜË1«J\¸pÛ™„r8¶YÙdz¥AÄEÕxÙÀXw0¢ Èt#äÏ9²ôúyà°ÛOS&… W”×Ä’KÞ㪠Räˆqñ¸Ù¸!ÉŠÙ/ÒfG0Óq¦‰ÁV€ÂØdèñ ü:ÒJÏ@¢ &¢Dô Ã×i㪧¬AyStŒþªÜ#9De4¨X41ÿlç¼`¨Û<Òt <.ªÀÛ–ÔùùN…ù´(þ»r —Ÿ&2s'+±‡ä^óU¶QÍâÖKé|‚$â”v—V†Ïê´tŸxÖñ/á´dáˆ0f& §åüDJ¸§[s!H{\aò€c’‹ìÚQß¾1NÐþßÍäðÈy4Cãí³CšŒ7\H´ÙÕ¢´Ó¸t ”ÆŠfaâÐ\ô…%¥v™EK]täâò„c¸hèúcAq«è’­vûëÎYZ´í·ÿåÐôÕÅÔMW‘S IêÇE( K¯ ··?ï)Í5È+À€ÕXZ–¯VÖø¯W¬3ŒÇêäijÁ-µ÷XªÑ3\9ÌEØAãûÞS#Ì:ÝNtXj¡¼Õ"ã¸ô‚”¹Lú>+JºU‘Ò˜&ÀÓ¤4ú·ð´‰Éê}¼þ†)"<<¶l’žY£3(ê¹Æµr÷¯‰#8vüXµ ¢B¸Š¬zÊ ëƒÌXüA‰È5¢×™"àouù<ƒ#R<þߌ}°»¨F 9<ö-G^È´¨sxò†àŒõÑ­5MuÞ“js¿£ßLeÉF0f!3NFýžÍ<Üßá¥oqš¸A·Ð?âþrx1Ð3ŠP²å×ì¨1 ,ð•MZ|ž:R$&Uq݆Üèh%Ïgë§­"KíIVñh§ì±™´(å§aÎfÌÿr…4÷¬'A&VuÝc1jîÅS±œ”& JØh¬“øIz/ŸE ,­úVy÷0@ö^™ð°c‡&JèYýi³a{gCaÄuòg…3Œ÷Nòa<Î9åÄu$ߊ1gÇcoŸsA^45ÎÕE.™KH¢#ÝÚ÷ÛeÒ´-´Ê «_ÆaËœúPîÀ ‹CtÅÑ-r ¤#Y»°ï…eª&žì¬‚­‰ZeS±*yÈi1wÝëœhú“Om€9† @ý&`f„üë<Æa^l|€å (v˜¢É‰„=»;éGÞ~JßL²ú†!þ퀟š ¾LŽ(ølGUvD…)çMô2Ðh¬Lã­ÌìØ}8‰‚·ñ•`Sò*…a‡08‡T‚Xˆb[LH°&tô¸ìh÷±äd&–"&?Å• ×jHn¬Õ®?ÌhÖ¡ãÖ3æ>Z_Ú„|"ØÍ=­šÑ™dÈsFZyf°daoKœÑå¶:[;k<µªRÕéÒöº¤"Š“”ù¨ƹ‘]¼—¦DÞ¿‡þD-6ºU9&pË0Äà ÿÁt?~À»øñ~|ƒŸÂäc"ýý ¾:Îzgï|_4ûwüó6~|'øÌ¸Vß¾QÿªêûN¹x§^¼Y.~Y/žêÅ5Ëÿ2øÙ «@¼á/”•¢;&†%áD6Ý:®4•ôC¯ á-h-à ‹ò þIy¯+ņÖÎùöhZR‚7À£ÁßW™Õ.©´KÅì_âêßè •ÂIe§™ô‰Œ‹>Nl·3‰º6  ÎÞÔ-”ÒœËÅÝ`%Â…’ «ÚS’ˆëOÁ‰vÀ<kH\ƒQî&VYòf®5§qt5Íc­˜Î%éMµ+`r_x~¦&tBsX=Ÿ†8„PHäT¯s–Ž[Ü9Þ¦")‰ka't=Ú¥UP«6˜ªß›¹@œÈŒ\d6·Rƒ8'Qúá$ïëPoKæ—.¤j`´ž>K¢ê¦@©Ró|)вÒÓg’Á!÷%¦µ-ó#Ua“oZª=œoá¬_Ô›7u?€Š¿ßCãÐ~"'çfÉ7ÅðvÈz.LQö+ü¸›Ž?4Ý—;’‚ íÊGÊ+q§ÏkÒNÔÓ.±!пPCD@5–R­ÓOÈÒVÈÅtØ_8Ì_8);_äS¥üå町ÎË0Cš ¿½FkB·Öš´Íh¬†Å³0’jï—ízSŸÃxOî(‰»‘ð?“ÎÉ}Ë@ÉA}ºì|Åû,àÃK§b£oËÙmÄò#–ˆíý´V‡÷j Sþõ¦B«¤2çÒ€km´ó¡¾VöVÊ1ääÑ‘'äüûdXŒB[., õC8?gFéc^°I¿š9uŠñ½&<–Ç`x™¦Ôˆ À4o½Yêé"ŒafA¬Ööûý§Ö+Œvfùs…Ëœ'ÿ‹ ©™ç^Oý•>;‡è§©Ô›N‰)¥Çâ³îz\”¢GnæéØ2»žZI\/YzädašuëJûåv1øDÐÄí )"XœY‚3<Ò’t7Ø6»•êÔÍxZ“ç“ÏÀ…°·[úƒ¶…(è3ÆB£Úº&¹ÜÒzQ}¯‰v¨ªM!áCkˆeoMÞã9Ó=“yðч¼pÓxÿ¾ñðˆr˜ÂOµ!ªYPOD¥ŒIµ¡R‘ÐÊš@aÛ¨R&ZLïí;?¨5Ó1JºR  :*“>=:ÝJ©º(ãÀfšV])š”bàlŽ…¨z¨*ËAÊZrìz#…„üº th­êøMs¤ƒSÏIS—¸Ì¢^‹?‡˜JF4ãʉ]Ò¼ªdù¶/(ô4Ï®J›ñ  Ͳ)> stream xœ­\YoÇ~Wô#ˆvízúšÃ|H¶â32ذó@‰: K¤-R¶õïSgwõL/¹‚@ôîlÕu~U]“ßú;êñòß'¯n½ÿh…±ŸtÛ¸ù¼s»yžâ¼ù¨ó›o»­ßãóûÝVxÔmƒïw½‹´<þÛuÛqšwó4Ðè]?8Ço¾ê<΃_h±/ñÏGÝÜ/†àaŰyÐxBÜ<ÌÃqx˜¼Û|×m,7ŽžS3aËçÙ†~7ºyæcù/ºí°y ëýOº0"õŸžý¯aYú𤋛Ë.ÀЈý0Ñ¡. |NΜáÔç¸àô„Í] 04EZæ%ŒxÃ[Fš<$u¦Ïðß)J4q'Ñh¤·ÀYE0yQ zŽJ&ì+Mv 9Óú”‡á¬ßaÐŽìõ“ß ªL! Ç9?° ÀM£â¦ß‰+ÌdNÁOžˆñ Y:…€R.㪪U/òä2ú- $¹LO>âHG_Ny’?U›"Ç/ûËZ@Áœ€ì·ø3,3 ¯¶Ì¬­ »4 õ!ÏPcÎaBSdò>«S%ˆ7ÕÏ/PzÒ© {`§KWhd˜‘ªqó >ò¯(ºWðmBUákŠþ& ŸDÉü€ÊŒ;ÐŽð™ÇžX-8a!x†²õG®l~ÃÝx¢ÙÓ Ÿ7FÀgx:6øŽŒIöôÕoz˜ã©×/¤‰¡ïwS˜U/p㑨:)lÊä³¶‰Xõ8‹ûMQ¯Kœ‡[ ›»°cÙ9Áw˜‰b‘o-ç„ÿª…F-T¼%žðç.ÃäÁ[ÿ÷¢Ð•µ”JÏMj•æ‰ÿkh óúÏΓ« 1@RÑÇbø½§gôùR7!ÔÁ÷SõM·?ˆ[Q6)5¡µÐbñ6Ô%ÃÒ%‚p™dÕ3"Nõœ~±g}j²ró7ÝödáœðŒè̲J 'ªùhÀ¹¨×V«Úu¦«¾E Hó|=r0²ÇÍk¡#ÞÉèž’i\ܯê@hB?“3|VŽw.lcW&uVÙP—zŽ;¢ÎŽW»FÑ*:ní«îÀfb¨¼ƒÁ8‘’ Ç® ò©¢RT›Ï*˜­=‡©u Y !ð³ÖfÂrJül\kDðHq÷áß²ŠÈè‡ùXܯ [Œd†·Uí‘ËfëSû¹mï•N’Zÿ@öº Èñ—·Žÿñ•an˜ØK7myH•²ôù`×`Œ™Ý€ƒW„ÀÐûÚ˜²@0{ò•ˆ'üê„§‡÷ÖC?“ÍG±£Ÿ9Šžâ’!˜×ÑEJŠDÀ÷DµOœ41"PÎjwR¶µ âDðÖi…a±ÑÁ¯‰0éí< §LžN§èJ8uR>RhXÙgZxvÓéšpPƒÜ-þæ! Äã½>p`O'šjR“ú­6xú³¸²‚JNy ®¤¡ è©ÑÜV"¬¿AiɃ,ÃÌ,6®‡eéop1Ö«… ÀZIE££ó~•i*YœÛ¥œ-#€s A¶BÃ/†^À䈆녟ˆ^"tªA<1sÊh–ÆU¨ø5OëÝ‘ÛÈÀG®#é3©BV#Ü,;NôP.*ÒÁ‘‡>¡§¤ZÖ Tƒ Ÿ>­…\q¾g ÿ/Ï ,ãÄM‘CÜÜÃ#̤EþK=ÎR‹Že¢Ðq­nÇÐùÚ'ˆ+*PbŸw.«W¦ÉÔeîŒKNËœ*÷ÕÔ$µkôˆó¼GM„gF×ö&CŸ—ìmI‚+â—jY²,ñvÄ–ÚÝ-$nW€œEV ÑÄ÷äDÐAl¾îÄ}#ÁoßwÞ–7îâÌ‘Èn{ÙaáEƨ Ä*F¤Xá[Í-Ð^&öÐÿNj ct!n>è¤î1„ªøã0@ÀBÃÔ;æØ—˜ý}ƒ¾Æ?ŸáŸ/ðÖZ6?ñ=—6†¥Ð £à§cüƒÑTO!Ãg~Hß©Dù—N™ÇŸòÏòÃ縇í‹üð²Œ|mËÓÁŸü‘ž”‘e÷7õm“›w ù2÷ è0„(uõ¹ƒ£ŠÌ“«wiÁ¡><+ÿžÞÕO„ÕÏ2\ü¤‰âaþú½ˆÏõÊX\oð*;ê"Ÿ×6—ø—×".p”ž>^?-46XFž–‡ö4°)@qZ¶¹B o0éRµ’‹+e(“^–‡§EÄÏ[Û?­¤)"~Ñ:‹)Í*c6·©QaÄ„Ö@å—ì( y‚‹¡_q˜€­;âX2{ •&Lq5fìÛžBÏ^”ÌÆúBuzK¨ÏÑ[¸þ G¨Ë[¿6”ÄãÞò‚ c¼wÓ¤1ò*Ïø1+y ŸÑ‰FIMZÅ<­1K8ŽÎÄ.SëCé8\.]—Œ‡ÉwRâ/Z/®9¹íŒ"må„Ûb˜­ö,ƒ‘F…=Iñ*Æe/u)<‘–4tl™Œ¯0–<_Rcðo¼ûEÎ3jA?^U %‡Fž¡øóóó}ÒRÁ«³%cBNào„…ð+,)9Šð‡-¸Ð¾&`+UÖbºt8äo,ò7µy›¦ÕÞ p¥Hg ²\–|¥›ÞWÍÀhÓº^!ì_`Ìʺ2µõ½Bð/ªQĺÂi¸WÉ,j4=EÈR’!Þ5É;åþ=:é2×6`•-¹6öϱÖÂÉv›[IÅd›öŸ—ÕH eøÂoäÚF™û”Ä|­Ê°Xäu¾´.¼‡Ð4Úƒj?ÙºöÔ~òjKÅ b³:Kƒo dª U7‹‰fÍ3Vµë²ci¤ï:î ¹=ô:ýæ?TPBý#}„´|ZbšX+Ûùªæc$"9Ñ톚Ve¼x@6Ó,߆ˆÇr{<»5SýTÙ©Œ»§þ†ÏRûýÏa,¹}ªcgð¨›Ä¸ah8žs›ä0÷J³¨á*¶ÛÙ/äˆâG*POwß­4ˆJ<ûì5—±àÓwvö@N,ÞŸÈ´rO9¦oh¶¿AÍÞ›ˆB»SHñ}`"¾ê |ÊEÖê>oQ|ͦg*¤ŸK Å¡¹$M na•OåΆ¹“ ~;Ó`}ÉKγ3uÙrÙÿi6“2«ƒ4gZjØ¿¿¸¸¬ž¸þ³¾NÊ÷ÓTúÎBѲéÞ"ñ~%`?1ì†,÷¢Ö]ôѸŠúbyGwUWÖã¨ä+i«_8sï§ådH‡D½±" g1óAQ¤–ßê#èµh0QP½õÕ¨¸zf*py²)»w%Ïȱr¬ò›*œl¦ÕV_ ‰6tØd©”ΤîúChOURV9Wx„鯨Ôuã«À–€çê2Šê|`Lyˆ tèøwFN^*n #”jmX CóÎì¹ 6$«¯°ÆgÄÑœùP"˜=B­‘ó¶ÝÂÏžÔo¿Ö¬ÃüN«Ò)N‡ÊX޶Ï'(•ÙÉ]jSF$.1`¬qÇm+ݨBʯ”ÖÆD6µ¯†9p‹G1wc¡9’Qá/:V¨‹îâßMõ¥Igr¢UDa½ás¬;@rP‹“ÆÜƒòüa.¸N €è®$Šœ8õX§vqZ–®7”€Ì~yë´8† í×e‡ÄøðReå­Ù‚û–?º™è—…,*ûOær¤¡©æ¾„Câµ½I­K-y!'¿Éþ×€éU•B9*½kV®Ý¨”môͧÆã†Ä}ø­Æl~ß#Òf¨Q®“s葹™D6ðad‘{Q¤ ZJ#ânÙ÷SM„ { ê"Áƒ¼f”³'‰£ÛíëíÌy«»¾b§›iÅÎ$ZÂùjÚSi¢ 6ã*"Ô3æ® ©¯qܨ׹7|ÇRm®¥XGž¦+ï×S×X÷îéåãÄÝ"32 ²¥Tõ™núÝ3Aׂ†¿Å*õ71ã»ÙÄìfϤ:œúŠDö³ÿ B}‹îÚGÆ=•|ÿ˜à­ŠüpÚ5ºèþÊH±áàõÑ‘nܪ«hlÑÕØV6x§ˆ4VîCáxgq³r!74–ǯ«-oœÕ%R¶Ë¥»=I:Öçé¼wm‰¶ª4¼’˜Ì• ñ’©JÇ…¯¸Ú?;j„¨;e KÓ¤,%OaÞ*—@M?õ{Ö…7`X;oy ‰6‹±\J–Oeã¡.Ó˜D£ÅEbdÈWQ½V«I!ƒ ¾d¡Ê¾òYÝh¯7‚_«ÈšzAG1C¥§‘úüZ+¤öØe‘ëQûß12%ЃðPØ«zH9hi( nÕÁ›+a„wöù)ËÿåŸfx~_ ìcjä«zÏiÁªO\U6úööçj¹öpj;wý Ši½ú뿦ŸÙgL6cÎjaÞh,nŒ]‰OVBßhg/RZ¨9~ ì æ[ãðd\…Öêµ  NÑÙëj!ŸJDôçGNÍý‹Ÿ¦Ú(¯*ò çÚc§½¸‰ˆˆ‹høÄ*º‚òª õ¶ ´IÅk& iX_¡(WjÌUê&z{©%ǹ‚/YJþÚ>éÒz']¶?âD-Üý÷³~Èÿ)}¸_é’e£ƒ—†>è´÷QžT¯ˆ€–ú^p‰<ïzJh½òØ%%ìñoNÉ}¡äÚN×¥÷SÈïÞ-¯ö)µü¿ ˜û¼\½‡‹É˜ùÅÂÒ$”/$e0悚 Uaïñí<"R[ó“«öT([ïéKÆa¯HoÈ6RfØ|L©žÞvú©Ä ~ŸL°ß3y³m¿RwÅdsš¦š¾¶fG„¾ƒÆž1ã> stream xœµZ[Ç~_ñ#6ÊÓ‘§ÓuëꎔÛ`À²cK$+Îòk/ˆ½™em“_Ÿs­:ÕÓ R„˜é®:uêœï\«~=zw8à?ù{rqð×gùðìæ`8<;øõÀÑËCùsrqøÕ žôó0»Ã£_x¦;Ìþ0‡Øþðèâàß×%úßw~èïv\?¸´9ê¶qó°ÛúÍ÷]Ø<Å/ßáÇ—Ý<”—!xü´›R?ÏÁÁk¿yÖmÝæy·qˆƒçSœña€÷º¸yÒ>gÞC™·”ëÖ¹>‚ Æ~NóÄ‚z˜x…~ ú¾‰1Þ½ÍÏ ãTß-Ž8‡8üFà2L4é'ÉiÜã°Xó„çøb¤)÷””çãæw÷š— ‰![DmÊL„>~,@zZDèFœ|Sæ; ÷‹áÀ00è‚GGÆó÷ÊŠN ç~^â>N-‹(ò¦~ˆ ]¡™3ÑDRqDÊ2âü xü ¢kV$ b@‘æìI<'H$I>"ø¢< 7ÅÍ5ð³½G5Fœß\Á /Ë‹cþ¥”Q!ïQBð’lr+;Ù3À Ѧ‘Ð;Üx¦µIq¡cyá‘©/ü„_x±ÂÞ(¨áQ )Ä‚ t|†?7ê<£y:t±‡-{r0ÌÍÓ¢SŽ$ù–2:Ã>¹aÎà;û¤ ÐÓ”û† ø>nž6¸äq>£è<¬á&çeú1| h˜àÇ0!ËÛC?&tš 5ä(#Éd™\Æ}}p¤1^qÅÃûžvòèH‡>ÆÙdN°¢›ìüÊå >›r-–›¿à°Ù²5R–WQ¤vݘ¶±{b¤’Fäyøœ¨—7'åîäŒUl]ÏË€: ©“¿©´þ"0(ˆ`|-Š"z*fð4Eqø¼Ä¨#xÃ’¡ßúA•u’Îã¸+a­@iás˜™ºñª(Ò–õI,è*…So38Uulïu3Ávò9de@¦½A<ÞÔh¥Z¿ðÅ>§YÑg¸m¶0ÖÝ2õXyÀMЛ¿©cm3ª1³W%~ú ]"ãíuýzÉ_Á ¡cÒ§çõëmýzZÇþ\Ÿ‚qÄ9“|ìgõëÛ:ïj•ðuùºæÞfp—º ´D—ÉR4z³O Æ×³K§ó×È/û,rƒ¤ÿ5<ˆÜˆ²ïÔV€±-`×l5hÄ!›÷­D"n+΋Ÿ»s\úD‚¡›ñ3ƒî¶¸¬wÈA$^¢Å²oà .RTøESZrÈÔ9EPRøb(1¤Ö ¢C[G@ÃWNüš„ðR¡{Q•ŒÏ¡žçüåå=úìü¼å4 jŸÊ]M6ý°îŽi{ ÖOð£Ñ¡w|…ôYv÷êäõ&6ë½îJZ*ç¾Y.™ðÀY›lœàZ’ü‚†Ñ °Î‘Ñ„îi @¡än‹,t {C[9ß›ü]B¼:ÀךFñe½&³Î3)¼a¤À¤uÇ̳qŠˢ+VF®vŽ&Οê¤q¦¤ -ÂsðDÌdú&|ž˜ÐÉëN6Ž¿21EØú¤€žçµ€nâÊ47k˜è î‰æ®3#Ùk±<ZPs‹ë²™;©Cp‰V9Ïb W³3%ÀÈÁ-D3ÿCIaÊ9©©*XÙm±qksJÚ9WK5\’t1« @ê_Å­¾E»¦‚ã¦` &•kßFä‹&ªá†ƒaT .-‰CÅ´‹EPJIú]‘s Üß½òLïBæ¤AÚ%òÃÚiœ(jèCG?®zÌÊØ:Y ­Û­ÇÇÍcà{T/ ¦V¶Ë=¥Í(mR«Ð×DRÓY¥¯EÕ—’º[ÇØ4O*&¯-ª)sKÄŠ+¥ä·©¢¹£$>‚©•›tC×–Ø"´‹9 \#Û±šuJÔè‘´óQ‡Ý(m›¼°56¢DÆ}·EE#”¦®ô¥­‘"ÅìBÍ´!ŒÀPù åáö4“âBÊE(Ex×™nÉ“æHø÷¥5´MŽE©¤{ãTR “sÕm5µ‹@ÒÑ•:»IHyãÞA.ÝšÑêlÕWÄQ¬³ÄïQ¡ûŒ8ÃŽ„‰[/Èû%ï¨[Ì_9»½¶!`¥à^1¨è| ¶š‡Ù,ö²"äªô8‰”~X¡úJ’Gî<¬§q÷mBy**ŒCª‹®¥É{TÆé'+Ëô¯k|•¦»”Š5 Ó„ŒÃL`æ¥J°ÂŽkÆCn)΄‡šDK‰BÆ^É4¯ÚäEdØü]VÍmÊe3^¦_ûˆœûcE0‰Z„¦‰ÊXê&_@4LË‚jz­.›!R“ã˜ÙÏ­:.y°Ÿ:‚§#5è̃½i8c]¤“H}dÇðR½¨n(ÛªZër`‹d æsiráó©ª >×B°Â,†÷pdö›&èDÌí†éC)ŽÁGœ‡=^ƒ–Ø­"M æŒÚ¡ ŽwjšÏ—,{ ߟ îgC¦ÔÌÂ{øÛH&°õˆ´Œ!wÈBÊÅeÉÁ;ÜÁ/å8ߥ͠èNÄ—ÔÈñÚuŒ‘è•ÃÄžoŠÒÌ¡ÚQUÄseÇ·ù°L\Pô «n\"ÌhC·É–9vFOÓLÂy^U‹qVU tŒ±xö¬ûù”`Cy ZÌz~y¿vaz;ðó~]…}¯ò¾{×väh×…ÉK^åeyz©sÔ…n¿=W:zò*¬DÿU™CO{m“Ý‘(ò@4Ž•†#Ub(ÇEN„aÓNZ7Mß4 “f)”H•ý}e¾îë®=ÌL5KQ4m•L½­¬§tÁé¦{£V©i?õk—§Ê{ü#uàsë¥ÏþAS uu»1Ÿ:ìíãÆÍ¥:Ž×ÅXq\£°Å£®(/ˆ€‡tÁàq'×Èxû=Wür•G^ø¡®R( i]¥YÑ Ž[q^0*©º«`»h,1nO¤x•·»þ9D¾jŽä¡9Jx¥\fóþ¦nòeyØžJÈÃwõáqyørÍ´0?›9¿¬ ¡ÃŽ’±ÇåáƒFšj»uÍÛ5îNÂB`À{-å=êpa¥a©ÛÆÛèÄùÖj«µÂ<{+n…š€q”×L„'Í[Ëš?”‡/êçÕ7µ²îÿ¯²Ìd üp!ʧÖÚéQ7aÇ,Mᛓ´’jV®gxÀ—ør‘#à¨7z®,}èTNƒåļxK’pØW¨ÇÙÒ=·<´W‚™°àÉëWí-­tÕuòŽñ˜>ûªÐ¥ b+µºÏ‘—Ò¥6Ðä)©4Ð/+•Z Iôé° ÏP¿äþ˜¶‰®›ÒA4Ñ×Îc-xLò®“ͦ~¥½2Ð/:“÷*‰•Æ%§•¼¿Ý^ä/M˜®!—¦Ú>®âÛZÔkÝïaæ¼Â‡rëÊGmìì…‘\í‘O\)èA R÷Ú÷!ßá±—w.KyéWÞå‚–î6ŒÝ¦ÛÜ‹"ŒÅÔ¦ùV O:ç÷Ôv'¼”Jb(*̆éG®(&ù™Ý¥´ÿÑ¥DÏ·ØÞЕŸy²½ZÉ©t_’9f®W&˜÷¶*‘ šÇ7Ù–ìØyÕ¶!©‹¯ß¤Í¶3gY‹›T,¼‘ô©9ñú_Þ*^ë¸V®ÎNN0–}‡ÕFsñ©ßtØ1“¾1&r:„pÍ£"TUvÅÖŽ­6ÝA?óUIJI9=m›WJØgöšÈŒœß|róÝO»ç˜¸ÄÇM(Më·Bp¶©ùƪm/‡û™ÖJ'“®’Ù[;ކ‘Ìôd0ì]qøòß½×ç©èÞwRˆJ¥>Ñ^á·¼òÑwö<»½ê$Ç=´ýÖFÖüb(z Qn'67#ïtîÈI:]«Írرv»íkv†¦}S/½6ÝL˜> stream xœ½ÙrÔHrŸ;øˆ~”6PÝU1` x†Ã@³Ãðà ð.>° xb™ß<êR·ÚcO,²º*++¯Ê«ôy>ôb>à¿øwïhvç…›8Ÿ ó³Ï3A“óøgïh~oBÂH† æ‹÷3^)æNÎÒý ç‹£Ù›F´¦±ð_·æÝâgX¥D½JzÛKX·ØضÓÍ£Vô!xš»­l¶ÛN6 ßl»4ñ¢í”úAhBÿû¶s>ôÁ[‚¸F6OZ‰ë`†=ÆÇÝ6 K€JIÀ¨š­‚A¥t³•Á )š—mgs’Ùñs¡{¥­Dn:f§SCïDÌ•†ŒÓD,½äÊÞˆ!8K'„²°5ìì=üµ¶9ÉKÎëÁ Þ4G-¨Ç ¹f–+ Ñ4Ÿ€p§zï°ã]ïÔàš˜vVÏklPÒ5§ÈƒÒÂjXD» iÙ\ÀË •W°¸S^’p_–%¿·Ý»( "8n•è…tõªŒè²²€ÆV¢@Õg‹¿¿a¥~l;K;JCº»h‘ tw )¶¨ŸÁ#Ű…‰óÒ (`ô•¤!MÒ!ÍŠ@ôÁ$íF:F-£öTó7810жK6‚p¸þÿ½ Ø…×€o‘\Ûì3麹…/Çé×>3j$TçŒ"€þpKdGоi“VùæÊâ¼ø?Úh]V B³Bû OÚ×YAK‡ÇvÞæ1þ¼‹¢ÊÍ7?Óˆq§ò>6òê_fðóf ž±'™=˃e0¯×x8ã|_æáÕˆ@HߥydZ8°Xà­…Š|ˆ®CfÅÕàUàKö>>^•ݾ°‡Í‹)n^•ÁíÂÍ5µ™H6jDHî‰É|•QmO’ùö-Bå­/"«#C7?2ìÝuĸ‰†Û,pOóàýù;X$ÜØquÙ=KDz{Íû¡A懴‰iºÑÁ@°=„ØÁÇq9›w0☘ïœfŠÎ Eyð|jð¸ ^ÚïzR#4؇ÁRøM¡*¯=˃É4"Œƒ‡ò¨†Lƒç#'¯zCŒÝf9‹I&ñýVFþà‘U¹!D<‰ÈíáˆøÍ âwW©àQT'1 QÓ|žL‰x'~ª9^N„ºé`~·U†6s‚Î3f39I2¼"Ža ùÑHU†¢ E¾0ÃÀ¬äk«ønc†§Ö¢ŽùWâ‡v©ò¯¬Xå2¤5‰e> ÍLYöi1ÝRÆ‘pjAÆDŒI©·¹&-6PlÞmQÖ ŒSûTUp–©9§o{­Š™â¿1q¬².Œ<q6UiµC^MZm<­É–í0ƒ—˜iÆu)ß´,Ø¥üQ#:ìEðÖ³iæó#g¾RV(9 Ë‚…(+Á‘¦‰Wœ,v‘ë.Ÿ-dþm}­iÊÚB|ƒ ¬û~œãÔ†% bV'‘¨ÅIM“Qe2 ôs_ÛÃ}=ØÛ3Ìj_årn»õ”äs„, úAÈå˜lƒ$ëHôu}ÄIE“»ÉÖéU_ì#¹ ¼š¬h'™™(`Š…h‹I*ɦl2©dßb@ûNŒ£¬ËQ̼¨tF±¦Œ3 Ã`„$ªb±õ~å8zȳ¤X£Ò“h‹úciº]ªÔhÕ¬•&B‡åÚ¶*€ÇemÇÜ’)™à™é[Iè©^ *Y"™ ²o§êb0ýP¹û«+bS*âM4箪ƒ«×É:ù+P%…Uæê ”d€žÛqlýвҫ#bbA@c)íÀÁAd÷Ú\ÌžÏ>Ï•"Sæ ^ƒ1C/ý\bzë±¹rokvgëÉüâìËÁìίs1»ó÷¶7àÏÖýùßf›[óç7l¼€Sê5ì"zÇ­dá}¾ YIôÂÀzrÔ«öÿ@nppÖôÞ øèê°‘{•Qý’ƒrž—’Ó0QíeœT}ý$ªz¨È /ûq0Šl±Ò—OE‹»Uá{H°ˆ~ÓÔÛô9œWgïæØƒ{<Á·ÙFi kÙXJ‰wŠÑd×@Dq”Ĉ„qh¯>v9Ö ø‡ó ÒàÕ*Ù~2Z’Ë—à+k©æ'¬dïz«BÒò{â<5Ù–£®›r•ꢶ»`(ɹ•©)€Åz×z­!Iòàq”‡å?ÎãhðÃ]â>½ÐÙGF>.s>WÆJ:÷%ÇÇ)!¬gÍ[I¾ÿG³æé,ÕœMéªJDN CWiÜl?[· ´pùøæt“™‡±µ‰õò95¢3šü…Ò2×1”VjÌéiª\ꎯ0ã¢Ee{Nõ$44Q÷Àß@n½ƒ”–R–ºQ2!lbàý¸õc2_õÙÁ,i*-cæ7úš Š™¢Ñ” ޲Y›%µŸ=ÄA<»Co<ºÇÌ*&p¸cœÖ9î·è±¼‰p¦ÂœØ$w’„ò­0ù±hŸ’"¯G ùÔ"Ÿ.G¢Ôår ¨’Ú”¾*C<=âÔÉŠÈ+)0û…ÜÛ±Ú‰"›_e:wû} }ð“#Á:+Õs±&ZîÆåÀþt”a -ì2Iò¦å¬öÙ¡.§Ü;)"îGüɵüe>ò^Ë踷%BåàDŽ"+G °t»2!Íšâ K{t²)Üu®ÍìT‘PÝ=UWd«w`Žý§ŒªÜ–]»rˆ7Ž&ðåP¹ÊŠ9†r7»Î \ŽÔí‡i[õ’Æ'ÊÔÊ~BÊ.O#az ÿ0ÃhñvÌiJÔêìiâ%—´³"nq|éÂ,UN haÉt§=¦ã6æ’ïòåo—àvÇmÌ—¤dŒƒ©É¸)*Jµ\NGYée•¹T=ŸÈl€b­KNþK»š-W:öÖ°ØÅûF™^ÙÝᄘå1vi§94D¹«’ b,Ѻ_s{ØõR·±Ü¼ä«CnøóuJêË/bGÓ 3u>÷òêE^M?_V+’EÝø¥;…»qM\ý2µðm 1E¥Ú#µðQ®¨ î­PUVŒ„„3¤žcšy_šèû×nZOuÖëîøjxÔ辂I•Zð‘Kì”Ò!ć(áIü¢E2oÄù‡¼/z}ŠæWñû~Šß³)Ö.ÊõIéc_N±^ý)›rĦüalfÁ×Ük'®2ŠZ÷ Î3L·Zt~nÓÅ×F<Ã$—‡q2Ýë >T¬{'wæ(]ñMò^w',±HÑûשË"È4¾]-à‹‘„V.<&üÏø?ä–Hýu§ŽßZé9*į,´ànnôÐfì¢s‹6ø(þÃûÔß/-Pþ.ˆ~¾.6{Ù*žzÃ{àéÛ¦ö1S9Êmb.¥Êž ƒÆ/¦jÐìO—r6æ”{ÔJ2Qw©GßÅ”XÌZ#7ü¹ÊRÎ]5L…éÛ1Y—Ȇ¨§ºDü1·<Ž{"U`Ë(Ð./ßÅæ Ž÷˜¢ü…xor¥¤2Ž«Iw r¾NH[êPE¤D.%:q¨ëø¢0©vfäÞþulù .¨›·g©‰5ÊþVj¾ð¨»Š+ÄðÊÛm._s§é'[#w!E±ÙÂVY5ÿ#ºøÆ•¬D\3gß@P;æùì¿úÕ“5endstream endobj 880 0 obj 3059 endobj 884 0 obj <> stream xœ¥YYoÝD~øWâ¡6âÏf‘x`)¨¨”R.¨å!$]MnÚ$´ù÷œÝ3¾7 UilÏÌ™³|gÍ›Uß¹Uÿä÷ÑéÁgOÆÕË‹ƒ~õòàͣŕü::]}µ ÁÁ—nê'·Ú¼8à“n5úÕb×ûÕæôàiãÚD?]ë›~¯sïºÞ¥æ~»öͯðýKøù¡ Ícüðÿƒ%×MSŽSós»º¾w}þ}ó=Üê|ykL®2\¼9–Ëð’Ô&ܼ–Õuè»ÑMoòÌEô#›M›C7å”›-Ü3°›£66oÛujžÃÃ!¸öžÃúÐëmû¾>@~7@9õa¤­xä`¼y ¢!Oaîhý®!½Ið et´÷¾£ð°÷\iºiíÓ[bón N/K& ‡›3¾"ÒÏ1¾àŽg2[&ƒJ8+è Ž÷]áËqÉeïÀV¨U?ÅnôNuN¢özÔ––Cõèû°éÄ6+=¼äæ |HbŠñU«›>¥ŽùN(²`@ŠdŠG­¿“¼'ï"*ÍÚ…. ˆZ mê !ïA!êÍ®ƒ‹tÉ;ÔÀ+ƒ)m,ŒLH >’¡QÑ—øÊ:¿À;Ý>ÕD\“ò¾FÊ øÓ4¹‰}hU%]šYðRsM›gsïÃd@°äA/'““Ðy, ‰üüjojßB¦Aº¡‚ rL€ .I“æ=f8­°ezOË»ý€’Â&¯ž¶Ý 8,”IãboÒO o@u½@Ù€AçYAÛ6Œ(i" Ê™ Qñ¤U ìçNŽ”TN‚Ršò ¥ÕCüI1³ï¼k}f!Pk;$ÇŠ¢€`«ˆ¤›ä§Ï†<‡bŒÉ€%± ¾€0|ž¡=CBbÿ¯Ì+ŒÞà)SxZÞ y½Aµv&Olž5zp#JUÈùÍùXÝš¨²ežµè5™€¬àæ”g@î& ßð-„8qAÁϲ)'O²Þ•ÛC¥“XúUÜý59Oæ“+ªÓ‚ªŽ<(9 ÜQX 8›'àv”%Ïf4”sQ…ðTe™òr î¸Í¼°j>ÓAQÁg2²Œ@Šž4±ã¥mËh–9o¾GŽ6>/½àóÖsNBUI¸´„D%ïÑ0h’,Ä]w®9Lã·ÔO˜K„¼?lñLj„WZ}­äóׇ›Ožò!ÚúÞÑ}žÉË-?õBÏ]Ÿ×âµÂñÇÕ¹GFþTwwÂI 3'Dì…IùÖÕrBdU"‚ÔÃæìÜ®;)Ñ!ç/–òÞÍÝŸ®¢'¦"3»©ÈÈ\™OlgMæÈx³½,‰Ò|ö…Rè,ëÑõ¼-¨ÊžœSòf,HD™=ýï6p΃ЀÑuéF;¹‰Nž¼»ŠÄ²¥Ì>gÒi(^h>•P€Ä^#±Dž[]‰Ž=Ç à2iF¯‘8c–lè¿CʰX¹àŽ”–B’ÜéI~IƒÈfJR&…ß“#y#Pè9;ôH³U¤k Le–ïP¯ž"›”L˜AOi cÚ8úª|òyŠ}úœÈ9!ˆBi#…š ·”GçÕâ6Џ'¤®þ\$þŠ‚„+Æ¢ö öC¤ÉQéë<²7Ö[˜ýdá°°D¡ú{-×Ò†<\ÃE‚Ð=èÇTHº“…ZÎòÄÅ\8*7Ö¥§ã+Àÿ±ËÎçeçSð@ÅW߬¤9!¡c-1Š ˜j¾å¦&ƒÁ¬À(VE5çzÒ¾¦[ô}H†È”#@rù~O”.]‰Ia¯Öÿz¶r]ä{(NŽ·àй¨7ëê_ Vû ¦p¶þP÷d´pä;^Q¨+tß§œ£×¢ º¶U©¿G Èƒãfd9$ý\;kª]rÕû s±™6vH{ä½DÿÙ[Ü6¨ìc%ðK¢C¸´{#.yBXž"¯uÿjæSd µ±¾Z¢7wÐ×-€Sêü¹•Ú»„¸±œ\hí›Ó¢®bù`‘awcA½m' AaÀh<˜l²ò¦ð¶¹·BÍ:Ã¥sÂ{|óWK½mk ï°yÖ£ÍTk—‘‘ÇzBàÅXUÉÐØÓêèH ,{Ned„ŸiºVÞpÃ"â7¸DÝÈã…ËRUþ E@]%FD¾SƒP#_Ì?ö‹=¤üW|°˜ˆ=œ¿i£‰¦hÅ…:(LGmó|Æã1a½0ö`!Ý:‚Ä+.·J£ Œ5b—+‰]´U a e Md9W;<"Ÿno.]×ÝóY$k/½èŸ’Ä#×1ô¤[k%æXƒIôœ’ˆ*ös“Uué{guHaTÏ(,÷^INVá ·Û:GõÈè±NL„°Á²÷UQéEª}£"A%¨5FAýŸÈPoèÆÁJ(ÒÅœ'-h[T,°Ut¿ERÙrÙ=Îzoœí°" ê– î §ÿ3¬D7QtªÒžÌY »³@‹¶¹×Þ÷_ŒghÎ3žÇ¹­Ú0㔆sö•>;G0› ÁfeêÅ Þê¹%¶.«Òx§´B~ò¨¨=Yhò{RT­—™Úþ96W[¹ËÁ&‚;¤3YÔq›tsðüûÊÒ@Iendstream endobj 885 0 obj 2303 endobj 889 0 obj <> stream xœ]1k1 …wÿ Ò`Õ’|ç󘔄¤´Ð¦ÞJ§”fº!äÿCåKZJ²à½÷=ð ¤>·{œÃáÀéœÂ9ÈbÂígX7ˆºÂ5Uö®¤@Q(–9)´9| Ð€ãu?Û“S&ÿ)FVçÚ—g)fÜ‘p­S®¸"ÅWŠŠ­ëŠ¿Æ¢iâ$y©ïËËT¹Nã’æäæØÅÒι³”=÷gE5ÝÍÔ ·d.šeÜÿÅ{‹ƒ ¾S¼®íßÙ´ðæóœå@Rendstream endobj 890 0 obj 205 endobj 894 0 obj <> stream xœ­[ÉrÇõføæÆ‡Ð¬½«¾’lZ”,‰Û’¸@!)@4ýõε–ž8¤ 3ݵdef½|™Uófc&»1øŸü=»8zðý¼yùë‘Ù¼G™Étª Γã³ËjÞ•<Åî~ò |‡¿Æ&3ν}†ƒ¢4÷ðÃ%ó0z·z†ú‹¨š÷²Ív]5pζpŽ&†Ö¥Ð@?4ƃsD18Šê2ƒï|¹ÓfÕòûZ$ëµ9OYE8l•í±¾ÀÕËr­ŸbÄ…«¦eVÁ·0gò‹SÕ6=+MÓâ_¾aËS#x•}ƒÃó ¢Ü­ª’VOm®BËpŽìiùˆÓ¡ÿ½ÇA4w:I¨®ôREÆÆÿ‘ÑAüh@£6é¹ôsÞÈFcé–‰nØ2ì†2`H™–ú¹‘7ð-¨¡€³'yÑÒõ|ô ’ç)wšÌ‘e{ã€/ãØ(4Àà»Ë{Î îðniø’M–aÚ_v„ɼ‡QuÏ«7ÒdÓΑÛÈòÈm—p•ßb šH_ã‚ý–ŒŸ˜à®-¹ymçK8™-Œ{«XÑ/|ĉö8bµÞC‡A‡` µêú¿np ²6WO­,Úz©rÌ{F|%+ŽòE]ús‘³ö¤¹ªÇvÝ?(š'ØøêD‹6è“¥ºzʶ%ÐFÆÑ+¢‚ÛÀ–U²ûÂÈÚïÕž8×à#dNXÛÚ4§²áM ”ìüRHâe£sq°ÇÕ_U]Q´aŒ"žµM !™äà=2a“ƒúúø§ÚÃð§C$nŽ^co lK¯ 3í¬¥PëèÕœ‚gÀ!…!5¢½Çio‡Ú+>Î$W7žì|i,?Ϻñ£õ0›¾ó{TE÷ýZ\.N¹w¸ F´#ˆÀjtõôˆ•Åa’-®4±ÛDT joê X§îVg ìdšwîû­¢êÓÚ³Ò#~#Þ†+Œ÷<['Wç E¢¾3ÙÔ‚ˆÈSm˜ â;äk„ÉÆ*_³@ã`±Ž?Å;NÑ ‹H~-ÏnSmê§cÔ ì@º‡,{ö´«¡»ÍŽT9ÃÔ)3Ž@¨1öiÿKb–éèKnš!8?F¾ê\63.wÞNÖ1i0EpÁ@¬A!úà@1yfKFU ¯¶„Ú²M>®ñVo¦Ù–r(o ¶ãŸÁ[ÛißW,E =y ‘P@p¾FÅÊe\`¿¦°õFÆ®ó!Œ–›òXÝêÂ*É,µRâC›XbUˆ…—‘tÃĆ8†¨]ݮ؎±›ï²ß[ÁŠíaö\Û/(ãøä›’È—$,)#AÛÿ*¯$©[/ü0We¬M×ÈH9ÐL7d¥ã6­4½àØecCˆ7]ˆF³DO5Š|ØÑŽf<І @^À”Är?)8b§ºŒ`/…A™Ô”¹R$éa_dZ»¥#ðÁ¥Bæ¨CcD¢˜žöʱ›­¦jƒ3ÁHwköÓ% “í¸¾ j˜{kÒ‚„D)$ðÑÒ 7£ª+ùÒu|^=£ùÈÙʳ‹7“X¢EíΫ²àŒh·FþEø§ôVÔ0fE{¸å ^wÆìîM$g‘ýï—;ß[ÃÖ8ݱ+ÖTº²Ë<Üís°o›ÒéÕ?QÝŒgž–Œ¤B}†RåZŠvN˜é¾[?ô_õh^YjÏ.‡lñ=J”F·c(cÈ¢hÑC–®Øäš³é–e÷¸ Î0u…¼~à—¤Ë9¢.IO¾)Ô÷zü’È’gŠ:òð{ŒeÐÉBÔûz×ÍÉ óMÅa{Düªuů57’5 V,Ùä–)ãú%·ƒÐæ>­”CFà¯jß`ؾ(íw(Á}ܾÍÔ™R·…Bó } Áqt'”u,ÉÑ>XŠáôäŽ`gÕ#•üär_“¹%Ö‘²¢l¹hu–šŒ°¤ïš1ÏHíQÜ`Š~fù2×tùr´W’~¢f^Sñ"¦\—âqé! þЂGüé-©5+´$¥ÝhIÇáa¹‹ºäûRŠD’–6§iMN»ŠWñ-kR¾{¥ù25È é{ç„Q¹ïð `ª„/5¸uIÊ™„É®þs5$ý² ïcµ 'µ’–êÔÖì]@Rc¥Q•C>Se% À:Ö)ÕîEœï-×üŒ­¹™Çç!Iš} Iê3§ÃxYÇàež881IáUS)k5£)pwg5VÀ_¿*±—PÞ£ZHL]áØa/s¾«VÔ­~X)WI¸ m–^Øeý÷÷XÔu^sȯ©«éè>®¤î g½f Õ=†*öž0….e®Ú[­sì~ûã¶¶Cv….åe±yœT"8Ï·žÊhK—úúdsŒF°Ú³\%/¹¬U‰×œm´^™³öøE½• ërµ ƒU̬Lq'GCe&]Br½ojöÎçairsSË™ö"ÖìýÎÈí#Yöu×ÒQ4|F³z ~6 ßm—°P. ú|W—Œ!l6ØõŽÔÏRcwUðz¨ëÇpÚG¿\É}6ayÈ* Ò,`Áè;‚uª”~nˆØyÜËZÍ¥_ ; ç´MJì-5-©ŒM©Nb²vˆ;ù±wcY$"ð!³$—múÅÀ¡DZÓOΗþ‡^‘¿½dÈåP%ð”è$ŠgÊþf¶¼"2¦A%w»éî+sè}î>£QgüÒ;´dVý±Ã~<—$Ïİvà!a–õ1†Ù @ËLklή×ÑÔÒ!éiLÛžh#ÈêsÕ—ü²¢C ?âß8y ,Cz½AСàâAw\‚5:×'^i— *¸q,Ö;~æáy—ÉQ=€äøó‰þ-‡ÖÉt»xèá|ãë·F-*rï÷î_ö¦ž×Ûã²60ÿC)' ¬ˆ¥Ÿ­~1>ýMÑÂú­ dŒ•¿½êÊ"W æwDÕKÿljnŽøŽô8×Ί™Æ@1÷2=’õÞzòÌ.4ÕÔàng –¯¼,¯õëQ,ÌØJBnº#h©Aƒ¯X…´ý”5óaÀʉÖú çxí„Ïã"ŽÆdѸ¹yò5ŽÚßâš9u¥ºýwGÿ¡+–endstream endobj 895 0 obj 4167 endobj 899 0 obj <> stream xœí\YsÇ Î3+?bŸìÝ”w4}LÏLRy°eÙfì$>è¤\vÊÅh%Qe^â%ëß§4Ðè9–KZTâŠËåÕrŽn4€Æñ½¯ue5ü—þ}z²÷èëvñâr¯^¼Ø{µgðæ"ýóôdñÑA|ÀØx¥êëÞ,žïÑ›fÑÚEë|UÛÅÁÉÞ÷K³j–!þß­šü%¾åŒ~ËÚ¦ŠãÔ‹ƒM|øñjí—Ÿ­LÕ÷ï—®ìòËÕÚ.àú“Õšo|½Z;gªºnq|ÿ¯â]kûøÀò‹üàßã‹ñ1ã #ÆÛÎÆ—MX~²rñ®s~¹ÏÓ¤§¿Îð8_ù8rˆ“ü-Žôøÿxþ8È÷p05u¼¿5ÖÀ°0¨µÄ‹’ƒëÄŒµ««Öô=ñäjå–Gñµå³8jÖÁW¿<…k¼¶<‹ x_{¤nÆKOW®ëô8€íéÝK îšè0u·ü7Œƒa¦‹ÕºY¾ŒËÁá_ÄËm7Î`øHkïòí |À_OÓ„WÈOcÖ¾wù.‚žŠCÙH ÍtEÏòŸ@J@~8,,íteÜ·y0¢/_£ãN H‘jPLõ=Éò>!% ¡jÅ?+Ø ¨H/‘:Ð+¥z\š6ôç·I;â‚Á]ÂÚyÏßPœ?@˜ ¦™ÑMÝ% ͺƒ^±X».¡îøè¶j…R€—S¬,HHß6líÅþÉÍ}‘uΑdßšî\’d ¢yÍYS¦Mç{À|Þ moÞݲ©ÉüßYŽnù‰<“í÷7ygÉFám îâ$¿ð>ÛºîV—ðrÀäÀ¤*N 8³Y©ÂÑ””.’v­zéíìÏI%ÍâÉ”n÷$Yë)ÄEûô}Š ×Î4ÉØR¸d¼²$¸Žá(‚Ã)ã˼% ΄"޳ÎàV|ºÊ*th­"P¾šrÐéh'”áàÎRt™…Ñz¦ŒR<ˆ%1?Åu1í>óç\f;‡)ƒ±*ƒÈp&QK© Ðà v‘ ’øSçœ%'²&IA'ç›qKÒÈ8ÓiÎáJc,`u ÁŸÅç>–¾MfZTéêGv”óæŒƒÓgÑy’ g¶cB¾X5[°¹˜“ß?‹àŒšEï ‘ƒ=h›BLIgN™X5}U |°©žsXô†Æ‡[©çlf¤ëªÀú2AÄ3š¶ÇÝ=,Ûa‡Üy£R‘4u°d“PûÂ0›MÉ=®£ó³I Ò`a£ájÜýs̘½ï‘3rƒ,(#|WáVNg»˜QÖ¤á8Ë6ˆóÅßó»03Lõä`﫽W çåõb æÐ4­¯l·hŒ5ðïÓ“½ö÷íÿuquqýlïÑ?fïÑgðñÑ—ã?û/~·÷dñÕë&ÔÌbª¨T€¶E”œrr?OgׄwBg×T¶u–:[7 àeM­BÑŽ m#°Þz/G­È;ðÜÅv׳oCÐ"Z­sx#i#û„p2 ²Âî¼±âFf Ø'²©¤ìBžm¿ð€®cÌOE 4P‹Ê’6ÜçÌÃÖÀj@;¹“áõýµ÷ÚË£ön¢·ƒÐ!C1ω©àÌ ºp—ûÆV]7p"r¶ÑT\ÇaÏÀùYé^x»‹ fp2…!hy`Ú?³¨Ä©Tdu"$¼Ey”®‰\Ö@³’‘ÜV=Š®ßÜÕKªéð]&"9(å@О‹<ÏAeh(‘‘ªHq<5|Â/•Þä‘lËj;(‰Ëõ­Örth½ÑðÜv…·´É´µgo1¬üŒãåÞf ¬µ ]å½YDB«^*Œˆ¸¾LI£S(ÀðçkÉ@ò#˜•àÝ"o£Ø‰n`¢ Š™#‰Ç83ˆãGwŠÎ:ç5¯§R½œÂ\•IæÁ˜Íðû; )/ú¯#œAÝÙ=Έĵ^ôDnº]˜/E —"Ç yøGyø'¹;'QáÌ&Yè±Bã´\'…Ë)^èA™Û öúáZ·I—J„…1™'M…8|®Œ·KýD$·‘çžÂ}R?™’×fJ Ùä¾ùMê#©{_”Êf¥úD’ú¡<÷ì7©ÿú¤¾ë^¿i ’˜=µ‚ɶzêY.šÆÔZºSìÊ0Þ&—9þŸÜ²–áí>y#;–o·îSÚN b3µÔã©‹Wúâ`›½-~¦»bÎ2øÌÉàcÌHEŽça€¨`HÅ,§ƒ„ûÁ`€¸ƒ‡i*×Q¢=“sÍ“ê|W…w@jÌ‚lIên …ibþò.x3;ÛnE=}M½ž#ŒÍ€‚Â0ß—·hv3wvI¿ã泬à9Ï¥.“®hu3!•”†icj³¼Ðqï¼—™`†Sâ!¤èljcÝR©NÁø°O¥!K:Õÿ1î;Ìó2Ä”jäQprc}-ÅPÁ:‹l!¨¨VRÁ?zÂ:¤Ö¢cŠ”-c{ALÒ@D^%ØjˆÛ#4#…‘ljTÜ@çB§èB†b¤ƒíO@º+`°È­4 4§­ºSÞH­j”ÝŽÔŠ0†ÈX©²ÌjYÓà÷×2h#›ÁÄ~oÍdí…[áZ¤Gƒw%bwD"ë{“±Jï æX”ŒìAè9ñb>/{:U#ÛÚ[¥!¼-Ü|³êg×µ†(…þ:Ó9´kÒsvãÙ¨ 4®Yþ£2Ùg훌 [ö®»¢sNÏp´-zŠØoj-UÚz†×r#í1ᾜz?[/!ÎÝ.Sï©1?•†<ÖļR©²½ùd©_\uê—MÏR€Kw×›^æVÚG H™:éAÈÂE®@½ÓQûE!]‚Q 2<Êø¬êÔs¸ã¹€¦ë†„EvcÓ å(`Jò¯OøÆ€‹wµAúÁê1䉡H]W‰šæi =VxœÆÖîXáéúæpÎQ¸¾ p*Zšò[ LRãÜ89K=ç©pü¨AôŠ=ÔæmP•xUªåKÏ‹<)ídpvPÜaå^¢ ÉRä±;]Ô‘M±%ÀP”N6bmÈ:ÀY!×Ou¾s,R†!)#+ÂGÇAŠ0$•±o/ž mF*Éaù=µDpE¨—ª,â`>%ßÕáÏ4¹ƒ:LBþ’KEÓ·aµH U¸[7UMÚ¥Å÷KeMO *Þz'2F&²%}˜8ÂØi«x¿hãçb‘§Ã!w-9a•ÊÚ‘(Â0ø“ —ÃHü8¹cfE™(»í¬¢&ùÙcE7¥Ï¹CGL þÁ\¥©©c¬¹þƒCÔ—iPm2Z¤[¿2×+/îl¥úS’§›ŒPN™¶ ¶õtÃÓMŠôîŠ@ƒ\¼=QÈ=¬u‰ P×è ƒO6'-®½GÌ2µ‡ÖìÕÉ^»›h€®v<%‰hŒ[þ°žý^ʺ]âM“©¡Qðtë25ôq?v15‰óÈï-\cÓ¾ ³øIqsz)=e¹½”¦¶X€È ™iÇ£~­~|²^›8>,›îÖýÚµ³€ä°m³¯#Sk*Õøûµ¿š¸-ꇧÔ¬YiBËÓ?¬³­+Ö3´)q*:CÍ1nñûç)£Â<*¸2ÂÓ×Ãóûƒ£ß#¿‘`zWSÓPê|ÿ^ú®…D3”HÙìÆâDÛJôûAî'Iýí»»zåÊÌÀ: ”t~w–Hf—hú39Ц`þjâT<¡ 5Žø Oò™ŒÔõ9åe5GÍmÈ®UᩜJGÝРά/Ó Î<ï†UV€1O²,„£'/c´{‘yp%v«˜\ÿ l¤ 5Žt"ZÈZIoÁ›% u)¾›†Ô8Îh<-u'´ì"y¦Ö§â¾ôà ^+)3¤õè£wéà)sªñ+î}Äc¦U¡S‘`h¬ŽgɯҴ٠)k| ¾ ­€Š3áÜpÓÿemXÍÿ¢‰ÊÍIDkRBDð’»®µ‰¨äæI¿Sþ¼A¡æúrzÞs4Y–h™j#K@·”ù¨æP­y•xºh±vذÌ!Ûê' ”¸’Ó7È—Òn½­&èq~ø•¾­ZØ÷‰*\‡‘ëCs—n@è®-*Ý;ád08‹&p{‹Š±;UYzê$ÙZeÁŽŒ¡£¢Æ’ÛyÉlSá*»qOKQØ5@oIãúé“ 8š±w KȵQgÅ­E·0, 3¿ #=‚=wkf@:{úe±*ä‘ôKmÕX3Ó®2¬4”?td§òq¤EáSS0€)§%’=”†…†qå©›-Þ1Ç. -©.!‡Xy|uw|“1“n78†‚œºjåüç/@g$ ÑW¸¡ü›EÙnµ÷$Pendstream endobj 900 0 obj 4564 endobj 904 0 obj <> stream xœ½\ësG’¿Ï âþ}óŒƒiºÞÕwá`ã…]Û»æä»½°aá0H6÷×o>*«²º{¤?‚`4S]]̬_>»>s<â¿ò÷É‹£;Òñùë£ñøüèç#CËŸ'/Žï@g e˜ÆÉŸüpÄwšãd“óÃhO^}»1Û°±ðØÚ£¿»<ša4asšmw†?în§š½Ûü/´ÿ×vç\Æ1oþ¾ÝùÍçø; Óäà«Û<ÜîìæŸÐï>~ùl óÁ­q³Û:üf6_ÀÐ;û‰»|}ÿ²µØ”ãæ‡|€CN4ÌVi)ÛÍ_måÛ_dh\šõÐêy_áo^Ú½­_¿ùnýöh›l3ZØæÎ…¦Ín˜r°ªÓ½º¡/pÚLàrJöû“¿õÕÔ÷Á 1NÎ Ñ#üŸ¶;çcãç£Å¾»ÒyçÆ!™i’{Ì’7ØEßBB¦ ÁŒSÖíŒA† £v~09³y…{ØCùê§iÚœn]RؼÛîÆ!gg­Ù¼†Í¦8$ç6—u¢¸ÑEGü*d ïuÒ_ÕO¡5ÅÑæÍPöb¢vä~ 1¡†`sö¥«™òæ¢u=§Y\~—GoÛ<Ãùó|BêJO¾î²“í™$k2v}Ⱥ;[zšL=it—€Ÿ¸» 'šäPŽN¡ÑÁšÔŒ@<ó0¹Œ’†d‰²¥ßã¶ŠçuÂF¢×H8¬u~MX€ïÖMùøä‹£“¿Ý|ʬœ*:t è'œ>›&Ñn® åNÌKì–˜#2•D õuN ähg'ƒ×7¿lmf!áÈ|ÌßáQî\š,ÝyÙnyÝÎÎ3Áöüæ ü ’äði„QlŽp2®´=ÃÅnq1 ãñgùÉÖ%^BíHKÇ/8Ag„+ÎX:íx ÷ 'Rl^ Q™“%0Áõ]l‘îÀª!Áù*§R-á1ÞÎõ êf"I!W3孥ɟâ¶!hM)pe[‹w7»]fâ!ˆæÝ~J7Áh޹.äžñi ††àf&Zð Æ É~¨»Ç½îd³;ã†þqÏ·p¿"§‘˜gø 0ºìÂóöÏ·,6xC&’¸a­¦ {Ò%Ð"–O²ú¬I%Æã‰'¦»ËXöx%ì‘Åœ6·ñÀZºû˜æ‰LY¢áEá¹ÀÃàß›<ˆ žyÁÿx¤SÀ µp_•“T˜#g*Ør¦¸kCöF©Ð3ÜhØÀãÂ~žŠ¤@Ÿ¤N`…÷9]pη3_ĵãaYP/IU 3¹K‘\‘G‚ÕO6Ñ_ËìU½¬ŽÒÓz™ÅwÖq{Kúo'$éňI GÒÀo&ÒÌE¾ˆ zˆ$=Ÿm ¾„°;oýæ§­ã¢@^h14;k"’˜@~¾…Ó­;zçi’$’Ú%¨<ï3-´ ›·#ý<)ØŒš×Y¶…ÈFùRX[Öü þaú†@í?nÙÆú/E’ˆ;À»ã›õÁ+€9æ*x}¹UPç-ª³©MšhÒï6µ“˜}À®M€¿ßmë%\hµÆÒgU 4ëë$kÜ;ø)Ë%y¨ÜpÕkMl&ãÒ>è?–úœA¢4Ù†‰´–†òTÔCÓ‹â@¿Ÿ²iÇ“ ÙSF/çY\dmÝ ÌSÙýðhÖ¡.ÊÁ)ѸzÄÆÙPÿÄvÞ»n*hª“wËä>¯(”lE!:f·Éˆ¦²úTª•@ ÊB]léòŒŸÎ %š4ùd”íû.‹pËšÉé¨`+ߤ¸Éèqyª”~ÎPO ækê= "D~fÕÎlðš ‘bO Ÿã$‘ÔÄRDÞ 4­HÍÞe# ñ¾Ð¾¨þEï­Š1…Qt‹0y3êÙ䉛EDðè‹gÈ +¡± Ó0\{”!RG„cR§øÿŽ åÑFçì;x–{ßnQ@²¯|¼R`S6oê~FT7@S1vh›½òAvÔóÑÓÞ© ј1T1›ÆsÆ Š@ŸÜnÆ{â¨mÖDC›e²"80Š2ÏÓ{ØØ•CÀE¤ù—BUl¤zárztC!‡ÓPá—,Ã…,ôãD˜Ê̲ˬø°ÃgÆjÌz:¡f÷ËžÌÌâîEªwJãm²U‹¢ê¬óèw²Ý^ƒ}¤DÆMŽDFLÏ)ÑOa•uE¥9ö R lïlù(%€’yΧ¹cl5,Ë1 \Y±üÁ€Ž–¼½5 ) +J‹¼•´¾Q6fø×[Y5µ\±ÖšLsÀHð\¶d ‘APUì¦ïÌ:¿^+ÂP#Yÿ¿48ã±”‰½,ò;ÚrhVÅŒ I@¿½5±®x†h$«;‹! [”«¬'.ï±æÆ©[˜¥Î$"½†o8r ž=HØÕ'ø•e%WÌ@1EMùŽÂLzO‡p±W2ÿYsÉgQ• ÛÐÿ¼>°Y;±ê»ÆŸf8vZ€i\¦ÇfÅ/Ï Ãs xFŽ3ùäÆ)šõÙZû}M&Ôr g2ÛÐh¡ëx·=.užDÌe™¾aŒ.²5±‚|b( ¾R±Ö}•Œ\ñ¸¾ìVÃ5aI°®G˜4~Ìe6 =dï Ãjø¡*äÀVǵvƒ’âÂWnBÜÁ×lI lÃmÞ®Q¯‹Î{ÿoýÿÚ¡ÉÁéþ.`@xØÎ úïÓ&6Ë(‚,¬…ª=ÍW áî{ã‰vVÅ¥žÈâʃßÜør¶q$< ÕíÂv gCG«àŸÆfkU³jdéý qHI.ÚK±7‚k°UÓhÀ'âP1\ifÅ}¯hê"Ké¨u\‹%&•^˜ÍXáïl»t¿o51j;ï5›V›É<ü£=´UŒ¹V£#]÷6.®äÖÊ& E£Å $:õ06(VY V!=ÇGuൗZJ+æ‰1d^Ãfk;׋Dƒz fžš/·.£|;»öÓ¬îçiS³oX»‡öRȧÜž² [õYÏx‚™U¤_¢Ê{—s¨OXUø‡x‚"Ç·™/âÇó®Ã*Úi…<ú?½L]|Êθjˆ6WyóÞ¤Éh ߆ - ›Æ:jµÖŠqŽ‹”€³²Ù±;R<™æki~Ø0­ð'ŽÀ¡‹Jhöqbë©Á5àÔæA“þœg4/ º¸åýª@•ö¬ˆ×8„XèüI}F-æÌ&Ðò‰wÕŠ©k¶PK&OöÓ >‡¨þÊ圧%¯?)à¼,Ê*šùd¢À‹¸9z‰«€%¢3êÐÞFêÁ¬ÏfÉcç’rÆœ;¼>kì[Öøop9Yãtz¶$ˆý˜ÐÇÅ¢ ıå‡Uzù¬%S¿û}CԹؖVmé[¤@™Ëñ·§wÇ 9º°'jIÈ7ºÐá5Ðr<éØŠñQ¸ ÜyNåô¶Eê9zU3\Õún’»)XgÙŒp9úyðùõÆj ÂtÅÒÇ’¨¡aô.^¶¬ëŒO: ©šy„ÃË|Yü-e-×ÏäàßO¾Y«#mšÂ­¦zõïiJã\sJ*¬¦ÏRìVL‰ ¡ÄgcU¦<-Þ=”¤˜»­ˆiüM­™Á ŸË¿hE:?ÕÀ´õ-0}ýê(¡êgª^%\æé¡@™ªfà6Ó³w¼hM]>ó² z¨€*ÁÁi›‡­½Ü D¸F"&­DPU“¯‘Ù›ïD°Ø6…åÁ/YNAM¾SlÈi”´‰ËãfŸûTÓ7ÔhD2'ÑÇ$$ØƒÑ Y«Vã1Ö‡¼ë¢¯¡Ç©0˜ÎS^­*þ’Pqà&ˆ?Ĥ1öøSj'»j£jòK›h콦œÊÞÔû‹oW¹$`?£Ž¹ê‚o1ÕªŒ:JHTt¦©()® -ï? ·NrYiM’¨íï§&;ëu ×Y'£¢;iL•S€×‡g`ËÁ¥™z/‘ÆÁ×Z÷ÿ¤À aø‹…©ÃäµIòÝ‹j‡=ÀY¬¯€^&7›‚Š6Ú«êÒZVv%hܼ†¥ìª‹,Ÿ#Ù]Ù©1Ñ^KöA% G"z¹*_Úa“x±¿W¬¯êlJìBXóŽ‹ÈéZ3M p­˜8**¬Øô¼L¤šžµBkL0ßÙR2ó@:Òu ñf—6$Í`”¶äð g[€ ­NÞ…V»”AN‘ÁO%qâšÃÕ±?t™š1UsFºôªOuüýòÅä„Sù«VWªªa&v…:=ô]#+%&ž+Ök†í‡Ñ·H”ŒßÊ€k y“W²¡p†CЋXïöG·Ä"[êé©X³æKpv­ ´èe’¶Ô]¯§ãæ?$bŽOîÊ(;œ±>ïsIúOüø~`Š–¬ÆÍ7øñ?¨Ë'Û]Ê>R‘Ï™›Ìµqlƒn v„CJ¾­í¯[çïáZ©Ñ~Z¯?×F±4¾l¯&ÕFôNÇLo#ýÚU\Wã{e¤«ÖøJï§\¢i»Js .‹… *ìrHø¿‘ÿ‡*]¿À‡…ô¼ðˆÄÎn³¥è×Hk[£+$„/(ýS·V¡tÛõÇíúǵñ»MkÝÕVÓ©‹[¿oz¶Æ•çkd»¬O4:Kã…ò©W˜¢Â-Æa@ù¿íFRÓS"ÙeÍu5«ìMëû®ã&²Øu?0IOtm>+mf$Mª¹êjýͧe/÷N»àUi<_“ÞUB52+5UFÄ_2ìâŸv´•÷ËÚõ·×ËC?§|=_ð£˜T3~|^ÏÐ7ÈìH¥…Ȥ¢ÇfŠ-Øþ×võ“ÒPgõøÚúíΚ¨ˆ”€=7ö§§U¿,aø¼ë)Ð" »¯V`x5f†ú0"yÆ(ƒ†k]¥nµVUmŽŠž*ãÀñoj6áº`5úÎ52»°oiæ©Ö¹’r[ú¯0 ­ö.¦.I-·lD«ƒÅ‚¶©Ö eø…ÿ AÇ@$óøÉ²F¤œ€Ð>¾ BWí/Ú=R–÷ªDnÆYêcÝLndh®Éòa¯Î î‹+0Ï{]%,Svý‰Ùì”úÄz‹=”›×CÚ–oÊNÞõO 19–©sóð±w©;c¯wµ»ÔZ „‘Í[åµ6×àï>-áW·ni¨¨½ dk»r²äUÿåœÝ$zHjía‰;w7ÔE/ÊÓÈÌ¥åTÚ»ËÑaöþV—PÆc‡wÝ?9úúèçcç(£;ƒ´äcc05³Íh©>yqtïáч_¿yuõôèÎÿ›£;ðãÞ?>…??;þ·£û¿Þûn‚`äÝÆxœcp™_N°2+ö¯Óû§¬!v+í|•ýë Üþ?|}!cõ‰^àiö¶=¡¦<\G®½[³Žmüã·f­\¿µEÕhÅÉý«õùOa„~Ïq˜¤Ø˜ÿr&ƒE—«’¢ B–å¿Í½Õ5ÀÞÆÇÜJL]¥Cf󩘺7œ+Ÿ•Q—ÓïQO-X3HNBžDUºMERz5×¥Ú8Ó™g:R–t¿×zw-.÷,¶%¹]žŽ\–ZWïµ®7e?g:Ëãåû%nxfßùfQ¹äg øE¶¨)ìj\ÜáèëJÙìè+e ­”íÁv’ÓHoŠcÂæ|Æûhü,|„wyO¯¸¡w¥øˆ%­%÷)Ü]k‡¢8Kc6DzYÇòÛ˜8qB*䀼k/7Á«6é’·VÈvY«×Ä9 Ð zä1Øô,¨þS|Le iêÞ¼ÒF_}±ŠzK»~Væ4¹þ“÷“”Â?ޝþŬ–Ü*óTÝßWDvPq¼,ïAym‘Òæzû‰á½ö¥ç@få/>rtüÔ)Ñ[}t¡3¿‰æpXh]ðI.;9DÒñ©–ÎóÉ#'×¼û§þ¡èçì_X2Þji®¼TCÁ%=mI‘z˜7eÂßʳ—)tÐJÏMëϱHEb6û'e3½w Ÿ.×ORº<-Ý> stream xœµ\isÇ‘õg„~Ä|Ó̆¦Ùuôåo„y™\ieðjmkÃÆE€KCiþ{Wž•Õ0é`€t×]Y/3_fÍ/«ºr«þñï“«ƒG?t«ó›ƒzu~ðË×+þurµz|˜ 8ŸžTC=¸Õ᫪éV_u!Vµ_^üuí6ͺK?õ¦ù¿ÃÿJµ‚³µ¼oªÔN½:u|–~¿ƒ™ C¬=ôøv'ýÞäå~ú3¾ÇåuŸ_ËÔ×ç0„×yã†áZ,|žžÃomÁ ;IÒz+χôÇWi|uÄn¡·ü_šwZ Çs€÷ýPÕÝ âӀɚ!ŸÑ؆!àâÑ2P_úE–£‚g YÛ´Ï©™4Ž¿Ð’5ÎÃèBçQÜÞëû ] í'OÏ̘Z…C‹sYYôò%Ô *TYÅÀ-ôÇR 뱕ÙºP5-œYX\E‘©¶˜®×½Ç'g°ôiU\Cƒ&Ÿ|ðË*„ªE@HëЯ\p®Šýªê´=àËã—^þ÷êý»Û³ƒG?­ÜÁ£ðßã_/Ÿ®~sðìåêûbKÀÓøU›fÕEÂX±„ í@§‘„WÃÕ½N É¢Lì*- ŠÏe–àzã[XÖ¡ÊèA’[‘dø„çB$YOW:vÐNßåB"ˆ—Ð@·~³ TñS‚tl¬¥¶yÙOùÜEísÛ0Ü—BéPH9= 2¢- v c xâŽqæ}Ò€`CZ±¡•St}\]>ì @FGG™Ž ÏÉù­ׄš!Ò¿äsU·ÔäÛ\Á‰ë”ÒÚ¤ …¹z9äË(g5Hlë¤W,wˆ b‹€ ª*ôÂþA;¿Ý0°·ÁŠgÂó>Âáúæàð?þš\0˜"Àz@e––E>=ÿR‘¦è=¨"€}x€µ¾å§ î~H#¦\÷Oé eÊß ˜J¿ÃR L¶¼óu.VÍ=¬ï~èõS³P'"RÆõ£Ôs¨uäô~—+èÃÛüðæOøv®Ò>|¾Ÿ{¸Ó‡×òiNÃF=ÎúÁÎ)éÖO›tŠAý4Š…j£+éùõ9ÞùT|Ê%*&U{;Ò­PÁy=±„OŠÃÏô_æÊ¥eÇ6öÁ™èIëd«Ì4‹fI’ZØÍÞùO÷©U:plÎd´•"Æ—0„¡E§±Ã®ˆõ æcÏ«Ïs ³+ódd™ÓvT{0™+"[…ëÚ™Nì¦Ø4œuȘcÞæ†Í.fKoKÓ/I:n<ÊÎ1`ÎvD×à¤!âi¹Uð¨@ö::K*{$YÛȰež§gdg OOZ«¨­Qö’Ž¦Ã²×Rÿ*4ì^ƒ kNZ‰Ž>-¬F6xLÏ Üâ‡pë éá·³÷ÜV’÷OôáŸrKßÍ•Ì}~©ç€"Y2vÞ´Ø´¼òËÒ“0²ô8U©Èdßj]6H¹ø±I˜ HeÇhDµ¡³ih:.^ˆ¦Ò6”– €t2‚ÆÑ5o<»_5¹_ ðÑœ‰…r@:ò&#où¤=S¤=g dù2ë¡ ü 4¤¨™AD–v>­X1ׂœiݦÿ܇€¬ôÔ}t"6ÚD(1!³Ú*]:K/Ó㇆º5¿5Ù°¹º–üZ'Ú`q>n ,½Üda”ÒòaÓ Á˜•äíH9ÎêPãø »ûJO+ÈNñ;ÉÏ‚oÐöi1ñÃÒNþ?´2Ö`ôðÇ ú<Öƒ.8ÈYíp,sΫóÄ„Æy¸½”n½ŸÂeˆŸ÷%ŠEÚ‚M€âãú¬K±Z!¾#?Ý÷ºFåv:ó: ņœIX¢:êQ©Vû»PM|á“Åi—:Ô:>Á7ˆ!곪»Š% Ñc"ú6ˆ M•ÄHÉO ×ÍZeðƒ¾S²í“éÚàÊ!¼á­B¼b‰ÀG¯¬9±„¢ƒ‘±#DNB;âiêtx>€p<Ê3‹ ås≅>Iãw"áÑÀù,deì‡&w *-úî¡©;ðªÒ1ï*ÿïóÝC‚âÎC7•oÉwßï¸ÀÒž*Ôua$rï6·Ç³4åJBƒ/ðÏ!d¢ÎˆêÉÌ™1¢*-EÞÔ®#i ¡¹  ß‹—ñ° ì1 ¼–$`$Íõ”]òGÉöQŸ…£ûJ1VìÀ3Ò@Pmö|lÉÓ z»Ò>|Џ½M]àavÄDÈÚOi“ž€ –±®+=bS¥$=¢æðt.ØÐ!Í)Æ–q$øYž¨Žÿ ºñ¨ ì9Xm%µÁÉéç$Ÿ£G€ø‡jE¨*L8„Š‹Ë®lõœ;ËBgÚèçG…+´#CеN ìD9CER˜i‰¥x˜`C{¥Ã²Ég´qPy³8QÔÝGkutRCßÒ¾¢”6ñ~)¹¦q«™ÞI"ìºhÅÕ[|°ÜS.k“|‡€Ô;Q5j˪ŠKÃü5}èëûXùŽç:!¦ä:–¹dή`exÃ1²×H*±{Zj~LÅþÓ–Í´4Ú6Š×9:Èlâ&eÑŽÑ Ü𥅘3haá c64ÐãˆÂ”Ñj¹;´ƒ`ç Ê—V¡/KVÞÐü¢£˜æ\‚ö ËŸ¡•QZ-° O™åÕÑœééLs(Ä#„C%1 XÜè ]ÃúÁ˜ ·DU­/Úîvéo1–å‡n‰è €'%:¿Q ÉÍ?èÙÿZkÿþûIËaOÓv`T¨C>“YŨµ»9N³Á.ÇTäׯñÐJŸôáÇ9ñ]~xÊü$±ú \ɼÄóÚÓ¯Ìv^Xw¦‹üðdŽâ<›«£´(b›øjŸmw€=oÑߦûD…ŸÂŸ\ÔÖîVc)äén…LÓ<¢ûfŽÿU.3©ðæ_ÞÓ8tˆ®聯/rŸy÷?Ît“ó†]ç‡_e9bg/¤×Åèàc ½]¹÷†R—²»Ù²g2ÕÁ mÙÊo?HÇdýêÇóÜE¹D…áA“)펆Cò«C]Àà†~äýHVêﳤý(•´ Á#ŽÏIÈ>+2ˆÜ-¹ïçÎúë¹’7´Y‚Œ‚>žî©><ÀSŽÎ0•¢v¯ŽlÚ4•&pÜû=Ip ²[‡iÎGÒÖYO“£I‘â™h' =aÜuOŒkÇœ/£ž3qR[!—` +¶´ –þ¦Ç¢¬‚ ž*Ù7&£UÄP®¢uç2V7l_ÅÊ×J!îòØ`¼’Ѫó´;±A§NãklØkÊœÛÐéU4Âßf£h'ˆhüí;z »š§UòŠçÙ;›ÀáŠÐºüBX6`a‹wÙžFÆøšÜ$[ZÜJ0¡39)â›Rô$#ÍAyüÃän‰J@G3œðÊ!¯l¤R `ä'øù‚ 5- ÏFµü¦Þvv¦²ûD®†ªñÎZåÆ=Q¯¢¨iA²ù»Ò£XÊ2áÁ;4€ñ,ß,l‹L€´€ lÆT¢tP:´2±R±L¼²~êµ&C£‰½Ð%ì„nH-u‰aAô-$øôA±BÏž1Ñmì¸HВ凄¤òßZ‡orÞL*òìQ]öÂaãCº;Ï…è!’ g|Y.³Kþ‰¤bª3ܳºaÇÐñ¯É˜ƒx §Oe`¹b0[еßO6 ¦m£Í<,—rBoë<{òq‹$_ýDÑH‘b¢vîÖ9%0‘±·b6Cc³ê–— ¥°vNô²¤¢Ñ(hánH- •I bihºÜE¨æYäÖÐåCÏ1¤©3^r±SùäŸ+iX3(-ûÛ‘n~Þ¨Ø>ÔEë'MºÈEm £TdÃ$X1ÙÁró %µ ¢ñì¶M¹‡,9€@CÄÚ Ö› ¥o¾P¼áœ¦tÖjD–QÖ¡@`Õ(‘×€vm'8öQÖŠÉ©”]êûõÈåöb©0~Ø á伕¼q6X•ZÉ%MbR†ÔÏ7Ùª³q-¤ü•”%¾wÓSÜsµ^é!i;˜9Ì*Rô’Lx&ITS‡g-ô9µodaÁœ-e]^Z•{žSØÖülÊ®Nì‘ë±E†‰ŠƒÉI»¾&žïr N÷göŠƒíæ\cv¶LR6–° ÔBøÓ}A&fó% ¥ÏL8’¹£P¼„U'É8ëAwsx’Ï‹Éåp¯‹-nÈKhÆà…Ü×”$Vi¦3è&kÑk¨˶• Ä£—´C źï€OõP‚÷ ‡†=}4$fW96¨H‚zÈ/fº(SýSÎЉJ:­Œc>Ë¢PR¸$}³dXG$mGÁ¦2ÜÏxcC½Ð¹G“–y?³š§;Nò¸Ïª„y^sÂÑ ›&îÎ^ª5sZ¹¡Që«§ !}NNT@Ò É‘­¦aªp…3²ú¬záŽÅ+Ó Œ„»Rn ©QP¤ÝÀE]1ÆÛ´ºKê¤L…¶ùFš(‘«2àŽp)cΣbâ™ó JEy¤A›¹”8¬»:‘ŸŒÆjŠú¸ôÑiÌÂ[Ê„©¡Ï+£Æ@EŽ3Cór:¼äa80„N36KÃ3u4îÚD ޲úƒ'U ΠiTìh—cŒ¾V„œð ä¯5UŒ9PC2©u^Ç{töÇá÷¾†ð@Á øÔÍÙÕâ‰Ø‹z6Ø—Ãu)ñŠÝi kK¦™£ëc…Aþ±k²‰¤Fq½(A =‹‚W°€U¶+Øj7êkÄ„šûls¹bÖ×e¯QzYa(r_dgTs)á€kPPÅPwš\\ê| ¤H,ÒÓ™­lGwc ZµØÜàBž¬lb“ó=#Çy’Š a|~ •* q?IS}8I0E7DÍ2#3ˆº(EWöÈä3Ë_ÛN[MGÉ3ã^ûÍè¾ÝCÝ€ÐJè#æÂl\Iž@omrÔÕ’íñVéÔQafŸ#JÌØ#3Zr|÷°1èÒB!‰Š…šcºôfµ>iæ6ïJ‹]‘Îjç<à ˜û`ˆ¤žÎ€IÚ׃–idU(6]ItkÈw°êmVªzqÉ^„:ͨAªˆæXR$sr‘íæä†“MöG×E ©nRÃw–(žhð{ˆó™U(<=#‰e^‘¤¡HÅ <œ,{i*—2bÔø5¿´²rh* Ú -tÿe6¥_›!õYHn•0—0ËmW¦Ù[®Ë¢ŒM[hûÅ8·ž ¬Cq·ÏO&Me”vR@˜Ï=Œ³ÿaiÆ"qžÉy¾NׯT§xL2ª¡ÉI&n㪦ƒ @ž>5T¬W'\hSÓ1Gž oû~©ŸÎÒ§®uI¶0œX7-Üý®«6tIS¤ J?Wé¡ëj×u#M»”Fþa ©1eGšº²Ê(i/}ö® ¶rB]å:Úuå}_‡Þöq”Ê&kÖEF€L©¾çäÒº†ØôQ†â:j¦í!åB›”¬còæB´ 0œOÚŽ÷ÞàlÍd˜{ý2­ 9aZîqdߌºl[KÌ26êI>’s j,á3=8úLJ ÿV¨—Ô'¡·‘c/ÍÑX ˜ú+—ëV`»Oƒ|GÊrÍ%µI3´«ÁQNéä¾\\bÐ@ʦf6Ó§·C. "lz˜! æ_úƒÇJ#hÄUÈA2×]B'˜Êl ˜ æ‘J\™v©Æésº·3þ{Vitç)Ë”½eÔrc}73¨TÇÅ©søD2PÄðdNÊröU›/áõƒm×ä‹Y9vW.A8Â>±Êi¥Ëì¼Ìæ ,tà¹Q€r1ÜÓ¸‡“+éÃ|êͻԇã¹’eû«n庠'›j•æêëÅXŠùV‹ÂCŠfìjÑ–#É㠟yŒ²í&ôCƸÈd‚qô}½¹š9óp0Deaÿb"ç›f,ÓÅŒ9·ÇÔ|‡…بå¼*i÷¸`AgçeÙ…®-Ü4¾kÑëÅGµÇÿn"t&ÉÖë÷I°ÄbH›Ì8"?p14Åvwn®€ékPizswæbÜ~ºK <]yÜ.~sGŒ%Ç!à±ãr£N®Ù‹—¡ÌJkŒó7Ô+°þ“ ØÌ¼eåó ©ù*ëÄém“w“ÊgÐW¨+Ͱ1(¶ÜÇ €tÕ­taîÓƒ>‡Wõr£Qï‹l.Œo>åL¶Hðþ#YSöÖ¬«­õVÒ ]›¥?,qäFÇŽ¢€K:‹iöƒ ³™ÄsR†iabN“»órf %×¥—&Ú7 ã»ÝƤ˜ÜÑ h‰|{lù‚XSD¯Œ'~0™1ÆÑò3@fÝ‘Þã)–øUÜúgOx‹ùö]©øvd³Ì€ |c þ‰àwg²ž|kFjÂUœgeé9ƒe#MV’UqÕ‡ªôQyN27@7̆QÜÙG¥ÕcŽ+=2ƒÀjí”0,Öù²Žšµjî¹V8º»?hŽ×ïÀBrPk¢‰â$É@ã™*J6Á1ÖQ(Á µn²û”ã2» f#|ü½K¥‚3ò†…¬¹]žI4;ËöÓž²‰‹p¢TÕ¨yÉi*à{*Z\l|=gŒWƒ©é†y/¢2b_køßîÿH• -‹‘Fú–¾Ð]“u@¾Ž*âóÛoò=ÀŒ? Ê)Y—€Ÿ&áÄYàc“\„ îé†ü"R.«£«wÒÓAépúS@1° ùão°&óq%@úÕ©—37µl3÷:x¹&¶¸§¬Kxáãë8,ßÙŸ~=@I’›߀Ùœÿ«‰›Hå vŽä¯˜ðO8ù®²endstream endobj 910 0 obj 5512 endobj 914 0 obj <> stream xœWÛr7 }×tú š>ív²Ûå|ì%½M:mS½Å}-ÇöŒ-5uœÔ_€äre9íh$qIî»õ4ªõ„Oþ¿¸[}õ:¬¯îWÓújõn¥xqÿ.îÖßlHÀ(šÓ”Ôzóv%;Õ:èu0vœôzs·zÓ©Þuš¾c¯;ÏÿCœÔ8)×múÁv?õƒî^õƒSŠ6u/ñ<ô¦û«¿âçzú Ó¯ILþèÏ?ã4©)b²(ø®Ì”õÒN¨îëÞ8yÕýP¦h‹±ûîûÞ@‘wrÓlM“l…½n~&Ï•n=·N>’ó›]v8Зþ!<äU2j *%ú öß$ÿà¬ËÞv·ôpO&iÂf ÝYGNcž.h€ÞöR¤" Mw¹Kš#Dw2¶Ý[zî¶dÅÃŒNÀ^åù„põ†ç²§×Pl F»˜«Úì Æ‹Øˆ` Ð¥ã2Nf2r˜;®èÿ@ß¿ûÁ=1Âww´Ã`‡Xȸ@q"9€Jn?`Ù1HÐI›5Œˆx9† å$‚§X•pÆkߢþ¾/;¯7­Åy "åý׳æCö© j&›i½Dº²%|’I¨¾ ð¶7&jv%ÜÊT’Ý3Wtt£o©’=Çá~‡‰CU3è3 öòè<…i7 užÐIN*Í^BÆ>G"D(ÂL¡t^$×R.!wc$UOH[ðOšz£a»>’|ÅétϬ˜T.EAƒO¿+¥â–#4è`*aªZ–f»JÙ Ñ*Ö„A‡cpµpù¼¦"}޽àÔMfkffð¢]å”Ï\8À€‰i|:×ýÌT> ?ž+ûÓ‚FÚË‘^L_P5+b±ŒÆÌ¹š¾:*æÒV˜–âhm¡Ú=#=H^¦RsP@O¥°Žúˆ?M"績 ±$ û|A{¨´“’ߪÛϦÔ.qFå¸CûJfÃæÃÜCt««©¬'–…qÇ²Ž—Æ·/9Ï~> stream xœM½j1„{=Å–«âí®î•޹„[¤ ©lâê “÷‡ŒÎgÎ!igæЙbŠm-çarw»L§?éäÎNf‘–ã0ÑC…A“Pbª¿î’ÊJÙRˆJurß,¾çŒ­¾ÿ©/H™Ü¦TûN¤z„yë»ÄO^B)÷©ðÆ+øN¹¶ù軫°ó™„óÌ›TÕ¿®Æwa“4\ØÙaøÑT³ÄÏךŽo Ãܰ]§ÀÈJÞ@úÂ[°=êªÍ°›jȸõ* Û ªí/Æê>±þN¢Ltendstream endobj 920 0 obj 227 endobj 924 0 obj <> stream xœ[[sÅ}T~ƒÞØM¡eçº3ÅS ¡âT (•ȃ,Ù’ K2–/˜üùôez¦gw?I¦(áOßîÜzzNŸ>=úåxžÌñŒÿ•ϯ¾ø~9¾¼;š/~92ôð¸üs~}üÕ)¼Ží<Åhãñéó#nhŽ{­òñéõÑÃ×㉙æèS®Æ;YkœÎÆyšSˆÑ™áUù:ÛáÍh&osÌÃ3ø”Ý—áõxâ–e²ÐÁ¾œKÆŽ?.Áý÷ôo<?-i18“&ïr:>ýûÑ龃&k‚[`¬yòÉŸi,›²^àø1Ís®ñ£É)ë/ƒ]pÎê/o¨£9†8\B÷q™‚1Ã?qVKˆ†¦=OÙÄœ‡[|×,Ñdx·~T/œ‘BJVfýp‡Ÿ\v¾¬ÐX°þ”çÌKÌ“‰³•%‚•ýðÍè†'Ðj8Åß~O"ÿ ë·>LÖz…_žzax sÏÓÒÌb{ˆ³À^pr1OhŸúìŠ{…YcëÄ¿ËW;ÓyƒÌ4ÛWmý·#ÚÙfph~|zΫ­–CÓÃ¥ãÀ.áLô+Ô¯˜úÈ‹æ)¾‡ *ßÂqk–ŪWe S±}y‚†¸hMŠMp?,.š-ðÈÒ{íØ|M ý?æ ÷óf´8û7½´ÌI1͉qSxºÐBŸs1‘e?mb_&˜6®ßxnqÓ^¾'»h¾…íèìó+°Ýè".²‹àúÎG·`w®m96z7:+. »`Èñ7Þâ–yíý½‹¸Åh÷(Ó tÄcˬéвéÄîtv°ÍçÔy, }‹“Î)XØ ›ø“̺ Â~˜¦Å±“ìÈ8À+ìè•×-'µßÃ[žŒŸ-yÝ«º¥jçñKYv¡sÍKuN»±j{‡û-,Éä@ƒµbK lË›¬ Îߢå’o¬áªÃ¬Ž0í²8†…ý” Kðí{ˆ8Êâs.C$cÓÈh¡·Éù¨¾ûÂjojãÎîŒc¼W¥;ìEPtÁ“š1hTìƒEò#ò‘´Lª°“?´­CSȸ-,'F¾d ”³ã;¿P4ÊZ“ÚÅ‘Êwçõ»öôKè78‹n…Å"W=p÷A3”¬J¡ü®«g^9Ù }‹Yš EwòžœèqnáŒÙºEymí»«O"Ú9—ڧ;O(^àÂf^ÒqnÐA3¯ñ¶{âëX:¼VÜsìÚ8ö¯Ð?}ÀIn]¼À‡ó‘¦} ¼¡‰ÝŒ¦ÑÒn–±NLžœI;V—h-á‹z¡u⊮G7£—Z^íuqz"Àôˆÿ·öÎ6 Ÿø^E¿ðá`ðß³Fït²À-u“qëhØJ¯Ú ‚‘\ÎÎE«¡pƒ+Ž‘uiqäKá\´‘HqÅå³ 8gBêà"ÛõQÙÙ2µªñß̦ŸWP`rË»-ñFF;éT8rDn^ÒdôÅ^£6»¯ºGˆ9ø„`šDm†¿¢Í—bS´)7BKnÚƒËÞèdF>ÁÞ'ÇSD§À › Q¸³íÓŠ:õä¼l¼gPý†×}X Þ×ó#«…XyÑ~¯4Zdš|çÿ1’Óíœr*³@²¢UõÖà+›+ˆHKÃÝ£Q­ðsI%º÷ªåÑ×:Xér½â:Ÿá‹–py.*sÔ˜Ú³b2DŸq=”êóaŒmŸ*Õ8}aËÅ Ð"ÃO#|…”m £Ê‰ä{šqíRxÖ “°ë /Š'æ–}Üã‰ËBñM|aGªï¾Š ÏJ‘Xón’wWó)WÊ6Bƒ;î@âÇ&ÊtìoÒo†ÍNç9A 鲤 Jçrž1*„šJ9»%Üöšˆ¿á¨‹Ü¦ïxZÊÎW$“(ƒih˜iŸ“{ºåΔ‹%¡ñÏDÕU ë®å;Îz [š=ïÇŸFñrw:Oð1§6O÷éT£nÄÂ!:Vå¬gŽjQ’y[³H¢Ý©aÕ*”ãþ€ l 3…Xµã¦¨´´$ÒDªÇ7%Ã`^4?¦@ ŽÂí¸:,4ù§‚ß|,ºˆiÇ­’ÀjíØÅËFAÚ&zÄ>s|7*¾ïÁr•ˆp2š‚;Äæh*r ÎÔ>|`£ÍfÒ«÷»°™:\´|ö ³û¤SVYf°¶4(öÎ æÕ’(K5UxZ"QlX8!¡w)¦ÐYÈ‘“sì*†@ìÂìeM+J.Â&v‚ýbzK<€¬î„šz!ämárZM¸“¡FSœV2þ>V¨áñ×ßJf駘w,Ø‘ë$•' ìÉ{œ²‡ß°H"þ˜ô÷N"I 0”ïp…Þ¥BKf_eÀØI]Š ô$`“œ¸~3Ú¦#)=Nਉã'À^‹Õ679 f€â°xð%ǟ‚ §`f îX¥1Dº†¿Ž˜«ÏËŒÛáb¶f!L¹Ì€ç)ºÅœÛ &? vô ¦pÖ.&-4ÓÉÆD¨oaBÖgy!Í`ÈïØÕRˆÃ·ØEŒ–N0¼‹Ö½áV&úöÝeþ3ø ‹1ŒÈ &Ûõg¬Ñø ƒ–&!@SŠìÄç|ìfñu’ÇùÌS²³ a¯nƒÛá[ÝæÛQ¸‚å45@ï+SZOÐ\ÎÓFª.¹Ûd}È–5h }E¦RIÑYÇoGÎö¼gmôFŸ¾>acË{Eôô¶Ô,NlQ§ž¬ÄuÑvýLKoJh¨ì®h;– Ò¬Uþ×8J¨e‡çTƒ—$,µ4a/@‘Ýëöø¶M¼pk,à T†YÉ\¸,‡ÅCq‰ÊJ`ïoF vÕÊdðH¸…J-: ^kŸÁ®ÐÒ#'|ˆ¢21ÇL¦&U9¦¦¯‹Fjð‘3øŸ¥|A9Å{4þ<ǰ[ÙÁÑìReª×Dù˜aU§ÙjíuÜE«˜“ð[…X~)é÷sC̃øÑ—Å%!¼’€žUɦò(NÕ9Å€Ö´u,gO±WUy 9vMJº7iàJÒ/_¾{ižfGb/ˆsÊâ[x¼â6^gÅ«@xÞ%)š„9¤ÙùþT¦¤"d‘ž1É–f#›m*KÀ¢tf´x ¯Z¤¥—CRA™…È+Lãá0ð†´Â!‘cÉp•lÂõ+°`r0¹ž:?ò®‹;–Io©K©·wìZð¯?ïÂHTyµ6_†¹(*N.qË•pCëÇóÍ7|6@å¬Á«í¸·ÛQ xžqëë6ñ-„IÇ?T—¬ú6r^“ü©Ðk;v¾:<Í bô{铤ʊÄêM¨ –ç-K5}˜”dZ’ô¾ÄF±)¤êñ+-† ÿãœÁ¯jHlývPËûUûEèæwg䂉£{¥¸}R§x‡bcÖ0ÃKÃ÷J,oùõ·¥;XÃJ޹ÞîxI<>`Âüýü‚ ET‘R•òY+õn]ØKÕÆcÅo8|z=øô†©G¯$ T¯&ö³%{­€*^ª…y¤ò3cY”K†O«÷P€ìôÜ?›jyÈ.©úwÂU’<0ügôíZ‹ò¯Õ-èrþ(ñ/9E©µRocèµ²ŸÞ@_¯<ô·f,jÌÆïã)uAq–±Ê(‘©{2;÷|³·$ʼnŠZr€!Þéj5ÅKQ³µèo9X}g¨¹ f¢@ìðá­Šˆ/-Ë#àb‘‡îÜP.ùˆXéÓ¤Ë=¦i(ÝÓº< A5÷¬e)#¿ãçM¸ã  R»Ô¦¬‹cªf½ª&¬m×PâüÔ•XzP$½0WÕUF¾.¢–ï/Wì`¬•gtt<Ÿ!ÓèÊ»Ë]¥.vyÞ¯ ‰…Æi'zì$×qjíõ÷†Y~R”-?­iÚ. ¸œ„EÓ^åƒ@>áóàsÕ <™zÉ«nfAN…&«ò³#Ÿ|ØóI%¯„ÛáV¨ÛjWùz…ʰ¶x»ó®2ÆÆ+iŽF_ãª{YT×¼¤è–Õ•“”« WF >õI_OªÄÐK˜»— _ó:8do¨šÅRîÞ·Ù f™;lšiÜÞë*÷Å_âéë¤L^‹ ­/½èûrt50ך¿i’h9¬(:×…ö’N·kR| láŶÇ\ÿÂÊÙÌif_Jð©âÿÊtAÁ\Àm$|øÝ(énć‹ÒRÜÊÖ¨Ô³å%FW")Þ>ÆŸB¹Â4Éš«:í”VÞšÐó%æ)ô*ܺäEIpRê°©}DÀSôó£U|ù+0÷¿á›o8ϗ̸ °R“,Yk™ä­"ƧBêë!ÜBK´Í²G Ç“Áºú@¹§%öõ¶âR»«³ªxŠX¨\²¦æ†¶g%ÇW8ì†ZÏTµÕób3cˆ5™„“ŽŠ=¨UE¤ÓnmQË.½aë ÝؘÏ}ÍñJîhæZüƾ(NÁ ãÝç­åN&qGÎÌ>­ÛU £g@^ÝSfµ +Ï\Õ°ËÖÕV–k¬8öórö—)¹ÜBÈNòe£¹/Brrƒ€ãY³*fùƒâdà[:÷‹“«×k"^.qú ˱Ýz}©D•]e©)VåÀóúûó²œAñƒV•Ê;Éüm‹;íô}9'„ž ”Ç{кÃ6e‘)&¾˜õ¤ä ª|»NQwQ¤™¹¿LTÜ„â2³méôu™£@¸”׋Z´¢¸RžcHøPÈ ìZªa¦ 6áQô„¢›ß†4¿Šhas¯K%nr—æÞHP×ÕŸ‹|Ñ@Ýê_ D•åõ¡cåI\ÂTIªŸ>LB£; ')ì\¬ü½H·'츘p‡¦½WlÄ7‹˜-Hö; Œ¾ŠÆÿNY’u)²û\S&,ÕÉÀHÒoÝdkLõ¶8}O0·—o1¸`ÜŠ²…÷èUìe]X.øíÚç)@\ _ô³Gü-w\®šÒj{´ÚjàzGü\}D$K¥^nb#KZn³tÉ+¦¹a œ¦Ý¿)¦÷&îg×¾TS*‘šç‡äF}¯SÒ 5È77 ÑhZQ)þàµI»TMýMÍÔCc¿%»ˆ~s3¡Êv—¿öõ•‹.uç> stream xœ¥\YoÇÎ3-ä7,ü´hGÓÇ\ ¶e[O™Øy H…T,‘²$Ú–óçÓuvuÏÌr­À µ;;ÓGuuÕW_UÏO›¶q›þãÏ_œ¹Ø§BúB„Q´Ðœó#5·þínß§›¼§)—‚Úóœ÷¡m7M4õ«ôÈö,Mä5ÍmJͰtañ–Ùª…~ˆ:ò•7¶©Ý^õz˜¨%| nT--ž‚¶“FŸaÛO¬Í;ÍÖí[é'b+iºr?Œ‰ô‚thlÆQt(ßnb#z[(¶ ©4Š¢Å0ŠÅ"¦=3‚YEgÀ¿~¢6÷QeÖÕÒÒ/_Á„Aiâ¢ö¼Ì ©VêȲ÷¢98OÔœniº`Ôà`ËœºñÚpûNö%dèõ9(KDé˜G2óh&oóíïi*3²9¸º¨¨9ÆŒTËöR;ü-ô͸eƒ>Æ ‹èØ8eëïš0¸±çV’es!º^ Z„'Æ žjr,R²I4 ÖpÞ1Œ¶¥Ñgõz•½z^ÖscoD4" 6q'»&L-Û|¹ïÊØUQ΋Z£YiÀ—…~ âˆYôùÙ_²b“8MG¬ž¬{ÓÌd%{DØÕÖlôN:‰m@žóÒÂåçp™0{6iÆ´HîY.ù>ÝLÍFôh°Ì¤4Т°£{âÛŸÒúA[µrÅÖ£'a½ŠŽ¾®êšS¸ƒ]&y– }$ëÓ££Žbà6Ìn çH·ÒHÕ Ò¦ -uF~šÖLØ¢~áräõÃ!ƒLT§=x6†ˆ¡}ÖT W2unv¯/vˆuƒ«@G÷®§Ê=°báÜK£öD—ì5õŠÓ((ÝÛÊû©Xcû(Ý6[c˜š½ˆ—–‹w‘QýÒC~$Ør¦ [µÑßêÝ„ŒYñ¼¡öá™nô4¹ò#Íæ‹%Çø¥†"ï¢ýÁBÿ‡°ô¹œÒ¬A/ÎãÌáƒÑB$j¡ëšÐ‹²µ÷¨0N =­¸J8”ÓÆ¶Ý.)i‰‡@›R—™%ôhO§„æÙaåGŒ"„üqî¨ °(lM¼4oGD än¶¡ ]ŽIJ=˜ÛLKÀ‘+_ª³Œô´ ö¸‚OÐFý:‘¢Í=ÏûE¹·B"4¤!AÿÌ7‚~ÆÆ•¶øäðþ˜dCè~qÄÖ¨±1åõ~DG–Ÿ56Õ~DôÁDÖ“'C±M¼<Éj\-X©ëlTöš<¤±Mhl ?Ýe];£ø¾=‚ü/9^[ˆH·hF+˜šNÈÉͬOèi8Ò¸£«œÏÉÖ„C @»cC¾.¢-€ñDÎ톇ڷˆ¯`TØèKÙ'ðøù'Ö C…y¤ÑjZÊØ$ÖwRkTµ: GÅˉהõÈV ¥ÑLÉb„Ï×›ã¡QY?¡žñøÓV:hg(ä©èI…ƬÆðÄgÖȰ/"æ[FÊ^äv(‚ŽF»n€H Æ=˜§h{Å nÄ0N&4G¸µ'›¼¤*²8×:ˆ:I¨ž‘• +éñÒº“žÀ(g60ÒXŠœ¦DºDŽ:6ålœT…8U›g;"ŒH½d19Ì÷Š•ì*… H9Z2oz+ùû OáxWŒ)†¨ 5=S=Ÿb­xEL€ñoÙi­Ã§ ŠÍ—ò¬ä|yI¶pžônmŠ˜cXªT(BS®0°ûâN&uŽºØ’N¡Å¯$æÀ£W¸¨[ì– Thú˜©±åDõ’Z±ÐU­|8^­R¡Ÿä§ å3¸5´òwi¡U쳘JÓÇè0zëF­Zvl˜pÞum¸á@QÇᨺFä<»YÀ¶/éÒnÉ’cÞ "\LW6Š-øvºé(ÏNìnEõSvÓ˜* µÎ–~±=˜21 $ŽqÊLÜ2ß¼¦Ã™!7\dœLzÃÂÎkB|%ì½ÂLMǨkšç¢Æè*à^3“{_ àxƥʉ‚(lªƒÌÅ!µ\iCR3ã§ ¬GJbjÝ¡·R19´¼d•ÿY”„­eޱ4Qdù‰Ûî‘?×*só펓» ˆ1†Í Vĸ–%PptƒÁ‘™>Î2UÜ_«ôš¤çÖ `4 aœ¥Ê%Ò‘Ly×’þ…5ãÁãq“LRŠ”=ÕÛÑü’Um&­·s;×tCLÖ;Чn€ç›ÎµÓ°õi´]"´ß6£o}‡Á¤Oíz”~Ú‘Í?õb×6nhÝ0˜‹¿ÁÄÇr géb²r¡ã§¨37Þèˆ$ ¨è·Ô£ë£yæ†S¸Åèe8ö‰H0zCƒÝ¹7zþµõÈQ´MHòq©J1¤ITŠç(1·2°¬8oª‚¯‰KÖðßÉÙ8±—lâU”ÄL&ät{{AK+‰4g™Ú¥evrTŽ©ëa¾/¬Pë{ËðdÿLû`ªïì¾}Ÿ5´¶Ÿ•¾ Ý¢ÃË É¶Â 0ƒË?]­Þ/¨ÊUe)†BÇ%ô†Ú1®åu…WެàS0ÔÄx´r:cÌuP¤ÃÒ’•î0'‘©š[{¦Òr1Q2gÁ™œ\z‡ó¿¤suÐ|)ŒñQ`®pTÌ)ع`jÌ4Šš0Æä«ƒ}ÎzØ&K`õ°uœVé†'êùÔB´ÅSV”Ù9¡<㪎kS†çEN–Ǧèò²`¿m´÷U•áBýëÊ£.ŠÉB§Þî“vþǚ™;XbÿNP’ðby«ôRÃ"† ªz˜ºœTfíöW®z“¤ÿÁ…-ñúêF-4n»…D2–”w•¬"…)ˆ ^¢©6¸£~5Ξ*"ÎÆ9¬‘θ]¶°ž ¿y\•¾Ùw\ã¥!Ó;‚){b«…B†~cªíöœ.¶ÞC“4|æ²Ît(+l?ÆÑè:5{#±þµæ° >Ç÷EÕHÿ¥m¶÷½«uúxðWdpÉ}¶o j»ÑÚ…%ý”’RU"F'²¨wÁsœØ4-¢:&0¾Ssêtš¤Õ ~—S% ÌÏò˜vZ!X†¢û ºd ò›Â-=fv!žk¯ªf%˜5OµWTš7 ë’"?²P{ƒG¸Æ–êÒýY¤Êe0ŃÈœ³ r{ââx›¨¶åᅳذ41Ó1á'˜jǪø´LöYGY•"ò‹>T…Ð û€óÈüTÐúißUžE Û",ιž#¥!73ŒHÝ‚§|sÁä ·²P†E A‡©F¼`ÊqL]ã&m¼&±zM‚kJÁ+)öaûþV W‘–°噟Áÿ`œ°„˜™#¿ºœ†½‡ï{¾ˆE8ŠÃö1žÎ!’z?ëôLà2»ø4_ rqñ­#Î5{toI~):Š…g5?p°2W¦)“^†gÒ`WÄoõh‚`éòèoó‚ÇG9Ãm÷N1°ü*‚‘¬‚ò•ÂfQ™9Ã,µAÃRÙ ëY¤úÔŒXRp¢&<ìWÞyA|ö¡E&ò(ë«R(™qëTG*&(cÚO Ž0=Ї`Xu}‰Kñ.›ã‰ìH'Üg†|4Þà-ˆÜû`‘;¾ëg ”T¢ºDYlãgC¨Î)Ç*§SÅ䤌£­Lìîùêž^øå“¿_¡:ZzÔ¬*蘧Œöò68º’»Ê'=¹Ð3´1†´jZ§v+«iÉŒ½R¢Žœ©0l·$ÝÁ%Ði`†ÐnNùɘJÚÕ‚9R[ÕeÍ…2U^üpà ÙÉœø“é_›‹t÷äsZðw„¢zð8d‡¥h®É ÛF3.1YÉ‹a¡`¬.31Áð ÕÖäCèp°Êužƒ]l6ž‡§§Ù6òï¶×Zru<ïaîr­É│r :8-G±í/QB»e(¼á—o0÷|•E±J6 6¸F*Ò¹výWedy¿@§OO¾9ùi“‚ò_Þ–Lÿ¸‰x{ÜLiõ⯂ûðÑɃG_lÞ¼º}zòà»;yðüïï?Jÿ<úx󇓇6ßüÎ×ÄÅdÄãj>ÆÖÑ«âxßÂp [WõÈœÎd ëõ•–ž¶¯l©Žz ˆŽfµ'Ê¥N.Ú‚BóÆ•"£lSÑÓ òd‘>,©|XGЉÏEßEUS~ºøEÙÒ¡ónå›aÈÈv^Ž.ª¨y\¥’.ÍŽœn}‡ÏmT<ë`¿°Ë„å±äHȰi¤FOï\–æL£Å¸ýn' ïjº“¥þ“ºB2Ï‚ZÜaßœüœf-endstream endobj 930 0 obj 5521 endobj 934 0 obj <> stream xœµ\[sÇqÎ3¬òoÀKªÎ¦x–;—½Ù•Ë¡¦¬Ä’èrU¬<€E²D¼A2ýë=}žÙYàˆ ‹Eçìm.=_ýuϾ=zw>À?þýìêìá7óù‹÷gÃù‹³·gžó¯gWç_>I'—¾é×auçO¾?£+ÝùìÏçûÁŸ?¹:ûÛÁuã!¤ÿ}ç—ÁõƒÿÓãáÏÝÑžÀ_ᯯº@üow¿ë–µ_W·š3ðªÿîŽÁMýºL‡o»ãD‡¿éŽ®¾ä\òÇ.ôÃàÜÀ¥ƒK\é\ûOþ+õÅyÛ—8º~ZRwž\ræôìF8ùÈGaèg·®tÒßááK:k¢³=9ûúìíyý„sŒýr¾¬®Ëù<„î†ùËÇguþáÝíó³‡=wgÿ~|ùçß§_ÿãü_Î=>ÿzw Êfˬ¾ŸÂŠÏéMCjÕ!¦A cê8ü^‡þ/i^Þ§1 ‘‹‡ŸàÀ«ô݇4/ù‚eÆ)„é;¦¯ŸÂˆÓ9éºçò&{“>¦OÃ<žwñðfð"}ÿA†®¹†‹_À…súrgË”|„!4Ÿõ:¸ÛUj,|ŸfÜœòZH-г_ÂàsÞs8oÆó¾O҉ж½Ç¥Æ‡‘ Œ»MÇžv¾=µÖ\“z½¹÷ëÐ/‹ûù©ó ™äÒD?d8Ò¼Ç1 ð÷„§½îà+XIpƒÔI˜Éyö02Ј"M$ž‚÷Àë¨e=42?ì§Ç$uæp«x<&C}‹ÓáR£ùçúÑŸ]èÇ –9ôQÆeq ø¥ÌŒ9¶ˆäÒÄ¿f‚&$‹äÁ( ô¸”¿Í×f p4±h–æpsjÔáYj<Þ<à©5V8ŠÖ gâÍ ‰ðí%O£“p©¿‘ áp^4dpb 8¡vU#ýMç }¦`—qÂŒuLË÷ɟΞüÛß1Ãá!üx?nàt„FõüÛ®´[èP\lï>ùKºNŒÿHƒÚ*Gñ¼÷ú㹞ìuñµÐ‰XÂöu\®¨…jæ0-j˜i|â2ÊÚ•KÈS]óN]q*C.óa™c¹ïa$fD¶rèéÔt¬½ž—-xÄœ Ù`þAKæQ>3¤3§Çæ†íLW›+Ñóx8“ßSiG¦ÞGÁ6?êý¼…ÁƒÜåcWá$¬åA€’>CµýM†‘ Å„bƒ ¿pð\€Ü<ƒ'ÔaÄ4{Â^ž`ï‡4àÓÙDº&ñSSƹñDðÀRÒç–ÛÊNB{lÎ-q-¸ÌÕ‚®3jè€+/-ögW¨ qÄžáÝÌ`ï:Q—ú*M3 ú̓þ-žš.EKøí&õNU¿`–ÙþÃH$F2¤—Òÿ…¯FÅš4Bª£E>S+Fç)÷`@oø˜¦Ý ÐQúQ:¢WÌgV2E!œå<›`64з•L ž•\”Möq°o2´€Ï‰n¡yIÇÈzöôðœ÷c|6)¸ÊÏmÂ'³Ÿ‚'™9Q¦ ÎF tzúЉÂ8ÌÅðñó97dÁÑ„µ+¦-¡Ÿ'± ð¤%=JÍ$’XùÎÅð Ì$ÌŒfX)8EX¼4&õ ¦ì»CÕz øM#‰àPš&‚ÍÚf3[²µ¼(V7 Ç¥( ÂÈ@\ºÕ¤–Ôë!O‡¾{'Sý‚,ÌcÁy–ÀìÃÿï:øÎ7àdZpº”é¨a˜’»8’‡AA#¼áF(7¿R ÃvÿlÛèì66ñ;ˆmº—~óyß3Å´vÅÔ6D†“SÌ/½Ÿ>¯Ó«øE†ÑU7gÈÂn—ˆ¥·WºŒ09¡ EŠE Gò†¨Ú ~ϤÐî×/• ˜Y/üñI:gÑ• ·‰QS̱>ê~ZüXP"iø–%Ÿ™}\+<ƒ1€¿ê.™ ܈Gù´jÕÍÕ·û-,!»íšËÔÞt6<’±A^bm*›E‚ û)O½±|ÙÙá¢mã’Ær™Q‚tÙµLÆ¢4¼+ŠÊÈyQà–‚GèÛ£˜Õ­`ÀkÆ$ä)щFùˆ–Š<í5v°í ÓQëµ1Zrú»|ªÆ¡í2ö#°™]fÏé0< °©’œµÜ¥ŒYÎÐPÈÎ ò¯êi2ƒS §Š-Ø{Öó\Œ\—èöVqóvk-{ FÜü£[{¶–íÆ•Œã¯]5)™iò¾ÄX¶A\˜×<±Veª…aAÝ …–Ê »S=‡qÁ@Xë‘âiäɳʃCÝ),¾xqÔƒJ’tÿßuî:¹,(>‚sg¼T•BGªa§°¦TiUx1‘Õ¸`U6‹„a¹“4ã<ÀðäÙýu>=ÃÅ«Îóßhp4¦vC"nǠإ̚6…ÄQêMÉ•6‘Œ šÀRtf(ú@›{`ûŽ`$²Òpí³úUC`ÎÄg…°õŒ|Û ¢sØ£gç‰dqäÀöh¶¹0‘W£.š[}opáB§âÔ)ñ\˜˜³Ån|z¶TR×Ul Ëc\þï4PðLÖ®C7e§20ƒ$È_ÑKr7é±éÕd¤xö`öj\LB3l̶^Œ< ¥T9`¢_‘ôK&°ÉYßd5'ìœ?Ï%‘ª59 ‹xiDàW'–5F¤÷AL$Lˆ6WÙ<㨒Až 1îõ’(÷ÀM½Î·,n\E1 óGXWWÒÖÔ¦’×Ç=úå×ä?–’~×Ìûª5(#Ï$T ‡ÆÙÕ‰EÞ¶œÞj¦:†£‚Âg9cD%!»I¨ôsŒ]æä³ó¤^—øwŸ°£ÊµH:sþ ÒnZ8V*YóFÿ•ŠUÊÄÏ¿"n ñe^þâ€" æ>•Nú)#T9¢£]ÍMLæ Žü:ßO$uÏ-ƒ»M‡†fQÊ-—`ƒ=¸²²ç)¢›}ÜÁÁ¶Vù÷ ºàÑ[Ç‚¤o±bRíµ‘8˶?îÇ Öè¸ã%¬Ù`Ëss†àVÚ¹(î7%Ä1Ùõëh»ÒcÑýþЗ¡þ×\–  g¹—v{#˜¸®‡¦ áרòº,O¿’«WèΛõýú’1(å¡åsª8å5AX"aStÖ¢ÒA˜ù„9ô#³Nƒâ…½Aƒ$WAA‹Ý#†½¥Ëe|*{$™bÙÛ@«« ]d™öôѬcÓÈRý¨$2ª­  ÷.çŒ! Èé‘6´<8›H”•ê])êZææ‰:©á!—dµ¢—䪤×5“q¸‡»›ãñR²éíʽ)‰]Åù‹|"&-'„àSd *sVHerÍøl=<Žê W6r’gj R‰f&)X`ð ›gâç‚‚ÿ†æ¥Ûç„–½ñ€…Å žu«{ÅûJZa)û\l³T!xõÊWä¤VöJЬæ&’Oë.¼ú4UÁׄcA]TîÆîø›î£»8¿¤pTžñ•àj øVvÑ(–P%¯ =mÈhxz^¬Èõ°Ü46—Tñc¢!-1K´ël»có4ï³bS°Sù âÙ°Á¶­4ºYmªb [·`fé‘ ËD‚+!ã§5íçÇa¼RFÉpõš’Qá*PˆQ·†Lfä“0à|KÖ@Uå2cñÈXMJp°DŠJ+I#µb£$MkY7ò JÒ´n3¿"}°±yÈ?F’ÑZ%óPU·têË$^•|Ìí(ÉíLNêN2ŒEKríu I'k,kœŠM\=$÷‡Œ/¶90@ êhu(Ä81ªóšÊØiʰ½)¼âTËužY!O¼±§[ð¿ÉyÃ:ɯþ“¦ÃNô­\½‰äÉ^é¾—™~‚åûj%Š<~k,|ý bNº%å^˜KÊ¥Õ#.:MJ7Äo@¾AÚ'!}%9av|é·‰>ÍÞÒÝ(Q7÷!KG/©m¸×fKÁ–So,=6)ý íŠ;¹síØê¢ÛäÁ ¾ Ó ê#Ø;ìa,Y©d‰’ûTú=IR¶aA oM6"gæ¦#ȉY±—ÊË­$WÞgÄŽ&ÒL}ƒIQMWÒÈjÆA* à¢ÛJs¹–Û»]d$CÂÆ›LG,ë6)ä"kIg/EAŽßáâ‚]WI¥è šïTYeJƒß…-6Æ:`‚¼Œª­¢‹‹Ù| ÛxߪAÁ—–Ôó ŠÿÑÏÁ ºçä¸d›­³÷Éçh‰XÖ$€«¢¦ÏnèÄÚ|üXÇÑjNætTà§ßc+ÚúBZHøBÈp=£~ûVÞ˜|WèƒV„.çÀá–uSh.ªöЗ¿…Uû2E–Í@Ü*xϬhÿ¨`ctN14M`~”‘Þ€o ¿í*]zlz:öfØ÷R$ ŽXÔö™,¢”°(j41{Dˆ|y–I¬›‘ïT4\³TdZ,¼v5e.nñ¦~TS|¨ÈLÓg¢)ã3ZYX(¢( :‰l‘b“†'çüÍíÅK ƒJÜ'Qý:u«°ì¨Øs mWãš X´œˆÜ4(ÌWEwºÌµ#¹…†@Ί uµ„)k«É-‰¬&&º.év¥Ì;Ù’7J”ÒžRI¨.ŸL5+™‚ìmfß—+l§RÒS-á$ÏSCc¶ÄÂÔýUqLÈ…B<ï#ÛMºJÇEQ?†*¾æ[ÿ`™ÓT²l\h‹þèT¸ŸÕàÆ&._!šPaG*”ËöÎxO9„zw•ëòXí•ëÊò‰H„³š3Y¬ùB‚d¶#Pc&²,X*‘ éI…R´ºé!…¸â"º³“ ¬Z˜zÉ"ËÆ·rãb‚4 Ÿ|,Ê‚rƒv¬JB¨H@ò^4ò]X2ôzJ½>Bp‚'¥í4õ–‡©.@’Ÿ!Grªé-¥£K>z+òŠÌcZSyAîs[V[5m±…o*]I[ÇØNÆrµ—Ö¸ñÎ%šBCPm½Ý®NvÑ-~ìFÔi°ä›F&r¶y’  Ç£Û #S¬Í—ýÄ_õAëyM ¶¥Š< ¶.„#áYçB‘Œ+Éui-xÊpÒ8|èE©ì‰:XUºÄ7vvr²F¿«ƒ| Z_ªä8*H3¶ªUkNIU•Zj2·j,íò¹ØL2àáì2Öþó¢³›š[ÚÛ]4£|Oc&¨'B?ö±±©À°ÀX6È.‹‰¹ª6´S’Y’0T¼Å™M™î]Å'Ætïª à;4Jz±Û[öR(Ów¨²Ø›\IK:`¢ºx»km$Øag'7àÊŽR“jÎ.œÇ.¢qõ‡se%VWÚ°Z/g0 ^ïunlË:™ÈÍÖQw°L½¼©-Ùô¸ÄëÉ2âýªÊ¶L2KKüÙS®U)l-ò8¬ÈÏСMÞ Z‹˜‘û\Zš¨N‹qHâ¾× µrÄàf¿^S½Þ>IÜuiH6…D"U+Ô©£_–íf‘¨Š‡ u¤«I:F£$©üC_¦)<sº·>ºº5J›¯æ¢mäO‘Û磊³«£Îg÷yÄ{v¬`Xï §«Ôiõ}\ü¹ÙÆ]o)òù*u\rT}Ý Fh|¡=9}„[ ûÖ*liSð–Ñâ÷¶ä¥.=À’5°¶½„MQáÌ}-ùD³Îì)É0N?#LÞ:v>C:ž‰‡;ømp㆛ù©;öRt\ª<É÷Z,{¦ÙM6Å¢"qŸÃ¬K±3çDH^ݶïgó¿:â%Ðdÿù\>a˜ƒçôqú™¼$ +ñ’ÏÜHÇ—˜FÞ“…ˉVÚ²„õ¡Ì K]Ñe†ouVêþÕ Ò=$D ßÀøéÕ÷aL¶+ ÞÈŽ‚¾~Žyƒ¡˜;^QB¾)ºݹ;yªºÈKº)nÜŒ™ A¬¹‚ëÜŠÒ©ñ”§Ñ>DW¤}eõkE›aCåšê’:cT%ÎBk[xñÊ>̽°CJØB.a“ú—4y¿—È$䡜3–²yÊÀ aCh=¥¾£¹uðôÌEh›À]‰TÛq;¶÷¾„‹Çeón² Â_Ö£º-Î~ѶØ@Û糤¬5j'¾5†÷üÝ›&p:˜¦¾Ý‘†q§ÅʲÓMáFÆ÷+Uø ¶P䥵õk'E…Þ©\1OÙ­ëTlÄmž”ˆ¥$œM÷•IÑjC@i¤Äë@ïÜ7MaÝÃ&/ÒR\“÷=Ô›¾–ÁbѨµnÕÞ%±…¼Åh+><`öáªwfñKH Þh•Aa»Ó²ÝÄ©5¶r)x-7¿48%½™Ú,xZËRÜz4tç›”¹}T#ÛÑñ5ƒ«ìšª(ý«NæßÄsô.Áêõ¶‚DaZ9ÓÎÐV¥Â() ÞTPD¼Õ;>*;ÜDv8 ¥‘m@aTž€¤û„wGèKœO}}öO«.5Žendstream endobj 935 0 obj 5911 endobj 939 0 obj <> stream xœ½\Ys$E’ÞgñôFÕJ2޼öa``¦1ØáÐڬͰf£>aQ«›>Ø_¿ág¸Gf–$ÆÀ°FRUf„GÄ~|î?ž÷]8ïá?þùèùÙ‡_OçÏ^ŸõçÏÎ~< øå9ÿxôüü£Ëò@ˆå“né—p~ùôŒÞ çS<ŸRîúx~ùüìï‡pSù7‡ÿ¹ü¬¼•‚}+æÐ¥X^¼|\þøx‘>†nYæ¼þpŒ‡/ñp Ÿr¼/¾>^¤º¾Ÿ°ýTþuåÛ—òÀá/ð´¼—Ê'cùðüýÅ1B óHþ­,2Çaì-4ñ䘯ŽÃáªt¼(?Ëq‘$ú>{ }½Á¡†pø¾HsC½g’Ú¨_ë{–wÊÃÚÁQ¼„ßùÙ4 Ârø©,$>øX:Ävahcf4.© £€æyùšçG3`û€!þQš‚Ï–æpéð¿õÒ>¯ë#ýíMùzN¸ Ú TŸ½9Â,&uÝÒcYýÃûÔRÁìáŸÇ8ãZ\ÓÜ•çÒáø–{Á~žÂœÀ$,2i«4Z¦v™ e©g´±.xR.Bê†vÌ ¼‰^^OÓ‚küOX4€@—åYyj$1WØJs_Äïƒ×4°4ij³ßU B£Ž æ)á‰1vµ‚ŒÞ¬"c³B¦, ~½Â¿2q¹ŸPLlèuÕ V¨Ù4#{'M} óöfÀ7¡?„'cæ8õ¹Kaà½àGhtFøOhâ`Q+,è‰:\^š€¥GÞÖå~§á­Oߤ »ÿÓoµ/Óø ?ï`›•Uœe¥bl ý“ê<ý á%cG| ËLS`ÕRJ¤lÊôRg?ËN~~L€i¹àÒ (D؇åÙ¿ÀgÐß\ÛôJ¤àœ>ÆñꎨiÃÒÜ~vùï? 'ôéÒdœm»™µW²áasU +Ö Œ|h±†cÍzÃ`¤9}!{OôâîuÀć U–ÿ’÷pIŸýAÍ#(|2eS&õ 3šM· .0éQ·Îc7Îq³7ö†ôl¬ncÅŒ½¦&ßêÆŠÌ-Í oƒþYfóá{ÔXܪ£[}¬»¥>+8Áº’nâO¿«º÷c†}Ì.õú¦±"ï«æ¥)óšÕ¡(ØÒidQ˜ÞVà]³æx˜¸aËêË;Ï#káËFÛ>•H=Ø=•Áï°ˆzÁ’„»)-3ZÝ=0¡ªÍ±ë_~Åç j®5 ÅQŸcÂ-æ±¢ ­Ý‹ô¹4ˆÚ8 ]žƒ@õ)Žv­ñË ØÅ µ»EÅaƒÉ#oØÆß óR4c€&‘Œ¶w>Ä£|^aëõ}ý­5ä ’êÇæåqzÍûRÀ’«ÒQ3žÑðz /2ƒ¯º^òèWQƒ½‹4Ì8‹ïŠºº ¬í½§Áß}UQ´~¾ &sº“iêÜ@óÂÍó³"㨟»iT±e)-¸MÞ€S¦-Ë– ÇhFèµó„=h¥Í®Ђ©0¹}´ÚþFÍX“”r@k½ûêµS‹<ÇEX6á4P¯¨!´ÚÅ “gÅŸÉÖ¿€Vjb °"¹€ˆÂ+ræŒÿƒ.G®ð‹Q=kuœËÇ–zÈtè#Œ<†Øš®ÕÇì€+0’êœztl,/HX}=£¾râ}ÄÎxâ¥ï ˜ªâ²°ÊQß(¿çÕTæ0 ìÈ `ÔÐï^T .T šÓ]ýõ©]e—\VÃö <± õ)´U·ÍÁ´˜ `pº!xp­Tß³ÆMÆê78fq¶e¶€¨Ö߃VmwkÅû ¤ —ûÚ6å«`£Š&ýV‡÷‰u$‚gU ôŠöDid8±{ËÞiy\Ä+[Ào‰6R_CÜtøë1×%‚wa¶Â° §ÑCBt絋‡@.= _àèe ,¢ÀïÉihÂ*E>OtÑÇ: Ðc±_ùƒ¤^˶˂l€„†½2B'DEöñ˜UsƸž°¡4OÎ2›9ÔL!öà+Úü¥µÆÊúîEW¡üAcyz‚5/ÎÁŽâe¸ˆ­xMd*âÍ·à2w+eGέþzMô™>sT‰Î`=£ ¸±µ#@@ë9‰mbð0ÔpÉ/z7Škßc3cÔ¬ï&UKVÝ¥H[ÆúâÚ¤¨ 0iñqˆöÿ®~hŒq VÁ®2tw ¨~Øp?aiáÁQÖwΛÚwô¤Ž¨öÄ(ÉØE)›qAƒgÔšr R~I€o²ÚüH2xð²wõZXFÝÕopÁE“ÅÆÅú}»•F Œ“YrÂ- å‘ßZ\Nö¥V:6tóìT˜Ó0!(®t.Lp‰¤ÚŠ—Ž·áÂåýtwt[À[cx~K8do ·˜à£š#/5½!N Q‰^WVÞñ{c€ì¡Ç—um‰Øfi`"•Ëq‡êcu±ã Bç: ÝÁÇ‚VA«íc5Á£F;7Œ±F)…=_\ e]ïŌְjNn[ê#ª‘p~0ôÛÆN‹¡¡:DQƒß3źVhäb÷–í§ÁWÃ\“G~ÁC÷jªÍX(=‚ô§ r?V'­ÔZ–UŽdµDÊ•¶-ÝÉ¡ŠsPä bªxMTðVjkˆ¬¾ˆcôq0ÑæjBe¾Ý [£mM@ETÝÔi± ò\v:Vm ÈöéÇ–­øaÍÓ '%¶ áC_Bc,ßY©£!ù9SSgº«Ë_3n23­'o=d·]¨_$¿ha³7 ì²êB ?'f¢e ‰}š‡åáDW>@2¤ª„¶__}¤¾§mj¤¡²Å.ÿö Ðz¨ŠÆØÏ¨oZBfåSÇMsÙSˆõÑ1¶¦28Ÿ×?L̪ÜÕ„÷I[ø̱Kñ þ!" ‘9<\ t§…ý†Lt™Ô¡’8WÈÀœCX´o— 0ZorŸp–‹"£8/hkþ—íÛ£·¶,½×‰¢Ï9s#ÙÒfß¼®çÜ××¶p…ˆZöɹ/Kï­smÊ ÍÄ©ÉÔ¬¤g¨eÄkȱˆ6o\eG%W8KÒ¸:q>dĜ簲±†²€qÃÖ¯ï=1ªÊd~×¾– ÒEf”ÛÉ^ü¶B(Í”!4ºÐDµ^ËDÍÃŽ`óz<-€¼œDSner¬n]œyJ—9Âl¯àGµâkV¡šž) ù'^3¥lvìå-y~èä½úÀI"I×2Šsôî?B¨¼eúC¤×^Õ&ˆÿ…Òaœß¡&Þ*Fo8ˆHÝhSÇïÀ`7üVÈÐÉ4˜ØL@¡©…•(^„­Álå7Tú@˜¯QnÅŠç?¹<ûêìÇóDâ÷çuóy^ú p“§tö3T }ôàìÃ_œ¿yõöÉÙ‡=gþþ÷Ñ——þxþogŸ<8ÿêžÕDyÉ](š1·eÈTR$˜êš”â®°C_Öwüí…BèröÂ>ÜZõÊúMYv"6äí¨J×H4A {wì¡ï!}tž‡1ÃÏßjì¡À{‰¥Îü:ûò…iîâï _ O¦ÎÙ:·çbzuÿZžjE©`@:yNìqM^4붪¿i2%'BYÖ>†dH9×:˜ZÀC‚Væ¤{,ù"AßXè(¦îVå¦\@,“†³µ|ꪘØ;ŸŒÎñù*vš‘€ÈZ ä„ äf2C3غÒѺÒy"6ªºÎÖÉÃ䜞<ÒÓÿ`íŠéåѥ噦èjå$s¦Þ™ÉŽ“‘пÉbL æCóÞ Ž`M^ý$‘¨„»›µï—&°HiRäj2XKZHnò{¢Y•"­%ÔPÍM€dXF"AvRRH©µ³Ë7ÊÿÄòú‚á“VÐå™Ê:¼2*ÑSýÛ¡üöA™ >Æ»Tvظæ,jõ–´KOÅW-„²KyF-I¶7 «Z÷lM_ÖO±§ÿ†—ˆJûø•Œþ…À `#'’Êþªá}ažT€—øöñ–ž»K<•MÞ‘ž`…æúÙ†—œ+Œ]ÌÁÓXr$l†AwÑ·Ü-€arìHã÷’ýßæ¶ùd©¶àÅOcÎÓh–ÜêSþ³aºeÜÕ 4ñMÛR±œi‰W‹âUXFÝrëzä´.ãȹr§(ޱ(àƒVÈD‰VÈ;º?³"±±¡^}ä@ú}˜x÷ j° ,™v„+ûnê3î˜ÄÌ)5¾u0U©X|¢2¦3O'B*žŽSÈ£¹ÏÛ]q-™ Ö{~ª•*Ú²ÚL¯ªÆ”.g›DuÇÕ&‰ ù&amK¸ÔçX»ÌÝ«šÍ…Lü©}—'Wn¡¬h<±Q&ÌÏCo¹9±ŽÜW”»Ò. ¹ ÿ¿Ð¹W<êktæfÇlV(- ßJ½É“«oÀɉ][FG.…ä4é®î io„Ë©sżË/œ*z‡‘rùQ a„¸ØÚ'’çXâ©­D\K<¹—tÕ8žÔ€Ñodº²wS¶›È_kSOWÄÌn¦?oEYËZJ ‰4/ümJ\‚lèØ¦× B 9Ä.îVKòi³‚Xâ7ȸ…>cÛÈÇ/Ž¡„òÙ0i UÒò-,‡IÔ5AÅs`KKïÁ׫üæËjw\zÔ„JëïR\SÌñ5®)ÅeÁ ýg¥r›Ú¥—ÇíÀåImÑÌxÛ/ÞÖRDT<Q“«R«Õ+'µ®â_çpö>¸Òr;Na½a™¯6è×¶†+Wqj³¹Oäæ%Ñ(ñªÈnúÞ%i·ÈE óÙ l¬–E=Ïý³žŠµSïˆÖ¤7¼ê¬ñ rÚ½Ãgc¿“©NÖ’|JÖxšìÑ2{ ì — à{¶¸ôi.6†XgJô¼ð#¼ðVíê¨Y0Sšð~ °ë›&Oó>LÕ½´Õ{oš¾µ¶ä(q­Šì<³Qw²­î‘ }2OK虺`#âÆ‹ñe ëòÅ4,Ö—+Éê_T+@düK{”IÕç&ÂÉetÁr¥z™*«C>øhy§þ—‘ƒƒõ*iu8Âõj1+7vUÿg:.uêôNmæÄ¾®¯yYTÅŽŸB:"“‹¶YËEòOëµÌìÈ^§{.ÑqNØm¡l3uìï^;Pjv¥ çnž\:þº2"›^¿ìÌ4¯Ó°Žª¬$v>«¬ |dÌ›¤h(–Ü«.r+Ëí•ËF‘¶øl8š2Îúp~xTàTrïK:ÜÂg†^7SØ©YqßÕàE 1!EÛñ4LE³”F-4náæE¼ëJuÜ%§·UdsS§IdžÙ0{¡®w¯Ä%|4ÚLŠ{çVÓp a?ds°ðqžTýÀŒ¬+1žR:½õY yhÚTK2·+(Ñ1!ldß§É%–Ö[¾Sh}=¾6÷{}sæéDXÓjNYª‰:„©àüàŒ¦‰áê)Õi|Û]ÿÄ‘÷\vÃ+ £l¡+Ñæ±= •>~ì§JEbʼnõ‚¹ ´žtáέHñæk?Eyb+'Îã:¸z4¦mXŸ»“ÐÖ¨£¾ÞÙiXÄñ[ílžc-ª¬¾Ç4®ô9Y/Aþêè òrnlÓŒ¿³éެº«0$š¹F ó¸¯ M[2AÒa([—z] ÛâHÊîî7ÓTÖ2&¬Þæ L ìÎ1)rXG€išµ6¡ÒÒ;(Ô¤F¤…²þJ¢t“zÉ©˜þÌœÚh3Fêbq@ˆ¦q• 'XU×v7W·¦HØFO›'«8i)+‘‰ó6%ý±…ßU:ÐEë_Jñ­g…µ®²Æ Ækf` w8ÿ4¸J×ÿ«ÉÓt#I}ATäc¾´¤'22Iwsâ™o²ô¥{|Nf{d—æ` ´jüùÊbêùH™}‡úàc—'©Bº?à6g†‰,p©…ÅÙÔænQŸ¤D,Øh£«-ÔÒ[cØL²øC–ÙÖŠéÐw´woç£ÕÃO˜¡HwBVÛ–¨ü¦·C_Sº¬–Ý3·ê°¨Ÿa| ý’ÎázJ(+îul Ôþ†ÑLt…ñAOÀ(õ¬ÃÿåqUÑÀ¯!ך{ô„Bnmà¹âmç*  ö8³lŒkM­8…^‚ž[†\”Â…iOi!w‰ÁÚ™*öwÃp“r8í2ñFbh#Ù³.ÜX™ Wo*ôü×p¿SºMÍYŽ6ÌŠí¨ýs‰MÚH"ù˜K³ÉîßH©‡åaìøLœøMî/±ÙeÏ.¶½2QHcÌ×ÉÚ [Ï%g´«rØpeÕ ‰  d‡fÌùçÕáQŠóƒn¨—>£àk_ÆÍ a&¹ËÀÜõœ88MdÏ££r—ãÈJAìñÈÃìÉ?Ÿµ ¼‘ë0µÇ•0R•ÃU<÷H0¹3©äÉ¡)óç•_z”c7´MýP7ÃÍÑx?=n\1õŠÖ ·$‘m™§4†Ìñ·±zœ£Ørr|çu—¨cÈÓÅ'š3™«Zc‰ÚŠ™U™œÄ¼. ·~3ï8¡ñV¢PØ:ì•‘÷ ´rNP›+uè"í±KU_ÜǦÂ-kpî1C²ì™&·¦©ÇTÙ¯.ÚŠé.s˜!ûüíNSÓýt‰ë`Oºf'ÊŒçü{H<í:/qZojü^{0ǻؿ M2rRØÛIæôTuï ã¦1þ¦Õ³¡4ŸK7C7qùìz+—¡ï ¦ñw4÷à%YAA4Ýܼx5ß.¾3Þt!<£9¿—û¡e¯Ôþ¬®¾"¢|¦Sœ\7Ãî1¶«ex¢gÚS~z_Ùº(‘ò¤ZñÁ\Ïn1q¶/ðÝH6nâ[ôæC›§õÔ0yHXAÎ ï6ªúÜ2‹\)·T‰X Ñ–ù>†-㩵àõ$× gÍu™fNZ¯/ršK S²u‘[± ÃÐX6€>–#¾Ðªù½Ë4‰O¦Þ$>»ÕJtüv£fHJ»Ç&R29ÑUiú¨HJÓ²""uŠó ¡–IBV[l²rvq‡”3ÇT´{Êuþê2Ýþ¬Ýéê…ÝÛº˜Âú£P²KÕ‹aÿW«ÚdV ŒD“iïSÝ šG’lÔ†"ʵµeÿVæØw›Tf¢Ï4t[Å“MU½ÕÓŽRjéDfÒkŠK´‡ž{¿j¢@ÆúUfï$:áüë]$ŒY¶Îí:§Ü–¦ês¦5Zr}9ì•S¦ ÃòÝïÒ!š ¯´DÎZ¬©"»ê!“MÌ}½¤CÓß}{ŒØ},±U<È~È©ƒ |‘#T ¢®Z¨ÀLqâå"8s¹H£†¨4Lë5WÄ6·ÎP+œÇ0 KmÎ\ë?é<ŸjúÍc›¾†c¦ÜÔJï][ܜғZð˜X›ï–QŠË)ñ/xð>ÔÓ@º&ó+rÄÀ9~,OÞXÛ¦VÛ_HÍÝí.jsx#5W¹È¯Ã|¹éw‰N`ïVŸA5™[Èn)G^g2åzÌÓ61]ì×,·ßxã]ðâ†Nhn6¨SÑÆ€Æ<ú+Z¾öà•6¸áKñ½^ROÉ€––kÉÆ~}œávCæLP[«ßÎMýq·ð3d+gœëÕÁ‚×—O5·šá §‹½Í:[oÞ°çÛ£`Ù¸öjÕ³møÅÆQ­[¼Æ~ÑÚ)ñï^‰b–> stream xœµY[oÜÆîóÂèoà#x)Î…äÌS`§v« nâxmò KŽdDÒʱ'ùõ™ïœ9sáre·@8Ú]Î̹Ìw¾sá»fèU3à¿ø÷üfsòýÜ\¾ß ÍåæÝFÑÃ&þ9¿ižî£Â/½¼jv?mx§jfÝÌÆöƒnv7›ÿ´ª[þõn5ýݺAõƒÛo»­m¿ë¶ºÝáÓ)>½è øw·Û'ó½÷Ê+h×?»­QSïÝÔ¾ê¶?þ¾Ûªå–gØò÷ÎôàPᡳž`ﻯƒ-J—¶ØQõ“ æì.¢ 3ÿÃâm|º5C?+ïyÑ/ÐwV}€>÷ÁŒ·Áâ[|yÓÙö=ÄÛ§ª8Vî*|‡bá{Zó&Xæà[×­lÜLgž…¥´gxEÞÁvZ{6ý޵8i–u¶=ÿ°è&‡kžð1ú+,À;Ñá£Öí…H¾€”à3oÚŸÒŽ=뀃¯wÑ!¼Ê²ðõpØÛ®ÕAk›üNz_²-°ª’ÞØTˆ'°þ:xuƒó&’Ê cA6ä<}Ê¿Á‡Þõ¢?¬ñ><‹Õû 3–XCà£é²à’^ùˆ\ã⥆‹êyÖå}†…¸•‹ôÐ}°U¦'D\qp“¡ë} Aäi¨2z !0‚‰¯irtM¯;˜óáGºžµKÁÐcÂÔhàgð×4¶ÃpŽ]¾“øã¸ˆ ~UÙžôð¼‚l,ý+îÇAøè ¤K'â~²ÖÎD/µ6ðÏ<ÄØ£ ~¨¥µÉF:-bÊÌh Ám4Ά¯£Òâ$c‡÷¼ @M¸cžÈ WŠ&ÖÜ>ïä˜SáÅè€Wpñéâ Èz]9´5´ž41Ü–Í%TÞ%«Å9–®ÂêšDôHId‡™Œ!HÍ”"`,m%Œ”A[n¢¬í”ïпÙì¾`¶‰ÂZÆíÙ²'ßš%qòöX’@Œ/Xq°Ñ(º¬èH÷y©ˆ‡·}g\û+RKe®²k‡ ‹>+Pz‡ %$±¹À†1tÖ¯2Á%±šÙíLd EvÛE:{—0þJ¶Û:n^ ¯@»ÇPÇ·+WèKÏ ç)S rOBŽÂ\Y‚y&ç"†2tám0âˆ.9âwDòÄ¡â Iå¡h’ü1”PŠLZmô)ÕJlv¢d˜Z•¶‘ ‚ˆ¯Ø*jcN uÄßvT<2}HYèVˆN‡îA[\×4ËܽÀ®k🇫5˜ž#„›tNnëÞ%œèÊJ….âéÞØ75ûëÂSû6=ܿ͞’sU·Îž0ºlŠ—ý°ñÜ)~2å‹) ›Ð×ZÚ´GÔœ¤6Ʀ$â%‘¼Øøs¾| ™ã®tlç©ÖðZ ·hÆsnJY)r Í2Ã@Ç¿æÅ¹Ó_ÖáhʲÊuC±²Õ‘îUªÜX,–þ¨çÔ«¯ *”±7jvKüÄÁEDÎSüºE}¼µDE®.h`1¥»óZüiÊ[›ÆúÖ¦º¸c'æ¯ÿú’<;º¼k.”¸á¹  “¦R¹ÙJ³„¢Ô‰¥æ|*ªP,Áˆ26¥ÁI4#æ¢Â½QÂÑ›¸z¦I©×ͧ³(91ÄØæOÅ<©aœ¿-x„¼Éëc§¨1K›ð»[ˆáÇœBÙødåÀÉV„'Ll¶ý±S÷3ÒZ—ô\æÁ’šxÎàÊ"Ò¶_%¡°÷qdª`âT!ôóÏKêœîM°š“•¿Å¦«ÅùC¤Yím¦hü&cònçÎZð»EX‹™õb†KZïc{½švjyÐÁçÈ€aŽŸq!.(º» ù ï#$\ô#ˆêy¼Â. NÎY³Ô£¥¸á82* “¨ÚSˆ?ЏHO£àCŒkE¦–ÔÌöfŽ›" ð%Ö+ƒ§Ö(‡¥aêbš*-f˜tWóbAøFB$!¬ò{=¡]™)Ïðe`¾h#'¿Ân‘¼Ïê·©¸[eX±ÊQ&À+â”ví“N õ‚¼Ë”\¢T¹L){]ǹíØë4ÔZ °‚5†¬‘NÚ Ÿ¹’/ôZdè|ßðó ZP ˜Üf&.›g ‰gi,‘ÛžEˆÕ| i5úR$\ÊMáË#7±"E¿auî7Òd³`­8£²±åˆciîh¯THãYiN:~¡§åc¬¯««¢5‰ƒkYD`åY›8G ·=Ó˜FìÆ~æ›88^Á]jT”JÊçW¾©•fq2zÊ£Gàdi[rÜmªêÙ•äJKi¯‚HõN!³ÕGÌÄÂ¥Øj:/®£ j~"(IhÂ’µ5US‹W‰q˜'¢òÀSŠ0£óð½˜Í'jˆ’äîE¹¢˜ØRûœr¾°í‰4CqRYM¦âo2C(+>åë;ÎSÐÔ¿Ëû£ò혥b—Ó*«º/ÑòÀôV†£SŸRå5—Á‚—‹6°’>ÔovÖjE.!œóH±ä¬šiÆP/7¦>ߌendstream endobj 945 0 obj 2405 endobj 949 0 obj <> stream xœMO»N1 ìó.ã"!¶³ÙM èÄCâµ— Duˆ«¶8ñÿ“Ý;"Ë{fìœ(E¡Ôß9w5tüq‰ŽîädÒ9ºi ˆ¢kªBíÛmJ¡Qi´“R[܇üˆ˜xølP™üWi–h aûù–Cö÷,±Ö)WÍê_9¨o½¿ãpÌÌ$¦4®þ†ˆ˜ªVüKg_t†NAó¡ã'Öî0• ¾ƒ<ˆnøûî ‘²Ég6íKtµD%¹€`¨Ìr¿"u;Ñi=õÏ}Ï¡€¤Ú¿¼kî ïE¸GÖendstream endobj 950 0 obj 222 endobj 954 0 obj <> stream xœ-‹; €0Dû=Å”¦‰»Á$¦lì”íÄ* U ñþ`üðæs‚­€~Ï…Ú%⸈qÐIò–ø- Zâjb'îô=.EÛwðÁö´ÐÚˆñM¬JÆo:Ѩ4Wn§äüendstream endobj 955 0 obj 101 endobj 959 0 obj <> stream xœ½][³ÇmÎó‰~Ä>£¾_#[®0å$–sRv•âQ¤)–Lš%ÇʯÐݘAïÙ™ÃYL±Ïž½Í×ýhÝÀüpPƒ>(ü×~ûîáóßÇÛêðæá‡]^<´_ß¾;|ñoО²Êúðøç‡úI}ˆæ­”9<¾{øú¨Oþ˜àGüŸÿ >e5ÿ” a0 >øø Þü/'=äœ\>þît¾òðËÓÙÿãdŽ¿>¹ã üã§³µyPÚ³§sð¤ õMíð„v¡~Iù\‚÷ÛãžÎôÒoàYàÙxüýÉâ×ÙÄ_ÿï“GÞèããôäx‰òÅÿu:{ü‚hêpÓÁ¨!p´ç6ܳÖz€é­RvÇðùÁËC¸¼ñÆ_ã°¬ ñø¾¾®­=¾š¾Åé ZÃ`ÿŸŠðeðÞö¥9(ÜS,sîýàlN‡Çß><þÓ׈ß:Eø‚÷'5¸¤5Ìá«òPÁ#* ÓR.áãìñ¯øµ‰Ç?ã³i°ÎÁ¼éÁ…¨R{=ëŽ?×ï N‚×MÊ·B‚él—}r­ø›­³u½¼…ÃÙ‡A9Õ¦ñ3 ¾Ý–á¾||øêᇃµC(¢ „¥C¶ ðZ§!%ô/^<|þâß?ýøóë‡ÏÿpПÿ+þ÷Åï~¿^üúð_¾8|u£ä€ÒxÁ5Mø´à‚ÄÿPvTš… DàO§ÖqÈ¡ƒù`þB üy Ž ¢H†y¼Îç]ðºÜèñ¾Ù±qðÀdÐJ<„UÚìhK؇ä[‡÷ñáô¿Ÿ4äé/`’ç911N„AkX@”㘯RâÇe°£ÄÛjW·¨¬ (â”D5DWLJüåTµWùŸDàmÜ!æ"… Ì–Û*…>"(ù!ûËõmCö –Ûú¢»ÂèqAƒW8ø"‚LÞ€O•ïx7Nëœ7ñâœÚc­w`É‚¹ÊË‚ö €4F\–Ëe&ˆ×,Ø{þ\ñ¾†?&åø' (¨HÚcɆã 6®¥Vù]ÖR«ÀA^É’0Fb‰Alž˜7-ysü_˜œNpZm®* +UEƒ¾í±ê0xâÀ¢8A<ñ"E::“àч[XL³E«% \Ãü$Çq/¸ÉÞ¨DÞæ¸¤ZŒ¹œ|ÝN޲ûhˆ²† v¼nšòþ„á1JbYi>|B$cmÕaôÚ|×ÿn‹SŒ?ˆçÚ 6L×Äþ®,0:>ëTÈBн‡ Áu&êIZ^ï5hL’Ç©i—!˜-›\O;yÌßÃÚ&äÄr“ˆ7š4ƒÛÃŬHv[J„0œW)¡%8b>µÈƺUÞ“öð‘á:ƒM=¥ÈyqA!6„ çg仿†õÝÂd·é÷wT—Í®°uiHÌÆ©/âõ¡–ñ5À¾°x„’V’Æ­Áwrê…åÝyð€›Ì` ÑmÒ qÑk»ÅE8J¤Üf%†J\1¤3çÍ„T¨7³YÏuz“÷©Â'×áŽà.„¡6*:¤ã2*ÈÉVÄÀr®î‹Ž¥X@‹Ó‚çàO„Ž{”f\>úçËI i´Úäé+2g…ŸïѦñ”œWÆRLEfËoÒ’°OuC Vs!Œ©˜PòI(ý¤kmë¹bœ÷~Ö1Ö8õ­`pv\ÆÇz8^¸~Æ€ÇCW?sƒŠ{‰“€Í°à\'—~’-ë~6îÉQØ9e¸á¢%-jÆ ¬Hãm¬LxǤ\I‹âvN;•¡®òdµ¸áª"ä¢èg#Ò€# psu NiÂ"‹sLK†KÈþìŠq;'Â…=ÄÉEUÒN¤7N`ÆG Ç??«9ScÆ•FÕg™޹YÂu@DÖE©Ò²¤7²àßË꜓Q–‚{›&\ôC”\Ô%m Dp£„æø¸ö|¸(G¤7AU<ùZ$\ D”MÕ@üpÄ4í¬µ¥_nav%7(MËkPŸ&7nŸáŠšVq󊶛j}6©fßèùyÌÙ–S’â˜s­BíJœº´Ï1ÒŠ'‹uÒ±ž“ ì¤uÍ— ÝL˜tIN#Œ•älæKrå‹A'v Ãßᆿ©ËRÌ׿3¬6g¤† ‰>u (Õv″Á¨ú²è©‘Låìde„Œ›WKy©Û®Ï!FX}ÎFF¤7Ff Š™¹((ê(¹ƒ’é%¬Jg#%Ò€% p§ZHdÕD¸<‡8aå99‘Ü8a€ùæmRvek|¶a©ùvj„K‡ˆš©tè6f¤á5f&x,qÿTÏÏ ªKttÜAS„K‡ˆV:tÒø ß{ÚUèö' û$—soÝ®jdðú¡‚õ=+"2ó£LÌq˜É`{ä'0‹oFXËäÎBµÊì2£¸éw1£O=È•íÛkÚ¥¶§7‹t…‰ «pZ#6â0›Ø0˜ïÉÇ-+ß8·ß]æ©z çH>$­{ËÝ5o'I¸ä‰Hb%O«H’†ÙHb0gB®dsmJ«¯r­. "B¦¢ÿù±¥ Cµbè%/ZNíQ8fR¼(Çz9¢üÇV¿²óüÛ¨"þnÚ!\=Dd°ê¡ulHãll0œý~’ÒKDÜA+„+ˆˆVA„ÍÑÇh¾¦ —=Ãö(ËKuYè4sZ’å-“ë‰K:S5q…-ž\†¯ Ôõ©ºà9Ì÷M»?áB#âQ1í³Nøô%5!ŽSS®ÃHm©Íòñ©'qù±t·3œ¼89û™œý;’.3"¦X™ÑíLIclL1Œ¬zð“ ‹Ö.²u½.Djdu…H7³%±’uQÖõI)¿èLêò};ÛÝéj¤FOWt3=â +?O껚 -eŒÕh&l*:[ÕEBóþÆ9‚æ—¼—Ë­Kä‡bá²ébªKÜò¶Ý¸a’âïðæfjl^×2Gàæù q3aˆÌ6ÕqÿtbÖ §%˜y×ÔÙP {%»É KÞ \fÚäl*ÐîÈ6¢ž‡ê]½_•4Tì(ß!ývDI Ê´û4Õçƒ sÏ®þ8sY‹#hœÁeÆck9‡Z8ãH¯qV‹‡-u3åjPvž«~íßÂUL{è—£²U¿Ä¡V®Ò§\Äcv¶zã¼—Âlr‹YžZÓã¹M¢-ÈîƒmaÚ]M›4ÔJ[èú`2ÚÞÕ@ÜÚr'Ìv?Í1(ooœ¦¾¦MXvΫãô:Ä=Æéj—ú¼4jŸ«¡œJNs]³·H£—Ýø%iôÓÆïji”†Z¥Ñw[Ô å#I× Ë,‹^…@Ei²fÅÊ뀹ŠGi¤•Ç è’îr‚õÏ^Íghºkåýõódr0¦·ÚÓn«~6hÜB¤‘Ý`&"Í´Á¼šIi¨•IÓwù¬sûêbA`j×îðâCU=ÊwÊ:cZv_—XSÓ¾îjÖ¤¡VÖTßô:klñþÐÅ?“™E#jÕØÞ8I²h³ìŽpc.3î¯eQja‘#½Êâ÷ÌޱܛOp 18â™ðÌ] ï–÷­¾»se“ìÞ5‰Sšö®W‹“4Ô*N éVq’Üĉ!~Þg÷Æèy±º›• ²;ð$VaÜ_-UÒH«TM@—…ŠÚÓ ã)”âæÚµý²-Žˆ“g½ì¶=Qè§mûÕJC­2¤Hô-E&+ÃÈÛ,sz7µt²ûÿĩӗû§·s* µrÊRgÏ–Îysš¿¦‹Áï2ærïE†r’¥†×{ãéÞØ“‰Ýön‰wkò.Á¤íAj†tðHƒlÂÃP^˱âoã àKà *ÍúÔ÷vNôîg·´ì™ =ýäÜÇí¢' µŠCºFô¤A6Ñc(ûØ™%¸ÚV¢sz'YR²G>H–”¾<íu»,IC­²Ä®‘%iM–ÊqåÿºL°y^|îå›$Û¯´‰jMfq¨E|8Òâ#²ŠGù)Ar ò–ÈDÙ&«$Jql²ºZ’¤‘VIš€¾íN.L³û);ä¾d΢ô&ˆ ² Y‰½05d]MŸ4ÔJCÚª…JÂ;2¶`¯ÛoDuîÏíêÏcžÕ;`õ°îÅ^ .¶™/Õ*DÛHÊ=vœ£«>ÍØgu-âP ét°½?V[VrÂ<ðdjy¥4ð:Ø/»½€N,bÙj*7Äàw¹ì„ë^Þ‹ö²M­I¸üÔÔzµpIC­ÂÅn.iÀM¸âgÎ_|ĸTqi•,+Û››$ËN½¹WK–4Ô*Y éVÉ’Ü$‹!î¢+šâvŸ^«/nÔËÏìcÎ$×{ûeñ¥ÒÈö'™3SïñÕ2' µÊCºUæ¤7™cˆy7§èKUôT9æ²J—…µ2†L˶O'¡ÒcûôÕ2%´Ê”îû¼ÏDqâÓ ioòØcãjQÀ½ìA–í¬Þ˜ËØX}kÁ¦4ÔB]‡´$³9"Ô&]f·¹™ÿ„mí÷F.ÕžÝ8&ÄÛì¯1£sw‡®h6¬Ó.ݶ PuKC-bÖ!f´oÇÓEÔ磡|»èQß(Û¾q…w¹¸l¾s3WÒP WÒ^•º=­ÿÀÿ@m¬o8ܧg~£óÙ½‚ù«‡ÿ‡l´®endstream endobj 960 0 obj 4806 endobj 964 0 obj <> stream xœ½]ÛŽ7’ÝçÆ|D?v[eÞ/¯ž`<Àã…€ÅÀëµZ– «¥¶eÙžùúeð¬ÊÌîÊÌ ëÒR«yÉ qøó-;ñ[ÿåŸß<Þ|õ?ööÝçvûîæçÿð6ÿôæñöëWá/p¾ròÌóÛW?ܤïä·ZÈ“q·Vª·¯o¾»ã}çÂÿáçï_ýý樔†¿rTâä¤w·¯Â_úÓáhî~=Ȼχ£€¿ö×W7ßÞü|+Ã?ÿé£:¹[/ÅI¸[ã¹9)@¿þææ«oþqûë/_ÞÞ|õ¿·üæ«¿Á_ÿóÏá§oþrû_7ýæöÛ+áá_g>çÄ]jŻЂ·gáqÎ4|Œ7<èºâîñp”ç§€÷KèÔcœ¹ðçGÃ|ø§|äƒ!>¤ ÿX ëÈåIÃ/Vb;¹„X{2b!Äø !Þo)"¾_G;1ò´| ]ëCg.L—<èuı%ð`Âð6©¡ïàCSZl¯8ä6òðãŒ?1~§’îîþ;ÈTºÐ2N ¥ ¸Kÿþ)jærò.Ðì¤S¯ÀiüŲÃï=F¦k0Ä÷Ôåt"þÀ¡C-Ó˜¹˜\ø'²ÕÊiZÚ1j”¶ª±rÕWÇß"+"´u\.ìIt`_"²»{ü!ü`$Ç\ȲbúÓ¶éYÈ1c",þçcbÄh3 ë}éËû6‹Úèe6VNÒœ…Ùsa’ñj;Äp3웾¬ }8Ðá·v§Ñ ½q#¢Çð9'é6÷?5ÜÔÿlëW¡Øî¸ðó€€Q»ð1b;Äp3,D·ÞY˶TqLøCŒ³v™“´ñvÄR>ç$¶/ÕÔp3g`ãÞê]@l ´0\’°rPhÃG,ÓZë“ÝÎ1ÚÌAÃúSÙQýûpäóðT°Ôx*ÀSßÇcIñœ€L9ÛÅt>‹´aõ–A«Â$Âçœøö@‚n {¥b¨ñeÅ €¯‚>îþºôŸáRÛ Ÿe¡¬œX„gC"áNz‡ˆ‡n ¡ÆúÄ/<„Lø»£wóTϵÿp]Ïa·0B 73‚ÀæØGÚ4£þåsN„Ô` ôw`aqNÑÝQúv˜_2@KzÙ²8s!Gì‡$„÷û¡r]ñÛ!,4áWi»q_.]Ä#†@çÞwÀϳw!€’é¼ Ì´pz™Æ³=ÆÔ–ñ¢1;bGQŸœa%L­0 ¬X39Wê J´gâœ#· :dÄîG8u²jžŽ²²@[U ÝŽs<ÈÔÐÃ` ‹O c/ KáæAbÇT¶„Ï©¥#“»§B°©¡rF„è¾íÈÄHZòdÿÓáhe€H1ø¦ž……ÉM¤è1Õ-B·òXŸ`‰LH^1Í+a1ôXa ‚¡ž_CZ¸ÍC£¦Æéð]lÛŒ¥ÆÔ¶„Ï© ú«Y ÆZX@Pk¨¯"‚¹õOe8‡-”áÖ-’²rhÈ1Õ6ásJ¶þjNˆ¡NR€ö½ < ›â£Ñ©ÖcïQÂíâfÚ’¯¿šb¬… ë%É`rHyAøœš±¿šb¬…µ&RÊ‘nð ˜’KL¬<ßá~L¡ w~óX Æš™ÀPÓr­KõYLSŒ nǔ܄ÏÙ<&¨±&Ô¥ c›BZ¸.V;bÆÔßpÓJZVBŒµ‚ Ö<ƒÇƒð1Ññ¾lY®"-z¿Õ;l­†”áÀNlŒq©±ZTDK¹À ºv¢Ž»ãX‘cÊràp.—’<•-U3XNtìz¤r¤0Î.Â…ûú”xÏaˆ€ H"Ä·Ì£M ©¡­CŠ^ÂçÔ2µtCÍtˆ‰êœ§þ°j9ÉòîÕ¸:wN…‹ošt2är< ƒZX&Î5–ÎMõ0œ©‡ m©%&k5D 5kˆMî¬Ò5ܤ!7B‹}ú®#Û[,~L¥Ž¯ï7‰…jÒJU„T±ÔM]ªFÀu!['‹a89ªaJ™ÅJ2¨±&6:¤yQ¯¯?åCÙé¬ %­ª…mì‚¡•V#nHy‚±§mC…g"§¡,UEqUC+,~­È訹«cFì4f´R´¦©6b¨‰”hQl|I7Kaãmbn0Êš‡IrUR=iH…fòðNùÙ† £"'–Ñ^a +š-kw˜Oå~à¥,áRb9@gàr¬ýøé0Ÿ¸" e„ À—ò1¾ßÂ¥›Æšõ!{Yî|,º+!‡†+¸Ù Ó«ÕBm'˜Õ‚ík ‹‡¥ãáœ&ÈAz‘?¦‚Ïa“LÅœ,jl’YHsÂØrZi¦’K£­U.%ç(&Ò8ãébѽ^,ÄV‡E,Èêp…X¨Af± òÅb!ÆVÄ‚°­Ë3 ±_d ²‹\!jY,dÉRÖû‘š-Á­ ¹©–$ ¾k>]üz†ˆ­" CÍ*rAÔ3A ã}×—…¯ ‘X‚Ë_·ÈÒåíâõ,[G–wä š¨AfšÈó‚;§dÍšsD†Ø=²PÑì#W0A13Ñ0"KEÏYM’ãSì°¬[Fgä ¨Af&-çwínà =<Ȇ’¦ƒw_¶ˆ…óyrd€ Û0Þ›ƒæJ¾ZÄêÀw‹ž©Í6³r±ÛæõÊ%™”;c ú¬r©áeåbx4³ªÐÍt†…ïÝo·Em Zô‚œAWè…dÖ ‰-d§«s­2–r ¢¶-Ì ÐÌPƒÌÌ Ï2³0À…,m&E-E2JD¨/¸RRã^«»]øÞ8±h‘Q³]¡"jŒYE ã™C´³\‡”Ôæœ…dι‚j™ò¡´¾Œìxèd—ž…yJý~4êuÝEµó&ŒÚÁ³°5eáùr¶¨Af¶ÈëØjýb9‚6b›ÏBÛ¹Ïçu´QƒÌ´!Õq*þÐ.Ñ‹ï úL«‹ÜégAb7ÐBДèË ¢™ B QâÑ)­ñ‘ßÔX¹ô$½š j»ÏLöû¼ž r‰ ²æ²?•²z˜f¸…ðRÉÜdRÐ^šóTtÉD½|1-´4{dj³Ò"dVºB>Ô ³|È\W+ΘV`IÑE µ]i!¤Ù•®àƒcæ£a¼ c>5CòìëG RF¾1È´‰YoPÞùÓxýipv†Q»Þ¡R[­á «ÕÊ¡™•ƒ@®‘1Ê"„òrêׯuWïfJ6;Ì7Äö°E6Èv…l¨AfÙ —²9»w7~Ľ;µgl¡ÙÆ® ‡d¦œ '?À}w¾‹_Ï›]¶w˜}‰]d OÈEvOÔ 3OäKyZ:íu ÖqjðÞ5è}z'âq¦Ù”šœXò™»ZMÔþ·YMÈÿöz1‘cLbB±‡§sÚgpPÈì ¨Af®¶á•Ì™½(×1ºèqë8ݠñª‚ÐÏ ÌÔÐv®žÌÚ™]¯bÙ¢d"»B?Ô ³~®¶â­ú!õƒÐaèv ^J»òS>£f®²ûzÕ›ÝÕ ³Ûª¡™Uƒ@^©b€Q5]ŒdÐÛëGc™)VÁgSËyžÔÖ»E$SÖ»/ 5È,òJ‘Œ"Aè&öøNò¥Eh‡é„ØY·(9ë®P 5Ȭòâ• 'YŒìñ€ÝyHíª[¸@¶º+¸ ™¹@ {.^Сc²&Æ 6žRtX'ư’ærÛ“„âôF1µóoV2ÿ½^8ä“pÆ^7¿ƒER-7/ïÆòèí=»OÜ>¬©}€ 9Èx;Ô 3;nºÒ×y­Ëìji¶ëÔ>À…»¥:•d¦ì ®³9\OuI°a&-OQÑCl\èÑ[êAÉAfz¦@ž?ia!±œ Ê€„Ú¸p¢¶”]’ƒÌœ 3GFž+ê3GjsàˆÜPfIŽ1Ò0Îð¡«GTª³|wx>µ‡±Ý,¾é%Ê ‘Ù1f§ö/â3[joÉAfñ!¾(KÛÑæŒd®ØÆ rvMˆV.rvqÙööPÚ»¼HGm)&™¥ƒ@^ZêÜפ±gŸïö@÷çÈ•Á뎧ٞS›¾ä†*\rŒ™®†±öd}ûéÊ%L¬BÓt9—ÔFá… ±¥—d¦l‘oúÏÚÉù¹¨ŒÓÑiµ w!ˆM”ßV™º³Ÿ‡ë…×Ç„I w–ªï’¥§¹ûhR&ִׇWÌ® ±]wféÒ¯;—Üàô"'Lñå!á…€!Ù¼#qɉ›ùÅ9ñ‚Åp[üÞëÃà&|ï~¡µwféÒÇ{;KÔÐ3Mt„½Ÿ#ùÔ:†ÇÚ,ü†NGÞfp´.ßÕ õ¢¤¯>ªóü{:Â'¯ab¬’I0UiXñË9aR‹±[]Âøn.*{¸wŒ(‘뜽+‰†ºÁxöXGx«bÌöäÎÜÈ{Ÿ ÙJo;OÍÃ7fnö(dS÷zYöŠV]ˆþ¾´4« ¯âóÏÔx}¬Ÿ¯€=Zãõ¹»¼ £K[0£«„¤3Ÿ_å»s“˜Ÿ”Ò±ìÆxÚ*xä­|Lï/€Úºøº€2X7§e'Öãü¿_j×ÂIf½aã£lÿØ;MM`[8q´õð…wV´5'Ô83'g|ãá=˜‡o s• ‹Fì0©±fæÖÝaЇnøÕ6Ì#w)i—¹I»y‹0Sñ:ÒFØ>Ä2v¼P™^ÚÜwZP´µØE\Êí0-PcÍâBX[Ÿþ˜2ò^¤(.“M71\ÃM„ö¡Ô#¼LÙ’AX»Úñ»Ç{ZÒV’ÉVI¾^FÔX³ŒÖ^FhyÛmM¾´`¢ZY´€“|‚¶¤»(ZI÷z©±fÖ®OÅÌáÑ|Øáf´Uß…/V«¾/OøKBB;5^8áN©>䰭νS`? ð`â˜ûc¢Sî“êw-ló޾E:tœ5¸EOµE`§Àkž€×™¹s γ«5žNÂ"å›rßÚ OåiËÞ³žmà­Yš” ƒ˜ñ˜&Y†{0¸GÚwkÚÂÒ°n…¥í-'$@}øüþîù#vÁ“›2qK\X»†ô'5ªp^?𦝠ò*¤¢-2-Ô©ZdJÅuCs =Y+¡TL;çÿt82@Î…K³Lkì#Œz^U3EênãQÒ–ªRe+U¥b•º%‰UÔ™‰ÖƺôdâÇI$§­]-ÜñV»JÅuKw¨!‹‹äüÁ;o™IZò> éԶ׊%<í¿Ymácj‘ÚÈ[Õ†²MmÔx³Ú0àWí¶ô_¡‡Ó‚Ç7¹$«/ñ‘ÏoÂÒ–GÅÙZÝ ®ìE‹öï·æúlcÐ¥ öFºó³™Ý’…Ršæ2—#Ó-ÙM)#Ô¬)c}>5ÞS_o×”™B©Sºùý61ãDÍÞ·™ôSíËòÛ”N–ßÄ ‡ÂnÈûºîµžo¿jy¡!ÚNdNiGp]#äúÅð1µ&p–P8<Îç¡Jº,+Êj3¤ÖCênÄõrì.õ¨ÕÚÊï!ÄbFÈa+‚|R7"ó‰qnЃ–LGíÙéEÑLJÔ3†©5‚ÙF =}òá€kB–xRÉÊš³u¹k*æÖ·ŸžäVι!êXCb€mϯgkmï)Nz÷”5î‡Qrß öP" ¡úb€¬Çp½1¢6 ïÐei-i)ùÅQ ÑF7·qÑS™3!9¾lsæS[då†TB†)å…;«ŠVUÃ/¯5>U·IS»MUvHu&7­âqgQQ7 ‹ 5`ÉGeµ?àM­†Ç®Ñ>¢ª¦-Ô·0ª‡TgrÝ*wf”º™QÔ€4ÌVZ[Ï0±†ŽXEû n!Vµ7qw&–º™XÔ€;Cá/w†•Ëݦ]áGÔHqèpš‘º™KÔ€>¡ï¼÷jjæ>;§j·ìK·Ô#r®©†u2U¨çT-Ä^>¿>A 2ÈÂ/ò¼f: }8²wõ± Ö2§ö?ëãlH•$gœj n@–jÀ YQƒÌ²býó“a½Tßqù)uí+¸!%®î+-jôIY ýõº¢F˜dÕ.\Ó©M·’LWvH¦…rFF² R7 iªkÀ…¬iÌ.‹“ÁÌ~fZCê2 ”e2’3$ê$»\CãB‘7sÑʃ¸ºïñÏ-HÒ2ϙʂä8«‡SþfåúÌþ£n@^×€KáA··Oô·7ÿ º_;endstream endobj 965 0 obj 6516 endobj 969 0 obj <> stream xœ½›ÛnÛF†{-ô!xI^h½çÃeÓ¤¨ ´MRmQô¢‰]·H|È IÞ¾3K®4tdÒrA,›Åûÿ3;»Ü}ÓI¡:‰ÿ¦×——«“ç¡»x·’ÝÅêÍJå7»éååe÷hPŽˆ$“ê6ÿ¬Æ3UtŒRw›ËÕŸ½\á¿Ü_›à,£èYÚ{¡#œ¸9ƒ3(‘R´©:¬÷üúdXëþ§A÷ÛŸâ¿kc’Ê‘“ŰöJ?~h:(ëÇ/ÉçEø¼éÖå­ïà¨öp4ôσ_g"}ÿ×AÃoN«~³;¸½Dþâ_†µÃ/z¼Ýy#­µ—x¿kàEªñ¶¿Þþý`úwð xÚ“ÍêÙêMgŒð¹UáZ±KFã©®/dD®NNìÞ¿ýp¾:ù­S«“ïñÇ£§ßÂËéãî«Õ“ÓîÙú%/,’iE°£ˆánû·pgýpŸHz>Ø;A•V ¹I•¶ÂÇèKðÅ5¸í„Ì?P#…´ýÕ  ¯µüÒÛ)×ÖÃÁ=¯ܹÅ'… Ç. \G¨X# 7é$ =Öü|d\;§â½xL‡k¢±!¯«4`&-Ь¶d”-õÍØÈN¡,j”¥— †‡·_Ù¥ñ–}•4̤Ez^ÄÈ?rîÂ`ɽ‚¿’ (‹Y8ZœLHÂ.‰“ÂU) ZÙqî$GÍðÛ\nô~¬k¾Þ>*>Lh&ÔÆ3iQƒ€¢Ÿ  ÄåcŽ‚ü„A±X@hÓ& ´© fÐ"ÁŽ“(`ú±Q±;ÁâJFä·ÒÎTq ö ê»õ®‡$“ªê]nÒ" ½(ÝÄÍNŽ­<øŽIÖ<(Ìqáâ’-*^¸Ž0U/7é$ Ý'ÌM©‚ñ»¡ ]mh‰Î˜qLÛÿíŠ#n›‚H1ûFßD¾Ê4^”è@cU‰ÎMZLC@o'ÖÀ´/µ_X.©‚ÇB‹r½¬«Ê nÒ"Í2 c®ùôºDóg¸ã9Æ®ÎyÕ¢ø€úI„*A˜A‹ ;N¤Ë58”ßN§Pú3µl¡á,†Z TRU…7i‘€€ î麬˜2Ùù@måg|WÎÛF§1iúþ5à¾ÆÉÜ=]„¯Â­ Vd“ÒGGáêJfÒbz˜U¸ù&«>Zæèݾt²„G”³M*å¶[Žô3iñ¥ÉýíTñl‡-!&¦ñ¤“*5)}¤¶®ôa&-ºЙ.cNM·Rª÷ê¡ØÚ£"ÆÆØ$bà:•ÃM:)CATæîæ…Læ§¯ã¥Æ)m;£ž )ñaéãIˆ|[íqmƒmÐpÊ€æ&-¶! ¯£óìŒ\\²ªŒ\Ôr#ëáÜ#ëὪæg-Ϳ㤭¯î©…T“†TÖŠ )fŽëœO@oL,Û/4®–AC’ÙöÁeúÁ{TJU!kCl1Ô‚ëS5Ôâ&-ž! š†p2 üÂ5—Ò¨ÝcË+Ì÷Òßož#óq_ƒÁ—…«‡ªÁ7i1=Ð<Ü€“yàõ¤ÝíIµ%¬¢¡òiQQj)t]EÉLZ¬B@´ 7àd8µÝXö’ç(貘n-Ñ~*.ØOÉ š”–X ×•–̤Å?ô@ÿpNþ!€S³[ãDüsŽs?Æ>è›ãòŽIƵ(‰á:BÕØ†t² á<Ì5ì|£k_î•®vf['¤$šÅ’%'K%JÙ¢6! WUs“§Ð­Â 8Y…Îf’qU-ÏhÉàZÁ¯ñN¤ª‚—›´˜„€ÎLrs*ëÒ±SB="íŒræÜ?p»ÓÎq7vd.Á‡ Š]¸Ž°UÅ.7i± =Æ&Ü”“M徕k#ÉËMí¯¹ÜÔ˜Ô&¥à›º”ÂLZ¼B@÷Qïó‹QÙ/Ü¤Ö §g¤teD~d6U(~÷Óiiª²Švm²ŠvµY…™´8…€îwʈ~=˜0NŠåÛy—­a9–ÜZa”6-©F)«©Ü¤E!zS2ê'øEîv~ùåžèC‹Á\G˜šæçšŸpÒÖWy´¿™Oýav·$Ç…„ŽmöHêX»G’›´hB@3#–Be³d>pø>.¾¬Q‡6Û"á:•Û"¹I‹4Wyvs /°eóA”ç=*â·Ol\¹e“}’ÚÕî“ä&-¢ЇD1÷¬Üw¹d‡†:ÇΘgË,¼×tå~I«Àd«rªm³ƒ®S¹C›´˜†€"Ú‹Ò©½(«s>—SÓ¶[ƒSUdíTZ0¤M›Íœpº½kÜ Eœ'’•BFKÎØ¼¶Ð-\s¨ÐdŸšÆyÆºšƒ™´H@@·Û1ðÙÝ î¤ ³hˆd¹ð³Õÿfó¢endstream endobj 970 0 obj 1839 endobj 974 0 obj <> stream xœ½Ûn\·±Ï›"ß°»E÷˜ÞŸ¸ P)PúÐöÁ–d)°%ËŽ•8ùúÎ /‡‡Kž• ¬XvìrîWž[1É­ ÿÒï—w›g?ºíÍϱ½Ù|ØHþÇmúíònûü$àßLA¹½x³‰˜rk@MÖoÒ“€íÅÝæß;¹7;¿ÔÞü÷âֆ@&ð±¯è›Wñóþ»7ûƒÚÝá¡Â$äÎá?@D•j2&øíÅ›‹?!ÎëýÁîîéGFÂ}ƒÄ—{½£Þíaw‰°Z:³«`šþþû‹ÍË͇­B¶˜Åƒž<2ŽÄk¿µyO{þbóìÅ?¶Ÿ>>^ožýk+7ÏþF?žÿó/øÛ‹¿nÿ°ùþÅöåJS ;iM×LÂFi~Ü ó< !…ßÝìÒø0…Psƒ‚˜´BQHf–TÁR&é1ˆÒV€ä`¢Š’Œ1Ëør¯Üîvv ÞøÝ§½Ú=ÄIWÿìGÐ5éVL„BòùÆïð²ï¢$[&´C#Ñ÷>Z„Ò–u…æCtöì€0Èb"e·H™tŠpÈôäÌ[˜ØðZdcè²Èß ƒLIk5 Èö{C€!Œ‰«‡= KÂí~#3÷2ú)T>Ê= å ”dU›­ô±ö 1x8‚“ Äì‚5ŠÝýç#‚4™ Ûº¥x,£rÉb4iï‡#bSjE¤(iT¦\ÕȈ?¡öY $KmX–º/KŠ‘$H0"d‹¾xlTå¯ÌFkøK@V% ¼òaE0VªúúVï œ“,æI÷àÞïQ“d ¿’9ŠU L.ùš( &SZë™m![Þ;†ó äZ ëäx¤--:N· WµYØÝ#™½RǶ=»Fz»Wd•`øFöíYGt³rIj÷Ù.Ȫµ/÷ècŒ|xô´˜!@ }äŽ ¿€øíU1kŽŸ(C%²h®4H¶ÏÖÅk¤Îàü㆖>+±‰Çi¶Îô’­—ì‚,X1%}Zð‘þDÉ£q¶4»¢t:Rpe3ÊšÊ åª\£d¦Ü¶! Í¡QrHÎäŒ.*èëK£î”ˆÄ·º#¸tžl(:[@‰F¦^ÊÄkÙȤ~¦c ¦r‹ÐÒû9ÑÁôJ˰áB÷MÖ²RNôüžÂµáñŠŽ‘¡qÔ ê>ƒJi;î\GíˆÀœÜrÐéqâýX¨É딬#Úã\pUB¹ ÷oJn%Ù\£lÌ)›ÿL=Ç[¶^Yñ7#£§9T¥’,4§K¬†½‰d—tA*KÏ]ÒVfÊ.JºÌrr ƒ…I’5uÑMtà'²AÙОŸ #&sš‹C Tb¿NÕŠUPMòǦدãHFÌ•Ž•~sm]œŸj'ÄHÅPƒÀ8ýʧ—´o:ph~ZùZkK j¬&OE­ßÜW°6¼f‚ÊÚ êV¬kNÁäÕ.¸ãì°ðèÌú}ŽÉ&†0Ó$êÜ{„³`ÖàØÏ¯Ø»K•ê;p¿ Vd,+­´‘®‚–+ ’¤½Çÿ=»‚ðšE¿ 3ùK™…#e6XØ6šì’ó#ºŒyHÙ9ÀCSܤ “s&KóTXˆ„5„ë¬S*Oªš«u£6g‚“P'–öÜ›TœŒŽ*(ó¢#^3Éet´§½ŽkêWQ®JPSmWÑs¼Øm Ë¡/–³K§ªû³¸JñžR7‘ÖEƒ°‡IƒK ;6?Æ|˜1Édì5VÉ|XVRè¥ ·¥–y`Êô(jÌBË]”4rMf?ÅÉ®E"ù¦‚Ë`¹ÞUÚt»½I0Xƒ#oøDׂZË}nv¬‹çwfC6p=•ǾŠÊçœNƒT9e¯Ä›%_úŽç T´±NZÙ͹=¤Š3· äì”§YSу-(¹ä˜‚R“Å­…MÙ[XJg'xÍ$õ2žˆÓñ¤á†M¢ÿØ™ù¾îâhE 'G”abJc$=’þo1š£›9[«ªüød(7ÚÑ=)]'è‘ìc¥QdÏmZÎ¥M˜kJlᱟÂð $*†½O Ü ×Ç–*Ü^¨0SoŒU4ˆ=hÎÆwÉ…‚?ŽNDäx˜8glöO8B¢I‰ðŽ, äÂ83¢ê>Ï«ÐI5J|·0¼¯G"Ê‹2aéb!ˆb žŒKÑ(á{†ú š`›¼}”$24S,…€B„qØðéóÙ©Âd5^C3ŽAÉa'È+¦!ËiKÕ$V-‹>i%›/ðÆ¾ ^CôÕðU„ ý“„ÐÄÉ™®9YÂd+qc¯k³é´k­‡ˆ¨õ]d¸ÊË~g/sµZÚ@\AçŠBKÍÞl;”TàO2ã˜é´õâœí¨Á-m|,´cÚñ,¨í`ñ¯»ÝQÅâÛÊý9¡©¶üè™÷øY-z%D…ZßÇÝh¤×žö°?ÒÈAÚ¦:A6uÄÆšlfm[Bfׂ™'+PÞú³ú1[Þ2)ÿXÁÒ­‹±¥¢?ø¸]v®d =ví‚Ì=ÕkžGBí…­Þ BÚ›’–ÌÝ&Ç 8¦;b9¥»6-.`Ù’”È™ºíƒ°DCŒ4'aÉÆ€2£?M/u@`i:[w@½Ö¡ •ŽÈ‰ù\É./·›x°k¦„ÇÀ©·ÑZé“|T% ×1wN‰iQbaM¥•ÛŶŽ-h÷ ë•Ý¿/–JÊqqºŠQê·_VY¨\“81ºà1Žª=.¶‹p”²æ5àuš|ZX´Ñºë¾eù:ï÷¨‹ðZw¶ÖVÈÕ‹Í-8à´ ÕFúÎ^®þ#‘õŽ›oz·RäºÐñ™DUÔÎËd¥¬¯'²{@Ú×6ia!‹dÊÁÇ–ƒæïiSS7Å ¬+Ø}²s³UŒâ‘v1F}!Ú0mðä‹ë¤:çÔMcÚ0¯ÁšÓFÅÀA·…_ÅN%÷ëbQ‚µíOàb;í•iWÓ Ð#‰;OitYzJg2nh)Ëå¶ömóõmÓÛ¥šÛY}B­õR ©¤õµvk>R'XòcÐóÝ:-ô°ÓP TœPL71T˜¹L±òžÍÑF5Í“œÌó$ŽÆ¡Œ¯êPV™ñ“#›ôֽ޹;Ž*d6NÄj Æ y£!MÝ!ÈÝÂÏêÖ5ÎE|Pk¤×8)H—TÿÄ«XP 0e¼K-Þ8x+©rÄ,pÖõd xM»ž”M(˜[†vìò*©ÓxW?žhëõ­XŒK•ú Âi§/ÉCÑzúc±¾Ü¬îXf»ü²WP¼_ª²«ÛÇ4rQ©‹½M/oŒm¦„3xzg£|ö* -¾çPÉ+ÚØJNš¾4Ϭü<þeOß{ÙÁáïä^ëd¶8%ÌYyÉâ𚩚¡É1 'wú™Àx|Îeqb¯™´]gan±*}E ¢:±LÚU´‰•E ü¸XÀpžÍNô}ç rlGÐD›”ºA‡UŒ“Å €†söÄY9 &ç—‹bñ4åDλrj{ß‘w¯ ž ÜûuC¦½0-×Ï»~M²ÂkÚõk[.\±æ#çr,óBcð.¥B¼ÊiƒÊ@pºÁì‚§½¹ôPú‹¸Þˆ—ÆR*iêÞb¨â.áÄŠ<‰yï+ÄK¼fÒ_/çgÅyÑ--½ ˜·äƒŒ;?dNb,5Ë'¢š«VÓ¦™Û\àSà0ÐU«7Õ”¡¥ÓêĹ9DPÑ‚º0a¸[«‰‹™šZ9Y @¦P5Ñͤ36h´°%‚Y,áÝ)¼´P„qdÔVñÌøÜ/êèíŒÕG/êª7àtâÞv´ËØ,Χ­-kð‘D÷ ª‰h‚À`G>B-Ô@ ÓÇ4<›‚½Òa‡V0×”×®á¼#à¤T¼f1®Ló JͶÍM¬°²càÄ—±iœ†ÂPJÏ_€@¿í ”oARõÚ~]RaÝW~ÌNÅͬð‹…êc?ÊÒé±wJWqN»18Fž¹€N—ãz¡ñEV8fì#atòbÝÔ5eµ=Y1™ŸçhºGÃ:âŠ.°ðüûy'iQÚ.&i_ªŠlÕŸ9ê¼Igç.êœo0”ùÞ&«ÂÌ4ÕFÚrÏKËõøW¾«HXÜÌŽªÝŒÅ~Y®zÇôÉZׇͯ$•t…²Y”•+ÍZ„²ç}_,BÙñû‚Óñ˜Ùù%¼ŠÚö뎕ܺ¨t’¿¼Ž³êN'·b`óAWå šQHßý2¥‹y[0ŽIDúÇ*îÆ/*Uú ©¼F©†Öqø÷FBEçlÝ´·W˯Ît{ÆÉ#ª lí*\F‹²àðýƒšG´;ßýî¦BbµçÕ†äøÞ}Â[¡Ìb¾¯$ùSÍ[ô±+_ÎVa.PÙÐêÚ6mÀ-Ì£¤xÛ'eáúÆÙ Ïd«:¾V^ù6ªBŸÍi¦6Ñ?£NH= µ¨ì³1ª&°mUvçã5·qíwHÒ‚í\½ç)õhéõÍŒ3Ûàíæ*mCì³cÍ2{œ?m‡¢]ÌùöWÑ5¤qåÉuëÊó i© CuüÖ©,¬ÐE¬F¡é:´“ÖÌœûòÀ¨Q©Uyù\©”óÄËÍÿ6#_ùendstream endobj 975 0 obj 3530 endobj 979 0 obj <> stream xœ•SÉnAåÜüD»‘fÜÕû11ˆ%ƒ@BœlK‰!NOUÍâŽ1d{¦ú½Z_í¤©Aúõçr+&I^Þ #/ÅN_ÊþXnå´EX´Ôi@¶ßDÇ™¬LÎׯÊv+¾(ÐAe|¼_Û×ÈrP²lŒµÍHlW~®¡nšìu®«¯3]YõN[u¦½šÓÇg]9×ÔBA®u#Mì@= àcç„yñN½×Õpõ­6¢5© íÈËåýGmñ-XPíÁ8†`ÇtÈA²]¹›TÙh¨ÞÊ6xèÊ~º×NýÀ&Ý`âê;ºq™‚+‡6Û5\B“eûF´Ïz ï1ò))R9ªéúM”w‹9©5¶lI8°„‹ˆkŽpwTÀq×”Bò<"“¶ÝdR„”‡¤Ó­~y£mߌŽLedÖáBüq 'Æendstream endobj 980 0 obj 587 endobj 984 0 obj <> stream xœÝ[moÛ8þÜ0ö“|¨µ¢¨×=,mšîv‘·MÜnw…k'N®q’ÚNÒüûåP$gFÕIšÞ‡¢ªL )røÌÌ3CõÓ ‰Õ ?îßébëû£r0_m%ƒùÖ§-eÜ?ÓÅàÕØTƒ4‰‹"-ãÓ­¦£”é HÓ¸Œ[¿G/‡*Nª:‹®‡£4NÓ¤´·ZÅižêèÄ<®uR”Ñeó\iÍðö|8Rq¡TRDŸM¯Ò fd_@–ÕºüÏø—fY\V¥‚yäyœéºŒw·Æÿ=:¦eœV¹Š&0V’×ZEËá(‰kUÔ5m]À°ª®j3-ó\•‰®Ëhm¦˜Vµ•XÂdt\Ôyôz˜Äi¡•z ¥«4ú›iÎ*UdÊ, n“"/`=i\TI’㸤í $UY¨švZ€®u¦›åÚlD\'u³Þ:VE’úõšõhP¦ŽîÃÝ \.ÌBó"FÃQž&0¨]’6媎ëÚÞj3 ˆ•Gcø}—wpÙqO’*ú#2 æN©èG˜^]WU©ÐøÇÐÈ&µ%ƒºÖSÓh¶>1Û9 —ØÿÞv²Úmžà³uh¼ÁÆ¥4ÊIhœ5ã݆† J]Hãaו›R’©.™¤×Ú4‰™´†S¼=Ç[×+Ó• a·uQÄUf k<3Öôb8ÊêÒÔTòoWl¨f³Êè ¼ÄÛ]”=ÆÖp ¯¹÷”Žó¬ ¦a1¶ —‰C[še8x "6ìWVoWð$@¢"X]8pv·™¨mJwÕÝ]8U9Ù€‰¢ âó©ð0ËÄñ‚Õd2|'-PZÉ+Š,owÜІÖÂt`«`‡Ú~À9èÉö·Ê#{tÄÔÙ=ÎÐù†™Û-§îè,ãž,¤1E˜ Á­ÐL¨ÙxaèOêÃEfMAă˜³N«°@öR”%#üÀƒHZÔ†ê4AÄB&÷ ððo¸Œ·pË{?ßÂe.?þò h†ÊËÜ U  ¹‘¬m%©q.I¶ƒÕíT¢È€ì #k:†™ÿ —ƒ¡£PM/»Va…IZØ&™"DªÀ¸BÖû¨¥‘ jœyI~&¬-¸ÁLvYkéMs©ý|W_»AUûN#›ÁàT¥ƒlúMT…ÞåJê4GšõWèGx:óc¾ ‚{Øh„²ª„æF9à€æD³¿JÎðØL¼äHrÃŒùò¨müØlqd°o@èõ—µlpX¸¯K1ºmÇ+*nBWÞï‡^‡‰ÚîÇÍNgÊ"6€©îÜ ËĹÏ$—BêÞíDò¥M¥2éO,·6ÿVÜü ”%ƒ1µYte:.*.âS¯Z0iä¸z"`÷&¤÷Ø­&¢ñ¤í÷<ðNîšn¿gDo~CIdúGÌ ùá1f xÚ$FSA;9­G{ÄÁ´»€µhª.PºnÄ×®zá“eÞË„:˜«º£Z £.H‡*o8:%×' BŠ…g×XJ6"‰ÉW¡Yv b™ëáe‹5E‘»»•ú\°M$ópÎõn(8žsé•gR.³B¶»f¢B›ŠÈ!õÛ[ÜJÑu5a­ŠUáñÄGõµ^y^$®[(kÆäNêMày–0cáÆ–\ñ< ”òÎy€X¿ÓFâãŸ3øù=¶T çÑâš…nq©wí§’[¤Ê—Ű0˜gxkc¨Îwc˜h]ý¨^P,- ãú‚ñSëÍṅכE_b4!9ñ- §NSt&eVe3Ë?·Øu³(‚⃉g&dÔ‰û•Ž«J‘Š™ïE”±`z¬Z4ÅžÚX+§ùô¡¦E{ZØÞºL´©;a€ ?ÚûB¾Ý%Hë´-3‘£º\®¯.¥ œH¶|Â4-l4Û/ÕÖR#w®6 Õ=>ió™‚73ht=6ŒbS—(<è¸ÎzÈqÝ1Êâ8t»¿Iv_ðÍäü6Á~˜öß…÷cM±v2̓Ǵ" ðd€rc~ÔÒ>eqÁû;i{зs½–vwJãî¾Ã4öŠNQd+ÝW^" ÄW.¥F„žxÌ-Ü@”òÉ>–ž.¸º|Ç´ˆ>É$¦s¨^–ëÙwoÀÐ>¨Sx?÷~¶bu¸ @¬§ÛcšŸö4áÈ)Gõ|^@*!Xô8Äç˜Â’¢ÇvhÜë‘ì>Ƽ‡¤8(ùÑWïnb"Üꮜy` Íilè>õ´¯vˆÇ£h+âÛ„fb „ð0ý%äŽl øNÑ%‹ñI”›V_9•”ì¿M ç¡-9vì­©*Z_70&Ç¢\>—ÖÏbŸïÿ•[õ^ØÍçŸóL úFGï§!J\P…yšø•k}¶Cv‘m޾ñHgP "ošáÚÅAüìH¬z†ÂWm¯@SBýZS=È>/ZxWøp©Í+m “ ök6»²M,1:ÌÛyo—Q9”m4bÝ.äÈéáU0oïl]ïõÌácèb¿Ü»£Û«IzˆŸãt¿ I7Ù&Ÿµ!ç?—:ðÌ‚'EjK©8zS=ÇEûR=¬ôxÄ£gç‰^w¦˜}HŸKõævÞ ·?W’× : Ÿ/ ¹ø[Ÿjža=;%1‚Ë%ybÖ%¯ÃÌÈ9¯>8³ˆ×ÒNH’}8íöA'÷Ï/„%Tê:•P°šNHhâíËõxpØåšsI-bZÊ*ç¨pŸŽˆn~C”ømòH òûE~JJÈäÏ&IÒ‰ìxgóHþÛ6<úÜŽöÐÎ¥&%œzeÉÑê1›Š¿•æÒGV½L+»LkþeÞÐ9RÈ;sëHmí³=Ã=<^xC‡ïöÑeÑiú)0Óèò™ÿnð1RÁ¿]ïn^D‚ˈíjû,N8?ˆÞŸœ¢cº¼ß…·%vzÉ ÖBj _²áçØM‘;£óÜgÖásÈ^ÊX‹ôu̦ùšÇ~©qÌ—Ù°+c³_[â;b2äœ#®óâRßJJãyQë¹Xû_€Ä˜ƒð¼G÷÷YÌ#¢w®}Ÿ­x ² Nç“Ñ•'Õ“*9mo×[ȱÐÞO߸£ð üLíáÕ w¤ŠzH%Ýݦj Wßàíü¿a¸Æ]þöG¯}ï o-Þb|<`#áë-pT«€>‘–$ý9D–xË/N ºµ§{ÿK‡{⎂ó<ô®6xP«•“¨HR…'U¼?D8ú¿˜ß@§üý‘Ñùÿ`ªHíÿØ1™5¦j˜G•ù›sè³3ÞúÕüùå°êendstream endobj 985 0 obj 2898 endobj 989 0 obj <> stream xœÕ\YoG~ׯöÅäB¤ç"9£ ¶%' ,Û+K É" I]0™¤®üú>êš®áд¼È"Möô]_U}UÝ£¯»Q7ÞÌþßÑtçùÉ`÷r¹í^î|݉íÃ]ÿÏhºûò´¬'eI·ˆŠx÷ôbǵŒwÉî ͺQ²{:Ýù½·{­¼ü¿ßîýçô·²UóVIY5Ïʆ§ã²ò‹vÜ-Š<+ZïÛåëa»“´Þ¶“ÖA;k™Û4-ºQÜk½,˺íN¿ošä½²Iš±OÚÈ|“¼,MZÇíÄüÌû®×Ó²£òw¿p£t£¨—ĦQšÆe÷vȲ0ÎúüùëvZ~KS?3µ#7Ý~Ò7}Bûøaj~('[>N·1ý”oLÇïL'ºƒ¸(ÜÊZ óqn>†æc…?ÿ4¶ÊÜ|LÌG§œC‘—+°sH[íN/‰ì†™%Û¶ÎÌÇ¡™]9Û¸µWÖ‰r³®ó+Á=žù.¢AëšÂ~.±ðœ X¸2½¶ùÐödÚ† îËgqa'1Âçsz>ÁÂ[*œŠIúQÄ${FœQß.Ì^Qós“žéùg,œˆF|ß̘=>ÑUÛÈ7íõº àÜ™¥ye‹Øâáë5Õ]ŠAýWÓy')’²÷Nœv{}£yf‹; àAtÍñ“ƒn‘¤Èa;h‘bj¾pÉ— …×TH¾´{´­H¡° …võ¥æØ¥÷Šœ©É-.“fæGéÀ¨†Aßõ·¨…Ù¿HR [œ5âj¤­‘d³Ðp5»kU³”Ó¯øü€žŸÑH÷š h‹'4g‚õ9)ˆ*¡­OšèX ÑøfçôŸ¿›‡Üb ÑN})åÑë÷@÷øt)Õ1eØ£[QÏÊ>Ø;‚ëŠ,ØÝzcÅ–y¡Ò. yïás¡ V׊Œ™Ê[­Ï‘¶ÉLרù…ÖÑÄÛþ(nýÑ ?S… ÿhæšI2 ôl†2\‘TìPfP¨Žùm†²£¤FyKýëw«õøJƒÞò= »t0ùk½àæ´žk¾KnRÍzz€Ï_ÐóS­ðžQá1éém¢ÜCá\3cêéZHÞ­D |. …5V…QZÅÅœ7ø•ŠÕºÝ¶0¹èm4í^¢žJ“›š²ÄÓ“”ÙpHàº-jžUl0œÐCÜhx9×jÖWЗQ e Ë´{¸ ‘RßÕYЫ™Ì»u°óùºv~|w¯øä¦îéùûûQŠÏ GY·@Ÿón9“Ì+M¨ÇTø Õ>?ØŽ3æmtwO£3ÏýRè•ãc,lžWù zª¸òì+ïò9ù²ò9B|ËŸkݸñŸc™u8‚ü:ÛÑÓݵþŠî“ö>ӌǧõ…mWµÇšÌHÌi]aá>~›j!À¾Æ‡ÇKk”_­'ƒnŒî…œô3¡xYÏf{yé§à«Ñâ°Ô|•›uÕ cõë³z÷ÓÏÌ”„á‚âvw}ηÓÁÉAì?M€7µã 9ÓL$„g8:PecØE?¦€e7Î4x0+c ®%Þ,Ûê S*”™Iƒ$?R<¶º¥ ‹v…·XM¤â`ÁÈÆyšRލ+á\Ò$PW¢†Œ‘‘å¬Ë<Álˆ/Ή±«yı6;R85dgS~RÕGfãWb-+…¿|`MfÿÓÈ:œR:_a2˜bß=†.,™¯ÄóÞÇ µíU ïH[µH¢‡Îì’ũ֧XDÂþ‡0Q›?ê;M°6zÓOb@sþB¢<?v:JGR6ŒÕ --FR€Pñ©îÕLëIdxIRà_·Zõ9ÕtóR6²Ä5©âÐj_Æõ˜ÅhŸËÓnžó ‰”$-È›HýäŽÅ÷©ä 3Éß 3êa¥zöAâ“ü1èù®Õå  ÿ:t  ™ù"fý@³ jHC~ç´;ÑSÔ*Í"_›žÛ’χnýJ$ËÎîú»¿!¡Ñ„}–ˆõ'a&¦2츂"7¨Q– #fæ’¨H…¥‘ç…>†R3z–fUiW“ö=Ýic§,‚x¥âÉ4ÃXLJ…,L¦Â£ºš^jTøZÔ óç B"›ÞGÑ „Z!ÒEÜíçQÕ4¼r’ûYêžË“‚XË^E¾›fù4ñ/¢7Á,'ž¦¦vZ{bØèñ(è‘H*„ùŒ †[T{|ôxîÖM´Ž~ª™²¶Ìªœ•¥û©'ÕRJ#è,è£9òŒ¦ÓÀŽuXH_‡;Ü•Jçô|n”6ŒY« Ó°+çØüóLKEô¨°Oƒ’&ÑT¬¥J…| ï¹?qÇ–°<ñT©,uÝߣ N¦8…»D“šW8ñ¬½'žÕ(w¨½3Í6LˆFНZ/$gf’sªµ•Û=WZ¯ÌX-©W5T¨5”ûš)‰øà²4ÃÓKñ;™†J¡îA1â,ìN(n•–K–*þ|N9 ÍìÈ»%<ÔÚÔª¹€ÒÌd,湬?·!i³¼àèÔyš´¤M6#­ãg«XtÀ#6N´Â+t@´ðr»T«zo«£æÍs×K2ºªÒðr»i©W"8K'ü‰›ì ijÿtîGça‡¤¹lW#ÜU¿ãrW³¦k,}¬2•¯Iz |JµuLf·mE™ë2{á-#Âæ Xè·Rî«Í£©=ÒÎ!½·šïøŒ+¾µ¡¯Y…Ps£OÌ4±¨)æcT3'óµ~¢*¬ Á·ŠØ*§ö°%|˸qN&hJa‡~-M·rªE ‚Å”Šp$Ðc¿ñ»¨D‘Á µ¢ã ¢'t–±’ôü-©£zÑLæ'TÂ]Ò­²£“"³Àâ9Õa«Wï5X$M iGVô|¹‚ Ië+í+wW nì#-È–ÇÐï—Z´iVëÆ[#žÿüŒ&ßÚ €Õ!iFù«ê!]5Ö®51èLk@"cDQMÂM[1S ·”ë®CËHUpØê}D¦œOÃ2^ãœXD\jµØ\T>ñHªx¥=7Ñ!I£n½êо%¿J"`1äD«É–ɲAì>4»žòÁkj¿;H0gŒ¼%L—]KÖ0RßW‚­,V1 ¤á´àŸZÃ~+·]§òr^T¨·<jÞŠñ…ìèþÜùI2ßjâ$Ôvj`ŽD V™µÊœ5fçÞX§ñáJ.?õ¢¤b3p'ø)ðÜã#<Ÿc®®éÍõôš†iúw¡ªûü“¸ ¹­-sfáa[çæLrtöŽ:bv $íC1ÔõWö†ÁCÀ¸|WBG˜/"rPë{!û³`ïÈqó¿°ÿFÁž¸ñ¿ß47¬ä‘#¡z”º¼2»ŠÛ©nˆ ¦WnªD·Œ$Œý [ÕxHq,vòt ð„*×›muô”Ä"ÐÃL—ãæqšhNÉ‘ðäùFCɵ½ºt+쯰«p_;»f 1FXÕ F ªž UÌ ëÌ4cfžê:£ã#Ž†Ñµ/(=F«H »Ì2J : õ5fv1’îüÑ7v„HÀ]‰Ýj訊æÒ–\i=­4îk=‰Ù…G9+MCØ¡LÈH*[JHÅE¨d„r7Òo¬ÈoÈjÝ`VšÜÔ(°rjW=õü&ÜÂr0»]á ®xõIy=ŠÂT¶·þMòϨ& ¤ð½Ïo8gR³üìo4i”̼s¹;"ÖüRV˜…aÙÛ¦éù«%µ×U× æ7½b§ ;÷÷tVÔpmÕpi÷º#ÐGXý€–ÆvV¾u ­Ô³æ¥ÖHuT‚®°Ý ]£È—š`©æ­föšÎÌÅû[P³îOKÀ‹K¿87™Ý ¹6{ùå=ù%Æ6ÄL Ó%çǼkÈ¡YÖÁÝÏûf|}oB“ÙŠL¢3DÑ¥¶'[‰±î SE…÷jš¬úFvõï)¡!_ÞžŠh¬ÊsŒ,¥*)¤iDuõû‚‚ëÁKL=|ûq] –´è™z2ó^k|ΥəV¼‚Ò.ð©JÌ(ÁÝ8ÀVÝ‹¸ÕðfÄÇU£/€‡nÎ.ù k£79vŽš@v휒Mìe<º2ÆLÃdÖh‡3=i7WÒíŒ'ƒ¯Á·Íli,jå÷¬;«¼O»9ºÙ6qRý½¾¾ÉY7\ïý3Àâûf×OjÂ7«²™BûªIó0õ΂ÿ7r†Ø›Kgýóø'-ûUï×N4Õ¹×$¤²ß& ø·ú=xq6tÿxh+»ük=ЧnÂ`»î…½Axõ›^IT7L—Ï…BãXû¢S@Íåi5cëÎWï5€©§yznÏSÉ2,nh¹å©`˜Ö0ÕOwþUþ÷_ViÍŸendstream endobj 990 0 obj 3775 endobj 994 0 obj <> stream xœí\YsI~ׯàÍ0!˜>8;ôàCöxWžñJrì:< ЄYf~ývyueÓ€äµcÃá0jêêêÌ/ÏÊæs-jŵÈüó“½_{µËÅ^T»Üû¼ÛΚÿ3˜Ôžæâ$oiõ£~\;½Øs3ãZ'I[ݬÖKÛ­(©Nö>ÔãF§žåÿ{Î_§ÿÈgvS>³™f™™ÒL£V/î÷k§Ã|ÒËF3­¿6§æã¤Ñì$Q+вú™ù>Çó5oãúÊ|m5šq”tZý¾èz®Í$oɲn}”/÷ó/|æœúçØxF+?)ëÕ'ØKý l\æ#£~+ŠÛõsl4÷Lãüº[¿ÁÆ ÿDùÈ1 kN±ñ’—ü‘ì¢^ýwl|J#ÿƒ¯©ÑP1Êò/mþtSºƒö9ÍØØ/î²fö©,KzÐZ;¦±·‚Œlî:ù¥FÚí¶º9Œ,Øœ­DÛ2šnF3N[®Á›™hˆdÆ9[–xè\˜ï3óqm>¾rº§– õæ#ÂŽ¿Ív¿—¤c§¸Æ±Ž§Ô¸¬žŠ1•ß#^l×gkßÐ ·B€oŒ©qßÃ"¿ËöϨŸò«ÊÇ1]~ N±H*röÛˆyë„ÅÒZ! ç Ç;ý¬vz´wúËR–ކ„Lö,äSKÁ\ǘK $`Çp Ú%*íF\ 0èúÆ–Dn®%l œK¯Ü’n×›Žï3¿cÝ)¿Wêð;‡­tƒç;s‹<âÚ'äîRðfÝHUc=2\ÎL³Tˆ¡j½ÕèÃFÞrÍÌé4ëP»;Ýr Ý’!ìœ7’ôB÷%=F• ¿¤V†“S’§ÖzI+iƒ^“U”%{¨füBM?â†ð?¸¹à){¢kÔ‡ŒAN{ohjɸy¯Ú±*r}Òø¶ÂÆ;j¼áàÆÉ‹ÚMƒŽ5|¡PMq‰´°‹Èwwº Ü{É—ÖÜËZIATè¸ÌáÁ†fÂŒø5¤ñ¾B)9£>[e®ÉçDäpäŠH¹“ôg}½t«Ý¬±jÒ–Õ@? ãôgCȲPQ—QŽ1ûkìêÌwŒQqþR€=ªÙ@7KF‚X@LÕ:Ÿ‘ݹԈ]iÉG²-5^kTgÞÄoØÿ‚úß•Ø*¤9¢Ú ÆLÒü•i;6oÞyÇ[xûÕ|Æ™çœÚí¬g%Ieªü¿Ò“m¥À¦; Õ¡#€ñ…¼¦Õfló¨È‰öˆ0ŠaÉ%ÏŸN§•€í9'+3V‘\@«LÛ6€‰·SI?·SÖLµS0SC4(K^¹-tAÁwm 7¤0ì\cSÏLUÐЈ¬1O>ôOµ~jl Ï¡‚—¡o=âÈl 5 «rn´#ٷЩ,[Ï„~‘ l’ºzµ†3Ì-j#Çæ*4ÓžG5<Äì‘FÁvˆ3TãI¶ˆ¹2‹õlaÞ$i Õ)¦9‹Š}0Ÿˆü_†®±“Ü4'iÚWâቢ§J¹@CT!°½Ž½•ÏÙ?®côɺ‡BÌñ ÜæÎë÷jshxºÞ]aLºÓPy?•»„R( |3šø1múU|˜Ë4–E'/‚æò©C\;mõÑXQ÷‘:é]«÷Ú/„/ny¾Xcs|¯á#ú ‡æÃf÷)@ƒÉlsaÜþÙÞßbãxu"vÎïáúwºêˆ_=üޱñ¯^j ½ÓæH®µ³nþ¥S%ÜyX9P³ €¥Cð-MúƒZOvC^1pÎRsÿ2Û8CKf-×Ä«·8J{àÜ~ÁÞ±4…,Á„YÀeÎÚ.übFwU¹UÆ‚r¬!ùw uo¨ñ”Ów Å•ðâÊCðÍ£r fZÿ°ÁO0‚‡AüZ_q§¬F™m~怾Õfì&-i$‹•wŠÚ c¦ÄÖFX¿ï“ŒóîPºnr4N3z|i(ÐSÉq¡5øC’?ºcÒ[·1¥ÈLªIȆ…ð±X"!XhLÚ\;$íÃlš ¤w~Š1Ó­Uòsþ0aÙ+õPõ dnë•FÊà°ëá´»j{UÖ&­ÀŽä‰È®2ß&Ì`š`Ia)­ 5CßêøŸ v*»¥œ)¯ Oâ"k}ã!5Ò) ÎNÊi,ñØJõ 6¡¿\vü–Á% çÕ‡43œ´£¡Ð4xœZ.ÖÃéGïMƒSþáÅV§q®ý,æ%ný0żBàŒl×­ÀTNmP Œvô>%Àäêa"¦à¢ˆ£J»Ð•!1 a'+€é͖ΖáêƒÿBxqâ_*zžàä­8¥B¥+Þ>à‡H¤Ü)#ey#ž"$&d¹Óv-@¦R–…;þž¢FR–•*z`éD2Mï=/­ó˜ÃÈåXp @±ù†þÇ ‰`‰ÕC,µ2,ªç)MyÜ 1“›/‹?¡ ¬PVJKÂÞ²‰×Ørõ­]8ÆŒ> stream xœå\YsÛF~ׯà[ˆDD€¸.?ÄŽUÊV¼2½åìfËE‘:Xæe’:˜_¿3Àô…iEy“M¥"ƒÌÕç7Ý |©5èִÿ¹‡Ó£ïϺµ«ÕQ³vuôå(ÊnÖÜ?ÃiíEß<Ŧ%ì5{Q­y”÷ŒjݸÖMZa3®õ§Gÿ®GA»žæÿÿ§ÿ³é•D¼WlM[¦cdþ!ˆÂ^/mõêrù*hÄõÓ ®ÿ´ê'öÇÇ ‘$½°µë/L[4:Û%m›.I‹x4šö2ŠSÓ×ß±ý™vòQûf ó»ÓËg ›ÍvÙNI™á³)McÔêðû¯ƒÄ\%‰[]ÚI¾ÜNܱcBŸìö/4‡}ò½Y¬¹Ç9a: 'LÃQ¦‘4ÃnÔëåššêöOvµ²ÆöÏïîFÔLºõFÐhÇMå®i5¦õ¹ý}é~Ò­íïkx(êYÚe3ØÕG¶hEsj\bãÆtov4»õslœÐ“slRãgÛ)5?ZõÖi¢Í9ÄÆ5®ù’ÝÕÈ0¡× {iÛîX]<옺_Ó}F‘×xÿ„î÷±ñ=¸kg‚ûc±{ÙJR3ªez”„íŽÕ”7Gýowí"ë û'ãŠY^Ü4s;ž^"O× ùätc‚2ò-l½›8‡gò.³ÂqÊX¾˜îkN¹\j2fµ“fF™+¼¿Ô˜}C ld„™aã•]rš éZã°*UÀ"³Ð ¡=hÉ ´ÇÆéÉtâ¥eòì © Œã<»r|tÜà äÙÌbÖ‘3Ö*B¶Ùâ>¢¨û\r2*æ|fŸõcu3"ÎBcÈRkTW§)çR6ç|dÌó®VàN›hDr{K­Uo2=LÚí0'ÄFZÁæÛ…-3âÂH¢Ñˆ{±²nG¶öߺ³$3õO¸ø·ö§õ5õŸàFý¥ýC=~Ň ¡Ònf·¢Ë#2X¿àýwšÁúDo±ñŒâOÒRá6þOÁƼ1£‚ñi Ú½”90ù´dÖwµ;mÐå¹|*x„òNÄk.Í —^ºÃ䇯]’ñþ­Ž­4²½¤ÆßÒ.Ö­IF²AF²÷{r"Z”9n¶Å-ÊM{ƒÄ €»›[6eD˜ýZ]þž»ŽÔ]Gx?Þm×Kô_ŸñjãœÝ G7 Ü*á4x$@m‹áœK!œcƺûAZ5*sΫ`™pHã]‘¬‘¥d†ÜáF{RE^ †øŸµMm°ñN3óKa?h’I3´Näñæ(rŸ¤Ÿ»s<ˬzÔ¾‘ÞOÁÇ‘WྸR—î4¢¯n5®N4ýWQ¤Š•®ÈQ©°ˆT†™ÒØøJø c[‰5ŽoˆÀ$Ϊø8¸¿öµ`„ D‘Ñdè[Üx¢c±ªÝ3ü7ÔxC;lðáÈ’¨Gˆv¡ñn(4F"‘e?áñ×4Ö.Ž  Oê@+Þ=í^˜ ˆ`d¸ûÓât”h‰ŽÊ™'uÃK@Aârâ²’®b÷Cà…°¥¹kÈO֣피Є‡ÑgÌ…£+ y…˜à(æ†p)ÛŠZÑD*G³¥Ç ¥÷6l#ñÑ4eÂZúTäu¶vOòn¡i8¤-5Ž¯Ë «†5>b÷ï…Žú¾Ô¿¦Ãmý¾ÂË.ÿ@"¾•ñSòàWdù™ð«Ž…4"·Ò»p‘Jr"3ËrN˜¡ÿ·š<%þ¥q¡ºJœø§ YÄ%;l¬‘Ô+Ƀ½Í¼Û“ô±T`4Ôˆ¤îWEKÑ—U¨]jK%ŸÃlñwÚœ$ kÁv…/€Hè\{8¾È±ÿ Ô¤c¥Ȫ``ÙR¶ñ8p3R?ÐŽjeÕüà ‚>VZàxN6~’{.âÐ$¿s´)Ä÷yΆ‚k 8N›°¡œã“aý]"úYB ×Ò‰´ÍªT#Ê*§Š'+rM”IJèx‹?‡RœgšèB?p)·(–Ig=ºDâ> G¤ÚË„L9™@}n5*Ó˜kôLûT&-´ÆóI#üæhNSKîãN=Ú’ËèÉ6»×¡ˆ6u¯ñF +UÙ 9Ye`\òãÓS¡²eÏ)DÓÄû6ø*CPy|žñ†DÿUjt +£ºyŸÅ$¥õP£ù…tˆ«VÁ-Ëš©aÉ ³ŠÇGZAÓ‘FµeyKh–¶’T˜K?‚~ˆÅAX¸—ª‡Ä/ñT/$²Š›¦ŒÓŸÄ&©1Ú¯h“4](R9ÇŸÛYüút_ºÊ¤ºÇýê2™§Ù¥Ä`[ê}wU]‘Ò3{tJPöû#5ž`ã{jŒi¨[m'*ì E1?PŸ…ÉfÄnØò [Y‘°| ¨g%5ï%`’â¿£þ*œo¨D8&½RÔD#²Z?!×'$mm¨ñg©^Êx°ŒL8þžsaËRi¦i¹ ™ù`¦ 0€MHÌ„Š7`$% 1ŠÏQ2JN–€Ì8AJ\–6ëðeL$ÝDNº!“EUÓµ¦,G1ÛWÅÙU;lˆN‡LèZa¼ã\‡ÜU «0YyÌ„´KÚµœ"&ˆ° ƪ b•Ï/KEHª(zEÖÀ$T!ÇÝÍ:©àq¦ †ŸªwÕ+èf¯¶EÉD¾Ó¦«­xfo„±Õ ΘÉS’†Q ÎŒÄÕ÷ék¬Ù4t½¸‚d§6…"qÅtª[¡bÈü †ƒø>9¬']{¡¿áîRõ…U×ò˜Gu¥€ÞøH–Ù°¨9 S“f r¨"‚håKü¹)˜²kIº4$,äF!w—m$$ß‚¹W÷Ë2TÒ|ú˜<¤C«újþÏØÈKcžÉ»ž“Fd“ª¾²CõM~ˆ·àAvñúVcK¬— ™L¨Þék}ÀEÍìPëäÅxÿêŸrñ¾ßr£ñÿ«}Ê%ó$o¡-ÿž =wLŸC ÔPõm–3ld_¡Écj±z(õ2[}Bæ…Öç˜ÿ‡ûlMÙ’€“,ŸôF½”óUÿèæ¿ÿô¥®×endstream endobj 1000 0 obj 3326 endobj 1004 0 obj <> stream xœí\[sÛÆ~ׯ`ŸL¦"ƒ+ 8ãù–ȵ×bÜtšŽ‡"%ZRbJªüë‹öÜvJ¶'Ó™Ž'4|°»XìùÎw.»È½`öóÇþ=_|ÿ~Ò[AoyðÇAXÝìÙ¿æëÞÓiÙ ŒJÉ(ò°7=?¨{†½4ŠGã¬7‰“Qõ¦ëƒõÃAÚÏÊÿòAúï髲ç8æ=‡Iš.Ã8MÂ<ïMe§í`÷¯ðgg~.ÍÏÌü¬ÍÏÙ`˜yXþJ‡R: ‚¬nþ}a~V¶[\ÊÃPÏÞ8 “|2ʳ´ºS Ë¢QžgÙ¸êX ¯IX˜édå?’jL|Ü¿+ï‡yùþ¤ÿÐý Ï´'$¼@áL™„嚤qX^«EðÞc… Ïxwÿ‘4£%=²ÍÆI¥û ÖàF i.“8ëÏŘpyîI¶3±NÊWÔíRèÄ^šù í‡a6XhÈY’æ{¦µ,ðê·P–ÑQšg½éëƒéw\K·B#fÖa:NAiâFÌ^¤Ò×§êKÁ¤ëܲD˜šuHK2æ©®æiÇ’¨z¹å”RóÑDÚRýø¤M-ü$Pï㇄sMתù„Éöéôrw„„ú2:jRLe`%aO@;6Þ‚ Ѭ ”@;þ0Àæ4ÿsšÓâ᪄MÔ~ÚÁ~@í¥qïø“üå;#áB[¾•&TzAÏ<׿Dë°¶ËV>“Fú$AjÖ!Ë9¥hWì=Æ@Þã‚C«fC4OI¡·hy×Ö¯rã7b¹l$šŒŒ7Æ—ÉãN¥3’’þEU0ÑL¢kü'Äa‹)²EŸ å„2íàçëâ ]‚€®7¢û Âá«ÂÇÖ–løïÇtÿ…cQ˜i-ie#ívJÂ1 ‡$ÌPàU9·$—ö0ÖÉðuOm\“’L# H#¯—ƒ©{·ZÌG®l‹Ž co‹ Ñ„ô]ÛúØÃÊÔ6‡i^k¬ó= _jg¥©] N4—ÁÉW = óT·ZÍ *œ(pbèUÎQ8î[~ßFA<ËÞþÆ£\ƒœ•ÐCs”kÚJ§Ð-Œg+ÍFEAù®Á\†ÎZ VÆÂˆ2vF_sªf˜ºÕðøÍ×6Át|£=s¥áá¤âïr1˜›`˜?Fᔄ'Ôù^Od¾¡^Ù´ÿ0ã¦4÷6‰FqƒW®#ϨÿWðCaÿ³æ¶aõ –®ÕÃ%1pS˜`™Ì¥Ï¸7WÚ±¼šs·7ôãEÐpÿd{ç¡ ìÎ4ÉMù}j„œ„y§ð!}@h€P¹ <å“^i aðÚP¶Q¨ŠžsEWðIÓQèaæÊ’¶¿P'vÖ½v!¥S 0ñÂ}Ù˜)þ µŸ©«j´Ö8y©ØAâ„æ6äQCó9oÉV×éa¡âìLÃÑRaziXÈäG?ª’¡ } H ¤\–j†Ð´@õUù†; nêUìðÞüüb~^PDZ­…¡Ò:&Ž2…¾Ä9Ól¦( –†eØk°Xu%)¦º{‡P9#ßµÁ.Î*øQ LU­ÝîŸa2 é@ÛVPp™ZüT§.ßZÌÞfBa¬~Üô$xQ™@ó¬Þ¯?²šë¼&–,e¸{ä<À¦:O(k ¥uoT$™egé€WÖ6)/QãNuZ”ì \%ªº_Ä2’z¾ê^ê¨;[¹»îzY“^º°Jî*§tE7Ú¹0}‡!lœ4·Fõí¬ªxÊ¡VŠoP+é-p²±Zrn[Š[ŸkUƒ7Òq[ûý?™iÙÚ·ÅÒœáªPü¾“îRi‡Šã®ÖÖ¡ÅêÆz2¾$p wØœ9•TÕ±õu¥Q•µ©[Ó…6Ð%U'Ó1w=PPL(e…ÝŽM¶Žê…(îÕÕÃd`õP­ò!µaÐT÷‘qöÎB×mY/¬©pypÄ-à­Ø‚«Añ-s Û+M kmõä>q+ž¾*—‘½™Yb¼Ék2½sôk2ÜŸ,Ñ‚®$ílp)a ÈX…½Ü(œºæúò‘×´“ég3ꎲŒÖýÚ“©r£ÙIËÁƒj:Mê.”úÞ9‚ý¨œ§¿+¿2ƲÁ±÷f8¯U*û,=w2"¹1Œ|i§­á± l¢<‚‚¿ÉúïÌOU¤ùÈ=P\%…õÝj‹É$ŽÆ_ÙsÎ)›TÜØT©£¡´äÝ'ø‘„oPøŒ„ïxKßEÒè„úÈú†ãX èÈ·–Ò¸úw X1öÚoþzqöŸí}ü—c¥?”ø˜¤U´;kŸ§zæE?ÍÐd6žU6›ÝCùóAUq‚¦BÜ1…†>1s—YK­“¥þŒ= CG÷_j÷iEGš¿]È‘ì2¿øâ‘`/_=Jðü‹†Wx=•>Q„zq ‘ kÕ<ø1-¹”×ê²Óý_;î?í¸Üqÿ•£¬œÝ;êè{¤­4;XF-_4Òç~ƒ,ç žu5x#”i4xËI“Ï›eYæ\HݰºzÂQdÕÏ@("9ˆùÔHW̧n(tı‡„9:ÎÂfGBV$'Æe”8"$ª³WŠÍµ) æ„–] ÎR~¢e+æDùDmÀ&³¡¶v§!ÎF!–¥w K†üÌãÁP—¢[-ÎÚöI’¶? @†Ê=;mØ„Ö?Ú ±RÝjž©†¥P¡¹oµC·#êã˜U¸¨Àë:Y(Î}guðÄ@ÃjmïH{ˆyNUМ«aµóNÖ—3ýRÎÖ°3ŒÌõó23âŠÐ” f‰5í¬Öy ǰFÛàÀzp¼Þ­¤M{ÃmL#ÝwÔ’Õ?Í U òBtÒeQÔÝj-»”;ßÔerv˜ú´½“š÷Ý©¸ØgÛJúÖj„HÍ·üÒÇÛ…‡,sÙø½Mßà;íd°Þ;¤¸""Ø· ¢ó†8®Ê[hDå¬ÄwsŒz’O¥¸å@a3"äÏ E9•‚h/s#Y~äEéäcÂä#íA!c3yø•Ó¦¥ ÝŸ~Ôh)ÈÇ‚íƒ]cædÊQ¶Ç!]™"K}Ü“‚õð’ØªæLTuWZªHé´2«À"›¨oè*8¼MÅìð  >ÕpŦw¡=Du}KMHP?$´tœdÝho£~A“»Ñú0úbÊ Lí#š°²EÙ3K¼ìñYÄà¸éh·/Q‘Îwh´c^Çoñ_…€Åˆ¨–± ªÛNùÅ ŠïµAÚá—ä‡N‚û[_!tßËÆcÔÒÎ…Ô?IÁoÛ-WÉ;(A œC0´w}Ãà»[êY•eû:«ô¯~.ø î‹ ^ù¾Ç¦zTK†š®ú;3òÓSvæî3SÐ>ûÝʪ“Ý7¹y‹BVOøUs£'´û’ߟ#/8 |¡°B@NHÔ wuï éËZrÖðIk® -(Íený\â!ÊÓ[©[»µeÚÙžYúµ îÔÍÑ¥ºgçûáÌ1Ħ×Þè-z?Xõ¾D œ]øE÷-á]ý b-?>UO9|«S "½úŸ*ù3Üâö&ƒˆënƒ@¾^cá£øjÄ0œ?ØÿÕömÔ&¬-VêÌáØÁ9GébT'ÿ£“ÛÞƒ|úý4kS×/܇kòé$ô¿¦•Å#;Wß]1Xý¯˜ã«¡ø·ÑÃ×)xB¥jÚ1·KeÁ™ƒìªOɬ Ò;á³útçõƒd2Çòæ3oŸ¹ˆzˆ¶"«ž“Ýj¡ÈìTS «Š·ÄE~•\)qŒ0ø6Z‹²Ñ8 BGuÏ=«â¹‘0ª²·)Sîoê{óŽ‚,*ÕÆB¨µö~WZKŠ„ñ‘À3âLwL߉¤&Ž/{¦´“„yb¦AöÅö.µZš]˜¶M äåPYUãÓ‡IõCË€9ÓúOå¡´O g¬bÚ^!Õ-áiE˜²ºÍëÁp§•Nib‰61¶Lõµ%b{¡G¼»˜w ¿zÞû*¯ÜZÙP?Sé/©¶jæ&¹ÔÒX[ ö ßk‹ñ–„?º¸,3ñÐ žKêÛøôÞT§3üuL ×µ¾ÞO(ü™„ï[ÌøÜ1ø?7Ø\ð0iŸ˶ß*sÐ+£OywêÞ‚¾U,AÙb-ø«;Gö«ÐALFZ &Ñ›¾˜ü½üó_op Gendstream endobj 1005 0 obj 3559 endobj 1009 0 obj <> stream xœíZ[sÓV~÷¯ð[%Š„ŽŽ$Kíôû¤BÁIúàXvÈàv Q}Ï}÷Hk;¦ÐÒi&ƒ¢ì¹íÙýöÛ=G|è'1ë'òÇüÏ{÷^ ú›^Ò¿è}è1ÕØ7¿Æóþƒ¡èÀR!‰«¤býá´§G²þ íx'i8ï½ X˜•ø—„ùßÅ(Îð¨Tt-31pX‹Î÷CWU™UÁË0"^‡Q¼ÓàQ˜'ò³0⼊–„,£¢CÊ\ ášñU%ò•¥¥¦Áó0•–…žu(&•^%N’ƒ™NðŸìiÞžºfi3Æã¼@{ÖÞy£””Jó`$3¬sž”Òwe•*3מR:?Mž9á)ï;áÐSJjR;glåãÜu•ׄ[V®e 3Oœp Bpà†.)ÿ:_1Þ(-RÈWä¾Qø „(_=¶Bk±³À\>V ðàZ>œ†Ñ€ç-9¥âCJÅç |¹WEÅž²7v×ÛÛNá‚Æ¤ÔpM_®Ü@×¶0¦°6µiN©ïúÖ jO°Q”º"jw¼ºy›{ÑӢޖ·¯LîaqjIdâuwæC4r/qLœ;7.{Ø\†ŒzÖ‹,LÁxhMÝqêÒC¤Á?ç;l‰«Õ£óœµÐ}Á‰ÂÕ€Ì\Ýrè´'Ùê<$8dD +´•â'?£ÛHÅÑKtq{µ&®†—×`¶Ht/¨÷p¨t…è^Ã+å[Na;ÐÉÊšyàÛO]OÀ5ÆÌ?á~öˆdLò^ä@€óâÀµÄ‚²Üh¿åÈ[ ¨ûEÙÄI²{KK õ~FÔ>&¶&V©¿ÅvÆx–ø¼ ¢8pÆYiIò°f;ÝègÂk( ƒ Œ…3ýKeJ蹃 Èe@W-ðcw­=AzjL™Ð>§„Lì9È[]G~áó¶hJ Éž°Ð7Û%W ®©‰fPȯXþ„(^RŽB½¢,°ì:ª«üÒèu<('!º€Ê“cÔ]†]PÎÀqÿ@ kÈ£¢ …ô†zŠvùTßÚ¨;qû¨©®â ¡k*vZà"Üåij¸D:è­ÖD~1øÕÂÌ”ÈlNžžˆÍ¯ ü–A¼³ÊQ–ý äüYG’s%Üÿ('«,œçpéœ9T£º¬ÊlnÂÛ‚ì^¹ógã¢ß^:a,xß’0Y*Ôx˜ÌÝÉìéã¸ÏB–.á3^í%¼ a“ºöÄ»‘è Ñ  å p4Qñ4Ž©Jö÷ÛJöfÍ}•,|¶¡*ÙæÛ®dAyª’=¨üm%ûÈ Ðw|¸šR5m÷ Úñ5mcƒþ&5íA2¹­i÷[vgMûoÐômMûåjZ¨cþt_oaæÛ„Që?Æ ²ý@}qn [óØP{B¾ý‘ú²†ba‹ÇÛ‚è8˜P3_vóÜà®Üšþ¨}¾ î€"ö«ƒn|o+g&Ôò¸ŸuþR9ÿñ°÷«øù @•Eendstream endobj 1010 0 obj 1917 endobj 1014 0 obj <> stream xœÍZmS#7þNåGøãø*Ìée^4Ù]HH»·˜Ü¥’Åb^\‡ ± »{¿þº¥‘Z÷€mØ«+ŠñXÓjIO?Ýjõø¯Èå@à_ûy1ÝùûÇzp½Øƒë¿v¤}8h?.¦ƒ7#0%òªRÕ`tµã:ÊA­•Ry3Mw~Ïö†2¦)²ûá®Ê•µ½Õ2W¥ÒÙ%Üy#+!Êpß4Ùju%lÕµÎ+Ó´zEUVÙÖ«L£³s»„ÒEm$·€ÞFäBÔa0—;˜€É+À 0 ²—8¾¬¥] œ¢nt¡2RÍòF4š&‡)+ ,½Èn†»V…Ev0H™Ý•ý¿j“}F± |U0%)Lv&Ôy³^q5eö a'T&ì…S²B¸&àKÓ8y7ˆÖv™ ºeÀUª ç$±vâJÊä©Âù•>NønÑ€žƒ(giæ×n‰fÃBð8,5Ž^„ óûxƒÉÒÓQëÒFœ¶åÇ=q¦u?€CíPÑUˆxÁºØf*ïVnÔ1ii#£Ÿü¤ ¬ø j*G °…p\Æ\l@t1 «ÁµMÝÊ€3.øW: þy]¸÷ #¤ƒëW“pëÿäœ.šqûÕÖ¯ccñÛðx†—… =0Ç%ÌC4¿bóyèÿ*Ua2Ù/Ic0·oœQã„k¼ö¸ÈcÜŽ¶‹ƒnwqãø¯JTè=O J¡k/ý,·lüÿSÄ5"JY¯'X½ªÑQÂjc™ªsÈWÚP–j´»=¸b¢²ó|3Q·SAQ"@Fâî(mòçæý3éøÜYºlbžƒS”ÊîO6*¸Æ9ušÇ’+v2xBJ×™ŒõÏ=¼ Û` ª³3¼àÓÔì¨}PÔÂrVâwé¼YWºÔ®\Ú̦àrLË¿ëéß6ÞS#«ÞîÞ6Ø¹Æ IÞrÑaÑŽ QïœC÷’æDÃߤÏa«¦xuNϦD™Ë„mŠìŽîr aMrŒ—ßzLâ²;¡€BÆÑdœ%·¦ ĘŒC"îÝqà_Æf´’v{ayG8N9¬ˆï_IÓAh<$ÉQh†Ë{W¬+Âz£=Îcýùé0·|>ñ³šLÍǾ5âPë¸hû.OìÇ«Öß"äO9Ô2¶Ë¦í>"[’Ã{ÉKvã¿¢‰l„*$9q•.x¾szB¹‡œ…¬;Ñ×¼œs{J6Æë“óŠž›~ÓÓŠ¢2ßæqøÈ?óèÙ÷<üÿ£|Ëá¹X ¬æ‰À iàÆî¿—’Ð~¥´ËßxÌÊ@eiLŠ[”³I-12rׯ„Û˜[»wÌ8°&1ì«„^øSìO_’Tku ’ÓÈúË’ë>ç$Ïcó£ùn“50iü$¦cK.Ò¼Þp”š¶'£_µ¥"[¾åÌ6ãVF¸G‡¢õ7É˾ <¢Ú ¢± ‡øJ ]‡N­¿Äñ;y/âN"%‡±©Š+lMdÍ™àÃÐ9×ÿ–ëD®ñDzÈ{*»™ÏcKtð}Ãì™\Àÿ`ì¦vö]Xw}ä–D‹Ÿ¬"Ú—§Q,zžVž€÷@[DŸõúÓ”g¿ãÝiÀïÌ·9åÓä€o/ÑÑä8ˆŸÒ\(¤QJ°Uæå <™X³©SRÑyrÌË.æ”OØËÏÕu’={yéIdÁÁ@šþ½~²ÇBOêYâGIä-íÛ¤¸a›Ìº/*Põb”†T Ñ”òyº¯²::Ã|â‚BtJx&h<$Я–:¦k•>…w¥1§é3gO6Š';¥?¬ÙHžºJ×iîä­„Ó˜ö p_‡ËѨ)ÛNîŘ벋õt|Af{r”8 ®FqïChÛ÷{I8¢èì_6ù©a°÷X^ȲÂ÷ͯ¸yœ†ç“éy@ŽÇf®8þBiVêxkû™çÖÚu›­ Éï‚ èñk OìIL¦†Pdˆ×«/°iä5‡Tú:pÅ$sá^¯ðL༧éŽ{‘‘q»y²ŠÈ™:uŠÔ2]£t*¶…I›w´w˜Ó––údPMí[WÛøØx^ñLí­Ï[Û»ÿp±’U”ë û#‹2ò¶s®Ó-·¢qâXBÕ3:îem`+?¦ú!5ÎSÖ]5NAÆa9KD¿ ÆÎqˆÝ×´Õlkp%"©9Æsç›×ôs6Êt"bïæCÕJÓô0ì ”#*Q6i0,É<[2mµˆ…E¶˜:“›¶*µUv¿þ®Ô·g¦é7Õ°Èö×3SÞ“¦K!tj‚ŠL°\íÊ7Ëí9ŒW71vS¹f‡gSŽüö÷>Ù:¢3Î)–>ÎÇ5BÊÈ‚œÓÞ-–Ãݤdø\òÍ–É#ª=S2\RHJ¡mËLHTií{K¿ê\[–A|÷—n÷Ì6²†é:UƒP\!ç[1]T!œqV ²Ýrol¶=ØM§%öÝÏâ+Ç’ÞòÉÏC¼§½œw£Pk¤îo™Žgì!G‡_™Êa™5ðŸØg´óøû/¤ýºÑendstream endobj 1015 0 obj 2525 endobj 1019 0 obj <> stream xœÝ\msÚ8þίà[ñÍ@ýØ3w7òrGBškz×›NBÒ4Ó-Цé¯?I¶´»ÖÚ¼ ½éÔµõ®çÙ]íJ¢ŸËnÍ+»òOúoPzyÖ,ßMJnù®ô¹ä©ÌrúOPnõDÏ)µØ½rï})©é•›~¹„5×/÷¥*žS¯Äâ¯ïÔÿíý!j®å»Z‰Š½QxÇñjq…qåÔ©2¯m§êWN¿²ç„•#ùqéTƒ ®¹^½²ëTÃJÍ©6Q-ŽÉ÷¾ã˺âSïÉ´sQF~êV»¢ ?Pm¨Μª+³z&·%ûòq!!ÆãU:òS<5®˜£`P|×å#‰±Dª24ÅGbŒ¾,V8Qã>6‰·iI·YyoÇPò–”tcÕæÄ$~€’WÅÕoÒꢣnS—œ1Î'5NÙ_šp¥†¸øÀu2I^à ’ÜyA­Þ:Ñ)õ~™‹¤ù躎tZÒÑQša“IÂ.­~Ãuto¿r½¡:”œ€„ ¹Þ§"ß‹ÅG€* ¹>§$!‚˜LIþ“¡ê×G;'›Š¯SùØ5¹gf\âͯG%²D™’§Ðÿ.Lû–ƒzœÃTÝä©b",ÓÄ/\KÃ|‘©\gHv•èÒç! ±yf }NW&uJ@ÁŽM®|ó¼%¢1·Ù[JOˆÌê67gö–TÛÅñWæÍ8 ÿ&àÏÊì„›×n}\=Œ…¹šð-5kçG\›=x,ζ FG&¿Ï5Í)ãR¢¾o î˜ÆÛœõ‰tÀbÊ VÂ>Qó,g5Q%¤>#®È29/9ˆHØV‚ŒSQ.ºœ‹HU•{N¨KÃ,(÷œ‘¢«È³Läž›A)zÿN3¼zàSfãmq`Á@аŠð…] À,¹–¦‰e»¶hórVÁ ë'乩xbD’àѨ5tD3Õ=åù@ZR«xKäÐØžZ‚nÉŒ‘„# ª&ÝWýf2€C# ;F†Œ÷Ázšït‘µ8žšÜ7B¤\7”ÒãËoW><©ž¬5e½¾+N&XŽØ6ŸÀÖô99b™°[ºçJN`©øÈ äÉ$>rÂ7&¢mR#þ§áå Ë¡DÅ»‰‚ŸkJÒõØðçXÃ9Ëó~Ïåê7´Ê̺>KJPÆŠr€*,/¨ ·hDX{)È:Â|ƒuàËÊ8+Ãc …Ö ¹ `Н— ¶F\›ˆrÈ•®É”‘ h#F%Á¶¸šÀ¿ŒÍêvÚ†6C²hÆ·Iu‚N½ ‹á:XüÊ­NŽ· ¬4ñ#eLîF¹ ~EÕAЛ)k¸3Ææ•†¶dÙ†(Deƒ¹173Õ»8àªOpI;>As¼ãOfé¢Üç€-ÓÓgŽlj2m'B“Ð22ŸÙ9ÈHú¥É5f.éó ¸òÀŠ_ï¹y²ÛWw9’¬çÉâÀ†R߸D¤3Ï×¾0n*rc&NªvÖßV¸NkX2Qb¢s~å¤öàul[RÏ_°é×ã C¶•\Hå_Q·oS/qö’ö«f{QvÃIQf9T›P4Æh„§®¹±E›q@" H4u”DuÞŸX‡4K¾2;niÐ'³C´(ØÁ Ç%~Ä››nÆQA1<ë^°¶êž„ëð†åÆÉRþÆŒ¦o ÎyK¸ƒ§&휱À=NOP<½aGb©-s¹C¸êõWÖÛ{NQâW<{-$táϬ‚™ öŽÌÊÖ_¥WȆ?^J’æ‡õ§ó¶æìåíöqôYïi£Ëô ”Ü&V¥OE¶£eºgÄý(u)B¯éSèP\¿º% eòÈzš&¢ðå/ÁSÜŽ´b­ C8ÊãP>1i$^'Zì¯`ˆaw ÿ’CýlÇ6ÀZ¯ÇѰ¶sa 6+rC¶EnóP…SIº ¢®0X&!\´§&ò»&ñ„ÞOíÁBÐÖ×íÁÿZµ|Ái–²SDj vÔ¾k‰ƒaáÚç®6$ÂÛžmW?jØ4;0P¿6(ïä9³‹"ÆáÜXÎïJN¹êì–—9TÁûªÈå{§‹uo¿3£/Bę̀øëTú`£L!­™ew}—ªò@#ñš*I#îtr!¢¨ü±ìt¹8mß6ª [xLÁB46`uc@¦–ÚÃG޲»¨½}vËñžÃpþm…u °…9­¤$ê¸=Î.²ØçÆŒÀ‘b'U&²êÐzõÆz©¨šÕrÚ®+›DÄ{«[V³Ýjl¶µŠh¨O¹Þÿ »$:~eóÇþO5DÝ#Ƕx4áÕ„´{ö8‚ÓºŸ_¹ÏÉZø×ÚA@¿¶-EÉWž[Ä¡èäqÖñ!ÝšX¹›7ËD-ý#Ødü@ ˜A0'ô†õX=P€ØÃüÚ"ÏÌr¥Ñò,¼–ˆ:™ûÆÅ µyP¨·[¼°¬y㌽òÍ:Ýû‘‘;2umìcî 3—F÷aW¬yW§áØF=PìxhF†âŒ @ã§1²À:mc7QÙÕ¸‹K¢3 ÛkÑ—’%C °Ytްc>áwùΊLgÉ2hâ!äï™Ä Î5G7æ8 @ :;;&­{»æGÀóbÑZZ Äðžf‡¿g_דeG\Ù"ÎZ qÖÜ&ÎèõFÖžÒÇ4ÝÆüYøš½giùI(úÞì ÐÆ÷9 £†ÂÝJ ÔY1õuã;œ… Îܧ$–%pª[t`¹M{›³AnQñí`Váêm®-n=ír¸®ô$iN‰…‹&ǘþö¹Ï©ÿ$ÿX0Á±€øÍSv'&phXºyŸÂöAõÑM6pˆ—>ËE°Q'WîíH¼Ð?È="²­‚ ; t7®šÏÚªüîò¸Ùíý1ðø;ËÛéG=2ñ½úª8ö.…;6=Êãv[\Õ·IE$ÂKvd6h¸sžIãœ9‹“îþý‡‚E“Ï<í`/”M¹6G€ à“yöÉšg-ÞO¼í1ÍABÆtÌ{äþ°Âÿ$Åù¥ˆbňóÿ߬X_YôˆY{ ÇÏ$zŽ#¨´ÏW†Ü'6À¶…°pìMxüs·Og†h·h­™óÙ¼Sm0ø1t¨ï8ÉAµðšê:ŽA§¦êŽ^Þ”ý‚´Ì^©GtªÝ+½þ¢³­endstream endobj 1020 0 obj 2588 endobj 1024 0 obj <> stream xœÕ[ésÓFÿž¿ÂíÎXÕ}L™.B’§@K‡Éi<Ó;@øë«•´ûÞ[ý$+Æ¡í0kµÇÛ÷{÷.z®ãõ\õ§ú÷l¶ñýQÒ›Ì7ÜÞdãÆW|ìUÿœÍz[㼃çç-Næf^o|¹QŽôz‘8qÚK‚ÐqýÞx¶ñGßDý,ÿ ¢?ÇÏò‘qÀGÃ0r2¿7 \'ñ²¬7>φA_=ž›_êñʼ¾S‘z¼VqþˆÃ|Y¯ï«÷H=¼ÁÐw³@5ÞåïŽëz^ÿ:ot²,Mãþ­i¼ Æ3Óø75Nøðê×”>1'Ôxj¯¨1_(Lãü%êÿb¾ïÒ÷±i|9Fn–ÓªAUãgê¹@ÄusjœòÑ6ôì4Ñ=¹$W?€^àD±wocü]w¤Ž \Û) R¡FÚÍ'ÁÈM,M/õ<§Æh&±uQ°‘ÆV¹G¤½·ÔxN«\#ÒÔ*^–¿J"t+“˜åÏ0Hû‡ÔºG?GÔndm9ò]G­öš‹ŸÂ8È"Ç‹s.”qD ìSOLÌꫦVs•üDYj¦®„dÇHÊ3õbù~Êd% YŽ1ÊvˆcëÃfÊ% d\¸0hNZå[ñJéÕ–Úé¦äÌS£Côad”«è"lJ ¤ xxQàK… ‰‰O“ˆJ¦œI¥L%ýKd¯øÎ vå=OiÎ2IPI‰Û Dçõœ—: ¢Æá£}"1ÌÂ,É¥#RôêÖ÷¥Å®“†ZƒNH+ØÎç–‚”C¤‚ 1Ø1mcóË€O¸—»Pv JS ~Dàï¢ý^!‰˜p XO­!çèû¡Û]b{4ç…`fAHößöÛÅ‚æÿ‚¦ºå¢{bËy*è·ÄEÁ-Ä¥Œ4pÒT ÆÛ%åסq²M206x;‚0q]ul…@ÓµAMAÊ/ÂôWGÂ9iX.@‰×3¤Ó 23Ð$œêÛ,hÛ¸bÑÞÞ¨×ÃÊÈ w YþÝàr%ˆ:¨p¥M1#í¸Õ”Ÿ“†<¸cß^ð  ¶‚‚ÇóíT/êQgÎÄõÅȫ"ô0Pd¯k$qh>f+Ýð¼XÊ|ˆ¸Ìd~ ÅS¸Í-ó’û¦qL›¦qKDºUãH9äÜÕ¹iî…[cš’dZ&ŸpsÐïÜ. Ù¤wbª"FL3Þá’Ë­ š¤¬t!™ùÚ…LšµaÕoè'Žç»A³3yj^MÛ¾yUö±Ê×õîZn…ÂG¦$Ç“Mc ˜™ÆS Å<¼ü±` e`:Ú%|Ûù½®{b-¨y´‘k¢y [Ü‚y^¹{a)´hýLÝH4/‘_ M°¸~Ι«8ºoìÃÃ=]–_Éf¬~I6ƒØÊlÆ‚o£•Ìs²§ Ž…Þû ô‘ÏT÷Tlø5Zz>mZ(Ï/–Ç©Ú^!ÂÏÈÊ¥˜Ó`Á¥Z\&>Ú‚\²LÞÓÆBÆÛØõ™‰ ‘(ïq£JtJ2?† ÀKä­,x¯«Ï§vBBIKk¬Up´¯b.Fš ´ÂóÔÊ:̇°a÷5©’¸ç -ú:2þª«1M#›#t`UrŸÀ›÷E¶§{~Z›û‘„½Úç)s…oh$Íò‹”j¶9ý¿ t¨£Æj”¡[½Èº*žÀØ~„ÊÌ:ã„È~…Ã=0–ôÁø¥ fvÍC8%‰¬ÎCðfÈì¾GÖnNÆr¥J§(jêA®³bñ¶idÑþ.™z(=·K¥µLй±™,%Cxì™¶'Šm” 3Ë…Dü©‹2^Ï·CFE0î˜ ¶W®ó­R$êÁB”®¸!ãh•J·¤­´ÊæV]H “Üræ±!È2 •ä¼É@3§Ã¯ÌKÞ£5ç$+0$g†LrVªëÕc[]±éL¸õ( ²”ªÐÄœ ½Ýkgźÿœ•ˆ5Á ÔOà òr2¢V,¢¥¢$Š¥]dÉ"tÔð”àAu2ÍûeÌë~¶w!æ·`òBX¤Æg 0»0ÃÛ|ÓoFÎŒo"§eŽYyXð›…é߯A¬ {§â¡ZeÞ0B‘AÝE½_.4'dÝýŽ(W";ö­``}QøWƹd&. ãs„Ó¬å÷P˜ò•ᾇ³&)0ÖO«vrß ¡CƒÐk`¥ì¼Ö·Ü>Tá[´ñ™4è3báª:¬„å„7Ö{Â0—¸¡±?Õ¹€›˜‹Œˆ•à™ˆ0¦è¾’+°¿å¢2E$¥N «#/ñ%¦, XŸþQ<ƒÂMjuýc%«ñ s²xa}'S?i»žÆ äNV¥pÓ(ÙnMq~G<ÊùIæg!bÌ{Õʲ+¹Y±'w­Ž^ŠKv@Džû‰”Ücc—èÜS{1—ߪo!Ñ誔3ó·bú–Ùh™ì›½;Ôë 1jŠV¾FÅi×[Ò m¢S,R|ºH>àîW®C^ºøµÅíŠï†æµÀ[ÑÑ6 ÷1–XÙ ]€S¤zn„W÷-†ðƒßvÉj¢Õ”$ ÒX4ðë¡Èë¶Óµ[uŽ|/Áë…6ÇÇf.2þ”øí ¨-11Ö”ëÛ‘[xç¦ß¨ÆQ¦@ò"›¼¯Ì&¢ =^Î,LLlƒ90Œ ëb?i€=±§Þ5³ÒµNšTÊèä°œ|W#¥yÙ¦€i—-¶Ëœ©1~«Ÿ¶)`öõ«–u\=†^:›âœŸ9›'r)+#·L•)›”ë¼Q‚žr®Çbe?ö•Ëc(L¿¯õ?C÷GO“†õ~:»n*;XGZF''GÕò9±°òz»Žk×ö;øµzý:ìYçk”õ“£F‰ ¢LýP”„æ‰O<éP«©ˆ^ßušI&õôë¢ޏŒ<)&Ì;ëˆL(;Á5G²¬G·:R†ÓÀñËÛ¿¥Wg98´W &ëHùZ¨ÅÂ*í×o/kr !«tƒvÜ”ôÊ·I±4³nÑ|Óvœ@ÑxYÉMrÔ>`±¶¸ÎÁ$˺Ía™rd(nÚÖ†¢¤íȘ òÚê?ŠDIƒ ÈZÀ ×íü]vÅcŽzÂbvS^+…Ý(ðòß 3‘ª0µ¾§éÕEtÝ|'… Ë¥1ÐÌEðia½'ñ :g*X·ÒGã_ó?ÿäñendstream endobj 1025 0 obj 2457 endobj 1029 0 obj <> stream xœí[mSÛHþί𷓮Î^½¿|º"@¨ì±À³›­Ý«+bÉ/6þýÍH3ÓÝÒ#ɆÛÛJQy43õÓOwOOóû(˜„£@ÿ˜¿³ë­ïNòÑår+]ný¾V7GæÏìzôjª:„‘j™”Aަ[õÈp”G£ú«õHÍÅÕÕNüq o…Q¡®cÕÍôRo„I¦;Ī9£j.Õé©‹XR=·ý2¨ždºŸª5A…ºwWý«Õ™ûúùjdV–ê½ìUµÕ?Ußó<ªe—Å\vã(' „qLò°,kªÙ¼}ýq¬?þ¥?NõGuC/]Ï«Uª]×åG½µž°î¼ç†í¹.¯m[Ýï@UI–ê/vw2µv#õD]f‘§7s÷Ïèþk¼¡ÆO®q¥(xƒÜ»C=o]ã95ž¹Æ9 ¿vŸ:†W=ÃD?Ó4~ žçüé©z!=gX]zWîÞGñbú2‰‹jn3â7¿¥5΂I‘X¨¥a©®ô–ÔO{I­Wb¡æRÏ>ó|’Æa¬S}X«î»ªõ·('™Ó߆öiëžtjŸÄdmÿf„UrN2\£A4=³2b¸üù0šÆ¥n¡® 6çJÀÄÌàë…a|Yx§Ö'“hÏùi·\¿=·ÎCm¼•©ÔɈ:²‚„T•ëš~›Z6×ÒÛ+$äy['žéO ÊA3¿÷™öYdY©L ¬Â`²]U´J%ù¨ƒVæ¦äU§6È‹4ÇPçõ9’_íF™Ä´Òê(ÈÖ1cƯ©gHµ «6W·ÚRIX=ò¬ëm*ÆÅ aO²N˜áýY¨> õ¬…7ÓÝw.PtT>ØšþÃ÷ ÄiÛŽÛªsš')†´ Hß#žHÏ(/]ã2¶î„Î’_ '/yÏ^®Oˆë§hКžTQñѹÀkÈå3éF¬”ãÅL°#ô#ÐYÝ¢žg|±(±Û~‰Ý’MƒÌ á0òÐð·(ò•¼vÎÙé0Ÿ>´dÞàÓâs#àÞ0‰û¼áÔÙ¿8sx(ƒË#÷ÎSi6ß ‡YŤ®Ÿ²Ý[žr æüO“l¬sƒ­ÈhÈÒ$µ'%ãºBŠ3'Wô¡_e¥ÿ‰rµë bk¹•ªÂóÈÈ-ÍSµç õ^0öý¡6NQ ev['ó¶] ³÷…ˆ+&8`¡×¹F \ù˜À\XÊ„)½iv¸©º$–A—G=ï!ŸYHùòM²¥ágZ¯ûÑŠÖG‹%–CòvpÿâZÏôBÚË/a/Í¥##÷‹ÒÖ0$Ž1á8;ÿâôg·@ç\úh]ãÒ§[¡„v‹qßÜ pjÏ”3-Z’â=°ŒæYÔÔ¹êÛ‡ãóSûÖ×ïÀb[¯Ï¬6×8ùð†K+Õ€²ÁNߟ™Ô]6ÉÝíJ =67e¸Øi|I¶1›ã0lXåôØ‚}!Æ7p×`·wìöw×ÁV¥Ê_9(÷€õJ4eÓ¢(fßPÜÅy :¶5Ñ(¾‡0Ÿ¯莋„Þ H(J$ô AaÄ5iå¸u¢×¢âÏ ÑfáµaÑ%X%àvp埸9Z1寤ɢŭ³ßа¼Àž1ItÐÒ½gÜ•Á ]é`…ò&<‡e1âàe}{€F&:ÕK€Ö ØF PONe]°~öÈ;IãÊŽ@’gÏ%Ÿˆ AÑÆ§Qi°*käí íiÞFEm¬ªÐ¹ï'‰Pl2ÚfÃX±Í´ÃWHp×høó=¨g"Kc'ͧÆTNW}ýÅ)4±ä›¼]ÒAâÜGìK×Oë{D¯·BÊòù‰§‡PSðÅŽ1á <õï"RßÖDaý!ʸ ·~|Ev6ö¥Ÿñ¬-EȘŨƒÁ¡³Æ{¤<°Nª‹ÃÖz l¤Ç»)þRU Û´<Ò‡Ä&;+Ã’vŒWçlë!2gÛ¯îÆ¾ks1`ýB;NKŽ:IÌŽfî‘$àI®4††;®_áÓœp÷Êd–×Ñ3¥ëÁ|ÆFÀ…®ÐBEé„-5>²V£Æ¢lŽ>cÕµyÖñ±¡ÕY[Я®Ž€íN-èÌ*ض0# ?;¸Y#æ6Îì™Fö‰…xvøåX"x…/²{Q¤eíÁ'¤¬d&´“©´Xln­=ˆ³ÐêÂM›úúî&ÜïLrQM‰2"ç_¡ÍNn†6ëëïÀ^¦ºÎÎþà? +‹¥ýú ÚU·ÌJ=7@»g/¸9 ŽÍõú*;.ÙÜ2æìL‡4áÉzPY!Ž®_#ŽéÓ60⨋½E¾¢kÓÏ¤ßØ|l;ùïÜ(AÞ’ÌjÎ7û>1+õÇíº¢XN.TÒ‹hÇæˆaaé¥ßÁ“ˆïû„Íüª™°+nAïÂ×^þFRí:Ö¾´ñš™ÌŸq|ëÚ~rý4üY’H07(;zY°¡í:ðlóõÌ.ëñl´w· 4ç玮5#iDëý³}2ŠÀ»P em*š`c¡ì—˼ ÀÖ»}5€áÿ¤®µe…Êòõ 7›¸®KÌc ó÷¾ËZÌ,d…Ür./: ÅGѧÍK®‘o6ØBÇ÷²êôµÌ®;ˆ8êEV°ŽèÿÚŒ>¿j…"T훇b« ˆ«H‘ÿ|Ò å¶c\ƒvïQ­Õ¬$hY J2[ ÂÀøï3‚àµó> /Contents 5 0 R >> endobj 16 0 obj <> /Contents 17 0 R >> endobj 21 0 obj <> /Contents 22 0 R >> endobj 28 0 obj <> /Contents 29 0 R >> endobj 35 0 obj <> /Contents 36 0 R >> endobj 40 0 obj <> /Contents 41 0 R >> endobj 45 0 obj <> /Contents 46 0 R >> endobj 50 0 obj <> /Contents 51 0 R >> endobj 55 0 obj <> /Contents 56 0 R >> endobj 60 0 obj <> /Contents 61 0 R >> endobj 67 0 obj <> /Contents 68 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 82 0 obj <> /Contents 83 0 R >> endobj 87 0 obj <> /Contents 88 0 R >> endobj 92 0 obj <> /Contents 93 0 R >> endobj 97 0 obj <> /Contents 98 0 R >> endobj 102 0 obj <> /Contents 103 0 R >> endobj 107 0 obj <> /Contents 108 0 R >> endobj 112 0 obj <> /Contents 113 0 R >> endobj 117 0 obj <> /Contents 118 0 R >> endobj 124 0 obj <> /Contents 125 0 R >> endobj 129 0 obj <> /Contents 130 0 R >> endobj 134 0 obj <> /Contents 135 0 R >> endobj 139 0 obj <> /Contents 140 0 R >> endobj 144 0 obj <> /Contents 145 0 R >> endobj 149 0 obj <> /Contents 150 0 R >> endobj 154 0 obj <> /Contents 155 0 R >> endobj 159 0 obj <> /Contents 160 0 R >> endobj 164 0 obj <> /Contents 165 0 R >> endobj 169 0 obj <> /Contents 170 0 R >> endobj 174 0 obj <> /Contents 175 0 R >> endobj 179 0 obj <> /Contents 180 0 R >> endobj 184 0 obj <> /Contents 185 0 R >> endobj 189 0 obj <> /Contents 190 0 R >> endobj 194 0 obj <> /Contents 195 0 R >> endobj 199 0 obj <> /Contents 200 0 R >> endobj 204 0 obj <> /Contents 205 0 R >> endobj 209 0 obj <> /Contents 210 0 R >> endobj 216 0 obj <> /Contents 217 0 R >> endobj 221 0 obj <> /Contents 222 0 R >> endobj 226 0 obj <> /Contents 227 0 R >> endobj 231 0 obj <> /Contents 232 0 R >> endobj 236 0 obj <> /Contents 237 0 R >> endobj 241 0 obj <> /Contents 242 0 R >> endobj 246 0 obj <> /Contents 247 0 R >> endobj 251 0 obj <> /Contents 252 0 R >> endobj 256 0 obj <> /Contents 257 0 R >> endobj 261 0 obj <> /Contents 262 0 R >> endobj 266 0 obj <> /Contents 267 0 R >> endobj 271 0 obj <> /Contents 272 0 R >> endobj 276 0 obj <> /Contents 277 0 R >> endobj 281 0 obj <> /Contents 282 0 R >> endobj 286 0 obj <> /Contents 287 0 R >> endobj 291 0 obj <> /Contents 292 0 R >> endobj 296 0 obj <> /Contents 297 0 R >> endobj 301 0 obj <> /Contents 302 0 R >> endobj 306 0 obj <> /Contents 307 0 R >> endobj 311 0 obj <> /Contents 312 0 R >> endobj 316 0 obj <> /Contents 317 0 R >> endobj 321 0 obj <> /Contents 322 0 R >> endobj 326 0 obj <> /Contents 327 0 R >> endobj 331 0 obj <> /Contents 332 0 R >> endobj 336 0 obj <> /Contents 337 0 R >> endobj 341 0 obj <> /Contents 342 0 R >> endobj 346 0 obj <> /Contents 347 0 R >> endobj 351 0 obj <> /Contents 352 0 R >> endobj 356 0 obj <> /Contents 357 0 R >> endobj 361 0 obj <> /Contents 362 0 R >> endobj 366 0 obj <> /Contents 367 0 R >> endobj 371 0 obj <> /Contents 372 0 R >> endobj 376 0 obj <> /Contents 377 0 R >> endobj 381 0 obj <> /Contents 382 0 R >> endobj 386 0 obj <> /Contents 387 0 R >> endobj 391 0 obj <> /Contents 392 0 R >> endobj 396 0 obj <> /Contents 397 0 R >> endobj 401 0 obj <> /Contents 402 0 R >> endobj 406 0 obj <> /Contents 407 0 R >> endobj 411 0 obj <> /Contents 412 0 R >> endobj 416 0 obj <> /Contents 417 0 R >> endobj 421 0 obj <> /Contents 422 0 R >> endobj 426 0 obj <> /Contents 427 0 R >> endobj 431 0 obj <> /Contents 432 0 R >> endobj 436 0 obj <> /Contents 437 0 R >> endobj 441 0 obj <> /Contents 442 0 R >> endobj 446 0 obj <> /Contents 447 0 R >> endobj 451 0 obj <> /Contents 452 0 R >> endobj 456 0 obj <> /Contents 457 0 R >> endobj 461 0 obj <> /Contents 462 0 R >> endobj 466 0 obj <> /Contents 467 0 R >> endobj 471 0 obj <> /Contents 472 0 R >> endobj 476 0 obj <> /Contents 477 0 R >> endobj 481 0 obj <> /Contents 482 0 R >> endobj 486 0 obj <> /Contents 487 0 R >> endobj 491 0 obj <> /Contents 492 0 R >> endobj 496 0 obj <> /Contents 497 0 R >> endobj 501 0 obj <> /Contents 502 0 R >> endobj 506 0 obj <> /Contents 507 0 R >> endobj 511 0 obj <> /Contents 512 0 R >> endobj 518 0 obj <> /Contents 519 0 R >> endobj 523 0 obj <> /Contents 524 0 R >> endobj 528 0 obj <> /Contents 529 0 R >> endobj 533 0 obj <> /Contents 534 0 R >> endobj 538 0 obj <> /Contents 539 0 R >> endobj 543 0 obj <> /Contents 544 0 R >> endobj 548 0 obj <> /Contents 549 0 R >> endobj 553 0 obj <> /Contents 554 0 R >> endobj 558 0 obj <> /Contents 559 0 R >> endobj 563 0 obj <> /Contents 564 0 R >> endobj 568 0 obj <> /Contents 569 0 R >> endobj 573 0 obj <> /Contents 574 0 R >> endobj 578 0 obj <> /Contents 579 0 R >> endobj 583 0 obj <> /Contents 584 0 R >> endobj 588 0 obj <> /Contents 589 0 R >> endobj 593 0 obj <> /Contents 594 0 R >> endobj 598 0 obj <> /Contents 599 0 R >> endobj 603 0 obj <> /Contents 604 0 R >> endobj 608 0 obj <> /Contents 609 0 R >> endobj 613 0 obj <> /Contents 614 0 R >> endobj 618 0 obj <> /Contents 619 0 R >> endobj 623 0 obj <> /Contents 624 0 R >> endobj 628 0 obj <> /Contents 629 0 R >> endobj 633 0 obj <> /Contents 634 0 R >> endobj 638 0 obj <> /Contents 639 0 R >> endobj 643 0 obj <> /Contents 644 0 R >> endobj 648 0 obj <> /Contents 649 0 R >> endobj 653 0 obj <> /Contents 654 0 R >> endobj 658 0 obj <> /Contents 659 0 R >> endobj 663 0 obj <> /Contents 664 0 R >> endobj 668 0 obj <> /Contents 669 0 R >> endobj 673 0 obj <> /Contents 674 0 R >> endobj 678 0 obj <> /Contents 679 0 R >> endobj 683 0 obj <> /Contents 684 0 R >> endobj 688 0 obj <> /Contents 689 0 R >> endobj 693 0 obj <> /Contents 694 0 R >> endobj 698 0 obj <> /Contents 699 0 R >> endobj 703 0 obj <> /Contents 704 0 R >> endobj 708 0 obj <> /Contents 709 0 R >> endobj 713 0 obj <> /Contents 714 0 R >> endobj 718 0 obj <> /Contents 719 0 R >> endobj 723 0 obj <> /Contents 724 0 R >> endobj 728 0 obj <> /Contents 729 0 R >> endobj 733 0 obj <> /Contents 734 0 R >> endobj 738 0 obj <> /Contents 739 0 R >> endobj 743 0 obj <> /Contents 744 0 R >> endobj 748 0 obj <> /Contents 749 0 R >> endobj 753 0 obj <> /Contents 754 0 R >> endobj 758 0 obj <> /Contents 759 0 R >> endobj 763 0 obj <> /Contents 764 0 R >> endobj 768 0 obj <> /Contents 769 0 R >> endobj 773 0 obj <> /Contents 774 0 R >> endobj 778 0 obj <> /Contents 779 0 R >> endobj 783 0 obj <> /Contents 784 0 R >> endobj 788 0 obj <> /Contents 789 0 R >> endobj 793 0 obj <> /Contents 794 0 R >> endobj 798 0 obj <> /Contents 799 0 R >> endobj 803 0 obj <> /Contents 804 0 R >> endobj 808 0 obj <> /Contents 809 0 R >> endobj 813 0 obj <> /Contents 814 0 R >> endobj 818 0 obj <> /Contents 819 0 R >> endobj 823 0 obj <> /Contents 824 0 R >> endobj 828 0 obj <> /Contents 829 0 R >> endobj 833 0 obj <> /Contents 834 0 R >> endobj 838 0 obj <> /Contents 839 0 R >> endobj 843 0 obj <> /Contents 844 0 R >> endobj 848 0 obj <> /Contents 849 0 R >> endobj 853 0 obj <> /Contents 854 0 R >> endobj 858 0 obj <> /Contents 859 0 R >> endobj 863 0 obj <> /Contents 864 0 R >> endobj 868 0 obj <> /Contents 869 0 R >> endobj 873 0 obj <> /Contents 874 0 R >> endobj 878 0 obj <> /Contents 879 0 R >> endobj 883 0 obj <> /Contents 884 0 R >> endobj 888 0 obj <> /Contents 889 0 R >> endobj 893 0 obj <> /Contents 894 0 R >> endobj 898 0 obj <> /Contents 899 0 R >> endobj 903 0 obj <> /Contents 904 0 R >> endobj 908 0 obj <> /Contents 909 0 R >> endobj 913 0 obj <> /Contents 914 0 R >> endobj 918 0 obj <> /Contents 919 0 R >> endobj 923 0 obj <> /Contents 924 0 R >> endobj 928 0 obj <> /Contents 929 0 R >> endobj 933 0 obj <> /Contents 934 0 R >> endobj 938 0 obj <> /Contents 939 0 R >> endobj 943 0 obj <> /Contents 944 0 R >> endobj 948 0 obj <> /Contents 949 0 R >> endobj 953 0 obj <> /Contents 954 0 R >> endobj 958 0 obj <> /Contents 959 0 R >> endobj 963 0 obj <> /Contents 964 0 R >> endobj 968 0 obj <> /Contents 969 0 R >> endobj 973 0 obj <> /Contents 974 0 R >> endobj 978 0 obj <> /Contents 979 0 R >> endobj 983 0 obj <> /Contents 984 0 R >> endobj 988 0 obj <> /Contents 989 0 R >> endobj 993 0 obj <> /Contents 994 0 R >> endobj 998 0 obj <> /Contents 999 0 R >> endobj 1003 0 obj <> /Contents 1004 0 R >> endobj 1008 0 obj <> /Contents 1009 0 R >> endobj 1013 0 obj <> /Contents 1014 0 R >> endobj 1018 0 obj <> /Contents 1019 0 R >> endobj 1023 0 obj <> /Contents 1024 0 R >> endobj 1028 0 obj <> /Contents 1029 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 16 0 R 21 0 R 28 0 R 35 0 R 40 0 R 45 0 R 50 0 R 55 0 R 60 0 R 67 0 R 72 0 R 77 0 R 82 0 R 87 0 R 92 0 R 97 0 R 102 0 R 107 0 R 112 0 R 117 0 R 124 0 R 129 0 R 134 0 R 139 0 R 144 0 R 149 0 R 154 0 R 159 0 R 164 0 R 169 0 R 174 0 R 179 0 R 184 0 R 189 0 R 194 0 R 199 0 R 204 0 R 209 0 R 216 0 R 221 0 R 226 0 R 231 0 R 236 0 R 241 0 R 246 0 R 251 0 R 256 0 R 261 0 R 266 0 R 271 0 R 276 0 R 281 0 R 286 0 R 291 0 R 296 0 R 301 0 R 306 0 R 311 0 R 316 0 R 321 0 R 326 0 R 331 0 R 336 0 R 341 0 R 346 0 R 351 0 R 356 0 R 361 0 R 366 0 R 371 0 R 376 0 R 381 0 R 386 0 R 391 0 R 396 0 R 401 0 R 406 0 R 411 0 R 416 0 R 421 0 R 426 0 R 431 0 R 436 0 R 441 0 R 446 0 R 451 0 R 456 0 R 461 0 R 466 0 R 471 0 R 476 0 R 481 0 R 486 0 R 491 0 R 496 0 R 501 0 R 506 0 R 511 0 R 518 0 R 523 0 R 528 0 R 533 0 R 538 0 R 543 0 R 548 0 R 553 0 R 558 0 R 563 0 R 568 0 R 573 0 R 578 0 R 583 0 R 588 0 R 593 0 R 598 0 R 603 0 R 608 0 R 613 0 R 618 0 R 623 0 R 628 0 R 633 0 R 638 0 R 643 0 R 648 0 R 653 0 R 658 0 R 663 0 R 668 0 R 673 0 R 678 0 R 683 0 R 688 0 R 693 0 R 698 0 R 703 0 R 708 0 R 713 0 R 718 0 R 723 0 R 728 0 R 733 0 R 738 0 R 743 0 R 748 0 R 753 0 R 758 0 R 763 0 R 768 0 R 773 0 R 778 0 R 783 0 R 788 0 R 793 0 R 798 0 R 803 0 R 808 0 R 813 0 R 818 0 R 823 0 R 828 0 R 833 0 R 838 0 R 843 0 R 848 0 R 853 0 R 858 0 R 863 0 R 868 0 R 873 0 R 878 0 R 883 0 R 888 0 R 893 0 R 898 0 R 903 0 R 908 0 R 913 0 R 918 0 R 923 0 R 928 0 R 933 0 R 938 0 R 943 0 R 948 0 R 953 0 R 958 0 R 963 0 R 968 0 R 973 0 R 978 0 R 983 0 R 988 0 R 993 0 R 998 0 R 1003 0 R 1008 0 R 1013 0 R 1018 0 R 1023 0 R 1028 0 R ] /Count 202 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 14 0 obj <> endobj 15 0 obj <> endobj 19 0 obj <> endobj 20 0 obj <> endobj 26 0 obj <> endobj 27 0 obj <> endobj 33 0 obj <> endobj 34 0 obj <> endobj 38 0 obj <> endobj 39 0 obj <> endobj 43 0 obj <> endobj 44 0 obj <> endobj 48 0 obj <> endobj 49 0 obj <> endobj 53 0 obj <> endobj 54 0 obj <> endobj 58 0 obj <> endobj 59 0 obj <> endobj 65 0 obj <> endobj 66 0 obj <> endobj 70 0 obj <> endobj 71 0 obj <> endobj 75 0 obj <> endobj 76 0 obj <> endobj 80 0 obj <> endobj 81 0 obj <> endobj 85 0 obj <> endobj 86 0 obj <> endobj 90 0 obj <> endobj 91 0 obj <> endobj 95 0 obj <> endobj 96 0 obj <> endobj 100 0 obj <> endobj 101 0 obj <> endobj 105 0 obj <> endobj 106 0 obj <> endobj 110 0 obj <> endobj 111 0 obj <> endobj 115 0 obj <> endobj 116 0 obj <> endobj 122 0 obj <> endobj 123 0 obj <> endobj 127 0 obj <> endobj 128 0 obj <> endobj 132 0 obj <> endobj 133 0 obj <> endobj 137 0 obj <> endobj 138 0 obj <> endobj 142 0 obj <> endobj 143 0 obj <> endobj 147 0 obj <> endobj 148 0 obj <> endobj 152 0 obj <> endobj 153 0 obj <> endobj 157 0 obj <> endobj 158 0 obj <> endobj 162 0 obj <> endobj 163 0 obj <> endobj 167 0 obj <> endobj 168 0 obj <> endobj 172 0 obj <> endobj 173 0 obj <> endobj 177 0 obj <> endobj 178 0 obj <> endobj 182 0 obj <> endobj 183 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <> endobj 192 0 obj <> endobj 193 0 obj <> endobj 197 0 obj <> endobj 198 0 obj <> endobj 202 0 obj <> endobj 203 0 obj <> endobj 207 0 obj <> endobj 208 0 obj <> endobj 214 0 obj <> endobj 215 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 224 0 obj <> endobj 225 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <> endobj 234 0 obj <> endobj 235 0 obj <> endobj 239 0 obj <> endobj 240 0 obj <> endobj 244 0 obj <> endobj 245 0 obj <> endobj 249 0 obj <> endobj 250 0 obj <> endobj 254 0 obj <> endobj 255 0 obj <> endobj 259 0 obj <> endobj 260 0 obj <> endobj 264 0 obj <> endobj 265 0 obj <> endobj 269 0 obj <> endobj 270 0 obj <> endobj 274 0 obj <> endobj 275 0 obj <> endobj 279 0 obj <> endobj 280 0 obj <> endobj 284 0 obj <> endobj 285 0 obj <> endobj 289 0 obj <> endobj 290 0 obj <> endobj 294 0 obj <> endobj 295 0 obj <> endobj 299 0 obj <> endobj 300 0 obj <> endobj 304 0 obj <> endobj 305 0 obj <> endobj 309 0 obj <> endobj 310 0 obj <> endobj 314 0 obj <> endobj 315 0 obj <> endobj 319 0 obj <> endobj 320 0 obj <> endobj 324 0 obj <> endobj 325 0 obj <> endobj 329 0 obj <> endobj 330 0 obj <> endobj 334 0 obj <> endobj 335 0 obj <> endobj 339 0 obj <> endobj 340 0 obj <> endobj 344 0 obj <> endobj 345 0 obj <> endobj 349 0 obj <> endobj 350 0 obj <> endobj 354 0 obj <> endobj 355 0 obj <> endobj 359 0 obj <> endobj 360 0 obj <> endobj 364 0 obj <> endobj 365 0 obj <> endobj 369 0 obj <> endobj 370 0 obj <> endobj 374 0 obj <> endobj 375 0 obj <> endobj 379 0 obj <> endobj 380 0 obj <> endobj 384 0 obj <> endobj 385 0 obj <> endobj 389 0 obj <> endobj 390 0 obj <> endobj 394 0 obj <> endobj 395 0 obj <> endobj 399 0 obj <> endobj 400 0 obj <> endobj 404 0 obj <> endobj 405 0 obj <> endobj 409 0 obj <> endobj 410 0 obj <> endobj 414 0 obj <> endobj 415 0 obj <> endobj 419 0 obj <> endobj 420 0 obj <> endobj 424 0 obj <> endobj 425 0 obj <> endobj 429 0 obj <> endobj 430 0 obj <> endobj 434 0 obj <> endobj 435 0 obj <> endobj 439 0 obj <> endobj 440 0 obj <> endobj 444 0 obj <> endobj 445 0 obj <> endobj 449 0 obj <> endobj 450 0 obj <> endobj 454 0 obj <> endobj 455 0 obj <> endobj 459 0 obj <> endobj 460 0 obj <> endobj 464 0 obj <> endobj 465 0 obj <> endobj 469 0 obj <> endobj 470 0 obj <> endobj 474 0 obj <> endobj 475 0 obj <> endobj 479 0 obj <> endobj 480 0 obj <> endobj 484 0 obj <> endobj 485 0 obj <> endobj 489 0 obj <> endobj 490 0 obj <> endobj 494 0 obj <> endobj 495 0 obj <> endobj 499 0 obj <> endobj 500 0 obj <> endobj 504 0 obj <> endobj 505 0 obj <> endobj 509 0 obj <> endobj 510 0 obj <> endobj 516 0 obj <> endobj 517 0 obj <> endobj 521 0 obj <> endobj 522 0 obj <> endobj 526 0 obj <> endobj 527 0 obj <> endobj 531 0 obj <> endobj 532 0 obj <> endobj 536 0 obj <> endobj 537 0 obj <> endobj 541 0 obj <> endobj 542 0 obj <> endobj 546 0 obj <> endobj 547 0 obj <> endobj 551 0 obj <> endobj 552 0 obj <> endobj 556 0 obj <> endobj 557 0 obj <> endobj 561 0 obj <> endobj 562 0 obj <> endobj 566 0 obj <> endobj 567 0 obj <> endobj 571 0 obj <> endobj 572 0 obj <> endobj 576 0 obj <> endobj 577 0 obj <> endobj 581 0 obj <> endobj 582 0 obj <> endobj 586 0 obj <> endobj 587 0 obj <> endobj 591 0 obj <> endobj 592 0 obj <> endobj 596 0 obj <> endobj 597 0 obj <> endobj 601 0 obj <> endobj 602 0 obj <> endobj 606 0 obj <> endobj 607 0 obj <> endobj 611 0 obj <> endobj 612 0 obj <> endobj 616 0 obj <> endobj 617 0 obj <> endobj 621 0 obj <> endobj 622 0 obj <> endobj 626 0 obj <> endobj 627 0 obj <> endobj 631 0 obj <> endobj 632 0 obj <> endobj 636 0 obj <> endobj 637 0 obj <> endobj 641 0 obj <> endobj 642 0 obj <> endobj 646 0 obj <> endobj 647 0 obj <> endobj 651 0 obj <> endobj 652 0 obj <> endobj 656 0 obj <> endobj 657 0 obj <> endobj 661 0 obj <> endobj 662 0 obj <> endobj 666 0 obj <> endobj 667 0 obj <> endobj 671 0 obj <> endobj 672 0 obj <> endobj 676 0 obj <> endobj 677 0 obj <> endobj 681 0 obj <> endobj 682 0 obj <> endobj 686 0 obj <> endobj 687 0 obj <> endobj 691 0 obj <> endobj 692 0 obj <> endobj 696 0 obj <> endobj 697 0 obj <> endobj 701 0 obj <> endobj 702 0 obj <> endobj 706 0 obj <> endobj 707 0 obj <> endobj 711 0 obj <> endobj 712 0 obj <> endobj 716 0 obj <> endobj 717 0 obj <> endobj 721 0 obj <> endobj 722 0 obj <> endobj 726 0 obj <> endobj 727 0 obj <> endobj 731 0 obj <> endobj 732 0 obj <> endobj 736 0 obj <> endobj 737 0 obj <> endobj 741 0 obj <> endobj 742 0 obj <> endobj 746 0 obj <> endobj 747 0 obj <> endobj 751 0 obj <> endobj 752 0 obj <> endobj 756 0 obj <> endobj 757 0 obj <> endobj 761 0 obj <> endobj 762 0 obj <> endobj 766 0 obj <> endobj 767 0 obj <> endobj 771 0 obj <> endobj 772 0 obj <> endobj 776 0 obj <> endobj 777 0 obj <> endobj 781 0 obj <> endobj 782 0 obj <> endobj 786 0 obj <> endobj 787 0 obj <> endobj 791 0 obj <> endobj 792 0 obj <> endobj 796 0 obj <> endobj 797 0 obj <> endobj 801 0 obj <> endobj 802 0 obj <> endobj 806 0 obj <> endobj 807 0 obj <> endobj 811 0 obj <> endobj 812 0 obj <> endobj 816 0 obj <> endobj 817 0 obj <> endobj 821 0 obj <> endobj 822 0 obj <> endobj 826 0 obj <> endobj 827 0 obj <> endobj 831 0 obj <> endobj 832 0 obj <> endobj 836 0 obj <> endobj 837 0 obj <> endobj 841 0 obj <> endobj 842 0 obj <> endobj 846 0 obj <> endobj 847 0 obj <> endobj 851 0 obj <> endobj 852 0 obj <> endobj 856 0 obj <> endobj 857 0 obj <> endobj 861 0 obj <> endobj 862 0 obj <> endobj 866 0 obj <> endobj 867 0 obj <> endobj 871 0 obj <> endobj 872 0 obj <> endobj 876 0 obj <> endobj 877 0 obj <> endobj 881 0 obj <> endobj 882 0 obj <> endobj 886 0 obj <> endobj 887 0 obj <> endobj 891 0 obj <> endobj 892 0 obj <> endobj 896 0 obj <> endobj 897 0 obj <> endobj 901 0 obj <> endobj 902 0 obj <> endobj 906 0 obj <> endobj 907 0 obj <> endobj 911 0 obj <> endobj 912 0 obj <> endobj 916 0 obj <> endobj 917 0 obj <> endobj 921 0 obj <> endobj 922 0 obj <> endobj 926 0 obj <> endobj 927 0 obj <> endobj 931 0 obj <> endobj 932 0 obj <> endobj 936 0 obj <> endobj 937 0 obj <> endobj 941 0 obj <> endobj 942 0 obj <> endobj 946 0 obj <> endobj 947 0 obj <> endobj 951 0 obj <> endobj 952 0 obj <> endobj 956 0 obj <> endobj 957 0 obj <> endobj 961 0 obj <> endobj 962 0 obj <> endobj 966 0 obj <> endobj 967 0 obj <> endobj 971 0 obj <> endobj 972 0 obj <> endobj 976 0 obj <> endobj 977 0 obj <> endobj 981 0 obj <> endobj 982 0 obj <> endobj 986 0 obj <> endobj 987 0 obj <> endobj 991 0 obj <> endobj 992 0 obj <> endobj 996 0 obj <> endobj 997 0 obj <> endobj 1001 0 obj <> endobj 1002 0 obj <> endobj 1006 0 obj <> endobj 1007 0 obj <> endobj 1011 0 obj <> endobj 1012 0 obj <> endobj 1016 0 obj <> endobj 1017 0 obj <> endobj 1021 0 obj <> endobj 1022 0 obj <> endobj 1026 0 obj <> endobj 1027 0 obj <> endobj 1031 0 obj <> endobj 1032 0 obj <> endobj 31 0 obj <> endobj 24 0 obj <> endobj 1042 0 obj <> endobj 12 0 obj <> endobj 1043 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 1044 0 obj <> endobj 514 0 obj <> endobj 1045 0 obj <> endobj 212 0 obj <> endobj 120 0 obj <> endobj 1046 0 obj <> endobj 63 0 obj <> endobj 1047 0 obj <> endobj 32 0 obj <> endobj 1033 0 obj <>stream xœµWyXTeÛ?ã8Ç£!š:Æ”Í`åšn¹kйŠûB"‚€ Û ›À0û9sŸ†d‘q!455óUs«Ð·²,«·Ô´´çŒÏ¼]ß3 Yïõ¾__ýñ]sq±çÜ¿û¾¿ûþ="ªgJ$õ X¼"hœ¿ûÇáÂ3"aHáY1`ë#äÔJÀK ^=›‡Hï @çžD¹ýкþ”X$JPé3’c6G+}GFŒò7uêä1¾ãýý§úΉLމßê»8\®$¿Äù®Hˆˆ‰TføŽœ­T&NóóKKK{)<>奄äͳFñM‹QFû.L‰LNÜä;?a«ÒwIx|¤¯ÝKžo ñ‰*ed²ïâ„M‘É[)Š6gíÜu!ó^¿`á¢À ÅK‚—._±rÕê5'½”Œzšò¦úQý©'©Ô@j5œTêIU‹¸ò'ÅÄoõ×ó”dÍз{½ÁŒcêzÇöéÓgKá‰3^ê¾¢¾Û½xßíÝß»eÿ_ŸÌðä€ÑÐ ¸3pÙÀ ƒbÖÛ©ZçÕˆZœóÅB‰s‘”­6çmƒ,0™tÛð)×?}TáÑI Ó˜s9 SË¿ii‡¸À5™x=Ÿß,Ñ.Ëë(KY£¢f_ýÛM zų¼XYl $ËÍ:6Û¬eÚ¬a/쇃掜勬å|!³®Ø°‹ÁB¾ô$¾"Á*º ™SäÕ;ËÅB”0XŠf¢×+kÚý2›C²ÙÎÅB¬‡+y•) XÞ\ÈÉ:ôÖdÐÚhÐjðsx¦Ï´\_ °È ¼©r?osølf`$B¿ÉBΚµœŽ© ÏA©¾2=ƒ|p$†°5Ú0u罛ﰴB;‚v¶+oS ;e`å‹Ë*Ð|åƒzáœ|5p`–Anrz¨¹ûÍmÖIÚ;à¬yŸ;mK1_b)f2é`È*Èjf¼kI.ØÑ>‡H¸~WŒF;gKqå°*Ì2;[Á ôœÖ¬›à²û˜RXu¼140ÆùÏÐh=¼ûõŒã‹÷ª¿û¾f>›ý>ö–ãLÜ)í@ÛN¾ðÈ}»bÖæ©óüqo‰¿’&¤C­,Ö튃¨A‚Ó÷+ÇGøÍõÃ=뼜 bçáséÁSÇó÷¹ëÇE˜!–Y’x’1NÒV‘•ž­ÍÕk8 Ûñ`´ßP6àeM‡¡QNÚÍÎHˆƒÅ|”¥ëÈ(1m‘¡1ø»l?.+ÓOÆ©YUºQeŒƒXwb» Wö‘ÏEØí®·Í‘@(™f‘©,ê<¨…Šf4Ýæ®]”ÊáK`RwÅN»ó5i¡Áj0±ËÉ93kä¸U‹}t:0›|x}Aè‰å5ÁÀà8¯Á8ɰšôi§ãíw·®—Þž)ÖóFVZN®ß6g^pðÚå™k€‡½N E倦ƒú+Ÿÿêä÷À ¯“˜Âb™<¯à5…O¸VyVÆ[@°KøÕ!:)<;Ÿw>#-)sÿ‡)1@šÜµœÁ*Ií@Ã/FO“7ùÑ.µë‘Nc2‚Z–kƒZ¹F¿‡j$Ét~>j"¸'eäy:ãœô½ú;\¡h´‚05mEF ~Ø_/zèÁܦoÿ°ûešð™CW¬ÌhúwŽx;gžžv Ö]¢Vç±3•H“éÕxNÈ*<Ž`ü‡‡ßBÕ’›ôûÍêÕil›©h  *’Iö‹ ©™@·#£­Å–ˆðòIÉw†cQd˜ÕäÉ"¤’¸NÓ„Wvú\©>•ŽÓ*Æ»v·pêi SÑÝš>&Õð% 9ÐA7¨ÑbÔ‚®HoÐç›Õk2ØL6ãqà,ÿ´$?`&Ó¨ð·À žmšé¿Ç=øgqÝT·^!¬Ü_Á^/%[èêB»¤]AjÔ r l‡0¬›’KQ¨4¿Íf;ži÷·Ñ¼ ‘O€TØ ©Ò}©R¯âØ N£0%êÂXrÙ+ÑÀŒÅ}O¡ù€^ù=¡8óÅ·o}NˆÂ¼÷Q°²Ÿ[Ýt;ˆê}º¨o6«såAsãÚCúƒ oÂð:œ† )î¦ß¸¶ëènE‰ª%¢„«µ‚ñì€3´ËA*¸Wì Jm-y%W±Ó]Ú}…hwÀf÷¨ížåµô…b}jÕ‘8C‚‘–jmKéuýÅs„£ÿ^ÚOȜܗ<’ï^©tPN¾ÝÊç󅊨R‚ŽÒa¸êïóFÿòh¦I˜,Fׄ$AKé `êÝ@7³3 ÌM0¢ÿ´Žþ äw uÆXƒf:ÈRÜwwq`\¶®€…$`£¤ô…µ–"w@g•'`«s¿Xˆ¦HQ$š}éÔ ¾Žw¯¯D6Ž, Í°ÊÒ/á÷™·fd«u…‹ÂÇŽ£ÿŸKÙŒ^E2Ôƒl» ›6?›Œœ˜PH—ãª,»¡d|à:̲|ÇzHâ“˼’¯ÅNI—øã0‹ŸÀó€™ññßZ ú²@Ö⩯l$ègÿ%ô¿i»Šö~4ÒpÏ£¥bô³s„ÔXgæɤ™Nÿ——Lv±¦]è°Ç+»›¬l;œå]VÅ!I™ïxtKh‘ðDþÿYÕM ÈŠ!¿ÈVˆ8½}xz´ë£?Vs·õî~¿{þ—j~-4{$ãéžA§€ rÓð9×)ŸÇ»Ô-/tÇé'Õm7óJ’Ç´ßòØA„JS ëïêð1%ë†Á_Èá¦PnÓÛ4V£ wÝ(Èæ¹b•o³V}'÷Ék,<ø}m!^)–XâÜûÚ'©ë„ÕFàØmŠy®YBVU£sJƒè—{BÒ±³^%E p_Ôûã¼’|)ñ+¨ Q(Z‹BP†Ü%w “Ž˜ö5òÛU€Æv"JñÁý/ÛÎóù½`ÓVྠoáñ@þM"¤èDbá‹nd0s¹ZyèòÔ–7öظ¯ïsø •%|w˜ÂÕh¸žz-Õç\RÞ"Èdf,ô3|âD—åUA©¼„8÷\³1“•ÇàPNK,-+3X…<_\(?xÊ®<°þ²@Ÿºú£>5ÜÑÈƒŠø½[ ƒ·Gû¤Ùb‹ô–Øò¸]p”¹Üyù&¿={h¦¹¶É5 +µÚx‹UNœ8¼G„ÄN±G–Ž'Å"KT‘-×{wæˆD.…M"›¹Ú½™½¼Ë1íG~ÅûÐDØuo®ål,q†:ç©õ1nas†IzÔ`9 û?÷áMÖ=w#é—·Úyȳ”¸-.©ÛSdQÏþRì .K+&’[oŽ%ZâÿC1Ëðr³Od~ÕȧÊ­UŠ÷…Qœÿ÷Ä^ì’°¹2<èîÄ ÁˆF}´VîVëJ€ rn;#ˆ÷¶·ïj<½w,,·¤t{ïcåI™ŽÓe)ðvWª¯@îRf+äÉZÎ@ƒÇzÏ#HÖÁj‹ÒsâR¹¢2$uý’—fe·ƒ¬,yEÄ <*íŽ;ðQºø‘N¸.-­¯Ý…ï¾±D²«‰‹Ž‚ Kï¹s™xÒY¹ù„ž¤ªeõF-NwEøÌ2¹°ÿ¿ë,ìwïÇhöU$6ðaž;À)(a ·Éòt¥ AKÞl4äâp×r%ã¡ 0¿j¬§ñ¾¬Z‘L/ÀÉ)ê@MbÔ‰8)®¢5Ë$DÞ¨Šþù‹½qZÚ’\ž“¯¬T6ït4îrç­µ–4ˆª„bá¸s½´°Ì£+M‘Æ 7ghä.ïsõ9næÊÔEº’R[q‘­«v§]tõcôî%±P/¬•ÞLD±/ŒûF¤ÉÃ_Vâ©ðTŽG¡±×¾x õ>&?Žž(FÓ¡‘ÁÍ®µÒØÀJÔób;ªjùT±ïÖ¹²À츨ƒ¹1›4K%¯ªÀ#aã@è{ô™Xæø›úË´ –Ï Gjíñ\pN6NtUû㸜±ÀÄyœÇM"ýv¸ùož?žž™ûøîGb\FÜ#tðC´á–XHFs‰IæôiÙ™&“Él4³° >díž÷÷/uì9~èôyø†AâñÇÆâ!Óð€EmÆ’ææú=;2* f0›ä­çßÛs ˜OZW,˜; Â^ ‹×k4ÆÈ– ½÷ÎBùÿŒ§uÝ’Ö@Ôo­R$Àfdî;*zfé¹Dù}kìfê²ê£3Ök¾üÙêÛHŽ($ypiÍù‰Õrä½çíûpœ9ûÚÉøÉ9“–¦—¦´¶W·6ì€ùá“Wó*€9Ж²"E³0bµ"rm4Ʀ“ œÁÌšÀÀh  Zî­² •hkI¾ÆK{9ú\}BÞ§çä¯Þö"//Šú È: endstream endobj 25 0 obj <> endobj 1034 0 obj <>stream xœ¥X T×¶­¶¡ª4ˆJ§DÔTã¢q ÆÄÅ §VA!€„yTd’îÓÍ$80£BË(”8ÆÙÄÄ!FWò’gÔÄ$&1$æ¹äÿb†•¼õÿZÕ‚j¨Ûuï¹gï}ö¹ Ƭ£P(¸K\ÖNq2}´—G(ä‘ýä—”@6Ž4Ów/7 %X˜5´é°Âî!˜3×f” Ehtڂаøˆ@ÿ€(Ûñ[l§Ìœ9c’íT'§™¶óƒý"·ú„Ø.ñ‰ ð ö‰¢¼m»2tk _T¼íøYQQa¯Mžû²OpäË¡þs&ÙÆFØzúEúEÄøùÚº…†DÙ.õ ö³í[ÞË}·¡ÁaÑQ~¶KB}ý"B†™>?Ä%tAØB×·H÷¨7¢ßŒñ‰Ûâ¿5Áw©ß²·–ûx®\õvðšéίÌxuæ\ G§)S§1Ìhf3†YÎŒeV0ã;f%cϬbÆ3«Æ‹™À¬a\˜uÌÆ‘YÏ,d60®ÌdÆqbÜ™)ÌÌ›Ì4f3qf–0K™WÊX3Ãf8cË3–ÌÆŠQ1/2Ît3&‰ù^±Mq¾ß‚~•¢2^ù™Ùl³/ÍóÍï²ëØì¯ÜVî>¯ÿþýßà8 yÀ½PlÑÏ"Ôâý“-YËðA#… =8fpÝÏ!?Z¹Y=V%©½øâ3!v耡ê¡iC¯[Ï·þBδìî í$yQ©¢¥ûRéž.$Wï„…Ý©iñDßóݰô¤ÌÔ¹ÀÇhØFý C-4Á;p,ó¤Å‰ÓN‡"}V^¯>‰ͱŒ½DìÌ'ÑY_C4Ãhè8#_ÉA²¤ÖœÄ±–ÝVtÞ§çüVÈÒËYkU;ý 䊛†;¬¿dh¤ó\ÔÖ™¾î†~*îw^­/‹™+’ŠRÈý´ºÉ~¢—çÚpQuŽÌK5×pªö+yà«¶ì¾H§l7âÉ íÑÏâh¡½µJÆZùà"îéÁYçlX2Al‚€LÉ»—à.ÿåô‰³Øã¦A¦ç!«ú‰0Ù—Å×>{ðí7Î×É ùjgrM ØŽ^l)HPï}ÔVB2¿È‹d¬h)ßJo–UFE¾ˆyø¢Rn‡O~JfWÆ2ø=¾Ž³>ŠƒD²‡xDÈ|Þ§Ô«K޵–uB+´&–”Â*ØÀO•hÙ}3Y’‘×ÐQÎìTvçuOJ ?>E«MKß\¾ääÝÁ†ˆ#q >Äé ¸ Íqr¥iú„) S§‘ádàR;˜ 3*×\ÖœßyÁ;YÈ\}ïÝ÷>ß{š®¾ž[NTYqzmðÕzC5ÝS+â%á(£¬8·µÙêM`¾h­úÃð_”èõÅÅÍ-§sË¿þÎRbEF¹®Y´]g7©“‹@%ül³¶€ã»Z€Ç ?J­zÒÉWSiþüÔ=úJ:gù‹9HòCIAs:R¶F{%Úw«„ž‡¦,-àpN nÃ02²^Ýã¢a1³ç¡ ?D;î=ø4®Óµaíwxˆb§WЦ îÓ—oÙ½›Â¥A‚3¦WFgIÙí‡ MÄЩd ðd6œc¿)𞯖°^ÃÎOñž ®ÂœÄ¢3T»ì'y‰}ÓÍU˜Àó)]S·k)ÓWá˜Uçè–1ÏÐÒ„ýÍøH@s޼ö[ľê^&4èÛ Ð×ÀØK¤é¸€SݽQ…–ß‹:]|"„ð[êbkjêʚϬ®Y#ªÚ]aëº(€?¥BÂòߘ,áK4†aݳ„žž/‡õ)‡N@ÀŠ“Ü7ù¿•JƒZ‡åhk ªbÎ>ÒŸe)¯K7Ê#ê¬[}nâNúËšRÎ%á­¼E{Aâ¯<†’;!«rD}’>£ øJÈ©PÌ™À¹[ q¾bxQ@îVàƒ Ýyë­¥a¥ êæ€Æô»ÛyÕCcúˇϛ Ñ£Âo·í3Š3`;ð‘¥& .Ræ`_™¨‡ò}Y†Ž ÓP |-¾ h×ÛpX­ºë[”;»ˆ·üed²ä_†¾’<@²2ñdŽ^ßi­JêuF¨ »ž|1íSãÆ%. s:øÂ ‡ÕYt;48ÖŽSI!¾QáIAéAà Î5ë¯xŸÛq¾4+½p¬³ùäÝcßÀÏ'qf£Ë…k(ud2±'[ÉG&ã^µ*é(tN^á-å•éÍøßÎ-UtQ6 ”]ò(âl?¾ùQûùÛâÍZÎ=(2t\«±†Š7±Ã•Ng¿~üøLÞŸ2bM|“„…R_â?ÄÑÊî4J d$Ö/Ó¼éå~}ñ1¤|ˆ…ô÷÷g½4â³¾¥bÞßBcDlÂIÓ??ã¨*¤ýÏPyÿ“¸ÇÉ‹n ³9tÍ5—¸%iФVµËT¢ÿ÷•Ü̵^.s2«ÎŠøÕ_žlçl?‰þNTÅUÃ-è¸G·éßI?Z‰­¦ØX‰ÝB׿‘^°¥oý,]?«áZè;èõ-´ô­‘å,å®Ýeò`IQ-ŸRÊY²…[œw x‰‹Ð†è" 6bô¦·p%5™©:vwŠšð$‹¨°Úü¬ÄnÓNÑéh•ÜdØÒ;ì‡ z, #Š l@AVA]ç;éÆ` —AG£UöŸƒCpºi;bäw…·aãâ ¶´*+vÀõR=ýnOAópá»ÄÁ“Xîž¶¹!îPm]Y둸™ñpn¾ø; >sÕ— 3I^ 7|"Žÿ@TÅ| RKy+Ÿ€S„IÜÄÉ;"Önm8Ž N->™EËPF—¤(—/)ñ;Ô Ø‡çæ} 6ùÚ5º ÷:Ch_ÜÅP¨-LÛÚÝ»g8s@μYbÃuÚ ¢qoëv“C'âA¬‰}Bœ?lªY†Óú¨‚ ÚÒ^•æâãrrõ ÏÛ£~‚ ìG†šûjØjýeÃQ¨ƒvíÑÞQ û€\&¿dÄçþ¨&I¸M'`ÇÕÀWÝóDâ:ß1Wu¦îé\ýp:tõVǯÈ8Ê&XËç’sfs‡NÔœ£ÆÈ@W ¬ ÷U‡lÙ˜®à{v×>ª”î  /Q´îÕùT·2•¸?–ÖŠ»9“(`=l»¿òC¾a‚Ñå to‘ëÃS^qVž"µÁÅ“¡vêvïÒéÔ„£R ÂŠÿ€§e=£¢6Dor_6ÛA«OÍÊÏ®(†þhde`hHœïZiË¥»®œ?Ds»‡ZŒAÍŠFj1\pˆ{ä‰B|¢6RøçºOøÜÄ}>–'6_M—ñ•#Èço‡]ñ:íŽ 1ÜcCÜZZØÔ€öïE¡á@ff‘š¾še3jad¥¼šæcÏ^ƒòù²í/ö(Ùd¹ÄævÕ»€ÿ7Kêz˜”dÐBŠMt”ˆò`ö n2×°)v‰KÉ0àÙ¾lK²²7Û¦u瘘‘$¿Ò&¬çpñïB!ÿôçÌ“5œª³iÝšÜm#ˆÝèidöå$O³~NTÖVñxÕŒdq;â·¬¢ž•X¼qÎV7©kZ¥‚Z8ÍAå!|¯Jö%ýŒ¼ûŒÏv; É…:} ýR¼)µ—XˆÖéB3#3µ4-|„©Vž§Þ£Nÿ¦#\<$èã !Y:Z‡x¹”“3z>-Ø©×í›C_¡–ïpP®×ΪÌ2Àaà«LìI Œ¬ùM¤ª¸ƒp@wP[“©×A4ßã@ÁTI‹€ÇQ|­Ï1¦~­”·PÃX^‡jÓo¯;©~ËèuЮsúô±dþýtÆ©mÏŒƒŒmFbº:fƒgÐ":b”mN©ššô­eG«›› kûƒXë(ðLnéf[zÝã|tTv7ã—¾MÆQkA≚Œ'o‘­hKÆ`,& ˆãÐGì1#—…åàrxËGÛ®¤Þ„ûp-ëßÇßo¹|½ê"õ)„6¿Ù¸8{¸ƒëî©>n›\\£WSC…?öª†Tw˜‡8H‰ýååÂ<ÍÒå¦aÿîtº“ÈÀ§öû(¿*'´ybRrjÄñÞ qÕGêÊZZýÛg;Ƈ˜S+|ˆ¾O vþFä:¶"•W–j‹ÎÚoü¿ÉkêççÔeÿ¡|ÑïÈpìÄ,N€¹ Â2‘2àÙhÄIßÜ4bT‹UÝW®¨Ä…¨„®÷­U?'ãô¦Áõöv¸þ༱i¼1MM,w ‘§´UTÆž»wCŠ8š´_}d™a¯^›¡Mt>â@|uõ’ÊŠ„†IšÌ€Íb|¡OÙ|𼱫f»n)ÝRG½p7¾-f8$e¯oÚ‘éüÚsóPƒ®÷.Þ8’zõzqåáe0ÂiÌÐoÎKn„ƒP½/w…¬¦ZÏÖ¢9,ñ÷]M†‹õ—®B±º·ëã âyµVÒb*ÐŒüº°µ+¶F‰øõŸ™kÙÝ•lŒ°Öˆµ½=ØHLÁ ¶èøÅIkU"ñWkq‡Î†ÙKW«d¦'ÆÈ9õ.¼Ç?%ý>#ËÅžÁ¿'ÏH“G»"š<ãs_RË©NÒH‹©§­ ¬  ¾ÍÞ„õ7G_ÙMÛŒŸ‹í/§r£ÛµC§ÎЄDÃ2H¹™ÑªÝ›ú.gûUµÞû)Xoõö§ÑÉê­o±V=Æ(ÙK .¦€.þnÐkõ†V8§´ÆÞX©žÈ×…ãþõ>ÞÞÞ m­Æúã V´Wû¯6«k훞àOæ´[«nËvòTŒ«Ýš¿².Û´¾òýÇOÉÈ 1;´Ïm3.ԅìJ7m^ѱ(ŸZ2iÁÄÑ‹Žn,‹Vw®¯OCE$¯zü€ú„ò˜}IUü†p·1sɤRtHu!'ú¹…^Ôk¡ó †¼=bGÇ{ë§·€ μ‚æOÕªÛ€Ê×>q*¡úÐB±qï‚¢UÂ4ʨTZ£ºg¿:³1$Ê}>š|‚c¿Ûs8jسY”éEogûRâ(ßûˆÃ1PðzaMƒigå‡l<2JŒê^$ü¹¬Ÿ¤;Z§?a0q²C[ÿ{“çù—㟾kUçÿvdðyç•úòØ9ÿ ¬ÿ‡!…\×Ú–±NkÖm cOÎòƒéà¹)ȃ§]îïG }iV•ZÖÍJŠÊ‘fQÊ_ÎÊDÈ= 7Ôf•Ê`¿É „é´›À–€¯úsUpj’ɼž•È«¼ÉüS…p¤&ÜfA@ï˜û\Ë(2’üôŸŸcÚ¯ŠÜÄì]U`SÙ¹ûÑEö†.=^ù/õ£&X+$ÙµT·©KW “ðDš ÏdisBctº¤"ù¡çMs ¶13ü/zOr>ÿã$‡¥_"À"àUsúÊä¶Ë”Êcp°ÕyþêÚn¦’(ãF¹YÉø¯Ì ˆÃ¸Ã{µõT í¾Dóª<íÞ™:جöŒöJ÷†¹àUžŸB«i&ðÛ!9QMÚi‰ÝQ^dÈÞ“'6uœ- ~Ó^W«~q{bé‘sÞG4j*¡…?ã½/2iMÊÒWƒEÕÏ8ýÛGh©î]!vOààê&«´ˆ-Å!¶8ÒZÕƒøµP²emyû*¥³ÆËT3ë3+¢ü3âà ˜¬mjª¬n¼âsÕ”‚™Î$GTý³ò_oq“æ~yƒ†¢þæ_8mín“jUO4¬Ÿ¹üO䪰šR÷'ÖÁm8Èã³Ò¹¯až½Ì·3%—ɹ8DqMú—)íòc¡`/¨¹#ÞlûœíÙ1Ùº|m¯aHe[ÁGEEÙ†½¹ŸÀ:ílvÕ¢‰Äld¼ë;»_ÊyOìààDÖ‰<)ÿzÙņ¾7xù÷ýÕwðÀÕ÷M}ú9RHÌ=õüGyÍŸÜâ¾>èqo³¨z8ã­Ížó‡“ȬE§òû!3CZX$sÝ…†x)ìÜÛÇ#ŽÅÀ~†c¢§ƒç©{÷δ5”öÛV†C:øÌ”€‘¶´ Z†/™ 2Ï Ñ¸¤,O LðõÞäñào.-Ì:V í|}Ôa_ßÈp?÷Sž´ÚÅ)Ÿa>MÀuÀB²‹ŒÿNÄïæá šîòoðD¹E˜w¾ÿ>þùb…×®luá6ÚÏòáãfе4:Ý(Ã}8¸Öhu ‡ìD';é¦©Ï Ô2èz|¹±¼´ðÄ!¸Ê£@Üà-¢^æ±xñĪºÚòÉ»H««KZ ;€ÿRï«Ùœš«^²(t,âý¸hȨ¨„ÜJQõì,qÚ¼Ÿ—¶††6±ïè³KÒœ¿†ª£é£õS…9)‹´Û¯Ì…5yÿŸ”PžÈ‘…é´OÐÖFõ)±ÿ–ýìýÆ/kÊ2vTˆ éa °•÷­ 7«©j9½ùéG“±¾¤¿hÿ›Ëúû+±‹Nºak§> endobj 1035 0 obj <>stream xœµz xSå¶ö¡Ù[„"[ZÁ&™çAAdÊL)”Ž@KÇйM‡´IV’Îó¦MÒÒJ™„dR#" (¢(GQŵëW=ÿ—´E~ãùÏsïÓç $Ù÷Öz×û¾ëÛ‘0Ý»1‰D6oùê ãmÿ*ö“ˆý»‰/I=‰ñu[¢ô”BÏîûúosƒú`so\÷#•Hv‡&Î Š Ùáë6`¸çˆ¦OŸ:zÀÄñ㧘à²ÃÓc÷€åa~Þaôÿ×@ÏÞa‘†Ïô š1n\xxøX€Ð±!¾¯= |G˜ß€ÕÞ¡Þ!{¼½,Ü6àMïöŵ¿Î R†y‡ Xèå²›a˜-svo˜¸q^ЦùÁo„,]¶H¹xÏ’p¥Û—Ez.òzÓ{…ÏJßU~«w¸î\³k­ÿº€õ“§ zeêÀiÓÏòêËCÝg s>{Äë#7ê9º×–1ÑcÇm?aâ$ÇÞÏ2Ì f3̬df0C˜UÌ«ÌËÌjf(ãÊ cÖ0ÙµÌf3’YÏŒb60s™ÑÌFf3†ÙÄÌgÆ2›™7˜qÌf<³™À,b&2‹™IÌf2³”™Â,c^a–3S™7™i ϼÀ„3}g¦ã¼Ètgú1LFưL#0³ƒy†Àô`2Ï23™žLÓ‹ÙͼÆ82Loæ9fÓ‡qbäÌó’g%=%=wZZz½äEɃn~ÝÞ“n’~Ô}G÷Ó£êeƒe9¬ŒmæÖs%ÏÌ}¦â™Ÿ{ô¸ô¬¶çðž·{™G8&övé­z®ßsa}ºõ1ô–:5Ë=ßëùsü²z¼àÕ÷¥¾ª¾?9çºÈ]Vº¼óbF¿ýöößÔÿË—B_º! ês<7`Á@v Ï qƒþ1xà`ÏÁCf ÉyÙéeÿ¡³‡~>ô·a‹‡ý8üÕá7‡ãˆž#Ž˜="bÄÙ‘sFêGIF•.“7v‹¨qlK+n´Š‹M’Ú¶9RqPÛ2>%_› Ñ Q§ÄÏö¯#7xƬÕqþl¹þ¡¬Ðª­Õè9ØÊn ±Tõ9zƒâ(öu@$cô©5¤º¸BàÏ6?€ýpŽêšµ¶S"Ù›©ªãˆYÌáÑÜt J™£Ø VÑ¡YivÂn—Ñûr_ùì†yRƺ«`½P½¾ÅP•ôÞû:î½HG¸ŒýñÊé‹r×®Hì?=v=„€n/‡®,Ü«ClñNÓ*˜ nÛ—sò?±d ÊÁŸ•ù +y“ž•6‰URѶZ*_àñ%Üb®ÝW{Wïbe½tnÚð„Íài¤W÷g›tf%„A‚V›¬"22Ë™ð¸VkLÉ‚4È3ÒsVÖO3¼Á–ë} ¶³JÙ·¡4¹4—«3™FRbö š2}³¡ámhÐØW¿EU%mLËÌÅAèãŒI’!Õ˜ ˆWFm³Õ¦Þx•&ºùi¢#hÐ{Ò÷X9Ƕ ´Æ—ÌxÀꄊÛxöáÜG}å"†ˆÝxÔ±u†Ìc>'{Xÿʺ¥›¦©â«Dþaéå‹pûbܧ䡽›…ì†Aå«h¯`å?ùjU¯ ¡þbºÜ»û÷/¦_'Ò<Årò1OúÈÜ´™u ¬Ä•ìwÍcÍ_?}ˆÂQÔ¨,âx³¤ú6î½-wáNŸö„ô"}F éCøGá3ØëûoQ.`âÆoƒ­eAGCÃ;ÐàTÅ᪣ÇÊšà0RVn«Ü«h*}a­r«Ò}ëîÀ=­~vG*þ,~Æ7¾s.­hÞýµžº š÷U†`½½Z‹"ÂUê¸Tµ‚L'ed1¾•œHw)³¤¬¬/-”xÀ½‡½P%ìû¥* Fòµ3YÏvÆ/k0^¡k;W:Ëƾ¦É9 Àµ¬c›ÒÚ6Æêtú±¸«>ÄÒWþà4~ÍO|…LÀ7qê·¨@.2ãT NÐ Idð€éDÜ›dÃ>lQÈ¿ÇV\¿ï”ÜO†šC,h €+c™ØbÈT¥¦B|’°qŽOÆ£ÀEþ€¬ SÈ$²¦»•¬³âh³èÒbqzr‹n÷•?Ä×Åžü%– ±áüJ¦z«B~«Ý¯«aöé[ •P-Úú?6×L6›Mn^ûpøìß"ò‘ß‘î ùÃYà±5\ÉI!¡lMËñšா3‰8^oLãém:¤ˆ-=˜8GaŸø›UrÙ".·HÅÃmýùÌ\úU&W¤†p¡}LE”Y&:ì½…ÓèÍ&ÈÚ]ÚI² tä•e‚è!+F“Cˆ,‰("ÆåÀ‘i2Ƕ´Î² wDù#i}ÛlÞ¿‚íÂjR»Ép& 8WâjÒ'Ù òü¯x;XÅý-ðHö.\V¶Ì?´2{ Ì"Xá»)¤—*¾·7tŠâãMjBbªÆ»z;ÄÐê9z/rõ+ ¬R*äwkƒ«ÕÆÒüX”ÖD†XÅ—íüòÊ]¿ú¾òñÞ>_Ùä™ \6d*p.{ -ý=Jg>º5ÚªV¯€¯]­jÙ{F•b)+?Fºyb಩[(ãl¬;ÿóWȰI8»jמ.äMò ™H<ˆN&“pµBs>©ÜwŽöŠ³Ê‚ÃLhÅi&É—ñEŠÒ9â[É`\"ÓM0"•S~NjXÒûA|Õê+…3!kXjk}ÁWÅB‡1y׊û¬v´Þ•Šmâ|ƒ!÷†Pa•ùiæP ð†×ÁÏUgÓ“8ÒŠqì_õ;5Pü\£ª¹®C½?¡ìkvÀb+)ü«£(ÕªÌÊfÚ O]K„Øïc~‹Cr¬ìI™Çi{ ²dØÓv! ØÉ›Κz¬UÀÏ;¿¹ š‰ 2’ãq´ 8 ‡«kÞåñ×N~ëWŠJ[üÆÜ…J[d3i\^0³3²JöccgdÕL!ضæéŠÀÇkfgjìk®P•‰/Z%¥b¬TœŒwøìòâC—l%L»[¡°ÅÕ¡”ºÜ0ˆ€Dmjªêe’åLºc­:Ÿ×àRyJ(¸t®Ú0O}€]+Ù ¦Î÷Ç!3b )ùiÙi99JóYì.î±JbwqGŠoãp~ÜF×uê…pÖWhÍÛ[Ùh TîˆÝ:çÊŠ»?\ýàz®BŸEo·W² à½ãV­·Îªó$ð¶ÞÀ~ q~”}:Â*±¹Øà]¾ä„5¿Þ–’†¥„Ýànˆè«AgޤïÕ M‰O²‡cmjžÎ檀‰Þc·nƒ6`wWTP¤Í‰KWçdFL!)Σє’G–ÖuFGRa޷㌧ÉÛ…NägçôXc’-†Œô‚ï±ÁùÒ˜¦²}ä’ÆŽÜhTæ(+î2WÞ›pÿ¨Ù©ùÆæû8õòUjNâø4Ï*cÀ•½SpKq:Ä•]¢VíL=’. K-ßßF¯‹67}ÛâSTeu‰©2/¥n‹^QU<—ú ãg¼&*|Xù¡“4oh–¼¾#d=låf< ¹ Л\‚£M¥Ç¸dœÆcGÏÛá¾i{ý‰·›oãô ÚŠ%¿ƒP"NåqÎÉÊ:ÙrËæ†ƒ5»(|a5ìèrÃaÑ IÉäiuÆ+ÿ 9EŽN‹IYFbvÄ»xQë`³½¶ù¢öwÚ^v-ìI 8l“l›tY%y¢^ŠMÏïÝ¿ÿxE¥µá`á1,‚µº`Zäu†¸X”i³âèÔ—¢^>ËyÖ÷‰6[˜á……Ù&ûºÅÚhØnú Ž"zݱßÞy yvóª•Ú=6û^i°ê+¡šµ>@iL·B0×Ô½óáGܳTùÑ|‰‰1A6ß¾WÚ`¦¶á€noW‘†°ÎN.ÓƒÍèÓÜeãb¨ëÅã>ÎN(í,¬^ŸUPuŒ“+lÞx­_—Yñ‘QfžÛÜ¢#©Y+âq; ¥ Ï-:púí¬ 8 ÁÞ•Û«a;øhWìvßãï½s-¸ƒoEh#õoF(¡šã@¹ØÓ$ \ü¹M1—‘©^Ž¥ö}>Å]‡Ï÷²û àk¡Î*óÕŒ§—ô¢NêŸTZ,‘Ùl•‡¹ä3QIéè3©8‰¶må…}÷6¿˜Åa¿kæqñÇ?Bœø³»¶U®µ]cÐÂù·Ãцì‹pdŸ¥–òîă¥`Ѫ¢6»+·Ù\º?ø æ 5‡†ó5GʬûëNQ¢hޱºçFÑuFþajì_-N¯–bLÛD>1O§ 7zÍ¿FV&]¡®\£×A×^ú•(fÓSôº4µ8ºý¡sv¼^— \d–*Äãl{Lê§Û¤Ý ;a“Á¯ÔÁ-HÑ>›íÀ\@Î5;Ñ99ñRˆtÝ1ÏÀŸYö÷8‡ôóRÄ=<ÖÊÌF(ûníCÚ}ܸ!¤‚bîÅŸFÒÁñJKs’ )‰Zu’Vð2`#xî k x .AºDYÙ6µRBÝãÖÇÒ6o¼Ïã62ЧKÈB2†L&Û©­KÆã\‚£pº äsò%?мø%`}ÿö8x>É&%䥩ãŽxÖN¶8ù³,³»_ºÿ…ç‰óxäØ/ßzë°±’ …øÔÈ8ካj M>uëÞxeÝ@°3ý?&7þj†¸Ž2+Û1í¯Ä ¶¡ï.{,Åp¼Ìã,öDæÖ£o‡I^R'زø iÑ`1åCà]N‚›Ü€6ò$ÛÎÙ^Ž«Ï~VŽPîTÝ~ç^¯oÝz¶¯üg†àëüdxT^¥¯-´(²òÊ«›€û†…évÅ„(’âÃ=)8/Ò ¼Øt 𠦸—/ßhŒn )W4ìkH/±m=€Q§JMQA<•_”SšY^_ë¾U½ÝCð¨ó0*»`Ák[ÍÞ–=Џ˜ÈàÇÉÛðÏ÷¶†¯ˆÚµ <¹yß­AGìñcËÍúØ– ÕºêUð&åËm¬ß•¶Ç ´M†ËüÐ-'îo‘t˜p)vûˆÿ¿Û4œ [WDysøøåئ4S`ž4c«Õ …;¨C‡Ù¿©ì+ÿÃð y,”CžÙ˜c¨p÷°{*yyAè 2\ñ(ŽXqó¸É}CdŸ‘aùÛŸ ÷¿o7u£ dYù¯EÔÖïØï þ°–€çAo«÷w³øÓê ÈSAb2MÝ|¿ÈØI-±â>q޼¸©nM)3öÚÇ|ìõÄéú“7.õ•?À7Ä7y2Àà{ÙjÊÀæ®4ÕêO*(Öw¥iqjú…üû4q?_Rè¯ 2[«-eµTJ[•Ö¶ñÕN§+ƒ/âû×Ñ„\ÅDgžx&ëtñÉ‚ßꀚí'ÒÁS:uÒÀi'çÞ R䦶ÄÅÉT%ïM®ö) ΡÔÊÍß8oêîÙéÇ× «Ni.êt9I éšÚÝìS{¦Þ›)€Þh¬;iÝqÑ÷.°g>ù»)äWáÑâO§šhJÎRkRô¥jÏŠçýÖŸ–\²ÓÇ–—Ѷ¼Üȶ™¯¬{┥)a,¦™  Š«Œ4F†¯?xæú»¿¢† ml÷šÐŠÝ»CCwï®­©©¨¨¡¾Ú‡f}zÎi”4X0ë.fY¤mcÛ¦óí(‹°oˆà”Â:%–9Ú²TPAG1±b žþ²ƒÆà(ý{ í˜ðdAÁ>›¬SŒ”¤åR@—ÒFƒÂdŠ}·£Ãcp³äÉ%é“§RGI·öB“®Iû{£Zל‹}z m3lëZá{63ë1í¿8gF¤kò¡ ééTϯý×g'öˆãÿ›Oþ·X3ö‹9¹îO»ÜzúØåxGéÉëH`É/¡Ò_Ò–œ9”sÀ6 hýut‡¥] ü›Î´"@­I¢ پݙLãtiÚ :Åï= •ö.´£c›a{Ç9g  ò|Ío8Eû2ETéŒÔ¢ÿéñ×!-%ÏÝÚÛœ‰Æ„| õÉLËÇébº3ÎhÏèøÐ¥ãSÛOàE«èa’à±R<†ÓùÉ6úž#ì±µj+¥èf8ÙÙª®æ‹GÖaâfÖщÛ9ß¾ƒ¦-Vžhd¨Ÿq WVVc·oq™ûÞv:ñÝf+FÜ¥D\‹[x|vú#ÂlÞíç+àzÖ¤®K¦ó>öþà«ü Mz²N šExâ¦ðEà [2ÝÊ’ŒZê~¹HŠVãl$$dŒiBnQã©[Ð –-Y‘E>/ØÈÉ¡=²"Ô#ÔË'x -Üê“QçŒ4m”£ëŠ-Q–±~É[¦\‰ÝòŸ‘ûá”Û|“¨(Ûƒ­Ÿ8ÕaO¥ùší¥¯ü7#ÞáχÙæ\Ô`*ÈÉ ¬oÐëõÀ 6uWò¼eËññt….9=5=÷öGØCÀu/ü'§Ù3'*¿ýU“Å©ùzÝ_r¯¯¼ñ_ÁRé|®¡¥¢Y½Ã,Äx‚»EŒ¹hoöó[ßšFž'ý蜬ÿBLÈÍ€Ò¯ÿNÏ“Oü†HyûBðÙ¾™ÃgÉu~œWFƒOè°|³öѽ¢£°Ü*”øÀ*µ›ac”oÀŠ-T"lQ–‰ïÝœ¶|}_*‰OølÛ>RGReÄ´ù©¥\ˆl'ÙNÉßX”}!?/3ã&äÓzzÊTÑ3‰D¹sé·“(àeZ@÷£GáHŽÐÂÂÛÆ·³N¥•Ü9ü®]ÍŸÜ*cLNwž,Ük#Æ 7@ts¨ * ŠÜ)h߬Ñ'åKÓõÅÜ2žÿŸ eÞßÎ`1ÍÞ‰°ÃXy8ì„íYÒTq ¿eoê>(æÞy¯ùÊÕ‹ëç­öÚ¼ÂO0Çð6o…KÜý‰gÆ›1gl¤Á½ÙMÈo ±P©~¼j÷×á/üaÑOèðõíŸTG¼›…ˆ²èœ¥MÜ0{ϪŽ8oºÌy}ýô)óÞ½}¶öâçÇ:VÒpÿ³rqˆ­Kî£×=[Hñ ¿‹%qƒ·¬ŠZkØ$Ϊ)¶†*£½Úþ9òÔ÷Ç]´Žh&ìû×lŠtß&lwó€×9ÒçËØ]ÿül.?Ë‘ç^ã£a ø_ˆl„pNÁ±²Æªûóë©ÊÖí(vÏÛ•¶ ¶pÓvŒœDüYW†çšplž7IN·yIÅ"tá1LVP &SÄ(ˆ¯Œ~e…Å*ÈdÙMlÖŒyæ’›˜­ŠÖÄ©4 rÚ¬üç_…Éb# <¼ è+ó$cÈlYLÇG œ,›EšuZM<¤º¨²s‹Œù¹FážvÀ•úéßðöµ­´_ÍŽ |"¹óDŠkDÇÿ‰róO\Œ¨q-³X‘»Æû?ì­29ÞЂr+Ê[(ø~;‰%x‘Çž!™#!m^43óÇž´°“ÒÝZâÞMÓeéÒ€«*-­ªÞS¢öÔnšxröIR¸[²?e_}@ýÍm÷–ÄlÏþٛó8ù¯et^û<õ­­…®©z­>¸àðÈ@KL™ñþøÃÅWI÷ Åÿ-,‘&,šãaAãæ’¨ý^û’Zâ¸ûÝIïÊÔ;Ô ?öî'Y¶v!kËðu[è´a"(O}ÿçáËD´Kyêff-“œô;Õ|ø r5Úkk»Ø)Ýz½©Ï5deÚÔÙÕŒÄ f4š¿0KN¿‹«-8Ãö*m›ÓæÆgdŒÁÙŠ’œ¬6.\4Þ€å–5­Å{ w7{þTò éõáŒëWÏÜÅîplO«â=Ÿ) ð´X3Òô:çöµ¿NHŒƒк¨rsr i¹Y‚Eˇ/ÎÇøê{ùe'[æ "ÌúyëâŠöaúí—…<²+¿˜ÿßîiÛVZÅ~V,2Kšoï¿€ý,x¾ZÚ¶ {ñš™KwºÃZXß²kÿÑ“MïýøÀ¥²ú»6ëã£]«SSß:µkÓô¨%"„ªÓ(ÖŒt_¸m]\!5j/mEöÔù÷?¢Äq4úöüåsÖ ôȘW?Q?Ò}Kp¬u™üé²ï>?w¨®Q¸¼â\ô[4î g w¸vo<È}¢9 VÚúó0X»xÆäÐ`aÛ«¼Ù­0àÐòÒÀ†õ>KW/OnZØÃS·ö5œjµ‹TcÙ­V rh’¢Ñfö^$ýK"©ˆ!ûrI‰]lÍM;{Œ´m~Â?íáöo~ïFñk²ŽÚðíÿ½))¶ž á qû¨¶ Obk¸É‰NçJìyÍöb“U‹èÊWFUù†Ç&¨Õ‚N«Óé€ÓBAZmæ‡ÞUäÙ4ÆÈe¦¤¥¨¦Í&=VT¸ª/©ª´Éêrš£èLŒe¿¸š$ß•âg$™§¶ßULú Ó.\8pî~œ‹½±O~çERê„ ‰|¥°t‹'Rêgå’^o‡ó¤÷%9Àe¤3iUümâ…—¿zßìtú~Ù“%–‡·ûÊ Æ£tzx¥¾²ÊTÖÍÜYÏda–/\²£<¶ÜöÄãˆÄ Ö“g ›©`J`¡×ÊèÈÈHÅâyÊqð&çN­Ž:/²Kù¯MdÊŸé]W\MkF#7UØk :¬ÀÞSÞ£D£NMUk@[©øvø2 ˆ7Ù>d>yŽ8ÅuTL–š‘sï}”ŸZ°[Já3Ûž›ÊŒÏ˜ñ¢é‚í_j¹Œ—‘±HÅÏ©œ–ëôaB”,tzuæ– ë ¼€2z,q"N_}|ꭚ潊œõ­ûû²àñÏGf£ ™B–’‘dÙLV¢@^C·Ö‹™…•سЏœdˆéEµ¢yÅslèàÈòNÀ…芃ñeœ†/álÒ¨Ç%OXì-…ŠGyˆ„ÔØ=[—mP‡7oÅ”¢ôÜ«µoE»6(ò#è<ió2øaÙq¹wð<ý»frzOt ÊûÊÿb.Â÷ºkº&]cÔdW”[˜Ÿ›š•¥ /¡âRivZ&ä¹ä« £“µ,éôB|Í¡0.'.Z—OƒR ÏÝ‹ÍÕ‚\¢U1qª´¤â$\L‹#S“!ÞE Áuø>†¼æ“Ÿ_”›—Ÿ‡‚Ö,ØˆÝØôËè& öh’b1òM#ý°‰¼ô[ K+2­ 4áQ“Dth’Šc0ʶ±ZðT¥k±NV¥áá+:RÇÆ>[úN &”?^³úBönƒí§¸ì¾m·àÞ‡ðG3ã¶+Hù¿E)Kœ£u¶t‘ßÖiµÛô@ÙwwšÞÝÛf¶kÕÍí¬Œ+-//Ú{nMóœ±äÙ D"ÙÙAýó[à ¶Cël|TFùè™>Úªç/†ô좣¢¼Œ¬Á`pÐëu±KßÜê¦P«éªRíT”÷ñÇÈ>SM*{¼¾4Ú‡¢œFûW«c}Õò[©詆]Û©6pƒˆÄu°âß}él´“¦æÁGG¯eWAbµ˜Á™S¬æþPøgiá'µ%òä%χ¿é‰/Éñ®8+ÉÅ)Öà þ,)YÅÚÀœe–€˜*S1‹7·§*Y»!êpC'ÿÔw’Åi±¯T\B¥<=߯ƒv)MMHÐäï¿ÍM‰£í¢µû®‚´œ£ —OyüéáøÏÜfŒÍmÎfÉÛ˜u[*në<|’ò‰ßµ-ßL/ò€07xûØ] RfÁ«ðzÚ„ƒ³͸n3¶•þºörúMø˜#¾ä*ï+-‘ߨÎÃ}8áRÖ©R|öz¶êàRdéðW˜ ËàuX¨Z3zu€;tL¼b£õ0åË ktàm{ž¯C˜°|é$ ®ÅŸŽµç µ’k/¤Ãuüa—mþ h¢_tîÁïb'hrmb 7𧟾·:ø ·~ÕñôC~ƒòÇ£pþcÎîÙó²©g/†ùƒÖ@Z endstream endobj 11 0 obj <> endobj 1036 0 obj <>stream xœu”}TSçÇïåBî ˆÚ»¹Êî[_<ˆØjY=³¼¬TJ¨¢öX´ ÃðVr’„*ã%’ü  T^Brµ°[”RGÕ–j×µ£eÎöXÇô [çz|.»ìœ]âi»?¶žó<ç×€‡ 賟•ÿ‚'Ÿ«†Qe‘ß~tþÒ¥¶=YŒXý÷¾:p©(¡ª¶[HôâÁiœ&„S÷nÍq[¯Ésèxh¨ýº½·íú¦‚ið€Óá´76€ ¨°V²b Y Öcn§Ó×ɸ›ÁÕÞ1´o:úv|rf¢t°î([4 mÚöªº)¥ .P¾3ExS|™‹qZšáP­àöHeŽHe®ùîÏÑï…ú;éä¦Ü´§“¬o½Ã /Hqõ¢úi°%²b, J( –úËOUŸ“^„<ßÓ1@m {,‚'Ó-Íc,È(ŒÞ‹w…j?÷5Š›!„há=Üè¾Ìð¤Îž ”Âã uIð¸òÆ‘ê"v!LÜ·}·q{ˤš Zƒ8Iùö–Ê« Ó¦”׿¸y…1QBzm7Òv¡Ô],—a:Dw» ëÎî[b¤(Ûø°-®üG,"Уó5Yë-v«ÕΖo~ÖTþ£”Ìv‘Î.ºmøÊ€{Ð$®v–PQÈ/¹„A+æp„¿O aî3öhÊ+ŒZµßìðôu3"#fI¸>8Z/áêýÁoKÖn…I8qßÜ îaV'C—ÎGŒÜ¿ñéù Zd¿·Ô‚ï‡óc’¥‚pÿ¤¨yÑ7ÿs÷Ì+  W飽§?wR<¹Çn‡ )D!Œä9G»LPöú*ñù…Ú•â‹B§µ\àú)z%ôzûV ½ÒAÿÌ%è€öôÛ……•î*—µ ÚÀy¤¹s1’À#†ò¤Îðö‡ú÷ÿjöÎß’ÿ×É\ï=ÿ |NÍ$MÆ>–œ•R0`i÷ùÛƒƒú¶ŠúPECWn¨×¦­5ÛvrûYu^‰Më ¢Œ>!µi޵ødb~+É/™z€Y¾Ù+ÿ‘÷¨\>Õ!İÿ«yfÐ endstream endobj 9 0 obj <> endobj 1037 0 obj <>stream xœY Xײîq`ºEÄ-A“ÜqÇhÜbÅEqÇe@MvY†}¦fÀaßwaQ$šÅÄĽ7Q£Ïè5‰F©ÆCrßi ‰ï&¹ß}÷;ÃL×ô9Uõ×_õȳ~ŒL&cmžñ’ôçq¤L|¡Ÿø¢Hæ f¡]‰æ`)K³ã/Ê¡¢í,„[3r™,(<Ù1hoTˆ¯·O˜­Ý®‰¶3æÍ›3Åö%{ûy¶ ¼B|w¹Ú:»‡ùx¸‡Ñüm]ƒvùz…EÙÚ½ê¶wþôé‘‘‘ÓÜB§…x¿6qŠm¤o˜í:¯P¯/O[§ À0ÛÕî^¶½Ç›ÖûË1(`ox˜Wˆ­s§WH Ã0 . rÜ»8xIˆSèÒ°eáË#"ÝWîóXµË9Úsµ×šÝ.Þ>ë|]×ûmðß°iÖ˳çÌ7‚ÝD˩ӦÛÏxiæ†ͬaÆ0.ÌXf-3ŽYÇŒg\™ ÌzÆŽÙÀLd62“˜MÌff3…ÙÂ82S™­ÌbfãÆ,a¦3NŒ=³”™Á,c–33™Ì,æef3›qfæ0«™¹ Ï<Ï g¬f3’á˜þŒÀX1ƒ˜ÁÌf(3ŒyNfÁ,¢©`̘æžl­¬¡ßä~eýËÝäÍfVfÞæœyù]…JaRˆìVöŸ\t¾£…µÅF‹«^pÅr’eñÀ—–ZYXùX½5(}ÐOƒ 5D3äÊа¡? 7,í¹ñÏuðƒùÃÏÛ=Ÿ?|èpíðsÃÿi½Ýú´ƒÍ:››†CGlq~¤û Ät«®;`B{“¸¢\&îèšÇ'—j„BhR“£ˆ®û'ëäÐ¥‡¤§A8pQ*ÅAý»PµðTiÞ´cbÃÁ ‚ò2r@¯ÏìÀç­±Bñ±7ŸªR4èïC4ÀPÓc:…%·Ä9ÒlNbV]æ`-Œ2”£ w L.ÂNþ[7H?GgŸ×}-öS‡$sû~x*ÉE'[¥¿‡èúu'ôe‘¹ÚqþXEèÔþ™ kÕu‚ºù¦«L2‡ƒððùñ®E¼êI÷ýQ*q3‹ó®Ý¾÷íÜOÈÀ%Ž­=tÚ¸»s®’YÙ@>â± —³*¶,ñt$ý•d"ù’Ç7ÑÅþ%„Ù±Êw>a•VbgJ£8Â(«GKÌGK¹X‹A<Žœþ€Ì sf!Ï“áw§â œs눞¬åÉó€ý¯·Á›eÊÊ'KMð64î- *÷†MàÆÍÂ^°êêˆ7á¦r\Q&Ùû8JԵȻÔ]³ø*È^wt=½¬z!Ø$2Œ#»‰N$QƒNÈ¢Z”¤èö«Õ U&’)„ß4VÀÌR×|šüÎ ð]ÑgmçÎ_y˜{®t?Lës ¸*ÐW+iªÈFŽ3ŠÃei¶ Ô;‚â­Å„ŧ¥ó[ã<š­’¹"‚LÜí@Gì±¥Sq/×c²»+^W»O\°í8Œ+Šϵ(QmÞý#uûî(U—¹ÂJÜÙ[3?BNŽžÎ³p&öb’£!Šó0F×ÔKšÛ7r{Õ×É=–V‘\Aæþk]¡®ÔÁ5¨îqf-‘MôÈuôÕwä™ôÈ]|÷íÞÝuzTÀ1è€ÛðFχˆ Öeïeï\ÔëÁ¢¤“…õX‡c8j’Ô+qMŠQ´=,kúc>–‹Å|díOÑ@â~!-=!95=¨x·Á¸2 Èó£qpx}ª²6Õ˜’ 'O„€;÷š=Dl^U|?HH)×ꢋ€ô0%aÙ}\”¥‡ârá`ÙIŸ· lÎâ|´9lŒ,Uzñ5lÈ]™·&NsÞ† ”–„è]\¶î ȨRZ=åhq¹™Ä¡½•õZÓÒÂhþs“"Tc ~°–Ãj=uY…£Æ±A»B"ãüÕî°ì ?ó<ú %<*¹x²ã¯«Ù_­¾(êhVñ{;4¸|È-¦”²œR kÂå²hÝ l‘£·8ŽÇ±&2]ÝZ;7;»tnÏ5RÏŽºvérë¹ËB‡û&vy@ ÿ¸P%X=•ÓÄž4a©©7±W%ÿB»†óOLŠ@êŸ7]¶ØãßRJ®béû‡+Rá±uúŸ ‘®Ÿ ®£ð$^%'ÿì E”9M<×þ;¿ãq5ÿ+ 7³ v¬vx=­æ¬€÷Xâô;@Õì„ ?U_†k&A7_ æ&Ö9Ž+E3ÖJœÝÇ c¨xˆúf&…·f¸Ó5¼{eÖ}Ÿ˜©ØFýCh¡ë!4öbVºÃÔ ‘7ÉÄ$ÑŠÏ*ÊÌþ8ë­Ñ€ì ¬ë¹[[™š¬mªZIú“\Âãó³&E˜f 5 „µÜcö‹‹»‡æìÓ§VM1dësÊ9J×½;tyŠù¬’Œ¬w¤5q4 ×wF6ç ˆ£;¤©•£Ia±Éüm r.tƒÍô[z¬:ÙŒ¤q™‰)¹¡ šôdmú²Öš0X&Ù‡i–R{?pƒ€>{œÚ=$+*3¹lò(ø²ËŸ`©õRœ.ýkS †¬RÊ…¦#zÔâ,£ìM‘‡D…*<Ãß]ô>åJ,Rç¸7DÕ®«h*K.ÎŒ9ÕPÜÇÍ^ó”»Xò™¹“Èí‘‹üäïo´´–+wƒê{¡]Q‘ •‰«\¥ƒb¨âˆì?uN”ßVã© SÿÝ I³ß¸ÝZ.úŠóyLÄy9Ù·ÁÆÄ®¡©Øà!½ª„jíA5§e»-È%s¼ñÿÀçöÑWèEô险f“°ÂÛ ÿšJ“ÃðM™ïe7@Úu¡Ô!hµ<¥G»ƒ@¥ Úääd)Ê•žÊ—f^A½§*«HM¦:I£QΚh‡Í[~MFlè³ù”E{²Ž6þ ñ±ÉÉsÁFž«×C=¥Þ8Ô+ öEÈÒ.+[ùÍQNFš»«Õú ” S¶íµZÒWN#Œ¸¡²?æIسkÿl‹ý¾…-)+)+.oßx6ámÉ“Tï¼8õyÑeÛ>?å7þèé3¥-ôÚ` Öï€u¡»•þnÛÔ~°vŸŽ­¤èóLvº¸ž¶•ìC3¾ 8[ÚcmLŠ­š—`#ì¢x6þâ;Ru‘mFñC“¬RT’8ˆ7ffŸ— ÀW“öKL×qéé)Út©Äçð°Tb¡4ˆA4Ð.}%vžEçîq©ñ±©ñ6;üœ–@ÄC‚A¯;œMœ1´"À?4Âw[«û»×ߺÜZ.X‰é”6ûzüR´‹>ØŸÏOuŒVŸ*$ïÛ»l:mÁ£§œìÔápžÕ©IÕjµ­2==n?„pîG¢k*š Ú®Ö°8-¡BŒ%/|;'àŒzä²(ŠÏôÅiB›øXÚä0ãI²x4‘â?‚Ò»/Ê„kµÁiQšHmpa*E•þó!ñEöÂX)"¡™ZTrâY‹5Ý?H0¨KÀ¦ ¹òðpW?kbE­þ1¡ë1ÔöB\¼ÿÄD|ÙH„Ä àthP*Γ‹«ÄI|NèÁÀ•©aŸ@~Q$×Í[†o+[QÜ©ïfè ’m"s \(Jp«¹»"iT¸+ œ½âYèýªšð¡$Çú{^¶³Î‰Ftôø™Ä–Œy0mζ•+7±èô;‹,‘ußáÝWoŽ£ýž ö¿•MÊús†*h†Ö(ãN®§gõB°MLi“£©k6¯ÎÓê"釂ÿ«¨Y1©ûë¼x¶lªÁP¥¯±P©ÓÌ,Õ—ëJi–Ê×"/^…°äU±µ4vÕéui:-„sݳ)¼sSѵ_ë•ù‰wåâf æ« Ps8ùÊö6¥{‹kÁZIÞÍG†ÛGö8'Ÿ|RR´Rb´éq)ÊàË#ܨÅ8-Ž<§¬3Ó7ëŽW4–5­4QâÊ!–º-´oÆ7u nìQ$+p”¼« ¿æÑ‡8ž„Pò"™@¼‰7Ú’Q¸—.[…Þé&ø°ªÞëm·ÏR¿¡bõ½ŒÍ·^¼TÓIÅÞ»ªºÇÖæ;Ó6i—0w‹Sˆïz••Åx¯‡ô0”cæoKÊ2@R ðHñø£bcž^«1ûÕ‰ÑÁíjˆ:XÙXÔÚìݲ؞Ƚ'Œ[¨ºLžþ…²Ì¡w/jÂŽ^1mÔªßáñ5¾òõÍGÈL¹Iæ)»§ô²ˆâZGˆ÷yœó–.‡9dº’(±ƒ*ËN²½_º{¥ãŽÈê¯cèÃu9>+øÓÁç H"À³¿ØØŸ«¬+®Î,ѧ§ÒI6Ž‹(Üwð`aYEuTƒ»Ê#"*Bð¨öÌÙL“"¬m‰®G‹¯2z_”m0ªªÝ1¡)Îa°Žsùp®Âù7ÞºòÕÚº|Á­z%̤ÓòNHÕ©²â›hÌÖåp8ÀÀÏ‚ON‚OnݧíÛÁi–òqã?»·ÉÇg-u¬½Ï5ÿŠ”¿ÎÁRuýÉ(<~ëâIħx–éßùïGá«ñÆ3b£ihO>špÔðaûŃÀF6/Á[ÜÃÑ7ˆ³Ðmþ[B÷$äÇßÚê1vØ8@qâ+ƒûB8,£Ë£Ý÷ŒÏum%p?äß),IʈۧMŽÓ*S·øGÁJH¾t—¶?¥#ù2aŒ”ËyÒépNÆ<—õÚYä¥~Hñ"¶c%4Ê1´KÎ7ï©÷ôð÷õòª÷m>n¬oÈb²œòOç3#Í'PK]=ß§bÁvÒe2 r%ÌÞ% Œ¼Ë¯„·Ò²cpr8Ôq¦ó¼2Á^#HÛWˆ…h!…ÄUÒ¹FñŸ“KK’R¸·"ÈÄñúLMž&—sWì!@‰‹z|±$/Çð%9\® òyT\Œ¿‹ ágÀVnY;d×de Åt*mœZˆf\áz¼oSG¯â»W¥çEfü›ÏƒÏ¹GÓ[‰ŒØ,^0iCíšËž1ß²Ï 6QaþЭÑîÖU:°É^nÛ|H Ëñ‘yAUôˆWÒWÝ<½c¹G”jÝô™GáUã>S(l¶yå•G;׎/>;yêtm§'ªÑ⬑= }ð9¹8òK€¬"öþÞÙÅB¡¢¸Æ½U~Á{¢w.9»ù5ö%æ], 1D˜ø ÕgÊ{¯£eË›EŸ6D±‘·ƒkß݃[(;_µ.!S™ w†=Ü’@»9=ÄD Ñž6¼8VŽûD®§áyîñ÷ð0úïmxfx~Å \ØóÁYÒ£¡‹¼Æa³ëŽÄ$­Ò¸Ä|µ¡ð‡hóÑž³®;÷îñô®ñn«+-ÊΦÎ.'™O×K8§"Ö‚$ñ ú}¥Ä ÍT¸¤×–7p6šÑjÈ×é “Ë‡ÔD D d,a—’U@GB²ê²Gî`¸žRw ò•ÏÜ=ᮯ¡ž\å„KÉhä‚+5 .5âÓ@S¥D3bf"‹AzmÙJf3bßãA|>ÈÑCÅAFˆýW.ãz$>=óZVHÏBÑ“úCq=ŸFÆ>dém‘{"¯" þê¸Pæv׆1ªj:»ãñ” ¦ø’Âøß%ë¿°>>Å%lAë£$Wþìº8’Å\|W–ršƒÅü]Ò1íÍc_/ý1…’`ͨxêZ.{_\.»Öó4X4è\ilnܾ´øØ¡Ûò—Y404.6Q…ꂲ̼"C0⣬•ޱÒ7 …x‰¿˜BˆHò¤É@â1t¸ÿ@ßlçý ´ ²"¤&¦0.Âùì3….eUB¼¿¿p»óa5„ý±‘‘{Õ¡Ð˨b†©•f-Íåø ‹åë4à',\IäÒ@ûTeŠ£Ða8QÀuW¥ŠmÑÿmt=ék÷äE‰G-ð<Ú´›dçÐ]¤"Ò£ï®HHvÙ¯NJv€ýTkOW45üãoEy(ÿòãv¸Ç¡…í§T›OZ9e£iU}cÅ©ÿ ÿLáÄ©ŽÌ J­¯;:ltôP)I‰T'RÝe-Îí¥îã(àУ7ð¹–FÙçØ¥1£oðhcÜvÀ(ÂD,Ï8â¦4åÕÃa®9°ÎÃ=0Ð}úà 8ç}ñ‡o„|K¦× _Õ¾÷>|Á]qü€(‰Ù<—ù[ŽÇ¬;ZvªJ}d[–ÐÒü1€» NiÛý<”Á¾Á/M¼6R›¦II‡dŠÚh¤­ºÆþ6Võ`T¬Ä’ÿp°ò_Ÿ°UØud-DÓPYñÞd€òßbÖó/0r‘nIË‚ù±èÌÑê¤ôl!!52 ÊS˜@Ù“µŠÏ]rpgyn¾‚lÏbM( X˜Í)·ì$ÇÒeU–u–V ó¿7aŽ endstream endobj 515 0 obj <> endobj 1038 0 obj <>stream xœ­Wipç^!#ð¸ f!*é® Ä±  „ÐÄRc̡Ɨ0²lIȲ%[X‡W’%½’¬[>°ŽX¾„!6‡m07L @RRH€d€f&M'í'gùѵM'IÓ™&™ÎþØÝÙy¿ù¾÷9Þg9XÜŒÃáŒKK_ÿîüyÃɱiœØ³cb¿âʘܡCÆB<âã:ž¿3 yŸFâ_ -Oa\GR¦O“H+dÂÂò¤”üÔ¤ùK–,ž´`Þ¼%IËJ2a~®8)=W¾SP’+g_Š“ÖIò…yERʯwÊåÒW_zI¡PÌÍ-)+‘¾ž:;I!”ïLZ+(ÈÊI+$byÒêÜAÒèîæŽÞÒ$%Ò2¹@–”.)ÈĆ%Š%Ò·e¥òwÊró*… Å%ñ–­Á2±ç±uØzl–ŠmÄÞÂÒ°­Ø ìl¶KÇVc%ØdöüXÖÉ眳pLw·-®nlÚØû¼Òq³Æ¹ð—ñÁñ»ÆÿyÂ&vÇL ±óÚplN˜ƒ Qú U¢4Âv†áº`ÝÓ^ßÜwã&ྲྀìòôíÌĪ|J-4UC9¾½­°ÿÁ>”êðÒ Wƒyw IK¥©™€—[ê#Þw3SŽÇÏpÖAÀ¯ƒªÍàô:]-µÔ(ÙUÉ; |ÄAQ JýgƱŒ¬œB¡˜Ò dûe?âäPé%Ôy9áÞwñÖÀû¼kE¹Rf¢ø=J#ËY¾ðLÝ=·Ýj·¹©„¡ˆq¢œ¡wîpÑ›× Zh W®Ò‚RãF ]à¡L´ QšñêW A1—y#_݈¶B¥ Ì5UÔ­)žý.k'à_ð>½•ÍL]#f2½@e­};w)à3yÅ`w9í^«“Jˆ-це[ l—Rïr‘"¬ö>DüÐÁªZ“Œ¸Ú£liŠÖ8¹ÊW´¢pK™ŠÔž*ýLä;\ín‹ülmøÜm4÷êñð¤›÷ôgѤsÛ®OMüÚBôêút°I—Î,ËtœP‘'plx@]W.—Tf¯(üÍêF GþôZSž‡Lü‡ÄYèîùesèêíÖ.]ÕÐRÐáZgeóžÏ‘¼ï2ãó^ÜD&~¯_®j3à èË=~¥Y|/pQ]l&q·ÇÇ¡TÔR^J©­8ø¡J‡N¦+geQÀ¼?E”/Öl1”K„üümù°ÔP R_ÐíÁ¼®:°«¢¸ª ¿«âî×7w3@"NlUmK©ÚJiä´¸†L|Ô^%mË™ÆÄ1ã˜fú¢£+YJ}}zùýøeTOd3«hÑê×XJm0ßôõw ñ¡£Täto;2/xÓT ˆÿé$4ùìÑ3¹ŸMMŒ¡»hñ –¾ÈƺÊÚÚR×Y×E]BoxÛYºøg‘s„Lªñ[Iz:[ŒHÒ(/ÕŠõJªäu‘†½øU‚-(ð‚æ¼“;ѬZ2ñ/Ƙœˆ(ÜUåR…D¤ëƒmv’5ȲèÐÔ(eßàÉcŸ—ÎÚÛ­¸ÝoÝã®qTS%Pd*Ù‹‡-ÇÈZœÖcñP'Ín”CµYo¦0±gD 1}ÞÀ7­ß÷yرצ¾Œ%ÿd¿|ññZe ã3ñwW>D‰ˆ‹¦ 1­dbÝbˆ8Ìyxᧉyú±ÉRcTÀnþÆvôw[#uäžýõ—XGî»ÑF©—U.WæJ€?ê, Îfvv |ïV¢ßOxÇÀæµï¸øؼ[ª›«©ULÝR×A´p´†ÿƒ¢Ÿ ïf·-ß²}{ I_ÛȆ È*þöÿϳ2 ܾ>2«gÜnsdwу §ØÀÒÎNl´í;#x¸¡]¡H´üßF}³:m°ñ}z¨$š×ô ø×ºQðÛà¨)"Û^ `‰?ᶦîÌ1ø²fº”¬˜3vÕ·1à"o3¤ËÒfi²øú]ê…`†RP7u8ê›!ˆ‡+¼*™L±s[¯rÿý^”Œžo#ʱ4*µ5†yL®o\tÂՉ䄸ÅÁøñaO<û‡ð/<)\ endstream endobj 213 0 obj <> endobj 1039 0 obj <>stream xœcd`ab`dddwöõõ441U~H3þaú!ËÜüÓëÇÖnæn–•ß7 }üÅÿ=\€™‘1¿´Å9¿ ²(3=£DA#YSÁÐÒÒ\GÁÈÀÀRÁ17µ(391OÁ7±$#57±ÈÉQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMU€¸MB9çç”–¤)øæ§¤å1000Ú10È3012²þèàû97eÁµóïýøÎüÓü{…è´ “'tOïžÞ<¡aŸ}ßgJÔMêìîèæhhjjhšÐ:³EþÇÂß=€¸¶¥­µ»I²aJÓ´¾ÞîI3äøJþpž6mÆ÷Ü…l¿§±¯âºÌ-ÇÅb>Ÿ‡sÉDt¦vÌ endstream endobj 121 0 obj <> endobj 1040 0 obj <>stream xœ5_HSqÇש›º´‚UÚ7!TÿCýA!lQùâ¿kÞýqn׿յòn3÷çìîÛ®RÍ$R‰ŽDñEz)ìµ§^¤‡‚^Êß]—¢«#‡s|>ŸC â"D„¼[Û7ÐÚr´^ª á|‘pAb8_ž÷”€RÊâÕ<}Â÷«pÿI$#zj¶›žp9,&3CÖÈÖÎÎËd[KK'Ùe£ƒÞNjõŒ™²éé'ûhƒ…b\dýU3ÃL\inv:MzÛdí0]oh$ÆLÞ£&)Ç45JöÐv†¼­·Qd®©0ºiÛÄC9H-=J9ì¡’"ãX• ¡4ŒtˆA#¨T’BÅÈC¨ˆkÄâ—à¯Ì§A›&pà” j¼¦‡ñÐÌB€ó‚Úíö°³\€gk𰨥fÙ@fÕlÒ“ŒsÜ‚Ie \p~.ê…x‚ç âÖ9±·ìâ^Ü{.{¶…¸Hæ¼71ãõùXVS)øÅpF0. ‰`ü“ ¯ T{õóÑ”ŽIi`ëZú»‚ñ‘FÁj3Û©ÀTp.èóÁSpÇ Ü÷m›øÁ0 0)ÄA9èÁºMmÚöÙMPðqà“R0Ts+2˜}²ëOë l”Ö÷…5;±'éø——ë[ð^Q‰W%¤ß}OEN†Ûó#ª¤œNp¹4;ä.p¥ÓJ¡ïeð4±'œ• wpXuØvP+¢Ž¶Ú‹íýüzpøßÏœ,™‚߸X¦ÃÃ^‘˜-ð+Xß¿í|i°ä· ÙÜ›·+ÜR¨àÇä7#Cë쎟/€K~ï ;´aXëIZ@áa=þBÍߎu±?ì)¼AòÓÅg­™é÷ko'cÒÁ]EåärþÆR©XÍËså¹ Myñ㌲,÷\©”úBÿÔDTo endstream endobj 64 0 obj <> endobj 1041 0 obj <>stream xœZ@SWÛ¾¸¹*.âUP¿{q·jÕ*Z·¶ XnA‘½B $Œ@€ä„öNØK÷‰#¨­ÁÕúUk«XíT[ýNì¡ÿ÷Ÿ$@Ò¯þÞ{OÎyÏû>ïû<ïI8„m‚Ãáp—¹{x̘nüïÃHŽaTÃ?lRQŒaÿ[7;`oìmFMí`ˆO ‚[6NXTò²°ð~€Ÿ¿Àù½Ýï;Ϙ7ï£)Î3§OŸç¼$Ä—°Û;ÔÙÝ[àïâ-ÀÁÎÂvø bœß[à/„»L›& §z‡DN ãû-|г0@àï¼Þ7Ò—í»ÇyeX¨Àywˆ¯³Ùº©æ?ËÂB£¾|g÷°=¾üP‚ v. ݲ4lë²ðmË#VðWF~"ø4Ê5ÚMè½Jä³:f·{ìž5¾Ÿí]ë·Î}À†@ Á›B68{ÎG£çŽ™7ÖeÜüñ &| ¶ˉ©Ävb1XIL'>!fŸ3 WbáF|H¬"f«‰9„;ñ±†˜KÐÄ0b8áHô!œbaKŒ$ìˆQIüƒà A,Ñ—p&ú£‰þÄžø˜@,$‹ˆAÄbb01„ØA8; áI %¼O]\etS‚ΣãÖÛWm "Ã}ºT‡Ä¤$&§0ŠT ˆãÖíÔlÁ£ñF 7´ â¿p¤¾ë|º/$È TÁ&¿ïé¨é³ßÀIðýÇo:¯^ÜéRÄfĦ‹Õ ´ã¾_§éàÍndªqP@XJ_¹|þÚÝËK?œ¼ÂmÅÇþON3h‚íïc²&@AÎÏ?B4ó—ÑÛ=c‚XÞÏõŠ"߿หîÂ1ÙëÍ«zxûs¯áW Ô ÚD zL&%²K¹"µßh(sæsÑî˜D ƒD§€ PÎÀ×ä¾ìÜ&ö·Tøƒh!³ Õq{g¨‡ez›«HwÛQÌVtI£ÈÞ+èCÂáO 3œ ?œ '!'q»NÑéO\h׆qN¡¾ëÐ dcå§»¦ÀTb«= δyáX_&¼Þ§f=Žˆíø)ˆ‡ÿ0 ö¹y²¥RË¢ mV±žo‰õ6r%„ôúmóæ-qëxú¬Cÿõ½ ]s–Dé —)Ãõ'ô;pHþøYG‡X,7°æ­wZ¶¾i¸¼.‡s}€¸y?¨(gžw?û0h8ô‚ŠMd¯GïpåyLW_K~7XW)ø®|<œwòáú‡+?ÁŒ*²TX ¨ MI­&þèÜ-«bV{°¼¯ö›§B},H€Ú],W°ÈRM÷*ÆoÎ+=…÷hÁ:Ž"ßiû(3Þaû‹GöuI­";ÕâèÍdOp¸­ƒñº`ÝpÞKxæÐ‚La?+4ó“pˆªijüñ›¢ˆ F›ÛØ z®1÷"S¥É ÆKëD8Æóóü¦½Ž}&eyÏ[“¾ŽÛ4bïÞÀé;6äßç3)e©ù€2F„Ä~Cn‰ª¥€iõ;¯¨Ã‰3³é›Ó,ï%øÑÚ ,Ê”ìp–ÇÅYk0¬6B_ºÊX|MÎêoqâQ2ÙnÛ± P.‹ '¾þí~ó5"JÙôXu|M·É5Ù’ aüv{c›íÇ¡‘È­þ9Áþ—Ž6TjØ( 4{Úìž›ºß4cÐgâ`ð $ çZ|ˆæ>${‘6ïC3ñ+ü”FN¾éwçîƒce@먌Že”îë€ZÎU³VUŸóXýñ]qù¬¶šÛjÕÈùCÏ¿>íešê.)ßrõ× ýQ4Ÿ|wY5#ÀÈìöÁ?šhU”êYRmr¸”õ„I¶þBɘxg¸Ä-ûšXÉýûˆ\r²>òÃGòZ꨿¸ð½L©Z¸DmtœC‚a§Ñd-ž/ÄàúJÆDš„F9ÛJnEgí”djMÜÉø#1×ÒòýA"N°„¨´ä݈IRJr3 ±>±;LÕöà¯o´©e—LXôÒ®¦GÔ ¾#“°z F³ív[î¾fFƒ`ö;8¨ ² ëÑ…øYï»»“S ¡Úõj VÇŽ4tû{®u©I!ˆÆ¥KSÍðZ½`E2ÒJ°<ÉvàL¡­¶w¸S1–Ìäè¡'çJ ù6«=ϱdLK—t¯åÊ`ßCº8ƒp)FcÒ•õé ûuœcÿ ]†âöÊc’ƒ”dJ¹L›\>&;V¿;]I8½ÍL  t þ¼8~¨‡ŸB¢ª¬PHUÇ”ñÃcc"¼÷ïn}q:æg2½J÷ŽFvba9t](‹ÂdF'Ú±Ps–u|ºráHí! cUþåÒ*@UiKëhñghÔ,dÿÃxèÙý¿”vWð±zØ ãt´ÁjŒÙc;:ÞO*Å9šxj,P¨«ø@ ¨ æýjAÛ%åEwoæa‚XC„Š›¿ó:òÈŒËúf%«“ ’ @!(ÊÉ)ÊP Õç)UWùÎK¹MÚn nÀb!U*‹°¹U˜(ô-­Õ¨2@i·ž|nÖ“;-z²¦sÑ Ô-T¦X³ž4 "+Ô@Š©ËYå‹*¸=Õ㦠 zúÇÚH3ÖôaP¿ƒ>f’¼Öú@Ÿ’]#g²I>ôã´ ­­«§`írîϹ —v«ó§Ž×[7xXpú¼ FcŸ¯7ܦã÷I2Âõ‰a)±÷êçÂT$\Ý•Vè_¢¬N YƒºšÛ;b´5±†)»UÒ¨«p¨ŽsQ«°#À ´¶´@rÕ/hê?y"VÃ_N€4t<õ´Ú­˜¤4Q2µe£, ,‹Ïˆ¿£TWé¢;W.vÜÁñsÇQ½M›ÖâYýáe®CîÈ=:CGµáЮ®¨…GäƒrèY€¯?<A;¸™²ðJcÁCp4ËŠ= và•Öw°uþÒñãç.ݱi½—×fv†?¡8(hÔ³;·;dõ±u¬¶ *³P¥¯LÎTieA}¥¨qcÂ6eÀNVœï_¾P,_´1,‚'iã)ʧÆ®yIÿ—ƒšÿÇ1¹ÓßÚÝ9`qìª÷ÖkpiÃ阓n“ÏŽ¯Ý¾ÍsÝtv =‚èÏ[ÊuàõÝ¢‡¨ƒVüÿtq É;sk÷ÐV ¢€7p!åA¥!uâý€ºVõùÁ¦H€õzˆ’MRì 'Ï_9²J&¾^ •æ÷æÖƒÐ÷ÅJlßsØnA›{¾1VÙb‡ÚÑ+ÀŸ¶~ É{iPØÖEU„…EE……UDÕÕUTÔ1=µÁáÜ XrÃ÷†qòVXK×É¿‚©Í»Ö.Û–Y»›ñ®M=ª,S–*Ë‚ºÛ+ähê¯*ÔEM¹Ìáø:ÛO:¯û/d}‡g\Fñ^º”yø6ƒSNg[Oß‚ýŠ?V3QùrMO¿ähîñRbC’ŸæžX6‹Ìùô¤ë7‘¸ÇËTþ,(J£zy;ât'nrÅkƒm¯+f’½eëú€±À7Â?Ü7ëÀPŸ.IÇ””²©:Ai´ *6tÑ/àÚ_gxÏ ¿½Ó;f¨ÑC'=tìi%ßÑ |Ç™‰S—t³ÕéÃ’ÿhŠÍ%³?.™}ÚŒ0‡†ƒ ×®Ùª™j%†H4M±ƒ¯Í ºYh§µKºÍªó²ê½·= ¿¾‹ËÃ4óI©É5ý,Ó“½ýÇ==L0R÷ô´U5E?ή›7or;÷/þÐ`ÔÄïõ+‰=žöâÅãgpóŸ}Ø•)u‡áŒ¶º~hEÃŒ&iê®Ì 1ÛgêÆuÇ›—Õ‚fv!º·I´(y—QÙ5§–ÊZ&œ›ÿ6ò†[Wižo ¨Nµ ä¶ô&˜‡Îá|ìoü6žÁq ãiEƒÄ*ÈòrÔÎõ‹î.'OÌžŒ~,ü„Ëkí|e‡^qMØm{œ Xç&=Tâ’ð/Ø`p¢ýW²O×Ãd‹äBd`²,ˆEåÜ h*ËÌÊËaj›Ž”]ÆNþãብnó—öQتœ‹alVVN6ÐPõ‚’hIˆlÏÜG+ -òëShÃðþõrá/˜̧G-ípFÎ?¡´s³éD}0üž.‚£xøì% Y)øKb¨È2aMµ¦´¡ÕïÂ$4ÿ€<Þk”m—þ 9¿<‚öœÕ‰ú0<Ãf°9ÖÓ‡Â-äÚ ìiêj¥Z¡¦Pfü¥ÊàŒýXe¶¢W´ö«g¾|pþÓ%³]×/3™¥5´è8Çõ—pJÀAKÐêPJ ›KKóë™,Ø?€KuW4eéé ˆ2zˆAßò’c¿¢D¬ww5+7×´†ÑôaoÚéó>™2™Oꦀ,4-Ý“Qù€=é>ªˆÜL9é‡Ó/¨n¨.¨Îe^ç©®‚ÿ`ºîÔ9×{Ov§C?ÃbØE/u?Ñv®íô?ï_Ú¾y½»×RöŸÁô×µ'ZÁ%êáœû¨?²ÿhËú“[ÿÁð~[½jíⓞςC Ã³'?ßs»²DË,@Mô\×6½îòµïŸ]Z½f¥ë†¹F¹ÀSœqW‰þhóoâþ¿ Ãu:ãT@NЄ ¯Bä娒dD×jU¦*5Bi×ÿ>¼™yí°ãA¿¹ÆÝÇ[1Œƒ5t"üñ{“qúù©¢K2³²Ô¸7ªŠÑDð…±!Ae˱àsĵ܆åÈF?ÙL˜‹B>™ 1 ~>Εž8B¡q™´Ë¦/î>¾ÕvûX@XÂÖlÁ’P¡T€’)2Êcãú¹¦xiá˜8¡ŽÑpš Ûl }àGô—dA3hnöñ¬+Y'ضÜð%‹ 7«%2Oœ‚Aj¨2^‚8Ž{çÝ…d¼?ð÷oìd š`·Írã)Fƒ@*PR1E±ÚÆŒú‚t¦´ûí÷Ñ0œ.¿™fg"EìW8„wÀ!6ð¾Á–n © òåïmˆh:XÝØÈ +¶»‡_9W{Ew÷ôxÔŽ1ípùúªÎou¿Þ]u}8ïO-< ëéÏãŽy‚-`‹çŽU Ô(¦‘„ë©ö©œUgæå€Jª.²T(óKÝ9÷òBH%0{§±T—0¹p`ùÙï@h û¯¥xÿuîáîK=#-Ù’˜”â(¬*jµU-_yÜFýò˜“¬ |1ãËE}âV-K@¤pA0Õa»>oÓpœ>}¸=2+tØÏ¼wãÞ×^1“¿sÿ¼çk»l鸾"I’¯¿yz_PD("RØT/Qœì¾'eÚfÍɼj ­†“hÉ9åyC]®©©ØŸþ©,4ÆoëFˆlélqy`‘ bO–¬4rï&¿) <¯ÕžÎ/8uÎT˜6w<ìà4xØÜá º`Nͽ@ÊbY%Ý‹ÓkN/øM¡‹Zð“@œ´è2>?iÁJÂ8ÁEm4lŸˆ›H¯Ñ 郜þjo‹O`LDd¸FÐ¥éL&ÉEiËìd“RS0†bJ¥EUoôÐùk„Öãú•«6F&å'f£ï ¯£47M%”X/á»É,<Œ\þIH6…MP_’›¡Ê-2N6Oû6ÓÆã›iPœœS€?Ú ´/BŽø¾$?;S9)šˆP´ 9¢\ÔÿäŒæ­Ìù¥÷6Tª&K“Ãv³ü]çÐÞyòÅŒ¯ß˜ÿ0”ÓàTÉ¥çgëKZêÁ9ª…ÿw¯£·¹nª’hµ•¥u)y)j¦ºîTö!@½:/JdÑøù`&ØMíq‡òÔûqrå¡¥ô»ˆª{°} ¯ÐößùÔÿ̦;‹Û"Å— “$ùÉYi,œ‹8Åh6nó&îE,9]‚ëPIjau=Ü… }®ù ð¬6à_œãmß·Á²ã 1tZºIòÍw›ìPÿ—»­?…Kn(FËÑ(4 GŸ¢Oà@äŸ>ºT_cÓ@b"ë䛀['b$àøþËW¿ÕH\SÉ®B·èÞWï?:yñè‰ãë\\<×ï2:ò©6Ú° =¿]»¥q¸ipDÂχóþ ž€jZ°WÓá]+N9€Ò–—Æç*T,¿ô“}E¸âX]˜S6ÔïfÐàeé5ªÏA=ˆûA ,TåšÁ âš4W’“0.F"Ê—b˜pÖ"bm|rœRAèa¾­ˆPº‚P'Ü·ìË­W~®¨1/ÝÛ±¸uàcÜ|övmÑq®f÷ç*n°:q?]­Z†)oÇyä~܆;pç«h8ÆÂth K€fLYñ ‹Æp{Ù ŽAcÉxàߌ˜‰å­@ùl˜b‡¾F§ä%•FJ(‰IÊL̳ðÑŸŸd%æÄV'MqiYNj^šºûÐ%–¢!ZcAŸ`$"lΠ%î;Äñ©‰i1)X wÓ« °nÏ!¯Ý‚ ßzþ>u¶*=ÛÊR ¹‹oGw÷N®V½Þ”?Ç¢)V×®æ#rc¨ê0§ï<¼u˾oYX2i[;0¤ /éøl9H3 Y èê(IJJ±Tr^PU¦Z•]À¼i³¦H–ÔÀ©*¯)»T–ŸÍ𠻇¬ÛÿÎUxÀ”C¦üvX¦ÛÔ]¨»K¿@\d¿bûÊÀj©Æ¸Ÿ"y^ZÓØxËøþãÍ3~ž!ÿð(6(‚¯ðS¬O•Jñ~3&"s’üõì§ëÖlX=}÷ÂüS¸›ÌVãn²çíÚ™?¯Ãrø·Ïžciní¸âÚ`´ÉíÝn8<†¿ ç}kp5|I—HJÄ òy2!–âî=)7® ®P¨ á L,ˆJB£ps).—䫳ÔÙLC]MIÈ9²ÂøÂ8Mô~P êJ*K5Åõ Œ˜oX– å“(&›«ë§ïÏô³ ³ï«³·×Û ˆÿ½©ü‹ endstream endobj 1048 0 obj <>stream 2023-07-18T13:29:08-04:00 2023-07-18T13:29:08-04:00 dvips(k) 5.998 Copyright 2018 Radical Eye Software cfitsio.dvi endstream endobj 2 0 obj <>endobj xref 0 1049 0000000000 65535 f 0000834998 00000 n 0000902426 00000 n 0000833339 00000 n 0000799105 00000 n 0000000015 00000 n 0000000880 00000 n 0000835065 00000 n 0000855758 00000 n 0000881039 00000 n 0000855433 00000 n 0000878990 00000 n 0000854691 00000 n 0000868858 00000 n 0000835106 00000 n 0000835136 00000 n 0000799265 00000 n 0000000899 00000 n 0000001063 00000 n 0000835188 00000 n 0000835218 00000 n 0000799427 00000 n 0000001082 00000 n 0000002937 00000 n 0000854133 00000 n 0000862966 00000 n 0000835250 00000 n 0000835280 00000 n 0000799589 00000 n 0000002958 00000 n 0000005423 00000 n 0000853815 00000 n 0000858123 00000 n 0000835332 00000 n 0000835362 00000 n 0000799751 00000 n 0000005444 00000 n 0000007758 00000 n 0000835416 00000 n 0000835446 00000 n 0000799913 00000 n 0000007779 00000 n 0000010021 00000 n 0000835500 00000 n 0000835530 00000 n 0000800075 00000 n 0000010042 00000 n 0000011151 00000 n 0000835584 00000 n 0000835614 00000 n 0000800237 00000 n 0000011172 00000 n 0000011393 00000 n 0000835668 00000 n 0000835698 00000 n 0000800399 00000 n 0000011413 00000 n 0000015404 00000 n 0000835741 00000 n 0000835771 00000 n 0000800561 00000 n 0000015425 00000 n 0000020507 00000 n 0000857510 00000 n 0000892187 00000 n 0000835812 00000 n 0000835842 00000 n 0000800723 00000 n 0000020528 00000 n 0000026148 00000 n 0000835905 00000 n 0000835935 00000 n 0000800893 00000 n 0000026169 00000 n 0000029158 00000 n 0000835978 00000 n 0000836008 00000 n 0000801055 00000 n 0000029179 00000 n 0000032343 00000 n 0000836060 00000 n 0000836090 00000 n 0000801217 00000 n 0000032364 00000 n 0000036949 00000 n 0000836142 00000 n 0000836172 00000 n 0000801387 00000 n 0000036970 00000 n 0000041204 00000 n 0000836226 00000 n 0000836256 00000 n 0000801557 00000 n 0000041225 00000 n 0000045254 00000 n 0000836319 00000 n 0000836349 00000 n 0000801727 00000 n 0000045275 00000 n 0000050582 00000 n 0000836403 00000 n 0000836434 00000 n 0000801899 00000 n 0000050603 00000 n 0000054200 00000 n 0000836498 00000 n 0000836529 00000 n 0000802073 00000 n 0000054222 00000 n 0000054823 00000 n 0000836593 00000 n 0000836624 00000 n 0000802239 00000 n 0000054844 00000 n 0000055159 00000 n 0000836679 00000 n 0000836710 00000 n 0000802405 00000 n 0000055180 00000 n 0000058882 00000 n 0000857010 00000 n 0000891133 00000 n 0000836754 00000 n 0000836785 00000 n 0000802571 00000 n 0000058904 00000 n 0000063500 00000 n 0000836851 00000 n 0000836882 00000 n 0000802737 00000 n 0000063522 00000 n 0000066962 00000 n 0000836950 00000 n 0000836981 00000 n 0000802911 00000 n 0000066984 00000 n 0000069427 00000 n 0000837034 00000 n 0000837065 00000 n 0000803077 00000 n 0000069449 00000 n 0000071255 00000 n 0000837120 00000 n 0000837151 00000 n 0000803243 00000 n 0000071277 00000 n 0000075581 00000 n 0000837206 00000 n 0000837237 00000 n 0000803409 00000 n 0000075603 00000 n 0000080350 00000 n 0000837301 00000 n 0000837332 00000 n 0000803583 00000 n 0000080372 00000 n 0000085712 00000 n 0000837387 00000 n 0000837418 00000 n 0000803757 00000 n 0000085734 00000 n 0000089681 00000 n 0000837482 00000 n 0000837513 00000 n 0000803931 00000 n 0000089703 00000 n 0000094233 00000 n 0000837568 00000 n 0000837599 00000 n 0000804105 00000 n 0000094255 00000 n 0000099249 00000 n 0000837676 00000 n 0000837707 00000 n 0000804279 00000 n 0000099271 00000 n 0000104586 00000 n 0000837782 00000 n 0000837813 00000 n 0000804453 00000 n 0000104608 00000 n 0000109749 00000 n 0000837877 00000 n 0000837908 00000 n 0000804627 00000 n 0000109771 00000 n 0000115992 00000 n 0000837972 00000 n 0000838003 00000 n 0000804801 00000 n 0000116014 00000 n 0000121564 00000 n 0000838047 00000 n 0000838078 00000 n 0000804975 00000 n 0000121586 00000 n 0000127501 00000 n 0000838144 00000 n 0000838175 00000 n 0000805149 00000 n 0000127523 00000 n 0000131248 00000 n 0000838228 00000 n 0000838259 00000 n 0000805323 00000 n 0000131270 00000 n 0000131573 00000 n 0000838316 00000 n 0000838347 00000 n 0000805489 00000 n 0000131594 00000 n 0000135494 00000 n 0000856853 00000 n 0000890503 00000 n 0000838391 00000 n 0000838422 00000 n 0000805655 00000 n 0000135516 00000 n 0000138317 00000 n 0000838499 00000 n 0000838530 00000 n 0000805829 00000 n 0000138339 00000 n 0000144669 00000 n 0000838605 00000 n 0000838636 00000 n 0000806003 00000 n 0000144691 00000 n 0000149687 00000 n 0000838691 00000 n 0000838722 00000 n 0000806169 00000 n 0000149709 00000 n 0000154583 00000 n 0000838788 00000 n 0000838819 00000 n 0000806343 00000 n 0000154605 00000 n 0000158557 00000 n 0000838894 00000 n 0000838925 00000 n 0000806517 00000 n 0000158579 00000 n 0000162603 00000 n 0000838991 00000 n 0000839022 00000 n 0000806683 00000 n 0000162625 00000 n 0000167269 00000 n 0000839097 00000 n 0000839128 00000 n 0000806857 00000 n 0000167291 00000 n 0000171989 00000 n 0000839203 00000 n 0000839234 00000 n 0000807031 00000 n 0000172011 00000 n 0000176509 00000 n 0000839300 00000 n 0000839331 00000 n 0000807205 00000 n 0000176531 00000 n 0000180861 00000 n 0000839397 00000 n 0000839428 00000 n 0000807379 00000 n 0000180883 00000 n 0000183844 00000 n 0000839503 00000 n 0000839534 00000 n 0000807545 00000 n 0000183866 00000 n 0000188078 00000 n 0000839600 00000 n 0000839631 00000 n 0000807711 00000 n 0000188100 00000 n 0000192255 00000 n 0000839706 00000 n 0000839737 00000 n 0000807885 00000 n 0000192277 00000 n 0000196829 00000 n 0000839803 00000 n 0000839834 00000 n 0000808051 00000 n 0000196851 00000 n 0000200914 00000 n 0000839900 00000 n 0000839931 00000 n 0000808225 00000 n 0000200936 00000 n 0000205279 00000 n 0000839997 00000 n 0000840028 00000 n 0000808391 00000 n 0000205301 00000 n 0000211746 00000 n 0000840103 00000 n 0000840134 00000 n 0000808565 00000 n 0000211768 00000 n 0000218334 00000 n 0000840178 00000 n 0000840209 00000 n 0000808739 00000 n 0000218356 00000 n 0000222185 00000 n 0000840253 00000 n 0000840284 00000 n 0000808913 00000 n 0000222207 00000 n 0000226705 00000 n 0000840339 00000 n 0000840370 00000 n 0000809087 00000 n 0000226727 00000 n 0000229387 00000 n 0000840425 00000 n 0000840456 00000 n 0000809253 00000 n 0000229409 00000 n 0000234615 00000 n 0000840511 00000 n 0000840542 00000 n 0000809427 00000 n 0000234637 00000 n 0000239029 00000 n 0000840617 00000 n 0000840648 00000 n 0000809601 00000 n 0000239051 00000 n 0000243804 00000 n 0000840714 00000 n 0000840745 00000 n 0000809775 00000 n 0000243826 00000 n 0000247334 00000 n 0000840811 00000 n 0000840842 00000 n 0000809949 00000 n 0000247356 00000 n 0000251258 00000 n 0000840917 00000 n 0000840948 00000 n 0000810123 00000 n 0000251280 00000 n 0000255067 00000 n 0000841014 00000 n 0000841045 00000 n 0000810289 00000 n 0000255089 00000 n 0000260916 00000 n 0000841120 00000 n 0000841151 00000 n 0000810455 00000 n 0000260938 00000 n 0000265541 00000 n 0000841217 00000 n 0000841248 00000 n 0000810629 00000 n 0000265563 00000 n 0000270210 00000 n 0000841314 00000 n 0000841345 00000 n 0000810803 00000 n 0000270232 00000 n 0000274660 00000 n 0000841420 00000 n 0000841451 00000 n 0000810977 00000 n 0000274682 00000 n 0000279478 00000 n 0000841517 00000 n 0000841548 00000 n 0000811151 00000 n 0000279500 00000 n 0000283073 00000 n 0000841623 00000 n 0000841654 00000 n 0000811317 00000 n 0000283095 00000 n 0000287744 00000 n 0000841720 00000 n 0000841751 00000 n 0000811483 00000 n 0000287766 00000 n 0000291243 00000 n 0000841826 00000 n 0000841857 00000 n 0000811649 00000 n 0000291265 00000 n 0000295572 00000 n 0000841923 00000 n 0000841954 00000 n 0000811823 00000 n 0000295594 00000 n 0000299772 00000 n 0000842029 00000 n 0000842060 00000 n 0000811989 00000 n 0000299794 00000 n 0000304208 00000 n 0000842135 00000 n 0000842166 00000 n 0000812163 00000 n 0000304230 00000 n 0000307726 00000 n 0000842232 00000 n 0000842263 00000 n 0000812329 00000 n 0000307748 00000 n 0000311043 00000 n 0000842329 00000 n 0000842360 00000 n 0000812495 00000 n 0000311065 00000 n 0000315602 00000 n 0000842426 00000 n 0000842457 00000 n 0000812669 00000 n 0000315624 00000 n 0000320059 00000 n 0000842523 00000 n 0000842554 00000 n 0000812835 00000 n 0000320081 00000 n 0000324285 00000 n 0000842620 00000 n 0000842651 00000 n 0000813001 00000 n 0000324307 00000 n 0000328243 00000 n 0000842717 00000 n 0000842748 00000 n 0000813175 00000 n 0000328265 00000 n 0000330973 00000 n 0000842803 00000 n 0000842834 00000 n 0000813341 00000 n 0000330995 00000 n 0000335904 00000 n 0000842900 00000 n 0000842931 00000 n 0000813515 00000 n 0000335926 00000 n 0000336337 00000 n 0000842997 00000 n 0000843028 00000 n 0000813681 00000 n 0000336358 00000 n 0000340464 00000 n 0000843083 00000 n 0000843114 00000 n 0000813855 00000 n 0000340486 00000 n 0000345076 00000 n 0000843169 00000 n 0000843200 00000 n 0000814021 00000 n 0000345098 00000 n 0000349970 00000 n 0000843277 00000 n 0000843308 00000 n 0000814187 00000 n 0000349992 00000 n 0000354709 00000 n 0000843363 00000 n 0000843394 00000 n 0000814353 00000 n 0000354731 00000 n 0000360085 00000 n 0000843471 00000 n 0000843502 00000 n 0000814527 00000 n 0000360107 00000 n 0000365235 00000 n 0000843568 00000 n 0000843599 00000 n 0000814693 00000 n 0000365257 00000 n 0000367040 00000 n 0000843674 00000 n 0000843705 00000 n 0000814859 00000 n 0000367062 00000 n 0000367489 00000 n 0000843771 00000 n 0000843802 00000 n 0000815025 00000 n 0000367510 00000 n 0000371783 00000 n 0000843857 00000 n 0000843888 00000 n 0000815199 00000 n 0000371805 00000 n 0000377023 00000 n 0000843952 00000 n 0000843983 00000 n 0000815373 00000 n 0000377045 00000 n 0000380809 00000 n 0000844058 00000 n 0000844089 00000 n 0000815547 00000 n 0000380831 00000 n 0000381500 00000 n 0000844155 00000 n 0000844186 00000 n 0000815713 00000 n 0000381521 00000 n 0000386120 00000 n 0000856360 00000 n 0000887578 00000 n 0000844241 00000 n 0000844272 00000 n 0000815887 00000 n 0000386142 00000 n 0000391446 00000 n 0000844327 00000 n 0000844358 00000 n 0000816061 00000 n 0000391468 00000 n 0000396630 00000 n 0000844433 00000 n 0000844464 00000 n 0000816235 00000 n 0000396652 00000 n 0000400849 00000 n 0000844530 00000 n 0000844561 00000 n 0000816401 00000 n 0000400871 00000 n 0000405594 00000 n 0000844636 00000 n 0000844667 00000 n 0000816575 00000 n 0000405616 00000 n 0000406162 00000 n 0000844733 00000 n 0000844764 00000 n 0000816741 00000 n 0000406183 00000 n 0000410391 00000 n 0000844819 00000 n 0000844850 00000 n 0000816915 00000 n 0000410413 00000 n 0000415379 00000 n 0000844903 00000 n 0000844934 00000 n 0000817089 00000 n 0000415401 00000 n 0000419913 00000 n 0000845000 00000 n 0000845031 00000 n 0000817263 00000 n 0000419935 00000 n 0000424781 00000 n 0000845110 00000 n 0000845141 00000 n 0000817437 00000 n 0000424803 00000 n 0000428578 00000 n 0000845207 00000 n 0000845238 00000 n 0000817611 00000 n 0000428600 00000 n 0000433176 00000 n 0000845313 00000 n 0000845344 00000 n 0000817785 00000 n 0000433198 00000 n 0000437991 00000 n 0000845419 00000 n 0000845450 00000 n 0000817959 00000 n 0000438013 00000 n 0000442281 00000 n 0000845516 00000 n 0000845547 00000 n 0000818133 00000 n 0000442303 00000 n 0000446738 00000 n 0000845622 00000 n 0000845653 00000 n 0000818307 00000 n 0000446760 00000 n 0000449868 00000 n 0000845719 00000 n 0000845750 00000 n 0000818481 00000 n 0000449890 00000 n 0000454241 00000 n 0000845825 00000 n 0000845856 00000 n 0000818655 00000 n 0000454263 00000 n 0000458222 00000 n 0000845922 00000 n 0000845953 00000 n 0000818829 00000 n 0000458244 00000 n 0000461633 00000 n 0000846028 00000 n 0000846059 00000 n 0000818995 00000 n 0000461655 00000 n 0000465197 00000 n 0000846134 00000 n 0000846165 00000 n 0000819169 00000 n 0000465219 00000 n 0000469128 00000 n 0000846231 00000 n 0000846262 00000 n 0000819335 00000 n 0000469150 00000 n 0000472619 00000 n 0000846337 00000 n 0000846368 00000 n 0000819501 00000 n 0000472641 00000 n 0000476928 00000 n 0000846443 00000 n 0000846474 00000 n 0000819667 00000 n 0000476950 00000 n 0000483274 00000 n 0000846549 00000 n 0000846580 00000 n 0000819841 00000 n 0000483296 00000 n 0000486979 00000 n 0000846644 00000 n 0000846675 00000 n 0000820015 00000 n 0000487001 00000 n 0000489408 00000 n 0000846741 00000 n 0000846772 00000 n 0000820181 00000 n 0000489430 00000 n 0000493033 00000 n 0000846838 00000 n 0000846869 00000 n 0000820347 00000 n 0000493055 00000 n 0000497032 00000 n 0000846944 00000 n 0000846975 00000 n 0000820513 00000 n 0000497054 00000 n 0000500817 00000 n 0000847041 00000 n 0000847072 00000 n 0000820679 00000 n 0000500839 00000 n 0000506100 00000 n 0000847147 00000 n 0000847178 00000 n 0000820853 00000 n 0000506122 00000 n 0000511386 00000 n 0000847253 00000 n 0000847284 00000 n 0000821027 00000 n 0000511408 00000 n 0000515272 00000 n 0000847350 00000 n 0000847381 00000 n 0000821193 00000 n 0000515294 00000 n 0000520115 00000 n 0000847447 00000 n 0000847478 00000 n 0000821367 00000 n 0000520137 00000 n 0000520861 00000 n 0000847544 00000 n 0000847575 00000 n 0000821533 00000 n 0000520882 00000 n 0000524489 00000 n 0000847630 00000 n 0000847661 00000 n 0000821699 00000 n 0000524511 00000 n 0000529604 00000 n 0000847716 00000 n 0000847747 00000 n 0000821865 00000 n 0000529626 00000 n 0000534343 00000 n 0000847815 00000 n 0000847846 00000 n 0000822031 00000 n 0000534365 00000 n 0000538523 00000 n 0000847914 00000 n 0000847945 00000 n 0000822197 00000 n 0000538545 00000 n 0000543546 00000 n 0000848009 00000 n 0000848040 00000 n 0000822371 00000 n 0000543568 00000 n 0000548666 00000 n 0000848104 00000 n 0000848135 00000 n 0000822537 00000 n 0000548688 00000 n 0000553406 00000 n 0000848201 00000 n 0000848232 00000 n 0000822711 00000 n 0000553428 00000 n 0000556094 00000 n 0000848296 00000 n 0000848327 00000 n 0000822877 00000 n 0000556116 00000 n 0000561395 00000 n 0000848382 00000 n 0000848413 00000 n 0000823051 00000 n 0000561417 00000 n 0000566620 00000 n 0000848477 00000 n 0000848508 00000 n 0000823217 00000 n 0000566642 00000 n 0000572126 00000 n 0000848563 00000 n 0000848594 00000 n 0000823383 00000 n 0000572148 00000 n 0000576937 00000 n 0000848658 00000 n 0000848689 00000 n 0000823549 00000 n 0000576959 00000 n 0000581857 00000 n 0000848757 00000 n 0000848788 00000 n 0000823723 00000 n 0000581879 00000 n 0000587385 00000 n 0000848852 00000 n 0000848883 00000 n 0000823889 00000 n 0000587407 00000 n 0000591679 00000 n 0000848938 00000 n 0000848969 00000 n 0000824055 00000 n 0000591701 00000 n 0000596160 00000 n 0000849033 00000 n 0000849064 00000 n 0000824221 00000 n 0000596182 00000 n 0000601101 00000 n 0000849128 00000 n 0000849159 00000 n 0000824387 00000 n 0000601123 00000 n 0000606262 00000 n 0000849236 00000 n 0000849267 00000 n 0000824553 00000 n 0000606284 00000 n 0000610844 00000 n 0000849335 00000 n 0000849366 00000 n 0000824719 00000 n 0000610866 00000 n 0000613923 00000 n 0000849434 00000 n 0000849465 00000 n 0000824885 00000 n 0000613945 00000 n 0000619643 00000 n 0000849533 00000 n 0000849564 00000 n 0000825051 00000 n 0000619665 00000 n 0000623713 00000 n 0000849641 00000 n 0000849672 00000 n 0000825217 00000 n 0000623735 00000 n 0000629094 00000 n 0000849727 00000 n 0000849758 00000 n 0000825383 00000 n 0000629116 00000 n 0000633276 00000 n 0000849813 00000 n 0000849844 00000 n 0000825557 00000 n 0000633298 00000 n 0000636952 00000 n 0000849908 00000 n 0000849939 00000 n 0000825723 00000 n 0000636974 00000 n 0000642257 00000 n 0000850016 00000 n 0000850047 00000 n 0000825889 00000 n 0000642279 00000 n 0000647697 00000 n 0000850115 00000 n 0000850146 00000 n 0000826055 00000 n 0000647719 00000 n 0000653112 00000 n 0000850223 00000 n 0000850254 00000 n 0000826221 00000 n 0000653134 00000 n 0000657562 00000 n 0000850318 00000 n 0000850349 00000 n 0000826387 00000 n 0000657584 00000 n 0000663054 00000 n 0000850404 00000 n 0000850435 00000 n 0000826553 00000 n 0000663076 00000 n 0000668156 00000 n 0000850499 00000 n 0000850530 00000 n 0000826719 00000 n 0000668178 00000 n 0000670922 00000 n 0000850585 00000 n 0000850616 00000 n 0000826885 00000 n 0000670944 00000 n 0000675495 00000 n 0000850680 00000 n 0000850711 00000 n 0000827051 00000 n 0000675517 00000 n 0000680224 00000 n 0000850775 00000 n 0000850806 00000 n 0000827217 00000 n 0000680246 00000 n 0000684506 00000 n 0000850861 00000 n 0000850892 00000 n 0000827383 00000 n 0000684528 00000 n 0000685790 00000 n 0000850947 00000 n 0000850978 00000 n 0000827549 00000 n 0000685812 00000 n 0000689922 00000 n 0000851033 00000 n 0000851064 00000 n 0000827723 00000 n 0000689944 00000 n 0000694546 00000 n 0000851117 00000 n 0000851148 00000 n 0000827889 00000 n 0000694568 00000 n 0000698109 00000 n 0000851212 00000 n 0000851243 00000 n 0000828055 00000 n 0000698131 00000 n 0000701264 00000 n 0000851307 00000 n 0000851338 00000 n 0000828229 00000 n 0000701286 00000 n 0000703663 00000 n 0000851402 00000 n 0000851433 00000 n 0000828395 00000 n 0000703685 00000 n 0000703964 00000 n 0000851488 00000 n 0000851519 00000 n 0000828561 00000 n 0000703985 00000 n 0000708226 00000 n 0000851563 00000 n 0000851594 00000 n 0000828735 00000 n 0000708248 00000 n 0000712886 00000 n 0000851636 00000 n 0000851667 00000 n 0000828909 00000 n 0000712908 00000 n 0000718279 00000 n 0000851722 00000 n 0000851753 00000 n 0000829083 00000 n 0000718301 00000 n 0000723887 00000 n 0000851817 00000 n 0000851848 00000 n 0000829257 00000 n 0000723909 00000 n 0000725426 00000 n 0000851912 00000 n 0000851943 00000 n 0000829423 00000 n 0000725448 00000 n 0000725749 00000 n 0000851987 00000 n 0000852018 00000 n 0000829589 00000 n 0000725770 00000 n 0000730186 00000 n 0000852062 00000 n 0000852093 00000 n 0000829755 00000 n 0000730208 00000 n 0000735803 00000 n 0000852135 00000 n 0000852166 00000 n 0000829929 00000 n 0000735825 00000 n 0000741810 00000 n 0000852230 00000 n 0000852261 00000 n 0000830103 00000 n 0000741832 00000 n 0000748158 00000 n 0000852316 00000 n 0000852347 00000 n 0000830277 00000 n 0000748180 00000 n 0000750659 00000 n 0000852391 00000 n 0000852422 00000 n 0000830451 00000 n 0000750681 00000 n 0000750977 00000 n 0000852466 00000 n 0000852497 00000 n 0000830617 00000 n 0000750998 00000 n 0000751173 00000 n 0000852541 00000 n 0000852572 00000 n 0000830783 00000 n 0000751194 00000 n 0000756074 00000 n 0000852605 00000 n 0000852636 00000 n 0000830957 00000 n 0000756096 00000 n 0000762686 00000 n 0000852689 00000 n 0000852720 00000 n 0000831131 00000 n 0000762708 00000 n 0000764621 00000 n 0000852753 00000 n 0000852784 00000 n 0000831305 00000 n 0000764643 00000 n 0000768247 00000 n 0000852828 00000 n 0000852859 00000 n 0000831479 00000 n 0000768269 00000 n 0000768930 00000 n 0000852903 00000 n 0000852934 00000 n 0000831653 00000 n 0000768951 00000 n 0000771923 00000 n 0000852978 00000 n 0000853009 00000 n 0000831819 00000 n 0000771945 00000 n 0000775794 00000 n 0000853062 00000 n 0000853093 00000 n 0000831985 00000 n 0000775816 00000 n 0000779426 00000 n 0000853148 00000 n 0000853179 00000 n 0000832151 00000 n 0000779448 00000 n 0000782849 00000 n 0000853223 00000 n 0000853255 00000 n 0000832319 00000 n 0000782872 00000 n 0000786507 00000 n 0000853311 00000 n 0000853343 00000 n 0000832489 00000 n 0000786530 00000 n 0000788523 00000 n 0000853388 00000 n 0000853420 00000 n 0000832659 00000 n 0000788546 00000 n 0000791147 00000 n 0000853476 00000 n 0000853508 00000 n 0000832829 00000 n 0000791170 00000 n 0000793834 00000 n 0000853562 00000 n 0000853594 00000 n 0000832999 00000 n 0000793857 00000 n 0000796390 00000 n 0000853650 00000 n 0000853682 00000 n 0000833169 00000 n 0000796413 00000 n 0000799082 00000 n 0000853727 00000 n 0000853759 00000 n 0000858458 00000 n 0000863339 00000 n 0000869472 00000 n 0000879264 00000 n 0000881457 00000 n 0000887845 00000 n 0000890726 00000 n 0000891386 00000 n 0000892860 00000 n 0000854605 00000 n 0000855248 00000 n 0000856257 00000 n 0000856767 00000 n 0000857376 00000 n 0000858029 00000 n 0000900968 00000 n trailer << /Size 1049 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 902632 %%EOF cfitsio-4.3.1/docs/changes.txt0000644000225700000360000065543714523044740015575 0ustar cagordonlhea Log of Changes Made to CFITSIO Version 4.3.1 - Nov 2023 - Patch fix needed for modify and delete keyword functions to fully conform with v4.3.0 long string keyword read/write enhancements. Version 4.3.0 - Jul 2023 - Bug fix to fits_make_hist[d] that was introduced in 4.2.0. - Added overflow checking for case of reading images with 8-byte float values into 4-byte float arrays. - fits_write_key_longstr now handles case of writing a long keyword in combination with a long keyword value string. - Add conversion of French locale comma-to-period in corner cases appearing in ffr2e and ffd2e functions. - Increased the precision when writing version number to User-Agent strings for http connections. This is needed to fully conform to 3-field version string format. - Bug fix to GTIOVERLAP() calculator function, which was being treated as a boolean value in expressions, and is now correctly treated as a floating point result. - Bug fix to ARRAY() calculator function, which caused a memory overflow error - Enhancement to the ARRAY function, such that ARRAY(V,d) can apply new dimensions to V, as long as the total number of array/vector elements does not change. - Enhancement of long string keyword read/write functions to fully conform with FITS standard specifications for multi-line value and comment strings. Two new functions have been added to implement this: fits_get_key_com_strlen and fits_read_string_key_com. Version 4.2.0 - Nov 2022 - This release includes patches to security vulnerabilities. We strongly encourage this upgrade, particularly for those running CFITSIO in web accessible applications. - Fix to fits_read_key function, which was failing to properly read keywords declared type TUINT on compilers where sizeof(int) = sizeof(long). - Added new functions fits_read_cols and fits_write_cols to efficiently read or write multiple columns in a single function call - Added new function fits_copy_selrows to copy only selected rows, such as the selected rows returned by fits_find_rows - Added new calculator functions ERF(X), ERFC(X) and GAMMA(X), which are mathematical special functions of the same name - Added new calculator function GTIFIND() which reports which GTI row brackets a given time sample - Added new calculator functions which operate upon vector table values NAXIS(V), NAXES(V,n), ELEMENTNUM(V) and AXISELEM(V,n), and ARRAY(X,d) which promotes scalar X to a vector or array with given dimensions. - The CFITSIO histogramming code now handles binning by any arbitrary calculator expression rather than just a column name. Both the binned columns as well as the optional weights may be calculator expressions, enclosed in parentheses. - Binning of vector columns or expressions is now supported, as long as all binned inputs (as well as the optional weighting) have the same vector dimensions. Binning of variable-length columns remains unsupported. - A bug that caused histogram weights from columns that are null values to be tallied along with non-null values has been fixed. - The CFITSIO calculator and histogramming functionality is now fully reentrant and does not require multithreading interlocks. - A long-standing segmentation fault bug in the histogramming code related to binning any value using the "reciprocal" /XXXX notation has been fixed. - Added mutex locks for thread safety in ftgiou and ftfiou. - Added several Fortran wrappers to support image read/write when 'fpixel' and 'nelements' are 8-byte integers. - Fixed bug which was adding spaces to some cases of long string key value output. Version 4.1.0 - Feb 2022 - Calls to the zlib inflate() function in zcompress.c now handle the Z_BUF_ERROR return value rather than exiting. - The SUBTRACTIVE_DITHER_2 option has been removed when using the HCOMPRESS algorithm. - Updated fits_get_version function to return a float calculated from 3 version fields. - Added handling of SBYTE_IMG and ULONGLONG_IMG types to the fits_resize_img function. - Updates made to C/Fortran interfacing in cfortran.h and f77_wrap.h specifically driven by new Mac/ARM architecture. - Fix to the fits_insert_col functions to handle columns with TULONGLONG data. Version 4.0.0 - May 2021 - Removed separate directory for zlib/gzip code, and updated configuration to check for zlib on the user's system (required). When use of cURL is enabled, it may also pull in zlib such that user applications may not need to link with it separately. - Changed version numbering to 3-field format. - Added new calculator functions SETNULL(x,y) to allow substitution of NULL values into tables, and GTIOVERLAP() for calculating the amount of GTI overlap exposure for a time bin. - Fix added for proper handling of string columns with zero repeat count. - Fix to column filtering expressions which write #NULL values to columns of type (J) format. - Fix to memory clearing when using polygon shapes in region files. - Fix to fits_str2time function so that it now flags a particular case of bad syntax which was previously getting through. - In ffgclb and ffpclb (read/write byte columns), the "undocumented" feature of being able to transfer columns 'A' string columnss as byte arrays is now handled correctly, with improved error checking via updates to ffgcprll. More documentation on string handling is in cfitsio.tex. - Fix bug in 'colfilter' functionality. When performing a column deletion of the form -COLNAM*, and multiple matches existed, then none of the matches got deleted. Now the first is deleted as expected. - Improved handling of corner case in ffpkn functions. - In ffgky, modified TULONG case to allow it to read unsigned values greater than the 8-byte signed limit. - Fix to parsing of corner case of extended file syntax. - Major updates to CMake configuration. Version 3.49 - Aug 2020 - Fix to imcompress.c. It now turns off quantization if ZSCALE and ZZERO columns are missing. Treatment will be the same as if ZQUANTIZ were set to 'NONE', even if ZQUANTIZ is present and set to something else. - Added mutex to fits_execute_template() function so that the creation of files using ASCII templates will be thread safe. - In fpack when using -table flag, replaced warning message with a more detailed description mentioning FITS format update. - Added flag to CMake builds to disable curl dependency. Also only add CURL_LIBRARIES to CMake link target if curl is found. - Minor adjustment to download progress output. Version 3.48 - Mar 2020 - Now can handle parentheses in path names rather than automatically interpreting them as output file specifiers. - Fixed bug in imcompress.c that wasn't properly handling conversion between float and double types when reading from a gzip compressed float or double image. - Fixed bug that was preventing use of bracket and parentheses symbols in pathnames when opening multiple READWRITE files, even when requesting no-extended-syntax usage. *This fix necessitates a library interface version number change. - Fixed bug in ffmnhd / fits_movnam_hdu to properly handle wildcard syntax. - Fixed bug in fits_open_extlist to handle filename[EXT] syntax properly. The hdutype parameter may now be null. More documentaion for this function is in cfitsio.tex. - Added new function fits_copy_hdutab to create a new table with the same structure as an existing table. - fits_copy_col / ffcpcl handles long long integer data types more natively to prevent precision loss. - histo.c routines now recognize integer columns that have been scaled by TSCALn keywords and may be closer to floating point type. - Added backward compatibility for very old Rice compressed files which were not using the ZVAL2 keyword in the way that later became standard. - Change made to cfitsio.pc.in to prevent forcing downstream libraries to link against cfitsio's dependencies when using pkgconfig. Version 3.47 - May 2019 - Added set of drivers for performing ftps file transfers. - Tile sizes for compression may now be specified for any pair of axes, where previously 2D tiles where limited to just X and y. - Fix to ffgsky and ffgkls functions for case of keyword with long string values where the final CONTINUE statement ended with '&'. If the final CONTINUE also contained a comment, it was being repeated twice when passed back through the 'comm' argument. - Fix made to ffedit_columns() for case of multiple col filters containing wildcards. Only the first filter was being searched. - fits_copy_rows (ffcprw) can now handle 'P'-type variable-length columns. - Fix made to an obscure case in fits_modify_vector_len, where a wrongly issued EOF error may occur. - Added internal fffvcl() function. Version 3.46 - Oct 2018 (Ftools release) - Improved the algorithm for ensuring no tile dimensions are smaller than 4 pixels for HCOMPRESS compression. - Added new functions intended to assist in diagnosing (primarily https) download issues: fits_show_download_progress, fits_get_timeout, fits_set_timeout. - Added the '-O ' option to fpack, which previously existed only for funpack. Also added fpack/funpack auto-removal of .bz2 suffix equivalent to what existed for .gz. - For the fpack '-table' cases, warning message is now sent to stderr instead of stdout. This is to allow users to pipe the results from stdout in valid FITS format. (The warning message is otherwise placed at the start of the FITS file and therefore corrupts it.) - Fix made to the '-P' file prefix option in funpack. - Added wildcard deletion syntax for columns, i.e. -COLNAM* will delete the first matching column as always; -COLNAM*+ will delete all matching columns (or none); exact symmetry with the keyword deletion syntax. Version 3.45 - May 2018 - New support for reading and writing unsigned long long datatypes. This includes 'implicit datatype conversion' between the unsigned long long datatype and all the other datatypes. - Increased the hardcoded NMAXFILES setting for maximum number of open files from 1000 to 10000. - Bug fix to fits_calc_binning wrapper function, which wasn't filling in the returned float variables. - Fixed a parsing bug for image subsection and column binning range specifiers that was introduced in v3.44. Version 3.44 - April 2018 - This release primarily patches security vulnerabilities. We strongly encourage this upgrade, particularly for those running CFITSIO in web accessible applications. In addition, the following enhancements and fixes were made: - Enhancement to 'template' and 'colfilter' functionality. It is now possible to delete multiple keywords using wildcard syntax. See "Column and Keyword Filtering Specification" section of manual for details. - histo.c uses double precision internally for all floating point binning; new double-precision subroutines fits_calc_binningd(), fits_rebin_wcsd(), and fits_make_histd(); existing single-precision histogram functions still work but convert values to double-precision internally. - new subroutine fits_copy_cols() / ffccls() to copy multiple columns - Fix in imcompress.c for HCOMPRESS and PLIO compression of unsigned short integers. - Fix to fits_insert_card(ffikey). It had wrongly been capitalizing letters that appeared before an '=' sign on a CONTINUE line. Version 3.43 - March 2018 The NASA security team requires the following warning to all users of CFITSIO: ===== The CFITSIO open source software project contains vulnerabilities that could allow a remote, unauthenticated attacker to take control of a server running the CFITSIO software. These vulnerabilities affect all servers and products running the CFITSIO software. The CFITSIO team has released software updates to address these vulnerabilities. There are no workarounds to address these vulnerabilities. In all cases, the CFITSIO team is recommending an immediate update to resolve the issues. ===== - Fixed security vulnerabilities. - Calls to https driver functions in cfileio.c need to be macro- protected by the HAVE_NET_SERVICES variable (as are the http and ftp driver function calls). Otherwise CMake builds on native Windows will fail since drvrnet.o is left empty. - Bug fix to ffmvec function. Should be resetting a local colptr variable after making a call to ffiblk (which can reallocate Ftpr-> tableptr). Originally reported by Willem van Straten. - Ignore any attempted request to not quantize an image before compressing it if the image has integer datatype pixels. - Improved error message construction throughout CFITSIO. Version 3.42 - August 2017 (Stand-alone release) - added https support to the collection of drivers handled in cfileio.c and drvrnet.c. This also handles the case where http transfers are rerouted to https. Note that this enhancement introduces a dependency on the libcurl development package. If this package is absent, CFITSIO will still build but will not have https capability. - made fix to imcomp_init_table function in imcompress.c. It now writes ZSIMPLE keyword only to a compressed image that will be placed in the primary header. - fix made to fits_get_col_display_width for case of a vector column of strings. Version 3.42 - March 2017 (Ftools release only) - in ftp_open_network and in ftp_file_exist, added code to repeatedly attempt to make a ftp connection if the ftp server does not respond to the first request. (some ftp servers don't appear to be 100% reliable). - in drvrnet.c added many calls to 'fclose' to close unneeded files, to avoid exceeding the maximum allowed number of files that can be open at once. - made substantial changes to the ftp_checkfile and http_checkfile routines to streamline the process of checking for the existence of a .gz or .Z compressed version of the file before opening the uncompressed file (when using http or ftp to open the file). - modified the code in ftp_open_network to send "\r\n" as end-of-line characters instead of just "\n". Some ftp servers (in particular, at heasarc.gsfc.nasa.gov) now require both characters, otherwise the network connection simply hangs. - modified the http_open_network routine to handle HTTP 301 or 302 redirects to a FTP url. This is needed to support the new configuration on the heasarc HTTP server which sometimes redirects http URLS to a ftp URL. Version 3.41 - November 2016 - The change made in version 3.40 to include strings.h caused problems on Windows (and other) platforms, so this change was backed out. The reason for including it was to define the strcasecmp and strcasencmp functions, so as an alternative, new equivalent functions called fits_strcasecmp and fits_strncasecmp have been added to CFITSIO.as a substitute. All the previous calls to the str[n]casecmp functions have been changed to now call fits_str[n]casecmp. In addition, the previously defined ngp_strcasecmp function (in grparser.c) has been removed and the calls to it have been changed to fits_strcasecmp. - The speed.c utility program was changed to correctly call the gettimeofday function with a NULL second arguement. Version 3.40 - October 2016 - fixed a bug when writing long string keywords with the CONTINUE convention which caused the CONTINUE'd strings to only be 16 characters long, instead of using up all the available space in the 80-character header record. - fixed a missing 'defined' keyword in fitsio.h. - replaced all calls to strtok (which is not threadsafe) with a new ffstrtok function which internally calls the threadsafe strtok_r function. One byproduct of this change is that must also be included in several of the C source code files. - modified the ffphbn function in putkey.c to support TFORM specifiers that use lowercase 'p' (instead of uppercase) when referring to a variable-length array column. - modified the lexical parser in eval.y and eval_y.c to support bit array columns (with TFORMn = 'X') with greater than 256 elements. Fix to bitcmp function: The internal 'stream' array is now allocated dynamically rather than statically fixed at size 256. This was failing when users attempted a row filtering of a bitcol that was wider than 256X. In bitlgte, bitand, and bitor functions, replaced static stream[256] array allocation with dynamic allocation. - modified the ffiter function in putcol.c to fix a problem which could cause the iterator function to incorrectly deal with null values. This only affected TLONG type columns in cases where sizeof(long) = 8, as well as for TLONGLONG type columns. - Fix made to uncompress2mem function in zcomprss.c for case where output uncompressed file expands to over the 2^32 (4Gb) limit. It now checks for this case at the start, and implements a 4Gb paging system through the output buffer. The problem was specifically caused by the d_stream.avail_out member being of 4-byte type uInt, and thus unable to handle any memory position values above 4Gb. - fixed a bug in fpackutil.c when using the -i2f (integer to float) option in fpack to compress an integer image that is scaled with non-default values for BSCALE and BZERO. This required an additional call to ffrhdu to reset the internal structures that describe the input FITS file. - modified fits_uncompress_table in imcompress.c to silently ignore the ZTILELEN keyword value if it larger than the number of rows in the table - Tweak strcasecmp/strncasecmp ifdefs to exclude 64-bit MINGW environment, as it does not lack those functions. (eval_l.c, fitsio2.h) - CMakeLists.txt: Set M_LIB to "" for MINGW build environment (in addition to MSVC). - Makefile.in: Add *.dSYM (non-XCode gcc leftovers on Macs) to clean list. Install libs by name rather than using a wildcard. - configure: Fix rpath token usage for XCode vs. non-XCode gcc on Macs. Version 3.39 - April 2016 - added 2 new routines suggested by Eric Mandel: ffhisto3 is similar to ffhisto2, except that it does not close the original file. fits_open_extlist is similar to fits_open_data except that it opens the FITS file and then moves to the first extension in the user-input list of 'interesting' extensions. - in ffpsvc and ffprec, it is necessary to treat CONTINUE, COMMENT, HISTORY, and blank name keywords as a special case which must be treated differently from other keywords because they have no value field and, by definition, have keyword names that are strictly limited in length. - added the Fortran wrapper routines for the 2 new string keyword reading routines (FTGSKY and FTGKSL), and documented all the routines in the FITSIO and CFITSIO users guides. - in ffinttyp, added explicit initialization of the input 'negative' argument to 0. - added new routine to return the length of the keyword value string: fits_get_key_strlen / ffgksl. This is primarily intended for use with string keywords that use the CONTINUE convention to continue the value over multiple header records, but this routine can be used to get the length of the value string for any type keyword. - added new routine to read string-valued keywords: fits_read_string_key / ffgsky This routine supports normal string keywords as well as long string keywords that use the CONTINUE convention. In many cases this routine may be more convenient to use then the older fits_read_key_longstr routine. - changed the prototype of fits_register_driver in fitsio2.h so that the pointer definition argument does not have the same name as the pointer itself (to work around a bug in the pgcc compiler). - added the missing FTDTDM fortran wrapper definition to f77_wrap3.c. - modified Makefile.in and configure.in to add LDFLAGS_BIN for task linker flages, which will be the same as LDFLAGS except on newer Mac OS X where an rpath flag is added. - modified Makefile.in to add a new "make utils" command which will build fpack, funpack, cookbook, fitscopy, imcopy, smem, speed, and testprog. These programs will be installed into $prfix/bin. - fixed a bug when attempting to modify the values in a variable-length bit ("X") column in a binary table. - reinstated the ability to write HIERARCH keywords that contain characters that would not be allowed in a normal 8-character keyword name, which had been disabled in the previous release. Version 3.38 - February 2016 - CRITICAL BUG FIX: The Intel 15 and 16 compilers (and potentially other compilers) may silently produce incorrect assembly code when compiling CFITSIO with the -O2 (or higher) optimization flag. In particular, this problem could cause CFITSIO to incorrectly read the values of arrays of 32-bit integers in a FITS file (i.e., images with BITPIX = 32 or table columns with TFORM = 'J') when the array is being read into a 'long' integer array in cases where the long array elements are 8 bytes long. One way to test if a particular system is affected by this problem is to compile CFITSIO V3.37 (or earlier) with optimization enabled, and then compare the output of the testprog.c program with the testprog.out file that is distributed with CFITSIO. If there are any differences in the files, then this system might be affected by this bug. Further tests should be performed to determine the exact cause. The root cause of this problem was traced to the fact that CFITSIO was aliasing an array of 32-bit integers and an array of 64-bit integers to the same memory location in order to obtain better data I/O efficiency when reading FITS files. When CFITSIO modified the values in these arrays, it was essential that the processing be done in strict sequential order from one end of the array to the other end, as was implicit in the C code algorithm. In this case, however, the compiler adopted certain loop optimization techniques that produced assembly code that violated this assumption. Technically, the CFITSIO code violates the "strict aliasing" assumption in ANSI C99, therefore the affected CFITSIO routines have been modified so that the aliasing of different data types to the same memory location no longer occurs. - fixed problem in configure and configure.in which caused the programs that are distributed with CFITSIO (most notably, fack and funpack) to be build without using any compiler optimization options, which could make them run more slowly than expected. - in imcompress.c, fixed bug where the rowspertile variable (declared as 'long') was mistakenly declared as a TLONGLONG variable in a call to fits_write_key. This could have caused the ZTILELEN keyword to be written incorrectly in the header of tile-compressed FITS tables on systems where sizeof(long) = 4. - in imcompress.c, implemented a new set of routines that safely convert shorter integer arrays into a longer integer arrays (e.g. short to int) where both arrays are aliased to the same memory location. These special routines were needed to guard against certain compiler optimization techniques that could produce incorrect code. - modified the 4 FnNoise5_(type) routines in quantize.c to correctly count the number of non-null pixels in the input array. Previously the count could be inaccurate if the image mainly consisted of null pixels. This could have caused certain floating point image tiles to be quantized during the image compression process, when in fact the tile did not satisfy all the criteria to be safely quantized. - in imcomp_copy_comp2img, added THEAP to the list of binary table keywords that may be present in the header of a compressed image and should not be copied to the uncompressed image header. - modified fits_copy_col to check that when copying a vector column, the vector length in the output column is the same as in the input column. Also modified the code to support the case where a column is being copied to an earlier position in the same table (which shifts the input column over 1 space). - added configure option (--with-bzip2) to support reading bzip2 compressed FITS files. This also required modifications to drvrmem.c and drvrfile.c This depends on having the bzlib library installed on the local machine. This patch was submitted by Dustin Lang. - replaced calls to 'memcpy' by 'memmove' in getcolb.c, getcold.c, getcole.c, and getcoli.c to support cases where the 2 memory areas overlap. (submitted by Aurelien Jarno) - modified the FITS keyword reading and writing routines to potentially support keywords with names longer than 8-characters. This was implemented in anticipation of a new experimental FITS convention which allows longer keyword names. - in fits_quantize_double in quantize.c, test if iseed == N_RANDOM, to avoid the (unlikely) possibility of overflowing the random number array bounds. (The corresponding fits_quantize_float routine already performed this test). - in the FnNoise5_short routine in quantize.c, change the first 'if' statement from "if (nx < 5)" to "if )nx < 9)", in order to support the (very rare) case where the tile is from 5 to 8 pixels wide. Also make the same change in the 3 other similar FnNoise5_* routines. - in the qtree_bitins64 routine in fits_hdecompress.c, must declare the plane_val variable as 'LONGLONG' instead of int. This bug could have caused integer overflow errors when uncompressing integer*4 images that had been compressed with the Hcompress algorithm, but only in cases where the image contains large regions of pixels whose values are close to the maximum integer*4 value of 2**31. - in fits_hcompress.c, call the calloc function instead of malloc when allocating the signbits array, to eliminate the need to individually set each byte to zero. - in the ffinit routine, and in a couple other routines that call ffinit, initialize the *fptr input parameter to NULL, even if the input status parameter value is greater than zero. This helps prevent errors later on if that fptr value is passed to ffclos. - modified ftcopy, in edithdu.c, to only abort if status > 0 rather than if status != 0. This had caused a problem in funpack in rare circumstances. - in imcompress.c changed all the calls to ffgdes to ffgdesll, to support compressed files greater than 2.1 GB in size. - fixed bug in ffeqtyll when it is called with 4th and 5th arguments set to NULL. - in fitsio.h, added the standard C++ guard around the declaration of the function fits_read_wcstab. (reported by Tammo Jan Dijkema, Astron.) - in fitsio.h, changed the prototype variable name "zero" to "zeroval" to avoid conflict in code that uses a literal definition of 'zero' to mean 0. - tweaked Makefile.in and configure.in to use LDFLAGS instead of CFLAGS for linking, use Macros for library name, and let fpack and funpack link with shared library. - modified an 'ifdef' statement in cfileio.c to test for '__GLIBC__' instead of 'linux' when initializing support for multi-threading. - modified ffeqtyll to return an effective column data type of TDOUBLE in the case of a 'K' (64-bit integer) column that has non-integer TSCALn or TZEROn keywords. - modified ffgcls (which returns the value in a column as a formatted string) so that when reading a 'K' (TLONGLONG) column it returns a long long integer value if the column is not scaled, but returns a double floating point value if the column has non-integer TSCALn or TZEROn values. - modified fitsio.h to correctly define "OFF_T long long" when using the Borland compiler - converted the 'end of line' characters in simplerng.c file to the unix style, instead of PC DOS. - updated CMakeLists.txt CMake build file which is primarily used to build CFITSIO on Windows machines. - modified fits_get_keyclass to recognize ZQUANTIZ and ZDITHER0 as TYP_CMPRS_KEY type keywords, i.e., keywords used in tile compressed image files. - added test to see if HAVE_UNISTD_H is defined, as a condition for including unistd.h in drvrfile.c drvrnet.c, drvrsmem.c, and group.c. - modified the CMakelist.txt file to fix several issues (primarily for building CFITSIO on Windows machines).. - fixed bug when reading tile-compressed images that were compressed with the IRAF PLIO algorithm. This bug did not affect fpack or funpack, but other software that reads the compressed image could be affected. The bug would cause the data values to be offset by 32768 from the actual pixel values. Version 3.37 - 3 June 2014 - replaced the random Gaussian and Poissonian distribution functions with new code written by Craig Markwardt derived from public domain C++ functions written by John D Cook. - patched fitsio2.h to support CFITSIO on AArch64 (64-bit ARM) architecture (both big and little endian). Supplied by Marcin Juszkiewicz and Sergio Pascual Ramirez, with further update by Michel Normand. - fixed bug in fpackutil.c that caused fpack to exit prematurely if the FZALGOR directive keyword was present in the HDU header. Version 3.36 - 6 December 2013 - added 9 Dec: small change to the fileseek function in drvrfile.c to support large files > 2 GB when building CFITSIO with MinGW on Windows - reorganized the CFITSIO code directory structure; added a 'docs' subdirectory for all the documentation, and a 'zlib' directory for the zlib/gzip file compression code. - made major changes to the compression code for FITS binary table to support all types of columns, including variable-length arrays. This code is mainly used via the fpack and funpack programs. - increased the number of FITS files that can be opened as one time to 1000, as defined by NMAXFILES in fitsio2.h. - made small configuration changes to configure.in, configure, fitsio.h, and drvrfile.c to support large files (64-bit file offsets} when using the mingw-w64 compiler (provided by Benjamin Gilbert). - made small change to fits_delete_file to more completely ignore any non-zero input status value. - fixed a logic error in a 'if' test when parsing a keyword name in the ngp_keyword_is_write function in grparser.c (provided by David Binderman). - when specifying the image compression parameters as part of the compressed image file name (using the "[compress]" qualifier after the name of the file), the quantization level value, if specified, was not being recognized by the CFITSIO compression routines. The image would always be compressed with the default quantization level of 4.0, regardless of what was specified. This affected the imcopy program, and potentially other user-generated application programs that used this method to specify the compression parameters. This bug did not affect fpack or funpack. This was fixed in the imcomp_get_compressed_image_par routine in the imcompress.c file. (reported by Sean Peters) - defined a new CFITS_API macro in fitsio.h which is used to export the public symbols when building CFITSIO on Windows systems with CMake. This works in conjunction with the new Windows CMake build procedure that is described in the README.win32 file. This complete revamping of the way CFITSIO is built under Windows now supports building 64-bit versions of the library. Thanks to Daniel Kaneider (Luminance HDR Team) for providing these new CMake build procedures. - modified the way that the low-level file_create routine works when running in the Hera environment to ensure that the FITS file that is created is within the allow user data disk area. - modified fits_get_compression_type so that it does not return an error if the HDU is a normal FITS IMAGE extension, and is not a tile-compressed image. - modified the low-level ffgcl* and ffpcl* routines to ensure that they never try ro read or write more than 2**31 bytes from disk at one time, as might happen with very large images, to avoid integer overflow errors. Fix kindly provided by Fred Gutsche at NanoFocus AG (www.nanofocus.de). - modified Makefile.in so that doing 'make distclean' does not delete new config.sub and config.guess files that were recently added. - adopted a patch from Debian in zcompress.c to "define" the values of GZBUFSIZE and BUFFINCR, instead of exporting the symbols as 'int's. Version 3.35 - 26 June 2013 (1st beta release was on 24 May) - fixed problem with the default tile size when compressing images with fpack using the Hcompress algorithm. - fixed returned value ("status" instead of "*status") - in imcompress.c, declared some arrays that are used to store the dimensions of the image from 'int' to 'long', to support very large images (at least on systems where sizeof(long) = 8), - modified the routines that convert a string value to a float or double to prevent them from returning a NaN or Inf value if the string is "NaN" or "Inf" (as can happen with gcc implementation of the strtod function). - removed/replaced the use of the assert() functions when locking or unlocking threads because they did not work correctly if NDEBUG is defined. - made modifications to the way the command-line file filters are parsed to 1) remove the 1024-character limit when specifying a column filter, 2) fixed a potential character buffer-overflow risk in fits_get_token, and 3) improved the parsing logic to remove any possible of confusing 2 slash characters ("//") in the string as the beginning of a comment string. - modified configure and Makefile.in so that when building CFITSIO as a shared library on linux or Mac platforms, it will use the SONAME convention to indicate whether each new release of the CFITSIO library is binary-compatible with the previous version. Application programs that link with the shared library will not need to be recompiled as long as the versions are compatible. In practice, this means that the shared library binary file that is created (on Linux systems) will have a name like 'libcfitsio.so.I.J.K', where I is the SONAME version number, J is the major CFITSIO version number (e.g. 3), and K is the minor CFITSIO version number (e.g., 34). Two link files will also be created such that libcfitsio.so -> libcfitsio.so.I, and libcfitsio.so.I -> libcfitsio.I.J.K Application programs will still run correctly with the new version of CFITSIO as long as the 'I' version number remains the same, but the applications will fail to run if the 'I' number changes, thus alerting the user that the application must be rebuilt. - fixed bug in fits_insert_col when computing the new table row width when inserting a '1Q' variable length array column. - modified the image compression routines so that the output compressed image (stored in a FITS binary table) uses the '1Q' variable length array format (instead of '1P') when the input file is larger than 4 GB. - added support for "compression directive" keywords which indicate how that HDU should be compressed (e.g., which compression algorithm to use, what tiling pattern to use, etc.). The values of these keywords will override the compression parameters that were specified on the command line when running the fpack FITS file compression program. - globally changed the variable and/or subroutine name "dither_offset" to "dither_seed" and "quantize_dither" to "quantize_method" so that the names more accurately reflects their purpose. - added support for a new SUBTRACTIVE_DITHER_2 method when compressing floating point images. The only difference with the previous method is that pixels with a value exactly equal to 0.0 will not be dithered, and instead will be exactly preserved when the image is compressed. - added support for an alias of "RICE_ONE" for "RICE_1" as the value of the ZCMPTYPE keyword, which gives the name of the image compression algorithm. This alias is used if the new SUBTRACTIVE_DITHER_2 option is used, to prevent old versions of funpack from creating a corrupted uncompressed image file. Only newer versions of funpack will recognize this alias and be able to uncompress the image. - made performance improvement to fits_read_compressed_img so that when reading a section of an compressed image that includes only every nth pixel in some dimension, it will only uncompressed a tile if there are actually any pixels of interest in that tile. - fixed several issues with the beta FITS binary table compression code that is used by fpack: added support for zero-length vector columns, made improvements to the output report when using the -T option in fpack, changed the default table compression method to 'Rice' instead of 'Best', and now writes the 'ZTILELEN' keyword to document the number of table rows in each tile. - fixed error in ffbinit in calculating the total length of the binary table extension if the THEAP keyword was used to override the default starting location of the heap. Version 3.34 - 20 March 2013 - modified configure and configure.in to support cross-compiled cfitsio as a static library for Windows on a Linux platform using MXE (http://mxe.cc) - a build environment for mingw32. (contributed by Niels Kristian Bech Jensen) - added conditional compilation statementsfor the mingw32 environment in drvrfile.c because mingw32 does not include the ftello and fseeko functions. (contributed by Niels Kristian Bech Jensen) - fixed a potential bug in ffcpcl (routine to copy a column from one table to another table) when dealing with the rare case of a '0X' column (zero length bit column). - fixed an issue in the routines that update or modify string-valued keyword values, as a result of the change to ffc2s in the previous release. These routines would exit with a 204 error status if the current value of the keyword to be updated or modified is null. - fixed typo in the previous modification that was intended to ignore numerical overflows in Hcompress when decompressing an image. - moved the 'startcol' static variable out of the ffgcnn routine and instead added it as a member of the 'FITSfile' structure that is defined in fitsio.h. This removes a possible race condition in ffgcnn in multi-threaded environments. Version 3.33 - 14 Feb 2013 - modified the imcomp_decompress_tile routine to ignore any numerical overflows that might occur when using Hcompress to decompress the image. If Hcompress is used in its 'lossy' mode, the uncompressed image pixel values may slightly exceed the range of an integer*2 variable. This is generally of no consequence, so we can safely ignore any overflows in this case and just clip the values to the legal range. - the default tiling pattern when writing a tile-compressed image has been changed. The old behavior was to compress the whole image as one single large tile. This is often not optimal when dealing with large images, so the new default behavior is to treat each row of the image as one tile. This is the same default behavior as in the standalone fpack program. The default tile size can be overridden by calling fits_set_tile_dim. - fixed bug that resulted in a corrupted output FITS image when attempting to write a float or double array of values to a tile-compressed integer data type image. CFITSIO does not support implicit data type conversion in this case and now correctly returns an appropriate error status. - modified ricecomp.c to define the nonzero_count lookup table as an external variable, rather then dynamically allocating it within the 3 routines that use it. This simplifies the code and eliminates the need for special thread locking and unlocking statements. (Thanks to Lars Kr. Lundin for this suggestion). - modified how the uncompressed size of a gzipped file is computed in the mem_compress_open routine in drvrmem.c. Since gzip only uses 4 bytes in the compressed file header to store the original file size, one may need to apply a modulo 2^32 byte correction in some cases. The logic here was modified to allow for corner cases (e.g., very small files, and when running on 32-bit platforms that do not support files larger than 2^31 bytes in size). - added new public routine to construct a 80 keyword record from the 3 input component strings, i.e, the keyword name string, the value string, and the comment string: fits_make_key/ffmkky. (This was already an undocumented internal routine in previous versions of CFITSIO). - modified ffc2s so that if the input keyword value string is a null string, then it will return a VALUE_UNDEFINED (204) status value. This makes it consistent with the behavior when attempting to read a null keyword (which has no value) as a logical or as a number (which also returns the 204 error). This should only affect cases where the header keyword does not have an equal sign followed by a space character in columns 9 and 10 of the header record. - Changed the "char *" parameter declarations to "const char *" in many of the routines (mainly the routines that modify or update keywords) to avoid compiler warnings or errors from C++ programs that tend to be more rigorous about using "const char *" when appropriate. - added support for caching uncompressed image tiles, so that the tile does not need to be uncompressed again if the application program wants to read more data from the same tile. This required changes to the main FITS file structure that is defined in fitsio.h, as well as changes to imcompress.c. - enhanced the previous modification to drvrfile.c to handle additional user cases when running in the HEASARC's Hera environment. Version 3.32 - Oct 2012 - fixed flaw in the way logical columns (TFORM = 'L') in binary tables were read which caused an illegal value of 1 in the column to be interpreted as a 'T' (TRUE) value. - extended the column filtering syntax in the CFITSIO file name parser to enable users and scripts to append new COMMENT or HISTORY keyword into the header of the filtered file (provided by Craig Markwardt). For example, fcopy "infile.fits[col #HISTORY='Processed on 2012-10-05']" outfile.fits will append this header keyword: "HISTORY Processed on 2012-10-05" - small change to the code that opens and reads an ASCII region file to return an error if the file is empty. - fixed obscure sign propagation error when attempting to read the uncompressed size of a gzipped FITS file. This resulted in a memory allocation error if the gzipped file had an uncompressed file size between 2^31 and 2^32 bytes. Fix supplied by Gudlaugur Johannesson (Stanford). Version 3.31 - 18 July 2012 - enhanced the CFITSIO column filtering syntax to allow the comma, in addition to the semi-colon, to be used to separate clauses, for example: [col X,Y;Z = max(X,Y)]. This was done because users are not allowed to enter the semi-colon character in the on-line Hera data processing system due to computer security concerns. - enhanced the CFITSIO extended filename syntax to allow specifying image compression parameters (e.g. '[compress Rice]') when opening an existing FITS file with write access. The specified compression parameters will be used by default if more images are appended to the existing file. - modified drvrfile.c to do additional file security checks when CFITSIO is running within the HEASARC's Hera software system. In this case CFITSIO will not allow FITS files to be created outside of the user's individual Hera data directory area. - fixed an issue in fpack and funpack on Windows machines, caused by the fact that the 'rename' function behaves differently on Windows in that it does not clobber an existing file, as it does on Unix platforms. - fixed bug in the way byte-swapping was being performed when writing integer*8 null values to an image or binary table column. - added the missing macro definition for fffree to fitsio.h. - modified the low level table read and write functions in getcol*.c and putcol*.c to remove the 32-bit limitation on the number of elements. These routines now support reading and writing more than 2**31 elements at one time. Thanks to Keh-Cheng Chu (Stanford U.) for the patch. - modified Makefile.in so that the shared libcfitsio.so is linked against pthreads and libm. Version 3.30 - 11 April 2012 Enhancements - Added new routine called fits_is_reentrant which returns 1 or 0 depending on whether or not CFITSIO was compiled with the -D_REENTRANT directive. This can be used to determine if it is safe to use CFITSIO in multi-threaded programs. - Implemented much faster byte-swapping algorithms in swapproc.c based on code provided by Julian Taylor at ESO, Garching. These routines significantly improve the FITS image read and write speed (by more than a factor of 2 in some cases) on little-endian machines (e.g., Linux and Microsoft Windows and Macs running on x86 CPUs) where byte-swapping is required when reading and writing data in FITS files. This has no effect on big-endian machines (e.g. Motorola CPUs and some IBM systems). Even faster byte-swapping performance can be achieved in some cases by invoking the new "--enable-sse2" or "--enable-ssse3" configure options when building CFITSIO on machines that have CPUs and compilers that support the SSE2 and SSSE3 machine instructions. - added additional support for implicit data type conversion in cases where the floating point image has been losslessly compressed with gzip. The pixels in these compressed images can now be read back as arrays of short, int, and long integers as well as single and double precision floating-point. - modified fitsio2.h and f77_wrap.h to recognize IBM System z mainframes by testing if __s390x__ or __s390__ is defined. - small change to ffgcrd in getkey.c so that it supports reading a blank keyword (e.g., a keyword whose name simply contains 8 space characters). Bug Fixes - fixed a bug in imcomp_decompress_tile that caused the tile-compressed image to be uncompressed incorrectly (even though the tile-compressed image itself was written correctly) under the following specific conditions: - the original FITS image has a "float" datatype (R*4) - one or more of the image tiles cannot be compressed using the standard quantization method and instead are losslessly compressed with gzip - the pixels in these tiles are not all equal to zero (this bug does affect tiles where all the pixels are equal to zero) - the program that is reading the compressed image uses CFITSIO's "implicit datatype conversion" feature to read the "float" image back into an array of "double" pixel values. If all these conditions are met, then the returned pixel values in the affected image tiles will be garbage, with values often ranging up to 10**34. Note that this bug does not affect the fpack/funpack programs, because funpack does not use CFITSIO's implicit datatype conversion feature when uncompressing the image. Version 3.29 - 2 December 2011 Enhancements - modified Makefile.in to allow configure to override the lib and include destination directories. - added (or restored actually) support for tile compression of 1-byte integer images in imcomp_compress_tile. Support for that data type was overlooked during recent updates to this routine. - modified the fits_get_token command-line parsing routine to perform more rigorous checks to determine if the token can be interpreted as a number or not. - made small modification to fpack.c to not allow the -i2f option (convert image from integer to floating point) with the "-g -q 0" option (do lossless gzip compression). It is more efficient to simply use the -g option alone. - made modifications to fitsio.h and drvrfile.c to support reading and writing large FITS files (> 2.1 GB) when building CFITSIO using Microsoft Visual C++ on Windows platforms. - added new WCS routine (ffgicsa) which returns the WCS keyword values for a particular WCS version ('A' - 'Z'). Bug Fixes - fixed a problem with multi-threaded apps that open/close FITS files simultaneously by putting mutex locks around the call to fits_already_open and in fits_clear_Fptr. - fixed a bug when using the 'regfilter' function to select a subset of the rows in a FITS table that have coordinates that lie within a specified spatial region on the sky. This bug only affects the rarely used panda (and epanda and bpanda) region shapes in which the region is defined by the intersection of an annulus and a pie-shaped wedge. The previous code (starting with version 3.181 of CFITSIO where support for the panda region was first introduced) only worked correctly if the 2 angles that define the wedge have values between -180 and +180. If not, then fewer rows than expected may have been selected from the table. - fixed the extended filename parser so that when creating a histogram by binning 2 table columns, if a keyword or column name is given as the weighting factor, then the output histogram image will have a floating point datatype, not the default integer datatype as is the case when no weight is specified (e.g. with a filename like "myfile.fits[bin x,y; weight_column]" - added fix to the code in imcompress.c to work around a problem with dereferencing the value of a pointer, in cases where the address of that pointer has not been defined (e.g., the nulval variable). - modified the byte shuffling algorithm in fits_shuffle_8bytes to work around a strange bug in the proprietary SunStudioExpress C compiler under OpenSolaris. - removed spurious messages on the CFITSIO error stack when opening a FITS file with FTP (in drvrnet.c); Version 3.28 - 12 May 2011 - added an enhancement to the tiled-image compression method when compressing floating-point image using the standard (lossy) quantization method. In cases where an image tile cannot be quantized, The floating-point pixel values will be losslessly compressed with gzip before writing them to the tile- compressed file. Previously, the uncompressed pixel values would have been written to the file, which obviously requires more disk space. - made significant internal changes to the structure of the tile compression and uncompression routines in imcompress.c to make them more modular and easier to maintain. - modified configure.in and configure to force it to build a Universal binary on Mac OS X. - modified the ffiter function in putcol.c to properly clean up allocated memory if an error occurs. - in quantize.c, when searching for the min and max values in a float array, initialize the max value to -FLT_MAX instead of FLT_MIN (and similarly for double array). Version 3.27 - 3 March 2011 Enhancements - added new routines fits_read_str and fits_delete_str which read or delete, respectively, a header keyword record that contains a specified character string. - added a new routine called fits_free_memory which frees the memory that fits_read_key_longstr allocated for the long string keyword value. - enhanced the ffmkky routine in fitscore.c to not put a space before the equals sign when writing long string-valued keywords using the ESO HIERARCH keyword convention, if that extra character is needed to fit the length of the keyword name + value string within the 80-character FITS keyword record. - made small change to fits_translate_keyword to support translation of blank keywords (where the name = 8 blank characters) - modified fpack so that it uses the minimum of the 2nd, 3rd, and 5th order MAD noise values when quantizing and compressing a floating point image. This is more conservative than just using the 3rd order MAD value alone. - added new routine imcomp_copy_prime2img to imcompress.c that is used by funpack to copy any keywords that may have been added to the primary array of the compressed image file (a null image) back into the header of the uncompressed image. - enhanced the fits_quantize_float and fits_quantize_double routines in quantize.c to also compress the tile if it is completely filled with null values. Previously, this type of tile would have been written to the output compressed image without any compression. - enhanced imcomp_decompress_tile to support implicit datatype conversion when reading a losslessly compressed (with gzip) real*4 image into an array of real*8 values. - in imcompress.c, removed possible attempt to free memory that had not been allocated. Version 3.26 - 30 December 2010 Enhancements - defined 2 new macros in fitsio.h: #define CFITSIO_MAJOR 3 #define CFITSIO_MINOR 26 These may be used within other macros to detect the CFITSIO version number at compile time. - modified group.c to initialize the output URL to a null string in fits_url2relurl. Also added more robust tests to see if 2 file pointers point to the same file. - enhanced the template keyword parsing code in grparser.c to support the 'D' exponent character in the ASCII representation of floating point keyword values (as in TVAL = 1.23D03). Previously, the parser would have written this keyword with a string value (TVAL = '1.23D03'). - modified the low-level routines that write a keyword record to a FITS header so that they silently replace any illegal characters (ASCII values less than 32 or greater than 126) with an ASCII space character. Previously, these routines would have returned with an error when encountering these illegal characters in the keyword record (most commonly tab, carriage return, and line feed characters). - made substantial internal changes to imcompress.c in preparation for possible future support for compression methods for FITS tables analogous to the tiled image compression method. - replaced all the source code in CFITSIO that was distributed under the GNU General Public License with freely available code. In particular, the gzip file compression and uncompression code was replaced by the zlib compression library. Thus, beginning with this version 3.26 of CFITSIO, other software applications may freely use CFITSIO without necessarily incurring any GNU licensing requirement. See the License.txt file for the CFITSIO licensing requirements. - added support for using cfitsio in different 'locales' which use a comma, not a period, as the decimal point character in ASCII representation of a floating point number (e.g., France). This affects how floating point keyword values and floating point numbers in ASCII tables are read and written with the 'printf' and 'strtod' functions. - added a new utility routine called fits_copy_rows/ffcprw that copies a specified range of rows from one table to another. - enhanced the test for illegal ASCII characters in a header (fftrec) to print out the name of the offending character (e.g TAB or Line Feed) as well as the Hex value of the character. - modified ffgtbc (in fitscore.c) to support nonstandard vector variable length array columns in binary tables (e.g. with TFORMn = 2000PE(500)'). - modified the configure file to add "-lm" when linking CFITSIO on Solaris machines. - added new routine, fits_get_inttype, to parse an integer keyword value string and return the minimum integer datatype (TBYTE, TSHORT, TLONG, TLONGLONG) required to store the integer value. - added new routine, fits_convert_hdr2str, which is similar to fits_hdr2str except that if the input HDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of a normal uncompressed FITS image before concatenating the header keyword records. - modified the file template reading routine (ngp_line_from_file in grparser.c) so that it ignores any carriage return characters (\r) in the line, that might be present, e.g. if the file was created on a Windows machine that uses \r\n as end of line characters. - modified the ffoptplt routine in cfileio.c to check if the PCOUNT keyword in the template file has a non-zero value, and if so, resets it to zero in the newly created file. Bug Fixes - fixed a bug when uncompressing floating-point images that contain Nan values on some 64-bit platforms. - fixed a bug when updating the value of the CRPIXn world coordinate system keywords when extracting a subimage from larger FITS image, using the extended CFITSIO syntax (e.g. myimage[1:500:2, 1:500:2]). This bug only affects cases where the pixel increment value is not equal to 1, and caused the coordinate grid to be shifted by between 0.25 pixels (in the case of a pixel increment of 2) and 0.5 pixels (for large pixel increment values). - fixed a potential string buffer overflow error in the ffmkls routine that modifies the value and comment strings in a keyword that uses the HEASARC long string keyword convention. - fixed a bug in imcompress.c that could cause programs to abort on 64-bit machines when using gzip to tile-compress images. Changed the declaration of clen in imcomp_compress_tile from int to size_t. Version 3.25 - 9 June 2010 - fixed bug that was introduced in version 3.13 that broke the ability to reverse an image section along the y-axis with an image section specifier like this: myimage.fits[*,-*]. This bug caused the output image to be filled with zeros. - fixed typo in the definition of the ftgprh Fortran wrapper routine in f77_wrap3.c. - modified the cfitsio.pc.in configuration file to make the lib path a variable instead of hard coding the path. The provides more flexibility for projects such as suse and fedora when building CFITSIO. - fixed bug in imcomp_compress_tile in imcompress.c which caused null pixel values to be written incorrectly in the rare case where the floating-point tile of pixels could not be quantized into integers. - modified imcompress.c to add a new specialized routine to uncompress an input image and then write it to a output image on a tile by tile basis. This appears to be faster than the old method of uncompressing the whole image into memory before writing it out. It also supports large images with more than 2**31 pixels. - made trivial changes to 2 statements in drvrfile.c to suppress nuisance compiler warnings. - some compilers define CLOCKS_PER_SEC as a double instead of an integer, so added an explicit integer type conversion to 2 statements in imcompress.c that used this macro. - removed debugging printf statements in drvrnet.c (15 July) Version 3.24 - 26 January 2010 - modified fits_translate_keywords so that it silently ignores any illegal ASCII characters in the value or comment fields of the input FITS file. Otherwise, fpack would abort without compressing input files that contained this minor violation of the FITS rules. - added support for Super H cpu in fitsio2.h - updated funpack to correctly handle the -S option, and to use a more robust algorithm for creating temporary output files. - modified the imcomp_compress_tile routine to support the NOCOMPRESS debugging option for real*4 images. Version 3.23 - 7 January 2010 - reduced the default value for the floating point image quantization parameter (q) from 16 to 4. This parameter is used when tile compressing floating point images. This change will increase the average compression ratio for floating point images from about 4.6 to about 6.5 without losing any significant information in the image. - enhanced the template keyword parsing routine to reject a header template string that only contains a sequence of dashes. - enhanced the ASCII region file reading routine to allow tabs as well as spaces between fields in the file. - got rid of bogus error message when calling fits_update_key_longstr - Made the error message more explicit when CFITSIO tries to write to a GZIP compressed file. Instead of just stating "cannot write to a READONLY file", it will say "cannot write to a GZIP compressed file". Version 3.22 - 28 October 2009 - added an option (in imcompress.c) to losslessly compress floating point images, rather than using the default integer scaling method. This option is almost never useful in practice for astronomical images (because the amount of compression is so poor), but it has been added for test comparison purposes. - enhanced the dithering option when quantizing and compressing floating point images so that a random dithering starting point is used, so that the same dithering pattern does not get used for every image. - modified the architecture setup section of fitsio2.h to support the 64-core 8x8-architecture Tile64 platform (thanks to Ken Mighell, NOAO) Fixes - fixed a problem that was introduced in version 3.13 of CFITSIO in cases where a program writes it own END keyword to the header instead of letting CFITSIO do it, as is strongly recommended. In one case this caused CFITSIO to rewrite the END keyword and any blank fill keywords in the header many times, causing a noticeable slow-down in the FITS file writing speed. Version 3.21 - 24 September 2009 - fixed bug in cfileio.c that caused CFITSIO to crash with a bus error on Mac OS X if CFITSIO was compiled with multi-threaded support (with the --enable-reentrant configure option). The Mac requires an additional thread initialization step that is not required on Linux machines. Even with this fix, occasional bus errors have been seen on some Mac platforms, The bus errors are seen when running the thread_test.c program. The bus errors are very intermittent, and occur less than about 1% of the time, on the affected platforms. These bus errors have not been seen on Linux platforms. - fixed invalid C comment delimiter ("//*" should have been "/*") in imcompress.c. - Increased the CFITSIO version number string length in fpackutil.c, to fix problem on some platforms when running fpack -V or funpack -V. Also modified the output format of the fpack -L command. Version 3.20 - 31 August 2009 - modified configure.in and configure so that it will build the Fortran interface routines by default, even if no Fortran compiler is found in the user's path. Building the interface routines may be disabled by specifying FC="none". This was done at the request of users who obtained CFITSIO from some other standard linux distributions, where CFITSIO was apparently built in an environment that had no Fortran compiler and hence did not build the Fortran wrappers. - modified ffchdu (close HDU) so that it calls the routine to update the maximum length of variable length table columns in the TFORM values in all cases where the values may have changed. Previously it would not update the values if a value was already specified in the TFORM value. - added 2 new string manipulation functions to the CFITSIO parser (contributed by Craig Markwardt): strmid extracts a substring from a string, and strstr searches for a substring within a string. - removed the code in quantize.c that treated "floating-point integer" images as a special case (it would just do a datatype conversion from float to int, and not otherwise quantize the pixel values). This caused complications with the new subtractive dithering feature. - enhanced the code for converting floating point images to quantized scaled integer prior to tile-compressing them, to apply a random subtractive dithering, which improves the photometric accuracy of the compressed images. - added new internal routine, iraf_delete_file, for use by fpack to delete a pair of IRAF format header and pixel files. - small change in cfileio.c in the way it recognizes an IRAF format .imh file. Instead of just requiring that the filename contain the ".imh" string, that string must occur at the end of the file name. - fixed bug in the code that is used when tile-compressing real*4 FITS images, which quantizes the floating point pixel values into integer levels. The bug would only appear in the fairly rare circumstance of tile compressing a floating point image that contains null pixels (NaNs) and only when using the lossy Hcompress algorithm (with the s parameter not equal to 1). This could cause underflow of low valued pixels, causing them to appear as very large pixel values (e.g., > 10**30) in the compressed image - changed the "if defined" blocks in fitsio.h, fitsio2.h and f77_wrap.h to correctly set the length of long variables on sparc64 machines. Patch contributed by Matthew Truch (U. Penn). - modified the HTTP file access code in drvrnet.c to support basic HTTP authentication, where the user supplies a user name and password. The CFITSIO filename format in this case is: "http://username:password@hostname/..." Thanks to Jochen Liske (ESO) for the suggestion and the code. Version 3.181 (BETA) - 12 May 2009 - modified region.c and region.h to add support for additional types of region shapes that are supported by ds9: panda, epanda, and bpanda. - fixed compiler error when using the new _REENTRANT flag, having to do with the an attempted static definition of Fitsio_Lock in several source files, after declaring it to be non-static in fitsio2.h. Version 3.18 (BETA) - 10 April 2009 - Made extensive changes to make CFITSIO thread safe. Previously, all opened FITS files shared a common pool of memory to store the most recently read or written FITS records in the files. In a multi-threaded environment different threads could simultaneously read or write to this common area causing unpredictable results. This was changed so that every opened FITS file has its own private memory area for buffering the file. Most of the changes were in buffers.c, fitsio.h, and fitsio2.h. Additional changes were made to cfileio.c, mainly to put locks around small sections of code when setting up the low-level drivers to read or write the FITS file. Also, locks were needed around the GZIP compression and uncompression code in compress.c., the error message stack access routine in fitscore.c, the encode and decode routines in fits_hcompress.c and fits_hdecompress.c, in ricecomp.c, and the table row selection and table calculator functions. Also, removed the 'static' declaration of the local variables in pliocomp.c which did not appeared to be required and prevented the routines from being thread safe. As a consequence of having a separate memory buffer for every FITS file (by default, about 115 kB per file), CFITSIO may now allocate more memory than previously when an application program opens multiple FITS files at once. The read and write speed may also be slightly faster, since the buffers are not shared between files. - Added new families of Fortran wrapper routines to read and write values to large tables that have more than 2**31 rows. The arguments that define the first row and first element to read or write must be I*8 integers, not ordinary I*4 integers. The names of these new routines have 'LL' appended to them, so for example, ftgcvb becomes ftgcvbll. Fixes - Corrected an obscure bug in imcompress.c that would have incorrectly written the null values only in the rare case of writing a signed byte array that is then tile compressed using the Hcompress or PLIO algorithm. Version 3.14 - 18 March 2009 Enhancements - modified the tiled-image compression and uncompression code to support compressing unsigned 16-bit integer images with PLIO. FITS unsigned integer arrays are offset by -32768, but the PLIO algorithm does not work with negative integer values. In this case, an offset of 32768 is added to the array before compression, and then subtracted again when reading the compressed array. IMPORTANT NOTE: This change is not backward compatible, so these PLIO compressed unsigned 16-bit integer images will not be read correctly by previous versions of CFITSIO; the pixel values will have an offset of +32768. - minor changes to the fpack utility to print out more complete version information with the -V option, and format the report produced by the -T option more compactly. Fixes - Modified imcomp_compress_image (which is called by fpack) so that it will preserve any null values (NaNs) if the input image has a floating point datatype (BITPIX = -32 or -64). Null values in integer datatype images are handled correctly. - Modified imcomp_copy_comp2img so that it does not copy the ZBLANK keyword, if present, from the compressed image header when uncompressing the image. - Fixed typo in the Fortran wrapper macro for the ftexist function. Version 3.13 - 5 January 2009 Enhancements - updated the typedef of LONGLONG in fitsio.h and cfortran.h to support the Borland compiler which uses the __int64 data type. - added new feature to the extended filename syntax so that when performing a filtering operation on specified HDU, if you add a '#' character after the name or number of the HDU, then ONLY that HDU (and the primary array if the HDU is a table) will be copied into the filtered version of the file in memory. Otherwise, by default CFITSIO copies all the HDUs from the input file into memory. - when specifying a section, if the specified number of dimensions is less than the number of dimensions in the image, then CFITSIO will use the entire dimension, as if a '*' had been specified. Thus [1:100] is equivalent to [1:100,*] when specifying a section of 2 dimensional image. - modified fits_copy_image_section to read/write the section 1 row at a time, instead of the whole section, to reduce memory usage. - added new stream:// drivers for reading/writing to stdin/stdout. This driver is somewhat fragile, but for simple FITS read and write operations this driver streams the FITS file on stdin or stdout without first copying the entire file in memory, as is done when specifying the file name as "-". - slight modification to ffcopy to make sure that the END keyword is correctly written before copying the data. This is required by the new stream driver. - modified ffgcprll, so that when writing data to an HDU, it first checks that the END keyword has been written to the correct place. This is required by the new stream driver. Fixes - fixed bug in ffgcls2 when reading an ASCII string column in binary tables in cases where the width of the column is greater than 2880 characters and when reading more than 1 row at a time. Similar change was made to ffpcls to fix same problem with writing to columns wider than 2880 characters. - updated the source files listed in makepc.bat so that it can be used to build CFITSIO with the Borland C++ compiler. - fixed overflow error in ffiblk that could cause writing to Large Files (> 2.1 GB) to fail with an error status. - fixed a bug in the spatial region code (region.c) with the annulus region. This bug only affected specialized applications which directly use the internal region structure; it does not affect any CFITSIO functions directly. - fixed memory corruption bug in region.c that was triggered if the region file contained a large number of excluded regions. - got rid of a harmless error message that would appear if filtering a FITS table with a GTI file that has zero rows. (eval_f.c) - modified fits_read_rgnfile so that it removes the error messages from the error stack if it is unable to open the region file as a FITS file. (region.c) Version 3.12 - 8 October 2008 - modified the histogramming code so that the first pixel in the binned array is chosen as the reference pixel by default, if no other value is previously defined. - modified ffitab and ffibin to allow a null pointer to the EXTNAME string, when inserting a table with no name. Version 3.11 - 19 September 2008 - optimized the code when tile compressing real*4 images (which get scaled to integers). This produced a modest speed increase. For best performance, one must specify the absolute q quantization parameter, rather than relative to the noise in the tile (which is expensive to compute). - modified the FITS region file reading code to check for NaN values, which signify the end of the array of points in a polygon region. - removed the test for LONGSIZE == 64 from fitsio.h, since it may not be defined. - modified imcompress.c to support unconventional floating point FITS images that also have BSCALE and BZERO keywords. The compressed floating point images are linearly scaled twice in this case. Version 3.10 - 20 August 2008 - fixed a number of cases, mainly dealing with long input file names (> 1024 char), where unsafe usage of strcat and strcpy could have caused buffer overflows. These buffer overflows could cause the application to crash, and at least theoretically, could be exploited by a malicious user to execute arbitrary code. There are no known instances of this type of malicious attack on CFITSIO applications, and the likelihood of such an attack seems remote. None the less, it would be prudent for CFITSIO users to upgrade to this new version to guard against this possibility. - modified some of the routines to define input character string parameters as "const char *" rather than just "char *" to eliminate some compiler warnings when the calling routine passes a constant string to the CFITSIO routine. Most of the changes were to the keyword name argument in the many routines that read or write keywords. - fixed bug when tile-compressing a FITS image which caused all the completely blank keywords in the input header to be deleted from the output compressed image. Also added a feature to preserve any empty FITS blocks in the header (reserved space for future keywords) when compressing or uncompressing an image. - fixed small bug in the way the default tile size is set in imcompress.c. (Fix sent in by Paul Price). - added support for reading FITS format region files (in addition to the ASCII format that was previously supported). Thanks to Keith Arnaud for modifying region.c to do this. Version 3.09 - 12 June 2008 - fixed bug in the calculator function, parse_data, that evaluates expressions then selecting rows or modifying values in table columns. This bug only appeared in unusual circumstances where the calculated value has a null value (= TNULLn). The bug could cause elements to not be flagged as having a null value, or in rare cases could cause valid elements to be flagged as null. This only appears to have affected 64-bit platforms (where size(long) = 8). - fixed typo in imcomp_decompress_tile: call to fffi2r8 should have been to fffi4r8. - in the imcopy_copy_comp2img routine, moved the call to fits_translate_keywords outside of the 'if' statement. This could affect reading compressed images that did not have a EXTNAME keyword in the header. - fixed imcomp_compress_tile in imcompress.c to properly support writing unsigned integers, in place, to tile compressed images. - modified fits_read_compressed_img so that if the calling routine specifies nullval = 0, then it will not check for null-valued pixels in the compressed FITS image. This mimics the same behavior when reading normal uncompressed FITS images. Version 3.08 - 15 April 2008 - fixed backwards compatibility issue when uncompressing a Rice compressed image that was created with previous versions of CFITSIO (this late fix was added on May 18). - small change to cfortran.h to add "extern" to the common block definition. This was done for compatibility with the version of cfortran.h that is distributed by the Debian project. - relaxed the requirement that a string valued keyword must have a closing quote character. If the quote is missing, CFITSIO will silently append a quote at the end of the keyword record. This change was made because otherwise it is very difficult to correct the keyword because CFITSIO would exit with an error before making the fix. - added a new BYTEPIX compression parameter when tile-compressing images with the Rice algorithm. - cached the NAXIS and NAXISn keyword values in the fitsio structure for efficiency, to eliminate duplicates reads of these keywords. - added variants of the Rice compression and uncompression routines to support short int images (in addition to the routines that support int). - moved the definition of LONGLONG_MIN and LONGLONG_MAX from fitsio2.h to fitsio.h, to make it accessible to application programs. - make efficiency improvements to fitscore.c, to avoid needless searches through the entire header when reading the required keywords that must be near the beginning of the header. - made several improvements to getcol.c to optimize reading of compressed and uncompressed images. - changed the compression level in the gzip code from 6 to 1. In most cases this will provide nearly the same amount of compression, but is significantly faster in some cases. - added new "helper routines' to imcompress.c to allow applications to specified the "quantize level" and Hcompress scaling and smoothing parameters - modified the extended filename syntax to support the "quantize level" and Hcompress scaling and smoothing parameters. The parser in cfileio.c was extensively modified. - extensive changes to quantize.c: - replace the "nbits" parameter with "quantize level" - the quantize level is now relative to the RMS noise in the image - the HCOMPRESS scale factor is now relative to the RMS noise - added routines to calculate RMS noise in image (these changes require a change to the main file structure in fitsio.h) - initialize errno = 0 before the call to strtol in ffext, in case errno has previously been set by an unrelated error condition. - added the corresponding long name for the ffgkyjj routine to longnam.h. - changed imcomp_copy_comp2img (in imcompress.c) to not require the presence of the EXTNAME keyword in the input compressed image header. - modified imcompress.c to only write the UNCOMPRESSED_DATA column in tile-compressed images if it is actually needed. This eliminates the need to subsequently delete the column if it is not used (which is almost always the case). - found that it is necessary to seek to the EOF of a file after truncating the size of the file, to reestablish a definite current location in the file. The required small changes to 3 routines: file_truncate (to seek to EOF) and fftrun (to set io_pos) and the truncation routine in drvrmem.c. - improved the efficiency when compressing integer images with gzip. Previously, the image was always represented using integer*4 pixels, which were then compressed. Now, if the range of pixel values can be represented with integer*2 pixels or integer*1 pixels, then that is used. This change is backward compatible with any compressed images that used the previous method. - changed the default tiling pattern when using Hcompress from large squares (200 to 600 pixels wide) to 16 rows of the image. This generally requires less memory, compresses faster, and is more consistent with the default row by row tiling when using the other compression methods. - modified imcomp_init_table in imcompress.c to enforce a restriction when using the Hcompress algorithm that the 1st 2 dimensions of sll image tiles must be at least 4 pixels long. Hcompress becomes very inefficient for smaller dimensions, and does not work at all with 1D images. - fixed bug in the Hcompress compression algorithm that could affect compression of I*4 images, using non-square compression tiles (in the encode64 routine). Version 3.07 - 6 December 2007 (internal release) - fixed bug with the PLIO image compression routine which silently produced a corrupted compressed image if the uncompressed image pixels were not all in the range 0 to 2**24. (fixed in November) - fixed several 'for' loops in imcompress.c which were exceeding the bounds of an array by 1. (fixed in November) - fixed a possible, but unlikely, memory overflow issue in iraffits.c. - added a clarification to the cfortran.doc file that cfortran.h may be used and distributed under the terms of the GNU Library General Public License. - fixed bug in the fits_modify_vector_len routine when modifying the vector length of a 'X' bit column. Version 3.06 - 27 August 2007 - modified the imcopy.c utility program (to tile-compress images) so that it writes the default EXTNAME = 'COMPRESSED_IMAGE' keyword in the compressed images, to preserve the behavior of earlier versions of imcopy. - modified the angsep function in the FITS calculator (in eval.y) to use haversines, instead of the 'law of cosines', to provide more precision at small angles (< 0.1 arcsec). Version 3.05 - July 2007 (internal release only) - extensive changes to imcompress.c to fully support implicit data type conversion when reading and writing arrays of data to FITS images, where the data type of the array is not the same as the data type of the FITS image. This includes support for null pixels, and data scaling via the BSCALE and BZERO keywords. - rewrote the fits_read_tbl_coord routine in wcssub.c, that gets the standard set of WCS keywords appropriate to a pair of columns in a table, to better support the full set of officially approved WCS keywords. - made significant changes to histo.c, which creates an image by binning columns of a table, to better translate the WCS keywords in the table header into the WCS keywords that are appropriate for an image HDU. - modified imcompress.c so that when pixels are written to a tile-compressed image, the appropriate BSCALE and BZERO values of that image are applied. This fixes a bug in which writing to an unsigned integer datatype image (with BZERO = 32768) was not done correctly. Version 3.04 - 3 April 2007 - The various table calculator routines (fits_select_rows, etc.) implicitly assumed that the input table has not been modified immediately prior to the call. To cover cases where the table has been modified a call to ffrdef has been added to ffprs. IN UNUSUAL CASES THIS CHANGE COULD CAUSE CFITSIO TO BEHAVE DIFFERENTLY THAN IN PREVIOUS VERSIONS. For example, opening a FITS table with this column-editing virtual file expression: myfile.fits[3][col A==X; B = sqrt(X)] no longer works, because the X column does not exist when the sqrt expression is evaluated. The correct expression in this case is myfile.fits[3][col A==X; B = sqrt(A)] - modified putkey.c to support USHORT_IMG when calling fits_create_img to create a signed byte datatype image. - enhanced the column histogramming function to propagate any TCn_k and TPn_k keywords in the table header to the corresponding CDi_j and PCi_j keywords in the image header. - enhanced the random, randomn, and randomp functions in the lexical parser to take a vector column name argument to specify the length of the vector of random numbers that should be generated (provided by Craig Markwardt, GSFC) - enhanced the ffmcrd routine (to modify an existing header card) to support long string keywords so that any CONTINUE keywords associated with the previous keyword will be deleted. - modified the ffgtbp routine to recognize the TDIMn keyword for ASCII string columns in a binary table. The first dimension is taken to be the size of a unit string. (The TFORMn = 'rAw' syntax may also be used to specify the unit string size). - in fits_img_decompress, the fits_get_img_param function was called with an invalid dimension size, which caused a fatal error on at least 1 platform. - in ffopentest, set the status value before returning in case of error. - in the drvrnet.c file, the string terminators needed to be changed from "\n" to "\r\n" to support the strict interpretation of the http and ftp standard that is enforced by some newer web servers. Version 3.03 - 11 December 2006 New Routine - fits_write_hdu writes the current HDU to a FILE stream (e.g. stdout). Changes - modified the region parsing code to support region files where the keyword "physical" is on a separate line preceding the region shape token. (However, "physical" coordinates are not fully supported, and are treated identically to "image" coordinates). - enhanced the iterator routines to support calculations on 64-bit integer columns and images. Currently, the values are cast to double precision when doing the calculations, which can cause a loss of precision for integer values greater than about 2**52. - added support for accessing FITS files on the computational grid. Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, Italy, implemented the necessary I/O driver routines in drvrgsiftp.c. - modified the tiled image compression/uncompression routines to preserve/restore the original CHECKSUM and DATASUM keywords if they exist. (saved as ZHECKSUM and ZDATASUM in the compressed image) - split fits_select_image_section into 2 routines: a higher level routine that creates the output file and copies other HDUs from the input file to the output file, and a lower level routine that extracts the image section from the input image into an output image HDU. - Improved the error messages that get generated if one tries to use the lexical parser to perform calculations on variable-length array columns. - added "#define MACHINE NATIVE" in fitsio2.h for all machines where BYTESWAPPED == FALSE. This may improve the file writing performance by eliminating the need to allocate a temporary buffer in some cases. - modified the configure.in and configure script to fix problems with testing if network services are available, which affects the definition of the HAVE_NET_SERVICES flag. - added explicit type casting to all malloc statements, and deleted declarations of unreferenced variables in the image compression code to suppress compiler warnings. - fixed incorrect logic in fitsio2.h in the way it determined if numerical values are byteswapped or not on MIPS and ARM architectures. - added __BORLANDC__ to the list of environments in fitsio.h that don't use %lld in printf for longlong integers - added "#if defined(unix)" around "#include " statements in several C source files, to make them compatible with Windows. Version 3.02 - 18 Sept 2006 - applied the security patch to the gzip code, available at http://security.FreeBSD.org/patches/SA-06:21/gzip.patch The insufficient bounds checks in buffer use can cause gzip to crash, and may permit the execution of arbitrary code. The NULL pointer deference can cause gzip to crash. The infinite loop can cause a Denial-of-Service situation where gzip uses all available CPU time. - added HCOMPRESS as one of the compression algorithm options in the tiled image compression code. (code provided by Richard White (STScI)) Made other improvements to preserve the exact header structure in the compressed image file so that the compressed-and-then-uncompressed FITS image will be as identical as possible to the original FITS image file. New Routines - the following new routines were added to support reading and writing non-standard extension types: fits_write_exthdr - write required keywords for a conforming extension fits_write_ext - write data to the extension fits_read_ext - read data from the extension - added new routines to compute the RMS noise in the background pixels of an image: fits_rms_float and fits_rms_short (take an input array of floats or shorts, respectively). Fixes - added the missing 64-bit integer case to set of "if (datatype)" statements in the routine that returns information about a particular column (ffgbclll). - fixed a parsing error in ffexts in cases where an extension number is followed by a semi-colon and then the column and row number of an array in a binary table. Also removed an extraneous HISTORY keyword that was being written when specifying an input image in a table cel. - modified the routine that reads a table column returning a string value (ffgcls) so that if the displayed numerical value is too wide to fit in the specified length string, then it will return a string of "*" characters instead of the number string. - small change to fitsio.h to support a particular Fortran and C compiler combination on a SGI Altix system - added a test in the gunzip code to prevent seg. fault when trying to uncompress a corrupted file (at least in some cases). - fixed a rarely-occurring bug in the routine that copies a table cell into an image; had to call the ffflsh call a few lines earlier. Version 3.01 - (in FTOOLS 6.1 release) - modified fits_copy_image2cell to correctly copy all the appropriate header keywords when copying an image into a table cell - in eval.y, explicitly included the code for the lgamma function instead of assuming it is available in a system library (e.g., the lgamma function is currently not included in MS Visual++ libraries) - modified the logic in fits_pixel_filter so that the default data type of the output image will be promoted to at least BITPIX = -32 (a single precision floating point) if the expression that is being evaluated resolves to a floating point result. If the expression resolves to an integer result, the output image will have the same BITPIX as the input image. - in fits_copy_cell2image, added 5 more WCS keywords to the list of keywords related to other columns that should be deleted in the output image header. - disabled code in cfileio.c that would write HISTORY keywords to the output file in fits_copy_image2cell and cell2image, because some tasks would not want these extraneous HISTORY keywords. - added 2 new random number functions to the CFITSIO parser RANDOMN() - produces a normal deviate (mean=0, stddev=1) RANDOMP(X) - produces a Poisson deviate for an expected # of counts X - in f77_wrap.h, removed the restriction that "g77Fortran" must be defined on 64-bit Itanium machines before assuming that sizeof(long) = 8. It appears that "long"s are always 8 bytes long on this machine, regardless of what compilers are used. - added test in fitsio.h so that LONGLONG cannot be multiply defined - modified longnam.h so that both "fits_write_nulrows" and "fits_write_nullrows" get replace by the string "ffprwu". This fixes a documentation error regarding the long name of this routine. Bug fixes - fixed a potential null character string dereferencing error in the the ffphtb and ffphbn routines that write the FITS table keywords. This concerned the optional TUNITn keywords. - fixed a few issues in fits_copy_cell2image and fits_copy_image2cell related to converting some WCS keyword between the image extension form and the table cell form of the keyword. (cfileio.c) - fixed bug in fits_translate_keyword (fitscore.c) that, e.g., caused 'EQUINOX' to be translated to EQUINOXA' if the pattern is 'EQUINOXa' - fixed 2 bugs that could affect 'tile compressed' floating point images that contain NaN pixels (null pixels). First, the ZBLANK keyword was not being written, and second, an integer overflow could occur when computing the BZERO offset in the compressed array. (quantize.c and imcompress.c) Version 3.006 - 20 February 2006 -(first full release of v3) - enhanced the 'col' extended filename syntax to support keyword name expressions like [col error=sqrt(rate); #TUNIT# = 'counts/s'], in which the trailing '#' will be replaced by the column number of the most recently referenced column. - fixed bug in the parse_data iterator work function that caused it to fail to return a value of -1 in cases where only a selected set of rows were to be processed. (affected Fv) - added code to fitsio.h and cfortran.h to typedef LONGLONG to the appropriate 8-byte integer data type. Most compilers now support the 'long long' data type, but older MS Visual C++ compilers used '__int64' instead. - made several small changes based on testing by Martin Reinecke: o in eval.y, change 'int undef' to 'long undef' o in getcold.c and getcole.c, fixed a couple format conversion specifiers when displaying the value of long long variables. o in fitsio.h, modified the definition of USE_LL_SUFFIX in the case of Athon64 machines. o in fitsio2.h, defined BYTESWAPPED in the case of SGI machines. o in group.c, added 'include unistd.h' to get rid of compiler warning. Version 3.005 - 20 December 2005 (beta) - cfortran.h has been enhanced to support 64-bit integer parameters when calling C routines from Fortran. This modification was kindly provided by Martin Reinecke (MPE, Garching). - Many new Fortran wrapper routines have been added to support reading and writing 64-bit integer values in FITS files. These new routines are documented in the updated version of the 'FITSIO User's Guide' for Fortran programmers. - fixed a problem in the fits_get_keyclass routine that caused it to not recognize the special COMMENT keywords at the beginning of most FITS files that defines the FITS format. - added a new check to the ffifile routine that parses the input extended file name, to distinguish between a FITS extension name that begins with 'pix', and a pixel filtering operator that begins with the 'pix' keyword. - small change to the WCSLIB interface routine, fits_read_wcstab, to be more permissive in allowing the TDIMn keyword to be omitted for degenerate coordinate array. Version 3.004 - 16 September 2005 (3rd public beta release) - a major enhancement to the CFITSIO virtual file parser was provided by Robert Wiegand (GSFC). One can now specify filtering operations that will be applied on the fly to the pixel values in a FITS image. For example [pix sqrt(X)] will create a virtual FITS image where the pixel values are the square root of the input image pixels. - modified region.c so that it interprets the position angles of regions in a SAO style region file in the same way as DS9. In particular, if the region parameters are given in WCS units, then the position angle should be relative to the WCS coordinates of the image (increasing CCW from West) instead of relative to the X/Y pixel coordinate system. This only affects rotated images (e.g. with non-zero CROTA2 keyword) with elliptical or rectangular regions. - cleaned up fitsio.h and fitsio2.h to make the definition of LONGLONG and BYTESWAPPED and MACHINE more logical. - removed HAVE_LONGLONG everywhere since it is no longer needed (the compiler now must have an 8-byte integer datatype to build CFITSIO). - added support for the 64-bit IBM AIX platform - modified eval.y so that the circle, ellipse, box, and near functions can operate on vectors as well as scalars. This allows region filtering on images that are stored in a vector cell in a binary table. (provided by Craig Markwardt, GSFC) New Routines - added new fits_read_wcstab routine that serves as an interface to Mark Calabretta's wcslib library for reading WCS information when the -TAB table lookup convention is used in the FITS file. - added new fits_write_nullrows routine, which writes null values into every column of a specified range of rows in a FITS table. - added the fits_translate_keyword and fits_translate_keywords utility routines for converting the names of keywords when moving columns and images around. - added fits_copy_cell2image and fits_copy_image2cell routines for copying an image extension (or primary array) to or from a cell in a binary table vector column. Bug fixes - fixed a memory leak in eval.y; was fixed by changing a call to malloc to cmalloc instead. - changed the definition of several global variables at the beginning of buffers.c to make them 'static' and thus invisible to applications programs. - in fits_copy_image_cell, added a call to flush the internal buffers before reading from the file, in case any records had been modified. Version 3.003 - 28 July 2005 - 2nd public beta release (used in HEASOFT) Enhancements - enhanced the string column reading routing fits_get_col_str to support cases where the user enters a null pointer (rather than a null string) as the nulval parameter. - modified the low level ffread and ffwrite routines that physically read and write data from the FITS file so that they write the name of the file to the CFITSIO error stack if an error occurs. - changed the definition of fits_open_file into a macro that will test that the version of the fitsio.h include file that was used to build the CFITSIO library is the same version as included when compiling the application program. - made a simple modification to region.c to support regions files of type "linear", for compatibility with ds9 and fv. - modified the internal ffgpr routine (and renamed it ffgprll) so that it returns the TNULL value as a LONGLONG parameter instead of 'long'. - in fits_get_col_display_width, added support for TFORM = 'k' - modified fitsio.h, fitsio2.h, and f77_wrap.h to add test for (_SX) to identify NEC SX supercomputers. - modified eval_f.c to treat table columns of TULONG (unsigned long) as a double. Also added support for TLONGLONG (8-byte integers) as a double, which is only a temporary fix, since doubles only have about 52 bits of precision. - changed the 'blank' parameter in the internal ffgphd function to to type LONGLONG to support integer*8 FITS images. - when reading the TNULL keyword value, now use ffc2jj instead of ffc2ii, to support integer*8 values. Bug fixes - fixed a significant bug when writing character strings to a variable length array column of a binary table. This bug would result in some unused space in the variable length heap, making the heap somewhat larger than necessary. This in itself is usually a minor issue, since the FITS files are perfectly valid, and other software should have no problems reading back the characters strings. In some cases, however, this problem could cause the program that is writing the table to exit with a status = 108 disk read error. - modified the standalone imcopy.c utility program to fix a memory allocation bug when running on 64-bit platforms where sizeof(long) = 8 bytes. - added an immediate 'return' statement to ffgtcl if the input status >0, to prevent a segfault on some platforms. Version 3.002 - 15 April 2005 - first public beta release - in drvrfile.c, if it fails to open the file for some reason, then it should reset file_outfile to a null string, to avoid errors on a subsequent call to open a file. - updated fits_get_keyclass to recognize most of the WCS keywords defined in the WCS Papers I and II. Version 3.001 - 15 March 2005 - released with HEASOFT 6.0 - numerous minor changes to the code to get rid of compiler warning messages, mainly dealing with numerical data type casting and the subsequent possible loss of precision in the result. Version 3.000 - 1 March 2005 (internal beta release) Enhancements: - Made major changes to many of the CFITSIO routines to more generally support Large Files (> 2.1 GB). These changes are intended to be 100% backward compatible with software that used the previous versions of CFITSIO. The datatype of many of the integer parameters in the CFITSIO functions has been changed from 'long' to 'LONGLONG', which is typedef'ed to be equivalent to an 8-byte integer datatype on each platform. With these changes, CFITSIO supports the following: - integer FITS keywords with absolute values > 2**31 - FITS files with total sizes > 2**31 bytes - FITS tables in which the number of rows, the row width, or the size of the heap is > 2**31 bytes - FITS images with dimensions > 2**31 bytes (support is still somewhat limited, with full support to be added later). - added another lexical parser function (thanks to Craig Markwardt, GSFC): angsep computes the angular separation between 2 positions on the celestial sphere. - modified the image subset extraction code (e.g., when specifying an image subregion when opening the file, such as 'myimage.fits[21:40, 81:90]') so that in addition to updating the values of the primary WCS keywords CRPIXk, CDELTi, and CDj_i in the extracted/binned image, it also looks for and updates any secondary WCS keywords (e.g., 'CRPIX1P'). - made cosmetic change to group.c, so that when a group table is copied, any extra columns will be appended after the last existing column, instead of being inserted before the last column. - modified the routines that read tile compressed images to support NULL as the input value for the 'anynul' parameter (meaning the calling program does not want the value of 'anynul' returned to it). - when constructing or parsing a year/month/day character string, (e.g, when writing the DATE keyword) the routines now rigorously verify that the input day value is valid for the given month (including leap years). - added some checks in cfileio.c to detect if some vital parameters that are stored in memory have been corrupted. This can occur if a user's program writes to areas of memory that it did not allocate. - added the wcsutil_alternate.c source code file which contains non-working stubs for the 2 Classic AIPS world coordinate conversion routines that are distributed under the GNU General Public License. Users who are unwilling or unable to distribute their software under the General Public License may use this alternate source file which has no GPL restrictions, instead of wcsutil.c. This will have no effect on programs that use CFITSIO as long as they do not call the fits_pix_to_world/ffwldp or fits_world_to_pix/ffxypx routines. Bug Fixes - in ffdtdm (which parses the TDIMn keyword value), the check for consistency between the length of the array defined by TDIMn and the size of the TFORMn repeat value, is now not performed for variable length array columns (which always have repeat = 1). - fixed byteswapping problem when writing null values to non-standard long integer FITS images with BITPIX = 64 and FITS table columns with TFORMn = 'K'. - fixed buffer overflow problem in fits_parse_template/ffgthd that occurred only if the input template keyword value string was much longer than can fit in an 80-char header record. Version 2.510 - 2 December 2004 New Routines: - added fits_open_diskfile and fits_create_diskfile routines that simply open or create a FITS file with a specified name. CFITSIO does not try to parse the name using the extended filename syntax. - 2 new C functions, CFITS2Unit and CUnit2FITS, were added to convert between the C fitsfile pointer value and the Fortran unit number. These functions may be useful in mixed language C and Fortran programs. Enhancements: - added the ability to recognize and open a compressed FITS file (compressed with gzip or unix compress) on the stdin standard input stream. - Craig Markwardt (GSFC) provided 2 more lexical parser functions: accum(x) and seqdiff(x) that compute the cumulative sum and the sequential difference of the values of x. - modified putcole.c and putcold.c so that when writing arrays of pixels to the FITS image or column that contain null values, and there are also numerical overflows when converting some of the non-null values to the FITS values, CFITSIO will now ignore the overflow error until after all the data have been written. Previously, in some circumstances CFITSIO would have simply stopped writing any data after the first overflow error. - modified fitsio2.h to try to eliminate compiler warning messages on some platforms about the use of 'long long' constants when defining the value of LONGLONG_MAX (whether to use L or LL suffix). - modified region.c to support 'physical' regions in addition to 'image', 'fk4', etc. - modified ffiurl (input filename parsing routine) to increase the maximum allowed extension number that can be specified from 9999 to 99999 (e.g. 'myfile.fits+99999') Bug Fixes: - added check to fits_create_template to force it to start with the primary array in the template file, in case an extension number was specified as part of the template FITS file name. Version 2.500 - 28 & 30 July 2004 New Routine: - fits_file_exists tests whether the specified input file, or a compressed version of the file, exists on disk. Enhancements: - modified the way CFITSIO reads and writes data in COMPLEX ('C') and DBLCOMPLEX 'M' columns. Now, in all cases, when referring to the number of elements in the vector, or the value of the offset to a particular element within the vector, CFITSIO considers each pair of numbers (the imaginary and real parts) as a single element instead of treating each single number as an element. In particular, this changes the behavior of fits_write_col_null when writing to complex columns. It also changes the length of the 'nullarray' vector in the fits_read_colnull routine; it is now only 1/2 as long as before. Each element of the nullarray is set = 1 if either the real or imaginary parts of the corresponding complex value have a null value.(this change was added to version 2.500 on 30 July). - Craig Markwardt, at GSFC, provided a number of significant enhancements to the CFITSIO lexical parser that is used to evaluate expressions: - the parser now can operate on bit columns ('X') in a similar way as for other numeric columns (e.g., 'B' or 'I' columns) - range checking has been implemented, so that the following conditions return a Null value, rather than returning an error: divide by zero, sqrt(negative), arccos(>1), arcsin(>1), log(negative), log10(negative) - new vector functions: MEDIAN, AVERAGE, STDDEV, and NVALID (returns the number of non-null values in the vector) - all the new functions (and SUM, MIN and MAX) ignore null values - modified the iterator to support variable-length array columns - modified configure to support AIX systems that have flock in a non- standard location. - modified configure to remove the -D_FILE_OFFSET_BITS flag when running on Mac Darwin systems. This caused conflicts with the Fortran wrappers, and should only be needed in any case when using CFITSIO to read/write FITS files greater than 2.1 GB in size. - modified fitsio2.h to support compilers that define LONG_LONG_MAX. - modified ffrsim (resize an existing image) so that it supports changing the datatype to an unsigned integer image using the USHORT_IMG and ULONG_IMG definitions. - modified the disk file driver (drvrfile.c) so that if an output file is specified when opening an ordinary file (e.g. with the syntax 'myfile.fits(outputfile.fits)' then it will make a copy of the file, close the original file and open the copy. Previously, the specified output file would be ignored unless the file was compressed. - modified f77_wrap.h and f77_wrap3.c to support the Fortran wrappers on 64-bit AMD Opteron machines Bug fixes: - made small change to ffsrow in eval_f.c to avoid potential array bounds overflow. - made small change to group.c to fix problem where an 'int' was incorrectly being cast to a 'long'. - corrected a memory allocation error in the new fits_hdr2str routine that was added in version 2.48 - The on-the-fly row-selection filtering would fail with a segfault if the length of a table row (NAXIS1 value) was greater than 500000 bytes. A small change to eval_f.c was required to fix this. Version 2.490 - 11 February 2004 Bug fixes: - fixed a bug that was introduced in the previous release, which caused the CFITSIO parser to no longer move to a named extension when opening a FITS file, e.g., when opening myfile.fit[events] CFITSIO would just open the primary array instead of moving to the EVENTS extension. - new group.c file from the INTEGRAL Science Data Center. It fixes a problem when you attach a child to a parent and they are both is the same file, but, that parent contains groups in other files. In certain cases the attach would not happen because it seemed that the new child was already in the parent group. - fixed bug in fits_calculator_rng when performing a calculation on a range of rows in a table, so that it does not reset the value in all the other rows that are not in the range = 0. - modified fits_write_chksum so that it updates the TFORMn keywords for any variable length vector table columns BEFORE calculating the CHECKSUM values. Otherwise the CHECKSUM value is invalidated when the HDU is subsequently closed. Version 2.480 - 28 January 2004 New Routines: - fits_get_img_equivtype - just like fits_get_img_type, except in the case of scaled integer images, it returns the 'equivalent' data type that is necessary to store the scaled data values. - fits_hdr2str copies all the header keywords in the current HDU into a single long character string. This is a convenient method of passing the header information to other subroutines. The user may exclude any specified keywords from the list. Enhancements: - modified the filename parser so that it accepts extension names that begin with digits, as in 'myfile.fits[123TEST]'. In this case CFITSIO will try to open the extension with EXTNAME = '123TEST' instead of trying to move to the 123rd extension in the file. - the template keyword parser now preserves the comments on the the mandatory FITS keywords if present, otherwise a standard default comment is provided. - modified the ftp driver file (drvrnet.c) to overcome a timeout or hangup problem caused by some firewall software at the user's end (Thanks to Bruce O'Neel for this fix). - modified iraffits.c to incorporate Doug Mink's latest changes to his wcstools library routines. The biggest change is that now the actual image dimensions, rather than the physically stored dimensions, are used when converting an IRAF file to FITS. Bug fixes: - when writing to ASCII FITS tables, the 'elemnum' parameter was supposed to be ignored if it did not have the default value of 1. In some cases however setting elemnum to a value other than 1 could cause the wrong number of rows to be produced in the output table. - If a cfitsio calculator expression was imported from a text file (e.g. using the extended filename syntax 'file.fits[col @file.calc]') and if any individual lines in that text file were greater than 255 characters long, then a space character would be inserted after the 255th character. This could corrupt the line if the space was inserted within a column name or keyword name token. Version 2.480beta (used in the FTOOLS 5.3 release, 1 Nov 2003) New Routines: - fits_get_eqcoltype - just like fits_get_coltype, except in the case of scaled integer columns, it returns the 'equivalent' data type that is necessary to store the scaled data values. - fits_split_names - splits an input string containing a comma or space delimited list of names (typically file names or column names) into individual name tokens. Enhancements: - changed fhist in histo.c so that it can make histograms of ASCII table columns as well as binary table columns (as long as they contain numeric data). Bug fixes: - removed an erroneous reference to listhead.c in makefile.vcc, that is used to build the cfitsio dll under Windows. This caused a 'main' routine to be added to the library, which causes problems when linking fortran programs to cfitsio under windows. - if an error occurs when opening for a 2nd time (with ffopen) a file that is already open (e.g., the specified extension doesn't exist), and if the file had been modified before attempting to reopen it, then the modified buffers may not get written to disk and the internal state of the file may become corrupted. ffclos was modified to always set status=0 before calling ffflsh if the file has been concurrently opened more than once. Version 2.470 - 18 August 2003 Enhancements: - defined 'TSBYTE' to represent the 'signed char' datatype (similar to 'TBYTE' that represents the 'unsigned char' datatype) and added support for this datatype to all the routines that read or write data to a FITS image or table. This was implemented by adding 2 new C source code files to the package: getcolsb.c and putcolsb.c. - Defined a new '1S' shorthand data code for a signed byte column in a binary table. CFITSIO will write TFORMn = '1B' and TZEROn = -128 in this case, which is the convention used to store signed byte values in a 'B' type column. - in fitsio2.h, added test of whether `__x86_64__` is defined, to support the new AMD Opteron 64-bit processor - modified configure to not use the -fast compiler flag on Solaris platforms when using the proprietary Solaris cc compiler. This flag causes compilation problems in eval_y.c (compiler just hangs forever). Bug fixes: - In the special case of writing 0 elements to a vector table column that contains 0 rows, ffgcpr no longer adds a blank row to the table. - added error checking code for cases where a ASCII string column in a binary table is greater than 28800 characters wide, to avoid going into an infinite loop. - the fits_get_col_display_width routine was incorrectly returning width = 0 for a 'A' binary table column that did not have an explicit vector length character. Version 2.460 - 20 May 2003 Enhancements: - modified the HTTP driver in drvrnet.c so that CFITSIO can read FITS files via a proxy HTTP server. (This code was contributed by Philippe Prugniel, Obs. de Lyon). To use this feature, the 'http_proxy' environment variable must be defined with the address (URL) and port number of the proxy server, i.e., > setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 will use port 3128 on heasarc.gsfc.nasa.gov - suppressed some compiler warnings by casting a variable of type 'size_t' to type 'int' in fftkey (in fitscore.c) and iraftofits and irafrdimge (in iraffits.c). Version 2.450 - 30 April 2003 Enhancements: - modified the WCS keyword reading routine (ffgics) to support cases where some of the CDi_j keywords are omitted (with an assumed value = 0). - Made a change to http_open_network in drvrnet.c to add a 'Host: ' string to the open request. This is required by newer HTTP 1.1 servers (so-called virtual servers). - modified ffgcll (read logical table column) to return the illegal character value itself if the FITS file contains a logical value that is not equal to T, F or zero. Previously it treated this case the same as if the FITS file value was = 0. - modified fits_movnam_hdu (ffmnhd) so that it will move to a tile- compressed image (that is stored in a binary table) if the input desired HDU type is BINARY_TBL as well as if the HDU type = IMAGE_HDU. Bug fixes: - in the routine that checks the data fill bytes (ffcdfl), the call to ffmbyt should not ignore an EOF error when trying to read the bytes. This is a little-used routine that is not called by any other CFITSIO routine. - fits_copy_file was not reporting an error if it hit the End Of File while copying the last extension in the input file to the output file. - fixed inconsistencies in the virtual file column filter parser (ffedit_columns) to properly support expressions which create or modify a keyword, instead of a column. Previously it was only possible to modify keywords in a table extension (not an image), and the keyword filtering could cause some of the table columns to not get propagated into the virtual file. Also, spaces are now allowed within the specified keyword comment field. - ffdtyp was incorrectly returning the data type of FITS keyword values of the form '1E-09' (i.e., an exponential value without a decimal point) as integer rather than floating point. - The enhancement in the previous 2.440 release to allow more files to be opened at one time introduced a bug: if ffclos is called with a non-zero status value, then any subsequent call to ffopen will likely cause a segmentation fault. The fits_clear_Fptr routine was modified to fix this. - rearranged the order of some computations in fits_resize_img so as to not exceed the range of a 32-bit integer when dealing with large images. - the template parser routine, ngp_read_xtension, was testing for "ASCIITABLE" instead of "TABLE" as the XTENSION value of an ASCII table, and it did not allow for optional trailing spaces in the IMAGE" or "TABLE" string value. Version 2.440 - 8 January 2003 Enhancements: - modified the iterator function, ffiter, to operate on random groups files. - decoupled the NIOBUF (= 40) parameter from the limit on the number FITS files that can be opened, so that more files may be opened without the overhead of having to increase the number of NIOBUF buffers. A new NMAXFILES parameter is defined in fitsio2.h which sets the maximum number of opened FITS files. It is set = 300 by default. Note however, that the underlying compiler or operating system may not allow this many files to be opened at one time. - updated the version of cfortran.h that is distributed with CFITSIO from version 3.9 to version 4.4. This required changes to f77_wrap.h and f77_wrap3.c. The original cfortran.h v4.4 file was modified slightly to support CFITSIO and ftools (see comments in the header of cfortran.h). - modified ffhist so that it copies all the non-structural keywords from the original binary table header to the binned image header. - modified fits_get_keyclass so that it recognizes EXTNAME = COMPRESSED_IMAGE as a special tile compression keyword. - modified Makefile.in to support the standard --prefix convention for specifying the install target directory. Bug fixes: - in fits_decompress_img, needed to add a call to ffpscl to turn off the BZERO and BSCALE scaling when reading the compressed image. Version 2.430 - 4 November 2002 Enhancements: - modified fits_create_hdu/ffcrhd so that it returns without doing anything and does not generate an error if the current HDU is already an empty HDU. There is no need in this case to append a new empty HDU to the file. - new version of group.c (supplied by B. O'Neel at the ISDC) fixes 2 limitations: 1 - Groups now have 256 characters rather than 160 for the path lengths in the group tables. - ISDC SPR 1720. 2 - Groups now can have backpointers longer than 68 chars using the long string convention. - ISDC SPR 1738. - small change to f77_wrap.h and f77_wrap3.c to support the fortran wrappers on SUN solaris 64-bit sparc systems (see also change to v2.033) - small change to find_column in eval_f.c to support unsigned long columns in binary tables (with TZEROn = 2147483648.0) - small modification to cfortran.h to support Mac OS-X, (Darwin) Bug fixes: - When reading tile-compress images, the BSCALE and BZERO scaling keywords were not being applied, if present. - Previous changes to the error message stack code caused the tile compressed image routines to not clean up spurious error messages properly. - fits_open_image was not skipping over null primary arrays. Version 2.420 - 19 July 2002 Enhancements: - modified the virtual filename parser to support exponential notation when specifying the min, max or binsize in a binning specifier, as in: myfile.fits[binr X=1:10:1.0E-01, Y=1:10:1.0E-01] - removed the limitation on the maximum number of HDUs in a FITS file (limit used to be 1000 HDUs per file). Now any number of HDUs can be written/read in a FITS file. (BUT files that have huge numbers of HDUs can be difficult to manage and are not recommended); - modified grparser.c to support HIERARCH keywords, based on code supplied by Richard Mathar (Max-Planck) - moved the ffflsh (fits_flush_buffer) from the private to the public interface, since this routine may be useful for some applications. It is much faster than ffflus. - small change to the definition of OFF_T in fitsio.h to support large files on IBM AIX operating systems. Bug fixes: - fixed potential problem reading beyond array bounds in ffpkls. This would not have affected the content of any previously generated FITS files. - in the net driver code in drvrnet.c, the requested protocol string was changed from "http/1.0" to "HTTP/1.0" to support apache 1.3.26. - When using the virtual file syntax to open a vector cell in a binary table as if it were a primary array image, there was a bug in fits_copy_image_cell which garbled the data if the vector was more than 30000 bytes long. - fixed problem that caused fits_report_error to crash under Visual C++ on Windows systems. The fix is to use the '/MD' switch on the cl command line, or, in Visual Studio, under project settings / C++ select use runtime library multithreaded DLL - modified ffpscl so it does not attempt to reset the scaling values in the internal structure if the image is tile-compressed. - fixed multiple bugs in mem_rawfile_open which affected the case where a raw binary file is read and converted on the fly into a FITS file. - several small changes to group.c to suppress compiler warnings. Version 2.410 - 22 April 2002 (used in the FTOOLS 5.2 release) New Routines: - fits_open_data behaves similarly to fits_open_file except that it also will move to the first HDU containing significant data if and an explicit HDU name or number to open was not specified. This is useful for automatically skipping over a null primary array when opening the file. - fits_open_table and fits_open_image behaves similarly to fits_open_data, except they move to the first table or image HDU in the file, respectively. - fits_write_errmark and fits_clear_errmark routines can be use to write an invisible marker to the CFITSIO error stack, and then clear any more recent messages on the stack, back to that mark. This preserves any older messages on the stack. - fits_parse_range utility routine parses a row list string and returns integer arrays giving the min and max row in each range. - fits_delete_rowrange deletes a specified list of rows or row ranges. - fits_copy_file copies all or part of the HDUs in the input file to the output file. - added fits_insert_card/ffikey to the publicly defined set of routines (previously, it was a private routine). Enhancements: - changed the default numeric display format in ffgkys from 'E' format to 'G' format, and changed the format for 'X' columns to a string of 8 1s or 0s representing each bit value. - modified ffflsh so the system 'fflush' call is not made in cases where the file was opened with 'READONLY' access. - modified the output filename parser so the "-.gz", and "stdout.gz" now cause the output file to be initially created in memory, and then compressed and written out to the stdout stream when the file is closed. - modified the routines that delete rows from a table to also update the variable length array heap, to remove any orphaned data from the heap. - modified ffedit_columns so that wild card characters may be used when specifying column names in the 'col' file filter specifier (e.g., file.fits[col TIME; *RAW] will create a virtual table contain only the TIME column and any other columns whose name ends with 'RAW'). - modified the keyword classifier utility, fits_get_keyclass, to support cases where the input string is just the keyword name, not the entire 80-character card. - modified configure.in and configure to see if a proprietary C compiler is available (e.g. 'cc'), and only use 'gcc' if not. - modified ffcpcl (copy columns from one table to another) so that it also copies any WCS keywords related to that column. - included an alternate source file that can be used to replace compress.c, which is distributed under the GNU General Public License. The alternate file contains non-functional stubs for the compression routines, which can be used to make a version of CFITSIO that does not have the GPL restrictions (and is also less functional since it cannot read or write compressed FITS files). - modifications to the iterator routine (ffiter) to support writing tile compressed output images. - modified ffourl to support the [compress] qualifier when specifying the optional output file name. E.g., file.fit(out.file[compress])[3] - modified imcomp_compress_tile to fully support implicit data type conversion when writing to tile-compressed images. Previously, one could not write a floating point array to an integer compressed image. - increased the number of internal 2880-byte I/O buffers allocated by CFITSIO from 25 to 40, in recognition of the larger amount of memory available on typical machines today compared with a few years ago. The number of buffers can be set by the user with the NIOBUF parameter in fitsio2.h. (Setting this too large can actually hurt performance). - modified the #if statements in fitsio2.h, f77_wrap.h and f77_wrap1.c to support the new Itanium 64-bit Intel PC. - a couple minor modifications to fitsio.h needed to support the off_t datatype on Debian linux systems. - increased internal buffer sizes in ffshft and ffsrow to improve the I/O performance. Bug fixes: - fits_get_keyclass could sometimes try to append to an unterminated string, causing an overflow of a string array. - fits_create_template no longer worked because of improvements made to other routines. Had to modify ffghdt to not try to rescan the header keywords if the file is still empty and contains no keywords yet. - ffrtnm, which returns the root filename, sometimes did not work properly when testing if the 'filename+n' convention was used for specifying an extension number. - fixed minor problem in the keyword template parsing routine, ffgthd which in rare cases could cause an improperly terminated string to be returned. - the routine to compare 2 strings, ffcmps, failed to find a match in comparing strings like "*R" and "ERROR" where the match occurs on the last character, but where the same matching character occurs previously in the 2nd string. - the region file reading routine (ffrrgn) did not work correctly if the region file (created by POW and perhaps other programs) had an 'exclude' region (beginning with a '-' sign) as the first region in the file. In this case all points outside the excluded region should be accepted, but in fact no points were being accepted in this case. Version 2.401 - 28 Jan 2002 - added the imcopy example program to the release (and Makefile) Bug fixes: - fixed typo in the imcompress code which affected compression of 3D datacubes. - made small change to fficls (insert column) to allow colums with TFORMn = '1PU' and '1PV' to be inserted in a binary table. The 'U' and 'V' are codes only used within CFITSIO to represent unsigned 16-bit and 32-bit integers; They get replaced by '1PI' and '1PJ' respectively in the FITS table header, along with the appropriate TZEROn keyword. Version 2.400 - 18 Jan 2002 (N.B.: Application programs must be recompiled, not just relinked with the new CFITSIO library because of changes made to fitsio.h) New Routines: - fits_write_subset/ffpss writes a rectangular subset (or the whole image) to a FITS image. - added a whole new family of routines to read and write arrays of 'long long' integers (64-bit) to FITS images or table columns. The new routine names all end in 'jj': ffpprjj, ffppnjj, ffp2djj, ffp3djj, ffppssjj, ffpgpjj, ffpcljj, ffpcnjj. ffgpvjj, ffgpfjj, ffg2djj, ffg3djj, ffgsvjj, ffgsfjj, ffggpjj, ffgcvjj, and ffgcfjj. - added a set of helper routines that are used in conjunction with the new support for tiled image compression. 3 routines set the parameters that should be used when CFITSIO compresses an image: fits_set_compression_type fits_set_tile_dim fits_set_noise_bits 3 corresponding routines report back the current settings: fits_get_compression_type fits_get_tile_dim fits_get_noise_bits Enhancements: - major enhancement was made to support writing to tile-compressed images. In this format, the image is divided up into a rectangular grid of tiles, and each tile of pixels is compressed individually and stored in a row of a variable-length array column in a binary table. CFITSIO has been able to transparently read this compressed image format ever since version 2.1. Now all the CFITSIO image writing routines also transparently support this format. There are 2 ways to force CFITSIO to write compressed images: 1) call the fits_set_compression_type routine before writing the image header keywords, or 2), specify that the image should be compressed when entering the name of the output FITS file, using a new extended filename syntax. (examples: "myfile.fits[compress]" will use the default compression parameters, and "myfile.fits[compress GZIP 100,100] will use the GZIP compression algorithm with 100 x 100 pixel tiles. - added new driver to support creating output .gz compressed fits files. If the name of the output FITS file to be created ends with '.gz' then CFITSIO will initially write the FITS file in memory and then, when the FITS file is closed, CFITSIO will gzip the entire file before writing it out to disk. - when over-writing vectors in a variable length array in a binary table, if the new vector to be written is less than or equal to the length of the previously written vector, then CFITSIO will now reuse the existing space in the heap, rather than always appending the new array to the end of the heap. - modified configure.in to support building cfitsio as a dynamic library on Mac OS X. Use 'make shared' like on other UNIX platforms, but a .dylib file will be created instead of .so. If installed in a nonstandard location, add its location to the DYLD_LIBRARY_PATH environment variable so that the library can be found at run time. - made various modifications to better support the 8-byte long integer datatype on more platforms. The 'LONGLONG' datatype is typedef'ed to equal 'long long' on most Unix platforms and MacOS, and equal to '__int64' on Windows machines. - modified configure.in and makefile.in to better support cases where the system has no Fortran compiler and thus the f77 wrapper routines should not be compiled. - made small modification to eval.y and eval_y.f to get rid of warning on some platforms about redefinition of the 'alloca'. Bug fixes: - other recent bug fixes in ffdblk (delete blocks) caused ffdhdu (delete HDU) to fail when trying to replace the primary array with a null primary array. - fixed bug that prevented inserting a new variable length column into a table that already contained variable length data. - modified fits_delete_file so that it will delete the file even if the input status value is not equal to zero. - in fits_resize_image, it was sometimes necessary to call ffrdef to force the image structure to be defined. - modified the filename parser to support input files with names like: "myfile.fits.gz(mem://tmp)" in which the url type is specified for the output file but not for the input file itself. This required modifications to ffiurl and ffrtnm. Version 2.301 - 7 Dec 2001 Enhancements: - modified the http file driver so that if the filename to be opened contains a '?' character (most likely a cgi related string) then it will not attempt to append a .gz or .Z as it would normally do. - added support for the '!' clobber character when specifying the output disk file name in CFITSIO's extended filename syntax, e.g., 'http://a.b.c.d/myfile.fits.gz(!outfile.fits)' - added new device driver which is used when opening a compressed FITS file on disk by uncompressing it into memory with READWRITE access. This happens when specifying an output filename 'mem://'. - added 2 other device drivers to open http and ftp files in memory with write access. - improved the error trapping and reporting in cases where program attempts to write to a READONLY file (especially in cases where the 'file' resides in memory, as is the case when opening an ftp or http file. - modified the extended filename parser so that it is does not confuse the bracket character '[' which is sometimes used in the root name of files of type 'http://', as the start of an extname or row filter expression. If the file is of type 'http://', the parser now checks to see if the last character in the extended file name is a ')' or ']'. If not, it does not try to parse the file name any further. - improved the efficiency when writing FITS files in memory, by initially allocating enough memory for the entire HDU when it is created, rather than incrementally reallocing memory 2880 bytes at a time (modified ffrhdu and mem_truncate). This change also means that the program will fail much sooner if it cannot allocate enough memory to hold the entire FITS HDU. Bug fixes: - There was an error in the definition of the Fortran ftphtb wrapper routine (writes required ASCII table header keywords) that caused it to fail on DEC OSF and other platforms where sizeof(long) = 8. Version 2.300 - 23 Oct 2001 New Routines: - fits_comp_img and fits_decomp_img are now fully supported and documented. These routine compress and decompress, respective, a FITS image using a new algorithm in which the image is first divided into a grid of rectangular tiles, then the compressed byte stream from each tile is stored in a row of a binary table. CFITSIO can transparently read FITS images stored in this compressed format. Compression ratios of 3 - 6 are typically achieved. Large compression ratios are achieved for floating point images by throwing away non-significant noise bits in the pixel values. - fits_test_heap tests the integrity of the binary table heap and returns statistics on the amount of unused space in the heap and the amount of space that is pointed to by more than 1 descriptor. - fits_compress_heap which will reorder the arrays in the binary table heap, recovering any unused space. Enhancements: - made substantial internal changes to the code to support FITS files containing 64-bit integer data values. These files have BITPIX = 64 or TFORMn = 'K'. This new feature in CFITSIO is currently only enabled if SUPPORT_64BIT_INTEGERS is defined = 1 in the beginning of the fitsio2.h file. By default support for 64-bit integers is not enabled. - improved the ability to read and return a table column value as a formatted string by supporting quasi-legal TDISPn values which have a lowercase format code letter, and by completely ignoring other unrecognizable TDISPn values. Previously, unrecognized TDISPn values could cause zero length strings to be returned. - made fits_write_key_longstr more efficient when writing keywords using the long string CONTINUE convention. It previously did not use all the available space on each card when the string to be written contained many single quote characters. - added a new "CFITSIO Quick Start Guide" which provides all the basic information needed to write C programs using CFITSIO. - updated the standard COMMENT keywords that are written at the beginning of every primary array to refer to the newly published FITS Standard document in Astronomy and Astrophysics. Note: because of this change, any FITS file created with this version of CFITSIO will not be identical to the same file written with a previous version of CFITSIO. - replaced the 2 routines in pliocomp.c with new versions provided by D Tody and N Zarate. These routines compress/uncompress image pixels using the IRAF pixel list compression algorithm. - modified fits_copy_hdu so that when copying a Primary Array to an Image extension, the COMMENT cards which give the reference to the A&A journal article about FITS are not copied. In the inverse case the COMMENT keywords are inserted in the header. - modified configure and Makefile.in to add capability to build a shared version of the CFITSIO library. Type 'make shared' or 'make libcfitsio.so' to invoke this option. - disabled some uninformative error messages on the error stack: 1) when calling ffclos (and then ffchdu) with input status > 0 2) when ffmahd tries to move beyond the end of file. The returned status value remains the same as before, but the annoying error messages no longer get written to the error stack. - The syntax for column filtering has been modified so that if one only specifies a list of column names, then only those columns will be copied into the output file. This provides a simple way to make a copy of a table containing only a specified list of columns. If the column specifier explicitly deletes a column, however, than all the other columns will be copied to the filtered input file, regardless of whether the columns were listed or not. Similarly, if the expression specifies only a column to be modified or created, then all the other columns in the table will be copied. mytable.fit[1][col Time;Rate] - only the Time and Rate columns will be copied to the filtered input file. mytable.fit[1][col -Time ] - all but the Time column are copied to the filtered input file. mytable.fit[1][col Rate;-Time] - same as above. - changed a '#if defined' statement in f77_wrap.h and f77_wrap1.c to support the fortran wrappers on 64-bit IBM/RS6000 systems - modified group.c so that when attaching one group (the child) to another (the parent), check in each file for the existence of a pointer to the other before adding the link. This is to prevent multiple links from forming under all circumstances. - modified the filename parser to accept 'STDIN', 'stdin', 'STDOUT' and 'stdout' in addition to '-' to mean read the file from standard input or write to standard output. - Added support for reversing an axis when reading a subsection of a compressed image using the extended filename syntax, as in myfile.fits+1[-*, *] or myfile.fits+1[600:501,501:600] - When copying a compressed image to a uncompressed image, the EXTNAME keyword is no longer copied if the value is equal to 'COMPRESSED_IMAGE'. - slight change to the comment field of the DATE keyword to reflect the fact that the Unix system date and time is not true UTC time. Bug fixes: - fits_write_key_longstr was not writing the keyword if a null input string value was given. - writing data to a variable length column, if that binary table is not the last HDU in the FITS file, might overwrite the following HDU. Fixed this by changing the order of a couple operations in ffgcpr. - deleting a column from a table containing variable length columns could cause the last few FITS blocks of the file to be reset = 0. This bug occurred as a result of modifications to ffdblk in v2.202. This mainly affects users of the 'compress_fits' utility program. - fixed obscure problem when writing bits to a variable length 'B' column. - when reading a subsection of an image, the BSCALE and BZERO pixel scaling may not have been applied when reading image pixel values (even though the scaling keywords were properly written in the header). - fits_get_keyclass was not returning 'TYP_STRUCT_KEY' for the END keyword. Version 2.204 - 26 July 2001 Bug fixes: - Re-write of fits_clean_url in group.c to solve various problems with invalid bounds checking. Version 2.203 - 19 July 2001 (version in FTOOLS v5.1) Enhancements: - When a row selection or calculator expression is written in an external file (and read by CFITSIO with the '@filename' syntax) the file can now contain comment lines. The comment line must begin with 2 slash characters as the first 2 characters on the line. CFITSIO will ignore the entire line when reading the expression. Bug fixes: - With previous versions of CFITSIO, the pixel values in a FITS image could be read incorrectly in the following case: when opening a subset of a FITS image (using the 'filename.fits[Xmin:Xmax,Ymin:Ymax]' notation) on a PC linux, PC Windows, or DEC OSF machine (but not on a SUN or Mac). This problem only occurs when reading more than 8640 bytes of data (2160 4-byte integers) at a time, and usually only occurs if the reading program reads the pixel data immediately after opening the file, without first reading any header keywords. This error would cause strips of zero valued pixels to appear at semi-random positions in the image, where each strip usually would be 2880 bytes long. This problem does not affect cases where the input subsetted image is simply copied to a new output FITS file. Version 2.202 - 22 May 2001 Enhancements: - revised the logic in the routine that tests if a point is within a region: if the first region is an excluded region, then it implicitly assumes a prior include region covering the entire detector. It also now supports cases where a smaller include region is within a prior exclude region. - made enhancement to ffgclb (read bytes) so that it can also read values from a logical column, returning an array of 1s and 0s. - defined 2 new grouping error status values (349, 350) in cfitsio.h and made minor changes to group.c to use these new status values. - modified fits_open_file so that if it encounters an error while trying to move to a user-specified extension (or select a subset of the rows in an input table, or make a histogram of the column values) it will close the input file instead of leaving it open. - when using the extended filename syntax to filter the rows in an input table, or create a histogram image from the values in a table column, CFITSIO now writes HISTORY keywords in the output file to document the filtering expression that was used. Bug fixes: - ffdblk (called by ffdrow) could overwrite the last FITS block(s) in the file in some cases where one writes data to a variable length column and then calls ffdrow to delete rows in the table. This bug was similar to the ffiblk bug that was fixed in v2.033. - modified fits_write_col_null to fix a problem which under unusual circumstances would cause a End-of-File error when trying to read back the value in an ASCII string column, after initializing if by writing a null value to it. - fixed obscure bug in the calculator function that caused an error when trying to modify the value of a keyword in a HDU that does not have a NAXIS2 keyword (e.g., a null primary array). - the iterator function (in putcol.c) had a bug when calculating the optimum number rows to process in the case where the table has very wide rows (>33120 bytes) and the calculator expression involves columns from more than one FITS table. This could cause an infinite loop in calls to the ffcalc calculator function. - fixed bug in ffmvec, which modifies the length of an existing vector column in a binary table. If the vector was reduced in length, the FITS file could sometimes be left in a corrupted state, and in all cases the values in the remaining vector elements of that column would be altered. - in drvrfile.c, replaced calls to fsetpos and fgetpos with fseek and ftell (or fseeko and ftello) because the fpos_t filetype used in fsetpos is incompatible with the off_t filetype used in fseek, at least on some platforms (Linux 7.0). (This fix was inserted into the V2.201 release on April 4). - added "#define fits_write_pixnull ffppxn" to longnam.h Version 2.201 - 15 March 2001 Enhancements - enhanced the keyword reading routines so that they will do implicit datatype conversion from a string keyword value to a numeric keyword value, if the string consist of a valid number enclosed in quotes. For example, the keyword mykey = '37.5' can be read by ffgkye. - modified ffiimg so that it is possible to insert a new primary array at the beginning of the file. The original primary array is then converted into an IMAGE extension. - modified ffcpdt (copy data unit) to support the case where the data unit is being copied between 2 HDUs in the same file. - enhanced the fits_read_pix and fits_read_pixnull routines so that they support the tiled image compression format that the other image reading routines also support. - modified the Extended File Name syntax to also accept a minus sign (-) as well as an exclamation point (!) as the leading character when specifying a column or or keyword to be deleted, as in [col -time] will delete the TIME column. - now completely support reading subimages, including pixel increments in each dimension, for tile-compressed images (where the compressed image tiles are stored in a binary table). Bug fixes: - fixed confusion in the use of the fpos_t and off_t datatypes in the fgetpos and fsetpos routines in drvrfile.c which caused problems with the Windows VC++ compiler. (fpos_t is not necessarily identical to off_t) - fixed a typo in the fits_get_url function in group.c which caused problems when determining the relative URL to a compressed FITS file. - included fitsio.h in the shared memory utility program, smem.c, in order to define OFF_T. - fixed typo in the datatype of 'nullvalue' in ffgsvi, which caused attempts to read subsections of a short integer tiled compressed image to fail with a bus error. - fixed bug in ffdkey which sometimes worked incorrectly if one tried to delete a nonexistent keyword beyond the end of the header. - fixed problem in fits_select_image_section when it writes a dummy value to the last pixel of the section. If the image contains scaled integer pixels, then in some cases the pixel value could end up out of range. - fixed obscure bug in the ffpcn_ family of routines which gave a floating exception when trying to write zero number of pixels to a zero length array (why would anyone do this?) Version 2.200 - 26 Jan 2001 Enhancements - updated the region filtering code to support the latest region file formats that are generated by the POW, SAOtng and ds9 programs. Region positions may now be given in HH:MM:SS.s, DD:MM:SS.s format, and region sizes may be given arcsec or arcmin instead of only in pixel units. Also changed the logic so that if multiple 'include' regions are specified in the region file, they are ORed together, instead of ANDed, so that the filtering keeps points that are located within any of the 'include' regions, not just the intersection of the regions. - added support for reading raw binary data arrays by converting them on the fly into virtual FITS files. - modified ffpmsg, which writes error messages to CFITSIO's internal error stack, so that messages > 80 characters long will be wrapped around into multiple 80 character messages, instead of just being truncated at 80 characters. - modified the CFITSIO parser so that expression which involve scaled integer columns get cast to double rather than int. - Modified the keyword template parsing routine, ffgthd, to support the HIERARCH keyword. - modified ffainit and ffbinit so that they don't unnecessarily allocate 0 bytes of memory if there are no columns (TFIELDS = 0) in the table that is being opened. - modified fitsio2.h to support NetBSD on Alpha OSF platforms (NetBSD does not define the '__unix__' symbol). - changed the way OFF_T is defined in fitsio.h for greater portability. - changed drvrsmem.c so it is compiled only when HAVE_SHMEM_SERVICES is defined in order to removed the conditional logic from the Makefile - reorganized the CFITSIO User's guide to make it clearer and easier for new users to learn the basic routines. - fixed ffhdef (which reserves space for more header keywords) so that is also updates the start position of the next HDU. This affected the offset values returned by ffghof. Version 2.100 - 18 Oct 2000 Enhancements - made substantial modification to the code to support Large files, i.e., files larger than 2**31 bytes = 2.1GB. FITS files up to 6 terabytes in size may now be read and written on platforms that support Large files (currently only Solaris). - modified ffpcom and ffphis, which write COMMENT and HISTORY keywords, respectively, so that they now use columns 9 - 80, instead of only columns 11 - 80. Previously, these routines avoided using columns 9 and 10, but this is was unnecessarily restrictive. - modified ffdhdu so that instead of refusing to delete the primary array, it will replace the current primary array with a null primary array containing the bare minimum of required keywords and no data. New Routines - fits_read_pix, fits_read_pixnull, fits_read_subset, and fits_write_pix routines were added to enable reading and writing of Large images, with more than 2.1e9 pixels. These new routines are now recommended as the basic routines for reading and writing all images. - fits_get_hduoff returns the byte offset in the file to the start and end of the current HDU. This routine replaces the now obsolete fits_get_hduaddr routine; it uses 'off_t' instead of 'long' as the datatype of the arguments and can support offsets in files greater than 2.1GB in size. Bug fixes: - fixed bug in fits_select_image_section that caused an integer overflow when reading very large image sections (bigger than 8192 x 8192 4-byte pixels). - improved ffptbb, the low-level table writing routine, so that it will insert additional rows in the table if the table is not already big enough. Previously it would have just over- written any HDUs following the table in the FITS file. - fixed a bug in the fits_write_col_bit/ffpclx routine which could not write to a bit 'X' column if that was the first column in the table to be written to. This bug would not appear if any other datatype column was written to first. - non-sensible (but still formally legal) binary table TFORM values such as '8A15', or '1A8' or 'A8' would confuse CFITSIO and cause it to return a 308 error. When parsing the TFORMn = 'rAw' value, the ffbnfm routine has been modified to ignore the 'w' value in cases where w > r. - fixed bug in the blsearch routine in iraffits.c which sometimes caused an out-of-bounds string pointer to be returned when searching for blank space in the header just before the 'END' keyword. - fixed minor problem in ffgtcr in group.c, which sometimes failed while trying to move to the end of file before appending a grouping table. - on Solaris, with Sun CC 5.0, one must check for '__unix' rather than '__unix__' or 'unix' as it's symbol. Needed to modify this in drvrfile.c in 3 places. - in ffextn, the FITS file would be left open if the named extension doesn't exist, thus preventing the file from being opened again later with write access. - fixed bug in ffiimg that would cause attempts to insert a new image extension following a table extension, and in front of any other type of extension, to fail. Version 2.037 - 6 July 2000 Enhancements - added support in the extended filename syntax for flipping an image along any axis either by specifying a starting section pixel number greater than the ending pixel number, or by using '-*' to flip the whole axis. Examples: "myfile.fits[1:100, 50:10]" or "myfile.fits[-*,*]". - when reading a section of an image with the extended filename syntax (e.g. image.fits[1:100:2, 1:100:2), any CDi_j WCS keywords will be updated if necessary to transfer the world coordinate system from the input image to the output image section. - on UNIX platforms, added support for filenames that begin with "~/" or "~user/". The "~" symbol will get expanded into a string that gives the user's home directory. - changed the filename parser to support disk file names that begin with a minus sign. Previously, the leading minus sign would cause CFITSIO to try to read/write the file from/to stdin/stdout. - modified the general fits_update_key routine, which writes or updates a keyword value, to use the 'G' display format instead of the 'E' format for floating point keyword values. This will eliminate trailing zeros from appearing in the value. - added support for the "-CAR" celestial coordinate projection in the ffwldp and ffxypx routines. The "-CAR" projection is the default simplest possible linear projection. - added new fits_create_memfile/ffimem routine to create a new fits file at a designated memory location. - ported f77_wrap.h and f77_wrap1.c so that the Fortran interface wrappers work correctly on 64-bit SGI operating systems. In this environment, C 'long's are 8-bytes long, but Fortran 'integers' are still only 4-bytes long, so the words have to be converted by the wrappers. - minor modification to cfortran.h to automatically detect when it is running on a linux platform, and then define f2cFortran in that case. This eliminates the need to define -Df2cFortran on the command line. - modified group.c to support multiple "/" characters in the path name of the file to be opened/created. - minor modifications to the parser (eval.y, eval_f.c, eval_y.c) to a) add the unary '+' operator, and b) support copying the TDIMn keyword from the input to the output image under certain circumstances. - modified the lexical parser in eval_l.y and eval_l.c to support #NULL and #SNULL constants which act to set the value to Null. Support was also added for the C-conditional expression: 'Boolean ? trueVal : falseVal'. - small modification to eval_f.c to write an error message to the error stack if numerical overflow occurs when evaluating an expression. - configure and configure.in now support the egcs g77 compiler on Linux platforms. Bug fixes: - fixed a significant bug when using the extended filename binning syntax to generate a 2-dimensional image from a histogram of the values in 2 table columns. This bug would cause table events that should have been located in the row just below the bottom row of the image (and thus should have been excluded from the histogram) to be instead added into the first row of the image. Similarly, the first plane of a 3-D or 4-D data cube would include the events that should have been excluded as falling in the previous plane of the cube. - fixed minor bug when parsing an extended filename that contains nested pairs of square brackets (e.g., '[col newcol=oldcol[9]]'). - fixed bug when reading unsigned integer values from a table or image with fits_read_col_uint/ffgcvuk. This bug only occurred on systems like Digital Unix (now Tru64 Unix) in which 'long' integers are 8 bytes long, and only when reading more than 7200 elements at a time. This bug would generally cause the program to crash with a segmentation fault. - modified ffgcpr to update 'heapstart' as well as 'numrows' when writing more rows beyond the end of the table. heapstart is needed to calculate if more space needs to be inserted in the table when inserting columns into the table. - modified fficls (insert column), ffmvec, ffdrow and ffdcol to not use the value of the NAXIS2 keyword as the number of rows in the table, and instead use the value that is stored in an internal structure, because the keyword value may not be up to date. - Fixed bug in the iterator function that affected the handling of null values in string columns in ASCII and binary tables. - Reading a subsample of pixels in very large images, (e.g., file = myfile.fits[1:10000:10,1:10000:10], could cause a long integer overflow (value > 2**31) in the computation of the starting byte offset in the file, and cause a return error status = 304 (negative byte address). This was fixed by changing the order of the arithmetic operations in calculating the value of 'readptr' in the ffgcli, ffgclj, ffgcle, ffgcld, etc. routines. - In version 2.031, a fix to prevent compressed files from being opened with write privilege was implemented incorrectly. The fix was intended to not allow a compressed FITS file to be opened except when a local uncompressed copy of the file is being produced (then the copy is opened with write access), but in fact the opposite behavior occurred: Compressed files could be opened with write access, EXCEPT when a local copy is produced. This has been fixed in the mem_compress_open and file_compress_open routines. - in iraffits.c, a global variable called 'val' caused multiply defined symbols warning when linking cfitsio and IRAF libraries. This was fixed by making 'val' a local variable within the routine. Version 2.036 - 1 Feb 2000 - added 2 new generic routines, ffgpf and ffgcf which are analogous to ffgpv and ffgcv but return an array of null flag values instead of setting null pixels to a reserved value. - minor change to eval_y.c and eval.y to "define alloca malloc" on all platforms, not just VMS. - added support for the unsigned int datatype (TUINT) in the generic ffuky routine and changed ffpky so that unsigned ints are cast to double instead of long before being written to the header. - modified ffs2c so that if a null string is given as input then a null FITS string (2 successive single quotes) will be returned. Previously this routine would just return a string with a single quote, which could cause an illegal keyword record to be written. - The file flush operation on Windows platforms apparently changes the internal file position pointer (!) in violation of the C standard. Put a patch into the file_flush routine to explicitly seek back to the original file position. - changed the name of imcomp_get_compressed_image_parms to imcomp_get_compressed_image_par to not exceed the 31 character limit on some compilers. - modified the filename parser (which is used when moving to a named HDU) to support EXTNAME values which contain embedded blanks. - modified drvrnet.c to deal with ftp compressed files better so that even fits files returned from cgi queries which have the wrong mime types and/or wrong types of file names should still decompress. - modified ffgics to reduce the tolerance for acceptable skewness between the axes, and added a new warning return status = APPROX_WCS_KEY in cases where there is significant skewness between the axes. - fixed bug in ffgics that affected cases where the first coordinate axis was DEC, not RA, and the image was a mirror image of the sky. - fixed bug in ffhist when trying to read the default binning factor keyword, TDBIN. - modified ffhist so that is correctly computes the rotation angle in a 2-D image if the first histogram column has a CROTA type keyword but the 2nd column does not. - modified ffcpcl so that it preserves the comment fields on the TTYPE and TFORM keywords when the column is copied to a new file. - make small change to configure.in to support FreeBSD Linux by setting CFLAGS = -Df2cFortran instead of -Dg77Fortran. Then regenerated configure with autoconf 2.13 instead of 2.12. Version 2.035 - 7 Dec 1999 (internal release only, FTOOLS 5.0.2) - added new routine called fits_get_keyclass/ffgkcl that returns the general class of the keyword, e.g., required structural keyword, WCS keyword, Comment keyword, etc. 15 classes of keywords have been defined in fitsio.h - added new routine called fits_get_img_parm/ffgipr that is similar to ffgphd but it only return the bitpix, naxis, and naxisn values. - added 3 new routines that support the long string keyword convention: fits_insert_key_longstr, fits_modify_key_longstr fits_update_key_longstr. - modified ffgphd which reads image header keywords to support the new experimental compressed image format. - when opening a .Z compressed file, CFITSIO tries to allocate memory equal to 3 times the file size, which may be excessive in some cases. This was changed so that if the allocation fails, then CFITSIO will try again to allocate only enough memory equal to 1 times the file size. More memory will be allocated later if this turns out to be too small. - improved the error checking in the fits_insert_key routine to check for illegal characters in the keyword. Version 2.034 - 23 Nov 1999 - enhanced support for the new 'CD' matrix world coordinate system keywords in the ffigics routine. This routine has been enhanced to look for the new 'CD' keywords, if present, and convert them back to the old CDELTn and CROTAn values, which are then returned. The routine will also swap the WCS parameters for the 2 axes if the declination-like axis is the first WCS axis. - modified ffphbn in putkey.c to support the 'U' and 'V" TFORM characters (which represent unsigned short and unsigned int columns) in variable length array columns. (previously only supported these types in fixed length columns). - added checks when reading gzipped files to detect unexpected EOF. Previously, the 'inflate_codes' routine would just sit in an infinite loop if the file ended unexpectedly. - modified fits_verify_chksum/ffvcks so that checksum keywords with a blank value string are treated as undefined, the same as if the keyword did not exist at all. - fixed ffghtb and ffghbn so that they return the extname value in cases where there are no columns in the table. - fixed bug in the ffgtwcs routine (this is a little utility routine to aid in interfacing to Doug Mink's WCS routines); it was not correctly padding the length of string-valued keywords in the returned string. - fixed bug in 'iraffits.c' that prevented Type-2 IRAF images from being correctly byte-swapped on PCs and DEC-OSF machines. - fixed tiny memory leak in irafncmp in iraffits.c. Only relevant when reading IRAF .imh files. - fixed a bug (introduced in version 2.027) that caused the keyword reading routines to sometimes not find a matching keyword if the input name template used the '*' wildcard as the last character. (e.g., if input name = 'COMMENT*' then it would not find the 'COMMENT' keywords. (It would have found longer keywords like 'COMMENTX' correctly). The fix required a minor change to ffgcrd in getkey.c - modified the routine (ffswap8) that does byteswapping of double precision numbers. Some linux systems have reported floating point exceptions because they were trying to interpret the bytes as a double before the bytes had been swapped. - fixed bug in the calculation of the position of the last byte in the string of bits to be read in ffgcxuk and ffgcxui. This bug generally caused no harm, but could cause the routine to exit with an invalid error message about trying to read beyond the size of the field. - If a unix machine did not have '__unix__', 'unix', or '__unix' C preprocessor symbols defined, then CFITSIO would correctly open one FITS file, but would not correctly open subsequent files. Instead it would think that the same file was being opened multiple times. This problem has only been seen on an IBM/AIX machine. The fits_path2url and fits_url2path routines in group.c were modified to fix the problem. - fixed bug in group.c, which affected WINDOWS platforms only, that caused programs to go into infinite loop when trying to open certain files. - the ftrsim Fortran wrapper routine to ffrsim was not defined correctly, which caused the naxis(2) value to be passed incorrectly on Dec OSF machines, where sizeof(long) != sizeof(int). Version 2.033 - 17 Sept 1999 - New Feature: enhanced the row selection parser so that comparisons between values in different rows of the table are allowed, and the string comparisons with <, >, <=, and >= are supported. - added new routine the returns the name of the keyword in the input keyword record string. The name is usually the first 8 characters of the record, except if the HIERARCH convention is being used in which case the name may be up to 67 characters long. - added new routine called fits_null_check/ffnchk that checks to see if the current header contains any null (ASCII 0) characters. These characters are illegal in FITS headers, but they go undetected by the other CFITSIO routines that read the header keywords. - the group.c file has been replaced with a new version as supplied by the ISDC. The changes are mainly to support partial URLs and absolute URLs more robustly. Host dependent directory paths are now converted to true URLs before being read from/written to grouping tables. - modified ffnmhd slightly so that it will move to the first extension in which either the EXTNAME or the HDUNAME keyword is equal to the user-specified name. Previously, it only checked for HDUNAME if the EXTNAME keyword did not exist. - made small change to drvrnet.c so that it uncompress files which end in .Z and .gz just as for ftp files. - rewrote ffcphd (copy header) to handle the case where the input and output HDU are in the same physical FITS file. - fixed bug in how long string keyword values (using the CONTINUE convention) were read. If the string keyword value ended in an '&' character, then fits_read_key_longstr, fits_modify_key_str, and fits_delete_key would interpret the following keyword as a continuation, regardless of whether that keyword name was 'CONTINUE' as required by this convention. There was also a bug in that if the string keyword value was all blanks, then fits_modify_key_str could in certain unusual cases think that the keyword ended in an '&' and go into an infinite loop. - modified ffgpv so that it calls the higher level ffgpv_ routine rather than directly calling the lower level ffgcl_ routine. This change is needed to eventually support reading compressed images. - added 3 new routines to get the image datatype, image dimensions, and image axes length. These support the case where the image is compressed and stored in a binary table. - fixed bug in ffiblk that could sometimes cause it to insert a new block in a file somewhere in the middle of the data, instead of at the end of the HDU. This fortunately is a rare problem, mainly only occurring in certain cases when inserting rows in a binary table that contains variable length array data (i.e., has a heap). - modified fits_write_tdim so that it double checks the TFORMn value directly if the column repeat count stored in the internal structure is not equal to the product of all the dimensions. - fixed bug that prevented ffitab or ffibin from inserting a new table after a null primary array (can't read NAXIS2 keyword). Required a small change to ffrdef. - modified testprog.c so that it will continue to run even if it cannot open or process the template file testprog.tpt. - modified the logic in lines 1182-1185 of grparser.c so that it returns the correct status value in case of an error. - added test in fitsio2.h to see if __sparcv9 is defined; this identifies a machine running Solaris 7 in 64-bit mode where long integers are 64 bits long. Version 2.032 - 25 May 1999 - the distribution .tar file was changed so that all the files will be untarred into a subdirectory by default instead of into the current directory. - modified ffclos so that it always frees the space allocated by the fptr pointer, even when another fptr points to the same file. - plugged a potential (but rare in practice) memory leak in ffpinit - fixed bug in all the ffp3d_ and ffg3d_ routines in cases where the data cube that has been allocated in memory has more planes than the data cube in the FITS file. - modified drvrsmem.c so that it allocates a small shared memory segment only if CFITSIO tries to read or write a FITS file in shared memory. Previously it always allocated the segment whether it was needed or not. Also, this small segment is removed if 0 shared memory segments remain in the system. - put "static" in front of 7 DECLARE macros in compress.c because these global variables were causing conflicts with other applications programs that had variables with the same names. - modified ffasfm to return datatype = TDOUBLE instead of TFLOAT if the ASCII table column has TFORMn = 'Ew.d' with d > 6. - modified the column reading routines to a) print out the offending entry if an error occurs when trying to read a numeric ASCII table column, and b) print out the column number that had the error (the messages are written to CFITSIOs error stack) - major updates to the Fortran FITSIO User's Guide to include many new functions that have been added to CFITSIO in the past year. - modified fitsio2.h so that the test for __D_FLOAT etc. is only made on Alpha VMS machines, to avoid syntax errors on some other platforms. - modified ffgthd so that it recognizes a floating point value that uses the 'd' or 'D' exponent character. - removed the range check in fftm2s that returned an error if 'decimals' was less than zero. A negative value is OK and is used to return only the date and not the time in the string. Version 2.031 - 31 Mar 1999 - moved the code that updates the NAXIS2 and PCOUNT keywords from ffchdu into the lower lever ffrdef routine. This ensures that other routines which call ffrdef will correctly update these 2 keywords if required. Otherwise, for instance, calling fits_write_checksum before closing the HDU could cause the NAXIS2 keyword (number of rows in the table) to not be updated. - fixed bug (introduced in version 2.030) when writing null values to a primary array or image extension. If trying to set more than 1 pixel to null at a time, then typically only 1 null would be written. Also fixed related bug when writing null values to rows in a table that are beyond the currently defined size of the table (the size of the table was not being expanded properly). - enhanced the extended filename parser to support '*' in image section specifiers, to mean use the whole range of the axis. myfile.fits[*,1:100] means use the whole range of the first axis and pixels 1 to 100 in the second axis. Also supports an increment, as in myfile.fits[*:2, *:2] to use just the odd numbered rows and columns. - modified fitscore.c to set the initial max size of the header, when first reading it, to the current size of the file, rather than to 2 x 10**9 to avoid rare cases where CFITSIO ends up writing a huge file to disk. - modified file_compress_open so that it will not allow a compressed FITS file to be opened with write access. Otherwise, a program could write to the temporary copy of the uncompressed file, but the modification would be lost when the program exits. Version 2.030 - 24 Feb 1999 - fixed bug in ffpclu when trying to write a null value to a row beyond the current size of the table (wouldn't append new rows like it should). - major new feature: enhanced the routines that read ASCII string columns in tables so that they can read any table column, including logical and numeric valued columns. The column values are returned as a formatted string. The format is determined by the TDISPn keyword if present, otherwise a default format based on the datatype of the column is used. - new routine: fits_get_col_display_width/ffgcdw returns the length of the formatted strings that will be returned by the routines that read table columns as strings. - major new feature: added support for specifying an 'image section' when opening an image: e.g, myfile.fits[1:512:2,2:512:2] to open a 256x256 pixel image consisting of the odd columns and the even numbered rows of the input image. - added supporting project files and instructions for building CFITSIO under Windows NT with the Microsoft Visual C++ compiler. - changed the variable 'template' to 'templt' in testprog.c since it conflicted with a reserved word on some compilers. - modified group.c to conditionally include sys/stat.h only on unix platforms - fixed bug in the ffiter iterator function that caused it to always pass 'firstn' = 1 to the work function when reading from the primary array or IMAGE extension. It worked correctly for tables. - fixed bug in the template header keyword parser (ffgthd) in cases where the input template line contains a logical valued keyword (T or F) without any following comment string. It was previously interpreting this as a string-valued keyword. - modified ffrhdu that reads and opens a new HDU, so that it ignores any leading blank characters in the XTENSION name, e.g., XTENSION= ' BINTABLE' will not cause any errors, even though this technically violates the FITS Standard. - modified ffgtbp that reads the required table keywords to make it more lenient and not exit with an error if the THEAP keyword in binary tables cannot be read as an integer. Now it will simply ignore this keyword if it cannot be read. - added test for 'WIN32' as well as '__WIN32__' in fitsio2.h, eval.l and eval_l.c in a preprocessor statement. - changed definition of strcasecmp and strncasecmp in fitsio2.h, eval.l and eval_l.c to conform to the function prototypes under the Alpha VMS v7.1 compiler. - corrected the long function names in longnam.h for the new WCS utility functions in wcssubs.c Version 2.029 - 11 Feb 1999 - fixed bug in the way NANs and underflows were being detected on VAX and Alpha VMS machines. - enhanced the filename parser to distinguish between a VMS-style directory name (e.g. disk:[directory]myfile.fits) and a CFITSIO filter specifier at the end of the name. - modified ffgthd to support the HIERARCH convention for keyword names that are longer than 8 characters or contain characters that would be illegal in standard FITS keyword names. - modified the include statements in grparser.c so that malloc.h and memory.h are only included on the few platforms that really need them. - modified the file_read routine in drvrfile.c to ignore the last record in the FITS file it it only contains a single character that is equal to 0, 10 or 32. Text editors sometimes append a character like this to the end of the file, so CFITSIO will ignore it and treat it as if it had reached the end of file. - minor modifications to fitsio.h to help support the ROOT environment. - installed new version of group.c and group.h; the main change is to support relative paths (e.g. "../filename") in the URLs - modified the histogramming routines so that it looks for the default preferred column axes in a keyword of the form CPREF = 'Xcol, Ycol' instead of separate keywords of the form CPREF1 = 'Xcol' CPREF2 = 'Ycol' - fixed bug so that if the binning spec is just a single integer, as in [bin 4] then this will be interpreted as meaning to make a 2D histogram using the preferred or default axes, with the integer taken as the binning factor in both axes. Version 2.028 - 27 Jan 1999 - if the TNULLn keyword value was outside the range of a 'I' or 'B' column, an overflow would occur when setting the short or char to the TNULLn value, leading to incorrect values being flagged as being undefined. This has been fixed so that CFITSIO will ignore TNULLn values that are beyond the range of the column data type. - changed a few instances of the string {"\0"} to {'\0'} in the file groups.c - installed new version of the grparser.c file from the ISDC - added new WCS support routines (in wcssub.c) which make it easier to call Doug Mink's WCSlib routines for converting between plate and sky coordinates. The CFITSIO routines themselves never call a WCSlib routine, so CFITSIO is not dependent on WCSlib. - modified ffopen so that if you use the extended filename syntax to both select rows in a table and then bin columns into a histogram, then CFITSIO will simply construct an array listing the good row numbers to be used when making the histogram, instead of making a whole new temporary FITS file containing the selected rows. - modified ffgphd which parses the primary array header keywords when opening a file, to not choke on minor format errors in optional keywords. Otherwise, this prevents CFITSIO from even opening the file. - changed a few more variable declarations in compress.c from global to static. Version 2.027 - 12 Jan 1999 - modified the usage of the output filename specifier so that it, a) gives the name of the binned image, if specified, else, b) gives the name of column filtered and/or row filtered table, if specified, else c) is the name for a local copy of the ftp or http file, else, d) is the name for the local uncompressed version of the compressed FITS file, else, e) the output filename is ignored. - fixed minor bug in ffcmps, when comparing 2 strings while using a '*' wild card character. - fixed bug in ftgthd that affected cases where the template string started with a minus sign and contained 2 tokens (to rename a keyword). - added support for the HIERARCH keyword convention for reading and writing keywords longer than 8 characters or that contain ASCII characters not allowed in normal FITS keywords. - modified the extended filename syntax to support opening images that are contained in a single cell of a binary table with syntax: filename.fits[extname; col_name(row_expression)] Version 2.026 - 23 Dec 1998 - modified the group parser to: a) support CFITSIO_INCLUDE_FILES environment variable, which can point to the location of template files, and, b) the FITS file parameter passed to the parser no longer has to point to an empty file. If there are already HDUs in the file, then the parser appends new HDUs to the end of the file. - make a small change to the drvrnet.c file to accommodate creating a static version of the CFITSIO library. - added 2 new routines to read consecutive bits as an unsigned integer from a Bit 'X' or Byte 'B' column (ffgcxui and ffgcxuk). - modified the logic for determining histogram boundaries in ffhisto to add one more bin by default, to catch values that are right on the upper boundary of the histogram, or are in the last partial bin. - modified cfitsio2.h to support the new Solaris 7 64-bit mode operating system. - Add utility routine, CFits2Unit, to the Fortran wrappers which searches the gFitsFiles array for a fptr, returning its element (Fortran unit number), or allocating a new element if one doesn't already exists... for C calling Fortran calling CFITSIO. - modified configure so that it does not use the compiler optimizer when using gcc 2.8.x on Linux - (re)added the fitsio.* documentation files that describe the Fortran-callable FITSIO interface to the C routines. - modified the lexical parser in eval_f.c to fix bug in null detections and bug in ffsrow when nrows = 0. - modified ffcalc so that it creates a TNULLn keyword if appropriate when a new column is created. Also fixed detection of OVERFLOWs so that it ignores null values. - added hyperbolic trig and rounding functions to the lexical parser in the eval* files. - improved error message that gets written when the group number is out of range when reading a 'random groups' array. - added description of shared memory, grouping, and template parsing error messages to ffgerr and to the User's Guide. Moved the error code definitions from drvsmem.h to fitsio.h. - modified grparser.c to compile correctly on Alpha/OSF machines - modified drvrnet.c to eliminate compiler warnings - Modified Makefile.in to include targets for building all the sample programs that are included with CFITSIO. Version 2.025 - 1 Dec 1998 - modified ffgphd and ffgtbp so that they ignores BLANK and TNULLn keywords that do not have a valid integer value. Also, any error while reading the BSCALE, BZERO, TSCALn, or TZEROn keywords will be ignored. Previously, CFITSIO would have simply refused to read an HDU that had such an invalid keyword. - modified the parser in eval_f.c to accept out of order times in GTIs - updated cfitsio_mac.sit.hqx to fix bad target parameters for Mac's speed test program - modified template parser in grparser.c to: 1) not write GRPNAME keyword twice, and 2) assign correct value for EXTVERS keyword. - fixed minor bugs in group.c; mainly would only affect users of the INTEGRAL Data Access Layer. - temporarily removed the prototype for ffiwcs from fitsio.h until full WCS support is added to CFITSIO in the near future. - modified the HTTP driver to send a User-Agent string: HEASARC/CFITSIO/ - declared local variables in compress.c as 'static' to avoid conflicts with other libraries. Version 2.024 - 9 Nov 1998 - added new function fits_url_type which returns the driver prefix string associated with a particular FITS file pointer. Version 2.023 - 1 Nov 1998 - first full release of CFITSIO 2.0 - slightly modified the way real keyword values are formatted, to ensure that it includes a decimal point. E.g., '1.0E-09' instead of '1E-09' - added new function to support template files when creating new FITS files. - support the TCROTn WCS keyword in tables, when reading the WCS keywords. - modified the iterator to support null values in logical columns in binary tables. - fixed bug in iterator to support null values in integer columns in ASCII tables. - changed the values for FLOATNULLVALUE and DOUBLENULLVALUE to make them less likely to duplicate actual values in the data. - fixed major bug when freeing memory in the iterator function. It caused mysterious crashes on a few platforms, but had no effect on most others. - added support for reading IRAF format image (.imh files) - added more error checking to return an error if the size of the FITS file exceeds the largest value of a long integer (2.1 GB on 32-bit platforms). - CFITSIO now will automatically insert space for additional table rows or add space to the data heap, if one writes beyond the current end of the table or heap. This prevents any HDUs which might follow the current HDU from being overwritten. It is thus no longer necessary to explicitly call fits_insert_rows before writing new rows of data to the FITS file. - CFITSIO now automatically keeps track of the number of rows that have been written to a FITS table, and updates the NAXIS2 keyword accordingly when the table is closed. It is no longer necessary for the application program to updated NAXIS2. - When reading from a FITS table, CFITSIO will now return an error if the application tries to read beyond the end of the table. - added 2 routines to get the number of rows or columns in a table. - improved the undocumented feature that allows a '20A' column to be read as though it were a '20B' column by fits_read_col_byt. - added overflow error checking when reading keywords. Previously, the returned value could be silently truncated to the maximum allowed value for that data type. Now an error status is returned whenever an overflow occurs. - added new set of routines dealing with hierarchical groups of files. These were provided by Don Jennings of the INTEGRAL Science Data Center. - added new URL parsing routines. - changed the calling sequence to ffghad (get HDU address) from ffghad(fitsfile *fptr, > long *headstart, long *dataend) to ffghad(fitsfile *fptr, > long *headstart, long datastart, long *dataend, int *status) - major modification to support opening the same FITS file more than once. Now one can open the same file multiple times and read and write simultaneously to different HDUs within the file. fits_open_file automatically detects if the file is already opened. - added the ability to clobber/overwrite an existing file with the same name when creating a new output file. Just precede the output file name with '!' (an exclamation mark) - changed the ffpdat routine which writes the DATE keyword to use the new 'YYYY-MM-DDThh:mm:ss' format. - added several new routines to create or parse the new date/time format string. - changed ifdef for DECFortran in f77_wrap.h and f77_wrap1.c: expanded to recognize Linux/Alpha - added new lexical parsing routines (from Peter Wilson): eval_l.c, eval_y.c, eval_f.c, eval_defs.h, and eval_tab.h. These are used when doing on-the-fly table row selections. - added new family of routines to support reading and writing 'unsigned int' data type values in keywords, images or tables. - restructured all the putcol and getcol routines to provide simpler and more robust support for machines which have sizeof(long) = 8. Defined a new datatype INT32BIT which is always 32 bits long (platform independent) and is used internally in CFITSIO when reading or writing BITPIX = 32 images or 'J' columns. This eliminated the need for specialize routines like ffswaplong, ffunswaplong, and ffpacklong. - overhauled cfileio.c (and other files) to use loadable drivers for doing data I/O to different devices. Now CFITSIO support network access to ftp:// and http:// files, and to shared memory files. - removed the ffsmem routine and replaced it with ffomem. This will only affect software that reads an existing file in core memory. (written there by some other process). - modified all the ffgkn[] routines (get an array of keywords) so that the 'nfound' parameter is = the number of keywords returned, not the highest index value on the returned keywords. This makes no difference if the starting index value to look for = 1. This change is not backward compatible with previous versions of CFITSIO, but is the way that FITSIO behaved. - added new error code = 1 for any application error external to CFITSIO. Also reports "unknown error status" if the value doesn't match a known CFITSIO error. Version 1.42 - 30 April 1998 (included in FTOOLS 4.1 release) - modified the routines which read a FITS float values into a float array, or read FITS double values into a double array, so that the array value is also explicitly set in addition to setting the array of flag values, if the FITS value is a NaN. This ensures that no NaN values get passed back to the calling program, which can cause serious problems on some platforms (OSF). - added calls to ffrdef at the beginning of the insert or delete rows or columns routines in editcol.c to make sure that CFITSIO has correctly initialized the HDU information. - added new routine ffdrws to delete a list of rows in a table - added ffcphd to copy the header keywords from one hdu to another - made the anynul parameter in the ffgcl* routines optional by first checking to see if the pointer is not null before initializing it. - modified ffbinit and ffainit to ignore minor format errors in header keywords so that cfitsio can at least move to an extension that contains illegal keywords. - modified all the ffgcl* routines to simply return without error if nelem = 0. - added check to ffclose to check the validity of the fitsfile pointer before closing it. This should prevent program crashes when someone tries to close the same file more than once. - replaced calls to strcmp and strncmp with macros FSTRCMP and FSTRNCMP in a few places to improve performance when reading header keywords (suggested by Mike Noble) Bug Fixes: - fixed typo in macro definition of error 504 in the file fitsio.h. - in ffopen, reserved space for 4 more characters in the input file name in case a '.zip' suffix needs to be added. - small changes to ffpclx to fix problems when writing bit (X) data columns beyond the current end of file. - fixed small bug in ffcrhd where a dummy pointer was not initialized - initialized the dummy variable in ffgcfe and ffgcfd which was causing crashes under OSF in some cases. - increased the length of the allocated string ffgkls by 2 to support the case of reading a numeric keyword as a string which doesn't have the enclosing quote characters. Version 1.4 - 6 Feb 1998 - major restructuring of the CFITSIO User's Guide - added the new 'iterator' function. The fortran wrapper is in f77_iter.c for now. - enhanced ffcrtb so that it writes a dummy primary array if none currently exists before appending the table. - removed the ffgcl routine and replaced it with ffgcvl - modified ffpcnl to just take a single input null value instead of an entire array of null value flags. - modified ffcmps and ffgnxk so that, for example, the string 'rate' is not considered a match to the string 'rate2', and 'rate*' is a match to the string 'rate'. - modified ffgrsz to also work with images, in which case it returns the optimum number of pixels to process at one time. - modified ffgthd to support null valued keywords - added a new source file 'f77_wrap.c' that includes all the Fortran77 wrapper routines for calling CFITSIO. This will eventually replace the Fortran FITSIO library. - added new routines: ffppn - generic write primary array with null values ffpprn - write null values to primary array ffuky - 'update' a keyword value, with any specified datatype. ffrprt - write out report of error status and error messages ffiter - apply a user function iteratively to all the rows of a table ffpkyc - write complex-valued keyword ffpkym - write double complex-valued keyword ffpkfc - write complex-valued keyword in fixed format ffpkfm - write double complex-valued keyword in fixed format ffgkyc - read complex-valued keyword ffgkym - read double complex-valued keyword ffmkyc - modify complex-valued keyword ffmkym - modify double complex-valued keyword ffmkfc - modify complex-valued keyword in fixed format ffmkfm - modify double complex-valued keyword in fixed format ffukyc - update complex-valued keyword ffukym - update double complex-valued keyword ffukfc - update complex-valued keyword in fixed format ffukfm - update double complex-valued keyword in fixed format ffikyc - insert complex-valued keyword ffikym - insert double complex-valued keyword ffikfc - insert complex-valued keyword in fixed format ffikfm - insert double complex-valued keyword in fixed format ffpktp - write or modify keywords using ASCII template file ffcpcl - copy a column from one table to another ffcpky - copy an indexed keyword from one HDU to another ffpcnl - write logical values, including nulls, to binary table ffpcns - write string values, including nulls, to table ffmnhd - move to HDU with given exttype, EXTNAME and EXTVERS values ffthdu - return the total number of HDUs in the file ffghdt - return the type of the CHDU ffflnm - return the name of the open FITS file ffflmd - return the mode of the file (READONLY or READWRITE) - modified ffmahd and ffmrhd (to move to a new extension) so that a null pointer may be given for the returned HDUTYPE argument. - worked around a bug in the Mac CWpro2 compiler by changing all the statements like "#if BYTESWAPPED == TRUE" to "if BYTESWAPPED". - modified ffitab (insert new ASCII table) to allow tables with zero number of columns - modified Makefile.in and configure to define the -Dg77Fortran CFLAGS variable on Linux platforms. This is needed to compile the new f77_wrap.c file (which includes cfortran.h) Bug Fixes: - fixed small bug in ffgrz (get optimum row size) which sometimes caused it to return slightly less than the maximum optimum size. This bug would have done no harm to application programs. - fixed bug in ffpclk and ffgclk to add an 'else' case if size of int is not equal to size of short or size of long. - added test to ffgkls to check if the input string is not null before allocating memory for it. Version 1.32 - 21 November 1997 (internal release only) - fixed bug in the memory deallocation (free) statements in the ffopen routine in the cfileio.c file. - modified ffgphd to tolerate minor violations of the FITS standard in the format of the XTENSION = 'IMAGE ' keyword when reading FITS files. Extra trailing spaces are now allowed in the keyword value. (FITS standard will be changed so that this is not a violation). Version 1.31 - 4 November 1997 (internal release only) Enhancements: - added support for directly reading compressed FITS files by copying the algorithms from the gzip program. This supports the Unix compress, gzip and pkzip algorithms. - modified ffiimg, ffitab, and ffibin (insert HDUs into a FITS file) so that if the inserted HDU is at the end of the FITS file, then it simply appends a new empty HDU and writes the required keywords. This allows space to be reserved for additional keywords in the header if desired. - added the ffchfl and ffcdfl routines to check the header and data fill values, for compatibility with the Fortran FITSIO library. - added the ffgsdt routine to return the system date for compatibility with the Fortran FITSIO library. - added a diagnostic error message (written to the error stack) if the routines that read data from image or column fail. - modified ffgclb so that it simply copies the bytes from an ASCII 'nA' or 'An' format column into the user's byte array. Previously, CFITSIO would return an error when trying to read an 'A' column with ffgclb. - modified ffpclb so that it simply copies the input array of bytes to an ASCII 'nA' or 'An' format column. Previously, CFITSIO would return an error when trying to write to an 'A' column with ffpclb. Bug Fixes: - ffgkls was allocating one too few bytes when reading continued string keyword values. - in testprog.c added code to properly free the memory that had been allocated for string arrays. - corrected typographical errors in the User's Guide. Version 1.30 - 11 September 1997 - major overhaul to support reading and writing FITS files in memory. The new routines fits_set_mem_buff and fits_write_mem_buff have been added to initialize and copy out the memory buffer, respectively. - added support for reading FITS files piped in on 'stdin' and piped out on 'stdout'. Just specify the file name as '-' when opening or creating the FITS file. - added support for 64-bit SGI IRIX machines. This required adding routines to pack and unpack 32-bit integers into 64-bit integers. - cleaned up the code that supports G_FLOAT and IEEE_FLOAT on Alpha VMS systems. Now, the type of float is determined at compile time, not run time. Bug Fixes: - replaced the malloc calls in the error message stack routines with a static fixed size array. The malloc's cause more problems than they solved, and were prone to cause memory leaks if users don't clear the error message stack when closing the FITS file. - when writing float or double keywords, test that the value is not a special IEEE value such as a NaN. Some compilers would write the string 'NaN' in this case into the output value string. - fixed bug in ffiblk, to ignore EOF status return if it is inserting blocks at the end of the file. - removed the 'l' from printf format string that is constructed in the ffcfmt routine. This 'l' is non-standard and causes problems with the Metrowerks compiler on a Mac. - the default null value in images was mistakenly being set equal to NO_NULL = 314, rather than NULL_UNDEFINED = 1234554321 in the ffgphd routine. - check status value in ffgkls to make sure the keyword exists before allocating memory for the value string. - fixed the support for writing and reading unsigned long integer keyword values in ffpky and ffgky by internally treating the values as doubles. This required changes to ffc2r and ffc2d as well. - added explicit cast to 'double' in one place in putcolb.c and 6 places in pubcolui.c, to get rid of warning messages issued by one compiler. - in ffbinit and ffainit, it is necessary to test that tfield > 0 before trying to allocate memory with calloc. Otherwise, some compilers return a null pointer which CFITSIO interprets to mean the memory allocation failed. - had to explicitly cast the null buffer pointer to a char pointer (cptr = (char *)buffer;) in 4 places in the buffers.c file to satisfy a picky C++ compiler. - changed the test for an ALPHA VMS system to see if '__VMS' is defined, rather than 'VMS'. The latter is not defined by at least one C++ compiler. - modified ffpcls so that it can write a null string to a variable length string column, without going into an infinite loop. - fixed bug in ffgcfl that caused the 'next' variable to be incremented twice. - fixed bug in ffgcpr that caused it write 2x the number of complex elements into the descriptor when writing to a complex or double complex variable length array column. - added call to ffrdef at the end of ffrsim to ensure that the internal structures are updated to correspond to the modified header keywords Version 1.25 - 7 July 1997 - improved the efficiency of the ffiblk routine, when inserting more than one block into the file. - fixed bug in ffwend that in rare instances caused the beginning of the following extension to be overwritten by blank fill. - added new routine to modify the size of an existing primary array or image extension: fits_resize_img/ffrsim. - added support for null-valued keywords, e.g., keywords that have no defined value. These keywords have an equal sign and space in columns 9-10, but have not value string. Example: KEYNAME = / null-valued keyword Support for this feature required the following changes: - modified ffpsvc to return a null value string without error - modified ffc2[ilrd] to return error VALUE_UNDEFINED in this case - modified ffgkn[sljed] to continue reading additional keywords even if one or more keywords have undefined values. - added 4 new routines: ffpkyu, ffikyu, ffmkyu, ffukyu to write, insert, modify, or update an undefined keyword - a new makefile.os2 file was added, for building CFITSIO on OS/2 systems. - modified ffgtkn so that if it finds an unexpected keyword name, the returned error status = BAD_ORDER instead of NOT_POS_INT. - added 2 new routines, fits_write_key_unit/ffpunt and fits_read_key_unit/ffgunt to write/read the physical units of a keyword value. These routines use a local FITS convention for storing the units in square brackets following the '/' comment field separator, as in: VELOCITY= 12 / [km/s] orbit speed The testprog.c program was modified to test these new routines. - in the test of Alpha OSF/1 machines in fitsio2.h, change 'defined(unix)' to 'defined(__unix__)' which appears to be a more robust test. - remove test for linux environment variable from fitsio2.h Version 1.24 - 2 May 1997 - fixed bug in ffpbyt that incorrectly computed the current location in the FITS file when writing > 10000 bytes. - changed the datatype of the 'nbytes' parameter in ffpbyt from 'int' to 'long'. Made corresponding datatype change to some internal variables in ffshft. - changed '(unsigned short *)' to '(short *)' in getcolui.c, and changed '(unsigned long *)' to '(long *)' in getcoluj.c, to work around problem with the VAX/VMS cc compiler. Version 1.23 - 24 April 1997 - modified ffcins and ffdins (in editcol.c) to simply return without error if there are no (zero) rows in the table. Version 1.22 - 18 April 1997 - fixed bug in ffgcpr that caused it to think that all values were undefined in ASCII tables columns that have TNULLn = ' ' (i.e., the TNULLn keyword value is a string of blanks. - fixed bug in the ffgcl[bdeijk,ui,uj] family of routines when parsing a numeric value in an ASCII table. The returned values would have the decimal place shifted to the left if the table field contained an explicit decimal point followed by blanks. Example: in an F5.2 column, the value '16. ' would be returned as 0.16. If the trailing zeros were present, then cfitsio returned the correct value (e.g., '16.00' returns 16.). - fixed another bug in the ffgcl[bdeijk,ui,uj] family of routines that caused them to misread values in an ASCII table in rows following an undefined value when all the values were read at once in a single call to the routine. Version 1.21 - 26 March 1997 - added general support for reading and writing unsigned integer keywords, images, and binary table column values. - fixed bug in the way the column number was used in ffgsve and similar routines. This bug caused cfitsio to read (colnum - 1) rather than the desired column. - fixed a bug in ftgkls that prevented it from reading more than one continuation line of a long string keyword value. - fixed the definition of fits_write_longwarn in longnam.h Version 1.20 - 29 Jan 1997 - when creating a binary table with variable length vector columns, if the calling routine does not specify a value for the maximum length of the vector (e.g., TFORMn = '1PE(400)') then cfitsio will automatically calculate the maximum value and append it to the TFORM value when the binary table is first closed. - added the set of routines to do coordinate system transformations - added support for wildcards ('*', '?', and '#') in the input keyword name when reading, modifying, or deleting keywords. - added new general keyword reading routine, ffgnxk, to return the next keyword whose name matches a list of template names, but does not match any names on a second template list. - modified ftgrec so that it simply moves to the beginning of the header if the input keyword number = 0 - added check in ffdelt to make sure the input fits file pointer is not already null - added check in ffcopy to make sure the output HDU does not already contain any keywords (it must be empty). - modified ffgcls so that it does not test if each string column value equals the null string value if the null string value is longer than the width of the column. - fixed bug in ftgtdm that caused it to fail if the TDIMn keyword did not exist in the FITS file - modified testprog.c to include tests of keyword wildcards and the WCS coordinate transformation routines. - added a test for 'EMX' in fitsio2.h so that cfitsio builds correctly on a PC running OS/2. Version 1.11 - 04 Dec 1996 - modified the testprog.c program that is included with the distribution, so that the output FITS file is identical to that produced by the Fortran FITSIO test program. - changed all instances of the 'extname' variable to 'extnm' to avoid a conflict with the -Dextname switch in cfortran.h on HP machines. - in all the routines like ffi4fi1, which convert an array of values to integers just prior to writing them to the FITS file, the integer value is now rounded to the nearest integer rather than truncated. (ffi4fi1, ffi4fi2, ffi4fi4, etc) - changed ffgcfl (and hence ffgcl) so that the input value of the logical array element is not changed if the corresponding FITS value is undefined. - in ffgacl, the returned value of TBCOL was off by 1 (too small) - fixed the comment of EXTNAME keyword to read 'binary table' instead of 'ASCII table' in the header of binary tables. Version 1.101 - 17 Nov 1996 - Made major I/O efficiency improvements by adding internal buffers rather than directly reading or writing to disk. Access to columns in binary tables is now 50 - 150 times faster. Access to FITS image is also slightly faster. - made significant speed improvements when reading numerical data in FITS ASCII tables by writing my own number parsing routines rather than using the sscanf C library routine. This change requires that the -lm argument now be included when linking a program that calls cfitsio (under UNIX). - regrouped the source files into logically related sets of routines. The Makefile now runs much faster since every single routine is not split into a separate file. - now use the memcpy function, rather than a 'for' loop in several places for added efficiency - redesigned the low-level binary table read and write routines (ffpbytoff and ffgbytoff) for greater efficiency. - added a new error status: 103 = too many open FITS files. - added a 'extern "C"' statement around the function prototypes in fitsio.h, to support use of cfitsio by C++ compilers. - fixed routines for writing or reading fixed-length substrings within a binary table ASCII column, with TFORM values of of the form 'rAw' where 'r' is the total width of the ASCII column and 'w' is the width of a substring within the column. - no longer automatically rewrite the END card and following fill values if they are already correct. - all the 'get keyword value and comment' routines have been changed so that the comment is not returned if the input pointer is NULL. - added new routine to return the optimum number of tables rows that should be read or written at one time for optimum efficiency. - modified the way numerical values in ASCII tables are parsed so that embedded spaces in the value are ignored, and implicit decimal points are now supported. (e.g, the string '123E 12' in a 'E10.2' format column will be interpreted as 1.23 * 10**12). - modified ffpcl and ffgcl to support binary table columns of all datatype (added logical, bit, complex, and double complex) - when writing numerical data to ASCII table columns, the ffpcl_ routines now return an overflow error if a value is too large to be expressed in the column format. - closed small memory leak in ffpcls. - initialized the 'incre' variable in ffgcpr to eliminate compiler warning. Version 1.04 - 17 Sept 1996 - added README.MacOS and cfitsio_mac.sit.hqx to the distribution to support the Mac platforms. - fixed bug in ffpdfl that caused an EOF error (107) when a program creates a new extension that is an exact multiple of 2880 bytes long, AND the program does not write a value to the last element in the table or image. - fixed bug in all the ffgsf* and ffgcv* routines which caused core dumps when reading null values in a table. Version 1.03 - 20 August 1996 - added full support for reading and writing the C 'int' data type. This was a problem on Alpha/OSF where short, int, and long datatypes are 2, 4, and 8 bytes long, respectively. - cleaned up the code in the byte-swapping routines. - renamed the file 'longname.h' to 'longnam.h' to avoid conflict with a file with the same name in another unrelated package. Version 1.02 - 15 August 1996 - ffgtbp was not correctly reading the THEAP keyword, hence would not correctly read variable length data in binary tables if the heap was not at the default starting location (i.e., starting immediately after the fixed length table). - now force the cbuff variable in ffpcl_ and ffgcl_ to be aligned on a double word boundary. Non-alignment can cause program to crash on some systems. Version 1.01 - 12 August 1996 - initial public release cfitsio-4.3.1/docs/fitsio.pdf0000644000225700000360000236464314456514035015416 0ustar cagordonlhea%PDF-1.4 %Çì¢ 5 0 obj <> stream xœ}TÉŽ1 ½÷WÔD¢BlÇYŽì‹„€¡á‚8ÀÌ0 1ìü?ÏIuuµ@¨T]îØy~¶_ò}ЦhÏò=¿ÞÝ:+ÓÕÏ]œ®vßwÔÓò9¿žîìP'N¡ÔBÓþÃnl¤‰ŠáI¥k½{ãxÀÖÈ)»Ç~ØEÜÞϸFÊî%ü©Æ¬«? »g0 Jâ^Y¬Ö¨Åý4Sš`õÒÏÀ-QZq?Ìn”[s7,"×Õ‚¥D°©î¡Ÿ)´¤0Ó}:Æ^ôUΜÀ$•ßîŸô:©&MVçœcÈÓ¬"ØOû TxÛ•€ÿ(Æ&I ‰VóýÑüaL¢Òíé »6¡¿Ì¤‹±£ »/Ûب‰Ö DÖª˜[Ið³M,‡Íx,”C%rH)¹ºžBJ¥‰{ç‰ögwnîZ°Úñ æ‚No ¾ŽÕ(³äÐjlºÍ¿¨ÄT¬x)5ìyà›`fÀUÆ&‡ÚSÃô® HYÛBDbOiÛ5¥Mž¥ Q«û|4—ê$SŸr ¢Ô§U%T›Ë,xLgÔŒM§Llb ùÿÃT™O±Y=¶ïËj)äž#d®ºÜ ^-¯ÿ€²Œ¦¤õ»T™ÑMüiÁ·Îp*)A™MŸEB’V¡Ð”Z=xí+Õ®‹ˆ$Ðì$’/  Õm3aÔSЈfEFƒÒÒºŽ‘rX\(1îŠÐbëWÏ4£ê y°y„d­U¨ý~?—ݼ½.BFÙyìbÉî.ð :a’‘pÒ­gÞÞç:¢/ À´ŒsÑ õ쵿ìÕ@æTÑ?´ÆPTѬŽòÐ ¶ý…ÔÞù>U»):àøvðžû>1ÁÍI‡„[­ºet•1~u=›;õ³* Òªþ—¾ŸäŒMd×ÀBÆ–-¯§bieð·êWÞÞ¥?ªÅ.i£s›ý¦ñ­½IOW¾÷3ì°Ž¹ˆ·,/¦ØGºeñê¯ñýK3ìÜåÙ-<Á>âŒç·Ý(¹ÑZ†&CûP&¯z‹«µ¬ÕSÝÝßï^àùã÷jendstream endobj 6 0 obj 791 endobj 17 0 obj <> stream xœ+T0Ð3T0A(œË¥d®^Ìe ÎUÈe–T€Rɹ N!@†F@=KKC…4.ˆNCs#sc=#…\®hLM#Ž ñâr á BÞ*“endstream endobj 18 0 obj 92 endobj 22 0 obj <> stream xœíZ[w7~wÿÄ>®zÎ.º®¤G  ÐC[ ¦}€>„‚ÄBÚ¦¿¾3#i%¯×&†“à ^¯´£Ë|úæ›Y¿¯x+*ŽÿâçáÉäÖc[ŸNxu5Kísó)kd«<<ò×ôg[j˜Më¹§Á-\ ï«éÃÉôÇgµ`—p ž{À öŽW¬Q¼å¼3õÑÙ!3áölÁܺ¢}݉Öv°žéÑÍI°å\‡MMlkÌ,´KX£âúàr»ú¬EÔ0ãh}~ £â]WïÃe˜Õ¯žÐåo¬14„®o1¬`Ç0§Ô;Î"?Ó­ÎU•s½õXÈr›­M«uÕ¼Ÿ¾©[&qׇ碾Ãt}†“˜Áý·ðw”¾Ìñ—£:èˆÛ§ê×xÖ¬¤¡=ˆ+ÇÎ/h7`m°&\œÃ-å ›„1 ½áÃpE®½ÜØïê;lݧœi…wɵ—KhÚj…!è&ƒäKþ—ÙÿSæÀ–3ܪéì‘£–Ü ´…/ö*0PJ0ø¢[}ƒ@D7†ˆFP½3‰Þ ÁÑÁ#ìF^€ãänôûIÏg§Ø_ÐÌþ!~d¯Ðø@Î&Æ{€Q.!"jì©qð¢ QkhÝŽ»òzF¶k;ëÇpELØ„‰h{œ%tÆÄ=¦ˆððo¦òvé àc|ö(wÚ6:îG°°‹ý`a2,öþ (ûú]Fª Ê^€0¼Æ)è›± #$A ‚þÚ@’ã]t|zfE; ÎÒq4câ¬Ñz5³ÿ%†`bà$ÚGährD@`rM})a¯ìÑÂ"ªt¯–”{W"‰E]Bz*\LÝS†ÉË®©6ÔäŽÃ‚`|kÍ\û0$Hô©}mœ+Ô€+ YFœþË‘X(">%m}?†nôæQp³ÆîJ üÛ ’€6€—õÓžBæ‰r‚UŒõõó:=BSºßwF“O¡ïsË4DËß:!¬u®‹ÏGƒãdP$ðt* ÏçB2xÑPf÷tÞ hü ßJʹଠCz#Í®c„Ô—­kµOC =>~øÍ– °Ï<ù»Ë@H¤ó»‚-£·–¼×©ì»@ìAJ|DxÚ2ŃN¬_(I+Å÷YÖ%pt®•Kºpû0ˆCŒG„"s_ãWb‰ÃØ–`1_*õzJá¶'ñoâÂ&B¹H/`´Ž·Ü €›Uà"eAã/×ñÕ<*ÒHÊ'ÿ`ž÷P9K; x}0Öæ{™p>1á\šš fa9·Ð%•—±Ì\$9iU9 2xì FÌåͶJG^éVÉ‹žøÏ (âLÆ1á3&z—ҾϢö{1Luݤ}ì«ÁK<Ñÿb@u`—{Ê03Ö¨LˆU—óPóƒÌ#ÉŒ(#R4J4ƒ0š±ÁW‘ŸR^z'>3OihÿZÁš_x§eõ ”׹‘œã2Ï]ë.[rûr`HÞ8Íñ(ªQ:ô‹ãOŠ¡ø‹ü¦´bW¿Bu˜©5^{åÄ <I´æÉÉç饂të9ƾ;|e#_¦P s)÷…t»Ènÿ6ùuÚíyRzô ûeÊ\G¯ÔÚ’#"¡¢uú]É (ô¶/\1Zª#Äæ§i&Wý †•ÅüY|¹y¬£vñ}5nõIù|ëce™!AD¿@–,$"xÐÇß» ŠÐèA ÃT@æL Ü Åö‘²r©$ŠÈ~9#–‹Ô±à¢h.ýôHýE?Øy¨k"ÿ\áçÖ~^¾ (À­üd.ù9ñ!@tU#m H‰„1‹ñx^oìM'¿Ã¿ÿ 0{tendstream endobj 23 0 obj 1907 endobj 29 0 obj <> stream xœí[KsÜD¾»ø{”R4ïnŠCb'&E¼Øyñëéîyj¥ÝÕZÞØ¦R®ò®3#õ×_¿¦÷ŸEײE‡áóøìàΡYœžt‹Óƒ]\„ã³ÅWGpãp¦uc‹£~$[¾0B¶_ü^½¬yõ®nØGßÃÁÊ!²ÓmgaÔÑ ÜùuÝÀ°ŽI]ýT7¢uN;W=‚ñGùʽºáñ\¼åIÝÀ<ç~þc5BËVÛE#ºÖ0çüZ²VU ³0øäé{£µ‚9ÍX½õÓ²ÎVã1ü¶uV‹ê5 yS7ªº€sLW/à#žBÁ([ý/ “YéèÊ2>du ÷p¸‡I¿ÎE-pægDyÞû¡z^Ëê#L\½¯¹ÃÓųœøµ5Õ¯µëª§pá̆ïAÏóµpÎvôœðUu‚^¾JÿQœÿºñ¾ÁEF€Rhã"Ús¦¹è„ P\¬‰«5̵b#ì<Ã~I”ôïi p“ˆIâ =Äp ©ê~-²uÓ¡l·$ëz‘ýµO#²ªÊ ÿ‰Óšk‚6 j1+èa‡o!èᾂUâ(Ršç#®‚¤± 8«8]y†· †å0†áÅI`v®å²Àr?z³höO‚8óõ ‹ ò.<ú% %š!Mà0Û20EC_‰tnÇ$¤:Ú¶ZØ©º³»ˆ°‡Y¶ó[f迃ÃHEò"‡ˆ?Rþ°F*¡  ‚»‡¨ùco½¹FÀø2©Œ§K „>Øz¡,qM…¿Øs!ãø i’d&N¢Ý&…}G³‹ò>ªãHö3xe<´É8æË3)€]»!¶3œÜ®c1°WaHbû ðwöÌÁþž¡Æ/ÿ–öï”$al¸Å9’dɵâs Ý·©ÖQ\(½Ò¼ûå@ò0”yKIÒ|œqE@ùqqã踖«Þ¸ø:tÿˆ<<Ï“‚8ôB‚Ÿ¿Jn‚”Åd ÷aÖåЬÓ[ £6t}Öq-À¡vZU!KN#7á"¨‹$‹î—,|‘¹’ˆu–ˆü´tßåuõ%¼Ž´ÁÔäàOX`*)^ï'í¢U1Àõ?Ȫ€A0÷QF_“kÇ7 ª$:vY}dàð„#XWxÃ;i và°뺭ž6¨~ѵ,d“Ø^7BG6ØÐk8é†(BåË"ÒÝ”PèæxÖKLBj X«œÊ/‰¶òhß9¨{‰˜#%¦LLè.h€ÕÂø *z@¼+é"‡ñM\­0nzë`i VL;U¼ß¥â½Â"(#뵂}™–õ³jćY,·|6j{rdv½#Óàæ›PúÑYÆZšÐd¼RMÒZäÍÒ†HoTÈé©§{"½ zösøœù`I-]#¦Ó aæÞŽ\¿P(þÆÅ¼6ÃK[sÀÇŠ9ï%3WBrYn—…%Æ-¼œ`ῠŤpÂú …4Ã0'D·3,¶P>_¾|½Ä$ûÈieY§:Ш‘—…›gXs[±ŽµêHq_”µ˜Âe÷<}ضx\ \DÈUWßÛƒ+·ZBþ4¯2¢5­s£ €´o3ÙáH†=(¡„\±ÿ¿ÕŽç}Ñ¢ä ìÈ®w©yÿ:ÔtOB7,“íô&Eœ§†Ú=>}žu=¨¯¡½È°,a­tp7º39'Rç×»íö|»Ï7@'1õl ÚÃp¢3ïÄ8¶2c›6¿‚É>ñ{jsâ¾\ñ©pfW·³ys&™×ÿ€°™‘þ‡5ÌUÛõ.í3À4Týà7•ýñw§ÊRÞ0|³;Öá‡un2Ì;C„Z°ûKø Í] Ò3×ÞuÿôvÀ<ŸÁn:ƒMÆë*EjŠŽ¢9ì'"tá…ÿ˜Î§®*7†&Q×fhc9%tb†,)«ìz`¯Þí:åvݾÏã­*K%ëkdjëfAs®!àE¿†]§Ñ7ÛÑ*ø/)ë‰WVjj©_P2ÝKŸ?Ä8ë°Âw*å|;u ô öšeè&2ØÓtÙ²ìn˜ÇTˆOŠçåI=ÌÃÂãœÖÊcS×Gê_ê5g F.wC:¶#5WlZíaDçnM틚U߯S÷¨o†nï9])·”x‰a o¦±nËùvSÞ¾æ} ž¶tý#ŒÜL@a$ÁPMùJÐÇeø•û¦¦±Ú×úæ}ÔöÚþô©¢¬¿jü¸s›k°»8Ýëƒ\§îDîa´b†5ÐÔb,8Q{™Ua5±Ž½Æ¡¤5±·»˜ç0Ío~ÜÏíÝu×26c›sp˜pÜŠGŒ‹'mb¾Ænb"ï{„|us“y:®lnnçéÝäÊ1o ïýÊä’‰˜žô›žO wüEsW¾§¥ÊḬ́Ä>ÅMjËLió…к…~œžœ{‹Œ‚îXª¼‰Xš…2Z&ô¨Â¥Í0xºiD¼NÁîiÊx=BsèxÇx™3¢,·ÂÆœñ†­‹rÇxØÞ¸>yæßÒìwS²®]™ŽHëœUß;:øþþøá5'endstream endobj 30 0 obj 2393 endobj 36 0 obj <> stream xœí[YwÓF~Ïéð£ô`¡Ùgú ….´Ó—ž>Ð’œ',…òï{ïU–lˉ84',K£ÑŒ¾»|wñ»IÛ°I‹áóèüàÁs39ùpÐNNÞ0º8 G瓇3 œi\ëØdöæÀßÉ&†OŒMË'³óƒ?ªGõTV¿àÏj^Íðà°žòüíE=ÕMÛ²Öþ9ûfe¼œUjÞp ÏŽa²Oõ”ÁX®qèTJÕ8>™Š¶1Ì9?Dתj`n C[îš–UÏá°º¨…iœ¬ú\O…”³šž]½®eõîÀÏ#ø÷±Õ|¿€™æ0VYx¤­^ù¯º:†sžlß^ÀûñÞp~Á“0nŒÑLïq&ƒßq=°Ag·téÿ8ÏwÀóñŒ3ôH×÷w% ìpªZûY~(¯|q³I ¡XÃ…‹8í`Mᢂ –µ"ˆž2×HálW\‚ª„úJaÄÚc8: ¼€‹»Ñ<…¸A¥[H:0¿† 8 aA°¾ Ü!b¶tå@Y£q¸Âý`’œ¿ØôÄ(¹ðNÂ`Û›–Â4\ðî-ÊÓ8PQüJ‰F§ÄŸÁg ³ =jMõ8 íE¬YøiFס½¹ø; È= 7‘q ÷!zc³§·[y%{c †/’¼hÛpãÆ Ì&‚`¢ „G [”¯Ý¨ê»ZF½-¥ cß9ø'½ƒBèõ¬äàIZ&«—5” ¾$ Ö¤Çh„×´øF£ÓÓ·ä]; Jž Ã÷$ 2¾úhH—£kPm\ô Ž0_Ç h#H¨¾*ƒp+ÔÀy xðxcÁ$A"L£H„€ùŰí¢.çPÕEuŠÚm5ñ½GÎã¤÷OÑРO¥ÚùÓ=·?ñþ•gS”+&‘=„û‘ÿ—uVÁ¤YHÄüˆìP}v‘ÌÉœ^žTªIìפ‹éÈó`„Û‰Û¼³C\Ý¿5+–9?¦´t´ØÕÙ[Ü»‘ôRŸá.h+çµ7yøR@:_|ïóZÐFüFq\d8ð”«v媉þlvÓÚóm“¾&"G±Ä'\ØD•õcÒ*<ßy·WúpGÔvÛ“L®LÙ¾ÉGµ5Ym§q`—ÑEAàYºlNF§ 2AÄû¥£<òòÚŠøöûEÝ<¯ç$h½fØ!BaÉGonØn³Ä:ðÂJ0L‹Ò ‰ä‘‡ˆxf471¾ ®™Â7ŒÈžÔѢ͂ٗկHüð˯SV¡é™C ðù¸¯0Qhµ˜ù®Ë(zè>át…I"¯Ób@É×:îØa–Õ`óm(Ù©§c¡&[1ºh¯CA± §mßÄÄO°DÊ[žŽ%R<Í+;NB„F¬/°¯[œ0•¢AZ±e®ŽpŠxxD—«/.vøI­JЗ7‰¦».é† Š3ŠÚﱞ{ånÆ–ùM`O¹»0áj=—;‡=XòNÆ/Ýç6ÚHÞ³¼eÛ¾©ècîgYÆîü§ºIÛ~ÓzÝä,G{,Æ£/«o1Ucï±Ök'°0³D¿Efòƒ?¥,kLÉYÝcøóœZ‰î—ì«U{ò^¿U_ÅÙí(ήS ×f×Su¹Ñi3TõËT!m6”’YÌß Cæ¡”<÷9æó£Ð ÒcU†„Jë’8å<Ü œg¸'SÁT僽– Žd↩„Oñ<îå‡a‘Öš`D‰6y3y6[fZýs‡µ\e˜gµÙX`—ô¢hêM€]U²)a/óòØc*?–j;ì}9nd_üÏê2Ãêq*' `«¹/êݰz{pQ× hkawTO‹°û§ ã®3îO}1…¯‰vf*³DC?­E¬Ãª,)¾Bûøz,Ú‹¢›5Kô8ŠœúÑ„ûàÛ´|¯Ì±ÆxcøZß)î~ ÃVÝdØŸÀW,µ½DœùóŸPˆh—/¿ƒ›Ô¹1ã ¸).H}ÿ_^œ$ÃèF›í”Yz‡¹‡UÝn¢ê©ãf ÓF _uÝ«·|ç„a­ ¥…°{ —[. ,Òºpû°p›ÙýÈR¥užE˜É-8—±,:ßN{ML®*‡NÜÝKÆÍe&zq’{Gè òOÞ~^±~ÛÝuèå¢(üsMò&E§U+Ž#']¨®åÆ2‡ëÅçØôÄFÇç» ²ì¿Z䇶›úòNÌ’çÇTOi(¨º*6®µ_5;¸¹ Àèë^—MýT›ÓÚT#»mr弿ÆkxBÇA0.­¤ŠÜ=Øx*«®Oët ÷¬RøT¡‹? *úÑGö ÿ\‹œô‹M–24 Üâ[Ü7œv8IdƒÒtJ¶Âg#€8j˜ô• ‹ úïµk;\¿ìƒ3Þ£èüsÿS삤6gÌÌ­H­ßýÒ'8p¿f ,_BÍRÖÞ^¯ß²kÒ;4:D‹}œi«»i)\ð–§è³´Oµ¯ûˆä$°øónLñêøù‹Ž2jetîjÐ:­ëæmoÌÆ•ð§Z¼_ÍzEWýÈÇÊâÌâ/+°Jïœ ¢‚¡`ïW6lc,µÜ³|Á–'‰‰}å¶³•«"¯Üj Ÿ²ºsú•CRùe!›Ÿt[uy¿íòþQa¼P’ª±÷¦¾+ÞïøÞê|ÓI笟ûŸMD Gš7/Kgó“\l‰Ž^x6÷$ôÊÇŸ\å_ÅĈ=Q†â°g¹ÁJ\5Œ–ÿö¼åè½”€¥}òªõ-ØPÎ[áWé°£º ~œ’j\ûfrl¿|›ß}»xL¾ÄÎrd÷œø¦t Óqï,©>t+Åᇳƒßàï? ¹Üendstream endobj 37 0 obj 2215 endobj 41 0 obj <> stream xœÕWYo1~_ñ#öÑFòÖ÷ñÈÑJ@ÅÑ,Oˆ‡’´U¥$¥ )ðï™{³IŽÒBSE›õîœö÷íx|YËFÕå>œT{G¡>›W²>«.+Eº܆“úi JÛ&ɤêö´Ê–ªºÆ6R×í¤úÀ®¸PìœëíK01jÕÄJßÈVí4ŸqfRYÏÞpaš”|Jì5׬í%û\èî]§2àüH]b¬§%LLMðµ0² *¥+qÇð¢ ;©S#{Î-;ë 7ìÄ3Ã…ïFÌ£–ƒ¸âF—°Ï9¾’‘ М€Ì0²ìÂ@²Ñ&r;í^êHÏxR8pì̸pè]£YôÅ©póNâÜ m¾­¼ùSáÎ8AØŒ©ã­r*Bk"àëè2ÜaÑ…*5z º§Âx\F#¢!à¾"=B9Rà[!8 Ùê K†§ðh‘»½‚ŒÈà;|åÊšmò8ç"J öúNÖ`Ç‘ß$Að_#ÁÝ o;ô‹Dß\«¦'ÀÍ>r à·J $¡HHαZ¡‹ªyRÃ:ƒt!” sÑAç™HWÜd+0Oºå*? 2ü‡2à~_lÏ‚R‘ƒ_«È(Äx ONªÅܸr9˜rr9X2õ¡¶˜`Ñï¿íaÐâº%ºF¥¸½TÜ”¾£Eqº…®§µ Äú»XùØ}r^¼ÿ%ÚÍ÷ë!¶€¬rñz}ÙF‡Ny ü¨ À/vÛ—_Jy€ž`G—æ x/4Ø;Òví@a¡¿³!Ò‰B-»¥]È&Ç,&\1¼Ž©\@•7 ‹…¡ž0æ^€dãq®òxº8@ú¼ÀNÏ7l@C< EÉÞèÌ ØL )‰§b–½ƒZLŸfB.Cîhç)‹O³ Þ.dx>ì`¢Ò «Œñ&Ö©õ£D#X,*ÅÝ2Ví㼪_èŠn`±,ýúÐy.ålWòÆqÃÃ>Iåw¦ç9?\¼éœ—)ŽpôŒ}~z9 «™Š¢OÈiizätŸðO!À ¤(ôs3L†²ul@éÑÄh´˜ã{ÚÆñP‹íƒ€ZA­áh}õ¯fa6Feûmõ~?D&ªendstream endobj 42 0 obj 870 endobj 46 0 obj <> stream xœµ[]sݶ}×dúôÖËŽ/M ä-qíÖ4™&ê¤3IÉ–ÝX²âXv”__ì'$¯¤LÚÉ8–Hâk÷àìÙüÓñÐÇüÇŸ]=þz>¾øùh8¾8úéhÄ—Çü×Ùåñç'åƒtì†>FO^QÃñxvÇѹ>Ÿ\}·{ÒíÇ~ˆ!¥Ý«nïzçFïw§ÝÐiŠÑ»k~œÝî}7öÁå˜w/ÊOÙqÞ½ëö~ž{W:¡/ïÓèþ}ò7>ôsšG~šúàs:>ùâèäOßíž—fý˜æ!î®:—ûÉ%ý»”=t:ôyŒ9ïÞ–áS]p»ó2«Æ1äÝ þ8Ä)îÎJ#?yïjó×0嘆a*͡ãÇ\Æ‘64½Ñ{õyÈ4¿Üqp2¿“nÀ"±tæv?—ÙÆÐçÒ÷9<£I à Ç2›òìV4 ãXŒ`Qs™ÐÞ'GMàaéÆaƒ²¾ ;þ¾èsŠ^>ðq*½¤ÒÖÓø/ÀÀÃîY—‹£ÊìËàuP>¡ñ·Óòø ìå1ŒOß”àü\Œå­£'¥ï0z†..Í [z©bï0(>×AaúW2Áb=˜ôëLëæÜûXÀvr^V,Ë“«M_ˆ ^ªÍ`n0_è,›OÑðm 3tê‘y‚ @ëLÁIÓèÊ|ý\~,nÿ€y²øZÍ3,>À!ÂCŸ ⇌Cmö}JV—þߣWà4 ,$DàM‹I_ic ̳gûì‹å§ ¶Ä9mÄPœìag8‚ß7°vüõ+ º'g2rbu<þp “˜¥ßïJOÃ06zÐç#|– ȾƒæÅv QuEã¾+híØéŸú³Npôey!kði¦%~ßI7=´!ð­w[šËj};3Xª`Ë_Â^'{_ V®†~,´¢0„žÞÒ¡‰Ó¾$ÿÈ~žô˨¸Ñ×fŒ ÂuN²Íá±qþÛjÞmD ä ÁU¸Ëgh ˜' ~£ ôÅ+E@!‡Á‚ÿI¦su·ý‘ž„âü¿xÜ´È`–"BÈAŸhó‘ÒÄê1Œ;žËD˜8DYñÔ‡H#KzÓ-ã‡, £á &Ã-YB¹ÑýÑr [#8_lÕ]+b$¶K€ÙB”^°²T±yî=,Èý "‚ƒnfÓæªÒÕùšM,!¹nª»ÒˆùÿÒØ€4Šæ`ˆ;))1ù—Ý>…D[L3cæ°øè² êªsãCÂH8NÒ¥ñw,ÜáÛìñfwsw Øæó R8õux3}ª‚pÅöòðy…üIõP¦¼úŠØl†Í4ØCèŠY¢‡éø>§NdõÔ ìáGƦ¨í VÜML)ebž—`ö¢›L«-ýaã"/±¥±f¥eû¡*HÀëŠ[œ‹ß-Á…“ÄX§8Ô_{ï&äBn!]•‹wî°{\º8Þ™6Õ+a ¯ ò&Â9̘…’ç©(įd_ìWú¬!’@OcðÇͦjcZ0ߣ8b@ ›pŽÕE‡D#qéT$ú(€Võ<ÎŒì#)u=ÌÁˆ¹á9d˜Ì‹s~QöÄǺ㠒âį{EÚ²dLÑ¡Æ î?í>ÙFºÄ¹’•1£’ZÔ‹¦Ú²£g+0ÂÁ¨ýà-»û¥ŒX=鼧 ·DK;¶ô5—~“'”µùî kN\&gó‘¢D˜¿ ÙÞ£áÅ"ËŠbåf²§ÎH÷üCbt–!$4ÒsÆZîgåN˜¦Gµ§’1µ$L¸Já’x†ËLt*ZòkÌZsÉSQÁ@ô´´’Ù¾¬SÅ€cóC(–43—€[¼mø”áƒKks‰OªŸqW…@BÔriÑâW?“#aG/z­A?”ÝõÁ»ÀS$‚|ýÎt‰˜@"‡ÆÿAÃ[š"²JByù¡óFîÓO7!"m®•Þ%Ê]œ–Hµ°¥^¶ÄÔéã·¬i·r–wÅÊn¬@RD¢>¥¿Ú„³É7 }¼viC“E@Ê7ü& …byHJ1DZ½,«¥ uNV²£‡Å‚cntš‹«Ìÿp"âôÄ#ªhÊê8œØœ¾IZ DJ‚XÛUî…¼:³§¥‡m}+ÈÃd«/–ÒxÚ쳩¬àœ²kä”ÓL¢AÒ=‘yßoEÑâÖúStœ‰<-Q°¿„ýîm$rg]_µQZrÈPe#3Ù 1¯¹€õ¦V ÐZè0@Μñ!oq) ^zÛq–úžÛ¼?¸l¬z%Ô pΤené)'£4ê|°Ñ*q1üV\†5ÔZ­Â…©§ÙàT£Ý‡"jûLRÚ̹ÄÄèh>ãêHÑ‚¿‡&"XêU}S[Á¿- l„™˜)L’O³Í4Ú:I†èå,õµq¸áU™Ñ"^ĹVënãåà ´Tƒí8åX†Xø[ÐÕ뮲<*꩎÷ 8¶•¶¦²@–ןÁ£×’KJîUTeÀYóD•\í0êI¢ê;ÆV,©‘á6VKøUA÷J“Sãƒ4¹,–µ=cHß¡Ê šg³¸gZ`jø@j¯M™…‹mYkÃÁ‚ž@"ý=° †$”E×Ýò LN9 ?ŒjªçMàäí¸Üú*kæ¡Ê%p,âF¿u­¨¬½Vq‘0}…2n üœä8¡á!“aÐ*"MrúªfuˆÏÕä_À´ŸVä–ô€Šå"êQÝIŸwfi@,fî¨<ÔY˜¥´¨SÂ8¥lžyDm¿ž2ŠZ7bF bq tf'.wà¢Z*ÂÑþÞA¶i1”jŸ ¦ß`}¬µNUαš×zf’¿%Ì¿ë¼(ØŠœ>_ô¨¾‚ò܆9:&’´¨Å% ÿV8BêD@šú¤\°Ul–úAj¥Œ e‚PsÚD}ÀÐà›z&Wó2+hjdáà@¢9=³U÷åx§ Úl¹òÕq¸ú–«lsóØŠ£ë ‘þÂú‚¿2?Ç®x)‚K‚I«PðÍÛx*™úSÃ%¢úÉ3I%nìlµÕÎýÑϱ˜nräG0Úܯ¨@\sb›0˜\U|!× -ùؼSÂR'P ÔzÆ(óÛÄý&ÏyúCÞŒs²ÝLgQµ3#ü5\œUÄsËmÐbòœ<C eÀmm÷j¥fƒp¤&¡OVkyÕíÛž˜¥¿xè¼±–¨Ð‘Î\PïcaéŽ:0¼¨™Ä!Ða¹­­›P=h^%mñ )WJ¢ž4ÛÀI%¼yUÀ©*MØ^P׌T${X•Ùç§ç¥µžüc7at¶å¦½ X0^§õÎ;=?ÞV±öúA‰ÊŽz¯6TÏÇ‚äl0šIÝ…aØkMÍÈ9ª­©ÀÑ×U…a$ÅBÙ@0ÿZgñ† ظˆŠÉDŒÚ#¬ì·fX#?å³­»64Á©óeÝìκ«5nÕÌêçƒ=ç[¤ôgM¾ãéìµþÔׯ d¢ÑFñ€CGZ‡ŽÏ:§GA¨”k½ˆiC¤Š£cͱ$)°­#SÂBÙœI8 8ØëƳ„¾’7Ä@aª/»ê{'^ç³¼ úJ² =D²¤ñaɺC=¬+5ÆyÊTÕº[Ù¾:qÇ]&ø®2Á–haý[s ò«!Œ­¶]£¡¦ëyÌöù‹ TÁ1µ ÓÊ"¢Uëó³&uŸŠ5ÇK_rˆþ'_ÕŒJoK5A‰Ï8 H\u,r%y|#\f8`ï”\·—kжI-dÔ5P^î m7é“wÂf8 ¶¬@]€£ˆÌ\Ÿ‚½ª€Ëu4Nw_«¦¾½e˜ÚaAƒVu7ipT¹ª'=Úû9–·˜',‚Ü(æfYÇ3¥áŠñZL°g¸jûzR‹÷ a d¦X ¢h,a bG=íÈ5ßRV»Ä#šMqºQ|ÚÏãÝwgÌP‡µbŒöhïù°h$jéH.ÿÔªš nÝTóq^þ7¬À†~Öâ”Tµô!ñ·ôÿçea9£½µºÊÚ2£Íþ# Ü#¥*+ €žîÚ´ø¯k=EË” ¹›7¼ÉÉ-½%®åÝŸ&»awý«£*üë'(Mq£Sð×'`äÔ”Iö!“úÿOg/3ŸÉØ€Raa…•›«Þj¢½~׬Ÿ)Ê\²^„6ƒûeF„©‚N²M9ˆ‹ Së9Ç-º[,ò.ZWÀ£zÊuÖàʘÏÓÿŸ|fÊ çý-áª[‰eckîXjtðµ|a®Dè½#•â`Çà,R’Û‡Hªmµ| õ²X£°ÖÓ’$ÙÛ|pÍœaî¶›º/–‡‡É®|[²ëÝ+›—©û-jX{` \µc{º;Ö³CìæÒ‡lñ`º8.îC, ¿n"e"AjZ_ ÂAƃWÒ p¾)ViyÅ„f`Ç¢h;hQ‘-þ®˜'T†K½ Î5½&³àÊŒÑO×ç¶½=Ãw‘ ùþÁÔ†­ö¾§ uRMÂRÊД M&%ÏûnJòŠÛ¸ §ßw\~ü¶ËæX–ïhKyh_|Ë$ªŒ+جZ3D=™Â{—¡n#"`&cûJŠzÈKAe6{%õøu-Õ·VþHŸvü/B²ÿÄ'L}‚KË…e÷AÁY„þw­Ý~ ¿>Öÿ½"U<¸'…?éö{Ì ´&³½Õgê‡Õl?o,¼Á ˜íãÖ€ïL4“o¹þµx¯ù×ýœ5.Yþ¶1ad™S?Ž9¼G*¹<=9úGùï¿++Èendstream endobj 47 0 obj 3981 endobj 53 0 obj <> stream xœåYKs·¾³Tù {óLÊ;34¹Iÿì¯7_žÃca¤‹}4›óg¼Ól&»™œïz»9¿>ûgcÛá_ç…ÕÎèÕ6Ænô°áü‹ž¶[ß|Óš.ÆàcóEk›Ú­mÎa¼ë{ãÇæþþc»uÎÀÈÔ˜vhºv;M6¹æ[œþ{K[ŒŒ1Âjgq­m¾/r¾jóÿ~‚ÕOËju û¾L\¾C}ãmºÄÖõÝdbä» òÇÖN¤åéYÃ×íÖ4·ívl~k}óxÛºæ%,?Á]Ž8C£Ÿãž±ùp=*Õ‡ææ"ݧù½Ý$å–FÚNC(O‹H®‡mfÀ©laÒã¦ñoÒ'Ï<ÒÐø¶Û¶³Ú¤å%þØe÷0ŒS×h/ÙÇ0Þqp„ëõ ˜\à n¿kѸ6¸n  Œ/c'ú,!c—lX0‘£»>-ÞüšÖ8çÙ¯ ÏÙºÖŠÇmˆ0Ѱiï¹oÝØÅbóª`sð4̶#ûà²<è¿M{õVäàMì‹-z×E¼Ù•5E3l“¶ÆuÈA„æ Ñɬ#îG_C(L„,t;ÚÄ òk6‡#ÅÉpŠþñ]ñøóäd@Ù7­ÇÜð~þ*9YÁäÌzKîDcˆ>v锬E‰ðgEέRc¤ðÉ;21<Éáçƒ??tÁE00B²èHþq#|‚¿>–´Õ·3ü?^Œ!>‡þÀÀC ÅgZó¢ îe°+ƒGÜ­mßµþ3˜‰Žà1uΩK†¡wÍ;™~¼vâÉ™¼ÉcÛ²ðW|) k_Èoeú¤õɃW"§\æ²,üme¡xa•CW¼H@%ì 9Â9q ðÿÊ%ù,-=Eý_æŠ2_rÌ‘ZÞ3##VIý ¼f4ºý`s) '€û!’B_8~È”N£$ÂцÐrå.0tFíÈô\í,i:ò);\É“YúXÅĉùÅ÷&3ç è)hér´å 4$dƒ"<¨1›“Qvb¦vÞq(Œö’R[ž¼z‹l8Õ½`7€%êR .ÀÛØUm•SÊ x^‘¥2eZJ„™ïOŒ9’È ’žsÑõf(9—¬w›“×Ûšì,¦«èò­Ü0æìá‰/1â|IÀ×*À™} =BùW‰[‰Bôû€¿x8"be3J™ …b2"¨ò€¸„Éq[´Ñ.aÊÙ48¯R§.JËÑw±’–a£ókñË·å:ª†zN—jeÌ%SaZfå4IB¼c’MáïŒn *¸¦x§Ó0®â:‚î ò-úrÄ„>i¾VJ N¨ˆ§ŠàÜVÙ™ÍXó.cmo˜DžÏJ8¬*ˆ£Ó…˜ÞR¨Snþ“X«+˜ÍäÖR¡1AOud97åþOÖÀcÙ'2]½)ƒ«©ëÍŠ ýÚž£FçŠô2¨Òêå);E•’ÞÉôZ‚¸tAL¢FëÉÐä±cv–eçìT)]‚p›#8/Áéà°Ôö.¤btö¨Võ”«–µ¨Š—̦¥,]præÈB¡»:¬ÊÄg0Ø{IxÈ0©N/Zœ¡=Z¨8g…çZ-¹Kuí‚âiæn—Q«ÎÇ\‡â¦ž¬&ùóQ‘rÌÉöBBFɬìïy å"¥} A‰'*ŠÜjüÄŠl>¢G ã¹nÌÜž3Ç!ñ+¸ÔJöÆš+0 è®uy%O€ ®®(óáȪŒ÷«p–´ÆIàgÌY°5*@aBI¸uŸÓ)ß¾Ýä¿SËOŠƒÜTõœ³lF)¬uÝ7[§).Ì@þª0mzD)ðîSÕ†«)/~’«!ùêu‘÷å'ߢô¨Ê$ èÕ5Y¤_’NÑVÝ•`3ƒÀF¬“Ò‹œ–Ã&½ oS!Gâžã§¾˜¦ò¢G3)FÁF‹lŸ¸%©»5qYäã«=p‡_ŸÔèÁWàü98Ò«¹?W×ä¸Sê‹ÀöpœY‡[/gùm†`¦ê;•Öw´FÛ My#Ý ›¥Ë݋ަWø)É£‹Eég€øî\øûNÛ^sæÚ|ÑP[f(xÝqýcCDݓٺµWé¬Ë/U"C# FÌ8ЈÔ÷åR—õûC':r~6~}¸@2Õ÷xͺº—RU—ëÝVÌŽônéxÎ_‡Ê7%¯»@ý:oå¡8ã$8ç&¦Ê0ÞŸ„„6F…•aUïª÷Ç®’!Z~¤0ijHé<.™c—Ù“³O ˜p¯ªÉ»’Žå‚™ TøÚÏ/®Œ„âp²"¦<§dؽG‘o>P;åTþ)a•?kݬ<øF^ºùJ/n_ÞàŒ¯kÈT¬3“Övq"õCåM´ô~”.A¶ü]Y¿HèÃzFÏÞõ)He‹‹\o©râÔVMaz…¸ÔiɃRŠý• ›äùJê,™{承Uî>•Dc7¸ÊFÕԭŹèëx…»béós›[½)Õ-ëç“Ø÷}%•2}‡XÌÙm;Pæ?µÝœfR-Ä×®™®&µÜbr–«Ìkn\æÂ?¤|¡S$•©#(}g,¢’e•“ª©ºlPÕtž1 å‰BPËþ³-穼¿tqEˆǪÝ>ëΤwÀƒŽy¬ï|á±lÅ~ÎÞ¹ÄåFû25å42³¤HÖíÖY”ÞŸúµ¨z÷³®È±Îå«„¢Ò‡ë5v¾wÍbU´$lÌj ËEÅtIéV:aTì„¥uÂèU¡_nÈ›®'ÎY*<}<¶äY_¥¿±&˜ÝG¬9¥šKhcpÙ.ÈçL¼¼³ôQhšòcÐH´-9&u‹¢7j^gOÝÕïû'æÞ7Z‚ñCo45kˆÝóIfkÇéS¾ÇvÐÙòÅÅÍIê{Ì'6ŽV>kÈǼ‹„Çwgçþ¿ù”TÐüV>ØœÖluµbj4Û³ó³ÀŸÿíjÞÀendstream endobj 54 0 obj 2364 endobj 58 0 obj <> stream xœµZ[ÇÎóÈ?bÞ趘޺wU¤D2"ÆLœDq†]XVaXXüë}.uêÒ3 R„v¦§»êÔ¹|ç;§ªy»V“^+ü—¿ÏWG?ÍëÓw+µ>]½]iz¸Î_Ççë;[×FM!˜°Þ¾XñD½žÍ:3¥õö|õïáî¸Ñ“ .Æáå¸1“1ÚÚa7ªIE‚ÕÛ|;™áý¨'gRHÃs¸JV…y¸7vž' ʲ6jóŸíßxy7ÍqÖ¸¼÷“³)®·?¬¶ßæu­ )¢5%Š…K=+›fÐ5ó TÀuMLv8C]BTÊ ¢‹Z»4œ¢ f²Á ÷ᮎʸ0<€»p¬¶dBT: Oiš ¾ð/öqŽp€žƒNEÇÙ 7Yìœtü´Xp®8D»Éº`Ð!Áâ -1`£ŸvÃ4šÉkmÓ Amæ)¸áŠJivóp…ËZgÀò3ªÀ[¯ÊÕÉò±Ž¼Un’·Üí ~5“‚€æØósˆp_Ûá¼ë!´NVÒfxFCmJ#‡!Ò,¸¢š[1–05ËÖkøœ’J„ Õ)‰ùÛ1‚}ÑÇáõ¸q!Âú- Ã;X•r»÷£EUCþ=)!4}NQvˆMàŸqHžŽ‚`°†áÏphéa!Ï+€T|¨ÑHôŠw8ÑyKzàÈ Y6ªá|4 ” UCȆ¦‚(˜„zÍÃ7e!RžDÆ*ÐL\"‡1#›•®Ê,í¼‹æÝ?ƒˆ˜,:<ÑßÖBŒ&ýöòWÁÕž±' EÊÁ !Ý}¤éÇ1†‰„܆Ÿ g‡8TìƒNQ8³°ãÑâð›YOÌSÞRv' …(a0<{1ýð‡ÃÔÜ-‹£Q±j£íäƒ2lÜñÈ1:è"_UÇb iiÜm=§0ggßjB7ÇÛ`Xéç‰àƒ¢ncì ­ƒ®>Ã¡ç˜ |r ødWÇRÀÚß2ë¬T1¼‘IèïhÅÆXYù°É ` _yø mV´æŽa¢æ)¶ i,ÀLô3 þ0šˆéYì÷ÛÀŠw?·Ñ‚8¶è1ßDS® ¦͈8,O RJ.;œEæçÙ ž!X Ç…bØHP ‡ìDØpjas1šÀ܃ü‚ñîˆ 5jJÎ|ßÌŠ†A2YŠphÉdc¼¢LppOñh0Ú„ÈL C3!‘3Q•ç8“x…¹C‚‰“¼~ ߎˆgC“~Q;§1i}B’*ÒðÁI;P…bµ·Lð$h©—¨S°ÀÊyDß™™‚DÞ¥µÖî 킜#÷3Vå6{*>æqñÈàÊô)C+c`ºgüå± 19ívcæÞŒih„ºÙHâ bW9}Ñ.½‘U Clþ!êé€H‰ñ@ ­e¯ ‡‡_A-æ,Òò,“?’…Χ!™£¡{(¶I¬-eÖ\䉧šT^ÊΜhÚᥠ¦ +ëd¢.F #öTÁZ„š7ņÆô£N“©eãj¥KŠ$Ü“®YE«cbÒE¶ª©Ç ÉékhT±î£ð¹K‚yØ×v‘3¤ x2¹®ìWîÄñR,—7,â°V$î½™jDæÚOÐeåmC'ª`ظV2ÝQ‰ÚÏ1ˆ›7–ôÈ VseôËŽ}i%ô¾<žA4ü¡‚÷¶«'«·kk‰FÔ*A\»™ëà[;Í=îmî»§gºl®½žé‚Øeuîxs¤|á@óæð‚‘XåéÞ’!» º…û Åb¬™òy4gr`õ¬#‘½j+‰jñ\" QçܽZj¼c¿ÿP6ŸÄQ)¾ó Ïd—à§kT\Ì8Ú¾Üà`£6k„uKed[¹®’aT¢gœAgÑ¢~Ú¿´%ÈD’>q¹Û©}c_K³+zÞËÄH»Dðw‡;SÒ}F C’‡“«ÑåÄ–}Ü+Þîá­7ÒÒed|¦6ü…©ê¸SªÇ ~köUîU©ÑȬaï7¾(åšÊñ!ms#âëÑfú£ÎöµL~ÐfÏIP8åv^noxоÃå™ó!„í€ßTò2gñ"é¼é“.ÇMÜfç#`É:[¸œppÇÿ錫Ä$ùü%g‡ÖíŸZÃû—Î×Üv6ç-ñ¼'Uº=‡®GÀSJÅ´Dc:‘™íñždÓ"Í®º R“óvÅv=æéš$R¾4Z•/¨¶­õn¤,œ™dRajC(”ù¼Q׃êRBJoÇù€á@ïRUA‰VåÄ,9Ú÷-œxÕ¦ê%ÏhXøS§'´›B¤êÐw2lyçÛ®Ôóû?ØÓ7ÛM?Í$­Áß“5ʲGþ xQÔwæÈíºb$£Æx¸å÷„˜`æ†^PYÊRøüù´Üàïïñã˜ë¶ ”µG•'¯ÊÕóúø²Ü|Ô6_´f#—oþ©\éòøÐ{°Më—Ì;t:ø¡ÛD—38Ï`¾•QнöÈÔ²—Í2JJ×| ßêRÕÐóÑÓn¥¬OµUÙõXÁÇ6 ]…kÚEscò¡óǙϬ~ ‘&3í+è÷Uî4àVي״¾Xn¢$Ñ:µ+xÞv·oZ–ø¦2ÉiÇBMQ´ 1 ±,šúºÀI]`ÂcOzíK–¾Á ì÷°µà¶{¡™ëH³Â.¤œ? ]¡Þ§ýþ ½ùÛØž;œÔZvŒÖ扷¯\>@7Tí»­ÜM‡Þ5£ NùìM>î 3L=—|ྡŒÞ^—.­ñ?½’âÇOøan&@†"óÿ‚È$F,÷ŠØë$Nùh»W²ý/XgØÚ³¯6ô‘,s+ª„ê³"+w‹µ/Š›Žo®N|™Ác»vøß—ÍÞ•Ù4üUùxý6¼+Z\|™wKDÉÿºùìeÅÀM3})kKbÛæ ùÉêwónÂýendstream endobj 59 0 obj 2835 endobj 63 0 obj <> stream xœ½[mo·îçC~Ä!_|[äNKrßX ìØN\äÅq”¦E ²$K‚¥;Y/‰Õþùrf8Ãá.ï$7Ad-í’Cr8óÌ3Cêý¼^™y ÿÅ/f{¯úùÉõ¬žŸÌÞÏ ~œÇ/æOöCcÛ•¯½™ï¿QO3ïí¼wͪ¶óý‹ÙÏ‹¦jÙÿ[híŒnm]y:ì…F_TËfñUeVÞ_<®ìâeµ´‹}xÿ¬Zò‡WÕÒ9³ªë~a«v± _¬ÂG’>Ýüqåk”z˜¦[¼ Oí߆!¾iJ{^¹ð¯s ´±ºÏÕ² }úÞÒ§ïÒ§½0…0®‘a Ï+ ãÙ8¹¤.üh­þžÄ‘–šAkiim¿2Ý|éêUo¼'m]„1gð¸„Ç5<žÃc+xÜÈOðX‡È7nÕv°3_Ïöÿüóâ)|{/.:þ /.>rpèˆã|oáñw™À?î•Z2™°—Òü7xKó¤÷üt&×"ìþyc;ï1¼}#«ÆŽo¥ã²ªÓÑx÷ig÷/¥ãfª,`‡ì¦eé3vïà}W£-šhD`‹àªçáÿ› 6 A-Èè‚´ßž…¯¿VÎâghzW ýâ³`÷­_ùà-›*öØð†lë r}hÑB—ðüœ9‚Ög8jxßb›*êà”EÕá…i ’o~­áÁ…¾Æ bç ¥ÆÒ4Aþz$+¾ Mvù ZxW•ù¡78ùO - ím›„l*л ë zfd„þ¸Ü#Xª‹Ã²ôSÑ]³xd/¥ÉÓŠñçP~_Ñä]Š”³¸›ÇÒô ðÉûÖX„ÌêÉÂS»G¡ì–o¯¯D4?¡°ä…-„Z?¤õEr4n»¸……¯åÁ;C5œ„–¸ä;ó8Û¢¡€Vá@é°ôdf¸aV(>ÊÂá`øG¼tPkU?°¨#Yi Ö¯]1xe³ ]£5ºg8.À48Â8KvÄvø¤àahüá&ZãJ¡Å5EFø«µ‰‹¹8ë"('õ£D^Ñó‡(>4¾NsVý.¶ ªS âÙ„Þo*ÓÒŒCð6¸Ù,°!‰—zwqkþBêÇCAÝŒ mè¯AFÝ„@n€¸°ãáq˜CïZ°Øè("xÝâgø})˼31ôáCZ÷çòr/½¼‘—éeÂìùé¸ÔG :ӫѪðO Ài{6ž?ŸëÏ©òŸÆ(á›ÔprÚštJŸ/wË9•w¿HCØÊ!Ø?0˜¥pغ‘¶óý:xx^RÒR^^—ô¡ZZ=©¦GÛñéå²$óX«¡°ƒo´f?zr×Dù¥Û¢»e¦<ÁNe÷¢®wQ­u¾¼^èpÏíÉH¥í|—Í®­!ô6jö§¥NW¥%¥—iÌו¦V#RzϪj gLUˆ)e.FÖSÛ.é‰Îiî»×¼:Wv¤´K¼u‡—¦QPsYrã³ô2¥©Ï35)+ØÉÈïZÚÎLB£íj„~5_»ÄÙ4]˃¬mEAV"@b|`@]OŽ’»0Û%N¬ˆ°A`È£müŽ rAÀà¨ñ€¤q uBXŠa$ 9XBVÇ 4òïÐ +ïû)ñ š…eâIDé¡ ‘Ú¢¸‡¨’,ƒ¼íÀƒÍ6¾g?û^Ñ·H˜°¥~°„Dÿn³)䈪ÑúmÇh³}û°yÛYmk w`„€´™ Zâÿ CGÿFEÙ0£N8˜m z•Úb·usa”Ú–ÌAˆE$µ8õ¦)ì_œ•²‹MÁøÑ ˆƒ¦ñ$Ö9œ±šèÒú ê†MI¨™Lê(Z£µ–ݵ4³>£‚´yj§+:²8ô´§´_ÙW»}Q1n ZÆcxƒ{¢(³ÊÖ2ê'©¢8t>EE5äÁ_o¢ë=‚ þ¾!sƒIÀsíE¡ %“¡k‹3Ÿà‡@Øvª?pF•¸óµ$šëVd«m1:ôÿù¾èØé¦ºÆx0ä$05—CFnÐL€›ˆ`õÊe¶N+Û5 D¨meÍÅ6ëÊöD`©½AM¦Œ-ÚD%ÔF§5ÀvÝà´f ã䌭o&øÆAf¡GÒ&‚ª"§N™™òÀ4Ç”Y‚J6U›ÃÚeg»"ÐY¬JÑ*ŽXÏ tè>bÛk7NÁ¶n»Š°PÔ YVž€â‚Žÿ*&ƒ ™ ¨ˆíQ³p²zÕ·žMJ¼(ų PPߪ;´Á¦¸FÞ?U€ØfS¦Õ;6•¤ü¿Ÿ‚˜C´‰*Ô°S“‘œz[V•Û%ë'‡¸K] ;ÅÙã°›Æ0£TØõÂvSå ¶&Û:M¨&<Ž­¦èçÓrX^†àÊ4”!Œ™ÄžB¢ö²Ñç¦I ýa,üÝrÉ$ùBö‹ðʬ¶-U©µñŸ²Ûæt±Ü ¨m˜Zƒž H­µ,Êï7_;Ÿ”¿@2–*:¨yÇày†¬I†ÜBÏÈázáX©YV]‹Å1\n; ©GÉM0" øÑ‹ JV‘EI®¤ÊX œbxCú‹&çª\ÁŽ|°Õ%CƒÏÊu§a]˜©ô¾—üµ%¬ßQ·ˆå%U_ÉJ6<éòùóô2Õ8nK)»Êo¼L}ΫB†w¸%ÃÛ•ÖeÊ’´N‚ íoHˆ>pä@#27Xf$‰Dö¦hNH¸C#uÄöd‡flO÷%^È[lF°ìˆü\ê ¡ÿ»Køì²í˜7S ¡Q€æËñ2šÂ ‹ž1×gÐ`• 6MÐt/'…4ˆ–&|Ý‹:Å\¼Še¬pnQ×Ås… Ñ!]n;Èã®<ÏéÖÌjU~K á»-hƒ`:fbý$7r]+Q/–œ÷”Ù²Æ÷ ŠŠ?ÕÕX1{VÔ=L0à÷ëE¥pO [ä÷ÊžUaZ¦Og5¶oW$w€1mªJÏtÍøÈˆó¬t[# VÃŒb{ŠË C) Êè è–Î…’̨þ—ƒThk%²Mk戒ÉÒH+y0ãíwt8ƒh&4–˜3™"H±mF¿E—±íÓ™JÒ¡¦Æ+JG6Ö §6Tbqi.òeBÆvñŸªM‰#|{“¼„RƒägðÆ" äÀÙy¤ëEZÔ·ô&ÅÒ–uñtŽæ°q×b’ú€Ã6/&qùá•»n”-GÔÌùQ‰)åÇ•Ìð¡Î )¼é¦Hœ %*éPe*k6Tâ Ó[ |·#»»AGtôE,ž ¾iØàSLÎðÈd@È·ˆ³ÌHKK“›i!¶ó[e‘Û‘´ÍËdj9dõ‚–°-™_äp”ŸàA-hÙÖ1ºSé‹°¨-äñçA<\j)$™#4š*Mí*Àt+‚j=^*ˆ püM}±SåŸs†|€=oGEBy¹ë¬ÐnâYuÛl¹\³hÜ*®°E‘sc¡­±*ÐpÂÝÖ8³iXf£’òZÆ1æ6å±ì*Vð6k!$pfˆ·±š¢Ò(‰e|~\€ä„52ø=uÕ)â0€ï“ O„›šneñJ+ G Ta6pŸ„Jñåû$ßTÂ{ —=GW1bË1 6±1J,½ù¨ª¦6y^¾‰w:"+ÃLV;`^®Ãtl«MÈŸŸÇ{%vÕ r¯D¬AdK^ŸfºE2e¨œÖ¾IàÊšŒ÷[ÖQ©:™¬­Z»Á§¢ß&/å>šf›1ŸHQâÍZzÐRAAùÂ+,kŽ™Ý:aiSü~­ŒR¶¢Õ MâÕêªÊQÁ•¸ÎMˆ¤,ªM€TcP÷1TîÎàĨ”=éë#C¬A!«$k—3³üÞÀv£(°ªB2`5Ä™dA«¼.o,•SS,ÓQÝÛêr—Òbä€XqlåBY‰­9K%Ч0~À˜sêŒãꜻ¶«-v䚉³Âà-Ümc*¬G.ÈqÂg¡iúŸ7’É:õ0ÛŠûÛ‹~ÛÙEÿóÿÓ©“?U,ú4ù­®ò’zMWΕs¿æ d´âiZ!dÝ“‡‰­L¬Äz›­hZËÄ,y|bé l¥ÆYFŒŠ:2)v‹\-A¾v4ˉ•÷HôÉ„õy½EŽ3ÅêèøŠôÅ„1;̪I'w`_„£äµ!E«­*æ»jòcüV [¯§|ˆïx—ÕXÒžÁßGƒÔ6ŸUý£Ì(ìÈÊÆ–P,Üg¡Iú>¨fÕE¦®IÄ]åxÁDÕš¼À}ý¡E—z˜¸àvƒÝbd<&ê,»]¼"g#®NuÝà±}2ÎH$å`¨ÓV#4rèTG98éàNÄé”|ôkÐÅÓJ¥XÏögßÏÞÏ[uøgƒ†yز~5 sÓöuððW O^Ìö^|3¿¹º=žíý47³½¯àñäåáŸOçš={1ÿþ#ÿ¢¡ ¡Û„š›µýYNÑò‰Øß+9!x\JÛ`¯ÿI!±¼8S÷X‰ï'+yYáy«™þ¹ÄWR%®7¶€”ЧG¨*˜¡ºÉFl›ªÕ1¾SU+KÐý!³äœVîIÿZµxúåTÆ•¡"—>RmRf¯qŒk“ã„ÜøœÐªR…Øñaw{âñ™K~ôºå’lÐ\xîè°Ž,ðfj8=ò`Àñ:ëu|ðݺ#9mÁ/ï à™ðÆã•>ªaº¹lT“_¾M—ãî䥺\z;Ñ•åéÉK’¤ŽVŽÒuÄ‹’Ðì܇/ì¥kxÅ‹‹k^aZâ#©ìæïôdç¤4¦º*³+\q´Þ ñ%Îò³ÛÈwqâñNbÒx+Íÿ ½ï,§ <,íEÒà]sS²üñP9ÚF`$·òýºdPj'lº¾÷y:]å൬\að#ðÞ+òÖòM]#MÆ«oõºÆ³Áè¹x^|ÎêÔ¶âmé*åt>ºæÇtúU/;êJßâ–)š†Úðë-°ËÈζµŒFv]j™–pXØ“-6\œè]VÜu×÷‚ýªÕ35gFu±Åô`µéþ¿Ÿý†[Káendstream endobj 64 0 obj 3938 endobj 68 0 obj <> stream xœ½\isÇ‘ÝÏXÿ„žÙõ4»«ª/}#uXt2EBò:,‡@.â —ûë·ò¬¬ê ¤:ÌTwו™/_fVëý~Ûtû-üÇÎ÷½÷OoöÚýÓ½÷{^Üç?GçûOâ ¾‹-ÍÜÎÝþÁ›=z²ÛÝþèCÓºýƒó½¿¯Üº_5k·êðïfœæfž†Õ“uXý›Ÿ®7nõ >¾Ž-øëûØü§õÆû©iÛqu°Þ„Õw±íhëšyæðfèçåzÓ­¯áÒæøsâc·ú›´ýãàÏq¾³ó ƒk†8ãƒã8Ë~ÝÓ=a²÷l‚sMïö7¾mÆnžéæ“8‘Õ|\ÂÇ]üˆ3íºÕ)ü|»ÞôíŒS¿å{z×6mׯnøº_Âǵ>{ì;Ú˜#mŒ:˜~l¼ÒÆw©ñDoÒ—ÚøFÆ 8j|›=ŽcÎ絸~¨×µ1Ó˜gµÙ½®=^íóô4ÄÌõÛ4û´Mwé¡‹4ûÛÔjÆ?§¯ÁO0iimô+ˆ{¥;ƒX7oúTäëA8ñή c¼yõBE}#º\ Å- …̤‡zû;+eºìÛ¹^9Ì–À©ñÖöa¶ =¾|æÈ>Ð$†|îËŽŽ–êAR‰²0·™I|LrøP»ž„wS[ãe.QVƒmJ,·V´xší™ƒ¤}ß7NŒ=×gùzœ«†÷®qiF?Oôä™”¤~I&m& У­øàI„w|]¦‘$t[³›³Ôx–)–Ze˜£ÒN=Hf)ê*¤í¾Ëîq\×[5ú¤"¿lÑè„”2Ïmk3æ½ ¼ÌBäë›dþ·™¶š-5:𠄝hðlïà¿þN0ž`[ ©úÉÊOøÚ¶ˆîŒ îüyeQ`"màemOe‹Š7¿ÓP« ¼Müäà2ƒîr2è»T™› R–’K1Àu˜)„Èè,S-³sòõTïa‚“ˆÞç;¹ò#+EÒMÒ|j<ñä¿HP~W[ÏQMDÕ•ŸÖMY.ÿ¼ÖÖ9°P8°ï r-›@KßXÈa|;˜Š¹Ò]¸Èwá,ÓãÏÓdé[mº±é`Êq·›aj;š;Ò½¸_Ä5\Hz ¿ßEÆ'ÐSˇu‰f;ŒØt±vàäz'ã±å4þ;‰Äwv=6ƒ Æö/×®ÆúìÄø;ÞQ±¾çJ DENdá,í¨Zu¢9¥P. ™áyŽ¡´ý{Ь·,w$Ê·5ÛÊ·€Î­íE–ÆÛåSÒ†ð$ø¹«-ì,‡†Š]@wµrã /N«70/"€"Næq´Îð%|¦Ÿ’wÍÙ'¥ù`µ$^y¦]~æþOm|–Ÿjã“ÔøRë·—érR•¦Æöi<ÐÆï€Mލë7Vq,q`Ñ\×Ôå´&Ï$äàÀa»s€s…9¨‡޽ ¬ÁQ[ØSÝZÒN£FÉŠn“rï n×Ëš¬ß¸J«¹ªmkÕÍžÕÆLøûGñÒÔ²Ï׌4g(¨¥ÁPˆ‹´ŒÙ†ŒL,çáÈ6clÿ‰ ³m¦ vYþ%…ËPæÒp“cG8^g†‹nî4ù[«^–`m æýç Öô@ª|Uëÿr]Ñðëš¶§™¼¹¿§ó¤»ælöDƒ½]!õw™îˆ§úÊB×"Øû1鋪Dw|"ǘåB*þz_èR·¢~†(ˆýk¶s½®äDÁa@”yÇYü´îº]ìc¤ÜD¿ŠŸ«: 1mÇžÁCX¥Gæþ±v!ÓÈ;òÙî§_,˜é½ äïÜö}3·´ Î Kÿæ`÷ûÞãy€6†#Í´ äÜLñ¯Ÿg(ï=yº÷èéóýÛ뻓½GÝïö}O^|ÿ<ýzÿ?ö¾yºÿÃÖãyð#Ç%@ëÓ„ŽL‹ùùZ´0“pÃ,‰I˜,¨Œi2Áº]tÒ´ã¤i¥M¡aسűG6Õ¬naà÷Z늀 CǶ-¹¬ –´D×ù°ž 1Re:ðµ° 5gècîÄœT#BëÑ2`¿0€‹jµ—LX„ØÄnC‡M0 hš÷«QÈO ý† 6 e¬Œ³!ê¿`ÚÄ mž»T ±S˜ph£À[Z&X®FùbÕ öÓMÞðÙ H.(XŠ9Ü‚ðè–TqÑAább³I‚t°ËÎ×"ŶE<Ö8Â…y½PÙ¦§x¨Æßòô‚Ó8¿ ïDîB²b*Ï6Ú±H:×ö$1¦‡>t1â¦ñ€UEÎtÛàI %ŽVM9“œúß ÎE?;|þu; ùºß‘˜õßb©ÄsE°âëÚ|™#c ±0lLÍš9Î'“™’msd\É ºÙxþKF¢±KJe`NÆJ†öÖ,F¼îÁ¤‹2ÿ˜Âƒwk—wO¨8dã 6ÆÉIZˆ»kËhÀPóA¸ŠC䮸À —|ëwb’›2Á$íDÙc@áó÷ÊN.­ßÅ8ÕWhgÜêÜÍM„ÚRŠÖ@‘S× Ã„è¨X8Á#û™ºcwpË8Y„ì{mbR<Ÿ(Í·Eqa¶àwyŸÓUÝr3é–f] ¬N^€ ÅXmèd•!ŠêƒÁü»±7nl16ÙFLˆm0ÃVäZ¦³÷@+•)H0LmRBÞ¸žM|G‚ ±ƒsTwªP™ÿ)C\¤|ïÍ…O°–¨3µµ\˜c*¬Ð4¼±:àøí\ÑÓ0#µ1©I““~‘¾¦<Åc2y:+ª÷ûuŸÎey¹Þ@ÿäµ!x‰i§6 øoñ×—ñăDŠ7| á~•pˆŠ]˜ÜÅ3vâÁB†bž©*uÊui |¨f[žê»‡¹MŒ&˜ê˜p^ V™c[qÓª,W•4ò€Ï/ò›¾[ÊÚôÍm’¬^²E¾OSgœŸÆ(°»0þm0#9I@x_Á9¡©é´ÌpLøM>–Ým¯¨L†õ&Z†n ±—‡"V­þºiwL¾ýrí'Êø¡ ðQ²G?_ÃÁ'Oñ)”g­ ô(† àa&JOšS!u0‰Zžs‚o›¦µ%Ç—¹ÝKAžö_„ú"¢–bxÄ ­Ó9a æ¨yUäÉç¦Kfm“óÁhŸÈKµ”‚>‰QáM:Ñ ;+™›ftÛÜn–+ÊqrºÌ°%,¨eŸr/"°d+ožÉê¾]s°¦¬›£0rÁ`öYàn¡@ØœMÕ Oéú…[ cË9Ç$Ò 9MÑú¼)ý—ÅHÁüŒòdï¹4Uø• I½Ü—¥wá’­’‚xZö¹„nòFFF¢²/Ê€†\m ÷RR"'´¹BàéÏ™ž¬ ‹+S¡ËR£Zðäb»-Ú›y#ÚƒÜ1Mð‚€>ÎX‚?–s‰.e,Y²žQËôÀ9"˜-ëðÐïPbJö£‚q]ƒÒµP Aˆ']Ò“šÿ©Úœ×Øo‰7RÍü!ùI^@† ËôéTd~Ê‚ïã[eêÛÖwÞPPÎ CVÐãÁá“ã-3È%ÀZØg¨šgS)¿¤â.T&A¥®dˆ¢í3JˆG„f—ƒ •ãÐTŸp§¸™žfx9`Á=þoþ :mõ,ÌAÀ hû5*è Ïêù:¯Ë„¤ÓFDWšt¸° ¸)ùœ8 \ŠÔÕBE E*–ÉÒÈ»†ÌÂù^œ4ÔMÚ‘Fì$axGæsèª^5G±hP¸< ž\䍯tSZŠEC‰E™^0Ñ-'øJÞ´=¥µŸ@s{ž¬÷8…nž>ož¬àdaFóEP©F~¬Ûg9Qyü³Ïr‚aí$‹zfÕ.±š³ú?fÅW’érãu ÏJ¬‘s9?Xx>FeÿáQ†)Ûo„§1æ½2ônîÿ2„WȦ)›,º<)J²ô°§ß¶Ð"®(úÕâs²z"6Ù7ÝŒ?€•ΘØ)€Æ€Ôv*‰Xç,¹ØÊx9òúÏÒ‰ã3ç ÄQ<ç‚ËúÒ Á¥C©È÷g.ë áÔ͈½Óž"Õ™¼×•M’z+\f¨bc4ñzìž4û„§a ЧÄÌ[-–{Á#…‡ãÈÚ»Põ/ ‰Ëö ÆG>Ð¥üa=ˆ™èÄ:*¦^H)> ”ûÂÏ…¾G¦SKæÞ«v86O¨u6Ü{›ûV>­ãÑ`h+ú‡d iÑ‹R"G1iþm›MK/OÀÙ"—²çSvÌ„ÔphŸc¦º&Õ>0c’¯…®äÌQùígÀ>ºüÝSbëW>‹ƒ3róT«,f*Åe»½fO ¢µÊNð? ˜<!Ñ J­ÆÌã=Tº†AÞ`hw솛ÛM%Í·‘/>gSKš~¯þ &øn¸WÓæè9:Í)ÍTë^$°Ù‘Ø4¶›å£ˆµ¢UJqñÉ‘ æÐʸTF¹à1@ZæÌ Îø(Ê õ(®×ÿOÃ¥-Jä1B ð†kÆÃB¹ERÀ(FÁíLÑ#¬½¥—îך"å5S1ù7Î 5«““êÑ~å¨f1εÐë9t‚Ò*…—¶ƒ«‡ŠAϺ9N-« KÒ@c2=‹ÀW]²|Ù°#×@ƒu$1”rã2ïDyb?òÙ”|è)´­Øë‚/Ê.Î ž ;apëâ&k¡Óœ0”U±ñWÀu6fu™vuWmŒ‘JCoxºukØ!¦wËÃ>rN°'r¶ýô~ê?Ë 5Rák¨â’ÿBT’wk\^&kÇ CŹâÉ»]‰Rv«2% A4¨æÃõŽ8ç Y‡ïRµ=ÑÖŒ;zöQ‹"m )<8]•„ÆC³l’L¯j>iÞ`Þã¨eŽé—nTGŸÏÅï€)-( …c³çhî2uä“nv[u+Ŧ˜·<,Õ»Wú¤žL¥+¬Lƒ¾Ø¡øfq^ŽqþÚªžžõ1®ƒ—²ÊiÑeiÙ<¯A$¤ÏòÞŽ@N:È÷å)QÙ­â|M~Lu¾œŒúÆ ³®Ò@¤)*žsI¯5DnÁ!$µè“e±ïSN=ð[O£‰ ¬ÔÊêæ£h ÏM4ð”¨×[b[Z#Ü•D‡w3ÐTŒ¼¯R…²þ.µÚá@Úåìð`â§²,/¯w5»ŒÁ[* Íp·òjI3ë‹iù»F¸1ð¦8Ñ{„­”Ê–'Ûm~—ªý³ñy¿5ñi˜Ð—X:LQlÈ(¼n¡/+õê+ÌA“e’‡ZÌR¶·x[Ì—•¾+zïÐy‹,Ã/ÉÑ¥x¬`òJòfS ~²ãæL5Ô²fe.ѾóRcõ87&¾~Øû! ¡Eendstream endobj 69 0 obj 5117 endobj 73 0 obj <> stream xœÍ[YoÇ~gü#øà@;v4}ÌÑ~à$¶“ÀGb3Ƀ ÔR"ó²HÚ–}ê쮞™IYËÝ>«««¾ªþºõÃa׺ÃÿÉßÝÅÁ³¯ÇÃÓ›ƒîðôà‡G•‡ògwqø‡#hà<”´©Kîðèå÷t‡£?Cl;xtqðífhúýZg[ûàÛä¡ÃÑ 4úc³›?7®MiŠióqã7k¶~s„åŸ4[­øºÙ†àÚ®7¾é7-Ôx7A%ÕÎ6ÿ¸I=\6áªÁ›/aŠÏp´‰Fû´ ð7„ˆm¼íóM³í¡Ï8z®úªT=`Þ€C‚Ÿ6çªyê‘øê½­/ñ–¦CÛJÚŠ–¶¡kG—+˃žú1ºë÷mï\HP¶uÎíaÆilÇ‹zÕãàÒ´¹i¶]¼B¿¹…Ò.z(}EÝ»4n.ae0«‚¦Ðºdž•êP=†vèãæs,íý4EÉùÍsjRŠ›×¸Ê®wãæª eŠÞ DÐ5ùÀ ¯)€a|~pô»oÙ@€§ŽöL» {VvKµëº©ì“wÔúö$DÙ¡zþbÄÓ¦€:ò4‘Œrmî°v?á¹;7à(!¡Ñ°D¾'º%rÊ"¥&X•ã(ý£ô0Š@¸Þ³ X@šÅ•yùÇe6žSœlö—,^lEë"wériGPãÁ¥¶œz`–³R5¨å6[5¬@,™TU*®‹‹Ð쨹SrO¿Ùáê`É]ÍDž×hô)õ`/Ú6oËv@Y&3ÃYîŠMnyLÐ- ¥ÁmuI[à/®,¯{;€:½ º'! 4ßOhGØ”S²¶Q’Z‚gµ¼/dDü‹‚‘^ðS:2 ´Cœ_ûGF¹¼+?cmGë1–óÁlŸ%] ›±nn±74к"w¾FWf#Ã>5ž]-NÃ@ˆ-[?µ!ƒÌoa}¾Ãy, >¾ÇT*›Ã¿ÉqýdñpVTO€½…Äœ÷¤O“ºµŒÿˆQú.m~ÿ˜^ª Ó\Ý–Âó\øªV%¢ÀFJ´l6/åã]´€Óš˜Ç‚qB×p¦ß‹i°Úøš¾.…W¹pu­¥ú®ÞîYëE£mG·bxì2_æe¢·¦‘°é»ÌÕNì2çQf[Ù¾ïÛ~í²ÃæŸà£_|S¼˜<]=”CÜRÉS„ ƨï6M(ð@A¬¢ŒítNe Ð9ÂÕŽÁ  Ò‘«'¿Äkj71ê+äfÜÁoqob¬ÃÖß0¯ ! rUxmc.M 2Š®4¿àˆJAÙq4x1®Ÿ”ò]“qµHÁÖ+¶V; 3€“à´æ ‡êÛiœã܇Æêᣧìò]üz'8‡®$ƒW¿}'Øx*»·«\kaìÅ^­yͳüí¼T—ž—§Åg×:÷<+…¥å‡{pv9Ñë\x¼Vø¦~” \ëós.Ü­ t»&Ñ3[ˆ öcªÄœí'íËìç»@ãý”í²J{Ùy‡ 3s® r˜ÌKš‘Ý´JÉlšpoÒ‹3cÒkGA9}ºÓ¬ Et1›‹Øâ<„YL}RA?Ð) í$©:70ƒõ%Ðÿi îKº¯i =˜ò˜Ïš¸ ¬pcô›¦«d@ÊcÊ(íèçIn[0ê’²ÿmýвemÁ+߆ÁQ¦_š]¯åÇY¢ {“÷­~£ZTUgÐK3j%í&#$[-ù1,Ïd~ìh»ìû¡[ÏÊÅmn®ýmn^gH’WØ(¦g‚U<íÍÔÕX4_ ±•ãùž'ÈǰcQ‰~UtËÆ6N­ŸÔØxSÁc<á~“+“%mÊèb“êéÓ„)„öû©8ÐY‰™<§ $>è šú‰p£l¾(ƒÔšÀHÊ™ GxZwáM¨-°.¨¬OG.ž$z/,ÇVt´Íg9.Ámivz˜͈±@å˜æG'-_±üÉmp’Ÿ1uSÌx=d„6 ½ÞìÒ™n»ÅHßOd951àåü§@Êß;Qâöêð>E…z®ÏÚ®56µÔjiF/ 4GLS´ËLBä¦(FÍ7Ô–<1•ÚeâSã¯%d´¾tj9ÿÛ²vj$[ªO,Ïò›fK¸z~r‡P-Ás¤{"§g%E¯'’³ºhSá`,í8»¸Ž)Ê‘cZ1:Ä'´œŸf„ÊfLb€Œò¤àóÉ€ ®·Ú1ãT° ãÙ«/ Š‘¨–ŠLÖSK}±Ë7>ý£ä •À¨º(¡°2€ÜP1釅Â=X¤A#@Lj Ø­‚í>é…„êf', ç©dÈBòÆ‘´=› yÁUNX;p¹vl”ý#ãýKÎ:e*Ã#”\¿Þ¡²é9PÏ‚ÏR$¥™RI ƒ Ý‹ŽáO"/.~ý pRP?ƒ™lbò”Ì^æõ'u‡âQºÃ÷+˜³BÒ âÀg&ƒÃ‡ý©aœ’ä•¿¬˜oÆ0#•Q¡ÝD@€À'[]j-óN `ç$t(NÏÇC¸¯Ã‡Ù :aîT%<_á9 ®˜IMzŒŒR9«­!Ô ¾™±¡€,y‰”²i Ng"ˆ`Ne~õê€(˜¡&¾@2ʹ…!¾Z–+È.BíÊƒË - ŽÞN˜Ó¹£°‡¡¯°«#}™ÌPÂ[ìœiÆ=îÖAcÅjmhîu.èÞY^f„Å;»vÈ9ðH¡åžÃh‰Þ‰O‡ÌMÛ¥†ÝœÕÙÄ7óç)ór˜{LÎOóŒ¢8£ "^ùe}_©ñÖVüêJ LÖ°J¦õy2( Á] þa–@ò(h8CÜ{„ŽCN|Nì4Ù,â·J¿ö%ýÁz·ˆµm,·Zómnlêgy­ø¾í4sYWÊ”d®Fˆ“cáZbš(~l¥5Ñh®ßϽа£|ôÝ$·#eŸ­=çÂ1¶v¦æz’ ?¯¬Yy¢Rox´iÉÈí£öÊÑ ï8eXý—Ïnî^¯´Ôû²÷r#ù°]`>1ÐΣ:–{“¥‚n*gr­ÜÚtév³zaƒ–è†<Âû1#sYu·2ÐÊÚwK³¶¬ú‚32 v„w_PÙ#ÅIµ ºù.&ò½¹¤Ò½¤%s–ab‰T¡7âRu©wão¹{¡@‘æË&æH|òA•˜êôLæ øý=ð†‰Ž÷°²Yƒú1âqÞ5žSV`¢&1PÌò9ò½ýê†/e\ë27j9ÖÎY®éUÅ&ži›aïÉ+N-³§¾PŒh@˜§)³ªgu…‡ª Ñ+«º4£A%Œè” ÐÇ+gHŽá¼è:†ŸTgâç–¯ìYÐúh‚ºU"ÊʪŒåMÐ@cym¢ âóbt–‰°ä§ÂøÌ褘ò“¥zr^¬\é䌛©)º~oâlJ'ääP“æ kF!ÌÅ+a ÆÖwΚ.$:9Í9¬*Çí7ß7Á—õF¨U"iÿ6«¨²¡Ÿ¹b,i`1‘sÙœ#‘9è¨;º¾¡:ô‚aP6Š5…6ƒžâÙ`>¢ë{¥ÊLäˆ:,_ªôœ ÑÉ£hü»˜çMØ¥`Œæœ…Âà?ð½ßCo}¥¹:qÍ-d÷Mû8CX* îÓd¼í´Úü4Ê ĺhê¤rQÄLV}´Ñ'{yƒA 5„[ [ø& VEΆFêá„açTe‹w\ kÓ ÖHî¨!k‰Á8Æë®q,Óà…%ÏzЪðŠ(ݾ&©hküTÎ,ÇŠÂÈ@· GкOn”«G½‘£K‰{îsä® Kd±¹Çnçgn¼æÍÒÝ-Œ6CêM6®÷<”“ë?ŸøA^¶K¡‰”.«ñSgcª°:¼*(»h¸¦áý¼™óêã{žÙ­ÞZð’ѳuáÂkâéž°V´5R&'tÛÏ¿$ŒZ*œ)Må± ì„eÉ—4Š“Kª³PQÝP¹>À˜Qž(ƒ‹Ïà\xTçÓDñbvq|[.2àƒ›Î‘'ÎÞ«²v&M³ÏW}*î]òóвQɧ~õ2zõÖoõeŽ¢I7du±Ý÷Ta¼Ãêhlòx_讯¿ïh\:‰qvËnNgÑŠ0%F¾ŒeKдˆnK®$»’«!ÔGaÖ¿Ñ$±¢æùYr¿ÈÏuV‰®87¾/r^ÁCÁV¯jbä¼½fdªLŒÞþ’Ægl>Ø­û*õƒîTìP€^#Wo¶ØØBòÎ,k[^YÑšº¡\7g'ú^ž6 ™Ú¾å&åR^0CÈ\ |+o ƒ°:«–ÇÚ`î6yäÌbú?Ú¦RoÎYå™ßµ¾]MK³¡åùÝê†^¯Y^ôíÖúRlõ_õtP¾]VÔ«y(Ôê»Få< ¾=€y-õô¿…b%œy|–Ï ò˜j‚j£žå|ÙÅ• ÜÙýüQÚ1îÍð¾í“£ƒ¿Ã¿ÿh‡Fendstream endobj 74 0 obj 3618 endobj 78 0 obj <> stream xœÍ[Ys·~gô#ø’òNÊ;`0—ßbWd+±-Gbâ‡8å,IñˆÉ%ÍÃ’òëƒ>јÁ’”œ‡”JËY4º¿>ýe¿©Ý~ÿøïÑåÞg¯†ýÓÛ½fÿtï—=‡ûüçèrÿ‹ƒ8 u±¥žšÉíœìÑ›nðûCêÆï\îýcå«nUW~Õâßõ0Nõ4ö«oªµ_½€ïbç_ªuHß¾ªÖ­ïëijWßCÛ«ªõuÓ ýê%Œûªò±oŒ“¼ªÖnõÇøÆ·U8·z_ =®ðC…S:¦Õ¼ú5Ì<ÂÐÕse6zC3e]°ô?þ·í¼Ývè}ÝÇÇÍUcÖÔ¸n›zpÓD}@çEü [ºb:ã·°ÐUäÎ]Õ®ÞÄönŠ$Œøõ ú6ØÇÇv×áÐ- ñ+O×­.c1& °Ëzß›ðé®Ò!^ܱ˅4×–©xÝ{hÓ×ð›€<ÜÞ9mQئƒ¡·z cÜ"Ly[év/›‘\šø¤–û©¯ûàŒ âÿ8ó±Ð¥7Õšvqÿã— ³­ ( æ`Û†ØÓ›CÌk;hö«ã8 <Ð& b¬Ü¹Îl>ÀBgB9ó…ÝÐóöml@HÏ 0¶¹L¦‘"„•lríÚºëAÃ`¯ åZ`,•:²™¹Bú¨=qWíØè°$ò öe´n :û ÷ ÛcÑÁxF‹rQwãê?±¨n=±Û ê6Ä1Mlëôhfdè8äÐ8Nšˆ#ƘŒØ»ºU=&V$ŸÞß´a+wÄE€Ía|œÈòä/\å"ª7iàKò™¢Eåâ „zŽô ¶g´Ⱥˆï€ùlj`ýÄ‹±kÕÃêm2b‘€å0Øõ¶BaŠ˜ƒê¦‘x„Ì@„d²ôªäóøØŽ©+‘áeÆM@KD¬à¦:õ›½ƒ?€ $ûëHï‘«oQyÔž‰x@©¢9ˆÙAjD¹â÷N¤ *ú˜’q½mH¿– £ÛBÁ•pi…̱0¡G. j¹Z$iX} ™‡ñä€J^…Åò9±ë³Wa´þÅÇIÀ‡Ä¹I6·¬ ¤ŽøAëGâºfD®ãct>bÔhä>nuø=|½ÑÞØ¦‘=Ïå€=›¬qDù*Bßiãyj¼´K˜F$Õv8f Ÿê–6Þkãij<ÓÆëÒBw²·úqU"o›öô­ö}ƒ¦3Íú&#O^º-õ•ÈߦÇãôøcEÏ¡AÞÑCùMynÓY·HB²ò[•Ø9|ÜÙݵvµÓÄìÊ©‘9oJ»ÙXLIãyi&³Òsí‘ú´ñ5ŒœÃ'%±\”¹eBɪ-_Ê $Ó©ÏÓÈÚx_gýòø2“ÏZä‡Úi4w¡b¸Íe!zÃúvœÔÊ(åηo“ãëü!â*êŽÑÒ³'‹3Ùf] .½þ^ߦÆ+ûºÁ•ÝÇ”cF¬É÷i¿H,>³ qC'™>RµCû¾(¼Ù s˳–wŽÜÜÌÔòÃöÜŠ“<®, cîrJær)ü£’‚' ]”Ö¶Ä5ï­Ä—³›ÈöÞÎ)*âã(CÙ̘‚XÿÍš€!ÍŽÒ[wÙNw¯ÀhYû醯Í"£·9tÎDPÉk´òƒ,Ò/µñËî0Qr“Øý®dßd;|È”VFíòµd­>Ħo-Ì–1ÚÂé}Fœy@²ÃÏ®‡P2â¾i¬Éø‘¬ßᢣ`6({²à¨ê’:%œ·ªŸì©ç&Ãß2ĹÙÁ¢#¨¤´wÉzì f–úY4è—9ÞˆÅX'¼,ÍIêý„hCŒÙ¦¤—[)It©ž¥I´1£ªhov°ti&³í{+ñç|û²1àÄÿÒHc-3¼kÐ’ìÖáMò“bøSAYÿÈèÃGG Y?Yg#ʰ&6mWb»ÁR¦WK©qÀ‘X~’XþXÐôÛͳ(fÂÆÝÇ@ë*™·›¤o™µ×ââîsqÛŒ£?óRæºí{,[²yÄŒU+K¾C9?Ó,›+HëÖQO¨(ÿZ-ì…€ÂÎòz| SîABˆÇ’ûàŘ}P‚ÄE)ð8Z2¨2ã .µ¨õJÖ–¨dÉóQ¬ëú>!ÛÖbõ.LNuçMñ©T¥B’ ÔöP T´½NõY ÆêÑ)šçÅ‚µ=Vs" #„A¸èïãT  ÈEmÄÙ¡pør­–]Þ©­õo?qPkÛáDS$)Ôq›IrÑA^»ŽRÄD iò•«»!Dùו¯;çÚiÕF:]4X}ÀãȶqÄKìo¦€Á& ¾‰;l½wå@´€cðp†× ¼—È稭!$`‚¡B w;ÝãDM€r\S»¡qÖÒÛ±«›¡¦îÛÑõ¬î¨¾ÛDÕ¢,lë!¾v>𥩽›¨©xÐ#Ì¡£$´ ®Ùˆ—¸Cßø®+éjŒAZôz”ÑÀa‡j˜àÍ škgqåÝÓ¤´m„þ¬ú oˆ*‰žò!„ Ân@X›½X±síSy?ò³üË…5P?W:&àÂÝGç@u*y²ÇC5/J–Ô“¢ÂŸVx3Û+ðýW£ú!;ºw¨dæ…÷ ßøèü(–4Yi¡´+ ~2*ɘ´|^ÙJï-ÙN°…÷úÓÐûÞ4^O&‚à n åêôt¬Ö‰+ÉȦåḵ‘bfµ¿èŠ>–ÂÊ62 p{xf*®~tN!æâ×ìȺ§±_@=’S2î³ú:Oø·Jä²ãÿ§@«œ‹Í¡–'j2$ÆOçˆ3ø ²€¹Ë'$´è%YK’³ÙP(иZË¡aÀÄS‹+Z]k1gDzî¬é è@Hq²tHQB§ 9:c¤s‡¸Iþ´ã`‚7i£ýÇâœ!@$¦ä‰ÁÒÒžþB½Oæ f×Îãd}ølujìÛtÄwƒ©:¡q«v**À'tÄCÖÖÆ tf`wxj_G ¶ø B"(ô Æ%Y¬Â[˜™¬¹ÝÍœ /ÙGÙÈÑœ±“:8Üô‹Íë‰n"…ÏNù0n!|ŠÉb•@Ô\ë›|&}–Ù8=èvz\IÇUá¤,uÇÔ* нu*¥ã56…£ªYS8ÃGŸùVÈk†öqvSÝ÷â3¡ù^ƒ<<Á¦ðÒ³sÞŠYÓÚ\]áw4Îy˜ìƒää|ÀkÏÃ|7*ØDÁð,–hÊF›ýUÊÌŒaßÌͳÄ^pLÃ[ÁÚN×yŒ5 Þ©&¨¬‰ê)R˜2j_' béž<…ÜîÀ[&84Lsº”5¯Í¬*FìÀ¿È“°=Éë–Ê÷€?9úTÕØÅû‰¬í)nt1j)ñƒ«7㨂Csð¾®øHs>øÙÜ 9’Ê»÷™Y3QZ,mP7¾îb“Д<×À™Û 3Pɲ#?è“{{¢‚M#ª;õêÆÈO--›íÙK ~ È£j`ûˆ”]’C–òu˜m¢óïx±É–š7½„"ʤY€,5sÂÉ]i`¼ñÌÊFsz-r•<`yþOâ¹%áÍ.Pˆ¥K× ´°ÐeÀà >¶Y,I¤ÿ0–äSæªs ÑÝ2²»÷ŠãP)‡ò~g˜V#²ïÞdMÞ«çï|bÁ¥¤M°U§ÞPò±Ü>ÎBC- tfá$AÍI*Íoj@¬fÌßÖX3ekº¶Ô}ÇùžÞO…¼<\èŽ8Ya9˜ÒŒù™ñŠPSÆÉ®-3Tëª$êÚ¤ŠŠª½“›Ô tÄ*ÈÐRrfØirZœ˜Ó ¾áô!×9à.Ëy~H°ØÔRF?†ï®Ï+y)Ta,Ú¤¬KÖfîŽ ŽÂum“_ZÒ]žc%^¬P¨–Õz+î" ÌÁ ¤Ê}Èxß¹‡’TeÔ<ç‚‚P)N˜Ð{‘À`™ãÓôjv?Î’)%Rq¼j\<¤[I3•ôÿ(vT}ÄllÀ2Êær¨F¹bSšVMv³kšW™aV0“EŸ™8{–óàd¸i(å›tá3.“Ê-Yz0)vʃømž,¤wk¹B•W yãP€Lg!¥dHȯ€Ê>x¤Í×Cï\k*|ôåîêcÌg£zÓ;T]Œ¬äŠc€82uó‚ñ ïfµkúÿ’cÀš2•Ô[²­RóG%Òì o?¨‚m饸ðþ,B[jŠ¿Väõ½*6˜¨É¸ (mI`çË£SìÐl<\Äâ¦TÿA†C­p×rÈ€H60+¯ö]ÍwZíeNvMëMmÝ“©î„dXu6•ÅÙà:Ý“­¸ 2]\FYèJ‹×^³¸ œÕà¥.ŒX¹pƒûßuÕ:î–*')G .Ý) Z¤Ùyö¤— ¡Ó%Øþùòþª£1ôÕñ÷æêsðíÂㄦM÷]K„†BÀ#ý«ò«I@Îcû}B‰ ag7‰•sŸAĶ®ÁDqו½ÞÏ/O êòö³÷ìÙãœNŽ×ú<“:NºÁ—R< û•±ËL6«çÛÁ¡mQÔì<‚oênZG‹ŸU´æÎƒ>)Ì:*”7ïæµ^ Ùär0Sfy@<ÉOæ‘Q!òäQQÊY³ý0èã8 ÛÚËBú¬°Ï+]U™²…Ý+'Hw”áN”G䣋A!p29–F†F '%*&²ÉÏê²ÑYË:+&¢†2rÐÄJv=˜š•pÄL]> stream xœ­ZYsÇ~gåGàM».aµs앪<ȉè(¥rl ~²S€ˆ) iýúô1=Ç£RXÌÑÓÇ×_÷,ýeVWjVã?÷}ruôæc7;ÛÕ³³£/GŠ&gîëäjöý( #ÕPj¶8=âjÖéYglUëÙâêè×¢/›-þ«ŠWk£«AÆÅýµœÛâ索†¡·Cñ¶ÔÅOå\ WÎeâc97FUuݺlŠ f´êa’%À´Š—¿-‡šdÀeÛâ=Oµº-~„#~@i=I;. |cqŽ÷|*ç ìé:ÍSÿ So@8× HPá¸ÔxnŸœ“JjáQëx>ˆc/¥>;7ÍM]ujØ[†M·-7lõ¦´Å)èB·ð Ð ¾Ø—¦¸†Ÿº¡ÇsЖÀtSœÀJ˜ÒàeqUS|FQ+˜É}k²ÓxO;nPÖÐìüG?–ðp…gÔ(ÏE Ž“{ÜÞ‚òº¸i;ü kÁ‡øs‹ËP¹Køq‡?Ö¬µÅ4lè»âŽËcñFÙÑq,}«‡¦j{A)ºq‡à7êµ ÐÙÏè$4–%^³…FAPzrµ ín„жb» áÆÇÜã6ìÈÃÀBÉŸð³·Áwx{,ñËLåÕ ‹ÏýBvºGgÌ7æàͦÅ\E§€¶f |p(bÍÄnŽ*ˆûoÙ`öÍ bNkÁPB°ãqâœó`ð’Õ Ä%Ð ëná±e/E“5 &]´½æß«ÔªÈdtCWG !ÍFwá·‹–V̧(’¦Ï†Ô 'ËÙÛS·o†s' ¼Ž…œ¬T+y'Þ7ñŠ÷㔜Ñ8_» FÜ ‡Ñ†Ÿ!$B[§±Ÿd>I†8Í„¢œêÛ$G»ö`Šù}”^ÎhJ¯fèÙv‡oWÖ°ø’YEâü޼™fbˆ0F§zµC-¢> :™†K/1Ó´ÄÞ甋i¡°=eðUÂ8Ñ ¤R_;£!M0´ÉAwQئµTÚD´ÞÕ-§vªd¯­T Ãã@­±ƒÇZ¤>ÕGW¨u]i+@½.M‡±@÷9˜”¡¦‹ÆÎUÍd8/ªâß°ú-Kв8BO#›¢è€H阹aµ g¬é6©¯@!£¹óAZÂsâm²IƒÈ$:Ž=ãðhc²=)­L]Æo'˜Ó®[‹ÐCR=7 É á}uYŽÓ.àáHB”o6Ö Ô¦žô.X@‚q E½F×W½ï5â6éQPiÓèWž~‡Ah¾ÀŠü}ŸpEŸàf„¾ùpYÔþñEz^¶7ûp•±­æ^—6·ºjÙqnMgÑ\Õ(e¨P*v´x1‰ªï$¡ö‹";êÊ@+P‚ûL;Ýa`Ô‚; ª:.nšPñj×Xtæ-õrMÝ£‘t>T£3¯‰›V;Èj>§«U×åzxhÝm7tÒ[ÄÉļPw¡ËºtÕ€Ò‡½ Ùu&ÒxS¼ã¬‹–6=OG]ŠÃ Q,ŸÈÓÆ=‰p™g÷LOë;°®¦­ÂÚMöñ!ˆà{T¸“»Hhn®ÿw£báÒg:W‹&­i·ˆSÌé}¥{%™ˆ•¶!GL Ës:l*2jÌùË`Íq9à= ïmÉ·¨á04J{OS$mtKˆÖä®T"*Ð5›—òuöBhµñåÿÚ´ØàØÿ{)´ZÅU•=Œ„ÛÒØ«¹Z-W7Z‡ïé«¡Å{ÙÐä{[0xŠ(´øš¸u…j(Ø‘~M–àÍ])ÂRèSÎÂtIðù’´ ¤yç·¥ðsÕÇâ^5qëPeõ·¸€Zƒ}/¹ßÙðU×eò ß2ØÖe䨳śN<ñ†€ÉÉ×Û'Ä µßyÀÕ¯2¾‰Æ‚OG‹ÉqLilé.˜@ß®{¿ú?ö~õÆ]ù}gœ.n ;BtÐS¥[zYA¯~XöFD°ì½kj¹ëÍרcœz üÀ—Kï>²K´’.ce;tÄÙùÛè¶ojÔ@/5N¢ÎËÏoc¦Ç_äV^ø§m˜>CízÊ%™¥\–Íò¿9}‰ÉZ~–^x}€¢øTÊ¿ #n%àaGˆ0ÁÐadç.SŒÜ9„šâ5~Üy©9?½öƒ«0x»Ù=„éÏ~pߨeðkÆjhÿ‘§hu` éMºä4!ÏÇ<”¸Ì;&ã„ËÜàUn0NF é.‡‚8ÿÅÃÒ_BÀ„ùÚÖ^Ðë\¤r ÓèaÈbè•çU¢’áYKÞ õΑàeêmÌðñÄwAµ>R-.i¨ÐeR5"\ŸxÁ—#Z"`ÁkÅ£§‡Iu™2å:Q K×Fðý ú ~ ëÓÊ”¼bŠÊÓoI©!œºßŠ_‘p 6Wªpƒ¾È>e#+®±*êãVÉJRÁFåè6— ˆ³N^ûÁ?g«CÒȼ_ìôWøñV|Á‹ß9¯8ÿw}j½ó««0xì߇Á ÷“z5êÉiE~ðúîC—Ž2%Ì¡~yLE½Ðšëô‡IŽˆŠ!DË$ìÒ†ü’#¾¤R2€:B¦·¬ XåpÚ©U@w~p—lgd7ýAÔM9ŸžÙãýhjyÅò)øä4öa·ªÆ_>.æÍM#­ºg„ϘԢÜå|Q`(‡TFÍoyóñ>v×´+ÊÆ%­ó|ÁûDêÇSv–ɶ~ã}Üdˆ=R;ꔟÎW¡»§‰1 \ž›V>hÐϾ P<¾¦¥\U5MÏÁo¬B#ÉÏÁÁi.Ósç{Ì«ÜÊ'ûhì8ðý[âY¸‹,‘ÖäëãÇ„¾tŸSrﻦo‚å‹©C#χ`%a–ËÔ_ão»¾ƒ  Ëž‘ƒ¢«ÙÔÓážr—$¹¤Ã£¤çú†ç¥Ë‹®|rüÓ«—ÿ®Ý:ž6‰Ò*Œ¶áqHwUŽé¹Ó•õoø÷BAÍè’9pÊß#£«»¬á,á}ÓOÿÂøŒž•ø¢ò¹|ë“< ¥rl‚²JS?¹¹¶×3úÎo ÍÔCZiB/«kYƒ&|Èíܤ;™–è8J=eJ×(døð9’õH²ÎKFqiç?n$×/ôöÓÔñØË,Î6_Céü" DA ³kᆞDL83$çúËH!þœÛþ»¼ÏñMDR¡Ÿ÷|~¸f>§Ê݈[XjxÙöÂn'ᬠì±bŸ/hÙWHqvI•‹_Ød«©¯‡hs¦>ûuÏ&gw°!÷j@ån2š%ÅIܺÿ=«‡˜ ¡®‰£J2òw~éa}·8úþýÓ:¯Àendstream endobj 84 0 obj 2715 endobj 88 0 obj <> stream xœÅ[[w· ~Wÿ„N_¼“j·Cr83ì9yP|‹SGJìUŸ´Š$_Krl©ŽÛ?_\œ•å´==9]¯8$>€˜í¯»íÊí¶ø_þ÷ä|çÏO†ÝïvÚÝ;¿î8z¸›ÿ99ßýb ‚ƒ‘Uj“Û]?ßá•nwð»CèV­ß]Ÿïü¸ðM\¬¿èéßå0¦UûÅãfé÷›¥[¥4viñ°ñø žìÃdx‚_hªmÃ/_ 8oèz¿êA…õ)ˆMMä9Ýhç,yÒ2´«Á¥Äsï‚.½‡Iiñ /.ðƒ¾]Áˤ?ñãµ>ý'~œziÄI4{ñ2FMañj!ov óiÏtð¬i|hwUbpð½7º¼¬–Ã"³à¼<;ÖÁõÔlïíáäy%…ôqîCKÇy=·èBÏæÄ¿-'{«ƒÇeæ¹¾™àœù¼<¿®$á×.Œ‹“JiùúªA·‡a\ùN°pY]èLœ¶ ]X%¿»ta{D,N?Eg]ŠáÇÅÏø÷çøáðcÏ:'»ö·ìô€^ ‹¿-ðÓÓ×F¦£@Âv$0¦q"î"ƒëwtÅ ›b}&ç¤ÞêGñׇ²å+Q€­P¶EýŠÍeðOeðg«À²Ò@~¦ÑvZF¬t¡ZLU¿ÅB  @ ý°rs¡þ^O> u ‘~>¢o²[lGšsU¹´Û¼yÏúüQy¾ÖÁ§U\làëf3)Ä`½.ˆÙ_¨îh- ¯~x¸ZýñÎú³I8Ïz%(T±™«å¸æB¡úZ¾)UãÉ+Eóç:Vl» ðŒI±Ãg6T6‰è·-¼›¿á¦òÜ7ÀéÎã$”ðD'u.x-ÎÙ>Wj¤7–%„bóIž1qnøºæå\ú(öÊ`È›¹ µÂk‚_ãÆÇêäËzŽ0JàÔ8ÒìK…ÍUÞV4¿œóȱñH®@ÆÅ/3<`Ìö~nOcôSÑf0Ê~‹½œ_=ƒÉÛ­„UèþÖWÎÿá“îNÑì¾þ ß¾)-'Ëà‘>™ÛèŽE½ : ¸¨cm™Ø¬ ¬ïèØzΑsøGlÄ€¸7úü6Ç—s!u=¹æ,ÙÉ@õ¼™AÀ®É „b<Ç[ÁRž]U°™)ï®g—m/”u7Äî‰"éRÊí2ÿsŤ2®£ õÓzúFŒUÒrRÿX`•mà•ñ¼–ês¾+^ùé‚j×’°l¶Þ‚Ý8ÐíÉù yÔ ØÌ'¿/M«GÊ×ÿ•±DëJ©U•¸ù¾ WYp\aé*«Ž´·cëØQ¾q«$Ðá­{ îÞKç úŽîÝ«èDZ ~5ô0ê Z¡q c¡ !’ÍF·¨‘™.t®éWð¼í u2¼xð "¥ ÃÜ­é.^å/›´ã{0‚ÈÓ|A {P$B€¦­ƒë?دk…#¸#Pà[ÀZ=Ú­%5zD5ÖÀžö@c!Â;4^¿øWƒi 2bÛQŽ›ŠE•ž±¸ª£°âe½½Ç)¸¬c^MK#8kO§ÇNk¶1z0•0c\9ï„SçÌØj;éh€ã&Œüà=ºC ,„"žóŸpBò5õ¥Ñ;+åÄæ ›¾¬(ç#CÀðH8ÊÛ”‰è–¹eÙν§01é`FÎCñØWzZT€?ùΘÍR_66È÷´:Žè-¯dïäûr(š®í#¼HIŒutp2`08´ñfÆqL×ýd< ƒ‰2ô†ÿø~¿¼f% ÿçpȨ—yº éÄV~‹8Z¸^¼Ë9oFþʯvB™—¹ŽîL^¿PsÀÁæT•˜s¨ÕQ¼A.¸žŠ:!`ÄÔ©FvK‘GÖ¶+@{So¢ø:c_QÃñ´ÌËÉ2„N-Ì{3#,—-9²ê¤‰Ž·NÈVS­8+€tÏi逞Âñz²Ø\ÔßH–Á‚( äLnÅ}8ðy]u[cTvCn<ÑyþscЇÐÓŽGêKşΕ-CÏí[}PÁ'G jXµ|œ"3b×rýÊ+ä*ñxPÔ´éD„ð?¬»·ff‰#Ã4QŠÊb±"¦½›ÕJÙ†•YBg·ÓP³ÔÇõs®!rv¢ƒö¸#ˆ <‡e!•³ìB! . ûB6{DTÄ"s°k9ãÀ–'¥JÙ 1'B…«Ý@°”¨#/{ ¡®¬ÝFC9GâJÖ×4˜jr%l1Ç[’Ë(_ÔåFŒp˜”\dJênû‘̤-‚7á&LùÞïH*)œUGV~|Á…Ý©ç³^…½÷†µZ/ j/çù’AÉæª3àsIpB~£:-8¾ˆhݤЃL5îrgó…X“MÈuœMq½‚1Ñ­¼²gvrøF„}jŠ4JŒÔb°þg;ÁÃir*j Mr1HçÌ]—Ó¤v"öÁ2òFì™ü–õEýd‹Ù©ÉJhNá‹sr‚Ú¾€ö-"!¥è¼µ8¡ ¡ŽÔÿ¡ŠüxL†0ÙB¾Â£îŒä‘°òÓD'ÕI©•3ű ¦7B±{¶‚V?™™¹ò¿ϰ³Í9îôs/­7/Ÿ #ÿ»á.ô*ðˆ^†ž ƒ6<Äú~¦}ß8pîO»àŠØÑ Ñ#DÆ(vw`Rð̃‡Jßiš{Tt“ܷ.ÃÐ.î4ÞT8¸yO›˜Cc÷=~ÏÖéùXòç!¿ð4OCŒŠ"K…g(ÚSšÃê‰Ê86bjt~¬¾£Ip9õo¸SïHpÉV­)óUœ[ü•£ón”Je„³ï)Ø÷hs$M´[vw]<åj|Yg“»>ð÷`0;=›-ü´TU4xcÇDŒeg?Îzˆ©ªÙûˆ¼€R#⢗wÑcàKâ~“Zy5]ù1¯W<Ó²mʧG•8j|‰|ôP€¼'µ¡[|¡ñ{ľëJÍ´à°¸ŸDNÊÙK`Ïâ"hô§AA¶¬ÇÇB²L#`/sî[§ z¯¸Œ%éÃ`°ô©¿÷›1q¦ è÷„ðIŒH8ÃÖ€ysV`. L‚ñqõ5Dî?ÜU×–ûЮ5ú‚Ö…Ò“;q‚:Ak/%ßäß>x[mšøyP»èn1>¢ŽóØzvåaLlñˆ×êZw¯ÔºÅañè]FZ]ã|üø‚nïpYiè’[ƒø17,â¶´Àñ‘ÝRPÁRJ8މ¼` „Ñ£|CñŠG·.Òq*ŸØ€ÏÛ4Ó#egëáú `òB¤‡I´di 2FáOl‚ÙÝ×^§fm‚'Zœ85¾dX’¨ÌØ;â1†šóžupÓ:òÅù}ZêêÛ{Xs‡NjÈYé•ÖCˆøÁç)Ò2Ó'pIP,6·ÊšœÁÆ,`jŠÞ#9¤hQñƒÛL³~$³þÒ¬ªÐýR"OHÏ‘Š~H$oÃÙ—%hÖa Äz¯1L-_ ¦éÖ©ƒ5Âà÷ż9×grÝ#EÁÖœÉhÆ[þé–%L¿•*¹W¨ÒÓ9²§ˆ÷¿›ìMDó=yPM¸tžBᙜ¯x]«ÉO)«BÒô5ãsr/žIßCãò謳kÐ=–¬yqíʪ$ÞZ çÖ˦÷rÊû‚ ]I³R…¹iÔ>¡%[‚õþ„êWœ“ä6„Qä_=ؘ*ÞT-ýÎâa6²CÇwZ:ôpÔ³Âöëô¸_,¹BÍ0šÔ‡ Ëù=£Ì{C7ˆckÊ­5lMÁaò“{x{æ6*‡é~"GÔC Ú§ùî lµYfÊqgŠMÓ\÷½Sßç:ÓG©3«û =¡;õFýz[ªÔjÁG¶p)˜Qvt¢Yuÿ3Þ¾›%çù-‘…žDµ@Ä&V¦ ®ð7„išÓ=FQÕN454j;ɹYôL “ßÊ` = Ëfw‘*ým°BXOÛˆ³\^Í…ÜCîÌÌÜW} °NˆšKÏM÷.Xƾ”·£ÔäªÐ̤x®½©p'AGïYBajRIqÊåTZ9­œŸÉF]• ÊàÅ[{˜·®«ªƒÆ LcÄô°Q†ÎiQ‹º-‰|Ÿ ùÝÐùx‚ÄíQæ—uI[§#Í~@ê5ø¡ŸãŠjoaÛ\ožõH®öÆsT0RŒ}j*–6E4>õ™#)éÜÖ{y“™E¾Þ„Žß+N(ÊMš†Bží˜gª#צ‡ºÕÄO—›±“»k]š‡D)ô\Ùcã Mñsîì¢Íá~ñU}óÈýÍ'µß­‘Ûc GZâ”±|ƒëK›ð ÷4:óþ§”D„¢ŽßØ—Ô,zÍJG·¡Ú˜·®Ã´ÄT¾LÃ=§X À¿ÑB\Ö²ø5ŠÓ~¦h]Ϩ¨Ü=SéÜÒéc·Ø¼Ó$Ÿ½pk$$&·©Ž3H9<ž­)©Ø^ÔRÚÄAò[0 ¡Ûv¥4ÞDÃfY\îB¸í´µhîžq´é#÷Üð÷!©œ>pVÊœƒNÆ¥—áÒr ƒ¹v cÒŽFH[ï6‰oA·Î‹Ø^N­í—Ø ›ÂŒòÁ$hŒÈݾGÕo§Ù¶³a³ºŒÉ`vv®r§Ý7 ‰|ÍÐäs¨Ð‡¤EX•,nêZȺÚÓß Tîjýù”^°R}rCç?/ËÝ~ #y§l¥*OªöÓäEÕ_?ÿ‘ÿJ÷×;ßÂÿõendstream endobj 89 0 obj 3731 endobj 93 0 obj <> stream xœ­\Y“G’Þç^ýˆ~›Ê5ªÈ¸ò˜7B+ft ™Öl›n®IÐèøõ~†{fVÓhÆd¢»+#ãôãóÏ=êçÓþN{øž¿>¹ýíxúìíIúìäç“€OùÇùëÓ»jƒë'‡¹ŸÃ飧'ôf8ãé˜ò¡§^Ÿüsº²ë»ò?¾¬o¤`߈)æX_ztQ~Úíóî‹.æyÊóîNw_wû¸{ŸÞíåÁ·Ý>¥pèûqk߇ú$†©>¤êã`›ßéæû¨o„<ìУ!»¿Õ!îCoöv¯KõgJÚDûÎwݾÔwÆ1Ò£¿·G·ëê¸ º¬S¸×Ewrãøž†úkŒöyëŽvi: ùòa“ö¼KûÔÆ0Ï´Y±îSsÈuýñPBHón¬=†8†\]{ S)awÞ%hZŸ¿ìöýašRŒawY—Q‡ˆuƒÞt©ÔӦݯ]Ò˜j¯¯¨×)îžÔ߯¡°»hï<£áë‚_×wÂ0åq–óT{¯c†ºÈwõ£>§)íÞÂà)†!±(xáɡά¯¿~uòè¿þIgþ¼îUít_çS7 LJ¿óî}W·¤ï‡‚Õ©Ö5”ÝOðø5EÝÊ€.»8Ö9ìSýMžÂa×ç¡`ÃÝYý¬¶j÷q÷;Œ4æzv®m®=pŸmF8\šAn 9HPÈ©î`¬’8•ˆÃÿRÅû¡·¯àíWðöˆòöÔÍæ¢aS|½…Ô½ªÛý¢.öþ,$íNÞXW@ÆD¼@þCÖ?¦±Î6?…xˆYô~K:ÛðN™º„'Môõ(¢_<¾áh˜åc•t8 y·JÂ;òsmò Èë<—@Gy¥žÕ¿žÃ» ¶µ ³(4ƒŽá˜gn/ýÃR÷¼Ö}í ”y¢%Ã˸»¼é8á7( uë`3¦OþWØOx`c9‘žiÀ—ÌæÀé©lÊ>Œ½L M3J¶Î–{&ó€qÿXJÆj¦UÝš a'ð&8‚˜Ñ)êç(Xøn=Ø4L(kùžzœ‹K_­‘ši+,U²Zà2öµ‡ÉZºç^p†·éi“.{‚ A¸Ùü2‹¹tÛr«>í Ž"J0õ¸±tì¼L£&eкÉÍ•ËÅK·ºHBC+¡É,7ç¬K#Hâ„FW–G´*4B¨}‚šŠ’Ëz̪ƒÖIáäÎÌF€•D-áÙ3>jî>úæÑÄRg]2;˜áŒkfI›¤çŒç'Jj¶äz@+fôìm3(¥mªÆ2¡C"›ÎZí™U±f•q—Ô6Â2G2„Ntã4¡š±Ö¡LÆ1ãŤ¹Ð—«Ø8´ñßñNájÈðÐßœP˜>[jØ<#[ˆ&– ¨y˜[3]Ä­Å€ÖfPÓ?ºÌÍaÛbµ-Ó$ê$RØ6úBÆO»wÒÅ% _±æù‰ÊIÚ¬0„RO¦èˆL®¶Œm뢂ƒ8ÀÇÃî®3²¸Æ—z‡)9_§êjLÿKøµCzw«y»Ö+öئÓDYgƒJÈûä-7@¥Ý_jÏã##OA (˜¸2é)³<ƒ)‚f_¶Ã›È†E´í™¸¶»*i0BéñUE"F)¬¶â3T±lØ2ã´šŽª`fr ÈCoL»¸ŒBþæh—êjÐÔ?#‘›+*ìƒÈÜÞ:“KÙ$V/´€JÁq.¶ÄÞ#òöÄŸ,8¥ŸäMWOº‹CïĈiP2€/<5²\3°™¨ÒA¯Íïªù‹ ‘j I¸xG¼‰_¹û¹Ç¹1ÔJ Åb"!AlMQI„¨|ãØ¥*³bZãòÿWìÌ£:ß©(Pßvÿ+îV7Ÿ@öUäñ/ðjDÿ®öq…3ÅåÌãR”i>š¿Hß×ýCGDŸ‹¸Ïa%— ˜˜­Éóf¤Iä+Vk†ø£·rûÈ®9Ieú9A7³5M†H ? O„¨ÀLˆ§ Ú¦½¼dX7•}8ËN¶fL¿F Æ»áñåœQ~Ô‚À2 ø«óz*~Së*BÈ%âÛ¼ œÊ†Øš(t!äHBs9ÐïÚ,lž“•œC“@6ý¨ãxgVPÓW¦,K²Á…ȹÕ9üAâF’5bRÉZEßÐÚ¯;C°[ý¤óá‰qe9 TVn&\AÍǘ›Ù‹~ñÌ ZJ<¡o!F®CœþPB‚‰ÖŠ‚4ˆÉBÁб„‚…Í“ „~‡ù„ž#û¤Å%Y]]}ŠáK}+δ˜+òO‰$èN&c'2¹0,Ò5ÂháM{kÃÂè4<ÂqØ–;ªF5Ohȉ;U%‘y cuL<Y3õ—,UÂ(B{AÓÆæ T ¤ í§M§û ýcìÒ™1ÏÍY¥4à vk¼÷z%G…#èüOøìøàʽˆY<ËŒªNát…çGÀY}–Ö[‡/•™­®ÁùõÜÄÏÅ¡HDéÍJ,¡á´Ï9ÌZ`µ…°^Rª˜"à!ÞÀŒÄ‚j¾V žU±÷ŒÀúCšÕPñBbu@+  .àsUôRJF–ëÎÂp“Ñ€ Óì¬/Œ7…4ŽÄ15Ô¬ùën*A¼3ö}Ñ¡[|¤¹ .ÚïV§¥V3ˆÁFbÂ`tÅø‘$„ƒêFà4Д4L›¼bft‡¶×à9ˆÀuΨÏlŸu¨ÒÓkvr× ¿òù… 5†E”ªNÊá3èÄ…“[ñlahJH æ«å¾€‘™;uX&–ç€Þ-bgòLñZMu]TûŽme9Œƒ•kàmBÄI>Vêáwèx@{üQ1ižA&ægL ® Ÿ8®]<îvä²Äu¸po*ŸK©–J¨zϱ=?g· ˜6„nØÏ §lM@ì­†BbÒLγŸPéopžŽ9¯óJHÂøCô±tŽYx†KÓn].¦î ÔâËלˆ×Òž^µTõ³ïë¯ ¹ ÂK_Á„zœP]­àgŽ*k{&Óðå3nEFšÞ¶Q¾‚9%¦îw•È…{­Ëµœô&³±RÏ•f¦Õ 1^@”v„L…¨ÁïÄM憇 "4X[ö½LQ :[¤?>*ÑÓšƒA»>.3 /MˆGë˜ÉÃÿFt)ÃÒi/ù׫E =§Ã4Ζ¼†•åŒ6né{s Â%žvt›—#,PœõB{™ÉžüÌæûºŒ_cÃ\C±H1”_Ó¥…(pÐæÝõý‡õ'üÁðçª" Ðü‰ì~.¹T¦6Ñ•Ôr§s„ËrÅq6äZï–æìq E@ƒ'tSÖ phå&•Ë!kêJÍ)§‰ä4$ÙœÃR'ùdsš|ødbzcL­MØCÔG¿9ãÉyÀSÆøïh¶%e‘¸¢•zÿb]A.£ªÚ+Þ]‰!±0\È £ÎAb.D†¾ €“ÂX–Â3ÁÁ¬Æ¼ÆÄLá¹¾¡XVÌNr¿r-*9úèÇ_à#ð,Cò!éši_­¾¢Ñy(7Šþ‹YÂ'CÃaÈÊ>^zé§ÆœÐí$—ì Æ`Ãu§b…¼¬'´2Æñ´'œŽÀÔMs-2I$’œ¥Uzqò4K=ËŤ†>Ì~¤y\…liÎß} ]â@\AKZ[P=2ú¹µA&AU½xó+æèHÌ'^°Nl¥›£•rD' -_®lá*ö¤›§ Š^X™9J&[lLæXà±Ísvn(ò'/k-Èw"obò¾+ ѬÈÅUçYøµkUéYEÖŠ0 í‰Ç0Bwä>“eŠL¨{Œ(˜ŠjĘz ¢Ø×(‡ÄfåœÈ3±,r‰XýÓ\Ý’ƒþ ${Jùüå}92|v‚ïê;Ð["5FÓß°hX•‘q˜kh¢XŽdÜ#¡±eXG>¯6n$ç‘0Ê+úŽyñV¢½ælMŠ;Øä<5묫x¬ù­q«¸éº J?W ‹Ï®ìÕcÙë—ý_Z€Ú¡(ÌŽ¤iK|ÒE‡TÒFäD‡Lóq]ç3m$Ÿóð ¦@U s}N™L¢ògõ+dÂ뎡'òi2uvœ©ñŠQNɾå¸)ÞgüùÓM€¼\ 2o“4ß šþœX3ñ„«÷ÂÄ´‘,Yô–RYff`úRÄûoÒx }™ÅÈRÛ=¦Û/š#HèGX ,•$TÖ‡)˦úLûSó%#ä–§<˜â¡W€Ó°µHVOÛñŸt0$Wƒ‰Ú%å0K™É¤ß´Õ:?× ÍÚ(}²uÔk’<8_µ(%{M³‡º†³vÞ¬Å9¸:”ñÉé…ú4ÞyáÐÿÒ5Ò¶x×( æ7a üø6Ÿ×¨iÆéà~8<™¡kÅHZ(“jµ.)÷ÐX¬ør S¾{OùtcÉ=Z§ñpi†9©4ù"Øßbx²•_®Õˆ(Â⡬E+Â}bŸÄÜlŠ7f»ÔD·X…öÑ…•(^=Hqfjdÿ¸‰p 9T¢Aá_ÍቿŒE‹æèç4]µ#k ‚¹i\Öª >^*zX4ÑB½©€]ÌV§qfqŽ:’íý1¶¯åYåc-â`¨Iƒ)¸Ø°€ï•WÀ]ï‹Æ–޵ÆòØyf`q s½4U¼X“,ŠW/·ôo¹¡):ÕˆiPô0¨s5 £Çõæ°nÕ–9TwØ,?ô¤1§’nV¸“‘œ”4qä½ð£°sC+ܶøZÑCVdN „E†˘@˜Þx~\L/ò"£I }!s!ÓrÄã=FÙuIâJ*v‚ËêðÈHoçcÝ…²m§a"Ì¢¨kif±êl<"ÄueðbdâSš<„DN×pýE‹qÂ2iÃì¿E]QŹ’ãóäúF’‘#ÙX–‘,¤{E±”{¾6Š%ªöC6ûúø5Ž-ÅñHèÍœô±2Qe×ÉD¥˜ Yeœ]©ìð^7#6¢ŒX¹t0ÈÒÖ-«AR±âŽ<,Æ·ļrõ}œéP=êm7«y&N.SãZˆ#˜3Ä7H)â¢=n65e×ÛHòãý´©—†…/<¬Ý¡¼Ìó5ý½Õ=L6mßÉ`Qa%—©ÉÕ2ôBÈ¥žÖÖ%xHËÆrÕSGŠ_ ƒ %}¡CÁ+†TÙàoÂÔ`)yÖNõ’!ÎlIX\ƒ'o´hÀ_çu‹Ä«j‹ª;Þ}‡Q¶Åž4?H™º¾ˆ§F­ßïˆÊÞBXƒ_WUÍ\|€Bë;«’n³½p-^†¾Õ¸BèWUN½FS|Ù•¬7t&\4u×@¬W_ÏINrã,3‡»O¸ q¢ž¯³Bú ZŽ¿2öºÍ ›…Ëb8ÄȳܜwZZÍŸàâ ”øR* ÖƒœìÅMß BE.D»-5 >,âÜÓŠÐäÿœ-^–3˜ã@/±·àèôŒÅÉá¡‘'øÜHí·¿Bu“kÕÂã 4…W.‹}²œâG…¼´…>âõ)€sëpø2Ž»"*§u5É*Î]X@¹j¾e¯ÐÈÏñƒö*Þ$¦K$ƒõJz«Sû²É^#Ыºûè3¦=Ò/ô²°vàyó&´É›usM¶q.T9Œ‹¯õÞ YÙë/À®&Ï Íl,~ÒjÆØÊ…ÛxM;~QEÀÎp¶INø¶O õê¦äDàüßåÅ%YíÀª- à5{Ó¬}6ÜÒ±äæ‡hÂ}ÆÍìòUV ¶¶ªÁ¶nÀ”£…»Rsx%ø#‘‡6ÄAêSrv! )ŒÈr(HÜ"ˆ§¹Ö›ðÊ*dÅ–©–£¥µTÀ7¿ë+»ïÙ°îY¡ð´u…DDU,´¹Ú¸ê\”é‘M™+År•äÐj¤<Ñ©¸W¦¸¾ÀgˆÁk¿pC’ZGË–3ygHüv» 6 rL¹ éN(—OºìKw_J½áÄ$ÍC3Õ€ ¯?›Z¸V9–¸Vî¤ 7’/2ï]­œ;]b;ÜKW]›I²%Æ-³»(¾m·h”Æ~[ê»KúÜ^ùò‹¶aG¯¡º+*t[sT³.1Ï'ÝF?ËÍ‹èpÑeÆË†VªÍÔsOÇEgqŸÔêY¸^vØDnŽZÓÛ/¿gÂUê†b%*/<¬6E&¡—*\X |q¬ŽŠêÌ-°wzÁ3 õ³Ü•Æ•i„,j=ù»¶‹À›Õ[“às’ª¢¡Õ¸¹"ü¢’ب%ñ씣Ȇè×û¤"¥$iÁÜ'ø ®ÛW¬`ÉÈh4}´p@¦êÆ>\:`w5þx„ǾÃß{ë‹°kþª‡çCEn[¹uZÒa¥eóÇc-µ"pEÁ.$[}_Eôu47Í ‹Ø •(OÜØEô욎òtYæ¶rͪ٩uÅ”´û/VøT+¢­ëŠÝe…Û&Tru(zÿPe¹‰ Êâ£nJ’poåùû ûBe?äRZ·b•@Ç}ë¸E»¶óêëobÝ% {X°ÑjˆaÔ [Ö/¨“Eñ¾šó*U½Ã^ãξùcjÕ¸çàŽþ‰ÊZ šÒÙ¾¦)X‡¿ÐçHœ~Ò±›žHb›(S|€Ç…ÜÈãrC6´ŒIû{LÍE7wuW_la.8èsb:)5¤)Í¥†Þvú…Q6#n=ƒM2šªjE‹’=ÌOº,Ø€Ï|sòóiUØ¿XnôQœ†þ0L§¡¯cN|OÝÝ'·<<}÷ËÕ““Ûÿ8 '·¿€î~ýiýñà³Óÿ8ùüÁé7ùvqš9Öa™¿ÇŽ<©Níb¾ï;W褶¢j®Ÿú )QѪîak³µüÀ|Ëû⩞諭ªºÝ~!UOœ¼û‚#sÁ&‘­Åƒ üö1H°:ùø0çßL$潃mhˆHr·ÎÃöu]ùŸµ¹ýæ×ñØò|<9÷§4?€®ÿZ™¬H*É7'ÿÇ®Œwendstream endobj 94 0 obj 5678 endobj 98 0 obj <> stream xœXÇr7½Ó?±ÇA•v=à”-­KòaÅ¥HšQ¢é¯wt£±´ª\,nÐèððúa>,ú•_ôøWÞÎ÷¾}5-Ž>íõ‹£½{žåíà|q ¢‡_V¹Ï~±~¿Ç+ýb ‹)¦Uëó½?ºà†nåB7Ñûršó*Ïc·ïâÐ=pËÔ=Á—ç0ã… 3Œ ¡{ãR÷Ô-C÷_·\ìž¹°Êy†Åð³Ç)ÃBù´F;¯ÝrüsýœóÁ:—†iÕÏàßz >yðþqⲌ,c¿š|Î@7nrà4nkŠjh)Jû¿¯…ÃÔàIè ùJ¯FôJŠz­®J2d„ö£€ZxÈIÝ ø8OŒg6²qÍI1P«‚Œ÷QôKá­/Hzþ*`›ê+–0‘8r…A‘wŠç]œåŒ%Š« 꼂:!AŒµÂ:)©¼ÂùW¥¢WA¡p6¨"ãkP¤0€O•® )B–å'± NAvz\áÃL3+æ`#ü'hDgëN•læ$p+(ÍÉ·1™0Ëúcݬ‡L½§Ø²Ýxîju n b,IŸ›pѓ٢˶ÄüÞY»Ðä‚_ànleš û¨ô¶’BÞgÎ¶Ò 5‘gÜk '…Àn13=\DåÂ*± îÈ“QÒ°$÷Ì?ºPù€^´]ÙÎuyǧTÁª{r"ޏ:?*Ùáb““—qÇ:ȸp›…LFÐx¶â’†5qH¸ðœARŒ*#~ÂŒi ÚW /(¤‡î7—{9 'K±Ú6…NÝ€8˜G™„ h3¶6.2Êk[àÝcvÃSR±,g^¡¥×òÔc9áZ9"ÚÏPγ*šuJM›¼~ÊÒ‰M-¼dxè ]k7G¦?CjÛÒ±HæÌ¥7è%Oü‹!˜SÙ§xbÑitceõŠ´PãÛ*Ñž´Îu¦ÁױÎ5öÔPž0jà$ÛýfÞ»Æz,ŽûŽŒû3'µÞ1hØ‚Ô×\sl“oØi§å¿ÿƒ^ã€Æ¼‘%²|SD©ä•“'=ŽCl‰†Eas¾½U°\ˆ&)­è°Èið4Źeeœœ|hÖc;ÄÿK æîo,<®œúÚç4+„×]}Ãö‚‰n¹O¾ÂÍŽ U¡sí\'0G¼Ú9!ö;‹Ž C(MžØQeu¬6DÎóÎhxÇJ7e¯LÚÄlùjjA‚î¤L€mC(²b=Ä’ ­Lý¦€FŒµ[Ø…ËGmð¶J6´)ª9´¢i(4Þ¥ 4Â7€Z"‡FC¾s´Ç§Ùp(ˆ"i_ºH0ñŠëBI¼}WpkIKbEnÈž¢#gÍEj¨èñõ3eÓo1Ü5«UÃrÈ}c0÷Öµ'+¹‰‡Ø ÿ¤T ¨cB• –ÛSßÐŒ¹cÑy™gì®;ÚZ¦aÀähJ«Hžák]x`äöÐ\Õ 9\'ËT-ól[lË¥ËRÚ•>UN(-á ye/¯wo{…f÷ûD¼¢à¸â¶„ &5ƒÔTWíň^ðv J¶´‘8r$åiZ[Ó…Ä?Lૃákç⻄ øå¤Èi¿òÚ¿jŒkxöæh.ŸJí¢‘ùG`Ì7Q–Â? „[ã¼ÑQLDyf®gš»©Ü"ýÞŠ9us{)¿UæC@÷žªý±óH¡8·\IMÉhJoÙåÚ¸øFU¾)w)`LtÂÂëR‚Byªcˆì#ÓˆHM}DD47ï<»-o{ɘù°(—k•>PúºCbíbb#3^‚å¥ÜІîE†Æ#’µÀ¶àù &+àì£~´Æ]¬{ãr=ûŸ›ÇV €óD<û­‚ªÏZ)-;Ìø2£ÛS®çÖt¾é”¾;Ì;·³¡WܵJªÐ…ØÂHRæ0± @ÉÜ“˜»1ñe Ÿšj®êª+Ë'Eo\m#)Ù¯æ ‡UF‡öÔEÙöŸ†N Èõt]ÝE­÷-Õ‡©’E1$:Ö¿*¦®õ|°"Þ0ŒB\ͳå-{xÞh–³ö&i3;t¿ËÃÀgÓ´¬jiÅ èÑzïgøûo„÷Tendstream endobj 99 0 obj 2004 endobj 103 0 obj <> stream xœU1o1 …÷ü öÛ¹Ëe¤Ðv€–f«:Q•éÔÿ/áÜQqȃ#~ïY¹@ ±Õ­ŸF·:f8ÿ¹gwqá q(eH×$øN^°¶ù†ü?8’Wåcn¾Œgü\_S‰“‡)8õø:£^zÜ[Ä®¹ “Û–Ôºjj;²Ô|’ïL“³ÌèpG+;ÁrµYÚ [’–;<ä<:õöYò»]û¥MuVW=ÈQendstream endobj 104 0 obj 226 endobj 108 0 obj <> stream xœ½ZÛr·}gTÉ/ð-»‰v<¸ NåÁ¶ä’Çq"æ!e¥Ê¢(S.‰MëbåëÓw³³¥¤R*®vg0@£ût÷éÆüt<îxÄòÿ“‹£OþžÏ>Ï~:rtóXþ{rqüù ˜ý8L“ŸŽO~8âÝqöÇ“÷C9>¹8únóÅvç†qŠó¼y¶ÝùÁ{ÂæñvÆ9MSp›+¹\üæÕÖ Ñ—©lžÂ·Æ)o®·»óàa‚€s…0;ÿ¯“?ñòqÈsv¸|JC e>>ùúèäwßm>ÃÇÒ0‡yó%,ææÑÇió\…ï9lNhÕ\`…‡8~·ùWÈir´î87•²ùÇNó8¦Í~ueŽD„.¡´ƒY2çAUC ‹V7^Eƒ¥#*c‚‰ýæg˜1Å¡”@_aÚ¸y¯¶î¿Ü¦Í%Ü(~]ÚœÃO¼üfx,>”3hþ7§8-HÃðþ8ÿÏF˜*Ìø%Ô§ièص ãçBòàÒøø4 ežP¢acÙŸâ‚—KBJ½O“¾†AðÓ{Ý ß{mⱈ`¼PžqÌã”3ÙKgG­á]°âCÜÒ 2¥Í-*ÜÏ4 è;9ȽؚfôávÓæ[½ÐÜ35 &§W»Û°Y¼–3›¢n —9#­ÓdO*#n‹€¿zñšÇá¯l/ÙrõÂ3[â)OÙEzJ„™¹ŠuÁ ãDuáK»½ÓePo;QÜÎ…!%tÔ"ï1luÀ0±ÆnU¥€Vˆ4‡¢Nð;Áí° ‰ŸÖNb†PC´ŽB*ÆÚ—pí ñC$§å]cü½Á·@°`™i­Wp ,ÿWô¹_WÕ &ÑðwQ¾QöEѲÎX¢FO*(ÊÌÊ9­kâà3ÜB"ïÁ»—Ï0ºaÊEñ¹çG!ÎäÛü„ŸxºÞ«W(¼®Ø¬P¨@jŒ'àvšÃÊ$e…H“‘i`HQï`xJΛ¬cn„xº²r‹‡zÿÌÄ%ð©Z}Q;¬„ÝÄx1;¢P«¨Œ™t§?Eù‚ÏÁö!ËPØÍÊJ–©ùG9HXW‹ß{sGçiÑ·[/P,űpw,èQˆ…wbEFc´ ÅÒ ˆhFSåI‘}¤=ˆŠ"è gßÃSù†z£ À{>‘ý\/ð—áo„¿ßr*ŠÃnÀ–Ç8©#Ï\ ød¼¥Ç¢]ñ’3QÐÜÜnžämЮÈWF$§¾²â¯Ÿl)XÄÔDL‘D½³åSV\~±yEvƒy–ÄJ¤ÄÓÎ †t„“ƒ$*6oovaWm&±2šv‘X÷½ï šuÄjÒH§¤~ ¬ô+û«Nr*Suù?¡S63ùq5—fÄB‰„Ía9¦2ú`ÇKXFÃì8ß&ųWy~¼âqaZ•÷ML L@=(‹«ÒØ ó¸ÚZ@}©PÎjö‰wg œ™3Ì‹1íT°MÌŒó‡àµËꬄSbÔ l ³æÊ¹Í•Á’yLe«ÿ½ÃêFC5šf·&aÏ ™z5>PH¯*žä!’¨ Õ¦57w„_Êœì¼#±ØÊJ•ƒ\ébh`Øs¡›¹Žà8WÇNï ƒW ?CÕ‰k™N“©&(wV8”‚ýÒœXKR9î>Oæê?ðÏ"ð¹TºlSS~.-a|Ùja*„€Û–(ãfÍcxJ'¿Ç2Éxo÷m84¬ðK mÒ%á!Ý<Úèźú=óÇUÿh« Ç)vý–SJˆRÕ\ Ÿïˆ9oËŠrˆ‹³J2Y†/6i¾¸xz{ke¦u 0͉|¼ÆÅõiâÅ8Mð^ú,ÑhÎýqó=Lò-ŠdaÜ]Aw.™IAFO4à.KV˜]sÈBP-'Uå_ô¡s¹Àg6îÐG­"Èq]H,UG¡)‘QíRú^uµmGÝ„j4¬C—wÍžuá Ò¸‚CbçSÌ?Â0n«+£½\dâËÊŒ¾Ù6åUCv[q1`¯•e‚äɯ±vÍâ.Q”l÷£è[î ´²º£¼½>7\©3þ‚¶PJˆ¾+ÑyžjAéIqK œ×0]EÉ,DAÈ8w€Ô{âf:#ñÜ®íaýƒÆÈV¹¤vNÏsò›ØÒ‚RC4N49ŠTSÑmÞ°œ7æn]€DRŸÚŽÁ”%‹‡¦AG À‹¿Ú‹H)œ‡…˜8¹Z‹C °-øÇ;6 ¸È üƒ¶GI—½GMmu]åB °æETZK©HÈVIˆíSt7‚Ũ>ù×ÌVËoPÎ,p;­‰îe‚GÇj\_Z49…1GÀàï.ñáå’xG[© øTl¡´&Ì‚Áœ[(òs²+•ÌòþbnŠÀÕêH¡®g»Ÿ¦ÙQŒ>';3G88®nMqsÚAùk“È£ë¦w•h“˜Úlšxï=¤¬$¦‰–ÀFÝTß±ŒJ`Á H´Ï¹|²èe¼¬Ü³­A‚ é±&}¨$Ö\]1O×¹`WbªñKF×!Ñžï 3‚Û¹J/í°=ï„X­È@b„Ю%»€–ÞÊÔ´¤´"XœÞdS.›ª]Šý¾¥v¥æ¸œÿ=ý.6\<AÛꯛx—jªï”"ºED’!ÄÈÜëÑ@·T-’0ñÓܵ«0µôª‘5XŒ”ï1Áó>QF‡ÈnÁµBþ8®…}#ÀÃ:_— ™ûœÌñ¯æ$ê3q¿4¾íæw¥œéóÆb—´"(F"=«’³°V™%tm‰ùÙ²½%[{=ªž©ÀDD¥ñ‰ûëC›Âsf/æ:<;K¬Y¡°@¼Luy%ißB…~‘´z^“‰”èÝÃÍ…øA¶¸(}ùÎ ŸIÚ)Ћí^l=wÍóÿÉl™R-BŽ ¥ä’=;Éu/jÁýÞ’2L‰Lz¬´¿ÜZ¹á!¢!䕦“vú?ؽRÿ8XʸÍth6­eºÂwï@ƒ[ ¦PËòmårÓyB§Ú´WóúªÎÔóAêgÄ-~y?} >ÐéÏœq»¿ÅÓd+úè!5(“„Tã¢ÀÈb4Êï'ã KŽke€Jì(” 3¼ ‡¨¹†ÔÒb‘t™Sdûö¼mu©o®ýÛ]×®mÉf­{ýì‡9*VhîÐ'–;Æ.¬GÈ´c¥G8Lú ¾Üjb¶êùžXðã{¬rãÓ­¼)àÜØÈÓ‘v‚ü౦Mÿ†Ãóòô¿bãNTCòöçFrʹssï¾qwwRT:ùE"+Î4ÞöG»7Ôš¤R3Ï7ͽ]²ÌïòM9„wpèsf¾le;5<7iöJºõqp–é—ñð@ùê0Sô¡pµ ÂeëºýÃÐÇ;†Éº ·³?f4ªâ¿Àø€/”DÎÅ_IiÖ9ÙΡö•»Ãp ª€‹¶Õ5!ïhݵ+C¥‰¯ÔeжŠI— Á[aÕ àF"°0omóíëLbú¡†zææŸV×’±ÒàcÛY_ãù=Kù#ÏIV`:Æ×!ÉáC`ñ9èØˆV×þƒ‡ZÇQ|„kÑÃD…”ik͉ÿ*¬å±¯?jòdÖ? ÁØÊU ô‹VXÓ*íª;D”w{¬ƒäEúé8ä’›O/¼ØÉ®UÔ†Â]=Å’ò”N:$wW֗ǦÉCÂáÚe¯âG+̹³Bîz3°âm\/Ýö(gõŒVá,q#éõÝ›0ìÐe°ægOrl¡‰»·$y¯šN1¡émæÓØ{ìÎRùè©h¾Îlö%:ÜIÀL u‡³•ÙÂ=q#}Íֽ÷nÞÀƸô¸Ko…xV§Ç „×.íGFžFÀ‘sÑÚqMU|Ó02+s¼àzlž¢½yPqiƒºZ ¯š-Å7Œ‡J ײ½ék.Öz±]´ËšH A“„ìµÁPø\²³üU_ó{º”Åw=á¶å½–rÐK¦£»ËBLP~u›=fö b9SSx9Qym°°¶6WzdÒ·òâòq=ühŽ`컩– 7Fã#çŒîDöYMvÝ4%V³ø.5Ö^¾±ó3W²½Ú8¼=m°Äiéì9¿À¨ ”•Šªö6P¿å}?{)ôøhÛDµO³ã7¾p*ÊÍõ=€âé…#~2tÇ8J[Pñ–Š•‰ï9ÊŸâZç㲋¢)4Ú^Jp·h¦Lœ£ÙcšsŠ5-z<2’çÚú¦‚UŽßG?LqaÒ•œYdT¬sžÚ(OÜWû~ë[Sx)kU…´]÷Iv_'×6ôžõiCÏ=c-m:´Ñ¾=!úcb6ëÙ(ò;Õ•&x¶†6„/4%Ëx+áöÍ+yãܱU7ÄE¹ûgœá>~ü?¾Á|/eó¹‘Fæ?„¯#ú›íŽË8ñVß,¤á0æ“:ü òQã©>yY/â[wZ™»ò¶ŽÝ¿ÞÖ÷‡Zª*Ï»£n‹ºüÒ&mÉ׿kûè4Ðì6LȰÊ·³ì‰a~bŸÕ‘?ÚEØròlÜç­^uä;»ø¶-wôâu½x¦»É¨,íë}\i,æ^âFñ»7k¼°‹¯W6¾Vy—±Å ™"˜+à9jàbêþÉÑßàßçþÖ)endstream endobj 109 0 obj 3600 endobj 115 0 obj <> stream xœ½\[Å~_YÉ_Ø7¦#¦Ý]U}Câ#ˆÀ{‘@q¤x½ø"ã{ >uî§zºgg ‰ñLO]Ïõ;—öO§MÝž6ðÿýäÕÉÝÃé³×'Í鳓ŸNZüñ”ÿzòêôÓ³<  ùI=5S{zöô„f¶§C8bª›pzöê䟛¶ê6©êþuö÷<#¶~F˜Æºë󤳋<ð¯Õ6m>¯ÚzšÆ4m>©Âæ›j6gùyÝ4mê7÷àûƒjc›Ÿ ›˜×®«m”gå)Ûƺiãæ³*æ1¦Í³5Âô§ÃË5°eFûUàûhÛÉït‡òÖ[¾Ä66õÐNÝöÛ<¯¶ý懼ݘ‡çå^V1äïió.yóK•Ý4}·Ùå[ü\m»ÍEžÕ¹ÇÍ%Ì}œx•çÃÉ[œù:ËûÁáá‡<"yí.Àšqð—søŸh÷ (7×°â|‡Ó ›7¯»ãgy̘дxØ'°r&X¤k<–3‡'ù$:Ž…¿¼†Éc^'l~̼ƒ[á-žÁóעɸìÂ΋ñsÙ[§Â:ïàù€ËÂÐ]\ˆ±«Ã0‰è\V¡2Ä|,a¬ù"Ï¿d¢æíùÐ!º‹VRrâ _ñôrÓ|ìI¦ Y±òe:t5àà<8.ô”Ƴª•zÚ”å-Yö%ÍØŠôpÁzG–½‡¤ÑJw+F¯˜MãæmÕÅ<')ϯ—FW>Êñ…KC¶è‡‚q ÕýEô™…š¥ iDRgÛ¼ä‡Ä¤(¼c¶ÀZØZì's‹Äj½0ÃÒ$@b4 9 PŒ›"î ¢ßÓý «Ã½`IÍR‰Þ2ö´ç•t§ÎÌöÍgkQ¢í! 0¢¡L‹âª"lSPaÓcÁ±T=3O?ˆÊ‚ÓÑÂ=·Wxðð  ¨í6Æ-#·¦=àêyzg7mIi[ Ò(¼³W€©E³Pì¤r´(­3f†xxP]gwÄ;Ád,LDRfÉBÊ9»wî9ºE¨š©¼Ó]LÎØ:±ö}¡„Þ”˜½[µ6²ö›½‘"ä!—k)çgÐö™².IkB‚ »é>.+qϘ-L]gÂÇ®ÁÙÜRgÛ ó:ñ*гé ùÄiC—IND²RªÈc³Ü†Íž‘%Ý A` zØxi°q ÔܱŸ/~¾ÐŸÉÝ2=JCÈïÒ>Ç#ÙrN°¸‘œûÜbu4–˜Ãp$FŠ.IvÙEGõÃqÂÙOØÞ‘å.ȯ‚ï9 ‰|.‡ãTÀðà-E_g¾¦Pƒ¤Oª)IÄÉÁ÷Uh#SÁJÜ%j^T(׋ò!tB ÒÐì—:¥˜ \pÙ ÔáÒxœ²4(Ñ­öŒa8‘£4f«)ž$~s›Frþ_ƒ ®À”Dq–ÍqÜWyüA÷z¿ÂÀ#Ÿº¼@ïJìÎñC4â|PXxh7ßW\Y¿ûâ * f ä’y†Ì ž·êZ¡¿^0 Y]Át@)t’Y{ÃèMÙfEêõö­ˆË•h—åÌ•`œHâQâ[Ó,½qŽneW¼1õÀ¿’ã¤[ƒ¨¥$Íç)ÊžR³Xn;¾<9û˼·a jZ½Õ²ý‡bïÇêÂ"¨KMÔØ%- óø0 å\L ] û¾tßÕ² Í‚¥š ¹Ÿ%:óê†üËȸôNËœ»;yܾU<Ýóî -é¹0Aäcðý/ñFÚÛpRû¼:Ö‰Î`öªïQa{—ÇØÍ«âElG·FñŒb â^j½YB]šúÒJ.”ìL¨8o%:'ßà³E3‰CMοU3X˜K™a1¶æm)Ò…T¤g¯”pi»ôÅ™©^Ìù¦ný&dô$‰¨)ÄæÇ‘ÅÐDMM œ ý°\S T·Ö Å5³hØÚ½¸YºD”Dú5E#oañp׬òÔï¼­Q×JḭbpBß"Ê´:®àèXW+ cs“æÅ¥éVá°5ôýÍ>Ù³Ðå4 ³ LGyþA"T²òðÃîåQå<Ôá€ke8êrµ_Ao“!à ·Íp¬0+\“cãr€ ™ÓS †ê½ä8:ŸF+|–#&‡É ­îaÒs/àM|"šW&ZÑ4fDÐXƒ\±–|Þ^öXì„ØLˆ½w´m3k«e'•U—9þgé"žõçOùxŸV®ìB-¾øõ»|Žž:Ö~«´×EèŽñóÒEcÒá´ ÛЬD­ù ’7j/¥ºÁ'9ç߯·]:h•³åg-YB•GjCëí+´Fû ¿$ûªàt6lk × ž¦bëÓ¬ ä©—Cêygàr¸…Y£¯ò[Eà×\µ9•ýkœh\òLjoPCB!ÙÅÊaÉŠTî¸>àæîϽR”¦›}Ûõ‘tJÜå Ó\odÛƒšêí5›5XÏRVïí:Ržf}Wô;}ª“e˜ßÿóË<•³ fÞ+þ7pœÅ¥ÙK´Ki»Cýr¾v%2"7-Ëð_£hL”ÉÛ¿Y]dŠü¹^zËZJ¹•@CRÌ*–;u—œ/É~ô˜~BLh¤ã©dÞ¤ˆ4K.–íòe2V|ë«3Éû2“oY¯›üˆ!b.'{œÑ‡l¼0ò]ÅÖþ¡]û7óÇKéåîÉ0/)q›œïHµ*-åÍÒâCáß§ÅiÝ dR:^]ÏqÑYÎbãúË>äi˵NäDÜWò Ô@19^ÆrØ,C ª²Êäp*“UéÞŸÉ=±W¿Îô8íé«5_g×År)~#ÖÒXéŠo»À*Wê½_¼¶ôÝj†•Ú5Æ}èQ‚î7¿m‰e$V(Úz‹úÁ‹Jú 1¦ÂP‡dïÙ,ôìC>M4tÙ†û,³ÅЙ«1K¥E£6ߥ$¯ È Î·)guÝYy|/§rTóÏ7Fâq›à¯e_‡ ‘û°+ÕÄàe„±•î¬Â$DÂ,“>Uó%{ùå+„Xˆ¸WÄž…ÌëOܱˆ}c=/Ø}$%Ee ’¹ëòõ&ÇtäÖ  ­‹ê •‡šjÏà! -(0²¤! Ã×6hÖÒKQ+%9mw)!ÐSÿýqé§/–è ]ƒÚŽFBSJÆÑœ¼³*wÎz® ­lhTJ‹Àb-‰™†•÷GX†oÊdÞŸÛfÑÞ,@~ÉV¾uÅàcŠ<á@7v`:nÀ¡ª©@ž¡R@n塨ûßåµٙ[5×kýq/ Eê¼¼ÑÁ‡ÙsAZ¦ªës Á’ M;ñ Ö}´-lùÿƒ4·(tø¿ï+~ïØáKöS%ÆX²ËΖÛn)<š_0tá6ÞYát¿„n»°¾¹LUqwg?Yû®I¯•6ßX†§x“¥7 9ì¿X)ï fýÝ5*ð—e øLeky!hªf­‡þì,NV²º ëI¸šžMéW•Eo›„n1.ñ&Ÿ\r/êúä׽ޭ,ÝdÉþGYßûb}ð‰óAˆÁo%[{kÑ•¼@N­5î½ã¢ÑofÔXEÙ·VW_·ˆxV ö7½Ö¤ËùÉo+ížµwëãÀ×µ‚h ‚}¾98º‚1ÖÃ$‚6`löR›ìzWÒÕ#ÖÐ È?)`/Õ‹D*NÐ, ÷¨üÉH(Ú\ôé §4ÿXDj¬yõyemܺà}xe?Ò‡wíá]}hz±´Ðk{XëÃgöðõÂBOŠ9N`|ÄæÏž¦ŒáÜ4·×Î>¾Õ‹Š—|̶³hÛß×ËyßiþnÈS»ƒJÀ¶ìR‡zL³¾;­ÚÌšGÄJ²û÷É«kR3ìzYËì¬Äš]ḻ²Öb=a±ï;ì5œ¸ÆÍ÷ï€Û¤®ÄdP¿ {Y¼ƒç0€ìT£o½wvòüßè·ùãendstream endobj 116 0 obj 4523 endobj 120 0 obj <> stream xœ½[[o·î³’qÞº'°ÖËër ô¡níÖm.M« š±¬X.jK¶c'M~}çNrÏY  p$Ã%9Ão¾¹pöõnÝnÂÿäçÓ—'÷ÿ6ï.¿;™v—'¯O}¹“O_îœÁ€²óÓ˜³Ï»³g'ü ÛÍ~—½—ÝÙË“ ¿ßŸºqʱ”áùþÔÞ»†'ûiœJÊ9¸á•|¼øáíÞÑ/y¾…ß–0åyx³? óŽs™.ŸÒÃRvgŸžœ}ò¯á¬àÊ𞆟ó”‡3Zg^`ο×±8†/p!7ºxÓÁgøô‡:Øh®ö~SˆóðýÞç1‡û<…uæ),³|ïaR”×% ÿÁ5s™¦$ͺ¢å§œòð.:Pt‚šJKq2Àåè† àÇ0¹á8`‰ îá ðø«,á¦cíSÙ— Å/êˆfðÕöàïpDXB ªcÇ‹¢ŽsÀ};Õq1Ó]ƽ“salÒùyÌ´às€ï¡–—*G…OpÜ3è$Ž>—N—žO”):“\F@J;â?´Ú*ÿ U‡— k9ÅáSš1Q‡:?¼ÜÓA¹y–]AÀùqŠIÐ>*9êG¡„fص zÅ»€£AMÁÁ¹tŪrìc\¦…ðò¸äÉ«®R¨†€ây%Êü'ŠZB†Óò°™4<ÝG‰–AñžÁúûüæ. M#éÜxàO`ßô4J²€Ò3I2Mv 3ƒ ÿô2÷8¹ _„¼ÀW'ƒŸp\ÏqO¨ÛX`\ÂGÎÊÇYóÍ€»L äÔ•×átØ0g¤³ i†Ïýð±ÊÜÈÚ/ŽÊx»GƒŒ1Éœ]³àòoñ‰0eàø |g4à¾Þ0ŽÐ¨Ûxƒ¿.Ktðdºk˜F†fG˜Do€%;Ͼ+;U¡h…6bŸ%Ô+yH¨Éˆº:\ï2`À>‰O]rCÁQ[¸ß— ÞxàÞƒOÂBçDª»Þ‡‘âa^_ø7TÑ÷ûÀ¿Ðöð©4ÑS¨z·0`(!”—@ÇÊxí'6ý(5bl&©?¹‚ÔF<‘—­ô0íLëãsÿƒv¬ëhO´®ØÌ.@Ò?³'oá²U5GÏÀ±F |<‹3•»n&ªŒ‰wÄ6 cq@Œ´ñ+ô¤ ù\Âû†àÉÏYõ TO;WsÁ @m·1™ièÉÄ@ûÝ2ørQatþØRè7y ~omå"@à®m‹=F¡Ý PïÄö<û‘-´ÞLM‡½ê4#RVjªŸ]°E¡Ÿ‹–CÜBÌ*CѦЙ*ËŠ1×òÄF¸>М(ßw<È˯‹7ìw8YfÙÐH1>Šø9LûØåïàç?áß#Õ­jxˆÿ#'€è ¯€9xÇ$†Zý¸¤iµâЧ»uûÄа£Y"jÝî=C 2ß÷à¢lÁtšd„ø?œ·°ÄÏ||¨#‡ÌuˈìŠ56ôû}¢í3RñËwü03}Ki™žtÞuYÈv§æß=>#TŹó»Êиè„[o)þ¹ìf'› ‰Ì‰Ð)òÚV\"aädƧû S1%G¼Â¸ìVhŸÄïi×x†'ÆÖnHhߪãùq_&!ä„£ž ëèsz !&òöiDô`0T‚–†™V¡‹Â ì)†@L¨§ù‚–9õäì*Q8eË1G2ÃÏ÷:×jÚá üʾ}„»+ăŸà¯ìŽÖEþM(S8(+ÿØ9œøœd¸—D’*5Ç)b ±ïÃg¸¢ë#@û¨‹p(èžäU%Á ü–µ½ $fAñ0jè±ótÏÞ²T ‘<=5Îâ4Næ(úã&µ„8qqÈÒý(%´r^z7*_éšpX·`ŠaíQf€FÚ¨›>7Ž=o'f€,†1ãX9_Š’Ž;ѣÃÂH›qyB6çv…S;Âßdž’J†¯Õpƒ1šYÌâÑdU4TS lÄ£usŒ\$ ’?žª®1¶½$fÿ÷P1?¨|LLŒõð¸ÍQ+'ëß]ÎÐpc3ó›™ÃÖÏö«(:I]kIO…}“dJN+mKŠ¡Ïä – Éë:þŒ¤]ô¼ Çì”¶Âé¶nø¤s¸¢ …Ö¥ Kæ´KÅù¢¾ëÆMèW-Ìè5½¬ÄhlI¥”éB­_–p/-ýà>`»ÒòFf{WZ’hÌ€@ŒT+G}ù¯×À×Ôqq– +Þqap >=ÿi–,5 ©Iƒ+›hhƒe©rÞªâ¨UèêŸU¾¯hÎÉ7ùoùT}£Çzðÿ̳E¶’ø•¦Â:f?óÊᯈ6Ÿ8Þ½Øð±ßàÃíg/$^Ü·MÂÈcMôÔ†4…™çП„VWÂþ#¥Üà¾x‹ª¬Þq¹OÅøÐQ­1\àÚÖÚ‡E?5ç¾*'7©çscFƒ•ýBûýÍž‹÷……·ÆŒLØºÄ N£Ü߬Êä÷× ëPêõsᬹ݈èã÷%µ>ЮÞ*GÎÇ÷ÞpN˜¹…¦´Z‘*³jíë€ØäKM¥ýÚœ»P’s^m?¬És#§¾êp'šé¯ Gâb÷WqNrEò ‰‚éãX,…¾ïf«aUœ‹E $çdvç¥ §âÌ\믗4Ÿrn.m]ã5–™Ê r.Øön$#âZnŸùúMç_î»` ·NɘÃÎ ṗ¨ÞJ‡È¥T ¥÷\Û™¥êÍkoÙõŠ <_EêýŽ]nøX“ôׯ4e1ÔƒeóÛ%CóÙ7· Q·xOÁ[¾CòYÒ8‰¢Û=¡¥ÖÀzŽÛ%Ö×ãÝo÷º-߆Nàˆi—à9·HæŠw ÈŒ0lðÅÌbòMC‚V·wÔhqóÝ*¡Ñ€Öq,¾í)ÉÄ,øçE¶éÖBšÔõøÝwïv×*‘ú©º¸>¥HèÔåŒÐGZ+Æ›À%‰X)¥»ÌÐ[îþ5Ç)\(æÊUظ'ïóƒÒ…®8Ùa¿‘äßHþõÑþ8’c™ ÉÊ»tŒ“>Xf ‘¡l[F¤.Í[žü¶¯úÐ5Zæbq:£ ‹«­rm“¤YÏ9›TÔÎ|ï±…Ö&¦ìâøeÚÌóUû£ö“P.£=”]©™¿àì䣯t}M‘ªÙmÕÆªÁ}\Û¤Ôj–¶ &é yÛ%N®LšrǨ®àÉ>ÕªÎbÕ$¾édë›Ø¨¨eå¾VŒÈ㸶#°k*ÕvÑÈɶVë·Ÿå\÷™[6z*Úg#ÅÃ¦Žˆ·<9Qw÷²çÆåÕvH.¹µõP\Ò:.jc”‡’¬gå}_<—®@{Kž ù¦ƒÔ6u¹ÐfK¬Þûón͸ë*7 ˆì=1¾²þ´kÙž•>4Á†þQa¶ò¡)ý¿Òæ%ÅõÞÚ]Û8ƒ*ÌØÅ͆ɖ;·]¯zµ`êmbðSÐ Eš£±ÚåßSŸòr½*p÷ÁÛ ¡Uì_õ1–zh@05óœvã+µ¿£gïY/·KŽB¡,ÃÍKÄôìÎ|@¤ ÝaÕÇ[¦'ó;k:¶mê7ÆjaÊ^Þµt2L/[éÚÜöP8Ëp½'Úk\ô“ŽÝêüÂ2EQìÝJˆ๓ðÆp]zòîè¾!<,¿Ä¾#¼Ý¾¿Øoô)×ßj’ö°/—%ÃìåÒÔ•,ŒÌ7êÙÊæ¿­ŸrÒË:½1kåòزàš}¬–på>ÿIm#¸E©u¡K¤CG ÷Hvë$LxÃÝSh{6СքsC1Ó¤Cï­ e¶Ëcé‰lZ:Tüõ /Ø3£ ¸jÓ:‘ø¹Œ¤·–ú·hìR€ô³l8¶zÂÚwuCOê›/¾Ž7Œ‘êÓ*2¸².þ:Io(Ä¡Õâï+³m@²¦E‘öðægÝ$â¹zÐwßq*Ieª•†ƒh[ âÐñíMègë˜hÚ®ÚÙ"›@oÍí›(§­rºki˜‹ŽïNr…ÌϹ"â¨sK÷âUs›wE‘Ú‚_bHvÛˆ}ó­_ßpküñ‚,„n¦V7F¯›ëñЦ6ÔvBÀâh_Úû ö¢ƒ>ú”VåZ•ƒP6ãx×Ó¿<@½–úŠÈc{y@^îè¬ÙóÝõ_q`óÚ‹•²k34¾úâBÜ!òpcê¤Vƒç±[L8,rO8ÛÆ¼yML¸Å#“<7“XÎs“µ¾¾ÀÌ߉=Jâ×Ì)SЛˆ®MÔòg›0×ZÚyÛnzÐL_I‹µ³ñ>‘¢ÓZ‚»%¥U¸ê®›/6‹&®ì:›§kßåÜì•Þ|™3µ^_kª$Vä²&HÕX§¼Ö·Ÿ¯‚,Q¡kaû^ly‡X¾žŒ>T†§©wMhJx2-Æ”q¶06eíUh;´À¾B ,_V­-ë©ûW…ìí÷èbÍiõé>íËìsç:—ø о8<òe¦xáyS’›g¬×O]…ÓK-‡\yã´ö@µµ"ï›Ï½}%}á†û1¾ûÊ‘ŧžº_È€è­6E J¹ªß«]`ÒZ5ÛuEsåG7|©t=ôª¬¨aõÂq“%ù£•`µrø¡»ººñÍw㥠æ=¤þ;Ø0úcáSyÉrì/Oþ¢nendstream endobj 121 0 obj 4820 endobj 125 0 obj <> stream xœµ\YsÝÆ±Î3ãÊo8o:¸åaƒÇØrb¥/ }s«âÆ…&˜$_ã”Ø78¤ãKþÁ×i Ç›N†{ÏÜtü~èÃÁ1i›«§…ç &áXØ—òŸ:Öw¸Úgð…ÓºãSl‰O^°˜‰öT¹èJó˜ÍHãàrŠÙï L3O´ Ì2Òþm O:·_ÆÞ«Æ¾ÎsÍâñº°EJâI‚4ô-÷)‹Ô{jE’ÓæmzÔ8Š·ÖîßÝiÀgÎ'> \4©ƒ4À¹ q£îŽÇ£S´N,‚ÖñR¶›"Kñ“NÕù/º^Üû‰7r¡'¼Þ(Ômêô(eÜôL yYK•ŽgE=“ƒT•ºÒ3¼ÎŸ@¬ü6ÆÞרTô¤ïDëÓÁÅÄêQéDZO‡ó?ŸÿÏ?\?΃¶ýè\XŽFt éS„B?Ma!­ö0„‡ã{NM‡e¦bH´Jyö²Õ-A[‡PÂviÝñU"ÍaõW8­'ÐižÜ’pC¼›«à”ú0‡bÒ5ôn‹‡Oy~¸Ù4ë G ¹¡¡q7 4CZè’|Æ„„×eä~¨L× ÀGʈ‚-UÉI…p z ⨵Á ¶¼ÄçžPÂ:Ï“¨CLO°E ]`¯ ìB@¤@š“nCî '#/?M±\?Ê7  ØÉ)ÞàÌ/3fÚÌÙh>°›û ßzšÖ)¨ÀŸî6¢\>ÜÏ5ê7´ùfŸWœb)/EõBN÷6±Ui ¾†çlŠAö¶+~·GBÉ|TžŽa>ÛXØ5VX1ëÿíöŽÆvˆÙ°"[°®C±”l«Í<“$^šÁG™\±J &ó¹–qVškœ"n­Cq@z¯'Ó…ab<þØZL`™ÍdG²‚Ýäeû| —6VTÝ´.37ÁÕéÃßôºòBÐFÂÐø¼DöäbÙŸ½y¾F6§s=†z6M¡Õ@KõPìå#&ûUÿü¾ ¼j²˜ïEHå //å …àéüJðqúöDd¨_TC<-œ”gú7jœ[ !åi©kš±ù¦R&ó»Üñ_ù²½]õC_ B±ØÎÒшèb†@°Vþ„× ¡0Èx÷4K´ˆ÷ZãPÈ‹ýÈeƒz:_œÑ ÃH Ë'öL•KÝö³a„%;=ø¼èb.s¾œ¥¶ø…~¿ 4ùÅomm ±S$¸Ãlû€âi’>×}²³q5ïî9;ÉàÁÄXZ­7<muG—…T’Ƹ!}‡g‘R ÷M7šüqÕ»%è´Wæä…Q5ðè‚_Zk1/‘½LÖäÕЦ1Rå¼ü’z¾S!Ø®@AAgG?n/9{?⋬Œ™ørÁUΜBáŽGgg¶TßóLìI¥~—ÂîÅ÷­ÖAö¢gÞ‚7Ró㦵]ÕÀa_±'¤®­vÉʕ˴4½†¸o;>]4ïò=_…{Å‹ßÅR¨•5‚âŽÐ~bGõRá·vÃ…1˜X9ÞPD«–XÕ!Ó8Ïœ6qº@ÑD.îOe”ÓÐ6ʉÑöƒ‚þi"9ÙÚŸ¯tM¸ÿd”§õ ,ØúŽLIÍ¿ÚKVª¹À9 ¸†ú¦Âß ¡ŒW·Â.ŒÈo•5~Ðu¦%-¨è+Ä9öx’ná0ì¬Ö:ŠÆÌ†Rf i‹‹‘CÿÙùÙ×g?À(OD‚2¦„½O°¯ þ¼¸>ûäáÙý‡9¼yõöÉÙý¿ÜÙýÏñŸO¾ú~<|pøÍÙg_ Ý÷6¦Áá<}œ˜s¬„i¦jw¥ÎàM¿þR›{«•VzŽ—9´Š¥rƒÒÚËTgá'aDa¯;dypi'4šŒ´rq㱚K°Gv©Ç‹.jbî4Ïா”uy«{+ +:w;¼‘]Sq»˜ƒ‹}˜ôÚí©º8‚ëPÔ^< ÀŸ5t[ pWõ¹àÜ• µëA°ÃÁ v9ѽŠQ[Ù^¿ |÷!SvpïØFߪž`á'!OØÆ¿ÚD‰ÃËܬÒKt§¶šíê¹ä3 ·8È0Ä×Ól)•Õ™lŸ »Ô1šocÍ”¬—[íR‚¸gÆÎ.%= s“`Þ§øÂ~VñmE¢Z„66NnŽSÛìÒÒ ÷íJã][ì§YÏV„÷|JÞÖ[Ÿrˆj GÜìcÖn½Â†Â8]²×~bÂw²“t½Þqês †¤g‡aëT¸‰,âöü‡¨t¡"Ñ–´ÁÍ• B!ŒcLâál××…à­`³ŽóÂzVvSÙXú »Ýc•ãV¿ÕbõöʰpîÐB'Ø‹R&³ þ=š=ÄÛ´ºÈ6tõY2s¡A<­µ ] T ̰–ˆA3³¶ñE¬RLœO"‡ø3Bèþ7˜vT¦“•oñ·07¬ø~l(¢£‚6Ù’{âTcb —¸ÊúT—FÅÌ 9 1æ·¸Öù&Á†5ç‹•J]À¿§«8Ìeç‚qYG0*tOaÚUœ©\Ñ£B+K;;®ñêšW°%Ç!)1Ñ /DqpÝ#+ ³r”ȈPÂÓÌb&i3ÎÄL$· éP®enÅw#rðìG¦è Ër[²±`³ojH+øþX«ÂÅÄøúí+l™b Q@SQØÜù‘DÛÆDäç8Òo;VbÀrš²bgß.c 1²‘ÈN¡]k&¸à ë@êÖ„jó’jÀÚ¸7ÉWée,oêg#¯ŠóÊ8W1g«< °q1 × 2ÔÇnæÏH8ü¶ç¢ x”ÝñýÚ©^ÒäJvOªV(WA¯Ýks³B¦ˆ‹v+æ®Ô‘7L o6|È[Î<ã_aÔÌCI1X´êgØ”Ñ/8µ^“#¥yTÉÔÚVæ[®Cp¦†*iy¿@kWeZ ׄΪ曑à)œ¹y!ÛcÌ_/ë ¯…2w•g8- °4~q¾-õ1ñ:Z©u²â¼ä€¯°±5ŸrÓ­Üs|ÿ œýÖWÃëCŽíXžîÆÐa¦]÷2#£“¬îã.{X¸ÛÚ(–)B¯úسÏÒ«*+FU($¦5Æþ{$ƒ\ôÖB´v™†O¦Uµkîg·¡ìð. |Î+6 çé9¡!ý c—í&º®i¶ä˰G¡•+k©‰Çûþ]~£¸¬e< V1¨JrÓ´dšáâ–~Ö­Ü&ŸJó’ÆùÎ|M®¤k—š1™qa勜ƒm¤»Ê´lSÑT Ä:„ÂN1‡(‡•t ¬!k KaI|âì¬dÇÍSËâ ÒÚÏ;\€Ä‚;Æ(ëâØÄŽœ˜ UÏÔ¶f¤†‚.ÖZªMmWNoœ} F-ßO9,K® µ<«ÝB9­ï²ö¶b¶kê¹j°&.:ª7 q¥NµòÁX+Ó딂i›^ZuÜÂí&,-ÖœñäÒк›ÎݱNÅ‹z~ë&I¢ÝÊÅž Ûöœ?ŠhE¸ûÒo{+æK/9•C†"\ª+v”+ Çî ³§ìã 0–Y xp¶c¥ÊBae5¦Eå<Ø*f€T‰Ö5[&Ë(ì›EsB„©~F8€R?æ¸d[˜" å–æqÞzöÁÓ‚´&’rð4ŠéôÝ-Š_÷@]Û—G\ßà[ØØàRD7I&µé½Tk[¹ZDw Çp^"öÅqͶÞ)‰&J¾®^êÒHÀU=êZ}ngż­¸Ý­¥œ0ŸrK9eÈ唟vC?…3E9å+r´Æ!òkÄT•”RÒÔѹÁI±ŸV± ýì‡ypÇ\0É•°ye.‚Ô×xfÌPÍ º~.~ÒNã"%”Þ ”`.Œƒv)‘îA»€PþÌê‹Qj+0y›Sœ¢,Ó£ç)G,̓~Ûi§I«U%íyÁ„žám…ÞÒ TWdyÚIÖÁ։ȢTN3¯ê6,h‘A϶Y¢X NY–¨þ|.K¬ø5Ű™×ÿ 3::3EFøîÁÖš½6Ë)X”ÐLd– ­ò)Jiggj*õ× zhØ ù4'¶õ”jÍsq·9XüÆàjSB²N¿D—,¬¿­([ E ƒ˜ÜUÀ!Žš%ú°¡3¢dÛå¨Ðe6ØÃ…G¹]õì9ôUâóG­rÃiÃx«¥ÃJј6Á)€Ò8u¹x êO#,>‰j+ýPør6R)áÅ[—l¹Öª‹Â2m•èR*#ST3°–Û¬a@¤Lïx5Î5¯ï%Éxƒµá»ËG#rŒ3-»uÍa å§*V)O.î4,{G9¿¸úH-#¦¸AŸÏúï]]¯#—ˆñNÅ»a$µ*Þ šWôùV,ÜÄÞ?ÛE·Ê%HwˆXY`^–^좨V]œÈÎχ¦}bà~{%Ý´‘m>·Žò·Fßð h…¥ÖuœdùušúQfB®w,Yù2WQ;ºñQÆ”2ëÇT¦­•qX‘ÓÐ ‡¨Î›óÕjVâI¦@–>{IÌfĺ‚­œ²æs‹7 XAŽaŠ–y%„„Ç›·ªËæ#Y¸¾·Ö|$6Ýn=Ô¾ýðT‹3ã_ï{µl5Á!4„U¨’ øzä:ËÂg¿±müh†ôYçÛT˜ñ$BQ°Tj\ZQœ’/bæ(YÆ?Ü(©ÉYJéãÇ^TVŠj %Öoæ‡p.¥ ˆX}V;""œ" ™nÏz1Ó¨û߯!ËçZ¹s)À¼a +ÿѨj5ô¿µ”5‰PÈ/+†T—.kªˆ‰–v†‹_ÞZ% ŸjEo‰ÏT½-¢¥ÌïVÞïjï“û"rm*T¶>¹·e¼Òت KyÇqn;ôËß)¦MáW#“¨L€|ö¸HîÞŸ÷å]Ì¡âßr|X„Š›Qã µTM%šã„¶|…÷"¿ÖÞB8~‘CÉö§qïñîð=Ûï3·äSlG_ùë6?/›/Û›¡(ª@œÔÀˆU1î2”-Õ¼­ùS¿™Ùç6`x)+ßZ³Ä8±É8o©Õ‚2½'•[«¦÷TNuá·ÖÈ 9Â_ ̽›·|W[}ç”ËgVÈú”÷\mk}íñJ$ÎÆDSe°øÞÌ(^MϽ‡å¤ôʶXâqÛ –;ØÝ­Q4wLÄTCTeÑæÅ0תc»GŽkµ¦´sâ']ÞX{‹ /ŠÏV,!¿$«N±#ÁÈ<š±§RužGrêC+ÒYJì"প”,¬.EIp%Î2n1¥j U4Ú!MH|ç–~ÊÆbm´¤_ìñ³à&[YÜY°b›.Ÿ¸ôç¶Bµ¢r5õMnsOùxÙ{ÛDz:•¹Wʆ^ªå’GNíT¦Œ5H>ß>Å…ízÛÂ/.%L!,¥ÿÄWB†šíÝO÷dRå¥ÚW…» dɲJAa•Ķr§81R´Ši™4xÚÙÿ FËBÙîmâÛ%dYüªH ê#’Uåi•;Ò=®>ÏÔâoÚ™±õA"[¡3×¼‡AÙ& dGQ—ømâK-É߇ZW%L?ûù¾™øB{Õ\qÎ5Ø0ªŠš÷ÕfÚ·sÁãž“¯»Ý1¶W–ØÎÿK•žý¶žQø×½Ž/áÌÕ¿†b¹áÎJ%ŽíÝ>d²lû¿‹0ó’c‹V(k©îá¿U6)Èږ༧ºþƒ‚=…c©Ýªp1¼Çü…î¥(Ü„ŸÌÔ W¨Zþ>èë³ÿ²ý€endstream endobj 126 0 obj 4875 endobj 130 0 obj <> stream xœÕ\Y“Å~— ÿ†}q0­`𮫻Ê~°a9À‡´Æà#Â{Kx/´+,þ½+¯ª¬îž=;p’fzêÌü*/«ùfoèÍÞÿñ¿GO>|1íÝ<öΞ|óÄà{üÏÑÅÞoösgò“> ÉìíŸ>¡žfo²{“óý`÷ö/žümã»°é;» øïvŠ©Oqܼì¶ãæÏùùo:¿yÑ9ÛÆ»Íº­ÇÇûðáy·µ›ßçoŸt[‡MÂæYgŒíSr›_ç>ïµú þÂO¹­É¿GŸ`çBžoÊå!Œ÷1ü0â(wnê‡as“4äy£Ë‚•¯y_•¾¬csÁ.þ±ÿ», cµ,|ÈcÆ,Žýã,“·>uÆ=ã{çG í¶Üpë†~2)Q{Ÿç “7×c\ÊâÛæ}OýèaR›G°yoëÇÃúñ ¬rC ›+*5Mo󨃷)n^ãøCš6—õç“,œÉõ£sYØ1f©ãæ ·t¹Óæ¢Ë ™3MÒÛØÍ9­3Z~ŸNò§ilÜÜäcèsË: Ïgò~Ža¾ØO~ÊÊzï“#· eµÆÕη]ÖªOCØ|×m‡>Fg­Ù\çqB‡Aæ6 çzgÍ蚢\VÑgOöŸþ ‘tuÙYÄ úx•ŸŸÂׄ_óô›W€ßxfÏ7‡,ã1·0CuŒ ˆ€ÕÐ9 xèé³tRò›£üš_€p2Ì"Ma"Ÿ{…a@àæ9Óà²Uh—‚ÿò°‘”Ìæßg\:üxÔá0 e¥áFŽåןAß78.  ã’`æËÉû¢Õ¼ê@ÐÎN%¥c’ƒµ¸fÐ,-™¾áQL` Õˆ*te”¼‹Fz˜WeøÜ:ã#?Æ¡Q97tvÇ<ìUþAÚ°bOÛmtR~+K†]ma[Û¬0‚}ƒÝ]ƒX 3*›UáPð jâæï›ü ò÷oJ=Þ£löE7 8†>b«c™ã–Aʲ ¨ 3“›Z7†¹‚*òÄšA·|ÖÔ€,¢˜Ú@¹Ž5G²ó€UÏohîak³ãŠ=Ï;¹Ú8*{ cQ#žŠÃÎŽe³nÌæ9ÙÅn`ùùAD„ßB‡—pN§µZ5½¦ó7d‘òãVˆfÖhr_¬4ž&ÛÊ/«9…l,•A°V(Šû–å ðXBˆ½" êRpÁËðÄ#D`1‚ç=cülàzÞÏ_¿†>ïCŸ¨Í :Ìä° l1‡ ÿ@ ñÆ]ÊŽ@ÊBwΠ‚ªy‚ýž³Mºê\$+¤ öËÎ’mö±u¢}t‰œ£+çí]–6Ûü#Ës«yMKÝ:©‰Lûá¢Ë´~À_o”)Ýò¯·"Rüuóþ2`ªGŒ'²„¥ÏÛjz/ËÃmåáÙZË“òé˜mšñ¸'zø]ís«ûÈCT>…Ãv_/¶{S¶{Õn÷fŒØxÙì¼,Úé ßpŸVÏkƒ§å¡½k™_/–yï\|¤Éa^Vޝ“} Ûò·¶˜myx¸¦¦ÛêêëÃË{ôp¶ö°JºÝ¨÷€hè¿¢8/ÊByœ 2ÂÚ/v@Ë'âû^Ë|¨J㪔Çò»ÿiIY›“…”ß\á¹?¯RƇïà¯k‘wY wY]êëúð <<‡`$â¹>Õ¥eýàž1«Õ DàêÄʮȸ]£hKéøÅšŽý]ÇöôR<-–ù]{ Á»#> ÉR oê˲ñi½ü˜E%åƒô8¡š4?8êñB¨Ç嘿…¿õ6Ãtv®‹‹:ßµØåª3j0âŒA¥“H&k3ý¨‚çOÛúó£T€>9…{UïRÁÙOE§kÝß­éåxMr§+£ÿ_§ûŒ|ô9Šœi“?‹:Öc>Tç…ØõVh¥$ºX5¥É•5^¯%˜z°n*pª\Où` ÃäáÓÚݳ¡ÉûøvMç塊FOôœ»‘ñSAþÑN.ÖD\·{Òœ‘•(濬˜ø_TÌùaᙸVç¨u¿:Bþ¬[‰—“Ýüà$‰Ô8Q¶q»&á]†BÝ9A·ÕY u’ùþ¥ó•Ç(â8–gœt óseS“:¼˜…ÂÏLçYä+³g= Ï„bF‚æ%áÚð¦2Ø7b¬‰‘ÝœéjÙaµ:9^ÝÖBÖÎ, &TREÑ~0LÂd¹šfÆK\*0}j¸Ò⊠CtL{¯Ù˜†„¯n@«€§e’ ³‹£}ÃÜ»8’·Í!˜¨É¢a¿ípóU¹oUán@@HÖüe¢v­Ü² =ƒfhfÔ J£eýªPcˆ˜£OÌÝ ¾ihqcGbÿäMË"X#ùP¥¬p@Õ!xÇp²Ç0JBLC¯¿‚üT„Š+°u,®¼F+;¶q(¸¦¹X8<£ GÌOe­Í‹CÈĦ¾7o§¤ó™³\G¯ü+Îàó…ý+>ÆåÁ¬y!x1 ˜`Û…¢Ô’׳æÿ Qþ’*Ÿ«@A„3T;×)‰¦´$rq ˜jDþØI±êËüuhº~¥âXÌÓÃüàð»À¨vDóÜð ßm›m_(7$kÕáE½}Î2…uÑùÇ5=ƒbÀ`²ŠPg/`äÏ;夡 ‘A¬–ù>—ï„ Äå&S¥wBÏ*»(ëV¶’üµÔKày,üymu K°hU‰iDä÷X,U…¢QñP¾ft^Åh'¡BšÇJ*ü”̵2n$³ñ±ð%,ÑÖZ³Sj ¨HØQaÖ!Þv¡ •°¿€,ênÈ}©€ÝÏ]667 ü*´‚h–Õ(ÏÕgÊl +.G/Ó{€Õ¸VÛº–bsóÔdÜ¢q]D¦ü¥š: ›ÜâíêR–¶] ¸7fêc±83W)óW°´þ°èàËx¿Iñx¬ì,}mó—ðFC¢[)Žh«-ŽJa>ÚìO3 Øxo! X¶†šÁD…wô?h>•ˆ¨õMM´ÿ¢¨äþÀX|ų2ê•£Rõ‰;ê”.P¹Bü,’#Ej 2 Ü*k2‹›¤r5…y/¡B¶èšº·l8k½ŒJTñÀÕUE’òLkÖ¶¡ê]³’“rÊ¿…Rø¬A¡¿€ÒvËØ˜¿#³ˆTó}ˆ±ó´)U͸XUÊИ™×b“|µæR%=”B0K΂Õðx Æy}Ľ äš.(™¬QÀvQ²Š“d\t®æ¢Ü ‘ej-ViJì?lœî9°R C\YÌ×8®>jî;envPÌéS =ôÁ `ªGž¿æX®tÊ1çt@ŸéFíŸÈ läÈb¼„goRUyÁ=1û3\¸s*Èa ¾¬¶ê¹&¶F´Ö©Ü¥X¹E±~"PQÌI‡•b?UÑ•…­ŒõNki¤(ähn;Š»e«vÀ³˜Ð þ¶\âSjfÇSYÝ¥2`ß7o”«(¶·|Ãõ£¯ž.˪\b¡‘«B9¿ô£G¥®™ª#¼-erÎS»© Š+ûÊ®Iá÷;à ò$l†^w¶„ª»î_ܱ°û¢‡†ï¶5e©LM 2 ¥r|W´òŸì0]½ÑsÛ9¨ŠnJ’’ Úí&1J¶„½0P"z¢%`°’GÌ<6ÐicbD9ŽCí*öüˆœš2cw˜ßbx)yVõ|K#ö¦X+}­ÀFY ƒ¹6\ß|Ѽ[ð<|™ÿ|˜Û~Q|ÙçE­/¹Sö¨LûIQ+Ži×& Ï} ùªJ° ÑBÚ⊾×3_·À­¶vI‚«¯ZèÄïægËoåòëì‘ØÇ{dåË¿Oùqçë5C²ÀA"ݘS뺤f¶ªÀÙÂóãžn[äQJýY²tÊù>ÇiÇטäâÑÛbŒÅò›¬€’´bN }ÄéeË¢Éq¯`]xè%# b=\Òü‚SC8阰ßè8R+¬`-èh ²ÚàûòÐ;«‚?òAGÿD8ÈqŸœ.¬¢·ÃßÕä¡‹t—©šXèS¯6Û²SHå’w§bâ@XžLK›¶Ô®Íå*vì(ÖË¡8¶`)*›òJ"áºh³k·Ê× ]8ã(^"$òW¢+}Y&:¦C*ÆuêŸ×¦í5àÚ„k&ÞÎCÌ„P—ãË“í’ÚÓuÝ&D”70i) 6“¹Ãl¿ÈhŠ%Y)C͉ Ä!:d±1ç•ÕÞÅŒ€b\)‰Ï|`ñ§`ý€ç£ûí3/|Y÷:—ËØ$T°#@)\Ž_SH‚Â…¨–IáfìJ“¶ƒ¤X‡–íƒÚ$¥’wo[yާ°§kÊ뎛㭭ìeK‘ì§\ù&Šoª%ÌÙKŠrÉ \¬lyD£ÂQŸ§¦" ÷dTápÞAS[oÿ?*ñ¤ü¹^ùÆìѸ&ÕÁœÓxÌ”Ã(ÙÕN‹Ñ¦Xl¹orëÔ3Á¥@e‘ÞÑœã‘d~ )+Ë5:òhUO‰HÑijນJÙ¦öxµFÕ?Kz\;1 Ò£3],t¿36\>4gLnÑ)Nš3môœžïÐnˆ=3àZ<Œå—ëü­™‘× ðrvø¾ô‰KŽí¡¼“Pãy}Ù!f·%kÊaP›eKýš6Z<Û£IaTØ8ƒê‹jh¼‹Äi÷1e]’Ã5ùïXÂ÷å«.Eµ0y˜1Öî^ æüC-&qœ±Ñ%ßRZW5²þŸ¼õ"½!¶ÂXdjM;LòƒjRtœÈG·'x¯ã8ßkyÅEÞÔ`?v—«‹Ã 9¬:‡W*\ûžÎÎW©äõ–YÄ.ï“„‡X¸Ø²^Þéì° ŽfìŠ%x1SXKÎAÉfà÷ÓÊû(-3!, Ç;tTšjªN~'J«}ÓëvƧÌÞìÌáië ÿµW:ÇúJçs ­ƒ‹ô‚嘜èî½$y^ÞÔ¬ïlò┕§R¾ÜOÖÐÛ”!¯.4À«“Yª›úòçµô#ܰ©71ÆÝ/Tò;¡@ç ð¯ËÛ¥X6Éb6yÙ¾./%´¼„É/¤šI¿Ž©^¥qBôêµÐ»ßÖlŽ—0VKŽ©²Kþáoc½¤°§¨¤y‹,  ÷›OûŽH•H£Ç™p6~rN,œk^'_¡´:‹Ò»47Dí[¥ÌæC ïT‚¥òx¹éÔ&R(0Xh¸#ÊbùáøöÉ® 8ŽnFdTÆá[¼s”¢ýÅ¾Š¯ÔŒ(-H‚sGNU‰oš¦úvç¬,À?/@íò~W4‹`…i;Òëð+á¶åKœv\÷se’Öì*äâ:Á™È½°40_cˆÐF`ÃÕ»PˆØ¹öö¼ØSÒ·½ÎºPƒT€ÜDUõ&ê :}gaW=^ii·€%ïPê3š§ºbù/.¹¶«Š[´ å´ˆæc´óåMÂÂHµï–SåÂ/pB5’¸ '£+TX%èÝ0¬0eqwdUZH´1<×qrü?fm?¯Q[ ²é½ > stream xœ­\Y“ÇöóÚ?bÞ<#k›®«»úABB$$XÛ²aÄéì"„%ëß;Ϫ¬>fp@owו••ùå—ÙûÓ®ïÜ®Ç?òÿãW·Œ»ç?_ô»ç?]8z¸“ÿ¿Úݾ‚œ‡;ÝÔOnwõì‚[ºÝèwcˆ]ïwW¯.þ±w‡´Ï‡ôÏ«¿@‹àš¼¡ÑÕxñ³ÃeÜypÝ4å8í?=øý7‡K¿¿Âûw—úàÁá2ø¾ë]ÜGè»;\Žyê¦<ì¿8x|®îÖ×±y×ÃÛÃþáá²yt{‚&yäÁïã?_—ü­\™Ñ¿>xÛå]œáýú3<†«ä|„V-Û}·Â·ÜþÏeª--¨¯ÏÛL4¨ßßÃèv@· ã¯Œ£g™¶»p)B½ }7ºibÙ¾À•?=Äý#Øýá Ì'0ú¸ÿñ<Ýû –ºÿõà'¸=¤ý ¼¯Q£GzÚÿrH0Çœ¸·—0¯ÿp¼:XÞ¿Æ{¦Õ3¸ÔîBH4êõÁcƒ$=¼‚å‰TdzøšËaÿoä1¶qZ:ƒa˜Ï îÆiǯ¸eå×<½Þ ¼ FØ?Mø¹¼Õç2טhM¿PÜ¡»48ÕYê ¿…mƒ©ºÕždº­¼à‰'‘‹æ”‰—>PJÓ o•Ê ÓN„í÷¯ËÍ7¨‡Ó”œ§.@œ8©x`óô7l :“'}Ò<~t9ƒ–N¤ Ø÷€k¿ÔÅ_ºÿãGˆœbŒ4ÛGx©Ôÿ(\7Ì:¦LêðÄc7Of Ë'ñá±2í#Í/ ¯»Å<ä5;n{žcÔ}Ùâ²14ˆQ)ågœ,5ÇKí§´ÁÉ·POÓúI7ªÍ€Ó¼ÿJ÷ …vçêâÛ‹Ÿv0­ì#9ÃO0hλaꡯŒæööÝ‹[w¿Ú½}󟧷þ¾s·¾Änóüw÷óÝï.îÜÝ}ûަÏKvØÇ1²9¾ð™ÜªyãÚã¥óÙ˜Ó{VÆlÜþï( >¨mÏX`ʶ6’>ã΋Êß™`à”$˜CAÛX»«àÔFTž.e Þ.}YÎÝ94Ü F ž¦Ì Žjô_4‹¨³Oåïц-PP×_¨L{š½ÚBQ×ç‡$¯ÐòŸqzZJ‘O ¾BzW´O»Þ‚×&žH£¨°OÒb4wIl:4 ²ó88_ɱöÒ±2¶÷µW¶ºQ tŠ^7lŒˆçÖwlT6 °É^í§Zê~QGDÂ3‡'Á¯^†q"§·p Pí\P){~O'ÜÓ6Ñ–‹Û4ÓL¯xº u#kœÙ«È]–‹Ñu@ "¦“–ÝZÎ×S,±Zçu Ú¸¸¥SͼZlXœ“ø£´ÿ1 kÖK'ÞÖ}ÖÓ¯ž<´nКz”sï£'3v¤*E‰­ž}ñö(7?/Q d±·ô0°»>®ý$£îÀ{#ƒ\º©“¡qMØ¥b„P¶Fõd£R/ç]Õ÷2²(×¼¡žó5o¨â¸ C˜»ì£u0ŸÐm@³3V$6…ÔQ4†?š£#<ÄHSÕId+§´ñEÅÄ.ª)h<*Ÿ}D\‚§zp h70Þ jÂ1Oˆ!fü!6ûw=Uo$"ñÕ‚Çb¢#;¶ê¬ê\ZÐjý–+ã^T­Y…BŸ„àÕ°V÷ 8Û¢’SÇÓl‰?aø Íøà%ý僇¹z¼ŸÀVLg£Ÿæ\– Näù+¤²6¾UG‘Fí`.BƒŸd˲јàO­kW*‡‹0v4Jó_Ûvb¨ÙU…­Ýºõ ïÀƒƒ,=~²lܦ˜{Ç«òÒ:|ß%ç´¡gsPr}ߘ>;À>zÀÄhO³ïâ@á,<>"€ƒ™åp‹iô’»Ïäüટ0¼+mžë<ÖbÖ[uïâ꣦l#6hÛÂyµÆ¢èVƒcïWJ£xöPŠQXV}ItÁÆoáfô½Îƒ¸u……SO¯5±›Q KL„ò®‰1®ÒRŸE‡ž·à—èyÎ:}‚¦d|8ƹ.â2Ÿfȼ5¹­C’›#¨ÏäA¶0Ï!í¹!p' j޲ÄÑn^6ƨ1°²ÈgÑ©±GÌhÝR„­@¤þðÿ¢à;›¬³3K­ûÀA+³Ÿ–ÐËDVw°õÔp'ª€Øú;Üù&R#Ç"À°×³“ø~hm²ªC‰ši"Yä¥îµæqrdæÖ&qÅj¢²ïªù#jê…pŠË(×À5FâÅŠÈéÖ×aWBÄBQ(k•cÃZ®ì’'ßzßM6+JxWìwJvk#//¤G±Q%ú«g½ N¶j䆡¸X!G–îNpâ&—8 #ÓÁ›]=%#>ãèVŽ…TêÄvfZü㺾úbZfaÙYTÌrË&L6"»QÅM\'ÈMG]׬%Ф¸J¤iŒTbùjÒñÚ[‹³…¢Dp Ý5Øe§³uŠ1u9€’Bxbˆ\Ê/öPXSdJ÷R? |¾$..ÐðôX=!¼ÃÁÚ'p)&}á‹jéï–›WõæCí Ò EKôùK;§ õ&ÚäGu·Ë k«ÏÊÍOëÍ{åæÚÓŸàüpíå»ÚàN¹ù Þ¼¯7WIt+ü%¦•êk@T]r9âh¡Ä‡[€£\º âQ¿Ñ,b‡PpTÐø³Ñò¹ÆžÆO±W|L]¨Ë)†}tœ#¡Æìô°{ÜÆi1ÇDbl,%O–ƒ›©å¸–5Låüj2ääù•¥|>;Äè×ÑKº†"dTP?Ç6+4å`ÈvÐq}®$ƒ®´µm :gÇb©Û¸4—¸4igs’9ÓŒœâriSÎ몒†JñDz%Eå3fNJ&÷ýe}GÒ¨~"ÿ¨ îæ°\GaŽ:.Ž÷>ÅýlξLpæ Ê IçŒ8êÞ¶,ÁC˜FBâ«îJ™zx»Ú°Ú¡ì`@¼ ÑRùnì´˜Õ©´h‡–X4¡X'ƒˆ€àäcH-š•ŒT¡ î‰J.À[£5G43áAÙS¾g¤ÞøÅ U¶¡¥ÂgÚAAÂHúÙ`ذÙK¹Xé .ÍÝÂa€¢d L†Ôn û†“p±á  ŒDûb. IÑ–l‰DÞ ÆþSÓ¦D›ÙFqo¦Å#Y–Yò°fUžjžg+±Ó$PX'⯖xŠtÌ_7¸ ­PØ-›ÞÑÍýCµf ë%VѵÄbKÃu YçIujhÅéOšÜ ].ô÷Û~Épã ìµ~ÏâïñǼJtUû¦Úµa—"í«7:b^ÝDe¬Ü°±Ç´ ÌÏÉñTf¦óšÔQtnÌ×Ìzmr  ©3"ŒmF1q¢[4À,M¿ Ú”K1£¯x¸¾w+jåÙZžQ–¢¤÷lnÅG &( ¶Ù$˦žÖA ËV&´4ÙÄ!ç»Se `*Üـ‘V˜°‰ñþ;3a9’s=Æ„Mùs¥>ò´˜Î£Ù¬f,AÒÐϳ“ÇÀ-%ç+E* ·[Îaª-ðoÓ`ä2“æ¼lPª­köx˜–’¶"¥ÒØ£!ˆLh|sÑR¥[|MM ¶ž¤©­ºp5%²Õ _¤¼ëCMÙÀˆQíó0Iôw4oð®i©$Ñ É¤5lį‹c-ja"rS ßmÕ nFØbæ„r›„âJ×Ò:t­šYüjô—¸Lçd¨¯ ˧]¯èlÏBs[;TŒÄҪĖ Åì¢ Çʘ(gwv‰6‘Ÿq“¿;#AEòÃ4‹R@¥¬yàÄŽñÊ[C¶ˆÉÜŽŽH=¢å ¬2稇øÒÆM –¤-ö`½ð'($gí21›hèì` hʼn@ -Yî®Ò„¥bÖ¯ÃG)6l(<£ìëG„µï”gW-X#yMmß1*Àæh)ÛQ² Cפ;¤õ‘xÒ+f+Ú×`‡|4™\7Ø<Ú¨*˜XÄ Î&N²'GR–Žþ'œç£t%ý«ù÷Á|>`*I—©È·’¿Ìãç//ß;ëØtsëƒÓ †ø_ä2ËÔ,²æ2‰î7U¾˜Ïœ˜–='Ÿ©E%'sš‘èWnN3öT¹·QÀr"§©/ÊŽžËÇ7ršü¶[æ4a½1›”&Ï)Û6#ÛëÁÞ\Ké{gf29w2þßS™¼Àì<À y%±dÄ÷QA÷˼ÔâÏ.y,`Gu"»~È'öˆ›,ã%xä…^šùk™j6‘–¦ ­ÄÄ#uÌW6X½QhN½ñìyÀçs¾Ïµ_Ë´½c2L5r X¯å¥<¾Ÿ6z¬0raÓYI_zB›áJ›“ØÖTœßVîW$¦®‰$×z'Öa©c ?Ÿ“qýsjqÕz¥m)°e~­Ä6×Û;é8dEÞКÀ÷4—7¥9†b9ufaªmm5n[¡r`Å/"°òãþo‡,Ô¬M1Fè«Ù7T£I.«&–^ú½¡ÃÙŸssÆCc K/èŠÕsóMZ°1Ö´!}ÄåÅë×–Åœ^̲ Ó6}ÄÕ‰ ¤3EùHuöÝÚZ_jÛ(²°L„Чh4öÄ÷nŒÛu•X­ôù@ÛÈS ç:_/ÈbuÙFãÿ}\?+•XdÖÚGÉûAs ¼Ö—/Æ£nêqÅÂ5u5(ç¡/quªHÛôò€'~àï/dü÷uš~tЦGo»Sl+vÜu\*ÓÐ/?ëE¹f›Ì^ªÔÈßmFÖ½«hÏ9Ás´‘O ý"‹-;ŠZ†ÜÈüw4 ØúÙjñq³IÌJ u«l*ýBo/þ¡ŽÈ‘endstream endobj 136 0 obj 4731 endobj 140 0 obj <> stream xœ¥\[sÝÆ‘~WRûøæs¶D,æ`ð({cÇ)Çqb&©­uª–"%*k‰”-)¶’?ŸéÛL÷`pHÉ¥²yÎ0—žž¯¿¾ ~8w6Â?þ{õêÑýi9»yóh<»yôÃ#‡ÏøÏÕ«³O/ò Áå_†u\ÝÙÅóGô¤;[üÙâ0ú³‹Wþ÷Óa8úÊÏ—´kš9:çò§éð$_üÓñܾ<ž{üöé1¾‚/¿É?ëšâz8?†ò›?|ïú"ÿrq<‡ßÏCHØê“£ÜŸ[á£óÉ|~r\Ça„Oÿ­Ã8¦Ãçy0>ß݇éð´Š£ùª¿cð O¹‘™~üºö#ÿ²>óuŽXZàY¯pqL„áÕ¹­|ÍÅy#‹oçSþ¸,þo¿Ëëà¼^‡8åöS^Š‹ë,~—ÅžE7žó•ó0‹[WºáYòÏ þ¿g™¾Í=呌ã‚__åâÿ` o½>žÏxí27ü6/üø2Ÿ]æÃO !j*^ä›áÑ<û|û;xºXüáê@ ‘nÂÖnáÃMþó—<‡ÊÍÑ ðögùÂ<þqœ@l3=£x'W‡]>‡ žì´ïyS¥Z®óÌè 6øç÷^ÓhAž>MCVvôyQðÑ,/Ð¥”f”Mi ¾ÀMð-Ø Ñ£P«x©_=ôi&ùGïeŒ³Ÿa „3[òï+Nô¶Ü3›VÐ,ýSíÀ„`@Ük™, þ…iq±+|°ÞC¢’oïŠ^â}¨s,¤s†iLYñºMq³n!̸‘Pš,>¨þ~K7£2?¡~<UÅ«w´! Üñ>èÅ(\˜`ÿNyã½_ÕB| }¨K€®òDÓR{a}æõ-Z ÓÈ«øÀbÑ#Ô•[P‹d;T¥sw0zdØ*-Ì.àÞ…V‚ ú9êf—¡`ÀÎÕC­æÓ¢ ?Âóë:9_$@ªð$åÙªeiªùé-“oyþ)"œ”­Ñió¶óø?Ž,KžRý Ö õ‘ƒê8­‰äÃàÃT6i]d˜q@”Á™eÑÄèp ®e ¯Ôçk¸oÂÇDÇ_ÂO EmmÕº]kIô!/©HëÁ+=|‰¤h<—¼qˆÐ²Â=õQô“$zƒ½£âT—y ²…Òé9‚âêÀ¸ˆêÁE°úÓB¶ó…˜c¶CÐøUY%2@À4^Ç5³ÞrÕ*C`œ>j“²¶‘¶ j6›6y¾¢$ÌN°•/¾§qLŸTZ;ž¼E»®N‚æoì ©‚`&ß‹]k²_딀I¾\a•’¹\ñò€b*I!fxÔ 2¡õÕ†ŒR luÈY–¹¨ü¥@¡Ò¤gH0Cæ„O^_ gv‡ã£[’Â÷«bgg­PVyѸ±QUöõ=õ1ºÐV+÷Bx Ò Kæp´Ødy1jÖ¦mîbR"tuo›ençÞ^ Á2+k rYq¹.y€½kð5ïJ_U¤¼&—­u[•ð†ESJ´Û?Ì„íéuG}3fé^“o¸¨Ù:M3ù$Èæaî34 2ËQÙe›¹Bûº»fž…H³Kiá6E‚û‚î¸aj?(Wæ]ßtòoŸQk@Eû€ì¥Ø6K úÆpм ƹ–Ð1bI–ÐÃây€d6ZîØ÷cò7@XBb…ÛËý·H>ÿßXLÞùV‡rºGÁ7éú÷xUO8¹9Ù>ôlKþ}û£x‰¡]Pî›L¶§¿1$’yÑw³øä ø=¬gA(7?ØÅ¡ß["–ùŽßéƒ@kYNã¦òPØwa˜C!miO"Û(‡‹[d_LŠÖgñ[ãHVµø¶<ƒ`Z~`~9 >f?Ž]f0c«®!k÷B¬ª t{McÇÕšÔŒh”å—»ê¸uÈÚSiŽDŸÃX»uÜPUë*+ÿwÒ¿Œ Õ«5než1ÁÂâh‹­g(„éöÈp¬QˆÁ¦ È­ÝEM¿\­iˆ¤v$‹}èÐîëIÊW´KhY kA­[‡ÜÅW.þó$ÀfëXæŽß!Þ“‘¯f㠵ߢÙoÐ^ Ô’ÙIêÐó­ÖÜ §x Ö„|=$58–ˆ4@,ÑLt¬/°yÁ†›ˆJ‡þ>0ïã;ÀÄiÿî CIl½ãࣨ÷˜=—:!©‚´ÿÕ(ªyŒ£C¶À)B²Ÿ•¥&‡Ý§´©‚ìß­¿96üPÔó»#<8Â];²Ú›!V¸gްJÌêsý-ºÃz2½ua[+ÑtæFC”pÉIt0Ù¹–m²zä8 ØÛAo;e [¢º,3t³}¬×ˆ% hl¹vóü¡Qĕƿ ¸°%i< ²dÃ¥<“,„€»çam.-ÍjàQéVÏtËŽ!¦XüªuÁ¯¯û ‹K’á–.ϲ.]èCuÈžÏÓB`ßËsLAX3¬ñ0†Û;úb'OáaD/.*8Â%xuôDk”b&¸ ‚ŠŠZ–hÄ—Ì£Ÿ´ø(¶ãküQ8¼Â ßìÚ¢³×Q²‹OS̽vØhGX¨eÛ7þF I-ÁM×U‘%ÔÀb×±4>oœ|‡›D ¶Î}åRf&-]°d‰ì˜~Ò(š,hTŒN•s*gyØ‹pËÉßÞ˜âéHÞº6±jôc\XȈ¹b S‰’b5!tWû½&ÉÁÑVƒXƒ¥Sˆ¶N#îë2dÓá8žU'4›‡˜š‰Ç\§‹äã‹òõ÷G1xß–åüž[±}í” ¼lˆžŽy,ipašM²>E‡® “ç8ºÜ|w”@0N×b—¸ oÙÀ’”*nOÄŽ$>.(uÅ*öÐ×XÇ0ƒ+»XÃ/õÞºE{™L°Îm#Äe‰D½Æ:0à=Ú-%‘ÅmuÎ`w*«A¾™ðúxU”ÌG'ZöšÃ5|¸^¡Ñ7^Ùûµ Ѭ ‘ X£Îo•ë¤7¢ÙõOn±õ•g¾oì"ÍÒr¬bçŠS2ž°ó#‘…¯Ù`ñ®Xª^êXé\‘&š¯+E”ütø¿üëçf âXl”A°h"o)åjû¯=½¿ v7 Ñå>á4PZª¶eúnA‡^†ŒH~–iÕ6óåQ™æv¾ ç×÷A8¢Ø}/*±1´!R:άƒûåÞ(å;×ï{&ØZufû$ ‹sBèî¹àDJÔ÷FBÄØé'—¤3‡¼#ËŸ–ÙeÑžÃÃqœæ+$†Égö£®ßÖÇophS"'.·í( œGäFwx"t)γŒÈ-êÓ%Ô2e©c¸{|‚-@m–©Ž÷ žH ¸Ó4—¼Œœÿ†ˆ× ÓKBöQ_†=·¤a ËáSP»¬q9Ï à—¾ëheŒ+²ˆeX|¦„­LÝydÐ!Élôˆò㸽ÚÈØ!žÝ• dx?™æ«Tâ9Zo‡e? ’wä¨7®Ê6EFé6øT©* âT“¤\³H6ªm ÅŽ•ÆÈÈJˆP2r”!]ª¿yMOÂâ o-`ßd%§æŒ¸!hâõÆs½”fKP¨´‰–žàËÓŠD÷"M7Pþ:*¨©½´^£Êæ²ïc@Gã’éOµ…!-Í2ÞŒî2(k9;Ê”¤2+…J4Ù"“V8:MZ"±tQ,³6/äj/Å',±å…•˜Z"»Í6›Lª—ìYö¬}ÿçGôÊ›K,†û½ô{[ûý^Ro¸5~˜cÄä'N^WStM=º÷Ó8»$¡Lc?S‰ÑY1—íÃ6 eÆ}`Pöu>¿;”{ºùݱÜò ç¡dº–c•P+méñ ײ”4+ͺ{Q%PÎó§†Hà2¢U ©HmR˽ŒÁå;½ >1N3ÅY4bIl™iXÌA±Êë¦åð¤­R 8Ò¨¨2X“0Cþ;˜$|wX}¦‹ ¥j'ëßcºƒ’TIEQM„îŠ{… eœpø‰·E”ÙÞr E\]ËŸ$èÅh¡+y—G7šRJÉ‚ÜorÌz²c¹kÁFáy>»}Ç^ÖÿB©®WðMm&\I~pºjªX$æœÒ†ÖêŒ1ÎÑ'·q}=çeõJÁ};ŽnÚÔwh=zj…y@KRñÅIWm:žâPJ=ý2!H‚&Rõ¬¤hkRƒ‡{ÒÉ£9et;u&â¦BAx6§í5bY“Þg?*Ù3·Æ³ö¦nw e l0±dd%«Qà}SÂù£RÙfð,Q,ÄT­dù0wš*)ö¹k¤-ÿkÑÊž•²@ôDR”Ê)ñŸ3q(Q[‹*¯n¢Ä—úï)!¥Â(u¤‚mK·´ö!§JEu«;ß«¢w "§XÖ¾”{c0E%eÞ Üzxè­ñ¨¥z\U‚ úUS€p²Îž+ äøD šlÞ–€²*žTôO²«ÝRôe*vå6ëà ¯–ËÞÈTË¢iŠÈ€v•¦*ÌfKiŸTÇÆ‰b,Ò†á8¬4¥3—õãmªé»{E—¥Ïvßè±”"i—RJ)ÌèÌBzcëä&;×IÛˆ2Œ+ÆÞiðeÇh¶W+w†ÍÙ¾ÊnVMôjô™Pé^c ÙlݰMM”Ì¢‰]É AotSãtT*{ÿIž»åHME^1§ÚhEÙ¢ çMœJC¨<¼áé`áL`•³§$Ðz¥†Út=z>êÓã"Úñú'æ¿1Ϋ˪Æ^Ás"ÁR^ØÔƒ¯ÓP+ xÊ<©âè÷tôM)³­€J7•ö‰vÅ/tö… 4‰f£ÈlÖ´GÜIHŽ\¹Ïj;à[±‹ðç#r®)p&ÞI Ÿk}Lß·6äÉ«Ã8 U¿õæ½—ê–V¡<¹vf¹”–´<JÚò‚ÜF7 ¡,%Tp¤¨®e”…»þ¿Q¾e?uàýxOœê1ÃÓ8„R½·URGéc“ÃáòW1pwÏùj®œÿi@zäa€“–0•‚4[Ies2 C8G C•ö½Ùi7<ʆ3UéêÐ0:Íq-ÑFå$ýó¨Òèw\ØüN0¡SµçïªÇ+‡i.(«îeá{áǰI*“ÀV‰Àô%· ÅSAÇÐ„æ ³á3o{î<öêG³eN—Ò`U`ƒæ”lSWŸÞñ3°EŽÛ˜"Féª[O#Ú:žÆ&úsoàg$]’|mX-×â#2«Ø‚t¶Oä£êòüœËyât÷¹‰'y<>Ö)ó+ÙC!R˜¼Ø*ÂXšcÅï°a¨óÆ ˆÎ£øk‰2í… é• þAZ³9 g±> ël9NÙ‚Ñ®‡¸¬›DÙÎÅÐá#rê´\7] ~áJ´Ï8VSÁhØ/Ùœ¦¡dñ7¥d6Ò)DÙàÒÆÄut_Ž•ö–›ÏïUlˆZ‡Â2î!Z¾bÿíù¨à ÊM굃 µ@^U|Ö°wR_S;US¥ÔóýIkÖŒÐF)tjíl©l§|N"Yâò´ÅP]w`{Æ•At9ü6_$éŸ5<«º].YëyÖ•§1q%…8®6ÎQ¼:¦ó'}»¹Wü”p0„±Žîn•W…_r¬ÜÍ»áÝ–ÍKp|³ƒC}-‚vE:{E?šw$` ÀchËóuÆD<àúØ)n´â>—ÇS‡8)"Ö;Öá&}3{.sÿ§,ºª‹¢à”¶ ÏÓ™Âê¤è°¯"úüÞ* :DÇÆÁ¥…Ñ€q")‰¦K§½}¯ñÃëyu’Ý»ZC…YVAÏPnNˆnXOb•[Š%ö^†à S‘µG"ƒ˜eÁh£1%Ýß™ÅV©—É`ìÖ3µV€ã×ÞËØ‹æ÷[‰ê¨²Œúž¨oªg«HŽ$1—¢‚}ÎC¯e)j+õц aO‹OMœU¾B± ÛD;6¥Šé6 ÆÆ–Ûª°øuÇš>T“Këÿ”Ú„e©5}%ÁШ†Šž ñOA§ZÔÎåº}[³°¨ƒ™Ü(äBªÐŒ¨$éÓ6ÑØ;Kvþ”ãKº›„ ©ƒ,'œ³-’ø^­^Dáø2…0#Í1í [:Çx[×·)Í)6î+TûxÖcýê©T3ZÜ`®p[[X«>ôȰK3kÝBÐ’íŠUtˆ3É™¥ºáEX‘tÔ$,t’vGmu­ÇPH´ 5)óÕë¸)=½†¬B[)ò-9Õ‘Ø[>PÚÄ–U s×n<<‰J˜Am*§ãþ£Â†åµ™ J’ðL´åeýž­OÔº°ë¢:Üpb{X‰BýH,î #Óì¶,7…h_¿§*ö_!¶=ºdJqÉ»þ2l^ „‡&bËbÊ`KîŽ yZé¨åöÄÈî¡øõÄ{ƒ‘[Â*ñÀzš÷õ±äì…¾Ë~dQI¡ÈnQYÏãéZ+[Kf~ƒVI?µ›„ËÖÛ—g,5ªÞŽ-Ac-6'˜Ær²·ŸÓ€+ÜçZ¹à^´Áßçm*ÊVÑÇêWÜËÛº.ëÇË¥ÅýôsÑ…8íå ÁL.FÊjr“'+G¡žQå«IÓs‚XÎ_¿—#¶³-˜·Õ)ò&¿XOÌ™’HIMôØöøBD2¯e(/Íè¿X-Óv³Þ ¹›“yiƒÔöïØRS{¼øt#ͱU7@д±~K±¶Pz?¬DÍ·z& é[ÎOŽË%%o©ÞIPê.Œ§/.·ÉÙnØF7ÛpÊ 6‡i¿©x¦Â˜êµ³Ú«ƒsžò+&'¯K0t˰@5¨S{‚ ê8¸Ùé³s{¯2¨ì‰SµZÛ%`cuB€ceü²‚-û«¿ØüFkKõÑrL’˜£Í ªSýÍÅ£?æÿòG17endstream endobj 141 0 obj 5817 endobj 145 0 obj <> stream xœ­\[“År~WèGìÛ™¶µC×¥»«ƒðæf9@ƒaü°ha¥8H+$„Åùõ§òZ™Ý5{Ái4ÓuËÊÊüòˬþõl<†³þ㿟¿zðÑ·ËÙÕ»ãÙÕƒ_üñŒÿzþêì_ŸÖB¬ß×q gO~@-ÃÙÏ–”c<{úêÁâ0ÆaúŸ§ÿ^[¤àZÌõ±\=½¬~:œçÿ Ḯ%¯‡O†xøëpOáûχsùáÛá<Åñ8†|ȵïãp¾”õ¸–ùðÅá™úéq{šÇúô|øn8w?}=Õ&e¡Á¿?žè žé'3ú“!Ú.à ¿iÿ®?×OS 0Xй¶šq)Ðî³úUšëWáð¥Nõ{m}}6$h³â ñðü?@øUíxª,K$™ú]8g¡ž§ñ¸„u%ÙþpRë;ÅO_ׯÿVýE¶® ô8¯ÿ‡*é†ú¡Š;Zòáu•'´Ëá'XmV™χ|¸¨Ã¯ôÇuý×oõ¼Ö§üñ |_ÿHkmJ=.EbùðªŽÍòÆoë’qˆ´Ô}Ÿ°É/u5ð·y”zŠ(ᵎÈKzWNU(!µï®a:3j Ï5%jÂN>Ôý>¼¬¼@Æ)–ã\DOµxàµnÆáªuùq†¬0_Xa^p&,“º"XðEk Ò¯f]ÜÉ[XÊÂK‘ŸaU 0«”²yúcxzÔáH4eJ‡?@ŸëüfXÝ9/ï<¤ã4ñ…UÒ Pb"æ„»Æs/7yδ½—´åðo}”Ïÿ *sýÿ?OK¤ßÍü«TQ3à‘? ,¥ÔRŸ¿‰¶U»„Oд$ìI·ôe…³E[ÜFÅYêc/`$Ö³²ôR©¢¬"¡ ½[@;Öº(Ô£±—Yôˆ•:×5±¶ª¿WÕyGFgŽMµ·1àDš>À™B䵋Nô”çµv]ñ4­(š'<®m€;;†¨rkÛXà!óð íÓ©,é-õjZ‹ž'ò×ô9êҲ ¤í6àô´§D|öGØeØQêVrS Q Õã×¼¡eòÆ Œ<jÇ~VdÓtÏxV ¹Ÿá:º{¥*#Îò…ôǶÚª¼Ë}­4Å¥(Zô¦5Æ]zÓ  ð\wÿ'ZݺƾŽ5=¹”ÎUºÆd¤%£¯ìí¾ö¾ˆ‘¨_íl½ÿ.¶çF•WÃTWê Ó~këØyL¸o;ßÃÖŠ=P®¾c£0kÀ Ò}ήzñ† ~Eͬ§g®êòŰÂBæI\TŽ ­€ßDr#u†¤YFƒ&Y/àŠkšuØ–×Fóm;akŽSù½9*í‰ç‰=…i3:UdŒjƒDdJÕ®-dj_ÀŠÈþ⤯á4n°!àAã㈰ææð,ü>LÉsn^²Xl*JN¼ö¦þ|g«®œqz!"ºÑÉ|t.ëôfèZ”D=MÂY«vÜÝšàQI­GÐ ø Œl.þä1Æ(/ä1ôwSpO`;œ§2>¶«b©ª"HK•úI²ãõ<ÕøÝ{Y=-zìdŸó9ÀGÞ¢¶Äu>Î Õß‘k[Ò¼¢Èc*¨ÁhÚÎô\S@±Ýñ;ÚþÕ…9 ù²õ0ÃBP[lô<±Š’tÙe«vcuš¾Ý%Â(½£;ó^Qï¥åáÆ9C‚6¤ôð´Ø´WC\éÜaß(W0 ‘ðêCÚ¤ó©ý2&ôÒ;µU\çíBŽ7#6ì¼Y»WC‚UsÿôXä<Ï M½gUgÂ[IÎ":••Av® šYéO^î9V0´VY­ÕËAÜ–7 1!Ü¢h´Ä„jL~ÚþAÎõFê/ˆ2“z².—­ß¾ç36Kln·AO6G¼oŽê„)ÎÕIÒô¾E%!(»zžÞŠ)¿"(á@ÕDŠ­ê§[]Ï%—ÿD$…§ªÜyBcìÕ~+™fªÕ.ɘ҂Ñ) ðÙy‘ †Iô¸=ÍÕ¡é2ªEi6´ƒ¨;©€áÍüÜË5ò *¨h=Ìâ2ÑΊÛY¾ vWÒ@∠øYçÔ÷¶bTÄÚs .ûŽR¾b¸ý¢áe¯Ø«J7¨PJPdfh“k?áp³½ ©“ï¡æ0õ ê¨ÒŽcxƒ·3²x]ç#x~±±y¶tÌm§ƒ{™ñD(ôß/ÃàAÉŠÉßA°²;ã i/Ë*‹9{pˆMâµùr¢ÑâA¿r[ÄÛC’/q#qÁ1öÎtÉN^­›p3b „Áº¢& x@ h]'H DáÔMÍLãÀtÊbÏè…*<Ÿ‰ ØL·Úý^Òh0M:͸Ã|reù–Wq)muÉhÛù/AfÌ[‘ŒëˆU\ÄZß1Q“ÿ<Îʹ3w5,àêr"Ðg™²~¼—ÙÈÈ\å®ÙГ'bè>Qs€¤+z´Ç ò(ÁpŒLš€cnáèÕo€´yA|¹µN¸¦b p:9GÞ…hP,xü•ýîîobfó[…_ÓÂa¦ÿÒ¿ÔnýëP&ZÀ|ø¶ÚÅ:ÅÕ…túXssGbAuÔC;0®~P¡ŽRêßö“É¿‡‚MÀùšV¯/ÔL ŒNÄÂ׈rxÒK¾}âìDí#%© ΀‚bòA¾hÿý5 ³|³[Ýom‘Øo‰ÿ8vt…¬å%ÃÒ|,j|®d¾B툲æÌ™pÂ4-a<’‹êòp4jÞ( á›‚"¯eÞC‘3`¡5 íÀq ­nk™ÈÃkò@Ϩ¨Œ¸ó‘˜–² ªÊj+øÃúÁ=‰`Šk¾°“ê‹+´;&9®S³-Ýp9®Im0ô]˜ú'b”îëÛ޶àÅÒq }’Y¦r‡ôg– Æ<ÔD0ñ7Ja t÷èJhÿ Æ<+BÑqÆìÆ[-ëù)X?Ês>bPQé.ìqho½ûù²~øÔå1¿“§6”«ií¢fn |™Ç°‘³>eBPÝ çI›Ñ_ÉÛ7TâhÜL-¾>Å.ø£„ „¶®k²_¸ÞrUi–­gö£o&‰A©QƒÃ9œ•ÄSAa˜´‹cv™7üžàÖu¸Ôø^˜'¼«CMÐ÷fuW‡*èhëPÉ ŽÆÀíl_OX#PGaÒ¨#ˆ’ØD<5\4éÿ¢F$˜¤Š¢‚Ÿ¶¼wwßÔeTÞ}¥ø`ÏNešb¥ÑPhDFw3AÊ –IMÉ ÀnBZ†×w¯t3ßwO —× Ž„ ëMÛœüºPïjîÀ€lO—XÜ6ÿÑN?ÁÈ¡ß1ß)4 aQafB¸' øl•¼8ÔÙÔÓ§9…Fú¹ ©ÄcÕ3‚j©\Ái‰ò|§±Ò­vè‚aÎTîJ!ö)Ë¥˜ÔÛâÅò³B¼aD}:Es0hk[Ldg5}™lÑ…òˆÁÂTÊ¥Ì'&`TÙ¦(Y^ [²G Yäž6fBô0$¸1SÞ?FvÁZ€ËŽÒ=ve8>­)ANp¹áªœVò@7ä”0·Ýã x%Žƒ66‘Íäô®cÍx&Z?Q2aÄÙW8œO¼ ¦š¡ÛÉu*À€fêÀ™ëf‘û°xêjÆ>Én däÓL¢Nôp®ãM;œmØÇN//a”ÊKWn|N{‚[mg â†e9R9À±œ"Ç•},¤-7Óâ#ÙïòÝ ª€a¶¼¶h£%$¶³Îœg½+lY5&ãŽAý®œ|. “œ.ãYN5úJ­…éÿ‡B ¯ Ïu§"Ȧ’6 ªs” ›?\¨WÏMm¯-—Ør5ƒœ©D¢±›˜„ÀYD¯à·ïa© q“—üXˆ—½Mž½ör±ˆTØÂ§LV¶ûæ²æðR<ɪ5—ì²e›ÃG¬»L)Vhi×òx;_í]ø{ëÑ^WÍêKX ®¿Å»ö2éš>4š3uPlW't¹Àmr§ÞÅî Ÿ{Ø¡02‘xªÖŠ<,С®äøØ*‡@EÇŽ¦ô¬ÝHD­˜ˆ ÕÔšš´ &¶‰A²²ý™Kz£Á€ŽË|³ÍK õ„–NÂUs1Ro ”d5Ÿ Étï˜1ckÞôP’” ”É9R­Q?‰)}*å1½ï¨ú*ˆ>ÔW‰Ÿ®2U›Í§¢N”{t™F=uzª5N˜´®X®hbFÝ]"h9@©´6lGËÃÙ››äyš½Íòœ…Q¥]ÑO.áú5S†Î:µ‰rp 2w S±öR’èÎPÔŽ±¸T½ŽeÇkr®Ï›*fK *w+·—1(¡­Æc‚–ÿ¯ˆ•UJ)‹(¼ž2[¡–¹…p2rÕzرtÊa Õp¡ò=«ŠˆVo Ø¾í©ýØ11ÃØãVë(\ÿQ‹Å>÷æL(΄¦JÕjÀߨ½­Ÿb%c¼ùÑ·å¬Zˆªü.VÕ­˜.%š‡pœ(¤„â)„´‚~7Ö ¬(À¬Kí$Ò\äã÷±.¾Œ3réà- Lc!/>ϸ®Ÿ‡zö§4X¯kžøšç?ã1Æ2¦RESeÖ™?,HñBµZ^£Ì*ÌYÇŸ€ˆÇe+Â:~Y ¤ø%­¯ÀÆ×6cÖû±jƳ¡,5“ýU¼o£´®ßÁS sšzØR¬ã®‹ÈÙqº±D®.¡ûpß5-ÄÔßGucëݵÏ7ä6Üc[êSý?s>­ªUS‚Nˆ!4>t‚V¤# §BõzØW¼RÙNHw5"°mu£º¹$˽ïó%´ òb ÃKáØ‰\ë ‚w”‡H ó;f>z?-NCãb0}š÷õþžzuõÓLýì5CmèRR’ß $g¸ÃÝ•X°tÇÍì_IÞÁªÿz£Lù fs* ÒMλ¼_K‚|P”¿dRßö£WÕðoÁï1l≪Ês³¬úUkÂê—ÆŽæ¥˜MN²µñŸP~Š3U“†à¶Ù§fàiëQëªUhWÝ`‘çh;Ny‚›+‡q<¡G.a”›€ž¥$~ò7qQ©×›€ÄkÀïÊïŽtùÄ3o[íKÞá™óã+Õù‘"’t¼âÝïDÄ&åØKC~"ü“TaÊmg6áÀ‡Aë+ä¬çNÏêmÓéú¬‚¤j‘{-@ÒBÕw×¼Ä;”3`—uYß«þnÒo¸áá4]¦PøKS)qüð1Ͷl<ÎJµ˜ù-IœC‘z+¥G‰ðÀê–¨rC-  º«a•¦õèÊ &dgj‡w”1H`5a_W[EÍò§“¨dFWB­[¾-­ YKS³ŸÚ¹í ’»’ð+ï‰ÜçŽÈO'®ÿšc3Þ¹ÐFBèy§¹”Ý-`ÁÍšÝg£É}šºý{)ј="¢?ÀKö[pKºw]½˜ì{j¤úÞÒ»d®5Ì_Ë•ÓÒãy¸½ðZEYl¸J€ìÒFÍ‚ÙD­ $Où1AqêÚ¹¨žñ)nêÑ›ÖÌ¡ŸP%rÃ¥*wÙÁ‚MNÍû <D‡:lh„ªêñ•\F¿Í´ ý¯b-‡.ubî]¥kµ²¾`žˆ5ãÿZK],˜Üdw £Ä/½ëð³½°`&Ø ²˜¬^Él—îð)wê°ø\ƒ0tó-¿YA‘tÓOº"­5•;ûåƒÝ +Z¥7K’Go7Ý¥E“»‘\cŒ¸Š½¥Žl¶§R¶ûŽ'†}·8’³ìe•Ë€¹c'‚åÜ å×}5€ž kPŒ ¾b ¹R§N!k×ÝR«(w#Çõööåó¼2¯_ªÎ(HýWEÅ5Ú® Ø—UŒ[´åþEö ôÆ ²5ÊH“)ÅvÅ£aÃæ‰9Su¿Lv ¯í—[J,åa+^¾önIl‹½ýø_±ÒÏô-o_ëǯy[jAlb)ë&_øº¹7üÀo/hMl(êëG¸ÙIœýHê«i­aòêŸíÝ÷ãªï°I‹¾ß]ðÓÐü„V–lÞ¥%è\ O²;éðN‡TÂ){%ïãÚ» yû—/Ú֫Ę\áu »@Ó—`û\8m Åqù˜ËF»äÒÇî–Æ~¨÷{ Нj)˽£ý’îÍ=U31•p‡ÇkõJLIiP.@äBZälH ;îIIQÔwã%…€`l.G½ ¶/¯È ¦›‹qð)¸o|+uR^›~mŠsäÍ>uÁÓØÓ¾^QÍ_c1YH® =jA{­ŸÙv•Êy¡Íìý¢‹M)…Ñ I§5O“×ñæâÜñ;anZó-¼¥¼I<œ°rô6Å@¶¦¬Âîã–@’°2:d0«Ð6µQJ%(—§Ò½×%Üè¢%lò[Ui˲wù²K~ÙæË†¨™vUÕ,gÓÐÝa´«ç‚‰C‚¹þ /£Ô*Þ;¾@޳vøº Yý=8r²ÿÊçÎB=oï7n*½HÞVíï¶v4B¤›Ú-‘ŽÉ÷£\bnºæVÙ,éÉŽîÙýàcNÞ%]¦„§ó®ŠÊB°½±ôä+žà)YŠÔ¯IoÀN”Éì_r“Šê˜w|x'“Ã^“_²„žx-7´Ïx¢ î$tÓÍ Ä{í…€FH¥%g|LRÈR¢tá¯eáŒ#Ä埾üÁKœåZÍÁ¼}å6åèe°£É¹r“Û^U& í7bd´ðoq8ÁùùÓÿQÿûVÛtßendstream endobj 146 0 obj 5931 endobj 150 0 obj <> stream xœ½\[s·‘Þg–+¿o{NJ ®ƒy؇øVQâã]y“ÚdÑI¤l‰vì_¿è+s9$µ®-—íà h4º¿þº1߃;áþÿ‹7gOÿc:ùîl<yöݙÛçü¿oÎ?~^W¯ ó8»óçߞѓî|òçSˆÃèÏŸ¿9ûË!Óa8úƒ«ÿwøû¢Œn]:üé¿­·>;^øÃŽ!”a.ùðüx¡7BpÃ<ûÃçÇpxFíüá7õß/àž?üçñ"Óÿ>^$|ÂøÄ—ÐËçÐjªGéº+qîûöp±`Gršãèb†wŸêíóŸåö×<òú4¹Þœê-iÃþ=ŒàzéË£‡ù&‚¨ þçùïªT·RiÆRûüª Ó“©a9wq1{hwÁ /Â8Lnž©}¬/KS¬¯K0$çÂ\Ÿ—k®ÎÖÁH]ÁÅ8ä)Ìc8\×IÔ~}â7õ©)×F‡›:©iB™ïëÅ1ú¹ô-ëý0äD2¯ó*ÎþNo-ž‡¦.ÇÃe½j‡×µañƒO3ÈLn·g~†Õ(SÈ©uŸ·8þTâá[¸˜‡P¢1…¢£‡žÌC<¦Éãƒ÷e …ÙçyJ¸j0Á9ÔE®2ô.Õ•ù´þŒiœ'\åÚÙœì¬ÞÑ&÷=´LÙNõ¼«J"¹Ù^¾=†„"<üXûÏ¡*ýdîoéA¨ðÅÙó_ÿ…tì}ýÏŒ²Â1Ô† n7°n«ŽÐmÜdßöø¦*ØwUš‡»ÚÔv,ø¬Þ¼‚<>ð¾î´ÛÚçPã_ÁcÜqÕòq¬«ñ#ÜvÚúî‚°GØ®Á;…ÿ¸¬ÀŠ» Çú®m5ÉÏÇh»€'ayDZ>§cyÀF­³€Éd|y7õQ{†ë8müÏå­C]žŸ IA{p‹M`à¡Xœl¿n.ƒ·¼®C7î× ÓyȨ¾……¥aSÏu¼sÕ#|¤>WÛ|òem¹¡Uóø+ÕöÓä7^Ö®ŠƒåÁ½ ¯SÑýؤd}´æ4sáZ»×1T.D,. )ƒ¥éX±£ÄãÔ)TH8ÓNcªõ‹¯Ö´Ðrø¨ lØEœ^ÇÆ7­ÝV§/އc4 îÆ‚£ ‹ÕQ—vÙË[øu„õ숨ü¨nòOP¢j€«Q?©gÑãB±6„˜ðMðÄM“¿NÖî¾$¥t¹J]t†šfÈ蟰]í’ʪÍyƒîo鼯OÄÇÅ •š£G¯[WÐðNÂB]5gÙkh¯kðYzì'°”õ–ó…TŒ&‰–æBs…U“%šfÖªÓ·³ÁÑ2‘ý‚}ÁCÃgƒ‹}7žVCe&†Š¯‹y'#X¨Q}þ†ga?óhÕò=¶Ã®¤­Yzhx¹p(誼=Èk_³Xq¤.¾¤¦+«×‚Iw•¶ú³þeì,"-x© ¨à¯ŽŸJ0Jö4¯««\=*e-O05Q›¿að°h…&ÕºxÏwf¿0d>¡Qq´_¯T¯îZ·¼;CˆõgÉYé˜P¯@½Ùúá˜pBQõñN–è Հ낣4ÞóÅt” Ç4Š¥ñ9 Ìž<Ú´ëö(/§O5è’5ˆ•5¼¢³;jÿa­Y~rÛžðÔ5Ý…€ùÃ1·)nÃÛ´‘Á=¡&O»ÖÒ<Ï©Än͹Bž•ËÔaç±]Ä—ÜÉúzÑWÉè÷A3fÜ„Õ9û¼aÑp=@9æ¶)ôEBÒÖkÑå¤ÎešûOd9N8IÓž”ŽDÒ³-—%ÁÍŸë¿KdÝéÕ”ì*«v!Z´M,´gö˜ À–£Voáò†^1H >âݱ9²®#âvý*zv½Ûº}öü쫳ïÎCÅîTÖu(çÁ¾)çÙÍiðbÔŸ=}öïçï¿¿ûæìéŸÎÝÙÓßÂ>þã'õÏ>=ÿ—³Ïžµ¿ö[âWœb†× c¦ö>Éì9•<äÿ‡1ç*=ßùmùˆÎ.JiÊ £ïŽ4¡.œÿ(‹OV{g¬ð-Y  Wö¿QöèJSšöžaÐe·£)¢0[Oºic„‰²©ŸA(½µ7)œp¬‘”TZˆ8À¯¹•>rÓöÚK½„'W¢C¹†[`²`uÑtÔõøK èA½ÿ†¹Öaá€\PltÛüçq³…!ðÞ…7h”èqQŸÃbb²Ö]¢}‰‘ŽË•‚08·ÓNñ)†äqNªãðï[^HduJ²N†B¹q¨›‡ÝtH.Üã+Áƒ§ñ\Û#.¢¹î<£»µF¾ãˆä¦!yÛM{`XÕ­Úõ@Qˆ26·#¨æèqÜ[þèÒnÜP½#!E{u2[¥4Ö¤„š>c €†}ЬÄ„4âuUÎ%šçj®%bÖÖ~„㸡Œ,gJû=ìGõÜúåNndÿ½`­{ÇlŒò¸à;bAØX ¦Fƒ]ØÙGp3ϼiAñΗd €4e%è ›GsK¢¬ÀF· õiîÆF´ñÚ U¼Å~ìð5I¢·ººæöiáaOÌAè [˜M)mP\Ë8Rî$ŽnìÍn‡G˜Ý’G þ̲Îs#Ïú¥UÍzÈ‚>iˆßØ6®õ5Òm[¦9œ%AKQ»Š;˜Š§Å–Î.[Kg£ƒ8Í÷¯Gß¼ 4zÛL܃é¸Ü ILŠ<@3Eÿìü»AåM…PˆÔmg4H&:|zL /œçvb{uã¹öÚ\±5ÊS4á(R’äí!åði•Æ×l½kJÆKP›R°vkv„ bÅ7 €} ãx¤ÂÔÕAY^nÖˆþdâˆÂö ï'5ݬœ§Â7 ÕªØ:Ÿ¨drnûfæü†×2þ-ŒRÙ0K¼äC¨ÇÆ ÁË=2tBÙm…`úÚv[¤ÞHªöÆY,Š \ ŽßÄQÂôªŒÄ¥ÊЍ„˜^Be‚M£a-ë™5à:önIñÑRúMd8oyošvo–~fÄû‘Ƕkþ)bà´ÅÊ/ò³z]ô µ¤·Œ#%WìõcgkÅ…ž2¯šj#ÖxÉD\YtÈ2‹c3Hem°‘)H£µ¶@‚K\[µÉu‹~½‡½ìÊ r$vÔˆŸ1íÚlíïI¢WºZÅ\ܳr‰ÆÁ(UÆaHæÖ¼å7˜^@¯iF•fñot¡Šod3c‡M¢¿‡Ãrª­š‡ETè7V”+$£©‡»&?ëæ•öFVð¾—)®G° A}+7éÌÞê\y€ª²eVo#2ÚHÔo&â ÃIÄ3(ñ!~IìC'%s#³•¡e\·ˆ&°h¦ K1ˆWÜñ]‘‹©D§ô þ,¤ˆ¹âÚžF))ª†õÍ©ùÈU¡Ò|ËZ$ÞZÅЙeZ y‰e®u_—Ÿ¨œò^bXèeìjYŽpbÅM`‡ ~zLKW¹@´ `¥·M7QŒé”®èô¶TDªòZ*ç¥+Mc2ŠöY¤ÇAÅ]°×/ XCI-Š[®Úë—3O3NEµpE´F‹îV¹ñ3ìÑCÓ²Xü°]}‚ÑÔ`™´¼æG_MZmÁŸâò/óFÐ$«ƒ²½Åä ÷Ó±cg œ–f$w+û8­³Tª­óCQ¤¾¬~òG-Ÿøê'20F2›8íx†IÞ/ÍЄE¸±/USO/ÐI »‘¸ÊéƒYµ$¸O¡]ÇžsÍKnhLk^ÕÂ:>´˜ –sôh¼ZªÓñRàèÏ«¥¡¾`KÚÆ…­|§øÜÛ¼×Óˆû‡ºæ%´Ã:n*·û€zŒ1H,7ߪ]°u+¶½×À‘hЇëŒ_£ëö¡!ȤW»eW×Óñ6ÿà§G Ty°K(Pºcv¹²‚uÙ²"§”Í-˜ƒMe°G¶óÚ`Ì¥PrC*V5!´(s~·‘´E]e©È`™hQ=Käµø% …OÙô³ðK[Ô7´\ :Hb !þ“½E‚‹sÃ]ë:Iò÷±ñÍj½ U¶“Ã{‰‰JÔ( ŠÌOio`¨ß*É`àÓ Ÿ‡”š¦¢t4ìñRïþÒ´ƒÏÙß°£Œàw-:u¸"Æh#¨¤oÙ’¢+`<–š„U]‚jh·ÀëMs˜ÁU›•îWFQ7³0\,aKylŠÓE'˜ Fåb×r#U»Œ´ÖÇÌ£²ïˆÕ2¦‹ç©óÃR»…t=¿tÅ´5+‘êÏ!eÓät5Z ) ¥{juã„hé„hö¸>Ác›Åe9Ž C¸ßà\žF ©$˜9  ßõíh:«JIGÄ6r¨ÕE"‡à]DKƒ·ø3À¦¤š†i6=}áhr¿Ñ»`Æsuä½à!phäv¦iðM;fY2ÛâK<òꫜçÓçXï¥T}Ѽy+À}³º;²7X¶5 ŠnôÙ€G–µ:R’Jš¬à­%'RaáýGĹŒ»å„ÄÆ*×.u.Ôf„éýQh†ÎÉÿë†>;¾Ž·—ÔusBP°ëf~±&’ù©5]ŸÞkäÎ6úÇô¾ãW Œ5i*‡„Zûü(ÍNó ³æÒ຋®ª™§»sU‘ÍÔ³ÿtmn’fý2ò¦Ó]µÑÐg]=CWQÜþÝàBÙÕ}KÔ£‰?I ŽÅCØÍ~—y™Õì#²À@Ên™Æå‚<²äÐãæ`€åTºsÝ×½á8à=óé…Æå(-"T £€¿èï„€ÊLÍ ÛúÚWÖsr­^f^Kþxz=€ú#´Ø§¾hÊHh©1‘*ÑÚTÔ,ØåâÔæ¬Oçh„*Å{ÊóæHVk¹ÍÉÓYóV™ñBg±°˜`zÃå-¡gÁŽjl—–$S4Ù pÑf]­¸‚à X¿,CÞ3FXíï±0<÷vˆ+- Ú.\„F/-h’iïóªÕÛºkôNÔœè¸(¥]žð6þϯÒEÖŒœþ×±.´.N‹î4¨mëeq¹’!N ”ZÂsÇBÿ“¦k½=q„î°¶ÁŒûŒ5íyZ¢Ê‚D– °èñw|J„¿#«®àï ì܈@j¨ø·T¨Xà°s»ìw›TlÀ¾ÎÃy¸~dôK| ÐìTg€¡—ö§¡‡É'¬­§xfà굘ʲi¨.ÔUÜý|¥¢}ß5¸‘W½$[™ðB| 6õ#€i~gEÌUŒ8 ?ÉÓ‘€Ç§úxÝ¿‡•#Ôå}s„ó©Aã0•âsd–e5NéQx¦êôþ N’¸”æ *4_··ßÉ8ÛkÞÕ_U‹ »¶ÛÂÜU *6w²šD;Ά)­È}PÄ©w΂;ù¤¸¢´®¤Â ‘hÁ>àÒÞH< ß×+õgÄWLžØ.WÌ â\ñAõöµ9.„Õ¢Âj‰‰ª:R@æžë ý¡ßC«‘¹îd°" ,|ðÓ´£÷”ùž‘¡óìBhÕùÈ`ê;ºí±%©d\!=Þ‘©RÚSe &lë"`-?¸¡emè—]ǘm•¾d€`ÎSìžúêÎ7™ÂU=—@uœÑ!!,WØ\‹bÏx$×µÏÓ0ÖX8¼.£ Ë’[íZÈfKZ¶u++­Æ¿?¡•”e.”L°G½×JÖ Ñ ],C¤'I,Fºm ·UoI|JÂ¥Øô ߱ߢߚdªiEI»„©R'xdôƒ;¦Ò~ ˦1|! e,‡²BæsÌ‚o˜P×Ç›Õ[ž‘öÓÇojÖ<šg>¸ÏkÀ×ÁäI%+¨зÓxP«;>$8ÁbH“t„_*y”.è÷¯N3§”·umI'lÛ§˜ö¬ÞÖí­ÌWúaÉÏoŸÜ Ó¬‰JßF©º1Çb¥h3Ó‡MË•So˜øQŽ}/SEÏ»µárĵ>,Jmº¼Á*$iÜ™jã>˜ “cË@–â)HíN.JY5}ÞŠƒLñ·ÒݪTª 9çšÊ"ð3êÇ—~+ ô=a;ùØ{—mG‰rF[ÖS*Çf ™: ¥±þÒ#- _QRB•HxÅpТ 5*go>%§MŒrÙ3ïù£\NÎ ,ŽÐŽi\°üéZý1Ÿ>}œ"JTÚŠÚÂf>ÐÔ )[Ç_Á` xO‰’åb°=t@åpŒxî?†@ždïsAZ;ñáÖçD)E’é|ðgº@5T¿rÙHjËÁ .6ìÊ)Š–SÄÙœ¤¶ìiO«Á> stream xœÍ\[sG~wQü=¡³”Ïfw.;»Tñ \ Q (àAö‘%W,Ù±-ñ뙾NÏîžã#ÛT*òÑž¹v÷t_O¯~:éÚþ¤ƒÿøßÇ×>ù.\¾zÐ\>øéA_žð?¯O~{–ô.?i§nêOΞ< žýIr'ɇ¶s'g×þ¾qM„ÿÿyö‡ÜÃ÷U!7 ¹ÓÙ.7ü´Ù†Í¦1L›ß4nó§fë6gðüwÍV¾ø®Ùz×µ]6!Ý6Û4Ní4›Ïmò§/KsèÞv¹õ°ù¾ÙV_} #å.c¢É¿…ßè þ¢ŸÌìß4Îù%¬ðÛò{þ:Š®‡É¼ ¹×€[~ŸåG~ÈúͺԴŽõYã¡Ï„“ºÍWð¿€ðQ8æ&)9’i­…- uë»6õÓD²}Ü„Íó,¬›ÆåùÇ8n^7~ó4YžÜ‚t.rìˆ;9»Ú–þ~UÀ¶DïWjVÚ= ?Ì&$îç;cŒ,Æ.èo`¤³|@p{Þ˜'œo3’è儈eýªaÆÊ…‰„À‡9?$¨ì =ºì|Ró/à8Y\4Fúâ×y±ˆSí‚­¿„Ý¡Ds`‰ìœzø¦…üÈ]b@µ›OòGבLD"Ç `¢ñéû/Ê÷õT®²¬¾Ò‡ÏKË}x™[f·í{}øº´|©ŸêÞ¡£;4Ñ›jæ{ùÈ“?Ú©ê±PÆYJ•¿Öw"àióÈÎú½k½û¿-_¿Z¬ V°+O[ýˆ‰ª]ÒÌ$þ?À™ƒÑöZ0Ðì©6…3 [e½*æñw„à¶°ëx GÈhå®húÙ»5Í-_}˜¦Ô‡•ðùáÛJ{üðey¸Ó‡¿ÐO§ §|vÙü‹y¿¨ d¹À2ÃMeüð®lsÅ ®‹¾¯)´æ3˜ÔHÞe¦ ¨ šC¯ñií5ÎÄЯ?°uä ƒSÂÓï Ó †aõ¨L0Ó"èØì¡Åv°ákQë8³%†«[…1€§k¢¬–ÀŸvâì¢}¾‹ÖÅæÎù\5Òk}x½f[Ë3IÞz hL'½~I 0ã‰Èþ–™E¯ W¡[µ ÏÐY<Ïþ2',„ ”g8+DeC ‘Ëñ¼XÍ`áµÅF`]DUì' Ѱƒ‡°;Â';˜,TÄf`žc"ö$"&kE>¢8Ø:O`µê< îah Ó³f†’£µçeƒ|º¼åÞ+Æ'”øX‘cOt;ƒ. Wñ½G5c“羘6¿G®,ü@(qË›ª£ýBÁY0v!ÌJÜ8®r 7M± o¼$½¶¢$çæphªïÍ(È„Åo` Ñê×þHE‰óCO|^Ç´+o®×f7; ŸÿHc›1ä¿*“Å)†aóW$ŽEºFX•‘ˆžÊ'p­è…ÝðýØ;c×oÔa;†ÔöƒeË2ö§å@~ŽRñž©¼¡1…ÛHª†¿A›bYÔ”¾’iž=5KY1¼­SÖUW0ÄÊø”(+Y“Yp˜~Gž ëX®MlÏÙø}ÒôÈ3“5(ù8d¡Çqáù¿`q¼r15°–Î]>“„Ï* )‡3;=Y®Ýß{xì¹ÅËäCœ»M<"Åæò'ÏnO¯ûãÃá"P™ñ† (ÅývC‡z’踒A©·™O%(Ô¦%ñŽ];Úó×îMOºHný8ï ‡§ÐýY*§œ*Ô]\M °'u ò’ýªO缚K~ž7ªtÄÉN¶^ÄÔqÜî¶1pK¢ª]>g?b˜g?È×ù±xv4àúö$#|h=¤Që\ĆûãAÒwB™Ÿm b|¹À›B˜S¾âAÿw,pw—¾¨wúlÿNß*€~*½Ôé•Ä‹5» . FÿGChÕˆîÿ€Eƒüj¡==ZhØò†¿÷5q#jÉ}>pË‘ø-·{}ôv±ås!^†$á`w¥pìîøF;™ÌSI½ÜÖÐð‚ÙÒ“=t,zÀ$Öÿµ‡â¤[•Ø…Aþ7 Õ oTg2&µînÖÝ­ºƒbÝ“'Y«©z› ø˜…ÓÿÑ2‹†ª–²ð·kÝŸ®éRÌsÔƒz³¶È·ÅŠ\ÍÆÞ•„ØiuWkõbvºŒVwŸžÕhE«Û‹,n1«°$ôü)¬æ®"*¢Ä¡½\•N!8Ô´6‚qùùˆð²º¢º™Á„B‡\¯p=0K"D‡Žd‰ÃÁÞ€³MaI/ :5­¶„HY’lGXžé—’ª!2>'à9¶Jü,\Çfã°J*ô.8-÷pk Æj,&p[Áwq`¯^GIë%™3™&N›ŸiO7Q™±¾žóí%í½&z¨KµšKQê9§šL¾IÓ-à¿§Qylª#RÝ5#¥í)LK$%s~ê°“eos-A7q9¥Eùk'Ö)Dçž%m&bx…bm)5 «º1€ÆÍrÄ•šqLÂ!?sëŒÈ3!Ûñm8PEÍØ£„±é ÁÊÊ8ôIï*1·°NIpûÀŽ{“{²ì+ ÷åÛš±P‚“$á^$:ÆÉá°O0¥ ž©Î7oã Pö@~S­ƒ£Œ~'ÒŒS[%-ͳ9ÁÆKiñI ’­ÇÔÇ„Yɼ :ÃL‘<Í42¤ºaujj^-ˆˆ~ë¯qز‚>¬¸DZ"Ù‘kG-«Ð]JCß*y”Ýc9øGòMȦž/Pìx*•ý€ƒˆzãÝØU‚-à d^ç*Û[iYº›5i6.Üü2#Ue9S¿j%JK™Öê…ÓÔꛉÍ4ç0j ¯ªºuÌ‚¡èxX)“Íße“¡îŠíŽO…,¥ÿR)×!yòyÚœü8+—4ýÈ|J¹ÈZÞ¤Nœ³Lv€BJ„!ÚùšµÍRA`âêÕ8¦EÏ,ãy%Qé%e%§R™Wš¬'ìøxk«½VFDÊÐÏn8¦ Þón`f8÷b<›:mq+‘~}½£Ø|<øÁùìÌëp(»žZ[ÛP-lŽ8½×â·f+0 ]»…!¯`Žd±£R&ÆÚÇåm)© Kü† ŒóÚŽêŽ*oã’«T/· Lá ç†}uWgÛ°,‡²I.{<æ³Ý½G]'”A×»V!7«p ²‘«7…%`±ĺ¼€~Kx‡EQ¦t< §Zi%ãU_饨É8‘pßFÀX‡kŠÀþÖØ2THÆÙ¤­l½Žaõ=†r1.I3ÄÊL˜Õ¹š —{ÁÉ}:4Æô¨÷Á#¿ÀN÷݇é8¿§ñÈÛ>á`Â&t;Í…-zÈÇ^gZêL5•.@‰Ê=ö–g“¹µÓ¢¦Éx™ç‚ŸÓfÈÇò+ƒŒk8mB㶦5×%d‹¸úl© ”ºeñ—Ða.jrãÚ¥’E`»Ò«;‡&T…|¾Î«Ã¾‚YŽ—;‰—&Y`î+²“áh5G¬0„®r?> iŒ+$Ì77E¾Btïâ¹b0¾¦ÐöjMå¶K{_“ ÀÔU2†wÀ+êÓ\ŸkŠæúî`»ì?zÕæŠiå]&F{JP|¨‡¤¨IR©m­P>‹š¡&q²ATgÙnVleÛø‚¬›çfq¡÷Œõß×Å©q”%þÁÅ:ç  pE^"¿GFµÑ20Ö¦ƒ,íþja¼K5'IßïYŠ‹ûª –¶>«g‚0WÙ(ø9p7’nóÃì*í›7¼‡Ò‘·ØWˆoy‹¡Ž‘9øjA\­ÇŽyP|Tíý™O*åéF!³±.ʧú«lŸ3(ÚGöéë…%¦îýf†á*Ͳ‡ÀCÙ×9¬ ¦*Ø6°¾EþÃQáÁ;b¹´LxÆ’N€;Ç×'Æ:,h@àw8Žºb7Y 'ýŸßÐNEˆœ›ä}ô«bÞewRZ5…*0s“¶]û¬µ,ëWã•Ç/¥Nk:˜;ðDÑÜÕ›è*e”©ï‘„Ù‰Y2%eì!†xD¤JUP‡5š$™—œy…%ˆÜMƔꅵR?0žôy1:z—ºÀ…Æ0v=õ P?ØwXÐ6];ú”F|A»õ&ùqßÃåH€Â±•ÆèV%¹àzùx /E(JèÚ4æt·œ2 òX8ª3<¡üÊÅ*y𼳎n²‹×.š:ó¤pþ];ä–¾Ú¡ï°xÌåÍ& CÐl¤Ÿ›A¡å¥™|ö`EW„TÇ^çà!Í×fs´¢äRÜ3*&n:˜¸n‹“”mé·óV†9‡÷îÒÐUÞÑxÐ’1ë±7ôV ÑjŸ•˾_åO>dó^»ßÊ."F2ÅÍ¿^x(§EZ”ÛÞ‡ ‘oK ¬Ej¦ö€RY߈€Ó@ÒÅÇŠX%¶h¨<~í¨jI&½2IâýŽ©GPU Õ‘˜Žõat±gRÉ9è¥IY¸Y£’sžy7IJ—ÊW#Õ}ÇÓ°÷B¢î^G -¥ êÏ:Ïwv¼Š-I¹äé @1âšwÓfk—e„Ñ8hˆ7÷1¥Ã ¥2rü]Xp)ɪò úXæ##¢«u[ÌÞ“ñ{zÛ.– 8tßT£ ùy±1T [à<§ø>,2%cèWa«ÉV…„>®½Ã§7-.9}H¦pµ¶$“E+)æ¿Þ1YœlZr/ÑÚlAuR¿fg˜û•oJ*‘E²I†‡ËlQèZÏg ËàëÆóµÜ½ª÷x÷tAùy3õUÃ@ŸìÆ”²ÈU{Ì>¡Ì¿è¾@ç$Õw0Ü×¢Z^ó¯9s•—tš‡dÒ5_þ†WHÜ %ÿ6 d_JÞ©NÔGÔê¼¾nŒ«“„ŒNšpR“Èë|ïÔµ‰ùß’¤Ãåøõ{ÏêJa™õ™_V[Sš5—Mun(Ñxœxý¯¹ËRæ`“ÿåx­¼q ï:ì{¯¸­n¬oª0qÙPѶ¾¼ `ÑúíX{l¨ Dî¹¥É"‚£“sâ…’S/„ÇŒîO”eU¡U2Fd s”üq2t„žûÕ›ªXîxåææáÞ !pY^Í–B$¦r_,$É—ª"F="«Ü<Éôa¯w„D.¾®ÇêµüëhÑ:ÎÿÂk*í‘«jðQ‘li>(å…}¹ˆÚçÄ( V{”±¯Ä™ô}GUÆï¾ÞľÂúnÜ·ó,Ü“êê²¼åy*×à€ÑÉœÝ*ºPØ¢% °¼Òù´Ñu$‘—¢ua°Õ@ ³€¥2,`œî«õ³*ÁÉ- ‰a‘I®ÄÚ¡qËõ¿oS$!æØ¦ò× ¤Èi›òƒÀýwFÊŽˆòSDﱯê‡M¥ÙµEÕ€>DxʼÃ:¥’ÞeÌLÛ­ƒÖ©1?ùêÅD|ÛVG• ¬õØd5ß»âºÖõN`Çø}°L9S_+v^~•£>³ö¡R ¸&· úuHI,WõXi}£[ó§WÞȪñÉ-çÜú¹èo°Œñbª¯I¾÷º¥"Šß~õD ²é¹v_©— Ò­‘­™µú›Œ=Ú£`Ï1é·œ†›#ä9õ ${raÖk_COHå@ƒ0%E‚úyöüùTÎÃhØ—¦ú¹ÎÆ[êWBcUbš&N;®þè/ù,=ÔØàÝaðµ™Ë»¬ƒy]ñQ  ïáB¢w*WÐ8väKLÎÜò[¬ƒ¾qX§eõmÙ‚0óª¬S¯c¡R¨þ Ì@GP —Љi@6àÞ ¬;ø«;Çß=·uVÏÀäV²òîž*ÚA³²÷ÿû>“¼€S¥„G,Ü€Ü+ÝÔ^æß+å`¦ëQõ¢3ßlîsG\wx0G sÏþäwgþœÿû€¥­Uendstream endobj 156 0 obj 4990 endobj 160 0 obj <> stream xœµ\YsÇ‘ÞgÞ8£Ð4»®®noìƒx-éµEЇ÷°A2I€â%É¿ÞyVeu÷#Z …†3ÕÕudåñåQøñ¸ïÜqÿÉ¿/ÞÝz’ÏÞõÇgG?9zx,ÿ¼xs|ûtZº©ŸÜñ³ïøMwœýq±ëýñ³7GÝÄmÚt[¿qð¯§ï»±w]ïÒæOÛß<Úîâæ~|½ )x|6÷·aó{<ÇOáAº¾¹3½ö5¼ñ—­ë¦iŒÓæÞv§_ñ¾ý]p}"ïéOÖGøA3 ›çåÉãúÎãöuôÉvºiÌŽx—z†s8œßÜÞÆÍÿâ¢'Úëý­Ç!Æf1f‰4ûlß>û#PÙyKå˜r×@èg§@\$hØ&츓'»ÐwÙMwx«úˆc‡ï¶»´¹„—¨éPø Ôþx ë…Þ1:Ü=;ÇöèýÛ3´ËØÛO·<«ãAßáÏDÝ~B’P_œÃm:x‘ÂÞ×½–Çå\4y¿9Û&|6^œ‡Y»Ä4Ðd´µ²‘^IÚü‚/å¦PgÀ‡Ôý5t—-ë2˜3ù4Ï™$HØÐ‡Î@(ŽÇº>UB–­H§á=ð\Ðcìp §å,@ŽÿŒËÈÙîI§|ƒ¿Ê¸ñ8êH—pÎ0zŸâæEôcyüË0u΋­°1×Iˆ‘dÃ;º4 Fz ü<Ù^nÖ ˆìâ‚uÂГÜ^ÒÏ ´%þ¸xŸ½µ<);åA^ã & È;Ñ OÔÇ/¸ ÃfÂ|¸ªäqL–'8´y<·0’×ïá+¿}I3ò±]nÈ̆L{(SÈ&H)á‰ŸÖ VCjú1)ëÀŽ€Ó:"æÈËÀqÒD„À}ÈaâFOuš8’Ôë!ÙpÖÊ熩¤·³ú´)R:çV…íP>FçÇÍŸñ5^ëm ™†YpÉ8>жŸQežô€rï—|TÄ.—¢™ÄMi )˜‚¸<¤‰·Ç$/»!zÎ?ºÁÐ' ó"ñ>m‹rmš1Q I'Šýdé{GtÔQ “¼U-]O”±#в d3HÍ5îõ4Ç‚Wbµ0ƪ†, 9­@l6 ]òNYž~‰ÃÄ¢^Ï–9¨!УUKËwÔGÄu¿t¨ïjd2ÖøoˆÕd·›Q»!­b=têfÌIJ1¹*ä¥ ³”ì·URº+Ô:af°~D¡•è@”ñØÊÃÓŠy.ñýD¦£tQ9“#0Ãüƒ¹‚Ä®ÏKîÅx(ïò5Z£ñØS¤ä ÌÀd?ûÓѳ/j8»¾ï„Y}7†œÎ4ûõ.hã`48¿ÿB= *zù1ÇÒ bÌd’ÅDþ¨C½C¹É>yÒXa»Ü'SðVŽÓ„Û놜P˜pÎŽ@E7D$9Òh#‘‘]¤§y,£Gïäýìs’1ƒÃ©+yk=6¦5ð4öyÊJ/‚V8Ŧґܨg¬ÖŽOJÔÚ|7Ëö#ú‚6ªÌ»H]ð‚¦‚M aÉL—ù^¯œ'«õTlæ~í°Süt*ên Ez4ÌÃL+(àóƒh¶²®S/F¹BFÒ©ÁJá&7v>¶*Iéj@ÎKV˜°I˜ft n hPK…7Š?xœª_éb¥- ´-ìZ}ºi±ø¾Eºð39ψI¶Új£…æP[iÀêê¤Ð¢¢ ÏÓ’:gœæ6eð}cÁÉ`æšé%e+ø‚ÑæVG'4Z{æl^¬{šퟶ‰nµ(õX;$ÖH*×"hÞ `Lj¬îzhÕ»»¨ê÷•€nÕ¨¼sÝêWYä+‚ :ü;DʳBÜÉÀc±´ƒ·Œ¦&ÁâckeQÃ:7C/Væ Ë*0œHЧ†!Ò1Å+9bÌv#GŒc‹Ü‘JC#9ò—G^€[q‰ÂÄð„ú^·« !•Œ2¬`‚a`+$ô¾ø­0º#T?ÇXQ¥Ž ž]A˜ùUI1¥Î ÊcEwê6ÕÖ_’A)5 Zï7U4Ž)²T4HS˜ÿ_AåÂO´ÝVG]}ºž¤šÜ·\¥ZØ©Èv²ð9ÐGuÃÐÀ8œQFœËh–™nÚëgýmUà—§Uê³ZžV9,{[ØXeãâ Dôz¾Èþ>®áÙ‘°ìƒêB7ox÷¢¾ÞŠ¥u¯Œ`ÔemTþÁÿ [ÆËsÆ[ƒê×Å HW}#ºø¤~–(^u”ÁÑ®;~µOÆiyÞ³(/žtñ´¢xgy|g”ëìç,‚JÞøDÑc­ÎW"®¡gê ßÅ ªï †0Ú 虀nØR1­”8ñmíg²nŒÊ‡MŠï! /TŽg~%0…3¢½†wÝßRh¶4Ó%d±ëá=×ø< ³LÜ–£ê® îþAƒ»ðЉVîdàFçRóðã1~<ÂDŽ›çøñ?¨ËlwyŒø•éÆÊî}iìkcg“ïA>響–ö÷µó·ð à ÀËòüµÆÚø¶6¾7ê¨4¢‡Šqþ1›‘~nr0€¯Œô±6¾³ÃÇi”ˆÚ®Ûê•ÅBúEãrlø/HÈÿÇ…®Xœ€`HÏ Øc˜P¬ ½‡5ÒúÚ„„°ñ¥_5kUJ×]QŸQÿ¶©­»Òêjãß¶¥õÛJ¡óµSy½F¶ËÒøÂ*fm¼0~õÊ¡˜0N‹±°ûŸš‘Ìôø5†Ñžº™Õ ö¡öý¥9MÖëŒdðé8$[FcjgÚ‘v!¬ÔŒë²i˜÷ÀìóÉnåg* ¼/¥:yjV Õ9§ZÑSžÊ”0ø¢Üh$~űG?D-7Z«6Âz Rm”AïÀ*`¤ŒÒ ¦'ðÚø–œJœ!z.Jnœö•¶ ZóE%úÀ?Q½s­±%»¢y½!Tn4SXdÛãÀ1¸ZAåä¶>«ãŸP¢ó´.d·ÌYîCb"x@ŸLH=‡¼~*†c‘-€ñ; osD‡ô#QTõ#Fxw MFòÁ>GyÅ<ΨÙ“)Õ¡p¢ÌåùkZT+ŸÆ½e‡²™Vó½¶±…¿(4ã´Ä$$ml\ÐoûCªš› %å“#Ÿ5ÇŠ6§«ÃS×´–ÄÖ<ªDrÃÈUHrHÚ-×Pë2XNZŠBR)Ý PÉIÜ…’"/M¬÷Z1Ã2•³Wi,òô´¼5+v½¾²U®:x}¦rú»:Ò,eo^ý´MˆD$lQ½6 ò-Ñ"F‹tÑ3au@š‡ŠÉÉN<Š[”µlÖ£¹r’Ä#sý¤äÇpW<&\”-Ïïtp¹'(m­ÉȦŠ;Ÿmg Í,»‡g;mOÍ:Ý;̘–IƒHöyRvÓlë,ü+̧Á겆õû×Ú£~.~Ëæÿ* tËžhŸE—ͬ ó—çläð`o6³ ‡0e²òÄî€"3%HËrÅÓY ø¶šÑÔrÝd˜uïÙÑ7G?‡Ð t! è¸+8Êky,æG¼_vûáÑ­‡>þðîãË£[ÿ}ìŽn=ÀÛïÀ?ïÿÛѽ‡Çßì½{ÖZm½{†8 àGµ ÷Ïb 0‡‰¥e¥ŠI+›*&Î47)(75\©E´³࢓›}£ VÛØÑzÑÁÿŠ G¤èp“M,dz҃·VÄ%¸qR†µÑk˜£§Ê ÐvZ»öK¹5™Ê9©^‹×%Ä`i$'OëÓ;U§"dŽLà‡"W}- Ú—±·Ö´%V9ËwÓø[ cŽƒi.Hñ¡Õ q~'`VãÇ®½~rZC1¸ÑpgÛã…0­ó.Ì2.î=í½SPŒSã²bt -Ûw‡€ï¡ÅEÙ—²˜zcp’ÇQæ¶ÓÄžëÕµÙuàCoÞÚ»uü­/ö ïÙs¡s‰ŠKÄz¿®ØR/Vö] iP ÏþÙ€—+ Má©LRu`¹*„?1Up…VSøw²¡´íV?5iTÉîϵ8­%1ñ]Í–kꔋ*ç *ÃÿßJ­/âÿ7$w¥G5ûkÍÕ¯tEÎüÝÃc'Û¤oK´ÿŽÃ'dŽ[6­§ª|=5žÄ¯ï“ å³á•¹7Ê!Üa¯RŸÑ·rèßÿ~|Uœ=NÓ…Èüaâ‚<7E¢µŒFsÓzd¬1³1‘{ ³üÔÓIٗijU÷0’þÝ›XÓ[ͧkBÁ<ÇL½¶¡ÀȖ뮸$ì•2ö˜‚gÐãaæîÖœ²âÀ—lðEÂìUl'“Ú»lñáÝ-ÿÁ ù‹åžóUõ» X涺ùK3©5‚©ü) WMèùÔ‚-ãHH[ÝhYÿ›-ý-´VÎU­¦©„Ë€ éŸæjÙœ)D’[êWî²tÂEfÔ3™¬2ahcŸoÍÌê3¡Ifu²Ó–½ÚKÞÍykCá·¦–õ–ä?ʦvÛ`mteRÄås%.Mñz.õMãVK8ˆ.ÌåhÙÕ[ý`#x†M¥WQßý¨‹endstream endobj 161 0 obj 5181 endobj 165 0 obj <> stream xœ­\ësÇqÿΨò7à›ïR¼ÕÎsgíJªlY6K¦#!q¥âT È" R"!…ö?ïéçôìîÇ¥Òñ°;Ïîžî_?æ¾?w6Âüïå›GŸ;ݼ4žÝ<úþ‘×güÏ図_×Î×'Ã<Îîìüù#êéÎ&6…8ŒþìüÍ£ÿÚù}ÚÅ}úïó­=‚ëzäÚ,ÖNçWµáûCÜ=Ù»ažKœw¿ÜûÝö¿;‡ç_îòâÛý!øq]„qwÃþ0•y˜KÞýfï¡MýöUk݇±¶Î»ïö‡îÕS©v)Mþ>~¯+øýffÿýÞÛ!¿‚>m××õ[ò& >Ö^·ý~]…\¹Ýou©ÿ®=p¬_ïô™qR¿û>ð €êÀ©6™&O4í¹p`¢Â8Lnž‰¶Hðý—u˜÷u)î.÷q÷¶Rðvïë¢Jò»÷Áï®ëãöèÃ>`jxeÜ]Ô¯¯ë£×ø8`EØýSÀȬ.ÔVu|·{ÿP— £¡JÀA®à9L÷´ÂDjvA“åÝMýr /g\Àóú5Óð¯d©+oêä~®O›áW<ÿXh(óM¥“ºÂjsÄáê6aaŽˆDóyÃ8 ¹ˆˆ ñ2ì"%„/(Žu –Š+"Ü3¦j€E‡3eI05<ò¼åú=V™†f!D’‚^šCšj_ îÙFc²¨ ­©ÉQöœ}1ìQ¢¼çƒ CÊpŒaëOö^XE, “ŒÄgÜt%qhL€>Áž±óÿ¯˜a÷Žfv•C¯yt nô8ð;Â~'x#GðXt¹§“4ÙB8](2 åw?Çcçç‰Q,ö?Li.gç_?:ÿ'Ø{]íWðñ%|€ªgZ¾}µIg8®ÕJ=®õã·õƒÄêwÚû?áãÚ‡¨Š!–ŒŠèŸë@õèÂn¢öžšÜú0á”xÀ>o~§ï¯[§úð§öð­>ü¡=¼‚A ®ä…¾¿hï+í’›q¦©_ý¸+ôÏ¥¶~ÑZ_lMÑ^¶‡ì²×}ÞËCà–Êåß;øsÁ¢ÿY󉃯Ví«`n%mà·¸L(ÊŸžÖwo[‡[}xÓ:¼úó4ÎjןôýË-Ú¿hs6îl-ßm1¹1ì¶=|ÜäèŽi F‘Þv«ƒ¯1»»ž÷òõ²µ}»ÙöZ¶:[¡ígCù-³L O 1nÚ=‰ø+iHÚ jHÔ¤!O•Ã/ûWçJÀ'Lµ™úŽùá4IûN:颌8þ†„ìïªDŠ.?-¹¶ÎúË­–ï‰M‚Œ~¶µÜ+}xµ%€¸F²ùª1@hÍr„¹—¶? hJƒù|ßñ{…±¨íÌ„HDÕZ7;­x“"²B8é%£†×õL  Õ6h­Þ *a«ºDh0ÖG+´Œ°b&‚(¦‚g7Àœ¸ì R §(N²*ƒ‹ØD‹!†vy~ˆÕ} ª#ºPÿ&|?:¡ûÛ¶6X/n?`ƒ°ÆKÅTð¾¡QãTPJß)°1hÚÜȺð=Lîñ¬4P+Š€`¢0ÅÓ( 5;˜\_2„¢mõ‚Ð, ÔÀ¡È *]{ÿ ,~Ûðô+ 3¶%Ô9fd%@h¡\d  ðŸ‘µíá´¶!Ä»i‡K1¨/ Îe¤ŒÃŒ+Ç&úŒ€š6†g†ÞÊXè³€æuý¸Efjb8×ÏóP&‹Ê{¢^E×SNœbþ©÷(ÜQ Ž‹w€ñ,£V•.hÕâ|A÷îÛzj³ìQ°ˆ>!‚±irû¶ï:ÁaoíŠl¬‡Þ+¯¬,½2)Zà­8a¡7¤ðçNˆ¯où‚ê ={¢Kgb…jöFþiF“ÿÎ:|«óÖ”?ø@p²®H–{‡Y˜>y.Ä‘\8£ÀËås‹m@À™ëD|å†ýoíö7I€8÷?ƒ`£˜®ì¬ÁèO“Mž…Eg)6Ûj¹w«ö¶Î±à õµõO8`)`õU°24Ò¤S1Q' Ÿ¶9½b"œq²ahÆŸvö¸¿¶c¿qº“˜ ÛLf‚VA„¯fé ›¥yÈ"Kû0©. 9 Ëm&’kB§µ³æÐÃrî¶œñ>FP©%òÉŒßjɲ=Í'|hãÈ4Ú«Ø€~#ŠÖ5Âô¢5mý—† Ñ›±{æ•‘­ jãMæÔó%4б÷4Å S…LNógªoe ÖQ³\ï0,£†"ÀN´£ >ˆk;u‚kï ND>ÂÒÂ¥RŽ˜GnwR”jqprÞJÞ"f'V¥V^(œÈV”Y.¨bK¶ý…nðo !—+tÿdxÊ„)´¯k¨èéd‹I8DG&jgŠcÀÞ ux70Bá~n%Ö6]ZРø `apØùµ5¹7m1¶ægëèê Ü.Yô¹«s®)Î÷z­œ: ³¹xaÀÞç’á,Ì~³—“l°hè…êOù‹¬6 dHˆÊ¦Ä€¶ã1˜‹:'ÂcFH ¥N&¾•]ÏÊÍ…â‰Aªo¡sî6é•Þj–ªö ˜ˆ‚ú¶ã©HSˆzž?àN7´{=1z´Ú6sœEd”°C Ý;¶·Õ‹ä ¿Â~(Á'¤1°©;ÕB'Ç€Š$¨Tœ)"ô¢#¦ú§H£kÚ(,«ÑÖѳV¤¥3RH’’ŽëˆA[óìe§ÄŒ¾ÑCJ‡wôI€Ì§ÁjÞîCQ5hÈ…çµ%˜P­c|£“LZæJ¹–¡QôU¬î`øœœ¨€AF4püRâPá gú¬yá‰Å+Ó$ Ë›z¹¡I‘\[Ob¬o+u_3'¬z™‘MZ:YH ¥D®ÊŒáVΣ‚'4 Yi9ia(/4iS¥OZèEXlפò£(h©£ÃHYW¿:ÍYxëB‰¹¦& xž3&rÆ`£‘¥ºæ÷è&¥¨ÈöμýLN/¼‰Š¤€1@è41Óâ{&=3Fã®­¬ õøNx2â šAG»–cô£jÈU|üµ4DÍÿBç‘dòºc£ã=6û‚ƒëð' Ž‹öDœ*8Ÿº-\-žˆLÉþˆÝL—^_±;}ðEAœ{çðÏNŽ|DYWˆ¤ x~•²rhLÚ –@”؈Hô†Ø„_š%•fFØýJ¹„]nX;Øq£¥uY-#:€k@®÷QÁ¹õl€À\5x2e*‹²“N…ù6C[– £0/Eâ¦ç¹T«œUU]â!‹ÝPÊ褌!îݦXWX›ɹ: Óg¡íÀs`;Ç¡øÑ§D¹ÍJ]t3« ‰ž_ûU›¼Ùƒ›F7MæáŸa•eªxÝ<¼mOq("ÙãCqˆªÊ'J½†è2!Ù)@›J´j$“Ÿ´•eÝKª«Í»o@^söˆÿkÿºVP’u+•^>ðZ\A禮ô( 2è…)¾ª’?ÀúS(8zÕXÉMvu—m{×{Hк“¨ã¼Ëäš×ïÀy!Ì%ðèjËSH#ÔŒ)ð¸£/ü-äbˆ²•1®ú+˜‚¢ûrÅ>’¤©r¡M©:GñÐ<+ÑÎ6Á;…FUŠ’€ŠÈH9&»|Ø|*bÒ5DêS ÏÈ­\ž–+ê#Ú˜f,/—åyÄÕ¾³(ˆ4dи‘ôYlçYK5<¦LÝvЍ³–´ÁrÄUèÐò`tË`<§F¬wamxíFöÀäü½WzÏ{»À}î»C¬V‘4½Z]ÉfAêŸÙ\,ªHˆKp~[³ŠÜx+v/Zv*êþ¥p5ˆˆÎæq´ã0ƒæQf·‰Ó!ž¿”þ^D Mø®o€KlfRW½ˆª(€€>q$”XÎIî‡Ë:S[5OBrX*•EsÜ'جbøDýÂèQê\¿`¢°›a4 ÒÔf²´ñHO’'óRÝ?‚·ÛC¿ãêì£Ï^ *èŽi4q,„ñSèÌm=ô'¦|"ˆ£à]§ž‰l§ˆ¦¾çvîèNz¬ËwK¬´(Ö:÷ñÿª4T÷M£)%öe¢sÿh Û¢Žž;Ò|Å£‚X¤¢¾7Éç-¨¿•ƒlo±Çƒ³[c¦ˆ¨«£¸ù¢ÊEËoŠÚ óB¸N½ÞZ ²³ƒÎ­Å‚ÛtYK­<*“PÞX™î$A¼“´âW„«êÀ•«½íÞDËš×¥ç¡.¥Ô1¬EÜú½ßcÍ9«ã0i÷ªmUÈ‚¦pù̓•Q+&ǹnüò.‚Ân.ߊqßbÜ‘âZ `ßQQ½µôÁSA ÄçµéSt´Zþ-RôwZd dÎ\oh“´ôÄG×.‡$²4 ¦™Œµ àB.z7øh*jeéG*YP’Ð/ÊD׿ðÃÕ¸é•n]Ë\‹16Fc´c~$ÛÅ9>-¶|´Nm"’'Úu¯ºœ/ƒ‰GO®óD§¼Aèr±üâ¦[hu¾/fPŽÔ÷Á´ÅI:pùv»úA‡8¦¬l0Á"|˜H´‹ì6-¥h08•cÍ¡—,™Ø<’áq]ÈÁÔØ(”Óð ‚û騉´U*ÏT2äp"Âíï)­>Q"eSÉ»nø¾“æpܲ¨Ö‘šãŽ(› {:Rv •‹‘)*¼"äʱ£Uˆ„KzMƒ:Ë#¹Ù=UseQóÖ‰Àì‘«"å3Úš…Ÿ­ÒÑ&Â®Š³·*¢+o4+l¦'à ‘‚î ß©Zr¯µ@uG«²¿W5Í”VùY ‚*¼b?¢k§”YëÔJçè±è@â-ÅŒX›ƒ*õþú;$D¯—îóóé0æÆ'ŃnN †Ë¥¤!;™Q#‹æB›) K“[²ð’%qn®Ç'$qš$¿dKv/ú±—YYX´cöðÞ«3ž¬-tÇ •øP/™ ÕÂÚ÷&µù`_ž¼ãd4Ñ,eÆ[<3p̈ª–‰eSrB,L|»ué»*l‘¸¹ÅÓ胦‘ëÁÕŒ=Û°rFÄ*$Áù/$¤#!n8“éáL¡@fŽ5ÿRo΢¸ã1€ -‘üš¯öéBFÝŒ 7RجGŽÕÏÒ¬§½…ÙtÕ”gºYã›™a`ÕŽ›­©æžr¥µô~bÀìBÙý(xõªÉ±Ä™[ÞaUgQÿLô÷¢ Q›‚@¥vîìå*@¹ˆm=LöÝû¾¥–SR r«÷UæÖM¹ MC|$¢n©¥í;﯑úhÍ”c÷¥‰]#[{§Ö^µñå^˜óÜÅC)N£A€gl‰rÓe)¶ì•ÅœëÉs³þöv+ÄÎÌJ žjÉi#eÐmòåÉS%´Qž|ÇXΆ®öZ ÝÕ¿æÜ}·ò5uÖ»<Ù$AµXuS×ñ(«û¿³ØÂ”½úå»Ð'š|)ZÚ++Ÿ·«bK _¡W»mœË€¦À=ÎIè™Ñ˜ŽÒ‰ÑØ¥•*YR´R]+Ýû—´Rõ±Üˆ5Ã~JµÞT¥¤ÃÑ&ÎÈWí~Ó]@Ýø”F8• >V7èUm>•ÉG“´QðÚ`}êQ”ôñ]=§yJ¨XèËáÀ)Ò…GÈM¹½~^íÈäCÊÝ0fô7uMÉÅäxuaƨYåB$%†»ñSê ñ¡xêçP_‘fåòèªÈƒ÷¡¾/;ù¤à „¤õ|UÖÔ†SôIÖœ&pÁ—õURå¯ß¼J€#e¿ûŽC%ŸY³î¸=²ô¼®tKŽ îáy‚{Èb¾p¯‚Þn~"ϳµ£,Öþ9Ô9˜ÄòS R Ùmÿ 7>T[µ÷›½'O1 ˆ†ÆpjÀÖSÅ +—UÐ^RùÛæHgÍÿn…àÍcÒˆ#ÎÍái ÿ=—[Ûʈ֙ßjL5ü=gožãtF¹.Ò åŽã@Õ4n•èòh7Ü2ßbÏÕ ¢ bêS‚}¦-kt C™èm[8;Ko‚%Ì"àÛ xƒä˜‘Æ[¥÷'ïø@×6lL`^ÕìâM‡h2±ž`ÝIבœde´¶ð¡÷Sü¤1;*µ;éB“£j43¯‘Þ¼†¤¥¢Ë´?”Á)¤W¿`j˜jLŸ9(É+•· +›ŸáY ‡‘îã˜|{ ¡ÅÕn÷+Ÿx‘Üà‡}…7':0ì„…j'œ²ù†^èÕ‚&î TÐ_¶ˆëÑçOûuì—!EÖ¿zí¥à¨XLHÊI­CÆF .n–ĚȧášÏlR¨zu)Ç.†œÒ‘P ñ4 ]F#G{±Y}´¼î„ ÏL¢yUÅÇÓ\1šÌÕì¸ÅOïÈà¸8Ùmåk½âf”WãøºüΣ9{s­ÂdàïT$5˜)žy^z<ý…˜þ²Uxš3˜$ô*ÐܺQìFß%…ëpÇÅ·{jý/è^D^KÑxÐt¿¼~g#ƒ»¿Ù´A‹öh3zƒœáízf°UsÕ…G, káÇÐ%Â’q¶j†¶ž—oE(¾ááæ°ŒMm¿³·«Uµm:[DX­®=ÚÛyÝõ†­)kÚ0:ôW®i ÷þòSt=ú°º©,n {%Š’¤ w°aVáwÚÊ^Je±*oÆŸáXý€ºÇÀ?_4Wæ§Ò)üwàûc3ü˜Nl>F¾õuÈñA‘dŸIo,o‰èÉ©4!ètHµ¥ôõCž/wnêSí,é*g"–ù/n­-ýä¶¶d0‡ŽŽà"Ðw6oåp¥¼ZÍÖ£¯÷ð¶zª++V$lËzxxR…FÓt8üËóGÿVÿû+˜.7Fendstream endobj 166 0 obj 5582 endobj 170 0 obj <> stream xœ­\Y“Çq~‡þ |švpZÝuô!‡L“PØ!Q2¸ 9,úaµ ,`»€%ÿzWž•U]=;93Õud}•Ç—Yý·‹¡/øÿýöɯŸÏ·ž ·OþödÄ/ø×o/¾¹L ü˜¾é×a/._>¡'Ç‹Ù]Ì>ôƒ»¸|ûä/‡ÐÅC߹ØþïñóqÆ~ãáÝ1þØÝá>ý|ú}çéÃuÇHŸ¾OOÿ¶;úq:ü+´ÃǾíÂá»ô¥w©+xÖù©†‰;}ž~ ¾Hº~]—e:üKêç?»þVèZ>æ&ê`©×¹_—æ&mžw0Ò0O4Nä;˜ÝÝq¢¿ŠÉº—ˆ?à¿Ë}™ßv>}šÖõ¿/ÿ=IttV¢!¦N–$ÔË›$H—„» üËÑý<®+5x&¢Ciþ˙̇¿Â$Þ¤‰Ý§_ZÅuça†Á~YÍéËÚÄÃ]ç¦$€èSŸWé›×éé;èF>¤öã°nááÔQúM_AèáÌãI2’¦ =~N‹‡¶ÐÁ˜šh HáÞÍàÔê:Š©…çé¥Q^ÐúÖ…| ÿô8–>öªj‡Âùü;d¹<À_¿‚y¼ÄÁd\Ú‚ÕÉReä·ˆÞ¡²%ðÔÛÔ)£æ|î1íoB{ˆ+Ž»ó L úœg’‘‹°^«ƒ/¥å/Ý&³Œ̰JŸdH˜cš,8­*/Ö!B¹“gü.ð`Ð!D0ŽÙ†ð GL>ŽüuF-~¤ç`+`ÆW„43‡U~txÌoSÛûF[#Œ *qŽ#!—~¹ÂƒC(›’Ìf°ñ+ݦeUÓ>dLý*ãç=5]ב Cdô84À:@*EKGÅBŠ÷Aà ™\¡$Ò·´iÐáë/^B+® -ómçà¤Ä…Îäu‡HNÿLƒû¸àÙFц¢ŽNøùÔ¥ÅO|ˆý¼R;D~xÁQ‰Å~#Ú ¢ÃÍk V€èœøŒÃaÇyêÆªŽ„§ÒÁC@¢:Vø†¿ÌZ;¡µ¯~„õ+!UÖb¡æ"l£_Ã?w ;Mª¦A:Wˆ"—ŽåêF‘˜ÆB¨T<ň:ï <‘Ž ÞQèc@4Ü4TXQ‰±ôe íÅÜBòF€í^ToxØ]áQ×Ä©>€Q”Ê ŒµH ¾Iâà(QRhï@dW¢ÖYÏ”R¸AÓáÇCúwe1ž2<b¯µí88Dˆˆ»<Ø•˜¶î"y "_°¬—/8ø Ö¸xÖG`8 IØm“q{ ”i ìéĦ©Ïm É‚ ǵObûÝ“ËüËáÏ](ô }ø9ùH"7­ä$m¼qDð.’uÆ%½`Å{“ÛðbPãÏ}‚ÞðRÝ¥?á&2©7²Úà z[Eß»ä±ÒN ¶é—@Z3[ ]¯(&Ô¤`æ µ³•¢›‡ZÞ/`bŽý’èÜ/~ÍzÞššvzbíÄd‹Ô1ŒV[j«!*v$ Š‘0Rxz•?nlc]öÌVxÐ<Ó2dõÓ¿EŽoà«©‡1` ð§ë°ª;"jHb•ZÉg~†1V<4² øó5~Ĥ$œŽÙEå`b/Çh^ÎÆˆÞ^Ëɼî¬f¸)âk ç͆ödÑWgŽ6'ª5Q³I2´VÕìjeöŒ&e*Äz£²êR[¡ ‘dáT©ç)rnŽo×ê¦0‚qGááÁ^òwbZ(¢´ñ‡Õ? €ýàÈ:;7ˆá óHfKEÃ(ž®uHаë¸n|ÙÏC¶°‹g‹ˆUú—Njr#i®ß+äqW^¡5nF,·Œ*ËŠùfHÓúõm¸GYE‘Ñ…\V«— \‰æ»)¨‰±5b]²'”DÓ¾ÈÏb±”x+vßs¡»_l¾2`Goí£ÚŸ§Ù[—­w¡ìÐô’zÈŠÅ» %½ñù ³<æ¸u“”ØÓÃò‰X@æ£}”Àš2Fw9ླ߉ @…c¸îÿcVrX¿À‚fqÈ4¼“€6sf,ãíy`ö­Dš÷ÆóN…‘¾ÓXW¾Çcà†G‘t$ç:˜ØŽxžG²QÁi£åaP½1):9ŽW¸õqÒwê?~â@„·Ì½Ð˜‰1úÙ‰aªT¯w ÊØ•¬(ÍCn¨jc ÕN+.}„="Ôe¬ãõ8Î!MVûŠô¡Ë\ ?µu~^°ÉÖœôñ#ÑÓÈŽß¼oOAßˌۼ gyž8N[ÚÜ„¡¥_ÔÇ^meÖæ.÷P›B_’6Àº²é ò4¿”+ç0»…žw:`ǬÌ9¸ÎRGž9;,–‡Re$O` ( q,gš—9뵡`Ì×BTÛö®ðÂÁMYbfž °ÁËŒŠE0†,µ„סDÖŒWÙ(_PM³¢Ê`=HIƒ dÊ´T0Û!VæØÐ˜-W4kÈ ‡X³i95Фiœ'=€…xŸ IÃÏVs‹ùgìÕ$ÌUÎf({É=Ê âXK¶D‚!hÖÆ$ELLà³òÂ-?¦Æâ'þL¹Ö‰@ó†ã†4 ‹4TƒKR2Œ+ˆ¨„;hâ Õ)´8“ÕŸÐP‡Êcà>Ìi ç[i¦jéÐøAxÿô캧šøÏUÔË=K^1Î`•“LñR~;P£øn47›×½Ô„a‡8Ã$ì£ñ›¡—kíiä—JæœSjX¦¦ ZTY[¦”Ï ù˜á)ãÕ&.”Ya§ïäœM”âώƈ¡Â.c½}ˆ¨IxSmT9ku"eI0¤XMÙ¬µPªÕ”löLþùþfs<¤\µd ý„ž¡§ÐN „©\x‰˜’u1gžJAmÊïD-Í´¦A)~j—id?ÙòS¨s\ •fÍXv$TÏž•LkõÍ}'œÀ,i1œ •èÐ’K™Væ\ÂN1™.5Ó’RJBÆJABŸkØO/k0TUÓç'1VÚ£•ïÂÌ d`¦Šý¸‹¶ƒyÈõ/LiølFœ€Ê^8ÞĤÐ}ªqñó®aãMV6Œu‰­ÚÒ]'•ˆ€bM"VŠÊ<ö9Zƒ¡w°UJ\Þä匄¦²fÑãtv‹äx¦®½w&©z:Ãfªö¥™³È¶mXu®šPW¬•17åSsÓ_»ô3éÅ`eüˆr(µÚ>ëU4Ì{•«‹–7JH+ånËÄ*‡s™³Øzþ&Ó!Õ^EAÇmWƒŒëV¿+YíŠÈ*´¡2ʹˆƒ­ Ù¬¿N¥‚ôéÂÿãŽL¥ŸÑyÐÑåöLuý˜3q\Öt¦#Y•¡j”LÇ–©bÙ“…ƒ|rN[á0o‚±%²8?Ý”¨‘4*`¥ü³áX3Nþ:shêJnN};Ž’&R¼¿I_OkvŸ^XCÌÆ™!uÂÅE3yçÞäê]2¡HÎ`h!½ËÎúÓ»S“\®)™FxPØgоƒ­,ØÄœŽý¸` WñѸ€W!?p©0±ÝoS–] ¸´Ò.#8!ä‚2 E‘ õ6©¡ýxb¹/8 µˆ1k>ëÎhJÙ[hï} ()öðË6ч1·„ÙÃLü')Ä™ÿk3aéŠ(–òy†šªê¦~ EX¯)Œg¥%•tµ¼µªž­0š9a6(Øá®¸g§xVaõ%˜{]®ÀÕu(‡Ç \µVTŸ!§·Ä¬ˆ$aE¹wSw'¾û"õÿ˜* ªÂjÎÊp*>?o£8ûóxñðä£9Qêd¹½‚‡4ñSIiÉLe ¸»²f9%ÌÒ‹BFr¯šcS pËLÎtvɶŠr–– æk+ì'–ì[ÔôÔTk­Ý>ßÙ–&m®@l.•‹wƒDÛßál§•åRÚÓ,´¥ò¢éq0…qigd0{å”G6„›Ь±lÝÁ¹4 Vr9,}ÙÖ™E0¤^eÚ«¸TjM«ÂÆ¡?ûÐdèñóÉ$K†æËj(WÍ©RÇžb¶ûv¸RJ“Þ`ÿrfÀ‡‰‰¢ âžcJû ëE4‡ŸÉ„Ñ*T‘Y¤ûnÍezÿÚÝ–;Ë1;ÿn_”ý •úÅ\±.¢2vCÚÕÜí%.m!/7DoU;ä%é6qXm.Ë„·÷$;òJÈÒpMó"®º‘(Ëp]Ð;H.›%©Û1þ»pŸ|¹QZ¨[UG¨Íê"Ud¦CF4ûW­K–s.!¯¬(â¸ô–^ÇÐÂñXgr]7i’)ô=%ß‚òCÇ™áF`Ð €3}¨&|KÑxr!ï1~’Õ…Mú  O¸š¸æðäîW…ö-6s5S,tèÛý}w+¿~¾\Œi°Üö=òúŽ0YÍ•HÿƇ}7ô‹Ÿç´ÊÑ|íÛM\Zɘ¼O7¦Ó·qˆ¸­®ŸæHê:tXýk|hIþ"d¦ût¾ÂÌ_ÎnŽIœI&Ëìñ’YZć½çïÍ\îˆFšã˜d±Òý삹׃Ùß_tÉ\–€;¨šiQƒ)À¦½ãÒ¼E´â"÷–FJï„™BèoØå°Œ;Ÿ¹‚wß1#.•3}§²Ú½—]Ty+Q‘S|éKœ¨$ÝhYàÖ¹3=¨öÎõù2ͯ„ÞÚþhÙ#!¿& ²æ´y¹²Ï미SC™oï}³©Œyzûa•„9ÃãûEaé gšoIgÚÈÍÇñ%þ3«õJÓ\“îEµaN•,¹$ó{±tf¹g3Íó ž‡©â<ãâ¾!>wkLOç–½^ÁµÄø­å žJÈîîp¾h(¬ ¾Ç,£urw²o‡C?O‡Õ¬Ãº“¤Ï@tÖB´þe¶]±¾Pb 'ZïE¾—ç¦îèmÁ¬ÛÒjçª ÆFmãåQÜd¡Óh_ºáÜŸwK“¨£X;Hù¨LR#Š *†˜ü4ÅÍ›m´Ç?³ÎkAÁ9ovxìõÌÉìÒK”Ã"=#S¾¶"¨{¤6¶W2ÛQðwš 2Æa‡ý¡ãâϹ½T,иÞy^Þì„å®~ØV4‹Ë9ß-ô3lðGSÉwìüÆzh‰ˆì)'x*6²ò‚e/ç|Y޳tpàÿë•îéý®Îßa,™D¸ý¥+ɪt&û6a¨4dTK™nÅ#°Ëýgë|ÞP²€ÜרOd¸äžIyë?n ³U’‰\Y{|6Ub|&·Õ놑ÎIÆ/BFý:`Ëþ(Åiš’“)°ü’°Ù ¼ŒÃ¦‹©ÚJϪ)ãOÌ.ÈŸÍít¼ÍOèÌE6ÊkF”"ÜâîÈÔÇOÆû6~¡äNãÁdwƉžý4Ck¨²7 ô«ù ËúàÝH_uš´¬ˆ­£‘yÁPXúfJYбÑÀŒ(‚¹Ÿ,%…Bùzê‰cWO8]ö¬Ê I‰(ärýÉ’e‚ü*ÕÿÛêÂŒuHM¤Å<Þ—SQÉ9x#Ó¸ò£[ܱÇ+p Àkþ3w賺¹,¡wæ27<ÉÆ ÞK¯½ú¶£»õcØ4Ô”„ú8Â]m·œ›Šñª™Žü®úº‰^ÐòEÎ]‘ý%ó8Økxõn¶ð”rTEF²©¹ß¸°um±zbŸ–/êκ2QÓ¸zÆ3šC¾qWÐåoX¬ªŒþSÍÙj®†¶Õ[n•›¸ÕMüؾŠo‹uߣ¿,Ü ‰t±Pz˜Îß-?Œ8_0[ÛKs\«Ã´ ݯnße­…Ætžú°ØÔ‹&¡LmwKp¶†MjwèÃFÒ¬ª‹bo£´/$³oüb™öæ¤l> stream xœµ\Ys$Çqö3ÄÐoÀ‹#¦;³]G_VØâe­CE2D?€À^±¸v—X‹òŸwåYYÕÕì2 b™îê:²¾üòˬ~{ÚÜiÿñ¿×'O¿ŸN_¾?éO_ž¼=qøå)ÿsq}úùYºÀùôÉaéwzöâ„ît§“?B<ôþôìúä¯;ß »±þçì?ÓÁwŒé²˜n:»L~Ñíãî;,Ë—Ýï;¿ûs·÷»3øü«n/_|ßíƒï½‹»˜Ú>tûi^Ë<î¾î<\“~{–/‡Û}ºzÜýW·/¾úZJ·Ì=ü[øñ'íÁëoæéê¼mòôðÛüwú:ý6x >¦»F Ü÷eú(Œé#·ûíê_ôlëË.À= >Ôïþ?ð h?J é’iò4§q¶sºwƒ?ŒñtúÃä–…æößÓúaI“óvOáÇü¸M? ïnw¾€¯áÇKøq?ÞÁçiŒóˆsµ‡¿÷üaÀû¨…søó'øq•:Êã{®_ïó‡ïõÃ÷­Ÿçƒ|Hƒ-Mnï܆êãÜ;*ÌÓm²‹Ÿ;è_Ü=Iï‡Ý+XûÛ.Liƒßýoçgú ®ùÐú% uÀ;ܘ:c#xç9¶¸3ØAÀ‘Î=ŒuL³åaà—n+ßA¤% Ãî—tå4`ãK‹€¿\¤ÿïáÖÔ¼ÌÜ@]u§º÷hÑŸ™ÏÒñÙzÓºc;óK•þ¼1ÁcéR⸻¤õnHÝùõË$»ñ}6y3@ïÑ.Fœ»ª'Ð"¬¦ö5]ñ"/$<= =ˆl0´¥·7Ý«­›\è ¹‘×¼êù*™…9¤ÅÖý ×]áÿé[[±¼ ¾LkS=;?ììaZö.†a™ivpNq Áúã”0Ì8¥×°`Ôlz°µW {ái C\[ÛØ£â¬Þç[îàš;IÀcàO+_¯Mê%u APР ¾Á~ Úu¹xÃÀ¶‡l%Ör´Ð;øm4k`—ú¥]»t7Lyè{1Ä„WqñØ!ÄÁŸñq¸r°®ÅŠ=ñÂZÔP[Þ+^¢ÞµV,}B´ž0ÍRŒ2Û®.¡LY¾§XÍvqKnq£EûÁi o­è>Ĭ1[ÁñõÀ¾®Yz ·Ò“þxrö/M^sqj¿€\}Ï{!öûž¦=B¯¾ïí=Å/€ntUj"Ð]³K „»có }9èô/l ˜` wù^vÄU§ÛZ?N­lQv&Ò]ä…¿"ã]Zyô÷H/þb3õéÇEHu 7p«Ãy1;‹Mõà•ÄÜf[ƒ {c!„= ÛÖ&’¿ 󾱆‚WÃ>˜µ±Â;½PŒbð¥Q°éåŸID >@š„NÍøIžÙól®0â?tC€Gq€.å9.1avÅÏ´—ïÙ|ŽäYü€&á€×ÛC ^Œ„¸<ܽàUŠü§ÐÞOÐç9;nö¬+h3ŸTyòeqRµsQÚ±í߈E €î8]3«i]Â4,ÈÀŠ]—®BûÁ¦^2Æ Úƒ‰Ÿ ›‹ ÒO=Ž V~”ýýêì仓·§!F$ôÉuΧ1,©÷óéè_Nÿ¦øàóg'OŸ}súó»ûç'O8u'Oÿ?>ÿóéŸg_žþÓÉWÏN¿ûÈØ!ÆݘhÝ)|à} Ýý"»q»sÁ6Ò¸*'_±Gê4sc òåO²ëMdç²Ë˜o ÆÂ‚«¬”± V•ƒÉ€l\ÊS‘)¼§°ö`ïœ=®-j;Á;E>c~·ìºÙ_— :^9ô¢Ã]\ì@$tËD£v­6Éà–&AD£NÁZ?-bÕÿ× G°oì2œ:&š²â†µüø®p¼/K8ƒ-câî´^µú k©!e{k*j¨ÀŠ%ûÅX†_Ÿä)(MË:®Í8§FSÀ7̉êÌÿ¸}˜ÍxN<Œ¾Ø‰2Ïkšö.œ²2¦ d“:–Lö²MÓ}„ÚÅÖØ[¸«wÏÖ6do­Pš·™ 5åppai¸h&æÖ•'&ו »õ8`JÈ&à•Š¤ïÖ”IƒÞÄÑ™ûÖ×É.aå–Ì£îªX‚C34ÙÌ—Àü• ¬pQl×_\H¼$;rZœ„"j O¼·T;ï¦Ëb„ðƒ¯„ÌËŒ’bz˜ê±)¬1²²gÃ.,A&£0Я;PE2ÌA…4G ‹fi ñÔ<(>šüd.|)aiܘÅ\ øË›†ÌAA8à‚Ú]eŒô_»¦ ¤ŠQü†æó¹g™±¿“{øÛ½¸2ú‘ů›¯%ä@'KT¬y¹¦¶$Wâ<ÈÞÍ ü±öÂq&¯¤r™¿¶.›Ê]\&D¶&…‹kÜ5xDdõññwg n¤Ÿéî§Œ#m¾Ÿ¤?=&$¥gnpG×Ôa2=2{9A ¤Ï¤!Ǧ Œ äáW¡N~oƒúó•Cå×x"4í Liø,ãt+•äqà@ç&Afå¶²“ÐWüëF‚ãZp›« qc©â]ŒºB}TˆD±53Ù›NÔ=F;O—¦[ÑÀ~»Q½S5®—LéHÁ £ ÒýÿÏðÑ XƒôŒèBõm1ºhíD¤‹Ô‹ÁY'êQjÕ£‚áó8J"&,{!óPÂU¶qu(Â[ÐI£E”eeÃÈ9Y”f‰ù#…i?m( ¬ €=U\_™‚8£w$fÀÓo…NÆan†?ÿ^‹Ç&XŽ> ¬]3m ‡i»?Ó#ÔÛ*ß9”™„YÑ +§š“ΰD“¨5ª€àß'9R/MÁfi³™5Ùš ÞZ¢Ÿ>—dœ—Ò΀#q Ð¨e…õú•§¯0¨ÑÍÆ9 ç™{ü悳 )â}»' Ý/135ŒSòò0h#h„·Ü åæY\Ä~ÿlÛèäV6ñˆ}z~óu/ƒbÚ»bj+"ŽÑ;,N±¾,wüCžXů¢à0®jœ! ‡ –ƒ¸:m^é2Âäˆ.X))É;&Pµ|Á¤Ðî+Œ—Ê %)c…ÎuÖ ÍÄ()ÖøcÒ~(Eîøš%Ÿù«ÓÄ£|Úµêæêæ~×iÆ¡ÉÎeio;Éܰà~g¾°˜»†`Ã~Žå½žé“üÒÂ%å2£2é²k#˜ÌE aœã"çE[ô8¶sF#0«¦‚?§ÔL›ØHJ¬Þ^áÛÞÑ0"u&1Zrú›|ªÆ¡õ6ö°YÝfÏékx@aS%9kkË4d9}C à<,¨<†À·„0§+ ´`ï¢#æ9©T­·Š›÷kã°hÉÉ¥=wï–CЮw?,d?tպ̔ëT{i¨©Ó’×Ö MKÏâ'ú½ËÉëìф੤ÃÐ`P³øYžŸ¼à(>¸%g¥4 â’´å7²€¿ï´:B ô\;á­*RR<…A=!¬JËň²6“ä/„9Ã|”7kæ>/ðoóå1^w¥VŠ8lS¡·´ ây ]ʪiW8Å„£)Ü*˜±qÓUgV†ªµ™ÕÄ#‰l6ÉÝ‹Y½aát'X3q[!¬#7[¡tŽ|ô ¡=‘,îœ|ØÓ67æ$dÕ„0øÝaÎ(á éÂÈ$˜¥(öàÖó´½QUaXS –.íþ& ž)‰×ˆÑ›’ŽÇ’0&HaÑQr.YÓdzì<[¾Ïc²({9Î7¯#ÇF•‰j 0 ¥#TE`¤_“úëª £]ˆì„ƒƒë§©ä¶FÇ1t2q:1çQEfD†¯™û0"Úd\5f#ÕA rðLxˆñ°—ĺ{îêMþsMä†E´C25§/$ˆûTRû¸ÅÀü²ü\20p"œèEÖWíAáeYÑ4stœ½Xä}Ëï½Q3Õ90á茕œì\¡’Ð1|™6`ДôíeÔëÔã1mGÅS’¤ÓNòM ÇJ1kZ‰à¿Qý¡Êšø©¢X$¢R…#fÕdû‹ŠZ¿s–C‰Ñ&r‹àí¬Xf%ùßü6·'ª:M‹çžIE„«4|B¹Rlp" ·¢VöÖ‰>ÍÞSk”¨›!ëF¯¨oµ÷fKÁžÓh,76)ýíeÀƒu74öV`uÞ­òàÙ¦SV9G »J:V„)YŸä1•hþ@’”mXÐÂ[“H˜½©Ý×ÚmsJ«rq i•±£…4Kß QT“À•t²šqЏé¾\n¤y·‰ŒdHØy“éˆeÝ&Å[d- ÌmAÞáæ‚ZWI¥èfŒ˜J,2¥ÞoÂc-Aü]†Ô‚VÑE„Ål¾†j¼oÕ à€KKjÍy¹ï§`aÝsr\²ÍũЩÏ%bY|wEMŸÝÒ…µùø¡¢!ÎéjüôlE{_è éŸ ®W~4òÆä»Â!h@èrš¬»BkQõ‡>üìòx(Sd噯|Îà¶ŒœýAÁƈœbhšÀüEfz¥þ½5Tü¾«Dé¡é騛áØKoh-bçJyÂX¦3j¼Æs²rÇz2?¹Â½€¨ðgÈe!ÿAgd,œy[î£~ôÎ6?´KB°š#á¸<é`4¨âAD¨H’cήb£BI&:È #@ø4ýý- ›¢C[Ê1Ɇ°Aã¥ã'w-Hh¹ {ZÁQž™OéÍzL/5ª©ƒ†þÍ‚ ´„)[«É+)¨Æ6D´%Q®ÔpÇò„"ÒO¥¬©” TwO$>#™‚ëuæÞ—;h£ÒS­à5$ÇSG£=e,AÝ[ÄÀRœë‡çý¢ÇVÕ…‹¢} E|ͧþΦ©TY¹È½Ñ¥p>©Á}M”\:·B4¡À†¸>aýzÕ78淸ݱr\ž«­r\Ù¶¢ÿˆ*Vs"‹+ŸIÌvRËH–%Gz’!Uˆ ÷|¾ªPN§zt¶€e>KðÒ(Y¡`Mø^¾ä —4e | ʆr½¬Ê0¨@Ú]4ÚÝX2ð[zJ½?B`‚'íqÒ,OS]`$<}ŽÔT°›K•F·|ôVä Çô¦òrC>eš[ZÍy8Zàã°#Í2µJ'í®¸´×,.À`â1g[nó¼³gš'Õš¯`} ¶±$RˆN<}8ÄÆYCøbÙ¡âêlB©ª2 Í£yzSÎ[õþèÁàc%¦RòX¦Ÿ[hTêâ°×äë•0'fæøöŒÅ•´¶Hü#•»ÛÃhöm#¹Nú šØx7Iá38+°YÑ¡µ½\˜F™†Å•6¬ÖËY ±ÞaØÜЪ –}¯,ØzLJât”cõ¤Œß{S/²q™«°'ÀMäö›*ƒn Éœ-ágK¸iTš°µÈã°Ð>C‡vy3-BAsii"&ÍÆ)‰×–×/°sN3ZW”_E3ùÚ•S(‰jáÊq"gÕuiÁèçy}$ªÁÂå×jgG……Ñ,Iz>ÁÐçé ¿Y®|°ì†º6J›ƒï§¢oäRQÑd…9Ü }/Nö¸C|à ™‹/üq?²ÝD6ZQÿIæR^œ”ßÕÄÕ­Eö\÷¸IÌ IVõBÑÅTtYT¤c Ò•ë¶*Ù۬ÔG©öx´Ü˜ú ™Ò9'›lµ©=*|´¾’kªºSX=yÈ䀮d÷1%ž\Ç^$ÜP»E1G¯%iSþ@{£’¡aÛ»°UÞËþñ"–šRš41뜪ÉGÉ"Böв#楡8·.·&wSÖ“ưøÉ`œ,ºWuÄ[žƒ'_ºe6U8Çö«·ŽyšS ÇÊUx +YYïRÞÓ/9¸15&ɶŒ±ÞäU?´@®•åã·-mK°Ò>} ÛÑ'Kª`š+¹"éìñ˜®*ib Ó¬–m¾Œù¤fÉgVeaž\DjHZOƒÜØŠ'…•%nüÙŠrÝrÛù µ@krpÄ{%©8x×Ðã"Ÿ ­ÙÔ×ú*°Æ¡YðúužBöúJæÂg óÁ¾jCk•ðóa½`•1Õ¯‚“×b‹:T‚šÞ­êÜn»ÂZž5Ž<¦ñQªöR»*Qß~‹Ë mµž‹AéÆÃ:yœe@ñd•n”» ìòŠV–›ƒd‹—·Ù*¾bK8‡~ìá‚@J@Ìʘ؉©q0ÄÜT›ó©ŠÍЮ N>PÝ,™ÿVï[ëXôE—UQ¨˜òé5‰á¬ñÆÒÖG­r¹LeJ?v¤Ö3!š¼xЬ+Ën²­­Ä™‘_ïËs_ÿà‘jyËtØú} RÇ’kKäE«måO²”Sq2«©.+9è«7x¾Ým®&ƒŽ±V‘åðü;<¥Êæ­o®úîäÿÀõoÃendstream endobj 176 0 obj 5825 endobj 180 0 obj <> stream xœµ\[·‘~—ü†yó9 M§›dß؇ȱŒÞdWV°Aâ}]G°43Ö%‰öׇue›}æ$ÆBtÎi6›,¿ªúªØ?_ôÝpÑÃþÿù»¿~2_¼þð ¿xýàç^¼àÿž¿»xô47ˆCþ¥[ûu¸xúêÝ9\ÌábŽ©ëÃÅÓwþrHÇñÐÃaÈÿGü|¹ôC×ãáÇËtø¯ãe8<…O¿ƒOÿyŒôáÏÇË‘>ý>ßýíñ2Óákh‡·ýö˜ßäcÈ]ÅÃãcœº¾Ÿ¸Ó'ùJ ðCî0tëº,Óá7¹Ÿ?ø–VèZ>–&<Âr¯s·.3ŒMÚ<9“úy¢à@¾Ñýp¼œè7Ø0ãñNñ›Ò—ùøÛcÌŸ¦uýß§ße‰ÁJ4¹“% õé‹,È…7GhxÉW.cßÍúRƒ›c˜ò°Çåð žúîÖÜwÏòxVüáe–Úûüm¤ÑÝæ._å¯3Ü7Áø '?†Ãß`Žàò˜û‰Øoæ{¸Ê'êûu¾ò&Ïþ¯YRø ›|méóû~r[Êtx{¤ÿžŸçÃóü®ÁÏoázݤw¿¦0"‘Þÿå;¡ù _ܯ ÷°Ì]’õ€!tÏ6í<Ê•¬ïãÜÃgRÐ^ã%á0U¾ Ž.· …ŒíÜ›xÜ43QWøV i²ë`šÝÒB|Òþy S˜ò:dmXa9¸—¿ÃµÜŠú+½—î`>K+TG’Ëå»q‚}âÉ¢9\ƒTà iÉÚ’²jŒt«¬÷'×¢hdJ¨S›‹CQ˱S¼ êOä9ýB¿ßPÿéðn˜pYŸñ>ÁYLèJ^‹Õ€¡ápµ)´Ò€ÞŒ´Î09¸{LˆM0O¸›¾†^gÞ;®™61âxßóò……°ç%ªaìûnIAñÍ"ψîíI+Wµ,èËÆ§„ 5*MËZœ2üñè”G@ZõšE¼L ü1ÃnŠhƒò$áCw!cÕ¥<© A@Ý’É¢vëBs¾_“®I̲ ñÈC1Š L! k\tuÞy|·ü{V+/¸þ¢4W¥¦Yòw‚»º†C*šF”iÄ üÝ êUÂ…†Q¿$kCxæ{’9ÕÐ$2Ês‘Ý6ŽVÿIņ.ôªbn‡Fžˆâ({Ý‚ˆgZpϽ*ÃÏ­Sþ8´+ÞÑX—Õ¨Ûµ*•>y@É_‰<À8…B›ÖGµ‚Ñà›Â ^FFY×hÖÉ*LB…@¡>3è4Zè$2à]—±²r¬W)ù°vùYß?xúo!WHs ‹wŒ=Øó;ÕFýÔ¸¤7 nÎ ¨•¡ïQez+™ñ' õæ2£­1}ð3|]¢‡Üu¨àvnÏ6ðùÁ‡ÉŒã¢ÀTäG¦!ªÈnÄÛ '3â¢~!£Ê ú]C4<Ô@4=4ì*èšÇ»rÞé…;ɺÎsÐáy[íí8?>…ˆ¦ôSíÓÕÑ¢é/ÏÊc¥ºÓV(Ë„Z£«ÊÛVY•ø5ºˆjÅ$å0~Iô7ÀÞ_&2bÎ[º"œJ¾!®=~õfø%úJV!-Þàæ/­ºa§é„Ë ÞXÞ ¿Ñ0 ï—™¶ˆcNhFoM@\ ’éXVô+{$ ûnã…y¯ªeŽ ‹•pï…ª‚ו¢z"än·ut»»I4Ô‚åC#P,\k(W=I„u@x(fVÝ¥·´/Ã2 sT›%]X#Þ®ÝV:(ª¥ú˨–„ú«kl|¥çG´‹ÙPý”õµ.(-F¼°¤5õ3,„ŽÖ®Üç“ÇÒË0ŠN,0iÆoZÁA &–.h4aºßì\Àøá×GŒqÃÚ›åûT°æ‹ÊÍ‚yC|·NF‘Þx?îÎé×PV-éþµ¬d8¥—$½ûÌ>Øë˜8‚@axàr!Cº¢„›7ES$ ½ÃíxÈ××Xü(@Ž!‘2^—îj Ž`‰ÖÊÏÊ¿&„Å+ïÝòð¬6Ä8âÀð·Úl:äìÉߢ!;sK,B[ u pa\‹yÓI·ÜÍ7~ã8p_ýM‘7G ˜ñ.Ê °Æó=0“꤆i€°©ö_½ú™£ØZLVåo†¤[\Ý:‘†Ç²­ñ‚¿L\LâšKFV6Íh)$"àšÈ(>Uê(‘NI  „>4HócÀ§8܃_¦-‹:µ– c—ª‹¬òa";YÌ òT_3 Q#€7ißšnN­hô„pS7-&L•§íMi÷à,–Õ(JV>9ð |,æÇ_)êTWš¬+M>ˆB|jÿ^—¦îþ€á•5Ü/+’&la•U•DÖÐTQÒkvqû àLøa¥n{kãðÿ¬Ï:tc‰8øö—àðÒ¬ÅIÀLZºgûEBgÆò,d?;ôêç‡Û­!#Ûèß“ç̾À™apBo–±K‹†¯p¶[øM ‹.n³MÝ`J —lX$b1Æ’Õ_ f1–•©õ!„ÃIR’É#¡ÌÓÛÙ;Qu¼5 £b—¢HìpêÛ%Èu7?ÖºÇfp*žû[±“øh°Ð¸€£·Ðl<ÿ –ƒy‘3”3ôÞÞ¶”SÈ@”µ§8!uÉxuÊrR2Á¸’ìkñÂl, ¤‡„Hð¥²×´XÝ k¬]ŠQ6õqq9DÀ¹ž+Yí–öàz_o­yKñî\âÚª:K"´*hýTümgš6?S?4Î=&{0ËÄËÔë„-G!‰<áU…T&«))èùs*â ™äíJ›Œ$—›`oÛÀ±qX9¶ÜÁ§Çºš&Ëõ´® iÀ>v#:²)OÌòå“SF“'Wê #jì4\F^C ö˜­.kŽ÷A¯öq[`}R@ Å{Ýšjò”A׈v¯ ­åÓ¶Ê2„…¡&èÔ°¼Ï›ÄÍ“²)”0«ðt¤ß¾¬ÉŠ8þç˜Ê2Ý0C¿Ì ÝØ²/óùë4õ•Áã r—þÃBƒ°K–yF\Œ&¿¶®aiìÅR:ÈöÊ ]hy—«³XfÌè kIÒO^õìicO›|ä«r–Í£éŸH« £„’[D+3µ—}ݲS°´Å¢psTH‹…ÎNlh„Gœ4GŸ–3È´!u¿E3ÒèÝé[Ùfè«‘¼ pØ!O(ÖŒè$‡6+@Yà‹ÀÀ.³3dÚ¥€ˆ!üO±85ô£±¸žxñl Åúó®RqDýSÃÑÔ$¬¬ï’š8)œ»œú$ͯÍd)6˜—Ä…¦Ïœî_΃ø%ýIÈT2ü·ÂMn×ìjɯ±.Ph²Ã»,N;/rZO9ž§ûÔÀ©ûj«ac·hô»…@çwm²¥„‘ žBæj‹ÿ º/´U¯w\„¾©u §ì«µÀQ(1BŽ´–hó†ÜCP;¡È„’T—ï9ûeštŸkˆÚ$ÝÙ uNr‹ac¸Øqáá*Έža+1„Ò ]Ð`r‰hN Iñ*ëÔÍ“/@!Ä_ÍlƒíÆm¢Hm¢ˆ„òÁL[¯ˆ±³$'æßh´B¶É>ÜèÉí-ûœJ¿ª@EÊxê^µ,=§IÈy&W¿P‚Óy7”eÚÀ›Ã¦¬(;bÀ%œå^IZJ´X´×À†dŒ–±Ø©‡š†-¯ARR•„ÿL@ŠCÅ*_Ü#”$QIÓÈ]ï»hÍ!ˆD¬7´î§š…ø‰+âªQª™„äj‘¢˜“Z+óX'0µÆí|¨Ì˜w¦»O]°³®xë»ý9zÍùLpÓ[®·"ªåVâXÁO#ωIæ¸ ©BÄó™LBÞ…NO1m6T¹4 çÅnö=ýl”K Ø8DÜ¥”ÎçìûU½¦X6NthÚÇž¢«Gy…)œÌ÷®.ò@‚æj³û¨=`U¨©Ÿte™þ–²–÷äY)¿ù©yê8)Ï÷uÑù÷0…UŸMóÒLÓÿ\‚¬}BËE‘PÀ´ðø‹|6\¶Þ¼òè=VôÇR@ËÓæ¼ýèCKSÖéø>V ©,Âôeòظôå¶–^¡F­ƒ­[Ùdœ\Ú¢ÎÄeV¢M’Á›ÌþíñDͱøè·îànQg2±Ñxmͱ6ª†­ˆœÂ½9n We·u®d’.0³ÜÉw­”h•_¨À@¡ c=‹ –qÇèÛj‹×¼fRa¤<£ør©×ºŠæö]ôGQÑT ÖcÐ~â*†—*ø’7 skÀ91˜ÀÃ~UšH5IqûÀK^nˆNñR_Åšp—y©èSÕ6ˆQ‡±÷³ïBÓÁbC(ütõÞ´çŸá´†Aw¥Ñ’f¶ Ò€÷ÒY³6xË’¬ä –¤Œç®¯2 ,OKZlV²8Go}…LÅ¿Š10‡ †èroR÷5‹!N' j²BxbÙ2”±Ø¦ƒ Íy„ÝXWÙDqP+¸²XM*—Õ½£Œ¿`ñ ‰xÖFU›‹A™Ù¸ì;ãz̈¶ä=+ª´¢àæšïû¸¤BEèg>Ç]ék÷ÄÚö6ÎÌW¬¯¸áï|VSb?ñL{Ÿ]*þnþ‚ñ^$¿v¤f ±*gåMï‰ïMïe¬¿Â'£Ò €i M h¸TŒ1˜”lÅÅaµ™)úÈW$‹¥êñ÷iÖ}Ññj&ü†6;ÝS¦m?[>=”Ù‡³rá+ùdmóet‹4R·1lóKP]”ó›ÆEëD5EÄ2) ªsSRžeé ëà×?A“pø,%8\Š‚Á1¦ÀENÎm¦ ci©Úðšåðã{"}^n<ÁŠÁ©+Èòˆ‹ïäX…!éÔæQ”‡Ê|šÚ E&Û*4 ãɲ¯¹ß óoé2·²h`j ´²d¦È°Y[´È×pÔÕ2ܯ²œZ¤Æf³~Òrÿ*pYUã\a¯¶ßØHCAIÒÇ…´´-LˆtÁz²ÛàrÒÍlÞ˜Œ–ïØ´³û€&D-P(pÀKxJ6'uSq¢ÛðJJ¼?éSІ&¹V/>etUFt>³PŸ/ezíç×ö…:gd¼ó Òð0Ö úê$³-€E«\îÁJ´‰´MJ¹¥¬±—ºTF’VþLåR¦baO?P—.=©{áèν´^>Ìæ™·êÌä&È ©ð.›¬;gåÏ!\¹ÙÕåùʇ¥òžš5+©Ô½Ô‡Ç«†??º`u´JvŸLå@¡º{&”¸‘XºTÊ­u„®Wå5ÙPÏaÐãL8¶â !–WáÈOžz8±Mé…+„ðûbêêšß“U™‘*gj®ÿŠ˜±f^Gõç“@½¬%zÓ²aèD‹f>…?‹‘«; V•:VGG©ˆöžâLaû›Å™ϸI†–öY‹IE33k U_&ÃdT!jçò8Lf¤ 2è Ñ’*¾Ý$”ª3/¦˜Ç+šGë97TrA˜T©}Xª×2šîOªúø»Y¾ôP¢’Ì–F¥çs)§¿R³YR&Ó+ eÙš=îWÈ ‡Ãìö7Ï!ÈI¤Šå»jÐ_uynâðk«efsŸH†JfGâW»yö¾RºîÌŒgÛž1ƒÓgë&ü0W(-^ß­ ’;>ég¡³:È)öNï<v-¢ŽÖ’Ðk†yÆ‹|R*Ê«ÐÆí™™v†È§ØÂ@'¢#à†Ÿá†O²h šƒf!L."fx½B_ý5<9„¬|¾N‡ïÝý 1\X[ÓŽ*ÝøT–×Ý3+ú5ƒ>™ #í™»!˜°¹"9|Þ}[9ÇÚV’á_ ŠWÎr•3±X’~úð——We]p…ŸÚŠ'Û°…¶î› oWë2M‹=©¾9½™†’[4¥Þ69†¢M#ù„º¾æfŠ?…0‚½Ðfñ Þ®ebÃoÞsyÓÈ«<x'GJ³$UάG)kcv¥€–n™W›D+%Õq=oÞ‹²C0Óó»×àÎM0é ßêáë=ð'cÞ”OS·_ÎáÎãñ¸=¸4JcÅÇ`ÃQQìXGå¬ççJNÕé™2‡éÞ0£ö©]Ço½n¦a§\T†û¥-Rùü!lÇÓj*È’;µ* q w/ÃÐfUé=¶s*­ª†›"&™æ+ù˜*›ÖâO¬Ûé[B š¹ŽÝ#퓜‰<Ù•x°D¶™psNÒ‘µó`™bϰ˜ÜÐÆ¾ûG*7¼Ÿ•“AK¿GÙWåÞJAsʣ⃿x<”¢h,Á˜é1=E£åœÄ·Ñ÷/™Ç,õH̲V]ñˆš'¢$dTŽù…•;(;X/˜ëîxY¯‹váÎ-šâÍ×6!„òÆS[™ØðAò:¸ ï„Õ¦mÜi’Pf£¾ÝÙPëÂŽßfg³ŒµŠ­øó´Á!ÇQƒü’¶ÑÐݼD iƸZhëŽlWÔ_Waß»°‹…¦/ÿ¥káÖ¬K½-?¬õHÒÊçûÍòÖW~¹è“ëov*ø%ɼã¼hnXˆ²ªõkö<×ÏG¡¡ä#Äò¶1/ÅKŽ¥¢ïïœ š٤¤DÓ¸ r¥%˜E¬Ï‡ï'ä ÓVUeÚè©U!IÌê$¦†šÏ¸_ÑEÛ_2Ö³¦´ª­l0“©²ëaÃJZ5Ž®Ãõ_`5YÃ:ó" t‘×.Û¹Hƒ_‰‹' ÷S‘%XÞ”‰øê©QkñãÒzk•ÚãÒ"“7ƒºø%$v‚Aí|[È8qŽÛQ£!m–þó9Ãh䥋uƒjþÓ2[:¥â¦yhÖHãÊ95òâ‘aO—öÒ‚Z‚£ï ¡ì%k§Is\X‹Z5Ùœkä£(깨Ãaœ!½«6&ïX 7ÃñƒŸ!»+t§o(!ݰž?ë Êk¨´JŸYÑ»ã¦:bZ e½aÙª¢imxªV†nJ×I¹ÂTCJñôìÍ›DËú¸D\ëî¶#Êè=ž Ä·¦P}[°Te–E°oþµygjþ¦¶aîÜ‚R²¥/ûë¤åÄÛ@·UPL <> mFñ­Žòiá ÉKq{¢—Ú i¡b»_}«2t´ó.zÄõV šüÛ~‡ îu©á÷o{ëz:àÚÄâÍXÎ!Vovà’\óp¿‘â7(Îz„¼e·w2ౕb²¯mnŠ€z3u[›÷ÎЄÇNtX«’ƼÉñ±ïÀÁÖŒ¼9ç#{ÙFLITUó§ÔÏ€ÊKKüÂÉ ˆ)¸ôƒ½<ã_VÇoä÷¿6Îñ¼%·q¿îÜ’Ž=ùø¶´÷›§þ;ÿù]æê> stream xœµZÉrǽ#ú§œQ×ÒÛÉ!K¢M‡,Ú$ì‹äH ‚†âjéë{eU÷€’†„™éZ³^¾|™Õ?÷‡pÞã?ùûôæì‹GÓùõÛ³þüúì§³@ÏåÏÓ›ó?]@ƒá—ÃÒ/áüâù÷ çS<ŸR>ôñüâæìû]ì†ÝÜ ÿ¾ø+ôH¡ê1B³ .® áWÝ>ïþ҅òÌyÙ}ÙÅÝß»}Ü]àïßt{}ð¨Û§ØúwÆ>tûi^Ë<îîwÛÀ§¥9v?ôÐzÜ=îöÕ£‡8t™'žü!þï;[Á¿ì“›ý».ú!à –ïð> 1àd)fè5ÒV°ß×ðSá§°û³-õŸÖƒÆúºKØg¡Iãî[ü=Àè'x€&ÓÙ¦õ)ìŨûÔ¦°,lÛ¸³7Ðq÷# ó®K»g]Þ½…õL™î–|_ç™ { _o»k‡¸ûÛej÷º«‡8z ¿¾Gõ¿ÀxýÄSó ð›>ÃÉz²½Î=4Å?oÀñѶÁVCH+B÷r¥‹Á1÷øü”ÚÈPó¢Þã6ÁZ´õ$¯‘§p˞Ѫi×ðäÈÄ|ˆäúWÞì—,Löl‚šæÚP7ï>t)³,\°ÈÃT˧‚ó˜^ØQ”[ó¨°¿QL«3"&fž+my«ÀŠLfXs þ” 24ÖT"4hâ‰Zhg›°ŸªU³Î +¤ÀÝÒõ&Z·pPƒI˜4É× §×jþgc¨XÎ…oe{ˆoømQX›ëL³?ûp²;p"öÕ"<¼©š§Ç@üí=Eón%Êo؆ìõ™(ÐÏ©S/ìWt2 —´ŒjîjZGbKgÕ_§4a`V¯øMø bÇ€bDÙýnA`ŒÆ7 ¥9œÒEnin-w/%rÆRpÙÃ3aD7€¹ yê=´"%ž’L2~¬i>Èü´ÿ‡ äÆ8ÚyMW>Š8qzì„cÐF¦Ä”žÒ(\˜Š£>Dü¬1­µç‰ø “*³Áç™\öC7$DæX…«u˜s9ˆN1„,EçÛï·&³¦1(ˆÐ¨‚æa#ÑY±¿{µv4¦q}r‹×•õ [Ì(B¥¹ŽBkO6-:%•:Åk› mE f¯VU&ocA*ÆÄ‡Lù)î¾Îïré`dþ µ«ôä’Ö“„T+XfrV§Mãšç+=ösñJÅï±æ±:'…[RƒgÆs@˜"¸Ç‘uÔœ³iö7œÀà´8ÓëÕfÜÜøõ—.WJ+…¤@ô€©~k=ô$¤aFWÙUéÐÈqL3ü°¦á®4¯Žà½V£oHÂ*‘dÛÔ”E'ÿ¢ª¼bvˆK¡P‘rÞWéâ”™³"¥ÄÚÌÈGê,*+§—y›jǪÌÒPâ5ÕAÉÓÂrGNçßž]üáû]€'«¤šß©½Ž€}]F®óÊ9¿ÐÒ!ÎÈûå”Ü<œHr˜£ f1I€HÚd•TÙJ£µ¨â ^ºÒq(¤kI©8æ6£Ñ1Z»Ể J‹€³éÍÇÚ=ïN•„(µJ‰Y˲ņö±é¥3^ðÞw¤INå,0'ÇóΣŠã~0ŸT¡Ré_Gû[’ô^W*s›å¨ÌìøhÉy,¹+6©Â®ÏZFîW´–r¸aŽÈ»±4ã\¢Dœ‹å†«I—Ó6?¤e¾3ÝÉó&«V®‹¸êèÏÇ7Œ"HÌ>8”‚gžë q)êaШðª*‹Ø!X ñÒa¤'X!mÖ2”¤Lšƒ;óW+ñºð«N RÞO7 >Ïvj’ЦXpêߢV)®Œ¨ùlžšŒþ_‹Yˆ¯³ ‡KTVæ!dµ¡Éï®1¤i²âž_*œ/ ËßR’qŠ^\*Ë¿s~Õ;í'Å÷5×A¾þ+ 8id-[U ä‚c»ö «-`µ'¯E%Œ‡±¤?ò쉙9·gÛ® [¦“üZ‚t‰6À±A³¾B;x3$œ)ÅÔ4§“TGiÝäjLeøF¢lÖ¬]ÈÕš6^ÓÙ§ËriŽ\öBì3qéÃ}2¸‹º|uÜJ|8:1 ´˜}ã×FEÐˤhêJ몳K#ºØ¬`UTÎê2tïw`Û*0uŽÆñqé¡XÚLÁÔîö¬Î–è”Rõ0;8ÜÖàûÉÂÛû-ÄhŽ¡]êø'é†úTË™S”ªK ž¢xãuns2©äRèžvÍ-š§3Ê覚óD®}‚ù´™Õ¿Â´±“U1Ç•å≕ËúAÂJUyÙ¥X†{Ër¼â<=ÖÙq<~•OúÇn|M­{°mp¹õ`íaƒ¦4>/q w7msÅÁq –8®€u"óRqÕ$2«Ì7ÏëT:Xß’”ìkÉíÀu­Ð䘤&0¼âÈ•W9º8ÅÂhr`c¡°yZÕãNžÓx0#KüqXZ­NkKPá´xÈt)»¢Zç.uâȵ¨lrwðï=ÊK ëWššË§p‡dR[Ê…jâÚŠQ›z·O®q:`÷¦P1²Ov>vq¦²z5Ÿîæ}×ÕÆhúì¹w”¡Öÿoœ·t‘iT‹*u\\à-VŸ-Ð×/,K¨odœò,M0¬aŠ> stream xœ¥ZYoÇ~'ü#öqÆÑNúžî1`R #²ŠÈ‹•Š—›¤D‘¦˜_Ÿ:ºú˜•¨ÉÙ™žîê:¾úªz?lÔ¤7 òÿ“˃¿Λ‹jsqðá@ÓÃMþwr¹ùéÄQS&lŽÎøE½™Í&3¥ÍÑåÁoÃÏãVO*¸‡·ãÖLÆhk‡ãQM*ú¬ÞçÛÉ ·£žœI! gp•¬ óp3ní×  Ó 7ÜáeÔÁéºV#Þ=VÁ‡N‚¼ë,kC0Ï”Tbu¤IeDGãÖ¡LlèUÿÁ”Du°²¥g×#®¸µÚ §8Ÿ“RZE|Ä÷hŽ8¥„ÖÜZe'¯¼ÁÇÇ0Íó¡r ‹¦è½}‹w=ÌhÁs\PÑdÍÀ;œì ¯ ¶•{M÷A^IÓ"T1’(eÀ[‘©Yw|\v ·".d\ͤf“À`1ðZð¨m“À¶Üýè|ü4ï_éºèuÕÉûvbÇÛÀ Ë@”È©™\òRœa.ƒ‹‚o‹ÎH›øŽÄ),8Ð5+e„`¬ûDíã`íXÍÍ+¸Nž½XÜ Ò,¦ÁoÈ™̈[@¡<ùKžuÊØfmlaï1Q)Ù¬f޼±³¬ñSÜ åú­|NJƒÑ¦èhˆ™t´ªE6jç·â§(Ü<Ë]\ñYQçójNŒ‹¼Wø†"‹¡¿ŒF\JFO0Ú’õ×±uç{|7­8 Š+DrmP·¦DîYÜW=IºÉn³çÍDzöÜôÚáùA]&G¦¼Û{Nð¤Çãj6cª3|IÚfÚ'£x!i†¼O«Ù€6˜+Nào7ºxÂIcï}u Ï±E®EÏ­_Øvk9P<> ŽËr_öü’ƒçSñ±ðfƒÃ@¬Ò7.rÒû¾ú¦‹\‚*øèebxùÆ[ØÏ$ñ³F̹H9¬ «ç5Ö¹@å$³“Ñθrl,zÌ‘-£«Ñ«©‘„n·¯Eðy õ%†t2«]ÐJ@0¶Ú8t™';©‹jU-Zý${ŽušrYžVÔfXÜ’uQ[ÇYxýßê›b§/€_õAÀ±(8tš¬QVØÀ0áÙ Ü^ÀÛoGB7«)…˜¹âKvN;óã{Ü”­›ÂLª°Ÿ¶M¥ì$\f2Öëaº’:¾¢áZ9ñ·Àk¬&N^ƒ#Ȱ×#‹™9µšÜd †Q¡Æå¼Úähã—#ß ]h"éx”«ò2†ús:jxž/Ç4>!ˆé¡‹&!3A*ë,so³ÄèÀ½‘áìccm/d7±Ø>î䮑{“¡"MshSRY5$÷ĶÄm̵Ñ"~NGpÞEøuàë˜ðut•u/<¢%¶n.”Ó9rJ¡& M-¸ØÁr&2eŸÜˆDM>¶Ã·aoHªZgkƒÆûµ q‰”.S8CÈ%„á–‡àÞYüÆmîÄÁ¡pK–&ÈÎǶ³Poˆí„J@E³Šž¼_ñq`‰(\e˜íj) š)_jŽüÎ*£ \2±q¸.Ïç{uúŽ<è¯Ù­—¡­)RÖbḜqžtшÎÑò–iø@øgãh'ïÖãÛJdKP[OpÛ8,=!‹`¯.eKþ¸g ¥ÚŽf£6š{2Á.åègB_à4ûUˆ…*µ ¡#«Eë)N.±Ê†hÐõ• ùbX”gdФ~ÆáÞÒÏEnÝñ %D¢ºg@ÀQU;ð¬8AUëäöÚí:oŒ,%ç2D(:²iÖ¼íÜ{ŽG˜ò ŸÒÇ—ŒõÅ!'¤*ü‘|r—)”¦Á!;ßmÈŒì.ëég¼,B&v¡swHÀ¸ËT•rÞf¼—ÓéŽöcûÿÁW”J¼¬-ɪ/¸º‹i†¥ú¦ììö5`Ó62)yCÔ iúÏÁ9¼Ð |2õжùU»/ÅvL8gŠ 8Uç+»\¼²Õ’1{öä´›À) ÒµmÞîÖa»OiÞµ‡ÒÙÏNcÂ4@è4ða SiÀ¬àÀß·˜¦"lû9fc¢¹©R7!ByE/g@«íˆ—Ë1ÌÃS¬ÎuœÉ‚ØS±»¼."äö¢ó³L«ƒ£½+ÐB<ÜSÎä[FÚË8´wô“V‚ö✖É}tíÈúú;Þt$Êã3¸9((à;:XÏ5®eÀ@ÛKS«­?¤j˜¿²“•(–LÅÖ¾ÊM†EÀ™¨%­7ƒK| 9oÈu­5µ&)]¿ëB˜¯¸—¦¨w(>N33öc9Ña;MeB `¹ÎÛ‰Vì }×a[n,m!G·"c ï‡1f©¨½ÃuJåoy¡?9|A–ÐTÅuÛýº~mÛ¶Éqûö^ƒÖPZâ¢:ß}—3Ǹ/Œ·lZE¸ÑìÉÝ®k­’õlçy¶ŸvÝÌqrÜ=qjÛPD_ˆÆ=d;ªš”î™)i‰â=)®KkùŒºTÙçÜãÁ”‰ºfß"uŠ©^VÍNƒ©·:• °•R<'ç4<Ò½ÏåÜ8Ù‰”—a.Òåenûaw¼¥é-éy6”7/Êæ`©“Å]ÜO ٞƶ¿‹9gÆ®H ‹RXéE¹º3숤´Ët³ÇgrfaÆDÚ-êÂt\/_ßHÍ#}|ìDÄæ¨áo éÞ‹JZÿRû¸a£5ü~¿­2°eã-ÅÊò+o>4o¶à‘3 ‹Ç)l€2$Ó61Á¡«Ùáßøçi)ãñã+üózm)ÞÎpi(›8üÁ”EŽ'Ô‡(Tá'Wå µGèr-“lŸ"ê¥‹Åæ“ŠWèSºK*^³rO;#ÝJrâÂñCv,øeÓ³µÒž½å™gÍ0mWd'@0j¤y×ç¶ÒžËýÒÒO;º)tÝ%îη$HéÙ#Ëå#NðWJz*ÊE`J‰V(x±h·ßð*ö¹•¥ºº¶åsñ•Ô󖚀Á§+ì01Í´ÛÈü¶my€± £Í!²í jÈ–iÙ‘ïpÁ²O–åñ\€?«¾©†¹b*µxgmBBãI61veÅl¸fy…¡œ`£AžJÞeI¤¦dþ}GRúReY¦,Ó±0C=ó‘:r·ÀÈUïçl£oRme–à½âiûÀmkü½§WíèL̬:½hÑ>‰JÛB×ìÈîÛV,Wú r"‘ŸBo ¬ø+ïHGÅ9×ÂJ ª'#ÅKLÃï0.à¤F"ÍpøG„Rî4‚O-;¥AHk·ê,GFï6õt~¡é½ ®Î%¢”/í«®Ç€ô"™šþÓv¸¸K1÷¡¿Òš-¸€ù»»¤Yñƒµ¼Þ¶òûH"JçHÃN_ƈ5‹G¹ tñ¨œY²½Ö¸,Ž˜8Â0dÌuQQáWzdú/»‰EÎÆY-þ2λéH¼¥SÝ÷$ÎXãR4]I}›lI7lßë‹måþ?£«D#FWVš‹‚>Ëñ(£k2 ƸÊÝǶçŠ_Õ¯>Õâò³ R9JwG$ù˜Ïq§zúñÙZYNað{ Ü@m³ów…²ý&92{)››…º£t ¢ÕB¾éÑ-!e긃”ð¥-ßÈT¨|]ìj¿i7‡;ɧ×S-ÆJI]Ær—5úõDCMàþœì3ïg';H&Ô‹wðP±â¾)õ]ikâïx(üFŽô Ø2Ð|E¥ÁèÓéìA’ãêé[{v'¨±Ìmk~µ—œE‹Í*"0n·ø$rö¢äåWåÞJñYëNúsÙ“´‹ªï%©ZФˆ]ÎÍ0ÔúZpâ‰%ƧGÿ‚ŸÿÐk&ãendstream endobj 191 0 obj 3240 endobj 197 0 obj <> stream xœÕ[[o·~Wý#ô–ÝÖgÃÛî’-Æv’&±SGAQ$*K¶Ä’_â$¿¾sáÃÝ=ÒqÐ>l‹ËËpøqæ›ê§c3Øcƒò¿g—G>ž/^™ã‹£ŸŽ,}<Îÿœ]ÿý:X-C2ÉŸ<;â‘öxvdzƒqÇ'—Gßv¾;ÓߟüFx«G8g†`ÐÉ9tü¸ß…îÓÞ)źz×}Õï\w‚í÷û|xÜï¼·ƒ1s7ÂÜ|q6ÂÇîï} a_÷» ¾;×}V‡}ŒÃü⌭®{ØÓÔÐ’&{Ûcw8uzk=ü×Ä~$Ùà'&ì轌õÐÝãì>vê÷ozøhFgIðÜXV¤e@¾ÆÍ³c­¸ µ²ËjÙy3Ì6%ÖNè=w^(&š@ÕY‡¤«ç°ýî)ˆ9&؇çFRå—½§=vŸÃ×yeLÝ+¦»E¾e­Y»7ÐïöJfšõ}‰?c?ì}m÷g!âØÂ$0ÂG“» Û]÷3.‰M¯ëqàOp¦ð\"ÚîdÄϰÎE’ýØ“²ƒ‡N›üœHܼR¤ì:<†Óƒ^&ü¬@ Ñ¡ñ5…çp‰|`¯zÔ¶wq0sí¾ÂMi´Ž$ a"mý5Îþ¦×ÒŸõ·lAPX“¥ Ï Ô©!ö|ÐÝ¿,ß+b?/XFÉwÞNC<ÞˆGćÈëQ‡0ÓÕ:mç ãD§]³–·CW;â1ú„ƒxŸ!¢œãܰªUà¹Æ¶‘Žë\&f<„Ú ç#­Ä ¬~ÅxÙ&œkAŽlÆ–Ÿ튥ÇI’M° ÍŽG’6V=½bùp µöS›£³?e¼ÀuŒÁ ^.úQA ú… È ~«beêçÅr=eu¥è×]‘<¦'ešUgÖXRó]³qÞ‰ð„™1EÞƒ:ô| /ëãNH>Ä`I®gÖ>þø  „¬fFÏíúî8e´¤ðΆR# 0ñº#âMÜFŠ÷HAͺWQ±†Î¸FФøp#Rø`ì{˜¡Ù niªSýD ØÈîZSS0'Ë÷ø¥X{P²)òL]ørü8vœ¸Šâëi Þ亻Él óí˜NEž&‘Õ±˜$¥XK:õ‘nŸv‡ r×á:¥²Á„™9€6d\ð4üT™7ÑŠØjÔdÖf>>¯›M÷®(ßS…"q=Ê/8ìB³£eÖ7Äóá¡(c傇ÊLùÈ4U˜af“QW'Õ }fA!¶,}òD,(kôí²6ä3Ð)àBRH.ç*HüâèäÏzÐÇ7 º±ç×øã'¹çа‹ˆDÜ!-Ʋ¬ãAŒxi1s&ÔÒ„èßy7k €™—~¸ÐÛ,’¯X܆;™c KÅ…¶ÆÍ~dÈg³4±u,ؽ@¡Ç•G9Ik®–¥/h‚‰û'ñ÷ÝÀòÃÛlfí`º2ìf°ýØ8Må’¼mÖŸ…èdìŸg‰£¾U0[ºÑ{vÖšB²—”‘Åoß’¼ÕÉM7ø†Üƒ­ïœÀi/Œ¯8ªö•Æ1.XSbGdØ9ê’‰_[;v‘óû±:Eâ…ááßk‰ºwÈø¬') ¢œ—媺ï:£Ü>*³Å{Åé¶üiv|š_AÜʲp(Dx¢À{AäP‰K7®0$…G”ëæ»š°Wŵ÷zùß£Úø Ǿ"×l‚w¸™–ý f‘¤Ç©¬Â¨¹×‡6ó_Øá»03ðõ-Ñö3Žš÷Áq°ãÞS_Ž7½ñS÷ל yÌ~ð†râ¼ø(ÜÓ3ºÝ«ƒ>8ú9gà˜i€POÀ7cM3.¬Í<°ú5m|Ã/±1îw­&Œ6±o-V£:¿Çâ`•›„£¡[€ P8:$H ÕÐ\ìØºaDcº¿Á?ÎÐîöFÇùoKãëÚ°Ê­Û>ذëm}ðtþWŸ”F|bôåJF#8f«‘SYÝz€Aœ9F!8.ÄÆ2äYÈ)c˜‡z{_ŠË6À»Q–`ÄΖel22¿ºëÙ`-¹þíø½A ïAƒgËAèG½²÷x³³½„hA7U~V Ú [“ÁSܙѽp«ZûJÍr;CÞ€T¼—îæ@/XG${Ïmc#iðÒ,Ãdºä…7•pV9Å•–,rñØÈðGŽy®u¸§L¥cuàAÜÅÒpŠ­ªIVY˜9‰(X޹ÍÄílƒã…Kt¾îA01ד˛Wö»±èêäqn¶˜fð%$z—ƒ¬š9kxW±·Û>¹±Þ¾&±¾ó ß­˜Y 9Qâ'U„6ôÚk|!òž§½¶w×”À#[ݧbpù¯K±ÄÜû‚:ö%N•Ã`rm˜"¶2‡)vg0(1¸ ÔÌÁf-¸ï)d˜?à3ï&͸Sìsæ1AtÒ ÎEãc÷a™YÇ<ÎÏàG`T”’Ïo'p5¦@çd‚³>/„Ó_ÕÏO¡qžlЏ_@‚³“·\øÑ(¡Ÿ=Èþ£ T¤4g–…&Î'ã—_T"»¦®j6 »Í°11— áµI…æJ<Ï+Ãel¨ê¹š+•Nñ‰í…еȑûz`1>ÙË4K’<®x0É•¶~Jþ;l±˜uj.—4=’ëÒšù«^óàD5”bBßõ.ÒÁEöº¿–lyK¶L%'uöAfG¡âD·þF²žs[ ¨¸0õ5Í(ù­êýñ,¼)1eõ¦lE“·Ôe¤ë¼M…ï”é3ÈrìTmì^_«MÒF×>p&{q]Äd9‘« ÈcxQs ï…þfà1M …‘ç,K6£‘ÙïVJþ,bÌ`5[®®fŽË×UEšÄ1*(üR€SÏ¿ŠŒ,)L¹mŒv¬ÄpðcQó¸è×"I6Ðê×#_:\0%q”î–0ÙáÉ5ìçZ¢+ØCR.¦mL8ª,0q%³-¸+f;çN*›‚ɇ\jïB•©’ÙxØkJŠ~P~~ˆR“2 ³¹£¨qÅÄs¦(:]$;uñhQ…lÍTËT5½£’t“ÖɘŸKõ!gÚL ôèUw.;‚ÛmRÞH ¤âœ$ìȼi`Îü»j§³Ûj )ómuB]¬ô\)þK’e£)à|Ñ~¯û¦0Ôškvù,§ÐýFë¢ (°©B^Ÿm°>±œ0£M£Ê ½[ö^¥yVh»Q)Ý@“Àflqgº55”ؤl q¯iÂQ9 Î;TåD­5½Å1¬œOÒ ¶…ði®õɾEÁ‹g»Áeq¡ß$²ëš­'P ˆ2Bø ÓCøf»î‹>’=Ý¿±ÿX* û™šL4 OtuÎÿ[{H4)0®$¯õÓ¯ª€kƒîÁzÒÙ:*» A‡XÏ«¼S»Ž øRƒ ¾{U4ÿkñ\A§k)¥1+w&®?<Èv&ä9|¯Þaåh(Â’$"¬rib"ÿÂ)Ê]˜Y9œ—_‘>•„,-¬<ÑDûžL©î±‘Dv(‘-%ñ3HÀFÇqÚÿ@„C$7K·•~Þ;ä.éÇI_ñ;¤\K_^Þ¸!S …ßRõEš¾ßîg&_èÉ*µu) –-‘ޱdøfŒ55¶`Ô9‰Mm­­`CC[¥­}õ´DÑX#‡’ã ´ª ½(¹Ø÷Œàè‹ïQ;ÙçlN¡©0‘))ã±Èh4e…`öÕ2²:M}0£ÞÊ«”¶páž[S³¢¤™“È&+™$k#Pïÿž¼ŒÃ´Hפ̣6!ŽOñIRóÕä@‘’¿[z?+^dYEIW¥Ïim¬WGõ¬³½ªïJãeOµ;“'á¶sm#)ö2$UJ”3òOJçÚ€IãYmüq+#ÿCiüíf™Õ˜7[[®dþ‹ÁY÷ïõ¹šÏ”3»å¤¸7 Ûž”N_rŸ«­²ÅåVÏ»µ±GÞ•CªG|];ž—Cjæã"ÛòG>²Lè$¨ûÉ:|á’ µ„Q‡&ë¤ÿ*Yç¢mœˆ‹7$ê°óíI:›$£ìÞô;’táÞB)`æü*Éþ˜JòD¨—$ÖYšeÄJ¡| ‹ˆ5¿³=­Z|ÖÒ Ã34$Šùßfi²C‰~ð˪vÎÛÇ;(Õ…Ef†êH’ÚQY™`š¬Œˆ².ë¹Ã32Sâ௼ü¡ƒÉžŒ©”òœ;® 0ú¸@ï/}ybà`&¤Ú–Þ;”b¢'Ú)‹¿/‰Qµ¿f¬t:ßÂW\þ{ø÷z–·D_Ff©çÁ®ZÆA¬b³$t0ùÓ¼¯Iãæ»àå°Ï‰MÑMû4GÅ߈^„2–¢ÁúüÍFV_X 9£±›FŠÒU„t­ i<Çb✼ô”e¹ª$ƒ'XH¹‘ÆÖÇ`*”—&šÉz(ë ¯ëáÕIÝK^ ´Þ,C™û9žñ”ϘÖê\SXÙ» åÞ,V‹ˆ}éo~V¼‘þžDÕ7$¾WÅÝâ Ϋ›"½×x¹}°L¯d¦!×d§lo‹”5Âý1çptýõ7ŽÞI ý´ôBN{a òëÄQE?7³éí§›…Róp´?›þ?¿oÙ|cêo}³Z8­•¿âPÚÄýÃF3£¦Æ™‹MÛ5NJfÄCjœ{f©qŽ‹_í8¼Æ™Ýã–ìã4Ê/u€õKò$rßüàOTk¦Cê³ÉÖXóú¬é}ÇDÁxu¦*cXꇞFÙý R9”ŸÍ.ÍÝ:“*At1ü[lÚUŽôCæªK!Jõ‘¥zîLIܨ¬\“1Ã*ñsæLßÜÌCüŠ—‡Ç—G[HÊ·+¦D ‘(mS® ÙúËÑ(5d»è§Æ›‡0;7©‡9Š'¯’^Œ­±Á†pŒºà­ª{AÜìkPÖü»K+æü²}šÒ–¯Úת¢$õ{$ù¹wj˜w;Á ÌŸ7¿ÜxÿäèŸð翉 vûendstream endobj 198 0 obj 3931 endobj 202 0 obj <> stream xœí[ÙoÞÆüGè­ 4÷âñÐÎÕ¸ñ‘:  )P[²eÃÖKJìüõÝ9w—\JŸå$} Kâr¹œ™ã7ßö»ÖìwðžìÝ{:ì_ìuûÇ{?í¼¹Ï¿Oö?;ˆœ‰#íÔMfÿàå=iö»?8ßvvÿàdïߛЄMÛØÅßÛaœÚiì7_5nó ÙÚÍÃfkÚiý´ù²Ù:|ë^|äIóaó´¡üæû¸àüóÇ«/áïšmÿŸƒFÒŒÍIóah»1Rwp)rqYÓ˜¸õvjG¿¿u];˜i¢ Ïâ„ x¯ERÏãª8ö®Ù†Í%9¶ñ›³8öæÅÝvC¼ã6¯`î ˜Òã³wàúm¤ïEã7§ñ"Î4݈ËÄi0C¾ßÜ—¡ƒ ¼ “7G°Rˆ+ ›çpýcC›×qÕòíð¬YðUc¿ñ¯‰ÕÀ<~ïw4ÖȨÕÇÚèica Øô& ¨@RaHyTÑÓé©+Yûm¼k”2rö]’pÝÔZ/"‚U=q9ç¼0ßLJ‚±›@]”î8%±d·Ÿ5À¡ÉL81À"vóãFÙ‹·$f\û{ƒr}ºÿÿéº` ©™0Êô›¿)ûP‹˜ø­qmèAña]$-ÊËÖ{?&µŽì²“Mêô÷L‡Ìfí#•ªÌ€S@ñº€þªÿyIüì@~#^žÅGQ=Ší Ü…—“²àΈk®3xc©:Çõî|¶LÐ%, Smä‘ ?‹z½Ø!ßžææ<†{QŽ3€j]×\‚Œe'×¢žy¡-’µÐ:‹·tŒ%;Œ\Å;ºãìEç AÜ( +^è2+nÌ¢u àNºd±HuúVýŸDâžWÎ9<|$à8¶ë>¢Ôøó;ái8œÓ('8N‹Éìì`qË(sØ!>–/–ô°ÔÏ4ã(©p«Ê*-Ú 4Ï¥@S?.£G&•dyXä`Â9Å88Êl¬Xº± V ÌìŒMžÿØÊÄ{0>µØtf»2%v~ÜA‰ïòK5+ÞòÈ9ëÑ.Žé‘os ó"{~ƼÄ>Ý`A„d¦®·½øÞS?æé:›q–$}R;€_À'\~ — v°7[Tl‡Þ0îtëP.ÈšýRo¼¥tH9~ªsž¥ÁÌf¦ÕÞ¥Á_tð¤ý f@5¢±£ü¢âuH•Î2†ÁvèÒhòe®•Á+¼Hƒsà(°TÏÊýƒ¿æÌ;ø“y72¯ä؃?9v#Çî=Î??ÁÑTŒnšŸa߸\ ”•M óäO!Ž¢Œ!Ç)Ê$ѯ+q„&ÔO_À›¯õ¡¢v…@AGJp˜2Å[1†Ø|Ôð8Ã;$s€V²~€5ìÄPW@ÙU’Îex岊¯šRª2Óð%€£Ã< ™BhFW¸‚·’—î¬ÔUíJ`:ZHšÂX’C¢Ã|êÊÍ3BÜ܉ÒR\–÷,¥9 `T¡ˆsQdÆM^ 6ñ[C%–]ƒ—™E¤‰ð³+F_ó¤;Çl?]Ì“…¡š¿XÒpx¸¯Š5Kikæá(1çNS8³o çEBd Ê>ÊµÑØ‘sdcÍ,¬MÔ®F¯ÑÓ˜~5|} ‰âÞøãã‰çið­žiVޝ²X_L|V/9óÉÜÆæÌÖ‰‡ÊØ7µçÜFâÍŒÙ}Pfÿ±ñí)yØ)¾ûìä[vm\y shÎmbÅ;,ÎWB Ò¯ç 7—°aŒžf‡È`’œ¦W‘ë¤,Yõ¹Ä˜ŒcÞe°5øº Q|ý+´—6VZ!ŸÍ’´¸™`^VC‡AÎ>óâçþ•V¿S\!ùI<⇌GC7TŽ3ˆ»¯aMŠ»Ê<Ȥ¦­DfÜ.9ötÆi\ˆ°t³cp43ŠcǸ5®AsÅ4Iƒ]+¦žÃôjODò‹òĬó¦DÀN¸j½UOå{}òT(o¢Œƒ «` ‡ÍZf¨cÑ¥¶OÐ/©•!u¨r§_¥iÒW„TÒºÔó0­…ðÚJ#…ümPm¾hZ¨vf°ƒÍ«Y¬£kðñ'õÚ$‹g|œ£ä¯9¶Y;Ö²{6i#ýuñr^ÍÁeùC_ø»Æ~ËÌÙNcˇv—Ì™"mÚ}i¢ææ“"­åѵƒ©t‰æ]A#-éÇä~Qˆ;&“5}a+Ö.À1BÓÿÑ®©OѬ‚û(Böaº…çã¿”‡žih”ë¬Ùí–"îýÇ‚#Øb<‹˜ ¹úº!LU: [)­”å6¿Œ´ §Æ=N‹Ì«m´oKå‘96Fón0‚V犢êm´%0³; "®Óôž¾Ó 3v”â+ ÞÌT.‘ì˜vû×êzKSÆü˜me{fZlO¿É6D8]ßZխ늴\ «¦$æt÷µ32ÊÑB ËYzDW¤+ûì©n»j¢,¤N0 ÈHø¦Ê"äm©ÝØîÀ›-ÍÏ‚=ŠxœX+óƨë†ï ?†#º`ü¼¼‘ứø¾V`<­•gÞ׿ÐRäÊÓRŠ|¯·³’fB‡ÿðï*cê]j¼Ââ%þÉÜƾ®mí®2¶Z@ι-5ÞÄÌ·µšôLÿ§Æ¾q'À_í>%ú‰#Cŧ|Yöé©¶ @ ~$óùÒÙ~øû8ÓõïgÄ}|ôFýþ$ƒDJT»Ä³ái˜wïy-zJXJm¹ÆÈßmÑ2øŠCÈÈ!ŸðÿZD•WWÁןÆ-ÑUéç¾-º œº €·-öäÚ¡Ÿçµ5sPŠú‡HLp±,¢|5ÏHÀµ¯ ªÅ—!ˆ’’ý»Uµ“EbVUño dÕNµ¯P~‹¤rÒ .GØ+Š®í©ËÝ÷ Š@t‘¶Jú¬%9…c£çïGnxÅÈOý» Þö1¨X|ÒHð*L3+ð!\Ú²Ì h‹À5üЭ ÔX „ ®)·„S½©ô#ä;9…T‹.mú¦1æyjš5ú)s‰ j÷C=%@ˆyÖË—`Tâ¸Æ† ZoXìºzÓHŇ l«…»lžh«¥Í!ÓÝô Ï…Ðzª7Î*r‚¥Ìz3©9Ë!CQÍ̺QÔ öÆ>aFGO4¤Šã̳BìÕâ¾KJRÌ…<l€/µ׺>9Ûöó®ãò3GàbÑ ‡Ÿ¬—~õMèk¦ 9+F_†@÷—{ÿŠÿþw§7sendstream endobj 203 0 obj 4217 endobj 207 0 obj <> stream xœÝ[Ys$Åö³‚1o;ãдêì#&Á²,` B„Ã<¤ÝXiF«c~½ó¨¬£ÑH?8´ÓÝÕud~•ÇWÙogªÒ3…ÿ…O¯öŽšÙÅížš]ì½ÝÓôpþ9½šCmàNÕ©NÏŽÏ÷øM=k̬±®Rfv|µ÷óÜ.üÜ,ü¯Ç_ÃVço£*çà¥ã4ü|±tó¯ºêºÖuóÏfþýbiæÇxÿùb)ŽKku¥T3÷ÐwOŒnááüpáèµËž3™^û_³U×6x×Ì¿[P×p§«áÝçxï›Ã‹õüË…Ö~ZèÐzš\iWcCkM¥´…æ{·íüŸéùO x¨¼Ñ4ñp3ŽHÃÀü<¼×4†¥RÊq©;[™ÙÒªªÑ]ǹWæXî=¯M«v~·°ó×ÐçnÍÏ`Z!©œ>ÀJæ§ð/®±Á6°ôÒ+¼>Îîø¥®­Ó}ì¨U¸,Tw¾ÂvŠdw2rULÌî]Ëô\ÁÒQmM“‚qš.°^µv~‹ãרpþË\ÚÄÆùÔñj7¿€K”û…58}§â’²—Î(l«ÚÊ4`îÕïþ¾U‘ A­­!yŸãe‡…þdþ¯"À¢´²§8½ßb‹Ë¶’ÞY¤yGédCÖpÏÁÿËØ[ê çGÁÅ,e5KÀª¯qÇá¢dØzCŠE£”DÔ¸n×dºíd…v®nJ¼€âo`ò^¶5L4ç¦}+¸Yg’4ÞŸŽlSØÎ-Zâ§h puœ™÷¤bz°9^áv¦`²N—ÐØ¡þZÚ8#j‹¸—²—n !vì^AHœtþiùPƒå؇ÞÚ™v 0ηö¸Ž7qEÐÒkÄœmà§îæï“ù@uy[åÓàW¢û¸Þd²NøŸÀ$ '0ù®åõîcFh¶A5ûˆ±ˆ-‡hö¼½2\‰£qqîÆ’Àp®”¸‘]Mvè~‚~·ðÔœçƒ]܃O©aذÍ2t«àòop Oȹ|õñ2:ô¹›@Kn4™0†¥÷Ùüݳ9 ¸Ø”¦-ì&~†/Ÿ²ÝÑ:·;²üÿ#îD|#Ætxv»dÜóMî;Ñ¥Ó¨S7 4KÜ6ëÿja:í[‹û£Éñ|úA«dZ˜°˜Òì%J$é¡1w6Z»[vݨªU2ä¤`kyG£Èè-¶áÔ õ̦ÅF¬­ñš Ÿé‚ûéìÀøSãÂ+ˆ™ ¦'øc×qM[ÕàaÚщ[ƒDÿâ>?ÃËCü¾kI§‰ŽziÉߢ­oðçŒË$S•é6´Y§›ûc7oâÍMºù>³i-j°•Þ¾K Ϥ-Åóë_Æ›+ê§qš”Ã÷öSû¬siø1Þ»Î&ŽÎç·xó4ö³‰÷.Çd‘<ÅMð*›8zSµÉÌÓb¹ûØa&æ×ÅZ¥é~lš íCÞï|ÞÓIúy•z:‹=í£ßuÿ|Zn;ãMÁuiŸo#®Nä/’ GO1æ°Ôƒ·Ü*ÝÛ¸; ùÛøg ×Q¬Õˆë!‚øåv]¯#š'`/º¾ëç2€H;Éë¼PvÜ Ò0ß ±áív4§Î?Æ~®ÇöÙšó­nâ€ùb¶¡ù<ßG™ÑÁ`!y~Ÿ~®ÍÃÍ1Dó‡Ñ¦ëÔô$6-òƒ¼W } \Ù¶"–³ŽŒ+¯Ö³/}·°ciš†Æ8l9ERУ!\u˾ w~§SÜŠmpk(Nfc½NS ¼>b7Ñõ}Ån2ÇÔ¯ˆµeZãà Ž#-E-ݺ Brµ‚¼¦ìÖtMè`£ËXÅÑvnS°ñA›+šØÎ5Œq A¹ÕUiñß²ÄMðŒ )7æ ¦ó|ÆYGÃA J®CŒ™|‹Î)?af!E§ù)›G"Kcò4{3f—›"hOñ7ã’%[÷ÌúXìYDjûi7ˆ±ñ¥sƾå9ÃZ^qºT„hkz\ÄPܼ釵oÖ¤á§6!êtò£;kz ÒPZ0ˆÍ\@a¾-œ1‡s8hBVA[òœãyÌF‹a%Hæà¼K¶3ËžÎX]gŠ\]¢î¤ÑMHe:NqÆÃñ"¶6dÑž HÂpœviÿr‰Â*HIZبóÃh ⫸è‰Òn9¥hCfv ó L6§blxç‰vJ<ØÊS‡½·2ä^L ¨í¨ëm'ZaÇ–õ:xÔÓ`ÛÅIÆä[T’´‹XÓQþ˜`° RÕ“©šð?…É’|ÅŒ£$¸ª#°Må}й‚O&H¨*fü¸Â@”TÐÒo|³#ÎÀ´ 4f¼&M–y'ñ1½T‡®ÕÐZ˜ÀçlñµI ‘%¤ìŸ‘u8\ Úoñþñ¾d]Ë´~=°!-Zq•(¸[êƒrè×Lw LAØ1.ãõg -˜(AÚNƓ즀™°f"±­ÑÕ›ÒÑN䳩Ë= Ÿ]+‰yI@›º¼ŸåêM–Ø=žX¶Žæü›lÙ+öÙd—؈Ç% !4EK¶%®Ò:Ò?B,;·M‰ÖøÇ˲„‚Cq ¿µ otd¤rÞ6^.зɥù`Qxˆç fhšf6u[AŽÓÔiü$Á=c ÂÙ4fg²¹Âè¤!Ìma˜ ’´’<Ä0›šÇæè¥FyeÁ›4”ªµA8«©DãF’zȸ!åk¼#“0 Y̤£K™6g¹Ê¬!Žƒ5*L`ÔÇ`–ŸÄx™d0`A¶ÍÖ5S$³õ]à'ÉR ¬ÑìÝ€hF#†V®·ÑlA ØÕcÈfkÇë9ºz áœæ-!'òucrî5rlmlš…€ò°>Ôxýõüi”2®‘&ÒóLsåÄqã{@ÃFl }Œ—ÚN’â¤E>NÊx=e°³]vM°Î¶G,'q˜tï¿G'F{A—ßMÑn}:ysoÄ)'žj+g;A}MÒÀHÀMt)ôTN}塸€W› ¥Sæ( ã—dÀ‚±ZÆ1düöó¸An~iX°·C:ùlHÀe\Ø»ØaÆüÞ—¦«±¦wOó) Õ*ÚB·£¼ÚIêkœÂË^À!4®Û ²É€ù8fX šE²¡Í(Z'ÈÛQ 0',j[åÎxÿúG,¦%–¬ë*úi–?dóóqÌëîÌðj€ÅÂÌáþi>8Cë*ðâ†è\k[ä—à2žz<„|VBö¹òZƒ?´à‘5„!µ›£)D1USkðO ˆ8Z§¤ÌÐ_w¾½JG7ÄzÕrLÛTÚÐŽQ•`VrÛ¢ÇošÊØf~„ã;GÑ>ö­ãuZ§k& ”3ìÈp¢­aíñã4½[È][?ÆjƒS¶ ùÙñ·{Çýy®wb³©ðê^27Ã%˜@~$†1éY¥à‹Rí#²Nγ…Kâ÷Sôøàæ³ ?& §cy\ÝPŒh¸DÄÒ#rØíT"°ËápR`:aÔƒXÛ¦kØ“eûó{üs·"VQ ÚNžüt!äÎWŦt º£­dTf-Ë]4¼y?fúHYtwôHÄùªµe—‹yˆ”#Ñ? DÊÓJ4GÙÅ¡ 1¨–8iº÷9‡÷‚*Uë9°ÓèÑò0Äl1³:×ynÄÑâ ~ÖLˆƒëpAõ –'Ê;ŸÌl­ñ1(·•ŒX]Ô'~ëf5qL9ô*g.Q5„O£BºÝKùt 6fy`‘ï¸ò±µÓ¹ÚÈyö¹&)7©ë’HŒÚNt” lÓDÒ)sŒíó4×¾*¨€÷…RŠJÏBŠÕtÑRv>¤™ S–#dG­‘œÏm­]Ú–,/c ž±Ë“ k`̤v"ÿFz@RËŒÒÌùÏœ*Ó1!ÒPyKŒ-:4¼í°dÍLLW̯¤:IXŽ„õ"6y&7K¢ kW9 X<—´£-9{ª.Öl+&¨Ÿàb¶¬±£¦†óË`–†v(d•ϸ^8©6nåÁÉÚ#ˆÕnÈ,&¿zçÁ|Ý÷Î`ÂÚ÷«žV¨¯Mˆ7»Êeñf]Ò^YøH;X Qâ¼Kø$ ]ˆ-gK5ó[oFLÓÇxb^êÞAoñÄCèPDÜ?4–èê’Kå»!4eðRNì˜RN;à:„Oñ|nâ˜Uô<´;­Šç¯Ùê8Íoœâ¿œ’:¸›‡|ÌJ›ó(\ÏÐüôSšI»ñ4†’òšo¢:þ—?㟯å³A?âŸ_cÂä^Ö3d`ÞŒ±ró>ƒÂHìj¤àµèRh’Tžún,oºáwŠB¼ÄFf4ÊyZ0”TâéÉüýI\„gü;莲S ï¹ñ‹ÿCݭƦ–ŠŒ_gú!{/Ǥ¾?ÒÏf¬ŸYmñP¹TìèJ’L¿ºWÜù‡É²^¦g¿)ûÞî”过&Ù7YãÅCù7I¯ü­ØãY¡è,kÑGÅìM(.5™dŒÈiµŠÑ£ÎÚ&$ý=,h”-bg (ô‘„ÉŸÄ`‰Üø]¬IyýSX®Ùгöb£±„+ÈpXØ噾Ñèš,÷¿K«‡™}AÕ`³çÇ{?ì½Yƶš-]~Hû¦jñ_ŠjñKÔ×{/ÿ1»»¹?Û;ø×Lï|…¿ÿþyùÅì/{Ï_Î~xäWªZw•¡a*ëøKÕpÔ?qû;íFÒ´æ^o9° <ñ]WÕazõ?XUçw]’Âù·²Y‡é©¼R> ªÇ/PYþ@QEª(y tj.ŸwµƒŠ¿ÉÚ=þt.¾é;T=á°Ž{š0Ïï.r¡5d›¥ ‡³!yÞ„|᡾x§ûJçæ‚Q[þŒCãyDÿ0»WPw§µŒQ®Žìx¨»¦°61£• ÷¤‘E[ƒ%™7Á ˜â›c¿==â-qÀ¥6mŠ^Cåˆ'¿c1òÁM=´ú:»¹Ð† §°ÌkÔC^ÃRiyÓ¯Öª¥cl}ž¯dµ1üe6 1P÷`±hZŠä;}¸œ#Š×Vâi ñ’ÛâŠ^¬ uU½`â¹K›±ˆ°Œ½•Æ"5ZòZ9¯‰u±Xê Ñt±Ö¥$rš-ŸŠJZ$žrôDHœåÏXe”*CúDÿ‡½ÿà—ï‰endstream endobj 208 0 obj 4258 endobj 212 0 obj <> stream xœí[[s· ~Wó#ô–³Ÿ ¯»ËΤ3Nœ8NÓ6µ•v2I¦µ%KÖX:r"ËŽÿ} €Á]ž£#Û}èx¼Òîry|@è×CÕëCÿÒÏã˃χg×êðìà×/ÓãËÃ/Žb«ã“>¨ NèK}8šÃѺ^™Ã£ËƒŸV¾ó«¾3+‡?×ãú0 «{¥Æau¿ juÔM6>÷&Þ®­W«GÝÚ¬>‹ßü=Þ;¿zÜY݇`5 QMÒV<ì@"§u#*ÎËz\ëËÎ|å¥Wo»8€RƒBò°d«µ.n­ö«7Ger±¿ºˆÊ×2 ¸ õ·ÈÆN¢þœÇ·¯»´Ð¥ù¬úº|Ïð‚C_¥G¨sôº…–Ü ô`ìá>¬^¦–ai…±?;‘EÀªQî •@ýn “$žiŒªàp—e«.;ºUñ#–1tµé Ì#~’v~Z)‹¿zmrÖŠîâZðÚfƒË ¹–ªÃ¢Ç0ÎV_TýA­ê¨à?¾'Œ¼-›rÅm~+Oäî»Á¡é -½nÙÇûƒC”ƒë£”M­6<õîýè´ùõ^k"^¬µ6c?¸(Õ;{ q¦·*n2ú!åL˜pn“éÝ ¨Þ˜IÙ)ò†Ü)°‡É÷> ªcÿÎiØØüÚ:=¸Ü©FM‰L† ‡^?ÇAÇ1¯a kô`}K£(5®î»ƒ£?þD$…1ÄÛ@okQ{@­áÿUgÍx4SÓaÂÍa¨¹)¯¥b£ZÂøåöð Ìv~Yc­'mƯ*¬ò¡‰Sñ,aÊ; sŒ¥9 >Ï ?hªØXÒ c)\ Ýz ò5A÷£ÑÙ!DôJ¼‘ÑËG¼ÉÔïûˆâëÑ e‚UƒÈ=àÚ´Æp>.š&¢MÜò¨ÀÚ’`ð'üeí™"ÃõÑ…©¨F÷I&à“ÆÑˆQ3ª¦QH¢ H„ºƒõ¯³ÖÚö\#ÊAnŽä‘/Tüa ÿ bºx-âÐøMv~(}ô–çI"´;t‘¬š¤°qN7õY֌۸ ¶®tFh•“ð„ô©z :ªAwîVF9ÒXmp§ËÄQe*¸sRy’a.éIž¶Ò{00Ô¼IGoFÈ@É xÍ€CÁ„•Z*¹ u]¢“ÔQ 9'½á-ÇÞ>z™ŸƒtôŽ¿¦×µî,i$´ê©']°ŒŽ!àmé^ü¡ œýHºÍ; è ©)I ´ÔÙÌèÐѱã"*‰ÛbÕÇHþ-í,yQ~wTw ÉÒNmº K àkᣲO3Ã7-èiÆ|¼<í“Gtüu·'«¬u¸´JÇžÁÈä2 ´g£d'*´zS1‹šX1¡ ¤Ñ{ªuÁT._ÊA0-Ü,/Pãkr£0mòïÙáåUá`Õ§ÞKÀŸÎZLTØ/ÈS·C‰íÚ«Q³ó~84Œ<¸4š³ÎÏÅ€²rO¸ÂŽÉMD¹OÛ™àÚDÆ7gü>_hÌÇô|—GuÐÃЇ=g­ÔÁU‹é½â §|}*:íÊŠo…#ØOä_¢ŸÍî†åYåñó€›Ö ™½Çý¼iÅ7"¾Yx] ­ ëà%ÅØ¶²ÔÌ~uvšQçATlÜ ¢¬ ½K3“³—É?U–D0ª9˜Î~ÖŽi§©éÉKÿ',}æyo·ôäzïbé@>h·µÈ¨ôHFýÀ,tShßIÊ ¼‹†5ÒŠÍäšsR¦^¹‡y˯k>*x惓¤”;åÅI1Jâ¢*Fe‰‹rÞ¦f9ÍÅñGÆô³àsX²>*]åãd*u€kGf/©ÞçИHëŒ+æX‹úÖrà†ðŽ-7¤QbŽÅœÖ¾½¢ÁÎ&¤ÊBrp”nßr”H¼EwøEÒ8¥ž5®PE §Ç­sìh £ñ´ß¢(§*â)Üe7H'$ʈ–ïðcáâ¥}…1oj­Ç[>¿Þ4^ŸðkT²´Ü:Þy•…ó{öfÄ_-Å¡‹Åœ+g¢Ãü$>‹€Ã—˜²;dçQëÞx¶Ô¢ÈI1ä$Öø*;¶ä»üYüq•5rJ!MÈ'¦Ôé«â¢aç];œFŽÚ Y€¦(F¸ëdjb¦>²…™[çäfN-Íòß-a'3Ú71aKùj§“C¯£Ê@¨»NiDg9³4?ÖÍðµ$¬³ÜŒ‰J¦Ñ@—Õ$¸dŠer0±%ÛÏúz–©8„«”×ð=›¢Hî@fûIÙFqð;³’)ÊìÙ–Ôyâ6ƒÙ‘@‡˜ˆù“/y¿cL„ôÝ6б/Çnr«¿Ëø…Ûd.‘nô^²„ïÛÉ’8’B›aOú£†3ࣇi†{‹LJ:´Íç·mvdRÒ¹,$.KçSoàð?n–6“ Ʊòa$°?g¢Ççù \hÌ‹²¿"ïcïq”VºgÈ­êt#êt÷tO2ì<™3@é¡‘ýItƒiXe«¹kl’ÆmÕIÒq\žC õ<2Ãiå—i˜"ø¥â?¡æôG¾‹,ÄLÿι3•Ü ®sÈ€Uçzr*°œIˤ•ð$ËŒ 4èÅqu'Þ.R40>Tû¥Mn·%E“{ý¸)Ÿ’ß3Eó´pãOÌè1á9³Þ§HÑ@,_QÎmÑ8GMsaÞ~…'{Òô–Zq•©°ªè «s*ß5E8fK¥H’C®¶+Çz—ÝÊAQ9švhi©¶¯Q¸*"3C!¶P’è3,„HUoFºbQc•‚”œñ<•œê(¤ öÍXx–ßN+­}æ é²äê£,Òɱ+Ÿ»Ñ¥ši¡ZI„Y««0Ïx>YI1Ý k ‘ž°f'©£³FÆ®œÇ 7×ÖÔ¼‡\‚1 ŠuìZð5Í ì€ÞToEÔ›©#ë\“þq€N'Á¹Zd=r*x–ø óG×t™²Vurs·™öL’‚ZŸ[œ±¬£•Õ. ²8©Ô/Ú¢¬ k»/ÈO)aaL¥^œ5[hÁ¤˜®Í†txLÕ…Ì9‚W hNÍâŠ*Ó,N”}g:ØuŠJ}  ækgnœI’vªNïU¹òùIðòD…d,€õ*úyÏŠµÜÆóBícÌï™íÜk{ùà÷“ey¹ÌǬӲjÏÅ<‰ás ¥µ'9`Ä1_eh{ •®ï  &—Âò™›ŒAíú93K¨ep SuèÜçäý ý—˜ð#¢(sWŸ„ȦY\ÌÍøák?5coàX¢ø¥AÖ¶XÖŸ$Ú©ý2»ùu¯²ÚïJ#ਨ53VµýÔ<Ì€ì0Ûn5¯—ÞþWÌ!âô°øûšlò{I»•š-øô !ÊùŽtòT¹#‰°È8œ™ê`N;Ì{”Ý/ ,º]Ö,ó ”ì·).KTÌ“¨ž¢|)ÿí_.7f—Hpî?n~utðøï¿hú±¤endstream endobj 213 0 obj 3840 endobj 217 0 obj <> stream xœåX[oE~·ø~ce·;÷Y!!5­Ó P 1<ÐV"µ7’/iâ´ôßsΙëvÇTÞP¤=sîsæ|ßúÝ´kÙ´Ã?ÿ±<87Óõݤ›®'ï&Œ6§þßb;=ƒã°Òö]Ϧó«‰ÓdSçFȶãÓùvò²µªd­^ÏŸƒ†`¹ç]+%(Í— ø¨ndõ´fmß[ÙWk^ý\7¼šãú¬nÂÆyÝÁÚ®3•Û-ìpfa³:­%©]Ô†}ΫgIíª‰¶·Wyõ¢&Ó°ÒkÐáÚ9Šƒ¢®ÎjÆ|`P(Š ¾1©QPÞvL€¸@ëÂV?¥ý_kØìg¸_ŒÉ ħ@Ïîª"m^•†™®åvÚˆ®5¬ï]uÀ‚¨>à£ÅÇ"UZAng‡>V˜xeÕ:|­ná® %¥ñ`~˜Ì¿y‰Q±I;‹hó2ÚÜ@謇*êêÚûåX`ø~ˆB«´¸.-Þ†EŒ ùýh OcYÆ ó:nl“ŸAز·`Pf’ÿMìgÃØ—)ö³˜‹}•ÇŠx…;›d~….KÑ]§Å]~Δ\g«›¸¸O’ŸÏ8ä1;šÇ,¦€æ³wñ bûÂ,žÁU¾ø…©«®ÿ’´ÿ?Ó~r4í'ÃìR×Þ† ˆÑ‹ê[Ã}Ü¿KîVù"HQögqñC’l—ðÇzJáÊ/‚ú]©$ëR²õñâ¢Tð]¾¥!{_d¶¿T•îqïJ2ÚO!Òâ VáŠçce3ÐÂ`e•j2KÃòÙe\u 2ç†Ã&”«oR²}I“GëL —Ų[ 5ÌÆÝkJÚÊxDz%’îWjÛ»ƒ nS|eÆ C¦fk};wBzîðèQœ¤¿á×—ø¸ÀÇ)>ˆ?ÇÇ÷ø˜EáÇA·ú¯SÅ^UQ辄×u‹OÒb‘}3I1“a@F÷µÁ.êD¸îC;‰Ü’#YƲI’ZL0›ÁÇêóSŠ«hg“­EÁmA0)g€vždp=Ë[Zö>AÕ&÷̼§±(—ZÒôúnu ïtk-Í#¥zëܽ/¡ü¦tè²2.÷eéT?–(ÆIÉС`è·GAçUÓµç\ßᚘÁmQµ(>ƒû‡¯{þžÔ‚ ¸—ªÓ'©,M\à û&ÌpÜÓ=ÍOé}ŽÛ¼:Râ*ÿb0K¥FH@f˜ÊîÆ}eCÎI¢ÊvpŒ”AšòR«ñx•ÒG)“ìŽHí˜FdI$LØFF0QåÛÑ Þ÷C™ÅerÀG¡42aT¶„l0†Á«4Øù&SÉýѱ@#üÆMÀ÷ã9MWGpÓrÉÜÝÑ˾Q¶þå';èÊï7ÂvT\‹àGç³v?Î(gÏPS¹vƒÄ?ÀÀÃø3Á 3‰-!RŸ,È’£ ºw?°@ß×]c"y•ÝCåµÑ]ƒóºéÐã®yòrE@üq—QN ¿ÆP]‡VâœòmBéÓ8…±ô U6UöŽ$ SÖ½€©ø:™‘pÔþšÝ‘¥e¹¡<ÃB$vè/k›"¨ œLG"£ÑRkfl> stream xœíZIs·¾3úïæ7‰Þû9¤Ê‰å²â””X/'Ù.¥²Hj£dù×§4–™y$­äâ*•ª¨y Ñèþzż٨QoþËÿŸ^ýù‡isþîHmÎÞiz¹Éÿ^lþ¶‡ qcÔ‚ ›ýó#^¨7“ÙcÆ´Ù_=Ýþ}ØéQãöŰ3£1ÚÚíñ F}Vo_çád¶ï=:“BÚ>ƒ§dU˜¶o‡¦Ñ€´¬Úü´ÿoïÆ)N·÷~t6ÅÍþŸGû?>Ý~ ¦è&»=ƒ½\ÔÚ¥í‡!ÀsÐ@¶|‚ý/é½ >lOa‘õÖØ¢˜”M ´3Û‡ð8ê`Æå`ÒèÍ”ˆk“í½Åç¤CJÛçø8™“+ûFÝof'˜³Û'•™kæ;8½=©£ Ý+ÕSÐ)Ï¥ ÌM²/Q°!jåò hJ˜Ô6ší;œa“u–ª hxL*±DÓ¨ƒ2"Ñý°s¨Ã„i),•šà v•îéíñàQ§ÞiŒ#=zf ß÷ê”Kc¢Dáìñ ¦1Å@T^ð4‹°‡i6ò¾oqoþ’–z>Á5øƒd¬pVŠe¯N˜ c?"õ<û!sšˆÍøÃ=eܺ üñü9“ß÷ƒ)ëÖûå Z£›ÙŸ¡<Á…ÍœÇ@Ã: ˜£†s§CÖcfÅ #Þ'²!LCž\à³=Ge'Y$Éœ–·uÞóþ0ÀwÒH}"™àn¤Úuøâ B)àuîþ4™,p™·ÆÑe‘{Ë'D"0·÷²ó]–ÓNÛÑ{´pW ñDàGËQ,§ô’_WÀÑÄNá XçwÞ’&Ïš1¤ì˜NzE?g:ϸÈÄÜ”HU ˜8Ï0y]8B@´´àù˜ü!S«t34ø«DîÆ UB\Š£À‰•5ÀºBqEâ´ðômj´„ËÖ4zVOùbE¹È¬ñÚôx‹ÎÓš¯q9øždªXÏa«ìä08Ð ¶ü|¬†êŠ&%p†q6`øÐ¡ =äÍðì¤ÂO(å‹Á*–(*‘qtE’ÙY=ÑOqwà‘SÑGѵÒ)8:‘¼pôQuÅ?‘^YÛxÉr"xÀ¡h[î,=ÁÒÍh_KPÈîkgoþZ€"äÑfõ-°#ûã‘ ú€€®#Ï)Fƒ†¯á­¶ ¦PêVA)P[ºÕžUíÉX^Üd~E·Ç½§¹Ùµ4ëʦâ¯I±YØ‚5kŒ£ÔÁ÷ª«Þ ÉVZb²—e*!0 !È)ŠÈå<© …Ïn¹±pÕÿà»Ð›ƒdÑ`JìÎsÒÞ-MÁûj ¡ØBÐ%ì½c®´×yS4–ƒKÕõµ ðUÌŸðdÔÒ£ó=|±ÁFEçH(ÍCèJ¥ 3QäØ)¼jùP¬´èšÐw1¶üDþKŽZáü¢B''%.’Ó«PæÀÕúÛWœ ¢\ä\¤¶²¦8:çfžî˜áHþÙZ¶³ƒ9£Ù¶8¶–“ чµÅß”¢¿î|²où .ÈáD]€g5Éø<çy˾”ä oˆ$ËêXBÇT“ëESaçØU÷k™‡‚7›p3`uèod‰ )¥ xHà &Ú;!‡V˜d€4ÞON£›Ñk AXÃ6ÚLcpží0ã…²sFõSTØ¡Pi@žö„l²{ßN~IÄT" !ÙÈ~/"º,&jŒFO‰%²Z̈uÁ„¨FÌÒ¡vPŽ O*.•â8¹ ?( ¡V >o¥(Hã©|$·dŒÖW r-´®ëãI}|Ë”žZÍL´àIÛ|R<_Ã_=H»ÿ_d*ëÆ¸¶ 2q´:%©‚ô°Z+aC›Ë€xŒþ¶dNlG ºl‚U|û‹d{Ù¦«϶y^ëŒoáíCœFý‰8K¦\ Ë“1›.0¦Û9:?~)dÐGçÄW ?ÑÏåBÚ§1ÛnKª…ªc<Íö‘i1›æq, D "ÏZ{>cÃæÒJ‚}Éø¶ßÇù=è:*¥dð_(»G9ž)ßRqѽ'¾ìòÜZ5FãȪ»ÏòÃLvÍ ;Î\ógïi‹;âÀ,þgQQÒÞ[(Lääž8õ³ªãž“óUP„6EC^ß’„> DK8%ü6nµõ¨YúöZëd¸p ÑÓ,¥›ÓdIåàÂUQ VºØBLa%T|Sföú%3›¦†ÄE±ªpPkÙä¥$EK8«%À\xþ¾@®yè"§”'$E—“-ô*db`=컊¨@:½«XžwP(zSn‰Â<Ö¥%Ê–±eA )y«R.óX%ôS–™\êá¨×bøœ/Bdv¼‡-%tß Â@u'ÿa„Y ä’ýÄ £ +"¤#Õ× nÏ¥‚tÕ­œwED±ïy6ÊR4+…*)ÎÖ*âúrI[E8în… PVjNðAñŠBÊMÎç” ŠFßÁb …–¸:–.úÙ(ù_6¥ÒÊÀõ‰Ô¿R8DM/$ƒ;ˆÊ¤é$kÞdQƒD§M#,…þô¦) ¦ÇÖŒf*Yb9Œ^]×S®–°¿‹„1ÚÍäqI×ÒÉg1«á¨í‚â|Öyæ¨×yIB$0瞘¶­!(§Õf2mXrècÌÔ$¹,0“½Ñn¸îK»+Sëåž™ôš½De£äyË—0f8á*g7êÙ‘¢ð Cë´dì¾Pµ@‘bÆÜQ9‹Vçëµbðô@Y²£Íl3—³ 2+¿_}v6e éÅ¡Ä4ç‚°ƒZBmäL}´‘Ñq…YÃ?嘊axÒ‡\a\_ÛÙ¾©@¨¹Ù0®sX8®: fíæR¯)ïè(rñàbWD¨ç@ŸÁÓ’¤°C«§bË¢‘ç}àO4ôí[ü{°TÀ‹Kœ“vyöóòKpÂhfç²Ì9®ƒe°™Y©½­ƒËàÅ@*µdì¬=6´"®”yE:æÉ¯Zó—ÁÓ:øs|×ú-üõfž›5ï׎\¯×Öü8È(*®´æ¸Ê«Júÿ|_Ý¢)žÌöšj3SžsÙ:œ*ú•™÷ëàÛ2ø±(©ªøªN<+Jêè8ìß‹ø=« Òm”= ²Ç…À´õ»°«weòû5È4ƒwÃ;;ï¹ðö_„w«ðz‰=ü"±[%6oªí OˆèoûØh>³¹†yM®(MNïïÚX“ù‹Æ¤|]å*)àjÿ'ßÞP3‘ûr’ræšê·7ÔL¼­™fWör=âF_óP)¼M2ÔXY¦é“ïRMšÉ‰v$Y?®R|ÞRª>@56ײ+0±ùŒîJ)~DÜœÄÖ¯ìhÍ,]Í©±3|‚¢(¼‘Ï7„“¯ôsB‰“ñÅRQg\¿*,ÓP§8ïÌi¨°²üBÀ¬w¾VkUD¤Ààyš¦Û˜ ø?Ú¸çûš¯„é;ä¶0Qš²6ÔG5{ÞŸ†R¾ ôÊ«Á¼3¸Æ—ÍÇÏë{ežVZ¶¤§ð·ÿ þG–èËÈ,׳pª¾&Æ]WŠVB·èk mËÏyƒÁвŠ-­é‹°\ʇDNéõ‰œ²Ëî'x×< µž¯ µmæ;4f„s1ï4ßã®ÝsÁA¸…rû—Q̤Òì½ðÅJ··ôl\ër}Œ%–Ñíg¼/@h½I2ïå?îKrt’…8—Í\9»rEýEª°ÕûŒìÒ)bI{KÕšE=݇¸1-Áଆ)’»8íÒõ+ýõÜõ µóÑpY¿'ø£acªxî_)xt4ÄÀ¹h{æ r³Ñ7-—Ï©|}I™þ_)“½SÊôê(}|´0«ÅíC¼¹¾Ò/s!ôÚ³ž)N”€Õ»Vb§ãkû;|æ&ðÌ9“ÃoRr˜\»€h"îjfæ,w…fíÛÚ¹}P·|”$™Ö´î±ãrxyÜ$¤«=[y"šu‘% :wKyyX»„Íë±ÆŽf´ùÄdÖ¯Ã[ÐùW!Et$³ê_XzäÎ٧ݵçç²6«ÇCš´Øxš¯~:‚-»%]†Ü](žU Ï®ãgŸgt©Xΰ×?»sù^¦‹½¨M;Íe>ü˜Òg¡%¡ÄK,yiœBýSÒí"©©í擼­nn/_uœ÷÷DϺ‹©Õ+O1+â®á&/ËHûñšSø~m …˜Úø®ìþ ÿþ ÌiE­endstream endobj 223 0 obj 3282 endobj 227 0 obj <> stream xœÍ[IwÉöYæGô±Ëoº¨Ê­².~Ï0à‘™Mc<>h„H0†ùõŽ%32²©å±±uwUV._F|‘õvÓµý¦ÃéóôõÁýï†Í‹ŸºÍ‹ƒ·=ÝܤÓ×›GР7p¥»±ß=?à'ûÍ`6ƒumg6G¯þ¾µß†ÆÿãèOð„í«'ÂØv::ƒ†›Û~Õôí8F7nÿИí7ÍÎlðú£f—o|×ì¬éÚ®wØï¶…;ÆŒpÉm¾ll€¯ÖmÿÚô=\^Ý} ]?L½h»³.nñ;Þ9’;ßá ]gÂö1ôbá«…^¬§‡áWï6´ÖÀlìöûf°¹ÙþÐÀ•Λ~û ±0hqÚÔ,˜í×åéÒð¨\”™Ð$ W] ƒaÖBßõ®o£Ûìl×ý8²(/A.ï Ãưýˆ+‚ß~ûz}ߨí3˜õhH†øóv(°­)_ÜÒ­ª«×p;_óÐMžó >g©Ç3ô[¸/ ·oP8} ÝøÄŒÓÀ®úÔzø©¨;ÃAóu;F ¯¿)–>α­±§Y«®Ž¡XŽc(‚ðÛ{øÐEÃsTÐ8>Lx8-ÀmTB0 vÓÈð¦ô¨ôL@~ÄzÝÙh /ÇiEŒ™³´Žè–{C@@NØc‚ÎÓ "œ×.Ml³÷7!Δ€¼æñú.’â“­;’©çw‚³‚†[’ºÝ~(Ó¤õh¨%öœÀTIï‰bp¼Sx/¢¨ñÿ'‚v+#;®Ðpª/à$#áH:RÚÍËH->&Õq§(ì$2þ}$óW„Ó¶¼~@X¾$e›Ø·CÈÊÎrÔç… 8Â@M®ŠèÊ>)ú.×ÎÒ º@äÛ Ä hÙÜOÜ? ¨ÕRúÉÊä^ä^ýg£ìÍ.-àäÇÈ@©¿€ÿø)úFèA5-«C­1ÔD oÊu~¶˜+zÊSC BIm2ÝH:«Ñ—]~ÜdüÑöKŽ&"ö&ò6Ľ‰{(ëïQ¶¹° 3zšRïe™sÉe’ýHv¥ ÔÄîu/$AÏCk[qÆ §®ºEó‹Wz­¦$3Â(1.j²FMwhL^H«´üY\ÞU±x8VÚ¹ j¥§¬’±T3µÍLi±µqtd;žÕ^F«m’_t±¢¼" C¶Í¸}ŒÞëÿ ‰ ßÍúBÊpàkd¤ÑÂßküƒ…askô_‡fftÛßÃDMG­²Õó÷Q.^—‹¥åËrñ½\„®}7’(dÀbN.^WÀKÉ8ÓUqqp@¡bº0`…9¸Æ.ÑŒ €úJ(¥ÝC%ïh3tÕÎ7d·\ÑUfø™aßiÙ¹ÎÑî:ÆÃÞ\Tü»ç‘”_¹JþÆScÜ CPÛþ°l;åD¿Çîû™«wf7OœÀ ýÔ„| MÿŒ_TÏO…R&¦Š­p[û¾7Ì@œN¸C5Gm&k,î€×H,´l± co[ØM¾Ž½hÿº}®Œú1žêÝcÕG½ýïÝî;P©f²Ù•è8‡ÂO3@ÎËfW2Z33Á&´æOìžöèó 2­M?gž¦Ð êM¬ºWF5 Ì2M½B!v`Ú°=å sMŒÓ¯v[>KÞ"¸PEd<Ë`J. È–^y1¤Ÿ2yϰø¤Ü(H“dÓ+@áãѬ˜fñÐÚuÓ|˜-0¯ðPn,d±Å©õs¹d€ ¬íqÑKñÕÊX—~NÊÅ ¹x)ßNrîƒÛ¾Z2½/ñvô°QYÆyv–mÝÔÔË~{rpô;-YŒtцiÉ>‘¯Ê¸vzv"ãÙêþMq§o"Y-myä•H¶ˆLùP-n侃#oê‚ÏNús9Um¿—S}(Qú³ÄiS¤nüH 9æ¯_T¾Ñ1Š räå0º™Ú'䶃½Ý7äÐ(Xœ©¾H>]5"—¦m½qcd3!i¿ÉþCÍ®ÏN¡¨! ¥g´¢xØãdûVÌà/{²âDg!cZc9ŠÐF'¯³æÿ˜ÖŸoaKl„¬{ ’" uU€¢vpAÈP»™Èß »a(F©ÿ´Nbë“"ÆÄ›1R¼¯t¶ï¼ã@·ë—@—fr¯ ËPF޾=x»«¨xjˆÛ›âÆ °¾±óàðàþá_6ïß]?;¸ÿ·Mpÿ+üóà›‡ðqøåæ77ßÞ±Nƒéš0Œ0,›k5W9€!ä`±ë3uÞ|–™ºØú±šéÝùHÚ‘Óà¼PvmÈó¥Â'mLª*¬ÒCGäSƒ7§Zվ㔈¤¨òk/›’ƒ«¯V>+˜äñnY?N¬zÖhN©W…•´É€á2Ï÷í.ò•µ†¨8ä8µNÜY®´Í™ºìì/R á³3pXî™ƒÓØ :ÉãOlá,õ>†Å†ñÏ+MsAØr"l9n¤éŒrJ²Ý¯P„Ü"úiXúLÒN£ð\mJ½Ÿ&ÚqÙZ­ÌÉÄ®+<—c\_³GŸÔCþlÉzÆÝ"OYcôí‰øÉðç÷·3ŒÏî•}ѵWöO®N4Àµ Êl!|æY+ÆY\ÄÙœXÞB «XÒ\©X[Äd—ä›Ï•<ÅÎNÝ’_vJi/=¿˜N]BH>ã°Z»yX#éëÿ{$ÄLgyñW )ä½:ü(Ë©.>iò1°|È™LÊígVö¹˜•¹™IÕÀ ã (Ãx@®d@ø,¦³ê0ÝÞTiç©:aVRé9* œóÔ)7¹!þçóauBŒlÿ@µg†ûq §r*øœE³èp‹‡eöÛƒf4-äÎ*ìPÖÀÐÑÍJg{ì}PŢ˺Ò>Éú?[(*MJ:¼üÛWÊD¼8¤]L¬k2m+dª:8œÃVµ+×N`Å6¬ú ªD—ãWûæ4þ§ŒCˆÓ¸—ŸøcSN‘ءΗ)õ|h<ú(qÐõ¤EŽð­®vPJPSbÌ̬¼ð 6VÄnîC_3@wS2ܬcÉî•\5yÝÐ!{;íX§ÎÚª­ÖÂ\`®Õ©àYvpžC/,&Ó2cÙ8² m‹ –Œ(›±~bê×jvåÀ‘>0is’7î>ç½ÉŠ•cóÉ=x äÓ8 )è µ&Œ€qøi" Ûé8ì  Ä¨IþW ”ú‰ë˜£—/ïô3õÉñû{BKRAÓ¹*^j ¾cOzœC5öw€*Gþ¡íKñ ±GŠò.Á±¹„ßÊæ$vJɨäÏ$œC#1UboÌDqò‚½ñø?…÷<ÿÚî§ŒHÞR´™oÉ9¸D.=ôÕñ[3ÞÅU ùUM!JnûOÁÄT¨©ÐÑZ^åz-þ¿Êy#:Õ.µæLo;³'Çí$_ê¤\°0zWLiJ–Îëyä’’b¦á[1ëR²vÞò¬ ©X••M3ŠU”ÖkW‡ÿ¬«¶ëÊñŒVÞ&Iï”Âeš{çõ‰o9Àˬ «:ïA±1—ØÎ³Ç¡c˜rvuá݇T ¯J?\…²I¹¯R;NJ—â »0ÊÖÇÍØs¾Jg£¸­Þ¦u97)ÀnÆR/ÆU!Ê».äŸC—rIŽH¨ãËøÞÌ,’Í'©h«3št 7yqF9¦e©Z]ŸþÈåÊ› J.ÿßR¸,ﱑÃ?n@ˆiWÙæ餤h¸xѵÙÊÛ1ÆôÎÆ$ÿ’ 6§²$ºÀÈIàd¹&¼‡-‰Z²Uèí¦¼³bp‹–J|J>]KÇfä0@6aœ™S'€åfrlQUZä=!Gƒè½²hYÔQ¥ÎH¦²XEJÚSºÖ’k%£Q)È©Å!%û_eqHÈ{:LK˜»Ñ_b ErMrr|œ£›ål.»Døä´Çs:T[›´«·ûI›!y´Hý¢ö+X^ð“döe™Óä 0' o#ÃI3É}Ìœ¹pû Îs}¯7•`KÅŽpS… 1W©vß1Ârõµ\ÝZÊ›Òð@?Èar|®¼^P{Z×è×51¦xúµ Êv·ì(9Q&n"ÿHˆ9Mo¬¤”Ÿ¼—ªRñà‹0âFµcSR0E3y7:NäÉ›Ofn{ÜXÀ[Wkð)¹¬:¯as\÷³úrÁœ]³¼C Èlɪw%Uʪ²ÉŠ&ÙœHËI"ÂQÅYâJÖ*c!; Šh{?9޹ÁÔ¦o rÚ‘ñòjTö8uY;s—×ÚèØÕ·ÿ{Ù–Óendstream endobj 228 0 obj 4213 endobj 232 0 obj <> stream xœÅ[ioEþnEûü-3(~™>æhV¬„@VY`‰ÙCi}&ˆÄ69€ì¯ßº»{;Ér(Šýz¦êꪧÎ÷Çýnçö;ü'¿Oží½ÿõ¸ÿøÅ^·ÿxïÇ=G/÷å×ɳýa@pðd—ºäöÏ÷x¦Ûýþâ®óû‡Ïö5CÛ7»Ö7Ž~ŒSÚ¥ih¹ßøæ°=ˆÍÃö „a×uS~ñ =p»”¦˜šOñ5þš/qøWøþSüñ¼ñÓ®s}óQ‹úæ.¯…ƒ?ÁÁpÜ—²Ë@ky :yþû›Vwù¸Í×mð°Ú 3òK"ó>oI{ë \÷¾ù õßþøâ|É—Ø»nÖž;°al{§ràAtnçãþAèv£K‰'Üzq÷Ð|†?€„Û9‡ ~|Û´}7_ÿ}×|Ï/ñÇ+üqa³èÅK8’ãïèÔ±yaƒŠ÷Gk_ÙÃùá·­>åÃÁIªÃõ»)¤‰N§ÎñéÜv׆5¾9ãÙ½69Xxlž±Í\Ól5vxðМâ-âÃ#`íS¸üGG±èÆ¡9‘W/a,#:“'ÁçÈ›!‘ìÑý¾Ï·Ã@\y…Ë_àïa]`Bˆ‰ˆ¹h=Žè=yÖú„kºæ×ç½q? : €ˆþŒBôD×:iIL]ÂG¡ŸdˆŸxU¤ ¯dèa­¡¹ÂiÆ€Ÿ@i‘KEû¿È"‰ x3A òYìÓ´‹Ñ)_ F¹ Fé•ÂNx¡q@&‡ÔÏðò”9¢£ñŸ*1 !’ÞÈèÏlä}¦uð©™¼ÿVÛá¬ÉU>Í®Lמ㴔zç "t<++í<ÈÙ »¾É£3¯2ÎËPD.f¢TsˆE ¹zšab‚´€(‰°øßVXèÖýD[ÂÀBÃÈK¡¾ž»y·P VãÙaøl¢ç±Š4àDTäôØôZDkØùÉDëd¶9²ãÂnï1®ð\ë’’ÞWð6ªp•þz9ì)MyѼ5gGoúŒ§ì|ó¡­Çâ#Bñ‰­žënž-™_ƒp7íF¸1sü¾w~‡5Ȧg†¾Á:NˆQqþ÷ÃlÐAŸ1ÛÝ„Ù_£ž¡X¡®¼2ìºPCïèÅT6Øä0Òtk4‡ÑÅê8’Fm(\¬8oƒÎ>fM ŠTþYáH˜ƒ` @¤ xmZr*¨È•(Ö¾ÌVïWpàÀuÃú‘} ªÀY{òø;h²:ƒœ‘!,ŽV#§3ÎøîPéjÉ››BM@¯‡DÃp”µ tqŸ‘ÜÄðP©€Ý l»Ðxøè‚o…ö•¶) g¢ˆ)@é2Q,ÁÃûøFеͭ1.xnÊGoѤ¥@£e_¦´/·Ã7¿¨â^oäHeí±Z1|‚ !>DdáR^š=+Á€Ž ×]ê–0ß¿UÂfWuÆ^"ñq-lëÁì ¢Ï"uÊœCAí§«Ð~]«°øÕ$ BimêIŠk>®øqÃýûqÌË €90äBk Ô¦‰Yq"#‹»Ç…»‹ ÇÕpz1\®&k' òľ[,6¤è$EÅd,ze™G/5›¥g¶æU¹Ð±¦p)xþó–œ&¤ö?v²ÅÌmãpˆ~¿Ã@E$ä!Šhå»P⓲Á%ßf$yCН*4ùºXÁ›S%hºÖðë˜ë ¾=]#ÚqŸ¯ñØðñµ"˜€²FŸ£Œåoa´Þ]$ñªü¸j;"[՞•‚.4%!ÐÇj‹¼@±;Œ(FaN•ÛÈP2ÞnX±_ž7½Vši×o#ÛµNêÆԾŠ—z­ O :”"5l+ 1É’ qÍãne¡QÃJ¤¿›aí£à\óX„ m_[Z†ð^QFmØ Ê6ÅЩTØeDé.iÌòÔ@ bSJ¿žŒÜ–'N|$“šÛ "W•Œ=gàG CÛ{Úæ“:»RÄ×2ÍÖÈ#™¾3Lð Vg– qgŽ(¸¸ºÊm0G27Cp<É÷oΜ U*ÒÁùÂë§Z$ºDò©ž£ hášë‚ê$“±Oty"­x£ Ž^O4·ÕùO^³'Ïi  –{éºfOɯü(NRZ”íÖr%ã »JMN}o³¸No&:™Œ~¤n‰ ùÁé]Ù³7ÛBk8g½îG"\+ÉîXâ*»Î$AaÚM¦Ã[·Ûãöq=#Œ»Ò&ʯo53Þ… UpI¡•K0`m¢¼[˜ƒÇ¥Zd&³6Éɚ鳟e$J\)#±˜*ñîû›Ñ)ãR`<[àÒ–{È4â¢ÿ!Žy" Rü38ýv:ê¼Dwí;ø}™ëDw׋'–(+#5Ž)ÃÎ  "’¼\ÿ3¢c2$ÌBB-H‚ªÎÓ(½;¶tOlŒÆGÎlÌòÖ…ƒ9+MÈká¡r¤&¼Ã”˜?EÚ^ÜþX­/ø5ôdþ×)vì€Wò$aoè³2c©sOZŽ€B¾O.`!pü€+W$T|·Òº‡©EU„PQÙÒ~‘"Ó@¨†À2Dy-ÔL½ìÂA•¦T®$¡ÙÆ|ûÊàô(±K”SP¿Xê`Y~±ŒçZXˆÈÊ‘r™µa †—a%Ÿ«-åxqìs Hr!ÇÐ|«0ŠH Γ—ü¹øµ9(ˆ£Pq{ʼn¯½¾‘Mú{ê-€)¢÷ ñT¿,ò H¶…9§íqÉÿÔdª¹½(EÖ*ð•gM$.`÷k?&©Êù×®CÎQ(cùóóº´Zq†‹¦ài/¥‘÷1·NLR(À:ºœ¬šaŒ Æ˜UT/rNtÀG­tWü£µ6‹Ü¨1Ð.U…ÆxI/,HTq¤˜o’‘òœk2OBa]ò`â¦jR\Éìß•îì%¥z6 1ø9ÑdÖ ©Ïa*2Ÿ8mÀÒßä4Ó"ëÍlró3’ùó ¿p‘8èîâ Y­YžÊgUŸ,Ý9ÌýI$D¿’kòµ>×e@¸ é+”¨°JJ1Nµ*å*úh gÊ5¢c-¡¥…‘£ÒGå,Pác+ä`ª&Y¦Ï‹eäÒÒFgý3礿&¡b,ÍÍñ\2¨b”&³3Ä]·u±| ÓÑs½§ªO&¨ëçÞrë´ 9PmgÈá5]ÆëO“*ÿÂäÓ•¿”–].Û^ðÔb‘N-VwøMUhMUѬT—}Œ*uEú“ºÜŒSŠTäfÞbr9ƒþæ‘×Ô‘÷£©s+b­ˆ˜8âD«TvUn*Ç4ä(J7A¨™XSI›˜¸3¥`7ú±E•/{¼ê’ö±Nt²c «Ê"Eà [6|’,ŒÕ|gž—/+dI•Ùb}],ðéªF®Ú»™Ýx¾{Ž•¿ $ÀÎ>7Ù±ìÑÐ͵¬ ÉŸöŒ·]ŠØXçd$\æ]ŸÖ_1v sÓ(ئºÏP5}ÀØî «ØsÖPÅ çxªÊHz×Ì›ö:²R9uÙbdOVÍžöé›\b©²b~V¬]«œÍ>¢FGb}ƒD¢u‘®å>»x̬F=™³w À@£êr*Çàh–EÁP3ôœr;»¢û¸ð`˜Ù¹àŒ] Ídü _ª­Ëh„ÉJÍ•vå2'+n©³¢ ÌzÉ: Ø2,º¾#Äàü¡8@®.1ëôõ̰xpymI”ëú˜ÿ“æx‡Þa`*ŸîHò8`ËâõÙãâÒyÛM‘¢Bòô††æÏŒ»æ¥}¡.eªåì1ÓYw—š.Â"9ãE`¬­E\i;™©bñeGA”4;v@&Ú–ÀÜKÒ™ ¸û§ìrà}¶$C‡_Èë¬á\‡"0F¬¸¥¼1űh7ÛÐú^@œÁË¦ÚÆÜ}µÉ}7—kÊp¹†·gK¼ý¿©$PD›C1Ì¿¿–ä}­câo­èÈbÝ›`X•_MW®ÉQUøýAˈ€ÿñ¥}u£Ÿ5n¾ä¢“àÌ…¦tm‰ÈžñZRè¤*_-UâÓý¿Ã¿ÿƒn܉endstream endobj 233 0 obj 4072 endobj 237 0 obj <> stream xœÕ[YsÅ~Wøzc&…†éuzH%U€q ±E’ äAÖE– I×h;¿>géåôÜéšå!E!ßÛËéÓ§¿³vߟÇAŽø_ü÷ôòàÃgÓáË›ƒñðåÁOŠ:ã?§—‡ŸÃ¥¡e˜ÇYŸðLu8éÃÉØaԇǗßu¦w]èÝŽ¿€FU3ü<Œ&o`à§ý‘ížôj˜ç`çîã^wßôGº;ÆöÏú£Ôñ¬?2zFe;´èÑz†N˜’Æ<ê‡Ævÿè•‚ÖàDïS ýi¤ªa쑱¡û?cÏqîy†‹Ž£öÝc bà£*ÆÑdø¦¬ÇÆhàÆtÏû#Ãu÷m-£Óªû¤7°¨Ÿ‘mæu÷u™]—ÆÌ 1T˜&Í"´AŠönmÌ8LjžY”)¤h`øƒCÚªû2w|ßáß;üs…^áŸ[üóp&ßý Ö HÉ4®+dðÝEn¼-osãëÒøCnDòs€Ï¡»iM?i5–ÕoJã÷}jeÉ€¤d¬‚™ˆÎ=‹Fõ¦s½á g(~ÓÓ®µnnØÑº¸ =ã’0gºs8pj ˆ02Ô(LG$(Øã~ÇLº{?_ôHÇÒÀ8¹DÑ3ýnË‹êy$²ßöúÈWP:àQêH x]íæ9cQm‘Dá,·ãVæ™ { Œlyõ$UàÝÌÔxÅÛ³‘6È6p¤¦=ñTÄ»àŒ‰[:–Âz¯Ç30£œNrgÙä!·¨ÅÀ¦FLEMDöo”¤¥i@sâÿ½¬…QÒQ«>‚o»ø?`ÐŒ8Êugeç·½AÔ¹ÝiÐ&Ø ‹ÛˆYÕüÈC=T˜öƒ\‚EqÍ$n匘Â`“šIï` LˆÄu/’ø0©ßB£'š,€˜ ^%‚—Rk-ñáFÒ׳¼nd)˜ÎŒ['c"›ÅzøÂ¹áݵ8¯i"8ÁΤ·fó ´J8;Ïç“ɨ,8î¸Ë F$Ì ¡‰ 6gIà (¶¸”'`¿@C2>Ïœ}Ä* £`èU…ãMåŽÒÎMÍmëYtZ %é)ÒŠæÅŽ*£kË_ç×.ü±©’âAH½d}°ÊW𴣡3y"\qqvÐmI}2 láp‘7 âå(ó²7Åñ'ޯкØäAR/Û-œ‡*„c +ø…!) *žv@¶­a¨ÒV’¡²"V¹ {*Ô$n÷Néœ^"w(oÏ ÍØ\Í.Hì'6ègá'.*P3óŠÌDAÑUõÕZÇKŽÕŽâ†k+•yoHch1ÐIvŸ$h@­ñsmÉGÉ¡LIÝ…ÁÐdš 2ufBBçf:¼O  gF~DŠ–˜óág%‘Gç°/RëÉ“Fý‚A"Ž» ÿyð™…f;6BD•-<Ê»· KwI9ã*Éí}7'ÃY _…ƒlóö’Kz›ö8-lÊ%LÆX À¤ K°E·o%ÔI•ÐDkZlÎŽöJ0rÉ<å°!ÛMÏÛÞFãm&j+v …=Å#Ÿz}Z:0cB…²H¾r‹Å­(ƒáV$C ‡8ôÍH\é!XГ:Ü,‘øç)g aLÎá8Gâg9¿ˆ‘ æ<ƒâ"rˆN§`eˆ~–‡¿j…è?ÈH'5¾­¿/.Í-ª]›T‡£±?âL E°®ûÌñ_„Xª½BÖìɬbhÿÜ;­góÒUVbÃêäÔ—Á®æpe¹Ñ²‹hÃH‰½ú⊡á«ráu¬­LE¢Lƒô½¦ ‰¾RÆTq˜ªqB–ÐRAa;‘K©Õ–ÕjDK²-Å›‹X;ÚöBþR.ÿVªqq[u•7³Ë²é¦íF¦AùèFÈ(1†ÿ#8‡ÑNƒÑ]àyt NÍ9|¬½ˆÓcÂ&•‘°î7©{AøŽÛ{ò÷W-#+¦8 UJ@²'Ås5SåâÄ=eñq"U¾‘¼ìvoRN®àDý×­­¼j±t•Š$†"Êâb,;ÜÐ. Zb­Z‚e,XÒðI5ŠCeŵRû`b“1ÒA³”0Q£%Ë%abÓAž²ÁwEn*‡ð_ÿù»n\ìæ*Ç;ùò»d9ÜqįëÃpoýë^¸.”NÐÿwH•å¼³¸]ºvÂg+·Ài”\‚¬ÝðçOhvƒ+ip>ÂÓ+˜6xÚ>×R‰£ú[‰8oã˜Xû\?öˆÜ‡#á´Ë ÎIŒ«f³Fͦ€Ë*û–Òn=m…ûw­ù›¸s˜ÿb‡( YõÅ» cE16ñrÞ{[Æ ½ø€Ã€Àª¿“ÆË4§œÃåX·Iï‰eWß_ï—uïÙ Ù]—^j³‰¨zÝÙ¬ònÒÆ$À®ÊòÛVãCÊû<÷—þGåãçåãÓ´}½°Ò‹:yTy‘÷ e‘9ž¬¤ÓN…ñMV÷¯Ì$ݼ<Ͻ«ùp–ƒiæÃÝÍ2þ5qËÍ.2ønó÷É}»¿Hÿ÷á3ˆûì`¬×”øL5xȆ£Ð<ÄÅn²œS N)3c$¨„àŸãvŽØÉGðÑ: <Ó«5øè0” étSR–— E†Â@¤tO¼{,/YÔ_#aáI|4Äg82“º”*#Ë͸ÁrSq"’.º wèý…ô‘–”‰É/¦FU/ÉÆ‡vYû—ªúÁÐ8ýø ëIO-] Ó]¼¹÷"[ÒKb,[ŽO«ë£,¹œâRš9g)Máû;`âµÑò9VÓKzõ ¾¹?eÑŽl±ç­“r4ënñ¶'#ÞÓKù†1 #ÖUIÌ6¯KZñ1ÕòÝU$qR•h¶ZÎ úªÂ/ÎŇ\ñ´†\à^=³öÍF|¶ö<1–|âþêÀõiŸ¸e¯ãçô>²~óæ³Ê$8¾@”`ó*—Iùã³Íw}uq½~#’ª…N®+6ìŠ(‘™0®Àqz’„êø‰ß¦£êBÓᨖî1¬¼úȦ.!ʆü6¡ííЬgñSAù¾sq3 ØÄºUêEp&?Ö!¡ŠnV|b‹=^.ºô¼ÓxGåª5dÑ [,A7Úœ*Óû­MWÁ=-Kàn=¥Y·hò_‘ù²Bš^A.ç„lÜ>G;wzØ÷¶Þ›Æq è,NjԈñöåVj‚ªna£ßk$#DöˆŸ“8 Æä|¹öY\^¤±õÛ‰æ­,V#RýŠžvšP¬£²åØÖ¢7Y.Ýt¦íѽ8îûE>åm~+—«‘U`A‘j|A»roÈÍ®)eõ #^ÊÁy¾ú¼ã1¨îE|ߝФjßš<]‘ðO¨fûÉ1-ŽAe49´ÜeúWÚJÕüö&^rÔ×;¿2Áò³ íl‹.?ÎÂx‚_•Dkå'&2Û¢êË&é‘̹ôHÃr™a7!z§Ÿ Ü—£´g%[{—_ èѤBû¤º9:û%âì_~»²{ÏÔxÐMû±üréõÜA¿ƒeõ̯q2êÖ“˜üû…Sú©† t¡ÅD0öDXèÖPD™sŸô°·Š1(åÌáfZb6ý`*Æw%Ešä>ä_j=Ê?éú–íõgLJÿþǶSendstream endobj 238 0 obj 3728 endobj 242 0 obj <> stream xœÅ\YsGÞç ~Ä>_uëãÕ»•¢“kùóât}ï.0 Ž´c7ªõá«ߩփ^ƶ^ž®þ½é·i½Ñôw;ø±}¿y‡î7vó+üÝ6fóC³Õ›ÍVµãèí¸ù{C?5ž0VÓ=?5[»ùY.Ô›§põæn3vm§¬ÙâÙÔlãHcÚ®S ¦?ïãÇoü¼Ä~¼Á ü¸¯¦§øq†ÀPn˜îËx \mG:ø[³uºÛ¼ŽçŽÒ —ñàE:øßxðíÂÐòí<¾ˆŸÕ^¦ƒçñàoMøÊ*}*t­7£_oõØvøE”nj+£`®=,Íã•c<(Çh”]›”qA'¶ZÃõ£¡Ÿ šžV| –ÀlnáÁ÷ 9š$]‡âjíAà!³E:„·}@¢±ÞÀÉéá°ñPx}Öð˜ŒÍ;™µ1ã4ÎàM¼Ü'0ÚeX±l-À¹9¯ø‰aùMÏò¼ùhÂòtZËBuº¶NÆèÔð(?”DÂ/§ù&¶¥u¼g‘»nÌ/{ÖÐnqô ãÑ8¢ñ†3°±h†îaÚãˆ{¾Â9T¾ÁKãŽÌõÀ³‰÷‘_¡¢{ZròÈÉLî6` êúÍÃÂtðWOVïÖÆ´=Ű9¿vJ ­÷ë¾'Ü{ M÷Vw¯/Þ_¾\ÝùÇZ­î<Â{? î¯ÿ²zp°~²¶&¾F–ƒªñ1àã9rÍŒ•ŒÐ*˜±Ø y™&kØ]+Z@4mŒ?›o%:Ad H-‹sVNkœkoA‰ÝÍÍY9×Z|J«,Ï™¬÷Ø„]kºäBU>9Ç1¯;H EÜ»ñÛÓöl§z½ùW8¶8km½jíÍÏZ;0$3~bÞšæÍ›KËäS4 ˆ·°ÆfsF—öéÙÛu_cCuålEYsûÞZ=óH߆/²ü[ £ n>d^.Œ@> ü€…­1Ždú¬ q狪°üÞº¾Õfª ]SÂ@L"Rš¢ÄŒéàÑû“±PäÞìuô‰xõEÁŒØs¸€€ÎBôBwŠq×ùËA9&à›$"Ä·÷tiµ¥ 4‡ìöý‡e”yuÄ3†ÑBúèáÏ1¡Yzp¬¨ÐË vÀCÒAB! 6<á‚7[„iˆð/±Nçž!¯ ´¾: ]R:Y+î]¸Ê)-ò‹ø !¯Á‡çfŽ*Äõí³5OgKëÐ9B«œ`{ÌY4ÇFŒ•œÆ¡jDq*4TæmzPŽ) kãI—¡J–ÖÙéÒ27Cמְ´:±§£ÅtšnBápž‘y‡_»)*'«G¾cŽ•½¢{ ì¾ ?³kžòSQÔ*¨úÔ…ÇóÏã°iâõ”ã=°)ó]µ4 ²6e[Õ«`n·âúdö&™ÈV8¶š;"=2Rý°7 YØëØSš6²ö2¿UøIb¼3ã“ †tÌùï6È–cc²V‚ê ¸Ó™‘­…À‚è/ØFžëç a’>„”Ivè4`údEMghu¦îHŽ_º#²20ËWÑmâX´v¥ãEœ£†=ª=Áó` qý ¤™ƒ¨vФ‘øØ^÷¥¾QxÑŽ- '³‚`®¨fEÒç)Öe3yˆ#ž,¦²ÎÁFü ;•Ù+j2ú66 ›L#9•é!§ˆb ,ôà—1[l×PÐíy\R|‘•=_]£†4Àddº!´¤Å-ù>ígÜù“xT‹ ˜)KÒe,.y±þ!ÜÍáüjcÞ¥™!HêÇe€h•'€èFÈü ¢">®¾¾"õ©Ki{Ân7.¥ëZ8“ ‰èWr"„<Ð]dÌòy˜‘äJ ,¬áÄÐE•¾¢°{x¾÷ðíí\¢°ŸAÇw«N´¬É)Á¨<¨”˜1vÔ„]üñsÙEK!‘¢’!¾.;èº1;ð±ÆîòÝž.ŒgGO~õcVyÐ÷é Iæi§"%*©êymŽÏj“62ÞóZ¦Ý‹Ã|ر¶D& “sö<¡D ò§ð0ß*í’‚«¶‘j1&@‘Ù€s‹óó&÷»+Ÿ 0s!9D Œû'øV9× î–wbFd<â/Œk‘$¹òŸìö”ƒ¾Òã£S¶ÞV¦’ÍŠ2(v¸Ï2ï„õ4jÌX¬n¼ÿ†µˆª‡‘éY=@#Ëfט˜Œ•zÀCüx½6ð~;63ç]ãu2Ò£ÿ9–}ŒÛËr©Ì’;¹èÞ,Ry“\âANC[SÒ›½‰&دuSkãìo¿Ö\i¿LÙ Á~­]°ßðà=ì/E¹3ûµTãhª%ŒÌ nÒ·i'Ÿqñ >áõŸg(ŒXÝê!2ö/yƘFJJg«´l¹ Çønß³6ºÎfpð¨ž^ ’ÿ–œµ%0¦}7  šXåIvØ/Œð¡$Ëì¨ÒD R¶7ÆŽZ€vl}_€¢ä Íœ÷5–‰Á‚÷•ì/ Ï+Ù_­A}óóÓ€j¿|Ž9hžäŠ ƒy˜nHø˜ÝþÒÄ0€³1æM+' éîg(¤$†ÐÝV£É£é/ ¼Z¼8¼N¼ø’Uá€Ó¾¤ÊCiÿ'‹)‰šê£d®ø—ýe´âë/k%]­…Ì·“õŒ17)PÖ‰Ë}”© k+3WpT‰*¤Í÷W¤Ôƒ ÐôyјMhþ,ZdD‡äÝÆNØñ’{Ê¢ÕQF—Ö7•é,‹§=uXÙS¿ÞÀžÚÕžV󔯘œD'3쵓È$âÊ ‘ê×çð8ñÔÁ3ÉoIƾ ¥ã˜ÀÃÃÔ®h°‹F2 tITœw‹)ˆ§ù‹€ðSà˜ï ¡+¤ƒY”UéÚ®¶zŸ]×38ÝuÎ¥]'W¿NöÍ“|ª5eëŬ¡¾f$f¼0h¡JSdu‹³T*ëWh‚ê`Ø 1.%^#K™2O"¶mgf^·S}íyÖ ¡ÈWÃìJ™æÞZÅé¡PŸVwÄñ`FpVvB¼ÍW¢h‰ªVéB-ã*´Ê“ÎÉ?«m|fŠé*3± 8êÈ[!Á#=Š7dè:T †¶·Á$‘kMÃüžuf„UL\qo B9‹kö,¨9P7TäqÂX ²àêIô>± È ÚÉ>®ÀÙ²‡Œ¨ÊåµKõÁeŒ#Ò²ùnUñêÒŸ¦«$Q¹ViÏýŒF=ñ ¸¨$ƉT'¨ó5V¿vÉocñ¸+»^-…ƒ€ñ‹À‹mOx.´d:Îïö[/Ñš­O&'ë¤Ý€Ùáþì^Ñ``‚Íkk2\X¾Ô¡v&Fd”£WæÍ2óI®v£ó¼ dÚ{“×;¦ÞâØáMz©\J´KåÒTDvD%²2NËM©¸Ùš·©RU«Ó×<Š~¼i¸lF‰µÉŒÓד‚r%7Oø¬^ŠÄ=¼Rí±±™úU溳0wÄÏ?bGSéQ;rge‡¸Õ‰ia»@|%äm¹Ó;!cÅfT6°#Á«]0)£Õ§p»¢á†!ÃÉÀ¾ Cäü‡œ||Û¶cå9¶´†‰•P?“æú@QœˆÃ ½,\B2ÓÒý¼d´lbºNËO» ê”I‘oJè¨8 ¦"#ôÙ­öa"Kýo“»NÅzÆÖ&úþmá48Wçú˜w·¡ï‹‚îÔˆæ¼}¢ 5eÚÌbΆ¿ªçìêGˆõðÄJ/4Ï·g©ö,:9?ÉžOùöÃÇî¿s 1NÒÇ“/™@·°À?|v)±7mQÒÈ‘¤YC}áœül)¥Ÿ¯`;qŠžÞoš“œ6úVÛè’Ê$îf¨s).VغYL4nˆYdÖÚ¿d:üÀwñIºr¥0 ™Dé~ ¯@]\!õ&¸ìÃN‹I?ý›C$îçÉÞü 8=ãÎ €ÓˆÒ¦ŸÇ%Ÿ÷¸uª\í¢µ†ˆW>ˆT­K€Íµ ëÄ1Í+½©¤ßìñÙ[Ho[;|…M '¬º(da²õ———„ÌY¥à²ü¡/âÝܤtîÔ²¾È ä–­Î"t„/Ó&Þbk²Lòæ;tQ³~Aτդ_pPúçЗH¤•5#†WÓ¤ãN—öªžËô{ñ€› ÑõvhêZ0%ýó( û0^#òuf’‡žEh”€5fôêTÝ%îñG¿ïóË|‹½]¼®öº¤i„H‚´SClÔ(+róÌ«mbm%®GØÌ@Þ}Fn™©¡Dó 7eC5rÔ{8 ®‹é=¿OËnì(á+-­‘ÅÉA@Q%6Î:õç®Lô1gÏ–¸;iµ·ù„ȶ@®Í5å«X—«:¦´ÌélÖAÁ£Í-¿È‘5nÕ£eÇd›ê%ÒA“)Qõ-?㚸 ¨‚ê0E»:@¨ØÉ*pó¯ŠÙlŸà.>ãEö®¥ƒ5ˆv×À°#0ÀˆÆØ4ÄIýT|+õãìób’ï“}V÷—Ð:HZ‚Y„Þø’¯5Z,È!£~¥¬³d8Ï>° ÕiW]J%*€Ê:#µ§jR@xZê÷)Úü%~ÑdK³™©'2…&>ÝtZ)Ÿ„V9õ R›Â>¯´?/Odoâ5YÓgñ.üœàýX»ý¼AæÔ°t7íTPûÇxúe:(åÛÒ}nç¦(ç¸f?¬ÿº—Žˆ5mGXåQÛóÚ?­ø ã7µYÞŽ:NmŠÙÿ. W<‘/Vez=Iž,-$Ä_t!¨·èÉê^À&zendstream endobj 243 0 obj 4250 endobj 247 0 obj <> stream xœµ\YoÜF~ò#ô8\h&d$ûe8â…“Í:Ê"‹Í>ÈË6,ËŠe9v~ývUuUW“Í9dä²ÙGõ×u|UœßOÛMwÚ¿ôÿÓ×'_>NŸßž´§ÏO~?éðæiúïéëÓç±Agâ•MhCwz~yBOv§ƒ9¬Û´æôüõÉW®ñ«¶ñÿ;ÿG|ÂvÅ}Ø´c|è|~ݬÝêû¦Û„0º°úª1«ŸšµYÃõo›5ßxܬ­i7mçV}ì{ïâÍø·ù¦±}ühÝêßM×Å«£WwŒ]z5±íÚºqõ>Ãs¹óm[Ó¯¾‹½ØøÑÆ^¬Ç‡ã·ÎõÐÐZgcW?7ëš›Õ/M¼ÒzÓ­46Ú˜66ëÍêŸùéÜð<_”™à$b¯>v1 †Dhœá:ÉpmÛÍÐ…@¢ ¥Æ“Šõq_’Àqœë8éÕ-|zÖ¸ÕÛ8ØêÅ·ºÙÄcO ¡ÍpÍ£üa`Õ$͇pëð#.×Ç…äo°õƒ†WùÆé9ƒÛ]ˆä»¯ðôxë^Æ>ÞÄ]×­q¸ô:v-â<ÕGè`+›òemÂWåËQ®bc=Ln\]Æt†‚›W8¬añGĉ=‡éøŒô÷¢ÑÛ6Jȱ¤Ÿ!Äp¶ å;FF Øúaôön Û¡Çi9˜x€iñʪóJ‚M³K Á9ú–™îT¿k”¤Ò]õäšoÂÖ&ØÍÐw§ëx< W†ÈQ›²î¢8àú8²ÈhÂñºE@=‰ ´È(3tÔÙ‹Ü <{ÂåÍ4c‡{ ËW8À5Ý’mxß[±Bìü+<ˆ>C·`9ðÜÇa‚ˆ·ð\§·|-kÐÇÄ áxX÷ „ vã†PÖË<£¼w/áyßBðÁyëÍÝÓ5Њ†÷Ì‘Øèp*{ˆ«ƒ!î K4 k^&Âʇ‘L–Z!°lpÅzÇ7›ãÁì¼¾.‡p®Ë”B)=° õнÔôÐA÷Ó§LoD⬙\‡SžkYK{|þئÒ5Ámú¶c myÙ[z6Z#µÍo²®¯ï=7šR[¤Û[–¸Åå_ÒÆÄNöuöE±ÖÜuÔˆnDùhÛø"#Hš&õDK-ÕS±Ñýp ®ìØÎ7­ïfŸÕÓÆ‰®]º¶C;×Öìaâç|{` 0$ïC=]îø<Yh4:šCvj&–õL9"»ÝæWwЭÌK¬Ø3‚j´à[~L+j"ã6£Ó šjƒh®‰Î¨Í†®žJ‹ Ô Q²v‚¸…¹’tÌ…€ÞWôç¦~RÅèJ÷‚t M¼T-…4’¡4âh!2\`›áË I06°Y±;ÑáQ '™ à ŽI%K^Èôše ­®Ýðxãb 6Wê#hߢ a#ÇOÐo+nSÂ2Mݵ DTÊ(‡÷ÑDÂô]+K*°LöiܘlŸä ý){Ž‚$+Ã*!ÄÕÒn£´Ô]VÅ5ýð[“ç­  ±ÄâŨž`žï ï†WSªÂ`ü Ö %q–Å y ]©­µ¾4H p÷Þà„“°ÑÑT£n ¸ÒÙŒòÎO§ÅŠaÓ¤ÈÁE00nz FËGã;ðµÎáÏCþDÝ_ÀŸ¤ø÷þÀÔã|Ð=‹Τ5¬Ï6j]tù”j¤6×ùâYíâ[åpÉÅ?äâm~šïõô»Üð²A×°¥ù±ˆäö•\Üb?ƒCß3];Ë ß©Î¹áG¹v£ÆVçóD.>•~Þȵ«š,ò€—5Q¼•_«‰“Í7‰©Ó\tÅî¤C%æ—ÅZ¹é™4UBû ›ÂàÁëž.fôôLzŠ+s=9—¦d¹½Ù fW$\]ð'Z$Bï‚À07ª³í÷G ù‘ü©áZ¶‘vUp=‡ã>ˆ_íÞëkAóìy¯oký\)°´³¼.‹Í–³À õQ†·»Ñœ;ÿ(ýÜÔÎY Íú(¨¸Ô‹Ù…æK}Ž”Ò¨`° ߿˯ÍóÃ1Gó‡jÓëÜôBš–ž¡êÕy$>ûq˜QDc´/@ ²ÒeÍP»ÀPD&:«9Ȟƽb¼) f:êPÓ“%œF[@3Ü+Ú2h÷ûÏH™‘¢¡cè ƒž#x”ˆÞ(¡Û„%i¢Ëq1$nΙ>c'énŽdƒjL1¼½IècM<¥œ&‘¬ëÈ‘;„r†þ(Þ.X j>ìdœñÙƒ›³@Κ9ä ñ–³8×ç§O„£péx&h=b˘ÿq¦Ã ®–=hôË»5fÉ(B0…»L³u%ä`Ðh©âP¡ÿT§ ¸qŽUÔ,kæÆ9¤í‹ë)B(m×'£Ô†´]X&†\{OUÅž‹ÖM …¾F Á …";:Dw?¡BÓDŠ¿™+…Ë7êýM’jç㸂-ðDU*ž¶nODRîvðD&@°ÂRñ™"‘ØÚD¡¶ÊÊ EÕ6ç²ý¬é+¬qûX!ÓOX!XBÊ d˜ 2Þï£J2n¬À%‘B± ‘BæÓH 3LH ãw’@p{7 4_yÒ)¸ŒÒ•:ˆÿ1}y²güñ€Í8 ”7+Ô%7¢à€P»ã¹`hã÷}„Ž%«8%tÐÀrÂmNP¦‰¦óÅ>MÑ’Yå®懹çvm¢5þ8n‡—À”$ÎÚ¡ÿküìN•2ÑÀËÃ%æ$›4/”2¬³Âî`ypƒ†E–'Í_‘=žÇÌóì#w²¿? ‡ˆ?ƒ_<”ܹ֑02<9jÜÉ ,¢‹¤ „à ]r°¨Qm"gQîI”=:n˜ãouÏ*ñãZTé<þ>+L@ºø¡Ò°àRæäγy8¬"Ó÷Ò¡âaÞç¦ÛZÓw)-„£€(;r/r_õ€Z=95NGÊ$/ÏÌãx†¨N3P›*Z¨”*„˜ æmÛÊí[ £9ò©æóKd1t?ó€Ô|fÀ<Ž9ɧÙΰ¨!LŒÊ_á»bmÔµîtÍŸËÌJ·YÚ"¶È’8‘d}+é!ð:S@þ<©ažˆ‘@RÅáÅ×ÌT¦8vËœèÌU¸jÃ$ù39@°_¢étâ²,iÜáù€:Ö¯¾l¼Wô#ÚÊmöh$#°ÙQ¬ šÖÞ‚ˆ‰I"i)ÉAÙ]9AÌE¼ÝÕ;¹­Âè7+§7Ñ3¤”#¾©=È›˜\Øäôñ]Ø’€Ï ÷±l+×,vnÎó vZ¯Ø·› ­œ¹h ··9/‘‘dG ‚aã²d³1 NÅ· §§Xà<Žaõ f×£åHr@´uõ¡ Ý®Â+Ce#¹¢y¢ÄY4¢ÃˆŽÄ„I2ðÁI:&‡~Éhá¢K…T0&íœA7¡•h~¦`:¡ LL¡å_(Üp Þ™Š÷ÃêµÚxâ¥ôÔü @»Ñꓜ‚`…ǨšAYn]‰¥™ÌT¬™¿t8ÈQê7]/õú°èòà΢$>kR7¢uSæŸUn -ýôLa½_®æQJ -)L;…™´îbwÉðc]fbý@‰®@É›ä6 ¨·Ù¼íü¼¾+Úž ÷˔۵¸Úórñ¬ˆ{Ï|áýì¡…=Lu†E}Y*c¤†;gQ·Œ±¿ÙÎs* íŠì¨’‰„У0@(påie0•üñ’µLŽÁQÅ…ž ªÙoîk;°`ç˜A»§Þ8•I¤cëJ.³©W2°)ĉ$×õ) ©Òý’š,rÑEˆÂîô 9)IYÍ*MN»žVO•¾Q§é…òÖ—¹/­Z¨š6Ô_ÅÉJ.ß½©ôš´-¦TGå¢ Ù—ó˜˜ˆ—ª©(ËI¨i€ îNXÌB©‘v%“$)ÂÖÐtÂL$'w ã mÓ» pCG£ @ÌQ"Ѷí6\ï€1³/È_Ò*Ð:§¥É} Ê;?$å¤rVǦœd£Õ9&¥”æùy©*®«¯ WÀŠYûI=ñ\uQ‘íò›hÃ4å·˜ÌBqô…8–˨­W• Ox'ý¡MÎÀA=(¥õ¤¼q£Ãœœ±Ù]¯|Qk™¯Õ+W>™WW$¹NƒÍë•ßÕf‘S wM%‡¯‚¨Å=:9ÿÛAb=.!ÞgT>YÖó„L‘qa±æ ‡ÊhYÏź§ÂvAþ;3…ùN*$>K*8Oeùó’M³/±ðMrFË ž8ôó—âÊ÷’Lª=‘7ž˜¶Ko³ÕÞ§;$RqƒŽRÐñ9™ù%¦ò½×¨;z71%EMšÁ/rM^oê{ÇKÞ²S*ªˆMó+Râ^ìVYš“¢9Eù“sÛ™PÄ£»öóM©G8¸?˵Sg¼æ2pòâeðuNÞÑÄ)ú_!äz•á9PöÉ…æê·§¬ûÙÜ—5ž%«ï:b;æÕ–iq_EŒ”ºÜ $¾~R÷ìÚÚ]^@J[pê.W·"¿+óËš> stream xœÅ[[sݶ~×äGè­‡ˆ!n$øÐδN2I›Öi,?t’>(Re«‘%_$»î¯ï^°À‚uŽíf:ž9>‡A`ñíî· WÇCoŽü—þ?qôÅÓñ³7GÃñ³£WG†n§ÿÎ_ÿñ8Wúy˜Íñéå?iŽ'{<9ßöøôÅÑ»± »¾³;GÿŸLqîç8î¾ìüî«îÄôóý¼ûºs»o»»û+4…ëλ~¦ÝãîÄï~€ßÎôƒ øÕà}+X|š#ÏK—Ò‹ñ»Sìå›êŽÃv÷¤;ùö³øÊq÷47|„7èn¹#𫱑:²uDýO8š^ù¨¾ƒóxÚÙœþ ,j¬¶¨ÐW£ž^€!=Ðtú¨žxczëOÜÐOfžù ŽÃÁ;àãø`CÑϧøñÓ?ïñã?®ðã?>‡QFžÊﻓàp–n÷<÷qÆÆÀRÞç‹wåâû|ñe¹øÏ|ñóüíM¹}—/žµ.Þ—‹oòÅŸ:ùʆ+T† }tsËØ~“hhskÙÜd{Ó:Ý‚Ñ_vv¤•Ã9Íáò ®_T¯¡Ñà ÑØô5þèçKDÖ_ 4‹™Áˆí.ñçL=ÝudV6ÎlèÙ+èù¯Q'÷øDK>ðu'fø¶8â ÍàGÄ4v„†â8Uç8&êüË]žÑ4ù…n†Ö>7q8ììiL4 K¶¸¯»Å^¸ç|m9ÝŸ¼’Í€Kàœë!h$³ßåÙa/ПU£·ôØ}¾QÃÀ|&[Ýf«ƒ%8J8ç9Ll›‹Ÿd›Iˆ[£ 0lËO_f$âø[¾‡<1®ÀFóø ô@&¥õG ¼ÅØ…f”9ö¡á‰'€ytG'ëã]H8À›1É©Ÿg÷‡`óžü²~y¡½Î—¥Iü¹wˆiFÝü‰¾>ó‚áPïh€ôä+œÂ½¼ ÁáÎø0òncñ‘Æ·D†çzš5OXfùž1(‰Ù¿é(Þ§ÕxªÇiî¼hh¸Œ^»óü­\»È$Oè<ÃA+3náoC[Õí}ëý²è© Loâä’»eäð4 99:¥Ùb„öf$ó¦a*GË>æGþTÅ |í‘ÃWá@ž{‡a%œºþ3ºYܦbâ ×½ÚàǼ:ûAnQÇ»äºjÔž\Ò"Žå‰ŒAa]&’}ášá„ËFðô¾‹ˆ6›Ÿ'ÃkÐa?yUÉ›SB@ËÝäÐçèM%„®Ó¸o;iIÒ+Vø ø4c'Í©;â`-hÌ/8¹'„ŒCYýç1òdöSœ½µkÔÙ@X¸ÏNöïbŠoa*Ö“½Y®áZÀìu~w_t!gVG#^@”1d×ËÌ š&-x–‚Oœ6†Ä˜û1‡ pÄ]Ø$ä…|c+EyÃA|™}èÆ0ø%ÄQº©5µK¡ ÔÁeË]ˆâÀè»Î«5wÌ—nÛŒ6.6ýÖO†^!)Ù9,¡æRÎsuàÊ>:µ!G ø_W³ÐéÍ¡)ch§8Ó‚ñÈàþ“’•A¨d¯»å$èFœ÷XJ0^'Âñr#Q *‘èGpM빚q¨×­Á‚RÂâ©ÖAg™C°'4Ï"‡˜@ýoAPp„P›c¢ª -ãykæR½{Ò‚ÓŠ¢½Í‚“dÛ“ØaË1›7¢ÏsÎ…FÙ`;ùż޲VEÖÓʲŒ4ª í±´Nb*‡œwˆ£Ùy…®suši±%4®„ÑUrã%ò›à¥ åÜLÌwÉ…hn†+r• ¹/†;ŒvÜþçØ P6Œ}dÈò„AÕ¶äûqQñ-à~|Ÿ3%Ýø®hW‚@.ÛI ,À eµor£«VñO†+Þ—ùâë–4ðV³¹’ÐrÛj\3Çðó–^ðúáWÞl¸"¹Õu¾x­yœ\|ךB1гr›Ža—e3è5ùšDäHw !ε<"_±ÀKO57ÙÞ%´äxŽúˆÿ8}$Ž{ §A¼GU²UžJ:A’ÆŠKGK¾q©—ó*2Ú‰ëÖµKÁ Iâ°ªŠð¾1Å(yP}ED W)–Uä¢Ô=9銜B$+Ù"XÖÅÙ1㥞z“—‘6)ž´Ãí8}Tf vEbQÿZ4»²M–¥b$c«_²ÏÃjJÊ"‰ƒNë÷ƒ[þhù!ûjÓ>®[T”ó(‘\äù{ÆËÈî Á+{[?ÒC€LK$ÖgGšK0ÝE2‚«q‚ŠÝ¾Lcᑽ«•|ǘ5¾x›¤µ©÷¾HkЋй-^¾(<@^98UߪòKãŸ]ègUÓ÷h \J÷<´šHþÒ9ÎlØØ¢Æ\M (ÂÁxOâ¾D|È·©™68j&šjùõÅÛý8e¿‡L¾(A1íœäwÉv’- ½‹ ¯øsq$uõïpOx.ØaZªT&WaF4Æ]Ř‘èH²°I_$‘´8bõè+« $0ç:–1„ÙP•÷¿Öm^²V©´@i¹ƒÍ\rI%¯ºTuú~¡»û’ˆp°1ˆê<+U­HÉέ<(/H‚úŽgÑ,Ëß9À Á~Îj d¹Üeè~Ç{œ¡ˆl@t8Çs™Ý9Í —¹«Lºø¢E…š|ë—)O0“ºö^Ó¢rïBû#5²ƒâ{5+Z_¬8¢¦B‡nUT(|²s¬iÐÀ~’A·L¡lµÀ›0Ë«ˆvöí2×Î,¯^”r üAV̵9•±;–£oî^ÂÝ‘î~ m’8’‚4Kp¾½)ùKñ(²ˆ¤’bšoÚ¹"{ ³Š=·©³Yµ²)Í!4Š,*ƒs-/ØÉªÖ…$Ù(v|Ç-•ú„* ŽJ»/€ºQ‰¥eÑ*oa!Üç€ §^ÛÈ;‚{ØtúP¹l£ËR Úo©ª/Š!kK¦$U13f\:xŸå°9æ$»’éý/ØϪ|”˜ÅòHင8bb¾Gγ‘õâ-lEÞÑÜ-²MÜЙgËlk@ÕÜÆŽÌ2Ï“)nª gv.›Áxl¢Æg2'[4;òVÌrƒÖÉð’qñT–bŒŒìmè12°æ¦åXZÉûp9KõÕj;©*aÉ1)ªÝê;ï5n´{S­ùÄ{«mEŒF&hñ¤à9Dè÷œWôH6?œ›Ç^snŒY[¿YðëK&¡l#ya{*³¹±Ð$4Ÿp—RÐeiQàÐÝ$ûÓX“}¦aüÀ;U´ù,˜Q©„jW¨ÈÞ(¸bO…O–âÊî|ÚD,Y2Å:öÞ3”ê+EE4Qíu¼-3§™.ÒMzõº€KÒ¿ F#lÇb,ô…æñ*Äü;SöòŽ*)În«¢ ÏjnèµbòKâzß(Ø©ÝfÚTÔ#LÇ–sØM'gÔ ¤§´ádó锜“?t}ì(Þªõ!T—ú§/‡þ3Ñ ¿½å72º}Ñ$òžu‹{eGoR4z—£‰0ìÄŒ[Qb´f‹J…½Qa QÚ·pBÌ‹’ÒN_¤HXÒ{Û©Ý4¼wßH{…õ¤€CÓC(y'çw莌:0!u{«œ-=¬dãù6>Ú¦ªœ›u©“‹…tÈmLÚOC6nž=Û/t³¢õÁ¹ÿWé2~Téâ'^ž%ëU)w¬§a¥òú‘Tƒ ù8C?±†^•~Åùë„-½´Ë í'•~Úª,r¯"ë§±f·ô`RÚFÚØÙa|9…²ÁöT™g3,ûVAéCvð.b¨ÃS®nq+»ŠI­l%ÊP—«½¤aW1áѬ7·SŸ9¹”ócj‡»:³²€3P<«¨‡ÆÁïÙnL{c‹M.öä’oëL«R.×·¶÷E„Å@øÄBëDÜhÒI´ÇÅÇžfú£&ê ¸¼(®©vm\¯m Oµ.O®–DÎ;¯Ö=ŸOBÂTÇ$Ù+¢ÝÀP%UáDrÞA’O=´óe¾ñëlèø)Øü+00ußfl]¿ø4óÈT˜¼¡í¯>ãf<jŒz@ú—ÝÐûa&F‹ ŸáÛœ·©žO_iwÝÁCP¤Sôµ ·ŸñÊ @@P=]ðãfôëîñ⾟×#ò¡¬Í«ûøú@\‹a3¦sÃÜö5E>Ü »/OãÅ8¹Q·T÷ËCªž^ˆÌL VqãþA=KŽ.šÒ ýdM–íëg;FòR0u[e$`ÑÓ|wtúÛÙ‡9êp}^mz¢'q,,$ÇÇD»]°­Ãz~úp±þcŠYÆ/\[‡ôšÛK\Wñ”&ñ³&W­?aÐ~žÅËò'ê`µza‘—‘ˆyuè\3Îs}Ú¹ÚäïñìX IWÔfãhß bçÕ¬ÏtÔ[ëZS\ˆÌ€5èhÚP¡Ñ Rö‚V¥î"N“YêÔ¾Z€µí“ÌÐú+‡Ü.ã¹uÓ| Ò¨F4ô— nv'5çuÅê&Ÿ÷±–VЬÁTÈCƒWVÐÈ'˜Ã$ã,¨mŒŸ[ã{¨$Yî>H ‚HgÆ*Ah±†iCõt«"2Œ‹,ÒßhÎÛ‘æÞ@“œD‰öDé õñÅ$X~uzô7ø÷_›¢endstream endobj 253 0 obj 4030 endobj 257 0 obj <> stream xœÕ\[sÇ~Çü½ùlŠ³Ù¹íΦʩc‚S±Cˆr©Jò *HÂ`að¯Ït÷tOÏîéH¢œ¤¨iw®==_}Y~8zs0ÀŸüïóÓ;¿~:œ¼¿3œÜùáŽÁ—ùŸç§ScÓ“~fspøòõ4“=˜œï{pxzçß…í¿Ÿz8Sõç~ˆ©Óáqjøu·õ›Çéç9úys¿³›'ÝÖnáù7Ý–_<í¶Îý`üfLc÷éµsz™ºp›‡ÓÎoþÚ“žÆ Þ~Ÿ†þ:jSÛ­óqó-ü oåÍS˜tì¸y”FqéG—Fq;§ßŒ¡¡s6­ÆmþÜmGhn7éÒ“!X³yй4é8ò±Ùh7,½KÃÃòPV‚‹H£†4Ä4Y¡õZ„Û,íúÉÌ3‰ÒtŽ/N( 4¦sÉǾJ‹Þ¼N“½O™cZ´y—¦Üœ'Ù^ÐŽÌ7?v›Aû©g’ÅËÔÛa‡çO/< äóùîà®ù¤óéþÆÍ?7© ®QiÙó|oñXƒu8h§·8N5¶¥&ßW°ñwùMij_‘ã=\ªû“ÒH]lÐN¸ŸjìCèãXG84gA¨~ó;VGÄ•ú†/FH t¹BmQ ù PDÿì #-œóÔ¦RÔŶèY³ž97¡®Ã†_ñuþySÎÓañU'aQ/ž~ƒæo:zó³ "º‹ª‘‚šæØÐŒÙ¨É,Ì,¶È0ð@7hÊÔ‰nÌ3D©ÎÒte"½ÙX ³E1È-_€Œ‚ XTš# WËf ;¼‡ÇÊö”³O¯ꇚG†ÀÅVw±¼+«L6nLx»ì8¡åQ€Mh4öFÐHƬÏôI#YŸÍiúŒ›DE™¨¦›AKfCÖPè5fjåys£U€—#É&Y¼ÅĪuÑ©•"äÎ7 'oo7âxK{*÷ zT 3<Ço‹þ°6³­a5„µ„ ׯ é:ïM†xeÀ¬Ç‹ú’Äj”Ö¼- %*Xš%Lòù’7úVÖé%45¸¡¼Iï|«×³KgLŠ5¡AVÊ¢¶óØG!hš0:Õ¨P›)x¾H ©ÄPÀj±ÆÒºÆ>t¸2ÔYpÆOÔîü*WôDµ|vxD=WïYhd³%ÃÍÖp%WPm´…ѵ°pÙô$_„$ã ü¦M´+P°ò½›øF¸‰šx`š­Cü ¬^>5ÄÔÒÚ ã*N;äØÎÔh€éà~˜°\YÖ²<6™¹­½ŠŠ.ey¹8¤ÍäLJ³`‡ÏÔyjŽt/ClôBú#É6ß·¹B˜bô`æ» æØ5B?À>ƒC@œ@¥§ÌKÛ¾¼Ã£€Ó?±D‹‘“X¢H°ç&/CÅ X­`çpÆ Ûwäí,N‰È¯PªS}¶ÄƒF– ƒÒŒ¨Ipà”|S¾Ô@ÈZ(.CÕ Üd5p<ºÇ8Žr.x}—]+o&öãAtoä¶>LŽ…N"zv4!xiô6ÑÎô÷üòHKÙ:dˆ¾‘hÑoÓ®¡ ¤n‹F6^ÈÃ÷å!7`k3MM-–ßÈÃ'åáS½r~øµ<¼/?¶zXÏOO›Þ£}L^‰QôÔîå>>Ìju—‰5 º&THÇÏv£] tv&¢Ïp2 ÍáÞJP§SÙ}ÒŸLá›ûZNdéˆ/þE„g63Þï!¢5Ï÷ÍI3á]ý®á;u4…ôƒèòõ@"áöвç«7j+>g7¢Rdû·Î‹[š1éŒÖ“N‘´XHöêÖ$½˜ã”jZpQ0ˆF ÉkF#žt þѺ(FæQÇ|Q¼ûܨŽVÐQÚ¥wˆ“q©ÁVLÝG#Øk‘Œ…»Ûô³ö”|ƒ!‚®¤ÿµ.MKDvJȶt_¯Ò@— yþ>ž3¶…f?@³ Þ÷ZgE('2‰Cj’P*@ÜbvšÎ”sKÊdAî:±4q@ G@ö9›öèM›_‰¤ìÂZ †·v"™WŠãçAkm­ª¯jÉk¯yØ‹ïVÖKA“ÎY$ãæ«ôã4ãã{ðÔãS0¾èÓÒë¡~}Þ…•"d‰Ëk¦¬€@Ѧ+ÀËWÚP_„e°ËŽèZ•ñHTi8WøÌ ¬e.*6f2hf3ٳєå‰9~/è ZîæQ†Ó{7¯œCÅéq›_žRäÒ¥±AZ¤Ã}–åôj°²ã¼àJÌæÑ0660*Ùm¯Ø =Üõˆ¼×}Ž Ê8´äÀ‰r\é\GäÇ“.TÎS°·„Þä´%ö}Fvwl˜ +¾{fH ÓPî`1d|§ÀD^¢‰"to—TMÚ¬©‚Þ^íÖ¦…Í(¢áè>U¦_EäX!úF¶© Ò¶©wF´­©+ï(êDHÜ”2s¾Ù„%ŠÔ×]ÓOåeì`™Iý"DÖw2Í'7bšÊ;W/Þ–S|-m>–‡¥ãY‹Œ~luß»fÚÕݳÁAoa,òºÐß{8Îä)ˆAÏžWn„ 7®ˆ» ăö%îÎOqa(98´,ÿ:Ç]MÊØûÏh&‹ÓÏ>Ð`Õðä^ÿ¯À =¢‘˜ßÈú6ØqAÏ à%±;kXÔÙ Èò £X˜ÞÁ­àÑ1i²¯ÊT† (¯ê*  6@‚¥¶°ri¹ÌãçF–Ò{l ‹è—-¢2Ž,§¶JfAþÏH‘òsEÈ*˜_Xäu”ûÆ¡ƒû·tØŠèŠCv'Ô¤¾¥£§iyÝêþFý¸q(øú£63üú¹<<|}£@^£e~øRžë}rÃS™°i`Þ5&üI/ÜuÜ× ¸3µÆs¸èúèþßpÜßÇ…B¯ól{ãx4‚á‘.2ÀL#?ã»(>{%ë¶»óB v'œÖ^’Δ^Ô9•~óLu:Šƒµ5º¯3Uì(m+À>ãQ—ô`í·z7°£ýµ}›æ+dÞ6.°{'éÿ|® »"ñÓ×Ü×ñ×—òV1äžÇmÚÜDÔß}'¸~ÚêýA`ö¨k ðkµ †Ù&jj憣¥áO2!ôº'Xžö‚eö¹wr3Y|¡·¨S6†nÏSÌ–, '„/ÒiËnHž·ûòV•NÆ»B8.éHºŽh6 %I¸Î×`– B¯„®„]K :”@£ÜÖ“L/߬⬰ ŽQäÆÌ£!V°øU¶>q•ýÜQS&Ç_-è¨qØ÷4/Àù¬„ 4Qì2µXPX¢ ²A62MážšPljÚ;0ÉÚß-X+8 ¢°h–U°Ü"&*À…£«ËðhÇe)—•:¢•cÔ#ºB7)<P»•ð~]Õqi(1ݲ ”Õ^ÍHâ(¾•Ò1õʃÄe©ôç Ò¼8ë©ZÀµ§B¢ Êùœ•æÐ‚G’;N}Ë®µ²0Ù‹Ä7l)º #²š)5¯.E;F¶HOçM^ tºŒ`YýøvxrókP¿¹¤_`á£Éä1å’šqÍSõÁ¬p*/&ó ®*ÈHD}©,¬•÷ÝÀлÀ• ¿fŠ=;íQé'‡I($¢™$#÷*6A8Hˆ6÷£—È@u]³µH¦ Œ\„s6|âc@c~•· 骒‰ÓUí` ßæ@ÒUÄY…¡Ë ¾0Ì‘ÃU©ßÒàä-§S"EŒøá‘JçQ®!½«$…IܤsíR ƒ©<‚_•ÄÁ¾iµà] ~Gù}=Å^¿â/yƒª+О›[Ì[Å2?£Ô -³ÎàË^ø{‚g5Úð1ß俏Ä\âÝ, O$óq#Á„ø} 8»èrx¢ÄäBë ˳^BÌ ùáÈ7TdN ß“tÁóD%J|uÌNÌZ‹' ¼.M"«OH¦Í¨¾Ødíò&Ÿ*™Õ·^´¯-C5ÛZ¥õ4íRã%«§ Ôp²Šüm¸ˆ8øU ’ y­jÚáçkº²2fÀ¡ª0P °éq"P­}|{EÅl3®ÉQ^ÕµSà<â®Oá)05®ôF`rV–¨Œ|ÚÍjQ`åF*e³›tu±:ÓªºXݺ½‹ÕñžkjƳ³V£hê@“Tû÷%./9x¹ã?M¥TΑXÑŽ€8EÓˆCùžÁp›-Ù˜†ÍLØñÕ+ NH>o$áiÖÔ%墿¯çQ®+B2KTvæ[8ðy+ÎÍ>ã `'b°uàªè­¤ÿÆURæòù®ÌZ*ÇÀ%ô¹É°?íÃg;rv˜)uô‘²bü.r;2ýª¼X늤P$׎ÿ4·¡ r›vú'Wé/ªç÷ÔabÍc…Ã,B¥ÄìÚ•ZýÝ%í.#7ý´;Šò„¢¥<–g{§ÀyâruÉs)Õ¾‡ŸYáF>_G [|sxçOéÏú´kŠendstream endobj 258 0 obj 4563 endobj 262 0 obj <> stream xœÕ\[Å~_Yù û8'â Ó·™îHDC0 Ç^(D‘Ùµe{×·5˜_ŸºtuWÏe÷,„‡gúZ]õÕWÕ5¼:zs<à?ùÏÓGÞŸŽŸ¼9ŽŸ½:2ôò8ÿqúâø“hà <éÓÌñÉã#îiŽ'{<9ßöøäÅÑ¿ºqº~g;OúÇîo;×}±ÛÛîd·÷݃ÝÞ¹±†ØÝ¶Ÿá‹áǧ;1}Jѧî>4ó†úSßa̯±«§®0ÊØ}³“ÖŸ@çû;gûÁŒÛyõ’¦¥Aîò„òѬý÷ÉßaÆê=ú0õC„mžœÁÖpKn¸a<6¾w~´ØnŸîÝÐO&%n?ÂìaòÆ£@ú`ŒK0ÆÞ;õ£‘ìì-ƒ zkãà"­´·c‰iz—ˆ F¶Ã4˜î 6&Åî!ürƒs¡;ƒÁj,l¨¾~ Ýc裳ÍÒ²Bô$Ëiê­›p*ÀÀº.ëÏëÏ×(²!˜©»(ýUË·0ëà­qÝSÞk´Ýy}]õWâ¬]$œE$Hßx|òåÑÉŸQ|ÐÒ Ã0¢& °iMðËÇv !Á‚äÈ %˜Ò„²‚EÇÉ{{ ƒYÙ~œ‚U/IR¾7(òüò%ý­U=OQÐaŒÐwïl$&õþ\:Ÿ¡`c?ùÐÝÛÙÐ[È­.ü Lí|ŠÄU¶ð×=ú”¼~ª»DÝãÚ,Ø'PuÝâR–°>¯ÐÁFyóÑu-|Ök €Å;Rh>³skvbBŸF@€l(°6½Çöôºw;‡VçðÝÞ– ›š¼d#4êt9{nâàá„…;÷CÁ[€’ŸÐô¥ ìæ6š÷bíßàéxzó­ †6 ¦€ëð¨nÉv_( 5 HPq…76jxøŠºƒœÔÓïw >\2Ý Tu-Oê¢,×ÓîÎä/¯yOØàà={¢ûygî\ FHVª£{Ô“†ó Eö0Fš&Kr{ƒë‹0Xî}Y_ÿ(ÈG ‡ÁXšð²¼x[d”Ï@ú¢úG”—Ç­ã&”Ñ&XèÙ{”sÄ1q—wdYâ²ÆAýñÞ¸> òÐòO³žÃ|ø/Êä¬=û 6=P$‘óº¢ÅÀëL¤tW)m%®è ΃xðñ¸~@ðgT):uÜéœ]J&á#YûC¥',K‡Û“ùK»F~äpE4uÇ J¿ò{Λw“‘¦€‹¢¼ÅiQ4ˆ`e6”9®¬ž|94ÖW””Ÿ)†RÚúl`vðqµ±YØz쟊"‘¤ùY»Ì‡ì˜÷¼GRª"o¥!GÏ"ƒ <|Ú[µiýc1=ê+Ô€K1aÀÓ©'à%qr“_°I³IšÇØÀà´òœlÔd•ÉfêûŽõ®€ekKõùìÔ  1G+›²/~&KÖCüM¶óEÝÅIÇY×@5oe]›zïEÙž`ŽV9‘ÀÀÄì1›œñšh0ƒõýA`Vf™HÍÏKç ­lYÑhƒ-|•ãG !cbû÷r$ô Pœ*M¸wd>È–rv|ÖÙ£,Ê&ö„yoc«O³Y?çQgšø+à qÁæêÌ ”æS í¦ós¤ˆˆ§(P;½)èô4ËŠD•—­Ö“•_ųÝD@›ÏÕy¿4gÃ\¿”‡’E‰›ö–xû3Ñt<ûÈ.‚° &YQ "鯙}“æ0L'ÇhÓ¬bý.'…|l‚ÝØÇàIBc*1ÂaîÁuŸ–8â3ü+½ý¡Ãÿ^âÎÙ÷ŽH#yzn­mO cy>¼g¥zø¾<|S"í•éþ §c”ó¾Ò啇—kþ°“§kù½ÇSŠ$1†bo–'@ ¸,îè<»ZŸ5™l3hÑÔüFbhx3büš²†LfC A{º[q/ _"]xBXA*sxŒŽ C´Šˤºx´!P–ÜþnyMYŠCªËCUEÓ¿dÌfâ@?ª$ö‰Önº%²‰3²w)#‹(DøŒÓ7Ñ)øyOYÁÁŽ"èy°ì"Ycî2KP䨨Q샀'¸›a*önSÙÒ ±A!è`ŠÖ¥€”è’Ï!Wyù±íG–çXðä\9Îå“ÃuºÚg¼}åÈü•.×§%óGE=™ù^Ñ &™„2Ÿn‚sÅÒÔñ)/4çÙyAÅègía·!˜œY¥MÏÙÿM“iªêÐn[&-™D×"‹ÏN!¤S¤<›'MØ­rMVÙ¿ d‘êy;ÐYaÚè{Š.*>.–Œ·Ÿâ¬#µýºn/cxÙIz·™{®È+:G^¯Ä¸67Vjóñd|Hÿœfôf"B²–¾kH § “ ö+yžOY²'5“ãRÌ{ Ĉy.fì%ËkºªÃá9/ Ïß{AŽÅ-ÔX9|kEEŸ¨9Π³é:Mq˜¿IrA¬%àB½µòHÀ¯áÙ‹Œ¥,6ÒŒïþ€c^/.®mš±òŠŸùl_©ÝàžÜ)#å­ƒPÆÃ鿣òð­ßªå’fVÂûlm ÷õaí^ùêY}}¦·°ìs#º›‘O¯0r%Ý­ŒÄýNºë­_Ð]qJ‡S^o¦¼â9æ­Þ[º¼h½äoð:š yçÛä ‘¬ ÿƒmØïKn}«£"teýäz`ÓSá»…ý­2 ^‹i7¸Êƒ=³SóP‡Õgk0•­w?ù@'t² k ¿uÆö`æ-Æ4†¸yz•Éw¢2v#åë —\¢K »ºáæå¥q9Ï¡gÈYJoðüÇ…öf-,—" /SÄŠã¿°¢Àc§=¸§BäÌU²!…A-bðè?æîìªK3‹ÇMârÎ3¦ÍlaskÊÛh#¢Æ*‚¶§õ_R4ËÍ¿˜PÕ’væ0‘áWÏ©ù¸<<®|~„®ÞÊÁ ‡æ™)"˽S<„Ä''Ui##œ™ìx4ÃA.q0•¯¡ÔYC\ÇÐÒz)J(;XhC=GuG%ö»DŽ3¾ %7Fgc¶ð Wø4;x66~·¥ŽB}üyš¼Úx¨Z >µû!¶^s²s]ËÙ¼,=ÑÑpc4L78q*'Ssˆ-bÉà,Ñ"ŽõàÿŸhý§<5×Þ’šžSh ‘ͺƒ[fs²ZÖÓTP ,ø’Ü¢”¨™eY0?Þ$b¯½ØÊ%rƒ”©ðÃ])8¤8Ý;àÅ­šrm2º=gÜг­›mµ˜ˆ}SôRmhåCFJœÏ]J.‚!š KÖV2·2_‰Ë¸R;¦@sä‹v¯ÊüïÕÖt«w.“%_Ê ŠbžòxÎ0éÝ®ç´ÔÔ›Ñ4-8Ú-‰~ ;³Ñ^EÞš2ÅÚF¡^E¼Ó¥ÆÒ”Š”6\-à• Èßì$ÓÉûlQ‹S“1DåùPçíJfŸ.ñ¡\ÊKÎ!ÌÁk­¾h»(ÕÊ[Ì’ vòŠ ŸªI×÷œAAï¸ZIÉÐW]çy]êlÔ=¼Ø)x[ØÍ¦²žØ9« ÅUaFÅ NëZÙ+JZk†ev‹‚KjoPû°èž@E¯ƒo³ß6(/X*b É{ÏIóÕïqj«&lKá£Ü«„|%"üë3áŒM÷¹<ú,_²ÇЕ:£e’rý3ººÉ—@2“ÎùY}öyȕܘdóoç” ãwv„2Ö”"0†õ›ŒÙÍÇ#N½·¼º¤Ìm]Ï﬑¦l^ÙqhÁvÁ…LéÒÇÏ &™ eF•ôK… cõ/4–rwÖ|lj&Í[^‹)7Fä ÝŠc1ÒýauóýYQ Ê€# 5…¹™’ÏKž–j¡PÔ¢¦_5–ÑTY|õ M骥(è»þöžNœÿ°~Q¢ÌÏŸyǧ—þàþv'2›*•Daη%£9ÁRkI ô‘™y…°£(ñHºI*pÙ¢ÄhÆëì»Ü¢å¢u›îk2$²<ìhªi% ¿¢oâœDîkÚ¾úWâWÅŸ¾k?­ÖƒÈ–m*4ÇÐNb¢al¿]µ?NÆCHXI85ÆZ¾†S)Tú€%ìäó2åí:Â×µ)ÂÚÝru Æšcùù….í£­~—ço+%Ç+>œ“b])ª“Ë\Û ÇCy(e¡\µ·öÐ8¬xHá%ü«<ÞΕl뇩—Êœ\ fL£b´X”„<²Ùf®4]ÍÜ \Щ;\»å:ÏsªoB %´FÕ×¼TÅ]—ßT”ñ¶Z˜Ý˜5Y"Ê–Œ³s“¯°|*÷aŠªþšKÏ‹wh΄ëŒÙÇBTiürAsE’¹Ô8‡å> stream xœÍ[mo·þ.ôGè[n Ýv—äîrQ´@Ú©ƒÄnµ Ј¬“d7zñ‹dYýõr8ÜåJw®€†¥;¾‡Ãç™Rï÷›ºÝoð_ø}|±÷›WÃþÙǽfÿlïý^K•ûá×ñÅþ“ChÐ(©Çfl÷O÷¸g»?˜ýÁºº1û‡{ÿX¹ªÃÿÿ<üzØ6ëÑuã¡Óá~]­ÝêOU[£wãê•Yý¹Z›Õ!–?­Ö±âUµ¶¦©›Ö­z»†cF¨„.±Í+ÛÃGëV«ÚJ}§j_ÀÐ_‡Q ´][çWÏñ3ÖJÍ+œ´iL¿z£XøhaÛQgøÖºZk@»ú¡Z÷ØÜ¬þZAIÓ™võ¤²0i?¢ØÔ¬7«—©wjx˜ EFí`ˆa0¬Bçµ aí¶6nm›zhÇ‘Uù „Â-jЂR×(|Ûò×ðÇO+üyƒ?.ñÇ[üq?¤õë¼âˆƒô=r›Ï©0u¼L…G¥–©ûÇÊ£Úa©÷€{zÿ,Õ'©ú£Bo×92ŠßƒÂ@°ûªþº$‘*¼QIáOU,EÕ›¡nIÃßíþú!¿ÚVÇ¥âb¢ãóÒŠ³Í™«S­è¾ÖúŠ /EÇ[íÕàÚ‡w:6<)©õ@&L2§ê+)¼‘q.K+LRœIÃc)»Ò›'ÔãÐžŽ¦ :qÖƒÜq@¥ 5õIjz)M7™h®ƒ“ïm2ÇL¹=ƱrƒTV®-24f4€£¯ÑÀZ_÷ˆ}°U\—©,7žà5ÀJ(VÿMeaYep¾Å­éW@v0öyhK%wФG=úÕl†Ý°rÃØ6žŠ ­:ˆWÜÕù‘Ñíû*lÂ)|ê[œŸ‹žb»Ž G ÀÝ’£àpI)ÎQ@œÊÝØ¬~ ¥vwØó¶n€ýé£ ,&ö³œŠQP5¶»@Ñ{Bu™:,–>ÒÒ_Ú ¡Š­k'öôwÁþ7‚á(X€yw‘xÞTt»àú.…[ÎPÔªAÁ£a rácך\~OƒIoØÓ×f „Öáþ“¬qWdC:2d·ÎeûmÑÊ·8—lÛŠ²¬éÈ'[Oäþ]ÚFaR'2£¬Á…eÀÂ䉫‘/‘É™÷Ù|Å`X%éôºÜ¢°~óLÎÐq•îj¸Ü3­Q1í ý60º¡†°‘ÆuUfq >JÛÓ¹5vôSÿæ¿a˜pv×Ì¡¥Þê6ºzÔÆXfÒ·©é…îD[ó®K=ìc„OG©úsiôÌKH¬wo÷áÌbïwÂ( „£èì¡qµ mNañãYês,”231öØ-Œ¤È)1ñœ¼‚bÓf÷POpazW·S¼ø(†v?EÎ^³µ°÷Td)Ä]d§œ¦ìV4E¨qƒ§çš9âx¶XŒu§Ÿã±Æò–>ôÃSþÛW†ú-Õ͘-"…í­yÆú˜„qÜ Hv&Љ2ϸ&.f1ã@7ôx;FAéÒ„—(Æ;Ö“ jÄF²Ëv¬­èö<r£ Æ>!Yb1;Œ‚— 7aY>ôUÖï…ŒŠõ}-Û2K5`nbvE÷]®óà‚’ãÒ‡É-³Ô-*M´EnØÕ êBã¸#j æè2XK\5ß³0A¤mÞ1Ù–MOù/2‚H“±=RNô©"²g^Cn¢UÆ¥êœ.•¤À¥àühà;¼žû¿8¤0ï/û.q–Óò3¼QÙ“m) O Ü%‹v©°kyÑ%`¾3yà©0òT>ÑÂÍDr 6‹Dq­ ïJlw"åI´™‘C(;/é"MxZRÅ™ðB >3ŠëÄY8¦XzÓ`Ó*vMMƒåñ£r,æ‘9&ˆá“Œ¡:S¡ºè==C™Æòn×@ÊZÒqÎOáPÞËOÍù`ÎOÎ4-ó:ð;ñ¡d¿Yc¨vçæÜT‚ ˜Ýã°­‹»^<Š‹û`ìBIó¬Æíži²Ô´!oK“+‰6 ׊PPýN0¥a2—=âCê¢rNÇéˆ^Í]Ü qZrq?h1ï>s°ãHs(Ró‡ŒIÙ›=Ó¹Žv&±AHÌD‹›dqæAD†4óΓŠ[úÆÝãúÆ„'ÊÑ@wIgwÀ?þBßxðÐ`Ø{FOèroì›ýboHŠÜ/Æ.PxŸ_Ì.1¸¨vŒ:e_ë‘ýâPñ…~±ÁÔBNv»úŤõ‰_öö~¿¡—9ó‹}OFßx¤ý^Þ·ß8˜ì¾1Ê=à{²«âr3ߨ·™o<Ö¦äǼœv‘×}cõ6f¿`{dw6œ„cÉöáä7²(>£3,'c¹ú(Ï6…Ä]MY§Rˆ×Uâ‹X¦ú0I¯Ãs4¼Ç& jý8\¨ÑV⑤ä­‡´ Ë¡v¿Òj:ñb¦ ¹ÃWN—£2Ѐ¼_®†f²Ùb3° ž¿†œåít”CTuB¾7Àa±íÖæ Gv{ F™ì›`=mm%÷˜„Ù°l¸¾Ü ùÀ%×ň5OŽÙïiW Ôþ6 ˜MùYí` Fé‘«^bÿAŽ{hõ6Lt.ÆAKÈã(®wõ*™_Ë8‡¥l/n*¼RÕM8÷`9›˜¥eˆYÇ©õÙ¶›¾Av‹*V÷¯x™J¸ÿB'…M7Ð@Ûð “E ¡Ù²™ž^†‚ÈW¸: Màˆßkœì'5µwVp†¡všøC`®SVñ& Üf6›AY®Á+€ÆªüóQ6:-§ˆ eÄ3ÙwôUY…<·ÏÄL.x©9U±ÝP”2‡iXó.@¬Cë€Cs8Á'êIÁW=«({ã,Þâ‘B›íb"’ÌßÃ)r ãêNB¯-#”é¶@('ˆ~L±%»*Mr¹£®£œ[Î/Qz¶ %3CÀ6ÈîlšÁr†ŠÒRo”qQ¸;à!°t­Ä‰c›Ûpè"–ÃöBëAsq.â ê8mJ”…úø*¾A ‚ Ñæj7ÛBºìŠ™ÇÞ•EW¡ ¬‹l;µÑbý”Ot˦6A•Î:…†œâ°”¨#5"»; O£ƒ¦kFÜíqȶ–xX™ÙlwãìˆÜs­-¸`½áX¢ÁCi(q@^·%•.Ýï÷šƒSD Í"ÙÐhHnÈ@§ã¯¨ç÷¸±7±-F–vNìÄëeÙÎõåM4Å,PZÛ¾¹?£q+Ó}ýÄ8BŠ‘QDqß„8:Öôj„Î+a]2uL¹žÍ®I>-÷FYX²¨rÚÈeÑ{”Œ,Æ z!Øp| w»¥i3#ˆí(+èG3ZdöĪY@a9Ï'‚ŽÀgŽÃ²:¼A¨ „U9ØNþ²oçwP„b´ >'H?f>“5™Ï¤²œ#óæ=N²šWëyÓþ¥³a“Ð^DPl< ü¿ tzf©dP01ˆwâyâP Kâ°ø %6y‰2Œc!Ü’;E¶wœ…hÅ.Ù «Äì€4`ã·±Qågó Iù«Å”žzØÂ. Çðþ¾´D3@DuÑDƒZz·CÎ’Ò(˜kŠ wJ·bÔßv»$ï É žÂHŽÎúÚ§ìßÒt„ÎÏ0è×½pŠ;}k¼ @Ä3ŽÍî$ï ‰¨.;zS  ·µë¸Ü*^„Í ñ6BK„â6”Õè%èõã"”l*º™(PgŸ¶*¦ª )z»I'Ý ÎujËbbßW4;ßYsÝ’šÚ0fè$³'x9äLDRPÉ Âì}ŸjÑÄÜxeÊ†Û .xŽw·O 8 Îo[÷:}*˜äqÁC×Nap´‚KM‹žGù¤#B”\› ñæ;6÷£Ó{ˆN½PÉB&~]LŒZ+=¢›å¯ì¬ÚÕèX¸6ùY“G¦9n²‹°˜ˆ‡TÓ¾_J‚Õr!VË Öà£^¤…{Ø]Ñ(xU_„HÁ•Ú‘ ïG =ðÙî Ý¿¨¶¼¦ŠìÉöW®ó«ã{~,¾¼.\ŸÞ¥j}å:UŸ=DIö¦›êìR{>aöf0ÿs€ð&p.xº_þ\hXüÛŒ µ˜û^Õ’Õué‡Lãó׈ùͪ¾Âï(ãð?{`o$GÕ?æ»ïfMSväBÿå»Y××ÛæÄùœ„¿kZxBáݸŒG»¿ )ÁÀä]Èn0ð(ïBþ/ŸsÌbáUÙ¶hw¥Ví¢Ü;ûô7Só÷`|ØfïB比ÕÃ0îSxc–½ ïBòÇåñã§4Ò‘†ËÂkµM©iñAõ㼂~z¸÷ø÷9Jendstream endobj 268 0 obj 3547 endobj 272 0 obj <> stream xœÝ[Y·~_øG,üâî@Ón^ÝM`[²åKI¤5 Ãöƒ´« –veI+Yùõ©ƒU${8£Iq‚ÀÐz¦›G±Xüê«*ÎïÇã`ŽGü/ýÿôéѧ·çã‡/ŽÆã‡G¿zyœþwúôøóhà <âÍñɃ#îiŽg{<;?ŒöøäéÑÏÝÔ‡nèmçéÿ›y‰C\¦îËÞu_÷ÛôßÝé7ÎMÃ8.ÝMh{_|®÷¿˜!ÆÅÇî64ó†úSßOaÌ¿cWO]a”©û¡—ÖŸCçÛ½³Ãh&‹í|ñ’¦¥Anñ„òѬýõäX£±å}˜‡qežœÁÒpI¡Üp960DÛmRÇÙÄÈí§~ ÇqBUŒÃâæ–â·Û9td2Ö6v?öËÒ=a‡ÙzkºÇ¹ÕKXÇ0ù%Úî>hb7ÎÝ·ð>Œc„§$™½ïÞ@¯y\÷º·žšî¢˜;M¬ëΠÿ´ ó@v˜æ`»KúàLèîÉ£B¤r Ü2I£/e>—þ,Ûâ§î|r>.I™Ö—Z·Zðñ»£“¿üܙ޵öÆ„!N`uisþ{{‰B8 ÛòüÒÙÝ…m{†/àCy¾žñΰ¤_zx…Fn~ŽFÆ_ø:¿ ŒtÚ;úÀ– ’@NaØ—½Ã Íñu:¨ j„ϰхôB¥û™,ù1Ø$hiS5é0Y }F3ßçóƒã 4ì›jç?ÀHpüXa~©Ô‡eŽ3i qa½} Cáép¨AGGŽ'º_¿À? Eø{‰P1 íÆ‘–»kÚú¿ÞÅ?¸n\›E‰@@hãgTtìþ˶#l¾ôz™›Ým=¼Ô‡/òCÚ,zÚ28Š`w‘Ï"-Ó¾ƒEœe>̈°ñ¸oø#m¡Ñ÷0þ»!0„ „€‰üÀE£¾Hçuœ§ÊZhĽÖ"snY‹7 ™MkÙø1ÐÛïûBñS÷¤/FÇIŸÉS±\6ƒ“ÇÈŸÒ‚q\X†h(\5`Q$–C5¤ÁPΓhd©Ïžy¶hìëuÅ}Bÿ`Ü!„1Ø֪΀"Ñ)œ¼9Þ€ö‚ Œ'zÌz iãùàÎôêFGxƒ-Ö”w‹-GLEM íÚ.<ÍV^|ä9q¿ã2S77“Ê^d7¦û¤Ÿ‹c늷eyñø‘ªYCŒw4 \~’õvT"#2ÃWËmy oGT¶v“lš.ÐñÞ…[;;8¥t /z…[_(R AÛ;·gQá®Öº´9Ï_êC„µÉ“"Öl¦ÿDhSCu‡C›FÚ³C ú„ ‰·Ÿº“›(ÔÝî—O?õ´ÐàJg³ßì2¶½¡ÍlƒÉÂ5€¦È}]“EZeB™´V6`-Ù°qÕ2×ð¾¸fçy®ÙŽt¬p¶ XYÙç9~Œ1› ,[s1©ñyɇ €.ŒŒêKô¼'L©@Ï2]Ù z‰œQŸH °ª‚7ˆ2z¢øå`C²h¼›·¤ôl‰zÊúö£™Y†iÅMVPvS‘áküzçªPöH_¼Hoew/´ÍóüðÍÿ ”ù?‰¥-|4+Ëh^§ÝÆÃôYG†´H"¢°”ÁÓFžl›Õ')öó4*w±dÒW’l䶯ú€Ø1±5ãa¹ÔCuŸá ´0i仃X¡8*§ |äxÅ®€œ%]o™‰æ—Š©“Ê1³dŽID¥ eÓ¦é° _ Š_¡NÒ‘B j ݤ39æü@c¡çøOEðéëU %\ÜÞððçgy(´ëøz&6N’šD¦ñðÅŒÙá…± +à\ÁB+x -Õ^ž–Ǿ€L4ÄÅÒ¡#@®ÀѺ›åºÎf4ªKÔã”öìiòÜ#èãÄxWÖ€ 'Š@Ð-,E›?tŠä9PˆÉ–>̓­QDzQéH>މ¢¤ï^¤üQ'qPÙ—#‹9’QèsñlL¨Jc!¼W@jJÐXœsˆÅ5Å)F¼\ß»ÿL§À.¨ÎÏa€¡¶<3b䪋m˜K/fq`0azB¬¥±õî£ÖáY1ßÄ0’ú múbQb Ø79ód «~ }l‰$m,+CLY] E ¤CZšf‰šM!±¥5 ùwç×õ˜¦/ör ¿ÌÄÝÿËÄ ¼CŒVyP|cIÝXÏÏå\¾ÆgA7Ýìdê &Dúþ?îÈßY—ŠH7å3ü¬>Ö“‰–§ËúHRn½ô…r Žŵ/LDŠ®{"­¹çÉÁfmÖkHlÅjÌ å·.HŽ" ÆQê[†…†&¿|IÂ8çKŸAümþþSOñ'íWód€c · 2œãñšDÐA€mb,ÜÎý "À®¶£qÍ ‘B Id-xh¦ÓÏu‚}b•ceINÎøw ?f\uƒÓX!Ÿ>‡EµYþ;r?Š àÀ‹…Y®N_X2Š4¶pUœî¾q«˜µUã,™!®¶Ù}—Ò"nä¬`å˜â  UžÚ2“ôŽÚ°ÖÃÈ9W²¢Bí¸¥gi¾ÑÔFe8Hß²èì¤Çæn3Cµî0†*t—Î †¦fnJ¼Ålm´äC’¸$ÈE¢pbÅz³©HÚ*Ð8ÏÛwV¡K?ˆ¶L3ZžLf€;h˜×îŠp^5Èk+þy\è—åI|#««‰xJ²)>UUªIÜÍõ”ù1È‹’‡Ê¹ˆr~z2qDœÔ45ÂQIÍ„pjÉÐ> Ha†}J†tÛ>p•óŸdÉ«`w9*&­cdÞ¤I¯y+­Ã¾k”!PîÓH‹×½‹¿ñ’â¬!ÖŠØV±"Ì‚þ¤ûO8ùl—)ÞåM¬0ßÂ.Ìß ›HÊ×…Y#“²<б×+*’#¿Ä·×R&±ŽcÈGXË ±2¾ŸJù žãòü˜ãæ"œÂƒ^ÅøôÉÖ¿ÁñH–+  >Ô®MŠŒÞ¦«Û/qMnndqa6ÔÅýYŒ·‘¬ ­U¸[â"ê’Hó‰hníî,U¢cÏñiåÇPæÑTħå¼x/¹éÊSìv³§ ãÜrl¬—Ö*;šw¦Psé‰ãá=ÜJ,˜ŒÞÿ†–ô Kͪ¶¾·òNå å†íÜ™À™ ê¼+ÖìŒTÿw#Eip3&dļœ¦P’^U^  cvaÖÚ9¼ÈS–~ÚÁ‹Ô7xµîm2‡Ëx‘B2é˜Å+ðUþ†úd{T{rSÞ dâÂÑu>L)@›õ>ûÅ‹>d–} ý²S6¾*Y,áä6ÿ¢àà.%6ºð-æ—”—¥ýºÄ!G<Üqn^™+‡ÇÄqŠúäÁ.¬b@¡VXQ­˜Õý]Áè“*ÎÞ®Î:›,ŒDIÃ\b¨œZáÐj~-%œ¢kºÔ$bl—¤JêÞÌV–ø-±öŒ­2=•QÖ‡y “’øØþ²à(”WFNû¾JØN¸x,ηjH?áןñÏ7òÃT5úUÓ;Ê™V9žr[¸Ío­ ø›üðuaÄ›ÂO¤‡g=_0ó®!‰Ž®(?½je‘žÐ8³7u­~»¢õTæd÷ýÜð\'\•î¹løŸ¸‘¤¦Æ××®°w7$5Ç¿ú?Ü»³–h§Úðq±ŸÅˆ2á“–Ö¯5ƹhS†4MPþ‚@~ uãdXðŽ¬¦%.tcv§eF½‰HG~ üެܳ‰=Z…´¼óU˜Ü61ݦ·dÒ=ö*»Y_ç'w¤%Ímm'«k6ïEåPÑ®~wPsé9îH(ùmÁuLT¬BÕ‰!K):NdÂtäªS”-NálgMÝv”KVªkóŠ×ÙÉ⢡[UcSA¾Í`hÅInq!Ù‚þLL>¥¨në%®[¨K;p“ø$æL^BŒe ‡)ó®KC‰Ü½ÿÏx$ÛãäèŸðß¿7˜endstream endobj 273 0 obj 4027 endobj 277 0 obj <> stream xœí[Yo7~ü#„¼dza»IöÁ‡,dãØYÇÙµ•A,dY‡a¶%Ûñ¿_ÖÉbšbg_AÆ#6›,’ůª¾ªy½[¯›ÝþãÏwî=éwO®vêÝ“×; >ÜåÏw¿ÚO—ZÖ±ŽÍîþñ½Ùìön·÷a]»Ýýó_W¡jW]Õþ¾ÿ]zÃ7Å]\×CziÿyêøuµVªfãâêËÊ­þUí¹Õ>´SíɃ'ÕžwõºnŒ»Z§'ÎÅô0½"}þQù.}õaõSÕ4©uhÍÓÇiè¯yT—úîù0¬Âwx²¯OžÀ¤uíºÕý4ŠO_}Å·ørú« tôÞ%iüêiµ×Aw·ú±J-uëšÕW•O“vÄÆn[ýßÎ÷s£J‚B¤QÛ4Dß;ÚÂ0Ø-Lk÷kv÷|½î›i+ï'¡`D;èWÿL0v³z>…ßVðù>.àã|\ÃÇ]íýþ<‚ðñ>‰;8t«Kíó&7>ׯ»¹ñ¥6åÆÚø®`š~u mg¹ãݪ‡³Kû~¨/óãsm<Çqú€ÓpÛEîxmE m@íù{ÚYW¯®ôÙu~á`®ñ­6^åÆß*i…óIZÒv úvöÿ69ˆG:žÁÏ" =ôGQÓ 'þ¸âÞ{’tǪSh׃ÃîžëÖ}›¾ >õ•§Þ£ŸËokš”¶Û%É›–ç“xíê¦# °VÔ¸1M=\iR¸©°ßâj±ôm¿L7 Û’5éAºüuÝb´ Ž-*b éßÃe~‘îÒuÅ{qʃ=Š{`ÚŽD·r9œ†oåmS™ ^—¤¾<¹OÈGrÓZxCÎ’ð?töÎö®ja9]‡bÀ÷4nêAò€Øl¼O›®8©+¹Ì¢_Wr¾§FtÉY¼z ˆ“°ÀÓûˆ;eèT!q-n;  y'SªqÞÀ¨1¶ãåÈ+'dö\ŒëÖíîéÅ%ÂfÃê@¢VŒëRiÒÏ+A;«03\›àp³@vxóXnšGìX=““b½ ðòH.:iU©ÓÁ=Y™ÃŠ6è*,˜k]ÍÂw3¬»Ñ][Äî_àÏÿJìÞ s»0W°€,ͧÀÛ›Lj¸=€…@ZqÃwP€´`ú:‚ó ]ʯî JPeSB x©ÐkPô·‚=8=(ÛÌ# rm`¯g¯Gß×£ƒBX¿EN‹/²ŠRåÍ”#§1%t5>5žY‚ð04²á0ÞÑ j•ð3ížÍé[>ôà@µz„p ÌÙ„Î࢛–‘äW0öyÖ0Ê;·vuC¥·vþ’^óæJÐɸ¨öŒÍ·²nÖ,o‚R>< XeÝ/£ÚèØz¢*&ͪxOk‡˜ƒ–ÁÙšµ ã;zªG$-Œ:=ixдÙꉖòD…ºðOi<ƤQ¼\|%È+½pq¨ɯo:Ñc;h¬ØDÚ,¸™N­D„M"”Ÿ3ܤÙ1X³}µ´´±ªb~ 'ÌŠ9§#2üÐçáYop-¥acëèé0õ0NÈ` ”šûBŒ^¤B‹Åºv„?„íIÒ ™Dýh¶…„­:° ›Áõ4sÈõV€obÑAΩ‰ð£[–‘…1`'ê¬wÙ5L^&ªK]'4u9uÑŽÈùäCÏgÛçâ0ÛjXíMp— Qï€Ï‘v® F\>6ñŸöt¼gÚŸÒí¥Dš¤:´.Pà3â˜3î&«E­âÝ ÙÛò±Ÿer hÙÀ­Õ ÝD ;ÐíF|_}¯+ù^Nø2óÖ>å㪠û¥JQè}Ö>àW“••WÎ"é ü5x°9]zC÷Â+ƒø©ñcí:g¯ºË^õI.Üö.,n%\’÷y^°«F›ñJÌ)•1[xJIû §€ä‰ÑøÙ¼ŒÎYeVÌ#ÝÁE•¨caœXÆù‰O½…Qóž Õ±g„ºR‰Ú¹VÄ3Žy&žó&o~Î]!÷"âg øX=Ë‘]j§œ–,›Ñ-Ët¹„àˆ;:h6e¤> D.ÙXµö|`#.%¾ì­{>Pݸ ZQµÆ`8 Œó6cGiÕ.æÇBŽªnÕªd$J;j64n`j¦Ù•xÆììª/Œ±¬ÏçjÓ9‚ÉãFBæ„U䈋o¡ƒöö[SËšè¶GÁŠoÜí#eáÏ_áã;y`H¶ß5Z£ÞÓ-]&pËk–ƹñÍ\P–cºk ÊòWsAYޏÞT3<Ù…jyl^)¤ãæ× ~˜“Ç®{Êà™e¿ÓÆíx6?âeçì¢ËxϪüPr‡ffS¤ë•vŘì€qmñëÕä-ne€2º•¯£ð–;3?â&x¾…6-Ì6uþöÿÚø¿ÖÆÌ°Mµñ0kÈ ð|¢A²WóÚhH›|0y,¼¨Ru¤¼¿×³Z‰¬9f2@Ûm˜©—a_UÂGÈ7Õ¸•¿ÑI†b=„¡·"tÐ{½Dæ-‡§CD[¨ô¯CÒÆDc†Ô«ó¸$ô:¦f·a]ÑÜ“ĆÍ‘]â9OR<09¬œ%Jƒ5<*¢mFÃÿÂ÷9 gétÑ΋‹êò´4 ;¶ú.ž UÓ¼””0SQ43-ë)­ðsË,Ëòþ€Þ ²<ÂByãô2e–ήäÌr,ç\@?›,—b9’ ®8N:x3ØÍøñ™¡8S“‰KÈܯû±£¤ÜŠuŸ™\QïXˆ¹ ì•Æcx8Lñ1Q%pç!%I±‡*]Šú”ùAÜ™û† bׯHà‰ø³§Ñ>U]\£ž›&< I¤ô&È4Gñ6 é¢+GhbËG°ü‡>Ì.2¡žÃ1¢>n}´D«!Ç2ù‰KÁ}wŽái%2꾽ʣ³šRG*ÈI¤ú:"ŒÔKv¦¦ˆ v‹^,•€™¯3ÛÅÜëfÌsûz[£;¶I$3fNéÁ‘TÍ åB&8Ìs^.,.IgrÎ>.¿EÁL“nM½¢ óõ2-ÝÙ[ÕË„ÈLzüµÏ«Q~É8´u4Sö4a|¸-Š#L^š[Iúóôvïp¢mÛ4Ó ¹eßÅÿìëi^9uÏ…œ|¾¯pïÒ¬{É)Ñbº¯é, Q³ÇV…ZëS)hkLÖP}EžØr•LŠö~{S@x9Ë.¯€‹Ö x¡_å°æ²j‹ó#;àbH˜ÕŒœˆ­jaû¹Š§-Ëx,ï-FÁe—^pÙ Ž›­åá89ƒSv#¿X2®‘Ña'0­Ú¾ÞL¨Ï¥mú­×‹³ªcuDC0´@0ÔÙª‚WÍÀ‡Ö–k-U?5 Dý8Tø#ž£Ô%'·/oò4Ÿ g’e¶± Mx½¥mFâJ(ýƒ¥IúÑvl©ªlYÝ\ Kœ}Ì÷EöîJx“gxš9â†.Ð0÷Ÿ{”…꜊s„9Y®ÁéFe:×zž-„%n ñ¥&BVÞª±.™t«N›¬Ál-K)£&dTÒò|Ïáû à þ€ZÄç(wr¿ü2]¿Õa'¦bä_(iëB7‰ò·N+±.Ñú& ín8óeiJ›ã|'¸éÑëÑ: G¸’f;RA3ÁÝrñèB…Í¢z‘åHEÏÆ j¢¯Å‰E/p°üRg2×[Ç$5ªËÆñk¼}rð‹InIN1fD”ÌÅÌ#óWD@N“åøØf’‡Îò” ,¨3%ÌÔG!œo8†)l†ƒcvÁ;ØÑ[¹J0X]Ç™ÖÑ™³¹½AÉ>VÑè~5>}Ñèl(‘ýò­ þóàÏŠäG1d,Æ‘ÆÃ™ÔQ‘‘ o÷ÃWo²}[V³BtÑlŠ.~®¢ËaUÝŠJð6˜ ±/Ñ•ž%¨FN»˜X3.þ*Œè¸ä_Ib®{!ç…¼SIa¾¬RPy$~çz§üc,ã@ÉÂm$—¾ö-sFÆïœ£ËIRbêur2lÉP¤h(ÿ8 p·«ª©h9rè¨"ø m[ 2ð¹¤D«cŒ#”•Ú1,ºEŒì…s- ªÁœI(~¬ T’=;ÉCaèöÒ¸NÏ 7üøâ ¹ÏEl½åÖñ—“‰=å°d‹´]ÝØ¼Ÿ!Þc )x2O›`ºóa:·mõs c}’±¬]Ðìô q“N(œOôc¨[À™Ûg_2—!ÑrӪ׭©‚¹š6|ç´âb/„;µÛ⪩¥²ò (ÈG©£* 7Õ6&AŠúËJËãF„£%s'£°¿MÙœTÌ ïÏn±!Då@¥pkLß ð5±áél‘¢ú€ÖO )q¸I“jl$±±žÁVcgbäÝ )?C›Ø ”¼Ë 7øu7lŽ]¨ä‘ãS8²VHS§ŽS6jå¥ü  #;µE)óAnë.Rq™ú9n£¨# ey·eõ2ZO.‡ú\Сš³¿÷™æ~¶‘úŒm©àU¨³ÑÒñì^›²…¬•…ƒ¨`6€ázzþùð\ê'ë–‰]h¥Yþnlb´FÖEÒ¹30¤—¥-ËIÛÙÑ·:Nþ‘œ)¼œ­Z(¿w‹æpRüéGËO•«aÕäjT0eòPí%Æ1_T{C„ŽÉfHG—…\k£Ï†í^vÖµÎÔ.Þ+ˆnü}.Ëab gÚ8›c) ·$Ë‘‡U¦g'¦\£ üqq¿nZ4Ÿé‹«ý¬Sñ£óXüU±_ö Le3Yû]Ù·Q„ŸìGÎßìïü;ý÷_Œ&× endstream endobj 278 0 obj 4120 endobj 282 0 obj <> stream xœÝ\YoÇÎ3cä7,íÞÑô5= 1"[¶å+¶LÃ0l# H†(REËʯO]}ÍÌr©#AäîLŸUÕU_Íg«¾S«ÿÅßÇOnÞõ«‡ýêáÁ³E/Wñ×ñ“Õ­Ch`<éBÔêðÁ÷T+¯WÞØ®×«Ã'?­‡[w½¶ô{ëÇÐ…qX²1ë;›­^n¶výÝfkÌÐõý¸þ ÚÞÆÿ€o,~Q]£ ë»ÐÌ*êO}o˜ÿÄ®–ºÂ(Ãúû´¾ïnŒîz5hlg‹—4- ò5O(/pMë_?‡=*]îÑ:ßõ#lóð¶†[òÇ Ç•‚!œÓØnnMßy·6[ pß÷’¢ïFã=lÅNkïð±RÚv:à:Mç¼õÃúl£»ÁZ¯/`/Ɔѭïç~ôÖ®ŸÃ†:¯6ëÐg„ jýv70A(𾂙üèµ5ë—à©ZŸ+)†:þÃØùÞupz§×—ôÁ(·¾'b«ërKX’í‚]ÿš÷y&ýym£òÖ˜´Ú–<’„¥ë˃Ã÷Z«™ã”rÜ*²Š8}†òqŸîoˆV´$=j’¨#øX¸¨!¶y‰Ïz »~ ’DÏ^_"Ép{çÇC!•zC‚Hß±í1üŸ6P°}\`6Øø‹ =%²ÉÒ³G¼x€ˆ¡à~–äø{|ãhÖ£ ï¢T,Žp‘…ý),)¤•âªÞ“­Ÿ`M¨Œ⇛)úc¤¿é‹VÈϱéY¦ÉÏkà3ô‚½á[T 0 ®Žß>€¶Êã4Ôà mßÃÙÆÒ5w9‘sJ­yïÓV§ðî."Ð"ž¦NÏQCpª\Æqú´4l+x¯×ùäÇÌ V[gÔ…‘)ÔO„7¾Çí›F†HÊJ?o6F:˜±§•î%nti°²03ð&'ŒÇù _‘R'ò…FBâöÎ8=RÔ¾À‘Tz}c“ˆ0”R #á¬#k‡+SËa€Á`](ë†BBÒAKt‰mî•좽Ã7 r™^¼¨¤ª`îÛŽ¨ûó6°»c €‹™•«—(üñQ-ž-\q¯<‰UîBâ›/þ”ex+ëŒ2C{%‘!]†[–#ˆô*•H¯#TÈ”-V)krÈoÄC_sbíñ*æ°VQ%ŸxÂÏ“Ô% ¹OÓH¡ôóÛO¿H̾©Œ»* 1):”K=Ú~’ÚbIǵèáÜ÷’4e}”šŠªÍV¡Ô XÂß6†F6$>=ðQ™²åœª8Š`¢Äµ :sä5Ké£Ô21+s"ŽXÈ%.½B Ñ~Q¢¬%´Áaʯ5Iý¢x¡>¦Vef NÔI%oâ9€çmŒg‰þWÅcñøÉüɜͷFWú&é¦|¾ k#rZÆ9a+SãáN[ÍmTµµb¢ÓhÆÒè *lرc7ÖÓ‰ôŸÀ€(â„r !Wâ6~ýÀ¡€Ÿ—ø—;Ú²ò$SÈ­ãW\Y±õ¿²dœ¥6çùaîx\Ê<|žž¤‡ÐÇ:KŒú;È„îI„¬3£/ÓËüÏ,?ƒo0 ¿ÀØXéÞ0½ô›Â8Œ³ýÆÙ~gµÝЬ2¢k3kû„†hÞ2JËÖõ>/»LWêæW!X»Ò ìH[íe «ÃBðM{`†*ñÛ[`V16yGÂ}à[>df,-ïDÉÁN ayMû‘&O£m‹ÇNãIn%Ûe*/Àú¤iGÏ!=ÃÁG2%ÑÛ+(™Þ¨>i?(ªK Ńú`1EôѼîw[kU’§ýÄÓáú?}Y¹Ãˆ*@£4 ^‘— ®>¯ ã. ¦}Oò´¡DýÇèHB7¥G¦®&cÞž=43ù¨ExÉ «¢¸ÐFj(V™¼ž£ ±hèô#ìä»È½Þó´—Ù"Uj”_àðL²¨ƒ o)–ŠßQ£Øk #Öé4A}"¬KB…Nî`!¥“›Q–@6! |­s¦›5΃ý ¹bºÞÄ`æŽdO…È®´š•ü¶¾Y㕉<0Ð ·QˆZŒ†ó†QÎÖÔ3ËìýµòêØúK§Í*>;ÍsWÓ±\ÐP&°†*ݳê<†J¸ò9:I 3Âýaê@^î£û­ ¿ÚŠçuoÇ,iAéŠUë.L‹ÐXÔãhî.'X‡†e¬ÐBTV,K^VüÀêÊtCŠö¢îÓŽÎÚ,¡ÇÚ‰ó†4Ò=Zü*½$Gqå~V¸¢mÏf³Ôšc~¥#ŸÇ»Æ§Õ.B‰†EE›­ÈY7L—ªHÜ0Ž·â|é×p»¬Æíú¢v»~¼Òí²£§¨Ç1~G—‡¨ËCœT~–Svñ.|¦d68Ľ¸)ÚÏOøãsyØÍP>eýKÚ-·žnyê6>®S|ø*?|9çu–$Ñ´(¿4$‰BÏÞ,¿þmŽ\§4Ž·jÞ£=OŸ¤†OÒ³û¥“,¾¨üÝjïˆwÖæôÄ"ï2Ÿ^#ðrŽKÞ½<|62ÏF§Œ p~«bÞ88eÁGdei|ò1æXHø%e?0#8ù;cϸHÂý0ñ^z–ÖAÖ™é8þ'ÆÌ/b´ £‘%rƒ<úwÈ0´N%Ÿ–ƒi¸Ò¦qx¡ÇŒ´6†Ô´Ó(s„8œMÖà¬.Èšlµ¤ µ†@P+„Šc(¾ßÄ‘5£ŒMóø†¿:$¥Áÿ{õpÝXòPS ËêÊw| ¦ÂÐbè.¡®³ŒÒPõ5Ø//S Z]Â×Mñ*(¦RµÃn…ûýÓòíe±Pá.X,Ñ ÞQ˜¼- ‘(¹íüëT¸\ArÅZÙ0H™Å`ÉGè‚zí~ì¼óo¥X‡2Ãÿ¦X¤VÑ s4ž¼ÊhBA¯k¼†ÏÛ‡:Š‹Š>ôZ©å¨\Ш˜œ*˨wñ\ë…Bs³”ò˜ÄyrŠ–È‚5 Hºè ûÎ%[÷Cœ Oß@úG”FR_o;Êf°œ«we5ÉûÐùV¨Ô>DÒÀ$l˜ĖQa\ÿy“¢?t )¾5”ì>¿’ñ¢—LT¨yò’9ÈÌ*ú²'Q‚aãÝó8FÉͧ }µŸ*Mvåpìl´úL¢du^'Ãc2±ÅûÈÑM¨å|£:¾ ]ÚÔǰþ fw(ÔFÚ3ö¾“Â">LÙŸ„ï†ä4LFBŒG`í\EX±² ·€4¢HŒ”EÆH [JÆ&lc¢cO̘fÛ£í%J¾5ÑN™¯› qL5qü±()Ÿ÷ÃL‰–€XcQî2Fmä«r•Yµƒûƒš¤ÍÆ4j®äY ‚c0²TsñWËRŠ>+ׯë’ÄEŽ: KÁŠŠiqRr$ìÆÜã”gG9AÌ2 ŸÎgC[¼–Qáq•è¼Ì’²£lŒ7Üúß3åfÉ¡bî^£Zʆ$ŒZɆ۪#’a[È­! nŠë‰&üí#'§‰‰ÈxÎG ž%Ö*>•{Ì%"Mh¡£8 •Nù"aܲ8HéÓ\ÆßMóNå 6Œ]õ’Œ„-R£ó9±†MV÷9bzaYBhRÍnO³Ú¬…íaŒfg¹à<º;…$÷r\üz›3eO!³{Î0}²%½»#“*tzØiµ•*1ó “3Á1¬,~ŒVµ Ž””Æ\ç¤gŠe9P^`?JÃ^J.¶·ôv/×5¯()÷Ë™¿¼Š™²9„ݘC!Ó|[µ¾­ª;‰3•dŸ¥GªeêR>»N@ª‡Y0ÄFq)›úŽçLl\Ûz?Ü+ð·²×:1A¨¬‘ÀÚµI±šå´_:ÈÔ!Pž=îÜöŠÂ6Ú xHW•CÌhÇ1” %Ùaß;.•)Ë5% ÐÍÍIlÜíÅ TrïOȾßp„ ¸«Ë* ‘—J5Ë)¨eÛT}Q™. µ;Ë8x'êZòçF) ™±’"#DX˜¶ª!b:LUÙ9çl1l%¼ˆumÁ÷U‚äYÞî‰VÈ6 #xs#š£dÕøIÅ”*?édU'ùeyà%¼–<Ç8dŒQZ?è¤y=çcúå W5F;RÀ%8ÛÎ÷¤·él£hC×Ö‡ãlsùz\\‘¯ŸuÜQ5ÙÚ9ZŸ¿Faqtt­ÜŒ0è¶€r ‘¡Vè|‚ZsÒÅúªŽ)¯Àó=…-é¤.nì×ïE}c4Ów1O”UEŠƒi® ”+i*˜–vÅÇ-תé(vY‚$mk_”NE‰b"Á´jÍæúWÎXøpØ UPUòÿ»¹¼¤¬)Õ®{ 9åÙ+oTÎÔ –W¸rÞ!¨º|RüÏ«=v]7–w ž3‚ÇJ1!P`jI|æ4ÌÓ¬SÊ:IÒÜžThL(UŒ–ɇóÌ‘) ËFsârFßw¸ã S¬Ï¸NÎ"¿UÅd«Òd‹‹2úºÙÔÆÑÄ0~ñq…l**MG–=ŠÅ¾Ë¦Ò²&ÍAÒ˜ ¡£+·×E,Áó@ +ºrúU4€c—ìßW2ÝsE· Ó$x‰U¥ƒd9ļ€Þ©ŽÊ^ E¸9Ð- á¢ämJ±Í–Ú/u÷[+©’&†þ—û·jý%XŠ.Α‡ªºù:ÉŽøcYTŠ !«]F¯»o1Yŵç‹Z-j͆š² —¡… +n®œgw¼i]Äù¦—b¸nÎê²<ø÷Çì.ÎÇ²Š°Är8±ì*AÅ$›¿9WWGÆMguž‘k{¥‰]ËÐ$ï,.®ÐAE(%6ë‚€”Ò¼ÎmãOcÌ ×Û©{lT‘OfäPÏ(è:ñ9—Ùe5†Voçýd²î|M£Dnâ? ÷dC×¹ù22Z|/ùåQñs|cìtR—‹F‘¥”•Y¨¾dAK.„½¢*÷ºe—LÏœ:>Õ´ê=4öµÒtØìöáÁ·ÏV†«\ú'L ;ßøˆÒø§nÝ9¸yç«Õ‹ç—÷nþ°R7?÷¾ù~Ýùxõ‡ƒÛwVß.þÙ†FtãŸm)ï4MÓ˺!:ûüÇ Àÿ ¶Ó ¶øW¬Ïɶpr|Ï]Thÿ…]·ï–0:$_¾pF¾±ËlÕ„&šûú·e­Ü@lâ¾¹\> stream xœÕ[YoÇ~'ô#äA;†¸ž¾æxˆƒXñ!Û‹N"ØF@‘)H"m‰ÔñïÓuuWÏôpwiÉ@ h¹ÛÓgu_óû~»6û-üã¿Ç/÷>ý±ß?{½×îŸíý¾gðá>ÿ9~¹ÿùaì`llYíhöŸîÑH³ßÛýÞùuk÷_îý¼òMX Møõð›8™bD7®Û!:<‰ï7~õucÖã8øqõ÷Æ®~hìêÚ¿häÁͳíº5~ÕŹ×ñ‰µc|‡HŸ4®‹__ý«1&¶A=}§¾Ï³ÚØ÷Àùaõ¾Ã“ÃôäGX´mm·ú2ÎââWgqÇ_ÆwÐÑ9wãVšƒºÛÕOMliƒ5«ÏíFØ6vëìêû<:w<Ìi'¸‰8kˆSô½%úA“0žÝ­­ß?píº7ãH¤ü2n ft«¯à(sÜ-ìÞ­~YÁç5|\ÀÇ3ø¸‚{©÷søy ïáã¿q;@Á¡Ã!Ôç27ƾ ±y\}7wo`uœº宯RãI1ž_çÆ+=œ¿]åÇ×µ1¿4ÒJ$‹ôÑ$óa=¸qØ?ˆ\Ó¤™mõžpu$~y™™ô«(âq[®G¾ºŠMçñê‘RÀvDŸ.n8¬^¦ýÁ(8¡¥Qošàà‹Çn/âm_Oæˆ7äðák`P‹m@®¯³DÄБ¬!Þ¤Åõ‰Ï¸38  wƒm¸xövÀùq³'<óÐÇóñZqïBQõÎqÑX¯Ø÷ …OCžÂ,e3mjN<[t‘c=b‚kD–3«· ÜQÛwqv¸¥Ð»QnÏ ;÷=J ]æRbúu´(r 3&h¹;O’†½Î’ëÀù®s—«F(RNØ›nX†Ã ¢ Úµ ãþAüSíãse!R×÷©ñmn¼L¯rãIjÌûz“g£ù¢f4OkÖ÷¸¶ùlÈ&òN5‹}/7¾VÆ{Mlú%ƒŽö±ujh~¾ƒAwÒ G»jãÿƒÆM9ñH”#K9ŽgVv]—œXúœÈÄÝ]VÕ¢õ²ºí°ÃSu)Y.Úþ&;[SÐ^Oº¾ïj2;ýØO(>«ûiË@gßF¬v’ßyÔkÿ?Ô‹b÷»ò«ìŒ_mo²e·ŠpUŠ«¶¸;¨s<ÍxIŠÜÒÔ@ÏqÉðÃn@O¿ÔÊ'döÌÊ: Ì< Êrç30˜´ÃXgrè³3†õú^ÇÓ®îXhã…$¼€ˆâ‹F,2Û*ù™øÝ8ÕM?I‹@ñÀv@:'zšõ W €÷w¡z!Ƴ½Å{aìœgÒʘ¶ÃˆHºuxG ;¡(‘/‹°ÂŽŒ"¡i–^Áï¡®‘ àAAbP M}{p—€q!Ñ2kî÷£Ã›>L¼'@6Jómnº²£ÉÍZ}§4wìJ W`%ô.Bí0@LÛëÎ ÷L§LiJ¡ 3C 48 /‹Ë׫à®ëÈo{›Qé3Ä6£:¯¦<Ò¦„½¤X‰«ˆ%^E7ö“8hgÓ¡´ÿ ¨Úvôsj÷#:AsŠtß—8m ‡çDk¼’ÄO ÑX ÞÐ&‡ ¦›!ÑSìÀöÀ±„ÑgÚ׸Ôʼïc@ákúJ`î€7«YD,~ê]“.ŒbÑ¡gD,H[uëÁkms÷çÞÕSo¬èø ×7§hÚ¹¬´VÔ!kØýÓÂÀÊpŽ%8Põ­æëÊlì"ã ‘‚¨' †H²‡À¡ˆž,Üm¿fp‹_]­?Å)´ƒò€†S—àt$ãR”k-ºÑzLÚ³2tŽm¦-½¨éØE”ˆÂ‡ÁHìAŽíÀî4ô0ý\œx'dÎQaE Ö5nn}¨m·…ž"ö’öë‚Ñ0,Ð/\>SÀˆ»™çÈ\²Í£c—êI›:ÏvÚ`‚È#>P_¡^ä{6jÓÁL@Æ'Ÿ ïÕw¥wí}¨óЬ–p½ÐQÎðs}æŒ.ʇٽ®x†Ö”¶Ø«è`)‡lsO9ðÒFê o±tö£½ï‘kJ„i&*«°3@ àÌe‘Õ È‡ðŒ]™Ðòö,o$8ìa¢íµ¢ƒ”Ü’ÔŽ0* H×dýqž1C¤ü€mOÉçqxmÊñ‹h€B9Z‰wå%li0x#SbãRîSžpfëÄ"ƒtwá˜ö£n-Ù#–1i¡ ੨/ÿ Ã:<~[2 †©“¿Sc%çBVÖzLM&µ)”YÂ?ÑÂ]:5e‚Çâ ¥.Œ Æ.xÅr—De8ã¬OTÚ³š¼f­õÆ K£÷ÄI"¹XÛ·»ˆAïÊQüµs$©fNÑUkQj(¼pñ®u86.—ΑCËñÛ¤Àáäòîoë> î5žT¹¸dæ:…Ë‚Ù*q¢”¦b94¤ŒÍdå!ÙÉ[HF.2ŒŸ¸ÿ“àÉÃWøOÃ!Ê­‚'ÏÒSdõ{vstCë.ôlóÆãÁË˪@â»ÁË‘—…m àz³i§©ã;µ‰"®eòÏ ù¨°¦ŠùlöètØ98‰y[Îóˆ+«9«ZÔºÛÄ$)À¹ÉN°„ÊMòŠâ‹qTŸew‹À¨\(áp°Ñí-9 1KÔAhî|0vHîšvzyì R ƒW*í¸ÎRx»1•™1+ÒB­QÆdX{E;~A“œSžd,WÔ¦¶ä1`÷8±d{·vSx“˜‹õ¡oÇl+6ØO!{âÄœ-ø-{*±  LÏØ£BžÃ`rmÍ:q„M(Þ´;ó*.åA†àÉ}kÄ_˜ìŽ}“7lˆÚubº©DÉAîTpGu<–ždóŽÃЄæVLâ­Cn”MŠCä)8O‰ffø—UI-’¨ê ܤ@ü…do£ž¹#Ø”IÑmHòÝÈI>,‚y¼­AýÀÙˆ75Óô"5*ÛrÚTŒb‘››'ä45+†ôjÁðÍä\GwÛÜœ*€ÙÊ¢±vCµ [4 Sj.N­\¹Rʵ1D5÷[r‹9zÀ‚“Rh•ßt’ݲW+ëQÏ¥=Ûß-«x(~Ø+ÿj¡œ§ßWqèTo°SKõ77ƒâíõ?ÃJ3æ¿I@ù;øx”:ÿ:—õ9­ÊÆóš8¾Ïo•8 (^™Œº!ï¿)‡ÿqÒõ°ð¼q ß"aßo¥°´E…Ù¬pk›ÓT»ŠX²ë§Š}mƵb µb1äPVÏIÛVàÆB…X5¯é)¿³=®±®—š¦|Ôr^°ÁØÛã`³Eˆ×vƒV–ø¯v§1ªÒ3ÄžB"Wò“”~Ú$µmýb˜ög&hà+ ¸VnŠ'1m§ÉªÞ`°Ž`¨Þb‚Q¨;Iÿ3 üµ x–½‚bªØGÍ'G‘¢.ºP¬¦Ã ­ï`{¸†p¾Žì*bdK$µpÁåºÆí€8xF5 î±Ä,è:ñp$Ýžðð‚oååª?LªÒõƒ¤Þ¶d\tNÁ¶²4”È!oïS½‚b0:ær¶ÁÞƵS*6rGé$g© r¸£ØÕ3`*óé\œYÉ@^ja ¶n‡Æ’frÅ—X¹ùöqŠTS¶JWÈæ6&Ýj¬IÌcÖÞëàÌ©:Hk¨Ú3_PÙ{SFom˜V¼S1âÀ¶«p oi?^>ÏZzZ)ðóL”Ò„Œ³EÝ-:£ÊË—BÆ8~ÎPg´ª8Ì¡xö*ëP|¦sô¸/}ç<£äJ€L¤S(y9*Tv77o$ºf%#í­<õ\ËñAl!¶ÔU7 )0‡Ì7˜ÃšIÀ[ä Äg¢b毀ìɲíj³Xq/Ú,•p¸^àn[£OÔÕA²Òó”‘0ö¼´€No*K¢²Ú`: eÃ&„dÞPSªÃ§“Š)ƒƒu9(„g«ë*.òã’BI%¾E»/ÞÞ‚¼È"Ñu;sÏJvJa¯ãdªÔ EÁ ‡ºŽgÜ”ëë /[çËÄjw”÷̯Aä¢JØ—2˜QN™Ê=2s Tž—)JÊ(E%uÃü±‹Ž%¥ý¦)sÄR±Ì„ÙzZ¿hT¦/:Ô‚2dm’m¥j÷Td6S/¬¡p¥^z%·Ê^å×¥jùW]Àïû¸­ðW&ª…®%t”q ‡y’:PU8Û;†dIû MT•ÆR¢›ß~ªñÔ0ÊÌܤtC*à ›,  }&ŒÞ˜”—1ùɃ<3<ù‰_dí¤X#´Î_ z#¤(Þ)Òe#PLå?äÐ/½‡TÔ:ÍdøÐÑ2±Ví¸XçÅ´Ö'åeh× ¼?È{<$féQt„[ÑæªÅjÌ‚?±0%V©Ú™â ¨o¸Øé bϺ«C „"ªÉÖa«hÅÁ$F@'/Ó"dFÍ•[û þ¤–ÕL°&É×Je_kN¥a“J Ôˆäø;LùfLå9­y#œ¡‚©”ûôüJ¼b=äEo•6Ã0…xÏ@€%Õ*åcRLo*ÈXP7V?ÃÒX|wÆÞÀœÂ…=ݼFlÇ‹—b6mºÎÊ[|2©µ²ŠìOòT…¯”îDÁ“g Ï@ zS5³kv=@îfËÛ£ƒ¿]‚ÍÝ.µ–³hÕä×Y-~}þÑ3b‰7¾Û;üdF´œ¤ÀÄÅÈJnC4iÌ/“©ŸWÕócþ½÷*Ëp®i"¥>¯jËä$ÄÑÍ<畎Õ?£4ÊËìÂ2„›†µŽ›«U†VE—)à«wÃôµ©¼¨âNé[¾A9én`tXpCÌ5IÊ|q¸÷Ïøï ˆñendstream endobj 288 0 obj 4052 endobj 292 0 obj <> stream xœÍZÙrÉ}Wðz›n·éZº»êÁŽ`ðl€ ÂŽ ˜˜t‘ ’ÐÆð÷Î¥–¬^¤+™;®ºkÍÊÊÜú´¥¨r;üÙÿ¸ýí40 Jßzµ½s°Å=Õö ·c›Voï|Üz]õuW5µ®,ý] Î7ÞõÕ“ÚT?Ô+]íÔ+[½¬WÆôMÛºê{hû+ÂÃwµÅÕxאָ^@3«¨?õ}c>Ç®–ºÂ(}õªŽ­¿…Î/j£›VõÛYQIÓÒ ÏxÂXƒÀhZÿºó#¬Qi¹FÛ Më`™;kX.É×7ÔV6\…–+Ó6ƒòž;¸Ú̪ºÆ÷ ¯0ìßA5oAö ®WÕ.üé<ˆ4Tç(/V}y«K–TÁʱìW¿o±_[€tøØ“ÂŽk¦~ÕÇZÃFx]íþhôžF9«W=¬¡«u¤× D*û‚Ó~ÆžÔg öضÇáluUwçëAî®:ªÃtØû<+ Áªž7á¨×$|‡&†Æ9h„‹ÚàbUõÆ<–}:KÍ×XvR£‚µ÷NÛtÌ]T(Íc‚Öý0èê4î8>ÇJJkÃN¨ eaå+44e{‡+ï ‹÷¨úP¹+õ’j „ê­—§ í@|ß)~̓\Ô•åh¡Œ jìuK]iV¦LÓ¡Ñzƒ‚ŒÁT\Ô19CP-tÎ;yÕu!¡8¡ŒµŽÊ7fóµ®0_×ô`誱Æ;á ôÃÝ5`ÌðóSæ¾¾ÆŸÇøóþü›T?ãÏËÔøW|}Sáï%þ€XQ'ïS£‹\x?~È…oSá—\x– OjTA§TÇÜÚCkPíÓêÝTxFã –ªC™7~?5ÌÊÝÍ OþvÓjâ8çbì•í;²Õ¿Á뻦 Lƒ|I…WÅRâã9‘iM3$P:çjkÎ[Š‹—¹›h».ö,>žçÇ‹ÜmwR*Æݰí›:Ï‚²±üdd«þÖ ì-©X:–v–üuv ©E€eÓ¶´4גǽ9‹ µK®h2Ì⌚€ø4c56å&ÖQ2§ Ó7lv—¶ÏˆŸ–DÆb|u y†6·«`,•CFgç›Ð9ÓbœæåÓ4ë°lÕIÓÚ.qþ“0JÆÙ#Þ7ðt €óhSý+í—v¨ÃN´É8ž¯ãþ—Û[Y¶‡¡Ñ À !—¢ýiô)´D3A@°.Å´Øn/na  ¡¢0-ÒÀ‡1à~”¨ƒôB¨a'£€î5™rê8‚“5¤IÑœ&ØKª¹9Ò¯Œæh&¤ÚÅJF†€Ö›)áÕyÃãžnÐ7C/­o"ä`yw°­–o‹è¾»ÔöÁ`ÙÜ IÒ¡øä„´\#ú¢?be,E:e4«Fð ÐhI³šM‰WD¶ÔETK„Š0ƒ^‘bÇhšøŸåú öv".FÀÊ ‚œÆ Ⱥ(Ñ· …œ D´µoj 4v?å 5·$²Äei¶¸4¸¹€(VØ7(…Æk` ¡·I†aQX,¾,`YbZØØãlC{…1€  .žP8¨{„NÿÀuü”ß©é8„†Ü{¿D·€–w´ßÅlÄŽEÆõKª(™”!EFU'Æ0e0gE —Ôñu êa8¬ešv\„ñYú æ]žhOò”Û´/˜_ªÎL¬½ke/ˆ ⼨.hK¤t—©ZpHZ€À,œ$‡d÷Û¤£¤o˜‹›!-ª+H‹ 'ò²wd¶^³³$Û¯c,£!˜ç|ûX«‰ ¨Ÿ:zöÕC–{„ Ûåp„¯–%ÄEüŽr÷Ÿ .ñ'ޱ œ„oÉs'‘‹—cb|bV܉£å|¼J¬ÀbNCIoÀ†´¿ ØS¤oö9ç–¯](„KiÖHDI =S<ÁòdWºChâæþð¬2D°ë)CÔ3D üM]äˆÄ-л¹()R)ƒl¬¸ÉÉT7eU ß^”aï àXyÔ1ÚÆ­œdYf/qx½®Kihk)Ü5:Æ}N›z’Ím¬è‚4‰Ë§”@º'¸»åy8[öGµQöf '•4cÔªAŒ­@X13FÆËdƒ¨ ‘Ù09›Ù‚Iü]Ö=¶ðë6‹”w"ZÓÄòÓ jJÇņ3qEm²}⨖¯ £´œ°‡âÎËSJ0‘G¨’ïÓ¥ú«¥ŒœÈ[·xGø^$+%òôèŽQþ·ârjšê)2As×x |€0¸×j7\–Uó)ŸL‚®Íøä Ÿþ*–n[ÎÞÑÒ-[èìYí¿¶gLÜà@‹öl•¦´hÏVòˆ±õ|ŃlÉëi̋‡`¤g£.Gù…€Lt\mÕòû,ŸO'_Í“/\*±l–¼,Lð}è€ó€¯ÉÏ(¦©¼#p-Ý|çïHZ'˜bvy5°.cŽ@ûMlir ·W‹72†ÉS±a&ˆ†¹.’Ó6!’EÒe5Eh,ȧ©èǵäzBùU8”ëF/k|ANy. ÎÙQ®O0ÒL‹l_HJ ¹ÃÇ{Ó ÉHf£åÐn/Þ>xÓô°Œ¥ë‡§½Y ëü™Ç}d‹…9Ã/ŽWùƒuúàƒ¿–øó!='ñÍ×!/½½3œ·%”›¡]ô¹ðWô9GS%üpíí’ôØa#·|‘Ét3_˜ðÅ„°Ûõâ|‘ïþEJ³ÈÄËWÑæ*!û$ïÆg@½„â,pÝË9F™¹pÛ>pb o š6þ¸/)z;B{ùeãÉ ›fô±J ¿ ›$3Cîí:°È_†-ų4çÃT¶ P ÓjnüÞkó/Ã>‹)"PHðC)” ¢?‘&mÿŸ?·L›³¥é‰¥EcEûˆ<æW„±ÓmˆÁûôù08ñméÌ¡IªaX¤oóáÎtJo]ŸßÊi¾nt]¸?N³p}¯ÂÿÀàûxgëŸðï? ‚ý¯endstream endobj 293 0 obj 3081 endobj 297 0 obj <> stream xœí\YoÇ~'ô#øÏÞñô1×K€Ø–ìøˆ‰ `Ø~H]Dê¢då×§Îîêٙݥ,I@¢vgú¬ª®úºê£^·;nñü{úüè³ÛÃñ£×Gíñ££—GŽ^Ë?§Ï??ÎÓfj'w|òðˆ{ºãÁ!6­?>y~ôSÕÕ]ÕÖÝ/'ß@àŠýÔ´#t:9ƒ†_Ô›X}]»fšÆ8U­}õzã«|~³Þè‹Ûõ&ø¶i]¬z»7ÞOðºh›/ëÐÃÇ«ÕÎÁÓ±3oÿC!£zh» q¬þ†ŸñÍIzs'm[ßW·`”Œ:ê ß\ì±aVª;õ¦Ç澺[Ó¶ó®ú¼0i?ᲩYï«rïÜð$?L+¡EÀ¨ 1 žEè£áFd¸ m3¸ibQvuàÆ3 Á@=èEþ}ª ˜b@I¹ê –_=i–ª÷ð¢ø¦zíãËØØUoë. Dcuäÿ z\š·øì¿Ÿá¨—XÖfêªçðu0ööãx{^{TØ8Àl?â+_Ýàa#ÍAË{cv¤Nï!N9¢ØtZ?´ÔãWPmæu6Ø6åç´ÄG8WK›| ꡞï±ç»,ªm‡ž¦y* íŒ©/Îó¦F!‡è&ª”1“¯“¢Aåh³~Vç“–©s7‘nÑŠ˜±iú}­‚û%ÖõŠ“'¸£rw$.TŽ}?Yè+oš:çi‡—éÅFGǽÁާ¦ëãïÐrh‹hI„°Ú "¡¨Ÿ…ö… « 4<°Ö”ˆx-C”£‚ŠñvpýFv„[Itn áÄêÇšPèG²Cc d²…<º$‰KAËøgôټЪñË îËF𢯎–­‡ÄL~Kšà Ë^ÍÇ(ëEZÜ l&Ù7i£(¡ƒÏÉ…œ?îú×lŒ!w3 »Ì]zšNOzyйl\ìQöÕ{6ÞYL7¼«GºjŽ…v€ŸqÞx9Å‘œíHþ}”¯ÝHðƒiL£â‡Ó´ž¤<™€l(º‰v$[åyOì~Èt3ƒsÚwàÁ-¡ÓVMãPi' áß÷õسºÀdbs+0ÚØòÔÆÞÃ}Qû÷¸´‘ξy!Ž&¨•ˆ«±“Dû†™`€0¡Æ™!ðº`öA|ºþبTçv+>µº±` âªYƒI¡Ò쬈eÜQéZT ‘‘5ý–ý2„hQ_z×ÙÐ /B1…ÂI¼çy8 >’W #Oê9eØà¦ÂÙ2°£v{¸OKtĺÌÇæÉR#Ž´íÖ|GëMÉì.ÕË´• ÀüPú¼ïu¨› !Èl+ù!ŧ?^ÉFN’úã1ö<0GËÄlyö Ü‘ûÉ_&ädÛL{2ƒ]ОWlR†dƒ‘½”ÞE—K~r*޽/à ¶%›ÙéG¬w =ÛÎÏ•ŠöO(òŸký ."ö- K¨P"h—ð¡Ká,-%ðë/É<ÕÊóÂÕŒ ƒž>E>!¢hæö#˜Ú‘ËÜרµ ÍhŒšù¥A …|ãš x†F–üÙÂÑ7frÆ­«+m‹C…>7¦$Á„çšÜâRŠÎâop›¥ÇÀ‹@G„™!ÜÄžúEŸ¨ ´ì“]‰ïÚB·ŽOlaW3¼;R¡uä‹D}~¤€±z {6>a÷t¥@”ªðÄ[î„‚›Ÿ]ûÆÅ‰$CÙ"ëÕÍ9Æ.xÆq`8ã)ˆf ¦ZëËãÞÒ}Fb¯Ø)ÏNÙ#]?ßÄ¥Ó¥NeJ>Õ!,:A3ýºc½¢SSKªÜ¿MÕù!61cÂmðpõ¡Æ·P|ʼÃo“ü~į?áoôfy(ͪ_ð€ÒMÞ\ QÁž7¢©äÓÔæ©… úð}~øÎéIÈóÝFkeH‚,-¥åõ[«}øŒÆ¢3ãœÚ3£Ÿ§†EvHž§ ߤ×è$Õô0GO¦t [XŒyx™¾ÎèËSTiŠåßüy‡î²žHE Ú ¥W“äP Û²x•žÙÝêçK²ŠPÝY=QQž.ÙÀó•d :Ï KEtñwSÄNé瓃—/ºbqã¯þOÎÙÒÒNSÃ'FufDðÙ’¨?]çbi{,µáù’FÙÈB+ÉHIieèVš…&´J»09OkÒx±@‚qJ½n*ô§@‚—ìù¥‘WÝ®"Iœ]h#¦Ì€Ü÷jŒŽo®0"#¿4Ð…Ng×8Ý–scKX7£¢HHè˜"'EdzúzžÒf4ò³„àO`ìWH¢ëK˜šÄÛ{ ;+áJ)o\ ¢œ¤l9®Þe‚§&/¢ByŸr_¢„1J°P‹ÉÊœºK;ä[ æ2% Šg20ºÏÂôö9º§m8E')e°åâ9Ye–n!‘­(Î&³˜If‡È%‘ƒòºËÀ늵CNön×gÉ^õ>àÔìÊäoªU6’6˜_²Wš fzǪ·fž<ÍŸÄ óø2âZ2T>3ßy„…›®¦Úi¯e:Âæý½iªà!ðe1™45KG2/z‰I`–·^ÂT¸µÞUÝÏgÛù]õŒ[eNõî-mçáºÖ¿#ß»î݈·tˆý!°þî ‚tNV bÆÖ¿ œûì6tÙužbvìšo¨`NM0AnÞ®‚¬š  ·û¡«°‡ÞO 8Qêt)˜û¦:Jr7Óзä^cÓGô(Š©mŒCª -V,Ôp°Ç!bŒ…Ç€8ù‘¤›ÖA:מP–SZwtÎKú€å«ûúÈô°å–fuOò.ϵ?¯m¤z¬kôŒÝıuzƒqá ¤,¤ôÈ!>Wq)ñ¡§õ<§LF&þT›:\¥âݳË\–ŸšÒR®L·åD436ã ÿ"L‘ÞÙÝ4–ù©ä‹dwe\üæÙnø£ (È8Ú€‹)Ú,4[6ÅÀ¥Bhr=ÄR¨Ø‹1˶ù5Áƒ±J\0b;ŠÔö$Î5ŸtX…ÅOCæéÊTˆ0!Í^¤pÏéí­ŒžŸ'Ï£¤‰ÓP/,.R¾9n§!­Ú£_ÈEßeØ]d£3ÙL2»mò„_業¦å爋€%Ø*¸²x±U!¨% Ý$Ž\§£»'ßn+³¨{dϵ6`^H6Ò÷‡%^[7`>!6kºYmvTÚMºS –¼ÿ‘ÄÌH0¹8¦ÃÔç´d*0Eé'Û6áX/[ž1 jÔPÞc4Å<£/ÝMæCô¥ï²±Üɬ˜ÃYL+0SоSc4þˆ=‚ån%V«q«U_–E,]&1 ~{¥t© `¼Ê·ÞªƒÊË—D/©„)ñM]ÍýT™0l7{ *H^-›Í:ÑËsUS‰^dfEǽ|Ô%­—Mè]3|C·ì.)ŠîNX4™ÓU$²ùž.àR½A¶ê̲·L Z%ƒD*¥î¨Q°–&¥wiµQ@B7Îz̘)§ûè(L¤ÒøL£æ÷í%˜-ŒíÃü9¯”a?Aü/ô½2‘<ì¿·7'ùûáúY2.ûBjþc P€µE"®\¸žˆ‹óVmõ°C6ïÕ³]»ƒ±Ç‚± МŽó=™í@ò1¯lH¾\ºn%ÙÕ2ìíÚ˜¸Jrbo†.6.çEÈ—Šà§â¬•¥î%6 FÔ‘é§”*s >µ”Í!z4¢Y“RŠxSS¼QN$•}›¾*´i‡->G¯H¦ -5Ý›¯E#ÌTɉ…‚A=3Oël§[EñÀ‘d?噃G‘7Ó À›ƒhk 4IºŠ`ÓÕh¶Èo3$›ë˜Ðmùƒt¬Q–©@0Û:0ô˜¡ŠlO.³Ýf³ï”¸S”&xƒ~!¥3*ˆÌ×o*èöèé°ßä&Ÿ{CœZ¥Fq!‡S§TCˆ®]¡Êœûi€¼R³9‰«yZEÍÅ4ý #XlÆw™Nxpr¿È [Æ¥‰eÁw/­ÝLÓ¡à“6RÚËÙ€¡kH rê±O~è5§Î?„Ø»ÅË Å„uºšpÓaõW¤Rú¦0ÉÿEò“p\ã ê–IàJL^ì"#†sÎä2xû{‰«–ðâèº+‘zBIÊïrŒÍ—R­ûÐÎË[ÍìšÙ¶ˆ€œ»ˆkdÀHìa‹ ÈžÄ\'ÿÅn…m…†sZ‰=Ww“ÿâä›ýä?ZÐä×dIùæÅI·)˜w0QhuöüÞCÇU?õº=×30öí ïãšxÍü˜,Àìz®Y€ÿ-,À» åÂkàÿ p¦»kàÊ\=9×,Àk a C#|Œ¤£rù  <ÛÁ¼§<³>CØs%ó™ÒÃA À¡=Œý'ÿCÁþöàŒý‡[pö7c#û¯ŸÖ˜}3Žó{ KxA©e9Ã#g™ÿ7$]iâ6®¤­<],FòM‘leÇúziH“àHÿ‚šÁî_¢hÖ5};‡f‹ší»B³z¯×‡g¸ªõ)?°bLzT yÚ"ÿO´œÕ¥´øbT8nû‰‡ð½ü½X·ç·Âœ»ziKQœ_a„èÈOüM˜&[ôÚûÛli¯ÌÍtZ:0 _Ë„®3õYÃÐTCÁM•UÝV¢òº·“Á\0¥¬jײŠ?‘ŒÛ¾ ½æ«•ÀãæÉÑ?áÏþÜ¡àendstream endobj 298 0 obj 4100 endobj 302 0 obj <> stream xœµ\k“å´ý¾áGL¾ÙÀ\¬‡-9)RáQ  •H¥vg`ØbË>Xà×§ŸRËö½swYjkfîµ%YjµºÏénï'ÃÎ øOþž_ß{ëótrùäÞpryïÇ{ŽnžÈŸóë“wÏ Appe7³;9ûî÷t'ÉŸ¤wƒ?9»¾÷u7õc·ë}7ÒßÓ”çÝœ§î½>¤Ý0¤©{§Ÿ‡î¬Ï®¾ž†qè¾èO§î¯ýi„ ¾û¸?õÝßð×'ðíChâ±w¦›xé=¸¦Ý<‡îËÞÁßg¹»÷ûS½ôAïñL Œö>~Àþ1wŸÕ–tÿße,3ÆÇø,‡³…öyćâ,õöçýé€Ïæê?úvÎtËËq²Wm”´ðþ¿g;oGA™Ÿ]€œQ¾®¹a>q0Ü8zlw* OðKnž¹ý„qÃ0L¸/Ã.‡”@,q}Ù§±Ë0?çãÎÏ(*·ó>ú©û–7ä)úf?ëÅc÷×7ÅyŽpñ4äaüØ}wž0›¦¿@ÿ”“¡{Þû®ºîÖLå1ìÆ.ùчîúOy—†ÄãwS¥yF‚»zIzDßT[šÙ=¬ ½Ñþ<· {ó>…ÛͲõÑn‚¡Õ?¾wöú×°ak«hÉ'Bö •ò[ø¹êñ9ªOû@rЉôø~³U# £ö?ƒèa²¦ʉíñË +‰ƒãpYÛÿÐD X¨(€Ûž¤9’áQƒ“ïØö~lƒ l ZM¤®Ý÷xg Ÿs™¨â>Â[8ëóž7<ðèt½<â']>çÞ2C @~¡ã…›æñ¹ ç43”«Ï©b¤Þ4úC$­ ÌÎaÂ3d@ºø´ÿïõd•ÅÌ(2šH0›‚ÒÃv“Š0Ç Ý2 ³+Ë•QÎË'\!ÊÛ_£ŠòtjÓ {äO}J» Ž® »qœ3¯[—F²ò™ì(`f sºSÄŒÚzágWÔ 'q…—"ÙbT$ÝWŸ]ûއӶ¸]!ƒ Nc3jJ×HC_è—ÇüH4ÒÔ 9粓žŽýÈÛÙP‡º¸çø`GÊ%“ÁŽOÕÄ–µÌÚÈwR yÞùb3e¸ù)Ù£HÏCÕgA[Ký½mûƒ¶zî^+êô›ÎóèÊ)…ÉÚ"Y©½ŽQ5ÒeÖJŸ=|«F˜ .-ÇZäTM~bEâ…“"¡%’õƒ)inG™‹i&‘Á’BrÔÍŒ@«…= sÙk\Òkª8À˜I!¨{ßìQöQ­Ä ?ZÄÏËëí#ߨ«aBË»o:íº# 9øöl‹§‡AÕø¬±ÐtNý8+úðÑ<(ñ0Ôá‘FK_«m 鑇ˆYôy°ÆXx1Z­ ¥¾cðc t¸¦CI¡ÒÇcÑô 2Bz˜Båôtw2­†Ào™œO¡ægBÝÓn,èxíý4Ó¡mÉ-ä± Ûm„Ͼ¨þŽâvŸb×$€ÃJà}õE-Àþ~¡ø ¿ Ö=o`3;!©û†âí„#yѸ×Úø>íNE@-ê@ĈH¨DñQª•k˜Ã^¾d3 äÄÉ—µP½*£½Q¼&ã´jùYÛ“Ý„Àå?´:Q4ß(,Y>YpΡÔcöº¹õ)b0šq OH€À¯^e Ñ0ªÂý6 á…‚r÷¾’°¼@åõÓ¨YPüK$­’*¡Þ®&Ö§Ÿz<è¹’œgÛ˜>$c‚ÜdHÁë$5¾jy^ìÞÁmäß'>¡ÊÉ,ìñ®ž¢ëŸžæp‚n–`0Å+FÉ3›Þò8YˆÓ1©ÒÿÉ`éÈ?½3!ô’³x­ýfÈ03Ý ¸˜PÒƒ­”ñG~#Ú´ ÆDŽ›]³[ !*åIcð ÑeE­Õ*Ⱥijs¥D5RK'(£&j¿AÃh ½Píœæ5¥”Ðv8˵ԑ,{Ôƒ4MÍIR;jme˜¢ÁÔS°—&va ¶1ÎÕ/œáŠt0a… ±´‘ôÉ9e¸Qýoc¨hÁŠnòaÑÈxU™Ú´EA£²ƒs{€G2šØzÛbÈîpÁ¬e¼ÎVÉ‘°¨)4 ¨Žªø·â´»fÕô T¶~Œ›[<“ aålôÍNøyâ`u”Zá\ϪLF‹ÔôÅ~2 :z“Í×ËzLÌ‚*_öãÒKkøªúÆe-º*æ…îªÔòþØ€‹w»/ h¸! AÚ‹°tÈw‹~¢{BU~ñN¯Ÿ0Ù‹t4pÀNMA ]­\!sìõ¥z<ú…ª0V‰šÇÁKô…ÍÜ\)Ÿ‰Ë6nªxž!ÑDj#..®ZRuy+gQSeS/ú5߯pHš1è;³á' bÌNö²…E±ÝwX”¯‰Ä’Ø38QÍ»˜µª <à>gæDn~a?†ð&£44ñÉ0/Sf_³ŠU©Û±ÌJœ¶vŸ÷~ØÛ9I<‹@ñѨfì€ BÙn—c¹’Òà§YRʶ.²sÕøZ5»•dú ‰aªÑàb“PŸÇeøôNœ:†%—€q“GlIÏ#±_X¾ªÚ­Aˆ5ÏFøÛ:ÇòtÓ<Ì ¢`0‚þ[’ÅÇBwUèelkNe™h,V븄s/ˆÌ$*·Â+Wº.=À¦h®È|i!›½±&Ôr²Nu;q+Ϭ•â ýRþhH%† ˆêäê2 F˜Ý\ÓåMpeáw±3»Å’@.µO[fËqɨÚ"•Y4ïÏ=E³eÛzÆØî¸OÉ0D9ws8€êö刚hø~ ©‹ê0K¡Ñ‚s‰ë4þ •”&ŒkPÖ1aŽûx ó ú"óŒé‘;¡zpÃje¼ ̸±ÝV™"ªàðƒ—Æ}’5jÝÛmk,"jÁy_ja6£z–Ò]Rû4G›^¸'¡ô1ä*0ãJ[W8Òý»2Ä7ÚÔíE\$‹xgL WÓb*›˜¹æFŸNÁ<“´L.¦Øâ@Å&`ÍïÐ6¿eÓ7bǵô¥Ù°·Zî4•0–}Ä"£-÷£S8o£Y[}Ÿ(Kló~Øn9Ýɨ–èLF!ÈÄ‚63·\çŸÐ² Fó& A‚£˹R.ÑG lJqËVdÁ kk›ÐàòZÙ–)d\okSlø"o¤›y?r*Gõí¾Ô QƯanÒæîQ.¥\«„#(_[Jh:nÃ`¨÷8†\˜pÀq9ŽXJwÝëúÜupΔ©šâU8RÝUK»L¦Í”KtêÓ:Ãögس¿J\ŽÍ0€Õ‹–còQ”jÍT·¯û€1g ’c642÷uíE@DŸžo ë›ÅíÆÜ4øqbx¾!¦øR¸ËifñÖ8™ðF4úuÊÃf¸ayº5ôúIo‚Ù2µÈê©B ]P£f4È'ÕŒ O±(uÅ4&lTáÇ "$Êá„„¼Ðc˜/ºm®÷”¹ fh†Ø„`Z&E½diÊ€R)›‰^ªÖã’L=¨2.üä3\ISõhØàRre¥%Eã¤F¥n£å·•!|†¿¾(~„*°´ý¨ô<ÊšCà†\(åUiómS†P;êÅ_·Z>îkd—¤ˆÒù~xÕ©ü¥ª¹ü?ÔüËsªèÇU”::ö,Gpª8|ü[±Ñd»¿3²eãJ¡0|(V¯|¼8 â¥ùƒzöD!à´ Öð¼qeN•­hQ±í§EQÒ`[´(ŽÜ[v,Æ’1kÕGÇ8bspBŠÄR£HÎÃ#5Òçª$ˆÓToàÇpGÅ€IÕí%@Ñ3Ü=†i1@}}¯åC1&¤¾(âÅç9cdsrw¦ÄÐp™Û†‘y•Liƒ$íspœõ<’$• ÇÝ'_êoVD) ‹•ã‰Ò!¥cJ´pÔ†öa ¦æy+Ì4ˆßiá׿^Š&I!Âö ë·ÖŒîUšê:*ü Y”_ó§%BzÅü©2ÊŸÎ~ "Ö„JL|‰‹h—¤åz‹?zóÄŽ¶&BW–?­{ÿÚSáÄÀUÖÅ•®«¬‘}Ì~¿‚êC,¬¤Jà ½\[Š9AíÖµBrmUKݵ2¢°€ƒ¡Â:|±Oš­_œ·ìö½B…öÅ63È"v 5¹Ó™íÁKÕäao§R±Z¢>~Ð¥o££™ƒÄÊÅEB½Éû7FkBóÜ8ÿú:”qÈ„ÔKCñ‹Ⱦ6ˆ:jZ¾ÍShʯé¥ñ¡Ðèðq™Ÿ×Ècf?®_çT*»N6§»”B7zf§‡Ñ¸m¯¶þ/  E–(žÙYg˜lÇ&ø&á$—<+P€¯¾e;®Ì3¨C¬ °®ŠËiáZn5Jh^ân+I@qÅtÔ‹ÓÚŠ´¦ºLéÿB#ŽÎ¡.ˆ8ãý/Dj¨ÿîd‚V4 Ãæ¸¯&p¯ÿ½–-aä~pGÕªWÞÒöKË´Ìì}[Ö¼ –¢m6JV‘­’2I?ç‚‹Kn/¬Ši*+f1y¯¶juYƒÏ‰u ]Yç%Ù‘šùjψo »æeåîÏ¥’£>®Þ}´ñþ¶(Ê:}U¶Y_ù iíŠò¤bbæŽräô"P¯P‰W‰!0ªÅ§uìNUèQ-s×®pWBŠÆbèÀ¼{ߘ­¦Oó>gÕý4ꨓSc³=¹8#zSÞ%IF=¶§9*¬{ÿìÞ?áßÿL¯#Õendstream endobj 303 0 obj 4647 endobj 307 0 obj <> stream xœÍ\[“Õ‘~×ò#æ® º¨s«ËFx#À ŒWØ,Œ»Þ‡Ñ ’K$lþ½ó~òTU÷ ÒÞ è鮪sË“ùå—™§ôÃÅЇ‹ÿ“¿×/|üÍtñôõƒáâ郺y!®_\|z „WúeXÂÅå“Ü2\LñbJ¹âÅå‹ÿs(]9Ä®üïåï¡E M‹qé‡]ÞÀƒ¿íŽùð».ôË2çåðI_wÇx¸ÄëŸwG½ñMwLqè‡#ôÝø Mô™Ïº4Â×”îB€«sqwÿ]ÿVzðì1åùð%~Ç;—vçtâxx½$øš —T¨1ü yÄSŠ0›tø¶;Žøx<ü©ƒ+C‰áði—`ÐqÁiÓcc<ü±¶®^Ö‹6šôZ ‹iŠ,Â<{ÂÚSóÅ1 ý–…Eù&…=&”`‚¾Ž8ù`<øù?þrÀÏ·øñ?¾Ç7øñ‘=ý>Ç+y.¢çñðW{žÎL.þ;Ì4‡×vïMmpµwñ­]|]/þ¥Ó«¸^zQ•=¸ü×{-ìÑÙ%Úx¶Äíþö×oy.ýœ–™ö<Øžç.ñÓ+«„½AŠ‘}ÖåÃwðÿ «¸Ä~Óhßtéðlu §E7~„¥#·zÊO ÃD7oñç€G]ðw3\#õ£æ‡ãßHû@£² “<بú4ù윆ÅOLd?c'Mâ­­çÆ¬Æ‹úÀ®É’yópx¥½þF¤ÏáÇkîxY‚®XWwU¿^Ã÷0±çÊ= SoPF³yQ7ô%® -}Öþt¡W¼2íA¯¼Ç™/¥pF }'‚œ7]Õ®‚¢—eâ"êò"Ç„wЇ™guœïyÍ„0ǸŒ}‰G4½jF+B©âÅY·6“”R y¿äÛ…,+M´4”) >{E÷©D†>B¡ÇÄdzˆ3áš²¨à•n9î½¶ù™¶˜¢ÆBíêJÂq¹) à­>¾`æù¡òä¬z»ß9€?˜·ŒF<¡½†[–õ&‡D²Fm ‡¿uQ”_–WXt}· ßaîÇ•Wˆûö}°ûÞ€¿Üƒ§¡µáëFmåâÛ=܃o¹äîÅ!±¼Ê{àÞ4´˜7^•JÞª’´¸eôXaÝ4T,ÚÁ»i!…ñx‡Üë¦LDæ°®°ÑÆ» “áNL± ¾òÕˆvTÐ0âòf0vŦªùQ:g„¹xëʳlaR…ÔLã˜F’²8¹¯v¥ÆFb*÷ÃEA»©OcXÁXX[xÆm@ÏwÐ@gƉ‡È4 ¶Öe<|Õ‘Áå2‘ÌÃv‚ô!Œÿ)tƒ‰9 ´£ø“XŸ^úú{ìR¯åÅÃf¹s¼ûú¨KOЗº …ù\ð¡ñ¦çiRÓsYˆpïa:ˆ2¡]še†¤"1÷³©ˆ Eêòó˜I¹÷ûôê 3>ïĉ‹Cˆê Ô\É+àF“ Ëû®`,­+e‚ š&êC› t÷óÇdÕ±=öóFíž-)ƒmÞ¿îTj´¯Âü*ƒç^SÊ9’UâP'ײ¯ê†¢îçN»Âg"UÁ}5¸>µùès½j(&%·ý¨ ÏyXÔ;…{l¤H²6ð¤PrRlÀ 3ÃÿÇŽÈ.›z_1Ð5V&ÄxŒLÇV«ºaÒ¢æîHË•ðR‰kœ‡…ku2DÂv&£ÖŲ́¼?¹ü§ð“7ÿ_øIžÆ/‹GU,ÛÕ¼·„Ð K˜ZÕqH_Úˆf%FÊ•{°ª¸"t “5±¯Ð—)0‚Rö%„´Àµcq¾A"‡©Î0¸Ì¡q;ã>Ž3Ä8ß2KKÁ,t–qV?R2§ lØïŒäT{\RDËŠ}À¸ü“D'¦>N3„f0@˜ó8ê Ëúíª³œÊ°X›7—Rf6{¸˜óÔÌú+\Ì8F£OÐ]ÄiJ‡/P~cŽ3g—€õå“A¿aZj‡~žSŒpÈiFèˆý4pr¤()‡‘¼9È!†1ùEßš€_r$ "nfõ±Mû²Ø‚ok·oë×Çõk•E]¶{’§Cr3qSåùqÖI'€°=bŸMUb#Ì…=Îì•è÷Ûêp  ëRÝ ^ƒbíiš˜*7ÏA߉<¶†®ÓF+’â E샂„F3$"H'CU{ži¥ÀØ(¸Ž4Z‰3§^Ù°Š3Cè¿Ìœº‘¯?c;ÎìN1.¼¤+rÊ‘²+A½2 BWHåˆY`‡ tH˜+Ãè™fÓ_Ä¥0IĽëÕQfزF.ÈoáÉ¢úF=ôñ»3¶5 ­™Z‹¸¢å²ÎŽõ¦›RfÞíÒ"m¾õ¨"hã #%˜`›9¢š1/’.²ŠÆÁÈ3ÈÌ ¿€_háËÜò(¥•àân50êX–ب?EHHA÷õ³K ØC ÿ¶MÂ|Lé/2®oJ&z$ºêC\ ’ÀihÆMç’g¥†šQt,ǘŒø­‚a˱¬9BŸ‹Ébüm×oÚì–˜nx}Úk)ûÀ&™õÜHP5tGŽ–k’Ù0™ä…¶¡ÅùÇTw¥på Ó?š;²×anò\ËbùÙuV;º&ÄbælñÀPÈüotZŽ`œÑH…1&ŸÌ\) Êb †”››Ï¾f MsoQ$†ÂBîš#¼‘üêLê5¤¡ªÒ—¬hcÿ¥¥–G"öy¡}©!J³Ûe_™*àlS ËDÛ‡âù©£”)›<†{‡­¡œ€­&aAÂØhç¡Hض?êÙdŸˆŒrzÏå6 =c«3аyAbžÏØ'Ü6 h¨ŒK4e Ûí2ùÄÌ‹µˆ¿Ÿ²‚f…€ I¦ ì›Å ¯{å±I â3IÃÀçæ¹FŸ¿0“BÁÔä*ˆd3nìâ …áWqÄ “(–tñ±¯çÔC J‘ò= q‡gâTh!­òj5ÞS2•­j½WŒ˜-éVË,’6ö­Šf‘ãŽXDÐ4 ö#§Eü).Õ:‰·™kbq,ïÔ,Æèâà7j‚)¬¢Gv‰T+;ê[«8nÿ^ypý;öi¸}ß*si`/´ûÕ¸Jb yŠÇ,+;x¶B!•Œ33É÷Q*އ6·p {dÐè ÑÁáÊ·®Àq€òTËÝž“g*œ+o=%¥d-µåóø¬l!é±)—Pj] ˜?¦`÷™?ˆà  ÉHxt¿²mfà|ŒùÌ1=FäŒ1©ª€ƒ ÜB:Þ XÜßé˜uY'uN0"Û&G«ñ6#qšJUÀs,1´ÙùÀ“<¥8!“ë«(¥~G‘Ÿ·‘¢cµz›Ýâ¬Ç™Û/wç/|ÆWVºƒÎûçfZ®§é¦æ›(L“µ“caÇQŠ—‹³lç67’&>X³JÁâ%z¥Ö$àÝ.:ËjèñY¯N|¡×¿®#ÿÙh& ‡b¢…Z­Ó¹« »¢êÏÕ56m·Ù¾]%¡ }*ÐgšÏçi)­¿´b*g³3 ‹¼êMË:Nd˜éFöôÕ2,²Ü³5´®b8ìM.‘¥ë‘.;浬‰‘†ßtv~à´J—Uvψμ§p’ËÀŸ?`O>ŸŒ®r“¦“¥]Õ¯gÎn vãRІC‚Š øÀçÊNÌ+²Ck 5&Y3î½£{ÌêÛ9M3ºsÛÃ)z|i‰‹­øÃÊ´ÿï’ÏÒ΂_Y}«rŸØY;3¥‰ dž>Þ¶pfµö›O”®jÌlæzƒàjlÓ¸>n¾B2A¾é½bŽ\ YvÂYëZ­Çä têÁË:Íe”c¢[e±Tò´8KÓ¼^LkZ›k W à”¶±âÿêù0À¬±b…ê¤GõüQp¬zÂ[áè€×{Gôjk†Ÿy^ðÉ,Z©jvõ.;¤ÈúWóÉ —Ö¯¶gYO¤ö$˜»³VfÅ 9ÆU»ñÄ1ÝWþªKf+PÕŒ¶¯€Ñ4?­o¹W³unSM'7§'wª5¶„Õ«oeláPôö7Z2O^sØ–÷ûÝÍñbã§«ÀTEbf9ñj£1Ê¿M›Úâ…§pú¶ÄªÉ–ßø«¬¼· Nl!"'N.cºEI'…ñJå4ãЖ—ãéºHSŠ;R/³vKÚQõÿnª¯õ<§L'£ñèö|Ž7ùcŠæÏ곟Óƒçû ÆZé{,hP²ÆÌç]U9rÚDÉ`„qÝí5ÊUF²í­vyRDÔæÌ¥Ô‡ûÞÌÊ•RY­b?ïõû–Xæ<5áyN”þuÊ.toÊY\ù->ìl½ oïâ[µÎ¯"jÅ ºjV”RåPÿ?×ì–½ âÀ¥¡X ­VïSÓ—î,™X‡ JS{µ‡•V“’âU™Öm•Ó¾R}ÜŠÏ}$Ìv`V!Ùô”ßK‘´Mè¹VvÀš‰f<5Üàé2ýÊ}¨ÀU1¾ E»Tw r•‹?'´»?j©ß-üþÁ½añ¾µXºòS€å°2RùFßAÔÊ“{-qŘ–P ¯© ±-õX²ø$Ô^±QõñU ÿªY±ú®éÐ2<ï[õè‚u¡o’ÈéÉ}¼â]™°FÛé=J>wRKkòúgÈý4îœbÓ—Z—¸%—z6è³®ÝP;œÙ¹ªàßw«PAa²vWo¤!%/¼%]›LkâíS(OîÝâwδF{½1äÒ í8'šÐûm3©±ÂvÊÛê‰a¤:ºXGmª¨ò&PÚ™ÔGé”uÕZ…;Z½M¾´VU ÈP¾è*ý{6êȼ ˜óÚ-¶Æ³Å`;ªêÓÙ< Éio=m¥ôRÛÜ»“¡Ñ˜×¦–¡(1Ü \¦¦¹¾LG$Š×Bø=z L)Õλj`ò'oyÌMÝWÞ^½ì|ZÁøÐ„²Ïa¥ g¾«^ù¬§êXÌ£îO³ÀßÙ¡£è^ÍË;¾ÜúrÈŠ®=ÛiæÎ˜µ‘ÚœÚ-ðÇŠ„±"TÌ!zo¡q~jâKwø¨Àk»Ç™JFë9IÇ.5|ö`¶:ñ8m’Ðõtdh*Wë—œíU+.f…{½ÜüE§ub°ÓöŸqÈqç KjŽqQ%ø(†æøBöºï°]uÕóJÜSK ølJzøj§êçj z‹Žúže¢yéu’úå×»œ¬'bµãUÊ屪·bû&Ý?W£áþ.Â\†ñþg^h¶>ã®7ÿ­³»aæLŸb&žÇ咼Ʃ¯Vç<ô너¾¾èr†¨äµ)°ˆlçÈ)}¹ÐÜÒI÷ˆe‹³ 3 £st‚%·è)þ”š=í\ŧŠÏrƒ!·éþ&ìÌ–­Nÿ»"Ú›êW¯U®ºÖ,ï2Ö(ƒ^Ñ(<4oóò›·äE襆·nn»ê¥óä×PuˆÇÆó*ð9ÆfŽéþs¬yÜe—ðy‰VÂOóÍÌ^æN_›]ï–şôáæÚbY§õI+41wÏS3=|Ó8GgÿY1ùóËÿ ÿý­ÛÆendstream endobj 308 0 obj 4961 endobj 312 0 obj <> stream xœí[YsG~WøGèÍÓ¦é:úÚ ;Â,˜À–1‹å ïB#±º ÄþúÍ£²*«ÑH(lÐÐS]gæ—gå¼Ý®J³]á¿ðÿþñÖݧíöáû­jûpëí–¡—Ûá¿ýãí{»ÐÁh)ûª7Û»¯¶x¤Ùnívë|YÙíÝã­g‹¦¨eaÃÿ˶ë˾kßnñ¨XÚÅn±ô‹Ÿ‹¥sMYUÝâ 6>-–†_ÿý¾-°¥kËÊx·ø'öí¡o^@Wø€ô±4öô„§Ø³[ü„«<ÅïÞ¹87¼4†¸ž³x(M ¯Çç Nîûů…<Ѷà,a°ÿ†ç¤…Ã`ƒÛ­¹ñ.œý'œ°æž¿Äiî¸-g¡oÃqy] ­ª­¡•Bã#Y†©j˜¦mí‹ÝïÆjvø6ÐGvWÀ…vàŠ;.½íËÎo/]U¶¦ï¹ç5l—‚À nË/Þãb°Ñ}ø;…‰NR·v3Üå"5¿ÄS¾ƒýQõâØù€SЭ¡ï80¸ïj|êà›cxƒ_3øõþö`N˜Üö†x{.<;ÅIà%ƒè`‘­DÁû…TÑöNèaŸõa…Æ/g¸Ûs¦ÌšVD‚ÑvÎy4’ wù û2FU_¤>­Ñ[àœØÑ9O¼uîwÖRßK÷ƒx˜#\¿ØÅ‡¢v@Lž IvǧþDó®Ä½ŠÖÌv Ç,A „Þ2S¿Šøâ—átKãʺA €‡üˆÀm#ó_ã™ñ00ÀÓº¬©èh]Ü=-.d†žáˆu~F‡;ï™ú¯˜ª:¢« ñ8ga¤tGù/$…{–ЪmHŠ+C’½vN2Ð[jÃÁ$áÃ3Å|'Íõ P6÷o˜–6ü Áö±°=/r*Ü Jî Fiˆ¥ç„#glé£x¿ž`ï‰P¡+Òð:ÃQ$”Ï„U¸š†‰ÈÊt`”„I€D:†}MZ6@Jz¤ùÔ"Ôç$SeËp8‚QÝw|Æ€f–ïˆÞ_2 o‘€ÄÜ@ƒD±Ö …5,°f~ “4†v•„á6¢&_\%ðDÐu<í •NcU૲@cç-}=€â_DùŠ'j2çZ@©Cõ:‰+‘¢ê¤6¨ƒ PŸi’¬X%¡¦j{ÁR¬¦ ´öMßË„mР{Ð_߬ŠÛ(eh|‰÷¨O=<«RêI³åÚïÙWÕy|GB¦í¡Òáä;P㯢ÂÙrô5 qna`' úVo‚oCç颴ªþÁºÉ׿À\”ïÌ„J ë\)åbxTwÀ†äÝ)=)@ª“׆(ñ†Áô„¦ÆDΓ͇…Vî¹ó@ô0 ¦V¬~Áò)ªŒ›Æ;¸÷³ÈJkðåÛ;Ü·'”lꉚ÷&r½{ã=›T)ÂѪ) Õåz¨&™èÈÑØÐ‘ i>à<ÞÑ”&ÌÓ²m›Óik=™KMËX/Ú°Õ.,Ó»ujάó<DîJσÐÕ¸Òºh¢2WDð0£PÉtþZ®JD ³=¬žk9÷•°Ï®D¢½tˆjA9³ž,ôpÔWAXUÄ„*xvÆ_ÿ•¹^Ši‰=Τå{±[3ëx²ù¿?ËÈù ™Ùe…Gä‚´] q‡vgµO>¯¼$>JqŠVaZ-hÆØAϬB#Þ*ùWÊj#%†Ahß× -%¦-“œ=×*Z»1œöA£1ac`PWif2È~l›q\Ü-¨zI)‘¤Ã‚Ô8òšÜœ.m2›Éð¹X¿‚5Qj¼˜ƒt ­Wâ1¹îºxô¦É„G_±‘˜ûe /ÒÀVoª¨`ÑG2py4ÓjÂÄÏB›ƒ°©û«µÆI˜}>èfD¨WŒ·âP8ÊÚ /á™|\å0ï`àÛ‚,‘G Rè¬Ñ¡êf™/_±€Ý ·Eé[ôzãb2‘zc”‚…AŠƒÚo:ò3U¾F° ? KÐKg§Äi€’*Bú« Wû˜H,—Þ¸ëU¸ºIç^eë7Ð,xß„øØP³s">’YMY·ã̺ÕUGÎæŠéà·TLk½‚D¡ø1E«´&XC!æñúc^“v¶ºÝŽRã‘&æØ¸)17t:’’÷×v:ºÎ%ÛÛV³E¥Rª2Êå"Ü6yx Iê0uLDÁÙœ°HÝMç)qõõ™ñ¶¥S]ÛÓlƒ»½`pJÑt!5³ìzkQw|¸îGÚ²Ó÷#¢ƒ%'ßð]ß5ï=\ÓSÒ"Z¾ÙLö'^w”§ìãužõaJ‰LF˜¸NH=5åðbM§óTR…“2x‰ )Ç̲[Œr1O ×ñåú¾’¤ èï8>»ÊMÌQ7¹áš˜3¤4&·ÚÀÓµû‰ÎE¥ÛMʶïàFª 6²¯í¦Q*y+]È jÚF¥™0ã|µm&†F§™ó°^Yà”Ð ¹ûå2£Il¬¸´÷ŸÍ2áïÀæ9/Ç÷|/<˼¿ìn®)IgKMëFh¹G®íè&%óŽê¼#ºI¹Š¶–ñf4zA¬ ‚ç„Ô2U)©ä\y†$n—‡Ò\ÓL_«Jê^›†:3 †’¯ñ2;È5UõÐ*ë'õoÑ>ƒ¿à‹gÉÚvs«Üñ½Ã>]3rR¦Â¤*¤Tâä*Î*l`¼tÁÓMŒ—$ßS8+—–ÜEèâþ´—Ê òú§žsk£+e]]‚å7~”pÓPÒ©<Û –ìŒÚùàIIý=Ã{¢ßãÇøAIÙû±ó‹±†«¤óL%…ÆÃÔø.6žN%TÏ TµiÕ茰WnZ (…D)D¯c­“õS[–e’O¦Ž¨¨ÌóaJ&­x1±àûŒhBšhÿñ¥\mGŸ0OP‹º[k%E:Ǜ䡯v‹PÉÍê˜×ŸІ-œ{5õZãgÌI{v%¦dÁ4DK-É2ϘJ fFU:~ˆ î©!¬Zm9´ˆ´òqMM˜ß‹Üwfø3Ñ6¶¾î5~ ©šë[_g¹Èy3 Ì•LÓX.g/W†XŠôÖZ`UC¦"Ú}²fSvÙUåŒu=Äó{Ùõ [aù8¸;²¬g~’‰K™jzÊðlÙF:gçbd…ÍêúF•ÀÅJúVÙät½-÷»–Ë¥ÖÂØ í¨^^g"¡µ=Ö™ U߬kT #^ç\bÊö¦ô~ªÚFÕ^!;ö &ÑßWfT€å‚—××…R+ÇY.Ba_QÆÎ_MËeÆ …•®Ý~‘²Á¶L1ê? c¸†j²¶§Äu]`8ÕV6µÐÞ;-GÉYQ±¸ôÞ7´P;)NŒteç£Ç˜ª²*) %H&Ë~"-íZdö È+&ZMÔm}‘<Å“‰×gP†(óNLñËHWLãUÝ¡2%É5ÒûbKîÃ.$íÒóOPòlÿ@$¤æz†3móÁOÒÐFÅÿ’&/Þ ŠíÛT„±ˆù¯iÉq9’±„òa=iœžm&Ð^×v‘n5Ž¢ý³B¥)Çõ¤°ÀE½ «‚ÚtigW¦òª):ü%¹Vá1i\vJ…1·¦ŠZE´­‹o%C[îݸº'Töê +ݨºÔ2öhDz’B]]H‚Z‡?¦áT½À‡5/Çdw«E8@Dy¯y•ã¥ø's €¥m`ñ¡g=Ø=þ3ð‡ËŒ¼vG);Ò+‚µ°´¯é§3yfá–c¼%ï/78·¼?3 ÿ+y> stream xœí[YoÇ~gü#ø8x7Ó×1`;–#Gp™Hz H‘RÌK¢¨ãß§Ž®îê™Þåê@`ÁánOŸÕu|uðå~·6ûþÄ¿Gç{y0ìŸ^ïuû§{/÷ ½ÜŽÎ÷¿9€ÆBËzê&³p²Ç#Íþ`÷ç×Ý?8ß{Ô„64¾ O~€Î#úiÝ0èà:~Û®|ó÷Ö¬§iôSóuk›ûíÊ6Øþ]»’Ú•³Ýº3¾éaî5¼±v‚—0Dúü­u=|t¾yØ­cPo„©¿³Zè»r~lîâg|sÞ<ÀE»Îö͘ÅÁG³¸@ƒá›ñ=vtÎÂn\óS»ê±»mþÝBK¬i¾i,ÚO¸mêÖÛæŸytîxÓNh0k€)†Á2 ­×$\E®\·Ì41)‡ÖqçÙ ÁD=ÜK$8î·yÖúæ5œ¡Šv}sŒm‡@Ö×­ƒ¿+Fh©é섇­¼¦y]ôå™Î`×ø÷šéÃEkñ",Íwyzúˆçšš\òlj€04ã‹Ôv!Û¥=µ‡ÎÑÂw€ˆp±ð‰®î~f•û|‹`0@myq/÷¹‡‡´©#˜q‘+\6Û0y»–xø¹YÉ»§ØóE‹w&i:ñ¢µ‘cpðBv›y óåoDâ´bs‡ˆ#.ù\Ô~s•¸„–{—87O{† ô"õX®¸WzŒþ¶’­ãYã€åìþ # Wѱ7^¼…‹ìÇ‚)Çu¿¿Â4ò$wp’|Ü—“En|Þàã/ð4o¾L½Oñ+’ èÆµbŸ/sãIj¼Ê/Rã»Üø,5žµH»`µì…îˆ|JÄç×ÏòësÕˆó žFǶ׹ãµÞ¯ž”ßWpå¶SïÔ€ÃZãMj¼Î[iÅËIwyoïàÏ;]Ľô¨]IÚßKº’ÌÐÒç“oG.B_NêxV¹5ùEå">õÆ– ªýð5Ò‚âMú9®Q çÂLø°È ZïDÐÆìÄ÷­Kfb²dKwÓõÓ@úù$^z ý…ÝG¤¡~ÏY«CÓA >%aêh¦ª2X¡q@‹ÐwN)ùdShw_$3mˆ&4 [&…MõdÙgÇU \ ýµ±ðÝDߢAжšàR"Mq6äŒÑÒ©Ÿâ‘Ÿ-&ÞPV¿ÙrÜdmO}.ò÷Üý˜'꺉¶[Ñ:䉞G2L™Ì°›7m@Ëê‰4¸Óeâîš¿¦9ÉX¼ì~f Äêñ ñÐ6Î?Át²Êƒiñpr@Bw²!DZî·ãÜ+o$,í×Z3|D8g|´ÍðÆÓº¯çlÐ-`ïö¹Œ`Œ0Ú3œ€­*j4ê “!+Á"‰É}œ7ý §ãxB€J¿E#›EQÛ1—…µé°™°z¼Ø«Ô;‚lg&÷!öŒu"ßzbúqÆ·¾³Ä6Wºµ@5±x7Ê1ƒèTç|ɼÂÑ7¬ähÄb +8†}¨¥ï=„->‚ß'ð{Ð:y–³M(ÔÚU`”MÏ’t¤× Lg³èãœÌeç]ܰsaöâJVš] © $© ¿Ñ½Û5³ZÛ®¤@Ù)%…Dµã4nÙ€ÐV¶A¨Ùvx‘íŒ ¾/±ÁCüúßàã.>~ÀÇ?ðþ¹\ÜùÉ9,ûëÂpft'¯e+fòªÒ è,¦z'°‡&Ø[vÌmç5Tx+Ø[bŒ j– ¾Im‡5ôƒzœ¯¢®pkŸÜï7ìPkˆÀÞGU»Uw#} l%ßp®2LMöººU†ÍpÐ*žq®3>ë–ðwÉ{ŸÌϺšÕh¹ØàqÉ‘gÛ9éÿäМUwÌeÁ5„T@Ñ1Ã©Ä oÒ„K6NЛ‚2~›ß'÷/¼çÀÙöìm'6}°à'‚»9ä­ÎÌ–¨m„{ü*£?¿<Ÿw3£YxžÀß/".{›áGKK|­< ‘t‰.¸ŠY9»\Z [ïd{Ïh#2ŠÀqæ*VŠ$÷Ø#¥ú@ȲŽà«=O{eBŒCaptrGÚ"°+S8 Ê @‹XY¹TgDxÌæ’üÚ-0A}‘4™¦3òDÄì=E ljg„[*ÆuÄ€Ë8å&gƒÂõ  ï5į/ÇßÈâŒÓ2×]2ÊCè¹–Ð2‚•—ª"Û·EÈv_wþ_Ÿ |‘6'®q_UÐY^½n$NýÌŒÍÔ¾"ö›ª‘9+ö?[KM†Ã>Ú Ù6Ù#|?…²F`Gúqû5`6º )™{òónØw½Êj=F-B¶ØÙäð+ÇMË詨.T;7Yã\±žÃU®DÔ£sRø‚Ø)Û®(ç5‡3äø\EÌóÜ÷³bžCš* |®¤n‰¯ FN£¥£¬e¹àYm㨖¢Æó#ƒìYE‡£D&@¼6ÊDtµ3BC™0·É„hޝ»IÄ2<ëèX¿ipܶ?¤áVið|ÿŸ×€åÆ ¶("S?‰d&J'‘˜[‰ƒ§}Æ@M\âUq$.[7JÞê˜2Ç06¾å䧉ÑeÅãó«1?ZŒ@g’”˜=Iõ¢¹OJ¹@ò,C9}}7CAUðîrXK&ù\S;¤h#þ|Ú´—çmJâ[^Uƒ„ ÛN—)q\sJf 3V–£½ R£d{¸…œFN˜;(çá2¯Tì¡Èf+ÏAtRÀ"ƒ)•$¯éê8)VSp²b&ZaâïÀÌ6!]'éŸäYaJâyŸëFx[(ºCOé&?ÝÐÎc¼?:ÀT&3““~LÑyå*g9!rNÓ@=”|UðR4N½ç«¥%"ÏÐq‘e|2SO#º `œ}Ò©N‹u!cŸÉƒÕ²# –>’™ü¶^–{¹®§[Óáœíwu¤(‡+ð>>ňãù8{X¬¿dW9ô6þ—Œ„›&a!ˆŽáÈ®|XUD¹kê…Ùì8ѽo`6Þ¬Ul1ÓHs1²¤šnQ6vB5\J<óÇBâÉKt¥´‹Mì£hIIDÿ¥H¨£UÕ®ÉïÄ´œ9ëa¹¡ígÅ|e qî)r©ãu|‚±¢OÈ¥Nt}æèM: µúuÂäÛ (7)[ƒxÀŽÀ%Kç×]ÆÍÆ`ÑGÚ”gú‰a:Íg|ö’ˈ¯Ä$Ðt¯qNUÞ4²Âö)'*‘0¦–ï©ãt;&o+jÜNvË¥ŒŒªmi@}‰šö¼Åbб÷üF1êTæ­ídSy Þ˜ÁÓ¤â·y¶{tzGìs¢ø”êRÙ kÛ%u§P7÷!ËTôL–²öá0Ù Cƒ&4ô$ÀÓ1Ýn1=ŸQdÍ:OÖq[½HiÿøteøKW±z÷gø¥mP¡©‰„K1ÐÇD¾®÷µÕ¾˜”ïè7ÁX1ãŽ+-ŽÂ3)¶![¯äë0¼09.î¸UiôÛŠId-Ù„ÉuG|äj`•L›@•™4Úy-P:iÈ$3TžˆCùï²ÞÓoyÖ»Õ`]OdÞ~©t”F`ˆÌ*}¡%„_ Nµ¼›äïHZñŒùoôïµ^J’kb5ØlÌÒœ˜üH.äyÛÚ‘™Hœ8›“ 9%EJ$=@˜“2"ÉiÄ‘†œâ-ã£å&"63æií’E«{Æ&&eBD…åz(TL’:zBû¹R®#ÄÈDC³Ò‡BŒmØmÅ'ÑQKó3ZÀNö".âZ*lOu…¸VÒG U ¹‘JåU ºì ­sîIe! ß/Öù,o0° ‡‹þ)¯Lí(‚Â}q  \&V¸uaˆÀ-RX¬¢áÄÝpiZH6Ñõ|¾Er‹Ñ‘WÊF¶ÂÆú¤$öLn°Ð·”FgNî>*žOrý|YÉy«»Ïg,5R†cÍ)Éͪ¼Ž±(šu•¸HK †X€§Š,/äJzJ%gå•…[›¯tâ0Øõ¬BwU¸Åâ=š¡|õUô[Äùï# ëãÞÞÿ:jÌu,ý4}$âÙ/ÓÉT‰,Žoi©LÕ\°ò[1I>7…•t¬¾Q¨k¦Ü~™ñ±â°UU¬ªA¬EsQëÉÂFs—þýE´ltòDFœÌ‡º •ª±Ã¢GéL~„wµ @2óM‘§êÿ5¥À?ÿ#ÂNjVã$ Vü_^C] > stream xœí\YoÇ~'ü#ø¦Ý@\Os%p€‘ 9‰ìØŒ‘Àöʤ(I‰¤"ýûÔÑU]=Ó³\ZC0´Üí鳺ú«¯ªküæ°Ù¸ÃÿKO^|þ]x~}О¼9pôð0ý9y}øå1TJ6c3ºÃãçÜÒöþ°qÓøÃã×?®ºu»Ú¬}ú{ÔãfºÕãuX=YùÕñú(®¾_…ÐmšfX}‹…ß­?þ ÔûÃK†~Ó¸VÿÀº#ÔíÓ¨ 0‘qp~€Â±šðMk«op”ïð·ƒgAû†‡ÎA“Ð·έ¾’¢GP7â÷¿:ì<Ž«¿¯åMûöò&óï¸Oè)4v8Ý– ?‡µƒ¶\óoÚÍ—kœVðP·ãÆ8|Ä*PÖ´ÞÑH©ð‰ŒGCW-tÓ÷þçã¯a;œ·Û[˜À;r| »Ð àWôÑV¶ëЃ<ܸúÊ‚ÊãÁÈû»:åþãê3ür!¿NqDOêr…e8÷÷¨]øðü¸Æ ÐãéÙM‚êëÄdê¡áÓ¢<ñÙèE†°2NÓ¯þ™wûEÿà)Œvõ ¾’Ú'ÙxšÎ '˜ÚáN4¤Ë¦ð *pÓønu«*C3{ŵGÖ èˆ¶ìR–e q]Ø…ÏûâVïÖm Ip_»×Zip\04h7h˜ ›¶C`À…ãÆ£DëIÔwÐaË=%ø4Î轄•âiæý½•}Ä1AêX7„sõx[w÷‚öÿžâ¶ªÆé'Œ‡Å[NÖ]¤w/r•“5‹å:ƒª($j4é ÚGª­ú“f-M´ÌOµð¥V|­eήA¼0}ëã÷•~®ëýäÕHÅ­–½·’”s?žõQ-ôéPw«ßƒVÔWœ„öó:Ýfý2qVL®R׈ýCþú¼Úì:7»™u†_oŠÍ®4ûi­ÅU#އ«‹¬×Cã²÷1âh@aÜ` yìÏ4éôòÁí*f<ОfœOxX0ã aï4å-óƽM9A+´]4å!ú¤¶ÏMyšþò ɨ;œ×(Bý%X1å´í¾¦œúôS®Ëªšr{K¿éÛñ“)ÿdÊÿ“LyhÇ¡jÊÃ'S~Sn›Xƒ©æVú©NÜšm©˜…v+:Ðö33åÆäNŒ$~õ¹êC­zQ5¸ïið±]è)ØžÀøDŒ= •06øÈ»a'Px¢:óLuVS3—L>è·çµ6×a˜w” okmCpi9jJ!Ža±Ùä_&pÅ—kÁ¨ [‚n8 ±gT'ô¾Íža‡ÊÌä Ac7q²“NØK}qa«·44ŠH>)µÁG'DuTv­`q› I²ôq1,cA\PBÐÂ"ƒŠí@¤‚-¢è²:û3rÝì 8ľ%ÕKBáå+{¼øÔxZÑï±ÿžB 4:ZLt•Í /¦«ì<Ïð2ÉŒ&3›Ü|\*Åãj,©k°EMÒ9·ô~#1cÁ«¼,ðY TÚÃÈ¿rzÍÍvÖdCãú6ÓΓ´S: aŸÍt3¶±H.…cÈ¡âv-óÖ‰ g€E]gè|Ýæsaœ¤Î¡p´šñ"+ÀSTsˆ®J y¯´³F(¢º-ÔBøè¨Þ=H‡O<“V]bë•ì‘]¨8/A~›ãtÝɽ,è©´dݤ‚ ›ZðÎh»±ÍH,h—z5Â4Hq•(Vl‘Ù:’CG.†kœRgZg™ Ù²´E™PŠRIàÓµ¢ãɱ²phÔHµc“üEÿ“r=œË JŠ’Tâ§§…ª¼.p}Ohò#¶ê–8öþë.P§d±”6»©ˆ¯ÂZÌÁà 'hpã\[èbLIQãÜŒOÓ:Bìá”&@`Fç3ÊQ]œjBáÐn&tí@ø7=}ªŽõ¥uÑÏxr¥FÊâG›§ê'î-Øž©3F7ÄôìÙÌíc>?Ö± ÛììCA`wÏy³fÐÄ U•šØÆYg÷‡²´ÄËä` M+ÚòùõØÐ *Љ¢º.ùÅäŽÒÞ„õ§k‚*iÀ»-ÚèHc–à ŠÀ0Sÿ¨c´w¡¤`ÑB7aìI¥jpÏ¡s•9³|NoÁâ½L&jè& 3`”–n3t¥÷,Dʪ€Ù­.ÎŒ»eÙRM[gC+¼¬ydE¹0†ä—ÕôelÙY Ëñµ’%M¢8µöBÛR’,…ŸíD0ZX ÒŠÌV!4›f¡Š‰ñÒŒÝÎ}dºTZ¶Z¬e‘ƒÕ88ŠVCÌ-¸`OÞöYAð?ñž¡”:'ªfX>˜ü‰vöKÄœ ä ïò–,VˆŽi3ð~/§dΓuwP‹C ¬¸²AІµ™Œel¢ÌŠÂÍžíUÚoã’NÛ—fÇ ØKÇB)©¼,´i*‹œ¤9Ù™øB{G¯È)šÌ´ŽÔ<#ÊúAï}ÆPqÃBbÎu[*=ä‡Ô}–WÅä+Nã„¿ÓåãÀ. kG&0ü™Õ.û”œ“¼¾ÂB«k…ø²9h îáƒõ”tŸÔlëlaé×ÄÈÀ,¦UãxHìÙ¤QQãÒ‡˜ODŠRÌÀ 7’æêªÀ° ³Ôˆøb òÐi6ëqÉŸc]Û]è3½ƒÆÂQ<9ÉE4ãÐ9« G& +¬0Ë Æ%)d-~’ìh‡—ÚMEçÈ&ç ö».Ž õŽ”÷ñ½˜fè5؈¹o…'˜C]À)Ù~nð°¢®³ÝG•òuH‹M~~‘Wë9qï(‰£Ô·*º1kʼnܚòxî=ð}(^‹u ´¼J&QÎnØQˆˆ7[vïpWR* oó½ô%{.½ßp|;+…bÌDh-ítŒ‰‹_ Š MŸot6bÚS«[(+®7M½ËÂ¥¬œHû(:ßííô¾*§»ƒ¥«}ò´{s)l ²Œ§$0Ãå—sOo“`ègº˜„å3þ¨„ZJ2¡²Ó„, × iÙq¾ì)Š´ü`Bž³ë(ÈI¿е}>-ö",D´“ÏLÈôé„o'°rYOà ûî4-<’ù¼‹š ¸¡ íùšãW³£Ò.ÝØ%9”xõãšo£R”‘$ó[hëóz¡½+Q„?Äzët)™X¯dw(–ÞëaD&ÙuÙ½›ýø¾ßÚGŸ.ÑÕÖhxšwö&5{…•Ë÷¬*7Toƒùi`ß7ÒLŒŸl˜ë QÊ[QÓ®%ð•sfñhçÍ­°#üùô=Ígç¢ð"Év÷ŸŒF‹ˆóõmÉùÈÝäVM½Õ™/«&ÏOQIo“%X„чâöG‚–9Ìq>ú3åFˆDÑ/FºH•Ôë#ŽÂº$E5E£¢lÛÉÕ ¶Ï>X4?GæküµD§öUgz ãgɦ)óõÎÿÏÇ¿áÄÁö®ÄÁouÐõ½^rÔ.gŸ•ÔE®‚SË€iš`Ffd8¥nå}_¼‚/¼r‹ß±3¡ð?.åÈéǤ/V3˜@bFß(Iñ1'0}‹ß«^à·ÿ¦¦­¦÷Ø,`›l£ÉJ&UgWñY%‡Ød:=ׯjÖúÉS×5Y¼ÒŠ =Ê€g¦É,Édñ>´ÉÍFÌ“¯X5§u}(¦FiÍ€¨&­¹L ª¤*ïÌ.–Ì TùÎìbÍšGèî“]ì;ÅóîÌý ¢çðâ|.NPxþnR >êå¤ý2šYúMg™€†…ô>^ìüî„N×LÚ/ù()Ù ÞM'Ù~u÷zwI¢?³„ç"H< ó  OÚ†0¹ È[Žç×Â,éê¤-ïN¬ópïTf“j,©Ì›tMež'1Sêù/IbN~Ò$Z³+%Uá@9‡‹ý¦÷®¸3bЬædßjŒr'Ÿæ$ü⃠àJÈ%RsÛ`Z-d5Ëã‹ÊãÓl»ï}7/²(µlæä¥;Ôi¶s7ÉtÖç2—Û¤)™Ê)p´»ßNÊŒà‡OŒàˆ˜nŒÌNrÕk›w]©z+)Í&M¼ÌŸs‹WÅ"c×Ò‹{ä9£‘#u0:a¶èCm;¶V)LÆ›îV¥ÍuM7·¶0Uæmîzkʤo¶tm=¤¸3¾v7êù³*’˜X³qbq4¢1¿+ãc? ŠÙŒáù­4鋤Ðt¡|VC÷žÔå§·²å㘓£w²Q”\uü;‹¤úDDð”DŽÑÏsæÍ[nrƪ›Ž±ŒcþŸ:«Lmƒ&`,¾AÔ°þ“­íãOÖöÿÖÚâ+(HØÿM†ñ¹™~¥Í¹¾«ÙÀWõM½ëE£_ËìüõqÙê>:>ø+ü÷/ÛÅ endstream endobj 323 0 obj 3993 endobj 327 0 obj <> stream xœí\[sÇq~gùG *:ëâYïÜgSå¤"Ê’•¢E„§â<ÀE²DAHf~}ú:—Ý=”ÊO)—)`w.=Ý=Ý__?žM£9›ðòßË·~÷m:{yûh:{ùèÇG†^žÉ.ßž}~Œ…'ã<ÍæìüûG<Óœ%{–œ'{vþöÑïÂvqÿsþ¯0ÙnFœÇ)äó+ødØûÝ3Îsöóî_»ûfØÛÝ9>ÿð×ß{g§q2×ÝðÆÚ^ÂóÅà"üèüî?càiÍÛg°ôYÕÂØ½óy÷5þŒoÎË›oqÓi²q÷%¬âàG«¸@“á7ã#tÎ5n÷|ØGnwß ðd Öì>lg$›†E»û·:»<¯ %D¬`‰”,³0Ÿ?:-rp/,Ü»iLfž™“N’°~Òç]‚³›Æèá0{ *gcp«i´6O.36æ)àž.M£›‘kðÔä >µ°³>¦1ºlbÀ%œ#H?Æ<Úäw°±›¼Ý]ó$û^áªyL>[„|M$NF‡ºyn¦¿'“vqv-Ðt>ä4& L-ãþZ·yÃgÎv÷§m!€§ÑûŽ's¼û€Ì÷$w³™÷…!¿#6†ìQb´·KÊÜè®þØl_)¾)ó›‘uÓׅΆG/àaŠ“Í»[¤ÄYç\*‚òöy‚[ôôÑùoQâ0ØLÓñBLcrsD¡/Ûv†t„‚DjHì†Çš æ½¡±ÙÎH·cLÁîÞ‚&˜•\—AŽ '”8ªZŠðFÐþïáÜÉúuMÚÿ=2Ù`]³Ô^8/òô,zþëJi»Àµ¨ODý¢˜:gH@É>Àânv¹½ÓµÎÔO9ƒ.ÜÂO΃é`þ[ßÚ.`ßæ¬0ƒãQ ›W¤©&î«ÁÁú|ØÉ“ û^á eÑR+#š,<¼y;y#%wpݧi•÷(|ãà¤ؾ÷f§È7—x…ŸÑšÝâÄLûáÈ÷¸ýD[]ü.nì3Idì£LEeÅßýÄÕh¬L!ÝOð˜‹ëÑ:Dþƒã2Ε˜ü¸ª¥C}9è~_WßXÃ縸­;^ (ì}$’qUpT‰Ìö«¥à€}¹ø•¼^ëˆF¶ÕÂ]gì•í “2 ÚìŽÑ @?W’o‘dä‰oÄBåw/a |ôÓà訮ÙéZIÂ#ìASÇ|~Ç{t¦x–¿Í@s˜ãAB÷ôÏðÿ¯ÅÄÅIì:wD샅 o‘ÞT?ZkØ–„Š,'e@ >£â¤µਊÛÊ»b/16Í…©™Õó$}̤E…·9’"5¼µ¢nE_{¾Í8Ÿí?¯üªhà V @ÖÕ F¿¤c;癫䡟2ŠPGÿ\™DL^‰ùcÂôì;¦ë\¹q­JU¨l×Ißg˜üîIrW¼öÂw‰Êû6WÁg[·ÍÓÍuzãdÜœT¯3½þJÕäÙPñ›¡Ë1ïþÖ{Z/ýS$Åer·ë@Ñ5åI¡r2E ¼%”‡¿^éñYg3÷K\ gÞ ^1z‡øý +°x¶EªÔUøªœôYAqz¶g m#û¿Ù_–gõí»‚ôÈ>¸7y[K‘xâg!~K‘eY±&|R¨Öä~Æú¢-¾ÑÊÏ8SäPÄ"î€]Ÿ«B|ÃµÊ ÕßZ¨ËÍ–š ¤vú=ü¯"#ýÄý–°¦èñŠtq´z¬ÀJKÔ1S{«Æ£`cî‹—b‰ªœZ¼±¬FèecQ£Žb“’ÍlìÈv\«’õÕ;!²“ÐÀç{ì-@ZÐo \±ˆþQ(0üó …q©íî/;ü÷ÿÁU{GTÉúšÝ?ÁÖNM¾®ñ¾Zë›òðçúð¶<„•]•Ô<üPG^l=¼+oëÿ ú¹PœqÙ §}ZþÙ:w¡AöÄÓáíôIS¾Ypã×åÄÑã?9zèÓ„}¹uæ7Oa/AùÞÀós^¨¼}(8· ­ÎÜyE§-·ÌDÒB?Æwq>í7Ñ‘ è>2 ¨¾ŠÃhÁÙóïø¢J¸2J!–ÛÆ¸ ÞaÜ}À‹éOlæiÞ hæAÐÓbØ‹fˆ™çˆÓÀÙ*oУ²ÙÕ­.)q“Áïm¸2Ú€bá…MS”Z/ZAþ’Ÿœ~mTršéÈŠžº…S€Ô¸ò©UÓAØdb…Lí-ÆD‚âWºå Þ+Ä^0ì. Û²Žþù¯ö¾©ðްò5-¼}¤Øaä,?ÅÊ9DÞÖÅ…@[•ªÌ±÷‘%ft¶Mp³jÂÊáB`x=¼W>¨J²^Õ=N?Í>\ñÕ5¯¶à–®. 熑Ÿ…(“°‡.óß4´·§ %̇ÃÂ^0°ëc$Ðk°@L¼ÚƋۺm1þ¨¯ 2¸JcnU£ ê› @WŸi=¥‘¡‡)MdE¯»9‹àLÒ߈æÑrìh£‚bÛlUߊMÁCõ&EÍwʵXò²Ù‘?.öâ¢îЦåœA•ì‹«¨µ ÝKÁãâpÄž£v;v=m„竵 ³lz‘’ø*°=U¬{¾[¹>44 Š‘ãq#ñ€ä4tT÷c¬ÙÖùÀÀºî]1xUpU,H§ˆü§‡q(&¬Ó½d dÝe>áœ9¦0»S«¤8|صâ\«z`âcÊÛÁ˜¨ =×,‹è‡úÕa ™³|§Žvf¯«Áã4mPVm®T‹ &€Ý^i¤GD¾8®ïM¹‰–jЋ*ÚX³“°§ü†§Ÿó";Ù§3¨|ôLP¦“UÏžáÜP.*Ý™¥ øßµÂÝU­Q1èï06M”Ãdòä›(ärMúÈÉÐ Žä•ÄÕ÷a±˜ã‹sÄâRN ÃŒ$%"•-þ£ fþ'²}‡&~'ÖÜ©q;Š÷¸!Í×¹Ê#çiÕÆE ü·q¥*pù“ôÖIMšø5rÆ9 "uU! m¢”sw¡xùõ4„ë£ý†kÙÊ2/ýRoû8Aç6s)y†½P»7ન¥9Ò²õ>5¹˜=YF}-^a÷i–œñ= Þ¨á<Ê¿ò®u‘Í Xwb‘š¢i…à8Gæ|-ÿI‡}Óe-1ÕN5‚ÜÆÌS °dÃ|à$eÝÏE<0‘½AÊ{ilÁS,àÄ$~…ÖaLE:Ûà=*á¶ûPŒxç¨HµÞDéÚm`µˆ•˜ÀÞ?Ý#t¬>Lt{Ñ‚z,À¿¼Ù” PÁÍ¥”ÿsp%+€´7°¦:0KD dUTVEe•û%u‡•/œ×Yåñ}ß62’C(Å5㊉ã`Û2Ìe{Ä«Zœ1ß¼Âyìš@Ð5~Âc‰ÁØ•ä×1±BofªG#tÐoæWóvÿ\ôIÙ8Ûž~÷5ÂêB4>’ éxƒgµínŽùÞ;,>Çœz,Í¥&Cd¡2õ¢pÉwƦG+ —§Þÿ…YìÓk[’ZVàƒ¢©…+’¥K Þ@Y¤fR0C3)Ü}Î ‡Í¾Qà#è‡ÜŠí }«£³~Å=À¤ÕÉTâ…+5Hä[éÝõ¹Ÿm—v%Þu2¥j ;ÞЛ¶l\ð\B¤"ZŧéÔ•bN­/¢bÜŠwƒø-ÀŒ3+5¼úÀp •˱†«)Ë;鷺¾ïÓ&Ô> À*²d][¥j4E÷,i¬`¤~S ý®ë¢"”÷gÁm³œUK…×ÕÙÙ¶`äŒ2^aÔé9A¹¨*Y”Í?"øLø¶a2î4§Ýg0mØgøˆm˜˜ÏáÙƒM&c|ÜP‹=âºê"¦Ñhxæ¤ÍEgœ>R8RÝܘš¹ºª®²mFº‰¹NÈTäTtUb jA ’Ã9Åî”R‘ÃK¢b÷¿DPÉñÀŠêÉî#‡”&Á¥ö5€o“TÀk”}›ø°ty,µ"äƒ Š7 ŠÙWÝ×gèÓ¢×_Gœ±¿0áÝf‡„#½Z)‹÷\Ó&F5rÁþ‡Ñ`¹eˆÀÜ¥ÔdKÿöCÍäç½ç#/MZ\4/…Õn乯³;-°òc¹lp·ßÇÖâ™J»’Àh0®±ú³×ƒ: ‡8s‰ÑêÝ"“רÆê2ðIkŸ–w„r®6D^Uja©¥cAmÜUg «s:˜XœK?QµIxµwÓw3-öi³#ïI%|WŠÝžy¬CŸ] mh§æÿñ@ÕøÍŠ“s‹RÔ©÷TäVŽ}r`Éú&§ƒùŒú¢têç…×hv_ ]£1ŽÅCÎšŠž„>Ïîn‹áZ™'NKxYÐ.–j@Êå…¬Àf*e¸.‹@÷ƹ\ ¢> <Äþˆ Ã#ô–¦KŠ“‘Kàzî‹ ;Ñ“Ãë 6hÍ9Pª*)Q²£ÑŠ®Ñþv#ñ£UAñ3åÚßS§mki8õ`-­l«5¨ù@?¤îv¨m±Iz®sˆ-‰ÎÜkxÈÝ)vÓC^ø$({ºÅÃÑ®’‹[šÄ™ºØÛ]š¶ps˜Õ/@R¸uQFŸìkæÿPûQœK™©´+T«CW’Ø™%q>dÇ‹Þ0ç~Óui>Þ{3ê2Ë´ ÔØ-ÙÍä!SýëôLP¶g ê¾íß¼+kšƒwÆšîæ‹¡™h¢üˆ—+Û–‡ _§Ø—(åNn»LÕŽãÎhÕÚ$EÄï@ôGÿ„ªÚ—©J³ÿÂM}]м$ǹv˜N·1øIÌû21Á] ©°CÖ.t#5ÔÐvB·Fcr¥¬ð†J]‡û2$úºÖÎìoøÁÌ16Óùg*xþÂÌt,©ÝWQÃF‹õÊ(í'Xx1q c͹誮âƒôÂðġܷ cp–Ì)½gJâûƒãµP(­ÕïÕ‡óJÒ ó%Œ•ic±ƒ›mÔ ¼¼¨±Áé1xªó…HÌDÕ2‚žScæê‰š¤pßl¡Z>.›?(f©ÍQ4@¢ŠÔŒQç ©½ï{Úk;Õ—Ÿ(9ÑtôÞj†QNÖÛ«OÒ —WÖNµWƒÛòý ðp~mÙ{Hµ‚sÌrÛ›\¡4BŸVõºqŒ¸2e¹ÉA®ÒØ©ŽѬ™ãýP*ÑqUít=¬UWú^tª~ÄiiàèNõµ†ÕY¶>V4ÛH: Á#Gò…‰%–S,ï"Nœ¨¨uW…E׊`™Ù#ÿ¤ïÅþµªÒjJ,]9!¶ øpBýذX3òáWÆM¯Si Ý¬¾SíÓV°ßìÄoð{IDóáìÊù4c”4GæìHBÉ|$®ÀjÜ-6,®8>ýf;Ž¿“”/…ºh*ÎKE‘&™ÀdlX³˜”O5î ç°à´®f©—Àbýì5?J—ªiƦũ´n€pb§“ÆtB¤¦Ñ‘ã€Ôõóò5I§:*íF9ÞfP¸0“êÇÒÁ¿´F›mLMÌûû¾WMNÔëý™û4cùŽTµ¿Æ©ÑBŸ„®ÈRbKš“~/òlPßïŠû”„N‡øs jÞ,kò—ð¬´Ó—€†MèóÎö÷¡ÆÕ¢¿W5^(‡R]m§ë/¯kÀ±ÇL½{îNaùËÉUŸ üylÊäÍ2‘ÚÁÇ´«üuI…Ö"α45-`SQí^a©¾p°GW+{Õù6!ÀV–½I]‘>÷~¼Ü*é«;¡TÚ®Jöt³P³(¨ø €x¦cŸøÄ•èE“Àë¡·°a±a^Ø[Âÿ~i ¯ŠrWꉖF_Þ)YM¢ô,z@ê>râóº|´kl‹ï¶Â¼¶ý¬uQ3:±–½4Ö[Ç’(…{‰ªê˜´šX>Ù5KÀÿЖl\ñ¢E3w™,«;բ冈”¦ª(ŠzwBs·|EhòAø¤"lि•qü£²úùÿå :#¥ªM¨°uÉüðq}xÙ$í6>«û0PûIÄ2~ÖA5ŠÑ&×L¹¨¯?4dP|èioƒ~ÿwÏö×õáÝÖþ•ÇO âzöÿâÚ×ÅÖþ/Ú#U®´¹u~øf‹ w[®ûñ–4EÚãKº¡Ü$õeh„ “èÓ¿êŒVIRÒÆ..µ{ð0±=ò6T8£ýtðßP"l£i«I¼+Ѷ·“˜8ê$àŽœãÎÍq×z ˹M±Æúk­×£òcßúEíM¿¢u[6_Ëû‘'tÙ…EeÚÒ“eR{$´X¶{/. ÿŒ2wØûðºs|ˆ†r½âÚNýšÀOµ C¬ü´Ï¥¼7¯¾;aÑÑ7lè定¢d§C-R—ìtèAMþ%ŸÕ¨O¬]óe{=²Ü%¤$tÙ¬àµJ[%*š [ušä¯JM%0>¥¹óÞ¿jBq#GuŠ=Wü¤q mjÄÝ^FD›ŸÕ>Œrê—-⨛3Kܸ½¸]¾ü³yÙ]Ù.Ø5ë2ݽŠ|jA¦i“+pX 1]@&µŽï¤a“]›²iÓxÜ9•|§w[}B]~TôÏIÛ“*‚™6A#U3­>ï,ýG h.w*$Rg&€V}ëÔ\FiªÒžùf£sNö¯Yy _‘¼Š«Úð¨»×u¤„JrÁûû½Œ¾š ¯‡ãú9O£µ¯ÚÏpËWL[@i«¯M]ýáüÑ¿ÃÿþøðI endstream endobj 328 0 obj 5382 endobj 332 0 obj <> stream xœí\YoÇ~Wü#ø¦€»ž>f¦'ȶdİ|È ;΃LR¢‰”EÒ¶òëÓuvõÌìAÙ‰ $íÎôÝÕ_}uôþpÔnÜQ øÿÓW÷Þ2=¿¾×=¿÷Ã=‡/ø¿ÓWGžäÁå'›±ÝÑɳ{TÓ þhqÓú£“W÷þ¶ê›nµiüjÀÿ×C7cêWš°ús³ö«“fW_7ëúMÛ¦Õƒ\6íWÁ‹\$·5ŽÁáGßbe(óyþû1U˯W6‘ڃ痦8®ž4iØ´®÷«o ìˆ]œ4)äv:[0×Ïï\ìWŸA+¡_…r'!7ÑÐíØV•סk©×÷óì¾€ •&ðÛxIð4’/`båå Ï“†ž;–¹‘.ÿ÷“Oór;o—;vyT)¯øÉY^å.÷ŸW ®£7)­C»Ü8R7¹±ÕyÇë<Ê?=Íunrç®Ë㊫Óüè*?º…±_6ÖÕÛß­òžý£½ÈE`µòZ¾Èc>mh¼ˆ>â"ËkøÚæ¯=vö2?ú©ñ‰–ïi´Vo3,¶ƒîv÷,:q8ª7P†6¤lÚ\N܈Ç„Þ4Üôþ=†!œC4H™3<Æy¿Êû'X‚üýö廆jä>·M뺥í°Ñ-¹â©´.>KØM#}ÜêS™Ëò½?£ÕöÎO?ÐùAy]ää–6/´¸N4Ò<`ë”êMë§ú ¦öž©lú7r¸¦I®óÔº9Ìuiyé/á”$®Ö5ìí0|…×±×S½õäãáé@Ôm>À tÇAÀó›Ð¹ˆkÈoD"é kA'ëÂy£Uì© ÍríYl±M(Žíøq*.7À’zØ¡Pz¾ z‘æ>`ÝéKmΛîʘëóÂ;‘²²9µ œºwNRk™ò¬u¹ou«Ô Ü@턵QlJ»póÇÎQÁKmá9ÎDJË2ÉÓ!YâÉ 4uc:Hšú„ˆÏ'1ôåró¯àùX@//¯Ì@KÎmîc>ZïqÃ?W|¹²sŽm"Õ»Å87y!#ìH)`¯Š°ZTV’d.¡¸^-€…_ëú½áצLgS‚åöcWà ÖÊó)+„—0Md¸Âƒ !uaõcppÁ`Dy[6ýEã¹fä÷ìYW=ÐÜÔ¡eZ€3 ‹ÒËŠ?gEHó­‘Jƒa# „1¸~õžœ›HËÉ!P5ݲç h¤éø„©‚¼”óìü^d䲂²·P˜–k«þt¸3ihÝ~½wŒÜËÞ’DJÝÆG‘ 9x" •ì©*B¦–ø€æI“ó d&á­ƒ üL»‘ë#Gb!xÔàJò(~øÄ4÷ºðœ*"w«û «Ø¬e@'çÞ ´æ·$14Áަ”‡×²ÃI!f˜æïó¡(䑽ÊUëdƒdôôERðr¢tƒ€!¤~lj©ìªSy½«`¨mgÔÙ\;ñøUèÏ*H[Ð?!ÌEƒa)´~Óy‘ª©h’üLä“¢vM•'Ì\‚ßœÁ‹ Û}$f§yœî¢ÙV%b[)b¿UïRE&J8¯x="tŠr®|—ywľ·£O~ëëXFŸè³ùÉFL„ÁtkaÌ,d ¸Qða[”JAi`ȆݱKr¬ˆcn“zg¾”¦|NZŨÇP©Yë†òÔ¬m ªùnDÖvó–2¶q± KÈTï™åÐjT©Øïl^E?ÝÝ—ø7?ör›àÖ]f¾†ÊœMÎ5œ}çq›„Ê‚Fði‡ \L"SWÖù˜Î)´,çh–úâH&cñèG &ì6C/;K6Ãh‹ kPÑzŽ•:ùX÷-ªÇAÁ¸úÇá)äã'@æ<ºXÙb2¢ S×"“4t¥2“`œÇœ§Ttv@ø¯Ñ_m9ƒ^­dR0H\•Æ”)àãŠ&PèéhÎñ~h >©‘з–¨j¥ ¤ 9è‘¶2ƒ‰…?ÕýQ§žˆÞå™" Æ…yAÚ67©úe N•·ŠšËŒ7m¢‚ïÔÐW;%òª`èpŒw£VbpÙG”Ù~XÄ›ûW×ã¼¹—¢éì4ÜvèÝ5rbŽóƒŽ Ò€Cè NqǨaò’£X¦Œ¿Ä¨<ÿ¢—àôeo%æiÀýœ4;õ;‘D±;Û®8 ¼îÇóa¬@± ——aë‘< ˆã²Ù0 ¤‡k7dýݳô äYÄrðD¥-~FîÐ>2éε@f=‚_ÄWâÓt]M6;»úðÆ¬¾¨¦„b@ÿ?Ã’Âß{Ü’nDµlóFŸ™á¿Å›!V¦žpÀq3øâ:«œ¸¾Å h¬»DüF[&.9Ã<8±fn–?8D=–AÛ¹V' ðèF1]áDCÍŠ¢õ9•V`‚@?Xo8/˜i«¸7|5Ь¡ó”ð§³]/bRœRŸHCÍÜw„ÿåá/QïÌÃ%çÆb_(ù|R­ç †Y“^€šDX ÚçúBÜûâöðìÈW'Pô„ÐV\ÔZ!ðêÕ{_¤¥Ú—S£t¯)P¨…uèÊfÎe¶ ywÞ²¾¯ö K±•P Å=RUc1™–¹¡U¿Qâù¨‚§ñ,ÞȯÅ>³6¢¸rHj#+Ê£f„ÝÍ“ÕèÅJ韕‚NìëIó¹n§àXh S0•¥ÀG•o@câ´€3¤Pж¸g9@!*!µØÐ>¯ab¢Tþ®DTE€¬%€Hq^ÐöŸ•MjÆô©˜<ÕF.LÕ¶¡D™b²«•¾:æ·:ç1¦·R Uèwš{liÌ81,œ†²ŒäÌ 4A¬²ì[5îøýÅ}/„#+l[û4ì§4¢snL‡û …Å\·‡õâKxÿILU–TÍ›ÉuR1}@vÿ|"Ÿ¨àëgðÏw+ø÷þÏ«¸¦óR²áì„5ùúpm¡œÉ2á2æüÁÐù¸úœl"XgZôi)z³ôð´Yë–êçú鸼~c_¶:øTÞ,5ô“>|±ÔùMyx±TýÚ”DÛß ueåÐíÕS¢N†A«Ð|vïä÷v3!… <6\ Ÿ}óÿÍü¯ÞÌ÷ŸøhOë:CT8±%™.6a)%Ïe\Q`üC¥uö(±óÈz†™‡çL¬#ñÓ÷¬MCBâÝOÂAgµ3ñBš¾®Šº¨ƒåH_Df0¼ *jœï§èíN'¿èÉ—3VúMT£mÀuÀL¹¯Uï¶(¦üiN­˜<ú:‹ZåzwOæ£ÝO¶ó‹¥¢†“º™ÍVé'# 6BŒ|–#AË {_¢•0¨¾›òÔYŠf冨œŒ->‡@:|K…³`¢VWŒôÊÅLwWi¹rˆÀÔþ˜ú“¥_ßDÿ²“$¼6ŸúÞˆ¥,Že s ©µøóL„p’ÇT;¸aÁd ‰sÆÍù1ÛÈîsÜï,9ÆÈ…7”SÆÀ>"œmí$2‘¶µ“ÐZßU¡5‘ÇcæÌ®„9OåµÂ"ß꾨9[=_5ó—JéõÞªü™›v‹]4ãœ^\’ÍJÎíj ?d¨íL>Ï`¾½ZÙ‚]s[Æ9Ï k¢´ÁÃo [O/ „òNN¾KÑW„‰Òè&øIrõÁаf™Î;e÷ª:NDMFò/WqDñi4¹ÚFtohs’í1ñ.‰”EB±Ú7ªªx²Õ•ó ’ hao#)ö"Jj؎‹wôW`L4e¦ºM¯RR¥;V™ æûÊ»°¨“5²쎈KaK<ºŠ¨ ÓnÐÃjˆ!‰ä<ßµŠã·*è·+Ì\Ú=JàÂÝУP 4¶›6µn›”A;׆# ‚Þ‰‚‘'Ž|Yu½ å/—Ë¢-Z>[êòMyøÊT³³Ô6z¥ØÖO±àÑ©UßbŸþsÉŠ.öö•¶s¼Ôa™ííB‡ÕªI‡eàgÖ™‹3XçÖ¥¡×Õ¢u.Eo´èSæ2¾$ØÌ¬ñ±›ªà]ÖxæTTî³þ·WÁ~¬ò~‘ Þ!…Œ°ê®Ð¿QýÒÎeLñzÓȸÉ×Â)m3Ý$µò`MÜ’'ü×ÐÄ©ßÄ8…£;kbL {51ûâKM¼ãëØJ,DZø²4ÌNJöH¨ý–›'’rÙõVS@yQßf]y§;f5é¶xNìUÔHwê@ÈÌßá±{·¡œ§}רxÎ U2gô¶aç—RfBrj@¦4Ëÿ‚Ü=G›/Š€äŸSÁ~O“ll1Míä!.\qã–‡É)‹‚Iî-Þ ËC(H6ó„ÿ9©¿ß„Qý€›á`œ§°j@ã¾~ ªŒH½¥R§Å[z_ü!“—Kòrj2u0ƒT^€Sj$[Ç5u ððëðdåýÃ4AÒÛç"­¦«øÑí½5 ùw¾"†KËY>Ó+bpÁ,ï_‚0x¥¿›]qð‰®/lK?n#_!Ö…0 rO¶¯n;Ö ¸°zæ|é\ö›Òó`¢ñâ²Ë‚‡‚ô öäAî%ä ¶~¯×·+½%ÛOsûî E€˜ä`Ò‚JDjç¹ Ó´„ØRJŒr•™GN6k¢¬”·0Š,Æ*ç0Lò÷ç­pæ×{\’žÞë0`žwr!¥®à‰\€Ãö]"‰œeà…D¹Fï'_F ÷‹#t Ìœ»Þp0C¡VB4§Úà ¹ 6 >5tÝÉëšW‰’â ?Ñg¸3ü„" X#ݹ›žÙÔËu‡ò±õ¿7(êÄ®dvÔ¬ ¤ußQ@ïAµÛÐ$¶„&¿ÒÏBFаjŒx=; hàHL²¾û¹àî(W9lnpñtDJg, 鯽CmçT_&Ðòιþ/{6n']¿Xrb”1Ë|) ¾â»'2_Z7ží­žóÝý«Ñ¿Å"ކ2ò-Þiç\ 7– H‡·K¾,îŠjä&æ°Ç 2ólTÎölÔa³jÒbñϼ›¤xü†ƒœ h…jÜ€oNã=18¸ˆår à§˜µzÛšh—Ä€—¯¤uŒ=Èà²zÍßj /¦íéºÈ®2ý¶ü†^BZŽZãe#¾/^Ì‘—lBT`à9L2@ùèLœNÿÛ «¥Îu:ŸeÅŽ‰{×4@)–ßgp6ƒµ `E_“ƒµUŽð³,mþ~ÑE ŸÆf(÷6ŒÃdÜŠ§¤ v]ÍoØ©#IÔ/I[Þ8I2•N+ïÏć"¢ÂI†F Úßýp#Btôè¤Úg_ó/èzhj|¼ÓzȲ”[K•SgÓ˜äOî}•ÿü _…nendstream endobj 333 0 obj 4862 endobj 337 0 obj <> stream xœí[[o·~‚þ¡/=øl——årR ¶“4Enu•¶hœYòE¨,)²œØùõÎÃ]ë(5ÃÐñ9\^‡Ão¾™áþt8ôæpÀüÿÉ˃??šŸ¿:Ÿüt`èá!ÿwòòðþT0Júy˜ÍáѳƒÔÒNöpr¾ìáÑ˃6c7nb7þxô7háLÕ"Ìý¡ÑÑ)T|Ðmýæ¯éç9úyóig7ßu[»9ÂòϺ­ØÆ‹ôà>xšÊp1 ( ›š¼ìHéíæ Ts4Lú„®éj„­7ÏP?á§aá4FØœbt'\­œŠ3и_¡5dÕM7Éh9µSüí•6à\h4(=¼”ñq[œ¡É/F8¦>Ë@8å'ØäÚã€x¬¡óè›bñëEîß{/Vó $¼M=û†grnžGC³¦Ãí< ˆâß[<Ÿ3LHº{‘9.IVý¼ÈŸ¥ À 2ظ¦ôÉÂg~˜J'¸¬­]o‚9ÜÂžŽ¨C´>¦‡âxÝaÑÏ€1"x7FÚõ'Ymòz¦Z¿X¦„{¡1áÏ×]Ö“ÿJÏoQwAÝ#Ë‹#À3<¤{´k¤¨*i 4GÜmïeJŸòš’*ì3¢ó­±+Ù%‰@²¹ÊÇ û$|ÊŠ3÷&M8dSGÚξ¹ûÐ Ãõ…ÌÃí£&4œÛëŒë M¸PcÐóÌyÌÒBu# "¿q‘¤C¼DR¡qf¨Âs€6ößð÷%T”ç'éDâÑ6¬ðµ…º1W ï¬6£tú< ÿ'ÜPRtÚàá\tá² ¸ÆVÕ¼Wˆ}ôíXm7àŠ “s6³®Á¢Þ=c‹Ï;’Œ«Œ7À8š™hl$›ÊšŠKêDÁ@9XfÖ°·™T°NG_é´ì^ßµ ¾³±Ÿ ;euйÿâw1÷/o1÷§¹ð,›û—µév$:eº/òóãÒÑÕQ›(Ô/Í×3zÚ2÷÷Z…7ŽÞ?o˜÷â »t€’ro-ê[`ë‹+ç5yà2ÂAœ”etã¿ÿLÅ\˜÷Ãb¨§ØD>Oô¼Æµç„˜ %°kÐw²c`ªG ã‚Ÿ5Œ üwžXõ¤Íµ¨ ÈÞI`¡`í•§qÊÖd‘$Ï·¨nLѶ,cŸ Zâté1³4g4!ÉšG$õ™ Ýd°MÝä+:õkî%÷—C  V5_ÎÍ `W4dð$ ÍáÔ¶´)k–Ï3™ŒÅxX†dÈŸHÇù$×·Ø6Q”ÝtçVÓ="¿;ø{O8“aØAZ¹ÓêHäÃ`gÕ¤Åk_±Bù>z#¥µÝ †M#v•¶×Äž4Œz­ 6i3mB©£ºYŸ®Áf÷*m ’ˆ–‚ ÙEðU»•î(t+‚@}óNÈEV0ž¦Šùˆa½¼èØÁQª ¼xH\_NdRÉq¤ÎzõÑIF ŽË'8øŒ4ÆÒ1*cÃL ¯î‚¢@ÙÐ#ÍP?&VÔ¤16ØZã£c>qµÚ0´i iWœúà‹rÁp2sEkÒÆ0·ñ6UCzoD¤vva zžtØ9ìÔnŽ#hŽ#UïHl¶¼È¨È½(žÙ³%¤ØG‡ÐÙX9ÉeÔÞJ›\ˆD)k7 V‡|þó,<š×²‰ÙZ~+ì k&ö¡MÕþ?T~žæ§<5XÊu‹"äÂËRxž /2UÛÁþ$2SìE“©R?“7*êS³H?úߟùù8‘f×ÔOÑZqço²×肜Ð×Õœ4 äVM迬Vš<ì`‚qàÒ”85ùž™«dâÜÂÊ‹FSXLfZÒ©qªlHÒäY@ƒ-Á)<®½¼ð8£ N„‰$ㆠ‰¥Q™HÞÚˆëË®ßdñs˜©¦Ä¢=‹ 4`ò´§fêcÌ6]æ0"¾.ƒ7o.¦>Ò SQ?˜?ó‘?C“oé7q½š(Ý"pÖµ ®ªò¶C}5p:NÝPƸxùY[pò¾åLºP»Û+Oûñã4s¯­C9l¸&!.¤(;™Á¤8ìªøÍ§½iÅÒŠsSmï§0ö…ßþ@ m‹¨xá¯×©*ñFrêI¢„i‡}E(³Í’ ©S>ô0…l–Ï(ŸlàײCEÔã%‘–U,~SÍÇhñ `Ü ™`±éj÷šãå%´Y›H®ÕhXZå=Ì®¿»¤`Å£¼ÚüçV (@Ý´×z¥ð—[,Fe2צ§¾nµ”‡Ò´|X=tíÂÙû1'h‡®Ðá Ê4A¯ÓºØÂÖ[Ø"§ÅΛ¯`AŽ4ÇÀò¹Éo¶ ùÁX°§¥ÞSPÓ!NÞctä…ˆUÊøçEØ“8÷~‘!ËÆs ¶S ?!O• h-¤Í§ÈMŒ± f}†¨¿¦‘¢G‰™ÞyvdtaƸçØ?ÙüâR¼:Ñ^NÖ[²Y.¥æ <­³2» iߺeYÁÚù㯎>Vì“ÖH¾KÈy©˜#HžM’Â<<zÓ\œ5uZždC}Û1bKy¥PÄÒ̰ìßäˆO4dBeVè~¸4µ­€ pÝŸ)ÿ(Öû£$ž žPú[x>8—>”åŽCífOç”=¯ƒžÉD+^6%Ù ˜C‡%=K!äU>Ôù$ü:f·ÂM›p  ){©ƒ nÒ(‘†âƒ›WíQš¸)=/c/iÙ5|’<îJ,§—0=L‰iqN‚MõëTòHÍsÞ,O í6AAÈÔAÜB›²/ºd1ѱã¬'ÊÑ©v׎ÙϼjyEÅ‹Â`tÞ ›8B mêD¢5¬rðd‘ZÅ~8þ^Ìõ5aȦIŠ×Ú5÷3#Št8ˆ‚ઋ…n&áR:'0?ÒÆÄŽ u¸ìVUÔ® ߌ%8崻ݬ/: TŠ×[Óº IšBñ3ÆQÿ•Ò@Æ— o¬…ù"à%†`×P`'£Q¤D7DC?’‰žR/wñ9,Ó@Ö(;EÚdQX‰ -åëW1a´ãÔ©ISÀÄtʪ €©‰%Eµá ·°†àWL‹•Ë» Ìu/©p\`¸¨Ù°/¨ÝSQA PÙ˜e@銢#¢Ï3€íóFYHŒIªÍÐáÚ’PÀj_U–nË‚ôM8³.–1&‰Ë`ÆÖdÑ@?8/Ò®¨1ôä<å6åÏuÞfÛî#¾R5DrM?ÚuxeH··5Ʀ €øQÞ@áåØ/Í jr>’ Ê›qò!½?iuY‡W)è66%Dâe7 I»ñìÞ‰ypégIÄGYžb«Î¯Â¹ê¬ºtÓë¶³JÄ!›à„æ·\6±‹Ô°ò¶”ÑÓŠQYY¤c1¨” ð®øªT[È× gÀ[uÊÎz"wÈ­™”0ø¹£´ª/£aU^¥ìï%0Oä—¦¢žåèé;˧ÉÀc„ùœÇÌ*Ìiò¦ œSW¬L¨TºM¢IGá%e@T «­—žâ{XvX«(F¡(ön ž¶«Ò7¦"‹ÙîÐ9ïÈ’—v¬!h%HªfÔµ—•êƒQαšòVÉ«¢5Yª&ÓTº‹çôLÚÙQ}]Ls&”áI—¯¿œV4mñxd­O%Ì#Ê6T<=­¾V1L7/RÑ”èïêv¨¨Ày.ùÊ(µÜÝ©ÝÇÝH™mlo .ªü UDVñ~Á£:§,Åç¾ÏþÓý,JªøÎf¦íø®ºEkô|(Ž&÷€8jIý~“’ê¬n=JH;Ë þJÆq4}¦Zw»õ¤zóC$«(ÀeŠXàAYRq’:JíªkçÚÇ[îå%óF¯[¢uI#ùB!%³kwB7ŽQÓrÞSE–GªPâÌzrMrÞ¦t1#áb&EKÇ™P$˜’/ÿÑ¢;ų¡ðÄ´„“ÝÀ”¢ ±ê/á5²×r½ªrüÏ“»0s¢¼ê ;pƒ6q²Má{³Ì”Jl? dM‹ó¦×înë|¤ÆBbÐÞHAúgUÒLs¥·)Æý™=;pÃh4_‹ ±«®/ ‚†Õºœµ¸as/’Ó\Úgæð_Þo{gŽ „â²Äå|}ËíÄ(ª[ Iz‹ÓÚ†óYòtgUöÎŽõ…³ú쑆èÆPâô» ­\ÝßMvNò›/ û«Ñéø$+4r‚Ù™7Éñ»£:¥ÅÕøt;½,ÉŸQøL‰œ®hSáÉïÈ ¥*¢fjˆ±Ü§8/„R£X ºqu£3hço‘xL¯¨{+i2vß7#:03õFðòs&^Jd‹6˵O8 \h]+icyÈâ)ˆSiÇ«Ò[Ëo«€¯òÁz¯n),RѼü:}—7$t4§³Šé“ÙTWõïäÓ±gŸÁÕŽú8¶¼;`ãÌ$ýÖ3Pv_ŒæñQêmBmcdB¢:¼¤F¨zyT§wD6ñJº ’ˆøÐ{uý¼§â ùí¹OôÞ.—™tSì¾"îž%}ãA+g$½¨áT;ªììMùrº÷b!ßAâSít$þ¤Ë ûÜÌ#nÝÉ›êîÁí¯¬¯ë©+håºÞ‹|3¯Üp»ÖãÈͼr/â¤<~¡F”›y×­©­oæÝr·PÝÌ+#?ß!€uGw{¿¢ºrqû v/:ó¯NŽ®2ݶ:»ßÆi<½®ñN#‡Ràˆß’ûm¼Æ·ãÖ’7柷3LQWùÿ]¯d.ó´HËŽ—‰Z‡7×Â|OT›;ÑFÿ÷Iebo—ëTæ•ùMT&kÐ*óÊd*óÙÑÁßáßÿTÓâendstream endobj 338 0 obj 4305 endobj 342 0 obj <> stream xœí[KoǾA~oÚ1¼ãé×tÏ!ìÈ2v"1p;š”DÁ)‰TýûÔ£«º{vf¹”å“ëeOO?ª¾ªþªª÷õñЛãÿËÿž½<úâq<~~s4??z}dèáqþçìåñW'ÐÁhé§a2Ç'ÏŽøMsíqt¾ìñÉË£7c6}g7‘þÝÆ4õS7:·ùk·µ›“në7Oº­sc? ió%ô…?ÇÍ_ðt±¦Éújzû|ÿ?ä×àñæ«ÎóxØþeg 1ùió¸K±Ìh7ÿƾMqÒ%ㄺ#¼ÏŒ7ßâ(_ã¼;Á$†"N; ÍË[žõ ØÝ÷8Žyÿ¬‡•8Ë+ù7Vžä}òÒabyƒø£ýÏÉß@ÜÆÖâöV•@â'ç åóO]àŽ>Õ·Þ˜Þúã­úh¦‰_x‹Å©Ýæïò ÷o`­ð'êcóÓ?ßâÇ~¼À[üø\{?Ã?ßàÇ5~¼ƒmàêAG¥ÏMi¼ÕÆÓÒøFoKã™6^t ¾ñÜö¦ž'¢:^$?>+/ªqœèM5áÍòz¥ãíÒ„/&|ÞŒãƒßü”GhÞ,íït©ñíÒÂ~êô;«tÙ¨7ôÉMéxkÝø…ôë:·„ˆÁ43lÚ6O§€Ÿs˜vuJÿT=Èу^nt¤%Q_l}‹-·‚ÂnþÛ9Ã&ñmt¤Ñ@bùã ˆLø=໥a<†eôsgGâ=. Ff9à|(¿½†§7T!y Ëšøé)/•W*ãÞõ'f"“K¨é‘ÆAPGþág쎣}ëfÞã #9 ]>¤î—ŠÛ ¦Õ(Q°IöwÛ‰b¯‹ +™KO² ƒe8ù>y…Ó²¯¸ÄV …çðoC EåÈïžgž‡çèäHVbfèe­Ê‹N-šÛfxáÀ^ÿ„_ÓÆ@‡H+°1¼BLsõ}!6‡©=2 ÄÎ+ü†b ±~α  _;Ë€!âk‚‰L•Ë‘øÿúFd\Ñ;:{?ƒW=™]CZ‹w©¿#ÿDI& ³Ò\x)`í‹ì4©‰)µ±Â¿Y`‚_ý.™àŒÁ-N÷fiïµñóÒØÀÝwJãÛ¥w>Œÿùƒøßø0õ£±h×Žàƒˆ`˜2·Y7 à”z>šï"‚žDQÚlžI™Ð¿¼æ»éŸ£ˆÌ)ýóÆY§.ãa‰þáž™úŠ.Vœ˜Ý¾.þÃhŸeW}/Þ—}Ýs?×û…sz™ýEbn±?:u¦a€tæúû1À4¿_c€DàƒMQ¤ÿX {ˆø–ü¼‰HÁœ"VRÞ—¨Â¯R><¿ÎùˆdMsΊ‚~%ç› ¦7Z‚dör¾¼¯öÿDù>Q¾ƒ(Ÿ:ŸO”ï0ÊWÈÁþäßï“òíéXMxª6LÏc„k˜3Úácdü¸•õ ê݇`[¾L¦Áˆ 1øq´ÉºÄCÅÝf g ë{;!<}cï|§ÊG°Ì¥ëmvqé{ã§0¡Áú€Jîbö#ØŠçn™Řཀ ,w­Ÿ_ÒTÁ:DÎø€}`fÑnÿ΃ì—H0l…SÛß|ö#øCÈ/mËhÉàQ=É*(®£â6¿t”°˜Ò¸J4̰“øsmʯIVâìÿC÷‰rTDGO¦<Æý3œƒ¥Ùöd8'&ÿk—mLf/”Çq†Üæc4<ê±#.ÖN¼]ZêÃë ñ.Ðïq‚@ç,y.ém*´ç¢â*yI¾QE$hÊiuÃIbìô¨ãBS¤:L_Õ|èãûÎI€ÐHòk3SŸÒü Òà›|¤/RP<ñ€Áâ×c•ò”ðí~¹‰š„Ór!Aô}! |Vy•êP?§·øœóªë&Øžò]u(•’UY"Wëí «4[FÀŒh2,¢Ûö.:̈f&É6‰"¾GPÚü ¿ ,ѤË8ÎAY˜Zþk¡¡èë¨çR8ÚH»XŠË°ì\5eº­Lµš–RØç\W5WÄËXŽ HdTµjqjUܘã–9Rìd…Žâ(HhvHnµè:x¢€:cRM Á ;Ê1¾M“p®åÁלŽG yϺ®£+ö4 Q=MÞ6¹p„‘ÆÝ•ª‹B«˜µQ*Ž’"¯ ¦®±ùˆ¯‚¥l…8¢w‰«DXsNkîŠwkr¥ÚnþÕáJƒÍvòDûZ.ène‡­Ëù¬“dC”þÆÈt ^ (Î9 Ìõ*:{¦¡À _ýéM0e J…g'¤¡ò;²gò#;1›˜1ÏЂæ<¦(øÕS´ ׯÄçáWÚŸ”!ð„ÉVŽíº µ¨ËiÆ–…ü‡b£¸†m6§Í8FA41^"ª_Ðų $>íøE–À»%Î:ÚQ“uüD>CŸº$t1”w€òìø %@Î¥}þÝñÙ¥zq8éW ÂêàFaU5*Êv]z–}0MY§(è ”z¨3hP²ö-×Í"+,]·¡7-˜ß½C ;Th”Ø“ý×±ÎÞÐC 9Й˜QAäØšÞÉ©–½VÆ ñ\öãæ9Ákþìup%/ºöC#FârËá1­«ÕYlç5¤³‡¢=¶Š@uCT1B%ÝÙëP'N<ë-RðÉ•ŒLeêè’%³Õ’—J¸»*ƒúª$¾=e^VVå—q•³C ®ÒÐ$¼š¥-ÐÁ¸ãïíÝÈ;Ax¨ÎI’1É×ø¢~EãûyÍÞ#SËÝŽMþÊ.po&»å¦¥Zëƒó´ñ‡§â¨h3-’„šé¹%@É ¢ÄŒ!9Íã(—Vv’ýWbù·„Ñ;Šfa7ƒ‚ñ†ÆY=x ŒXìGË \-%K®K㻕„†§Ëî#ßD*y ÕÇÜHä[ýX’®¤²©÷©Ät©—÷ä”Ew©)ž2øožâ9¨¦gJk<Ì%ŒË®µuJ{ÛhVƒŠ‘½»È½\¯ MiƾE¹disZMA@IT8WG}vœö%)‚¤V’vvOeYønø½«„—\†ÞX *š;>väc_‘âX·vˆ´~'r®CÔ'$SU„Ós¸{È(21Ƽ9‚ ð·äSøpG¼›5­y/ô¨ÈÃqì¼Lëí«·.(cÁXȯr&›ë¼MèšçÓ„½÷y J¦MâŸüb’LG]ä‰Ö ÁÚúö°¿À‡kWǬgüß™¹À!P>y¢ÔÌAelÑÓró€tF“$C!S§ ,QCÞÂØPJT[3–ó3û„ŠVq| kKjý\³ãÅ·é5e;ÎSŠ:½=Y°fÖãÁEƒËcÃ9 &s‚_á|ž0PÓ6éó™Ï’¬ Yº]ŠÚõµŒ+ÅdL^˜6qáKžÂÆ<Å(IÔDU¢X–÷-£> CA駘7eÉPP_\ÿ/ã)¹ `Zî•ôDòMz¢Î›É^wk{UäqgâÂ). ÚÍjüxê;NsÝ'qa½RÙ ëµ°Ð7¨_6«rã¾ÄÅý+z¯|´%¡«bøDB =ì‡ûIh²TbˆÏ+þm0Ú¸z{ªŽ±—›ÖW”>„z¯êÝÔsÜSCv½K;“¹“rji¿S† #dœÉ“•ä‰ÐÇ5÷ЋE:ϸ±½eÁ’‡º~yÏüøçeQº¥è¿Ê"ÈÌ-_ÁÊAïÞð°½³ËT+ÂÊ­~ B:ïfWaäô•ÄùoWˆ¶kʧTU9CParÖ¸–J¨cÏ%Ò;ª7³_,䇌-Oôb\œþ,fžƒÊ¢ÙG¦…[$½§XP›Ïærã²%jÚB³D7ž¯9ÿòퟩé;u|‡©­öúÀ¿h³î,õΊ[%§™Ó…‚d%AÊ1`Ï‹ÜUS­†CÄ–mñ¨¬‹VgnÌÑ5¬É+ ÐëcúLîÜ(%£ùÛ²àõ+fwU¤}Þ#¿àhA6É϶v/Æ6ùêâÜ%Ò9G ó}ÜgÍ)îCîÎF´øU|Pº´M+’‹î5õ[ßaÛŽÆÍJ0ÍŒ"ãö*—wTáÙq……]ÃCý}£jÇ?}_‘^PkÎÐÜ[­³2ŽŸýºmN¡÷yF´å‰h{ÿ5×P(¸*÷‘baäc– Jösèºö'ÇÇbtqÏoLWÝÀn u\é ä ·>q´u²’UÏ;Ýq0_„5ÝHëgfNƒ x:;¬_+õ’æuQWWgV,åEÔò)š7-5(p“;忦€&áo)ˆµlB*wå(¬R@Õu…ž¢O;Å_ á7þ‘Ë!±P5A@aص®OÛ°‡~üfʾ7ä¡hçÉî¶ d^,­£Üå¬~çrU¶1IÈsS¿íÇâ¿U\øõÉÑ?à¿ÿ¿Ï†endstream endobj 343 0 obj 3804 endobj 347 0 obj <> stream xœÅ\éoÇ‘ÿ®ùøÍo q2}ÎÌ.²€%[ˆ_±ÇÙõ+“’e„I´¢üõ©³»zŽGÊ‹$@½7Ógկή~=zw2à?ùÿüŽß|3žüøúÞpò㽿ÞsôòDþ;qòà 8Oúy˜ÝÉÙ³{ÜÓŒþd ±üÉÙ‹{ÿsÈ]: ]úß³ßCàšyî‡ :]@ÇÝi<ü®sý|ÜùÃ×Ý©?œáóO»S}ñMwüÐ.ÒØ=¼ñ~†—ÐEÛ|Ò… C<|Û9O§dÞ~ C?”Q=´= q:|†ŸñÍYyó N: >Á(>%$ê ß\ÌØ0« ‡ÇÝiÆæþðÇž ɻÃ.À¤yÆeS³ì_ÕÞµáY}XVB‹€Q 1ŽžIè£%á©Ðð4 ýèæ™I»À‚2ðENó¼„E^ã§§]<¼‚Éo`)#x˜Oàã<~ÀF—°¢'@ð—¼M¯ÿ¯§_ÆÃ9ô¾‚·Øê›¿Â`3‡Òàˆaß:yˆm_a÷y³«GVMÙ,ïûׂäʇŸ:\¸ÏÈWë-cÒje‘ø÷ô7à"õx]1TºðH0ǸÈ1c€‚e¤|† §nÆqÄÏÞnâ‡)¼ïcTËàÂ>Zø‘ ¡»Ä7?ô žÒúÔ@2m¦ãÉ:kÿç¥/öQF ÒO:8¤¤vì;BÕiqÙœÊB¤J$¢õðy%Gùž‡‘¸Jü¹ ÍDpä'.õ¤>€÷1²áiµ´Ðˆ Ì·ñ›Ü†K#úàraFfÅpÁ/,¦éˆë8ê2ÌK\KHDÓ PZ=±‹¶Wzi゜ó- ’>­ùÒl‰¦~(H¡)žW¨à7 .xHn€¹ŸðSÀÉ„±õSíwM›£'Ä%”YAc:"‹±Á+%h¤yâ#µ؈ª8‡LŠ£¨X…)²€Ðœò]&b63èª #³þ-vâA IYâi³  ï°ÍHŠâ.ª%L#i°"žO±¿£9¬j 3‹]7èm”ˆÑ0ªM±ûê@øüÛ"±<«‘©?ëØÇbß1ü…%¤ÎØ(–}6œÔõ07A³ÅÁ©¤É(· Tò¤Ã³ú% >&Ç@MBd¼ðZURä^óº‡"``lÿ_‰.÷±Øø^†û±K*Ç,ý†FŸì+ ~³¬LÃ7"[å £H‹15>Ü )/i¹Ú[5t¢5ˆÐêF_`G}V ¥šôžÜRƒá&\$ᬸÜ[^ññ–G†}¾?»­1ÀjìÅéHŽÐl£¸x• ^Ø÷+‹ÂÍ´:f[áû-}Ÿá[Ñ’‘ ÉpŒ¢SšVr&n†  ©ô*/‰š“cƒÛ#Èx‡®Å[\Wa,1ûB”ú e]MhæV•=œCî\=2œ«úS•†@!θÒ/è Tp¬g8aRÔ s²«¸Qÿ´‚¥Žo@@’)¥ÂV%ü0mU>WJÿºvíûW[8¨ó¢}N3kϵ!Ž9­÷²”ì³UCwT7çêáWDGdI·à aßy1~¯l·ºÅ—…˜Í•r;ˆ3´z¨¼X™ÝÿxÂ)vy϶—àt'ió$Z8¡H<ººpn†:*ýù3ej©Æ¢~>ÕI˜+f¦U ƒžÁg×JaWdH‡iðe鎮'm ÿȳ¦»/Fh\*ÚÂ㾑>Öu×>_É­ÿ!ÜŸÁ±N"º™X{ÆpB=Áçæ}Rñu¢Ì uKë|âàY^— ±¶Èêm´­Íw¶Íïêü_¡ÓÁ+}+c}öe“«ðâ ÆFŽÕ2!}¿Û*±R6C=,RlŸþYs[œ¦ÉZ1§-=,À¦®ßU“$ì* -á1iëo—ˆn4 ‘TŸw@¥3E6’ûo žUÍWE~ZqìâZÇ&KÍ04i ýôÙMÆýæð»l¼?õùÝŽJ™GhëÎðF´LnÂÈWøõsüº þÞàÔK  NÑñ?÷Kës6™ðçRÚ)tnJãaÔŽoêÃ7åá»úðÚX9ÔÁ H¿ÙûYGÜÀËàׯê명ï£Ù`‡ê¿=âw¾ÞóÉÖú¡×õ!)pzŠt/Jæó{g¡1‘÷ñ?Ʀå¹ñ-ËÃK³££4~Shü®¼¾®¯Ÿ“kaª‰,‡´á‚A$áŸÅ UÖ ‚ß)ÇZáHwJ›Z%jŽœ}¸Ð0„ÜHt‰†iå-Ä!I+1º oº`\þbÎÅÓ,¹Œuĉn ”ºà€çtê—šâÐôR˜; %”¸-÷Bξ3þ ÇùtáÿÈ=òd0Áù PS.ês:“ÞO9|â(í„§º®£Ai0QÐq{ÆÑ&aÁF æ&ö ÚÀ2K>ü¶´%‹ãç¡wyá[|«u]bOèCub”ÉŽÃfž3âÚ”ÜÁ€¡û[bCžW[…‚æIÈ@MàÒH(ÛBRq*fºÀP5é†:‘s¬‹4‡Ï;qÉö£mÞíXÄÀ¤dHCàøùBÃô!¶~šÚ ÖŽu<8?¿9ýæÍ,™k°Hx5²­B^îHYÅ]Þtë`dÇ ƒÒ€©<©< ni“¿À?ß}ö©š™½¨*ým}øó†M®†åÒöV{ñ²Ñî9ó뇋fÏwÒìèÙ!æD~JXˆ..IRbKÖ¿Çc¿à8ýCvAr@œ„¢æ¨~_Ûð^gÁqHzûY…Ÿ&’g•DÒiÓÛá§[lPÂ_Å ,ãWÖÿ¾ŸÚs>$õê,¢xÄ»¹%Ô¸í»å—üŒxœJ")4ödûø@z£+‰ùÞ©ØÞ€¸™M÷‰5p}ÜF~¼Dð‘óL›i£œÚ´‘¨|’Ì:'Hx#«EIR{j^c‘À< #›•ʳUÊ1¤L¡Ï£Â3A’ß>")ä‰VÙ-2c«ìV £—¼cšìV£xÛ¼VœÝO¬Á$!pW)\l%™Þ'¹…hmÊ•®à—$·B<šÜb˜Ü1¹5”ìÆûæ¶<ž¡º¤°öÓ¼òVýäþ¹-?ÑULa¼u^K'ÙÏkõ|ÐVr1r”ô¸š¦±Ú b …èp×D-»ƒq=6Oi[SZ²^ü’¦…™†:¾œ*m€)âU 4Xš¤jrõÙ…²6¼wÞ¿xµi‰©•hgWtΥ꤫ª‹nyå¬Ñbªð€ÙÉq)AÍs\Yßõ)Oƒjj“;“êÃV5q.ü¿?·Ç„ÎÚYÜæy§~ ‡Ì^´ø;ùeL5iãLYÛ<²y5˘¸ÇD©ÃùÏ%VR‹+#½­Vú6ÅqÕRdÁ*qK#ZѲ¥7/8Ðà“5¬¨-S 7} ÝíQ¥à6ÚšM\øu·<ÞIÂâF5‰¼Ñ:T¼ÄÅaOpÕÐ0à-ãÚÝL̾ «ç*Šª2'{5þ‹€+à!Ÿó%AàYÔkºdŠe—w°,Û°ÛT ú…Bµ}>àղѴ•êÙn]è“Í+Ñ"aWn0´¥Ä.*õs5˜aÇyFQ[¯øÑÆzï[`ÚbÜ ¶>éNÿ• PŠ‚Àúÿ›s\ã"!òùXI]JÒ†àJäÓmáeZÒ:üáHÝ9®áy0å¶d‰€˜î„ɬàƒUjrPá'ŠÈ(+u¿®ëh3:i>¤½ù¥b·•RÞ³8Žï?KÄœ‘i­>òÎD³ZÎht~Ü(áIªéýó½Ï¥ÀàFŒG¯ùð¬`Ìþ}Ÿ–ЊCéÙŽ®]wër4 õâ=gñþ¬«Ê Žõ"”V] w¬?ÿaçËy"ÌpÕl &hZ¨u£¤‰ˆã®ëKôÝ,¹{™ÃOhÑú±–$j³ÐyPÆ¡ ¼=âÑŒÎÊ+vã¦yŒ;ÕDjƒË†Í HU“6ñ»æ\¼ŒTJ¡Î¹î¼Ûç5%£Nm“¥-úŒ§.çE¦yÿM ¶•Ôå^ÔO©ëZüŠ'5GÕª"ºë¶6¶åìª6B°žEÛI|Db$9u‚®‰kÂõ&ï„e'Èþ/;¿À{[ É;ÜÉô¨ëF5*«ŽUMé]G«¦ªé#ì'ê¢&K¸’Kfß,töÍÔ«’+®}$ÿ– 7Nëøèç½Oœ)“ýuÙ×Ã…ÃõSq¸Z׫8Cì±×u³uŽ|ÓĶEV6ZÞ¯2„^g·›cÓuvÛÌh4õój«a]ÅùFÃK»ð–~çUWÓh›¥6|j:›sZðÒl†E{ì§"ÛèÂb¼2OÖm}X͈´N¬©.´^¬6þÏò˜ÁØÈ&ð{С 1€#‚Ém›Ù?z7P"µïpyÇF×ý˜´‚Cÿ„®‘ÄÞE°)@ P òP4âc8×8Ný˜Fy˜>™SÎa‚×c<ü©›&.=}ô¸2V´A;Í,ŽŽãÓ‡¤šÂH•Üe•—Ô-ù€ìÆihÐ4.&V8ߌÕ6Ð쿟deažu&9P yì#Dgfvª2¾éeVÍ»äH 3Q²Ôõ!8¶‚Ð`uG­¨É:©åf-š]pzQbóBcý—v”Àç$Åã*m©d õ£øõ>²Æ'Í‘Zd.¶½¨šº(MhÏÙ+9Ú˹9Û+óK úŠ¢\×¾bœ‹Ù½)4Æ~™áFÒ,n(íæ°(òyƒqöÌ–t¦\µ9Õ‰^RgG/øÄ—G¶±­0Ãø%ál400šWò-•‚÷ÓæF¿`í œ/Ìp=r‰Q5e-qÕ—è.³F?ur(Ž'Õ.DY·ÀÖa[n·j‘ñU\‡ÍÜÕê°e4r â¸bÕw­-³aáJŠÇ'O(hbLnÿ%TŠ-¡Øob äü7Øk:â8+Pxãmæ ¿þ¾†÷9¼´oñ,€ˆ€äÉ0DD_ï–paß”MEÝTð{!>QºID°ú~Ø‹y¤õ/L± ÁZÝúš"'±¨½’k %×ÊéB¬#X:™’$¶õ½z[ß ýÜE(¹4ržª”8ýÊÊC „–½¿ÐdyRTú/ò(ã° Ãç£ä š|ç¸W1Tsâ$"±k\Rok¬îÉÐý¤Ù;¥šªªÉEáIeú*,]âÅ0ûçÛ°ôcñÜÇâ µ®Ø®7m¹þ“±&(YåpÅßëH¹%£D- %5ØR"ÌRvm¯$JÙµ)cÅæ˜¦Û-‡ÕZl¯UØ£+UØÚ°¸’Ž^%Úx.lwæ –ÄÍ:O„(–—Ék«ÍBƒ5)ÉМõеÉò‹Ì©×|hÏ­%hT1—\[ßÕjê².T*6 YBÎk¦ƒxƒò©%þtf’§~r¨FÍ-žP<ÒԷǽ"UǬ³$&EqNgŒ 3¸Jļ!&7b\}Î <׊@ÌŽŒ1šG‚&í#j™:QÉÉšÆæû[SLÒ -[`«uðT aKä0t·š ³#§RÜ×t±Q}:°ê>ØQ{¢c ÷¤uÒŽŸF›~¸¹ãEn­ßÛ&Xà»75=Ö0”Ú'±ˆK‡O ˆ%å–}ܸºJ¨ÕC<õM!“n/W–z±bÁÖeãbq€ í'ŠÇKIÉe>×]œYÈ¡@ª÷, Ðv•b UÛH ÆJ8ÄϤZgSŒJ™†’}ÊJÇmà™ã¦‚\œ6pÁ˜UïÊmÙF³˜¦j!­n,õWnhãg¿_’×TÁÌ¡h·cµ)5i(u‚qƒëšðŸ9›¦I×!‡5Š˜gúúÑæ‘ÖG— ÒPSC%&^!¢µLâü›È£À™‹pK5£9>!pQÝ ³µ¸ÍA Ñ •ÐÑÜÐŽe3&\žÕ)ÞŠR}ˆÛf³¹]Ш)® º“ù\Ù^ÄÆmî—Òe¾*éØu©RŸJØ!þ ‰þü@[Î$IާÂh‚3ß]*©]’Ñ“_ùÊ*’ÆckŒ•”Û4y–_Wºê­|IWPÀhÇ ˆ¼ˆÚ•úbÞÂ5§žtg`Êío¬*^YˆYÕÑ¡â`B}-üŸfy”¼®oSõTsèMÃëƒïˆ/wB’©Ð?“2a—eÛslSOcnGËî7ÔœB‰l¦&èïpmuS©é©ï”«Y6ø3ãT—Z êú$m`}gÛá „!j¹ÖZ.+pÞåÖÚi”1Ê€Õù’ Šv]{õ¦ÂÕ·KsïÛ_ÐQd雓·ÆÍxÆÑ³üšD£ˆœTו›<¹ÔU¯VÌ·9“lîz€GtüÆÈÈΩ¸H+ÕßÔØò¶.s8ƒ(uOUžëTleæ>ïÍŒžåu“À\UZ47ÞÕ›á QíVùÑŽ#m걄­Ð}Ÿºµ^F3±/%£g°ÉßÌý£¦âSì Qh§.³ù] ¼²äà ‰z×kÁè`YÌgaܽ¡–ø·ü">ÓŸópüÓ ïõú[SÉ£FÏ‹ú³Å *ÒO?Ó©Ï&ä£Üo°¹t®zËÆ€lý¦Ó0[ý³vH6êÆ•$°˜Ç KÍ®µN P…M ]²`!Òûs……*ñ› dnÆEL×–¼à†?=»÷ø÷"mžfendstream endobj 348 0 obj 5207 endobj 352 0 obj <> stream xœí\[s\·‘~×úGðMs\šÉÁåÜv+©òErœhåĦ½•µóÀ¥ EÊ¢®û냾¢ƒRJRµ*Å™sFãë¯üõ¨ß¹£þñïÓçw~óýtt~}§?:¿óë‡7ø×éó£/ÓÁ¥+»¥_ÜÑñ“;ô¦;šüÑâ®÷GÇÏïü¼»a³ëüfÂßÛi^vËôëá¡ÔIHMôt»ôÅËÛ0ôÔëoÒ较 •‰ð£m7¤ã™û|4÷ªÍú%î|•ƒD,n; ìâ5´ò¼ó Ùíß@2 Çjd/AÑi*ú¡œ¿yÓ”>˜§OõÓ«N4pÅš“˜czmøÄ")ÒKÞ›vtú)5ß·Î`à ´ÓÆÑžxØ[vÃËFÿ¬­‚1ÀMð6ö—Á/›t 4íeÁ“d{…ÊÄA¤4ç¹z=}uh×°X^ç'ÑDñ"ôÿk·kœŸ©]¶:XÄXÍ6Ì á…Ä¿‚åBà®á6Y8Èó&gO5¸,±^>ƒ+¿tÜüL&‹«áŒGâø»µ¨!éT,je‡a¡°m…d[Ib[4„ÁX¬l²ZªIÈÔ?­'nŠ×0KëLNÎ\äõ½iç"9û}ú€.ŽÛy Íž­ U€Ö5,3iB'L¦‡®•0“kÏê`od‹Ë«Ÿ¦yÊ.>“#{aó]¿i‡FΤ‘3œ!ë)ÔDÏ»åOø¶—‘Ù•"«Öú¹Kz,íÔí š7t7iGDÛ}*6yÚá®è–t ”úqÔÌÎä±ÿ`Ç™íˆüy.Ÿ?ÂúáID3 8wŽšõ<—ºƒa§µ;ú,ß¾lÜõŽ´c¿ÐÛ ç;³ÂK[ƒ@«â—>«˜éH&ôT´*+5ovø%YqpµÑFý4´Ð µò™Ú š$Ì:(&y cɩϥ°â³cƒÍ³»²WpðÉŽÀ©Òt’P´oä:"§Ÿ` OŠ3ú$³7BûÆÒ^Þà=¼âpCQ§’½–ÑÂ×9 ‘âJ‡Å$ö6ëF ·ãÈöÂ3À{:®­d¦ïix`=…rc7dúÙ¥G@ùá_â®Â8`w¬t‘÷mv\O³±š%b^ jxs¬Ü*,(ó3½Ä¦‡1ör§@ ÑŠ¨8[1kaqvÕÅ(%Î µðUiÙŸ¡ýÄ8Âôr Pu†Í%?,ûʰe½æ­[Úf'0 hÍÉÍ»~³9‘ÈsÙ¤:)¸›&ŠÑ(IŒW‚¡Á xñ‹ø.+*iãEaw ìZÎ ][V¶§æñ{É‘Ìó‚&þEg]#™ qí¯ÎÔjgÁoDâ‰t’ÉyÃòAMòn‘,«]AÕ2+òøŠç£Ø«2ض2t¸¥óŠ#ùºgbË"°Ò&H\4bÆ^q°ÿ²¼.¡«°S/Tx0þ+lUGÅ J#ø-Y'|ìÓ{iü©Z[­=3;Dü0ê¼ÙÁ*) 8Å0Ó sómr7É€6‡§»ŒæÕ‚ªª¸€ÍŽ!èáÃ]’Ý}›.),ˆ}<ëdi¥ëÂð4Ò^––­dAOhE¹zÔÑŠy^¸‰“(&°ð8žÓÎlc0ŸÕ6˜'伂t5VkºÁÇlmýÎÏd%°Tði»/ì‚—/Ÿï €]\ï‹®Í&%hmt‡XE“ìF F£ˆk®_;+xa9ؾpä¥óZ9†µOèg´ŒCæè ðKtÊeÁˆøxýRç¿¡i n†6ŒŽ.`ó7ónAâ¸pÏD7£iE¶‰Ôòó£æÝ˜”qü$/‰Îˆý¢ËCÅÆöàÀÂ\È›74+5cxÙúãÈ_^Ûá9-!¸Û÷ñ£P L&ñI{<̨w¨) s‚Çrã‚h& ò2 cjå9ÓÝ–35Aw×<ø |ƒ 3¶c±Ôñ>Ü£l~ _¹àFp”£(ãwªÐ-»àûptüðÎñç?3¤ð´/Á<´[µbK–ø’jœ(æUuÀ쪡*êšZ‡WÄJ†¼¹«BîvùQõņ¢§”A’µ+v³‘ÓR5~h²Þƒ’eò’F•Ä3+øDYUN½=Å ‰ÜyRAö!HŸtÅšÁÁ2Œƒ %Z˜uVo4D‡#’‰ÿÇMØh“á3Á‚4‘"‚zà e MtzVbPq‰žaEÚ›%òhé½é‚×eǪÑeÇh.à«c¹ÿžå%\,/?°zi1µhÕÂ)› ”Í&  7’*¯ºQ&R¸þ”ÁîòmKÍ`ãÞji»ÔlŸ±e5èâ®Íi<ŒôHTÛáè½M›úŠ5¥=“Läl ¬0ØõUn{ä"Q” §zO¢“l¤¯”.³+gÈÛ«: 3nïÂF ÔtfÒËÀ§´Ñì&NmÈS¬3„œ’ƒõpó’“ÙãcDüq<ºÑ‡ìÅxéò$唤4R²[@[âÆ”Ú^ÍBcm‡Ä©ù¹Øý¬ð^AŒúfÄÊ[»Ÿ4}E~¹7&­°§ƒæytù¹tyÌu„Œ­VY3 Rk ‘e*ùX”nv%­ã!±Ú7‚gÑü×’–ýA#òQ7Õ?e¾¤þ.Ëwõ·°`q WŽÈ´C,ØÂxdŒÆ ¨}jÙßiÜ\™F•¶ fÑšÊ}³–6 ¸êuâU{¡²<ÖI=àµ7#!šga,¼Ša“r=£+®‡[ŸoDŠ;Œ P/J„óûŠÅP £¬É²ÿÊy²·âš3?Ñû:(?¼]K7çB`ã€g&ï*¡#q*þ„,œÌ­É?C>+È¿ÊSB¿n¬m©°Á€Qÿþ ‹H~F(? SsÚ€¦CÍø†ÚÞЃ}Drƒ­D‰G#Í.Ux6س++Ó¿ÒâÊ“¤K×AÀeÊñZIÓdÏÏÞCÞC%Àl_n³Óeú0#F“SòèÀ’2åjŒ×d¢'³ .È0TÃ|O]ÀL×äk‘ {TæÂ¿›)þÏŽËHÂ2e$[?DýÉ9Eê m`JÌ)FQn€ô•à ¾Øã©¯sùŠ` ãSñfŸ~··M¼sªmžh›X[A ѳ[õk()èò÷vù{}ë]Ùå™Þ@žñ{ôr(˜‡ñŽúƼζªúm^r‹/å¢Èú ”õ,Ëú@yWý,«ç KGՌ畾|YH4ôD_йë½Ããây%lNóz¯à÷Uæ"™¶ÌJÎ3ú¬¥ä¼ /,½½Õͯ¡ùge”§V‚m•ý‘£&GH£þúÿǨa¨ßìê7刲e¾´Ã ›ÿ"{{ Ÿ¯õk¼Šîý¾ù¶à·¡ûž£l¹ø„/R¼VÃykpÅëë‹§-%_ÚÛyO!É„!ÚeKµ¯ .‹2g­ûYäWùâ=~ Qkî‹þEy÷óÕR{ð(ß³Â1ÖU„[ŸnB‘ ñÿo ¼S2øs¼ã)A ‰qÈÃ5³ lì,x¢ÊMDLå bAÊŒ2!o°žhùšÄÿPA>‡+!(à¯Æl`XUV¬˜½ZN Å§6³$Tq¾fO)v•;«ê±•¤»%Ù+Ǫ2§½vú•D^?Új2ªÉDðUJc¤lIÚîW÷ƒšNÑŸÐÔ8ë ž®ºÿUnï!‡@ÕÛ¨T:)M­QZÈþ)즺äF÷rË2½ÍLí.'0n¨Ëñ¤Íµ!IºMJWB,¹ãVΣ(e¶‰èŒë½2†Xú¨zƒù©sŽŠ–󉈇y;˳_OµÜ¼wÓÆÓ"v¶ e ¹HáVìpê–*jo™w)mš·LdNDªÙjOæà¨¬ì #È–EmÔ4Cûÿ‡%#ºÆÖž~µ ]g K)Ÿ¦›Ræé”‚ã®d¦Ø*1OcÈÀæÖb}xšŸžÝÊöDÚžÐ1ü^{·÷=½U”(®Ë"°œƒÛ“Tö´ós \5Ø#ϸ²MÈÒQݬ7cûHÓÃÌ—ÙÖ ÏBäO”x©Jî áÉݶò e?G«¯:­É¡¡Ícvþ넟Iç) òã²£IìÍOý殲H¹ôÖ¬atšwáQõ‡ò6À§`ñß> óÀ¸ï¯Ð­Óô;¤ß‹\½¶Ò*kT^¶NÂBCE§³I¥¯O ¼`BÍ–~0¶ “kfó¤’hß ©Àg¬4þ±Ö$%@fšµO-ÙZã½|¬ÆÑ¢ü<ý„}iОã,bP1æ©4æºX4 %oB 1kó…Òq.KšFg3† wi²P: ù¨½Ú¶aU%ÕÓykÝEAVå87P“géPUM„Œµ‘¬1dŒí#kA³Ö!œ\Úçø_Ê ÆU:ãsAqC”HjÃÑ:j…”º_ì-À©ÖÜq ºŽw5niÙ½ ~夥©ìAç”ܫϠBRߘ՟ËMÊNPYßjCcF[ÁωH#bì[áBxg› =…¦—auYŸS¤«÷ðìÉÑ#(€·;PÒ»Çðà_ØVY%áëÏð]úú%ü‡üà¿?êÃÈ:~- lþ;ÿ_õ™ÍõêëÃìXIJ)ý…KÇM†Œ4ìÔe‡fÖÓøóV;O°)ºÌ‚[jì­^¼§f`k8ô íðñá/µ&­fß^?XP£Òᵑ‘‚n¿Ó˜ûM¦ÞN´Á‹B÷¦kyôZ½GÅò`Š¿q¶äŸ™“ÜÀ«fæ5¨¢å‡9ÇB—»ã-¬qŸ!¢ f˜¨†ÀE†‡¶Al£W_wEØ*€ªÁxßSk)~Ùë òIx*øæ3ðÊ{®¨Œ ñ´sA.çY\Fǹ2$È<›´:]Æ*YBE¥ 9¬~• ù§ýS«tòÛ$Ñ FèüÜPW zšI^uL0ŠKÝüÛ*’ã¨ê˜…Ø@íÃZèi¾x-äâÝÀgìð,^”ãÉ«VK´‡D¯º5{Á¾ƒñ$ßæÅ_.Ø¥oK4ÄENìQ‘eyÆb}ê]ø®þ–w•Fªä~nü‘¦i½=[ôH7ØÚ£®>¼³-èÕmñ¤Ab¹$`_Ž ? áÆÃ9ˆ+scÛÈäÜ ¦<µÑôÍÿ„a1«ò)?ð)?ð)?ð)?ðï™P+ú”ø”¸!?pÿøÎŸÓ¿‰gæ-endstream endobj 353 0 obj 5092 endobj 357 0 obj <> stream xœí\ë“EÿNøGì7§ ¶¯ëÑÝÕw¡røÀãÔÃÅÓP?¬ì·» °pø×_efeVVwõÌ,bh\ÃLuu=²~ùÎâ—ƒ®5üIÿ>¸¸ñ—{ãÁ£ç7ºƒG7~¹aðáAúçÁÅÁ­£ØÁØØÒNÝdŽÞ 7ÍÁhFçÛÎ]Üøa34ýÆ6ýOG_Ä7œ)Þ¦¶ ñ¥£“ØñïÍ¡ß|Þ˜vš‚Ÿ67vóush7GÐþIsÈî5‡Îvmg<ŽÝÆ'ÖNña|…ûÜnÜ¿:¿ù¶1&¶†^=ý2ý÷4ª}›;ðžÉ“{0i×ÙaóiÅů.Žâz|9þ2~€ŽÎÙ¸·ù¦9 »ÝÜobK×[³¹Õ¸8é0Á²±Û`7_å·sÇ£Ü(+ÁEÄQû8Ä8Z"¡š„q﮵þàÐuíh¦‰Hùi\Œè€‚– ‹7&ŽþßÀÇ-ø¸_ÀÇ?àãé „Ùü?nàó*.(†Í¥tzœ_HãÍÜø@ŸäÆsi¼lÀŒ0zj»Èo6#œ]¤ûCyü,?~"¯pœÑãÜ©íaîx*çÒñtû„y‹§µ…ŸÊ8µŽùíÒñy>/eÂcµF8j;ÙV˜#ÑÞ» f~®×­§æ®WÒõ¼ØC9ùÔÃÜê±úÖñQ„žÎ zªùëqžJµ*œ¨×~l¤3ìî¶wÙª@Vü¸½›>d éô›Á̸ÕXV$àS½¨£ÖqGŽèi %Õ|ïwÃ_#!5Â,ÜzGZ×§™`%FMµ|i¼XÁœ¯ë\5A‚ïi~õ¡N3¨.«¨«Ãþe~í¸:ÛUuŠê`Ð~lCBh?ÚÈe„)¢Èò~§6? }¢`†¯™ùKþY6fA8ãj%-E¾Ö“i‡Ð™ƒC;¶NØÉ5ŽzÏuÔ'Ð' *Ù8)ÒØw~ó3|õüŽ».Äíõíãšû¸ÅôÆiãa•ÞvøÂecè¯:€§· ÔFبjÔè—ðF‹ˆî7¯aî@ÓÇÎÆÎÄžÀ%½6=n7ÊŒ€ó‹-̃$Dáv €0¢ý@¢›ió=QÈ K c¡†û¼äɉXjfÆ rxøqÜ8D½cs£óÓ1€@ü T‚¦Gñ/L Ô#@ºàv Ì=²“à…#E¾Î‚E¨)¾#œD›&ˆBSú©TJg¼ §Ïÿç¬-Êîæq ÁŽÑ”5ÙI’MO‡|Cr,& ¨&Ó&­¾”& µ4Nh¶iŽÂ0ÊZ¸U+ ‰7ZSì~M†(¶ÍK ãÒÞÎâ%ò~ÕŽAá (ú^`+¢f›¨@Áß+k™!ˆQ]OadPÂþœ)NâÎdý¸Î´Nœ´Ü}ŒVât¶ É{Öšu@ ঩M,ûï'<%_d >r¦åµB|Ò°ÐÁ®:h‚˜+ça‰c±ñ Ôp(¯à‡+-øÛõ…Zsû ib4ÿ¥Ó¦y#ëûôòäVÔËà ø£.ç¶4îrntBeÏœš=qdâáË/ge»Ë)hàòš)#­0MÁ9KÖ V1„#æó„×é0£×njN”¶÷h7Ÿ–ORß}È+ 4¥m”pZ2,-wLî¶Ò¹éÌaâl>gSh®f½Å!”’L»¶h+ñ,ªAjÚB"`W#}²û®ÑAgŠÅBpÎájTˆëmŠÃ1—µ(J¥ZƆŸ59¨'¯š¶ãH_Œýœ;>–H_5bx©Þá@ßã¦õÉKËêgê¤ãk™ð&Fj1Èd»ß9Àíßàâá•&¿W€é›l_F)0°§³§0R¡+5yÄiâsõ¦D½8‰ ó×]Yâ|ÖfÉ"»hŸ4K»6+“ý5ÐÛ© ã4"ŬÛ÷÷ÿä¸/¸ Õkœ0Áhöù˜ävÒ$·!Vc$JÇ~äK‘Ó0³ ñ~O›;È,,úÝ@þèzÖ ¾ôX|MÉ]Ì5sJjÅêÕ.̓:ÃÕߎ£ß' ¹¦ ⎶h£é¯R§g•Ø“Š)À¢2-•5°feƒaÀXæÐSz’ßUbŸË]6ªŽŽžï‡yXcGD4™clX8!»…ÙµMà^CR.½`¯i!p3T«($cÛL…AÉg ¡'ˆNÅÕçƒÏáÛº‹lœ8ekëBk†U EÅ|k½ÑQb¡ì"¦åú¹)‡jÂϽ\vî,N=wðR¾á:¸Y¢ø„βë¦í.¶ë9¢e´ßÒ|\…Õ¡ 1ñaƒAòØÖ¼bðÀ_cJñ¿s CÀtmIBÎeP /ÂÇ8î×9Î @Ü K§M-áËâ%I7ˆ òêGˆÈËêkÖgüVô@s£ÀóQCa’—*® ‹ í‰ÂqIjDâ©%8(â%ÏÀ˜;£Žañd'×rl’èe”µ Ï@áâ–º„0mþ#å*i9Ù׉>©E—py³Ú ÃGL~sÅâÇ5AyRÔ«¦­ï ?’j¦[†MºÕ–â,¨!€ã~ª[“€^œrŸõ,ÊÎ’E r¤Â t¨Pu½Ð÷ò L¸Î#’žºó˜ô³zE𴯱¼¡¢d¨$:’…kݹ2ùÀé’2Ç(—±[28bñö0ºÈŠ̖ɬzÁå»CÕ˜äBú¥¢¿:qU•Ävà­ä%•<› ¤¥ZI |Àè†b_*-B ú+gY+Ážu‹TAÁæ³bH‰L¬3p,Ô%0ý6˜þø,-„~œÒTen+?vÑÐJJiÉM&[h½È2¡©}›*‹É½ÎT÷ÄWY°‘”%í´„ ÑP‚’(´I ¡Ó‡E<_'i ¹L|n'úTß’è yw{œ%èÐŽg¬å@cÙIÏÎg ~žˆµ^D7ªƒe‚ èQ¬„‘,½@i:/¡o\ö#^öÒÅ€øgOÔ (\s0Øjù%a…e©Ì …Kf]#"íG©.ÑýÆœØ}U¸Ëä©YpÇeâ“BÀKÕZ¬ªÏa;Óy)2íri^ððj!‚7ÕIq¨Tͦdñ(ïUÏÕ(ÿLWýšêcRò±ðW}e”䘚2—¤8±¯pG~SNš{2ÚËiÙ$K;³±ïaÒ{£2¥°Zœ|úT°nñìï%'XGß‹ãU:5Yé5@sš±õ4_…ñmJZ±B`ƒ„M/îz¬+PÐ(¡Z8ÉäÔ“"¸&\u‘tü²Œ¥Ô/`mì–'^ .lr i¼'ÚêÙåLÂbv¼Ðoè%JÌ;Pz–ݰè4½ŸÎ®W1£»yÕȪàŽDÇÝý¤‰`!“:M[Ì<ŒžŠ”2TÅšå­ Is'J`%„+„ÆUFŒ¤qU-Ž’‚–œ)¬lˆJ€‰DÅrz»Ð gð2AR³ÌÉ)ÜJ"OžßNý þuñ¯f²ikéÄ2à4Xªmýwã‹ÝdåZ òÄœÏí˜Ë=k.zšv°$Ü&‹yã8$uËu·Ò¡}ogQFP$N u QÿiÒžA.°ÐÎ<ïµ4P²[­ãÙÞ×½c‚»BaX-Š´°“TX¨ÿª†Ý \§Cm‘,p)È£ôÎÙº\<—ôÇ~–‹k²rô öõ8ñÄ÷¼hL\Sl[@ôœ„S¯Vè©E$ƒŠª€B©¹ôí*ŸJ¦–KÉU7 ÇgVîç))¿Vë™È¥eŽÂèJFýæë9;öY³ÌŽmOŒ•7rb¬¸·T½ñ&w+Jvl%«µõþ‡¾[¤nè,³l•Žúj‘ºQÏ ¿”Î奈ÔXÞ‰XæÃnêÆjb-kM¾õ‘õ­º´T¹ÄõœéÒœ]E·ÍuoÁ»›6t'Hñ'¹ ¤±Ç¼ô¶$TÿHè ¶Ý`;¯]K{¹€UÙqíQ(}TÈvC»ؼ5à×Nõµ::³,Ñó¦YèÃh¹M¶s×ç5æ@¾ ÎswåîJ}ìªF-„C2²Ï5"?;jâ: Åu6îrOº5'Á¸½¥{ßIÞ:_Г«Wçð–dX­”ØqáífŠPôÌ*—Õ7Î3Wl½8—¸œûîº8G,×uæ%‹ûÝu#3‘}¤.¼ýÿ0ࢠîZ—ÆËpÝ2ö,ñÓÐÎk?}ªã¨&QãÐ#·d§>"Û}É RRâÇÄ4Ÿ:•ýZ+*ñXŸ+øÃ´ínß ^"Æì.Ý´ziƒŠ?‚ŠßÁGáÔ™ËäG.1©úDýøQײ.·ðoKþ¿r¥. Eö-7)k;ÆvHIøì}!“äÉÏc&Pø"EÁì=©w¤Ö¤#'ª(ÿÀxÏÖlkŠè²‹aÍJýî¶Óã°ß®J’=*6®WIBAž!J-u¡N•xªþX•`x$’÷[Ì$ÔrjÕ( íT»R¿5šQJñy&sš)ªÏñ‘¤{¦“]¤‰Þà^‰žè¶T)™æõtµ›®ÌÄÖ3é" 779›ƒñ“²‚ÓUÑu¥èë=ÉBÙN¼õ\¥„Áþ6†Uù SI‹O‰î\RЮÅûªX ýQ’L®J~ öPIõ¹$Cž _礂9Ìò)’¢ä†N«Ú ó¾"_I-àÄJ ˜ü êò–僽VÍ—úUòi oTþ‹§o¨@%—$颾ø2„¢(º’µKÇ›ÿ/™ÏäxÑÄ'픯hlQ)_3 ˆGÝE`•fÑ•[ài¥|)RmN-±&{Ò,’`ÉN•Ü"ñg(o}½Ä¤98EYIlóØi«Wn¹t£ö©BÁÿÊTbñ?KvaÐk•A“¯†;ŸI.ÃJleq ÖÍi¾¥øÑÉ>Ÿ*ÐàÕBzO… ÉÉÎþÍÙ J¶<)×´I’éWyYH-¦‡èÿšÙ]+›HQŠ1ÓÌïç EšPÑ»ž%Ä<©Ù,³„[„*ÐäÆÚauåÍ6‹Ç¨[N)\Jé¿»7Ž>x—|—|ë À,¼ß%ß%ß%ß%÷à'G7þÿüžÏŽendstream endobj 358 0 obj 4705 endobj 362 0 obj <> stream xœí\[Å~·øûæ3 ;L_æ¦(H\-“€³ aï®K{1¶ð¿O×µ«gzÎîb’‡!ìsæôtWWU×å«jÿ|еÿøïã‹{ï=Î^ÝëÎîý|Ïáü×ñÅÁ‡Gi@péI;w³;8zvÞt£?Cl;ptqï»ÝÐô»¶ñ»ÿ>§¹§a÷iv›C¿;jãîËæ0„¡íºi÷A›¾»à‡4$Í5ÏÁáGßáË0æ‹ôÿÇôZúy÷ai>xþAãÒÃ)λÇÍ4¶üî[;ãGÍÒ<½˜ÞO¿¹8ìþ ³|ëz” iŠn„eç®xù0ô­ú^ÚÝ#Xfi_ÙÉ%Á%`cùÇ#Þ'‘ž–Ò$}ú8Žþ‡£Ï»·ìŽ}¢jJ?:a.‡¦§q²£s­‡¡kG7Ïô§‰XX:ìÀ‰Ùöïè‡ïà p˜{ˆÒ »Ïàè``J'Ø}žvÄ'ý c¾ßå§×úô2?|®_ç‡ïêÃãfJz7î®ôÙyxÙŒ Ž.˜É/jó<ÃyÆèv/õÙUø«>|W>Óg§yà¹.xºÁKç´F¸}{=Ððçµ.øÊТöóØNQtà}}~;ô]×öþàÐ…¶à4˜_t†'vGòðºFÞ«:7+[z¢ÏòÖ´{ªLdøðÆ.¾¦è•å˜YRu+qqvc4zb^ù¾‘§È¼ÄØdlq¯Ÿ§[šÊQɧ„ÿ ç ÿxûó¡í‘CsYî…ªTš'=ÁÃæaчSÉ©¾›Ò·h´àeŠ_ z{¦|ûµNkztjwg—͆?Æ0¥± äàz°‹|zÊ“Y™ê4¿_NýXž“8‚ñv«SéçÝüç±ü=Çò½ÇI^Öµ¹Z7ú©AN騄šÃLÒžá,ï ðˆD9ØZGÅE àkRé~÷4yrX?={žÜóëô>×°ýnހLJ‡0â N„û€m 2‹÷ðLü;¬~Œð¾a+C‡[°½€_]ú5,‰þBcŠC™É‚y EŽðÖ`i1KÓ6Α-x^u«¼qò<]«GX€g»Çy 6&æÜIfáØfÉI|ïu“U®7¯ž§WOiúôrÒá€@Irøv¬Ÿò$W´DÀPÒ™!W¸S­pQ ~˜âW:¼ãÜ:ï‡÷+ÚÏ€Ìf]¿Ïðø–~ #À"”ß’ðG N\úQ8˜ q-¨ÓO4Gzæ0ü] $àš‘3ĪÍDœêÿO3{œî) ¡h&œÜR!á8ÌøÂןÂk«SÀW•öª •ž- þ¥é!fd>ft}šPYî“îÆVÏëeãAû`„uΤùg?ëü÷Óÿ`„“ Ã|ù£x¤L¢ xXA#¼âï¸ÞßÓZ¤ô+ºû¥…CËײ±šÚAS¥#f·¨¬17Ûz òœçÞyá"’Üf£ËaÛ(3nFÅ/Œjµá„NcÏú0DÐ?,mßOkΓ¢ý”VˆüKµ“]T…€T‡[Éf?9Ü’zÊ*v£!_5žÆÎŸáQ.êÅ`ïeHÓ¦…è y0M‰j#6«# Å“ó“U±I)XÌ!s(²¯=/_ùkf²kzø”@½• Ý%,[Ó[ÔŸtÎT}6i²œÐãXqHBN” 6>r`ª+úD$…šø­ùÊ^ …èñ¬¬…åŒB‰ˆù= WÌ¡áç'ðpHÛmË1–èù4¢FY/åG—­òbä‰oÎÒËÆÞñ¡NËÜ®x¨€†±ßð#`·ö@¨Ü7Ét³ü޲¢| stÈÂ?8ŠòÓ"¢\9m2QÎdòm",L5KD‚­Q¼è£¬b°‡!Gù¬cö„HмÌkzBA×>榮”ÕP,ÀRg™Aƒë…[][/¹\Ó,VŽªx4ôe¾GÓ3±8â‘Ýâ°½†1‘`H±½¡GË æï1¿”] ûe·v'åL›(í,ÆùZô1¹”° •ðœçeÖQT0ësŠ‘Ó( œ !«/êÔϳèÓŠ``Ò½‘:¸#ÂL¿èLOªC!í@k3¬±Ÿ¤™ ÃâÀ¸Û ÒfÞ75U(`þô&ÿü¬öΫššZ¦‚5åw0zÊ;Yã0¾ÃCqô¦?q˜?q˜ÿ!óù@pÑ““¿5@Šk;Áa¢È¬‹¡_»ëèû=ÁÕ¯ràèGš‚FCpØŠlŽ¡À2 µWÅRšös¬Ó¨>©räD xgrc€M¾Yx}Ö×x®qHù—¨J5Ö´ñΊìÙWc–§ô lTî…xõ©Ø9è`h­%•U³JåéÀËtž¼Ñ %gVξbHêIáxJ?˜ÑÒ=,46a‰¨"œõǪ­#f8¼Ó§˜ m8ÉY?0’²~Ÿ¼u­ÑfJ%°~Ü𴚊a7Ñ3­Ý8ZÐ\btÈxB©Ôá^\,r~l™‰82’ê´œ1Û(£ÿKR_àãâ\o€y !¾bŒ"f–ÅÚ†HG>Ìâ: ÞÉ‹‹¶œ‰x6Ó°L¬½b&â™=ÑV‚]œÖ÷ì!FÊùÿ½,~ÜTé…ê@@ 7{1€zú7²}gÎ7x›>bèZJµ’æ ¾G]]%øYÌó]‹Çl €µqÖ°•ħ‰«¹QNÜf÷ž‹?øÿÃsí¤_Û¹vŸAë»çÚECÅú3}øKMB\¬Lô_É䥵âw%òA{ç;'òC‡!ÂSñ–úl’Zp—µà˜Kb¤±eªì_5kЈ§ñVîðpu•“RÉkWH¥êËíÉí°QŸ¬Í`4è >›6'7R0 &yר&l7XpÝì¢Bã€6÷>Zdì÷áð{PíP¿_³½¶pK@(‘˜³º—0Ð×GtL@€5än‰¦@â.ö‰3“©8»Û‡}aª%IÉ]ö¸@í²?w±€PkA°0ÄÍ1¥¨]pji;"ðçªY…1@µ+£ àÍrg;É”Á€:Á6.u›Ý7tÞá^C:"*™š’¨¬92ÓE»­>»ÛTƱ°ÝÒâ¬þÖgÌØß)Ì'Kµ¥_V^…8âÒ­ßàH¡j @±szK¾ÌE¬hÛlÊ倖k Á°/ ™PqGäŠRô7d$aÑqÉFþÖŠ"ÑxöÉ–¨Vh¡€rEÉ‚Ë eDä©ظI¾òJ…Ál×6²šój<&4è€a¹®)T·ð9ÛÞrÛê™ÉלÀU,P´€8R‚’¼Ì ´4®¸~´i¹Å]"~øL!·§úÌÀG¯í5§5’fßpéµ%-Tx?‰ÅwzYC^ÞÔ(¼ñúKåî×í¦0p±•òsÉzt˜¢p¥Z%Þ)æòÄ¥u*¢uåYªxx¥ÏœzÒÆIµ•Oò—åìÅ=1qˆa_ûEÀŽ/…%غÜ/Pšû ÞÒ-Z‚ƒ¨pö7"4Ê“… ç*ÜsN—æ6 Ëû Þúä¢~aª›«Þ84¡”ùí‹o.˜N/Hß‚'Õ Z°:knêºãäªÓÚ†Ú.äÅaÖ:ŒÍrý`Ù˜ ‹jæÛ¦?fªnéMn°@> µrDßm]—©ßªˆyÇÛ×å égEÒצ³ï. 'ü},³/MÆU´þ\»1Ì‘™\ؘ)fš:æUÓ iñCÎl‘RW»»ÀÓnÝ…ÁXh+¹_F×H|©ÂB.8×Ùg‰ ƒìiCúÕç¯Ë[2R`Om…Ÿ×á{17¤A¢ŸÁ׿¡Ù`èµ Öœ’)ƒÅ%÷ãššÞÇáâœÐc ŠœHJ*Ýf ¬n¶//RIHä'ZsÝØ`.¶8m“G}žä˜±´õ°Å(w‚– [7ŒwT¾ C¿«ù9‘ZÞ%@Ë% =Ä„aµ%F;\z†M—׆ .y°IWœm¾ÐðÚÁmM¿ÕB&¢•Ó¸ç^¬ÎR@ ÔÔpa2ÿ‰ðŽ:0ä»%(ÄĒ׉œaÚ™ïËpÏšU9)”œÆäƒçN,`ZÏG²Ï«zÕ,9ä°vq«„é.ÍP!±7» m3¹,Ïþ+nÜ;bI¥y+vdŸ—^…š'°×oÚfys1h¿òdêØÕ¥EïUóʼn(Oo4S°'¥<òý;륳 æPçì\ÝÓÊʤ)Së§œš÷e@#! w¸+ñj¾Û°'¶Ë™M ¦ßQœ¤@¢¦}«vk)_þc Aí¸˜pöx5ÇN80«ìQ"k vgI¿ènDÊ ±ùLËŠNݾ¹Ìéf„ny%s™3#.¤²5 ?¡‰ ®a «S,9ÌóvŒ»¹-ú’t5'QI2\St뛸›­9ûBÛõ+'D¬ '%Ф û "mÙÆ²0µ¥eɦ+…“È üvŸ+[Ѹ/¥Ù²˜>› 6Üt,ÎEƒ¹ ±³“ ‘S‡M‹RÈf:0z=6Ðæ ^ð¦ëÜþSCRúº!«×ZÀ㮿³fè­ºÅúuR.eçwhFîív wGßTøãñ[=|˜¿WÁ ÖB]Z#²½Ãì†*•gÞÀªC«D{¹<°B{“F×óŒ­~Úu'Ã0,Or­b¼R‰ç7‰Çf1ž«mÚ>P) îmX¨5QfOfÈ¿jùÙÂêÐöÊåè0N&È|LPB¢à‘D_7a¶9«yÛÊäíŠÎk›’…Äx'$aÑî·4Ï|¯ù¸ŠÌf S›4· sZ_Ãì1ð©$,x%¸³÷°%Âw¾’›+äÙ1r$e.цŽ:—ï܇¸ŸWËZ‘[Óá=|õÚcǶ^f©¤*¸‘°eOh;q½!IÛX“»^h@”<7x@V¼mà h˜w»ü§BFÚ(E.Rê=0m2Y?ŠtsTbà5ù\ž7éççÅMž ƒ}?•Ì §ÍÄò°¿ì38S€.Y1OµØÚš,Ÿk¸7úPºÈ?šêÁfö–M †ŸŸÝûWúï?äðN'endstream endobj 363 0 obj 4946 endobj 367 0 obj <> stream xœÕ\éݶÿ¾õ±ß"~ŠxH¢Z hs8M`$©³i $AºÞµ×.öp¼v÷¯/ç"‡µo}´Haøù=Š3üÍ)ÿ|Øwæ°‡?üïÉÅÁ‡¦Ã³ëƒþðìàçƒùŸ“‹ÃŽbccK7÷³9j]œtœaÙØm´ÍWytîx”ÓJp‘êIL“¥#ôAaÜ»ë¬?ܹ¾›Ì<ÓQÞ‹‹Š®ù >ârañÆ4ÿ€ŸßÃÇçðñ|Àþ›áã‡>_¦Þ—ðó)|¼€»q9p‚alNRŸ«Üx®Jc¦v‘ï¦ÆÇm€0Só¼FòU;ïz§†(âz Й¼‰C¤íz{Bèø0µ=Í_Ü<¡#t^¤¶8ÄJæŸ"×lß§gÏk«>ίõbÓ®w]¼J|9x/Þ˜Ozë…ë#—¯jØmj&AŠR£Éù¹ÆÃ0Âå…iMëà/ X\÷tq?‹µ–àû(Äfˆ_]ó$^‡Ø¾s¡‡«ØœÒo‹Šäá †x¶y`ÌU¼ÐÏ y bÇmnŽw¾x¤3=þ¥âí #Ä©Á‡@ñ<þxÔޤŸø96g-®’øð:Y\9¬ f„Î/¡£[¸³KŒó\敨EáÌüX-ì5Ä€=Ò´ÇÌèˆK‰Ñjá°m´®KáÓ„éx#¼&ô‰#¹ç5¡æháÆJ£>u¡ó¢•=.8‡ÁƒË4‡¢ ¤¥™È5Ç?pØãBòvv¶ÝwQ‡a´o (<7ùð,ü,Šœ0ì &<“gŠ× ’E'½ZÝ⦆'Ð|'u4sž•YzÅVÌpßÇ´†¨âà€xÎÃ9MøT¸§$‡ÄˆÏfÎóÃ9`ôY ÜBF–KLÛå=»‰h‚| £à&E´ š"*LxÅBž69ý@D›œÁÖ'<…ß)™È"øµ+4ÓŠó“s¾ª%é_PMö,Û‘a Y ñD¢¡%°*@€(ÞyÞ•Ëç@9³„w}_ûD Æ>£-›Øo¥GV:²dœ gîÀï,x0a€'¼˜õ%žèF‹DĤÃʽ^ Yø€Š*ƒÙ \gk)Ñ>cP£ h,} “á|m;ïEp4D‹º%Lîi¾WàT@Nþ ç Ÿ.<ç€%…³ÁnÉã_-j3|‚nÉ­ó•;»X°\ÁM›-z[Á'á­NIf´ïð0y Ê%?ެ܋ê,h؇I91l¹»‘¸^ Ç$*ÎÑ,<“—â"gNñÓá2Ia è¿÷Ä…ÁÆvm`àUZ¹,™™ÑñÁ½´Wô?“ÇŸ´E 0wO9±W™ÓI–V7Î8Èæ¾"À#IÙ…†’Aü3¸:7ÅG(ÞªÉØêŠžY7vN0›_o™¿m76wÓ#» 祀Ê2Ä¢Èm—…Ž-Lfè¸aeÊ„{EG™0ת‡ÖëëÆ}ΫǨÄÒyÝdèÿ¡óºžQsyÍЋZÇËJÊ«0úd¼Żµ…çÜ­9¿ePÎ’IÎkô~?6_ßE{Å&“„QW4ÏØšnˆKÅX7ãæ&Dh2.Fß<€Fï1$1<Ùæ|ðàó70[D°ˆ“bÏi43\‘P?Oªí5Ln$ÝÓ{;£ÂçŽW´Šhý€L€É€³H;ö$ö;oF2¦ÐM~j>nûntÁŒCîÉS«'|™‡ÓslBËqÁÉ"(ÞI¯H»8x<¯ òfŒãÍiµÜ|‘G}ç¬ÝP3®]/Y‡æ}²ðldèè"϶(ÇK=ÈÚŽ²Ž¤@üe‘ÊìÓr•ˆ‰mZ}@³4º“™|¬íi ãç4ï%S˜ÕòprÎ"ì¢0¡*UÚ6ÑJf}‘³±vÄUfÛP¥Û²Uý”¬îÉC¾Ž/Ôea -IYY¢˜¤²ΗYÎc²#ýN6”+!y:¼1¨ò•”‰%X¯9ç‹ü“¶ËÁ§wdãç.¿¦2•]¤,½‹¤g™e›aǧUšcEžÈJ®óDÝ€'®…Xû­…SfÈŽ€¸jdØ£©5‡q3üo=mòì€j4þ“ ýÏ3C•3êÐP|;'êÇ\ÀCõ…|E3îˆX¦qöWÅ V†¡Äœ¦y©”¬,æ–á5Ãû㸬5wæ[í‹KMrQ¦8KoÐS†«ô"¬î‹zYñ&S4 ¡t £UÂÙÁ+œ;vLà~s9AÀÙL2'>@Ovø¿[Ÿè@4¢Jé?ª™Àƒì<ùÒ=⮆xQ#ÉÀW÷$#Õ”êÕ"ÜÓð=áóþ̪Ï)G»‰Ä”ûìUîs ÌάW©JÊ‚l<¿@qÞò¸@¿™JËÊxÁ9¹+Ü’EmQOI;¾AX—1‡>%C”­kr¦”$?iÑ©óŽ*jÌ긙4¨d'C×/ßW^«¤îWe1Æ­¥…Ja&¥¬á„ûÀ¯Zh 9ÞÜÄ5Q‹|ºpkÔStF£2åS(@ñWXàˆìä’¬‘ I'ŠíjtÕW™›OÉ ±¢rGñ–•I[Á,Ê*x3 ™7*§,U5Cãnε#µ}©}ùܨÔÊ•VIªêˆ»/áL‹…gtÃõß²h@¸ÄºæŸR=‰|•b ±ÇÆ$Œ÷X©JÁ ×—©bt®¡€$Pô¹í¦ù,îǘêJ4ÀðÐ÷ âM¿Àœ$@tsN ì1Ü¡C³ÈN“œ¡zER˜2u¸ZC¸¡Ú IXï¨KñöFoÇI_ñÁžl©^®dÜpCÀ”v^‚šEÄ]Éš2J²Ô§ÀTF Pª–Œî;K[ǔƿ["›rØság÷‰å`ÒÕKÕ¸8©6m‰_ÏfoêÂ/J§æ5>•'F71IбߟaÀ@`ì(À¼’êEÔ²%€O!aK œ™Ù nÓY· ×?KØ¥DR¡Dv.À|ˆ«Ñ§2èʰ„G° Knêñd*šÎiж[–+ºiF¹B+Žkj0ì¯æ ÊbâB!Zªžtšµ¿‚û7jlÈ@®°Å†‰jmKíÊaù·P—äEÎ]ðÊ‹”Ü€(¬°9>XµGü½ÎÄ‘ ÁàºÁtس”îcb…’XÑ w4.‹Î””.¬‹ìâæw)Ø(¦eB P× ËU…Öª±g8,O Ã%N«©€õœAN„ìCÊa2–ËÍ(\Ê9'^“UÀÅm qqw!ˆªlùþº1YšºL¸$|Ì~ ¤ïÂãñ2,¬Æ0)§ª5¯tÆæ•xœ’T1ž•šz’-Ƹ!(3êm€éƒNƒpe¼âÒ ®à‡‘üåë™Jg¨ª+E4!:“¿©ù JÔzÊ`’ÜÃtA݈‚é(vuA>žXñp7<ÁÚâêÙ±’•d‹<Ìs*ó€O=û‘Ršq¿Õ‚4x.Vy½}…Œ ©µµô~JëSXqëmˆz±Ø¡íý¬ÒÇJ)8´1=ø’£¤R¥î$›.&ïå»;.bsm`‰%Ÿ{uj²ä„§bŠªôbÖ;§y¢À“,í®TûjÙ3Ù±^sêsA.;B«pd~%£8+>Ì7V%½K™Jf}?#0ýð¼¸ïg-ß`Êå–˜vZj™RQmWÐIEÌã2›b` ÝD—^n#PÓeÀÛ¥½*à±-”tWý$wuu‘Ѐٚo“k¤þ^ð¦yFù};¥Ð]ÊCjYÖö¿•hÅo’‰óüü®½e¢.?zâhwËìš~Ol—ùUéYÍ>>ÇXäd=Ë «½%[•IâС'\-ü):KW5ò§¹ñ'½›ÊÍÊŠA&¹Õ•‚®W9ËöS[K­qÍ`DÌèx“Ô¬­û¿¨íGx ¯,îÚ*ì*uÀ=©?•Àîúå€J€]ËJä̹lïÜÊÍyvG›~þ†×ê (`æi0YÞÛúã³O 멾k”1|ñÀmɽ$än$"ý‚$"I[x2ô俍k»ç¶Ý¢.‰F èj Ö—cúØZþÁtËBÝ{2ÄoP.ܶ,pÔ§z½ÊÃU†’Ð[ú0`ž3ù5S.@Ôþg-ä> stream xœí[YÜÆÎó@?b€~ÙÁç|œÂÇUúv”Z_ÂÏûqC¿;KWcK kˆr¼¬]_ì¼Û]èYJÓƒÚÅ«tñ"_ü¥‘«$Uë ©ÓöQ¦¦uI¦¾qµ2¡ú¨×¼U¨q¿Žãn?ŠqEÛlº/Á­ËÆáò;j òêâ\LˆW=ˆÃ€ z]‚yÓÇQì⌞±ST¸ØëË´<¸q<qºþ:‹ÚÑà1ƒNNáÚ!|ñDyfôŒz ïPî8“³Æ ñù`wïa‘0ŸqŒÓö80L£ë`ìDäΠçg0z¾=²>ª»6©{zðJ¤?GG“N³ e¸ld__Ë©ÂO V“ Ýøfêm/»›ÃÜr7ªÉ}èÇÇÄÄ]À’pC@¯;˜_¾6Mˆ)‡©k’lÖQ”s¹ÝG(¶"ÝI¾iª š=ÛOm°Û½¸4 e¯#lù!+ØWº ¢*þpd„²\‚´Kð@O öÔ#˜|€Ýº7È^¸0⤀üq€ú2™).2N'â|°=ê Â!(Œw°àØE¼+¿5y×P=çÒaú3Ì?2¢ÿذ©xºX@F`À]X6š“Çz‹]û:D}A»(þÎÑBXÛ1þg :Pb7ÁÂñ89ÇÁïþ›´"«˜¨ ñBðêÎa›¬€YC@RV`ÄÇÍêÅLJÀžLu"L#Íø]´A¸qÏióäo,ŽWâI5´Ä+ ¹‰žÈp|Àf;tÒX°¤Î”"A pýˆ¸$ ÀwåüŸd†ŸÔ9(JÒ¸8ßÑ9J³¾±ú ‡;ÑFApë#LvÀÃ:ÛÊ¡C}– ^du5qíqUÓØöcR””ÀøÔ¡Fœ*’}ç®ùW)¾Èrˆ›]?TÈ$Pû©™H™aPB^j =(î3D±ÈÃzÔÀÚäP†IáºïÑ$Þ´ }SÚIØPì¢HÎáÎ.̶›\¡Þ²{s|”^2} ]Ü릤wciÝ©7:£ ‚ì~â±?Çvß ÏTs?ÃiÇ?<‘N$ñ¬0¢@­ðT¬X<’…²=Ë%&=&ÊÖé5§›Äµ§rìÊ ´á¢u•uE¯ Fs­o( R2Û¹9Íýòzš[’ÛÄk¹5ÀRGÅRjÔõc©¾(˜êòâ‡N–¦5v‹àÔ9Eäo>WäpuðFMHõ“ùùûÔ0ÏçT«€ x\›î‰º(ýdF¯hu&à÷+ •?pœ|Wï1£ªÍ\ŽàñÄ|ž" ÝL¡pßÎÓÇÞ,Údj‚»ÿQ»;yÊ5Y®î¸ª=Þ…šö½|ëgîE¸•{ ¹QF¡+±?âU„ ͯ rO?ïâY ?éŒtѳ]%Ú5ʽ@*D6‰Í<›Ûas˜ÐÐA»b„×bà‰^”0Š p“Q  ?gZ<'¬bQ–I’jÀ¥åà‘‰íÃun-J“ºšÅóÃ`+^ÇÖÊDØøÂð‘5ê%½,ÜY!ÃtöLòœ`N'hômïç6½ÀöÀÖÝ•‚wÍqEº eè8rMÅfÙP’J+â]sÑ;'Ö–¼Z^?Ä&ô ³Žÿã§*j«e‚'Ôõ¯¡²ç7Ñ‹õ¤¨¢|=b‹sîEãd³­ÇdÍ _g,ÏtÍu,”ÉBv^ÝV±ÚY]XtQÁ’ahfˆ'¾Ï&Ýc~ˆë+UI”Ø[¤|u¶˜öì%ƒ±p?l.þ‹>"Ü^Õ{<õëŠ:TUŨHˆÞ%-u3­¼“ºò-à‰=¹Ûèäb¿=NuÙ¯#R¼à„9)='šØE:å&Q'‰Ù ®dÍHÿ:|ḉq³–ŸACJ¸Ä;ÊSQËÕ§O,©ðù9bм´Ò´³&yoDþIvž7ëT¬Ÿ¦-{Þz­,Þ§£½èà%ñ¬K.оÎ3Ç®ëk‡ú\ó=a!°/â–»u7UšêÓãq(›P"A\@†ÌHÅ\wÀW6Û1T¹–½ÏÆ‘Ü}W¢K®Ÿ7ñu¶DJÎkY\÷¼Rž£"ú&û3†.¼ šy B·uxƒ!¸‚åxãÐp½µÂ~ä$ÓQE˜;l'Ú“Ã#H¤P%h±íd(…­,Žt©mQò9iŸ1Àc¡Sùdê|Ç×ІØòm, ¬‘­N/Ä„Öô)¶q¥aò7b/!ÌI$Åw&Aý<"ÛÝuè0–©´s³S‡SÌ|ˆce¬‰ûS?¯ñBJ@yÞøòÔgöâ/ƒˆÂ”Æ0¥Ž_Éîè͈&¤Ø ±rs³”šÖÆÎua&M¯¹¸SŠëÁs÷tÀ ±nÉ[(îb¼ÐC¹œÍÍÇÿÆôÖMé€5¥yŽØóã>ß:‚Š3»¡Ú:¥ ­Š)ß¾Oã0V”CèÓJ ã°Ä+­5M©e^e‰-µøè]Ü+¥iS%IÓ†áŽÝW¹gfMÃ$\sMi ½jÊB‡ªÿdÔÛ+µÀ>Í&³{ @E¹!Êú€¬©¢·Hq¦L`P*wÈê`|†]QÎÑÖ”cÂý­ Vâà2ÀŠ÷… É #›å S±ñp2¢ŽT½¥Kcü ÂüWÜÇWl‹Š¬¡ž%ÓÁ̳ÖR‡™¬Ò0æD ­ ¸¬ |bÑΗʧ¢ú”$D³¦M4¦=MXN±>àްšvÌ1û|òÙ¯†Øî%H!¿ÿÉ8®3à9ý Ó¼!dy‡™æÁÁÞÝ9ØJK\bÕYömbBY½2S-ž¯™J•¤ Ë¡‘Úãz²‡½LÌÚJÛ…§ÉÞÞ×ï³13ÄÚŠz‹+v‹^Éø­MÑÊl‰ª ?Œ‡˜SÕR9ÄKJßæ,³2Z°?è é69ô´Êöá$¡zÝ´‡ùi÷ž—yõ³×ya€0ÚeçØR­ƒ[ÁGn8‡ÔÓù(í0+ìp冴©´ž «Šü’8¤¹x£Ã7G ëbrõY¼ýǬçŸ!tC4?|½Áç5ä‹;%h•}±³æ/HÔÌÀ¸ÚF‡ª0” ¿‹]ÅlZ¸ é+D&¹n‰¤/¢Ì‰¥Kú‹pAãš (]žÄ` Ox¹©¬a%<ðQåp¤Öuk¿%qõEšâÓtí®õYw«§2Ä ?eQ—ŸF±¿Ë|INc}S«ÖšQ‡Ô'ŠÝÐß“ÚU¸ü¬6DzŽL-GMMxAYI¦r=*˜rÛ²þVIžý"Ä|œ­²„ütmYQU&‘¥~hSÖEU™JÑä¸Ä Š*Ç’¡ù£3Bmp¡F>0Ç;Äy6V"n%¿“8•L3O–ó/£$©æã>{AEÚ“»$ÏÜ%Ni¬"àAe[IZŧKýH€±ˆušYÈžÉe4väL¨oûq†ÊÏ[O¢Åó©JÇd£’s›‚”ð-ös}LƒãP+ôXÕ•í Wò-üY¨ †)ŽÕ¯>àAý½]ÀDD< *e=Þg R!f‰…êpU½þIdçPÓŠ´-$2 ”VÓ 5âej-B´ïi¼&5ƒË)¹Û½$I®]tiB#®÷ÄÓ” Ðkî%ç~ñø@Ò€Ç=yø3Ÿ“«åú%.÷^ $à˳ÿŠyNu3Mµ<©Ð'=żn©œ²ò»»Y/E^‹˜cñDÑ{†‹‰õYöÖü.³ì¤|ŠY&iÖð9Wž”UFäB¨ÌY™ÈÃÝ­F²â¹‹_ËEJ-ÉiddX¸8N ¶µªòZUÅ-‹3i1ó6•µ# ¼³4IO ºr\¸u¤šy/Þ‹Xfp8/áRài4qÅs†–Ô 0‰âPÎübܲn­t –î‰>ÐŒ¸å^‚ ø)ša€Ý¢_Xäê1ŽÂ¼p;y¡ Ýž¨J](U0 h0ìSBhr{çSšc,+‹2q´s®BNÁZ³uŸÇƒ¥]õ{ðãQ2£?ÃÏo³³ò.€!fF‰‹»¼’šíµâÉÒÅC8S¾F໢浞~å š{§¸µÂ†v^ú^}à~žçéõËTÙÅLLT&tª•Rw aÖ+=ЛyC~9à“l¥1)XÔ/ßFgÜ¢~¹q‚ܼ‡—W8jkÚ0D*ÙcÜ´›¢Þ;´½>u×önpø’›Ž‡™ð¦Ø²C’kÀSœ5½#žÛyK§…[Äo.ÂeTá˜D”V½ƒÇÔäÁk–)#]ñ½õ;ð¦÷Ò)½&&©F¸.®ž¼™ˆ ¾. 1Ö8ŽÎZS™4='‹m"Dz«{¸Ê_Ÿå¯4×`dþa,Z²LŒãé›±˜~U5‡.ž'ƒ¸ðt³ÿ'NG·€hï㈽œòmäÃ:{í$ìäHÑnNŠ ‡íÆl`/hëÄH"ð. ýû§B·:á&ÿ!÷)Š|—:¿e¢òM¼¼HîsÙâ%Wˆ-^¾÷¨fX3ò÷j¯+ÈFtk©ÍØ¥k) Â ‹ Ù›>U^£YÅM¾å¼+®'¥uV^z|¡2ÆòE2Š’‘äÞ5Rç€flJö{U¼LU…q_ó á9J¼‹ž,0€FD¦ã&"@'‹Wûç;Lïäw¹SJ5èáf¬îR„’Þý1aW‹ÂÎ9DŠ ¤@éÝ×vê^Öñ}rªØtμ£F˜¼>Žª© V“<õ«Ïâšw6˜'/ä»ÍÿkÞ·endstream endobj 373 0 obj 4473 endobj 377 0 obj <> stream xœ½\[ÜÆrÎóÂ8¿aß< 4Ùݼ ,ÉöQbŸÈÖžAœ‡ÕJZ)Ú›%­,ÿût]»ŠäÌŽd#0¼šá}©®®úê«jþzÜÔíqÿñ¿g—G÷ŽÏß5ÇçG¿µøã1ÿsvyüà$ßІ|¥žš©=>yuDO¶ÇC8bª›p|ryôß›¾êàÿÿ9ù·üDlÝýT7c~èäE¾ñaµM›¿Um=Mcš6ßTaó¤Ú†Í \ÿ¶ÚÊ?WÛšºi¶]ç_B˜òù¹çQûü1¦ÍVm›¯Žùõï¹é‡ÜjÈ÷nc7á3ür¢¿ü 6Mè7ßåVbþs+±Ã‡ó·6õpcŒ!&nžVÛn›TùJÓ…v󠊹Ó~‚aãm}ØüGyºÜxR.êHp¹Õ.71 Dè…¾encSí4‘(¯³\®òÃc»ùPÅÍë<°ÍKüž%ÑoÞC»oóä6¿W#Ê©ÝÜËצ„?ÃÓïàîfs™g'ß;lbh7ç|LÐCðÇÓ|õ"þÏͰ@šmþÜ 0˜`KÃÛ?@'ç…´õ|¸’wy]Çaó[F¸-”±@7/hŠgù±køH]ê-Øæ›|ßUé‡=¦ÜìòumȲˆí$úè†9€îLøUEÁÒÔFq ˆsóæµÄ5b„mæv½Ñ$»÷q/Nd¨a?´4Qú%Ò…qDýe“¯=Ë Býà¿T°ý¸lYíLl Ú¾¦Có†¶ä¬X±gpóÇìŠ%‹9³–ܦh¬\“ìHDƒb Ú=06zòWPà¦A‡_Ù]€0@9x2·Ewn¬BŹaFk û¨5.!÷Òãt†J5V¥†±^ì±~¼VüƒªLž±·MnÙRHìŠ- EâåÒÌtõº„©oÐ(à÷kj‘ö_þØãO¼Ï ’¬v¨-h/Èçƒz‚ÏÏ"–ü^ç‡jì¨üW¾£ÅÏ€;Ô"#ÀÙ`?ª`~”&¾¸ jpÒ#+®àªë…Þš¦·z%f€nþ *OHýoÏd»¦ÇV´-¯aŠ0zÙn§d9Ì ôwc]¥üˆš"mAcÃŒë„>ѪãW8ùQ–eàFBìÓ2Ü[½x^$Tdù¦Üyeeiì7Lì;§·;Ïç üy.£U óàat )=Ì8ž|¡Sú(ŸèÁ •ÕÿAõbÇÔËJ½v )Cý‡þ^—ßÿÝ^Ñ<Ý»æVO.îbšFt57k_ëÅÿ]Ó½³rQ'·Z¶u¢ÝÅDf§ãÂÁh< zÍW.`D¿DöK§dlÅþP•1PïbטuÓ[Snã­ørtÙS™ÆŠå= àdá@6lFà5†¢b&ñÚ[òŽ÷uÁÅТ³µÁb ƒHÙÛ‹8íBKW˜G‚°îQÃdY •WëŒ:µhÜä̾›žäÈè·@~6Bn•fíᘮ/ëKQ‘[ õ_0D;Øý¸å‡I@ÄDåçÐn=ŸÍŽ@ªâÓ>:| º…hê/e+€j¼¤æ<ãÊñ¼ Ê %…Á³è–:ÁWÃ˧°Ð,ý€£Ìþqs??ÿåb ÓYo:þà•7é[_‡$úV۸ǴqŠtµ“ƒ0!]BK9$œuYWw¤O4—UD‚œvkc3³{‡ž}kÀo]‰báô¶Ùæ²Váò«rti•Yœ?,ê°§(=‘øöájÅÄA[ß!¢‘ ½0@ºå¯wi#ÅV6–ˆ^±£¡3p£x;7Pv'ÃÎãH@Ui2.öjD(3än Ñ3³Ø ›UŽfѯq–;µ 'ü¾S ˜¸ð*`¸çJÚû‘×6ÿ–ò¼½Aâ){˜?w¸ŒŽ¨™dPŠZVI+g—¦v‡]BΉ7´°-|³j tªj&1bÿx¾<4SB‡Š:íucÌ;Ÿ „{¹E@9Ų¢ þîwÛ°tP<á›[òžìNv:}ZP¯ ûE*3gþØÓ 35ÔåYWEdENRvm0N±Œš½5Ù$šú’ÝÚå¹Q® µªK@*$ò.%è|)Ñ{\êS’ 1ÍÄN•ãF•zî‚_]ÑßÄnm§J¦QçY=ÍŒ²!´Þ ×g&«ÙŒã‚Õj¬“š*½ïî#™œ½Îûk4‹|êC~¶d¼ž»Ö¸fÄ’mÂë,¸M"„<öAS ]íGlÅ«² á4½ ÙÍF(4ºÆncEÊk)‡©¾@„%؈µCð¦X‹E*–¨ð@↠🴅ø/€Îk„x°Ì`¶Ãбeo>(a7\ŒÍJÇ‚ÏÐ8†¹«D®‡µÇRìQ4‚—ßÖ(ñÒÌ*ÌÇ¥ž©¹LsÜ ¶ËNÂò.ñsÃ7o±ä°R*á_à¯ÓTòŒ/Esz¯ÅfùUÛu¾s¶ ?TxjÕqÜ7ó]ÚÞf¶c»§s£F)Þ%ã>vwÒí8 wï…H‰¤’EöY³ä« ™t=aÞ¼¬92EuáÀÈïwUö_*@­ÙÀn' Çdmž™êdƒ!Ô(»Ì¥ç!´,=>.t˜¢öv‡[Å4áŠd9†A2a˜ õŽˆ ²=fެ^ÜrÌxGv£kÖ})äÆ/- ãӿޛÃ3òz¡ŽjÇ\ÀiîÚ%Û8±›±N :G#¿.P”ÑL_gf)zû&²†ÎõM ñì]ò{iÏfœMÚûÀSÊ ô>@ ÌÛF¶MòEݧ,Wj(7ÀÔJjgƒR›ð9§€Åtf¤¹j9¬•)ýÕ”ÔÅkâ{"ð9WiKE¿‚ß»ƒÁ:1š T ökµfÅkÓ$r r`}G"¶jý&“åUhÍmI¦f$ó3Ë_¥†¢eÊ0"pÌ7>£%ÌÖöi­Õ4Rƒ¶yëÒ}<ï» HÇdɾ©¦Æ”ð²œßú¸×BÄ@±èZÒõ¦ìbƒŸKÇÌÜ0Õ­f ñb…Jè“6+U?¹jÕµÕz# Sæq,̱ t6'Âǰ=Iažö'øÂ»¬¦ò¨33óµÃa|Q…Ý}v)‰+ö )ùM¼N|¥°a(Þ„öªYv±1¨&õŠT$eáÊ–‚ ’p&¨eJºè‚Ųr-Éÿ­Ü[0ñß9Ê ”ÎÖ;Nª1’}©«XL•ò½åŽR—ŠæÇÝL´qªÓ U‘HãíOÐ)Žý@#K¦ÄÅU±òuƒ¹êâ"å“TÞª[ÅMŠõí"I­ÒàÁq¹«qjÉxì†lÁˆÁCçe™g±ùÊ æa!46ÆÇªÃuJšý»5ælt¡8€äEð¬gGåk¾™ö2v7ÖÊ#þxÖ£åSo»^ZU}éGŽ K†;qÅåÒöb›yrŠ›“Ý:CÒÔÖmò´Õ:¯­ee#îGá+k©™¤?ÜG Ä’› ›1WE÷ÖˆÅÕ+6”q&˜céa™-ÅM%ã}F)E0VªäOxo¡=¦]5â¯Âeqêu-•ªøçÜûdîúÁ`óJ¤Â•Å\ãíÖÏ}‘uìRÂnyçìšmC@ÔŒ2)ùâ9)$ø×ª]î¼"3j¤ áܸ³9@ª¥X)®X õÕm× ' Š”Gð=#@¥ÑŽ%·!RÖx¿U<ñÕÉ•@»sû ízbí®¸5й‰Cªª×~qQ|.KU;Œµ_V±OHi¨³U0…Ò•”ó.º–ÊÞH[ò›0Ûõ›F¦v8²óAŠ)Y³`¸3Á|1î£}iAÚUÇÃÆ;E¾I—>Õ\ÝOf¤Ï?§vfG|0HZYÝÑ)®¼e.n¨+÷\ÁÜ/Uvh Ô‘VUÁŠå€1å>î©Áçã îü «k˜ÊA‚¬—iðaŒõLÂ_9Üå]•d±ö‰¦¶qÙŒTÃ[×ïÜl†Ä%:…J3ç3îL"!kÚ.Ž™ôDLP=ó‘3æiQ“õG‹\`ë˜3>Š"˜^üG‰Vö„Ò†gÅɾ:xž™r™Š áÍnj싌sT)R*<± vDVMù„Ñ”W(Ù@oŠÚöÁŸÇÜGj›ºØps®'µ#FWRó"ª¥q©í­ûHˆ1wÖîÄÒaù$š’·>«Éâ¾ó2g­ |°Š PÂÂ/á>±Œ°Ù‰‰Ñ¨‰.”ID-ëtLKaÏxÞ W`J¹x£÷ýª–úÀEB±k´´¶ìV(…Óyèoezl9¯ôdZ¡â˜çèm¸èŒÁèøÔ#J6`UJ=Oi±{űגpXÝ6â®<½0?¿Á¨•ô±¤R…z‰NÊ]”Cg ¾nüèº 4 Ùkð;;“ÇÞV”L'!%Rµ/Z­[_ZVµÃcÉ‚¥àO]ÀmÆá•†B¬¢àgDíκˆ¯Ôعƒ(œ®]ãü8|i'8´9 1«Öa$t³VÁæ Õø«eºKyá ÊÍ:Q¢ ÔI QC,_WL2AúCi1ï·'G?ýzœt§È³MCêSÝçáül6g—GÝüãñ‡w·/î?;nîÿ þ ó)Žäýö5ôÚáµq®”qjK@yJÀIU !ª[ÂÃxáðÂ7:-ˆ°lnàÙòcÊzawŘLã¼Äd—@äÝ´ €“gZP ¥Ô‡çìábZìµó–roYãÖPÔ1ˬp1}?ß…2:óyhôÄZÉ™`œ×ÑÅ~åø@Ga,D¡±ˆwBrÊð)óÓ Y¹bÓuO5¢Õž¬6|Ãêg…"©OaÙ¯gñˆ´»ž'ÚgÂsßS5Ì.fVÒd+¾zCÈKúX>¨B»£|-eû[¥çŽ‹cÃÑ/l !²Ï÷¥/ŸÃ蘚¦• WhÈ5òtM‚jBëU!ÝÉùsäàp…+Y›¥]Ì0cEJ›…ãàœgnxž¨^/µ˜—[ƾ ²í öÕÍ€³5äp0VRao¬"#¬çï0(uA>ªX v… `üÑÕÒNåü96Íï9)L+¼²÷ó°×‘ÆÞË×@°{OÑí¢@@Þ§‚õ5ŽÄ¶/J)§š03>T~-µ8iN,‰ÝS‹pA쟄—{ÝÙç¼.#CA불êÑ”'YAÌ@1±ó|Þ·ÈL±?bÖãÏÓ·yç9¿…}Y ôúDî½#m ˜„^JÓ—ó•Ó:Y!BZó;Xz=„¸ÀÈÂE²Z$-í*®ó S¸ùh”(.ßÓTøj)œc4°êZ´%W°,f¸*æˆâ=Ê®\TUМ¬ö̼¤&ž|¦UÀp÷˜-ZÞlÛpSõÓ³ýóSp†| Š!äõ$l¢òÅœ†Ã¨WjlÔ8 “ž}ˆ–Üž‹ ôN¤‰ã:ºäZº^)Œ3äKK$¦wßÎ+-ù:x±b+ç0ì¡#ÍÚ!IÿR'—ÞѲ1ó§ÕÚ™ý©€¹OÂyîa͆æÏTœÁaëóbê¿TåÔy²çÒæd­”!i5œBT˲àæãDÝ"!ûa±’Ç8¯6P†º“·Z” [ Ðz¤`ÕKˆeð6c_•†ܬQAFäÜþ°vÐhãÁ/Fái{å)wYH-ñ`Nlµ‚Q%.Ô',›Ü 1•¡@„æKÛÍ¿VúOÕÊ 1>šÄÎÊK6î•‹¿ÛÇùÓG«˜æ}"rñž^üäªøbyE‡y™Ç§;;7¤kö†s-«¿Ñ‹W¦r¾õc_oôÆ+c²ÍÑ 6ö],æU0Jõè=æ›R­ÖÓ´s½øϼÓÎ_,Ú¤aBï\ÃS™–ÞkKþ++½Õ[ß—ßáo”!-ýÓÑÿ2æM—endstream endobj 378 0 obj 5669 endobj 382 0 obj <> stream xœí\Ys·~gùGð-;)ïdpÌ ð’*Û²-ùŽÅ$vÙy ¨Ã*‹‡IÑ¢ü냾€Æ –\ÉÊU•ri¹;ƒ³ÑøºûCÿ½9à?þ{rzð§oçÃgWÃ᳃_ ¾<ä?'§‡¥Τ'}¢9ê¶~s?Uý¸¼ÆgŸÃÇÃn;mþšÞ~™j˜©† Ϥð‡ß|Û9›:›ìæk¨U^ÁOìý«º h$µfí?Ž>K“4VOÒs?„4Ï£Ç<·¹© õºà–KnÝÐÏ&Fª`;×jÕŒ}œ’À¸ÙO“\ž¤±¿L3›Múã6?ÁÌž¤ßcÄ™þÚ®aô›ã4†i×TÂo®R©iÜœ§çOñ+ Sн€6“D†¹ÙîU‘CzƒUÏ Ücø€_—Ýv„wÁÁ3—fÔ–ÓBÕôíAiÄ Eý‚uS€QoNÒ8a¬0"óªÛçézë‚ÅI@µó´d!­¨w8E ÊŸÉs+O:¸¦7Y¾ª·×ék³wÕ) t!n~îP). Ïê‚¢L›WEñùjH øy¶´ >ý°° "£KLŒ£±XIú2!AÊü$ªX–ÈWe(0eÕcyclíûà·Æõ#¨ Bt$FTˆã4¤´5i-ykñ^sÑ ‚€Ò@o@Ò´|ø*½‚²<<“Ê‚ QX”n*ΚǕ¿ƒ¯ûÐ çbÚ&aÞ|_^ÿ¸‘6XÚ~°‰o»í’36l>€òi‹D_5ç‹Ðs/ ­†vô&:&ëTä}]¤†¢É¥LTÃùTbŒ¢Ž¥™ëEiVFžfÏC…²,¢´;®`½J‹¢y(;†"£Bc Á‘8Ä€¢’ôQ ÜEÑemÇZ|@‘74ǃ5‡39íD Ýr3ê Þ4µoô¨Á§ew`i´°OÝäpÿ-µÏÃ$œŸq€@”Ð ›PíB–[¡„HÔÏ¥Ùsø=a½µ¢³T;פÆöÉx°6<ÊÛ{×ùEYAV†õ¾™xÇr_à éA*AËaŽeæ:°¼ e'œRÛ°YÚPUiM®ÆÛöcÇÍ‹.áÊê|VêಀÖcÍVŒMVeaÎKÖêµI> ™j*Súépk§ÞÓT>îŽàãSùF¤ p^¥ÏkømKÝnJó~.}?OhèéãEÑãRæuyx’ž—‡/òÃTÇ'»ŸÜžÍŸå!LÆÉ%Ìb‹cß—ðñ+|çf^Èq å"e‡©‚ëáÞT¶Ž^äoÏËë=pyø:?¼,ﬞ4jͬž©‚gùá œ½i‹÷y‡Ð1¸ªJcŽ—¹óüìe«àI£à¹tø¸ÕÎë² /rCOª~äëU)ú2=f'Èö¡\å;£Ô…g?vù{Ó»usè“£Á‚Fa›n/ï]xq@‚벃_tVox?†ìtŒâ3Ót!ßµßègrZÞÊoäÞM6X…-:÷úÈÊœwÚKÎ>Kí8ÚŠÚJøq‡•ðl>¨\¶äüú¼nhŽÐô½„–Ér}õbå;žßqˆqà@Q2iôz¹Q^SAÿRÜ¢„•ôN*¯³¶E,?ÇÊWÉ“½ËZØ´`va, ‘S¦1‰sd¿á ÑùïðñEÞ\÷àç7/2:ßÔèüzõvO¸Û-_gèÚQ[¢Bù5DÚ +¡à¤•Ÿ·¦¨ç-픂g-KÕê°géPWYáÖ¥vH¤Á—-(D…2!"N-|ÚŸ·¤° WÖ¬c 9’ñí „~Ñê節 £wGõð¥ò{¯[u󋯰‚|ñÕ»Ëÿ;ñ>cÜ\t~Dlù¾¼¾¾àžlDj&b°³÷5ŠMÅÒü‡ð «O1ÂÐg‰.á¿ ²ÆïE8° ÄDtxU; ¥Ä20H”€Í ´÷æÐI½þØÔ$êoò³%ö£ï}µ ûåíÿ±ÿû½û¯Âþ;ÄÚÄþ;ê¼cìO;Ë÷ÎO¶‚~{—÷æÔ™~L+€²qqcò³!a¯q@hâFLË]SÉ!΀OP'É3»~ò>™Š¡ŸÒƒDM°)’ŠÎ“ArÐ>бÉg ÁY‹³zgÍä#ZÎy;§èƒpxh&/ïáë£òõ‰\Øç8þ1T%»oãáàÏÊë2<5’–]tI¿88úãÕ¼n!-ˆ¢k’”ùT…·`1“=A=2¢˜!Ö3›Ž|àƒá'¼SÖç±ð¤bçN+õËÑFÑv7R6.-Èšžƒž·Â*7 r,=<éОy5ºôh"óú3ÇB(âšÇjR…ÁpòTívë„HS ÏûNÂŒ. [Ãû°øÃh!dqŠOz3™NuÄñ“æâˆñKɽŽHL`¥ãÊbßúùªK2ðV‡r §„VYÐxû6cEB¡ò6ë E>gð½:E©O³’Ðl<ʼn² X5h»‹./–fÆ6»´Žâš_ƒ¯I[+3WiCw³«˜|Ž=šK©ù/”ÕÒµ”õ*yR…,„ Ì î:³~1®$ê S)qS2ºãBPhÆùJYr‰œY[Ôñäâ¾%®KÞ¸£³ZQ3ï‘â<.K #)çj¤ •%©Õ ‡Š"Ú“Á ,§¡óNRÙ–/9iC¢Tœìjðõñ&{j²ß†yD8g»@5˜}Û˜jOÀú¬¶`ÚÌ€8°V9šÙ€K^ŸgNƒU’Då#êimœ:¶ÿ Ó6i‚ÈkX˜!{ÞDÜó!à`e‡’VDÅ0zeÖ*8¢•ŠÚŸûƒt㲯Œ&!á ˆ¿÷e'Öb–° å#Ô(-â¹Ô ¦]&±4w8º”‘¢ŽÛò"ôÉf²*uÓl¢HVZ'aå³µåR÷óRÜËâ*™Q=¤áaåúçå®p7˜PÅíáFi‘¨Ñ×>Û0!g€œ·1É:;oÚ½°±5.¶Dâ>ìð–ÄBé¢o¥p±šb_ãˆô=Ö=™û06|>±Á-Tˆ]:’Q̓¬34üëåDYwZ/É uÍHa™$ñ® 0ÚŠ™z2+Ue±Â’06 舧‹CeÈ71#®½ø¦”ËЊ*xÜïéT'Ž4²2©ä“…yÂÄí܇5ÓMÈu8ÕËÙ@2Ødïµr;rðŠRI Z\¸#$x÷:[Þs ‰ Æd¯9¯Óļ­ÃÉY%è‹ðb­ˆn#{T¹ùÞeSTxu» öÒ«cª½ÔI8xoñ\!s5œd™]YÙ 6r LU’ ÷F"êìN¦f¦¶†{G;æ76£C?ùâöÕ?[äßvÕ)Ê Ðÿ]¢™‡$ÜäXüŽ4J6±8ÏvŠšØ=ÈŽeÏhm s¤ w.¹±ÙáMÿHmð™ŒAp|,u\6tÎÃtªÌ®ñÕ£<àGWe+žS^œãŒƒ‡¢ǵÝI§.6¶ûu/µÍÑöOhkí¬°’3êW©ìÑ›±æéTD?’’¼¡RHD 9ZotÄFÀ•ÊÜÆ€gzò­;ÏØíòHU"E(Ó:½Ž©æëïf ‘í­ÐBç”’ï3Ÿi4it“½ˆ[‰%Ûf—€à5UœÒ Ù2M†Úf² }M£ Xœ©¢[>îq]ïb·lx.5öìæ¬é:Ôúâ qøäæàþ •5Ghžšv›Ag6­`B¥hxÊBº™uú±ø˜á¶ƒ¹´[×ç«sl¿ä!þ6(¿Aa;4˜Þg'õ)Jå–\£ìC¾ÃxŽ7’ImÆíg_5²Â‹T6¦[£Ð}ô‡}>‘åÈMØ™*8ηjÆØvøâ`ÉŽG ”þl=ÅFbD3ˆvðü¦á=Vd^ Þ{}FÇdeÚw]øAçdvÃÙîâÏH‰µ/2k貓¨Î×;;ï„iqS„cv¼XÄŽo¾miT9­YM’N4 —f<(Wø1AªšÎÞë«ô>ørå`bÁMó”wsÓäTd—%Ô¬È.Õ0®É.¯Ñ)Q‚ÄjÍ*'ò= 1H3ÌMË•C¯yŸÖí(i9æËÙü .îï"óE°;TÏÓˆXv#wLS“^ùÅ£¨>¶5Y¦Ü•Ö ¯J¥à]~¿#2I~@¸¨.h””HÌü(£÷çÝ^—•| ¹m._:\gÉ·¾MÎqòŒPÖ*òÛï 5bNÎ U>“ªv@Zùý¯œ¿Í!Ü-¶T±&m¡òe|ŠÆÄñÀÞ7ÙuU·×Ì£²¯•'24Ò&´›Ž×Ýåä“\ý›e^U+þ”x^ÞÑ1Çï®$ë[Ìç|ÿAgkä§’`–éSrkb•>å‰xKŠ è>¯ÂŒì û>Ã.-$³A0oonsŸijwƒt‘ÂÞF&‰ìäç¤oµˆ¨Ø/§yìóÖn}‘EèÚùH~‡“3ëµ×Ör´«žI,Ïȧ«€þ¼xm;½¬· ÷ùʲ…Ì~ÌÇGIÿýxÖ³endstream endobj 383 0 obj 4437 endobj 387 0 obj <> stream xœ½[kݶý¾èØo¾*¼Šø’¨)ÐÄv›6Ù’]ïõ#°w׎w¸¿¾óà I‰Ú‡“Æ^ëJ$EgΜÎ}{8ôæpÀéÿÓ³ƒ¾_¼;_¼=0ôð0ýwzvøé140îôó0›ÃãçÜÓNöpr¾ìáñÙÁ»± »Ø…=œ©zŒs?Dèt¼‡†ŸuG~÷EgúyŽ~Þýµ³»tGvwŒ÷vGòàÛîÈÙ¡Œ§±{xbí ¡‹´yй.ß=錻1OÿC–FµÐöÈù¸û¯ñɱ>ù_: vÜ=‚Q\:Åê ߌ±¡sfãvßuG#6·»ï;¸3kvŸv^:Î8mj6ÚÝ7¹wnxœoêLh0j€!¦É²},Ekw½õ‡Gnè'3Ï,ÊG0)ÑÁ ঋ“7f÷7üú~ü´ÃÏ+ü8ÇŸñã?îÃLâ„íwwÃÀ ÈÝ;Ydw'­›Wzó]¾ùS'wy0år>ôÑÍ‘–añ‚–á:Ç­ŠòA½’Þ<éæa÷¬ó»_`¶°»{®3xW1Ðö_vn÷vš¹iuÃý÷$¦hi¡O;;bËGR´ShsÊv–WôǺ™߆ï>W%xÝQÁ¡»¶Ð D–êiç&l¡SÃW¹ôþW ~(CQ[zY1ƒw-@‹½V¬œm¦¬8¸·”xм™÷]µá̇„²µ¸„ç%8£™Ã;&¥«h›.hà´TL’€ó#-¨˜¯·¢³…å³#ð.e<‚U|)8(Y$aæmIo¹a‚9¬Nƒf?üùÿß¿ë®ð¬ô©YÀòxßêsëÞÝ0£?Ð9;8–q¸•s¦„<ésÈ#V<#9"šäÜïÝ“<.N7„l˜íË~°ÐaÕV5 “c¦2Ú.&Øt9é&‘~V-]bŠìÏS"€š,<#§ §ÞÇ2WˆƒÓ9Aä›­øû"Ïý„Wc`T< :Ò6-zž&"®¿¶8rÐ{t‘CrÚ¹M1Ì2‹Ni@zŽržW F>övå² N)Åò`–¾¾Î[KЇ§TÎÑD)rŽ´¦gcy+ƒ y?ä­ñP36â{‰˜¬Ê’|Sƒ§B Ð=r´ˆb Å® éÈÆUŽÃ¹˜Qå츽µ©ÖYÊÁ,lf€ò´ŒF[Aù‰Õ$äyÞUåOÊ!Éë¡~–/)ã7æYÁg‡¾LQ±BmDm AÎ.ÂŒì-Š{à=££ÀÇÙ[¼S—q–†ÆEå4q”vRI›³ÖÍóR££ôBv(Þô²5Êi+€+<ÃU9‰ ËÔ»Ž·Bþ)w[à~â¾·’Ùl€)0an»åªœiJRi݇tàøq™· V+ŸÐ>ñó†Ã˜YT%5œäËm‡áS>îF‡Á`.òlç8¾#j£Å2Å‚G,4{£(ëÍ@i¹âxþÔ>€×EW>aïùþ1-0µÂXçô‰™0<‚ó2 ʽBß>*û2_ÂoFÞ„‹òÖ Kzl‚®s×GçÛ ›xômAwT·½Èü'd ‹3„Ô5´ËD~yR€aM“CÅ ¿Õ xÚiRðlPí׃'Â%¡HBüµª´f^ÒHQe{“o¾Ö›ÏZ-Ÿu´x3‘i.«È”yL³€£É¿Wà Òò=x@»ÀΙ/vš>LÞ zCdŒ›ûäžÝ xT‡gSCï¼g†·½;ãÄøàí̧]Húæ©xLŽÂC?3‡ýä#ãvŒ¡¾3b¸ü4˜ib‚ìú1Pm÷1Ê‹GÙ©Ëkº˜À¥{ †¡÷s ò7c ÖíÀcï)M‚+ ѳ7£—E˜rìóüøY‡©ykù pft¡åo¨÷×Çþ1r ìi÷žs^&ë‹Ù€ë¼Ú7"@™ŠÇe&H2uTÀ4Ä Jøtû)Ù_ú ®$"n;œ«’õp:€;Ê|}Ž˜Î ˜A™V±Câ¤οÌo/R5ßqS”þ.Pð^°¤Â–ÿ‚Þp@q§H ÈÝþ¶Èwåa±ÉVÂè…,*';ìæ K ty]^#âÖb¿¬‡A§3H'V“–ŸÂÜЗZ­‡²÷Ó:WÇ…u.läãFSåãÈWPqÍuifçÙÝÕ©a=ÚNc¬Õ(Mü†ÁS);ñùk;³&zÝ¿©®ŒóÏ¡W’S‰Ááê= i9Ûø»«¡(„ö˜ÊŪÈè7’‰—d!%/Cdâ¼ê48­a܆¢ÕµU¸ÜZ•»hºèrf®„ºRúañ‡DçqúÃk$Þøwë_˜žàN7Žœ‹B¦”Ö4©lÄ]”pÍðÑ ÏBä‡Õ7 z3|,·ô™L3ƒ7}|Ì0²Ž—>îl‰šÅ%’È=k/¯.ëO±Õ}—ÿ@6#UtE”M‘…+eˆ›ääÕR¸fÙ»ØèŸó gÔBã7*• E¡uÕ9 XÌKT…ßR©¯]ÄäâKvª¥I‚ä½`k‡i0'W6+1Ù]©åM¯´ÈUW^r/Écr·[qN N‹SvéM·¬8Õñyör¦Ÿ”1£ë2Œ’[øm_»¹é*S̰§Yéû”¦JñW•õúokòx1(áٯѦð–ɉђkä¹—m >>’SUúÀo ôq¯ãã‹ÁÔ• Åf¬a,k’Dds¼yÄQIðó;{ì…×ëÕ/­A±RãÂ.+úz“÷ð+T† *?ˆ899WÍDJ•‹VìAƒ°EJ&RaæV™ÏSÒ¤f‹˜ ^i:Bs)BSeÅĶð^Óñ’’ÑúŒ¶Çñj\àHĽ8†­O—Šr8eâ¼ÃÈ׬ÜÒ®Z‰æŽ`Å>Ô"ñ¬Ž³š$ɤÓ+oÐò¸ºÊß}bôæ ø¬‘@?-r4DGª¸r†ü ÈVåÉçuþ@`N§”âž-Ï©)ê–aï¬kDÝ͸9ו`÷OÞ·BñüÛ‡_ª°›&5ûýÁ„¼ó.?˜ð™´ßÕr¦º,D*Éo´ܵáZ«¹¨¬ÉÓäçSç•*Ã/˜Ùíóš\à }ÿŸ±¼õ#>®½çšõ¥{•uÜæW HįãfR¹º¨*‘ôÞD ng¬~¡¤,ÉVŠ“S÷|`…NôóÄÖS éºn¼aädv}ª)sKå29Èå™ËM[(Ôæò–*ËHUQC¬ËläÔCQðy7pN5TZ@ýs.~Bø5ñ±±(h¿}I)%zó9"Õ^obZSZóí¢uQ“"• k¶ŽKÅ œa¾þGUBœWXÓ¯—Ô1¤¥ÀÐCIm§÷Rˆ\ðíëSæÂ”kº~“ªHUm³pº”±/“î¹²#XuÇž„Ñbxo²µ]ta#èÃT'ï–™^;ó&ÇçFUêBZª_¥HÖüã¥þº_ã0“ç #%ØÑlO«ÄÑëÌ ®Å"ÏeðõÁý±ÁýN=-°Ö¨ÊaT: kê, ©Å ׫Ëá`T}k¥åÜdcÿï†'ZŽûðøàŸðï¿ÈÞª endstream endobj 388 0 obj 4041 endobj 392 0 obj <> stream xœÝ[[o·~ú#Î[ζ:^w¹ ÷´ˆ{‰•#)PY²e–äØVç×w®¼ìî9–ã:F‹@òŠË%‡œof¾2?mLo7ÿ“Ï.>þnÜ\¼82›‹£ŸŽ,½ÜÈ?g—›ÏN ƒ·ÐÒOf²›“GGü¥ÝŒn3úз9¹<úa;tqÛwnká_GÏ»dlolÜ~Ýùí—ÝÎmÿïéá»ng·ŸÂ_ßv;ïÝö{x<évaû| ¶Ÿ¦&þ›Þ܇žn„f¿½×íøDû|ÖÐ;˜kpÛ¿cçò²Œ*“ë ¤7ƹüÖh]½ÆÇÞ$XæÉ¹,mê"w ©î¸ Öö.lvÞô£&þà+gö°ôÉëa*k¹í.þúq‹¿?é¦ïÒöÿ>Å_/ñ×ÃüÍ‹Üö–Ò§a{Üí¢™¨™{=)ï.sãÃÒø|­ñQn<.‚¼È/KÏӵƛZFmü±ÓVÞ/Øœf¿bŸü”`Ã\on˜ïüšlì'ì#zøuy ʸBàœ mKDYPpx@)“#´ è$²÷—é3ÜatÉÕPO(4Ã4O®Ú%z\⛩ ágüò1~‚›;yB}æþBùX*ì>6¢d½¨AC¶¦#µ_é ¸ÀaZ`±@F«´œ_7Øäõ@}b¿BÛÀ·OéÚýyÂIäµâDÁ8šh¿»à¡Ä7}¥›Šp«ý«èà^‘¦˜ Žó\°–úlÊ—µk‰äÇ&G› ŽQß|Äóp¨z?fÄ)¼õ`øæ5JŸ Õž©rŸl wàš¦×ótÅÏq‰Ó­£]–V1܇ÁU gÄÑZo!¨kPYÅÂ!Iû~‡äÑðÀpúöl†{ôíã´îp<ü.CôJIŠÛ(<Œ eïâšzQ"p¦ ^éŒ*¹ŸãôýÅ_;íx7‹qW›ò»/@büýâæ{°Þº{úÒD£Q /ÀV$U‹«ïæ÷HlhÕbfÕàPF¸ç<):ØÒ嚩Ŏo”úq³ QÐ-b$xB7ùh °µorAÞ±Z1 úH+_àOÐðþGðx#!Y?[v´¨†xKzOqí6nƒBé4uËÙÔ3^RˆÜúÄC8åuDä¢aã{­Ì‰\á\ÇÒ¶ýˆ˜%»ZcVÛ/'¥ ÒxZz¾nz:C=?¡Çõ e¬ˆà*盉?ýŽÌÐx5€ð˜¡­Ûjðt/„§J>»²d œ#øŸ°k<¿F›¨0ùNñþ=ùQJ—È2é×ö¨«”ªÐ½xï°w•_}×ÄëÕ Ž}ôgžÁkä¬*f;¢Ë÷„jÙH‡ü–ÖîgŽ—6ó˜í8æ„–ŽŽ6[ú¥ªûªs¹Ó¯‘z–œ¶ÒÕìÈK ׈ûš²RøV)¼…þjÇ)@±Æ‘™š‰4+<ùhäŒ-‡¢ù®`æj…^B¤tQþ‚Z¯3dBè½'ç5³• ÉÔ¤Ö•âhr¶ñ¨L,v¦4«‚˜Ú\Hds”¢øÇMw:÷ÞÙ+nDþ6Dg“'£$:Ų;¸kOŠ„ä‘Yó¸Ç”xœ'f°ž ÇÕˆ®&ÐFaeÅØÚo<ÚÉþPnŒ BÂu+†ZÊc‡y°3°*Q¶·ºžú#„ñÏØŽÝU‰Ø iüûHN fèGW§£ŠE,º …Pø³E¥÷¤ôâ ÊòÕ(dBŽŽ–CÅ-SÐón‘Iˆóá5¶îGU^Öä …“­çTk IBö—0ñ¿%:¬2W£è#4yCØRa9GHœ°‰zU-åô˜a:à¸ÄS,—çÀ¼—#®‡\yùŠÓÌú4NŠ¡:E’òaSË€Ö’¼/àUé³eÑ‹<õ~ùAè8+±·„ÜåSyûEž»<-bâ*iݹa謷¥M…¸æ’ãÿq-Ÿ_¯‘Éy4QÅ 8Õ'kÒݼûêH]^¬½?[“© ¾:Òùž‘ŠßªËµ—Öǧü|ª)ôq~D, cÆòBëJ*ò°žüh>µ!ˉV¢ñV4ŸŽ ê 7[e˜ŒdÕÅq†d n4L¸±é~6¶sê,IzH\é[/ý† É´tSa"ÚÒo&z{k²ñPYÔ ù8)ûdWŠ_IœË“k¶Šõ†‰¹x2¢VtÃ/dg­o9—©Ô†[hì¬BŒ{ßcW– KP|윮—݈›ìë(ëªK•åDâlĤ¥µ ÌšrYQ?@Ò¦Eþ¥UDþ%ŽXJXAÉ*VÉu ÇU×ß+;«å’òê<³ø>˜f>È¿IеHF0‚Aã (ZÄ4ÉÀCUyË}«•Ûæ o –ž Çʰ,òP\tyGsÍGNëV\jë,9rRuyˆá 3öŒýð®¹Õ7Ŷ÷y?DmgxG§Ï±«ly_e}-ƒÇ.û3a ʃç¡BY>øÃ©øz¨@ª*ço*<¹át0T +C÷üRÒ®ÔÇ’vÍE”Ä£â j{ªÁÃÞ`¥jè» à‘â©&ARóxË`áñÌÞøÃåtf¤SÏ6¯O¼\ÌîQÎC/KÏU]N¸×I}{X©–„¿ª@ïÙT*ÂÃߦ„ŸÙëP+¯9J”C¬äî£i-\èF¶sŽÎûÎú"'¬ç¬ß\tÓRÊÉØ®Tý\Ú.C Rråñ\EŠY–)NJ¡K^?s‰°œ–Úd¥ jy EÈê/Y—”Så‚§Úˆì„d0H ‚æœä¿œ^S¡,‹N E¢|5h¾й\¤ãºEBEæ¢Ô“ТäÝ. $Noªë¹¦ +às½y ÛÎ3”ªocÎr­áàyÆá+)ZÕÛw af™ÉÎý‡^¨Ó—ªæö«Å¹¢.ÇUUe-*î;+ +•?j¹cuš %°DÛY…:µ6ù·—³rmhGÉîÆÍÂÔÙ9èbl<\>Ì<;'G9áî´VPL{žÑ7¾¡,¼'û…®•ÌP'œ9BÌËÆÜæ":j›ŒTgØu6"M&Üapœ&߀§`›dÄöq `‡ˆÑh­Ÿ¶6·¼ ÑW:]?G‹vx d=¯Î;„ªñ9]?‚õ¡¿…×À‡ùŒdô}šð–ªëC4‘Ùˆ n¢ n8y" O†i¶´ýÆ>L‘á€G-Žn²êÜ7åñAy9ìúÀÅÔô”É­¯&Z®g¢B¤úc×ò6°GIõ·G'üaFn]lÙñS ×O%l\§s!©•Þ-Ñ$ ?â|ÀÇrâœf±®¤2!Îô¸¡7Wu Óã4»5RŸêÒóBº×µû/8è£Ú¦†úbqY~p˜³:ÐeQ1@•^lõå_>ˤnÏY¶‹Sšö†Äõµ³d]Ço+´ö]“u<7™UhG[™Ö¨¶ç1êQш-×–8•”\¢NfWzú Ð¥nzö˜õ/™°c&O·J¾Éü+pßwù¦]C¡‹®2Ð~a±9ÃYšá…”Ûë}· Ý„'\ãÞ2]:ÿ&CìÓNï/q@|‚¿0HZøÏâé1 ¦1‡AgªÊÛ–SƒÓƱ/OEç %ÔTAã—µèxº6^™¤Œ¬_FnYro{·ˆhµ·z«2›)—†E`9Â=CßA÷ô/ÎõÏÄ@dÈóÑ39plx±Lr“íÿ)¼Û"˜ú€Æ-Q²+m+ô¬k.xgQ祽¹2;°^=î— ™àOÊuÌ=‡˜\ÛËðÐê¶ÿÈÚþ\ñ-€nþ tÙuÄú$NýåÉÑ?á¿ÿ,]Ñàendstream endobj 393 0 obj 3262 endobj 397 0 obj <> stream xœÍ[YÅ~·ò#FâîÈ÷ÒµtwU$Áà 1Êâ(²gÆcäYlÏŒÁùõ©³UêÅ÷Ž1 BxnW×zÎWgï—ÝÖtðÿ=:¿óÑÃñàôêNwpzçåƒ/øÏÑùÁ§‡©ƒ±©e»hŸÞ¡‘æ`´£óÛΞßùW3¶}Óµý¿ÿ’F8Sâ¶ iÐáqêøY»ñÍ—­ÙÆ|l>imóm»±Í!´ÞnäÅÃvãl·íŒo†4÷6½±6¦—iˆôùsë†ôÓùæ‡Ö˜ÔzõöAšú3žÕ¦¾çCs~ÛÃüæ!,Úuvhî¥Y\úéÒ,®ÇÁéÉø::gÓn\ó]» »m¾oSK×[Ó|Úº´èaÛØm°Í7etéxXóNpiÖ>M1Ž–Hh½&á†i¸qÝv41)]ë¨ó„Ci¢!ñEü2‘ð<¡y‘vßBéF ™…ùDx¼à^´v —™ ŽÙûàÚ`'ÇÂË õcYi3 øÜ~ÀY†žâéW›Óô¿O=?„ 'ËžA›ÅíœRBغÁRª Á,JÇzVNñX×b Sè¼l70 KWrŠ‘‚Ç# 7 A‚PnÁHpc‚ôA…©âS÷ÞX¡ ÏTpVVBÁ¬@ˆŽêc *Í "B à^«“DJkZ ³Åó/rÍ[h¶²–lmY¥ Âk“Å&Ïó”Ní]˜Bb'&eF²ªßTÀ‚9` `tîZD¡jVà¸'ráåýÜ^Gšoq ˆqÃ8—5péûi¶ïh÷΃™0(¹W+9ؼcÌsÃ6^·ÎÐ4pÖ1m¦»–unÀ"¼ÇÇcR ´( :WX«dš€ï.M #NYN¶^AW˜ßƒÖV4ÔÐNˆitºÒi šÕ Ñx­&Ã+Iaeª}’­b©‰‰ÅÀ¶Nšæã=9ª…4ïÞÚLdλìéòœ·¥‡ÏÇS~#˜Ö „MC!öŠršÚ].¡ ÞÍî"®x|‡Ç©ä{„ÑY9äžÇ ¶›ð¢î\J•'ˆcÁôÑCª(ƒ :8H¼Ü†êÈ \Ýâ< ßÁ?é¾lˆàHPáeqŽÅª†+ó†.´ó Ê!&Ðlƒá Ä» |ѯ§WQÐŒú'Œ¸›–ïÒ|¹5¢óigwÙô‰}Z_…X…½(—z)RTdÌc5¢ýéÅ1Ë‘àUá¢L{¼0­2»ð°EÔe6ά ¹°ú­E4ŽÙ&*²ÿùk†<Ä_›YóþA‘\ëPáf½àð`x=Ù6R×sQŽ,Š¡›ÜxUß4jÝ}ÑÆ8ÒÑúßðE˼\©ÜÁ 1ûU¯š²íµN·ˆ×±^ë‰Ì©Œ¾a!*] Þ™¯÷a0Ü#þ´:kõ½~1¯9Γ¦bwô‡5Ð?+@?"‹^”ju¡ÿÿ ÔùÃ/µMÂå§Y¤Æ×^t:´hâEÛÑ”H2AEñíHH‡5@ˆwC™Xz¬'ÝmÀmG-BUè&½hd×éû4ä+8æWe=iÒ’¡Zèí=jŽŽâi—¡;b›ÓmCvlÞðÜ Y4¿Áî⮤€¸ˆh0CßkØØÆ€Îõã™É™~Xò¡Ïøÿ‰PÑþÙºÔ‹.ö  ‰¯H7C˜_<„!ç¿ Ê¶ä¡Àu#¥gÖÜeØç%m çg|¦i+ëbfn€4ˆy÷¤ $Žeœ²›.ëØ:»”/“ _ 7èš1f¶¶‚X,™¹×JÀå>'q%Z¢møæ°¨ÈE~ŽÁ%P•Òb‹†5U˜("ÌúE#‡97Ç+ &ÿOS»ÏœB¨ây×:/‘ešNã<öæsÐM;Íi1_#ÍhYq#ê ÐÐQÆ€b©c‡Âª(¿JeDf5ÉŽîÉ,ŒËyÓ+Vz1ÎÀ ›Å-à‰3Áµû"«à~{ å"JÒ +ßnkKO@E³d»ö!i>ÀªÈPØ®×yÐËZ´óÀÁµ(óÂ&bi„ÈëëvyÑi攈Q +&Õ¨Ãöl>™Ž¯¡›1éEA_çÀÅ¿lr9ë‘MÂkVbk ˜¿Ë 4ۚ꡽­W.’"íBž^޹¦¬ f&™‚2qj˜ã'ÖK’Pƒå’CŽ×!UveÚr`¤–uùµ“¸d´:È-®•¨«© ñ÷Z”çå@= ]ã ¨ÁÌúž¦ãO(‡Ùœ–A¬Â°R-¦yÝöx=«V+Q\ÎÜ)|aÒ£Áz J܆AEäJT²¬Yîæä¯Hת‚¤£„o v‡@åóÝ™ +Ò.ÐŽ_ÈQȸۺ’ÙÒfœ‹£Š/Ó#Çé.Á@£ËP‡r—d×qI°J¾µ“û¹˜o¥½ÛÆQÕR7ŽÓÞß9Hì Ù&ÂÌ®6˜lt’J²•¯xQåíÁN%¶è~ŽC­Ô™™LW•,½nÅÓ¥Q6våÑ l•üZÄ„Z‚Ä͈*x¨ˆ _I+1{ÞfŒÐ6giñYôDDN&‘Éj)ìÝ.¡Ø¯X¿ç¯åÎYQ5”€‚X>±uö€EmÆo¤¨çÑ‹hëè…Ü-,‚ê«Ç¨–TÖûÌv^|îWW|A´(¨º— q¿˜&Ê2@M½3v$Q]u:^Û=õQû!Ùëe1'¢GÜ"­×¤ÕñLT:+“Eäú’R•Ü–ñµˆŸÉ Š#¦ÒyJ0eq45¹3YޏŒGòJ¥Š³^LOâz¾)r#à‹lƒ\dÔ¸~!‹Ê‘°%£³Ò+b¾C1°Š‰1 S…ç«´ÕbXÓ„ízåwh HkcŒ“c=—AŒ@&ƒS)¿XϸW¬çÛ·hûÂÒ6ˆDÞÇvÙÇûvÉLß+ŽÉŠd5ŽIZ©„¾sÛ¾Õ É[×K+y ËÙäZ¡N¦$Á×Õ%yã#„;åG¨SÏâùt²UÙAÛ6û§ e>>”3€%½cúÚ#«H3/r„w".–ʸ¸èx/P`È`¨¸£r‘<Ó>Žo‘H¡gµ£-¾‰|!2]dÿØ/—$‹^Z0H1id0猱ÉwÈ>‰ÊY‰ìŒ@cÛ)r‰2ÞÆ@Qé%°ž:ÍÞRi¡ëýä—J]eCüV)(,Æ k0×þ¸œ¹¶c¾l96•¿À¯¸‚ß;ùT!9¯q!HüZ0XÅj*Gœ ýо.åÈM±ßÕ)D8·±G”€èÀI!ƒ28%2»ls}À‘o¼Ú€DÙ$°&åñï½ZÁuqUÓ~!ª•6‰Š÷ëö²*ÏÛ…ôÿ›Üx±¤~'œ¢FU(°cγ¥áj¡S­ç jT•-dv™ ‡Ke'¥ áÃÜøèQéúAnMï{Kµ¦GK;)+½ªË7 Ó:*Ö¥m¸Cˆ«Än£€•{ž•ñgeWç‹ËªµêB ,ÁøŽ.ôP ê $>¢v9ë ó^U,\8ïMé«X£ôºÁ0€˜ aÖc!AmZÃEY'7¤ÿp AýGMFþ™TÃ#@6çiÝMЫ‚º=¬ã¡XWnJ,h)•(XçgäK!ép³T^³«~ªÔáÓ§úʇ_j•Š!ð˜î.‹t ëöÚŠ²j•u8©rX9…@–¢Ê}A9þ$KÌÝ(UbRèx˜Ý—ÒQ» €ÆŽ§’ ]›MгLØJõmáÇ_IÝ&2Æ-U¨ûl»#ŒU™aí‡:Ž?¹®ÇBÅÀ[8íD£zÛi¨f¯€\gsÙo£ëõŽx¢_ôqyJ ÖyUmg ½KÍ%åXìX•éÃw@‹†ð‚ÿ#q·RÊñöèaòº¢Åjä’=Îàw:ÄwQÀ5ëç•ðçF Ó% ¾_Øä™($ÞçÀZ:àB|äRÇ"ûåà‡ ^‚+ø°åcxó#†åÀ0ï†iJÉS¼ÕJaÅ2SVã :¼g>æ”0XdÞöÓðÂsýOÆùóÉY¾žCì“ÐJþ¤ hõ˜5‡Õ7‹>kuQÔïÿéb˜Ft'Ÿ÷]sÑGÐRíeö§”TcÖ° 篩Ì|‘™›Åå•/Vºu¹íñSGyP»“/…–ÂnÕÇÃEYØñvȼK¼-W(Óü?HøíÖ^ÀkÐ6çÜž© ~eø)‡kæ$T‰y‰±2ïêhÞû‹~~xçoé¿ÿÃë³_endstream endobj 398 0 obj 4078 endobj 402 0 obj <> stream xœÝZYsÜ6~WåG¨òrã™%$²U¶$±ly¥‘×v²•R¤Xv%Ù’—ÿýv7€FƒgF*ûeËåG³ÑÇ׿ãv5¯·+üçÿž^lýó°Ý>¿Þª¶Ï·>nÕ4¹íÿœ^l?XÀ]Ãȼ¯úz{ñvËí¬·[µÝêf^©íÅÅÖ/…-M1/UQÃ_Eϳ®ªçUmŠG¥.öÊ™*žÃ<=–³º¸ßö˙֪8†ÇE9kŠ'8 ƒõ¼ï»¦wßiæ5¬T- ë⨜YØÖ<( ¨¼ËªâÇÉHÕ¿—ª‡áÖFŽÏJ©®ÀtY‚4›ðÕb¥Ó Èîm<&¾ M­h徺xkÞ›¢@ePïA†Kž)ƒû¶UAGJ‘zH.ÏA¦‘/iº$ÅPÖÎk )p)•#ýÃù?žáÇS øDÉJk†Ña†ò†/ø±Ä^}Á³pÖ¦µdbóôIt£¿xðF¢Y„íFU à0p™Ä€øºñÖeü$é5}G`ñ/ éJñ4ÇÙžÅAä§ê(*]óü'‰ ™Á¼Žƒˆ†nt"œwºïH=Z§žŒ¼šÈ»lèñt]¨;E¼w•[ŠŽÀ.é—º@;s(÷-&émÊu_QÂ&S©²ÎMGOV¤èŽéÑ+_´sË.ü$ÍÄ~@~)ý&Ãך¤¯â)~Š£îÊ“†êµ2ªT>TÄ0‘èmÝdˆ ˜°ÇàFÑáùdˆ¸r•¢rM:'éHdŒþ1þ–ÃõH qÝ¢UXÂuŠš†7|áÁÏ9*WqðL’£wŒ('¹AËb˜¸â«÷õ7{Õ’(s ¸WßÐc–޶n=hy”‡­sÜÚQî;yUÝäm ‡9. o1Mâ,Ôc|BxÂWÃ<øS¦±bj ònšIð'ýà(Ô«A‰·9ú+Õ0ä#ºÜ6IPÊE€·L¨—Ð`4õ<”ȱÓÒ’™$Ž„¹M…§Û$ž(©VÆÕ„0Ïë7êk4.Í{‡ë$´¢ô[X°¹RÇ÷ÿˆ ~'zÌ‚Ëy@jU¼@Ûù%é2ªŸÒXP¬Ý¼>€´ÝܨÉò<­1ö5Æ5øñ[(4D¹'Íå¯r(™CìÿߢÖ]Âw® e_ê8á+..øtݤ©][¹~Œw’ð×p“¤æ†ŽÕ~úFðsÝZßÜ—¼æV•Åt«9»u/K‡¦ËDŸ–¯(.©«çšÝ8arEC,|“#4˜p¸é¦ãµ­Ú;µuëZŽ^®igwY¸?ˆÉbR9ä3yJ⩯ãr'îò«ü=ƒæ2ݱÈÊ€eZ;᭠Ю}g„ï4]<€¤]` –§uZO Ë•ÉkÌ¿2&o |¯\:”,£Íäw®íc°kïí'žö=åõ$„éRZåDŠbŽòh©ð,±¬¸D¸ªÕÂ2D6i Oô“Ú9 ÒÖï†'Q,¼ˆXÍ!r}êQË$m5“¡G篟rèüa¢™4Õ»qö6Cb½‰éþ2@ñ _Ã-Ý}–»ÞˆˆÛtÙºjüçÇ]¢î­»iÝWv>ê­{0Vû·hmK­®æ÷±ÖZ,ÈœíWÜ£µ®…æ19 Ýsq˜€¯âñ½‡Uo¼gù.p(wÓýëK\ÒsØIܧiZ&r«'ïñ(F5ò.ðRÀÖe •Ëç˜@:ïÆƒ¦ÛfpŸÆT“Î…Ù‹/\E¡5ö®A:ŒÅ9ËÐÖLÇɆ»b=G#ã[ÆwÜu =zƒvÂøîÂwçÖ1¬%jtW˜Â¾ó «9£=Å6Éå°C—Zvè’[†ËßS²W îU1Šöm ñhŽfl !œ†°aWˆ[b D?ãvK üÛ•ü«¿è(Ú Mð”¿ÓmØv8à&õ¬ÏØÐ4Øûƒ¢a2ATt‰ª¢EQÅ[E¬e¼¥ñ[Ttu3×O¨\…ï/ÿ¸q•ËË’*+dÀ/yí óLµ‚Z ‹5'¡ÔˆfZÑUSñr“Ø-TÙ¸æiù•ªæÀëvn‘×Ñe«‘“ ¢#ް‡øqŒ;<;nÑÕ x9ÖŒx—ßé ŽÎ“Òßü¸å/"£û²JÞ†€³>àù'q~‘£ô„_e)=çùûqþUŽü‘Œì¦r°~—íË,#{9F99ÄwîN 'Ê‘"XsÛs;pó „Œ¸ôi|ïÚkï%Yˆ+ßM?„GlÌåq$÷‚²¬ÇyÁY–RÂ"KéÑW£ó<‘Kôöšý­Å?~!õ;Én=ÊYÇ\90³ºvð0gÚ{9ÏÙ0Ýp#¹Èûu·öÖ˜n¤$Lo‡rÜ­£ô0‘Mx<ŒÏâcŽ––§z<²m4èû‰]ÊßD3G}&Ó•3Þ™Õ½o:Nß%ɘ+ʧÌ%oÚ› —¼M¼$Ί/b峜v„‘-¢L¿Zgé:ÚÎ{©G(|A»B$]/«$Aÿ}THò{—ÜÚ/Q»ùW‘ØI²m Rº z.—ft@õ³œÈ²]Ê•!(¬³‡«£×Qd$¾ó2gE©ÀÆê<‰òœñ¯òVù—ÝØ!þ5A^ ‚ü‚¥,ÿ5Ížÿ¹C¬ÂÏ"ˆ¦F«kŸ¨Oè H¯ùȇœJÄ¡’,o<}Ü©œ]mù[ãú4aM·ìenëaÖÖPʦBYòû’Çò=ÎyìñÝÎÜlŠfð­—Î 5¬æë ¢sbвE’§š "“{îåÖ:çu¬¬ÏWvØ’ŽØÎ2!ˆM,H$t—½¹~úmÜ“ö;Ç>q,•0ðt¨ 7GÍØq˜À4W¹ÙX™’Û¹»ið|tè:wh&;ªZÖeó;9¶7†²<¥ÃÄZnŸ¾e)­)&nA)æ|‹œ3¦”È­{iF"æ mà5‚| ¸{‹­ÿÿİ'endstream endobj 403 0 obj 3625 endobj 407 0 obj <> stream xœÕ[és7ÿîÚ?ÂßèN1ÖÕGªØ*³q–1 •lQÆclñá¿ßwHzRÆ3 Ù[¦­–žÞ¥wüÔü¹Û6j·Å?þߣ³ïúÝ“‹v÷dçÏE/wý?Gg»wæ0AiiÆvT»óW;¼Ríöz·7¶iõîülç÷ª¯]¥k÷ŸùO°Â¨lE76í‹æ ˜x·žÙêÇZ5ã8رº]ëêq=ÓÕÇ÷êYxqPÏŒn›VÙªÚ ¼Ñz„—°$̹W›­žÕJÁèà’·ô]OUÃÜ™±CµÏøfßà¦m«»ê>P1ðh€Šq´~S¶Ã‰ÆhàÆTOêY‡Óuõ´†‘ÖiUÝ© lÚÈ6MëtõHVËĹ FNˆ  ê€DßkV¡RÎìÐ t=3mÓ«qŒº4$Xõ~ ]U½j¨€¡«^ÇÁ ¼ µ¨ªG½û÷Ïä}‘ÒÙJâûGòþa|,ƒâàÜKÉû' nÇžL*ÔoËšù·PGƒ¥]‡îû`gþÝïD*”Ÿ ÑÕû¢dÑÝ ¥÷ktY¤ô4>”Áýmx*RÚŠ§ƒ’ûpòIŠ@ôÊç ‹ÎTý2Ò=GükÒÄìU|qY†=# #Õ-2S}Œ³½*)o·€¬]p•Ъ”ìi\9‘ù£lZà‹“•²ÍÐËÙj•;€SWÊ-MϯO3_À´3ºH@e^ë%±¢mfzPtq5ùÖwÒ´­8f’l_òö&¥¸C¥Ô ƒ¯#ù1š4YË4$’ðK/‚`™cÃ/è$A·'šé3Ïâé°/«hAN¤GJ>„›aÍÝv”1W–9×Q Þ#ü®#•°aП =Pe‚<ø¹g²F«iòhè(à”W¸C¡[ÇÍ?’Á° ê…xÜÍš€ß™:/žS3#!¨°©oíMp íF¯‰XºkI±¸:D6 ¼w×ýZϳcxÚÍ£ÈL[lüXDÁËÍÈR îú‚Z–‰£¢e œ¤þuŠRŒd½‰PËÄ@pŽMÀ“ÀûÍжî+£ « — ú§Y䈫˜Ä9˜ãß5ÔŸeá$ì¡êú6܇Ðiü}X¼ð6¨@0¹Gz‹ÆÉ¨Ç,b >ÑJÛó’^­·­'û©v”wY=1k&3|Þé¨1Þ0Tfb±¥^1,.Ù«ú¾‰MÒ”±5‰\»¡Bà5³çžˆÒtÈHÞŠÝp¦¯-‚[ù³ä·™EÂùxîèYpK.©f,sîSqsC £8øÓ‘‡bÎ+û‡ºxÙÕÙÆÒ]—t÷båzžb­MîoÈóQçƒémÒoŒ’Aé‹H ë ±çûT*j¥=»* $\zYl‰xÈ‚CàÖ´Ôc,/ù—èÀ/ðº; 騱¶õø4¶¨äÇÞ@¥:Š}çÙ ½(Tø½qmè~xº]¢|;öQÔH—¶/LÒ&§kÊüúÐd¸ØòšÈ.Ùª²1WD·Äî…gÅkCдKa—¬ôàœ ö19PéGÕ*ó„—,}~%Ò©y~óØk(ŸGÑÈK>´'>$¤ô©EÔÚþx§¾ó{„†ðcÉT"SbÞâÍ´ J³;½A`›#òÔiÒÁp ãG‘ñ³!rÆMõªêm!c22dcU¥²,ƒãKQ$ñ§¿°×CÑ£ ÕŠñbfÿ2û}ݘÒÄß©3`…^vƨ7ùÝ«ì\$|¢Î‡ž¢Õ?¦ü°tP’Á¢ õò¹¾Y:G‰2>–ó°Dès|]Ú¼Ñ$Ë/ Ô3y±dRÃ@n°äÈ9ˆ¶„V ÅЧ0¿¹ˆÐ fá¾³P6Ç+ZCvÛ¯°Š›ª·PyQµCÙús­G®Ã"®´Ú^Sh…]ó-`ŠË®XhRSð>);M© 4×Á!ôéŽZ ‡0>¡àÔ¨ ÖÀ›ŠÕ•õŒï¼ˆ¶rôµ’|©“~ „ùáE±ßP ê&•›À y¹D‡‡ZÕI„²ÕcºéZEuÇ&äLWå›Áˆ>áyÃFãt·ä@¬›ìÆt 0ëƒÔ¯„?<$f Ú©«c!¸?ÂE_Ûqš®§úxó®ùžâ#†º¥~s|„üúpq”Ä7c›o,…ƒokÖ€JOå{Úd½Y3An²ÖqÍ ü!06i3©å–²“y¹óâÞ7bÖºËÂíVb–’Ë9‹C/™ÆZÒ ·‹¾¹ [øÖÜÒÝøqG§É‘ñ«þ8GJJ½¤Ç ˆ=<À¨ò$¨M®¸ÑšXÃ1Þš¾쎉)*°„´§A0ºä lˆ=Ï}hbš2•뢈à8è÷®ƒìIøñ‡Í¯ÌÁSgÎ}ÉíYi4+\-…‚9†*¶”§Œ©qäh™ÚKjTë÷IpƒÑˆGÍã…M F,¥Úný„oÌ`ÚaŸ€hlŽ ´n¶Á?MkIöë˜qŒ¡, 1´Œ<㤪Ñâ11vûIIÔD‰D‰û€¢òÏœ`Vò"‘•@çÈ#ng¥w“£šÈUÉQ€Q–2H87dLj¡cLq|4=eñãUü)”:TâÞDaÒGò½˜²8çv^e,zyðAfÀÈÌ"À¸a#‰UBLLÏmðÆ+¹b·¨~€7Ð'ÉáôŒ}ª¦ï¢«¬‹rM€˜¬¥˜‹æÅáú)']w—±H€Bshrl>â¬ãÜ¢$ …üÁ,HBóX'K™» ¶¸þï+.cèXXº»ìIJ 'mh}:JDo'!+¯u¼ªU œùAÊÎLa0S¥§ø4d»$a¥£¼2ÞM.mX.¹É=z)mæë>².4ÐRðW༆ó–§ÁÁ~ßÅOêŽ4ë­Ç_tõ”É^€d©Ò”sè4ø3{Ç*§6ôMÚš-Kc$HžÄ2kzHmŠÑÁWiÎÌÍiµ#­Ç,s’—í!;Ÿ3PmjÓÎnfÓÉnqu¶`ÓYß3Zô$­DŸ¯k²ËšÿRžQŒ­½" îg÷»Õ34ù ôUGZçïþðšo”@uýè+ŠUE€ápÕS·¸ã„h*Nð†”¯•ykó dC•™É6¶ô0›ÃQîÓp”¿ +´“¥Ð)'ÑƦ‘Hwi$J’œ /ÐVƒo2£‹‡‚2—OvRJq»6Êô+à)5üÿzÖù3{ÍØ¨x ƒÓìÔšš;Ðц.ŠÑã3Ï|ì8®(Ò7ÏZÆŸ/%×f-Ï|pzXLIÞ~uÒ2=·<å¤Å—é]Ò%ùËÙ+9›ª%o1(8eIö_k¡ÛuŸ®ÙMÃA¸Ûµ¾ÿ_Ó\!÷ˆ0Z¸ç YÞ¸D犔fƒKŠ:!‹&8Æ´åžR„´NÉW'«:°ÔÇÉ_¯†˜©Ö­ïýa&º¤McÏ­{|õCçfC@Ÿô¸‘KÞáÿŸMc ¸Õá±aAÒ²Þ¦ñ—(Ù”<Ò.Û”¾Àˆ~Í(‘%:•?åÞ*‰xJcµ2´1döC ˜Z›ÂzŒ u#©á^mS-„ZFâÉÀ©*ôGÁ)¼‚Œ±¹††íJ”¾ *õ°Lo*«ÅIy½ó'?“_®jÔôÒ6ÕµÜ¹%¹(8VS¾ËUCþežÜKÄûÃæÿà^bËëÿ´Øø6,«g’»¥å{ ¡~Qî%K¼¥—dY;ýàwo¾ó üù/Ñ‹¦«endstream endobj 408 0 obj 3685 endobj 412 0 obj <> stream xœµ\[sÅ~wñ#ôÆÙ”Ïaw.»³T‘*n”Tȃ,a+e,láðï3}žÙ]éHE*èìe.Ý=Ý_Ý›_NúÃpÒÃÿø¿ç/½÷ítòüõ£þäù£_ xó„ÿsþòä£Óü€ò•ÃÜÏÃÉé³Gôæp2¹“ɇCïNN_>úa7vqwèÜnÈÿuø÷>õáâî/ß}ÚíÝîoù>þñm·væ__v{ïÝîùÏÓnvŸÃÝ|q8Ìs 3ýÆ;ßç'Ý”/ûÝwÝ~̯È3u!è]žkt»¯áár³ŒÊ“Ë äÐ÷Îýûô¯yƒ³{ q:ô)oóô"omÊÛñ]¤]°îùɽïÓ0ÏôÂ7kÀ1yÏ£I˜+Ð~XD¼oÜ^¶ÇjDF5äTt#‹Þš&' w Õ½"ŠAÕ˜ÿ[¬ÉO$…ßaeù•6½wÓ|Hád?øCá ÂæaqÏòx}'l)L?à˜&5ؽÍÍ…†çI¶3OÇ íWðL@]ÿÖE‹ÕŽoÈ:ƒ5›ì ¬?‹ vÉáL¸Âo:4i­à%湘ñ+ø× ©//†žé¢Ê þ0 ‹PC¿‚LàÅ@v×Þ)ʸ2ªázç!ˆEÁ)K ƒdt|ÝѶÐÂ<:»K€I½—£àF˜Óê`ˆ¾ŸµÉA¿* y[‡qmc0ðä¹d1Mx ‚çDk-_ƒ"ëVæéõ·ì8AàÇÀüž–ÓÏdxÛ¹§€òšC @cÂâ²DðñËró¿Ì0î~ÜY×ò<¢šáçkøÙãOT6L(ãšáXø¤qNQ¬ªý‚¤aÜþ¾${B¥æ}ªhˆûPo×\í± ‡ìçÙXZ5Áàè¸jáò}qž‹EloVÛ0å‹V¬´ÇZ¶|¥æéÀ3ÈýëÎ:¶ÜGíP–&Áq‰ÎT ¿u‰†r'}%žv,êƒë%ä©uÞ8ÚŒèóv?v¢¬ 2(°†TÖØÃpÞe†´ð'yVp9>#ü¯uIÁÏá_ÙèöÝ/úÌ<éž".F&z?F¸Ýc~X$øLŸ¹.Õ‹Fõâërñ•‘ø8@.lß1ìþœE‡‡À›IÌÌoõâÏÖÊÅ«µå¼Ñ¿ž–Ûçk£<._¯ tVn—‹7kïd¥ÊÕ puH~N¨Ö ®Æ‚®¦»ÐÕ7JÊÅ ð¼‚8fA*{Ÿzµe°X )ŒßR¼…cV8+õK4÷øÔêÕçà)Ëð3y<":.ÌZoÁXÔ™…RU ï.?”òC}þg/÷+ÝÏóeÄDh5‡ÑB‰ëúl% ò8*O»)AŒÎµÝFEÖ}\qV Ͼ'¿²˜*dz¹v•ß·“׫„¸7Û]ÒÇ`Ýb+ˆQê7‚©U$¸ZüͶô\ÂA3’Ç.s‚#¤~Fñ艮éó"u€P¼Ãï(²€É\Ê"Ä«Š{†˜Ñõñ ² –“WV™ ³©ÂýhªEIºxÆc&jkxŽ.c†…|ù‚ kyF´µ±c(€]+ ²ÏéøÅ¤xB Âvxø‹¢Z¤­¾//·QhûÃ4Š6î¦û2Uã*„tǪФ‚|`$Û¡U.içÑPý%Òý…„Œ_`7ÃŒ‚8+<È“lB…°ûN,!mG'ï):-r:¼€O>§û ~~ÒÀ}ùâe-Ü?«ì=Ñþ þ>ïVÐnåkPû²\¼XÍ¿¯%?Ý‘BT¨» )·oÖÞ¤AW× tºÙ6jÚ&4¼ G(egÆ-èTxœ|$=h$v]Ž‚s_nÆÀò¼.Ý»y@Ë:ŽºˆôFvqj†ƒ€‚"¦ §àšñüLL" XhÕ•€wÆz2ä/Ì¥aça¢¾fG_éêì]ÂÎû­*eÝŽiÔn|Øâ"]„Ó:­x4$Æm;bä‹ÿÄ ×›¼ÑÑŒ&oÛó—´S¡ú(ìÿ³†ÕÀä?Qÿ:SòìS ‚Wac½½ìvöŠ–Ú9Ðí]‡‚¯DÄZ†8…AúãíGÒ´#Ò™9 µÅÓX&ޱñ§™ü´>œ‘{X2Jb¹æ<@.‰Á'¤ƒs“©Ù¼)öaX—<ÚåFŠÊÏö±Ž?.õ·qÞ¤„Í$Gëºó éxžjÎ)õ’Ôê…¤‚Z½"â÷%HÔ‚†‡/þ釜ïW«=yå j¥FŠq_¨bù¼ðI¡²Ö9ƒô‹ §œÕ4†Eúj‰}˯ƒ'‘½ƒügtxw©ÄÈÙ¢oÐÌ?ÑpÕÑŠsïÀwsJNmvð_@c°¦—@°düË2ÆÂ“rV—S¨¤¢MePv÷ѲéMòV“¨k€XI æÙÀb}lõÀæ±É3Yè´aÃ<<ó¡i‰²ßæFð6”°`w>"©~L0+‘€ÞDÔ€Tnb¬+}¬ú*µ¼’ TeoðâHÉŸMtm]Lf&yjÃ^ÀM·ŠÞ)Qˆé°–ê î*S¢È˜ŸMd737 ûªœªu«ü†Ó‡Õ4_o2ACWU'«!Xêˆ-c`Lw+gãíÖ^Mª3¼·ú<?"6v`Ç”B|]X2a5%ÑUÊ,ZµšÃz6چκj!‡õtÈп?§ecð2Þ•œ„¦Dgyýý„ì^¦>2ž5¢`¢JÛ“N’g•‰!Æ%¡/8/š–õh5UŸÂÊâ½1„Å´¶SåòR¬Ëµ´ŠeÚu%†´*Õ­P%N϶ªÓVž"Iv²é€ƬajòEs2•xÿ‚Û$â*Ryîð^F¦Kþ›ù§wó¢õùwaBzÅT }%o‰š ™†˜„ŸËl˜Ö$B—´r1Á€o³¢’rÇÁF¿ Š,‹”8θ¼ ^HÎe3 `XÖ‡’ìl“ë‘'@¶c¯‘@ØÜ†—ˆõîRi2¥â†½þ&Þ›Rò¹íéžUÁ£Wt¸VlÆdîŠ>Îc’6ï›?â8y^AnJT…‘bøv¼Ò“d<ÈbQÎ:9£QX¯Õ/ ›úÝj Ø4 üXa§Ù µcaE¬À ›Ááöj×t+êõcÜ}@! ηM¼üzÊ%<ÀHì¨ðN#¡è3õ?Ÿ×ýZ÷¾.ã|Û¡Sȹ×÷úŒû ¬2Î+8…áÐ:N‰.)Þa `&°™ƒ×€DÂ’Süs+@#æbÿ€‚°da”TÀxyµ YòÁ·2€.¢l¶Q™P°ÒWe8ÈÛí€wÀIÅ´Wú\’Šå)C=Ç"tjôýª¢®œ`š KÙT°ÝtpB¦¦òþ‰h¢âó-üIš8/_f¡¾'¨À™h,…8ÇÔ@›B%’Û–êª~+R´5h‡E\g*N¶êé&XïÊi”þ³ÖûÈB–U"½I£ÉöŸÚ˜#­X׊ YíÃP|¼’l;kùU‡WSÏ1šºOë3@UÑ&Aïuê&ù`f³³1ÕþZm¸ö žô"8Ä^På=2Óƒ pCuˆë=å[2PÕ•™àö”𢀎­Žðª¸ÍA(¥Ö1÷´kõ†M“?K³/v &TÒ¶5¸hPçÕ¢kÉ&'ÆÎþ€çFœâg.:St„Ù„À)êÌ´R|ßÇ?ŒñÎ\y$4@àÜÏáFjŒaÉ~<*Rj3”Pem˜º–‚J‰ÜzW¥›|ÇñekBÕ= ëÃT ª.b«/·WÛ練NX-¶“Ñxøªý¹3XIFnév‰°Ð€±37A«5Ël»˜'Ûë[´z³Äl5^QCÃr4'1õkõèÑ ë`q«£æ€Ï¹UQLStÉ{­µÑ¤ ùJh>ö‹†b™uÖ¦qBi„ˆ˜ ¼‡ýÄ– ¡VÅïÑQ~-UØ1ê‘}CxlŽLPص¾Ök:Ò9è¢ÊMäæ×;OŽ–üNŸ#~Á¦’¾×aÊ¢gBJÚiôöm<í²vRZà;gv-IZÕ§J‚!ÃÐJ{õÚAú¹¤—š¿Í˜v¿@œ»‘Bae(M/üì5óÁ×_4´¾l³Ã^ŸØtì0ŸtVvv7 Ì×›'™Ï8aÞ}óÆ^€õ\˜ «ºujÅÖê®ÁzÙaeÝ¡DYæñnCnwB[®]e†‚ ›¢Í…É q—yV·¦Pù±Ôo§É¼)§‹ «ð0’#–ŽE_)LÖSº—íø$‚±K‘™ä/‡íj^IY›¥£ÔªÆ—š6Nòyª:]–&æ!Å ìàOîCYÀëpÍöX”ž ·\ÛÕFVæ‰ kƒCçm§ÈiÂÅ™q‚ÞúÀâÆH2G»±#ÒÝiž˜îfàyc0 Ú°†ðÅé äQà‘W$¬>_³øÜMúAXŒ}Ô¨ËÉŠ¢Lï&R½Ænç– 0ŒÝè¸-t8&ûF\™E:;ë«/(Çhú—¬ Ð<Ð&w5Й“TlZ(ê¡îVC½à|uZQE[Ý÷ý!´\¤á˜nñ¥Þ·ùQ²M㟻¸:MÔîïåŽ9îø“g *ÝòùÇR¼@`±nkØØ&ËŸ^ø·V[æ6üòágû}˜Ÿ(Láµ Šm?GÞfÔˆ¦ ð ‚ÝD?k•öÄt_(ÐRYZ³ ç¤Øg¹÷JðÜ¡Ø;òì)Y¢_°ÖÌïÚ`“º¨”óíw> stream xœå[YoÇ~'ò#çA3±w<}ÌL·?XY°$‡bŒvxJ„—»4Sú÷©ª>k§g—dHÄp`˜š­¾ª«¾:úúm»mÄv‹ÿù϶¾Þ¶?\nµÛ¶~ÛT¸íÿ9<Û~¶„Jc[+¶÷N¶\K±=ÈíA馕Û{g[?WCÝUºîþ½÷Z(ÁZô¶i 4Ú;‚ŠÏë™®^Õ¢±Öh[}[Ëê‡z&«=¤ïÔ³P°[Ï”l›V誇¾(‘ÒB!4 u^Ôª‡O¥«k!€jº¬ô-týÜ÷*¡îLiS}‡ßX²Kvqж•}õzQð© ÕQcø%t•’ÀªÞ׳«ËêŸ5PÚNŠêY­`ÐÞ"ÛT­—Õ»Ô:UÜKÄÈ 1½vÐÅ0H'B.ô™Ð¢1z{¦ÚfÖ:QÔ²Ç9Ëê3°7høî«¿{ÕôV]b¿W8m ÿ¨j büØ«Žk]-°µPÆãˆª7Ô 6øˆuNÃK¤wÕ!´Û¯©ã ãc(1-ê[àÌ„k†è½54îz9¢º‰`ZT7µÄZCOÕˆo¬7 ¦=—8ä°‡C×s˜…YwXG$¶ÆÓÿ¥FŽp*¦‰rWíÐD¤ºY£â\ÏÐΫîªÌ\Gµ¹:‹ô;U?r*Hš ÿDsX«ÅoHhUûN MÛ ÷ó°0rê>L[™˜Ðbëg”37µà»ëÑhq†(’7K¯Á‘òÂÌ©ðÚ1)}á*kš¡îI'dqhÕhVduØXq†š¨êÅËÄOÿC"FU_!g-uŠB Áp Îg“x‹\Ý ­'Ú­@×ÛIÀu6ÛäÈ„½¤˜C‡)ðb¢ ZÖ $q>"S­G*IKeý%!r‘çÁ””¸¢7 ÂOg›Œ‡¯ö°ÙÂô˜%̠УaZC@ƒ@áQê¾ ŒÜ*B‰‡¤4¤ I9G§ƒë`ù59&¥YXAH! ‚û¼30ÁmjeÈž)Š| CzýS¯™×“VOÍQŒ¬-Òڦ׷r°Šs ”Am8è0`….…Öj±fèí’¼‚ÍÀ\ ƒ–$?n ªÌ”·š RmuÎñ"ëe¿Šù#Çf~rÜí¸`µàv0 ŒÄÊÉö |`DòË …+5sGÑÿ£Ü Q—AÔ¿tcÞD½aé¡Ë#„ER`‹ª`éœþ‡¦Ñ  §Þ4‚žrO~è[¹"MaaÂY7µ“ñÐH&9Ñ›V8!çÈtcCÛW5&BÚþR/—Ü0É}£l=€Lls—¦îm½ ‚9*â( ÞùvÖšVdþÄÿÒÁÒtèZ‡ü¤,Þ»yÀÛzá<¸aYÁí¼q„ #aõcò¸AήbÈŒTO3æÖç&e}ß.ÛSÓIÀùŠ›/…‚’©VOkŸvjÃÒNi Yï5ØÁIm„X&PPîéÄpŽ?k«U ,ò"¡ã*ñ"ï`L<Ž_W©x¿DLC.qˆ8Á膾ßÚûÛÏ€aþǵ?»¡Cñ’Ðó=‰¼ŽÖ÷Ž^O zsô{ƒždl¸U“ýà'„UÞÑJù«â ¶ã42iÐk4éÛ÷èR!ˆA!¦ÅTˆ#Áª¥E«§X5ÂâQ$ž&âI$‚%umÈ{ñ#KD;aÉËET£%„ò³Üf:\¶™îÓ'ZcÁ\>'(s{ÌBèÈ U>Çe2­ξ§ž§3êU±îQ¬;mX'%’äq–„´IÜ/cùw©|/ß{ÿ*(1NÒ9Ÿø˜»&O*fƒn4bºqk®u˜ÎºÌr›ó «Mƒß6 l¶— ºËÈ/ÖƒüC‰‘;8¿[¨Ãs÷±žý´2/ƒÝJ@ Îæ:ƒÒió‡ G¹ÜƺL"X”j^%a&$Í'²äµ0þì …4ü§Rî|YJ׿JPX–ô±è2™Ü°¡BÝKŽoœ×ÌTÆ®$w¦E·ƒjÅü~@SøÌzœGâuIe_'"‹&É[ý|1ØhãVÔIøÿ“-³Ëd;\$+*]QôþHMž™u΋ 8žBB&­E{£Eí“›MR{lÇï“™Ìßž–q^Â[–ÿ?FÜ`&ÜÎáè¾!"PyŒ¸xÐ ‘/ Æ‹ ìb7QS²É£DÌ[Æò¹s=eØ-J!É3Ó{§ÜyÚ«Rô|‰{‰ø.3öJšaš¯Þ¥FiÕú&w"ñ-SQè~ B×?™ùg+´µLÑØœðýR;K'6!½¨.Ÿaß>S) ãEt1"—¹áâß™WN‘"ð{YšnÒo±æL¾ÁE]„4ÃØ‰…ÀMQoY ¿bM{òéœëñ3Ìûøý`—ë՚ſëR"uœÔº™åÌ!& ÍD6Ò88æj=c3-Ô=es)Ô>±Y²íŠï®ò¬cEÊ$û â½Yï©õæµhk'Á¶9PÑ,ÌDFvXTÌrS•Ö0+,Ü2QtÈ˶ûézÊ¿âœrgFß×îà(œ…¼OçE¸ #Ý1]<„òEñ(ÊÝ;ˆ‡¤øÿ²v;:?IÁF¸ó…çamOõ²ã<ç•»ø“ŽêÜÉàôIÍʉ“?²°è.¹Ó­0V87}šŽÀâ¹˜èø‘2vÆì9wg½mzËl˜»ŸGÓÓäÞ€X=DׂD‡¬ªú1ßFP¨Û`CÊG¨&ý`dJ‘Õðß"ßôÈóÛŸ}(/6ç·OYS Îk7ˆ Í~èñ<¸Rø[㟘÷W=h§ëi·—‚=]Ó¸Mâ·œ¨áÚ§!i'l^šÄ~Ipkvn2¼,qÅöŒd·qe©¶3±gá›:¾á®2fuNÖNêþIŸêµø#@˜>É?ÜŠ~lY§Ÿ˜w*¤‹"Ü…<œ·2x1~þZÎ!´Åp §³ÏÀAycçtÔ ë¦ÎÜ©œãŠ/ÑpmM»<ä“ðgðY/ÞïäÔ‚'<()wYBÐq A‹Çqe½i†ñæúú N­‡Š SÚ½8+Ͱ€é™aèé¦dx, ©™ŸÄAI#û%~Ýlƒwq~aÓkQ´‡³Ôß±œ1 Æ…Ñû)ß)ª­G7Š3~‚p߀Ԓí,Í]²ÅÒ\x–Ï ¸Â1Úa¨-æ'â{Këö_žGF§x‰.(ïEt ”vÄÌ=xÙ?•žÏrîÆ‘³xÃë”é‘-Q6jûmIÛo˜¶=gwÒöú¦|[$;1xæ—¶Ñqcãur;©æs†QžºSkî2X½°zãaåfÚÑɰ^3ÀÑéÐí‰HÍöD”nžØñ.Q«ÊÔª´3&â]ÁjbJvét¸õO¡LÇï³ûÇQlçYÌïUã{Ó‡—KŠoöÐvˆq¡ ¯K»$ááWÜ BnbÖÖŠ¸)cÚ¸«Å6™ ’$Öà ch<¡>»~ívܼ+ÃueâÖëJmì'–¬\”ǞܖØd‹~¬¦Å {ð3¸—\wyÝ$¶ùâ´çÆÿ‡W¡ŒNúe±]‡µty¿¡GƒÙË«ôNË?óñ[uñ5–»¯µ‡¾ð&¢¨CФ´²ñ/ Ò›#&^ýÉA®>8Á®+ø°6ʽ¨q|‰“í}⻕ckŸ½„pxº ]Ó“™Á€XÚzé~pSÔ:àÆ„X}Rà÷OÝ£ ÄHÛGÝâS¡ÁíÞzÖÃ6«‰&K°-㞦 ¾÷›:¾¸ùWì]¿pX1P,íÝOlŠ\Vׯ/êøšéÖn5âG…¬/Tʶµý‹šGϦWzÎrÇAÎ'…°) EhÓ&·dåe|Nv¦»ðÞ‘Tn =éÖ‰±ç?óVÌ L†ÍcbÙ'lï„dcvkÇ´î™qOÏ]TC»·ÙNùI«óÇVKþ*iœzîÈbŸ€Øû,b0¾2a3j²Í} pã½°+dmgoëðß@úvendstream endobj 418 0 obj 3394 endobj 422 0 obj <> stream xœ­Vmk7þ~ôG,þ-t·z¡Ph -%¥î•Rš~pür ÔgÇg7î¿ïÌH#iïÎMÅxoWÍ<óÌ£‘ÞrVƒÄ¿ò{~½úê4 ›ÝJ›Õû•¢É¡üœ_Ï×``ŒÌI&5¬¯Vy¥‚‚±³ÔÃúzõ‡ð£ó¨…‚_MïS”j–ʉ—£/ÆI‹W0O/§ã¤Ä·ðõã8£Å¯ðº'+¾ÇYTsJѦüM3¿ƒ¥0lÄ/ãäa Û<-84by-~Bã6Ù¼–àŸ7uU“Ê(þ“ÔIGÚY÷ÂA Š”ö“Ì&«[øŽXÔ^Tçõ ñÑIÇ/˜)U%¤lÝ(Ûºâ¼*Ú;Õ»AÒ FY…pC ʲ„(5K1gXY¼hÕ/•uâKâ³`X „ÕEU=رS“·ä.ïÃèm¥˜»mSÙË¥Ì<½§µ—¿¡¡7¨,ÏÛ"§=~×H29¸e’J5<5QµèWÚŒOË^ÄÂçÍa+‡má)pSÐe–—V³¶µ3µpSxÍ>IJW âp†*€,ðNò¹a?Õˆ\¢¶õI½­GZäTRYv¤…((@Ì$Ü6ApnІû.Òõ%Ÿ†yôŠŽ™v^RO;.¦P,TO 6DWÙ›¦á“|r ÿw©ª8i°«:­Û 3³ ;hZqx˜žj?Dp Ã&/,†.ŸkØ^mÁX%ÒWƒe%åY=yš Zo©ûº]=¼£–ô¿cXˆ¨É_×rÜÒ§ª¨$sµKäêPaÊáŠÜ,JR´µ£ûâÁNÈz[ªÓøv:R8Ia vdãØÃ^y Ÿöe‚i`²#=QdƒÌ$¸×0¾†r.}öUkË¥ÕÆþÒ ûÚÀ•ÎÈ­ì×ïÇ5>Nññ[HŸ/ññZà÷íŒfˆTà†­‘0êÓ˜­O5:ÃÇcñÐw»¼ðCÜÕAô‘bõÁ¼VËÇžÆFnÛà¦^öXyºRâžGæ,\/ãÁm e€ÆäÌîzh&Ïn²,'“éüß28ô¶®Þô=†'V—XÏ)v ãó½7Ú{ïN&>ŒÊàý±5ÝàÃ1‚_=­/Ö«Ÿáï_ õhendstream endobj 423 0 obj 1209 endobj 427 0 obj <> stream xœUP;O1 Þó+2ÚCBlçqi)×À‚˜ŠètCÅÿ—pŽkäÁÎ÷²•“ žlèµôÃd®Æbß&Ø£9šI»´Ãd7MÄŠø*Ùöe~d Û"Ѷm2ïP0AÆôÑÔ!ôÏ‘«ƒšÚ§ ·è"Ü!ùZ‡XážÑ1´ŽïЉpðbϯ sUR-gÍ JÖQ"¼!‘¢CúÃ>jôvIeÕ:‰Ü÷¹3íÂŒ}iœáVSDGÑI³Y_sа^#°G—»œá ‰ 6(º4×~ö,Ë O«{¶¼\2¡©I#Jáþ…»f^´~ÓiVÉendstream endobj 428 0 obj 250 endobj 432 0 obj <> stream xœµ[[o·î³¤á¼ùœ"Zó¾Ü>:mP Ò$*ú¨-Ëv[’#;Nþ}97r¸—£ãÄEÑXÚå’Ãá73ßÌPovf°;ÿã/_Ÿ=üfܽ¸;3»goÎ,¾Üñ?—¯w.Ê€¼sfHÉ¥ÝÅó3úÐîF·KÎ ÓîâõÙwûÏçv0)ä¼y8wƒsÖûý“ƒLŽ)y»¿åǓۿ=Ø!¸)Mû«òÓäM÷?Îý8®L0Â\Þgëþ}ñ7Z> c-,ãü”w?»øãwû œuœ‚+ëš!dkL[&+²•Q0ïÒè÷_”6ÒþqP~.e‚"·4A VÞ'ïö_Á\v°Q?„¸{øøËÝÛß]=ü×Ξ=ü+üçÑ?>/ÿ<þóîwgy¼ûzd½¸‚²rœƒO°Ìà iß@ ùzŒE×Ql‹b1ÿïâP³÷èTD,°)õæýóräç ”]~¿†q—eO0öxS¾)Að)'|tÍŸ—£úÎï‹CÁø”3âÙÑ™~ ó<ø•7_Áñ\ò^¡Ên~,ï *#qîg„…Ç’/k——IIFü¾z'èñ±Ìå÷¯•$Îíƒp„(»)/3,"€í=‡_|_Àèbš?£é—Ô³ËúSYVG,÷ýÞ¨DšÝų¢÷kR­sû²hÀsP:…_QOÛ¬/™¹¬ü‚Fëö¿ˆ€°è¹/ækÂîÜú!FðK°8ªì§¡ô¼+>Áw·õ?¯´& ,êñS™Û¦ýÊ£÷—‹œ‘°€³üŠPd1u~2ŠŒÅ÷‡B°ÄÉ@;0öD(CÆ´00úP bpT¿lNU¡ ä~ˆ¼ƒ)s]ÝšÎ.hæ'xŠn*¿+Ç(°gù;Ä Ä÷ oa¨>@Xái…Â+R4®Û¢à` ¶«Û:ˆó3ºùâÚ†-L;ñ`Dnžá ܤ÷¡Yj“˜¡‡p’í#žÐ_‹^ÃQÃv^”ÿó)¸ýPfr —ü°!žæ¥˜sÙ•K QŸ³¸@®†Õõ€õÆo øÝÑdñ¬á[˜î™¸Dà ˜QM.Á'‚~ÊŽœíÓ¬WðbBïG"©¸z›4”‡š+2Ážª¡¹Hši~^ÀþßU(¨Éš¯©b¨z¿ÂÌDc舴 ŸR½ Ž‡]¡¾U9u Øs‰ójšD9 L˜"E¤ˆ:>.ùà`S»ä$ªÊÁÁ3Ž7~iØíàC J©«Õ-vfzv‘œâ ðýg`–^>aª»vìhåØnQUçö}6¸Lø6dª¾= ûž&·Ä| ã®eÍ.¼Ñë<ò)cø).ªDÁÛæ„dUGøÊiÅû§ÎùûœpGÏ›0*"¶Í7àê(YÃ(¡½|9ƒ')&“•ÞÑÂãöE™Š ï»÷XO%ŽàÖ)˜““|rä5ò…TÆ«&*z£¬‰ÎCÀõRž@T<³q_JðŠHb”ÞûÊÈÊ£Ì*™Ÿ›‹ý )MŠàÄh`SÚMÌ=ªÑ»6! ð¡‚qÕ9°Ê7¾«’6,ar@Kp‰€Ó=[ÖFªn³;ߪÓz˜J!“ŠŠÊ$Á+ ñaÂÙúƸ2ûš õk†i ‡˜Ð£ÜYH0ã1£!4%2µšñGÀnGÑ7àŒjûLª‹mëDJ\a"Àä¥j_j­Ù³Š9VC}i2Ed¤ÝÎ ã±^C?Ø„Öð–á5«9¢¡5×I©h]ž3è-t€aQlðÊ;õ±°sÀÛG,¿&åj¸RSEùD!s|¾xÍž!Ϫ¼½‹|ÀŠÍ¸noÞV{s¡¼ÿÕœˆ¤é  ™Êl15î¶}ËŽ²h¸Æœ‹B5®‚ަ ùÈÒ±ñš'pjÙQ€I4nÛ¤–Yž˜‰ç—ãH[Ñ2à‘[Û‡nã§kƒ÷6§¡g¿1pò¨ºõXù-½xÆRštÜ­Á'=íGmÌÜŒ*÷0‚L‘ñy}€Œ’  ãTkXòÓK˜îƒ§µßàùåÁóÌ`å6÷déf+³TÌñÄ”MA«~ú„£5M<÷§ÁÚuêvŠ«rK‡K5„<¸ ¨Üô¿¼çµ¢EŸ2©¨aëliÿ¨~·VâxÂg×2 Ü”%t3o…=óaªC^ÝÕ¤ƒ—_ËfÈã÷ÈÃ\óF±‰‚ úOá¥d‡t0%¹œDzè°d²ºô… ø¼æ°ËrBÍ5å°ž´©”‹Áƒ{z˜%FBªEK“Õu‡M´t¹#{"ÝØgsÜfñCöö„fŠ¢ms|Eªˆ¹î½J;¡Õ0ùqÀ-ÇØCg‰ÅMæ üÓGòš 7Ú~w%½æ4 §VìòH¦J!µÀÔSŸªÿ¿'HúsÂIè9ÐqÊâœN°S@dç±²æ©Ú˜äëᘖ.|1ßÝ–˜غ;-dâp…ì òžHg‹f›ëVg\ö_†0”>T6Ãg µA‹rèZ½ƒM¹ä%3'·È¼ÖÃ:ž¦[ëRˆcN‡;î]YÍ63Ñ´>ñnûÔp‘6ÿ&/Õ¤ŠSCŠ®³´‘QÚ%WAX|™ÿ˜ÓT¸Ñ.¯)}8 ½Ùi¨-Ÿ/ÌtƆVX¬{ÿ…jAÂ.j±šI„® w˜Y; »#.ÞiNWrgŠÚÄêT ¥2Ò쀾Ú1ÓXÉÀœ?5û’²b ªÍ ÅåÄAØÿž «ò§ƒ‡‘t|C«$Cè_•Ç#ÿ É54:Q#µÎï Y·)³-ÇqïiåP¬‰Þ•É“±DŒéË~Œ–ŽÞJ®j'!íªthQÛ§dZ€pÈ­;ÀÇSJÐòåªs— {Q㿟èZÊ£Ž£ƒ7hˆ0ø!T¼©m,¸Hs·]CÐpY¶õÏCWF^æÝ•ÔlBÕŽ<ÍJRMæ¸ãÞ×nZ1W¹h] Üt4Õòѧa/«… qš®z7¶öÅO‡t‘…ê½úìˆ| ÌÙ<×4@,ÉÇqµ>S}~}Qå¯ý“µ@ê=•—NkµJ`¿† #°¨@õãmˆs²lr„÷ àªGÚ#c/šÕo‹IÑp»sR…øä~ôÿéÀ·I¬5ºsî 7œwçàˆí4‘~þ@ÅíE›ßÐÖ" (Â> E©ŽÔ¾—П1"&*ŽU@­%&u•Q6¦¾qwEkÕòÞ‚v¦‰„zX^Ô~Lܨ yîT-aÊkÜßžA&ºìÕIy´GšÊTJ ”ó³O±r´41Í_a‘ڸǚlÅýEl^ãìeßù'Óž¡¨ë¨‘`€ó¾œ¹Žûé=—jN,òjO¤^^Ôb-ž®ŠŽêÁ¹@M47‹lÆ8â­ŽHJüþ¿õè¥ñò–-¯ª(³TÞNýa 8š‹ÕÌ”üb…ï뺞rR½G¡žG× ¡tÉSQULhØ2Y1Ãó¢ 7N㯱Y7…Z¢TBw-ðO²3O°YÏ Ô=$žf¿êÝ!Ü W*–q±£J}{…$£,¸¦öÎO,kÑk­vÞZ¥cWD¬ê©×jgî]§ÊwPýs€RˆITïwÓV½ß!1·œmñhgži®•ö¹6ê{ºãØY(ÜÁEÏNÊëØ(¡€#@‹a.£[˜k oq:²øZ„<ÈØ•“Mf­ùøÎ±?Èq¥^æŠSÿ„Ì…ˆ;?L(uKÌn{ôI•·7¹Vˆ%Jl‹žæïâ2\JŽ5Ë*K¤JU“RB}˜–T…«ëTEŸæå’_UøÀ Ù‚C犵ÀJÝZ;!kÉsÙ9Ö–zîxÌÌþf…Œ§ h;øVêmaí>æz5©ÒÞI¬ ƒ¹Ê*Þ"^íK󓪕Hk'ºÓ³ltw†N©)Ek%(ÞÕŸŒ\pj”r&'™Æ¬Ú]‘UÉÐ"ÆFKao+·Ç½j`(¨Ó³2à«o?~Ú†÷ØÓ}§-ôà>{'Ø’o.Õsá~V,­W6SóÀoöbœ™—m´Ç¢ÂFÖÀ™µyæT«¿%ÔŠóµÖ8»-) É]\ìg¤fM ÚOk2-¡Ìèn(ë²Í*:9|(è«[ózÿ½».G"¿:’µÅ܉¹á–ªF,r_ŽÜ¼‰8»ô±Ãé—ì¨~ ot­¸gûnZ +Êvè3~µª}`­Rqe»ó³}oZM Û_}PÕÞ®ª¶å¤ ×’ÎôåÔTËVø×Ó*K•[ IY°Üo%öã7Ž>Î…ŽzG}Ý/Šqrz²rwJE§3F.îOÙ³…Ê·õ¢wš— jZ1[8¥×ŽŠ¸sßåuÌ®ª§©±ÑGãû„i®U:ЦÆÍúwuýŠ¡Áµõê˾·j›ÛSµÉ͢º;,žšòÓ<ä ï|ËÝæH3vÍ[·¥çx¼>‰EÌeñ±~½yMG×>>³#"}ŒÓ¬*©ÿh+´#qiɤ[s±FŸ¾i§ a¤Påµû~GÙ€ŸW*kŸ:Ö>uP ´B®†¾æ»VmdY?¨Ëçüvù°&ÏwÕ12r8qðî¾k?ØB ‰J`râqœ9*@¨#¿“üÊ)Ë\kžÜŠõú9ó_½=ûLáv¥ì S¼8´vÿf µÏKQ§\·-9óÉWm]¶5WÇôŠ\œËÓ"c ¸bÍÖ#\`¢‚9…âäŠ${cqÄÑIo+9 ³'ð#ñÄkòqyPÝA&uP·bÂE‘åM#—¾`î2Ýùéîs‰ÉGE声Š“M*vu¿µ>OEzû j×Õ<Ôu‡Í"5®ÑÉw_¿Wá芶(w¹ZXTWåß¾r·Ñ#Ô¦¸+&ꂉ…mƒ¯n,ÓŽ5ño;¿>û™¤œendstream endobj 433 0 obj 4033 endobj 437 0 obj <> stream xœ½XYoÛFî3‘Á·EEsOrѧ:µmÇ úôA–l9h|ÄŽ›º¿¾sì,w%¹…´b‰{ÌñÍÌ7C}¬ûNÕ=þ‹ŸËËjïÍP¯ïª¾^W+E›uüX^Öûs8 4¬t¡ªžŸW|SÕƒ®c»^×óËê]3´®[÷ÛüG¸aTqct…;óœ{ÑÎló²U]£ Íw­n^·3ÝÌqý ÉÆ›vfŒêú~ Ñìh`“ONø`še¶wFß%¹'íŒåÎ+¸£àa é-Hœ­N+4¡Ç J`çÊÇÁ‘@8 ¬'1ñZfîakàÓÛ¼ç~iÙ®x%ÓDš_M[p’3†%ê3qfúnP!0–ïAö[è‘%ýw(÷SkšÛvæš{t}ÙZZ¡Z>ÃóŽÎãæ5@|Õj.:¾¼€”…Wä ZÚÍ…åšøPŒ'|0“ƒ7h³¬­Uý´qÖ»éùµ±md]¢?‹Ö œ ÍÄ‘‹ôž  Õ7+w“P|ø ³¥ áÖ#`g•$éçVìµñû`TÆÏ« a^FÑ”÷c˜qÃ8²&ð,!瘉!X3NV\Âé¾äECm£(C £u&ðŽsßkŽeLÙ…hÌ0hÄb&`Ì”éœÇGLІdìÑéÌqÉ ”·äª@2Rü–ƒîÂî 5}À¼³‚"ÙnÜHSä!£ô˜ðdõ˜ç1N×d.¬õÓžÃÿ(ʇ29=»»#!èÏ{'–Õ@é‘i»` d¨‚®³„ƒCy±] CŸ Äõ&Å‹Tð"êj›¢Ï‘2D‚ð#>ˆ3[ Ç!€»™ (j%‚d&нEþ Á)Fæ’KÈ2I¼¤Lradg³à )ÏðùCËy ]Ê—[<ÂéÑÃŒÀ@ dÖÒåB`v9âOE&ù˜bl€¶‹.¸8Aðº%[JTáÁ˜¤KÕ] ?zÌ¿lMdEd«)!ŠT³^œÙˆô(ƒÈB?¤Z…’‡òü©šýŽ;\Ò.Ð¥X[6cùÅ KEMýÝÐî¢=cH…Õ“ÐUQ¹xnÍ’µ»}Ѓâ[ ¹?Z¤oeP ç݉·øý¯$yWˆ€á(;@^f6fk –X*.k‰‚y1Qú"D,)ÓäcuZº3¦šu~«´-ò¼Ú(¼Ý(R‡œú”ŽíqÖ{E‹š²6£ŒÇÙ:&>Flâü(Ù…ŠÖ Xg7fNN*AK-&éEÖã#.*3·N¦Î“t3ÍŸÖ•Y³ÑÊfr]d:S=»X2=â¾ y1Å1è³¹ 0eb÷¿˜“ƒ>Ž%½*Ÿ?(@ngßùGú/†Œ¨'¥ôfõË´§RF¢›‚é'W6˜>u¹JäKŽãéÑ4Ï)+ˆ¶ÂˆhÿËØjõŽbJº’1® ª‰íf& gÜxPéax,ž^.ŠQEø©gä/’߃}Ös zb˜5³ªúBVžÆbÓ²Ms§,æM†I; O½LÒÈZŽýûÈ ÐP}š3Á[¹!nJŸ&­|,DáÃ^‘¿€#ÞrÀä]bƒ$žÇ‰!ûVöä-mK9ñ æ>OÚEÍid+)°ƒRÉÄè§À£ óê¸úXÓyúÍ<k5Â@T. ?——ÕþQµwôsýéöþ¬ÚûµVÕÞKü³ÿú|}_UÕÇOüyDÁ¬¤-ªéÿB² Ÿ1¸sw&î£ökQÿ÷ök¨pØÉì?åÞÈCýñ±h=ÁŸóÿðF¨¡ðgÉctrGñT÷'¾iÆ®,„x“¿pS’öÖÍ~ÝÏH> stream xœµZYs·~g©*aß4“òŽçyK\vÙ)Çq$úÉʃDÊ”Ê")’åüúô3³¥8å2µ»ƒÁÑýõ×~:Ì“9Ìø_ù÷âúìÓGËáê—³ùpuöÓ™¡‡‡òÏÅõáoç0 ì<Åhãáü‡3~Ñ{ˆÖNùp~}öýðÙx4Ó}JËñh'ksÃÓqžæbtfx]~Îvøu4“·9æá9|ÊnŽËðóxtË2Y˜ á\Î%cÿ}þw^ÞOKZ .Âä]N‡ó¯ÏÎÿüýð9κÌÉ-Ã;üèc=-`Sv0ÿŽºÌ./à lƧ9†8\ÒGc|îF\â,íá aÒl}^â¼1Ís^µÏyl†)¾Á_ÍìR„£BNf¸¦_sò¦·=üÞ¶{3Ú<»ä¶ñ2QJVÎ5Û(â0~r>ZGt8Ÿq$x?,ÞøaíŒqy00•±ËýðOƒkÊ]Dœ,I~NR½VÑã$x8…¸ DØj·ÎS…IÊ´ÍW£hgº]b˜tú-0iHP»æp í@ O 3kã2qr&çÃÑ‚F—¼°Xþ4îZ"~ÄÁ1'̱ˆ@ŒÒ{6Ê‹²W8ŒÇNò 2Xâôê#4¤¿V±| êüÕ‰ {¤%ÐØ põôj¬âñÑÓ”Í$qüÅÈÀËø“¬ªR~°Dy¨I3Zz³çrþò3¿çGCðÄ0¿Ê*¥‚5Í,ظ݀Êv^¬,…ûÙ3’*bæ òOÜM(cöV©Ó²M•½öFõ&—!¢wò:¢â!Loâ j%Þ~Iø/dõ G‰rFW£8mbM¶ð*k¾)Ü(“½Ñœ¯$‡äç1ÅF«XYæAZ”'ÆýÐZ[ Pf‰ä·~eè ½v촎Ūø}r¢KhÂØD~ 3w;j9?$Ž«XoÉtê>œÌ,9!~Å—•ØC|†ž~ö"µêÌ´Ý:hÿR°T(¡.a5~õÌC—-¦T9„å)¬¯k¼ÙžªYã—bÀŸ0ÝÔ³·xå7|âèɳÎöÁrÛÛ[lR/¨0V¢Ì§Æ»x–]XEˆ¤Wû±>±C>¡2^ÛWªw…Î:u´¦u‡´NPwj¾ÂðZœ7ÍÕ© ûÎàGi¤8±5„nû³vˆ*^ãÉÏøƒœ£:GEÿšùߢtqDM\Uºñ”2ˆªú{„"Âìw‡Çòît"{8JFp´fò˜>l¨”Ã#· (D½™Rl¦ó2 jf×2‡B¶±es$³Jd%›Ð%$F" IŒìPy›4¥‡Om¸ëÐQ‰ïvì2Þƒ¢ØÕ3<²É”½œˆ?;ßO ?‹7“©)ý.{v!X `O ½ˆU Eߎ)°åÒ"ï/GÒ'MÌùôðÙW§Ü2tÞ|oH؈!rÁ\’ÿœ—R \Ú©Þ«ØŒM5È{ÅQ®½'„©üõ?@˜Í*m Œ&ŽúT˜;Eƒ‘Ï„jjE K¢~,ˆ*>~• Õ²R%ŸSË+aÓ/;œµîª)êUq*vVÁ¾œ~W°×ºÁ ïyªèÞñ*ÈPˆ?©z*GÀýäeí¾æ­sdJóÖíiÞš-ÓXËRÓ’”ßîI Ö-:ó²[¾ÐQ@ ' æøPËš vÂóò^‰DCqLá„󮸂2±–à™¨ý¶)êÎõéZîYü}ïÖŸëçéh=¾É?_Œ\èLŠí^vY.´g¬W£f|¦í^ciŠðX¹T”‰qW±2eÛÝ^Ž¬Ê”tÞžu<†¡˜MœÓ?…ßm)ª­rBÈ~ÅÌ5\]kmÈ”» {öi¥ ýÉPuªjS{ï]ì2÷¨Ž¼ò= .–*{Ë–Ÿìb4®u¡¶™T¡Û&K²ÒÉp±å"Ù¥ev:‘Uõ8)¥-Ä)ÒXåÄWüTbÌ=DpѱlË«²z1a²©§2ßÉiBhèÊ(k¼mjŒò­ÂeüGR¡ô­´œïlœ wµ¢*(Ÿÿ”&Çëæ~$[ržF}§ré‚¥w%a¿úY þQ…úmƒÕ’?oß)³¢z:½*ÊŽJsù>>œS­F®ì¬S(ÿ%U”†‰‹ts·îNjï†ÇÎßÇÅ9$Y•o :ªÇ.ñÜý±PZnZ˜ë‡ÂZ¿«mV²©Ø½Ð·ˆÓUZq¦µ(öhoc‚#š­Q\ÀýCI‚¹Hó4Æä¦ñ¶ÏAÅÉu1=ö´@í¼¯VVy[ib'¿E…ÌùNŽ¡¢ˆáYU!˜]§à®!ð4äæ4ù?(¼Ê¶8¿Àõ‹RT´™37ï(ÕÖBêšPnÞËù×ëÆ`ÛeéM¸yU«¤6NU1ø@µ‹é›)XØRž¬-#1’õ‚´_ê ¨þȱÙãÌL¶ïàÛu•X뺉ü°ìÊ,’"PUþd ¨HÝt_ÖKWñ•aö¥…Š8ÚÎÝÓfºâ¼T_èÔÓB R­ó™t^ãÔ2¨lÛE•θGe²ÀåÜMÁfjZ©×,Ü«¸O½&r;SwõCÓNC£ËøjìÔõ3jÙtäA`v'¤9 r gJ©RÚ\o¡H“¿«é–Š·ÊOï.ÉÝHá>0Àº‚0­Ón‡i¯¦÷t õ¶‰ÀèUi…^(Ø(©^fÓW2J:u¥»8Ñþ/å¸ó19>ãšc]k¨j²¯<Á ¢SÅf”U°6In¶raÆvlw±ÃxÅ’S«á`©®U;è^Ò¹ ŽÄŒbÛÕ`â¦iD%ØZÃÌj­=9¶p·wxˆžÍé)Jc^Zc—4q/èÓü;!áÃïÀÌ|U #M›e(Ÿ5nÙ¦@R»{\'® ×ò¤6àè0kS)ü¦SbðVÁ×+¹6}cáYÏÁh0›^&%mšcƒbAÕõ­ïVñõ,}ÁJ{jÚ…M (©Ý­…©ôñ¶äcn¬¸oô’Ÿ6¨7‚I:»ŠA\û÷Uý$Ò|ën`yW£Eë­’ øJY²ÞÌ×›tñ$8¢w)Á¼Y‘û¶üѦfÎçÞvåTCäáXÜú#ìÞßðþ&Æ2ÒQÕŠÚª«j”`rÕþÕw¿æ¸NUO–DÅ¿îEh=ÞRÜNàvj´ù®l¯¢…ÊTȵ'[Ý«ÄýYa$0$WÝ€ê«@\à_ÇVFŠÃ{_H ݶ6ÊŠoKñD{@™ãŽú(?|œ ür¬ÙPWÓÚnÙֲ[u…}aퟜõ±é†Dÿ·=enk`%j‹­P‰Q8;®¯Bpkip»Dⵋ™ÇØÙ9Œ?§®•Tfk…è Mí{Còž~ÕãíIEÁ¢‹2…¬(éò{µ5èM·òâP]_½{R)ª ö³8´zá>í[iŠ}ÃÀoµ²E~w\•“œ"s¸qŸëhs½öµ×ÿ/ý¢ª÷r%¥4$jœ»áNµl«»¶ë0Öb°Ì“‹]_Gì,ç÷‡ýt¯Ü§¹éÔˆd&å‘ç;• ´ÔœV©ì{: ;•â> ³lq±¹> stream xœå\[oDZ~Œœ¿À7ïÚõôenò;6’ qr¶P¤D)IYÔÅʯO×µ«{z–”c=ajw¦ï]õÕWÕÕûÃIp'=üÇÿž]ÞûäÁtrqs¯?¹¸÷Ã=‡/OøŸ³Ë“ϦΧ'‡¥_ÜÉÃ'÷¨¦;™üÉâ¡÷'/ï}³›»a×wÃwŸjgkø>–1Uzxž ~Þíãî·;,Ë—ݯ;¿ûs·÷»‡ðü‹n//tûÜ¡ï'lûÞx¿¤—¶Ð×ÚŽT÷»¯R‹¿éøËoR+~HeâîË.¤ÖBˆ»ßÁ›?ÀŸT&DXæ«Á`þ¨Å¾ ,˸ûK·ÓSïwë|ú0x‡vsÄZ_wž¦^.Öžç¾ýarËBK€c}ššÜ=NŸÆe÷<µpš&ùª øÿã4ü—éÕó »>N .Å“4&|-Å_C3©ì€OoRÉyÜ=Kí]I¥y÷Ê@,÷ 'è–:K•° t;§jŽjœÃ»slj÷¦ ^†6ìÞAÁ!ŒÐ~Àá»ë.Ìð,ìÞv~N ;˜*0xêš»LÍ:lá\F¨ƒ;¥>_Ðô`mC?æÙ‰]§ý›qüRÑy^K"c˜pP_v ,,U6Dè+šŠ?BÅÔ ­çeê™Göb£§û„`{ž*Š×°Ì4cØl•˜L°wÀ#¿,(tðŸ‹ô±akØÌµ Œv&è:…n.ÑJºüBÊ\)ü‘¹¦*A %µ^H§²LŒ¹m™LºŠþÈÌ^a¸ï =׈.°®~ž’ÚŠ1„  »^–„f:(lÑP_ë$ ñ9 F*Ÿ¥(ŒØ"Š®­Y挗Y6ÞBõ>½ö8#;"³Ô‚š×(Y¼%p}$Æjýwßî’¬î~OÛ¾½Ç—FµÂß;š0¾DÊ‹ï'·ûšÚ»º<•°,û¿xEBØ:À™$?Ë‚Àõ¡/ø4,òH¶4—AÄI+¬Bh’‡€/“¾¯àe+½Ü"µ²›ßv©½Ù£$טnd#ö´¸§yh—0°9:³ÇÏW¶±) Æ2]p#íÂÉ Ü— ” ¸$1ãÕ(Ìî{E<ýQ­K<Á³ –'NÃ…ŠçÝg©>àДiMN ©P:n_–F{™ /‚f˜;  üßæ&·û„þµ¯hÓGâØÃ ZÁ©Æ],$ Ø4%•ù*Uƒ»»’žÌ¸ø4ý>K²ôÔ@Mz Û_s¶ XI‹ÒãÇÁ©?j\ïž‚á¼eP¹ocsC°˜${´P%ıyFîBɘ[äØÚÁ° æÝdd@Ht_ ØAy8ž-pèì¸`b öFÑà2%YÝH½2´*ë×I*] ÕϤ_Ú3ê: ÿ¦ÍˆqF˜9S‹é,ç,ÑFöÑsð°³ïшf¦-Z›7ÑÈèUkga,~B'ˆ7#:æï£ Ü+d!z^cm+ÓØ"îã±¹G½â{j2]MÆÄ»sj»ªA.ª÷Ñ ¸»Ålˆ¢Ô k…aåP@EØ¡ €NÙ”Š êû4ÁpmR[D¨p³®ì7uÏÀ€RTÃ|z̾¶H¿2#4L|>’¿‰h‘™Ø›n |8]ÉPÁÑ“h§/±ÜšÁȇìJÓ´ÌñßÕdŠÆ€u¡Ê†Ù˜¢~ˆÂX«ÐSÏLÛÚ'Û|¨ÉÏXŸJ—Äq\p‘Ï %W¡Î‹Q%P÷ XºfS+/±fÙÚ³vè¶ÑìAÍ‹Ùÿ=DÜq #¹e-…>äJeV®®6.lMdÉÆš•eÒ¦-?©Vø´5ÔæÇÆ„¦ù¢t<€ bŠ›µLMo=M {v~F]Çë¤êwØŽDQh¹O¾"lÍÓF_­ 'Ë-II]N­¼…QýKÖ|&½¥›dܰÓ#’t#qüQ¼ÈЬ( ÿ\n’§þ76IaƆ2[±Ê vßԜũžbIäÏÀ¢™£P(‚rŽ¡—!/E%Z!á1s<™{Œë±fÑÁɪ…yŽ{^Eí­lŠU ðΈk§wÕÉÑÇOõ`ÄõåÉHòl’`œ$Ÿé”™ü!Ź8tJáø„çù1ˆÊÀ®A€gðõ9IQús·ôv ÷’ C+­C›„+óÜ«)ÿ”xû*öÄ⫱ƒc1Ö*DÑGk³ÁHÛG«]Hr´Bt;*)¿i‰9«¸XÕVø ÄÑ“u@Ê6¸BUnUŽ’VñžŠ`°=›Æ¼î§\+üޱðßu3 7Íä°%€a1&ùs¯\åÈß3- q<¬‹…[¢—PÝ™~Œè5…6rj@?Äln9¸Hcn‡{JÎø3‚÷°µ’ÌÖIê±ÄOΤ…xÄzøL£ è‚Ñèïëð”\‘™º¾Ý×ÁTB5»vm¯'ÉÑ{h¨''gÁôž æ—`ƒù#.þ¦ŠnœBY¼)GX3‹í856@ó$pÚepJJÙOSidö1žê’ÿOÕ˜ÉF!Ϋþ‹¬]ú ‡ÑɃÝáXj™qöZY¼8XäøŽW(œ\ 2 VËM NËcl¨g+(Wäìdhd¢i(/•ù‹®¯Sy*Ÿ"f^) àI1eÊ\ND+ú}5Ñð:¸®C×Vª×†¿ë>Œêþ<± |«ú‹$ª½‘OTî*¯÷+}x“ÂÉ&G$'ôþ»üþ¨wê†x°1Ftäq¸…ÃeV¥¾Öƒ@#“ëŠÌFާœ9†¾ô,—¥f³Ðæ,q䊸W Ã:‘Šô&F<(, Q¦:{vœÕX–hÙÊ‹ÈQ“â\¶¢ÔìKÒ¼êL¢—“æ²4ƒõq²Áñb½ ;æ2Ñ ©9¨ÙÄàïeÀø ËË9Å &çâ ñHøWEnùuU¿ÀŠ(°¿êè¬/€3Åÿ*¾"lFiv6§*³9ÙcÐ<ÚmV£÷™ûŽÔæ×]‘›òWM"‡·üñ—ã+pœÇR2sO‰·#ÖOŠnÁ!Üf„ÔM_EHÃlÝ£s³ïžø-7¦ö]Ê 97I¾âò©È]n ‹AQêú\WË N’#¼³[§Deìd¬Øûj­¸jeªZ¶ç®ŒÎç(é=MÁ†6ʉlFÄaŸ‰J™ó’ß{¹B;>-¨hhMòP£œP Ç•ðyËÆA(6§ ¸›èµÐ?K`ŽîÙS³Åßq‡~ʱ)d­TT3KÑVz©ŠOŽaü2} xx¢å…ö Ý'ú'Sä-a:ÓÂï”ó\¨§òDŠŸåÊÈ¡9í,E?ãf‰ð³7¹Ê'úðU=EgÔM‹A}¢ßè³Ç¹àó±¤åpäµå|ÒN“e_Ø–¥_èZÜ1üà("RøD|t À9_Ö£?_(…SÆFG¸mŒ˜çÅ`‘œŠÂì ®,éË»ÉÆÁc;J‘èØ™©NŒ¢C·AÉ Öd2PJ‚ZŽ© ÒØB+l¡.…ªã™Ío‘èÁZ|Yü-¾’s4ø]›Ñ&$±=´Ý²vÆCÛæÓŽR»ÎU²Úg(¸i̺žÁåmk/3›¶Øó¸Ñá«\0ÃÞ-ø¬UðF;<3Ó`SMhjãœU’$'GÉ­ÿëÊóÈ?@Uº“YÆ3æ7„ÃÇ/ÌíÔnMŒ¹¶|œs³‡#ámc“ÿ¿[ AÏÙ{|0ø/Uo–íݶøÖ‹î”qßœÇÏ™8Õ2R¥‰Iñ8¨h4ÌÇy6DUòÇçú³`ù¾êü>þ„(ö²¸K‹Щ`ËaÎÀ7eaX#z›ƒ*M¸êœþýÓ6Õà.þ“¹¦ÝŠ)˜cÎV0*£ “`£\`_ã=sÆ:Ÿ÷b+·˜ƒlˆì,7z@k•ÈJœ àä JIHq2¡R/§º:—JQ§¥s¼Æ ,¢ŽÁÚt(À»§dÔüÛò©’›å¿’ú­ˆ)d•ÓÓí7î`åC ’)¹âeäJkÉ-E0n;.…{áU¢¨Üÿ’ëLÜ·ÓH·Û8¾i\sÆK]%ðv‘/’8÷ãDëÕ6 rg«WêL¬£Éx1VâØõåòŽ.Î}¡s‚­{¤pµ3%79:&zQßå³g‘¾¼E<“屆–$=t1A ˆ‘±4YÆÏ´mÅ•wÆ‘ÕÏðå\U²Â11Bwf—Õ…d´}#?X¦Æ·ŒåëL±÷êtX#îróy›jÖ¿#ã§2£•nd àÈŽëWˆc+ ú¬!©.k/¾"“&#—R6mðö^»%ÀEµÚ™6ÅYì]ê¤tcwæFrN˜6Ä¥ì¯dÑ*”¬öJBÌ&Öž)Zéé¶aNxZ·ËUe6ò¦Ù¼æÚÉ;&ó}“hÞmë“€;æç|ЄðÍC~<Õðç—ðs@ÊÛï´éìÍ^”Ù3ª¤òðÛ>Íiš½yßéÓ;Ÿý}qö?„[Ïþ%ïtmA^Ô·ƒeÇò7×;οô±‰^£V"¥™CuÀ~Î×võG1Ì­ê¦÷@w„ÞS,ŠIÝÆMoGá4ùUã€Òo¨ÐÁaL¬T8s›Ž¦û{’‘‹Å¦!LØ/®á¦ãíD[?W·Cêß&îÚU¨ò÷ä·qŽÜß«" Ò“øî0d½… ˜7DŽ~0ç¶Ÿ˜ÀôËy“€?Kô{›¸øÙ«Û]䤨TJ±°G­Ík{6ÞÉS-å ~ºÈÞÖæƒ]¼q«I_U<`•ñWŸÒ×A‡ì Mš?¸q{„óNŠpI+Kñ>3“KÂÆ¼¦r•eÑmgy'¿‚ Âïýoúï_®*Tendstream endobj 448 0 obj 5056 endobj 452 0 obj <> stream xœí[Y“Å~—á¿°Ohk†®£/Â8#)ÀÂF‹Bð°‡ØU°{˯wefåQÝ5³‹ŒÃ†p(v4]U]GfV_æ|¿Ó¬ÝNÿòÿ§>ø¢ß9ºzÐì=øþÃÎüßÁéÎßvÓ€àRËzlF·³ûízÓíô~§qÝøÝÓ¯ò]¬—~áðÿU?ŒëqèŸ/ý¾´~ñ"u>Y®üâ‹¥kÆuãZlú š°ý«eüf÷ïi=çíz±í×Í–Ü=Ìˤ%ò@ר‘«›ußí¬BúÏ#½ñ'‡âé+ŒÉó>\®Ââ>náãÛô±nçoáñ>ÞÀÇš{©ã>®dðkxtðñ!|´òè¹Æ¥G¿Ç!èÑr»65{Iýj+N}m¤6~#ßJw´®ï×Cd¤©ÚhÝô‹óDå‹4ÉO]:y\œ-Wžt耟‹=èNSx~‹ÄG¤¿ë¥Ïãléõè mÀG à0$!0Ca òèPtàU\5í¤Mó÷½_ܤg •GÊÅžÒ‘Cˆigíâ(ý¥©b“ÓÔ—il?Ó©`/ASÑÚMÓÁþ˜¬éݘ¾¶ŽršwÞóy̱̑§‰HïU&ð*¼íà¦á†\À§#øt8k"Bš==Eá‘Éá{—„¥>±¸å>Ÿ©tÃà?%. ýO`žÈgó}³x‰-HüL„nq˜ÚºtGǸxµdö=â]uà„Ñ'K?g8œlD¹Á¾–! na?]M`Îír£Ç½N$õ£Y8j䨃Ã{´¯’{Ž3lr ·²äp¿0ÏEÞkç;+ËóN$]H,è¨:—¤â ´ÓåÑDñɇEñiÇΜdžТ¨ìéW”.5Å¥ã'èuxK*½UÙ ~@êOhcnUˆƒÜ;³“ò"Cç­êx¼G‚oYŸ,F]•³z^ùø_RãOàã…|{»ðñÜêY&Ïki<ÐÆsiL+Ç6 „ë’ùãÆ=™D²u#’ñ#PâXóÐï }”¯µñë…´¾ÔÖ÷¥Q¿%+“XOþ¬+½²#ç¯{õõ²vü‡ÜX33>™Œn0f&ºUÿë…7Y:ôFׇ„(ˆN¢+t² ªÙUìUí‡(Üã•qUTmAcJ`Î&3blÂ-tZ~>j©ðÿ÷”eÚC#w T[*ü‘Ú¾¾„P™À¯Ä¤ÄdÑuüâ)‰tä];$|Iô‚ýæ¯8 \ÛÀ' YOÞ‰£šËË7õ;PÀxØHNyÕ‰s©3"Wùæ' C‡t4ð"|Kµ\P×gÎÈqòaጽʈT·tM Mrm½cYÃÊc¶M.vÿÄ „]ä6í5¾Ç5qoƪåÏTM+ÇæÇDåAbhJè9Á¿Ô /·feâ†GËz{SoÅ[Zˆ$ß1’N>cÂÃú1ˆ*>Gb“?eD¼´Ø á±íÄAaYá?Q y!.„i|&IoFЛ¸­<´9Âeëbò[ÖwÌÛPAñÂùCð É"=\Bx±68OÞÊÞCX{DJÐQÎÙÃ3ѱX¶@¥®“enŒo‡"üÚu,aYØct¨ˆJF–š¤æÃεœ¦íÍ ‰R¸«À æ»=ѼëR1‰‡="—Íþ¨ãPî,Äi(üCBT8? ëR¶3t§%BVÇêA°æˆ^BŒÜ£†%7½)Îàw8ÎaCœH¦ê,ç±Ãz7Ê}(fCß4ż©¾„wÇÂéžÙ­W<¦›HN)xÆ «úž½¨¤~ƒÔ?´ñSiüX=¨¿ªßÒÖfÚꌸ>Q­³Îêô®æŒÝdš"2j·h²ìÀžÐÓÓÐNg5ŒÅ¶y0DO—¬S:ÙUÃòœWÐði Q8S´§n› £¨´åûèð£Xò‰~a£§ÍŠŸr,Œ„/M•5üI_ç08xRåÙÞ·¾jï=ŸÔ¼‰šç!ºª¡`x¸ W ÍÝã}«º0ÁÍovjlßÁÔ«r`ú}ëzRQ¨­?àz„¡ î oÄY¦>Žƒ£èšb¡YXV³ èï3ŒÒv¾ Àâ¾ðS®híq»»ƒ¬÷EÏ•b¤JÐ#¬mcÕ¾ÎCf‰ƒãÔ«fõîæ ;Ù H’ ñ <üx—瓼LŒp7+ðš}@(d.>ì”§u[Â@c莞‘· t¢:ªc&·6õEØ3Ž ÉA3à {¼Å}¶¥²«9¦Žù!oÙ¯;S˜2Ê>V j>³ñkæ°Ç&ô„èäîéäx<´ŸÀW‡_Y[f_S ÉÓ%z½‰ß@P,Ø%=ðà°òwK²÷^<„1+TA‰#=,Mò3 ’a¾ ÛÝœLÇUÁË’9ìÆÂA×pGX}&:)¢”|¼T äQYÍŒ¨¢Ïa[_ ,Ô –Ä„]™^WYTÒQ‘ó%ðÊ7_Ó[¡ã›™Ö*çKW3ˈêžs Û³×ÎÃK©UOÊè§­jÎêš|ÐÒL¡Ÿ“§ ·>Ðʱ?±R¿7|k_ßcöÎêPÔ#i|UÅ’>ÒVMƒèK€j¤1jã`ßáÆhr¯„ˆO¼ Þ&Dš€Ì½Ó9Œ ;‡«04[½¼»%ȱÜéê¥eP ^ÈU2“TR"“%úˆ^ XÓM÷”ÖÜ"êÌcHH [÷æx[’REË Ž}ÞÅ—æ»Ð÷nÈw3$E­PÁ°MñSX*»n£¡à‚V¬j©aÏì“"´áiÀá4ê\ç«м ö†ñÝäç¿Î·]÷­Üüªó˜¾xÙ¿b^øäÇŤæ-«˜[uœöÊs§+nƒ>T©^Ù•ëçXSh)„Înc[ú¤÷ €,tôR1åÁBOi³Â>¶”ñx¥Ý5Oцà¸h‘]óÝO„0ábˆnüåPYæV²mÿ“€«4טaîÔó]ìH¼ O¡²0l ä´Qi­Ž–ÂÝ€±À«e†1óÎJÍBR)3ÅÏø^ OÞ°{v­É”µ¯o×&ïY4“ñdLÑ'NËÏ®ÕÞ{òÅ&°OYåø;y•¬ô*w'v‰‡qa.æö°eapQµÓ^Ål3ØÑŽ€±9¬¡»ÛÆéѬÑ-‘ ¢YV»íÜîO*ˆ}iCê.Ïܸd#Ì­(ì-Z 3TÀ#$UëO·ÐÛäTµ€à´Cª_/ÎÎp}rX,.Ñ@׈;1dæKÂd),DÀÚô.çûè+©¨-ñ8ŠÃ"ài;EDÈ£: Ï A‰ ç¤f K|¯–¸·'ôS(–O®‰QùjìåÖ­oÂNR kºFC°o%ªº™Â’¯äCƒ±#Ò&+p yð­DiG›ñ45kcé¥àÆ+ÛRëûѼsT+Føa ס7Jm‡µÉ¯e ¶} ¯pÁ"™îI¬³ÎÕ<Ïi[ë@ÅòÀëÚ ×²à‘tÿ\‹QŸÈÜý¡ßºÙõ%ÜTý.C<šäYIdÎÄ»ŒrO*h±IU9šu¬¼LK%áh¥ºA^·ÌëaËf©É1b %k ‰][8WÆû-UÁn‹NK#- ?]ò%STŠ]â?¯´ë<‘±¸òš]ªŒð6<Ê©7é~ Ö&¢öÈÈ–׌TH9͸Ñц^ÍÐϦ|2Ãk=z0Ut†Œ…¨fðãlz±@E…È4óbÑ=R0'ñ>mq"¦äsÜû±©¹ð—àKV‚”ƒÖ¹!{¤ª¤îuÌ)ì‚-¨!üÈo̰R+˜Ìå Ñ•š¦Ìe#7.HJH$2y£A¸ü@cò¬T»ÉÍ¿_ùÈ^vë¨Ã ±—¦£,šÀÕLֶ䣌çC–ºäîä“‚lEÂÌ9å\‹ñ‰+ø¡9 j¦™L<ç„M^ä5ôÿî-ŒõQ)-³·¡"6hÉÙ¤ÿ¦hÛ¼˜’¼—´Ñhü`"Dí‡dSðh’õG„&n¬_[KÆ M1†:]`U!0&ìÀç‡!RsS‚’'T¬$³Þ:v&ÅÀÙÆìPÞ/æa…Ï!{\ù/’S`èÔÁ-[qd0Ç ZiK²»0 2ü6-‘út@ö™Ë~p¶ôùo¬z¶…ëRù¾­$ÚæÂkQ«,4EüµbD3kMÚËÔGYhÔ7åN²7K§¾;ÑPeB)ad‚*€{Ôôšï¦0r0Õ¡‚€V~JQÔNK!›ìO~…aøÏæ5+ É>Qj Høýýu‚yì¦ƒV;æÆ!V”Æ‘Ú{þž´ˆ¿6@¸«¼(Š^˜÷•@so @¦'$ïRz,jàÄãHñÉžBrgòâŠfi#Â,Éò{`ع 7IÌb( øe£ ì®nY@hé ý·¥ðhÆqOgû2¥ö·i§µ•M•ÏõÍEM÷0pAWœÑÝgvÏfâ ñ/)w&+Lݯù—–ø6ä÷r– Ó64üjy·¬(- 0ù¶Fµ½ÚÈ[†0ûzÿenüÒK´–ŽqçòG÷y&­Ë¬ý_J£þ*}*ÚªA ¢}.¢}S“X+§,’VLm ˶¢ìŸjÿciüR&:1»•5UòÖbh¼ Juëÿ¬²sC¡#sœYþäyí¬²ò† d&KOQtH»ÿÝk|]£Ô¾ÑsŕɅ°ÿ¿2¿—+s ó?ðæOÍä³+sR#ŠZ¾Ë +ó•¹´KsÿÅÚ<ô­%‹&&‹Ž­5 õE÷e&C-“~®C/l¦×p`²@ ”y²ûàŸéß¿5<ÿšendstream endobj 453 0 obj 4430 endobj 457 0 obj <> stream xœí\ÛrÜÆÍ3ãØ·,RZs0ð“cYŽ”²Yf*NÅ©Å{$riîR”þ>ÓÝÓ3=À`—’’ª<¤\¦vÀ\ºOŸ¾`f]4µZ4ð_ø÷äúàðU¿¸Ø4‹‹ƒ_^\„N®_ù”ö-õÐ jqt~@OªE¯½±u£G×_ºª]êªýÇÑŸüFÉ'tcë¡óúŸV+»|^©zœ–¨ôòeµÒË#hV­øÂ«jeŒª›¦Ç¾kEëÁ_”7ýûáÇõòßã7UøòïE·þ»ü¶2¾7cìò\ùþø{ŒÕõà| &ó}¼íÍ`ºåOÕªó­Z/ÿViÿ¡Õ 8ªœÅ§~®4-=Ö*¬}ešºWÃ@"À¹^ú.—gþ“íëFµË/àû[ßÕ™Ÿû¶2~Ò®ÕË~±Ë[?ç¿w¯>ñO fùµÿxìE³•@;­P©å•º¡©«ÆáÍ×¾+î¤U-½öí÷0ü–;ø!Ê5<£á«ëäðI‡^Úð˜í–‰m0üÚ?çüÖ,OÂ\·rŠ0.LOÎå˜ÛNý(-‰õ%&÷\T oãeÝ8ÅØ‚ÙýDrµ8di8Û¾ÍÁõ0ëuKÐ{¶wœ!éþ,>qSé@¥ý<+TÊZhÈsÿµ³pôº¹ó¾©U²GVb ìwb€'„±/z¥LÝv`€°öë ¬ÃµŽT‰ýmýgùÚ¨Ç3lõlqŽï*‘bZ‡‡vø (ôªöb$¼’ }{_³xüjZPƒ z¶'p‰ú5<f$ À–@†JXžB߯Õ3¦ãcÙ@œÑ÷u…ÓóÆó†ö1]#¹Api× Þ:… Zd\NqC´ÐÞ졈Q NI¿ |Ðψ ”l ·…&`zLËì[àÓB3ŽWË"$K4¤a¬ÅnX¿–ÀAk&½¤è¬C´) ØÚÁ‘02Å'1z’¶o¯€·àÀì8»™ ¥ƒkSØá9~ħ#àEÅ”Çi9ƒ lZ´;|Nb@;úD°Gµ{; ¡Ñ›ÁÇ!Ñ[ ,‡ô>4 œú¶n5É՞O¦é˜6ÀÈa^@t=ŠŒlµÄþ)lEà | üÕ©(ç |ål™ ÂZG„–Ûiy,Å£,å‹RŸLMMiu$¬œâž’9rèEÑøðëŸá+‹@šJ6 Ñpš'‚Õæ04ìO£\Ù >ì 4Zx晄ðæ&e^$LÞ*DNaEs„â`kÏwŒÅ1ïå·Hb`%þËŒéêàâx‚+5ÔAù>.#Ä‹ÝÝ&>YYÓ v ÁCAº¶ë¤³@‹~áeÝšY­Ú¶Ånökuwü³)hô`Y˜Ãù×IÐÉ-k„ ìjÑ'ãêëβv7ôð0h9Oxð–Ñ#ˆÔ Ÿ²ÅB4f;ä–×%›†^N*0‘ÁOãM…q³3Bˉ§2¦°-i"5¾g"€ù û^Gœ!)Mš›¸1Y ™Cô{tOpo(«Ü½IèPúÊ!@v<Þûu®™j¸Ÿáª[ç£!kÛW¥‘L>Š'ðñ}È,r÷Âø'PUh&¯~Ã¥-ÅAcßúRÚ•0UÉ;=àØ …ÝYŸZ5Š!ëã$Ÿžù¯~š- ±Ï}\„>@JRÚoKĵÍdúÁlˆîˆR7òXórÖi^¸€ä}rJ¨Ñ«€ƒËÄý;`!;çtà‰_o¥Û˜ÝÉIÆ'Å€k8‡x”«úhº THsìmݪpDólø2Ø?ؘÎå™™ë0°ŸqK)ÅåÎÀ#õ.‡â:É@\*Dme îå”Ýò°ŠÑ%Ü5èS4’èçß„r^ÉCÑåAä}Á{D¯:¨x÷ú4w? ü‹Óài´C‡˜PÂúó°ŒÝp—R)G±¾ð½&…/uí¢7›Ü¿‘žÂZ'iÔz®5ý+…Áù?oÉ-s ô%|= ”_»+ß¹!uOl›!„|ܾø*¥Ã›"dXj'±ñ85¾…ž.üºtýBv/ñc·4sã ÎeÊ|%Êç¡ñ ¯Áéqëii”s™-sã}¶KÒ'`¬p”©ˆÊs"ƒâ§Ç¢ÚÖŽtà‡nuƒ¶ƒss³^—–&øds^’Mºë,ÉæXŠuªÊ³’h7%!žÒÈ¥‘“Ø.q‘ÁÏ‹FÑ_«–Çt¥Ååˆ×ÙðœÙ}¶;`¦ Ñ·¥/Ãa¸õ®Øop¸]# ü¹Az›Zë B+ ç~/’Pjøf‹Œtª•uí¦„âÛØx[’ç]I]d `Ñ<¡šöùej<”hçÆ{Ùç\w%½—ôš“ÚdAÇ%”¦!ö,]XÚW$g>Z–ø\g& ð­ùìùãuZ¹âà  §:ö”ƒ#’ ÌÝÂÄJ>É~¯¤Üç‹d#I¿Ç{:z8œj5‘õª„ž»’Z¶%¥Ÿì¾ ¡nOåÔ9À²äÒ2r¦ŽT]°ÙÎLÃÐÀü‘þç‚ÿOÿ9ý?×;ÅÆ—i àé’ý>†žAODÇ•€ÖƒÒ­‘ Vkƒ»OJ_§–ñ«ff÷»å+O–šQŒÐÙ”“?Ñ‹i{‡å¿J^&õ¹Mº~[BÅ› DÅy&űU»AÚŠ˜õUR𻢅ßej÷2ñ¾ œØ÷}nnÝêÇÀu✋þïÝío˜˜|®Ÿ•î3Àœ_ƒo(6ó'"Èç$@(­ `7ÈÖíä#èOÌúŸÙªFª„{…ù½ÏÂÅ‘gE¾³é±ˆ)Ÿäx]Òå44o…e©Þ•ì"iõõ y3eˆ¼¦È®’GX—:}[‚ÂÃŒZ§aÂM©÷mI6"m»ÒÞÖ-ln›$ÙÁ•FÏÅh¨¢7ñ¬Ò­n"+£’Of$.DÂÖuZBAÄœ¢WʘŒsÚY4•IæèYaYöí+ô}&|6¹oãuáÈ3ýTI6H3 >÷|bo#?zqzÑæ)yêÒë¾M6ÿQH^eF&ÁÛO7ŠÅvaGøMþø¤Ä¬7ÙD¦yͺ¤û‡ÝÐÙŽDJz*j|=£Ü)…ßËîy"Ÿ¯û¢‹‹§‰ªýľW¹ël-Ó{Qσª»~èw‘ÄÔ*U`Hgz…êXôÚ¤z×i„Ëûƒä¥Ž“:7©0v^R|RìE ¹!¥ŽÑ ¤Å¾ýr& ãëÅëºÔXäéˆõ,ù¼~rš(l£ÄÖÑ—r©"\HãÀûvG/·Ð…‘þΙ£.g£ÀÿoZsg¦úZ å0½ˆkE䯨S¥pÖ—³£? ày©ƒºß¤Ç1å`ó“Yè8Íá¤$œ„«9BšÚ¶4»bz{,ËÀI…ã"Å O:§N=I Tõ~>¶|G®¬…:|ܘyMd$³Ù‹H8ð|7ve·‘–Ö¹-Í&´Bd!\Ì`ÏŒ5›pùï»-êuI×*c'¸.õ÷¦„ƒm"ÂÿVË& ¥å ÌPèA$'‹t¹h‰!)v¤Ý}E£ûœ=…Û—H?ן¥ë¯bãIªw»U)ÒüÇ×óRã>Ðu*Ꟶv¦¦óI> qÍC&½QP F"f=—«|åWYåY~&©Ïf-¬¿Ü”FJí+¯'c¯e€1-£nb€v»ºiÆÇHf±Žþ4fö‰Á¯'ËWVx·¹@rg<×fäËÕ=¡uȪJÒÏ^| ŸDŽHZ]±žT,ÎlJ Ùd®BÀðÑ1þ´¤*R¬Qñæ~ê4§ÅwxFhâws†ùŸ.Ue/£‘sïÓ.k9©±øZ#•’ö:Â8!8æ’so„c³"$‹¡YÑ6³j¢ˆÔƒï{|‚˜ÇË* RÁçëS¼Ý`=Ï £ÀìgÄ&Ž™"§òuôm6²HG'ÒÆ§Ê,p– 5ˆj[ïqÈ%Q浦³4üûLlS7»IÌ4}7=7ç|/oÔŠëèlÞØM„|Óªï(xJÏ·~LÓ©r$2çDœ”^XMGº+á'éªûnÆ/Ýf“"ˆÎ÷¸Œ\ÂÓ é¬Ô¸MT±³’3qò’uû±¶ ÚŒ…œ°Qâ&„Ó²÷ ©ÓÝšº*ɤTÉ9rj[yÛqVîÏÂíx€# ¦cSZ|ô nzb¼mÐÐv<Þ1ާòÄÁª™£b§áü4í•t“Ý©t¬7ìù ;ØZ›OªÕrRÙ2¾ôÿÂÞÀCÚÀ+¶´ò^Çp𢰱ú>îù+mÄå~Ä£°S+„“Ci®á¢~—Nª¿í'ô·)ÜËŠò‚61/ØýZØ6«À\Õùø„×ÙB¬báØ¾K‡£’šuÜÄN½ågCÂnâÑQ•°‘–—»¢ìdí¸¥0#;üEûçûñ!nEÛcã}>)"÷.¶fº¯«p8’ÏbÒžw$6¯Š¯rÛºok[ܶn¼&Å.:;„UÓ4ìMnjgúÞ¯LO›uß.nd·µ†_aXÁ¿C\oŠª; ÑYåízK;.{O¶ôúñû¶ÑXÚè}(itÖÁ½WS×·´Ö¡óͼøå±ŽpG³ö>³Ï>Ãû㮫µê= Cîu§ñìPÖ§ šÚ¯Pë°§·©;,¯jcXiÖÎvü¸ÕÒAü§”+_ŽO—8JûY¹F±ÀÿªnÄy:æ—A!øˆ¸·ßçUØXŒ`…Ö¤ƒRqÃôt¯s8ÂZ€gGv<‚'mÐžÝ ‡$ð·äfèÖ¤ýØé„kvl ˆ¦°íßXBâ4îlžºÂü”§BéW+^‰íߥ)cµ¸kÄo€!µi¯>¯GyÊ*;Èc¸Åž%=⛕KPì¾6¶Å=Ò|ª«¥ß”˜Ûs‚Ps'ºj-G[¦ÃÚ {¦w ÃyMެ!©õ¹Ã çŒ/³­úð?Ìæðìèàǃ_žU:ü¹?{O7p¼[x3©ƒ¯ùúÅÁá‹ïÛ»û³ƒÃ¿.ÔÁásøóõ˧þŸß,~sðìÅâÇüaÕ«ÚÂ(µÆ_l¹¦"nnWF%» I\8–VÄ£n7áÔ‰ô„7â¤Ad€G[Øß ÷sÚké›áL[Go\¾­, §MüAñ$Ôèw\Ä©)þãÁ¿väUendstream endobj 458 0 obj 4525 endobj 462 0 obj <> stream xœµ\Y“G~ü… ^˜&4㮫9ÄÆàõ b´«Ãaí®lY2ú÷Tž•UÝ=3‹!^ïöQGÖ—™_ío®úƒ»êáþïÍÝ“Oþ6^½z÷¤¿zõä›'o^ñnî®~u._9Ìýì®®_>¡7ÝÕè¯Æ½¿º¾{òÝԥݡó;ÿÝÓ|˜§a÷¬ »?t{¿ûs·w‡yžâ¼û-ü}Ýíãîïù…Ïêÿ¼þcžÒy;eL㡟ò¬×·æ¹ájúÃèæ™^x×íÃîüøN~;ô½s»{øóC·Oýœ/Œ»×ú þx«þKþÜ} ?àÇ¿áÇǼ‹y‚‡ôe›É;ÿNß~[.þR/~R.~¢_ëo/Êí£^|·vñÛrñF/ô·Wåö;½ørã¹x¯k¯;Ørrãú<zñ>8Fg6ʃN/z}p’kk@Øûü*œëÞÏùœ{pÀß–¾ÊXzƒÿî£ðÛÝ>ŸXÈþ0…qÌcúåe?ZöÎeløy÷)ìÊg¡8€¡> ; ÎýEç²cD%ûC¦,¦ Š1õ~÷<Ëf<Ä|5ÀûΆ1y4Uó/vÐ×x{ÀÅA¢ÇB6yÕôh‚F½ã•Lxš0}˜çݼžÑ˜Áýc™ò î4ùÌ+ßu>âOóc¾…ãóäoyñ‘Ö1åuä}ÞÊ@<÷àS>0•^^þ}ž“½¬rÍ´øáàÇy”úfœ£*†´#‘Ò«¢ z·wh.¾¬€€«V(¥Ø÷ˆ#1L÷‚äg$FgthzÄÖX½…q|m4À<õdžG~bí;!.ßwy—hôEÐ0Üuª÷$åÕËøÏ:úe]âõ¤t¬oùoÚãKë´ZÀ;²7ù„óq°¹YšB|ùËüK[!ri5žä9ùv8’ükr¾1Ctœ0„˜t0&}~îû²Só6Ù ¶11´9´0ê²@ #±Ž…ŠÃXù~ŽmIdê:v]âí@;‡‡©Nb˜Q@R›x.´`³wv!›?y)»ð~Ô¸ìÅ£<Í?ÂX£:.r5¬lqð±}fœÑ͉g Çû% ‡(0bc ˜ó6æyV!Ñrlo žìmä#À#^éÌÁ櫨c™â”Áy{ƒ§›€o4¦ Fl¯RB±Â¿,1/ìmEC1^pí ï fŠe˜ ä ã¾aJõ±›F8Ñ&¦ÚÆ<4#xÝà&Ù´X†ž¸Mkn†r´¯äÍQ4þT ¢6V1³ö& ûVò1â3 ÆA@o *«¡˜ž‘ô9½!.° γOh*Df(j`Áâ6x.rž—8•—™šüxDšS.¾6TŒo'Yˤ&AKÀ<*ƒC‚FrÍb$“ÆS —õz/¯º%]‚O>XÁñÂ;À.u†I'BÑ‹„­’„ q™¹á—`¨‰öúh œoµTÀ5Œ‚,0‘äüqcL÷ðÄ>SqVßHDc€¦—…e”VP ‚ <ÐP…)d˜)„QÝú‘ ¥=Ë<”CØÝòÏÔòΨö ³Løºq좫s>kÅ:‰ Í¯VuÉ…»KhpAÀ˜±,Ñ®êc™X|Â}á1K¡ùçY ° KÅEÿäNŒÐºžŽ·Ö`p Äáuyç­Y ڲ̛f_< å„•5-‘ÂØ ̹ÃòY´üÆ™´ íq™VÑ·ÅL&r]Æd••i¨ 3w([¤öŒö[4\’˜a‰IaócyHú)ĹãÂD NGÊX/8iMCè˜yêÕ€6/`DGº†šÛöYzO)UÚÈlÀx¾†Èx†´ÉÏ0Í1´Ê­dÉñ•Ü_¾8LÃö ;ÀHdÿ÷fÃUßÂÑd2œ¼‡„š³;Ùt·DóíêØ}âÖn1ˆA»%Ú“6|F2"bd³°à#—¡Ùb(k˜S_1»­H΂EO¨€±ŒP ꄘ•óÁƹðíÊR³{»$ÀÂE× (qžïÈ'NsÖÙEJG¥ÉQ»±ÑÀ 206t ñ•êsÕ¥ÈMvÁ†KV˜8„KµÑXO±3| ¼l5*ðkš¨àŒ$‰ ¶^ÕÙ&ÊìX*>©k«ò´ŒÈ× rÜ VáLJâJ^'/˜cî0PFgc¸&ÒY}Ze,^`R‡…y4*‡|ù­&mP^[‹HØ"FàËïÑÚÔ@Æ2ð#÷˜Óä6óˆ"œ üMÒÓã@蔓åVÕDÔn‹Š]â“y`vš$…wHwâ0‡trÙN}Ø ’xÀäôÉï~Õq"¤Ä“+lŒÐò+I§¥o cQhèH½Á©Õ‚6©¸áQ#w€-¦ïR…æ&´ÇšKâŒà°×˜³Ýz›”ò’„Z5H6Åqgå,EÈ6Ñ!0»U5Ôªd$NáùËo¦âº8àTœõ±¡ÿÖ!NE~¼YuJ¤×êóFÍà,¤µ´zôtˆO)’³aÎ|é¡ù@ÕxiÈØÁ§dw ˜nr̸h±K#pÀbæŒQyT@(l²$Ñ Æ£¤jjd•웚L¸ÍñWsÊUÑ5 ¤'Ÿ±FÙ‰©y­Ø55ˆ¤”™N¿6‡¸ã•R”‚µîÔJ÷ÎÙ’1£sôýÈ’V­žm%àF'>’èûó¶²* `7O´Ý?ë)nehæÙì¯Ú´µ„/w˜L%=|º¨ b£ýˆgÖ<™æ¿È“Aê(PÚˆŸ_ÂòDàLwV°ÑÚË>HÙLèb"†eà´–f¢e½%Ñ[9uÈnÔ©~@™ÆëˆÂÀ$Ú15)Œ¥“ãìã¢Z ö®Ä±Ú’ð†©]œª ¢IfžuíiÞÅüw_˜ù3N«¹ƒW(mG3ql¼$Ú³ügŠRwÈIJÖðÈ`m•Ö©IŸ'áXÖ=×.1lSìùß?eÏþÜ&½”ˆÒ&{ PÖ«•6œ7ÄIš‹$£«û¥4 ;×WX ‡°ìqÿ©|ñP·­Â¯ðpßûEÄæÕ³¶lš˜„}òÆËc{p(­÷F0Ÿ gÚ¹f§TÀôÂ^RmÀñ×Ðh¶¾/"ô¥ï†îøßdÑùÒ߀{/€ÝçPsŠ?ÝžSóeen~ì5P¨i籸Ï@âv5?Ð!4ì»öî~¤~© rÅã “ˆê(p9›põ˜Û/«('8ÜT4‰QÎóË@<’fn¼¿ÝB²m` þwÓGs½ö •źƒÜ†a3¢)ÔêUó1>²5é gÚEmµåó‹™~èK«dóÔ¶pˆ‰åxÔ'Šž‹¯N>¦èkx{Øôþ-7ñ²ûÆ,×êËùøc…Å–D°XöjIƒÎÕ«[oÊû¤äô½)ûk4t £ÍËÒ:ˆUd±ê¥•z±–¯“K·EU˜á‡ˆªÐ˜Ïš!4=5´I,óÊÄÒŠ=äÖ„ñ²¨Ҽ¤d#G5—ÜèÚ$9rÝâˆ÷Û<°¦LníVB_S@† Ъ@!Á9‡}uŒÖ[7©ã§ú@ݱ*ø…Þ}ÆPoá{Ô>}7ØÏË*M‹c9÷µpSóØz§ãÑ&õ>ô­ª-‰lº-Œ+'òZêDÿ{N‹\Np²DÙ¸-N¦UÖEÄ\yÔG0KžÅ9‹Í ÓòÉ–ï5]œ©s@l'ZÈ‹I–”7ëU% &Î&\"—–ÇñÊ×NGž Íi>×ñøÃSM¯Öi/Èðò¦j ecXÏߣIÏÉ´ü@ÈÏdªjN–/GÖaÏE*ôa%I*nz¦ÆÇ4§‰à~ÎiÄ|þ2õWaÍÿ©Sž¸ ²Ñ¯P?õ§«ô‚˜a*±-¼¥»¦Óå7-V%iä^1H~äÐýïôo°õÍ<@LH„›Òz ~)Ð6¤ªÃM;ÜQ0˜Öñ$JÖ¡âÂ.QÈ3Z÷]Dv”:ƒM*¦P[‚Æ’0«–$w"ÓRáICAW|°ËA~P:óD)ZY¸Ñ%¥¤&ú^ ¸%V†‰ñµ½… IõØöȯ‘/¨èú¼­ÊÕqV7T›¤sEE ·n\~ ½ülT¾!\Z9×_Ôq“Û0mµ÷%ò[Ú7ko˜øæàV;$-ÐhÐ6§`l›k_p?íh>[¼GÅ^1 üaeÑv­W§Ç÷÷—[þï^a::öcÍ]‚£æ±õÿûÅZûÖ( GýUäiië5š*]:”šaÛ$‰kl\Ï-hO΢炜pÉ7ÿÇŽ·6<¬>°W]7b›BµolDc^üϦµrúéÐ<ÙÉ%Ç?Ù?å©—¦-òp ¸i…Ýj«7@Û­úù0úÿƒ£\/ ¸áiC9žA9õhÚE%£3iÿÊÖw=u- ‰ƒn íkâücWòðæD¬¥ÊèÌU7–äpÌ異sÊ–“5éMߌ¬,i? ˆî‡}’ù© óë!UôÛh_ÄÔìq+CÉ·Y–6Kɲ,.ÒV¦yûË/éÛîºÇô*‰îPuÑ> stream xœÍ[YsÜÆÎ3£±‹”æJåÁò!3e'²Í$N9~X‰¥ŠDIÔ‘(ùóé{f,IÅV*¥ww0GO÷7}MãÕ¦kûM‡ÿäóÑó£ãïÆÍÅë£nsqôꨧ‡ùxô|sï:ôZÚ©›úÍéã#ÙoF·}h;·9}~ôã65qšøÓéïa„ïË® í4À Ó3èøY³ Û¯š¾¦¦í§Û>hvn{Ší_4;}ð]³ó¾o»n¤¹[xâÜËN?Ø<:Ümÿ3~ÞÈÏa¡OØ~Ùx˜Íû°=Á'_ãèãƒk§4Ñ0$æëöS0MÃöûf7@«sÛ¿6¾D×Ó€Ó&õCãxëiÓÃî|'[ßù®ûib¤fèºnÀmumò㘆­[6»1n=ì¶w¡uHâ?§±ß¾(:¿Áæ!àÏ]CؾâÇ®í|ÚîaGÓ;·}{Û¼«&x {Æèp&? Ð<”“>¡Çlþœ'õðü¢ÿVõaJqû4ÓýGçc5ÕKœ µc·wtÑg4&:ï…üp H- …÷ðØã`ù—B~p¹'s½†¨Z—:øúõÑéo~Ì`x "¯0¢Â&Âæ‰õB©oï"É ó>nï7¨EÞEd%"¢ï°º!¿Ó- hGõ$$—`dð4‡þ. «±_Üþm«ÝáA¢O`_Op…kLôó ®‰ó\@;ý8‡í@˜®a)M€©<õ}ýB…ú$ØzBéh"\‰¶„ôž5È`ßÇÖÛ ~ˆTáÁxH‘˜K;&2éàH”8=P³&à éQŸÙ 8ã1ávYÈs ð8–ƒh§¸úüHž¦¶6šÅóö€õ4 dÇ‹Ìϼ*þ$…JNËNÉÅïdç»Þ·1N‰½}æ7~¹l˜$h”«i Y 'PpðåX¡®ž(ò‘º+ñ±£‡™_Ði ‚$Á»¬pú©uŠó¾aá”ôEh 0e0’Ðè§ f†‰ {!+)² ïר-è,×:$F]Þ8òæ!ŽOt€^âÔ¸+\ïœ@gØýñ¶Œlü•gd¦GNÛJ¨¦ù(âZÄÓ3!ÚPzz>3_0Ð;Úµ")g‡zκ ¤ >î+vr™Ñ«Û@¢P„¨•FžäLˆïýö‘¡G=g²Ñ0½Ìs>ò÷$g=hOe%›–±,›#0h¸qK؉Ã@µÌæT¸ío„>§àKl³gà‹»5ðý¹á}кÆç|vÆ£ÒÞË´{lêh °ÃžwD'Tån¢#³€¨è 0‚0 íËK¶n{ cðÿ;\‘û B‘3Ðð‘¶×‚?0ªÎð‡ZV–<Ý[ÃÉ1‘¶BÕ¤-¥asPq¸è”HÏfÌ<±YΙ°Û(uE‹"2£ö<S 4yßµžEëÅF˜TÞww„­?â/´×¨ ¿néÏ\3V“Ѓý‰z( Ø7[õ¹·‰¸øŠ° \ÓZ—z€5zò\œ ç×hNÁ?œ‹Á08íÜÀgæ‰bÆÚÐ'+§êàê6 n3S‹Èpd*M¦.°N~ßx—mþöc½TL«Vk± NýIÂ-Í¥¶z‰a´^ ;8V)ÐÑ/œh6dÎp‡YŽì¦Ýþ튙C*Øö®!×D[›CàW^Ôz¹4]ä"È9ºÑE(U¬÷ $Ç vn üßgœR#Ýcè’êCADÌî•â—-è@– Ç_|T ðËujëE¹3z ½áÃ@³(Dpò]P ]°)dK(Œx.sg\4ãÌ•í#‰òíšÆ[sXÅ Û !;öÆõÅœc_ðßM\?*ƒçBq(.)›K².?B þÿÎñ IèÙ†BO°§Q»íOôç<Ǥí.U§N>ßüêè‹“Í·˜¢ð*ÎÒ(麩Ïò.>m(´ì§’'ÿŨ?ì€Û­¸“ê² ~ˆtk¥$ g¨zT¸våÁl§ð'")æÂlª¥s¿jY18:ó·¶›‡TÑ0¼Ô÷ÕÀïçv|LzÎü_pÚÞÍ7ו‚¯”‚nð' •;bЙf H_ê/åGˆu¬£+8v³¾¿VÁ°ú `'}ÅÀ¯ x¤5ÿ‰š‡Íedf6Àù›‡vÇYÉ,‡JÚ[.îž(Á§Z™5ªÆ–&æ°”Ó;ìáÍmŒ+”¬ºfž3µÍwÜ0M¶œz1œµ$?£Ì®è࡯ª?±±ïq:C©_5QHùœ@^¼ÞÊ‹rþ'yðA숺õ˜/¥Pö7ö“Š_ð*¼[6ì…C KÉÙ¹qN±4ÆëœEdrìIgq$"d¶\´ú„#'s0q7Ç•©Tvì˜<s3}d5v'[åPbJ•ŸMc_/JWŒD½n_H“†¾kXZ‹Î–ä ƒÍtE±›6¶·”Í-ÐøX £À)$ƒqr_°4„¾Ô…ð{P¿q–vµVtfk2´1[Q\0+é±åöäü×iÓ*ÄÓœµ¸‹ÊðC 3"‹‘{ÔIMë.жTK™ÀÙm„ì²N“qŠÕxI·P#zG©ëIÈß?f¡ãJßYE÷dÅû:g¢ñ1agéóÍ@RäTLEò× Ì\‡[VE†¦bšæÈ:.ÝRÌר,À³#Ö6yÆ÷[]bÄ¥Þw½á= ³Œ`xù6¥Â0)_ö¿¸ìË4S–.îøö ¦ÚÙ]×ÔvL–ß3ì÷«y®9ªhsugƫ̄Îk€@l„ȲÇj¶ˆFÉ“âétK 7[5šjç> .PFpá¦Î ôðBÈyò¦—ú·Äw»ü€<=:1_ÿO9ÀÒõÚ8ïàÄ¡Yî¦ácö(±€«´½öDá7Fp¦µØÅInÔâœZ§¤ßi^GÒ2±¼Å*€AËc§À@Ä4ZÎAôä²WÙCÉE•—b„–€éþ¥&Î~(´!u«Ö3=%Æ]ÁÌ ~_oDÚÞä|8uÓ÷‹ 6~0iûñ¯~Àé=ø_ƒ«D칌Á’¹*J-%P½o8–˜g Žg÷ªšW;˜îÐÙ\Ö"y¶JY´\Þäû ¶À;I‰n$Í#º¯âüø‘MK)?ZhãÊû–—šˆ¦Û~_b:ûa¬?ã ¬†UÀ/÷øvsYeI0ÏžPc®‰9395ÿ¸òü¸V7Œ|]‰Y ‹0".32ÙYÝ7±$ˆë)ѱ§ò†¹½Ôlú3¹\™ÚP+*ˆHãM»ÓL í±ôvÊMêÙ¥­°ïN!dÐ0—"Êɺ±SQQ)Œòf{~S” È Ê¤§Û¼¢¯òm'_õ²¹ÇFdò ‹½ {½ˆ1zð¦hiÑ=ÃZØ!>lÁ!±n8 ½Ž`×"e+ô)’³{Á…DzËç÷ŠÈø0[éÃ’̈́ݗôÝÔšKô³¬æ„Y<ø Ý}D«9QÖÝ®MëT» @}Ww˜ß‘k€OíB ›Øï5m7,ì`Šž¤ÀÆiæéÕ÷à7[Se8`M—ñ›{róËËgn9É0K¦ ÖuUʉMNð.n¿¬ÊÌ®7¥“g±‡iü¸9Œ‘Ä»ó3©£¼ûÒx~j óo*°¸Jœì¯-Ù¼î³w‘q†ûoŠ>ÃÿgÑ'^®·£ Ž3x]ëzJTdùáÂÿ°À³Ê¢¸>J­_qL. ägEEછkªY#,šp…«q8íå$u£~TQ_Q§ÿ]?ä»êÖÉ4°–kxÖÂÙ<˜7^”»Š?ˆ6Jvz+Ø,s¤U2†ïæÆck<ÎWM.˜+¾éã7ÖØæÆGÖx¾6Ñåõcž¬QtU›Ñ–Ë5+BÈv~Füê(u¨8r–¿¶¹ëëº_µ¥U'*;Ô¶Ù×Uôv õ]®¦ÍEêYe¿ëDR§H˜%Ħ°/ Ls'H›¡³Ò”áÀŠ>ÁÙaù;>õ†ekŸ'Eɘ¼g'ާÊ×t¹ØR OŠ´(?)#R¼O\¨oqj)v*K£Ô ªndKóZœ"0)ûÜëìNq ÕªýF¹¯èÇ6æj½òÒzäZ«¢´(c~Jµ€\ÿŒ[}´€F;ÞTË ›à‚â–U‰ÌW$­\¶zÍVÔ.ìtµ?¡ÉI{2°=Ç…—’s™Ýýk^·Ê•_äÌÍ*§Œ¥_Ô4­d€©Ô`Ø{ÏÖ@3aâS€Ô5]4—úZÚRkg9çEX3 E\Ã×]±M£å¬ç~Zˆ« èÊXE½½.tfàç@zÈð™Bÿ ¤ ‘¡·K‹—UnºÛZA(LË%iŽÓsåݹÝbÁ }zCšìê{Í.‚?Fwÿäfaõüoä:ÏÓ®AÏ0&&eB­FöŠt Y2yŠÇ‘'¥.…‰Ëv¯0&¯×[k¼X3ºïÐ*õ}J…|]â[MáªíÿG±¢Z·lœ ‹'lŸ®ÍøÚ|ºFnžç‘ÍsȲÛèÂD¯9%œép9=ä¨%?³ÛÅsÖ…Öõj­keàÅè·×Zz€ïØBÂÍ›]((Ê„è%ËsÆW.ëûÛx úbN™†> stream xœÝZmo#·þnäG)PìÑzù¶/‡¶@Z$H‹CÐTAÓ²Þìže9’|>ÿûp†ä ¹KYöµIƒâyÅ%‡œ™gfž¡ò㤮Ĥ†þïb{qù®lõdsñã…À—ÿg±üqf'(aGª¾îÅd¶¾p+Ť•“V骖“ÙöâŸEWš¢*e!ñï´íúªïšâ›R.§²x[NEÕ÷áû¬œêâ{»à¯é‹Íþb·2ÞR›¶ª;»ëléw2¥quOœjmª¦›LU]µ¢ïÝ‚}9UÅŽ>Žð±,§F¸#h'®ìGU×BsøºµëÞ´nÎ>îýê^w$÷>æ´úÆ*zÙŽ,cOïwü~Gƒ0SÖ8ó’xæW<È2/sƒKzÚòk–¾Ïc—ž¥û§+~}CƒwŸ&½µNmÇÔ9e ð¶’MÕèƒ#¿gÖý"‹ir2ÿ˜ÃÔT©®ªµ…Ьº®Nè7e/Ðú»b¬¿5B¢­­@ J6ö»¶Û#ˆ”±Rê¿‚‚ ¹Ùà4z˜[n>ÊùàÌÆàrضDñk˜¦]ŸÁ÷[;Ž`zœû‘ãe8K]ó9>·BÞۈ ·øŸÝÄªÝ k?ÿÛ2DÜß]ªF£õ~g¿ÞÖ°:Òn¨9«)þ€®‘½ªÚ&¸æs—ŒÐ`ß—}Ú=9…çNá0_áÄH»°¹qßepëÜyl„Dx61ÒÙPƒëœAyÝ’wº*-’úΨ⠶Q¸Ú±Îeì¶E;¸ èÔk:ª2¦ï(àv³Ò]0!>lì]í¬ƒ‰…‡(m¢ëÍErÀÊö´Ë`xÖj Œ®d0)ƺU»÷ß nõ¡4ÎÌä³ì#q_øc¨;4M/z0¬®˜©ø¡(9Æ1Aœ#1yÛx“ÓÂçö'eô=:‘¶‰É¨« h¨I„iX²)ш Cc^Ôa… –“2zÍOKök2è—üP^,€0 Y¡£´€Ö±ˆ ™áÌ%Ú{’íÃØ™_GÈܹb6õú´´†º fðèW÷h_Õ taÞü*Æ:ìz¢ Þñ"t `jÕ¢L¨µÇW= §`È5P‡ áê±ýk§Ö˜¶þ×®&u»[+ äª@¤6`§Ìíüû¦”¹ /EW ÂÈùj:*J„ï«­UÙРàE¹Á\-i»JC ñ§úŽÒë.=°´«& ÝÔè€á뜱+~ -–ï<Õ|óÁ’2V‘¦xWNÁWCP&]zoBÁñ¢¸ª„lˆ%9͆š ‹2¸Ü!Ìe\.”Z 0‰‰Tã¼åkSRrq™ÉáºôÂm@†TŽT)Y)*°Lpä59³ÊCKˆjHÞ=ÏçD!x°¼ÑrDÒÑC\‡4Óú]ÁÞv/ü ׄXdméT‘á–ÌO´ÁyâcL œ“Á1%\yBjg2£Œ¢…Yì>GWã¸BW„÷O|,=\åö$šŠö xz{1û†¢Õ`®p.Ùû:y¿9Fzg¼ûܦ‹{]çW±Áußb5°Æ1ÊESëˆí¯s2W9‹®bã°EÂF÷¹ì¶g ã™Áô·¹ÃeÝœ#t*ÑžwIö#‡,Ù!·øiuË s‚Ô9<ÝržÞÅv4Úu„’x#/j•6,) ÂõÈfI0ísx8ž‰†;ï¼^\âOÏÖʹä6WÄ6‰ñ…eV¶Nn ¿g`ÞåñI¶³Ü/j$LjYç²ÆCâP6ž²,+Ñ)ðìb¤Í6‡ä»Üà6wÌdùÌf«LrŠ7Kòý @Ô3r£ŒþñÓ”5³B6ãÒ%’Â4Ië%t¾õ²h¹bæÞ®5b(iT?㺼‰z×Ý,½x»(5×á éS© -…‰ZäƒÛ8 I%óKåzÜÖC—Ë‘à÷Ð6Á ÏÓOï÷ µ‰šÚÜ!Ö¸#NéXÚLh¸o¨ûbVv ÙÃ.Ø¿%¢âY³°–ÕÀ‚;ßèz¿Æ=mæû>¿×"Ã"¹g!Èö¼AÒ䓳£4äC5dpÇÓ $À-;ï7êCà½V!a5Ä$1ç*lÓ »\‡-n‰u;±*º)¡G·hFN¹­y¸iQ-Vµ$’¤©à[Rº8¤U Â`+Òn\Û«mûÀ0vs”3ýÓ‰Îh*Û¶RÓ@SÊ€¾ò5›)lï©éµ¯Ì¶ô{N•«×·Qè†;Î"¶›À#MžmpŽŽg¶2^–™¬Ë3#ÊÆ3ïs¥ç?…×\Ö£ö&) ˶ÏÝ“Gæ‹/è©…‘|u“%}E–ÛÑ“úm®ü§—¿Ú@Œª×5¾„›Œ ™„EU){¡|ÈÙ=¹Ó³˜O¹eÎy(¹z~%Ú¬î’n’4ݯs:úSÚ¬l5ÀÓ1öèBÆŠALÈZ9iqĨaSÕaT=‘‹8Ô0ν˓ÁEf¶yJ‚pï¯2Ä1%¹ÉAàKŽÂ͉™ARÄûZž Qž4'H3ãYóœ§Iè9­®sˆÙ¦S½Zzn@gGée‘Àoð[Ü™Ç÷L‘3’’èæ¥%ñ躣ƒG‚OdzAX9óº‚é^F«3ƨâ´6òÚÿAØ$%¦(•rký&ñç« pÊO’Þ#áUíä’—¤—ÔGÞqòÄr^bì÷dÛ‘¬}¯Ã…×ùôs.©$);´¥ÿƒÒ2F¢<ÊŸ‚'œOxÇ#Ç ¥ç‘c(±_^è*kd¼UN§0tüûL]Ù3ŒÀœî¾fžîI€á‹6Η#Xg ÈÈê™îûWxÊdÇ$¿ŽZý9Š9 J´”ZÆk5_©dïÿ™T…â¼ö¤¨_Êkº5ƒÛ•ìÿ-Ý•¾.ñù[°s‰ïu?DùlzŠÖŒ+döú)±û9NCü'¡2Ètl³ÛËÀtæ‰õ¦ã楿X°# ‹øœ¾7¿¡·ËpµÝc )›8CÙ=kOï¤_°è¾CÇ$7çã-SÞè«Ô®ùüUŸY™²Iî#ÞÇåǾy¤"3æ™~É…Z´îUð»`ë{¦„éÎýî—ܾG[>Û2ìrƒçûgÞ}OÑî_òî'Ogù0«ó1ÁN°ô·ÎÙkZUtÓ³â5o†¡&+Ùýú+z>ŽØâW‰Z”8ÞÊ&5L ½>/ Þ'þç> ƒ›Žq¤ïsºŽÚˆŸ·¿À_Ï.þfÿý‘2Ûqendstream endobj 473 0 obj 2516 endobj 477 0 obj <> stream xœ½\ksGÑ~?‹üˆSþg©œõÎegg×—ÄL%@‚( €ÂŠd[Á×XV.ÿž¾Îôìî‘äPNQÄÒ^f{fºŸ~ú2úf7ôn7àÿäßó'÷¿œvO¯N†ÝÓ“oNÝÜÉ?ç/vŸÂÎÕ~f·;}rÂoºÝäwSˆýàw§/Nþ±ÏݸOÝø¯ÓßÃÁÙ7üû9ÁK§ðà'Ý!î×¹~žsœ÷¿îüþOÝÁïOñú§ÝAo|ÙBpý0L4vw¼Ÿá¦}èoe}Ýïÿ#>èä—0ŠᙸÿM`´âþ!Þù ÿÏ„èû9Ïô óyyìS–`žÓþÏÝ!ÁUï÷ï<ü0zG/œv9Ò[ëÒ># •½¢Ú<}@”V0;´›uÁ.ŸÌ_â'îÔmú½Äž‚ÚÜÞ.Ú|±–•5{c \¤Í0‰¢_Þ‘µ˜wÁRŸ£êëó*ïÖЊѲáe©Êö€óA`Z Ú[¼c1å‹wL-è³±5l0 6l}å‚Çh•Û¬á­h®-ZÑÚ¢èÅ÷ ¡6­ú¡Ë‰MðCÚpµS]~ã·Zu„yÄ!Ìz©ËŠV1Ov™ #ã@жT9vTÜw˜çåV²èÇ 5Kïyº}tÊUwdÞ0âÒâJút)9Õš®áM0|ü\Æ– L5ˆ% rQ6Ì*øÝ@Äæe‹L`PˆÖhPøFºÑÃÂJ“‡5hfôé¢Q:=WzÂ7dÇ”u*é ´n‚°:×5|†FRO>Wuýš€X`ÀoQIÐGˆ*ƒ^R¨¦\} ‡SîT7WÑ])ˆð-ЇoŸ©›Jâ[­ ¥é•cæƒO£GŠ <娿g'§¿Dkå"ˆ}7ô9LÈè×—ý4îGÀ.{ä¿üwžˆx•‡ßâå‘Ú=²=ä)2¥ï3$›»Ó8xTDЉÿÕ®/Ò4z 9Áåd½¤ÛITœ€ñ]"¢ù¥¾ý¾„,N"Fޤx!ƒ~…Ö,Ï=§É>ó `ÖØÇЭÏð9MòFožü¨¬ÍgâÍZ'/<¾Ø3îpH« ý_xȬhK, yvXŸE‹&ÇE7 ß`…f€4ð¤—Ù´±~åu±4Cv^ÕÜ4«}†™åYX¿Ÿ6<ÿK‰Ó^*ü}/ÓÏÂüž“à'Ù3Î pOÖKg¾i¾÷!~9†!Ø—À..‹êÍŽúAZs¶h3ŽÝ튟¼ç ÔÕû‹UR`ÿ8 Å €Vàç©¥ó¸Å/W»¦VOˆÒ±q2$˜w&W+· ÑWÄ•pû•7E¥7ÆK–0´(Œ¡jcÍ^ý È\uÅ(Ú ŽXP5ža8Y¾P€ñ9J3ý-|ÏÄ$~F!¾§9õ!U¦!ä†ÌÀu_laŽViªSºØÒ)ášy2Ú¤Æçf’«‰6Fc{&â$÷ˆV^(žþDú k–üêòáÀŽûôõo5OÖ¦efJMC¥ÔhÕ“«K¥°…š¢(гÿç¾ µš"Ý)o?Q-5çsÉUü³£O‘[üÎDŒì·íÏa_|,«¹Á‚B͸¨ç]pá’ì™^,¸Þèw3ÕIPËÏ–Pµ¬ˆ‹ú©:°È§žÖtGÍ–Ò?¢¼" a A¼-éò=7h^¢ÿ” Ãk6;=õì§2¡Ì×øŸ·uAþ]xÅ9Þy£©bãsü+>gH ó¼ÜŒƒÿþ\Ÿ¡Ûü pU¿÷Äú¡°³CÑ@ÜG7±ó)Cè+oÊE ƒÇHy¯\4ß¹,èêâGåâ}ûÓz _/ÞkäÈl´?ß’ãm¹x¶uñºápr‘ ŸüU·™Po6ØÄ~Ö=¨ßò“kßÎU¯žl™CÃÆ¯…6­Z!§›i¤Æaâ‡~$O÷Sª ±EÌH FKó³o²è^¥M Xw ÕŠ úQ$Â{â`#íqyÔuãÑ{þø=„`ÈR6K¥QéOÏcö5¾&^ë¼r›Öòà%ÎêœiÔïMƒŽY»3WhÂ5Y&ÙÆ2ïð‹Ž S~¬+¬zè}$1 áù òœÂfq˯VÖrI„!NwSÛÖâ¾Dßj*lºˆËðééÉ'ßìBèÕÿÀ äÏ(uÞÅ«“2–?~xrÿáç»·o®ŸÜÿëÎÜÿþçã?}ÿ<|°û¿“Oî¾xÇR£Ïðµìà;pËŸ—-çꛊK32âÿW‡ Ùh5“opž×¦ æíak8ñ8*nÂ#¼Î›”š\–*¯@~ Ùr\q·Ukõj1à«ú6‰W>å=1}ý5p!ë¬Ê|$¸k!ƒÏƒ:Ö„^Sö°9\ïíŠâ‘QkQ=ð(šÖÖ‡hó%ÒwДE–y “T’éhøPfwcÒh†‰WëK×ÓlKRãûàæ^´ä¯]›7ðã\<á"‰UR“&cößÈ¥¤¢ü<·em»7Ñ5P Ê\à{Íõoq:›,Cþò›2ã‡õiãþ,Rå¶ZèÓ C©”w‹!u°wNO¢¦ƒ¥ši¢XfÁ]ñšàkG4寰³)"iºãº³¹ôÙ‰íêGF¥>rTZ`xSéÚ¬LÕ¹#(Xè¼=­qŘ¯Ä‡Jdù² >1ãñàÓ„XWrÄ51YÃýéu‰@ëoê+wþd1çtKÌi+*åÉ ;-#ø( Øw T¥ ar3mÈjØ› V+Ò„kÓƒÁç°¨üû9Ô ÒF7‚Þ·9&)@/¼ÌeI%öÜåö c?7@~i¢¢mÄÁç™(§¶s ,´}× ©/eÿ‡ÂÌ?ë¸Ø÷Ç—ÙüǦR‹“{í ÒïS¬/ýlÅUúeuÝ õ¬£7zõe‹ö8‚³J=Ýà u˜$bjŸw $TFý˜× ëÒÔi̾¬ÝËïhÝÿX `ß'óØN¢™ŠÝ-õ›‚Tr’‡•þ” ö‹­ÍEqoj¦/wSÕm’w^1"Íëö®¸KOIyã_¾ ó¼ [ÔÚ¸[éD¥@ÒØ&1SÒŽ3d…¬;¦ì¶Rª…ý‘lŽi¥åZ>7.YK•ÌËJŽû¼ãæºL­Ý-:Éžv±£ö|Õ ¤p4§!ñ"ôÀ…]åw!ÜYI\*…ËBˆqHc P‚Ðñ;ã·B¥›±áÍ€äÕÏpXÓÜU…Ü`6ÚEfºL¤êåFòhj¶{ v3ãþý¥VB¦Ãïô@ß(·r„•5Sèóû—5µ[Y×v ­kMÞOÃQŠøÑ¬VNræüÉ æSÙ0§í{zË•¯^”òp\RK-¡°wœÝº kJ¯mךìÂ.ë= Ç›J¡Þ†¦ç&¨+©¦ ö½+‡Û ÔíÎ}2Ë ½â“dmuÐÖõ¶&m„]jC ª´ýŠä1\)@ ¸o±¤nno“kz¨[‚¨"6?Þ!Rãή©íëô›áñYýñÖÀéiè]ñ?:/ïÈq“Ç g›§GÚ87;)Mª>ZÛ|ƒRêa6¼f¡w%ÐôÆK|OÞðR'™æu^§%ô{a’šÉšL8_ã Ó~Í]u߀ÝFOnët±a6VlÒ[žÑñ#ÄÛSõ˜0~~%z1ؘ"CóQLÏéqi±©'þÒ‚‚ùVÚƨ¯¢¦ ßÐl¶¼ÔZ³†tƒ»ñ¤+Ól|Xà ·ßv»#ØÝðþ+ŽtÌÄ.ÖV­£í Øh\9>‘üÓèh„øgÈ«]ï7 0: œXäÃi—ùj•ÄЇ¤¢ËøÖ‘[G†P3ó±®Í6*ãä¢DÙêä2·zfN”Èõšò6]›×ìõ8DyÖh&z­í™‹þNŠÑü]®$ÀÛ"Ï ûŸµ¨ÁEigŽy݇ë?kV­ˆŒë®6¶¼NÆ;AA9Èß'‡uØkŸé]~/Æ„=Öé'˜HOÜNäXLZÅ/š¶ÕhÎ=w»ØÓ)àZ¹2¶GãÙ>Èý3A˜ŠÕÚÞf꫆’΄ý7NéHé¤ö0* MåØb5ɾ/ G¦ó&D/›É _#jê¤rCΛª•49ªO’^J›áBP„Z暥ÀÛv)¤5W*F@&kªtÕÆ·]÷Iœí×&¨ñ˜\“ÏsctP—IÎ|”sƒÜõgsl¦eõh½j+»_[|%:JƒZSø6ìýÕLz·$xm,å5ú5ΰ4ú#g¨!0Üzö@zïÖ'¾(¤¦?F«W× è*¯*;rÇgén#Sþ\ÉB¾ÍÉiå+t’Ú4ï:æI¤ßˆWãÐi4^¥¨ŽiWOt-QÅ–Šhóå]hÞ1 ¬ˆ?º³2r® h²ßkn"Ónñ±©“ÑëV¶ô^ày(} ~Žw/A”¡MhÎÇ4´­5ÔÛµ<‘›šxœÎ‚Áš>jS¼(Ï3S±æ¼‹wV˜_uR¤ð+NËL‡-ùj댤•’h*wˆ“ÛµÛÓ3{…CóMlB”vºÖIJz±µUM?ÑAù²@j‹Wuçè]m ÃcsÖ²jtøÎEÝYÑ•O6Š¢™e9• â¡8æ –T,I˜FñtÉÉëQô¶›yÉlàlû„ÊI_=TZvŒªEyðõ ÃlÿHä´EiæZžþV23LêsãÀMIÍ5V;b(uE­ G—nµ<÷™¸zjÙõã±Þ~t.Ìû@g“§>ÅýÇÌ€¦ˆ6æ{0ô@H4ôÁ»ä('Î'yÂgsæ¹ÃXÃLÚ…£fÔßO >@eyÇS h*x)ˆA&}pÎ[MaPÉ7ÿ”ÉWj”5£=Õ: ÒØá.û"ÖCL#4:ˆ·û‹j;ã¸!ÒãØ„§17þýˆ´T•hôí Êi^´OñiÐÒ]ã`ÇåŠ$›(a•)Öx¿&§Ú^1ÃE[’Ütql…™›5“Èλr öœžA´÷qèµYpëøhén ~#_xK‹ª2‘¶l’–ͨ$×a*‘ÏŶ/mOñúÉq:iœçæG7™¿š“,úcÚ6êß Ñ‚9¯ÚYýt$=YO;[7{^‚ï˪ƒÄ¿'J5›Ãv¡ž;,¡÷‘<馾Ê&r3iᱜ6ç„[½nÿ*Ï¢‹GÚ)™÷ÅÉz-ŽÚendstream endobj 478 0 obj 5232 endobj 482 0 obj <> stream xœÕ\Û’·‘}g0ü ã'u;ÔÍ*uÓ›µ–"¼!Û»ö®äˆÎCZœ‹x±Dý"¯ÈD¡z†´vƒÁž™*@&NžLdõgݱ?ëàÿ¼¸~ôäÓÙÕÛGÝÙÕ£õxóŒ\\Ÿ}ù47ˆ}¾r\º¥?{úâ=ÙŸMálŠéØ…³§×¾ÛÍûaw܇]ÄŸ‡i^ŽË<î¾Ü§Ý¯óåo÷‡q÷ÕþcØ}½»ßîa÷ÍþЗeN Ü »ßç†Ðøw¹ÁWzï¯Oÿ= Ñ+D¦c7g9ž^òØÓ~ †i¶ )ËØg‡Ø§~Yèë,Èî|¼€WùãØu}¿{ >‡£»»{oó ÒÇã0ÂÄ¿yôôWßí~ ÷.áã\šRoç÷uO?9ù4Þmˆ[$¥Æ÷Ò¸e¼’kÔîBå¾¹¨ñ[³ÙÚÇ.G'¹ãï÷ јÇ( zœ¯ þ’Ö$ðyA—i÷L/ÂŒycK›€RPúK#¬ÍLôð5YHŒIž# ˜Ìhž„•5J¸z°d RÖ§´ƒ6ïö¢“—:,ÂWá€6,3-Æ9ksîpÍ~†µÉEHgg¬þÔTç]÷V…„…Í€M=jôš±3àÊ ]„>‘O0£ÄBI/°u'Xœ¡ˆX364AØKÞeKôO<¯NŠ5#òÚÈR?g;q;{&=˜Çx¢ãúy¥RçküŸïBÓÞ›Ç!°kУ¨©ÊÃÞöŠU”k—¼Fs’ýŸ;xÃ/ËÐU÷XÜl¦›[rÁžóAÝ$Lý¡(‹>;;@ 9¨š&Ô¢òˆ§ ¾Ì0â8×ø”³‡®ÿÚyu>g±àRÞjjNA *Bpa׸ ’Ö¶õ® WU«Œ{o-= T5ádZË1ÄEl †tO#¬âNɳë’a»€fè`U¾…eýFŒ¸ÔAVvuÃK¿,»+¦úõ^°L”}¹Ñ·ÚÞù<>¢Ñ5-]°Š¦ëÍJg ƒ~ ¯Üc¨à oã‡ØñHÖt.®êõTLÁm·Hmn&Pkö:Yb A1”1ðycZ^ds÷±mD‡js·6y°©ìš¿—Go½AÁš†eë9 r["®ìéÂAMhÔi!ZÅqt0ÌpÊqX ³ÌëùY5c8ÏöÎXyÍÀîó0.ÌÖ{:´r— öß+–ÞH3þ´§Èmõ/x=7)]× •¿\°5ª%€h41€ ‹ÈÝPºŽí#;}غ5cßáŸhڕ׸”~ze`ðg?4Ö%劷^-•†t 䕬Eª±™žxºdFóqn¯AjÐt¥"t7:vW˜š5ÅÀ¦+à‘Iô™†®÷<Û0«*é6Gí∖|§€&öÉzÕxË‹ŠÐ¹(e@–±Ñ€+Æ”d«šKÀ~†Ù›Òméô…2·bø$ˆ³‰ºû“â‘ÛRC‡ó"Ð$~ay6ä¹£I¢SÌ:b‹¦;ØJ)ê΂•;ÄßŒÚØ(Ö&öÌss]`@»5#RÛaò2ôØa±:c[²Ý ’nÂ&=L¾gíÁ­ØÎ-bŠP×Áã³}öª’È@u@0œnÙs2eP¾²8ow–~Œ.&Á•lv¸„¨@Æ,&•RO¦†ÌK»{Ê\£ÍÁQHbUì>aåt…p¢Ÿ ëEÕÅ|^U¹Ø‡¾L&S¢û!"Ê•i|•ü¯˜=¤àºô16‡P‘>J@AKp vËðkšÞÐõj\8Û;A|:DõiK ¥ìî„®(2Á|nœ4†º©‘¦JK¿k«­Ðaèj› .G[í¨5qº¶â C_è( Üë,¡Å˜òÏÐqǶä…H!mËÛcTÿºÅ«`udnŽuºÝƒé.ï­!Í¢M»J<´éŠ SqáıHòuÊUÃ]XN>öaÞZ™ˆ¤äR×­r`‰#kõ$üÌCÀÌFbËÜdÖ,áìÌT®é)ÃFŠCÚ}ÿFòž‹l“røP`/ZŒsé2y´¬!—¢bJö ½ÀùÐØ‹Á|€E›4í0!a"¢‡CÊ݈ óGy¨ÔQ4Í×n ’OãOÑ1NØ}¿WqzdRÞç¡Í8ŸòT;ðj4Ô%6Gè™°| ®QÒ«3’çnïØ¼ž1Ú§;ãÒH—ìQ£dZ …OiÀkŒâ £Ø ö <3ÌÚƒ]õEtVÐ%I vÇt¼#3‡ØÊaXB®pQ6“#…Ž5ޤ†Ea§Qü!Çy±@¶Æúõ¡ÎÒ¯0®-sIå,ÁQ¬…6¡ËÔC“ÙFK2Í#NùH {“»'4ñéúÛ"³dsL.Y ZóÑL¡5­SY JrÍP öTÈ)€!—t¤,F ddÿã“l8Ÿ–$ëMSGÇÒþ¿AcŸÑ)m ʵÏISFq§øÉÇ?t‡sY490¥ ±ôŠÅœ“qÆ%AmHš}+-GIº+wªSXqñ™ª±Û:Íݵ¡Å%ÊpT«ü‹s2G“›ûL¿?YÖ%£†E³cĺöÜðì9JE`Ô—,é;‹y«óW²‘”ô0, ®‹R ›³4©tÇZ òbåÖÂ0a­Ã9ª ÑýŸO€mæ hþ¬Z±í9–nJ(;7¬“š‘i9gcóªõ”ËÀWÛÎ0%1r­n˜ÅiV ÷3çØ‰Ï‡Á c×~ÐM—@NG½+’¸¨”Ï©_®™—y”T:NÖOôÀÌr²UJãYuêhÁ>fŠO-W^}3¯ö†I#ð4½Á½Fn€Æñ%èDŽfR¿hì¬À Ua¸-•°~|A¨¡?ª^¦‘]K ]ÇN‘öÇêôùÀ‹ŸEÇDé±¥cS|^Ks5ÖTå0²[ŸFÆßf%®hr#šP2C«> ©¶3›0[Y½–©C}-ž™ÏP_ËëÄ.ƒ'ñzpøbÏ%\ïEgfŸ2ð°‘vI ÿî:„ïsœ‡•^ p‚ýð‘Éš¬md %§ÄàöÉŒO]/V.±YÉÚ¢Ë(þžKǵFÅI{Þ]~»ã ‰¹a¢ýoKç«Ø“òÜ›õ·¥ÿOÎ’ÆuöÁwlxË  ¿P;ÔZÃr|ýÒú'6Hãcpâ³³KØŒ×3Ö¤*O7Žj€C€°ªZâ‰<è’Ž6Ê6»éÖ_³ÕPÓÞÉBß³‚–Ðñ:¦ÁÀ[$ Oè&“AÖ2$bxȱôÆ5VW†þHÛ#w‚ö95ÝluÞØç½x%<Ì¡Ñp':›•¼ ãmñ£ÊÙAe—|½óÁƒP§ŸDïlzòù,0ã÷iž°ÏŒîò!O² LJ¦¨™úbóK™N“øÑ\‰²và†Êñ¾B–I.g÷÷XY[¾o+ym3“ŸœÎ((湤ººhóhÓ7Îú_Þ¢s6äÒÇ•ÃÁ¤=Ê)¹’ª¯ª@LýGòê1$Un‹ëÖK•ÿŒÖvåØî}Åý\5Ô_1•/ÛH‰j¥ Ò@§¼/$O÷ÔÀ¨íÒf U© ½­£ <½ ˆšMY õûêÐÛ~5à ›¼å¥z@ä IPÕÀh¦Ê~ˆ xH»§2 Ù|Œ9”l,ÄH‹Ǹ”€ïÀsáèk¸ÑIRý¢E«™))¢_qj¨êƒ3¢—Ðn§~t”ÈÉÕ²„ø)KæÜºË)(3%e¹óÓ¥¾jÊÄbà¦6êsgaC›E`æLÝÕ v“KV'åÂe ˜EêEXÊá°Û”Z$Ú'[Çøw‰xt››­Ïž?,IÈ¢WGXVj·¦Ó?0 K°ëßèq,œ˜Ã†¾/7ϰ®v1-4ÙBða“¬B„ ´hÎŒ`]æJ_PJò†J»Þ³®’3 OÌ£ö£nHõ¼/2¹A‹Ù󕶤 CéÊZ+[â™yf³:•ˆDùmEÔÜ»ú¶lÀÔIÉu|%f÷•_ (%åßìçòzÿµç#ý*OJÉÂÅf&¿2øB%â·ÂlÂÙÓvTMfËùœÜ«€Õ¦$<º`tµÉ&F‡iuL.•«‚ÓIÓ0âWØb¬›L©Tßê€*>j޲)—rCí‹w'5ùò¾°ô L}ÂYC²w«BQtÉMqÃIvËi¨Ž”Àa )µ‰\¾1#gÿ$8»£-ÃåB Ù¢«ŸE¥«flG¸òÎßã³É§µÑU#*.Ò[W„¨–¥+£j Ãj—™ð¢"âœ5k½&F؆I,X®ŠÞ=Gâ8Öéºû*ÊL¸£Ö£é#¦ó ?HÖðƒ¼€$¶ôT·kN;†‡¹Ìì.šo1®ŽŸ“\æ”'X6"Lw u«0Ò'×z*¦†a?ã9ÆCªY—Æû’Ö1…Ú94Pê=ÕÙ‰“f+€fd°ÈâôƒúahœÙ_Éz$ä@©œ?ı‘¨Pˆ,ééõ„ài•I‹Ý#ùÞ¦Ò°Û faWF“q¯Ï "e(œåW'ª7%+rÔ2¥ªzU½(ÕhrÂ’ˆ<Ä®hþë—HjH‘7pä’àß(!"Ro.RÝxåé±!aqYy§Ÿ, ¢¾ÉP´gjÔ%ÕþJqC5hÞlò$S8;¼UW¬_“r]ë•Gw±Ë WÎ6Ìhœá.ØÙæ:%M*? ¶Bë±yÃf郱-¬|Ç(aÞ1rƒ>ÿ{xcÌÿý×Õù{šÒQ“ZziSxÖ´dçöhFÙÏG¼Ü~»®5[±-Me”¿|­üż!Î%þLô–±º#=ç×C†PdÈg ?ðDØžíÕWN ™èû½|aÇ[½ýªX{ùö‰_ÑC±HsÁîé‡Ҫ|¥Æs½(߃‚n^z…Î>A™bŒNh(’ÐúB$/Ƀäcš×hÙ’Ñôi.¾‘‹l¼ÿ¹ÿ%‹ý¯žÈßÊD"ˆþŸ(¶Iè0åÁ¿#å×X2øðé`:¿çVÛœ·„4ʺыW¤—ò­3·¶¼ïÔ¤e*—EhFéÿ¸Ìëïž™3¦AšÛAWŸ§D´O{댷ÆJi)¤AˆF•¿äþ)ÞëqŠw† aœÐmfy‚Ó@°úõPchÞä¡Ü‹‡D ³ŠlD’4ØŠš”VÇÄ~œs%»zj¼á)Òñ{cÉi¾_SHËK¿È·±š 9 (® åMȆ¿„_KÂZI±/6o¿ƒêFMƒ„S–E_iM(LÔÿzç+ÎëÜkÐr·´ †GÈlÖ1xÖ$PÄëMíà%w27Câ„ÎÍŠ109 ʧÓ0m½ ½ÊP£Á;mb$Ñ L»Ø¢é0KÖ~KZ6U¶™ªè˜\8„¶•Ký˽߾ ×ÅÖ¡­XÚýÎuwÁ˰̻ÿM­•1G`q ·÷º_ó]D_=}ôŸùßÿØÓendstream endobj 483 0 obj 5070 endobj 487 0 obj <> stream xœÍ\YoÇ•~Wô#˜'ÝÄž®­»Ë@ìÄA$q&æ`2ˆ )J”`q1%ÙRŸ:kê劊3ÀÀ0Ev×zÎWg¯þþdèÝÉÿñ¿Ï®ýÇŸ§“«7†“«Gß?røò„ÿyv}òÅYià|yÒç!»“³¨§;™üÉb?ø“³ëG=Ì]‚ÿÿvö»Ò#8ÛñÏcétvYþª;‡ßv®ÏyŽùðyçêNýá žÙÊ‹?w§!¸~&»/o¼Ïå¥môGºûÃˈ¿îø_—Q|*mâá7](£…_Á›ßÃÒ&Dßç9c7XÌ´Ù—´‚œÇÃ7ÝéXžzøŸÎ—_’wØá¬›#öúKçië-±Nyï§aè'—3‘àuYkœËÀáp[¶v_þLeó‹Š©ÌïÒáUõ¦L{¸¤¹Ý0ã³gekç¥×Û.žwÞÄñð†;j½. !4€ÿáïçåõ˜Ë¸úlŽ[Æ„¿æocšÊóáÛRÃ9êÂóÒèôC€Óˆ3”N°‰…nÔ„w—×…ØÀ¨YÆ( æ„M^ÀŸÏŒ®Xb( §Ã×À`àCady8áÃ;Ãø:Õw¥w!p#¸d€§ _íú–ýL¦É#-Ljû?§7ÌûK˜ÅúBÉÿÙÐD`†uWÎ †üxø¶ë„ ÎÓ hN4€˜ËʤÍKYÇ­òÞN]èÓ‡¶ø¬ 09`_\=Ò~Ü0fàaH“ K ',F…=ÐüšÏHx„c3ŒBH¸kóœ\¨ÓóÊÚrvùðÝ0Œº<ƒ´Î7•ûæ×wJ %Y›Oˆåé-¯++`j@ à— ªÚE×F|aàäö9÷.eÒ úØ­LwÑù‘fú0Ôá±É„[V ^VÄÕs|OK\“"¼K›¸Pbã!/Û.§ÙÿL„=¼†Q2îëšÎ&ˆ7î·ˆ¿l7[këIÆ 1{)ÏDÀ 7jXž‹8ï¥òo2”º+MáüŒ65~ –aÈ gN+öd}D}Њ) 1ÌF¬Ä"Á¢áop™Q \°hÕu½ê¼#øÁ ¼àŽH²‡06ô!+ÆÌAbÈ”…[ôß6›¥=ïhÁ@¦2ñªK ¸±Dû¡K9gj¼303 ÷‘…Áò⮦áÔÖ.é¼À‘½Ðµ `¶‘!F´XŠ·X…þ`QxÃý(lô%MðñRðð¸6¾ÀmD‹Ü5Œú÷.’™QY SCPËÇ«bE¨K47Œ±d8¿NÀ:©LÜ ‚i_f1 ý‘Ös\£šæ~žwE3ÅÉá6>WëªéÌ2F9F:Í"ä³™´ˆZ tA°U`ÝÉit¦åmeSª‚ü²‘O-éxª¨Î5´\½$EJ»o…Y#Høú`é†Ä6‚=©±õ-W—ˆï*Æî ¿‘uz†ª•¶ÀÖN¨¶à¹‘Tº¢wŸVÑÎbè˜ *oD³ül!®ÞÂkÒP[zt º²;ØH&xÛjn¶ ¬‰…"nN3c;,Ïz*fÀc%>’V Öuys×€ã}w "jv~6è%êqÈBκ·mÍŠ2u2ÈkÚ¹ì@¥ˆ÷blKßFÝâÁœÒRÔš´bîBÈ #ù™Œ3Ü2Ù`„m<AVVé³GÐ5ðyVY-trlÙ)m0vtõ)bc#àŸ(^Ö©›Ê¥é´'¥Égåÿ'¥=bj2Ê'e)–ÐoÅr˜¶òš -\OD¤Þ#ë½qlŽ'EeP#†-n˜Ûʺ¥' άU_+Õ ²À9å7òlÏ®Ó ò¶ÁØ ˜á‡tiÅ_£úæAŸ)’à𕇿„÷äÉ䤧ŒVq5*=1£B$AØ`õy݈‘[䯋ÎnãIŠª‰›Ix]T™‹Ÿ\Í;F„•x`†LY¼—*ñò NZ£K ¸#rÀˆ·ªÙ§ÀUÆa`YœÔk–§†(´P+äžôpÙN­Q•Ö Úv,Æ©uª­-_ùÍ:¯¼‹e¥àÎ &|ó°+ôÛž? S¼‘VªÝ©ôù%úN-d´!æÃ–áu!GýfC„¡ÂÔLhüŒžc-3hÒìHSW5ÞHµvÕ CA£8©÷óºÚ÷–Ï$ç&læúˆa 9È)»' ¶üS VŠëçgpÂ…郃ƒü 5럇¿•½LhìaCz}Z{©_Õ‡×úðy}x£ßlõ¹Õ‡7ö ÊCˆleŠ8»Li9ìkñ4óõ©,HË3™÷[ø©X¸¬ËÊ’E*ï_Zë„Þçł彯ïßãYýh³7[ÓTôÝo"eIë]^5k¯ÜE$ÅГFi>´¿8 ®Ø¶SZF>Ê(‰5ÜotÅ_ÕAÎôá70 Eúë5Ó½ÞÚðÓÊÁJÚï¶á]£x°+g~h(k<ÐïOçÕ¯@u±uÑÚæ¶Ï+©^nrü¼¶½Ü„åÝ*ùãÆ¡~¡õ1!±&?¹=ÏŽ·~ šò‘ *ú„³†ü4Wï͸xhåÀ~G2JW‹'oc_d®Á3 _ö”âæk'­<|l­ Q\·Ô*í~ ÿäÃÿ––§2ÎØ ¨jž h> ÕŽ3–ÕKŽV¢ª•ÌÆ°/­™´†A!Ê%Æ¿)¨žáU›÷ù¶ƒ¹ÁuvÜ'L&cüg®5ÓŸÃÜV®6^O9ÜÎnBe–‰qú„@Ƙäz›Ö{lÌnŸñNÎÐùÑ5¦¸OóQ¨a„ej¡fúátieò)Ë‘5ΛSkŸ 7ØØ ML!Qk W^GK¨ÚLÝ ^rˆàÏÑ­’ˆÍ¢ª­õ” ±gÎLdEбNµÇfEMŒTh¶ãÈÑnã'`»h¨©v1«}Þ¤•ªÿ©‘ T TØ 0j5H9ÒÂoƒ`BOf‘5!ð6ð-Ñâ«øø]˜€xhÂZcFYÚð® 4  Šqƒ™Â> ÓF û¬c“er#žk|¡‰›,Á<¶+„è‚×Ð&ÉL:¨?Ô?†hf1X†“Ã}˜üô¢,-‰œÇbäÖ¢|ó5MØÆ; 84(Ë<ª9H A¢m3J3Œº‡å†, ƒ&½Õv®¢PòxB}IؘVç5 mÆŒZšÐyDZ ΣNšZƒ0Mƒ ²‰¯*WÎ*¹¿&ÇÄ:­ŠPb5¼”Eˆs#ÈÚ×g\•X˜³"ÑŒ¨YFºŠTi†¸ó¾÷ÕàMZ>‚#ÍQ³"Y.¶1•åßkâh+ÅÈù”‰Î;d¢Ê9î鳫ƒõÕ³‡¼ÞK¡7í¶ 0r4°%¤i-„RS×äà9#ÀúH á.çUÏŠ “f;ïL±è Õÿ»3Û KVéDhþùíQ$hp±Ñ´˜¸/N¬tVuG"e¢º®ý•bÍaøZks¨zu#·ƒRóBŒlæø]•,Ÿ™x²qW y9Õ´M¤;Ê~ÙêÍÊõP)÷nP©5;°çV~Ià›~¹µòdJ(ª)g̸gœÆ¤O¬ÂÈ4Q¦]Ó–%2ýÌ`Ûr› ªO†;TxÂÑ%@ }ŒY±QŠìFaN!ì^À÷í=·#ñ­:Äݯ .SÔ|~Í9pÍÞ,²Ì#9Ìjì@=•KÕBYT J¶ð¶Ep=T¥ª]#Ý5-­,¹S0H.ºt}ˆIií“Q\ððÄú™=û@P³ñ¤Ó|¹hǵ˶ä#7 ö®ñ:ÛÅ/礶áÏYcv Q¼( 4?tù"¯åé`ò”¦Û]§yíVršl‘)ÖY(V#T>—$crìç­)úÔÖ(y©ùÙ7Ð=ñb¥ÀÔ£’E•©PPKÏ õVkZWÜ ~î5¢Ö8Ô™kšy2uµµr- ”ýäÅx6úW.+§æ­õQðêv´5Æy¼VÈ6âÚ³åxÐG=ÛL ¶Å*¤ð1TìÛjlìj£eÁ!OÿœËÛFSedËíÈ\B2€àrÃCŒh¢ô¼'u~·t›™C‹Pª·ðR¸P'¯2ìE´(V#±¼TÚ—…J\ë6® $}‰¨æ’æ"¨ƒ–e`‘ö¨5j@ˆ¬VDLΖ‡Uq̇DR×iäx‚ Á,#Å/V•´§­E‰«É¾Q²ÂcN7¦[Y¹ðoŽ8\¸5µ¦Wºß(q[—W¦Ã/yZÕ."ŠÀ]{Ë“1 `’ Ë£i!P[Ýf¤ðwê+E=T—ljìYcLiUɦBy™¾6qTbïauKV ´èƒ\Ìl1S­6/Ž3¹šCPvDÙ‹hyȱϾµ ÀêÆ•X“ª¤¦èéèz–©Ù¯öÈu8*¼¦~òMõPhoiìlèZd+[HÑ]íÖ}S…”ûô)´çCjÓhÛ€¨¨ Œ¦< *µïDÅÔ$Uå/U=‹Gö¶ÀZ;W}n™‹¾³¥ˆkш7ÐL²E7X…ÙÄÇÖy–jû`êdK›åS±ÎíD9l˜¨Å€7UÄ|×™d&¥ÙFÈÞC¢óôOÓ/˜¾é¶³Lv)a{^Ï+›Ê ‹œKllS- ”à&˜¢#c.D;ÜϬÃÈ^ÇÖøÿ¥ÕÄ7˜÷Ä8à‘Ñ"&ŠîHcÝ`eëu Ê“˜‰snM"­,;¬3ªåu¿m"7A’JÝòÒÔç ø«šÖêâ!e| îš|¬WX*ÒÃNHLj¬÷œJž±†Q6Ü)ªY×ìb_“Ó¼ùVÃlñz3cŸ²‰™qc¬,ì°„ËÖÒ×r÷ÕðË‹–fªðŠAV³]Ó ½h•û`Ç(–ɧ<‰;0°¦):lÞ'çŠÔˆ ®¸cc„Xx9l~ð ›/ÃøHåqC„’Û»ú°y¦2çè)_Mq¹2ÃñêÌ5s^#”©âáÝP„pÁ90«ŒT&({z7 n"!<{Žû ýf7R°LêF®¾ŸF—g ½ÌP^Ðldbê燶­ ðJWe^ÑVæàêªdü8¾„Ãî¦LÅØó¼wf 7ð4x7†$D£XÏöDEº9+ÍòhšZšÁâ?o‰É0k?gëyðš˜hc¤×¹UøMLåÐ/ŸqY«Ø³ˆŠÛ-hŽJEŽÖrð}•f‹Â©ôS •83ÐÖßò=¬X_0i‚„ügä2úk溟f^×"}Þ;¹UülÝÑjÂ%&ÎȾDº;g’FP¢‚y³kÈs0×­­m¡ l`k ÂÅuüC-p†¢5—n m¸ÎÓ]ý ë!«ODî4’r!%U"Ê….„Ù*”®Ò;ê¡·d1\܈v-®„016“¥Q霎ס”ýŠ=º©&¥–vÀJ ¸Í]cJt –º:²ÒAq³ee“èÁÒy•ð±~ZeK·ïÅÑ®[Ì5×g¦ÝÒCYJ-—vÔµ «’!1ÅFý:Îç’š„oÉä„P¥à=Äü1¼Ë%ÍF£Û{­áV/júÔ\·ä‰ì^*:Àn1a+oqé~¥'Ðäâ»]ý2)m®ºöšƒ ¯—Ð$ã¶™tAs¢ý¢äÞqiÑm™êû÷-yÇ­£§µù/:¾jùNà@úÕ}ËE„vÇ‹L–~ëUZEBµnßô/f•9üˆÞ?ut”eª‰ðÿ¶ýX„´–‡š/ Isho&'/þî*þ@·ù‚Kn…j‚ ¤-s]ëŸØ;ù? ä˸GcrEwߤçM6–5b^ 'Ø×¬¯¨«5˜Kâ~'×þi}»¶ìjÔFpŒZTÚfú Èvå$?›¦ÊŠü°ø:-e»Ý~½Xt›Õk4ñèçÕŠ?èµZa5G…gÕH3BËÒ-5f$ØS2€™P'‚š­L×ß?y´!õT*‘ê•©hì±…9w³÷‚C3§¼ï6€þ±û’xŸ>4–’7mI›š»»*UÍè+$ìÑZÕ¢`M˜ßÉàˆ6Ú'Ššn´±KpŽé-R@ H‡/4Ë9)‚äZÕœZUPª­> =¿êhTÿ¿Él‚"o·ñ¶‰G¹O·øjY€æ;§e¾sqx·Žc戤\E3×Iƒ÷Ö`³:Ô{˸ÚÖJðPÕªú¨`p¼5<.ý±ã¥cxËÀµöSUCûY Íì~`Ë”Ü*q"¬h’ —,DÇnÜCo>Bó¯V5:‡èx¾bã½æd4ƒOUÏG?~ÀIÿóµÚäͶòKÁ   e²n´\ƒËÑÉUü@Å0-¯H‰M•¦†MÚšú´O:IýÇ =Çï&ŸÜU]é8êÖsŠZò5/‚„Q+ä* ¹PmáIó7x6`J˜òF;ŠÕ±Ÿçè§âÌGÚÒÃÍš´uŒ– D)@ý}ž-ÿ-"²1ïýº\ÃR9rlB¢DŽ v<³,rí)ú1mê%óîÇ/4èà6Œ³uÍ /nÞ+ÿ‰.¶ëN?=ºåÈãZ|[àÁ­j9 8‰n…áøÇ‡Ž¶ÐfÙ-{PpËm|°‚h –W„^~J6Ø¢Ê~еØ¢§{Õ^}=•oCa[+¥øØlZob»h™Ø®†zRÈT&ûyG_®`Um è0óu¡¦–ñ-©”ñœ½}&Ñ—gþ³ü÷O?7l6endstream endobj 488 0 obj 5395 endobj 492 0 obj <> stream xœÝ\YÅ~w,å/Ì›ï¸í®¥·HyH"D„,8J¤‰±Ç#Û3Æ ÄüúÔYëTuõ½×†ä!`¦»º–s¾³Ÿšo/úÎ]ôðÿÿÑ‹;÷ÿ6]\¿¾Ó_\ßùöŽÃ—ü¿G/.~÷ .=é–~qžÜ¡/ÝÅä/¦»Þ_ì>ƒçŸï.=™ã²û^;|ýEýÛôïŸÒ0x=Îû}Ü}šœ?ú>šÓÛ™VÅÅŠ÷òÓg­‡HŸû1ý²¤õVsŽv¦Ú™üîËýa¤ómNì>«‡‡i63òsÞ§ÿ÷ƒ?&j;o©‡©ë§%QüÁSyÙ0ò ¯¡ï&·,4÷ñt'ñÃî-ìí5¬ðÑþ0øq÷M"Ú“4f™»ÞÅÝ›DÖ§0æ1<ëq—0äž½LÿéúÞõ3Íó&™{¤Æ]øýyø81â&»L|‘Ló9YÞºÝ-®±û=l± à i(lœaŸîéu~óë=S+ΖZÞB¬tL^ø›´¯ö\>Î>ìòÃâsþéM~ýºõ͵>ü!?üj§OÏߒߨüÃl¿³ŸO†> £eѽþÜ•‹s7ŒB©7ÊŒ§ÄJŒ…õãì ΋CÖñÓO«!De Èó˜ÄçKß(Ãîûü90ô9ý‹hSèæ‹ƒ i[ S`[:D⣄²[Àr÷*ÁÁ‡àNÿ‰Ðw_§I t:ÖLw3J‘ø1¼¼Nƒ~Hƒï¥‰ÆžE„h| àH¢¬ÏTz½€eÓ8òpç ÏáÓG\Á ŸÑú~²›×IW‡òæPö8@KŸH¹(oáDqIïçÝÃD=øiqŽ F -4-9â6àÙËòƒe,«ØÜ4õÑ$?¼ÉpK0Î ŸÈ3G$½aÂöC4øæG‡ø¼1#‡¼D“!6,3QXú-d„]âǤ 3 °ïÒ€1¢Rº"ÖGå |óŒ)-«\ƒ'NÞš‰øgѯÁOøiÁì²2¹…§>%¢§_'Ðú(fFÀpRXÛ|¬«ÛaCkÃ’ÿICkŒê  æ h¾›çµºÕÉa¦W@q-/BKÂYÜ S¹{i‰ï€„7°]@‚+•xþ `¶,ƒ£1ׂj1J! däÀ)áÓ±‚-zô€`ÏèÁ³ÜÒ±vB”Â>ÀÌ%A]rkí_ð… ¨ÊJLn̿۟†ƒPmP½Ñn°Ñ_è’ʬ§pÍôsÉ‚Ù, Dgy¿”ÕóØvPdéýV¨TBö&VÀ[â³PÕZ‰T §Zƒ•·}WAò¼ðb[½!Ì,1ÄS[=; 6Lqr *‘Ù@Ny[}© *ÍáÃb‹Ö²w…X»æHƒ+`I;¨N·.9.Dãªðt0É´(ìÄžrˆ,LPDçñ4O}S/JHP¹ÁV­ßi’™ÁƬÜTše(¥g°+¸^“7D¸Ós© ­½Ï5”ÍK:;2Â"c†Zš •>w~*ˆ«–©§„Þq#ËnF ššEŸ) ô]•«à¹0t^5¡½²¹×Òšf>ÄQÁ_‡$!äw¯s ¨¥jUè"åÑŠ(jJP5lmÖ_³Ê¢PQXx"J®ïdÓmÈÚA„èཤ–ÞOÜÆÁ`¤†wµ!vâ"7TiÊa)cóÆßËïgÄöÚÐñ¤G’ÂJÎóm³`êUžLà'.ž`ŠøMqÖÀY®t€Â[¯Jƒ?0^Ñýý â0LvCkG; #¾9oåâÖÑ:üVÝ 8Li¬Ðlq®²b= £ýÜ»)Km+)¾Ó0išë §oë¬:k†íø3Ä¥pÚ_ !bʵ\¡V^朴ízX§Ç¨¤=ghDJÞº·‰Ö<Ú÷˜ ,œÎÿiq‡O}w"Ùº{µŽÇ0+seÜžSùZÞòTyœ+Ú!„F;/’‡ÖÜJ¹,{Öå~+^û#µú2¸T¶U¬¥ÄK]fŸŽÐH hÉ[™—uR…e&ç\EUWyu™mcߥÀ7$Û’.ÙiRÚv[é„D€-°c‘¨ücvpå0[yîÿ‡ö’yIª ¨9*dûÒ”˵z*š5?+t6 ò£&TlÉö^K¾ÄTs9âÌE¬Î§¸\Ý2"þvvÉnº_ÅÄèXŸ²6ê"=C ¤Ê`å;×9D׈µ íÏ]xƒ >õE`T ºš™u­ú°qK+ËèDé;ç;sr¬ ‘ÅîÍ⨌WK¨ÍŸàž‹ÒŒ( ëð3C½Öˆl½«„ø¦¦ò~GSI3ª§Ð:¶Ð@(]*®'÷%'掻æÂ.óÐ#†} ý2ÆÂñ+­ý<k’JPm’?YÀzhˤ}C1É+;£ XMI˜Á™C窚X²qVA¾‘ã×KòÞžp½¡ï@—õ¦WF‡¿Õ蟼†ÃîvÏÖ?ŽøûVeÌ9ßÌþ<ØX'û¶§yÚÒ² O¤xpQ¿ûŠè ¥iŽ˜_¥)îí)½i“¾¢ ßË‘8ç…À‰')?÷«€Vlt¡ìy¬Qbb÷Ü´©ÜùµÇ›ø¶sÆjI AÎéû½g…£Và#¿*z¬·JÊænÈÖX ±tðœ™0vÔ=óžêÒ¡£yÌB´pYIÜ6ñ† c‘9n´Ï¨L#ÍY Hmš]P0Ðç4j-\Dªˆj–/ÛN›â3V¬Ç@õÑ‚IJ=5€( Ãv7¢ï°éòžÞx*lPâïI“tÖBMóžuô×-|µ/ës¬…ªF·ìúŸ\¸¯ïi†…Üɯ³µ­" Œ—4QÈi¢qC7–7³TL \5é ‰ÞŒ)]KPB€Â–+íŸ]U!˜L'S¶ ¬A ïy>î×§¨¯«`ãþ¾¬…Ó2‚ÑhÎÕ=Úƒ» $¶ÙP9 ¿¯i[T3ö»4ØŒ6P¢º‚W}ªtm3çW;–⫽üvíaòá”™k5°Þ j€‹UÍŸMÎ)ÈŸÊÁ\ëò®îMã8 ¨2ÏïàfÞ²s`Z8>z>4êÌ ¨ß6¬~&ä]£»­`Ÿ¾òÃüØ#T¹v7ƃ{{lÆY‡Ô}h°ì9½[Ìu7ÛšüìÚË­ì¡gJVÇv¾MvøR©,Y°­9´¼ÚœBÑRõ·¡ ¥óU¡8oôÃuÒO|á\{ãË:±>0†ðèë·#a>5»ææ&ûLûŒV ¢\Ǭ!HØhß>ÙŽZs7úP%ÁÛh>¥ï~úÞÏ_y“¼/Á½ït…Æ“C Hö’$gÍý}`¶ë.÷ù–i͙˓®µÀÝivX&¬‡Ÿmx3$‰DˆR­ˆI·f#‰{êJ† !ÍáŽ]«p©wir:Òaæ§Up#_ý(s&.0ôޤȔæ3æFjÇ- ¹Á}ç£Æè²9.-VXh7/kSjqÔ‹ù…·[§ÌƒPî}L„íäÓ•þ¯Å’ aÝÊŒ–°ùNîhîQ3Ä ™ØõÒ0g-Cp œ¨mB‹3›êÿn=Ÿ);Š;϶ñgU0ýŒŽô²§KÊ㦂…/Í#JÞÿ=p© ÖàmûyÁ8}Xþçdâ~³VXIkâÄ™纱máÄåzgðð±¯zÿ³>ªú.}ÈÞŠû| 'és{ëíFŠÚÃ]ˆyáYîŠÒ÷PNŒ¿zôíÊë ­Šè©Rš;¾ª«¨ Mù WQajàžk™Ïf c)ÙŠPö%œÌˆÎ©:¨K(”…ù¡QØÌš½ÝEBñÖ}ª2Ü*Åeô3^‰q¶‘MÅNëõµÞ0Sl[]çÙôÃàè…ÿ]w‹àÅîQYõü«;p4É䞭Л‹%f[”:7:›]tÿPbØÕ(Ë?ÒÓ*$ƒBIb­ ­Šü:\o¨|B#t[̹©z ·”fÎ9qËöÁˆÈºçiîËë*œ$¥ã®K:ÇÚ#¬&Ö^JaÚÊX¿h{øIq+Hþ–@u²2ÜöIÔµ8Uÿ*Mñò‚ö5sѼ¸¹Êà³±qõÄüJõbU(E÷‰4&×±&u+ýjœÝ貯c…奿hnEûêú£ÞŠ73úýìÌ R3Qy²é‚H±šKËÆ×9'Í:6ÍM´Å÷A]Hñc³‚$±OñWX%U¬ÅݰTÆP«¥ÕÍG–ºY§Œ¬Q1e~òö˜²<*¹QäÐ6ŽZ5°§N4×Ç‘pk/b•AqëB›Þþª‘õÕ‰_¶®˜pø»©9Gyoí9¬Ñ6n…¸LÖ¼@N|9q‹œn"Í›ÕpZŒ÷¾´HšbÊWå sE.øÀBÏö@ªxEÀw¢ãŠ® Ý͵&ܼ :É8o”7YÇåŽ~£—fi†¡´YZXÛL“½Ú¦ãø>Yœ³z#˜"¥[Q²¸6ú=6ítP÷³Ûë_•PgU› žgINiDÎÀ¢îêHÝi«ýǘd<ýá3ˆÝøš²éé Ñ¦Z®xÞ7H¯H·_Âùb—r¢ÕÛ,½î—%28_‘-4'˜ó`Êz¿×WªÀV‹…/kj—¦¶™ÑVúmLÆŸTY]ç¦î“vCÃÉF0ÓòQ÷œÓ 6QU£y©‚-š[]Ÿ—ú0–´Âf/-níñ˜Ï¾òØXé[s NsaOé^ùÐM9ñŒþ¶ƒ½é4°®” µÁÌ'ü"ígJ¢ÍrÌ/Tßo7÷àÉÛåÛm!]êßÞ]YÿáËåtÚAú6p¾êÖ/u@d'äçëSŸ‰s?~pç¯éŸÿÜqØendstream endobj 493 0 obj 4612 endobj 497 0 obj <> stream xœÍ\YoÇÎ3á±ÈKvs4}Í‘ ±åD |È6“8± „"%’°xH$}ýúÔÙ]=3Ë%¥À ‘»3}V}utU5_¯ÚÆ­Zü'¿Î÷}ѯN®÷ÚÕÉÞë=G/Wòëè|õÁ4pž4c;ºÕÁË=îéV½_õ!6­_œï}½7iÝnÒ·…ÁÙ¾ÍØA§ƒchøáf?®Ÿl\3ŽC×Úøõ³Í¾_àó6ûúâ‹Í~®iÛ~=ÀØ ¼ñ~„—¶ÑWyíîןˆ7òå1Œâ´‰ë?oŒB\?Å7ãh¢oÆa¤n¸˜Or³xãØ­¿ÜìwðÔûõ?7>$ï¨ÃÁfˆÔë«ç­+›;;ß—­ï‡¶éÝ82Xt꣋°)ß$ç¸N°'çû¦‹8fßôöý^÷‡õùXÖÁ÷ë+X7Làaϯ¨{;öëCø`Ñi}ƒë‹aÐ{? ðÅáÖ÷lrpn}–ûpo7øÜ²EâÁJ½KɢÑóä}ëúžZö¡éRZÿO»0¸.­OyI_–|M‡¦O#°<7}ƒ¼k“³›ËñÚ½ ²J\ÛEû—7&èB+Ž]pñœ;5}?æ­Ë vëØ§õs¯†:p-tð÷~ûõú*Øj"® xÔ¥ÅÐGàØ…¾þŸyÄ£àù%>ÄÕtë÷°!,)}µ­¯ácpë#èdJ4ÎáYŠˆÞáƒcl Ð8uÌ NËK\” Äý#§{…-†Òã¿'^N~x ©òÑÁÞç{¯WØN¢¿›a|>«ŽtÀ€šäƒ§{ž~²ºysûbïÑ?VnïÑüñÁ³á×ÓÇ«_í}ôtõùµ xÓ€FÖ4wÒgû‚Sç›îXp›a¨lx×ï#Á{ n¨ØÖ)A¸«s>0aWÈVüJë—„€Q´ÐCáÑæøÄpœ#øY™Ú@5Ø÷„~¡› Àë‘ÀšNÑép´hÇ:Üà†>­"qn}‡tß÷ ¸`ïû€»”ƵÝsè7Ò y‡ôñeâ·z•à|gB¥c^PÛô…-&"Ú•Ò'Càbãq÷¡È&.bdˆÃ’VÔ¥ùd×g¤ß=éÔ‰èáaÃ19á—L".dPŠd7Op©Š9Ëá¶íÄ•FE‡¶U+Šˆ,Þó1“J”Q@ fpl·ÀdêbqY(žØv(…2e„|"KŸ‚-ÕLA½( NKцdR÷q×)RŸyd62!Y°#üÂEú1Ìt°\¶ XŒ5¿Ä-íôX$ôqí D„1œv'Æ]YA¹Í4F…•ßÑ:„d4¨H´XHð«ó’¡îÇ–¦3ð¸,B½=‘³øU3áÿ–Ÿáö‡žÄ\ÀÉD`luÍ^Ó]Z»æ‘uíD:_ƒ épÊ-Ü¥!ÅÇwUZÊçžuü{(-ÙøJ+Äžˆp¨¬¹¤˜¼`£:Ví3»¿˜Ú‚ hGo©Iá‘ò0Cãë£M@Šº_„4³Õ®’ÖÎUZ¥¶ Y|Qh¡‹ÙO¸ÓñýH¾…u^tä¬òÄˣ秂.0ã^Ñ%¬—íûMð²h¡v\ÿۡ鋊)L×%ìÓ—§yQbæZ^¯¿ÛkO~²N“»ñ´­X¤Ìè¯k¦ÚcUò4µà‰¶Zk,¥èîæ"ì ð=‘ÃÊß³AÙ‰ K%”ÙY$²kçúO2Õ‚Ùû×½?-H1¢ ðô)µþž~`wõ9>¿e'·ÖŸ¤6Kî .õXíZ~{È{¢ÁŽ•‹›OLZƒ(†îbT ½b‚ÕÆ fÌú [äbQëw#YÀÊöy~ƒ#"4ÿ9ãEmì.‹Ðužë–;^iSï¦ð¤‡àŒéQ+.+šª¼ &Eæ~B½9d’Œ Ù„L(Ú;Õ{~äáð¸‹ça>É?Eýˆüw¤ðºDm¡$Ë7¬¨Ñ Ìð5&š4ë0\ äÍb Ó]@æHÃR„¨+" BÛx@E¨"C9Žr’»çÈN`HùnhÓ,„ŸJðd÷ÛÔõ¸éƒCLá˜iˆ2ãûNcQœY ì\ã:ƒÆEùì]’ Ä\æ•¢Ê ‚ý²Œz…ƺ53ìN5ô¡³#½W:™÷w†–Ê–Jé-Â@Áqˆ).x¤7ˆ J©õÐZŸpÖðwuÀØÅJv\»lsqls[t®¬ùmu§[\˜ºÔ;B"€Ý­mµ¼_Ù) »ÊNââÖªS\1ÉÁy’ݣꪼ)AÑlÇõIóhëÙU4[Zô3U«¹Nƒ 娑Ծõ/ÞÛnÚ(jÔÔrÓ®Nõxq«?&Ë<µÊ£'ÕE…H+NTVŠ .=Z´EÕže·(‚¨âÎeí"_™3ª8ÑÕƒÕ¶ƒ¨æ×¡”H-Úù`Ìñd@¬É›êô|¶ñjCQ)%J ¥î³™Æ‡x²r=aò›oàû³2æDOÖJë ±Œâ ¨6ÇSH‹ŽbÒ£G†›$ þIFÌŸ6Ér`ƒÿ’Ÿaj¡eÒ?f+¾ä ä¯Óœ>µ¥¦Õ<‚†Ÿáœ¬6¾@udÕ„õ„㿆×à!¾E¶ñPoÈì=eK'JÐF¾ØMõ â,ì~0þ,×uPpvà‹µÆ1¸fUÚº™¨\3¬†HéZ¯‘n·“$G!ØsîÊ äÈê`Ém+l¾f$Q²ÁYHÑX.Š ;=}Çq¸å®^ÀŸ„¯)Jƒs°»UÔBí»I”—iRì2Þ Õ”éñ¨G² OD)ÁE«¨ªî™œO¦öÏuÀ`Éq–/Õ¾çBìÔ̪x#ÛAf–{sM85ŽŒöL†cÝ:Ô²wÀ½~B š9?XÒ£oÑo•24šœqZ8TNN†Ç£z\ÂLª'bfXûz?xöµ`׿W¯8Öó¢X#çúlš?=*°ou–IøŠa?šê-­jý5þ82\‚¯A Ä0î{­?¸Ý·@t´Á-NÕçm~y]Å•`‰ª^3‹òû23¶lYíÚµå‰]£>|³4æM~xš?/~Qú—uÛ%éû‚ÈÃòðvi0{{Îä‡fuÒó/Ç)aê­-ϼÓ϶“>e§‰{&÷Kc!v(Ë#Xpíò¯²ä§ùá³òð[!3èUDŽow¢¦bæÂûÉ«:š©‚oÉ)_.=,}Ž…ƒCª‰a²dó)ß,¡æÚnnT3æC$ºDVg 9P(Ô‚°››Òö´Z¿~üÃL<mÃ~a0íVL¾ó`ƒ)R7—éWÖŠ¨ôïÂÓË¥éßl@zS°üjiye¦›%d¾‘5QvË „Bj£¯“•ã}àA˜êZSgôv8apð@udõdzÜåã%MóÙ"8.–twå7)8Î,ŸÕYm‘ì×ùáí’2y³ÄñbXšŠ²¨ºÁ˜j$åÿNÞ‘S—¶¥e›¾_îh ¼q)Å{9°Âm£©ÈþX†ÙÕôji³?V3™Jt’õ÷6ä %Yü`Cνÿ§âõ?ÀÂò'_ oñ8æ,F-FTM–‡Ï+Ã*¿_Ä÷‹êÝå îrO.ªI ÃٚÖð`Pö|†.D³.„:#ÔiC«¥úJÕÔ9~¾­¾²/Ñó'T1Øö@òÇð1&Øóˆ XŒ”À)ÜäʤÀÙcÉ QåRm‰Ñm1m,Œþÿ=¦]¥sbìóÁïʈrm §É@˜Z á˜$vì•ãiÀCóQ‰üÚ‘bÏÅw‘ß3ºcU¬µR§ \ÅL6qV;Ÿï— eà5»9%NYjôú¸¬‡°âÙeìçsøcnq—ª8ïPvíp¾*ŽS硱Nª[ÆY¦6&ä/a; §›0ºc"FÚ)WDªù𹦥)õ ¼ŸÚ3þ·„$Ÿ›cÌ] øepü†ó§ÀF¤Öøô¤®…Ê^9þ˜<ˆdÍËhºYB]ðrIK¥*.8“Ì ÖÐÜŒ½âÜ&î¨/Ø›Du/â†æ¢ºËs̵‹˜3¥ŒAt#è‘fL¹nák5dB‹ï4ïzWÜ0 jÜ—£ƒTAÉ“Ù0ÁeÈRu¨v¾¨:×;cJì‰QÛ~”¶5ëÇ ÀÝ*Rmê]rF«ogEÕØoK*-9ôÖ3ÎZYʘÈ<`Ï6ucA×uäG3è`t—¿¢ÿÑ£ŒŽ¶„ ›ÜSù™ò«iÐ2ꙺE³µ=y/oôZؼ‹/ª¯cÊÁéNð\å‡&c²4oµò¬ %îk^sÁ ªíRâÔ¯IÞp­ª”Ú]j´ž2 w‘m#pˆ$d¦d+³)”WT8Poc稼íÞvUÒ½m– jÎ2oÄÀ³$!Î6%¢›#¶Òᘠ޵^Oãĸ’ •5R½+¥V~=K PŠmšSÐâ"RövžÏ/¨O?l­>fòv®3)[¥¨ŠmK}Ie!$#f½­¬V°„jHu—±À øy›ê…ls_0¿%Õªk6eš—]LÔ{fÉEž˜Æe kº&àÏz¡í¦‡ƒ*÷Fín&å}œ=Á; ®[¼ Å.cÖo-õX€Ÿó*pºMê¶X9:ï¶rͳ^Ì—,\>©¼«ª&9½—6î²åŽFñÖŽæ5®â¨1‰jU'÷%Tà§šÈÚGQl‹.W¾».CZ ~w:Õu$k¨µÈ()1ÙíYª#ð|¬|D¹Ø#Í–¿¸«ø¸Ð©kr,S‹ðMRÏS9RUæ¶zg¤lf1ûjýyK»áâ¯òpg•J¥>g*¹¢”·WA©8\÷ô®äâ„Ò$e®h [EÔ$¡É^¼A™ ,ðÞŽ{¨Å)|Dá¤|èˆCv®´þ㗽Ͼh^ 4îJm}Í!…ê[cYMó|jM…JUÎd*¾a¨YÝÅiÅ7ßv‰ïä<™;ÏÔ IþBŠä\ìåä‚ÙÖÊêkâÝãILΛªÿÚ¡r'ضú¦k3·‰M‹ ©JÝ͵' Ëš9˜Z“mê¹ÀÆ—PÖý3^›Z›2^UÓ%ÈÊ)¤2Ú*ï’Ãf!ôÁ•Qž4 þ6 ¼} ÿ¼ú~ÿ¦¼ú#CFKá§™õñ¢NuÉêÎ@ž"è!×\KÚ"~Vñ3fgN&ºbD©H‹¢ŽTÝ\|¸VoµØêÅNa“Sš(í©Z™Å\θhpyŸîàz×Å$½ËqXà\â.¢ˆ¬ –ŠP73¶™×'‡wŒ B#BîwÈYÄœs)ùÖ|¥ï`C·Â£å ì¨~í0»ìaÛbñXxJ§$úè8–¹|_š¯×ÓÉ4ÒÞp zÇPïžÏïKË:¶ÝÁ§¯\»…»•Q ¡%/Àù°Ö*Á‰Šž»ZQê×g§H¦A¼G Ž7áô^þâÃmÕJ.óë~ü]îcu"•ÕÚ‹j—¿ÚH|Þü*pÙgÒ Fm+™=$øiØò¥ðïÔe'©–{M½¹ñL¤Fi-ŸD¬ÛbVõ 1;”NOЫWU:ñßEÒl‚Y2òD󤽭PIS7\ûŠu};=¾ähP³uPÇ‘ÃûÀ‚6Tk—ßHû*_dn—jæ6{åúó4?'’"ê¨Ô“?ÜUòir𚜹ô¶EI Î#]·æ´·óŽŽ¬tþÇ‹ôû§ù ]‚3÷s>“œ£3•NŸnøeûv7Õbü¾\c½ß ŸñàYÊ=ìÃbÆôöžiÜaÈX\ä].¸2'B63|ã`¢þÉ&žxä«ÉjèÎc`;Z¾üy&±Tf%% D¶ÍŒ–CµÕ•qHŠ—2»O¦qœ׆Ž: 7&·N®E[N4™&|ÌekZçhܶ»ýjÕ#ì¤1tƺTC{ìö‰9+ûßq‰ÉŸp¬’rú ³qc¿ÍÂÉôwj2£›è¯}¾÷fugëendstream endobj 498 0 obj 5091 endobj 502 0 obj <> stream xœÍ\k“µýîäGì7OOÓzôC¤H•˜@ Lb/) *»~¬Ø;f× ö¿îKºêVÏì‚)(—í™–Z«£sºšŽºÖuð‡ÿüêևǣ³Ë[ÝÑÙ­n,<âÿ¿:ºw+8Ÿ´¡ æèøÙ-zÓöht¾íìÑñ«[ßn¦¦ß´åÿ·ãÚ0 ›Ïš­Ý|ѸÍÝÆõm× ýæïñÛýf뼋ßÇÍ£f;Àw»ùk³õ›cøßú>=hì÷Çÿˆƒ0VÂ÷cÛMqÇObß!öiš*n¹dëºv4!P…]¬ð,v98(ìí›8XììëøŸ<Œ5׆à6'ñ…sØ“ø¬Ÿâ@§üB¬lb­ÉN V0±J7|÷C,Ž-lí¢Ùö›§0†ŽZ†1½òIJ¹Ì¾ŽOC¬ë7ãß±‹? ðà |¸­@e!³y.5Ρɰ(À~±È% z÷tŠo¾#Èïq[00«‹òœ¼Æ´#¹Ð¡Ä~ʳ†Ò7…†£°ŸÃ€ —P>™Y‹CëCüŒ³åv"° h5„Þ@E)Íõ`S”Ä4m~lú¸t“Ga¿Œ#¸*º"Ã(@àa `xf[ãÚ~4ÃK„À*ßmDZÄ;˜²Åy^ÂWƒíⲤ‡,ölz¿y½ÁØãM=JË»¡À¬·}ÙXŽxB=52|›FTœ‘,FÕHŠõJ.­ p§û$üð¬@}˜hr,_ïfòÅ…v†0— ¨Æ$ùwPB´yª±¹Ì§ ŸÂ:œfÜðù(¬Ø ñÉ ö#í }Ÿä3`áJŸñ.zJÕ úª8§€h‡sþ».¥pÆÊ˜ ä+}Ó £¡‹+ê‚^a@gÐ#P.Ö5NoDW×·6©„»ÆED3É8Mãöe¨(ÒW`•bAœl )}Gsˆey»¨bZÙ`B¬8ÁŽ™JÀNqf±_PF‹a‹0F C‘€F,‰ê.+ Rž T\ƒ’G\õ^Plý‚k •PÇ1w®¦,6s>òJÚ)!xÈpJây5H 'ø¬ï^ƒ3ʺV>7“£-s7=»—¶íç0 ðæ8ÙK©¢©5ƒ%|×È»-Pî”mÐ&|wk´cQCÙͧqvK£ü è±—(ìX#«7ÚÉš|q˜WBÁ[¹±d,ò<ƒ”‘E³.)ŒÕ›$Æ@ŒW² /¡0$baÚÿO|íÛø÷ŸlRm“i¤yþ;~û>þ½ @—öè³8ÕŒ,Uf ‘ºý#™ÆŠ äy¯“¤ö7>Ä¥„Bþ(¬l±Éûb{£3.sß¼w´ qǤ+ö˜áVdÒ1pg1"Ï,®—ø—ø5šA3 b{ÔŒK;%ëºJždý×’¾• l£D˜>i­0Z4j+‘-Š 4,*LI›%«x"+ëï%䲄wdÝ8m⤠Ӈu˜ÆGZˆ]î4c;"±”X²KØðàn ›Ñ„Í4 G ø<Ñý@2²FÙJ2¼ŠJ"áâ|€hÞ›}ƒÆVÔ:€ÈÓôð*¿öý `’õaIo¼"ƒemfÍL•‰5 sõ´QÅ–ÇáÇø·ý܃àÅ-^A{Aåz-œdŠV¦MÞ–jÂõÔ™À#)½yÈpòä8B»Ð¾ìPORœRŸ 2îb]w:7ÃèLw’ëZŸ ¡LHÐ`Ë6\›­è§,öÇ€Ë8ß =6ðy ÷»# uìr`¸b¶¤Ñ÷kºEû&K”dÝÓÛ9‰ÞÍ<ÂÒ«S$03Èiþ¥2þ8oì@v¸XFI΀ÛñþKÆñY‹?°•Û³š¡vhàYa<0PÞàèG‘¢µ†:ôqƒ~Tdx瘴°ûIš”™êÝn „zÛðKuïညˆ/ƒZa_,ó`l™,ÌObfÔfRAÿCŠ‚ )•Î)ËŠH±›/®k¾do=)b3^3¡¡3ý*aþ]òà —I Û”å](@ÏzI[„€sÜC…WžŒO&†±Œ21µ,“âñË]»°Gï]Á»¶ÌÿÓr¡•auÂwŇëɵ_*AËnòf¿]OqžiŸHªã•HiDßNÞè0‡ÆÀñ"Ö.ˆE;S¾#¼=ϘÙ%5¬ì¨sf¾n˜³þ~{VZ$/Ù‹Ls;­ÀmϺ¦U+ù-‚2@Ä Ç A@i$o¤PBC¸¯C”Ö#H©X ù¬!Ú«lÝñ44A›@Ù.*Pà÷Î*2ısï-‡qfô¼+B¿,øk†R/R\s´¨Ó´ÞÑL'9Ȇ2Ïü M/µ•ÄèpºÙ{Î+Ü“~5`…óµ-\Äh ¥¾ËzNƒU¦SÚñÖ×\½sÒP>ÍCæ®*Ù$¶/ *réƒù9pÆÞÜw¨<ÎÉWƒ.Êô@ØË¤¸y¬°D´K-%ï| ΠÏ([å5õFN[ß:«K0O~É’'Y-ï1Ó—œ¡‚FâäX®¬ÒŽ#`äbáZª"„ËÕ203vµ»ÈÃ=Ozº0ÈØñC!ȼ†:ÑüH°žr![â¥k*~ÔLØd -ܦøzò¶Ç¹–Ët¢¼ð—Ùž¡ãŽ)q4#¶ì¾è=›Ë™bÓBO¤ÄqF‰™ $+Ö7aÉ© ¥Dsâ­,—£%‰ïZÚ+pÐÚË“áüߌ­«™—÷&GftV˜Eðu2ˆ¹} —"—ExéëÒæYu¶K ~@â² ëJñ5mÑj R®8³¼›Îµ.?ýÆÇ3Åó£~šÃO¦f Tưt%à:aåã‹•UÅTœ¦ÒeÜ‘ÐgNBR â&"è7ZQ%DQ%Á-4Ætèù³c˜3ãœ%²4¡ôÂ'gZèz&Ä-:ñA ûóѰ …§vš"æ…}Elˆ5çäjK舗Ȋ¸²||2rKßBqvýkѰ:ÖŠ9sQ¸ –rJÆwá²ïhD:.v©{îÔ"+u(”eƒ_7ƒÀÇ–‚à°ÁÖÜ1n(2;ûžÝPÖ•,¨’ïN$ª¢b³:ì/’xŒø"ú &“b2æ‘;ò_L†ü‰Î3˜ø¨Ïʇ`»Ê58A Œ}¹j»< 䱇=û*äp>7ô(ï%ù–O*6¢¸åìIˆÚØÔEŠx9}j£öƺz8p5ýŒyÙ ß‹;° R%6Œl .d!s&ˆåaŽ >ÔîµÜÿ <$¬¸×ŽqzÇç>ú«•®Æ’Ö|Òøâ–›9²ëcg=f>éYŸ§´¶r ÌsNdn:Pb¾>›ÿO*ƺôšašª&€CD{½´Ûß6|î?ª1´U=²Ê• ¥ÓF%rh=ÍJK¬.Ž™=l¶`MÆNÕ€ Ó]?ƒ ‚Ä1ý»zÄÖòºgu¡+Q¨€ñû®æH†„Îd€æ_}~ëøÎõYZ¸õ"Üò‘d£EKC§ÄA\0N>j•¶sBøØ˜@Zy¼H¤[ e †ØK‘8›oSe_¿À<¿ÙÆõ检x\Ôè#ÈI@ßt›‰Va³7tÊä}‘ò'¹üÓTþ·\þU.ןÊ_ê f/RþTÅyú-Žþumô¹Í"h^©ùä4ñ¦ÓŽøì£w“ÇEh éðöÝ,ŒKËðË1ð'Óa.Ž^þKòŒ¶|vú4/žv¬ÓÛnöð´¶ ³Í×ð~‚ÌTÌ5Â{¤–ù±e;…‰×5Lœ3¤ºÃË—_z[È'Ÿ‡¨s¼}èÙéÞ÷Òĉ^hçóôP­ÓeçýTþM.?Nä‡wÓÃ/òÃû<¦°ù8ÑÅ\ôÛEEùøuƃzú è^>>Êuoϱƒ=½oæ¹.vîdìØôÊ÷@V~²Š€º¬‰¿8“…ú-ˆëDKF#COFwQCîµæ³´/ŠÑÉ2ÂiJ µúßT8æ8¿ôuHe¦=äà‘n0°kó«àëý¨M]ïNªgù«t§Vˆœž0\7ÊõG•üïj¹–»Ü²Tf™zž~¦Õƒí8:d©ÅWŒs/ü,#©N3w¯AÝÏ«¨›óê×Óahÿ9[Á/’ÙƒÐY D¥C¾Û¤"“>ª¼ÑÄå9AíÚšp®L®aÓ0TÏÊ—Õ…!%Ęª¬ðŸrOÅ„å%Uõ™<-¬¢bÔ¹¾W7nnk©veÅ*ç¢dµ¢ÎÌ4·¢צ˜«bJBÌý¥Øï†õŠ{ôcôëX4b·ßlmqa¶½f&-ˆY «I|ðÎÔïzãV…þº†ŒË2 ÷Èÿ…vxÞ"]~¡K”~’-Îôð[X+»BÓ✓"‘%#"±“ß&dšÚ¦f~’ª›šÂA~hÝ0;)~Áöɇ¬öfÌQ…µÕ»,ÂÌxˆߟ—_R|»¶÷ßÖôÆ®6‘ì5W­Û¢ß 0áÌ—œmò«êÂ%2ì5ôNµP®lb ›Á¦ÅñÒ¦-„Yáû‹o9°Š lÌ’Æ>|8ß:?XÊEÿc‹}.¨› ScÚ~„›vmcÛÞâ³­1vl¼nÒµÖN]Ä«¦kÍœĶ®ópÄ#¯ãQ5­yfÎ[ ZÛh™I¿[ÓN£(ê_˜Íûìð""6Ý£szÛ ¾vÑÕu"ï»’#3æJ9¿+îdP”£x*g‚ȼy¬]¦ÁÊq‡=§/¥D¨b/"ó)ŸñŒNÖåÄšnE Äý**ŽUrÖÊ,ø¿ô÷>åNû^r§9ÏŠÌÕ¤Y:6ŠUF™J¢•FÊ󠾈XË­/.õÕ ç"*ï‡/¯®&†Ýô8^Þ+Î:i˜|JŽ(Í«tZÆãŸ±`* °©ÌÜàôΔ´R¼Òs•”8>’^ æ0OQ{uh#‡‰7=ËþˆÃö’^ËÂBC¿ÅEá]F-^ž%Ä{œ!dLðYIéCét±5Ð{é ryÚ˧ŽcËͳL’$·øå)\­éÂÔ±Þ£Axà¶uJ‘zÁ4g§ÙrÃk8œä“¯‘ Jxá=þó"kªØp‡.{€§\‰˜µ–’øæ§Fib=ˆ×ˆ÷Ú#>Ö‰ÿ:ò7#ìu½ÏÉUö—"–Îm›õQc«-¥ì[Ķ+ٔߵ~ÓCÀݦÌIãLŠk\öàtCEWN •/o€œL¯ÉúàBi”N Db»u"¡+–rŽ(G‘€¥(#¸vÜœ¼Ê[¹Þñ7^xÒ™1ƒVr«×ÓEYÓJHÑä‹\éòˆ‘Ë­U„üFD‡× oòr|º¦ )õ”Õå¶Â©èÍ)§þ0pa\+Û§ëuž¥ÌIYóE–3ßUÞÒIŽ˜m´ž“χ×5e™®-§3^keô餻L’½“®>’ Jr+2ËRúÍX½ÆQ¹””æv}W»é††¢6¼©«“jÉbÊI2lôe&Ò¦q?T®„ãŠü/'¾£Î²ÝSæ%4=©[s”ä³zqÉQqjL©„)™ÇªØæ™ˆtšáVRl˜ðž«YîÁ f·~Ê;°sÝUÆõ$6O½fÉÍ~0ëý/q醮¶ÄÍ·—?hz¾Å,×ÕìJÔT~bÂÛ¶öËžSi8ž(ør6üôÿÔÃ>]êMX˜užSEæ·Þ”a®'¤°þåò+$b¶ÛBeGÛza[ ÝA¯§¸)åñ—&âV†ARÝzWl%º«fTÊ5øG† ]l"úM”*ŸJ>Y&Ê—r ©êTA\ÝÁ™L“â¦Õ %êúzÚ´ÃÓ„Kžªr[8?B3Úáß+Q×= ~³JïIÙ6”é¼~šÒ¶Ë+ Ø›ŒÎöë¼’¦ó3r´¥×)ß@åß2!‡™xÉ•¿^³Ø …­9xJ«(ò=¡ÉÜôZ,{w׸Ï!›sx{›û;-XrfìË:)wQæ¼Ôy³»}t£˜ðÓøá‹N§¢>møÇ0r`@§‡utïN-ù€ºß“³°BXhXiõÆK/iq+wßÀä„b–Öò°cu*Ÿ†œ)™M¬XÁ±‡(НÏWþ¡ûѶù*QßÌf•òÙUE¥»hÂk4(?c²~±‰¹ÍüZI Ðj ж,‚R®(-/ØÿJ‰}¦õ”Õç«çå|äq£³ð5bñŸþÁ¯6=Ë’VA;"9‰iñzÝ¢<¬Ö,²2ä¤x‹ `˜Þ Õç$çåFûüÒ¾­u_Ö¤l¯ÎpTÀ?ÏU ùe>|Y;?­:ÂÒÞ?¾õ¯øçÿâÚJ;endstream endobj 503 0 obj 5115 endobj 507 0 obj <> stream xœÍ[Ys·~gùG°*Þq¼“Á5‡ó”ÄRY)Çq$¦âXÖ‰R™\R$E‰ùõA_@cË+J*åòŠ‹ÁàèþúëØ÷»]kv;øÿ=<ÝùÝóa÷ør§Û=Þy¿cðá.ÿsxºûǽØÁØØÒNÝdv÷ÞìЛfw°»ƒómgw÷Nw^®¦&¬l^íý9¾áŒ~Ãv¾úøÒÞQìø§fíWß5¦¦ÑO«?4võc³¶«=hÒ¬åÁófíœi»nXqì6>±vŠu§ŸÒ8òº]ýGü¶á/߯Qlˆ}üêiãâhÎùÕ3xò=|Ä>ÎÛv'| ó—Ôí ­`šúÕ‹fÝÇVkWÿllü#Xƒ/ì5£Ç·~j,mÝzëq;w×®k3M$Ã8îê >6ðq?âÆ¬ÞÉ×Õ|¼K]Žãæ¦:á{ÔûM³¶k;ã±;5¾»‰Œýêu|n@`N½t”Ÿåç›ôüC~~šŠA¹ñ¢ÖcvîÎr¯“Û'ÙäÆKeŒZV¿¬RStàÆ+œ…°ŸŸÊ¾£?½á-iý¥áÍÅ{›B:üèÕ¸6ôõïwö¾zIêy JÈ …Õ57¢LQ=ÝøYÅK8áùRÄSã¥Ì^ˆÐ[U:ã®û©±”`´ è(Ö£ ™G=ÍÏóüÇåK8“eòúÒN%­å\J µsPËE²¬¬€ýôàF×§FïBw—Æ›mRÀ¥õÛ¥ä¶û¥‘¼Î­4ÂNÖý؀ŵZ“Hå”—ïp\ÚáIc[>¸JDó2Í÷|ý:lìq?¾ø°ðñ‘£§}^â+ÚÓ dq^ƒñ¦†¸MÆÎðf<Ô9'£üò@_im,)é.Ϋ;)”)p/0 jtÞEÇÀ>1m©S:–Ü),VRH…¹. àG”„¶ó»ëDa0¡¸Z~¨Zö?ç5»Ê²¸ñkfۆ/Üצf)7ÙÜŸmj ¹g_(li¹Õá?Ôöù6»05¾ra6k´M­ÂT{[Õf¾Ï1Af "!§¶Z唓¼ÿƒâuFñ›гr•1Ÿë×uDÁ›®ÚCUÇ™Bïò¶ö¾ cîv_²û’ fF:9,0SOÕZrÜ–ÜI QÜl–Œ ÍóšÒ>Õ|’eµÜVÔ_ÆD5|Ø/¬k9üEÖ_UK²î¶ôœ…E5¥-·< ÄÙs¥tDS¥x”ËTJÓ>ósºËo’{ÇIö¾ÕqÊòJÎáçÕž¯²ãaçzYÓçi37ç¹^Ö<ÕAÍ2¯+—¿“¡­Á)kþ¼fŽˆÒ;[˜#i}¦Á•±Ó¼)Ulû©µãÌÏÍbòl”7â¼hï¥IÏíaÚîX–ÔS§¦GfDâ! ©=<ÄVkÚêʼrW~·µ}Îu _s˜:`„ß_åHŒ$fÛ[e~^@€Ã†GqX1.#„×5í=*Uo™5}!šÎKâ`æþÙè- ’íÜg‚Ÿc¤Q1|v!õë¡N‡{eúT <#³3ŽÈ÷}¸"¥¢~‰Æ÷ç~BYúAM|yÀÃ-ð®fVÿQIêf<"w üÍÀÚÏÀ«¥{Û’~õÚÕ š}ĤAS nB)-Âô}œA7šŽK»RÖQ(>Õ$ùºf•ÕÌ´•…¦%èÿ³2ƒ‡¯¿Ïe†Û²~ X*ƒZÆHPŒâÖW¹5ÏYµÃ€a¾4"4@ï6bÑ~Aµè¢–‹ûÄUàˆûäÈ:ŸëæØu€àQŸ®“¸VÞa\ Œì{Þ‹… MÜk‘Àæ6逗¿Á*‡Á"‰zãmêùš¶ GP,hØœkAL$¨×i=yeyd%sž}+!ƒku¸žËF?°ò] @¢'‘‚*´e‹1Ûà¹àìCÏ]Y4‹~Q7µÀ³ý¸úŽØyýOGð°Œ!ànYˆ´œ1k˜‡Šý:­,&üHðÇN0ïëÞø ®_æ”Q!^Ãã9ŠŒºŸ m4î·³´:ÞüFAÚŽò{ q¸&Ã6(¬¢ÒqçéÁyF"lÖŸ¡CöU½Lè¡Í•yÏy²ß3Fj’ úƒ»€ @ÜŸv.QÊ=¦8j'"3ä" u‰o(ÁÁ?àÝm±è‘¯Ã”qŽ \ M®„ÎWß`L8CkV˜a¤Å Ì2ñ•`RÛ/!WÇ9"± íøo°Äí‘vªä½áÛÀb(Wrn(*@ÎØW©‚+{¹þŽŠîkœ5YÜ:;g¼vž‚¿GñT4_B›l¾¬ÂþÀ/™Ä©¼%~IÜB8^{C€¹ŸGô]‡/²È5êø 3£+}Ú!»%P üe轡AˆOŽòŠJÏå»™»døNtkG"ÑÄI0Åî˜)Ñg¼Ë] 74±89Ÿ²5xoeÊw ôw½nÖÝ),°2­~mðJÓèÔã ¤¸dl_¬O´LBÅÂR(ޝò™GÈù¢Q—7?€“ÓóóSkq\}àèÕEÀ]Àzè¤%™3%  o´< %,gñä‰ùàë'=SàBü8¤kù¸QK…±âÙÜ`*î’ã¹ûb(”,ÙK]Ø9jÛ^Ôâ,̓-Œ<ÛDå à1ÅJÄû•ú>lÜx±ËØ)'#DQÂÈ£±£zÂï¾ã;³âV/º•èxdb+Céo‹(Iü3,Ñ(”"ÄÖ>ÅaËó ·DZ"V×+³VS]DæÄZpúhåÞá¸íÍùÞB âmëÔuµ1†haˆ ÝÛ`L¤¹)jÝÄu÷x²k­;®²kM?ÅE™ÅQ:îD^MVe 7‡vpÜÈ1[ üŠs”7ÄåX »6†!½ë¹Xˆk 6–G0Ê)†¥ÖÑDíEÅ“{ƒU(ðøWgqwÈc¶z3j5g-Es]ëáƒå³Åá$WãzŠ”ÅylÀ©iŲOA’àØØS¢t+a4øU¥@ìC%P¬è`ö…І–Ó<¥›Ó…ßÚ¡ô€q.Š r„ EÙ– ÂvTÈEÞÊE¸-¼U"¯‘(㺠 Ð¾OøCÍr…äG 9í®+ž+Åûcò¾/§ ëµÂ)¨LügvIx/ÓÜ‹yV†›žŸ',X ¦pVæÎ\êÍŽüZʾpèÄWÔBNÁŽUÑ$qI »ÎOÓÖže^+ÍÆ”Üq üü˜r-H×Ñðm™]:*õÝ‘Û)ê$T™6ê (z@t£´Oö–éåv³ycsÐÄ;ÌPTC`û”%Ñ*ÖfjY±{*+\[´uá,Õ›0tÌjT3¾¡1+¬H‰æ ±nÈ™çTw:P„ÆŒmH&ç(RÖxä·QEGÊ_YãùB™*Ñ»^ÀYŽmû´õJŽm0€Œ“v “(s+Ú`‹E]çHà-8*>øTnnîh ¾”¯òÇ¡ò5VŠ‚‚\¬'#®µ”s JÞ+ï•=eªr-CYFé’ísg®6@H¡À'èé\æ—tã°ˆj}iü`¦Ë1'Kð2ù2C3!Uû’âç~#hkû’~$jÅuåüÀùŒAû-K@V¥Cµ´,­ý˜‹9^PÝß–5òI*¦)ÐÉQSbW°5c’›Yfà]2ˆäíUúÍõ ¤‚EœE$¤ØjzãâM3–…JAÎi‹RåJOù »¤"º’“EŒõ|¿¨DòU >Õ Æà˜2rˆ˜³qQŠÒ@üÿj|i7ÞR¤¤ðiÀXêžõ#­•pЗ4ìн‡[¼”Ô}’š FN\?sN„«°ŒÓœ+O­êîÑ‘ìu$°ú¦þûÓw¸LGÑù×KÞ_¾ù$7)Bt¯éÓWt‹Ð6r¯ n<Áe§aì¿ú²Ó©f¬åÑùUS9¸?¯õ¼É?p¬þl!ß—P7sõû‰=§\Èw3ó¾éUù!èvIâ˜÷ÜmÊ—ðç˜ hG÷ÖH¤¢N-Ò«Úö‹kö÷½¼œo¢¼ÏÏ?Ô†¯^^®^®9Óº=To]–)w’÷í<ÙÛù[üïß{‘±Iendstream endobj 508 0 obj 4017 endobj 512 0 obj <> stream xœµ[Y“Ç~Çüˆ ëAÓ‚iº®>á‡$[„ÃbÆ€…eå…EZ(úï®<+«YlIAì0S]GVV_fe{ԵüÿÓ—×n}=^^ëŽN¯}{ÍáÃ#þïéË£?çÁå–vê&wtüütGƒ?Bl;tüòÚƒÝØ¤]ÛøÝ„ÿï‡qj§±ß}Ùìýî«&ìn7!µ]×§ÝŸó¯Ï›}ˆ!ÿvÇÍ>î¾nö.wñ»»ùï^³ïó#×»/š_‡~÷7íöU†<{Ê};M#­ãàkœvwš‘ÇàÔŸy`qúGÇÍsÞn,¦¡íƼ·ã“¼ØGhuŒ£í¸ÉµÁíC×nšhÀƒLÖî5|œÁÇûfŸº©í\Ú݇߿‡.7ºÌ˜)ìþ¿†¿žÃ£ ø8…—?`ûº‡ÝÃ|⛼¡iÌÇݧeü^Ly¯ÌIÛÒøˆóƒdü™v}ž}—‰Ž»7Úø¢ŒVè­ÏÏÊó÷Úø¬4ž—E¿×ç«çÜø¶^‰ò.fR„œ¢ÆïªAËé߬Ñăbá€ÝàÚ1í]hS ç¹Ê€ÇÚøJÎ7â1QãÍ¿§ÚxQ†¿ÔÆ×¥ñ­6¾Yî®<‰'k»¾´»Fš²ªU’%„ž—A†ÒSelŠ[‘W™GiŽï\;þäaùùÖḁ̂˵sxS¶ñ«Üïþ-Y³ {7 mŸ5Þµ1Š„ü#ÛªK°.°v/j€þžÛ2-ð˜ÚᾃðÝîãüè~þûz:´–gùg,Ÿ&Ôñùd0ø=˜À×И§IØtYlŸù s]d#óõK’I\c(³èœÐe ó™áç«Æ°K<, 4Q'µ”>ͽß*‘³Yi0Ðo`¶¦6³› /ÒÄãN¡?HVß7)§@2÷­YuÁ>9æäQ<U°7+d'§£ùrù'zwß]â@vË`ïÌ:!‡e%‰·Z;·Õs‘,í†LA¯ì BêpžIqDÛeUȨ Ú6gÂQ†!Fé ’ÛêÜÑ`g™1k„£R„葓̉{¡ª"!m[ˆ›Ò!Þ_B×2H8þ}àXІM  ÐÓ,j_ÎÇv{2ƒJ.ì2á7ÆB<3"EäL½•CP¼ü59’²—„­¡Ó†<ª= ; DËT­JnH#Ú{>1ã,÷¼ùÚXUòà6T„³aºëÅÚïj­4f P`G*~µ1œ€±GQöúEk2BÖñ ¢íúuûÙvEÁȵ#ðA+x`{BóÕd©R‡',JYaE’Dü¢±ÝHâ"LávïoŽ%í¤÷EãÃ{`Þir´h#3R°u?6¹Pü˜s!Ãü_g•9ÅŸ¼@Ÿ5Å*Þª‚ÌœRv/<¸:’1Ø'Œ˜R¾Ðx8{¾vù9‘¤ öÃiJÝŽ:ÚZª,€½€f°BãñI2T,B36">QTÖ•ÙcæeË gC0ïZƒ¡ÍXz1`ɸo4A/è}µâàPµí”úXé0`e šàµ—ñí–Qt …öÏ£q¬:®ÆÁ³ Ý]ù܆Ql˜€ KŃ¿i‚€aUVà»tÃ$qƒôÛÆ¡édC‹)ºJqr$€þ G&„¸ÀïÊÒ†‘\)g0òœšÃ c¹V017£ŒÍVRt@Ëç~soJ!¯íœ²t™¥*_u 3D ÃÞ²–Ùˆ¥xžSJ ¶¬FOÉàƒáªÀY1DCÐQgp;·)ÅŸ%ïH ïiWÇ~wYÛ¢Y^À$Â…«qeŸª¸R¬$24YØD±çÀ†_ ºÊ5è6tý~Þ…ÛÜu~ ÷œ"°Ó€&íaÑ÷Í–žðÇâU?ÒÆ»¥ñ¶6Þ/_jã= ª×qäHöׯaÀD²ÆZbøà0QâË • sðR, ó,å*¼=¹ÚUX¦+¢Yœ}=ô¼FàšKKc»šÉßš…Ì]Ÿ0 :#bªO8s[§™‹3T5? K\$†Ññ AÔ”‰öi¸þišÙHã€jKÙj¿Õê•´Bè¶ÊúÞì2?¦íd‡ŸBI-…çü‰øÛ±x'šÊ©òh] aÁ…Pß³„wŠÌ+0˜|;»¬QcÓ͈ыµ ÄɃ¥8”“wÉ®²CÃ!HÓ´ÁÊÆÜú„—­~Fá‘çD ¢‡jùƒ©'Œ  8à@%Ç ü1©ÌPÜ“@IHÁÕ= yëµËyg/ðÎáÒº½à[–ƒÉ¹œáò ŸÐZ2âßhÖ´®ª&Îý”ÉÀÔ L8C2±¤tf×9bÿBäÌ&™‹¡WŒ®{±¶¯]umÄ7Z†’[6›ÏVN˧”U]Ôå#ºÚ³òE°–QMG²™žû•¿5% ?I•DXï¾™BàŸ[¡ò©– íe+/|•›>öâÔe"!£B ÒxWo—ÆûÚXyvy줖Êa-T^ªæ 2Øâ× Åð°¢Ç€ ¨»Yeµâ(]ÿ0—y9Ãåðóñ’Ôû¬2•kŽfÔÿò  ±â˜d{kœ¤ü&Ý*mÎBu!¶Õ¡Buˆ÷ñŽ(,oÈ9Uxð"^²ô’F[V96¹ßšWl€ÍMmÁ,Žûìä…i|ù´4ˆlЮk,wÉat£Û¥y!É[cÝ sßmy¼Sõ­=Órf<·«º}ï8ºš«i8¡û¹åˆp]²©0 ã±TÂÞž3WA— 3/4b¤ý×HP³Ó%^¼®MÕµw׫G4W°BIÛ8å;”AAßD}Tï'ñ£Vü„¸©DCwpTI©hJQèA¾T5au;à“#ã‰ë2á<á•*}Àlí%جÚ(ªXËòVÄÝ”÷Ѧ tåb_€Ì+*Œ2dð^cFµQ²Rô‹U¤aáØ(©'Ê¿„J"¹\k¨ƒ$ŽWºÅuþÂr!-zÕ~αÄTª%¹÷>¦©œ#ì•mEUïÓÜÒ¢m”ö™¤PþTƒ XoÙ„ñyÜ`Ì“¤ŸleLëJу‘`:®Ì`EÌø¬ VáÀ%ű‡ÉÔ´¹*47 ‰ àÞæAã—™ÕÜa÷Ç"”׋ôT PCê,Ȳu”V`‹D–¶GGJàÅ©CÝÙª¸¬ÃÚrB5@­¤ j…=Š‚v}íVWêJæ™|ª;rV±É¦Òª#WÛQ,´HÂF.½É¤ztóœF­„çŒÏJãՉʟ৚2!zšÔèšZ$.º…pµ*3E ]lM%\µ.ï*§PðÁy³,%0õ³·I8õ ~ÄŸ¾¢{›øZðsx«²)r«æÏšÑK[‹±ÔN2“æ/„~…Ê8aa­® AòqÍ@™)ávÛ+jºñö\v©]P$W@—ôÎëTÑz_î]$O´ô‡€;ªM+%% ›·òøƒï¶8nq©?¥%îÔ¼J©(!,¯Ü˜l]d²ŠY /l¨ü½Ü¹Z[Ý´µZûrRW¹8a¸äÚZ½ ç„MA‰‚h8ý²jɓе°ye¢ˆ\7¿ °þgÔ;#ö0kµkF£À8€oÿlbíÉ£8!_ã!¬: Õ´Œ¢À5Å}åéøª\æ³?ëk7Òê2Õà Ò¨P3ááÃ&вÍ@iøÃïà\aÓ7ó¿->\œ>bÍ]Å@÷çk€ð%y^?¶1š$tY}ÍêH=~uþ̃ `'n!Z1>oæÕº¯çŽšX4¦™ÖÁ‡‘Ó†£½ÕðàISU.½¶÷?yT»JížüϪ¹Âx'(¢œE•A”ÚÎ+`“[ËÕa†/+.å´vÒtør¬…þ 3 r=“?Zø(Ë;P`†)ã/’ÑÛŽQtýîøýÈö1‚T^È’ò­’¨úW•ÓàÆ¥qõµµórùöo}þ»µìÖ*§õaWbʾ’ê|×øQ JSAARÅ;ö3û<¹ÚyÆ^= ç8¤$†ÓÑðô[8ð·’›Èñ9¾ñ‘4@ç›…þú>€5_bŠ¿il« Qi†_Kµ„«èá¼è•;z•@2ù×d.Ðí²R˜4‹ª FcQ½£dÍÓMIã”ËgXûóãkÏÿþ Yêòìendstream endobj 513 0 obj 4111 endobj 517 0 obj <> stream xœí\YsÅ~w¨Ê_Ðwˆï0½ÍôJUX HP*àA–ŒQbYÆFþ}ú¬}zIY^¨¤\\Ý;ÓÓËé³|çë3|2ôîd€ü÷üêÁ›ŸM'O^>Nž<øþÛ'üçüêäÓÒÀùr¥Ÿ‡Ùœ~û€žt'“?™Bìrzõà«ÃÜ¥CìÒ7§(OgŸðCìç±J›}?çƒÉ|¢ÍÞ§Ìóxø¼;Žåª÷‡/;_¾$ïðÓ.G|ê‹ÎÓÒc¶K?º9ôi<9†¡ŸÜ<“¾-.áã)|<†gðqWz­‡Úø‡òQÆvîð~~çðqÍ]Å<Á$oÀïßvÇä‡~pépÔ¿,‹åîóÅózñZ/–îÒ0£øÿ¦W[~¡S/:½ø^$±´:tt®'GŸû BA%xZDù¸ìÝYÙñ—p¡È!(˜\*2 ÙäÒÙðçwpï ïà ›9yyÜL+¸ê@srò‡h £À“Ðê9í¬2Ž} .±D.ãcWu¡°[sQN7^3=ÒÚa/Šø°œùš14‡›?Æ©\zYuÚ|…` Ø l:nð„«}Ñd}޽ÏNŒë1Í DpÃÏH_0Ê…ªñChX¬w Y‰èf?q¨±üt84=rmEœ`þ¥‹k‚•G^‘õ-¿ê·úÄE•d½ j8ÓŸñ 6Èõbt7:/^ãèM· š£ÈæèÀÁQˆTeJã-“u¹ÏaÎ"ÑÆÊd~bŶ~ßÚèSµ€Û­ zÀñg±™°e-Îù>F™ÙÒŸAžu~} UAf?‘g“ †‰„¤-d?³›u7V#*™vÇÒbGªZƒ:á¯W0ø‚WnÄ Aersžþ3µ÷Efè^ËNº²¥eGçž·óÒKYƒŸ3Nú‚w"»S¹iÍ”à!<ÑVŒN­!û¹¨n%Èߤ2Ã…„ -i[KŒ§Á2ôyÞ–¡ô¾%ªÒ;¹ÄˆãçÉØâ˜»S{½jû¤K8V‰= ¢?Bh„fOñ¿r=áõGÖ‚~rÓå.Ì,ÏØïLý¨:iÆÇ5z|Hœ88aöeqÞŒý%Ì ´mš¼ª«òY DèºXq'±DhXKë¦öõ Ð݈†QÏb€€ú›pÏ¡¥¸\>z–TœE 뺠aBÀƧ&ó+ð¥ÚãøHm{ #>õhË´ái´<ôÚ<¤X0G†à#šêZ:‡?ˆÑè\.Ä À0yÔH­»º !M¨zýºJa×µ¼ÎEôjZ|ï=¾̇t†GAüáõX¥Q·ü­hæÇ©Ïe‹ˆ* y®ž(è"l€¨ò¤Qðh¹uäûÔ\Ýx2oC¹ós Û@Ç ³æ™Ævåâ“Æ ¨Ï†¬>áXƒê± _ñ;ïèÅjËS½øi½ø‘^ü¢"¾‚ó\š@€¸V¼2Ô@úñƒÓ7Vºl„U¦‚xð06ÒÒù’ x©Á²•OòÉÖÅ,˜<ý¤ÉšSòØä iþ}%Í—ýÿ¥©Ò zßß%Íÿ¾4¿\g²£³f.ñaÔ)¨® a¨yké"¼X‰-;þ¯‹°Z2ÊBE¸JzC¤@ÓFœ·˜I‚ãAÄ¥/‰ãámÀ‘¤y ¨60>t ù³d?`¾ôÿ!&Œ þÒDîS²)„G»KP.Ð M žk"ˆ«DlM“Më0M±ò˜z6’+> Ü‚htû8h¬ý¶ó¼f‘á”âÌ„)›$á)~4]$Òd¨$Œh.~× ÉKˆ:*ݨŸ×ìmÖ+›¸Š²M`ÉÙÇošé>åüHѦ¼”MÿH9¶Ï’{»!‘r!Í F«YŠ˜cÍÉ x¿"eD˜Ìª6ç sQ«Ï‰ÑsP|ægÌkö“Ö׿&)-ɰˆ{êË©Gƒ‰=’(„¬/š4V¸XÛ€Kß™Y5-&†˜ ® „Õ»„¯¤ Í:ˆo]÷u›{ZbòfO§p|§0™nV>‚_ÊÎgìäùðÇÒéä<¤òý4º“ž¡Ï9xü4ÌçŒÞ½lVrHùù˜ó¡øè#ØÛDÀ–”½L”Ñó¢!§ös©íh–\ žÜ…Þwø9ÍÝä€RŸ‡d{:‡žòÆd­>dî“@¢ÌÈ“ ñ#uÏôá­XQ‡vÃRT܈.uë°“-›¿Yî˜$èÔ2¯á$e’K§÷=<67þ¬ÒÔ0±KV}¥–Ö~iÜа{âIxÖ€6ãRºf'eÏÚ43øV¥¡gM[ÎrˆMôa’Z£û‰dÃÕߘ\¯>y®N¨Éÿĉ»÷x2wÑ:n¢ QG§½Û³9E%‰´!Q³1M¢xk¢÷è 7 ú…šˆ++"ˆÀªÔ˜_„$`*ÜèÓŠ©(!q˜·ÃEDtïat†ü|"…£ÍóRWÄsž[¨ÏJcBntõ”鮕æÛv*Ú$J3Åb~c6G»Ñ;i-¯uâdJ“•ªkøÄÖŽ“Ÿ9^p47Á­vrYÃŒU«˜%“˜@}Š8Àépƒïªž]ZLÅKl õ ÛN!¦©ÎwßÄ4""^Tx°U•ÛDܵŒRŒ£‚/ïœwÿºK$N;E9ì;áWL¹2*Œ¸á\ ÕÒ™C,ÕP€))T—#ºÈi#ñ(t(ÙŸb)˜Õ¨ƒm¬”™ÔI˜’‰ÞÖæd}Œr9f››"šãdÏÝÊ\Sž1³@ RloŸÝ®y–ê€bÕD˜á.árâBØT·r½5Š[”¬@‹’¾ Vi-ÕÛG9Œ%µa'ÖìHT.„¬ý $ÁÑ-MI¡·KG¤R‘ülÁ’PgèµÒ§|E[LŒNÞ…N­‡ûR…®iÛý ÷;à;zßû‘n©y p\;`âêš(¤–áâw¸Švøð<‹Ê’³Ï«B¦¥ëã|I­¥t'V8P…(Yzàs=ÞËç .jÊОÖóÙ1/I’š­‘“ ¤—–¥3OÄuô¤â¨-NÙ-ºX!CKoÀi’°¹§a¨V7d%³e¸7Ë Wg,bì1¹®òòMáPÕœ&Å`YW ¾¸~¹+ÊÃ+jµçGµßKô‰m\ 㬎°©”çm²¥ Á„&© ,imnŠ_› SÔ‚-ðsc-(dþ5L~{sKª¿žÆ|÷YMrVÆ'íE†Dì‚ 9¦`½à%Ãïòp­ž…Qðz‘±š}5èYw“MHœ *<ÎkÅ£ÉEõ]#˜¤%*Ï*e ¶ÀYEV l±ì(å†wes²â6ÔÙò0iÙÊ äGeaGÁ[Äß©4@`)ÚXFsÓæ¹o¨|­$ØÝ"¶ °Ê $·$ËQò3g¤õµm1%ŽÇ¿›|'Ÿp7Q/ÖÃí—´2`=)i È,ßÎ"ÀÇ@«IÚÐÒÌr›ÕÄy9£= ĽړhS¥;Û*m£~Ù¢õ…&Þ±yq‡¸7õiŽ„AQúf ¶òŸætž÷ÄÄ2Ù õ÷Áì!Ð!âv1#;ÈÄ à É_IZ†gS1ëYì}ô|£¾V¶YÊÛÌðF¬Šdר—BJ¦j©¨yƒÍ ¡æÿ=’¨õ“&7 qÔ( `”£s›_Êêõ†ü±ÙÒëÚÑ–±×´Fg K ¾õÉKcmÛ;p–bÒ¤ózòœ7€ß=!—§#ÖC¤Ã'Ý"Ú‹A>¦ÁèpcmÏ*æIkñ›âdRÛ»ê±Ikxµk_¿ôèU6µrþ¾Øu‰L·˜ ä8Ñ›ŠäTMò¹¥M ÖsÌÆq·=¬ÝwTuÉi;W•$¦dÐÙõ¾¤ž¤î­beÞ<¤Õ## gª–­án¾ØðægÎ íy÷µ:Ùúùµ¼`·xA¤|…“û†]o3É}¦lb0gªøæ×mî±­q ò~qcFæõ ÁˆüÖ/S ×Ôùf»¬‰‘z•8ì`rEÍ-gv]Cn¼ÅØOê-ö ¶¿î°{b˜Å9Œ>!3³M—šwÎŒLý®4ÓŠÙ?f ‹ì p5­7ÐŒ¿†LÅ0[WÆO°Æhò‚ò¨ ÒV;L­‰÷µ¨BëÒÄe½ÅزaÑ)èºÓnK^«º8FÑí[í–§q›±§<£Eýµ«–æ¬Á’,%§© WÝÀv±á‚áÜ:îYøù—”V¯µ÷¶ ¥ÝóroeQ·¿>W_䌔–Ñ‚¸ÛÎj†pÀBD]ØÖAT¾è澩KwÿfÛ¨ÛXm¾«“ãã16/€ÖÈb ¯˜¯¼óýϪãD:ÕAÀp`YÄÖ‘!ôîzNÒS£>öDÇ™£q¶ÆÊ¦*שſ –äŒeG"ò¥wNy£æA¦Ýzš»À«ð™¦îÅ/=KpäY”¼ƒS¶Õ¾Ò”pâMú/l/M(¶øu=+~÷OG^Õ *Ò‡„Š+רåYœ¥Tüº•‚Sìýà¶ ÆíÁ .L‰PªÜÙN2± çÞïèñëž­þÕÚ¯&2rT¢e´¾E-„Þ¢‹RÄPÄO¼RkN–½`ôg°N-½m£è%ã{¢–‰r¥©‘½ ‹WïØç‘R¼!¾_øEw_ˆqûe}qeÒÁݹ ܵ%Aa"ý»à«âqXÖ*oðKËdº7™3Òwí1 SI¹Ét¤·&ÙzcZûšP0ïÞ_#)ä5î ÓêÅ`!î¥aÁƒšÉ­s©Mw¶áÈj- ¿¢½û*÷½æƒ”€u¯Y±VúùÚ26CÏåÌÿb ­±||+¨1E*†çäèýÓ.ÿþ aå¾µendstream endobj 518 0 obj 4603 endobj 522 0 obj <> stream xœµ\Ys·~gT•¿ÀT´“ÒnשòƒËWl%±é²]v(J¢U¢HÙ¢d+¿>è h`0»+Ë.Eî €¯¿>f<íwæ´‡üûâùÉ_¿O/_žô§—'?ž¼yÊ¿.žŸþý,6p&^ÙÍýlNÏžœPOs:ÚÓÑù]oOÏžŸ|·™º°ÙuvcâïÿÞN½Ùõ&lþÑmýæ_ðßgÝÖìæyò󿫨öóÎmt[g'l÷~¼ô þ|/¹!¶s›B¯ûÝÖn¾7¾îܸëûq Ñ¾ˆ£QãxÕøÍ‡…Á§aóI~ÎgÝ4PŸ³4VìØÃmc'hJOý&Ÿ:…Í—ÝvØünÜÏá*°õ‡‹#CŸðúûÝÜÇ9ÄñÎR3œãƒŽûÿ÷ìÓ(Jcµ(}ˆŸ¢4ÏE ÎQj¡ ÜÐôºåÖû~7§[™y¦L­‹aáOhÃã~ÐùÍãøsÃÔý°¹²—ìGôyüÓÀ½qsÛÞĹ@ûW ‰çñ-ød䣌lñ~Ü<ë޼yòsgg87 ›G°G!v7;’±…ÆÎÌ(oxÒÓøó2KûVd ׯa—òì1ßünÀ*¢ö`£óøÈ8]уǴªyö›pg3½`™Ä™vX-˜­ q7‡öl•¨Ô£žv°θ³"ùkì>{’#=ç%ŒÚѲ/»$;›,YCã’ðnPsü$Ç`%| ¤X­>ÞvyŠ¿–ÉÀŒ·<åmü8Í0sØrì{GŒûùý&êÌŸâ ßwñ{ñâäPy@’;^üŽ·\?à™¼?ncë|,>OóQ‡ë.<75êOl S½Â¸ŽÛ¤u8kÀc˜…A\h…úâ¹| `l«¹Ìì:Ϩk0“'ðqÀ‡ÀÇ[x&4¥¹À^°ú‚@ív>ê4)¥ÛJr7¸AjÞµ2FùƒVcQ0|U–ÁÒZGЩYí¶-Ý>Ëc|’û[+ݧ'ìÔlÞ$µãS>ùâ”Ç3>£%@ÝbY n…y"‘¼O'ÚÍ0Ô„"ÄþøŸ(ÿ8%qəȤó èÅgÊÄ1ðúµ( à¸{`Rx÷Ü4¡6¦&´¥¾øüàùÜãC(ŠIQpl=ýùHd„ÇÄþIïõ¼äf9׬l®‡ÍpdÏ@8õ_-©ô)+bT4åa¶xBr o†¦îaxx[=yBG¼¢Ò9»`àõ9~€Óàæz‹B{ÏÍ'K"€~Ë6“9‹Šèv—Lî°l"2ÃaÒÇ“¬ÊSžÜU>ä_ @ñ!}C¸vÑuq´¯ pá‹æø ´T.5…š”`UÔ>@RR&Ĥ1ì\V“jI¨Ôj4>C‚€,U€Ù¸_‡&Û£Þ¢øÑ9_›¥¬ªð¨ ùX"×­‘“dŠä}xÕ%üÀÆ'i_#TàŠKÕH@S….ú<<ç 5=Q¼‹Gæ4 ˆ9™x(Ä-Åëiƒa_: lbè€6öað‹}ºÅ>‘¤$5‡Ãæê±Çðaj°³Á¡Sk|(r‹ŠË ŸÁ©T“¢ÃI\(nÓ`DéP.? ©¼Éƒ?É Âø(–/ë,pìÚWô×ß{ô/ø¸ ¬}CBå³cÛÚC¬C¨­ Ä"Øèf´³Ó Nûãì–0¦‹Q\r{áë[kwÞ‰žGîÑ"õÍô×1'F9•üQ³•­MÈyméå~O@[>ãP˜oë XbämƒgüÂ0#½W*†cÇãÊЙšÃJÉ<ý.j€µŸÉ#ëAJvÖ‹4“¹Í{™)½câ8èÓ)EQ”ç2JŒxY©`*ÑŠz7"Ãò+,²ð Q|k#NµTF!HÞ¢±:ž ‡oAr•¥&Hr¶L&jÎ úl8¨#ŽØdÁ޹qG)‹qbmea§²ÅŽbO—9_ƒYê«Îª~7y…Y ‡”)ÑÊYE?ýWeÐ Dmæ-&ø|²£(¼q¸eç Hj«@4ήRÕìº{K€.èê=v:f¼£3›¤pC“XUoCy ÑdˆÛÏÀˆêq’É‘á¡.´Å=×~Ñcl a i«×Iè_hnfN¼9àé\1,ak,¸‰œÛ´f—Ö÷ļÐôÊ ËjPxìÌ*É/Ž[åûNoÆvplãDâåÚcBeâ!6f\q'ò}Ƀ‹=àð ŽTô5= ý:±‹×Ù‹zQÜL¸Zñ_³Qy. óÀ™Û¿„9÷ÁƒÃ-çó³R@—;m7,îBR-ï¥ô‹/±õª­BÏx°f‡8BGK-áû-ivbØ=‰Â•oÔäpÉ<'ïCc4µ°NâL•à\±7ÈY–È'tÚ‡ÜF‚qM/“nÔL©€é—YгAú°Cnë¬ÊF¥ 3†¡HÓöó+ñ”]â)ijš¬–ô¡Ž´Û OÆ•8v7"¹@Ÿ‚H£ ÍsºÛ“Gr_÷àk> 5"tëÌ‘ÌéBÏ)yÌ®¦4‰¡À#Ög¨=ÏÄÀ:σ˜%Ltü©)¹¸ê …,’© ²úçÔNÆT¥S ý,E°)¯iS¯ÜY$&.ˆîl>ŠM‚°‘õË0ëÈYFB!®kÅ'È&J¶¦“S²% :"*Ê‚,¢tžÀL  ²Î{Aãí:*íØ’#j¦K€ÙÏèeg@+¢Ê M¸þR—–×;ʵŸ%ù*™PB3Ì¢),=¢ý¢r“ãLàãääNœÞÐn‘|ͯ!ÉÐm‘èlEÊìÐs¦W6O–ÇáÚ”+ËRâ³AJ5KnÕb"اhïØ¯)D”#:Bëñ:°6ÌX°—²gþЈ­ÔÄ‹L¬+:%dWÈez“\š7Ldrö€ ­ ®ÁŒ­0èïŽÙ ;±aÌn\OZ¤í¸(¤ƒ[xÅ+7Uó­{”9Hø©#È AWJ ¸¯nL™°‚úe2­ø_ñyG-é0)Õ iÐ0íR†m­Âæ­ºOÒ°¯¾&oC"J(Î<Rj^ëûÊŵ|HѶ–\ûלæEðq7Zp C²<\;²µwcrW’ ì³-K¤Ã†äB¥¬ÖcP-Œ'ž«2—¥¡t­iYKEcÊ…Öðã¥\•ûªÒKŽ¡ò-µÄÆ7‡9ìW„}ŽФ0úI.XP¥0Ùµ•ŒPÉŸóNq0Ä2RïHÀùkšÕÖ0p|ÝùҤ̔NhÅ®qu‹‰RÊ!²[«£xÑÍ?*7a[VUoÛÙˆ<†²h¹åÇ çª5 ®T‘ˆjª¢I¥²/Â'ì¨ÑÚ1Ý•ê.”ð?©5`zÒ•«dË] *²§×F?Óô¬Äwå>äÉ^6ŠBñºB™…ÎÅŬùŽ^v õ÷•Rx=Ã,ñÁ]ÚiZDIب!….¦ã{uYÝMGO³ÞÚ´ÂôrÇ‘¥¥ïÆxu+uÅ©rNEƒ‹tÛKˆ|vrö—ïÔ[Mðü`>vó¬Ã§¾Ÿ²W¤ çcÙð/ó³Tž‰³IPò>E{ûm—^:.8ð’€¢í«ÜÜÛ´}X×\-c=ëÈr­¶#†Ài—ÛL¥<ónÈ)Ù£öq%¤tfb›œÕ´:éÁ¹Möüþ&^~*ë»,¥Õ£èÇD—êAì肜[ø Ô‚^sƒMý EÁöXL€ª‚²‰Óßf.°†ÑW!ËlAÿ IbÖ*8a\¼…ÉL\ˆ§Ùß“.þ¬7D.þ”/>JïÊ_xTä ÑyA!} ÿA* ³©Ôé, î øïÛßTH?¤{Oó„_¦‹·–öæ÷R]¸5ã΀ÔPÃNå÷.¨Tmh'à}˜Å«É}† õJ9^tE*oM1e|?ÑTùUߪ¹„ç°gžŸqÓUE|~‘Ê:âÈ޾ô 8d퇾TÞ©PÛs½-\ð+ ÒÊ<ÒVÎÏTÓ‡øq#òhÛ)Ù?îyÑ……dÑ$!VšC5xÏ2"*ß-ù+˜O%Ÿxë‘Qé*Õ´ý˜ÜgJ\íqù{ÐŽª¤O*t×2WâH‘ÂÀÌžeÛU³+‰,5‹åÉ+°®ݪ¥JDW°^!:Ͷ©EºRŸñ8mƒZú®î瑉éoO €ë©quÔ©BêwXü»cóï±ø#y·õ9‰g¼¨âP<Á¬ªk¾9†E7ýJ…|åm„OED1’%/?ÿ<a½á7w°/§;rýy~‡5M¦L+Ø•0šŽ(³ò¾.ÅC¢¬’Óь̷ދepk¾ý…i‹©‘¿‘²ª•úMvXëš,kƒ±þ°7iÌÑ \M‰È4]zìémÊ2+ôZÞÌIñ,TñÆÉÞÊ¡÷wµ‹"º^¼]{+Ûð”ìý8ù¨ª"Ë”~[w½+ù<ñ†TÂç·|CªH§¤:e–š«hí1úk_Ë*pÊh«R’EW†Þ×_£èµ¯V)"hø)¤ŒЮ¹Ý…?ë]ßû ¡?ê¥e?åw;²[t&gõ û¡—¾q¬Ù”9[?QV ¿i¡ß5.Ý´Ðïuÿý(ÊCoVðœ—ïœù’„d—¶N«¼HLJ«Å§ó»X«œZœàV` zBóåÛêåêKUNÁðõü³Ìl·æY¥”帳Oƒ/™—Æí-3ºcÝ:.êó˜:Û1} ˆ ôvÚâmêKøUqß´“÷sWX‘drc•Ч‹xóÚ» ;¶7Ο ô2+u_FÕÖê¡hÕäæÈ”†ù¾„A%T. »Éå}Uѱ*¥{˜G*#°É_«b´l¨hnë!·% Kœ *Ëç!©~]Ñ»,Øs3Ѥ*P5ýR}…ô)Pìë¦ïMúvè8Ón.¾¦C ‚ç¯8Z8]Eƒ#3ê²ÐýÆ"žFp;;E´3ú ô—J”ßÕ°ö#¸ˆ·Ï&¾¤£§ ÕňõÂòÚÁ>~õåà ÷ÏNþÿýCiendstream endobj 523 0 obj 4860 endobj 527 0 obj <> stream xœ½[mo7þnäG(Ðì些IóvAË]Ó&‡6—K\ ‡4\¯µ½®wíÄÿþDJ©®½Þø¯fDI>$µîŸ»å¬Ú-á¿øïÁÙÎÓ·íî§åN¹ûiçÏ îÆÎvÿ¾ç_¨Œ™õe_íîí„™Õnkv[ëf¥ÙÝ;Ûù0é‹zÒõǽú¶’3Léf}ã'íÍý‹ÿ(¦nò²¨f}ß¹~ò¼0“7ÅÔLö`üE1¥o‹©µÕ¬,ÛIçmÏüczÿP¾ô>Ù¡éfòÚ[ü¡ˆ~ðVLíßq“ ë­Yë&¯àÉÏðÿc™õ]Ó`3¿¤×^„ô}3yWL?jÌä?…ñ¿Ô¦Â {EçpÖû„£ç`MãÙ§¶œµUß.‹i=Y¶õ ×Ýä3lý·¢°pȦgÆó‡e«²›úÏ¥ÅGG~_“+~tê×?…Ç~©ÞN–p°Ñä¼0í¬¬œ¬¼ñ}âÿ€Ø5øñÜ™ÌýX–;?f»0Ẩ-¼Þ;Á þþ;̰#[ã’°#ØL…Û f¼ VE Zp {íÓQÂðôv€ž àR•Ã-z³_àpð‘„¡eð›Þͼ"Ӗ̱~8k…g‰Ó“ñyr³· o¹†¬4q"õhxȼåB´B´,µÏOq75¸ß„,žóä•çšß¿wÖ±ØXÜ­ËhÔÖh',PL#So«n J’Gä< àv wHäÍ쟀ÿ`?È™LXÚºCÜp*M¼C,…©ú™ßËÏ;{O>„8 ”%@3Éß¶tÉZû©øCnÇŸ"v†L|CüãamUJ÷,Âñëlœ°O¿:,b­ÀN˜|„&1h0#âÌï4º’–7}—3}Á e¬ PTŽ7æ“éy`~çOj*¢>@4‡5€W&‹u[¹Ñþµ› ƒi§• ãڭ‚5‚fÐ'6–Å èIÛšÉw ÛHì5Q@sÎãVÊ TA Mˆ€ˆ †@ÝwšŒdm©ú*z$1¥m Ѷ+GV¤&ðÎ'Á´Èþ°7?ÕÄ3Å%†Šêm#ƒía{ðé¿ à°#„]äÁBt¥HNSàÁ ø ²ƒEgáÔ°‡@'3s±)MŒ´²}‰§Ø„æ¶qø.«SÊ&„G`¸HÞ½¢Úgäˆzmœ/T™´ T - X Â7æä?XWÓ"—\MIU„äp’ìHúfº1YÀç?o@=Ó"Yp–¯ `Ö âº ×8Ñœ†Z€zÆyÏôAã„ ­IÑHi:ÓSNA»¦eR¶d3’õqBHÙÞ)eo$œ­® !?aÞaÊÎ uÒ»%0­“舀Tåµ(n°x±2輚³6©ôÔ ä*•œŒL¶ úXMQ`æÂKÖ¥RºI“é•ëÐEZ1P ¸î`¨l¸®­[ÜF*ÆF:˜“óQ1N‰,g‘_D.]1XlTªŒÊÐÆÆaeEuŽ ÅY6Í„^`Á­Ë¤=Kêªb§"zœPËö6¶D@_h0:fsì7Öº?%@XI¸úB²R¨],J¡ý±ˆWLåX‹Z´™ru]q9ëÂyh¦qù,–õ¡*ZÒýU¤"틂Єä¹éQt0û²föXd ðÇ™?ȼ?¨¬ÐR°  òƒÀ^ ¥IÂ~…agK33mOqw,V»ýä*q ¤ŒÁ( De½ŒÉE~‚s䣪÷wçY>ÉÁ´ê<Å*†kú#&a-«ÌäPÚÛlÏ¥%Ä«áL ÂW¢b¨^P¥?“ɵy6ˆ—e.&RÏØŽx+ª^u0.•BX1y|gÁiåK¸¨T Jû!–µá Aî›Y['Þý 䑌zDy ìÉY–è5¶|ôoÀÒÓÚ ïgâÜcf*e­Ê)l—wqÞ…Ú!Ï Þ(îáØ¹º'¤Ìž(ÖWâæáº°†<êÊP“žx?TG^Py;‰Ÿ7g²ÆøœŠØ}‡tL)£ëÖdîØñdÎÍê-•»¢ÜhÃËq—ËvÉ:x!CMT¤Šhhj"SêeºàÚÁêƒë€¸Ål4Y§«$ªgð£†ß›ÇÓµJô¾¨TSÉó(¿‚*ázФ’Më¨m‹oQ†š… O1SSóSF™®€¤û”-ÀpZä· ƒË œà#©®B’} T§©q¯µÕYÕpëWwj’ê[™zÕ,ZM)æùEzlP3ívÚÂTQ5ÁwùÅŸ¸ Ú´jÒm V;Y‡~\¤»5C'Í ÊÁâvò˜uû @ª»A{$ò\Là·ÜÆ PéöÃL~›¤—@ŸzO±à5pyí_«pí5>€\ê÷¡©JHò”I·)±s®óÅ6©ªÌshˆ¸¯ØC©åÂë ÔL“‚Ø S"…Å|P‹:ÀÉóKÌËÙ¥€Z»Q=3¸ ¼«ÖÍS²ø½‡,‚Õ²ÏûWúÖÂuÙW<­w…õ©¯ œ£˜ÿ–àÇ‚Oè][›¿b?Ö»¸Ó°q/æuЍËà–©ÅPï|,¦-T©}ç¥L"é.D,oháM%ˆz/.}l=§I¥—R¸'KûÚšs¶t™žïóóUf îð†u*JS±}øÕùçJ%ŒXvQëð®4c§i¯Ø}§mÜ ’øhY[Ä[gé§ÁËà‰‰ B…jy;èGèì¾U6‰×B&냞¨@]¨ ®âV|r=º >qøY†ä” ô™©J_ß=D <' Ÿo „”i}ÇgФOG(¼üBóî•6ý½\©žÙò<£Xm…'ƬeË1ð~Ò¹¦+9ðQWµåçÒ<¹H#tÌï>ÖÀ¢½¸pùÿAƒe 0b^Á_ÒQàÛ÷É3æÌOÑFü1gßÃçïIšjø²>ÚØã%Ÿkƒ¿¦Áw<è#°ªáÛïž"p^(2yª ®´Áå6øŠŸg˜ü¯#0z|m¤\j'¼›¿[`±Ô’ž6x•ñ?žð^‰ƒ„ùµ´ï Ôø§(N²ÿ§QЇHYŒÐ̃fûHy“‚ ÿ&å%||Î'X[Áð ~T ê_à(¡A-“Žcì6Âà3on×<øJ{“§û‚~Í ¤ÛrYî× }-ž þžhì`A›B }Ï@<¾}SWÏsûŠ6>ã_ŸHmÁÀò­R7 ¬¨5L[µZWw*ñu®=ÿÌT`½â²î+eåHÛ½ˆŽ3°7üÂËL¦)Å_2ÑúúPsB]ÍÐÎŽ+a½Èß×踔¸ˆ;>­ÊAv P¨Í“Á¯üüµ–!ö2Š’‚ý¡âs£fuáíË ™ˆ®á¯wŽ4ª\òöï:Þ]üüÊš þ`°´­@qm£¢ÔIçŒRN¾PÀê"¾g€Jìù/üÚÅíA¾Ôxw¢ÁqNÍQ¥§[•ëK.<7߈ڥ]gÏ©MG+a#{\± Ž ì®*ߪ…U¯ mù#ÊF ¿«ˆ2›ræ… Vãt­õm—š]i»;eœÔ¬ÇGºÐ,­4EË?ÖS¦Ó3ŒSHêµ,Š` /MÖ‚G,Ü4‚ï¢Éÿ3bÙg-2®´Is"™膒PÅš~%T1¯ÉoUÐM\j4æ,ñIÓ€C’Ë8QZpAúø«{'‘YÂàöµüø4ÔÚµ¬K×^–>¥øµ(J’\g©DíÛ¾ãzú^ÅFü†EeÿmVo»¯à¶Þ8Œ[ÏKð8ø1/E%ž®Jc%®"¦R‡Y².ØÕB2÷]q±Á­ó6ÄV*F‘§n8 ‰>Væ5kÕߺñ)ÇŸÊsú9´ÝRo6Ïß/Òó÷üœ»žñà;üoÓà ®mþÐ|y“7©¨)AmÙßÌØ]¢ì?áò^4xóææLãß„ ïªWýÃŽçNo]k,W¹{¨¦´£ ê&Jýù5†P;nmo%¹KMeh‡îÅŒq)=ç"l«Æê$ÃûÁíI§š€ô*£ÓÈUÍÐUñ>m“wÐw²À›©þ¸o÷5ÌyP$¢LXyÝ…mÝõúXGbÝ}ÔC/ÐÎØØÙÎAá·Ê@dÕ×K-º³ª ’åýºÏ½_ß}òš$зÊL×Ë퉆\ÕL‰Â&ÉlmËÊàœiGÊ}B·­3”ÿ³ncžf·ë$"yþ"–Rendstream endobj 528 0 obj 3465 endobj 532 0 obj <> stream xœ­\[“ÜÆu~gô#¶b—5“âÀèÐxH*r,ÉŠeË‘˜²«H=\rɈäRâR"ÿ}ú\û4ЮX.Ö.gF_Ný+æÇ‹qp#üãÿ¿¼óûoç‹«7wÆ‹«;?Þqxó‚ÿ{üòâ÷JƒàÊ•awqïézÒ]ÌþbqýŽ—wîò1†£?¸ò¿Ãϧ<ºatéðí1¸aY‚;|sôyXrò‡¿O!ÌÃ8·/ŽáðÕñä_óT®äýã)>‡KßOŽnþµôýeyÈO¥ƒùðÝñ4þ7J;è=Çåð_ð¶.}–ž?‹×?;.c™ŽçîñÆ7ðé¯G~þû{ÿ]Vë¼]mLe’¹,øÞeYäR65Ì.!NÚ¸á)ŒÃì–…ÚçÒu𣋠š!9–"¹æÊÌ](KveåvŒEX×ÇŠPÝ|ø¥¬vNÜ@D§P–Ë‚žcGã2^P—Ùnʧ1ú%ž”OóäʧŸ@,cs2¼*‹.SvS<\•.s\¹ÿ]½úº\MCS0]=†®ò&é Æü¤>dî?,÷C™ŠLÉóÈ5®<åhæÑ“y¡C~}çÞ¿Ý/P‰‡g°ÝOŽødð QB" ðJY7NZš\i kõÚa3îìЏ¡U™u:¼#dðNÀ–§ÃSx¸ $C;¼C õšrñ«Š?ô'ipA†¤Ža˜G0^Ù9¥,FÑÏd27 ôÅãRÞ@g¼ãTÛ^ãóÐ_X`F´¢±Œ_ó~mïDZ(|¸da,±<,Ò{Ïfð!uüú[ü<”Íaø£l¡ï«òƒ°äDwa¢å8Zm–ÌvÃ2¨5,íšš æÙãS/à©O9ð¯„'€÷‚¬ý•Õ±ô‚X–ä<,âÄ«8• I,6¼Œ‡}§Œˆ÷VeŠ" nÒà ”)JñqùùbÅZŽÌ0vÍʓЄ¶ž…Ž Ò#3üÆÓê+9¶X€ê€àÿ»G²¬H-ß|*öxµHù€ §uŸïü|$³×w¼Hløý‘©óÁPÄgåÒœøwØ#ü•ÊìÆòO}Ê>PYÍÊhoíÿ ‡]«l^«¶¶ÊªÆæÒœ‡):ëØÁ09`Ÿi‡‚À,ûR.ZyðF}.kI†‰ÚÕh2[oì­3VMG¦¢âGÅãÛµÿHœgÝ—F³ €H- mb ùh—rMèD¦ŒTO.›>¥ µÅ ´Å”𭉫‰|rù1lpY=u\ ëí¶‡iÆÓ¦±Füñ‰Ü²‡-’ZKÆgõoI ”×"F,_'‹’Ý;ÁL=<~LbÀDam¾üùG^*¹ÀÞª¶­"%œ=*z£e•ÔŸ?g€@Åì˜P{–—ÕW°¨&Øñt…4áîù'døNÆè½…" qVk²³w rk~¦ŒwW¡8£Xß®,kÙJ¥ +%¢£³ìâÛ )¤(q”i 4'ët±‰Xã†ATZ{·Vo!J£vF€†œ–… –ˆz 2€‰µ|Ùúe¥Ëå#œ°Ëú”±w6cÒ´ÊjÑ€-šd&Ùï„¥óÜâ—†¬h´ðV­€vMܺð†ÏáZOªq¢|ë>ä19¡F9MèGN pS@söÑâöìYÏ­Ù( kö©$ú´Tïàg1—̞ɱ1¨ˆ €Ï0X>NŽ"ù'£Te"7G~î½ñàZb¿Ç\O£Le5á=§‰õ ¦ʘ)Q:€Çhú¨>x>žÆÁeÂ`ÌŒCó\îÌe·ÛĹ醂„q˜Ç1¢íR4`ž#Z0Ã4ë¥)¢ î‡ÙG¡º‚¸y#ñæ8¤ìŠù‘÷ÐaÎ~‚nByLö€ü ëÓï´e/l_l¨b•Ͷ¿gôš’}}ÕsRc‡´ümX”•r‡Eû<Ù¡Zá‘8ó jëd‹Ê~Î&<øqS@ƒE¢m¨³Z6„K`-<ÐFߟ[ãœ- OIOsëyZöÙõ õ.ï÷ò”SüÁêä›pD%ªŸÖT߈Õ78ÉäØUD ´Ú7YL*²ÝŸªí~|޹º^ï,¿=¬eJuÆêæd1>Sk}V\A—5©ëŠ£—…46îʼ𺬹  ëðMPýÃâ‡VOQs0 ï…Ìá.ž AÔ:uAŠÖqTEÛä2ÀÆË·Ês•–+9àù‡àºµ_s‚6Ž /ò?Ûd˜ åS¼}€JVÚéc /GH^oUÏYr¬yH¢Caoª×âÏŠ ª¶ˆàëI¥1ñªyÀiZ#W]ÿMD>:·ïUÄÐu&=¡˜¹&ú•ðŒñ”79ã÷²Fb±ÁùŠÝ¿_Îo§‰¼ n¬ðλѓI(k(˜„ç¿8:‡d†ØEÄ~§}^M3ZZkšaÝlÊD6—5·Ý0K´úÉ9Ìg«;Iá!µáVêËOÍãz«njµVÜ2xÑÓ_!UÂáz° çFik Z¥5§³O½lPgèîJg{. «ì]O*)%£ —Mà„}N«í‹“¬ú–À¥Ù6ÄZ.îr¼l×Ô ÿwL2](°d>×b]๗=´ sÃ}ߦ.§a½ áÑDÍ÷ û¹ÍFÇÖufèã¢[ê´«ËÊg|„s‚£Ã)εáÊNè·rlc 2bí8•‡zŸ<2 ·†ƒÞÁC†æûO8eMì°[B!Eíèëe,(*Ò‹$ ÅÑ£Öæ´MR©ú»ç2•¼‰bjcÿhy¸SÀ~,®±l…dÛ°I/‹d Ü">Ìo¶†\ 4›ŸèàZ³ɯUs“¾áàpßÓ½“b3*0Å7{CŠÌ*};äH7ŒˆÄÛ­ÕkÊŸMŽcÕ Ër°’ÒÁñúÁ3Qwn=Ù~“ ”õßbœŽ)Ï@pl  ¡ó©˜¼™ƒ&%¡"¯ÑØ­cR9¢ïcY¤†1Ç"˜ðŸ1 Iß^OK6ô•Dôõ¬_5=×àŸSšÆ±x¨DªuK½¡öT,Ù=7ÕJ0ðåjàŽÛÄÀH5ÎÃ4kô—Ý2;ˆÖÕ¤F{ø•nÔ¤nBœ² ŠÆœd6'²t`F† Z¹ƒb[¯ÝÁÛúy¼2uóæÆÍ³^/g¨û^-t…^“°”%÷Õ”íÅÝäòΔ(žÃ;ðt,3^¦Éqxoõ. Õ&Në.Ñ|Äx§v㣘ËÀN¥$eº±€IûHÅŠÍcWÛ¿±Š¶Å%Z¯(¥Gj¯½ot/³UQ5!,….LØ1ùʰ'{u÷"¶Z¶U}Ik̸d››ë¸˜Äž€Œ"‡ÙÄÑ‹¤ÈÎæ™¥"[@6eNh[%b±,â^¨ÉÞ}½Ê•Ç)<Ó@Ädõµúzr¡Â±ž7¹ ±ÎÓÚþ¾EDLàD…A”˜B³ØU0\£§|-4å«Í9¯\É^1Žçmöó¦“÷ð€Ï’-êÆ‚ç©QþR/æ}PgÖØÚÆ¸ÝC»£nŒAHÀ›‡kâ‰Šß µô+øWü§4*’‹½luµÙ¢%> Ñ@ÄÝß6PÀvkzkvÎ} ®F žÍÅ.Ö/õ¶ÖðH¶t÷”P9|Tun À´IÍrì9yD×&ès,µÈDÔM켂´+yǧÎnK½+ƒN”!”ua…!á€µš”°æ%ÝÃB«­’|e™õ­›†¨`ܤèU0gk#¬ÁeÄ%…¸€U@;µ=ÊÊÌ"o_7$Jg禟Úr[_­Ó\kïM1O t¸›È“Í›oPñ<¦¶ˆ`6pc0`æuÜјÿ&’¦5™©Ü *‘œ»½Ê@öý¬t0yÖZ ~pI½@Ÿ˜]WšÆP±¬*£]ÓòÌXuÐU›µdÙSþ›‚?éN¹ 51«5ú™Ð³oá"â+ˆ#øGùùJòX¿Äñ>ªÍX!(YˆBHÔ¿©÷Þ¾ùkR¿O‰ÃVœÝ¬L_­8ÎIÔ–Ï„æ[$îÊÔ>dÙa eì×ýŸ™õqPçÐTÀ™D÷ý’DТҞ±C…úëPä٢åæ³ðm‘ÉêzS•è™»ROP–È 9Gíû>°`|ñ"ˆBk” eZúæíæuȱ?Ö¢¬MqŽh7L¨Öƒð?m>|‹àW£µÂœ+ô_ß‘B #^9žÏÈÛs —‹©)Õ롱mBj+ƒ¦d]ÎZ!ú+x·©Œh ±[‘кyYl9tÍp-l˜>¤ 5ñ³´7n¦)>¯6ï??ˆj´° —oAæ“ñ5ºDõ[$,LøEðqѦ‚+¬‚Aþ¢‹!Ö¤! ‹ÿ­2ÒŸ4.U#T¿=ê‹z«JµßT”õ´lg ’6V›WÀ{Zâ–š4AÆ`Ã52Ù¦aø®]t·ñ »··­\Á¾XªÒè'OÎD?ÅHÎ6Æ*[,F†¸yRÀiª%;ÌZ¹qÈõ­²À‘°ÕË¥¦ßNâ;F-R\8Q‰b“žàr½Ý÷W…‡¨@Ùd—1ŒÒ¸ªÉ!m#¬Ü”ÊÛRç¶3±ùW(/¾ø)Úxݹ}Õ‚‹çó,(¹°·9Û×xx­Ûw¾þE_¬¹¡ÈJSÇ –+0¾¯WÛ#äqM-1)bÁ,>>2Ô ¯8ŽmØ`%˜¦*¼p ØóÅånlê  b>•¯‰h‹$S}ÙKY*hÓ¶Ce—«öõiý&µ•ÂN±ÐªÈ_+‡šüкè¿nú@¤€[I„e!«îöÈ'”ðü‰ÍqØ¹Ò Kñä‹CâÖå Û‚}M­2«U/d•CÆDZ5à\k‡º|èð‹e–‰‚kÎú¶á¶ÔMæêÖ÷3öËZQ<“r¸±LúU]ˆ-•™jFRR¿ôíëB gM5ï5nCàÀÅ-ǘ%²QqÛ½·E™rèÅ[¹V¤J-|üBÆn*;J'Db[c(»Qe‡bÒ°Õ:H¯û,Yi ÔˆhßM‘ñš$nQ"óß«ºÖ¯ªqU[³ª*ÀWM ð÷/T¯º$…^ªÚSPë¯)ÙØ¬ZoŸoóŒâp„>'ó•#’±^½6Àyä6(¸¶É?é%|š€¤}hÄ/âƒ3R\þÿ=rYà××—Èh®ÆÎZ¿@†q·%ì2e‚V‡J–E+/>PoŠ¡ Oï俯úM6ܰy‘™£õ0È#[\HãŸàÂûcfÓénéë_k‚‚t>çK|ÜLQ.kéêÀüv›‡"5@X3ô‚µ;i”>Ì‹ƒ¢3-Ûo–á:¡¶œI_ZÝOýšoªÙ¤Ûû{´Ü¯\KKl%‰RIáçÔ‚~k/uK@ïV²QŽLû<_Í6‘¡só•cÞ÷yúÍZHwÏá× ñxQË ²« ë ¦ñj(Ààá>üÂØÞ·ðëøõwp )¼ùeÚNIÒ¿¯è¼¯ÿѼ'ϯêÅ:n½=×ÛßËÅž™wê,_Òö¹òû ârÊÿìîšoÃY~%$Ô2Òg T5.¹öþ¸"*µÖ#‡þ¯ñ™šÔ¶ò™?ã½}4¬´0{Ô¶(›¨þšVjŸ$^#Ukb0ì&òY-÷Ò@…Ro%a\fd£ ŸÈ5yN଻ò®Y{> stream xœ½\{o·ÿ_è‡PS4½M}›]>ö$iÚI[¸Nâª@Š4¤;é$ô’N²å"èg/gÈ÷xZY6 ç=.3¿ypfÈÓÕaUÖ‡ü ÿÏVŸ¾jÛƒêpqpuPãËÃðßluøÕ‘ëP+×RöU_ø‘õa«[mÊJ­~œô…t…ýéè¯n„®åU™²oÜ £¹ëø§bj&.ê²ï;ÓOžjò]1U“#h^LéÅ«bªu]VU óNJ÷F©Þ½”~àyh¸š¼t3>+—gne]3ùºÐn6­Íä/ðæ|¸>Ú¨²ïzÄü»=÷ô}3ù{1m\«R“Ê=XU〣¢38ê‡ByÖS°¦÷©®Ê¶î{ò»t£N™Ç޹-4œºå:Çpm&k·Üdã^ÜÚ·»){_ÏáÝ1¾ÃþÐ~áæ:ƒ¯_TgÕä:ÃJ0z]zFêª ø¹;;¹.¦Ö­©[?ò{Óv“_‰ `\4c_˜ ]øIªºÁ—wN<¸ŽïMÛ(1ñ“8‰k×AJ€¹0”9¿õ}cÕÙÒt¤N0ýœ¥óF8BkÏ-Cäƒ5Z‹_¡ b£{P8ä¸5‡•“Ý5aZúŸâˆ9pÒ¡ÊÅ×dY[zJ¶õ¾Aö<ŸF5È~Ó#iq¢sîÉ+zÅs$ŠçQšÖº´ )€õ£›qòGømq¼¸%|ÀR€‰vº·•ðyáßÑ×ÉOî#§ñ]_ZPô dô-hĺP-h§×bâÎXxÐ%­-JûµB5^ßR?/1 ]kTtVJ4 XØ&ê&¨~{ 4À¶Ü’÷ T¾}?ÝU)ôS`Z÷e€ý+76®c;'­·`¹_¥jè 9¾`C¦ªl4b7ÓÏþ‰œÂ1Øý0ýÁl´2È;áÆï⪼`‹‘6NöÎç ä c/¤s ë!×@ `2|‰> ×eÍ[ L!|]ô°o46ÂÅs0š‚¨Ð˹|GT ”6ÞE» ‹­ZHØ&‚ô§\§;QpŽb`´mƒ¸;+¨Â¡Ò¸]°¢ ~sÖѰmßyXà¨g·³œžà£g‰[vvìhö‹½.¬îüR'x>¡-VùŒöÉÔ])"ýˆ=Ð|ܲ:fŸåº˜¶† Ó{©ØÛ}µU¢äÏ#êßs#ôT²÷7º§º2 L$Ã7®¥Ð¨ñ&.tÊW±gB65.¹ñ#XdP :ÅB§’κÌ{x¤÷/ãcàÎ8*#ù¿Ž¾àGÀŸw…GŸ´ãF°åu·À`b)a‹XK.T£¢–¼Gdåð"Òt”“ÃçŽ|‹»´@™e™N#6«óøþ8ï§Üx¯¸q\xªj« ’ûèÌ ïŘð>O„‡ðxå¤ÖÏ‘²!C&H8f™œ†·¦ïÐùÝ'VGIçeº¸_¦ßŒÈôËœLqÐuNQf79T<üŸDŽK&¼/.òoÆDþ¥9Õ…à´É Á™âôAœ‡z°a=p_Õ[¶Ðø&+ÍoãJ¯rÒü…ÉyJ]Ô¦ylt=;Ý™ÔpÆ•dàJútÇ ÏÒau!öDZõã¼á¬Ù>ù`äÖSå¶_âÂ7nÒh9%:4 §ý-7eHnÁ}ƒ ‚ܲð^rãeΖ6±ñNÒDfó˜-ë_“ØZKc OÓøºƒŠDúµ ÒÊJMþKò™ó0$xÂIʉM·››žBÆ”€CWˆ—)6YyÇg9?¦xµñ‰iSPÊKy •uj¿KþØëœä”{ôùhãszJ@±Ü`Q±B0&Bf\I…И’”0ÿ?¸àp`!ã÷ÖV(ѤïŽ1*!¬óA³*µ" ì&õHp…© kˆ ™d`ÆpâÀcì;`roZ+3eÝ`á`“&0ù|7ÈRíaŠMbˆÅE¢"Þ0xÎt¢ ðšÆ×¥àÄV³>¤N"ãóX@¡<Ŷ©"zýÁ׉²D”)ûr½Hs› µÔÂvir*D$ŒCoŒµE&p¨Cv–¨gã‹<$.\MS¡¨1;ù!“cL‚»÷¾G$€ Li%FJw²ª)9a;Ir{«%Û'£SfèÔ!ÇЩFª™0¦_çÁd1qzãyØŸÈEU:õ4ܧ~¨Æ¡"ó#jBýoêÙL“3¢Ðû Ÿî9UŽ®ŠÌ+TòTWØ$WËnÆ„rƒÛ)´ª4òXeÏ[Gu_a#¢¤ã)¸ý&8Fª‚˜ZR¾A Ëv2µoØ¿Þrý…i©£KÚMû…ížJß=g^”°)ޤ®´õ‰üÊŠ\Tò4Ñg"ôó.²¥jf'¡E–}È\pÓ¶8åQÑiŠÙy†A”ÌÜV4–¨yBG ¶B•9Kvkš2úºYf6I8{dm êóýn:8L¦&ÅfܹÊv\Ȓ؈‘*CÖ[UØ­æd‹¨ç&ª&D*µ· Vkö¼S¥;²lªt0’bJR¦V.fx¼ºÑ¸É½³*Kˆ:Öª²2‰ŽA ‹ömœ6PAj¡QêAÊz‡˜úož·¯°5#EѰ•é‚ÃÊúF”‡$Âwìµ/£–’˜CòADÀŽšzåóˆ¥9Ž‹DC{(9Q¹XÓ¶wÉ i¦ê“Ú–©M¦ÒÃjg…”S×CD©šˆîuGJÚ‡.2Žqy[ùbøS IÀùg T4HE¨·5Ñ!ßWKt²öÓÈÊ¢S}pÑOðVÞÿ™Òtµ<\aêoi÷€¯¦0 7}S+Yw7µÆ¥RL4TÌ7ªBŒ¤Êè|Cˆ!·Ûµ½RœÓx Ìøaç´âbÏìQÖ.-¿pSÏO°òÛL~Î‚ÌÆ$Î6,é[†vÞÓ¾æq܇!ñBoêJè­Ðð¸†,cEü°N£#γÓY•Èâì&j;‹Î$H¢²å€&zųº-«Ìz·&êý6'¼õ»£ ”$[V_½LtL࡞x¥sŠAÄUâ:ø_ªî¼›Ø$pE½e¸L[Á>)xpö`]‚CkŠf Ap¶‚{-'§úúˆÔÄèq\èU 'Äœ©Òð&ò©ócñ¾á7ëÔËÅ &7zݪ€>¦z ô›\Ïzö”G‘¨¸UªȽ*o oãã“{-Ä {­OÙÅ^‹~oi_"ºf‡Ý0m¸þì«Up¹ÁÇí†QÏ÷‰-¡¼ê”ÛyÂøîFwšSŸ“ÌF-Žf/¤ЉވÕáöÖ4÷›ˆjÀäƒä³ ½—|F(ä3¢ä‘@=b}››}ÎcÛÐɶÉ{¸¬wÈ^¸ ‡mx›iÜB½Õ§Ô‹ð˜¤)&˜ß+X´Ò=®òšåu+)Ó’9÷y$—øTÆÉÆ=Ÿ])5ÇÚÑ2'Áatûc€ÚZ󾂎ü^FA§ÒÇ;¾{©DfºÆC&¹ E¹ˆbX¾«² ÐÄîR³‹ù`»`3KoÔx~&”T,|ùܱ—Pñ«îû,„Œ!{œ\aÑ„UxÎ8Xt° 6¯wÄxͰÝHv‚•žtF½d³XpÜÐðeË_‹wÇ7Õ‰Jð*·Î:â;Bfq šgj”¢+ZÇÖêÑÎ&n‰äñ+™%•Mƒ4’hkÏMŒÙ³›íÙ‡Ç<šIöB•,áæÓ ÚÔãìgÑÿŒp»zl8ÃE!Ìm ÖöU´½¯˜’â®'‡äã²ó ñ+^:¥¸rãŸ(4l xï ¼WïïòÿEùdêf-º‡7ܶ-¨àÝÃSøþ>ž ܃Xïã¸^D„&ŠêÀ…„—ßp£ˆöb¨ˆ~¶y^¥î´mZ"îôô\™òtÕ"àö®wµö ð3Oôs4X¾ÁÚ»Œö> ÑîÆBõì-¿ì÷A_²û·<ÄXOôNÓh¶)“I –g÷dÈ7t5«ìô¸ŒK¼ÝuÙ°ppë2†+ÚbšÉo¼ã¯7*ø(éÉ‚Ò5ÞÆŠ/¼åòÅJ"9v×.ë’…Š¤N¯Ð¼xgßpGv,ma±‡«Ú÷æ$­í¯d•4Ív7þU ¾Ë½ÏÖ•·¹žƒÔ4e²Ï”yA•ØZ9‚xPȆ¥úAíñ‚_Üò“ðÿ«"ã7ÆJ‘¢¾ñ6Uš›dw´»ê¢ç­lŒPS}r•…ún¾”æ±hm–6ÜIg¯¥ï¯½Þ¤hS¢ŸÛ93¹ÂnXðàLPhîÈÒ‘jðENl˽Ís=c v–£#[&XçàHªô~I5àm ,! ï¸Y[jŧçg£º2Њ)MžJÄ €á4AÒ—Šbj:å¯ËÔ£R±[7 2ÖÈþ“ûgÓÛ­ÿª¼ÍWô·LÖ%½Žü½g`¤ #Y¥Á‡ðõÙý#^fýeq_ÿ[X“þÔ@=¸$Š„µ.ÅÒv§ãƒ.ŠŸà­"½Ÿ®Ú*ë2ë,Þ:¯Ó/‚Å›)üس–?tÍüþ ½-•Ü‰ÒÆâMü|-‘®ìàÜ z[€µÀežpÕåùÑÁ÷îßÿRDendstream endobj 538 0 obj 4032 endobj 542 0 obj <> stream xœÕ\YsÇ‘~§ý#°ôË´–Óê:úÒ†cƒë+ìPPZ k9ÂÚ@†A‰ô¯wåYYÕ݃!ìÄ :²¾Êüò¨ùñ¤kÝIÿø÷ùõ“Ï_Ž'—ïžt'—O~|âðæ ÿ:¿>ùŸÓô@péJ;w³;9ýá ½éNF2†ØvþäôúÉ_wSÓïÚÆï\úíðó~ê\Û¹~÷² ®çàv_5~jç©÷»o›}cÛuãî÷MØý±ÙûÝ—Í4¤+Óî´ÙÇÝïàÒËfïèæ‹ÔöÒK~H Œ»ošý°ûn¤ç õ)λßÀ{øtj3µäø]¼þ¼™»4ÏÍã¯àÓ‹†ßÿÿÓ?¥Ù:ogû4È)Møô"MrNK?ðàžïìC׎nžélú5Œí®Ù÷»ï›˜~pÐ ˆ ¸ñ&MäpCŸxÛऒTîI*IVt÷,õ÷6½sIrÁ÷oÒµkx. ¬òËïáîuãg’õ«ôÌ vÜ[ðq÷CúE’ÁÇ¡ñÝyº}/ƒáÝp·»wЃæq(<ât ºv·:Ñ›‡íæÝO°bÐzÆ_$ÁÄi93;'kèú6Џ¿Ûɨ¾käÓ3˜Ç„Àù„ ]éà“äCLË₈ÍÃl`æ0º<‰Ëô!  OWÇÑ£<ÓÃ!ÀrEh+‚lüHò»o< dBxBG”õ’š…>z‡zZ,ºe::×Ös?(dƒ>cl‘ö.´ý „‘× ¦ ëˆbÃé\S°1Ä÷‹°<º`ðR’$.p?áWJwÈ1‰^62A@œDO°è`4=®µ]f¼–FÚá¿àéŸÞ„ƒ¯oCß½Jã—Áà _ mj]? ÔÞR¿<Èáß)*c‹ôÞ¶nÆÊ2bpÑÌ^ý<å½–,-Ù{ÞüžþtH¥U؇É? ·äyn³ßØÌ#(³¸û;ƒŒu _ÐÈnó8ä­||­ÜE o‡Î"G{/)p€{SÀ§•С)™ŒàLkó,´kú#¦wóÊ¥ý»¸Ø†‹b‰Í¬3ªÒúÉÅ0tq U;UÖÿ ð®ÏªŠf^ꪯ›dÓS=Ž÷M㠘ظ„îaç§ù0püì?‹ÙåFHİRØ%<9y\.h äâF…6­V"ªO0±~êpð?àà±GhùFö5vR;ƒÎ3njÿù!&‰L‘Êò­Ÿœ ì/ðd†3´Â0Ðpo*¸÷€„yf‰Óœ? Ë2áÇaĺ÷³Vƒ¿~jÊÒë L™Ì0PHßÀøØKoïj[bä AVW4ëR]±CŒË:ÙeÕe•¹¶&¨y*µMV’Væ}U}à¬Q£É$K¾Í±XTbjúµkïe5…#œ¯à6>s/ô¸/”è@´Ïäë{„“c;(µÕ7Þ ©ãô–øÌkslÊÁHg5"v’•@!£*¯:XÛàT x¸{7·¬e¾m¢ÌøGçq°Ž2o?Ó~PÕÌdQW™5¶yÁý”ö‹%7î"òr1¡²bŒ@Ø/p›a#*æL>FÜ^K•Ħ=8býïÆ×0ý™Å°9]¶ð•구_Ò^õ‹jÞ gåWl<;Úßy)_ëþVᓊÃw { ¢:ÒÚM³`/ÐÓžHê ƒf}E?¬Ghv¥¥RÝ£­¸hèO¶ # KÍpÈDáûrj°JU‘ m9ÕúFä¦ÍŠ7 ø]ÑkDhÇϳ*DïdT ¡ì ´ÐeG-½ŽÞ14ç€I Ûž+*’yl‡¬GÒK¾t€Ù;â$´ j$»jï9à&£PA]`? žæQÙ«‹Œ>Ù iqÖaY¿¼Cú ¥PZ)«‰"ïoUúÙÑ» …¼ŒÑu bçØ(” §L?Dµe 7ƒ–·ÐvbõÁkY ÝÊñVz®(Cd•jÞÆ—2™¼•6Þ4y»°«ý˜YCTxŒŽôd¥§xôŒ}–ËÄËLT;¶½RíK™F±G`KiSXÇ ›*Wõ†Åãâ–£EsÇ©©zü!ÃpéLô3«.IÕM6MžõͳTW襔!ÔvÉ!7@ìHôöiºôÝ0ÖTÐ ïþ“èyè¬CWðY6ÓútÖÙȽ‘AÊîùS%áϘÞÌ}Ö¢êÏñ3ßK@p¨&AÍ>-YpŒè7¨Nœ˜¶çf­N À€(̾·ÎôOŒ1 Æ›[µÅ°æÞ,éÍÂ4•{Q\µF¥*w¢Ûi6]¯3rt²E³jß4Æp^jɒޝÐ-Æ̵„ÙYÞ›ª 4UX¾; ; (h±æSù— ÕH˜'Þ¦v±iZ©ï!‡X$ÑQ(y]m3Ñ•¬ˆ¢_¨(xðGÀ£’r%ˆF§• 7J˜ˆ7Øþ0(ÏZgÕ•ráx\‚Kb@*W.5“‰ä½a‘À”‚ÿÚŠf¥ˆÈð"îIW.³;l V<ÉÒ n¡)ôÈ~ðZŠº)áÅù_>9ý쯻çÌ®ã¨2/Û4oá }ÎÔÓG e÷eÚ‡"þbésˆ3d6ÿÓ}™âk…OýDÿˆx}¤}«Ä\Óç@ ©ƒ³·-L19s§"DjL3êY5Í•b `‘ÞT}çqNú"Rh_ÇéíƒBe†ÂgØg-. ±v p†¥öÛiì­‹^Ó|ãe£™VÂܨÔÛ.^˜b¨6À~Z&~jt ܸêð•@Þ£U¨Ucðãr,êûlF–h¦×MèìófÐä+Ì6ìN á—VЉaŸêSVð¤°J«¼u8ãÐäÛ¥Ëû2Ô&·Ð|ªo³S÷°v1§5º­ÄÔiºâœ_T)Ò:"…š1 ŽŽsˆ²Ì7iô2L>«3Ó»fPÅJ_­EÇ%º˜·€9öϱ¡q3yñ8Ñg0î£]h"|¾•ñÙÀHj™Xé#ÀhXÞ€™³¸ûs3wæé5w@–£—ïhÌé²uŽKʇ³-µª+uîl U—ÝDR#¢Ô(gHÜ ÝÌ4ÌH4:Jß6K®—íÛBñ\—ƒ¦—ž¥ïWCOUZiÍŽ&Æ„X²émH“œsªŒ²%JT_£DV4+ FX™óè‰Ê¦M7ÔS`ã`l%Ò‘€7:Ê ¿hŠìŽô‰ôf8ºáˆyM\ÑLW1؈ګœ»ÉñøiTžâ»¦Z, ÚN£nl}EB~‘ŸÁ8U©ö(J>‰Nfó‡!‰Ã¦¼ÊjÌíç!W~˜HJ lðlèÐZ$a‚qÙ ÆÁ DþrVð…èÀé|¼c@u*9ˆŒ‰$ð%9ªù¸f­_l°$‡µ9E‰” í—º)0時lÛN<8†; 3ÐC£xéìêWÂ~ýÊhÐ'%½U‘wÍhÑ`O†­Òs2uEќŚß+|»Ø„ÔJ$ukI›¡à#iGɨ!ET*7svHÛÈñDaew¤#Xtú:˜vkAcôë"tQGé¯Éƒ+ϲD‘ÆIaQo5(uO,}à îššBjÖ?ˆŸ0õšDRŸp>@ë&Ìñ>Â3œ†e%לéÝñ‰~šü"­ç3‰½Óä€SèTÚP²­\•™ˆDËŒ#›ÈqQÅÈ0JÂ¥;¹¢|A4¿µðç+dkÝKÝ*¡ÐP'òç¸ûuÖH¿&" –óI¬)›³œp¾búWVœ—MQv¤±Í!W%ù¸5«ºMµmàp!Ÿ® ›'uÖÆÁ꿚èÐ2µ}ìц_öMvó¤V#rúë˜@P«Iê!)bãÿ m|0`ù¢áÐ<òŒX׫¬ˆ M®õk¢DÊQIÖ6 Wý0ßú†¶hÝ7ªšcÝÅqÖ@´£³{"ƒö6㻊‹m.¬È=Xãò€é5ZÄ£«RÏ:Ö7na)ÔÁf£a5Å`“¦çl§ú-.AŒQ¼”qT‡Ózý…RÚ÷€é SÅ•Â_ÓÆå´Y¥IeÈ£qNnrøªÀÆÞsðg”š9‰EIÈ9i]güYS©J§N”H§É„š¼C‘3“”ц¥ç mBú¼2ôÿH?F݇Ü–çiä}ÙìZ±4©ºŸu­[:¶ftYl‰†·>ä§yíD?SA{õ]†øX^S#kã§ h±î£UÃÊ)»gµQO¡Âùöù²ï*èÈñ=+öŽiÁÀ£ØÉ“eÓ¡°¸V·+٠ɺMº«©fÕa¹@¥;[]bå¼p9Œ/ÙA™>AÏ BÉ¥eS Yv+Tdï$U;` M+“Š“‘*sµ±iš>NGÇã<[lQqˆæÛüž(Ò¶“BFè©ë©RšÍG(Í:úHÕŠ»Ý 4šïL òqô=…ûY¦2­3ºl$Çï'ž¢MÀÚ™,ãè¦ûž¢P¾ÃeËW­0aür?†#K%yâF¡"§õ=VÇnä=öµðtI2Ûe&ÂèW¼_(MjÙ³1‡r µ(EDZL )\$‰ÓîLJu3úûÒ¯çZѺ—Ç…DýMÚãïÒw¿å%ð¯5€Jy²­Ð6)´0N¨,ÝÇJEæw/›¢˜ÿûÀâÊŠWR·ü]^ðhëjðòê½,d þû¡æ“ ’L­êšZËœ³N6FX%‰M©ÔĬ­âÚšÔbuß+Q‘èB.7dÇb­È7ð| 'Ȳz¢œUoÙuXdnsñS³³£nxœÓŠ\÷–á‹â¶£EyÅaŸ#‹p¾ëOL…¾j-ÇøõøYެ߃èw_7.WÄ¿ôìm#OtDÝ<øz7Ä©@òLÊEÆEîáUÍg‹s&µ Èü¦ÄmÝ+‰ž(Ù7êùRÁËÖY³Í%Ên¨ž„cDTYÓj–ç(~¤-|²¨Œe–ÅqàÍ0ÆH¥½³g…pÛ3²Éa–(êô@º3é1¡çJ„¤u>:ôƒSéO·’˜ïç5‹Û“WS÷VŠiqðäŽL Œh)Cä]ÍY Sà ¡Lì›ç2ïš°¯T&H’fêÔï{ Áòß¾'D«…‡C¯_ÃG ÈK\” *Æ ïT1 ®¡ŒhÊëº_8PVÚ·­åpkÁÿ¶ÅZŠc¯•@>‚¸±6hœ—ök"^¥0º %=Î9kÙ³@­õ:–çö+¥o:9FKIƶs’6û'Ô“î–Ÿõ¸î4ÙÄ€Ä$yj•ƒ9Ò¡9ØJÿ×À‰ï=ÿ×0¾ÑÁ<ã–àaµæpìÉRzZ×Ã¥¶y‹ö6¶ËG£Æ>§ôçÕs=;M•ÖQË´i“Ìé±;Ü4E^(fy½„Û~}GZ/‰Þ¤C·× “Ú&ŽžµÔX!Âb?|Z}Hè·q³2¤‹l´Âaĉõ7ëñº9Ë qOi‘­‘‚Ë:&‹Vo/ÏûL ¹+’2ønQÊœ“±ÊÙqZ¶ÂÃñU=‘ÉøãàÔ” õZlÖ26V¬zi’Ó>z ½RRJ|—´zyË)¯3>¦*ÒÕ²£2._œ âT«Ø€i°»ÖFÛ‹¸ÆÔõ4ÔFᬌZ"Z÷•Of Dܶýd³ì¨ÁO6Ë„*_Dd‹ª¥Mçy…SàqÞXîΠí1M3•™ö1a³#ƒIJêr¸@BÓæ™‰Ov1§•j¤#ÖFµh?`›…¶¿±:=ŠªH /%›¦¤&øVŽÙïÌ7l±ü{oKV«s‘¥’Ê6åBˆað$§vÓ4 ޱÆyQDrè(»¨Ã#Þvm͓Ď+(Ê ‡³éHòá(-B”t?ÔÎfoÀÄTë…Ã#'’¬­‚¦jÏQßkUkÔñ×Rã75&gZø[&x„EIS¸8¨Â¡Ëßj±qŒ&I‹«ÁyòÊÎê“WEÍ$¤W I²Áš5_k¬Æ¨¸¦çÁ3t—ˆÔr[5·•dÏø©gékŽ· 2QZ®ÿMrˆoó¾FDÉÂÄè,¢4¿¡Û€Yß2èWÈøé)¥ú¤J~$bðÐÙÀêâ›PzÀmGV8[=cŠ¥ú}-¥YÔ÷]iÕcŸƒZfƒ-”–)N8t¦±l[Îm†SžÌ[¥Or†¿™ÉBzÎe·NKë_:ûüeœìWHí½KcuI½%ö8L#‰ß\œ©äò\ý…eûľd€¶¬Ø¤XGŽÅHîå zã¼òXný>jòº®KÊßm!FÑ|DžĹ˜…,¿ÀeÜËÃ~²Ï™ÈüMJGWx¥÷±Òpü–ïÎí?õ] GoSÁ$qÅJ½üª¡Ä0n£Æ’PTFmž›Ó‹qíbŸ/¶öuóÉ¡±Ç.u³ “‡×0Û¸èrÔ‹._œòG_ô)ÁÀvq•]Ð8ß U —0çÊaÝÚ“rñóµI›±tx`Á—-Ýåû7z1‘²~Pçzñýšú½³È²:×ètR"¡êÊxq=[Ïö5ÓÙu–Û«ÕÞî þîôÉÿ¦ÿRÅ®£endstream endobj 543 0 obj 5250 endobj 547 0 obj <> stream xœ½ZYoÇÎóÂ?b!?x7ÑŽ¦™éqà–EÁ dÅ–hØKê„E2IGú÷©£«ºzv–`‚–»}TwU×ñUu¿[¶[¶ø/ÿ=>YÜ{:,_/Úå«Å»…£Îeþs|²¼œ‡–flG·<|¹à™n9øåbÓúåáÉâ§•[w«–ÿÿûð0+8;Ë·±{˜xøµÞÄÕ×k׌cŠãê˵_}»ÞøÕ!¶¬7Òñt½ Á5m;¬Ðn Çû:í •ŽL÷«'@ñÁ:ÿxT|câêá:µâêö<Æ¢oÆ4Ò4ÜÌ7:ì€w0ŽýêÙzÓC«÷«­=|é¼£ ‡ëiÖkϬÇdY߸nl@†›Ð6ƒGÁ§@xuŠ—øñ>€¦sø-˜vÜc<ò—úÕsô¢4¾ÔÆ7¥ñÔŽÌß`và³[ýªÛ2§lá²4Ât×õEþ©öŸÏ-t9G‰™iqú¥6Þ€#ùZ³„_cHv¬aÊìê¢|}_¦íï¯ô+^­í›Ø5)Œ N/4¿Ðé} ˆgiYX0àJ¬á‘8‘>ÀÆúÕ1(â¨/µëð-µø7#°0†Õɵ;u¥¥cPGÝG ­­Î[Ñ2^y"ë¼…õq­óbØbŠ ½®—ÆÈ4ßÁ@^ §]¬õ8ˆ³‰ m<ÊqJã3øI&M"À±GH›Ád‡€ûtl¯±ãÅE|Ûø$.á‹£7ì¿%Ãî}O\ÝÉë±£H1ö*V¶ËÌ4θXËùn•ð˜Ó®Ü9B[G©†.kë.Ѻ®QÑ2•×±ýgLM¨sä 6™ó M×£ETZò?Pʨ)oò™fF]ËçBÁÿé\XYðØpŠL3SD!Ç êwÄRöY›À-t¤±½Ò¿äãb]ðmÑ3ø ÛGØ–¯OÔ¿ÎÞõqQÄ»8°§"ä/£Œ³4‹°?ѶSÙÉéµ [wŽ‚õ#8ÚÞ‰JM˜ ^Y EAÅ¥˜H6¨‡µ~! Œn_à!róè¶@'@Q6ªP#Œñ,à¨AÓþ«&\Ë‹çÄxòDC‡•ˆ¶Á=}Îd#ŒÌkˆl·úóβái&Á¦–‡‡þ‰#zòxæÂ2þ}Q¯»™ غH¢>Á ´]‡-õ#GO\¢vOÁgbÿÅfZB­üÄcð‘"³8 @ØÃÿÌ82Á[ þøÞS[þgð6’áÚM‰žÕ:ä±½‹“Ýf`è³Ôõ½¤h]—àÆhÄÓë}ã‡1,!´uã0ðÒ0û&&7Ň¡=€Ê妚ƒ;N5´ëL²ÓH}Šô|}wŠÿRâð>NÀ‘˜iýñœ@ÇÀ;`t _XÇá0lÂ9lp¦Í ¿»Ô[ÀÂM?Ï4…n QêB×¹ÚbÍl|1YLy.ÏYóKºT2+“ u™(q½ïü|&)<¡Ö±É‘Í"úXŒ,Û2Ú à±Á·¹‰<*ÃF?:Ü‚£Dåã eMà m r/Ùy“]ç‰Æ4s¡íUøo™.jÛYâ]’_ ‹ƒk+ÚHÐbo6¦#Œ a¼›”¬Éo ‹†]ÑkÙQªK}wqTOŠÝ‰EÒë7äP@"ÀS¤¥äF¯gP8*XŽ8»ìÆœ¿íNÛVéfq(üº?óØ¥²0Ã`–H‚%šX¶}Ÿ4±A<´òÉØ¬[Y |Ç3P ;Œ%å¶TÓP,аÇÙå¬ÊdĪÓâË @• ÑVðäTÀýh_±['Xß8|^%Z~•Þ²‚uÍàEÁ¬cïÁáâ»Å»eMO>8²´ ƒ÷hôq3°{|²¸ÿhqïÑ7Ë‹÷—/÷~XºÅ½¯ñãþ·_ÁŸG–ZØS„;pÁ·*ŸIÔ¶ugã Tï0ž%…¦øu§ºåûvõP íQq.‡% z–d«c\ߥ:;Ä9mØÇ¥‘ɱ«Ý×ëÂf ÆLÑ¢'èÑmˆ=OÂÊyÎH$O1À8ÃÙäÄŒát›°J!sEpç‚­(%L |í‰8®1Óu\›ª ]ûaGEDFÂQ^‚ÖNÕñ¶ê®ª³+U‰At/ÙÙ2% áë.ÎæÄ/¥¦b.Bç©B¥W®{p «ˆì[‡I•¼¥ÜØ`¢à‡QTi[›œ%µÁ¤w“¬„+ñxYHjŒÙ„Qð§k:ŸèøÊÉ5™<1"óÛnÆ9ÜÉŠ!<Ôe°slµzµ žëé‘`#ãq›²Cºú !•Þ×VøF:™\–OM¬{OÙšóÔ½ kœVÂËÅJ¥*U1›Ü©NÍÕÀ€k^Ø€œRÎâª[ r@mo_à«E5˜9t[ Ã…­\hA #¬ì&T™£?,Rî™×,céDeÜ ÿ€h'`àNÆÝãt“{}.½1¼•1/Þá Ôf ¡»ÏÝÏŠ¤Ÿhã÷¥ñ±6>žE"ôFcSËR3àš?qRn#ªÇAA]¹söÜÇW1&urëZ,¢èÕÃnð˜@ï`yf<Ð΃ÒùPŸ”ÆïçT¤V‹JúïjãÇ}pfFhÇvÇfÉ¥\’ÑÔS®_*ÈUÏ­Ë<ÞN¦t°Ò³9±þ‘bÝA‰Û‰tÁ‰¯rvܽø¼íåä´¾oI$õЇ›²#µë¥BßçÚƒ–!Lb†ú›½£­ölî\ƒqÒK^ddÑjô½p)uºhâ}Ƥú¦ÒuÝUÚ–«—|F#]ü‚;§rsbWIДü FÃxM1Óâ¸Õ.³²? ôø&ìGÑbË=Ú‹&éÂuw,¾¥³¬Êeùv¦²AÉw·ï6DªöEœÑë9à‰¦è‚:ƹ¬ÙÃv=½,25|œŸ_[‰¿ªkeh“~ȯ9XÝéɤ3Ò¼82ïàt)B­£eæw]\..î¤ÀCß\YpÝ„\o{úP©¥ääp(•™=WWšîär2,Ío÷goè´Ä¹¢À‹Tº-”«¢÷À÷0fáü4³ß}©t‘µn4¾m¨z5-*5:J§Ã¬O‹öä¼ðY™ 3Ym›¹êQ]tÛÑÍ¿h¼àÍáȹ-Ó²Y¯FubªWtNǦ~ª:oŸ¥Ý{ ,Øuž.Ú‡&Ð+hN8z×ÂZ˜À·M ÃÀ¥OmvóC<°áBleÜgÍÁ®äGf«ç@JO¹!iÃÍH†®E¸&tXöÿe·3ƒ¡4ÎÁO8·ÁdI÷×QÃ'=ÛÝy"ëæ†nãBâw-ÇÆÖé“#ëä&—r–qŒl…:D 'çõt9/+‰Ö›Fö3}±§Ž9?­*YYÈoü†¡É×}á•ËQö!âj*HH|Ç\l‚ÎC®\Òý'c^~ Ü7j:ßÈøÓÌ5øRô~‰sHó–òG}KIÑh¤v½ É›¼ø¯«¦èÛP墣öÌÆR †‚Þç+Û¶ä÷¼¸ÿÚ6ªû²koÊò³¥)šQ,^ôh&ƒßóSŽ”ïCp†O6e©jAÖ±ÄÑ^¯ô¶,¨®Z X;S*ìêw|ÆÓ “0Œîƒ|m ‚ £}A5£}—F¼K®sÅ«Éòó@Ÿc"¤¡ÑÜÝÎÝÆ¸ÒØÎå·ìÈ«µs„f¯!4»ølcE=‚ÆzIqÈ<½ê-$Ék2(¿3íænžÚ=¢’'Šmü›ÔÔ¢-%]s(×Ký†ò¿^–W­3©´¡'/e?'܈ „zvh=œ[ÿ=NEçqAÝœéJ¤W ÷æJwé˜Æº D8¾[üè–úendstream endobj 548 0 obj 3893 endobj 554 0 obj <> stream xœ­[Ys·~gü#è{'ñŽ× &•<ȉrÊ%%2ËI••Š”(Ç)‰¤Žüú / 1‹YI¹,îG__è}{8ôæp€ÿøïÉ냯ŸN‡gWÃáÙÁÛƒƒ‡üçäõá7GégÒ“~fsxôò€fšÃÉNÎ÷ƒ=Û#­~U¤ø+ì G÷2RŽ\·³ï'kD&@†¿ðáNyç´ÁIGó‘‡éyHËO“ÅôfD}ºDöÉ1àp?«‡¯HÖ2¯‘Cp–Ö+™<_¸²~ñÊQ#̃юê! ܵ#°õOX±5®#˜"pä8 Ïi¥ôæ)p˜óQV§´èH’K¹! ³ËØõº³3jÉóô 5á±Pa’%ÁêÀ¿—°À°+…Ù¢ü—RpƒCé<—ƒe¢fÜGtß5tbXã¤ÄÍK,wÆïš ~ƒå¢³­RƓȻ²Ñ—ÊŒ@O|D: B$êH]?¢€`×JÌ÷8ȨÕè¸RF}R®+`Hd* }Ï<*ÜIÖ1=Ê-Kµ­1LÒ‡z`g§¦&ÜguD¾ 6†9{±Rd̲PÃÎÒ‡ô㹬UàAIÉù|Á¼Oj¯¤Ñ¤¨´Ÿ`„àµÒØ­wYS=àÊ ¸«†øXÆY‚°´•'$ 2à|˜4â¢ùyÐa!@‹é) Y@~Œ¼Bf [0Ø™ôȽ³dßkH—|€@‹Ó Z‰üˆuÂsç¼°u …­óBa{ž¸äw@½Ù¯o§2ŒªÃ¤Õ@&LÌÎÙ&Θ_B÷9ìQ,AG²׉ÿ,l ¬øJonz©ÆaK˜ökç,!8X|™Ž·#NØŽÈ`é­ËþHûhÁƒJ h9’XÁEoÉç<Û¨‡OðP.ëž’GñÖï º&«  æ>ë`ƒ7@]{%6‘ðcfÔmBå·µí àv—ºàÀÍæºL6‰ÌS¦D¡æš¤õÖ;Ñ[p¦ˆ)èoó êDUŸÇ_”ñ·ù!€[ÊÄjRïE?lœ¶fzgI8™Îï)8HH€a¨ÔgOT‰ cˆKÆC‚Òâ+Â"h©p}œsˆ!óÙäh¶ŸmÅ1r™1,{Äœ½ ì?ª¦4ó‚ÇPSg³ÕÕ6#/×¶›·랩֜OAÂÐO!Cxs%bå´'T°ÙIÍô‹²N#T„Ç éj¹IœÏlv1Îåï»!ÒH¶NÔדXà(3Ú¡ŸÀœUÆVÅü1c5žOꔀ7¢z<š|Ë="Y^þ}¶8—tCèíׯiZBˆ?ìǽeÒÇÖÃ[À°5‡ŽE9Åÿˆmjüz?¶ÝFNÁ¶&௑ó AMzqg|nÒpûÃ& ûàÛØÁ‘Ž•bs±8¯uàãÆR…È%<EbÈê}¿¼BhéèÎe7v× &oœP´”@TP¼ˆÉV£§¶CpT$[ÐÓvXk Ë4„às?zpˆ%­Ç­%¦_æÇ»pYÝ 4â²Û¤o®¾×²9Pƒó!uMFú.ŒHغdñ –ðBùF|]wž/gpýs—í®V4^æ €l§¨¾Ô‘{.ë|(‡epz&„/Ÿéâ#•´‡ ãg]ŽŠ£Ï©ø˜œ4Õƒ>éP•JûÃU—V .T¥mb^húÒÌ_×8ƒNÇ¡¼ ¯Sè0}EræJ•˜(ç Ù‡’°Áa<^ÒÕÅÒ,fÆŠÓU¶˜¯üt•ˆ L§’ì«çìÖ§$§ØWF =K+©ÿ(çÖĤ>ƒò½À•O9”üòþÌ |¤, o[ŸÂ+®.‘¤0åIá#äÀÞ×4Š0ºüÒº½ªéäsp,·%ét¸• ˜E½/aÆÜ™Wò4>{Ôa#Û§up—뎄äÕUé¥ O\ÁZBÊ­UµJ))×L8n—Ô_Ä1Q­ì³FɉSEÑYàÌèÛÙbž' Á÷ÞP]I¨ûË´à vø^éF2r‡Ö-JêK ÛŒ´S ]¯3{þ_«\¯“ñ¼—(œQ;¹l×¢~¥W8 i‰-ØÙçi%Y”,7 ÐâØJ€X5À4õR4R©-Œßúº‘ê,“©B€1HvV9€Å5#%uó­GŸÉMr°ÕÈ¥»ÉWOJeê’Ä5!­´¨×8g7_i.‚ü~ÍucÄ %…± ƒÕM…óE=I)“ˆËšÁ‰J%|Ž{ sÒ³¼Ht†¼½ϼÆâ †¼ž,Ó‚÷Õ|ê~ÒÂ[j 8¸Ð:†\hõ%u»µÐº–2Á¸]”Š’9H4üyYî^¡| ¶~&ø¯kIŽì©À7óV¥.Å”ZR®}’_Sô¼,sÏóÃãòð,?¼â,#)ĘޣtËCSñGr™[jmÍôò{¶³š–¨pÀ±‹ÿLŒH.§û|ÏJ 2VæGymbaÎøŒêYÂ`kYRloŒÙËË.ˆº7Ip4ºÛï¯pÁfVƒ~Án~Gþ ŠÇ÷7Ö õ®Õ |¿?¸ª~œ%Šz<žf#WëZ¬têš©¾¿?¹µ^tQ@víuqÛ $MB¡”Röq8?uXã‹àœ²‘õíçGº&Ô \%´J¢ Áb0¥Ü’n²ëØm‡Þ ˆ‰}7ôÑM!E~lÚ¯¸¤ Æù>y”Ÿàˆ&Œ@v¤8yÉ“þ¤OcÄà+åŠägËZïHRCŒÐ}˜æ¹)¿´Ð6‹vjûqÂŒDµ±J~t•öLe -³´c?ºc?uó ¯'rðhJ/Ö¾K;,ªN½nžSÝk5æ…ÖE³cb‹«1 ŠÖrÅCµ5BQ¼kÞÕðEãCoZð¶räv²Çlˆ)nCDZÉ©vósñ᳓«#lŒ€ÃEh;muòÁ¨ÚDJÌÄ^ð"Ü/ oÕb7•íV4¤n,…ì¬ XDðHt¿ï»D8ékŸôïDÖ(>L†~Ñ'—E*Š \J #¤Þº`DÊ‘2†ÆïêŒ!'¼ÕžìÙcÍŒ@{Q{£c_ø0OØ¢CÀ;}ÕÙÇA…³"TQ¹¥¥Ò&õµtÀ»Ý··ïò–Aœ£Ÿ‘e:ÈR‡Ë#Ç$DÔÝÚA¨j½¾Dƒ×€ÝDšÒV9«X帅î.Xå]+–_à‘ÕiQ,(§y«j5Ín.œ¶¨"Ò²qíIÇÿYÄ’(e(kÂSJ±’›k*°>qÀYUHàx߯z|•µÕ¤»Î–¶Rſυ2†)N”É7•NJç¸0{˜õc.¸"í5ø<¸¡¯Ç†À>ÿ”à•Ž±s8W§ó‚ùJêš=ÕzisühÖRBÉÌ­©ëèÙG™*ÙßµTªòOÅ÷íÀäœUOVÕ&Õòf÷UÚý}Ö±Pµÿ­ŸÇêk ’˜ªØ*Ù7šŽ”îí´E…Ò’û?ÙÙ~­va³’íí—ß©^Õÿ•R¯ÐŠ*› ÉT¨È’Ëøònl—šý°ÒãâJÿ59 ò ˆ™ê÷ù* ÖâJ;¾3wëÇ¿·ç”n;]Z׈cåßýG¦º–M9ã ¿NX£¸ôËí@IIÚUËU¤MÆ› §›ªTýÀ]ÍgìJäÛì2@¿GåZý}ÜÖL´ïü@Rßeð‘ãõa¸C“…ÓU>]µ.ËuTl\¡A.[•²–¡:&Õ^Õ=‹g3Ó |õUõ~©’®‘°„¢ó@*Òbô jõ‡˜»QÚ‘?Æf:‡¿‚_™%ú¢®^:ëªkÂP¡(wR¨¨è¦¨G+a¾íg”îî¶lpsíŠ ©Áâ8þö *åOKÈÏá–£‹I­NY´wlœÀ‹Ä›¢)r·óS2β¿=:ø{úï¿?óÎendstream endobj 555 0 obj 3850 endobj 559 0 obj <> stream xœ­\YoG’öQØAÌ<¸kÁ®É«Ž\Àh,Í®²¼#Q†Œ™} II†e‰Ô±¿~3®ÌȪlv·¼0LuבGÄwdÿvbz{bà?þ÷âͽ?=™N^}¸gN^ÝûížÅ›'üÏÅ›“¿œ¥¬KWúh¢=9{yÞ´'“;™|è;9{sïïÛ “þwÝð?gÿ•ÞòV¿åLèã˜^<»L×mÃæ?;ÛÇ8‡¸¹ß¹Íw[·9ƒë»­ÜxÒm½·½1ÓfNc÷éŽs1ÝÔ=ÏãÈënó8ø ã/Ò(nHÏ„Í_;ŸFó>l¾‡;àOzÆ×Ç9âk°˜òci1Ž›§ÝvLWÛüܹôap_8ëæ€o=ïm½&Ø–÷¾õ¦ŸlŒDxá}·6¯Ó‡›Îo~MÃoÞ¤é6/ÒÂá ܹH+Íæ<íþ-o®ÒíëtýU7𣟻JÌ>-ÙãíwiÈ$q`œ»Á=Z‹ï^ËøÒËCÀ—á!|úEYÌ ã™ÒûeºF_ËiWX4Óc°?õÆ2¯"né¼þ _u@S7Å≯¾ómçÆôÕÆ´¯´<À̸ù/΃Û|A&ŽÅa™ˆÎì.yÀàpÀ ökÓ€XéÂàèF¤! ì€Èy0ئZð»j˜÷ð\Œƒu8ÌÛ|óóÚ"ÒEëÝæSçæ´'(³eÒl­ï‡¤(ô±ó´Ó ÆóÂŽ—¯™Ÿ·<âZ†ÁæäfΜx¢0 4þ^Eþþ<*²hIÔà•oáÖ·ðN¢û<ÕÏ;Ð8Lžd*ˆü5óí–ƒ28g<¡=Ìy› vE¢Dƒà[(§BVY}¦k-(ŒbxÒØQÈtöÖõIå1™¬Ή¶„é—´o“xúK‘‘kL ¿ÏÄ/€ãUù0"{?v€×9d±+Û,ïdÊøt’ˆÁ^§É‰jP³ÜtÄ%ÞQ¼UDÔgÚñ'àÒˆô n€KBW%YE‘±‘Žƒõ&í²¢ÒP4à ¸F$`Ð'j1èPTŠB5ÆJæ Ñ®5™ /þ–@D"÷¤Âmì“ =ºwöoGµOÃ|ˆÓJ&mèí„[Ù„~Ä×…R䕆EÝåuYÏ3<˜û­ýuG؆Ϡ‚˜ÊlÕüÃÄâdmT‚Ù^/ÒÛÀëK£ ÷Ô^ ½t?›cVݳé}$ 7í©6†¥`0˜­+]TÉi”¶VäÕOYW0ò êo‹pà3°cã¤jÇ8Q-8²vçÑcXL¢LÂR-Éìÿ.^BRÚ•—ÔG8I„èmVãT¡(½†?o³’~oÜæOð°EaKþKúþ=üy þ±É/þT¬Ð?º´vçf|‘î*už/~._·ž¼ÕùSršY‹jZtÓbѵöŒä6mÚÛŸ–«gM=hòð§¯fÑ~†húþ²|ÿ˜9u%|,úx›†°ÆO¤PÉ'zô‡õÂx½" ø¸à[ÅCX•·lqäb^ZP<¼n1vÛºx[.^å‹éSˆä•~låªõú‹Ö)\¹_˜ò¨\ý~ÅâÃ9˜TXÆU*L1ùö9+­ZøqKG\Cö\T<=óô븦èö¹%iCr†À¿lÝÓ5¤ìm‹ØûJV÷xŃ…ÁPR´{Ûòðiµ®cËgQxy?ƒ™Ñçz—µ ŠÕ7zS$eÃ8,X… ’žR{P誤Pž5;O[ä†]ÙÁ/xü±%-•«$ó=ïtžÔKW­‘šÆîm5¼Œô®5SÁù7;ŒaÒ‘s>mš ¯ÛÖRáéŒB¹aP©ºý¬|Ü­³ÛRChk§©ŸÃ"/\xWÑvM†7­‹…5/вռÕZYÂõ$JÆ¿T:Åb´¡…ìÉê#ìT=ðs›,J80•±^«‘"3+ç·Dœ9fIT'Bˆ•£/yˆ¿t¢ÀI :Q°À‘hœ„™9Ú[¾•@ªFwUˆFÔÚ!PvgŒFzµ•yQ¨DHë—·T#ù(a ¥U>ú _U ÿÁ=òŒ|ozø%ÑS‚$›Š.áS‰v.yU<Ì’Î^Ýn½,ûšfÌÌ” i‘L«²`Ó1^ XÞSÙ3Þ38!Žd’7\g20îÌ!pÉdüSØÇøÀ(Ý9êœ'¤ÿ¥ RÄ’Æ…T†¡>ç9'£@’!¹Î>‚¢g7QúZè&»ù×¼R‰zÓմظa=¦—ïKø›t•*ƒqg‡»*iZÄÎWˆ•_$-& ÓŒ×_qdŸØQÃéZe4d¦‚RÉÄÎú‰o«4_‰•ÁÌLþà ˜›–V`ãf€Âܯê=¼gw,`!AüT’º¿1Ñicž‹r³D¡Ú&ˆÀ°êJ‚”$åZkÕ$ÉžZ³ÝJ:í‹NÌXb}(Ì%´ð>TH¸J"ù)go’~Wn…÷HÉQ°‘DÚ°PµÚ¶X¸Pr¶­D'îœÏI«%ï¢À°™f¿Â‚‹äÌxR± ÕÇùWaéå®ýeÇ))HÞÈål‰Ê:á*BEoBþ;DÜÙkJ@ªÁ€¡C¹y#|¹à@jŽ(P«¹wYyHW•´[¦&*’Õt:mT=ÈI^¨óý©cý Pô¤#yT€¬‹m;záÉÁh À+Àä@áPÌ @.PJoçäÓX&§Á w]qš½ ÇnÏw9Ì(b å)KûšQ6*Û)‰÷èÔDIv,·ä@±ÖµÆ™«i‘ÅŸt°>ùÊéç-O¶¥<4L¸² Rª|ÞñøH$>J9UVõ‡ä¦“j,ÚîÝ „˜>KS°’QR®KÍžd‹¶Þ.má{4cKø ©yÑr`yã¼ÏÒåÙwùaÄF/<Ä­$8}_¹k°,â³øKo°R.8{tl­²i†×¾£ ªJ›œw(ÐÉ}ˆ1V5¾…m¼¤á¢5- [Œ¿09€Å'Lå’Ý8áÚ“úÂÜ´%Jve`¼²%y’žs€rãT´€L|”UI,5RÕ» ¸zö#Ö&%yg—RÒZ”Å;¦¹<Î÷nV”ü„O° vX pXUÃM¨Öª+Õë…Ã1N}íÅ´/t°Î…ZÓ&TKrRé£ Õ`Ñ0 É?†àq¦àK×ã†âƒ€âž"Ú'®DÁ»ð‹d Ö\Œ ­ I€H6(?®‚g`x‚³—T©G?T0”&ùþCV·êâ㺉Öø¬[¿¡ÑÌrKQ:4ѵ¸I\ó”@4úÞ:+(B È¥­¤ôŸ,l…H±›ÄÇ ‚TüVžmù¶ko¤Da„^kíY´mF¯ÚF$\UeC¤úŸÑó¸ÓöEÙc¤—$H@|yí?À.þ· ò‡ka0RZ }Ŭ³Ò¾(ÞÝËGz¨h4pÔfjQø=È£ =AzŠ%=H,ÀPH\8°{ŒÅ)|Êw Ø4p¯I3p"º…c'V4¼©mÎKÏ®†osÛ]À¾–"°4Ni&–à6[òX<Ë‹ûŽ"MªÜ‹UÔF@wE,Éç83ZÁí ‰ž‹1w–ÌÙóh9ÂYWöOCܤÑFó=÷H…>'‰·¦ ¥À–õ.–'i8|@-> :øÅ”yg;BbN„¶*dýNý§3°D€ZWeßw§×+˜iD·/+êG·a¼§ðLkîc`vCQDÕ®$šRg'³{â¨l¶3â= £¯…E«Êv¤Þh]*~ Ó†r>N5â)òåTeá$*“ˆ†ßƒˆÆ»äŸ®ƒq)Ñk|†M˜Éþ˜ƒ£?̸˜_TâS'§Ñ¡€î"S¼Æî!¤´î{ôÓ®äDÕ±¸—Uj’‰Ì”´¨±qBª£h¥‡8»Èž8¥À1;U>‰³1çBª*3XšG ¾§[\ÊÃ/¡sòe1À® CÏý#àG€e|R-åÈ.9cã-£iñ"÷»=SÈ'“›RAµöa"Ëy‘ÌþxtÜëç¨Ó·Á‡'°ðg:œò#Äã±¥œ“q ×ÇÖòq+xSM¨¢3‰B­¡ÇR¸¡uÂa.g0D´¯tWˆMW…Øá2;¼‚ì.žðìÅc¡MÕÖD˜å(¾?¨á1øl¾ƒ#³º œÁcÂ!X*1ZÅÝz•9g…‚Éß`>,P—’œÂÕªkÒ,n­» GˆA°®ª¨1e¹˜@A·>9€7¶21Ó:!aUAè9jÕqdÓ·ªO‡`uö2XÏ=«mG©p¼£\²´ã:*ÏiÕÚaB¹4ÅÀ¡ÛBMû:?sÆÝšeãç/’‘ÎÌe€ =’µýÌ`ÈÕ°ª„' –{ÊŸªóÜ +êŽ4Oí ¯"‘+„0ƒ9ÈÏM!aåÒ99Œh6òð«èh¤dìñAÐXévqZÈrü•ÀHÌhé\ÞÐâ`yÛã²Z%µã)éG[¥ô©·tÝG!Ö‚;tЏe¤ê:u‡‚”_%c¾ó Nm3Aí~½ #!W5 Ë6‘ 6ÓZ³1«´;ص' ðÏý. ä~óÌsNâ\ªœ‡u´öû'×EnÝC'ÞÁª¿`}cØw«àWjGÏ%@÷Úåš‹*¿Üi»$L¢“fC?ê<®'î/²§ «u{Ã/ §!ÍŒ}û¿`ý´dš8ýúyÎ!.´p¯«þ,rYK)kªšˆf]ŠÊ]X Øø–¬ÃƬ`(îЙ"tXN)ÎU™R`àR»›EVg“y>›ýn.L3{1.´•+#æ…׺è:Ý«®‚ów¨ª ³ùÒ'›ó¤-“y‰cöÒi$ÉEŸœ 1­ò(³1µ« ’öøj5ƒ¥V÷;Ê@ü’@Ò_3¹ŽmüIVO•Œ‡¨-¡D®Š+K¶f&–Ê%–UÐSÎ~¡ôçœÑ¸ð`Zt%‚ó¹WŒ&Kê\kFp—TÖ² u6)œiCß!ã½ör LÇ=Ÿ²U­§ÖúÒ¶z2沿[iÙQWw%“ªèorUMr¯­ÑþõàzgJkÐKù‹Ú ú¼Œ¯©‚®f~ÃB”²5kìçͰίÒñu­¤÷Ê¥Ž°]z¸Šùb\™fÝ,#±}Ý&Suª®iqí©çF2†lš?ARÄä„Ó ìââð4ÓŠÜKNK· 7»×¸P5L‡ZÒròËÖâ´4òåÄÊOѶ÷¥©Ê=à2>Ÿ߀/¬ÕZ¯·ç¦e³è«ÕXdÖ–4»‰&,Â#]¥•Í׺“&ÿN<2RT“t=åÎõÉøÊ­Ã¬!Šªk{Ð=y;Ã…eƒá-w‡HW6xB9lÑ—_Pän,S*eeX.c'Nïü¥•¶Â‰öpW ŸUO3oåΗnÆf ºÞ—ÿ›ÓÛϳ±{ôZÅT:¼²Ê× ™Ù‚H3é9GóâõçUpZ‰mÁó#—Fª®Š^¡ûlÑ|¿51.ëEbÒçuŸœ à•U:u"ú Œ±y!tN×D„‰8üs-!§j/?‹Î•“šSè(K÷ÇnõëLwQ6}ú¹qš~$êt@ÜTNu?Dµñü¯ívÚdÞG>ïpG§£=R)Þu¶ ÃØ)+üü {b~Õ¾Ò¹;â‚‚då,ù@÷o:uj ç«‹ÚÇË¿í²Ðf*NØgþ¥›Æí`LŠÒPZ˜òÿ’fo1>*GÉïm§ܑ£Ù’ÛÚZËe“Üx'xù·I²ë¾›a¯’R0SÕ|Fb ”ŒÍ<Ф×Ê•QñÈÐB”g EôZú¡Ívé‚sXN?$î<]µ”ˉÄ#‘‰RQÍÝ’ª¼ _Qõ¸Þçl×”£™17ƒ1¶ªFæ,jàZ»Z(ÓUNì¬-s¿²8b> stream xœµ\mo7’!xæàém¾6ûc6›dsÈÅ9[w‹…×d)¶ƒu,g-%1îÏë•ÅîIvŽfºÙl’U¬zê©âü|2îd„ÿøïùO÷þôx:yùîÞxòòÞÏ÷Þ<á?ç?üù´6®^æqv'§/îÑ“îdò'SˆÃèONº÷tWöi7ìýÎÕ¿?Êè†Ñ¥Ýã}pÃ<·{´÷e˜Kò»¿í!LÃ8N»¯öa÷ÍþàwßîK®WÊîtˆ»/áÒãýÁÑÍïjß_ׇ|®L»'ûCÞ}7j;è½Äy÷<‡­kŸµ'ÇÏâõÏ÷óX‡ã¹{¼ñ>}·ççŸþg­óv¶1¹!—:áÓ‹:I˜ØXÿ…}‚ƾ{ã0¹y¦Fg0Ê´û•çZê…Pê›cؽ‡YÓ¢\ÕY_RËíi÷Ã>îõÚE ½.ÃuÊ?Õ&xï Lø ._ÖA¼¡§ÏøcH°ÆØö7X5hö®­Í•¬\ÇÎ^¶çqø¿:Ö©>áæ:ÖºÌUŠ1ìø«ý\G>æ„/¯C¬o,¹½zªãõðÆzý-¼äu}4x/+U2ž*Ù>‚@ìç&¦¿kÛìö,7Zá„11Šp^P–LC´â{Xäùoà¿QŸ\ö?dyöå­½Ûžáï?öuÎ3¬Feȸv×$bïqu.`e"¬y•‘¬Ë% r&OÂÑÖ—Å&Gšâ늕búy¥¯ªBùÇŒŠ ²+ñäàÂ2la˜@]TÁ_ö„v^ÿ‘ž’ÀsÁíI„±îdQdÖ¿³öÑYÖ2¥ÚY·«sØZZø›Š›yûŽ •­æ…UÖã«¶Öéægwº/ö#Œ6f®é[“Nf÷vlÖè°L*án[ðMÛ¨U7XÑëô&ºoö0,Ú kVsÄþ`máu)á[x\KÐÖ½”yÃnªï…¡pëÚÉŒ}ê ~U5:ÐÛ%´ÐnW°!qB£yXìf[©Ã…#¾DÄ#ݾFëŠÚ?šhyžññç¬:´Â zñvî碩Ø',^ýB´£9CU•o(Up§ìÕøÐ¶EkkÆ#g£é[[Ú.E´ Gái¼d6f ¸²Tÿå=mU½Ä« 5Pkç{àp`-Í&kȤÞ1Gã`ØPù™Œüsx¬/½ÕúéÕ< >º†dÂØF\ šà_ú½’Åá=ðM3U󄸵ñÚrC½9yh1gÇì ?Õn_6‘-LïþÖ,!8 —ïàØe zKò›Øä¼_–¬à $Ŷ]£nÉLÒáY¤wQÍ[ô£þHíÇ[µPlE9ÌÇNQAAÙíeï¨Ü8Åzóûöü_O6ŠaÄÓÚ±¬Ð3ÜÌ"L@[y>€¬eì6e«]¶ïëi ^8¯)`)`”ÅÆ€Æ]Ð*A3ðø¯š{kªÒH´Úª¼í×ZÙ좱av}›Ñ|ÍpŠ&Ý[®MæaãЕÄdKÇÌë#žï Ü YtT?zVû=´&ó‡jÑà¿/&z޵ »!äSÞô ÷):ÑGü¹¶Å6WÐÎ@{æî:W.V^ÛIù²=°BÈÍðb?ªîp½€E½òÉÄšWäÇ1ݼííÜꮈÅá´¶Ÿ©#„ç0æçÿ¢=aLü_{³R$¢HMa{ï{UÔ_Á8×Ý»•b%%í¡©õV‰l: òfDÀÒL£¢ümÓ¬&¦Œ­7;Í úÒå¯ÒOµ]3Ûg©9]äœ oe»ÇI¹ë ªÑ™€Ë BXn[йú !ct ·üñ¸¼N2¢3%GJ&) ɋ꼕±°U©:¨PìÕL lµ4ôî –µIš»B«V`¦q$ïÅŽwî~±­¨Ÿ2êÎu×Ãú›Ð›L<¯ÞìØð$Ȥ|´a¡»!k„ÿc6¡Âñ¿óÿ…é˜7€WB9ÝÄPTï`ˆù÷à E|hLôv{ƒŒD³Y"1XÌb%’åfá~dE™‡I¶\Á¦Ü#a;öÁwè! ãë.”ƒžÆq ÜÄîôòà~Ÿ2{xlåŸÕ¿ƒz#œF¯ðânÇ4Ö ÝQÈ´m®Å¨4?:Ï[õCsH¨ú>(AÐ_&î¾VˆÓ~”÷DxV hìóÐŽ,mÒ[Ý80 R°ûÎÝ\°·KcÄ‘¶´_µ@øXFú3Q}To‹só¿ÁzøE8/L%¿žº:ÿf&ƒÿñ=èGÁ‘eé:ÜŠÓ  ð’Û,| ª²áœ{ç%‘’‰ŒÑb ¨’¦yˆ>£v‰Óó½Ó‹¾Ñ·¿ìnú¨/¹Þ,gPû¦ÖöðDó¢Ô&7Á¤ æùµ9÷¯ýGñÍÅz0êX@^xÔO麭 ”¦øyVƒãbÍ qŠÄÁ žØàiA™"˜øY¿ûßj’îö-”û`Of´LZ&ò5F1^›ñ¨GM2Äk¨å^Ïöâ¸NXM>bÛ…mJ±EpIYEz!.¼S—G8RXš·¡9kí‚ÀäQðfÈQ7ƒ!ÙoAVâÒ”ìD#°.#{:ô³5T‘¨³mr“&%o›ôÎ;£ÄŒÜ¶[L´‹ð÷~}äßë¿ûV”M™hËðù,´•2v1_j~-*1ÄTL¿·Yv£b’> î&ÜIÁNÐö<µ›‡€™±oïþ¸hi™W…€Íÿu|Bĸ ={NÊðñ–O@ÈÑ•¥‘r^×ö¯ß/²’¼H8Ã91ö]úŠæÜ[ОC’e¾0^Š"·Ño¦-ƒµ˜’ÍXŒ}ª8{µlozÛÆ_PeAHô1›ä»°áZdƒˆ:.AÎ%át\[?›Ç]lziÊ^¬‰2²’q˜²‰ä]ë­EÏòþª›ÕäΠݣ_ ÆS6"òÙ›ÏNJÕO°ê;¶ÅÖ0buøô;ð¤4ïÞ>ªòøØˆ™õмJꈎ¿CPÖ L –ÍË|µ¶8¡lÍct&XGX‡²Æ¡, }(ªÏ@?ó¼HÁQvNóù‹¶k䯳DWôBZè ú#a×ú›šÔ=Š9£Î½L]H%¯ÏÒ©Í“ –¸óðkÔRˆÏ;7|Ô`f± Áf"UL­ºÂR4ã>Vå”ÚÔ…m]ڟ⇼û¿Ú_H¬a¬•˜¥‹öÇ´íÉæ4mœÉð4ö48ö\¬æK±SlT¨ñ{š0ÐTM=Ä˲[w:6ðõ–Œ¶±Ý*VZý¡¸VÔrÌÀe °ØÂq »+Îh·— ¥ºØwÎÿŽ)ö ýˆLîÓ2qX¸©¤½Úat5÷ )εW­ÛjB£WyÇÒ†KB2ERšŽWåøôVŒÌt$2Eª.¼­Q׫’3Éé¨Ù¦ÙÙj’@úÂd¥(‘ÞÏ–¼1“EÌ °cËÄ. ;6œ+%ÝàcƒV]iÔCΕ¼ ^d½Êô ý£P_<(SÙ‚lÁ òëÐ ‚êÆ/™ GjX$,Èe³EƒÆ4Ý¥š„byv¤+ƺôFLÙeA¿Ÿê’°ÃKÌ!þräÔ3å|¯t’gÒ®‡cnd•Dá³!g¤ü¸Ðèµ[%ƒ·ªñp )wÆQ˜m®ê¹™ñaÚyõÆï˵zð¯/†ÁoÀÅÎïÌöÌwAyBèù £&PIŸÆe9O]ÆQ­8TÑ!™cIÃŒsìHRÂÒôˆ_Þ3¿–³”)&fÀ§f¥Õ)ꊪRë‰õ,:Òe…Ï&¤$½x@;dU•çê‚x[Ly¬ä±~T÷Z;[øktUÕ¢àØ¤½SÉÀÔcÃ-eˆa.^ü)DEæ¿î“>€Ôê¬É_¬!-í(à˶»m…àÍA5îº ?éܦ,·’~†F4Õ¦üôe£´ï^•%09Âk l(d§HNX«ú¯¹ÿz&¶6}q¸D\}Wz¿²Z5 î–:³Ñ«w0»á(Ûb#¡ý8§v_|B]¹Ž ïJEtF0Ë6Ë ›´D̂ҧ Q7-×g™!9ð{4ñÐËg#|"Q9ñâyd¬šTŒ¹YͼÔB¢¸Ô6•=J=ÍŠK ¢ûçÁÃ3Rw¬e0²k\”r6|(õå¥Usvîì´öMêÇSÖTs£\:<–uD¿vªÆjQéwÝ´øæÔŽ2 Z~^¤¨Ó¸Óc 7f*'®Ž$%€&v©˜1¨£ ûŠéÂ4Õ18sÙm7‰u~z‹»¯ëÕi#Ç÷ãà)ˆÝŒtU˜Ê0%°ÇUê…cN;ó»ÎÉù8¡Î—q¨a9¢Õ«Sœ@N5‚œfªuÛAÂà‡j}ÆR(Vo×p ¼zO‘íæ)Ì3’Õ¤ÇÌêˆ'ÈG›·¿noëžžJ>@àê‡<%ÄDPë•|6ïÔ»2÷ˆ”mí²¾¾›¾ûn—)f(…ã§_·÷Ñ3yŒvf—$'ïªa–·oáÕªñÞ°X›õ´l$Ae&ë` cµ&é¥ëf™ôhfWº+µëx’Äsbï3Lë²ÉUgŽ‘D‡@·×L i¢e•§ÑÞ´ é ”ncsbë\ê`2% êûÚú÷²‚z”§ô”ãªD—*Ѫ ±ÓÖIh›ýló†TÁï2†¸° u„ÒÓ)l³j¨ª2~ÃŒÈ;OÞÜRƒÞ´Ì£têSÆŽ A€Ô*«– 9âclY9-ÿ4[b› og4”Û-NœQ|»í¯VÕ2¦h²SŸÅù(žªeñ³ÂrK™6Îg­ŠFuñ$abõ¬1fÜ^¼·$ÄCÉÌy­çüLNëg¡X_·õŠEÃdm}=!ׂÇÔ;eMä-öZùLòî6º mÌ ‘蛽Qx_:#±¢3·ñZ®‘7ìmUݼC°;±Ñ&‡Å*zûLé ‹åÆVˆîéÃ%|¥ø¦é»Éê?¦¾ÏÃq~d®nZ•=b$ÛR•-´ØT8MÁÙ)¼´¡$ ¹Îù椞$„ìÁ^A™· P†x“åà&l„&lÅcÇÑ ¦¡³’ ýøé>ú QJEÛŸȰæ5®y\ŽÝÑÞœqÊɤærˆúªq2Ù¤Ö‹§íâzñ‘~ú¶Ý¾o_ÆÜòÊGíâ÷zñ‹vÑÜïß$ËôLÖßáG¨z®.ç¡õ”@ܬ[`¸»ßŒÉy”¼!càä†eé“)˃߯,þXeyð‡*˃-e¹å•§,>²,‰úêqfÐjHæ#.Céz—µ¼kåù¥ò N A-!ÔÞo—±µ]áÖ?ùЬ÷N Þ%jéù|)"ðtºFÓ”ŠÚŽ “i°w7Ƭ¸£ŸŸÑ_ç[fÕë 'D›l*Ü„a¯Óëžæþ3K“A°×^5C”E˜K›VWÃ¥@@jÞŽä ½C*õed2vqÕì¹>žÁ784 ½PíåÜ5RÌÙ[*ðOµ—' ¦˜;`†?‚ Þ;Ž›&…¹ªG 4âFy£ilN›ÊÄIzÓ”ÃIåXè·ÍAµŒ¦yy(Æ„éíWØ@Ïí”ã4·ºy¸E§@Ë@ãöûY[*¿fÚÖU,šŸ,‘ßdX$ñ¹v“ÓÂñ´øfþdàô9õÃ…¸ö †®=³âèýFLÒÕ)Ûç¬CfªlÿÄu<0ÿ/Oïýwýïÿe÷&endstream endobj 565 0 obj 5613 endobj 569 0 obj <> stream xœå\Ys7’~×úG0ü¢.¯»]8êzôÊÇxB^{eNÄÌzü “²¤0MÒ–dK;~'(T7iÏîþԹòÌqÙ}ÜùÝ×ÝÞïÎáú§Ý^n<éö!¸CßO»9}Hw¼_ÒMÛè¯:Žt÷»ÿN#~Òñ—OÒ(~Hmâî³.¤ÑBˆ»/àÎcø/µ Ñ–yÁn0™/µÙ§4ƒewßtû1]õ~÷·Î§ƒwØá¼›#öúkçié¥Àö¼ö}è“[ÁËÔá• vÏÒd¯;?¦i óîuGW~éö~¸„–i ó´»I‚¸æ¯©#4}‘f–šñ*Ãî/iìk¸y m{ww‘F‚î?¥KðŸ¹Íãî) 9Òc`‘Ëî*u})ãÀ>„ñ'3Ùt„†0諼#0•0z7ÀôÒpέæhìs3x$¯§²Ìôô´ ·»…1ø.HÚ/áŸTfæãKžÞ5/Ͳ¬4X0ï)´y“†NݦÉï¾×°>œ7tö»Ÿaètc´­¡óëNÄ™æ ‹‰#ÌÓàf2ªMÇz;MøYžO?÷ù†žYs¸PúIsEhñ¤x^Ãä@‰8Q~„Û“+¾$ëon|¾(]à玂 èÍQdUô…gÖ/`ÄÂ@ ËL2m¾…¤Õ:ÔI0zzPÇÔ¢ ö¿îý¯]€åŽC–NŠ5KLê4”{ì=Žq‡Ý.®w_æ€ ~!gèãÍ„äß Uï|íÊ j\8ÒYËÁ©!\¾Œ£W0êŒb¥:H4á´ê iŽ[ª#í×½¼£\ÐöÝ_²~ÂÕ—úi¥eTCký†åÄÆù¬ðn²à@m¥S8ęܣÍhÔZ´øìq:pï‡ôuë=Çc‡Í«:[ðÞä= I}|Ÿ«,0mÉ÷òt=?2€Ü!ù^  ¿ïdÆï§fðó÷F…-ú0—‹ j:×p)Œ$Gh»ô’uÈÎw<ö„ònÊÔ§ÍRÞðvÚ\tµØ5ÁEF¹-ËàxKµ#c Qê(……X2”\ z:ZNl‚ yÚ©<ðˆò„Jýƒôó¹l õü¸)ø<Á´µõsoÏð´›Õ[š%¯a¶öFŸæ­¸µ@Ò“µ°¨@”!陬“ -$âk¹Si%(X@=ÔâÈ_tVï5ÔÓ/0 ]ë„âµÒ€ó+Z‚Jù?3X=Ã]Z$5 _¿Mƒ[ߥßt›/±T<°˜EˆúèŽ>í!„ŸëÔò¶ÊèxÖâRšã#ñ‰ ¸Óâ±+ðä¬ðÒð•`_Z:ŠÀ¬Ü¤WÊè›KQG¯e®Yù„ì‹Ë¡¹ÛÖóÓM9\¬’©ˆ+ãÐßæøÙüÎ î~ #Yl¦ÃÀÓã`pel–œŒ_hYr¨ZO»Î½Œ2(”#ƒ ^j¦•¾A÷ÔyGúºår³]ÎRqê-ÉnÜQ÷­‘rÄl‰Dçé¨1aIoãõ@d® j: ´B±”¯Ôô ËÒ@ÔÖ™2~ø³®Ä}y™´i¹ p‡Më…3ñG­×>¸áPªÉ·êFµü&¸–Oã½BËq¯Š\ÁId@^üpGÐHë¶!÷û¤Dúf#›–hè›Â‰?Úî»yt©Á^”ºáúÌrœY¾aˆÂß»H½YµÛèƒQb…³iƒü*¸*6 Žþ$* ÙHnRÊþ8wÏ9ÖX†¼GfM·…æ"q0s$R ¥E Å`C>~D ïß©—hê Ë•%yÍáI‚Z-qàlñ1 ñ#DˆÆVQŒÑù’Iª–l"½ßÌÁª€Zit,F3ä3ùòo$$}†®Âæ)GÃI÷™å ŒÒ*ÂÚŪÖh0ŽOcLØZyàu®¹& ®:ã?óJó¼›ÁÍb2öI7ƒþ‰‘åaÁ&¦aS\ñU¾úXB;^a©„ f±'”Ý+†ˆßGúÆ›Íéö½ãÂ3çkbö`µÚ“{âƒpÍõF‰‡ây¡È!³ÐV»º¡Z‹V2OÓjχLO,ÎoÎ.9ƒxs~…fåG~AàŠ³!×ÿeÆY«HÞ*rb߸׵8ËXJÛ×;F*!ZG ¡Š(׈ãHœÍ.“0Öó`¡A-†èËÃ6nÙô¸_ȨˆNœLMi@¥á!pË!Íúñƒó¾%‰©&5Ã0JŒè‚[íÍûªš@â@@¦¢.¬Bý?£nAoø!«-=HC²â-Ù ÇiRL¥ô?ËÖ§-⳨±^#ÆÂXhï1ô)”'°|p¶~% ‹¿4Ûæ)VÚýƒ?Îc¾ýƒ®÷)y‚³ÒþoDj"¬´;¿vjîQ¹Ñ72’lA?mP~ ꣵšS¼±ÛpvÒ(款Èç œPh­Óz›[Þ×× ‡pž«àÜ/æ·Jj«È4™1m@Îb˜õìE¯Ff,áf4ÂyPA×yÌ ‰w#ÉÁ8Û YL:eîÝÙr}ðçü¤'íƒ~½Ò» |0f€ùïã2cÄ+ ÿÒ ™‚søþE>_ꘟæ‹Ðˆ×%bºÿA¾ÿ^<Ï?Ö‹OòÅsÛ]i:û ;Û»=è+½øu¾X ?ô x¥™‘ÌOUÓ*/š÷=èAiEWÊà«’) A|Oc·ã¬~IØà,r Ç¥_FƒÆÏ#º_Å­ÂÄðïá:ˆdzœ¶=7ë€ÕêÅ ²ÖÌ?GG_v‚Ià&&°)•Ò‹‘ž)/}+@EÉ;3~ׄª•Â)ÙÜ7ÃÆo$’”zkò´Ù¨š< þ„|uÅ–ŒKC鄱©/ÜÉ0uàBáBvJ÷fÿ£øé×ÙwÏàb»E|»äüÞÉ·›F|”lͲå{Îtc W BOC•ÂÔxð¦j\Ó+ãh ]ÊÞEãÌ­…l|Â4ˆk@*ú>TÈ(ƒÝV$ëùМNqy¼6l´Æúšoƒ©™7>§÷Y]õs³Dâ¡Þ_ùü·0­1ôAìK,UgXT{^JÔ¨*3» bi“›‘Ó:¿~£Vgâß&}“cÅ¡âoÐ`¶ð:J¦ecŽDÓ¡ë1™X:M*Ó§ENÏ(F<„1ZvCÿ&¦J`|OÙ»y~ÄoÀi`% ]"ªe³´æ‰¼Å£…hø¬Ÿ%×ÞÓW7בuY7‘Ôµ¤lË;!# ‹$%6†Ò­\㫦qäB' ò#ÒÜcÕ¤P7,KŠcþ£I*äÞ°$ä F)B)t­¯t´•À¹`'WÈèÉ~×ÍœËc ø«Ò´8SŒj²wrÎc «‚,Õ›Œ)­ÛÜUi)kR”ë\f+ý¡§”Ô7QLJtñ7ª`0”C“S“¯è`ƒ_á§òMLNÓbôÏMö¶*†0ò›zÃÉ®+óŠÀ«‹AiÅQÓ¼±ö4à¶ítIžL˜‰ØÎÓkðfL™¬¶1¶·q(\bb3D~ÂGô|«|µ®±$’¸JØï1SU˜£!):¡ƒA ¬)‡eýÔ´ÃI ÑW&±8ÈÃÂó=TÔ/ÿÓRéH:¤õd[ÕçÔ¹ªgí-Võ‚Å¥L÷.®Jsp»T¯?“¦G’iò”m/²L2æ½ä¤Òó•N̾™WŽ{Lõ¯ù¢vô>ˆ}E{w‡€’ÄQêJÃRC>S»\šoÁà[Xp¡ eŽ”éˆ Ê ¡’ËÎ[¥/®š]ù8Ü–€~a@‚¬^«`võ¬8¸ÉÁ"2°R‡ªÜª²«½<αï7FO¥Ö24朩-œÕQ++åjøŽàYký…õ`3f£ oXþ˜ðGù•¦.e¿ÚJ˜ Ø Sœ8IÆ'\އ0uâEæ¥Mø¬[ÜAÓª¦ºAÝy‰¹åäÁH¦†5yíJžÂdªc}ƯlAŘÎ*~‘²/öã7Â*è/¤Y…¶æÇA³N†’Õu‡qv60»ú¤‡Ø¦.Iœd{,\fz·‰0gJGôãeË}ÛGH„k–­¨ß•LëâEÌA+nié°Ö¾ŸSVîú)ÈKHìÈúy¹§¾ó3¹†¦˜ÌÏ®NìNn«Î65m]€_­Œdse+×ë†S®õ2/¤†ôÜ\Ûoêg{~Àøq”Mêi¼èó/Š‘V^¡Ÿ%ïaÊ=ŸöGÉK]㢼Ïun—÷ý›ºT]æQv~oØ×£KîªçвÇ~m?k3é[ùæäxxÓŸª ç›A ²Æ,3äX1¹\v¢ö?èWä§ ^È[ƒürM$}Þîˆ1~=!áÛÎ| @G;›žþ¦•tþ8_|Ò5RÉôbN*?η߷Œœ;;ñȯòůõâ£VöúqgRÖ"šï²hðgrc•Â.ö°­^à]“u¬d,—Þ,ë¸Æ}V[~†QœàV)6-H%DÉ07<î©?úÚ6(JáøE‘Í7HŽrÿôŠTTóÚÊ\:©™t¢4i-¯iÌÑ©6ù2¨52—¶É¯fùâEiløµÅu*@œ(®‰/*»$5ÖR[üBØcÉCÿˆäsS-²DJßéõ4zŒ0ªK"Z•«Ágî‡}õºIq[J_Ã)Q¿?2#™+ð-µzßRY..’¤ì«i¨D¯ËÞ¥pVl•¦rˆ«õ&ÃÎR4–Éezkz(­ž E ¥ÂíKmŠ|{Ú9S/À‘ê—튮T¯©Õ ­l¼ Î)¶ífÙÊû#ÇK±GŽøKIÚŒ‰8ßô^ ?Ay‹Uæ¼™«š¤üCô÷ 6JeÑ_æMÆ9ô÷d“!º´G²8ù>J‰fMìçÔË+Nù L3ŒSéÉK°U½{Ëø žs›âmàc}#¦ÁY¸ã‘ ³<êOǬ££2„ã‡kå3ŠÕü͉òïq¬˜¦Ñ*¢Ï¼w¶¦l|ûåc¯E5bm$‚µ,´IR\Íl˜ü’ª w‚¼¼ƒ¼b~²m̶êô¨›xåZ¤dΰ}Q^w;9GáCŠÕhÈ,Ù=×s£rÞ¤@r ¹»]'2ä4¡ÌëߪrãuFSa·rIMÙwN¬ùX ^Ú2⣋…½+ ,qΘÁR”(cã½÷;Á¨Ê_q ¸dÙ°^f¬úcÈ|„0$În<ÔµÝ@AUÅEéH>:W™½4”î:K[Õ¡yå E-vЊAYŠª>›ÞG[æc Ì`sBO¡ JM…Ñä‘Ö–á!G8.«¿ Cµ»¡XM‘,ãVœÀsc•Œ4•”÷¶%ýo^ݱ´kÝ’ÁÙ¡e1…YÄ6”ú0‡¿Uè-3£“×åp~Ì ~ø’ô¬˜ÊÅ ”ׇCñ ß÷ÐÄréµx2Å8õ45L8?s1„ó®òßfÝU©»uíx,SQ“:/1H´.ƒ3-~dïc%»Çø‘•ö¯]Q…E&Ñ»¦(ß§)™é• È<¡P^éý×6 f(¹øZ/šbÿ·zñ¶ÕÇ”è7tc»›àá«CcΫ¨²ó³:X±fËÆ¼ÃŒ& ëœGþ+ öóüƨ_¯Ë$´-é$!³¾“72æšæÁW |­ön[øŽ•;ÔÜ¿™ÿ2þ?AæÃ32GæÃ2Þ™Ÿž?øŸôïŸR‚_¤endstream endobj 570 0 obj 5135 endobj 574 0 obj <> stream xœµ\YoÝÆ~7ŒþÁ}Èe«Ë³Ã}pÛ$uÑÔ©£ )Ò>(’m±%%Ž·þúÎYçÌW–†¬{ÉYÏœå;ËèÇ£¡øÇ¿Ï^ÜùôÑ|ôôåáèéïŒøòˆ½8úÃInàÇü¤_†e<:yr‡zŽG³;š}èwtòâÎw»ÔÅ]߹ݘøyŸ†±Ƹ{Ôù±_?îv.õKŠn÷nïýÜüû¼ó»ÝÞíþÚ¥)?I»“nvŸÁ£GÝ~¤—Ëc‘;¹)0ï¾îöÓî+x‘ÛÁè),»?B?lÇÌ#ÜŸßï–!/Çñðøâ!|ú[Çýÿ}ò—¼ÛÑÙ݆8öSÊ>9Ï›„ ù'vïùíÞý<. 5Âá/`}ó‹ÇMþÔícþv?ÂŽ^å·°¾¼×gy_úòEÞ ­¾]vnÞýœ©óÆY–Or‹ÝU^BîãG—i1áëÝuþ¾`·³ü£bÓw0|»„=…Òøg¡¬Ô_<̓ëKèy<ÏL£SZA´ÏŽø²œôË›tð5I#|ª{ô¸péª2»Ì™—ätçñ†µêS ®ô_;yô¯Fˆy Q¦öùȇ!îÎé`l?†I–?¹ HËqH˜ñûÜ™yºt9‡ÍŒx80´Y€ ¦¼£Ü:·ñ»×$É›~YhBH +»oèÌ`•óìpO0ÝØ+-¦r¢Ðh?ú>N ”@*¦ÏŠ45U€ Lšã¼€Ë ØLN2øˆ‹BNƒzþðÅHà[`·kèõô ȳÐÙ/“%¸`ùA Xû¡ØçahÒZ6U¬'ëÂѯp³ùYÖ‹+#V r%ka€™äsœpÇÕºñòº |g÷L¾w­×ÊNðn„%dÅ·,ã’Y O˜_O¸´órÚó?¢ 9Åýʈñªdp!@J¸Õ'ÀPÔžéra˜œI()?3ìþ¸bwâ3" ²Y\’Jd£Üð›r |É»óó¢œm‡* xФ¦PÁdžM_wÑé:{n1} Û\ùž‚µÀ Áœ ÿ3Pùqž ¤8±54*3ÃÏ;èµU±&_V³èø= óŠxqï§!Gzmîçi´üu ã5ŒÒŇ¢FB#XÆP…RY&³” WÎò­rÝuá89ÂÂv'XÑ!6úÏC¶Ù{UL°Ùq6£¼¾¤Lç5gwŽ£V`z´+ý°V3ò=Š„eÀñZÌß¹aÊ’äF dž8ãà•0…µ­ aBu§l sp‡9,)+ÈB=ðTZ¬6¡2÷J~ øš•Z60Î2p *~Çzƨkž½>~"ÍYsipy›ÃªÑÿ÷æ)¡ô}Þ-0`^"ƒ"QS¸ÉZM!s…xb‚6Ö“ñ­P– yð#¼ñóza¾÷`¼â:\¦;ŠF eçH.pËF>Ìl-s›x@­xOg\ñÑáD†#@‡ ›ª£ÄÅßÌHÞë¡ 7i7âðæ?y‘Ÿü8õ^ù‰åć€ëÙ+ ñðxËiÎâ3®8ß²HxFÀoíY¦سÿ1Ë‘k’u ²ÊÊ–d4xkï‘òÈAd_‹©CŽÊǶ÷xÐÛ„åÿ?ÑÖÍ0OôÓóú¸¨õ'åá±><)èÃ/õÓg¶HÒ˜Ð/2^¿þ²›½„yüú·åõ¨{g˜Ãˆ‡]6·Ür®2›ôü&¤¢Êéö ¼u48”kŽUÖàË)^ÐE£º%Å#1 ü…ȸqÆØãÊíœbH þ‚*®ï®(V™ìÅèqVÕ5×Å?¸"_CÄHLž ¨Õn’QÞB¥xƒ.oÔÇ~Œ2 ~$ÊiöÆ‚‚ÙÇLÁ30•¸¥ /]k[Ô}ˆìâQ!ùeñùòcïÑÖtD}Cs‰ÒÐ’‚ê/zy^^l ¿uˆx»5œø¢+xÍOM¹L²Ö'¬×WnPìž!‘jÆ~s &QN…M™l« ^2 ;ë>oœ97©ô2¬—ã/y7ly 5ìF„ª'd›HÆUÍ5Ó7Œ´iHvÊü•WÍ‚Í#®éÖ[6¬AMB‰m€a® Da>9¦Öq?*´•Æ€ˆŸ<úþ'ž>(ºÿKe-PxS@ë·bDætf5Ú9ðZðmÔ¶—´ecÕ”_5tÎh S¿Vj¬o L€´M{Ü)šcCtªºüW ÐRœlµÍGºòÞ­]y€Nò3Æ­®O&•y]·²0oØ‚§Þmè¬5ȨkBÔ„œ¬ ‹š’ZEò ߃}Á‹^)5NýëµoÅ(HR«¸JÌUd$Ëã-ãç(þì©&¸ ¸‰ŸÉ¼° ­&ñ iiyú ûY¢å¼RqÓ² ;ƒ(aFÿST¾œ›I¾·êÛ '¸ßxP=YsO8[óÙš~²MsR¨]'F,«Ó.rnT³Ñcl÷žÕ-;žà8¬oÌz†P[!€KÄ2nG´£z“ÿîaÿ5³UØŠ ÄT”ïÉË—>÷üë“ß|GN~ýÑ pw¨' ó³kGŠÚb5LíØ C¿<ö÷AFñ•Ù ùå¾ r(=š øm ¡è)ŽÔL…!4\™¥üf(ö„Ì—¾zY²¶hà^ –ýhaáf< L,‰j£k'(`¿ë¿^®ùuôÈü"ɼXCÓ6ÂßïÔUË»B êÖÛðh/1#¤Iíä³JÐx@˜ßpþYù™@ £—ÐE!艹ð;ULZ6_E°um€…ßB”ñpH©2¬•r{Î8`¼ÿ…yùH·$ yv‡ìe^v~)Q$ŠeÚÝ­XDö—l‚å(UŽqÀyn…ËBô¨­¹ÈÒ æ^r ¯àeFn¼Z«)ï‘ Wóè`ØX¬Å¢¬Ôâr,(ˆÌßÅpiêi¤„™”7Do“']‚$¦Ó£.cOÝvç7c=¶·Ò“ž_u !éŒ:Ç¥Û0ÐTôGAo“åy²ž?óª¦öy âZ‡€²² ©‰_ü´ 8»o`4ò¾~ ÿ}ÿ=âvq ÜîïóG7¼?ˆd,6¿y®ŸN+u#a˜]yZE™äáÏúð™~2Pã™è–¨_—‡%®ôuWâS˜›¥åÙ#ÛE¢NïQ¢N'–ÌÒ°ÐþƒBQª l.?lq€Ëò­‡;z¿µ–únä`r ¨5 ÃÞÉ-¿Ÿ²¨ƒ1LCZ”Ð!ŸYÞX¦|š"Þ pE3þ¢Úœúy‚c^Ñ ÌBmg7ÃèG³š"Q¹„ëgÜȽ¢óP¥Â»2+ØÒÿ™ú«Éˆ¢÷EQ3þ¯„D¢q7¼\æ`\ ÈZ‚0Rn¼‰×ÒsŠ%oômZ‹­9³=±’e@ýa’ôÀe(·/Q5ß±+í£%™û5Ñ+1§ e¦»‰çêL¨ª„Q ÖœÍÖfàYçÔûrT9´˜ Ed;Ù…—P}¥Xˆ²5ä½ÁYQÇMÖæb ÐÕœh€4lŒè­ÂŠä0ãZ©ûYÑÌj©óp› ¹É` dí#ÉuA.%¦˜v.¿ÛË8Š`>Ôâ¶Š½òPä,«5‘ù¨¡”|N³gtS]Ò‰‘꺬Ѣ³©5o;Í8l„ï°öl3Ÿ¥$'í^¿ P²rè^û³ì1lDŽ‘3•ÔÎú“•(´–y6cΛYòÍ=&V.ÒOäÃÑÛ)Ÿ’æf¨¤ÌÁ‡ qÌ=}ªC¨Ï‚^S!FA0é”Ó‘‡/¶üš{PCEßeR{Š¢“—ö­Zú¾Õ‡×[nÚ1ûz™òÿüî‚rYa}GS—ÅÜÓoJ3}øRœKÐņõ,àcð¤ôøé=™2ìþͳ“a>¾Ï™ª½VG5r…Íû´­Ü<ä•í]žÛÁª\$êi$¦X:ø?€,Âf¸ÅÖnj7¢ÄMJjU©jÜi"dF@fnœàu¸'q@óÀÆl¦™ª“qQ,(7œ*ãŠFò¸¬c¥Ù·W•i<¨X©7Å[%£%/^€÷’·9nW‹þ ËóYÚè1Ú‹ƒËðgF-U¡ÈºJ°¶uLšÖŠUÉv§¸“WÆ(±{µ‘#= ŽºQæg«ÿ´3 ©ò›§¥”~$ëø„ÎC ͬûúåˆ ¸T+ÚÊÜ´ký`?˜¬‚ë4ׯƒKà¿q\8‡¼í"sò}mõ$±irþ5ÊÑüYº!åu¨lZÐ`6ÞH\À—Ôœã?°JRoZo?Øëm“-ââZæôçäkUyÌ™sþ¬ÁbA.)M4«÷1VLz…lu=MT¤b¢Ýy“®XŠ€•‹vŸ+bðRnÔ^fS™Úæíƒ"œ¬0Å™Æ>iÚ·ˆÁÕE_o%ªWJc ³kã(šÏ”cÞïĪ9º gR5ÚœIR4uð«ú%7á^k;ˆé‰ï+[%·· Ô*¨<èˆú˜.âùƦ2°]ƒ+†–¹qUîcà)‰—zÂ(¶XnÕ­cŒÛÎ5àI©ºwy*Iƒ¶À»”ˆ¬.,á•@®4ëgÅåÕý%Ùå0ß”ïo®®,ƇñöËÀt¹¸òÖ݈ÒêjFÜt­Ötß’ñ””è:7(´þß*øLD÷p«žÌí-gòj¯Ëð@‡m&Ô`UžD+@Ïxnâ‹™fŸëé=(L d’W‚釂™K•¶îqÛ«Ö¼ s¼’Ç'd¸é®ôÝb½.7^Ÿ—e7T5•ae\»6k&k ÔÐÂ*ÇÜ…´¨Ö©)zÁ [ “5–êî'€ŒêOx$cÍ{\H¸rõðv[k[¥ÄfÿÖ\:ªØ_ÙX•Ë{¹adæ×¬|ØŒsý¹lçV?®ãb#ekôÔ󮚒cÙ*lIn}8?kbEbrÙJ!³‘~Gq²õ=C›o?†¨$¹Vи„w¿áýÜÐëVúàÏ¥¡•Æšp‚jdè„ßDu?“nÔvøÄW´b*75]TÕ¼ÕÁŽjñHYoÕ…c$ypÚ-¥ô¤¹O»¶êKN#³Üîù6ÿ@=S4\VÇB=9zÐöŸÜ6 P‡¸tÄh±­ã_ÕGÌdgKq"û+»¦¤©s3¯r¿/(câÄZþ !™™”Øf„>,[)Ã0W•–0h.)²>Ú¹x)a.ñ‚W‡4ÓVÿ5’ãâ©^W-ןM] ÖÇþÂ2Ä0%»W"}:€ÅxaïS[в2 k kËß D>é•gå¢ûp¹9s+lÖ™;œÅ®'RÕys5]A6“5x¹¹‹á—ÞzuTÝÙreZÚ¾àV)±—Róé—Ñ£‚{\O—êKBcì%rfƒž’iu DÀ"ßàfÑ‘;ÐÑxÜIEêæŸú(ª‹jUù¹õ ðW%>ŸÜù{þ÷_ÉÐÔêendstream endobj 575 0 obj 5120 endobj 579 0 obj <> stream xœÕ\[sÝÆ‘~WéG°¼>HtŽ™ÁØì‹;•¤œÄ‘X«’{4<}¯?y~ï»{¾<á¿Î¯N~yš .=9,ý2œœ~sf'“;™|8ôîäôêÞ_vC7îúôìÆ¿þ.ÍòƒåúpXbšxzLƒÕíÃî7ÝpX–9,»‡Û}ÕíÝîžÑíåÅ£nïýpèûi7§µésKzi}­ëÈt·ûCZñóŽÿñyZÅiLØýºói5ïÃî·ðæKø#ñÁ–yÁip˜ßë°/èËw»}LOÛ=é\úatN8íæ€³¾î]=Ìöêûa\‰†{ߦaYˆß§…wÏàçðÇ7é´æ0ì^À?/átþëþüDþM£ó 8ï:]ˆ1ÇÝKsÈ‹‰òð¹>ü$?|h9 Bº—¼ÿ*¿ÿ£>|\L‡ÄŸyJ4ºë¤¿vò”¨WŠ[:ÅaöË|²wóÁ+ù’dÀB:ü˜®îÒÍG¸rüî~bT¢ Kô8&Ýš½„7pÝ…„ê<½<ã‰}âr:ÍSx /#ÒvpÀ+˜øŠ`èg\„Õ¼ÞwWùVpž×YH—Kºåvo`-< ¬|Õù6¸Üß_˯ADa»÷pš$Å3]fÁƒÂ5‰¨0áîò*ß…Žö½;̳hâ "“ˆžÒ7NdÇ ˜t~IlY@.å’ªº«#j'ÂÀš!®”¶ï™I4õ²+¦3?øå‘·M*ƧFµOÁ»ÂE÷|Óýàc;™€-žŠzÁ»ë|ÏJ¦‰Ñ–®BH¨ø¹®þ´äL¿žöJ¢;çÁŒÝUwyW#oÀ®yBÒÂê ó¬gyÊq„!p1³nÚ LÛŒšÛ\²¢¬âdviFTy:Ã…“F]lž„N†?ŠÀgNŸ!Mä:zR’ƒŸ&Çrk.ïÀÌHꑌûˬç-Yh1MñpRØ3ÒÜB(o6& Û˜ÌRãå^¯/æX_ëš3ÜÂg‰Dn\è$0ø™#ð`š„ÉnšE’h.’8=C”wjÏakPÉÂ\]ˆy2ƒëT1px°÷ÜÔ¯ œBÕ¢2.™ÔûYùP„æáƒ!Ñ7 öXhÐpQ %,zŸvDåsBƒÁž¬4&l]E†à¼™‹3 Îe-’–! š61q!.~ÛíA‘çÁÍ`ÍA4  ´TÉß“9°c€¿@°²´­û^ŽZJ»,uOŒ®ìM@Ug|'6ÇhsÐÏ8,:@ 5"Šã’»ÿœ¥óÏ›œ6ÜÛ5‡~VríyÈê *ç¥!’ýè¢$HñàDŽŽÊˆ×ÄÍb|‘†ÅÒFWè.Â?'#Ö@‰½àE‡¡Œ¼"$FI6§ÚÅáÈ~-Rºð•Ï›Ý`ìyçÁÒ3:f.p oÒ‘ÇÝÛ´¿5OH°àÅ:‰Ÿˆ£¸—A$‘¾ÙÑÅY'­Üiš Ûëý š:6,xÊ1{<гø.áŽÞlj·È ¸y'o#8»¼HëY±Þ2­É&ÅlMU­Gä™ ¬yL›•ÏÀk…SæðEiy@xǽ’7=Ï’d)5v@¢Y3q½ô®fá7…W¾ì4µ6‹ˆPÚ,pO³°ïа3. nG•©D«àm¨kÃôTЋ³S/–žE‘ßàèbUx³ ‹×•kȶÌѧéÑŸ»ÅeqAx®€9#&«,Vblï VpjX´IWJ1…Nñ nïYi>ÍA8Z–·N'KGö`¦ÏÇð8‹dUa»:ë=-&çÑ™}Û‘‰´ÆF9ž„Ù¯™Cq}Ùì5ìE¿å ™äh n^KGqå÷5AZY&‡YÔx£®³Ç«YƒÊÞ{µ[8þlå%)·Ê+¦<¶º5xäuÑè´%p’C‡Ž;¨´›äÐ-$ãeÎqx@MAWÉg›æÍ¯Y¸ÒÜ8ˆx­“Ä> týØh=£*ÉasL¥%î5Œ[á­P§¾NÿJ··‘€¦u0C¶cŸ”c³E³y Í4ÜxÙ0],]tõuæw£ kàç7BZ+-#ݾp.ÏÿpÄh™Ô%ëË{§?û ÆV+G[L,¢5Ž& ܜӈJ=˜ä³WV´x“ ;â>Mâ—‘wCüÅÿ&é¶ÑB•¥Z“ ­U ÌuàdÐr›ä{ÔúœdUA âõJ¦¿Ôè’´Žn‹—Öo'«&ôý‚pÅ7%Izàv6ª¬nÁOŒÉMº¹V+~Ï.éTªSùB I­r×|‚rnðCé.šsc*³Îä€C¥RÓëVò(JW‹ËœÜòæÔǾ†o¤1¢É0ƒQ¶«ÁT 2œ-ûeãÄ‹ÌÖ|l[_q ±Gǰ¦BMà ^#¾3‚á#‰µí(V¬m´‘Þaçrü]ƒsV¼'ب a¹á­KÇ®qÛ%ã–›™Ì͆~øƒØÁœÁÄwrá!œC1»HZ‹1–ªz6ž³èÙ E§qTÀMï¸lp }²krmô s²ÀŽ/b É`5mï Ÿ7YI3ðl õ¼—­1MË:~eåZ…ý+#ìlj7f4O‹DÖÈÜËnŠadÂÓ%+à ŽÇç±:§YêR,d•~0æÝ6,3.cêÆf)™ŽhþQn´4mK¼—ÓDYE+9oß´0ÅÌ…kAʬ"häó¬–iÐGÙÅ.Ô&¹0äŒ#aÆA(ø÷3”hå,»$´H—Óì#òílä rJ[#P}šo2+"‚X³—–õ#°ÖL|§ùÉY‰u¾ÚØIM(Qªœ˜38™ÕÁ1­Àµå‰Pñ¢@s«€ƒæÞ‚‰7„Íø/XÞªø#6Š®Pf8¬sÀ&[”ŸÚEPRçÐ) 80YêôWDiƒ ï˜þ÷Vy±Ú+P_º3Ë™IĦ,4(ZòQC-O‚Bû0<·à j\±[”ˆ¿9 œhþÁæÎ†^|éÚ’‘z üë£çÜNƒ ôðNWHî'+ÀáòlÉoøŸÖãLt3Ê2F[€É#¤ugfð;ƒYçç\X™7=öZ¦¬’gñW`ŸÆ9Çp«qD—f³™V|8¤Iw!éRѪbEhñæè( %„uu’ƒ¤Òoµð™´Æ8l‹î‘7"%4µy™(ºH“ªUÉ,l?hs%’$:ÈnaMAPˆÛãýM†Ì/«´Œy„j}?£j14gÞ›©¢÷¡£˜ãÜà¦z:ï½àåmß™Ïé¡»!w ˆœ @N øy¥-QÌ›)Û¡çÀè-6ÊÛ¸¹´ŠþðÈj ˆ“7 ɬP¾mé9«gÉþÀ>`Ýᢠã…ÈJwT5ô¢ 2šR1ê4€Æ¹ú«ªY(QWR|ûd• b^rR* ú?Û=¶%Å}Ôv žMƒ¹ž”½µ­’ÓÃçùá'úzxæ¢éáù,ôúе6úyëáX¬¾Pœñäã¯FÄ Æ7·¹ÞþÀ¦œñ»±× ©ˆÂ2”%/6¡a&‘ÜÌŠêD̈ÂMP¡\’®”ˆ;/´øµ=¥ËY‹”Å*¤ËD‰°!ÿø(ú…›–,£ ŠÉ^¥S(—åíÙûu68³»,¨Uá¥p€eÉê~ÃVAª:ÍH’»¥ª8zÍÒy±U¶QC(l5µk(Öfñƒ*‹DÒ¡lö2‘= –Ïfz}ÀZ@„™¢k©uÍ7øåb2Íö.pYaƃb%kÄ-‘uÉE°_+Ñ´ŽD>ø·yÎÉæÀœB»…âÖ•¦4-B/’Nñk|fêû°‘‰žZr–gs§‚æÆÒ×”Âd 6¿ ÆÞ¥#ˆnZÆlÂvX®rÓO(0$w¬Ä$/¯òÄ}Ï\Ù3ì`ÁÆ,õžêÑ¡ÚUp‹®¶*{›Å‚ÿ§CÑÀ(„ãHíC”õFÿÊ^·d¥$1^g<=7lT¯é®ÐCÙŒÂ`?På@c?”¡“u4ö-Œa/„1|Ä^ ¬Ï G‡káD©{Þ¯»ºuGîÕ¨ñ±Jnô©ˆ|€&.¹ §þh¡Õv=ÿÀº«0@kÍÀ6²ø˜Ãm„-¼ ¤ÃKfžBù\¦{’_à ÞieÑÂFÁÆë‹t™JÇ{Q© þ¶Dƒ–MåGŽzj¡Q£9C0ik÷.ãÜËT½Pƒ0(¨ˆþªó¦†sßcaâiª¬Q;"eˆv›ä.Š«n„ÖfT¨´fŽ.}Ú4n¶ŸÈ–VV=¬_¶Y«]!["=Ÿ|¢ñšº£9¶¶ñpØAƒ©V<åöA­áˆûÆ»^ÀÅ:vͦÉ0Zº’äß…Õªb:ÚFˆòõ F9Œx(ƒæ0eý¾(]Œ Þ”Är·\YòÙ>ñ b¥,¼(xeáI¤º—›071ã‰Õç?Œ]›Þ“_K¤jA+A«713õW8s4_áü¨89¬‘¼ ÝÀ3÷.¤ÙÎüª£ ù³Â—jÖš°H`޾×Ò( 2QäkÀôþ‰}?:¬+£wžæØý—ØÃªº¥ü¹àËó”U_Y”UÞ¿Ó‡æÇK­ð;”~ú]þñ ý˜bNˆALÜg·íAiÆê©ùŠRVxa¥5/ƪ9¤À/ Zãntô'¹ñ>Ïwåûë?±ï„Xʉˆçü YôÖ~"¡?3Ÿ±õÓÇap ‹<¢õï-´Î/°ðˆeÊWs3t~(ðty ú°­cZ¼xmõÅZ»![½hQWJ̵†b­ùc¿/#u†¶`˜-.Vl}ÔIÕå¼ã"ŒV¢lÏ•éôÅÖ¿Oísæc2NØó¨èÉ%¸´¶l­“G{qƵv>[“>mx~“é_7ys\­[q÷Yk¬0ï—ªzÉdŒô mqæüδßÿYß yÊÑYÁ.2O¿±¦ÁdíYe“*>#õQþ7ññm‹Ís¼°Ì%4Ù-/ ÒÒ×øËdz’Ÿ«ŸBý¹²òÇêt¼ÍJþ?cüJ ð½ZK Hfÿ±ïþˆ¤d}š‡JuüãMyø'·^tvd¿QÚý\¿ñ¨»ÑFý}ùú~_¨i¾ºÓ¬Wr5´íÿÔû½[Ùìüîýl¶^I?¿üò·ûAµ¬dpæí!×õ&iïùW1¸¦ ©Î-“Þß2iK@Öãƒlüî>ý}kúÃ#‹e|åóaÓHšÔ¡”åF˜ÿx+¹f‹òϰù†Å·Ç ¡4‚ëIg–ým­]7j¤Q3à…Åïoy[àš+ó×yˆ+Í]ü:ú@ìœRYnnÍmo€YÖßh}Ђ¶Ì[|ŒèD®¤կ᰻Օ’ÆïNøÔž7j™³Ñ¦$ùE§˜MÆòï;úË9 ’|÷7i…Ý AÚ Õwï|üÖàAQÕøHM»Ž èBU7 ÀxKýC Ë+¥ï`v`*K%i±ÆöC3¤È7çÁ;ûô‘ V¬d›ÊJŠ´íß «¢ïù£øòLýfÎþ l¡ŸñlÚË-"¹ ~X&TmhÁ]ü÷ÓRKÕ¯!Я¥sDwÆËy÷?ÆNñ?+0b¿ãò,z²*gÔR¬dõÍ‘‘z€r«Ë‹¶)Y¹Sá~‘~ñÆ-ß<­?Èúƒ'þ1ò Wr<üÅé½?¥ÿþ_'ˆ½endstream endobj 580 0 obj 4902 endobj 584 0 obj <> stream xœÝ[moÇ þ®öGùܾõÎ˾9͇´H‚Aœ:’ ‚³NÒ ‘uŠ%¿õ×wH9œÝYë¤-R¶ïfçäÇÎÞ¯ÇMmŽøÿ?}vôðI|q{Ô_ýzdðáqüïôÙñ_OBgBK=6£9>9?¢‘渷ǽóucOžý°ªvUWveÂÿ?¯‡ÆÔiWO*gêqtfõ¸²C=­]}[­ëë¦éWŸUnõEµ¶«/«¡ -Ãê¤ZûÕ§Ðô¤ZzøU˜ûó0Èva‚~õMµîV_ÃÐfü¸úŒÃÞaÎ0“‰c±ý“jlÂvlœ<†O_UqüO'Ò«¥õ­©»!|² B‚`MøÛW-t^ǧk×Ô½Gêô¼Z·«}èuÛÄÿ/Ãö¡í:ˆÐ«W¡ ¾‡ÎηA¤nõ4|A#>y†î ”²…ï0 ´­.@-jkCÓB[»º Î*¿º Ï[ú=I²`GúƒŽ§áï]•whW?VÐ wÃk†Q¸Í-¼àÎð%®É–Ö÷ƒAK}VM×Êòm°PzeÚÁ×gMG½Ñ¶`ò-)N­±ƒ@¿›ð(Àjô"º]=|Ö@: #ÂÖw¤M ýÂcÇêmp¿Mö-3¬3ŠÊi²¤÷ ¤¡†­ÂÖ}Ç]]; ÐÊÈgÜ¡Å_W·8h­ & ;“àVþâu 8U‚Ä6aÚÀ°} JßÓ¨=h‚x¸˜µm< ‚>žuGM=ÓHƒƒ#䀣[œ$Ê슋^³)Õ£ ²1=P«0¼½[€w ;Z†Õ8ÔÎ2¬vÞhü.ál¨D ûÞF7Z6'‹„˜ÛÇöfbfôT€Í L„qg Ø€áñ£ Ü¾A) ð|ñ>€õlÄ»Õk˜1 Žh"©Mí8ðÃN\ÚÛdôê£ðÀts(ˆ’"W”GØ<.ò6c<®{ šF$3굩%°‘~¶#Ü(ñ"µ<…&dL°˜m ÈàVŒEŽ|»Ù…b'ˆÛG‚’8|‡|ÉfTb_ÜDS‚Š :EÚWO¸IH8KÖŽ¨öákk,2k× P߆} H…ŒØ4Ù5î (P ¤ÕTߌ<úA„td¦aBKÚ+JÖx”ohs(x†‚ÈâÐycQeO+Œé!)x¬ÇðÑ8ib0Kž-†6Ðç‚õ Ù$k¶/|öˆõ…€×8ÌÂÿÌñ—÷kG‹4¶Ä΂&ŠP!û6ò‘Sa.£BÐ(ÂÆá<‹[ܨÀ+´‡ ««VòÂhÂ’¢ØV"œ4Ó‡q¦dËÆ’Hm)S¡is¦¹79€ßLˆÊIØ¢Âìè2rlt àQFß,[blÅØ}§ð@{Y9›¢LËàŒ8£Ý`BâÈÚº‚ù êgn ¾yËÅu-‚ãDÑKw*Ísýˆ)Ôs& ÷  Žx+p²`­¤(X`ŒX×SD&‹ ÆÕƒY1_Ž8 ™9ô ¡þ€°„ÙÑÐN¸ –<+ðÚ®>€ ²9DøSÝ1‡¿^ušX¡rËdÚE$1p ò3†Ï¦Â@ïR­ á‚c†Mk) ¾ e8• † Û*n€pà‰2ñX“„"2J!>Ç<'.Wœ'ùp¶‘AÀÈÞ"TA¦sÜ0ö¾B%ÊÆÚ»‘aý~tb~V飡èâVT;‡±):1/%tRbޭΡ~LÊDHA–­lq„H³|F@{ª (Ã`*ã"ÔH9›Ý/œFg—–`Vƹ_Lr|Ž¢v½‘¦DåcnÀyÁV²§”ÁÇÜ*pÉ}C2çlC²ŒýòvОýI”§;ðû~œ%êÁ9_ °÷ŠéàåV ‚ûR+ç<ž'(R‡¦¥Œ=†ùj¢V¸Ü¶÷“"ˆµ³ÿ$q%ï¼£ åÝœ_¡#¬j‡”ZœV.ŽÛÅÌ0ô[´$_á9¢â×(yÜŒ–^z|dJ?qºæ0â³^ÔÓ”/îaÛ’1*rT³”l(³rSBÎ=Ëzh @ ì}*ØO%ô1a•@µpŠŒg’EPMwt`1ÙŠÞz:Àmvô¡&Á±|´%ŠP ¤Éê>{G¥û·S)Cçí#ÿò´ÿ%Ç)h*Æ!ÕJ1wRHê<•üRvÍ\0'6 hCû[ˆgñ‚:õáüPL¼ºB‹9%èºT©csuogÙ½Ì-âË1Á7„ÿ{ìê/#€ Àcá˜,Á¦nJ*!à%§Ü™-‚´#}þ“b‚Bx¤üy~_(`D.C]äT¶È7žŠ‚¬$ª#þö|мIôÆNÝá; °µ’\1’¬¸–.Sp r.&uÂ’ |hاSoe*øUeÀ/R`M)VS²#àrètÐs\R¥YN²ægXÑZÎ&á)Š{?YY\n“¥©¤›I•¢TÔª+®'8ªMµ“¢y–¼z<–8â!1—ØrZ–Œ˜ ”V ”°y~)%»p±3„6ñ;¬dÛ~vÈûgJo0 &]B`›n‚8;C–PG•3I6 ,)c4ª—¡@ꆇ*VMÝÚ,*Üø<A¨¾)•@š’JÕð†¾XŸÊ°” Ž•¼)‹qØg‹ÌÇ”òþ}FXÛ,=³œG ùvƒ¬.V¡&òã,Áb£Kü»¹'lÝÒ±zº<Ýs”‹ñ1«ÔDÊŸ¦Îé8§Ê®\U̳6gÌÒÊKÔ†¥¿N~\Y€_gÒåm:BÅ;Ìí$}ã!t(ÝÓ8ª ¤/D)O½µõ ‡XJ^eÔF®Ÿ.+†DÄ;^ÅMÀÊÞc2uàí‚ä´NÁ£ÏõMBÆ¢ŠþòV-$‡2/ÇJÉöC.˜×ì|$©O)Ï¥‡Q÷ì‰PÉRfWœª6Cšq’Ÿf«ÇóeÂæe¢ûÌBðPŒe9“ó1ÌPR^9I¤l, 4” ªÞÐC¼ôþ¤BÜuð6ÃÊfÆo#ÓÝ}Å(ÒOª ÑðØ‘¥L|iÀð<†Ýê²ë¤ªù}5’Ø/Ê{(|y LfÀ]Wb\ÂêTí‘ĘÞaÃ`1ˆ¶;% Åé} Ù†Œ=IJžõ(=Ï!Ž[é²t5Í!¤Q§ g|ã€êæc/™Ô‘-K ™“YÈFtQ§ Üet¶0Ò¡ð\á1et®>‰´4 ³—8cÈ¢`1\å%„ ªØÿìs ^%Ôï–âAw„g­L-Ÿ®‘ÒgÆÍ¯œÅþñ¦ÐOŽeåž/Soªìœßá`1·Ÿ¹ÚO7YqþÀ?‡X]]¡Øðˆ<ëá?èW…lP'ptЄr´÷b àð"#¬ÇHAˆ¶á×lÖ¸Xk›øjÁºuM<Ç‘¸/ü*Øw¨0„:eÜ×õÒ›lç i¼Ô!IíˆßãFD³§à“›vqSWU¼†{¼5¾[E`‘Údw˜åÆ•OKÛ¹“Æç©ñA©q#[xj…Ñ§Û ò5Ó{5Ïw¥mì+ÐhïI0™fþÎ˵tL3~¯gÄ”¾qJãWéqÚÙ3™çZÚà},}Ó &±}mlã~;Ö²ïg‚««|¢±àeIW›ÔxÅX4¿+étCc&X¼¿·‡)8rÈØvš6’Ìq—3$sãkiÜil?ªpñszüJð±-­³Së0>Þ”—áÆséø³´½J·²à]ií^<Ͼ´³jäŽÉ{­?^pÁåè´ië!Ý%*ßSž¢œ>ÂÁ-ó>~>s¿±ÕšO 3eþÇÏghÉà¿Í?œžæ¸ÜVÁkU\•¬Q`P÷»y^ ³çu*Œ"¿£y–hÿÿ>;/!_éeú Ç%ècA|”‡-¬óó0ùaÏbgmzëí¿ëbáhî)ÂÉÑ÷`g'~’áÛÁ(z8s”–x?ÙÂû˹ ìÐ} ™ì±­cºY0³zž»Çorm´xÒ×ç¶¾-¹ñ]©1óíÀCªáœ‰ÈÜû©Öõ½!ñLû.óžÚ¹,: pÓU‡Q§v…Q^N¶RÊVÌ1…Cf¯›1:vœCˆzº6o+˜Ø2;6KG‹šFlá[a6çò‚)þC0K)FžÇM°Œùª³iËm†…"þÞ Â*—„ ¸ëõ)ƒX„õ[$Šó WÿdìdØ YM¶_ÿ_¡0adø [\¥$ŒN¤·‘šoSf·“¡L (´im[ÒiBBö[ˆ·àßßÊ÷j)ž–pq–éU<ëË£“3…îÙ{T~Ë§ÊøôšU˧ȩz“ó©M'%]g¸˜ç…II°¯9pÓó‹’øg¥™n'> Yø¸`nÓ‰3²É;æóúì‘<0âày6HûÒfÖ:ñ»mŒÆNýRNeÁ—ÅYw [tÝüe‘˜è¡£ÝdÆ‘CrVäRR¦¾w©/½K5`±b“½nE>ñˆ“̶gÙJ€ù>ë§:§~’¢b5õ;t鬀Çç%o»,éuSÒpæm>¾Ku§—œœÂêmiÎió/²®…£Kž>¾‰¡§W'§Ó¢]¥Yç5R˜j‚‡ÍŠƒŒüG´ãfÀKÑí+èýþ9>•qXÑó6‚¹óÔ@…ŽtÊB“ÓêÎl ê#žSË•Ãë„ÀË’µnKvÍÓÔÈwOuÏÖáÏPóÁXI»SH¿©Êþ3gûì,V:–«×f®K=ïRŽ“GyE0Œ™³ûàÎ9éj3Á‘i'(Jœrʲ'é©5Êg|îܬÒ" \—´w·€‚Y‰¦Îäxød8†×«ÚÖÂõ˺Çrkk#(à>Ô4øÁºjêÁõ}˜Û¨fSîÒUkcÀuð‡è¾îû¶…ƒAS÷Ã`;¸sõØ· \mUëáåW[w}‡wÃ8“í©–>45¼ÿýf2~ìàÎ ^¯·ßnk°ègUX°÷®¥d¼š îÚëÎOUÍÃà#"zëñ‡$&l88Ö½×S¶«-òPC?mŸJò%VV‘åMr©÷áûûìMAAq‘Üö/ðýã‰Û‚W4þWËChVëT M”ôº•âÏiîI˜ôêyÎØ¼ÝDKahÞ•JŠ!e3sÙÈD®-t¸Lî­ÒÎ]&Ö„ ïóÌ1Ì0ýÁ 4Èj¸ÕWJç% wLU}öZG!-½Îä›Ï”è&K¿9Hèü\MµOâçJa —O‘›Ò0ÐQeD—o-ÓeI%W “ 47€|–’“bþ~=CDLs qâ¶øqS½ëÚÇôÒÖÙ(ù²Ô˜§Þ¬“L‘,Þyiúpž¥ÃSíçvÈ„¬Ò> stream xœÕZmoÓHþž_qÒÉF‰±½ëÄ–ô…ëQ8ŽæPð¡MÒ¦"/%I[N§ûï·³öîìdÇIZ^B¸öì‹wgžyvfœOÍ8Jš1ü«þö'¯»ÍóE#nž7>5ÝØ¬þô'ͧ=Õ!I•$*â"iöÎåȤÙM›]!£8mö&wAfA¬þçaö¡÷‡%wT˨訽ê¼¶eð{˜DE‘Ë"x¦Á«°=ï…mÓð:l ‘DqÜ…yƒHµ¤i¡ÝNÇv3< ^ªwÃêaWÍ’fª öC¡fBÐrÕGÈ4*òBƒÅ¼°ÝöÊE'8 Û%MÓàm˜ª›,Mô€^˜K=ê8LË­ËÜÝz;ÉUwÙlK¥yœ”*x§&~Ë.3uQs&Ip¶³8WoÁchy¤žÓ8Š“LéX=§pÉ”0)t§_áY]2­¨|eÎrºB —ÁCû;§Ôs–®R(2ïÀô•ðƒÒsÖÉT×  ïˆõ;÷lûg´´Â9 O¬°Ozê-æ]½Ð²}†í7¸»©m¿Âö‰ž¢pȽ~¡Qtµéq£)Ù¨~“²ý¥#¼­æ’"wè¬åœ +·%ÔË ¢›ÄSåVSBŸ6tj§Ý(IŠÂÆ\^Àå‰]ø3xÝ—]$\Z˜J¹²TEÀÊ„6 <–¨ ›‹µq–Šâ›ÙÛÇØ>F×a .Áøú÷úekE´ÝÜ^£5‡Ø—·ü˜)É‹f;Q–yi¥÷}¯ÄQ-+ÌPø>4>-AEþfЗ(DJ˜r(Ÿ’mW Â1gèâ¬Ö†¨ÿ”¾ÀÛ'¨«g(Ý3;I]cψ]Í0ê±æ7£õªTÚ3ä°Ñ»ÿNcÖÃîù„Câx«Ý¨LQgH 1ö´Þ¡}T[ß÷Q˜(HF«94,ôsp0S%Ô¾8‚ËеžGæ ûÚl%‰h×s (ó¾°Ú‰òCô^ôÖÍöp—qÆ¿¶Â X ªR'Ù­œ[ ãܸ~ç„Yp‹s§&eu0_s;a‡ßTм“C/Pêëg…üœ­Ø7$µævÀÝ€.Á‹Ç!㛠׺I,ïÛxiµÎ“Ò1X8Œ=%©75JbùÅpZí¾M”pR‡7£˜±§®jó+::©[IeÃ%·ÑS-c®'A`u7¨‚¡<ÓÔDU¬`5àÌVÇÈõ›4M iÁåoÝ iš W·¿²‘ÎŽ±há0@@€ø>\žÒðhŸÃÅ9°^Ûæ—(Ü5^™¸Tú;<²Â…4n»?AœÄ$``‚#ž*j ¶Œ«Á#øøýý’ …U¯¬++ÄਅqXEO °P¿æ†÷99 œã©òUb #ûÎW$ÈBH;‘¥‰!ÑæœG„5Wbcµy–žO\­‚³µÑ¨!ÆkS¼Fì0 μ¢‘%·¹ ·ä®î»Æ˜6¬=…OYôQ#½ÄÉ8h­hÏÑÿ`»£—Eûµ÷…Ît‚dø‘›é+¼!{ó-6À ·0pzê%%p»ƒ}Ÿ£”2¿¹}‰}w‰Êê©7ÕÑ#‚?í:òS]þ…‹N§u n“ñÈÔDð_X¦å¹ÈÒŸàÔ`#¦YÈð‚ãÀ×DÊ üûp© á%$“`Ç7‰kPßê´dóÔÁì&r¶½ÍEN<)¨gJ`á£9¡¦…!¾d¥||‹~ix&eòKêPi,‡ú-d+"ØM¦ „SæÃCÛ9r­ ÀWª.Ê«ºy*¿{]Ò÷š+ÎAO:$oÒºMðpŒîìäÎã ïv%„›qæåã·¯æl²9„aUi*›ô·dÕó™°’qÿ36vøgH4è߀Ž}nõcnŸl>qJþÌ×`XýÅ%œ­õµ²HåäCÊÇ ç+>vä.Þ‡€³¾k¤m-‡ƒÚŸsÓ“R(ãÂgÄ(±>c=dNÒþrÿ‰aôðö€0du;qÒ)=ªcN¤!¥0ZÊuJ†ú»Í´Š'µ>51g;„,umIÅQp϶Ӻo%ÜóÀÞ·kÒo¦‰™ë”¦Þi>W‘z§k_=G ºyÈ ‰·ç†ŠÈ˜CF Ww+ž.…n’¦õ¦‹ NIAË„¦ª¡!Ä€dά–úºË05S6+`Ãè)ìmš- a\j7…ÍÃíÌ)0vÀ¶ùºÈÚô™Ýü–Hp£ìYL7¶Î2\æ©™Ïz™Ï~sKm˜nÃ~÷lïK«&¦Du³ÞÃ%Sꔬó„'lPÁM?Âð¤®èÎP§ÃŒ| ï$±~¦·rèNÍgÓ(•æË)ÍÝýSÝ‚0„ò­ó…Ιd¸E+^m®õ=6ÞDºÇRKpÔaº¾5·ù—gFn褬à~xûÆñ[ $Å)zZFò‘O‹Ô šf+ö+ÓM‡c.=<¢úìd~”HCC¦s'¤\®÷lçk^&6iÊ·óŒ3é-ÂâÚð å–fb%†ßç0çL‹xžßNIùhzÄ–Ô+ýbì‚Ï*á)gJº~TÞ²}Îò¬%ñ[‡þÇÄ9º`?¿Õ•«½H² Ž1 ÷öy׌Ã!=º×¥ûµçµ)Gñ_œ‡ü*$5Ž<…múíØø÷.Y¥¿½^ã/õïê¯þendstream endobj 590 0 obj 2083 endobj 594 0 obj <> stream xœ­\ÙŽÇ•}'ô Ì« V:cÉ?ÈcÉž—±Dc$Kzhv‹lÙìnJ\%cþ}â®q#2²ªH ª«r‰åƉsר/úÎ]ôðÿ½º}ðë/¦‹ç¯ôÏüøÀáÍ þsu{ñÛ'éàÒ•néwñäÙzÓ]Lþb ±ëýÅ“Ûßìæý°ëö~çÒ_ŸÎG×õn÷Û}ÜýçþàwÞÓ?ýòûý!„©[–¸ûËþw_ÀwxgØýAžûr»¾wý¼{’žq¤Ç¿ðÕÁ{i€Ëìü¼ûtïàc\v’ÛÚ{¸4UÏsº=a»ÿ†Ÿ¥1ó»ÿíãÓŸK+ø ¯º_ú4HO#¢8 ?Kßß=ù¯$8ç­àâàºqN²{rärêÓ¿e?ÐÃó…‹]ˆ£‡güð!ôÝä–…Þ™SóÃ]IwƒsaIíÈ5ŸF?ôI@c’ø!¤LqÚý€OöË´»KÃLø4;ó±yÿyzŠÝìw÷ÚüOpmêb„µI£òn<¿îÒ“¯` ‚wcv¯ÓÕ>†9˜÷Ÿã§aÆ–ÒnÚ]¦çBýî6µè¦ÞM“ýÈcs^ÆæÆˆc[RSC„•“«/ÓÕ¡›û!ì¾OoM£[æÝt4OaÌ8?É/™û:ºwÁ¼r¯CÏãh­pHkûÇO~õ áâ€õ}zƒvŸ–û%\{½ÇÖñÂ\¸L^¤G‡{á)\ƒî2öïì5‚cz8€Ü=NI}Áœ">ö uŽÒöqJ­Ìx†ô•îbkðÎ Ï«¼àþ5Œjé–y’Îý°`cæÁÓÇÝ™HêpÐi§Œ³Á‹p÷jãvËîŸûà±×{¦ŸÒ¨¢læÎøÆgìFÌ×e#`¼Ï€‚°CZuXf¼™Ö>æF@7ÇaùŽ–¾¦mX¬+ N·Á+h2âæz;î;ѸIp)ûƒQF¦bðgÂà’„;;ỽçžï××$‚‡©#»K¡ÏûÌkz¿žß-I'„ˆø`äÀ2°%­Ÿ‚u…%£ˆ\ž¹'Äð® ?ã†hôA¸â©#°†e& ÈRÏÐO<Šš7^ÒH@ ¾’^Ц‰cÀ.f0缓™Ò’‰0"MMþÏ^é9)ãš K”ízH ¡Î[F™Flùé;‚vÒ[UçTì³BÔ’¢Aé¥ãðUµviäšÆ rnî’Ò`€•ko¦eˆÊ* ºÉÚ"ÆñD @ c$} (à—ú¶á• ‰<¹ sŠI¹ÍKžgAJh¹%"ÿõyïGϰ$(Y ¯4š+â ¤@e^Ž8/¼ô†eâP¸ð"“j9”ÞXµ*2N nrKOq$zº(˜è¢CÏíß°&l î=£™@©;x»ýyG¼Ì fxÝËpã8ËH«Öæ¾dBÒF˜@©…ll¶G.gDÜ›±  øÅdÿ¥>ËùÒ™Oànœp‚™¶@ Oµ„Rã†æSÌä=‹ Dxß—T`%†û4]í£¯€¶ I¡ÐTIà¨:Vk#Lv,.kE£344,1*$3€îð©A76’'<)~mÉ ˆx÷sëÈ(JÁSªøI«É  ˜ÎdèwºÕt\—FÍfEd4˜áadÔʨnŒ“ä ƒžN@[Yfµ´‚GOn£Qc0‘W…:d¶2ÒxЬèP%?Y3L‹lí¼¼«Å{Bßg‡ n_ó:ˆGÆKÙ \€k„aµuÖ{¢²+E æú·{y ögs\lA๷к4ð†ÑÓw£ H{„™„ØG@i们/Ëðÿƒ7ç c»µ™Aü° nÁÑLcvmæQçÑWÞ°1ŸX %¸t=X39râÕÖrÔÏ#Aôu ê#èþÕkU‡–ˆ*8kðF/¼Ð=8 E$yÎ~dågz;m …±\òš„ÈòPRš.!b­½yPî.–´]jÌ-ÃN•]>$¥Á‹RÄÑã8•*…Ëb50ƒF@^Ç1ÐË£Øç!F™ìʦ\¯ Jæ#œ k_Òâ.Å¥(V=º$e´&r¶¿N†_å RÚ@Ì \¤ƒœ*•Üd&êë2ÌW‚# &ºáp®L°Š»€»a„ “"}.·#!.ŒÎ$dWºïI)Òùÿ™  ähâ¥}‚*½"âˆ9ˆ‡r¤EÇ%Ãøû^xTÄ@Ü8¢¢90¢@_e”S{“E)YbX"k–b(Y}ÀPF‡H…¡à]]º€C¡sr5(Ô,‰ž³ãttßþ$|Å›8+K%XŽÂ6½ß¯§'+,’µ+ÎØ³(K.:Ìñú£1 ˆçá4wr_FÉùõ,ÄR1e×îòÚ­§M8®…[Êž"oå˜\ùXx´\JÆê /l5Š“¦U4‘ãÄË‘bfª 8x¡cûZBKÀž¾Yõ‹ä<¶ð§HfCißíi±ûAãuL-wjTØež6?ÏFªZsŽ/(ö¼Þk³§ œ^‡@ÁŒÂ.Xà ºÓð›2œ9)2¯)ϪB?»•šÍFAú2¨&©•¬_¼’!t&n´ö‰Ÿ½ÄÖÕÜ w-hØ÷Ëùú.}…OÊD.žÍ§ô yÕG Õ/9P~”P k±ÓdõO´ºÇU¿_G31”€Hc£]\%è&ñbÌjoÓÊ.Â9_4"ŒÞ„…é“\3Iåw.1ÿ¦ «×Åö”7ËÜ•®@ájZ+RÆh=Õ‹?è§»|û•½-Ñ‹ßç‹ßŒŸ}­÷¯¬G$_ä‹iƒ£x^§÷»"‡7ÿÐ/¸¨ÿæµY´96Æ „²1rÊ~LëÕGxÖ\ý÷<‘w–-YêkÏóÕ›üñuþø>Û*•í&{ÂáT” Üa¾mnP n¿áÜ $ Ø—ƒË‘þHbSÓî·@Ì1°„BÝ¥+P?¨morˆ4”Sn¬|VÇF{”Ž%ì¿Yå¬JhTÁHêq¯É÷¸Á;·áºï:u%k·Šª]ü-ÿrÖC¼ÖôMû[ !(à äi4S)ÇùÿÁŠ…CY8«Ò,ÒIJ‹¬Ç²”Ú¤'«Õ˜¥ÞÚžkc@ìëd†8²qá™Ghyv¦Êø"­33‚‹f¶ô¾3?ÔV਺—^l©vŒµŸQä•ÃÅ~¬¤öØÈ";ö¢3 81ú­¨VbÙ9×Ù÷E ;ëüÚ•(Š­ò³X“KÖΨ䧮™À–ˆëåY8«˜+0$‹º>Bƒ(?5ù%6šÜDÔo’UÃhò69U‡€Dµÿbt¿R„¨mÒî»!ý•j{ˆ•é3GûR¢%!VÙºòLq ®Ø|FA®Ë4R ž ’Î’3ÎÎñF%4eXGÍ牠–íóÕuÙ’ôñ¥¶!ýUûï]~Ý:¢U¨~ÒgÉŸ -šþ:L¥5„=E¨E£¹ Áe°ˆ„QfzðG,ËÐê3áÈRƒ]KñÄtjá1èÝÐI‘¨'4> œ9xTÖôµXSf‚ç,ðP†=Ûah|ÏF,˜¨Šx¥c¢ˆ+8ÉÿŒf!OŽ À(ÀðËXz¯‰™Í:rŒ§òxÏMT›ÞÆ~ <[sö9ÝÉIEšaÉQ@)(hówI ŸiÖï+ì´¾ú5¥4g*¨¹ß¥rŒ Ä(¹þç„â4#zÚܵڅñ•Ð>dIÍNsq_»ùwJôølâ”§¨’’BbK§h9îC”ÀÆn›©Ôªq˜ÐoVÃ@£iàʈ*T[ÙXI(b)ã¡l£˜ºK¯Þ»MéHyÿc&˜:ÀA $­¦Ù –I]IðVö¡^$E4bMŸ¼º‹8´ã…‘7‘±þ}•®Y(…¼æw–ÅEd´©Ê"tÒÊ›½RBp#Wš¼Vd³ו啂‡. =*…šk ÚNžOÂ-¥Ð*®âQŸ&å’;-cWEg½]Y2VYEÕ8&ƒL²6¶ŽùlLTµ a9e¦ª¡Û2Sü`2IŇÖ9ê<ȇG×™—5bÁ¸*iêg¥+¬ÈØμä$ËfMðÖdˆ ÌÚ™nëúŠAµO¯I hªŸª¤ÌVB†KmÄyÜlYÂð–×b‡)•ÒHf\»$­„±‰*©Ý؈É1‹È—2W‘ô(g]´¡sJŽâö”Ú¯Ž7oušJhrw6.÷»\ ƒu™S_pÖÑPWòMê¸È€J=ki»³7PP+ºÆ"‰]*å2ÆÐ­êØ8™áJ S '{xb[¶|;¶öEsjeÑܰÒW™ƒDBgmÖª•Ë™‰{0OÎD§€G:Ÿ ¾'ìd\õùåa^Å`!­å’P`ÃsØÖ5&úœºY-?ëH=RÝäxGgÿ±¤Q<ã¬Uœ’…;‘ñ[ÓñÚå(+ÖlÌ3ÎGÊàÛÊ<Š"(ýŠf-ë‡Ø†b°m³Þ`yUSË• Yœ—…Ë´®’â›!›ÊÙ:[C×7 ÆÙÝòf¥2óˆ•[VCáÊàWÌqý³­Ôc0J‰c]•‘nFð%Ú †|œÀk¾e#˜h,˦TÞE8L¬àµ)5ÖGF…¿Zaó¨û\Ä´‡“AÒœX qÁ(ó9U‚õ[öì|/³£-Ú§,YcEb‚ƒÇÙ •î9àÑŠêgAîô2ÖåÌUÔÖî²§Î)Ö>zçÄŠóNÏûÔ‡f½û›«3!jÒ&µ×Äêf`£BÞ/ûhïž,ºi öÔ)9=ä“:æXKY¾£¬ìÈ(«ât/KØ©HN„HJÎÃíÓ: _Æ ˜=³\5–V:ÔøÃ4ýõhÍû\•°Içfçú;?ÖŽ.]`*Îìꈼ@Dl1=dÂg16ÝîþâGG0õH¡‹-ÙýìdãJëézgâlÕ‘³æÏʘ#cc}œŸ»Ð:pÿpïK¿”¡öx¿ª†Í6ÖcÊ ·*UÖ/•×C8«¢Žê§@l™Úpži訸ÃXr•§ñH½IIrZ$ú>§>‹|kìK&5åufØùÍ!kòâ77|ß(?®U,ÉÑæ ¨ì#˜³GL”´™ùzÆ™ 4ÃSçV8i­ÛS"” ÝÜ·rí|p9Ñäü‘qeAÍÛV{ìçFd¹éÑRÊæ¬JÊ;73^<Õ’ÑÚ¦wiyg,……rRÖ¯•£¤¦5 inEÀÐ;í(m©Ê“•Éí"Þæx*††Æ8åŽeÞ(áà–ŒµÚöiJëiAÑ ýîR/hØèÃþ¬ ™gÁPÙr*®•Ö@àªàÈfã?©îªÈ~惑¼’s,–’®?~A Lx̓jÍ~™»ÈÁ”ãuplÅ%¸ªžQ~B«:YÝJo}LZý‘Ïž<økúïÿ:††endstream endobj 595 0 obj 5507 endobj 599 0 obj <> stream xœå\YoÇ~ü#øæ@;ž¾æ Jl# l'qø`ÃÖEJ¤ Š+›:lÿút]ÝÕ=3»«#N„ÀDÎôY]]õÕW5þé¤kÍIÿñ¿çÏï|öípry{§;¹¼óÓƒ/OøŸóç'> ŒOÚ©›ÌÉé“;ÔÓœ ödp¾íìÉéó;?lLðOׄ‡§‹½œÑ½lçÛ©O/bã¿4[¿ùkcÚiý´¹ßØÍ?š­ÝœÂó/š­¼ø¶Ù:gÚ®6c»o¬âKÝè»4Žt·›o∟7üËçqb¿ù²qq4çüæ¼ù þŠmœ·í4NØ óujö­`šúÍ¿šmŸZ»ù¾±ñ‡` v8mF½¾k,m½Ø–÷¾u];˜i"ÀêÇ?O⛳¸¹WqøÍuæeÜEç7¯›à⢂Ƿð[@ŸÛØgÛÎp÷]lð3ô2±³Û\Q»Ø&.|ì7Ï¡ÍÓ8À íÀtãæ.4(ÙøÚ‚cK˜éè8àÐ~s-ã~MØ<‚ße X……ß@&±Ão¸¡ØŒ›ŸâÑŠi$;Àz,–`pœâÞ™ï¦ØÒmÞÀaÂóküv¸›G 9Î(Ê“Ž<×mV NÖ×#°F[ED‚ðþW ¦1›Ë884xÝ N—àCÁ²LãâópWi™©ì~ ÛßÆÎ¡‡ûR(Ïæ¦øí2îÛxœ ¤ƒ=õ 4AänÓ¢Hn@ñã܆ðV. ŸûUV¥]ㆸ\gèȰc×8Èð×Iý•Rä|\±ÝP®&VÚùBnHÕõžÜ;?&'öƒë¶ªgÒ½û.Ã#ºñ¯¸¼`;Ô_ðÇÍéŸ{ð6À_þ²ñ/Zü=ùuó0.¡sÃfK=^¥&·yÍq[ÁL¸ý‹ôþq~ÿ$=<ËóH×ùaÔѵ äú<½šßß,=Ì-_e¤×KÓ_/uz,AÔ yaON¿ºsú‡ãeŠ’¼—þÊ2’´]ÑQ’ªÓ/¿£$ßM|I/i𤡿¿ ­h£Ìt»ôþ·…éß]ÑÀMÿ7úƒ&@òþ&¿¿È=âhäiy6ð£wã{Ϊýü¸ë¿«ÕüÎJì‡ë‡Ú›ñþ¶ª=+™É·owBx&aè?Ê3á‡waÌéJ~õŒã,{¯P ï>èò ôá ÛËm~ÿy>ê§é}¾ÉÃ˸Ág1ßûûlà &$J#Äø¶\šH+†Uò0»bÃ"ú«$Ò!x˜r\“¸ž8Ž%Æâ ··š#Àù,FêOô-#N(þ ÆÇ[ÙÞ6…o°K}ì¾sx[/$@/Ø)Ž÷™£¢Gœê»d˜xbNÉÐÀû{Grɧ1â™kîBNôEœÑ–Á7çñOA1½n±DÓÄ;ÜÆÉú7‚êžF<¼9]Äp–$´ƒÆîè†Y©¾5ašSK$ u”°ê—$øi24äF¤åðöóÓŠÓ<[udšc™ŒÂÚÛ£ah3ÅæAcå°m¡pÂí?E‚(9*8v>“L *³´¤JðëóÆuÔZxb²–î|©pÒfsÿ@´'›¶¾¯Mñ«Ác+¡°`3× 2ž†¶µÓãQõSbŠÛò!½[/jàç£L.;lc½´ÂRÞ/ŠæbÁ=熅 å˜ã…ì«Q -Ûk° ùâl¯Õ7k/.©~`K"%óNü¿˜„AëPQ^ 8ªÔ¤ø26ªò+'2Sâ†)E ÐJû78¡àr¼!³>Ë ù’À¤9Üóý¾L-Iä’ŽR4z9]+ÆEý˜S·‹ô}’mJ‘iÜè ×§/cïgiuØí´J4ŒÒ¥=‘Ç\ý ì‰KðFu».rí°ú*5Ÿ²È¾j§”y ŸRÐB›¶x¼ ~’;dS-D[¹*°¶aU{=ófl~¼“"€ÊüÀï¨[àƒ ™^¹B}…c¯OblÄ;ƒøio{<¾?´à)kt[#©~J#Y;pj±­À̬ˆÊšÍA ¼|¤O»¥2‘jgJë§’n0 úB™Ê Å@o¦1–FÎ;z< мu¸íyPâ¾- ‡,—ó„ ÞT†+i×cºnÐæE¾n;k)®y¤k#ëÆ»ö6¤ºŒ.``òPà ýX‚¾3þW©’çØF”!ØFÄbî’dÕrœaÒPÑs˜{ÇGÓŠþ³m:j3t¼VOª0êý®÷aàÉEsûä‡ëuTz«Vá½ßÚ‚ZÇWÓѪýI+?/-¬:?™'„ ×ļQ~•Ô¸÷k(OùœæëúVJ€~¦Ù–íŒQh± “‰'ö5õ~Ö$âú™ðùÈ(q†dPÆE¾Fâ†oæŠu–ö]}ñ´("óm?Ö¿C†fŸ ï·R¨¸þ¸œyËìÛdVåìy_Ó)ÑnwŽU <›ÎAŠ,t˜=ø‚Jyß!—6Ï3êµ;]S‘~*T„}éY“òáÅ!+",¹áCŰLõ¹ûË}4yDŠ÷Ðß0kÉ# ¨cÖµvÔ|h­ É?ÊŠ|¬çÎSÙ©rÀŠ£‡*M/Ÿ{–*#1˜¹bˆ4‡6QƒFŠ7¢R0ÄÖ㔪36c–D%PþrÌ´¨ÎÊ›¡V&®­ÒÚ)‘²m(w÷i£ÒFº %¾yU¥›ÞµFšÞ$€,±ÿRI@ñ!…¯)K²ï*òl‘é®:£ï*|é2¯ (ÊÖkš¼UIeÁ”ÁÖqR]ÛÁºˆ«Ê—oVG/nD°X§°L+‰±º@~P|ÀÛ|Ÿóݨ:ïÅÿCƒH;Ã[c—2”¿+)r­J7zóJ½v¥â¤÷ä —œYm„†EŽÔϘ#Œ±ƒq Ü,s¹XPhF&­Î[ø2ð(  W.ÍmsUê”’0W:C§ YÞ¤ÀØE¸|‘RBJ-u*Z\?êÿ›ðwõ’Žló„“Ø˜r&fò$<û¡•7Á%BK_6 “*Ø"—UHY")‘ÒtÕs˜Ê^ù–&+"…rC˜Õ%¦š ü[g7ò'¯ªB)™ ¯ÀsÊ)¦xv1c^"Õ% hUðé¼3­R•Ç_¨«*3œ<^]¦¶X”³¹Fîfáù’ÿË*õ’`Ü•\"¬“ kYƪü2û½TÀD&DUmý(u­ðc›¿œÑ×2Ô‰Éþ"nl©~FÕù~¨ o× d§%õ/°„6k5Ñv~Xþlë¹ÌBuFðµPëËH~ô8€››þFc;Lék1©? ¬ý ¼÷'™ÍÒµÝój˜ÄjÓú ÏÆ°Œè_'Kå?«<£ˆÿ­UHZÊYºMÛU¾­²)´é9¤Ê53·Kqd7!ÝM“ª\Ë’;où‹BÃpWÊÐtQ¸7’õæ”QqÙKÈm™l*.PUž¾²GÞd V*ÌŽ37 á‹ÿ!UúŒÒ¨¸©"hÉdf.‚\áÐö¾Èö&9cȼ֟;×|GbeÖl« ˆÄc½(t6«Háã †,œÀκ¢L2ÕCÕ_·¢99À\X¾8½óÏøß¿''ü´endstream endobj 600 0 obj 4737 endobj 604 0 obj <> stream xœ½ZùoWþÝØ?B¿íÌ"#Ï©™ñ"èºmŽiÒuU A,lÉG±òQIvìüõK¾‹ä ¥ñ‘, Û#¾‹üø‘ïþ¥ãl”âû?;ßÙ=¨G§«ttºó×NfGîßì|ôý:HÆmÚf£éÉŽ™ê|Tå8ÍGÓóQWÑ8Σ þçæ9Éò2§Yô}\F?ÅI½íoøð*NŠ¢·m½‹“2:ÀÏ8¦Š^û~¿ÅÉdœ¦YÚDSèƒåÄvø1Ãq `ÛdyíÇ>–mô‹oþ%ÎQÔL:+7Ð\›¢_±áèìÆþ€ó›Þ/ý,æ“‘ïÇm JæV#Û`zë×þ4ý —åÜpe•' Øn:{¡Ü/vN\kR¤ã:k[Ûé´Œþu/PÇ=x0’Cw ºÉ6ù>ÎP+Ôe_ÀôÇ YŠ(¬üG^Äy [(‹h‡ ˬ1Ýð£Yqn‡¢?Ža&”Ïâ <ƒÆýÑB¸æ 'jÇ`|ô½Å[3Ë ~±ßßp…™›ví­Œ-—v}˜ö›ãT“2ºÆîlÂ5êV i˜Íš7í¸šx›/`î«Ì–ŽP%œ`lÔXP°´G {D]“'cOØ“%챂–ºÎM¿%|t›ó¨ïœúB¨LT ÈÊkP«;Ô AšÕ™“s¾,<Å”²‹Á•³@’ðƒ >?C{¾‹²A×b#~0ê3PáNÀzÅ$3ý}77&)ªÖ€Ç¸Õ sW´žµÌ‘Ü”Ñ)´ºåÄxã3†Ê‚cÏp©Æ Ï©ƒ®ë0Q“IüN¤ŸÐõa`‚ê[Â*UôGä[ÿ‹ìÂ]³É8D66ýà •²-8øUªÀ¯(k³ìxWÌÑ—VEР­²\BÈïêPŒ˜ÛéÒ¬0|¢À0Cªmê qUL œ¯«DÖl3kv*gÄIÞÁ®™\@оtDfmaðVµ5 ª7w„RU7΂šÎì3hú2v9z»2h€Áv®¶x.,"KÌL¨ÐDÀ›é?>"Ù缇^‹+»h"|ÏŽÞ=(Nè9h†T@Êrõ§9²¬ .¶àc•ZvEEM$  ®Ï3ècˆsÒísú|Š“¦h @CI•§&l[B4õ£˜4O MfA8¡žI‘ðÏ \£Þ LxA=×ÌqAxª —ÎM®b+q2ÅR @T%+>-›Ì÷=ÔxÚešŽËñ]ÍN@Â(ëÍ5 Â÷Άb‚¹s¸v`¦ä‹Y² .èñZÍ>ªµÀÅekñº×û^hæ4¡áãÕFÇ\sáI Mp!`á}£ Z!Óø8W„ºÍPK29ƒÊ™˜Ê†RûÚl©í”(àTQ¯„Ô§þ¤ÒËNøE±©åfP_d¡ÆìS–ÅhƒÙ.éÒ•]9Ë0‹sÒFº2y0zŽ}x\Ë?´µÉª»Öˆ¯„úû&.µ‰>ùèÈΘEæaLUrø‚:Ó¼¼ñ4„Qt0i²PîJ°zk³ñ'NXöG’JêòÈ/à¬Zk[V–¥ùoM}Ò8×Ö\ý|Ö,+Iƒ±{U¤¦’žeaçY¥Ï®øø…ìuLó>§y3ê;Eþ Ö'§#͉gZrºÝÀ©^8&ú™ò™8=¥íVP>8½Ê7",:i‡ÉìÐ oºCÎ]–u5Wo+7šPM|sÂùãÎGO)ý¡,ÏàNqdîÜ>ß‘ô7zü¨ï ëÿª¦¹£~ŸU÷,Å®\_oÆÇäê±$†‡¥˜užûbg5)Á‰öpOûøç |Ü e?+{'ìì„{$L• ° ²F‘6(÷YƒÚdÖð>^hh:Õ€Ah™mÏb7š½}µ—•,8Ìñ#÷^ïàf-˜«“Uª Î7i¸’Ú^Vʰ1YŒxÔƒhÈ$UéÏ‹ì~b{<‘›Y´p_Ä Äçå¡<50½„Våf­4ã_i¾S¯ …©Õü哃ãaWh½¹j†~Áä¼â D?è1¯èUÿnìGs­Œ]QqôR…BÉZkÂK-PÎýK‚¯Yê!/ëçIý‹'TØò(’éÛËô÷3•Ô¾ÞÆ›2QÿNŠE®~/ót0²ÒÏsÝ&\²@¦ÛƬ£t<ªžj“y«ŠŠ¹ÿrºó–pÂ*R5Ðs…qrøW¯…ÎHN†€°' óôŠ©¥»_h1] ªÔ5Ö|þZþwí Çî&†î.b~­!Ký†eãN¡vßúZ ¯[Â:æ§C¥žb¯åeÐi_´¸~)VØvR/ÂÆšõn¹ÐÛÆ›WQaê&,+øÆÈxèJóûL³Ë‰&$Tm*äTïóa°%ªøbºóoøùý oendstream endobj 605 0 obj 2691 endobj 609 0 obj <> stream xœM½NC1 …÷<…G{HˆÜ…^´ŠP§":Ý¡âý%œô¶ª¢Ä‰ÏùŽœÄÀëZêavw›Ž.ÂÑ7–r˜á¾˜Å:A£2”_w&!åÊ쾑©k[¨Û—£ßRsÐÞÀòcæòŸˆƒê˜W$øA^°ÔþDþ"lȧÄ!ÆG˦ˆ¨‰·¦Ý5ç‚ ¾[âš–ÇÚR¤3OÆGJ––RÆçª¼ÖÃ<)KÐQV‡y»Ú¦óª=nÉ÷ÖÁ/»t (4æFíHê×§â>mýƒàIcendstream endobj 610 0 obj 226 endobj 614 0 obj <> stream xœµ[Y“Çöó†~ÄDø™iºÎ®’áH–´!K~€]®° @²üëgÝ=Ãr;;ÛGUVÖ—™_f/7ã`6#þ“ßgÏN®}3m½:7N^žº¹‘_gÏ6×Oᴱ㣛Ӈ'ü¢ÙLv­òæôÙÉÛ»½ÆèSÚ>Þíí`­qn{o7c 1:³}!—³Ý¾Þ™ÁÛóö|ËnŒÓö—ÝÞMÓ`a€Œc9—Œý÷é?xz?Li28}ƒw9mNoŸœ~üãöt—òó`¨=¬jÜöÎerÊ0ë8ødŒÏÛ§x1¦q J2ˆ…²Ø”¾ïb̘¶ŸÁK&ÖÇí“úRó¾Îåò´}…—]ö^¤5Ô7ä1³¸y0q´*îÝGýDÁoŸïöV6ˆ¾Ž^åÛ¿á5 ¸í-˜–º÷Ûoñ¢rŠÛðÁ§;‹Òx@T‹ÂxXÔ¼ 4ν]€U:ܺpŽù!gžƒ^,<®7Q(—§qœî)>‘êøw`qÊÅW¨áœ“Ϩ•›§'_Ÿ¼Ü87DBÏÞi㬇MH›0¦ ôŠX¼~ëäÚ­;›×¿¼ypríîÆœ\û?®ÿóüºõéæO'7om¾>ˆÓ^õ Tg§ÁEœfp Ö£ê9,oˆ¸ÿÿy3)µò6;í·WQÝèÖu›„\lA’[¸©v+lJD¾Þë]}¯€?ŒS8çÑ~ÜŸ&K¢°ÚÚ ÜNŒxÅÚ‚Mƒ£ùv¬{;\A«ý,q´Õ¾· YXúPù9¬þ>¼—IB^!}E«Û¾Á¥¾(8ßÑÒ9 4‚5ã%45Hi/T?ÏwWïªeÒèò ›L‡iTÚi—æ“UÃsø<ÃÂðP@X°† ø!+„LHM 7Œ«Ø%íæ#”"’£Xn9ÜÀÁm;íÊ£¢‚݈#­"<÷rLǪWî|u&¡ŽmV6™^iqQ5^60ÖŒh„2ÝùsŽ,½~^8ìöÓ”I!èåÇõñ…ä’÷¸j‚9b\-Šÿ®\Ã姉Ì\ÀÉJ`lÅ!y…×|•mT³¸uãD:߀ ‰8åÝ¥•¡Æó‡:-ÝçžuüK8-Y8"Œ™ÉÂi9?‘îéÖ\ÒW˜<à˜ä"»öEÔwoÌc´?Çw39‡÷ÁTÁH³N·–Z(ogµÈ8.ýŸ eϊ’nU¤4¦ ð´)þ-Ïßàˆ”ÿ·ãAì.ªÑAVE}ˇ2-êÞ¼!8c}ô@kMS7Á¤ÚÜïè7SÙA² ‚™CÈL£“Q¿g3÷wxé[œænÐ-ô¸ÿ†^ ôŒ"”lù5;j  |å@“Ÿ§ŽI†IÆc\·!7:@ÉãóYàúi«ÈR{’U<Ú){l&-JùiG˜³ó?…\¡Ã=ëÅÅIP‰U]÷XŒZ£{ñT,'¥‰6ë$~’ÞËg‘‚ÆK«¾UÆ= Æ6LxرC%ô¬þ´Ù°½³¡0â:ù³ÂÆ{'y0çœrâ:’‹oŘ³c‡±Æ·Ï¹ F/šçê"—Ì%$Ñ‘níûí2iÚZå„Õ/ã°eN}(w`ÐÅ!ºâè¹ÒŒ¬]Ø÷Â2UOvVÁÖD­²©X•¼ä´˜»îuN4ýÉŽŽ§ÎÀà ¾6c\Þ˜Õ@J=Ä­qðØaŠ&'aôì`ìès¤x{„œê)“¬¾aˆu;pX{:Ý=ðVsbväQ Êy½ 4+Óx+3;vNbßm|%Ø”¼JaØ Î! îá†ÀÒª Ý;.;$Ús,4™I¤H~Š+®UŽÜXk\˜©¬»@¡ƒGmfÌ}Œ¾´áøD`›ûW5ž3É‹/æ<´²Ë`ɮޖ.£ Êhu¶v 6×øgU¥.ªÓ¥íuI¥'‰òQç‹s#§x/çKé»çû‰Ú©O-ª(^LàŒa6ˆ †þ‚é&~ü€wñã+üø?>…ÉÇDúû|uœëÎÞù¾höïøçmüøNñ™1p­¾}£<þUÕ÷rñN½x³\ü²^<Õ‹k–þeð³.xÃ?^(E'L¼J‚ˆlºu\_ ;+I \AÃ[ ÐZ6Àî䬓²]WJ ­œóíÑ´To€G%‚¿¯2—]h—ŠÙ¿ÄÕ¿Ñ*q“zN3é}œØngu%l@@˜½©‰Y(9—‹»Áúƒ %Vµ§ Ôן‚í €yÖ¸;#ÚM„²äÍ\¡hN£çjrÇZ1KÒ›jWÀß¾¤íüLMã„ܰz qóžÈ©^çÜ·¸s¼MRÒÕÂIè"z´)Jƒ Öj0A¿7s<&8‘¥Èln¥òpN¢ôÃIÞWŸÞ–Â/],HÕÀh=i–ôÔM¤æùR–e¥§Ï$oCî K+j[fEªÂ&Ë ´T{8ËÂY¿¨7o"ê~¿3†Æ¡ýDNÎÍ’oŠáí ‘%ô ˜¢ìWøq6hº/w$Ú•”MâNŸ×T§]bC ¡†ˆ€j,¥Z?&›­‹é°¿pþ˜¿pRl¾È+¦JÑËωt—a†4V{!<Ö„n­5U›‘W Kfa$ÕÞ/Ûõ¦>‡ñžÜQw#á&9’ûF’ƒút#ØùŠ÷YÀ‡—N%Fß±ÛˆåG,Ûûi­úî9Ô*¦üëM…VI`Î¥ï×ÚhçC}­ì­aÈÉ£#Â’u`1 l´°$Ôá¬ü¥yÁ&ýj¾Ô)Æ÷šðZƒáeš#ö}Ó¼õ©g¤ˆ0>p„™±ZÑï÷Ÿ®0Ú˜åÏ.WpžDüO,*¤fž{=õ;Tð좟¦Rulú#¦‹wj̺ëppQJ=¹™§c£lì:i%]½dÁ‘“…iÖ£+M—_ØÅà]@·s€¦ˆ`qf ÎðHKÒUÜ`ÛâVª_P7ãiMvO>ÂÞnéÚÆ¡ Ï@J j«™ärKÃEõ½&Ú¡Z6…„­–½Y´JxgäL÷LæÁGòÂñì€V†tÙ{“gr^) ic £rÇwÉFȺ)€~ƒ±êÓZ°n›¡ÕqèÝyHÕÂ¥…t¸ÔÇ4Ö¹µªõç!´F˜jkð]c"Ã>§¶I ÃjýS :}WXåi,„fáÝX£§Ü”ÛöeZ`ì{tõácÔ‹«‘¦}yî_ÕiQ‡À'ë:èÅ9÷ˆÊÜ•áf.Ã_WP¼Ê>Pv¾‚«ÕAL³·žÌ°šuçž×bñ|ÄÒ‹˜GÐê¿Ô¢&¿.p™ˆäƒì !<óx#·é¤™¢}$Hcè(}XåPÆA“®W·E^µ¶:Ûè02”9 X”Ï›YH®ìgA£ûÛÎ8¢d¤Ù=É;[iºHåÏ-Qžx›[DìLÖ´ià:TÓ%ÅTbÞHa-ôTÑ6Ïê¬ç#7‹|Õ-R÷˶ê\Ò"OK0–¢R ]QIÓúGF°rQZ*MCÖŠ’ÖkŠïºé¿ª(4ïÜmÚ{—):hÏôP!¥Á'EXnµuEÔÝîïàý‹i8Ø#™?‡w‚”ãÎÈ»Uþ¸ž¨¦¯<êc½hŽøR;×þ©öôPK!¤ˆ—”ÄÐC˜JËTU%;ÞHÓ•§Òk9HKcéŽf^ñc,ÙæˆJ©&”†nÎÑ,‹i"ïGE“„a²4å2Ü0aohÀì¤ÕéþHPY=ÍrTÒÔoåJSÿ~›Æ5!ògÜš«»¶ùߌÅ!Q§s0ʽ9 FéæÒ2…r¨‹Ï]®î¥/,øåf.sJO©ÈAi@Àòc­jËøHÔT!k×-sÖB`ÁVu¼£g¤UÜ,¬ÖIš}T<ýÌ=ûÑ|ÈA«¢£•§µbiÖIt\K»:M L/ÔÕ)o—êQ¦îW„jt•Àu1ûxv ût „`2…)¦ q«Š(ÉP<»Ú!ô#Ÿië3&­`ÚEÓKogžÑÙo®þÏ:Þ0—Æ:?‹E~KI´á€úÞ%‹×xªü*ó†aõ¤.âõŽK¾ðû¶ùþ è5sõâ8'Òë±½T(ïzÅQù_#„>Óxÿ¾ñðˆr˜ÂOµ!ªYPOD¥ŒIµ¡R‘ÐÊš@aÛ¨R&ZLïí;?¨5Ó1JºR  :*“>=0ÝJ©º(ãÀfšQ])š”bàlŽ…¨z”*ËñÉZrìz#…„üº tT­êøMsƒSÏIS—¸Ì¢^‹?‡˜JF4ãʉ]Ò¼ªdù¶/(ô4O¬J›ñ  Ͳ)> stream xœ­\YÇ‘~§ù#4°ê2Ø­Ê£.-ô ë°´:lSc¬{†‚ʼn‡,þû;#«²gzÃ਻:È8¿ˆŒò/gý!œõø?ùï“—÷>|4=}¯?{~ï—{~<“ÿž¿¼÷]èú—»áÿÎÿf¥àgÅ%F˜w~ c?íöy÷eË2çe÷IwéöqwŽÏ?ÇOº}JáÐ÷ÓnEÝ~šfžh <yä‘ßv—™G^âüóI·ô«)ÅCÒî‹.ÁÔòî+ŽëÀÃ!†Ý÷Ý~€å¦)ò!ê£ïùûÔ¦°,|"úE·wOa8Γ.M°WNüôèËÒ‡']Þ½é Íø0Žp( ý5’ÏiàÀ+œúœèØ¿vC‚¡C¦e~‚oyËL“ÇF]é3üw χ…Ÿ]ä7ø½‡ƒŽ»ÇÀ¹«D#½4‰F#•¸΂ÕUN¶(J"+™°¬4ûîLëS†³~a@;²7αèSˆÂ Æ=u7uŽŠ›~'®Œ0“9?E"JÄ+déþ2pWU­za“Ëèw80‘äŒ;âDG_OybŸªM‘cc”ýe- `€ìwø3,3"¯ö̬}H‡aD›Cž¡Æ\Ä>-—È ä½©S%ˆ·ÕÏ/PzÒ© œ{`gnÐÈ´°]>ƒü+Šî%|›QU8Æ–¢ß‰Â¢dqDeÆhGøÌc/¼\‰°R*=7©Õ°Ì|üu‰2¯ÿÝEr$fâH*Ç\ìñ5~ïéãýDþ€ÔM ðýR}ÓýÕâV”ÍEŠEMh-´XüÇ…MFu‰ã¸v‰ \&YõŒˆS=ç…_¬Æy‚š¬ÜüY·½X9'<#:3S ôD5 ¸õšÀjU»®tÕwH©±Í×#''{ܼ:2<ᙜî)™ÎÅýKMèr†ÏÊñ®…mìêÓ ¢6•‘ u©ç¸#êìt³k­¢ãÖ¾êlö1†ÊŒRráX•A>UTÊjóàùAÍÚ-L¥<ªk0¦ÄÏZ› sÈ)ñ³i«)r Å>„Ê>*"§îcqk¼.l1‘ÞWµG.»­/ýsä¶[ ¿V:IjþÙ–°ô›{çø•ñn˜ÙK7my*eMèóÁ nÁ »W„ÀÔÇÚ˜Ì? HX"ùʾÎá(æééÁÝÂzMF›)Žb#Ƹps<Å%C0¯¢‹aP$¾'«}⤙‘€„rV¿“²­e‚·–Lë¬ ‹~“Þ·i8eŽt:EW©‹ò‘BÃÆ> гƒœVH×…ƒäîùðwÃD<>êGöÔy¦©(e1©Ÿkƒ§ŸH0‹++¨4á’—ÀàJÚ€žÁm $‚­ó"(ùÂdhÌbãúª,ýg\Œõje°Ö ¢ÑѶ_ešJE…CT­[G€æ˜<‚l…†¼4€9 · ?½DrèTƒøÀÌ)£Y7¡âW<­+Gî#¹Ž ¤Ï¤ ¦F¸™9NôP!+ÒÀ´=ô=%Õò¡ Âùôy+´Šó½Zùy–Öa'îŠòî!a!-ÒðXê±Iý:–™BÇ­ºCç—hŸ ®¬@‰}Z>S/£1êŒ;Óšäò§Ê}55Ií=â²Qá™Óµc€‡ÉÐç%{Ûb’ó†øµZ–,K¼±¥vwkã#‰{à• çE‘U`Ctñ=9t»ï:qäHðÛß:*1¨?À™‘Ýö²ãÊ‹:QÈUŒ H±Á·š[ ½Ìì¡)þ]ÔÆéBÞ}ÔIÝ#ÏUÉ'`€€…ƹ̱o0ûû3þùÿü ÿ|°Ö²ûˆï¹´0lH½0jOõb!Ú˜zú×2|á‡ô=örb›þ“¿.ä_ÙÃ縇í×öðMùÊ–¦ƒ?ùÕ^”‘e÷·õ퇰ò÷ èp„(uõ¹©Ê…HèÆÃ½ñàP^•‡ÿe?ÐO„ÕÏ2\ü´‰â+ûú7_è ”±¸ÞâTvÔE>:®}".ñ/¯D\à(#}t¼~Zhl±Œ¼,_ûÓÀ¦ÅiÙæ 0Tp¼Á¤7ª•\¼Ø(C™ôSyxYDü¼µýÓJš"â­ó·˜Ò¬2š¹Í #†$´*¿˜£(Lä .†~ÅaZ´îˆcÉì%Tº0Å9ÔdØ·"„Ÿ½(™÷…êôÖQŸ£·ýIŽP—÷~m)(‰Ç½+uã ‹1ÞʇyÖ€h°¬Ê3>BLÄJžÈÃ:Ѩ#©I«˜§5f Ç9¸Øåj}(€Ë ·%ã)gòÝŸ–ø‹Ö‹ë@ ENî;§H{9!ƶœ¯=ë`¤QáHR¼‰qò¥.ƒgÒ’†Ž­“ñ Æ’ç+Aj þYƒ—b¿ÌyF-èÇ›j¡äÐÈ3¿=¿> )ü÷:[2&äø~AX¿ `IÉQä€?ìÁm¤ö5ÛX©²Ó¥Ã!sɸ¿C›·Æ0­öÀ•"eƒ3ÈrYò­nú¹jFƒ®ì'ÆÃhr/:áÝEŸ«¨/–tWuc=ŽJ¾’¶Æ•ãp÷~ZN†tHÔ+ò¸°‰™Š"õüVAç¨}Dƒ‰‚꽯FÅÕë4W³É®ìvÝ•<ÃbåTå >U¸(ØL«­±@mèðÉ& s)IÝõïu¢á0 ð(™SŒ¡=ë9ãì9²Õ‘E0çÃóîkx8žZô[ôß¾¶à¦¿"S¤4…‘4¡?¤Æ4´.ÃRTð`‡g 4's(®ðØ+ýH'GZZA½\³¹‹2Ó¤KWûñ\5ã³Ô+Û¿/ÁáAt÷"ØCÎ!õ¢ì X›\ï€ÓY®Pr£êRõhD©Ðˆ™FUì§Úz nˆcúBùPn¬Öí-€Cj £Cœë"¼ŒÄÍ0e¡šD>æ¯ôKY»â(á3¯BN~‡#MÜè`Ò–î>ºè×å+*öÏîJ¤¡©î–„ÒA⵿ZWYòN~k^×AéP•ò8*½a‘6Ý©”oïœÜ{—ÎϦ»ï[íØü–ÇàtJ[ &¹D¶€#" ‰läÃÈþ"÷¢HUJûáaÝíSM„ { å#ÁÔV¼ %gÒH8…ñŽNËVÃíu:ÝLët.½nÔxW“JëãT`iš6IaÉzæ¾FoS_gÜð ´VA±Nä dJêOºé#tÏX þ ®0R¿‰ìÕ-.R7;%ÕáÔ¯M d?Ç_› ¬·ê©}äÜSÉòÏ Ôz¡È—]£wî7Ç 'XŽtç]Å`«^ƶ²ÅÓûC¤òöÆ›Š» ¹±tv~Im}Ϭ.‘Ú®ƒ쎤æX•§ó~à ³U}á¥Ä¼ä.—ª$\øŠ«ýwGíu¬cé0+KÉS¸·‚ÊÕOÓOýbºð¶ kç-/¬f1–«Èò©¬ã<ÔÊe:“h4¶HŒLvÁ˜ÕkµZ dðÕ ÕÛðõÎê~½üÚDÖ¡t” j¬=Tå·Z!Çv(Ë\…:þf‘+|ž„‡ÒQÕ+@²ÈA BÃ6}»Vÿ"¼sÌOyþ¯ßótÃí-*«OC#KÕÛH 6ÝከÚ°Ñåp´kØj@xäÚéíŒÜëƒ*¦UꇬÿštšÏ˜}žljáÞc,nŒ]I¼2¤¾ÑÄ$^¤4 žP# üò×I-·Îá­È¸ mûÒ jA@sð—ÔB>†èÏ>œº[—8ϵQÞTä.µÇŽâ&""¯¢á¯ÛºÉË‚ÔÛ.Ð'¯˜$¤a{q¢\©1W©–襗 ¾˜”â­ÝÑ¥áNzkÀ?ˆZ¸+ú÷ÜÅú1ÿ§tß~«#H–¾]úE§Í»lR½"ZêvÁ%lÞí”ÐzŸØØ5%ìñïNÉçBÉ­ý­kÿçdoÜ­/Ž)µü?¸[¼R}ˆ‹É˜/ìuÂÒd×2sÁÍ…j¯ùN©¯~Å9T{*”­÷Œ¥3ã´¤#dŸ©÷2íþH©žÞqÆ¹Ä ~‹L°ß3yŸí¸ROÅìsš¦ºn¶f„¾yÆžÑp ¢nk™¹áM¯Ì[ÒÚôùù½¿ÂÿþÍè=endstream endobj 620 0 obj 4517 endobj 624 0 obj <> stream xœµZYÉ~ñ#ÆòÃtYÛåÊ«²Ò’–…V‹Á0XZ?Ìb.æ`ÿzÇ‘‘Y] ’…èé®ÊŒŒŒøâÌü¸;ôfwÀùïÑÙÎ__ÄÝ“ëa÷dç㎡—»ùÏÑÙîý}à <éÓÌîþÛživ£ÝÎ÷ƒÝÝ?Ûù÷*uaÕwvåèï:N©OÓ¸ÚïÖ~õ°[ÛÕÓέžã—_ñãÇ. å¥s¶L€×SèSr^ÛÕ‹nmV/»õÈó_à8³zÐùÕxã&ŸxÐÃúû'$ItŸà¤uòBAšÿÙÿvf¬Þ™¦'ØÜþ1lÈÀFðèö“¼ö~èí´»vCMJ< Vvüñ~<ÇÜàêÏÝ:ØaõwþC#žàÇSу1¸q}Qª¿îìÿåÎQ: 5ÛP,d~Ægøñ¢¬Ý’1øè||ϼ‡yÞ\®kcz‚ûÒÄ‚º4¼CݾM_ÃDïW@oõt|ê»Å§0‡_g  M:ÇI#ìßr€UÇš' ¼Ä#M¹'¤2q^Я~Çqïy ’²EÔ¦ÈDèã·¤çH„KÄÈ8%Ýi¸ †Aã, Ø3žŸ +28 $œøyŽû8Ö,¢È›úÁ t3͉&’ò#Rc'XÀâW]³‚#iäñ iŒ–Äs„4Ažä“_”ä&¿ºÞ`¶µ¨F£ƒ±« Xá°¼8à_Bò%/É&×y'ëb¸!Ú4ºÁGZ›G:È/,2à…ð /VØ3jxC ± E ŸáÏÕŸ:Ëh»÷=lÙ’“€édîlž ¢ óëƒ1 W26ö#‚aŠ}tC²¶£IÓê¬÷;&g# Ìe à8¥éCŠÀ5<@¿À"ÀÝ» ]»É`Ÿw5D¯^‘Ã0Ñ~‡ÞÒ¯9€Â¯p~è'‹tè½Ov$3B–'+ŒæóŸMÑšž2€^?u`Œa £šÂ‹[3º°ä€qïаìÈNÑŒm ¡ºŽEb“ô÷‚ï|$[ÆÇ4¯ú‘7L}€hö ÒeÕ,‚±Âõ€4Ð >Îe,ÞeLX)0©øXíX¦‘‡9^2hž…pÙÓ'´püBOnÀ§È¤9@²Dñ3Ù¶¦‚m¶m@wB¶ÙÈ]!ò—hÉ~´díΔt<é’m–ȶ~ÆáÂ9²amœ,¯:£Hí²1ieïÄH%ȳð8ßžß•o¸“V±v9ÿ-ê$¤N~"K¥õŽAA,ƒ`‹(FXˆè‰˜ÁÃÅáósp @Žà Kº0lëw2ª´s4] gšH ŸÃ„ÈÔ•7E‘¶Ìˆ/bAW)K\KàLÅ¡}FÔ%‚íå;rÄÂ@žöñx]£”hý:ƒÏ÷1$AŸâ¶ÙÂXwËÔ}å7Aoþ&µÍ¤ÆÈ^!/ñú5:EÆÛûúõœ¿‚BÇ$OOë×Ûúõ¸Ž}SŸ‚qøI>z“úõªÎ»X$|Y¾.¹·îRv–h"YŠDmVâqÁørV à´.Ípü²Ï"7Hú_âÀ‚È•(ûNl[6lÉR}†±¹§Ý *p[q^üÜÌ1áM6†nÆ&ÝmqY7È'ÑbÙ·áã)*¼•T–Ü2uJ”T#}6ïBkÞ ­# á+'|M"x.Ð=«JÆçPÁŒi ùD¸DžÌŒŸ+N¿ˆlÞˆÜÅtaƒÞËbý?ê Ú¨rÇHŸe÷u¯N^oRac¶Þû®¤c é£(¨.Txàl-oœàZ’û‚†Ñ °N‘Ñ„îi @¡än‹,t kC[9Ï›ì]B¼8ÀW—Jñe½&£Ž‰ÞÀÐS`’z#ñ¬»ìo\pÂyÑ+#W›¼ŠóÇ2iL”4°Ex–ˆ© _…Ï#:yÝIÇñw*¦d¶¾) Ç´ÐU\™R³†ŠÞàžhî23y {-–B jíìºtÆNêȸD«L)›‚ÂU2*õÿ¢c9˜¹ƒhæß0”¦œ“ªj‚•Ý·:§¤s•TÃ%I³j$ÿ5PœÐêÛQ´i*8nrÚ`âX¹¶mD>k¢nX0èFÁàÜ’8TL›X¡”$¡ßD¡9ÇÀ øÝ+Ï2áMÈ5H;G~X;mà`‚I‰²¡†>t´ã¢Ç¬Œý ¡“Òú·Í:|\=®±7õj–`JeÁv¾¥´s{ƒÔšéK")é¬Ð€×YÕç94%¶Ž¾išTL^jTS澈WJÉÿf3ErÇœp@øpªFnÒ Y;Ç–L»˜ÂÕ³‹Y‡@ žœv>ê° %í’WÀ¶ÄF”ȸM⺨h„ÒÔ•¶´3‚§˜]¨©öƒ*? <Ì–&’ŸI¹ˆ¥/0ã:‘#yÒ /·d€¶Ê±(Õ€toœJª¡r®º­¦vÉÐÆ„t4¥ÎnRÞÆ¸5@K×f´8[ôåqë,°Ç{Tè¾ Î°#¡âÖ+ò~ÁêóWÎ.ò^Û°Pp/”7¶[ÉÃt{^rQzœDæ>X¡ú.'ÜyXNãötByœUè‡P]J“·¨ŒÓOV–ê[×øš[˜î>*Ú(TóщÀÌ!K4”a!„ÔŒ‡Ü’wœ 5‰ÎI$ {A*Ó¼h“‘ óStYX5·)—Îx™~írî ÀÄK&*c©‹¨||Ñ0Í ª赺l†HMŽ}d?·èlD¸äÁ^w0Ô5Ô Sö¦nàŒu–N"õ‘áxQÙPÔUµÔåÀÉ ›—¥É…σ§þ©$ø\ Á )ÞWÀÙoª ã1·¦/¥8 > [¼!-°[AZ6#j‡*8Þ©j:Ÿ³ì1|/dH¸ß ™R3gÞÛÀßF²Ü [ŽHór‡À…X\V>ð`§‚;xËQŽó]Ú Šî(û’9Þ«#ŽÑ½’b¨ØósQš:LÛ¯Šx)ìØ6ÎÓ=èªÏfÔ¡[eóŽ;£ˆ§h*á<­ªÅ8«ª:ÆX+_Շϫoje™¹ÿ¿Ê2’%ðÙ(7œZk§ûÝ„³0åßœ¤•ôP²r9óÀ¾À‡³G}så܇å48Ÿ˜oIvÛjñ8ÛBºå–‡ôJ0áô£j¾Õ“Îù-µÝ‰›K¥l("ȆiG®(¦ü3:º=©ÿ£Kñ–o¯} K?iÒ½Zå;!Sé¾uÌ\¯L0ïmU’'Hßd[¹`ÇΫ´ I]|ý&¬Ö:˚ݠúcærŸš¯øòVðú©ãZ¹:»|‚1ï;,6š‹Oý¹ÃŽYîc2O‡®qà`TăªŠ¦ÁÒ1¢öÀª;h_A,›Ì§Ç™GÝfÇr%l#{Md&Ÿß|sóÝN›ç˜¸Ä×M(LË·Bp¶ªùÆ*m›!·52µ?ÌLºJ¦oíP8F2Õ’Á°wÁáËF|ëä>Ÿ¥¢{ÛI!*•úDD{v„ßzðÊGßéóìöªS>î¡í·6²”àC‘ˇùVbs#òN玜¤Ó¸zМ;–n·ýÄÎPµoêeצ›ƒ “åHTô¦`RРŽqu%ÅÎ%áUçTÙôîïüþý€Úendstream endobj 625 0 obj 3466 endobj 629 0 obj <> stream xœ½Ùr9rŸ;øˆ~¬Ú ŠÒU%mÄ<€1àÍÀƒ/À»øÀ6à‰eþ}óRªîj=±l”«¥T*/å¥ú<ïZ5ïð_ü»w4»ób˜8Ÿuó³Ï3E“óøgïh~oJÃHº æ‹÷3^©æƒžƶž/Žfo*U;úß×îÝâgXeT¹JÕö°n±°uc«GµjCð6Twk]m×®8¾‰o/êÆÕvÝP@ÚÖÍ0x7ãÊö ù¤ÖˆÆ÷Œâ1>îÖ¡[4F·2ÕƒÚÀ 1¶ÚpăN«êeÝ8@7 š™ðse[c{<4ÌDcºvP!0/ØpƒUˆÔ­SÊ„ÊÖRzh{ ûy÷}u"€g0Ýv®ó®:ªAC§†¡Úå(sÕ' ×ëV[Lø¡ ˆá¦‡^Ïkú`ôP"åÆjâ'ÞÝëˆÈêê^:k¼ÅLÛ;‡â´ý^7]ë½ÑÀøq âšËU‚è2²XÆa@­g‹¿¿a~¬›žvÔ JÐËEX »1HqZé~-¹~?žð‡…râõ…v¢MFÄÿLw3'Ù"^”̾@‘Þá‘)-<‘Á'b‹ÄÂ0v\¸g=°ì^ó~hòнFbªft0l!vðqœÏ&ÆŒ8¤_ÈN…¢³LÑ žO çÁ‹L»â]OJ„Žò¨žÂo U²öL’XD3äQ ™ÏGNÞ´Ž»Í|“Lâ1ú-üÁ#«rCˆx‘#ÛÃ=ñ›Äï®RÁ!¢:ϨNbb¦ù<™ñŽ ~*9^N„šé`~·6Ž68£ÅlF’$È+⦘Tå8!º`Pä 3 ÌJ¾Ö†_pà6æŒf-ê˜%~h—"ÿÅß‘!­I„(ó1hf¦gŸÓ-ãîQ)Șˆ1)å6פ¥›wk”µã„Ì)Vœe5Úsú¶W›˜)þÇ"ëÂÁsgS=VÈ«K«§Õ£Ù²ÈT•ÆL3®KùfÏ‚]Ê-¢³È^?¬9›f>?ræ«u’ëaYè!Êjp¤iâ'‹M云³…Ì¿­@£¢ M¢-Ä×)ʺïÇ9NaXÓ0 fu2q‰jœ´4U¦CG?wjªxðõa¾ìífµ¯¤tÛ®=%ù¡»žý ärœXG§É:½Y]qÒÐän²ƒuzÕÁgûHF®¯&+ÚI&GG& X b!Úb’J²))J“}«í;1޲ÎGQx1éŒb%g@†Á)MTyM’x¿rH=ä™Ó¬L;íI´Yý± Ýεi´ê¬•¦B‡åж({ÇÅlÃÜ’)¹à™é[Iè©^ &Y"™ ²­§ªa0ýP¸û©:Øå:xMFái+ªßâu²:>ǺÓhÕwuÝIœ£¿8¢~¨YÕÇÅÁp±  ±ŸÔ}ÇrÀAd÷Ú\ÌžÏ>Ï!éæ TàÞ¹®Õ~n@mï±}rokvgëÉüâìËÁìίs5»ó÷¶7àÏÖýùßf›[óç7l­€+j-ì¢Ú›+ÈÂ%z6|Acþ’è…õä¨Rûÿ¹a€4³¤÷!ÇGŒÌÚ›ttâè Aȹ,=$Wá¢Úó8©ú0zGT'¸ñPºŽ^0öÞ`Ïb}¯{< aL,îVp„{ì!Á*zKWnwšÑK/N0.Þ•ˆCz<··ÙFi ë`4´ƒ^r-‡Ñ}ô±­uÅÒŽ©L 8}à©“°>æ.QÚ6k4†XX¶u\‚ЇpduOÐäлžál4â葨qå1aôÙ+D´£¯Ì Þ¬’í'cÔ!9z†‘TeÅ +Ùƒ 5!iù=qžZkKá°ï®›h嚢´»à(µ¹%ÔdÀl½k=޵yð8ÆÃòçq,øaÈ)qŸVYñ‘‘KÉâòXNâ¾HTœÂzÖ|¯É÷ÿhÖ<¥’³)]éÇifè*í‚›MƒàgË&Uƒ_I2©}yšXõ/ Ñä/ŒÕR½P2iP’ÒT¯”}^寥Š{NU¤44QíÀ\ 9Èè±c’QÊM7rþƒ­ ¼¡·žcŒðUžÌÝ‘¦Ü(f~£¯PÌ¥üo”Ãö"©}ññì ½ñè3«˜¶áŒqÖJÜ9®ÑcyÛß$Lƒ™°Kî$ å[fòcÖ>$C^Úð©1>]„D©ëåP¤²)i5Žx{Ä©“‘(RÚaö3¹·cE46¿Â:¬ôø} }ð“#Á:+5s¶&Z>Œ‹€ýé(ÃZ*Óu’äM‹XëÅ¡.'Ú;)"îgGüéµü ²×r:®ã…$d‰P/ J¢Èʈ,Ý©LFH·¦$hÒ…ljÃú+²~ª4(밫PÞŒ]»^P|§è_åk«˜Y˜áfWW˽‘’}7m¡^ÓøDIZXMH9%â©4Lwôf-Þ„ –’³:{šx‘¢v6Ä-Ž/]Ž¥z 2«z2Øi?9pKÆrùŒ÷:T“àvÇnlÌ—¦Œƒ™Éh)Ê~ÉvµWNG¹èe‘¯ýÈl€°á ­K®ýK½š#y9öѰ°VÙçF™^ÙÉá4˜å1vd§¢ÜMN1z*–hYt¯¹)ìv©³˜oYäš›û|u’zð‹Ø=¬ÁüœOÁ=Y½ÕôóõhµÁ!Q”M^º?¸×ÄÕ/S»¾O4&¦Tq¤v=ÊUÁ}ªÅ²‘pºÔ_L3ïsÃ|ÿÚ êã©.úaÙ _möŽšÚW0iR»=r‰]Q:„øP¥9‰_´Hæ8ÿ û¢¯§~¿ï§ø=›bí"_•äžõåëyÑŸ²©GlêƦ¾Ôà^=qm‘ÕºŸqÞ˜aºÁ¢Cðs.¹6âq(&¹<Œ“釤àðaò`iÜ;ɸ…£t7É{ܰÄR Yï_§.†X Óøþuµ€/FZ¹Ü˜ð?ãï=|'òKN¿ÕÚsTˆ_TXÅÛè¡ÝØEK;6ø(þØÂûÔËÏíNþò‡~¾ÎV¼lO=ŒaŒ‹ýîø½’„=@ŒÁT‡$°MÌ¥Ù³(bµcP ö§K™sÊýè 1Uv¤GßÀäÆWÌU#7üiÊR¦]5L€é;5YçȆ¨§zCüáŒïy÷DªÀ–Q ,ßÅæ Ž÷˜¢ü…xï¤>HRÇÕ¤;9_¤-m(¢wÊDR"—¸Ts|)˜T»‚ ópßÿulr—´ÕÛ³Ôºe+•_n”½ÄbxåíZŠV©Û,ýdkä~!¤(½XØ*«îDß®’•¨kælãÛjÂ<Ÿý9´‹´endstream endobj 630 0 obj 3055 endobj 634 0 obj <> stream xœ¥YYoÝD~øWâ¡6âÏf‘x`)¨¨”R.¨å!$]MnÚ$´ù÷œÝ3¾7 UilÏÌ™³|gÍ›Uß¹Uÿä÷ÑéÁgOÆÕË‹ƒ~õòàͣŕü::]}µ ÁÁ—nê'·Ú¼8à“n5úÕb×ûÕæôài3µ©éZß ô{=æ©›òÐÜo×¾ù¾ ??´¡yŒâ°äºiÊqj~n×C×÷®Ï¿o¾‡/oŒÉuC†K7Çp‘ƒ ðgln^Ëê:ôÝ覉7yæ"úȎͦÍØI¹ÙÂÍ1w½‹ÍQ›·í:5Ïáá\{Ïa}èáÕ¶} _ ¿ ‡œú0ÒV<ò0Þ¼ÑÆ§°F÷ ´þ ×^@BDet´÷¾£ð°÷\iºiíèpŠÍG¸8½@>.™$nÎøŠH?Çø‚;bœÉl™ *á® (8Þw…/Ç%—½[¡Vý»Ñ;Õ9‰^ØëQ[ZÕ£ï?ÂN¤Ø¬ôð’›/ðq uŠ)ÄW­nVDø”:æ;¡È>‚](6’)µþNBðž¼#ˆ¨4kº4 bQ(´¨'„¼U„¨[4».Ò%ïP¯ ¦´±02!)øH†FE_â+ëüïptZø WqMÊû)ƒTàKÓä&zô=¢U•thfÁC^HÍ5mžÍ½“Á’½œLNBç±0$òó«½=¨}ü ™é† Z(È1&8¸$M ˜ô˜á´Â^”é=-{4ìöJ›¼zÚztƒàP°@P&‹½I?¼ÕõegmÛ0¢¤‰,(g.DÅ“jT1°Ÿ;9FPR9 JiÊ3”vTñ'Å̾ó®õ™…@­ ìo(Š‚­"n’Ÿ>ðŠ1&–Ä2øVÂðyF„öD y‰ý¿2¯0zƒk¤Láiy,LäõÕ"Ø™<±yÖèÁ@(u>V!ç7äcuk¢Ê–yÖ¢×d²‚›WPž¹›0|÷âÄ?˦œH@>ÉzWn•NF`éWqKô×ä<™O®¨N ^H¨:ò ä, pGa1Pàlž€ÛQ–<›Ñ@RÎEÂS•eBÈË1¸ã6 ð¨ùLEŸÉHÈ2)zÒÄŽC”¶-£Yæ¼ù9^Øø¼ô‚Ï[Ï9=檊ph‰JÞ£`Ð$Yˆº î\s˜Æo©Ÿ0—$yØâ™Õ¯´úZÉ!æ¯6Ÿ<åC´õ½¢û<“—["~ê…ž»4>¯Åk…ã«sŒü©î î„“fNˆØ “ò­ª):å„ȪD©‡ÌÙ¹]wR¢CÎ_,å½›»??\EOLEfvS‘‘¹2ŸØÎšÌ‘ñf{Y¥ùì? ¥ÐYÖ£ë%x7ZP!•=9§äÍXˆ2{úßmàœ¡£ëÒvrP¼Ð|*¡‰½Fb‰8<·º{ŽÀ>dÒŒ>^#q.Æ,ÙЇ”a±rÁ-)-…$¹Ó“ü’‘Í:•¤L ,¾'GòF Ðsvè!f«HטÊ,$Þ¡^=E6)™0ƒ žÒÆ´qôUùäó ûô9‘sB„ÓF, 4n)ΫÅmqOH\ý¹Hü WŒEíAì‡&H“£Ò×ydo¬·0úÉ2Âaa‰Bõ÷Z®¥ y¸†‹¡{Щ t'' µœå‰‹¹pT:n¬KOÇW€ÿc –ÏËΧàŠ7®¾YIs>BBÇZb0-Ô |ËMMƒYQ$¬ŠjÎõ¤}M·èû ‘)G€äòýž( \2º“Â^­ÿõlåºÈ÷Pœ!nÁsQoÖÕ¾¬öAM+àlý¡î)ÈháÈw¼¢PWè¾O9G¯EAum«R6@‘ÇÌÈrHú¹vÖT»äª÷æb3m*ìöÈ{‰þ³·¸mPÙÇJà—D‡pi1öF\'ò„°=E^ëþ Ô Ì§È@> stream xœ]?k1 Åw Ò`W|çó˜–„¶´Ð¦ÞB¦„fº!ôûCä»PJ²ÄÓï=ð8 p¯û<Íáa_àò.ád9Â}œfxlˆº’*WöV§@Q(–+´9PhXz¢áØ^Ýeò×¥UÒè¾vvö‰bÆg’Të”+nHñƒ¢bëú¶o{Šf’˜ VMK™·…q]ò¸’ï¤=f׈·þl¨ò?ÐL‹áŽÌE³Œ/¿xÏqqPÁ/ŠƒÇ•¢ýÛ>½n#©>\endstream endobj 640 0 obj 202 endobj 644 0 obj <> stream xœíYKSG¾ëWìqÖ…Æó~äC0¸HØ r±sePœä×§{fwfW á*IQ”¤Ùžžž¯¿~Ìîò¹b”W ÿšßñtðúÀVçwV>x˜¬šŸñ´úa ®Œ#L5š âB^YQ!¨¯FÓÁ²Y9eF9G~«‡‚ Á¥$Ç5£Ìic$'7Ø r_sª„7žœÁÈKf,¹­‡ÒZ*ÀG[R:.‹C«å¯£#E­³‘hM•ô®íF¯>CØL9Ε'³<œâ¶Ü»îè8€ÕÞqÜ–QÏò–ü‰`!ì{¸5Ü“ J•Jv×]¢1c=³8€TiC¶awL(Cv@ c#Ïã¦ÁÈŒî)ìãPpí,z)YëÑ.ÔŽiKîp(=¢8CÈÜ2ém‚ï=ÖH¯NväU-<ÕB©À¸p~éâ ­0Ϋ®—cX&µˆgè$DöïøÐðl''YÚ±Ûáq–š‹À¢cLÖ4ÝŘýŽ À$'õÌÇ ð”)&Z¾¶@w×ñëº )à N‡õ·Æ0êð;ÌpæpØ"¨€ûaé¬Õ¿¨À"04¼FCçðAr¤¡Þ"àÒ×:‚U® Viê0]e!oO¡p¶a-fˆ$¿à×F0qÄ\Ã×GÞ0ìCÁÈï(ÇmƒƒT\u—×Hš÷ô¯ÒÌǺ"8.©6™¹ŒâmÅA‹"î¤ C14£YÒ³õP9`R©A{–n3²Û$¼Ï¬ùGÞ/ñ¡üç¤z˜dú2sákÚwàS#Üʇ<šç+û{–è›¶|yS.À“1¾Ò=Ç%aþ2pˆv·SfÞ­"M–xê;ЏÑÊŒšÛ#ðôS³¨¯¹¹̓š=›óMb¸¬ð$öÊОUØKš¸í¦ä/ëØö¤Å­°ä¥=‹ :-–è §¨¥!Á,Sa%vŒGc‚2®b må$¶!r§jÛM[ÇýžÃ1®pœ}öE,®e-HÂ¥^£…ÆÙoAûý”Æ6@ör:`¦çc›¹o²·Ñž¤‰Ë&w›Ðqæ¢ëhfkNñ% §5Ö‰æ[\#;ív hkÊè¶ÜO’òeVÎÆYø©TKIø×jÌw¥žu\®Q³ý„Ófx\•õ@x¢6"ì‡g±ß^•ºÌ´¤¹Qêá_Rdr\;ÇÐiŠLÏÄ(Æÿ'N{mÅUk„è?QAßô4*dö c`lôÂØ#Ûya쑌…;ªüÏ›Õ÷iãÒcÀU‰™L¬DìE©+o„»ì'O˜½´j'M<œdáe^§„'Ù§¬x—¦w&Ïr¥U:ƒŸâÙcå}LâùŠûy•of™ùÇl·ÄvÉNŠãDìƒw hÇ*¾ò†çyòÒSX4°»^2+gQ.›¿‚ä^Ñïs%ß”B8)ºì¦uý·=÷å‡ß0ÚMŽðòpm&7û÷ÿß´gÏWåðó`|Ûö±G-ƹ7Pí{ºôtàÉ.Šv©}JèÛ« ËÚ‡ûo 7¿ÄI¥vÿíÐ} ©+’sYš,ðݼª[<»• ojÈ+¼¾IÚ·}¤\k —Ñ|´¼‰IÇaÜ}N¾.y}_jxW¥†×'eþM—@’ª†ÂR©Û÷\¼ÖáÓ¼•Þ ÞÃßßîpŸendstream endobj 645 0 obj 1300 endobj 649 0 obj <> stream xœÕZmSÛFþίðG©S«º;É’ò¡3H¡I δ¤Ó›· 8 ÿ¾»{º7im ƒi˜ Š|Ú»ÛÝ{öUúÒKÑKñ_ýÿh²öË~Ñ;½]K{§k_Ö=ìÕÿ&½! #I•V¢7õbÁÁ¹ÁïÜš·˜ÞJæv¤o3UjN« > stream xœí[ÛrÛ6}×WèQêX,ï—>t¦q]׉㶮2i&ÉdTYv5%Ç’o_,I`Äò¢DfÝÖ“)-ìž={°b?÷mËéÛð¯ø;M{ßžFý‹uÏî_ô>÷œìf¿ø3Mû/Æ¢ƒãŠ+±§?>ïå#~àzV÷#Ï·l·?N{ïÎ0¸â?ñ÷ãø¥éÇtäÈ·+öû#϶"'Iúã31è§áÈŒáò+\~˶'ÿú;\> àz—%\æpÙÀeOõþS¿q5¹V’Äq˜5æ}î±.±qÂõÄáëa,>NT5:²’8°=]Üžáíµj£ý@XÍñßG°F’xäþ†[i¼!+R†²LïxV‚[Ž{ãošl|ÚÖÆku#-ÙxÁíXsŽiN²£+Õ8W6¾§ö’—ÊÆ­|ùN³§eÇgÖ=õ@\ão¯TãšgÉíWq¡:NUÛŠ:W>Î>u׊EèeQSØÄ÷b±n9!±yô ».U×3mi~à‰‡zGÍ:å\: Ê)"‹Î°üQ¾þ@3Hârð~ 038‚O3ÔÐÍÍiºã0Í €s욪ƭÐnN´á&j¦¦âÓoßs³kä‚ÁR;|¦B}¥€XS‚*ð¯gû–+á©#_~¼À1S…DsN ô$¨˜‰`ØÄ|aÙõŒ’Bq?‡fè["ËmÂÖ hùI†ú(GKNºÙ ¾mÙ±íT»ĻYÛ‹¶ð¾†¯@5ƒ;¸,´}šäÆ2Þ5çÄ»ÚÜFìy®À02ØÇ€@³ ÚÉeÇ.2fêìz0Ä4 m ÎøÀsÎ×ê)Y¸Á»D“Æø$¢K´ ]÷h’!‘ˆ] ´ë)ŠIö‰ùÐHLCsàZÑ£¢¹DÖÛ¡y'dÝç­B£ÌLëw ‹vDT͹‡“ñBƒ9Îþ âuˆ–|$zq]SÐÊ$k=\øžsd}MñYÀ×n¤ 9“(äùJ2p¼ ‰“¶q‘ÝШ¾=ò̪açÊ”¿aPôÀ©ô£®µlÁ);bÀ¦õ°ÕD€~,(’¼¹p ³{¦#{FKÉfêÔõ­špÂbÎÉ `]«k)•„½0wBØO’gMèVˆ‘¶ñ·"»”¡–ò£%o8œÎ) Â6…0ÑùFšh‚¢ lýü"?ÞâLÀŒÈ9㺲š}7B»\Å•@- ŠJ‰’*o‡‰ +ÄZ]1cžü8+º¼ß}p6 ÏM h7ÈÇp<1oAý)‹ÀVdÇTüô&7àð¬%t€ÉźعŸ ¾tC0  <ˆ³Pf}ÏíÂN¾øðe3?°bÈ5°ÃØ7c[•s£À×ý¶±=Uf¿.Å6„qª0víÝV¨˜²Ô¾õ |}½ÕV*ù§\à.¹À•Zøù± qµÕ·#øÚºÂù—º!†c†Éþ™mþ¨Fý nÔnÓ#èßå_©Qïàë{¸¼”7ÇÊ=Õâ 1i;0ÓË%C¢¦ð°¢‹jCªUL)óúù–³Ñ‚‘jl3U©4"ZÌ”j2Ó…ì(‚sØD[Þùð?è°3niSz–2eJÝgê=fž7ECS‰Û|]åæÒųB¦0ø5j7Ÿ³¶Ø†PÁ8nC³—Cy€GQaÊÒ,ŠL" .¹¢~—P¡ngNElå5š!Û"Ñ‘_œ:Ôc5*3üÛû¿é!­< ©ð,©Ž îž~O:Ï—lÅoEöfÒ؄ó-˜lÈþ¦‚¥Omùž¥ßK&ˆÉ¶oU#ž¯*c £´AjÉ)W•ÖùCv]W”'É>v]ϨDcWbàmшôÇÚHazNõ'S³XT ‘0*ú¡(oè2¦T3ÑëÑ•ò·ñ$4~dq“ŸX®+dT@évz•pß—˜Ï§ËØöð²"eaî‡Üêùù†ÃYEÑ•—ɹä†Þh†×†‚½µ÷&XØ3‰ªTbL"ða“Ôb‹«š5dÒ/å³fùÑ|@Þ¡ü`݇¶h-PqròkÓ¢4OQçæi}‘ÜNèîNH¶u%¶µR»çêûN û‡vñ⇥Æ£UÈÊI#ì xŽê®;>áºcÉaÏŤN‹I•áò\õý_W}™C•çšÞ6E•ÒOAw€F!{õA®FÝ w—’„ùÍ<£‹î$ ó> ‚eÂó ³U/³í€g™àiý‚ÐN Òæ¶ŠÈz¦e¬Ä¾ÇßÏ =WeLÂnÆ)¥Âƒ’ô·I Šñ ¾BqªòãcÓónÁS÷‰õ‡Äz+Ó`‰-{Ï„Àg^¿v¶N;ç§ŒˆÐ^ì2%\Å2jß’\’ÉÉÿ2dŠórNïÀ¡|öWŒ{¿‰/EÞéendstream endobj 655 0 obj 1942 endobj 659 0 obj <> stream xœíZYoÛH ~7öGøQZTªæÐµÒ&é¶97qж(r'ˆ´±Ó&ûë—äh)#;—í VlŠÃ’‡¤4?ºI̺ þUÿ÷×[y÷xØIºÇF7»Õ¿ýA÷mJ\&%ëöŽ:j$ëæ¼› '¼Ût>,L®>_{a”`î(YÆ%+KÙ;îwa$ƒ¿C,Àg3ŒX\–…,ƒҗˆ[a$‹“¤ Ñ |bàã•ÁveÁN¨‡­…8ƒ/IEF‚·Â"&E𠤥I°â—á;Ï‘˜´„U»†U5sY¤ÀªÅ}¨¯GËL-ùµ¢aH‘;‹#¦%Ëš%ø•ñ"ˆôÂ? Îë¡×†{9dŒÓÂB‘’«…,áš9è*h: rKJ’r¼…iÊ2+qrbË8Ù¢mݪ¡3eKàÚw´,˜%‘yΕ·eáz;’IÚDçès…VGñ"x—¸(ÍqéäŸàK€×+¼œãå/#¼¼2Ügøó/7xùk©êç5šèÑŒv#v¬m&ü6I-gèÈFTc•H;Oîp[3 cE"âÜ`tèÅ’£á‘®‚ÞzöóÓ ‹Lgò6¡Y©™Òa,6?™sH7§>ÔŒZ5n'²íùªÀùÖWˆnž—mŃk*¬\Ý’ wêͼœyå3ˆwËú­äp޽Īˆ h¶¼PlÆ…€šZžÐu’ŸsT€P„+æ”áÉ(¨4k+ØÌ†i -,5¥ÐÓ‚…R²HÉ"Ô,^©ŽAﻇ¿‰ ¹£PÐdçȀ‡¶Ãü &äz=øŽ·waè1|Ð[è »„Ÿ¥nÕëÍ[MYOÿ¶†—-c;JJo¾ÌÑZ¾ Ò‚¯Tb“«wô)–“kZ{5jËdèY•“vËqàî6M:W«D7+“¬›Q †v“ â´õ’¶‹’™ô–³ƒÏƽlõ´ðiÉXÚV- K'ŸÙ¢Ë÷äÂS;Õ°Ùüö|&œO¤¶ØÄ–IתÞ=ð¢á¢zq\ëmô„µê¢QóÎÎaÖ9³‚øÄz^;¬¥¸Óö»S¨ &×v*?MÇúP¸KLß·žùµFŽm+‰ùýo9¾¥íÆSÇ‹ŽD=aßgõW9Ÿkƶ‡ÀµÌƒÓé®2ÓMe!º‹Ûæyú€HÉlëò|PÙyIKµ8Û$Ð2êÔèP„‹WT¨&ëq¬ßqñ<¥ãYõ¬ËÒ UïÝ&ö¦!²"°üßËbóx¯¹ï´íÄ/5Ìó¬a{©aæUôFÎK óRÃxRÐK ó5Ìb¨j“>Ôø_×.iAÏŸUíR=ßÄÚ…=ìù&í"³{¾IY,)§öÀ©õ Èb=@æzgv¨¶רþ!TÁÌàoê2×!3Z'Áw¿º‡á !Z¡öXIÀêy3Tº1â%ˆãw'ÕG­F¡%)N´‡4€VæD=X¦ïd·Ô4€+3;Çëpµ×¤*šAfAjÙsn¨“§FÄ¥%YƉ8µ±ƒeRs°ïn!ñŒÅशÜ #÷¥6EßµìáO4 íÀþƒ]‡¾è¼üû×Çé{>³çž½Ç˜„ a­ŸûÖ1ð™ÄûÚÍû*¦ï©|F®Au:³ÙîÒ·i4*Ëé?‚'¬Ù×;÷ÇZ¿‚YͰg5ò”Bbú0Ù~Œ6†ÉЗæ®|ןå˹Þ\Œ1z.Ƹc\†G‡}{XÇmW,¡ÄÁU:¼1P(¯Rf}¦ž´&Z•ãD¡Ê?d‘œ$U• ’¢™f÷çxŒ2 ›S†¤Ò=/M «–")Ë ëiíB¥J•}«Ó˯†¯ÔdjëNª8c:]+;í ÷¯:)‚5 S÷ |3õå".³ñ§£?ç.šc1+ u ÝÙ2÷Œ 眡íà¿[¢í¯[‚{ZÚPvé7Sv©×ùþþT Uµendstream endobj 660 0 obj 1840 endobj 664 0 obj <> stream xœí[Ýs7ç¯à:p½ï>t&ŽOÓ4ubÚN›ä€ÁÌ!`»}µ:$­N{§Ã`Ç4LÆ ·'i%ío?´Ò}iºŽ×táßæÿÁ¬ñ㻤9^5Üæ¸ñ¥áñ—Í̓Yó¤Ç*x>£8™›yÍÞ¨‘·ôš‘8qÚL‚ÐqýfoÖxßòÚQËgA;úØ{ÅZ†)nÙ ÝÈIÃf7pÄ˲foȽlwƒVŠ3(~a…㺞×:…Çß øÐ‚r ÅŠ ×PtÚÝ0M ~ëçv7bgY^)ï£ßîúŒ”¦qëV'Џ’ÄE¼¦:RÄ5ÕæC[Ra¼À‰bX ×Þ³½€ÇjÏvÏ}(Ô¼†j8Iœ)"k¹©“¥É‹uù˜‹U¹Bçðøî¬Ð' 9jb ªÓ[­Ó qG\jÍM>—’¸¢˜¯¨±k’JØÄý$ã k´IåTSPç¢È[q½‡âDH°õ Š_¡xÅ©¬üѨ¹š×Ô„ÆŠ¸”ÄÏŠ¸FJÙÈKP둪¸à3Ü€–ŸZ×)ï' =]¦Um†+ †sjŠXø¢ŸJdS¤\&Ca*LÃKcà2ά97Ähabª®Á›ÊÐe7ï³ v/ÊÒ¢/@åÍ*O*&Ã5‹ŸùN*À2U™bÎmX‡QÀb€ØíxùøºÒáVÛ¨?¬ÎDá'àÈÐx< ÊPjû†"tàÍ)(I"׋«£^_ò9=ÙkI!{%)â8—"%S#$QÑ£T~N€ÍÒOõƒ³KæÈÆ75â®ýï•pÌS¶Kþÿ°Jáé@,ZÓ¶h9<3ÈB«ïÕïG'„KññÌ «oîÒoD´E7• dU¦OE̲P„C6*7š^Æ>öÎþìmÜW4wö(ÊÀ.HˆeÚ&LÎÀN ü)ìÔÄàý¬¯`ˆ±l€µCæ‰PR|F¢I3¦{ŠÍ €­Ühš}5‚1asÏÐæ> ã&D\èWol1dMo Yqäªe?ŒÜ´ ;竪šc Àv+l.ÝS€{ÂÛj ^ê„3:˜Q§\—Pôt͆x'¨6ö#'I›mô„b7 Ñ"– ÙËÅiO_bËzX3€(Ù“*›'.(†T?SJFj6*-TÒ£`ˆ3I†ö¬(•èkË\ø™§jDÕ;mhù–.x´s‡2³®€y™ï#0kuƒÖl ª®°ï!ªÊ¬r•º×4!>Õ!ΓL^[Ï/C,EaˆèŽGƒBY}:™mìÉ3Rz%™}»vDrþ¨]¢]h'J+Bî¢#4|¢ÍXo(ÌOi¡Ú‚«}©Y®/ ˵¬xɯëù®ãÃU=&¤ÔõòuëµSž"kAÀÆÊç’ bö"n=gr`šq:Sƒ¸¹i~ ¦æƒµŠ@3}xïa‚¼H$®nElQñùhÆ yPx®d<+]ø~Þêq:k( ˜óaƒäÓ÷`ÎaÖú‰ ÔÏ{[Àkà6fh.{Œé›Œaä¤pÀË“”™¥7r±ùeƒ¿Ls³ÍMFø|–į%°ŠÜ ãÁOôÕŸÃãëݦ8 ¦X¦95Å粿«ô»uŠj2›ë‡0Búå%¥öÍÔ™ÎeŠæ&œ y» vääæëR7£‘8°²°ŸSK«_¦Tëý˜2zs”kTÊèÁ…­öWùGè¸Òý×=´àm*óÀ½m-†¿Ü5më±`ÙtyàífØ” «eØ· fˆ¤M mÙ&0¹ ˆT€:ú*‰Š9ÛÕ X€»D™Í¼oå…o ¿•u9íï£H‚sÌ“ØöÀça$Hn¤Û,âæ×U‰™«ÄÇV¹MbŸ} C¦FºÌÔ²¸_7¶×’!ì‘tèæƒÈßB.ÙΩ1“€ò¶äWŠ8¢XV\à«Ö+J»-ÇêÚÖ¿”ãô€y âÛ›&CmÕC5pý³sw¼Ð½àisŸ¬R­ÆÞ|ÛKh|ËXí¥Ož¸åö­.¸·L!áPV4hëOºÕ;·r9 "è$ù¨\K‰T^€Ã ,ú¹‡\c- ×éB¬6rd¼-z@:+}Ø€»ò¸7¿æLÜ¥¨Ð•y*X©hµæÇŽ÷Öƒªý@ŧ­2—eŸ ·|zGøè ;³,lñXÖvûðI~.¸ î"!þ8”ogÔ" Á-©•±îu…„J„nÞ.#d¹]Ö)|”÷­.rr5NFó{æñ¶;wÞ¦òçÞ–ŸBïž.%d éÍ6¶”:N«œ:‹} ¿@ŠÞ`ˆa«Ûr:$­oÚxËŸ¥aÆóÓ"ï—f㟱Çk›ü·ÏÌmM¬òè07Íûx˜DzZ#‘nÏéðS½‹º¦‚*¨¯ö¾ncæLûqMÙ+bÿ¼¤L™å¾B…©XRC3M…ÅØM(«0.Y€]=qi6àü(½âxÍx1œ Ç[£`O£Tïä»^aÑIvõ’÷êdìúö}Ь¢âkŠ`¨Ij—ï¶l‘ð‹^ã-û÷Œ†ç endstream endobj 665 0 obj 2196 endobj 669 0 obj <> stream xœí[moÛ6þž_áÒkIYÒ h»´ë–u]ëv¶¢pS;à8Yì¤Í¿É£xz‰S{VvdúHïž{#é¿Gi’Rø«ÿŸœ|ý¢®ÒÑéÁß™úrTÿ;9=œJ‚ŒÉ–¤J«l4]èžÙ¨`£‚‹$e£éùÁŸQç“/ço¦?Ê^<ýD•TYUÉžÓ÷’úQ<Ñ1‹È×óxœ%UUŠ*šBûQ˜~…%òýÿU"b€§èÉP1xP ™Cb8µsÅ“ _­˜¥{\­Ò÷Ë-W»tSžQ|llã¡k\áÑLã…mü—àв AA‚+ï¹C#œFÓH”ÛxäÉñPyXy-kº¥sÊr6”o]ã%‘‘Ù{ ·”##¹Ÿû2ÊiïÝ5d||'Ln-cDyBy§%ZQ§Œ7VÆ·öëK÷õÉÆ)D†”º ŒàÊ6´[#ðµò3¼½¶½ŽŒ’ö¦'8]nä;õ-qo£••'Cð´5È÷ài÷ç9t©ö„ç¶×£ÆâÎìâüeÚ‰õZõ ¯)g‡þÎzb‹›bE€Ã³í×´[4–xAnÂBÂ%^ƒ™°ÿn—2ÍiíÂ9ꌜ‰™p‰ŠdU ~]\2(ÌÊFäF3£àe0æ±Cü­m&Ë ¨&Íl]UóX¨Ô_–\@±W¨ª<€6µ„™KÅ@Fy]’p%Qª²¤¯Ð€zêÓïë¹6¦˜ù YkT~ùC]ÛêÌRŸ©êK Tq§¿öU£ ÂÖJf¢+ã¾JF=4*™çD¸üÓÆLõñ¡ «?ÂÛO¾·ž |¼ÑÝK&:†ef›vƒíÝÏ„)Õƒ3Òe3ÎØçÝ®“ò"Šë®°õ˜ q«m%¥1½g,3;à’´±¹#][Råô…BÙ®¬xk¦Ç¾uuÏ, :øiâ7a8Œ1"mò@æ¼µA£—K… ò}Aæç%AòÂÿ¾ óÓÓuÛ V} ®C4¶A I´ ]RÀ &¯Àï¬ù0×ùûîr²0Ç2«Ù;lF•=¥õ;«–;Z>væoí„:ÃÜCÚL©èÕg®¢Ï/Øì±ÎyB(¬[W~NîtÅÛrpä­]‰Lnµ¦ °Aùµ¸ëЯc_OðëW”€×-6å*Û†QuÌ)âFR×1 DžrT —N8×:‰×}ÚR^ÛTàeW> ‰½œ”Cf`™ˆ( / 1Ø œX=щŒ½°Öë€^‡ÿ›Ð³R;Åw‚ÔOL1€X:IÊf.ùÉ€On¹ß"mÐÆ¢g[Ç8.ó¤b)oÍ?òØ·/¥ÛgMÉm×i’³]ázA-ÉaôԳ̮)½ !èZ œg…d4R°Ü ö;ži†•ÿF…éŒÆ è#ÅUÇ­(=}$0ìÇLè€sIMHƒVˆÑÆoD3áGdÄAXYöT˜gžp ©ÛõmÃo•c{Z0ÒiF’š–j˜wV&Í´Ô¡D[*§>S«ŸÐ©Þ‚êÓŸ¹‡þÄõifp…0 i‹NÎÐ\túbhÿcCÓ§Ž|W6á·°»1qCi¨EŠÄ@;±8æ†\Á4`'êß*ßÙ6¯Ü¢Ê û5î|‡{KŠÃ¥¶¥ïû¿[oè¡ÊÆžÏùw_uT9J¤hwÙ²2Êiɱ;•ƒûå´ÝÇ ’ú} Á)ñŠâÚw+ŽY³µQØKkçâÚöC°È‘0ݨm¢™í7€ã"㑉ª»ÝÁì³êÞ0JÜ.Á;V[¶ ˆ)7ÝÈB°unjáéÂÞ•K´¹ƒ°±õ4¡eGú¿§Ï0-Úå“§Â0-ZSnü£íNÚµH\mFë»tP_af¹r‚B¨3zuýÎóáü?‘/¸i7.ôžÃJòŠ‚º…0«o!@_tšê›ö–t®¯¶ßï⹇þœ\”ÊŒ»î ˆ·©‰RA=m{wXP¬ºÇˆ‘Nȸ<úŠr Í 6÷š¬ë½„Jg•Σn„·T²zA ûÞ5¾Å PÁ›ö—¢Ôiëd"Ö[Ò.êÿ,O2ïrÖ TpÁ†íàà¶f«-¨>6ozÙ/†ÎÈËG\ ùÃúDº,Œz{´2Àçi©ÜáÉÛËn#v O”å¬zî·ÝéèE¡D:9çêQ>P[Ê-O+ˆ)ý—·u^àßu¡»©ŸB´ÜÔ&Üjt%ý%‘Ù{•œ‰¯½žñλð-_ç.<ÎÂÌžLø¡SžwÀîä,Ã}ŽŽ »‰HX÷î„_YÖÕõ̪þO˜ú¶m O9ëÆfmÁJÍqÛÂîÛýضmców³OphŸØQHkEó!©9À>£¬ŸDr<=c>¥x$oâ×<:Ÿtÿ¨×ùs“Võ¾5>Kß°{â«ÜF¥†Þiï\ä*ýû¢ýÚG¶ ? wWžCA#B2¨µ1»š¿…µTÇY¹¶%§žÕ¦ ¹wÚ›#“¡À²¹«_Œ=A¹žzsWCÔÎÛóÞø¼u®÷¾Ûmß)Âc)RcøÊ¡ËcV.U8£´}Ø,QÈ®ó¶®jæ|{g§Š Î{XÞHõÃߥŠÖÞoTñŒ‹oàÇVߺª†_†+)Õ÷ý!zÊSQ«˜Šº­L%l~/Àõ T¥ v˜4Âs¦) ‡ÌºâV3˜ Ý+ÎõDDEÎtàíªÈs]‘M~•ÿ XÓendstream endobj 670 0 obj 2532 endobj 674 0 obj <> stream xœíZmoÛ6þî_áòkz¡,iÀ ´I—n}AÖ¹Û‚u(<;MŒÔvbÙmüïÇ#ÅãQ:YŽ›téPU¤y$>÷“¯»vøWþÏ:ß¿N»çE'èžw®;¡zÙ-ÿŒgÝ'CÙ Œ¤Äσ<ìßwtϰ›D±?Ⱥi,ü êg¿¼°—x‘üŸô’¿‡¿Èž"£=û"HüLtûqà§ažw‡Ùé§^?ö†p9†ËÏòâAz‡ðø\Þzp]Ãe—)\Vp9èõE–B{ïQ¯ŸHÅy{7¨cÙëGR”eï# GVø…V¸¡ÝË»öõ…¬ð…7Vh»_áÝÔ¾¾iܺ§~žEiÎ>Eá¼—É›T„ÞxûˆSl8GÙ˜®L‚˜,la_¯ô­ˆ3Ùö?„I®¨m&zµ[è³ÄÁ'5zš0zžFvæl€ÑT ¦•³kÌDר´°ïßöð–Ñ×ë臱Ÿ €ê k‡·e­Ý¯Xí ó„ÚXá˜ÃÝá°$~À´V ?È‚P/!É3½56ì¤2 —ÖzŽŠØäáñßv‡]L”ÈHCJf³Ý,¼S$xÿíÔŒžÊV\Ã1ÓpA2N8=KÔ+TTç<Ü¶é ›Ž”FyägÆ ‰öµ1¨mÔe߬‘ûÀåNýO,÷îû7.÷7µ·;’iw.n ½ ül¸aö{'&BÛ§ÜéºêÆ?À èPß H»ÔX±´ìYpÎóÀeE˜å~UÜ ë› M\¯ù —ê"Ï0ÐGýНàùÀ¸”–>D¸âR+\s}À¢¬'î‡|h6¨?árŠzNPV5(.Š&ƒ2o¿Ô7ƒú<ƒj•5¨–>wjPÕÓI?™ŸGꌑ k`@H²2 b‘ªs‚ÌÕ„wÑëC")$ÞñÄ¡wÙëë!ao&{D$u%€ÁƒÌûžå.$rSúbUŽ67š•ªä`1'¨ÀVï\þ‡ùÀÀriù˜òg'!ON±d¬+GŠXÇ¡<Å!âõ¼·ïÙ©à¸4â„;ìz¹áwtºoätÝ9þ~Ws´æÉ²|ÄY÷%g9x7áÖEÜÄ%ç~¬Zì®Þ§’ºXy¬ nº3ºn‹ZÝQ²KlQt+ÇÕ  ´ !8ÛxjÀÓÝ”©¼´XèÌ„7T”/T"@‚ø¶™qÂ9·÷@ AbÌÁjµŒ9 Yg[pÑ1°ŠËÑv\Ô),DMG?:s¨ ¶õLmgGb¡Íiθ–g˜ÙÓ£òE"xßů‚K-ÒaHÂO°œ6„˜Ñgf ˆ\ Þ¨ˆF'*ÉàrˆX$.¾‘ÝW$dNõ³Î)±jÓ ¡‹IÜ`ªD®Bb1Wl ‰Y{H¤¡ÞñI–/Gøø’™Ò_Ò0QaC'ÑJ*ûed?=Ø ¶Þº9d}$ #œ±ñiéðCM*û53æ¶ VeX1¢G&+Ì$+Ã$bJJV}N\Ç”7æôA„ïÏSNäCö ÷õ1f%·=89Â,9æZ:O¸–ö¼;wèT o8:6i¯ó~›ãP'ºìuh ¡_ë¦Ýú\5íuŇnrâä!5ÅïÌ#šZÉšu—©¦ÊKò)sr<§FY¯9³…3ú5»î)ætjò,*}«0!{Æi¶ ôá‚[ Ãº¢1·þÖÌñ9öR%‘S»c—9Töø©§ÓCK·2Ìð1ä¾3Þ×î¼í¼ÇûÜ9~Ѻæ+3)Ýë™ú!Õ^Ýýe øÖs´ b6v²Â–/+ä@Ú¢“­¹_zN*ï.¨µã‡™{ø¥ ðóÏ7°–ßW­[\¤[ÂÔwäxÂÖëlÄë„dvÖ3)Ðþu¨÷Æ\]ÑV€Ÿní3ÐóÞ]ÈLRä}Š NÑɱ\^º\^PWRè²Íµ¾ã,zAá¬ÌïÒÕÚ÷;ÄÖØÐw „òºg2¥¹ å…¼¾Þ%·Þ7÷¯ÊJmñM]C‰¿¹Ó?·[díâÁÀËÄÅ)û5}ãß=Ýk¤ø ãÔG†©)Ûýh}SchWžî…ëîvsÔÛÀìúTõ‚äÊÞßG ]‚óůü¶¯’lÅΩÈÕ÷æ §\Ÿ¦òDö;œý5†[í«g+£Ý1™•„a–µ{ps Ù¶EOŒ¿ù¶ˆýZÁþ®ÆÁæÎözg36[´C<}:ìü*ÿý »Ïöendstream endobj 675 0 obj 1978 endobj 679 0 obj <> stream xœµTMoÔ0½çWøh£MðGۤݲ¥E-…%!ÊaÙ/*ui»Ûªåß3ã$¶Ó„z@Q&ÎóÌxüžÇw„‚p|Úïb›½ž²Ùgœl²»LøIÒ~[2©ÁAH@ Ç õ:k"1’U\’z›}§‚i*á­˜þQ¿‡(%Ò¨ÒN8‘õ¼X^Ò&éÞ,…s¶t´F|ÊrIg,WJœ[ŸšÃ[€Ÿ”ÈÑÏ,¯èÖ…3žBÀ@"d+ŸxƬ)¸(ýÙ4§˜þÆÒ ?8uÎb gÍÊÎjpíÒökÄè²jÊH¦.05„X“ç¦Ñ vÆq(¤¥yWø)îùä!x3!¤/lÌ”ö$¶…L±f {U~9@¥„áZ :eœ«.îÝ*é¹h££c²·¶"³äP‚ì´óeÁ*R#µK›ª—\“\ñ æ> YÇôоC3Óì|‚¿Gh.)Ú{4k4WhVh®ƒ÷÷hF­s§Ð:øÜDpÀmGÜGð6€sf‘ aè"`«^t©KúP¨ŒJIV~ àuWü=TÎ}ýŒÓ‹¡ì‘Q÷‰æq:‚C1—, (©P…®°¹Ï²úÕ|u;Áß·Ïäó¢mÑÜöå›÷]K£=‰ Ÿ‹¡ê#ÉË!ê~Ep9@ß!¡Wÿ8=cÊnúa(YlP$±Ï^iôkˆš6æp‡¨±ògÇ“æ[ ¬Ñ2çIƒÚS|ÀÔSw¼ àãøSs÷‚|‘‘ä$oRj¹ÁÂõ/ª-9ÆÉíXo7´±6S©,fJz4©¤^ù‹PI^XÛ]„ýNz'—üHz½½¼þü㮟ÕÞ4‹Ÿ}ê4vÆ_õ½®>¤ãerZgŸàù > stream xœÝ[YÛF~ò#ô¶d0bØlžAŒÀk{7^d“ìDyrò c4£µ.K;ã_¿}W5Y5”  ºÙw}UõUuëÃ0ŽØ0–ÿÌßÙzðÍm1¼? âáýàÀ©Cóg¶þ},*”Ã$Žò<ɇãÅ@7dÃ"æIUÃñzð.xŽXçiYá(‰’„qLÂ8ŠË,Ï9 v¦¸J‚cÈ¢4©ò*¸oó"؇#^Q":`²/ÎK–Ø×"ãŒÿ¥g’FEY09“,‹R^•Ãñƒñ×ï‚_ÂD¶Ï˜VN&«Ä¨¢Û8ªX^U¸t-çªRN@|gEÌ«BM+)+î KQAÍ‹Gy•¯Åj’œÅb^¦ãe|%ŠÓ’å) 6ê5γKWh'ÉR5².Ü@ó'nK5:ºÂhtöîû|‡FP¸§†¿s…sÑg\É?¦`Bõ7QµÔÌ>R5Wú5å%MíJAó=A…>eòä<åÞhÓut YtX™7 ¸tô婬¡~Û×Í_m `wGIbö¾#uû“j´r…ßÂìKWx`®0‡æ70&wßÿ»Pž‘ûÆá[â2[ ¨¡S[(%%„}ðÔ¹Pý÷' Dé|ôýÖ#nh‚ÂC›u7ë^`Ý!$ =ùƶ)Ñ%û aDæv-Y/¼/K<9‹—%5cÒ„ÜS…ÆB¤UÄk!v]ª¾n˜Z]k÷JÞRaùæÒ3 zV„Yø˜ûZ>J@Ÿ0õ,'Ð×pÑé5à'”÷Ë@Ï–«BÏØ‹ç@O£ŒG”ÚZþ:ГSmCžâ×3ƒ<®ù³ÂÙgƒ)k¼®bƒL;Up1‚ížz‹BdËfÍHz‹EE¸•OwõN4ŸQÝCÍ9  hÐ j‚‹B,íýièßkUZ é*àq‹•…žÏúÐxM´(0$… 'i#y.ÀÄ ðïtXF FOÍBÜ|ùL ë;è(ó j3˜BÞ½+˜ê`Åžâ¸zÉÐZÎ%Noù(¨DⶤtJ)°j-à9xBuš­™ -M¹ÑJ¤&F28%ÖæˆÏ.е.•]¡”½-ÔšÅI.æ¼ô,¹h ýÝãæÍ…l}‰Kô8¾,DÐDnÌÊñPú^Ç Ç_É ?{ ØÔ•ÒõÉi‹âÕl¶*³!Þ½³ÄàMÉœåÆ Z×¼ˆÅu·¸­'£N¤¿,+XÒÄ{ö²ÉW´Í@º‰ThòÔ[jf´Î= b#›Q"C ßÊN¬jù«»AàÜ 8Õ·Tjgâ72‚ÈC¤¹LDwp^vlFI}EiêêðƒáO-{ow¤+Êér;J 0ç5µ:Š‚Öÿ 6•;æ×‡‹å${²DÊI–k[tÅì€×3Ϊ"!<À˜½ò˜gä¹ ƒ„%5§ð²$yVê 2β~ö·l{"ëÔG–üL}äÝšø™Zø³-m;ÔÓæÆËnýº\´…j1ú­©F3½6;ÄÝ*eQ9RÜL›„ÜêȶñuLóÞˆ›<šPÕl]·*Ótæt™ˆÉ34ºYæjwLõænÎ==kZÈ –¶,â­&=C4iôé3DÚ?FÒ±Cu§·ª ¢‚CxÛ€*ö>T²¹ÓON[Wæaz ¦¿Ç·vjï×§%‚üÃ9}ÖÄfö xšqá6!©ó‘*$9ø÷¡M»¦¬€"93‰H­´±r“LBøbý#Ò …R°M‡.‘Ù¬9°òº'óhƒÁ»¬­+(û¢­*fôž9eX…–LÌž{ÞìÂÍÇiHÉáè•ëECoÁãÃR|×!ß^|….„Ô˜oOÛ6÷zÎë™û ïoP¸ž[bÇT‹sƒ6Þ²Bäág¯á_PÉ%”Uh VmìÎ}˜à¯Ä—éÌI÷—Ò–·£6¢-†¿ÐZÈuÁ LaFLrÌй˜¥w>,lÐåãÂKçH`dØ¢OuO&ØFv~@Zc› :ý¬çÑ´&Ôö=µÁ6G‡Þd’ƒô][ kox:ºhÿKªÑÊž w§v×o_¶½ø"Ä9 R^kqþO6¾zBpoa~e·faÍ1 ¡9 ë½{ Íx]HéØLdSl©ÍÚƒMíH†ŒôÊKÁ:î;¸†¸z‰¨ŸâNÝÅw*Ž®¯ø¹:lÖ#ÕÒ®ž}T‘t ;€jª³UÄ‹£µµó°³ÈO€/%ãá.vt=bß·uáw…›“™´”;¶GŒ™ÃÊ÷5Qëm²Þ:õž;Së]Œk=Nîéeàæ±‡V[q*J ÷ºÍZŸ"Pž-@è°èîPûÿv@êˆGoÎx!>‚ ¿ºÂ·pšì²Ù?AÅàM¨ù^_‚ ©5S™»7{ ¯·Ðì•× cŒ<¤–·äP\EŒÁ/n%nL}s ø§|üê(Õ”.þ c¿q•nk˯_v܃o+ hmo]!Ú' R 6þѯ?*ª›ZègåQdðNo›7Quƒ²µ«R«æú8ÿ}G©‰_ÿÎKª­!‹ÒâüŒÃƒfa›¾Ã¦×núÁy™»‡;ù¬Ñöç°ì‰àªpíD±# ³®ÌÏ))€Á@îÆÞµ-½¸¼vÁ¼Ç1ŠÇƒ{% ýó|í k¤¯òZò$ §-'°>’t·)ŒîxÔ˜~›U,>P®Ÿ¸yÔvnFÜt¸«ß¹4z"a@‹Ž8~pß_Ãw_|RfÄzDæÖfÕú>A…R?E>€ M)«EžfÏô,º“¿'ƒ®ýk£M¡<…YE5ÉëKèŽçsl»Ž(¡‚ ’o™­‡o–šÈA¶™|i½´HAG¡æý•£ÑO®ûÃù ÎÿÁM÷Á·ÕÞŽ»L2d¼ïü4ii+…, E!É[3Ð猲 ¾ë}piÖYFÌýlheÌJ‰Ì6¯ `¢Œ2ùã@ >‘å5øl^t²Ùä…UÖRSCfÑÀõý3.O†K<Ç–£HÜ òŒóûS?6낸JÄDÇT!°a°Ê’[~yëdFb㵯û̲j¹/}²?4Jk© dz¢PÓmÖø%eEj‡i¸Þ½Rûšö_!'CÞ’ö­ˆA ƒüÍ'†§Î{®™h°ë¸8ubCÖÔÚs6¼ ±µlùœ>1?Ë—¡‹KøÈŸ¹”Iz†/£ExÅÃk†W6>¡OûH ÑqVdøv¿0âKó(ë¶âýèCƒ'ÁÀ}æÙ‚É7·,Á¿™1–DĬ#a@uü*‡ea&¬@a&[½þ#þýnœJ:endstream endobj 685 0 obj 2890 endobj 689 0 obj <> stream xœí\Ys¹~ׯЛ9["=É»T©µ6¶7±åª¸²y I‰R™‡ÌÃ’÷×À}=^ŽSIjki 3ÀÝ_ß=ürw’ÓXÿgÿNO¿ëŸŽ—'ñéøäËIb.žÚ†ÓÓ?_ª’TtʸLN/¯Oª™Éi?=így'NO/§'ÿh%Q·•ªÿ‹¨ûÏË_Õ¬,¡³Ò´ìô 5ñr¤n~µóÖ«(é”e‘—­Ÿ£´õר¶.õø‹¨í.¼‹ÚY–tâ¸oÖ×ÿwÔU½XYª)EWý›åj2#Ö_“´0˾‰RýgÑÓËšdêïžš­ÿV+wÓ“¤­ç‘:Rœä=zýe”©o™zÐ…^ä­Z÷¢Úd/í™MÛ9æòoø }çû¨ÝS—Ó´"K^P²´-]ÚYÜé'eY‘g¤Vh ôÇJ\é%ü¹P޳~«µ»iÜú½\Ö»M’Ö­þs¦?Æúã÷HMˆKuõÇ…þÐÔÐûS£êð¹yn5u _ÑmƒW8øW8x ƒS:'/û²èš-sØnÝà Ç8øDï³P+õ[àúG¼þqó`ßÀàéòs|Žƒ—0xƒƒ70ø$ÒÜͲ´ÓËȧx£ýšg…>†]Š_;xïG寢¾€²hÁ ÞH;í•z'í$ët{ZDõ†4Ù Eð–i d† Õ‡ùsHrõ¤¼è+¼t[s\,á|Ïvð1£ â%DÖ7ú OlÍ1{YuÄnYø’£æt­&2.(( ØVF®œ9i1çê5\Zð‰n1ƒó2“¥ˆl©v­z£RFðuU ,Òi.ÉÈJ¤¦ðþõÉåO–4ŸôÇD|JMìAãJ¥d±ÙeE-3iîŽ_=׸ÂCßu M†\ --åÝ>‘3ÔÏËBkÊ ²Ü Jê©ný|Ðt}Aikp­hÃÙfÁ^Ë6ËëÏ’òD`ßK[^0±q:ïk¥aòŒ˜Q~$§5Öl'T+ØÙ‚ÈÓ*~M)8 û4÷–£Êô«Û×î€&²[¢N,$EiIdJH˜Öò_ã6'üŸ4 w·ÄÝáÙ縻Otw)#iwhïØîDýqH(S‡„QÈhu‘«ÿgo‚Ð>˜±€ÏŠë _Á,%*üÐk_q»––_PƵa&©Í‹œaL¨sÉJ·¨uœ×³×9øF–†ñÝnø>æÓµ®(Sj&À03,ñ ¡>W†ÞW}¯Í {f‚ŽAè¥ÿ…Ð[J€Rl„(áî¾c¿×‰^äy¸±:n•e<ãdÜÃØ¸~ƒx\˜}@eQÙD¡Ãuº³î÷ÒJ¸CM,æäœO"fûD^n"A ˜åÒ´[‚1á4 ì„bŒI0¶‡;χÜ[¶s¤zÖW à9ë•c÷è¡ZÏy@¸Ìå+u!ÊËä{¯ød‰Zb'>;%… ãak_ØftÂÏ*pˆÕ”{‰å¬á°*†Ü@WÐá¤ÛrÉD猹œóºf£x¼i !ÕÍã@ £þ•­wîg]¢ß9íÜ2T’"çD"'w6%Wšu …¡ èy6Ù®$f“Eì¡"!lDŽ؈±Š¥ äzËœí•F_ d®˜8,ØÞˆ1DØ•ê” ‚ù–t{]gs0–X SÉCAâÈ"`ÒX\ô$Ç”«‰€RõÍ“U—dÙ+{= ØÏ2”‹«ˆ»c{jp¯ÂË#Vœ|’–±Š^Ü)r!ÁüÊxIv j-]Ïñrn“ìx-q]ß?¯ve’Ay¨€Pw8èÔÆoûص:G§ë9: UaÑ{ g¹þ¼½Bã©]òÏÌvø•]Ñw#š Wº—ĤŸæréK[Qzò ’U^¤{!›Qó¼7æ$ý*‰‡ÂÀh X9J”H“® `£MÀµsó ¸öw¼†Ý4oqðg|ƒƒ/ÐIû.©L¢3®QDfHWL„`ès{¾”æ;A)*¢ i§s¯È˜¶O`I+ÂÁE³k˜¸pÖÝ#´Š}+Ò€IâAZÔ=“]Ìn6¹E¢aC±5XÐ{ 7·”8‚…C1—ü¼LàÛtC¬ttfÚÝIt¨5Awt¯‚ƒÈLœJƒB¶Öt¼ÛJÜàÌ´öZò±ôPQ_0ß'´/u¬Ÿqô=~}†ª”9.0Ÿæ‹‚Ué'â‰-vÊÅÂP¶5¦dpÊc›-/bLµ…™y ×YÑ̼GÉoö²‰ff!†×='7Hmçêi»†¦x,×µDÆí³g)Qd™ÐP–Äš¸XÂiè6à1vÑ).¯cLR/™-¸pbÍ6M…± u„Ðc&Þë7hÙ àAaσkç>j»ƒ™#&/d÷IÿE w'e+nE:†Á³€"ì¾!00&‘ànl €ÝÓ_áÏÙ,´%)±ÁJˆ/K÷ˆuÈ(eL¶ˆÔ9,…Þ-Ê;ÐY®ÀyT« _¢vÆuYFO<Œ¸–Û·¤+w—~—.C ÿ1}|ˆº5ãªóÀº“›R‹+¡STHMu%)Ù"Ñ w¨©dW¸g£B-:Òõ=¬F³Àͦ&ö})öbün®w0‰ÐUì`ܶÿy35̰&ÒÛ'È”TÛÔC ;¨(lb–è€ôø^<d\z íìŠ%6éð†¨y«× 9ˆõCŽ–ƒø—\§lõ±¡”ê…ûäX÷Rg/ã@"HnHCE†Ôü¦í5þ‰°ƒ4W%º­Ÿˆ™}¨j{| €±Ý̓U(t(aÛIÀê ÑÁL"ón¬?À'ppþOa9êgÆ bÅ]³-ïkZxÂmx7$¬)jL½hÙ Uá…Ý=±_àú3¼þ ~ÀÁ·0x‰‡û.åµ2X³°èÆpUᱞ£à£WR=æR½¶VþØKß>½°—kN8~Ž7Ä ±ç"¢Æ ŸD$‹@^M³•ÈV…0ðŽQ…`¶ÒÊù.5«P/ko¹¶­þˆêä. Ü#)^H:YÌ#‹I0R÷mnÐwƒî ueÛpHð9]>¼˜ÛK°OuGLÚëÄ)I œ3vÚÁ»†-Ów‘Â÷Kå˜NŽ I.b"kLÓ÷>å¸J³ÜUçX‰æò9ðûN:]͙ܷ§ê¦ÅDe»õ,ľ&]„EPRï|Ž×7Dä)h@CÈâ p®ÁH|>²}¸-ñh.¨ò V&?´ð¯‹ ±¿O Y_%ŠSÈ]™.Ý8‘7®Y÷fphû¯¥…È+è²%I`ÐDËe ¥ÔkåMËT¿ÃEhL¯|;Ëås—‰-ªß{HK3ó;+ö}›Öä‡1³Ø8@„åÍœãÁÄJE“XáËG$‹²F|¿Àà{5;ø«Çó å/;ÒÜÅÆ¾¢2ÖK/ò_AûU í’' y6Üú wβ=¡ᯖ„ŠÉ\±E L£å¶Ðj,3Ôá °w[NפGdŽ•G`…ˆô')Or]çNî£^<=Õº®Þ:‹eŸ >‹#ÿ­7t[ÄæÞmÞI^¯‹U7‰5n‘†— ªÝ$ìÃú…iU÷õ ¹`îá¼Ba?í¤£ü÷¶@?¾Õ™\5†Ø§€þ ÁÁÙ:;xÆ´)† Ž)dwÈé™ÇÔ²Ñ{jŽ[6öBÉ…ðÏÈÙݳi®Ö¾b»B¯öSïÂzÝàsêo5Zá°Ž•­¼× sL3¹ALH½ÃÁ(ÏÇs9lØÍW®Wý8ï'ß0çàuŒòAÝÒ$¸C¢MýLÜŒ 3v/}~k"Ú iÌÌ_Ðyö&a&Š¢n-O…W†´åµ ¡½xl±ó-OÝoý¹78›iá`ÊÁ0Õûu2„Àÿ_âÁQ]¯ë±kœb¹RŽ5ÈÅI†6¼ì“¯Ï{Ì_¤&šŠÐãñr3“D¯¿©±MäLûé_)u ùËYr&y§êt¤X§~)§y¦3òü—F‰ Lè:G¯ismùCˆ{·Õ±_Î e².¶éûiÒ> stream xœí\ëÛÆÿ~…>J©¥"©?EÛ8HŠ4NbhÚÅYÒÖËÒ=ûׇK³$¢  ËòKîÎüæ¹³úÔ Fa/0ì¿óõÅ—?_önAïæâÓE˜_ìÙæëÞ_gÙ á8£ŒÒ {³ë‹bdØKÆÑh2í]Fñ(÷fë‹÷ÃAÒgÓAòŸÙß³‘ñ”ÆIh† £`t¦io¶È݆Qk>îÍÇÆ|ä´»Á0 ÒQ\ö‡Ù×lPšFý_ûxÃÆÞe÷„aiþ{c>òo{óñë`0ŒÓËQ:½ì?•ùXÁÛp`L³§óyÄëŒ8FAçc âÆÌ#̾OØðŒ8ÎO§œx ≠ZÑwHü’î|“]Ó|™êão‘¼Éf·Aâ=ݹFâ{m"{$9…Ñ(™~1û D“Å4ŸY'²X¡ÐoàÅÀ¹Ìye_œiÀ#°Œ¹-Y²¹Ò¤x@â–ˆs$ÞñŠO‰ø—† SCî?jÃiв ²É\ØøÍÀÈ4Šsí Û—ãhÊ9rgÇOãþ7Dý޾ÎhØ[šËµà>ÜËûŠ^uH_#5øÚÅ P“tZ¬é#¢ëÙ|üQ¸íØnðÒ'ÇnÓL,AÒÓc™OÞ$-)Ìž£ÏÕšÈ I´9C$-T­fd?Zœ¦£8œ2Ž>0‰º *• +åÄ¥ <Ëû‰·|RC4Œ ÞVøß âÇ,Ù¬Ó©”P# ú…•¡¦¥Xx?#QÊÂq'…‹+ì5MôJÃüRðÜ8ž‡÷è#¶Üö#[ŽåéÜ2=b†w®~Žr)s7SÌp‚/qÅüÉa è)Ú­G8 ‡kÍuì‰å§I¡ñÑ"9 _öƒ‰Ä99Á žp–5Ÿ±‡îŠ÷5ÈÞhƒOì½ö¤¹GÊû±PžD–—‰^DC@üXÌÞt% ½V"iØ Ÿœ–[0R€\d6ìoDý–¾¾C+ÛØi“k}B䬯vjD_/w½*ÔèÎ'Mlª®°gM°g¡¥¨ø20Éêp«ðŠe®kaWÆRïb-%/×tÃî-{ÄbÚ2ÑÙH¸DÔ¥øPjž}7ˆ®ªª r;\ÍZµ}"ffê#ÇBÑ’vøþ¯Ë€ÈßÒä}¡ r¬€²œîæ·Ä1xLlB‚õˆVÙ.Õ¤`CÌSu’?ðøªˆ›î6€J“ŠKw}†ö³:ª¶J£Úðö4’¹q`µzábæ¿_¤àn \­&Nx”‡#†½J{ˆѪA‰/ë!¼Ö¼×dÉ"Hâ¨o?SOÛn§4­}|…t̸×vS¶ãûø3û/šØÕŒR-m“^/¨ÌÚFøçí¸krdz?;áÿK¾/8WË¿+²dí\GgŠ-]°åÝ®v[2Æ· „T@¡ÝJ‚Á¦œj•Jí%)¥Nîiøã@ \²›Æ G-·v 9:VÚ.:ÏæšHÔ(EMýåd1,¨:RL¢ŽVFAéO¢wÞ Ž8OrE—×mÄfàyÁª_TwŒ×ÇÐ׊ÓÎççµKí£3íj«ï  ©æ„ˆk¸ñ;(ƒHl[[ÙÛŽ“jh‚Œg¹«Ü ­Éóš œêÐr|T}€eý°çvŠ]Ï ¥à1“a4AÂÂŽ©°ðx¦!¸äýïGíÚ´'u©vZÀGu–»gðù€ÇR. Q5ÂV7XøCô'¯Æ&C åx`Ò«=lê!9¿¢®áÚL’{ÈÉd4 ÐCÊHÜ¢l…dõ$§¢ñíέ@›Œ±ë.uûV=0  4æ`UëF¬éMÝ].·N¶\ô†€ç܈Õ0£ Ðx¯b’± ” »aŠ7)ØÉaãív:bo·èlƒ¹ÏË=ö)N'¨!·/}r<oyhåÑÔòõ'-Ú–‚û¡ÃŽú*¡{2ѹ¼…™*Lë³r]7š ¶gvUP¿±z2¼.>ù¿¤Ž¯ŠdjüÈõö<¹ç¬‚ÐZY ÒJƒÔ³[4E-9¯á]Ç òÜuÇ¥«3gî=ç¦s¤Q0·òL[®Þ…~òŽwjÛÛ5g­bÈ–Cüï Ügª[ ~'©<<ýEG!ÜÜåm`µÊf_t Ž®C“íešº]¶¥Qí”þX¯+ß{ô©ºb†•Õ©;Ø?웣‹ñ‡¥jžâ†V›Úó–BØézàÊH…ŸµYª±.o¸:IAåZ)JË} ÿJE+‹ÿXM“éò i£ÿPYå1î¯é¹ïÊTÊåpüÚ~Щÿ»A·©Y^O{F.)î’rí—j‹ÊÕIÚqwTTC¨V›¼Þ.úJõ¥´J²“dÙ!`Hô·‚Bâ˜Î»b*ÒÈUAŒ2-œÄÔ›µ…âð³Êñ²fº³…`,Ý»ÓÕ±$ñû°Èjk%Ö—í¶=86n…U”¼6®åoM'á+A,õUèÊàî~‰DÕ{g"¾òªÚ¨ZÓÛ"Í›à»T ÄF ?~ÊÐá÷Ùü”¡(`zxÆ(èŽß)¬M¾ú¤Ù¯ZF7ùUC¸·ëŸ2Ü¡¶—Ûu|Ôú'Pë„ö#^gã$Ê“­–8£ÅuguXȯ!þ^÷Jœ\º 잤Ü*æ"5vÓî‚ï(’gW§Ôò1ì§ŒÈ@l¥8[ôŸ„º¸Nb5¨n øŠˆj+ÕN0Ñi>[¹ïL#= §Ù?ýtß)v:¡ªí¦,6×E=ØÝ¯`4•ŸJÀ¿AD+‡)ÉzÙFêö‚_S5S}=»ø)ûó"ìýÞendstream endobj 695 0 obj 3072 endobj 699 0 obj <> stream xœå\ÛnÛH}÷WxŸl "HŠ4™ArÅ&›Lv0ÀÎb [¶,ĺD’íh¾~ÙìKU±IIfì`ƒqèfw³»êÔµ«ýõ°ß ûê?óïùôàçO'‡ãÕAÿp|ðõ (^šΧ‡/NóA˜·ô²~ž^è‘ÁáIxx zýððtzðïã GùÿýNüŸÓwù¨(à£Â0ë%i>ðt”w~ÙéŽÿÞ zY–²ãçðøŸnx|ªÚ_wºöŧN7Š‚^¿R̯þïåoÕdY–IãüßhOÀFôÕc¦Å´:¡ú5MÔ´Å¢ü÷$­~ÏgŽÃÀ}&_uò-õƒAÂß¿éDùS”è­šä×|Þ·z‘I˜‹6cŠ×éªççN7É_‡¡&Ë ådéºt£~ï$È2Mže>Ãñ…ú±pOCõcÝéÆý¬ G7ŒÔV£ã?ŽÕ»‰ú13½Ôzƒ@»9ŠyÿèäëÍNzYzr|í^ÍlO=p­6¯évEßœ»÷—ycØÏ)6(†ëÆkDSÔ8£ÆbKi±š[¾nûþ­‰²¤ÕdðÆ÷\ãX4Í9¦ìûÞ¿sŠZ¶õ—|TK Yg|ŠÛÑ ê9Ì/!ìãÈn?R4eû³K»Ô$dzkýL/õã J ø™Ö·v­N·!=žÑ°k´2µþ®Þ@7ˆzq¢ÝsnѨ¾‘C°[àÁ qäzÜ82©_-ÜôŽn;±ºÀòÊ¡zîªÁ›ª^¬;£ç5j\!  ‡ÁZ4b6û¼wŒ…´l†oöµ ³ÝÆ}h͇û´¤Y! ì{ cÇ(ì…’ídaÁB¶³0\ƜӬïŠZ™$iléÅàŠ³´ ®;˜ÈlîÇÒ|CZä×Y…f´ªrþÎ5>1_êsu3£ÏB¯„„û¥Æs„¦ 4fE•ÚÖ|ýŒºnø¤Îâ¸Z˜I9(ºUiæ×ks¡r¶…ÀOêG*4IP¡4H‚LjhÛ€#_ÞnÀ0Öe `¨Oç_‘À(\¥ä!€‘ QîÞX+—õfæ4 ‚Jˆ8íP =g³r K±&»²4¬æÔ)~q6R‹Y¾l&b#¤I¬üB„TqÙÚTà ½Ÿr‹ê;VˆO¶ñ9¡äŒSîiÔ’Åc7s"ma“¤ßKL¤©dΞÅ6-C1ª/žlÌŠLÖ"qYB¢^v­–šY_G±§U3%fŽ$Ï„‡X£‰„Î*k›,jÄ!ó«™‹:©À¿YTÓüÏ´´’#^òœxpú“G{'ªdÈ5-»DEM«%øŽ'r ‘n¨Z”ÂK6¢Ô ¯W¤¯¡)m"½  ûæéÂûfNÿ‡”~Æ6Ç«;ß‚k£Ž Z”“K7ðšOŸ3 š8:¬ñrDN_ ž’S××cŸÑ®–h-‹9Ù—÷é¿á€Sú¤í¿wÕâÄùp‘sâdèRvâ"íÅ "k©WŽSçŽï3Ãü NâmEÍd!Ë`jd#BIá¡÷ )4kLÑph˜VAJ¢ObÆŸð÷~Ê"£Æ¬±qŸ1Ü­¤‰•Bß­ósÊl2}´ r…ÀÂmû\ÐD›£¾^ØÈ£ª9·t.¾ é™?ÍTEq’f,S¶äƒÊ 4k²¸ŒÐCAIßõsøÊ¿ð5qvlᄯk§Ý(»0qŠkèºp|‘F¼0Þ‡µcM„~ãÞ³,à©küLÁÈ%ÒiÂÊÛž0FØ Kßœ6D "ïÆb·T¹åÜC«Ú®å*Ûï „~NT ÂʈÁfI}Y‡rìÊ"†XXDòæ)‘‘ölþT€çÜ)¸Üœ[­å©)и•»)‘O{*ds¥Âf’o(%º „ƒ‹ú ÖäÖÜð×µ¾„óŒ÷¤ ÙÙé¤aˆD@ÐK'Nsº:ð8ß:.}R{°s¢ÞØÍû$êõÖZHÐ\Ô`®í5j Ma" &°¿PvŒÌí :¯^­ƒAÍy Fã4ýZˆ4²6YRßkåˆÇŽ‘j.äÀ“¾ðÙ( S¶£¸›lk_Ç©U­Æ„LyûjhMìü>iSœ©m)5± Cû­ƒBºWrü꽓­¥Qƒx;cµWf š†&Ty¬¾TWZ©n3.P>OUL@òî:£4a,Îøn0óÖ¡§JJbCQK #JéWûGÉ%Œ­-aêºU@gÌîãfˆ#ÚL²C]"[µFb·|ðmtÀG%\¢PÊ4Ûd„>ºwÿ Ò­¾ÈôúÓýzáì;E>Cþvž¨™Zð]’«~ä»ô½¸r³@d€}§qÜà.@;­_3Wh‹LqTøÛÚÍ@¾/QH[qŒ2£¾Ò]²²T ü©¸áÌ’¬Nó⤤tB_2ý¥LKaòˆ€…èð%*—l­" Y^Ô ï~©Í7á6$õ9'Éý4;Ç6ß +:aÚ º ²½U^i´åDTUŸÑòQÄØZz¨2ðÛ.ª(°ã¡Æí'ªGîW@'Ðáûêã„M5eƒÛŸæÀXžöCÅ ÝÌsP-\[B•ÖÕôd§ Çì‘Q­e’üdôîF.Õ§±³8\Š?^8>hh”Ɉ÷K#îT„Êøé|‹K©t§-jwëâíZ|yOͺ—ð§Ã,d®íð‹$‡Çkô}ªpÁÉ„[´ù9½’:—eQ6o蟄–œ‹§R„YØë—u¿0àJ£>WÏŸÕ—êÇ[®út-aIB]x{fþZ¾Ž &9SÙt,sû„xú¼áýôžhÞCú`$g2ŒxÝÚL°ŠðÕ.Ócý­äÝcÏ™ÔÆ%©Þt\™»ä¯:%¬WF"ûÒŸÞÿÞðþEÃû· ïß5¼¾ý{X«O=_û3¥©WM^6uøà1öÎ)æ’‹ÄŽ„Ô›¢cñôŒCÊ€`ä4øY¥ö¯Kû„4øj|†l*S›=$Nlõ°Öà-æ}IC­X†k)Vo5é3ØA¦m_ªQ ámUE–Uxô74•¼˜)]»bzéÚýê”…µé¼\‰íº»).¡#¾±ÝBÕ|D¡x³ àߟZ‡!,¨±‹B?xŠ3CH„)•пUDÐ%´¾xæ|­£m^µ2{`ØoU… 4´!P'GÅõhý…¤*¾8M²±JƒÖ£mƒsB87hc¬ßÐ! Lº°r?Éis 9Í2…0´‡™=š^… ýUSiBÂNUM@°ÂÈRÒ¨í6ãQ&ñE£±79­qÈÄùí>5[ðœb‚˜8#y„ÞC s¥Œ>I>S¡ã W. Ê̤.÷µÏáõ_òÕœT©}cÉv÷ 5² ‚Á ¢=;hÆÒç'¬ðkŠ»ôë²>ët¢§?Fh¾ ?Æv°"Éš‹Í6*Të‘ùjÖlÍÜ…„˜Š˜Bt푲&BíDÝš.6e¿æ@Ö˜Ù\X¾6®'0ÙÑ»„F7¹„ðHG\¥÷Íü™‰naÐ 4S­Ø¡´wà×HùÎûYÏkÕÆSÏËýƒ› H‘0ûy&@_2Æ¥k0ŒL˜ñ½*{ÙyuäJàK÷L©âKò‚Mäý?./·`¯€£_IÞ˜qÃÝã’•šËñcc\ úRó‡ÊÃ3hø®;qå^ét[ øsǶ* ¡ê‚€+GOk=*yò]j9ü°²ÚɹÀ£OHèéŽ)‹x‰X²ÅŸŽÊuc%·sGò8-Î]nœÆž‘xt‰"|%4K]ТлÖ]…Úx¹çß]kC4½’ŽVESpqÿ‹røR­¢HÚr–2Âéפ™íãóO²ÌZîúzÕQzl¾$ýHÝ·nñÏY¹»¦¥ŒTÉk³1ÿöRwÏâ,B’Œ­}ªÃüº x=tÇÍ—ýY~´6}C­¢Ã¿%/Ö·Œ°²4 /¸b·&ºÔ9¢Ö>|´Ö¿öò•;*¹h¿8KærÚÞešf´r÷¹îúÅöÅ:»ýEIÓ¨¾ ¹ùIÑ`°µ! þoÕ¿~06î©ß“Ò5æiî rV]<ªó‘, åëRƒ±¶âTÎ6¤¬í=“{µÒ’áŸ~X".*hí/^èe{gë¼Ú…™ú Ä8ÄH*Ü”o­¶ŒÜ)ëÊÕÞìlN¨uµkIɰ[Ê0yy'¼#ÎE(¹çŸFÄFa ìèìhc™ëPºÝ¦‰o©zÍåÈœç±Ò{ã£ö½W”+ ðOLžu€pC‰w&Z±êõéÁ¿òÿþ yyÖœendstream endobj 700 0 obj 3683 endobj 704 0 obj <> stream xœíWKoÛ0 ¾ûWøh°gù[Ç=zvYáÆv‡ÔI¼yÕnºøßO”­WÍ´ËÜ•UJEò#EÞÛOì~Ý·X[ï¯S»¬­À.­{‹ðE»ûkûcÎ6Q|Pbç «å$vFþ$³Ó(öƒÐÎ×ÖCÜĉØûþÌ¿0Î8Ó9½8!ÀâEŸJí|Ƙ~»^ä,a˜ÁðÃ/×K‚̧4r<6eûazëÈ­±ÕBœ9ü[ÂÀg ·®ëÅ4õi–b2ZFMÐV ’°ùÄܲ}Y6 ¡œ©ÀÖ§’XaÄBM $O{íÄ©%ñAñT’¸TÄ$– eóôèïT‚VŠ8Dp‰üd.ýjåïnœX ôä®$ øùŸp ß¾‡a ÃÉX)Múf«ÖW’¸Wĵ$n”L”}ƒydú¼G–úéb¹+d@~Qï­™Ñû(ÃT†7Åté‚G£˜2—²¨å×Ý"Ž2¸¹EM6÷¥Î£¡¥fDqÂÞ`ÓZNA¼×É÷Y ÍÚkLÔGp5“ÈÛK]ï: r\ñøe2wbsXeJílÛ‰wmÙº¢3µrèA7¥ Öêª'9å9L1`ÍÕÍP˜ àkŒh X$C:×ÄZ¢Ñ<»èÅs(m¹Bá !®0!±ÆDí 3‹éA±Í ðµ);äA@?W|¥ég”\O¦; ÊÄÊá,A¹Ã vÀ¼)mk‰q‹ÌÌýã·}€•岓ZÖgiÓâˆùúDôÑ^ºý@_©ø{³4ÂMÝ{ÿjŒ8m#=bŒ±ˆô•¡»²†²s­?˜Vç/YFÆk{$^«~Ð+ÿ ÈzyyÒŽ¤]„ˆîTX0 +öO¹-h+t‚Øg§GÊ|±,œ²V ˜2Z$€lž€¢cGJ î¼G¦ƒÏo–!1·¢UóˆV?¼T×âµÂBV¬q<¼ÀÐ`RÁ1-0¸fÂjn.ÝÔ¥›ÜMÅ‘HyÄÅTxûµpµ’§Öc{tæ„íÑhÆ)1¢Ú¦¶'PüËÄÑ`Ï•ñF‰¾B+wµ5PGiO•[©Óf5Û˜fEÛúc´¯É¥m}“¶•ƒrdmksæm«²éxÚÖ“mzi[_l[?«Å+5ý¤öñV{P^·ƒm$,ÆÚÁžüº\:ØÁ¬BÅX;ØñÖ—ö•:Ø«ÜúÆ~¬ffŸendstream endobj 705 0 obj 934 endobj 709 0 obj <> stream xœMP=o! Ýùñņã`LÛDI¥~%lQ¦DÍtCÔÿ/Õ&×ödYþx~φOÔæxžÌÃ~„ë· p57C„9œ'xl2@,_C%h_æÎ$Ƙ|`h“9ZÂÁFqÆáÔ^„iÉb®>!¶‹ ?¡Kv‹äk-©Ú²ý@ǶiîØ£‹‘|c×W÷‚ªX­B)ƒÄ˜D`Áš—.ûЬeÉ*ÛD©³°µåéo ±}FyR ”—ø£dQíTäMtw÷#3ç~ôÌéðûÿ< Ë3ë·¬›ùûÒiNÜendstream endobj 710 0 obj 232 endobj 714 0 obj <> stream xœµZW7~ׯÐã*°Ö,[Hø!@ pbÄÉY~²ó S»CT.’®ùׇe‡3ܥ𠷷brÊ÷ͺÿú,ç}fš¿“UïåUÝ_ìz¬¿èý×㮳ßü™¬ú¿ÌÕ,¯*QõGóžŸÈûµèWBäº?Zõ>g¯Cž³ªP*» E.—2XÎTYU’gwM³Ù~ÀóBèJg3ó¦%«êl;ʺ΅À­,)™ð¯u)ÿýîwR䵪¹ÝIYæ…Ôª?zßýò9{kã*{g™¿5«²‘[²ÖFüGÓY(Î Èìƒ]“ç¼Ù;´fªv',×¼Òš¾n¬^W\û­Ê¼Rº˪²rJ ¥­ÒÖ¥RÛîqÜÎÌVÆ,¬öF“¢2[Ù˜õU^SdS;³ëóšI]Ûy"—Z) eÜ”k¦½-tÎ+&ÀÍ"fõ¡ÛMóvoFJÉ´[}b?oìcj3kÆ8÷cT®Í¾omÏÚ|–F%¦¼ ›fxɵ´ ë¬íca7ªµRnÿ^R‘ ƒxý…ìC¿ÙRiâñÓ°‘3Y™v·¼o\ãÈ)ŠçVvx%}b{(«GlàûgØ¿‹†Â+ðÐPHe·]håì=XgËZȦg›HŽ[Ý„á[ïñu"ï“Ëã¦ì*C»Ì˼,-¨ìjo­?-^,”¤*÷ñ†„• ,CX‘Üà¼?µ—Ƭ»L 2î—ýa/Іë& ½OJ/oê‚¡—o·ìbß.ÂíPf–FX¡ìr·!8ï ^ÒC˜„Í&g³ýDh+Ìíç[4íò@<NÅéM²úÇØ¿J,êÜòä€&’h¢}`ƒ ®²Š‘ýÜèk|Ó ç5²Ã†7–hEWÞEÚ!„½´šØi`Ý `Ÿ¤,þ*eñeä&Ðõ6%tŸºMŒÄ+e×4V`Ô<4ÎSŠo»±¢êè^zj¨ ©UÀË }gŒiô~Þ?5È&àgáÇ º°i¯TöbaGý*¼ ´e?²Ä1dYmãÈ./Ómºgòa·²­ öïnä£ox&¼ÃŽBãG è³u¢±û% ¦8`“šµƒ¬à°cV=cEØÛcjdÄD02IOˆ ¨2 Vcˆ¦‚Ô4£`÷!]剈p4sB‰iž!%ûÔ =+lé ¯¿âë—AÜÀÊnðPÚ©.‹¼ÇÐ} iæª0D'‰´êi²R²Ôù ±ÚÅ_ݲ$VIj:G(shK$ŽBU.QBKëûÐA<—¤Sl„êÊXã=ÅËh:`1Yé |&3Êy=)iBÍÓÍ8Ĺó”žh›úñ¤Çì {¤ÜÍ;Pi|ß… Ç„Ÿ}ê2PÄLìâæÇâ|»}[üƒÖçŸ%t“l™T8Q|5eÙwì8Y.ïÁ´XxûŽq³aHÕãXIÄÃ3ä£ÊÃßÉ^5b»Ù—‚O²ÞÛÁâœlð)¤ÙH6âá%6@ó¼XÃ9¬‚Cƒê¡øÃjšœúÀ¡ç§äóy)iÎeä1FOÔ“FÝ%¼×;Š¢uìpÙ²%ž²–t¿Žu³äÞZ6a·ôÖc†1š:‘Æ$ß>wR%Þ8¡FE \¿MÑG.® †» –s¦™Ç¦yÂì±ù6È ­i<ó*©Í€bçÇ}ØømÌ€„ÓẠîúPÏî(“K::jânzqÕÑ }Fíß…ÆxD‚s›BÂà " DÁC´Rß46Óµ8( ~ mûØ›˜_íÑJÓ‚qœÒt™ÒtED¬I„«x'X:ÜDÔE/|.3ÉÃgR“T Éâh‘‚Hò¢*®€;‚Òe£h‘þ<Ø#”D¹Ö©bã.LÜõÇ_Ô´î¨Û¦PçjŸBãŽ|XWBýçlùœôÐþþ鬯š–) S~õdqYÙâñë° ùVsd…yÎ5xz¢Y'ÜkŸ:Z»áiq&'¾¡~…éßGj‡È¿l‘ÿ,j`(mÎ+[¢T?†à‰#(B Úo‡})1ii$dÍœ<¤Ž0P¶ø½ýuž!ÙÑS;É€áFTµÂ$fùcã&•Páé¦8žðÊVB¸Hßl†ìÛéCù‚èK³F'TN¥Žd|¨òì1"£æíëYµlewíó—}¼Æ=^v§þ€¿Ñ ß>ã1î9B‘=†íhß™És…®˜·Õòˆ1ª;'pŽÓñÏÃÙ÷sðË+.è?~Qæªèwü?ÃøCgi˜ÈýÚ9oF½¿ÍÏÿÞL“àendstream endobj 715 0 obj 1984 endobj 719 0 obj <> stream xœå[YsÛF~ׯà[€T‘ÁI»)ùŒ³ò±]åT’š²Ž2‰¤¬u~ýÎ ¦/ EJe‰I¹ =w÷×× æ¢õâNdÿù¿ãéÞOï“å^Ô9ٻ؋]aÇÿO;O†¦BœJ¯ŒÊ¸3<Þ«ZÆAÒ¤Y/J:ÃéÞïAæAjþgaþçðWÓ*y«$*{ƒ¾i8<2•Ÿ†Ý,ø%Œ{eYde°&Á»°›CKv¡à}ØMÓ¸E×bþ÷Li’”¦Bð"Ll½¢¼¢&¶ Ó ÎúÁaØEomo¦0îÛ1Û{d‹â¤0¿Í8P :€áãÄõe¨‰c‘šVnÚeÄÇû`æEyÛÚiê껥úr;¾iÙ7SÂ/7S?7ïƒARñ.+8ﺞyÝ4ê Ⲭx›Þ‚Ü>f‰QV˜y ûþÙ>–ö1·#šÁãàÒ¾ºÒ±¯’•¦ETGØddGØd=TM¾˜9Fep…妸ÉñÈ6(,«Ø<ÆT>æ“∖qÚËû`{ÃùŠ Z±›ô Ÿ±Ó©}=÷Y90ø:f6¹CUQ-ï90ÃÖ?ẲÛÍu…DË΢oðÓw\kð‡–j¹˜DÑÇH<£šÞg³&ýLã9Íó‰–“’}%±ÏÁ䥿àç•K7‡)2i*‘åøó*~²ï;´t‡‡„Ù‚ˆù3"Ò8+9„dRœÉ©Có¥Æã¿´š€Öbà8AcúîIا‚Ýy\:dM5¹Oµ‘f¼{&£,êõ‹(´'–{‘}Ä$®Óë”õ³—°h†XÑI| ¾õ7ûúoj½A>?%'˰ÐPº’lóT©]h–áLë^àÝš§/Zßx¥!k!Pà‰ˆ0DyY4E“Ô4‰L ±ÐNÜ©põ Ë™$ƒ¶/HtRöÕ[Ä&Âè˜9Æ\#¡†Y¨–åX+'C?“ªc™Åœñò›ªÎ©&³—lSÜ‹†y#¡¤wÊõ ¼CÓÒ3®-B‰RÔÐÈI’Ÿ®Y54'N/‰Ós­O&S*?¦FŸn#h“±ß¨G–jê‘‘$nsðÓ_‘õΓ\rþWXë×¥7‘L®Ê%ZðDÃ%¡Uæ÷¹Ê%Xêªõ™6Í“ ° T SÐæšî+׸I•ÇkçmFR}€ˆo2Ö¦G’]"©¬•nš•F¼ øî³´àÊ-N×7é"0lK‚EŸ`q†2ž@ªp,\íØVûÜTG»±›>ßÀ¡ø(ô@³Ó=¾F‘ü€åC*Ä·D|Ä×DŒ‘ñ_PLD“ürµ•º:h+— hò % h§ã\÷ˆwRn!>ˆžªü§ßÖõrï×h¾Ù^빋¶–Ô)Ê›€í3žƒav_5¼ ½ƒšçëW¼ÒvDÉöfqqòAÕŠM-ュ6üÈK¾fgJó¼—€% 6)FõçšQu»qK›ZþÝ¢ºÅ•Öç‰F\eøªAm¢'"2öL~‘O—`3káVªó’â4ðiÀúÚÔÊNm=|Ž„7TëÙ30ÛJ6›|Ûº©'öý•} íãÖv´Ž÷ŠêÜÔ€lTIÛŽ±ïû~!Õ2«Ú‡/¯3 Í8Ž»Ò­¬-½µ¥>vø¾‚ þ%wÿ5É1¬È(ª{s‘8¢š‹YPù¹&%uïn¥…uÞdItÒt[ͨߴYï œü³¶ò·šj RwL|à–Ë)óƒ(®Íì³ZÎ ûÈíÖùò±®³±ÁçÖÙ:‰sæ÷ZcòDöõ™}n-‰ÛŠéb©Ñ §ƒkCE÷¾ü«¯ê¶ïWä…KöëÙfˆÌ*µÏ™­`ʬ†È°“†•VSÝÜa[WÚ˜G|@<¥üVü…‘X¾Ì¢}$~$¢°öÍÔ÷š„ÖI­¸“Ô\Ϲca¼Å>§Ý1‰ŽÂ,6ñvIAM€÷µ?å˜a¬)¨®ã!0t;ÉÂO¶Ò„Ü‘mS¨¥v×öÀfµŸŠ3ÿ¼šneÜã7ìã7MÛhbm¾ÕCE 3lg£Ñ<¿E°||yÐ`ð°ËØ¡¦Ó¯9x€DÈǘ Ác—ÅòDËP ¹¦; –t·Åò ûTë£&«CòFVÙ½ ƒÎÍ&ó6M=¨°X´m_»¬¦ÓöèQ <.OÄŽÔšõ±ª‰r"æùnk'É–e©[Œª×{ËkÚþ‘âj'øîÁò_É_/—ìýBJûA|Ñ!t®Ksä •Zå­bxuó^Ýh§V=¾&æÎ„2hŸ ¸ÇàÞY {m‘Ý;_%3‹Ý6)”r<Õ Å"’·î@¦&°»#–—?±¤awçó(Ay¡%(ϵdòY3f.±„î7Ýð˜™$øDóïo5 þccæ4¼÷†G¦Òdißk›Fÿ @ÈÆ4”[ß#"'óʾʣ0ý¥È„ "ÿ~A cIëCW·î>™ÀɪöAø0ðK­>ÖZhcÎ8c6ù™kCôx4Õ®NÕ>ˆ¤#§9Š·›¡„ ß0s'ÿ;Ñø¥4}V9¯+,ˆu·K3—ØØñ“º‘ªî Ñç­¿U mÓ+  ÕZ÷;E‘JfÚ3¨¹VwýÇ'ýÇTu#´Â†s’Ï¢¾€ô¬¸dá+Võ&ÝJv§•7­º´ÿ> stream xœíZYoG ~÷¯Ð£¶¨¶»ÚEQ8©Û¸ÍUGy(š")B%[‘ä¤Î¯ïÎÁ!¹Ã•V–Ó @QT±Fœ‹üø‘Ù÷½(Œ{‘úÏþ{±8úî¬èM×GQozôþ(Ö?öì?‹Þ£Q-ë–°Šª¸7š™žq/&a^öŠ$ £ao´8ú³Y?©ÿÏ‚ì¯Ñ¯uÏ´¤=i«.ƒ$ ‹¸ªz£ËºÓ0$uú# q”–a÷Ÿ¨ïWêc¬>.ë0ŠâØ´­‚AUuCÑŸ¨ï3õ1·ú—83WtœlÕ}Êþ…ú~ †aU•eÞ¿v£o°qìg’äZODÄñØxîçÒ$Øçï`VEX•™^¨i|'õYIظaZóú¬¡QÙ*NÂ,Wv|z4ú†%C£üäì±Z] V°ºÞm…Dï}?Õ§U©Çø¼ê¿¡?gI\ÿï1å'ª~h\Ñî°®qŒ’s×x‹WT ¶Q™ÏÙ,W1ÚìÖ)X[‚©AÛicÍ¡ÍS›téúhë­éf²¨¬§¶0xÅ•n9ÉŸqÝ/\ã6>³ÊBiÝ×ÕküˆhåKk´*ÝO—0=în#™J„át‹†’œ8GµøŸ:íBŸ¶X+-s½K¥d¥ßDk¶©Tmž”°æX"±ñ—Ô&U¤¤¦~Ïz¾RT £ ª”©ÛûLjeÈçT}ß ¼q‚„Zz‚–^IF•cDÚÓw15@PUî÷ ÀÆ7SU­¡4©JßíHòˆ)ʆ»ÖÄÒþnçŸð¥ÒJù@Cd›!ò:7•”„Ð$pø@»«dr"I1—ü¯¤™EjFÉKŽ Ý®ñ\òãUÓ 4]D3äûšÁ²6DðÒÏDXö¨%!…ù裰dB¥cÄãCZÕÏS÷R8uQôF›ˆ¢GßíàÀ5î“g2FeL'ï, æaèò¤Šft§øçyíbt"rà| ª9Û(°¸oT];œ¹dÖÁ&\š*§ÆW?~䡸#¢ws÷„áÅÄL<¶ÜŠD€!óÍñp¾‚#-½8¨ìÊŽ¥MYMª?K1XèΙâ}‹ò?‚Å•íî[x!5ò¬ò›ÿ¤æÖ#*¢`ÑJT¥{C¨ž©Zª¯3d}žâdý÷<VY‚Ûì^:iÛ›p’³“Va^Æ€¦ ,XiY@V'ÌpÎŽˆÉd7$¼qoƒ¦]·Ào±è׈͹dé©„´4?}ßëtN²‚¾½ w»Wï»_.Ó”i­Ÿé:Lç[éC¬•ÿâà‚űúþJ}<lqÆHŸb]Cì9 KÎ<Æ•îU1l‹†~XS°Aí®cî »lø­y8†úe‹$F]¿Ý!þÒT@ØÞ¡Ò Ô•á}¡rγ*¦tÉ®¦+‚oïÛéóƒ=_, ÉÐâCä+‚!x‘’Ì Z¶"· “ /DaX>¿ä0Ã+§k?êe¤xM‚Í?’¢‘’ÖhñwRØYKgÁ¦>øý\š‰1Rí\®‰… ×êí¨þâëÌD…`:z!9ðŒŸœä$_4E™XÎQÅBЮ„a÷’·©aé9 ñ:ðÚ’8­¹ÿIZŠ+$.ÌÙêšN[J>«ojH¹_y‚(Á[Ã'û;töKç¾ Iyì¶×W»™% Óâï·¢{^ÞF§Sé´Q <¯B²j\¦nP#K'ó÷Ñ9Êt6ÉŒê2àÃojà’µûM(In‹çÒô\?v¤½Èd¯’‹º„RwÖ¸q<:ìÆaíX•@ôQÀ’ëc\ÞS7ú‰T"&ü‹¹Ò+ìþØ5Šc’+$‘tÑÊsÉ3‰?Nñ·”¬,ú›È-µ ˆõ?˜ô1C¡6Õ½¯žÇÎgÖq!à¹Þ®NHÂŽ;hñ3ÝÉâV¥›èÔr9 é¹ú®Ÿ èËô·nÐ_Ô×3÷ëkõñDŒð±Ö˜TPQÈÓõ“Zl¾8ËÓzB=¬G5"+‹nÍX.Q&Rw”k[3iök¬ézkdïs¼Æ¶«¯Ôò=¨›]åSu; žY5Úc´þƒ ?s"ú¯Gî«êË@žZ¤ÃüBOÇvjm_úU‰FD<‡%ú³&8«€%3ÐË’Ü® ÓG¢úº¢úzøl¡gÈøc&3Æ Á6Çn©Îr Ó;ö¥uæújjÿZ ·eyùCã¬mQ¦[‰tý®Ut°Ê g†‘3à PáV×*qtg<³ºç|§n¨·nZÙ©³Üˆy•6•¯òê`ÌÃ\d±¨í'ÍYõÓËèàYž¶Î*¼±­«_ØèfLôh=cƒyàuš®W$±ŽÃèÅÂî\"î é2l,¥!âUÝ¥—×5Á¯'wîZòª·IõGQ¦¹Úk‡K6Ø÷ŠI~)T ¶ ©–Ùö„(ˆkeØ ¯Ç†)“"…£¥Ê™ñaÅKiï{=ÿÚšƒ²Ì‡ wâ}ĉ"â nf‰º!MLpKáGK¯6ävn,Þ<‰/„ÚR SOc°“Ñ$_l\{­&9ÒÀ­²0%oU©ÑU$iÞf‹¯;Äköo¥ð0YÃáVİõ1ñbMŽ"dü `¿ìÿˆ­ ï9ý^ÿ÷/Ó†-6endstream endobj 725 0 obj 2540 endobj 729 0 obj <> stream xœíZYsÛ6~ׯУةX’àÙ·¤Iï©ÓD™éLÓÉÈ’l«‘%Y‡ÿû €Ý%–º,·ŽÇcšq,¾ýöÀq׸©ówtÛùêmѽ^w¢îuç®ë]ógtÛ}9âD–„UTÅÝÁU§nw‹¤[ˆ4Œ’îà¶ó{/²ž¿yý1øQ¶1n•DUXä²á`,+ôÓÞ÷AVU™V½AÒ{ô“Þ@•¿úöÃÛ /DFQ¡ûOäo(¿&I%+ô¾ U¯Ì{?@Õ…l§yï]Ð'Ÿ.Toòcœ«1Õ{¤>ÅI)ßå8¶–íÀ'º/Yš(K![i±«÷^ÊEY«ÚBèúzªæ»_¶Ì¥è¯û¦%‘õ3ùQ$5vi‰±ëðú" ‹¸ªj …ìM¢]?²X!"z¿¨ÿ¿S7êñQ(Õ0Bϧ~¨?ù¸p•_»Ê²—BÄ¥œxïÊ.¤ î¥+œ@áÜ~èAé‡@ο*`¨¯!T˜ºÂN\á ¿”ÓŒJ©¤¢7âzæP¸p…Õ¼Ò\‚Â%7¦lž%‘®¹!ßíëmýšŠw€äGRm îDA!QJzPêO£<ÌKk*0¬úÖ7û±³\Ù¥Bq(. â(mÎÝJ3Ö€!°¤Ð™¶Æ©’ˆh¡±ŽS¾ëǪ-Wsƒû4o«¢hpåöÙd(=ÐHºBYaU&¬GšDSi¨‘EÕ*½eUÙüÜ|5W ¹—êßêñÊñ gÓ²E) åßz—œ}}9¯]á–Ð|—™ƒjÖ î%7ò×Üiã!Øø{®Ñ–ëx‡LðÁúk­ ‚†æDR¬¬²jXÚt/Gmካ9Ä’*e°p­võGÆÚ4_p…!4ç oX“ØŒ)T¤ÛoI7à KZ²Ê™5ô´åPW`7çñ~²®®üѽ]ÐÊ]½ßH|TáÕË“D™Û†CüS‹õh~Ëh8çm`6 [êƒüNÁ›n8¾Œ!ìÜìf*5IÆ:Û¨]Uª¦©G\‡ 5s5Šî ~@¬XÙ‰ Mz QýÁ”Ñ3ª?(ÛÒ¨(oTK\C«ºÕYú6r”÷-ƒñ5þ…D Ûýáö}Ý¥ížpÂv?T4Ò¨°‰Õ cã;M‹LXÑÒ啎JÄ•^E–…‰M/V¬úA­õV0ÔÚ«k*ØfSή~ØÄk¡¨³Æ%ÿÆÉNY{kD“}ÞïŽv[2´õ+”x&_3CŸ“t(°¬ÓTË£°L-×PÈ=v6Ñ8íjïRaƒ ðNï jbÍíÃ!)ðâbdiYW¼Ç˜Ò:N8ÅÜ©b¤Ï?±t;Üš« *rœ½†æl”zp…q"­ˆò÷9¼§p²u¡Í§µÃh©Tw¨;Ð rt.ž «u7q<[C-­Ù…}ΈÜl¡g’3XëœO'9iÍF¹¶y2‹_2S§„ T3+©À.—ŠjMŸÊÚ 3¢=ÎdÏöþh{·ª? ÌW~ó6©ÁçϺ;›îÆœÙÂÚû’SÓ]rÃó{&hÎkÆê§`ÔÔ¥Ú”ãé|Añ/æœ{lÇE¼zÃÕ\q…4Íò–4· aÛ¢J L~úø”ÀèÛ÷ 峟Jçsõ¬µúº¬žuùÔº|¼ëo%è’l<´Å€f铹~Öódžj–e—.“@çŸ,™tðUq§«­"  ˆ‰damz › j_˜Ýt3 $6›‡•^ózæÌ#Ó Õ 4]›Ç%MOK%?zŠW°&âdBÒ#ÕÂiÕ–ÍI i˜í1˜ÇˆZ¸!òûDË—³í‡°ñ 9“+N‡È¦6•T„e# B;ŠÝ×îõÇ ¨õÌ“G–­ÍxÐV]ƒPÄ›§;òˆXÖdz:R€“¯Û]9*/ŒáÙm á–Sd«S”ŒžrêfÉȮʧ˜¾8CŽ-lá7ú.wpøä:ðyº¨y&’0s>¹qìb>Ò“д8.ÃZËE_ÄÝÃÚ=üˆ缦†XŸ f‹(MzéqØ:™F´d;§â¤LËBûÎÓçƒScu$n2+vå(PM`{ËÆ5[Ó&M¾kŸpYÐ9ëwdOª’HDD#®]´Û):cêˆ Ÿ© ÝÒAwÊÙ-{¾Ç^rXŸ†ÇÑpÖb2Šþ :Û-ÞÆî ½f!ðŽ šÇ=ÇwäiÙc~’«þØ] 6!!`ùážfø›$m®™ËÁDÃ5BQÞ9£2|høŽ-Æ…lZm® {Æ!3¤¾„?*ڵΚl|ƒt$BÇO>­WœÈn;˹k?§®˜MKDŠŸ4à¾r]–Œ*¢M»}çôk/rKÆzDö0dÁ!‹ºgÝ(»9z‹»o¥f¶gqÓíÄ9ÏFüƒÀÇ(+HçŽËÌõő∋1m©·Wð<¢}æ]d³¡bW8½¯g kõ5ŠK ï†2×sft1n·ºôjŸ!$‚öܘ\Qït°×l\1É‚¾Ådä8ÕXÄ®VS§´Š€ýÿkÏÀ­rÎàJ _ÛV’ô’‹èŸ¢ì~ÐA‘¾>Çnšì1ûSQaqÚ0&êûEvA=”‚æ]7QŸŸ9<ƒ(wÔñMšÐÉ2@y产™+>iOùm=»Ö½ûg/W^ˆ™$GawJ|9@bßÉÆ(ÖCtiäEKë&Ѿ=Ç/s8Çpµ› äû`ê“×êg”BtãlXþƒ~€¢‰b>d™wͩîAÔ›ÿyÂ>þ\&¤üõ¾°Éúzööú¸]'yã~ °™Üß5k2 ð­CÙÒÜ2\¥XµžÖmÛÔcqÒ}`H÷c¹«;8K9qÁáNÐ~=èü*þ‰Ô+çendstream endobj 730 0 obj 2241 endobj 4 0 obj <> /Contents 5 0 R >> endobj 16 0 obj <> /Contents 17 0 R >> endobj 21 0 obj <> /Contents 22 0 R >> endobj 28 0 obj <> /Contents 29 0 R >> endobj 35 0 obj <> /Contents 36 0 R >> endobj 40 0 obj <> /Contents 41 0 R >> endobj 45 0 obj <> /Contents 46 0 R >> endobj 52 0 obj <> /Contents 53 0 R >> endobj 57 0 obj <> /Contents 58 0 R >> endobj 62 0 obj <> /Contents 63 0 R >> endobj 67 0 obj <> /Contents 68 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 82 0 obj <> /Contents 83 0 R >> endobj 87 0 obj <> /Contents 88 0 R >> endobj 92 0 obj <> /Contents 93 0 R >> endobj 97 0 obj <> /Contents 98 0 R >> endobj 102 0 obj <> /Contents 103 0 R >> endobj 107 0 obj <> /Contents 108 0 R >> endobj 114 0 obj <> /Contents 115 0 R >> endobj 119 0 obj <> /Contents 120 0 R >> endobj 124 0 obj <> /Contents 125 0 R >> endobj 129 0 obj <> /Contents 130 0 R >> endobj 134 0 obj <> /Contents 135 0 R >> endobj 139 0 obj <> /Contents 140 0 R >> endobj 144 0 obj <> /Contents 145 0 R >> endobj 149 0 obj <> /Contents 150 0 R >> endobj 154 0 obj <> /Contents 155 0 R >> endobj 159 0 obj <> /Contents 160 0 R >> endobj 164 0 obj <> /Contents 165 0 R >> endobj 169 0 obj <> /Contents 170 0 R >> endobj 174 0 obj <> /Contents 175 0 R >> endobj 179 0 obj <> /Contents 180 0 R >> endobj 184 0 obj <> /Contents 185 0 R >> endobj 189 0 obj <> /Contents 190 0 R >> endobj 196 0 obj <> /Contents 197 0 R >> endobj 201 0 obj <> /Contents 202 0 R >> endobj 206 0 obj <> /Contents 207 0 R >> endobj 211 0 obj <> /Contents 212 0 R >> endobj 216 0 obj <> /Contents 217 0 R >> endobj 221 0 obj <> /Contents 222 0 R >> endobj 226 0 obj <> /Contents 227 0 R >> endobj 231 0 obj <> /Contents 232 0 R >> endobj 236 0 obj <> /Contents 237 0 R >> endobj 241 0 obj <> /Contents 242 0 R >> endobj 246 0 obj <> /Contents 247 0 R >> endobj 251 0 obj <> /Contents 252 0 R >> endobj 256 0 obj <> /Contents 257 0 R >> endobj 261 0 obj <> /Contents 262 0 R >> endobj 266 0 obj <> /Contents 267 0 R >> endobj 271 0 obj <> /Contents 272 0 R >> endobj 276 0 obj <> /Contents 277 0 R >> endobj 281 0 obj <> /Contents 282 0 R >> endobj 286 0 obj <> /Contents 287 0 R >> endobj 291 0 obj <> /Contents 292 0 R >> endobj 296 0 obj <> /Contents 297 0 R >> endobj 301 0 obj <> /Contents 302 0 R >> endobj 306 0 obj <> /Contents 307 0 R >> endobj 311 0 obj <> /Contents 312 0 R >> endobj 316 0 obj <> /Contents 317 0 R >> endobj 321 0 obj <> /Contents 322 0 R >> endobj 326 0 obj <> /Contents 327 0 R >> endobj 331 0 obj <> /Contents 332 0 R >> endobj 336 0 obj <> /Contents 337 0 R >> endobj 341 0 obj <> /Contents 342 0 R >> endobj 346 0 obj <> /Contents 347 0 R >> endobj 351 0 obj <> /Contents 352 0 R >> endobj 356 0 obj <> /Contents 357 0 R >> endobj 361 0 obj <> /Contents 362 0 R >> endobj 366 0 obj <> /Contents 367 0 R >> endobj 371 0 obj <> /Contents 372 0 R >> endobj 376 0 obj <> /Contents 377 0 R >> endobj 381 0 obj <> /Contents 382 0 R >> endobj 386 0 obj <> /Contents 387 0 R >> endobj 391 0 obj <> /Contents 392 0 R >> endobj 396 0 obj <> /Contents 397 0 R >> endobj 401 0 obj <> /Contents 402 0 R >> endobj 406 0 obj <> /Contents 407 0 R >> endobj 411 0 obj <> /Contents 412 0 R >> endobj 416 0 obj <> /Contents 417 0 R >> endobj 421 0 obj <> /Contents 422 0 R >> endobj 426 0 obj <> /Contents 427 0 R >> endobj 431 0 obj <> /Contents 432 0 R >> endobj 436 0 obj <> /Contents 437 0 R >> endobj 441 0 obj <> /Contents 442 0 R >> endobj 446 0 obj <> /Contents 447 0 R >> endobj 451 0 obj <> /Contents 452 0 R >> endobj 456 0 obj <> /Contents 457 0 R >> endobj 461 0 obj <> /Contents 462 0 R >> endobj 466 0 obj <> /Contents 467 0 R >> endobj 471 0 obj <> /Contents 472 0 R >> endobj 476 0 obj <> /Contents 477 0 R >> endobj 481 0 obj <> /Contents 482 0 R >> endobj 486 0 obj <> /Contents 487 0 R >> endobj 491 0 obj <> /Contents 492 0 R >> endobj 496 0 obj <> /Contents 497 0 R >> endobj 501 0 obj <> /Contents 502 0 R >> endobj 506 0 obj <> /Contents 507 0 R >> endobj 511 0 obj <> /Contents 512 0 R >> endobj 516 0 obj <> /Contents 517 0 R >> endobj 521 0 obj <> /Contents 522 0 R >> endobj 526 0 obj <> /Contents 527 0 R >> endobj 531 0 obj <> /Contents 532 0 R >> endobj 536 0 obj <> /Contents 537 0 R >> endobj 541 0 obj <> /Contents 542 0 R >> endobj 546 0 obj <> /Contents 547 0 R >> endobj 553 0 obj <> /Contents 554 0 R >> endobj 558 0 obj <> /Contents 559 0 R >> endobj 563 0 obj <> /Contents 564 0 R >> endobj 568 0 obj <> /Contents 569 0 R >> endobj 573 0 obj <> /Contents 574 0 R >> endobj 578 0 obj <> /Contents 579 0 R >> endobj 583 0 obj <> /Contents 584 0 R >> endobj 588 0 obj <> /Contents 589 0 R >> endobj 593 0 obj <> /Contents 594 0 R >> endobj 598 0 obj <> /Contents 599 0 R >> endobj 603 0 obj <> /Contents 604 0 R >> endobj 608 0 obj <> /Contents 609 0 R >> endobj 613 0 obj <> /Contents 614 0 R >> endobj 618 0 obj <> /Contents 619 0 R >> endobj 623 0 obj <> /Contents 624 0 R >> endobj 628 0 obj <> /Contents 629 0 R >> endobj 633 0 obj <> /Contents 634 0 R >> endobj 638 0 obj <> /Contents 639 0 R >> endobj 643 0 obj <> /Contents 644 0 R >> endobj 648 0 obj <> /Contents 649 0 R >> endobj 653 0 obj <> /Contents 654 0 R >> endobj 658 0 obj <> /Contents 659 0 R >> endobj 663 0 obj <> /Contents 664 0 R >> endobj 668 0 obj <> /Contents 669 0 R >> endobj 673 0 obj <> /Contents 674 0 R >> endobj 678 0 obj <> /Contents 679 0 R >> endobj 683 0 obj <> /Contents 684 0 R >> endobj 688 0 obj <> /Contents 689 0 R >> endobj 693 0 obj <> /Contents 694 0 R >> endobj 698 0 obj <> /Contents 699 0 R >> endobj 703 0 obj <> /Contents 704 0 R >> endobj 708 0 obj <> /Contents 709 0 R >> endobj 713 0 obj <> /Contents 714 0 R >> endobj 718 0 obj <> /Contents 719 0 R >> endobj 723 0 obj <> /Contents 724 0 R >> endobj 728 0 obj <> /Contents 729 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 16 0 R 21 0 R 28 0 R 35 0 R 40 0 R 45 0 R 52 0 R 57 0 R 62 0 R 67 0 R 72 0 R 77 0 R 82 0 R 87 0 R 92 0 R 97 0 R 102 0 R 107 0 R 114 0 R 119 0 R 124 0 R 129 0 R 134 0 R 139 0 R 144 0 R 149 0 R 154 0 R 159 0 R 164 0 R 169 0 R 174 0 R 179 0 R 184 0 R 189 0 R 196 0 R 201 0 R 206 0 R 211 0 R 216 0 R 221 0 R 226 0 R 231 0 R 236 0 R 241 0 R 246 0 R 251 0 R 256 0 R 261 0 R 266 0 R 271 0 R 276 0 R 281 0 R 286 0 R 291 0 R 296 0 R 301 0 R 306 0 R 311 0 R 316 0 R 321 0 R 326 0 R 331 0 R 336 0 R 341 0 R 346 0 R 351 0 R 356 0 R 361 0 R 366 0 R 371 0 R 376 0 R 381 0 R 386 0 R 391 0 R 396 0 R 401 0 R 406 0 R 411 0 R 416 0 R 421 0 R 426 0 R 431 0 R 436 0 R 441 0 R 446 0 R 451 0 R 456 0 R 461 0 R 466 0 R 471 0 R 476 0 R 481 0 R 486 0 R 491 0 R 496 0 R 501 0 R 506 0 R 511 0 R 516 0 R 521 0 R 526 0 R 531 0 R 536 0 R 541 0 R 546 0 R 553 0 R 558 0 R 563 0 R 568 0 R 573 0 R 578 0 R 583 0 R 588 0 R 593 0 R 598 0 R 603 0 R 608 0 R 613 0 R 618 0 R 623 0 R 628 0 R 633 0 R 638 0 R 643 0 R 648 0 R 653 0 R 658 0 R 663 0 R 668 0 R 673 0 R 678 0 R 683 0 R 688 0 R 693 0 R 698 0 R 703 0 R 708 0 R 713 0 R 718 0 R 723 0 R 728 0 R ] /Count 142 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 14 0 obj <> endobj 15 0 obj <> endobj 19 0 obj <> endobj 20 0 obj <> endobj 26 0 obj <> endobj 27 0 obj <> endobj 33 0 obj <> endobj 34 0 obj <> endobj 38 0 obj <> endobj 39 0 obj <> endobj 43 0 obj <> endobj 44 0 obj <> endobj 50 0 obj <> endobj 51 0 obj <> endobj 55 0 obj <> endobj 56 0 obj <> endobj 60 0 obj <> endobj 61 0 obj <> endobj 65 0 obj <> endobj 66 0 obj <> endobj 70 0 obj <> endobj 71 0 obj <> endobj 75 0 obj <> endobj 76 0 obj <> endobj 80 0 obj <> endobj 81 0 obj <> endobj 85 0 obj <> endobj 86 0 obj <> endobj 90 0 obj <> endobj 91 0 obj <> endobj 95 0 obj <> endobj 96 0 obj <> endobj 100 0 obj <> endobj 101 0 obj <> endobj 105 0 obj <> endobj 106 0 obj <> endobj 112 0 obj <> endobj 113 0 obj <> endobj 117 0 obj <> endobj 118 0 obj <> endobj 122 0 obj <> endobj 123 0 obj <> endobj 127 0 obj <> endobj 128 0 obj <> endobj 132 0 obj <> endobj 133 0 obj <> endobj 137 0 obj <> endobj 138 0 obj <> endobj 142 0 obj <> endobj 143 0 obj <> endobj 147 0 obj <> endobj 148 0 obj <> endobj 152 0 obj <> endobj 153 0 obj <> endobj 157 0 obj <> endobj 158 0 obj <> endobj 162 0 obj <> endobj 163 0 obj <> endobj 167 0 obj <> endobj 168 0 obj <> endobj 172 0 obj <> endobj 173 0 obj <> endobj 177 0 obj <> endobj 178 0 obj <> endobj 182 0 obj <> endobj 183 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <> endobj 194 0 obj <> endobj 195 0 obj <> endobj 199 0 obj <> endobj 200 0 obj <> endobj 204 0 obj <> endobj 205 0 obj <> endobj 209 0 obj <> endobj 210 0 obj <> endobj 214 0 obj <> endobj 215 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 224 0 obj <> endobj 225 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <> endobj 234 0 obj <> endobj 235 0 obj <> endobj 239 0 obj <> endobj 240 0 obj <> endobj 244 0 obj <> endobj 245 0 obj <> endobj 249 0 obj <> endobj 250 0 obj <> endobj 254 0 obj <> endobj 255 0 obj <> endobj 259 0 obj <> endobj 260 0 obj <> endobj 264 0 obj <> endobj 265 0 obj <> endobj 269 0 obj <> endobj 270 0 obj <> endobj 274 0 obj <> endobj 275 0 obj <> endobj 279 0 obj <> endobj 280 0 obj <> endobj 284 0 obj <> endobj 285 0 obj <> endobj 289 0 obj <> endobj 290 0 obj <> endobj 294 0 obj <> endobj 295 0 obj <> endobj 299 0 obj <> endobj 300 0 obj <> endobj 304 0 obj <> endobj 305 0 obj <> endobj 309 0 obj <> endobj 310 0 obj <> endobj 314 0 obj <> endobj 315 0 obj <> endobj 319 0 obj <> endobj 320 0 obj <> endobj 324 0 obj <> endobj 325 0 obj <> endobj 329 0 obj <> endobj 330 0 obj <> endobj 334 0 obj <> endobj 335 0 obj <> endobj 339 0 obj <> endobj 340 0 obj <> endobj 344 0 obj <> endobj 345 0 obj <> endobj 349 0 obj <> endobj 350 0 obj <> endobj 354 0 obj <> endobj 355 0 obj <> endobj 359 0 obj <> endobj 360 0 obj <> endobj 364 0 obj <> endobj 365 0 obj <> endobj 369 0 obj <> endobj 370 0 obj <> endobj 374 0 obj <> endobj 375 0 obj <> endobj 379 0 obj <> endobj 380 0 obj <> endobj 384 0 obj <> endobj 385 0 obj <> endobj 389 0 obj <> endobj 390 0 obj <> endobj 394 0 obj <> endobj 395 0 obj <> endobj 399 0 obj <> endobj 400 0 obj <> endobj 404 0 obj <> endobj 405 0 obj <> endobj 409 0 obj <> endobj 410 0 obj <> endobj 414 0 obj <> endobj 415 0 obj <> endobj 419 0 obj <> endobj 420 0 obj <> endobj 424 0 obj <> endobj 425 0 obj <> endobj 429 0 obj <> endobj 430 0 obj <> endobj 434 0 obj <> endobj 435 0 obj <> endobj 439 0 obj <> endobj 440 0 obj <> endobj 444 0 obj <> endobj 445 0 obj <> endobj 449 0 obj <> endobj 450 0 obj <> endobj 454 0 obj <> endobj 455 0 obj <> endobj 459 0 obj <> endobj 460 0 obj <> endobj 464 0 obj <> endobj 465 0 obj <> endobj 469 0 obj <> endobj 470 0 obj <> endobj 474 0 obj <> endobj 475 0 obj <> endobj 479 0 obj <> endobj 480 0 obj <> endobj 484 0 obj <> endobj 485 0 obj <> endobj 489 0 obj <> endobj 490 0 obj <> endobj 494 0 obj <> endobj 495 0 obj <> endobj 499 0 obj <> endobj 500 0 obj <> endobj 504 0 obj <> endobj 505 0 obj <> endobj 509 0 obj <> endobj 510 0 obj <> endobj 514 0 obj <> endobj 515 0 obj <> endobj 519 0 obj <> endobj 520 0 obj <> endobj 524 0 obj <> endobj 525 0 obj <> endobj 529 0 obj <> endobj 530 0 obj <> endobj 534 0 obj <> endobj 535 0 obj <> endobj 539 0 obj <> endobj 540 0 obj <> endobj 544 0 obj <> endobj 545 0 obj <> endobj 551 0 obj <> endobj 552 0 obj <> endobj 556 0 obj <> endobj 557 0 obj <> endobj 561 0 obj <> endobj 562 0 obj <> endobj 566 0 obj <> endobj 567 0 obj <> endobj 571 0 obj <> endobj 572 0 obj <> endobj 576 0 obj <> endobj 577 0 obj <> endobj 581 0 obj <> endobj 582 0 obj <> endobj 586 0 obj <> endobj 587 0 obj <> endobj 591 0 obj <> endobj 592 0 obj <> endobj 596 0 obj <> endobj 597 0 obj <> endobj 601 0 obj <> endobj 602 0 obj <> endobj 606 0 obj <> endobj 607 0 obj <> endobj 611 0 obj <> endobj 612 0 obj <> endobj 616 0 obj <> endobj 617 0 obj <> endobj 621 0 obj <> endobj 622 0 obj <> endobj 626 0 obj <> endobj 627 0 obj <> endobj 631 0 obj <> endobj 632 0 obj <> endobj 636 0 obj <> endobj 637 0 obj <> endobj 641 0 obj <> endobj 642 0 obj <> endobj 646 0 obj <> endobj 647 0 obj <> endobj 651 0 obj <> endobj 652 0 obj <> endobj 656 0 obj <> endobj 657 0 obj <> endobj 661 0 obj <> endobj 662 0 obj <> endobj 666 0 obj <> endobj 667 0 obj <> endobj 671 0 obj <> endobj 672 0 obj <> endobj 676 0 obj <> endobj 677 0 obj <> endobj 681 0 obj <> endobj 682 0 obj <> endobj 686 0 obj <> endobj 687 0 obj <> endobj 691 0 obj <> endobj 692 0 obj <> endobj 696 0 obj <> endobj 697 0 obj <> endobj 701 0 obj <> endobj 702 0 obj <> endobj 706 0 obj <> endobj 707 0 obj <> endobj 711 0 obj <> endobj 712 0 obj <> endobj 716 0 obj <> endobj 717 0 obj <> endobj 721 0 obj <> endobj 722 0 obj <> endobj 726 0 obj <> endobj 727 0 obj <> endobj 731 0 obj <> endobj 732 0 obj <> endobj 48 0 obj <> endobj 742 0 obj <> endobj 31 0 obj <> endobj 24 0 obj <> endobj 743 0 obj <> endobj 12 0 obj <> endobj 744 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 745 0 obj <> endobj 549 0 obj <> endobj 192 0 obj <> endobj 746 0 obj <> endobj 110 0 obj <> endobj 747 0 obj <> endobj 49 0 obj <> endobj 733 0 obj <>stream xœZ@SWÛ¾¸¹*.âUP¿{q·jÕ*Z·¶ XnA‘½B $Œ@€ä„öNØK÷‰#¨­ÁÕúUk«XíT[ýNì¡ÿ÷Ÿ$@Ò¯þÞ{OÎyÏû>ïû<ïI8„m‚Ãáp—¹{x̘nüïÃHŽaTÃ?lRQŒaÿ[7;`oìmFMí`ˆO ‚[6NXTò²°ð~€Ÿ¿Àù½Ýï;Ϙ7ï£)Î3§OŸç¼$Ä—°Û;ÔÙÝ[àïâ-ÀÁÎÂvø bœß[à/„»L›& §z‡DN ãû-|г0@àï¼Þ7Ò—í»ÇyeX¨Àywˆ¯³Ùº©æ?ËÂB£¾|g÷°=¾üP‚ v. ݲ4lë²ðmË#VðWF~"ø4Ê5ÚMè½Jä³:f·{ìž5¾Ÿí]ë·Î}À†@ Á›B68{ÎG£çŽ™7ÖeÜüñ &| ¶ˉ©Ävb1XIL'>!fŸ3 WbáF|H¬"f«‰9„;ñ±†˜KÐÄ0b8áHô!œbaKŒ$ìˆQIüƒà A,Ñ—p&ú£‰þÄžø˜@,$‹ˆAÄbb01„ØA8; áI %¼O]\etS‚ΣãÖÛWm "Ã}ºT‡Ä¤$&§0ŠT ˆãÖíÔlÁ£ñF 7´ â¿p¤¾ë|º/$È TÁ&¿ïé¨é³ßÀIðýÇo:¯^ÜéRÄfĦ‹Õ ´ã¾_§éàÍndªqP@XJ_¹|þÚÝËK?œ¼ÂmÅÇþON3h‚íïc²&@AÎÏ?B4ó—ÑÛ=c‚XÞÏõŠ"߿หîÂ1ÙëÍ«zxûs¯áW Ô ÚD zL&%²K¹"µßh(sæsÑî˜D ƒD§€ PÎÀ×ä¾ìÜ&ö·Tøƒh!³ Õq{g¨‡ez›«HwÛQÌVtI£ÈÞ+èCÂáO 3œ ?œ '!'q»NÑéO\h׆qN¡¾ëÐ dcå§»¦ÀTb«= δyáX_&¼Þ§f=Žˆíø)ˆ‡ÿ0 ö¹y²¥RË¢ mV±žo‰õ6r%„ôúmóæ-qëxú¬Cÿõ½ ]s–Dé —)Ãõ'ô;pHþøYG‡X,7°æ­wZ¶¾i¸¼.‡s}€¸y?¨(gžw?û0h8ô‚ŠMd¯GïpåyLW_K~7XW)ø®|<œwòáú‡+?ÁŒ*²TX ¨ MI­&þèÜ-«bV{°¼¯ö›§B},H€Ú],W°ÈRM÷*ÆoÎ+=…÷hÁ:Ž"ßiû(3Þaû‹GöuI­";ÕâèÍdOp¸­ƒñº`ÝpÞKxæÐ‚La?+4ó“pˆªijüñ›¢ˆ F›ÛØ z®1÷"S¥É ÆKëD8Æóóü¦½Ž}&eyÏ[“¾ŽÛ4bïÞÀé;6äßç3)e©ù€2F„Ä~Cn‰ª¥€iõ;¯¨Ã‰3³é›Ó,ï%øÑÚ ,Ê”ìp–ÇÅYk0¬6B_ºÊX|MÎêoqâQ2ÙnÛ± P.‹ '¾þí~ó5"JÙôXu|M·É5Ù’ aüv{c›íÇ¡‘È­þ9Áþ—Ž6TjØ( 4{Úìž›ºß4cÐgâ`ð $ çZ|ˆæ>${‘6ïC3ñ+ü”FN¾éwçîƒce@먌Že”îë€ZÎU³VUŸóXýñ]qù¬¶šÛjÕÈùCÏ¿>íešê.)ßrõ× ýQ4Ÿ|wY5#ÀÈìöÁ?šhU”êYRmr¸”õ„I¶þBɘxg¸Ä-ûšXÉýûˆ\r²>òÃGòZ꨿¸ð½L©Z¸DmtœC‚a§Ñd-ž/ÄàúJÆDš„F9ÛJnEgí”djMÜÉø#1×ÒòýA"N°„¨´ä݈IRJr3 ±>±;LÕöà¯o´©e—LXôÒ®¦GÔ ¾#“°z F³ív[î¾fFƒ`ö;8¨ ² ëÑ…øYï»»“S ¡Úõj VÇŽ4tû{®u©I!ˆÆ¥KSÍðZ½`E2ÒJ°<ÉvàL¡­¶w¸S1–Ìäè¡'çJ ù6«=ϱdLK—t¯åÊ`ßCº8ƒp)FcÒ•õé ûuœcÿ ]†âöÊc’ƒ”dJ¹L›\>&;V¿;]I8½ÍL  t þ¼8~¨‡ŸB¢ª¬PHUÇ”ñÃcc"¼÷ïn}q:æg2½J÷ŽFvba9t](‹ÂdF'Ú±Ps–u|ºráHí! cUþåÒ*@UiKëhñghÔ,dÿÃxèÙý¿”vWð±zØ ãt´ÁjŒÙc;:ÞO*Å9šxj,P¨«ø@ ¨ æýjAÛ%åEwoæa‚XC„Š›¿ó:òÈŒËúf%«“ ’ @!(ÊÉ)ÊP Õç)UWùÎK¹MÚn nÀb!U*‹°¹U˜(ô-­Õ¨2@i·ž|nÖ“;-z²¦sÑ Ô-T¦X³ž4 "+Ô@Š©ËYå‹*¸=Õ㦠 zúÇÚH3ÖôaP¿ƒ>f’¼Öú@Ÿ’]#g²I>ôã´ ­­«§`írîϹ —v«ó§Ž×[7xXpú¼ FcŸ¯7ܦã÷I2Âõ‰a)±÷êçÂT$\Ý•Vè_¢¬N YƒºšÛ;b´5±†)»UÒ¨«p¨ŽsQ«°#À ´¶´@rÕ/hê?y"VÃ_N€4t<õ´Ú­˜¤4Q2µe£, ,‹Ïˆ¿£TWé¢;W.vÜÁñsÇQ½M›ÖâYýáe®CîÈ=:CGµáЮ®¨…GäƒrèY€¯?<A;¸™²ðJcÁCp4ËŠ= và•Öw°uþÒñãç.ݱi½—×fv†?¡8(hÔ³;·;dõ±u¬¶ *³P¥¯LÎTieA}¥¨qcÂ6eÀNVœï_¾P,_´1,‚'iã)ʧÆ®yIÿ—ƒšÿÇ1¹ÓßÚÝ9`qìª÷ÖkpiÃ阓n“ÏŽ¯Ý¾ÍsÝtv =‚èÏ[ÊuàõÝ¢‡¨ƒVüÿtq É;sk÷ÐV ¢€7p!åA¥!uâý€ºVõùÁ¦H€õzˆ’MRì 'Ï_9²J&¾^ •æ÷æÖƒÐ÷ÅJlßsØnA›{¾1VÙb‡ÚÑ+ÀŸ¶~ É{iPØÖEU„…EE……UDÕÕUTÔ1=µÁáÜ XrÃ÷†qòVXK×É¿‚©Í»Ö.Û–Y»›ñ®M=ª,S–*Ë‚ºÛ+ähê¯*ÔEM¹Ìáø:ÛO:¯û/d}‡g\Fñ^º”yø6ƒSNg[Oß‚ýŠ?V3QùrMO¿ähîñRbC’ŸæžX6‹Ìùô¤ë7‘¸ÇËTþ,(J£zy;ât'nrÅkƒm¯+f’½eëú€±À7Â?Ü7ëÀPŸ.IÇ””²©:Ai´ *6tÑ/àÚ_gxÏ ¿½Ó;f¨ÑC'=tìi%ßÑ |Ç™‰S—t³ÕéÃ’ÿhŠÍ%³?.™}ÚŒ0‡†ƒ ×®Ùª™j%†H4M±ƒ¯Í ºYh§µKºÍªó²ê½·= ¿¾‹ËÃ4óI©É5ý,Ó“½ýÇ==L0R÷ô´U5E?ή›7or;÷/þÐ`ÔÄïõ+‰=žöâÅãgpóŸ}Ø•)u‡áŒ¶º~hEÃŒ&iê®Ì 1ÛgêÆuÇ›—Õ‚fv!º·I´(y—QÙ5§–ÊZ&œ›ÿ6ò†[Wižo ¨Nµ ä¶ô&˜‡Îá|ìoü6žÁq ãiEƒÄ*ÈòrÔÎõ‹î.'OÌžŒ~,ü„Ëkí|e‡^qMØm{œ Xç&=Tâ’ð/Ø`p¢ýW²O×Ãd‹äBd`²,ˆEåÜ h*ËÌÊËaj›Ž”]ÆNþãብnó—öQتœ‹alVVN6ÐPõ‚’hIˆlÏÜG+ -òëShÃðþõrá/˜̧G-ípFÎ?¡´s³éD}0üž.‚£xøì% Y)øKb¨È2aMµ¦´¡ÕïÂ$4ÿ€<Þk”m—þ 9¿<‚öœÕ‰ú0<Ãf°9ÖÓ‡Â-äÚ ìiêj¥Z¡¦Pfü¥ÊàŒýXe¶¢W´ö«g¾|pþÓ%³]×/3™¥5´è8Çõ—pJÀAKÐêPJ ›KKóë™,Ø?€KuW4eéé ˆ2zˆAßò’c¿¢D¬ww5+7×´†ÑôaoÚéó>™2™Oꦀ,4-Ý“Qù€=é>ªˆÜL9é‡Ó/¨n¨.¨Îe^ç©®‚ÿ`ºîÔ9×{Ov§C?ÃbØE/u?Ñv®íô?ï_Ú¾y½»×RöŸÁô×µ'ZÁ%êáœû¨?²ÿhËú“[ÿÁð~[½jíⓞςC Ã³'?ßs»²DË,@Mô\×6½îòµïŸ]Z½f¥ë†¹F¹ÀSœqW‰þhóoâþ¿ Ãu:ãT@NЄ ¯Bä娒dD×jU¦*5Bi×ÿ>¼™yí°ãA¿¹ÆÝÇ[1Œƒ5t"üñ{“qúù©¢K2³²Ô¸7ªŠÑDð…±!Ae˱àsĵ܆åÈF?ÙL˜‹B>™ 1 ~>Εž8B¡q™´Ë¦/î>¾ÕvûX@XÂÖlÁ’P¡T€’)2Êcãú¹¦xiá˜8¡ŽÑpš Ûl }àGô—dA3hnöñ¬+Y'ضÜð%‹ 7«%2Oœ‚Aj¨2^‚8Ž{çÝ…d¼?ð÷oìd š`·Írã)Fƒ@*PR1E±ÚÆŒú‚t¦´ûí÷Ñ0œ.¿™fg"EìW8„wÀ!6ð¾Á–n © òåïmˆh:XÝØÈ +¶»‡_9W{Ew÷ôxÔŽ1ípùúªÎou¿Þ]u}8ïO-< ëéÏãŽy‚-`‹çŽU Ô(¦‘„ë©ö©œUgæå€Jª.²T(óKÝ9÷òBH%0{§±T—0¹p`ùÙï@h û¯¥xÿuîáîK=#-Ù’˜”â(¬*jµU-_yÜFýò˜“¬ |1ãËE}âV-K@¤pA0Õa»>oÓpœ>}¸=2+tØÏ¼wãÞ×^1“¿sÿ¼çk»l鸾"I’¯¿yz_PD("RØT/Qœì¾'eÚfÍɼj ­†“hÉ9åyC]®©©ØŸþ©,4ÆoëFˆlélqy`‘ bO–¬4rï&¿) <¯ÕžÎ/8uÎT˜6w<ìà4xØÜá º`Nͽ@ÊbY%Ý‹ÓkN/øM¡‹Zð“@œ´è2>?iÁJÂ8ÁEm4lŸˆ›H¯Ñ 郜þjo‹O`LDd¸FÐ¥éL&ÉEiËìd“RS0†bJ¥EUoôÐùk„Öãú•«6F&å'f£ï ¯£47M%”X/á»É,<Œ\þIH6…MP_’›¡Ê-2N6Oû6ÓÆã›iPœœS€?Ú ´/BŽø¾$?;S9)šˆP´ 9¢\ÔÿäŒæ­Ìù¥÷6Tª&K“Ãv³ü]çÐÞyòÅŒ¯ß˜ÿ0”ÓàTÉ¥çgëKZêÁ9ª…ÿw¯£·¹nª’hµ•¥u)y)j¦ºîTö!@½:/JdÑøù`&ØMíq‡òÔûqrå¡¥ô»ˆª{°} ¯ÐößùÔÿ̦;‹Û"Å— “$ùÉYi,œ‹8Åh6nó&îE,9]‚ëPIjau=Ü… }®ù ð¬6à_œãmß·Á²ã 1tZºIòÍw›ìPÿ—»­?…Kn(FËÑ(4 GŸ¢Oà@äŸ>ºT_cÓ@b"ë䛀['b$àøþËW¿ÕH\SÉ®B·èÞWï?:yñè‰ãë\\<×ï2:ò©6Ú° =¿]»¥q¸ipDÂχóþ ž€jZ°WÓá]+N9€Ò–—Æç*T,¿ô“}E¸âX]˜S6ÔïfÐàeé5ªÏA=ˆûA ,TåšÁ âš4W’“0.F"Ê—b˜pÖ"bm|rœRAèa¾­ˆPº‚P'Ü·ìË­W~®¨1/ÝÛ±¸uàcÜ|övmÑq®f÷ç*n°:q?]­Z†)oÇyä~܆;pç«h8ÆÂth K€fLYñ ‹Æp{Ù ŽAcÉxàߌ˜‰å­@ùl˜b‡¾F§ä%•FJ(‰IÊL̳ðÑŸŸd%æÄV'MqiYNj^šºûÐ%–¢!ZcAŸ`$"lΠ%î;Äñ©‰i1)X wÓ« °nÏ!¯Ý‚ ßzþ>u¶*=ÛÊR ¹‹oGw÷N®V½Þ”?Ç¢)V×®æ#rc¨ê0§ï<¼u˾oYX2i[;0¤ /éøl9H3 Y èê(IJJ±Tr^PU¦Z•]À¼i³¦H–ÔÀ©*¯)»T–ŸÍ𠻇¬ÛÿÎUxÀ”C¦üvX¦ÛÔ]¨»K¿@\d¿bûÊÀj©Æ¸Ÿ"y^ZÓØxËøþãÍ3~ž!ÿð(6(‚¯ðS¬O•Jñ~3&"s’üõì§ëÖlX=}÷ÂüS¸›ÌVãn²çíÚ™?¯Ãrø·Ïžciní¸âÚ`´ÉíÝn8<†¿ ç}kp5|I—HJÄ òy2!–âî=)7® ®P¨ á L,ˆJB£ps).—䫳ÔÙLC]MIÈ9²ÂøÂ8Mô~P êJ*K5Åõ Œ˜oX– å“(&›«ë§ïÏô³ ³ï«³·×Û ˆÿ½©ü‹ endstream endobj 32 0 obj <> endobj 734 0 obj <>stream xœµWiXS×Ö>1æxTÄ1–tH°­cµàTg­bPq¨A@)a™ÏÉ: aà ŠV­ZëUëÐZ[§jkkÛÛªÕV»Oܹ÷ùvµ½Ïíׯýñ=yx˜Î>ë]k½k½ïQÝ»Q"‘¨GÀ’•‹Çú»&<#ží&<'l}ŒœZ x‰Á«{Ó³ƒG@ôGš¾h}?J,Å«ôñ éIÑ[¢”¾#ÂGúŽ2eÒhßqþþS|gÇE$E‡‡mó]¦ŒŠˆ S’_b}WƇGG(Ó}GLR*¦úù¥¦¦¾—ür|Ò–™#Gû¦F+£|WD$G$¥Dlö¿Mé»4,.Â׃îeÏ·€ø¸•2"ÉwIü戤mE ›½nÎú€à¹¯Í›¿`aàâ%Kƒ–­X¹jõšµ&¾2iò”©c^öó;nºvÉÀÊ•–£y(ÒõÀÙyjàÀ,ƒœ¤´s×›[­—HÚ;áœy¿;mK_l)b2è ÈÌÏlb¼ëHÞ·£ý‘pýžrÎ’cË`”›ev¶œè9­Y7Þe÷1%³ê8c ©`Œõž¡Ñp$ztïëé'&*îW}÷|Í|>ëì-ǸCÚŽ,¶]|ÁQ!/úNùÌ-Sæúãž <%Oƒ+X¬;‡P½-¡TŒ ÷›ã‡»+žÔy9ãÅε é¡Ó'òö»ëË…› –[y’1VÒZž™–¥ÍÑk8Ûñ`tÀP 6àeG ANÚÅΆˆ…%|¤¥óÈ(6툖¡Ñø»,?.3ÃOÆ©YUšQeŒ…wb{Wö“ÏǰÇ]o›#žP2Õ"SYÔ¹PåMhšÍ]»H•Ã9†À¤î‰vç"iÁj0±ËÉ93kä¸ÕK|t:0›|x}~ÈÉÕAÀàM8 ¯Åé8ɰšøY‡ãíw·¯—Üž)ÒóFVZN®Û>{nPкk‹½N¢…e€¦}ƒú)Ž\øêÔ÷À ¯S˜Âb™<¯à5G¸V¹VÆ[@°[ø·CtJx(v¾à|FZ\êþSl€T¹kŒU’zÚ†}|=MÞäG»Ô®Ç:ÉjYŽ jäB(ýª–$ѱø…ȱx1Á=‰LF®§3ΉߋÑȿÊF+ SÑ64~8ê‹ýxÉ|©‡ÌúΫ°_† /˜1D±iUÀšaÀŒ¢㈷s:áéjÙ-jqN;Q±4‰^ƒg¯Æc ¶Á¿{ø-T%¹EФ^“Êf²Šzú ª$™d½Ÿ2˜ñt2Úšmy‡ /ûÓH¾+ ‹²!ݬ&O"•Äu†&¼²ÓçKô),pœV1ε˸•SO™ŠîšIᩆ/uعA£ftEz“¾Ð¤^›Îf°éOgú§&ú3‰nG¿fhô\}èlHû-î¡?‹ë¦ºõ aåø öyx)ÙJOWØm$írR£z•e9„¡]”\†B¤y­6Ûðl»7¸Mæ- |<¤ÀH±Æ8è‹zǦs…)AÊj”Ë_ f îsÍÏôê—¨·âìß¾uƒ…yïE2ÁÊ|N>äwÑíªó餾٬Α/žÛ|Èdx3Þˆ×ãT<Iq?4íæµÝÇö(ŠUÍáÅäX­åŒGÎ:Ðn©à>±3Tx$µ5ç_ÆNwÎî«dv7Clq¯Ú®]^C¿_¤O餚"§KðqÒR­Ía)¹²¿xŽpô?Kû)Ù“ûá¢gä»ä!…^œg·òy|â ª ct(®ü{ç¼Ñ¿<3Ó(L£kÂC’ ¥ä&0un [Øæf˜Q¿ZKXüÐZcŒA3 dÉî€{:9°®@kgÀ°QÒú‚š|K¡; ³Ò°Åy@,Ä“¥(ͺxú$_Ë»å+%´V{Bâ$ü~ó¶ô,µÎ pQøø téÿ¹”Mè5$C݈ڕ۴yYdåD‡@šÜ[iÙU ëàá ×n–å96@"ŸtDæí”tå$|-vJ:‡?S1¸7ž Ìôß ÿm¡… /ýdÍžúúÁ&‚~Ö_BÿëlWÒÞGxî}¼LŒ~v—kÍ|Ù4Óè?xÉ$kJÖ… }"Ù­üÛD²ípŽstZ‡$y¼ãiÐm¡Y“ñÿ—Ȫ¶hŠAVy…¶ôÐéíÃÓ£\Ÿü¾š{¬uöûØû¿Tók¡É32ž~áét2˜ 'Ÿwöy¢¥îñBw~RÝ3¯$yLý5ô!¨0³þ®vS’.t(ü…n e6½Mc5ÊÐ ×Íü,ž+Y ð6kåw ŸÜ†‚C?Ñë(s0ñJɰÔëÖkC¬¤¶Öc·+æºfJYU ÎÉõ¢_î ‰wÅÎ:a¤ÍÇ}PìÃñ*ò¥Ä¯¢^dL@!h Fér—Ü5T:|ê×Èow>Ó(Ň¾l= ÌûAxÎÔdüÔ2?Eà¨i›æãQŽ} èq8~£ô‘M£ÑÓhÐ÷¨Û糯ágøç?jêßæõ-aϯŠö%}íLÂŒ,6Z³Y‘2yA”?©ø³D1”*;óŽ'pŒ?À}± FßIïÚ½ß3·Gvàgåø‚;ÜŸ ù/"ù= "2ÔƒFðÓÁ˜³Xaˆàt°™xykÇ­ú¥6S¾NcÖ«YyöÚèèh`BÙ7?«ãk¡NALf]RkZ}Tur3¢TŠEDÂväÖðEÕ¹²BK31ßÌ¥_‹±ÏÔ•¸Â[8N<£):P~‡Xø¢ËÌ\ŽV²"¥ù}6îãû<î­²„í U8" ×S®¥øœOÌ]Ìôþ£‡M8ŠèÒÜJ(‘çžc6f°òhÂi‰¥ee«± Ÿç‹ ä‡NÛ•7üBô©¨êUÍ‹8¤ˆÛ·µ hGD‘Oª-¦Po‰)‹Ý ǘË—o!ñÛ³†d˜K`»\º«·XåĹCÀ{EHìô ¹Dt<)Z¡’¨\Ï=ød6‘(s•[™½¢Ó1@~EûÑØµg®ál,q†:ç©ñ1ne³‡AzTo9õ û?àMÖ½w#èW¶Øyȵ»-.©ÛSD¨g})v —¥O&&‚Û`Ž%Zâþkb–ã»Éäf!žöÈÂýªO ”Y+#¿þï½Ä%aÓ!rdxнɈAƒz!iÜ ¬Æ9„äÜ(v†ïmoÛÝpžxïXaIîòÞÇË34§ËTà®_Ü¥ÌVÈ•5Ÿ…zõžK¬‡5¥çć¤r…›dHêú%7ÕÊîY9Xr ‰x\Òwàã4ñcp]ZRWsà ßuc‰`× ‹-é¼çÎeâIdeæ“z’ª–Õµ8Íî3SÈàŠÁJüÿîs°SÞ¥QìkH4läC=w€ÓPÌl—åêJ€–¼ÙhÈÁa®ñäxÙd°ýùñ P ù!²\?Y2-ºR‘+G‘­Y›Ï5XÓxÓ?7Î’™Ú!„U‹N «Ä‚Òé+µ’(V†°Ýc6gåÈ]^® Ú62e¨’6)Õ39½>e»a0iî¡ßoý™Îv8NèôÛM.^ªÎ³ç–ß¶”(~t78­zJ—¸zJ0G“ȪFÔí.ZlGOÝ(®}ú¥Ü£Tá¬t¯z'Wí¾D|u»¬PÏs&­b]êýfRç°¼jµ#Ó§NÇe­ÇG}:‡ÑÄé.Îç-ùòÖöc;OsØþZª÷ˆ T$¾¹V@Ð6®ÐlæÍòÖšjµ}ërÌwvþ·h’Æ ¿t}ĺô­‘ŠN”Âóö›ßî¯ݼ‚¬á2ô…´øý·ÿñqcëÑÃï:`*ßÂò€Ù–¬ŒK®Ê´ÛŽÀ…WÖ®ÄCñ<{©B²3GkÞyWqþ\ŧpšùäõŸ±×¼ k6)åçðUixp÷Vø©¹CQÞÚöÑ%²ÌÊmRf㾉A CNä«ÓÁÝ-UpárIµ=-„ˆ…ÏÈzÈ/Èˇjëi<€/­R$Ñóñ&²š¾)äK,µÖ}ÐDJJo\?{jä†å³·.U…†ŒÎ&½4¥ñ­¼6{®¼âî.pý»Îξõ¢ G[¡†ƒbdB_K#3ðE€2þ_,¿CVsõº¾~ob•\“§¬Ðæï«Bâð€¹þê‘IX<ÒxDyÈ›qrä»C:ñ\T}R%´ÉÎ^={å«6y'‚=ßÞ¬^¬'Kð&ʽ,&¡¥š ¬qo,ˆ ]LnÌayi+願úÕ-»”EÙ› Ëçt¤øâæÉoÞSÜ@}óÐ(8 !K¯Çýð@Üû/mÇ xáÈÑà rüÜliPÂÁs-åh@ýÛŠ’Ú¶³ŸónÓë‹¶›Æª–)”ËBçšàŠ$úç/bT(H¥öíu±1ñqqªòdGKcS“|¾"mN*K‰Nˆ‹SV(›v9v˽ї(蔨5ŠQ⤸’Ö,—ñé|_çËÞ8óÇ[k/­U Å çiA©g5…ƒÞœ®‘» ÿž£Ïv^¦.Ô—ØŠ mu³;}좫—лÅB°Nz+ ľøÙ Ü'?;XÞj,njªÛ»3½"Þ`³IÞrá½½§ù´eåü91Sñ ì¥À1xƒFc̆,™Ðó›>Cbôb-êuÿ,á¡ÿÏh1hÑmi54BݶJU~#£f”œOÔ·´Â¦6³.*}ƒfÁ+Ÿ¯¹ƒäˆB’‡×^˜P%GÞ{ß~'˜s‹N ÇýgO\–V’ÜÒVÕR ²åGN]Í-æ`kòÊdÍ‚ð5ŠˆuQ\(›FR4p3k£É‡*¹·Ê.T mÅyvo*éáèuµ·¼W÷IÕ^=í…^^õ?2¦å¡ endstream endobj 25 0 obj <> endobj 735 0 obj <>stream xœ¥X T×¶­¶¥«TD¥­ ÆTáâ<@Œ&N(’8‹b«ŒæA@@è>ÝNÌŠ ´ÌPℳ&¾hüFWò’Íl¢á%žÂËûÿ߆Lo½÷ÖÿýU ºYܪ{Ï9{ï³O)˜þý…BÁ.^éâ1cºù«½üªBÕO~M $ëå›Ý©`©Ëþ £F8Zã³ah‚›‡2J…",fßâ°ðøÈ €Àh» ¾Žv3æÌ™=Ùnæôésì…øGùz‡Ú­ôŽôñަ¼k·.Ì7È?:ÞnÂ[ÑÑás§MÛµk×T﨩a‘ó'Ûí Š´s÷òŒõ÷³[m·Ê;Äß®ïtSû>‡…„ÇDûGÚ­ óó efÆ¢P—°ÅáK\#—F¹EǼëçïë·ÊõŽ5îAëÖox7ÄÉùõÙo̱œ2múŒ™³f ³šˬaÆ1k™ñŒ=³Žq`Ö3˜ ÌFf"³‰qa63‹Of ãÊLc–2Ó7fó6ó3‹YÆ81ÎÌëÌJfÃ3¯06ÌÆ–É„0VÌPfcͨ™áÌLšY¦?“ÈìieaµyÈ !Û‡|>”Ú1lȰzkWë:õLõ¹ák‡ï^Ì÷çWñ_Ù!gZuwƒ„ö’¼¬XÑÔ}\)‡v;ñ)•{  #m_<1ôü8B›˜™¶¸XªÞpÆX p Ngžµ+±:'(4då âYl%ªkÄÞb2]˜õ´@#<†ºÞ…Yò­Ì£ŠT[8•U·5Ý÷yg€ÉUôòB•º~‘yrc©†=a¸f¬§û\ÕЛo_Šþ,*uܬ-‰] ²¹¤€ýyCƒÃ¤î‚ú2,Y˜f¡aÕm7rÁO´ê¾J·l3áÉÐ/⢃ZÆjyGpûüè[[çoY9QDU̱÷®Áîk§‰³Ð³TƒLÏ•úgÂhd?Îýìñß;ß&ƒòDgr‹'+° 7ªŠA‚Z¯SÞ°R¸=@†“q‚•ü¡¶QV›58sq¸RnÀPGN{Nf“7¦'¶dèc|ßúâ9Ȳ‚'j@æ‹68w¤V¥gê¶VYÉ!ôÑ…8v}'Mó Z™±¿¿äÑ‚%sØOìeB¡ÍØõp L½DrÂŬúÁ ´z&èõñ»!”ó©ÙUUUSÒxaCÕ&AÝæ ¾›£WÐè.e–þÀ4 _£1Œè~‹ïùé·ãP¢>‡VèT@kïäU,;Ë~Ÿ÷{Pi4¨ÍXŠvæ Êæ"hPVòf­I~µÆº¾Ùû.î¡¿l(åPâwä.;wã8v¿>t}¶`H4¤—WÙeâǬœ:ˆó" s| !4ó6¾ÅáÅ bc`½öA§~bÒÞO^3rá4ˆq¯e^”IÀE6Z$ 6RæáP‰`€ÒCYÆöàóP \5N´oÙUxBT?ð« ΙWÈY½•"” Ÿ$”¬Í<™ˆc<;lԉݣ/ðÕá×"r+‚ÂC"nýXb3ÀÖR8lÈ¢éÐà8{V-A„úEG$kƒÁœ«½Ën±¸¸Ç² ² Áöägå—Ðs^ÒšB$\}§˜¬kpÀ|†NætÄÊðïÂÖ¿ gTÅP^– Éâ*½·Œ£5{²ä=âèN¬2fm¯‹;^]SÒ|2îH¦Q8‘Sc(î~÷1ˆÂbI&ÉM%ãGN¡ñêØAj*mæp?™4-9Ò÷®œYt6‹v.JÈ.IQ*_Sâ¨çq¾RX”“û)ØRàé6éÓiÜ›a}qA®`_†t³§ŒpDÖ¢QREèWè‚!˜Æ½³wÙ]§“Ć8$ÄÀ°¥’a.;džÜâST`?òŠ…ŸFUi¸n<5Ц;Õ»jIpBJä×L¸¶ó1OÄòxÛÿc?±ç©Äv\²Pw¤èØðäUtìêï)ß’ñÌ.°94j—C:yÜϯ;SÕIÞ È`W ¬ðC}¶¦ƒ+ø]Ü{ˆV©‹hLòšdûÀ[”Õ†(]È?‚ÁØ{ô{õz‘°”Fj,û7`XÝ3:zKÌ–`·%`›:CZVÞþ²"¨ãNE•……ÆùyH>×\¹qù8-ÌÚž‡4*êi{vÁaJì‘'ññ»u±Êý€G„ËYKÜÑm9bûídœŠ¯ŸD.·( öÆëuÉéBÄŠ-q´)ˆ€í—_A¾îHff¡Ø—WIVöæÕ¼I¶ƒ‰òë-¼'‹Ë§¤üóŸsL6±êŽ†Í›rv¾JìÇÌ"£Éˆ¯'ãšßëp¦¼º‚ÛýI›ﳞš3b8øÎ¸XÙ V5KùÕpƒKC©þø¬äŒ J¼Øí̧è ±ô¦xs¸¦‚½>,3*SGsÈEš›ÂeÚd›áü¯Œdã!Áo ÍÒSÁåäbVNïù4AlC^™(ßg¡Ô`8‘Uže„ÀUH*ÿLwª¤Þ°éW9¨`ÂýQ]U¦A1\#Urªv+NáÜ>k”öRö¡Î¨4ŽWkïm>+î0m<º”žÓÉiFF>›ˆÎ8³å—#Gã =A—¾[+Ænq^FWŒÖ£í9ñTcƒ¡¹äTeccAà0C í…KiêV5õÚ¤E8EÙ݈_óø.O=`$‰'"™@v_´#cq& €ãÑ[èéO®ókÀå„ÏG;o¤Ý…Gp+ëóÖ¿4]¿]q•6äÂß©_¾>¸kÆLï¥Û\\c6Pç€ëå9†›”áÌ¢Äò~¡æ>éZªQýsKïBV"ƒŸ³Øï£¼ŠìlÐå ‰)iqÇyÕÅUž¬)ijh›çHobA=ßqúüMØÑ'ÀXCÂf¤dsUQrÒ]ûMøœÌ{œ{=k_Ÿÿò*Âõ}"̰4ã<‰øª '‚ÅK`>™$R·J¶špò÷wMÝd]ó­+*q *á±ë#õ‹<€îü,¸ÝÖ·?†··mƒ·g‰Äj/ßuNWA™>®óá)òTâañäáãAƒ.]— Z.òH|eå‘cåe u[5™Û…øï’E´xãÖÏsõ)ö©¡¦¯› ÔîŒ ‰û=ƒ“3]baçѹ5èúðê“i7ß®ÖX “ ‚öštÃöÜ”z8 ùûåàn TUUÕh+ü6Wˆ¥g{ûµ›P$öŽ}TüÖ•´mñ´"ÿŸqÃc­o´€ßý™¹VÝ])¦H «MXÝ;lŒÂTœh‡S¾:k£Þ&ü;Õ8Egã¼Uëà 2GÄI±9º{6ÿwgU,ÑZHª<´ÈÿÇ÷ ç!™¢Q]Ì¢|¸J/úq±¯$S䇱8òßÌ'*³C~ÉÑ,<ëã¨,^PvÇÈ/øÿ«Hf©2)<‰‚,Ö¡Í%AvBFbý©Óò¢—#ø÷9-¦g2Kl‘! ôE÷Ï© zK+?¡hçQbt÷2þÏü,-i ç͢Ю«ý}œrÿ‡ÁÜ»ïÇFÝñ? ç_tܨ-Ý5ÿ߱層€íòh7}Óæ­®o¦eùƒ¸o ^ÁÑyò÷a¾£a²¶ Iv-Và=Ú²åµ8*M”税ë²ÃbõúÄ=ù©ç 6Ñìõ×°õY_õ¾’øâW*zÞ´ Li¹N©:Îô%µ¾Œ#߸@çÆ1Tòä"ÜÊ#ûÖ7dBèÆÌ`€#ØéuµTëì¿F‹Š\ÝÁ=™zÈHÝc6j½`l<‘—J»e&pI²[$m´…&—÷ÈÚ/æSŠ>YoŠê—.à@,£Vd_öLƪrhâ.xŠJÜ”ºêõ‡¯ãPAý~ø­ÄÞb—é ­l°>C›Ô*f‡£lÔ=¸¿ã±€ª’–ÜCåÒEÓuª‰µ™eÑéñá•…54”WÖßð¾9šŒ"sœI¶ ~ oå½Ù´TZðQÔŠøý_q$ÚÙß#ƒEuO ¬ïÜÏä&¿ ÂÒï®{p”Ãa¥Îï`¡ƒ=,²7¿ÚH)‘sp˜â–ôWsÚäoøüƒ`¤N‹x©¢8d'íݯÏÓåsU É¥lÊÿ¨°p¿ñ`Î'p„n;Oµ~Ù$Ò1yÈ[×KsXÊ~_hgáLÖ™\)ïvÉÕº&®7xù÷£ ÷ñÈý Ìç9Šßvj¹;_æ6~vÖÇÍ3"h{¨ÐÉß1U·Âî§émDED×·&m?ºâávAýdöŽíî‹F’ÁÈx NŸ<Æ~ÈÌ–~qµlãÞýbÁN:˜q+"ÆÏúÞ uIšË·P}Ìd~‘€ËÑf¬Y¿ÏÊËs P$ùW4—'±d‰–Zf=èlÕŸ‡TŸý¥þ몒ôä2!Až¾œ_U„étUEÓùí·H?2”Œó#‡_=Ì??»¨S£ËSE!^Qâ]t្+Y³›È*y¹®XqKvWÊÆî5|vä€+Þ}0)6=)I+ô ùÏ©é{@ zÛ]‡SŠJ² åô&Û$eR´QŸg~iV‰òOõ˜F´D«'©Ž d7jqŸž $H|¬+M¾—zþtT}ïÀù‚'wòËá44ÅÛ~dŒ†9ÖÓ÷mJšº")¸^‘µR+•‘=8H‰/º•|)äG¤è`_ª0ß}P›¼KS¬: †«Ç¸ž""jØÖ¬_ ƒ^¿üöÎÄÎ'P4\ÆÑõ’â2ŽÃ¥((©pDòUæ®ÔåIûR´ a75;*©á|KÛ)T}vK‚ï8dÇþ5÷ƒ§¬œ±æLbyMcéÙóÞ‡÷ UåõMÀ=jw[¸ÔßÍu‰H¶ïä= ƒ]¶ñò"¶ŽÔü¡EÇøZ½‘S(ªE* ¯ÑÏ)6jê~ÆŸùJî]†G܃7è>ƒæ-Ó«:¼¾­¢æô• 3 B݉ÖÕÀ}šµ|g²žØŒÕŠ>:>]¿W¯ÛKm›º'%>Ž ­*T€£‡ÆØ´ÿäñT^EU«¶àêíÞá3ž®¦tr»÷ì+n ¡h»ç¬RÊkòp[IþAÙšËJQ5HØv±å€Æ\KKT°l°´b˜ÿÙ•‚ endstream endobj 13 0 obj <> endobj 736 0 obj <>stream xœµzxTå¶öCfo‚dÜ’î¡IïEŠ)Ò‘:!$¤BÒIO&e2eÍLz/“!“6 I „&$ U#" ¢ í(Š¢¸vür¼÷›ôÞ빞ÿ<÷ò<3³Ë·Öz×û¾ëÛcÃtïÆØØØHç¯X3a¼õCÅ~6bÿnâwbøUÙšh =%гûÞþã«íÅÀ>ØÔ׿ÂHllv…$ÎŒ Þáí:`¸ûˆ¦OŸ:zÀÄñ㧘ëï¼ÃÝm×€n¡>žþn¡ôß§÷ž¡‘†Ïô œ1n\xxøX7ÿ±ÁÞ³GŒ¾#ÔgÀÏÏàÝžì 𞛿ç€öÅmàê<`E€‡gð.†a¶Îݵq^À¦ù›½¼0dQèâ°%»—†»-‹Ø¾<Ò}E”Ç{ž+½Vy¯öY³ÃiçZßu~ëý7Lž9eÐ[SN›>xöŒ!o¿9tÖ0çásF¼3r˨ž£{m=vœëø 'Ù½Ì0ƒ˜•Ìtf0³Š™Á aV3o3o2k˜¡Œ3ŒYË gÖ1#˜õÌHf3ŠÙÈÌcF3›˜ùÌf3³€ËlaÞeÆ1 ™ñÌ"f³˜™È,a&1K™ÉÌ2f ³œy‹YÁLeÞc¦1<ãʼƄ3}¦ãȼÎtg¢™~Œ-ÓŸ‘2,#0³ƒy‰Àô`2/33™žŒ?Ó‹ÙÅÌf옦7ó 3—éÃØ32æU›—mz0.´´ô":›×mwóéö‘d³ä³î;ºŸ²e[',Íf¥l·+~iÞKe/ýÒÿǥ—5=‡÷¼ÓËh7Â.±·coÅ+ý^ íÓ­¾h¿Ì¾I6èÕ^¯žå—¿Öã5¾oôUôýÙ!ÇQæ¸ÊñüëéýVö«î÷¬Ù£ß8& |…çrí€Mnì=ðò qƒÄÁç‡ô²aÈÝ7g¾yd¨lèÃaªaåÃ~^0üÞň’#Îx8R>ÒoäãQ“FU^2fÑØ^¢Ú®5,¸É".1ÚԴΕˆƒZ—ó)yšŒhˆµ2%–¸·}ã¹Ñ=f–óc÷èêëÁ-šíñžƒ-ì¦`s¹A—­ÓË`_[é 2F§Ò+Aåèï‚[oøöÁA8¢mÒXO‰dWBl†¢–#&1›G[rÓ–„Ií݈¶Ma&{ìv=/÷•Ænø„'¥¬‹Ó ÕéšõPNï½·ãÞ‹pXŽËÙŸ®œºx!gÝÄþÓc7@0h«9tbá.Xüêc‹vWÃ_þé;äQ6ò{Ò].{2 ܶ…‡qRÀc[Õ|¬ª¸«ç'[ÒëÝ©sÝ=å±¥ #g'"ì³Ø\6‹+ÌñPk>#‡~•Á*!\h[+U0[³4m«oã4z³ Ò6Ç6’¬-$9F¥A© ºI‹Ðh,M"òˆ1dpdšÔ®5µ³ìÂ]QöTR×:‡÷+c»°Ú…ÔnRœ‰ÇU¸†ôà dŽœ¼ú|;XÅ}-ðTú!\k^ppUÖ˜D±Ò{sxàšÕC)¼Ä²ÎœŽ4‡í÷ÞÁBÊP·ÅWÎódÑÿžCñtë9ÞVö¤2nû…·ûnÐHòéód(r´ŸÀƒ¦*΀~<È‚od@XH\¬o 3póÞ»,¾üÉk·š&¯§œ4“vñ9 ÖîµÁþ÷q³G™ f ö¿ÉwÅyMÚ„94EÁdlè<òM‘cgC°Or|ß’›±8X:Eá7R˜€ÉÒŽÖç¥8*Ö9g–`˜mÛ¹®~·ûuÑòóKÏïö•ÝÀ·ñ+»±DnÅQ;[ÊÿNÒûuGõ•ÐG¡±½'v³s59õrKéàþgzÐêµ6<‚¸€ÒS±9·¦Æ¯ÊUݘÞ‹c]i# aµà‘Ž0ךq0…Ìç­3ù¶#/h¨ôEÖnÒ<;›p';òê䨽Ë~›ÝðÔ„£„)˜ÞpO)޳S!hÀv¢ 0‰o•Ø×šƒßÇHsèû}e÷Ñ×ó&ÕÑ0ŸÛèã>kª÷é¯"už65¸8HŽ”6 ’sÒtº’A¯}qÉ!·ÃÚRŠ]öÈß>=á_Ÿ+ßYã‘é–IõÅ)gqÞ™×ëÊÜÅniüô‚.1‹R—i%òÚ:Eñq‚Z•¨R{Vn‡Z=;ÏÅN>…arÙýš Jå§±4?æ0K¢ƒ-â›íüòÖ}Ÿº¾²ñÁ>/¬Ñ=¸,È,ã¸uíø ag·¶[HÁ_E©Va k¢ òµDˆý>ç'°8$ÇÖ¾›”qŒ¶"K†½h²¼eѼ©ª£-~ÕùÍMPO”“‘ì,£YÄ)8TYõ!g‡ÿèä·þ÷%fßó¹Pnl&ËfvFVÎ~nèŒL­˜)Y×ü9]ñ~ø¼sÍAìLuûšË¥âë›1V"NÆ»|Öž¢ƒ—¬%T³K !°UÕ¡” ÚœPˆ€DJ¥x“d:îX£Ì£ÀÕ;–ï‡b .­“&Á]çß®•ìHUæùá‚é±ú”<ȃԬÔlŠŠì0Óì.î¶ØÀî8â®?Àáü¸MNë•‹àŒ·Ð’[]^` Û»mî••÷¼úÉõ¹.“Þn/'®bäÃzÇmO­3UçIàÙx=ûÄùPzôê«ØêbÿïóÅÇ-yuÖ°ÂhXa° \ôaÕkM‘ô½4)qãI–Ãp¬Qåj­ b?é=vi7jBÀvuEÕ…šì¸4eŽFÄ’â0)¹ta©]gtäAëuÞg‡\u®/Ú“_Òb IÖ<èÓÓòÀz‡ICªÂú‘c:r£V˜¢,èk*0áÑ“}Ó-pêå«Ô8øŸÀ»Ÿñ©înG+=Ÿ[~*؉]¬TìTNЙ¥–o¿wƒÇþM…[€›¾Ðy‰¿1ª¼²ØXž›R»U'¯¨;–C}бÓå^¬ìà‰êwÕËýßÙ¼¶q3ž_èM.Á‘Æ’£\2Nㇱ£çïpÙ¼½îøMwpz:mÅâßA(§ò¸çffžh¾muÃAj_ oX;ºÜpz($BtBBR2¹DZðÊÿACÎg‘£ÁRšž˜ñŽþÔ:Xm¯u¾¨ƒ}¶—]»SýY%Û*]›\Q'ÁFŒç«÷í;VVn©?PpÔ ‹ ¿6ˆy½>®¥šÌ8:õD'Ä¥(WÌr˜õC¢Õ¦;BAA–±ý íM4ìg]`G‘?öèÊï ï0†¼¼eõ*Ín«}/×[tåPMš²fH΃0UÕžÿô³a™Š¼h ¾ÄĘ@«o¯ÖÒ›¨mد­î RZŵ“ Åô`z5uÙ¸jãzñøI§k'”¶ÇfV§Ë̯8ÊÉŽ…4mºÖ¯Ë¬øžH)3ÏWçèHjÖ yÜÎB èr ÷Ÿú ³ C}P™gùvÃØ^š•»\vûyî\.à]Ò@ý›Š©æØR.v7ŠBedÌქŠ7c©}_@q×á3Äjv/ä#ÔZ¤Þêñô’ÔIý“J‹ÅR«­r3)†Q:úR"N¢m[~¡YW/Ø(œõaõ±h £è— Õ¤Ä%Z"A“*[“J»°¼J„ŽEý‘Þ§±æûàÈ6‡”¸ØÊ¸°µ —A Ö"Š-©™&(äÊ# CÃÃâü]š¼_8pút™`'®¢ Vû¨ÁluzÅš­ãÒK¸‹Ç©_4Ⱥ õ®¶«•þLJW–‹ª?ž³6é3Ž0äAö3yõûᮯ×`ÏììPSUj„]c—Æ{'×O:ˆSäv¿ïì«•bÙm *[Gð‰&5]Gf½ð:j6œ‡´µÇèXX Ǻüå8Z!ëu,*ÿÑ--.âÕ1 ™©9¨míå k»"íêªÃÇí³Êß á]%–uu&™% Ð&G’€¶s4`_5Ù4™ñCZí×Å7ù¬+áqyI)«Ô±O¡Ž=ýÇ’ìFMTJjÚz%*@)ޱ´x‡ö•Ô&’»·ŽÕCÚ¥˜Ží îôÑ1â+ðKXö»fú#ĉ»«Þµ|õƒFžÈ¾ŽVd_„Ã{Í5–v'n,‹Få¿Å%ÌÕ àò}AÔ§©9lП«:\jÙW{’ESŒÅ%'Š®3òScÿJqz¥cZ'ò‰¹Z]½Ñl¿*iµÚ=j"¸¶’¿¨D›–¢Ó¦*ÅÑmO²âuÚ àò!£D.c+àè3ŠPífÍNØ ›õ> ~Îò¶9læüKqžÉžÎɉ—‚ÛA×Óøtñ¥y/pϲI?9IÜÍcÔd€Òï×=¡ÝÇBúÈ)æ^ÿy$죤$;IŸ’¨Q&iŸ! 6{uhƒÿûp êiÔÅaå­SËm¨{ÜöLÒê‰xt%£èpº”,"cÈd²Úº±d<.Ä¥8 '¡‹@¾"_ó£Èë_c>æâÐïÜÃÁ H)&oL'·Ã3íd‹“¿Ì4Ù`÷KîIp¾8ŸGŽýúý÷ ¹@ˆWEÆA0Z^QU`,kðª]ÿî[ë „é÷9¹ñW3Äu”ZØŽ1h_9^°}÷ñè3 †ãegI±'2·Ÿ~7ükò†œ<ÿÖÅ_H‹‹xÜÓ1Þ—â$¸Ùh#O²î\í{pÍ™/÷ 챯l ¿Žó®×µl;ÓWö‹ƒñ~2<ÝS¡«)0Ë3s÷T6w†…j}c‚åIñ¡îHœ©°§È¸?à€º¸Ç—/ßhˆnÞ#¯ß[ŸVlÝzƒV¡JQ@<•_˜]’±§(¾Æ#|›r»›àVëfnìÂ…³·™<Í»åq1‘;Á‡“µ2à—çi _åë îÜüï×¢öø©ùf]lóÆJa}åjxò¥+$ë|Sw[€¶Ér™º°ùÄ‘} ‡ ò³Ò»Ø¦¬[°iõOÅdý³Ëfìm«Ìö§žÒa‡xö4ØÒWö ^/ä×I÷«€Qæá€Ûž`ÿ)$sV<8p–vÊ÷ø*à6ú¹nÌ‹Ðiä8.›ßá«¢+ߘt¤ ª´vÿI“Ûêù{œø _Åýعà(:M,µÔ¥gU ²ß£ òÇ=î÷c :6gCŽ"Q›” •+×¹ù»‚3ï ¹Èuì¶ó‰M‡ —`·Ïøÿ›†SaÛÊ(OŸý‘ ìZCÃL˜'LØb±Gá.jÑvγoËûÊ~ÅP|Îc. { ×dÈÖW¸Ø]EÞ\2ƒ —?㟔Ý<7¹o‰ôK2L ûôþ÷í¦.c”Ž,+ûG!µu;öyƒ,†¥à~Àó€÷Êjàn}Q™9q HL¦©[à ›!©9öqÜ-‡È‹›k×–Ð1£º}ÌÇ^Ïí¯?÷R_Ùc|W|'¬~”¥¤ lêJSŒòh]Wš–¨ÒöËe?¤ŠûøšàÒ¿°À @S¥Ò\ZC¥´%ÌÒ:¾ÒþTyÐEüøâz𫸣èÀ“W-+ YðYã_µýÀD:xJ¦N8íļ›òUsü'QœìqErur¥WiP6¥VnÁ¦ùSwÍI;¶^X}R}Q[¯ÍNu×ÔîÜ>µgèô9è †Ú–½ïS{éÖwØM.» O—|1ÕHSr†Z“¯Åö¬¸?jùyé%k1½¬ymÍË,«ùÀº$NY– yABAª1*¸òHc@@dxІS§¯xñ!5­c»W…”íÚ²kWYHUUYYõÕ^4ëÓKqnƒM½3ïc¦YÒ:¶u:߆҈ö ±|œRP‹£ ˜Â2[Sª„r; vàî'=`øŽÐ¿gp îì Èßk•uбüâÔ èÚhP°3ŸLißíèpÅÔdóü’äù‹F©¥¤[ÕШmÔüÞ(ÏØ‹ÜØä‘ŽQªz\¥î¬¾”šÛ*mUÇq^ž'ˆ 9hõ)éÔ0¦^9—y¡¹I_j5Í»Ôq@ǃúØÅ+Ñf+ Âcãéx0Ø9ˆ¡ÿµ“)búv8ÍV‹ÕiFódÐÈ·G;“f\#ˆ}þršèÅ’Èz d_Tm5†Nd,ï)®¢î43鈑¢òhsvØYY^^Q\+ˆâŸ0ލ«Änßárö½cüû-Œ¸O½Œ¸·òøòô§„Ùâíã-àÖ¨¬M®¡ÄØû“‡yéê´d­†ÞDž¸9|1¸ÃÖ çÒ$ƒ†Úh.’¢åä IùzCzªSØpò6´€ykfd¡—Þ6q²_i³­ q ñð ÚJ°æDÔYÍ?%ûÚ"sYY”yg¬OòÖ)—Gbw¹ìä~üeV&ÊKwcËÀçöµØ3ÌtÍúÒWöŽïòçB»úDÖó³Ó©|èu:pzˆUù&Ï_¾BOW¨æ’ÓTi9w>îíß9­=sâ =w6ší› Ç£¥úÊÚÐoóe,ÕàWê›Ëš”;LBŒ;¸ø•Ř «³öŸÛöþ4ò*éG– ¹ìWbDnÁc”|ówzžlâ·D"ÈÚׯð-¾L®óËÁÿœ² ò(Ü¢S÷Íš§ À ‹Pì©foMQÞþ+·R­±‚-¬Tüè†Í)ó7$b øœÏ²nH•rD%%v ÉS•pÁÒd;UCaÖ…¼ÜŒô›Gëé.UDÏ$6a;'~;‰Þ¤t9rg Í,|`ø ódêžü»‡>l·Ïo[÷vcГß/:ÛÖFîö·mÑÅè’rÁ1 iº"n?Ïÿàýí4Ñì=„å‡B[JM·ò[«U{¡ˆ;ÿQÓ•«7Ì_ã±e¥`Šá?m8Ö—¸GO6cîØH½K“³ßl¦šÿlõ®)NÃ_øãâŸÑö›;¿Ô+{6 ¥ÑÙ˹an<öžUqÔÞsœûΆéSæxçLÍůŽv¬¤þÑ—{Ä!ÖB.}„¬ Á+¼/Kâo]µN¿7P8”YUd )‹öOôX|rûWÈSwÝ}iÑDØ'®Ýéâ*lw uƒw8ÒçëØ]ýr4í9ÑWfóѰü.D6Àq8'áhiCÅñ}yuT®kw¹äú¦.‡­Ü´#'Q'p¬/ų8¶ÏmNµzHÄBtä1Tš_FcÄȉ·”~o‹s¤ÅÊÉdéMlÒé ¹ê˜“˜¥ˆVÇ)Ô rÊ–¬úç_…Jc# <¼ äè-u'cmÉiLÇGùrœ,Eš´u<¨Y‰9…†¼ƒpOÙâª?ýŠôÇoùöµ­j¿šèG½ÓÇñ+cºSý|©ùëG}eãñ$¯ÍM´ú±xPFÊ£YØNG­!“"£wÀ nMÍ,|ýù½·ö†æ‡Z-THIp}ªà¿qnÔfà¦Àécçs Jåîg<‚Ï8Ù?qöŸ ÍŠ[ xns÷¹׊vÿóróOÉÑ©ÔlAîýX]a´?Uíߌ2 Êšý)ø;Åx‘ÇžÁ#!oY<3óÃfž4³“Òœ›ã>LÕfjS«()©¨Ü]¬t×lžxböI’»Xް?g]}LÚ—æÄ,÷CÞY[réúKéàù•êýmN*F—\Pxd€Ÿ9¦ÔpPwìÉ’«¤{ºü°ßV–HO€ñ°°aKqÔ>½IÍqÜ£î¤w¹ê.uzçŽ~x+ÓÚ®d])¾c 6låÉþ<|Ùãˆ6 OmÙ¬es““~§ºOo!W¥¹¶®‹Óô Ó º}f†Õf8™˜À„Ó=“Í©qgX_%­s[ùô,½Ò9+ØR’“•¦E‹çÁ»°Â¼¶%¢hw/psL%/‘^ŸÎ¸~õô}ìžGw·È?ò:žRŸA³%=U§uh[÷ ‰qGEvbv¶>5'S0‹cùð%y8ßþ(¯ôDóÜA„Ù0ƒ\\Ù6ìO¿ ýºˆGvÕ½ÿížÖýì0‹ØÏ‚…&›¦;û.`?3ž«”´.Ç^¼zæ².°64ûî;r¢ñã#Ÿï¿TZwßêá¼4ë´JjÀ§víþ1GÓ@µjùÚ‘.‹\×ÇPÇùÆ6dOžûø3J\G¢ï,X1wí@·ôùu…ñ#]¶Â:ÇÉ_,ÿþ«³k„Ë+ÏF¿Oã¾pZ—kóÄ|à-õ°p_6ÖÔƒÁš%3&‡ ®oó&çÿƒ+Jê74x-[³"9¸i¡ONÞÞ[²Å:º££•:(oŒ‘´ÎÇ[ü †hûö÷^¿!ëùtÒö÷ß[ž"ç…ÌÞíPX·ÿ› kÕláù@l 7ÚãhSö¼f}±Š¶YtâË£*¼Ãc”JA«ÑjµÀi ?µ&ãÓ Ês­ fà2RRSÓæ+Ë\ÖW”[Eûß9ÍNt †Ò_Œ6ߟ‘à—$™§Ó‰>ªˆôA{_\ 8pÞ>œ‡½±O^çETe„ED¶JØHºÅ 5®³rH¯ˆí9ÒûîÒlàÒS Ô˜øY¥/?üØdêQ)e¸'w:NÏÚ?¹RW^a,­‡&îŒû 2‚0+-ݱ'võÁÌa7ˆ,'Î4Q9¶E«¢###åK懃÷8j¤”¹yU,P~#SþLM»âÂhXx¸©À^kÑv%öžò¥¥J¥Tƒ¦$RþÝðÓdO s¼Èò ±ë¨˜2U•žýàc”š±[.JàKë֠„/™ð¢ñ‚õ_j/¹Œù—‘1Kį¨XïÑêB…(i4huÊŒ­6ä{7dôXbOì¿ûìäûUMÕòì -û€û:ÿÙ/Gæ #™B–‘‘dÙBV¡@f£sËÅŒ‚‹òòtìY…\v2D ‰ô¢HQ¿å>6d pd)y 'à"tÂÁø&NÃ7péF”ã’',ñæùÂ#»¶iîXòòFb#éÙèýó[à ¶Cɬ|TJùè¥>Ú¦ã/†pÂÜôÌlA¯·Õé´±ËÞÛæ,W*éªTíT”ûùçȾˆUFE{¼Þ4Ú'¢ŒFûW«c½•¶²Û* t•Þ7;e~n±q,ÿW£@o:Âí¤©yüÙ‘kYX)$ª¢ "3cŠ”Ü ÿ2-ü¤ÖDž¼áþä·Ñ#Ýñ ©ÞÅ•glr°X‚U¸’?CŠW³V0gšl@TIDfò¦6UÛnw:¼Î‰?µÞdqJì+—R¡N˳ò`»PǪÔùûoóRâh»hÚ]]~jv¶ÁŠË<þiƒ‹ÔNü{ nµÝ¦V“Íþ;˜yG"ºâUn¥Üò¹¶õÛé…n°æmë»0e¼ ï¤N80çàŒ«áVÛüYé¡oj.§Ý„Ï9âM®ò°Êù­â<‚³p.ež,Á—¯g™¡.E– Ïv‚9°ÞEŠe1£×ø»@Ç`.6XQ¾ ¼FçòÖWù2Ї +–MêIüèô}Zʹ¶Ö[?Aðµ>*¸ôï^ç£_v‚:§Á: üùç,öÇÆm;ÒÈnðÏŸáx΄§Ž(p‹ØÛ¹ã&:CQ]îòÈrŸ$ hÕžN6œîáÁÓßÞ4sí 9YKv*¬OÍBe?‹¬´çÙKSü“·%Ä$'-°ŽY¯ò r8döøáC:¶`÷·~Ä·ÍyF‡Áƒø3ÿEÅ™Oh†¾˜tjÔÐ9+çì4ETYŒ¦ªãÎ#XŽ]Ê«îÀaâ5«ƒ¶Éý·ìPk“´!šdHÒ&k!“µ)P$’~Ѱhé¿p×6×wŠÎúÈëR,&ØÇÕw…øÆnÿx Ú ÝÇ? ôÖðÅò›ƒK»6 Ú‰åQmg£urK³Büéÿ\<Ô›UI°Eå(û’ùWÉeÒ÷˜H!´Î͸ ¸1ä%Ê4ÿj¢÷¿ÐÇK:Ûøé½ýgËêR*Mb„CXntq -Ï­’I3ÙÐȽ.=¾'×ZîÄZèâ9éý÷þÓ`õ>{VmóT¥»œÒM¸ „ù—ïõ—Į̈8<çÑ–}òEÓGÇ*#@'hÙ(M¸uGV© ®HTÇA"Äs„eíÂLâü"Ü•“n’’í¹¬¥Çå—…ݧ{¾dÊêÙó²±g/†ùOM ’ endstream endobj 11 0 obj <> endobj 737 0 obj <>stream xœu”}TSçÇïåBî ˆÚ»¹Êî[_<ˆØjY=³¼¬TJ¨¢öX´ ÃðVr’„*ã%’ü  T^Brµ°[”RGÕ–j×µ£eÎöXÇô [çz|.»ìœ]âi»?¶žó<ç×€‡ 賟•ÿ‚'Ÿ«†Qe‘ß~tþÒ¥¶=YŒXý÷¾:p©(¡ª¶[HôâÁiœ&„S÷nÍq[¯Ésèxh¨ýº½·íú¦‚ið€Óá´76€ ¨°V²b Y Öcn§Ó×ɸ›ÁÕÞ1´o:úv|rf¢t°î([4 mÚöªº)¥ .P¾3ExS|™‹qZšáP­àöHeŽHe®ùîÏÑï…ú;éä¦Ü´§“¬o½Ã /Hqõ¢úi°%²b, J( –úËOUŸ“^„<ßÓ1@m {,‚'Ó-Íc,È(ŒÞ‹w…j?÷5Š›!„há=Üè¾Ìð¤Îž ”Âã uIð¸òÆ‘ê"v!LÜ·}·q{ˤš Zƒ8Iùö–Ê« Ó¦”׿¸y…1QBzm7Òv¡Ô],—a:Dw» ëÎî[b¤(Ûø°-®üG,"Уó5Yë-v«ÕΖo~ÖTþ£”Ìv‘Î.ºmøÊ€{Ð$®v–PQÈ/¹„A+æp„¿O aî3öhÊ+ŒZµßìðôu3"#fI¸>8Z/áêýÁoKÖn…I8qßÜ îaV'C—ÎGŒÜ¿ñéù Zd¿·Ô‚ï‡óc’¥‚pÿ¤¨yÑ7ÿs÷Ì+  W飽§?wR<¹Çn‡ )D!Œä9G»LPöú*ñù…Ú•â‹B§µ\àú)z%ôzûV ½ÒAÿÌ%è€öôÛ……•î*—µ ÚÀy¤¹s1’À#†ò¤Îðö‡ú÷ÿjöÎß’ÿ×É\ï=ÿ |NÍ$MÆ>–œ•R0`i÷ùÛƒƒú¶ŠúPECWn¨×¦­5ÛvrûYu^‰Më ¢Œ>!µi޵ødb~+É/™z€Y¾Ù+ÿ‘÷¨\>Õ!İÿ«yfÐ endstream endobj 9 0 obj <> endobj 738 0 obj <>stream xœY Xç֞Ȍˆ¸ulàŽ;V+ÚÖº ¸¢(î¸Ùd‘%ìÉIÀ°ï„EDˆ"*Á¥Eª­ÖÚÚZ—ÛV­þV¯mµÚjíüè½ÿ7@[ÿÛö>÷¿Ï„GI¾Ì÷sÞóž÷dŒEF&“±Î®s×M~Uúïhñe™øJqˆHÖ+áíI–`-k‹Ã¯ 9Ü_ÒKûà†¾Œ\& ‰LqÙæïëaï°uŒýä3œÆÛ¿êè8Ã~NO˜ÿVÏ`{WÏ?Ÿ ÏúK ½{ÈVŸˆ{‡7ý""v¼>iRttôDÏ ð‰!a¾ooíág¿Ò'Ü',ÊÇÛÞ%$8Â~™g}×ñ&výã´#2Â'ÌÞ5ÄÛ',˜a˜Ùs‚ç†8ï˜7?Ì%|AÄÂÈEQÑžKvz-ÙêºË{™Ïòmn¾~+ýÝW¬\´vêkÓœ¦Ïx}´Ãë '9N~uJ/†Æ,g†3nÌf3’Ÿ3£™UŒ³šìaÆ2k™uÌ\f<³žqf&0˜yÌDƃ™ÏLb\Gf3™YÈ,b¦0‹™©ÌkÌRfãÊ81˘é Ï d1¶Œ3˜y™á˜žŒÄØ0}˜¾L?¦?3€yIfÅÌ¡u`,˜Dæl…¬¡Ç¸å=žÊ—Êkåÿ´0Z¾i™`)*–)ö(ž°\î@Ï=õ|dnõy¯à^§­§XÜûµÞU6ŒÍú>ö}2û:öí7´_pëþšþï Ph}iÝKuü¾mà¤õƒ† òT0è™­»íUÛïì¬ìœíêí~¼upûËÕb†Mû=0££Y\\!7·ÏàSÊ4{Â! 4i)1D×ñ³mJ,hB2Â2Ò!¸•b¯þÔA-\*Í;ÖÃÍl$ø@H~f.èõYm8Њ‰£å•¢Aÿš ~„šÎ¥ãYrGŒå‘#G-IœÂ¦ÝÌ¢•I†r”áf”ÉÅ}x–ÿÎëmÒÃÙÕo¶¿ Å 23ÙRÅžÏo%¹ä¢b«ô—a½~ÝßýYd®·]8d Ÿ%Ú?[ÂÚ´¡a¾cÂ*³ Gbü|E~¸}.¯zÖñp¨J\ÇâŒw|7ýSÒ;W‰#j÷Ý„Ü}§ëdª@V“y¬ÂEìãÌõó½IO%C¾âñô`±g)a6/õ°Jñlj£8Ø$«Gk,@k¹X‹!<¾<é™Lœ¦'É ûp2:Ýy„ý¢'+x2°çÍðNy£²òȱ23¼;JC*|a-xpÓp„lÚÛ̸¶ÑË,;CE]³¼]Ý>•¯‚ÌHa¶³ûÉ…ÕsÀŽ$“‰d$ÙF¼p ƒtAmЪ4U·[­†D­2‰Œ'üÚɰ¦”¹è×pP€ï‹¯œ8sáÚ㼓p °·ç~2OŸ” ÀU¾ZIKEÖ˜q¤IÔ({J«e ÑáA2ŽwÁUŠšÈ–°sÀ៿ÂQ(L¼K^v[°UyŠ%s~«^GÎKã"ål+9 ÜGg݈-é¼n‰JUy"nù„¢ã!­× ¾BëÕô{½f°¸ h·c}ˆ›’¸ý2ˆâXö\ò?´¶Î«|HÏÝký6úmZ¸}2p6íQÍf,9)Ý×gÐ,®Á*ÞSEÆl›IæG±ù¬âAž×,e3î÷TÌV{Žܰ8L‹‹ Ï5+‚QmÙñ=Îý¡ªvK…¸¥ ËOŸ>ANŽÞÉ›²q öâSvA çeÚUSc*=ÚºvŸÇ›þ.žqÝr™þ¯è¾F³S7 ººS)t×Ò#×ÑW÷‘§Ð#[µÏä;îví®¨Ó£AÜ…·;¿Dì°î4û gËÜ®æ&o'¬Â:®À)P3·ˆô¦؈ËSM¢ý~YÓ'û‰\ì-ÎâË!{wª’v é‰)i!%Û ¾À‘±@þ‘õiÊÚ4SjI:žÜ[޵niÉÃ!µB«Û\dD( Ëî„”âl=”T{Ëù½ e`wû ÝÉPSt™Ò뀿auÞ’üåùp’ûè.Qn˜¦tñ9èŒY¥´yÎQÐ{˜Åþ]ˆm)äqÿ…Y®±‡X‹`™ž†¬Â¡#Yˆ‚­aÑñjOX E®W¼…h OJ/kûktc0ûï»èâ—ÅmG•Þ Ï®òJh«/¢­ÎšqV…ìGÚ½›åè+Žäq„™Œ@wO…ÖÁÃÁ!ƒÛ~ƒÔ³CoF\¾ÚræªÐæ¹–]¸.V 6Ïå´°ÇÌXfî*ìu)¾ðöAü3³"˜ÆçK/{îŒï)#ױ왙ýÃ'RC°uúŸ¡‘^?C]'†â1¼NŽýÙ'Q–´ð\ë+ÏÄeü¯0\ÇÎÚ¼læìôšÓ>`‰ËïU³£/ÿ\}n˜Ýë œc°4³®)pX)Z°6â´î~NãÀ}4´0+|5£Á“^£Á·«P‰…ŠmÔ?†fz=†Æ.ÌJw¸—fy³LLmøì⬜3³¾ xÁÐÀÊÎ;°µ•i)ZЦ©•¤'É#<°B³€®ê^:úeÇd¥T‚]>_NÅ3,³}FJr#¥_í*!Ó]ÆÙˆæTzÕâT“ì-‘—4UxŠ¿?÷<êN¬Òœ<bj÷×›ÊSÊvå ¦Üj(î“£>3”[Yò*™²…È‘‹þôó·›[*”Û@õƒÐª0æ@¥1 â”KuPU‘á'8Ålð2ÿ;2õßï¡´øsm墿ø:I¸¹0?7ç.Ø™Ùå´›!fBXW¢*¡Z»WÍiÙ+rÙoý?ð¹}ò5ú}FV¤Û%n€HAÅ6è¿¡’a?|Û=ºw°«!}ºˆfE*ÏéÑî!P vù…¹9_I§r§§ò§•WAHשÊi)T¿h4Ê©c°·eó¯Å‚ÕÝk>cÑ‘¬¤ytB\JÊt°S±çôz¨§ÔÛ ûº„ÍΨ=Ù:Ðeç(£%ÊÉË–ž*Eµþ"%èý”m»VÍïn§Á&\ÝJÙó¥Éèݾ˜qôýÐÌ––—–—T´®9x„ŽJáÙ-ªC†L¸G†¸mÜà¥ÜãÁèÁÀ•«a§@þ¡H$³-›†ï*[PÜ=©ï`“é Rì¢s¡B{)Jqƒ¥§"yh¤;霣âEèI5H\þX’IÝŒ½™,ßRçB3:lÔbO†?š†v§O”›+ײèò;‹,‘uÜã=—­‹§óžôð1¥•MÊú3g UpZbL[¸Î™ÕÁbê 9šÛ§ñê|­.š~)ô¿Êª‰“;¾ÉOÐi Á® UJñ •:ÝÞ¬2}…®ŒÎh©}gRä…À›щ¼*¶–æ®:£.]§…H®c…w^j#º×á[]ò;é¾\\‡¡|•jö§\ÛtBéÙì^¸B’wÓF’þÄþ‰#ŽÃqÇž•ï†ÔXmF|ª2tñ¢(ºb¤_>£¬³ÐÕ66–7¬4SâÊ%Öºõ´ o'4µ÷mìT$‹q¨¼½ ¿áÑ8Š„‘p2„Œ&¾ÄíÉPÜA/{оé ùŰ´Þç=+ißRýûAæ­£Ÿ´\º\s–нsªºÍ‡V¸Ò1é8}½K˜ÿ*ÕL*WñA'éa85I–OïJÊ2HR 3éõDñôãS¾^«1»ÕI» ŠÛÚ³·²±¸å¨oóo)ðon?Afüm2CÙ1¾‹EÔ8X|Èã$˜±`8‘IJ¢Ä6ª,Ï’M øêýk @VßnÊq .æO†žb‰O~©5¸1!OYWRUªÏH£3ž‹*Ú¹woQ¹±:¦ÁSå%xU{箣EV½5?0Ï«Ù_¹kgŒ0ªªmÆØðT×Xɹ}´—âë·Þ½öõŠº°Á£z L¡.v ¤éTÙ Mt>æèŠó 9ìeà§Â§Ççwî€Ë¦Mà2Uy†xðW.ůõó[A-ˆ­ï™¦ B±òW*uןXÔQæI"þ{Å‹LÿþoQ¯'˜¢ÌxÈ„æþõh¡ƒì÷J{¹ÑtÞå»E\…Ëß ò´³ ?ý6V±ÞÆ^Š#ÐPºßŸšö…ôòjõ?åwS[ Ü÷ŠJ“3ãwjSâµÊ´õQ!°R.&ßçìNmK¹Jåß žôÄFz#tÊœá¶J;•¼¡´Á(^ÄÖp„„F9†·Ëù£Ûë½½ý}|êý6ÕÈ<²ˆòÏÙ,ͧPKC½Ð ¼³‘ 2 ™Q -ï6èÆJæ$%C«NTÂŒë¥L>|Öd"[ظ±(Nyjí¾Ô§# 4•Q…ñu!°ŽSE½I,¦å~•,hË 3úWƒâÖePtºÜ_%ᜊX+’ÌCèw– ´Pá<^ë߯ihA»¡@§ƒ,® Ò’4*„]@–µ„dé§d#ÜÞH=¥4nO(_¸{â}9Þ@=¸ÔaÈ…Vj@ \Z$¤ƒ¦?u­Ò³Pô¦„þX\ŧ“YꢭòŽä7Bô~!P¡Ü¶Úð¦}UM§7¿?Š2ÁxÒ[õ»dýÖÇç8Ÿ­1hý”äÚŸ}.N¤dÑ çÝ—`›œÖ`Ÿ´Mb»êØ]ÃË,¡$X3ÏÝ+dçÅEr1©}O“E“ΕÅåÅïLOˆK:¬ÿ1•&†æÅ.¦H]Xž•_lè¦I|d’µPË'=ñ/ÂËüÀT’HÔ@RÆŽ’€‰˜¨ÃÝúf+á…ÑÆ°šØÀ¸rN=ºœ] p~w‘»¯Ã2 ‰»ã‚‚¢£w¨Ã¡‹QÅLs ­ZZÊñQ;Ë×i @˜³„È¥?ÌìT•+B›áH!×QI”*¶Yÿœ ×³îqO†H< h…ЮÕ,;ƒvè&5‘xOEFTŠÛnurÊLØMµö$ESÃßÿVœò¯>i…ZÙF•±åØ%ãטwWÕ77³„#ÇÛ²Œ”:[f;Ï\ãì¥R’ ­N¢º#Æn—8½‹º£€ýÞ—še_`t•lFÞâц{l†¡„‰Z”yÀCiÎ-®‡ýÜÑà:/Ïà`ÏIWcœñåß¿ö™T+|]ûÁyø’»æü!Q‹n¯¯?»·î`ùñ*õÙBóÑOÀÜ]p JßॠõÕøh´ÑÚtMj¤PÔî2P'mÓ>â7[Õ‰QÉX‰¥ÿ¡± \•´AØz`좩²"£|I/å¿Å¬÷_0r‰nIÛ‚ù©øÔÁêäŒ!1-zAŒ!¶(‘²'k“P ºåâ–Š¼͚ٔ­PÖK°²pª°îy ×ÚeUÖ½uÖ6 ó¿¿uåŸ endstream endobj 550 0 obj <> endobj 739 0 obj <>stream xœcd`ab`ddduö ²1TH3þaú!ËÜý»ïûןM¬Ý<ÌÝ<,k¿oú!ø=”ÿ{3#cnaƒs~AeQfzF‰‚F²¦‚¡¥¥¹Ž‚‘¥‚cnjQfrbž‚obIFjnb “£œŸœ™ZR© a“QRR`¥¯_^^®—˜[¬—_”n§©£PžY’¡”ZœZT–š¢à–ŸW¢à—˜›ªršˆpÎÏ-(-I-RðÍOI-Êc```Ô``àd`bdd‰øÑÁ÷Ãðwß‚_Áó?aþþðwŸèäéÝÓû»zêfÈÿ–ý.šùݯû»~÷÷-ß¹¿KïÛ9sFOO÷Ž í“«##ššå~KýVÈÿíÑý›§ûwÉËßße´9øÊüpžõ=êäl¿§±¯áºÎ-ÇÅb>Ÿ‡sùžë³yxd÷{ endstream endobj 193 0 obj <> endobj 740 0 obj <>stream xœW pS÷™B``L’Yíà}Ï@MHwC $ I8 æ2`0ƇlÉF²$Ë–äK÷ùé´.K–-ˇ,É_Øs &\…Ý$Ým—Bl»3-ö/÷±3ûl¶Û$;mG£‘4š÷Þ÷ýŽïûýØÔ)ƒÁ˜ž–ž¾qù²ñ¯‹âóñצÄÿYBåŽ=Û= ™85úÚKݯ ®—QÅ´ï%ŒÉ`”–kÒJ2·ˆ#NIÍ_œ²|åÊKRÞY¶leʇ<¶ˆ›ŸËOIÏsؼ\1ýãpÊÎÒ|.[,KI]Í‹ï½ý¶D"y+—WöV©¨èƒÅKR$\1'e»Œ-ª`¤|TʧlÍå±S&«{kò#­”'(³E)é¥lðyüR¨L\¾Q’+Í“å° ‹8Ü]%‡y¬zöaØvl'¶ Ûebob{±uØ>, ËÂÖc°°±O°Ø&쟱-X:¶#±ÙØì5l*v‚‘ĸ.Þ™x¥ÆÝÒæju…Ȧsh Œà7õ§-ÏÚ,®$tòbÙ Ò¥¬Š[“z\é‹Ûl9ˆÀçÁ“Ý€=µÅEí2).,úØ]Ôu‡ç¢vÖ·®-§^¥_ó©ù©765[lPè+É« V]8ÜÑè?‹ÔïoåddSÓel’»aq!àkå°€Åê¥áØ£hF—ÔÓ,þöÑrh±u¡×lÎ#·a[}ÇpkÈYi„vðËÍÀÓ•—¯òHég¶t-‰îÝ”“U*%ÔCEþ‚¢¿ã…£»Rï Ó¥$ Å#Ìø¼øLV©IRåx«:j ô :¶†š[¸0çý»Õ-qVyV»p¡x•X󜽺¶(tà-UÞ !¯âàŽ‘ü{èÝ>4{¨[Ú&÷‚¾=ÇUä̯ƒ!<Òzù~ÛiMŸHBÿMË"9†Ò‚Œ«W˜(/þëqBÐ=Á‘ŒüiB7šo‚ÈÝ•†RGEP?¶4A¢©Ü Aò~BÕ£¯¾»—ýéFÆe¬½ÊdPèˆC 2˸€W(ë´ZêlºÝ›Ï½ƒ]õŒ2Ñ“ ,OÞQá …––†Î@wýe°à>0ék DÍNéǹ“7y‡GÉ„Yýî^›?ÙÞâî¥ k¤Ò M\5!]—C¥É3MúüUëߣê¹ÐñUûMÒµû  *éÙ·¤Z¨šdÃÒ`'Ú~ÓÛÓ ¸«ÁTR¦àk«ÉÂÔŠtÈ—Ü}z½{( ’â›!6ƈ1â3ãOX®n«û+À[ÐäU€žäÇ>ð`•7.mM-H.hƒTF£Š¤æ=ëV”«!Y¬¢ÿô‚•ŒÀk¢p׿Èé¥o¦†r™,²Â¢·œ§¥OËyãškôWQÆcf<=dÙCîžç­Ëej‰†0hP;5B Ï((ÀhÖ‰3y‡ _wö¾a4‡ôD>âCÅ=Y†CøQ_ìè$"E©¦’Ì¡fʳ/»ÁùE`nõí›oj£ð 8~¥}´ëËNô*œÄÏ ü•"‘°¼Ö¡u© ¢MûË_,Ü+Ìäpèñu@騋Ù|4ïm“­ôΌψ'±d=üðAÀ©ÔKÔO¨EKÏoü2xÚöù(éÌ=Z|òÇäP¹I–‘¸ÀÐ Yœžã¤gÀâvõv£”¹u`Û„N˪ËË Ä&ÊËÒÉÀX]™³+¯ªð}5çûNw¢9-'ÈØ¥¡ž~À¯ùVjµF­IG×÷sE¨þÊŸ‘‡èÆC&ú :Ïr´·<¼vh…æÚRDeŽu6öŸÍðq·s2ÅrBt}·›ø‚K4ªÓjqYÈ®§×Ûºo:ªÚ~¸ò“B*…¬Jç俀ÄPQßf5Óv —;«y"aIöiÉñëÝ·VÂ[Ø]0 ø“Äjo\eÔkŒdqÊÇe%€TuvÑ…n<)þá ¨p€1<Š·™H=¶†ew­xÚ($Ô&…‰6¥Üþ“R£âê*ˆ•ÔWò}ú*à$/9—~ÍDsÐbôÆ7™7WeçñóÉ,G,.Ï©kCþvÀ»Ã¼ÍÏGhñ'ÙE´ž¸Åá»MÐÔp…® –Ê Üø?Ç+ã/³l>š‰º u*«´Õ*¨SÖËhy ´‚ƒÔ'sõÕ‡6l|¯âxωÀg]÷Ɇc6ϸ2¿ïÐðãþ( ¢3%"¥P#%ó_—í€ø;Wx—úºDíyV~¦ËægC ´Vö5@=ø¼n—»žv}L`SŠ‹«²ö/üìÉ“oдÚÓë!Ôu¿bò1ã)ñ—XUôÕ55UÕÆJÐàeЦH¸µÿÔžõÔ<*™Z@½¾üâêoÑ‚_?õ:´uZѨÖ«S)Èß"85z,ø»®ÏÈØÈùÁóнµ>½/8×}ýs‚ª—¨Œ•4AZÔ¾ ˆ0H¶QÊI[$ÿí¶˜³›}ôÙ4‚Zbœ¸G˜hªbEà®åtó­¨ýøðãìcQLêߤÒ^ZýŸ?Ãûª_wzÍ1ÿeÒbõ¡%OÆ%4æsPÿyôƒjhÁ4Ý bháƒÆãÜCôó‡Ì8“Þ9÷¾Û9•äÏšQ‚­Ù÷¹Ã›ìj ø›ÁF¯Ü&YŽ^Éj\Ü(oj„zOd·äq·ÈRy„¶Â ,£^Á?JÒ™ƒÆ³‰¼ž°ö){³rÙHÖƒ¤'¬®nðã-2¯TÈ/g<^vì|ÿ¥ÞF¢óJ šm¦‡m\@Wçý÷{¡øüãÎmf¼$>›evX촖ǧŠR )Ò²N{>=·h‚R¨7R/gܾ4<ìq“fSÅ;ò<0&ëUÜÔ×A ÅæRWÔåi‡Þ h”—Èòóz$¿E/ßþrÔOHÑ–V(•K+d‡eôôØW}¶ÿdÍ Ÿ!çû¿î{O§£)ÒÓÈÝy!$toÙ–â­{Ÿ×çðµ\¦±ûWˆÅ©F|Mü[V]‡Íᵺ,G ðßé߯Öè…¤Io”Ó9MkÕ¸<§ßB„Ñ:³Íìkò¸&‰ggÊÀdÒH·Që皌:X\k×Õ¹Íöñ)z»½¥Þ—ÐzµÖ 7HêÕg1zõ+R ¹HKËÒŽp‡ÂdDÌ@¿LáñýOG#­Ý^ZþjŠjÁ"$ùVµÀ v›rŒ Ñ¯½“üÞ¸øè¯æ¿Þïò:»k¥;Úº ÿVAzƒÒ(7ŽA2úóÏFà =!¢í¸çüÿ.’uâ½tž—Özº¶[i ÐŽtõ-‘w=±ÆÎΖ֓çN ž]¯Åä5šÁ©µ˜Àd1î7¨ @>±1iËöEÅG–f«W¥\vA>»OBg¡1Öã==ßïHŠ+ÜtGf•z¼£Wž £ª’wç i vˆÆ^ïÅ?…Ò ÚŸ<èôµšíö&2éS&“ÇØœ¿õ´&Ò”ªyd)…KÖè%*.è’ǯ9Ú:„ïíWŸµþJDŒIíÈ¥$™¤ªL¯ø MÔtv1éÓݸ‰ÖîÍÉ,$Lõ†®ÒVQs‰]Ë!ks¥X7’=øÝ¹‚S›ñCçŠÿ‹sÅXcAs¼+ÈøU1ÇV )ËcwÚÁ ^µ]avùæÖÖÁ¸B¥R¨ìZŸ†Œ‡(ó3ú]£ÑiA•¬p©> endobj 741 0 obj <>stream xœ5_HSqÇש›º´‚UÚ7!TÿCýA!lQùâ¿kÞýqn׿յòn3÷çìîÛ®RÍ$R‰ŽDñEz)ìµ§^¤‡‚^Êß]—¢«#‡s|>ŸC â"D„¼[Û7ÐÚr´^ª á|‘pAb8_ž÷”€RÊâÕ<}Â÷«pÿI$#zj¶›žp9,&3CÖÈÖÎÎËd[KK'Ùe£ƒÞNjõŒ™²éé'ûhƒ…b\dýU3ÃL\inv:MzÛdí0]oh$ÆLÞ£&)Ç45JöÐv†¼­·Qd®©0ºiÛÄC9H-=J9ì¡’"ãX• ¡4ŒtˆA#¨T’BÅÈC¨ˆkÄâ—à¯Ì§A›&pà” j¼¦‡ñÐÌB€ó‚Úíö°³\€gk𰨥fÙ@fÕlÒ“ŒsÜ‚Ie \p~.ê…x‚ç âÖ9±·ìâ^Ü{.{¶…¸Hæ¼71ãõùXVS)øÅpF0. ‰`ü“ ¯ T{õóÑ”ŽIi`ëZú»‚ñ‘FÁj3Û©ÀTp.èóÁSpÇ Ü÷m›øÁ0 0)ÄA9èÁºMmÚöÙMPðqà“R0Ts+2˜}²ëOë l”Ö÷…5;±'éø——ë[ð^Q‰W%¤ß}OEN†Ûó#ª¤œNp¹4;ä.p¥ÓJ¡ïeð4±'œ• wpXuØvP+¢Ž¶Ú‹íýüzpøßÏœ,™‚߸X¦ÃÃ^‘˜-ð+Xß¿í|i°ä· ÙÜ›·+ÜR¨àÇä7#Cë쎟/€K~ï ;´aXëIZ@áa=þBÍߎu±?ì)¼AòÓÅg­™é÷ko'cÒÁ]EåärþÆR©XÍËså¹ Myñ㌲,÷\©”úBÿÔDTo endstream endobj 748 0 obj <>stream 2023-07-18T13:38:02-04:00 2023-07-18T13:38:02-04:00 dvips(k) 5.998 Copyright 2018 Radical Eye Software fitsio.dvi endstream endobj 2 0 obj <>endobj xref 0 749 0000000000 65535 f 0000571947 00000 n 0000634293 00000 n 0000570774 00000 n 0000547070 00000 n 0000000015 00000 n 0000000876 00000 n 0000572013 00000 n 0000587697 00000 n 0000620858 00000 n 0000587372 00000 n 0000618811 00000 n 0000586620 00000 n 0000608631 00000 n 0000572054 00000 n 0000572084 00000 n 0000547230 00000 n 0000000895 00000 n 0000001059 00000 n 0000572136 00000 n 0000572166 00000 n 0000547392 00000 n 0000001078 00000 n 0000003057 00000 n 0000586073 00000 n 0000603038 00000 n 0000572198 00000 n 0000572228 00000 n 0000547554 00000 n 0000003078 00000 n 0000005543 00000 n 0000585753 00000 n 0000598150 00000 n 0000572280 00000 n 0000572310 00000 n 0000547716 00000 n 0000005564 00000 n 0000007851 00000 n 0000572364 00000 n 0000572394 00000 n 0000547878 00000 n 0000007872 00000 n 0000008814 00000 n 0000572448 00000 n 0000572478 00000 n 0000548040 00000 n 0000008834 00000 n 0000012887 00000 n 0000585142 00000 n 0000589371 00000 n 0000572532 00000 n 0000572562 00000 n 0000548202 00000 n 0000012908 00000 n 0000015344 00000 n 0000572614 00000 n 0000572644 00000 n 0000548364 00000 n 0000015365 00000 n 0000018272 00000 n 0000572698 00000 n 0000572728 00000 n 0000548534 00000 n 0000018293 00000 n 0000022303 00000 n 0000572780 00000 n 0000572810 00000 n 0000548704 00000 n 0000022324 00000 n 0000027513 00000 n 0000572864 00000 n 0000572894 00000 n 0000548874 00000 n 0000027534 00000 n 0000031224 00000 n 0000572948 00000 n 0000572978 00000 n 0000549036 00000 n 0000031245 00000 n 0000035222 00000 n 0000573041 00000 n 0000573071 00000 n 0000549198 00000 n 0000035243 00000 n 0000038030 00000 n 0000573134 00000 n 0000573164 00000 n 0000549360 00000 n 0000038051 00000 n 0000041854 00000 n 0000573227 00000 n 0000573257 00000 n 0000549522 00000 n 0000041875 00000 n 0000047625 00000 n 0000573320 00000 n 0000573350 00000 n 0000549692 00000 n 0000047646 00000 n 0000049722 00000 n 0000573402 00000 n 0000573433 00000 n 0000549856 00000 n 0000049743 00000 n 0000050043 00000 n 0000573477 00000 n 0000573508 00000 n 0000550022 00000 n 0000050064 00000 n 0000053738 00000 n 0000588873 00000 n 0000631785 00000 n 0000573552 00000 n 0000573583 00000 n 0000550188 00000 n 0000053760 00000 n 0000058357 00000 n 0000573649 00000 n 0000573680 00000 n 0000550354 00000 n 0000058379 00000 n 0000063273 00000 n 0000573748 00000 n 0000573779 00000 n 0000550528 00000 n 0000063295 00000 n 0000068244 00000 n 0000573821 00000 n 0000573852 00000 n 0000550702 00000 n 0000068266 00000 n 0000073084 00000 n 0000573905 00000 n 0000573936 00000 n 0000550868 00000 n 0000073106 00000 n 0000077911 00000 n 0000574000 00000 n 0000574031 00000 n 0000551042 00000 n 0000077933 00000 n 0000083824 00000 n 0000574095 00000 n 0000574126 00000 n 0000551208 00000 n 0000083846 00000 n 0000089851 00000 n 0000574179 00000 n 0000574210 00000 n 0000551374 00000 n 0000089873 00000 n 0000095822 00000 n 0000574263 00000 n 0000574294 00000 n 0000551548 00000 n 0000095844 00000 n 0000100908 00000 n 0000574347 00000 n 0000574378 00000 n 0000551714 00000 n 0000100930 00000 n 0000106185 00000 n 0000574442 00000 n 0000574473 00000 n 0000551888 00000 n 0000106207 00000 n 0000111863 00000 n 0000574537 00000 n 0000574568 00000 n 0000552054 00000 n 0000111885 00000 n 0000117820 00000 n 0000574632 00000 n 0000574663 00000 n 0000552220 00000 n 0000117842 00000 n 0000123741 00000 n 0000574716 00000 n 0000574747 00000 n 0000552394 00000 n 0000123763 00000 n 0000129811 00000 n 0000574802 00000 n 0000574833 00000 n 0000552560 00000 n 0000129833 00000 n 0000133223 00000 n 0000574877 00000 n 0000574908 00000 n 0000552726 00000 n 0000133245 00000 n 0000136559 00000 n 0000588450 00000 n 0000627965 00000 n 0000574952 00000 n 0000574983 00000 n 0000552892 00000 n 0000136581 00000 n 0000140586 00000 n 0000575060 00000 n 0000575091 00000 n 0000553058 00000 n 0000140608 00000 n 0000144899 00000 n 0000575166 00000 n 0000575197 00000 n 0000553224 00000 n 0000144921 00000 n 0000149253 00000 n 0000575263 00000 n 0000575294 00000 n 0000553398 00000 n 0000149275 00000 n 0000153189 00000 n 0000575369 00000 n 0000575400 00000 n 0000553564 00000 n 0000153211 00000 n 0000155010 00000 n 0000575475 00000 n 0000575506 00000 n 0000553730 00000 n 0000155032 00000 n 0000158388 00000 n 0000575572 00000 n 0000575603 00000 n 0000553896 00000 n 0000158410 00000 n 0000162697 00000 n 0000575667 00000 n 0000575698 00000 n 0000554070 00000 n 0000162719 00000 n 0000166865 00000 n 0000575764 00000 n 0000575795 00000 n 0000554236 00000 n 0000166887 00000 n 0000170689 00000 n 0000575861 00000 n 0000575892 00000 n 0000554402 00000 n 0000170711 00000 n 0000175035 00000 n 0000575967 00000 n 0000575998 00000 n 0000554576 00000 n 0000175057 00000 n 0000179798 00000 n 0000576064 00000 n 0000576095 00000 n 0000554742 00000 n 0000179820 00000 n 0000183924 00000 n 0000576161 00000 n 0000576192 00000 n 0000554908 00000 n 0000183946 00000 n 0000188583 00000 n 0000576267 00000 n 0000576298 00000 n 0000555074 00000 n 0000188605 00000 n 0000193371 00000 n 0000576364 00000 n 0000576395 00000 n 0000555240 00000 n 0000193393 00000 n 0000197014 00000 n 0000576470 00000 n 0000576501 00000 n 0000555406 00000 n 0000197036 00000 n 0000201137 00000 n 0000576567 00000 n 0000576598 00000 n 0000555572 00000 n 0000201159 00000 n 0000205353 00000 n 0000576673 00000 n 0000576704 00000 n 0000555738 00000 n 0000205375 00000 n 0000209990 00000 n 0000576770 00000 n 0000576801 00000 n 0000555912 00000 n 0000210012 00000 n 0000214138 00000 n 0000576876 00000 n 0000576907 00000 n 0000556078 00000 n 0000214160 00000 n 0000217315 00000 n 0000576973 00000 n 0000577004 00000 n 0000556244 00000 n 0000217337 00000 n 0000221511 00000 n 0000577079 00000 n 0000577110 00000 n 0000556410 00000 n 0000221533 00000 n 0000226254 00000 n 0000577185 00000 n 0000577216 00000 n 0000556576 00000 n 0000226276 00000 n 0000231311 00000 n 0000577291 00000 n 0000577322 00000 n 0000556742 00000 n 0000231333 00000 n 0000235076 00000 n 0000577397 00000 n 0000577428 00000 n 0000556908 00000 n 0000235098 00000 n 0000238737 00000 n 0000577494 00000 n 0000577525 00000 n 0000557074 00000 n 0000238759 00000 n 0000242826 00000 n 0000577591 00000 n 0000577622 00000 n 0000557240 00000 n 0000242848 00000 n 0000248304 00000 n 0000577688 00000 n 0000577719 00000 n 0000557406 00000 n 0000248326 00000 n 0000253262 00000 n 0000577794 00000 n 0000577825 00000 n 0000557572 00000 n 0000253284 00000 n 0000257663 00000 n 0000577891 00000 n 0000577922 00000 n 0000557738 00000 n 0000257685 00000 n 0000261563 00000 n 0000577997 00000 n 0000578028 00000 n 0000557904 00000 n 0000261585 00000 n 0000266866 00000 n 0000578103 00000 n 0000578134 00000 n 0000558070 00000 n 0000266888 00000 n 0000272054 00000 n 0000578209 00000 n 0000578240 00000 n 0000558236 00000 n 0000272076 00000 n 0000276855 00000 n 0000578306 00000 n 0000578337 00000 n 0000558402 00000 n 0000276877 00000 n 0000281897 00000 n 0000578403 00000 n 0000578434 00000 n 0000558568 00000 n 0000281919 00000 n 0000286358 00000 n 0000578500 00000 n 0000578531 00000 n 0000558734 00000 n 0000286380 00000 n 0000290927 00000 n 0000578606 00000 n 0000578637 00000 n 0000558908 00000 n 0000290949 00000 n 0000296692 00000 n 0000578712 00000 n 0000578743 00000 n 0000559082 00000 n 0000296714 00000 n 0000301225 00000 n 0000578809 00000 n 0000578840 00000 n 0000559248 00000 n 0000301247 00000 n 0000305362 00000 n 0000578915 00000 n 0000578946 00000 n 0000559414 00000 n 0000305384 00000 n 0000308720 00000 n 0000579021 00000 n 0000579052 00000 n 0000559580 00000 n 0000308742 00000 n 0000312894 00000 n 0000579127 00000 n 0000579158 00000 n 0000559746 00000 n 0000312916 00000 n 0000316615 00000 n 0000579224 00000 n 0000579255 00000 n 0000559912 00000 n 0000316637 00000 n 0000320396 00000 n 0000579321 00000 n 0000579352 00000 n 0000560078 00000 n 0000320418 00000 n 0000325134 00000 n 0000579418 00000 n 0000579449 00000 n 0000560244 00000 n 0000325156 00000 n 0000328624 00000 n 0000579515 00000 n 0000579546 00000 n 0000560410 00000 n 0000328646 00000 n 0000329929 00000 n 0000579612 00000 n 0000579643 00000 n 0000560576 00000 n 0000329951 00000 n 0000330275 00000 n 0000579698 00000 n 0000579729 00000 n 0000560742 00000 n 0000330296 00000 n 0000334403 00000 n 0000579773 00000 n 0000579804 00000 n 0000560916 00000 n 0000334425 00000 n 0000336066 00000 n 0000579859 00000 n 0000579890 00000 n 0000561090 00000 n 0000336088 00000 n 0000339684 00000 n 0000579934 00000 n 0000579965 00000 n 0000561256 00000 n 0000339706 00000 n 0000344836 00000 n 0000580020 00000 n 0000580051 00000 n 0000561422 00000 n 0000344858 00000 n 0000349362 00000 n 0000580119 00000 n 0000580150 00000 n 0000561588 00000 n 0000349384 00000 n 0000353983 00000 n 0000580218 00000 n 0000580249 00000 n 0000561762 00000 n 0000354005 00000 n 0000358962 00000 n 0000580313 00000 n 0000580344 00000 n 0000561928 00000 n 0000358984 00000 n 0000363751 00000 n 0000580421 00000 n 0000580452 00000 n 0000562102 00000 n 0000363773 00000 n 0000366363 00000 n 0000580516 00000 n 0000580547 00000 n 0000562268 00000 n 0000366385 00000 n 0000371691 00000 n 0000580602 00000 n 0000580633 00000 n 0000562442 00000 n 0000371713 00000 n 0000376857 00000 n 0000580697 00000 n 0000580728 00000 n 0000562608 00000 n 0000376879 00000 n 0000382348 00000 n 0000580783 00000 n 0000580814 00000 n 0000562774 00000 n 0000382370 00000 n 0000387056 00000 n 0000580878 00000 n 0000580909 00000 n 0000562940 00000 n 0000387078 00000 n 0000392243 00000 n 0000580977 00000 n 0000581008 00000 n 0000563114 00000 n 0000392265 00000 n 0000397454 00000 n 0000581072 00000 n 0000581103 00000 n 0000563280 00000 n 0000397476 00000 n 0000401567 00000 n 0000581167 00000 n 0000581198 00000 n 0000563446 00000 n 0000401589 00000 n 0000405774 00000 n 0000581262 00000 n 0000581293 00000 n 0000563612 00000 n 0000405796 00000 n 0000410473 00000 n 0000581348 00000 n 0000581379 00000 n 0000563778 00000 n 0000410495 00000 n 0000415429 00000 n 0000581456 00000 n 0000581487 00000 n 0000563944 00000 n 0000415451 00000 n 0000418990 00000 n 0000581555 00000 n 0000581586 00000 n 0000564110 00000 n 0000419012 00000 n 0000424499 00000 n 0000581641 00000 n 0000581672 00000 n 0000564276 00000 n 0000424521 00000 n 0000428627 00000 n 0000581749 00000 n 0000581780 00000 n 0000564442 00000 n 0000428649 00000 n 0000433973 00000 n 0000581835 00000 n 0000581866 00000 n 0000564608 00000 n 0000433995 00000 n 0000437962 00000 n 0000588295 00000 n 0000627324 00000 n 0000581921 00000 n 0000581952 00000 n 0000564782 00000 n 0000437984 00000 n 0000441908 00000 n 0000582042 00000 n 0000582073 00000 n 0000564948 00000 n 0000441930 00000 n 0000447263 00000 n 0000582150 00000 n 0000582181 00000 n 0000565114 00000 n 0000447285 00000 n 0000452972 00000 n 0000582249 00000 n 0000582280 00000 n 0000565280 00000 n 0000452994 00000 n 0000458203 00000 n 0000582357 00000 n 0000582388 00000 n 0000565446 00000 n 0000458225 00000 n 0000463419 00000 n 0000582443 00000 n 0000582474 00000 n 0000565612 00000 n 0000463441 00000 n 0000468417 00000 n 0000582538 00000 n 0000582569 00000 n 0000565778 00000 n 0000468439 00000 n 0000472857 00000 n 0000582624 00000 n 0000582655 00000 n 0000565944 00000 n 0000472879 00000 n 0000475036 00000 n 0000582719 00000 n 0000582750 00000 n 0000566110 00000 n 0000475058 00000 n 0000480639 00000 n 0000582805 00000 n 0000582836 00000 n 0000566276 00000 n 0000480661 00000 n 0000485472 00000 n 0000582900 00000 n 0000582931 00000 n 0000566442 00000 n 0000485494 00000 n 0000488259 00000 n 0000582986 00000 n 0000583017 00000 n 0000566608 00000 n 0000488281 00000 n 0000488581 00000 n 0000583072 00000 n 0000583103 00000 n 0000566774 00000 n 0000488602 00000 n 0000492709 00000 n 0000583147 00000 n 0000583178 00000 n 0000566948 00000 n 0000492731 00000 n 0000497322 00000 n 0000583231 00000 n 0000583262 00000 n 0000567114 00000 n 0000497344 00000 n 0000500884 00000 n 0000583326 00000 n 0000583357 00000 n 0000567280 00000 n 0000500906 00000 n 0000504035 00000 n 0000583421 00000 n 0000583452 00000 n 0000567454 00000 n 0000504057 00000 n 0000506435 00000 n 0000583516 00000 n 0000583547 00000 n 0000567620 00000 n 0000506457 00000 n 0000506733 00000 n 0000583602 00000 n 0000583633 00000 n 0000567786 00000 n 0000506754 00000 n 0000508128 00000 n 0000583677 00000 n 0000583708 00000 n 0000567952 00000 n 0000508150 00000 n 0000510524 00000 n 0000583761 00000 n 0000583792 00000 n 0000568118 00000 n 0000510546 00000 n 0000512562 00000 n 0000583847 00000 n 0000583878 00000 n 0000568284 00000 n 0000512584 00000 n 0000514498 00000 n 0000583922 00000 n 0000583953 00000 n 0000568450 00000 n 0000514520 00000 n 0000516790 00000 n 0000584008 00000 n 0000584039 00000 n 0000568616 00000 n 0000516812 00000 n 0000519418 00000 n 0000584083 00000 n 0000584114 00000 n 0000568782 00000 n 0000519440 00000 n 0000521492 00000 n 0000584169 00000 n 0000584200 00000 n 0000568948 00000 n 0000521514 00000 n 0000522272 00000 n 0000584244 00000 n 0000584275 00000 n 0000569114 00000 n 0000522293 00000 n 0000525257 00000 n 0000584330 00000 n 0000584361 00000 n 0000569280 00000 n 0000525279 00000 n 0000529086 00000 n 0000584414 00000 n 0000584445 00000 n 0000569446 00000 n 0000529108 00000 n 0000532254 00000 n 0000584500 00000 n 0000584531 00000 n 0000569612 00000 n 0000532276 00000 n 0000536033 00000 n 0000584575 00000 n 0000584606 00000 n 0000569778 00000 n 0000536055 00000 n 0000537063 00000 n 0000584661 00000 n 0000584692 00000 n 0000569944 00000 n 0000537084 00000 n 0000537390 00000 n 0000584736 00000 n 0000584767 00000 n 0000570110 00000 n 0000537411 00000 n 0000539469 00000 n 0000584811 00000 n 0000584842 00000 n 0000570276 00000 n 0000539491 00000 n 0000542075 00000 n 0000584895 00000 n 0000584926 00000 n 0000570442 00000 n 0000542097 00000 n 0000544711 00000 n 0000584981 00000 n 0000585012 00000 n 0000570608 00000 n 0000544733 00000 n 0000547048 00000 n 0000585056 00000 n 0000585087 00000 n 0000590043 00000 n 0000598492 00000 n 0000603400 00000 n 0000609253 00000 n 0000619084 00000 n 0000621273 00000 n 0000627547 00000 n 0000628261 00000 n 0000632037 00000 n 0000585660 00000 n 0000586535 00000 n 0000587176 00000 n 0000588193 00000 n 0000588778 00000 n 0000589238 00000 n 0000632837 00000 n trailer << /Size 749 /Root 1 0 R /Info 2 0 R /ID [<2E9FAAE9D412E8A523C314EDED73C032><2E9FAAE9D412E8A523C314EDED73C032>] >> startxref 634498 %%EOF cfitsio-4.3.1/docs/quick.ps0000644000225700000360000114204513472024437015072 0ustar cagordonlhea%!PS-Adobe-2.0 %%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software %%Title: quick.dvi %%CreationDate: Mon May 12 15:50:42 2014 %%Pages: 41 %%PageOrder: Ascend %%BoundingBox: 0 0 612 792 %%DocumentFonts: CMR17 CMR12 CMSY8 CMBX12 CMBX10 CMR10 CMSY6 CMR9 CMTT10 %%+ CMSY10 %%DocumentPaperSizes: Letter %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o quick.ps quick.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2014.05.12:1550 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMSY10 %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 15 /bullet put dup 102 /braceleft put dup 103 /braceright put dup 106 /bar put readonly def /FontBBox{-29 -960 1116 775}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A 27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF 5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A 71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C 515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE 46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D 1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E 328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D 6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE 8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 37711A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.1: CMBX12 1.0 %%CreationDate: 1991 Aug 20 16:34:54 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 72 /H put dup 73 /I put dup 75 /K put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 103 /g put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put readonly def /FontBBox{-53 -251 1139 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF 20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D 68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E 26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 326BC603CD28B9A6E511975D39BF5957AC2D66D48E75D233CC1B78B0BDE71C21 DF00ADE87769BAF3FF3896F1FE5A8786C78F798741CB0F38300E98711F994F13 37994AF499D5BEF056FCC6F2BEBE3923EE7AC09AC246F5C63106DB4C92DB5DA2 47D1016490CE3A3D571211DA35CA7A7E6FA4CE92074E44590F0E4B4C90834406 EE27172A83A5F1C53F8E474448B21598395590F38D23697E65441DC75FB7294B B560D82E1DDE2EC994ECDCB7F362E60E108B09EEBB71078B84C9070FEAD4F1C4 2332D28EF482E89F064A5F32D95FA80AA2D84CAA27F7B61D457B0DBC7102D70B 3D6274006BA0C4D4731E03CD99E792A76E888922B1DBBB7AFAB73EB3B8306423 25C6856218DA59FA5EB6EFE9FED08048D04842E4D18C13D6DF5F3D92CD3B0706 ABC2024946EA8DDE0ADFFBDD693C08FED862012C73CF7491E1677ADBBDEB1C78 C4791859D9FCF9B153A2A5C3B4B3436254BAF92984DE37309E384D8827978CE7 2B9EF2E4034DDB15418C9C765FECE6FE63BE00659B226092C926F8D652E510C5 B2632A691B7FF8C1ED57C720423CA5BF6F27DAF0C0B90A1C7A568E1C3C21FB0E EB2336F01B06D047EB9E17BFEC91E7994A40165D4DBD085E47C310C0DC0D69C1 FEF02C68B548FD04A31571B0A0ECDF246FB628C9C470B615DC5946D081938DBA 62C43AB08053AE7E3886C50426C64DFA698D9016F6E4421433B2F057FFC237F1 1260F9CA7240208CF50B00AFDA29ABB70231B0886D657F143AF25529AD866823 64D025895B10D19A63C9F07D2730661490DA4E3C3871F38268F5134DD8B67F9A 24A34E18C062E606B06D6287FA2E0336960A11F6B181752772323659BDB9ED0E 96453ED61C7A3CEE10778226B944B46459F36029D48D7A83799979F2162BAF61 83178AB7DEDD28DB42F4CCB6C5F065F4D6F0F97C75D48C2CD500BCC746F45F97 00BB3B543D368B5604B994005587E8158B43CFEB22A43515EF9EDBE9AAC13EB1 6119EB67621D3BD51DDED406D7C7219953BD21F3E8312182CE62BB9F6AEF9199 B64CDBA4C22760D9BE412AFC6E179EBB295A627871A82E88D92FAE94C00BE7EA 581712D8D85FFDA4C8A4EA7421DB198356DCD58F5F2C7058D87959B16199672B 897D985FCBBBCF691A97F9631DD8F5F51134144D3F0BFF482F24C397F3CA59C6 FE739D2D3139574B068E0E7C96B7E1159B79BC024BDE17B54AE59BBD2B0E37A0 F5442F6375D4ADC1D795202B1DA5EE38D0EBE98EE62866718830446C29CB1DCE E31C449C0EC11E936D9F2BC2E38964803852C6550C6E591D3111763BD79B7D14 BECB90421A01B6E242B3D08F90C63815689A90CB904C07BA1D224F790950997A 0AEAE5AC6AE2F213C8E7A418B3F6EADD3BC67596654692F4A61895DAF6D4FA61 459E7E24F2A0E027A5501632188B9348EE4E0D9FCE65FEA80F4281697053210E 73664CDD8A7E2825A308EC570CF22034A51026E13BB004B9F563E3E3F45ACD4A BD3A60D29C82869474E8B523461BA062D2D6A9C98B99B081EEF2DC2739A2860E 769323E29266E24452B9C96FA2B5B6D14FFC5CB45CE9BED68D5DFB5FE278B85C 0E2E0B454A3E657608170E1E0830FA07D09B454F2B1A7792F4BB96E6FE43ED14 4977BBBF88C912DCDFD3D4DEB06B6D1EEA1BB019D19BDC57840A4A3F92AA29D4 AC8A0840A73BB3F118F668D9D4E4C136DFA73CEF0344C2E32C02CEB865FDBEBF 3DBD44B9B6F63EF01C2691F9C7F43309C9EE45DBB423E50505CC6A7165B47ED5 A0311E24203E4CE075F50B36DD2A7DDC85077BC599CC3E00A29C483F1DEB4218 32262EE6B07E54EBA32BE65240B3A47E2B5606674FBC33EB8372B7D39CB2D8FF 6495F31BB367301FC5BAEBE1ED5B854571D4544595D18628C0C789B4AA86CAA7 42C26E3C9CFFF98D224E05E94F5DD426203199FC1DD7B9347B044ED1116D7378 496D80454518EF2A7DC3D2BFBF77EA8227C91E2A8C41B3118E7BCA38B5E8C38A 52587793FA7D5A7B2DBBD8AEB61ADF5F75115DBE4741EEBC0EDE1D74975DF021 49C5E3C4000FA4E4D9E8E6644F21572AB30F6E8CD1886B020198DB7F94F8C722 EC0123D49783351D36BF1AFBB12717E3DFC23063B77388C409A4157C89D552F7 E5B3A2F825A1C8A8524936C2C7872A87C158AAF6AC142D529F0A66CD5495DFA1 BACE93058E8B9D6FD1C62AD19DABEFC18BD047256DFD19B29D88C63ADE376DB2 DC51939606E3EBA52798D23831BBC8E5DC8E6A0DD40D1F434B70CD292EA5E1FE DE034CBC40C250758A3E5300B99CC4342167A4D44784471216C8028E7DC9BA9F E6F540EAE0E87FEFC5BCB5E19650C68FD642F82F3292710AC357F6FCEA4EFD88 6F1049CAE4CCEFFAF6CCC82DDD484D4F7C8F8A825436A6CE713B0A697832BF9B 9BC9BB3A674C608E2913CB52C9471B4F3027124EDB6AAA9A975424A0DB8D63C1 2FEFE0B08D3493A79D685006BEF07C8DD1F2F635309F463025666F2EBCDECC42 B9FFC43D93AD2D4B7F2C0AD302336E8FD7E670E4378BF2052D9B70D25E9D2301 C97C2B9AE8FA1009F7DE7D5AD311F4672CA62775AE5D045E010A031EAC6B266E 7EA68D21B569770452D665DE101075E10E6CEEAF15A6961872A797F9A2E702D7 8FCC9CC526B9764E264FF987591E96482527CE200A0B2D7603BD25547AD258C9 6D8459BAB17C74DDA7101CD13EB38C8DF5A2C9BF87A8D22545B6E8EE6C5D5BB8 F958F433DC59B75F5318882634A85A9FDD941BCD026B75FCC64F068090BC5972 F25E08155D46288E4AD897D72BD07234E04CABEFF5ED56D036786CC07016D92E A638B3BBC6CF15BB6001943D18AB42292A2A8B72FAE9157D2427D375673520D1 850AD7C2A24748951566C61D6B2CFC1818ED0A67F44D07CF80DB914D283E19B7 0A1E167D19FB0BBDDBF65C79BD171B17545CA156096032A60EE45160F77C88A6 9DABD8E12857C244BA0B43394CF491D17C07813B9174EF9D89C9748EABB0F938 157758BAE4E2A4A69C9E460B9E4AD99F23048D258B0D321108EE9B96F843F864 DBD079685328F02EEA46F946A7EF927A1D49DE6DD5D9766420E74C7930895AAD C95C60AC4A1D2FCA0F85072FAE3675EB4DBEC07255C1C0891F87C3DFAF219EF5 1A64166BFA2E77D1ABCCF87DFB1A3BE7F83FCA5FD0F73586D6B0E66B6415EF63 2A7B085D9D61DEEE88BF1A180968C784B175B3D9856A3F9479FDFA071343E654 202EF4CB01815987E628973BC140EEF476CA4CF3E4FB62E657D10E3EBB76CCC6 EB03E73DB444C674EC7737301D62AE46F26A22E049B7AE657194AF8EE17E47BB 2E16CA163719EF4AB0BA827185E862BDEB8E22845FEB1ACE2960E94256D7FBCF 05F2EA5541B861BE2B0D97576E2440555C388B2B3A906DED36206ED6578D1563 8BCD8FFDAE85CF16918B2747CFB5D61DBE55F0E5154910E00CAA6DDF27F8016C 25311A7379F820566CE9D9B27FAA27AA37901EE2A4E72CB77F74879E00140927 89A71148CB996F35E4D2DA6DE9E4B419F1D2387279135677502E169048171730 59ABF7B6EC751302663320C108861037834E28E4457410A2E7BCD9EBA553E4C9 A1927FB48707FF104678AF51681ABB7B728478BBE37726E26A3C545F267FFE88 8E4F2A0EFE2902510D6739A4B201BB1EC21E8CC1E693C7D14819CBD3512A8BEA 3A936897E9EBA3FCDCF0F13A9525F80B182EF1423C5E5A3C82850BE2F7520CE3 0834D1E448235C68F246CBE9420E853F5F22F1404C7A3DE38B8C3D288F7FE595 2D09071B6D22988D80D46D3666E2AEB88872B37B5D5B535D07F61DCF0A29A059 F4E533BC39A06FDB2B45ADDB0190BBB9CA8100EAC30FCC212BE0A475CA57248F E2DF1BAA0729A4A97A479DDBC64573E00DD22FBEABF86F15C60227BC2D074B32 E6F73778F13FA9959FB62F1EA5B2B687F870A7BCA4670C038200D4674E168F9F 684FD2D8C626EDF0465CA01B27978D141722C3FEBF42D86FEF470541590CC184 B487E5816400FD06FFB8C30FED82BACA4671315A7610496DFEB5867A6883DB99 BF42E232663A17F27BDB01C4E2072A7725C02E631B3F85518A00B6E4BFAAD763 8C9E89D64B35F754DAAF4549D4E528941403FF224ACF62E172126CFFCCC4FB6B 68FF632DC25971C19AD4AE284075A7A2DBCC894B5515B5CB914185F388AB124E A1E8BA75BFA9B601724A84A8BBC0CA23716CD9F5B37D0F1DADABF475F23EC122 162BF687970F2E9720B4CF355C5829E395F526FE538CC265C43C916AC1323BDB 543E0DFD699AF2D3AF09BA03B9B7F458FC9073DD02378AA9B70D90A6CCBB2D40 DBF2F4E111C65F8F561BD2004E0DC6BB4DA203D79D11848DB7E224CAF034FACB AF3446FF041FD26C403F31A00DAFDB13BE1CE58B9CE9CE7056C8C2E0C9221987 8E13BD744FC4502135270FF93F8B476A53066B2BD1F7CA457F39B0544C993470 9475861C6B0324C3F9687C0BE4CED83AD7D7B2C2F6D28F4C11F9D61592E6C599 42C152B7204B81F5A64FAF76D0E0CE099F597FED59F4D5EF4947D7994340CA9F D5B0ECBC1B73207A06248B774140E38846BA0B5E6A7A8F88BE3DD277C768FD3A E0D289A8C87CD2F61150EB0F9F30C0745978D3EAF105FA555485877050AC1FC6 A879987588713AE7C38E3639A020382DBFD279AB3236401A954EE71003B9BDD4 95A51D4797188EDFD0144009E3381D7A6A63CCB6E2020F9FD86AB2853407D8EC ADA5D3E7B58066AA797F88FBA287F2C323D340F5E687BA4A08FEA9154ED4F784 5AE1650DC0FDBBA07F733DD26BECD42003F40058DA772D696C4556BE0B9369F6 3E9226DD203FF16C1B38DC8FD4ABDF248EF005295BC9E560598352D2645CEA9B 71A510701EBF4594B2EB118F65426DC4270798402797DB94124CD4079686DF91 9971CCE83DB9DC53A84ECB899FC619D275E7B4F458E80AA3234CF5CAFE573334 D00DC2F92631670510535D8AE7AE12AF46A6208F851ADE39B425E18B65C18072 DFC2816EBC7FBF5D9FAC1C787822B072B739AB88F7FD8DEE48114B45D0E30F71 63A174D8EBAB7C7FE646A6038F7F16A4AB483DD983E57C7DE881F7DBC406AA0A 0BD9B02F1ABF43F390CC750FDED74EB3AE170ECE0468D7DD525543C8DC07AC43 D568BD8749005E1558A811A1A67E2ABC3B8A2680A6EA5E930AA53757897CBACD DC223939F3E07B0BCBD73702A69DC8EFB34896ED2F80523AFCF9E02C37E997F1 9438363D34ED456DBECBC021C4F88CCC95D30F576C026EF40E8886D0F3E11E11 1D28CF7A48786FDC4B2B51B34F19C1D85D118ED41E89F184DD98CE91A33DC5E6 DFB4C390661562E03E83430AB585F4B1247207D22AEF9EAB794E8E2A41C8604B F905C3EC9857FF9D597836999560EF1940A7C64B8FBA9D6B81F4D847E2696F79 B71E7C5CF4AA19F65F9C2CD290ECEE979F7B373F74434D821545F78D295A4536 7045828EC0135DEC4BDC7E7D0E25F90BB531CDD88BB04D16B7DB32231A86B253 AED0F6E049E3601D8CF82B86E55711B1D0DEA05E40ABC9FE0F55F2366B0C2919 051DDB4963B2063FDF8C95AE22AD9CC6F64C78AE0927738CD56492731E54EAB6 C1FE7535949CB688B6D36F1C5D09077C6848631E7CCAEF6BA8B6D09E449DF25C A2E1CB85F5EEEABBB0D892830556D609B1940CDE70ED6C073E1F914D975EF7D4 B7E66E6B6998648AEBC849340619360D69FF7648320E583200740798B2FF1767 E8B46453E37612E7CCDB90E87FA3E1607228AA669263649808BD322EBF924C53 17F38ABFD0740A8A69D86CFEF9EABD0A01A4443B27CF8ACA8A29BAE0EFCBB3F5 A85FE3D3CEEC5962EE8E7368D0140A3E15DE2EC239449F64D7074D2F24215BF2 C71E142773DB4293FC234820E52F1B9E068E86D80DF6F08691A2B4B8694B584D D575CCBFA92640B644697BF687644DFB0E150FF04AE0FB6AA6FF6240A050107D C5F6E4316BEFF51948803156F7C4ADC3D40841982526F125F589D398FA95DCEB 80ADC11560465096F0D5C1C74902CFB4A04C7127BBEEDD068939AD1D345F06E2 D4F7D7AF180E8811716D6F69506FCE9DBFF3EE7FCCD96E745181B24847DC9BE4 F62B1907B0B7612A611578FB82916EBA3717F8F2912D608C4052D2B2B5DCC04F 50524A820AD3D2AC158CAB7E67FA96729A5C22945D5176AB5C276E883FD48294 EF2E1E97EB49FA82D566650259CD9686ADF6D285C4A40F5048BCEEA56EF3EDA3 9F541300644FBCE3CD5F2DD631C1908D2BBAEF439CFD86A577EEDE2EA6AE420C 450A6CF28DE4BCADE38BD15A4C5FCFEC295A2C14A7C99F78D75A7151CC6B5FC1 A95441D26FADF69B58B589B13D3294D6B4167C0A0D39B74FAC3DF4F78ACD895D 5B5B7F4D7925ED66323A408C417DDECFBE5E35527509682E74A9E81F208261F6 443716499B5131978288E6ECCD744F621A0341E400E99B4C4CDBFC764C0209B0 F602296E6F6AAC228282DB7CBD51AFF102A6C7B31EAAC95108DCAD3C97FCC0EF 52CB3B343B5B2F4DDFC39B9BB1D2B2C47955218094DC1374594448205B04F702 6B16F57344D3FABEBEC4387A79D4F135B92F5CCC4D713B1B3EE3F9614F9B9C3E 0E8CC8A1BF6981BCA87E341741224F10FA7A1F74B80D679497C47BDDF3F6F21C 8863E66172417B347E4E19F53998EA8202582B16CDC53906537181BC0640F535 BAB91426DECF471FA5DF51755B0875910C894768C252199554ABD01051380599 4C522244F32179A7104442577AC317ACC38287EADBDCD530C20159431C4BF2CF 1E2AECD88D0521C338B3BC44BAF8233A7E175E6B9DBEB9250309FB3ED820EF83 07F6FEE0A61FFB1E988DF80D11E3F0F62AD3551E0F41CD758BB904C88F816A0D 03D109B3DFBBB87536011EBEBFE0AEBD8EC4FA50EF20C2F256EDC1D7F0A3AF6F 8D10C2F7BE71F206CA45D00A6A34D2786EBDBDB8188BBCB727775AFDB3A49524 CCCFA7AABAED170E1E7EC4D28AADC153A5759830311FB7F25631A90426226517 4FFDD1EA98363A59CC089311D9601B398FC70503669FCCCB1B0D03AA4FA5BF9E 7C176E1CE75A2F1C7D9CFFBD77F8031E4E96C4EECA264B8892801193F1F701D1 573575F9751FCD28BF995E77AF7A72394C442329DE642413F1B647671F573E97 8F4BFB6FF576BEE0C8FB6F0C69A0F4E63719BC5D9568FA1D4F312048BE5604CB FE837ADE17F9D3AC9B443DCC48277D7BC9A8A2E61CF50420DDB4E902791D4753 720D284FFC5A720F0C4278E8FEE55192A28DD49B48A34E4DD203995026B34D2C 0175EBD90BE3F4231A3E28CA35702B6BC05CC6945D804B097D3587A1343935AE 063541A6B114486C87A6EDC4CC6D3C4A82729D3280CF29384F0884AA68954B83 237088C86D58AA5E443CE266681C94D1264207A10FF5E0D274C95F9190EFD560 F0D2D14090D2EF11AED9BB5B64A4FD4BE18DD7EE118DB3014E8F78E8298CAAA7 59C56D8DD2EDCCB625B528DF2C3F52D9092B8C16BF77CF463569F32BECC3FBB7 6D813A2A2E1BC4C4B087BA4C22588349E8DFE84FDC6C94924972C147757AF4D3 6A8CF31BAEC00D5A2F7C7D5CB6062EE8A5B25343843B7F09C001FF5CA1CD3798 03968680DFF00740CB879F36F2536BC35C67DA1ED7FD799F4A71771CC9465B4A FEBAF71098146848359D2FD208B9788F60DBF0E0BDEE9616DFEA61238D49290E C721F0D4253352B1C56387EC8D4DE1E70EE1E30E90F78402261895A74166D150 A82277535A5331CCC170467B469A8D36BC6860A525EF9269CC7A9059D7D29C62 73099824E6B3A08410BAD07601B75DAA79A58D295849BE35BE56F26846D62A7C B523578CB4210E31C61FC784B7F4BE773E78AA4CA142D1A010153F81AC1CAA88 E59E094516F4B8E1D3E183ED5AF7AE7970C2389A78362490379DCA0BD16B9C2D 6CB15F823DDEE982F453C151DB9A4335EDF95DB8EFBA8926CB1751831DC17BF9 9D44041777B5744D4877B57F7EC8D9B1C667F20B6536316801524451089EA76B EFF2691B26676E5B01F86B5FA1FA302FE1529DE451EA1518F4C74EE8215E50AD 386D7E916B1D6C46210228B0CEBD8BBDD8BB90D766DBCC40E31279E7FF519A1C 1B393AD1FAD738BE72E47D40743622A3EAA68B28BB62C816B11903F854FE9ED1 717FB82AFCB6C5AB7EFA6B57B687B2928790F99FEBED5C6153C4EBE542474433 4BCC7DCE4285D3109594339D98E1627C43D1CA82D66F24C0F1AE779D5A84929B 644F23AB2490202E9153756D806A983F4BD669130D7E3E1E112B80EB1F9A2E61 0A57EEBF0D421234DDB6801DA9263E5B7AEF9055F6DD2CA80A4DCB018D1BE7EA 4944FFFDF62F83295CB02931F2AAA43C70D153AC573842833521F7092F390F67 01ACB0D063567FF45192F96D62D95CF756756E1CC4E94AB7D316A831CCC87173 2C0B7DCAB227F4FC95D8F3FA706431B5E0C3361882544F21D5797E65928D1954 64E011ED2FBDA05CEAF274A6BC5F5B0DEF498423C060B386F010FE87CB44587E CDC0D322CA0C0CC9C7E153A463DCBC231C16AA8FBA2D9B893AD442F954391BA4 3C580FB9A98335AB9E28394775D5113DCF63D5A2531E17BDF5554EAA1D4562D0 855779D1DBBF4D065FEA1BB746B2D211A03F7EEF809EC999A7D32A8732505E70 9810C8A4249F87F455A3BAF29A3AAA820E4374E29736A960AEDCF962CB14AD04 06D9AA7722A79EE2894C690F8895F274A9BA733F0C1B7A6AEC56FF1238EADD0C BFA6B7A283D0CD175DFB6153DB8C3B8590421AEF02F8A549C62A9494A06763B4 0D9E865736B91F9022F7047F58498670C533F98E961872339A298A0ABC7CD422 97F0C48DA54EA126B45538584B14599634C6B883602EC1093166A010A740A62A 528150DF94584717C23C1B346D078189320538CB31AF029DB8ACD77DE35921AD A02E3C69497575CD8BCF5B94CFCB84F91CBBFEC7D01E5F1CCA520CBFCA1B85C8 8F4567A6D9569BCDCD573DDE6E78FD88851DB77C61E07C0236F433C69D64AD68 9A31B2FFC998689264B5C8EFA7AB4B41287799DDFC544838A58458B9A39DAD9D 9B30B1E5344F95DEFE5B32D163DF5A671333D6491B5DE96E9E2DB5DC475FA62B 0833525DAC164392A442D0A4ACC95BCEC20994B4FE363C32C34828BE8DBD7F06 EBB3B9E79AED47AEB5C7291EF28BEAFC7457B85C077F6FD1BE613365BC191477 607D6847424C8A25FC6D1F1D5C1E7255309102E1821EFAF81E6AEB3B9DB9D2AB 60490EA74D6E251028BC9C7C8F593319A00D8C1D25D296EBD536352653770268 6F575ADA2CCC98D3C393B046BAE30C833A6BFD12251BB3B5DA36B63EB502A369 3C94C87B26BA40DADDE1162DC60FFF11DE6FF88E1ADE26300B6EAFA3B4E884CB FD5745951839A3ED75436B022326888EF1546263EDD8FF7CACC4D569 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMTT10 %!PS-AdobeFont-1.1: CMTT10 1.00B %%CreationDate: 1992 Apr 26 10:42:42 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def end readonly def /FontName /CMTT10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 33 /exclam put dup 34 /quotedbl put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /backslash put dup 93 /bracketright put dup 94 /asciicircum put dup 95 /underscore put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /braceleft put dup 124 /bar put dup 125 /braceright put dup 126 /asciitilde put readonly def /FontBBox{-4 -235 731 800}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA 6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F 1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF 8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA 726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B 7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A 814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D 11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE 087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF 87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C 4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD 33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 A2D8AC44DDE818C4E23DFF5B846F412C1D28C52DA1EC7F6B68D2E63E6586EA41 0B01DFF80C744F65C069047200AFBD969234842863A2CF78DD48BC0BA686C91F 3B1382C42DC044F539B7089E055DDDE9E76F7EC4A120B4D8D3E14FEAD686B0F5 3EB80AD386901D788C51B61A9C04955BE06E75B24FB77F501D9937DC244B7446 60E9453930286D8112EDA6EB6291C0BDB909AA3B3EA0578815A4CE3AFC9C699C 54C86466BA0F2FC9BF260DB773E29B2D4AF20562C31E83E45950A3A777E06C18 0F29343F91938126514FB2B4A81C98E9CC420F54C8CCD614FC7AA290B7D42FF0 429259B32D92836F4B71D517C130240B63949875D2423339FDEB14B1F1FEC58D 49BC8B826DFD0C2DF5E94A4B4088A7E4029EF2B97B970A53A43F0D280CCDB41F 8F9F3573F522404F634212E534EF3B2FA648D9BF218BAFA1135F6800478D711B 9E3FC435C0D12C845F0B3E77DDA804A75EA9BE82DCB9435BF16A2B94CF7684E6 748B2BB7C5EB08C5728DE734125E6E48B895FF3483E07558714F68F2FDC0F4F3 D195335C8216499611CF9355764266CFB43B77B30E90BA64BC8EB301B5E2D060 B1C053E8071EE600A76C8309801C7927F77D1FF4CBBDB83573EAF13DB5588412 23B6F8EF8C388136CA0BD33DA6043043163E34E1B647A549136C33DCF3A816B4 BFF8424CBC2C9EA6FBFFD26B7789815EE0D3576FB50A3D0D2101D4C43C0F67BF 16984BAF98F16F7652BD26329516CF3979539C902F5BB43BFA0B1DE623E26CA0 521BE8F6908E249743D1F7E62350986EF4385E7E617B1EC50F7408CB18A0352A 9CF70E0FC30958BD6335211756B872801AA86C2F43801FDD42BE49F16DD74849 40E5F5FE77FF2948CBCC494E3D9259938F26C916EF34919924CEBEA9315B603C 5D618FEA13211BD46B019852FE26E305A4EF2362536C9FEA7475769262D3C2EB E4E5C2334FC9E57F57BA7CFB29AD573D3FC5CB5781419899DED8B473385280A0 B375271DC9550455D9AFE5171CA247F90902D62F65F84D05B5F65B8BC80376EF A0DA23DEE61AEE96577629DA3835F2D50C36D181D714E5CEA92198F4EDBC4A3F 17995EBCA8A6B3C86EFF6EBEA1991D3A3BC2EF33833103F462CDA92BCA15974C 49B3F1E7D585E056666A2CB937B7B49572A12E9953438F334B727200C9D7A86F F995C454EFA2D0A5B6043E85A5D282F6C6CEBF5781A59AC4DEA90A6E4F2BCC54 B77584E08B6FB01CD73D5BAE1AFB220EF723C9F99F0F8ED7EA821FF9BFC9D57B 1F84B91A3CDE5B158D3DB7D1369D51CD9A2822D4CCF0DB935B56CF3A52866394 0899E7A965B08BB808186D885D12335BDF0095C476462297D3AC3BE208B1CA01 54CF223348B87BF3472AA2966C208D7BCC2AA07BE712AB448824D7DE9968C6F5 7B6C957577BEBF7EDCFC01EE0D276501830548E6604D50E4C534CE727BADF7D3 BBEC9CE7E326DCEFF2B5908BCF60495C7CD9E47448434353363A82096FA9E1F2 1F8C780C4917DE4EC79CF95A42CD2D15E3D51BBDB9CD624F9C358390748A9A95 5AB4DFEB92EFEF7FB8907751FA44DA024FA91C6C064B5E61069B2796590202F1 2DFF657471BADB7A62F2ABCB770815750378DDF973CD4E11EFC3D19C27C02171 4AD74C3CC0B96793A7E0EB9A0AA40C7A6D426100FF3FECF3E3CB60ADA80DCDCE 870F74D04ED5B167D965F8AD2677298548FBD803C716488925CCBC9A3C515D3D 86C03CDC708D2F95F403008963361C8E7EE7C5C62C15DBE6B22C2CDB249C4445 21C8AD0C014BBE4B28827A5C84D714327904518E36EFBF4356DE0750B52035E9 2E06426EA0395C4852AD2ED3129F4D43E3BB75B546F092C1E7CDFCFEC2F00331 D9D0BBA5D76287C4CA7088332D5BCCBDBFD20B7A07DC6619A4AD3894C699B01B 045D803FC5E36061648DD13B6BCD95844E171F4380CA89F7A7F948715630A623 DD5E011B419FAAB28B814DAFBD3DA2EBC7B6CA635D62145E87679FC56843AC49 FF421EFC70F30062D749120D1C492EF1070EAA096E283CECD8411964DEA10390 147718F191A0A786C3A9862EDEE74767762BCB27D5621A5562EE1D22BE784FB4 0BEACE3F8A806ED5257A038C8DD59D3D52CDB4EBC501C13CC9DC9BD89A51CF86 B6C3F769C470912FFDA75C99C2EF55D78874558397C923C330CCAC3C149BA314 C6CBCA464B176721E9C04D0C08ADA8BDEFEA62E3231FCA6A646F837115D0F479 E51C7E509BB81045FE2F3DCD4A761E956BAF0561BCE5A0D20C0F1C45F40306B5 B6A834974281675F2A33F258B6BF7F7AB717FB72A96C0D50DA6B6E4D3EDF9416 6640E77C36BC882A09024789FA969E730CAC7948640EC203B610D8B02B0E8897 6E0395D5C45E7D414331145412115E3DDD7D137716192A10F8D1F6E134210034 0AC5572B33F6FD9D2B95D7D62D12919B23F7CBF114A5E1FF5C3C310CB947B914 E7729E00E22E2F5E4614CE226310306FEFA46DC9ACD671478C026A15FD6668D3 3562902F13842676E2A15F813364FBF3751A6BCA132596BB02DC0BCB18463F0F 28C1A0E1DD23BBAB471ED0A91788353A27BDB2D3DF7F547A2E401DD536417F74 5CF1285AACD4D96642200201BAB9EB201272A1D102FA7B4C293787CA1DB59847 482B209F980BA3107F7538C5FA1CDC5DB36C5F0A7917FB0BF90F185CFDEDCDA7 3B1D584F43CE6CFC46EEA3907B6E81BABC903DA628077D83A1F18C291729A92F 77607547D61D0CE06750F927EA4F37AA39C1FFA07EDABD3147228D161F0D0FDA 771EF1F476174134A27076EF9AE92D3F6DA91C9568C0E27BB954E27CA09345FD 2AFB9150ADB7AEE906AEE84C5375F25C2210D3F5A3C57298BE1B6AE3CD38DEB2 97904795D70A9F2082DAA0C6071AB9E8FF71508AC77052A242DF4D01C9139805 C2F5BDEFD7BFA42D3B3335332B37983D213B6F7DDEA6217186A93B911DCC0FE6 42957686973CA3E07AD6EA4895AAAD5D5CD878AD776FB9975EDC7EE3934EB131 37EE8F063BC1EBC11D807BEE136A31A70EF2A46B36D99B98B8B1B933F032FB54 B9EAFB5CFED5D813488D6A28250605034BBF2BEF55108CA0D6FF94BCB1650F91 99071E1A1B3B2F1E8E7C89A5E4DA1F77DBF6AA289D331C35C2C2BFDE4A391C6E FB679CA42BCB2AF018303A3F55EBD657AAD46815B45DD067823B4BC3FE3B4245 C9940627467C5F9AE0EAE53CB7CC118984272BCC5E1B8548494E812676FBCA78 A70C417C270EB6E435A6A75CAB4AE742B1194E3F9811A7B581D9C552A3EE5B1B 98E997DE7F74B3D85B46825B620B19357E4A7D82AE97C3B85609335B1B41A532 FB2F53C79A4064C88C84FCE693FA6EDB086732B6F76D31F8A6FF27DD850DD1CE B9C29258680CE73A371B3613F17A3533C5EF5D4E3F833E563E976FD58B381643 F097AD8D3BBD1E4F0C22A79F464FB1168E6B12E503DEE9D1D563B6F9B5A8D6DB D1FD6BF4A90DA086275F7F7AB784F8F945569601AE0499EFCBC5F5585A759D09 6829A9649317B8C53F66C083170EAD52494006623FFED560D382CE663A1B4BC0 D68B544A2D3F4AF0C1A6E50A4603CD433329F379B960A2E6822A381D91DADA65 E5D973E67820C6AFDFB917126A4C4C7CCE0C00EA9762059E3BA7C3BA56F739CA 2F89F58A2F058A78FA9F0F040A8B04B77F300343CEFEBF9357243118D9B62B83 2EC312A4AEBD8BEEDE4DBF3CBA2F574BF9AD66B43C19615961A00D70ECE67C17 6C93C248AAB0D3F9580ABDC833D52A5BE4A5C7F06C12E934BCB99C8D484A0CB3 BC75FE276F26C6AC861A17CCE8EAE60AD5E4573D4DC2FCE59477702AEA956B2A 0DB471C240961BF1402F6ADC61C3D7B72C78145B5FEB9853485C862FC428BE26 F2FCA109EC1D6F77284C5ABA95359FDB4507D921934DAF4EDE1A1071F7157982 3A9799E17F5377F27700EE7CB253ADB2371B228647FD11DC38F4FCD9D75ACC96 D6B5508773BF71AD6B9D49829D6872CE8271A17C6FC89994159850529D5A8A32 206A8BD5E688D5AEEDBE8E0195DFDD5ED07D11DC54131B7E22958959CD35E529 F9DB957C31AEA4F25811C7E0B9ADCBFCD7AE1BB84D65C7EB2BE322E245F50CE9 D611E6D52493244E89003784149E23DCE1624930D53B937405064775D2CF8103 66D2FE6F360D5AFF017C7CD773F0303CA4F8C9FD08B91E414546CECECC770884 87FA3D4EDA2E7D8474D5C30EBF966C9F40F4707E939C22779BC757DB50E9BACA 80E0AD329BABE0AABBCD5C1C59E80CF55E63F84F49FB24D5F8F953D028568083 015973AD8921C03794814AF609FEE8A5466BB982A15644C00BEDD08D351F661A AB6DE4FD2715935A73399ED21B074120B214C8E6BBDD346CE84E704A8DF4EB4A 73C5ACF8E106D56287BF82A4C04C8AD092B9643CC1512154D04AA5213EC06B2E 6B8A5452428EF353C92B18855E9C7BE2BFE82B568AA0A4B620EAE77EA0D60755 E78C6FF41E2503A3868195127619E97805A628A0348CC7C92C3EBE700EF008A5 86B6B5736A275BEB0431FD754D9866829C9B8218552737AE357B6DEB6DE5B17D 5D86DFE33C9A4C93CAE5DC1777EA1DD2D810FC772C8855B4055A1B520BB0EF02 9B1C32FFFEA106BDE7EEFD7C05FEBEA882C2FE39993EA2BB7CB9DDF009C08642 B3B12A2752F8F6BDFDFDF83B0F8648C309248AC9274C823CEC96A0766C58488B EF98089D39CFFC48DB5076BC1DF598C450E76E32EAC21E2A63ED2F4CD9BFD34A 23731B4BCE26D3500339CE43CCA5FB9FD2CE1BF78DE258A270490158921A8430 BA9F37EA3BAE30895A57D8BE8A3DEA3DA9E35E3AFB9E650815E81F9252427FBD 4B27B5C81F4F6D98CC7B7E289231FDEA58E629C4A414C5635B69B7ED30BD3583 2C0CE0A350FA686F91C11AC4EF37F651FF61BB9D087E42A7ECABB2073D930C03 E206ADC510961C03634984D380EE3604635695DB7B240CC9D60E31E684867FB0 C7AF5D477F96C24D377970A9B0431780F0EADC1FCF162245EEBB2C99946C28D8 E85A85CE650089EDDE2C11C224B3BBC65835D33D25DCDE8C9ECF38FC58D24972 EB715C666E5598E6F6ED4268BBAC9F99D725B95F81B3A93EDEAEA3B33EC2025B C944E72BDEBEB532A01D263064123E1514EA9778E34DAD260C3EFB820E9B7B2C 005FB6B60E44782CBB9AAAD0D84E2A7FB9B9A003B2E9C4BE6528537B909FA590 F2AE7CA038C6912DD59455C76BFA330BD5801BB94B2869F9F4011DC70BD31FEC A18F3944CEE997E9D984425D95C28DD02D8E0E0DED0D1FAF045C6BA250868E80 730180003EEE66D87118E677DB28B9F54AEF115FC1F1BDE48DC42BADB2F70A05 0112E3E69AE8F24E90D2C020131BCB703D4BE761B59237786AA2565B1FBE6F13 66F74844A3B2BD29F9BC483BF9931838BD701F8FE96B0751A3C2E93E326FF14A 037BED6C2D42D93E06082DEF985E39557D9A0A607D5DA570E084CE011B3F96B6 2F3633344FB5DEF35A48F468C019A9A881C036F095A4516AF9289085217C2556 62808AEB100B2D3D049629C688392CC8A62BBC7494881B5F64F71F6A280F86DC 288C82510A59277BBC18751679448EFDDB168F3BD63947E6C96897DDFF56A60E 747AF59AE10C996931ED47E0567A0FB1EB9C2A7F062E04CB75174E05D9571D1C FA2EFBA213E13CA73D9FF1CC4661E04E4D1267CF8E792F6AC270F03C38B7DDFB 9155F17C13DC7EFBEDD541AA9FD866F3214FB78FC78DFD68A4B8819144D9A28C DA70DF8489B06196672EAAA63953DC4987FE1BC025CFC38CAA8DD29A19E0B007 F99DF8D4D56FF048A53A5A4919256A3918ED9C87A681B168120E65E24EBA3060 EBB79FE24DBFCA590B47A732B5A84F68392E5CCD7F0AAF8AE46E8B2F7B9B629D 984BE10229CE058AEBF5A5625F3EDAFC37D75C087BBA244FCDA5C6CA4D02EA1F 3F64D397F84FE2AC9ED7D8F03BB56BB25DAFE7E691DC2F7F42B82B79EDA8111F B98941BF10B58EAF2D86FECA8239774A6AE2AF22F8A4103D0CAA22ED11E639EA 899DC81867C0E3C42F6FEB53370D06AF2975843410C8114F5C1057D53F078FB5 96E572702A18C71E09DD607BD6CCCB2CE9D3C84E9D626CE715805C0697204A81 DBB43CD0B952BCD9EADA1FE80EE1E24B1C328FE08783FE66C8A1F615EAF8CFAA DD5A57695ED5BF8866603CFCB4EDF22FB010CE429278CCCD13B39C7AF2135FE1 DEFED11CD2275ED4C51DAE380DF3CBD87A5502AB213D816FF6ADF4BDFC53F18B 1BA97CCC685B11BB417FEFB94140FCE2733949AC3E2E1D25BEB6E6D2E5D83144 463283C90090E110280FC2C220DA957E4F74568CADA115E02BA45417C09CC34B EE51F2452A50D20A5B8D532C283E46E6AFBBA38DECEB61836673F76E8B20FC0E 238CE894EA5EA7C7D0AD342F87831DBDB01586AF952CA32796A6276B2AFE3269 0A26B0D6473A5FBB2A7FDD47EB4CB0AECFE2EB581146A37B403EDF0E53C2F969 450DD44BB534B0D1F8161CB2B04FBD5FB691FFBFF6AEA8664FD8F776A2C328A7 30E745E7F8D46289C8CB4FCDAF7A42371604E47AA073B7200173E1D0075A7895 747C48506669C5FB8EA2EDAC1BA526BF2A3629C7457CECEC6D8F0296C2107BB4 AB5E3895B2DA8C0B2DD14E756EAE39CC14480AC37EF83226903389C6AE3A4109 C93577F97BC888773C24DD888767B11C9628204AA55DFF463AE17936E6BCDD15 F93C818EB1DF9F2664B1BC06BEEFD54A913448E69BDCBC969B7653B868D54B81 8934B0E26F35BA405917D207E2C02266F89261C2566261D204DF7BE4E4FD30F8 E5914FC6956A02F641A478DCF80C02A2B42BA2A326D2202673C65647475460EC 99999A568C1B4C259E3B7A16B741004FF2901AF4F186D02F44B0C6D3F53A6F5F B4066C137C8687ACDD32F7062884391D6861FF0543A377F06B4F85490F096A1C 6213247A6F0C7DFD5EF4940ACB1562927FC7EC5FFCB07A393CBF6FC21C94BF73 453B75ABAD9FBEDC164EBAA111108CCA28F219C0003C488A54BB9B2BF0858419 538058DEBA6C22CB17B7786C34D3F569B42D7065ED309A5AE6F8D457B9655ABC BF4AB6BA6BA1EB95AFE3CD45B37BCAAD8A715629142D9D1138CD3314CF2E777D BC790A63DD1B724741F23B4D3B39C2D3BED0023BD240C19E129B6CF5741A6ACC D6C0310DF5A560D7CA26AB6AF212131073CDA02C770A275F7DDED8C52D673019 AC4A4D4F036F94FBAA1448A0BE735C2CA1193B0B3795B3B4AB693C5B97EE0DE0 CA05AD896B47D71CE613090AB4B0F5FAFFAC48A7F52EC247ACC0CCB10A9DF052 6D19E742A514CCFD71ED7EC2C7D86118990C93748459293FD21BFBBA03C57C59 18572EAED78F8E0A39A03A7C8C1ACE30AB791FB6C477A4B74F21DBEC1DE8F611 B1C849F0A01F93C4E1D76F5E0AF2537624C2A263EE163734F71701E05D77C1B6 AD220682785BDE886373582908664529C9D081667C7354AB745600E3A610F672 53AF7D1DFBF502594B2B50194406F831251EFE156C063B458BD4F42E7DA02833 23CF0005BE43376DECD1A306F75261D6248A6DEDF5F56AFDC8CD410BE0213C4C BB9304DD363D0D60AB2B2D645A8ADAFAC099847344A7C010CD16E61236DBC4F6 D9EA4FB7563A01E3F799123FAB7977699D1134E49A5E079A69D8E9296A062F30 2F163064A215845D0D65B815FE0082852CABE0481120CFAA3B687B32EECA8F62 CC327D1D7BD071F9945AB8B9539AE8E8C5A717FDA594DEFE8511BBBAAD08D7A2 4072A4E4ECA0F3EA8FAB76883439ACB4727A36DF72DE574418B13CAEB099E9FB 466DED499B8E01942E2D6F72035222BC90E6BBE16ED4FB2DBEFC64CD371A6FE5 97D70A6E6319DAF2AF90064B7A240A6B11493984E63B84DD3D59B4243DE9160F D2657C215AADB68343D6ADA3268E20CD294301ED7C46F137DC50B152A2718BBF 8EBF5880626E9DCA1DFABF1AF6828E8D5AA9150BDAF9701F288F864D8C91E976 9E9BE865B6DEB2796C6C3FFA603A947B9F43790A98058936B3109610B502B2C2 320E75318B535D194D764C0AC7A322B5DD0D4520F96036908CBB808212A7B27E CE14671E77725B8EC619C68EB5657863D3663208D21318F7F9415B93B1E72BB7 83612E137E85645CC4A1327859818781CB1DF455AD4BFC77E49A90F893179F5D ECF976993082E64B63ED0533008AE77515453DA9B07AB2F1F0B1CE816E6E1D4E D0D7A445F75F126538FE849BE9A9CA6BF221DDF53BD7E9A45017D919A46B9287 1D1D98703C6622F41A997BCE4F77456A23418E6BB7C0F9FA957FE88A449DBD23 D713F39CFB2D4A639AB99409DC6DDA631A53CF8F5F617159E03BCBC89C688A22 971129FD158E8AD10D39AD3D2E6A8A469BB27AB8F929B28A3459928FBBD0C33C 4DE82E1E1DBC8DDB977706FC4B5C14087456D9634A65BF0C97D5C49593350CFD 826633734D9B96E850FBD5F3F319ABBA61397724E8D21B14FE56B6367ECEBBE8 2D7D0CCE1C2FBBE5817C3D60CF93CAEDF9886632B27DA37F7C1A0342911D160B E520A5D20B4013983021365E2BA6792766B0541F3262A83C4E863A94FAE921E0 57EB7E291DBE76944B7CF7F0D7363681586B405EEDD879BB508FA7E4203C8854 44027B509D69E1CAF1BAA5C1A239999E190C7B91D315AA81B289FE88E5C43D0B 251FAB17BBF7D49A71F75364C6DCECAC2C22ABD8D215AFD535C9EFD9629F178A A75E11332FF6B05A4B1569306E3F3616EE35D8338F65B6601D3535B2C6EF7EAC C71EF79C4EE2A862A75531E4131866D6836F7569B1659A734F35C78FDA7F3DEF 39397290CF54AA9C263E7AEF736798672CFD722612716938391A1053B727C7B1 BEA9DA04AD5B47C42E7B8A53F98AF379F3353F0FD438D215B517A69DB1CA5F27 B567D55144197A840F0BCF876AF832CF3F620A1E2EB286E45794ACF216062F88 D70270FA4453AE510543FB2E62CAB84A3BD7E2F5881B20B5BFE7FAC1125F075A 84070D639DDF28A73E73478FD27FFDDFC0246B3AAE90143AAA71DEC5E440C660 857432CAB7E1E0DE1F6ECBA47F0E0448E21EA69126434DE576DD22996B9C4671 1B5B07B923B59A56A39F22396B2BE68B14283BC384F7EC76C90DC17BF57AE82E AB5BC5D2F39C916F68167A22824BBDAEF18501224005E4E63D8A357F85CDAC2E 1F7FA28FC65DC65FF10059A658F64A06E98152D580385B2DAA906ADC3840245C 7AAA12C0945F8E14BDD097A4BA5F2BE5F6C1704C256FDE77DE6671FC25B05400 61EB206F67B7C752E406CE88205485A27E626161E3FFEE0153BCA76E4F474E22 57DECDFB9294B874FC26D354787AE7D53389C77AFDF711FA5D7552FE3FCFA9B7 DAC7564C749913F4020389E4C7F4DC4FE13ED85AC8F57D0477D752BE1722B02E E2B54C21DA7A976EAF928B142D2E0A5591DCF14420BABDC027E06CE3CE027336 C20703A85CD2D290AD1DC4D347A05FE5E3BB87889B74B7E0CC251A58B2F999B2 F04EA13EF3C6CE11D6FFDE47712BE6C84428E7D95E26DE1BC6142876868B6929 A8F88012693A34E2740818DE3FA7458EE6160364795A3DF3CE46A3BAEDB5E361 B1BF48DCC0B9B9045F65A4E9D61BDB537FD76AB51C39CC123DDB09534FB63C1E A5F85BA1DF0EC2736D029EBBFA7D935A20B087832EE66475FC2AF6E938363F3F 708949FCCCD04CB56E8A00628106F12D7D6B31D08D8A047C5B9E39F4C8F1A7E9 8A06D46ACF7ABE91EF88322FC5C8346310953F9C61CAAB6B8AF4C489447D6A08 125F9E06EA30D6B07DB76E305626581D69929EA0B06E104674747A436637D015 34A880E798BB653C9AE9E8BD619FFA875FDE8F488CD798DCDB0C63532D0D1A7C C866EB30FAE071B43C02EE5C01198E81CADFF0686839C2D44FED8257A2BE9E88 32A38671E067BE2A49D3BC5C0E7893E12A04355315FB0B46EB033DFB8C101EDD 84749263790C308966FE76F6789F21CBDF83A280C6D6FE8BDB669E2F30795E46 C6EDD896F762C9F3E647BB51E43A7BB4A949F51D5599C25DB872F75D72E9BBA1 616BEA9E026069F0262868FAAA16B44DFD016F80A6DE44A4A69B5AA6AB8C0424 C2932BB816DF4F7F74145AE2A0CCEBB71DDF61B2208823E42D3AEB663E3206F2 340F7369C6645397100FE513FDBA478C5DE5C9A0839B5DD2430725529939B414 89BA91759A62625E40B92E834A9EFB3C68005876010F9CAA8BABEEDB06B6A554 21609C50731E2435361AB8F53BF71B878591F8E0BDECC464736D96271F8872AE ADBE8BE4A26B8145480F7EA4AFBA97EA46F6EFE3A52A20711ACF947EF3F8B580 500DC99468972BB657E57245D4FC01F8665C939D385BEC9126193E1DB54E1078 042F0B0984E812A44726C4B369EE9CE54083A417BC8ABB50A6F2B185E3B8BCBD 53A75936812779305A859E533617E5192DA6C3531189CD57DB856B29807F383B 530DE0218926F7A6FFAA401D3864931FDA344BDA891E32359EC567739B25CEC1 A4C8169F251ADF4594215549F7F225DD1F20F1269CEBFC88CBA7CFF4B7214B3A C111FE9B511A8703810E222406D86F41996815618661ABB2C69F663AB97797B3 81D7BA0172D90246E5B076662ADAA4D2BC8FA1BDA20F13F9CB5A70465667B32F EE2A1FE5DBB8BF41ADA4B7D3970DCE1972508929AB078E35391BD8D8C0FA2FC9 A0C63973A0236E7582D4EF32D3213BEC05DF0ABF760767CC5020B609E8225CAD E64A95D1E7D032833DD90ACCE8B5E40A3D57D6D5F0B36617644E83AD6BB70DF0 DCD7D9410B7F47763F7FE5533806A1DE39BE6241C07B2BEBCE630CF7550B1595 81EE53E4C92D15FE69B8591DDA933337F7F789B3BBDCC5526B10BB959E76225B 2569292E55B90B4465A44624AA45A4327E23650D4C9A941E8D86A2D619CDA196 EEA705015C6EA8330D3C04F293512955F38C4170C12D709C55A2832C58930C13 D9B37FB7D4C8B0FDCAB5BA07FFBFCD805FA6089DC09D2CEBF1DC3C894CFD93C9 9BC945C25591C38596062BCF218F28DE9B4EE244182FDA170A07A7A6CFFFDD8F B08F7AD8857066E582F48C596F3C3B3AF67294D1C45C5E5E6C2B7BF67C8AE472 79835988AAB90BFF38E234EB1F49E67200F77BA40CFE10463DF43FEF5FB13F1A 7CBEDA0B168FB8DF78C793CE54D309AD9212A1EB5883C5FF17CB637390D2DBD6 07F05E04CE60D3211C1A32304D1DF076EFEAEE3ABA07DB78D9C13F58FB5B3DF8 1A92DBEDB9EA5C55E3752855AC1225A2345D3B9E37F4068272AA3E465C74D122 782864FEC675506304AFE1EBF79D0972A652D452FA8F70F9C6BB5F7B521E534B 1EC7CC493DE8D55C2F0007B2204D1E59383FD1380519DC4E699BF7AF8D81DA1F 8B0E9626F17C2F620117230E9BF7C4A58F42F8CC037182D73D7DD884A04E0C38 C9B7B80589278B76C2C858C9735A5816A0CEA72F099E038895151004E1DC8CBC B8D53BDA668D8F985BF4FECA6E8646042DBEAEF1AD6579B60FACA93175F3DA04 40F034036E621E1C7F31A376B3765B285B7E4CA83CB8CC1014658C2004D777E2 2D08F4B307A0E63DBB23B21D2A49101BB7CEACD2B40A686DD7C66F4FBC5B6163 24F3A4F48706C45D54FE0056B5C4E748FF43EE41D34563867E41D8160500122A 2115AB57213917F5B1BEFFDA531DEE363AE61D480B05F7F2F440B851B6CE6265 2FFA0A0FCDACA7C1FB9948A63967B3E4E106A7D2194844E368623FA61D327321 C0949D6495FD37433D8157365435FC316539671407676D347F7841CAF39E315D 00B2F5878D64D0BD920D3E418CBEBE3EF5717D509F0AD20C2B9BF8B481F8D7ED B1ABF3595255DBF1DA8AE4FEB4EF00FCA5E681AC5C80F71ED707CE5B6D0DD8B3 800B87042E1CA1C3FE1AC461FB47E7A8AF5977DEDEBD2B1FAE57780342CAD7B6 205770B6D14E8C4387DF27056D3E3AD60FE0811A1F9D2D7DFB6D1D52CA8F8E6C 3EDF8F78AE862AF1D75546E4C0C624CC57A18FD61968CF742FEA4B45C758CD53 78DA3A32960328BD4079C7280F19AC3FB66D24DA8C9235AE7ECEBA537F09A958 F5FD63C4E3A0C49F44F8CB0A828D2A7DE24949138C7206354D6BE8CDB99BA5D7 C60CB286AE290268214AC0A0C3F775BC92DD5326A100CF4842EDC00AEC236CDC E4F8F8448596B7E59BCB5EFFCB7D8C90837FA5BA690B9FB4D4F24BE0EF5EE864 717394793E045BA233A7B146AFECA0664577795ECACF06E811E1A0147A38A3B9 2941416AFB19B4C82A73921AA970B08D68818AB2F159E527EB7C48B64C43AA2D D5DD0DAD15AD0161667D273BFD59BA13D7AFD709F43DA9E1E5B3B5CCFE7EB38F 08DDDD02CC0CA2A60CEDB070D54AFD8F8EEF0B460E839A2904A8DE16CE73F632 3CBA9A65DDC7DFF06E5FD2B074A6312D01F8D75491B87EDBDAF045FD2093AE79 0C2CDF2CD7677D4639E412812A7E95224C3995631589DCFB5363C82E7D1F66D8 3224A7172E5F0DBB88275EA86428DF0D223AD4079C9D233CCF7C83D3D488EA8E 0D1A5710DB03D00B4729E51803322DB1C649D2C0FD6D3ECDD66DF8EF0FA80B1C C447EBBAFFFE5BCA6262F252CAA42FDB90837425645E57637A4FE5DE5CDF423F 85E41136A2DB6EEF9FF48965C73E07A1FA4C9C0DB88E5FDD963E55528C8986E1 030CD62EF13B3DCD4936080F90EDD2CFBBC294E666E0D78D448CA04113EFF2D9 C467D9E7616C426F93C1AA8C3D31D26B2F14C4B1ED42390E613B4881D137F79C 07A1E8874FB91F8C3F561945FD8903D4BE99F18212E8DB95BE4220E57876DA3F 5D502316602D0CD1B1121FC930F08BCAC9D6E5B9ADF80B3C1CA1215756F11ECC 7D2DA3D97ED094920C38CC4A68D7BFB6F75E8431A3840D5845CA8752F14AAF8D F5A80ACF8E703D88EDCBE251C10238BBAAA923DC490049E76DACCD2FD320C349 7FF97E3E2A9EC49C5EBA951F0EEA06D48727CCEC45DFE86D667725454B700F97 06B1A6521B25A0B5034BB64EFD4C7AD11E83F24BF7ED607789A1AE805881E4FA A5A8610DB42BC7341F81D63CE70A7E37715449BD850A4CA83A0C0EB1A33A29D3 82630F9F62CAA98AF0AEAE3E0F450B925E24A82907A642366EF798CC064FF67A D3BC3D3CF3BD23641A91F2DB09680BBED2586A8869FC8015134901F7F4684B70 73E4D6A466F013F76619BE61A4B9F66BF167EA7FF7DCCFDBDDE96DE78EBBC0C4 A4DAC9DE8D709078F4C134FC1BBF53315977ED4C9C41CC4A02026E4C3443653F 39B23880391A2320170337F211CD83794118E5A014922CFBD8482D88F5622059 3DE77CCE12C636241FAE4F5B91EFEBEFF1EA36C91465BB15A49EE3202451B862 BECD7D819A56F7D7E46F981BD96FF1FC2587943D90F4B0F7B4C6ED4B76D6050B 01C551C265BCFADE1E2D72A0FD4C8AE9559C7F2723769B1E3254E33B7725321A 1E57D149D9A3091EC5714180DD68B89D7BE2AEFEADCA9585069CEF9D5FBC51F6 B526E00E168E72F5CC9A70349DE30D46C50D30536821A4D988488C72AA9A8E87 52DF5FD0ACDBC377A37AB3140D89EE5803A70886696176D2CB7D226443866046 174AF7D525A28D851AE35BC42A2FC7EE4777EFD0E1650F7BCBEF9DF1AB64870B CA1E15C7D67B3FC527B86723054D6C1EF1A869A9FCD5244D0BCE4182BAFF60BA C7DC0ABB04C31C92741C14627D5ABE692403C6624B6CA64544E905B11C6D8FD7 1F28055E4BAA5CB25996FE88F502742F42E11D087F61117F9730652F493329A2 453D9508DE874DD92BE4185F6A7BF99E562EB614DF01385B86F6F271F355FF1E ED5A84D534446E834B5435D483DC20A729E81CEB96EDAEE53D2E431BD905046D 712133BB30F33DAF2FC62BDB3A171BAC8E33297C08360CF255050DDAD58DC96D 280AEE9F9B66D2D8806E2CD32F8A08434FE91B7451AC5948A1DAAFD2D28CCA24 8184E20D0F00EA9F2C663E7C4ECA2F9AF6EEA56F282AF32DBD960D40D4CF055F F33D5C25602C2D6040BDAFBED1926120464F183124F48D34BB54A06A6724DCBD DB2CD715999302DA068272B4E5742DD8D017E604C4114B1DB529A841F633160F CFE80EA9B3B52B940AC0F685DA509ECA4B420A996E8488933EAA721B562450B6 554302451C9AD6A56A84B85EAC18F03535099C8363599D4397454E19C0AB2A34 9EE7A3C94165E396B9EFB97067315FC4762F2BB4EFD7FC635FFF0593528D9079 69A5556D34927059A46525E6445A881CFF4B5B790ECF680068973A47EB6849A0 52B9F18FB039050940EA4F9B51A3B9A099F33147569AE9254322ED47A6C7612C 46EA207F0A0FCB785E1DAEB571BB99C97D296CA1DE3838CAAD06A98FF8146056 ED014E14180D505B17AFAE35F58696C16D8C46F13290F1600075A363489C9D63 6CB4DB7FDCCF49E15B6825CBC4E04A2D6BA136289D198E2C851D794A9A3E8E45 7790862DDC9EC0D12DF50176A194F39C7C13C88150D2DD1208F386BBA3B0FC1A 77F94819F12D78D5C59139A1DE0F2DFB3A7FFEC4FC38067455003968A57F73B3 6C15268401F75B5C843D46EC956AA677A8DB075B61E547DEC35A63124769324D BD64C1B1D38777BE93F60BF4D92C85CB8C9ED2C8A77EEE0A4EBFF3A44F237305 EC57E50E3120CFB0DF8D573A96A740E1260A26C3174AD869CF2EEB226ECD812C 480D45502C3A4BE2B4EF9A8EAC7DB836F0C843971067F690B653D9C722655066 D113AAFB04FBDC5BCEE0FF67A38C1808943882E4CE60A6969939BEFE16C09B59 CE50B529C3BE6377368C3E827E9441D96BB174BAAC8B518671E3A9B95D4F1722 A26F4FFF48348CEDACCC4FD98F71147D0B760B320705C1C13C9815E2CE82C5F9 D6CF04C81F1BCB9F12A188F9828498C220C6DF1738CA9F236B6D6A01D747BB6D F322F38D0D60A2E07E0BF1E259214C3F3EF0A72074C261ED09B05DB3915D0835 B2BB52B6ECCB04E712B6BFE1A0DA7437DDD8C4C05CA45B1D5CA17EA99BCE6428 7E635AAB8F2BA639F28C52CD0800BC348990D0E3832B0303A272D6C99D8A6044 C5093A422D646898EF85ADB647544B2CE33DB5DC66717506CC90ACB01CF58830 D50F4CF7BACAFA2311819C3F50A9F91249C624EEE17EF5752C6AF77D6B852703 81F95A42593045A69334D6DC1280384CDFA0D8088D97332FDB06A02E5DE9F962 1B41C68A0139BC5F03FF841D8E93FAD2DC08E645F476034919C218693989244F DBAFFDB4FC0436DA9D43C8A2D55CF8DDB0E7ACDF9D564BCBE38073E74D65C8AB 0E89D87275D680F0FBC2389D1AABA196474E26BB4BA01527A72E554C29EDD3FE 7B17BEF3AB22F2C7C0EFA69C708C36CDDA24C38A845EBA9E9A3E6052B54C188D 2743EF1487B6DF0E6E622A697BBE91D5627DB3F32A57C0AC98368FE53BD09844 A326B096D01FA3547FAF440D44E079EC0EFC2A482B05052B2D57DA79B8B811E6 DD9D0E46E838F1402F32EC5FB127DF771049F7B79BCF62C14E3FB4D6D7BBDB80 975272E6DEE0109857F51D57E304B74DE4AE99ECFCD0A40E57C5E51283D8F270 291665EE714A6596DBBB5285FDDC4B6328BA6745998EAEF40EE717C63AEF8A59 E87D8E3AC8161B6638FB5D0963F8795587949FFD6F58C5FD18741BA3483B7FD3 FC31F188B096FEC566BA23ABC2B34B79DC293909C9E8393AC9A26E6538672756 3FE2EEF3E04ABA6D344F2DF359AE718C7D0EB5CDA5AB3D09C62C990BD5BD7E73 3F1F8AF93ED0FF3222D7411CB9AD3C3AE9EDA04DD1AFD21A4653AE6A890E6C07 1607F1668E4B62730DA65DF88C3C63FD7816C32F26D21A87522C2097BB925D92 CBB694A7F77E91F3FAB14D0A493384DF902DE5D5F4FEAB5F5BDF567878AC8B4F 98FBFE8FD16D07A58E2211B87983D40D5CE6349A207FF195B7F09B914CB6D688 B103A5206380A90713D3C872EF8C026D2E302BEA473BAB705DE58D802A47C249 9C40EE6F20398E591A3878D4A9DE9F6EC097521DDB694503AA8FE3BBCF24A5FB 3DD6CCF1247B5D9724508C63A3E107DE56F0802CB083399BFC3A9DA62E7575E2 58AA589E85ABFF222717335997260A7F56965DE4DE551885BA8A1DAA5C97AC34 ECDB36FEBE3D8428A4681871FEF7CBF2B5DCFE747550D296B419140C39EB3AD9 D65B6146705DC3FEF0131533283A100D9DBCAEDB8A10CAE4C431136FD94089D7 64402322603B7049D4D10F97FD54D03D81B7B134293004BFB852D50DE5C6C5A8 29F3FC4855C34AE134EF939755B88270B114106573415FB185E395F6FB0A4698 B105964A9F374AF011972D67BBE0B3CDBBD0D9918A0E0D2653726C630FC8A63D 7C5BE82A965EDC1E0A57652688375FA60463EDEF222D4A6D726B768D8EA06584 BE7D23F6FE42CF8541F4BCAE1B01C73D6500207B211720DF98B72D016CC513FF 9109B59C4DBE5108CAE19687C1682A36F39AA8AD09C5AB7D69A13EB0BF2F50A4 0766AC191B105EE28BF0A87862C377E47EDAA69F99B7793F5F76114940848E50 CE05005B4E2C91103DB7BA7BCE79755E4324C0D0305EE203294CC82451EF3780 106156CC6C6BD07296CA7B927B869F8A9755CF9173F22D30EBD3217A98616E3C 8525AC8ACDB07F9311558AB53805673411836886A919BBB916416DC1C2061CF7 448ADED96B2933FD25C207BD374AB495DF564F25554274A3D2129CF7E6562F56 E3D7234B8660A536DF464418BD08E3DB7CC2A2A8B80A0CEA897505ED6367A460 3B6C0CE70E7C5F482C6B3FCFDD8C8266E023C421481CDBD041469219AFAFF611 97F1A2D6B13A90A76AF1FB2520D973DB1CA53BBB11A81115605A9ECEB0AA60CB 972E5FC2C431F1A5EB305D09C8B4C6D5CE1E397CE7FE9DA819F132192B2B91D1 2832F636D75DFC3A82143BDEE17461D536B13D21CDDC295EB617AFD850D59356 7172AD007B843AA74DB797099AB440C40BE561612B4506A8E26D1C4C5A8DD4D6 2B8DA07722FA903A6ADD179E0214071F1AA8A21022283E7380AF0B2656DAF629 50E8EB7C686EDCBAB6E56C5198041DEB47AE8BCDB4C30D318D2CF076491894E9 C9BBA0C6D9DC4B5962350AEF5B9DC1EFFB0C9B8F562660D677F376B2279089D0 294FD57B5ED589C1D28C6E9F02C821134A221334E1B4AFCD618FD86BAEBB31CC 28FF741E785DA99568AC909B091BDDEA56D6E3B75F4307E3A989C1BE6C92546C F518EE6BFA37355BF3A752C26A014FFD48B98F7C1B11B625A43E677DD04B16B5 B1B5F666AA67EBD602583D810578ADF8FBCE669C3913DDFECB2F64745EFDF7DA 13E21B44417230EA477D2E13452EE0E048FFBC3B3F3E32687948361AE63B2F3A C2393837699C356E580C995217D2BCADFDCCE3A6276B86DDA6DF06884B153369 327D3461E0493B6CDAC5102E62040437522DBA5DB6B6A4B30BE8AF1E9AD4DA47 AA79B1AC528F44184C40B9FC2E402F602FA679EFBF9F374BEE06E6332B112399 D18B8822C21B3B1DA3A84B31023D39508C1F0C97CFB05298E67DDF6EE891E261 67C5A17051C6DAEC3924E7E9FC00C98225CCDF01D885724122CBFD1354A59CC2 35EF7E987F633164341E2074B26689C6797F81618EC137BA7AE502904A211920 D7FA213A6F0BE82D49F7237690413AD381F5D2A3BB67D027C48455F48E717DCB E1D0ED373D62E180BF0AE16B91605EBB768E97242CA8DB982AC0C2DCFD4B5EE8 95BDC8910A12F20439946D3CA70A5F67A62B82BEC253FF1C68B1DB9BE887923C 1B4F803DEDBC42CB12082ED81E92F657D30E8652E76C6D93B1C7196BB77C0DBD C2DCB9E8734272157E4BD32B57FAD22278DF0B98DA7ACCE25626F453E8A7387E F75FB71ABECBCE09E6D35C7CDCD550EC6907A8832D6831B8F16C6FF757E3733A 3D028A0456B64C686A35EFFED2BEC9A9A1D93E98745DD6036FD954AAC48ECCC5 470FE468CC4AEEEC6D6E650378E5561990EF37879B517DA5D550B5DABF216D27 26941BDBE7286F95F3DB4673BEA513C8AE8FAABD78ACF6AB6918308627EE223A BFCD0B05C18134AB378AA07512D71E7AF987C925AD05686B6891EA8573FD13E2 790918687BD4DA3C12A9E0F33FCB6AA2BE3E3397B970E80338E5338F0F603B86 A42FA5A6285CDEF0739EBEB1B9133E86BAEE66E1AC48F83BECD4FA2CA3F1D5EE 8EA02DA4925191191A953FE68C13398E2D80796714C07FE16CAE171AC6BB0870 0AA402B06C310DC99F0A07669C57B5292530FB8DF265DB909A86B8D076468B4A B24AA398EE42F29BB41E7A640883F9D6021F4CC7E949670DACA3233FFCBD64F6 AAE2DFBB7B1E69F24A6C0A8D86081B2B09270D561B20EAD4D6B1D40B7F333A0A F1B2E915DA6709BA159E81455907510390AE7C870A4F38BC8DD19149558B9687 37B0777DC5D7964E3B50F4CEF6EF43F38BE9F01A68B60FBAC4BEE09E197C2554 C413B003ED8D8A095BEDCB291ACC0FB3AEC024D779BA9D69FD3D0F5D105F95E0 EA00C1483DC52F2A37BDD09F1F416BF99C1299784AA46D36515387FBD61C1C27 A2B6E55C6B086E87B32921BD7441F10E49DD10D7D82E81AED5FE4C5AC09F617B 9BEED75211D3FED854D9414ADC9B6AA0529863DD90FD48A3F82DF1F7C634D83A 261AB18F257A389AE958DC7315251E670296B0F415AB99D1FFB56AC1E7E61BBE 0DD2A5C6DCB7E270957BAC7584BFA9A6E21CFB293F0F51C58199D2EB431037D2 C44DB61F55B46B3F034CE7127628B7A3549AA2CA1FF18DD7AECFC4EE7B3AEC3D D0A1EBF2F7E045BCF177FFEC6A32B8BD47EDF924EDE5FAE04FFAE9904F4229AA DF5B82485C624F0B7319B147CAB299A6FC7EE302DB985DACE5B13F8FA8E73504 96E522B8D32869418AFE99B2EE70F52CCFE638419454432B9688E631272806CA FDC72B2F2971931F3D32AEE7B8979EF969E122CFB6D7AE0C314C3CF64859DADA 99AF547DF83E7B74AC852752D25B6EE4A29B6CBA28CB35FDCE44C0CF816E1420 9456518D9DC7A31DDA813F7ECE178F6C80A53010BF2272F50E93F5EC18E91D6A BA5DD888E1E9FBAB51276F78875DC0E6EBF759FD1C92A7D9E86D57B9632E5D3B 823FCB477610DEBF376FF0DAAF01A47E0CCBC52F0052C93C35EDAC9BD26C0CC6 5D62756F5476CD1BD7581567F55A6F04352AFB226DC7087F9D5B254E454126DA 1C12C7ECD608698A0B2E3595CAF63B8BB3C1DC9AC379FDB7F99F255C8AC29A46 AA322BD508021592969A16DCBA6959C5B92D0510AC400844405C810D6E34D41F DC8867E6A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR9 %!PS-AdobeFont-1.1: CMR9 1.0 %%CreationDate: 1991 Aug 20 16:39:59 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR9) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR9 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 44 /comma put dup 65 /A put dup 67 /C put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 78 /N put dup 82 /R put dup 83 /S put dup 97 /a put dup 99 /c put dup 100 /d put dup 101 /e put dup 103 /g put dup 104 /h put dup 105 /i put dup 108 /l put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 116 /t put readonly def /FontBBox{-39 -250 1036 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 92A36FADB679CF58BAFDD3E51DFDD314B91A605515D729EE20C42505FD4E0835 3C9D365B14C003BC6DD352F0228A8C161F172D2551CD1C67CD0B1B21DED53203 046FAFF9B1129167921DD82C5964F9DDDFE0D2686875BD075FC81831A941F20E C5CD90040A092E559F6D1D3B0E9BB71733595AE0EA6093F986377A96060BF12A A1B525CD9FA741FE051DD54A32BECD55A868DD63119A4370F8322CCBEC889BC2 A723CB4015FC4AA90AE873EA14DE13382CA9CF0D8DFB65F0ABEDFD9A64BB3F4D 731E2E1C9A1789228FF44116230A70C339C9819676022AB31B5C9C589AE9094B 09882051AD4637C1710D93E8DD117B4E7B478493B91EA6306FDB3FA6D738AAB1 49FBB21A00AC2A999C21445DE3177F21D8B6AAB33869C882613EA6B5EC56476B 5634181ECBF03BFEDB57F079EACE3B334F6F384BDF9D70AEBD592C8ECF21378B 54A8B5DBF7CB9282E16AA517E14843909339B5E7C55B038BF3BB493F3B884A1C C25F9E8FB912CBE23199AD9D2C3E573727701BA301526C66C3617B9514D6F11F 11930B1D97C17816C85B1BFD9B973A191B33CC3B391815AC46268691C741B2D4 48A840F1128D9B2F9CF07D0709FE796B23A836417BF7B5B12D67F74453C82F5F 25F7B30701D6F6D4F4DC623C0C27D6A6FBECC7312A3CD10932FC7C10851C3C52 24B75DEA8A648B7F34F5711DB0E843C914E25663C510185BC37BDB7593C1C259 21D8DDAD33982C336BF272BAB2F48E68217403FE9F54877B243614A87E64784D 2796EE4179FBF96123D1BEE3EF89D682B427BA4F12A1318A57F18BE5DD903815 2613667F0F25922C8476E353296B5FC2300FB8AE7CE38FF3CE3217A905E88E03 E2B4A68A22673EF30CEB2393FDF6387D8AF7EE943A23A81393BEB6D7033E6D90 A1D645FD1BC4965E6441C6336D5389E0C8EB790F1C97033C7470D8809199A090 63C898472D46F75F3990E561489CACE837690C938A7879B21FBF83AC6E268CFB 03AFBAD3FC5281BC608A9D7B613DBBE356BC7532175E2F8598E647D7F4947DCF 1D9EB823F13E4AFEB0BF3258692EBB2D2F11DF1396852DAD24650A51F63FBA4B 0F74B5294F62BFDDBB56BCD47A4428CD4F2EE44190651208DCB3C6E437971971 8979A4EC9F636B164FE1389FDC539ED9283B76E84266BF0E3EFB8A3C54F52174 E5BE4FF05E7190E4B3655DFAD9FC974681FB61502D974A70BA8949CE6B6D1659 DD840F16AB744D39C53B0753C4EAAB13EE3818898A0DE422FC8A6924CCDE45D7 161678E8F9F7C8BAC0246476A83B413ABDDC8033B5D1BD7C35E8701F0DC63CD1 BDEEE0FEE322C2CB2DDF84D10F97A24FC79E8EFCC492807B07B0E9A887B976E6 820010C4293F27C8B075DC9D1AE3CEDA7BC8B9EC9BB7C4388FD3A78D48FB8556 E49D309C8A1DDD38A1A149E6D39F7F4CC7EC293329B22F88598229196F1587F4 12D9BD35E5FEBC0D2A5813944E6651B7C4E5150C4D7C8AEEE4410F818B70D8C6 CBEFCDDB9B8F47B81B0C15A3054923057AC6D244EF133BBBFAD4EF41D6F41596 28195A27563D3AB6A62FEEE584F9AF0CD0253B7D7BB5E599081EA6657101E980 A558B9531CDC5DADA0D47F1CBB6DE4AC107A5D3AC24D69D0EC9609CC1762A583 121D6D0A48167E60C447D47AF8693A0E7B2796B839500CCE022FCEC5D2C1CA0D 8E8286CD2F31A756E0F3AA641C38ADF5E4926B3C41DB21B320F2EA5BE5D16E71 491B6CD80858B1F44A780DD7F6B77060FCC070FE625A196BD6DDCA6E40015DBD 378FCE94246918B68EDADA6F54B169F0535EF084923DB99FFDCDB9CBA30EFA21 EAE1F01B9AB170E6A1D92859BB2AA023E78D50601D9F33944D50104394EA45E9 EABD98646890231B2B7A5563A099212D51391746B21DE612301614B18E4493E6 BC78BB2D62EDED4D1384D85E7DF873E3A3F8C16FEB39B0EDCDB2CEBEC619E718 DA6EDE026FDCBBEBE75D47EFE7361C91C0B28118EBABE2C2B6078F4F82D925CB 4FE56054E9039C69AE61A0F1E5355E8B590405D36E3D2A2A2A51EF95777D433A 1EA1AFBBB14E0C68E8B751E7BBD06731573197AD614CC21DE871692FBA52BA34 D50E59B29207BCFA4556641ED3E868CB706C373073DA93FF91B2E6242D8A5E80 0F4DC93D6E7E6286D8E66D9126157EB7718B5C57496F3184192A0C61988D0946 2D4335FB6673F2EC4190CEC8C0E501517D1BC92693A73B02A6F6CE64BF7AB782 CFAB7E0BCA8DA23B10DC337CA184CF59C391A3F6399518C76AA0D9199A8614BB 5F0045C05233CC68A0B3DBA0F9D7F9DB81586954D5724B79F765F6BB51A4D330 53B753D84A14E2E4AC83262019E3018AB2EFAE580ED2F6093C0A1787756B33C8 9190925D0CF343543AB8011463206786871B4DFA4BB0CBC408C98DF27C4B70FF C04DA33A6E06259B0226B2DD479D2AD9A9AD51961AB9D861309E73662E78CF01 0979D545153EBC51FF9812BA01F652508505F4A82132331F3E3C74E00E52942C D8FCD78212A74A37247DF714338962F6585B8DB09E1BD63FDC2FC1C5FDFAE77F D12489A28366289F912890BFE5CDADAC498E10F9BCE6D05E1AC790171A484868 1CF5BD642B29E4355E18E3D48D6D5A9D63DC763D50E03C38C98BB908C05BD1C4 5D495B84C6AC10081C83B50B2B5BAAC285210D7D3D79C2151157B8A69839C5E1 691ABE5790C282037A98CA60D2C5E7627640607C35C285E39F3F4AE64533D4BF 65CCB9A11A79260B87F567C7AE128AC2C63C6A1F10C56E82AC562ED2C3A13B6B D7A5A06481890A93B8B2912E5AD052779D909EC758443A79C92535518B61D9AD 0ED1451E969C8E19BD78D3E51AD4B8C72EFD7FEFE8FD3ADE5157AF86CA3DA2D6 1E2B8D5154BF6BFBD8B45A52A095EF38480354F644A41F863119F882C07E48CD 2B64EF986CBBC000706F5B2ADC79D2411E1776F3067DD0CDB73F2B097A09D413 3C2659698D66F86082708B23D87DC0274DCB16EAB89170AEF3C6189DEA0ABC28 3691DA6C145EA5D191073041FA338AF636C4B817E5709D4B367F66A5CA9DCB1A 291F4231B3BECA853D6622E3500FD1842C8999D6412BB35985712C173B1D0684 EE50F6D36DAE6839A625EB242818A7F7D7E88CF3D20D000CC3789912E3FBF566 88F200B29B9422011CBF2EA1EACACADF2E0A44BF84DC296F6D4A7420F44A10AF FE9323E87BC10CC10752266E5EBB9F8DFB805930B77CA360B513A02E6F8D6826 C38F625C95606B5EA05B475DE83149DF464CA3D83C7095427784F6C10B353FD6 5885CA83C893FA30A28D45C69BBBB3F0498CA3B585DF4FCC18D5F55754553D7B B2CA38472D4A2BDB58C811C840FA82BF1A585AE685E848D222B3437D874E0A4C 6BC67DE7EC0F3E34A5A204AC7C4AA41A99503DF5CDD4E8B442212DD94A650A8D 706A0DA0379804FBB248FBC03FBEDD55705654C1962DC7124B4BABE0060EE47E 66F7FE127A645D9D05A88EF0FB573E4F86313C25B78081F2892012E3D429C7C2 322A20B4C11E6F4F54A8888F32C9ACF5A29F996C30BF35A10E15E4DE7E36D64F 530C3B766C110BD64AB6EDA4E7F3AEDB1E2DAA8EC41DA74E57C28284B98833F9 C0FEA33453C4A6BD3E62F488C46141BC8EECB66E291BE50F5017E822AFBB333A 30FD1B0F9F9E66CAC5F58A9B7BD6A4EFA43E74CA4CCEF7920F1128E51ECCCBF2 BB44236C4E4C047C87330822DACAE4F8FEB14C8CC0EF0D7F525CD1A08D07192A AFE999A4B565231B500D0BFC33114E0F6446F7E651D61489BB72EF88FEB7A436 3E04E8B69BEC231DFB97CD6EEBBE7D5E47F39E2121104BD3D6FA169AC8E86DEF A8AFF077E12F7CE025AB3C309D7F81D3196B4D14F3C7F8E2AF906C94CEC37D11 6B4D466A02B4BE6B0B7C9B4BA7A0399950E4D101CAC2C205385DC432ACCC8B76 59C0F9C82DB43C9A9B847997540698FB74107DFF24D1415C7EC8CD9A852AE85B 6EE981A4AECCC1C5123B486770FE6290CF1B3FC5F9B01526F9E9DB2C92C49259 3B9FF825A3C241EC51C85A2273E683B8B8E3ACDAC09D15C2BC69AE4DAC0ABD14 96BA077EAB7DFBE745718B859C711FAE6E3F47FD31E61E31BB7FFD0F467F14D6 6CE8AD12181EAF72449F8E57B2C102C8140F15B7B192DC31A12874BCE4A7AB86 0C4FBCA801F871CD67C92900C720582A59310A3E1A448404CBD62C0C1041A151 9E308E98F470051A07D0832139A4785D5CB07616D16E207E6838EC4A21F85327 F9432A7228EE66B1E989C7DB3B6F9B33AD1F5F0B4393EF820A2AF2517661F287 2BE4466C15E205E5557A0B70736E55F524B8645372AB001F540A3A0AB00CF7DE 1640B3C0CA275E6C75EFCF7A1AD7AEBE7F5CE88DEA735D8313281BF3B6BB0AEC 63F291F499321E58E390E11F7565081506DD5DE9FA7978A76221618185FE1E04 39D9DAC487CFB00EB6DD6E689FDB53C0219FE237F6EEA9C1F042843D3123C144 95CAF35CA462B0D8488D04B656EE64AECCD89AC054801E2463EF52FEE08B730B 58BF9F8600A8E0459D4284D99C009B05733A0302B67234E93735D5D02F1C88B6 65F48C5A80F4D566A4308ADD39C52D53EB6F016483AFA997A4EFF397F64732E6 1702B6D91C73D4FD49D438B9D7B3B770ED5DF0C3ED2891E29B26F5E5AA54B8A4 095CC7A7258E64D14CE7631591FC8C4657532E4431774890ED7C21B5232F4F7D E476260C734FFC1161D8EDB81766B7A85F4982B0007148BA232A5497AF5ECFBF 0C5C52ABAE562097A6170446FFA7DA4C816513A46CD44C1BC551A9153207D132 F77F4EC4FB69723148F9391026B8D694C922947368F5C3EAA437C75722971F1F F250848701DEA51D0E0BCC2003B2968586B2F5186B22B071A3323C92688E7314 6330B2EFC89CD6EE8DA5187C5B9E87C9DCAA7B295D80EFC26BA1CFA8CD89BD45 812C87F043E9CBF8BF047E1D800595C1ECADF24103FEAE5FCE32A9945C2297F5 A431B252800EB9CC44896BF15CF7754A54844DE09701EB22011DE9091C10B55D 9E6737C59654F68369A577C6C3D200DDEBA8BD4FF09915A5A015745809B20E45 04B6B0CE900472B2540CB1D18E60FF8ABA079A81D532395FFDA2FB03AE01999D FF7F199EDEAE47BA5BE4668E1D9B994C565890D4CE2FD7E9646CD3626AAB94CF CB1355CC2D54482F6C5B5745007AEF876C836E7B18D9B5C58448ED7F7ABF1BF2 8EDECB1A18D7DF20ECB502E15B5D471CAEA64EB2182F00F5B5B7BB72E358DA99 CDFF5BD7E274496774EF1155A6F09FDFA539E26BEDA3913D3B6405C9321C9D1B E5A0CE080F57BFE2CF3C80BCF2FF7A7C4924F96B627CFD45E5889996EDFD4E3A 9351034F1277B2D54C0D37783C9B8B07D2976ECE08DAD78FF7DE849DC077BE48 BA4FF934C2749765D4E27D679F94539611F98FE1CA92C52246AD2778652A6BA5 DEE57AAF3854424A78A23B36DB9E6F3364918BE5EE6CEEA1D6D40F8F00A9C116 3E6FDC117CF5B47B5BE09290686EE57D5A9C989F42C0946147B52C10B6996920 6AACAACC50E256B641D12ABF9F6F8546BBE525D57DD449F819A9A678746213FE AD49897C02A4DADE4721B1E1B11EEE9320240B05E9A74B02577DE56780EBAE18 4D810C4142026B75E4545DEF0FFB267DC1F44CE328749B121FA989760108BEF0 C21CB7CD0860B5E215133F66F88E0CB19109D36F47115298ABE66672708CB761 CD0C45CE5A12C237758F3D435F7D310DBF952F149090E9FD8A902AB674CE6A7D 08290FCF67CFA594F322360305C16A060D263D2F0CB6FA9E52CDD10A54F185FF A9AF4F97F64869515EE1DF31C64031DEE3627F46FF45ACB91F0BF272D7DF4D19 693BD2BD45F5308D5C9F71D78BDA39F7D2D0468E9E0548E16A2552C715F1DA8E 849AF2604E4CEF5021D4EA480E255087CE350A139F995BD23FC035EDA3DCC5EB 11FAE15DAD4CE711E12507A630445632FEC5BD2C35CA0F6894A168366207846D 570ADC67DB3BF684C15FFC064E9309F2D2CD794716995E7CB9F804F1955903E6 77D461A24BDEF84D03B167AAF05B8F86DB050D9EC43FB79C7A97AC86E32E0E82 FDC7B0EA5B8E13F09969DB412CB8CD5BC9C61205661EC3565139315DC3E67004 A4AD81E1140EAF34A51DAA72051247A64CD8A321283B05985AACAC914517CE14 AD6324E598C38FF0ECFE3B8DB05D9F6EB6B3C0471C34AC1CF8D9A6380B9D23E4 5A372AD76BEAE61C808DA495B7312F322BAE0C52A312485E4569DF0B8C0D365B 2E9C813851C10F0AAB4ADFF3A6A2B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSY6 %!PS-AdobeFont-1.1: CMSY6 1.0 %%CreationDate: 1991 Aug 15 07:21:34 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY6) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY6 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 3 /asteriskmath put readonly def /FontBBox{-4 -948 1329 786}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFB7605D7BA557CC35D6 49F6EB651B83771034BA0C39DB8D426A24543EF4529E2D939125B5157482688E 9045C2242F4AFA4C489D975C029177CD6497EACD181FF151A45F521A4C4043C2 1F3E76EF5B3291A941583E27DFC68B9211105827590393ABFB8AA4D1623D1761 6AC0DF1D3154B0277BE821712BE7B33385E7A4105E8F3370F981B8FE9E3CF3E0 007B8C9F2D934F24D591C330487DDF179CECEC5258C47E4B32538F948AB00673 F9D549C971B0822056B339600FC1E3A5E51844CC8A75B857F15E7276260ED115 C5FD550F53CE5583743B50B0F9B7C4F836DEF7499F439A6EBE9BF559D2EE0571 CE54AEC463244B0F8EAB9E96CB18BD39259CC1FEC10F47FB56A38588CE634209 8F77258607212EE1DCA4F0667B152875B2CF5AC44B930B888ACD9D4B55662542 71239286D82E14CAABE7276AB199E2429C4C3BC32713106A10F5F16C8045A580 86EE21E7783B70FAE03D8D47B5AA13A881D478232DD65DBCD1EB9811C440E362 527EF73FC86FE664ACED80DCD6806CFD932BDEE102B89C22F423992249FC2273 F39C59AEF75B2088527AA973C71A6B134D26EF1ABAB75721971A0E4E52639DA9 2E1C3B2A6FB552CA834F6443E0628DD9CE69E92DA0B9B8ACAF3641FA0A7F1126 8DF8803E683ACCCCDE88C9F6C1838BCE7E8B56A0BC8C5F0300D81479A5087FFD B8B66527B87F7977C31A54E0506C6D33EBC902841AB7B8D75BC8ADE5397905EF BCB96AE4B57D308DCF0F74A93177F2DDF3486642A43834DB5B123CFA402E4BA1 6EB4C27AF21C96932E05B79CF951354FF66668C6503CA6FD2089A91A8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR10 %!PS-AdobeFont-1.1: CMR10 1.00B %%CreationDate: 1992 Feb 19 19:54:52 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 14 /ffi put dup 33 /exclam put dup 34 /quotedblright put dup 35 /numbersign put dup 36 /dollar put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 61 /equal put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /quotedblleft put dup 93 /bracketright put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put readonly def /FontBBox{-251 -250 1009 969}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C 295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C 4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF 2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E 0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B 43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC 96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 3E6BB526D2D5B5321EE18DD2A0B15E53BCB8E3E01067B30ED2DD2CB9B06D3122 A737435305D42DE9C6B614926BFD44DF10D14402EBEDFF0B144B1C9BD22D7379 5262FEEAFE31C8A721C2D46AA00C10681BA9970D09F1EA4FA77428025D4059BA 2988AC2E3D7246BAAAFB89745F0E38580546045527C8779A254DB08DCC6FB9B9 0E172209FBE3857AF495A7F2B34BC893D942C145C2204CFCD6A5C69FEFC25B60 E412CB2BEAE7F7FAD03AF46344F6A7D483BBB1E896BF16B0F4C363799DF23CE2 E8127996DE841B6F9D8A9E56BD799B6A938582988AF87151BB8D3AEA85C49857 DD862B5E10D9F33D57795D656FB616BC9B8397B3612131A2B0F472656700958F 739A548F7C3A348698AF9F6F9821D7A9FD4131781ACBF7EAB885A3AC254DBF94 02FA697941A0F97F048861788BEACC20DE829764413CA58F9D045A6B38BCD6E6 E4827247EDF1171F64E3B041A69B244308DC07F66643FCD7D5FD37F36EC4CB5F 957D4ADAF91850A3B1A765E0E580EDC77556593D1B2E1C22685268469298688A 45C474C9D0472D019CE1E83F25182D084AD85A49C502E8D679C227DA8E32045F 8055D1622C478F8FDA342685F858DE3F53F1CEA0D70BF54A4B35884FD75D8B36 E54B9393BDC9E020D16B0C20E943CF4E22C0380840DC7628B70C3CE570EE2060 34708F5531EA5E286384292A5BD0E04ABD1165CDDF8C0ED8899A82F64D2C2DD9 90C50E0FD6180D25ED5EF2746914E41E859EDE14FE652EBC40BA85F56F625947 805E6854520522135276AA0AB3956E65553012A51DBA92C0BE18D9A974109FCC 24F2F7EADBEADF14359BB85A0516BF482639761B7C4134B68E863A71DC8C76A8 F7DA8AD952F9428B6B492FD55D800C3FF266774D9807C268FE482333BC9B70FB C55DE4418DC3AB396B4150C4774E01A035DC2EF956FC2A0BD0BFCFDADDCFA8E8 299D6610014F4A73D5641A82528DD45935EAF72CFBB6C95CE320FD5EBE8A9F7A 2BFF5C3A5EEDBAE186F86B95AC394FEA62EC3A756E5DA7AFF8145444A7D632BF F8F6B211BD2D7E4A5A56B235C3912249F53683F9A12AC5E8AEE324000781157E 739C254AD437934D7B83ACDC2D5D7E6779EB15BECAA10B662A8B8A1CC0D6CA60 FEC9AE92613561A80ECB2AEEA335B5BDE2EE3FFFDA3D144DE40B82F93664F07A 7265281680C3153A10DC16C13A3715BAAEE70345F509661D04FE872F66420B6A FD94B36FB9565C4BEF9EDC71B0CFF58437FC06ECA3B15B875AC3690F0D2E596A 55C05FBA3B348B097C1453F27CD6AFD2CA38D3A6002A0ABC3655AC52EC9207D5 6B74AF8B9931BEC0C18E2F1BFD273293AB3593D553A0194D694C4E7036D98DD4 CF5A800D9E729515FF910E63CB3E1060D7F7562F79FE18D45CA52FCE85DA9039 5C414211F00A20DEA60B26994B05D9F5DF57D97EF5086824B4A074C78BF7F845 9C92908BA9F903BEB71D0F70249D69B1A75759225143C842566C031A2D15FF07 2EAB20883AFF604886616903D8B95293F48C1A821C5F2096E88C7CC13EDFFEE6 B0992152E4D6625C612511EE6254D9154E1B7EEB4C64CA40BC6C5BBB3584D7AB 06A2D217BC95F8514FF2FFF8F1D31069E6DD6C215ED4AEA0FBB275161353D2BB 9148067B9C1C0DAEF86F43E907E2BFDBA15788EB4851AFA5900FDBEAC07EF37C F5117A1EDDD3F2C318B7AD11E4813F28E202202AB4B6041138EB93B973E2630F 9FB42C8AE50B8E22CD0A649BD154E965D6F0C378C721FDA4336DFF873BA9EFD9 70D180CACD57A935D5A2053CB80CD378046DCA9C33326BBA1565665D666894DB AC59A68F5A8779738BF5905482D37C304618365B90D8F2425101151993C08F26 B3FBD83D88FE9F5B599CE1D81D10A8E7329409771993331C65FEB8F8C9318B2B 06734219028EC64B67DA6C9EE1EE60DA0E98B762E788D9A670CEC85B1B3111D7 0491C6170259A4644A5B6B31F3C0DC0FFFED687B4D662BE20EDF460636729D16 DCADF1E56B9C92CF29A1BACFB5BF3399A7D8D26C459FED717712065843163C55 516DDEFDFE83E65794C4978393950E703FA69A86987DB4985C4358A52C1654F5 0C8157DD644FB4933CEF46D76F7CD1FC00261C538DDB6650782C98EF66AE0C7B 5DD6CBFC9B1D928F789BAEDE464A3D24548FCE78E1E9C0623B265D8387D2AF84 B95633228DF728614C79AC5C4E311759EAAF4963AE31009BB3543057FB921994 C6E3398260E44A36093277A0926A2A896AD272745C95CADB395EB062B597BCDC E9DEC016EB1BD5DDFA1BA1D1AE892E1FD36E2621716AB74976AD19C95343AC17 7E3B43388419EE16356F1F27FAB39B8B61E0CD78EC781C0A4FFE5376B3DC2728 66B51B26F2E598AE017DB1D3BFCAE34D526FF09DBBB0290C579AE1634EE91A1B 9080E9FC10CC70A925F9AFDC45CE2F14B682AEF58D40319B3FCA0C11D5FD51BF 14C2444E41A92312861C35A4046FF806F01819466244DA99A92C40268E4F0ECE 55981D227074FE1FA9970C21DDF336E901B67DB28CCD3B39F1A7B9F96FCF3379 3336D67B9054C7A8B70F54EFE987915AE2EB57A91126FA770C600EF56B3921B5 14A2754A01319C568882C984D2C383E60FFF9173C172761469BFD19808890843 451E381498EF49EA8B16E5475C932E0311202224194D14DD30A243FEEF7345D4 BF288C6E2B81F4E69224275F2422337BE9A1F794C9BD5A6518EAA88D8524F631 99CD511EA841A35E2EEE8AA366C8A83E2C97CF4A7D71C4CF6BB5F0A60A27FD32 38C860BBD86CEC4250BC156FB8C21B6DB40E627CD537602484E52259DA98E315 605BB00E57E58EFD5C73FB9B2A6410CA3F0E04D3CADA88BD06EB548151DB4956 081E3FBA9551DF06C51273CC8C54E3578C0A345309C2D45F7B6F6DECC9437169 14CDFB887CFF01A102BE870E653961F95483184DF4F23BB6A5E248B18DB2647D 60B3651467CA2BF2A4A2D0AFF286E23A90439FC6CF8FD2C8753EDB90EFF684FA 41FA29F8B2E0B3A27AD75C2001F32FECD8A10973919F3D0C1BC0C9E5EC63D862 5CA28C834B502D01B4CC0731E2043E759A23BEAAB499A032AF9E6804EDF54064 843BCB48501F7EA6C7FA3560A125DA0D737AFD1B95B1DA2F3B750D3051A4F4A0 E53997F0AD82FA4B6B9D74C89DABA8E58C6C00D0439CC48C948EB359A08819D0 48C7D4CD5E25E9E12F6AB3B29FDB31DB521DD21405CA3DF6383F3E056B4FBEDF E12CECB2E3F2107E834A7D97345B55069A9ADBA55A33501F16C426D6ECD3DC89 CF6506A13DB053F87FBA8C4EE8ED91B41879B0422FC897DB3BDEA8CB43DA0358 048997B7A29E967EECF2CC9B72D5F17C5233787DC1D8C622F758DD294D329533 D429D8BC22D8FB3D70AF1A9B56CEA7A99C9425E769AE254B14F243808BA07166 FD066C320202B682AD3E355E351E3A85F1F7CCB4206DED1E073D275A3AE42DF3 282E4556F4D9699BF08243AEA49E49B46C4F6DD498BD95051B5ECACFD7F9E24F C68D7F1129B32A9A8A6105B90D0A13525610780A306D3D08FEA04006EB0D25A0 A0221A02FA7CCD653FFC8A4681E61E119DFBE38F586465DB76E4E448831B4909 C159F6FAACD08EE361DBA21F0562D64FFEF7119343F756DDA0BFDF02D0D522CB 3AAB2050B1AE27D54AA650AA491476766FD9629FBBF8289D43C3EE1EEAF95274 1F211E8BA70CE9E05625BDDA24D9E223D6C61EFEB1630DB948759EB7A4C47DBE 510253CF41BBDD251E3313428C15F8CFA4D91C1B3F3DC222B4A1F59FE1DB20B4 00CFC1130449B672D9BEE105B668BBAD1ABC7DB1D178B3452398F3D5F744E610 5CABB91FC124609C46223554694C982FBB3DF11E7EC223D49796ED707DB63D8D 0EB76516EF6337BBE1C0DF28165736D101433C1AEC5CC5E0506D10B526CA9895 DA3212C6CA69C4E22F3C4EEA3A8BEF8784F4AE2834DD1B0CCEC94E9F558AFE07 3C55181A3DD4B59D66E74077F08A936482664A9788573B4F52D1F83B4B9569BB 1F4CD6047483AD6CC99997D934C437C8F331513C2954368BEEB76F0B9813ED45 6F99BBEE05502EE9CFF20194E5C80DDF2D54AE35400DC46B8EB305B2B1FAA969 0D50193138997801200C9CB2C01DA51131219686AFC5061FD07D65A0A48B679C B53999377CC8D41E5B01166137D0089F7528BA27D956BAE5E2287C5BA4B0A0D1 624CC04BC099FB64C7488BE0A59AEA1897896424A178943EC2DBE462F06273E1 A7D820E895B2139C33A508DBEB9D5DA3DB0B9F386871CA37C2ECD3968FD273DD 3D4D2E44549C2C5A071599627685D416A58EE6F3451E0062123131FCEDF49477 94B0D48AE7272952CB3FE673B1894BA6A3DF9D5513577E4F45C339E68EF964F8 CCA0678E74DA23FFA685812BF4DA30FDBFDA2934CA99292CFCF7EC8823834D1D 57105CF20BC4F51BC677C204038E35AE858B95C8F18613B610DAD20D58F5A7F7 32A339FBF48E60ABE863B5DC39F18CF214CB3B9394D02B5F0E0116EF923F4386 CDBC71A65E88B340B961D78EDBD2188F7378441C1595A9372B3E4A9F3987B1C0 09118E50F4507807077B0712C75C07AD8D79A4E1F372FA47E1D2C16D52BDE1E9 6D5DC79007B6EC2B54CF2DCB26C391A49355050DA57C1FFD90930D63811D78FE 4106E9D8EF7F019AC306B021BC73ECEE85813DBC2E5142C11C414087C11D044F 642920B7102ECFF2D43C0E2965CBAF13104C293B106C2721190372BD666CDD17 5A506CF6C991A9912C213D2FB1321C186FEA1F62DB678B80C948ACB252D364F3 92FD93099D65209786CAFFD0380BB432D9023122ABFE579B71224BD99E5C6929 44164CB829C4796774FED8C762B19C327AFF66606620D7651D32224FD5BEAAA1 40711364D630C023C94AF8D959692A5E973A69E7074A0BA92B52D2BCDDD9A8B4 311601A7407695F370F55E951D4873B8B7864DEB94C591A682393A519676D415 C9D48CF9BB5919CDE4FFEDE5EBE1E31C19B963FB3E4514C97227E772868B7E78 2DD1F64B8A1A59F5270035D286EA7A8A2E9819C5D2EA09F4710F662B32F56125 5A74841A8BC247977AB2DA5A870A24936CA3584CE542E281F0914CD9F58E141A BE8E434304666063BB6521C944B1AE674B623A7155A813FC624359E229E4F24E A7A8C08255B220A300A52ADB791F8A44D1BC46D3983677D60CC5B2A8419AEE66 7ADCD92EFFB7C3BC90410947CA4F9E8292FF2B72ED99D220AD00E2DBB8CBEA25 C000E01C497F94746C68C3C0CD040FB12D59AD7E9CAEB9B63510C56732312C39 AEC21A76E6A16BA4A7A3BA0C1DCDC25ACE7FAE968AB6FF1749D3B0D32BAA78C1 AE9997EF7ADDAF34A9FE3BE747EB44CCC1975F004A053B686BE11889A802CDC1 D2176AAAB3CD0BE0AA56235524D691978A4D4D4080F1F66819DF8324DECB0EFC 264E10E60690E31AFE1E41DFCDFF8533E8ECA0CDE4A399354B055BBCA4032B19 C607B196BC1A1E5A337D4E7FBD723AF1D6A288277EC83A7FF297727DA311FD4F 667ECE9C649A43A6C3863035EF823E71DDBE22DDC00416B3B1857D4C54ED15FC 664ABBD089B1ED429710815DB71927311E2CB28F2DD32AC556C4774FAC84FBBC 8B02D9D5362AAF3D2BA23E9A407763386F94B19C5AC87EDE226D8FF2FD44527D 4C930CF193CFD628D4A611E178F66DD1548B4EDAC700618259406D0D5083484B 41CA554BB87DA00D1764A502807D3C489E56CED505518F73099C9B5E5FA9537C 13F20C4A83931C9A3143E90ADD4E72DBC5006017ABCA949F2EE79138BA6782AD 2A5ECEC5746402681EE1977BB077BB1BC68A8A63E677C602197530EC172EBAA0 FA8131A5FC6F10E6994D7E623D77F4EA5A61E3CB66613A212E2947F63E49E94D 1E612EC3A99FF6A604F3AE1218C5ABFF453026269307061E5FC9CF1250CD45D3 636965F97AE53FF8F8330C6FB1D7721EB3A071E145A2154D31409CACF1C560C4 F898358C4AA08E456178C3E7CF59A83EA098657D8253E64819E5F6E5BE5851B3 AD9109EEC894F8DEFE366C4C9C16781DE0E14B1D51424B6ED025C91DB0FEAD34 930E47F9C11D6B50814AB6109019F20A6D030ADABF57E8EF567F718CFDD9AB3C EC02AE3EA1D1E84BA84CE1A505AD35BFD762F2E12E24CDDF4DC9A0C49AE2B91D 149A89B8279DB8474CE8E1B24C257EE32DC5CF94580131A57B80167E901A057C F1236233EE28368B160196FFF63AE7D42737EA6DCD90C9158D7AC59F399654DE 7034546051E2E5F9AD18B292FABE9556BDC152DD842922CC182F09B65F6D464E 9C50218E2ED2F1FFEE92B14963D06CEBA5AFD9A0A75441B09AA87AF2B4D253F6 340E831087DD7552A5322A3375D0BF870A773D36082AC8D0A0AE309D4E8DF387 26B7767EC42002A9D4EC80A5FCDEB57EBB86A4AD383C1BF85E873DCB73A7DCDE 077745D63CABC0B737550828F7C789470B358586C04395740DE69EBBA502CC2C A79EE29EA969D1986C9C55878E70320ABC50E46DF6362DCD9FAC8A4CE9CD95F4 9041D407809C25F4FDF04EB59BC9F008B34364EBF30BFAB3D2B965A892B9594F CBDDBB718C2D403BF678F998ABD78DAC10AC02D71AE1755DE8DD47CD8B06C0E1 0062A6C1FB2322BE6A26F86CB3A9C9EC950E37BC711D4F32BC878F2801485309 94FFFB772AD0167EC95AABDF0B82CC96FAC9CF45580638CAE52FF27A5853F6DF 13939DF00240882C9AF2DA83D08ECF7A6A40BBBCAB4D9E81700ADC65361E1736 DC0B4D69B52B9BB481061E06FD261EF05D22A1CCFDF59DC63779B4FCE6FBF25D 1243D54B3337D1EFB8F6C68C7CA33EA2392B5C034F514378BCA88CE84AB0C586 F6940D0DCFD14249733A8D4EEC25D494B41EB76F8944B6591A1D69F42A9064A4 4BA19CA154EF1850A4AE3E7F52E6CBC2B6A948740154E159FBB036A21069D105 03C2BD76B5D4930FF4B55593A282071015A7B9C739CB7FD6465AB557DDEF6763 F120F93EA6FAFD06FC2CDD1445A77C43C1F4B765538BF0440CC4C57A97FAF64D 1FADC38AD58E260EF5677ABA6D56A1F0D05639EA526EC7CE1F427CAB2B95AE97 9AB54683F08D3EAA25A9077A9E20162E62E0A32EA3BB577E77DEFDCD7117B53A E891E4A63DB284C45571E82AAE871580CE240E76FF8E0984B31BF119660CF391 41B6DC288A6A171F5270D2E3B0F64373DF64F472B02B7231F0DFD334B1355919 C1C489E2DBC11A2663A173713A6D220A5B25D34F15788640AFE26A9704AF2CFB F839E74BCDB0EF554049319B271BDCB736D775491FAF0D9FABD77E1250DF0AE2 084693EFC96A234331EF04EB85B976DD77AE513507B6669F6FD4BF5FA64E22A1 45A9894ED778FCDF3FE72AFDABE83F7D7E648FB8EC7FF219823088ABCE39211F 8DDB2FFF4793DF5FCDB25183D800ED0357AF5EEA5823CEFA7BC8A99248F91C71 EF0B218ACC2FF17E59C41DBBBF24312A92793829DE450A962033F5EC81F75E6B 9CE808EA804882618F4BB84D241C3E69FBAA333B540132B0466EBFA4B15D8ECA 445B2C013268E00AF58A33B05D6A8FC6931EBA68A5D1EB19BDEB8D6A13D75FC9 8F80ADD36DDAAF016C6E7F60B6726FDD9A9EE8BD042AB26C9E7BFB513FB16198 54566D34BED609703AF75C92D68081B40EDDD8F150CFB6E0A7EFA3A04502A04C C07ECF2136F294A0F9066A2F84C739F1A821FC202E3CBC6D8BFDD4D98C51753F 6400E1A38E91A628710BF3016933910A65913FCCB32E80A422F1432E0DC07145 D519A159053719183BA4AD772F708F86B4074DBE9E2A7DBB7EDA7A707CDDDF16 A4ED69D6A90DF8DB09E06917BE7BF1FAFA8148B2D4DF39C418F81166A0EF337D 78891C561FA087193CFA1D31C2DC7393F6A10786E09A7EDC0018D370071C3EDB BFB42B40AF7199F5CB901CDEFBCAF011ECEC8E390D372CE5D4EA30DDA53CB86B E69B1EC8DE69E84F5F3BABE2632576E7912831836E36DF7AFD3C7794009903E9 D6C0DE85044C3A69AFD7488F586C47B064DC3CEB8BB395FCCC3CF217F4C92CED 3014B8F8ED0D2B38FE1555CE4F026AEE85E4A31E657D8818034E5ABFBED828D8 7FE0E372F506E4EB3A539E738AF1FA5EDC1183C80170023E86AB36B7FFCA23B9 6CB86A39E4F57A3B9E4CC725F13C2C54B8A3E640328B8C0CEA0F95DA5288B615 F068DA3668272764C0CD9347DC0DD834D0D9259AEAB049E7BE906878FDA12C29 47F00E7825BE00DE8CFD5678EA7AE1726F5D665C8F5AE7318A4B65BACB0E8599 6E91BD9406898E88C2C524253A61AB8025DC8A873C53340F3D531718ACFF3218 DB61F8C4D321A343EF919657ACC0CF23AA411799D9DA0BBED27FBCA58B5EC49B 2D00F6B179C72141ECC41626BE0EBB55771546553FC052A858FC06987F5C3E7F 7076838EB3E284D00A5D394083C61CED195B0B7C9B8007C8A6A347EE98261AA9 644CABD5693D277241F3F6FE0ED9B661226F191E8DAADF48E15C63A2BD64B33F A0B5A8BD0AEDD3608ACE5E3F7038DAF3F9BAB659DD2EA4CD13CADAC984DCB03C 0B8D848666D54D21C788F95B400CF6EC834594C8275F51C941A1F5687D5A427E 5E9A93EAAD048F5D141778BFA3792EED2B0B3C37D06605BFA91FE8271CEDC1DD 1E8F3C374AA4BA92F2C9521D87AE6DA5D7791F38ADA438ACFCE4365229930215 894690C75D27BAD65579C588C2872FD26D49FFA96F7937E6FEB5A3820C1AB38B 574C86F272FF25EB6E70BD944635B186DE2AD84A74AE8FF76BCF22B01FB11343 CFB142CA4C3B0068F7215BA640766B2716BF3DF57D830D7AD9B00B39C998ADAE 436FC8B9730151A9C5D080EF2E41171EEB56E9F35A2EEEDD5481349D9AAA1E91 1C10F45F5E5BAC3592326EC5BB841DC70706455954F9827D987158AB480FF3AC 34C0410A9D1CAEC8C6B62A79AC582A75078E63A164387D23E076C54F4471BD88 0248CBD81A2FFAB7926F415E2B237694167BACADA7A71D9017D3200D2874D22D A2129B24F936F750ED529DA69A1A8F6F057338DB2209F221D03F22B383ED29B1 DD71FC1C5036997C0C879E78B542F3918003A7B55370288216F15DB91FE7578E 8C8CFA8E6BFF32C57ED566ADFEF0197826F073D45AF8580BF6B4DCC3F5856F44 2428C6450D2B471F6E1A67C511DD94DAB9273A506D7109DCB33888B76D2F2257 DC6DF167457BDD003DDAB6F3FC1C1121E4E59550A950FD4F713A2AA7CBE97941 5D78F7F17EB30A5CA883D17642E2334D7194A80961F0E2C26091360B805B4CC1 6CD14A722C1A144BBF7FC4061E417148C1E9B750CA0E18EE05485FFF19545794 311472B0EF215EABF1E7A8681CA71FD43FB0301A859CEAC0361B3E0C41736C53 7A9F938B39070AA29F9EA5A7C9219EDBDFA2E9132BF0E49B670057FB23B86B9B B3CC7C0FD12EB309DCF8D1D5967C235CFBCF541B5C191DA128D1DA4BEB088BDC B6ED683BDE7EE18598B9B2B1D233F26693A66B3FC2285444721107C7313F7FB3 201905B38DE3BFED9BA661AD4A3D940C6BFF8A74807F4A6D8348A6246D2CB9F1 D3E4DDE6D7460EDA0026E919EBD0E7305F66FA37D2C7EAFA415E67BE00399C5F 4BFF7851DC10B44A696B2F0952007736416CA5F02D8DF73B60BA764D2C1E978D 3F4DEE50CB7764FF586D1B719E726734625984657FE810FEA022CBFD09F16487 E6033B38A1E111F73B8566E60145A6E6D76E98CBD3F2F70692266012C9204A73 309578178217A109DCAFE3747AE4DDF549737B4DC9647A56D9D3A399663BC417 D83D252E7407E60270D2F592127B5DF30603482F1C17E20F2BFDB2B29E17E55B 100DF6F1E76963B086FF0729AEFEEE7B1283516C6254F0B54B3AE11E456ABF79 9E09F2D983E2F7CD3D056926DDF26E5A6B7E003029536DCB2FDB0BEBB6878448 444EE80334344CA7E42B5371E7C632EF9BFEE36AE2E22E713E7EA69BB2C8B4C3 B5E204981EC1DA73A72E0B0A26406E904DB16DE7303606D4D5F3538E095F5BC2 06917400DD909F3D880F5E6A07B0ADF0E61352872D4A52FC3C8D18293A4B2F94 5D32030E7B925B951F5FE050335123BC96BB5C8D6B6B9C7DBE7C049516854637 82AED9C2D708A8A8137F59F099A7BAF3254E4ADFC81CEFBA89D6C0D11C9A7B10 2F19ED50BCD3521AAB052185BC45EF2F2BDA547C57688219D038D1E5458B2877 7B20CEA17D4EFC5EBEFA32B99AA1BE19FD7AD6255F7E12450DA48C3A7947E5CA 95CADBCF440B38212FF36A840AD4BEF61438F4C08611C2919C1DEBE0B916887F CCF3918EEA989BF0F15FBA52906DA77BD57BA0CCCDE6CFCDAC76A75503040BF9 9728DAEAE729F7DAF8E7511C5F92C10DB4764421F8D968612FE1E01AEB35B067 2CC2D5D1386C0666885750E9F04E1A0407157F60FFE84E585A36714C844A6386 09EC06111CBDA2F6C561694D409D93933EF5A0E25FD7D2BF5A1E5267BD9267B0 151FF2A06D7B7085B8016DD4943AEF5A3274F0828E22CC6C9E68BF182CE6D474 3274F74E64565BF8E64FE4AFD4C98F05487C31A249D5C90F94F9CAC398B2F496 15CC249D62F0C9B9B9F71AD29479E69D5B449D2564802D6576C7584368381F36 E3C22F01AAAFC85D22617D6F6A4E598FA8DF1FACD4C7F205E88026D12F7C509E 38D29C65141EB2D397797FCDA3D2F54651F70FC52E8F4E12C5AA200495825FEB 54855AE33A8ABB57E61394902CAABFD06D42BD1ACA57DD9B81614CD44C822A55 88EBFD1DD771EFD92876B60131D4B86D3617863A1399A8CC1F2FE9EB1AC4C614 1989A0E2960CD5F830D33CE422D5BC52BD7DEE31D2C668E65ADE9220206136D5 7696FA00C4857CBBCE675A0B163AA73EC04A75598D18D82422A54FCA9A27CEE1 B922A0F52968D27616667F660EA1B5BD3BF25519E391FF9958D4A491A9308854 967312DB3174EA973FB5052ED4274F449F3D579EE90B54188F910AC3C69655A1 FBE9E3D09FB0233E3C7A80EEFE4FEDE817A7AFAFFC84E1D48F6E70C41D0226AC 31F46F7B29E99B562E9C4AEC9CF4558321DA229C3A7738B0CAF03C93EE489A2D 72458368E300FE0BCDEF04E7EDA685BEDCCE622C59EA429DDD81356BDB22E830 F65C8904824135F82A1A524C317153B103A0BC804FD186FEBED4AFCE8706EB4F 32DBD3BF2F40C5DF5B85E324D8C140D47F4D2E2DF2304424C327C6D12EE63E15 27BD4EDF53E355AE9A58A4AE77525B70DAA373CE7968CE286967B43F685C267E 7972594FD36DE1E0989111A30F43AF8B63EDAE180502A0D5873029770764B933 F7E43DF0B70A0DEC500AD685A57399DB8433BC975A90B0707C8BCD466D7C657B EC0D58E7CA755BF41D684CBF75D1941DCC4BACCDB5D0E1C0855E8C4C368E535B 327290B67D8CF7E12A2460E6294943BDD6E9BF9CF5A6AF70AD1B96BB33C70195 56AEAE0B1DABB09485C282D79C30517BC34583D16FD2B268F024E0D9654AAF3B 3D8AB3496E7D0622D0455BF82C2BFDE912500E6D5DBBD9546D54362922C9A46C B6D7A01363AF3699466875A416CCA72F97DD327264B3EA16BBBF7E088B47216F 626FEF9AD1034AB0CA82099509C9AF9B70599929CE3D21F612CD40577E9CB7AB A4A79A15A0B03A8B90A424B64E7414196B72ECC9D2632B4D7586700D495DDC0D 367F415737612CB6BA03D726004F8D49B2C5E155464B826349470D9499B60DF7 84764156762F2E38B9440CCE89A9555DB43328B59ED6AE0E53B015492D2455D5 C66E4DB65871164547C34E5D41FC3B9D5440E8D6B7B6E09FCF916BE674A43E36 6FA7A912481905177D896EC126DA80E125ABD27B9BD6D81B474F909DC8590571 6A815BB1F27853BC47EDE4718950C3702A9D27C28D3A0FE73381445B60BB1887 DE62F57BE2E473B1263877A11D766945ACD5310C4B9D2EDBDB5D3DA070814969 7F086E8EF24920F37A23FD09CFDE87F854808DA8FE7E5F2E54BC13CB936D498A 5CE1A7202EABF663BBA01BDBB0B479264BDE90A30543B7CFB8887B52D0F28BD7 8DB8A8438418D50BA775EA58624DE3055B394A9B7D31E268B45E4BE6304C3B3D CB9DDFBF78ACEB72082F2895B99AF925421472DDDCD0C2846E945797284FB405 74A05BE373C99648D46F0911A984AF9F726F28BE6534E2D1838FA129E508F81F B4490FC684E446659151B446B13331D0542223D0F7609A8925808F16E9992FCE 42983CDFDA4C8F3BA175E47F630534B706A3BC38CB3AD3D4AE304EFB9C00BEB2 A830A35B2FFC25F6BA978C28AC71B875C25A7808EC8A5BF619673CF8B8518368 852BC0AB7ADF6CC29D7CF4C31F0D606267DA15469DBFF23DEF654384E6074A55 A5AD235991F25EFB4973E03CC19305EDCF3B46314F1584B7216366C324D1D182 8CB2F48B836CBA52042005C67951904FE2889BEE51B90973202E6280FE134F80 C0EE88917639F293EA1840DE5D654665D5B38FD57B89B3807714FCD9A2510B03 4CFFB3DC6BDB2E5427FC725A91551F2615A5A9C1FD625FAD049CDF42AAF1F98D 9B6E9C29A1C35B51D14608DDECD76BDE9AD08F4D14B3BAAFB4ADE2B2D24E833D 9B520976E1345FDCAEB2FC5A6A7A47DB0EEDC35B0AC9B143C7066DAC1A9F1A3A 6759FCA1AFF0C9C14D7134EDC9AB838DB1A854C10309E456F8571B9DC87EE342 C1B703FFF292EEE81C043C6ABC32F31802981E734B15FA87A6BAA95FD4D4D9E0 7896ED06ED4A60DE13A62CB6C7190AA73D9520AFA10A6827E45BC35F4AE730C5 AD837CEE455989A3EF8B5920A4278082C7CA8582594231614029D6D084474864 3D96D86A4F31E258A49C4771262A64F7445B20E159C024D7A40B623D565A5CCD E4AC3E832F95BB8BA3B9FBBADA1A9DC928035B9FD5D81681362FC7F5E9004050 6538F992ECC8CC0F9A468621546153BB29ABE17CFB7FF412EB4FF42A4E6438A4 01F4D4C6264B4B815572E90327646FE756DAC90C9AB78402F791CB2669AC60F8 39F7902B6A95BD4EF3041C631D37E939518EE97E9B2E52BAB3BA8F2A26C8A9FB EBCE5C7306A617104C0D0C74A4FE03B94390A393498C1619932CC3EE1650404F AB16E40CD3B4870C9F687D11DDAE5C15B0AD50C727B34DED6C37925F1798FA5D 8AA565ABF2D368242F2985EDC4E299E5F93DB82656BBFDA364E2FAEA9893AC3C DDA311C7D6ABC7CA6C759C5DD2DEF44C675F7538EF35AAA5503BC12F311A1058 8DB47F91E9B56CDA671EFDDBFF09AE3D75E30272CA099A7DDEF518DF908687F4 BBBACDF9486E3FAB7B909199A258B6CA6E3B64F30EB8F6F907E7239F0BB4339B 519E733BE3239221256C20854881C6D0F9B974E1C4AE67C5E84BBC72152D7579 40036923F671F9B5C6D7BBA52C145664BC3F10B294A4BD345E019E95A7D7D93C C1DD7AF0929280D01A1AFC83D4FB0AD268502B1811F874AA648F40F5AEBCCB85 5C4C485F5B1031F3FE4B038581E9C0912CC3A877672F3889C32F72219A9A071F 7268F19AAE2F8F6FA3A02287D64E64FAB91252A1534DFD7338AFB26D3ADAA770 F89A63D3FBED4B0914D3A1D64D21864C561CF681D38ECA5AB013BC8E4A3D8E63 4FACA1387B57055E12AEB6E28330B7E679B211D108D6237215D34E8E8475FDC5 D291E6B3A00C1080923642062D15E1DC258D018F9E9138BEC0D1FFF34BEB39A9 573AB74F63651E0CBC8F12D965E255085DBBB4E8BCECCF0B4B5D58EA07C3C69B 97EBC9904E9A4E6F361635FDD544C88120AE84CCF5416E9EE6E9D534780ABF32 8A6EFCFFF3EC1F46E969E97C0F79AC02E2A0CFB7662EE288498182456452E0E3 62B24F03B95E0E70406033353FA3B0DFBB1741024E131710E3355FF2EF1848EC 26AE602D8806E44E38019F7D9865F7EE35A56082403BE5B4D3FFF0D485E5C718 389F5283C688EC02574ECE4C757CEDB01CC8596C6462E19261C6B32867ED7553 0EE2E171CA3ACD4C092AACD751F698E9B18C56FA5A9BC0A8DE405F08C9AF304D D4D481D2A1E93BEE9725025935D71408AABD74F3BAB3AAB21004155FFE19F551 E0E1B682C2F54C92F6B9ED91A38442CFACE98368AEEDA68BD8A28E91B1FAE708 6672771D26AADA36F30EB709FD01683A11B817FF646ED2C3A6FB1101913CB8CC 64C68E37148FEFDDC74F2FBDD70CD8000733D3BC44B6C787D1C7E49AC1D2E2C6 C2ECC696A9722F473EDF681863575E1FB1A54735F5C8136516AFB9A6D4E9A7AA 310A6118B3EF9349D1E96E6EB384D206DBC45B188BA8445738729DE24D48A159 80DABB850435C0A03359291C332C78C1656BE622FF734144AC17BE19D38F9F54 59CFF8FADB2D0164AFC718268AA4B94EE7CCCA7B479A0DC70D9B838D916833D3 6923D4B22126BAA2237DBC3515EEE6111F6F078C904EA4FC5EF00364455976FA E00E5D79C5B57DB1ACC73640A9E37C200A530430E0D7F899AC67F7EFB2F906D2 24722B0A9A35E7DA6571373E2BCB5DC0D5E5D1398B9BE20A2F2A5EBE0464E101 30BE52CF8C12D85B09F5DB9DEBD3ACF320DF140EC32ACACD0DA56642F44BB965 BB769C0AAA298E671A0371DD2CB06ACE542DBB79031312A482B86BE124801EF9 52D425F8F2F3B31598B93C2330E8B08BD1F6A4DB245A19B803EA947A2119DA5D 52A83D5637F85B4ACAA1373930A4674C354EA46BF19B439C764FFEB82F249514 ABE74189D9BFBDA3A8F81CA4A8DB1BF63E10AC6B5B5E0D6FF8CA45ECE9536571 A9E32433CBD5F04D2EFC1BC92D18CEC88D700121BD4923CBA73051595261307A 7B00D14A2300CF78C93EC96326C0D10E58E91A86FCAD94E1A47E34FCFC5C65BC BB7316ECBAA3E35C7D3C0814BF6A2AE8B18121BD68722CB277712D118F1CA88D 31D5EDBFD64D74318E5DA451D12F5CDD0F97258ED25157B1A0ED1994706EDED5 FF6293C9E4F20EDD1315FBE90446A5ED621B4898E4EB9F23927F9D33DFDC62B1 A38C8E7B247BE8511ABA17A2CC52D4AE3A6D7A87220FE1745620A4B3A56F3520 D718E0015A0606E4D187856647CB189D0DFCD96968890561843A9FA21DC5D508 C74D9E33F21EA57B90DFD7637128ED958AC4EE480901F96ADF4FA833143BD85A C7D0B1D132D5C000E1223CCCFCB5AC84A42052FC10113B6AA88189502B56431C 7CAD3A8DBB8D096569314ADC4236129F00A65E1C0B5EF666268AF208006F6A75 136970EAC3A2904C7426A018B751861BB6C46D4D74FDF9A162BB85546F22CF80 B7BBE9C846E8910289EEA599BCD5FF4075C30AA88F93450654EF831645D7383C CC7FEBBA9C0DDF8109581C4A85224F7C9223581FBB201951169DCA18FEE81B48 F2E916BE7E275CF75990102FFFC1DBEB859237F9AA511D4C884419E421DEA2EB 418C6A9318D45D858468323DD803918FA6497A4CE6E7FBF188A67297040712F8 FA68387D28D239AFEC749ACF53A5F72B21AF2C8DE24EDCE7230934E324AC2C89 F35E2F349E92D3927A367C942A9A685A4C28F364D7E61D2DA2604FA80C31BF40 5AC6DD6EFDD8799471B3D8890D93D451306E481CDB71C471D670369CBAB789FE EAFAAB9D94ECECD08F6C8F82BB4DF09BCB02F3E06A126E4E468F059089255F37 7488E957B2B5521A36FF62E26838E06E38719ED72D2A0C7FC560A5ADB530CF22 518CC4B715D7B6DA08217328C4A09C53AE70A7339514B56D13A2F7ECE09220D8 E2EE66CEF5E5D07B1B30BF15C3BEDE12CB52C974198C8F097C3DFC69A3AC2545 41A3913094A42F4A2BBF2CE0CEE9AD7E5A6CD79814CD5DC55C8F3A99FBA341FF 7D844AC9CB0E5BB3FED72ECDD97A8B22183EA6B9D13CDF6EC3DDA3D42515E94A CD45D8FB4CCA4DAB7138E8FC837C89C3E78C2541550F229A4AA9A836A449CA47 B2D77BAB5A7B4D53B3D2F35530523338AD7FFE86A0BD3B0842DA686A4B9B732F 4E81E47D2DA475BE2FBA41F05B9595BAC506F2D8F9C2EB22398342C77E79AFEF 763BDF8269B7688CF98F7823E5096AE4D644D5249F7EA1266ACFE9949AC8A288 D57AB37F51FAF7937F47E41CA2F51EB249A525E91040CC5F4E9322475FE14E87 2444BFE2BCB136FCDC23BDBC4981632CF1FEFBB494F1A3BA16F50DD9BA26DBD3 0CA3C7113A364D0EEFE600C47BD90DF257CECA68B3D173211380487FC90503BC C9FFC27435BDC41EEEF08A8BB309CB2B0C8BC86DA1AA3514B07E97582F3FE4A2 32BF7BAB02CDBA5930DFF4BAEE6F00A21916C9D1D0EE21AEA51AF561EB0113D5 3A0A251D173A77C1795BCC56863200338933817AA0AD96FDD6CE740213CA207C 864A97762A9FCD3EC94FC518E0B9CF871854BE2CCDE4C21C1AB11F6BE66A44F6 7D6751471D4BD779C949CBEF803B4E7672D5D399525FAA9252FF78BF7E7E81AE 10FE4DCFD6BD3CC4C99B2CE818B2B8B45B6C4B131ABF2FC61B71EB3E2BE21D84 F3A5F90B39D76D1618063E8EEC04992AA29CA3216217CAEE3E27B3916E5310DC 5C4E2B489822FE4D6AE8A12FB1589A3790F9FBD105F451637F396E04A13FE1CB 7E1E936F3EE1F37C9B4AEA80994EF8A217DEF96C747B8EDAF048EE8EACBE4757 3A6BA4B9297A4229CECB2719A9346B0D34FCFB9AB7575335EB477F0EA9AE54C8 063F5B3C4E40D158D44CCCA4BC7C7B55687FB89BE7DB9279E34F144247737AAB D3EFFD448FDD211DD3EFDF6750D9232C4AED40C8DCAC19A19CAD81FDC6A02470 7B0F5B743465E0910F67C559A5B25EF09C80BAA80486F04107559D253A9A62ED 7A25BAF326D8569E2DDC14688723C245CD694FBAF14B8BFDFC35038CE3A1BF0E 5D8FA4FD381BDFE34F68C81FA1E87D3A760F48998A443F70D6E38910354E23A6 4449FE903E50D30DF066972927585A61EE674F89B28B7AA90FDB1B94A6A5F1E1 9D6D7313A5389D5BE005CFC1CD4F35A0458B06D62EAAA5DEE8117FDE9BAEB25E A38E0886FEE01E0170C5B6351736816FBEF0351E5471697428F25239953E7FBE B16F4D7E00E81BEA0CA12AF27DC98B3BA32A2A504C8C4B523740FFAF29EA504D D747111DD946EC2034AD209B6645A6F3CB5CF0149A2C9635AA41E88A0938EB87 BB442A48D4B942A08212D1EA498E0C7106C458C857E003E5DD7635B0CC6344D1 C1D4C05A8263414C0340AF765282CAC8367B89FCB66D9D4B958FC981E9CC7785 E993DD791F9CD6B3557FD2F0B87023B6D60BE63DBDABA57C975EE37F44E5DD4F DA1159378A67B6E3D5ADA8E40D59816A584A456AA4D61B3373BF048C3BE6B806 8549DBE89116FCD001D507B7CF32F87B0887705BA11F8DFAABBFDCAA721D38BF 94C61F70A58891E577D7030491D60132C93DA3A80A856111549E02B317CE1035 DA5D9AA8EDC8A63F065EB93032B48869CAE47E94A805F395CFEB064905674633 4D0CED3373E67B52F127A58DD7C2770BF9FAA294C62B9F76F6D47BCA510E11EF 3DC37F5C317442821B2D056993E67646D9B1E5CA929FF709ABA27A27404EC2CB 6EBA02B7A2839955F8E2BB7F59449C1CF39449EF1E94759E6957F1BBB1E4516F 9C07F7578CD268C9D90111648AA654526A5E8351CE12FD3B5FA2DBBAEF8ABCD3 5882795FD9FADEBC8F3B7F9505CD9938D465360157D6DFD90E13D21DAEECE587 43E13F92BE4EB0980319CEB35C11C19B32A5D57B6CA259D4D8921BED9576CB01 4F2AD03704644F1E3C6E50477916D193EC3AE2E82FB86880765CB7E4F69A0F66 D39189F5E7E76136D7CC5E33102572FFC5BC1E2849243C43902F77462C36D42D 8E51F67A343A4070FC2F192E4C2A19C97526C01152A745FC60D4149B3566820B 4F45492B4D3304154F917081A0C7BD0838BEFC96ECD5BF1ADDC743D190FCAB15 77A24B3E0CB72C16F698F8ABDF2A653C8AF374582B3631035A61572421BD9B9F E630BBBF2C4D31C15C608950E5EB054F08C4BFD8C55E9346A023B5A6E384CE5A D45D147AD6A0D83E507D6E7CB4DB9D79BCDBD4DBAC53E4F2F54BC43E6604FF41 694998160DFE2ECE261A4258E6181962B3DF7511FCCBC1AA4BDA31FACB8352B6 00A20481D66FDF1D570C015AC07240E94A41D827BA17D9CEF845715EF094955C 63CD05D6C8F3D68AC0C0C46CFFB463C5E2EE902D6B866D374F01C7C33C42EB6B AEC6044F93F94DFF85ADE2626DEEF3EC73563C6EB2762D3A8E565A4E6FCA4026 9F33EB916C4CEBAC10ACF046C3C2F78397622EBCA2C19002B0BA6C6D74EB8235 AF5ADC77907D394ABF82C7C720D00A71F8C3BD25167F68939C3A61BDE015F57C 15DE3C8E3C211B8C68E6889879062A07E0B6B894D46BB2E0DF34BAD3775FE4C9 4DA40F0218232F7441D78D12611F2438580F4CB4C1E75AEA59898E6056FACFBC 5451492F6E3570287BA00F4EC9DB9A5C2491229324AF55AA7D30AE5420461B9F CEC74BE8C9B9131659625749C7DB4AC76BCD602EC1F8E598C53CCA21826BB99D B448D11D4F03537A14A97D50DE9478DCAE1FEA581EFA9B0E89C7539C09D231DB 748C8329C68B5E9DFBD7319ADE1AD03DB62C8D515F62C37CD84A3155FB80FCA6 474FA2DA6E10139EEFE6D979E8EABE053EA6CE44F447F098485588C92DD71169 F859DA274DE1385BA200EB34E3E612E12B433EE3D8A865B688C38664A0BF64B5 86E0ED0988031BBEEE9817433A39A2EEEB31BF3BA541E52A834F0C227E8AF023 1CEDFAE842A8DFE5CF5300792DC580079B337FA6EC58E12772B08294E75B8332 C827647CBF35832E687FC840EC24825AA13323DA00B2BCD7747C258FE67A5D47 4F26738DDB11A1B0A747EBE8440FD0CE69AF5156FD001136FA1629A048AA1F11 C1C043BB4A938B8D110EE8295571BBE468743D4CD63B8A9FCD8CD5EAF7AE5A6D 92F571A8953AF7C9A94E7B3A2B5D475760F8DA457D8E971BEB4217B626982D43 921EB2495D43846EDC899656D68F10353250F6FD091653FB9DC28192AA6A3D67 257C05AE25B98B1AA908330EC7236D87D9C52CA25B57B5BD5E9268CE92079712 F78911193C69210E5D533CE127B18D98EBFD6A1B27EBF418E9625BB14B478B47 4880A9B11180CCD6C72DEBFB26CD814BA5A70BCDDB7DC75232F1C67BCAC346AE 48608E977D3EA87289F49D51E2EF9BB68803911AF5B377F50B9120A9C825CE10 467FE5351241C8D382BE8D72D4330CAF4A9B39CF1848A1858118CEBF10AA5548 945638D4512D33F0E5CFBFAC4449CEBD93F1F8FC9EAD36F1899A5113920BB91B F7D1EBBC5B1D4BAE4B8766DA0A19644BD7576D4F3E202E157B4C27116A4939AF E8603DD5C3F6D83DE489C04B358AD6B099A1C4D84296CDA43A30FC1DDF90862E 8BE3B80E3A369C8BB4E92A88D6064900D62E95DA803CECDD5290C2B17BB198DD 741E52F6F018CA007FC8641E5233E9C5BFA590E4934B43D375E7B81C4F825F5D DCEB827E5A275F0ACE7AD79CF960F83258A709EE0F43364F5D3BD9DAD16A0881 85B4A339A1FF47A4B99D0367B523C1E290C336E823494A182B221E1D98E29647 43BF0A6438047179D7C8349D99C5317E455666BACECEFE59EEBFA802BE644BAC E8BB4E75C45634D873E6AB3ECDAE27AA3A5E3EA9F940A0E9CA41FDEB43C0ADDF BDE41162E016804DD7565E7E1AE954366E047F3EEB7DB01AE9841D2A56210956 F98D6260643B184E4AD42D6624C42B9001B197685773786B161C2D6054DA48C1 3C15F17B3D2E4A7398385D3AE8D4EE186257848AD0CADBE2F75B4AFE76B688C6 D8EA280780ED1CB990BE38267F3B735066E943A915FA42F29BBEE5E6FC1B4C4D 6F2A674564C5821F57F486B1E9018CD8D17D1E1876ED97F1EA76CDB98F05D9E8 65035F0EDA2CC69C97C8155BF0ADA6A1B2918E185F5FF3A06EF5D1FD4EEDF7A5 9150A04092CBD78E06101F9A47780D6B8BE95BEF38387523BCA92E1DCD2AA0C7 9A264081FFE7590A1402B9AF14522519FF03E6E685E66547F2EE341D99FB971C 826CB8E08AAB90139D1B8D5C9099AFCDD6972FDBE96D3E61F8E05A8AA04CF0F0 92C51CB4E2DF5AEB638EAC13304F09221FC53D95FF5EB888F3148AE6E466E75F 028DCF215DB6CEA0FA674048C5718A5B76137613F0662D5307887B3B4E38674E DFEEB1280F8C8F27E3493D6A7F207F46B4BCE140BF755DD97C183692EA46034A BEB413D09EDD53D247D61BA648EDE7F9EDB327632AB44AAFA8B296E5E70B7876 8CD9F8430A40F33220E92B036D1288B3E014F3BB824FCA9E94B82717F8390EEB 33E9325ABC989C7B8F4EFADE04B06EA3B62DA015E0CA00529FB6FA0D99B01106 5BF61B53ECA3416342C78184F24FA7B6C3587FED766C5E0CD8F9A8F74636095F C500B8883073FC260BF19739373B2C7C7601BC40708931FE8431904683FDDBA4 8656D76F8657DE79F9D6FB1089EFD8CD2EF801DF4576AC25E6B139DD4B376904 A5F0F08AAE17025F7D253A312FB988EEF658F71BA27AC2A5B87B8F8AB72294F9 C4A70110C08EF78F5C32DBFA317C22A91205C75481DDC96CA8BC08C40CE6D3DC 93584F6F75F14110BCD5AF322749B8010522BCBF6BFBA4AE147F116C1402A8D9 1E508ED3D65743BC6EE2C8D4C88545E97286C01CDB0A6953D85348EB082E4069 CAED3F907312DCF53C921C46371B054086CBA983E7CE06C1CF00DC2E4DD80F27 6FE999834EDFF088FE277193B813E231160B5EFD05B456AE9B20F993B2A67D71 9A5C954785FE6A1EC900F764F208553E79192DCE9A8D547D13FB277D28F4E2C5 9C62401D3EE1DC2EAF220F1AAF84C79D6EED2B8DF7E31E53669270C7DB9BCF9F BE74329F292817D2EE2777096BACEC1D52D4098A935B262A2BAE58169730BF90 478D83E60CEFE7E249A39A6CF370B721CA1476246665775213B547D9E9F89BFA 1B58EE8B5F475A7FE4FF94B1646FF075198930700660C0FE16546637E1D80F87 C39381E4DE2379DB83C7A6A5908D523B3D7B9264B8973F78770297C0D31F4B77 BBE4380FF20B0C4909A0CA6141ECF11A2ED1DACBCCBA0E72DBEF51CD8E2D8384 7DC963394F52840C1D70B7ED99E2931CCC36C5AB5451B1529215943C934894AD C1883A86B8C7684ABB0C115625F2ED431252EC74BD4396567344AEADCDBE47D9 389C4F6BD94FD2A8A0374F84C636549974C3B99626AA7CE2A19D5C69117EE444 0811B2CDB5D684E181D1899E33DCF7508BEA8D28EF90659AFE8EA18B5BBE9FC4 2F30348FDA1DD26C216AF5B2B35BD658F6B2F8C42569D2708C69F89B154111E1 F0C98EDDE70C937CC306493FDE8517C1245B2DA6D1583ABE196029CD4CBC54F8 F474FB10937C9121E33CC960DBC1C04E94BD0609BBB0F1216893C7B188223AD6 E9CD2FFA0257B35FA98F9A557865D99E4EA3ECE43461FCEA49277BB4A1BAE648 3E7C022D064240DC00B48AEBF69BC9074E29AF869CB37F4790DC8C4628AEA7C0 D5B96F78A60639863B0C37ABE636A2C2612DF83E47FC5808AAFD014C281A464B CD0F6CCE1941B8D847D488E6D425A7563E1BEA0EA77EF9ED2A1A1080B8E4FE12 0B34DFAFD4F9C324DE3A6E61753F524AACF5352FF05B8D3B2845883286F8AF57 C1E2E0CCD66B06945EC60DEFFBAEACC7FEC78F3165C38785DC2BCD874FB1668C AC46BCD6E09EDC69DDBBDE37FC061014A6252B5D1D52CFF5C8BD65CC3F854686 5724BB70C371E235CB710E18BE356D019DA9B6B70E0A4560A54F0B7A3CA934F0 040A901E078BE86CA8F02E898D99CC62BF056A9CBA3BF3004C885D6419AC5C21 43CF5C84C67EFBA1BE3F645E21FB1BAA00B67464372F04AFA2D88AFB0CE82CE1 A158B26B35C5FA3CEA597C73DD5204AC2F4F2E37A7788B80EC14E9CEB2D3BBE3 178376E87BB14F7C9A75EAD1BE571C01804BC18B1BE136D11E66CDE40FEC9A03 ADF328B9A0A3CCA9421052EF6281E7B7C0DE1DBEC4BC4E64D5EF2226318A54AF 61F4EDEFE8448783E5E32C86DF12AE1B79F7125EBB1C99049C8E8638982FDF77 93E5B8AC73665AC45819B7FC6CFD9A57811C33D018C9AE779281AB249A149CE1 45A4DD65254D1F6ABD1F28123E86D3EEAFEBEB4F9560F0F7256CB1911EF9D1B6 410B48FFADC02E2C7CAC032579E75C369854435051555F99252F757C64A2EFC4 55A09A67342CB362C91BD3E0315B584568873E5377C84272C3995A8D5B1ADF70 A9C4F91972C1E5BB289D407D24FA7744D33FC6D92BDE47E04322DC7EB83B6BAA 442E93178F13036E40BAC6E20E8CF2920F8A1610FBEF3F865D5D177C21422B11 4F160DBF271595289089478E31F9991C85D651A4F2BFBE09933C63DFDCF84D27 34812C6952B2E33F650EACFB44713D635225F83A2C3E8421B2FA9D85C4E31952 FC9594239D48C2F73C3FF5596EFA852B68030AA7BA5577FCEB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX10 %!PS-AdobeFont-1.1: CMBX10 1.00B %%CreationDate: 1992 Feb 19 19:54:06 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 56 /eight put dup 66 /B put dup 67 /C put dup 69 /E put dup 70 /F put dup 71 /G put dup 73 /I put dup 75 /K put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put readonly def /FontBBox{-301 -250 1164 946}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D 6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E 8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E 3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF 1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E 0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED E067598E1B8B781EB59569E3D0D54D8EFAE0F3EDE26279776ABA15341E42E636 6E02817082BE6FE0B04249A4840C11F95F8ADEFF72173E9A5F2AB2F62C427E5B DC010E18641EAC906A5EF0F9BC2108062134A7F10956219C5847C0D82F0E8663 12D963E012DF0DD899911EC5D8096F80B49CA3444CF1294FBFAB57DFACC9D01C 46F3BA2F3D1C14EC30CBF83E5729F1C074D4F1665405C9AAFADB8BE41EEE43AA 16966E2C0CCC853C4C09F245ABFD4603C4AA55EADC0A59AA6E9F5895FAF3D3FA 83EDC6E2540417530AE7DDA8EF33DEB81444316FB3F93EF944D9FB06745BACE4 848398BEB747E58310BBA39C64E341185C82CB77E9D4439EC15BEFF1335F22F8 F036517C436225F4125ED67ACA7A84230D4E2B6CA713FD6B3CA54BEB540D4604 D58A8335BC20052440C4903786FE3E335E331CCE36A13F05F71126F680077AAD ECAE10CB7C057C2D55F384723D58EF3AAE83E9E0B39D6A522667CC5B3257DAFA AC1C3C981B9415967F7F4DECD492A52D35BA7B396815CECCA18146C96709CFF8 62E8552A78B12788A80F068ACBB0C15C55B19DCE5100BF525A59D34EBA5D3A13 73692ED7E2A03532244FA23261C8E5702629C7BE1F33A09F93AFBF3AC607A7F6 FD3D8B19098655B4DED97B03E39E463CAA9DD92C9048EBA53AA76B0BC5C48741 AE3010D21B329E9E6C77CDE3E7C23AAE0B2F5FDD647F031623497C468C4ADA7C A6ECEFC0828FF8214FC6C2605626514112B610FCDE6E3174912BD93E116537F1 5A51218896CB80229A42DC94734B633C98207B81F871FCAE1DA58E4E9F7F0AE6 318F68EC0C22047DF931BFE6838CF1325D3CDE7E16708C02FDA7F4B85C04B987 7C51C13CB4DB516EF9E98538208CFEA698F392BCFF13D221B7497195A0D094FC 9E72EDF09FCBAE6C6FDDEC0518E1CB8D826BDCD34C59FC1E82231670879CE2B9 3E7D5243FABF7CABD16B39C45BB7C243DC390DCF64F899F9537B14005EDDB0D7 F98E90BD5D778E3EFE2616E93D67F52670BB3F476E21ADBB8FCE74076B7457E0 4BBA0B06CEA5BB324B30C5F22BB65FA337951FF7F4345A961FDF86CB5FDB3B5C 19EC0187D603393B63186C84C83A82E55C33BD018456156C0CC12AE262F04F34 8BDFAB8210BA22E314EA054E364844F0BF03BE50426089EC7071143F51776C3D F19EE3CA885FBAE5E0D4A5334D0E957CFD25095B28726D663375530A635E4B8E 7C4743B67C00FB8A600F088414D8992ECDA0ACC39AB210921930855FBCC2E72B 7679DCDC16C306CBAC3C0663A120E5B34F7EE20EA7A172A1EE0D13C2960C12C8 1DB42ADEE49AB99BC309CFD51B5644CEB809BCEB184AF69E06BE34187EBF6F45 6E03911CF01F71E6355631E5A8D5CD2F3B6BF8B78FE5A3E69465E58CF73E5607 B0B18E8749626DD295BF9A8EEF2D106D587DD28F85833BC375462A944F0C5D6E 2B4C9795FF0B0F87E0ECE86CFC8D7D71D73F8FAB6D0BDCA8250D0E561CB64E84 8E1A67E3FF6F3C662158EFC73CBE917A024FF406B6FBE6739CB663D0C9922640 E5FAEF847679EA07ADCF51C43C25FBFF1EC5A742CC0303AD21E70FDFC7D47E8E 426BA2387436930557ED1A11712C9DDC1233AB4ACE7135CF296FD17A81EB3DBE 8F4087D8253365227A41364D01903377F2F0278BE0D7DF9943DED57976E6159B 58DDA467640451D54B35E682993A36718B141979811679C11D5F274542802CD6 CA4C437B6D4C239EE3692F55D3C3CC2B675E18668A8015EA23B6EDF8679114DD 89955A03E23849A40D2D6F29D27F9F7CBC12FC1AA470E554B9089ED64CFC75FB F4A1A3D8337A9D4F313854A2D9C050FF5E3072C65B15FDF82C202F68FB700C14 94CB0BEAC49177A2EC2371EA7AA515534385265044118C801A159351F7A1D71D 0EB50570DF4093E459D3B067823AA3F43F9E72BFB2F77AE2BDFBD917782C5406 03673D21EA2563994CC49D8A2A947808AEADDC87F23E92CF0C0F7B4AAE346C78 536FB8F4A91DCCA4817AB4EAC3EF585A8287A6A6A628E5F0A53C78140EB9FC5A EFB93F761D6ABF9EA3065590CD95903801BE9372B76F1ED79B75D71B9124E643 BA7B5F6BEC678D080058C0489943440360D8F100890F26196F82F88E61BFBF6B CC6907531DE5D5CA4B91E4F9D634A9DD0CD8DE6402E94C756F5904A5BC37A179 A9CC8CC6061ED3BCD51B08C746DBF5D8385AF7389AF4ECC4981D33ED4BC37ACF BD70E1474BAEFC098AA9BF862F153237B0D2EE97E604F8B41741BC38A0B2403C 92B238FE8A3C1456473B6AF6D8F9FD32421B61440B9209B1484F3276BFDABF24 570BAA113D0E06C146B8771F399FCD6906310B8ECEBABDBECD1BCF21EC03D053 60E500F91B4FBB5005D6F4DB331D1B534C15D5C5C04DE155F2808BA11A547E2D F4B6DC0A2A938EAC4612427490F92ECAF7103F55DFCECAD39E76B1355C8EC989 124A09FC9090192F78EDC8E54ECEA741BDBDB8EE8CAB4BA00CBFF9BF98818A65 37CFD9F4302BEC0A7D4E5D770546D77A95D6EE406BDEDC3CDAB1D229A6957474 DD11AFF676C19E4E328C133455152719E95026D4CE07C8DE5E939A69CB8C5D2B CC72BA63102A44B92235A1EBCC109CB8ECA42D9AEF2D7B95EABFD64F3EB225EF E4EBC3FB687CB00513E4014CE228FA3352DEE01A567014F375B77EA45B029451 D8A8E85CD7E3BC527A5E8C44707EDF2E1DE4D476682C609ECDACEE5B5D9284FE 2FCE66AC8900FA34510A458B2EF57CD2E87527CF4C88AD298083D44FCBAF9B98 882614B8B91639DDD9E3D1EDDDB2C137C85455992DC331D6117366B3CEDA8466 071842D5633D709467FD6E44F48C0FDB5528B0AAD26B3958D626569E14EFAA58 B592DBE04142D9B40377F8DF83920C7D979E78F5B63B54B8A478F4A73B5B5905 A06C80E750152AE7C89DC2BCC3A8A7EF592C43FD4624D295A761ED5AE94ABB29 C8B308E10EDB40ADFEABC931078D5C888A85C72451BFD587E73E0491EFBD80BE B0F1E6D9FA7F3DD52561A1D59133EC64BCF2212C82BE4AEE81CF3A20180D032A 267EFDE0D9237B58A48D0E70C92C0C0CC3C46801689118DB38938E7C88C71CFA 91935C2CD9DCC7ABE8F55C74BE28D669F2B51F31838C80ED20BF83291DE67F32 0BD507BD5F27A4C92CD5C2E2ACAC4545B4B62B6040C75F99021E62ACCADD7621 5334B605570F0EBAC7AC6E5E8E7968A8DF189DD604D1CA7D3020551B9189DBEE 079A6D1EE22FBBE1E43BF8D42BB8FB91DD3C1C63E10E99B53CF3135C4553D977 0A7456BE3ED2E2251AD5482F4F51083C8CE3DD2F9348FB6B78233EBB14550E61 E6C598AFED884A6DB3B8D7DF288BE2044CEA11F418EF3B2E6294D9C346564B1B 068C623B971047F0612ECB7157655A06958DACACAFACC0C14CD990FDBFE98C33 024F9D19F939E8A4B7CAE47E0C6F3BD57A2C798243EEDC60195F72DB7C6C13A5 E7968D7436E5962BE4413BC173A4310DB1D012AE618F4C446D40CC395365B7AA 6480A6764396B5093A02C88DB727823721B19CBEECAE261A6F150CDDF3CFEB40 4BBF329CB53724772B35F73DF6B0565A305F2C0BF144750E76624A0EA80786DD A7460E442086D9E463DF4781165AF8D64F5693039903BA8793E8947890823FDE A641E42C221FDCF6832F3744AA1A03717DB22776B34DD116B9AC17A841A3FB3E D627822C0BC41544EE864FA8BACED0FA8C1CB1D1576428269DD2226AEDE06CB9 E2EE674E00B5C43C60D6354340392A8A3A99DCBAE08C2A860AB4AB61C1B5FA27 37987CC398084B20C56C0F7A46305CB266A4128C800F12E5930201D5E7568453 B02D947517639E438DF3306F60F35CBEC1F74335F3F39E803BCE81ED306553C6 6FB6E25837CD62F7B3C573A9547D14998398DEE75CE4ECF0D59AA711AA7C0FA8 2D9F4F7157054C69EAFCAD5C2BD34DECE8411AE76F6140187B34F7159AEA9EAF BFF54D43B9569BF69DEE57D2B72B2FFD226DE355C83E4A2255EC3BF88A36CE9B 26674E8A200B2E8BFC959F8436E01B31483D142D318E221E5A40E637D4760E9A CA70407F57097E56465DD18464CFAE5FA02945D3EC6C45DB6472A2848EC98A66 301C63A761A9F68A23A84A9B01BCA1999AB48318D5556DE86B286127C2FFBFF8 EF6ADE0D8535FEDD63676CA4F2F50FAC64B620DBE16FA0A7BC9F964669ED7E35 B6A9B87C893D96B275FC589770AFE82CA0FC9A5968CD514B778C21F99DEB59C2 1B3F75AA347B576BAA32CF97C0EE9B422CAA852F900212166F0B9CF715F820DC FE222F55980C61F3E6ADB2D6E6268DCBDC2B74A011B41C260EFFE4BFA189D94C 6ABEDC2FC79B8F0807F123D1D928F85775DD2B281C50263E87880A0E60A015D7 3D39C6851D7BEF1E7E0626F4F2579DE80238B932AD5F578D5BFDD585AC3C5BA1 4D013A681B9131C473ED99A248A0B08283A4048B9E5B1A9495389F05E35B9C64 525884AAB12E5A8E058D2E5CF549B11BEB5D084A38CF6C10D393F6BE73D6AFB9 7B2BDDE416711F63A2A06F5ED3D3D065CC139F5392737F59801DC1A2F6B3E712 9EBDE49DD68F804EC60000F3A858182E92DE46DFC5CD036C85613FAEC9694DCF 96A2D8EA8FD5A497406713319809A919BC6185B82FB2BA05BE0D69B7FF2EAA8D 7448E5456C5F241D43517059117587BEF12511472050019422E6CBD2013DC2BE 5B0A099545DA84C8CE959718ACB689AE0DC3C9E96497A108732218BF8AE2BD56 5391BFF57D1F2831B9418AA5FE63608D31EE37361272BA669A7534213EBB09A3 0065C49E4A8EA4FF40181205D3109ACEBBDD8DC9D46F4560BB3250E43320E567 C76836DD711AEABA26BEF38A4244673D1ECD3F13A10C2C3404C823F45ADBEA56 3373BB5C4BCF08FB8F20A8D6E05561381D6ACA2178EC37DF744FFAF9E8E1C2FB A039F33BA035EAF2EB4D4F928274947A0D296454B3905B931C1A3822302A93FE D5131A8FB03BDAE23A1B5F0212F57292C4593480C139C56235696CDA7673B14F 465C951D2369E361E1A39DDC3492D9C5C663268FC6EFE6D6CD7E7CD68FDD996C CA3BC0E32FC249A57C095076A7142B57B48C4BD5C5D056083FE81080E8ECFC2B 87635AD52F0D6A52FDC4AA0029BB9662781E7B0271C9DCD0F1F88436C30E5C1A 3919F6BEC574E5B905E36665CE0EEC42CA0DC0ADED2D3A4707EFF4051F584CF3 321A4DCA23FE91484079FDA322C3421E1F1C9BB5C04338F4C6081426D479F29E 7E819C6C039F2C2FDD140DC5FB836BA352418600AB78ADE5BED20099698C821A D95DB2D024D995F3794021879225B8595E694ACAA2E889B205CDDCAAB4BD95C0 0BC24BC520C5DAD90EA6BBF4AB76310B98DFF30694AD15ABB7E0867D526636B7 EB1F8635A09D3F559EF332201EA72C2C0E752B64DE4CB063DA0E9CB1EA1CCC4A D6C5919D2D86F3870C852B39A61D290D6E64FF77AE711F9D5631553ED0EE0CF8 C430BDA64264EC7085DCAAEACBD2D5BD8CF74157793A1AD75D3DA2912B58BDB9 D47FA8355AE7893F2E316504AFF0787342BA28B5412C5B2C92FA1E1011D2227F 52700351C0660CD64240E6A380ED7E532FB9DAF37DDD353DAB7AA31F005DD9F8 3339C1EE6D184833619538C5FC0EB09CF161E8E0F7BDEF34ACDC2A7AA7DB91B6 6D70DD3C73BFF9CEE0BEF6D6EA61ACF225E8E3768368C638D2C38B81E234A24F 2822E61F61D2BAB5D42222AD8BDC75CE1C19459B4AAA49D8FB785CCA4C1779EE 33D7AB8159C41192AB4E5F6B9217171746BA9A3147D40231B32C6D8C8857ED2C A5E5653B2748E64AFAE309794DFCF61CE1BF97A7DA067E6EB443A41C68CFB47F 1FB598AC5B411F2145769D0EC1CFBEE2C4BD4036E8CE214C5B9A91BE8231B920 7CBA80DEB3029701E61C53DF812A8D4CE9ED206E044B38D0F0651BA2B0D57A65 4D5894C0E934634242420E015F34F24F91275F3B55C4CC76CA06CE07BD0C014D 771070FD248C2F836AE35E2F5BFA2B6EA04983C5B0804ECE338147BEE6BAF694 3CFE3E50410A29D4261FF9B3506B7BE83292D631232438B231BC45EAAF35AF60 CA264092C9A1F30E72EA7AC1A47BDEE830F2318A4F450B6FDCB610BEEB2B2415 4054F4B96962744C23A99EEC2946DD3C27C52268A8992061C746ADF78E34464C D0709A4EC946CA29557F2651B62D4DB764EB51AC8D5F6A9251C67C7358660B64 AEF35020BD35731EA2A3A221E678F222A7A18B35960BB11146AD42A3B7755432 4B8E399C9C73190D55DD532A42C806E61F0376D139733BF8C95AF47894F96C55 C13371B4C23DCE32A9D669F42F1EC62F5B7EDADE0E43E52AD35E64FC2B63419D 6962C4EFAE49EE0171469486A071E124FC152281D42907863987B3298CDAC70F 40227B7EB91B3D2500B5B52C67B0E1C00C00B0FD1C32A31A637488C196A45A68 0796214B5C292308A510AC9F9835829AFFF1D4F0F5070C76BB4D62C43C787EC9 64973716583C3E56CC26D9375AE76BA815E179527D41B08AD9A4799FF43ECFF8 504FF729101081E8297B63FD3E2E4A8A60C2187D56E80AD9BDF773C9DBE12022 D7EED3406C5461A0079837A953A5BD6D856E10CDA9DDCEA668E1A9EF548EAA7F 6323A2581C6F2C3CEFF7AA95990FBAF5CF3C470DB2103A8F613182C40EC2C25E 83FA8BC39B49E89FE2E0F88D1004EF1793D5F1D5FBD7D13CBB8E8314FD2271F5 172B4F0663471BB39112E022156BF755AFCE5539EEA584B38CE90110F5AF981D E38F3C9E0DB13471A69F190F01623CE560631E543D8DD4CD8BF7E8067E2B024D 7844BCB9367B9E9CDF6AB1E051AE7C6AF8BBF0279AB76F91E3096A9B596CD481 ABC06548BBF56D87D68CE8F73CFE1658015612D08B09F9D8A8A94224F3F32306 3A488EF579B9B01F5A20DEDB30461F036C56909A76FA24584B58D1E791DCAB19 A2B879D6CD08433F7B143C34E12E5E6A017FE5A3CED564851F500A2FEA591A73 1402ABA57032E377E88E7D5F7B7667356873639B6576A91EC449679D8A2CFF11 5F06B9EE2AE1F2BA2F2EBE3C679375FE9B552B3387B840DE370E5BCD403AA781 95747DC5B54070B274F63E4CC7CBEBEDECC026F1BA45E0815EA806168B4FCF4A 561B540AFEBF5F20E7900077D3B8B98E2B30542DDCCEF75D31523F6DBDC925DF A219AAEF9050643026C49FF555FA2D545ABCF0C0B583DE9096EF351817993010 A6775D37D4326001B6A514581E2CADF0E90A49D0FC594E77491EFE76166023AF F60B0EEEA9BB4FE37C94C79E4AC5089579CCD9401601BB88842A46B8A889A53C 5AF0DDFAA07309D3709E9B04808E52B65A85C85D4327A70981E43AEAAF8510E4 56633D257C343457094A59410F99ED970EF0650530C9ECF94F54847686F21E79 5E02D132E45F1F430CFC5D5DAD19D075BFAA38699EED9C73276EA7C381A03B1A 4162806EF6E13969EEA1FBC89966B0745BDE1114CE32DBED470F4751DEC36D38 BB1BE46E7E162660DDABA0A9B1EC983DCC7C914AFFE334D658FFF5064A01F6E7 E23D4955DB4AFD2EA0E371F003E68957915893DA2626780FD111EB90CEDB2BF5 CF596382A55F28C43A525E461C8AA9744DB5820AB314B0183B48D1F801509825 FE331F9736D366BB658CBDDF6A4564DA618DECF9CEE7EBFCF1544B1EA1746C51 2E5F7B3A2B2EFCE6C9DB26011523FDD6FA32FC3615CEF4B0739F659D03AB26C3 21728BED1BD965BCF894B654D352B12254F6B204B27611BDD82A2E2DE60CABD9 6EE36EB6D6642D7AB158F8AAE1697CA540C2889BDD9A245BA34440DB21EFF755 15F766B02FB5E6D80AA19982AB19D7F8DA443919848859B103F4EBA3496769AD 496B7E78B3ABD7A95C516854AA97A8F574788729BDD7E04E1D34B640F3080EEC 8F0D6EBD83C496015575FCF9B002BE9AA6BFB7CA9E7CB1B1753B0C95FC9D561B E47D7A5D5A537DA5970C8792488733A277A1AB68F849553BE06E053567E27E75 3AD0FF5A5E249AD9208BB26E948FC9BF854F36CFDE63C2C6EAF3AE98D7A09BCA 93A1E1BDB84617D011DA89F90B350F133F387E734E4B8B70D3F9A6959BCD0679 1914693A5493F7C764507DD95BB903FED1A13289E61AA7CF12DA6D015BCB1E9C 188A823B9B01BDB31F7BDA8000FD5F80FCF92D5A3C199319B6D6863C81C9E0FC A10BA14F42652CAED0F1F7D7642D2EFD4D92B3E781AC03BA7696A87A4553152A 3520C9ED887A3A2535AA2D1F0CEB1D1DAE0708CA0238DE36AC55C535AFABFCAD E30CA91A3A09ADDE7D26281310DB8466E18CA33B43DFBD0FADD4B83016680851 BA9C3CE282ED28F7A200F3FD675D0561FDA731D6AF89045EB5E1F8F9E6C4FE94 2F0FCC80D9BC10A1B6C884F36DE8ABA0BF508F5BD45893B25FDFA559106B067C DF54EB9A3063A15F4769C513B146C382A0AE5429D7C7A912F4A075FC69F58149 B463A4C05CA69B0BF543DE43A11FA9D0B198AF6CAD0743013FA5685EB29C51FB 1CDF0F25D849864B676348D46B843E5AA5F32B5DDC8FD1F583FA666384918A39 50B7643B713C2CF845999B33993CB0928193BDDA2CBCE235C6AE3568EC3B49F6 7A85264646A237758E16CEF056BA5582600D0E269A6F7325DFC3AB3E9D3093C1 352D2D38CF7D20E38297F391D0484B378AD4E52396261EC2DAC5FE88CD47FE05 1A5ACEA9251468753B2889AD6AD61B70821121DA16A547EA99BECA292D8B1EF8 0C3F7AEF8B881E2246F7BF6D1A90E9CA285E7B06423A7012EBD1B224DBA27FDA 2F8E96798705CBDFB1DB849C9376689F6BDE02B9121BA1D2BEB3D1C30B03597D BDC559122BF28348FD4CCB1F0B9761D38C210B8A216937FE2EABBE2E0AD84AC8 E8A18BB49DE6FCB61DC3F92D56A2E932F6F085A9C40F52F734FF3A19F783DF0E 230D2101AA11F06CF5FA6E6A6B7791A6C8B2610B3CB66355C468A7C9C3EAB192 6F8BEBABC4BAE93DC632638DB829DAB434D9E6AF218FCD4BE65BE2DF86AAAF31 E481F80359AFBE9126388BFAED6989F931483CD14FB2500E3233D5539BDE3736 BCBAA1900D8163F501B178C0C2548434C3F68388B19D376F89766123BB78A08C 70BE85F8EB6955C114C9A7C11CFEF270B8BAD791AF4F9B6AF09AD577C28D5758 7ABCB4583129FBEC5E8942BD62A39989731469A762EF902C14AD17E47364658F 6E8DD5726F160024D231440727F1C36448FF44C27BDCA082798AD41456B66957 6FABACD1FAF8311092DC73285C0C6FDD11E974087BF0A987CF8F33A7766C4A76 6A9EEBD28D7E36FCA5A7C97EDBC62360A960220C495709A4BBC799AE67EEAB44 D770D0F38D24E8186A96FBFDBACCFFC67BD72DEBF1A055ADB21CEA9098540C8A D3A2B200963F54BC889CBD250C38065E61588516A25D5E1C502C1835FCD32559 08B04FD75BC68C7A7F90F1EDBA6FBBD166EDEAECF4756CB716A583D2E1438D9A 679EAC8073EF23B44127922BB92227A57B61AD03E8C128EA41E8E91DD30EE885 CF46A93741DCA7F351C98F7EBD4934675F4753798615579B28D7367C65CF012A A960AA3F1D3A9C903EF47A38ACC2434C47E2006F189C10BF5978D7E4978F18AF 382D0A5FB3708A0392A8A87B2FD8C20171DE23BA0C14BE83EB472DF4CC58988F B0D8959109D88C5EA5DF0BF962109263197A51738A00D1A709F3770C691D5E6C F66EDF8F2FA2629F59788B7D811083A8071E6E4D7185117661B366EF5964AC8A AED0F515A063728089FAD3D7586DFB85F0ADBA08517F3C434409300F74DB672E 6DF6BE832D1564C06988DC1469219A24F0233F38C84D721990353B90B2C0EDE7 9F0C3A540D14FA1B7F1CB74936A7B88321CC841CAB20A1E7A92273596A82496E D2401D7456AF4234BB36F7819232C4AB06DBE3F97542CEC05B38B6546269B791 ED2AF1DCB4061D7791F694EE1CCF051590C7F26EE59355DB084E5F609B928A58 B954BCA3E7463BFE064BB7B3DB09773DF3F0ABAEA53AD56F98D7F7BA263304CB AF3390CEF90555746B797084CC0C4996B4F30F54563298A69FBB4013184A1F35 969FF96AE7B3BB247709CB2320A0AD5D619A3E31F49F4CBD03B69C56098A83B3 E4D837861386A976DDFB2DA2A9472F1559943B9794B761898E7375FB2C55E3B5 E605C02952C46F537B2BBFA0B3B357340704448363FC4F20F0245A746E9A18F2 08425531F826E8FCA78866F0402F6D755B39574F57BFFDBB321D435502E0FB60 FBA64BF650EDF8033A246D8544E31C373DB2F250AE2BC5233B85A1290511E588 512035A383C14A2B27363E7C0B2E4DEB8E780FA2A4440CB653CEDF4BDA90945A 4AE0D6343D1B646934DA14505B99E522EE55E02E700B018483E6D10B3E8A6F2D 1001021FB17BDEA02A213BE8A3E33D6200213FDA458D25E8713C18B4EC7E4C6F 98DD981863188AB4EF4846717B770FA9D732C0388C411A0C393713CB4B1549AD 1494D73C958F4DE348C25AF9F845535F111AB37A31874926BAD2ABAF1C9FA2D8 EF4E1EC33232225457B465ECDB466F89BC9DD2A9E82EA7CD2E9BD90403258147 F3F094D3B7F63B576DCFF5E324C82C6801235D0DF850CC6FF7A070EC92456321 BBF4175403ADE97D1F62FD6B1358B7DE7473FF03959C0DD8731D7367D173DA56 170A2F3677A3CBBF9F4D351500860FA504F55FBA655ED5F79AE0E404FC5EA41D BE1334B65CD93468D3B365EF3406777B6CDEB5454945798E6B1FFDA470B089F7 3222BFD4002B7F1E8711E4D1865529C2045B7FD98069CD0674AC9DBC7F31C277 EB88F8BDA01AB9D67611B078D3A72083B6D92F8E96105C15844139424361A983 4B5CD4BE172478E1320D008E73CEB0B5D7DD07C65EAA231B884F822E613ED7C0 A3E24E90BCB4DD0E324A38D133A45704E818ECAFE0C59E420FF122CC71D6E96A A5D5EDD9DBE33296CE6AF62D797F558B884960250F13D11F6DB57BB264A12D89 88856C6B73202A54E9FDFFB7E3FA7E81B21C734B42B44BF2BBA5E8046FDD40FD 923A00084CC2111107D1B8186CD8287FFE1F26993F7D650D73D3A06C93B4B22C 4C64709E8D803BB9A8A3500791260AA785DCF3300E7BE08CAFCBE64A85711461 77543E4117B15B1215DBBAFB64CD4D90B606E42DE9EEA813884CDF19A9AE563D 4D506725A2CEB6D65452E8862D0EAF37AE2D799B7C959D00AFA2AE8C0DC184F5 56780C5EBC3E8AD7D720DA703529CD555CD25491ACA3FE8D9578B07E75FD0F44 98E43F871FCAD2A3F3EDA423A9A2C41B8C388234C9BB7A7D78AF6E5C74B56A42 3D8D31EAAFC3CC1BEB1967859EB33DCE2A51B88A9B5F5B85D13C619BEC3F6CC9 05F02C7C850A341B4B9B4DF952AA66DAB17308CD46913DAC7496CF31A30BB235 997E8D718C6CC2EBD503E131CE11664F4EBF5A0AC3AC0C3BFB2EA6C221AFC902 ABE0DCA95B14F26C7CA969199EE72FB6D2DFF8635703C8EF31C1A934D6BB9164 27C198F43AE7A54E6869E939DE2DBB183766D9F90C7C270EEE0854C72D296A3B 10174961017318135CA16F54C2BB2C422DDA5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSY8 %!PS-AdobeFont-1.1: CMSY8 1.0 %%CreationDate: 1991 Aug 15 07:22:10 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY8) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY8 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 3 /asteriskmath put readonly def /FontBBox{-30 -955 1185 779}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFBB2A7C1B5D8E7E8AA0 5B10EA43D6A8ED61AF5B23D49920D8F79DAB6A59062134D84AC0100187A6CD1F 80F5DDD9D222ACB1C23326A7656A635C4A241CCD32CBFDF8363206B8AA36E107 1477F5496111E055C7491002AFF272E46ECC46422F0380D093284870022523FB DA1716CC4F2E2CCAD5F173FCBE6EDDB874AD255CD5E5C0F86214393FCB5F5C20 9C3C2BB5886E36FC3CCC21483C3AC193485A46E9D22BD7201894E4D45ADD9BF1 CC5CF6A5010B5654AC0BE0DA903DB563B13840BA3015F72E51E3BC80156388BA F83C7D393392BCBC227771CDCB976E93302531886DDA73EBC9178917EFD0C20B 133F1E59AA9B568B69ECCFC0900517036FE3D4C09BBFD937BC5A9C0B89894A8F 63BCCA3746BA056D1B408B16E976D7BAA7D0F7693814ECF52D90BDB3398CF007 CAD14DF246B4D1886070D41A28110F88C9D3EB1F30B1823E0EAA1A35733AD321 E6338D62C26AB6FCD4BBB703248CD7C5CEE83E0167A63F89ACC9D09117C4D017 E773665CB7FA79D22231C8F858735B554E2ED612A436D299491FD31F810F202C C865B87083F980C8DF6A3DD43D437617A69D3E58FFE85F106F7E7F6E50D4D25E 328F7A76B73078B3604C51CCDEAEFA74ADFB9A6C3A5A0EBDCFB578CCBC3553F8 44D4B2853DC7C8415AE3174A4C2209F4107C23000ECC343882C5E2ECA42D8B33 F4846EB85076770BD7E5AF795E1EEEFDC5F0229761DE6BA728FA78549D6E31AC 55ECFE0C64351DCC357F619E3771692B7DF8FFD7FAF48B4299C702F866374FDC 696E83BF09BDB1C40B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.1: CMR12 1.0 %%CreationDate: 1991 Aug 20 16:38:05 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 48 /zero put dup 50 /two put dup 51 /three put dup 74 /J put dup 80 /P put dup 87 /W put dup 97 /a put dup 99 /c put dup 101 /e put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 114 /r put dup 117 /u put dup 121 /y put readonly def /FontBBox{-34 -251 988 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C 68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E 59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F 45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE 96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D 9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB 377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A 0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEBE01C1B982 4B1CF704E817814FF9C921A7DF8CB8898733795DC5382F10417D349D3A7D24B7 E093F2E23BA2C1EE337477E6D51957FEE9206BF92BA12FE5ED4056C4FAB42BCB B9E96E640C88DB1810A0BEC0F3E9F4BF00E642ACEBEF5781F8E57F9B9AF15B57 53572D8E00BEB804C5B7587FF816874FCEE012EE5CCF317AE25E9B3A801A805C 5EA4B24EFB92E54CF85F048BE9DF31C77AB6132EBAC1C124EF5C0DA0719EE902 BFB550602C5A8EA7E31F72207161530AE5DE53624E60A6383DE04E085E20E328 2D3B8009E90861D7309BCAD915694CC31FEABA2FB3DFE8E2C61DC65AB2FEDE93 02327D5B24B0537DA1B1299C9F8D03D6A10055CE522CE067381FFCD4D1E3E173 21CC73B94423D2D44E035E1CDB53846964AD93EB1EB99E6BF51167EFF6A4E33E 71277273918B7F4FCCE3796ACC9725B293CDBF517885C38D66DDDF8FE9D5C98F 771EB2DE9C0993E84AC0486F9361270031C246BBCC721E2D872E45230BFE7B8A 1817A8FAB0C82C2A5B002C9208FD316333C451D59243D312193F38FE79731FA2 BD4FE2DD6A3E4B4FFAABE064F8D2D97628C9FB2428BAAEC5E2AEA4BB1D609B85 2394287D1AA46D8E4B4018A4877F03F6A9E40277EA94C462404537694208AE33 45D7AB349A1916683BFD35479190FDB8E8E1E5F4E5C61774A1D966928E7AE59C 301D1C7D41DB96A94C23F41A650257297F87E726155BE35E84BE5554D97137E6 C0DB7D48CC0B5D6A78428A63A3E594ED30A6F33D6FACD6CD77F69EB2AEDD6767 403F5069AFB93BA02E40A13E9A5899EB68B5FBFB655610CE2FFFD76F0C7C6595 0D8F7BAF05232E793BA4C8C0A8AAA682DFE3E4F4189F9F9EF5785CCFDEE5CA8D E5685C89B52AC73837BC5C6712E4B8480D7EBAD4F54755F8BF549F0B6DEB32BF 7B8A98295BD62F14921F80D98C79BFDBBC84C6EBCDD598B54BD790925C72B0EF 1AE6086B1ACCAE8F9BF52C0AF6DD5FC38190A1457CEEE48DC5193DD6EA1A526F 3EE4CFB5E5EF88A803563D69A720ABFD9FB3AA77CEC8E29F49A9BFADEBA19588 01D88B45D250106F673D7A3F42F0F2539B28D0E6C57DA35B38335DD112CFE6BA D78289AD0B51D642BA212114C64432B8CD80D899FB60BEC1B2887E8AB5E48C58 91D0D4D559ED781196599006B2E3846D836D80DE176660DD8C9ACCD72883B2B4 77D9B991777561D77975456E8D4A7E2ED85FCC0884EB9553A7CD37AB92CE1AA8 009895B4AC7B00DF43FFBA9D96EC702914FFEF294C865B63B2498A54C97F1144 7CBD4DC79C8BD47984A4562F8A6AC40D8DE955EFEFCF78BC66CA604C96161251 420096A2264D7E22B8A3869839FBE8C8CA10082B0253E205500E7F47A03F027A C352CC0FB38F71AAE11F452A3560C63C844018619594C9DB2238162C23083DA6 22A2D92896B83272BE70340A93A08E15834C338077D933AF074372E4B2156190 992182D6AF62272AF7A9C80573D40E5BCD630AECA44FF51531F0028D8F38C91C 0421996D04B5B8FF3FC6435698633A37A84D2C39DF003CB018596F81639B3E86 93CD0F84B1934BAB24DCD0BBB3917E0B44FD109DFC2E437B0B79D37EC708BE69 09DA3B6B9F007B793000AD17A7D351417B6F26E02AD4A6F8BFE1A8C4317F8318 910C5024C8E2C03AAB963055C22D17764C9CEC7DA42FCFBC586DF4F27CB97EDF 91E4533A3151FBCABBF65E59D990719D9282F3CA8AA92D63E3ADDE7A50490CE6 FB007A2A55050A249D0F8A9072F46C99E07FAD9D5F4FC3C8C8B22F6303A1F66A 2F6F1309A9634760C3FE022D0F409D8CA59708FF8E1B719D93385CF45DBF0163 07A656241714503F4B36710123A458BA644307D21FB127E6E5C58BF02B61EDAF EB501080C38A3A8FF84F44B89FF04D247A332B271641B51A7E144437C3061D27 7696FAC42105CB57EF8A9CF333C47A421DC932A6B43D9CCEF85A3411ED5864F9 B298D46E912BBD32B6786E022BAF2ADC7AB7F8BB0C6620CC3214F537D5566B56 3B231615570AF593EE0549761DE550811271E1119CC8D243CD0471A77E7E0EED D8EF19FAE8BF32CAA225305222253C92C38DF2DDDD7AAE446D5458149A190122 A0191DF1015F768D48F3D2178E0C23E1F10317E80302466303A45615A3407436 DA93795EFAA90933030021B6AF5E51D192A3DEB83BBA00736D34F285018980E7 7ED75E6A08CD036B7E5C23C26A2E830B3C80D6CC389D9CD1B2771A87DE65F364 724E7D38003ED421540C5913F7B9011A60FAAF2B8A1A5F23ED9C52B1E109FC76 5C7B5C32328DF9F5568559B6ABFA3027735330B018A1608420FC7ED24A2E15CE 1FFD450A6F30A96B2DFFB53BD7ED444082A11B56291BB7D4314F341BA50E7D3D F9B3EE0EA5644811868C03108E15A6C7205DE872E64E2EE1236B93FC2F67FC40 3BD90F9D5F701AC1341DC7B4CA23551EAE479E1E157198A9F9D769CA701C2F81 0F6DEA36D65978BAD6982DDD54064D3CA2EAC8A92D91C67CFEF3031133D30516 544A4C047D0FAEB451C84DE160382877F7CED5BAE8B0E35B11CBD630999CF4C3 DD0563183FE38F2184BB79A1ED8D8CC73F69840672CCA0691EEFEBFBFD7FE954 ED86CC20598988A79B18766DC512F900775F2822268948701F4CFEF2E401F59C 7F256EFCBE807B84ABE4897D2AF421A1414DDE91124C371DC0A3353B0101F4F7 B1C420A1E72FD9264C626749838A3B708280E7920272DEEF0AA8DA45E0770540 7E86D3C94486AFE3AF466912059792DF482CD577F5C3787262E3ACE8DC9DFE54 96B92F4B030C162FB06E5F27B1CF0AED009EEADCA116694B39AB4EE9524ABFD9 617E98ED071E7E73E7F44005CA35363BD0241BAF45DFC2E4F667A21F9E9BF405 B8E36DEAC34CAF7FA7A6CF3C8BB6AB36F95486824D732818BFAAD9BBA4D455DF E36539DB08E528CA3888C1C59A2A85E0A2BA4CD7BF5C3543B65512BDB08FC111 A2F6A057955C6F707EA439C2AC6C4FB384FFBA470D94EB2487E9801A6AD0B852 557344D11B32B75400EA521DAE97403E8944C3F53E8200CCA04025633B999B82 443115C1FEC7B23A88C01B6CDDF535D284641D2907E108EDD2DF8219B08FCE78 13BBAC3F7AF36ED59F7749B402731F5B5C45517794349397506D893133AC20FA 9638418357ED6BCFBB08D8397661A3B6769A2B3F9A3884977197EACAA0B79F69 7FA986A578B631B64D33AC14946654E88165BD3650CBA76DAF505353AA5903E0 25D21068E4B22A9225A22DD8B1C543E24E3C899F8A23326BA8E47725F0566DE4 F8339574973D0E332853E558CEDB98EDB1E5974070BA39F770A206753178048A 63FD85278038789231B253D8AA40DFBF9F9BD4C6B7AD7004411947DD57ED4136 27746F0D7FC2EDEA705DAD77A20B7DA96312CEA8FDA0F0BB2372E6F3C40B6A21 0877D53D9CBF2EE9655C72D71F98268DF6F5DAF50992E161B2AE95BC12C395BF 2514307964F9A0E0F2F9506E9CDDE5EC3E99B73C3BAC69A0B57FA2A326D3BDEB 3781BE127BEF9D3F5884F21B91491762C545823F756301D0969E74390361D073 C370C66841F77D1D24E00B582DF2AEBD4E100252248C164DEBFAD4BDEEEF8DC0 188C3ED0AE0F97BD176527B68E7D2A7955AA0675A639A42BF5881C282A03B5D9 BEE37474797FFE8B4A1DF9623D7EBFBC7DEEA4AD3F1166547B3F32AF680B9500 1C86D08B4626E26E5C77B1AC7B0CEAC99BF6EED52519BEB561FEE2CB0FE9576C B194B32896B832B4388841C92A80685DB51D72274938 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR17 %!PS-AdobeFont-1.1: CMR17 1.0 %%CreationDate: 1991 Aug 20 16:38:24 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR17) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR17 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 67 /C put dup 70 /F put dup 71 /G put dup 73 /I put dup 79 /O put dup 81 /Q put dup 83 /S put dup 84 /T put dup 97 /a put dup 99 /c put dup 100 /d put dup 101 /e put dup 105 /i put dup 107 /k put dup 114 /r put dup 116 /t put dup 117 /u put readonly def /FontBBox{-33 -250 945 749}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F075EA0A10A15B0ED05D5039DA41B32B16E95 A3CE9725A429B35BAD796912FC328E3A28F96FCADA20A598E247755E7E7FF801 BDB00E9B9B086BDBE6EDCF841A3EAFC6F5284FED3C634085BA4EE0FC6A026E96 96D55575481B007BF93CA452EE3F71D83FAAB3D9DEDD2A8F96C5840EAE5BE5DC 9322E81DFF5E250DEB386E12A49FC9FBF9B4C25C3283F3CEA74B8278A1B09DA7 E9AE4FBAAF23EDF5A3E07D39385D521547C3AAAB8EB70549756EBA8EF445AF4A 497CA924ACCC3DD5456F8E2C7E36946A5BF14E2E959895F7C94F49137256BE46 4A238684D52792234869EAE1A6D8ADF4E138B79472D2A90A6CA99E2394CC20CD 3841733046175B20CEBE372327BF13428EED6A3E2FDF84C2DBA4B0AD584EE9DF B51828D3B8F385846158C29C9AC3496CB9692DD10219697B2ED4D425C3957FD8 C4600D76E045C561216EF05D38177243C314877A69A1C22E3BEC611A2EE5A216 9B7C264CF6D1839DBBD78A40610F2C0D7C2FE09FFA9822FF55035AD52546970F 83EED2D30EABB1F303091EBC11A5379B12BB3F405E371519A53EA9D66174ED25 A2E55463EC71A97BE4C04B39E68112956117C8252DB6FB14AB64534B4BCD568B 246DB833982B38CDE7268BBF74B6B0C18091E1B1F87D32D66F4DD023D1F10D2A 7736A960F72AC01F733A11023832CD68FB6288A5977743F781214D8FA9C0C3F7 80001321D4397771F728FD9EE57CFE7D9192B887EC883EB1505068261DC40089 7B7D2820F06515CD74513521F6397FEAB3AD3572D9A8269430E407E357422461 1785FC2782047F4C0339D79B16862D939F3A37F78E4E2174E4FBF132539CB760 207999FF86F6A3EBE48EB0A1CA635450FDEEF79EB16D853F3BF4B4156F735FAF A48459456EC1B4D72FF323BEC9D55791F10081E94A83ECDDEE2A3911BE6690D1 2BEDC34E7FB692B36A078DF52E761DA5BCDFFE8C6A64B6E6C633D4656CDB0CEC 198EC18DDD3031695D98888F72AEECD5CFE83260790707C3B471C17575127E2B 4BBAB487E96CEB7AA9346CB3B0C577D55226E44493EA8325E60BA821D9A6A9EE 0F81F3B3B43F30717553D92FE2F68BDEAF47C2C333F2889BA57F977A25424887 F947351DA7609E7D8D22C4F82415A63B83984B040C4C5944C6E36BD9898B0B18 F901B49A3FC5DA8D8DDC72210897B71E4D7DF418A7880B9B174B2A4F328DA7C8 FAD975E5657AF208A8381491BB159576CA96B54D235E6DB1FB320202DE6FE50D 7222DF9D4B745AAA1DC99D233ACEA2308CA87B7672F3057D3AAA3B8EA845F953 404C98E0985BA0BC8B6821F0089F6DB6BADD771406884672C9CEEE3E3136A32A A9DB459E705E041D98756ECB474D11BE8BD55ACCAB3C167B1EA11B7ED5AE6694 91197E9FB37E6AF997D1FF15B186505830789C19821DE5DA62FA888CC2C5AFD3 C0A243E39C48B98F837C87730BBB9A03E8BBDFE260DEB47822BBEA03C0F21FEA B644B1CDD2AEF52E5F2494676DEDEACD9ED89E2FB5FB5FFD14661A8701680FDE F27E716E1FB901227058A4C5C7CCCF9132D643409B46D6AC86828DF63FD40B8A 5D22F0D9B6F00216E3BA318C5B9EFDAD04FD6B1677A5C2A3AB503A436F6A2F55 EE37E9643259976A0A8425ABF863D4C66257E086B6F7811195FC8B20103C40C5 0329309E5C45253372762CA78ADF69AA56B3D642B2D5EAA092369865A2BCBB34 00E9924E31833320B636719A514B977F00261C4F782F63E3CED4B7AB7F58A685 6E529975417F43F801C3205449D4B95B2B1FEFBF1442F33B8A570E30350DB2D2 71CD7E333032367CF335B789D81202E1FE3CEA11382E5BCE751C51396A99FF9F 085D4FBF967AC8452EE633CF741011609A2DF3EB88A35DC3D8B47D1FBDAA8FAA 01EB756739B6AF9462DA13B3CD4DF3DDEE6E682B6500F2BDB6540E7EF295BE67 99D2F86B5A1EC89F20D88DF00962606E0BA15A6BFC772C72E50D4D67DC4B71EF A94FF2339E9377AF27A92BB8B9011338410D30CBCA33C5C90D22BC6C64153708 8EECF6CD2AB2143C6E19F865B11B561B28E5BD2A9271CEB846A588BC34784074 90757581B8DC08CC8D75184991532E9F0D3EA2A142213F0EB8DE2BFEA732B77C 4D854AF02B92AB046123EA0F96544A241BDAFB02B2A9095C342945468C50903D 8E6E8EAE6E72B8F4946DE02DAB91864B53359AE741F095A9D118C42DAD62BC01 DFBB386111F9BFD37B0E8BF85708EEB1B39CE3935288197A5658D74AF4B0E5BA AB39E1B33C8C7021680647E6298B5976C5E7E5A41C478A07A6DF0227630FD1B1 FB3E5E671177D2654598F3EB5393202CE28559AEABD64E343A18AB1664472080 6626EA9B789FC0BB90FA1977514D3C3848163C7CFBCFEBDE0F62C184F83955E4 9306CBE4715809D6789D0A65522229E6D08A139624932EA705229EF99E243DED E125C95EB549BBB9D91B68CD1438EB23BAD1C41762973DC781F324672C3AF537 706A63CBA3090575530CBE5ADA9658C8AB664E475D3F4E83308E82E256A7AD95 E323BB6A94CC0ED154304EAE95EC4175AA24E44C2257B471F14CA9CB6F57BB4D 445E256BA592017F89D45221D3B33A2617C680F5E5292AD80B62DF74195F0FD5 751BCAA8C8D62E0F81AAEE4FCB75A2E12C9C396BB5AD47207ED46FD39C2F03C0 7BE1A50F88BAAA4F639A5DB9807524DED9AEB5FDD9853308CAE5CCCA1D686F7B 65F742D0AD1784A1BF7464373ED630D9DFFD90DE75D664087BED3FB64002FC09 D608A8FB8BEFB9826A20616FA062B878DD536A6698A16107C2BAEAD4DC4A1F9A 762C8BED80715A1CB9280B59C8A239F93817DBAFB78877AB8EBE6D0E06CD47D5 40DA9F1586B227F8F0ABDBDCD2CC96EB61021726CA1C64F06FE173FDE1BFEF53 FE922E4EF539F2F608C745DCFEF232F9E31E4422CC7D234B4199570EEE1A851A 48CB3C0548E5EC973642C70F2341CE45CE1CEDFF5C9CF52E6CE5AE642F20FC76 42FF3636B821A9D200D4917E649C851B79BB6DB61B7BC1FA5DF3574AFAEDB447 F67057131C96B7453F879D0FE8AF4D5291FA4037C4C76CA7BD6C0D9181EE09AA 5C60C008E8A7C4D15748CA6F6FD2B7C6A55CBD816409299616FD4153EF63E121 BDE077D2AF5D2FAEE8B6D6004EB569B398A3ADEE957B2003F524BA8DC248ACC3 9A813584955514610F5ED6CE54ECB06FEAE5638EE92AEDF446D23CB3F7F3F580 B11145C03146D73FA56920AC873813CA164089B9A6C19BAE482B8C94726EAE04 2805019DFF8E8F648FAA35EC7DB1AE3DDAC526ACE937F1DEB3E165699BA5879C 3703AF8BB30CE970E961B253024F82E73356B778BA2B52EF8ED83840E58F35E9 2C3864F74BB81FA96462393371827A3A495F7863B511080A6BEF0F358FC74C3A B69FE66AB8883E2146B42F2B3830F81A320C95CA68A39D7F477E44DBD8E2479B 56D0F614BBE4CC4601C878C8062902FE58978C9C5AD39A6D1F994ED4D0924522 25B011B5FBB553DAAD10CF3A6E26D8DD05F4844028D27DA0838BF0B2BF1B911B 7767E654A897D1C8CA4CAF8350986E853539561E927BC1A080AC4B469B78ED39 A69B5DC9B0D574BDF455EFC6BFA57C51052EBE883EBA245C8CCC570937436480 68BCD6219DB49CD850B41F40829C6F371A8E30249339229560425E452648DC34 FB7F26F92B75C9041F39F535B6755C957008118C634EE6D9109724F0AB20394C 15EDDE5EBA22D8C2FB8ECD7DF64213489A9BE1C7D7349A7564698908F31D40FD 801744BB39011DD455DB7E8D5DC9132FBF394307B6CEF020126C27D09C3B8A94 A48F670A18629AF96288C661284F0255A738E5878D18C0935E5C8979AF0DB055 E40A1E1B43C54743CD0C580CC8816FA290F5607580701433E7D3E478790E601E 3C9FD14BBE364AF5B74709EE37917F2B951A8CE286168981D1C7F47373E2F890 48EE22E3DD583A4FCCF20C5EDF82913664C528AC123F605600505D2A5081EBEB CD70C429F653753449900BD5CFDC00DCDAFFD97DE63002E1501799B7DBD221AE D0CD6AD33125FF1FAF59CF8B4D5E198BCA1C979440C2F9DE7D6C6AD842CA772E 2D8F9F65B1DC63CC3C491ED6AB32E9A215B0A769B44EA1CAC6CFA0E1510DE47E C212486745C14DF4E25EF7BBF691399099B7784329906133CC5196E775FB118E 7B7B0874E7ED63D09BDF212AC3539D13AF2502D417C91D8B32BD547E1D9A6A83 DCFEB61AB6685EF508C4C2501C2595E34ABA0591E6EBBA8CC280EFF9A8E98B41 11B7719DAF2D47900127DDFE0C8E53175F7A47189AFD3D2EB44A7999D7121F44 14A52FDEEC074C08CAF1DAE24CC9409E49E14D5FEE182733A7034293193BEBF7 DD577E6BF8849F541785363CA81DADDCC5F647FB2F9439E6A235E191D56D267C 75BD4FB3A4DB698C89D01E0F2FC151C5CE77C78ABF166532E506AFDF95991554 9E0A103B5059038358CB5E6CAC08201D62B319E2CE16EE236163679DDA3588FB 2BA260BE394C947BE83F2E6355A05A2AE2BB83D857535A75483F247028033D64 EF8657CB9C0ADB35721ABF0120E94750DA098EB448506BABADAC2E57658F7B35 991A4876C41924F45B24D28B9999EC06AFB581A49E2246F19B15CE492F318AE3 364C07D85229D41B91C9156639022FB0845E8E7EA20C1D3E48824842010550B6 4A60DC177B7D081F9FDF00E739C9EEA814A0B7A9F94C67896889367B21D4B8B1 E4916222E5FFD7B01001201F5B820597A872BD8C273EF291D10E1CB3C1EA2078 698B93975D06D3CFDCA014E72059873320E6B3601261A976125F67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont TeXDict begin 40258431 52099146 1000 600 600 (quick.dvi) @start /Fa 149[25 2[45 45 86[45 15[{}4 90.9091 /CMSY10 rf /Fb 134[59 59 81 59 62 44 44 46 1[62 56 62 93 31 2[31 1[56 1[51 62 1[62 54 11[86 78 1[84 2[84 88 2[88 1[42 88 1[70 74 86 81 11[56 56 56 56 56 56 56 1[56 31 37 45[{}41 99.6264 /CMBX12 rf /Fc 129[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}94 90.9091 /CMTT10 rf /Fd 139[30 1[30 1[43 38 43 1[21 2[21 43 38 1[34 43 34 1[38 13[43 57 3[58 5[58 60 50 52 1[55 1[58 20[21 44[{}23 74.7198 /CMR9 rf /Fe 252[32 3[{}1 49.8132 /CMSY6 rf /Ff 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 45 25 56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 1[71 1[25 25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 1[45 76 45 25 18[76 51 51 53 11[{}89 90.9091 /CMR10 rf /Fg 134[55 55 76 55 58 41 41 43 1[58 52 58 87 29 2[29 1[52 32 48 58 46 58 51 11[80 73 58 78 1[71 79 82 2[82 1[40 1[82 66 69 1[76 74 9[52 1[52 52 52 52 52 52 2[29 46[{}43 90.9091 /CMBX10 rf /Fh 135[71 2[75 52 53 55 1[75 67 75 112 37 2[37 1[67 1[61 75 60 1[65 11[103 94 75 100 1[92 101 105 4[50 2[85 88 1[97 12[67 67 67 67 67 67 49[{}33 119.552 /CMBX12 rf /Fi 252[35 3[{}1 66.4176 /CMSY8 rf /Fj 134[51 3[54 2[38 3[54 81 27 2[27 3[43 1[43 1[49 9[100 6[66 5[50 22[49 49 1[49 48[{}16 99.6264 /CMR12 rf /Fk 138[73 51 1[51 6[70 1[36 3[58 73 58 1[66 12[96 73 1[103 1[103 5[47 1[104 86 2[96 67[{}17 143.462 /CMR17 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: Letter letter %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 1125 937 a Fk(CFITSIO)44 b(Quic)l(k)g(Start)e (Guide)1625 1190 y Fj(William)33 b(P)m(ence)2277 1154 y Fi(\003)1666 1394 y Fj(Jan)m(uary)g(2003)120 1916 y Fh(Con)l(ten)l(ts)120 2120 y Fg(1)84 b(In)m(tro)s(duction)2897 b(2)120 2324 y(2)84 b(Installing)35 b(and)g(Using)h(CFITSIO)2080 b(3)120 2528 y(3)84 b(Example)35 b(Programs)2601 b(4)120 2731 y(4)84 b(CFITSIO)33 b(Routines)2603 b(6)256 2844 y Ff(4.1)94 b(Error)30 b(Rep)s(orting)25 b(.)45 b(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(6)256 2957 y(4.2)94 b(File)32 b(Op)s(en/Close)e(Routines)58 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(6)256 3070 y(4.3)94 b(HDU-lev)m(el)34 b(Routines)86 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(7)256 3183 y(4.4)94 b(Image)32 b(I/O)e(Routines)80 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(9)256 3296 y(4.5)94 b(T)-8 b(able)31 b(I/O)g(Routines)e(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(12)256 3409 y(4.6)94 b(Header)31 b(Keyw)m(ord)f(I/O)h(Routines)79 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(19)256 3522 y(4.7)94 b(Utilit)m(y)33 b(Routines)27 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(22)120 3726 y Fg(5)84 b(CFITSIO)33 b(File)i(Names)g(and)f(Filters)1907 b(23)256 3839 y Ff(5.1)94 b(Creating)31 b(New)g(Files)45 b(.)h(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(23)256 3951 y(5.2)94 b(Op)s(ening)30 b(Existing)g(Files)41 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(24)256 4064 y(5.3)94 b(Image)32 b(Filtering)56 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(26)465 4177 y(5.3.1)106 b(Extracting)32 b(a)f(subsection)f(of)h(an)f (image)77 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)129 b(26)465 4290 y(5.3.2)106 b(Create)32 b(an)e(Image)h(b)m(y)f(Binning)g(T)-8 b(able)31 b(Columns)i(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(26)256 4403 y(5.4)94 b(T)-8 b(able)31 b(Filtering)77 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)129 b(28)465 4516 y(5.4.1)106 b(Column)30 b(and)g(Keyw)m(ord)g (Filtering)50 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(28)465 4629 y(5.4.2)106 b(Ro)m(w)31 b(Filtering)42 b(.)j(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(29)465 4742 y(5.4.3)106 b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)129 b(32)465 4855 y(5.4.4)106 b(Spatial)31 b(Region)h(Filtering)59 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)129 b(32)465 4968 y(5.4.5)106 b(Example)31 b(Ro)m(w)g(Filters)h(.) 45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(34)256 5081 y(5.5)94 b(Com)m(bined)30 b(Filtering)i(Examples)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(36)120 5284 y Fg(6)84 b(CFITSIO)33 b(Error)i(Status)f(Co)s(des)2069 b(38)p 120 5346 1465 4 v 222 5400 a Fe(\003)258 5431 y Fd(HEASAR)n(C,)25 b(NASA)f(Go)r(ddard)i(Space)f(Fligh)n(t)h(Cen)n (ter)1928 5809 y Ff(1)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 120 573 a Fh(1)135 b(In)l(tro)t(duction)120 776 y Ff(This)34 b(do)s(cumen)m(t)g(is)g(in)m(tended)g(to)h(help)f(y)m (ou)h(quic)m(kly)g(start)g(writing)f(C)g(programs)g(to)h(read)f(and)g (write)120 889 y(FITS)45 b(\014les)g(using)g(the)g(CFITSIO)f(library)-8 b(.)86 b(It)45 b(co)m(v)m(ers)i(the)f(most)f(imp)s(ortan)m(t)h(CFITSIO) d(routines)120 1002 y(that)i(are)f(needed)g(to)h(p)s(erform)d(most)i(t) m(yp)s(es)h(of)f(op)s(erations)g(on)g(FITS)f(\014les.)82 b(F)-8 b(or)45 b(more)f(complete)120 1115 y(information)d(ab)s(out)e (these)i(and)f(all)h(the)f(other)h(a)m(v)-5 b(ailable)42 b(routines)e(in)g(the)h(library)f(please)h(refer)f(to)120 1227 y(the)c(\\CFITSIO)e(User's)i(Reference)g(Guide",)i(whic)m(h)d(is)g (a)m(v)-5 b(ailable)38 b(from)d(the)h(CFITSIO)e(W)-8 b(eb)36 b(site)h(at)120 1340 y Fc(http://heasarc.gsfc.nasa)o(.gov)o (/fit)o(sio)o Ff(.)261 1453 y(F)-8 b(or)41 b(more)f(general)g (information)g(ab)s(out)g(the)g(FITS)f(data)h(format,)j(refer)d(to)g (the)g(follo)m(wing)h(w)m(eb)120 1566 y(page:)g(h)m (ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/heasa)q(rc/\014ts.h)m(t)q(ml) 261 1679 y(FITS)27 b(stands)h(for)g(Flexible)h(Image)g(T)-8 b(ransp)s(ort)27 b(System)h(and)f(is)h(the)h(standard)e(\014le)h (format)g(used)g(to)120 1792 y(store)j(most)g(astronomical)h(data)g (\014les.)41 b(There)30 b(are)h(2)g(basic)g(t)m(yp)s(es)f(of)h(FITS)f (\014les:)41 b(images)31 b(and)f(tables.)120 1905 y(FITS)j(images)i (often)f(con)m(tain)h(a)f(2-dimensional)g(arra)m(y)h(of)e(pixels)h (represen)m(ting)g(an)g(image)h(of)e(a)h(piece)120 2018 y(of)f(the)f(sky)-8 b(,)34 b(but)e(FITS)g(images)h(can)g(also)h(con)m (tain)g(1-D)f(arra)m(ys)g(\(i.e,)i(a)e(sp)s(ectrum)e(or)i(ligh)m(t)g (curv)m(e\),)h(or)120 2131 y(3-D)40 b(arra)m(ys)f(\(a)g(data)g(cub)s (e\),)i(or)d(ev)m(en)i(higher)e(dimensional)h(arra)m(ys)f(of)h(data.)66 b(An)38 b(image)i(ma)m(y)f(also)120 2244 y(ha)m(v)m(e)30 b(zero)g(dimensions,)e(in)h(whic)m(h)f(case)i(it)f(is)g(referred)f(to)i (as)f(a)g(n)m(ull)g(or)g(empt)m(y)g(arra)m(y)-8 b(.)41 b(The)28 b(supp)s(orted)120 2357 y(datat)m(yp)s(es)f(for)f(the)h(image) h(arra)m(ys)e(are)h(8,)h(16,)g(and)e(32-bit)i(in)m(tegers,)h(and)c(32)j (and)d(64-bit)j(\015oating)f(p)s(oin)m(t)120 2469 y(real)k(n)m(um)m(b)s (ers.)39 b(Both)31 b(signed)g(and)e(unsigned)h(in)m(tegers)h(are)g (supp)s(orted.)261 2582 y(FITS)j(tables)h(con)m(tain)g(ro)m(ws)f(and)g (columns)g(of)g(data,)i(similar)f(to)g(a)g(spreadsheet.)52 b(All)35 b(the)f(v)-5 b(alues)120 2695 y(in)31 b(a)g(particular)g (column)g(m)m(ust)f(ha)m(v)m(e)j(the)e(same)g(datat)m(yp)s(e.)43 b(A)31 b(cell)h(of)f(a)g(column)g(is)g(not)g(restricted)h(to)120 2808 y(a)g(single)f(n)m(um)m(b)s(er,)g(and)f(instead)i(can)f(con)m (tain)i(an)e(arra)m(y)g(or)h(v)m(ector)g(of)g(n)m(um)m(b)s(ers.)41 b(There)31 b(are)h(actually)120 2921 y(2)43 b(subt)m(yp)s(es)f(of)h (FITS)f(tables:)66 b(ASCI)s(I)41 b(and)i(binary)-8 b(.)77 b(As)43 b(the)g(names)g(imply)-8 b(,)46 b(ASCI)s(I)41 b(tables)j(store)120 3034 y(the)37 b(data)h(v)-5 b(alues)37 b(in)g(an)f(ASCI)s(I)g(represen)m(tation)i(whereas)e(binary)h(tables)g (store)h(the)f(data)g(v)-5 b(alues)38 b(in)120 3147 y(a)33 b(more)f(e\016cien)m(t)i(mac)m(hine-readable)f(binary)f(format.)46 b(Binary)33 b(tables)g(are)f(generally)i(more)e(compact)120 3260 y(and)25 b(supp)s(ort)e(more)j(features)f(\(e.g.,)j(a)e(wider)f (range)g(of)h(datat)m(yp)s(es,)h(and)e(v)m(ector)i(columns\))e(than)g (ASCI)s(I)120 3373 y(tables.)261 3486 y(A)31 b(single)g(FITS)f(\014le)h (man)m(y)g(con)m(tain)h(m)m(ultiple)f(images)h(or)f(tables.)42 b(Eac)m(h)31 b(table)h(or)e(image)i(is)f(called)120 3599 y(a)j(Header-Data)j(Unit,)e(or)f(HDU.)h(The)f(\014rst)f(HDU)i(in)e(a)i (FITS)e(\014le)h(m)m(ust)g(b)s(e)f(an)h(image)i(\(but)d(it)i(ma)m(y)120 3711 y(ha)m(v)m(e)30 b(zero)f(axes\))h(and)e(is)h(called)h(the)f (Primary)f(Arra)m(y)-8 b(.)41 b(An)m(y)28 b(additional)i(HDUs)f(in)g (the)f(\014le)h(\(whic)m(h)g(are)120 3824 y(also)i(referred)f(to)h(as)g (`extensions'\))g(ma)m(y)g(con)m(tain)h(either)f(an)f(image)i(or)e(a)h (table.)261 3937 y(Ev)m(ery)38 b(HDU)g(con)m(tains)h(a)f(header)g(con)m (taining)h(k)m(eyw)m(ord)f(records.)62 b(Eac)m(h)38 b(k)m(eyw)m(ord)g (record)g(is)g(80)120 4050 y(ASCI)s(I)29 b(c)m(haracters)j(long)f(and)e (has)i(the)f(follo)m(wing)i(format:)120 4263 y Fc(KEYWORD)46 b(=)h(value)g(/)g(comment)f(string)261 4475 y Ff(The)23 b(k)m(eyw)m(ord)i(name)f(can)g(b)s(e)f(up)g(to)h(8)g(c)m(haracters)i (long)e(\(all)h(upp)s(ercase\).)38 b(The)23 b(v)-5 b(alue)25 b(can)f(b)s(e)f(either)120 4588 y(an)k(in)m(teger)h(or)e(\015oating)i (p)s(oin)m(t)e(n)m(um)m(b)s(er,)h(a)g(logical)i(v)-5 b(alue)27 b(\(T)g(or)f(F\),)i(or)e(a)h(c)m(haracter)i(string)d (enclosed)i(in)120 4701 y(single)e(quotes.)40 b(Eac)m(h)26 b(header)f(b)s(egins)g(with)g(a)h(series)g(of)g(required)f(k)m(eyw)m (ords)g(to)i(describ)s(e)e(the)g(datat)m(yp)s(e)120 4814 y(and)35 b(format)h(of)f(the)h(follo)m(wing)h(data)f(unit,)g(if)f(an)m (y)-8 b(.)57 b(An)m(y)35 b(n)m(um)m(b)s(er)g(of)g(other)h(optional)g(k) m(eyw)m(ords)g(can)120 4927 y(b)s(e)d(included)g(in)g(the)g(header)h (to)g(pro)m(vide)f(other)h(descriptiv)m(e)h(information)e(ab)s(out)h (the)f(data.)51 b(F)-8 b(or)34 b(the)120 5040 y(most)g(part,)g(the)g (CFITSIO)d(routines)j(automatically)i(write)d(the)h(required)f(FITS)f (k)m(eyw)m(ords)i(for)f(eac)m(h)120 5153 y(HDU,)e(so)g(y)m(ou,)g(the)g (programmer,)f(usually)g(do)g(not)h(need)f(to)h(w)m(orry)f(ab)s(out)g (them.)1928 5809 y(2)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 120 573 a Fh(2)135 b(Installing)46 b(and)f(Using)g(CFITSIO)120 776 y Ff(First,)33 b(y)m(ou)f(should)e(do)m (wnload)i(the)g(CFITSIO)e(soft)m(w)m(are)j(and)e(the)h(set)g(of)g (example)h(FITS)e(utilit)m(y)i(pro-)120 889 y(grams)e(from)f(the)g(w)m (eb)h(site)g(at)h(h)m(ttp://heasarc.gsfc.nasa.go)m(v/\014tsio.)47 b(The)30 b(example)h(programs)f(illus-)120 1002 y(trate)g(ho)m(w)e(to)h (p)s(erform)f(man)m(y)g(common)h(t)m(yp)s(es)f(of)h(op)s(erations)g(on) f(FITS)g(\014les)h(using)f(CFITSIO.)f(They)120 1115 y(are)h(also)h (useful)d(when)h(writing)h(a)g(new)f(program)g(b)s(ecause)h(it)g(is)g (often)g(easier)g(to)h(tak)m(e)g(a)f(cop)m(y)g(of)g(one)g(of)120 1227 y(these)k(utilit)m(y)h(programs)e(as)g(a)h(template)h(and)e(then)g (mo)s(dify)f(it)i(for)f(y)m(our)h(o)m(wn)f(purp)s(oses,)f(rather)i (than)120 1340 y(writing)e(the)h(new)f(program)g(completely)i(from)e (scratc)m(h.)261 1453 y(T)-8 b(o)28 b(build)e(the)i(CFITSIO)d(library)i (on)g(Unix)g(platforms,)i(`un)m(tar')e(the)h(source)f(co)s(de)h (distribution)e(\014le)120 1566 y(and)k(then)g(execute)i(the)e(follo)m (wing)i(commands)e(in)g(the)h(directory)f(con)m(taining)i(the)f(source) g(co)s(de:)120 1779 y Fc(>)95 b(./configure)45 b ([--prefix=/target/instal)o(lati)o(on/)o(path)o(])120 1892 y(>)95 b(make)524 b(\(or)47 b('make)f(shared'\))120 2005 y(>)95 b(make)47 b(install)141 b(\(this)46 b(step)h(is)g (optional\))261 2217 y Ff(The)40 b(optional)i('pre\014x')e(argumen)m(t) h(to)g(con\014gure)f(giv)m(es)i(the)f(path)f(to)h(the)g(directory)g (where)f(the)120 2330 y(CFITSIO)30 b(library)i(and)f(include)h(\014les) g(should)f(b)s(e)g(installed)i(via)g(the)f(later)h('mak)m(e)g(install') g(command.)120 2443 y(F)-8 b(or)31 b(example,)120 2655 y Fc(>)95 b(./configure)45 b(--prefix=/usr1/local)261 2868 y Ff(will)21 b(cause)g(the)g('mak)m(e)h(install')g(command)e(to)h (cop)m(y)h(the)e(CFITSIO)f(lib)s(c\014tsio)i(\014le)g(to)g(/usr1/lo)s (cal/lib)120 2981 y(and)35 b(the)h(necessary)g(include)g(\014les)g(to)g (/usr1/lo)s(cal/include)i(\(assuming)e(of)f(course)h(that)h(the)f(pro)s (cess)120 3094 y(has)30 b(p)s(ermission)f(to)j(write)e(to)h(these)g (directories\).)261 3207 y(Pre-compiled)f(v)m(ersions)g(of)g(the)g (CFITSIO)e(DLL)i(library)f(are)h(a)m(v)-5 b(ailable)32 b(for)d(PCs.)40 b(On)29 b(Macin)m(tosh)120 3320 y(mac)m(hines,)46 b(refer)c(to)g(the)h(README.MacOS)g(\014le)f(for)g(instructions)g(on)g (building)f(CFITSIO)g(using)120 3432 y(Co)s(deW)-8 b(arrior.)261 3545 y(An)m(y)40 b(programs)g(that)h(use)f(CFITSIO)f(m)m(ust)h(of)g (course)h(b)s(e)e(link)m(ed)i(with)f(the)g(CFITSIO)f(library)120 3658 y(when)e(creating)i(the)f(executable)i(\014le.)64 b(The)37 b(exact)j(pro)s(cedure)c(for)i(linking)g(a)h(program)e(dep)s (ends)f(on)120 3771 y(y)m(our)31 b(soft)m(w)m(are)i(en)m(vironmen)m(t,) f(but)f(on)g(Unix)g(platforms,)h(the)f(command)g(line)h(to)g(compile)g (and)f(link)g(a)120 3884 y(program)f(will)h(lo)s(ok)g(something)g(lik)m (e)g(this:)120 4097 y Fc(gcc)47 b(-o)g(myprog)f(myprog.c)g(-L.)h (-lcfitsio)e(-lm)i(-lnsl)f(-lsocket)261 4309 y Ff(Y)-8 b(ou)37 b(ma)m(y)g(not)f(need)g(to)h(include)g(all)g(of)f(the)h('m',)h ('nsl',)g(and)e('so)s(c)m(k)m(et')i(system)f(libraries)f(on)g(y)m(our) 120 4422 y(particular)41 b(mac)m(hine.)73 b(T)-8 b(o)42 b(\014nd)d(out)i(what)g(libraries)g(are)g(required)f(on)h(y)m(our)g (\(Unix\))g(system,)j(t)m(yp)s(e)120 4535 y Fc('make)i(testprog')28 b Ff(and)i(see)h(what)f(libraries)h(are)f(then)h(included)e(on)h(the)h (resulting)g(link)f(line.)1928 5809 y(3)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 120 573 a Fh(3)135 b(Example)46 b(Programs)120 776 y Ff(Before)32 b(describing)f(the)h(individual)f (CFITSIO)e(routines)j(in)f(detail,)i(it)e(is)h(instructiv)m(e)g(to)g (\014rst)f(lo)s(ok)h(at)120 889 y(an)27 b(actual)h(program.)40 b(The)26 b(names)h(of)g(the)g(CFITSIO)f(routines)h(are)g(fairly)g (descriptiv)m(e)h(\(they)g(all)g(b)s(egin)120 1002 y(with)i Fc(fits)p 525 1002 29 4 v 33 w Ff(,)h(so)g(it)f(should)g(b)s(e)g (reasonably)g(clear)i(what)e(this)g(program)g(do)s(es:)120 1202 y Fc(------------------------)o(----)o(----)o(---)o(----)o(----)o (---)o(----)o(----)o(---)o(----)o(---)311 1315 y(#include)45 b()311 1428 y(#include)g()120 1541 y(1:)95 b(#include)45 b("fitsio.h")311 1767 y(int)i(main\(int)e(argc,)i (char)f(*argv[]\))311 1879 y({)120 1992 y(2:)286 b(fitsfile)45 b(*fptr;)502 2105 y(char)h(card[FLEN_CARD];)120 2218 y(3:)286 b(int)47 b(status)f(=)h(0,)95 b(nkeys,)46 b(ii;)95 b(/*)47 b(MUST)g(initialize)e(status)h(*/)120 2444 y(4:)286 b(fits_open_file\(&fptr,)42 b(argv[1],)j(READONLY,)h(&status\);)502 2557 y(fits_get_hdrspace\(fptr,)41 b(&nkeys,)46 b(NULL,)g(&status\);) 502 2783 y(for)h(\(ii)g(=)g(1;)g(ii)g(<=)h(nkeys;)e(ii++\))94 b({)597 2896 y(fits_read_record\(fptr,)42 b(ii,)47 b(card,)f (&status\);)g(/*)h(read)f(keyword)g(*/)597 3009 y(printf\("\045s\\n",)e (card\);)502 3121 y(})502 3234 y(printf\("END\\n\\n"\);)90 b(/*)48 b(terminate)d(listing)h(with)g(END)h(*/)502 3347 y(fits_close_file\(fptr,)42 b(&status\);)502 3573 y(if)47 b(\(status\))475 b(/*)47 b(print)g(any)g(error)f(messages)f(*/)120 3686 y(5:)477 b(fits_report_error\(stder)o(r,)42 b(status\);)502 3799 y(return\(status\);)311 3912 y(})120 4025 y (------------------------)o(----)o(----)o(---)o(----)o(----)o(---)o (----)o(----)o(---)o(----)o(---)261 4225 y Ff(This)29 b(program)g(op)s(ens)f(the)h(sp)s(eci\014ed)g(FITS)f(\014le)i(and)e (prin)m(ts)h(out)g(all)h(the)g(header)f(k)m(eyw)m(ords)g(in)g(the)120 4338 y(curren)m(t)h(HDU.)i(Some)e(other)h(p)s(oin)m(ts)f(to)h(notice)h (ab)s(out)e(the)g(program)g(are:)231 4516 y(1.)46 b(The)30 b Fc(fitsio.h)e Ff(header)i(\014le)g(m)m(ust)h(b)s(e)e(included)h(to)h (de\014ne)e(the)i(v)-5 b(arious)30 b(routines)g(and)g(sym)m(b)s(ols)347 4629 y(used)g(in)g(CFITSIO.)231 4812 y(2.)46 b(The)37 b Fc(fitsfile)e Ff(parameter)i(is)g(the)g(\014rst)g(argumen)m(t)g(in)g (almost)h(ev)m(ery)g(CFITSIO)d(routine.)61 b(It)347 4925 y(is)41 b(a)h(p)s(oin)m(ter)f(to)h(a)g(structure)e(\(de\014ned)g(in)h Fc(fitsio.h)p Ff(\))f(that)h(stores)h(information)f(ab)s(out)g(the)347 5038 y(particular)i(FITS)e(\014le)h(that)h(the)g(routine)f(will)g(op)s (erate)h(on.)76 b(Memory)43 b(for)f(this)g(structure)f(is)347 5151 y(automatically)36 b(allo)s(cated)e(when)e(the)h(\014le)g(is)f (\014rst)g(op)s(ened)g(or)h(created,)h(and)e(is)h(freed)f(when)g(the) 347 5264 y(\014le)f(is)f(closed.)231 5447 y(3.)46 b(Almost)41 b(ev)m(ery)f(CFITSIO)e(routine)h(has)h(a)g Fc(status)d Ff(parameter)j(as)g(the)g(last)g(argumen)m(t.)69 b(The)347 5560 y(status)28 b(v)-5 b(alue)28 b(is)g(also)h(usually)e(returned)g (as)h(the)g(v)-5 b(alue)28 b(of)g(the)f(function)h(itself.)40 b(Normally)29 b(status)1928 5809 y(4)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 347 573 a Ff(=)22 b(0,)i(and)d(a)h(p)s(ositiv)m (e)h(status)f(v)-5 b(alue)22 b(indicates)h(an)f(error)f(of)h(some)g (sort.)38 b(The)22 b(status)g(v)-5 b(ariable)22 b(m)m(ust)347 686 y(alw)m(a)m(ys)33 b(b)s(e)d(initialized)j(to)f(zero)g(b)s(efore)f (use,)g(b)s(ecause)g(if)g(status)g(is)g(greater)i(than)d(zero)i(on)f (input)347 799 y(then)e(the)g(CFITSIO)f(routines)h(will)g(simply)f (return)g(without)h(doing)g(an)m(ything.)41 b(This)28 b(`inherited)347 912 y(status')46 b(feature,)j(where)44 b(eac)m(h)i(CFITSIO)e(routine)h(inherits)f(the)h(status)g(from)g(the)g (previous)347 1024 y(routine,)f(mak)m(es)d(it)g(unnecessary)f(to)i(c)m (hec)m(k)g(the)f(status)g(v)-5 b(alue)41 b(after)g(ev)m(ery)h(single)f (CFITSIO)347 1137 y(routine)e(call.)66 b(Generally)40 b(y)m(ou)f(should)f(c)m(hec)m(k)i(the)e(status)h(after)g(an)g(esp)s (ecially)h(imp)s(ortan)m(t)e(or)347 1250 y(complicated)33 b(routine)e(has)g(b)s(een)g(called,)i(or)e(after)h(a)f(blo)s(c)m(k)h (of)f(closely)i(related)f(CFITSIO)e(calls.)347 1363 y(This)c(example)h (program)g(has)f(tak)m(en)i(this)f(feature)g(to)g(the)g(extreme)g(and)f (only)h(c)m(hec)m(ks)h(the)f(status)347 1476 y(v)-5 b(alue)31 b(at)g(the)g(v)m(ery)g(end)e(of)i(the)f(program.)231 1664 y(4.)46 b(In)37 b(this)f(example)i(program)f(the)g(\014le)g(name)g (to)h(b)s(e)e(op)s(ened)h(is)g(giv)m(en)h(as)f(an)g(argumen)m(t)g(on)g (the)347 1777 y(command)e(line)h(\()p Fc(arg[1])p Ff(\).)53 b(If)35 b(the)g(\014le)h(con)m(tains)g(more)f(than)g(1)g(HDU)h(or)f (extension,)j(y)m(ou)d(can)347 1890 y(sp)s(ecify)20 b(whic)m(h)g (particular)h(HDU)g(to)g(b)s(e)f(op)s(ened)f(b)m(y)h(enclosing)i(the)e (name)g(or)h(n)m(um)m(b)s(er)e(of)h(the)h(HDU)347 2002 y(in)k(square)h(brac)m(k)m(ets)h(follo)m(wing)g(the)e(ro)s(ot)h(name)g (of)f(the)h(\014le.)39 b(F)-8 b(or)26 b(example,)i Fc(file.fts[0])22 b Ff(op)s(ens)347 2115 y(the)31 b(primary)e(arra)m(y)-8 b(,)32 b(while)f Fc(file.fts[2])c Ff(will)k(mo)m(v)m(e)h(to)f(and)f(op) s(en)f(the)i(2nd)f(extension)h(in)f(the)347 2228 y(\014le,)37 b(and)d Fc(file.fit[EVENTS])d Ff(will)k(op)s(en)g(the)g(extension)g (that)h(has)f(a)g Fc(EXTNAME)46 b(=)i('EVENTS')347 2341 y Ff(k)m(eyw)m(ord)31 b(in)f(the)g(header.)41 b(Note)31 b(that)g(on)f(the)h(Unix)f(command)g(line)h(y)m(ou)f(m)m(ust)g(enclose) i(the)e(\014le)347 2454 y(name)h(in)f(single)h(or)g(double)f(quote)i(c) m(haracters)g(if)e(the)h(name)g(con)m(tains)g(sp)s(ecial)h(c)m (haracters)g(suc)m(h)347 2567 y(as)f(`[')g(or)f(`]'.)347 2717 y(All)44 b(of)f(the)h(CFITSIO)d(routines)i(whic)m(h)g(read)g(or)g (write)h(header)f(k)m(eyw)m(ords,)k(image)d(data,)j(or)347 2830 y(table)32 b(data)f(op)s(erate)g(only)g(within)f(the)h(curren)m (tly)g(op)s(ened)f(HDU)h(in)f(the)h(\014le.)42 b(T)-8 b(o)31 b(read)g(or)f(write)347 2943 y(information)38 b(in)f(a)h(di\013eren)m(t)g(HDU)g(y)m(ou)g(m)m(ust)f(\014rst)g (explicitly)i(mo)m(v)m(e)f(to)h(that)f(HDU)g(\(see)g(the)347 3056 y Fc(fits)p 545 3056 29 4 v 34 w(movabs)p 867 3056 V 32 w(hdu)30 b Ff(and)g Fc(fits)p 1442 3056 V 33 w(movrel)p 1763 3056 V 33 w(hdu)f Ff(routines)h(in)g(section)i(4.3\).)231 3244 y(5.)46 b(The)25 b Fc(fits)p 727 3244 V 33 w(report)p 1048 3244 V 33 w(error)e Ff(routine)i(pro)m(vides)g(a)g(con)m(v)m (enien)m(t)i(w)m(a)m(y)f(to)g(prin)m(t)f(out)g(diagnostic)h(mes-)347 3357 y(sages)32 b(ab)s(out)e(an)m(y)g(error)g(that)h(ma)m(y)g(ha)m(v)m (e)h(o)s(ccurred.)261 3544 y(A)f(set)g(of)f(example)h(FITS)f(utilit)m (y)i(programs)e(are)g(a)m(v)-5 b(ailable)33 b(from)d(the)g(CFITSIO)f(w) m(eb)i(site)g(at)120 3657 y(h)m(ttp://heasarc.gsfc.nasa.go)m(v/do)s (cs/soft)n(w)m(are/)q(\014tsio/c)q(exa)q(mples.h)m(tml.)89 b(These)45 b(are)g(real)g(w)m(orking)120 3770 y(programs)d(whic)m(h)f (illustrate)i(ho)m(w)f(to)h(read,)i(write,)g(and)c(mo)s(dify)g(FITS)h (\014les)f(using)h(the)g(CFITSIO)120 3883 y(library)-8 b(.)38 b(Most)24 b(of)g(these)f(programs)g(are)h(v)m(ery)f(short,)i (con)m(taining)g(only)e(a)h(few)f(10s)h(of)f(lines)g(of)h(executable) 120 3996 y(co)s(de)32 b(or)g(less,)h(y)m(et)g(they)f(p)s(erform)e (quite)i(useful)f(op)s(erations)h(on)g(FITS)f(\014les.)45 b(Running)31 b(eac)m(h)i(program)120 4109 y(without)41 b(an)m(y)g(command)f(line)h(argumen)m(ts)g(will)g(pro)s(duce)e(a)i (short)f(description)h(of)g(ho)m(w)g(to)g(use)f(the)120 4222 y(program.)g(The)30 b(curren)m(tly)h(a)m(v)-5 b(ailable)32 b(programs)e(are:)347 4409 y(\014tscop)m(y)h(-)g(cop)m(y)g(a)g(\014le) 347 4522 y(listhead)g(-)g(list)g(header)f(k)m(eyw)m(ords)347 4635 y(liststruc)h(-)g(sho)m(w)f(the)g(structure)g(of)h(a)g(FITS)e (\014le.)347 4748 y(mo)s(dhead)h(-)g(write)h(or)f(mo)s(dify)g(a)h (header)f(k)m(eyw)m(ord)347 4861 y(imarith)h(-)f(add,)g(subtract,)h(m)m (ultiply)-8 b(,)31 b(or)g(divide)f(2)h(images)347 4974 y(imlist)g(-)g(list)g(pixel)g(v)-5 b(alues)30 b(in)g(an)h(image)347 5087 y(imstat)h(-)e(compute)h(mean,)g(min,)f(and)f(max)i(pixel)g(v)-5 b(alues)30 b(in)g(an)h(image)347 5200 y(tablist)h(-)e(displa)m(y)h(the) f(con)m(ten)m(ts)i(of)f(a)g(FITS)e(table)347 5313 y(tab)s(calc)j(-)f (general)g(table)g(calculator)1928 5809 y(5)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 120 573 a Fh(4)135 b(CFITSIO)44 b(Routines)120 776 y Ff(This)37 b(c)m(hapter)h(describ)s(es)f(the)g (main)h(CFITSIO)e(routines)h(that)h(can)g(b)s(e)f(used)g(to)h(p)s (erform)e(the)i(most)120 889 y(common)31 b(t)m(yp)s(es)f(of)h(op)s (erations)f(on)h(FITS)e(\014les.)120 1136 y Fb(4.1)112 b(Error)37 b(Rep)s(orting)120 1310 y Fc(void)47 b (fits_report_error\(FILE)41 b(*stream,)46 b(int)h(status\))120 1423 y(void)g(fits_get_errstatus\(int)41 b(status,)46 b(char)h(*err_text\))120 1536 y(float)f(fits_get_version\(float)c (*version\))261 1748 y Ff(The)24 b(\014rst)g(routine)g(prin)m(ts)g(out) h(information)g(ab)s(out)f(an)m(y)h(error)f(that)h(has)g(o)s(ccurred.) 38 b(Whenev)m(er)25 b(an)m(y)120 1861 y(CFITSIO)f(routine)i(encoun)m (ters)h(an)f(error)f(it)i(usually)e(writes)h(a)h(message)g(describing)e (the)h(nature)g(of)g(the)120 1974 y(error)g(to)i(an)e(in)m(ternal)h (error)g(message)g(stac)m(k)h(and)e(then)h(returns)e(with)h(a)h(p)s (ositiv)m(e)h(in)m(teger)g(status)f(v)-5 b(alue.)120 2087 y(P)m(assing)28 b(the)g(error)f(status)h(v)-5 b(alue)28 b(to)g(this)g(routine)f(will)h(cause)g(a)g(generic)h(description)e(of)h (the)g(error)f(and)120 2200 y(all)g(the)g(messages)h(from)e(the)h(in)m (ternal)g(CFITSIO)e(error)h(stac)m(k)i(to)g(b)s(e)e(prin)m(ted)g(to)h (the)g(sp)s(eci\014ed)f(stream.)120 2313 y(The)k Fc(stream)f Ff(parameter)h(is)h(usually)f(set)h(equal)g(to)g Fc("stdout")d Ff(or)i Fc("stderr")p Ff(.)261 2426 y(The)25 b(second)g(routine)g (simply)f(returns)g(a)h(30-c)m(haracter)j(descriptiv)m(e)e(error)e (message)i(corresp)s(onding)120 2538 y(to)31 b(the)g(input)e(status)i (v)-5 b(alue.)261 2651 y(The)30 b(last)h(routine)g(returns)e(the)h (curren)m(t)g(CFITSIO)f(library)h(v)m(ersion)h(n)m(um)m(b)s(er.)120 2899 y Fb(4.2)112 b(File)39 b(Op)s(en/Close)f(Routines)120 3072 y Fc(int)47 b(fits_open_file\()d(fitsfile)h(**fptr,)h(char)h (*filename,)e(int)h(mode,)h(int)g(*status\))120 3185 y(int)g(fits_open_data\()d(fitsfile)h(**fptr,)h(char)h(*filename,)e (int)h(mode,)h(int)g(*status\))120 3298 y(int)g (fits_open_table\(fitsfile)41 b(**fptr,)46 b(char)h(*filename,)e(int)h (mode,)h(int)g(*status\))120 3411 y(int)g(fits_open_image\(fitsfile)41 b(**fptr,)46 b(char)h(*filename,)e(int)h(mode,)h(int)g(*status\))120 3637 y(int)g(fits_create_file\(fitsfil)o(e)42 b(**fptr,)k(char)g (*filename,)f(int)i(*status\))120 3750 y(int)g (fits_close_file\(fitsfile)41 b(*fptr,)46 b(int)h(*status\))261 3962 y Ff(These)38 b(routines)f(op)s(en)h(or)f(close)j(a)e(\014le.)63 b(The)37 b(\014rst)g Fc(fitsfile)f Ff(parameter)i(in)g(these)g(and)f (nearly)120 4075 y(ev)m(ery)28 b(other)g(CFITSIO)f(routine)g(is)h(a)g (p)s(oin)m(ter)g(to)g(a)g(structure)g(that)g(CFITSIO)e(uses)h(to)i (store)f(relev)-5 b(an)m(t)120 4188 y(parameters)31 b(ab)s(out)f(eac)m (h)i(op)s(ened)e(\014le.)42 b(Y)-8 b(ou)31 b(should)f(nev)m(er)h (directly)g(read)g(or)f(write)h(an)m(y)g(information)120 4301 y(in)24 b(this)h(structure.)38 b(Memory)26 b(for)e(this)h (structure)f(is)h(allo)s(cated)h(automatically)i(when)c(the)h(\014le)f (is)h(op)s(ened)120 4414 y(or)30 b(created,)i(and)e(is)g(freed)g(when)g (the)g(\014le)h(is)f(closed.)261 4527 y(The)e Fc(mode)e Ff(parameter)j(in)e(the)h Fc(fits)p 1552 4527 29 4 v 34 w(open)p 1778 4527 V 33 w(xxxx)f Ff(set)h(of)g(routines)g(can)g(b)s (e)f(set)i(to)f(either)h Fc(READONLY)120 4640 y Ff(or)h Fc(READWRITE)d Ff(to)j(select)h(the)f(t)m(yp)s(e)f(of)h(\014le)g (access)h(that)f(will)g(b)s(e)f(allo)m(w)m(ed.)42 b(These)29 b(sym)m(b)s(olic)h(constan)m(ts)120 4753 y(are)h(de\014ned)e(in)h Fc(fitsio.h)p Ff(.)261 4866 y(The)j Fc(fits)p 649 4866 V 33 w(open)p 874 4866 V 34 w(file)f Ff(routine)i(op)s(ens)e(the)i (\014le)g(and)e(p)s(ositions)i(the)g(in)m(ternal)g(\014le)f(p)s(oin)m (ter)h(to)g(the)120 4979 y(b)s(eginning)23 b(of)h(the)g(\014le,)h(or)f (to)h(the)f(sp)s(eci\014ed)f(extension)h(if)g(an)g(extension)g(name)g (or)g(n)m(um)m(b)s(er)e(is)i(app)s(ended)120 5092 y(to)j(the)f(\014le)h (name)f(\(see)h(the)g(later)g(section)h(on)e(\\CFITSIO)f(File)i(Names)g (and)f(Filters")i(for)e(a)g(description)120 5204 y(of)32 b(the)f(syn)m(tax\).)45 b Fc(fits)p 945 5204 V 33 w(open)p 1170 5204 V 33 w(data)31 b Ff(b)s(eha)m(v)m(es)g(similarly)h(except)h (that)f(it)g(will)f(mo)m(v)m(e)i(to)f(the)g(\014rst)f(HDU)120 5317 y(con)m(taining)37 b(signi\014can)m(t)f(data)g(if)f(a)h(HDU)g (name)g(or)f(n)m(um)m(b)s(er)f(to)i(op)s(en)f(is)g(not)h(explicitly)g (sp)s(eci\014ed)f(as)120 5430 y(part)23 b(of)h(the)g(\014lename.)39 b(It)23 b(will)h(mo)m(v)m(e)h(to)g(the)e(\014rst)g(IMA)m(GE)i(HDU)f (with)f(NAXIS)h(greater)h(than)e(0,)j(or)d(the)1928 5809 y(6)p eop end %%Page: 7 7 TeXDict begin 7 6 bop 120 573 a Ff(\014rst)29 b(table)h(that)h(do)s(es) e(not)h(con)m(tain)h(the)f(strings)f(`GTI')h(\(a)g(Go)s(o)s(d)g(Time)f (In)m(terv)-5 b(al)31 b(extension\))f(or)g(`OB-)120 686 y(ST)-8 b(ABLE')37 b(in)g(the)g(EXTNAME)h(k)m(eyw)m(ord)f(v)-5 b(alue.)62 b(The)36 b Fc(fits)p 2380 686 29 4 v 34 w(open)p 2606 686 V 33 w(table)g Ff(and)g Fc(fits)p 3290 686 V 34 w(open)p 3516 686 V 33 w(image)120 799 y Ff(routines)f(are)h (similar)f(except)i(that)f(they)f(will)h(mo)m(v)m(e)g(to)g(the)g (\014rst)e(signi\014can)m(t)j(table)f(HDU)g(or)f(image)120 912 y(HDU,)c(resp)s(ectiv)m(ely)h(if)e(a)h(HDU)g(name)g(of)f(n)m(um)m (b)s(er)f(is)i(not)f(sp)s(eci\014ed)g(as)h(part)f(of)g(the)h(input)e (\014le)i(name.)261 1024 y(When)d(op)s(ening)g(an)g(existing)h(\014le,) g(the)g Fc(filename)d Ff(can)i(include)g(optional)i(argumen)m(ts,)f (enclosed)g(in)120 1137 y(square)g(brac)m(k)m(ets)i(that)f(sp)s(ecify)f (\014ltering)h(op)s(erations)f(that)h(should)f(b)s(e)g(applied)g(to)h (the)g(input)e(\014le.)41 b(F)-8 b(or)120 1250 y(example,)263 1428 y Fc(myfile.fit[EVENTS][counts)41 b(>)48 b(0])120 1605 y Ff(op)s(ens)27 b(the)i(table)g(in)f(the)h(EVENTS)e(extension)i (and)f(creates)i(a)e(virtual)h(table)g(b)m(y)f(selecting)i(only)f (those)120 1718 y(ro)m(ws)f(where)f(the)i(COUNTS)d(column)i(v)-5 b(alue)29 b(is)f(greater)h(than)f(0.)40 b(See)28 b(section)h(5)g(for)f (more)g(examples)g(of)120 1831 y(these)j(p)s(o)m(w)m(erful)f (\014ltering)g(capabilities.)261 1944 y(In)38 b Fc(fits)p 581 1944 V 33 w(create)p 902 1944 V 33 w(file)p Ff(,)h(the)g Fc(filename)d Ff(is)j(simply)f(the)g(ro)s(ot)h(name)f(of)h(the)g (\014le)f(to)h(b)s(e)f(created.)120 2057 y(Y)-8 b(ou)36 b(can)g(o)m(v)m(erwrite)h(an)f(existing)g(\014le)g(b)m(y)f(pre\014xing) g(the)h(name)g(with)f(a)h(`!')57 b(c)m(haracter)37 b(\(on)f(the)f(Unix) 120 2170 y(command)30 b(line)g(this)g(m)m(ust)f(b)s(e)g(pre\014xed)g (with)h(a)g(bac)m(kslash,)h(as)f(in)f Fc(`\\!file.fit')p Ff(\).)38 b(If)29 b(the)h(\014le)g(name)120 2282 y(ends)e(with)g Fc(.gz)g Ff(the)h(\014le)g(will)g(b)s(e)f(compressed)g(using)g(the)h (gzip)g(algorithm.)41 b(If)29 b(the)f(\014lename)h(is)g Fc(stdout)120 2395 y Ff(or)g Fc("-")e Ff(\(a)j(single)f(dash)f(c)m (haracter\))j(then)d(the)h(output)f(\014le)h(will)g(b)s(e)f(pip)s(ed)f (to)j(the)f(stdout)f(stream.)41 b(Y)-8 b(ou)120 2508 y(can)27 b(c)m(hain)g(sev)m(eral)g(tasks)g(together)h(b)m(y)f(writing)f (the)h(output)f(from)g(the)g(\014rst)g(task)h(to)g Fc(stdout)e Ff(and)h(then)120 2621 y(reading)k(the)h(input)e(\014le)i(in)f(the)h (2nd)e(task)i(from)f Fc(stdin)f Ff(or)h Fc("-")p Ff(.)120 2867 y Fb(4.3)112 b(HDU-lev)m(el)38 b(Routines)261 3040 y Ff(The)30 b(routines)g(listed)h(in)f(this)h(section)g(op)s(erate)g (on)f(Header-Data)j(Units)e(\(HDUs\))g(in)f(a)h(\014le.)120 3153 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(__)120 3266 y(int)47 b(fits_get_num_hdus\(fitsfi)o(le)42 b(*fptr,)k(int)h(*hdunum,)e(int)i (*status\))120 3379 y(int)g(fits_get_hdu_num\(fitsfil)o(e)42 b(*fptr,)94 b(int)47 b(*hdunum\))261 3579 y Ff(The)39 b(\014rst)f(routines)h(returns)f(the)h(total)i(n)m(um)m(b)s(er)d(of)h (HDUs)h(in)e(the)i(FITS)e(\014le,)k(and)c(the)h(second)120 3692 y(routine)33 b(returns)e(the)i(p)s(osition)g(of)g(the)g(curren)m (tly)f(op)s(ened)g(HDU)i(in)e(the)h(FITS)f(\014le)h(\(starting)g(with)g (1,)120 3805 y(not)e(0\).)120 4005 y Fc(________________________)o (____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(__)120 4118 y(int)47 b(fits_movabs_hdu\(fitsfile) 41 b(*fptr,)46 b(int)h(hdunum,)f(int)h(*hdutype,)e(int)i(*status\))120 4231 y(int)g(fits_movrel_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(nmove,)94 b(int)47 b(*hdutype,)e(int)i(*status\))120 4344 y(int)g(fits_movnam_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(hdutype,)f(char)g(*extname,)1075 4457 y(int)g(extver,)g(int)h (*status\))261 4657 y Ff(These)31 b(routines)g(enable)h(y)m(ou)f(to)h (mo)m(v)m(e)g(to)g(a)g(di\013eren)m(t)f(HDU)h(in)f(the)g(\014le.)43 b(Most)32 b(of)g(the)f(CFITSIO)120 4770 y(functions)h(whic)m(h)h(read)g (or)g(write)g(k)m(eyw)m(ords)g(or)g(data)h(op)s(erate)f(only)h(on)e (the)h(curren)m(tly)g(op)s(ened)g(HDU)120 4883 y(in)i(the)g(\014le.)54 b(The)34 b(\014rst)g(routine)h(mo)m(v)m(es)h(to)g(the)f(sp)s(eci\014ed) f(absolute)i(HDU)f(n)m(um)m(b)s(er)f(in)g(the)h(FITS)f(\014le)120 4996 y(\(the)e(\014rst)f(HDU)i(=)e(1\),)i(whereas)f(the)g(second)f (routine)h(mo)m(v)m(es)h(a)f(relativ)m(e)i(n)m(um)m(b)s(er)d(of)h(HDUs) g(forw)m(ard)120 5109 y(or)f(bac)m(kw)m(ard)h(from)e(the)i(curren)m (tly)f(op)s(en)f(HDU.)i(The)f Fc(hdutype)e Ff(parameter)i(returns)f (the)i(t)m(yp)s(e)f(of)g(the)120 5222 y(newly)e(op)s(ened)g(HDU,)i(and) e(will)h(b)s(e)f(equal)h(to)g(one)g(of)g(these)g(sym)m(b)s(olic)g (constan)m(t)h(v)-5 b(alues:)41 b Fc(IMAGE)p 3564 5222 V 33 w(HDU,)120 5334 y(ASCII)p 366 5334 V 33 w(TBL,)47 b(or)g(BINARY)p 1069 5334 V 33 w(TBL)p Ff(.)37 b Fc(hdutype)g Ff(ma)m(y)h(b)s(e)g(set)h(to)g(NULL)f(if)g(it)h(is)g(not)f(needed.)64 b(The)38 b(third)120 5447 y(routine)31 b(mo)m(v)m(es)i(to)f(the)f (\(\014rst\))h(HDU)g(that)f(matc)m(hes)i(the)e(input)g(extension)h(t)m (yp)s(e,)f(name,)h(and)f(v)m(ersion)120 5560 y(n)m(um)m(b)s(er,)23 b(as)f(giv)m(en)i(b)m(y)e(the)g Fc(XTENSION,)46 b(EXTNAME)20 b Ff(\(or)j Fc(HDUNAME)p Ff(\))d(and)i Fc(EXTVER)f Ff(k)m(eyw)m(ords.) 38 b(If)22 b(the)g(input)1928 5809 y(7)p eop end %%Page: 8 8 TeXDict begin 8 7 bop 120 573 a Ff(v)-5 b(alue)34 b(of)f Fc(extver)e Ff(=)i(0,)i(then)e(the)g(v)m(ersion)h(n)m(um)m(b)s(er)d (will)j(b)s(e)e(ignored)i(when)e(lo)s(oking)i(for)f(a)g(matc)m(hing)120 686 y(HDU.)120 898 y Fc(________________________)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)120 1011 y(int)47 b(fits_get_hdu_type\(fitsfi)o(le)42 b(*fptr,)93 b(int)47 b(*hdutype,)f(int)g(*status\))261 1224 y Ff(Get)21 b(the)g(t)m(yp)s(e)f(of)h(the)f(curren)m(t)g(HDU)h(in)f(the)h(FITS)e (\014le:)36 b Fc(IMAGE)p 2435 1224 29 4 v 33 w(HDU,)47 b(ASCII)p 2947 1224 V 33 w(TBL,)f(or)h(BINARY)p 3649 1224 V 33 w(TBL)p Ff(.)120 1436 y Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o (___)120 1549 y(int)g(fits_copy_hdu\(fitsfile)42 b(*infptr,)j(fitsfile) h(*outfptr,)f(int)i(morekeys,)979 1662 y(int)g(*status\))120 1775 y(int)g(fits_copy_file\(fitsfile)41 b(*infptr,)46 b(fitsfile)f(*outfptr,)h(int)h(previous,)979 1888 y(int)g(current,)f (int)g(following,)f(>)j(int)f(*status\))261 2100 y Ff(The)34 b(\014rst)g(routine)g(copies)i(the)e(curren)m(t)g(HDU)i(from)e(the)g (FITS)g(\014le)h(asso)s(ciated)g(with)g(infptr)e(and)120 2213 y(app)s(ends)h(it)j(to)g(the)f(end)f(of)h(the)g(FITS)g(\014le)g (asso)s(ciated)h(with)f(outfptr.)57 b(Space)36 b(ma)m(y)h(b)s(e)e (reserv)m(ed)i(for)120 2326 y Fc(morekeys)32 b Ff(additional)k(k)m(eyw) m(ords)f(in)g(the)f(output)h(header.)53 b(The)35 b(second)f(routine)h (copies)h(an)m(y)f(HDUs)120 2439 y(previous)42 b(to)i(the)e(curren)m(t) h(HDU,)h(and/or)e(the)h(curren)m(t)f(HDU,)i(and/or)f(an)m(y)g(HDUs)g (follo)m(wing)h(the)120 2552 y(curren)m(t)22 b(HDU,)h(dep)s(ending)d (on)i(the)g(v)-5 b(alue)23 b(\(T)-8 b(rue)22 b(or)g(F)-8 b(alse\))24 b(of)e Fc(previous,)45 b(current)p Ff(,)22 b(and)g Fc(following)p Ff(,)120 2665 y(resp)s(ectiv)m(ely)-8 b(.)42 b(F)-8 b(or)32 b(example,)215 2853 y Fc(fits_copy_file\(infptr,) 42 b(outfptr,)k(0,)h(1,)g(1,)g(&status\);)120 3040 y Ff(will)35 b(cop)m(y)h(the)f(curren)m(t)g(HDU)g(and)g(an)m(y)g(HDUs)g (that)h(follo)m(w)g(it)f(from)g(the)g(input)f(to)h(the)h(output)e (\014le,)120 3153 y(but)c(it)h(will)f(not)h(cop)m(y)g(an)m(y)g(HDUs)g (preceding)f(the)h(curren)m(t)f(HDU.)1928 5809 y(8)p eop end %%Page: 9 9 TeXDict begin 9 8 bop 120 573 a Fb(4.4)112 b(Image)38 b(I/O)g(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(more)f (imp)s(ortan)m(t)h(CFITSIO)d(routines)j(whic)m(h)f(op)s(erate)h(on)f (FITS)g(images.)120 956 y Fc(________________________)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(__)120 1069 y(int)47 b(fits_get_img_type\(fitsfi)o(le)42 b(*fptr,)k(int)h (*bitpix,)e(int)i(*status\))120 1181 y(int)g(fits_get_img_dim\()c (fitsfile)j(*fptr,)g(int)h(*naxis,)93 b(int)47 b(*status\))120 1294 y(int)g(fits_get_img_size\(fitsfi)o(le)42 b(*fptr,)k(int)h (maxdim,)93 b(long)47 b(*naxes,)1170 1407 y(int)g(*status\))120 1520 y(int)g(fits_get_img_param\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(maxdim,)94 b(int)47 b(*bitpix,)1218 1633 y(int)g(*naxis,)e (long)i(*naxes,)f(int)h(*status\))261 1844 y Ff(Get)38 b(information)g(ab)s(out)f(the)g(curren)m(tly)g(op)s(ened)g(image)h (HDU.)g(The)f(\014rst)f(routine)h(returns)f(the)120 1957 y(datat)m(yp)s(e)41 b(of)e(the)h(image)h(as)f(\(de\014ned)f(b)m(y)g (the)h Fc(BITPIX)e Ff(k)m(eyw)m(ord\),)43 b(whic)m(h)c(can)h(ha)m(v)m (e)h(the)f(follo)m(wing)120 2070 y(sym)m(b)s(olic)31 b(constan)m(t)g(v)-5 b(alues:)311 2256 y Fc(BYTE_IMG)284 b(=)143 b(8)g(\()47 b(8-bit)g(byte)f(pixels,)g(0)i(-)f(255\))311 2369 y(SHORT_IMG)236 b(=)95 b(16)143 b(\(16)47 b(bit)g(integer)f (pixels\))311 2482 y(LONG_IMG)284 b(=)95 b(32)143 b(\(32-bit)46 b(integer)g(pixels\))311 2595 y(LONGLONG_IMG)92 b(=)j(64)143 b(\(64-bit)46 b(integer)g(pixels\))311 2708 y(FLOAT_IMG)236 b(=)48 b(-32)142 b(\(32-bit)46 b(floating)f(point)i(pixels\))311 2821 y(DOUBLE_IMG)188 b(=)48 b(-64)142 b(\(64-bit)46 b(floating)f(point)i(pixels\))261 3007 y Ff(The)34 b(second)g(and)f (third)g(routines)h(return)f(the)h(n)m(um)m(b)s(er)e(of)i(dimensions)f (in)h(the)g(image)h(\(from)f(the)120 3120 y Fc(NAXIS)25 b Ff(k)m(eyw)m(ord\),)j(and)e(the)h(sizes)g(of)f(eac)m(h)i(dimension)e (\(from)g(the)g Fc(NAXIS1,)46 b(NAXIS2)p Ff(,)26 b(etc.)40 b(k)m(eyw)m(ords\).)120 3233 y(The)g(last)i(routine)f(simply)g(com)m (bines)g(the)h(function)e(of)h(the)h(\014rst)e(3)h(routines.)73 b(The)40 b(input)g Fc(maxdim)120 3346 y Ff(parameter)28 b(in)g(this)f(routine)h(giv)m(es)h(the)f(maxim)m(um)g(n)m(um)m(b)s(er)e (dimensions)h(that)i(ma)m(y)f(b)s(e)f(returned)g(\(i.e.,)120 3459 y(the)k(dimension)e(of)i(the)f Fc(naxes)f Ff(arra)m(y\))120 3670 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(_)120 3783 y(int)47 b (fits_create_img\(fitsfile)41 b(*fptr,)46 b(int)h(bitpix,)f(int)h (naxis,)1075 3896 y(long)f(*naxes,)g(int)h(*status\))261 4107 y Ff(Create)28 b(an)f(image)i(HDU)f(b)m(y)f(writing)g(the)g (required)g(k)m(eyw)m(ords)g(whic)m(h)g(de\014ne)g(the)g(structure)g (of)g(the)120 4220 y(image.)51 b(The)33 b(2nd)f(through)h(4th)h (parameters)f(sp)s(eci\014ed)g(the)g(datat)m(yp)s(e,)j(the)d(n)m(um)m (b)s(er)f(of)i(dimensions,)120 4333 y(and)26 b(the)h(sizes)g(of)f(the)h (dimensions.)39 b(The)26 b(allo)m(w)m(ed)i(v)-5 b(alues)27 b(of)g(the)f Fc(bitpix)f Ff(parameter)i(are)g(listed)g(ab)s(o)m(v)m(e) 120 4446 y(in)33 b(the)g(description)g(of)g(the)g Fc(fits)p 1319 4446 29 4 v 33 w(get)p 1496 4446 V 33 w(img)p 1673 4446 V 34 w(type)f Ff(routine.)48 b(If)32 b(the)h(FITS)f(\014le)h(p)s (oin)m(ted)g(to)h(b)m(y)f Fc(fptr)e Ff(is)120 4559 y(empt)m(y)c (\(previously)f(created)h(with)f Fc(fits)p 1575 4559 V 33 w(create)p 1896 4559 V 33 w(file)p Ff(\))f(then)h(this)g(routine)g (creates)i(a)f(primary)e(arra)m(y)120 4672 y(in)37 b(the)g(\014le,)i (otherwise)f(a)f(new)g(IMA)m(GE)h(extension)g(is)f(app)s(ended)e(to)j (end)f(of)g(the)g(\014le)h(follo)m(wing)g(the)120 4785 y(other)31 b(HDUs)g(in)f(the)g(\014le.)120 4996 y Fc (________________________)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(_)120 5109 y(int)47 b (fits_write_pix\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(long)g (*fpixel,)836 5222 y(long)h(nelements,)e(void)h(*array,)g(int)h (*status\);)120 5447 y(int)g(fits_write_pixnull\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(datatype,)f(long)g(*fpixel,)836 5560 y(long)h(nelements,)e(void)h(*array,)g(void)h(*nulval,)e(int)i (*status\);)1928 5809 y Ff(9)p eop end %%Page: 10 10 TeXDict begin 10 9 bop 120 686 a Fc(int)47 b(fits_read_pix\(fitsfile)42 b(*fptr,)k(int)94 b(datatype,)46 b(long)g(*fpixel,)979 799 y(long)h(nelements,)e(void)h(*nulval,)g(void)h(*array,)979 912 y(int)g(*anynul,)f(int)g(*status\))261 1124 y Ff(Read)32 b(or)f(write)g(all)h(or)f(part)h(of)f(the)g(FITS)g(image.)44 b(There)31 b(are)h(2)f(di\013eren)m(t)h('write')g(pixel)f(routines:)120 1237 y(The)23 b(\014rst)g(simply)g(writes)h(the)g(input)f(arra)m(y)h (of)g(pixels)g(to)g(the)g(FITS)f(\014le.)39 b(The)23 b(second)h(is)g(similar,)h(except)120 1350 y(that)30 b(it)f(substitutes)g(the)g(appropriate)g(n)m(ull)g(pixel)g(v)-5 b(alue)30 b(in)f(the)g(FITS)f(\014le)h(for)g(an)m(y)g(pixels)g(whic)m (h)g(ha)m(v)m(e)120 1463 y(a)i(v)-5 b(alue)30 b(equal)h(to)g Fc(*nulval)d Ff(\(note)j(that)g(this)f(parameter)g(giv)m(es)i(the)e (address)f(of)i(the)f(n)m(ull)g(pixel)h(v)-5 b(alue,)120 1576 y(not)35 b(the)g(v)-5 b(alue)35 b(itself)7 b(\).)54 b(Similarly)-8 b(,)37 b(when)c(reading)i(an)g(image,)i(CFITSIO)c(will)i (substitute)f(the)h(v)-5 b(alue)120 1689 y(giv)m(en)30 b(b)m(y)e Fc(nulval)f Ff(for)i(an)m(y)g(unde\014ned)d(pixels)j(in)g (the)g(image,)h(unless)e Fc(nulval)46 b(=)i(NULL)p Ff(,)27 b(in)i(whic)m(h)f(case)120 1802 y(no)i(c)m(hec)m(ks)i(will)f(b)s(e)f (made)g(for)g(unde\014ned)e(pixels)j(when)e(reading)i(the)f(FITS)g (image.)261 1914 y(The)35 b Fc(fpixel)f Ff(parameter)i(in)f(these)h (routines)f(is)h(an)f(arra)m(y)h(whic)m(h)f(giv)m(es)i(the)f(co)s (ordinate)g(in)f(eac)m(h)120 2027 y(dimension)24 b(of)i(the)f(\014rst)f (pixel)i(to)f(b)s(e)g(read)g(or)g(written,)h(and)f Fc(nelements)d Ff(is)j(the)g(total)i(n)m(um)m(b)s(er)d(of)h(pixels)120 2140 y(to)i(read)g(or)f(write.)40 b Fc(array)25 b Ff(is)i(the)f (address)g(of)h(an)f(arra)m(y)h(whic)m(h)f(either)h(con)m(tains)h(the)f (pixel)g(v)-5 b(alues)27 b(to)g(b)s(e)120 2253 y(written,)32 b(or)f(will)h(hold)e(the)i(v)-5 b(alues)31 b(of)h(the)f(pixels)h(that)g (are)f(read.)43 b(When)31 b(reading,)h Fc(array)e Ff(m)m(ust)h(ha)m(v)m (e)120 2366 y(b)s(een)k(allo)s(cated)j(large)f(enough)e(to)i(hold)e (all)i(the)f(returned)f(pixel)h(v)-5 b(alues.)57 b(These)36 b(routines)f(starts)i(at)120 2479 y(the)e Fc(fpixel)d Ff(lo)s(cation)k(and)e(then)g(read)h(or)f(write)h(the)f Fc(nelements)e Ff(pixels,)k(con)m(tin)m(uing)g(on)e(successiv)m(e)120 2592 y(ro)m(ws)f(of)g(the)g(image)h(if)f(necessary)-8 b(.)49 b(F)-8 b(or)34 b(example,)h(to)e(write)g(an)g(en)m(tire)h(2D)g (image,)h(set)e Fc(fpixel[0])46 b(=)120 2705 y(fpixel[1])f(=)j(1)p Ff(,)35 b(and)f Fc(nelements)46 b(=)h(NAXIS1)f(*)i(NAXIS2)p Ff(.)j(Or)34 b(to)i(read)e(just)g(the)h(10th)h(ro)m(w)e(of)h(the)120 2818 y(image,)50 b(set)45 b Fc(fpixel[0])g(=)j(1,)f(fpixel[1])e(=)j(10) p Ff(,)g(and)c Fc(nelements)h(=)i(NAXIS1)p Ff(.)82 b(The)45 b Fc(datatype)120 2931 y Ff(parameter)28 b(sp)s(eci\014es)e(the)i (datat)m(yp)s(e)g(of)f(the)g(C)g Fc(array)e Ff(in)i(the)g(program,)h (whic)m(h)f(need)g(not)g(b)s(e)g(the)g(same)120 3044 y(as)32 b(the)f(datat)m(yp)s(e)i(of)e(the)h(FITS)f(image)h(itself.)45 b(If)31 b(the)h(datat)m(yp)s(es)g(di\013er)f(then)g(CFITSIO)f(will)i (con)m(v)m(ert)120 3156 y(the)f(data)h(as)f(it)h(is)f(read)g(or)g (written.)42 b(The)31 b(follo)m(wing)h(sym)m(b)s(olic)g(constan)m(ts)g (are)f(allo)m(w)m(ed)i(for)e(the)g(v)-5 b(alue)120 3269 y(of)31 b Fc(datatype)p Ff(:)215 3457 y Fc(TBYTE)238 b(unsigned)45 b(char)215 3570 y(TSBYTE)190 b(signed)46 b(char)215 3683 y(TSHORT)190 b(signed)46 b(short)215 3796 y(TUSHORT)142 b(unsigned)45 b(short)215 3909 y(TINT)286 b(signed)46 b(int)215 4022 y(TUINT)238 b(unsigned)45 b(int)215 4134 y(TLONG)238 b(signed)46 b(long)215 4247 y(TLONGLONG)g(signed)g(8-byte)g(integer)215 4360 y(TULONG)190 b(unsigned)45 b(long)215 4473 y(TFLOAT)190 b(float)215 4586 y(TDOUBLE)142 b(double)120 4799 y(________________________)o(____) o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)120 4912 y(int)47 b(fits_write_subset\(fitsfi)o(le)42 b(*fptr,)k(int)h (datatype,)e(long)h(*fpixel,)740 5024 y(long)h(*lpixel,)f(DTYPE)g (*array,)g(>)h(int)g(*status\))120 5250 y(int)g (fits_read_subset\(fitsfil)o(e)42 b(*fptr,)k(int)95 b(datatype,)45 b(long)h(*fpixel,)740 5363 y(long)h(*lpixel,)f(long)g(*inc,)h(void)f (*nulval,)94 b(void)46 b(*array,)740 5476 y(int)h(*anynul,)f(int)h (*status\))1905 5809 y Ff(10)p eop end %%Page: 11 11 TeXDict begin 11 10 bop 261 573 a Ff(Read)49 b(or)g(write)f(a)h (rectangular)h(section)g(of)f(the)f(FITS)g(image.)97 b(These)49 b(are)g(v)m(ery)g(similar)g(to)120 686 y Fc(fits)p 318 686 29 4 v 33 w(write)p 591 686 V 33 w(pix)37 b Ff(and)f Fc(fits)p 1180 686 V 34 w(read)p 1406 686 V 33 w(pix)g Ff(except)j(that)f(y)m(ou)f(sp)s(ecify)g(the)h(last)g(pixel)g(co)s (ordinate)g(\(the)120 799 y(upp)s(er)22 b(righ)m(t)i(corner)g(of)g(the) h(section\))g(instead)f(of)g(the)h(n)m(um)m(b)s(er)d(of)i(pixels)h(to)f (b)s(e)g(read.)38 b(The)23 b(read)h(routine)120 912 y(also)39 b(has)e(an)h Fc(inc)f Ff(parameter)h(whic)m(h)f(can)i(b)s(e)e(used)g (to)h(read)g(only)g(ev)m(ery)g Fc(inc-th)e Ff(pixel)i(along)h(eac)m(h) 120 1024 y(dimension)28 b(of)h(the)g(image.)41 b(Normally)30 b Fc(inc[0])46 b(=)h(inc[1])f(=)i(1)28 b Ff(to)i(read)e(ev)m(ery)i (pixel)f(in)f(a)h(2D)h(image.)120 1137 y(T)-8 b(o)31 b(read)f(ev)m(ery)h(other)g(pixel)g(in)f(the)g(en)m(tire)i(2D)f(image,) h(set)311 1325 y Fc(fpixel[0])45 b(=)j(fpixel[1])d(=)i(1)311 1438 y(lpixel[0])e(=)j({NAXIS1})311 1551 y(lpixel[1])d(=)j({NAXIS2})311 1664 y(inc[0])e(=)h(inc[1])g(=)g(2)261 1851 y Ff(Or,)30 b(to)h(read)f(the)h(8th)g(ro)m(w)f(of)h(a)f(2D)i(image,)f(set)311 2039 y Fc(fpixel[0])45 b(=)j(1)311 2152 y(fpixel[1])d(=)j(8)311 2265 y(lpixel[0])d(=)j({NAXIS1})311 2378 y(lpixel[1])d(=)j(8)311 2491 y(inc[0])e(=)h(inc[1])g(=)g(1)1905 5809 y Ff(11)p eop end %%Page: 12 12 TeXDict begin 12 11 bop 120 573 a Fb(4.5)112 b(T)-9 b(able)38 b(I/O)g(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(most)f (imp)s(ortan)m(t)h(CFITSIO)e(routines)h(whic)m(h)g(op)s(erate)h(on)f (FITS)g(tables.)120 957 y Fc(________________________)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(__)120 1070 y(int)47 b(fits_create_tbl\(fitsfile)41 b(*fptr,)46 b(int)h(tbltype,)f(long)g(nrows,)g(int)h(tfields,)311 1183 y(char)g(*ttype[],char)d(*tform[],)h(char)i(*tunit[],)e(char)i (*extname,)e(int)i(*status\))261 1395 y Ff(Create)e(a)f(new)f(table)i (extension)f(b)m(y)g(writing)g(the)g(required)f(k)m(eyw)m(ords)h(that)g (de\014ne)f(the)h(table)120 1508 y(structure.)38 b(The)22 b(required)f(n)m(ull)i(primary)e(arra)m(y)i(will)g(b)s(e)f(created)i (\014rst)d(if)i(the)g(\014le)f(is)h(initially)h(completely)120 1621 y(empt)m(y)-8 b(.)41 b Fc(tbltype)26 b Ff(de\014nes)i(the)g(t)m (yp)s(e)h(of)g(table)g(and)f(can)g(ha)m(v)m(e)i(v)-5 b(alues)29 b(of)f Fc(ASCII)p 2931 1621 29 4 v 33 w(TBL)47 b(or)g(BINARY)p 3586 1621 V 33 w(TBL)p Ff(.)120 1734 y(Binary)34 b(tables)h(are)g(generally)g(preferred)e(b)s(ecause)h(they) h(are)f(more)h(e\016cien)m(t)g(and)f(supp)s(ort)f(a)h(greater)120 1847 y(range)d(of)f(column)g(datat)m(yp)s(es)i(than)e(ASCI)s(I)f (tables.)261 1960 y(The)c Fc(nrows)f Ff(parameter)i(giv)m(es)h(the)e (initial)i(n)m(um)m(b)s(er)d(of)i(empt)m(y)g(ro)m(ws)f(to)h(b)s(e)f (allo)s(cated)i(for)f(the)f(table;)120 2073 y(this)h(should)g(normally) g(b)s(e)g(set)h(to)g(0.)40 b(The)26 b Fc(tfields)f Ff(parameter)i(giv)m (es)g(the)g(n)m(um)m(b)s(er)e(of)i(columns)f(in)g(the)120 2186 y(table)e(\(maxim)m(um)f(=)f(999\).)40 b(The)22 b Fc(ttype,)46 b(tform)p Ff(,)24 b(and)e Fc(tunit)f Ff(parameters)i (giv)m(e)i(the)e(name,)h(datat)m(yp)s(e,)120 2299 y(and)34 b(ph)m(ysical)h(units)g(of)f(eac)m(h)i(column,)g(and)e Fc(extname)f Ff(giv)m(es)j(the)f(name)g(for)f(the)h(table)h(\(the)f(v) -5 b(alue)35 b(of)120 2412 y(the)i Fc(EXTNAME)e Ff(k)m(eyw)m(ord\).)61 b(The)36 b(FITS)g(Standard)g(recommends)g(that)i(only)f(letters,)j (digits,)f(and)d(the)120 2524 y(underscore)27 b(c)m(haracter)h(b)s(e)f (used)g(in)g(column)g(names)g(with)g(no)g(em)m(b)s(edded)g(spaces.)40 b(It)27 b(is)h(recommended)120 2637 y(that)j(all)g(the)g(column)f (names)g(in)g(a)h(giv)m(en)g(table)h(b)s(e)d(unique)h(within)g(the)g (\014rst)g(8)h(c)m(haracters.)261 2750 y(The)g(follo)m(wing)i(table)g (sho)m(ws)e(the)h(TF)m(ORM)g(column)f(format)h(v)-5 b(alues)32 b(that)g(are)g(allo)m(w)m(ed)i(in)d(ASCI)s(I)120 2863 y(tables)g(and)f(in)g(binary)g(tables:)502 3051 y Fc(ASCII)46 b(Table)h(Column)f(Format)g(Codes)502 3164 y(------------------------)o (---)o(----)502 3277 y(\(w)h(=)g(column)g(width,)f(d)h(=)h(no.)e(of)i (decimal)d(places)i(to)g(display\))693 3390 y(Aw)142 b(-)48 b(character)d(string)693 3502 y(Iw)142 b(-)48 b(integer)693 3615 y(Fw.d)e(-)i(fixed)e(floating)g(point)693 3728 y(Ew.d)g(-)i(exponential)d(floating)g(point)693 3841 y(Dw.d)h(-)i(exponential)d(floating)g(point)502 4067 y(Binary)h(Table)g(Column)g(Format)g(Codes)502 4180 y(------------------------)o(---)o(----)o(-)502 4293 y(\(r)h(=)g(vector)g(length,)e(default)h(=)i(1\))693 4406 y(rA)95 b(-)47 b(character)e(string)693 4519 y(rAw)i(-)g(array)f (of)i(strings,)d(each)i(of)g(length)f(w)693 4632 y(rL)95 b(-)47 b(logical)693 4744 y(rX)95 b(-)47 b(bit)693 4857 y(rB)95 b(-)47 b(unsigned)f(byte)693 4970 y(rS)95 b(-)47 b(signed)f(byte)h(**)693 5083 y(rI)95 b(-)47 b(signed)f(16-bit)g (integer)693 5196 y(rU)95 b(-)47 b(unsigned)f(16-bit)g(integer)g(**)693 5309 y(rJ)95 b(-)47 b(signed)f(32-bit)g(integer)693 5422 y(rV)95 b(-)47 b(unsigned)f(32-bit)g(integer)g(**)693 5535 y(rK)95 b(-)47 b(signed)f(64-bit)g(integer)1905 5809 y Ff(12)p eop end %%Page: 13 13 TeXDict begin 13 12 bop 693 573 a Fc(rE)95 b(-)47 b(32-bit)f(floating)g (point)693 686 y(rD)95 b(-)47 b(64-bit)f(floating)g(point)693 799 y(rC)95 b(-)47 b(32-bit)f(complex)g(pair)693 912 y(rM)95 b(-)47 b(64-bit)f(complex)g(pair)359 1137 y(**)h(The)g(S,)g(U)g (and)g(V)h(format)e(codes)g(are)h(not)g(actual)f(legal)g(TFORMn)h (values.)502 1250 y(CFITSIO)f(substitutes)e(the)j(somewhat)f(more)g (complicated)f(set)i(of)502 1363 y(keywords)e(that)i(are)g(used)g(to)g (represent)e(unsigned)h(integers)f(or)502 1476 y(signed)h(bytes.)261 1777 y Ff(The)27 b Fc(tunit)e Ff(and)h Fc(extname)f Ff(parameters)j (are)f(optional)h(and)f(ma)m(y)g(b)s(e)g(set)g(to)h(NULL)f(if)g(they)g (are)g(not)120 1890 y(needed.)261 2002 y(Note)41 b(that)f(it)f(ma)m(y)h (b)s(e)f(easier)h(to)g(create)h(a)f(new)e(table)i(b)m(y)g(cop)m(ying)g (the)f(header)g(from)g(another)120 2115 y(existing)31 b(table)h(with)e Fc(fits)p 1089 2115 29 4 v 33 w(copy)p 1314 2115 V 33 w(header)f Ff(rather)h(than)g(calling)i(this)e(routine.) 120 2328 y Fc(________________________)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(__)120 2441 y(int)47 b(fits_get_num_rows\(fitsfi)o(le)42 b(*fptr,)k(long)g(*nrows,) g(int)h(*status\))120 2554 y(int)g(fits_get_num_cols\(fitsfi)o(le)42 b(*fptr,)k(int)94 b(*ncols,)46 b(int)h(*status\))261 2766 y Ff(Get)37 b(the)g(n)m(um)m(b)s(er)d(of)j(ro)m(ws)f(or)g(columns) g(in)f(the)i(curren)m(t)e(FITS)h(table.)59 b(The)35 b(n)m(um)m(b)s(er)g (of)h(ro)m(ws)g(is)120 2879 y(giv)m(en)e(b)m(y)f(the)g Fc(NAXIS2)e Ff(k)m(eyw)m(ord)j(and)e(the)h(n)m(um)m(b)s(er)f(of)h (columns)g(is)g(giv)m(en)h(b)m(y)f(the)g Fc(TFIELDS)e Ff(k)m(eyw)m(ord)120 2992 y(in)f(the)h(header)f(of)g(the)h(table.)120 3205 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(__)120 3318 y(int)47 b(fits_get_colnum\(fitsfile)41 b(*fptr,)46 b(int)h(casesen,)f(char)g (*template,)1075 3430 y(int)g(*colnum,)g(int)h(*status\))120 3543 y(int)g(fits_get_colname\(fitsfil)o(e)42 b(*fptr,)k(int)h (casesen,)e(char)i(*template,)1075 3656 y(char)f(*colname,)f(int)i (*colnum,)f(int)h(*status\))261 3869 y Ff(Get)33 b(the)e(column)g(n)m (um)m(b)s(er)f(\(starting)j(with)e(1,)h(not)g(0\))g(of)f(the)h(column)f (whose)g(name)h(matc)m(hes)g(the)120 3982 y(sp)s(eci\014ed)38 b(template)i(name.)66 b(The)38 b(only)h(di\013erence)g(in)f(these)h(2)g (routines)g(is)f(that)i(the)e(2nd)g(one)h(also)120 4095 y(returns)29 b(the)i(name)f(of)h(the)f(column)g(that)h(matc)m(hed)h (the)e(template)i(string.)261 4208 y(Normally)-8 b(,)29 b Fc(casesen)24 b Ff(should)h(b)s(e)h(set)h(to)g Fc(CASEINSEN)p Ff(,)d(but)i(it)g(ma)m(y)h(b)s(e)f(set)h(to)g Fc(CASESEN)d Ff(to)j(force)g(the)120 4320 y(name)j(matc)m(hing)i(to)f(b)s(e)f (case-sensitiv)m(e.)261 4433 y(The)22 b(input)f Fc(template)f Ff(string)i(giv)m(es)i(the)e(name)h(of)f(the)h(desired)e(column)h(and)g (ma)m(y)h(include)f(wildcard)120 4546 y(c)m(haracters:)41 b(a)30 b(`*')g(matc)m(hes)g(an)m(y)f(sequence)g(of)h(c)m(haracters)g (\(including)f(zero)h(c)m(haracters\),)h(`?')40 b(matc)m(hes)120 4659 y(an)m(y)45 b(single)g(c)m(haracter,)50 b(and)44 b(`#')h(matc)m(hes)g(an)m(y)g(consecutiv)m(e)i(string)d(of)h(decimal)h (digits)f(\(0-9\).)85 b(If)120 4772 y(more)27 b(than)g(one)g(column)g (name)g(in)g(the)g(table)h(matc)m(hes)g(the)f(template)h(string,)g (then)f(the)g(\014rst)f(matc)m(h)i(is)120 4885 y(returned)22 b(and)h(the)h(status)f(v)-5 b(alue)24 b(will)g(b)s(e)f(set)h(to)g Fc(COL)p 1962 4885 V 33 w(NOT)p 2139 4885 V 34 w(UNIQUE)e Ff(as)h(a)h(w)m(arning)f(that)h(a)g(unique)e(matc)m(h)120 4998 y(w)m(as)34 b(not)g(found.)50 b(T)-8 b(o)35 b(\014nd)d(the)i(next) g(column)g(that)h(matc)m(hes)g(the)f(template,)i(call)g(this)d(routine) h(again)120 5111 y(lea)m(ving)e(the)f(input)e(status)i(v)-5 b(alue)31 b(equal)g(to)g Fc(COL)p 1832 5111 V 33 w(NOT)p 2009 5111 V 34 w(UNIQUE)p Ff(.)e(Rep)s(eat)i(this)f(pro)s(cess)g(un)m (til)h Fc(status)46 b(=)120 5224 y(COL)p 270 5224 V 34 w(NOT)p 448 5224 V 33 w(FOUND)29 b Ff(is)h(returned.)120 5436 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(__)120 5549 y(int)47 b(fits_get_coltype\(fitsfil)o(e)42 b(*fptr,)k(int)h(colnum,)f(int)h (*typecode,)1905 5809 y Ff(13)p eop end %%Page: 14 14 TeXDict begin 14 13 bop 1122 573 a Fc(long)47 b(*repeat,)e(long)i (*width,)f(int)h(*status\))120 799 y(int)g(fits_get_eqcoltype\(fitsf)o (ile)41 b(*fptr,)46 b(int)h(colnum,)f(int)h(*typecode,)1122 912 y(long)g(*repeat,)e(long)i(*width,)f(int)h(*status\))261 1106 y Ff(Return)41 b(the)h(datat)m(yp)s(e,)k(v)m(ector)d(rep)s(eat)f (coun)m(t,)j(and)c(the)h(width)f(in)g(b)m(ytes)h(of)g(a)g(single)h (column)120 1219 y(elemen)m(t)h(for)d(column)h(n)m(um)m(b)s(er)f Fc(colnum)p Ff(.)74 b(Allo)m(w)m(ed)44 b(v)-5 b(alues)42 b(for)g(the)g(returned)f(datat)m(yp)s(e)i(in)f(ASCI)s(I)120 1332 y(tables)31 b(are:)42 b Fc(TSTRING,)j(TSHORT,)h(TLONG,)g(TFLOAT,)g (and)h(TDOUBLE)p Ff(.)29 b(Binary)i(tables)g(supp)s(ort)e(these)120 1445 y(additional)22 b(t)m(yp)s(es:)36 b Fc(TLOGICAL,)45 b(TBIT,)h(TBYTE,)g(TINT32BIT,)f(TCOMPLEX)h(and)h(TDBLCOMPLEX)p Ff(.)18 b(The)120 1558 y(negativ)m(e)33 b(of)d(the)h(datat)m(yp)s(e)g (co)s(de)g(v)-5 b(alue)30 b(is)h(returned)e(if)h(it)h(is)g(a)f(v)-5 b(ariable)32 b(length)e(arra)m(y)h(column.)261 1671 y(These)36 b(2)h(routines)f(are)h(similar,)h(except)f(that)g(in)f(the)g(case)i(of) e(scaled)h(in)m(teger)h(columns)e(the)g(2nd)120 1784 y(routine,)28 b(\014t)p 547 1784 28 4 v 33 w(get)p 700 1784 V 34 w(eqcolt)m(yp)s(e,)i(returns)c(the)i('equiv)-5 b(alen)m(t')29 b(datat)m(yp)s(e)g(that)f(is)f(needed)h(to)g(store)g (the)g(scaled)120 1897 y(v)-5 b(alues,)34 b(whic)m(h)e(is)h(not)g (necessarily)g(the)g(same)g(as)g(the)g(ph)m(ysical)g(datat)m(yp)s(e)h (of)f(the)g(unscaled)f(v)-5 b(alues)33 b(as)120 2010 y(stored)h(in)g(the)h(FITS)e(table.)54 b(F)-8 b(or)35 b(example)f(if)h(a)f('1I')h(column)f(in)g(a)h(binary)e(table)j(has)e (TSCALn)e(=)i(1)120 2122 y(and)f(TZER)m(On)f(=)h(32768,)k(then)d(this)f (column)h(e\013ectiv)m(ely)i(con)m(tains)f(unsigned)d(short)i(in)m (teger)h(v)-5 b(alues,)120 2235 y(and)32 b(th)m(us)h(the)g(returned)f (v)-5 b(alue)34 b(of)f(t)m(yp)s(eco)s(de)g(will)h(b)s(e)e(TUSHOR)-8 b(T,)32 b(not)i(TSHOR)-8 b(T.)32 b(Or,)h(if)g(TSCALn)120 2348 y(or)g(TZER)m(On)e(are)j(not)f(in)m(tegers,)i(then)d(the)h(equiv) -5 b(alen)m(t)34 b(datat)m(yp)s(e)g(will)f(b)s(e)g(returned)e(as)i (TFLO)m(A)-8 b(T)33 b(or)120 2461 y(TDOUBLE,)e(dep)s(ending)d(on)j(the) f(size)i(of)e(the)h(in)m(teger.)261 2574 y(The)e(rep)s(eat)h(coun)m(t)h (is)e(alw)m(a)m(ys)j(1)e(in)f(ASCI)s(I)f(tables.)42 b(The)29 b('rep)s(eat')h(parameter)g(returns)f(the)h(v)m(ector)120 2687 y(rep)s(eat)23 b(coun)m(t)h(on)f(the)h(binary)e(table)j(TF)m(ORMn) e(k)m(eyw)m(ord)g(v)-5 b(alue.)39 b(\(ASCI)s(I)22 b(table)i(columns)f (alw)m(a)m(ys)i(ha)m(v)m(e)120 2800 y(rep)s(eat)35 b(=)f(1\).)55 b(The)34 b('width')h(parameter)g(returns)f(the)h(width)f(in)g(b)m(ytes) i(of)f(a)g(single)g(column)g(elemen)m(t)120 2913 y(\(e.g.,)h(a)e('10D') h(binary)d(table)i(column)f(will)h(ha)m(v)m(e)g(width)f(=)g(8,)h(an)f (ASCI)s(I)f(table)i('F12.2')i(column)d(will)120 3026 y(ha)m(v)m(e)39 b(width)d(=)h(12,)j(and)d(a)h(binary)f(table'60A')i(c)m (haracter)g(string)f(column)f(will)h(ha)m(v)m(e)g(width)f(=)g(60\);)120 3139 y(Note)43 b(that)g(this)f(routine)f(supp)s(orts)g(the)h(lo)s(cal)h (con)m(v)m(en)m(tion)h(for)e(sp)s(ecifying)f(arra)m(ys)i(of)f(\014xed)f (length)120 3252 y(strings)32 b(within)f(a)h(binary)f(table)i(c)m (haracter)h(column)d(using)h(the)g(syn)m(tax)g(TF)m(ORM)h(=)e('rAw')h (where)f('r')120 3364 y(is)f(the)g(total)i(n)m(um)m(b)s(er)d(of)h(c)m (haracters)i(\(=)e(the)g(width)g(of)g(the)g(column\))h(and)e('w')h(is)g (the)h(width)e(of)h(a)h(unit)120 3477 y(string)h(within)f(the)h (column.)45 b(Th)m(us)31 b(if)h(the)g(column)f(has)h(TF)m(ORM)g(=)f ('60A12')k(then)c(this)h(means)g(that)120 3590 y(eac)m(h)38 b(ro)m(w)f(of)g(the)g(table)h(con)m(tains)g(5)g(12-c)m(haracter)i (substrings)35 b(within)i(the)g(60-c)m(haracter)j(\014eld,)e(and)120 3703 y(th)m(us)33 b(in)g(this)h(case)g(this)g(routine)f(will)h(return)e (t)m(yp)s(eco)s(de)i(=)f(TSTRING,)g(rep)s(eat)h(=)f(60,)i(and)e(width)g (=)120 3816 y(12.)47 b(The)31 b(n)m(um)m(b)s(er)g(of)h(substings)g(in)f (an)m(y)i(binary)e(table)i(c)m(haracter)h(string)e(\014eld)g(can)g(b)s (e)f(calculated)j(b)m(y)120 3929 y(\(rep)s(eat/width\).)47 b(A)33 b(n)m(ull)f(p)s(oin)m(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)h(for)f (an)m(y)h(of)f(the)h(output)f(parameters)g(that)h(are)g(not)120 4042 y(needed.)120 4237 y Fc(________________________)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)120 4349 y(int)47 b(fits_insert_rows\(fitsfil)o(e)42 b(*fptr,)k(long)h(firstrow,)e(long)h(nrows,)h(int)f(*status\))120 4462 y(int)h(fits_delete_rows\(fitsfil)o(e)42 b(*fptr,)k(long)h (firstrow,)e(long)h(nrows,)h(int)f(*status\))120 4575 y(int)h(fits_delete_rowrange\(fit)o(sfil)o(e)42 b(*fptr,)k(char)g (*rangelist,)f(int)i(*status\))120 4688 y(int)g (fits_delete_rowlist\(fits)o(file)41 b(*fptr,)46 b(long)h(*rowlist,)e (long)i(nrows,)f(int)h(*stat\))261 4883 y Ff(Insert)33 b(or)g(delete)h(ro)m(ws)f(in)f(a)i(table.)49 b(The)33 b(blank)f(ro)m(ws)h(are)h(inserted)e(immediately)j(follo)m(wing)f(ro)m (w)120 4996 y Fc(frow)p Ff(.)54 b(Set)35 b Fc(frow)f Ff(=)g(0)i(to)f(insert)g(ro)m(ws)g(at)h(the)f(b)s(eginning)g(of)g(the)g (table.)56 b(The)34 b(\014rst)h('delete')h(routine)120 5109 y(deletes)k Fc(nrows)d Ff(ro)m(ws)i(b)s(eginning)f(with)h(ro)m(w)g Fc(firstrow)p Ff(.)64 b(The)38 b(2nd)g(delete)i(routine)f(tak)m(es)i (an)d(input)120 5222 y(string)27 b(listing)h(the)f(ro)m(ws)f(or)h(ro)m (w)g(ranges)g(to)h(b)s(e)e(deleted)i(\(e.g.,)h('2,4-7,)h(9-12'\).)42 b(The)26 b(last)i(delete)g(routine)120 5334 y(tak)m(es)35 b(an)f(input)e(long)i(in)m(teger)h(arra)m(y)g(that)f(sp)s(eci\014es)f (eac)m(h)i(individual)e(ro)m(w)h(to)g(b)s(e)f(deleted.)51 b(The)33 b(ro)m(w)120 5447 y(lists)j(m)m(ust)f(b)s(e)f(sorted)i(in)f (ascending)g(order.)55 b(All)36 b(these)g(routines)f(up)s(date)f(the)i (v)-5 b(alue)35 b(of)h(the)f Fc(NAXIS2)120 5560 y Ff(k)m(eyw)m(ord)c (to)g(re\015ect)g(the)f(new)g(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(in)g (the)h(table.)1905 5809 y(14)p eop end %%Page: 15 15 TeXDict begin 15 14 bop 120 573 a Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(_)120 686 y(int)47 b(fits_insert_col\(fitsfile)41 b(*fptr,)46 b(int)h(colnum,)f(char)h(*ttype,)e(char)i(*tform,)1075 799 y(int)f(*status\))120 912 y(int)h(fits_insert_cols\(fitsfil)o(e)42 b(*fptr,)k(int)h(colnum,)f(int)h(ncols,)f(char)g(**ttype,)1122 1024 y(char)h(**tform,)e(int)i(*status\))120 1250 y(int)g (fits_delete_col\(fitsfile)41 b(*fptr,)46 b(int)h(colnum,)f(int)h (*status\))261 1457 y Ff(Insert)25 b(or)g(delete)h(columns)f(in)f(a)i (table.)39 b Fc(colnum)24 b Ff(giv)m(es)i(the)f(p)s(osition)g(of)g(the) h(column)e(to)i(b)s(e)f(inserted)120 1570 y(or)34 b(deleted)g(\(where)g (the)g(\014rst)f(column)h(of)g(the)g(table)h(is)e(at)i(p)s(osition)f (1\).)52 b Fc(ttype)32 b Ff(and)h Fc(tform)g Ff(giv)m(e)i(the)120 1683 y(column)j(name)h(and)f(column)g(format,)j(where)d(the)h(allo)m(w) m(ed)i(format)d(co)s(des)h(are)g(listed)g(ab)s(o)m(v)m(e)h(in)e(the)120 1796 y(description)45 b(of)g(the)h Fc(fits)p 1088 1796 29 4 v 33 w(create)p 1409 1796 V 33 w(table)d Ff(routine.)85 b(The)45 b(2nd)f('insert')i(routine)f(inserts)g(m)m(ultiple)120 1909 y(columns,)33 b(where)g Fc(ncols)e Ff(is)i(the)g(n)m(um)m(b)s(er)e (of)i(columns)g(to)g(insert,)h(and)e Fc(ttype)f Ff(and)h Fc(tform)g Ff(are)h(arra)m(ys)120 2022 y(of)e(string)f(p)s(oin)m(ters)g (in)g(this)g(case.)120 2229 y Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o (___)120 2342 y(int)47 b(fits_copy_col\(fitsfile)42 b(*infptr,)j (fitsfile)h(*outfptr,)f(int)i(incolnum,)502 2455 y(int)g(outcolnum,)e (int)i(create_col,)d(int)j(*status\);)261 2662 y Ff(Cop)m(y)31 b(a)g(column)g(from)f(one)i(table)f(HDU)h(to)g(another.)42 b(If)31 b Fc(create)p 2609 2662 V 32 w(col)f Ff(=)h(TR)m(UE)g(\(i.e.,)i (not)e(equal)120 2775 y(to)42 b(zero\),)k(then)41 b(a)h(new)f(column)g (will)h(b)s(e)f(inserted)g(in)h(the)f(output)g(table)i(at)f(p)s (osition)g Fc(outcolumn)p Ff(,)120 2888 y(otherwise)31 b(the)f(v)-5 b(alues)31 b(in)f(the)h(existing)g(output)f(column)g(will) h(b)s(e)f(o)m(v)m(erwritten.)120 3095 y Fc(________________________)o (____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(__)120 3208 y(int)47 b(fits_write_col\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(int)h(colnum,)e(long)i(firstrow,)979 3321 y(long)g(firstelem,)e(long)h(nelements,)f(void)i(*array,)f(int)h (*status\))120 3434 y(int)g(fits_write_colnull\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(datatype,)f(int)g(colnum,)979 3547 y(long)h(firstrow,)e(long)i(firstelem,)e(long)h(nelements,)979 3660 y(void)h(*array,)f(void)g(*nulval,)g(int)h(*status\))120 3772 y(int)g(fits_write_col_null\(fits)o(file)41 b(*fptr,)46 b(int)h(colnum,)f(long)g(firstrow,)979 3885 y(long)h(firstelem,)e(long) h(nelements,)f(int)i(*status\))120 4111 y(int)g (fits_read_col\(fitsfile)42 b(*fptr,)k(int)h(datatype,)e(int)i(colnum,) f(long)g(firstrow,)454 4224 y(long)h(firstelem,)e(long)h(nelements,)f (void)i(*nulval,)f(void)g(*array,)454 4337 y(int)h(*anynul,)f(int)g (*status\))261 4657 y Ff(W)-8 b(rite)45 b(or)e(read)g(elemen)m(ts)i(in) e(column)g(n)m(um)m(b)s(er)f Fc(colnum)p Ff(,)j(starting)f(with)f(ro)m (w)g Fc(firstsrow)e Ff(and)120 4770 y(elemen)m(t)34 b Fc(firstelem)c Ff(\(if)j(it)g(is)g(a)g(v)m(ector)h(column\).)47 b Fc(firstelem)30 b Ff(is)j(ignored)g(if)f(it)h(is)g(a)g(scalar)g (column.)120 4883 y(The)c Fc(nelements)f Ff(n)m(um)m(b)s(er)g(of)i (elemen)m(ts)i(are)e(read)g(or)f(written)h(con)m(tin)m(uing)h(on)f (successiv)m(e)h(ro)m(ws)f(of)g(the)120 4996 y(table)37 b(if)f(necessary)-8 b(.)59 b Fc(array)35 b Ff(is)h(the)h(address)e(of)h (an)g(arra)m(y)h(whic)m(h)f(either)h(con)m(tains)g(the)g(v)-5 b(alues)36 b(to)h(b)s(e)120 5109 y(written,)28 b(or)e(will)h(hold)g (the)f(returned)g(v)-5 b(alues)27 b(that)g(are)g(read.)39 b(When)27 b(reading,)h Fc(array)d Ff(m)m(ust)h(ha)m(v)m(e)i(b)s(een)120 5222 y(allo)s(cated)k(large)g(enough)e(to)h(hold)f(all)h(the)g (returned)e(v)-5 b(alues.)261 5334 y(There)40 b(are)h(3)h(di\013eren)m (t)f('write')g(column)g(routines:)61 b(The)40 b(\014rst)g(simply)g (writes)h(the)g(input)f(arra)m(y)120 5447 y(in)m(to)33 b(the)f(column.)44 b(The)31 b(second)h(is)g(similar,)g(except)h(that)f (it)g(substitutes)g(the)g(appropriate)f(n)m(ull)h(pixel)120 5560 y(v)-5 b(alue)36 b(in)e(the)i(column)e(for)h(an)m(y)h(input)e (arra)m(y)h(v)-5 b(alues)36 b(whic)m(h)f(are)g(equal)h(to)g Fc(*nulval)d Ff(\(note)j(that)f(this)1905 5809 y(15)p eop end %%Page: 16 16 TeXDict begin 16 15 bop 120 573 a Ff(parameter)39 b(giv)m(es)g(the)g (address)e(of)i(the)f(n)m(ull)g(pixel)h(v)-5 b(alue,)41 b(not)d(the)h(v)-5 b(alue)38 b(itself)7 b(\).)66 b(The)38 b(third)f(write)120 686 y(routine)28 b(sets)g(the)g(sp)s(eci\014ed)f (table)i(elemen)m(ts)g(to)g(a)f(n)m(ull)g(v)-5 b(alue.)40 b(New)28 b(ro)m(ws)g(will)g(b)s(e)g(automatical)i(added)120 799 y(to)h(the)g(table)g(if)f(the)h(write)f(op)s(eration)h(extends)g(b) s(ey)m(ond)e(the)i(curren)m(t)f(size)h(of)g(the)f(table.)261 912 y(When)42 b(reading)g(a)h(column,)i(CFITSIO)40 b(will)j(substitute) f(the)g(v)-5 b(alue)43 b(giv)m(en)g(b)m(y)f Fc(nulval)e Ff(for)i(an)m(y)120 1024 y(unde\014ned)25 b(elemen)m(ts)j(in)f(the)g (FITS)f(column,)i(unless)e Fc(nulval)f Ff(or)i Fc(*nulval)46 b(=)h(NULL)p Ff(,)26 b(in)h(whic)m(h)f(case)i(no)120 1137 y(c)m(hec)m(ks)k(will)f(b)s(e)e(made)i(for)f(unde\014ned)e(v)-5 b(alues)31 b(when)e(reading)i(the)f(column.)261 1250 y Fc(datatype)i Ff(sp)s(eci\014es)i(the)g(datat)m(yp)s(e)h(of)g(the)f (C)g Fc(array)e Ff(in)i(the)g(program,)i(whic)m(h)d(need)h(not)h(b)s(e) e(the)120 1363 y(same)42 b(as)f(the)g(in)m(trinsic)h(datat)m(yp)s(e)g (of)f(the)h(column)f(in)g(the)g(FITS)g(table.)74 b(The)40 b(follo)m(wing)j(sym)m(b)s(olic)120 1476 y(constan)m(ts)32 b(are)e(allo)m(w)m(ed)j(for)d(the)g(v)-5 b(alue)31 b(of)g Fc(datatype)p Ff(:)215 1650 y Fc(TSTRING)142 b(array)46 b(of)h(character)f(string)g(pointers)215 1763 y(TBYTE)238 b(unsigned)45 b(char)215 1876 y(TSHORT)190 b(signed)46 b(short)215 1989 y(TUSHORT)142 b(unsigned)45 b(short)215 2102 y(TINT)286 b(signed)46 b(int)215 2215 y(TUINT)238 b(unsigned)45 b(int)215 2328 y(TLONG)238 b(signed)46 b(long)215 2441 y(TLONGLONG)g(signed)g(8-byte)g(integer)215 2554 y(TULONG)190 b(unsigned)45 b(long)215 2667 y(TFLOAT)190 b(float)215 2779 y(TDOUBLE)142 b(double)261 2954 y Ff(Note)35 b(that)e Fc(TSTRING)f Ff(corresp)s(onds)g(to)h(the)h(C)f Fc(char**)e Ff(datat)m(yp)s(e,)k(i.e.,)h(a)d(p)s(oin)m(ter)g(to)h(an)f (arra)m(y)h(of)120 3067 y(p)s(oin)m(ters)c(to)h(an)g(arra)m(y)f(of)h(c) m(haracters.)261 3179 y(An)m(y)38 b(column,)j(regardless)d(of)h(it's)g (in)m(trinsic)f(datat)m(yp)s(e,)k(ma)m(y)d(b)s(e)e(read)h(as)h(a)f Fc(TSTRING)f Ff(c)m(haracter)120 3292 y(string.)i(The)24 b(displa)m(y)i(format)f(of)g(the)h(returned)e(strings)g(will)i(b)s(e)e (determined)h(b)m(y)g(the)g Fc(TDISPn)f Ff(k)m(eyw)m(ord,)120 3405 y(if)j(it)h(exists,)h(otherwise)f(a)f(default)h(format)g(will)f(b) s(e)g(used)f(dep)s(ending)g(on)i(the)f(datat)m(yp)s(e)h(of)g(the)f (column.)120 3518 y(The)22 b Fc(tablist)e Ff(example)j(utilit)m(y)h (program)e(\(a)m(v)-5 b(ailable)25 b(from)d(the)h(CFITSIO)e(w)m(eb)h (site\))i(uses)e(this)g(feature)120 3631 y(to)31 b(displa)m(y)g(all)g (the)g(v)-5 b(alues)30 b(in)g(a)h(FITS)f(table.)120 3805 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(____)o(___)o(_)120 3918 y(int)47 b(fits_select_rows\(fitsfil)o(e)42 b(*infptr,)j(fitsfile)h(*outfptr,)f (char)i(*expr,)1122 4031 y(int)g(*status\))120 4144 y(int)g (fits_calculator\(fitsfile)41 b(*infptr,)46 b(char)g(*expr,)g(fitsfile) g(*outfptr,)1075 4257 y(char)g(*colname,)f(char)i(*tform,)f(int)h (*status\))261 4431 y Ff(These)26 b(are)h(2)g(of)g(the)f(most)h(p)s(o)m (w)m(erful)f(routines)h(in)f(the)h(CFITSIO)d(library)-8 b(.)40 b(\(See)27 b(the)g(full)f(CFITSIO)120 4544 y(Reference)37 b(Guide)f(for)g(a)h(description)f(of)g(sev)m(eral)i(related)f (routines\).)58 b(These)36 b(routines)g(can)h(p)s(erform)120 4657 y(complicated)47 b(transformations)f(on)f(tables)h(based)f(on)g (an)g(input)g(arithmetic)h(expression)f(whic)m(h)g(is)120 4770 y(ev)-5 b(aluated)38 b(for)e(eac)m(h)h(ro)m(w)g(of)g(the)f(table.) 60 b(The)36 b(\014rst)g(routine)g(will)h(select)h(or)f(cop)m(y)g(ro)m (ws)f(of)h(the)f(table)120 4883 y(for)i(whic)m(h)g(the)g(expression)g (ev)-5 b(aluates)40 b(to)f(TR)m(UE)g(\(i.e.,)i(not)e(equal)g(to)g (zero\).)65 b(The)38 b(second)g(routine)120 4996 y(writes)d(the)g(v)-5 b(alue)35 b(of)g(the)g(expression)g(to)h(a)f(column)g(in)f(the)h (output)g(table.)55 b(Rather)35 b(than)g(supplying)120 5109 y(the)j(expression)f(directly)h(to)g(these)g(routines,)i(the)d (expression)h(ma)m(y)g(also)g(b)s(e)f(written)h(to)g(a)g(text)g(\014le) 120 5222 y(\(con)m(tin)m(ued)f(o)m(v)m(er)f(m)m(ultiple)h(lines)e(if)h (necessary\))g(and)f(the)h(name)f(of)h(the)g(\014le,)h(prep)s(ended)c (with)i(a)h('@')120 5334 y(c)m(haracter,)c(ma)m(y)f(b)s(e)f(supplied)f (as)i(the)f(v)-5 b(alue)31 b(of)g(the)f('expr')g(parameter)h(\(e.g.)42 b('@\014lename.txt'\).)261 5447 y(The)26 b(arithmetic)h(expression)f (ma)m(y)h(b)s(e)f(a)g(function)g(of)g(an)m(y)h(column)f(or)g(k)m(eyw)m (ord)h(in)f(the)g(input)f(table)120 5560 y(as)31 b(sho)m(wn)e(in)h (these)h(examples:)1905 5809 y(16)p eop end %%Page: 17 17 TeXDict begin 17 16 bop 120 573 a Fc(Row)47 b(Selection)e(Expressions:) 263 686 y(counts)h(>)i(0)1240 b(uses)47 b(COUNTS)f(column)g(value)263 799 y(sqrt\()h(X**2)f(+)i(Y**2\))e(<)h(10.)572 b(uses)47 b(X)g(and)g(Y)h(column)e(values)263 912 y(\(X)h(>)h(10\))f(||)g(\(X)g (<)h(-10\))e(&&)h(\(Y)h(==)f(0\))142 b(used)47 b('or')g(and)g('and')f (operators)263 1024 y(gtifilter\(\))1190 b(filter)46 b(on)i(Good)e(Time)h(Intervals)263 1137 y(regfilter\("myregion.reg"\)) 518 b(filter)46 b(using)h(a)g(region)f(file)263 1250 y(@select.txt)1190 b(reads)47 b(expression)e(from)h(a)i(text)e(file)120 1363 y(Calculator)f(Expressions:)263 1476 y(#row)i(\045)g(10)1145 b(modulus)46 b(of)h(the)g(row)g(number)263 1589 y(counts/#exposure)807 b(Fn)47 b(of)h(COUNTS)e(column)g(and)h(EXPOSURE)e(keyword)263 1702 y(dec)i(<)h(85)f(?)g(cos\(dec)f(*)h(#deg\))g(:)g(0)143 b(Conditional)45 b(expression:)g(evaluates)g(to)1934 1815 y(cos\(dec\))g(if)i(dec)g(<)h(85,)f(else)f(0)263 1928 y(\(count{-1}+count+count{+1)o(}\)/3)o(.)137 b(running)46 b(mean)h(of)g(the)g(count)f(values)g(in)h(the)1934 2041 y(previous,)e(current,)g(and)i(next)g(rows)263 2154 y(max\(0,)f (min\(X,)g(1000\)\))619 b(returns)46 b(a)h(value)g(between)f(0)h(-)h (1000)263 2267 y(@calc.txt)1143 b(reads)47 b(expression)e(from)h(a)i (text)e(file)261 2479 y Ff(Most)40 b(standard)d(mathematical)k(op)s (erators)e(and)f(functions)g(are)h(supp)s(orted.)64 b(If)38 b(the)h(expression)120 2592 y(includes)34 b(the)h(name)f(of)h(a)f (column,)i(than)e(the)h(v)-5 b(alue)35 b(in)f(the)g(curren)m(t)h(ro)m (w)f(of)h(the)f(table)i(will)e(b)s(e)g(used)120 2705 y(when)f(ev)-5 b(aluating)35 b(the)f(expression)g(on)g(eac)m(h)h(ro)m (w.)51 b(An)34 b(o\013set)h(to)g(an)e(adjacen)m(t)j(ro)m(w)e(can)g(b)s (e)f(sp)s(eci\014ed)120 2818 y(b)m(y)d(including)g(the)g(o\013set)h(v) -5 b(alue)30 b(in)g(curly)g(brac)m(k)m(ets)h(after)g(the)f(column)g (name)g(as)g(sho)m(wn)g(in)g(one)g(of)g(the)120 2931 y(examples.)40 b(Keyw)m(ord)27 b(v)-5 b(alues)28 b(can)f(b)s(e)g (included)f(in)h(the)h(expression)f(b)m(y)g(preceding)g(the)h(k)m(eyw)m (ord)f(name)120 3044 y(with)h(a)h(`#')f(sign.)40 b(See)28 b(Section)i(5)e(of)h(this)f(do)s(cumen)m(t)g(for)g(more)g(discussion)g (of)g(the)h(expression)f(syn)m(tax.)261 3156 y Fc(gtifilter)h Ff(is)i(a)h(sp)s(ecial)g(function)f(whic)m(h)g(tests)h(whether)f(the)h Fc(TIME)e Ff(column)h(v)-5 b(alue)32 b(in)f(the)g(input)120 3269 y(table)39 b(falls)g(within)f(one)h(or)f(more)h(Go)s(o)s(d)f(Time) g(In)m(terv)-5 b(als.)66 b(By)39 b(default,)h(this)f(function)f(lo)s (oks)h(for)f(a)120 3382 y('GTI')27 b(extension)g(in)f(the)h(same)g (\014le)f(as)h(the)g(input)e(table.)41 b(The)26 b('GTI')g(table)i(con)m (tains)g Fc(START)d Ff(and)h Fc(STOP)120 3495 y Ff(columns)g(whic)m(h)h (de\014ne)f(the)g(range)h(of)g(eac)m(h)h(go)s(o)s(d)f(time)g(in)m(terv) -5 b(al.)41 b(See)27 b(section)g(5.4.3)i(for)d(more)h(details.)261 3608 y Fc(regfilter)35 b Ff(is)i(another)g(sp)s(ecial)h(function)f (whic)m(h)g(selects)h(ro)m(ws)g(based)e(on)h(whether)g(the)g(spatial) 120 3721 y(p)s(osition)23 b(asso)s(ciated)i(with)e(eac)m(h)i(ro)m(w)e (is)g(lo)s(cated)i(within)e(in)g(a)g(sp)s(eci\014ed)g(region)h(of)f (the)h(sky)-8 b(.)38 b(By)24 b(default,)120 3834 y(the)35 b Fc(X)g Ff(and)f Fc(Y)h Ff(columns)g(in)g(the)g(input)f(table)i(are)f (assumed)g(to)h(giv)m(e)g(the)f(p)s(osition)g(of)h(eac)m(h)g(ro)m(w.)55 b(The)120 3947 y(spatial)37 b(region)f(is)f(de\014ned)g(in)g(an)g(ASCI) s(I)f(text)j(\014le)e(whose)h(name)f(is)h(giv)m(en)g(as)g(the)g (argumen)m(t)g(to)g(the)120 4060 y Fc(regfilter)28 b Ff(function.)40 b(See)31 b(section)g(5.4.4)i(for)d(more)g(details.)261 4173 y(The)e Fc(infptr)e Ff(and)i Fc(outfptr)e Ff(parameters)j(in)f (these)g(routines)g(ma)m(y)h(p)s(oin)m(t)f(to)h(the)g(same)f(table)h (or)g(to)120 4286 y(di\013eren)m(t)i(tables.)43 b(In)31 b Fc(fits)p 1092 4286 29 4 v 33 w(select)p 1413 4286 V 33 w(rows)p Ff(,)f(if)g(the)i(input)d(and)i(output)f(tables)i(are)f (the)g(same)h(then)e(the)120 4399 y(ro)m(ws)e(that)h(do)f(not)g (satisfy)h(the)f(selection)i(expression)e(will)g(b)s(e)f(deleted)i (from)f(the)g(table.)41 b(Otherwise,)28 b(if)120 4511 y(the)j(output)g(table)h(is)f(di\013eren)m(t)h(from)f(the)g(input)f (table)i(then)f(the)g(selected)i(ro)m(ws)e(will)h(b)s(e)e(copied)i (from)120 4624 y(the)f(input)e(table)i(to)g(the)g(output)f(table.)261 4737 y(The)i(output)g(column)g(in)g Fc(fits)p 1376 4737 V 33 w(calculator)e Ff(ma)m(y)i(or)h(ma)m(y)g(not)f(already)h(exist.)47 b(If)32 b(it)h(exists)g(then)120 4850 y(the)44 b(calculated)h(v)-5 b(alues)44 b(will)g(b)s(e)f(written)h(to)g(that)h(column,)i(o)m(v)m (erwriting)e(the)e(existing)i(v)-5 b(alues.)81 b(If)120 4963 y(the)36 b(column)g(do)s(esn't)g(exist)g(then)g(the)g(new)g (column)f(will)i(b)s(e)e(app)s(ended)f(to)j(the)f(output)g(table.)58 b(The)120 5076 y Fc(tform)37 b Ff(parameter)i(can)f(b)s(e)g(used)g(to)h (sp)s(ecify)f(the)g(datat)m(yp)s(e)i(of)e(the)h(new)f(column)g(\(e.g.,) k(the)d Fc(TFORM)120 5189 y Ff(k)m(eyw)m(ord)26 b(v)-5 b(alue)26 b(as)g(in)g Fc('1E',)46 b(or)h('1J')p Ff(\).)25 b(If)h Fc(tform)e Ff(=)h(NULL)h(then)f(a)h(default)g(datat)m(yp)s(e)h (will)f(b)s(e)f(used,)120 5302 y(dep)s(ending)k(on)h(the)h(expression.) 120 5514 y Fc(________________________)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(_)1905 5809 y Ff(17)p eop end %%Page: 18 18 TeXDict begin 18 17 bop 120 573 a Fc(int)47 b (fits_read_tblbytes\(fitsf)o(ile)41 b(*fptr,)46 b(long)h(firstrow,)e (long)i(firstchar,)1122 686 y(long)g(nchars,)f(unsigned)f(char)i (*array,)f(int)h(*status\))120 799 y(int)g(fits_write_tblbytes)42 b(\(fitsfile)k(*fptr,)g(long)g(firstrow,)g(long)g(firstchar,)1122 912 y(long)h(nchars,)f(unsigned)f(char)i(*array,)f(int)h(*status\))261 1124 y Ff(These)35 b(2)g(routines)f(pro)m(vide)h(lo)m(w-lev)m(el)j (access)e(to)f(tables)h(and)e(are)h(mainly)g(useful)f(as)h(an)g (e\016cien)m(t)120 1237 y(w)m(a)m(y)i(to)g(cop)m(y)g(ro)m(ws)f(of)g(a)h (table)g(from)f(one)g(\014le)g(to)h(another.)58 b(These)36 b(routines)g(simply)g(read)g(or)g(write)120 1350 y(the)30 b(sp)s(eci\014ed)g(n)m(um)m(b)s(er)f(of)h(consecutiv)m(e)j(c)m (haracters)e(\(b)m(ytes\))h(in)e(a)h(table,)g(without)f(regard)g(for)h (column)120 1463 y(b)s(oundaries.)84 b(F)-8 b(or)47 b(example,)j(to)c (read)f(or)h(write)f(the)h(\014rst)f(ro)m(w)g(of)h(a)g(table,)k(set)c Fc(firstrow)g(=)h(1,)120 1576 y(firstchar)e(=)j(1)p Ff(,)38 b(and)e Fc(nchars)46 b(=)i(NAXIS1)35 b Ff(where)h(the)h(length)g(of)g (a)h(ro)m(w)f(is)f(giv)m(en)i(b)m(y)f(the)g(v)-5 b(alue)37 b(of)120 1689 y(the)31 b Fc(NAXIS1)f Ff(header)h(k)m(eyw)m(ord.)43 b(When)31 b(reading)h(a)f(table,)i Fc(array)d Ff(m)m(ust)h(ha)m(v)m(e)h (b)s(een)f(declared)g(at)h(least)120 1802 y Fc(nchars)d Ff(b)m(ytes)i(long)g(to)g(hold)f(the)g(returned)f(string)i(of)f(b)m (ytes.)1905 5809 y(18)p eop end %%Page: 19 19 TeXDict begin 19 18 bop 120 573 a Fb(4.6)112 b(Header)38 b(Keyw)m(ord)f(I/O)h(Routines)120 744 y Ff(The)30 b(follo)m(wing)i (routines)e(read)g(and)g(write)h(header)f(k)m(eyw)m(ords)g(in)h(the)f (curren)m(t)g(HDU.)120 957 y Fc(________________________)o(____)o(____) o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)120 1070 y(int)47 b(fits_get_hdrspace\(fitsfi)o(le)42 b(*fptr,)k(int)h (*keysexist,)d(int)j(*morekeys,)1170 1183 y(int)g(*status\))120 1395 y Ff(Return)36 b(the)g(n)m(um)m(b)s(er)f(of)i(existing)g(k)m(eyw)m (ords)g(\(not)g(coun)m(ting)g(the)g(mandatory)f(END)h(k)m(eyw)m(ord\))g (and)120 1508 y(the)29 b(amoun)m(t)h(of)f(empt)m(y)h(space)g(curren)m (tly)f(a)m(v)-5 b(ailable)31 b(for)e(more)h(k)m(eyw)m(ords.)40 b(The)29 b Fc(morekeys)e Ff(parameter)120 1621 y(ma)m(y)k(b)s(e)f(set)h (to)g(NULL)f(if)g(it's)h(v)-5 b(alue)31 b(is)g(not)f(needed.)120 1834 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(___)120 1947 y(int)47 b(fits_read_record\(fitsfil)o(e)42 b(*fptr,)k(int)h (keynum,)f(char)g(*record,)g(int)h(*status\))120 2060 y(int)g(fits_read_card\(fitsfile)41 b(*fptr,)46 b(char)h(*keyname,)e (char)i(*record,)f(int)g(*status\))120 2172 y(int)h (fits_read_key\(fitsfile)42 b(*fptr,)k(int)h(datatype,)e(char)i (*keyname,)979 2285 y(void)g(*value,)f(char)g(*comment,)f(int)i (*status\))120 2511 y(int)g(fits_find_nextkey\(fitsfi)o(le)42 b(*fptr,)k(char)g(**inclist,)f(int)i(ninc,)1170 2624 y(char)g(**exclist,)e(int)i(nexc,)f(char)h(*card,)f(int)h(*status\))120 2850 y(int)g(fits_read_key_unit\(fitsf)o(ile)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*unit,)1218 2963 y(int)g(*status\))261 3175 y Ff(These)d(routines)h(all)g(read)f(a)h(header)f(record)g(in)g (the)h(curren)m(t)f(HDU.)i(The)e(\014rst)f(routine)i(reads)120 3288 y(k)m(eyw)m(ord)40 b(n)m(um)m(b)s(er)f Fc(keynum)f Ff(\(where)i(the)g(\014rst)f(k)m(eyw)m(ord)i(is)f(at)h(p)s(osition)f (1\).)70 b(This)39 b(routine)h(is)g(most)120 3401 y(commonly)29 b(used)f(when)f(sequen)m(tially)j(reading)e(ev)m(ery)i(record)e(in)g (the)h(header)f(from)g(b)s(eginning)g(to)h(end.)120 3514 y(The)d(2nd)f(and)g(3rd)h(routines)g(read)g(the)g(named)f(k)m(eyw)m (ord)i(and)e(return)g(either)i(the)f(whole)g(record,)h(or)f(the)120 3627 y(k)m(eyw)m(ord)g(v)-5 b(alue)26 b(and)e(commen)m(t)j(string.)39 b(In)25 b(eac)m(h)h(case)h(an)m(y)e(non-signi\014can)m(t)h(trailing)h (blank)e(c)m(haracters)120 3740 y(in)30 b(the)h(strings)f(are)h (truncated.)261 3853 y(Wild)c(card)e(c)m(haracters)j(\(*,)g(?,)f(and)e (#\))h(ma)m(y)h(b)s(e)e(used)g(when)g(sp)s(ecifying)h(the)g(name)h(of)f (the)g(k)m(eyw)m(ord)120 3966 y(to)31 b(b)s(e)f(read,)g(in)g(whic)m(h)h (case)g(the)g(\014rst)e(matc)m(hing)j(k)m(eyw)m(ord)e(is)h(returned.) 261 4079 y(The)41 b Fc(datatype)e Ff(parameter)j(sp)s(eci\014es)f(the)g (C)g(datat)m(yp)s(e)h(of)g(the)f(returned)f(k)m(eyw)m(ord)i(v)-5 b(alue)42 b(and)120 4192 y(can)48 b(ha)m(v)m(e)h(one)f(of)g(the)f (follo)m(wing)i(sym)m(b)s(olic)f(constan)m(t)h(v)-5 b(alues:)76 b Fc(TSTRING,)46 b(TLOGICAL)f Ff(\(==)i(in)m(t\),)120 4304 y Fc(TBYTE)p Ff(,)d Fc(TSHORT)p Ff(,)f Fc(TUSHORT)p Ff(,)g Fc(TINT)p Ff(,)h Fc(TUINT)p Ff(,)f Fc(TLONG)p Ff(,)h Fc(TULONG)p Ff(,)f Fc(TFLOAT)p Ff(,)g Fc(TDOUBLE)p Ff(,)g Fc(TCOMPLEX)p Ff(,)g(and)120 4417 y Fc(TDBLCOMPLEX)p Ff(.)e(Data)k(t)m(yp)s(e)f(con)m(v)m(ersion)h(will)f(b)s(e)f(p)s (erformed)f(for)i(n)m(umeric)f(v)-5 b(alues)44 b(if)g(the)g(in)m (trinsic)120 4530 y(FITS)32 b(k)m(eyw)m(ord)h(v)-5 b(alue)33 b(do)s(es)f(not)g(ha)m(v)m(e)i(the)f(same)g(datat)m(yp)s(e.)48 b(The)32 b Fc(comment)e Ff(parameter)j(ma)m(y)g(b)s(e)f(set)120 4643 y(equal)f(to)g(NULL)f(if)h(the)f(commen)m(t)i(string)e(is)g(not)h (needed.)261 4756 y(The)21 b(4th)h(routine)g(pro)m(vides)g(an)g(easy)g (w)m(a)m(y)h(to)f(\014nd)e(all)j(the)f(k)m(eyw)m(ords)g(in)g(the)f (header)h(that)g(matc)m(h)h(one)120 4869 y(of)29 b(the)h(name)f (templates)h(in)f Fc(inclist)e Ff(and)h(do)h(not)h(matc)m(h)g(an)m(y)f (of)g(the)h(name)f(templates)h(in)f Fc(exclist)p Ff(.)120 4982 y Fc(ninc)37 b Ff(and)h Fc(nexc)f Ff(are)i(the)g(n)m(um)m(b)s(er)e (of)h(template)i(strings)e(in)g Fc(inclist)f Ff(and)h Fc(exclist)p Ff(,)g(resp)s(ectiv)m(ely)-8 b(.)120 5095 y(Wild)35 b(cards)f(\(*,)i(?,)f(and)f(#\))g(ma)m(y)h(b)s(e)f(used)f(in) h(the)g(templates)i(to)f(matc)m(h)g(m)m(ultiple)g(k)m(eyw)m(ords.)53 b(Eac)m(h)120 5208 y(time)36 b(this)f(routine)g(is)g(called)h(it)f (returns)f(the)h(next)h(matc)m(hing)g(80-b)m(yte)g(k)m(eyw)m(ord)g (record.)54 b(It)36 b(returns)120 5321 y(status)31 b(=)f Fc(KEY)p 640 5321 29 4 v 33 w(NO)p 769 5321 V 34 w(EXIST)f Ff(if)h(there)h(are)g(no)f(more)g(matc)m(hes.)261 5434 y(The)f(5th)g(routine)g(returns)f(the)i(k)m(eyw)m(ord)g(v)-5 b(alue)29 b(units)g(string,)g(if)h(an)m(y)-8 b(.)41 b(The)28 b(units)h(are)h(recorded)f(at)120 5546 y(the)i(b)s(eginning)e(of)i(the) f(k)m(eyw)m(ord)h(commen)m(t)h(\014eld)e(enclosed)h(in)f(square)g(brac) m(k)m(ets.)1905 5809 y(19)p eop end %%Page: 20 20 TeXDict begin 20 19 bop 120 573 a Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(__)120 686 y(int)47 b(fits_write_key\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(char)g(*keyname,)502 799 y(void)g(*value,)g(char)h (*comment,)e(int)i(*status\))120 912 y(int)g(fits_update_key\(fitsfile) 41 b(*fptr,)46 b(int)h(datatype,)e(char)i(*keyname,)502 1024 y(void)f(*value,)g(char)h(*comment,)e(int)i(*status\))120 1137 y(int)g(fits_write_record\(fitsfi)o(le)42 b(*fptr,)k(char)g (*card,)g(int)h(*status\))120 1363 y(int)g(fits_modify_comment\(fits)o (file)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*comment,)502 1476 y(int)g(*status\))120 1589 y(int)g(fits_write_key_unit\(fits)o (file)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*unit,)502 1702 y(int)g(*status\))261 1975 y Ff(W)-8 b(rite)32 b(or)f(mo)s(dify)g (a)g(k)m(eyw)m(ord)g(in)g(the)g(header)g(of)g(the)g(curren)m(t)g(HDU.)h (The)e(\014rst)g(routine)h(app)s(ends)120 2087 y(the)f(new)g(k)m(eyw)m (ord)g(to)h(the)f(end)g(of)g(the)g(header,)h(whereas)e(the)i(second)f (routine)g(will)g(up)s(date)g(the)g(v)-5 b(alue)120 2200 y(and)40 b(commen)m(t)h(\014elds)f(of)h(the)g(k)m(eyw)m(ord)g(if)f(it)h (already)h(exists,)h(otherwise)e(it)h(b)s(eha)m(v)m(es)f(lik)m(e)g(the) g(\014rst)120 2313 y(routine)33 b(and)f(app)s(ends)f(the)h(new)h(k)m (eyw)m(ord.)48 b(Note)34 b(that)f Fc(value)e Ff(giv)m(es)j(the)f (address)f(to)h(the)g(v)-5 b(alue)33 b(and)120 2426 y(not)e(the)g(v)-5 b(alue)32 b(itself.)43 b(The)31 b Fc(datatype)d Ff(parameter)k(sp)s (eci\014es)e(the)i(C)e(datat)m(yp)s(e)i(of)f(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)120 2539 y(and)38 b(ma)m(y)g(ha)m(v)m(e)i(an)m(y)f(of)f(the)g(v) -5 b(alues)39 b(listed)g(in)f(the)g(description)g(of)h(the)f(k)m(eyw)m (ord)h(reading)f(routines,)120 2652 y(ab)s(o)m(v)m(e.)71 b(A)40 b(NULL)g(ma)m(y)h(b)s(e)e(en)m(tered)i(for)f(the)g(commen)m(t)h (parameter,)i(in)d(whic)m(h)g(case)h(the)f(k)m(eyw)m(ord)120 2765 y(commen)m(t)31 b(\014eld)f(will)h(b)s(e)f(unmo)s(di\014ed)e(or)i (left)i(blank.)261 2878 y(The)25 b(third)g(routine)h(is)g(more)g (primitiv)m(e)h(and)e(simply)g(writes)h(the)g(80-c)m(haracter)j Fc(card)c Ff(record)h(to)g(the)120 2991 y(header.)40 b(It)30 b(is)g(the)g(programmer's)f(resp)s(onsibilit)m(y)h(in)f(this)h (case)g(to)h(ensure)e(that)h(the)g(record)g(conforms)120 3104 y(to)h(all)g(the)g(FITS)f(format)g(requiremen)m(ts)h(for)f(a)h (header)f(record.)261 3217 y(The)42 b(fourth)f(routine)h(mo)s(di\014es) f(the)h(commen)m(t)h(string)f(in)g(an)f(existing)i(k)m(eyw)m(ord,)j (and)41 b(the)h(last)120 3329 y(routine)34 b(writes)g(or)g(up)s(dates)f (the)h(k)m(eyw)m(ord)h(units)e(string)h(for)g(an)g(existing)h(k)m(eyw)m (ord.)52 b(\(The)34 b(units)f(are)120 3442 y(recorded)d(at)h(the)g(b)s (eginning)f(of)g(the)h(k)m(eyw)m(ord)f(commen)m(t)i(\014eld)e(enclosed) h(in)f(square)g(brac)m(k)m(ets\).)120 3621 y Fc (________________________)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(____)o(__)120 3734 y(int)47 b(fits_write_comment\(fitsf)o(ile)41 b(*fptr,)46 b(char)h(*comment,)93 b(int)47 b(*status\))120 3847 y(int)g(fits_write_history\(fitsf)o(ile) 41 b(*fptr,)46 b(char)h(*history,)93 b(int)47 b(*status\))120 3960 y(int)g(fits_write_date\(fitsfile)41 b(*fptr,)94 b(int)47 b(*status\))261 4139 y Ff(W)-8 b(rite)22 b(a)f Fc(COMMENT,)46 b(HISTORY)p Ff(,)18 b(or)j Fc(DATE)e Ff(k)m(eyw)m(ord)i (to)h(the)f(curren)m(t)f(header.)37 b(The)20 b Fc(COMMENT)f Ff(k)m(eyw)m(ord)120 4252 y(is)38 b(t)m(ypically)i(used)d(to)h(write)h (a)f(commen)m(t)h(ab)s(out)e(the)i(\014le)f(or)f(the)i(data.)64 b(The)37 b Fc(HISTORY)f Ff(k)m(eyw)m(ord)i(is)120 4365 y(t)m(ypically)25 b(used)c(to)j(pro)m(vide)f(information)g(ab)s(out)f (the)h(history)f(of)h(the)g(pro)s(cessing)f(pro)s(cedures)g(that)h(ha)m (v)m(e)120 4478 y(b)s(een)36 b(applied)h(to)g(the)g(data.)61 b(The)36 b Fc(comment)f Ff(or)i Fc(history)e Ff(string)i(will)g(b)s(e)f (con)m(tin)m(ued)i(o)m(v)m(er)g(m)m(ultiple)120 4591 y(k)m(eyw)m(ords)31 b(if)f(it)h(is)f(more)h(than)f(70)h(c)m(haracters)h (long.)261 4704 y(The)k Fc(DATE)f Ff(k)m(eyw)m(ord)i(is)f(used)g(to)h (record)f(the)h(date)g(and)f(time)h(that)g(the)f(FITS)g(\014le)g(w)m (as)h(created.)120 4817 y(Note)f(that)f(this)f(\014le)h(creation)h (date)f(is)g(usually)f(di\013eren)m(t)h(from)f(the)h(date)g(of)g(the)f (observ)-5 b(ation)36 b(whic)m(h)120 4930 y(obtained)e(the)g(data)h(in) e(the)i(FITS)e(\014le.)51 b(The)33 b Fc(DATE)g Ff(k)m(eyw)m(ord)h(v)-5 b(alue)35 b(is)f(a)g(c)m(haracter)i(string)d(in)h('yyyy-)120 5042 y(mm-ddThh:mm:ss')27 b(format.)40 b(If)29 b(a)g Fc(DATE)f Ff(k)m(eyw)m(ord)i(already)f(exists)h(in)f(the)g(header,)h (then)e(this)h(routine)120 5155 y(will)i(up)s(date)e(the)i(v)-5 b(alue)31 b(with)f(the)g(curren)m(t)g(system)h(date.)120 5334 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(__)120 5447 y(int)47 b(fits_delete_record\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(keynum,)94 b(int)47 b(*status\))120 5560 y(int)g (fits_delete_key\(fitsfile)41 b(*fptr,)46 b(char)h(*keyname,)93 b(int)47 b(*status\))1905 5809 y Ff(20)p eop end %%Page: 21 21 TeXDict begin 21 20 bop 261 573 a Ff(Delete)33 b(a)e(k)m(eyw)m(ord)h (record.)42 b(The)30 b(\014rst)g(routine)h(deletes)h(a)f(k)m(eyw)m(ord) h(at)f(a)h(sp)s(eci\014ed)e(p)s(osition)h(\(the)120 686 y(\014rst)c(k)m(eyw)m(ord)h(is)f(at)h(p)s(osition)g(1,)h(not)e(0\),)i (whereas)f(the)f(second)h(routine)f(deletes)i(the)f(named)f(k)m(eyw)m (ord.)120 898 y Fc(________________________)o(____)o(____)o(___)o(____) o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(___)120 1011 y(int)47 b(fits_copy_header\(fitsfil)o(e)42 b(*infptr,)j(fitsfile) h(*outfptr,)93 b(int)47 b(*status\))261 1224 y Ff(Cop)m(y)26 b(all)h(the)f(header)g(k)m(eyw)m(ords)h(from)e(the)i(curren)m(t)e(HDU)i (asso)s(ciated)h(with)d(infptr)g(to)i(the)g(curren)m(t)120 1337 y(HDU)h(asso)s(ciated)g(with)e(outfptr.)39 b(If)27 b(the)g(curren)m(t)f(output)h(HDU)g(is)g(not)g(empt)m(y)-8 b(,)29 b(then)d(a)h(new)f(HDU)i(will)120 1450 y(b)s(e)34 b(app)s(ended)f(to)j(the)f(output)f(\014le.)54 b(The)35 b(output)f(HDU)i(will)f(then)f(ha)m(v)m(e)i(the)f(iden)m(tical)i (structure)d(as)120 1562 y(the)d(input)e(HDU,)i(but)f(will)h(con)m (tain)g(no)g(data.)1905 5809 y(21)p eop end %%Page: 22 22 TeXDict begin 22 21 bop 120 573 a Fb(4.7)112 b(Utilit)m(y)37 b(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(most)f(imp)s (ortan)m(t)h(CFITSIO)e(general)i(utilit)m(y)h(routines.)120 957 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(__)120 1070 y(int)47 b(fits_write_chksum\()c(fitsfile)i(*fptr,)h(int)h(*status\)) 120 1183 y(int)g(fits_verify_chksum\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(*dataok,)f(int)h(*hduok,)f(int)g(*status\))261 1395 y Ff(These)35 b(routines)g(compute)g(or)g(v)-5 b(alidate)36 b(the)g(c)m(hec)m(ksums)f(for)g(the)g(currenrt)f(HDU.)i(The)e Fc(DATASUM)120 1508 y Ff(k)m(eyw)m(ord)d(is)f(used)f(to)i(store)g(the)f (n)m(umerical)h(v)-5 b(alue)30 b(of)h(the)f(32-bit,)i(1's)e(complemen)m (t)h(c)m(hec)m(ksum)g(for)f(the)120 1621 y(data)25 b(unit)f(alone.)40 b(The)24 b Fc(CHECKSUM)f Ff(k)m(eyw)m(ord)i(is)g(used)e(to)j(store)f (the)g(ASCI)s(I)e(enco)s(ded)h(COMPLEMENT)120 1734 y(of)32 b(the)f(c)m(hec)m(ksum)h(for)f(the)h(en)m(tire)g(HDU.)h(Storing)e(the)h (complemen)m(t,)h(rather)e(than)g(the)h(actual)g(c)m(hec)m(k-)120 1847 y(sum,)26 b(forces)g(the)g(c)m(hec)m(ksum)g(for)f(the)h(whole)g (HDU)g(to)g(equal)g(zero.)40 b(If)25 b(the)h(\014le)g(has)f(b)s(een)g (mo)s(di\014ed)f(since)120 1960 y(the)31 b(c)m(hec)m(ksums)f(w)m(ere)h (computed,)g(then)f(the)g(HDU)i(c)m(hec)m(ksum)f(will)f(usually)g(not)h (equal)g(zero.)261 2073 y(The)f(returned)g Fc(dataok)f Ff(and)h Fc(hduok)g Ff(parameters)h(will)g(ha)m(v)m(e)h(a)f(v)-5 b(alue)31 b(=)g(1)g(if)g(the)g(data)g(or)g(HDU)g(is)120 2186 y(v)m(eri\014ed)d(correctly)-8 b(,)31 b(a)d(v)-5 b(alue)29 b(=)f(0)g(if)g(the)h Fc(DATASUM)d Ff(or)i Fc(CHECKSUM)e Ff(k)m(eyw)m(ord)j(is)f(not)g(presen)m(t,)h(or)f(v)-5 b(alue)29 b(=)120 2299 y(-1)i(if)f(the)h(computed)f(c)m(hec)m(ksum)h (is)g(not)f(correct.)120 2511 y Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(__) 120 2624 y(int)47 b(fits_parse_value\(char)42 b(*card,)k(char)h (*value,)e(char)i(*comment,)e(int)i(*status\))120 2737 y(int)g(fits_get_keytype\(char)42 b(*value,)k(char)g(*dtype,)g(int)h (*status\))120 2850 y(int)g(fits_get_keyclass\(char)42 b(*card\))120 2963 y(int)47 b(fits_parse_template\(char)41 b(*template,)k(char)i(*card,)f(int)h(*keytype,)e(int)i(*status\))261 3288 y(fits)p 459 3288 29 4 v 33 w(parse)p 732 3288 V 33 w(value)29 b Ff(parses)h(the)h(input)e(80-c)m(hararacter)k(header)d (k)m(eyw)m(ord)h(record,)g(returning)e(the)120 3401 y(v)-5 b(alue)21 b(\(as)h(a)f(literal)h(c)m(haracter)h(string\))e(and)f (commen)m(t)i(strings.)38 b(If)20 b(the)h(k)m(eyw)m(ord)h(has)e(no)h(v) -5 b(alue)21 b(\(columns)120 3514 y(9-10)38 b(not)e(equal)h(to)g('=)f ('\),)j(then)d(a)g(n)m(ull)h(v)-5 b(alue)36 b(string)h(is)f(returned)f (and)h(the)g(commen)m(t)h(string)g(is)f(set)120 3627 y(equal)31 b(to)g(column)f(9)h(-)g(80)g(of)f(the)h(input)e(string.)261 3740 y Fc(fits)p 459 3740 V 33 w(get)p 636 3740 V 34 w(keytype)41 b Ff(parses)i(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)43 b(string)g(to)h(determine)f(its)h(datat)m(yp)s(e.)80 b Fc(dtype)120 3853 y Ff(returns)34 b(with)g(a)h(v)-5 b(alue)36 b(of)f('C',)g('L',)g('I',)h('F')f(or)g('X',)h(for)f(c)m (haracter)h(string,)g(logical,)j(in)m(teger,)e(\015oating)120 3966 y(p)s(oin)m(t,)31 b(or)f(complex,)h(resp)s(ectiv)m(ely)-8 b(.)261 4079 y Fc(fits)p 459 4079 V 33 w(get)p 636 4079 V 34 w(keyclass)31 b Ff(returns)i(a)h(classi\014cation)h(co)s(de)f (that)g(indicates)h(the)f(classi\014cation)h(t)m(yp)s(e)f(of)120 4192 y(the)41 b(input)e(k)m(eyw)m(ord)i(record)f(\(e.g.,)45 b(a)40 b(required)g(structural)g(k)m(eyw)m(ord,)k(a)d(TDIM)f(k)m(eyw)m (ord,)k(a)c(W)m(CS)120 4304 y(k)m(eyw)m(ord,)49 b(a)d(commen)m(t)g(k)m (eyw)m(ord,)j(etc.)85 b(See)45 b(the)h(CFITSIO)d(Reference)j(Guide)e (for)h(a)g(list)h(of)f(the)120 4417 y(di\013eren)m(t)31 b(classi\014cation)h(co)s(des.)261 4530 y Fc(fits)p 459 4530 V 33 w(parse)p 732 4530 V 33 w(template)37 b Ff(tak)m(es)j(an)e (input)g(free)g(format)h(k)m(eyw)m(ord)g(template)h(string)f(and)f (returns)120 4643 y(a)i(formatted)g(80*c)m(har)h(record)e(that)h (satis\014es)g(all)h(the)e(FITS)g(requiremen)m(ts)h(for)f(a)h(header)f (k)m(eyw)m(ord)120 4756 y(record.)65 b(The)38 b(template)i(should)d (generally)j(con)m(tain)g(3)f(tok)m(ens:)58 b(the)38 b(k)m(eyw)m(ord)h(name,)i(the)e(k)m(eyw)m(ord)120 4869 y(v)-5 b(alue,)29 b(and)e(the)g(k)m(eyw)m(ord)h(commen)m(t)h(string.)40 b(The)27 b(returned)f Fc(keytype)g Ff(parameter)i(indicates)g(whether) 120 4982 y(the)33 b(k)m(eyw)m(ord)g(is)g(a)g(COMMENT)g(k)m(eyw)m(ord)g (or)g(not.)48 b(See)33 b(the)g(CFITSIO)e(Reference)j(Guide)f(for)f (more)120 5095 y(details.)1905 5809 y(22)p eop end %%Page: 23 23 TeXDict begin 23 22 bop 120 573 a Fh(5)135 b(CFITSIO)44 b(File)h(Names)h(and)f(Filters)120 779 y Fb(5.1)112 b(Creating)38 b(New)f(Files)120 951 y Ff(When)43 b(creating)h(a)f(new)g(output)f (\014le)h(on)g(magnetic)i(disk)d(with)h Fc(fits)p 2677 951 29 4 v 33 w(create)p 2998 951 V 33 w(file)f Ff(the)h(follo)m(wing) 120 1064 y(features)31 b(are)f(supp)s(orted.)256 1251 y Fa(\017)46 b Ff(Ov)m(erwriting,)31 b(or)f('Clobb)s(ering')g(an)h (Existing)f(File)347 1402 y(If)d(the)h(\014lename)g(is)g(preceded)f(b)m (y)g(an)h(exclamation)i(p)s(oin)m(t)d(\(!\))41 b(then)27 b(if)h(that)g(\014le)f(already)i(exists)f(it)347 1514 y(will)h(b)s(e)e(deleted)i(prior)e(to)i(creating)g(the)f(new)g(FITS)f (\014le.)40 b(Otherwise)27 b(if)h(there)g(is)g(an)g(existing)h(\014le) 347 1627 y(with)36 b(the)f(same)h(name,)i(CFITSIO)c(will)i(not)g(o)m(v) m(erwrite)h(the)f(existing)g(\014le)g(and)f(will)h(return)e(an)347 1740 y(error)28 b(status)h(co)s(de.)40 b(Note)30 b(that)f(the)f (exclamation)j(p)s(oin)m(t)d(is)g(a)h(sp)s(ecial)g(UNIX)f(c)m (haracter,)j(so)e(if)f(it)347 1853 y(is)f(used)f(on)g(the)h(command)g (line)g(rather)f(than)g(en)m(tered)i(at)f(a)g(task)g(prompt,)g(it)g(m)m (ust)g(b)s(e)f(preceded)347 1966 y(b)m(y)j(a)h(bac)m(kslash)g(to)g (force)g(the)f(UNIX)h(shell)f(to)i(pass)d(it)i(v)m(erbatim)g(to)g(the)g (application)g(program.)256 2154 y Fa(\017)46 b Ff(Compressed)30 b(Output)f(Files)347 2304 y(If)g(the)g(output)f(disk)h(\014le)g(name)g (ends)f(with)g(the)h(su\016x)f('.gz',)j(then)e(CFITSIO)e(will)i (compress)g(the)347 2417 y(\014le)39 b(using)g(the)g(gzip)h (compression)f(algorithm)h(b)s(efore)e(writing)h(it)h(to)g(disk.)66 b(This)38 b(can)i(reduce)347 2530 y(the)h(amoun)m(t)g(of)g(disk)f (space)h(used)f(b)m(y)g(the)h(\014le.)71 b(Note)42 b(that)f(this)g (feature)g(requires)f(that)h(the)347 2643 y(uncompressed)e(\014le)i(b)s (e)f(constructed)h(in)f(memory)g(b)s(efore)g(it)h(is)g(compressed)f (and)g(written)h(to)347 2756 y(disk,)30 b(so)h(it)g(can)g(fail)g(if)f (there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 b(ailable)32 b(memory)-8 b(.)347 2906 y(One)32 b(can)h(also)h(sp)s(ecify)e(that)h (an)m(y)g(images)h(written)f(to)g(the)g(output)f(\014le)h(should)f(b)s (e)g(compressed)347 3019 y(using)23 b(the)g(newly)g(dev)m(elop)s(ed)h (`tile-compression')h(algorithm)f(b)m(y)f(app)s(ending)f(`[compress]')i (to)g(the)347 3132 y(name)36 b(of)h(the)f(disk)g(\014le)g(\(as)h(in)f Fc(myfile.fits[compress])p Ff(\).)52 b(Refer)36 b(to)h(the)g(CFITSIO)d (User's)347 3245 y(Reference)d(Guide)g(for)f(more)g(information)h(ab)s (out)f(this)g(new)g(image)i(compression)e(format.)256 3432 y Fa(\017)46 b Ff(Using)31 b(a)g(T)-8 b(emplate)31 b(to)g(Create)g(a)g(New)g(FITS)e(File)347 3583 y(The)k(structure)g(of)g (an)m(y)h(new)f(FITS)f(\014le)i(that)g(is)f(to)h(b)s(e)f(created)h(ma)m (y)g(b)s(e)f(de\014ned)f(in)h(an)g(ASCI)s(I)347 3695 y(template)d(\014le.)40 b(If)29 b(the)f(name)h(of)g(the)f(template)i (\014le)f(is)g(app)s(ended)d(to)k(the)e(name)h(of)g(the)f(FITS)g (\014le)347 3808 y(itself,)38 b(enclosed)e(in)f(paren)m(thesis)g (\(e.g.,)j Fc('newfile.fits\(template.tx)o(t\)')p Ff(\))29 b(then)35 b(CFITSIO)347 3921 y(will)c(create)i(a)e(FITS)f(\014le)h (with)f(that)i(structure)e(b)s(efore)h(op)s(ening)f(it)h(for)g(the)g (application)h(to)f(use.)347 4034 y(The)h(template)i(\014le)f (basically)g(de\014nes)f(the)h(dimensions)e(and)h(data)h(t)m(yp)s(e)g (of)g(the)f(primary)g(arra)m(y)347 4147 y(and)23 b(an)m(y)h(IMA)m(GE)g (extensions,)i(and)d(the)g(names)g(and)g(data)h(t)m(yp)s(es)g(of)f(the) h(columns)f(in)g(an)m(y)h(ASCI)s(I)347 4260 y(or)35 b(binary)g(table)h (extensions.)55 b(The)35 b(template)h(\014le)f(can)h(also)g(b)s(e)e (used)h(to)g(de\014ne)g(an)m(y)g(optional)347 4373 y(k)m(eyw)m(ords)g (that)g(should)e(b)s(e)h(written)g(in)h(an)m(y)f(of)h(the)f(HDU)h (headers.)53 b(The)34 b(image)h(pixel)g(v)-5 b(alues)347 4486 y(and)38 b(table)i(en)m(try)e(v)-5 b(alues)39 b(are)g(all)g (initialized)i(to)e(zero.)66 b(The)38 b(application)i(program)e(can)h (then)347 4599 y(write)28 b(actual)g(data)g(in)m(to)h(the)e(HDUs.)40 b(See)28 b(the)f(CFITSIO)f(Reference)i(Guide)f(for)g(for)g(a)h (complete)347 4712 y(description)j(of)f(the)h(template)h(\014le)e(syn)m (tax.)256 4899 y Fa(\017)46 b Ff(Creating)31 b(a)g(T)-8 b(emp)s(orary)30 b(Scratc)m(h)h(File)g(in)f(Memory)347 5050 y(It)38 b(is)g(sometimes)h(useful)e(to)i(create)g(a)f(temp)s (orary)g(output)f(\014le)h(when)f(testing)i(an)f(application)347 5162 y(program.)45 b(If)31 b(the)h(name)g(of)g(the)g(\014le)g(to)h(b)s (e)e(created)i(is)f(sp)s(eci\014ed)f(as)h Fc(mem:)42 b Ff(then)32 b(CFITSIO)e(will)347 5275 y(create)39 b(the)e(\014le)h(in) f(memory)g(where)f(it)i(will)g(p)s(ersist)e(only)h(un)m(til)h(the)f (program)g(closes)i(the)e(\014le.)347 5388 y(Use)e(of)g(this)g Fc(mem:)48 b Ff(output)34 b(\014le)h(usually)f(enables)h(the)g(program) f(to)i(run)d(faster,)j(and)e(of)h(course)347 5501 y(the)c(output)f (\014le)g(do)s(es)g(not)h(use)f(up)f(an)m(y)i(disk)f(space.)1905 5809 y(23)p eop end %%Page: 24 24 TeXDict begin 24 23 bop 120 573 a Fb(5.2)112 b(Op)s(ening)39 b(Existing)e(Files)120 744 y Ff(When)h(op)s(ening)f(a)i(\014le)f(with)g Fc(fits)p 1392 744 29 4 v 33 w(open)p 1617 744 V 33 w(file)p Ff(,)h(CFITSIO)e(can)h(read)g(a)g(v)-5 b(ariet)m(y)40 b(of)e(di\013eren)m(t)g(input)120 857 y(\014le)31 b(formats)g(and)g(is) g(not)g(restricted)h(to)g(only)f(reading)g(FITS)g(format)g(\014les)g (from)g(magnetic)h(disk.)43 b(The)120 970 y(follo)m(wing)32 b(t)m(yp)s(es)e(of)h(input)e(\014les)i(are)f(all)i(supp)s(orted:)256 1183 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(compressed)g(with)g Fc(zip,)47 b(gzip)29 b Ff(or)i Fc(compress)347 1333 y Ff(If)36 b(CFITSIO)f(cannot)i(\014nd)e(the)i(sp)s(eci\014ed)f(\014le)g (to)h(op)s(en)f(it)h(will)g(automatically)i(lo)s(ok)e(for)f(a)h(\014le) 347 1446 y(with)k(the)f(same)h(ro)s(otname)h(but)d(with)i(a)g Fc(.gz,)46 b(.zip)p Ff(,)d(or)d Fc(.Z)g Ff(extension.)72 b(If)41 b(it)g(\014nds)e(suc)m(h)h(a)347 1559 y(compressed)d(\014le,)h (it)g(will)f(allo)s(cate)i(a)e(blo)s(c)m(k)g(of)g(memory)g(and)f (uncompress)f(the)i(\014le)g(in)m(to)h(that)347 1672 y(memory)25 b(space.)39 b(The)25 b(application)h(program)e(will)i(then) e(transparen)m(tly)h(op)s(en)f(this)h(virtual)g(FITS)347 1785 y(\014le)36 b(in)f(memory)-8 b(.)56 b(Compressed)35 b(\014les)g(can)h(only)g(b)s(e)e(op)s(ened)h(with)g('readonly',)j(not)e ('readwrite')347 1898 y(\014le)31 b(access.)256 2085 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(on)g(the)h(in)m(ternet,)g(using)f Fc(ftp)g Ff(or)g Fc(http)f Ff(URLs)347 2236 y(Simply)22 b(pro)m(vide)h(the)h(full)e(URL)h(as)g(the)g(name)g(of)h(the)f(\014le)g (that)g(y)m(ou)h(w)m(an)m(t)f(to)h(op)s(en.)38 b(F)-8 b(or)23 b(example,)347 2348 y Fc(ftp://legacy.gsfc.nasa.go)o(v/so)o (ftwa)o(re/)o(fits)o(io/c)o(/te)o(stpr)o(og.s)o(td)347 2461 y Ff(will)37 b(op)s(en)e(the)h(CFITSIO)e(test)j(FITS)e(\014le)h (that)h(is)e(lo)s(cated)j(on)d(the)h Fc(legacy)f Ff(mac)m(hine.)58 b(These)347 2574 y(\014les)31 b(can)f(only)h(b)s(e)e(op)s(ened)h(with)g ('readonly')h(\014le)g(access.)256 2762 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(on)g Fc(stdin)f Ff(or)i Fc(stdout)d Ff(\014le)j(streams)347 2912 y(If)j(the)g(name)h(of)f(the)h(\014le)f (to)h(b)s(e)f(op)s(ened)f(is)h Fc('stdin')f Ff(or)h Fc('-')f Ff(\(a)i(single)g(dash)e(c)m(haracter\))k(then)347 3025 y(CFITSIO)f(will)i(read)g(the)f(\014le)h(from)f(the)h(standard)f(input) f(stream.)63 b(Similarly)-8 b(,)40 b(if)e(the)g(output)347 3138 y(\014le)43 b(name)g(is)g Fc('stdout')e Ff(or)i Fc('-')p Ff(,)j(then)c(the)i(\014le)f(will)g(b)s(e)g(written)g(to)g (the)h(standard)e(output)347 3251 y(stream.)54 b(In)34 b(addition,)i(if)e(the)h(output)f(\014lename)h(is)g Fc('stdout.gz')c Ff(or)k Fc('-.gz')e Ff(then)h(it)h(will)g(b)s(e)347 3364 y(gzip)f(compressed)f(b)s(efore)g(b)s(eing)f(written)h(to)h(stdout.)49 b(This)33 b(mec)m(hanism)g(can)h(b)s(e)e(used)g(to)i(pip)s(e)347 3477 y(FITS)c(\014les)g(from)g(one)h(task)g(to)g(another)f(without)h (ha)m(ving)g(to)g(write)f(an)h(in)m(termediary)g(FITS)e(\014le)347 3590 y(on)i(magnetic)g(disk.)256 3777 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(that)h(exist)g(only)g(in)f(memory)-8 b(,)31 b(or)f(shared)g(memory)-8 b(.)347 3928 y(In)38 b(some)i(applications,)i(suc)m(h)d(as)g(real)g(time)h(data)f (acquisition,)k(y)m(ou)c(ma)m(y)h(w)m(an)m(t)f(to)h(ha)m(v)m(e)g(one) 347 4040 y(pro)s(cess)31 b(write)g(a)h(FITS)e(\014le)h(in)m(to)h(a)g (certain)g(section)g(of)f(computer)g(memory)-8 b(,)32 b(and)f(then)f(b)s(e)h(able)347 4153 y(to)26 b(op)s(en)f(that)g(\014le) g(in)g(memory)g(with)g(another)g(pro)s(cess.)39 b(There)25 b(is)g(a)g(sp)s(ecialized)h(CFITSIO)e(op)s(en)347 4266 y(routine)f(called)i Fc(fits)p 1102 4266 V 33 w(open)p 1327 4266 V 33 w(memfile)d Ff(that)h(can)h(b)s(e)e(used)h(for)g(this)g (purp)s(ose.)37 b(See)23 b(the)g(\\CFITSIO)347 4379 y(User's)31 b(Reference)g(Guide")g(for)f(more)g(details.)256 4567 y Fa(\017)46 b Ff(IRAF)31 b(format)g(images)g(\(with)f Fc(.imh)g Ff(\014le)g(extensions\))347 4717 y(CFITSIO)38 b(supp)s(orts)g(reading)i(IRAF)g(format)g(images)h(b)m(y)f(con)m(v)m (erting)h(them)f(on)f(the)h(\015y)f(in)m(to)347 4830 y(FITS)27 b(images)i(in)e(memory)-8 b(.)40 b(The)28 b(application)g (program)g(then)f(reads)h(this)f(virtual)h(FITS)f(format)347 4943 y(image)36 b(in)f(memory)-8 b(.)55 b(There)34 b(is)h(curren)m(tly) g(no)g(supp)s(ort)e(for)i(writing)g(IRAF)g(format)g(images,)i(or)347 5056 y(for)30 b(reading)h(or)f(writing)h(IRAF)f(tables.)256 5243 y Fa(\017)46 b Ff(Image)31 b(arra)m(ys)g(in)f(ra)m(w)h(binary)e (format)347 5394 y(If)23 b(the)h(input)e(\014le)i(is)f(a)h(ra)m(w)f (binary)g(data)h(arra)m(y)-8 b(,)26 b(then)d(CFITSIO)f(will)h(con)m(v)m (ert)i(it)f(on)f(the)h(\015y)f(in)m(to)h(a)347 5507 y(virtual)g(FITS)e (image)j(with)e(the)h(basic)f(set)h(of)g(required)e(header)h(k)m(eyw)m (ords)h(b)s(efore)f(it)h(is)f(op)s(ened)f(b)m(y)1905 5809 y(24)p eop end %%Page: 25 25 TeXDict begin 25 24 bop 347 573 a Ff(the)31 b(application)g(program.)40 b(In)30 b(this)g(case)h(the)f(data)h(t)m(yp)s(e)g(and)e(dimensions)g (of)i(the)f(image)h(m)m(ust)347 686 y(b)s(e)c(sp)s(eci\014ed)f(in)h (square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014lename)h(\(e.g.)41 b Fc(rawfile.dat[ib512,512])p Ff(\).)347 799 y(The)30 b(\014rst)g(c)m(haracter)i(inside)e(the)g(brac)m(k)m(ets)i(de\014nes)e (the)g(datat)m(yp)s(e)i(of)e(the)h(arra)m(y:)586 1049 y Fc(b)429 b(8-bit)47 b(unsigned)e(byte)586 1161 y(i)381 b(16-bit)47 b(signed)f(integer)586 1274 y(u)381 b(16-bit)47 b(unsigned)e(integer)586 1387 y(j)381 b(32-bit)47 b(signed)f(integer) 586 1500 y(r)h(or)h(f)142 b(32-bit)47 b(floating)e(point)586 1613 y(d)381 b(64-bit)47 b(floating)e(point)347 1863 y Ff(An)32 b(optional)g(second)g(c)m(haracter)h(sp)s(eci\014es)e(the)h (b)m(yte)h(order)e(of)g(the)h(arra)m(y)g(v)-5 b(alues:)44 b(b)31 b(or)h(B)g(indi-)347 1976 y(cates)27 b(big)e(endian)f(\(as)i(in) f(FITS)f(\014les)h(and)f(the)i(nativ)m(e)g(format)f(of)h(SUN)e(UNIX)i (w)m(orkstations)g(and)347 2089 y(Mac)35 b(PCs\))d(and)h(l)g(or)g(L)g (indicates)h(little)h(endian)e(\(nativ)m(e)i(format)e(of)g(DEC)h(OSF)e (w)m(orkstations)347 2202 y(and)41 b(IBM)g(PCs\).)73 b(If)41 b(this)g(c)m(haracter)h(is)g(omitted)g(then)e(the)i(arra)m(y)f (is)h(assumed)e(to)i(ha)m(v)m(e)g(the)347 2315 y(nativ)m(e)30 b(b)m(yte)f(order)e(of)h(the)h(lo)s(cal)g(mac)m(hine.)41 b(These)28 b(datat)m(yp)s(e)h(c)m(haracters)g(are)g(then)f(follo)m(w)m (ed)h(b)m(y)347 2428 y(a)d(series)g(of)f(one)h(or)f(more)h(in)m(teger)g (v)-5 b(alues)26 b(separated)g(b)m(y)f(commas)h(whic)m(h)f(de\014ne)g (the)g(size)i(of)e(eac)m(h)347 2540 y(dimension)30 b(of)h(the)f(ra)m(w) h(arra)m(y)-8 b(.)41 b(Arra)m(ys)31 b(with)f(up)f(to)i(5)g(dimensions)f (are)g(curren)m(tly)h(supp)s(orted.)347 2691 y(Finally)-8 b(,)35 b(a)e(b)m(yte)g(o\013set)g(to)g(the)g(p)s(osition)f(of)g(the)h (\014rst)f(pixel)g(in)g(the)h(data)g(\014le)f(ma)m(y)h(b)s(e)f(sp)s (eci\014ed)347 2804 y(b)m(y)c(separating)h(it)g(with)e(a)i(':')40 b(from)27 b(the)i(last)f(dimension)g(v)-5 b(alue.)40 b(If)28 b(omitted,)i(it)e(is)g(assumed)g(that)347 2917 y(the)h(o\013set)g(=)f(0.)41 b(This)27 b(parameter)i(ma)m(y)g(b)s(e)f (used)f(to)i(skip)f(o)m(v)m(er)i(an)m(y)e(header)g(information)h(in)f (the)347 3029 y(\014le)j(that)g(precedes)f(the)h(binary)e(data.)42 b(F)-8 b(urther)30 b(examples:)443 3279 y Fc(raw.dat[b10000])473 b(1-dimensional)44 b(10000)i(pixel)h(byte)f(array)443 3392 y(raw.dat[rb400,400,12])185 b(3-dimensional)44 b(floating)i(point) g(big-endian)f(array)443 3505 y(img.fits[ib512,512:2880)o(])d(reads)k (the)h(512)g(x)h(512)e(short)h(integer)f(array)g(in)h(a)1636 3618 y(FITS)g(file,)f(skipping)f(over)i(the)g(2880)g(byte)f(header)1905 5809 y Ff(25)p eop end %%Page: 26 26 TeXDict begin 26 25 bop 120 573 a Fb(5.3)112 b(Image)38 b(Filtering)120 744 y Fg(5.3.1)105 b(Extracting)35 b(a)g(subsection)h (of)f(an)g(image)120 916 y Ff(When)21 b(sp)s(ecifying)g(the)h(name)f (of)g(an)g(image)i(to)f(b)s(e)f(op)s(ened,)h(y)m(ou)g(can)f(select)i(a) f(rectangular)g(subsection)f(of)120 1029 y(the)29 b(image)g(to)g(b)s(e) f(extracted)i(and)e(op)s(ened)f(b)m(y)i(the)f(application)i(program.)40 b(The)28 b(application)i(program)120 1142 y(then)h(op)s(ens)f(a)i (virtual)g(image)g(that)g(only)f(con)m(tains)i(the)e(pixels)h(within)e (the)i(sp)s(eci\014ed)e(subsection.)44 b(T)-8 b(o)120 1255 y(do)33 b(this,)h(sp)s(ecify)f(the)h(the)f(range)h(of)f(pixels)g (\(start:end\))i(along)f(eac)m(h)g(axis)g(to)g(b)s(e)f(extracted)h (from)f(the)120 1368 y(original)e(image)h(enclosed)f(in)f(square)g (brac)m(k)m(ets.)42 b(Y)-8 b(ou)31 b(can)f(also)i(sp)s(ecify)e(an)g (optional)h(pixel)g(incremen)m(t)120 1481 y(\(start:end:step\))37 b(for)f(eac)m(h)g(axis)h(of)e(the)h(input)f(image.)58 b(A)36 b(pixel)g(step)g(=)f(1)h(will)g(b)s(e)f(assumed)g(if)h(it)g(is) 120 1594 y(not)29 b(sp)s(eci\014ed.)39 b(If)28 b(the)h(starting)g (pixel)g(is)f(larger)i(then)e(the)h(end)e(pixel,)j(then)e(the)h(image)h (will)e(b)s(e)g(\015ipp)s(ed)120 1706 y(\(pro)s(ducing)34 b(a)h(mirror)e(image\))j(along)g(that)f(dimension.)53 b(An)34 b(asterisk,)j('*',)g(ma)m(y)e(b)s(e)f(used)f(to)j(sp)s(ecify) 120 1819 y(the)25 b(en)m(tire)h(range)f(of)g(an)g(axis,)i(and)d('-*')i (will)g(\015ip)e(the)h(en)m(tire)h(axis.)39 b(In)24 b(the)h(follo)m (wing)i(examples,)g(assume)120 1932 y(that)k Fc(myfile.fits)c Ff(con)m(tains)32 b(a)f(512)g(x)g(512)g(pixel)g(2D)g(image.)215 2130 y Fc(myfile.fits[201:210,)43 b(251:260])i(-)j(opens)e(a)i(10)f(x)g (10)g(pixel)g(subimage.)215 2356 y(myfile.fits[*,)d(512:257])i(-)h (opens)g(a)g(512)g(x)h(256)e(image)h(consisting)e(of)406 2469 y(all)i(the)g(columns)f(in)h(the)g(input)f(image,)h(but)f(only)h (rows)g(257)406 2582 y(through)f(512.)95 b(The)46 b(image)h(will)f(be)i (flipped)d(along)i(the)g(Y)g(axis)406 2695 y(since)g(the)g(starting)e (row)i(is)g(greater)f(than)h(the)g(ending)406 2808 y(row.)215 3033 y(myfile.fits[*:2,)d(512:257:2])h(-)i(creates)f(a)i(256)e(x)i(128) f(pixel)f(image.)406 3146 y(Similar)g(to)h(the)g(previous)f(example,)f (but)i(only)g(every)f(other)h(row)406 3259 y(and)g(column)f(is)i(read)e (from)h(the)g(input)f(image.)215 3485 y(myfile.fits[-*,)e(*])j(-)h (creates)e(an)h(image)f(containing)f(all)i(the)g(rows)g(and)406 3598 y(columns)f(in)h(the)g(input)g(image,)f(but)h(flips)f(it)h(along)g (the)f(X)406 3711 y(axis.)261 3909 y Ff(If)33 b(the)g(arra)m(y)h(to)g (b)s(e)f(op)s(ened)f(is)i(in)f(an)g(Image)h(extension,)h(and)e(not)g (in)g(the)h(primary)e(arra)m(y)i(of)f(the)120 4022 y(\014le,)d(then)f (y)m(ou)g(need)g(to)h(sp)s(ecify)e(the)i(extension)g(name)f(or)g(n)m (um)m(b)s(er)f(in)g(square)h(brac)m(k)m(ets)i(b)s(efore)e(giving)120 4135 y(the)h(subsection)f(range,)h(as)g(in)f Fc(myfile.fits[1][-*,)42 b(*])29 b Ff(to)h(read)f(the)h(image)h(in)e(the)g(\014rst)g(extension) 120 4248 y(in)h(the)h(\014le.)120 4485 y Fg(5.3.2)105 b(Create)34 b(an)h(Image)g(b)m(y)g(Binning)h(T)-9 b(able)34 b(Columns)120 4657 y Ff(Y)-8 b(ou)40 b(can)f(also)h(create)h(and)d(op)s (en)h(a)g(virtual)h(image)g(b)m(y)f(binning)f(the)i(v)-5 b(alues)39 b(in)g(a)g(pair)g(of)h(columns)120 4770 y(of)f(a)h(FITS)f (table)h(\(in)f(other)h(w)m(ords,)h(create)g(a)e(2-D)i(histogram)f(of)f (the)g(v)-5 b(alues)40 b(in)f(the)g(2)h(columns\).)120 4883 y(This)34 b(tec)m(hnique)h(is)g(often)g(used)f(in)h(X-ra)m(y)h (astronom)m(y)f(where)f(eac)m(h)i(detected)g(X-ra)m(y)g(photon)f (during)120 4996 y(an)29 b(observ)-5 b(ation)29 b(is)g(recorded)g(in)f (a)h(FITS)f(table.)41 b(There)29 b(are)g(t)m(ypically)h(2)g(columns)e (in)g(the)h(table)h(called)120 5109 y Fc(X)35 b Ff(and)h Fc(Y)f Ff(whic)m(h)h(record)f(the)i(pixel)f(lo)s(cation)h(of)f(that)h (ev)m(en)m(t)g(in)e(a)i(virtual)f(2D)g(image.)59 b(T)-8 b(o)36 b(create)h(an)120 5222 y(image)28 b(from)e(this)h(table,)i(one)e (just)f(scans)h(the)g(X)g(and)f(Y)h(columns)g(and)f(coun)m(ts)h(up)f (ho)m(w)h(man)m(y)g(photons)120 5334 y(w)m(ere)k(recorded)g(in)g(eac)m (h)h(pixel)f(of)g(the)g(image.)44 b(When)30 b(table)i(binning)e(is)h (sp)s(eci\014ed,)g(CFITSIO)e(creates)120 5447 y(a)38 b(temp)s(orary)e(FITS)h(primary)f(arra)m(y)i(in)f(memory)g(b)m(y)g (computing)h(the)f(histogram)h(of)g(the)f(v)-5 b(alues)38 b(in)120 5560 y(the)29 b(sp)s(eci\014ed)f(columns.)40 b(After)29 b(the)g(histogram)g(is)g(computed)g(the)g(original)h(FITS)e (\014le)h(con)m(taining)h(the)1905 5809 y(26)p eop end %%Page: 27 27 TeXDict begin 27 26 bop 120 573 a Ff(table)25 b(is)e(closed)i(and)e (the)g(temp)s(orary)h(FITS)e(primary)h(arra)m(y)h(is)g(op)s(ened)f(and) g(passed)g(to)h(the)g(application)120 686 y(program.)39 b(Th)m(us,)27 b(the)g(application)h(program)f(nev)m(er)g(sees)h(the)f (original)h(FITS)e(table)i(and)e(only)h(sees)g(the)120 799 y(image)32 b(in)e(the)g(new)g(temp)s(orary)g(\014le)h(\(whic)m(h)f (has)g(no)g(extensions\).)261 912 y(The)f(table)h(binning)e(sp)s (eci\014er)h(is)h(enclosed)g(in)f(square)g(brac)m(k)m(ets)h(follo)m (wing)h(the)f(ro)s(ot)f(\014lename)h(and)120 1024 y(table)h(extension)g (name)g(or)f(n)m(um)m(b)s(er)f(and)h(b)s(egins)g(with)g(the)g(k)m(eyw)m (ord)h('bin',)g(as)f(in:)120 1137 y Fc('myfile.fits[events][bin)41 b(\(X,Y\)]')p Ff(.)20 b(In)h(this)h(case,)j(the)d(X)g(and)f(Y)h (columns)g(in)g(the)g('ev)m(en)m(ts')h(table)120 1250 y(extension)30 b(are)g(binned)f(up)f(to)j(create)g(the)f(image.)42 b(The)29 b(size)h(of)g(the)g(image)h(is)f(usually)f(determined)g(b)m(y) 120 1363 y(the)22 b Fc(TLMINn)d Ff(and)i Fc(TLMAXn)f Ff(header)h(k)m(eyw)m(ords)h(whic)m(h)f(giv)m(e)i(the)e(minim)m(um)g (and)g(maxim)m(um)g(allo)m(w)m(ed)i(pixel)120 1476 y(v)-5 b(alues)38 b(in)f(the)h(columns.)62 b(F)-8 b(or)38 b(instance)g(if)g Fc(TLMINn)46 b(=)h(1)37 b Ff(and)g Fc(TLMAXn)46 b(=)i(4096)36 b Ff(for)i(b)s(oth)e(columns,)120 1589 y(this)f(w)m(ould)g(generate)h (a)f(4096)i(x)e(4096)h(pixel)g(image)g(b)m(y)f(default.)54 b(This)34 b(is)h(rather)g(large,)j(so)d(y)m(ou)g(can)120 1702 y(also)e(sp)s(ecify)f(a)h(pixel)f(binning)f(factor)j(to)f(reduce)f (the)g(image)i(size.)47 b(F)-8 b(or)33 b(example)g(sp)s(ecifying)f(,)h Fc('[bin)120 1815 y(\(X,Y\))46 b(=)i(16]')29 b Ff(will)h(use)f(a)i (binning)d(factor)j(of)f(16,)h(whic)m(h)f(will)g(pro)s(duce)f(a)h(256)h (x)f(256)h(pixel)g(image)g(in)120 1928 y(the)g(previous)e(example.)261 2041 y(If)35 b(the)g(TLMIN)g(and)g(TLMAX)g(k)m(eyw)m(ords)g(don't)g (exist,)j(or)d(y)m(ou)g(w)m(an)m(t)h(to)g(o)m(v)m(erride)h(their)e(v)-5 b(alues,)120 2154 y(y)m(ou)36 b(can)h(sp)s(ecify)e(the)h(image)i(range) e(and)f(binning)g(factor)i(directly)-8 b(,)39 b(as)d(in)g Fc('[bin)46 b(X)i(=)f(1:4096:16,)120 2267 y(Y=1:4096:16]')p Ff(.)36 b(Y)-8 b(ou)28 b(can)g(also)g(sp)s(ecify)f(the)h(datat)m(yp)s (e)g(of)g(the)g(created)g(image)h(b)m(y)e(app)s(ending)f(a)i(b,)g(i,) 120 2379 y(j,)f(r,)g(or)f(d)f(\(for)h(8-bit)h(b)m(yte,)h(16-bit)g(in)m (tegers,)g(32-bit)f(in)m(teger,)i(32-bit)e(\015oating)g(p)s(oin)m(ts,)g (or)f(64-bit)i(double)120 2492 y(precision)36 b(\015oating)g(p)s(oin)m (t,)h(resp)s(ectiv)m(ely\))g(to)f(the)g('bin')f(k)m(eyw)m(ord)g(\(e.g.) 58 b Fc('[binr)46 b(\(X,Y\)]')33 b Ff(creates)k(a)120 2605 y(\015oating)j(p)s(oin)m(t)e(image\).)67 b(If)38 b(the)h(datat)m(yp)s(e)h(is)e(not)h(sp)s(eci\014ed)f(then)g(a)h(32-bit) h(in)m(teger)g(image)g(will)f(b)s(e)120 2718 y(created)31 b(b)m(y)g(default.)261 2831 y(If)39 b(the)h(column)f(name)g(is)h(not)f (sp)s(eci\014ed,)i(then)e(CFITSIO)f(will)i(\014rst)e(try)i(to)g(use)f (the)g('preferred)120 2944 y(column')c(as)g(sp)s(eci\014ed)f(b)m(y)h (the)g(CPREF)g(k)m(eyw)m(ord)g(if)g(it)h(exists)f(\(e.g.,)j('CPREF)d(=) g('DETX,DETY'\),)120 3057 y(otherwise)c(column)f(names)g('X',)i('Y')e (will)h(b)s(e)f(assumed)g(for)g(the)g(2)h(axes.)261 3170 y(Note)37 b(that)f(this)f(binning)f(sp)s(eci\014er)h(is)g(not)g (restricted)h(to)g(only)g(2D)g(images)g(and)f(can)g(b)s(e)g(used)g(to) 120 3283 y(create)f(1D,)f(3D,)g(or)g(4D)g(images)g(as)f(w)m(ell.)48 b(It)32 b(is)g(also)h(p)s(ossible)f(to)h(sp)s(ecify)f(a)g(w)m(eigh)m (ting)i(factor)g(that)e(is)120 3396 y(applied)d(during)g(the)g (binning.)40 b(Please)30 b(refer)g(to)g(the)g(\\CFITSIO)e(User's)i (Reference)g(Guide")g(for)f(more)120 3509 y(details)i(on)g(these)f(adv) -5 b(anced)31 b(features.)1905 5809 y(27)p eop end %%Page: 28 28 TeXDict begin 28 27 bop 120 573 a Fb(5.4)112 b(T)-9 b(able)38 b(Filtering)120 744 y Fg(5.4.1)105 b(Column)35 b(and)g(Keyw)m(ord)g (Filtering)120 916 y Ff(The)29 b(column)g(or)g(k)m(eyw)m(ord)h (\014ltering)g(sp)s(eci\014er)f(is)g(used)g(to)h(mo)s(dify)e(the)i (column)f(structure)g(and/or)g(the)120 1029 y(header)h(k)m(eyw)m(ords)h (in)f(the)h(HDU)g(that)g(w)m(as)g(selected)h(with)e(the)h(previous)f (HDU)h(lo)s(cation)h(sp)s(eci\014er.)40 b(It)120 1142 y(can)31 b(b)s(e)e(used)h(to)h(p)s(erform)e(the)i(follo)m(wing)g(t)m (yp)s(es)g(of)f(op)s(erations.)256 1354 y Fa(\017)46 b Ff(App)s(end)35 b(a)h(new)g(column)g(to)h(a)f(table)h(b)m(y)g(giving) g(the)f(column)g(name,)i(optionally)g(follo)m(w)m(ed)f(b)m(y)347 1467 y(the)c(datat)m(yp)s(e)h(in)e(paren)m(theses,)i(follo)m(w)m(ed)g (b)m(y)f(an)g(equals)g(sign)g(and)f(the)h(arithmetic)h(expression)347 1580 y(to)c(b)s(e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue.)41 b(The)28 b(datat)m(yp)s(e)i(is)f(sp)s(eci\014ed)f(using)h (the)g(same)g(syn)m(tax)h(that)347 1693 y(is)k(allo)m(w)m(ed)h(for)e (the)g(v)-5 b(alue)34 b(of)g(the)f(FITS)g(TF)m(ORMn)g(k)m(eyw)m(ord)h (\(e.g.,)i('I',)e('J',)g('E',)f('D',)i(etc.)51 b(for)347 1806 y(binary)32 b(tables,)h(and)f('I8',)h(F12.3',)i('E20.12',)g(etc.) 47 b(for)32 b(ASCI)s(I)f(tables\).)47 b(If)32 b(the)g(datat)m(yp)s(e)h (is)f(not)347 1919 y(sp)s(eci\014ed)e(then)g(a)h(default)f(datat)m(yp)s (e)i(will)e(b)s(e)g(c)m(hosen)h(dep)s(ending)e(on)h(the)h(expression.) 256 2107 y Fa(\017)46 b Ff(Create)33 b(a)g(new)f(header)g(k)m(eyw)m (ord)h(b)m(y)f(giving)h(the)g(k)m(eyw)m(ord)g(name,)g(preceded)f(b)m(y) g(a)h(p)s(ound)d(sign)347 2220 y('#',)24 b(follo)m(w)m(ed)e(b)m(y)f(an) g(equals)g(sign)g(and)f(an)h(arithmetic)h(expression)f(for)g(the)g(v)-5 b(alue)21 b(of)g(the)h(k)m(eyw)m(ord.)347 2332 y(The)k(expression)g(ma) m(y)h(b)s(e)f(a)h(function)f(of)h(other)f(header)g(k)m(eyw)m(ord)h(v)-5 b(alues.)40 b(The)26 b(commen)m(t)h(string)347 2445 y(for)40 b(the)h(k)m(eyw)m(ord)g(ma)m(y)g(b)s(e)f(sp)s(eci\014ed)g(in)g(paren)m (theses)h(immediately)g(follo)m(wing)h(the)f(k)m(eyw)m(ord)347 2558 y(name.)256 2746 y Fa(\017)46 b Ff(Ov)m(erwrite)30 b(the)f(v)-5 b(alues)30 b(in)e(an)h(existing)i(column)d(or)i(k)m(eyw)m (ord)f(b)m(y)g(giving)h(the)g(name)f(follo)m(w)m(ed)h(b)m(y)347 2859 y(an)h(equals)f(sign)h(and)e(an)i(arithmetic)g(expression.)256 3046 y Fa(\017)46 b Ff(Select)36 b(a)e(set)g(of)h(columns)e(to)i(b)s(e) e(included)h(in)f(the)i(\014ltered)f(\014le)g(b)m(y)g(listing)g(the)h (column)e(names)347 3159 y(separated)c(with)f(semi-colons.)41 b(Wild)29 b(card)f(c)m(haracters)i(ma)m(y)e(b)s(e)g(used)f(in)h(the)h (column)f(names)g(to)347 3272 y(matc)m(h)33 b(m)m(ultiple)g(columns.)46 b(An)m(y)32 b(other)h(columns)e(in)h(the)h(input)e(table)i(will)f(not)h (app)s(ear)e(in)h(the)347 3385 y(\014ltered)f(\014le.)256 3573 y Fa(\017)46 b Ff(Delete)32 b(a)e(column)g(or)f(k)m(eyw)m(ord)h(b) m(y)g(listing)g(the)g(name)g(preceded)f(b)m(y)h(a)g(min)m(us)f(sign)g (or)h(an)g(excla-)347 3686 y(mation)h(mark)f(\(!\))256 3873 y Fa(\017)46 b Ff(Rename)31 b(an)f(existing)i(column)e(or)g(k)m (eyw)m(ord)h(with)f(the)h(syn)m(tax)g('NewName)g(==)f(OldName'.)261 4086 y(The)20 b(column)g(\014ltering)h(sp)s(eci\014er)e(is)i(enclosed)g (in)f(square)g(brac)m(k)m(ets)h(and)f(b)s(egins)g(with)g(the)g(string)h ('col'.)120 4199 y(Multiple)32 b(op)s(erations)f(can)g(b)s(e)f(p)s (erformed)f(b)m(y)i(separating)g(them)g(with)f(semi-colons.)43 b(F)-8 b(or)32 b(complex)f(or)120 4312 y(commonly)g(used)g(op)s (erations,)g(y)m(ou)h(can)f(write)g(the)g(column)g(\014lter)g(to)h(a)f (text)h(\014le,)f(and)g(then)f(use)h(it)g(b)m(y)120 4425 y(giving)g(the)g(name)f(of)h(the)f(text)i(\014le,)e(preceded)g(b)m(y)h (a)f('@')h(c)m(haracter.)261 4538 y(Some)g(examples:)215 4750 y Fc([col)47 b(PI=PHA)f(*)i(1.1)f(+)g(0.2])285 b(-)48 b(creates)e(new)g(PI)i(column)e(from)g(PHA)h(values)215 4976 y([col)g(rate)g(=)g(counts/exposure])91 b(-)48 b(creates)e(or)h (overwrites)e(the)i(rate)f(column)g(by)1743 5089 y(dividing)f(the)i (counts)f(column)g(by)i(the)1743 5202 y(EXPOSURE)d(keyword)h(value.)215 5428 y([col)h(TIME;)f(X;)i(Y])667 b(-)48 b(only)e(the)h(listed)f (columns)g(will)h(appear)1743 5540 y(in)g(the)g(filtered)e(file)1905 5809 y Ff(28)p eop end %%Page: 29 29 TeXDict begin 29 28 bop 215 686 a Fc([col)47 b(Time;*raw])713 b(-)48 b(include)e(the)g(Time)h(column)f(and)h(any)g(other)1743 799 y(columns)f(whose)g(name)h(ends)f(with)h('raw'.)215 1024 y([col)g(-TIME;)f(Good)h(==)g(STATUS])141 b(-)48 b(deletes)e(the)g(TIME)h(column)f(and)1743 1137 y(renames)g(the)g (STATUS)h(column)f(to)h(GOOD)215 1363 y([col)g(@colfilt.txt])569 b(-)48 b(uses)e(the)h(filtering)f(expression)f(in)1743 1476 y(the)i(colfilt.txt)d(text)j(file)261 1689 y Ff(The)30 b(original)i(\014le)f(is)g(not)g(c)m(hanged)g(b)m(y)g(this)g (\014ltering)g(op)s(eration,)g(and)f(instead)h(the)g(mo)s (di\014cations)120 1802 y(are)36 b(made)f(on)h(a)f(temp)s(orary)h(cop)m (y)g(of)f(the)h(input)e(FITS)h(\014le)h(\(usually)f(in)g(memory\),)j (whic)m(h)d(includes)120 1914 y(a)42 b(cop)m(y)g(of)g(all)g(the)g (other)g(HDUs)g(in)f(the)h(input)f(\014le.)74 b(The)41 b(original)i(input)e(\014le)g(is)h(closed)g(and)f(the)120 2027 y(application)32 b(program)e(op)s(ens)f(the)i(\014ltered)f(cop)m (y)h(of)g(the)g(\014le.)120 2268 y Fg(5.4.2)105 b(Ro)m(w)36 b(Filtering)120 2439 y Ff(The)22 b(ro)m(w)h(\014lter)g(is)g(used)f(to)h (select)h(a)g(subset)e(of)h(the)g(ro)m(ws)f(from)h(a)g(table)g(based)g (on)f(a)i(b)s(o)s(olean)e(expression.)120 2552 y(A)37 b(temp)s(orary)g(new)f(FITS)g(\014le)i(is)f(created)h(on)f(the)g(\015y) f(\(usually)h(in)g(memory\))g(whic)m(h)g(con)m(tains)h(only)120 2665 y(those)30 b(ro)m(ws)g(for)g(whic)m(h)g(the)g(ro)m(w)g(\014lter)g (expression)f(ev)-5 b(aluates)32 b(to)e(true)g(\(i.e.,)i(not)e(equal)g (to)h(zero\).)42 b(The)120 2778 y(primary)25 b(arra)m(y)i(and)e(an)m(y) h(other)h(extensions)f(in)g(the)g(input)f(\014le)h(are)h(also)g(copied) f(to)h(the)f(temp)s(orary)g(\014le.)120 2891 y(The)h(original)i(FITS)e (\014le)h(is)g(closed)g(and)g(the)g(new)f(temp)s(orary)g(\014le)h(is)g (then)f(op)s(ened)g(b)m(y)h(the)g(application)120 3004 y(program.)261 3117 y(The)f(ro)m(w)g(\014lter)g(expression)g(is)g (enclosed)g(in)g(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014le) g(name)g(and)f(exten-)120 3230 y(sion)32 b(name.)48 b(F)-8 b(or)33 b(example,)h Fc('file.fits[events][GRAD)o(E==5)o(0]')26 b Ff(selects)34 b(only)f(those)g(ro)m(ws)f(in)g(the)120 3342 y(EVENTS)e(table)h(where)f(the)g(GRADE)h(column)g(v)-5 b(alue)30 b(is)h(equal)g(to)g(50\).)261 3455 y(The)d(ro)m(w)h (\014ltering)f(expression)h(can)f(b)s(e)g(an)h(arbitrarily)f(complex)i (series)e(of)h(op)s(erations)g(p)s(erformed)120 3568 y(on)d(constan)m(ts,)i(k)m(eyw)m(ord)e(v)-5 b(alues,)27 b(and)e(column)h(data)g(tak)m(en)h(from)e(the)h(sp)s(eci\014ed)f(FITS)g (T)-8 b(ABLE)26 b(exten-)120 3681 y(sion.)40 b(The)27 b(expression)g(also)i(can)e(b)s(e)g(written)h(in)m(to)h(a)e(text)i (\014le)f(and)f(then)g(used)g(b)m(y)g(giving)h(the)g(\014lename)120 3794 y(preceded)i(b)m(y)g(a)h('@')g(c)m(haracter,)h(as)e(in)g Fc('[@rowfilt.txt]')p Ff(.)261 3907 y(Keyw)m(ord)40 b(and)f(column)h (data)g(are)h(referenced)f(b)m(y)f(name.)70 b(An)m(y)40 b(string)g(of)g(c)m(haracters)h(not)f(sur-)120 4020 y(rounded)30 b(b)m(y)i(quotes)g(\(ie,)h(a)g(constan)m(t)g(string\))f(or)f(follo)m(w) m(ed)j(b)m(y)d(an)h(op)s(en)f(paren)m(theses)h(\(ie,)i(a)e(function)120 4133 y(name\))e(will)f(b)s(e)g(initially)h(in)m(terpreted)g(as)f(a)h (column)f(name)g(and)g(its)h(con)m(ten)m(ts)h(for)e(the)g(curren)m(t)g (ro)m(w)g(in-)120 4246 y(serted)e(in)m(to)h(the)g(expression.)39 b(If)27 b(no)g(suc)m(h)g(column)g(exists,)i(a)e(k)m(eyw)m(ord)h(of)g (that)f(name)h(will)f(b)s(e)g(searc)m(hed)120 4359 y(for)34 b(and)f(its)h(v)-5 b(alue)35 b(used,)f(if)g(found.)50 b(T)-8 b(o)35 b(force)f(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)h (a)f(k)m(eyw)m(ord)g(\(in)g(case)120 4472 y(there)28 b(is)g(b)s(oth)f(a)h(column)g(and)f(k)m(eyw)m(ord)h(with)g(the)g(same)g (name\),)h(precede)f(the)g(k)m(eyw)m(ord)h(name)e(with)h(a)120 4584 y(single)k(p)s(ound)d(sign,)j('#',)g(as)g(in)f Fc(#NAXIS2)p Ff(.)41 b(Due)32 b(to)g(the)f(generalities)j(of)d(FITS)g(column)g(and)g (k)m(eyw)m(ord)120 4697 y(names,)c(if)e(the)h(column)g(or)f(k)m(eyw)m (ord)h(name)g(con)m(tains)h(a)f(space)g(or)g(a)g(c)m(haracter)h(whic)m (h)f(migh)m(t)g(app)s(ear)f(as)120 4810 y(an)32 b(arithmetic)h(term)f (then)g(inclose)h(the)f(name)g(in)f('$')i(c)m(haracters)h(as)e(in)g Fc($MAX)46 b(PHA$)31 b Ff(or)h Fc(#$MAX-PHA$)p Ff(.)120 4923 y(The)e(names)g(are)h(case)g(insensitiv)m(e.)261 5036 y(T)-8 b(o)37 b(access)g(a)g(table)g(en)m(try)g(in)f(a)g(ro)m(w)h (other)f(than)g(the)h(curren)m(t)f(one,)i(follo)m(w)g(the)e(column's)g (name)120 5149 y(with)j(a)g(ro)m(w)g(o\013set)g(within)g(curly)f (braces.)66 b(F)-8 b(or)40 b(example,)i Fc('PHA)p Fa(f)p Fc(-3)p Fa(g)p Fc(')c Ff(will)h(ev)-5 b(aluate)40 b(to)g(the)f(v)-5 b(alue)120 5262 y(of)40 b(column)f(PHA,)h(3)g(ro)m(ws)f(ab)s(o)m(v)m(e) i(the)f(ro)m(w)g(curren)m(tly)f(b)s(eing)g(pro)s(cessed.)68 b(One)39 b(cannot)h(sp)s(ecify)f(an)120 5375 y(absolute)33 b(ro)m(w)f(n)m(um)m(b)s(er,)f(only)h(a)h(relativ)m(e)h(o\013set.)47 b(Ro)m(ws)32 b(that)h(fall)f(outside)g(the)h(table)g(will)f(b)s(e)f (treated)120 5488 y(as)g(unde\014ned,)d(or)i(NULLs.)1905 5809 y(29)p eop end %%Page: 30 30 TeXDict begin 30 29 bop 261 573 a Ff(Bo)s(olean)32 b(op)s(erators)f (can)g(b)s(e)g(used)f(in)g(the)h(expression)g(in)f(either)i(their)f(F) -8 b(ortran)31 b(or)g(C)f(forms.)42 b(The)120 686 y(follo)m(wing)32 b(b)s(o)s(olean)e(op)s(erators)h(are)g(a)m(v)-5 b(ailable:)311 886 y Fc("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)311 999 y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)311 1112 y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)311 1225 y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 b(.AND.)h(&&)311 1337 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 b(~)261 1537 y Ff(Note)34 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f (')10 b(!',)34 b(is)f(a)h(sp)s(ecial)f(UNIX)g(c)m(haracter,)j(so)d(if)g (it)g(is)g(used)f(on)h(the)120 1650 y(command)f(line)h(rather)f(than)g (en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s(e)g (preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)120 1763 y(force)e(the)g (UNIX)f(shell)h(to)g(ignore)g(it.)261 1876 y(The)c(expression)f(ma)m(y) i(also)g(include)f(arithmetic)h(op)s(erators)f(and)f(functions.)39 b(T)-8 b(rigonometric)29 b(func-)120 1989 y(tions)f(use)g(radians,)h (not)f(degrees.)40 b(The)28 b(follo)m(wing)i(arithmetic)f(op)s(erators) f(and)g(functions)f(can)i(b)s(e)e(used)120 2102 y(in)j(the)h (expression)f(\(function)g(names)g(are)h(case)h(insensitiv)m(e\):)311 2302 y Fc("addition")522 b(+)477 b("subtraction")d(-)311 2415 y("multiplication")234 b(*)477 b("division")618 b(/)311 2528 y("negation")522 b(-)477 b("exponentiation")330 b(**)143 b(^)311 2641 y("absolute)45 b(value")237 b(abs\(x\))g ("cosine")714 b(cos\(x\))311 2754 y("sine")g(sin\(x\))237 b("tangent")666 b(tan\(x\))311 2867 y("arc)47 b(cosine")427 b(arccos\(x\))93 b("arc)47 b(sine")619 b(arcsin\(x\))311 2979 y("arc)47 b(tangent")379 b(arctan\(x\))93 b("arc)47 b(tangent")475 b(arctan2\(x,y\))311 3092 y("exponential")378 b(exp\(x\))237 b("square)46 b(root")476 b(sqrt\(x\))311 3205 y("natural)45 b(log")381 b(log\(x\))237 b("common)46 b(log")524 b(log10\(x\))311 3318 y("modulus")570 b(i)48 b(\045)f(j)286 b("random)46 b(#)h([0.0,1.0\)")141 b(random\(\))311 3431 y("minimum")570 b(min\(x,y\))141 b("maximum")666 b(max\(x,y\))311 3544 y("if-then-else")330 b(b?x:y)261 3744 y Ff(The)37 b(follo)m(wing)i(t)m(yp)s(e)f(casting)g(op)s(erators)g (are)g(a)m(v)-5 b(ailable,)41 b(where)c(the)h(inclosing)g(paren)m (theses)g(are)120 3857 y(required)23 b(and)h(tak)m(en)h(from)f(the)h(C) f(language)h(usage.)40 b(Also,)26 b(the)e(in)m(teger)i(to)f(real)g (casts)g(v)-5 b(alues)25 b(to)g(double)120 3970 y(precision:)884 4170 y Fc("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 b(x)884 4283 y("integer)f(to)i(real")190 b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)261 4483 y Ff(Sev)m(eral)32 b(constan)m(ts)f(are)g(built)f(in)g(for)g(use)g(in)g (n)m(umerical)h(expressions:)502 4683 y Fc(#pi)667 b(3.1415...)284 b(#e)620 b(2.7182...)502 4796 y(#deg)f(#pi/180)380 b(#row)524 b(current)46 b(row)h(number)502 4909 y(#null)428 b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 b(string)261 5109 y Ff(A)d(string)g(constan)m(t)h(m)m(ust)f(b)s(e)f(enclosed)i(in)f (quotes)g(as)g(in)g('Crab'.)75 b(The)41 b("n)m(ull")i(constan)m(ts)g (are)120 5222 y(useful)37 b(for)g(conditionally)i(setting)g(table)f(v) -5 b(alues)38 b(to)g(a)g(NULL,)g(or)f(unde\014ned,)h(v)-5 b(alue)38 b(\(F)-8 b(or)38 b(example,)120 5334 y Fc("col1==-99)45 b(?)95 b(#NULL)47 b(:)g(col1")p Ff(\).)261 5447 y(There)33 b(is)h(also)g(a)g(function)g(for)f(testing)i(if)e(t)m(w)m(o)i(v)-5 b(alues)34 b(are)g(close)h(to)f(eac)m(h)h(other,)g(i.e.,)h(if)d(they)h (are)120 5560 y("near")29 b(eac)m(h)g(other)f(to)g(within)g(a)g(user)f (sp)s(eci\014ed)g(tolerance.)42 b(The)27 b(argumen)m(ts,)i Fc(value)p 3184 5560 29 4 v 33 w(1)e Ff(and)h Fc(value)p 3707 5560 V 33 w(2)1905 5809 y Ff(30)p eop end %%Page: 31 31 TeXDict begin 31 30 bop 120 573 a Ff(can)39 b(b)s(e)g(in)m(teger)h(or)f (real)g(and)g(represen)m(t)g(the)g(t)m(w)m(o)h(v)-5 b(alues)39 b(who's)g(pro)m(ximit)m(y)h(is)f(b)s(eing)g(tested)g(to)h(b)s(e)120 686 y(within)30 b(the)g(sp)s(eci\014ed)g(tolerance,)i(also)g(an)e(in)m (teger)i(or)e(real:)1075 880 y Fc(near\(value_1,)44 b(value_2,)h (tolerance\))261 1074 y Ff(When)30 b(a)h(NULL,)f(or)h(unde\014ned,)d(v) -5 b(alue)31 b(is)f(encoun)m(tered)h(in)f(the)g(FITS)g(table,)h(the)g (expression)f(will)120 1186 y(ev)-5 b(aluate)43 b(to)f(NULL)g(unless)e (the)i(unde\014ned)d(v)-5 b(alue)42 b(is)g(not)f(actually)i(required)e (for)g(ev)-5 b(aluation,)46 b(e.g.)120 1299 y("TR)m(UE)c(.or.)76 b(NULL")42 b(ev)-5 b(aluates)44 b(to)f(TR)m(UE.)f(The)f(follo)m(wing)j (t)m(w)m(o)f(functions)f(allo)m(w)h(some)f(NULL)120 1412 y(detection)32 b(and)e(handling:)1027 1606 y Fc(ISNULL\(x\))1027 1719 y(DEFNULL\(x,y\))261 1913 y Ff(The)43 b(former)g(returns)f(a)i(b)s (o)s(olean)f(v)-5 b(alue)44 b(of)f(TR)m(UE)h(if)f(the)h(argumen)m(t)f (x)h(is)f(NULL.)h(The)e(later)120 2026 y("de\014nes")e(a)g(v)-5 b(alue)40 b(to)g(b)s(e)g(substituted)f(for)g(NULL)h(v)-5 b(alues;)45 b(it)40 b(returns)e(the)i(v)-5 b(alue)41 b(of)e(x)h(if)g(x)f(is)h(not)120 2139 y(NULL,)31 b(otherwise)f(it)h (returns)e(the)i(v)-5 b(alue)31 b(of)f(y)-8 b(.)261 2252 y(Bit)32 b(masks)f(can)g(b)s(e)f(used)g(to)h(select)i(out)e(ro)m(ws)g (from)f(bit)h(columns)f(\()p Fc(TFORMn)47 b(=)g(#X)p Ff(\))31 b(in)f(FITS)g(\014les.)120 2365 y(T)-8 b(o)31 b(represen)m(t)f(the)h(mask,)f(binary)-8 b(,)31 b(o)s(ctal,)h(and)d (hex)i(formats)f(are)h(allo)m(w)m(ed:)931 2558 y Fc(binary:)142 b(b0110xx1010000101xxxx00)o(01)931 2671 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))931 2784 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))261 2978 y Ff(In)28 b(all)i(the)g(represen)m(tations,)g(an)f(x)g(or)g(X)g(is)g (allo)m(w)m(ed)i(in)e(the)g(mask)g(as)h(a)f(wild)g(card.)40 b(Note)30 b(that)g(the)120 3091 y(x)i(represen)m(ts)f(a)h(di\013eren)m (t)g(n)m(um)m(b)s(er)f(of)h(wild)f(card)h(bits)f(in)g(eac)m(h)i (represen)m(tation.)46 b(All)32 b(represen)m(tations)120 3204 y(are)f(case)g(insensitiv)m(e.)261 3317 y(T)-8 b(o)38 b(construct)f(the)h(b)s(o)s(olean)f(expression)g(using)g(the)g(mask)h (as)f(the)h(b)s(o)s(olean)f(equal)h(op)s(erator)f(de-)120 3430 y(scrib)s(ed)30 b(ab)s(o)m(v)m(e)h(on)g(a)g(bit)g(table)g(column.) 41 b(F)-8 b(or)32 b(example,)f(if)g(y)m(ou)g(had)f(a)h(7)g(bit)f (column)h(named)f(\015ags)h(in)120 3543 y(a)36 b(FITS)e(table)j(and)e (w)m(an)m(ted)h(all)g(ro)m(ws)f(ha)m(ving)h(the)g(bit)f(pattern)h (0010011,)k(the)35 b(selection)j(expression)120 3656 y(w)m(ould)30 b(b)s(e:)1456 3850 y Fc(flags)47 b(==)g(b0010011)311 3962 y(or)1456 4075 y(flags)g(.eq.)f(b10011)261 4269 y Ff(It)32 b(is)f(also)i(p)s(ossible)e(to)h(test)g(if)g(a)g(range)f(of) h(bits)f(is)h(less)g(than,)f(less)h(than)g(equal,)g(greater)h(than)e (and)120 4382 y(greater)h(than)e(equal)h(to)g(a)f(particular)h(b)s(o)s (olean)g(v)-5 b(alue:)1456 4576 y Fc(flags)47 b(<=)g(bxxx010xx)1456 4689 y(flags)g(.gt.)f(bxxx100xx)1456 4802 y(flags)h(.le.)f(b1xxxxxxx) 261 4996 y Ff(Notice)32 b(the)f(use)f(of)h(the)f(x)h(bit)f(v)-5 b(alue)31 b(to)g(limit)g(the)g(range)f(of)h(bits)f(b)s(eing)g (compared.)261 5109 y(It)j(is)g(not)g(necessary)g(to)g(sp)s(ecify)g (the)f(leading)i(\(most)f(signi\014can)m(t\))h(zero)g(\(0\))g(bits)e (in)h(the)g(mask,)g(as)120 5222 y(sho)m(wn)d(in)g(the)g(second)h (expression)f(ab)s(o)m(v)m(e.)261 5334 y(Bit)h(wise)f(AND,)g(OR)g(and)f (NOT)g(op)s(erations)h(are)g(also)h(p)s(ossible)e(on)g(t)m(w)m(o)i(or)f (more)g(bit)g(\014elds)f(using)120 5447 y(the)38 b('&'\(AND\),)h(')p Fa(j)p Ff('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))38 b(op)s(erators.)63 b(All)38 b(of)g(these)g(op)s(erators)g(result)f(in)g (a)h(bit)120 5560 y(\014eld)30 b(whic)m(h)g(can)h(then)f(b)s(e)g(used)f (with)h(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 b(example:)1905 5809 y(31)p eop end %%Page: 32 32 TeXDict begin 32 31 bop 1361 573 a Fc(\(!flags\))45 b(==)j(b1101100) 1361 686 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)261 887 y Ff(Bit)36 b(\014elds)e(can)g(b)s(e)g(app)s(ended)f(as)i(w)m(ell)g (using)f(the)h('+')g(op)s(erator.)53 b(Strings)34 b(can)h(b)s(e)f (concatenated)120 1000 y(this)c(w)m(a)m(y)-8 b(,)32 b(to)s(o.)120 1238 y Fg(5.4.3)105 b(Go)s(o)s(d)36 b(Time)f(In)m(terv)-6 b(al)34 b(Filtering)120 1410 y Ff(A)27 b(common)g(\014ltering)g(metho)s (d)g(in)m(v)m(olv)m(es)i(selecting)g(ro)m(ws)d(whic)m(h)h(ha)m(v)m(e)h (a)g(time)f(v)-5 b(alue)28 b(whic)m(h)e(lies)i(within)120 1523 y(what)38 b(is)f(called)i(a)f(Go)s(o)s(d)g(Time)f(In)m(terv)-5 b(al)39 b(or)e(GTI.)h(The)f(time)i(in)m(terv)-5 b(als)38 b(are)g(de\014ned)f(in)g(a)h(separate)120 1636 y(FITS)31 b(table)i(extension)f(whic)m(h)g(con)m(tains)h(2)f(columns)f(giving)i (the)f(start)g(and)f(stop)h(time)h(of)f(eac)m(h)g(go)s(o)s(d)120 1749 y(in)m(terv)-5 b(al.)61 b(The)37 b(\014ltering)g(op)s(eration)g (accepts)h(only)f(those)g(ro)m(ws)g(of)g(the)g(input)f(table)i(whic)m (h)e(ha)m(v)m(e)i(an)120 1861 y(asso)s(ciated)32 b(time)g(whic)m(h)f (falls)g(within)f(one)i(of)f(the)g(time)g(in)m(terv)-5 b(als)32 b(de\014ned)e(in)h(the)g(GTI)f(extension.)43 b(A)120 1974 y(high)29 b(lev)m(el)j(function,)e (gti\014lter\(a,b,c,d\),)j(is)c(a)m(v)-5 b(ailable)33 b(whic)m(h)c(ev)-5 b(aluates)32 b(eac)m(h)f(ro)m(w)f(of)g(the)g(input)e (table)120 2087 y(and)i(returns)g(TR)m(UE)g(or)h(F)-10 b(ALSE)30 b(dep)s(ending)g(whether)g(the)g(ro)m(w)h(is)g(inside)f(or)h (outside)g(the)g(go)s(o)s(d)g(time)120 2200 y(in)m(terv)-5 b(al.)42 b(The)30 b(syn)m(tax)h(is)406 2401 y Fc(gtifilter\()45 b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) g(\))120 2603 y Ff(where)35 b(eac)m(h)i("[]")g(demarks)e(optional)h (parameters.)57 b(Note)37 b(that)f(the)g(quotes)g(around)e(the)i (gti\014le)h(and)120 2716 y(ST)-8 b(AR)g(T/STOP)31 b(column)i(are)g (required.)46 b(Either)33 b(single)g(or)f(double)h(quote)g(c)m (haracters)h(ma)m(y)f(b)s(e)f(used.)120 2828 y(The)c(gti\014le,)i(if)e (sp)s(eci\014ed,)h(can)f(b)s(e)g(blank)g(\(""\))i(whic)m(h)e(will)h (mean)g(to)g(use)f(the)g(\014rst)g(extension)h(with)f(the)120 2941 y(name)23 b("*GTI*")i(in)e(the)g(curren)m(t)g(\014le,)i(a)e(plain) g(extension)h(sp)s(eci\014er)f(\(eg,)j("+2",)f("[2]",)i(or)c ("[STDGTI]"\))120 3054 y(whic)m(h)g(will)h(b)s(e)f(used)g(to)i(select)g (an)f(extension)g(in)f(the)h(curren)m(t)g(\014le,)h(or)f(a)g(regular)f (\014lename)h(with)g(or)f(with-)120 3167 y(out)j(an)g(extension)h(sp)s (eci\014er)e(whic)m(h)h(in)f(the)i(latter)g(case)g(will)f(mean)g(to)h (use)f(the)g(\014rst)f(extension)i(with)e(an)120 3280 y(extension)30 b(name)g("*GTI*".)42 b(Expr)28 b(can)i(b)s(e)f(an)m(y)g (arithmetic)i(expression,)f(including)f(simply)g(the)h(time)120 3393 y(column)k(name.)52 b(A)34 b(v)m(ector)i(time)f(expression)f(will) g(pro)s(duce)f(a)i(v)m(ector)g(b)s(o)s(olean)g(result.)51 b(ST)-8 b(AR)g(TCOL)120 3506 y(and)33 b(STOPCOL)f(are)j(the)f(names)g (of)g(the)g(ST)-8 b(AR)g(T/STOP)33 b(columns)h(in)f(the)i(GTI)e (extension.)53 b(If)33 b(one)120 3619 y(of)e(them)f(is)g(sp)s (eci\014ed,)g(they)h(b)s(oth)e(m)m(ust)i(b)s(e.)261 3732 y(In)37 b(its)i(simplest)f(form,)i(no)e(parameters)g(need)g(to)h(b)s(e) e(pro)m(vided)h({)g(default)h(v)-5 b(alues)38 b(will)g(b)s(e)g(used.) 120 3845 y(The)30 b(expression)g Fc("gtifilter\(\)")d Ff(is)j(equiv)-5 b(alen)m(t)32 b(to)454 4046 y Fc(gtifilter\()45 b("",)i(TIME,)f("*START*",)f("*STOP*")h(\))120 4247 y Ff(This)31 b(will)i(searc)m(h)g(the)f(curren)m(t)g(\014le)h(for)f(a)g (GTI)g(extension,)i(\014lter)e(the)g(TIME)g(column)g(in)g(the)h(curren) m(t)120 4360 y(table,)48 b(using)c(ST)-8 b(AR)g(T/STOP)43 b(times)h(tak)m(en)h(from)e(columns)h(in)g(the)g(GTI)f(extension)i (with)e(names)120 4473 y(con)m(taining)32 b(the)f(strings)f("ST)-8 b(AR)g(T")31 b(and)f("STOP".)41 b(The)30 b(wildcards)g(\('*'\))i(allo)m (w)g(sligh)m(t)f(v)-5 b(ariations)32 b(in)120 4586 y(naming)g(con)m(v)m (en)m(tions)h(suc)m(h)f(as)g("TST)-8 b(AR)g(T")32 b(or)g("ST)-8 b(AR)g(TTIME".)45 b(The)31 b(same)i(default)f(v)-5 b(alues)32 b(apply)120 4699 y(for)f(unsp)s(eci\014ed)f(parameters)i(when)e(the)i (\014rst)e(one)i(or)f(t)m(w)m(o)i(parameters)f(are)g(sp)s(eci\014ed.)43 b(The)31 b(function)120 4812 y(automatically)44 b(searc)m(hes)d(for)g (TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)g(in)f(the)h(curren)m(t)g(and)f(GTI)h (extensions,)120 4924 y(applying)30 b(a)h(relativ)m(e)h(time)g (o\013set,)f(if)g(necessary)-8 b(.)120 5163 y Fg(5.4.4)105 b(Spatial)35 b(Region)h(Filtering)120 5334 y Ff(Another)f(common)h (\014ltering)g(metho)s(d)f(selects)h(ro)m(ws)g(based)f(on)g(whether)g (the)h(spatial)g(p)s(osition)f(asso-)120 5447 y(ciated)41 b(with)f(eac)m(h)i(ro)m(w)e(is)g(lo)s(cated)h(within)f(a)g(giv)m(en)i (2-dimensional)f(region.)70 b(The)40 b(syn)m(tax)h(for)e(this)120 5560 y(high-lev)m(el)32 b(\014lter)f(is)1905 5809 y(32)p eop end %%Page: 33 33 TeXDict begin 33 32 bop 454 573 a Fc(regfilter\()45 b("regfilename")f ([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h("wcs)e(cols")h(])g(])g(\))120 757 y Ff(where)28 b(eac)m(h)i("[)g(]")f(demarks)g(optional)h (parameters.)40 b(The)29 b(region)g(\014le)g(name)g(is)g(required)f (and)g(m)m(ust)h(b)s(e)120 870 y(enclosed)h(in)f(quotes.)41 b(The)29 b(remaining)g(parameters)h(are)f(optional.)42 b(The)29 b(region)h(\014le)f(is)g(an)h(ASCI)s(I)d(text)120 983 y(\014le)37 b(whic)m(h)f(con)m(tains)i(a)f(list)h(of)e(one)h(or)g (more)g(geometric)i(shap)s(es)c(\(circle,)41 b(ellipse,)e(b)s(o)m(x,)f (etc.\))62 b(whic)m(h)120 1096 y(de\014nes)30 b(a)i(region)g(on)f(the)h (celestial)i(sphere)d(or)g(an)g(area)h(within)f(a)h(particular)g(2D)g (image.)45 b(The)31 b(region)120 1209 y(\014le)38 b(is)g(t)m(ypically)i (generated)f(using)f(an)g(image)h(displa)m(y)g(program)f(suc)m(h)f(as)i (fv/PO)m(W)f(\(distribute)g(b)m(y)120 1322 y(the)32 b(HEASAR)m(C\),)g (or)g(ds9)g(\(distributed)f(b)m(y)g(the)h(Smithsonian)g(Astroph)m (ysical)g(Observ)-5 b(atory\).)46 b(Users)120 1435 y(should)41 b(refer)h(to)h(the)f(do)s(cumen)m(tation)h(pro)m(vided)f(with)g(these)g (programs)g(for)g(more)g(details)h(on)f(the)120 1548 y(syn)m(tax)31 b(used)e(in)i(the)f(region)h(\014les.)261 1661 y(In)k(its)h(simpliest)g(form,)h(\(e.g.,)i Fc (regfilter\("region.reg"\))30 b Ff(\))36 b(the)f(co)s(ordinates)i(in)e (the)h(default)120 1774 y('X')24 b(and)e('Y')i(columns)e(will)i(b)s(e)e (used)g(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g(or)g (outside)g(the)g(area)h(sp)s(eci\014ed)120 1886 y(in)h(the)h(region)g (\014le.)39 b(Alternate)27 b(p)s(osition)e(column)g(names,)i(or)e (expressions,)h(ma)m(y)g(b)s(e)f(en)m(tered)h(if)f(needed,)120 1999 y(as)31 b(in)502 2184 y Fc(regfilter\("region.reg",)41 b(XPOS,)47 b(YPOS\))120 2368 y Ff(Region)39 b(\014ltering)g(can)f(b)s (e)g(applied)g(most)g(unam)m(biguously)g(if)g(the)g(p)s(ositions)h(in)e (the)i(region)g(\014le)f(and)120 2481 y(in)e(the)h(table)h(to)g(b)s(e)e (\014ltered)h(are)g(b)s(oth)f(giv)m(e)i(in)f(terms)f(of)h(absolute)h (celestial)h(co)s(ordinate)f(units.)59 b(In)120 2594 y(this)38 b(case)h(the)g(lo)s(cations)h(and)d(sizes)i(of)g(the)f (geometric)i(shap)s(es)e(in)g(the)g(region)h(\014le)f(are)h(sp)s (eci\014ed)f(in)120 2707 y(angular)d(units)f(on)g(the)h(sky)f(\(e.g.,)j (p)s(ositions)e(giv)m(en)h(in)e(R.A.)h(and)f(Dec.)54 b(and)34 b(sizes)h(in)f(arcseconds)h(or)120 2820 y(arcmin)m(utes\).)k (Similarly)-8 b(,)24 b(eac)m(h)f(ro)m(w)g(of)f(the)g(\014ltered)g (table)h(will)f(ha)m(v)m(e)h(a)g(celestial)h(co)s(ordinate)f(asso)s (ciated)120 2933 y(with)33 b(it.)51 b(This)33 b(asso)s(ciation)i(is)f (usually)f(implemen)m(ted)h(using)g(a)f(set)i(of)e(so-called)j('W)-8 b(orld)34 b(Co)s(ordinate)120 3046 y(System')i(\(or)h(W)m(CS\))f(FITS)f (k)m(eyw)m(ords)i(that)f(de\014ne)g(the)g(co)s(ordinate)h (transformation)f(that)h(m)m(ust)f(b)s(e)120 3159 y(applied)30 b(to)h(the)g(v)-5 b(alues)31 b(in)f(the)g('X')h(and)f('Y')h(columns)f (to)h(calculate)i(the)d(co)s(ordinate.)261 3272 y(Alternativ)m(ely)-8 b(,)40 b(one)c(can)f(p)s(erform)f(spatial)j(\014ltering)e(using)g (unitless)h('pixel')g(co)s(ordinates)g(for)f(the)120 3385 y(regions)c(and)f(ro)m(w)h(p)s(ositions.)42 b(In)30 b(this)g(case)i(the)f(user)f(m)m(ust)h(b)s(e)f(careful)h(to)g(ensure)f (that)h(the)g(p)s(ositions)120 3498 y(in)i(the)g(2)h(\014les)f(are)h (self-consisten)m(t.)51 b(A)34 b(t)m(ypical)g(problem)f(is)g(that)h (the)g(region)g(\014le)f(ma)m(y)h(b)s(e)e(generated)120 3610 y(using)23 b(a)h(binned)f(image,)j(but)d(the)h(un)m(binned)e(co)s (ordinates)i(are)h(giv)m(en)f(in)g(the)g(ev)m(en)m(t)h(table.)39 b(The)24 b(R)m(OSA)-8 b(T)120 3723 y(ev)m(en)m(ts)34 b(\014les,)g(for)f(example,)i(ha)m(v)m(e)f(X)f(and)g(Y)g(pixel)g(co)s (ordinates)h(that)g(range)f(from)g(1)g(-)h(15360.)51 b(These)120 3836 y(co)s(ordinates)33 b(are)g(t)m(ypically)i(binned)c(b) m(y)i(a)g(factor)g(of)g(32)h(to)f(pro)s(duce)f(a)h(480x480)i(pixel)e (image.)49 b(If)32 b(one)120 3949 y(then)f(uses)g(a)g(region)h(\014le)f (generated)i(from)d(this)h(image)i(\(in)e(image)h(pixel)g(units\))f(to) h(\014lter)f(the)h(R)m(OSA)-8 b(T)120 4062 y(ev)m(en)m(ts)33 b(\014le,)f(then)f(the)g(X)g(and)g(Y)h(column)f(v)-5 b(alues)31 b(m)m(ust)h(b)s(e)e(con)m(v)m(erted)j(to)f(corresp)s(onding) e(pixel)i(units)120 4175 y(as)f(in:)502 4360 y Fc (regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))120 4544 y Ff(Note)30 b(that)f(this)f(binning)g(con)m(v)m(ersion)h(is)g (not)g(necessary)g(if)f(the)h(region)g(\014le)f(is)h(sp)s(eci\014ed)f (using)g(celestial)120 4657 y(co)s(ordinate)g(units)f(instead)g(of)g (pixel)h(units)e(b)s(ecause)h(CFITSIO)f(is)h(then)g(able)h(to)g (directly)f(compare)h(the)120 4770 y(celestial)37 b(co)s(ordinate)e(of) f(eac)m(h)h(ro)m(w)f(in)g(the)g(table)h(with)f(the)g(celestial)j(co)s (ordinates)e(in)e(the)i(region)f(\014le)120 4883 y(without)c(ha)m(ving) h(to)g(kno)m(w)g(an)m(ything)g(ab)s(out)f(ho)m(w)g(the)h(image)g(ma)m (y)g(ha)m(v)m(e)h(b)s(een)d(binned.)261 4996 y(The)k(last)h("w)m(cs)f (cols")i(parameter)e(should)f(rarely)h(b)s(e)g(needed.)48 b(If)33 b(supplied,)f(this)h(string)g(con)m(tains)120 5109 y(the)39 b(names)g(of)h(the)f(2)g(columns)g(\(space)h(or)f(comma)h (separated\))g(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)120 5222 y(k)m(eyw)m(ords.)j(If)30 b(not)h(supplied,)f(the)h(\014lter)g (will)g(scan)g(the)g(X)g(and)g(Y)g(expressions)f(for)h(column)g(names.) 42 b(If)120 5334 y(only)33 b(one)f(is)h(found)e(in)h(eac)m(h)i (expression,)f(those)g(columns)f(will)h(b)s(e)f(used,)h(otherwise)g(an) f(error)g(will)h(b)s(e)120 5447 y(returned.)261 5560 y(These)d(region)h(shap)s(es)f(are)g(supp)s(orted)f(\(names)i(are)f (case)i(insensitiv)m(e\):)1905 5809 y(33)p eop end %%Page: 34 34 TeXDict begin 34 33 bop 454 573 a Fc(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)454 686 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region)454 799 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 b(Rest)e(are)h(interiors)e(with)454 912 y(Rectangle)236 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e (considered)454 1024 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) i(\))143 b(V)47 b(within)f(the)h(region)454 1137 y(Diamond)332 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))454 1250 y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))454 1363 y(Annulus)332 b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))454 1476 y(Ellipse)332 b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))454 1589 y(Elliptannulus)c(\() k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))454 1702 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))120 1914 y Ff(where)33 b(\(Xc,Yc\))j(is)e(the)h(co)s(ordinate)f(of)h(the)f (shap)s(e's)f(cen)m(ter;)k(\(X#,Y#\))e(are)f(the)g(co)s(ordinates)h(of) f(the)120 2027 y(shap)s(e's)22 b(edges;)k(Rxxx)d(are)g(the)h(shap)s (es')e(v)-5 b(arious)23 b(Radii)g(or)g(semima)5 b(jor/minor)23 b(axes;)k(and)22 b(Axxx)h(are)g(the)120 2140 y(angles)j(of)f(rotation)h (\(or)f(b)s(ounding)e(angles)j(for)f(Sector\))h(in)e(degrees.)40 b(F)-8 b(or)26 b(rotated)g(shap)s(es,)f(the)g(rotation)120 2253 y(angle)37 b(can)g(b)s(e)e(left)i(o\013,)h(indicating)f(no)f (rotation.)60 b(Common)35 b(alternate)j(names)e(for)g(the)g(regions)h (can)120 2366 y(also)28 b(b)s(e)e(used:)39 b(rotb)s(o)m(x)27 b(=)f(b)s(o)m(x;)j(rotrectangle)g(=)e(rectangle;)j(\(rot\)rhom)m(bus)c (=)h(\(rot\)diamond;)i(and)d(pie)120 2479 y(=)h(sector.)41 b(When)28 b(a)g(shap)s(e's)f(name)g(is)h(preceded)f(b)m(y)h(a)g(min)m (us)f(sign,)i('-',)g(the)f(de\014ned)e(region)i(is)g(instead)120 2592 y(the)36 b(area)g(*outside*)h(its)f(b)s(oundary)d(\(ie,)38 b(the)e(region)g(is)g(in)m(v)m(erted\).)57 b(All)36 b(the)g(shap)s(es)f (within)g(a)h(single)120 2705 y(region)f(\014le)g(are)g(OR'd)g (together)h(to)f(create)i(the)e(region,)h(and)f(the)g(order)f(is)h (signi\014can)m(t.)55 b(The)34 b(o)m(v)m(erall)120 2818 y(w)m(a)m(y)g(of)g(lo)s(oking)g(at)g(region)g(\014les)f(is)g(that)h(if) f(the)h(\014rst)e(region)i(is)g(an)f(excluded)g(region)h(then)f(a)g (dumm)m(y)120 2931 y(included)c(region)i(of)f(the)g(whole)g(detector)i (is)e(inserted)f(in)h(the)g(fron)m(t.)41 b(Then)29 b(eac)m(h)i(region)g (sp)s(eci\014cation)120 3044 y(as)g(it)h(is)f(pro)s(cessed)g(o)m(v)m (errides)h(an)m(y)f(selections)i(inside)e(of)g(that)h(region)g(sp)s (eci\014ed)e(b)m(y)h(previous)g(regions.)120 3156 y(Another)e(w)m(a)m (y)i(of)e(thinking)g(ab)s(out)g(this)g(is)h(that)f(if)h(a)f(previous)g (excluded)g(region)h(is)g(completely)h(inside)120 3269 y(of)g(a)f(subsequen)m(t)g(included)g(region)h(the)f(excluded)g(region) h(is)g(ignored.)261 3382 y(The)20 b(p)s(ositional)h(co)s(ordinates)g (ma)m(y)g(b)s(e)e(giv)m(en)j(either)e(in)g(pixel)h(units,)h(decimal)f (degrees)g(or)f(hh:mm:ss.s,)120 3495 y(dd:mm:ss.s)25 b(units.)38 b(The)26 b(shap)s(e)f(sizes)h(ma)m(y)h(b)s(e)e(giv)m(en)i (in)e(pixels,)j(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)120 3608 y(Lo)s(ok)k(at)i(examples)e(of)h(region)g(\014le)f(pro)s(duced)f (b)m(y)h(fv/PO)m(W)h(or)f(ds9)g(for)g(further)f(details)j(of)e(the)h (region)120 3721 y(\014le)f(format.)120 3961 y Fg(5.4.5)105 b(Example)35 b(Ro)m(w)g(Filters)311 4133 y Fc([double)46 b(&&)h(mag)g(<=)g(5.0])381 b(-)95 b(Extract)46 b(all)h(double)f(stars)g (brighter)1886 4246 y(than)94 b(fifth)47 b(magnitude)311 4472 y([#row)f(>=)h(125)g(&&)h(#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through)f(175)311 4697 y([abs\(sin\(theta)e(*)j(#deg\)\))f(<)i(0.5])e(-)i(Extract)e(all)h (rows)f(having)g(the)1886 4810 y(absolute)f(value)i(of)g(the)g(sine)g (of)g(theta)1886 4923 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h (angles)1886 5036 y(are)g(tabulated)e(in)i(degrees)311 5262 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g (expression)1886 5375 y(contained)e(within)h(the)h(text)g(file)1886 5488 y(rowFilter.txt)1905 5809 y Ff(34)p eop end %%Page: 35 35 TeXDict begin 35 34 bop 311 686 a Fc([gtifilter\(\)])855 b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)359 799 y(extension,)92 b(filter)i(the)47 b(TIME)359 912 y(column)f(in)h(the)g(current)f(table,)g(using)359 1024 y(START/STOP)f(times)h(taken)g(from)359 1137 y(columns)f(in)j(the)f (GTI)94 b(extension)311 1363 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h(have)f(a)i(coordinate)1886 1476 y(\(as)f(given)f(in)h(the)g(X)h(and)f(Y)g(columns\))1886 1589 y(within)f(the)h(spatial)f(region)g(specified)1886 1702 y(in)h(the)g(pow.reg)f(region)g(file.)1905 5809 y Ff(35)p eop end %%Page: 36 36 TeXDict begin 36 35 bop 120 573 a Fb(5.5)112 b(Com)m(bined)39 b(Filtering)f(Examples)120 744 y Ff(The)29 b(previous)h(sections)g (describ)s(ed)f(all)i(the)f(individual)f(t)m(yp)s(es)h(of)g(\014lters)f (that)i(ma)m(y)f(b)s(e)f(applied)h(to)g(the)120 857 y(input)j(\014le.) 50 b(In)33 b(this)g(section)i(w)m(e)f(sho)m(w)g(examples)g(whic)m(h)f (com)m(bine)i(sev)m(eral)f(di\013eren)m(t)h(\014lters)e(at)h(once.)120 970 y(These)h(examples)g(all)h(use)f(the)g Fc(fitscopy)e Ff(program)i(that)g(is)g(distributed)f(with)h(the)g(CFITSIO)f(co)s(de.) 120 1083 y(It)c(simply)g(copies)i(the)e(input)g(\014le)g(to)h(the)g (output)f(\014le.)120 1268 y Fc(fitscopy)46 b(rosat.fit)f(out.fit)261 1453 y Ff(This)26 b(trivial)i(example)f(simply)g(mak)m(es)g(an)g(iden)m (tical)i(cop)m(y)e(of)g(the)g(input)f(rosat.\014t)h(\014le)g(without)g (an)m(y)120 1566 y(\014ltering.)120 1751 y Fc(fitscopy)46 b('rosat.fit[events][col)41 b(Time;X;Y][#row)j(<)k(1000]')e(out.fit)261 1936 y Ff(The)34 b(output)g(\014le)h(con)m(tains)h(only)e(the)h(Time,)h (X,)f(and)e(Y)i(columns,)h(and)d(only)i(the)g(\014rst)f(999)h(ro)m(ws) 120 2049 y(from)g(the)g('EVENTS')f(table)i(extension)g(of)f(the)g (input)f(\014le.)55 b(All)35 b(the)h(other)f(HDUs)g(in)g(the)g(input)f (\014le)120 2162 y(are)d(copied)g(to)g(the)f(output)g(\014le)h(without) f(an)m(y)h(mo)s(di\014cation.)120 2346 y Fc(fitscopy)46 b('rosat.fit[events][PI)c(<)47 b(50][bin)f(\(Xdet,Ydet\))f(=)i(16]')g (image.fit)261 2531 y Ff(This)30 b(creates)h(an)f(output)g(image)i(b)m (y)e(binning)f(the)h(Xdet)h(and)f(Ydet)g(columns)g(of)g(the)h(ev)m(en)m (ts)g(table)120 2644 y(with)26 b(a)h(pixel)g(binning)e(factor)i(of)g (16.)40 b(Only)26 b(the)h(ro)m(ws)f(whic)m(h)g(ha)m(v)m(e)i(a)e(PI)h (energy)f(less)h(than)f(50)h(are)g(used)120 2757 y(to)33 b(construct)f(this)f(image.)46 b(The)32 b(output)f(image)i(\014le)f (con)m(tains)h(a)f(primary)f(arra)m(y)h(image)h(without)f(an)m(y)120 2870 y(extensions.)120 3055 y Fc(fitscopy)46 b('rosat.fit[events][gtif) o(ilt)o(er\(\))41 b(&&)47 b(regfilter\("pow.reg"\)]')42 b(out.fit)261 3240 y Ff(The)29 b(\014ltering)h(expression)f(in)g(this)h (example)g(uses)f(the)h Fc(gtifilter)d Ff(function)i(to)h(test)g (whether)f(the)120 3353 y(TIME)e(column)g(v)-5 b(alue)27 b(in)g(eac)m(h)i(ro)m(w)e(is)g(within)g(one)g(of)g(the)h(Go)s(o)s(d)f (Time)g(In)m(terv)-5 b(als)27 b(de\014ned)f(in)h(the)h(GTI)120 3466 y(extension)i(in)f(the)h(same)g(input)e(\014le,)i(and)f(also)i (uses)e(the)g Fc(regfilter)e Ff(function)j(to)g(test)g(if)g(the)f(p)s (osition)120 3579 y(asso)s(ciated)j(with)d(eac)m(h)i(ro)m(w)g(\(deriv)m (ed)f(b)m(y)g(default)g(from)g(the)g(v)-5 b(alues)30 b(in)g(the)g(X)h(and)e(Y)h(columns)g(of)g(the)120 3692 y(ev)m(en)m(ts)38 b(table\))f(is)g(lo)s(cated)h(within)d(the)i(area)g (de\014ned)e(in)i(the)f Fc(pow.reg)f Ff(text)i(region)g(\014le)f (\(whic)m(h)h(w)m(as)120 3804 y(previously)h(created)i(with)f(the)f Fc(fv/POW)f Ff(image)j(displa)m(y)f(program\).)66 b(Only)38 b(the)h(ro)m(ws)f(whic)m(h)h(satisfy)120 3917 y(b)s(oth)30 b(tests)h(are)g(copied)f(to)h(the)g(output)f(table.)120 4102 y Fc(fitscopy)46 b('r.fit[evt][PI<50]')c(stdout)k(|)i(fitscopy)d (stdin[evt][col)f(X,Y])j(out.fit)261 4287 y Ff(In)25 b(this)g(somewhat)h(con)m(v)m(oluted)g(example,)i(\014tscop)m(y)d(is)h (used)e(to)i(\014rst)f(select)i(the)e(ro)m(ws)g(from)g(the)h(evt)120 4400 y(extension)k(whic)m(h)g(ha)m(v)m(e)h(PI)e(less)h(than)g(50)g(and) f(write)h(the)g(resulting)g(table)h(out)f(to)g(the)g(stdout)g(stream.) 120 4513 y(This)37 b(is)g(pip)s(ed)f(to)i(a)g(2nd)f(instance)h(of)g (\014tscop)m(y)g(\(with)f(the)h(Unix)f(`)p Fa(j)p Ff(')h(pip)s(e)f (command\))g(whic)m(h)h(reads)120 4626 y(that)31 b(\014ltered)g(FITS)e (\014le)i(from)f(the)h(stdin)f(stream)h(and)f(copies)h(only)g(the)g(X)f (and)g(Y)h(columns)f(from)g(the)120 4739 y(evt)h(table)g(to)g(the)g (output)f(\014le.)120 4924 y Fc(fitscopy)46 b('r.fit[evt][col)d (RAD=sqrt\(\(X-#XCEN\)**2+\(Y-)o(#YCE)o(N\)*)o(*2\)])o([rad)o(<10)o (0]')e(out.fit)261 5109 y Ff(This)24 b(example)i(\014rst)e(creates)i(a) f(new)f(column)h(called)h(RAD)f(whic)m(h)f(giv)m(es)i(the)f(distance)h (b)s(et)m(w)m(een)f(the)120 5222 y(X,Y)k(co)s(ordinate)g(of)f(eac)m(h)i (ev)m(en)m(t)g(and)d(the)i(co)s(ordinate)g(de\014ned)e(b)m(y)h(the)h(X) m(CEN)f(and)g(YCEN)g(k)m(eyw)m(ords)120 5334 y(in)k(the)h(header.)47 b(Then,)32 b(only)h(those)g(ro)m(ws)g(whic)m(h)f(ha)m(v)m(e)i(a)f (distance)g(less)g(than)f(100)i(are)f(copied)g(to)g(the)120 5447 y(output)e(table.)46 b(In)31 b(other)h(w)m(ords,)f(only)h(the)g (ev)m(en)m(ts)h(whic)m(h)f(are)g(lo)s(cated)h(within)e(100)i(pixel)f (units)f(from)120 5560 y(the)g(\(X)m(CEN,)g(YCEN\))f(co)s(ordinate)i (are)e(copied)h(to)g(the)g(output)f(table.)1905 5809 y(36)p eop end %%Page: 37 37 TeXDict begin 37 36 bop 120 573 a Fc(fitscopy)46 b ('ftp://heasarc.gsfc.nas)o(a.g)o(ov/r)o(osat)o(.fi)o(t[ev)o(ents)o(][b) o(in)c(\(X,Y\)=16]')j(img.fit)261 785 y Ff(This)23 b(example)h(bins)e (the)h(X)h(and)f(Y)g(columns)g(of)g(the)h(h)m(yp)s(othetical)g(R)m(OSA) -8 b(T)24 b(\014le)f(at)h(the)f(HEASAR)m(C)120 898 y(ftp)30 b(site)h(to)g(create)h(the)f(output)f(image.)120 1111 y Fc(fitscopy)46 b('raw.fit[i512,512][101:)o(110)o(,51:)o(60]')41 b(image.fit)261 1323 y Ff(This)29 b(example)h(con)m(v)m(erts)h(the)e (512)i(x)e(512)i(pixel)f(ra)m(w)f(binary)g(16-bit)h(in)m(teger)h(image) g(to)f(a)g(FITS)e(\014le)120 1436 y(and)i(copies)h(a)g(10)g(x)f(10)h (pixel)g(subimage)g(from)f(it)g(to)i(the)e(output)g(FITS)g(image.)1905 5809 y(37)p eop end %%Page: 38 38 TeXDict begin 38 37 bop 120 573 a Fh(6)135 b(CFITSIO)44 b(Error)h(Status)g(Co)t(des)120 776 y Ff(The)34 b(follo)m(wing)h(table) g(lists)g(all)g(the)f(error)g(status)g(co)s(des)h(used)e(b)m(y)h (CFITSIO.)f(Programmers)h(are)g(en-)120 889 y(couraged)f(to)g(use)g (the)f(sym)m(b)s(olic)h(mnemonics)g(\(de\014ned)e(in)h(the)h(\014le)g (\014tsio.h\))g(rather)f(than)g(the)h(actual)120 1002 y(in)m(teger)f(status)e(v)-5 b(alues)31 b(to)g(impro)m(v)m(e)g(the)g (readabilit)m(y)h(of)e(their)h(co)s(de.)168 1214 y Fc(Symbolic)45 b(Const)190 b(Value)237 b(Meaning)168 1327 y(--------------)187 b(-----)94 b(------------------------)o(----)o(---)o(----)o(----)o(--) 1122 1440 y(0)191 b(OK,)47 b(no)g(error)168 1553 y(SAME_FILE)427 b(101)190 b(input)46 b(and)h(output)f(files)h(are)g(the)f(same)168 1666 y(TOO_MANY_FILES)187 b(103)j(tried)46 b(to)h(open)g(too)g(many)g (FITS)f(files)h(at)g(once)168 1779 y(FILE_NOT_OPENED)139 b(104)190 b(could)46 b(not)h(open)g(the)g(named)f(file)168 1892 y(FILE_NOT_CREATED)91 b(105)190 b(could)46 b(not)h(create)f(the)h (named)g(file)168 2005 y(WRITE_ERROR)331 b(106)190 b(error)46 b(writing)g(to)h(FITS)g(file)168 2117 y(END_OF_FILE)331 b(107)190 b(tried)46 b(to)h(move)g(past)g(end)g(of)g(file)168 2230 y(READ_ERROR)379 b(108)190 b(error)46 b(reading)g(from)h(FITS)f (file)168 2343 y(FILE_NOT_CLOSED)139 b(110)190 b(could)46 b(not)h(close)g(the)f(file)168 2456 y(ARRAY_TOO_BIG)235 b(111)190 b(array)46 b(dimensions)f(exceed)h(internal)g(limit)168 2569 y(READONLY_FILE)235 b(112)190 b(Cannot)46 b(write)g(to)i(readonly) d(file)168 2682 y(MEMORY_ALLOCATION)e(113)190 b(Could)46 b(not)h(allocate)f(memory)168 2795 y(BAD_FILEPTR)331 b(114)190 b(invalid)46 b(fitsfile)f(pointer)168 2908 y(NULL_INPUT_PTR)187 b(115)j(NULL)47 b(input)f(pointer)g(to)h(routine) 168 3021 y(SEEK_ERROR)379 b(116)190 b(error)46 b(seeking)g(position)g (in)h(file)168 3247 y(BAD_URL_PREFIX)235 b(121)142 b(invalid)46 b(URL)h(prefix)f(on)h(file)g(name)168 3359 y(TOO_MANY_DRIVERS)139 b(122)j(tried)46 b(to)h(register)f(too)h(many)g(IO)g(drivers)168 3472 y(DRIVER_INIT_FAILED)c(123)142 b(driver)46 b(initialization)e (failed)168 3585 y(NO_MATCHING_DRIVER)f(124)142 b(matching)45 b(driver)i(is)g(not)g(registered)168 3698 y(URL_PARSE_ERROR)187 b(125)142 b(failed)46 b(to)h(parse)g(input)f(file)h(URL)168 3924 y(SHARED_BADARG)235 b(151)190 b(bad)47 b(argument)e(in)j(shared)e (memory)g(driver)168 4037 y(SHARED_NULPTR)235 b(152)190 b(null)47 b(pointer)e(passed)h(as)i(an)f(argument)168 4150 y(SHARED_TABFULL)187 b(153)j(no)47 b(more)g(free)f(shared)g (memory)h(handles)168 4263 y(SHARED_NOTINIT)187 b(154)j(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)168 4376 y(SHARED_IPCERR)235 b(155)190 b(IPC)47 b(error)f(returned)g(by)h(a)g(system)f(call)168 4489 y(SHARED_NOMEM)283 b(156)190 b(no)47 b(memory)f(in)h(shared)f (memory)h(driver)168 4601 y(SHARED_AGAIN)283 b(157)190 b(resource)45 b(deadlock)h(would)g(occur)168 4714 y(SHARED_NOFILE)235 b(158)190 b(attempt)46 b(to)h(open/create)e(lock)h(file)h(failed)168 4827 y(SHARED_NORESIZE)139 b(159)190 b(shared)46 b(memory)g(block)g (cannot)h(be)g(resized)f(at)h(the)g(moment)168 5053 y(HEADER_NOT_EMPTY) 91 b(201)190 b(header)46 b(already)g(contains)f(keywords)168 5166 y(KEY_NO_EXIST)283 b(202)190 b(keyword)46 b(not)h(found)f(in)h (header)168 5279 y(KEY_OUT_BOUNDS)187 b(203)j(keyword)46 b(record)g(number)g(is)h(out)g(of)g(bounds)168 5392 y(VALUE_UNDEFINED) 139 b(204)190 b(keyword)46 b(value)g(field)g(is)i(blank)168 5505 y(NO_QUOTE)475 b(205)190 b(string)46 b(is)h(missing)f(the)h (closing)f(quote)1905 5809 y Ff(38)p eop end %%Page: 39 39 TeXDict begin 39 38 bop 168 573 a Fc(BAD_KEYCHAR)331 b(207)190 b(illegal)46 b(character)f(in)i(keyword)f(name)h(or)g(card) 168 686 y(BAD_ORDER)427 b(208)190 b(required)45 b(keywords)h(out)h(of)g (order)168 799 y(NOT_POS_INT)331 b(209)190 b(keyword)46 b(value)g(is)h(not)g(a)h(positive)d(integer)168 912 y(NO_END)571 b(210)190 b(couldn't)45 b(find)i(END)g(keyword)168 1024 y(BAD_BITPIX)379 b(211)190 b(illegal)46 b(BITPIX)g(keyword)g(value)168 1137 y(BAD_NAXIS)427 b(212)190 b(illegal)46 b(NAXIS)g(keyword)g(value) 168 1250 y(BAD_NAXES)427 b(213)190 b(illegal)46 b(NAXISn)g(keyword)g (value)168 1363 y(BAD_PCOUNT)379 b(214)190 b(illegal)46 b(PCOUNT)g(keyword)g(value)168 1476 y(BAD_GCOUNT)379 b(215)190 b(illegal)46 b(GCOUNT)g(keyword)g(value)168 1589 y(BAD_TFIELDS)331 b(216)190 b(illegal)46 b(TFIELDS)g(keyword)f (value)168 1702 y(NEG_WIDTH)427 b(217)190 b(negative)45 b(table)i(row)g(size)168 1815 y(NEG_ROWS)475 b(218)190 b(negative)45 b(number)i(of)g(rows)f(in)i(table)168 1928 y(COL_NOT_FOUND)235 b(219)190 b(column)46 b(with)h(this)f(name)h(not)g (found)f(in)h(table)168 2041 y(BAD_SIMPLE)379 b(220)190 b(illegal)46 b(value)g(of)h(SIMPLE)f(keyword)168 2154 y(NO_SIMPLE)427 b(221)190 b(Primary)46 b(array)g(doesn't)g(start)g (with)h(SIMPLE)168 2267 y(NO_BITPIX)427 b(222)190 b(Second)46 b(keyword)g(not)h(BITPIX)168 2379 y(NO_NAXIS)475 b(223)190 b(Third)46 b(keyword)g(not)h(NAXIS)168 2492 y(NO_NAXES)475 b(224)190 b(Couldn't)45 b(find)i(all)g(the)g(NAXISn)f(keywords)168 2605 y(NO_XTENSION)331 b(225)190 b(HDU)47 b(doesn't)f(start)g(with)h (XTENSION)e(keyword)168 2718 y(NOT_ATABLE)379 b(226)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(ASCII)f(table)g(extension)168 2831 y(NOT_BTABLE)379 b(227)190 b(the)47 b(CHDU)f(is)i(not)f(a)g (binary)f(table)g(extension)168 2944 y(NO_PCOUNT)427 b(228)190 b(couldn't)45 b(find)i(PCOUNT)f(keyword)168 3057 y(NO_GCOUNT)427 b(229)190 b(couldn't)45 b(find)i(GCOUNT)f(keyword) 168 3170 y(NO_TFIELDS)379 b(230)190 b(couldn't)45 b(find)i(TFIELDS)f (keyword)168 3283 y(NO_TBCOL)475 b(231)190 b(couldn't)45 b(find)i(TBCOLn)f(keyword)168 3396 y(NO_TFORM)475 b(232)190 b(couldn't)45 b(find)i(TFORMn)f(keyword)168 3509 y(NOT_IMAGE)427 b(233)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(IMAGE)f(extension)168 3621 y(BAD_TBCOL)427 b(234)190 b(TBCOLn)46 b(keyword)g(value)g(<)i(0)f (or)g(>)h(rowlength)168 3734 y(NOT_TABLE)427 b(235)190 b(the)47 b(CHDU)f(is)i(not)f(a)g(table)168 3847 y(COL_TOO_WIDE)283 b(236)190 b(column)46 b(is)h(too)g(wide)g(to)g(fit)g(in)g(table)168 3960 y(COL_NOT_UNIQUE)187 b(237)j(more)47 b(than)f(1)i(column)e(name)g (matches)g(template)168 4073 y(BAD_ROW_WIDTH)235 b(241)190 b(sum)47 b(of)g(column)f(widths)g(not)h(=)h(NAXIS1)168 4186 y(UNKNOWN_EXT)331 b(251)190 b(unrecognizable)44 b(FITS)i(extension)g(type)168 4299 y(UNKNOWN_REC)331 b(252)190 b(unknown)46 b(record;)g(1st)g(keyword)g(not)h(SIMPLE)f(or)h (XTENSION)168 4412 y(END_JUNK)475 b(253)190 b(END)47 b(keyword)f(is)h(not)g(blank)168 4525 y(BAD_HEADER_FILL)139 b(254)190 b(Header)46 b(fill)h(area)f(contains)g(non-blank)f(chars)168 4638 y(BAD_DATA_FILL)235 b(255)190 b(Illegal)46 b(data)g(fill)h(bytes)f (\(not)h(zero)g(or)g(blank\))168 4751 y(BAD_TFORM)427 b(261)190 b(illegal)46 b(TFORM)g(format)g(code)168 4863 y(BAD_TFORM_DTYPE)139 b(262)190 b(unrecognizable)44 b(TFORM)i(datatype) g(code)168 4976 y(BAD_TDIM)475 b(263)190 b(illegal)46 b(TDIMn)g(keyword)g(value)168 5089 y(BAD_HEAP_PTR)283 b(264)190 b(invalid)46 b(BINTABLE)f(heap)i(pointer)f(is)h(out)g(of)g (range)168 5315 y(BAD_HDU_NUM)331 b(301)190 b(HDU)47 b(number)f(<)h(1)h(or)f(>)g(MAXHDU)168 5428 y(BAD_COL_NUM)331 b(302)190 b(column)46 b(number)g(<)i(1)f(or)g(>)h(tfields)168 5541 y(NEG_FILE_POS)283 b(304)190 b(tried)46 b(to)h(move)g(to)g (negative)f(byte)g(location)g(in)h(file)1905 5809 y Ff(39)p eop end %%Page: 40 40 TeXDict begin 40 39 bop 168 573 a Fc(NEG_BYTES)427 b(306)190 b(tried)46 b(to)h(read)g(or)g(write)g(negative)e(number)h(of)h(bytes) 168 686 y(BAD_ROW_NUM)331 b(307)190 b(illegal)46 b(starting)f(row)i (number)f(in)h(table)168 799 y(BAD_ELEM_NUM)283 b(308)190 b(illegal)46 b(starting)f(element)h(number)g(in)h(vector)168 912 y(NOT_ASCII_COL)235 b(309)190 b(this)47 b(is)g(not)g(an)g(ASCII)f (string)g(column)168 1024 y(NOT_LOGICAL_COL)139 b(310)190 b(this)47 b(is)g(not)g(a)g(logical)f(datatype)f(column)168 1137 y(BAD_ATABLE_FORMAT)e(311)190 b(ASCII)46 b(table)h(column)f(has)h (wrong)f(format)168 1250 y(BAD_BTABLE_FORMAT)d(312)190 b(Binary)46 b(table)g(column)g(has)h(wrong)g(format)168 1363 y(NO_NULL)523 b(314)190 b(null)47 b(value)f(has)h(not)g(been)f (defined)168 1476 y(NOT_VARI_LEN)283 b(317)190 b(this)47 b(is)g(not)g(a)g(variable)f(length)g(column)168 1589 y(BAD_DIMEN)427 b(320)190 b(illegal)46 b(number)g(of)h(dimensions)e(in) i(array)168 1702 y(BAD_PIX_NUM)331 b(321)190 b(first)46 b(pixel)h(number)f(greater)g(than)g(last)h(pixel)168 1815 y(ZERO_SCALE)379 b(322)190 b(illegal)46 b(BSCALE)g(or)h(TSCALn)f (keyword)g(=)h(0)168 1928 y(NEG_AXIS)475 b(323)190 b(illegal)46 b(axis)g(length)g(<)i(1)168 2154 y(NOT_GROUP_TABLE)330 b(340)142 b(Grouping)46 b(function)f(error)168 2267 y (HDU_ALREADY_MEMBER)186 b(341)168 2379 y(MEMBER_NOT_FOUND)282 b(342)168 2492 y(GROUP_NOT_FOUND)330 b(343)168 2605 y(BAD_GROUP_ID)474 b(344)168 2718 y(TOO_MANY_HDUS_TRACKED)42 b(345)168 2831 y(HDU_ALREADY_TRACKED)138 b(346)168 2944 y(BAD_OPTION)570 b(347)168 3057 y(IDENTICAL_POINTERS)186 b(348)168 3170 y(BAD_GROUP_ATTACH)282 b(349)168 3283 y(BAD_GROUP_DETACH)g(350)168 3509 y(NGP_NO_MEMORY)426 b(360)238 b(malloc)46 b(failed)168 3621 y(NGP_READ_ERR)474 b(361)238 b(read)46 b(error)h(from)f(file)168 3734 y(NGP_NUL_PTR)522 b(362)238 b(null)46 b(pointer)g(passed)g(as)h (an)g(argument.)1695 3847 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f (of)1695 3960 y(template)f(file)g(raises)g(this)h(error)168 4073 y(NGP_EMPTY_CURLINE)234 b(363)k(line)46 b(read)h(seems)f(to)h(be)h (empty)e(\(used)1695 4186 y(internally\))168 4299 y (NGP_UNREAD_QUEUE_FULL)c(364)238 b(cannot)46 b(unread)g(more)g(then)h (1)g(line)g(\(or)g(single)1695 4412 y(line)g(twice\))168 4525 y(NGP_INC_NESTING)330 b(365)238 b(too)46 b(deep)h(include)f(file)h (nesting)e(\(infinite)1695 4638 y(loop,)h(template)g(includes)f(itself) i(?\))168 4751 y(NGP_ERR_FOPEN)426 b(366)238 b(fopen\(\))45 b(failed,)h(cannot)g(open)h(template)e(file)168 4863 y(NGP_EOF)714 b(367)238 b(end)46 b(of)i(file)e(encountered)f(and)i(not) g(expected)168 4976 y(NGP_BAD_ARG)522 b(368)238 b(bad)46 b(arguments)g(passed.)g(Usually)f(means)1695 5089 y(internal)h(parser)g (error.)g(Should)g(not)h(happen)168 5202 y(NGP_TOKEN_NOT_EXPECT)90 b(369)238 b(token)46 b(not)h(expected)e(here)168 5428 y(BAD_I2C)523 b(401)190 b(bad)47 b(int)g(to)g(formatted)e(string)h (conversion)168 5541 y(BAD_F2C)523 b(402)190 b(bad)47 b(float)f(to)h(formatted)f(string)g(conversion)1905 5809 y Ff(40)p eop end %%Page: 41 41 TeXDict begin 41 40 bop 168 573 a Fc(BAD_INTKEY)379 b(403)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(integer)168 686 y(BAD_LOGICALKEY)187 b(404)j(can't)46 b(interpret)g(keyword)f (value)i(as)g(logical)168 799 y(BAD_FLOATKEY)283 b(405)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(float)168 912 y(BAD_DOUBLEKEY)235 b(406)190 b(can't)46 b(interpret)g(keyword)f (value)i(as)g(double)168 1024 y(BAD_C2I)523 b(407)190 b(bad)47 b(formatted)e(string)h(to)h(int)g(conversion)168 1137 y(BAD_C2F)523 b(408)190 b(bad)47 b(formatted)e(string)h(to)h (float)g(conversion)168 1250 y(BAD_C2D)523 b(409)190 b(bad)47 b(formatted)e(string)h(to)h(double)f(conversion)168 1363 y(BAD_DATATYPE)283 b(410)190 b(illegal)46 b(datatype)f(code)i (value)168 1476 y(BAD_DECIM)427 b(411)190 b(bad)47 b(number)f(of)h (decimal)f(places)g(specified)168 1589 y(NUM_OVERFLOW)283 b(412)190 b(overflow)45 b(during)i(datatype)e(conversion)168 1702 y(DATA_COMPRESSION_ERR)137 b(413)95 b(error)46 b(compressing)f (image)168 1815 y(DATA_DECOMPRESSION_ERR)c(414)95 b(error)46 b(uncompressing)f(image)168 2041 y(BAD_DATE)475 b(420)190 b(error)46 b(in)h(date)g(or)g(time)g(conversion)168 2267 y(PARSE_SYNTAX_ERR)91 b(431)190 b(syntax)46 b(error)g(in)i(parser)e (expression)168 2379 y(PARSE_BAD_TYPE)187 b(432)j(expression)45 b(did)i(not)g(evaluate)e(to)i(desired)f(type)168 2492 y(PARSE_LRG_VECTOR)91 b(433)190 b(vector)46 b(result)g(too)h(large)f (to)i(return)e(in)h(array)168 2605 y(PARSE_NO_OUTPUT)139 b(434)190 b(data)47 b(parser)f(failed)g(not)h(sent)f(an)h(out)g(column) 168 2718 y(PARSE_BAD_COL)235 b(435)190 b(bad)47 b(data)f(encounter)g (while)g(parsing)g(column)168 2831 y(PARSE_BAD_OUTPUT)91 b(436)190 b(Output)46 b(file)h(not)g(of)g(proper)f(type)168 3057 y(ANGLE_TOO_BIG)235 b(501)190 b(celestial)45 b(angle)i(too)f (large)h(for)g(projection)168 3170 y(BAD_WCS_VAL)331 b(502)190 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)g(value)168 3283 y(WCS_ERROR)427 b(503)190 b(error)46 b(in)h(celestial)f (coordinate)f(calculation)168 3396 y(BAD_WCS_PROJ)283 b(504)190 b(unsupported)45 b(type)h(of)h(celestial)f(projection)168 3509 y(NO_WCS_KEY)379 b(505)190 b(celestial)45 b(coordinate)g(keywords) h(not)h(found)168 3621 y(APPROX_WCS_KEY)187 b(506)j(approximate)45 b(wcs)i(keyword)e(values)h(were)h(returned)1905 5809 y Ff(41)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF cfitsio-4.3.1/docs/cfitsio.ps0000644000225700000360000422062214456514035015420 0ustar cagordonlhea%!PS-Adobe-2.0 %%Creator: dvips(k) 5.998 Copyright 2018 Radical Eye Software %%Title: cfitsio.dvi %%CreationDate: Tue Jul 18 17:28:58 2023 %%Pages: 202 %%PageOrder: Ascend %%BoundingBox: 0 0 596 842 %%DocumentFonts: CMBX12 CMR12 CMR10 CMBX10 CMSL10 CMTT10 CMSY10 CMMI10 %%+ CMTI10 %%DocumentPaperSizes: a4 %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o cfitsio.ps cfitsio.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2023.07.18:1328 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /dir 0 def/dyy{/dir 0 def}B/dyt{/dir 1 def}B/dty{/dir 2 def}B/dtt{/dir 3 def}B/p{dir 2 eq{-90 rotate show 90 rotate}{dir 3 eq{-90 rotate show 90 rotate}{show}ifelse}ifelse}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT)(LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse} forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{ BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat {BDot}imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B /M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M} B/g{0 M}B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{ 0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMTI10 %!PS-AdobeFont-1.0: CMTI10 003.002 %%Title: CMTI10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMTI10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMTI10 known{/CMTI10 findfont dup/UniqueID known{dup /UniqueID get 5000828 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMTI10 def /FontBBox {-35 -250 1124 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMTI10.) readonly def /FullName (CMTI10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 12 /fi put dup 68 /D put dup 72 /H put dup 85 /U put dup 97 /a put dup 98 /b put dup 101 /e put dup 103 /g put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 122 /z put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7 5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99 8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716 EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C 02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D 46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A 4B60D020D325E4C2450F3BCF59223103D20DB6943DE1B57C5FD29DA32D34C95E 2AB2ADB3F60EEB0600C8ADE15A2380DE10AC5AAD585FBD13097B1A7E8E210D4A EE96785449E07F0C8EBC2EC5EFBFD0897DFDC15E5BFAC9584D8DE95C5AB288CD 8AD8B9BEF0B8E5F887B3B0B331542FC8184DCCB753DB6ACEEF98B85756B988DF CAF1AE0DBE7D37D5F44A2E760AAE3A5197C27B15E32275A64946C3E4D0476FD2 7FDE148C788DD2106F7C825E270588AC05B57E625AB17BDD02306F9E5FC851DC 32A5A6EDC43C770A71419B2C0C8074EF3F222C8A2097CD81A91F333A521B3A09 482A4FE1CB231CE344AD126AA284C3280AAC3AD162CF0EE241BFB4C8F20502FF 118507F5D1B5FD898571015E73E5CF2281085072E00D401F6F59761EEC3E8381 1F26F75DB66C504AB6BABA87D121B1E7040A07AA2FE01F80DBC246CC03C4B2DC C2A715980C52B7F96BC1A78FCC7F4F52EEED5F705E08FC1E5BBFCAD121FA88AA 8EBE58172C162AF409DBB0728F14923ED02A65EA24E5D52B6AD07777455A70A4 61833D3789C719BA92E901232599767E423D5AD9C807670BE0E7B5CFF8256A20 C7BF7214FFE0342809570F5966A2C43E784F35015D9040BA34FEAB6A6F089504 3A40A9E9D711A2721D3F4998371430FB3C94BFC619559B97D49627BB630F4B70 9D0A8FE4E916235335C3962F3CFDB04C4A3CF714DB5E260F4E66FFF2F27CEF2A D4AA26BBCAED23B8BDC98F8F453BA27AD7758537561E766B82DC3032E92A9EB0 125D98A22C5466AF069BF72A9BFA052A8628FEC6A6AD0B711DFFEDE3AA2D7CE8 34EA487038EF50F953B8B4471CBA6FC3C53877EC1BC94582B1123EDF44B4056A 30F49394BDE22CDAD7F01951C7013D26979277D18EFA594E8F4F2B5E615187D9 39E842EC28461B9ABA52020A127D2CB9002A673A435B13C10602EEFDBBA6BD49 9DDEAB9E68D655443A5C2492BA061C1391A51592BA8C353A6F6A0708E8860184 2B5D031D2CAB87D618E9F6F7A0BF3F66B3FD5A25BB91F7F1F5F99CFF56EFF4FF 0A35C55658001ED2E97B26C869292F6274D433A5443179DBB8EE987196306348 3F9E87C6422AFFDD30080C9AC4EE7FE5E2DCBFEE4974331F4AAE479FD8806D4D 9C2B85FC69EB0453AD827A1E767E5C484BDFBF5C8D6E2B3C96298B390F22D757 802643A79D5E29CF3AEDF0E12CFBECA4663444FC87F2027571DBA9ECF688BF28 FF0DDB3AEDBA0FB28447CB4B5D5205F40C1E7A525FD7373392EEFFD910AC82D0 98E71660A1B3227C4A2592F3E853CA4CDF64DF19A52582E167234F4036FAAAB9 5446BE102DE2BF43E82F0112C2A20F15A3F92C6571AC761665A905362C4F8BDF AC8705519C99862CD9C0D75113C4AB5FBB83C880E46B82715B5628890D9103AD A2329638B95D93C4DECDC5E6C588C9D5183EE6FC28FAF9825F02DCA567306D93 5440987A81B51EE7291107A08F201C609FEF91A8F0587E8B13D4BAF74A5A6815 DE9E4441F46AF8E1DDDFA2D611C889614040B144A5EC064DEE4638C04EAB2E37 4CA8F50FB8C4D65BB296DCCCD39F1F554CFBED96670A91F515CA10EF896874BC 8EF48C6447752C70FF5A06F928DB55586354076773BFF7E94C4C3A7A1C1F421B A9B4E3936EC26E0C19BBBFC90F021E877F54B62108F6DD1C7F6D5B8E64FC9362 E173F01BF2904B7E5A08B3543611562C2714099DE7D4FA330DB148B560A9601F 42A84452811CE213DCE782A0D7809CFD954D6BC1EBF2BA4D1B18F50FA8174C96 3E0120E266AD5DDB40B3F6798AC28CDC5C3C4BC34583528F5B5DC8A222B80B59 A3A93DC715D061EC6915E6E6E21A25425C25E8747C60F170D61047108826F96F 7830E220C108B441B6EA3198E33C49BAD8D43086E49F5A2BC7958A1A8CD011C4 49045193394696EC3DDD0BE084E8F2E9F0B9496F035C0DEC1CE11409DF566428 D50043CFF5CDD1092F6E0807E660B68163BCA738E8D98FC6EE3F713164CD204C 0BA84FFF4F33F47BC31750B448603D7ADB9AE92FA91AEBBBEC0DCD66980E6955 CEB425ED07115B24E40F53B29B9D840842EAC691B4F591F866DF27556474B485 1C6F53DD72499847109B16C7093984A6B8487D4F3870DD517945CD90E648C1BB 8A6861E540FCF9D75B984B5009B5CC760CBE297042C240DD624111670B703388 6FE6FC0E89C6B4C88F51DFF3913D0CC1FB4770C8CBEADD4B86393605C0B6C468 83CA5594754411B6FC331EF56D7CD6D247FAE42E966583C29239A8F862348D29 60B177984B6B957E733DB4D275015691D91443BBB13C2DA96097A29733CDB284 42F89C85A7A743338C9DD3BBC4EE53F695E5163E6E1ABE5791ABF100B198B9B2 1C21E2FA2FB4AFE7F9BB2D381260CDD3A2CC05BF513AA1E80ED69FA27BC5ED5A 21445BF00BC2F997B356D94AF13736C6D3B0613EB6F4CD96A685FEB672661DCA 206105EDC3CA07900676EB2FAB37F48D2E8207BDE1463894DA3C5B1488AC1EE9 D39DAF691648048F5D7A384B8927F8DA2BE3602669F71D80686E427F395134E7 7ADCC611BA91AD4B7A0237213C60CF2C905359C90795230344FC3C50A22BD44B 55B2044792509F50F5C21F53D9F9E9F063ADBED3AB99E2613B23334FE8DF70B4 6120F2EDF69F50BE793EE145B9FF9C73179DE640FC2ACEB5C6617F918CEEB762 4CD81E665B2E544864D13230B058717B207D3CC5D6647D5343DB4D0356082392 871EFFA896631A7E0D6477942B632074A9A4EF7B09D4701B1639BAAB4E03A40E 9B54A7A4F845CD63F88831EBFA4FB847847CB98F3455CB5957F2E0A0F5623645 DBB5C5564C7F8B117D6E27E65C0F3EA81AE67B4AE4B201E7C4FB0A8364FE53F5 41A7CE8F834C2C4B322809B353A5E63BBA7BF3B7DC1A85EA700BD287C2BD3FC8 2832B0BB4695FC937FF5EF06FCD87DCE6DE793C2B1EE10E6450352C17726155F 220D550B1759E15AB2C1D5968E52C8080CD280E99D3CCC0E80C2EF8BBFD96001 A226FEED7311EFB4B67F424B557A877379A15BCA54780F0CD2CCA00400B9B39D 981C6B552AFD2506D1B23618FA9AE6D8143CD7198A8482CB416CCE62B992347F 337D505A4078713BBD91E5535BD58EF0351EBDCD749CC24D4AD39F8CECD7D6C8 139756680A4C03A58B3374CEC658D30160AE4863A3938A891BB59CBE02BB451B 1BA4B2B6E68AB61DEB85F95E3C909B8B66E220B9F18280161C279F10F7093CDC 100A53D542F071CC0A5AF834DC1D18738F5DD62A5573E884E1FFD22BD810828A 1EA47F8218C15A2E97CBC609927DA3CC2B802EA4A0D7EB57627C135E3B065905 F97597D818A2C5CC6F328AD25AD11FA50F1E4FE637980B7474D6F85A521892FB 72989AABEBE02A2D0EFE88A6F67AC29F5D8DDFEDAAF465C439983C6B84389FF7 A6434462BEB7B07DBE4BBA61ACD4A60C55B5C0AAE527DE381DFECA2E6BAFDC8D 310364ECB42CAFF72BA93C067B2F02D1CA7C34AE7CDC46787A0E234C8BE8A928 7A6F3DDE0338FAD532A9886E8E3525B85DD39364AB03EC4C0DD25DC179CC1989 1BE232E387E857C78332D834679195E10F1E7B87B7966DA3B2238F53D1E13FE2 8F55ED6A92A750C7250C9B91E29796621E7E9520373214D7DA81B2875A986D33 80382AFF6DE1F829F048E57664D9C4ACE91E4684A51023943A4964AB5657D610 3A5405EFD4CFD1EBA684243E15093C9667797BB47617B66054EE02C41FFEC45C C1BAE8AD56B00D323FCB1D2744F061FA16E161988741A319B1564E04BA210996 4F9F02A3268CABE450D166A763F5284954564A1C86B76544C5F5ACDFE0D758DB 865A1CFCF9FE8CD5F9C3B2998C56468FD52DF8EE60C6935A3D221EAEC7714E3B 301371C7DDA0B03A2416238F2B47BAD3A2C5021C886DF51C695AF9C87A864B48 3BB3FE0B355EED5454B59B25A0D8A1B8CBD356C24F64D9B55E16C30C011365C9 1E0380753BA3EDC0868788D5F50B9353D0227BCEE1BE36998B2622C0759BD66B E4444250589F9CEDE766D8B940770CB6B89503E925B35C00CBEC2873D2DC4A29 0823FB7A3717B69A7DEDBAAECC067949932728E89BEECAA91DE3AF9BF070B9C0 30EEFA8C0A55C8388CAA2F0515915C98E67FA095BB98967D14B0DCAFA9622E4E 2E0EBFC768D80585ACDF28D8A5C2B6EE2FE7AAF62FFB90F569F84A0903996DF0 C1D5723366C436E4088F3E2BB9B47F9789052A71CF5C49908CDC1DDA194BFB89 14D7E3D7D4D72A150FD6FFD8303E9DE5A97A71B808B8BDF2AE466F31BF5D7A4A 44F81230BBE2B456A221E2F72A8B59F8FEA8D31F8A005A5BD93B9F49CFDC3DCC CE2B67090460F632271C7157BDC2F05BC2749FD562FC28682A616A52D1B67654 DF78B7843A9EC26A7DE2EB168F874904C2915B97534B2D4D9F74A9573A771D34 9F7BC855E8F794621BF6AD471BCC347E2DF5F620F5C209E33A4CBF1EA85AEA87 4492A77342DD33EF615FF34037D660B713C908786D9022051B825226545827A3 2AD1B05D654DB6E6D261B4E8AF0933AD1F0FCFC7201E1A7C1B4199F160C38676 21ABA2DDF1CEB655B3EC3226E0B122976EEA998F7A5241F062E54AD1DFD6ED26 47C99A439E0AE95415059179867CDD3F0FF751F3141309F40E00A6C7C28433E4 F649BCD5DAA64177580E05C495EE7BCBCC5FBF104DAF360CC2711386655B26F9 D349D887EEB32ADE595241560FD5924A1745A22E6A01DB9C285EF14596EBFF0F 03F36EB2E0A7C3864F819EF7B0855121292D49482F046A55CD7271FE03F02EA5 886864D9D8EC22A68C23089EAEFFF03DED6484D8C341861EF8B6FD3C5BDF5AC8 352DA4E13A1E30D0CB71E090E9CFB9AB2CAFD0CA7C34AE7D8E3B2EB4666834BD 9CCD1AC2108348AFEF6071796F4BB2FFA4A67ED917E76A109FA2DC2A30D744A0 9AE653A748C1D18FB52595D84E87F1C1FB6B2F32667FE203262C66627AEFFED3 92B23861E5EB238BB4EDCE09DAE1C65BAFC198CDD1B45D42CDF93E16BB82D35F 821E9E49067E966AFAB2AB52928F8DD6359984071FC37AA652FB834A09E5BD93 3AFAE161140E74C6531E413E8FBBFC42BFE8A464B71EB1D8CAA93B33D7BCC3B0 47C7EEFCD3E9FCF26FF9441DD9BDE68D77AD7251C06BBB9A2103049E8827CAF0 F26BEF33F656A690235DEEC623CC519AFA82DE2AE16FB99F780FD7D8290DA40B 9B604AEF36B529FD184239E7D50561A07428D28E51B55546590A1AEAD4B7F2B1 AB8C5B9022C1FA03E33F8F409B24911AB8BFCF6EF4A8E415263C789F89063E71 C0910DC20347469380B7FC1EEB87D4CED7F4A361E58B61C91AFCABA35C03F978 B9FB5257C31657EE48504C355CE893FE3C553274C641DBC4004F5D5B879CC5ED D3F21F867F6DF054127067DE86189F0B59A1B90FDABCDFEE61423609D888EEFD F4A1367129962110C651D9481CEDDB8C5C2576A59AED64E95F7ED042AEAE2F7E 81AC0C408E593DC30DCAC334EDE9EE27D932B98F040DDCD195D6155607DD2038 970EB78221A94C52BD4F0EAC65F1FC10E5DAA93C17266F351669CAE56F42B68C 6D01E1EA03AE554D63CE76D800FDD9CFD89F80A241EAEFF7EDFA41794EA25CE7 97BD5028464D2CD45B53834B4AEF8BF0B9E7C6ECDEACEC887E8790A47A93F668 A9095E5FA1116A122C0E5B74E2226C654D3187C6CFD8807917820423DA3EC1DE AA020EEEF2280C44A15209EE2F3FC1776875308CEAD38571E7BF889F287E4594 971A83605E0B4169D4A23EE790515223DF8724054EDAD905F57918FC0BC64F96 514B4BF7DC9BA79E763C22C977FB6146B10D26FEA1BAA7BAF21312F78D1625A7 8E242D743471DB5821408AB786E4A7EA9D35E30E85533C617689F95758FB2C7C 392E759C299DCCE36689686DE0C4DCE32649493650BA194A6208C5EAB670B170 3F2C70BF0EF0E3BE2FB0A79224FF4ECECD6BB3388C6D06867A0E5E3DB93C1B2F 464C23E44D3132E7D4086E3B59B1D13F49EB4772DEDF8EDC4F603217233FB7BE C13C28648E9AA51D53F11FB896839F97AEDD8834BCA53CB0021AE91FD8E95E2E F8A094093AF556B9639F508A401542B06821FF9DE1A745FE9AC5CACD5E8E1053 911442FC15CA5333751ABFE2C617D38FA1DC332BFEF44AE569DC631C93EC54D6 261583A695F5A392867A57F59B741EFCD2DCFECBC55D1EA5F2317601C9DFE9ED D1EA466210FFA905A8F85BD58B98991BEA58DFD1CDED5C9B086D42CCE632DADA 147941917B879139E016B0DDEB8446BA017FC8EE5A354533D667B0835F5D027D C2D580C16B80B3D05CC92C0465CAE077729F0A15B2DAFC89DCD349B3F81D0516 C65526EB5C10E45A8A85D716EE35FB9AB201FD7C89ADE5AD925A174169DA20FB 61E96C73A143DF964C20589EF24A0FCFE6195317F2FA0D2249C0D8E649C3D9AD FF13332EA2E4C9CD36D8443EC8F027B61CEF92C6A6B72DD4ACBACC16E429A9A3 F5F29C1631360E32F8C1C93ACB22F810B86D2969A7480F486F62F8488BEEC74C 2C1AF13BB92BC578E8CD30BEA6BC8CB68ED730F54CED0167605FA76AD7B7E88C 7AE7688E598F91C471BD65A542E96D64B1EAF19FB4F1234308C48C2DC86E2193 11ABDB4C6189C6F201627C693691A86DD07FF55C30FDB3F72381E09C6080FD7C 9182762E5001E30F52A216E0B71E4D2D4E2F3B20F95DF3A11FDB2D2B5B5FAA66 C46226D5E0C77066349770514E5675550FAC9394FB27CD2C2F974F1FD58C04A3 1EF53A8AB3B2202CCA1CEFA66228E1480A0709436C44BD3319C40CF888AE4692 5DBBB52B15CF3A518F627F672135A24D5DB9B2EBEF04C860AECF231EBB5A3BF5 6DCCD5E72FE4B6DD29E896691868A7DE4120AD06AC573F5608B8449B38E71CA0 EB5CDA3F942482EA7973661170F81DC88D54DD5B92323F46F833DFA757107E9E F62A47CC50FAA1B68ED535C3E0E1073532A05ED339C8D70B3B9864808ABACD23 AA95E9FDA43D54C66A675FA074E0A5B8777D3C07850A09087F36852B5351F35D 8BC4DDFCA35CF29CD5E3DE118A741FAC4DED36847F2E2C6CFE08669301722D94 376F540982958074E7F1383C409652F6C99DA39FE90B38221E75BC1ECB93ABF6 B00F410A0C5651DB418566AB350FDA1789AFD88286AF3BCB42B98386F7BC144B 02DEB8940D20A6B3062F0C4244EABC50923390064F1D027A8BACC3DE45156E56 4A942D1B87F1C4A76B0D4D6801AE792CCAE3009BF25368B31B6AD5476FBD3BFF 9759EF463EF5E78E10B7BF64005B2ABE0E8813950A08A1808587A98E0021D0DD 751AD515E8278F1A0759E85D8A084490BBB0F8206484AA36388B1013643D3198 3509078847BDAE08E76FA5BF3E3A73C323CE093DCC148E3C02C2DE1E26C94D5A 40EC8308ECB02FF7DD04EC1005A2A0DC74D4E587F10A3EF349E828F69FD38962 2F0C74D5DAB3ED6CC9F97008ACCE74C086A503948DEF1AAF58FC8BEC703CD360 D32098A56AC776B1BD08442052A2A4EF6C8798F7CDC102AF1A2009657254762A 0793F79A39DCD6ADBAA5EC84A7ED6018BBE727E5D477893D84F157074B24C13E 8D4881C7DF8ADC13EBA0D89745EF93B7616EC5355600BB0D2B630AABA3CF2946 AFFD0B2B724EF0F28393F3CB6A4DCBBA655E3D6E27F87E6D8BE12A15D35E1E75 D36532B9C5000C06A58822444593A1038EEB23C7AFC9EEE3907DF8232322B09B 230015E014F1B4CEB866234266440AD3686E30ABD086CF9C0926E711F0757925 5DEB3D39C8E6D6F0C05A364A0DBF90F6E32CD28887F7E237E04093E07A94C973 462254BC1B1586AAC29FC7F15A80FB5993ED22E79A0FB5BF0F7362CFA24BB2F3 D4EF7D39E1902C53053C27E2AA49C4DE54A05AFB1AA6C7CCFBD9F72150DE259A BEBFCA5C7E828BE667E9C72222B84C4C79C2DEB885A69861DDB635B02814BAAD 9672A14E50D6A2A236AB35C6DCBFA1165F47F8F52B0787EB4B70BFE3CAA8B511 A630E8148A51C1394C7C321156CF52EE7BFE07B6C354CB65782464D2BE42C0D8 14EAFBE88DA3D5C90614F22E02626ABD343F3AC0A9698AE84CB97F1CC421D34F 98B69FF4C335B95F4222A8BAB77662B4A57A4B574265A679334D5EBCB073FF69 66BD9322B1C2253AE85AB38889B26761BA509C7F638C6CBC4BBCDBBBF4BFE1AE 855973129978F707C87462B67509FE6EEFB5E0949674C34768F001827F12F1BA 77AE866711077C30DC0E40C2D8A6EF4D85355E596E26B675E8D223D4E55C3580 5B79260E90985DA5E5B2F43DE7713D5E67080D2843D44A3585E078615BEA476C 88233D241D3A427F9B1AD26ECD535E46C137084A835CD816CCA936D0011C53E7 B33D5B50ED7BF3F41289F48E394BDC963EB1AFD6F14F0C146E0F13B03E76B389 8AD8E81E41F14D1682A113D8BA1482D9DDFDE71208AFC351B62E028C3D50BE01 FC9CD5D5F36E28DADB469201F41E9F39098B65E43FD1227A26F6FF812CE452F8 B5476C28FC1B1B3E5FEF3A3B94CD552E29288AB0A3ABCEAAEACBD2D5E9001579 738029B0E7F635C6C4962340187558084D9CD408EF7FDCE23F465AFCAA8EAAC4 8855BF64EC9BC75371A98095CB51BE7FF107E4C6C21079571957B2AC35ABF77E 9DCBD599C549D3B40A36AB846859C7BD9F87A2FBC724621FC7B305F02742A66E F2BBB6B21671FF62D682982C4E8F6645EA4A7D875E03774474BD86F76AFD4053 61E9AF3C9B374D730501BE61106AFFF8A463406722AD2C14D1A81C08C2A31E60 42DBCDBFFE4056E6AEF59CA261835523196A8921D1BE0013F8B3D6F05793FD18 3E767E98289DA6CA9DC9E2EF9E697998D2367E45AA87B3E75A57F64021FAB21A A480FE7095000C29AB92E6D299B2E5EA7AE1997A6B23E1F90549334F62417196 89BF7E9F62484C2816CF5FC2ECB7DEFBB11E63D70CA13D96BF3DB3B95F39A41D 2E0C84ABD2FFD86525323ACE4A85A8944601CEE9D157445312EE9EB81873DD63 A1BF3256BD697289C32D8598046EF6F6646629A7C29D5B1C5855CDB95882C2D7 73536D20BEEF480B4213C0F02826D89B76300F6BF3ECC9C1DF3AA2C91CBF7D8C 2862CB42FE32A3715855D8B7B30FF83EAD80181F8034395A1ECCCE5BDE7A2C9A 124900DD8F1732791A32ED4820F93BE8D15A5B5960F824BD17A8455F537A947B 9726CDB5DBA4107593EDBBEFF3B140B7CF51BD51B099045DB94A946271DC6C00 24F77C781DBE53479E423426F3FE3004F4282816CB898B570C171FF63B4FC904 8D716F6B7F3BC9AABBFBF1DDF2779CDD19CBBB60DDA40D5DFC85ACDD2A0FD2D7 6402B7768E5B1D7CAACE9241F5891F922CD586255D1D9DDAF0910E14F3A2F8A4 631394010C96EB7EB6E3009591E12C0C80F511D1FF14AAF65FD0A74E56361BF7 07826E5FDC23C1AC2A50347CA313AFA7CDFA9E41F567AAD4784BDB4D1AEFB4BB 108438507C49652C2D62EE498B0DC3082DBE1386640593C9BBE665F0194AA415 8DC8F707C23921E5BDD170408D11B9228F00CCC5EA45F51C5AE792704EE9BAAC 9A4B9479972534CC6BFD9187AE53773CD4EBFE893D981C973FFF2BBE03070EEB 729BBA16875115DDBB97E62EDD4FABB2953D18E492210C07AF48EF4AF406C1E4 A15DFA3553E619D7C50740304B50D01E03AB8F52A2A0B4E5AB6A8EB244E1DDA7 7B4B60BC0FA3C2DBB142C3B07C82C1A49A7698C173FD336643FC71CC1AD0A157 FEA076C61C85EEBA233B836FAE739A19B4E2E01E2CDDC937A766D77FC8B21BF9 FC22DCF7B1A82791D0622F063017AEBA2D7F5C23E886A052725A6A32FE07C847 40EAE70970BC5497AF0C9B4DE429BC5FB83999046A714F7526D225EC3AED5937 9655B968A287C71465C2B6DFE0B817C1E91891A77C647A6DFCBE5BF85F907B2D 89A524F0525AB4B180D08264A30FC33F7330CF479780B57AAEF15F065FD94206 AC9C16FE4356740797B5BC11E83ABE058CFF063AAF6064349BF631E98CF062AA 948CC961BF1309CFA9BCABF604ACA0995C3D822C04EF947AEDE6EC09EAD88146 D7209248A0E9BE60A511EA78E45EF4B1FC459988D7F4AB483139E4882C89FE36 E53F25FBA01E2F476B322B43D601DA18059CB07C04BE96C7FCB279E3A10A2794 38D54D208C9408CBA31360E0B7BF377E0B98B105D9A833FA7C56F76FE1A034B2 2BA0F76CAD724D164FD310FFDE6952D66EA2C2DA00284AAF569C74982E38EB3F B9E4BFBDB1AF88D98D7DBBAEB302A70AD014CD2A1D8ECA99BD1F8D94C1E5C0EF 5141C116ADCCD43509D25ABFC8A78534D291E0269364E81734455F5D714EEDAA B57F6EBCC8D11C839495D3CF474E4765926BAFAE5AD115E4729B21E856D17E8C 73E348B0F0AC05B19C24C965E4FA9EED419104AC058A019A91A15CD6B19C9E92 51806541FDA27700AB879107D6FC22F4108AB175E82B73732E2754D9831A26D4 A1E37D57FFF6EFFBD31B9F0C468C4A426268E5A2A1A2968B7464EFAA60076797 12A1990B46F8A0AD088B9C3F452A1949B2EEEE0BF77AA8A8F467EBCE59B03D81 5192C53954D6693AC154D19C78023B403983A3CA52ADA1940CEBF4ECBE86F8F9 4F948E64E9C0DA0C7DE830EEE10925367F597D584789528FAF547E2B57C19187 33F36DAC93B4CF7CE2CE6991C178C8B67501FA1FF266194A020D9FDD06B9BF3D 12A818C817FE1E4FD3FEDFF16CB766DA527A114B8386B257FD4249362F0D60A3 183DC1E55A6EE803D8B62AC292D085355748A16826328B8602E5559D6CA7F29C 624083A8D0AE8CAFDB63045E9DAB86126A2D31C02CC945FF2F528CCFBCC87513 04799B17802E254160AC84A87F8E802FF41A590EC51D7543DF2F8691A88A928C E20768D57C67888FB6375F02D35EB778D2D7D7EBEA0F58D5745710A876DBFF87 C80E421454612ACE12AE7EFC44920C30A1B54D49574286A495E382C35CDC1457 533363B3E06C5617E26797CE5EF25188BED52AD9DC2835D6E413B4E7F02571E4 9402F96A2326BC707B343704C83631E2757B0FE3A0CBADAAB4C8972121A43087 9B7D8F71D630F8DAE7E913B6701DC5BFDFB598C5FF58FBE8583049D9EB6E6A1B C908FC1052BBDEBD70971490B27189D226DA6B27563CEF2B305A519DC8F70E8A 4D42C98BDF026827BF4B4F8488E5B283D9FCC5B5BDEB0F1ECB8CB713F7E2F81A BA0382BC6F5F2A1FE20B11CC94A7C7BF296DA9883C4FB2FF977BA4D39F6828B0 3EFE328CAD711D55242029E183833C6E904E1AF61133B33258A8ABBEDF324F0C 61C407443A50C827397359B042F37AC130F7E59B359F40D72F74D40F725DBC1F 35C1AE093B74A454F11A056B37541E0E6D3CBF0A472B5D89920A82796C55A074 4285020DB6E372928B769A5B8B85C3655360271EBA2EB6C5A9CC88B245DF7850 0C2543362DDDB90D9EA05A3BC56A59103E33390C89ABC2DAC18FD75D3E91F965 8F7786D76766273AC6E2339FD1F0DC62EFBCA9872A4B56C72E2EC3AF1212B464 393ABF4FCB0593B1EB1B955D5B7D1A744549CD361CFEFF44B1714A5F3B70F921 EB359FF93C0C91AA56C1E0AC03FAC195CD40E20EF73E7CAE75DE9AE457EF670B 551E6A1CDBADC4D747EBC5D70AAD371E93696238119E879090A74F811B712A09 2C50AD774FB3D1472DA1698BF66E23F64283F5A44F44B46F2136A37832AAE303 18029035AB98F8EE4DAD4EC11FD6C135A5BEA7E7A315FF5B109328D6AC1B2C1F 12AFC8C01BC24F100874753CAA7C9B2E1ACA85FEC0DE1CD9CD3FA3C6596DF25A 9D714C0A0E2CC989BA3E13B9937BE6851091083D13E96192FD1AE01EE8266966 42D749AAA750EB754BFD5D63746D0225D674A193E8732ED95CADBD514D930EA9 501C4B5C861CC73EBDA7CF0867E7FA56E5E8A8021DEA03476947D6CE7A4B1C22 BD2F3F2707D2E8DAAE4756C45A4D5C7DDA84D4FBF771492F489FB17B8F376A73 A11BC921FFF304F712E0C55AD8C7F89B184D876B47A34FDC662A1B4921A65AF5 0FB9FB8C30200CEA65ECF23E13301EB7CAFBD8736B04F0AE0354A749DDC15C7A 56AC528411F70EB8B855144BFF6965F99BD684C4706D264296F79A740637DEB3 7815680D5E43CE3170BC024B97C252DF6F2867C814D94A996DB26A6F5886A4D4 FF35CBFAE4961802E87AD786E1EB4B4683B5C4176E88F0ECC412025CEBA52738 BC8E48FC9F9A9415CA1F44AA34E1B613F034DD9E7666FAFC856875A1B4BD6EAD 0E267A5DDCF5BB138C07FA99E20779E6599F7990CB63C9DFAF7C3EB7A1463B97 F6C774AB136A759DAEDE71EE90CC007C22809CAA42547BBA42E4EB20BA4E9945 275DBAE7958CA89F44423F8DA7A080646636ABF7B0B675FF213204DD8FC8D6CD C6A609D0BD65D46A345A14AA8E5E7AAC0723442B1C4ECC676DB91750385BEC07 C622DC7F1D1FB8C7EA81BA35BB2DC3D98FC009CB73ED40EE0776024E8E5903D9 E27078DC9DAE4F92F5AB6695646FB0ACCBD3FA4B84146E459DB1EF3DDB7A256B A2F485ADB0D6FFB3B0892CE7A30D3D8404E37935B6A3E96433E542C810E071DF 095A09E541F326B6D4DEA649C1D73062C6DF8066424B20F3EB2835043C1625C4 9CAD1B0F7FFCB5ED4B4A58942716F289A5AE174964E161AC1668F8619F1BDA05 0E4737E3C88BBFA7B7CB2C03943E6F169043806A34982D706BB5455F27AF2CBC 52AED4F88B0E347C0C5D656457A5C941BE9E96CCE3E24D41A38BB59EADFF2758 E1F2C9A4B6613B2853AA5986395B32EAF358067946D06760C4B29574AA4FC902 7A635421BE44390C4981895C31B2E9E7133EBB71E454E17F76144B832EF57692 916536AF614AA0F7A22E0D7FD888FEBBD918AE33719F42635DFC97AC4064D13F C234927530EDF9646A5110B1DE674496B5D250CFA823AB14FB3F541A8B236F1E 0431CDEFE83AE501BA55CC3BAC2C281AC52668D6CF03A2FFDCD0CFE61CFB7DB3 B9391F64FFDB13E1D9765E3EF9A452D9FAB99DB9BDEDAD7A0A142EE25C5F078F A55C8377D763835C874D684D87E0AD8C4A9BE2DDA3F3A31F152C2C114CA200A4 D7A119BA4A1998E2E208E4A45FF765B947062D7B650644FFFD53ABAF7ED90440 0881167110D57E5D7F159EB0D1A019CFAE2E3405E0325CC7E1054D5A294D8357 4A0EF6E6ED863D6FD761507CC208303EB0894AA8055E11F8A6003C62E3457680 F95C8DFC7F6D84E68EA1A52ECBAB6B5002A29D2A740134D41F98C27F902329DC 7AB9BA8A53E97F41AB48F77FAE2039F97ACEFB9E9300DDEDD69A0C9D3D658AA5 9E0478CAED8CC949091746923DE8E2BFC410952C12E2C1FF605C8AE6055EB455 7B817F83DC64C51B7F25DBE06B551FF78594BABD05978378CD614A708887BA8B F54D72A339C600818BDFE9EA4B5BF63AD6C465F58B6D4B98BB1E0BAE8AD63AD1 E6A06BD7806FB0672459E515DCF93CCABB2363E8A6748561CAB8769511672F64 273857823503C62D6C29F17FCE16343E4EAA64BEB54E33C267CC6F91929C92D1 2218A56B10D99152D2C0DC9B7ECD40CD80286A5A642C9986FE095EA6EF3ADD28 41EC7CFABAAABB2FC6F2CC562E4131D82729D416714AC160F2E87433FABAB57A 0180E4943F6B201BAB120F8F3A8E42134FCE40E92383684E5856E91F12F11578 E00876D791F467933241746448D028690D5BF025639A393B2B273CCEB48749C2 925B8E231CB29D4FAFAF2590E649BD0B70EE46A053E27D5DB5927A52A5072A24 07402125FC775FCB04325FAF1816456BDFC9EDFC73E6D40E14AEFE711C698C45 28BAD2117271ED582504965871517D388714B7A602A797EECE522BBB50DB624B 0AD24BC457D79D425A10514B120472AC822B35140F575C718BD176B97DFF8C14 DC5EC096D6357D70D2969BF691BCB42D7892ABC7163E22894AC7BDBD71E4AC32 DA05C1AC63B8429F12606D89676D697A55AD87A8B59F32D145F9D251CAE9D5E9 54CA2135B75ACC211C234D823EB429693559C944B1993AF31AD0EF0CA046B1BC 99F974204BA9FC43038E3A45BD375B4CC99A003A51553E480DABDA3D0939A252 2F8D6CB3BFB57FF96F873B432E64FA3837669372304A25F4B290F0883E860E70 AE7C9F4E7650DE66E1FBFE707F737DECB2F63F19941DC474672A47842D464D36 6324D6E4B599EF9120520A5E2CC3ECD66767C0F4B3071771BE5760E0E2F7ADA2 03B111F0A36B79D86FDC3D14B7C1643A0AB9AC2254F68EE2B3DB067C976C9461 2F6FF5254ABE6CB0F5D76B63B31BD2D3E13F02654ECB6AD360E7DF52207AB680 CE94822223FEEB833720C7AB3D8C99CDEEBA7DDA000815A356FC07D98CF925C5 60016C7C8E55903BD13F03F1F9541A24D42AD7C96ED88AA20227AA0D3E01503B 60947656FCAFCBF15276F1B7C3C980ABFA5A9A74F49C912EE6CF381509BEE6A8 EB8E6E2BB6902B62D7558AA2D259ED01D14C0C47D74C2126A7B7DBCC8C73A753 D5C2CD60B4D6A27DBAFDB57FB3A89E4A39FD56CA30E0C6AC26787AD9D5B4EC56 CB05A2CA7ECD0DBC930D302EB390759FC26A8A03F3FCD1D9CDF2A9B76533FD78 69B13E25902AD368AEE4E6BE6909BA17189D3BB09AF77B0319A7686502E7065F 58C965D66210AB3DD4A2FC739B342EEB632D7DE7D851DBD0B1EA0117AD8656F0 13CF0A0436758B49D90C35BF4640F9A453113B38C5E2FF74BC1C1C1F9F238ED2 E301E1794F17FA7E89E3B3FF6D5A81DC08EFB95563E8DC89DF286A765C9B4886 4D2965096873CF97A9D7875A3F9C53BB7EB56BB82F8FDAF8725C8DA4A0E9E9BE 57A9F9DDB560B3052D2F36C52A49769B6AB8ED82C5DCD3E2CB029D5EC2EAFD43 366B4234AA0070B8E11628AFC07FC26FA44A5240554DECDD0DF8C2A518720007 7DB6011E853CBBC1CC58567DDA88FA5FE72E06FBC2BA706ACA205919095E9206 C176E3EF415F34733F33FE356C6AE44FB6662118848290E6F3B5309562E6166D E23BC05E16B62AEC365CF01D16703429F1F268686B7C49DE27D06D34DB09BA11 FB8F47 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMMI10 %!PS-AdobeFont-1.0: CMMI10 003.002 %%Title: CMMI10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMMI10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMMI10 known{/CMMI10 findfont dup/UniqueID known{dup /UniqueID get 5087385 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMMI10 def /FontBBox {-32 -250 1048 750 }readonly def /PaintType 0 def /FontInfo 10 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI10.) readonly def /FullName (CMMI10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def /ascent 750 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 62 /greater put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3C05EF98F858322DCEA45E0874C5 45D25FE192539D9CDA4BAA46D9C431465E6ABF4E4271F89EDED7F37BE4B31FB4 7934F62D1F46E8671F6290D6FFF601D4937BF71C22D60FB800A15796421E3AA7 72C500501D8B10C0093F6467C553250F7C27B2C3D893772614A846374A85BC4E BEC0B0A89C4C161C3956ECE25274B962C854E535F418279FE26D8F83E38C5C89 974E9A224B3CBEF90A9277AF10E0C7CAC8DC11C41DC18B814A7682E5F0248674 11453BC81C443407AF41AF8A831A85A700CFC65E2181BCBFBC7878DFBD546AC2 1EF6CC527FEEA044B7C8E686367E920F575AD585387358FFF41BCB212922791C 7B0BD3BED7C6D8F3D9D52D0F181CD4D164E75851D04F64309D810A0DEA1E257B 0D7633CEFE93FEF9D2FB7901453A46F8ACA007358D904E0189AE7B7221545085 EDD3D5A3CEACD6023861F13C8A345A68115425E94B8FDCCEC1255454EC3E7A37 404F6C00A3BCCF851B929D4FE66B6D8FD1C0C80130541609759F18EF07BCD133 78CBC4A0D8A796A2574260C6A952CA73D9EB5C28356F5C90D1A59DC788762BFF A1B6F0614958D09751C0DB2309406F6B4489125B31C5DD365B2F140CB5E42CEE 88BE11C7176E6BBC90D24E40956279FBDC9D89A6C4A1F4D27EC57F496602FBC4 C854143903A53EF1188D117C49F8B6F2498B4698C25F2C5E8D8BD833206F88FC BD5B495EB993A26B6055BD0BBA2B3DDFD462C39E022D4A1760C845EA448DED88 98C44BAAB85CD0423E00154C4741240EB3A2290B67144A4C80C88BE3D59AD760 E553DAC4E8BA00B06398B1D0DFE96FB89449D4AE18CE8B27AFE75D2B84EFDB44 143FD887F8FB364D000651912E40B0BAEDDA5AD57A3BC0E411E1AD908C77DCE3 981985F98E258A9BB3A1B845FC4A21BCC54559E51BC0E6C22F0C38540F8C9490 88A0E23EA504FA79F8960CC9D58611C519D3ACDC63FB2FBCAE6674357D7F2285 4BCC9F54D3DA421D744D3A341DA3B494BB526C0734E1A8FC71501745399F7683 FD17EC3044419A88C3979FD2ABA5B0130907B145A8462AAF0A9B511D2C8A7C7F 347FF6AC057E6512902BFD2918E2CD31DE615F5D643764E900B60287670AE18F FDE15545D8BC69591A8CBBB275AFFC9B14BD68DF0AAB32268FB84844D4DBC7BB C591C1AC5102C50A9C7BAAA848DA88B0519F0F5F0813BF055CF0E3C86F633A04 B779D2E8E656DB1E09A66A85FE21CA8BA5523F472A229E83F2C4E91ABA46C733 F3C7B5775B06C97782BC225C46385BEBDC61572458EFC5CF4190AB7A9C1C92DA 29F84BAACF552089195966E3AD9E57CC914D20B6962BE80429A16D4DF1ECAA66 36C4343FADF0B2B48F12E2EB8443C4AA29D00949255F3968617F98B8ABD4CC12 048B838EE243A21AC808BD295195E4AE9027005F52258BFCA915C8D9AED9A2C0 80814F79CF943FBE3594C530A22A92E11BE80FCEC1684C4F56712D5846B0749C 9B54A979B315222F209DEE72583B03093EC38F7C5B9F9BCB21DBE8EDDAE9BE8B 75ACE6B12A31083AC8348EC84D1D29D2297A266284B7E9734E207DAF59A25F4E 4AA38509E993C5394FED76E6A2F25462685C4C86C6E8CFC9863338EC1428BDFC 74616BB1BC8948B0ED4C87C15B4405F3A7796F9DB3798FFFE8BD0A94E834817B D5E9812E308D0CC920470A6F2CD088FCB80462BF7CB3F039A7DF3DAF5B2B5355 E083A385CD2EAF0FC181E40E96DD7E9AB9EF5C7E6866A13B8A54718E950FE097 EF0951A357114F18CE9933D28B3A77AA71E3CE884661F13284BCED5D5FD1A86D 543E588FF473DC2CF9A4DC312500135F29C2D0174B32018C8DBD40EF9A232883 710A1F2AB2CD11312300ACDF789A9B7B93D2035D81D1C84984D92D78A53A00C6 EDA94B24BBAC1AD17774A4E07E6F74ABD90415965616AD540C8ECD8C3A44EE4F 7F4F6BB6238C5062D63FA59B7BF08BE93FAEA70A2AB08FBEAAF7DBF56B95FD93 03CA406543BA6C9527D0DF01F5108D31A51778A5EB1C93F27B72B46146A353A2 01CACBC829603B9989A87CF64528682CCBA0562A8165B185C58A5C6BB72F5E89 500ACCAAB8ECEFBB2640E99EAEEC4EA979AA793D013D61D8ACF8784FF8D9398F F6A252A709324FB39509F0B3A4E725E82F53543383C6765BE556CC897C758208 AA3AD37B0406E4A79F8F0A6C1983FC73E71CD858C0DB66ED66D5D992978614EE 1EA91EBE191E082EBA1FC040AF19A2202575C2EBEB8058833E3520FA03D2F915 85C1ED337E457B9FEEB0C6EF2735EFDA6E0D05FA641BCF698AC6B97751E8306C 4DF00A39B8581FF53DB8F8525FDB196D85950906CCB59B8EF171349AA3B567B1 6A00819947A995FB383C3C1709C9A2C113B2E40BB832B7D4A0FBA0B16A2C455F 55809CC425C403E9668DC66BE45B71A81C332FD4DB279D22A2959962304A8F18 085893DAC61317D24A8F198FDAB95F3B86F0AFD35047B868A9A17037A2829A02 BAB042F75F349E197A7EED41984C2859754CAFD0251439921C248B463B516951 2E1322C80D73F9CBCAA63A585450275AC2492E4D3FB78E800F788254DB5E610D CF788DF5C70FF99892BCDF16133E34B24B77C8F097F546B87C603DDB8998B66E BACB68BA27462AF54AA405682EC96D701F0D474DECD5F95CA2102DF639EB169E D518162C2BAE45FF698B6DE15FC6E7DE48C336C40A670FD26952A6BAB09115E1 991F0073419F2CC2A1C08BE91096936AA0C37E4ED3CCCEE235476074B8FF1125 6BDE3701F85532D8BB64CCC927CC335281C95EA689706F0AC717DC2CF680C754 E5EFD7FA4BB8880B2B727A964C876D4A223069D4E6001771F0E23EAD2A4BBC80 E76675297B2EF05F52BF4E71B3EE2BE3048CF088C79540113C66AE98B2FD3CB1 B0741A215FD070882C52765009D7D711DAA2508F19AE7DDA15229A856AC49BC3 4DDF40814FF96500E4B9B02D412E94623C5FDCC76C0FB8E42DF56A904FE49D65 1DA7C53901B2EA71AB658A464D3ABDE27D9DB8D9E0B48F64E61A2495AD5D8DAB B5E72424AD017DF37964AF911BD7FA21A5EB4775DC8E95EF0C0EB856B00D89D7 8172A1DE8530767D317B8256103E53CFB877E10686A04F5A08F8DC58D843DEBA FD5F40597588663D103689F6EB3EB14D06E18C8078F2538B43E712DF491FC5C6 AF639256C8C6134B64D560D8476DEA6329D995E46CC4BC78841C59E73648B47E BFA7DE0846422F738454AE77E822A083405289247BD7C478BE4974F742CD6051 E99FBB1D1B3FBABFEE855174734EE45E87D0AADF32B1283B911162A9955847FD 38944D70584FAA6B1A7191C5C134B73F98EB632B69E2F0C0F94156787C34C8A3 7622A029D58F9626B74F8A8A1F3803E0BC20E0EADEB1E99B70F1BD9F980FB751 2A842843DE42EB142A84D5D3138629AE9EAF6F3479C423E8829C8816FA6EFA27 DCE5580E65AA9854B1C64163DC318420CD993C15BFD76A8BA1182860A6B03D6D 22B8CF43CFE6C8AB27C64842E239CAE707D3086BADDE1D7C94E3BC96319470D6 8D26915C575CFDD03271D6BB9DE86A0EB6EEA6E768B224A626C62A9AB48A6EDB 44F70BB5AF991CDF9736D65933E81CC57A78F623F33EC9AF535F2F25FA4EEC90 D50DB7E87F31E971A75A33A301CA6013EEC5A4E179D695B33DADF2C98364434A 42926776000B610E17524162253F6FA638D6581C18F99EA0BD1D2E24D2424ADF C05010D08192485153DD03930C7BF45237593E484F9851E6D464FA10FECA5D9E 0C8CCC97DE029030900CDBB491C5CF226DBF903CFE7735D939C3FDF3A20B70CE 66579B28B99313FEE914E295388C7BC8E055A2E54EA3A8206D3C8F4F7C0BA5E6 E519419FD8CE215F7B8E9BEC604A9E3FE272A0328A24E31997C8A91E0946BCF1 6943A97CBED2AB9FC636B49828BBB8B89E0BBC2653796431224895ABA5DAC41E 1854BD9764E86147FD7624F736F40DE3B7582EDDFD15C2BDE3F22B5A54D7DF10 B87A1301CE85CFC061689A890A321412A13314AE96DCD3EDA75035FDD8F4AB9B 897A2C68263A68457032C469987970648BA2D88B1C5375DFEAA35A917B8A952E EE670427942AEDB3CB599C5746180E392837D371E15D860620ABDB6AA7772C40 A5E346661673ACA530BE3D8E3FFB895E5DA3DC23B1B43C080C77F7E47847F0F3 F3AA5CA9E4BF75FC5EBD18D19F21A7DAA3B11CABC6E4070A15F7DBC8B05EB6AA A02EF1B078EB66D61D6AFE41DA9B36FE7EC9EF94D1EA26282A9871E2CACB3126 2AD49C2D9B50A6E47D8F2CCAD50992D1B430979A45FD9E76182A19964BB2A1F6 51779A2B258DC1DF4C2F3074621286831F3848AC152DDD2BA561E6586ADA88D3 598A2CE2CD048F027CE0008B828BD915887D7785341E8305DF2346ADB76BE99F 87B02173BDC334E9221C8DF54114A6B24C1C5340299512FA6C8C51AB4C8778CE 178CEF531C6D1B5FF0A1BE8EFF767F959BD4C345C52699A29A17B2A230842BF6 4B011217D6D24EDAC3F6D53482786F1CA33169B90ECD499407D37CE9B70DDF78 7B7547B32952535BA9ACD1E244447AE3FCED3AF28717083CF9590A09780984D6 AF0743C82AE4FB3E2BB2856A4153A3967A023FFC35382D6C22D84A924900B6A6 3DDD400E6D2418DA6C27F2FA34C075C902B89EBAE658B3C9A18EEE449DA5A379 337DE95CB7AB3F0970CF1A5D8FAD8090E495570FDFB2FBBA79244780D8035547 C5A55BB21A2270F724BF5D442CDC5BB9F09BE0CAE59B1C2270F0BDACE698F2C5 DE8F66BFB9634904B161F5BA2B1950048300D69BABD312D58D89C4ED527AF7BA 7DA2478EDC2CDEE3473DD8A8ED9D891CD1FC21F23013228BB3281B71FCE959BD 6F8E9059D682A7FCC5265A0620992D4FA8D78377EB34CE3ECA070EE3707239BC 98907DB0120CE42ABA32CF97127E28382BDDFD685674279F588D4F951216C355 821361790F64C2CC720DE97E8ECB57326C43EE47367628E05769E106868B54F4 C33C9951908DF6FC4F5ED2C7787BD8FA591BBB3E9C6C1DA94CC5E38D9B20C886 7D237572FF46DD896A4D6163408EA6CEFAC398EE041EAE29D577E75326CA17A6 B072D47A7B13EC441CE6DAA042ECD02134CBFA6809A435050413817193DAEB16 A5882C8AEA44BCF36E74E9ECCDFE7E19FF5A5DD7A94E5AB4F8702C3DA7F42325 23C808670A0490F5B373DADE40814FF9650241D3D69C91FBC5ECE728F827D9BF C928602E05477903449E079164CA39859C4BCA60C579F490AA455F82B5050BB3 969AFB478E0D4A257B3356EA3CD62051FCE6C6B1929CFF85BFDF166BEF658E10 3A55E007F38EBBB248B3F0B8ED1925106B499B762E45113AE1AC9DE09644C84B 9C08034B297314EE69BC32DB6E7D7FB9913CE5AC17E7335979E9DCCE2BAB3725 1976155551F9706A576FE0E3ADCCF72C87683291528ECB749CB0ED291966E239 B5E3630676BD409E08F85BC1AEC9A2D4135376284A96EA24431243BD6FE8B966 95F11A4BB53F392E0AEFEA623064FF8A7002367B0A515635CB2D2DDFB9B4A8D7 FE721754E81BBA548848A235B91AD4E4F7DB19CCE2F61D277FC00AB956EB93BE 44AB4970CA56BF59506C94ED160FB1E25D3DF2988A532BDB787BFB8539D22986 FDC378AC31444E63C4727FEE121A43751043849E6DCAC5B59D0FC703AAFBBFD4 E8B7C268F21615AD02CE9DABEFA27B5FE6A6441B619539CAB1F810F1263447AA 633F5DAF483752EF1A0421740E3A811D2D2898CBF53E7F686C9223FD7235F02D 6F90D2D48CC20AB87778DE3C6FB335E0F0EC20B5DC5B65223FE117526DE2C72F FE839DF93CB2A7D66CD900CB325F891E311BEC932F703FB4FEFA29DB8B9C88DD 375EC71B3D58C7BC59ADA91971A3BDA1ADEA629CE6CC92BD542CDDFAA7706FB2 6CDDE2DF07E56D6741916AE8E8744339816F3E6C38062747AA9FDA2A2678A6B7 EFEA870AA3A4D71B25EE3013EAB1DBA34401B867C7A41AE51E0421D41D3BB83C E120C8FEABA6E5DEC53A689C21426D4BBCB68CB37568761C360E6D4E3596FB7D F4DEC7918E58C0293D12D6DDA7E9DCDAAD7C939F55CD1BC4A228B31E9A904156 DA6B40B08E6ACE674618B768DD681C772A3E55FE096CF949CF3B0460ABDCD891 D17B37B355B29AB5137899C036F31DA026244FA25FB798FBE5105BDA29F46538 D3D3AC1001A7BCECE64DE94FFE6C354166A0F97256137BDFA07F6E22A3D1D2F4 9588DBAE95E895BC5E64DDCBBAA8D0A22C229B42CB717FC711E7E9DF793DF80B 9F14754585A3C7E17F37B32924B9F9870DA8635E3E18BD1DCD81EDF01834D9C6 B33F23C956C2FCBFA47D84422F583459D827D1E120B97694D12F1F54D02379C0 D288F7104F3FFCF4F76E3494F4ACBD1BE3A15543CC680924C78A473F8E311ADF 8FE00A04C6C393DE61AD3EDA5BC031E2353076A2489391B52632387CA28A7B93 FBB065A6EF3658AE80B1ADA47E9B2539E73A71FA75645F85ED8ECC257FB4CF26 B6C912DE9D0F9899E70BECCB934AD32CF49A093371A9F73DE6255EBC39DE1E7F 00D0CBDABD4D0383977E694890E71FBE5C376BE5F3A80C28987417504F515C50 909F3D31178BB9B1D085BE514F71B910A9085BD6122DDC72A150BFE266920E49 5661BCB4BAB51D6DEFE32B616963DBD989FCDD1637B294CE4E288655FBEFA1BF 7F25BBF8CF17C2D5FD161A7C2CC9CC7490D9BF15A1D35B3BFA43ADE256E88BDA BD490D92907C57BAC408A575EC84D6AEE070148C7C9A91C03B09FDBD792E8FF0 C0B886AAD2EDD86541E5E579359D40E3AC312ACD3D8FD49F71BD533DDF8859B1 BAF17F1884E331DD07CEEF93B71D492AEBAADF7A263450A7A72210CE630A0D37 BF024BDC09ACC882816B8C22C62AE38A3A8D0F6EBC2B1B2C0B8161A8B076DD5D 4B779C0788546BB4CF57332230D237856B00D79C28A7C01D11F44B7304F69075 94B97A745DA43D1BE561372CE611C345A843834E46AD9DDB16CABCD3FA33D6F1 F6B5C0497F5EE5400B305CDC16A7EC286AA4D45D0EEBB9DA06AC9C5294D68EC9 E4DC3CA2B92CE8FC0526184A86EDC7AB34D67E60AC12D9CA8FD300235EC968BA 92C6FBDA47572BC5600F25249F60AD287CBDAE980E747FCBE7EE5CD323E733F0 63553B494D3DDEB9CC1480B5C3BB79A28E419AA65B18CB297AB383419E890E2A CE6F98C9900CCB4675280A10CF060B8D220DDA1BE55DFA65715EABCC1AFAA271 B1F8732341613E17B231231A0D24D4D7FC198AE04D89A99C4536217769C6FBD9 5EE24A6302F97438F7C0E311C878F674B4477A5ADA3952CDE4055AC408B8174E 86F8FB797646DFFFE0ECA25D1BAB9A9F71F3926D3D85AA63E7A8C931D71E79E0 AF1EAC26FADE468F4FF7F3861D14C10E3BE1F9EAFD6D3A544E8108D5DAB5B180 3950C74818BC8AF4758A108F462EF1826647A49667F5E482038C54716856D9BC 35F29922846D2148F92F943E951D7438C73D6A60459A8003174036C64E1629CD 155D47FD04B03C023AD67CD5A70C98AB556EEAB8C48169706E5B352F6505D580 AC945171BFE62E81F8F500438AC3B64D857BA5BC54C2C4BBB237F8FA51296255 E66A92A61FE13FDE781D393557EB72CEBAD86511035F775FAC39A0479CCD400F 226709118F887F47CC2ECC8F79816D4A945B2845F50AFD62D8C9A9BBF4739496 9E644BC9F7B04803B7EE75A09EAE94365F6F374B4FCEB0B506C76297564B9B6B 8B812BC3A33929AA94692572B010E6210AEAA312BDFC88BF302244AB9D587A9B 919823FD01DE12438D960944D1977800FEB49E638C32E5B188B1CA033E0C37EE A142F746367888AA119535F0CCAF7EAA461B790EB089D2D6962E28A398439BB7 9C9943654D7A2D765B46BC0DD1F915327F369162E1BA1BA83110B93F442905E0 523BFF5E279508A98568CD5CFD18FABBE9D17265A9081E7BF64155A2CE3C0DF7 88D00671AD65654709589BAD7EA65BBA811387ABA5CA0BC3F66D3D48597A0D1D 2C268375DF47CCF62166262AE4840AB03BF49BE67A05EF66328EC729F03CA5FF AD3937FC053E223303565DC771ACF32E63DFB96D5030E787961D72D02C195C66 B48E9AF0309DC169CFE8D16E2818DA94693A18F027DEA0D916672480464F7E22 CA6E431FE38D3FC019BDD229E064B72C545C61C6EA55984565CCA88ACB01F744 3B4593CC8953C83DFB6FF3C5F9113898F45B76D98F7F118FE4D1E6BE669545C3 92676FA583E3D3B272D5BFB24153AF62BF53BA0C81BF5AA2012FD33DD7640BDD 5CE8BA566FC85FC277B1EF69622D720569405B04D49FAA4C9FB2D4E3983D5C90 6B9A4327AB712D655D33EBE0C95E1325576B034525DC7BEE4BE00928DFD23FC7 42F317916B81D6B189FAD3045D66E40AED0B64F709989F419019BD5CAD255631 C91E48735BF1A70917B17928088769ECA64EA6FF215A445CBCB6D6D784022768 BAE9BE186FBC80269392EC8C86 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMSY10 %!PS-AdobeFont-1.0: CMSY10 003.002 %%Title: CMSY10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMSY10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMSY10 known{/CMSY10 findfont dup/UniqueID known{dup /UniqueID get 5096651 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMSY10 def /FontBBox {-29 -960 1116 775 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMSY10.) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 2 /multiply put dup 15 /bullet put dup 102 /braceleft put dup 103 /braceright put dup 106 /bar put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CD06DFE1BE899059C588357426D7A0 7B684C079A47D271426064AD18CB9750D8A986D1D67C1B2AEEF8CE785CC19C81 DE96489F740045C5E342F02DA1C9F9F3C167651E646F1A67CF379789E311EF91 511D0F605B045B279357D6FC8537C233E7AEE6A4FDBE73E75A39EB206D20A6F6 1021961B748D419EBEEB028B592124E174CA595C108E12725B9875544955CFFD 028B698EF742BC8C19F979E35B8E99CADDDDC89CC6C59733F2A24BC3AF36AD86 1319147A4A219ECB92D0D9F6228B51A97C29547000FCC8A581BE543D73F1FED4 3D08C53693138003C01E1D216B185179E1856E2A05AA6C66AABB68B7E4409021 91AA9D8E4C5FBBDA55F1BB6BC679EABA06BE9795DB920A6343CE934B04D75DF2 E0C30B8FD2E475FE0D66D4AA65821864C7DD6AC9939A04094EEA832EAD33DB7A 11EE8D595FB0E543D0E80D31D584B97879B3C7B4A85CC6358A41342D70AD0B97 C14123421FE8A7D131FB0D03900B392FDA0ABAFC25E946D2251F150EC595E857 D17AE424DB76B431366086F377B2A0EEFD3909E3FA35E51886FC318989C1EF20 B6F5990F1D39C22127F0A47BC8461F3AFDF87D9BDA4B6C1D1CFD7513F1E3C3D3 93BEF764AA832316343F9FE869A720E4AA87AE76FA87A833BBC5892DE05B867F 10FA225E233BCFA9BB51F46A6DF22ADCEACC01C3CD1F54C9AEFA25E92EFAC00D 7E2BA427C25483BA42A199F4D2E43DFCE79A7156F7417ACF78E41FCA91E6C9EF B933450D851B73A6AB6AEA7EE4C710CB5C14270D1674FA334686653793FCB31B 491E870D3C2BC654D2C1DE463EC9BA29D7371AA1078800EF93D3F66263A2EBBB F5723697BF7448BD0D2E301544BECF497FD475B85DFEF52AF4F8F8BE445CABE6 019318806D10C5952157FF8F8286C1EE701545C8F60EFA854EAE66835A2046A6 915D395F1E0366EFE0C0391583FE001FF16D82A2E2DA5F57754A2C6F69306E36 356ECF8EFC3F1188AD6FCD2427E0580C97A5B69B4E0E09B85EEDE142F5ADD2F0 5DE51D6DB72B127412A0D57106C19CA493048A4F815129ABE767D51715B1515D 9C21067CB5BC88741B7298C83EAE36A866DFA87D8981F179B1C31292F56BBB64 3C430779468AAF07C8A8B4934E1E775FE3F35186BD1FA6EE3689C1C750678AF1 FBF9B23195A124C5C991FE670AC0C86FD39D2B07B9A319E74EFD498B45820252 720ECDF7294F7B0B137CEB86D33BFCEB8606985A3260FD669E461C8BE94216C5 D434FD8854F44EE66E5A289A9F9E32BC36AF645D53F96652602BAED418C8D726 BD04A1B4617551FE4DEF54083D414F7DCE004E6BB2DC9C2EF7CE232B254BA2C5 7DCBD36C2072ED46FF711F121A701E2284BF1B718B3164382B8F453D68FA0377 DFE106503B8401D4DB87F5402A3AC9A442FA060B0610A9524D530C7157C26B56 AC970FCC1D5655FFFFA39246E6420CF97D08ADFB7B05822679BD40C638DDF0E7 A97BFE8918B611A145AC965C203F1428812F9D340AF499B3A915B22BE798594E 0F520109FC81E452180AE45B170FF999C5FC2761C6CECD8742A5A6FC97F16743 AD4EFCC6572A6D3F3E4E330C5CB2FF6FEA48A5B64DD3DBE943BD9918D4A18E18 CBCF598AEFBB6AB3CD2CBC9BFD6099272F6543F3E532E0E21E614BD2880B1023 0AC234CB705827BF016DB84E00E8C255FDEFA0101A842929540B7B4AA8A089BD 5EFF05B72356B6BC3727817823B5CDBB1B963103000D7F2A4E2A1472FC3E614B 5CBCB6D6D784023173DEFEBFA8F9ED87EC1A0A9EE98CA59CFC964CF943DC683F E9E00DA718C4425A705A69D99988EC6F152525C790912C2E46A2381A569424AB 54DF4798BC2D7E7A361E7991641D4B756CE2A7FF4A2848927092C59C2C4B8809 E13AB84FB6B111E680D7FB9F2FFC2C5C66B0B501E4447C2E46C10E2F6124476F A140C404CFE2DC9E0199BF61E035CEB481D438139A9630934E541D261FFD2906 4CAD99E20655FA746AFB81EDBB5601F5FD6B1D6832A01D585E2C55053F6A7378 4DAACCAC7608DBDADAAE732D66B3E7F87E79756337C1A961E53A4651BE7C77F4 038B89C87F650C54A2A90EB7F1D525BB353F33318551EE8D84A6A83C718EA5A4 B2AC0F7306B1E095819B87015A90CA3ED739B09061782C28CDB36BA4BD5E5308 5CBB70414E4112193DAC4A1FA30996327230D1E021F3CD8115E12D239D93FFDC B645910EB29E40D830E7BAF2DB255FD7C4E776557BB38157917D993EAC245837 A3B515147043574157B8342D829C7228CCEA843ABC89D1785A9672A5923FC4CD 2F3FF27E6FCACF84E2D3136CA2C0FD3EF1EE7354CD04C38B5FB874553646ED2D CEDF7E362EADD04B18051F20A8FB0DE18E152385B9D05F98A3A7EF177824E246 455ABE69E2F700EB78185CCFC07E3B4C6FA301112528D977367D30D0D5D59EDE FAEB706DDC970A9E296236C725B2B55B09B9C336B8E23CBA5FB8692D56F33B03 16294E5FC7FAA42E96395A57CE51CA8DDD77442F142E2E576B778373FB31C81C 16840BB422CA827E30A81829648BDF1CA36700EA32AD888D097C1FE0A05B2D9F 483AEE40269DF09AF0D1AD3DF80C45DDC59C2A03FBB661C79B87853737C6D352 67626B657321B16198DBD6DB98A092F17878AE4698121E1006E53D6F9B0A3BE2 3FB68828EF854A0CDBAA68B37ABCA6AD4A3D809AAF0BAB1697A81FE59C98C472 1E33CD70A75A22C249DD11D76C2575ED3370A25892A16D2FD569CDA70C130770 93F493C7D47D6F9A5424A7A542BAD726BFC3AB225DCEBBE6AC4BE006F8C7C0EA 051424B08305BF2D951AB2986AAFEA04E078CA79B399585BFF0F1ADCED02E15B 8765EB6BF6A8E4D0901EFF2C3AA104924EAD9637A35D877E0C51A3C37DA78CD4 8643C8CE6DCDDE3F116A6C2390F948E5371BEB5AD2E87B41C5F01FB5C196C436 6E256A88D082E3F46E4EFFBF605B2EFF1E9D9AD5EE4DDC323A137CD9451EDEE0 06F7D82898D71FAF2362C0FCF1F726F97F820305B7CE20728CA08C63575083A7 84BA28B7DE2B916432475510E274C12FFD1660A717F51DACFDF0A102D85224E0 D6DB607BB72569ABB8A7BC6A10354CBBC01732EFE35B72062DF269CB25EA3DE6 DC603B04C90C5912D2C38D7A5ACDCDD3F6F116D884F0D8C528F69D5D47BA20DB 0A9E585C7D8CC3C324FE8A1DF150279F7E8FB43BDB720E624E5E9918032C02CD 8020636AE5C38DA2484B7F4B34163E0D0A561B43B80E97746DC05C871AB620EC C5D47101ECED4A7E25F291184BEF8B80024AA7BB456C1B83A907652B331DEA34 754226C39C6889EBEEFDAD081E01EF8FE47751987667836FDE4C8BB8A3FD4406 1E643B4EA37BD370734D1A2DB17C2F4B74B4ED75098B433601F75A88C9A37A05 CCB157EF6E32023BFA33973F3E655A4D58289136996FCFA61EEABD70791B6523 1FF5DE71AB8A17038923118A5EED8D59C4C58D246FFA9BB26472346B40C8741F 153D19CAFF20DD2A86C6DB89154A630FB1761929FC3F0448EE2F089C1C953E02 905BA8DE75D101A982A611056C4B237596C10951DD98BAB838B742D3CF7DE718 617DB72E5268583223E37E029D1C8FD3F1D21690151F76B76C52C725CA135CA2 8666553E863CE188BFC9B99AF56AC2DB5BFEBEB12FB563D00244EB89E478657A 98AF2E1223C1ABC25A4500E8119B86EB3C26B8A2F3505A3E5610F89B7C34E278 53FA0A54A7F46D84A35EFEC36AE660A9E3C37EE3864106702DE5AF6C45ABF64B 888A4A51323138CE77DB935576FE6B4824B6942DF80625098CE1B5B32B234F1D 052A9D6039697118A9D793793775D8729D8574A2E74D7109C7B7E23BC5E2E87A CA8E019203952A4892544E1AD3D4EDD22971611358AB230E9A2ABDF00A288501 A01B67C42B33F6B78C39562DB50F4663B922D9BE0D8A150311AE44B83C1F129F 07337323E9A23211EE58E16043E127C6F9574019179F5635648A011266677B56 B5D0201A4E1470B952A1579B57AB2329CD4C615395023C653F784D36B5EE3672 10D191F29EA508CE84763CA4CE7C2C5229E38E241255A5CABCD6C7CBAED901A2 CA53B5E24111921CDDF83578D33D463D70EDACA0E470D8F592303FB6BFD68B4D 3F3BE2D7C5EC8BBF10C90111A33E205F2649B56E8443F6FAA6C721C66575AE12 D4C40F1F46CF9E9DA675AB5D5840D938780CD9E4AD6736ECBEB6A4397613586F 849B51048AC5F9405E03E14540A5E5582F61CDCDB57EDDF95A8C6705F433EE16 648F098C03DED8A2AD94AE3DE202D629B9422ABB031318D48F2C85F9DBFA17BE 84708AA3B6C9F81F4508F7A5CB7B6646AB8722ECF817877B77D473F577556DAA 2BA0ABACFCF5DEA7498C47328E873019A956FBB250FD9D8885D21D368FA70CBD 2709D2DA44EE7A9869963EAB48789541906DE49FAE785ECE1F18A22C7E7ED204 9768896B78E9EB7A2BD6EEC1B26083940656ECD689D92942CC8AF05CBF82AED0 B45A7DF4DD7AA6526FB597322560B9ED3087A65B5EEF1371C328A021411BFE3B D9B5088B2F1AAE381FFED52D2D1E02CD0DA78683E3B06171CBE94BE9760005D7 135893D7CC2DB097F6AC664D9594CF1C650F84DA80D2EDE04802DBA33CE3DAFE EB7A37E8AEFA4FDA6252FF21E8673DD98E67124D5DBC7BACF361E57077B71939 C1D1FB923E4E35C075CD1BCBE0E80DAEA1320D55B43EAB45D9B26C366B278782 7519FDC482D98839BF0DF2E7C3A56A1C1A3FC0E57A75CA414F6536C1FE8EB7A0 4ADFEE3BEDA0F53BE8CF5F64230784A797133E8CD46BCCB3BF38BCE38A73CCE2 9E073ADE792F7128231DDD1F63E6156ADB2609C200837C2E8A2D93D2A7BC9171 050C709A71E44E32B1B03C92EB5CF1D3BAB1C38E027DC4ED9AED633D98CD7486 3F773ACF8AE332631CF2ABE6D606607593FE862ADE31803964E3F4DC3CE3A271 C76BDD95C87CDB3B87BC26FC7A16D567EEC62E6FF0D471B4853DB8A94D4CACF8 843824F818083F10E88D52FC4253E8203292CB40F1414AE7E51DD7347007C342 CD70E8E9F2D2A13D71213B841DDEAAB208AD9EA644591C15DEB084165F9DF24B B91D3BBEEC2E34E38EF16A0C3F00700A7BDCBBFED2EC0D09601AD6538288DB50 3478B051B5E16B604A0341FE621A58718D960D699D3FAD284310DCF54EB13175 19A75A539EE98E804AEA24689D3540F0F12951A3C01FACCE9A7BAF4D0DAFA946 FF65A4D2A4C39969607272C6886F44E90ABE27CA3A1F12A29D9B32E60E8E34F0 17C5FE43D0E69A99A922D98909B2BBCD145E59A5E7F5426B3988F73B09A525F6 8BD4915663C1301323180E760BE81CB874B020FDA3AE63340E4261E4F3E4949B CC0966BDC4426190BE9F5D77F76A72AD925662E5FE1CEF9CCAB68F0BD33DA003 F11EB91AC4502FBD6AE48DA0F9D07C35B96B103E379B8A83A05FE728F1716194 1F650F75BEBADB2E3810388F3E2DC7B19F1BA9E32925F2FD9F19F4E8701F3E4E 4069125D7C401144740691E7A460021A47B1E27997FC1DDABEC5BD0EE0B20194 2D579C7D6727AA124083242BDA46D8E116E2751C5F298851A62B60AEBE82A929 9B9F2492BA35690D1EFD16215B8EF14E7A3803B93C28FA41D971B05B6AF3B593 E74AD1E68A5FCE12A86E63B78BFEA87D3949FD164F12277A4688BE96356791CB 8671C49365608F3EDECC109321AF92B4C29CAF073DA3A7D73E913D0D83FAC5EB BD884D4C686056404DAAAD6F82F94F803FA1FB0DD8908D1DF08FB87A8BB83027 04DE0CBB1C6FEB6B517FBD7CF065120079E608CE41893C2BC96A347826CCDFD5 C69E161217F2127A59F1A6F22037641613F191F22D5B4CDCBCC2EE5615623404 ABA7BE6C5FE475481615B2AC1A2412E54688DD21E44CC9AF5F16E634AFCA389C 4D740B7B51BB141BFAD1080E7C726C1606A28ED492E6BDE9F800EFACD1513909 84E98CEB6A0B7A2A6F3E1D1DCC3B2552795E0932673E59ECC56DDD37A1D52BA6 C3F0E905978AB568941A163F4CE3AAB5C5B16F86016EC47BA6F3F7AAAA77C3B6 09C8C3ABDB6D514A76ECD37C37AA88B5860630B3406B494F7725975596F84777 D9CF48686EC9C5DBCC1D78513F591C7C10AB9D153B3D41426B7BF668B0D04503 56BCB686258462C1DC61095724B9F3312316262FD7C1AEC6E54DE7E5A7BD8EFF 035299B8FD8A4A7B0F51404F4A760F4D8B4C0FB7A32FA4B2383AB6E9C78FDEDB FE6A5788D38A6701B123630C2A6D820A684166FBBC83DB17069494FBD411B333 CB37E2491C5BD035A33867A6D3A3D420CC31ACF43AA07182CAAE67E40EC63663 B678F71D4C6E0EC3A0AAF904CD3AA66E0DE5E3CDE049E94249B39A1C06E3CE9A F974B2484BB2CDA14282B9511E505B3C89F9C802218AE40D1A7541335C5736DD CD565D4B9F4CC78F3A393737EDB4FBD0DA299E21CCFEBA5478EEF013F0552A8B 0BB11FF46CCDB784E8BDCF730A16363E66572049E42C695886EAB42A9AD9094C B635DF4B5B9BD9B9AE8455DFA3EEFC77653190F9A8B1E93B7281C2A21EA7DDA9 33484745BDF7E3DD63C7AC66C286C9A5A698A5E4D7A91710B7FF943FB23609B6 4B442F83CB795788FAB5E9CF3F75D5487DA26170E4561C7941C910B088C3B86D F844B0F340CF82786A3FCF347048463EBD2006281A816627065DDA6CD4D3AC5E 2024BC96C7D896381BBB567951E7A1F29D4E95351298B000D29E5F3D0448CB5A CFDAE1BADE9403B90371C3A07D208948AFA022A69C519434B6813086ADF518D5 88E0B92072A44BA1B3EBB630A13B7AB90992E85B6D67361C8D96F3E0D826FF37 17B67E4B1EB7BADFD98D7F4FD17BECE740ADF13C141EBF0A91CB105DABB32FE0 55086D56A0D358841D15FD349E6B95512E4EDF4C430216FF85C2ABE995E4B40A A6044CC8820AD885C07E052B3F91C2E9A1D163BFFD210F7BE95B923E2500DB50 2075106DB541C267BD450B25B670CE80BCD068D4DBFF2D82634175B61FBD3BC3 406131F44C7D6F18D375D1F2270829DDF29DC14DBB58A30AC193245D18DE91F8 AB88AB548D8138605BB5A50073295534E314366E26665AE70482B890E4101D6B 60E4F3B37ABCA1346DAAE8FDB8DD9C832EFF3E73BA470E2BACE7B8515CB43388 C27AF99FF9322175CF8D4947E6B3846AFF5163E972156847F58A66660EC8A3A6 5FB47C9F637B4CBB4C73B6A080B0CF6FD1E9665E92032540570FFCC747C67C50 822811AADC404BC7ECD1673E8AA6C3A2F1D82F39430B58C29145E2F1B679C46E 94EDC711883F1E4EA84117A54757E8895A40401A26E1437B39A2F65CAADD6E02 D71FA8AF7453668DC613F326A3344F74AD7AC67569AF399385500ABDA5EDD3BA 343CC5EDD4B558467626850E752B9959FEF1454E53E7A3DCBC2255AD8F6AB4FE 894455118A61C58840CB68A925ACCAD75CEACE863D806916228F0614191A1CD5 DC9BAE256018615AA3725834519449B0A88B4F396654E74099C007930ADB1327 DD119BF799FE3B0B223E1EDA04FE2DA7A1C879143E1C33B6C6344F4BA033AD6F 8E88C33DEF1977796B454BAB2494C930F492A518E8198C708A75FFEF8C49C324 A718AB59B889DED521229E741FFE53F98EBE88B0405AD523254FD3FA4BBE96DA DA1C27C1C979A0DD4E61C3B1F4C4DE01E42F1C4435EECFC02D97994BC8AF5270 E7CB1458D76ED0229C5FFB4A23B8716018F9050970895D51722CDE8F2EA3D947 DFF374D84915D5C5D16463A6FFCD079D1ED416C4347BF831FF0C4ADFB61295DC 4D5785BB0852BF472CFC97EC174491CAF961AB90629F055E75DAA6D9898E8653 5BCF379816CAE46FEA62E7BE8E9B953466E51828172C4DBD0E1BBAD1CE28B5B1 02B3E36403BE80B49A47446A6677FCED438F01D60EB10F478C89528FA337D0D8 88D3FC123C076507ACDAF783A9A6E24ED73BF24B6E0F11C13E532DE5F70B15A0 657F5ED27D204449A841ED19E01432CFFE928E921321113780D036D34F2797DE D4459CFD15BB117B5C9745EF3CD2B296D91FAD48C80B136D94476967E255F808 AD2B5D522ADEC64176833756510391815A1D4A8DA1D0AEE7CAD36A1D161889F2 3347D5B6BC503300FDDD48F594F391D5FB42C42113C538E707C16EE24A3F375E 7C506E8F49CE50FF9DEF3B4A4C1BEB3848EAA3477349833BA22D2A9012287D8B A8C4CB4307A1188ACC0E6E9338E1559BE5FAFF381BD82A6C71C267409468B3C0 2C1A29F4281D565836EAE57F680490FEA4A952FF64C8CD11C377C294DCD1EC25 CEFB2B6DCE959D0208F85B6E32E9B44FD455F9B134A5306D95EA29F37BB8B86D 9E592159338E1293F449380E13C21AE42E6D6952083BFD432F72DFB7B6F9257F 5784C683A6E9ACD72334E0EA8060A81E14EE32300055040E24B49810DFA14691 6C24BF2DE490536C01F7E874AEEF98A27529489EC334D0CD71D022C7F2BBB98A F39D6C0A24CF29DB0E4545C4D32475724F30A87F09B0440D5DB8F6D6FE35EF4A E22528DAAFC1EF6D0EC88A1B219DB61417DA4DBA42721255EC9BC5BE05026051 19D8A0F096F8D68C40B3503B07497CD44A236137AB06B407CA6F5F9EE2F4E99D 735EA287E2C3641BAADF92681D7D2794DD2B3C8D22F78C22D1E3AB2B40478AB8 1EA3AD94008B0D3A5C125EFD6410D27BDD3C8BD16760A91B021C3011332D045E 943A0FCE3EE596985F76817964430053449F5D3233033BAFA7ED9006FE3F8F03 7CF09FCECF6F9848B4911E308C2DBDC25125EEFCF25224F0FDBD646314EE17C2 08BDB63DFD830CE806A0D5D052D625AD620D280CA2784B6AEDA6506A0259806F 5D5C7B85E8F7BA376815E2F2215497C3AC9F73E6CE583B5078FEDDD2EAB2D715 7C1FE58B7AA299FEFF8F9B74132E774432D66B6F51CBFD2D501CF98755BF1710 67716A231B625079AD782207EEB1BC4F8FB30618FE4B98CE3474535899364083 B1A82A67CD5E9033553583A876BC1DAC1F7930DC099D806B1E27389125E1B15C BB1C66AD365F820FE2A7FCA56F38F9C8BB1658172DA09AB74E85D6DF8F81455E 28532112209876E18F8816DC08CC1EA309027B54F73921BFACC25D7255F26202 20C3FCB8E515C7F79EA3054A9B5AC4EDD0AE44B896169E458932B4B8E3EFCA58 679F2F0B9FBFBC4E524C762D07DCFC8BD7229068C1BF9CB2459B251A59600C8C EA5B5D9A1DCEBEBEB971D77F197D2C10067E6D4C013C60B8EB15C457602F3654 379B45E1CCF06CD4A72D50AEAB4F56AA49FFDB41A137F6EB9AC761F4582E18AC E8384F4B9CD7E26FB8A061431204F100081B243EF021572943842B32EE0A1434 3D615BE9A784FCEA05B8B846DDBB604AE63EB9901008B6D8469EC51784D53D21 42AAD960B0272DEF6A7CC0C48218F5ADAFB33DB55F35AC8998EA798171E0EFA0 9AEAFE35DCBFD62B28F52B14D8ACE54352B1E9E1E97171961E0873004EF1B289 3197CC5D8F426CEC68E7E00FCF5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.0: CMBX12 003.002 %%Title: CMBX12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMBX12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMBX12 known{/CMBX12 findfont dup/UniqueID known{dup /UniqueID get 5000769 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMBX12 def /FontBBox {-53 -251 1139 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMBX12.) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2D43A151FEE81296FBE 0CF37DF6A338C826464BA5198991445EC4BE80971DB687336AE8F74B516E333D 2D8AB74D362C559AAE6ACFAE49AEEF4F52E28C869222C1301D041E7A0BC1B608 1BF728EF9E98F3A12EB2714E7F16B14E055FE1FA0EEFB058860ACADEDA9D0E4C 42E3C6F1E4869471BFAA3760175F3FBD842755A9D7847EBF605F18293B42F557 FBE2715002669091BB033E1AAD657532F34F7C66E4F04D63ABB07E6CB9D9AEAE 78EDE8B79DD9BC87A1FF445EAA05B5572BB880E69F4DE1F82D7F0E9980AB0C18 22C448B0B1722D3CC33C56FF287CECB80658B3AF5E7675BE82CEFF3DAD5942EE A03C955FF979E41E54BCFB5316A9AB8945C403A73180D0961416EC9C92F49811 4B91BC4C788392994587517718521E416D469F69952149FF7F9224377EBA1065 4A727BF806A112A7B45B0A1BA1D5A23683960575368D9EAC8C04753BF7465AF7 95F25C258C63E4FDFFD0B412FD381946AA38C0B961652BCEC30322C47BF4755D 9F91880688AF066E32FFB22E1A52DE741307AD3ED830D6BAA1D1F562919666DC 5E8FD9862AC8600B0AE0BC7FC779252AAC57248744ACC8A8AAFA836BCF09B0DF 9253DFBB1CB77EA8A59D42D1B18FF25E9AED72FA62FEC3F126F030F5D7DED9C3 CF60FE890BA4A48E39E687BFFAEAB96AE542A6387F6624486037C8924002A511 BEE5FBFD780AC1D4BEC3FBC47A930BAD0280D444259528B6C565DE11DE36BB65 9BADC55C1EDA1A80458E98896D782DFB5C137897419602809F9BF8CA39F00C68 EFB9E076FB324C2963F23CBFED28B9EF70EAA4E4B903225D1F199A7162AB239A D92D71C18B1B682D04C6A48926275BCB16D413B2A0E953E1257E0B12D8B717CE 2EC84CFBC046A4338A69F454A469B12118E562B4F56C5FFB3CA5D357513E6FFE 947A564B229C7FD873057D5C7CDF03E958294A1003B37D8DF565A70A00A3734B 0138AE5277D383D10C2BD853EF806D3CCDC47739F0E374A3DF3B63638B949ED6 4EC25869DC1C0B1F4DBDFFCC97382841D8F10F3635C792139A1EC462FDBA379C BE0990CA2E70FE73137AFBBF30CA54954D7E7377CC50BDD780DDD4C7FDC77AD2 F3EB1169F14A0041F18160F43C24FAF556DB5D621709FBC544CE55424F7446D4 6AC07A51C8CD5161AB0AD5084A96FB35D77F1CA155147DEF8D7A590EA6939514 D4A226588295CE0007BA8A550895511C8D80BBE5CDFB8A50D249C3BDCA974415 F5557914A9B805782F399E4078DDB6264F1A49A9A5BA45E284A5196E9828EBA8 481D357B8D9E6ECA631A6204439FDFACE7D7E6A2392726107CB7D2517CD19A24 FBE592C119626DB221BBB635B6EB84845C16A9585282E34958B961F4A543AF9D 419B6A9105BF185FC767712D923437BE08A9C0EB92AB6792DBDC671029B6FCA6 7F717FCE379C0F3B51C6CF042A762ED04898FBB4B0105C3C4ADDDC18C51BAA3B 70A93666669547081D9246732CFF74C83EE90DA17F5B4F8BAF47FE4D81590988 2858C9B96071341FA0A0D23BDD4947FC9BC2297913CFBD4FD6CA4303AB3179AE 0203F1BD502065F90CE9BEA3B52DAFE4A29446082EA0E6B1D7AF1F31D0AD02CC 9A7FACE2CA86E5FE0F6A425B28A5940ECA306891CECDB3CFC7A5BBC76B5D9E8A C754379ADE80B4D72CE493010317BF21A0CF4A0A55C1246218839DCA3F4D626D 1F4161D38F54AD5142C1CEE95C61D8BB10FAD4B772F4955777AFDE8AE5A837C2 A2BBB11D0BF5DA2E63D0B75ED421DBA9C789B281B01846B65DC572BA69591969 21265DB722AE86BD8CAA3D887C975A617ACEDDFB7AAB341F47532AC0F354A530 7662C089DA3939588774FFA16FC4A52555DED6D6F51DE718BF5F345C23C90198 17B77CB8B5D53A5CE7A79F3E286B6A59F3F6178AC8BF15C0A15C1A8A95D03B60 30EBE53DE328CE085CD9A1D49C69AA299C5B58B24334A546F6E274C1B534DC8F 3289553F560C2F81E413ADB92FA0E7DD1C2F39D5FD268EBA97AB7335ECF28257 96B4EADB7D0778706CB41C7E9C882760E7670936774A1088FFB2011115FDADB3 B69EBD5108760762521C25C968C3E282DC3400001AC8FB1EA27FF643E3025950 1D617BB8BB321281708E496277E11DD3AE0023DA9F25AD06B39C7CF527FED27B 57397E88D3DF70EE4FCCEFC8A0927D6B05517E571B3E70ECC99F3CBA32CCD4DE B8BF22626B6C94FE65598A88AB90D238461EBD9A098DADEA4091AF1CDD7560EC 8E1B9BC2321686E1759E6B8A270C8CB4A254F7368039602EAEAB86ED21CDED91 8F2DB9889F46981C494C7EAF5E819B91C129F0740B8002B510014985E5791F59 B16879CC6521D8E9F1C4C1890AC85A78022BE614BEFF318AB2616F0C3F02405E BB425D1555472A2642BA7686E431DC3FB8A1688B76660D9957C3FDE8D58109AC 21B1234C9DDF3F0FAF93BCF7B2F88A001F23162E1A13E5E9118D51B485B70A91 D0CBC39CF44413FD8686D9030782DAB58064F5B987E0402AF5B264B17BD31BD4 FDF63951BECD73ACA6138854EF35B062D01F33073850D9C09A818828C581241F A625AB3638081DD0F00F946BE5450D38489CECEA4E66B4D85CC8AE0157E2AEE4 A22A9313829F24D573101D84CC1784D1CED7DFAD5DD966601370C6CCBB723082 A86BBAF0A5D867D0D2E3CA16E14E5109A29EF02649C47E12E88B3B397D65CACA DEB9940B92100744D686066F8250FF30E5F13D81428EE238A2E4E07ACE0F5C38 7D79D4A336D0D26AF9C2B84088ED8ECDF94A1E3FADB45AFDAB46CAD6FF950B0F 07AA2CDF82374DA76C56D29C80138841EB13F0D02ADD32F88B23E282ECC845F9 BB9AAECE9CDC644AC2D49577A92307A83A99434F6493156DF25DBF0FCF2EC21E 8C50A312C3D19E0609C0038554CF4FEF3ACEB7A833FD54B06EF0D617C2971C89 E4C06075B09B84A4F78A82152B9A9C540B1D881313C2C74F20ED064A9606EC2C B56D7BB4797F1EEF4A9B13579CCF311FA4A4DFA62D80FDB7F535CC6526D1AAE5 45C008EAF024B48C377522F74D939A475970533E645B1BFA81997549AFF26F67 2AAE6C2EFA357DB3B525276EF330905688777057F4E4CBF584520A534A8587E5 5A8360891E75A15205E8ADAC4A4E5A6E27D0C4A7D492216E4BC023AB027F37AF A8DC7579BA50204D5F45A51460C5BD8A5A7F87668CA6451137F2F59E117BBE28 5C40820882A5546FA76F0CF49F8A6EC445F0647CC3227C400F56E7E9B84A6975 E85E243CC1666DBAFF4E07EEAF3AF71BDACB30DAEA792F2B8504CAB071544F01 5D66243D529C479D276FE22F7E275D9E7FA9C6EECA18716B2F213916E32C1D94 6E32397B41AC6779543218E506569E3544803BBF9B404A983EBA62A494187B30 8D3DFA4E1237A2E5E08224A60492C09ADAD8775B7CDB830520829BA164209ACB BCDEB2D574CEBFB7AE4BE72DF4EB1945FEF2458761AD8DCC0D378AEB7DA002C6 9C14A665DAAA532B0ABA98D7BFB5A6151FF6703385AF7AE8FD315A492FCCDBCB B825707F9566B3B4943A3C61C3DEFDC31A843A2D67AB06891F3E110DD8C73D3B B5E4151B51D9F13905D7D94DB9ABBFCAF35F43B6EEE256B1A80ED6D1739D8D5E 8C767F6F0E8704C5345D028A2A6DAFD9BB7AA048B8B895FE9423A7ACE858BADD 595CB074A128DAFE08FDFFD6BDAC0114159A702FDCBF8013804B0CAEAD7AF38E FAF086A3248AD4FCA1401A85AE2F72E3E6956DC0996FE8ADB18F89B14A208A15 13F81AF73D0DB72F78C4DA634ADE3C73756CAE6AF2E149C26316DFD93370BE1A FB4A79F77A67C07CB0A53C78367F21661D4AFE9E27328E077B522B50FD9AE2E3 DA087BE481515B5DD7BF894A96A84A6C78874100505B7DDE1D22EFCE8D58B3AB 313AB5495F72E2CA4E6AE22C0CB854302B9990372F1661D9F0A517F90686F248 C5643008B3D29F7296E5C8FD4049886662EFDD4106E17C879F5D41CE84F87E89 F6A3117C968B95A35940CC29C43E1E0DEF51C1E46B676301F40D59615C3F73DD DE37B72FF7105DB84227DA5241583272AB1C3CD97AE11C1EE98FFDB5E5F44844 8FC41BEA5C54B26341AFF6830D9D0A5A2901B0653D8BD0746838194D240FF753 E99750D3383373F453723D86BE97B571B8B84D8696089B5CFDD53E6C562A2197 A8C4FB0CC690C27761A816B441029D3D306245052E0C41B53025D8CB7267CFE3 C17FDFE348E765326F91AEB700CC49162DF748171214252CBC821493DD01AA20 417D66DF47EBEFFF3E9BB2B0A2BE7D9B8C68BD570FC2EB0FA54CECC318F04C43 19598BDE93F2F13DC7847354C99059AB20593EE51E94F9D4E9241869D605AAF4 9D9B5FD88C3798A039A67993C5EC68B6326B132E647F67EACCA7F7AE7F718D85 12666E90D7C73EF210E344964A38228B236679A2B18F5E081234CAA2458F8D83 3F0CA308D19663CB12EB904076EF88E556407C33C9380A6A3D68A9EFE65387C1 A1BCD2D26DFD2AC0881EC30E81C0A4E76C244A2BD822EE88C4A60B480D107E68 90E419A1F512E865BA922A7830909BC2611A80931CB2E9344529586726614D94 3AC5200FB9FF68AD9686506C5EFA8788C0AD0251AFE7F95E84683380CDB421C5 B1A783B6D5F3A6BD1BC1C14B363DB01C87C0796DCDD5BECF41A1A9F43183CF6B 82C2AE49F0BFDC5DEF7729F2E638EE6EA9E4D059EB9BB1B992AD8C82D501A550 1BF73CBBFE740179B54E193E84A55DCD61B343C1852780FFB44248FC9426AC94 AA2B3FE20FBA30F6C4D1E0FF3EDCDD8C0F57CCB50CDB0EFE2E04A8927E239C1D 9B026C7929BB48461D4D695FFC766C8A0E545B1BCC2AA068D1865333108E7985 2D93F9B00EA0A90939D0D3840D59B6CC0CE2C147B2E1A9A4F14270FE3ACF51D5 99F7349106165AD627CBBB0ABA01ECC6D3A14C1DC1ED23A9DB9865BB4396C51A 31ECD001EAC94B33C34E29C5611148EF3E55DD61813470B8F3CE32564C749414 3C93C77EA5A3538A0B5AE3FC4DA32813B06772E0E48E25BB39F3F6FDCC077E86 F86FA50E18FD19EB2F37311CE87F18F3BC85CE7FD71CA92D5C3264E34E04A2E5 70C79D99F54D6C6D9D527AE45EBB48411221134587D2253E7C8ED7658EDCA34E 5E768DD14E0200470F73C44D006CE8CB35DE1CA3EC10ADC668B0662A7774C891 84EC95A31DD872F0728D9F65CA80940080E04630BE4DEC77A2C49E3913C39978 BF145F8832AF2C4385EBCDB15F9D32C22CBA0CF950877717D6F1591D7C0B8047 8C9BFCB16AF7124ED83137695F3D69228DB633053208C29E0ABA1B06A7FB3EE7 5625CB44927E2DA6E038A6E62DEBDA2D96A03177982D8FA33BAAF4426E05F4B7 9C1748B3FF7691F9888E7FF864A10B9DF761A41E6B5CFAD2BDD7E1C4924AC97B F4B352705316DD1A58637CC12D71C18A5CA691AB2AA8F171590EC24582B1123E 94D4DC587D8F99E18A711776BF4013C96446BFECFEE4C809EA94B169088024DE 0CBD20199A915AA406F0BD5F3D63D1467C49B4691AEBBB35ED6624F2D7BB74BC E80FD92B9FD04DD9C2BE9B6FD29EC7EC07FAB447511C61DD299C783BC09AE2A4 7B3CBCA6A20C6631D06D0B2E2482A50612BB7C29B7E7D0A205EB0E8436702581 596BC996ABD58CD8D5BAAE4B1478195CAFF98FE0141287296C4EFB8D2E7A8442 F0A3AA9F9264329982532295A176BA1867EF732BBAC49AF485D9D0F7130F617E 7F7DEEF935874D55A22240F8EDE4F247D5F73481373A392D40A8076BD91079E1 1CE5998BA13D48D56B49A92B4A18430E316405D2E2E391B496A1934671FF1785 AF42BA3B2D14B8E04014437FD194455C50289DFBA61B5C377BCBDADA48E82DEE 4E70EF5E9DC03064907BCB8BE4D59DE069FB0C0CB140DA54708E630767313F9F 744594AD8A499CFEF733E640A11FD74E46A749F9C7D18D49251BF85C6EB4668D 67598C31A8F90922FEAEAD4B83B6E7184567DC798E4BA1C4C9B3461A478D63CA 054F13B502DACB674EB49D6BB935E5EC82BF99FDA7D47C581AD7F940DF4FC6FA 6C6D25D647033AC69505F0CAC58DE99087F365531A6283CB89CB644688963C3B 8B2203A94294E58739EF23C7803630A1F9121D62BE1977DE2F41687C8CAF87FE CBD7AD3B98E0D95C8C6E1A7CCB0E09465AA874DC90A0F5DB2C5E7C130297FD39 EFE63B0350B5139D09E6864D22C3F1150B29196E40EEF9723E71158B7ECFB8E4 C426FEDCD439420B7F1C251FADA347C9A2C49738B5A17922E1EA93CA7B125B76 57449EAA9C1D591CAD327D0E98EF2D44D614EE9ED49DD31ACAC0B956620B6BA5 5BF6D08CA7541059D5ED2EF00AE2EE95488F5645BF6837D9241C0D3959B7580F C9ECB2BCF3E65C07D52EC9CFB21C11CD4C883E44C173214C900C44D2E1E43DD1 CE8DFE3DA93C38B548BC4EC46FF91F30CFB97525E1FD4E77686433B20BABF8D2 848C1CDF1BCF185CFD7A81D2D4BB826E837E2AF35CFC4F419F698DB0C43E9F9C B0FB628AC9A3CBE9B1FF4A067016E70333E78B32AB2D89C483834B31F5808FDB 77492E099F1504DABCA5722C7860CDCEDB2DDEB512FFCC7D287F4945FD711F28 87BC3D36173566B81FC2C1290C717A09697DAC6072408E20926D39270121CE58 3EF97CE12EDD7F87F2C8CFE36C3C0400869C0D813B71C425343EE0CDF717BDD8 409D5297D0F8F7FDEB0257C0A391F5635E0DB1116058942FF3E7C94D5F2873A7 A3B0ADAFC3835AF2BE474E6741319BC6695FB37F59AEE388F81F6E66F910000B 72E6BA7531B4378CEFEEDC79CCF4947BA1703823B5AB4F4AD73D9615C66C489D 99D68E49C9BF765B7FC547BAB9640D51D5A7A2396507AB5A4DFF3D14F52422CD 8FCFEAA06A56C6C7FFCD29C9A7A59DDD2A909A9363FE5F1E9629616D25ED38CB E754C059E4379318CC491C3B1A90128693AC53F80F8210FAEA7EE638902A7D3C 82B95B3F5AE340EC1B648DBB9FB679D6E80B7F426D8671FE7136D97F51E2D2F3 C9CE9183E4061CA40091A2A70DBB9ECBB19CE3F65ADD0FB346B54BAB182E2CD0 EAF4C0F402C25573FB344EA771B297BEB615FCD0595172E84ED2A62FF8962634 23C19076C2A9ECEED5135994EB397303A9619C76DC55E032DA83FBA441BD484A 59F70A5110A8927F6239A14D4E223E189A5462E4A92EAEFFA4B961A2A32B320F C2B4E8C1821FA67A655B5042C15E4DE1FB3652B55078DB123573C4E986B19DB0 1C5131F3DFAB271C30A5476B4A19D8FC922E31879C34BAED94C07A4841B8209C 403369FB8E842610D1EB4662B6171A4465FD0E819964F62EC5B0ADC92F08CF90 1DE0B410FFBAD16F6D355E8AD72CCF67961EDB6CDA82398021007C2D0462E893 75EB0710AE4A6CDD15077C9DEFC5774EF4A657734D703CE42174259B58E5277E 0DF26BF59AF8D1A3E7DC12E3C12AA4B67CF35B19962F6950C2020B698D971B35 82FF84E72F72FBB0C54A112BADBAE6C4CAA358BDE6A705AB59332C3850CA3D25 C7564499BC1319121CE0D93218210C68080AFF33420E3CB3A48BF9EB66BC07C8 A79D8CD8E78C200FF7CFA3DAED0B9E87E6141C88B436D8FCBA50AC195FCBB9BC 9512B95FE3A37FFAAB39850FCEBD4D50A243EA416E73F53B4B00F3B6EAE0CA06 0693AFFEF215D00BFCAD02E45496D7C8F5E99EB9096FC4300D038C1AFD31EC4C 5ACA6B72C1BE7204E37A4CBBCB1EC26AB87F2FF82DE20601025169A5FBD2D060 62B5B2DBC288C79C33B596832AA18D730AD572C6EDFABCBD36DEA87C0F323C3D 6E537AD3B43C6F3A905597570A8C6B0B4A5E08C08EAFF9731E745F2BA8ED0C0E 1ADF7821CFCD4E38F3F4C243CAD31D9F8FC68B9043740852B4CCBDD37BF728E5 648215961FA82A0C847ADCC5187331D0863A4573BE520C02CAE14AED4F06B3F1 FB4A318AB54CD86DEC824707B29F858FD726A167F2333855C0575EAF4EBEA0B6 754B1775F967140641FC06F82B191244186FF347A351FBD8FA62E8C978B21F6A E124929876488AFA97FAD1A68A0C3496BCA768F4AF8016D7A65BBA3AAFD7F5FE E75FE714FFF3D54D09C9747ACA01CEFD260985C6E87477C9C7843343C7E9E3F4 0537D461EF019E046DB8A6F08DC7B007337B688E610C55A35496196C01E6F8C3 C7ACEA49F6AFA7FD9CC809E9916813F64BB5704664DD21422F8F32477EB874E4 D86593B4D4050C116B8861EFDC6BE1ABCBF942F0BBBF4E4241C418DD1263F252 B16F904E5B650CFC5763390916625B28ECE4C39C55CA937E28093E66A9837BBD 98666F090E8E06F1934736F800CDD0E78706E3F1CE6D2EE55CC48D1302770DDB A139EEEFCF8353D4473D89EAD552B810E0F1737A6636D15265E0FA2699BA04F6 FB68CAB1237E29BB528DFA4F5FA91D651DFB030977585D1BCAE3E7E4D8CE5C9D 7EF3F0818C89DBF49334C1EAB88CDE3679F5D99AE73789CA43DD7432F510FEC5 64946ED2737E35744E2D6B4B2018C8C15CF9F23E8707AD638C50E214BFA28958 1DF5D70CDC4C38C41B7245F9D92ACE89EBE7A1FAC55B19122391382B33F768C3 9D6EE6CB83A7C18813E56E02896B1B34D7CB8D86B463C6D17578F64B3A758498 12954761C3B140EF7BFF72EBCA30E296D4F8A6A918191C2733D368D30B7E9B47 29B6F2C6EE5FD0F73FAEDBB6112BBF87107BF9D3008CC237496422661F2D30DA AF3DE2F9B92BADE1204B6D3C502B44F079BDE6DD16A634FAFBDC16C418B96349 1C8008696A2ED650B201F1DB9F10B4CD2F22E0601AAFCCFED995C712D4FBABAB C882338686FC4573D1516E7677BA3301D1A391C1223C1EC0FD493A28F897CA3B BA7BAE21AEF1EFBE4D70E95911988ACCD6357223C8DA884492A28F32B3767E8A 6E4DE35DB7F2E33CC9D20E19E2E76B64A96A3E4F30D41F1F583AFC672325C5F0 07DA305F63CB575BC51711EBA10A20958FE804BD185932B0C7E8D93315E7FEF1 C2B76878D72A3D9A61948693D19A67AFD5151A85B694B0E3B3ECCC3A1576CBCD 2CFFCEEC541EACA75D52CB0109832D0A1C99A3E4816F5B6899F4210A541EBCEA F1FFA31219E8DFC8CFAF0A309BE2C98E9E8F8B838E168B0C58093AB5AF57DE0F B4DDA520A169982DC5B3F8E4E382D01F4971331D6FA1CFB0E481A3ECCD393D74 6DC2335CAE00F059F2B86BF2E3AF6FB34009227246B4D958ED0CF8CDE709BE58 21CFB8DA9DEC4F1A9A23B555B7AB66C4A0D5946AE373FB1BCCDEDED21D95B434 9B0854EC632946A814E3586C10BF0516D47B8FFA4821791D5E570478A87077C1 73560DA9976B306ADF5DE0B891000A248833CBA9EC0B71DD2E52616413DFE681 CCA597A28460F96C7096D87868C7E2D38EFFB186455BB3FDE765C6E0566B7A7A 1B7D5F88B386F94D28587B9E44A839075A6EABC8BC217FDBE30FDC4F055167AA F4A9961AA6616D1124B27770B40F297EBC33A0CF2B625CBFF10A27E2B9B1F8B2 0F723E7D0584333E8CDD2A47F15F098F242AE43FF4E645E49C953B05BD935384 8F54E90486853156043B0096E3271633160E108F712B20B39F35E1366F728DD1 59BD1A675F9F42C811545EC3D367EF7F84369E53E6C63C04DC71C8FC578E8E7D 7584697514D10BF89A573BEB2136595C3EACAB6E6F786A20316B992FC810CD7D EBAD5A6C99BFA1EA394E5DEB1F2C39F1ED7AD5785E581E125EDD2424051D67CD 3CF5EF4349B3091447823142660D2713BC03510AD7BB1B282F41C18E05866BE8 592E112B33711043EB837C589B4C2DD401DE948141981D459C4A3C8B97DA0DB1 BE657B9710C8C1FCE396D4D0720975D3353BFC9987F5D0D3815947AB1800922C 738A88E22AC372C7B61BCC68EE3647410AA0FC495E6C9C2CD314C668AECBFE1F 62CADDC2C09F8E9A4E6522DD36EB90EB3733E70225735185754454FFCCFAEA96 74535B16CC24105ABAA802444D40E9EF96492EC936E8721550729AE5C0CD8344 16D0AC1D16D37B63AB62B09EBC8DE5368AE16C842675AE4776EA66063B96F015 59756B4C1D7105FA246310F1A835FE299AEBBAC290931F8EB632FD32EEAB96F7 F8B5CA6B16731BE616D7CC864B7F781E51764914DF795B08C7E690D1CF903A3F 457368EDACF59C3F163691B87FDDD7D39CA04F7DF56D6FEDB4C0C2EA7148DAF1 EB7B475ABB35354DD49E4BE90B856A92487C6B4A1F72E76A2CF70D626A156C70 28557CE8C751A649A620238D6B76F06039C725FC4FDDAE4211FFAA8E04ABB1E9 5809392E1C559613A6C5684C9BCD0BB25E144C71780EFDA18DAE01FB4B0D8197 B8EED3F4029A003E6B1026B21FCC8B9D10C887F13AFB0A5A71910F09B41A4FA0 1DDEF0892D103EAC654B8CA4028D3F9527B930F4CBC31A00EC2C5CC46E1E3BCB C53DAE1343C4DA0BAC190D0FF99E349BB7CFF37413D1CF6D75939C668710D787 C0FD1A531D923C598EF3DB58679FECDA7B0FC6E6F8F206D736727F16D3EFFD21 E66E961027A343146106BA16C420B92EA1ED3CB27F8027DCFD49701512B92547 DCBF93F35DFC940DF8A7084A2B53F280AFCBA00234CD1E0F81EF0E716271814A 072115E1A50DF4F1920A1CF0418049EFB6873F3356A6CBCA578B7DF1E0EB104B 25F5F378883C3FED59AB842DCCF410261D6E5D7A138BD0D7B7F41D536E046342 A44E469BDBD7ABF3667674E5361CAE364147735244804783AD09C38E6B32443F B0269EAAB8786A9A827B8EA80FE7352771B430EB60B9957EEAE2048EE60AFA88 8DD61A09D8787F22C68C2635AA18D6C51D9DD3D3A6AD6D4EC84A44AD9C0F4206 0F65E9B8C9EF30965B4016DCB113C24CA1A34E470D44DA36669BC34B89C469E3 E57C65B6AF073FFF4DD2E5B821ECDE0779703BE2C06CC8B308AEC8DDF7896D86 59B3EC3ECB9D699163A82F5656BA9AE6A83D5A50058380EBD27BEDC9C75B660B F728B176515817BDB4006D332D2B3AC9DC52337478F50B789DE88B9F2FA97079 31B7AE43ABEAD548FA76194E9360A35E8EAD1388A801BBE603B39166997F86CC A923E87E2124F8489E03B628B1E40BC281E59065C0586EC504E38362268EB9EF 2D67C9FDD556E13A47EF223B186A2F64BC7B79F967C51A6C03DA13F19DB5F768 C7E983A3F75F99771AD574F2CAB2D817810BBD406EDBDF60F23DB9B2ACBBF35C 25549AFC9C54C431975A51E92DD24F48560DBDE742B360F24E85E0BD6CA7DFDB 70D9A45A8F1AD21976094FE996E2F26A7EF3BCDCFC18F77794195DE199C7E82D 6C173B49407FAC50116B04C25A4E5B3F2D939955BA1066630FCC35FA9D7A16E9 5CCF342E3B821279991683A1F0DCF2E200EB974F92F502F501969E8E0FA31A02 A8FA282C5209B531380FDB80A635D66BAF7D962F7E7B59F5647DC667B4BC8961 4D8951D8B316335FF4C864375E490A261B980EF84D5AA79D77086FAD38E4FF57 827914543CF7FBB28457FA66B1EE122379F580300F7CC38B20BB660BCF4C41B0 AB422E31312B318EBFB174A9ABC8DE86F82CD7545387D8D2176685B16762C2CD 7017EAEC5C28C0F1FA53F4912AE56D5ACF9AA86DB5EB0767499AD6780BD60218 CB8FF23BB2DEBABBF02EF4E19AE8DC824C2F71AABB90942AA575246A647A4EE3 3DE544D00F47BE571D17CFA4FEDB8052C4A6D8B1982931C5A13C56D28DCC98ED 2184B048B50C611DFD6528FAA755BD89E615C4962CF5F753B1984A9149C731CF B6742E72E33EEBA9C102C40045D8DACA7A1D2764E5B788D3C1F2C766F9CBBC98 CA005ECD69DF4F1D7DACBE6EEE980D640ED0C106E91E475FE37E762B152342F7 DE01A2A5E69C56F8D7C30D73A2BFAA6A01965A5BC4996658C279C003FC621A36 0BB44E67A4CBF17B68B69CBDD80118E3777B53051C38931569B6C708C7EBCE0D 55D3E3CB788B33C05683CB186F31973266BA2A4933E3A9A4CB507534520DB01B 4C0C2996F8E1364E2713F2D404E4447FD064E97912830C17566C309755D7F188 419A2A3E1BDDD35A4F7C18FE16C099619C1489A4E37C8EAE5EFDEAEAB16E8864 B4AA9CC7D877DD9B53D58FA6731161818E539638E68A8BA00E398B7ED74E487B 6F6250BC2E040836A2F416A398CC5E1421627185E81C339B4C1DA29216FEF0D1 751F4377CF1D9A9908C753352C37DAA830986946AE0D1C16C51D67B6666FA9F0 333743B4AF9F336E0B17112779EC035DDBA628E610B66A90947A2E75BF7A3EE5 0B3C68FBF220FD5FDC432E2A390BC6D89F89B3258F7D29D8EF4645B1EF3EB927 0EDD6CAA0D73ECC3AA07DC0107064CD29A6AA0A27E0A89A41BAF8C47A96D8DDD 4BBBC4AE18BEE986F5F63E7ECDB6E2068EC38F13D692B32490A3444CE4488A64 87763B130EA45715AEA8AE5FB3D0FD64E7DBB687ED7F0593FB3A696C73DAA826 A46ECA206EEAECAAF0DA0A3E33B7B73081A375E3F67C0E9A991861545F17E7C5 5EF1207097CC2B5EF951F9F55F477210DADF8C252D2D58250FF67D456A7E7F5D 7B3FEA0DC94C1EA62BBBEC4AA866ACBBDC17575C08BB455ABBAE80D3444A4F36 BD75FA9D98279315BF0A66192595794E7DD746EC3C0E5C70EF9824D569A8C4D6 33514F324344A70B9D4C28053FB2543AA58DC7E709A70673EDA2786096F32EA6 0D9F15A0C4B334DCDD35C659542F065668A9D666F7CCE24369A6BDD5E0501B6D 6C8F5E7921EC7B2A966800F50E63056AB66DB66710B5202A967677702A75D372 15F95521CDE9BA0BA6E3418C72F17A256B3E4B30C72A962207044FC299EB8815 ABFD76B29033F51221FD815976F2F9F02C0EA898124BBCFDFB428F8FC3DB9E74 1FF7A830B7E1C7CB0805216322139EA2098C715DE806CEB70FF638306F6EA11D 1B6AE6DC794395C11CEDA7F96F9E48C2F365DE2D80D6AF3DDB7B3D484BC5BA63 F3E93A17A7A1DBA8E3D94567B08C5AB90578596CD5AFCCD414F10E404EF2F1FB 65E9EDB3CC34642B6F80FB7F60D98863339AB4FA1F47B6E94D7674630D8BF408 4A6E4127AB9A549A1C9C203DBB6B1B15FE8706F9BEA44026F2C011F717F33815 578D948FDE2E46B6C59BD61CA6375E441AEC54CCB38D9DA77481866003088ECD C798A14E0AB713FEDE8785A5FED8F2C7493CCCE9F0DE7FEA24FD640BBB11BFE4 D91895527F3CCB39FB702694D50B52AAE681C793493278C719DC5993EE91F752 E1034F3D9DDA55BC51BEC2FB8CD807AEB173E0501D54045F688A55E25ED208F0 D58EDA80040EBC93B8BDF6918D1C3B35C55929E8A98A21BE6345DE8CD5292E13 BEA214A9FD0FBB725147F0925CA143469405088894C435552C96069CD69175CF 7FFE0D07DD81C2288AFF9E6F5A5516C052599E582DF0DC455AD667438BA261BD 009DC7A66DD2A52F8D969F1C516EEC72D92E8282C33875C801DECECA7141245D AB01A7D642C9119AF7A3B6D101830CCC7C6C44E1CB4165CD34199517368DC705 864DF030771AB122C0B148D10A426F114644B2D6FA2A4057220EA8BC2AB71B02 C63D6699222A1B8D31B058A8E3A0E61D5B4C317939732AC00277461CBBF8E662 721D302EB956808620610AFC11AC5FF0A590473E5BC98F2D35AED31C0855B15E AAFEAF7C70761E822967AA670384CE6CA1AE967EFE4ECCAE8FDD31E56035AF38 732D5D5A5FF9EC47496E78575A26930C3A4DFCEBF8E5E5424776C2F3F6CA9114 BC9D85029C1FB81E6FE13889A10FE1461FBA61FF00AF5921243AF0644F8876A0 FF2A31F2AC779309978296438E9AB191E51826F43CB443CBE49D0D539C04E5B6 8CE901CB470D2F27ADDB91476451BCF60003767C3548AAA6C5798659168990BA 2D3A0784E8112F40D9EF861966A582199E12C578A53858924DD5445415F6D276 2DFF9D9AC0602F0FCA3AB6AE470231B33AA21715C261537597B1EC01921E06BB B3FE7B65081327ED6D42B727B64AB8A84BF0873AC02A4227FC2E70F405481EC8 6205189E29BBE4D28604A2F9D0F116E2E17930606D21847A09A172722AE1B8CD 45D14291252453A57F5A9290C266EAB1581C6AA5D593E0BAA78E982A2C97126F 834227B6CBB96C9E5FAAD3F795E7A07A82FF88DC8A83B3D17F526BC8563A08E8 F9DD4571747D37E87CC75529721AAE241A8DE536CEB128A8255F25812EDE4DD2 F82719DC11C6F0DA1345D9DF6030210159B107FC60B762F38BC80886E50C1DDD D856FBAA612E932132E1E4EE97C830C8A7F64EC53DA53A4E9C48B9FAD8C17790 2A033211B3817B6F289B1CF34B453F4F762715A851A728C6290F2134AAB296F6 E9FDF1B99016577A1428C5CC1E86F682B01A3B9438EF0FB7C79824902B66A148 06861F6EDFF266AF1C5262FF26AAC49D1FE43A27013FDAD2B76E0F03AD330215 927F3A707A78446E62B4319C366E508226CABA2B2CBA56270815068457AD7834 6E1D763624218754D4895BADCAF6813EAE194D0779ABD758355B9D5AE4315831 90BE688C3032C7951E78AD8D6692C814EFF6177A6B8E6ED289DC9B18A71FF7E2 3864FB6ED54CC9E41E65D84DE20F82F126B6B9F6DF4C9069EB7819084BA296D3 8DF06C2E660E97CB8CB1B18511A3BBE1DF893511F1A0F78CA4E4F7A7AA825A7B 00C3B1DCE7134F9A4F54C1F0F2CF70AD611369FE2155AC4B297732CBF206EB3B 04E674D21E42773F9F1E8ADC506F0B96A115B9EF416A044389986C6F109B4C7F 11B24BD7D514A5090A454D8C8B65B3253E8EB205C2934BBC6DAB1BFE5980F77D 32458B36A8B989A215B6224421CDCFA7D1F8367586DA1A4926BDE5E2D4254554 366B9CCFEF3EC6D3C2B2FBD3BF1EF9F2D7928511436CBA7B56EA1CFE0163297A 5502535114A9BA594239C3A062A3DA23564A70A053E31DE64A1EA6A93F747E20 D225592AED2508A0C1D654DBDDD1D99E71BCA9027AAA1F65F30AC939A59A222E B8A56F4EEE3AD2348E49B435D3E05779A3F18C8C53FC50EDE8D18A56D81D809E 99E9246B59A7A51D0826107A04450DCD8007D724FBA1E2D638E06F13C4C5C471 36C6B918C0EF3A92FCB29295720FBDAFF55A9E13A6253A71597FD7B847969967 C92982543AAF66613EDBC0885200444A8DB1707E0A429C44BBA54D4724D6B204 1247F4C3CB0808D6798486F5C2005FFA5B7481050ED950CE5C61E6D6504A4FB0 92A2549AC429C9F4F997A06D29409E06AC756F82C57CC151834787DFC9ED3E25 E05693F5D4E063A5796404663219E06A86CE00A5446AF8D44FA448454F5FFD81 C74399D753F837DDD6AE88343B18CA72C82DFE41420C8FB8756A4D40BB4FE81F 886475C83DC5612270B0A6EE550802006EE0DD529E606668767E1B8D8FC3DD6B 2322A91F8957D941DF4CEE7757C40D49B9D99A06CF88C18ABF1049783D22F815 93A7B3A405FEB7CC73A2DC5E4473EFBFABC5FE751BA0EFF0878D5F546D44CE9E 6709C58B5C3F2FA6F3BE58556DC4D5F20BD506CF42464D5F4C86530B51989ED5 A7E45ED0D927BCCB02DFB0FC278B529CE1056D6F82C3E65E918E5858C4E5BAE9 3B8B8D69EC9A5390FE737DFB8391672491CE770A1CAA352B3A723855F9306D49 FC55F5CCA5AAA8B61BCE155DC3B3D4C434CAD525B1782C67ACD4D2B62D044274 FA31F184123765CC476799C8A329FBD6C2B3936C42D71508C72DA860F0A053E4 C9AC6AD3649AA632CC51FC6014DCD0FA38E00E369191EB66C2878D4B385C706C 6C51E8072DEF88FDCE39E426670986E9534DECB8252EA1BD0FE8D9E99EB073BF E4B0F03C62F44E5ACF16D059825A4C211157C4AA5C5C5798A1423685096A8099 7D4FA0881387A6765C4728895CA0832E19DF2B8E71058DFE6F91DEA6239614A5 DB1D28EBEFBBBAB6EAC9BFF447C5BD66CFAF8B6A392691C637F3331F62F303FA D6C43DDEBB590E39D4169AE60C2091FDBDF9497DA1C84933BDBE74B79211D66A 57A8C574F8E1AA5941F174F4BF4CB6092157FA72D4455CB53D332F6465433610 F512DA9BF7DB49BB72023DFB2716556EA7016F911922C0A4551813B4743D2825 C84C90EE01D4ADE8FB07E927F8652559E4C206881B58504B537041936B769A3E 6AC3E1D6DCEA4663160FE730CE15F76C22D69EA1F00AB797A1A0F3800CA3F415 417655D73998D3FD7FD610FFE8EFC8E2854B8A3B211CCFA9C10BD50821E9A89A 422036BD668DBEF3CB3C210B53A913C9B95B2A49C4B681457DAC5AAA2258AFA4 F5515C6892C00D1820A90CEAEA4AFE9351B50E4F21ECB753241CA1F18DD0F16D 2383E200DBF477EC0C2D3AAD49BD90379F94E821E7E077CCA50A0E2232EB3353 C364DC4F802571FA392CC8B59A3CC3E954925A52FB60473E76B61647642DF158 3709ADDA7B8AB88A36970145EF6FA781494F5AB6E99F2D28F9835C5F31B2A0A2 C20E7B022227D125CCE47CC0A1FF309A81718BE1296FF73A61724CA03DFC40D0 989A6D46EE18957F6D744B1280389F207E0B93946FF62EBBA954DD7C2236DBD2 272A7B38F300943A732D9EDBC5C59DCFC17B1FB3DDFF91B27F29DEC3EA4FB4D3 CD5DD97609F211D50927629FCC55E1A490D592AF95EE138D9718ACB75717DFE8 74692145E1885B593920558831929670801B8F60563746CEE773DE93D79965FB 3C0325D419AA930138FE6481481FBD2F7E3A950792073F30DD3790554B5E841D 5AFC834800E28E364632125CAE2516DF1E408B8D6F1E1CA24A2D044224CE079C CBB6A0FDFBABF02CB5164193781BA9945B631CA7345B9ABEDE9273D9A0A2643B 7BDC26DBADD4178B53F98B90B30089BFFAFF07699DE0A515784E532F3187A0A9 9A10D3B458FFABB157064B96B97CAB90122391F4A13C951F5CA203D96F3BC2C0 F44982E055272D4B527660970F66F2061397B0DBC733FFCBAE766D8FB3EB4D46 A0DBDD5ED3A69D4F8BCD39C565D91805F4BEB6AAE731D6761A82F661A0708B82 6B8E4BAA15534AF560BDF81AED20734109E862F9E835C2D570086A681DC29D57 A4EDB84942C387C8676346333E4BC14699440C18D8B11EC70AD5A62A9E21ECF2 7147126113422E0203BE17621B4FE6026666AD30B65C11C3CDAC665D8BD5382D E7168D7857D335070C614D4EB8A64FCE768948368FD92EB2B244871E2F73E1ED 2D1EDE69653E9910730FD34B9D8AA52420E86132B91E3862C2BFA7243A72C25A DF8946BD6E85A99750D0AE5FFC076756F50B7F9817FF723A5DFF47041C2517C7 71846916317D4D6B1A2A5312DD3A3D3429D0862CE1263C7324DD47C801D8B66F AF06E38AB2E8FBE329BF4362A18CD6135783BFD5A48DE55C0E169CBBED290BBA 1B440E6067453CFBAAA4F0C42C2537495447BCB8624603D3CCC0F7165B59C820 C5241C327C85FC368E3EAC86362504A872F8B1104AAEB3BF87FD5F7310FF59A2 F354231163A670A220F1390BF886E34082DCC38BCAAFD8C6119524CF57246F86 6D1C1844286A2E53C6B1F5A070A57A807BBC412167935DBCE33C878621C65D99 1D18F79BA65B3F22CAA1990C91E7CCFA8106A5754091CDB21A0D5C7EAB330548 9401F0B267A6F79110905829C46DEDCCC41C6AFA2B7CB1BB86256AD3DEAC7DDD 554498A0B43E6D3E1824CB03EFB52DAB9B567C7650A3D504DCEF996914B2E26F D826A24E9387E3E188F2F568D982C9ADBBD844B9E888808D03ABCDC5A0F8E085 ADF520633CAC6C9CD30B4DF49E1C335CD80E822A08D61BC563EF4B88358A0515 96877DE1E379145112CCDC7F0FFAAAFFC3AFA996A1AA6D7C96501AA71344F09B E0B644296B25CA20588981A0AC159E3AC0BF664C08B09515EB84962AE4DD6176 57FCF3640EAFA5507BD4734F1A824171DAF836383213C7EDB74314455EF3FC73 CBC4A700C6C5A0955E72C8B28C81848F4F4DBD2558ADEC87632B23E68A4C75AF 5C20F577F0074EAFB5408C2448E0B7E3AA410ADF8B66DB1DBE61179FF95BA710 5DA4B472E5D56142515462A8EAAAC2C0CE1C909F5FFA569B8B355CBE10B80A00 1CD122459A3F1438D9DFFF2DED17A182F08612C2DB2146CE248496166FE89B56 8E02827393ECF154C32E026CEFBEFF3E32AA3A8C360A746386EBFE36DA97224A E25BFFF8780404AAFE00592A60C225AF2D8261901EF49DF260BC9A833D7041E7 E5A54AAEEC9211E090272394BC0177FE30588FE1FFCC1AF58E1B315B82E67410 4EF419E493B6DD5C4F9DB229E427B9690D7150ABD23AE8EF8637BB24246F0C83 F591BEA72398319FD9FA5A860A94A83C113DA9C8C6B8AC0BFE072AAAC0B24669 D2C8E2B6B7D979B154202B98164380AAADB00E6EA0712855FADDFFE430CF0CE0 6D021695B5261B788DDEE311AEC023EDA362F37642CCA95691D34034D04FCC72 2AFBB4F6B4A53FFED88AA70F10DB2516506FA18940B8433CDD0B854CA373BC71 68B3A2B0FC8968E437B69771E63AFD67A202565BDAB2CB797987802E88D39221 0622C2C2E5ED46E39856B07D81DF97F85735662ADB4DBA927398464D428FA79D AF84C379568294E999C195B71468DC7FCA62F161E45BF1EB385786C071F65A5B 3069A6B6F5CC17173A8EF7CBCBC7C7753842D2A3BA3B505E948BFDF09858F4F2 27E5605E76559E6C512A1852745EC34BA103F301F88CFE5302724CB5AAFA97AD 91F7D0664696BB46E0AC6A8BC207E48457134BD4E4B526D24C0511E22C4BB010 A019B7D645BFEE8A99692E825758DCBA53AD22A0F07D48D2030CF9D0F6F33CBA 54A6B318341F6D9E8C7933C9B83C459B3ECADB93040AA60447901AB6325E3B4C 8D4A1FB52A75826004A8AFA59FA2A72CF28FFCDC943CD74F95BA8D57CEEF1668 04999C442B9A9C8BFEABA9CEDD6E1BE9947B9F6FB8389E4765A3C01D4CD16BB8 AE498C7D5890CA9894FEF625964D3A122ACECB78DEBE615B97A973304BF64EAC AB90482932707F9F6A4DD81904E577FA26C2DDA48EFA3878642E309219F7AF32 0732B71F4F49DFED46763636B0C4FC0FC3019762180354B5FC0E55988986349B FDBC8CB1FAEDB6FEF383C5830B4CBBE6554581E6D2A07765171A2C24711E4BBC 8EC020845AD64EFB12A0038E1479E893D83355D7EEE8E77FB51DFE686AEB6E80 8B5789404C7C2B5598A44CAFA7E888DB53F00A02D07305366222D56B66085F92 349E572F0BDB481E2F9C6A82959DC3B4797A03C6A63F2A4DC64617EDE8181E0D 26A90AE1B08E6D1ABD1272E249C9F19E4BEAB288BE2F0E9432E005F5EF389F88 F2AF85A6195E4EFF774EC68105837DF89F8FBA5CCFA64D2B33B322CA521D83D3 FB78E52DAE2B2ABAD94CAFB3DAE3C39B1E3C5672C32B217ED7DD9A6C3DB09688 F86378AAF1F4C9CE909C20CE9DE76577476DA70277B288FFF37D26F1DC6B7DA2 28D5F077CD9ABB620A20A46A5E5F38C7A080C783CD1C170A9434E38C28F240CB 09EAE733F9477FF9CCFC4B1F944033F2ABC1383E4756F49E22C2ECA5EDC5D2DB 523C4D68FDA0F6EE8409E7709B3BE3E6D1CD0020C7914470B34E4E2EC06E6A5F 45395132819B639C5A7EAC91E9A196163BD41CBA3E72D7412CD6E191EC61BD2F E289EB694BA5FAB788E683C609774ECE4C212D278C9DD53AD3B5F82BD885B050 C512152A97C4FC30470239E015ABD5D8F8E75C3FC101DD09E7611D96C052AC5C BA92B0E539B8BF06738821DA20678FC789FE46D70827466DB60C4D9037F24BA3 4A8714CD2062C8F829AF6AC6AFE5C735A573E35CC15DEE33C4E101D34EE00060 8B3CF9D4FEA528623833F67F1475717D90D30CFAE324694C9DB75D47FB314AC9 28FF316EE97016729EDCAC1984F7D41969D030405CB9E32262CF6205EE3C618A B2FD935AB2858E7A726C9D63A9F8E3267351FD4B7D2E2ED5257E8961646664B5 49C098C32A45946B212EA2C99E2F60346EA46B5439B68162677330D6F9F9D029 D371CFCB78D7FFF643647F8BD3F3C5C03EE1146A1FFD5F7B1D808C5C74F0E016 E1E6F8C63F3F9EC2CA913D5E0B53F47078FE2212E3218CE5D613980431AEEA58 A3DE12746E2722356839FA4593F21FA686C59ECCF5975FB0F3870985F92FF5E0 4D9828A6B40FFCA68765D1668B90667E03B78AF567ABB51911B9AECEBFBCCFFF A7353A8AD6A0A006861DA150332B050B39548E8FF3B76B92097A94B684E999AB 3D4C2DFF4D3F26748900D1C2C3F064BE38A96C59FAE086E871033D8E6239A29F 6C00CAC1E7F3B2416B811DB0509BA60D2AB67B85CD0D78F150F081E585A77531 AD109C82F5EA7C0603A54B858F559B9EA5709709B658725F152330103DED9DAF 1F7547B828AC8EB807389AED364885B2D318C8B2C1550A85FF60E7A9A2043C8B BF6DCD0DB5891B7539FD619378844B2F15047DD021C04374349130A53CEC6D0D 7041D74A080913AB3E60195A341C6A137AFBCC9EE26CE2F674992957A5E39B8A D9D39CF7EBDB41F96C19FF4E78ADADBA8E06EF7E3D176C5C4F8EE24CDB6855C3 17C2D89F8A4E85F141C661C8319A17BDC7F6F9D226054273F64591C4F814CEDA A62482BA980F15BAC25E048C243CC216116DE22EE1F8F1CA6C36B8CDDA3492D1 3C76DB915CE64E05256FD14A6053B4CB4881C84CF8A11890B72E0E870468CC52 DB7A41939112530E95A601302EA3771DF0A54E3898BEE76D00A4629374B7ACEF 793C0597CF98857D9B22F6C19E5BB350D85FC343C598976099EF35C79DC55A66 6A04DA8A45E73342D11099F47DCBD9C99F0C7097308C09C95DC386EEDA02E176 969CFEFF00852719D9214002013E0F733CEEE9CA3BBA72CA90D9425783384FD8 DE5BAE3B51BE5ECB247297A358C6BC323B4F5B312E2BCB0F447078FC42D35935 16A2143F54CCAC706CA97CF1494E28798A2803548350E890378281C56B21459D 9F089D64914CC149F705E2337A7DC2582ACBFAA93752F662DA3A8C697EF5AF60 0C5A70E686ED741A005E6CEC29BCEA2D8C9B8C4D14C0C637CE3C30291F89B888 07FB39092A713B5C17DF4EC4EE2E745A4D7DE6595DF8F70AD5FE83B44FACA9CF AF65519FCBBE9D61BF65C9BA1073724049046A2CA929EF2569D49E340EDCA258 1F4391D9C9D69BCB9A9AEF048E25251203763DC185703EC7B6412CE02AAC0E52 27DF188EA0221AA746CB043AC69059CB9B4BA3A0C3BCFAA90B94599A3CE6A292 C6EF2FA1CB09E3E43571C4ABA77D4AE8DFCF6F2C994F922EA01B1FEE3D283E44 930D42DD149BF4AAECD77A575388643BBD19FA398DB17CD3CD3BB2AF3244BE3D 935527DD0C37EC1575D890D2BF1D4EF6ADC5D686092A8A86A719BD1C3DAA7C9A DA424CEF239E2F7A4B402DBEDD26F9EB1830D43C333EFBF91A9A9A7B089E3808 2058A2A51740263109746D700231CCCE2DDD7802B281D1B8F9938DC25CB01F91 E488227DBCB4A7605E3E1930EE11BE43E9B987210C708288F95857C57E98AF9A BFEE2C1E066D42033EDB4956617590B23AD085D1E1F2E2FA4CB048F7A27DEA16 894C92DD082C334F88F47C8B30C6F7F38A50DD3DD154FCC11D08023003936146 695AD1432C4919994A1D8368818BC121551BD26F4E6A2717A3AD49BBA6341C39 7AFE2845B125DB43B047A1038BADE14929D6D4FB8F42A89E18DD9E9D197D8364 017F93734437D4AFEA6F33A54B127E1C82CBDF742368C4D35BDD062EF86B40FE A7004D94281ACCA2CA8DFF63431C494A745B07B0905452EC96B80AFF7A758A9F A8294AC30441351D08EF1048CFC78B103685DE80E874495F8D821706C86270EF 77166BB5494439D0CB85D08F3880956C9F8D1436A4905CB999C558D39923EF50 FFDE5D53ADB1DDC858157D7CD33006CD83FE4ED790C5313113A63DFB5102585E DC9642F49A30A76740DF317E481097840F2A444D449FFD53E3A082CE099A1971 6A7E79B77196911B05CC762D6A997E2A8191EC8E62D936951C62DA78C04554B4 FA65FBA1A6D57AE13C32283F3F47EFB3DC5E65A7786B13A60E40FF016B555826 C2AB54FED36C2D09535E1C3B21BB6F85AF475B6B09B12320BFA005A8BC253CCC AD84BD015F8BEF7A13CE20C001C458967EBA18C52898040F36EBEEEA18E7EF30 F5AB3424DF07BCDF081C0A74FF37E42957181CD4F662ECBD5D7F03868ED97CE1 AE4C7ED4C298535F250A9B1B0243769675C5AB9B079E5D364F0ED8A890174B1D FDFC1D7E9225C4B55614C5E472E37CA872B9DB57C19781F613DCC495218C101D 19934550A50569E1D7D9BB7EFE0AFBA27CC08A3DEA037C3B4D6F40A8A1400722 03661C62E871FBBEA90CC523F0C7B8CB6DDE5F40ADB0FC889A2F9A936A43CF4D F0C5F23759745D721D946B8A0B10D7B723C05DA84B85A175EADFF2957A2E0FC5 01969864A53A8F29F57C85F4596618BBC1377F986ED8A06A2558B30486DD7152 F4DF9391059D355AB93744DEEE87D2D159504317E43051ABE89040D8114320B5 5EA855CE1823B9298174BFFCABE9D9A8FEFD6D4B998F179A67561B23446338F1 82A1213EF33B753A4F1E0A6266993406BD39C6301C53CD6D5C838BF6629B4BF7 B009E283F685FFAC786ABEAB2B6F7949931210541E9A7208EB367A4AD4E2D500 BB219A2FFAD26EC6B980745523207C74B15C28B6AEED0669F534CD36C86B7170 C9188C7E329EF24618B8C5060382E2743DD245B1B011CE8B4D41F718AF745CA4 311DA0ED2B0EABB80BA78292EC4A87C211AC758E41FCD963FAE911A7801E416D 302B9532057FDEE6F56EDF11B1FB91CF59D046A6DE37F1E23F97781A77E233A3 B62B1CED2E3AB87225C2A4EEB244CCA7CCABBEF60D7498CAEEA67EAA306FE1ED 78F21B81107E7053E3BCA64DBF7DCC857B90E416A685CB3A871D66D40597E4F2 A4099A1909AA93C25DB66AA036E5643CA818B3D97056AF21ADF453AF1EF623EF 7082F429B4400EBFC981D15157047070E36858EAD9B25635900827BB9D11EF06 17ABD80172D617183E5E8CB868FE15DC403AD8E4986311897F69CAABA6C1C1C3 50DD49D837D9242ECC902DFDE7D0670FF409C9B08FC423DD38A8C14E977604EF 5032C317B6A49042CD09A21B3F5710EE42ADFC2241651F6CF7DCBB77A6B9ABA1 B1F9705B55A55D1F001A729DFA61BF5322454C6A9CBBF205AABE6A13EC1D8AAE F18426B505068E965D5FBAAB3B5C4718C948AE67F75B1901587723D5F97E5E4A 2F8CC8E1CD0698FBB6162C288ADA8E89ACD86B1DCF0BDFF52677EE29D8F51FC0 2327B92B3C0C057350C8AF6A0C3AF9318B9DB56998360DC08B3EE34ED18DD35B 5521CF9442208B9BB80A397A273DEC85DC70925E8CD9019C7CA86018CD604BB3 1ABE9DEF0D2CCA50D94C279DCE48FB04EDE27935503C83DA1A3C1F2DEAA0BFB1 787302D2BD4E036324CE2AF85D5C2977DE86B450AC8A34112E886379BAE0BDD5 38CCD0B3C8424C1AB71C168448FFA1C603FFDCC16468C3610982B46B52B97D88 734596D5485E37618DD371E1C079A7330C3BC860D485244709E2CD975AC530AD ECC1340E90AC7CD93D492BF58C7889C6154FD5480E88E9BE7D898C057F85F906 4841E5E98B905276D5A0132C2880022348A96250D3D9997D1851ECED2495AD78 FB4C6D74BFED40C25FDCB74A564D82E3F14C0EC8ECCC98E4AC29A488A4B7B9A2 6432F1D3B4819BA996D5CD5D61A4251358A41AFF25C70572F07242723BDB130D 99E10BC5EADEADF3CA82A28FA8DFEC5EEC4A5E5B99138052AF0DD311B34A8B9C 835769C1C31C1EBD74239BB8A93FB49690C475A5DE87B6E5A04DAD93B69ACE86 233BC9FD6949F2590B405EF8330C913AE7119850FAF1B5F3CFFF4180B5212592 D20AE2982FCB090DC5B15DDCBF88157DFC0F039FD1CFFA367C5C29AFE511CB49 8DC4AF438AA70B3B982189913B00A9BA143D28519CFDD6893CF22F8533566C7E BFBEA47F0FD6FCC733C47B261BBE82F68C268C3FFBFAA044C927E2E954364D1D 35BB1246CCF238F33EF43FA8D707F900550852072CBFF61E0A14C36068575292 29D2F5B4B7CF3F9764E61F39BB3A16707D7AD76531E839A737B36B68EBC9114F 48AF35F4F0DF07DC3C011A9A4190315C0FF7E681F06F3F5BE48079BE4C5BC592 4E6911254E8E96C1A112E2483FC6FA56BC5B2E808A18F6862D348D01A1E17614 6D94525C26507A733ABB464332DCD625A53411E6581404676B8981B87179DE20 CFCAEA15171CA99872D9542BC32754B4B8DA06108630EF6A7BBEF1382655C83A BF0C48D8B3A021D722F3CFFE8AB5357EC2FA45638EFD7D27C4B73CCFA15DC4C1 E2B55BE2EB8B973B893801C2A1CB3A0C2678A74FBB9719034BE264D5D82878C9 D16DC69FE42E39C746CCBE11FE3C782997849F3221CE061C436302596C760F01 CCD1FB407962D6830A9336C02F94FB652AE3C93D3E84B6706C948A75CFDE2FCB 460FDA44F03875D55A9F59EE25BE5ED50132A818C9D5C35E852C4FE6190CEE6B 467E8253ADE595DB5802CC60DE76B8D3AD3DD54BB5E0CF0636B87B272D2B748E F0E7246328C4CC5A2D2E9B837B80F8A6163C3DEB2ECFFBBA894472E5FF6F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMTT10 %!PS-AdobeFont-1.0: CMTT10 003.002 %%Title: CMTT10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMTT10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMTT10 known{/CMTT10 findfont dup/UniqueID known{dup /UniqueID get 5000832 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMTT10 def /FontBBox {-4 -233 537 696 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMTT10.) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 33 /exclam put dup 34 /quotedbl put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /backslash put dup 93 /bracketright put dup 94 /asciicircum put dup 95 /underscore put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /braceleft put dup 124 /bar put dup 125 /braceright put dup 126 /asciitilde put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794DDF2E5ECEBA191DB82B3 7A69521B0C4D40495B5D9CE7A3AF33D17EE69979B82B715BAD8A5904C5DE0260 6C15950CCF6E188A0CDF841EB68E5A2F88253E382140F87C87E55C9EA93B8C89 14A36CDF630D6BE7CD36DBDCE22B21778E8648B97B7EC6742EB5114BDF0454B0 0EA7B1FE236C84C0E5308C871F67B973892890557AA12E00B2C20C71F516C397 3F3BBD14A1D0149CA064391056E45E9470FC7F6F556ABC82653B3C8049AB5CF4 BA83C8F2158C236B2FFD4208846013BAF4165E8BB8D334C8FF2E8D74AF5DAB2F D44788869B08399421AAA900ECC6A2D594641C121660D4B5F512938994C18DD0 FCD9B008F68F0351D21ED735B2740CB1E0C1CCD25EB548C35B844601D98828DB 556F71D07E081A593FF12DAF83676492A0FFE16E95717A07082B43A966C1EE8F 8A59E1255E1705C43A23CF29A5E4A6547C93F1680A870EE7BAD8CF74D838CD5E F806911D8FE4262ED8E7F5BC58B92C9C6D74F8AD45FBB021EC7E97393018B9DB B1B84E7B243ADB05ADD3F1DB3692ADC5D47FEC7DF93080669E63281F1576B673 125EDF08016664BE73364F65389F7C3B66623AD1754ECBEF9E5CE6948D933787 A5674279ACB2EBECD3B4E6361419AB32028A27670C9F3E18B746A10B00AF6D77 4EC00E3BE521C02A99AE5BAA98F793EB1228952BE67934B91472E01AF7B816BC 56D7F19F631A1927846D800C107B1E9CBFF9D2DD513B4A8CE2E0DFD77B1ED178 E43FA7052765E9FAF89989D490D8FEF6C536EC0D4AE27A74F474B98DA9E6B92F 15E063DB260571979A5DE2423920CE1F59F56EB11E00E3BB9D466A8263E1E385 2014BEFDA8D1EA3EDA04BE32AEE6CD15C5C010A1DF7F705A2C0C18E87C8DCCE9 05D9163181CBA56C0FAC8C06A2990554C8E759D076B01BBEADE3B5FB8B551390 6C8E4A2A1C6E7D9C708614626F3770C0AB7DD2027469C77975C27576065862AD 04E5E50CEBE907E3E991FA0C627302C0E207B4D5992BEBAB5853AD1C0D271728 C76F40A79392ACCA7358F948AC65DC823CFDA59E1FF69CEBB6B7EC3CF21669E4 70D999508F9C49E2D9F8818CA53C977D93E15FBBBAF75B1E84F0BA62BCC4BAFA 4EEC82D804C8A8C0210F3E5E258BB1F6921AF02BA9861BAD5C3D5FC8CEFABA8A A607E547B802096F7AEB09FBA99C83C9A494B94408DD607CA6561A6E6660C473 62CF8D35F31D052F6C6C8138A8E1430CBA7EA6973D6D510C1A06B3FBD79D9364 240C1A00272DA44B89A9FE8D5BF36DC1B5EBB4A78ADBE9C5EDB485F093D9517D 69E1AC9A8E6C9D7C324E3797CFEAD9A18E82E03F69B2CED7D5DDCD1A218BF2E2 ED2293AE999FE2A4B5213A10083EE0407BCF8007670B8C737EAB30311C868D84 121149ACB4A27F3ED6C0C181C98AAAF51B105F264B5672D7F745131ABAB5BEA4 0C9B43C0DD9116D6DC61F90BE72018F290D26D5E9D341055CAF09C9F45333CDB D45B7954271767F638EEC499F7B53C2CC5774EA7A7F024C4CABFB93D9CB1856A 0C671A4ECA7C62EA5242648A84E7F3AFB9547A0AFC29593CFCE6D8B873A78157 D337CABD291431C0A2CE1F37E0CD7340567AC206FF98E4B5A6410F70F750451C 550EFB54AA259A1B236CA9CB730D2CEF125EC65D959441F7CC9768F777B44844 CC9842A307C72B740680ACBBF6AA35FA7A94825069BF7696ED81A371A9E5475A 9D997F2DFAD339AADF797F7E03E654234455AC3D17702A420EE0A597BA31BDE4 FEB8DBA7C61D311CC90441A620164DC22DC2D373973EF84CC553453AB1B3337F 7B39983B8DFFB3A9425F119B45C1CD37A76F905777B3154CA6200792F1759D06 E017890F4041A385F2238E3C48B6C8EE6F5258463FDBFF7AC762F6C4363926D6 50F004D473B7B7F73CA686B559C2885F1AA761653C727A77D73431E9D110E76A 2E55C68CD50F43997C9B2FC4710F8C8540909829E215678E63BB8363C4B8AF05 9986102BB36580D9CA95CD216B7C321822CB41B2E0422CD077F3B55E0246FDB2 44D5976F67296B5B0BE4B06F6E43535C21164E6C5089C3E9BA2D6B30888C57DE 49DC8D9D46C0D5EDC47ACF2C03B72DE3B69512508539019B759280BABEA12BC9 385308A0395C4CD33182A10A5A229743379C2075D82D8BFCE4A66E1AA087A091 8F5372684FA5037D1B92D50CD9CB4F50AD4F8EE7D51F1C9E63C721CB5B9BD011 6F0A8DD4FDCD2B008F223A1036D90F0F3B252487DE7898F9AFBB3A9D9CD49E0C EF4ADAD5155A98D2125ED5A3D3907F67301649519419F33CD942E8DDEAC1BDA0 E90C431B198F646766A8FA9F8D1561B57E126EF604838C0C1966655CF31FB7EB C8CCC434FC1C96046D38203E1791EC824A3D7AED85C029288D4608CA7668A2BE 484C99639F121845B22EEFCE0A3B808261921AA042AE19E641769E91277BEC29 4594082CCB3058F90FAC4A700A8A827ACA00FCF574ABC8EB7DBCECD97F2B22C0 0AA19E8739B81AF8C6F621D69B8E6F29BAE233FBA655A0AF5BDFD7F5C6B9167C 6BC7AB693D45EF2AD999F5DA3CEFA39BA48A17EE6D9F2C4DAB91AE3F0044DC3F 5D5506CE4675AA928B0092D6F173644F91295216D8BBB14CDDE0AD524A4D545C 1B5E284A3BF0396664081CFB4F186A84A0D24D61E82F4767C1E55A0642720CF3 909FA1AB8EAB78030B59BEA067DEDBD2F1D0340E790AB2777DB18248521934A8 BB38A58B7F633DEA4291B0D5D13E9A882C974697CC6D3B49E030C94EA29B5506 CC29C44D01B4751B453A46A9F6BF3BF135AE87A4CE232AF57B66578310DE41E0 2A6AC422117F1963C4D7CC306BD25A6E724E51921779F22F029733122E23E2F0 CB340008813ABB104380C80A492B3FC6D0BB07CB8D8409E9576891EF6E5C9D08 EB8320DFA31BAFFBD336D0C2BBC3D3B2D30368B9860768FC080D30569C7F7811 0EBEDA2962476113625EEB555490B8CE4C5F99D74ED10F738C61854CFF8B41C6 9402E56BE8856144A1A05D0B05F4CB7EF728B2F4F5A439F18C3B68CEFA41E59A D8308ADC92EC1289DC84CF48D2CDEFF509A145BF945E1E00D552D329EBD2A7C4 21D58082CC8FA790E981F4AC8EAB99950678FD3A7DA3DF13778681B208DD71A0 7C3CBD0664B37C9EDC6B601D79A2C51FB54DAEE849F93209793849104E722D3F 52DFAF7047EEEDDFE744787A5801E4AC2C3D58EC5DDC15FCEE03990C53B0C57A FC54F125A04C8E4A0ADAA725808C587E7DAFB9F784FA2875689979D316DC22BD AA36B306A1ABCF907B63C6476737B746099973CAEA8C1E2C5C41F27E0F7DE8D7 F0D942E34E92F43FE902653D4D2EBB6F3B9F7928B1550A82AF234D45D028F429 067652BD3D391BF423AE72B9CB1E8D91E898161BE3A7849D456A861A2046711E E934DC59442AE7D81661CE8EF727D8D7DDC0270E937E40F896AEAE6171661431 C1025C53172F9D366834BA0054FBFD84503FBAE328B6FDEA180F8EA35B1DA937 5CC3B8F00C206908C2FFFFA6A7AC6915D15EA44BDCF29E2BFCFD4A849535F19B 0D307C696BE8205C7D84B9C77F02EF27D911056EDBB4080E4D3ED72788666CAD CD91B0ECE27A177DB23320A7FA9C31408B4D02D2A4B1CC6DDE1A6CAC3D8EC1EC 2226EC98E51046D1EC26FA20EE62D24747D83CF4941DCE5CCEEC0DBE387149CD E05B19FFCAFC0D117F9A3E60DCD4C815228D98EF95EB559AD0ACC0D50FFDF714 56C3C812EA5ADBB013BBD956A7C4CC0ED7D3E25D5C9AF5E626F18297F75D4957 F5B0B33379114B903FE98BCF35C3FF76FEE1D9AEB711F2962276531F7380EE3F E368720E0292A170A15C5539B1FC7BB954EE2624B504CB8C805B8D31AC38307F 0513606F09211AE64DAC447693B2A0AD15E9A64C34F5A911ECD0ABCA90E9791D 67C6BD202B0858EF96E7722305B8AC02B01AB1706CC6AE875A8DDD15EE349046 EAA65005E7866B506EDFB7A5A2AFD5C9E9DCC821A79EE9C1EA2C7BBA32A40BC7 CEC26DB1AC473C8C3960ACEC581B37D6569E8C8C42950BAB7930B65E1570E3F8 9A7FA719F1DCFDA45A3BF2AAB32C9A93BA3552608A61C623DE59BCB346E87EF5 9CF025A87803161221C5C1C6F6B3403712C76E9D755C7BD68D7F2DC03C14CDF0 C1BBED1D648B905B4B17037B7263C1EA7A7F06FAAC4E09E08483A8D714C19861 327CD9C32DDF850302DD6DDE24912D00C22ECDF3CDFB18FA831A41A7488EC203 F564CFE30D506F0829A96D35A7E09C3DCD107D589B627A15B55C5D6649126BEC 60B88C55ECCBB4E680265D9EAB4CE22965D3B1AF759B01ACB0D0E6C92B6B4EFD A81E6A648708979487FC591CF09631310D46891423F4EC159A73E30D8DD147A4 B0EACF6D45D18CD16CEB8176F03ABCB41F2234747B9733C8FAF34AE5D43D3BA5 0CE0FACFC9B087F84FB6C68678BC6E76022B1526D6E5B3A48EC1A110BD75F45F 1C4DC6D39F254976453F57DF873B7D635C80C42026DE020E5BAFE0DA0D54D1E1 DC634D2621BA184347E5252F645A6A1DB7657C48124186F0E4C644077457C24D 55753C651A9A7B6349867641464B515B821349C795A645420508673B93750D0C 7A3B33EB1F09782033742AE8F3A23FC02284E6C03818FADD1731361542E3FA3E 75B8D52B668C3E18A4AE967D0FC3157083D952AFB8144D549E69EAAC51C279C5 E5D88A0D9D53013DFFB4352A1598FF84DCDE6FA32FC377306B9B92C0F96EE149 8CD55E7B2445B86CCA7A547FA732D52D59025129FD8C6333AC0DF4F0CFF6287E F2036D5DBBB3B91B92F12FEBE0B61A313A4DB5A9CF0BB3DDB781A56FEBFFACCB 8CB9D1D3DBDBC4CB6AAE6769E470582403CB920630221B68BCB625CD4605FA8F D3D5B7A1A28D15E44B38E92E906C138E72C15B86F64C38E23BF0440052A8C914 54397F49DBED99D0AF7CEA3B0A05FF37C2D7EAE1412567E6776333237C31E3C0 49949EC8BFD6E0F6446CE2D4DCD2C1524A288818CC5D159BF8463A847AE4A2B9 CC8C58F822804B81B13BF4F2DEB6229C4F51F093075581791D02C36A13B855A0 34900AA7CD4F1A797652656FE3A8425A38F421C4CC0ACA1CDD44FA6B31219276 1CDE1CD63D6A58CE705CB56CCA1260F9B86E989019071563A9B4C274A87558CA 6EF1660D574EDA276801F0057740E2C3B80D253D697736484D892CE1AB128B8A DECD69712F5E70E895FBAA927E8194D792A04AB6CE205E04E38A433BBB793FB4 E8BBC4279D58A223C6673D909D6AFECD246E66A52F4CB35E5931D24C828489BD 4ECAF621A220D8ECF702BEB01C4FC7510197D3F6D15321EC87175ADBA6434ECD 2B5A306E91375CAD22CD94301763E4A8B981472890422C5488FCD523C9CB17DC ED22FBF12D5F7525D0D6BCFE8CE85B0DFB1D6F989C267FFBA0A996D309E4A934 3DB54A9D29C88B9D55D7300DA3D46419256C5A07A2A529A8DE8BD1727281F5FE 97033D861E0531B14E811378EC1AF1CC7EE9BA2B07D935843D3053F673979F8C FAFD59D555B56CE338F606747238B22BD62C42BB7238FEA335678D474A643570 A9E7B4970E8C541CE9DBC7BF70ED7BA33639D6744A18379455029E934C95E2EF 639C4848CE9A0879B51649FAB023A71782444B451F92A34CB8A124270CCF86D4 D18EEF5C1D2B2A29012613851C49F50702D63BACF95EE2AB4D72B375E0A62615 E0991E130A67ECBA9E05329B740708F1CB148724C3A6E5E3AEC1F88EBCA398D2 1CA8827C977D72734310233176D1AE26C55CF2CEACA62223315C28FCF6305C7E A22414D4739A059F552F1F9372CCCA5FED4F9AC987942848EB498900269511F3 F408CBEA0659B954F5F1B18AE4FB270213646F9B28AE4439D2BA2D3E0AAAA780 5E530E4EFC8A060EB979E12191044509DA0C14397AFF949E12DC970658D5EAF5 4EA963F5BC1407A32F3837CA6A24B7F3D60EB8E6222B702E25ED903F9D21AE50 664A095009BDEAF4B78DAF94E5A55D48366CABF07791A1684B2F54EA69070844 4F031AF8DF416C2D3679F8BA038B0DC9DD0400CA6B34667BCBBC07E62C1668A8 35A8C57C9048A7227E672E89681B54D662079A189A9E96A3CA96D8DD10189B04 1DA49BA2729F1CA585B1BD5C467295285D52E47CA904235A1A3E48EFAE9EB6F6 01374125CE89D53C276858668CF45D2F092DDCAA52418E0BB94C2B8266B4D88A 5D911507BB1DDA3D8F6E7C14A91CA11AE799EC42E993098E18CADA70BD2A1D82 2C39326C6E3F9E84CD9758B9AE43D79BF99E6A0CD713E95B3D9B7DB90D127DE0 DAFEBF850CAAACBD860B5DEF2082F1ADA64B44B193C4A1417BE221FDCA36456C BE5934C8CE3ED55AE3A11697C2D682B7D0F72D48976451D205783BE25DBD2507 39C14FFB4BB828DFD187104F38A7F11D5F0698C11E8C1D4F107CACE573FDC4B1 C56FDAE47024D6FD16A2FEABB434CA320300FC4B6C1B6CA08F76C60B7C08A665 99F404DBA8A2A1EB18EF6750E4EC186E31561A3F080BA6562967546715859481 7BA782940F5C5D06626D6F6A412CA7C13820EC7C1DF23E15E5829F698CF617BE D940523E4EE4ADECEC48C24297DBAD528BA1DCE7AC335A1D15D55415B108EFC8 6D45030D27B3EA63B2B4CD771DBE66AE0218ABB1153D4B7482289D1313CEF184 5C960B1E3C3C953912CC6F4521D1E15636C1545EEE457EFB87B88C9E43CC2F38 6BC4BC96969F4FF28ABB06F4454C01CEF1B6DC538F1E832FC1666D977E5A881B F72F1B4C7DD4BE167A5535F1163A0706F9A0B26400178DF8A128FB5EBE6A7B81 E478AD183EC06622B591337B9F1872AAEA356F4FC67EE767B34CB5A4D90702D9 39FB846947F4096FB3DCF16EC81455164783BA0B5D723060DAFF411B68307E81 7BEA1D9A47A5AA3D648E618C83C60F060029E6EC4D46B045FA7415BAB2AD0AA5 ED9C729C24136F6AF61E6409C0B5CA760B16225641E268A68CFB8260BBEAFC77 6626EBD97195E77CAB425CFB0096D805D9EE699E41680D095AE9FA10122A7882 2F00F495C9EB2102DF0D3E61833BC0A2E468C5CF7AB430FDB7C0BE3DF2C0D230 1580BAA25D65F599378D873165482A1FBB224AEA89C6BCCFBDBA42AE1C5DCF41 06969F585CD3B737D1388D6359F5468D88FCD2279BDB270F6A858FB7D2ABDEFE 5EE8FB79FA437F8F50237B92C307B73B0DCB808D07A9C3255CB9B3B17039CE5A 288103D05D132863FB522A02CEE3839EF9AF7F07D99732F0B8B384745369FB3E 7901166478F4A16076A1504C5E98D17408494E270BBF4470ED12B4332422679F 759F1D93984D7E506D16950DB6C2682FE1379EFFA6F6C95DD71F6E55BE3EF6AF E0CB25388EEB436E6527806FC75484133F6E561DEB979D5C1FFEFDAF2A6D964E 03BAE0BD593C2992AD84569C81050F7A793C5263E50C2F50B98C4CC703EAE17A 6AEDAACE312DAFAF5278D125B6EFC5587484F61DAFF46B87B7C9B1EEDECA4859 314A9A9E2248467DE1E54D90DD671660B9040B3E0DD982260822177EFD757266 74A16C83A7FB168016A320D3DF3BD7726F1F4EC90EE5DFE810C96B099FD4368D 906AE4699049EFD37E8EF058D4B97BF71106445AADD4FC6E90615A0066823A36 673B8DE32322BBE861AE251226B4385AB28702831270DBD25D666FBB0AD7B96E A44E891EA1EAF0F87013AFC982E33D67A28E96E0C9CB99B9E4192536830D9901 931A8CAFA41289633B20BA3BD7AA3414B6DA8D57CCF2FBE39920CC06361F075B CC40335DB9A0071CFF77F6B7BB47F3100DBDC9C4A58C2B81EC99E8E966AF3390 E3FBCC28BA1D79961C8A1584266454DF772FBA99664D74D4A89FC82FFEDFCFE1 4C9E4A04291E803D142E37E7ACA66AB279378F2F192FFB2B5BBAD18B95F03136 2CB594A3D6D3F8576B90A6C4DAD6D6C8EE07AF682F925F01D0B26CBA347C03BE F3B0585CF4539FDC66915E22117078CC94D621F31DCB3E021998A5D6EE94CA4B E214D07517283D56973D8E4367392BF6C1150DEBF459D141AE0941C1C8C5CFBE E735D796E365A1B0F60BB4CF2801EAFE4889EE5F338D3C4885368281B3C95CCE 251C28A90D318A8A0384439B38D63B94757252062EA44E88509FDD2E75FAAB71 7329622828B2785C1A8B26351BC74237A6BF99216652ACBD4CCF54CFC8AC72A6 46342F1E32D4318E7E27C7B2DAC943B3E72C472FC6F1DDA8684AA922516A672C E969C047E318B5E3B1270C1BEB1C4071A15BC81B29B268C679B41FC5E381BE33 DD95F0D68118CBB60C521E5CB2BA46A10E50E9238163713290DF6DD8A27D3813 F871C07E725D4518013D9A84CEC96782541E5580E33C2EBCDB18F08EB4655A46 507A8526DB26C854928B81FD502B0CCE4A68943C12078F57C10F4E85FBEE1025 46D925B8B3B447D4920410FEEB9844FABE985F9228FDD9F58392F2F3BD650E49 2E3AD5A14984874DF4572816931885CE8A448EC95BBF40DDF4F85653AD90A88C C4A879C0C7596E61997B972E8A55E57B17F802C738E5C7A8FBF6424F8B131B23 CEE3EA3747DB066246C250EAD335A76FA166ABF75120CECB59076AB31A51F176 57176CBE8C802A97B0542A5CFD6D5E6D7EC848B923012E45D9F065BFFA0D03E6 788B68BA4DE51DA37994948F859D41C28BA939C3A82BFDB44DA585AE80B8CD7B A6EEA79B70BFB4864E06F06A9751BD2D2A209D150D7135E0A25D67263EDD2A7C C63B5B76ADB05D44BD5BC0BB3EBCE2E74E1AE5F7DE07A59D90C932DAA2553505 27F2AFC05F7CEB39E1C7E54F69FB0BBB069959F2FBD11709F8E81F6E7CA06DBA 1CBDD8E7A78487462596DA288B50B295E46F4C3D9BA862688C68859734B232A7 4B371D2BD786924F186524765E789EEAA30B20C069322D42C893A30BF1BD2C46 F8F3732DDFE80B8FC1789239345944D8B457824FD80D11184E73FBA30EB80A9F 2FD466826D4E666E3A835B98A1D4AE5D17053A6A648E26E77BD08F9A3E02956A AE82C4929E9666F539079846527D0E326FE7CBBF86E3722BA3E53F8A5121080B ACF8D3C67A2A1DF624B9DB92105D3C833F5A6ECEC108E026E1D3D968967A1447 15CEFDD09123D56606134BC3449404ADAB1330C9238DE48F3CDFBC91EB86D7B3 8B85B5BA97376A0673E434DBFF19798EA90BFBD94493E2D21976F8106FC0C276 C81C9B9F7D4A68120DDA56FC6EC65FFA40DB78A60A05EC270A106DEEBD2CB92B F0622BD2B1D43771DF39AAD3ECB655F317AB483F7290C148690903AAA636583C 99DE3DBA99EFE20773D3D8DDD816A28D7BD8881DE570BAF5C7A30679179E1214 FCFED81605FE56AEA21C1894167F93D648B474352A65C0756F812F97AB435ADD 22C031A21714A626DE35308AC51CD676DB1748DD2773532294FA77CFB2AAFD32 A72BB7A045F12B4934A768F89217233DBBD69B900B28492A26713CA5D61A9042 A982CB071F1F875718FAC168E4E275860DB6369B8114E1BDD4801110B62C3E3E CF140554C826967A99F4E9726526E87D57BF845CE38E33893E5F9788769B6A4B A4577C38C8D45AF2EDC9F4FA7DD9979AB8E14FF5D8956233AB4C02982BE8E561 C63B7BC314793F634DB6F086E1A60D9FC3B69D3A7C20A99FBF3CB028CDBCEB60 E803C8DC3C5F0CCAC030905E72BBAC052520CB0E40E23B46B2150DE67F61E4B1 8C4D55904B7F90DDE4A4A78B11AE1009DE46DA396791B1C0EA63FB6897FDFA0F 42474042E7E9B06A703A7C6E672AC6705506F3C0B6861BC85CEBB9DC9CE89372 88DBC4F96661C812D31312FDBD0E6AFA59D5E0D41E963C93AE5F9D6562A5BDB2 EF35BEAF99FC9B83D0F6E963F0BBE59633708BABA1C0C474D507E7DD8C3FC2A0 0E05F058D68121D18C24FD704053E9568C1E110FF28D77255EF61C590A82774A 36F918A82ABEA5D650537545756AF0D00E5531E48A9EF82A048F9ABF657FD6E6 7A86F4EC045CF79F55472FC309009C30F1C3566B750DD4192CF586DE51D718CE 4E3203A1196B6C1B2C006DA31157A6A6DD46B4D1B3339108E2D9247B3769DE84 CA991F28D39B289A4F3AA3556BA6774225E83D3E036A9C7CF02AFF6ED9D3947E C669D9690A6B0607463E910C0D29608F8FACDD5CC249BAC915531365E910E062 8C0916C9A80195D4C3A837B0242CC141677B2C582F9C1085BC3584B742F6A17A C122BD3C37CD6584C8D40E7F673FB8B37B3D86A625B0F2987083E14E0E85B2B4 4CB39E84CCE637E8414538034A2B8DDD282DB19BB49971CBB107D16C3B6E8641 129AAF973C7B5548E265975B0F2A90CFA0BDCDB9800F9F13D7AE2DE432FD56FE F121AFD9D4146B47DEDA2CFC1099B1C9DAB8E89FE32554EAED0738F19E704157 D1A34793E173D032F16245239666AD054A9D6942EDC98B21EB7BF54F5C2B1EBD CE86CDC4D01C9D05ED97A4A38F3F28273DF70C21DB2925BCA2B4E479414E99F7 5FCFF8E6AF113C0C43B061AA6CB3FBDFD957BEAF2BFDC1947F8A69DD669AFF10 99E3D76DD5A4945962C6B1B9D8AB6640504BE4A5D372ECEFF0B5C6F4457709CB 0C0B62B3A7A743AFE1C00B37934F1ED8A45FC5AC174336A3F6F0D4386F3DB83C CF9143F3A1A431342A27B66A287D2BA92A6CE6C7DBBF62CD6792231B90603D75 10079164273D164E13868F7442FD4D56DF7C21D7CDACD60B6DAEE2521AB9B4F8 2C1E5EF603450BC562A195E9F1CC903DBB5EDD926DED61EB7DAD9A91018ACD85 8E992234AC9D62CF763D2629F7CF9DCB210F48CDD474BC04C426E2CECCDCBBDD D02819085642CC479A7551AC5123CCEBA6C81DB91F6A27E49ADC764433697176 4C8F6A20247B49CE410988A3940B5A7593797D8A4F67CCA9C991D6790A819B52 AAAD0CE9206955843D46ECE2BFAB537F81BE41B6B6B86D86D1979AB37E177D41 6C865EDEBE02288055452DA705EBAC5D4AFE97D78954E3B28DFF4D0BA7F68091 844E7E681A3282F7FC211E13A7C644170B7CC7787D549409C688B1419D3454DE BF570A46CB6F67CA472BDD5A7B8E16D11A40B488136291D57736A445C9C25EAC A42686BD3320E18FD75743B0B3C78EA9652D67879F3C114B8A5E8B6E99DE9C6D 9A6CBD0990E3CFB656D0A3750533B6406B6E4F61160966AD4165B00477B8B501 D4F5B5588C9C4F88668DA9986CF0A4655707C0E19F4369AD260BA4E5F609BD30 646213E8AD59DC1FC6C35CA80607ED028EF33FDAFB8101F25522059EBA068ECB 55D5B090D680EA3CF483FFBF44E686EE3924694FD82DFF58B3F228223DF2B2AD AEDB5CC749C4B2F54C33425A5B674C0A3C4911728B598303CE6A18A4D5D85DBA 9094E105CAAD0F7391273F4E0FA93AE99076AF27F0B2A858284EB11050DF759A B7FDEA1FC7B70491FAB93D6E15AC08C38D8F20F5F793C089AB91123A01080548 802256F9B2667F310CBBE92862923F3119B8DC47A3D0E704AA7C37E63715D5F0 01EB120BF36C723F0F77FB88A2FC7AD0509BD6DB28E2E057E05A99D9969F3913 787C334514D0136514B9C8364ABD5E890FB400B34650D6B02C13601F6E733390 1B8625E9528AA3E4A8496813687BB411670B10C94E35AB1661B14E8877CDEDD1 1680D5A7F7A701EE281D40A90AAB6D00D30539E1B0D9EDEC9711F4EDFE7E4BF6 43E63A8CFFC8027A67E904BA587A0B33795352B8057E8F3D4D3EDFF75891A1A6 B9B23604BD9F35A475A2BEBFAB5153D461C07824578B1B5370926C4ECA10ED72 B8AA80104B4E0A36030309B41C4DAC2B4ECBB370B685B687EA872452C1956802 8F08AA0313E0BF5E84B7D4E07907787E83DB7DEBE0A07E40969EBFF6D397E0AC 30205649C933A94C5CF53A7AE7AE268BA379FAB7929975425DF74660B49E571C 1BDE7D5E9A26CC7107E99558F90AC41F7D7A2AEBA96ECF1173CC7E8A9C109802 186AC9C475950B058CB249FEAE07E1C10CB6420412C672FEE56262D0BD65048C AB5EB395752344A096B4C8A969075E5097220816ADFE6796A4713EF7A3E40DB1 FA5DAD6FCB4AF346C1FF3752585854C18C871EAEBA8B1BDBB21A0E912CF4F75D 566F9123E268E792144FE20B24436949E390AC737DC9BE22D70C47C5C68B55CC 6B9BD17AAA6E4774F79C579E31310F35084808F6F1115CA55BDEAF26E630E5D1 0C7D7281C405CFD48C478C457CF37D5D21D8CFAC0022154E1325ED7E7D9A238D B6937066FC0F884F0C8A2E52A40C234EA3666415B37E79DF04C373C5E98DC38F 2458BC03E20A874C61E9C65CBE5BB0CBB09845F475EE91D3A789CC4D1E3F74B8 16DB60C84DF6C7804457B00128944046044230C8B030AA6D8BBEC3C886399E7C DC62884EC2652F2428F6955AB676DF8518E1D75ADFEB9C29EB4D9A4C7942212C 07203BB13E465F42EB5E8F516F4F18B9C177FE7D536B4D467A147297996B9063 1029DF29E739D1A9DB992C1B98FB6EE5479E68779E5A24BB4C05C70C79223CC9 B85EE37408A99D9A7403D0D24CF484919A5BC731A13BE98B56CC23394F9F3DDC 47323EEA5B227BBE9312E2074193AC1DED29E570950AF946A09D12F52C841721 27B0CAEC834A391C1E2DB2D736FDC92B3DCBB1FC128034E8A2381145C6426AC0 317E796BFE0ED1459EF793864DADFAF394DC051DCB5F1E409050E41B3D90D821 94447BF370C7CCE0A391899D08B9CEB3673274A23EED41CB5575C8896C8D3EF9 9F2DA10F70DFAA9BC0356ECEC7CCBB9EDED943EB85F3998786CB1A305920B7C5 0F7F154C0F22A6B53C186C3225BD58863FE1D9DF38FE913EF330CE80EFBBC43E DEE10A0DC03F64F0E4CA387130D5783E8A1D74EC5E65D8691708D655B69B0D75 7063B34BE04A4423C0514D6D7E8AC8A8CA198E5DDE9FE491A846BAC77C8CB95A 39BD4A352A12C62DF10F9D4EB04305EB2C683AC3B4A9EC143167C7A506DF61EA AFBF31298EF5100910F62F31F50185F8000EAB4825599225DD33ECA9005C4CC2 042016FB9C02418CFEFDE691DDDAF317A96F4AAFF639DF1EEAA31A84A5DEA1B0 4540B756B0B4FCC4F51D80EF8CD0DA91E38D2FC1121054E9732A0A0ACE182624 166722D9D6384AEEDCD7E6F3DC49987BA683180D8424ED60C600D143EC9B3803 E12459BE9A3563AFBE340864EDE14D416EC3D3F4BD0D3261E4C3DDB32922D953 3229BE070175C21FC6F94A9B0AE96AB31605BBAEE010D939EE89AB91738C8F45 10CE2906877AFD2E5F39E7C45CE1454D1C167BA90C2CF192AC834A4D1605BD94 6D9EFA985E106984CBB4ED442042586391FBF386F79999855B4812C437458063 12660E29DA28D77760EDE77C45D84E758EF3D265D2AB232A7F63F86DC8DD3534 01CFC76BEE8425B16131F483104ECBB582FC38DE857F05AC7D8FA2428962BA07 2FF35FC1FE7EE7E2D1A6CE661CAAB28D906E17D9918648D16339B87792FDF8D3 B04EFBB83861FF4610343298BE567E5A97B8E41911E88CCDB6710E29F24D1FAC 22F85455B4B17D6CCB61DE8E639E0667E46DCD004F5ADFC2F6CABA1B4180A25D E36C1A57DA64335544DAC4F790634C28C10F6AC8DBA8B6B0143FB00E7E3273F7 1D221F65291473CDFC71BB4F3C911DB6F5B02DD38A296934DCC471EA9DEF3941 9861D6F9D72FA13168DF02CB8880043139329C14B0D93DB8752C4E006C8FAAAB 7434BF31F2EE305EEC12A2F8581D86A2F93A22C6A16E7255B84937A97541F875 3A6737AEEAD8CC05C55278CD05A93FF79A573F08EE662D1451B7C29293FD3219 FF1F07B5EDD449F95D802AE6EE9461525B57B47AD676226CB0AF3C6C0E23CA49 8FE6744C36AA9A45F26B4E891691FFC7680B32B0F6C4422584579C7A13444C38 4C9067787825B07042E63B9C6FCBDE652C60D5D8574423A43CCA948E5B638CA7 813E94BB204CEE5BD7257B98D25F0207709974F33A9635621C3464137BE43708 97921345C6FAE91B6E974413EE5F3AD54966FEC1930A04A06B170EC02D88C95E 74FC4791588B9C5E8325DBA166CD541AC0148BF212BA9B24171312DFA9D8D946 B413C86FDEB625C874A94B986CA795379CD5B4061D2FE3C3A44355629714EE5A 3E6681C38B6C63557220661C4F7C6B38DD78B2D53021E9C3AAC3ECD21293590F E10CB86944EDAB1FFE5380E71276C60EAB7E9F1DAF306CB780BFC491511FFF59 EFCF82AF7044F013A1FDE387B201745FCC384A1744B16A299F59BCBAF2746733 C66F9D61CACD3AFF06739F388BF17F8292B8D7CA97C74386C93517AD89CDD358 18F35429A323958C0A528989A483DC1C8283F934AD2D560FAC2BC019A171E538 8AE1FA57FBAB7E9DFCE6483A0FB077A3A9EF1B9A39AA6B40211BEC3A46F1FEA6 11304E85DE80D20B8F155A2EE61B251535B10F4125F42E96F7E69CF3842F626E A34211CD49F42E03C74C1847E4DAF520D1A63FE74CB64B9D8314B8D1EF27DA97 E9FA4832346E86C1A47229298B3BBB52D079539970EFB2D13C85A1FDDB9DB567 0FDF672B9F3D74BB0798233CDC7A5057B697A11FFEBAFCBDC096A3AD9FBEDC38 8D8DDE21EE771251614E6540F835B394D80A2AEF21B41B6BFB1B762366DD8795 96EE306285FCA61F798F7C5A42C6E8A030BA7EECB8EC0BD769645FA3CC20DE1A 9107BD487278F660E74259BAB36599164D75D76C85777BA55226FDAF8D0D5204 0E030A10E035D32A32CCAB9F4C9D5C29ED4054CED2C59E5AC4177C736158B095 E800D8FF594A7E58589188F31AE61C754621CF48BF115F9DC62DB1D2C8807075 8F0955CEFA77F9E16A142D71DB3B36D27C78D824C85FD1B6E73566EC486937FE 85441BC81737AE4594EA4BA70404081783D86D7F782E996047C8C2333E1C00D5 260BCB452CD4F41A18368E2450F45F77C849DBF780D527C972FF1CB1D90E2155 B034450732E836A304C0C65A22DA2D3DC0DEFB51C62E5CF24A63F38CA9A7B725 6CF94CD6F2DEBC79AFC90912E05169B17C27CC63FE88C586A3039B246F6DFBEA C4DEAAEE8D94B91A3AE29A0F60470725430073E555AB6B69E97A1CECAF416959 EA671A353EEB40353A74C4397056796C948CAD4E34AA5649843F549DFC47F07E A46A2640A04E9E88F84803551A1858AD3C491CE4262EA7DE5CBC624CF9EDB79E D7649BBEAE2207CB7EF264D13487BAE1C05B47BE48EF0A1E423D52D626969F19 9BAF6C36A5F7ACA1EC5146751538C74BBC3A33408E950907D84A85745CB3C619 30890699C822D7FA30E4CE63A4B53C442D9BE56A99AC2EDD02C799E611050018 C6B95DFAA9355B146B1E3077C44DFFD62E1ADA32C5C21BAAA41D38C7782C1CF5 10ED256CE14FF1576E8BCAC3DAB51D9FC8035628C1B503D16659B2B761BB63B5 755C01509EE4433750EE5B0994E956B1567D5F1E9E0B7DB27681799299FEF9C8 C2AD946019AFC351D190BFA2C1B801DB3536BE9721DF544D11F39EA4D9F1DEC3 462E608F9CE48AB37F16A1874FE5F4AD980EBE76A345A50B2428C3DA1925ECC9 DF68179939E4EF14C760B1EA2E4212BCE7C0CDA8B34CF2990637829E8E951ECC 0AFC95875DB4F44B7703547C1D3CED8227C3F7AE582111EBC86A8908515FE091 2D12733064E9D215D4A4EB350DE11D3D3BBBF8AB4C628CDC2A8FB41FBFBC4048 AF83E702287BFD3D16F6FFE56CE24008B735B517D364E7BA4B02300B594DA978 0937CD3FFC89CECFAB77CE33651B05F18E56EAEC5779687619FC1878825B3776 89AE6FBE36BC60341E2AB511079FE8C9CFC57029CA387E28E78382CB0F318B8D 3FBDF6F5D8C097BF895955BAE8591CE021CCC49976EACA720179B72B68EC6AA2 427CA0A8808552F93676CD7156CC445787A052A784EA597E3E557B1141E32EA7 9758E599D3AC3A4A33A7ED2282B39DEB413CF1E63555953037FC11D9774E8281 E13DEE841B104551889CBBAFD08BA6485BD850957CC7D8355064C23CCFC09B86 15A1A2666DB274D772064661AD58CCF8B04336371080E88695461B7E0526CE77 0EB7596E6DBD17274E021441A6932317D5024AB0240C4944AAB762613A5DFC8D BBAFCC8C2A09C204E0558F49B3B9044BEBC0987548D105028693DC68DBB0A9E6 600C9045FF964A418772CF8D73808A59C278A9FE1825AF4EE6884E4E91216179 05E79DD583FFD06888AFCFD95E0CFAAFE51737076845363AAA1E59E1EDAD9D6A 0B392522EE77BDDCB6D191C7B797D203FDCF2DCDA4B6D4B74EBC6372A48B13E6 6D33C4973CABF2A3D8B91BD71421748308FA2147849025FBD2F1866908910C79 59635A0615DEA01BA7890B3AAD778D109AB6A785FF83E8734FA6AC6F7ECC990D 6DC1108D7D15164E248C6D1F0BC962C52AD2777B96487CE582456B2BB1BC33C3 3425403557E92A95DE74A982EA07396D0E7C5FF16C7BB1A54124A0DFC6FBFAF2 DBCBC7A2E723EE5B661FC62C2C396A3E3341DFE5031DE0E15E5BFE6C8305C555 728B93DDB0D2F998EB3D6E8526A25D77AFDB89149FDB6CBC03B80C71182E0393 E451562E199E075C5311A3674F372E6F0F2DE8954F04429B27A448442F0CA5D5 2404F4537FE01C9736A786163FDD429EEE672A60D52D5F58188549D9E9E5ED41 6C25FF8E53A97D859B18F91025B5501E09638D04DBEF22AA1D160B9CD4C94876 9EB9D8BB838455E647B8D4F4E5ADAC207E9C1F373C63B3987A07E0BEFE97EC54 4E24C1C0B953F3DAC89D066DC66CFCD3AF8AB505E6559BB8E9664C0647EA2030 65BB8F35D639EEFD9C0471BF83B8CE583C5288B12E164CCF57C31C326245A528 E45943DB79E305DCA23A2EFB82D1C752C7499CA8A01A7ECF7BF6B287350609F0 A2DC4FB958868D298978EB2FFDCDC4A0C8DCEF7066287EC7A53F7B350D5C37C4 E7C92A0D8232006FE5C7E3C22EB590C93A4096104BDF5117AE70DE4EDE2EF87C 11602CB8D4C3AF679D17FD5167C1AB635AE508EE90B912656E9121BDC481E2AC E7273B5576EF99038F2F07C7A23B5926DB6D9DEE504AB75DE45666AF661932EA 75AF60F39A6456EC731E53452B9BBDD951DF4E4FB7374B0F9371EAA6D4671432 461357C0C60F46C22A1A2B643CCAFCE21C74ED943AF4F5BA2478860F56042F0D F85BE9A9E810FB96E5A9D8A979CCFEFCBF1603F25AF1837A9191759387053011 7CDF0BD12C3417EF376F8E3DF06B3C48DB995618F372DA8705C9D04297D1B832 93C0316D8FAD1AA1F284BE4901E4B81079D76A018F871E3EA3B5BB46493652D2 5F7BDEE050F252308FCE5FFE339AE2230C3F5C9A28B875B2BF2A915EB1E23F2B C38B3A78F3E5DAC5B295BF326EE53B9BEA7D505F4CC01C6A8D06B90ABBFECF7C E71CDD427000179311C9D3BC851E294F95BE11F2F85A6BA3C217EBBB22761BEE D503CCB29BB09393917EB2F87567B4CEFC4024CD88761DBF9CEFBDCAACB1CDC2 AD3EC0B833F79B10FF2D912BCDA6C65E957ACFAE5D63ED379FF131919BCCF1E5 E88C26463F5B9587BCD7E153A12C696D8023B2E49A103C0C61560784A4FC0DC2 9A075F00072064FFC2C341DB19D82E11EED2648C7F6CD06270F93F4A2F5F8B75 858AD309A6D5E63B583A0E835D210F60FD71B9E159A8D639FE5E774D3754D41D B4B495EC984DA4AB7B831D13EB891A9C93150F3F50FCBBCCF047879CD4CE8F0A 0D8C9A90B89F14ADA6644B83E6D0B0890BDC8BCDC5EE6DB85CE8FA5F02DCF259 9DA572E0FBE9B2D9E2517667366B415441C6A1E56BBC5D0E6F88B2C03A17C2EF B13A2166C34D3C4C7D17DB62BAF7FDC49FB301D1AE0524D87D96955A2B38782B 62AACDE5B43E8D6646DDEE92C2C7EE93E4D892594C1D1BC58DB5E503F9A6E1F8 83165C19669F866924DCE4CDB53DF78E3A38177AB1507DA65916AF2A6F7CF34E E327C51527BA6E8358094F9EBA9957914BF0195E58ABC869E79A2E68C2BAB04D 75267D48E998F36CCA9A94117D1187146355E5E65A15A3D9C123F9199352D5E8 7AF96F0FD88C897A13A810DD3960B517462057C0463955471ADECC244B82A0D7 A93F3AA163855DBF547F7824231630C255F50311CBC7A48273A5FF91722480F6 782337A984344897E888C830DEB079EE3E7DA1312C95AD5E5078B63D1731102F C928820255CE8742C2A4B412AB6D662E40C7A767D06C73AFFF8C6336053078D1 7FCCAD175C7174016B054B3D09008D01D00D6D7FFBF6B39A053AF0181B718B90 ABC6DB0070BBF8B26D51D46599D8C2DD46A6F4A033FCB04E9EA807D3F3E9C45D 99FDC21412065FC11E2C9A0108B61BBDB87C9FB92CC6D4D32B254A45E391051B 9A9D77F5B2AB5452AE72B97B458B02742D74B5A946A9B778F28492F3CC5F3524 6645C9DC75BCC4FB2C994C86F91BCA6E3B20579C2219BFE0428668AED62D8470 92FAD9574363420F7F118A93ECC35F6FC174C74C016B503AD35710EFCF4C5CF9 02C7FD683D964E60A96FC687F611C496120255E3BD59EE81177B5AE8B6F69B41 BDBDFA0FCC571214D1F0DEFC52F9E41FF24747D2909AB62FDC59B498A76FB399 BF2B8F46AECA0FD74BA98994C540264997CC5615A0B601ADBE602E43ED5EFE81 9468A132227B985905AB5E0C8146B860B8E4D4CD3B33816377E08410ED37E146 803D54A10974EFD818ABE474DB1B187171D344AE88A717A333ECD8E45AB5FDCE 5E9F1DEF736B4B401C38C499FB8D374FA3BEC0931AB7A1AC2ED1CA55EE08D4D5 84D4D75043CDDC6F11795AD6C2765DE8E46324A8E32568903AF16EB7F7D42D6F 9EB34675EDDB76BBC74B8C66D9EAF9923844EE39FC4F8F36D444BDCCB32D5987 9E1A34023A8389C07A8A54BCFF045E57C596D9CBB7234F3D32CEF39A207C35C5 2EC594BC6D6F4D421DC37320E387499BAF6FF135F251328367021C8D48392B80 9CCE1B2FAD718580B126C50B243284A47C22D8F32C5F28F184E0D6A657EB6013 9BC8D85309A05A9A9302A61B9A49E8CC329F7E54AEB59BE426CA133C792FAAA4 C01FA639598C7B21A85E441636E19BC9CEA795158ECE11889F41D325BCD4EEBC 4AFEF80879C543CF28FE5E965E110C0322CFFF655A0C1D596A5ED2E2F831AD10 28219C8C0B7902D50E09C2D0041A2934A08A995E9171709ACE5B14B308B6D3E5 052A17FD842FA9ABCD527C53261FF5D874C5B805D1523FCFF4262F6E92112153 213154DBCBAC2959B6E5676A1735C26E2D174368745A1C8ECC5919AE8236BF03 CD207928040A8C5315B450948EA4D23B99F184137F464150D390E697E182B6CE 96ABEF0CB4125C8AD5D39081DE8A63FFC4F738FF4148E264BAC0F8890627DCE7 33BAA239C09323BACBFED301A71131799FDA54B04DB83697F29AB1CCB8FA6E01 DA5872D91E04392C1E635753DEA9C107357DB99D502CEDE64B65AAC691DFA7D6 53D366EACCC105D0BF34A4B6439AEE68BE5861A9F2F8B553F836B73D0B49EC4B 3E2AA6A55A026FD2258DD2E17BE18ED3AE93168243710DEE4C351D3568E39A5C DFA3ACE49BE65A86B2653BD63618B3BD1BD365BA7462140B4B9B2A81E0786410 46ABF80BF6DBA2E07503107A82A7DBC0B05A3005DF475E1BCA6417866555174F 08D6E401CC5EF31D8E2F2E89231D374AAD3467594BA95798DC4BB19A15A98FD4 D02EB96DEDE561B6A448F6772028022595A1C944D8EB4C9C0C04D3EBE1467157 99D8C5C72AD625DCD92856C1D793373784060513E260B587F3DC364C484C36AA 07BEE82A0E0BBE6F80D3467F02FE6635F508A6EE90FD293E81CF99CB3E52FA0A 763DE6CC0114A74458F738FAD91A088C9D25976F6286C8E0D2DD61A71643FB69 1415F21D1F6A95462F889DD443DEEF30D118FC756F917A5714C893CCDD7FE3A7 57286E3A15D5E87931196D64A026DA4A4C907C38BF95BDA599DC7A4F1967746E 4473ABBE80A5DD49CEA25B2BB8A9DFFC3537A1F5D4477EBF142103787818E09A E5D50417F82BA1C422B33BB66FC018C007987ACC6AAA798524FB776D7550E3DE 95B496B761D2B1EDB6B2BB0134A039D4BAAA83614B0058AEEF40A693D24AFE9E 7F97A02DBD8119651CE48E196A6F60043B34DC444DFE2ADC6E833E34E52B3455 A2A035DD0BA864612EB104C0C0D5E83D631BA37F10A7AAD7F630C19C6E8F6AC0 DDF3BD600808041AEA7CA46BC360F5DC1A8001FB2C962237E77ADFD7AE114290 F18B5DBD7456F3FA921B36CB4A6E90AAD8D12B27CDFEA15A81A590C1F3988660 BE432900B58B1CE7492672946CC32523CFDEA14777B4596330C7E93FE4C6E4C3 139C7EF73A4863A2A76863438CB15A31019289896D48AF13DD320428271374CD E901035EE605AB95C0033DD699D58B49129B0AB9C535E8CE5CE9F84389B3CBEF 33FEED3C1ED80371098ADAE53FC2B9A06515194632D184B8124C6BE8A25A5E16 9F23EFC9D3568513DACA3A97D8030E10D0DB62A117F573443D78994B623D7D39 0172E22566EED959B56B93A51AD64D9B36708881A2598C9422463D8BB16D5A78 94FB7535DD5E3BA93E6D2006789586C2441831522B2A87620835926DCA369367 F96E54DD0783CB5E0760E92B2119BF1EFB1B7CF18A70B87E5332CC6DFCF10CA3 F62A22A8E4E6818FC045B1B0FB0EDEFB230BE1834CA846F7C5E099A4C54C5F65 FA029ED16F0BC09AC2654C7A9B4114BE54DE04889A2EF322327817FBC8E6D0A6 F5F115A28A2759CEDE0CDA907192854912F402C9CE5790512F3B4B85DF290C6F 964EEC7BA3A5D2AF19417660F9FABBACD29CD3F1D0112E40C23C02D8A906CCDB 2757C309D8B89B88C3D3967D4BFC45472BF2FC58E888956C503F2774EDBC8C00 1E50E35497A0FA5131383AFB3CB8CC1DA2BD99C85AAF3A2346EA3DB89BC877B5 D37832226452483339333B2E4EF87E4B2985916DE138BC548D06CF247FD3BBF9 DC5BED8B1AB435814998EC910F71D300069C1EDED83E9346A85A3AEF295AF7D6 06C98C6454415056C21395D6FE6D636A1F316BA3E3AC963F9064532090840548 A62D1E3CAA038509C44B2762D363BA88C32EE1E82A65849278077875340644D3 38E445E3BF798205E90D6C19501246A2A77B93A65A82C21F763F7FB4AAC73823 FB377164F0E7683A8C143AE37F95D424C60C503640565ED52C9E79F720038392 5AAF1075DA2D9648C691139F1531F212B9BA66085AF612C0A6FCCBC49AD9A1AC ABD7BDE6998EE089283450DB280D71078671CE182F5C8D6B5BC6FD1EFA3D23FE 66C5FA9F47C81C84B81065B3AF067E617C2A49FA234EB71739D885EE2A088D60 F95439492707E02658BD498EBBF56F0435955718607D56B524345DD34292879D FB035E52B4E5C232771F6975285A56B6B3808C608B5408809069305E1DB194FE 33A29E71F16FDD2681288216A1A284919271D497D73E7F52A1A73788764063C9 44BD46F1E6F60A2A1709A06D653336A7845898E65524ABB1DD3EEAD1554B68C7 722AB41316562032D231946B27B2D809CB3AFEBB2D37B6BA50578A7F817B73FC FABCB63DF361EF5C24A607CD352757EEB7FE6EDF7BD7C1C0671B67064BC272C1 28F775A8012234BDF543AD5DFB86F64FDEB355F1D649AFBCF651BE1ED1DCA962 EF1F3235005A3CD6DC0B78DB6CA65A0373E1893114D6D4E5A5EF1FA6BE38E9AD AB6C62AB892E9AAD121AE50D5B185651FBA345909078FFE9FE7492EE182FC5C3 3F9717CE10169438F0FFFC3A84A84FF562B8D2F825E305891758D6B7E096C298 BD344F4BE443E423A0CE11E2428000032E06DEF85E3A5BCB9FFB8AE4687A539A F6B24E35385B10758D3CB03B34020341C9FDA67403C2298AE94C70A18FDC8BBF E7E0843F4BACE6D4F3A484B1C425084252E81A99414FE78175B23985846B1564 D02B333BD8209D16F89BF12970EBF251F32CC45D0D59737AA3C416EA61B74D23 75CD0040F8A289F1566CCA6B3B09ACC51AFD4BE9037483134687EE187C41E571 EF828AF4827ADC11BE88B28A0CA4E38F27DCFD55873CED7381EB4ED80A99524C 165FC25B21A0D982C650927023B246A122426C45ED4A730B66F160851B24F703 CCCA8BDFA289B0F957B87906EEA88F714497A11912D71355304483765ACF958B 3D114C33B1A78D3C2E667C7F12A3E345AD365CC31F8955AA214A4741E0AD8B06 40BB42258A561A5404402E6DD847A49621D5EB06FFD366EB14EB05E6140567B6 A3174BFBB7951F65248622426E41630FA9CE9782F77754CFF68E1D3BBDA2F8FF D00D99D23CB38F14645776BA3EAA34992055677E2FB4DF057A823548FB0C52AC 8A9511048C13F0B50FB20ECD37743D56F55379353FA48DDFF43D1C712C74476C 20391932824690F5EFC14869AB68DD533FE00F382469C1CF841B1E3C91285E47 CFD5B77615C6B710E9EEC208F90E27A363F41C4F0499935074B528682F33C1B3 7AA5C2F16CBA2FC1E0F87A0AAA3DC8BF4A6FBB91CDBE978062BAA77CC4B41F57 FFC2C9160AFF5DC1EFFF988ABB619D198CA98B2F9BBC97A34F86E0F7CC245AAD 91867351F98D6E93813BAD63F3557F1277F311B80E2E8DE6F16E34E0F5FF5FD4 10B68D52F11DD15EE620C15C64CD8392072419F74F8AF6FF61AB288E2807CFC6 6AC4603430B5424CE3F8DA182464DE9588169350908D368D15ECF34E90D8FE2B 85EF8FB0318A8CFB8EAAFB422EE66436DB534884A79348EDAF9A2AAB5DBC6B4D 224F6D0D41C718F86B83EB6807D3DF277BF391A95EFDDCFA4C2DD49E6FCE3A94 E4C4CA7A8363A8610A5CA5B7B13BDF3E4B5E95940C84D3699C7DD8C69CE3BC8F 1F513D39C25406A42FBC0D4F7926F5074D750B7929BCCC74B2A5A8D9326EA944 72768AD4DF13263D3D329FFCB2989A21A5BAE9C46EB0F28A5A5F2329F95797E4 A6A291DCECB13244146B8A1180C029610DA9B5C5242046D5C3BAD2AC9686F236 70B6B81AAF86F15D54AE46E75D39EE2548264452BC220416E57EBDEC45017949 2DC6718A3D14B931F38A389BFB88B14334447EF414D803100C3916FDF4F0A8D7 B68BE36F7B5AC9FEBB78162214DC349D6BA4F22D98A2FD90B9EF3A3038FB534D D6EB70EEEF1CD91A0487E88B1C0227FA7D1BADFC30DF34FB81E35DEDA1306C10 73CEBB33B7DA3C897752947CDED15C68243F7E1E9716D751B5CF68D32E9433EC 8317B6910DEDF297A1CFBF95C2FBB92EDA7CC2A5B853A5B3DBB1E2C869A13F8E 08FD2ECA621A75EFD69E2FE9CB5B10026901F535BF4E7F30C7A6AE3B00F55696 72FA49ED6B7A28F31DB28D2DF9CA1121E34036C6227BC244A8F22A48F29B7F3C 6FD319F8D8C398BF6D1DAF886FA3023C4B88777F963E74AA0C55B6EC65A38431 5E49F222F81AFD66DACA0F874E2FE897985C6C25347758A0D8608E6388D0EB1B 18FB22015E33B436CAF97804234749254718090DBD3C1801DB22823D0E172E45 978F25643F19AB284BB5A9E7BB776B37107C1BAD20BEADAC0E373254B3ED740E 4D0A32A6D2E8677F28970A49609FCBD876D5B8667ABCE147754178FC558D24C7 6FCD30FEF074372FB3FCE00DDB5B18A56300910F204C63E811985F5A3EBEC7F4 7A654939C8C2FCD6B3EFF62720368FC1264335DFF72C3A9B0E2D7B48E457941F 5DA2170F5448D870487D127779BDA70EC0DB3F1867C24561DDDE4DFF123D8551 280657FD211EFC9046FDFC083B03C04A7235EDFC207A00EFD54B962C94596101 8CFD7E202167DF4DB18E58919A83AA00A2678C370AE5F17623FD28D5158B8542 E5A28FFBC292BF1D2D236030187ED2838DC53B5E7E7536D898D88799418D9CAB 6C8C9EBAB0F089FFF4E2182AB7035FB6DC7A1DD60DD708728E65E7180CFD7B11 1E5C3A1B59B424931EB0854E08A29AE3B8FA326BD2EDE7AD52CAB7BD80F2074B 0054D51693EB90200F8D80BA4E00BD079DD54E311625373FF739251160E44EC3 6DA82F68B5F4A2B2CDFB8210F6577C22DC2B8800414F9F2ED2DEC8B5515D9D7E 9B11C9AD0101A0A5831C53AC007048D0DB8A377815595CF63B2F9B4AA6CD10AF D6802D71A97035F1B3C253CCD06A931F5B6A1BB87C05CF18332783033FB6A09A 1E92D5A657DD5F95969AB7BFF0C1A213843B1C247392E2316F3E4E85A8DA8048 F67CDBA7067FD19D3E6AE0268118AF722EE59FADE9624050D4DFDA25797C55D0 2E2C4C345DCB184D0706B2B3326CE2875FB12AB338892AC5054B51DBA189B2D3 780A6FE08E8E5A729C44D241FDD9074CF2869982E5ED9C80A77E57D90BED86D1 A49DF3D189EB13D2B25B1C176680304FE6FBD3FCBF4D37DFEF135B5CA76DF4AE 34F56E08926B653B76AB1D769CED9E41A017B3C6F6AE2F5DB2228DB4B476C11D 05C67986BC0FE0BA77E1B57A2B0B6DE4BFF8DF20DD19DC52CAC77C9A457685C2 3F255B5BEFB482136AF381FB2B52786A055F847141BC5292735A255AE3AFCCE2 62248B00DC1BBBC9D87799A72691D56D737C9143EB92D779470BBFB4150E5B8E 7CB3DB69B383352211F2BBBF0362F1F654F351E58B4CC642BCF4726E3BBFC4F9 EA7186583E117D73673905CBDD7B33127B3BE3F979031B6E0A858B205C4BD450 46FB47FE7EE3F6662FB9D6AF3484032AACF368E23E16AB67AAEF5D21EABDF65D 8B4414B902EFFF9B67701B836D91C20D92B5C18D980342E9BD9C834A4266FF14 DACEB9CDB91ADBC8377446B07192AB3401CFE6A35920ED5089720409E1951474 C33B5F87E617EAE9FA1B7C315335042A614794895DB545BAADF0939746DE346E 08258E8481F9A02A854E3773394C58FA1130E59128A3D9B229AAC8FC0D7F029A 4C2354983CF6985A495983CCAD4B00C8B22F818E49122CA60F34434BC713ECE5 27F7DE27339B9A46F0D9DE2A36056CE04B185760E8A43C4D61CDA9C9618010B3 E6B7B3A033A872EC36B3E67CBE583F1897F406AE6E08AC02BFEDD4BBA87897F8 BC3262A26AAB01EC30F482139EBD866859219D64F66D6755E26C2ACFE07A94FC 9D93C3E4761B8B9A37901611FA55FE882D9DF38787A488E9731057DE5DA081B7 D3052817F5BDAD299734960179E370A954FC694EE1CCDB9221AB1CD47F5D8317 ADF41385B22374FEB8697742F87E473E2D47DF10F793514C5CE04BE2C5C07984 BF6D9A16778EBF7C9E2DE1AFCAF44E45E0F419E94042DFBE37677D0BDFCA47F9 3D6B72642FD35B6568ED554D2CC8B4341F8FB81C33763C77EA401513125A5554 4C091EAFAFAFA7C19CEC41FFF244F013D8C6298EE0B9EBB7932E14541B4BC8CC C3F080415A8F016E2535780BA2FABB5753AFCBCB13DA8327317334D9E5605AFF E696E2879992B8F01C19227B3B31E923C14499ACFF83B5D8B73B300593EABC9A 892C6A90B66A0C492953E53D75CC57F8D9B8BBB6E19994FD03140DC1C868B51D BE73A61F7C685A3A9ACD538BF020C5363B1A146A83CB93E7B8637100DC6EAF1C 9B9422C4C0EBDC5181621AF1C3DF04F9F25730C40C3738D864F4089FF310B532 AC3E34974D87DF814F62F18C9766F2FCC22F2E8E2D1345AD1031D25FA6E379AA 4AFD6923CC92B3DB7880A7DCD2125B9AC32731E3FA2C3DAC501C85993E3BFC6E 3CB069A860FB2BD2F47E9A9A8F5AA5D90926A7D5B1AFA4AE370C650C18287C6E 4340DE71CC7027B28E54F398EBE74B101ACF563C54DF227F5857E435E9B332B1 A2CAB0E8D157F6BED371EA19CDBA98188697838808AB64F6AD8B8C0B611312A4 C52284A1D3BB62649934F3AF83E8680C4298107A9BA4937BC5DFC6E02B38D840 93798BE30797112D44C9AA9CF4E9437D11A8908D440743F16048B8F01E4DD644 8437F01748A496F0E1E95F1BF0A8A68CC3EC5D5687E8AB253207702CB2FB20AC 7A98D2D9ABD7156A270285E95138E27431FF37807872075A8E4B81988D59AB9B F4BA0E52D4B1D19047CBF5F66274B572A28BE387F4B580630F0C6199B63992DC 7C53B6E7B1CF6CCAF045CF09C8F7A0951921667A93C1493D749C2265ABD7F562 F595D537479000E76F5821EFE62FD197113165DF4289D5E1CBE9B05625A5F995 BB20409586D632BF2757C067AE77693E83A8921E04D3BAA94382B93A3E3693ED CA5A6C71D0073B78371D58BA0D2F016A43350F00343D6BEB95B49B7226ADEE5E BFBE8E2DEE5184187949A7CA9849127CA4E99CCDC1C550352D370567C62593CF 9DEA6F587EADAF2F04EE4F661D8FD7AE380827082C9AE060182AE0C63A3009E0 E1BEF1550620A0E462A0B8918BF60E06B61D3E435B428D615304AC3023E83772 C6B048A55AF204D70609174535E26D0E6B3A271D40AE1C2E5D73E0BF2ACB1C98 FD29B84C316F7496A482095BA784958039B6B7D2E9BE4FCC3FF4AD97B3CF54BE 7BDE581049257BA31BC9AABE7ECAA5701B91820A36C62FF7573346B9B30976F0 A43383030B52BAA6C11DC6C8B745414D41D4BDB61CB97F40BAD09BB4EB0D7209 2CBE2F02E4D808AFBA930C0BB8C106C5E59C922B770648FF3A3687FE55BD4ACF F0EF66BC4A2099BE15B16EB32ACF3A27497DA2E6142A2B9F13EA2A3A82EA7934 627D3971EFA6AC61B42599CB1FA51AB0DD8F4F7998B3CB5E543CE620E159D1A9 1B8121B319C0C3620C1355BD1F9F290174CD1D2AA05ADD70D60918BED9FA0A18 BB918CE247F51AF1B246A6515D62796B98F4F84D0F10F7234C1E6CDC520C5561 3C3D984560364932AA1AE0E2452FE7753916DC8B043F43EA00C2BFE47C868308 F390F7450AA754830F10AC9FEE0F230FAE46DC5CB40CA7E2B6E5CC8B22D64BA2 E82D011DE86FF52F012539ED02C4F58EF348976964AE729B949B77DF7ECEE7F3 F51E4202E26E21DCE18DC0FB0D31EFCFB0C188A52699AB1F0DC1CE623258DF54 B0332C84EEDA53BDF58809283A55C1B090503E2E1A0DA3E647832CF3231BB54D 0D6D6E4BB80425136FE1727EF3DC39205D1079C6414BB18C87AD7D3B445FADD1 ABFE8BE5E9B857942BA11EAA62316CD74848CC89E92D8697F20486F55EAB7468 FA49D3687C78B8C1A65C6D1D28860779F86A4068427E4BA5D8D5D4035B6FCA10 363AC21D2D9FA6CF465327CC19350184EB823B37AF8BF7501228FA813D9F022F 2FC12A96865C7AD4E799760C395A3FE61B5BA1369D12B045A8457FC32BB3CE24 2EE58564A0EA57A09F0EDC7223DB08C10951D4CC603E0F71859C4F05312FC832 5A2E34621E31787B0C9C762427803B6DD882EC59B545AB3CD8EE4700BF7E1834 C9431827E3C2A98DB9D2DD1E525EF0387BECA6CA7FA349040509E0C4D552BD3D DF1EA3E3B35C0BC7079A2C2ABE6C0DAE9EBEED559B413E34461642640A640244 A10E8F7A82506DB94CF83D2D44754FA3C2160821A7AD460762CDDF64D0960980 FC341EC9ACA3BFCA0600665311BAA75675E1D99CB2F24AC2DE674F06C03C6825 6B37946C533EB12A38FC2B31C52A60CBBB09B41BE98646966A43F0AF2402F4AA 57C0361DB95B1CCA33E4DF4E2EC2B42BF6DD85988CDA7E05BE6D949404DC878A 6B3B926A3A7ABDCB84836DEFBF5CAAF9EBD136B7CBC274729C142AA96FA6F20A 12010DBEE9AE0F53D568358ABAAA78477C9553F6C499188BCF09F0DDA2153035 2A47445EEC484F2A6BECB882E2CF121A04BAFA1A96FFED21ABF2903EBCE81DE7 DFE2787FCE858FAD5A9DC9F6BB6C520715C942D2A79D8EC549108474E00AF2D4 D466F695FF681F548F2829868172F14950E42CC66F826A3A6924A889C7AD044D DA06BDB19B3A49E60CBE7E9392DC77D06DC6600FC191717833206EBC349E3C64 AD0A7A3AA8EFB80C40A3B1CD93FBECA377367D539C0A0E91E2E6932BA2F50840 1FCB806459D2B4A164F7CA0FDADB88D91A4C3EA388FF62A402155A0E16B03435 F678283A1F28A5035804D3AE65019F31CB048D95BE60A97A6494F32BA9E17941 596545162A04FF0171A36F277F49DE998A3CBEB8F8C598AA96308CEF78ABB2C9 D8F3729FFCC82D8F529F017AE00AE9F8E5B02C8C1C687BC945059D72720C9716 9DD15F79C992F558874E9DA253B01B26F75F9F0ADB384B919F5A8427457B2EE9 7CBBC543066CB01F02276F0FA20A12FE9CE7E69DF74BB456A417588C22F82CD3 8AE7913A959E7D27B759C94D67FC55BC4D1FCFE739C50E5509B6F272B174A7AF 688A45DDF72B398B6B41A3D0BD3820791C943656C77FA49AE2447079BB4A61B3 397CE8F180621778693642D8493D2A3A1F2C54D475643671B1AA972F87902C62 8EA53B3EC372FFAE46CDA4DD79243DF892B2B49A3238028F41FDF9A1D904661A 5C89806C6E564789443F774A0D8F39D1925367747E62FF8F69279157D18DF644 A49318E7BD4F836ED366963BD57A5F704A55795567F23D2C1B07975A82B76EED 75ADCA889839536193CDE285933BB2495252D7B33C438D28349F30D71E5B9910 BBBFAA5D5F894E02EBB4F9076179115E5C082B34EED18535304B12ACAF3A5D77 C10AAACB24BF7CD17ADC52666EE8D730EBDF4659EA89EA088C1CB7D4CA4CED36 8A99AED7F997CE967808A477315F4919506B28C71805BB5AD4C797F5F98C81B5 3BD861F9F57D65662034C1D4E88F23A8092BB709FCF1D2F481534A4BBA20A18C 6BF85598FDF6480AEC0989533CD11BD25DF8C28ED16E6E8F75B91CCB41400602 DB164070B89F38B4FAD6867886DF305D45B8FD57C72489096E0CC2153D26AE41 7498546C6964461FD455441EF6BE1AE922D0E2A62253067BEBB65E926AE232EB D76AA7976EC599E9835E21E1D9EDABC53081E80F7F1B338F5A5F7D4E619FD6C8 2CDD33A1299C5DB13E7F5BB3765BE54EF46A2A5E4DB5A00D30609A085920C7EB 68DE604375D37EB9A0622783F2332E6FBB4262D268B79F5E939A99572214F969 C63AF218A2C6AD6180E819E880D9A78B0128E93E004B6510769015A724F64DF8 0E37A8DA8E541E836CFA5EFF5692585AE779045D6D4E2EDC8580502A5557AA7C 7C21EB7DD58225EF9676F2134E0B1D6038CD9CC41AA0BFE88DB3E2F1C8360576 3FF3557F29EEE84D0D14DFA2801DD9E8BC3AB5DCBBBFEC020FAB62671845574D 46C4BCF1455888C25EC9DCE45EA37E89DC6CF152503F9D118B9280A89C8A0C29 5E83F0DA2851A04DEC6AB0AF04B0EC40D17470605A874778D089F5150A19DC33 E29CD339F738111CAD30E1C542749C2CF8C23AF56212429CEC5F369D8D7EF956 5E3B00E83062875E4CBB17185D672241E2CE4B0E5CDAF8820F8B3D0B999CA50C 995EE9678A23B8E00AD23D18482C30DE5425384E2F7E68A8D7A1FB279B9B0502 D6C40FF8DF5137E9AC0FE1300EA255AE4D6B39AEED6F9E15711AF84C1E913D79 8F3A0095B43C875CC40262D707A05BFBAFABCBAB5071834CAA3678C5FF44BD45 6E11A024FA94D01981BE7AA5FB84450F7052E60006BA5CBCF8E11D7C859B464B 98FF90852E1B3AA5BE061C3A827B015EF5C7289C4D0D291B5BCA7E532F57ED10 48075D98290BAC772D84B07B1F7502B4DB59BF49EEE890EE61DDA21CFFDE7220 AEADC068CD3936952CC4735D59EE4747DB9E4DC5AED7F8B096B96D94FF5504B7 503CC1545182BDFF265410169208710DB4B7AAC094271076F36B90BB64202084 603747B336927227B88B4E036C6E359FD01838625A62F8D790C782A738D11AC9 624F0D4E1C3958B7FB28833B83CC9F54FF98EFC2D10674171B50335BFEFDB342 AD1344F973335E8F8AB6D483A8C75BC8B33DB9C49506DA009813979E6C9F5BF0 1885290C2B7F622EAD2B998CCCA6FD5818B6F9596A8087C73D95DBB1ECC3F414 8B2807A89C2734B2740E518A59ADC20ECCF98CE1C9803855A750C180B6E2B354 80D8ACD8F95FE36C1218E851258DDA90704E43F4366EC0D1A519A8685078CD28 B258F3DD351EA10519F0383F0A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMSL10 %!PS-AdobeFont-1.0: CMSL10 003.002 %%Title: CMSL10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMSL10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMSL10 known{/CMSL10 findfont dup/UniqueID known{dup /UniqueID get 5000798 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMSL10 def /FontBBox {-62 -250 1123 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMSL10.) readonly def /FullName (CMSL10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -9.46 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7 5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99 8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716 EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C 02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D 46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A 4B60D020D325E4C2450F3BCF59223103D20DB6943DE1BA6FC8D4362C3CE32E0D DCE118A7394CB72B56624142B74A3863C1D054C7CB14F89CBAFF08A4162FC384 7FEDA760DD8E09028C461D7C8C765390E13667DD233EA2E20063634941F668C0 C14657504A30C0C298F341B0EC9D1247E084CC760B7D4F27874744CDC5D76814 25E2367955EA15B0B5CD2C4A0B21F3653FCC70D32D6AC6E28FB470EB246D6ED5 7872201EF784EE43930DC4801FC99043C93D789F5ED9A09946EC104C430B5581 299CB76590919D5538B16837F966CF6B213D6E40238F55B4E0F715DBD2A8B8B8 80A4B633D128EB01BB783569E827F83AF61665C0510C7EA8E6FC89A30B0BC0EB 5A53E5E67EF62D8855F6606E421BD351916549C569C7368AAFB714E22A023584 8B1D6B52FC6F635E44058690002C6BA02CEC21C54CC8875B408A8BB84F445894 5D6B3E4841CA20AF852A660FE9C832F773691DC6F7197FF3DEAEE97418A5ED2F F2AE65300416227CD3BB03C29003C770CD7D2A7A2E4C1DCA193651C2CDDBF93B 966938788694BFB562AB0010268955FC3555E5984CCAB0A9B7590C77C9BC713E A29E5BD7193A4E971D1752DDD0F0AA4648E7E87BBCE66A1E836C715C408B07A5 9EB56BEFD4596706CF839BA4CFA90CAD4038C1E006B51913279A2C31FBEE5BD4 A7D74F9103CE6124F5B439CB860987DF44FE17EF88EF1BF62C67060D25696BCD 94ADF08F04E349CEBDF9D3389D870D94CC05E393B3F4362A13A6A672EE5E8F5A DFE7046AFE3EBAEA58FFEBA4A47BF61F92E2003756DA643CCF2C9DFCCAB62669 E3C2A18D690B64D907F50BCA155A85E47C3A6954C6FF7ACA36D8DFCE777B7929 5F5D5F787B9C247ABF13D6D7B4A8F06BA25CCB342F8A5071325CDA86AD71BA23 8A9695C7D1D50D0AAC267AB7CDBA7AAF46A264B7B081B7E79AD937FEE4969FD5 155A99E652461EFFB4BD010E5885631E2B2497D6B8C43CE77D7D47FE201DD46E 4482FFDCE150A1183C22C004A0AF0E1F42AA6804E038E1DFC8B0A3CE26B52038 44D2E7F759DA5C252489E5525963D68BC27C82247BEB18818C7D4CF0BC5CC97D 8C701034B8DF798DD4CE36C3F8B1FD40B2DA14EA75583852875031AF8C909EE0 04495FDCD04B05A5EFEBA56A8CAC1F57F1B8AB91FB25C81CD51EE69D6E0F52CC A0E12CF7E3187D67DF71A599FFD895FAA7BF80E2E6B96592BE77AE96905BAF0F F547355A36C443797DDA7C414AA606CF9153E03450B77D1BA4088D739DF55F07 111B9E11AF37F45B6EDE6D7AC126E05886A57C83886DA87761BE600DEECD1344 8A82BD652BE7ABFE6A0F50ED7C6F4EE12CDFD80CA7A5518692F267C51C3FE76C 567BB8DDBE09A2AF901F79AD02B435287CB8057B3D5EE6655071F67B00438728 C4C3EBD648BAF650993AFE5E2B29074A99ED0FB725D9B8CE8B0292B08A280214 C3AF252BEEAD30C88F72E322FAC3E9D78A1038F5DFC41F7BF1AE3744A0677094 51B77C2D630B67853FE5E975A395C06A4D4DA744040B272C2B88D8B7ED3A2C01 66F503C9DFD3C7DDAC865900D2A4F2CDF517F449851DB1963468D0266D7A3E58 9F6B2A1843E6444274F16A9930302DACD8D2BC4588765099A86BCCD8A31DF0E6 2853114DFF2D19F812F19AE6C2E419D7AC1BC024D1195074FD0C6717BFB389A4 4D5428E7BB2E4F9E9FDEDED7BDCBDD3460805AEA0B5F6460C2FDF19273CE5BA7 5D3AAE0DB94C6AFA8339646191C23B0149E7CBF136FC4C844E025A38935DF256 0A0A6466A45EE8B9B23B6A055856FB084F87C73BA28F1883E3B184CD813C72F9 233B78CA4E125ABD26F29B92CD9DF39D6FDC2A217E2B6B45D9B0A4D536790A5D BC0903069565A442FA7466414D948AC432C6B75D8D0E1DBB217CA3DC38A52DEF 62E9D5AE9E753956C13819D93148C7683BE4F71B80BC066D8C19FC807FB1C086 B49215DCF56A91A42089F0D063B9981925691F7DDE3237403AC714F5CC3ACA88 DB2F1DD205578C00472FD70C8BA4F752E3923ACF3164D442A6B639902ED060D0 C5777BC20F9A3BDA60FA3BC986C38136FBD2E8F910E32EF36377C9CC187F4AFA CCEC423DB925B378522B748BDF12D523804CABA83CB5A7ED69FAB9AAB75EE8FC 38D9866E3754C4E2F2B9AEFA804044D878DED0E114EA0E9682FCF38F6628E63D FE1C1B5615E54FAE8684566EDC4B616F76EEFD6207E0386F06D3BFFA26425F24 303CC7C8A8D7021E7D09B202616988287838C3DBCE3179B4FB5C726E603A47F2 8248CB508F327D1291CF3F08F7C88298DC2D0F778D24304EFCF6E074182BF5B1 8E6551811FD6991971692108E289B61053D6DCBA2925B3903E8916EBD09D97A2 C6D08E89DE4C0CDF7185E1E00DF456B249F0BFC686E04FDAAD2772DC2C39DD53 9C23A41471267F53A87E5C2B8CBCDB66CE0B9844BC506428E6150B48D2FA6363 4FDB2CEDFBAE0B7DBCE4D83E29B2955F8966272CB865EDB360C8A8C19EC62A29 03066483E4083524A1E8D80FE3867BC1AA91753C26ACBE8489AB0E3330206212 93E07ED473DBF457EB8489E66FB4B8ED8A9EA8911CF9308CFE3E6D6F36810EE8 91CCB11BD548617B2C683C354452B9229E7C9E68828BBEC324420DF7C188CCE0 FBB514547553A7E9B38AC265783891F42DA472388569C8E7594F7E8810895A27 06E456902A8D9F65CA808F1FD475D011C4572F8A654BA01D67942226A663D179 95149FFF41A9F55AE84EEB9A6A39C017D7E4FD6EFEEE7FF3CE847CDB064A4954 9DCD273B810E0F259501BA4003A3EC1ABA6E13D24C0B57FF82D6DF077833B6A2 7EA54801BA81DB961C261689C0887FAD83771E55D3D137AFBB21779397E11972 6C6CA922F45AFA5C0526863A5AD8B9C0775CCBA17FFD37A44CED4710884DBC31 5C9D3F5441595B86CF7CA2EEE42AE87896E9E60EBF5F35C2B7FDBF9A9CDAE262 3F48396F0F741E9DDF1D4FEF75E68AFB020D06CC29B3A7B2ED819D1AABC12B91 CA2A65F1AFDDA2F3FB322E0268DBBA024663E49EFF076455338FE31A16B04EC1 797EAB0B49AFFB906A0690A1E8E2F5314773E1CCFFF43E6FB3875AC907F0C5D0 DCB9BCC127014D472463560CA0CB1C2CE614D94177C7A52A5B089316689C8112 CA57E35D716D956DBF9013B1E5B9626456B1433C8C15FA906458F957133B9E19 8D46DC3AC015F7602538C2AE3927C6DDBACF38E59220C2F5AF36B68DE9117C51 04CF7DF32B1AF55B87D1D8A5F4BCFEC66F63B32B6548DEDA3AAB06C5310E4757 78AFF947DA22809B360FE535506A554DDDE5A6F2411246653710ECE5CD3185BE 730520A766C47E1ED01890059882BE1432586864E1A86A7F586438C8DD35C00F 021A741ED47E0F16DB6070ED0C50038632CA4AC2975578A8372A080CC0447C79 CEABDF2BCD5E78564247B0F0025F556DA8FB62125227849EACFB724A4AE3EF57 90C07A5B27D2E59425F56BF8AD84C5F5310FEB1BC73D536339FC2E6A5BE2DAFD 97FC835E0D52F680F80ACA37DB498AACF152B9B44626CD89E3302C3EE1623EE0 F998FA78305960AAB9F483F731F5F67A8C963C23DB8E48FB804EF8B86FAFE7F9 4C09641915FA7E3930AC922682313408BC1607C76751CEEAFD660206A39CF394 40ABE2A313AB7D5FD6444E219DC5C26734D322BA268D330AC17959A390D6C8E7 3A155095BDD66516DAD5D65519A7FB871ECDA77061EFB21F359158B4470EF79B 362C35C06B85C9A9505C8361939C6AC013F2CFE8EEF46FD8CB4452AAB3EF1FA7 DC066557BADC2ADDDF7DDC2A0E1DD4A357E27A2073427EACF9B9035DA5272136 7DF37E26D96ED4B2ACD60596E039BCB15E259C72FEB3344E3EEE3D4F17DF4233 04C1416BCADE80BD483DD8C9AF979E1C7D50C4CF015870703F88B92C4FE46AB8 DE6717B55C460C805B391B84333097E116F4A51F631FAFAB34CFC925BEE8B72B C9FD5F5A79D8F2295FBFAE649DC6AB47794AC7D73431FFE5BE992F2B5AC67049 B5208251C0E442385A9FACF25E3A98D7F5D4C2A1ABDC600AABE84769CA83350F 9B87F71CEAD3600E02FF9AC03C1B5C21C84F911511A0CF0111BAC7605EE31229 3C526A79D943D92E1CC3C38ABE82D560CFD4172F318030852A5FCC0534B8B3FE D7365987C8B48A072907B26CDC2108130A33233E8E0BB5FDF14FB55098A10EA2 B51AD9EFB119F82B08D256D396D3263FBD9DBF172D43A90ACD1A31F3E89E8571 74BE98B9560E2CD661A2F93C69FEA3FF26B00772AE2C2C24B98D3D122EA2AA8A 44652CCDF4EF4F01CA7D62A976E23E8A86291F43BFAF38FD9C325E70F9C36CB5 A181DAD30156E98339E6A0498D3420B7BB3B4E651A9090D4A17604AE386273A8 3D4AE8CC18345E6E19DF06BA848F203F74B161D6A8882991CBA7385F308696A1 BEEB0130D938A764B98A2001A38489B1334025EA848CA44A116D64926D460D64 01159E77EA7ED9ECE7BA77635BE564A4ED89315BDFF54ACE6AA1A26591D13CD4 6D6425CA7933769B842192858D10998509396829263290A3A7CFEBBDA3EE6CDD DF1E492AECDFF7941B53573F01F623CA0A5ECC9D05A3D0954F7AE8CE94AC3B2A CD4E27519B2E16F033EB732AA024BBAF74626DB55DC74B1FDDB07FAE98B4AC5C 683CFD8744F361838D343B657EBF52DEEE7AEA7565C5BEEFE455DDDBC4DCCA7D 87D6D769C5ECCF14118A14A85A86865777C8E28F953160D5E82844AE54D541DF 550D5F1519E183E0C42BE88F0458CE8087F2CD4B1B49A8E9E3D127C4A4CB74A6 2E73BF4CC317781D03FF04BC36AC0E4AF99E2ACAD20F6F8029DE8A035DAB40DB 17D237850BCDD05931FF4B0FE2D0B79EC5A88FE0236271CCB075BD194AA25AFB 3FB93A5206F61A14602E4EB6F1C31C654527CE0C02D04314DF9AFD710D0EBB9E F8721B97F5FB18E27507E1F800B5509A58A1A8296C72B7B73F99B6CFE42E9C2F B63B3555475E562672645CD374BCDE937A9B05A157FB3E74C8297507253E957B 1A9DC421946734CEFA3D5EE357DAC7E9DE17A5BDDEF6B2D2A740BC58128FC514 61154664412BA1C05209EC992A77B7CA45AB7C0EEBF590A5B5652866008CDEF7 124A3003AE6A7CF9DF3C72750CBD281358CD2FF25B162B78CBB971DB3477F8D2 ECA3EE9CBC90323B2C236E375337EA0848CD7CB5781A2B0A42DE7E4D99DB2746 0B26796CEE129D23C76794B7CE21C13C7D4A998B752C8CF43A4821B736EBE246 D2A2BD7BA3351FBCD1B0A501EC1EAABE60D06DA2FE39BE1F0AD629769FDDC933 F9D02F9686EC8C2D7455C26AF4DD3F6860B2289E3A30E1C254AD17D731CB73B2 BF4DFE90CAEECE3ED0CD3FB4C8F4C7BE1C056AB4E9B95781A8968E3CC1010003 75DFBC4AB9F6B27C5A9AD88D94441A8ADF09EB275E5F0E5E6F3BFEA0FA8C308A 8593ABA0645ECA8FDC3F0E264B35D4B0DDB86B93CD8A047FC409E18196B501C3 B003622999C47BAC04FD1ABD8AD359C977766E9643EF3BD6385306B08EE3E13E 7DA5A06AE33D17A3D574C6390DB6E9429754B210F0C349C359559C7EAA2350BD F61D4D8A92B1AF697BC620FA0351E67E0D9F41A95A47EE0BF210C2C48691901F F905F65693DCB85BE412F097480F6A7266AE0A928729DA0F691CBFFF3B276EA7 322BCD2206D96E3DAFDFB992CA8F2955F0E8B882729DFF840569D12E4DA1775E 523AA734552AAB6F2F16B89B39F1A3FF0E07EA08D13E612F201716C67F327017 6C041760DA30374434808273062C1FFA2C47B3FB578807BC26537F542040FF77 66C995EF3E8B08B09FCD3EE89C30F157158A739606D2CEAA26694A4F1CEA6633 B54933141CB85C60AB262E2D4E824A3B85C2BEF810DD774F296AB37D0BAE7182 5648CD18556ACB124246A75474B232D712C2358908B5D9A76F82C626BFDE01A1 093B8FA6AA0B32F2CDEF737B28BC0448FF816DDB5812131DA0DD5979D77C3838 B978CC3F6778A4BFCE9A7087EFB19749285AE4C92B99A6649DA349A2E0889D72 6D4FC664522F06C8C4D86D30BA43ED4E42211217D01636A4E17E2A132D26F394 EC34EA12D84594AED9C6CDBBC0908860F39B240FA7D7B3003DB10322498691CF A294C0FC7ACC0BAD1EED3E9D60AAE3F7429695892D1A21CEBF062C6129B33966 8B2EF6E932F9891DE6028B81C5E9B23278D35B7F0D83989BCBA25E20E9D503DE 144DC485F09A4EFA1268AC5E4B551C5B2F1D51E9B9B9C0FEE585204F869D0BE0 7287D7570A12940A47C1F51AC6134F03B415C30E147C49F89228855D093EE55F 172711F37776E97A99CC4B36E2F10713E36FB279FD3FA5A0EB9F3938F42E2BB9 254EB8F0C0F30391735019E02BFDA21D9813C6A22279B898EAF01AA892B14DC6 5912B9275167AB46EBC420836CC1A5F38A4EB47C039A7BCA62BC3FCE4199FC71 011DD6E5FFA0F3D7F04AC02AF91B9249B9F993AE346572329DA852115BEF8460 B94690E790003586F473F37EAB5AC2922F5F663EE2C3C0C336A8DB71650631AC 0A923A389AC911CB215EC2EC7D50CF8AEFD59EBFFA53A9F1FFB7E6215F17093E 3975F186FE23BB5FA5474C11408FABD223E1E6F62035B5A5C1AEFD8899F00FFB E729C2D5FD551E80716CEA4E8281660286A802AAE8D5834F37F2EAC46297E57E 993B09251DD7789D3467417E393B7DEABD06676B96241B0E43ED1A1A9FC3B12E 0D34B2B0792B79AA648FE9450C3B209FB6D7D91F50C52A5DAB0BC81A8B698BD9 18946EFF691912D7348D48FE68CD876FC6F71F81165D0C3272DA1A992308D9E0 ED6D0A4DAD679AF495F62B78D462B463BD4A40931172290C615B3B3B6B47E45F CEBB85E0A6AB6832067CA6D403C239530D07F199788AA4DD52553836851C5228 1072406F6D7323A334E7A7FCA588897C4FBA6D4F7DEB65525EFB74E539C988C3 A685A98752F7198E77E456A545F0D23A1BEF81EF58B02D289CF980A3F17BEC8A 6F83DD90C4A917EB0E5E2B444A608E2E9D2FF80620E16AC1D7775C0A10C1299B BEE0E1AB24C50647E5CA1DA65CFF3B2C295F0644CA7826E1DC6FADEA93D66A20 DE852F20AD224D28DB900519EB1569837139C833F24B799F7EBE3FDC14235323 1D0BCD4991C861F38DF413A5A5588B73AEC3BBFDB885CE17BB3E97B4E6A79761 93EC8418C2BC4725CD61B5E30C07352F647C3FD50083878C13CFAC241DDCB082 E53703D182068727F9EB6FACEC25F6D901D7309ED7370867E34E267519E22D62 4FC7093448BD0D6B1C43D318A3E14C92032325C132AE0FF7ED707E1FA4A955FB F5224BE0045CB14ECC321D0F333FE24EEFCC504F7C756451D7693C3E6CA87526 4912E1B6DB935BDE76FBFAFCA4ED473F1D2618812CFF25A6859C626A216603C1 361BE3E071FCFEC2D4BF2FEBDE07DBD56A1BFF8303901168FA06488BA6B76F36 95B0A90D7724E9ADB567C2ADC65CF3482CF47FD1D16F70AA19A97D0F9EFC611C AEA5E1ACCDA7FB2DF05E9480936281484BC329F0B771775E73F7FD72FE3F45F0 50ADBD03932B38F37A8F0A66B2F739EA3AC8811C8F514E68C5643E4AFF485C81 88475A523D7FCCA5C8809BD49846C77795A38DC6406082000236A4D2628B5932 AB7916D44EC2210CB941B1422DEB13896DD78CB7B7F400EA5A6CD639D9CC828F 52311A11F2A84E566DE98826F1E28D55FB08ED70950205DE52C207CF14238446 084FB4DCE04C781858BB4E0744C023EB0B563769751AF1D807EED20E4AFFDC46 3C1510C782FD92902761F7557FEF701AA67B20A9B019C760B2BBA8A048BA3681 35DB440925CABA05B8A13B2D30D14FA875D3E200A018C78BE2E930457BC33AD2 FE3610314A268E9A30EB41F7C771758410E7D1179567B22CFEB5163F7CADBC40 4D40860E83BD5DF2BAB4822B55B863D0793D3B60F0DDDB6DB993711C4C7C2F39 31D02C7D8EE36FFF8FF2179534EE4F2DF388C8AF7468EB28FD5E0CBDF9E23D1F F320EBF19352E03458A43BD42366D549EEE1256555177E3D6A0932C6028CA6D1 1849D17B5DA8ED647B79AB412E0D5BB39A58964B4CA44CAF45F63AF49B330AB3 DD863F5EA66EF0C6D7FB2EAF256CEA1CF067D32DDB9E44EF1E351BDB292EADD0 55C9796128CD979A5F012FA15EB06B0C15120E70E0FDC963BD83BC0E73C5DB4E 29A03DF4D2722616B45D8664ED5EA0F0587DFFD8DF4D75E2B6686336B4E51EEA EF477B86955E866E664E85AAA08E752F656BBF1A42399248C71DE0EF51ED7E50 34670F9B409A6C12A58D7479885795F31D3E6F90BADA0DCD650B5F64E2C61EBD FDDE74B2227D7C20D4F215E4514575253EE48341D472C2E89C2F3CD725C0D0F9 1B86D25D0B9C6EF72F6C4B911EF5040FD741AF3D54CDC8AD000EB830D2362FE5 0A5599553294736404CB5CD95D394627261605BF602F58D07091A4B329165CF0 0B1445F264F4884B5123963AC4219453664B075586E92448D9BE5460FB17E4BD FF59A4F1EC1E48F6271FF3E70DABFFA6ADAE1CC466593A63ECD1CB507C62002E A3132EB846195515B7FD321D332F0EF8608059CF34B1CA05024FEDA516423515 60CC65296D5DC3A82E43ADD814E0005B77C103B1EFDF07470B09FEB4443D8C5D 5182515A2FB5C5C6D38208322ED125E46249AB7A07AF98E4720F2F64E0BDD651 539168A6E5213ECA91E32702FBFA0385A91B743F5BC41378678EFEAC4A5B3CB4 BE3DC301AD0FA9E8E19DF5B13B03CBA0C37EC2515C2C9B665639255258219E69 092D1CE04E60C6858B1C24A83D683B1E9CA233DAD4836405A235A53C272F5695 1CD28C5AF4C609534E9DAD5723802FDEF1C516301D178C95CB729992924706EB 817491F033A6A5BB90D906064CE2EC3AEB2A7738F1FF86D8DAD4D3C71F265830 FDE5D597B168BA9FB84A4A928C4C7A8BF6C69E726C85B1CB4552E1714272B73B 8F872241429D74C4CA644611824E973A275571270AD7846A7E538A717303390D 2E597C60C14A09957274FB230E013648920756107BEAE66FB53CC8678CF45516 C4F16B0D8C3F315B8A167A9F28B681DC63456209A6AD3BBECD800F265CE1379B 74199AB1584FF9E8AD4A2E0EDFE146FB6F29FBB56E43F78695976ACCCD3C0C59 D727E7BC6CF570379A0FDA9B6969BAA5F50B409833EE64AFF6F07CD0DEE85522 01C04C5A392EB0912282146F575AE2FCF68802EDFFAEA1B27EEA2228AACD2653 E6070915AE82A8EE1132D1AEF54D714A11B8E5D7EEE908E656917B50D0503353 55AECED82FB999685D2299347040EEFDBDA0CEFB1957B6558E365E4A76B4C247 E455328E8D5472DF8AFA4B4EF21CD636D5E49F164DEBF1B76175E2A2CFE07C06 C89220C9676A83B24ADCCC2CA075320525849F3D27B2280B6CF29389BCCA214A C0F773C28D7261F17D42A06E3BC2B98D51F3554D6BDB9B705F27DB5360A803C1 6C8D69B3698642B4E38C5CD7F621E8C8AE9D40CAB4195E7C8955B0301FFC4616 0167E3FD40D062D0A82E70FA8B3B2C50B3A821E14109D3E909858B4B3625F0B1 B16022DBED75024D8609F1422D86620EFBF595D98CEE842B03B676BECDCEEB99 2A41C5D757BD071310757D9BE394E780195D255A309849348ED60ACB7A1FE0BC 707679240C61034675C4C1EE2C7EAD9441ACF23919646B9BC479BE540D60DFC3 2D90CD431C01BA26E64590B726376199A2C2106418ADA1D457691440F9CAF07B 3BF47809AF74CE3F7B17AAAE158A26968EE325619EAB134071968AE31CC6621A 4DEEAC286F6FA27792486E739E66449A3EABE222473285CBCE80951ABA1E8233 B3976218956FA4CE1735BFED7D90DF345C4EDA1E4BEDC378281FF4A6D25FD649 7D36A7543938A8BEE7E5D5C1B990F601AE018D72700D02492A4D15DD45EEEAFD 43F43B7577AACFE90ABA0D2362D6C372DB917121BC02CB67B0FBBF4E9EEE02F0 6B95424DE2303553331B76AEC459B4A98D406BACD9898DEC8DE2F24883EA3D66 FE753C15BD40E2E93EFF44A70AD9AA0356C3AB43C5F7F5AF4CE66131887D6D06 E6B7AE106D08B79CD8C9DE88F4B9C6243AAF7A54BF7880B6140580FA2ED3807B 275F68271018A364142F96BF11073FFAA7A6E19F8F6B6B3E8D3A387EE880DCA8 88E86CDAC6F4633B00FB3E79FA083FCF8977021F0CA2351E7DCAEB4BDC1AB94A BC0D536D6F0E9AE5BD44F9B177DDF0C76675700B34473F2F0E30F440EF59724A D661F9337032F6193224A926A3F8566832E64D38D40A350282E284DBD864D4EA AA04EE8B01CC7273D4A49B76D2F3B0C454A73063D94389721B80C6C65B16BA88 28B26ED7F00A92948EEF95C118FA36B99B61DCB8B332BA2D07D3EC989540C24E 3AB425CB74576E6179116FAC82D89247963153508262B922972006801C021944 31E3BBCC16FD5FB34D8C9FEFEE2B2C057FA129F23F6654680EEADA6C6F914C08 A3691318152B9E099B23B997ABABCB87475D261F3827F94C22CF179D6C0D4317 D30C8A03A1B98F367FC48AFE50BB6138C77E2363EB575628CEAC975C32D8810A 953EE00088A0746F4B8938AA636FA5C91A019300C64E792AD0272EEF3340DA31 A41FA95F1B374A14A57DF70BBB554124C2C4A787B9D87DD9EC857C61D5E2629B 17D6ADB9892DD973550E2C938BB3D4C8B16138700B3B8647E7E69B38FBC61B53 87663A0253513077C51585D467FFF3C7818875E709C582FCE5F804B2AD18BAD1 7932EC43E9412AF53F38F1AFCC13090559F113FEA5194C8860DD18EEBD72E969 04AF05584D26E25EB05EF7A5BA9D43FA767823072BCB67DE420D49C675E4E6C0 BEE3D0E9C5BF2F79D1C57F4E4D3A9C27A83704BA227F81EC74C51877085960E9 D137B676AF998C4B9CBE8C047DD31DDEE8E6B6341669E9948EC9C6E492D4F937 87664AACE9DEDA855AD5E865C94902B139DF132AE654F064BD36F87693E99F63 CD672DC99A9733E8430697E9D89C370AA3B9FB286F42AB7FEDD91FF355119A5F FBC2E62FCA5A7366491583E6414981985A919864F5210408AAF9CAA479302B8B 2326424B3502A9E74D9853F1CF8E351CB663F6ACCDB3FC823BF867227900A91C BA9B1341791046F11D046B3A36749E3CA8D5169718D67D452F003AE7513D56B8 E41BAAA7B37F73F57262E954A847F4D52176C81F2A394EEBC3770F1ADA9214B1 21E95925DF98313DA9F93A270722BD1CE2FDA5853837EF5B43468FF634C19FAD 840C47C8863B04D8D005C1952F9696A65549517F64475890362A61BF74A4277A 608F6D0B8FB9C1D87EADD818BEA6A70F1C4261B6A8DCAEE6E957E7247E02B5A7 2CA635A0843BA74FBAF90467D765E5B57D59CDC1E91F8A23F3561A1EFAEE1F46 6611E2D8C6B90532448CAC999DCA3A3C683120C19A72CE20B3252DB7A7FCA96A 46CFB0290F1B4BDE03287B2DF36EC3CC08C54FFEC21496EDBF417BD00EBA4008 D676A09A1F6921140AED1B590D6D6E24831E66777533C4205471FFCF3DF8321F 99C6D15D43EA0A7A7BFC03EDF36D946D77C5FDAAA61545EB6C97D55323E9321E 3717C38EE10FA8DB8186F815748A01CC17BFD5A1D7FF2EA5D14F54C7E4B21D90 FC7A33C7628A8D277BFB3DFFB0509B67B4564285C39A5BBCFE6E0A22C940A098 321FE35A05FFB0065FA6C200834C9BB826B82E96C2662F837B3EFCC82366F19A 3B3D0F7DEF1738F9F205BA39DD740BA6859D434B879F94DC12BD1FB1B8DBF950 82A1DBF778DE6AF2FB54E66C1C87517718D85BA286F21CBB11730549FDBF76E8 444B8D569BCF2603AC7DF008D148596C9864F7765147B70036FD5DB148A27DBB D7782C44FBAE1D6AB2F2D0BAA51050013FABECD93F99BB8F46DA83DFBA67E59F B79ABCFA4EBF1E0D9C3F445A18ADEA7FC8C21F44CF9C98FC30D8C8984F78DBEB 9E0891A62B5B79FA8AB9B42C2D525CA8421C1A349F53698AF2D2CC38BC270A81 3348D274D2E1E3295F2951E0AA6E286B0D6223572EBFC554BDD5D4E011E82219 CDB158B90EE9B98557C52D65CB7C979B5FEDD91DB787659283937822A9390413 98B5A93CECB4F49926C0C55BE6CD4DFD33B33B53D6E509CEBCEE00BDC29E3AB1 9F8E54F4596E4BD576EF9F016ABDA8B04AE78C5A8CF0DEB9E2A5424D243AA8BC 7E20BAE5F24568AA76E9ADC471F88FF601B76900DF822DC302D21F60448ADCDC BCE3FBAC54A5F210BBFD2B71ABD320475C006ECF08F10913D6EE3C9B27503699 F6EC63F9A3B8E8B314B156190D56CB197EC512F0B51E712A40EC0FC591CFD232 313EE57DBF5C4D6FD184089AB27AF4577383B51691B01DA4179E0B2B931C4C76 127C91FF9377F9547F766196F0D717C7499808F8F6D3F659B81D4ADE29D9E81F 052699E68E0011EC15CD5B0A897DCB84F36DE8F89E9E4534B6E5A04E8FEAD402 D86C375CDDCA25FA61C28DF40DC77BC9997E6176FD29602D9FECC4D7127A58D8 D5D6673C64690BB5D845C77EFC52CF7939020AE46031D059F4B99C10FC59095E 64A7C2A3738C1D4B6BA29397A2A455B704EFC6EE695B91E28EBA61E30E4E3851 A2A841BEF92FA4DAD9129FEB1E6A45E023081C753CAB7E2F136AEA23FF48B724 6FC0D3AA9DB64A68353CF97AF0B67C6CC85DAD6241D9A2291F6E99C8550AE9AF D9A539FF822B85261A655F3F69B3F445978013EF842F91667F65F4834958E6CD 01B59C73A1B1E62AA5C0343338C04ED034362D1422D5E8A2889E4F44E744014C 037DEB2EF4AF5ACFDD23B48110A1D476B8D67C24D2EF5A29E5132225F362774D 70EFA69543E32AA9654D2B41FACBCC541C7CC632972B22482120793C4A857173 BB6DB8F3EC0BBF7A12206A2E343D586D2F9CFFF0B661727E747BDFF93E0A3717 8F8A19B5E320DCA5079647FD5A73EEC44828D731C5D7EA65B32468D254DD1C98 38D3D1D01E30FB8A34063C54776A89DDF3D94209356BA1888DCA4C203DBDCB20 EEAB3E550E578865C13D2259AF1C76C57D3F5A738CE86BE565477019B456BB65 F17FF4847CB1F4CD45B53ACA2FFFD618958FBD3DBDFA099CB118B88D3F22ACD1 57335768B12D4DEA18A4F46C2AC08D584C32766FAF22F2DE7EB7F1C06FE11DBF 1876C71D82624FFBC92EBAC9293FB8E58BAF58CFBF51659B63A3BBF4B5BAC52E 2DCB647973BDB96BFA3AA31E29740A777526AC010C792F660807DCBDCA738D51 AC5DE05E3C1E9B76515D440AE83592F4F5FF55D4FE7EF28C2C0E83AB0D4B9B12 E927200ED40E5558B5755E47A3E71A078829EB3DAFCAC8AB7AFB80D5C2A97649 52AE504D8C2AAD5BBA40772EF01F6CAB10F21B2857A1447ED5D77BFC61D7430E D9F12FAD70E7D4D3A44EF35D0AC7D965A02B9E772398ECFA6B5344BAEC3B2221 BE6D46645AB0C562FE71370B788FBB19C3F9E98E546E09CB94B745214D71C5A5 B4598B17655BEC54BA1174749AB5A0AE842CA1A468035256CCA9036390B684C9 67DF1C4005ECF5995D1C2BD6A0EB3AE72AE64D736C37F5E41FEB9FFCDD6592F8 6E4F511EE57436F082E33D326F5DD84A8BEBA270E9DC3945F8A1F7697A696EC0 CB117E7503B6B666A6A70AAC4B496A5D10011592765DB0E4F1E93A821ADB5F19 819D2EC560175E5776D5D2458D08184A92657F631D60A03BBC1B7A779B1B36D1 64B505036ADA9B264400B636B4C469C07E09CA7DE9B06E334A3F005D30EB1DC3 5F6C6B73D3CE68D3DD6C938693DF7876ADB39004425595356AD59C27DFEBB662 8C66BDB4939C6A4E092F8AB4054CEB2115C130F2135DD7CD2412C561663916F5 CBF55EC58935978F692C0C83A1EC7AA8BC8F74C2243FC12F5C1FDD3D4FEDC7FB 79A26A22EA5CE7340AC9487D50B7828A7FDCB4108936D3332E35F9724620757F EE3455ACEEE1CFCB8EE28EEBA6459691BA50FB364749011843A99580B108E035 95D2835839B484B710CD51C4B7DEBED63259ACE5C9E40E802482CCEC74A49726 F1734047A753B55504440363320663B28DD410A94868D76AC7BB386225ACC7A0 4BC94AF022D89F2C352BB952F4651137BF8447C3DF53D142DA67CBA5E65C3245 DEA6A306A17D0227EA4C57243272117FF27707FEB256443287AC9E31832946A3 4751432C58927C1886BB357FB7FFDDBCD7C6E6E7488742D51D4C83C094135FAF 0AED43363615ED8CB1D47EA4BD8859A9BEA65C00C3D70968CC33DF7640029208 C5E30EC517567ED45A5808257BA19FB5DD8DC7DAA27C6AB2D96CF4761C95E4FC 6E07308B1DF6A68A8A95DCF793B5B3594C244D787F33E1B0D9F52595426AA71E D8C1C7C82FA8E7505CD05DE7762A73BE71C2D0A7E85416248F0CE3D77AEF3338 1561F588063226FDCB2DD4C0BDEE89724B0124B75A4BC9544DE91BCEC26E0D50 AC028AEE9C18F152DF02C17986A189CF49971B2B9DF33F539632F1E02E50E40F 0BE617596F41AA53E2976D9573DB7CBB1BB434DAA9410933C123CF71D281DB0B EA20D1BC62CF47BE606B04497949C2D5BDE8B461D5EDD69FAF2976062027D461 6C66FA277FB7B382E2F528BA4FD764C8F0E81F96F18D80D42415FBEC9FCBD938 6B46FF86443D3D689570B6F5C16A4AC5B19ACA3B4824AD0838A2D3BDE2B40E2A C61F9C560C3B67BF6F721774869074F9AB101BBFB71CCBCC09C8358E97CC89AE 3CEC64CA66F26EC18E485D96042BE5944A6F6C4DAD2E6FD143905E20B5FEC320 3D27760E01B624EAF921DBBEDF043F350A6D8EC98462365E646BC16B8F862B44 4B1E75B3EEF455D51AC56B97FE0237F60A5FCD4198B1CCA4A1FD8CC3886CF5A5 B7C9463C4E30655E6D8A89FD20308719DD762F7B55505E15A68C168439394AFA B1F35363D1F9316C380BFDBA6C5580F9FCFA9616A3507D218DBE8F728F625192 1394721322428091DB6C0BB488FAE9EC71812E3D4C83B1F049FEA0767F7CE1F6 7BD6E7712C3D021636533D4D7213C2779E24AE89A93C3B4C8B976E6AE682B54F 61006AF20B56F48F8CFF4DC312E6A4547B26A8C0D0EEB13CAF4D3B950F5DB9A3 80F9690A3E8BA70CAE056B449039DF34E307476BF981A6713DFFE2E0E522B80E F997EC420D1CF30C5FD3ABBFA7C2F7B3C89E17990D349D3FAF73C7E205F95153 858D3DB1C6AE78C54900B9C443C90B24A271C3511F056EA63ED644EDDC42F80E 35A95B96B6A35744989127115CDBCC39D2DD217DF73CCE88217A9C5D0A053C3C F1453E0F5DBBF65D0B6DC5D1124381413A8B319EAA13F5AB22006F6253B97731 8FDF0353C651003A62F4B199E863A25CC4F3609E3A7C49A8C7D9620C71061CB2 30AB742B723C4281C5832251605DAE1E22689294A91EACF5F15D93E9572C5A7B 76978C52DE63A06B1B76E2A46E9560519D95E455BBE380C6CEAA964BB772C195 F4230319EB46A8BE1893D29D84D2E4A574AD60FC53F5F8DE3424503872110B77 DF58DDC1115E7325927B5AE38B57ED44E7620C664298853990A97AF75C11B251 509F685173FC15D9B3FA013FAD670AC9902CE85F95641DF0CB406E3956248EEE D7E5166ACE9CD34EFD938F389C285625CE21B7D649C71A402D2795734855AEDA 12F8E10AE861715A09FC6539F75FD0EE5CA08B1F0A6FC42EF75369253BAC1452 A29BEC183849D659A720867F5BE079879D5E8D8478D15C0B7A5D03AADC4083D1 96A21A9E13201181F2EED3C81AFF88B28161802D60A34E386B234AE3FDFD61B1 D92CD893C3F96DA6DA13E4B028D1FF54F801D547E129169B724F47F7BA28118A 637415C3ECB345779D73D6AE24C15111AEE81501596CB6B023CC2BD13C3D0BB9 2B993961A2B053A7E24E99D78E1CBB5F4C694C0A729156244EFBE8E11DF9929C 66143227C30056B3051A51175F3369E34D364A461B4677DEDD5ACB1D3DDA2A8F 8D7D0007C12145C0C66DBBB016AC3F35D6928095D9FCF430DA49018D7242857C AD79ED461E626764D3CF0CDDB33C43480812BA66B60262D458F26CD06C676338 B8CB10C15B45EDCAD3314BDC8EB9B070333E55D8C96BCCB4ECCB5A068AF3FEA4 D25D6697979B3999F9DF2A9489A8610F50D1DF3691E4C862D11113F25C6332EC A9AB8532079A8518AF272DBD1C7A2D5D06D2F6D46163FF42C750A1B62323162A 47BFE591859E2E259AB4141E6A3700951B08BA73BB567512A7A984763206E50D 8A8601F7B25A4E52E70E7E767F22AAD74C9872ED97BBD6E7815B8ADD9339D89E 9A119790F7DEC6D5815A16DD9CBD0D688F58D377D88165FD74BD92E74C8716C3 02D4D33E5DCD707C8D7C44589E29B3458D4F5172B59D1F9327774A8137314D8A FD0F4F5516C79F0AF8EBBCD3E0BE9A13E53AF511F836037551316BAE27EAFAC2 A516296E5DFF5C47C67DBC60D0B1203A7392AF6E3C03DCF0EEA729807606B019 DC84E4D50122AE40E8627E17E4CD01EC1938611DE4E8DF60326CC886EFAC1C84 4C7F23ACD1802F1619EEEAF2F3D94A9BCEED27633205D96C42B54F6788410076 E4FC37F92155A15C996427D25A249F91A6CCB96AB906BC16B1119FD6C7354703 5466D5E113A33E61CC74AB43FE9D870F210F61BB6E60E242A765DF18B23F2E3C 88DEB0DA0E9C192A3C77957675A7253A90FF18E2CB2482CCE1D936BF3CC8F058 1FABD43B428E21E4C8B06302EA20F430A650E4B823B270DD82495CD678ACFB3F 835602997133AFB5AF02B9AD33B4EE51274B5D3731B2FBC37B74B7A6C549BAAC D29DB5E84C9CD564F7B65A338211623CB5D6A54C7BF1731B7C6FB033FA6658A4 8F8F719083ACA6B02A382834FDEA45C7DC2DA715A3B508759F342EE5527352DC 732C6D47B1AD38B42C9C41FF13334AF5214182A3B5E8433106B57676326D84D4 4DBDB110D8002D1110A62B60A409970A5D2CCE07ED756761165007BA320FAED0 5EDE3D99BCC65F270068CA0F20EA003E53BA7DE3E999B7F80265C113EA933882 9733E4AA1736364442A5A5F5C817C86D9521A6875EC14A5670CDFD87744E6AD2 052FB6F4CAC6ACEA29F5DFA087F9F97158BCF9DB4147D399120CBF8826A4BA20 F79A0F15869A7BFD170633526DCD7523C91950F3A90466E1C04431E7F4891630 2C9CC8B0DDF9A3963D0B119DA76E54E0AA599BFF467F2048651156EC73C719AF 045F917F507111408290D70D3992EE604798F876153E916F0871892BDB3C51B2 AE6B9CF9DBDC96809CBD75BC52C0FEFA49896C72CF900B0A15BD3E0F60C68F5F CB7C3ED9B155BE9DC503E3B71E4544E180A245570B285EDD310CD042ADC6EA57 6C97B28803191E469301CF33A4AEB4161156B50473D85320A4631FFDE61E0983 E094B6C7E9F2ECB7E2EB31658281B221A9371ACDF9E4B4DA38C3632C4D454F1C 5DFDE797EC6C7526C93DD1B611ACDF1F4F204E96DC36A30ABA189BF3F9EAD472 4BD072A0AF4928809E08395F55DAC06E17E06FDEAD7E311FD3CAFE43BB21FCD0 395890A85FA271DBB2C0EE2BCC2E93C7E4C895EC5ACB2C2780EA8E0F9C7DA91D 08D0879833C64AEC6D4DFFFCC2EAC4EE8BFBF9036081088BDB9E8B7BC3E7CBFA B7E836D8D17CACB86040862AC38A0AB7770468A7325BED1AE9792F20D4D1502D FD0ADFC9B37E0DE21548426AF9C111FC0C2DAD386971381439A65767A0082C11 5EEC0069E5CFEE1B5CC95067C7B539CCBBBE9930B0BAB982DC71185851A45119 B232A0E25F322B2FF97151E2465E04F97586BB9F582BC61FE7218A62519C0E21 5FAE43869FE5008E8F10FB4C504457BD790D2A5BF0DC20CBC17EF1F8A482AFD3 504F256ED4402C226466DF495D50B509014D16136E339DB244533731BCCE85BB BC6EF4B26E280F14CB34DA01670A6C49A1E7CCA644C2CC1629AC87E2C41550F1 D6A845B0B4C9D2E28E799F8DFB9553C3EC0EE8DDC954C5720A63102F1406BCEC 10419A88934379EFEB39E9651881805B74F8B80FB86AAA59914E161D7DC8863F A2F08FE10648C67CB3564CD07D4E24A8F6A5B9CF47248F0270F055262E4196CD 73D6660CFED5F08C7D63641B06A9BF475E1F30EEE591C3F7D99447A17A1BE38F 884D74D30EB547D9CF1B07E9949D04652BAE17CAE3C1DBB218ADFF4955DA8233 5614B69B89C687CE7B154784CF34A111E05A18B1C195326F0DA114A593C07B35 9D8AE5BD82CE550FF964F024542C99E68F97252843A48EFDAE2C024346F97CF2 CC76D312BBB4676F8296BFBDE5DEFB60DF1A3696AB9324D485AC2FD43846703F FB7C17A60EB3A0097D01773889EB6FA67D511D5FFD960F0990CFA9E4D8DBB4E3 3881636881C27572DED04AB12EB9D9A16A72B0320D748B66AF32D44FC0328E9C 05BA1017384F859D899AB1A2320C1D64B7B76549268E0F44EC26861E3B99A59B C589DFE69B89DACC79998215B923ECCEED368981419C0A603583DC4347EB1BD7 09A147A1F12B6BB5E3B5005C4C1B36FF339DD7447BE0C2D6DE59B141EE5D2035 29C6C50CF54178EDA0A58A5211B0EC6A6E07EA3981AE389F6A93F8B891B82F3B 362AB6DB11E43E4033FA28496F7EE49492E6EF7A62CD1DC97AC106098DCC4540 415F2F3F9CF23CAE718B77F2B3543323CBAEE83412F05EF68BC9F9C3ADCD20E1 2FB93874BD380763E9BD03059859A833BDAFB215D1CF0762133053445DA3E18C A58E3AE0865BD24DBBD9FFB8B15F81F2E54743B6FD44C4F5E77E4395A6E56889 514E47B0A28375B3E2B423EAB01A9B42862EE440663D9485198614F38B84B29E D87D0DA9D6AFCE8DC4E5294452422B5E165ED5609C202267FCEE59C3450CF6B0 2C920AF68C39D020940D3F69F3A726A7D4DE59ECABE459D3F9F8CE176F7C4654 9863C451410396822362363B9ED20850DAAA4ACF76361FFA0EBFCDCEC6C27EB7 33DA06AF6BF462F9CBA2EAE0C4A02DBF755CF6236A6D6E2497D5680F38B253D0 8682438DF3A317D05C77ED198B68797B1E5DEEDC528FFFD3AA8E05E72D7268DC B7CC741C3F083C5F237AB7A9CE8A7B69AAEA065E8F3076431D3DA33DB07F897E 0C9451456876D8031552126631DACA4231D3774F78F06C2B39AF962C79DBF69F 195B9C4347E648AA764A35E2D20C093E6DB57FCC77BB8DA1A0BD4362AF74BD87 EEE0351E39A3A2451012CAF5DCBA4EA07258428FAC61 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMBX10 %!PS-AdobeFont-1.0: CMBX10 003.002 %%Title: CMBX10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMBX10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMBX10 known{/CMBX10 findfont dup/UniqueID known{dup /UniqueID get 5000768 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMBX10 def /FontBBox {-56 -250 1164 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMBX10.) readonly def /FullName (CMBX10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 12 /fi put dup 45 /hyphen put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 63 /question put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 76 /L put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 87 /W put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 120 /x put dup 121 /y put dup 122 /z put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2D43B233BABF23DF8DB B6C2BD2F04672F9A3B7FE430263E962F16A948319C51B8ADE6E8A80D3D88023A 6DEA4D271676C2C8615C4A0EA7DC8F6601610F398673A4D4B905F49EA868FEF6 39BE073001A36DEA6C08ED51452F062B971740019692E221F4455EDE46AF24B8 407A98B791F6AD525C72C09776247E194043281D04FE1CD1D8AD8DCEEC3045B4 F95B3B41CD3300768D8A049815348BD7AC1004F5500817E3A267D694AE108BAF 285B288FC5F28A03E9D34FE5D9B2F9A9BB26ADE66B1CF8EB5BE606E83D213C33 DE083C20D636EF780E761944FCE3B8A950B1E6E7568F33B557C6D59E0CEAF185 53E609A4F58AC4D5269116F958C4D115C44B5A6DABAB79D3BB6E60BDFCECE108 74CFBE258779F32C80CD7D9A7CEBA50A0966BD9961F71560119668C4A0C30A5D ED91ACB30940502B24F33906D6E0F16F81DA87EB6D7FC8B7853BE388C40D75C2 2CA8F94713AAA1561F5321CE97997CB4AF0E37F44E25B0F73CF4986422B1CD89 8F861CA623004ADB1C28268D7F8C484AA10C9519B6AEADC95AFAA3304D60E85D 718B2F67D2B734095E5A92C90785252C98067DC05137BE735220BBCB7C341D61 C4B98BFB1EAF883D38D7A93195A059EF82B42027F23B6CD633231D704B891A9B 03D11A646F13898F20321D7BC150C63FD6DC6BF9CAFD8DA759E95384B729A0B2 767B9F3E55C682F7A248BC1184F7D294CFFAE0B246DFCC8F215625DDD4F49F09 FA8D41CBF4A06152FEB152C61539ADF7E70A4D23AF8267D25CE3B12D39D62377 547E2528D18DC4134FA3BE0437EE0B3509223D71F06D44C6227D62BD01AC0A2A 3EDA975E894371C07CA1027B102549A7D552FFD25ED2DCC68E29E71BBAB43C62 57B0BFC6A953ABC2EF703F35D112F6B5460018CDCEAD17F149DBE5B52C2B9E10 9818EA6D97C8AC884F6841C9B600A7D868F59C1D80E98DE0741D06D69858EC84 1B33C6C9938B7E8A6FF6C12AD456EECBD3EBAF0D7331536B9F6422019FAFFFA4 822E79D6D89D6366DA636CB708894FEF904F366E295F1CB808E78E883913C4FB 1631248ED6A7CF1095C0C61C4F05E4B9DFC47533A5FD24540AD71A0E2907B98B 28085EB88ABFC3478C9644594C7DC4244ED5A7C1CA8D960B65497D56D174645A B88F12C2CF0A807DA314017984CF3C4FB7F47392A651EB9CFA961B28E2989893 9FC4D97171BD5338673F5D1CE2C3C08D48A1B77769F01D5058236C655FFD864B 80E28F900191D4EB349AA5E400A7B0A0FCA0F3E79D7A7C69775BF754329397B7 D18B20B2683CBC4A19729BA878B3C17EBA0A7E9EE297A5B67E915CAD92C8F356 582B8299DE6A58E73408F525F7EA895C48A8F0D626A06A96A50348DFBE479D89 4272576FBB0CD332193D28A8F11503BAE98F8E1D73CF5BCADF23DCD4E6586ABB 323568F5A34E359661074D50CD8D9DF27191FCE24F10225A5D721EFDE2547E1D CA998077D2340B1A4ADFFF570AA677CDF3305D5E3A394BB1626EB35074D4EEAC 2F037CA2EA389F7683FD17A8E07C12B4CB3BA8C249C9B12D297C618009F76717 0EBF5F2DD39A6BDA10A2E5A811D4E190660F5FDDBA29201B6F8042620397AB2C E59267A7247B0463891831A6F40582BC3F614E5167B646A8F53D8A31717DD9A1 9034034E705BA7884F0E0738307AF69D3517147C282747F2788462FDC4336A4F 9CD222908401A25F0A1F7B13B8DAE622DC965AD0BE62497420B70C04AF432237 E0FDD043456187658ED93B0F9822A3998511DF05E59CC85B7B9992CA0CE3B814 9723BAE70D2631F32B4BF93511F67179FFAD2075E1591CA5907A4C67701B56CF A5E5B02EB4A842BA1F18D6864E5677359C2FB4AF5BCBABAFB053F230CC129B45 8D15413F736EB07C571521C7DE2A13F2AC1C133D491B0A607197BE9AA1231D96 BED7968788246B2E4D2BD330F802810F5BDA3760FEA5210CFC6F54748FB1D921 5CC3624BBA5B8962AA7D94159651589540B17CF7A785F297264F9C1006D36928 6E2756D3B623A6087E4B106FBA76255903C624C07E18A1AF4E185A533C640711 86BB477A906ADD36EB6C8F4A12BC2F01B2B98412E4E105977640930CD998D990 0254A1E5E9843B7A8ADE0AF6D5871E6D3D666465AE69813A2E26333213FF6713 6F08D55A90C079A56E1B9AC655F720FC22B5AD8550FFF26DA7B0C5A0B60DDB05 64E8FAF684F3A455BA9BC9278043D79537D201D520E38750335A4C8FEA887377 879331B68DAD6B253F4FF9981D0F9B9550ED5179B15EEEB00E560A3DB6E5973B 63403E4E2F40A3D0B937246E9652000B917B1369741E0F913C14C2D2D6D1FCBE 2CEC4422177C58523715BD070002EC2E13D383A1DC8C84228862B6C5D3B65667 9FA97E175239BB7FE7E37E14B96DD7960A8AD49DF428CFC13B5D3CC22E245317 47B5244DA97F1DF954CED2D552477237CB23D037C0DE728E26C82738954EEA1F F34FE497DA005AF03746DD2ACF77F6E6F2C224862A1D18AF6F7A5DAF34564387 9E01DBFF49F8621C058C04C2B3F4F3033FF3E8A977B2CD6B2A3CA4A6C569B19F C5AC457AE9AF334DA66A730960C7565E93A2D373C0E3DE14646FFDA05DF4C6EB 6D4CA8ACCA3C3115764F77B842581760BFB9E5C0EBE55308B0577A8F4D968CE2 BA3361D79378D451DD150C34D7E901397AC63B33BD7DB13C50D678F5DE999238 4B4EA15BD449C46F262D931478F5685CDEEC4C4201FC3EFA607AFB8F27AF6751 125DE42D2FE2D31DE769B7E7FD8CC8C5D91343B537139A822A5BC4160BB5314E 37501F65B4FC35475FE9E03E34CBF6795AE86CE409500BD0799DE39FA69978B6 EC74D2197C03632D3F59B85F404DB31240968FA75059B2581B101E028CDECC2E 7E5E25DFA106E9B8ADB81E82BE9ED3BAA9D03EEB22B7B67AB1262DF6AF5F5EFD A5627EFEB84F3A5F92EF2557EDA2843D7D18C592635623CEAB14CC3620F33986 410D6DBAEF9F86E4E6682054540E2B01D8FF2161F10E66851A188BC15BD6666E 8D3F21709F196A31EE676D28A2D12639CC2E7020A52910F052E61A0710DF09B0 064171D05611451BD24FAD64716F141E1C41D3218A8115A3D73CA041D02B46D9 28C3D07DF0FB668E8E91409C8D0A26A65CD737C075E026AC0A974C9BE658199B 3B9D82ED95E4646977D8F60717DA4C68767DBD7E8320D5AA1D5DEB2E6B009759 8282F27D64F1F904830AAB501CDA4D9233FC2F12F77F0FBCC46E6B729C71F6D5 E6F3EA02EC35D1048394F4EF2177FC5EB726DE5EF2DE7997166B8BE5B5105D08 EAAC3481FC612665CA112D3F889A0E5B7843EFFCEFACA24A01B6AC2B7DDE02F4 A9295AA2409A3756BAAB44608DACBB56840060037869455BEBA46F10AFC68DD0 0563843DF111C6D34911CF13AA6023E5E899060B5EC60D0F78FDEF3E981151A9 24903EB13ED1A67EA1977449716D1A5A7EDE1A2E9465C9C2B20A58AF02D9F373 73E627CBF296B3A6A4670C39F3B5EA30D76F0362C81020A1777F0ADDBC6B52F7 213FEE1718214087837049CF2AF00407639657428B9E8B532F68B631611A3501 3D9DCA38090E227BD0D6D0FB4130EE866DB6B195C873AFD18DDB3B1E40F740C6 B3B375ADCBBF628A07A5FACED539FEDA3379D3B60216C2EA6629BE2F65199D82 FE3AE627D7C67270F3497AE75F7A9514968B5950E2D63C38DA240AF4E6CAE88E E25167D179108679876E7C80C85FE1D2BCC2EC9B88BE76A8F5736E8E6B3A9CF9 42E58A4ECB7914865E67C1468CF66D658206830B9380FE346DC2DC4BB56A92CE 4B5E4EA9036C177869315A2D9E6CFE97E3BFD7CBE0747D40CE5E8A3A0988576B 8AD2B1E4314C0D8A0CBCA08844A49F7E054D31BA7543730C0A7390BC4A288D10 CE29E389A4791305D3AC1BB6F77C805F1032787306F78FF76A20A9E629899F6D 13356768D33D7B9E294E8CD50CBFB9CA02A193922BD9B4372C912D1689B6644D 52CAA30F7421E8114D077288119AD9514EF21E5B9989CCE2ABA0C12549FDF493 FFB39736AC9EB72DAF45E4EA6057527FA9F5AA0A1A3F03C12F7482E465C766D3 760DA7714D56C91BDAED507A5572BEB51A895F8DD3BD5AAB042650154FC7E4E5 5EEA6194DF73AC5EE2CBD4EE26E29B1D2D0C458B4850BFE842DDF2EBB4E2A25D C6A11CA2D8F346E2B736DF88A3D57BC0380B52396A6C039212699F5D3342EB58 0C3DD5D01D5078479BD9FD10C07925556C0AB0F03606F33796BA72074549EDA6 E33644F62CA35207D7421D2727AD8419AD1772789D33405FCDDC9286BC34C974 A52297F5BBD2E541E8BB473F733AE5097BBC9D5FACF18DE4173B4711E28B23ED 16E0A6746A60F6FF903026A3900169EDA87D98396E762C2EC963D89197B8CD0C 25244806BE7CBF46BE60A8F9171731EADFC969C28679B025371E5572E52A0EF8 B3FD9B4638D03E20BFDEC9345E70B8166D38846DCA68E0D0B4B53629C7E7620B 45E0A610BCD07FEF8814CF915CFB11119F42407D1C6DC1E6353451D40A382C2E C74DF2A4889ED5A3495C3E973565F7178CA190D22C9693C10EB12C1E7A8679CE 4AFECFC964CC98111BA4ED2BA9B10292A71D5B11870EB08EB483922CE8628A06 05E7CF6DF93E112B60EF888AA8DB52994EC33DC7277D7B7A4F913AD30257261A D6EE80476A9A8D316D190BE6CE0046CBBCED365AB305495284FA921BE0638E00 63DB2AA4C5F163340BCCD1061B469504DEE350B82FBE1689C1B65D095405614B 35997D6F0DACA7190D64ABA351705B17B23FE2EE5996FCD607F49F54392463EC DD5B944A4B82FA2BE3E75E2946D483060DF99277340B0AB65A2042AD088E2B75 BBDAB869D1940F64B50D25078519D18748AD64AC5615EFAAF4F3105B0111AD40 70EE173ABE6A4ACE486B4E5999158A4377FDA6922FAA6E9305F48570D14BC81F BFF4C663E1EA9D1E050534F9315A663C4C5DA52CB02EA6408AA473C32CB0CD71 169BB43C0508A842F400240F0063243B4C459A1FCB3312C41C32ED0EE87F591A BCB6D5D3830AE4645CB4D40336DB4AB6540B52E70E1EA415CC6D886827EBC5B3 EC35CC5C136243B0C20B3C603B648B132B99D05F9B48263ACFA59A856BE74441 FECF5C6D1FE9D1F4F9942F460961901E16017144C37E83C6822177B2A6C47ECC 6C47A1104460665E5BCFCF08874008302750EB991CD98D0D8D22B921F90B99B9 05EE7C39F2BC2A7798157503743C9F2F267BDBE2E8A4CDA7317F81DBF8962E1C EC02822CC7F770FD4D08D335904375BF0C6DAA0510771627ECB9EE69C0F47D30 69A87052989DF80D9F4F19F75B070C3689AB3BE0966453F9D56CED6C1745B50D 813AE6D7E44B73423AB3778ABE4CD2C4DF40E14C5A426043F7057E2DFA2DAA70 EA6723F1C7967FECB1E7C1C0CA283334163FBE31C32254490170C3513580A552 19A5DD75E6C4ADCB12D33517A03318A6BBC7E4214266E125140D8C40F78A0340 1F95D9FBEC4DCC55B71E89375AA94B0D55646F6C069561480407D0A3AC127024 D7D1E9ED6B599A2A8766B8792F46D35508B66F302D289405B101A3C6BADA680D 8C56E2A00B766A4CB155446F862FCF17537A2BE85418E20CD77C4F1F69F70BC6 17BB5DA8FAA876D0E8BABE273A19C04A8697B3E3CF4725E2C77C8761A9243F24 96F8AE96399996001A57FD75106745AB4646FB9C6421F1D4EBF3BE533BD11AE8 14BFBD6D308376B26E08E4ADA490DDCCA94BE8240403D5EB0FE3549061DFB668 4105B4FE77189546619B6BCF3F9723E278E98D50A17DB8A4C46744FA21760635 5B332689316BD17C966D466AE737FE3ED7ABC443ADD88D4823A10BC9747ABDEE 027515AC353A420523F85298029475D8BFD83A2CD00C02CA07974BAA581D2215 A850E6E4C0A5E17E0EDF91C63FAC18C70093F40FEEAF0350B403E2806F4EAE96 BF616A805616EE55C4657418C26CAF54187A6684821B86A76F15088AC4D5B551 66C3CA8DC61E9810858D1204F899C7E3A1754F483134609F6EEE6364B1CC04FD 92C86EF194FA3249601AD722D75D1D395CD15A93C768EC60A486AE885683364F 93DA00A865C1035F913FDA69E7D9A0422880FB81EC23C00427F07A5EA3CCB613 83C859958AC53FAEA26A6BB39ABA068863CCE3D447720BC31A5136E08EE58963 093AF587A72112D55853A1048A2B1695DB2D7F13CC924F2F0902071260C33ED6 30893A04577C0ACF0681C0FEC23E5404F844A83BB5A2F8DE1F0792196139993C 1152094BC36A6AE5BAB4B8281E506F485F0BAEEBBE71E174B7CED1E52A8242F9 DBDF3E0FBA296538D964EB5B7A4E23B1BB0F59872C9D4FE8498203E3AC08B71E D2B965AA6CD5D20DA6C83FDC86F4A5D68A58A72C5BB9BFE9BC755C56B24025CE 6F24443D3CF32CD711D3D94C7C1DC275DDAE3341D840090F97CB6CAEF274C94F 9F3BD3AAB3F98BA8A7B5CE5E48D1462DAAB37BEB1C10B410E8D33FA42D898183 BD4F807112D78AA94509E33C179BF7C9E82E55AA7D09E128A0DA06A330CF4AF8 5DC861498CE029CE8C1BD15C923A708F2E7AF98E4F7B34212A0CB417553C86EB 6DD46B0466F1A21D29FC5111226794ECFCA5DD4240C0B8D106CCD7EA6F03E133 BB7733F055D6FFA04EF5C6F872B4FDA3E42F0F036C4825543D75682ACF71B548 DED160ACD05625274799D0AE201305DA526E01A3D2A719B1B15C05CC09467F3A 5627860C0F36C503EE392E1786620F3F2287AFE56634E03566B9B1F537FD92A2 913166228791871A8F8CBA1A1DA634E8224058052A10FE1E67CBD3FD21A6C07E 243CBF58BDC78577847664EEA5225EB8D6679AB17C563848A9D4D58995EA3609 51C1443B752A070D9872FE1643F0677019235AC25DC2B29169D38308F2170A1A A0FDCC59E6602197D2815B914041FFC7106DAAAF30CD97400C6D0826A40385A4 C8520119A065CF32CF2FC5FBD8DFD29222528A7F96FDA533145846B3428F8239 E50277C366418D713F84B12A5FD4F904DC13DB1844A391FDAEB97643A6FD2945 942FD4FC5A4A35E184F23304B8B4D93D0C37EFCC4E106D4FCD0DA3E5D2117589 3FFC2BD1D121026562C55C455C3585050B9460891B006F62D9D9B66695C3D348 A467C14C0256FA9621CB056E7CD389505194FF463BCC4010897F9A690EA87D9D BB3ED4C174FBADB8A4744C6E4A44D773967FD703EC37672F9993DC48BCC8A060 6CEFE8E6B8F10886E15BA0466AF410B90DF0020FAB88BE493606B6A734EA85BB 926950EB10D2F2CFDBD182B0F133809612CCF6ACCAD049C8005A42FAF78368B9 E7684F98DE421BE0A3BC0FAEE024A7BE67E15C8394F17FE84DFD8156C2A3E94D 08259E15CC657E8CE3088395BF6B5F825764E141AE15EBD186DC049261623D26 8636705E06C6E4A1F8ACAEA59F91B042DF5DB9C2AB986A784384706A43E5F18E 42C29CC1CA86D4F247B3BBBC89F3633EE074DCA4AC15B1E33EE4822812A62E88 C32B0AA57249980EE17AFC1346074800FA529445D18649A0475246A25CF325A0 BDA06AAF392FD455218B13D9ED577D51A9500B9FB7860716A8E2FB3A8C4BE3B3 6656C6A5653AEF00184020ACA0BCCBF48BE3BF91E11C8658686C89848E714E6D DC158DCD1C1BC03B83FF94C60B1DC71CE8A86B46DBE661C9F8F4677F8A2C7CF1 E41A91EBDA2304735147BE66CDFF2673F09D408297302124C127F0B35690CAE9 CE1679120CC4D582FB69550AD34A047DDFCD9D411724554CCED753DB52D6AA7B 22B0C55EB698ADDBB0F8ED15C971AEF113C74B9E25DA29199237B98DA4023665 C2A63A837E4CAB38F8DF37DBAB5DC80C0AB25B56BCA5D899F1575E61ADF75676 F48EE26C054AD9A75FD88A3E17498AC26FD4DC8000A125D6DD423540B8A98779 B28CE97C9CAFAC45693FF43249E4B559E7F19FB349F94B60AAAAF05B5FBF244E 982B4B51D997DA5811CD43E1917DA885DD96133A5CE1A290DBBFD88AF285A879 D3136C41C839FD2276760A7B4F21F4026AADCDAB3F113FCCCA9588C7FB72643E AB8F6D8AEAD1DC3DCA6E436B3DF24E7DC6AD37137B49327871EA80F3B8AEE932 D20D9A5B4779DFFAD7B3E5D447023D6433575F8F5AF589D7E094DA3786555D0C 046A427ADF128E00AC7B458D5A131A130D6F49A7ABF47833791F172D69FE6393 EAE0E90E7FF7BC2333D4E0215D5201E4B209591782F8A664335F67B9DDE36DBA 793EC77E5EB405862D14EAB6A99218B3F66F11EA2F345629C402BD8FD9CA0AC8 FB5A2E119DAA9F80083C9BC54F4586C44320993CB5D9CBDC8F8522001F82A16C E307F175B794F4426E5D273581A6D2844444D82093FB03482B270D693391DEA7 CB26D4A418E48A2989167B7DCE251F0D53D5C9B29D359A568FEDB965DF31CBF3 900392FE739A2B43BFA2363CA74FA72668FC761D1A17B9C0B56D6172499CDDCC 90EA538A5526FD5AFF81D04BFEA703E5DA963B11042723106704021C1B90557C B7AA96E076842E2C5F929FDA6D05E0B91B5548006EB4A6EB262077411083C2EE D51D0D237A85D6480DA41A9D8DC24EAEC0C849E0D53D9FE1E54ECD82C957B8B9 ED68D7B29A43F369C28272083B7B4E700546D293DEDAC7E74EEC946B4412B0B2 0639AB78E79402C787F50C4F78991DBC12D73F5B371BBA2CD9535EEF0550084F 40A4B2C4D178C0C001E63E08DAF15D064426F6F24C49E02AF5417D18BB7997D1 46CD6476615EE2F496EF2D2E5A6DE68ACABAEC2033F9F3689D9F8CA23483C81F 8E9CC42B7AF2BC3FA80B68FD37E3B87FC27AEB7AF6D2DFF9B4B7A60D26292AB2 36461A349D3BEFAAB8918729204873D7793A647387156252B5A1B975639E02C8 9715F8B4853B592ED9E467BA41B32363ED0D7557EA0AFB8EB093B4CB1FB3CCD9 3369A67A60448575C7CE305DE7C1B59DC21DB0132F2B67B7B31EA068C5942DBD 7D1BE9CBA33107AA60AD033EA5B3618B83BEBA01BC0DB592BCB0796AF520E8EF BAE6CBAA5DAB5897040D6CB1E3EEE78A98B59897138A084E64E116446EDAB213 46AF2FED3E303F05D7EE630434645AD21B410AF8C1808A79F96CFC56741F62B4 431AD2FD90CCF0A876EDDE18506E73B4E390C752DB45A2E8BB824F2E0310C59E 864A74877AB522D1B477F5A3D7ABF80CC031C2F2BE5D633E49E6D10EB6EB8434 F17B15274840BEB842587F3B9AED05B97DD603AAF94D5FA688675B55D40FA43C 6D97741D9FE5F54C7D441AA62D48801769531ED7EFB3C438EFB1B513E930FA50 51B3D743AFEFD98A368F8A67BED1F89DB11BDBF10BD7C453B4711475E3D8B36D 38F6013E88D476907A47591803200911E2C91D05BFFFB6078443809546E9967F 2C28133CBECA6A46C69EB060253966788EB6B03FF7440121976BD13CF41A65E3 37735CA90366719B4BA72DA3AA9ABE687E00081AD5F370ACB8EC00E9A2608E78 5391C67AC9C3B91DF9A4D4CBA46CEAF0A879549CA69DF46E64E255F1FFD5F183 D3F0D57CC92CE4B9717BF0D529670457E00E1DB0091E05B3DCDCADB1E695F8A9 643B73234CD7CCFC906FF77FE1AEB7996F9BB0941764AC80BEAD3AB69689DD71 829FC2DA9FFD25C55A4F377ED8E0339C3CE89784152C25462CCF12E525B25FF4 3162BA21E584BE4744B3AB0D1D8702B3E070D395A24786EA7C0E671514A0C34C 04242B86A8ABBD44EE1CDF1EEE5E014744D5DCA956F1D0FD53A6826B19AB6FE2 B6725D8EDA0FA3EDEC3C9FC0BFBA6374EA60EDDDB9BC7FCFCA76A1653CAA740C 848CE2BD10913B1C0D56C31229D9BA0A6773C8686D59B5734B563FEB90C2AD89 B41A4482CA1EEBAA5C23F65B4433252909EE79FE294598331AFEF847A863E137 6EF97AFBB87EDD3875AF98FB1FE6F8D8C840D4896A183FF4E395EB7A69DCE16A F779DB5DECEB45541CB32FF7D147CB85CD34424CE13529BC008B07C5D4E3FB13 343F286E50D0E1C5C6294304F6DE699987694C2C554C31B5DC282F94973EE4F7 F6CB979D1F833A7D988627BF757E7EB41FF5421720E7677FAF7F5B3F108C3259 AD24C4E3568F66F15D2B2A9D73007D02FB25DA53070C2BBB4491BF12A6070CF4 16CA6A8A1CF3C9C525A99A138FF64C26509E5A8414F1DE38B6197DD8D11FB10D C168A78AD39F674929B5CA52529A0943657E521EF464B036392F4234435AC61C F55E02385AA48B228CF68EE003ABE571ACD364C5FB0D8C228BC7A3F25D01AAF6 F48FBFCBFA62794496BF3E3E81985D350AAA08318765F176B08490CE3A67142C 45F58D9EA0360C0964B7B212364259B91096A56BD0E793F02264142AD1CAF3E8 D35822D785C9CFBE1CE2D9EFB82C89095AF08B79F006105EB6DE44259EE9BF70 5C6E0EE6A07FA6EDB2501056EBEB0D9B5DAB1C8D20598F579B415541567E42DE 42EE97B97F664C4E305372C98E9401739B3454D2C121F96631EE73EAF3BE24F4 799D0520DB3E0D66477F3309BAF7334BE4825A689E15BA0AC471F50DA2B86551 0896B0133C1D0C2CA2204D441DE5C130420E468CA64092D1D03ACD2FADCF17B3 6116420CFAAE8DE28CFED91459D645C92FFDC3103333656C79DD1C174C26DD97 D462B4323F33B410DF5688199749C1033BF3AF5145DB173893CB13E06F29ED38 79FE573B8D71F623B9DDBDC3D963E6BD1216310F9E985BB49A95FBA4CE012773 9A7DA46B0786D3EB2CC51897FDFB7F0584A27B8858AEFBFD489E95ED63577DBD D11ACF5AADB51C830DB3013C710E64F79C9A3BF0D8FD11C624D47D855A697253 68619710B6D441D479677B8D2445E89188D4C6E30E071838B968315F4DAE4B93 182EFEB487A03399B7388FF1D7990C7022449B767A53B1F7A6E323FA469B9A79 CB3DB10C2CBEFC6EE7C3910BFC8A7F035020F22A24E5028F75BA9907504610E3 FCA106B6354EEEB39DF382A91608E6E18CB5B301C30552196E990462063969F6 EB3AD5A1FE45117A0C41ACBC43774A41103397A70D335D41F59317F44A60ED73 DAB72A2F1AC1DA27112B3B5BD9EE970A2FA1D95393902793AD1EE7449EF39334 3EA3CA06165FA1B97A103553E65A2E7BC2E0E314F947ABE6115070223439752D 6F68BF8C58D876D19E4EBCB30E13B1118FD1A2852505D49C1DD2E8EFDDDBA23B B2E122DA14EF90423285C4B2AEE0E0AC90BB3BF0C993A463C85C7B84E28B6530 76CA53A959BF6B5D832E47A32043643ACE7D7A6C034DF78B7705482F835A9B13 5A2ADBF33C3567BC7577376DE977EF041E8C7CBA75E31E934AFC237FADC20659 B5FFC23D6678819B0ECFFF5D5FFD4B7E393D0C0087260DB997935F0EBF3B02AC CC687DB7121310F0585CF385FF18BCF6690415AE872823D8DDFFCCCF5CAFD705 3A236404661DE55E772F5982E78CCADCFD0F1E7ED98F0DBA07B832A01384E9C4 BE1C89F8850E8E42ACD39AD383AD1C88F8A6095792FBC22E3475CC5F0868FC16 70AA36319BFB524C43653393F079F9C6D50E67276A6561CD437E2F807EA88EC3 A71BF767AF2CFFAAA7F2F7C36C8D1379D5E50809FC7E1269F6B0B975FC09D8AC EBE423B40140F7AB6FBC84982A912BCBF17E8709D2BA620993527700DC510B03 8A6AF5A1302E74E310656B8E39C664C378B22F5BEB0A7534B520BABBEDCEF166 2E2BA4F9908402DEF9AACE7BD76B3D4A244E3AC74FC0995E07B3C24E75C142A9 70F63BC1014A091DC95B235292FAC3C7A7D26021EC57FEAD507DCD205D996587 9F665CBFA93110676AD2AE5F9560C3190AC388C4D02E161B1383535A4F10EEED 8D94717B2F1204BBE95F919C0E1C145C9C4FA2E5F45647C73DEC207C3655C2C3 3ADFCD25AC12FC399B1BFA5399079A9895F9AA99EB00BBB0003D657CE719DA50 9D4F43BA1C8DDC44D84808BDBFA2B4520DD610CF4700F270FDEC99E3F728AD18 9C3704E7851BBF2779EA23D1556D2FA4B3EBFE54E9035030C051DC42FA7A2D4C D25B3031951431451DCC308C9F52C0FE67A430243F3A7669077A7C13047806EB D5E004ADF8877F37D4ECF3850ED78ED3D353CACADD313809CC2E963564A4C96A 8D2D967CBE4C2C1DA1D57C1262F9410698CE0EE13AB2EEE3C205CDEDA3E9FD1C 51ACA46DF2689707673F182D18B1B64AA641DC0B5D2E3C75F92B69DE2040CE0B E8D521A8EF2262E75AEB00318E3CC133EC8E06BFE8F5DC0B0DE4B5C07421CC4B AB585DB6B9C6006EBFB534E0BBB1EA690958489F447EBAA15D352756AD4F3F12 7998C476A97E0C02C44EA6960180EBEA8179AC127E389F8DFF90FFC1D382DAA9 11944A9EE8EEF929D59E67DA7CDAF60B5D4A4856E5013E0E1B9DA36CD2BC5805 EC4AAF141098AFE7A0ABFE13DA4A82127783186D035BF6AC2000A76CB9C2A81A D2DE6EB557A01E0D601F75E703B667C902386E8B52F673E637498B81C5850DE4 61EE162F63ACF4D0F6FF6D1BE8D75BD6F6B45E4D6B80AFD640A1FCB8F3569E43 505B1E2DDE5F3CD14DC9D79DA9A100E4BBFB032295F3D3D7D3D8FE7A74E85A68 B86AC38C1AE0BA99ED69509B0EC0C05DC92512D643D1E85DE755715CDB6188F9 71C4C231BB06D27A9824AD801B32E39A9DAD3D172CA9B298F1565BC05D894C24 77BE970C01496D0BB219D33A6EE47A2F0F17BE3D38C692A045D056DC7B0FE7E3 6DB650AB1B57A11227D1CB0F6BB39C6A42D6E1BFB364BB785632E7A32304E63A 9133DDD269E32DEA34E7F51899D0AFC478CB2E68466534F1CE6962A876219703 ED2FC5FA93395983F49A51773ED86EF88E92D8DFF989F1B889A6A4DA40CAAB08 4BD0B7F9204799606A54CFEBBB3337E9A8BD0F36F3AABBF60BC63BA27051EBB6 39005B0F32859A0329917E9C2115A4804AE3AFBF5A987A55C50502ABB7D40273 53DDFC7974CD3DF740A26BF4800C89786CD4C34A1735705301D15B620465DF3E 58C716D47F993149890751D449837C65824D0F5BEAF06105BC8F417457C1303E FE1D09B84149C161DE84DB241A0BE45798F3E4DFC138A7B517CCA9A654C48DF9 A6F3318D494E7C3862A8FAC46B3E3019A934464B108D04698782A19F72723107 06E6E4A362137F7ACD4503591A289C81ADF72732259B9A5808445A51332135B3 770D95945B561CF506D3C1ACF988ED2D57F99296041BB5E7EAB0DE706016B9A4 2588C88A0A872D3A23C2C7A7603A6B64AF9C9EB1DC8E975599EA1D24D9D74661 EC6F0E964937A736090B2720E7A8D0EFCF0E137B00FCEE27D9A785564A147922 8E89EEF3B7837A8F3B92006A798174E123B0BAAC7CFFB85667DE113AE99BF4E7 A8D3A053C5AF0FE4EE028F235576AF2B5839F48B5EA2E52E73E3C132C014B8BD C57ADEDB1EEB9D559E94145BB5D8C3C7991A3714DC3936819D3DE182DFCB51E3 9DF3DDC87E92E231B19349ACE65C3F92FA72A7B04A93B0ED306655770B72598C 02BAAD8E46C1EAA4C626EE4B79D8506CC911A6778B4E55D3775F1C528F86344E 732342B47E40DDA29D8AB7BFED5414CA5BE9EBB5B9C842B119D28969E5E93356 316A956653DC5DB230AD54DAC40C37B485E2134157179F42D042EA817808B720 A993A29EEE99FA05BF1F0AC366DFD68D1E5A73F883A8396C83B170310968A070 29EE691A16AAC8A766DE4D5422B7A31C76D078DFF769BBC6250E1CDE381F099C C15182FB08FB3F8D264466E05487ED12C4A03350893658681D7C3DC7A212FFF9 0C97B99B80C0C6D4B802525D45FA4F17A2A22967DDFD65BE3B7FE8AA99B47DC9 BDF9CDD6B195AB80805AE6845545DF7E1AD9422A1FDD4E1D83AC18B958E96314 6F212B6BDE0FC431C1E3CC432C88B95A411EF2D6E977AC24571D4D822EFC4FC0 3EFB0B272B6EFE4D0D48A9974BC93EAB0FABCBA97662B2D81A19A302235DE926 125A155461F09CA091145E1EC1DBC3F6793EBAF0507142FD3A647607B87D1AAD 082C03B124C018EDE123CB00C06C49FCF7730C99E1A3B78AD688CAE629620F41 3EA301711EADC4DFCB64F69006880845D221B914CF67BE88E06113C00D50E2AC CE37C887E26DC09BEC5FAB2671FD2050D4CABE61347D53A502C93ED92B489E9B B88A3C283C02A4655C572B06777CBE3A6509816D8F3CF05FA53FCBDC105A7642 E241E1C6E878CC719AEC4170A9E5A7BC6BD273B5675C5C8733D01F547AEAA9EE 879EFDFF98E5CBEBE33830F00626EDB945E6C350FCBDCB7588A2CF3CD1FB88AB DC67F7CBB76DB822768E21DE82C449F557B828A7BA3BE562D47E52151DF93042 6DF5BA30A9A5F7694170CB3288F30695356FBE6E78F140C7ABA068493635BE2E 9949EDF0284D9893633AA0FFF1124DEA4D6CBCA23AFF86A150AF7B6864C688EE 070982CF1A045C59C6C8EDD0074E53693FE44C2E3C1B4C6161FC975E77CAD117 2E1DC8307E5F34B5BB48C53B2832FEC5055EA232483F1BB8B41C56DADAF843D3 C5D4DAA4B0A473FC638441D06D50359CC11EC7D8213D627AB6AC0998026FEA42 61BF67BC22ABCA793402936212E580CE20AE3BD64AEF38C53D80D3A5C18BA612 6B467EB103BB7812C0D50F2E8AB1FC243C11224B31BB9C15528CAE8D1161F714 CC4326EE2C6C52B43BCF8373403E13635A1A2D15CEFA3D321F14DDF82016C296 850FF165ECEE7C7D34B5A3C2420F6AB3885EBACC2425617A4F62DBDBC2256813 8128028DA65C1226E4FA6960A29782148E56977896CE840834B4DE4466BF66F2 8BFC3E675AF4ECFD98091F925A6A7388FE7632E81ECEDAB09C2D52BE51C90B14 07BD70A44B0B322E40206BC00D3EE62FA32E00E9BE8AEF6AD053FDBED12E1601 A40DCF631B20A87BF2456FD8A662BFCDAA343B63A1626243AC146E7F30BDADC7 82571EF3897C86BA1856B3D61C61EDD544F5DF50E1FFD9280B1BB662D6521F66 4A25FA8E0EC8066FACB7487CEDCDC63C9B55E5F34092F44AE2386825EAD79839 5E3D1EBEB0DE988F909497C90508A225D6C6DEB0FAA8021CDD89CC9F4975F526 3CD610FE5447459BC4EA260FC6E59FA463B5D955A86442DC364AD7F7755ECE28 27DE7D890CB2B6D5803E1DE3793C732A497DE317B7D822BAB058B2DC8792A53D 14396E642619580BA0511256B7BA086E4D582DEEFA85013940B6030B05A8464D 4F3B9E0141661F1437B04C7EF3E4DE7B10D3B8A23628D6C44623E9514BD374C9 3FD5BF4451D4A5E2DB5A9C3C8E3B8E61A60F0CD695BA5D6E538B4F5CB6DA9FA3 3FA576BDF9204FB9223A49DBADA1F9548EFA3DC364520236B6CB4B571A7D075F A324DF77E1BAC3F9BA48BE5061C2DC90D0608A601DC234F2E148271124F5A16C E80155C891997AD0F18E6F75521502C040B7DB765F2D8559F1D3EF1A19565491 CEB28D067B5BCFD7DB631DFE03CB267A066F4924BA43417ED7CD5C9D5F002D7F 186EDD5C15FE2DDBF88697D6EDBED661C8507DB862737EA571B22E3C669DD417 26324EC6117823AA81A38EAA2A0587033A38F4A8DC7DBB0DBEFDC32E7AABFDC1 895DBAE3522D0E5C46EAB9B3DAE973F55508F5CCCB3452FB091CD2B5381C32BE FB8728979F8F884A0DD4329F8D77FAC666D0B8B698E3D80F6A9CEEDE7F1579DD E080743DD0C61EA2B9001CB2F3196A5A2103465EB911C6D4E691AA899C279952 3B8072EEDA3D4ADDE09BBC09C7D9C800829DB095A040F1AB1F54628DEB0FE14D 5510DE3D56E9054A9BC178C19B093377169EBA708CBEE34274060FEFB8B1AF2F 206451CAD4D9DC64966F5D97D4E545B000FED5157C4A6DAC5BFF0A733E0DFADF F3E131B62B29260BED1E18950210C5F698D56DC9C269D90D21B6267448C7C342 1F70172652FA4B661282F731D0986505D02EAF68DF8D96CF2CD30954EA9B4FD7 C49DF7C29C0B2FADBA3A19EAEF48F05084D2C9E653084C0FAB5D3159F97EC87A 668D0921DB864084A17F407FBC2E07435E1F2BB1EC837D289161FED3C9D24867 5356F09CD591E2D5E783AE67AA661114514DEF9D27BBCE8E94B840A51819550F 15D24ED33CBE809EB9F6920FE3DF926F304A7C84194232B97C44F4B4D6E6F79A 3255BF6A8B2A3CDB1CE1CB2D35B032317936F0581C68A514EF60E7E8407BBF98 4E946697CCFD6869D209FAE41FB35095253B149B84D6EBACDE7AC83724F5BF0B D9618D18F4978728B8FEC34903C236CD1563373D342A136BB42031D229279805 BB970423C5A50053F2A3A1A90AB59D401CB18F33BC9A522854FF786421E2161A 4B7E816B636136A19275772D913A348715E88B2AC979ED52B5D2A71C9CC842B1 EB4F19E3F65520693331F28F8C52B25F4E5B9728B4F18620B91D60C090C3BD1F 0F1BCA19028B01C2B74368594F604F07F32647C806958EFC69D5613A90DD13C6 2277894AED341D2FCD2408D92F7168462AA1FFDCA5092869D82C169DA78BC51A 3FE6749142A493EAB7515869AD83CB1284B5946312F7B8FB95CD03C41BD96B19 32B350FF96A532EA57C6496A9E7DC0FF32A77118D0F763D2C520EBAE65F0D30D 6A06AAF63D24483A60F924441B74ED4E115BA1FED174EA6D76F732F029E5B023 35D0F3D8494F89F73CA258CD3C69B87892AB774030B43ED877A2378EBC5D86AB AA9897C43F1AD3BCB208931FCC200FB8CBC0144FA905801895A32AD1148633E5 CAD90F7A5A3CD2B7C26D8C2894A65BE6EEBEAAB29C4287A91EFDDC141D5CFA74 85C2EE30B519B18176B302075F709FDC0E3628EB488E7F3556F6CEB8987D60D2 6D26AFBA656AE055054390E31049E54926A46C4E725C1813F8419547DF2F0290 BA684526A1413C834F5EADF7207C00F17DE7D4A5E9FE4B333C9FEED30D27394E F986C26A8134F087A30C517FFFBB5056C7E09288179CC323338B9E5D51B4CE40 084929BD0B319567C95013398F888C742A9117937C37A611831807E8B79FACF6 BB7437C907B9A1746718100BBDFE54F03D0DDACA812FDD655BE99D56568FD3C9 65ECC800BAB60A5E12F73265D9A5976E4F821067927EC46753DDD204DAE95D94 C28DA40D3FA922E165B199C1E62B4BC76D7B5D8EB08249D432578C36DE95715F 1FCF15C00846B18609779B397E7229E3BF2C53313597E089498BFAC7DE2DB922 9A2D0F4A057A571FF0CF9BA00C9EDF11607DDECC928A70343D823CD1AF3642C8 4432C2DBEA606BC21492CAC2F64D6B0613A14DE29AADF0AC9FF2D50838C43ACF 6ED3E66565FF76A92FCCCBE1DBD092D0456673025C133B024D9DA7BF108CFE93 44D7D30BB783A8B401030A1CFC146DBB271A3621FD679901D80E10DE4E918A82 E1F5054D3A6FDE3390F0928181597B551A0E88B7A555E6C6D348A58467F0195D A6592C53382310A1CC4DF1DC28886E566B637F165321E68B336D07712659ADDD E770F2BEDF71E714D91E61A53400DCDFFD600142AE2D30131AFE4CBD124E0BE9 39D59C7DEB0AC715D19231C9E8E339CF7052CBF4DCA0E55B87CE7F339DC4C7B5 E61744866A3BF7B23ECC97BCB2F103090DBD716F3CC00B5173878EB857CCCEE3 A82B9E44785D77B6BB0500929A29FC28C508671B1FEE39E8CA257712BE982C12 3931D9586F5CB3C6C0054B3386792768E220BD82629317D8E029F249645A77AD 0A19B154FFC4EE687059F77AA1E082300DFAD4CB633EAE2E84471570F496A3E1 B774E4A94B1463D8E39C04461E53582AC7097A5C3CEE507E91DDD6E235670844 8AED01C7B85E531D713777310C8C2EFF2BD948B3CD75E4A1D59D9EB46E2F9686 4F54645A052DB6E6EAE5429A3C26C45E6781CB518FFCB38F1AC2C22988C40701 4987A684C9CE8A3A3BDF22ECFFFF303480DA68BE3CCDA267331D914998F3DBED 2C40D6B3464CA0473AF611E05B8E3E1A83B311BE68E8CC89EBA849EE9BD830CF 40C3D3F086947245D5A2624B4287442CF4556996ED6A5AEF8E3B9819F9C14578 0EB7C1041A9161A1EF61ABFA81E8EB094FB9DFB8119954F31893213A1665DE12 954FFA96E565F524D531EF73B9B85EB0346ECA74787471DF4371A366661647DE 1DBCD7314D28072A43662E76E752F59CE9E0626E7E2CD577C56622B5170A9B6A 1F0AA075DBA0707B291BEBB9F12D88E7CEFA3B3189D7B141EB968CB03F9BFFDF 55B80A0268DAC7F38D75BCFE4AE9BCE32988428C490FE97A5A3AC7878A34118C 36733E3750EA1A0CA65A072F6BC0F8F080CC13B632F2E4CDDF21534258D74CA1 7C3DEDA5BEFAD5F4A848B745A0C8991B080264C3B8A97E457B49E3BE89E88F58 B76AACC3805B37D9B55294CFFEA68D62CD533D54FD4D5D2122AF19FBA5002307 456F6BE9BD9A05E15F1CB2ADF6B6D8282DF80C86251405B11A0ABA45E9AAF0D6 250D108104EBD83C29A7B8A2E8D3B405BCC1023B8FEBE7AFA64BF86948487614 75B89CF0B6BBBDA0D89251625B6883E0BDC7587D53627825D9D5F877AFF6E47F A475481FBBAEBDE6958BFCD2AF4C339DB8FAD6093B1C0B93949BB626DADF28E7 BE73B1187A4282DDC9C76AB4D2C1013F2ABDF0347B2ED863DAE6E0C16974A049 20B420366E23153A5DE9C59C58520C5D803BE95D640A957EF380E695CF308FEA BD6947A97DE2F6C80FD05985B455FE61C1E9C9F4A9FDBD377CB4CC93ECDE303D 832E38A9E2E8B2A96D4BDF3DEAA9ECDA4B17E99B684238258AB15D75AD724D14 A210BCAF06FC36EE3025F547DF566E547F414DBEC4AD342B70A58CE1DA417A2E E7C57492A6C419A68A1525F0F25FA14CF30F03E6019C90889B29A772CAD4B48D FB993FB6F1D1E043538D78BFBFCA5C7E828BE667417F207E8958D4C74A0E3617 AEBDA1820A6F6AA728ABBF2951605170C2C181EF7E9D6AD01FBE5AB82F0E885E 73AA7581D3C8AE764E03AE8E707F1C079413618183A46F61A2B9249308A6DF46 C48AACF726B82994CB298F11FD66D4235274328E2420185EC100F42A65E12165 A060FDF7BBED4EB3301F900F1CA1EAD79BAEEAEEDA6BE53AA695828BAF3791F1 4BE17F43F124B5DB0F2631DF408F317B6384E9ABDE4BBA689BDC532FFD68D672 775F7D59D8AD4A809F940019B38836624C4F0E4B2236F068AC48BDDFA5188579 5B6D28B8DD9AC9A71E80D140055782012159CCBD1E6C21D33C90B60DC37BCDCF D2DD9CBDEE36E1F877A4B96462E2A31138924FA625E0F1307538321AA90F26E0 BDDFAFA4CBA411AF3902AD078F7A17D436BF9B875E53DB9D92CEEA9535189E68 3C7DF98998368C586FA1CF7EA74B43E7182458B1CBD74E8F4147B205ED7AEAF5 68662947F89F6CAB53D142629E31CC4AE2E80921FC276C540BA457FCD9F0B03F D1BF3836AECAB05D56F240E0104AE35943F8371E671AA572D20FDDE7900CF5CD 3563F6178660E0C0E9DFD3611C9774F8A27E979655EE6E908ABE0610B534FACD 2BAC549B6AFBD267D7A65C52482D6E9791038BB23408277F6E552C04CA075B92 F90DD38F6A9F9DACCFF5F6C1D20C79BCD1E65D9C06F2FBB4A7D7ED0015F43C3D F8D9EFCF060B4E4F36AC7A6674E27430998BBDD0D9128C43D6B338A2A7CAF47F 9DF2A49780E4B23DD8DFBC2240D0C0232A07B945A71D0ACF267174CC828A6776 AF19A0276BC7E0AB58C9AA1C45DBAB3B77DF463051EB994E8E1F7BEF4252EE19 AD2FFA7EA3A65DDA9CA2E8637A48CCB3A1EED2C2E69C1FEEE3F5D7D4A4C34078 B954105701C313931A9341BA57DC9DD3D8992EFC9209F47A1F1AC0B616875ECD 1D752F86F340D9054A5FBD61A7C6590FAB798D2B1396281E0180378A1992F13A D6136AC53D92A3164E6BB0A0930768FE6AFE6D2879EE4AEAC58809B30A025E81 6150B1E8490C18A16E5B05C93090024FBEA893C380EF665405B49993ED9E659C 3BA313623878E9DA858271B4A9F97ED69AA74C602335F3D4AF9DAB166F733A41 7A82958BF203CD36186380BE1C591A1BE73364CBC1330CF85BAEB031D583A891 52709C2B2DA04BDE531910314BD327036C9C524167D30A7CA2F279276A33062F 60B35E8F706CAEA40D729435842B0ACA21E39D5FD5DF19773485211DDDDF651A ACADD787CE4208101C8698BC9C63F09519ACF4B9657ACCD657983D0273144497 FA40FD64C712430C190688B15D9C12EFF944806436A5DC610CACA624EBD0D25F A04DD8962C8A44FB6CF1FA39A5E562A438CFF0C3FA6C1C99EAC038AA313B4A95 5961E7C6928B4A48BCE1A6C008CA716DC21EBBA2411346F665CC7F3CB2BF854A A99825BDDBB7C347D6DDC3237E819BBAFC4B7C524D2B5F23EF538323A4976AA3 59698C365A384D8D72E28F0B84850FB092446A480DB8C4FE34B130C02FC0C476 3630DD318976AB9027B08C365B106FC60A9C2957AE7FB84D1857B23C8700308F 9041575CFE2BBE3545F866921D7026E4BD4B3E52C86A37855045EE396A1D085F E2310F995C83C94E701922AA6CA5D6CB4E3810E6525CEDF774B22FB958232834 7E073DFA42087B4F124DC5095D4392352476F719A81023C295435E03F281E109 2C83497D825FE9E776BAF2F82A82DDCC5F7EB05A0CDF3E68D5F50A9B737973EC 6D0A819EA3EBD18BE41AFB468EA875A0833DB1B09AA199E2F253B445417C43FA 925CBBB0B6AA77AE597675F5AC52B0D1E1ED4DB1BC25515CB7FE34622AD36A35 BF00DAB84F298DD5BA60CCE41BE93F8E8AE23E7B5D6E12D4108CCC2841924E4C 1F9088AC2A143B3A05D4EAB148A86FBF37AA04239D96DFD6719FFE41F92F9AB4 AE9A335B25FC54AB8238095006F338669DD41726324EC61B7B2A3E69D178453C 0BE8327D967B37774FEB60C991FB54328D63DAB0EF5F5518A29AC066DEAF23D4 1949F2F0831869331442742DE14849C5BD9B195D7C2DE699DC164B209CFBB8C7 93B8BFBB50552E7EEDEBE65D44DB80DED63014EB861422E72248D639EF6024B4 896355154AE8B39AD5BD95363E7F47318BB0859E71194B6A757FC027D3CC733D 19C39562BC4AF6B1F55D37581085F37DA1C44CC84487818D3773995FA2D8576D 7E0974BDD9B7DA02B15F569B2A790A365B7BEDD7C89DD3F0B32849BD779511A5 D737A46035614E5D888CDBDE98C5449BB919C1038D3188B0AB499F66AFB71AD7 4B28C2BC918477AD1F0BCF762A4EE94F17AAEF29B1E846A0A345015CA6B4817A ABD725B85CDD17DEE1548698617D3CAF1F94C7E057BC0C87D0636B6A098EA646 7CF57394206D2718A1B4828EEA5F3B0CE76AEEB2E2DA301B1A8D2C01E99FF4C8 B886EC3721FCCC77F52A246840890A2BC4B4E9B11AF17668A96602C376F6D2C9 A0351B90ED55CAE684E0865B713851B9CC0B8C4B72B3BB960BBC9C9BC91AD453 25CEEBDFF2850810DE61CEAA54B501EFF14ABA7932B1574D0FAFDFDF58418AA1 716DA0E5BDD1A205802258B7A3E8F6AAFD13FF5E1240497613B984C546A038A9 456214BCB825DAB57C2697E57126A02EBCCBA9BC51AC59E0CE027D66F6425000 7375276A39395FBAD2E09EB8E9880A2C448E7DECB8C9B1FA6F5716C12FA87448 3A6DD376D4AAE9661A8B6572DF9FD5D5B94DBE1876B3C95CC7A35537F63D9952 827831C0CD350D0A4BFC3F515E76A4A814F49B2F0869014444B4B3CD58BD73EE 70D72207407032B6B307E414051F222F506F0A4385E657361620208104F2A6B7 EDCFF91AB5DDF2041BCC68941ABC3A50607358EC386E20242386A83B75601ECD 9E672768549746C6E8448FE0393A4D7881ECEF8791600B851B3CB950944E631D 7DA811EC601D9DEEE8D04A8A2F9F4E9A6DE32727A53352D9455332329F13FE71 7E225D65250601DB655C2600F313D85C1207077F3CE767F6EC6A77F543024237 52B6AB0DA86C3AE56E323F64D9429E70FFE568FC7451444305E8212A5130737F 71A66D3E5D89300B3B93B76D2D513D15FF680239294029822A99C4A5B134D08D AF8059C66FB1E830E7616EF46BD14035FE3D32F1B7162DE509331CA04CA9C15B 15C73357DA32DAA04B51A1D48CB22D10DE2A863E6D261C0C7D05D147676D7D48 83995DD9879B25F0699EBCA61812480C81E05290C3923BC134DA2937C6632A14 F45BF42CD9A637AA58421994495556848404F9DD613E1E982256086A8369D24F 9B37FB818B24F9ABA65E2E47D8F853C6FCD1AD4E9E6F870671FF56E6D9BC6292 BE74F1E118F59B193E854A4B5B3AECF32668E0048FB691BC1995938FC4B63035 F88592D4345518CB8946D86E47D234086FA24F62E725F3E9CBDDECE622255627 24AEBE3A420D48203EF7B8003494C397087F875F45A01A3010C3152AFDEEEA42 D177E37D68B2D3D6C33F884E9DFD544508A44E5C4524DCAC6459A5991D49C5A6 EC5104B1C171007C9CFCCFF4D23BF82FD620078D7D89C0BF98D009D50723B19B 785AEEDEC0A91B0B295FE7F8D332D270D3658D77708AB9CD6F0CEBBE51438F0D F96515D0D2188D1D09EA56C8C8DC35ADB827EA66F2D6A71C4FF9B6D2756A4EA7 B015DA0E9066A96F09A59E167381CDD334E7F82C3124FC10D2718E22B349709D B3E0FFCCF2C0081AD043083C1EF45ED03461EB721018EDDF2332296D20077E03 79556C54BB765CB22AEA8DA2B9F4E379EACB93CA8CC1B0839EC2E6B48A0113AF 89616C38E235A850889A82BC1618653BE3F5134FE90D30E8859D78B6A7A4C07E B6C28CAE8CBB51910B76F9612E03272741174713DFEA804B935DF588AA833C4C 1A114B036C212FCA0FEB55CA1E7E197820692B5EF17440E28445CFBF97FDD309 95D1358B56C85377CB3968B1E23B5CBF4475A1A1710AF3054715D0BA1E30C553 720C007AE29DCDD59353A1A9E516CBAF80E23AAFA730E8E2000E5C2950398062 F23AD5E577F62B9B1F8BBF998AE0F4ADF79CAC8C94BB48CD8D46DBDEE683C766 3DA1F21F8A4ACDE586C3D0E6DBA170C7527F228CE30E7C450AD43519C5A9AF73 487538F6FE879F6418F4704895D7E5D4C51935646094B33E05CA7B26560B31CB 3D5A66917B83A96C41692C544AEB7E5CFF61BBFDA6EB0EDDD4500B64B984F513 D029BA2E937249B723A3AED50F40CC338BEB5862753102692544152365562847 BD7C33CD48AA241F12C6A49EC77A96474D517DB46782CA9018A762ACAF8EE172 9AC8595498140CB86877E4491F0FB0AA1A79597A7D4342719459CD7828AD8DAF 513FB2FEE4F40EC7FDEA01C9CF6D566114BD4FFD6E196F73D15D59D4F861A2CB 89E368B282544B0D97A710DFC41E59270BAE32D63DE7D7D3EFA2EFBA245E829C BFA6EE561C4439ACD963CB9103BD8EA9F7C3B2F812ED8C186B25A624238771B6 51BF343BCED266B089561920835BD58BB2F42526248F038FBFE73CAA97B59A84 D93212F1297B3A15D5819AC8576C1421D6DBC00C134E8B271C78DC48271794C9 94A3F982B416D5C6D5DB064E570FF7ED5A8A9111D081D669013646F6A0C808F4 FDFD1F116D52179D75BC5EEB24C86BF6D661D1C23B2E5EF4B22989028CE64477 D1F7B1850D30726ADCCE1D85A818BC1EDF630CBE19C69763C0F51B4AB68ED1E0 BFBA4EF19E7D5BAAEDFEDC43ABD7FC80628A4B511CE49A7FC2641094091B83B6 F07662CE3EEA432D19934972BF175837C7342DEA1BB3C71EF7908228AE07C8ED 1107D3C85C3A91006B568F910A2742B6614EF465B26161BCB9A24E9F87EF2066 4C1CCA1B0A1055D8B9815D386DA4EF70CCFE471C7CEF767D945FB34A0CD7B2B9 E41CDD00EBEF36F247986D05DB87BFDE6CA70AF16C4BCD3B5F9CA77F31D137B5 C8481A8B907D85A76E188FDABF97580861B9F282B3C97F5882CF61CD9554327C C0844930ABBC0B19A868C7A16FFAF238970115D9CB1D677979EFB116D866A3D2 330B377E6B6A23C1BFB132956969E786D92D1288792A27AB0D84B597036A5552 C1D1EB65E96116DD8C7E0C4B4D3A00CC3BD2E9E794BD0030736E83EBFEDF7D01 A4C0943C2A8F17076B3171A4AD0F6C8A0FFEF5A5334F2FB90C04656DBF2D0921 0C6F548536B7281F748DCFCB276565C5EDF76CF588E01F3E585AF6C42F871D08 62FEC1A63B5B54C82DB065A16E98F9B7A79480F4A97F40C3270A9303E77B6824 F1275E2871926FCBC697FB73F7DA3F55B8A21235CBCCE36F5621C2C797CB9C73 78BC62CA1EB1B50F112D511E86A9482F58808AA83A8A9302E7158CB3E45C753E 9E2343AAEEB203A009270E4872A810F0A191E0B5A79FD1FF23FB2A1EEF94917D 8B7B58DFD3EB76550F5A1F949DA055D7A5D0A22A07680753A80B801824B23066 C1526B5C4E24734026637C8473A37BAA7E34EE4573F0DD5107DB0E6772AA9387 C1BE6614E045272AD92642AE015216C42333AEC9D3952E497918B1F13F50D204 A1ECA662D60E022828E65B8696A32BAFD19ED17166499D429C48E20436B197E7 E91B22A4DE1794CEBF8E83 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMR10 %!PS-AdobeFont-1.0: CMR10 003.002 %%Title: CMR10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMR10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup /UniqueID get 5000793 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR10 def /FontBBox {-40 -250 1009 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR10.) readonly def /FullName (CMR10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 14 /ffi put dup 15 /ffl put dup 33 /exclam put dup 34 /quotedblright put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 61 /equal put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /quotedblleft put dup 93 /bracketright put dup 94 /circumflex put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9B8591E5F01442D8 569672CF86B91C3F79C5DDC97C190EE0082814A5B5A2A5E77C790F087E729079 24A5AC880DDED58334DD5E8DC6A0B2BD4F04B17334A74BF8FF5D88B7B678A04A 2255C050CB39A389106B0C672A1912AFA86A49EFD02E61E6509E50EE35E67944 8FC63D91C3D2794B49A0C2993832BC4CDC8F7BD7575AD61BCDF42E2E421AA93E 3FF9E4FAD980256D8B377043A07FC75D6169338028692CCA8CD1FE92FD60AD26 D57B7519B80A8F8DCE9CEE5CDF720AF268D3C14099498A843D76E3B6C0328F24 D36EFE7F5C4E5B5C612786200C8DE3A41EE5F1FFAF4097653CFCDC8F4FD32E0B 03EDB3E413283B9EFB0AC33B055617005BC9B0057FD68C52D1B0E67F0C571685 767F2AA85ADE4E0104A1C777733D5E318A22A9944336E5B98D965E50D31F357A 8B6EA5A0EA98E1B027CE68C2EDB149EDDD04ED74A1B3D206D471A0C11C11449B DE190BBFEBC08C9E1B7513B43DA3134D6B11A2516E6E86B67F68C970A320D05E 94FEC57FB347606DF89989C33482BD09D011C55AA920319E7B26A205D3D0F004 22466F09C0482A164CFB27EF6ED2B040ECCC3DCAF345B5A73676F193D43123B7 72FD6CFC5E37930E61EBD5A6307E4DE70194E6384EC0D79DB6AD86D3B319A31C 8B0589D0FE28241D8ACE280D0530EE99C80723E560BB72AE9D53F4713181F491 344B06D3027BA4E9E94D4305BE1D817197C54C8FF56CD6964165F6448ECC8A8A 64B48B4F0FD69299A137589E2491A283509B21A3A5772F75B7602A9F60AE559B 07A58436D04222C73EAEA72DE9A5A441F88D27C11F4F91255EFE280E91A4ACAC 1E98A4E5E6C57B9AE86FD218C3CD8F24A4104156A80F13821384E529783C52C8 78B94AB3A0096090867ED32E8A30980E737922037F75F062BD83BF4F5929BC51 CC22AEE2DBBAAA001CFFBFF41D258424FAD888FFF1BEAB796A44E3126159E120 7E4025C676CF94888A1971AEF8B6764B3AF4A92D36FAF6FC56FD049710EE3782 BC2CD84FE2473F133BE03C1346B875463F126DCAB15C7A9BCC9A727D23611462 4E8D2BFD2466600285D79518712B8681ABCD69608E6AA9578F7BD771EC36E01A 5A17BC17E375020ECA59B43790ABEB9DF5F4FBBEF807E5699EFEAC563E1ACC5D EFA336E75DE6D8248E9381BB110884FDC89C2F9A41EBBC9A8A1F98E6A41F68BE EE30E25CA148C1EFF42DFF8C214A6537AB11F260B8C329A4947B5FC8DC9C5622 4DF7BF4FBFB00380D47BABB03BC30627AA74103E553F55278F538EDD8C1E64CE 0F1398CA0AB5A86630139B4A7E8FC02804CAFF3830114640AE50D2FDA3B561B5 C63AD7EE3347804CBB40FB1E77A6C89735DD870351C3A1811591AB493251B904 314F65791963C0412377C1D02362C5E9655F1C3D4803CD379A8EF24C48218C2E DF1165840462BF37DDE1B8D5FF09FA2C3B261E2F1A65ECFBE5D4EAD43B52C029 EEB3948CB8A252CBAF545C8FA1C31E920E23A12DD7222CEF2D2A513BD758EA13 DA33BF5FBF1D734653EB83DA2D374A5B9A0CE316F24EE375D6DF6BDA49954C2E DB25A88821193636119D469BA66E5DAA9C92520FD4F84426A4E54273FA469084 7517817A6EE3E21176D333825E88046F50B3CF6938AF9BA79A2F51398239EB91 1A2D07F7FCD948427FF62F40FF95E39FE1A1AA8451411563FD5388472251C155 69BDE9283B41900B21EB1190D06E6B13B7794FED020D2C1BDD205AE77B084BCE EF628249398B496DE85B406FC2E1939EF00DFC84C07E26CF72EC401BAAE756E5 7F6673216E7560D1C2A723CB405EE5CA474A07F61B81F8836482F73DC9516D67 CE0CB770EAD755B6B356198B4B97EBB29C63456953270CCC8D5650C1D006E69D 38DE2DFEAB27DAD50A817F0D645D30AF5B75A7B53CBD3D2B8D87BD0A7E525AF3 22F7ADDFCE31716914C2318260C2E2B4664893921B68C5A93334A361D94A759C 0D7B146D6FD94F0442D672BDA0F6432E18F3C5DFA37ADA378D95B75F413C9ED1 BB5C606A3EC7DFB3F796F59B0478C13FD1900381EFE0BB5242D5B5D34D03AF1D 4BDC93EAF8020E26CA23C8B0E7DDEBBC6762A557067A4CE05A524188A8F02E2F 3625DA38DFCF381727887F5646A3995A8A38A5FB1E5D5EBB395FDD0B7C8E71AD B48EEDB62AB2CE99D121435EFBBFCEEA69AE9ED8238B60CC7288DE33C766CDFE 15B767B4AE2E6CE0965E77272AC9F86023DA620548CFAC85BC751C44218A29C9 849F1C2DCBDFAD895B54E51A569952ED50F82DC8A19F367E7E44643854EFD6B3 FCAEB04E55E4661C82D31E2932611748480EF61FB2FBFB0CFB940BEA81AFCD84 4C6A6332D7A600170E38A8EAFCD4F93DC153C43175434C86BC747348FAC61B76 1FEC9027C1A193E55C80F1F20B5317AA0A05AAA36AE235F6E49F06E570FEE798 84857D7552EA92EF3EFAD52DE39C2F8F43C59E3A957B7B926FC95FC4B60186DF 7F3523EE2AB74E294C8C4BCD8B4975E84849E0FBDA6C0B0F24A636DFA578B122 CF97BC5089E21E9F5298D1C9F30CB8BAFF6A3A11BB4D9A0A5CF2B18D055C44CA 4FD4D8FE1AF3630907DE7E585AA811F9CD11FB2C8FC791851D651009FA5DF20B 3C33FD2FF848A9E3F5652BD294965A332DD3F246C91B0ADA34017FF2451D1394 F9C3C95AAC6EC8062BE98E8914D51DA6A164AD13938693D446044859D03A949D F9AC5DF4A000CDA98BB516D762CB9F6D44B5268FD0C26E88BC4A760C0F75A140 DEBDECA4F511128B7D2805872160C55236F0A0FA7637FF0D4E94AC079CD3C8A7 D03A5A56F26B0438B577C46011A10532FEBCAD14FBD6032E224F45691A726886 56F305231EB2FCDF59C8BBFCB5DBD2D093A0E84D62AC93A2312CA69295E937C4 8DBA1802B85F54B5E7E6D6216A918F911FF705D3B5CF055F1D873B96283A0B53 59344D910CD396D883F6F7836BA65FAB4393A773A8F6BC298069E5BA38210EED 49C9D920F718E3FCE692527DC7CCE6963BF744F2C91BC5952564196D60574E86 87A0FAB21F2DB2BD5A51D7FBD8FC19946D24E5A228462C4772F978E650ADCE3B 8D66B9C21279C531CA1C3A8ECE3420BB65837287A7222CC3673A2A5F8BBFDB60 C719CD073EF9A23675198462C7C87B24CC92D6AEE5C25AC63855CC3281494342 D28F3D2FDE0C183486769A4FD5B0143193D31FCB2C2A14E487BBD96D0BADBB64 D1B56021C363A795BF10E2DB448261C363A54A4AC1182B470C457AA82DF3F5D1 F4B329806141EBD53CAE309319B94133D7EBDC2D0453A905ADD207364371E178 0A95C2686E3B34C4A978BFC0EE968C39ABA00889BC5149162C2B54483D44FD3B 5CFF41F611C7E03B94945F414560E874D7CF27FFD0630890D7D7EA66CBD15448 229059E1C436BB33D69552B5367AB5D53591C4678D0C704DD3EA23F5D9E8A7AC 17D003C19E333E726FFFA2961F33C70F429085F7BFE3E2510F59B78F58B19CB4 01B48E184BAD9020FECCE3AF52048A056981DAEA02AE78197E65855DDB170616 F54278395D9EA50DC83761AE759F9CDEF9E1948E7002414FC05286ED793E6662 3347F2A9AF8917493D7305B92CF93E8E9185F70015F5594084298A6C2F9FD3C0 689F262AC9FEDC9B89577ECDE92F08D3142209FBCE7B5C0A840CC767BCA56C20 4E4E545E2BE4D21C53855CEE4CD0AB35D1A604C0FFFF77DBAE4289752276559F A05FEE65F45ECAF44E95E23FAB6052195C7948AF0B1126482D4E02D72BF8AB03 DE0F1A632F7672AD9DDE70EDC82AA993678A82BEAD0BC2649C4707FD8509810D 364B5C6FE0E10772E95288C622C2F06C634F4DF8C7FD1432BC9310D5F24FEE3F 7AB324863D6DABAA1576E70643CA79EF4D7DF4105093D66CEE0F3B87D2164A7F 26EA05F5C4645B22D3E1BFD2219657712C168FD90DE801FB0F32759E80DEC1E1 43CEEB19FED12D757205043FC98FEC62D6A8D8B97BC083B4A0E985AF7850D6FD 8716B9957C1C35A0675BC53DF672C425C79F43FDABAEE7D63F092CF271C9A9D7 C41F40C4189510987887942E60A412B3EEC84C9A6E1AC7D54D528F5604B72C08 94B7882621A5BF1F325B92FF96B80878CC550D1AE4D8196E41CB1251856609A5 C4D3BD05A922D0D45E039D9450DEF8490A3E924E41434194910BF60BA1B08BE1 B41824345627745541A4F1703E956328F6227D11C74946B38CFB096139979E56 4E723B889B44C6D78673868C89912F8B4F0B4B485F1587A637B630F92E6072D5 7F3B44EA6FD96BBD4FC28A6C1D90805E3BE3E42A7BC9C880762966C55BC04E01 204D083AE976FAE6F37C94F27E68F8C0F28D52B17F6C0FD7C9150701FD78F8CE B8E8DC9260E3974005EB5CA728171F482D765016C94D4ADFE4A42EF42212BC56 7E4EEEE8B0D2A7856CD4E44F55C0BAB762F92CB8D64C17022D4BF3A47C12F5E6 279FC23101FEE93753653CE8CEDC3B75C9CCB29BF1D4554C6120DE8EE750FCBB E38B5D915206974962E320362E59B3F21B3AB1875703191043D03284D4467346 CFF2F98CEB4845B73ED8E003E0DC94251B73E13A9B51A3F1430BCF6A21EB9B7A 65E17FA411F53BE6432F1506232B8159E008FA257F884A4A01AC53BE91754D78 BF14A5B0FBFB9C31BF4908355F8A762052968DF526D118708CCB0B7CB5BEE285 6DAB6CD2E3934178E60BECB11AAB5478623CF6C50C92F8BB5D1A583609028FA7 B8A53B791BDC9EF76A124F3F7641857E4BEA0837CB36176EC9A522EA7F41B8D3 63C37D1145367BD300F17B54522A834BBB74DE12BF9EB26ACE6F24A046D58F89 4D4B7DF74875F1A0C1C9D97BE0849593D7B398EB4B00BEBC8C8D1497B6EF831A A35380FFB7F1AFA4D888AA52C9482E8B1755CC209905F98F40D95B44D4DCBCB6 67423D1BC2F3560FF0A8B4F0CAC352A4EE2C1D946E45AAEC8A6AD40303F3382C DF0756BFA3B1ED64C169E56ED1C760F2FF0E24DC5C9F41306EF8D2628153D30A 5DCB0791126BEFD4947D7EF08301FE015F2B0008DFFCBF9F2D4D859FD43EC7D9 C5BE237E9BF6665B7B1BEBB362F0C0C3A8D86010B9C97FA741C97C2E0513386C 9C26C235B14DD2A58BFDAC7B5F63DB4DA6D5D37D0098175A9071590E1DF66A3D B8173A047C29D7D35557F06132CC920B5460B8AFC11D23D09A4E45D089F5EB51 963FA1A6256E359D485107FD143B2BF21FDE9DA5744BC2615E86C31C89470CF0 D06C6397D9FCCB316EA9989430240759D2C4945D941F159FC02327F34B042BAB B5C3A47C78E8C1A6FBCD396B1A51CC4B020B8AD401841EDABACECDB482D6EC5B 72D2BFEB4556720FADD49D07307C8B22ACB7E310CA4151A85C71EEF70E8D15DE B3B00F26E0E166C14647A65ADA228A3D1C89025BE059306565DB1B1EFC37D358 8C1EB024254AFD049BA977BD4C2C605050E17940A89D0D4C5D963E792320F5DB 3706682E03D25D9E02487247819551465092CC22B6B56E93F3AB528038FEC3F0 668F866707A19B0463BE706EC729D2EE1653AAC7E29BD25BFB3241D4792F5152 ED415B4E7FA92C2EE5A22E27E8B75542C492E56D811C192E95542A6FE0BFE5A5 69273C2ABED4300D491B92D2AECDD278404CB84B1BB1BD7AFEC858215837D118 C0E928BE7E07CFEEB51A6D21375B772B8248C994564014015232A0DA4BEA1754 3274F407FED0837A236371F1A32056240F2015B1E7F4B2CA72C6B58610A66F13 407CFFBA5E0A2893C1F572D50F51286E9133B5A84239C9493B0574E77D281D01 11D00683354A000C9700EAFBC1FD104EA19DFCB87470190E7E2CE26E3A6FD0FF 2620B87B82AC8686B6206B530F17E9348BC7D04B948348802CE53A312443DB87 4DBBA5313A6A2A8DAB8A1CC9A594FF8C299281C0A261C8CB2226B732FBEEDE40 2C6ACC74A1A61379E2E1CD5548CD908268A32FA83D8504C442EA0E183ADBF7FF 9FD09C037AB03516ECCA93FF048235BD11A25DB07F164512A079C5392AC7F889 CE96AE5C8D9580BCAFCC087C35E76EED1A671E87C12E3045E15A687134736DF8 DA984772AFD189D68571A2ED7256F1E204230E41D3D9DD876F938951714A3973 0CA9310489F8E807C1C7A4E51AEA5BC030610A5D7263FF7E0F9FDE3E5E37A362 5B919000BD94D978583B942EB79CF2BEAC33FEBC9A67272EB10865BA8FB75FD7 9D280AB59F91B96C16C982DE848D76D8FA8620DFD7C80B7DEAE7264350D6FB3A EF04794DA3305844A7CF718F6D1A4A3AFF6826173A076A1372ABFC54ED3AC6C2 09C9287FC830556CA694E21CA5342ECA7B10C90AFC4783D841D7B1E34FA3DB7A 2B706F3E21B0FBAB23E7257962FC3BC309CEA2C7239A9D6B44CC96825115ABD2 AF9A2566D2F3382C01569FBDB94C8D664A5DA0F7DC3DD140CA77C743D7BC1420 324ECF9E4780280EB119885E96A6C619CE3C0C8E1E264E2DEB137E5DC8149786 486D65667ECF47B1A1E20E9E6E4FC8323E0BC8E61BDD3BCDFC6575C69C03E31A EFFC290472CBBD049DE3F840AEE37A2486034240F80E75D8A79E0762377DF660 52B12EAA16D678990B11A9BFBC03C1D4FCDA9FD4FFBB3E88352438102F10B7C5 9F04C013B6575B5E948FAB58EA691984A0E54E6B9F3F505FFFEF74D06FA1CDF3 4B8A95904C8A2763AA8AF5B71D00F5DE09DC1CDF87A08B6D181453063E14C12D B7BB3775A6E2A901636273D9EEB833EA8CF20FD83AE899E28DADE10EEEC20BD7 BD93085A4B1AC80AC1AE8280C14767F1A487BD066007A0D050317BD081131A14 6EA0898ED59E46DA7B6254BDCCBC660686E2EDA0E77A705A653733BB5C5497D0 B130359F866CF293FB6EF0C2AC5BAA2DB0DED045E2DED3A2612D078333260359 16CF0CCB272D34767EA069E0F0B0D42327A18529D72E890EDA6195C2688438ED E9ACDBEED41E81CA8EB5E43C2B09CE266EFCA03F2D7FF57F12B06F9E54FCC6A6 546676F6FFC5B8B7D3F0982B6FF0D21D949309F0C0B175CC1D0976F8C55C6AED 6E821C39041E22D91AB30922F2B2EC2746BC7DAB484991542FBC82D87B487507 559AB466F73EE23C2D3194DC5CE4C9AE66D3164613AC5CBB3DB501B64DA7C91B C7ED2EE9027FC0906820B35D4F2CF66C4F9CE4A884B7C07155BCA884ECA5EB3A ABB83F84DB1F5639599DC7D3F51241AB5D95C3BCB7AB1EC90B4BC989F74FB354 04B2D7366A34D335A47B8C00C05CB423482BF6C7970A95545424A08AFF9A035B 7F83F52B65A9799CE76E303B85664B624C65E9CA58184C7BE2BB9D9C86A4DE5A 8165EE3DA2E652B5022EE7893896BABD88931DE1D538F615787645DF5ACBBA0B A8E5B899A37321AA7D4B283AC9234978C2DD81813A1EE5DB6EC170DAC1B6EF02 94892635B498765C07A38D2E9DB0B7581B11056C28278F89B0E60998379C07EB C0EAEDC32AA69B8B836F92A61AFD35688315B2C3F860632FC13E4BDFB63214BC 41CC6859EAB3AC3034449213CAB99FA1D216563419CD6D6CE4E1B56F33E6C654 7AA9DCB5B05FC068DF02AC32408C8010AD004F6CCA9887830927F8CBCD49CDB5 18CAC1EAFF815FF2F6F527F936948201565003022C6C7390B4E3C2B219FB4F76 9F12BD25CA7B3B61D1A2F8DFEE795D04D5428B42FB66E0C254AF7B7A10CEF7FD E5ADA5E217BE24851180E9A1700FBA66C7D2B0D7BFDE4F4EED1D24B821A40947 5620363657F6D048E651A689822CF815E72FC8AE9D835BE31D1DD8B54C9A717F 4DC319B4B59AE073936EA40B070524C7E71D5A7B64436DA107749746B516E29F E3BBCB8F8C473E706670E11E5B221716F315FF097CD1841D0069FA69EA1898FF 9F9EC2518C77806A19730C97F54BEAD604548D553D4A6EDB247853225E24E7E9 89D71F6BC94DB986467E755CCC99069B313F5745B02B4BB608A39F0A0A732B87 7EA2DED68219754BF1FBCA350327572D769C962EF9242132D93A5C8E9725D8D3 AAAEC15ED0F362471AA58488620156F3474FA59CA080EA96FE995D2B3DEEADF3 3141D157481C66507725ACA5953CBBE1ACEE7E3F02C72C6552D15EB3D612730E 61A06A43575568DC3CF3844BABF04CA767E2995196097015E0C4F622C4356B6B F41DBAFD797A4B9D7AC22332C552043EF98913D0D9B50CA6B7CDAF903BC5C04F D20A952BA5CC35B646ACD0A287C956B98C450051AF6AAF79DF37F8954473F8F6 652BF03AE2AE82B99D820CF93F5FC0BA17EBD7A83D1DF278C46A4F26DEAEFC4D 95D07A253330DCFED1B05FDFFA1995E7DF4CCFB449E94C749BD813E1949FA757 5DD7B4C68A3F7946CCEE6BDC8B12FF30657F0808D07508AF7042C2C84135434B 0EE39A08AA24298C2D91085B4E047C7F92AF7461811CDA6D6215BE29949D9B7C 6C2CE48910D18041571B8D78EC12E8AA4D8136BE32EBCAA12C5A7FE604561890 08F10D3367C653C7041D0105C2E3CCAA6E055E80BC34A62418DD202F6161D512 A8BBEF81030F8F05464D998B930B8273C00CBCC50DBBB4EC8284631410D4156C 420D073AE8ADD268DF693B9120BCC42030AFDEE9E338CF20D2350EC7C23EFC6B 84FC7A00FC6766383E542DF699BE07F01832AC295BB1D4EC2A7176E1356941B0 D84EBB40D1DAF93B95079B5208FADEA55A7F4DB794381ACC21AA586257CB4CC1 93F4F5E302F4CD994EC08C58537CEB1A07B545CE68FAB9431C7C1EE4C4D18EE0 57054558E43C1043FEC9D4F753D432EE93A75860E50D0A6138F9C1E2AE758EB7 547F9797BB7D67C94CA4C56EEA98BDA4683F7C3DC9AD05A6A8599B1DB3D766D2 D3E27F50CA9762F00A7EE3605053C657F0C29BF1E997B9206318FAAF01FDEF07 66BE08CB3A8755F90917C0356397CB0A51F6AAD0A5B019AE84033C16C4CF8124 9AF3DDACEE33F598125CED9B9D1448435737C4B976DB7C1BE5A5E04D16742A22 995AE9DFF6669B0CAA80B3AA3DA84543A2502FE791EB65AE23597A3FE54DD7F3 B5F18D3352B561261827D71DEFC21540EEC68747915A3E95355129EB8DC3AB2D 124146609E1F385C696762F6FB9BE1563BDF84BDC84EC3858F2EFEB078DDDC8F 7E5D556AAF054BB91545316B7FBA68BBCC51F65169ECDB878BFBA233122F0664 A8C32A7059E8DAC855A30E6593E8A8404E0245C6168B352568B5EF321A2190B4 D7FF9600621DCE9CDE00B2B3B74BF42249F20CF8487587EC0B8A6D267733EEE1 5CDA5DFB03D48542403188A95DBA88B32D541CD389CB12F607844E3AAF1736B9 3336ADD7402F1101B6A8D9DDD843E6E80330277D6E0220FE94FA9533CB7AF0FD 1A0B0F4F745377F6F6C1F58BF65298A8EB4181F3DF95321B7061B7E0724EBD5B 5327E16738602270A3D5548BB5D2FB075D0F0C696E83C25D3EE91CF5FDA380B3 B2DBD0E45E3881311E524EA96043C842BF330951E778C5F78A54EC33AD31D062 C51CDC286B9862B0C69172ACBBD8C29BA4C6E728D678ED7B209DE28EA7638060 0C84A5B873BBB5C95ACF2CE541F4CD21D51E4F045880A3A59649A14960092DC6 D54944FACD587E2A577DEBC4F18E2C1755C5965ECF93B9B5DE86D991E624AB1D 39A3AF2F67162A1F55641176BD1D49AB8414398650AD64241FA6ACED9F3B3B05 C10B1139EA424EDEE58B78878788B84B2F90CD6E995D461C3BF7079D2F8D9D73 31ABB4B3D8CF7AA16E329C0906D77AB2144E83E3CDDDF095CE9A836EFFBC02CA 271AA81298AB867D8574101D474D76ABB31E3B327F7984A141A4B19E695B6E4F 5EE481A86FE19A47333DC0EF0298B8B1334C1AA1B349A966B2E35BED54243580 FCB57AC33C49ECED9B0651A8A701D7C4E589D08AAF91653F9751B87E080F9D58 D0497793CD7F3E58DDB55C8651D264798761C4EEDE4626686759852C14524F98 584ACA7958632CECDFE1ABA0F78067D7ECFD7DC1D74BDEA77930F422822BB15D 1BFC89A853310FBAC8751A7D639E32C56935D7366083F9998909DE898AD273C8 F9552DE49775BF217C8C749A987CD8D037DF90A94F3150F7A88E7F6FF258DFF2 EB297BF462F7EB65F130F53748C9962D5AAF9F3302634D5652B38169615F1FD6 62DAE00DB38E8658C45DE4C70C1E197DD490B67B5A764A3D83AB75E6D5A65E59 2B1F7EAF53044BC2FE71B260410EA8E723F2DC4906B1A90BE32A5D15AF3FF0DD C87384E2A7901330070E7724BD3016C37C9A52426B91F64BADEEFB478579F9F9 25E0752FB24F272F436E5D414AA8759CC24A39C5E1B3C64C0B1E2C6891E1E109 E5BEFC2A40E67C8F60BC42F8D99017A710686D68A8AE56B83ED766137BF9DE93 B26B72FFD337D62DEA8EAC52293A16689332B9DF2949CACC76360DFA0933B8B6 339B610664417DD9BAAE8EF5FA845DCBA0FA3A311C79E23615743D19F602150A EFFB2086FBC818F1F770E2089B1A002AD7115B409DDFFEE2750E1276820E89A9 E654601A8B32C456E1E3746540D3FEA7A44B3C2F29AF468130F037242EA8FCBF A2B8E79293FF92366AB94B406D388FDA08B4A409D560FB6D269A3EEACB007FC3 391DA43178FE70E2371303D2D91078E593A5F819389E62DC1445E0FB4E607854 D3522A68E2EB0CD41602210662C53D031FDEB13D7844D6E002604AE05DACE3CC 784196A194210FB5200157C08E263713A72EBA6781EB4FCE134D4CE319947B6B AD8DE8ADCD2BB3F1607EDB09F9C68ED0C763172E10FD68718C39BD2CD34A3C47 AB803282C1A9E108FC6EDCC61F4410BE7699FF1E5C27DDA0BFA7059E492DCA4A DE31F8A15EAB988543240EA6CD5C33499F99B48F8A92F37C36121A68B5D8D2BA 0F0F047058EE30FAD733A51CB3AF448089073281EA3A153F0BF38A97D9B5BEA3 216D4234DEE2C2587B4F6233E2C2D9287FA97D0495E28C4B6FEBD4BE11D76E02 0E67B72567D21A141B694939D474D8829CFB026CD53062529F03C23C59305C7A 2A13EB8D4BCA76305F268EDD6453D78ACD6A493857078586A4978D5D2CAC77A0 D5895184338DBAE2D178C1E449853FA9B65F9E640DB8482D545CC523F824A0D4 14B78ACAE4D1B79240DFC6BC5959F15CCDB5EDF6FB73792F19A3F3844CFB2338 3C256592C59097F591180A4428B5F5E1E3EEACCD45873DC47E51E1E4CAD664D7 FBA24456666C28476F17C3D9790465B8852E123B3BFB7A6E26E235884F9C0945 FEAC295D137EC71A9AAE17E12419D4535D8409BB38FF2AB511BC73278B4B03FA 647042DC6289EB1BC15D3597CD6CCC99AFA02F36C06FA7B262B332BD30692F25 91AE7511A4119791E6B68C05199277F14EA2931D0A242D59D7FF296038CBA571 9C9CFDDBFBDDAB3A2DCCBCEA4EBAED6D0ADE2863DD76BADDD8122A4AA386835E 5AA9534511D08883DEC5C8F0DD244C0B3338E977BA417A24BAA041A20FCD7FBB EAD7A812F017F1FC52133A2722778B45B6B523FA26ED6239CE1DA897BAE6C697 DA0BC2A32EB4096C1B91B6657FD21E34890BE1595C10BB71E5F4889D27DF09FA 50C30B0872FBA1717B269FB79A3C226B8D236BD37D19658E122460848153C749 EFFDCFDC9171FC9D061F44DB7BF580862400636F0ACD21C2FA7427FC511C2B34 20A7A62D9A3955AB33E42B976BF76149CE127D7C861B4CCCDB0C3F3595204D37 6C77D861C64BDE28CFDB30B78F38C77D3163197DEF4179E719D6674DBB3561FD 06A05039754056D3109E1AAE8CB959A3AFC7C565D987966CA67DAC6B285A4CB0 05F67A4B1FBC5612984D2A04E3524579C63649A9845BBFD1CBF53B8E4BF63912 1EC4CED70568FD44C4A06C1B09547297C581E8AEC8151ABE17AE47D537C4670C 6FFE45FF252DD40ACEC5357E6ADF9AD8C35E9A96A1D2599784487797175C0CED B92CA4DD93B10176613CDBBF70DD34918B0795ACDF070745A4FA25CDE80D862A 3AE7752AC76CC989E3E4CCCD6CD01101317A71126DA519151A647E7DD77D914D 1CA90A09651805ECFD787922329586268E4196CF4CE7479621A99C4CA4FE5116 34877E4FB07ECE69B6C0C7AFB1EB859DB7B66F106F417F4B4CBC5F9332C1ACC7 C133E69C3160A9F4490F24184C496FC2C22E040E6E8E405B6610D75EAD6A45B8 347529021C949CF1915866A31AAAAFCAE6A0C08435D6020EC60FA00E445FD4F3 1D0820766FD83B173D6AEF2574A74E55217B25524B08C70599D57ED954C28AE1 56752E92A226CBDF51C8551AA749A2775DFFD6711A6B3BCB4B613958D4D4F1CB 3CD42615AC9FB770C7CE955F51CEE21B1E85D5CED699B5AC793F7177BD054B39 8E1404776A715DE0C28F91F3886B838DE2164D11927919B3C72F82932D8EF131 E429251F2CF9D3C76B94DC43DB22C6537028F942B0784D2EDEAC0C2BD3890CA1 27D8F2302B44FA2589D4D15B15A6714A362DCAECAF28DCCF9A70CE5908DE101E 04B85AA7CB71C13F9E6EB178DE3123DE572509CF872FC9564795D286861C1864 8DD540ECB9D75A8D2443EF80302912AC116396E545C3B0C3250E81B78AE359CC 28A09A94BB5ED1381699AE3552A4F0B30901535E761D9BB32BFF10B5A8068E16 7B6E9A24BFADEE9D33611275BFACD8CCD3D4790CC8A485CD0B5BBA7123DAA842 FF6BCEC22ED9DFA194E73CBAD1ADC447BDE46FDE9B905931BBFB2A882A378DD5 8457081F0EF2F1B5A882CD357EE2E010146CBD7D1CC4816486665CEDBCF3870A D69B166BE00A41CEB198A892DCFAD21C4AA63E78FD039645AE07909F6DEF34B7 C561A353903C775B46790D67CC06C6250BA67DAC397C6B87F989FC077BC23630 4C27C88FA000B08933EC3A51C8CB043AD84D4AF8AF50715712512E1EBF48AC15 CCE2A38F3F519E39D425DFAAC92B25E5439013F84D6CB08FAA241E2C9A07614B 5F8F09784F3111760388606285F7FF57A7610F631602558F3496FC0B804A01F6 7C1EAE515B7754A260DC830EEC514178030468E498096276ED6814A0921275A7 53214B3D4772E45B9F25F6F6C8B0D9FBEB02F5BE5C5D73E2392AE89CED29B60A 0DA566D4A6C285E99DB9724FB8B94C70D4A9E7A6B63C8943299AF33E060EEEEC 399C89BABBC727B584FD784D9CDFFF83DB3A3120EDAAD93A074010C5626DD947 0582E82C1AB8A01068A179E313C19ADFA5F3C967DD2D82103395FD0A5270EB75 A26606DBE2F4FF499B415AD8AAFD99A0B9437188DD87665BF143F0344948E545 7C5F7ADA1132BDB614EE50849934DE288E3A719938FAFD11BB7767CF30843CA2 357377798039E6654F151F9B1D75F7C178DC1D745F5E7295D27D7524D37DC63A 4007C2C51C889DE95191E6BDA4106A1326E0AD8E367856F95A059C3FFE3CBA54 E59272E231A3EDB3ACFFB8F392F4F4784D11B869CBDC8CABB9120CB6305EEF0A 3E4897AAA74080B76D7947EFF83AB0A7B605CD31AC2704D9CB29D657B7DC36B0 2D835C03642447F06B227A655D9A5CF45A637C56E7163CFBB15970D77B7F462A 5103E3DB92B0A781A1D977076377C1F7019EB0793711DA2406022BA0DCD47B47 523BC1FB5FCA2D7BA2800FCE8A18B5C5C6CE9E652E375CD20A5770E5077AA859 3924F7ACFCAF40F5D477BF1D407BBB7CBC5A8B741A6AF13422ECD344B758AFEC 4F2868AF6AB5840305D1E2418C12DB4F97F8D526EB04E28EBE46EC37C2DD54F5 A04E0FDCF1800DB8CAB2576764AD1491252174E4568E4492983FDE04C1B9E5E0 69992EE28271F6B06858735FB7B599F56702AAC5DD867066189DA9F5C4FEB464 2E75F55A41867C72D2BC94095A71B6494AB1F759FDFEEF6EDDFC889C377CE2C6 84508BB9EC391E78279E529EE4B7031885F0BA10296951FBFEA1BA73B96B1D46 1B349AF797999C357BCB2F7A2BF77A9AECD22E9201D1630A6ACB74355FD70729 FD3667C5EDCF59D202A0B890AB7CC128D1F99BCBD0086EF77B2669F83E803DCB 319C298CCEABE4F40F4BE3C85E3406B70AD9750B37DF07EBAB3F540BDC8B8FED B83CC70B6943AFBDE80781A8BB8C1BC9B608E110857C869470D6ADB7194E9645 FF5C60735E1DED59151FAE925793215FEE83B75BD6E415168E505F05DDDF39CF 68CFF9EF7D1673F695D4D552199A30859E89DB375EE195A7DC4044F60BD20CAC 85DBF9D13477F914258511DDFA5AF3D3520E7B866E3E558CCCC8F8E8D1191D25 1910F6C347410B6B85AF874D9BBC9539E058E7B847F1D1AFE847965BEEB6D704 863AFA8D5908A0861BFB2D8CE195F17358B6294B991CABDD9B616E965FBA44A0 96D728EEDD2E3658E74D4C933E0E74A06D4128D4B9DDD8F69697410357F5D445 F1B9D3B75BD7B885AA3A88CEF0A296C23220255D8A71023AD5B00D7290BA7804 6965EE09387923E235E47C80BD27157D799C20796629260C526382759D207732 0420C4149F6EEB8E79CA3B56B72FD4D477985B8558F337D5DC2E5BE603C6AEED A68BD892AB7C7773E13896A851344E2E55406EBF16E2FE98307245F89A503091 8E1B7916120C7481FAD51C176BBE1D922E596A3A09121664C51C57B8C7DBC82D 3E9F870D5051258B24C606AE1CD8CB9A97999F9220BDB5CBE10E3CFF56D66685 5CDFA82562F6D6EEFD5AD4B8DE8FC03F3048ACA1D917748A15DBF5E85F6356E4 0060DFBCC82005CDFEF8A78535D8D5ABC256AD9F683D0420869778DC25EBF903 9CD73FC8FE3AAEBB784F72D8B6D220E9594BB1AB2B32C9AB1D27F75857A617E5 BC3506DEDC100BE726D06E3963572C574C20F8CDE8DAEC14FC13ECF358E5638D 43D8ED9E6217D831325C8EBB99AE19F26B38FA1F5B55A5D1422AC9C28A2D914C D0B4C4243AE423415BB200F1272655C28E45EB80733D3CE0FA479B249596EC4B 4EFCE4C652BE6F73319A584D7A75ACA1A664B07AB102E5C3E795613C941C9B64 69D6A353A0A12839E85F8A738AF62D6C8AE982412EC0721F2E6AA0AC28644C51 D3D884B9A022E28D0D50826A405D24DEE0BBEEDF2866DB8420784A2086A54503 3CBE8A431A7D3093CDBD8B2A97EA3103F4510CC0009F6F343A43B52A19043ADD 82CB77FBAEE64E365909583EE63161C5678DEE63D308C7C85050E0FF2E4D9F33 9A6AC9F080B94A349E063687EC632899E6BB020195EAA60D61D606F9D071E972 6393BDAE30F77676221BF1B8D87F69464536F8E025C7F3F14E9801337AEE4AFC F8F3336BD0ADF859F116EF11536CE3BEFE0A4B7C08CF588DCEE08FF8BADEB0F7 61862C9E5DB481B5076634C3E9A8C2843B3899DF4EC1B1BA0A7CD07EC2039467 3D9DA9246E808A4B6997E8FB5ECE77731B4D8376B30FB8976831CC9F1A17DB58 8A51103A65B5A10CB51B36C4DE319F40FB7183C975B82E4A0A688160590DB08C E69835E045F689189F5611CD797956DF0F67BE1A2E580B21E18E6A97F1AC0BF8 CA7B31E139DA17C16379D030F7FAC25C0CC59C3319C734432C4D66627B2C7CF0 08BE7428801B0937F9EEC70087D18EF50E89A3A535CFF020A61E74109D9036A9 DFDD9816C467879D8B847FB6DE81CB1D3AB81EF0CDD820C93E9924F4DD44CCDC 089327A3A029B2263A85E013550654EA780C7E31A64EDE06E26293E8168583D9 BB21B7BE35B720B07D8A0935C996D562E87E6009B23BA58C07D501A383A1713B CC9668A970FF84A029092E64B863FD3298A398B565F2B546101E15A0886F7A32 66802CCD40528240D2A97641D8155A14F1FD17AD1CA6FB8AB76F460862FA0880 7669C70075E0718A7EC0D09DFB5678ED496CA08EC75834E2D4954721C5E99C79 68420B8B1E596D7D5A80EBD6B5D915E0F178EFCB7901E799FE7C7A6E82BB3F43 442B2E0946F955D87FE9D758460BA12721FEDF6A55D01C722468DBB47237AB94 5361BE85A2F10D1892797C8DD860E7589A78047A111FA00AEB0CCDEDD631D728 646B94058876F522C889AA3F484AEDD5CF2E2C9C8A4EAC46B9CE8633344E9ECD A1FF51C37FA59348C0041E0F8ABBE8107A3B9CDA402D2402C154336AB175BC62 C5C4228072EA325D45CE7878413A7B0D02261217B2F1A7E79BB11E5BBC11F787 7B1E9D2EA81A5A6B38812205B29B008C3CCF16D12FB1DEA28857F3EEB23F0E5D D32C6D7ECB3FCC26F34DEEA4B0CBE763643B6F1D68373FBA6BBABE3B29C72C23 8DFD6FAFE8A7710CFF935675D12F3670E25B954B4D7DEF13928174FD0E1198BF B834688F207ED525C47C994B7AEB0CB3C5F7AE3354538A92D4ED7DD9E7772537 F62C99C80ABF955057C83283C3CF2E939605D43A9902175893CA0D40299CA3D5 7353670F92510ACA7AFDB9D826DB6064B184ED84EBFAFCF6380E7BF10494A5C4 7B175AE24DDE2A03C73B2DC68A7E2B5F32A794EF3F8ADADEF2256AD30263CF6F 750F4B2B847BB385B3FECC93029DFC23EE30D654890D5AB477A2DB5BA48E9288 2DDEA2E69CD9D2D176DA2F44E8922E0F5A3A12383C10B96501AE86FA39008DBD F211C0423122A22E65E2268B60E15AEAA9BB58C5EA0FE8DAD3CA7335F1CAC380 CE14337A1F699D06CC793CCF2A94713201268B541F7CF86399853012BAD437A9 7F46C99F7A548D9307FAA6D1CC41D8041E7495D0C83794BBF2583055770EFF67 81AB1798659CB97EE0050728F8B05807FEF753F268B92CE9272A381A157A7F82 40CA9577F140347F45C45FC60F0AE06FFF55D81C5D6130027A2119A3F2B64CF5 5A732396DAAD48CB6C6AE5FD53A0CDA8E3C2759FA2DD3C27DE372DCE530AE932 21B8F84C126D0F06504F5075D87B31C8D7B4364F61485C894AD549B03C68D50E C02F0E24391BDCA7219DDC48EFA064B5A4FDC60893F6483EC0B7D381FF24AF87 292316963F8EBC04E8C38F00860D0F1CAD54A08816B213B05F38EB05F4A3405C D59E17E74458703214BA564CF655CFC0608FC3BED7D1ED800D9835E67508EB65 F5C26B825E5CA4EC0A344E02274D7B9C21E5E02E6CE2F4A073AD2CBFF832695A C8B613C28EACCD6E20C1E07861DC6156BCECF805EFE55C99100CD502A1A3B910 23FEC01C9F454E1D56E3AD9241C12DA45A17AD8964415137726E78FA882C3B26 DA36925EC7D6264B53A9B7B2C0D57A3E5DAC9D7FAF15A7BFB981C75C2CA64F5C C7E200CCC1B64C9274D7708AA84D9E5AEF98A3C0B49946BFF3730FAC885954E3 AA8A1390E2BAE23E63EA0C00A3B11A94234727B9724D3895025DCE4E0EFDC14F ED6E5DA394B55BC19CB910918A097064721A9A1C80A1824AD39ECEF031BA43A8 6C201FE4A29A227B196F186151196283A6FB3C88C000765AA845973F0D4E3115 56CB1DB4B4ECCF17E67CEF91B59EDCB8B65F40A21592832BFEBB74896C3B6ED2 9920B9EA2B9288685F1EEA63F800348A1B1F85168BB999B9B2AA85658B3ED7F0 AC99746B262623D6A60F543DF68928199844AEE91AA06C316ECFBE3CE26C8F65 71D4E9CAB78DD25B707D89DF475660085F972F7EC9BEB4BBC40C0F934EDDA0A9 DD797A3035C5C39E05C78F6101D49E2413AFC08C6FB9213FC7B945F8C84CA9DE 77254614497A5D57EB79A04F2AEA7061D94B93F1195432E2507C0ADF224ACB20 A7018E3ADEEB9E0891A62B5B7990959D6A21659BD22C19E46AE1F711C9669496 04C7CD792412D381BAB29CABB62E6945FE9AEA45064464C0C7EE9DABCEB53619 AC4E32F2434C428F072645FC72DDD2CA0517FD6BDE03CE4F4DC2B8E89B18E9CC C8E3597EA41BD498115F43181321A7501E1454C04CC939C174650D168EFB90E8 B988327BB545FCF1D4CC290F83F8E540A1A4A6FB3B2880C515EBEBB02CFD4002 C7D9F52D1E57CA96441C2FAD3D97E0A03FBFB90E79A576461DD134434AF2918D 051740829C2D30DD8D16AF80AF6F986D9391AEC5B6EDA9383E938C44DB1B0CC9 AAD646CC36543EE8FC88EFEF0EC4FF6E47E1253016266DD2AB696DF2068B69E3 9B5CD352B7F33AE152FC5D2A258207F014DC7F374A5BDE0A947C9792125F1AC3 A4F3BF4374F445652AF17FBCB82E56F1989AE56D2357041FE5972F75FA7E60FD 83821BECBF33EBD89438FACC1CAE029766FCC6484376C29F75B893A2CEF3AFDD F871E5554BE12A5FC76806840398C04CF982C6E5F3BCA55FA833E7913B89B997 5BC10BAEEA945F6509A76FCDBACB38CFDAC38367E24EED989E4000ACBA9AF4CD E73BA6315A3D9D3E3E559A5B4C4EF173D2AD77F142B2AE01DB1925BF248D469A CD7137D001F8CBEA0F24AC4179A239DF08A91CE238818A4AE33DA93D9D759352 DBE3B9865EDA9DCD2D4CB85BF80A5BDD94A8E5806B801939F86C3A9196448C5A FB7AE91E3ABA2719E7118ADB43AD2C9E650126C094E4A858E9D1AA9A495AA02B DBB890E89A6A0FD4AF0539291B9B8004F27525FA9F85112A48D32336C8FFF479 63A4A068B50780645C1C2038753FC6CC7EF5541D20823040268B72299DA07D46 F13C025473C19BADB18F9C83E79EC2A5B1FCB0E7F7B18E28A481C2817242D2A3 04422186BAD0F0A1724E53E39B18BCB36893B04622C9B3F5278502B5007FEF9F D0128FD123463E69702266FBCFBD7B0035DF97D31929103C8AEC2B3FC2D8D62E A399239303FFE30987E4971C3A96C7207001A7E68C4EA0BA1FF1298411FA2321 98EB045D61F4D1E8449190F0DDC51BAC5F0CA234E28A24802B5CC12E6F65036A 66AE366595AEC983C2E675AAEAF52F415A94B40C8A0E6A6D23912EFCC75E2879 CB68EF6FC17D7B9829244F5CC0A420B7679FF3B74A47C5FD269BF2F5E7E28598 74FAD9746F48789DA1EC7103BDE77ADE410C027F30F15C2B66C1AD88CF3E9FB3 25A9466DF1CCDCAB04580397A095D81CD8F09D39B15784C68FE0B612240B683F D856264D5B81E5D8B0D8BA356C8ABA3E5611ADF0D0C2CBA21C4B0F2E029950AA 9B81B900F4D54E2069E7E87A903172132F2E463824B601E7EBF73DDEB95CA85E 029D83E0EE66A4E64FC6437EDDD826F9490C8416AF6C39013B5CA3E7184E1B57 A2B6036923F4E2B5EDB001D9345E7FCDA6AD291E30A73DAA23A4E1469FC59732 0DDF5314BF081F7BF68838358492FB24CBC04E6EBD62DF0418BC28B65E71C5D0 C771B093B1423764489EA75FD1932A9AE7D205CB7FCB8CFB68394C99F121F7F1 083063B75AC218D4381F095A377335BBC4AC514C8C1B975D21AB2882F63A17F2 4DE9EA152CD244696EFC6644C09BCD732068566C9E49CE74867C9C551A7FD9C6 A4583151A654F9EC72F2910956D8131E5533D5B86FAB90BA2D21BF947FE9CF74 D7B2598A23813A6DB138BCC4EB9E5F4C4C148B7572057DBEE66CFA190E68CA97 0D6C5BA584DAEB2096A5899D06F22E8BAFFC5381CD98F8925EB22C58CF68156F 45020BEA5D3811EB3C96E0DDA8457D02BE0561BB587C75BE5F59D625D64FB1D3 2AC2650ED3F5C0152DADAD834A4371B78D4E183E5F473A20A201E9CCA7B849BB F59F0160BE277E40A2D32A561A52C90717A01E977D2B5316D72E08AA17598D47 B97B2108F4C0E4D18A024B430F1712DDF359BC7058AD502F2353B47A6133B56D F32037AD54307C7FF2F90802916210A4C194035B1B1335FC05B7C7C29CA215C3 81612DC6120199434E7F6D99B690E9A325D2BC2B25001D50BEE1DE8F883047B9 54010A9DF87C786F1D28231967DEB5D353A63D457F79F15EB46C30C3A33F25B2 D575DB0F0376381DBEB0FFF36E36F9008774E14876656D55F301F38B2F6EE224 73B06035584F2EC6E6AAC139B11E1323D441EC89D2EEA94698D60B961258C017 FC2D1AE642EED8EA9C09FEA797AAABECF34D5B4E622D1DA425641BF598DF4ECE DA9ABD48DB912DA3FDEC974F2116AA8EF4D80AB291B29938607D3EFE136F7D80 48DE599F24603C4A103ADB925D23FB75E1CAEB1A547537156F61897F276D8F56 B01D834667CB9761B828E48ECA9018B190A838E774CDD1765AD69FE15ABDDEBC B89992EE34D77D308E65BA9A8E6BD6FDAB41D6851AFA4C068198A9BD63C5CA7C E0285391CD25E18943D7A54D5DBA8CCDF1EF2A6613740383406BF2EC199D2B0D 56EE8B97B440B4BF7A5EF674002AE023AB4C42FC80CD3420C5DC77AB70E47850 3FB83575CAEC98B880AD262DA529CB035080752271193281A6E7AD16C3A1A983 097A7B3960958A0D2D473CA0540A1DFA5DBD6CA4827C2337A43523A1F1B56699 D280B37499CEAEE60F9232957B17307C84453EA7C25C11B1895217D95AAE5506 042D570C1D7378C4667102653E32E6946BD32C180E648924B494CD4617FDB20A BDDA45BA74EDBBAC9961D64F9CDE456BCB59694531509629A0610900F42297AE 9CDBE0D7A1EBFDC10488B76BE38AB859A9A30684C67F73B1786DF4EDC11142D4 5B8063B6D6A8097F22DF6CB23096F0DD533C8A031DA4CFC891CB10A1BC7F3891 332FACDC661B6EE4598208A9F9A4F5E927DEA42B34DEEA97D08AE0270FB3229C 8E73945BC2C8C41EFCC4529FA4C6C054D23752C4F4A55CBE1D74042B44731B07 5EBAAFD8E7F79D4BBCD60D9C643F108C9B6D750AC50C52E7818B9B8AE6B6E90D FE9ADA41BF0DC33970CDA0840B86C197ECAAE22A01E65DAAE1DF4E6B29E378A9 EF8A9C5ADEDEE4DAB238A1985AF5AC5BBBC4DF5A7BEC250817DD65F9CD76E319 15A6D010A920A70BE94486BD8148463A624287E2017A335888C0243193E8EF9D AA6AF434A12BF2BC7C9EBC0D062F5EE9DA12A8FC905413E4DE2BF9B0F7F95D5C DC04C65B0BC591D7A5B3AB655CA7357A96E48A9AF74B0DB86A225F617BA7B43F 8CD01548A12E8373B7CE5FCA889E968291FEA4FD785BAAB74195287EF7B04323 66A6075CD4784CB799A582CC03206D19ECFB2FB79403A0A0F8D5E9ED52FB5341 4B387BA87C6E6FA5170FC3BE2E21F7ED13AF7544206F504F14DD921D8980016F FB0A727F6C468483879C0B8AD39CEC224FB98D7E6351FEFE68E826ABFB69A0B6 57A01C4ABBB245BAE6098B102B9B5AF2620BEAEF07609D82978C0C08D40D15BD 5F96451DEFEF8BB35134AE4283C50300BF7987CD89C1042A6C201B874889799C EA531DD4A1318C486C83AE6E6CCAF749D1D9AF427CCBA42CF589FAD9598A2B2D 2A043B2E7B0EE1F18799B86FCA87DE46C28090FE3344EA6D83FC91FAC2D087C0 E86921E8F0C55103CD5F93C8C6CD9746D59B4F163D7F5A49B730602EBDBB815D B95D97FB3C6C2D5AC838705A5F2E3D63E19A5417FB1DD423DBC5DD2872523D2F 3CD2433E11437115BBDAED7114EBB02412C07C95FD4F5D5298D93E33DAA9CC2D FA2BBC180E1CD045B65223EACA0F2A17D94AE2A452E21B82C7A0EFCB837CE70D 6406FF90414CDC00666001F9C3BE76794235BD35A36C5D25FE6FACB8503F6BC3 EDAF80FAE390BBB6AE1BA4817799C4B59271AB8C73C0AEBB99991B0D6940E655 3B52FEC6F3CEB5F0AA2E15E397DB73279257F4C970F5EC0967A011FF2663D844 4882AD1C142039767368C743F8D284353FACCB59DD03ACEBBF8264BA97600BBD F632BE01031AA26C9CE3E67EF354A1848BE02DC2F6EBECC29A4B09289229F655 6C050CE3B2D7666C9EFA6837728BCE6719A9993E86A0A000F0A7579B899DE114 61C061BD7F0532322926565E4D15E389C06D32902DCD5FD0941C69BB635CBB83 1C6E4B77B45D25C00C83E41599DEA037A9EC82605A813195D185A59A71E7C44F F805308E779AB55BE4193F03793A0C52A9CDB2D0751CB6F945E0A8B3D0BA3D16 92867B62ACA97729378CE2F9A849813DD546A043D330186D090127EBC347F38B E772EE47CA5C592CF7BBC03557F12B5857022FE5AD824D9A39AB2CD10DA3454F 1AD03B7F84F22C4B933300E0C1308A641E95A1BA9D469C21834A1A3CD0AB3F60 5248A00CD2F035B8772B0E63047BE5FAE23F5CDD12642A54879A8213961A55AD E70F735CB573FAFB358B9F48BCF02B325EFE2B62CDB2F68D461761378D324DB6 63EC869238A5600A5EBC45326A6C498C80878A115040B1DC3211AC681AEE84BC A90EB8F7701829BEAD6B9D1CBBE77431A8C5C7A8DD423C7942ED0508663E3813 C47BE7E8632EC4D2575822D5D841552BF6727E65A4FDCC3F6169FA189D9820BC 74F0C7A861EF56F93065597FAE9B50D8645CBD199BBFE54D8EC7BF8A53E242AC E04EC7F44702BC8FDB298E8013D9DF2DE48AE2385B8E1AC3B04242981719EC9E 91666D84C9F789C8A8DC976155B288252460BD1B88775041C145824EF438E300 894BE85CB201A0284813B298DD1D7E3ED1330BC1CCFCB68A9B1A04F80D4DAE7A 1E5D5961CA78A283566C7223A1C5714887A933DE11E06865D139AEA4DBBE4E00 7B2D3BF9CC99075530C783BA70A2AFCFFDFF65A9E57BFAA95C4CFE358163771E 073AE65C61DCFC5948F3A4426A747D6DB69CAB2A32ADEBB9F9B7924D967ED877 04CBEF3B584EFC3F84AD620747FB2F9AB06BB79FD2CD22C8C1CA9703EF940889 7607865A5EB3407178A48354694C9331C9AE9BF821C952A43CE5CA6DE317C660 6FDFDAB37BA3E2F8E916B0C8B71B68D84E17F3AB13DF8EE606A7C30FAEAA458A 974A6164BF74FB0DC06DE11E499A0D055926A9BF6BC19824625130AE725AC840 532D59F4565A033A160664CE9798999BFF16F9E18A42F914C6695D151E7BE06A 82A194601CCACF6A48657A57EA0D586414E317AAEFB125531BA1EA67E54E463E 79B93144C8F7DF602B41B247E68750E99865B7EADE60FABBD2F000C2A383086F 4B64787E2CD2F352862BBBA1843FCD428E728B4BAEFF3733F47AE3AD79E86FFD 1F51469CDA7720F2BAF97117A3C4A5FF99B3F57A4B88051282F20714C9601BCC 363272B3849BBD2A948E2DD9F27E40DACC127EA34B258D56D99953CE22B3A461 291A6AD8D41C267872FF64C7AB74953110333CFA7DBA351A98FED9B535275331 DAE004B9612809EF622FA0D1D3550BD96B118F665B3DD8E78F533568EC694E42 47EB4E7B57CFE7C1643C49CAEA4A5EF675A9C2546622D1ED11A94250B89431DA 71DECCAB3886ECE1A8F2A85362C9952D7274DF53BC699C9C1807870F47B6725C F43CA9920847C2FBDC8E86193E5401898BF602AC209F6F8B5EFCBFEBB68AF16F 3763736148F1808F1D35500556E4FA021548DD22EF27997488881ED68F0250E6 D19F6C2F521624AC7C11280C2EA1A210232844FBA9151A4615D0BA73077E813A 6D606257B126BFD550F5D1B392CFCE3E0A0EC01AD033FEA96972EE7B91C4D8DA 8AAA4D1F915FD25DCEFD6949172C3F7463731F9D7EB340122FC370DBF944E110 DE51727F999AC54E6FA355F731C470D0E555E32D9A87222A617E49232F94B30D 5FE7276F9389C39F0932311C2E636556FDFF95880ADA24FF55C27BD6691E5A24 20ECF70A0584A6EF2F9A1ECEA6AC50A6507512690D2DF6A39B850DC5F9F68285 6FF72A5F6E26F3AE0D45CE16C7252B0C41A64315BA5E932A5503499930DEE8CC 60A052B728EA0B0A8AD9B5CC69FA546071D307D12DEDF782F180EA03F2AED498 3B8A72A16CC18D3FA5E9EAEDDD20EB7AB97A28D317BAC4A43076BAA337F5832C 7F9D4A77D661D18106A79F5E58D74C4AD8788CBDF322D72DA20FBAF242731287 3F9B7FCD05450816C4A52BA2B728003C885BB2196C3DAE62B9A0EEC3BA8FF42D 659D610EA4764AD902AB4E6F59DE1CC4317893C41B6BB6676AAC34BC21617DB4 5CD467E268D0C512199CB76BCDE343BC8F9FE4642663FA14566AE23159583744 BDC5477D461CD6DA07ABD7E899E90643209F7AC2246C6D3412B41D62061CA8AA 3E8BD293A7C23512B1D4581B45BDC42D4A8F4909D2DD105B2B14A71B85058DBB D7A999041A9BA6E2A74AC5EDA22E4A92B34FFB6273EF4F2D931C23BC116053A7 7F0F4CEC599C5DA73B1AE3734BB3BD7708E46BDD4CAA9CED4627E24DB5E9F754 32CBBC44FD0F6358240638490B2C35F35490FF19A15EE538D9B04C7706E5A7B1 4AA35A21B1E50A937DFD1E06AEEA58A652D81F8067FB94A1DDB2B828CFB5F006 C6D84DAB3BA7DA45296DC365B547F8002934B37688998BE6CC3A994EE7B5DB07 38CF89619D639B93D08B91BD3B1BEE4A54BFBC43EBB535E069FC53F95B10FBDA 420169491B0FFC996FC80A35BEF59AF91CE28E3B45EA9BFD10EF8A6A779E9494 9C352606772DEAECF95688CB95910AA2E37547DE3E71C34BFCB04CC4B08C84D3 04341D3C5CF80E352C48B4DCB94C0409DB1B7C1BE82C9F36D70DBA3A3EA7B4CE 54D950B3FCC4FF9DD36DCBAD765E79190D10441D1DA45EE049DE1A133F19F265 21891E95F61789821F0B12C35E3402F254927D3A4A14A3F738EC0C9FC235ABC7 20E2FC92FE43BFAA64CC929A9AB82379DDBE313BB7B3163943A1F5418FB68106 5EBD65F0DABD2D4FAB19752C73E77A7C01623E1DDFC2512CBC60E733D5A21C79 1D2CD21F1246E3BBB8B8A153A76D6029A463667241CB491253355AC02D4BD4B7 48F5E70134F7370B7CBDF0C7A68E56EF86ACFD5E5B9B166E69278BC9A4EA0121 C0C369A3830F50356FB385592DB310B6F2F3728D7B32F48838F6E16A03EDDA3D 9F13251F8AA4F3CAD92D3C3A7B8942FDB5D62353E6CAA28F2C1DB0274A86A761 40EFCD5C3788BD69F6BD0AB13FCD39CA575AD1D62CC04E39A5D25975F24BF83C F374E8B80FD1441A2C8B0EFBFB20A0162288D410AF61B9750BC4ABE8330451CD 913E0A5F13A3B115ACB3A5EFB07561D3D214455A5C53F118C3DEBF69E12B8C3F ACD25C3C9751FF788FDE15BCC395E456BFDC320CABFC5F1BCB933445CBF1AECD B6FE6F1A7578AACCE5452F2F4661AB79699866861FCF72FD180F16232FA540A8 104AAEE0B96B79649A8AE247E4BCF690611A70D6CABC843E4088CF5BAFF037E5 61DEB4744E115A9CDC5EB743EBAD85AB467424615F0938477B633B767B0A5F44 7CE9B4EC87659B1ADADEC7357987FF154B2CC0EF422531AB78669B15B19A1EC1 59779117BC7879694E2C5B9378F6ED33ED6B25DE3745246C93DFF324FFD71D99 B01EE9FD99564BB4EAC575DC68FE6630D4D0EEB3C9C1CB04316CD77ED4D54F78 4060A0ECB0B66C5C9CE4E060AB295B37CAB264059008B17BF1AB2AFD8274E0D5 93B3FD54A06F0E6E8B4C5C832D09C1225904FC086B0D6F3F86BC13E75C0A9E4C D1611AB24F58CA37F1CBD19E7CD78366E829E87CB3B817125A0B558508C31CDC 1BF0EDBFCFB627190600805427390F155EDCF938033F18FC0200AD640FF0D8F1 8605279649FF3C1E87C0B8C6429B8C90D7A06BB47468F77E8C88F978FC047755 E90C1E85376681CA853DF212619A1D54E70C24F45E488000E18ADCEDE4428A03 576C2CD08A17777A4C598230971DAF473AFB39E807B307A04783165C299C7070 C34B2256601A51D52607EAFE7D6C819950A0B8D7E5FDAB4B6CCB4DFDBB8365F0 66A7F23DB207E23E214C1E245D5229C64961E58107A91B7AD4EEA1E5D8AD3532 EB2AA9AAC38CD19162EAE9456F039FB8F39FDEAF1167AE034E5C53DC5EBC04A2 6BD1941199D7FC33189125025A030B43D7A0558B14C320C8406957484097BEEB FA9EF240FCC0CAEE95439838D281EFC9DCB49F2F63AAB0583BCAFAA74CF72D1F D51F930AC472B04D9B4D550D6A3CD8279DFB51770AB747F504AC8059F947ABE2 90BCD8A13550090E423A30C79C5CFA48F2E01B59CAF7D4CBFFBBBEDDDEE4BA0E 24BD3EA73C9C09904C7D0BFA6E6992591468A61AAC2BBE7F86570C00C9D59A8C 5992735C102D5BF6497332095C47EBFCEEA7FE5D6DB3A2F97270CF2AA8EC0AEC 24B4741E265CDAEB5C2659ED2F132814C220AF46109BDCBFF4A0EB06B49F006D 9AE6AA322B268C9FF488CA7041B092DA3DAF847CA00B708E8C7EC030CCF0B461 1743731507AAEBAB4B4493E4C273DD348CA21BDEBEB2F7A976D900329BFA6537 6833904EE2FBB9CE98E8C2C775824F3B82734EFB3599A3317EE43399E142EFB3 10EF53B36579CA3FB19E7C09B841E2F74764DFA34E635F0A58596847718E8A39 8BD3EB1798CB9CB4ED71C09DCCF83427F45B7C94B0AAB4843B8F30F91E6371D8 BEFD029EF8495372FF2E78DA3F3C1BD733D2E237C27FCAEE958F7B8E4F8A4564 7245F4AF083CC23350263D50FD1394F1B0C79329D78AAB4AC47FC4FBA4607092 D0D22A55BB52378F19407054E157A1B6CC8B970CB25146B50236C4A89396875C 5290B3E24BED82E7D9113C43DE9DFD464BB738644AB1B67AFCE859C4C40EDA23 6FD48B009A41219C69378682BB40AF9F70592CAF12B5037F815AD3A3B13EC845 B323C5B1B906AE194A2EB640F2E213ECE427A8386FE228C19A1A0B1D300E5702 4662845EB7C4BC2B17E208F05DFB3A7AAF74195CF518D9DDFEB839D68B74D273 5CBB9D520B9F5DAA28736574997B0ADA6D494E0B3A5F5860532DFA1B064FDF10 8195890199E7E0983F44A58F63DF0751497344D5156E929FF43DF0AF6F4ED375 7EAB82597D2E39E3524EB9B1D500CE9884C7F0F4D9B2D44FCB6C20988B93D60D 8CC296AE4F2DC10B0656E20CFA369045E4372C04B3DC6C56D27FFCC1470C654E EE70427D4950ABBF5CF63812197F30C23C3C04401FE0A0F28034E9B6E7D8443A 83176C3937CB3D9D465558CD4970A471BCF403F1854F5CE3EB154A8D82213673 0F7E8021F4C25FF65C0BEB5F50600A472F5F574F0255FED06F2504090BE8D5EE 00D41E9FE617BF06113EADD93DFE12E78AEC879B24215D62556C37A6B25D7A9E 16E761E674B7AB6BFF3881D48F0B61AF8209A82A3251B440EF888694E1AAA1C9 6E4A823C16DD2ED27C4402E77325B8FA6FBD2652BA2E3057817DFBF6A81F44C7 2997B243BA0214908AF19AFAB784219C436A6664E046617A35D131549FD5D7E3 729DA7C96726D508E6C1151947057293CDD96FAE3902314352BA91EBEA37F68A 2F086A9AA6689BBE293616029CF172A756EFD7D0B0F470F45D1386FFB11B92F1 F80C12CFD8342E756CF725E31343CDFEE5E9E90A920C15EF2914A4179FA2F486 CA8D96EFD83693AEEFDBCAC372522CD4910157C31B8AB841FCBC129FA33685B2 8876433BB7851AAFEB17C2CD7815916C981AC78405FB29E59A1B0CEF5CD288E3 9B0868222721BBFEF7B228840DE2A979239F5C7911793421E967FAF247F614C4 69933199130AED34F38815700EE07E58DF77BA661A99E3BB1BD135C22064FBC1 D43E87346042166D587E6C30BCE854AF803FC6C6C0ED95E284857126E20BEC2D 750023C19C94FBCD6BE5957DA35ADF29844020D5BA22C551EC96C2F3CDE8687D 5DC6E6F3088AC773B9E096654B1DC5D75C8CFFB5328710DF8C04A7F8E0204C70 4DA4F5606972235E2A3F25572A6FEF27974CCDD6BCEEECE3C6B57E83D0BC8929 18F287AEE0012630E0A04080E848DC22283B57BB7B754C7DD1918109F778F559 AE0FE733E7F5F6B80B0AE1147BC7A8E1BEE5217C2FDD410091734A0B7395FBC5 A3D98F4962E3A6A1B8421E1C7672ABC3EFCB674526761461350E84AD9FC34C43 3F181182B2CC095E0E4C546AC278EB6D4D1A54194267D062143FC0E867EB0504 19895F9168E4E61F8EB148F736F958828756DB63678B61B989DFE75C85855F7A 1BB27E2EC7681435554E4FD64B74B5220408DD5DFFAF1821B7734E99B92AE516 455F92F5C0A078ECE5CBBBD0D4089D029B90B6876BBA6E483B74F18A259FC117 2B5BCEB48AF09BA4A43E697E2CB326F43F92833D71624923E4F6C7D1A630045B C5F94B9CC2EDD1F2BABE5C773F5C6B03068EE85D8E9F27024CEC47C402F5792F 1399A01DD71FB66CF7EEC6863CB0C80DA827F5EC08380585825DD8335616C116 37F7AD805613D374994306B2596BD39F426C89C7E6439E6F2BDFDC8F7B498B91 FC7C2D5B855C1FCD730110DA575A14AB4E017D2ACABBE044BC55B4EB50B050C7 BD021F2AB0D2BB1DE65248F21072FED8567AD203A0383D85BFED24AAF3C38B35 58D5248E2E36095ABB1696F0128186E593F5A7533824DC8D5AF53137CB0514C4 DBC250456F2C1550224D29ECF439DAAC289F57B901FC15B6A40E5D0210E1FDF2 D711353719733FB95F820C8DFAACDD4E9333236F9D2FB179E4E7E1E9DFAA2FB7 4470AE61EB250DF20EF82708A3719E3BC195DC182B637516146614AF5B577830 7CEBA2D1E26827EEF49FCEFB8567E280B54A9CDE4147069019A300E1934E31C2 EB0A0F3FEE3D3C85F39B757CA11233A368C6CE05B4EAFAD80F579B8C74C4A54C E531E71001F73C9A1BE5022D496E01EB7998C86F5B046C74888C770610C55D06 5611B2ABE837080960A307B08F20805130C0CFAA50729BA3ADF7389E1EF37CD1 8C2D0E9CE65335FCBA42110AB621C4ABAF8429289827FED9FAEE3DCE646D38D9 EADE090E1DBB490E2BC5A14ADB61DF9FD74541D0250F8936A3F9CDDDE7113F49 B66A08E6335CAABFBC8EA44A12B24AE27F16E28ECF015E011878634965CF38B8 F923BE1DD39B20D10277CFC0CACF038CE2DCDB0AD577FCCE397ED3FE97DF4F5D C50DAE8569729A517B8D4B7ABEAC79ABBEC555BA59F1D2E0B236F35EE8FD8032 8BE82D10A73C9B0D587682F2D226B00BCA7540AADF93F082895A966207191457 CE23E0F874893041A9EAFA05DA1AE13C4154F506C4A83F5137ACB51940EEA0B2 E6290C68FB2ADC728D06018DECA9743D476AA0AB1F29079D4E5EC315F53A4EC2 2CCEDE2F02BE3E1EF3DCBF1A074FFF17A1226689CCD5B3D72D5418F4933EE333 595510118CC5E0881E843E1703E60650DCD92677146FFBE0F9AB70F6ABB15B93 C9BDD3A5F5990A3F3FCE518D7C04A3DE4371288A0D61A2D21B15CC800C418750 3D21F53EADCA777617A9CE3CC80003496A8AAB45E90858C6BB021737624AD1AE D19182423A00313495B4C10EDCCD165040FBB08DAA28FF353616E5CE7528579C 72AC14CFF63777EE9572D7579A146767718F4D98F1F6D5243D188895EAD44731 040CD1943BABB3050DD87EAC400402E8F96A33062169E04474DF2EE118EEF60E A1A9F82BCFCE9C6D8A267B125B1DEBACDA50025D91528946458988925BA81F10 480D485D59CE434B73497D540BB59F6489CE3D60A641ED546BB25A11C243B088 BFA13CEA8F57E6C53BC6869177F8FDB77350EDBFFF5E1E5CED9F628C78304214 F3E1E690C68B70C4FA60BF8B226CD981B9BBA535D0D103BBF706E842FD4B55E1 2F750C6CE762832313B93B453C59BF4D7BCC80661A59091821AFC6F8C077D4ED FD02A45ABD1A4DD5FF30EBCD1292EDFFB383D33D3F49A370731A5DBF09A862D1 E92F8E0BC90B9FBC3011815633CAFA59A54B2D9014F7CDACE5032DF12AFEFCE4 5B1C635C5037114512BF8DAC59E260C8B45E20B97A00994F543BFDBC791167B6 F8061541F84AF8F1B66A3E7D3276F1907ACA1EECC9DDFAE06ABBC9C26537236F FAF589CBD2F3C596C6F28C2EE0AAA9A46C5CD5B007CA7902F1FE0FE665233750 CE07C67D69568D666B821F23CDFD88F933FC498D4DDA29E682C87FC9DF269DFE A274BA7EFA7E81448D5B0F13DCD591E02C393F98F896058F76E3B52E1FFC91D6 7AA1A7C8FC4D9C74C311355B02A78A3E11C1560B53135ABE4AA5D998652DD293 DF5A8BAA214135A36CA92DC028A438B9DFA001BFE5558A4E9ABD1520E07A73EB 0ABBB49FE2928B59AC6763A6075CD4784CB799F1EAAE4F7A66426BABC563B59F 471EA19A64EEDDED58B16E4ED5445CDD38C14E2E7F8BCA8D00D99BA42DE21674 69F2D1FE7D089F62FB961A6490A55DBA2BCF5F65ADCC9654E1736690A31199A6 81E68207EC965C2128DFC6C9539F7179AFF527FDFF1AD7B0C3D3E3E7C9D0416D FE799F9179A0A10E5E638CC79620E3731D2EB8AF9EE611C6871FB770269509EF 59CD98E9F816D3BDF18FA1C65B94FE46B85AB0E4D41825336318DA00D2F497BE 4B565CC8C8BCDEC9EB1BD54DEE190196588038242156A18EFBB599BC9152E31A CB6ABE7B8A74A00648D512B47969620BFAC1529BAF1A74F4842A00F139DE443A 71777C4F445277BFD3208F9591B6DD4C86299A1070D4B463BD6220CBA97B1C64 B62B337C0E1E98653D91AD107AEF3E217E77279AEED1F5F7BCF4343E7A24529A DED5FB06970A5B56C70B6BF390355A8DCBE0D0E6218801EA5D787B893EBE40D4 13849A3F880539F7E7920EE8E79D0E4F62A71D031DAB49817DEE16C1B9DC61E5 BE80DB8C3685AE8EE6002E359E8D1F3D41507B718A572B2F629D03E838B07EAA E5C3B2CC8433E23807743060D7A3941E4A47536EDE2A95F13EDF93177DFC728E 433E05A72CE51745E399B20090DBB6AB5320F607A638312A2E814B728A49EAD3 90A32F51521D865CA6DDFF41425DEF914177F1C47D16427D2651DB6D80ADF4BC 28D31E7ED95F4F96245377312D736FFB806902B0AFCC74EEB1DF9C38CBBCF080 B5EF36F36AF876B26D29BFF236FC05B8A53C4F92E609FFC7ED431C9954472695 D9D8A3A07179FE02C4E340B6A69C279C848D60F8A899049C6BAF564904F8F481 B4F30D9C5D8E9FF435AFF83A7B52F6A42E038A757ECA4BA330ABE385D130BD57 C40D9BAEB2CF4CE302732DA80BC676455AF5854DAF4A09A465A73BC51EAE4F9B 3B733B53790D8F84EC57F9ADA2399AFF6D87921C686CEBBB609AC94643774E15 31EE601349C3E804F9182B6B3E084593816151E856CC6A7F06C0DC52D52A2A45 F1B3D83C153C3C76139A71390BCA2327BEC5FAA018D9EE769908B3A055D7E90B 78D38FF6FE4C83467670F0A73D4396C2E4D9CCAC6B1A49664B5DD62C113E2C2C 1DDF67BB938441F9D875CB0A6938AB8461BAFED432362BB4383ACDBE2BFFBC26 F3D5F9D4CC7E175C4776A99A6DD6112B190CE4F44C7561A1203437D3971943BD DDF39727AB04A8540C14778903DBD5D0A73D8505A1BF7C7157A9AF2285A6C689 CA556A3EE87A216435E52C48F732ACEF5D27A3828312A306EFAA1C83F6132A97 BCA04100998B362A4F1FEE55EDFF7074C5F6A3C463B352540598E20EA2BB7299 F42D3282CB1C0B4974602DC568AA056ECFF392759F5DAF76311C0415F4B68E92 5047F5E7A4F384B785C91123ED0E455344675F7D8B5A58378DDB20750C00782C 7E204AE50AAFA96FBA09088CD6BB4512E922439182BD11B2E1DA6D2578F77D14 A5EF91DE35398DBC2C9960F7953E032B35706D98A134AFA190D9E1F353A00330 1F448816BAFA571C65B761548C5130FCD538374A079DD9D46C913BE0C609C678 E9B2250091FC86EDC52EC1704A449A571822857B9BD860C708123D29E418DB32 DA9005251479EF5C87D6B8DA5840139298877221F8AA92A99B7F50898FC6D4DD 141E3B31583E4D0E6B2C7072C367B070EF45AB0C400C57C787F82C65CB8FA87A BC56A0C40A42F3ABBE260FA79C8254DFAF43A70114989A9BB7BE16D27E610D84 4BD398CDAA53B30287AD6951DBC2D61BCA015D688B5C3A262B34395B0BB34833 5CCD137D66D45AF6AFA0C57DB65FFD25D92687709A2FABB26A7D24A95D761986 10DE1F19C3153AD36E5712E837C93726CC80F20F764056648BB435E63316371B 5464F813B8186D0B59A62D078736D9F2F63729BB0F8C3264BA455BD3C66B57B7 0DC609B690298D06EFEE8EEBD35D29B339610D51715D0F6DDCBFD807B17254AF 9E19F26DE3A5289FFE22515FDB2D2E26258848AE93B2AB9BBB9CFECB2D00071D B1A2F97270CF2AA8ECC73C5BB83E3B15961E204F371DF5105EBDCC6F38F62990 67DE8418AB677E06BF8558246B146315851288C4B3079AD2E896FD5B72823C41 C4F5665B35B0A4BAB17087A76DE9E9C96E0BB4DD5C38B9B5AA1E16CD4D0FDE64 BA5CEED97E0EE626194C29F059DF39884DB2FB908213D6D15A7E151F89273460 0CB93CBCB34E4F8B88F93C894BDF2ECF01346141EE96D43ACB028EBC38C1C5C4 108453B67D5150E7DCB6C8321FEE231D0D5B90A866C6FEBD1F75B2C63A8064CA 667C3CE72C7419FCE65EBBF7A8BF938CC1CD6897E77C2DDD46CCFA7FD0B5F2F5 50A14EE54F8F5728877AA088CDEC1515E6C37CA6BD894378079A2633C3624A38 0CD34E49A09C975E5D8A665A8C1BEF23184700BAC3BB3B5D06248A1476879F01 CDD0F5E316679573B86AFB75077DA4EB51791988DB90CCBE51CA7534150668A6 5076EBF7BB068C3D6CA62E2FC6F956D35D777F69EAFFBD5696D74F3A341228CA 66C9E286591E38B6DDEF610971D9D1F711DEF544E433EC4745C1D14DDC381520 BA29884834B90B4C285FEB9AD098449C4824375D6A17E147C5FDA303E1523CDD C99A81BF5D44D4FE90FF4F19D301F8B76F97E3AE0BE6AAFE084266D3BBBB32FC 8D1C279167998A1816839A88A3D4D2FCDD33D9A49165A7CFBF46D3234D005B91 C9791DB8EAD1B7B0D16BD7EBE986D8F92247954BB0C38385295FCE9152B02C1F 40074F171E8F9C392D9746E3D77D8C46DC7FCA00015EB1A15B14879C95814927 B2ED9AFF5C611EB9417B0B501B96322F7EC5A877D9DBCBD5B27C34B1C4939AC3 3A8DB1C022DFE023C7154271D4EEDD5FC6D59140DC64A1D7B0121BA080B86A68 5A981D92D9E630560CE6D4BBA9AEF413A165CBC085AF494B5439028759B41938 E2E3CA62E1C3C12D7C2D63609B6DF294B2C06868DF8B1D24F7AF20820B8016D5 02A391358D26CE305CBB12FEED9F8E579CBE176349A92466113602021AA71EA1 1AD0F11E6AECAB4559382D55FECAEDC26F5262F8BE7ECBC8A6F5483B5975E5FF B3B2B474E3D47B9EA951924A342A90218DC9DB1C2A8E04A4B27FA09D97CD8B12 582919236AD61D7BA88DBEA23AAE70E9CBDC091ADAFC992265CF1435525338CF E6A3D7ED1A14CC5CC164E51536E25BE480346BE351A788B872BDE3FD175177DD 70E275891DE1759DFAAD0EAB9229D67994AFBE9C15C20392253C8E2BDF2F7FA6 9BE6094D7583271C248DFEC5B4FD197147FA260636C769F160EA75F71B442FB2 EC9491C840AACF92881CBCC42C2D8267C4A911B71D036B6974F0408B67B753D7 472AD6652A1AD30C956C2ED929B6A4785251C206BDBB9549058F05709F24836A 1CA8AEB221BFCC548E77A584B0FEDB6F95B07316EDB3101F1B699C83E6E47FC8 966B6ED96C91298EBDB2767679A3A1372C430B03BC0974C7F49A9E2F1FAEE509 AE7A6B28180A132D04697F10D42B3241BED11F8ACB9C24802AB71BE75544C59A 21806A26533FF47AEB55E074E00BD3FCA07809310C3BD07E6DDE6A978154043C 5CAB655B7E0D8DC31843398C97CFC1D611761B4923B6F2BECEE22A7B1D8694A3 8E55388F420E353115414768BFAC7DB0EC4A9459E079BDD374CF6E9E0C0CE5C6 1B9D472BEE95A3F1351B034C4F561012185129540DB95EC415F36F48939E41D7 B8408FFC1A0EBE6C9BF115CE275A8BCF66EC243C867E70074D52AC72774E159C FA0C2D456A087C078E1AA583274D1DA7C39F677499C94E601EBBDE029BFB315D 2970DF345C37F3BE584E1854140C999A34E0FDB1E4344CA091081C72E9ADDC61 E51E1E7356AE738DE3449738CEBD46839D564027006B16C6787BBFFD74EAD0FE 1DD37A0047E6CF135091B147EE977961ADF55EBADC3C8A0B27BA40DC9F48BEE6 183AB7DF4A3FF555D0D50106B73A9D1AA6302EC43DB53EFD7CEA1DFBD0626455 CA7F6440488B3FD916E6EB6835522BD9169418C7CFCE957035D0ED122CFC04D5 D763FD9CA1D8876B9FCF7B4FEEEDC2875F4D6B2C1EA531FD8597DEEA3BECF729 A8FC7E1130912229F70923A65A411E21C4185E67F416193E56F5F74A0C8BE24E 7C6DE4ACEE749F72106A45AE3107877FE478F253A8FA6E3CFEE11C50988C02BD 572BF568C829253F3563B4E470FB1BEBD67D54B2500BD8818D50736A27C959D4 D2BEDA5585D9248FAB2A2B724FB9C64EE1F22CC9FD95F7E547D137BDE120B70F 6E5FE2253CCFE7E2508B23607D799EC63B8FD94FF57EB436168B2954A0D45D9F A21921BFA6C2B74215E2966EA726031148553E30B0D2B430F72DE725C3D53D6A 5EA010DAABFA9D91BA2C22E56C706E01BB9EE2407441B18597F20552CAD64204 EEF648D089FCE72951CE48B55A24FF7E22ED56C0CAD3DBE54F4F00948EADB312 4EF1518BEB4F4D4E7DCF2C752A83BEF181F39ECEF2A1D8305FDFE3CFFE22B8BB 454E0F8179AEDF45E00FFCEED7427C15F99EB399AA2A992849D1D97640C3753F 7E4B1703F3F1A0FC1010D3EF2646DA4423C56F0AE84C83459C3C84F0A31B1F19 877CB5568FCE0C37E49D0C8700AC31D70DAA6F297721E359871E452B03F135FE F66BB7A39BEBECBDBFBCA98E364A6D80EBA20792F54FCC9814AE2A00031AFC73 620BF3BF87C03A06346FF3C0D745064F575C6EA42EC8E6D74622FA57C0BDA324 4FE481F9DED0D26A775DF548A9A327B95C102221253E25533C939E8ED52D9830 78422CC904AE6AAEB2C9D60BDC86DBDC1F7E675E45301304BB3DB866C3422528 751D657E8308C45D99A95B6DE948F8F3212A4C11D9126756DDBF61B424EA4016 421720EF95CF47F56C5D0F76ADFAED8669A6A85BD25C3A8C3F65887D9E060157 60FCBB7935E68E817C3E992AA290BE0F8ACC2372706DD0C7BB959FEEF05EC2AA 75020AC0156CA3934DE290AC0FE9C50BDC3326222AE7F80D1AA723F1677A9CD6 6538238B4290881A47C67151437306F37D34457749AB0730F8EE813E5E30A378 75E0A29E5E6FFB68ED7C13FAF68056E5D04BF0278FD6455604DE654B0B7D0DCB 1770301DE0DE626F63A0AA9ED81E91AE29AD493706B8AF48866079B88CD98CC1 540A771609E992EF2A9D39AAFAFAD2194528E1F2ADC486385B92F16C3C0CEA56 024D03A955CCF76B337E5F62A953DCBF132089E46829EC6A77D8303C4DC2E437 B32134D8DF9EAADE281845C43D3C37135D33077FCAF7B3EE825DACE9BB801B35 025438C52B264BB955EEC3951E38C20E3A7C78160FCBA5E532173CCE46C1C24E 9E7640011F12B196F9844D7CA63A3E6600A29E31AD95CD7FA12FED0B10FCF9A9 0FE81AF02067608C15502D3FD6E598ABF676CC9BF5A69C9AC7D7AD5FEBE6F1AA 8301E9A139664B5BEA53C755CD45C70579D71F8DBCC20724D51101F87BA37D46 2F3752CD5A96D58CA5634058C711BEE0B3D70F86E11FB6C6995516CE179E6FF2 6632D9FE2B6E5863646EC391755A56CADC20701B404BCABAB2B57C209E083B3E A058545FEE90F7E81D58AB8FBEC1090973961481E0D91D6D70AA96B30D9FEEAD 290CE6BB038861850E4DDE34B9B2692D5A49FFF527BB632A8F41972596404674 9FADD1F7D69A496E6D0B663D4E6DE927D2E95D12A91CE3806640D64BB3A0F475 856DA5772F31EAF64D686FC1748FD07420E3EA75D17CF60CE933A0263F069E30 F66C9938065EFE94E913AF4EF0310CCB9F73FEA4BC65387EF19F92AAEFB93C78 3F0A41450391033152DE8D995AA73F6724AD2FA101EFA67F0032601C92512704 351CEE1AD33134D9BEB63448C0ACDF3DF3074CE10F4E9ABBFB9A87DCA6F76CF5 EEC9D84E3F5C49C50BDB2E3E774954EBFBB607F24EB1EDBB4E170DD080A4E6E7 06F06BC56AE52A69CEDDEE709A9FA231E18CFC480F50C772B8BF1F245B4C4F82 C05DFB3B78F96B154491843A5957E85594236C02F54C3BEB84C9BD412BC08113 E8AEA1EC49268A4DDD527984EA21A7B5017BDC93305C4D9DEB7FDB7D347A3488 F10BEAE27EC7EE52CD612698D1213CCA102B5360A1FAB8CF0E009CC38FCBE9B4 CC176BDFA6850B434A1BAD3B5AF1CE529A61910F757A4DDE0527F8E2072336D7 0E3CB40218CB6C4B2F4D9AFFA809685CD265068B8EFF0E42205DD534E0AA8A86 58CD5F0A69EF08F6284CFCB5BECBF3351AB1870042184E558319150EA03EECCD 8EC147370EC583641895A5CBAE71E7455648B33F16C855507B1DFF3399352C4F 13F2135EF94B10ED98565BDD10E99C8BDA017B48407DFF1E815EBCF27B13947D 10A9A545562A4E6D6E8C5BDDFA363250565A2B9E5D0E56ECA71C18785577B1BE 41A2A39F754B0B50E230028914B8BB54ACE5C0C7DAC6740A154C1515E57259EF 392002AE3F7E0DACC76D16F95A17A9025C1F443BDFB01D34AD898F080B3C6ABB 10C9C7F773E93BAB7B26A745B11733B888DCDE4BA060750B9971111BC8F9B446 1D65474BDA32D0A3CBE52E027EFC9FD69AF587009C9F8AEA9C436D858A0BD3C0 847EAB8D00A99ECBFF1D8831F58E16D2DC863C23FC88743378D61716B1B7D0E0 5B7DA8C435A28E751BAED3384C39E4EF0C8D05FA03D1737ACEA08206603E464C 17E0783A8EA1F6225CD5216C2E8CC1E070C988EE1D663426B1B69FC297CB02A3 A4A9DDF70A3FA3EA44CBFF0A608DCC5F94A8AD8E25467151732CFEFF4C1CF7AB 8E3B853271F9C28236CD5C4B8FB258AD53E534B0363185F351DE47916EEB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.0: CMR12 003.002 %%Title: CMR12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMR12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR12 known{/CMR12 findfont dup/UniqueID known{dup /UniqueID get 5000794 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR12 def /FontBBox {-34 -251 988 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR12.) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 48 /zero put dup 50 /two put dup 51 /three put dup 52 /four put dup 74 /J put dup 86 /V put dup 101 /e put dup 105 /i put dup 108 /l put dup 110 /n put dup 111 /o put dup 114 /r put dup 115 /s put dup 117 /u put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9C535A5E57376651 F6823308463DC4E0339C78699AC82C769542FD3B410E236AF8AF68CF124D9224 FD6EE92A38075CAAF82447C7AF41EF96F3ADF62F76FB425BEDE4C4124E7B1E0B 8BF254D91912D3A99557F5427907A56514C5A3EB961B94112077FE9417B70DA0 B2E1C1FA3E1D6F01D11F640CF848E45BE3E205258E64FE36AFBD4DF4E93F6B1A 966C8E7FBE2CC8FF43C1F67BF6C361678B5E90F4BA524FE8A4CAD6AB28183E6E CA6C9636E884845105595A2E40CDBE8D4807A81AF4DB77B31873FEB221BCADD4 2C4669459704CB58A7BC230FC59F867EEADE660E49AEEDEEB042BA9A7DD8193E 56C3A36A1F639F7EA512EE4BC6992F52C2FC82A890EFDA730105B0AF7B819295 EE00B48F64C2B5BCB275B1DD62F289CDAD4AD9B7EF057684642FA6FA6322C277 E779CAC36D78F7779CB6DE12638B3C65B70C6B5F8A8C6421A379719B8DD44973 5F52856A4A29B2ED37F2B1FBE6EF4B79B7C0CD6395C756A00FACD763C235914F 847D1D99831023CE1FD89EFEC83AA7E313131C0C197248605EF5BA773D0A4000 72F607551A8EA6F0FF19441ACA179177D1FF7B423FEBDF58B0C19CAE3C10EEF6 3538D8FC4762B77C5AA023A8186C40D0365A4487DC3564265B3DF908572DEAA2 57E29EC669DD72974F806EFF5ECAFA9ADF1F9D2A63087FB7BBD100F0F81C6FFB B1EA1C9DD46548AEDD147EE64B1B4894972DAE1DC3E8569D6A3CEF9F9E46DEB7 547E10BB2959D374A33E47C58F1B20419920AB485F166062FCCC08EB5CC9AC88 F388F0C0155027B727729488E44CCABB7064A1432E179189C4627453C5231535 47D1F2B8BA43069696830CBB6E5F9A135CF22D3D1FE490A3A63C088EA32FF444 24A2427BBA63033DFE2E06DF8CE67949B6AB02F26335A376B57376814D2A7DE7 64A4347577EBE9A6E33DD2FC214A09C6D889C8FFBF1D567032548851B8F97204 49E215CC7D222F593E1EF1439ED60AD922D41E0E9EFB5CA48F2FEFF75AC5FEE7 FB6676D8B8D4DB6885FBE8B61B586313E4DAFB09D94CEDC0507E93000104F3DD F83865A2C6F6A7DA8562BF86F5DB233CC9B53391273A1462E40876A8AC2B098A DBADD5A160DEAC061F86A5FCCAB495EF8A9D121AF07928EAFD56F618E4EAEA97 CF89A3AFD406FC9DE1E9769C1E1EB83BB883786BC075EB5DA2692CD59C4DD7C1 7FD2FF9B18AC740A390C1DB38670DEB18C67721A1DCD502FE7368F47DB4281D5 459B3F020595FA3B10544AAE9EF786A0645FB7C9BB29D091E1432CD878A05918 1665643005BFD9A4B0FFD347ADC84CE22D6F9AD4EDC05E8C7179DCB360AB57D1 6ABCD200A4B4AD56825DC345984D9A3DE11CDA5E9EC1E5006EE4181E4EFE0846 67D8C27BEE8F84A1E01947E945BBE988702DEB2240C4BED952E433E5305484E5 71965D3DE95C4115FF78CE9EC18E323C599727C8B93CDFBCD1CCA780DB8C81ED C4B5E596E1603624308972FFAE9A57B0EDB51FDDB6E23EDE2946F61BEB241345 2A192D8CAD53E823D687F9C64A70A4B4B703291FA6317C051DC6A44BCCE0288E 3839D726A8F2E39BFF429865E95C726E808E02CD06F36C1CC9AC77999F8E28BF CE9D74B699CA982479E9D0DD98EAB24D29C981EF0349721D6819549A39413801 F80182D567EE316E2F0AB208068E15693E4C399A381BF9BBA625E597E6E109B8 16F3A84C8EC92F2ADE288821092A421A8D3B907048FE947230810F0777EE2542 29A3485223FEA079B359034F70464DAD2F0E420271A4E0CCF57A0ABBC20AB327 0CA71B292126D395E0D083B19BEC6B48A9DE2BF470C3D01A8C3F52075BD4BE02 A0C518355814478202FD4762EC542F8E7B9B1F7824F0554660CEB83E35635E1E DF0D03C94C903ECB36B4948ED98B6324E0094EB1DF70863142D4ED3A932D7346 39D69F8F044B6084482D7748C27328AFD24A3A70B99D1F7D32CB984488672254 28B6A9E9DCA2C9FF6A1B311D72413404B3CE5428BDB7FF3C36357D7975184F56 FA6B32AD54C37D0AF7576663AB1397B80D4E998F0B4C4F6D90B483029EF2EDA9 D4C4204C1546EFF3100629453EAE01918D09FE104E626ABA38646F17B6A94CE8 116BC7A8D9C319434CA5B830859B4164DFADF1D7C3ECA5C78D8DEA930EA4AC3F 59DBBF3148C91A2E807FB934E3439D4F67C6DBBA9972854E6E3688E1E0A34B74 482217CFE031CD7B5DFEF727C3EF8DAEEEDA08F4C90289E62FB2AF2357EB2E45 4BC547980FD479101FFEEE477AAC6268DD659E8DD9E244676FD3C6909713B71A 323B211E571BE711D103FA23B5B9AF077D84E2D20FEE805E81D20C03501F0F17 C3B081946CD0FD577F00E50B76CC37CFA97A61B89C25DD43911B28857284BEBB 5BEC61FFE3A14C64BC5425A7A82326617F6F1FA4FEAE56071C9F559F91568179 46369B394A5CE96FB7420FF8AB7C61CB83492FA5AE4A4B0799578594C9EA67E1 E54498AA5CD6ABA34AD3417F04F5D8D664A7EB39D41E2D17643CAEBBCCD9C38C C5C9541641A09335EFBCE0D276A54253EFD68141807A66F1DFEB4BEA5889FFA3 4D20BD52012206A9F8D3E0F6AFC03FDBBDF3E51506EC6336E249CEFB571AB84C BDF8E471E3795C04E38A5306BA6D450D72E50910D1AC385BB06CCD4B8E433A32 5A4B7FACC976BB31FCAA1E62DB2C4FE06DDDE7367930E336B49F47DAD91C8735 9A35D80CA2E117E86B52E41E9278046ED923454989E48610ACB3B1663F197117 52659A9D7BFA561C7ACE0771794FC778675F83C5EDCB132AF124C7E6540A140B E0A268836C73A3C746DC964E482E63C56C0D396515283970FBFF182F9F684FE2 655FD8F5D057D22246DDC3FD11B77552DB4D90ADBAB77BBB1FB1592129DE0AEC F822D7D36E52BCDABBD560B403A5C56C5E1BE789C3AC049318C7FAC5E5861E42 FD66C3C0F46361078D7E036281682BCE9BBF77983C93ECBBEBA9B359769CA442 87FCA1B98F4EEC4935CC93B08AAADDF355C99816453587310F08C50B9BA3D107 5388A1F3AED2AE32BEFADF0285DA90436D1D7EA85D7B9B6DF2AC4B778CFADFF6 6EEE54D1A1C5DEE3CCA7EFF57A7C2931933CEED90CA26DAAB45E4388EC4DC366 B9E88518D6CF094861D2A59282044CC06E63EFB390A6DF4BA5EAC7CE39E1EE03 3D84099F5BE96612789AF3EDED07266EF10A0FC23EA1EA97040B6BAA63138B1A A9CB8F5DED781260962D7618EDB200C3ED976033E8967A8CC676E9C11F74BE34 343A7ECE7EE97E8F76F7E95517A6D6163527406EF5A669535CB2BF4031F29046 BB2D0FFFB47A576F5EAB1D00A582965C56F28C00B3BB7BE2CC8D8391F789070D 775EB775437F0CD53DA840BB3575104B63E4B0BF14E3F14B320EDEF65FD4CAF5 8596DA491BBCF3153DED3B718F833D106432DF8DB8B8E6B34D5308C9010A5DD0 7E0E53260BB84BAB3EA748E8D72F75901604F80F4416920D69B4B983DCDB72C5 E9928F01A4A85954FD74578AE336C782CDF81D1EB7EBCEBFBAE7ED8AB4862584 397928F502D65139CCD582CF0723C5262EE54B9D2B8C39614652A8A90E1C3B65 7D26B99DA298FE4B9A7E98848F619C9BB4FF9FD215B72F99506F06355B332689 37D80AFD9F9ACD8172CDC51FCD3A759ACA0F7D4EBB07840840EE42C2D5B8B257 2C6DB3A7657B75F2F0B9730A20112745703E2D0FE709436CA6A5F36F59E64D9E 37C0A23D6D289E1AC1DA273872F5FC5C3DA2B127F078A4D7AB3FD7E124455817 DDC796D54EF26A1FBFD539D3A21B86DD4477DA49213259ABB3FF241424F2BE5F 89151E02FF87E0BEE26E85C0E518D8BE7CC9214B8E9A9EA1DBB49C6C212CCF08 90C0F23E9858947EE344062EBD9C574979087439975EAD4E85CD7BFAD3C91CF1 EFF577843AF1427D06CB2F3BB519ED1591974218C43F0D2038665F9E2E3960B7 FE68CD3CB2DB6B36C7997C6B21EC11CF1DE049541001FFF26D14C255E3AE862C 5A5701292FD2FB3D04523D6E2F3547923BB117718DFB6E6520F0D0B5450C695B 8C9242CC8671B7284CB2E1E9EB097A3DB1B4D5E8EEB93B4DC7E38C0A10474665 54DDCBAF079B92EA494F6FA75A84C5AAFE280284D0823D7C22249A21044BB0E6 4062074ECD17B62E03EDF4945A294BFEFB51F5FD870D9D7230FC91B83C1D85A8 86CDDF326FC90E04362145D6E8630C50594484FB829DA18F5C078F2EE67D2F2B 08DFF39AE2E8C9741FA989AE494C7166F122D2C5F71B97C973B7CE8500E9F87E D59C30F2E99CC4D34713DAB680598F41955FBDC26A14CF1E73D6BD6B9AAC8D3B B998F2D0D647356CD236DEAD6561389ED3A6746221B0CF15D6648412B35A6B54 6A0EF5BBB34AA376D9BAF025BFC650C1B74333CE85413D0EBB2F4D082A26A5BC 3C0A25D2B12CB159F140E00E262F1CFECCB2C802FF94CD34DA0CE9B4B3830FB1 DA85B9B670D5169928990A2E9CC869891CA2FFAD9774E6B92549644DAA5FE00C A5BE4F5FF91A0B6D2FD8F96121D766391EC4ED3E73DADD476B7DAE1A50AFCD98 DB7E27E44D30416088D9BC07D4661D9ECEC0806830ABF14CE55AA3CA2DF66E8E 748B8ED46466F1EEB072AC0674FE6FED231E0DDA59ED7C42BC05EF00E176050A C4834D893DE42474EA20DB1E25059E84BD137EF65A02CC295B0FFDE4CDE95879 0FE88BDF2519ABAE7F8CC3E6386ED35E04A14F1E3861922645E3A3F43B48A5AA 1999A5EFE192515FCC625C829FF5A7B337AA422F5E920545F9BB269C869A821D 6C4C26DD2AE746EF0F0B4C1E7E9871ADB5270E1CA9BE28225F7A0370D4C52422 E25263EE101C4EC1C7811B05AD42F364844A56BB91EE72FC8ED53CC6954D2BD6 F945D739BE4C61E36143CE890FC0CBF2F610018D678ECF7CEAB18FF5A0E48F76 FDE2463D40A99380D679B3B76D39C664F4992D23E5988B0D1AF33DFB04894016 E852EFD1EFFE586153C0F31ADBDBDE3F73FB49C5EE64D0D02E1504248FAFAC3D 903FD44679BB09C30288139B41B1E90A10139CA3172677250B16535A1F3E5E4B 6F4264DE58896E66051FC677030A121C5A285C47B6129CB5A3998830CE070D21 2F093FC1B44089F603A21F45F60960F134A47226874C737EF6C085634B0A4A66 139420501351F737A73F39D960EC38420BE46E5B09D298E7C16B8E32F01507D4 0141FC52DA1DE718D634AD9C8B00E46EEEF84356759324D2B9A3473C5DA38DE9 E30182B87F91B6A7F7BACF29A93B44C879CCDEDB063F9D2E51E0F1FC9F018FE1 2433D85AF24B55DE3A61C4D0A2DA4FDE933F5F6FDF17E9FA9932BFC46E2D71F6 585EEF5B2E4E89E797A24B799D7F064DD1A817A53677FC9EB8CC3E7F93FE50E8 D50E3191052943FD6C98B573BDD1F6D70349E1F8011599E3F8FDF1D6E80A710E 51E434E85801617C6FD8ACCF1B77B4BFCCDD35CB4C0367F4EB4D8D9DE8284D5E B4F43E2F8320C2C5A9AE90ECBA7E65D377E91DB69FEF27069235366AD3E126C3 A73CE97F4C90BA00D206FA012C327FD69EE59AF4470A315B1799CDC0539BF90E 512C8FC3BEFE4D1B01D969EA9E3FEF976CD6E0FA4C9ECEC955B265CFD58AB8E5 F7371E479279EE14B689269205C5B506940606CF3E24A1E7EFF3CA96ED30AD6D E243DE57690C3D69A401AB3315FA49E4BF4ACD4DD1CA39272533E82EFDD508E5 1C2CD286CCC5DE1202C7C7F654521750632EB637F918667E2233A43DF75239EB F28F3129EB5DEE2FC5BFC331FF709B0FE9B327CBBCE98BCA2C861C6547E50407 1218CEBE6EB5F9BABA4F2E11BCC6FB553A544A567B459E06375102C69F8018DF BA6A227CFB13E2D74E6A521E01B74F2963E9A0A1C9FD87A88EE6356E3BFABF55 BABC751D2BF85E6712E8EF57914920775906662E4BA68FFA21AD422D34E15578 43CA0568B431101A1194F8AB1EF25E886BFCDFC10F4A5EBD9530816548BC298E AE4A0B6B52B8B59C644C409B4191B6F4203F52314F2675F02AEB65A72C66E92A 2AC703E15D8D381522C0AC30C165B822A9B8D18CAECC094EDE020756018DCF51 D0701B507519C4270B70D8CE94B436F640C15872F9B5B77892AA3D110E4D6A65 8F0815C61A5127BA25815378683F46E69E54A391A8675977E7DF9C2D4E6FA991 9F029E50CC2F266B31EE9F9F24452D5838905F330CB7E416B8AF836C5AC26AB8 BE2ECC6EA4BDAA08C30995709E225C21D35DB6369167602CBFA8DB2697635925 969002CD1BEE745DA2E56C17EF3F0C05E3847147F86963C37A221C8827195A8A 3D38993E4939AC915BFD9A212F5FF3F826F742B952018986F9FBDDB69C3AC65A 845F7F33C55D4BE60A1817EBBCA7E1538E8087E1BD5C083A320D52953BE65F31 E8339C612A510B59CE48D2EF7061560C4AD258E7DC59694493E3AC878246F37D 6DE89253EBC8830C6B209E818213C4AC4CF1F391AD91D57BE76FB0E2924A1407 E4A949C905E44F54EAED6419F13D59942C8079336A172D4758BEB5D3E786FB93 3CBE4FD2EB53E4E1DAC34E821EB30FD44BC6CB4298242C38F848FC23AEDC9733 52BE6F32E31E25F18301370F8936810B0566B664B042C7AE0D78ACF0A87E5BF6 F9B66E358168B2CEA30DCD940074F3ADB793CDB136161FE2522905E87B8E463F 95D4DAB7E14A3DF7BCCE8141C5A08FCFA2BCE9F2D1B05A7642E75877EB840149 AAB007CD239AE47AD115929427717F219B0A8907F0EC79ADE1B901DAEE87A2F8 39361DAB43DFFF69650F601B24061A9353CFD619FF9626F63275FD09A5B13BB4 8B3379EC4D147C41197E8387FC04DA7BE409524CEF74EA91DC066808A7FD0EF3 957A44E2503EDA67B1C61827479486134E922E560A673BF314D601C66003CD07 55569085AFC8428389A140EB976CCFB8F29E27587E46C413ABE2EFB51AF5913F 53EEB74063162E0BA1E24CEDCA320377D3E11BD374F0B44E132A5C35835B6E2C D32948EF9DC7931D104C1385709DA882DED6458319F21C2329938396BC074106 CB9CFB9E0A915F8DBC8435F386917AC87A2BA45D857EC30ECA66FB4044F5439E CDD556B82A0E43418D179AD883C85AC276E1190CEC242E3E1D86E725ADC39E46 BB6C47FE9E17E29F8EA81E870302A00D91434F3B7A05F243176E6EF1082541A1 B9052191EE5C2B8E94A2E02DB65FC769653CA8D1C07A13CB853544AEC7FC35C5 218DE3128AA31952DCE19C55C23FD69BCEA2C661F57B11B8F9E86BFA718D1521 3346E78C701A5E51923D6D937E62FDE3669B214D240538F069A100A542720A86 31DE88116DE775F7ACC2A49EA6C02A24408271A846990669F2AF60AFAB4C16F9 7F4E88E917F0FFDCE68F22998AC0AF2A60A73258C3A4BBC42A2F918123128195 196D0E150D79AC3CF4628503D1F3FC528265ED8324E56849A47B3B07C29940B9 1BC270071E221D355EA51E9942D3BD7F99816304FFFC8F5B036C953B38759341 ED5D7B9C8E6B70C409DD8362FD291201CC385E4A98D73E8518A4C0E544152563 82032FBD2FCB6E403D34B85ED4053A8CB619BDD4DE001F4C3007B1F317579651 E6D6662189CC2D95AB85D7473F65C5D7B4AC63B0FE928F3400035D5A9D443D0D F3532B99F3AC26CB25EA3CD64C341159061E02EFBC7C033C05CD919BBD827A6A BAD50D9C98DD94332DB4C7155F8A52013F9ECB7CCE3CFB3E667C57B022A0A753 A45E41A9D8229D5198031ABA3DAAC142AEA5FAB6694A6433629E15AE45A67FDA 34DE10D995ABCAF45FBB3B6B73E80D05F4C51F8C29D4B0F67C8A86432A6C5E86 F0126AB25A5CA2875B48C61CB8112A4CF9AA08F8B0157396CF63CBECDB8867CC AC10F060630C9BFBAD84B1FF01C814878F0C177F552BDC9BB181B14581C6E968 DAAAB2896FCFB745795C4D2C87CC15BAA041EF80C5BDC12EC1F5786BB41A5A21 073EE0BC436B346E014DB4099EDC67BC432E470A4B779FD556341061CA3F2BE8 EFA332637AEC878C2BB189CA3267B2BE5B8178E6B7889A33771F86276E6F0B8E 8E93B816AC7005575762EF4DE45E2794B7322F9B6D8E634FB8FF250D638EB502 818321B3C46DB51B8EC6C2EF1D05C716519A3BD6B12A67239898F8A012A3B5F1 9E59B54BABF9A72CF35A27CEF3AF07C2E4D6BF254DED2524F3068203896C931C 06398C1C3C2881CA864CFC4D243E945BFD8ACB9AD3AB8669A6912158FA150864 D96E34BDCE3142610E8A2BDD2A7DF6A26B718471AEF042F641D019829AFE8637 F8720D2DCC7342E0038D9B43B89953898AEBED5F09DEA465659EBCB83844DAAA 83C627DA47D46ED564CB5AF76309E2FD9E17724A0A893EA0A4329E978212DF25 C0E27E49B63FFEE33D72E04BFCFD84E8A39BFA23D8E7AF6987C87EE06686EA04 14FEE15429BAA6D979F242F4C431EEA7F8DE5A56B3CF11D1507DF22F7B2B4341 D7E72BE1CA8BEB4711ABA2BD032463EC1109E10E12D62D04BC1FA38CC0E6E3AC 0A6629378741E499FA56EFE26BD5D81A2A369BB6F2FDD36DF17CB0A386AE3CCE F9FF8FDC4A8972CE4C48E6647269D9433E76B12412CDCF9789789BFCB0C730C0 AC0378C1D874FC9A766D94D13F06FB2EFEBE97E38933D2F0B71984339FA9DDCB AD23EBB33DEB14341BE3E58999B740458C1D31C148008EBC95B1715FE66E4544 5721E1667C3125C6B2BBE0C6FFE6189426691A7771F75B76060DE2F326ED81A0 6403405A670AF7D7D694CD8E16EE63879F4C6F95A675EA0D2F5D01C7F3D7D838 53D81B570BEA4BFC8AC0279B7D1F7AC7B192873382E9F594B878F6E930591566 9B93F4116218F6F1C0F98A801786D767CED12CFFC95F3A573A726E0A81129869 01D0F89F2B249EC03137C3D05E95B9ADE0DB5941B2610317EB5A6967C88F5EAA 6F3AD85205C91B6BFBF5728DCC1CF564674AF97D467660F8F92005824615CC5B D8EABA48B0DE8871E416151AA005CF3393D136B87307C25B82188571D3161410 85A956927F583F34BBB23551C2C62138A2064D70EA258AB8C171886DBD0AAA9D 35B69196B6BB201477FD10F39BA156FCAEEBAC8B77A083BE199C7E86F173EAD1 6F61F4AAF088BB71CEB57FF0CCF01EF2937CD7BD4685143990BCEF2ABE5266AC 050B274635F92406E867B20048162DF4599F2820FD6EBD0465F634097AC8F836 E17B6D3740B71C2D21847A702489B239F6EF8F02EE7E486D9F9D0647BA8A3C7D B41EE31ADFBCAFC3D1854CE07BC3BFFE7FAAE38C3F849206E2DE9CAF52A5A7D6 BF8DD613A029AD2E5242C8E3499B1A666A662EC2D07C7F53BC1B19AC0B614A14 89F271AE9AD06115E0F188342E20D27F355B23874EFE655A696DA89A091886AA D09080318BF89A03ACD9B9E6E1E039B37B5C88F17579EAB32CF8619B39E91F9D 0922CBE43C2347EB3BB82558852D92D995D5F14ED59A308EEDEBD5594A6FA432 D598237172D1331EB90043662B0307A609E0378D316FDC2440241C76BD052EFB 7A806C2326A403ADD14A4457F85C2DA8D6E5E89D7C52B32BDB641F5146C6E8EF 226EE47E362D8F07D3479040089051A5BDDDC104CA3CB2673516BA61DC5259FE E4F9ACD9AF7922A972B4B11D9F97F5860C205314B55B63D5B05B6F68461553F6 74AAA475F1699C7BC7DF7034367DEE9FA5B06230EC58050F4282C4DC849EEFDC E4A2DF0CC5C0D4DD71BEE29AA08A9A1D1C8A6952665E034F93966D3D8746E6A4 E1B87A34158F72BF6AF182703DC53ACC510B839BA0D30A114B03AE9E4580FEA0 7898BCBAAB7F55FFEB3DF65D31A17092E5622EFBAEB050AF77C03499947062E3 0AB2724E042A796BED919D6B20CF7D725F06244A44D670D4A605BB89377E90EB A7470D58979386B7DA252B4BABEF2C61D8A07A577FB87F4308593EAAB3DBD4DC CA9BF7C39C49AF0FC4EBBAA2A83D876FD9E39F072EFE7BC02BC2B64464674B5A A7606E434318CD4AA8DBD50F78DF37847AF377B3CDD398DFC2D312F105258823 8678578406267B95493032BE79C40E914E6BFD3088A6E6A36EFD260C82B28DD9 2755B89D936803BD3896087AA292118FA9E5A62F64EF5974CD8E821E5DAB6D7E A7B7F2BB1F45423C0482170E375DC2B4336AE9080DEC9B67AAF54E186E363061 25D0805C41B86B2162018E573B99E0299E359E019AB1E05390CF03A823D8FC09 15BF1136CE47DFB8A9CC2EBA8664C279CEC216C9A0AC5FBDEADA05F714A23533 7D3FD8F57523055982026195CE819FD7A548F2D3D4653D143BB6977FDF163F03 DB8739F3B14379D6034726AA0C1A0F403751A4D3817E2C766C7B8CF6A764E1DA 52F3EBF045FA1568F4A56702D94DA948F585083B49D8C982F43DA91EB6968746 937465ADD9DF384EB17552847E3FB1F860BB7B66A6B02C0E9EFDD44D16F8EDE9 413043DBB3380589A7862AFFF381610CF66EBB48349D5695D01572F5BCF98BDC 21A0CB844930558CBF7046F7998280BB2F6570DADA9375D383EA71B0BC01AF71 00B41D3161AD6AD074665BEC701FA5AE108BED942D51B488136291D57736A445 EBA315D417844E206C5C8E1B0AB05E9422470BD4CF6F90F065FB13A3EB3E2FBD DA867D7E5436166535F510620BEAA7B85DBA01551FF3B2778C3FCB66D2770928 D375866328DF4FBED8DF3B4FBFE3E1B9F09B4FCAD829599A956C6E2757E84652 EE44DE26B7FB11A6755ADAD3CE479A97D231E169BDA9E6FC452594B472E5AE0B 439EFC837C35230DE828C55078FA7D49C0136E46CD70635D64E59794A4D394C2 28845F0A1D5CFD9CE6B5365A8B2139B4447FAC23BDB6F88C7E5D46BC86E4C2A8 8E160563D1D6F331858E8B0F379B7E778BBC35D310ABDDE2CAF3B8F019989D53 70E20B2A7E2F9E2945C730A9E3A8B9524DE3F12838171EFC7007303EE4CE5E84 DECC4EC0C39181106C7C3EEE6A3083CB4A7DC8AA0334192AB1EBB28B11229551 DC14178B61206A6251CBE9EB98DE1F41CC02A291192524801902BAAEA8B8E977 52F85693347AA2AA6C3E9B43C8C0DA6A5E1E83849277A39C5B5EDAC81CAA32E5 200F05E71324F5E376C99CA85A9D9054C16D0970446390BE750D34FF69FA5289 49E84B5219B00F9EF2389155DA155EBDD6D35D0A3718146FFF61B9657D29C640 349344E1FFA43B64D35BCF9986CEF358D97BC986D96631ABED765BA36AF94417 C972310916B9946F10AF8AAB37B925481C591F4E85ECC983312F77052D98B356 F2A0541EF41BCA2AA6A48BD3A37FFFB07CE7C933BD984E17B4AEC3FD3C3B07C4 DA43D96980004D0D97A8CA236AAE3DBEC0525C4BB911859ECB71AA52724AD006 64AE326374362DA1D266897860B873470AD1A9ADF0B7AF361BD44CC5AF587B2E AE824DE05EBAC3E8121525F820178DCA353745685EBD9AAEE5E3EC171ED8ACC7 D58DCCAA37BA237958217F7FFDD8A2608F04CBC038E49798F8CAA32A738358B4 3FBBF13A273B61104B7D109B1A3358C2D7D758CAA6BD4341B63739954E4E6690 D83417A80C3F5E515DDD71A3867D82E4081C2DC07F5FFB383CFC80F54E09 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont TeXDict begin 39158280 55380996 1000 600 600 (cfitsio.dvi) @start /Fa 133[37 4[49 30 37 38 1[46 46 51 74 23 2[28 1[42 1[42 2[42 46 11[68 12[68 3[69 55[51 12[{}19 90.9091 /CMTI10 rf /Fb 193[71 62[{}1 90.9091 /CMMI10 rf /Fc 149[25 2[45 45 86[45 12[71 2[{}5 90.9091 /CMSY10 rf /Fd 134[59 59 81 59 62 44 44 46 59 62 56 62 93 31 59 1[31 62 56 34 51 62 50 62 54 9[116 85 86 78 62 84 1[77 1[88 106 67 88 1[42 88 88 70 74 86 81 80 85 6[31 56 56 56 56 56 56 56 56 56 56 1[31 37 32[62 12[{}58 99.6264 /CMBX12 rf /Fe 129[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 1[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}93 90.9091 /CMTT10 rf /Ff 133[60 71 71 97 71 75 52 53 55 1[75 67 75 112 37 71 1[37 75 67 41 61 75 60 75 65 9[139 102 103 94 75 100 1[92 101 105 128 81 105 1[50 105 106 85 88 103 97 96 102 7[67 67 67 67 67 67 67 67 67 67 67 37 45 3[52 52 27[75 78 11[{}62 119.552 /CMBX12 rf /Fg 135[102 3[75 1[79 1[108 1[108 4[54 108 2[88 108 2[94 29[140 138 146 7[97 97 97 97 97 97 97 97 97 97 48[{}23 172.188 /CMBX12 rf /Fh 165[56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 1[33 68 71 59 62 69 66 64 68 7[45 45 45 45 45 45 45 45 45 45 45 25 30 45[{}37 90.9091 /CMSL10 rf /Fi 133[46 55 55 1[55 58 41 41 43 1[58 52 58 87 29 2[29 58 52 32 48 58 46 58 51 9[108 2[73 58 78 1[71 79 82 1[63 2[40 82 82 66 69 80 76 74 79 1[49 5[52 52 52 52 52 52 52 52 52 52 2[35 32[58 12[{}52 90.9091 /CMBX10 rf /Fj 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 1[45 25 45 25 56 68 68 93 68 68 66 51 67 71 62 71 68 83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 1[71 1[25 25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 76 45 76 45 25 17[76 76 51 51 53 11[{}93 90.9091 /CMR10 rf /Fk 138[65 1[46 46 2[59 65 1[33 2[33 3[52 14[88 11[60 21[59 59 59 1[59 1[33 46[{}15 119.552 /CMR12 rf /Fl 139[63 64 66 2[81 90 134 45 2[45 1[81 49 74 1[72 1[78 12[112 90 2[110 6[60 2[101 2[117 1[122 65[{}20 143.462 /CMBX12 rf /Fm 133[103 123 123 1[123 129 90 92 95 1[129 116 129 194 65 2[65 129 116 71 106 129 103 129 113 9[240 1[179 162 129 173 1[159 175 182 1[140 2[87 182 183 146 153 178 168 165 175 25[65 26[129 12[{}42 206.559 /CMBX12 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: a4 /setpagedevice where { pop << /PageSize [595 842] >> setpagedevice } { /a4 where { pop a4 } if } ifelse %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 240 1799 a Fm(CFITSIO)76 b(User's)g(Reference)i (Guide)727 2258 y Fl(An)53 b(In)l(terface)f(to)i(FITS)g(F)-13 b(ormat)54 b(Files)1263 2518 y(for)g(C)f(Programmers)1667 3013 y Fk(V)-10 b(ersion)38 b(4.3)1727 3916 y Fj(HEASAR)m(C)1764 4029 y(Co)s(de)30 b(662)1363 4142 y(Go)s(ddard)f(Space)i(Fligh)m(t)h (Cen)m(ter)1522 4255 y(Green)m(b)s(elt,)f(MD)h(20771)1857 4367 y(USA)1735 5239 y Fk(Jul)38 b(2023)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 0 299 a Fj(ii)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 0 1267 a Fm(Con)-6 b(ten)g(ts)0 1858 y Fi(1)84 b(In)m(tro)s(duction)3136 b(1)136 2020 y Fj(1.1)125 b(A)30 b(Brief)h(Ov)m(erview)85 b(.)46 b(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(1)136 2182 y(1.2)94 b(Sources)30 b(of)h(FITS)f(Soft)m(w)m(are)h(and)f (Information)38 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(1)136 2344 y(1.3)94 b(Ac)m(kno)m(wledgmen)m(ts)30 b(.)46 b(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(2)136 2506 y(1.4)94 b(Legal)32 b(Stu\013)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)131 b(4)0 2766 y Fi(2)119 b(Creating)34 b(the)h(CFITSIO)e(Library)2256 b(5)136 2928 y Fj(2.1)94 b(Building)31 b(the)f(Library)58 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(5)345 3090 y(2.1.1)106 b(Unix)31 b(Systems)44 b(.)h(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(5)345 3252 y(2.1.2)106 b(VMS)33 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)345 3413 y(2.1.3)106 b(Windo)m(ws)31 b(PCs)f(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)345 3575 y(2.1.4)106 b(Macin)m(tosh)32 b(PCs)55 b(.)46 b(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 3737 y(2.2)94 b(T)-8 b(esting)32 b(the)e(Library)j(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)131 b(7)136 3899 y(2.3)94 b(Linking)31 b(Programs)f(with)g(CFITSIO) 45 b(.)g(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4061 y(2.4)94 b(Using)31 b(CFITSIO)e(in)h(Multi-threaded)h(En)m (vironmen)m(ts)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4223 y(2.5)94 b(Getting)32 b(Started)f(with)f(CFITSIO)60 b(.)46 b(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4385 y(2.6)94 b(Example)31 b(Program)86 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(10)0 4645 y Fi(3)119 b(A)35 b(FITS)f(Primer)2918 b(13)0 4904 y(4)119 b(Programming)37 b(Guidelines)2482 b(15)136 5066 y Fj(4.1)94 b(CFITSIO)29 b(De\014nitions)44 b(.)h(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)85 b(15)136 5228 y(4.2)94 b(Curren)m(t)30 b(Header)h(Data)h(Unit)e(\(CHDU\))87 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)85 b(18)136 5390 y(4.3)94 b(F)-8 b(unction)32 b(Names)e(and)g(V)-8 b(ariable)32 b(Datat)m(yp)s(es)41 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(18)136 5552 y(4.4)94 b(Supp)s(ort)29 b(for)h(Unsigned)g(In)m(tegers)h(and)f(Signed)g(Bytes) 86 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)85 b(20)136 5714 y(4.5)94 b(Dealing)33 b(with)d(Character)g(Strings)61 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)85 b(22)1912 5942 y(iii)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 0 299 a Fj(iv)3311 b Fh(CONTENTS)136 555 y Fj(4.6)94 b(Implicit)31 b(Data)h(T)m(yp)s(e)e(Con)m(v)m(ersion)65 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(23)136 716 y(4.7)94 b(Data)32 b(Scaling)89 b(.)46 b(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(23)136 876 y(4.8)94 b(Supp)s(ort)29 b(for)h(IEEE)g(Sp)s(ecial)g(V)-8 b(alues)68 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(24)136 1037 y(4.9)94 b(Error)30 b(Status)g(V)-8 b(alues)32 b(and)d(the)i(Error)e(Message)j(Stac)m(k)44 b(.)i(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(25)136 1197 y(4.10)49 b(V)-8 b(ariable-Length)33 b(Arra)m(ys)d(in)g (Binary)h(T)-8 b(ables)31 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(25)136 1358 y(4.11)49 b(Multiple)32 b(Access)f(to)g(the)g(Same)f (FITS)g(File)h(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(27)136 1518 y(4.12)49 b(When)31 b(the)f(Final)h(Size)g(of)g(the)f (FITS)g(HDU)h(is)f(Unkno)m(wn)k(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(28)136 1678 y(4.13)49 b(CFITSIO)29 b(Size)i(Limitations)42 b(.)k(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(28)0 1931 y Fi(5)f(Basic)36 b(CFITSIO)d(In)m(terface)h(Routines)2074 b(31)136 2092 y Fj(5.1)94 b(CFITSIO)29 b(Error)h(Status)g(Routines)89 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(31)136 2252 y(5.2)94 b(FITS)30 b(File)i(Access)f(Routines)g(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(32)136 2412 y(5.3)94 b(HDU)32 b(Access)f(Routines)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(35)136 2573 y(5.4)94 b(Header)31 b(Keyw)m(ord)f(Read/W)-8 b(rite)33 b(Routines)40 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(37)345 2733 y(5.4.1)106 b(Keyw)m(ord)30 b(Reading)h(Routines)65 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(38)345 2894 y(5.4.2)106 b(Keyw)m(ord)30 b(W)-8 b(riting)32 b(Routines)86 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(41)136 3054 y(5.5)94 b(Primary)30 b(Arra)m(y)h(or)f(IMA)m(GE)i(Extension)e (I/O)g(Routines)54 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)136 3215 y(5.6)94 b(Image)32 b(Compression)f(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)136 3375 y(5.7)94 b(ASCI)s(I)29 b(and)h(Binary)h(T)-8 b(able)31 b(Routines)85 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(53)345 3536 y(5.7.1)106 b(Create)32 b(New)e(T)-8 b(able)84 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(53)345 3696 y(5.7.2)106 b(Column)30 b(Information)g(Routines)h(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(53)345 3857 y(5.7.3)106 b(Routines)31 b(to)g(Edit)f(Ro)m(ws)h(or)f(Columns)39 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(56)345 4017 y(5.7.4)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(Column)f(Data)i(Routines)66 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(58)345 4178 y(5.7.5)106 b(Ro)m(w)31 b(Selection)h(and)e(Calculator)h(Routines)88 b(.)46 b(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(61)345 4338 y(5.7.6)106 b(Column)30 b(Binning)g(or)g(Histogramming)i (Routines)74 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)85 b(63)136 4498 y(5.8)94 b(Utilit)m(y)33 b(Routines)27 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(65)345 4659 y(5.8.1)106 b(File)32 b(Chec)m(ksum)e(Routines)47 b(.)f(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(65)345 4819 y(5.8.2)106 b(Date)32 b(and)e(Time)g(Utilit)m(y)j(Routines)90 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(67)345 4980 y(5.8.3)106 b(General)32 b(Utilit)m(y)g(Routines)h (.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(68)0 5232 y Fi(6)119 b(The)35 b(CFITSIO)e(Iterator)g(F)-9 b(unction)2154 b(79)136 5393 y Fj(6.1)94 b(The)30 b(Iterator)i(W)-8 b(ork)31 b(F)-8 b(unction)45 b(.)g(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(80)136 5553 y(6.2)94 b(The)30 b(Iterator)i(Driv)m (er)f(F)-8 b(unction)78 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(82)136 5714 y(6.3)94 b(Guidelines)31 b(for)f(Using)h(the)f(Iterator)i(F)-8 b(unction)45 b(.)h(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)85 b(83)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 0 299 a Fh(CONTENTS)3334 b Fj(v)136 555 y(6.4)94 b(Complete)32 b(List)e(of)h(Iterator)g(Routines)62 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)0 823 y Fi(7)119 b(W)-9 b(orld)36 b(Co)s(ordinate)e(System)h(Routines) 1992 b(87)136 986 y Fj(7.1)125 b(Self-con)m(tained)32 b(W)m(CS)e(Routines)f(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)85 b(88)0 1254 y Fi(8)119 b(Hierarc)m(hical)36 b(Grouping)g(Routines)2163 b(91)136 1418 y Fj(8.1)94 b(Grouping)30 b(T)-8 b(able)31 b(Routines)87 b(.)46 b(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(92)136 1581 y(8.2)94 b(Group)30 b(Mem)m(b)s(er)g(Routines)h(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(94)0 1849 y Fi(9)119 b(Sp)s(ecialized)36 b(CFITSIO)d(In)m(terface)h (Routines)1777 b(97)136 2013 y Fj(9.1)94 b(FITS)30 b(File)i(Access)f (Routines)g(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)85 b(97)345 2176 y(9.1.1)106 b(File)32 b(Access)77 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(97)345 2340 y(9.1.2)106 b(Do)m(wnload)32 b(Utilit)m(y)g(F)-8 b(unctions)53 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)40 b(101)136 2503 y(9.2)94 b(HDU)32 b(Access)f(Routines)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)40 b(102)136 2667 y(9.3)94 b(Sp)s(ecialized)32 b(Header)e(Keyw)m (ord)h(Routines)74 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(104)345 2830 y(9.3.1)106 b(Header)31 b(Information)f(Routines)64 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(104)345 2994 y(9.3.2)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(the)g(Required)f (Keyw)m(ords)51 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(104)345 3157 y(9.3.3)106 b(W)-8 b(rite)32 b(Keyw)m(ord)e(Routines)c(.)46 b(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)40 b(106)345 3321 y(9.3.4)106 b(Insert)30 b(Keyw)m(ord)g(Routines)89 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)40 b(108)345 3484 y(9.3.5)106 b(Read)31 b(Keyw)m(ord)f(Routines)45 b(.)h(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(109)345 3648 y(9.3.6)106 b(Mo)s(dify)30 b(Keyw)m(ord)h (Routines)36 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(111)345 3811 y(9.3.7)106 b(Up)s(date)31 b(Keyw)m(ord)f(Routines)c(.) 45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(112)136 3975 y(9.4)94 b(De\014ne)31 b(Data)h(Scaling)f(and)f(Unde\014ned)f (Pixel)i(P)m(arameters)43 b(.)j(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(113)136 4138 y(9.5)94 b(Sp)s(ecialized)32 b(FITS)d(Primary)h(Arra)m(y)h(or)f(IMA)m(GE)h (Extension)g(I/O)f(Routines)55 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 40 b(114)136 4302 y(9.6)94 b(Sp)s(ecialized)32 b(FITS)d(ASCI)s(I)g(and) h(Binary)g(T)-8 b(able)31 b(Routines)87 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(117)345 4465 y(9.6.1)106 b(General)32 b(Column)d(Routines)51 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(117)345 4629 y(9.6.2)106 b(Lo)m(w-Lev)m(el)33 b(T)-8 b(able)31 b(Access)g(Routines)40 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(119)345 4792 y(9.6.3)106 b(W)-8 b(rite)32 b(Column)e(Data)i(Routines) 52 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(119)345 4956 y(9.6.4)106 b(Read)31 b(Column)e(Data)j(Routines)72 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(120)0 5223 y Fi(10)67 b(Extended)35 b(File)f(Name)h(Syn)m(tax)2278 b(125)136 5387 y Fj(10.1)49 b(Ov)m(erview)84 b(.)46 b(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(125)136 5550 y(10.2)49 b(Filet)m(yp)s(e)62 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(128)345 5714 y(10.2.1)61 b(Notes)32 b(ab)s(out)e(HTTP)g(pro)m(xy)g(serv)m(ers)k(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(129)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 0 299 a Fj(vi)3311 b Fh(CONTENTS)345 555 y Fj(10.2.2)61 b(Notes)32 b(ab)s(out)e(HTTPS)f(and)h(FTPS)g(\014le) g(access)k(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)40 b(129)345 716 y(10.2.3)61 b(Notes)32 b(ab)s(out)e(the)h(stream)f(\014let)m(yp)s(e)h(driv)m(er)54 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)40 b(130)345 876 y(10.2.4)61 b(Notes)32 b(ab)s(out)e(the)h(gsiftp)f(\014let)m(yp)s(e)83 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(131)345 1037 y(10.2.5)61 b(Notes)32 b(ab)s(out)e(the)h(ro)s(ot)f(\014let)m(yp)s(e)68 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(131)345 1197 y(10.2.6)61 b(Notes)32 b(ab)s(out)e(the)h(shmem)e(\014let)m(yp)s (e:)70 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(133)136 1358 y(10.3)49 b(Base)32 b(Filename)90 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(133)136 1518 y(10.4)49 b(Output)30 b(File)h(Name)g(when)f(Op)s(ening) f(an)h(Existing)h(File)81 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(135)136 1678 y(10.5)49 b(T)-8 b(emplate)32 b(File)g(Name)f(when)e(Creating)i(a)g (New)f(File)57 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(137)136 1839 y(10.6)49 b(Image)32 b(Tile-Compression)e(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(137)136 1999 y(10.7)49 b(HDU)32 b(Lo)s(cation)f(Sp)s(eci\014cation)47 b(.)e(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(137)136 2160 y(10.8)49 b(Image)32 b(Section)39 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)40 b(139)136 2320 y(10.9)49 b(Image)32 b(T)-8 b(ransform)29 b(Filters)54 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(140)136 2481 y(10.10)t(Column)30 b(and)g(Keyw)m(ord)g(Filtering)h(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)40 b(141)136 2641 y(10.11)t(Ro)m(w)31 b(Filtering)h(Sp)s(eci\014cation)82 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(145)345 2802 y(10.11.1)16 b(General)32 b(Syn)m(tax)44 b(.)i(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(145)345 2962 y(10.11.2)16 b(Bit)32 b(Masks)43 b(.)j(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(148)345 3123 y(10.11.3)16 b(V)-8 b(ector)32 b(Columns)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(149)345 3283 y(10.11.4)16 b(Ro)m(w)31 b(Access)52 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(151)345 3444 y(10.11.5)16 b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)h(and)d(Calculation)37 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(152)345 3604 y(10.11.6)16 b(Spatial)31 b(Region)h(Filtering)59 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(154)345 3764 y(10.11.7)16 b(Example)31 b(Ro)m(w)g(Filters)h(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(156)136 3925 y(10.12)35 b(Binning)30 b(or)g(Histogramming)i(Sp)s (eci\014cation)f(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(157)0 4178 y Fi(11)32 b(T)-9 b(emplate)35 b(Files)2933 b(161)136 4338 y Fj(11.1)49 b(Detailed)33 b(T)-8 b(emplate)31 b(Line)g(F)-8 b(ormat)48 b(.)e(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(161)136 4498 y(11.2)49 b(Auto-indexing)31 b(of)g(Keyw)m(ords)73 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(162)136 4659 y(11.3)49 b(T)-8 b(emplate)32 b(P)m(arser)f(Directiv)m (es)87 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(163)136 4819 y(11.4)49 b(F)-8 b(ormal)32 b(T)-8 b(emplate)32 b(Syn)m(tax)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)40 b(164)136 4980 y(11.5)49 b(Errors)63 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(164)136 5140 y(11.6)49 b(Examples)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(164)0 5393 y Fi(12)67 b(Lo)s(cal)35 b(FITS)g(Con)m(v)m(en)m(tions)2462 b(167)136 5553 y Fj(12.1)49 b(64-Bit)33 b(Long)e(In)m(tegers)61 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(167)136 5714 y(12.2)49 b(Long)31 b(String)f(Keyw)m(ord)g(V) -8 b(alues.)65 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 40 b(167)p eop end %%Page: 7 7 TeXDict begin 7 6 bop 0 299 a Fh(CONTENTS)3284 b Fj(vii)136 555 y(12.3)49 b(Arra)m(ys)31 b(of)f(Fixed-Length)i(Strings)d(in)h (Binary)h(T)-8 b(ables)78 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(169)136 715 y(12.4)49 b(Keyw)m(ord)31 b(Units)f(Strings)41 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(169)136 876 y(12.5)49 b(HIERAR)m(CH)31 b(Con)m(v)m(en)m(tion)h(for)e (Extended)g(Keyw)m(ord)g(Names)91 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(169)136 1036 y(12.6)49 b(Tile-Compressed)31 b(Image)g(F)-8 b(ormat)52 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(170)0 1287 y Fi(13)67 b(Optimizing)35 b(Programs)2589 b(173)136 1447 y Fj(13.1)49 b(Ho)m(w)32 b(CFITSIO)c(Manages)k(Data)g(I/O)78 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(173)136 1607 y(13.2)49 b(Optimization)32 b(Strategies)77 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(174)0 1858 y Fi(A)57 b(Index)35 b(of)g(Routines)2789 b(179)0 2109 y(B)62 b(P)m(arameter)35 b(De\014nitions)2598 b(185)0 2360 y(C)60 b(CFITSIO)33 b(Error)i(Status)f(Co)s(des)2255 b(191)p eop end %%Page: 8 8 TeXDict begin 8 7 bop 0 299 a Fj(viii)3261 b Fh(CONTENTS)p eop end %%Page: 1 9 TeXDict begin 1 8 bop 0 1225 a Fg(Chapter)65 b(1)0 1687 y Fm(In)-6 b(tro)6 b(duction)0 2216 y Ff(1.1)180 b(A)45 b(Brief)g(Ov)l(erview)0 2495 y Fj(CFITSIO)22 b(is)h(a)g(mac)m (hine-indep)s(enden)m(t)g(library)g(of)g(routines)h(for)e(reading)i (and)e(writing)h(data)h(\014les)f(in)g(the)h(FITS)0 2608 y(\(Flexible)30 b(Image)e(T)-8 b(ransp)s(ort)27 b(System\))i(data)f (format.)40 b(It)29 b(can)f(also)h(read)f(IRAF)g(format)g(image)h (\014les)f(and)g(ra)m(w)0 2721 y(binary)39 b(data)i(arra)m(ys)g(b)m(y)f (con)m(v)m(erting)i(them)e(on)g(the)g(\015y)g(in)m(to)h(a)f(virtual)h (FITS)e(format)i(\014le.)70 b(This)39 b(library)0 2833 y(is)c(written)g(in)g(ANSI)f(C)h(and)f(pro)m(vides)h(a)h(p)s(o)m(w)m (erful)e(y)m(et)i(simple)f(in)m(terface)i(for)e(accessing)h(FITS)e (\014les)h(whic)m(h)0 2946 y(will)c(run)f(on)h(most)g(commonly)h(used)e (computers)h(and)f(w)m(orkstations.)44 b(CFITSIO)29 b(supp)s(orts)h (all)h(the)h(features)0 3059 y(describ)s(ed)39 b(in)g(the)h(o\016cial)i (de\014nition)d(of)h(the)g(FITS)f(format)i(and)e(can)h(read)g(and)f (write)h(all)h(the)f(curren)m(tly)0 3172 y(de\014ned)g(t)m(yp)s(es)h (of)g(extensions,)j(including)d(ASCI)s(I)e(tables)j(\(T)-8 b(ABLE\),)42 b(Binary)f(tables)h(\(BINT)-8 b(ABLE\))43 b(and)0 3285 y(IMA)m(GE)30 b(extensions.)41 b(The)28 b(CFITSIO)f(routines)i(insulate)h(the)f(programmer)f(from)h(ha)m(ving)g (to)h(deal)f(with)g(the)0 3398 y(complicated)36 b(formatting)g(details) g(in)e(the)h(FITS)f(\014le,)i(ho)m(w)m(ev)m(er,)h(it)e(is)g(assumed)f (that)h(users)f(ha)m(v)m(e)i(a)f(general)0 3511 y(kno)m(wledge)c(ab)s (out)f(the)h(structure)f(and)g(usage)h(of)f(FITS)g(\014les.)0 3671 y(CFITSIO)k(also)j(con)m(tains)h(a)e(set)h(of)f(F)-8 b(ortran)36 b(callable)i(wrapp)s(er)d(routines)g(whic)m(h)h(allo)m(w)i (F)-8 b(ortran)36 b(programs)0 3784 y(to)31 b(call)g(the)f(CFITSIO)e (routines.)41 b(See)30 b(the)g(companion)g(\\FITSIO)f(User's)h(Guide")g (for)g(the)g(de\014nition)g(of)g(the)0 3897 y(F)-8 b(ortran)39 b(subroutine)d(calling)k(sequences.)63 b(These)38 b(wrapp)s(ers)e (replace)j(the)f(older)g(F)-8 b(ortran)39 b(FITSIO)d(library)0 4010 y(whic)m(h)30 b(is)h(no)f(longer)h(supp)s(orted.)0 4170 y(The)20 b(CFITSIO)f(pac)m(k)-5 b(age)23 b(w)m(as)e(initially)i (dev)m(elop)s(ed)e(b)m(y)f(the)h(HEASAR)m(C)g(\(High)h(Energy)e (Astroph)m(ysics)h(Science)0 4283 y(Arc)m(hiv)m(e)35 b(Researc)m(h)g(Cen)m(ter\))f(at)h(the)f(NASA)g(Go)s(ddard)e(Space)j (Fligh)m(t)g(Cen)m(ter)f(to)h(con)m(v)m(ert)g(v)-5 b(arious)34 b(existing)0 4396 y(and)25 b(newly)h(acquired)g(astronomical)i(data)e (sets)h(in)m(to)g(FITS)e(format)h(and)f(to)i(further)e(analyze)i(data)g (already)f(in)0 4509 y(FITS)h(format.)41 b(New)28 b(features)g(con)m (tin)m(ue)h(to)g(b)s(e)e(added)h(to)g(CFITSIO)f(in)g(large)i(part)f (due)g(to)g(con)m(tributions)h(of)0 4622 y(ideas)k(or)g(actual)h(co)s (de)f(from)f(users)g(of)h(the)g(pac)m(k)-5 b(age.)49 b(The)33 b(In)m(tegral)h(Science)f(Data)h(Cen)m(ter)f(in)g (Switzerland,)0 4734 y(and)g(the)g(XMM/ESTEC)h(pro)5 b(ject)34 b(in)f(The)g(Netherlands)g(made)g(esp)s(ecially)i (signi\014can)m(t)f(con)m(tributions)g(that)0 4847 y(resulted)c(in)g (man)m(y)h(of)f(the)h(new)f(features)g(that)h(app)s(eared)f(in)g(v2.0)i (of)e(CFITSIO.)0 5322 y Ff(1.2)135 b(Sources)45 b(of)g(FITS)f(Soft)l(w) l(are)i(and)f(Information)0 5601 y Fj(The)22 b(latest)i(v)m(ersion)f (of)g(the)f(CFITSIO)f(source)i(co)s(de,)h(do)s(cumen)m(tation,)i(and)21 b(example)j(programs)e(are)h(a)m(v)-5 b(ailable)0 5714 y(on)30 b(the)h(W)-8 b(eb)31 b(or)f(via)h(anon)m(ymous)g(ftp)e(from:) 1927 5942 y(1)p eop end %%Page: 2 10 TeXDict begin 2 9 bop 0 299 a Fj(2)2452 b Fh(CHAPTER)30 b(1.)71 b(INTR)m(ODUCTION)382 555 y Fe(http://heasarc.gsfc.nasa)o(.go)o (v/fi)o(tsio)382 668 y(ftp://legacy.gsfc.nasa.g)o(ov/)o(soft)o(ware)o (/fi)o(tsio)o(/c)0 933 y Fj(An)m(y)28 b(questions,)g(bug)f(rep)s(orts,) h(or)f(suggested)i(enhancemen)m(ts)f(related)g(to)h(the)e(CFITSIO)f (pac)m(k)-5 b(age)30 b(should)d(b)s(e)0 1045 y(sen)m(t)k(to)g(the)g (FTOOLS)e(Help)h(Desk)h(at)g(the)g(HEASAR)m(C:)382 1310 y Fe(http://heasarc.gsfc.nasa)o(.go)o(v/cg)o(i-bi)o(n/f)o(tool)o(shel)o (p)0 1574 y Fj(This)40 b(User's)i(Guide)f(assumes)g(that)h(readers)f (already)g(ha)m(v)m(e)i(a)f(general)g(understanding)d(of)j(the)f (de\014nition)0 1687 y(and)31 b(structure)g(of)h(FITS)e(format)i (\014les.)44 b(F)-8 b(urther)32 b(information)f(ab)s(out)h(FITS)f (formats)g(is)h(a)m(v)-5 b(ailable)34 b(from)d(the)0 1800 y(FITS)37 b(Supp)s(ort)f(O\016ce)i(at)h Fe (http://fits.gsfc.nasa.g)o(ov)p Fj(.)57 b(In)37 b(particular,)j(the)e ('FITS)g(Standard')f(giv)m(es)0 1913 y(the)31 b(authoritativ)m(e)j (de\014nition)d(of)g(the)h(FITS)e(data)i(format.)43 b(Other)31 b(do)s(cumen)m(ts)g(a)m(v)-5 b(ailable)34 b(at)d(that)h(W)-8 b(eb)32 b(site)0 2026 y(pro)m(vide)e(additional)i(historical)f(bac)m (kground)g(and)e(practical)j(advice)g(on)e(using)g(FITS)f(\014les.)0 2186 y(The)d(HEASAR)m(C)f(also)i(pro)m(vides)f(a)h(v)m(ery)f (sophisticated)h(FITS)e(\014le)i(analysis)f(program)g(called)h(`Fv')g (whic)m(h)f(can)0 2299 y(b)s(e)31 b(used)f(to)i(displa)m(y)f(and)g (edit)g(the)h(con)m(ten)m(ts)g(of)g(an)m(y)f(FITS)g(\014le)g(as)g(w)m (ell)h(as)g(construct)f(new)g(FITS)f(\014les)h(from)0 2412 y(scratc)m(h.)56 b(Fv)36 b(is)f(freely)h(a)m(v)-5 b(ailable)37 b(for)e(most)h(Unix)f(platforms,)i(Mac)f(PCs,)g(and)f (Windo)m(ws)g(PCs.)54 b(CFITSIO)0 2525 y(users)29 b(ma)m(y)h(also)h(b)s (e)f(in)m(terested)g(in)g(the)g(FTOOLS)f(pac)m(k)-5 b(age)31 b(of)g(programs)e(that)h(can)h(b)s(e)e(used)g(to)i(manipulate)0 2638 y(and)f(analyze)i(FITS)d(format)i(\014les.)41 b(Fv)30 b(and)g(FTOOLS)f(are)i(a)m(v)-5 b(ailable)32 b(from)e(their)h(resp)s (ectiv)m(e)g(W)-8 b(eb)31 b(sites)g(at:)382 2902 y Fe (http://fv.gsfc.nasa.gov)382 3015 y(http://heasarc.gsfc.nasa)o(.go)o (v/ft)o(ools)0 3354 y Ff(1.3)135 b(Ac)l(kno)l(wledgmen)l(ts)0 3605 y Fj(The)27 b(dev)m(elopmen)m(t)h(of)g(the)f(man)m(y)g(p)s(o)m(w)m (erful)g(features)h(in)f(CFITSIO)e(w)m(as)j(made)f(p)s(ossible)g (through)f(collab)s(ora-)0 3718 y(tions)33 b(with)e(man)m(y)i(p)s (eople)f(or)g(organizations)i(from)e(around)f(the)h(w)m(orld.)46 b(The)32 b(follo)m(wing)h(in)f(particular)h(ha)m(v)m(e)0 3831 y(made)d(esp)s(ecially)i(signi\014can)m(t)f(con)m(tributions:)0 3991 y(Programmers)25 b(from)h(the)f(In)m(tegral)i(Science)g(Data)g (Cen)m(ter,)g(Switzerland)f(\(namely)-8 b(,)28 b(Jurek)c(Bork)m(o)m (wski,)29 b(Bruce)0 4104 y(O'Neel,)34 b(and)e(Don)h(Jennings\),)f (designed)g(the)h(concept)g(for)f(the)h(plug-in)f(I/O)g(driv)m(ers)g (that)h(w)m(as)g(in)m(tro)s(duced)0 4217 y(with)i(CFITSIO)e(2.0.)56 b(The)34 b(use)h(of)g(`driv)m(ers')g(greatly)h(simpli\014ed)f(the)g(lo) m(w-lev)m(el)j(I/O,)d(whic)m(h)f(in)h(turn)f(made)0 4330 y(other)40 b(new)f(features)i(in)e(CFITSIO)f(\(e.g.,)45 b(supp)s(ort)38 b(for)h(compressed)h(FITS)f(\014les)h(and)f(supp)s(ort) f(for)i(IRAF)0 4443 y(format)32 b(image)g(\014les\))g(m)m(uc)m(h)f (easier)i(to)f(implemen)m(t.)44 b(Jurek)31 b(Bork)m(o)m(wski)h(wrote)g (the)g(Shared)e(Memory)i(driv)m(er,)0 4556 y(and)23 b(Bruce)i(O'Neel)g (wrote)f(the)g(driv)m(ers)g(for)f(accessing)j(FITS)d(\014les)h(o)m(v)m (er)h(the)f(net)m(w)m(ork)h(using)e(the)i(FTP)-8 b(,)24 b(HTTP)-8 b(,)0 4669 y(and)26 b(R)m(OOT)g(proto)s(cols.)41 b(Also,)28 b(in)e(2009,)k(Bruce)d(O'Neel)h(w)m(as)f(the)g(k)m(ey)g(dev) m(elop)s(er)g(of)g(the)g(thread-safe)g(v)m(ersion)0 4782 y(of)k(CFITSIO.)0 4942 y(The)45 b(ISDC)g(also)h(pro)m(vided)f(the)h (template)h(parsing)e(routines)g(\(written)h(b)m(y)f(Jurek)g(Bork)m(o)m (wski\))i(and)e(the)0 5055 y(hierarc)m(hical)39 b(grouping)d(routines)h (\(written)h(b)m(y)f(Don)h(Jennings\).)60 b(The)37 b(ISDC)f(D)m(AL)i (\(Data)h(Access)f(La)m(y)m(er\))0 5168 y(routines)30 b(are)h(la)m(y)m(ered)h(on)e(top)h(of)f(CFITSIO)f(and)h(mak)m(e)h (extensiv)m(e)h(use)e(of)h(these)g(features.)0 5328 y(Giuliano)g(T)-8 b(a\013oni)31 b(and)f(Andrea)g(Barisani,)i(at)f(INAF,)g(Univ)m(ersit)m (y)h(of)e(T)-8 b(rieste,)32 b(Italy)-8 b(,)32 b(implemen)m(ted)e(the)h (I/O)0 5441 y(driv)m(er)f(routines)g(for)h(accessing)g(FITS)f(\014les)g (on)h(the)f(computational)i(grids)e(using)g(the)h(gridftp)e(proto)s (col.)0 5601 y(Uw)m(e)c(Lammers)e(\(XMM/ESA/ESTEC,)h(The)g (Netherlands\))g(designed)g(the)g(high-p)s(erformance)f(lexical)j (pars-)0 5714 y(ing)42 b(algorithm)h(that)f(is)g(used)f(to)i(do)e (on-the-\015y)h(\014ltering)g(of)g(FITS)f(tables.)76 b(This)41 b(algorithm)i(essen)m(tially)p eop end %%Page: 3 11 TeXDict begin 3 10 bop 0 299 a Fh(1.3.)72 b(A)m(CKNO)m(WLEDGMENTS)2623 b Fj(3)0 555 y(pre-compiles)36 b(the)g(user-supplied)e(selection)k (expression)d(in)m(to)i(a)f(form)g(that)g(can)g(b)s(e)f(rapidly)g(ev)-5 b(aluated)37 b(for)0 668 y(eac)m(h)31 b(ro)m(w.)40 b(P)m(eter)31 b(Wilson)f(\(RSTX,)f(NASA/GSF)m(C\))i(then)e(wrote)h(the)g(parsing)f (routines)g(used)g(b)m(y)g(CFITSIO)0 781 y(based)i(on)f(Lammers')h (design,)g(com)m(bined)g(with)g(other)g(tec)m(hniques)g(suc)m(h)g(as)g (the)g(CFITSIO)f(iterator)i(routine)0 894 y(to)g(further)e(enhance)h (the)h(data)g(pro)s(cessing)f(throughput.)42 b(This)31 b(e\013ort)h(also)g(b)s(ene\014ted)e(from)h(a)h(m)m(uc)m(h)f(earlier)0 1007 y(lexical)25 b(parsing)f(routine)f(that)h(w)m(as)g(dev)m(elop)s (ed)g(b)m(y)g(Ken)m(t)g(Blac)m(kburn)f(\(NASA/GSF)m(C\).)i(More)g (recen)m(tly)-8 b(,)27 b(Craig)0 1120 y(Markw)m(ardt)i(\(NASA/GSF)m (C\))g(implemen)m(ted)g(additional)g(functions)f(\(median,)h(a)m(v)m (erage,)j(stddev\))c(and)g(other)0 1233 y(enhancemen)m(ts)j(to)g(the)g (lexical)h(parser.)0 1393 y(The)40 b(CFITSIO)g(iterator)i(function)e (is)h(lo)s(osely)h(based)f(on)f(similar)i(ideas)f(dev)m(elop)s(ed)g (for)g(the)g(XMM)g(Data)0 1506 y(Access)31 b(La)m(y)m(er.)0 1666 y(P)m(eter)25 b(Wilson)g(\(RSTX,)f(NASA/GSF)m(C\))h(wrote)g(the)f (complete)i(set)e(of)h(F)-8 b(ortran-callable)27 b(wrapp)s(ers)22 b(for)i(all)h(the)0 1779 y(CFITSIO)k(routines,)h(whic)m(h)g(in)g(turn)g (rely)g(on)h(the)f(CF)m(OR)-8 b(TRAN)31 b(macro)g(dev)m(elop)s(ed)g(b)m (y)f(Burkhard)f(Buro)m(w.)0 1939 y(The)h(syn)m(tax)i(used)e(b)m(y)h (CFITSIO)f(for)g(\014ltering)i(or)f(binning)e(input)h(FITS)h(\014les)g (is)g(based)f(on)h(ideas)h(dev)m(elop)s(ed)0 2052 y(for)41 b(the)g(AXAF)h(Science)g(Cen)m(ter)g(Data)h(Mo)s(del)e(b)m(y)g (Jonathan)g(McDo)m(w)m(ell,)47 b(An)m(tonella)c(F)-8 b(ruscione,)45 b(Aneta)0 2165 y(Siemigino)m(wsk)-5 b(a)27 b(and)e(Bill)i(Jo)m(y)m(e.)41 b(See)26 b(h)m (ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/journal/axa)q(f7.h)m(t)q(ml)32 b(for)25 b(further)0 2278 y(description)30 b(of)h(the)g(AXAF)g(Data)h (Mo)s(del.)0 2438 y(The)j(\014le)g(decompression)g(co)s(de)g(w)m(ere)h (tak)m(en)g(directly)g(from)e(the)i(gzip)f(\(GNU)h(zip\))g(program)f (dev)m(elop)s(ed)g(b)m(y)0 2551 y(Jean-loup)30 b(Gailly)i(and)e (others.)0 2711 y(The)e(new)h(compressed)g(image)h(data)g(format)f (\(where)g(the)g(image)h(is)f(tiled)h(and)e(the)h(compressed)g(b)m(yte) h(stream)0 2824 y(from)k(eac)m(h)i(tile)h(is)d(stored)h(in)g(a)g (binary)f(table\))j(w)m(as)e(implemen)m(ted)g(in)g(collab)s(oration)i (with)d(Ric)m(hard)h(White)0 2937 y(\(STScI\),)30 b(P)m(erry)g (Green\014eld)h(\(STScI\))f(and)f(Doug)i(T)-8 b(o)s(dy)30 b(\(NO)m(A)m(O\).)0 3097 y(Doug)h(Mink)g(\(SA)m(O\))f(pro)m(vided)g (the)h(routines)f(for)g(con)m(v)m(erting)j(IRAF)d(format)h(images)g(in) m(to)h(FITS)d(format.)0 3257 y(Martin)k(Reinec)m(k)m(e)i(\(Max)f(Planc) m(k)f(Institute,)h(Garc)m(hing\)\))g(pro)m(vided)f(the)g(mo)s (di\014cations)f(to)i(cfortran.h)e(that)0 3370 y(are)d(necessary)h(to)f (supp)s(ort)e(64-bit)k(in)m(teger)f(v)-5 b(alues)29 b(when)f(calling)i (C)f(routines)g(from)f(fortran)h(programs.)39 b(The)0 3483 y(cfortran.h)30 b(macros)h(w)m(ere)g(originally)h(dev)m(elop)s(ed) e(b)m(y)h(Burkhard)e(Buro)m(w)h(\(CERN\).)0 3643 y(Julian)f(T)-8 b(a)m(ylor)31 b(\(ESO,)e(Garc)m(hing\))i(pro)m(vided)e(the)g(fast)h(b)m (yte-sw)m(apping)g(algorithms)h(that)f(use)f(the)h(SSE2)f(and)0 3756 y(SSSE3)g(mac)m(hine)i(instructions)f(a)m(v)-5 b(ailable)33 b(on)d(x86)p 1784 3756 28 4 v 34 w(64)h(CPUs.)0 3916 y(In)c(addition,)i(man)m(y)f(other)g(p)s(eople)g(ha)m(v)m(e)h(made)f(v) -5 b(aluable)29 b(con)m(tributions)f(to)h(the)f(dev)m(elopmen)m(t)h(of) f(CFITSIO.)0 4029 y(These)i(include)g(\(with)h(ap)s(ologies)h(to)f (others)f(that)h(ma)m(y)g(ha)m(v)m(e)h(inadv)m(erten)m(tly)g(b)s(een)d (omitted\):)0 4189 y(Stev)m(e)g(Allen,)g(Carl)f(Ak)m(erlof,)h(Keith)f (Arnaud,)g(Morten)g(Krabb)s(e)e(Barfo)s(ed,)j(Ken)m(t)f(Blac)m(kburn,)h (G)f(Bo)s(dammer,)0 4302 y(Romk)m(e)h(Bon)m(tek)m(o)s(e,)i(Lucio)d (Chiapp)s(etti,)g(Keith)g(Costorf,)g(Robin)g(Corb)s(et,)g(John)e(Da)m (vis,)k(Ric)m(hard)e(Fink,)h(Ning)0 4415 y(Gan,)i(Emily)f(Greene,)h (Gretc)m(hen)g(Green,)f(Jo)s(e)g(Harrington,)h(Cheng)f(Ho,)h(Phil)f(Ho) s(dge,)g(Jim)g(Ingham,)g(Y)-8 b(oshi-)0 4528 y(tak)j(a)44 b(Ishisaki,)i(Diab)e(Jerius,)h(Mark)f(Levine,)i(T)-8 b(o)s(dd)42 b(Karak)-5 b(askian,)47 b(Edw)m(ard)42 b(King,)k(Scott)e (Ko)s(c)m(h,)i(Claire)0 4641 y(Larkin,)32 b(Rob)g(Managan,)i(Eric)e (Mandel,)h(Ric)m(hard)f(Mathar,)h(John)e(Matto)m(x,)k(Carsten)d(Mey)m (er,)i(Emi)d(Miy)m(ata,)0 4754 y(Stefan)39 b(Mo)s(c)m(hnac)m(ki,)k(Mik) m(e)e(Noble,)h(Oliv)m(er)e(Ob)s(erdorf,)f(Cliv)m(e)i(P)m(age,)i(Arvind) 38 b(P)m(armar,)j(Je\013)f(P)m(edelt)m(y)-8 b(,)43 b(Tim)0 4867 y(P)m(earson,)d(Philipp)s(e)c(Prugniel,)j(Maren)e(Purv)m(es,)i (Scott)g(Randall,)g(Chris)d(Rogers,)k(Arnold)d(Rots,)i(Rob)e(Sea-)0 4979 y(man,)23 b(Barry)e(Sc)m(hlesinger,)i(Robin)e(Stebbins,)h(Andrew)d (Szymk)m(o)m(wiak,)25 b(Allyn)c(T)-8 b(ennan)m(t,)23 b(P)m(eter)f(T)-8 b(eub)s(en,)22 b(James)0 5092 y(Theiler,)k(Doug)g(T) -8 b(o)s(dy)g(,)25 b(Shiro)f(Ueno,)j(Stev)m(e)f(W)-8 b(alton,)28 b(Arc)m(hie)d(W)-8 b(arno)s(c)m(k,)27 b(Alan)e(W)-8 b(atson,)28 b(Dan)d(Whipple,)h(Wim)0 5205 y(Wimmers,)31 b(P)m(eter)g(Y)-8 b(oung,)31 b(Jianjun)e(Xu,)h(and)g(Nelson)h(Zarate.)p eop end %%Page: 4 12 TeXDict begin 4 11 bop 0 299 a Fj(4)2452 b Fh(CHAPTER)30 b(1.)71 b(INTR)m(ODUCTION)0 555 y Ff(1.4)135 b(Legal)46 b(Stu\013)0 805 y Fj(Cop)m(yrigh)m(t)37 b(\(Unpublished{all)g(righ)m (ts)g(reserv)m(ed)g(under)e(the)i(cop)m(yrigh)m(t)h(la)m(ws)f(of)g(the) g(United)g(States\),)j(U.S.)0 918 y(Go)m(v)m(ernmen)m(t)30 b(as)g(represen)m(ted)e(b)m(y)h(the)g(Administrator)g(of)g(the)g (National)h(Aeronautics)g(and)e(Space)h(Adminis-)0 1031 y(tration.)42 b(No)31 b(cop)m(yrigh)m(t)g(is)g(claimed)g(in)f(the)h (United)f(States)h(under)e(Title)j(17,)f(U.S.)f(Co)s(de.)0 1191 y(P)m(ermission)g(to)g(freely)f(use,)h(cop)m(y)-8 b(,)31 b(mo)s(dify)-8 b(,)29 b(and)g(distribute)g(this)g(soft)m(w)m (are)i(and)e(its)h(do)s(cumen)m(tation)g(without)0 1304 y(fee)f(is)f(hereb)m(y)g(gran)m(ted,)i(pro)m(vided)e(that)h(this)f(cop) m(yrigh)m(t)i(notice)f(and)f(disclaimer)h(of)f(w)m(arran)m(t)m(y)i(app) s(ears)d(in)h(all)0 1417 y(copies.)0 1577 y(DISCLAIMER:)0 1737 y(THE)33 b(SOFTW)-10 b(ARE)32 b(IS)g(PR)m(O)m(VIDED)i('AS)f(IS')g (WITHOUT)f(ANY)i(W)-10 b(ARRANTY)33 b(OF)g(ANY)h(KIND,)f(EI-)0 1850 y(THER)42 b(EXPRESSED,)f(IMPLIED,)i(OR)e(ST)-8 b(A)g(TUTOR)g(Y,)43 b(INCLUDING,)f(BUT)h(NOT)e(LIMITED)h(TO,)0 1963 y(ANY)33 b(W)-10 b(ARRANTY)33 b(THA)-8 b(T)32 b(THE)g(SOFTW)-10 b(ARE)32 b(WILL)g(CONF)m(ORM)g(TO)g(SPECIFICA)-8 b(TIONS,)30 b(ANY)0 2076 y(IMPLIED)38 b(W)-10 b(ARRANTIES)37 b(OF)h(MER)m(CHANT)-8 b(ABILITY,)38 b(FITNESS)f(F)m(OR)h(A)g(P)-8 b(AR)g(TICULAR)38 b(PUR-)0 2189 y(POSE,)24 b(AND)i(FREEDOM)f(FR)m(OM)h(INFRINGEMENT,)g (AND)f(ANY)h(W)-10 b(ARRANTY)25 b(THA)-8 b(T)25 b(THE)g(DOC-)0 2302 y(UMENT)-8 b(A)g(TION)31 b(WILL)f(CONF)m(ORM)h(TO)e(THE)h(SOFTW) -10 b(ARE,)30 b(OR)g(ANY)h(W)-10 b(ARRANTY)31 b(THA)-8 b(T)30 b(THE)0 2415 y(SOFTW)-10 b(ARE)31 b(WILL)h(BE)g(ERR)m(OR)g (FREE.)g(IN)g(NO)g(EVENT)f(SHALL)g(NASA)h(BE)g(LIABLE)g(F)m(OR)g(ANY)0 2528 y(D)m(AMA)m(GES,)26 b(INCLUDING,)e(BUT)f(NOT)g(LIMITED)h(TO,)f (DIRECT,)g(INDIRECT,)g(SPECIAL)f(OR)h(CON-)0 2641 y(SEQUENTIAL)28 b(D)m(AMA)m(GES,)k(ARISING)d(OUT)g(OF,)h(RESUL)-8 b(TING)29 b(FR)m(OM,)h(OR)f(IN)h(ANY)g(W)-10 b(A)i(Y)30 b(CON-)0 2754 y(NECTED)25 b(WITH)g(THIS)f(SOFTW)-10 b(ARE,)25 b(WHETHER)g(OR)g(NOT)g(BASED)g(UPON)g(W)-10 b(ARRANTY,)26 b(CON-)0 2867 y(TRA)m(CT,)d(TOR)-8 b(T)23 b(,)g(OR)g(OTHER)-10 b(WISE,)22 b(WHETHER)i(OR)f(NOT)f(INJUR)-8 b(Y)24 b(W)-10 b(AS)23 b(SUST)-8 b(AINED)23 b(BY)h(PER-)0 2979 y(SONS)h(OR)i(PR)m (OPER)-8 b(TY)26 b(OR)g(OTHER)-10 b(WISE,)26 b(AND)h(WHETHER)g(OR)f (NOT)g(LOSS)f(W)-10 b(AS)26 b(SUST)-8 b(AINED)0 3092 y(FR)m(OM,)37 b(OR)e(AR)m(OSE)h(OUT)f(OF)h(THE)g(RESUL)-8 b(TS)35 b(OF,)h(OR)f(USE)h(OF,)g(THE)g(SOFTW)-10 b(ARE)35 b(OR)g(SER-)0 3205 y(VICES)29 b(PR)m(O)m(VIDED)j(HEREUNDER.")p eop end %%Page: 5 13 TeXDict begin 5 12 bop 0 1225 a Fg(Chapter)65 b(2)0 1687 y Fm(Creating)77 b(the)h(CFITSIO)e(Library)0 2216 y Ff(2.1)135 b(Building)45 b(the)h(Library)0 2467 y Fj(The)h(CFITSIO)f(co)s(de)h(is) h(con)m(tained)g(in)f(ab)s(out)g(40)h(C)f(source)h(\014les)f(\(*.c\))i (and)e(header)g(\014les)g(\(*.h\).)93 b(On)0 2580 y(V)-10 b(AX/VMS)31 b(systems)g(2)f(assem)m(bly-co)s(de)i(\014les)e (\(vmsieeed.mar)h(and)f(vmsieeer.mar\))i(are)e(also)i(needed.)0 2740 y(CFITSIO)22 b(is)h(written)g(in)g(ANCI)g(C)g(and)g(should)f(b)s (e)g(compatible)j(with)e(most)g(existing)i(C)d(and)h(C++)f(compilers.)0 2853 y(Cra)m(y)30 b(sup)s(ercomputers)f(are)i(curren)m(tly)f(not)h (supp)s(orted.)0 3149 y Fd(2.1.1)112 b(Unix)39 b(Systems)0 3369 y Fj(The)30 b(CFITSIO)f(library)h(is)g(built)g(on)h(Unix)f (systems)g(b)m(y)g(t)m(yping:)48 3633 y Fe(>)95 b(./configure)45 b([--prefix=/target/insta)o(llat)o(ion)o(/pat)o(h])d ([--enable-reentrant])764 3746 y([--enable-sse2])h([--enable-ssse3])48 3859 y(>)95 b(make)476 b(\(or)95 b('make)46 b(shared'\))48 3971 y(>)95 b(make)47 b(install)93 b(\(this)46 b(step)h(is)g (optional\))0 4235 y Fj(at)24 b(the)g(op)s(erating)g(system)g(prompt.) 38 b(The)23 b(con\014gure)g(command)g(customizes)i(the)f(Mak)m(e\014le) h(for)f(the)g(particular)0 4348 y(system,)g(then)d(the)g(`mak)m(e')i (command)e(compiles)h(the)f(source)h(\014les)f(and)g(builds)f(the)h (library)-8 b(.)38 b(T)m(yp)s(e)21 b(`./con\014gure')0 4461 y(and)34 b(not)h(simply)f(`con\014gure')h(to)h(ensure)e(that)h (the)g(con\014gure)g(script)f(in)h(the)g(curren)m(t)f(directory)h(is)g (run)f(and)0 4574 y(not)29 b(some)g(other)g(system-wide)g(con\014gure)f (script.)40 b(The)29 b(optional)h('pre\014x')e(argumen)m(t)h(to)g (con\014gure)g(giv)m(es)h(the)0 4687 y(path)e(to)i(the)f(directory)g (where)f(the)h(CFITSIO)f(library)g(and)g(include)h(\014les)f(should)g (b)s(e)g(installed)i(via)f(the)g(later)0 4800 y('mak)m(e)j(install')f (command.)41 b(F)-8 b(or)31 b(example,)143 5064 y Fe(>)48 b(./configure)c(--prefix=/usr1/local)0 5328 y Fj(will)25 b(cause)h(the)f('mak)m(e)h(install')g(command)f(to)h(cop)m(y)g(the)f (CFITSIO)e(lib)s(c\014tsio)i(\014le)h(to)f(/usr1/lo)s(cal/lib)i(and)e (the)0 5441 y(necessary)33 b(include)e(\014les)i(to)f(/usr1/lo)s (cal/include)j(\(assuming)d(of)g(course)g(that)h(the)f(pro)s(cess)g (has)g(p)s(ermission)0 5554 y(to)f(write)g(to)g(these)g(directories\).) 0 5714 y(All)g(the)g(a)m(v)-5 b(ailable)32 b(con\014gure)e(options)h (can)g(b)s(e)f(seen)g(b)m(y)g(en)m(tering)i(the)e(command)1927 5942 y(5)p eop end %%Page: 6 14 TeXDict begin 6 13 bop 0 299 a Fj(6)1580 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)143 555 y Fe(>)48 b(./configure)c(--help)0 830 y Fj(Some)30 b(of)h(the)g(more)f(useful)g(options)g(are)h(describ)s(ed)e (b)s(elo)m(w:)0 990 y(The)j({enable-reen)m(tran)m(t)j(option)f(will)f (attempt)h(to)f(con\014gure)g(CFITSIO)e(so)i(that)g(it)g(can)h(b)s(e)e (used)g(in)g(m)m(ulti-)0 1103 y(threaded)c(programs.)39 b(See)29 b(the)f("Using)h(CFITSIO)d(in)i(Multi-threaded)h(En)m (vironmen)m(ts")f(section,)i(b)s(elo)m(w,)f(for)0 1216 y(more)i(details.)0 1376 y(The)24 b({enable-sse2)j(and)d({enable-ssse3) i(options)g(will)f(cause)g(con\014gure)g(to)g(attempt)h(to)f(build)f (CFITSIO)f(using)0 1489 y(faster)31 b(b)m(yte-sw)m(apping)h (algorithms.)42 b(See)31 b(the)g("Optimizing)h(Programs")f(c)m(hapter)h (of)e(this)h(man)m(ual)g(for)g(more)0 1602 y(information)g(ab)s(out)f (these)h(options.)0 1762 y(The)44 b({with-gsiftp-\015a)m(v)m(our)h(and) f({with-gsiftp)g(options)h(enable)f(supp)s(ort)e(for)i(the)h(Globus)e (T)-8 b(o)s(olkit)46 b(gsiftp)0 1875 y(proto)s(cal.)c(See)30 b(the)h("Extended)f(File)i(Name)f(Syn)m(tax")g(c)m(hapter)g(for)f(more) g(information.)0 2035 y(The)22 b({with-bzip2)h(option)h(enables)f(supp) s(ort)d(for)j(reading)g(FITS)f(\014les)g(that)i(ha)m(v)m(e)f(b)s(een)f (externally)i(compressed)0 2148 y(b)m(y)j(the)h(bzip2)f(algorithm.)41 b(This)27 b(requires)g(that)h(the)f(CFITSIO)f(library)-8 b(,)28 b(and)f(all)i(applications)f(program)f(that)0 2261 y(use)j(CFITSIO,)f(to)i(b)s(e)f(link)m(ed)h(to)g(include)f(the)g (libbz2)h(library)-8 b(.)0 2421 y(The)28 b('mak)m(e)h(shared')f(option) h(builds)e(a)i(shared)e(or)i(dynamic)f(v)m(ersion)h(of)f(the)h(CFITSIO) d(library)-8 b(.)40 b(When)28 b(using)0 2534 y(the)f(shared)f(library)h (the)g(executable)h(co)s(de)f(is)g(not)g(copied)g(in)m(to)h(y)m(our)f (program)g(at)g(link)g(time)g(and)g(instead)g(the)0 2647 y(program)g(lo)s(cates)i(the)f(necessary)g(library)f(co)s(de)h(at)g (run)e(time,)j(normally)f(through)e(LD)p 3065 2647 28 4 v 33 w(LIBRAR)-8 b(Y)p 3514 2647 V 34 w(P)g(A)g(TH)28 b(or)0 2760 y(some)j(other)f(metho)s(d.)41 b(The)29 b(adv)-5 b(an)m(tages)33 b(of)d(using)g(a)h(shared)e(library)h(are:)143 3035 y Fe(1.)95 b(Less)47 b(disk)f(space)h(if)g(you)g(build)f(more)h (than)f(1)i(program)143 3148 y(2.)95 b(Less)47 b(memory)f(if)h(more)g (than)f(one)h(copy)g(of)g(a)g(program)f(using)h(the)g(shared)334 3261 y(library)f(is)h(running)f(at)h(the)g(same)g(time)f(since)h(the)g (system)f(is)h(smart)334 3374 y(enough)f(to)h(share)g(copies)f(of)h (the)g(shared)f(library)g(at)h(run)g(time.)143 3487 y(3.)95 b(Possibly)46 b(easier)g(maintenance)e(since)j(a)g(new)g(version)f(of)h (the)g(shared)334 3600 y(library)f(can)h(be)g(installed)e(without)h (relinking)f(all)i(the)g(software)334 3713 y(that)g(uses)f(it)i(\(as)e (long)h(as)g(the)g(subroutine)e(names)i(and)f(calling)334 3825 y(sequences)f(remain)h(unchanged\).)143 3938 y(4.)95 b(No)47 b(run-time)f(penalty.)0 4213 y Fj(The)30 b(disadv)-5 b(an)m(tages)32 b(are:)143 4488 y Fe(1.)47 b(More)g(hassle)f(at)h (runtime.)94 b(You)46 b(have)h(to)g(either)f(build)h(the)g(programs)286 4601 y(specially)f(or)h(have)f(LD_LIBRARY_PATH)e(set)j(right.)143 4714 y(2.)g(There)g(may)g(be)g(a)g(slight)f(start)h(up)g(penalty,)e (depending)h(on)h(where)f(you)h(are)286 4827 y(reading)f(the)h(shared)f (library)g(and)h(the)g(program)f(from)g(and)h(if)g(your)g(CPU)g(is)286 4940 y(either)f(really)h(slow)f(or)h(really)f(heavily)g(loaded.)0 5215 y Fj(On)32 b(Mac)i(OS)e(X)i(platforms)f(the)g('mak)m(e)h(shared')f (command)f(w)m(orks)h(lik)m(e)i(on)e(other)g(UNIX)g(platforms,)h(but)f (a)0 5328 y(.dylib)f(\014le)g(will)g(b)s(e)f(created)i(instead)g(of)f (.so.)46 b(If)31 b(installed)i(in)f(a)g(nonstandard)f(lo)s(cation,)j (add)d(its)i(lo)s(cation)g(to)0 5441 y(the)e(D)m(YLD)p 422 5441 V 34 w(LIBRAR)-8 b(Y)p 872 5441 V 33 w(P)g(A)g(TH)31 b(en)m(vironmen)m(t)g(v)-5 b(ariable)31 b(so)g(that)g(the)f(library)g (can)h(b)s(e)f(found)f(at)i(run)e(time.)0 5601 y(On)h(HP/UX)i(systems,) g(the)f(en)m(vironmen)m(t)h(v)-5 b(ariable)32 b(CFLA)m(GS)f(should)f(b) s(e)h(set)g(to)h(-Ae)g(b)s(efore)f(running)e(con-)0 5714 y(\014gure)h(to)h(enable)g("extended)g(ANSI")f(features.)p eop end %%Page: 7 15 TeXDict begin 7 14 bop 0 299 a Fh(2.2.)72 b(TESTING)29 b(THE)h(LIBRAR)-8 b(Y)2555 b Fj(7)0 555 y(By)31 b(default,)h(a)f(set)h (of)f(F)-8 b(ortran-callable)34 b(wrapp)s(er)29 b(routines)i(are)g (also)h(built)f(and)f(included)h(in)f(the)h(CFITSIO)0 668 y(library)-8 b(.)70 b(If)40 b(these)g(wrapp)s(er)f(routines)h(are)g (not)h(needed)e(\(i.e.,)45 b(the)40 b(CFITSIO)f(library)g(will)i(not)f (b)s(e)g(link)m(ed)0 781 y(to)d(an)m(y)f(F)-8 b(ortran)37 b(applications)g(whic)m(h)f(call)h(FITSIO)e(subroutines\))g(then)h (they)g(ma)m(y)h(b)s(e)e(omitted)i(from)f(the)0 894 y(build)28 b(b)m(y)i(t)m(yping)g('mak)m(e)g(all-no\014tsio')i(instead)d(of)h (simply)f(t)m(yping)h('mak)m(e'.)42 b(This)28 b(will)i(reduce)f(the)h (size)g(of)g(the)0 1007 y(CFITSIO)f(library)h(sligh)m(tly)-8 b(.)0 1167 y(It)33 b(ma)m(y)g(not)g(b)s(e)f(p)s(ossible)g(to)h (statically)i(link)e(programs)f(that)h(use)g(CFITSIO)e(on)h(some)h (platforms)g(\(namely)-8 b(,)0 1280 y(on)28 b(Solaris)h(2.6\))h(due)e (to)h(the)g(net)m(w)m(ork)g(driv)m(ers)f(\(whic)m(h)h(pro)m(vide)g(FTP) f(and)g(HTTP)g(access)h(to)h(FITS)d(\014les\).)41 b(It)0 1393 y(is)33 b(p)s(ossible)f(to)i(mak)m(e)f(b)s(oth)g(a)g(dynamic)f (and)g(a)i(static)g(v)m(ersion)f(of)g(the)g(CFITSIO)e(library)-8 b(,)34 b(but)e(net)m(w)m(ork)i(\014le)0 1506 y(access)e(will)e(not)h(b) s(e)f(p)s(ossible)g(using)g(the)g(static)i(v)m(ersion.)0 1813 y Fd(2.1.2)112 b(VMS)0 2035 y Fj(On)28 b(V)-10 b(AX/VMS)31 b(and)d(ALPHA/VMS)i(systems)f(the)h(mak)m(e)p 2100 2035 28 4 v 34 w(g\015oat.com)h(command)e(\014le)g(ma)m(y)h(b)s(e)f (executed)h(to)0 2148 y(build)35 b(the)i(c\014tsio.olb)g(ob)5 b(ject)37 b(library)f(using)g(the)g(default)h(G-\015oating)g(p)s(oin)m (t)g(option)f(for)g(double)g(v)-5 b(ariables.)0 2261 y(The)37 b(mak)m(e)p 405 2261 V 33 w(d\015oat.com)i(and)d(mak)m(e)p 1279 2261 V 34 w(ieee.com)j(\014les)f(ma)m(y)f(b)s(e)g(used)f(instead)i (to)g(build)e(the)h(library)g(with)g(the)0 2374 y(other)26 b(\015oating)i(p)s(oin)m(t)e(options.)39 b(Note)28 b(that)f(the)f (getcwd)h(function)f(that)h(is)f(used)f(in)h(the)h(group.c)f(mo)s(dule) f(ma)m(y)0 2487 y(require)44 b(that)i(programs)e(using)g(CFITSIO)f(b)s (e)h(link)m(ed)i(with)e(the)h(ALPHA$LIBRAR)-8 b(Y:V)e(AX)m(CR)i(TL.OLB) 0 2600 y(library)g(.)41 b(See)30 b(the)h(example)g(link)f(line)h(in)f (the)h(next)f(section)i(of)e(this)h(do)s(cumen)m(t.)0 2907 y Fd(2.1.3)112 b(Windo)m(ws)38 b(PCs)0 3129 y Fj(A)j(precompiled)f (DLL)g(v)m(ersion)h(of)g(CFITSIO)e(\(not)i(necessarily)g(the)g(latest)h (v)m(ersion\))f(is)g(a)m(v)-5 b(ailable)42 b(on)f(the)0 3242 y(CFITSIO)26 b(w)m(eb)i(site.)41 b(The)27 b(CFITSIO)f(library)h (ma)m(y)i(also)g(b)s(e)e(built)g(from)h(the)g(source)f(co)s(de)h(using) g(the)g(CMak)m(e)0 3355 y(build)j(system.)44 b(See)32 b(the)g("README.win")h(\014le)f(in)f(the)h(CFITSIO)e(source)i (distribution)f(for)g(more)h(informa-)0 3468 y(tion.)0 3775 y Fd(2.1.4)112 b(Macin)m(tosh)39 b(PCs)0 3998 y Fj(When)20 b(building)f(on)i(Mac)g(OS-X,)f(users)g(should)f(follo)m(w)i (the)g(Unix)f(instructions,)i(ab)s(o)m(v)m(e.)39 b(See)20 b(the)h(README.MacOS)0 4111 y(\014le)30 b(for)h(instructions)f(on)g (building)g(a)g(Univ)m(ersal)i(Binary)e(that)h(supp)s(orts)e(b)s(oth)g (In)m(tel)i(and)f(P)m(o)m(w)m(erPC)h(CPUs.)0 4461 y Ff(2.2)135 b(T)-11 b(esting)46 b(the)f(Library)0 4714 y Fj(The)40 b(CFITSIO)e(library)i(should)f(b)s(e)g(tested)i(b)m(y)f(building)f(and) g(running)g(the)h(testprog.c)h(program)f(that)h(is)0 4827 y(included)30 b(with)g(the)g(release.)42 b(On)30 b(Unix)g(systems,)h(t)m(yp)s(e:)191 5101 y Fe(\045)47 b(make)g(testprog)191 5214 y(\045)g(testprog)f(>)h(testprog.lis)191 5327 y(\045)g(diff)g(testprog.lis)d(testprog.out)191 5440 y(\045)j(cmp)g(testprog.fit)e(testprog.std)0 5714 y Fj(On)30 b(VMS)g(systems,)g(\(assuming)h(cc)g(is)f(the)h(name)f(of)h (the)f(C)g(compiler)h(command\),)g(t)m(yp)s(e:)p eop end %%Page: 8 16 TeXDict begin 8 15 bop 0 299 a Fj(8)1580 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)191 555 y Fe($)47 b(cc)h(testprog.c)191 668 y($)f(link)g(testprog,) e(cfitsio/lib,)g(alpha$library:vaxcrtl/l)o(ib)191 781 y($)i(run)g(testprog)0 1132 y Fj(The)42 b(test)h(program)f(should)f (pro)s(duce)g(a)i(FITS)e(\014le)i(called)g(`testprog.\014t')h(that)f (is)f(iden)m(tical)i(to)f(the)f(`test-)0 1245 y(prog.std')35 b(FITS)e(\014le)i(included)e(with)h(this)g(release.)54 b(The)34 b(diagnostic)i(messages)f(\(whic)m(h)g(w)m(ere)g(pip)s(ed)e (to)i(the)0 1358 y(\014le)h(testprog.lis)i(in)e(the)h(Unix)f(example\)) h(should)e(b)s(e)h(iden)m(tical)i(to)f(the)f(listing)h(con)m(tained)h (in)e(the)g(\014le)h(test-)0 1471 y(prog.out.)63 b(The)37 b('di\013)7 b(')38 b(and)f('cmp')h(commands)g(sho)m(wn)f(ab)s(o)m(v)m (e)i(should)d(not)i(rep)s(ort)f(an)m(y)h(di\013erences)g(in)g(the)0 1584 y(\014les.)65 b(\(There)38 b(ma)m(y)h(b)s(e)f(some)h(minor)f (format)h(di\013erences,)i(suc)m(h)d(as)h(the)g(presence)f(or)h (absence)g(of)f(leading)0 1697 y(zeros,)31 b(or)g(3)f(digit)i(exp)s (onen)m(ts)e(in)g(n)m(um)m(b)s(ers,)f(whic)m(h)h(can)h(b)s(e)f (ignored\).)0 1857 y(The)e(F)-8 b(ortran)30 b(wrapp)s(ers)d(in)h (CFITSIO)f(ma)m(y)j(b)s(e)e(tested)h(with)g(the)g(testf77)h(program)f (on)g(Unix)f(systems)h(with:)191 2208 y Fe(\045)47 b(gfortran)f(-o)h (testf77)f(testf77.f)f(-L.)i(-lcfitsio)e(-lz)i(-lcurl)191 2321 y(\045)g(testf77)f(>)i(testf77.lis)191 2433 y(\045)f(diff)g (testf77.lis)e(testf77.out)191 2546 y(\045)i(cmp)g(testf77.fit)e (testf77.std)0 2897 y Fj(On)31 b(mac)m(hines)h(running)f(SUN)g(O/S,)h (F)-8 b(ortran)33 b(programs)e(m)m(ust)h(b)s(e)f(compiled)h(with)g(the) g('-f)7 b(')32 b(option)h(to)f(force)0 3010 y(double)25 b(precision)h(v)-5 b(ariables)26 b(to)g(b)s(e)f(aligned)h(on)g(8-b)m (yte)h(b)s(oundarys)c(to)j(mak)m(e)h(the)e(fortran-declared)h(v)-5 b(ariables)0 3123 y(compatible)34 b(with)e(C.)g(A)h(similar)g(compiler) g(option)g(ma)m(y)g(b)s(e)f(required)g(on)g(other)h(platforms.)48 b(F)-8 b(ailing)34 b(to)f(use)0 3236 y(this)26 b(option)g(ma)m(y)g (cause)h(the)f(program)f(to)i(crash)e(on)h(FITSIO)f(routines)g(that)i (read)f(or)f(write)h(double)g(precision)0 3349 y(v)-5 b(ariables.)0 3509 y(Also)31 b(note)g(that)f(on)g(some)h(systems,)f (the)h(output)e(listing)i(of)g(the)f(testf77)i(program)d(ma)m(y)i (di\013er)f(sligh)m(tly)h(from)0 3622 y(the)g(testf77.std)h(template,)g (if)f(leading)g(zeros)g(are)g(not)g(prin)m(ted)f(b)m(y)h(default)g(b)s (efore)f(the)h(decimal)g(p)s(oin)m(t)g(when)0 3735 y(using)f(F)h (format.)0 3895 y(A)37 b(few)f(other)g(utilit)m(y)i(programs)e(are)h (included)f(with)g(CFITSIO;)f(the)i(\014rst)e(four)h(of)g(this)h (programs)f(can)h(b)s(e)0 4008 y(compiled)e(an)g(link)m(ed)g(b)m(y)g(t) m(yping)g(`mak)m(e)h(program)p 1815 4008 28 4 v 33 w(name')f(where)f (`program)p 2746 4008 V 33 w(name')h(is)g(the)g(actual)h(name)f(of)0 4121 y(the)c(program:)191 4472 y Fe(speed)46 b(-)i(measures)d(the)i (maximum)f(throughput)f(\(in)i(MB)g(per)g(second\))668 4585 y(for)g(writing)f(and)h(reading)f(FITS)g(files)h(with)f(CFITSIO.) 191 4811 y(listhead)f(-)j(lists)e(all)h(the)g(header)f(keywords)g(in)h (any)g(FITS)f(file)191 5036 y(fitscopy)f(-)j(copies)e(any)h(FITS)g (file)f(\(especially)f(useful)h(in)h(conjunction)811 5149 y(with)g(the)g(CFITSIO's)e(extended)h(input)g(filename)g (syntax\).)191 5375 y(cookbook)f(-)j(a)f(sample)f(program)g(that)h (performs)e(common)i(read)f(and)811 5488 y(write)h(operations)e(on)i(a) g(FITS)g(file.)191 5714 y(iter_a,)f(iter_b,)g(iter_c)g(-)h(examples)f (of)h(the)g(CFITSIO)f(iterator)f(routine)p eop end %%Page: 9 17 TeXDict begin 9 16 bop 0 299 a Fh(2.3.)72 b(LINKING)30 b(PR)m(OGRAMS)h(WITH)f(CFITSIO)1975 b Fj(9)0 555 y Ff(2.3)135 b(Linking)45 b(Programs)h(with)f(CFITSIO)0 805 y Fj(When)25 b(linking)h(applications)h(soft)m(w)m(are)g(with)e(the)h(CFITSIO)e (library)-8 b(,)27 b(sev)m(eral)g(system)f(libraries)g(usually)f(need)0 918 y(to)36 b(b)s(e)f(sp)s(eci\014ed)g(on)g(the)g(link)h(command)f (line.)56 b(On)34 b(Unix)i(systems,)h(the)e(most)h(reliable)g(w)m(a)m (y)h(to)f(determine)0 1031 y(what)26 b(libraries)h(are)f(required)g(is) g(to)h(t)m(yp)s(e)f('mak)m(e)i(testprog')f(and)f(see)h(what)f (libraries)h(the)f(con\014gure)g(script)g(has)0 1144 y(added.)39 b(The)25 b(t)m(ypical)j(libraries)e(that)g(need)g(to)g(b)s (e)g(added)f(are)h(-lm)h(\(the)f(math)g(library\))g(and)f(-lnsl)h(and)g (-lso)s(c)m(k)m(et)0 1257 y(\(needed)k(only)g(for)g(FTP)g(and)f(HTTP)g (\014le)h(access\).)43 b(These)30 b(latter)h(2)f(libraries)g(are)h(not) f(needed)g(on)g(VMS)g(and)0 1370 y(Windo)m(ws)g(platforms,)h(b)s (ecause)f(FTP)h(\014le)f(access)i(is)e(not)h(curren)m(tly)f(supp)s (orted)f(on)h(those)h(platforms.)0 1530 y(Note)i(that)g(when)e (upgrading)g(to)i(a)f(new)m(er)g(v)m(ersion)g(of)g(CFITSIO)f(it)h(is)g (usually)g(necessary)g(to)h(recompile,)h(as)0 1643 y(w)m(ell)d(as)g (relink,)g(the)f(programs)g(that)h(use)f(CFITSIO,)f(b)s(ecause)i(the)f (de\014nitions)g(in)g(\014tsio.h)h(often)f(c)m(hange.)0 1976 y Ff(2.4)135 b(Using)46 b(CFITSIO)e(in)h(Multi-threaded)g(En)l (vironmen)l(ts)0 2226 y Fj(CFITSIO)d(can)h(b)s(e)g(used)f(either)i (with)e(the)i(POSIX)e(pthreads)g(in)m(terface)j(or)e(the)h(Op)s(enMP)d (in)m(terface)k(for)0 2339 y(m)m(ulti-threaded)g(parallel)g(programs.) 81 b(When)43 b(used)h(in)f(a)i(m)m(ulti-threaded)f(en)m(vironmen)m(t,)k (the)c(CFITSIO)0 2452 y(library)26 b(*m)m(ust*)h(b)s(e)e(built)h(using) g(the)g(-D)p 1426 2452 28 4 v 34 w(REENTRANT)f(compiler)i(directiv)m (e.)41 b(This)25 b(can)i(b)s(e)e(done)h(using)g(the)0 2564 y(follo)m(wing)32 b(build)d(commands:)95 2817 y Fe(>./configure)45 b(--enable-reentrant)95 2930 y(>)j(make)0 3183 y Fj(A)32 b(function)g(called)i(\014ts)p 845 3183 V 32 w(is)p 938 3183 V 33 w(reen)m(tran)m(t)f(is)g(a)m(v)-5 b(ailable)34 b(to)f(test)h(whether)d(or)i(not)f(CFITSIO)f(w)m(as)h (compiled)h(with)0 3296 y(the)28 b(-D)p 258 3296 V 34 w(REENTRANT)f(directiv)m(e.)42 b(When)28 b(this)g(feature)g(is)g (enabled,)h(m)m(ultiple)g(threads)e(can)i(call)g(an)m(y)g(of)f(the)0 3409 y(CFITSIO)k(routines)h(to)h(sim)m(ultaneously)g(read)f(or)h(write) f(separate)h(FITS)f(\014les.)49 b(Multiple)34 b(threads)f(can)h(also)0 3522 y(read)29 b(data)h(from)e(the)h(same)h(FITS)e(\014le)h(sim)m (ultaneously)-8 b(,)31 b(as)e(long)h(as)f(the)g(\014le)g(w)m(as)h(op)s (ened)e(indep)s(enden)m(tly)g(b)m(y)0 3634 y(eac)m(h)37 b(thread.)58 b(This)35 b(relies)i(on)f(the)g(op)s(erating)h(system)f (to)h(correctly)g(deal)g(with)f(reading)g(the)g(same)h(\014le)f(b)m(y)0 3747 y(m)m(ultiple)30 b(pro)s(cesses.)41 b(Di\013eren)m(t)30 b(threads)g(should)e(not)i(share)f(the)h(same)g('\014ts\014le')g(p)s (oin)m(ter)f(to)i(read)e(an)h(op)s(ened)0 3860 y(FITS)40 b(\014le,)j(unless)d(lo)s(c)m(ks)h(are)g(placed)f(around)g(the)g(calls) i(to)f(the)g(CFITSIO)d(reading)j(routines.)71 b(Di\013eren)m(t)0 3973 y(threads)30 b(should)f(nev)m(er)i(try)f(to)h(write)g(to)g(the)g (same)f(FITS)g(\014le.)0 4306 y Ff(2.5)135 b(Getting)46 b(Started)g(with)f(CFITSIO)0 4556 y Fj(In)27 b(order)h(to)g(e\013ectiv) m(ely)j(use)d(the)g(CFITSIO)e(library)i(it)g(is)g(recommended)g(that)g (new)f(users)h(b)s(egin)f(b)m(y)h(reading)0 4669 y(the)g(\\CFITSIO)g (Quic)m(k)g(Start)g(Guide".)41 b(It)28 b(con)m(tains)h(all)h(the)e (basic)h(information)f(needed)g(to)h(write)f(programs)0 4782 y(that)c(p)s(erform)f(most)h(t)m(yp)s(es)g(of)g(op)s(erations)g (on)g(FITS)f(\014les.)39 b(The)23 b(set)i(of)f(example)g(FITS)g(utilit) m(y)h(programs)e(that)0 4895 y(are)29 b(a)m(v)-5 b(ailable)31 b(from)d(the)g(CFITSIO)f(w)m(eb)i(site)g(are)g(also)g(v)m(ery)g(useful) f(for)g(learning)h(ho)m(w)f(to)h(use)f(CFITSIO.)f(T)-8 b(o)0 5008 y(learn)23 b(ev)m(en)g(more)g(ab)s(out)f(the)h(capabilities) h(of)f(the)g(CFITSIO)e(library)h(the)h(follo)m(wing)h(steps)e(are)h (recommended:)0 5168 y(1.)41 b(Read)31 b(the)f(follo)m(wing)i(short)e (`FITS)g(Primer')g(c)m(hapter)h(for)f(an)h(o)m(v)m(erview)h(of)e(the)h (structure)f(of)g(FITS)g(\014les.)0 5328 y(2.)40 b(Review)28 b(the)f(Programming)g(Guidelines)h(in)f(Chapter)f(4)i(to)g(b)s(ecome)f (familiar)h(with)f(the)h(con)m(v)m(en)m(tions)h(used)0 5441 y(b)m(y)h(the)h(CFITSIO)e(in)m(terface.)0 5601 y(3.)74 b(Refer)41 b(to)h(the)g(co)s(okb)s(o)s(ok.c,)j(listhead.c,)h(and)40 b(\014tscop)m(y)-8 b(.c)43 b(programs)e(that)h(are)g(included)e(with)h (this)h(re-)0 5714 y(lease)g(for)e(examples)h(of)g(routines)f(that)h(p) s(erform)e(v)-5 b(arious)41 b(common)g(FITS)f(\014le)g(op)s(erations.) 72 b(T)m(yp)s(e)40 b('mak)m(e)p eop end %%Page: 10 18 TeXDict begin 10 17 bop 0 299 a Fj(10)1535 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)0 555 y Fj(program)p 339 555 28 4 v 33 w(name')30 b(to)h(compile)h(and)d(link)i(these)g(programs)f(on)g(Unix)g(systems.)0 715 y(4.)40 b(W)-8 b(rite)30 b(a)e(simple)g(program)g(to)g(read)g(or)g (write)g(a)h(FITS)e(\014le)h(using)g(the)g(Basic)h(In)m(terface)g (routines)f(describ)s(ed)0 828 y(in)i(Chapter)g(5.)0 988 y(5.)79 b(Scan)43 b(through)f(the)h(more)g(sp)s(ecialized)i (routines)d(that)i(are)f(describ)s(ed)f(in)h(the)g(follo)m(wing)i(c)m (hapters)e(to)0 1101 y(b)s(ecome)31 b(familiar)g(with)f(the)h (functionalit)m(y)g(that)g(they)g(pro)m(vide.)0 1434 y Ff(2.6)135 b(Example)46 b(Program)0 1685 y Fj(The)c(follo)m(wing)j (listing)f(sho)m(ws)e(an)h(example)h(of)f(ho)m(w)g(to)g(use)g(the)g (CFITSIO)f(routines)g(in)h(a)g(C)g(program.)0 1798 y(Refer)26 b(to)g(the)g(co)s(okb)s(o)s(ok.c)g(program)f(that)i(is)e(included)g (with)g(the)h(CFITSIO)e(distribution)h(for)g(other)h(example)0 1910 y(routines.)0 2071 y(This)38 b(program)h(creates)h(a)f(new)f(FITS) g(\014le,)k(con)m(taining)e(a)f(FITS)f(image.)68 b(An)38 b(`EXPOSURE')h(k)m(eyw)m(ord)g(is)0 2183 y(written)27 b(to)g(the)f(header,)i(then)e(the)h(image)g(data)h(are)f(written)f(to)h (the)g(FITS)f(\014le)g(b)s(efore)h(closing)g(the)g(FITS)f(\014le.)0 2439 y Fe(#include)46 b("fitsio.h")92 b(/*)47 b(required)f(by)h(every)g (program)e(that)i(uses)g(CFITSIO)93 b(*/)0 2552 y(main\(\))0 2665 y({)191 2778 y(fitsfile)45 b(*fptr;)333 b(/*)47 b(pointer)f(to)h(the)g(FITS)g(file;)f(defined)g(in)h(fitsio.h)f(*/)191 2891 y(int)h(status,)f(ii,)h(jj;)191 3004 y(long)94 b(fpixel)46 b(=)i(1,)f(naxis)f(=)i(2,)f(nelements,)e(exposure;)191 3117 y(long)i(naxes[2])e(=)j({)f(300,)g(200)g(};)142 b(/*)47 b(image)g(is)g(300)g(pixels)f(wide)h(by)g(200)g(rows)f(*/)191 3230 y(short)g(array[200][300];)191 3456 y(status)g(=)h(0;)429 b(/*)48 b(initialize)d(status)h(before)g(calling)g(fitsio)g(routines)f (*/)191 3569 y(fits_create_file\(&fptr,)c("testfile.fits",)j (&status\);)140 b(/*)48 b(create)e(new)h(file)f(*/)191 3794 y(/*)h(Create)f(the)h(primary)f(array)g(image)h(\(16-bit)e(short)i (integer)f(pixels)g(*/)191 3907 y(fits_create_img\(fptr,)c(SHORT_IMG,)j (naxis,)h(naxes,)g(&status\);)191 4133 y(/*)h(Write)f(a)i(keyword;)d (must)i(pass)g(the)g(ADDRESS)e(of)j(the)f(value)f(*/)191 4246 y(exposure)f(=)j(1500.;)191 4359 y(fits_update_key\(fptr,)42 b(TLONG,)k("EXPOSURE",)f(&exposure,)430 4472 y("Total)h(Exposure)f (Time",)h(&status\);)191 4698 y(/*)h(Initialize)e(the)i(values)f(in)h (the)g(image)g(with)f(a)i(linear)e(ramp)g(function)g(*/)191 4811 y(for)h(\(jj)g(=)g(0;)g(jj)h(<)f(naxes[1];)e(jj++\))382 4924 y(for)i(\(ii)g(=)g(0;)g(ii)g(<)h(naxes[0];)d(ii++\))573 5036 y(array[jj][ii])f(=)j(ii)h(+)f(jj;)191 5262 y(nelements)e(=)j (naxes[0])d(*)j(naxes[1];)474 b(/*)48 b(number)e(of)h(pixels)f(to)h (write)g(*/)191 5488 y(/*)g(Write)f(the)h(array)g(of)g(integers)e(to)j (the)f(image)f(*/)191 5601 y(fits_write_img\(fptr,)c(TSHORT,)k(fpixel,) g(nelements,)f(array[0],)g(&status\);)p eop end %%Page: 11 19 TeXDict begin 11 18 bop 0 299 a Fh(2.6.)72 b(EXAMPLE)31 b(PR)m(OGRAM)2618 b Fj(11)191 555 y Fe(fits_close_file\(fptr,)42 b(&status\);)570 b(/*)47 b(close)g(the)g(file)f(*/)191 781 y(fits_report_error\(stderr)o(,)c(status\);)93 b(/*)47 b(print)g(out)g(any)f(error)h(messages)e(*/)191 894 y(return\()h (status)g(\);)0 1007 y(})p eop end %%Page: 12 20 TeXDict begin 12 19 bop 0 299 a Fj(12)1535 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)p eop end %%Page: 13 21 TeXDict begin 13 20 bop 0 1225 a Fg(Chapter)65 b(3)0 1687 y Fm(A)78 b(FITS)f(Primer)0 2180 y Fj(This)36 b(section)h(giv)m (es)h(a)f(brief)f(o)m(v)m(erview)i(of)e(the)h(structure)f(of)h(FITS)e (\014les.)59 b(Users)36 b(should)g(refer)g(to)h(the)g(do)s(c-)0 2293 y(umen)m(tation)i(a)m(v)-5 b(ailable)41 b(from)d(the)g(FITS)g (Supp)s(ort)e(OF\014ce,)41 b(as)d(describ)s(ed)g(in)g(the)g(in)m(tro)s (duction,)j(for)d(more)0 2406 y(detailed)31 b(information)g(on)f(FITS)g (formats.)0 2566 y(FITS)e(w)m(as)h(\014rst)g(dev)m(elop)s(ed)g(in)f (the)h(late)i(1970's)g(as)e(a)g(standard)f(data)i(in)m(terc)m(hange)g (format)f(b)s(et)m(w)m(een)h(v)-5 b(arious)0 2679 y(astronomical)36 b(observ)-5 b(atories.)52 b(Since)34 b(then)g(FITS)f(has)h(b)s(ecome)g (the)h(standard)e(data)i(format)f(supp)s(orted)e(b)m(y)0 2791 y(most)f(astronomical)h(data)f(analysis)g(soft)m(w)m(are)h(pac)m (k)-5 b(ages.)0 2952 y(A)34 b(FITS)f(\014le)g(consists)h(of)g(one)g(or) g(more)g(Header)g(+)f(Data)i(Units)f(\(HDUs\),)i(where)d(the)h(\014rst) f(HDU)h(is)g(called)0 3065 y(the)j(`Primary)f(HDU',)i(or)f(`Primary)f (Arra)m(y'.)60 b(The)36 b(primary)g(arra)m(y)h(con)m(tains)h(an)e (N-dimensional)i(arra)m(y)f(of)0 3177 y(pixels,)30 b(suc)m(h)g(as)g(a)h (1-D)g(sp)s(ectrum,)e(a)h(2-D)h(image,)h(or)e(a)g(3-D)i(data)e(cub)s (e.)40 b(Six)30 b(di\013eren)m(t)g(primary)f(data)i(t)m(yp)s(es)0 3290 y(are)j(supp)s(orted:)44 b(Unsigned)33 b(8-bit)h(b)m(ytes,)h (16-bit,)g(32-bit,)h(and)c(64-bit)j(signed)e(in)m(tegers,)i(and)e(32)h (and)f(64-bit)0 3403 y(\015oating)c(p)s(oin)m(t)f(reals.)41 b(FITS)27 b(also)j(has)e(a)g(con)m(v)m(en)m(tion)j(for)d(storing)g(16,) i(32-bit,)g(and)e(64-bit)i(unsigned)d(in)m(tegers)0 3516 y(\(see)36 b(the)g(later)g(section)g(en)m(titled)h(`Unsigned)e(In)m (tegers')i(for)e(more)g(details\).)57 b(The)35 b(primary)f(HDU)i(ma)m (y)g(also)0 3629 y(consist)31 b(of)g(only)f(a)h(header)f(with)g(a)h(n)m (ull)f(arra)m(y)h(con)m(taining)h(no)e(data)h(pixels.)0 3789 y(An)m(y)i(n)m(um)m(b)s(er)e(of)h(additional)i(HDUs)f(ma)m(y)g (follo)m(w)h(the)e(primary)g(arra)m(y;)i(these)f(additional)h(HDUs)f (are)g(called)0 3902 y(FITS)d(`extensions'.)41 b(There)30 b(are)h(curren)m(tly)f(3)h(t)m(yp)s(es)g(of)f(extensions)h(de\014ned)e (b)m(y)h(the)h(FITS)f(standard:)136 4171 y Fc(\017)46 b Fj(Image)31 b(Extension)g(-)g(a)f(N-dimensional)h(arra)m(y)g(of)g (pixels,)g(lik)m(e)g(in)f(a)h(primary)e(arra)m(y)136 4368 y Fc(\017)46 b Fj(ASCI)s(I)29 b(T)-8 b(able)31 b(Extension)g(-)f (ro)m(ws)h(and)e(columns)h(of)h(data)g(in)f(ASCI)s(I)f(c)m(haracter)j (format)136 4564 y Fc(\017)46 b Fj(Binary)31 b(T)-8 b(able)31 b(Extension)f(-)h(ro)m(ws)f(and)g(columns)g(of)h(data)g(in)f(binary)f (represen)m(tation)0 4833 y(In)k(eac)m(h)i(case)g(the)f(HDU)h(consists) g(of)f(an)g(ASCI)s(I)e(Header)i(Unit)h(follo)m(w)m(ed)g(b)m(y)f(an)g (optional)h(Data)g(Unit.)52 b(F)-8 b(or)0 4946 y(historical)37 b(reasons,)g(eac)m(h)f(Header)g(or)g(Data)h(unit)e(m)m(ust)g(b)s(e)g (an)g(exact)i(m)m(ultiple)f(of)g(2880)h(8-bit)f(b)m(ytes)g(long.)0 5059 y(An)m(y)30 b(un)m(used)g(space)g(is)h(padded)e(with)h(\014ll)g(c) m(haracters)i(\(ASCI)s(I)d(blanks)h(or)h(zeros\).)0 5219 y(Eac)m(h)i(Header)f(Unit)h(consists)g(of)f(an)m(y)g(n)m(um)m(b)s(er)f (of)i(80-c)m(haracter)i(k)m(eyw)m(ord)d(records)g(or)g(`card)h(images') g(whic)m(h)0 5332 y(ha)m(v)m(e)f(the)e(general)i(form:)95 5601 y Fe(KEYNAME)46 b(=)i(value)e(/)i(comment)d(string)95 5714 y(NULLKEY)h(=)334 b(/)48 b(comment:)d(This)i(keyword)f(has)g(no)i (value)1905 5942 y Fj(13)p eop end %%Page: 14 22 TeXDict begin 14 21 bop 0 299 a Fj(14)2398 b Fh(CHAPTER)30 b(3.)112 b(A)30 b(FITS)g(PRIMER)0 555 y Fj(The)35 b(k)m(eyw)m(ord)i (names)f(ma)m(y)g(b)s(e)g(up)f(to)h(8)h(c)m(haracters)g(long)g(and)e (can)h(only)h(con)m(tain)g(upp)s(ercase)e(letters,)k(the)0 668 y(digits)25 b(0-9,)i(the)e(h)m(yphen,)g(and)f(the)h(underscore)e(c) m(haracter.)41 b(The)24 b(k)m(eyw)m(ord)h(name)g(is)f(\(usually\))h (follo)m(w)m(ed)i(b)m(y)d(an)0 781 y(equals)29 b(sign)g(and)f(a)g (space)i(c)m(haracter)g(\(=)e(\))h(in)f(columns)h(9)g(-)f(10)i(of)f (the)f(record,)h(follo)m(w)m(ed)i(b)m(y)d(the)h(v)-5 b(alue)29 b(of)g(the)0 894 y(k)m(eyw)m(ord)34 b(whic)m(h)g(ma)m(y)g(b)s (e)f(either)h(an)g(in)m(teger,)i(a)e(\015oating)g(p)s(oin)m(t)g(n)m(um) m(b)s(er,)g(a)g(c)m(haracter)h(string)e(\(enclosed)i(in)0 1007 y(single)28 b(quotes\),)i(or)e(a)g(b)s(o)s(olean)g(v)-5 b(alue)28 b(\(the)g(letter)h(T)f(or)f(F\).)i(A)f(k)m(eyw)m(ord)g(ma)m (y)h(also)f(ha)m(v)m(e)h(a)g(n)m(ull)e(or)h(unde\014ned)0 1120 y(v)-5 b(alue)31 b(if)f(there)h(is)f(no)g(sp)s(eci\014ed)g(v)-5 b(alue)31 b(string,)g(as)f(in)g(the)h(second)f(example,)i(ab)s(o)m(v)m (e)0 1280 y(The)26 b(last)h(k)m(eyw)m(ord)g(in)g(the)f(header)h(is)f (alw)m(a)m(ys)i(the)f(`END')g(k)m(eyw)m(ord)g(whic)m(h)g(has)f(no)g(v) -5 b(alue)27 b(or)g(commen)m(t)g(\014elds.)0 1393 y(There)k(are)g(man)m (y)g(rules)g(go)m(v)m(erning)h(the)g(exact)g(format)g(of)f(a)g(k)m(eyw) m(ord)h(record)f(\(see)h(the)f(FITS)f(Standard\))h(so)0 1506 y(it)i(is)f(b)s(etter)h(to)g(rely)g(on)f(standard)f(in)m(terface)j (soft)m(w)m(are)g(lik)m(e)g(CFITSIO)d(to)i(correctly)h(construct)f(or)f (to)h(parse)0 1619 y(the)e(k)m(eyw)m(ord)f(records)h(rather)f(than)g (try)g(to)h(deal)g(directly)g(with)f(the)h(ra)m(w)f(FITS)g(formats.)0 1779 y(Eac)m(h)37 b(Header)g(Unit)f(b)s(egins)g(with)g(a)g(series)h(of) f(required)g(k)m(eyw)m(ords)g(whic)m(h)g(dep)s(end)f(on)h(the)g(t)m(yp) s(e)h(of)f(HDU.)0 1892 y(These)31 b(required)g(k)m(eyw)m(ords)h(sp)s (ecify)g(the)f(size)i(and)e(format)h(of)g(the)g(follo)m(wing)h(Data)g (Unit.)45 b(The)31 b(header)g(ma)m(y)0 2005 y(con)m(tain)h(other)f (optional)g(k)m(eyw)m(ords)g(to)h(describ)s(e)e(other)g(asp)s(ects)h (of)g(the)g(data,)g(suc)m(h)g(as)g(the)f(units)g(or)h(scaling)0 2118 y(v)-5 b(alues.)44 b(Other)31 b(COMMENT)g(or)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)i(are)g(also)g(frequen)m(tly)g(added)e(to)i (further)e(do)s(cumen)m(t)0 2230 y(the)h(data)g(\014le.)0 2391 y(The)36 b(optional)h(Data)h(Unit)f(immediately)g(follo)m(ws)h (the)e(last)h(2880-b)m(yte)i(blo)s(c)m(k)e(in)f(the)g(Header)h(Unit.)59 b(Some)0 2503 y(HDUs)31 b(do)f(not)h(ha)m(v)m(e)g(a)g(Data)h(Unit)f (and)f(only)g(consist)h(of)g(the)f(Header)h(Unit.)0 2664 y(If)24 b(there)i(is)f(more)g(than)f(one)h(HDU)h(in)f(the)g(FITS)f (\014le,)i(then)f(the)g(Header)h(Unit)f(of)g(the)g(next)g(HDU)h (immediately)0 2777 y(follo)m(ws)g(the)e(last)i(2880-b)m(yte)h(blo)s(c) m(k)e(of)g(the)f(previous)g(Data)j(Unit)d(\(or)h(Header)g(Unit)g(if)f (there)h(is)g(no)f(Data)i(Unit\).)0 2937 y(The)k(main)g(required)g(k)m (eyw)m(ords)g(in)g(FITS)g(primary)g(arra)m(ys)g(or)h(image)g (extensions)g(are:)136 3172 y Fc(\017)46 b Fj(BITPIX)32 b({)g(de\014nes)e(the)i(data)g(t)m(yp)s(e)g(of)g(the)g(arra)m(y:)43 b(8,)33 b(16,)g(32,)g(64,)g(-32,)g(-64)g(for)e(unsigned)f(8{bit)j(b)m (yte,)227 3284 y(16{bit)41 b(signed)f(in)m(teger,)j(32{bit)f(signed)d (in)m(teger,)44 b(32{bit)d(IEEE)e(\015oating)h(p)s(oin)m(t,)i(and)e (64{bit)h(IEEE)227 3397 y(double)30 b(precision)h(\015oating)g(p)s(oin) m(t,)g(resp)s(ectiv)m(ely)-8 b(.)136 3585 y Fc(\017)46 b Fj(NAXIS)30 b({)h(the)g(n)m(um)m(b)s(er)e(of)h(dimensions)g(in)g(the) h(arra)m(y)-8 b(,)31 b(usually)f(0,)h(1,)g(2,)g(3,)g(or)g(4.)136 3773 y Fc(\017)46 b Fj(NAXISn)30 b({)h(\(n)f(ranges)g(from)g(1)h(to)g (NAXIS\))g(de\014nes)e(the)i(size)g(of)g(eac)m(h)g(dimension.)0 4008 y(FITS)e(tables)i(start)g(with)f(the)g(k)m(eyw)m(ord)g(XTENSION)g (=)f(`T)-8 b(ABLE')31 b(\(for)f(ASCI)s(I)f(tables\))i(or)f(XTENSION)f (=)0 4120 y(`BINT)-8 b(ABLE')32 b(\(for)e(binary)g(tables\))h(and)f(ha) m(v)m(e)i(the)e(follo)m(wing)i(main)e(k)m(eyw)m(ords:)136 4355 y Fc(\017)46 b Fj(TFIELDS)30 b({)h(n)m(um)m(b)s(er)e(of)h (\014elds)g(or)h(columns)f(in)g(the)g(table)136 4543 y Fc(\017)46 b Fj(NAXIS2)31 b({)g(n)m(um)m(b)s(er)e(of)h(ro)m(ws)h(in)f (the)g(table)136 4731 y Fc(\017)46 b Fj(TTYPEn)29 b({)i(for)f(eac)m(h)i (column)e(\(n)g(ranges)h(from)f(1)g(to)h(TFIELDS\))g(giv)m(es)g(the)g (name)f(of)h(the)f(column)136 4918 y Fc(\017)46 b Fj(TF)m(ORMn)31 b({)f(the)h(data)g(t)m(yp)s(e)f(of)h(the)g(column)136 5106 y Fc(\017)46 b Fj(TUNITn)30 b({)g(the)h(ph)m(ysical)g(units)f(of)g (the)h(column)f(\(optional\))0 5341 y(Users)k(should)f(refer)h(to)h (the)f(FITS)g(Supp)s(ort)e(O\016ce)i(at)h Fe(http://fits.gsfc.nasa.gov) 27 b Fj(for)34 b(further)f(infor-)0 5454 y(mation)e(ab)s(out)f(the)h (FITS)e(format)i(and)f(related)h(soft)m(w)m(are)h(pac)m(k)-5 b(ages.)p eop end %%Page: 15 23 TeXDict begin 15 22 bop 0 1225 a Fg(Chapter)65 b(4)0 1687 y Fm(Programming)77 b(Guidelines)0 2216 y Ff(4.1)135 b(CFITSIO)44 b(De\014nitions)0 2466 y Fj(An)m(y)30 b(program)g(that)h (uses)f(the)h(CFITSIO)d(in)m(terface)k(m)m(ust)e(include)g(the)h (\014tsio.h)f(header)g(\014le)h(with)f(the)g(state-)0 2579 y(men)m(t)95 2818 y Fe(#include)46 b("fitsio.h")0 3057 y Fj(This)30 b(header)h(\014le)h(con)m(tains)g(the)f(protot)m(yp)s (es)h(for)f(all)h(the)f(CFITSIO)f(user)g(in)m(terface)j(routines)e(as)g (w)m(ell)h(as)g(the)0 3170 y(de\014nitions)g(of)g(v)-5 b(arious)32 b(constan)m(ts)h(used)e(in)h(the)h(in)m(terface.)47 b(It)32 b(also)h(de\014nes)e(a)i(C)f(structure)f(of)h(t)m(yp)s(e)h (`\014ts\014le')0 3283 y(that)j(is)g(used)f(b)m(y)g(CFITSIO)f(to)j (store)f(the)g(relev)-5 b(an)m(t)37 b(parameters)f(that)g(de\014ne)f (the)h(format)g(of)g(a)g(particular)0 3396 y(FITS)c(\014le.)48 b(Application)34 b(programs)f(m)m(ust)g(de\014ne)f(a)h(p)s(oin)m(ter)g (to)g(this)g(structure)g(for)f(eac)m(h)i(FITS)e(\014le)h(that)h(is)0 3508 y(to)i(b)s(e)f(op)s(ened.)56 b(This)35 b(structure)g(is)h (initialized)h(\(i.e.,)i(memory)c(is)h(allo)s(cated)h(for)f(the)g (structure\))f(when)g(the)0 3621 y(FITS)h(\014le)g(is)h(\014rst)e(op)s (ened)h(or)g(created)i(with)e(the)g(\014ts)p 1949 3621 28 4 v 33 w(op)s(en)p 2172 3621 V 32 w(\014le)g(or)h(\014ts)p 2596 3621 V 32 w(create)p 2864 3621 V 34 w(\014le)g(routines.)59 b(This)35 b(\014ts\014le)0 3734 y(p)s(oin)m(ter)c(is)h(then)f(passed)g (as)g(the)h(\014rst)e(argumen)m(t)i(to)g(ev)m(ery)g(other)g(CFITSIO)d (routine)j(that)g(op)s(erates)g(on)f(the)0 3847 y(FITS)h(\014le.)48 b(Application)34 b(programs)f(m)m(ust)g(not)g(directly)g(read)g(or)g (write)g(elemen)m(ts)h(in)f(this)g(\014ts\014le)f(structure)0 3960 y(b)s(ecause)e(the)h(de\014nition)f(of)h(the)f(structure)g(ma)m(y) h(c)m(hange)g(in)g(future)e(v)m(ersions)i(of)f(CFITSIO.)0 4120 y(A)45 b(n)m(um)m(b)s(er)e(of)i(sym)m(b)s(olic)g(constan)m(ts)h (are)f(also)g(de\014ned)f(in)g(\014tsio.h)h(for)f(the)h(con)m(v)m (enience)i(of)e(application)0 4233 y(programmers.)55 b(Use)35 b(of)h(these)f(sym)m(b)s(olic)h(constan)m(ts)g(rather)f(than)g (the)h(actual)g(n)m(umeric)f(v)-5 b(alue)36 b(will)f(help)g(to)0 4346 y(mak)m(e)c(the)g(source)f(co)s(de)h(more)g(readable)f(and)g (easier)i(for)e(others)g(to)h(understand.)0 4585 y Fe(String)46 b(Lengths,)g(for)h(use)f(when)h(allocating)e(character)g(arrays:)95 4811 y(#define)h(FLEN_FILENAME)e(1025)j(/*)g(max)g(length)f(of)h(a)h (filename)857 b(*/)95 4924 y(#define)46 b(FLEN_KEYWORD)140 b(72)95 b(/*)47 b(max)g(length)f(of)h(a)h(keyword)905 b(*/)95 5036 y(#define)46 b(FLEN_CARD)284 b(81)95 b(/*)47 b(max)g(length)f(of)h(a)h(FITS)f(header)f(card)476 b(*/)95 5149 y(#define)46 b(FLEN_VALUE)236 b(71)95 b(/*)47 b(max)g(length)f(of) h(a)h(keyword)e(value)g(string)285 b(*/)95 5262 y(#define)46 b(FLEN_COMMENT)140 b(73)95 b(/*)47 b(max)g(length)f(of)h(a)h(keyword)e (comment)g(string)189 b(*/)95 5375 y(#define)46 b(FLEN_ERRMSG)188 b(81)95 b(/*)47 b(max)g(length)f(of)h(a)h(CFITSIO)e(error)g(message)237 b(*/)95 5488 y(#define)46 b(FLEN_STATUS)188 b(31)95 b(/*)47 b(max)g(length)f(of)h(a)h(CFITSIO)e(status)g(text)g(string)h(*/)95 5714 y(Note)g(that)g(FLEN_KEYWORD)d(is)j(longer)f(than)h(the)g(nominal) f(8-character)f(keyword)1905 5942 y Fj(15)p eop end %%Page: 16 24 TeXDict begin 16 23 bop 0 299 a Fj(16)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)95 555 y Fe(name)47 b(length)f(because)g(the)h(HIERARCH)e(convention)g(supports)h(longer)g (keyword)g(names.)0 781 y(Access)g(modes)g(when)h(opening)f(a)h(FITS)g (file:)95 1007 y(#define)f(READONLY)94 b(0)95 1120 y(#define)46 b(READWRITE)g(1)0 1346 y(BITPIX)g(data)h(type)f(code)h(values)f(for)h (FITS)g(images:)95 1571 y(#define)f(BYTE_IMG)284 b(8)96 b(/*)f(8-bit)46 b(unsigned)f(integers)h(*/)95 1684 y(#define)g (SHORT_IMG)189 b(16)95 b(/*)47 b(16-bit)141 b(signed)46 b(integers)g(*/)95 1797 y(#define)g(LONG_IMG)237 b(32)95 b(/*)47 b(32-bit)141 b(signed)46 b(integers)g(*/)95 1910 y(#define)g(LONGLONG_IMG)f(64)95 b(/*)47 b(64-bit)141 b(signed)46 b(integers)g(*/)95 2023 y(#define)g(FLOAT_IMG)141 b(-32)95 b(/*)47 b(32-bit)f(single)g(precision)f(floating)h(point)g(*/) 95 2136 y(#define)g(DOUBLE_IMG)93 b(-64)i(/*)47 b(64-bit)f(double)g (precision)f(floating)h(point)g(*/)95 2362 y(The)h(following)f(4)h (data)g(type)f(codes)h(are)g(also)f(supported)g(by)h(CFITSIO:)95 2475 y(#define)f(SBYTE_IMG)93 b(10)286 b(/*)95 b(8-bit)46 b(signed)g(integers,)g(equivalent)f(to)i(*/)1384 2588 y(/*)95 b(BITPIX)46 b(=)i(8,)f(BSCALE)f(=)h(1,)g(BZERO)g(=)g(-128)g(*/) 95 2700 y(#define)f(USHORT_IMG)93 b(20)238 b(/*)47 b(16-bit)f(unsigned) g(integers,)f(equivalent)g(to)i(*/)1384 2813 y(/*)95 b(BITPIX)46 b(=)i(16,)e(BSCALE)h(=)g(1,)g(BZERO)g(=)g(32768)f(*/)95 2926 y(#define)g(ULONG_IMG)141 b(40)238 b(/*)47 b(32-bit)f(unsigned)g (integers,)f(equivalent)g(to)i(*/)1384 3039 y(/*)95 b(BITPIX)46 b(=)i(32,)e(BSCALE)h(=)g(1,)g(BZERO)g(=)g(2147483648)e(*/)95 3152 y(#define)h(ULONGLONG_IMG)92 b(80)j(/*)47 b(64-bit)f(unsigned)g (integers,)f(equivalent)g(to)i(*/)1384 3265 y(/*)95 b(BITPIX)46 b(=)i(64,)e(BSCALE)h(=)g(1,)g(BZERO)g(=)g(9223372036854775808*/)0 3491 y(Codes)f(for)h(the)g(data)g(type)f(of)i(binary)e(table)g(columns) g(and/or)g(for)h(the)0 3604 y(data)g(type)f(of)h(variables)f(when)g (reading)g(or)h(writing)f(keywords)g(or)h(data:)1432 3830 y(DATATYPE)714 b(TFORM)46 b(CODE)95 3942 y(#define)g(TBIT)476 b(1)96 b(/*)1335 b('X')47 b(*/)95 4055 y(#define)f(TBYTE)381 b(11)95 b(/*)47 b(8-bit)f(unsigned)g(byte,)332 b('B')47 b(*/)95 4168 y(#define)f(TLOGICAL)237 b(14)95 b(/*)47 b(logicals)e(\(int)i(for)g(keywords)236 b(*/)1289 4281 y(/*)95 b(and)46 b(char)h(for)g(table)f(cols)142 b('L')47 b(*/)95 4394 y(#define)f(TSTRING)285 b(16)95 b(/*)47 b(ASCII)f(string,)666 b('A')47 b(*/)95 4507 y(#define)f(TSHORT)333 b(21)95 b(/*)47 b(signed)f(short,)666 b('I')47 b(*/)95 4620 y(#define)f(TLONG)381 b(41)95 b(/*)47 b(signed)f(long,)905 b(*/)95 4733 y(#define)46 b(TLONGLONG)189 b(81)95 b(/*)47 b(64-bit)f(long)h(signed)f(integer)f('K')i(*/)95 4846 y(#define)f(TFLOAT)333 b(42)95 b(/*)47 b(single)f(precision)f(float,) 189 b('E')47 b(*/)95 4959 y(#define)f(TDOUBLE)285 b(82)95 b(/*)47 b(double)f(precision)f(float,)189 b('D')47 b(*/)95 5072 y(#define)f(TCOMPLEX)237 b(83)95 b(/*)47 b(complex)f(\(pair)g(of)h (floats\))141 b('C')47 b(*/)95 5185 y(#define)f(TDBLCOMPLEX)f(163)95 b(/*)47 b(double)f(complex)g(\(2)h(doubles\))e('M')i(*/)95 5410 y(The)g(following)f(data)g(type)h(codes)f(are)h(also)g(supported)e (by)i(CFITSIO:)95 5523 y(#define)f(TINT)429 b(31)95 b(/*)47 b(int)1335 b(*/)95 5636 y(#define)46 b(TSBYTE)333 b(12)95 b(/*)47 b(8-bit)f(signed)g(byte,)428 b('S')47 b(*/)p eop end %%Page: 17 25 TeXDict begin 17 24 bop 0 299 a Fh(4.1.)72 b(CFITSIO)29 b(DEFINITIONS)2576 b Fj(17)95 555 y Fe(#define)46 b(TUINT)381 b(30)95 b(/*)47 b(unsigned)e(int)715 b('V')47 b(*/)95 668 y(#define)f(TUSHORT)285 b(20)95 b(/*)47 b(unsigned)e(short)619 b('U')47 b(*/)95 781 y(#define)f(TULONG)333 b(40)95 b(/*)47 b(unsigned)e(long)858 b(*/)95 894 y(#define)46 b(TULONGLONG)141 b(80)95 b(/*)47 b(unsigned)e(long)i(long)428 b('W')47 b(*/)95 1120 y(The)g(following)f(data)g(type)h(code)g(is)g(only)f(for)h (use)g(with)g(fits\\_get\\_coltype)95 1233 y(#define)f(TINT32BIT)189 b(41)95 b(/*)47 b(signed)f(32-bit)g(int,)428 b('J')47 b(*/)0 1571 y(HDU)g(type)g(code)f(values)g(\(value)g(returned)g(when)h (moving)f(to)h(new)g(HDU\):)95 1797 y(#define)f(IMAGE_HDU)93 b(0)i(/*)48 b(Primary)d(Array)i(or)g(IMAGE)f(HDU)h(*/)95 1910 y(#define)f(ASCII_TBL)93 b(1)i(/*)48 b(ASCII)94 b(table)46 b(HDU)h(*/)95 2023 y(#define)f(BINARY_TBL)f(2)95 b(/*)48 b(Binary)e(table)g(HDU)h(*/)95 2136 y(#define)f(ANY_HDU)142 b(-1)94 b(/*)48 b(matches)d(any)i(type)g(of)g(HDU)g(*/)0 2362 y(Column)f(name)h(and)g(string)f(matching)f(case-sensitivity:)95 2588 y(#define)h(CASESEN)142 b(1)g(/*)48 b(do)f(case-sensitive)d (string)i(match)g(*/)95 2700 y(#define)g(CASEINSEN)g(0)142 b(/*)48 b(do)f(case-insensitive)c(string)j(match)h(*/)0 2926 y(Logical)f(states)g(\(if)h(TRUE)f(and)h(FALSE)g(are)g(not)g (already)e(defined\):)95 3152 y(#define)h(TRUE)h(1)95 3265 y(#define)f(FALSE)h(0)0 3491 y(Values)f(to)h(represent)f (undefined)f(floating)g(point)i(numbers:)95 3717 y(#define)f (FLOATNULLVALUE)92 b(-9.11912E-36F)95 3830 y(#define)46 b(DOUBLENULLVALUE)e(-9.1191291391491E-36)0 4055 y(Image)i(compression)f (algorithm)g(definitions)95 4281 y(#define)h(RICE_1)333 b(11)95 4394 y(#define)46 b(GZIP_1)333 b(21)95 4507 y(#define)46 b(GZIP_2)333 b(22)95 4620 y(#define)46 b(PLIO_1)333 b(31)95 4733 y(#define)46 b(HCOMPRESS_1)93 b(41)95 4846 y(#define)46 b(NOCOMPRESS)93 b(-1)95 5072 y(#define)46 b(NO_DITHER)g(-1)95 5185 y(#define)g(SUBTRACTIVE_DITHER_1)d(1)95 5297 y(#define)j (SUBTRACTIVE_DITHER_2)d(2)p eop end %%Page: 18 26 TeXDict begin 18 25 bop 0 299 a Fj(18)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Ff(4.2)135 b(Curren)l(t)46 b(Header)f(Data)h(Unit)g(\(CHDU\))0 811 y Fj(The)37 b(concept)h(of)g(the)f(Curren)m(t)g(Header)g(and)g(Data)i (Unit,)h(or)d(CHDU,)h(is)f(fundamen)m(tal)h(to)g(the)f(use)g(of)h(the)0 924 y(CFITSIO)31 b(library)-8 b(.)46 b(A)32 b(simple)h(FITS)e(image)j (ma)m(y)f(only)f(con)m(tain)i(a)e(single)h(Header)g(and)f(Data)h(unit)f (\(HDU\),)0 1037 y(but)39 b(in)g(general)i(FITS)e(\014les)h(can)g(con)m (tain)h(m)m(ultiple)g(Header)f(Data)h(Units)f(\(also)h(kno)m(wn)e(as)h (`extensions'\),)0 1150 y(concatenated)c(one)f(after)f(the)h(other)f (in)g(the)g(\014le.)53 b(The)33 b(user)h(can)g(sp)s(ecify)g(whic)m(h)g (HDU)h(should)e(b)s(e)g(initially)0 1263 y(op)s(ened)j(at)i(run)d(time) j(b)m(y)f(giving)h(the)f(HDU)h(name)f(or)g(n)m(um)m(b)s(er)f(after)h (the)g(ro)s(ot)h(\014le)f(name.)60 b(F)-8 b(or)38 b(example,)0 1376 y('m)m(y\014le.\014ts[4]')i(op)s(ens)d(the)h(5th)h(HDU)g(in)f(the) g(\014le)g(\(note)h(that)g(the)f(n)m(um)m(b)s(ering)f(starts)i(with)f (0\),)j(and)c('m)m(y-)0 1489 y(\014le.\014ts[EVENTS])k(op)s(ens)f(the)h (HDU)h(with)e(the)h(name)g('EVENTS')g(\(as)g(de\014ned)f(b)m(y)h(the)g (EXTNAME)g(or)0 1602 y(HDUNAME)35 b(k)m(eyw)m(ords\).)50 b(If)33 b(no)g(HDU)h(is)f(sp)s(eci\014ed)g(then)g(CFITSIO)e(op)s(ens)i (the)g(\014rst)g(HDU)h(\(the)g(primary)0 1715 y(arra)m(y\))24 b(b)m(y)e(default.)39 b(The)22 b(CFITSIO)f(routines)i(whic)m(h)g(read)f (and)g(write)i(data)f(only)g(op)s(erate)g(within)g(the)g(op)s(ened)0 1827 y(HDU,)32 b(Other)e(CFITSIO)f(routines)i(are)g(pro)m(vided)f(to)i (mo)m(v)m(e)g(to)f(and)f(op)s(en)g(an)m(y)h(other)g(existing)h(HDU)f (within)0 1940 y(the)g(FITS)e(\014le)i(or)f(to)h(app)s(end)e(or)h (insert)g(new)g(HDUs)h(in)f(the)h(FITS)f(\014le.)0 2303 y Ff(4.3)135 b(F)-11 b(unction)44 b(Names)i(and)f(V)-11 b(ariable)46 b(Datat)l(yp)t(es)0 2559 y Fj(Most)33 b(of)f(the)g (CFITSIO)f(routines)h(ha)m(v)m(e)h(b)s(oth)e(a)i(short)e(name)h(as)h(w) m(ell)g(as)f(a)g(longer)h(descriptiv)m(e)g(name.)45 b(The)0 2672 y(short)32 b(name)g(is)g(only)g(5)h(or)f(6)g(c)m(haracters)h(long) g(and)f(is)g(similar)g(to)h(the)f(subroutine)f(name)h(in)g(the)g(F)-8 b(ortran-77)0 2785 y(v)m(ersion)38 b(of)g(FITSIO.)f(The)h(longer)g (name)g(is)g(more)g(descriptiv)m(e)h(and)e(it)h(is)g(recommended)g (that)g(it)h(b)s(e)e(used)0 2898 y(instead)31 b(of)f(the)h(short)f (name)g(to)h(more)g(clearly)h(do)s(cumen)m(t)e(the)g(source)h(co)s(de.) 0 3058 y(Man)m(y)c(of)f(the)g(CFITSIO)f(routines)h(come)h(in)e (families)i(whic)m(h)f(di\013er)g(only)g(in)g(the)g(data)h(t)m(yp)s(e)f (of)g(the)g(asso)s(ciated)0 3171 y(parameter\(s\).)45 b(The)31 b(data)h(t)m(yp)s(e)g(of)g(these)g(routines)f(is)h(indicated)g (b)m(y)f(the)h(su\016x)e(of)i(the)g(routine)f(name.)44 b(The)0 3284 y(short)27 b(routine)h(names)g(ha)m(v)m(e)h(a)f(1)g(or)f (2)h(c)m(haracter)i(su\016x)c(\(e.g.,)31 b('j')c(in)h('\013pkyj'\))g (while)f(the)h(long)g(routine)g(names)0 3397 y(ha)m(v)m(e)k(a)e(4)h(c)m (haracter)h(or)e(longer)h(su\016x)f(as)g(sho)m(wn)g(in)g(the)h(follo)m (wing)h(table:)191 3681 y Fe(Long)285 b(Short)94 b(Data)191 3794 y(Names)237 b(Names)94 b(Type)191 3907 y(-----)237 b(-----)94 b(----)191 4020 y(_bit)381 b(x)190 b(bit)191 4133 y(_byt)381 b(b)190 b(unsigned)46 b(byte)191 4246 y(_sbyt)333 b(sb)142 b(signed)46 b(byte)191 4359 y(_sht)381 b(i)190 b(short)47 b(integer)191 4472 y(_lng)381 b(j)190 b(long)47 b(integer)191 4585 y(_lnglng)237 b(jj)142 b(8-byte)46 b(LONGLONG)g(integer)g(\(see)g(note)h(below\))191 4698 y(_usht)333 b(ui)142 b(unsigned)46 b(short)g(integer)191 4811 y(_ulng)333 b(uj)142 b(unsigned)46 b(long)g(integer)191 4924 y(_ulnglng)189 b(ujj)94 b(unsigned)46 b(long)g(long)h(integer)191 5036 y(_uint)333 b(uk)142 b(unsigned)46 b(int)h(integer)191 5149 y(_int)381 b(k)190 b(int)47 b(integer)191 5262 y(_flt)381 b(e)190 b(real)47 b(exponential)e(floating)g(point)i(\(float\))191 5375 y(_fixflt)237 b(f)190 b(real)47 b(fixed-decimal)d(format)i (floating)g(point)g(\(float\))191 5488 y(_dbl)381 b(d)190 b(double)46 b(precision)g(real)g(floating-point)e(\(double\))191 5601 y(_fixdbl)237 b(g)190 b(double)46 b(precision)g(fixed-format)e (floating)i(point)g(\(double\))191 5714 y(_cmp)381 b(c)190 b(complex)46 b(reals)g(\(pairs)h(of)g(float)f(values\))p eop end %%Page: 19 27 TeXDict begin 19 26 bop 0 299 a Fh(4.3.)72 b(FUNCTION)30 b(NAMES)h(AND)g(V)-10 b(ARIABLE)30 b(D)m(A)-8 b(T)g(A)g(TYPES)1409 b Fj(19)191 555 y Fe(_fixcmp)237 b(fc)142 b(complex)46 b(reals,)g(fixed-format)f(floating)g(point)191 668 y(_dblcmp)237 b(m)190 b(double)46 b(precision)g(complex)f(\(pairs)i(of)g(double)f (values\))191 781 y(_fixdblcmp)93 b(fm)142 b(double)46 b(precision)g(complex,)f(fixed-format)g(floating)g(point)191 894 y(_log)381 b(l)190 b(logical)46 b(\(int\))191 1007 y(_str)381 b(s)190 b(character)46 b(string)0 1273 y Fj(The)32 b(logical)j(data)f(t)m(yp)s(e)f(corresp)s(onds)e(to)j(`in)m(t')f(for)g (logical)i(k)m(eyw)m(ord)e(v)-5 b(alues,)34 b(and)e(`b)m(yte')i(for)f (logical)i(binary)0 1386 y(table)40 b(columns.)67 b(In)39 b(other)g(w)m(ords,)i(the)f(v)-5 b(alue)39 b(when)g(writing)g(a)h (logical)h(k)m(eyw)m(ord)f(m)m(ust)f(b)s(e)g(stored)g(in)g(an)0 1499 y(`in)m(t')g(v)-5 b(ariable,)40 b(and)e(m)m(ust)f(b)s(e)g(stored)h (in)g(a)g(`c)m(har')h(arra)m(y)f(when)f(reading)h(or)f(writing)h(to)h (`L')f(columns)f(in)h(a)0 1612 y(binary)c(table.)56 b(Implicit)35 b(data)h(t)m(yp)s(e)f(con)m(v)m(ersion)i(is)e(not)g(supp)s(orted)e(for) i(logical)j(table)e(columns,)g(but)e(is)h(for)0 1725 y(k)m(eyw)m(ords,)30 b(so)f(a)h(logical)h(k)m(eyw)m(ord)f(ma)m(y)f(b)s (e)g(read)f(and)h(cast)h(to)g(an)m(y)f(n)m(umerical)h(data)f(t)m(yp)s (e;)h(a)g(returned)d(v)-5 b(alue)0 1838 y(=)30 b(0)h(indicates)g (false,)g(and)f(an)m(y)h(other)f(v)-5 b(alue)31 b(=)f(true.)0 1998 y(The)24 b(`in)m(t')i(data)g(t)m(yp)s(e)f(ma)m(y)h(b)s(e)e(2)h(b)m (ytes)h(long)f(on)g(some)g(old)g(PC)g(compilers,)h(but)f(otherwise)g (it)g(is)g(nearly)g(alw)m(a)m(ys)0 2111 y(4)i(b)m(ytes)g(long.)40 b(Some)27 b(64-bit)h(mac)m(hines,)g(lik)m(e)g(the)f(Alpha/OSF,)g (de\014ne)f(the)h(`short',)h(`in)m(t',)h(and)d(`long')i(in)m(teger)0 2224 y(data)j(t)m(yp)s(es)f(to)i(b)s(e)d(2,)i(4,)g(and)f(8)h(b)m(ytes)g (long,)g(resp)s(ectiv)m(ely)-8 b(.)0 2384 y(Because)40 b(there)e(is)h(no)f(univ)m(ersal)h(C)f(compiler)g(standard)g(for)g(the) h(name)f(of)h(the)f(8-b)m(yte)i(in)m(teger)g(datat)m(yp)s(e,)0 2497 y(the)33 b(\014tsio.h)h(include)f(\014le)g(t)m(yp)s(edef)7 b('s)33 b('LONGLONG')h(to)g(b)s(e)e(equiv)-5 b(alen)m(t)35 b(to)f(an)f(appropriate)g(8-b)m(yte)i(in)m(teger)0 2610 y(data)c(t)m(yp)s(e)g(on)f(eac)m(h)i(supp)s(orted)d(platform.)41 b(F)-8 b(or)31 b(maxim)m(um)f(soft)m(w)m(are)i(p)s(ortabilit)m(y)g(it)f (is)f(recommended)g(that)0 2723 y(this)g(LONGLONG)g(datat)m(yp)s(e)h(b) s(e)e(used)g(to)i(de\014ne)e(8-b)m(yte)i(in)m(teger)h(v)-5 b(ariables)30 b(rather)g(than)g(using)f(the)i(nativ)m(e)0 2835 y(data)h(t)m(yp)s(e)g(name)f(on)h(a)f(particular)h(platform.)44 b(On)31 b(most)h(32-bit)g(Unix)g(and)e(Mac)j(OS-X)e(op)s(erating)h (systems)0 2948 y(LONGLONG)h(is)f(equiv)-5 b(alen)m(t)34 b(to)f(the)g(in)m(trinsic)g('long)g(long')h(8-b)m(yte)g(in)m(teger)f (datat)m(yp)s(e.)49 b(On)31 b(64-bit)j(systems)0 3061 y(\(whic)m(h)e(curren)m(tly)g(includes)f(Alpha)h(OSF/1,)g(64-bit)h(Sun) e(Solaris,)h(64-bit)h(SGI)f(MIPS,)f(and)g(64-bit)i(Itanium)0 3174 y(and)28 b(Opteron)g(PC)h(systems\),)g(LONGLONG)g(is)g(simply)f(t) m(yp)s(edef)7 b('ed)29 b(to)g(b)s(e)g(equiv)-5 b(alen)m(t)30 b(to)f('long'.)42 b(Microsoft)0 3287 y(Visual)33 b(C++)e(V)-8 b(ersion)33 b(6.0)g(do)s(es)f(not)g(de\014ne)g(a)h('long)g(long')g (data)g(t)m(yp)s(e,)g(so)f(LONGLONG)h(is)f(t)m(yp)s(edef)7 b('ed)32 b(to)0 3400 y(b)s(e)e(equiv)-5 b(alen)m(t)32 b(to)f(the)f(')p 853 3400 28 4 v 887 3400 V 66 w(in)m(t64')i(data)f(t)m (yp)s(e)g(on)f(32-bit)h(windo)m(ws)f(systems)h(when)e(using)h(Visual)h (C++.)0 3560 y(A)j(related)h(issue)e(that)i(a\013ects)g(the)f(p)s (ortabilit)m(y)g(of)g(soft)m(w)m(are)i(is)d(ho)m(w)h(to)h(prin)m(t)e (out)h(the)g(v)-5 b(alue)34 b(of)g(a)g('LONG-)0 3673 y(LONG')e(v)-5 b(ariable)32 b(with)f(prin)m(tf.)44 b(Dev)m(elop)s(ers) 33 b(ma)m(y)f(\014nd)e(it)i(con)m(v)m(enien)m(t)h(to)g(use)e(the)h (follo)m(wing)h(prepro)s(cessing)0 3786 y(statemen)m(ts)f(in)e(their)h (C)f(programs)g(to)h(handle)f(this)g(in)g(a)h(mac)m(hine-p)s(ortable)g (manner:)0 4052 y Fe(#if)47 b(defined\(_MSC_VER\))c(/*)k(Microsoft)e (Visual)i(C++)f(*/)477 4165 y(printf\("\045I64d",)e(longlongvalue\);)0 4391 y(#elif)i(\(USE_LL_SUFFIX)e(==)j(1\))477 4504 y (printf\("\045lld",)d(longlongvalue\);)0 4730 y(#else)477 4843 y(printf\("\045ld",)g(longlongvalue\);)0 4956 y(#endif)0 5222 y Fj(Similarly)-8 b(,)32 b(the)f(name)g(of)g(the)h(C)e(utilit)m(y) j(routine)e(that)g(con)m(v)m(erts)i(a)e(c)m(haracter)i(string)d(of)i (digits)f(in)m(to)h(a)g(8-b)m(yte)0 5335 y(in)m(teger)g(v)-5 b(alue)31 b(is)f(platform)g(dep)s(enden)m(t:)0 5601 y Fe(#if)47 b(defined\(_MSC_VER\))c(/*)k(Microsoft)e(Visual)i(C++)f(*/) 286 5714 y(/*)i(VC++)e(6.0)h(does)g(not)g(seem)f(to)h(have)g(an)g (8-byte)f(conversion)f(routine)h(*/)p eop end %%Page: 20 28 TeXDict begin 20 27 bop 0 299 a Fj(20)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 668 y Fe(#elif)46 b(\(USE_LL_SUFFIX)e(==)j(1\))477 781 y(longlongvalue)d(=)k (atoll\(*string\);)0 1007 y(#else)477 1120 y(longlongvalue)c(=)k (atol\(*string\);)0 1233 y(#endif)0 1475 y Fj(When)23 b(dealing)h(with)f(the)h(FITS)f(b)m(yte)h(data)g(t)m(yp)s(e)f(it)h(is)g (imp)s(ortan)m(t)f(to)h(remem)m(b)s(er)f(that)h(the)g(ra)m(w)f(v)-5 b(alues)24 b(\(b)s(efore)0 1588 y(an)m(y)h(scaling)g(b)m(y)f(the)h (BSCALE)e(and)h(BZER)m(O,)g(or)h(TSCALn)d(and)i(TZER)m(On)f(k)m(eyw)m (ord)i(v)-5 b(alues\))25 b(in)f(b)m(yte)h(arra)m(ys)0 1700 y(\(BITPIX)37 b(=)f(8\))h(or)f(b)m(yte)i(columns)e(\(TF)m(ORMn)h (=)f('B'\))h(are)g(in)m(terpreted)g(as)g(unsigned)e(b)m(ytes)i(with)g (v)-5 b(alues)0 1813 y(ranging)34 b(from)g(0)g(to)h(255.)53 b(Some)34 b(C)g(compilers)h(de\014ne)e(a)h('c)m(har')h(v)-5 b(ariable)35 b(as)g(signed,)g(so)f(it)h(is)f(imp)s(ortan)m(t)g(to)0 1926 y(explicitly)e(declare)f(a)g(n)m(umeric)f(c)m(har)h(v)-5 b(ariable)31 b(as)g('unsigned)e(c)m(har')i(to)g(a)m(v)m(oid)h(an)m(y)f (am)m(biguit)m(y)0 2086 y(One)22 b(feature)h(of)g(the)g(CFITSIO)e (routines)i(is)f(that)i(they)f(can)g(op)s(erate)g(on)f(a)h(`X')h (\(bit\))f(column)g(in)f(a)h(binary)f(table)0 2199 y(as)33 b(though)f(it)h(w)m(ere)g(a)g(`B')g(\(b)m(yte\))h(column.)47 b(F)-8 b(or)33 b(example)g(a)g(`11X')h(data)f(t)m(yp)s(e)g(column)f (can)h(b)s(e)f(in)m(terpreted)0 2312 y(the)c(same)h(as)f(a)g(`2B')i (column)e(\(i.e.,)i(2)e(unsigned)f(8-bit)i(b)m(ytes\).)41 b(In)27 b(some)i(instances,)g(it)f(can)h(b)s(e)e(more)h(e\016cien)m(t)0 2425 y(to)j(read)f(and)g(write)h(whole)f(b)m(ytes)h(at)g(a)g(time,)g (rather)g(than)f(reading)g(or)h(writing)f(eac)m(h)i(individual)d(bit.)0 2585 y(The)36 b(complex)i(and)e(double)h(precision)g(complex)h(data)g (t)m(yp)s(es)f(are)g(not)g(directly)h(supp)s(orted)d(in)i(ANSI)f(C)h (so)0 2698 y(these)g(data)g(t)m(yp)s(es)f(should)f(b)s(e)h(in)m (terpreted)h(as)f(pairs)g(of)h(\015oat)g(or)f(double)g(v)-5 b(alues,)38 b(resp)s(ectiv)m(ely)-8 b(,)40 b(where)c(the)0 2811 y(\014rst)30 b(v)-5 b(alue)30 b(in)h(eac)m(h)g(pair)f(is)h(the)f (real)h(part,)g(and)e(the)i(second)f(is)h(the)f(imaginary)h(part.)0 3142 y Ff(4.4)135 b(Supp)t(ort)44 b(for)h(Unsigned)h(In)l(tegers)g(and) f(Signed)g(Bytes)0 3392 y Fj(Although)33 b(FITS)f(do)s(es)g(not)h (directly)h(supp)s(ort)d(unsigned)g(in)m(tegers)j(as)f(one)g(of)g(its)h (fundamen)m(tal)e(data)i(t)m(yp)s(es,)0 3505 y(FITS)27 b(can)h(still)h(b)s(e)e(used)g(to)i(e\016cien)m(tly)h(store)e(unsigned) f(in)m(teger)i(data)g(v)-5 b(alues)28 b(in)g(images)h(and)e(binary)g (tables.)0 3618 y(The)42 b(con)m(v)m(en)m(tion)j(used)d(in)g(FITS)g (\014les)h(is)f(to)i(store)f(the)g(unsigned)e(in)m(tegers)j(as)f (signed)g(in)m(tegers)h(with)e(an)0 3731 y(asso)s(ciated)34 b(o\013set)f(\(sp)s(eci\014ed)f(b)m(y)g(the)g(BZER)m(O)g(or)g(TZER)m (On)f(k)m(eyw)m(ord\).)47 b(F)-8 b(or)33 b(example,)g(to)g(store)g (unsigned)0 3844 y(16-bit)g(in)m(teger)g(v)-5 b(alues)32 b(in)f(a)h(FITS)f(image)i(the)e(image)i(w)m(ould)f(b)s(e)e(de\014ned)h (as)h(a)g(signed)f(16-bit)i(in)m(teger)g(\(with)0 3957 y(BITPIX)c(k)m(eyw)m(ord)g(=)g(SHOR)-8 b(T)p 1132 3957 28 4 v 32 w(IMG)30 b(=)e(16\))j(with)d(the)i(k)m(eyw)m(ords)f(BSCALE)f (=)h(1.0)h(and)f(BZER)m(O)g(=)f(32768.)0 4070 y(Th)m(us)34 b(the)h(unsigned)f(v)-5 b(alues)35 b(of)g(0,)i(32768,)h(and)d(65535,)j (for)d(example,)i(are)e(ph)m(ysically)h(stored)f(in)g(the)g(FITS)0 4183 y(image)40 b(as)e(-32768,)43 b(0,)e(and)d(32767,)k(resp)s(ectiv)m (ely;)i(CFITSIO)37 b(automatically)k(adds)c(the)i(BZER)m(O)f(o\013set)h (to)0 4296 y(these)g(v)-5 b(alues)39 b(when)f(they)g(are)h(read.)65 b(Similarly)-8 b(,)42 b(in)c(the)h(case)h(of)e(unsigned)g(32-bit)i(in)m (tegers)f(the)g(BITPIX)0 4408 y(k)m(eyw)m(ord)c(w)m(ould)f(b)s(e)g (equal)h(to)h(LONG)p 1392 4408 V 32 w(IMG)f(=)g(32)g(and)f(BZER)m(O)g (w)m(ould)h(b)s(e)f(equal)h(to)g(2147483648)k(\(i.e.)55 b(2)0 4521 y(raised)30 b(to)h(the)g(31st)g(p)s(o)m(w)m(er\).)0 4681 y(The)j(CFITSIO)g(in)m(terface)i(routines)f(will)g(e\016cien)m (tly)i(and)d(transparen)m(tly)i(apply)e(the)h(appropriate)g(o\013set)h (in)0 4794 y(these)29 b(cases)h(so)f(in)g(general)h(application)g (programs)f(do)g(not)g(need)f(to)i(b)s(e)e(concerned)h(with)g(ho)m(w)g (the)g(unsigned)0 4907 y(v)-5 b(alues)33 b(are)h(actually)g(stored)g (in)e(the)i(FITS)e(\014le.)49 b(As)33 b(a)g(con)m(v)m(enience)i(for)e (users,)g(CFITSIO)f(has)h(sev)m(eral)h(pre-)0 5020 y(de\014ned)f (constan)m(ts)i(for)e(the)h(v)-5 b(alue)35 b(of)f(BITPIX)f(\(USHOR)-8 b(T)p 2153 5020 V 33 w(IMG,)35 b(ULONG)p 2768 5020 V 33 w(IMG,)f(ULONGLONG)p 3649 5020 V 33 w(IMG\))0 5133 y(and)j(for)g(the)g(TF)m(ORMn)g(v)-5 b(alue)38 b(in)f(the)g(case)h(of)g (binary)e(tables)i(\(`U',)g(`V',)h(and)d(`W'\))j(whic)m(h)e (programmers)0 5246 y(can)31 b(use)g(when)f(creating)i(FITS)e(\014les)h (con)m(taining)h(unsigned)e(in)m(teger)i(v)-5 b(alues.)42 b(The)31 b(follo)m(wing)h(co)s(de)f(fragmen)m(t)0 5359 y(illustrates)g(ho)m(w)g(to)g(write)g(a)f(FITS)g(1-D)h(primary)f(arra)m (y)h(of)f(unsigned)g(16-bit)h(in)m(tegers:)286 5601 y Fe(unsigned)46 b(short)g(uarray[100];)286 5714 y(int)h(naxis,)f (status;)p eop end %%Page: 21 29 TeXDict begin 21 28 bop 0 299 a Fh(4.4.)72 b(SUPPOR)-8 b(T)30 b(F)m(OR)g(UNSIGNED)h(INTEGERS)f(AND)h(SIGNED)f(BYTES)942 b Fj(21)286 555 y Fe(long)47 b(naxes[10],)e(group,)h(firstelem,)f (nelements;)334 668 y(...)286 781 y(status)h(=)i(0;)286 894 y(naxis)f(=)g(1;)286 1007 y(naxes[0])f(=)h(100;)286 1120 y(fits_create_img\(fptr,)42 b(USHORT_IMG,)j(naxis,)h(naxes,)g (&status\);)286 1346 y(firstelem)g(=)h(1;)286 1458 y(nelements)f(=)h (100;)286 1571 y(fits_write_img\(fptr,)c(TUSHORT,)i(firstelem,)g (nelements,)1241 1684 y(uarray,)h(&status\);)334 1797 y(...)0 2038 y Fj(In)40 b(the)h(ab)s(o)m(v)m(e)i(example,)h(the)e(2nd)e (parameter)h(in)g(\014ts)p 1998 2038 28 4 v 33 w(create)p 2267 2038 V 34 w(img)g(tells)h(CFITSIO)e(to)i(write)f(the)g(header)0 2151 y(k)m(eyw)m(ords)34 b(appropriate)g(for)f(an)g(arra)m(y)i(of)e (16-bit)i(unsigned)e(in)m(tegers)i(\(i.e.,)h(BITPIX)d(=)g(16)i(and)e (BZER)m(O)g(=)0 2264 y(32768\).)41 b(Then)23 b(the)h(\014ts)p 834 2264 V 32 w(write)p 1068 2264 V 33 w(img)h(routine)f(writes)f(the)i (arra)m(y)f(of)g(unsigned)f(short)g(in)m(tegers)i(\(uarra)m(y\))g(in)m (to)g(the)0 2377 y(primary)f(arra)m(y)h(of)g(the)g(FITS)f(\014le.)39 b(Similarly)-8 b(,)27 b(a)e(32-bit)i(unsigned)c(in)m(teger)j(image)h (ma)m(y)e(b)s(e)f(created)i(b)m(y)f(setting)0 2490 y(the)34 b(second)f(parameter)h(in)f(\014ts)p 1130 2490 V 33 w(create)p 1399 2490 V 34 w(img)h(equal)g(to)g(`ULONG)p 2330 2490 V 33 w(IMG')g(and)f(b)m(y)h(calling)g(the)g(\014ts)p 3491 2490 V 33 w(write)p 3726 2490 V 33 w(img)0 2603 y(routine)j(with)f(the)h(second)f(parameter)h(=)f(TULONG)h(to)g(write)g (the)f(arra)m(y)h(of)g(unsigned)f(long)h(image)h(pixel)0 2716 y(v)-5 b(alues.)0 2876 y(An)27 b(analogous)h(set)f(of)g(routines)g (are)g(a)m(v)-5 b(ailable)30 b(for)c(reading)h(or)g(writing)g(unsigned) f(in)m(teger)i(v)-5 b(alues)28 b(and)e(signed)0 2989 y(b)m(yte)i(v)-5 b(alues)28 b(in)g(a)g(FITS)f(binary)g(table)i (extension.)40 b(When)28 b(sp)s(ecifying)f(the)h(TF)m(ORMn)g(k)m(eyw)m (ord)g(v)-5 b(alue)28 b(whic)m(h)0 3102 y(de\014nes)37 b(the)h(format)g(of)g(a)h(column,)h(CFITSIO)c(recognizes)j(4)g (additional)g(data)f(t)m(yp)s(e)g(co)s(des)g(b)s(esides)f(those)0 3215 y(already)j(de\014ned)e(in)g(the)i(FITS)e(standard:)57 b(`U')40 b(meaning)f(a)h(16-bit)g(unsigned)e(in)m(teger)j(column,)g (`V')f(for)f(a)0 3328 y(32-bit)29 b(unsigned)f(in)m(teger)h(column,)g (`W')g(for)f(a)g(64-bit)i(unsigned)d(in)m(teger)i(column,)g(and)f('S')g (for)g(a)g(signed)g(b)m(yte)0 3440 y(column.)39 b(These)24 b(non-standard)f(data)j(t)m(yp)s(e)e(co)s(des)h(are)g(not)g(actually)h (written)e(in)m(to)i(the)e(FITS)g(\014le)h(but)f(instead)0 3553 y(are)30 b(just)f(used)g(in)m(ternally)i(within)e(CFITSIO.)f(The)i (follo)m(wing)h(co)s(de)f(fragmen)m(t)g(illustrates)h(ho)m(w)f(to)g (use)f(these)0 3666 y(features:)286 3907 y Fe(unsigned)46 b(short)g(uarray[100];)286 4020 y(unsigned)g(int)95 b(varray[100];)286 4246 y(int)47 b(colnum,)f(tfields,)g(status;)286 4359 y(long)h(nrows,)f(firstrow,)f(firstelem,)g(nelements,)g(pcount;)286 4585 y(char)i(extname[])e(=)j("Test_table";)521 b(/*)47 b(extension)f(name)g(*/)286 4811 y(/*)i(define)e(the)h(name,)f(data)h (type,)f(and)h(physical)e(units)i(for)g(4)g(columns)f(*/)286 4924 y(char)h(*ttype[])f(=)h({)g("Col_1",)f("Col_2",)g("Col_3",)f ("Col_4")h(};)286 5036 y(char)h(*tform[])f(=)h({)g("1U",)285 b("1V",)190 b("1W",)g("1S"};)93 b(/*)48 b(special)d(CFITSIO)h(codes)h (*/)286 5149 y(char)g(*tunit[])f(=)h({)g(")h(",)381 b(")48 b(",)190 b(")47 b(",)191 b(")47 b(")h(};)334 5262 y(...)525 5488 y(/*)f(write)g(the)f(header)h(keywords)e(*/)286 5601 y(status)94 b(=)48 b(0;)286 5714 y(nrows)142 b(=)48 b(1;)p eop end %%Page: 22 30 TeXDict begin 22 29 bop 0 299 a Fj(22)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)286 555 y Fe(tfields)46 b(=)i(3)286 668 y(pcount)94 b(=)48 b(0;)286 781 y (fits_create_tbl\(fptr,)42 b(BINARY_TBL,)j(nrows,)h(tfields,)g(ttype,)g (tform,)764 894 y(tunit,)g(extname,)f(&status\);)525 1120 y(/*)i(write)g(the)f(unsigned)g(shorts)g(to)h(the)g(1st)g(column)f (*/)286 1233 y(colnum)190 b(=)47 b(1;)286 1346 y(firstrow)94 b(=)47 b(1;)286 1458 y(firstelem)f(=)h(1;)286 1571 y(nelements)f(=)h (100;)286 1684 y(fits_write_col\(fptr,)c(TUSHORT,)i(colnum,)h (firstrow,)f(firstelem,)668 1797 y(nelements,)g(uarray,)h(&status\);) 525 2023 y(/*)h(now)g(write)f(the)h(unsigned)f(longs)g(to)h(the)g(2nd)g (column)f(*/)286 2136 y(colnum)190 b(=)47 b(2;)286 2249 y(fits_write_col\(fptr,)c(TUINT,)j(colnum,)g(firstrow,)f(firstelem,)668 2362 y(nelements,)g(varray,)h(&status\);)334 2475 y(...)0 2752 y Fj(Note)34 b(that)e(the)h(non-standard)e(TF)m(ORM)i(v)-5 b(alues)32 b(for)g(the)h(3)f(columns,)h(`U',)g(`V',)g(and)f(`W')h(tell) g(CFITSIO)e(to)0 2865 y(write)i(the)g(k)m(eyw)m(ords)g(appropriate)f (for)h(unsigned)e(16-bit,)k(unsigned)c(32-bit)j(and)e(unsigned)g (64-bit)h(in)m(tegers,)0 2978 y(resp)s(ectiv)m(ely)27 b(\(i.e.,)i(TF)m(ORMn)d(=)f('1I')i(and)f(TZER)m(On)e(=)i(32768)i(for)e (unsigned)f(16-bit)i(in)m(tegers,)h(TF)m(ORMn)e(=)0 3091 y('1J')j(and)g(TZER)m(On)e(=)h(2147483648)34 b(for)28 b(unsigned)g(32-bit)i(in)m(tegers,)h(and)d(TF)m(ORMn)g(=)h('1K')g(and)f (TZER)m(On)0 3204 y(=)34 b(92233720368547)q(758)q(08)41 b(for)35 b(unsigned)e(64-bit)j(in)m(tegers\).)55 b(The)34 b('S')g(TF)m(ORMn)h(v)-5 b(alue)35 b(tells)g(CFITSIO)e(to)0 3317 y(write)26 b(the)f(k)m(eyw)m(ords)h(appropriate)g(for)f(a)h (signed)f(8-bit)i(b)m(yte)f(column)f(with)g(TF)m(ORMn)h(=)f('1B')h(and) f(TZER)m(On)0 3430 y(=)30 b(-128.)42 b(The)29 b(calls)j(to)e(\014ts)p 959 3430 28 4 v 33 w(write)p 1194 3430 V 33 w(col)h(then)e(write)i(the) f(arra)m(ys)g(of)g(unsigned)f(in)m(teger)j(v)-5 b(alues)30 b(to)h(the)f(columns.)0 3784 y Ff(4.5)135 b(Dealing)47 b(with)e(Character)h(Strings)0 4039 y Fj(The)36 b(c)m(haracter)j (string)d(v)-5 b(alues)38 b(in)e(a)h(FITS)f(header)h(or)g(in)f(an)h (ASCI)s(I)e(column)i(in)f(a)i(FITS)e(table)h(extension)0 4152 y(are)i(generally)i(padded)d(out)h(with)g(non-signi\014can)m(t)h (space)f(c)m(haracters)i(\(ASCI)s(I)d(32\))i(to)g(\014ll)f(up)f(the)h (header)0 4264 y(record)33 b(or)h(the)f(column)h(width.)49 b(When)33 b(reading)h(a)g(FITS)e(string)i(v)-5 b(alue,)35 b(the)e(CFITSIO)f(routines)i(will)f(strip)0 4377 y(o\013)38 b(these)f(non-signi\014can)m(t)h(trailing)g(spaces)f(and)g(will)g (return)f(a)i(n)m(ull-terminated)g(string)f(v)-5 b(alue)37 b(con)m(taining)0 4490 y(only)d(the)g(signi\014can)m(t)g(c)m (haracters.)52 b(Leading)34 b(spaces)g(in)g(a)g(FITS)f(string)g(are)h (considered)g(signi\014can)m(t.)52 b(If)33 b(the)0 4603 y(string)i(con)m(tains)h(all)g(blanks,)g(then)e(CFITSIO)g(will)h (return)f(a)h(single)g(blank)g(c)m(haracter,)j(i.e,)f(the)e(\014rst)f (blank)0 4716 y(is)c(considered)f(to)i(b)s(e)e(signi\014can)m(t,)i (since)f(it)g(distinguishes)g(the)g(string)f(from)h(a)g(n)m(ull)f(or)h (unde\014ned)e(string,)i(but)0 4829 y(the)h(remaining)f(trailing)h (spaces)g(are)g(not)g(signi\014can)m(t.)0 4989 y(Similarly)-8 b(,)41 b(when)c(writing)h(string)g(v)-5 b(alues)38 b(to)h(a)g(FITS)e (\014le)h(the)g(CFITSIO)f(routines)h(exp)s(ect)g(to)h(get)g(a)g(n)m (ull-)0 5102 y(terminated)33 b(string)g(as)g(input;)g(CFITSIO)e(will)i (pad)f(the)h(string)g(with)f(blanks)g(if)h(necessary)g(when)f(writing)g (it)0 5215 y(to)f(the)g(FITS)e(\014le.)0 5375 y(The)k(FITS)f(standard)g (do)s(es)h(not)g(require)g(trailing)h(spaces)f(to)h(b)s(e)e(treated)i (in)f(this)g(w)m(a)m(y)-8 b(,)35 b(but)e(it)g(do)s(es)g(allo)m(w)i(a)0 5488 y(more)d(seamless)h(transition)f(from)g(the)g(F)m(OR)-8 b(TRAN)33 b(FITS)e(w)m(orld)h(where)g(trailing)h(spaces)f(are)g(often)h (treated)0 5601 y(as)k(insigni\014can)m(t.)60 b(Users)36 b(who)g(wish)g(the)h(greatest)h(\014delit)m(y)f(when)f(transferring)g (strings)g(can)h(use)f(the)h Fe(_byt)0 5714 y Fj(v)-5 b(arian)m(ts)40 b(of)f(column)g(readers)g(and)f(writers)h(\(functions)g (\014ts)p 2176 5714 V 32 w Fc(f)p Fj(read,write)p Fc(g)p 2697 5714 V 35 w Fj(col)p 2842 5714 V 33 w(b)m(yt\).)68 b(These)39 b(routines)g(will)p eop end %%Page: 23 31 TeXDict begin 23 30 bop 0 299 a Fh(4.6.)72 b(IMPLICIT)29 b(D)m(A)-8 b(T)g(A)32 b(TYPE)e(CONVERSION)1938 b Fj(23)0 555 y(transfer)26 b(the)g(ra)m(w)h(\014xed-length)f(v)m(ectors)i(of)f (c)m(haracter)g(b)m(ytes)g(of)g(the)f(column,)h(including)f(an)m(y)h (trailing)g(blanks)0 668 y(of)38 b(course.)62 b(The)37 b Fe(_byt)f Fj(v)-5 b(arian)m(ts)38 b(mak)m(e)h(no)e(attempt)i(to)f(n)m (ull-terminate)h(an)m(y)f(elemen)m(ts.)63 b(A)38 b(NULL)f(string)0 781 y(w)m(ould)30 b(b)s(e)g(indicated)h(b)m(y)f(its)h(\014rst)e(c)m (haracter)j(b)s(eing)e(a)h(NUL)g(b)m(yte.)0 941 y(When)h(calling)i (CFITSIO)d(routines)i(that)g(return)e(a)i(c)m(haracter)h(string)f(it)g (is)f(vital)i(that)f(the)g(size)g(of)g(the)g(c)m(har)0 1054 y(arra)m(y)38 b(b)s(e)g(large)h(enough)e(to)i(hold)e(the)h(en)m (tire)h(string)f(of)g(c)m(haracters,)k(otherwise)c(CFITSIO)e(will)i(o)m (v)m(erwrite)0 1167 y(whatev)m(er)d(memory)e(lo)s(cations)i(follo)m(w)g (the)f(c)m(har)h(arra)m(y)-8 b(,)35 b(p)s(ossibly)e(causing)h(the)g (program)g(to)g(execute)h(incor-)0 1280 y(rectly)-8 b(.)42 b(This)30 b(t)m(yp)s(e)g(of)h(error)f(can)h(b)s(e)f(di\016cult)g(to)h (debug,)f(so)h(programmers)f(should)f(alw)m(a)m(ys)j(ensure)e(that)h (the)0 1393 y(c)m(har)c(arra)m(ys)g(are)g(allo)s(cated)i(enough)d (space)i(to)f(hold)g(the)f(longest)i(p)s(ossible)f(string,)g Fi(including)h Fj(the)f(terminat-)0 1506 y(ing)k(NULL)g(c)m(haracter.) 45 b(The)30 b(\014tsio.h)h(\014le)h(con)m(tains)g(the)f(follo)m(wing)i (de\014ned)d(constan)m(ts)i(whic)m(h)f(programmers)0 1619 y(are)g(strongly)g(encouraged)g(to)g(use)f(whenev)m(er)g(they)h (are)f(allo)s(cating)j(space)e(for)f(c)m(har)h(arra)m(ys:)0 1834 y Fe(#define)46 b(FLEN_FILENAME)e(1025)j(/*)g(max)g(length)f(of)h (a)g(filename)f(*/)0 1947 y(#define)g(FLEN_KEYWORD)140 b(72)95 b(/*)47 b(max)g(length)f(of)h(a)g(keyword)94 b(*/)0 2060 y(#define)46 b(FLEN_CARD)284 b(81)95 b(/*)47 b(length)f(of)h(a)h(FITS)e(header)g(card)h(*/)0 2173 y(#define)f(FLEN_VALUE)236 b(71)95 b(/*)47 b(max)g(length)f(of)h(a)g (keyword)f(value)h(string)f(*/)0 2286 y(#define)g(FLEN_COMMENT)140 b(73)95 b(/*)47 b(max)g(length)f(of)h(a)g(keyword)f(comment)g(string)g (*/)0 2399 y(#define)g(FLEN_ERRMSG)188 b(81)95 b(/*)47 b(max)g(length)f(of)h(a)g(CFITSIO)f(error)h(message)e(*/)0 2512 y(#define)h(FLEN_STATUS)188 b(31)95 b(/*)47 b(max)g(length)f(of)h (a)g(CFITSIO)f(status)g(text)h(string)f(*/)0 2727 y Fj(F)-8 b(or)23 b(example,)h(when)d(declaring)i(a)f(c)m(har)g(arra)m(y)h(to)f (hold)g(the)g(v)-5 b(alue)22 b(string)g(of)g(FITS)f(k)m(eyw)m(ord,)k (use)c(the)h(follo)m(wing)0 2840 y(statemen)m(t:)191 3055 y Fe(char)47 b(value[FLEN_VALUE];)0 3271 y Fj(Note)41 b(that)f(FLEN)p 686 3271 28 4 v 33 w(KEYW)m(ORD)g(is)f(longer)h(than)f (needed)g(for)g(the)h(nominal)f(8-c)m(haracter)j(k)m(eyw)m(ord)e(name)0 3384 y(b)s(ecause)30 b(the)h(HIERAR)m(CH)f(con)m(v)m(en)m(tion)j(supp)s (orts)28 b(longer)j(k)m(eyw)m(ord)g(names.)0 3710 y Ff(4.6)135 b(Implicit)46 b(Data)g(T)l(yp)t(e)f(Con)l(v)l(ersion)0 3961 y Fj(The)29 b(CFITSIO)e(routines)i(that)h(read)f(and)f(write)i(n)m (umerical)f(data)h(can)g(p)s(erform)d(implicit)j(data)g(t)m(yp)s(e)f (con)m(v)m(er-)0 4074 y(sion.)39 b(This)25 b(means)h(that)g(the)g(data) g(t)m(yp)s(e)g(of)g(the)g(v)-5 b(ariable)26 b(or)g(arra)m(y)g(in)f(the) h(program)g(do)s(es)f(not)h(need)f(to)i(b)s(e)e(the)0 4186 y(same)g(as)f(the)h(data)g(t)m(yp)s(e)g(of)f(the)h(v)-5 b(alue)25 b(in)f(the)g(FITS)g(\014le.)39 b(Data)26 b(t)m(yp)s(e)f(con)m (v)m(ersion)g(is)g(supp)s(orted)d(for)i(n)m(umerical)0 4299 y(and)37 b(string)g(data)g(t)m(yp)s(es)h(\(if)f(the)g(string)g (con)m(tains)i(a)e(v)-5 b(alid)38 b(n)m(um)m(b)s(er)e(enclosed)h(in)g (quotes\))h(when)e(reading)i(a)0 4412 y(FITS)30 b(header)h(k)m(eyw)m (ord)g(v)-5 b(alue)31 b(and)f(for)h(n)m(umeric)g(v)-5 b(alues)31 b(when)f(reading)h(or)f(writing)h(v)-5 b(alues)31 b(in)g(the)g(primary)0 4525 y(arra)m(y)24 b(or)g(a)h(table)f(column.)39 b(CFITSIO)22 b(returns)h(status)h(=)f(NUM)p 2267 4525 V 34 w(O)m(VERFLO)m(W)i(if)e(the)h(con)m(v)m(erted)i(data)e(v)-5 b(alue)0 4638 y(exceeds)33 b(the)g(range)g(of)g(the)f(output)g(data)i (t)m(yp)s(e.)47 b(Implicit)33 b(data)g(t)m(yp)s(e)g(con)m(v)m(ersion)h (is)e(not)h(supp)s(orted)d(within)0 4751 y(binary)g(tables)h(for)f (string,)g(logical,)k(complex,)d(or)f(double)g(complex)h(data)g(t)m(yp) s(es.)0 4911 y(In)g(addition,)h(an)m(y)f(table)h(column)f(ma)m(y)h(b)s (e)f(read)g(as)h(if)f(it)h(con)m(tained)g(string)f(v)-5 b(alues.)44 b(In)31 b(the)g(case)i(of)e(n)m(umeric)0 5024 y(columns)f(the)h(returned)e(string)h(will)h(b)s(e)f(formatted)h (using)e(the)i(TDISPn)e(displa)m(y)i(format)f(if)h(it)g(exists.)0 5351 y Ff(4.7)135 b(Data)46 b(Scaling)0 5601 y Fj(When)38 b(reading)f(n)m(umerical)i(data)f(v)-5 b(alues)38 b(in)f(the)h(primary) f(arra)m(y)h(or)g(a)g(table)h(column,)h(the)d(v)-5 b(alues)38 b(will)h(b)s(e)0 5714 y(scaled)f(automatically)j(b)m(y)c(the)g(BSCALE)g (and)g(BZER)m(O)g(\(or)h(TSCALn)e(and)h(TZER)m(On\))f(header)h(v)-5 b(alues)38 b(if)p eop end %%Page: 24 32 TeXDict begin 24 31 bop 0 299 a Fj(24)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(they)f(are)f (presen)m(t)h(in)f(the)g(header.)41 b(The)30 b(scaled)h(data)g(that)g (is)f(returned)g(to)h(the)f(reading)h(program)f(will)h(ha)m(v)m(e)382 875 y Fe(output)46 b(value)g(=)i(\(FITS)e(value\))g(*)i(BSCALE)e(+)h (BZERO)0 1196 y Fj(\(a)30 b(corresp)s(onding)e(form)m(ula)h(using)g (TSCALn)e(and)i(TZER)m(On)e(is)i(used)g(when)f(reading)h(from)g(table)h (columns\).)0 1308 y(In)h(the)i(case)g(of)f(in)m(teger)h(output)f(v)-5 b(alues)32 b(the)h(\015oating)g(p)s(oin)m(t)f(scaled)g(v)-5 b(alue)33 b(is)f(truncated)g(to)h(an)f(in)m(teger)h(\(not)0 1421 y(rounded)i(to)j(the)f(nearest)h(in)m(teger\).)62 b(The)36 b(\014ts)p 1673 1421 28 4 v 32 w(set)p 1816 1421 V 34 w(bscale)i(and)e(\014ts)p 2430 1421 V 32 w(set)p 2573 1421 V 34 w(tscale)i(routines)f(\(describ)s(ed)f(in)h(the)0 1534 y(`Adv)-5 b(anced')29 b(c)m(hapter\))h(ma)m(y)g(b)s(e)e(used)h(to) g(o)m(v)m(erride)i(the)e(scaling)h(parameters)f(de\014ned)f(in)h(the)g (header)g(\(e.g.,)i(to)0 1647 y(turn)e(o\013)i(the)g(scaling)g(so)g (that)g(the)f(program)g(can)h(read)f(the)h(ra)m(w)f(unscaled)h(v)-5 b(alues)30 b(from)g(the)h(FITS)e(\014le\).)0 1807 y(When)44 b(writing)h(n)m(umerical)g(data)g(to)g(the)g(primary)f(arra)m(y)h(or)f (to)h(a)g(table)h(column)e(the)h(data)g(v)-5 b(alues)45 b(will)0 1920 y(generally)29 b(b)s(e)f(automatically)j(in)m(v)m(ersely) f(scaled)f(b)m(y)f(the)g(v)-5 b(alue)29 b(of)f(the)h(BSCALE)e(and)h (BZER)m(O)g(\(or)h(TSCALn)0 2033 y(and)35 b(TZER)m(On\))f(k)m(eyw)m (ord)i(v)-5 b(alues)35 b(if)h(they)f(they)g(exist)i(in)e(the)g(header.) 55 b(These)35 b(k)m(eyw)m(ords)h(m)m(ust)f(ha)m(v)m(e)i(b)s(een)0 2146 y(written)31 b(to)h(the)g(header)f(b)s(efore)g(an)m(y)g(data)h(is) g(written)f(for)g(them)g(to)h(ha)m(v)m(e)h(an)m(y)e(immediate)i (e\013ect.)45 b(One)30 b(ma)m(y)0 2259 y(also)h(use)g(the)f(\014ts)p 623 2259 V 33 w(set)p 767 2259 V 33 w(bscale)i(and)d(\014ts)p 1367 2259 V 33 w(set)p 1511 2259 V 33 w(tscale)j(routines)f(to)g (de\014ne)f(or)g(o)m(v)m(erride)i(the)f(scaling)g(k)m(eyw)m(ords)g(in)0 2372 y(the)e(header)g(\(e.g.,)i(to)e(turn)f(o\013)h(the)g(scaling)h(so) f(that)h(the)f(program)f(can)h(write)g(the)g(ra)m(w)g(unscaled)g(v)-5 b(alues)29 b(in)m(to)0 2485 y(the)d(FITS)g(\014le\).)40 b(If)25 b(scaling)i(is)g(p)s(erformed,)e(the)i(in)m(v)m(erse)g(scaled)g (output)e(v)-5 b(alue)27 b(that)g(is)f(written)g(in)m(to)h(the)g(FITS)0 2598 y(\014le)j(will)h(ha)m(v)m(e)430 2918 y Fe(FITS)46 b(value)h(=)g(\(\(input)f(value\))g(-)h(BZERO\))f(/)i(BSCALE)0 3238 y Fj(\(a)39 b(corresp)s(onding)d(form)m(ula)i(using)g(TSCALn)e (and)h(TZER)m(On)g(is)h(used)f(when)f(writing)i(to)h(table)g (columns\).)0 3351 y(Rounding)34 b(to)i(the)g(nearest)g(in)m(teger,)i (rather)d(than)g(truncation,)j(is)d(p)s(erformed)f(when)g(writing)h(in) m(teger)i(data)0 3464 y(t)m(yp)s(es)30 b(to)i(the)e(FITS)g(\014le.)0 3869 y Ff(4.8)135 b(Supp)t(ort)44 b(for)h(IEEE)h(Sp)t(ecial)f(V)-11 b(alues)0 4133 y Fj(The)26 b(ANSI/IEEE-754)h(\015oating-p)s(oin)m(t)h (n)m(um)m(b)s(er)d(standard)g(de\014nes)h(certain)h(sp)s(ecial)g(v)-5 b(alues)26 b(that)h(are)g(used)e(to)0 4246 y(represen)m(t)j(suc)m(h)g (quan)m(tities)h(as)f(Not-a-Num)m(b)s(er)h(\(NaN\),)h(denormalized,)f (under\015o)m(w,)e(o)m(v)m(er\015o)m(w,)j(and)d(in\014nit)m(y)-8 b(.)0 4359 y(\(See)31 b(the)g(App)s(endix)d(in)j(the)f(FITS)g(standard) f(or)i(the)g(FITS)e(User's)i(Guide)f(for)g(a)h(list)g(of)g(these)g(v)-5 b(alues\).)41 b(The)0 4472 y(CFITSIO)31 b(routines)i(that)g(read)f (\015oating)i(p)s(oin)m(t)f(data)g(in)f(FITS)g(\014les)h(recognize)h (these)f(IEEE)f(sp)s(ecial)i(v)-5 b(alues)0 4585 y(and)27 b(b)m(y)h(default)h(in)m(terpret)f(the)h(o)m(v)m(er\015o)m(w)g(and)f (in\014nit)m(y)f(v)-5 b(alues)29 b(as)f(b)s(eing)g(equiv)-5 b(alen)m(t)29 b(to)g(a)g(NaN,)g(and)e(con)m(v)m(ert)0 4698 y(the)37 b(under\015o)m(w)e(and)i(denormalized)g(v)-5 b(alues)37 b(in)m(to)h(zeros.)60 b(In)36 b(some)i(cases)f(programmers)g (ma)m(y)g(w)m(an)m(t)h(access)0 4811 y(to)d(the)g(ra)m(w)f(IEEE)g(v)-5 b(alues,)36 b(without)e(an)m(y)h(mo)s(di\014cation)g(b)m(y)f(CFITSIO.)f (This)h(can)h(b)s(e)e(done)i(b)m(y)f(calling)i(the)0 4924 y(\014ts)p 127 4924 V 32 w(read)p 331 4924 V 33 w(img)27 b(or)g(\014ts)p 767 4924 V 32 w(read)p 971 4924 V 33 w(col)g(routines)g(while)f(sp)s(ecifying)h(0.0)h(as)e(the)h(v)-5 b(alue)27 b(of)g(the)g(NULL)-10 b(V)g(AL)26 b(parameter.)0 5036 y(This)44 b(will)h(force)h(CFITSIO)d(to)i(simply)g(pass)f(the)h (IEEE)f(v)-5 b(alues)45 b(through)f(to)i(the)f(application)h(program)0 5149 y(without)38 b(an)m(y)h(mo)s(di\014cation.)65 b(This)37 b(is)h(not)h(fully)f(supp)s(orted)e(on)i(V)-10 b(AX/VMS)40 b(mac)m(hines,)h(ho)m(w)m(ev)m(er,)g(where)0 5262 y(there)34 b(is)f(no)g(easy)h(w)m(a)m(y)h(to)f(b)m(ypass)f(the)g(default)h(in)m (terpretation)h(of)e(the)h(IEEE)f(sp)s(ecial)h(v)-5 b(alues.)50 b(This)33 b(is)g(also)0 5375 y(not)e(supp)s(orted)e(when)h(reading)g (\015oating-p)s(oin)m(t)i(images)g(that)g(ha)m(v)m(e)g(b)s(een)e (compressed)g(with)g(the)h(FITS)f(tiled)0 5488 y(image)i(compression)f (con)m(v)m(en)m(tion)j(that)d(is)g(discussed)g(in)f(section)j(5.6;)f (the)g(pixels)f(v)-5 b(alues)31 b(in)g(tile)h(compressed)0 5601 y(images)42 b(are)f(represen)m(ted)f(b)m(y)h(scaled)h(in)m (tegers,)i(and)c(a)h(reserv)m(ed)g(in)m(teger)h(v)-5 b(alue)41 b(\(not)h(a)f(NaN\))h(is)e(used)g(to)0 5714 y(represen)m(t)30 b(unde\014ned)f(pixels.)p eop end %%Page: 25 33 TeXDict begin 25 32 bop 0 299 a Fh(4.9.)72 b(ERR)m(OR)30 b(ST)-8 b(A)g(TUS)30 b(V)-10 b(ALUES)30 b(AND)h(THE)f(ERR)m(OR)g(MESSA) m(GE)h(ST)-8 b(A)m(CK)848 b Fj(25)0 555 y Ff(4.9)135 b(Error)46 b(Status)f(V)-11 b(alues)45 b(and)g(the)g(Error)g(Message)h (Stac)l(k)0 805 y Fj(Nearly)36 b(all)g(the)g(CFITSIO)e(routines)h (return)f(an)h(error)g(status)h(v)-5 b(alue)35 b(in)g(2)h(w)m(a)m(ys:) 51 b(as)36 b(the)f(v)-5 b(alue)36 b(of)g(the)f(last)0 918 y(parameter)29 b(in)f(the)g(function)g(call,)j(and)d(as)g(the)h (returned)e(v)-5 b(alue)29 b(of)f(the)h(function)f(itself.)41 b(This)27 b(pro)m(vides)i(some)0 1031 y(\015exibilit)m(y)37 b(in)e(the)h(w)m(a)m(y)h(programmers)e(can)h(test)h(if)f(an)f(error)h (o)s(ccurred,)g(as)g(illustrated)h(in)e(the)h(follo)m(wing)i(2)0 1144 y(co)s(de)31 b(fragmen)m(ts:)191 1397 y Fe(if)47 b(\()h(fits_write_record\(fptr,)41 b(card,)46 b(&status\))g(\))430 1510 y(printf\(")f(Error)h(occurred)g(while)g(writing)g(keyword."\);)0 1735 y(or,)191 1961 y(fits_write_record\(fptr,)41 b(card,)47 b(&status\);)191 2074 y(if)g(\()h(status)e(\))430 2187 y(printf\(")f(Error)h(occurred)g(while)g(writing)g(keyword."\);)0 2440 y Fj(A)27 b(listing)h(of)g(all)g(the)f(CFITSIO)f(status)i(co)s(de) f(v)-5 b(alues)28 b(is)f(giv)m(en)h(at)g(the)g(end)e(of)i(this)f(do)s (cumen)m(t.)39 b(Programmers)0 2553 y(are)33 b(encouraged)g(to)g(use)f (the)h(sym)m(b)s(olic)f(mnemonics)g(\(de\014ned)g(in)g(\014tsio.h\))h (rather)f(than)g(the)h(actual)h(in)m(teger)0 2666 y(status)d(v)-5 b(alues)30 b(to)i(impro)m(v)m(e)f(the)f(readabilit)m(y)i(of)f(their)f (co)s(de.)0 2826 y(The)i(CFITSIO)f(library)g(uses)h(an)g(`inherited)h (status')g(con)m(v)m(en)m(tion)h(for)e(the)h(status)f(parameter)h(whic) m(h)f(means)0 2939 y(that)37 b(if)f(a)h(routine)f(is)h(called)g(with)f (a)h(p)s(ositiv)m(e)g(input)f(v)-5 b(alue)36 b(of)h(the)g(status)f (parameter)h(as)g(input,)g(then)f(the)0 3052 y(routine)j(will)f(exit)i (immediately)g(without)e(c)m(hanging)i(the)e(v)-5 b(alue)39 b(of)g(the)g(status)g(parameter.)65 b(Th)m(us,)40 b(if)f(one)0 3164 y(passes)24 b(the)h(status)g(v)-5 b(alue)25 b(returned)f(from)g (eac)m(h)i(CFITSIO)d(routine)h(as)h(input)f(to)h(the)g(next)g(CFITSIO)e (routine,)0 3277 y(then)28 b(whenev)m(er)g(an)g(error)g(is)h(detected)g (all)h(further)d(CFITSIO)f(pro)s(cessing)i(will)h(cease.)42 b(This)27 b(con)m(v)m(en)m(tion)k(can)0 3390 y(simplify)h(the)h(error)f (c)m(hec)m(king)j(in)d(application)i(programs)e(b)s(ecause)h(it)g(is)g (not)g(necessary)g(to)g(c)m(hec)m(k)i(the)d(v)-5 b(alue)0 3503 y(of)30 b(the)g(status)h(parameter)f(after)h(ev)m(ery)g(single)f (CFITSIO)f(routine)h(call.)42 b(If)30 b(a)g(program)g(con)m(tains)h(a)g (sequence)0 3616 y(of)d(sev)m(eral)i(CFITSIO)d(calls,)j(one)e(can)h (just)e(c)m(hec)m(k)j(the)f(status)f(v)-5 b(alue)29 b(after)g(the)f (last)h(call.)41 b(Since)29 b(the)f(returned)0 3729 y(status)33 b(v)-5 b(alues)33 b(are)g(generally)h(distinctiv)m(e,)h(it)f(should)d (b)s(e)i(p)s(ossible)f(to)h(determine)g(whic)m(h)g(routine)g (originally)0 3842 y(returned)c(the)i(error)f(status.)0 4002 y(CFITSIO)c(also)i(main)m(tains)h(an)e(in)m(ternal)h(stac)m(k)h (of)f(error)f(messages)h(\(80-c)m(haracter)j(maxim)m(um)c(length\))h (whic)m(h)0 4115 y(in)36 b(man)m(y)g(cases)h(pro)m(vide)f(a)g(more)g (detailed)i(explanation)f(of)f(the)g(cause)h(of)f(the)g(error)g(than)f (is)h(pro)m(vided)g(b)m(y)0 4228 y(the)k(error)e(status)i(n)m(um)m(b)s (er)e(alone.)69 b(It)39 b(is)h(recommended)f(that)g(the)h(error)f (message)h(stac)m(k)h(b)s(e)e(prin)m(ted)g(out)0 4341 y(whenev)m(er)g(a)g(program)g(detects)h(a)f(CFITSIO)e(error.)66 b(The)38 b(function)h(\014ts)p 2653 4341 28 4 v 32 w(rep)s(ort)p 2931 4341 V 32 w(error)g(will)g(prin)m(t)g(out)g(the)0 4454 y(en)m(tire)31 b(error)e(message)h(stac)m(k,)i(or)d(alternativ)m (ely)k(one)d(ma)m(y)g(call)h(\014ts)p 2376 4454 V 32 w(read)p 2580 4454 V 33 w(errmsg)e(to)h(get)h(the)f(error)f(messages)0 4567 y(one)i(at)g(a)g(time.)0 4899 y Ff(4.10)136 b(V)-11 b(ariable-Length)45 b(Arra)l(ys)g(in)g(Binary)g(T)-11 b(ables)0 5149 y Fj(CFITSIO)33 b(pro)m(vides)i(easy-to-use)h(supp)s (ort)d(for)i(reading)g(and)f(writing)h(data)g(in)g(v)-5 b(ariable)35 b(length)g(\014elds)g(of)g(a)0 5262 y(binary)27 b(table.)40 b(The)27 b(v)-5 b(ariable)29 b(length)f(columns)f(ha)m(v)m (e)i(TF)m(ORMn)e(k)m(eyw)m(ord)h(v)-5 b(alues)28 b(of)g(the)f(form)g (`1Pt\(len\)')j(or)0 5375 y(`1Qt\(len\)')36 b(where)d(`t')h(is)g(the)g (data)g(t)m(yp)s(e)g(co)s(de)g(\(e.g.,)j(I,)c(J,)h(E,)g(D,)g(etc.\))52 b(and)33 b(`len')i(is)e(an)h(in)m(teger)h(sp)s(ecifying)0 5488 y(the)g(maxim)m(um)g(length)h(of)f(the)h(v)m(ector)h(in)d(the)i (table.)56 b(The)35 b('P')g(t)m(yp)s(e)g(v)-5 b(ariable)36 b(length)g(columns)f(use)g(32-bit)0 5601 y(arra)m(y)j(length)h(and)e(b) m(yte)h(o\013set)h(v)-5 b(alues,)41 b(whereas)c(the)h('Q')g(t)m(yp)s(e) g(columns)g(use)f(64-bit)i(v)-5 b(alues,)41 b(whic)m(h)c(ma)m(y)0 5714 y(b)s(e)31 b(required)h(when)f(dealing)i(with)f(large)h(arra)m (ys.)46 b(CFITSIO)31 b(supp)s(orts)f(a)i(lo)s(cal)i(con)m(v)m(en)m (tion)g(that)f(in)m(terprets)p eop end %%Page: 26 34 TeXDict begin 26 33 bop 0 299 a Fj(26)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(the)41 b('P')g(t)m(yp)s(e)g(descriptors)g(as)g(unsigned)e(32-bit)j(in)m (tegers,)j(whic)m(h)c(pro)m(vides)g(a)g(factor)g(of)g(2)h(greater)g (range)0 668 y(for)32 b(the)g(arra)m(y)h(length)g(or)f(heap)g(address)f (than)h(is)g(p)s(ossible)g(with)g(32-bit)h('signed')g(in)m(tegers.)47 b(Note,)34 b(ho)m(w)m(ev)m(er,)0 781 y(that)i(other)g(soft)m(w)m(are)g (pac)m(k)-5 b(ages)38 b(ma)m(y)d(not)h(supp)s(ort)e(this)h(con)m(v)m (en)m(tion,)k(and)c(ma)m(y)h(b)s(e)e(unable)h(to)h(read)f(thees)0 894 y(extended)30 b(range)h(v)-5 b(ariable)31 b(length)g(records.)0 1054 y(If)d(the)h(v)-5 b(alue)30 b(of)f(`len')g(is)g(not)g(sp)s (eci\014ed)f(when)g(the)h(table)h(is)e(created)i(\(e.g.,)h(if)e(the)g (TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)29 b(is)0 1167 y(simply)j(sp)s(eci\014ed)f(as)h('1PE')h(instead)g(of)f('1PE\(400\))i (\),)g(then)d(CFITSIO)g(will)h(automatically)j(scan)e(the)f(table)0 1280 y(when)27 b(it)j(is)e(closed)h(to)h(determine)e(the)h(maxim)m(um)f (length)h(of)g(the)f(v)m(ector)j(and)c(will)i(app)s(end)e(this)i(v)-5 b(alue)29 b(to)g(the)0 1393 y(TF)m(ORMn)h(v)-5 b(alue.)0 1553 y(The)29 b(same)h(routines)g(that)g(read)f(and)g(write)h(data)g (in)g(an)f(ordinary)g(\014xed)g(length)h(binary)f(table)h(extension)h (are)0 1666 y(also)41 b(used)d(for)i(v)-5 b(ariable)40 b(length)g(\014elds,)h(ho)m(w)m(ev)m(er,)j(the)c(routine)f(parameters)h (tak)m(e)h(on)f(a)g(sligh)m(tly)g(di\013eren)m(t)0 1779 y(in)m(terpretation)32 b(as)e(describ)s(ed)g(b)s(elo)m(w.)0 1939 y(All)37 b(the)f(data)h(in)f(a)h(v)-5 b(ariable)37 b(length)f(\014eld)g(is)g(written)h(in)m(to)g(an)f(area)h(called)h(the) e(`heap')g(whic)m(h)g(follo)m(ws)i(the)0 2052 y(main)31 b(\014xed-length)h(FITS)e(binary)h(table.)44 b(The)31 b(size)h(of)f(the)h(heap,)f(in)g(b)m(ytes,)h(is)g(sp)s(eci\014ed)e(b)m (y)h(the)h(PCOUNT)0 2165 y(k)m(eyw)m(ord)21 b(in)f(the)h(FITS)f (header.)37 b(When)20 b(creating)i(a)f(new)f(binary)g(table,)j(the)e (initial)h(v)-5 b(alue)21 b(of)f(PCOUNT)g(should)0 2278 y(usually)27 b(b)s(e)h(set)g(to)g(zero.)41 b(CFITSIO)26 b(will)i(recompute)g(the)g(size)g(of)g(the)g(heap)g(as)g(the)g(data)g (is)g(written)f(and)h(will)0 2391 y(automatically)g(up)s(date)c(the)i (PCOUNT)e(k)m(eyw)m(ord)h(v)-5 b(alue)26 b(when)e(the)h(table)h(is)f (closed.)40 b(When)25 b(writing)g(v)-5 b(ariable)0 2503 y(length)34 b(data)g(to)g(a)g(table,)i(CFITSIO)c(will)h(automatically)k (extend)c(the)h(size)g(of)g(the)g(heap)f(area)h(if)g(necessary)-8 b(,)0 2616 y(so)31 b(that)g(an)m(y)f(follo)m(wing)i(HDUs)f(do)f(not)h (get)h(o)m(v)m(erwritten.)0 2777 y(By)e(default)f(the)h(heap)f(data)i (area)f(starts)g(immediately)h(after)f(the)f(last)i(ro)m(w)e(of)h(the)g (\014xed-length)f(table.)42 b(This)0 2889 y(default)27 b(starting)g(lo)s(cation)i(ma)m(y)e(b)s(e)f(o)m(v)m(erridden)h(b)m(y)g (the)g(THEAP)f(k)m(eyw)m(ord,)i(but)f(this)f(is)h(not)g(recommended.)0 3002 y(If)34 b(additional)h(ro)m(ws)f(of)g(data)h(are)g(added)e(to)i (the)f(table,)j(CFITSIO)32 b(will)j(automatically)i(shift)c(the)i(the)f (heap)0 3115 y(do)m(wn)g(to)i(mak)m(e)f(ro)s(om)g(for)f(the)h(new)f(ro) m(ws,)i(but)e(it)i(is)e(ob)m(viously)i(b)s(e)e(more)h(e\016cien)m(t)h (to)f(initially)h(create)h(the)0 3228 y(table)31 b(with)e(the)h (necessary)g(n)m(um)m(b)s(er)f(of)h(blank)f(ro)m(ws,)h(so)g(that)g(the) g(heap)g(do)s(es)f(not)h(needed)g(to)g(b)s(e)f(constan)m(tly)0 3341 y(mo)m(v)m(ed.)0 3501 y(When)36 b(writing)g(ro)m(w)g(of)h(data)f (to)h(a)g(v)-5 b(ariable)37 b(length)f(\014eld)g(the)g(en)m(tire)i (arra)m(y)e(of)g(v)-5 b(alues)37 b(for)f(a)g(giv)m(en)i(ro)m(w)e(of)0 3614 y(the)30 b(table)h(m)m(ust)e(b)s(e)h(written)g(with)f(a)h(single)h (call)g(to)f(\014ts)p 1986 3614 28 4 v 33 w(write)p 2221 3614 V 33 w(col.)42 b(The)29 b(total)i(length)g(of)f(the)g(arra)m(y)g (is)g(giv)m(en)0 3727 y(b)m(y)j(nelemen)m(ts)h(+)f(\014rstelem)g(-)g (1.)49 b(Additional)34 b(elemen)m(ts)h(cannot)e(b)s(e)g(app)s(ended)e (to)j(an)f(existing)h(v)m(ector)h(at)f(a)0 3840 y(later)c(time)g(since) g(an)m(y)g(attempt)g(to)g(do)g(so)f(will)h(simply)f(o)m(v)m(erwrite)i (all)f(the)f(previously)h(written)f(data)h(and)f(the)0 3953 y(new)36 b(data)h(will)g(b)s(e)f(written)g(to)h(a)g(new)f(area)h (of)g(the)g(heap.)58 b(The)36 b(\014ts)p 2496 3953 V 33 w(compress)p 2889 3953 V 32 w(heap)g(routine)h(is)f(pro)m(vided)0 4066 y(to)h(compress)g(the)g(heap)g(and)f(reco)m(v)m(er)i(an)m(y)f(un)m (used)f(space.)60 b(T)-8 b(o)37 b(a)m(v)m(oid)i(ha)m(ving)e(to)h(deal)f (with)f(this)h(issue,)h(it)0 4179 y(is)31 b(recommended)h(that)g(ro)m (ws)f(in)g(a)h(v)-5 b(ariable)32 b(length)g(\014eld)f(should)f(only)i (b)s(e)f(written)g(once.)45 b(An)31 b(exception)h(to)0 4292 y(this)e(general)h(rule)f(o)s(ccurs)g(when)f(setting)i(elemen)m (ts)h(of)e(an)g(arra)m(y)g(as)h(unde\014ned.)38 b(It)30 b(is)h(allo)m(w)m(ed)h(to)e(\014rst)g(write)0 4405 y(a)e(dumm)m(y)f(v) -5 b(alue)28 b(in)m(to)h(the)f(arra)m(y)h(with)e(\014ts)p 1534 4405 V 33 w(write)p 1769 4405 V 33 w(col,)j(and)d(then)g(call)j (\014ts)p 2632 4405 V 32 w(write)p 2866 4405 V 33 w(col)p 3009 4405 V 34 w(n)m(ul)d(to)i(\015ag)f(the)g(desired)0 4517 y(elemen)m(ts)h(as)f(unde\014ned.)38 b(Note)29 b(that)g(the)f(ro)m (ws)g(of)g(a)g(table,)i(whether)d(\014xed)g(or)h(v)-5 b(ariable)29 b(length,)g(do)f(not)g(ha)m(v)m(e)0 4630 y(to)j(b)s(e)f(written)g(consecutiv)m(ely)j(and)d(ma)m(y)h(b)s(e)e (written)i(in)f(an)m(y)h(order.)0 4791 y(When)40 b(writing)h(to)g(a)g (v)-5 b(ariable)41 b(length)g(ASCI)s(I)e(c)m(haracter)j(\014eld)e (\(e.g.,)45 b(TF)m(ORM)c(=)f('1P)-8 b(A'\))43 b(only)d(a)h(single)0 4903 y(c)m(haracter)22 b(string)e(can)h(b)s(e)e(written.)38 b(The)20 b(`\014rstelem')g(and)g(`nelemen)m(ts')i(parameter)e(v)-5 b(alues)21 b(in)f(the)g(\014ts)p 3526 4903 V 33 w(write)p 3761 4903 V 33 w(col)0 5016 y(routine)35 b(are)h(ignored)f(and)f(the)i (n)m(um)m(b)s(er)d(of)j(c)m(haracters)g(to)g(write)f(is)h(simply)e (determined)h(b)m(y)g(the)g(length)h(of)0 5129 y(the)31 b(input)e(n)m(ull-terminated)i(c)m(haracter)h(string.)0 5289 y(The)21 b(\014ts)p 305 5289 V 33 w(write)p 540 5289 V 33 w(descript)g(routine)h(is)f(useful)g(in)g(situations)i(where) e(m)m(ultiple)h(ro)m(ws)g(of)g(a)g(v)-5 b(ariable)22 b(length)g(column)0 5402 y(ha)m(v)m(e)32 b(the)e(iden)m(tical)i(arra)m (y)f(of)g(v)-5 b(alues.)41 b(One)30 b(can)g(simply)g(write)h(the)f (arra)m(y)h(once)g(for)g(the)f(\014rst)g(ro)m(w,)g(and)g(then)0 5515 y(use)c(\014ts)p 280 5515 V 32 w(write)p 514 5515 V 33 w(descript)g(to)g(write)g(the)g(same)h(descriptor)e(v)-5 b(alues)27 b(in)m(to)g(the)f(other)g(ro)m(ws;)h(all)g(the)f(ro)m(ws)g (will)g(then)0 5628 y(p)s(oin)m(t)k(to)h(the)g(same)g(storage)h(lo)s (cation)g(th)m(us)e(sa)m(ving)h(disk)f(space.)p eop end %%Page: 27 35 TeXDict begin 27 34 bop 0 299 a Fh(4.11.)73 b(MUL)-8 b(TIPLE)30 b(A)m(CCESS)f(TO)g(THE)i(SAME)f(FITS)f(FILE)1515 b Fj(27)0 555 y(When)35 b(reading)g(from)f(a)i(v)-5 b(ariable)35 b(length)h(arra)m(y)f(\014eld)g(one)g(can)g(only)h(read)e(as)i(man)m(y) f(elemen)m(ts)h(as)f(actually)0 668 y(exist)i(in)e(that)i(ro)m(w)e(of)h (the)g(table;)k(reading)c(do)s(es)g(not)g(automatically)i(con)m(tin)m (ue)f(with)f(the)g(next)g(ro)m(w)g(of)g(the)0 781 y(table)29 b(as)f(o)s(ccurs)g(when)f(reading)h(an)g(ordinary)g(\014xed)f(length)h (table)h(\014eld.)40 b(A)m(ttempts)29 b(to)g(read)f(more)g(than)g(this) 0 894 y(will)k(cause)h(an)e(error)h(status)g(to)g(b)s(e)f(returned.)44 b(One)32 b(can)g(determine)g(the)g(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)h (in)f(eac)m(h)h(ro)m(w)0 1007 y(of)e(a)f(v)-5 b(ariable)31 b(column)g(with)f(the)g(\014ts)p 1329 1007 28 4 v 33 w(read)p 1534 1007 V 32 w(descript)h(routine.)0 1337 y Ff(4.11)136 b(Multiple)45 b(Access)g(to)g(the)g(Same)h(FITS)d(File)0 1588 y Fj(CFITSIO)29 b(supp)s(orts)g(sim)m(ultaneous)i(read)f(and)g (write)h(access)h(to)f(di\013eren)m(t)g(HDUs)g(in)f(the)h(same)g(FITS)f (\014le)g(in)0 1701 y(some)h(circumstances,)g(as)g(describ)s(ed)e(b)s (elo)m(w:)136 1941 y Fc(\017)46 b Fj(Multi-threaded)31 b(programs)227 2088 y(When)f(CFITSIO)f(is)h(compiled)h(with)e(the)i(-D) p 1842 2088 V 33 w(REENTRANT)f(directiv)m(e)h(\(as)g(can)f(b)s(e)g (tested)h(with)f(the)227 2201 y(\014ts)p 354 2201 V 33 w(is)p 448 2201 V 33 w(reen)m(tran)m(t)38 b(function\))f(di\013eren)m (t)h(threads)f(can)g(call)i(an)m(y)e(of)h(the)f(CFITSIO)f(routines)h (to)h(sim)m(ul-)227 2314 y(taneously)g(read)g(or)f(write)h(separate)h (FITS)d(\014les.)62 b(Multiple)39 b(threads)e(can)h(also)g(read)f(data) i(from)e(the)227 2427 y(same)32 b(FITS)f(\014le)g(sim)m(ultaneously)-8 b(,)33 b(as)f(long)g(as)f(the)h(\014le)f(w)m(as)h(op)s(ened)f(indep)s (enden)m(tly)f(b)m(y)h(eac)m(h)i(thread.)227 2539 y(This)g(relies)h(on) g(the)f(op)s(erating)h(system)g(to)g(correctly)h(deal)g(with)e(reading) g(the)h(same)g(\014le)g(b)m(y)f(m)m(ultiple)227 2652 y(pro)s(cesses.)64 b(Di\013eren)m(t)40 b(threads)e(should)f(not)i (share)f(the)g(same)h('\014ts\014le')f(p)s(oin)m(ter)g(to)h(read)g(an)f (op)s(ened)227 2765 y(FITS)25 b(\014le,)i(unless)e(lo)s(c)m(ks)h(are)g (placed)g(around)e(the)i(calls)g(to)g(the)g(CFITSIO)e(reading)i (routines.)39 b(Di\013eren)m(t)227 2878 y(threads)30 b(should)g(nev)m(er)g(try)h(to)g(write)f(to)h(the)g(same)g(FITS)e (\014le.)136 3059 y Fc(\017)46 b Fj(Multiple)31 b(read)g(access)g(to)h (the)e(same)h(FITS)e(\014le)i(within)f(a)h(single)g(program/thread)227 3206 y(A)46 b(single)g(pro)s(cess)f(ma)m(y)h(op)s(en)f(the)g(same)h (FITS)f(\014le)g(with)g(READONL)-8 b(Y)46 b(access)h(m)m(ultiple)f (times,)227 3319 y(and)32 b(th)m(us)f(create)j(m)m(ultiple)f ('\014ts\014le*')g(p)s(oin)m(ters)f(to)g(that)h(same)g(\014le)f(within) f(CFITSIO.)g(This)g(relies)i(on)227 3432 y(the)h(op)s(erating)g (system's)g(abilit)m(y)h(to)g(op)s(en)e(a)h(single)g(\014le)g(m)m (ultiple)g(times)g(and)f(correctly)i(manage)g(the)227 3545 y(subsequen)m(t)24 b(read)g(requests)g(directed)g(to)h(the)f (di\013eren)m(t)h(C)f('\014le*')h(p)s(oin)m(ters,)g(whic)m(h)f (actually)i(all)f(p)s(oin)m(t)f(to)227 3658 y(the)32 b(same)h(\014le.)45 b(CFITSIO)30 b(simply)i(executes)h(the)f(read)g (requests)g(to)g(the)g(di\013ernet)g('\014ts\014le*')h(p)s(oin)m(ters) 227 3771 y(the)e(same)g(as)f(if)h(they)f(w)m(ere)h(ph)m(ysically)g (di\013eren)m(t)g(\014les.)136 3952 y Fc(\017)46 b Fj(Multiple)31 b(write)g(access)h(to)f(the)f(same)h(FITS)f(\014le)g(within)g(a)h (single)g(program/thread)227 4099 y(CFITSIO)22 b(supp)s(orts)g(op)s (ening)h(the)g(same)h(FITS)f(\014le)g(m)m(ultiple)i(times)f(with)f (WRITE)g(access,)j(but)d(it)h(only)227 4212 y(ph)m(ysically)j(op)s(ens) f(the)g(\014le)h(\(at)g(the)g(op)s(erating)f(system)h(lev)m(el\))h (once,)g(on)e(the)h(\014rst)e(call)j(to)f(\014ts)p 3509 4212 V 32 w(op)s(en)p 3731 4212 V 33 w(\014le.)227 4325 y(If)38 b(\014ts)p 453 4325 V 32 w(op)s(en)p 675 4325 V 32 w(\014le)g(is)g(subsequen)m(tly)f(called)i(to)g(op)s(en)e(the)h (same)g(\014le)g(again,)j(CFITSIO)36 b(will)i(recognize)227 4438 y(that)c(the)f(\014le)g(is)g(already)g(op)s(en,)h(and)e(will)h (return)f(a)h(new)g('\014ts\014le*')g(p)s(oin)m(ter)g(that)h(logically) h(p)s(oin)m(ts)e(to)227 4551 y(the)i(\014rst)e('\014ts\014le*')i(p)s (oin)m(ter,)h(without)e(actually)i(op)s(ening)e(the)g(\014le)h(a)f (second)h(time.)53 b(The)34 b(application)227 4664 y(program)39 b(can)g(then)g(treat)h(the)f(2)g('\014ts\014le*')h(p)s(oin)m(ters)f(as) g(if)g(they)g(p)s(oin)m(t)g(to)h(di\013eren)m(t)f(\014les,)i(and)e(can) 227 4776 y(seemingly)c(mo)m(v)m(e)g(to)g(and)e(write)h(data)h(to)g(2)f (di\013eren)m(t)g(HDUs)h(within)e(the)h(same)g(\014le.)52 b(Ho)m(w)m(ev)m(er,)37 b(eac)m(h)227 4889 y(time)31 b(the)g (application)g(program)g(switc)m(hes)g(whic)m(h)f('\014ts\014le*')h(p)s (oin)m(ter)f(it)h(is)f(writing)h(to,)g(CFITSIO)e(will)227 5002 y(\015ush)24 b(an)m(y)i(in)m(ternal)g(bu\013ers)e(that)i(con)m (tain)h(data)f(written)g(to)g(the)g(\014rst)e('\014ts\014le*')i(p)s (oin)m(ter,)h(then)e(mo)m(v)m(e)i(to)227 5115 y(the)j(HDU)g(that)g(the) g(other)f('\014ts\014le*')h(p)s(oin)m(ter)g(is)f(writing)h(to.)41 b(Ob)m(viously)-8 b(,)30 b(this)f(ma)m(y)h(add)f(a)h(signi\014can)m(t) 227 5228 y(amoun)m(t)h(of)f(computational)i(o)m(v)m(erhead)f(if)f(the)g (application)h(program)f(uses)g(this)g(feature)g(to)h(frequen)m(tly)227 5341 y(switc)m(h)25 b(bac)m(k)h(and)e(forth)g(b)s(et)m(w)m(een)i (writing)f(to)g(2)g(\(or)g(more\))g(HDUs)h(in)e(the)h(same)g(\014le,)h (so)f(this)g(capabilit)m(y)227 5454 y(should)30 b(b)s(e)f(used)h (judiciously)-8 b(.)227 5601 y(Note)26 b(that)f(CFITSIO)e(will)i(not)g (allo)m(w)h(a)e(FITS)g(\014le)h(to)g(b)s(e)f(op)s(ened)g(a)g(second)h (time)g(with)f(READ)m(WRITE)227 5714 y(access)32 b(if)e(it)h(w)m(as)g (op)s(ened)f(previously)g(with)g(READONL)-8 b(Y)31 b(access.)p eop end %%Page: 28 36 TeXDict begin 28 35 bop 0 299 a Fj(28)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Ff(4.12)136 b(When)44 b(the)h(Final)h(Size)f(of)g(the)g(FITS)f(HDU)h(is)g(Unkno)l (wn)0 816 y Fj(It)27 b(is)h(not)f(required)f(to)i(kno)m(w)f(the)h (total)h(size)f(of)f(a)h(FITS)e(data)i(arra)m(y)g(or)f(table)h(b)s (efore)f(b)s(eginning)f(to)i(write)g(the)0 928 y(data)k(to)f(the)g (FITS)f(\014le.)43 b(In)30 b(the)h(case)h(of)f(the)g(primary)f(arra)m (y)h(or)g(an)f(image)j(extension,)e(one)h(should)d(initially)0 1041 y(create)i(the)e(arra)m(y)h(with)e(the)i(size)g(of)f(the)g (highest)g(dimension)g(\(largest)i(NAXISn)d(k)m(eyw)m(ord\))i(set)g(to) g(a)f(dumm)m(y)0 1154 y(v)-5 b(alue,)26 b(suc)m(h)e(as)g(1.)39 b(Then)23 b(after)i(all)g(the)g(data)f(ha)m(v)m(e)i(b)s(een)d(written)h (and)g(the)g(true)g(dimensions)g(are)g(kno)m(wn,)h(then)0 1267 y(the)33 b(NAXISn)f(v)-5 b(alue)33 b(should)f(b)s(e)g(up)s(dated)g (using)g(the)h(\014ts)p 2069 1267 28 4 v 33 w(up)s(date)p 2378 1267 V 32 w(k)m(ey)g(routine)g(b)s(efore)g(mo)m(ving)g(to)h (another)0 1380 y(extension)d(or)f(closing)i(the)e(FITS)g(\014le.)0 1540 y(When)f(writing)g(to)g(FITS)g(tables,)h(CFITSIO)d(automatically) 32 b(k)m(eeps)e(trac)m(k)g(of)f(the)g(highest)h(ro)m(w)f(n)m(um)m(b)s (er)e(that)0 1653 y(is)32 b(written)g(to,)h(and)e(will)h(increase)h (the)f(size)h(of)f(the)g(table)g(if)g(necessary)-8 b(.)46 b(CFITSIO)30 b(will)i(also)h(automatically)0 1766 y(insert)j(space)h (in)f(the)g(FITS)f(\014le)i(if)f(necessary)-8 b(,)39 b(to)e(ensure)e(that)i(the)f(data)h('heap',)h(if)e(it)h(exists,)h (and/or)f(an)m(y)0 1879 y(additional)29 b(HDUs)g(that)g(follo)m(w)g (the)g(table)g(do)f(not)h(get)g(o)m(v)m(erwritten)h(as)e(new)g(ro)m(ws) g(are)h(written)f(to)h(the)g(table.)0 2039 y(As)37 b(a)h(general)g (rule)f(it)h(is)f(b)s(est)g(to)h(sp)s(ecify)f(the)h(initial)g(n)m(um)m (b)s(er)e(of)i(ro)m(ws)f(=)g(0)g(when)g(the)g(table)h(is)g(created,)0 2152 y(then)g(let)h(CFITSIO)e(k)m(eep)i(trac)m(k)g(of)g(the)f(n)m(um)m (b)s(er)f(of)i(ro)m(ws)f(that)h(are)f(actually)i(written.)65 b(The)38 b(application)0 2265 y(program)e(should)f(not)i(man)m(ually)g (up)s(date)e(the)i(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(in)g(the)h(table)g (\(as)g(giv)m(en)g(b)m(y)f(the)h(NAXIS2)0 2378 y(k)m(eyw)m(ord\))j (since)f(CFITSIO)e(do)s(es)i(this)g(automatically)-8 b(.)69 b(If)38 b(a)i(table)f(is)g(initially)i(created)f(with)e(more)h (than)0 2491 y(zero)i(ro)m(ws,)j(then)c(this)h(will)f(usually)h(b)s(e)f (considered)g(as)h(the)g(minim)m(um)f(size)h(of)g(the)g(table,)j(ev)m (en)d(if)g(few)m(er)0 2604 y(ro)m(ws)30 b(are)g(actually)h(written)f (to)h(the)f(table.)41 b(Th)m(us,)30 b(if)f(a)i(table)f(is)g(initially)h (created)g(with)f(NAXIS2)g(=)g(20,)h(and)0 2717 y(CFITSIO)g(only)i (writes)f(10)i(ro)m(ws)e(of)h(data)g(b)s(efore)f(closing)i(the)f (table,)h(then)e(NAXIS2)h(will)g(remain)f(equal)h(to)0 2829 y(20.)50 b(If)33 b(ho)m(w)m(ev)m(er,)i(30)g(ro)m(ws)e(of)g(data)h (are)g(written)f(to)h(this)f(table,)i(then)e(NAXIS2)h(will)f(b)s(e)g (increased)g(from)g(20)0 2942 y(to)f(30.)44 b(The)31 b(one)g(exception)i(to)f(this)f(automatic)i(up)s(dating)d(of)h(the)h (NAXIS2)f(k)m(eyw)m(ord)h(is)f(if)g(the)h(application)0 3055 y(program)c(directly)g(mo)s(di\014es)f(the)i(v)-5 b(alue)28 b(of)g(NAXIS2)g(\(up)f(or)h(do)m(wn\))g(itself)h(just)e(b)s (efore)h(closing)h(the)f(table.)41 b(In)0 3168 y(this)28 b(case,)i(CFITSIO)d(do)s(es)h(not)h(up)s(date)e(NAXIS2)i(again,)h (since)f(it)g(assumes)f(that)h(the)f(application)i(program)0 3281 y(m)m(ust)i(ha)m(v)m(e)h(had)f(a)g(go)s(o)s(d)g(reason)h(for)f(c)m (hanging)h(the)f(v)-5 b(alue)33 b(directly)-8 b(.)47 b(This)31 b(is)h(not)h(recommended,)f(ho)m(w)m(ev)m(er,)0 3394 y(and)j(is)h(only)g(pro)m(vided)g(for)f(bac)m(kw)m(ard)h (compatibilit)m(y)i(with)e(soft)m(w)m(are)h(that)g(initially)g(creates) g(a)f(table)h(with)0 3507 y(a)d(large)h(n)m(um)m(b)s(er)e(of)h(ro)m (ws,)h(than)f(decreases)g(the)h(NAXIS2)f(v)-5 b(alue)34 b(to)h(the)f(actual)h(smaller)g(v)-5 b(alue)34 b(just)f(b)s(efore)0 3620 y(closing)e(the)g(table.)0 4004 y Ff(4.13)136 b(CFITSIO)44 b(Size)h(Limitations)0 4264 y Fj(CFITSIO)29 b(places)j(v)m(ery)f(few)g (restrictions)g(on)g(the)g(size)g(of)g(FITS)f(\014les)h(that)g(it)h (reads)e(or)h(writes.)42 b(There)30 b(are)i(a)0 4377 y(few)e(limits,)h(ho)m(w)m(ev)m(er,)h(that)f(ma)m(y)g(a\013ect)h(some)f (extreme)g(cases:)0 4538 y(1.)43 b(The)31 b(maxim)m(um)g(n)m(um)m(b)s (er)f(of)h(FITS)f(\014les)h(that)h(ma)m(y)g(b)s(e)e(sim)m(ultaneously)i (op)s(ened)f(b)m(y)g(CFITSIO)e(is)i(set)h(b)m(y)0 4650 y(NMAXFILES,)e(as)f(de\014ned)f(in)h(\014tsio2.h.)41 b(The)29 b(curren)m(t)g(default)g(v)-5 b(alue)30 b(is)f(1000,)j(but)c (this)h(ma)m(y)h(b)s(e)f(increased)0 4763 y(if)40 b(necessary)-8 b(.)72 b(Note)42 b(that)f(CFITSIO)e(allo)s(cates)j(NIOBUF)f(*)g(2880)h (b)m(ytes)f(of)g(I/O)f(bu\013er)g(space)h(for)f(eac)m(h)0 4876 y(\014le)d(that)h(is)f(op)s(ened.)61 b(The)37 b(default)g(v)-5 b(alue)38 b(of)f(NIOBUF)h(is)f(40)h(\(de\014ned)f(in)f(\014tsio.h\),)k (so)e(this)f(amoun)m(ts)g(to)0 4989 y(more)31 b(than)g(115K)i(of)e (memory)g(for)g(eac)m(h)i(op)s(ened)d(\014le)i(\(or)f(115)i(MB)f(for)f (1000)i(op)s(ened)d(\014les\).)44 b(Note)33 b(that)f(the)0 5102 y(underlying)k(op)s(erating)i(system,)h(ma)m(y)e(ha)m(v)m(e)i(a)e (lo)m(w)m(er)i(limit)f(on)f(the)g(n)m(um)m(b)s(er)f(of)h(\014les)g (that)h(can)f(b)s(e)g(op)s(ened)0 5215 y(sim)m(ultaneously)-8 b(.)0 5375 y(2.)67 b(It)40 b(used)e(to)i(b)s(e)e(common)i(for)f (computer)g(systems)g(to)h(only)f(supp)s(ort)f(disk)g(\014les)h(up)f (to)i(2**31)i(b)m(ytes)d(=)0 5488 y(2.1)k(GB)g(in)f(size,)47 b(but)41 b(most)i(systems)f(no)m(w)g(supp)s(ort)f(larger)i(\014les.)76 b(CFITSIO)41 b(can)i(optionally)g(read)g(and)0 5601 y(write)37 b(these)h(so-called)h('large)f(\014les')g(that)f(are)h(greater)g(than)f (2.1)h(GB)g(on)f(platforms)g(where)g(they)g(are)h(sup-)0 5714 y(p)s(orted,)43 b(but)d(this)g(usually)h(requires)f(that)i(sp)s (ecial)f(compiler)g(option)g(\015ags)g(b)s(e)f(sp)s(eci\014ed)g(to)i (turn)d(on)i(this)p eop end %%Page: 29 37 TeXDict begin 29 36 bop 0 299 a Fh(4.13.)73 b(CFITSIO)28 b(SIZE)h(LIMIT)-8 b(A)g(TIONS)2300 b Fj(29)0 555 y(option.)69 b(On)39 b(lin)m(ux)h(and)f(solaris)i(systems)f(the)g(compiler)g (\015ags)g(are)g('-D)p 2617 555 28 4 v 34 w(LAR)m(GEFILE)p 3184 555 V 33 w(SOUR)m(CE')f(and)g(`-)0 668 y(D)p 74 668 V 33 w(FILE)p 318 668 V 33 w(OFFSET)p 719 668 V 32 w(BITS=64'.)i(These)29 b(\015ags)h(ma)m(y)g(also)h(w)m(ork)f(on)g (other)g(platforms)f(but)g(this)h(has)g(not)g(b)s(een)0 781 y(tested.)43 b(Starting)31 b(with)f(v)m(ersion)h(3.0)h(of)f (CFITSIO,)f(the)h(default)f(Mak)m(e\014le)j(that)e(is)g(distributed)f (with)g(CFIT-)0 894 y(SIO)h(will)h(include)g(these)g(2)g(compiler)h (\015ags)f(when)e(building)h(on)h(Solaris)g(and)g(Lin)m(ux)f(PC)g (systems.)45 b(Users)32 b(on)0 1007 y(other)g(platforms)g(will)g(need)f (to)i(add)e(these)h(compiler)h(\015ags)f(man)m(ually)g(if)g(they)g(w)m (an)m(t)g(to)h(supp)s(ort)d(large)j(\014les.)0 1120 y(In)j(most)i (cases)g(it)g(app)s(ears)e(that)i(it)g(is)f(not)h(necessary)f(to)h (include)f(these)h(compiler)g(\015ags)f(when)f(compiling)0 1233 y(application)c(co)s(de)e(that)h(call)h(the)e(CFITSIO)f(library)h (routines.)0 1393 y(When)i(CFITSIO)e(is)i(built)g(with)g(large)h (\014le)f(supp)s(ort)e(\(e.g.,)35 b(on)d(Solaris)g(and)f(Lin)m(ux)h(PC) f(system)h(b)m(y)g(default\))0 1506 y(then)e(it)h(can)g(read)f(and)g (write)g(FITS)g(data)h(\014les)f(on)h(disk)e(that)i(ha)m(v)m(e)h(an)m (y)f(of)f(these)h(conditions:)136 1766 y Fc(\017)46 b Fj(FITS)30 b(\014les)g(larger)h(than)f(2.1)i(GB)f(in)f(size)136 1953 y Fc(\017)46 b Fj(FITS)30 b(images)h(con)m(taining)h(greater)g (than)e(2.1)h(G)g(pixels)136 2141 y Fc(\017)46 b Fj(FITS)34 b(images)i(that)g(ha)m(v)m(e)g(one)f(dimension)f(with)g(more)h(than)g (2.1)h(G)f(pixels)g(\(as)g(giv)m(en)h(b)m(y)f(one)g(of)g(the)227 2254 y(NAXISn)30 b(k)m(eyw)m(ord\))136 2441 y Fc(\017)46 b Fj(FITS)26 b(tables)h(con)m(taining)g(more)g(than)f(2.1E09)i(ro)m(ws) e(\(giv)m(en)i(b)m(y)e(the)g(NAXIS2)h(k)m(eyw)m(ord\),)h(or)e(with)g (ro)m(ws)227 2554 y(that)31 b(are)g(more)g(than)f(2.1)h(GB)g(wide)f (\(giv)m(en)i(b)m(y)e(the)h(NAXIS1)f(k)m(eyw)m(ord\))136 2742 y Fc(\017)46 b Fj(FITS)36 b(binary)f(tables)i(with)f(a)h(v)-5 b(ariable-length)38 b(arra)m(y)f(heap)f(that)h(is)f(larger)h(than)f (2.1)h(GB)g(\(giv)m(en)h(b)m(y)227 2855 y(the)31 b(PCOUNT)e(k)m(eyw)m (ord\))0 3115 y(The)c(curren)m(t)g(maxim)m(um)g(FITS)f(\014le)h(size)h (supp)s(orted)e(b)m(y)h(CFITSIO)e(is)j(ab)s(out)f(6)g(terab)m(ytes)i (\(con)m(taining)g(2**31)0 3227 y(FITS)d(blo)s(c)m(ks,)i(eac)m(h)g (2880)h(b)m(ytes)e(in)f(size\).)40 b(Curren)m(tly)-8 b(,)26 b(supp)s(ort)d(for)i(large)g(\014les)g(in)g(CFITSIO)e(has)h(b)s (een)g(tested)0 3340 y(on)30 b(the)h(Lin)m(ux,)f(Solaris,)h(and)f(IBM)g (AIX)h(op)s(erating)g(systems.)0 3501 y(Note)26 b(that)f(when)e (writing)h(application)i(programs)e(that)h(are)f(in)m(tended)g(to)h (supp)s(ort)e(large)i(\014les)g(it)f(is)h(imp)s(ortan)m(t)0 3613 y(to)31 b(use)g(64-bit)g(in)m(teger)h(v)-5 b(ariables)31 b(to)h(store)f(quan)m(tities)h(suc)m(h)e(as)h(the)f(dimensions)g(of)h (images,)h(or)f(the)f(n)m(um)m(b)s(er)0 3726 y(of)38 b(ro)m(ws)f(in)h(a)g(table.)63 b(These)38 b(programs)f(m)m(ust)g(also)i (call)g(the)f(sp)s(ecial)g(v)m(ersions)g(of)g(some)g(of)g(the)f (CFITSIO)0 3839 y(routines)28 b(that)h(ha)m(v)m(e)h(b)s(een)d(adapted)i (to)g(supp)s(ort)e(64-bit)i(in)m(tegers.)42 b(The)27 b(names)i(of)f(these)h(routines)f(end)g(in)g('ll')0 3952 y(\('el')k('el'\))g(to)f(distinguish)e(them)i(from)f(the)g(32-bit)i(in) m(teger)g(v)m(ersion)e(\(e.g.,)j(\014ts)p 2766 3952 V 32 w(get)p 2918 3952 V 34 w(n)m(um)p 3127 3952 V 32 w(ro)m(wsll\).)p eop end %%Page: 30 38 TeXDict begin 30 37 bop 0 299 a Fj(30)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)p eop end %%Page: 31 39 TeXDict begin 31 38 bop 0 1225 a Fg(Chapter)65 b(5)0 1687 y Fm(Basic)77 b(CFITSIO)f(In)-6 b(terface)77 b(Routines)0 2180 y Fj(This)30 b(c)m(hapter)i(describ)s(es)e(the)i(basic)f(routines) g(in)g(the)g(CFITSIO)e(user)i(in)m(terface)h(that)g(pro)m(vide)f(all)h (the)g(func-)0 2293 y(tions)j(normally)g(needed)g(to)g(read)g(and)f (write)h(most)h(FITS)e(\014les.)54 b(It)35 b(is)g(recommended)f(that)i (these)f(routines)0 2406 y(b)s(e)d(used)g(for)g(most)h(applications)h (and)e(that)h(the)f(more)h(adv)-5 b(anced)33 b(routines)f(describ)s(ed) g(in)g(the)h(next)f(c)m(hapter)0 2518 y(only)e(b)s(e)g(used)g(in)g(sp)s (ecial)h(circumstances)g(when)e(necessary)-8 b(.)0 2679 y(The)30 b(follo)m(wing)i(con)m(v)m(en)m(tions)g(are)f(used)e(in)i (this)f(c)m(hapter)h(in)f(the)g(description)h(of)f(eac)m(h)i(function:) 0 2839 y(1.)39 b(Most)25 b(functions)e(ha)m(v)m(e)i(2)f(names:)37 b(a)24 b(long)h(descriptiv)m(e)f(name)g(and)f(a)i(short)e(concise)i (name.)38 b(Both)25 b(names)f(are)0 2952 y(listed)g(on)f(the)g(\014rst) f(line)i(of)f(the)h(follo)m(wing)g(descriptions,)h(separated)e(b)m(y)h (a)f(slash)g(\(/\))h(c)m(haracter.)40 b(Programmers)0 3065 y(ma)m(y)27 b(use)g(either)g(name)g(in)f(their)h(programs)g(but)f (the)h(long)g(names)g(are)g(recommended)f(to)i(help)e(do)s(cumen)m(t)h (the)0 3177 y(co)s(de)k(and)e(mak)m(e)j(it)f(easier)g(to)g(read.)0 3338 y(2.)42 b(A)30 b(righ)m(t)h(arro)m(w)g(sym)m(b)s(ol)f(\()p Fb(>)p Fj(\))h(is)g(used)f(in)g(the)h(function)f(descriptions)g(to)i (separate)f(the)g(input)f(parameters)0 3451 y(from)j(the)g(output)f (parameters)i(in)f(the)g(de\014nition)g(of)g(eac)m(h)h(routine.)49 b(This)32 b(sym)m(b)s(ol)h(is)g(not)g(actually)i(part)e(of)0 3563 y(the)e(C)f(calling)h(sequence.)0 3724 y(3.)41 b(The)30 b(function)g(parameters)h(are)g(de\014ned)e(in)h(more)g(detail)i(in)e (the)g(alphab)s(etical)i(listing)f(in)f(App)s(endix)f(B.)0 3884 y(4.)39 b(The)23 b(\014rst)g(argumen)m(t)g(in)h(almost)g(all)h (the)e(functions)g(is)h(a)g(p)s(oin)m(ter)f(to)h(a)g(structure)f(of)h (t)m(yp)s(e)g(`\014ts\014le'.)38 b(Memory)0 3997 y(for)26 b(this)g(structure)f(is)h(allo)s(cated)i(b)m(y)e(CFITSIO)e(when)h(the)h (FITS)g(\014le)g(is)g(\014rst)f(op)s(ened)g(or)h(created)h(and)e(is)h (freed)0 4110 y(when)j(the)i(FITS)f(\014le)g(is)g(closed.)0 4270 y(5.)53 b(The)34 b(last)h(argumen)m(t)f(in)g(almost)i(all)f(the)f (functions)g(is)g(the)h(error)f(status)g(parameter.)53 b(It)35 b(m)m(ust)f(b)s(e)f(equal)0 4383 y(to)k(0)g(on)f(input,)h (otherwise)g(the)f(function)g(will)h(immediately)g(exit)g(without)g (doing)f(an)m(ything.)59 b(A)36 b(non-zero)0 4496 y(output)27 b(v)-5 b(alue)27 b(indicates)i(that)e(an)g(error)g(o)s(ccurred)g(in)g (the)g(function.)39 b(In)27 b(most)g(cases)h(the)g(status)f(v)-5 b(alue)28 b(is)f(also)0 4608 y(returned)i(as)i(the)f(v)-5 b(alue)31 b(of)g(the)f(function)g(itself.)0 4935 y Ff(5.1)135 b(CFITSIO)44 b(Error)h(Status)h(Routines)0 5168 y Fi(1)81 b Fj(Return)27 b(a)j(descriptiv)m(e)f(text)h(string)e(\(30)i(c)m(har)f (max.\))41 b(corresp)s(onding)28 b(to)h(a)g(CFITSIO)e(error)h(status)h (co)s(de.)95 5385 y Fe(void)47 b(fits_get_errstatus)c(/)k(ffgerr)f (\(int)h(status,)f(>)h(char)g(*err_text\))0 5601 y Fi(2)81 b Fj(Return)35 b(the)h(top)g(\(oldest\))h(80-c)m(haracter)i(error)c (message)i(from)e(the)h(in)m(ternal)h(CFITSIO)d(stac)m(k)j(of)f(error) 227 5714 y(messages)45 b(and)e(shift)h(an)m(y)g(remaining)g(messages)h (on)f(the)g(stac)m(k)h(up)e(one)h(lev)m(el.)83 b(Call)44 b(this)g(routine)1905 5942 y(31)p eop end %%Page: 32 40 TeXDict begin 32 39 bop 0 299 a Fj(32)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(rep)s(eatedly)c(to)h(get)g(eac)m(h)g (message)f(in)g(sequence.)39 b(The)26 b(function)f(returns)g(a)h(v)-5 b(alue)26 b(=)f(0)h(and)g(a)g(n)m(ull)f(error)227 668 y(message)32 b(when)d(the)i(error)f(stac)m(k)i(is)e(empt)m(y)-8 b(.)95 940 y Fe(int)47 b(fits_read_errmsg)d(/)j(ffgmsg)f(\(char)h (*err_msg\))0 1211 y Fi(3)81 b Fj(Prin)m(t)30 b(out)h(the)g(error)f (message)i(corresp)s(onding)e(to)h(the)g(input)f(status)h(v)-5 b(alue)31 b(and)f(all)i(the)f(error)f(messages)227 1324 y(on)d(the)h(CFITSIO)e(stac)m(k)j(to)f(the)f(sp)s(eci\014ed)g(\014le)g (stream)h(\(normally)g(to)g(stdout)f(or)g(stderr\).)40 b(If)26 b(the)i(input)227 1437 y(status)j(v)-5 b(alue)31 b(=)f(0)h(then)f(this)g(routine)g(do)s(es)g(nothing.)95 1709 y Fe(void)47 b(fits_report_error)c(/)48 b(ffrprt)e(\(FILE)g (*stream,)g(status\))0 1981 y Fi(4)81 b Fj(The)44 b(\014ts)p 461 1981 28 4 v 32 w(write)p 695 1981 V 33 w(errmark)g(routine)h(puts)f (an)h(in)m(visible)g(mark)m(er)g(on)g(the)g(CFITSIO)e(error)h(stac)m (k.)85 b(The)227 2094 y(\014ts)p 354 2094 V 33 w(clear)p 573 2094 V 34 w(errmark)31 b(routine)i(can)g(then)f(b)s(e)f(used)h(to)h (delete)h(an)m(y)f(more)f(recen)m(t)i(error)e(messages)h(on)g(the)227 2207 y(stac)m(k,)42 b(bac)m(k)c(to)g(the)g(p)s(osition)g(of)g(the)g (mark)m(er.)63 b(This)37 b(preserv)m(es)g(an)m(y)h(older)g(error)f (messages)i(on)f(the)227 2319 y(stac)m(k.)77 b(The)41 b(\014ts)p 855 2319 V 32 w(clear)p 1073 2319 V 34 w(errmsg)g(routine)h (simply)f(clears)i(all)g(the)f(messages)g(\(and)g(marks\))f(from)h(the) 227 2432 y(stac)m(k.)g(These)31 b(routines)f(are)h(called)g(without)g (an)m(y)f(argumen)m(ts.)95 2704 y Fe(void)47 b(fits_write_errmark)c(/)k (ffpmrk)f(\(void\))95 2817 y(void)h(fits_clear_errmark)c(/)k(ffcmrk)f (\(void\))95 2930 y(void)h(fits_clear_errmsg)c(/)48 b(ffcmsg)e (\(void\))0 3278 y Ff(5.2)135 b(FITS)44 b(File)i(Access)e(Routines)0 3527 y Fi(1)81 b Fj(Op)s(en)29 b(an)h(existing)h(data)g(\014le.)227 3794 y Fe(int)47 b(fits_open_file)d(/)k(ffopen)418 3907 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h(int)g (*status\))227 4133 y(int)g(fits_open_diskfile)c(/)k(ffdkopn)418 4246 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 4472 y(int)g(fits_open_data)d(/)k(ffdopn)418 4585 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 4811 y(int)g(fits_open_table)d(/)j(fftopn)418 4924 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 5149 y(int)g(fits_open_image)d(/)j(ffiopn)418 5262 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 5488 y(int)g(fits_open_extlist)c(/)48 b(ffeopn)418 5601 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i (iomode,)f(char)g(*extlist,)418 5714 y(>)95 b(int)47 b(*hdutype,)f(int)g(*status\))p eop end %%Page: 33 41 TeXDict begin 33 40 bop 0 299 a Fh(5.2.)72 b(FITS)30 b(FILE)g(A)m(CCESS)f(R)m(OUTINES)2244 b Fj(33)227 555 y(The)41 b(iomo)s(de)h(parameter)g(determines)g(the)f(read/write)h (access)h(allo)m(w)m(ed)h(in)d(the)g(\014le)h(and)f(can)h(ha)m(v)m(e) 227 668 y(v)-5 b(alues)32 b(of)g(READONL)-8 b(Y)32 b(\(0\))g(or)g(READ) m(WRITE)g(\(1\).)44 b(The)31 b(\014lename)h(parameter)g(giv)m(es)h(the) e(name)h(of)227 781 y(the)f(\014le)g(to)g(b)s(e)f(op)s(ened,)h(follo)m (w)m(ed)h(b)m(y)f(an)f(optional)i(argumen)m(t)f(giving)h(the)f(name)f (or)h(index)f(n)m(um)m(b)s(er)g(of)227 894 y(the)d(extension)g(within)g (the)f(FITS)g(\014le)h(that)g(should)f(b)s(e)g(mo)m(v)m(ed)i(to)f(and)f (op)s(ened)g(\(e.g.,)k Fe(myfile.fits+3)227 1007 y Fj(or)36 b Fe(myfile.fits[3])d Fj(mo)m(v)m(es)k(to)g(the)g(3rd)f(extension)g (within)g(the)h(\014le,)h(and)d Fe(myfile.fits[events])227 1120 y Fj(mo)m(v)m(es)d(to)f(the)g(extension)g(with)f(the)g(k)m(eyw)m (ord)h(EXTNAME)g(=)f('EVENTS'\).)227 1276 y(The)37 b(\014ts)p 548 1276 28 4 v 32 w(op)s(en)p 770 1276 V 32 w(disk\014le)g(routine)g (is)g(similar)g(to)h(the)f(\014ts)p 2241 1276 V 33 w(op)s(en)p 2464 1276 V 32 w(\014le)g(routine)g(except)h(that)f(it)h(do)s(es)f(not) 227 1389 y(supp)s(ort)22 b(the)h(extended)h(\014lename)f(syn)m(tax)h (in)f(the)h(input)e(\014le)i(name.)38 b(This)23 b(routine)g(simply)g (tries)h(to)g(op)s(en)227 1502 y(the)36 b(sp)s(eci\014ed)e(input)h (\014le)g(on)g(magnetic)i(disk.)55 b(This)34 b(routine)h(is)h(mainly)f (for)g(use)g(in)g(cases)h(where)f(the)227 1615 y(\014lename)f(\(or)h (directory)f(path\))g(con)m(tains)h(square)f(or)g(curly)f(brac)m(k)m (et)j(c)m(haracters)f(that)f(w)m(ould)g(confuse)227 1728 y(the)d(extended)f(\014lename)h(parser.)227 1884 y(The)i(\014ts)p 544 1884 V 32 w(op)s(en)p 766 1884 V 32 w(data)h(routine)e(is)h (similar)g(to)h(the)f(\014ts)p 2113 1884 V 32 w(op)s(en)p 2335 1884 V 33 w(\014le)f(routine)h(except)h(that)f(it)h(will)f(mo)m(v) m(e)h(to)227 1997 y(the)23 b(\014rst)f(HDU)h(con)m(taining)h (signi\014can)m(t)f(data,)i(if)e(a)g(HDU)g(name)f(or)h(n)m(um)m(b)s(er) e(to)i(op)s(en)f(w)m(as)h(not)f(explicitly)227 2110 y(sp)s(eci\014ed)37 b(as)g(part)h(of)f(the)h(\014lename.)61 b(In)37 b(this)g(case,)j(it)e (will)g(lo)s(ok)g(for)f(the)g(\014rst)g(IMA)m(GE)h(HDU)g(with)227 2223 y(NAXIS)29 b(greater)h(than)e(0,)i(or)f(the)f(\014rst)g(table)i (that)f(do)s(es)g(not)g(con)m(tain)h(the)f(strings)f(`GTI')h(\(Go)s(o)s (d)g(Time)227 2336 y(In)m(terv)-5 b(al)31 b(extension\))h(or)e(`OBST)-8 b(ABLE')31 b(in)f(the)h(EXTNAME)f(k)m(eyw)m(ord)h(v)-5 b(alue.)227 2492 y(The)25 b(\014ts)p 536 2492 V 32 w(op)s(en)p 758 2492 V 32 w(table)h(and)e(\014ts)p 1305 2492 V 33 w(op)s(en)p 1528 2492 V 32 w(image)i(routines)f(are)g(similar)h(to)f (\014ts)p 2828 2492 V 33 w(op)s(en)p 3051 2492 V 32 w(data)h(except)f (they)h(will)227 2605 y(mo)m(v)m(e)h(to)g(the)f(\014rst)f(signi\014can) m(t)h(table)h(HDU)f(or)g(image)h(HDU)f(in)f(the)h(\014le,)h(resp)s (ectiv)m(ely)-8 b(,)29 b(if)c(a)h(HDU)h(name)227 2718 y(or)k(n)m(um)m(b)s(er)e(is)h(not)h(sp)s(eci\014ed)e(as)i(part)f(of)h (the)f(\014lename.)227 2874 y(The)h(\014ts)p 542 2874 V 33 w(op)s(en)p 765 2874 V 32 w(extlist)i(routine)f(op)s(ens)f(the)h (\014le)f(and)g(attempts)i(to)f(mo)m(v)m(e)i(to)e(a)g('useful')g(HDU.)g (If)f(after)227 2987 y(op)s(ening)43 b(the)h(\014le)g(CFITSIO)d(is)j(p) s(oin)m(ting)g(to)g(n)m(ull)f(primary)g(arra)m(y)-8 b(,)48 b(then)43 b(CFITSIO)f(will)i(attempt)227 3100 y(to)38 b(mo)m(v)m(e)g(to)f(the)g(\014rst)f(extension)h(that)g(has)f(an)h (EXTNAME)g(or)f(HDUNAME)i(k)m(eyw)m(ord)f(v)-5 b(alue)37 b(that)227 3213 y(matc)m(hes)i(one)e(of)h(the)g(names)f(in)g(the)g (input)g(extlist)i(space-delimited)g(list)f(of)f(names)g(\(wildcards)h (are)227 3326 y(p)s(ermitted\).)g(If)19 b(that)i(fails,)j(then)c (CFITSIO)e(simply)i(mo)m(v)m(es)i(to)f(the)g(2nd)e(HDU)i(in)f(the)h (\014le.)37 b(Up)s(on)20 b(return,)227 3438 y(the)31 b(t)m(yp)s(e)f(of)h(the)f(HDU)i(is)e(returned)f(in)h(*hdut)m(yp)s(e,)g (as)h(describ)s(ed)e(in)h(5.3)h(HDU)h(Access)f(Routines.)227 3595 y(IRAF)26 b(images)g(\(.imh)g(format)g(\014les\))f(and)g(ra)m(w)h (binary)e(data)j(arra)m(ys)e(ma)m(y)h(also)h(b)s(e)e(op)s(ened)f(with)h (READ-)227 3708 y(ONL)-8 b(Y)37 b(access.)60 b(CFITSIO)35 b(will)i(automatically)i(test)f(if)e(the)h(input)e(\014le)i(is)f(an)h (IRAF)f(image,)k(and)c(if,)227 3821 y(so)c(will)g(con)m(v)m(ert)h(it)f (on)f(the)h(\015y)f(in)m(to)i(a)f(virtual)f(FITS)g(image)i(b)s(efore)e (it)h(is)g(op)s(ened)e(b)m(y)i(the)g(application)227 3933 y(program.)64 b(If)37 b(the)h(input)g(\014le)g(is)g(a)g(ra)m(w)g (binary)g(data)g(arra)m(y)h(of)f(n)m(um)m(b)s(ers,)h(then)e(the)i(data) f(t)m(yp)s(e)h(and)227 4046 y(dimensions)d(of)g(the)g(arra)m(y)h(m)m (ust)f(b)s(e)f(sp)s(eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m (wing)h(the)e(name)g(of)h(the)f(\014le)227 4159 y(\(e.g.)56 b('ra)m(w\014le.dat[i512,512]')40 b(op)s(ens)34 b(a)i(512)g(x)f(512)h (short)e(in)m(teger)j(image\).)56 b(See)35 b(the)g(`Extended)g(File)227 4272 y(Name)k(Syn)m(tax')g(c)m(hapter)g(for)e(more)i(details)g(on)f(ho) m(w)g(to)h(sp)s(ecify)f(the)g(ra)m(w)h(\014le)f(name.)64 b(The)38 b(ra)m(w)g(\014le)227 4385 y(is)k(con)m(v)m(erted)g(on)f(the)h (\015y)f(in)m(to)h(a)f(virtual)h(FITS)e(image)j(in)e(memory)g(that)h (is)f(then)g(op)s(ened)g(b)m(y)g(the)227 4498 y(application)32 b(program)e(with)g(READONL)-8 b(Y)31 b(access.)227 4654 y(Programs)g(can)g(read)f(the)h(input)e(\014le)i(from)f(the)h('stdin')f (\014le)h(stream)g(if)f(a)h(dash)f(c)m(haracter)i(\('-'\))g(is)f(giv)m (en)227 4767 y(as)36 b(the)g(\014lename.)58 b(Files)37 b(can)f(also)h(b)s(e)e(op)s(ened)g(o)m(v)m(er)i(the)f(net)m(w)m(ork)h (using)e(FTP)h(or)g(HTTP)f(proto)s(cols)227 4880 y(b)m(y)j(supplying)f (the)h(appropriate)h(URL)e(as)i(the)f(\014lename.)64 b(The)38 b(HTTPS)f(and)g(FTPS)h(proto)s(cols)h(are)227 4993 y(also)29 b(supp)s(orted)d(if)i(the)g(CFITSIO)e(build)h(includes)g (the)h(lib)s(curl)f(library)-8 b(.)40 b(\(If)27 b(the)h(CFITSIO)f ('con\014gure')227 5106 y(script)34 b(\014nds)e(a)i(usable)f(lib)s (curl)g(library)h(on)f(y)m(our)h(system,)h(it)f(will)g(automatically)i (b)s(e)d(included)g(in)h(the)227 5219 y(build.\))227 5375 y(The)43 b(input)f(\014le)h(can)h(b)s(e)f(mo)s(di\014ed)f(in)g(v) -5 b(arious)44 b(w)m(a)m(ys)g(to)g(create)g(a)g(virtual)f(\014le)h (\(usually)f(stored)g(in)227 5488 y(memory\))31 b(that)g(is)g(then)f (op)s(ened)f(b)m(y)i(the)f(application)i(program)e(b)m(y)h(supplying)e (a)i(\014ltering)g(or)f(binning)227 5601 y(sp)s(eci\014er)e(in)g (square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014lename.)40 b(Some)29 b(of)f(the)g(more)h(common)f(\014ltering)h(meth-)227 5714 y(o)s(ds)j(are)h(illustrated)h(in)e(the)h(follo)m(wing)i (paragraphs,)e(but)f(users)g(should)f(refer)i(to)g(the)g('Extended)g (File)p eop end %%Page: 34 42 TeXDict begin 34 41 bop 0 299 a Fj(34)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(Name)h(Syn)m(tax')g(c)m(hapter)g(for)f(a)h (complete)h(description)e(of)h(the)f(full)h(\014le)f(\014ltering)h(syn) m(tax.)227 705 y(When)c(op)s(ening)f(an)h(image,)h(a)g(rectangular)f (subset)f(of)h(the)g(ph)m(ysical)g(image)h(ma)m(y)g(b)s(e)e(op)s(ened)f (b)m(y)i(listing)227 818 y(the)k(\014rst)e(and)h(last)h(pixel)g(in)f (eac)m(h)i(dimension)e(\(and)g(optional)h(pixel)g(skipping)f(factor\):) 227 1066 y Fe(myimage.fits[101:200,301:)o(400])227 1313 y Fj(will)g(create)h(and)e(op)s(en)f(a)i(100x100)i(pixel)e(virtual)g (image)g(of)g(that)g(section)g(of)g(the)f(ph)m(ysical)h(image,)i(and) 227 1426 y Fe(myimage.fits[*,-*])c Fj(op)s(ens)k(a)h(virtual)g(image)h (that)f(is)g(the)g(same)g(size)h(as)e(the)h(ph)m(ysical)h(image)g(but) 227 1539 y(has)c(b)s(een)g(\015ipp)s(ed)f(in)h(the)g(v)m(ertical)j (direction.)227 1689 y(When)28 b(op)s(ening)g(a)g(table,)i(the)e (\014ltering)g(syn)m(tax)h(can)f(b)s(e)f(used)h(to)g(add)g(or)g(delete) h(columns)f(or)g(k)m(eyw)m(ords)227 1802 y(in)g(the)g(virtual)h(table:) 40 b Fe(myfile.fits[events][col)i(!time;)k(PI)h(=)h(PHA*1.2])26 b Fj(op)s(ens)h(a)h(virtual)h(ta-)227 1915 y(ble)j(in)f(whic)m(h)g(the) h(TIME)f(column)g(has)g(b)s(een)g(deleted)h(and)f(a)g(new)g(PI)g (column)h(has)f(b)s(een)g(added)f(with)227 2027 y(a)41 b(v)-5 b(alue)40 b(1.2)i(times)e(that)h(of)f(the)h(PHA)f(column.)70 b(Similarly)-8 b(,)43 b(one)e(can)f(\014lter)h(a)f(table)h(to)g(k)m (eep)g(only)227 2140 y(those)35 b(ro)m(ws)e(that)i(satisfy)f(a)g (selection)i(criterion:)48 b Fe(myfile.fits[events][pha)42 b(>)47 b(50])33 b Fj(creates)j(and)227 2253 y(op)s(ens)31 b(a)g(virtual)h(table)g(con)m(taining)h(only)e(those)h(ro)m(ws)f(with)g (a)g(PHA)h(v)-5 b(alue)31 b(greater)i(than)e(50.)44 b(A)31 b(large)227 2366 y(n)m(um)m(b)s(er)d(of)h(b)s(o)s(olean)h(and)e (mathematical)k(op)s(erators)d(can)g(b)s(e)g(used)f(in)h(the)g (selection)i(expression.)40 b(One)227 2479 y(can)25 b(also)g(\014lter)g (table)g(ro)m(ws)f(using)g('Go)s(o)s(d)h(Time)f(In)m(terv)-5 b(al')26 b(extensions,)g(and)e(spatial)h(region)g(\014lters)g(as)f(in) 227 2592 y Fe(myfile.fits[events][gtifi)o(lter)o(\(\)])14 b Fj(and)19 b Fe(myfile.fits[events][regfil)o(ter)o(\()42 b("stars.rng"\)])p Fj(.)227 2742 y(Finally)-8 b(,)34 b(table)e(columns)f(ma)m(y)h(b)s(e)f(binned)f(or)h(histogrammed)h(to)g (generate)h(a)e(virtual)h(image.)45 b(F)-8 b(or)32 b(ex-)227 2855 y(ample,)d Fe(myfile.fits[events][bin)41 b(\(X,Y\)=4])26 b Fj(will)h(result)h(in)f(a)h(2-dimensional)g(image)h(calculated)227 2968 y(b)m(y)35 b(binning)e(the)i(X)f(and)g(Y)h(columns)f(in)g(the)h (ev)m(en)m(t)h(table)f(with)f(a)h(bin)f(size)h(of)g(4)f(in)h(eac)m(h)g (dimension.)227 3081 y(The)30 b(TLMINn)g(and)f(TLMAXn)h(k)m(eyw)m(ords) h(will)g(b)s(e)e(used)h(b)m(y)g(default)h(to)g(determine)f(the)h(range) f(of)h(the)227 3194 y(image.)227 3343 y(A)j(single)g(program)f(can)g (op)s(en)g(the)h(same)f(FITS)g(\014le)g(more)h(than)f(once)h(and)f (then)g(treat)h(the)g(resulting)227 3456 y(\014ts\014le)c(p)s(oin)m (ters)g(as)g(though)g(they)g(w)m(ere)h(completely)h(indep)s(enden)m(t)d (FITS)g(\014les.)40 b(Using)31 b(this)f(facilit)m(y)-8 b(,)33 b(a)227 3569 y(program)f(can)f(op)s(en)g(a)h(FITS)f(\014le)g(t)m (wice,)j(mo)m(v)m(e)f(to)f(2)g(di\013eren)m(t)g(extensions)g(within)f (the)g(\014le,)h(and)f(then)227 3682 y(read)g(and)e(write)i(data)g(in)f (those)h(extensions)g(in)f(an)m(y)h(order.)0 3940 y Fi(2)81 b Fj(Create)31 b(and)f(op)s(en)f(a)i(new)f(empt)m(y)h(output)f(FITS)f (\014le.)227 4187 y Fe(int)47 b(fits_create_file)d(/)j(ffinit)418 4300 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(>)i(int)g(*status\)) 227 4526 y(int)g(fits_create_diskfile)42 b(/)48 b(ffdkinit)418 4639 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(>)i(int)g(*status\)) 227 4886 y Fj(An)36 b(error)h(will)g(b)s(e)f(returned)f(if)h(the)h(sp)s (eci\014ed)f(\014le)h(already)g(exists,)i(unless)d(the)h(\014lename)f (is)h(pre\014xed)227 4999 y(with)30 b(an)g(exclamation)i(p)s(oin)m(t)e (\(!\).)42 b(In)29 b(that)i(case)g(CFITSIO)d(will)j(o)m(v)m(erwrite)g (\(delete\))h(an)m(y)f(existing)g(\014le)227 5112 y(with)36 b(the)g(same)h(name.)57 b(Note)38 b(that)e(the)h(exclamation)h(p)s(oin) m(t)e(is)g(a)h(sp)s(ecial)f(UNIX)g(c)m(haracter)i(so)e(if)g(it)227 5225 y(is)d(used)e(on)h(the)h(command)f(line)h(it)g(m)m(ust)f(b)s(e)g (preceded)g(b)m(y)g(a)g(bac)m(kslash)h(to)h(force)e(the)h(UNIX)g(shell) f(to)227 5338 y(accept)g(the)f(c)m(haracter)h(as)e(part)g(of)h(the)g (\014lename.)227 5488 y(The)26 b(output)h(\014le)g(will)g(b)s(e)f (written)h(to)g(the)g('stdout')g(\014le)g(stream)g(if)g(a)g(dash)f(c)m (haracter)i(\('-'\))g(or)f(the)g(string)227 5601 y('stdout')34 b(is)f(giv)m(en)h(as)g(the)f(\014lename.)49 b(Similarly)-8 b(,)35 b('-.gz')g(or)e('stdout.gz')i(will)f(cause)f(the)h(\014le)f(to)h (b)s(e)e(gzip)227 5714 y(compressed)e(b)s(efore)g(it)h(is)g(written)f (out)h(to)g(the)f(stdout)h(stream.)p eop end %%Page: 35 43 TeXDict begin 35 42 bop 0 299 a Fh(5.3.)72 b(HDU)31 b(A)m(CCESS)e(R)m (OUTINES)2488 b Fj(35)227 555 y(Optionally)-8 b(,)41 b(the)c(name)h(of)f(a)h(template)h(\014le)e(that)h(is)f(used)g(to)h (de\014ne)f(the)g(structure)g(of)g(the)h(new)f(\014le)227 668 y(ma)m(y)i(b)s(e)f(sp)s(eci\014ed)f(in)h(paren)m(theses)h(follo)m (wing)g(the)g(output)e(\014le)i(name.)64 b(The)38 b(template)h(\014le)g (ma)m(y)g(b)s(e)227 781 y(another)32 b(FITS)e(\014le,)i(in)f(whic)m(h)g (case)i(the)e(new)g(\014le,)h(at)g(the)g(time)g(it)f(is)h(op)s(ened,)f (will)g(b)s(e)g(an)g(exact)i(cop)m(y)227 894 y(of)38 b(the)g(template)i(\014le)e(except)g(that)h(the)f(data)g(structures)g (\(images)h(and)e(tables\))i(will)f(b)s(e)g(\014lled)f(with)227 1007 y(zeros.)k(Alternativ)m(ely)-8 b(,)32 b(the)d(template)i(\014le)e (ma)m(y)g(b)s(e)f(an)h(ASCI)s(I)e(format)i(text)h(\014le)f(con)m (taining)i(directiv)m(es)227 1120 y(that)e(de\014ne)e(the)h(k)m(eyw)m (ords)g(to)g(b)s(e)g(created)h(in)e(eac)m(h)i(HDU)g(of)f(the)g(\014le.) 40 b(See)28 b(the)g('Extended)f(File)i(Name)227 1233 y(Syn)m(tax')i(section)h(for)e(a)h(complete)g(description)g(of)f(the)h (template)h(\014le)e(syn)m(tax.)227 1382 y(The)f(\014ts)p 540 1382 28 4 v 33 w(create)p 809 1382 V 34 w(disk\014le)g(routine)h (is)g(similar)g(to)g(the)g(\014ts)p 2238 1382 V 32 w(create)p 2506 1382 V 34 w(\014le)g(routine)g(except)g(that)g(it)g(do)s(es)g(not) 227 1495 y(supp)s(ort)36 b(the)i(extended)g(\014lename)g(syn)m(tax)g (in)g(the)g(input)f(\014le)h(name.)63 b(This)37 b(routine)h(simply)f (tries)h(to)227 1608 y(create)e(the)e(sp)s(eci\014ed)f(\014le)h(on)f (magnetic)j(disk.)50 b(This)33 b(routine)h(is)g(mainly)g(for)g(use)f (in)h(cases)g(where)g(the)227 1721 y(\014lename)g(\(or)h(directory)f (path\))g(con)m(tains)h(square)f(or)g(curly)f(brac)m(k)m(et)j(c)m (haracters)f(that)f(w)m(ould)g(confuse)227 1833 y(the)d(extended)f (\014lename)h(parser.)0 2086 y Fi(3)81 b Fj(Close)28 b(a)f(previously)g(op)s(ened)g(FITS)g(\014le.)40 b(The)27 b(\014rst)f(routine)i(simply)f(closes)h(the)g(\014le,)g(whereas)f(the)h (second)227 2199 y(one)g(also)h(DELETES)e(the)g(\014le,)i(whic)m(h)e (can)h(b)s(e)g(useful)e(in)i(cases)g(where)g(a)g(FITS)f(\014le)g(has)h (b)s(een)f(partially)227 2312 y(created,)37 b(but)c(then)h(an)h(error)e (o)s(ccurs)h(whic)m(h)g(prev)m(en)m(ts)h(it)g(from)f(b)s(eing)g (completed.)53 b(Note)36 b(that)e(these)227 2425 y(routines)23 b(b)s(eha)m(v)m(e)g(di\013eren)m(tly)h(than)e(most)h(other)g(CFITSIO)e (routines)i(if)f(the)h(input)f(v)-5 b(alue)23 b(of)g(the)g(`status')227 2538 y(parameter)43 b(is)f(not)h(zero:)65 b(Instead)42 b(of)h(simply)f(returning)f(to)i(the)g(calling)g(program)g(without)f (doing)227 2651 y(an)m(ything,)30 b(these)f(routines)f(e\013ectiv)m (ely)k(ignore)d(the)f(input)g(status)h(v)-5 b(alue)29 b(and)f(still)h(attempt)h(to)f(close)h(or)227 2764 y(delete)i(the)e (\014le.)95 3017 y Fe(int)47 b(fits_close_file)d(/)j(ffclos)g (\(fitsfile)e(*fptr,)h(>)h(int)g(*status\))95 3243 y(int)g (fits_delete_file)d(/)j(ffdelt)f(\(fitsfile)g(*fptr,)g(>)h(int)g (*status\))0 3496 y Fi(4)81 b Fj(Return)21 b(the)i(name,)h(I/O)e(mo)s (de)g(\(READONL)-8 b(Y)24 b(or)e(READ)m(WRITE\),)i(and/or)e(the)g (\014le)h(t)m(yp)s(e)f(\(e.g.)40 b('\014le://',)227 3609 y('ftp://'\))32 b(of)f(the)f(op)s(ened)g(FITS)g(\014le.)95 3862 y Fe(int)47 b(fits_file_name)d(/)k(ffflnm)e(\(fitsfile)f(*fptr,)h (>)i(char)e(*filename,)f(int)i(*status\))95 4088 y(int)g (fits_file_mode)d(/)k(ffflmd)e(\(fitsfile)f(*fptr,)h(>)i(int)f (*iomode,)e(int)i(*status\))95 4313 y(int)g(fits_url_type)e(/)i(ffurlt) f(\(fitsfile)f(*fptr,)h(>)i(char)f(*urltype,)e(int)i(*status\))0 4646 y Ff(5.3)135 b(HDU)46 b(Access)e(Routines)0 4896 y Fj(The)30 b(follo)m(wing)i(functions)e(p)s(erform)f(op)s(erations)h (on)h(Header-Data)h(Units)f(\(HDUs\))h(as)e(a)h(whole.)0 5149 y Fi(1)81 b Fj(Mo)m(v)m(e)25 b(to)g(a)f(di\013eren)m(t)g(HDU)g(in) g(the)g(\014le.)38 b(The)23 b(\014rst)g(routine)h(mo)m(v)m(es)h(to)f(a) g(sp)s(eci\014ed)f(absolute)i(HDU)f(n)m(um)m(b)s(er)227 5262 y(\(starting)f(with)e(1)g(for)g(the)h(primary)e(arra)m(y\))i(in)f (the)h(FITS)e(\014le,)k(and)c(the)i(second)f(routine)h(mo)m(v)m(es)g(a) g(relativ)m(e)227 5375 y(n)m(um)m(b)s(er)30 b(HDUs)i(forw)m(ard)e(or)h (bac)m(kw)m(ard)h(from)e(the)i(curren)m(t)f(HDU.)h(A)f(n)m(ull)g(p)s (oin)m(ter)g(ma)m(y)h(b)s(e)e(giv)m(en)i(for)227 5488 y(the)26 b(hdut)m(yp)s(e)f(parameter)i(if)f(it's)g(v)-5 b(alue)27 b(is)f(not)g(needed.)39 b(The)26 b(third)f(routine)h(mo)m(v)m (es)h(to)g(the)f(\(\014rst\))g(HDU)227 5601 y(whic)m(h)38 b(has)g(the)g(sp)s(eci\014ed)f(extension)i(t)m(yp)s(e)f(and)f(EXTNAME)h (and)f(EXTVER)h(k)m(eyw)m(ord)g(v)-5 b(alues)39 b(\(or)227 5714 y(HDUNAME)e(and)e(HDUVER)h(k)m(eyw)m(ords\).)57 b(The)35 b(extname)h(parameter)g(ma)m(y)g(con)m(tain)h(wildcards,)g(as) p eop end %%Page: 36 44 TeXDict begin 36 43 bop 0 299 a Fj(36)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(accepted)k(b)m(y)f(\014ts)p 859 555 28 4 v 33 w(compare)p 1225 555 V 33 w(str\(\).)48 b(The)33 b(hdut)m(yp)s(e)e(parameter)i(ma)m(y)h(ha)m(v)m(e)g(a)f(v)-5 b(alue)33 b(of)g(IMA)m(GE)p 3640 555 V 34 w(HDU,)227 668 y(ASCI)s(I)p 486 668 V 32 w(TBL,)f(BINAR)-8 b(Y)p 1122 668 V 34 w(TBL,)32 b(or)h(ANY)p 1718 668 V 33 w(HDU)g(where)f(ANY) p 2458 668 V 33 w(HDU)i(means)e(that)h(only)g(the)f(extname)227 781 y(and)k(extv)m(er)h(v)-5 b(alues)36 b(will)g(b)s(e)f(used)g(to)i (lo)s(cate)h(the)e(correct)h(extension.)58 b(If)35 b(the)h(input)f(v)-5 b(alue)37 b(of)f(extv)m(er)227 894 y(is)d(0)g(then)f(the)g(EXTVER)h(k)m (eyw)m(ord)g(is)f(ignored)h(and)f(the)g(\014rst)g(HDU)h(with)f(a)h (matc)m(hing)h(EXTNAME)227 1007 y(\(or)i(HDUNAME\))h(k)m(eyw)m(ord)f (will)f(b)s(e)g(found.)55 b(If)34 b(no)i(matc)m(hing)g(HDU)g(is)g (found)e(in)h(the)g(\014le)h(then)f(the)227 1120 y(curren)m(t)30 b(HDU)i(will)e(remain)h(unc)m(hanged)f(and)f(a)i(status)g(=)f(BAD)p 2535 1120 V 34 w(HDU)p 2774 1120 V 33 w(NUM)h(will)g(b)s(e)f(returned.) 95 1398 y Fe(int)47 b(fits_movabs_hdu)d(/)j(ffmahd)286 1511 y(\(fitsfile)f(*fptr,)g(int)h(hdunum,)e(>)j(int)f(*hdutype,)e(int) i(*status\))95 1736 y(int)g(fits_movrel_hdu)d(/)j(ffmrhd)286 1849 y(\(fitsfile)f(*fptr,)g(int)h(nmove,)f(>)h(int)g(*hdutype,)e(int)i (*status\))95 2075 y(int)g(fits_movnam_hdu)d(/)j(ffmnhd)286 2188 y(\(fitsfile)f(*fptr,)g(int)h(hdutype,)e(char)i(*extname,)e(int)i (extver,)f(>)h(int)g(*status\))0 2466 y Fi(2)81 b Fj(Return)38 b(the)i(total)h(n)m(um)m(b)s(er)d(of)i(HDUs)g(in)f(the)h(FITS)f (\014le.)68 b(This)39 b(returns)f(the)h(n)m(um)m(b)s(er)g(of)g (completely)227 2579 y(de\014ned)30 b(HDUs)h(in)f(the)h(\014le.)42 b(If)30 b(a)h(new)f(HDU)h(has)g(just)f(b)s(een)g(added)f(to)j(the)f (FITS)f(\014le,)h(then)f(that)h(last)227 2692 y(HDU)f(will)f(only)g(b)s (e)g(coun)m(ted)g(if)g(it)h(has)e(b)s(een)h(closed,)h(or)f(if)g(data)h (has)e(b)s(een)h(written)g(to)g(the)g(HDU.)h(The)227 2805 y(curren)m(t)g(HDU)i(remains)e(unc)m(hanged)g(b)m(y)g(this)g (routine.)95 3082 y Fe(int)47 b(fits_get_num_hdus)c(/)48 b(ffthdu)286 3195 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*hdunum,)f(int)h (*status\))0 3473 y Fi(3)81 b Fj(Return)31 b(the)h(n)m(um)m(b)s(er)f (of)h(the)h(curren)m(t)e(HDU)i(\(CHDU\))h(in)d(the)i(FITS)e(\014le)h (\(where)g(the)g(primary)g(arra)m(y)g(=)227 3586 y(1\).)42 b(This)29 b(function)h(returns)g(the)g(HDU)h(n)m(um)m(b)s(er)e(rather)h (than)h(a)f(status)h(v)-5 b(alue.)95 3864 y Fe(int)47 b(fits_get_hdu_num)d(/)j(ffghdn)286 3977 y(\(fitsfile)f(*fptr,)g(>)h (int)g(*hdunum\))0 4255 y Fi(4)81 b Fj(Return)38 b(the)h(t)m(yp)s(e)h (of)f(the)h(curren)m(t)f(HDU)h(in)f(the)g(FITS)g(\014le.)67 b(The)39 b(p)s(ossible)g(v)-5 b(alues)39 b(for)g(hdut)m(yp)s(e)f(are:) 227 4368 y(IMA)m(GE)p 546 4368 V 34 w(HDU,)31 b(ASCI)s(I)p 1095 4368 V 32 w(TBL,)f(or)g(BINAR)-8 b(Y)p 1840 4368 V 34 w(TBL.)95 4646 y Fe(int)47 b(fits_get_hdu_type)c(/)48 b(ffghdt)286 4759 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*hdutype,)e(int)i (*status\))0 5036 y Fi(5)81 b Fj(Cop)m(y)24 b(all)h(or)f(part)g(of)g (the)g(HDUs)h(in)f(the)g(FITS)g(\014le)g(asso)s(ciated)h(with)f(infptr) f(and)h(app)s(end)e(them)i(to)h(the)g(end)227 5149 y(of)f(the)f(FITS)f (\014le)i(asso)s(ciated)g(with)f(outfptr.)38 b(If)23 b('previous')g(is)g(true)g(\(not)h(0\),)i(then)d(an)m(y)g(HDUs)h (preceding)227 5262 y(the)35 b(curren)m(t)f(HDU)g(in)g(the)h(input)e (\014le)h(will)h(b)s(e)e(copied)i(to)g(the)f(output)g(\014le.)52 b(Similarly)-8 b(,)36 b('curren)m(t')f(and)227 5375 y('follo)m(wing')c (determine)e(whether)f(the)h(curren)m(t)g(HDU,)g(and/or)g(an)m(y)g (follo)m(wing)h(HDUs)g(in)e(the)h(input)f(\014le)227 5488 y(will)i(b)s(e)f(copied)i(to)f(the)g(output)f(\014le.)41 b(Th)m(us,)29 b(if)g(all)i(3)f(parameters)g(are)g(true,)g(then)g(the)f (en)m(tire)i(input)e(\014le)227 5601 y(will)36 b(b)s(e)e(copied.)56 b(On)35 b(exit,)i(the)f(curren)m(t)f(HDU)h(in)e(the)i(input)e(\014le)i (will)f(b)s(e)g(unc)m(hanged,)h(and)f(the)g(last)227 5714 y(HDU)c(in)f(the)h(output)f(\014le)g(will)h(b)s(e)f(the)g(curren)m (t)h(HDU.)p eop end %%Page: 37 45 TeXDict begin 37 44 bop 0 299 a Fh(5.4.)72 b(HEADER)31 b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(37)95 555 y Fe(int)47 b(fits_copy_file)d(/)k(ffcpfl)286 668 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(previous,)e(int) i(current,)477 781 y(int)g(following,)e(>)j(int)f(*status\))0 1042 y Fi(6)81 b Fj(Cop)m(y)34 b(the)h(curren)m(t)f(HDU)h(from)f(the)g (FITS)g(\014le)h(asso)s(ciated)g(with)g(infptr)e(and)h(app)s(end)e(it)j (to)g(the)g(end)f(of)227 1155 y(the)39 b(FITS)e(\014le)h(asso)s(ciated) i(with)e(outfptr.)64 b(Space)38 b(ma)m(y)h(b)s(e)e(reserv)m(ed)i(for)f (MOREKEYS)f(additional)227 1268 y(k)m(eyw)m(ords)31 b(in)f(the)h (output)f(header.)95 1529 y Fe(int)47 b(fits_copy_hdu)e(/)i(ffcopy)286 1642 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(morekeys,)e (>)j(int)f(*status\))0 1903 y Fi(7)81 b Fj(W)-8 b(rite)31 b(the)g(curren)m(t)f(HDU)h(in)f(the)h(input)e(FITS)h(\014le)g(to)h(the) g(output)f(FILE)g(stream)h(\(e.g.,)h(to)f(stdout\).)95 2164 y Fe(int)47 b(fits_write_hdu)d(/)k(ffwrhdu)286 2277 y(\(fitsfile)e(*infptr,)f(FILE)i(*stream,)e(>)j(int)f(*status\))0 2538 y Fi(8)81 b Fj(Cop)m(y)43 b(the)h(header)g(\(and)f(not)h(the)g (data\))h(from)e(the)h(CHDU)g(asso)s(ciated)h(with)f(infptr)e(to)j(the) f(CHDU)227 2651 y(asso)s(ciated)28 b(with)e(outfptr.)39 b(If)26 b(the)h(curren)m(t)f(output)g(HDU)h(is)g(not)f(completely)i (empt)m(y)-8 b(,)29 b(then)d(the)h(CHDU)227 2764 y(will)35 b(b)s(e)f(closed)h(and)f(a)h(new)f(HDU)h(will)g(b)s(e)f(app)s(ended)e (to)j(the)g(output)f(\014le.)53 b(An)34 b(empt)m(y)h(output)f(data)227 2877 y(unit)c(will)h(b)s(e)f(created)h(with)f(all)h(v)-5 b(alues)31 b(initially)h(=)e(0\).)95 3138 y Fe(int)47 b(fits_copy_header)d(/)j(ffcphd)286 3251 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(>)i(int)g(*status\))0 3512 y Fi(9)81 b Fj(Delete)35 b(the)e(CHDU)h(in)f(the)g(FITS)f(\014le.)50 b(An)m(y)33 b(follo)m(wing)i(HDUs)e(will)h(b)s(e)e(shifted)h(forw)m (ard)g(in)g(the)g(\014le,)h(to)227 3625 y(\014ll)k(in)f(the)g(gap)h (created)g(b)m(y)g(the)f(deleted)h(HDU.)h(In)d(the)i(case)g(of)g (deleting)g(the)g(primary)e(arra)m(y)i(\(the)227 3738 y(\014rst)30 b(HDU)h(in)f(the)h(\014le\))g(then)f(the)h(curren)m(t)f (primary)f(arra)m(y)i(will)g(b)s(e)f(replace)h(b)m(y)g(a)g(n)m(ull)f (primary)f(arra)m(y)227 3851 y(con)m(taining)k(the)f(minim)m(um)e(set)i (of)g(required)e(k)m(eyw)m(ords)i(and)e(no)i(data.)44 b(If)31 b(there)g(are)h(more)f(extensions)227 3964 y(in)f(the)g(\014le) g(follo)m(wing)i(the)e(one)g(that)h(is)f(deleted,)h(then)f(the)g(the)g (CHDU)h(will)f(b)s(e)g(rede\014ned)e(to)j(p)s(oin)m(t)f(to)227 4077 y(the)d(follo)m(wing)h(extension.)41 b(If)26 b(there)h(are)g(no)g (follo)m(wing)h(extensions)f(then)g(the)g(CHDU)g(will)g(b)s(e)f (rede\014ned)227 4190 y(to)36 b(p)s(oin)m(t)f(to)g(the)g(previous)f (HDU.)i(The)e(output)h(hdut)m(yp)s(e)e(parameter)i(returns)f(the)h(t)m (yp)s(e)g(of)f(the)h(new)227 4302 y(CHDU.)c(A)g(n)m(ull)f(p)s(oin)m (ter)g(ma)m(y)h(b)s(e)f(giv)m(en)i(for)e(hdut)m(yp)s(e)f(if)h(the)h (returned)e(v)-5 b(alue)31 b(is)f(not)h(needed.)95 4564 y Fe(int)47 b(fits_delete_hdu)d(/)j(ffdhdu)286 4676 y(\(fitsfile)f (*fptr,)g(>)h(int)g(*hdutype,)e(int)i(*status\))0 5012 y Ff(5.4)135 b(Header)46 b(Keyw)l(ord)g(Read/W)-11 b(rite)46 b(Routines)0 5262 y Fj(These)35 b(routines)g(read)f(or)h(write)h(k)m (eyw)m(ords)f(in)g(the)g(Curren)m(t)f(Header)h(Unit)g(\(CHU\).)h(Wild)g (card)e(c)m(haracters)0 5375 y(\(*,)28 b(?,)g(or)e(#\))h(ma)m(y)g(b)s (e)f(used)g(when)f(sp)s(ecifying)i(the)g(name)f(of)h(the)g(k)m(eyw)m (ord)g(to)g(b)s(e)f(read:)39 b(a)27 b(')10 b(?')39 b(will)27 b(matc)m(h)h(an)m(y)0 5488 y(single)35 b(c)m(haracter)g(at)g(that)f(p)s (osition)g(in)g(the)g(k)m(eyw)m(ord)h(name)f(and)f(a)h('*')h(will)g (matc)m(h)f(an)m(y)h(length)f(\(including)0 5601 y(zero\))c(string)f (of)g(c)m(haracters.)42 b(The)28 b('#')h(c)m(haracter)i(will)e(matc)m (h)h(an)m(y)f(consecutiv)m(e)i(string)e(of)g(decimal)h(digits)f(\(0)0 5714 y(-)35 b(9\).)55 b(When)35 b(a)g(wild)g(card)g(is)g(used)f(the)h (routine)g(will)g(only)g(searc)m(h)h(for)f(a)g(matc)m(h)h(from)e(the)h (curren)m(t)g(header)p eop end %%Page: 38 46 TeXDict begin 38 45 bop 0 299 a Fj(38)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(p)s(osition)d(to)h(the)f(end)f(of)h(the)g (header)g(and)f(will)h(not)g(resume)g(the)g(searc)m(h)g(from)g(the)g (top)g(of)g(the)g(header)g(bac)m(k)g(to)0 668 y(the)k(original)i (header)e(p)s(osition)g(as)h(is)f(done)g(when)f(no)h(wildcards)g(are)h (included)e(in)h(the)g(k)m(eyw)m(ord)h(name.)43 b(The)0 781 y(\014ts)p 127 781 28 4 v 32 w(read)p 331 781 V 33 w(record)29 b(routine)h(ma)m(y)g(b)s(e)f(used)f(to)i(set)g(the)g (starting)g(p)s(osition)f(when)g(doing)g(wild)g(card)h(searc)m(hes.)41 b(A)0 894 y(status)29 b(v)-5 b(alue)30 b(of)f(KEY)p 809 894 V 32 w(NO)p 980 894 V 33 w(EXIST)f(is)h(returned)e(if)i(the)g(sp)s (eci\014ed)f(k)m(eyw)m(ord)i(to)f(b)s(e)g(read)f(is)h(not)h(found)d(in) i(the)0 1007 y(header.)0 1291 y Fd(5.4.1)112 b(Keyw)m(ord)38 b(Reading)g(Routines)0 1493 y Fi(1)81 b Fj(Return)33 b(the)h(n)m(um)m(b)s(er)e(of)i(existing)h(k)m(eyw)m(ords)g(\(not)f (coun)m(ting)h(the)f(END)g(k)m(eyw)m(ord\))h(and)e(the)h(amoun)m(t)h (of)227 1606 y(space)e(curren)m(tly)f(a)m(v)-5 b(ailable)34 b(for)e(more)g(k)m(eyw)m(ords.)46 b(It)32 b(returns)e(morek)m(eys)j(=)f (-1)g(if)g(the)g(header)g(has)g(not)227 1719 y(y)m(et)27 b(b)s(een)d(closed.)40 b(Note)26 b(that)g(CFITSIO)d(will)j(dynamically) g(add)e(space)i(if)f(required)f(when)g(writing)h(new)227 1832 y(k)m(eyw)m(ords)32 b(to)g(a)f(header)g(so)h(in)f(practice)h (there)g(is)f(no)g(limit)h(to)g(the)f(n)m(um)m(b)s(er)f(of)i(k)m(eyw)m (ords)f(that)h(can)g(b)s(e)227 1945 y(added)e(to)h(a)f(header.)41 b(A)30 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(en)m(tered)h(for)f (the)g(morek)m(eys)h(parameter)g(if)f(it's)h(v)-5 b(alue)31 b(is)227 2058 y(not)g(needed.)95 2278 y Fe(int)47 b(fits_get_hdrspace)c (/)48 b(ffghsp)286 2391 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*keysexist,)e (int)i(*morekeys,)e(int)i(*status\))0 2610 y Fi(2)81 b Fj(Return)28 b(the)h(sp)s(eci\014ed)f(k)m(eyw)m(ord.)41 b(In)29 b(the)g(\014rst)f(routine,)i(the)f(datat)m(yp)s(e)h(parameter)g (sp)s(eci\014es)e(the)h(desired)227 2723 y(returned)e(data)h(t)m(yp)s (e)g(of)g(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)28 b(and)f(can)h(ha)m(v)m (e)h(one)f(of)g(the)g(follo)m(wing)h(sym)m(b)s(olic)g(constan)m(t)227 2836 y(v)-5 b(alues:)47 b(TSTRING,)33 b(TLOGICAL)f(\(==)h(in)m(t\),)j (TBYTE,)d(TSHOR)-8 b(T,)33 b(TUSHOR)-8 b(T,)32 b(TINT,)h(TUINT,)227 2949 y(TLONG,)24 b(TULONG,)g(TLONGLONG,)g(TFLO)m(A)-8 b(T,)25 b(TDOUBLE,)f(TCOMPLEX,)f(and)h(TDBLCOM-)227 3062 y(PLEX.)j(Within)f(the)h(con)m(text)h(of)f(this)g(routine,)g(TSTRING)f (corresp)s(onds)f(to)i(a)g('c)m(har*')h(data)f(t)m(yp)s(e,)h(i.e.,)227 3175 y(a)k(p)s(oin)m(ter)g(to)g(a)g(c)m(haracter)i(arra)m(y)-8 b(.)45 b(Data)33 b(t)m(yp)s(e)f(con)m(v)m(ersion)h(will)f(b)s(e)f(p)s (erformed)f(for)i(n)m(umeric)f(v)-5 b(alues)32 b(if)227 3288 y(the)27 b(k)m(eyw)m(ord)g(v)-5 b(alue)27 b(do)s(es)f(not)h(ha)m (v)m(e)h(the)f(same)g(data)g(t)m(yp)s(e.)40 b(If)26 b(the)h(v)-5 b(alue)27 b(of)g(the)f(k)m(eyw)m(ord)i(is)e(unde\014ned)227 3401 y(\(i.e.,)31 b(the)e(v)-5 b(alue)30 b(\014eld)e(is)h(blank\))g (then)f(an)h(error)g(status)g(=)f(V)-10 b(ALUE)p 2627 3401 V 33 w(UNDEFINED)30 b(will)g(b)s(e)e(returned.)227 3544 y(The)c(second)f(routine)h(returns)f(the)h(k)m(eyw)m(ord)g(v)-5 b(alue)24 b(as)g(a)g(c)m(haracter)i(string)d(\(a)i(literal)g(cop)m(y)g (of)f(what)f(is)h(in)227 3657 y(the)j(v)-5 b(alue)26 b(\014eld\))g(regardless)h(of)f(the)g(in)m(trinsic)h(data)g(t)m(yp)s(e) f(of)g(the)g(k)m(eyw)m(ord.)40 b(The)26 b(third)f(routine)h(returns)227 3770 y(the)45 b(en)m(tire)h(80-c)m(haracter)i(header)c(record)h(of)g (the)g(k)m(eyw)m(ord,)k(with)c(an)m(y)g(trailing)h(blank)e(c)m (haracters)227 3883 y(stripp)s(ed)37 b(o\013.)64 b(The)38 b(fourth)f(routine)h(returns)f(the)h(\(next\))h(header)f(record)g(that) h(con)m(tains)g(the)f(literal)227 3996 y(string)31 b(of)f(c)m (haracters)i(sp)s(eci\014ed)e(b)m(y)g(the)g('string')h(argumen)m(t.)227 4139 y(If)f(a)h(NULL)f(commen)m(t)i(p)s(oin)m(ter)e(is)g(supplied)g (then)g(the)g(commen)m(t)i(string)e(will)h(not)f(b)s(e)g(returned.)95 4359 y Fe(int)47 b(fits_read_key)e(/)i(ffgky)286 4472 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(>)i(DTYPE) g(*value,)334 4585 y(char)g(*comment,)e(int)i(*status\))95 4811 y(int)g(fits_read_keyword)c(/)48 b(ffgkey)286 4924 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(*value,)f(char)g (*comment,)334 5036 y(int)h(*status\))95 5262 y(int)g(fits_read_card)d (/)k(ffgcrd)286 5375 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h (char)g(*card,)f(int)h(*status\))95 5601 y(int)g(fits_read_str)e(/)i (ffgstr)286 5714 y(\(fitsfile)f(*fptr,)g(char)g(*string,)g(>)h(char)g (*card,)f(int)h(*status\))p eop end %%Page: 39 47 TeXDict begin 39 46 bop 0 299 a Fh(5.4.)72 b(HEADER)31 b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(39)0 555 y Fi(3)81 b Fj(Read)29 b(a)g(string-v)-5 b(alued)29 b(k)m(eyw)m(ord)h(and)e(return)g(the)h(string)g(length,)h(the)f(v)-5 b(alue)29 b(string,)g(and/or)g(the)g(comm-)227 668 y(men)m(t)34 b(length)g(and)f(commen)m(t)i(\014eld.)50 b(These)33 b(routines)h(supp)s(ort)d(the)j(reading)g(of)g(long)g(string)f(k)m(eyw) m(ord)227 781 y(v)-5 b(alues)42 b(of)f(arbitrary)f(length)i(whic)m(h)e (use)h(the)g(CONTINUE)f(con)m(v)m(en)m(tion.)75 b(The)40 b(\014rst)h(t)m(w)m(o)h(routines,)227 894 y(\013gk)m(csl)30 b(and)f(\013gskyc)g(are)g(the)g(new)m(er)g(v)m(ersions)g(of)g(the)g (second)g(t)m(w)m(o.)41 b(They)29 b(pro)m(vide)g(all)g(the)g (functional-)227 1007 y(it)m(y)35 b(of)f(the)g(older)g(routines,)h(but) e(ha)m(v)m(e)i(the)f(added)f(capabilit)m(y)j(of)e(returning)f(the)h (length)g(of)g(commen)m(t)227 1120 y(strings)28 b(\(if)g(an)m(y\),)i (and)d(reading)i(m)m(ulti-line)g(commen)m(t)g(strings)f(of)g(arbitrary) g(length.)40 b(They)28 b(are)g(recom-)227 1233 y(mended)i(for)g(use)g (in)g(the)g(future.)40 b(\013gksl)31 b(and)f(\013gsky)h(are)f(main)m (tained)i(for)e(bac)m(kw)m(ards-compatibilit)m(y)-8 b(.)227 1384 y(The)22 b(\014rst)g(routine,)j(\013gk)m(csl,)h(simply)c(returns)f (the)i(lengths)g(of)g(the)g(c)m(haracter)h(string)f(v)-5 b(alue)23 b(and)f(commen)m(t)227 1497 y(string)32 b(\(if)g(an)m(y\))g (of)g(the)g(sp)s(eci\014ed)f(k)m(eyw)m(ord.)45 b(These)32 b(lengths)g(are)g(particularly)g(helpful)f(for)h(allo)s(cating)227 1610 y(dynamic)26 b(memory)g(when)f(retrieving)i(the)f(strings)g(in)g (the)g(\013gskyc)g(function.)39 b(T)-8 b(o)27 b(create)g(an)f(arra)m(y) h(large)227 1723 y(enough)g(to)g(hold)f(the)h(full)f(string,)i(one)f (should)e(allo)s(cate)k(a)e(size)h(equal)f(to)g(the)g(returned)f (length)h(+)f(1)h(\(for)227 1836 y(the)k(trailing)g(NULL\).)227 1988 y(The)k(second)f(routine,)j(\013gskyc,)g(is)d(for)h(retrieving)h (the)f(v)-5 b(alue)35 b(string)g(and)f(optional)i(commen)m(t)g(string,) 227 2101 y(b)s(oth)28 b(of)g(whic)m(h)h(ma)m(y)g(b)s(e)e(of)i (arbitrary)f(length)h(spreading)f(o)m(v)m(er)h(m)m(ultiple)g(lines)g (with)f(the)h(CONTINUE)227 2214 y(k)m(eyw)m(ord)39 b(con)m(v)m(en)m (tion.)68 b(It)39 b(will)g(return)e(up)h(to)h(maxc)m(har)h(c)m (haracters)g(of)f(the)f(k)m(eyw)m(ord)i(v)-5 b(alue)39 b(string,)227 2327 y(starting)31 b(with)f(the)h(\014rstc)m(har)f(c)m (haracter.)42 b(Similarly)-8 b(,)32 b(maxcomc)m(har)f(determines)g(the) f(maxim)m(um)g(n)m(um-)227 2440 y(b)s(er)39 b(of)g(c)m(haracters)i(to)f (return)f(for)g(the)h(commen)m(t)g(string.)68 b(\(The)39 b(v)-5 b(aluelen)41 b(and)d(comlen)j(argumen)m(ts)227 2552 y(return)34 b(the)i(total)g(length)g(of)f(their)g(resp)s(ectiv)m (e)h(strings)f(regardless)h(of)f(what)g(is)g(actually)i(returned)d(as) 227 2665 y(determined)22 b(from)g(the)h(\014rstc)m(har)f(and)g (max\(com\)c)m(har)j(argumen)m(ts.\))38 b(If)22 b(NULL)h(is)f(passed)g (for)h(either)g(the)227 2778 y(v)-5 b(alue)32 b(or)e(comm)i(string)e(p) s(oin)m(ter,)i(its)f(max\(com\)c)m(har)i(setting)f(is)f(irrelev)-5 b(an)m(t)32 b(since)f(the)g(corresp)s(onding)227 2891 y(string)g(will)f(not)h(b)s(e)f(returned.)227 3043 y(The)g(\013gksl)h (routine)f(is)g(the)h(earlier)g(v)m(ersion)g(of)f(\013gk)m(csl.)42 b(It)31 b(only)f(returns)f(the)i(v)-5 b(alue)31 b(string)f(length)h (and)227 3156 y(not)22 b(the)g(commen)m(t)h(string)f(length.)38 b(\013gsky)-8 b(,)25 b(the)d(earlier)g(v)m(ersion)h(of)f(\013gskyc,)i (do)s(es)e(return)e(b)s(oth)h(the)h(v)-5 b(alue)227 3269 y(string)31 b(and)f(commen)m(t)i(string.)42 b(Ho)m(w)m(ev)m(er)33 b(it)e(will)g(only)g(return)e(up)h(to)i(the)f(\014rst)f(FLEN)p 3298 3269 28 4 v 33 w(COMMENT-1)227 3382 y(c)m(haracters)j(of)e(the)g (commen)m(t.)44 b(It)32 b(can)f(read)g(commen)m(ts)h(across)g(m)m (ultiple)f(lines,)h(but)f(not)g(of)g(arbitrary)227 3495 y(length.)95 3757 y Fe(int)47 b(fits_get_key_com_strlen)42 b(/)47 b(ffgkcsl)286 3870 y(\(fitsfile)f(*fptr,)g(const)g(char)h (*keyname,)e(int)i(*length,)e(int)i(*comlength,)286 3983 y(int)g(*status\);)95 4209 y(int)g(fits_read_string_key_com)42 b(/)47 b(ffgskyc)286 4322 y(\(fitsfile)f(*fptr,)g(const)g(char)h (*keyname,)e(int)i(firstchar,)e(int)i(maxchar,)286 4435 y(int)g(maxcomchar,)e(char)i(*value,)e(int)i(*valuelen,)e(char)i (*comm,)286 4548 y(int)g(*comlen,)f(int)h(*status\);)95 4774 y(int)g(fits_get_key_strlen)c(/)k(ffgksl)286 4887 y(\(fitsfile)f(*fptr,)g(const)g(char)h(*keyname,)e(int)i(*length,)e (int)i(*status\);)95 5112 y(int)g(fits_read_string_key)c(/)k(ffgsky)334 5225 y(\(fitsfile)e(*fptr,)h(const)h(char)f(*keyname,)g(int)h (firstchar,)e(int)i(maxchar,)334 5338 y(char)g(*value,)f(int)g (*valuelen,)f(char)i(*comm,)f(int)h(*status\);)0 5601 y Fi(4)81 b Fj(Return)38 b(the)h(n)m(th)f(header)h(record)g(in)f(the)i (CHU.)f(The)f(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g(at)g (k)m(eyn)m(um)g(=)227 5714 y(1;)53 b(if)45 b(k)m(eyn)m(um)g(=)f(0)h (then)g(these)g(routines)g(simply)f(reset)h(the)h(in)m(ternal)f (CFITSIO)e(p)s(oin)m(ter)i(to)h(the)p eop end %%Page: 40 48 TeXDict begin 40 47 bop 0 299 a Fj(40)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(b)s(eginning)35 b(of)h(the)g(header)f(so)h (that)g(subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g (at)g(the)g(top)g(of)g(the)227 668 y(header)26 b(\(e.g.,)j(prior)c(to)h (searc)m(hing)h(for)f(k)m(eyw)m(ords)g(using)f(wild)g(cards)h(in)f(the) h(k)m(eyw)m(ord)h(name\).)39 b(The)26 b(\014rst)227 781 y(routine)32 b(returns)e(the)i(en)m(tire)h(80-c)m(haracter)h(header)e (record)g(\(with)f(trailing)i(blanks)e(truncated\),)i(while)227 894 y(the)41 b(second)f(routine)g(parses)g(the)g(record)h(and)e (returns)g(the)i(name,)i(v)-5 b(alue,)43 b(and)d(commen)m(t)h(\014elds) f(as)227 1007 y(separate)32 b(\(blank)f(truncated\))g(c)m(haracter)i (strings.)42 b(If)30 b(a)h(NULL)g(commen)m(t)h(p)s(oin)m(ter)f(is)g (giv)m(en)h(on)f(input,)227 1120 y(then)f(the)h(commen)m(t)g(string)g (will)f(not)h(b)s(e)f(returned.)95 1396 y Fe(int)47 b(fits_read_record) d(/)j(ffgrec)286 1509 y(\(fitsfile)f(*fptr,)g(int)h(keynum,)e(>)j(char) f(*card,)f(int)h(*status\))95 1735 y(int)g(fits_read_keyn)d(/)k(ffgkyn) 286 1848 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(>)j(char)f(*keyname,)e (char)h(*value,)334 1961 y(char)h(*comment,)e(int)i(*status\))0 2237 y Fi(5)81 b Fj(Return)44 b(the)i(next)g(k)m(eyw)m(ord)g(whose)f (name)h(matc)m(hes)g(one)g(of)g(the)f(strings)h(in)f('inclist')i(but)e (do)s(es)g(not)227 2350 y(matc)m(h)31 b(an)m(y)g(of)g(the)f(strings)g (in)g('exclist'.)43 b(The)30 b(strings)g(in)g(inclist)h(and)f(exclist)i (ma)m(y)e(con)m(tain)i(wild)e(card)227 2463 y(c)m(haracters)k(\(*,)f (?,)f(and)f(#\))h(as)g(describ)s(ed)f(at)i(the)f(b)s(eginning)f(of)h (this)g(section.)46 b(This)31 b(routine)h(searc)m(hes)227 2576 y(from)j(the)g(curren)m(t)g(header)g(p)s(osition)g(to)h(the)f(end) f(of)h(the)h(header,)g(only)-8 b(,)37 b(and)d(do)s(es)h(not)g(con)m (tin)m(ue)i(the)227 2689 y(searc)m(h)32 b(from)e(the)h(top)g(of)g(the)g (header)g(bac)m(k)g(to)h(the)f(original)h(p)s(osition.)42 b(The)31 b(curren)m(t)f(header)h(p)s(osition)227 2802 y(ma)m(y)e(b)s(e)e(reset)h(with)g(the)g(\013grec)g(routine.)40 b(Note)29 b(that)g(nexc)f(ma)m(y)g(b)s(e)f(set)h(=)g(0)g(if)g(there)g (are)g(no)g(k)m(eyw)m(ords)227 2915 y(to)h(b)s(e)f(excluded.)39 b(This)28 b(routine)g(returns)f(status)h(=)g(KEY)p 2268 2915 28 4 v 32 w(NO)p 2439 2915 V 33 w(EXIST)f(if)h(a)h(matc)m(hing)g (k)m(eyw)m(ord)g(is)f(not)227 3027 y(found.)95 3304 y Fe(int)47 b(fits_find_nextkey)c(/)48 b(ffgnxk)286 3417 y(\(fitsfile)e(*fptr,)g(char)g(**inclist,)f(int)i(ninc,)g(char)f (**exclist,)334 3530 y(int)h(nexc,)f(>)i(char)e(*card,)h(int)94 b(*status\))0 3806 y Fi(6)81 b Fj(Return)25 b(the)h(ph)m(ysical)g (units)g(string)g(from)f(an)h(existing)h(k)m(eyw)m(ord.)39 b(This)26 b(routine)g(uses)f(a)h(lo)s(cal)i(con)m(v)m(en)m(tion,)227 3919 y(sho)m(wn)d(in)g(the)g(follo)m(wing)i(example,)g(in)e(whic)m(h)g (the)h(k)m(eyw)m(ord)f(units)g(are)h(enclosed)g(in)f(square)g(brac)m(k) m(ets)h(in)227 4032 y(the)k(b)s(eginning)f(of)h(the)g(k)m(eyw)m(ord)g (commen)m(t)g(\014eld.)40 b(A)30 b(n)m(ull)g(string)f(is)h(returned)e (if)i(no)f(units)g(are)h(de\014ned)227 4145 y(for)g(the)h(k)m(eyw)m (ord.)239 4421 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g (speed)95 4647 y(int)h(fits_read_key_unit)c(/)48 b(ffgunt)286 4760 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(*unit,)f (int)h(*status\))0 5036 y Fi(7)81 b Fj(Concatenate)39 b(the)f(header)f(k)m(eyw)m(ords)h(in)g(the)f(CHDU)h(in)m(to)h(a)f (single)g(long)g(string)g(of)g(c)m(haracters.)64 b(This)227 5149 y(pro)m(vides)28 b(a)h(con)m(v)m(enien)m(t)h(w)m(a)m(y)f(of)g (passing)f(all)h(or)f(part)g(of)g(the)h(header)f(information)g(in)g(a)h (FITS)e(HDU)i(to)227 5262 y(other)i(subroutines.)39 b(Eac)m(h)31 b(80-c)m(haracter)h(\014xed-length)f(k)m(eyw)m(ord)f(record)g(is)g(app) s(ended)e(to)j(the)f(output)227 5375 y(c)m(haracter)j(string,)f(in)f (order,)g(with)g(no)g(in)m(terv)m(ening)i(separator)f(or)f(terminating) h(c)m(haracters.)45 b(The)31 b(last)227 5488 y(header)e(record)g(is)g (terminated)h(with)f(a)g(NULL)g(c)m(haracter.)42 b(These)29 b(routine)g(allo)s(cates)j(memory)d(for)g(the)227 5601 y(returned)k(c)m(haracter)j(arra)m(y)-8 b(,)37 b(so)d(the)h(calling)h (program)e(m)m(ust)g(free)g(the)h(memory)f(when)f(\014nished.)51 b(The)227 5714 y(cleanest)32 b(w)m(a)m(y)g(to)f(do)f(this)g(is)h(to)g (call)g(the)g(\014ts)p 1823 5714 V 32 w(free)p 1999 5714 V 33 w(memory)g(routine.)p eop end %%Page: 41 49 TeXDict begin 41 48 bop 0 299 a Fh(5.4.)72 b(HEADER)31 b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(41)227 555 y(There)38 b(are)h(2)g(related)g(routines:)57 b(\014ts)p 1581 555 28 4 v 32 w(hdr2str)37 b(simply)h(concatenates)j(all)f(the)e (existing)i(k)m(eyw)m(ords)e(in)227 668 y(the)44 b(header;)51 b(\014ts)p 863 668 V 33 w(con)m(v)m(ert)p 1185 668 V 34 w(hdr2str)43 b(is)h(similar,)k(except)d(that)f(if)g(the)g(CHDU)h(is) f(a)g(tile)h(compressed)227 781 y(image)c(\(stored)f(in)f(a)h(binary)e (table\))j(then)e(it)h(will)f(\014rst)g(con)m(v)m(ert)i(that)f(header)f (bac)m(k)h(to)g(that)g(of)g(the)227 894 y(corresp)s(onding)30 b(normal)g(FITS)g(image)h(b)s(efore)f(concatenating)j(the)e(k)m(eyw)m (ords.)227 1038 y(Selected)f(k)m(eyw)m(ords)e(ma)m(y)h(b)s(e)e (excluded)h(from)g(the)g(returned)f(c)m(haracter)j(string.)40 b(If)27 b(the)i(second)f(param-)227 1150 y(eter)h(\(no)s(commen)m(ts\)) g(is)f(TR)m(UE)g(\(nonzero\))h(then)e(an)m(y)i(COMMENT,)f(HISTOR)-8 b(Y,)27 b(or)h(blank)g(k)m(eyw)m(ords)227 1263 y(in)i(the)h(header)f (will)h(not)f(b)s(e)g(copied)h(to)g(the)g(output)f(string.)227 1407 y(The)25 b('exclist')j(parameter)e(ma)m(y)g(b)s(e)f(used)g(to)h (supply)e(a)i(list)h(of)e(k)m(eyw)m(ords)h(that)h(are)f(to)g(b)s(e)f (excluded)g(from)227 1520 y(the)k(output)g(c)m(haracter)h(string.)41 b(Wild)29 b(card)g(c)m(haracters)h(\(*,)g(?,)f(and)g(#\))g(ma)m(y)g(b)s (e)f(used)g(in)h(the)g(excluded)227 1633 y(k)m(eyw)m(ord)h(names.)41 b(If)29 b(no)g(additional)i(k)m(eyw)m(ords)f(are)g(to)g(b)s(e)f (excluded,)h(then)f(set)h(nexc)g(=)f(0)h(and)f(sp)s(ecify)227 1746 y(NULL)i(for)f(the)g(the)h(**exclist)i(parameter.)95 1965 y Fe(int)47 b(fits_hdr2str)e(/)i(ffhdr2str)286 2078 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e(int)i (nexc,)286 2191 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i (*status\))95 2417 y(int)g(fits_convert_hdr2str)c(/)k(ffcnvthdr2str)286 2530 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e (int)i(nexc,)286 2643 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i (*status\))95 2869 y(int)g(fits_free_memory)d(/)j(fffree)286 2981 y(\(char)g(*header,)e(>)j(int)f(*status\);)0 3379 y Fd(5.4.2)112 b(Keyw)m(ord)38 b(W)-9 b(riting)37 b(Routines)0 3581 y Fi(1)81 b Fj(W)-8 b(rite)32 b(a)g(k)m(eyw)m(ord)g(of)f(the)h (appropriate)f(data)h(t)m(yp)s(e)g(in)m(to)g(the)g(CHU.)f(The)g (\014rst)g(routine)g(simply)g(app)s(ends)227 3694 y(a)j(new)f(k)m(eyw)m (ord)h(whereas)f(the)g(second)h(routine)f(will)h(up)s(date)e(the)i(v)-5 b(alue)33 b(and)g(commen)m(t)h(\014elds)f(of)h(the)227 3807 y(k)m(eyw)m(ord)g(if)g(it)g(already)g(exists,)h(otherwise)f(it)g (app)s(ends)e(a)i(new)f(k)m(eyw)m(ord.)51 b(Note)35 b(that)f(the)g (address)e(to)227 3920 y(the)37 b(v)-5 b(alue,)38 b(and)d(not)i(the)f (v)-5 b(alue)36 b(itself,)j(m)m(ust)d(b)s(e)f(en)m(tered.)59 b(The)35 b(datat)m(yp)s(e)i(parameter)g(sp)s(eci\014es)f(the)227 4033 y(data)25 b(t)m(yp)s(e)f(of)g(the)g(k)m(eyw)m(ord)g(v)-5 b(alue)25 b(with)e(one)h(of)g(the)g(follo)m(wing)i(v)-5 b(alues:)37 b(TSTRING,)23 b(TLOGICAL)g(\(==)227 4146 y(in)m(t\),)38 b(TBYTE,)d(TSHOR)-8 b(T,)34 b(TUSHOR)-8 b(T,)35 b(TINT,)f(TUINT,)h(TLONG,)g(TLONGLONG,)g(TULONG,)227 4258 y(TFLO)m(A)-8 b(T,)24 b(TDOUBLE.)f(Within)h(the)f(con)m(text)i(of) f(this)f(routine,)i(TSTRING)d(corresp)s(onds)g(to)i(a)g('c)m(har*')227 4371 y(data)j(t)m(yp)s(e,)h(i.e.,)g(a)f(p)s(oin)m(ter)f(to)i(a)e(c)m (haracter)i(arra)m(y)-8 b(.)41 b(A)26 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m (y)g(b)s(e)e(en)m(tered)i(for)f(the)h(commen)m(t)227 4484 y(parameter)k(in)f(whic)m(h)g(case)i(the)e(k)m(eyw)m(ord)h(commen) m(t)h(\014eld)d(will)i(b)s(e)f(unmo)s(di\014ed)e(or)j(left)g(blank.)95 4704 y Fe(int)47 b(fits_write_key)d(/)k(ffpky)286 4817 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(DTYPE)h (*value,)477 4930 y(char)h(*comment,)e(>)j(int)f(*status\))95 5156 y(int)g(fits_update_key)d(/)j(ffuky)286 5268 y(\(fitsfile)f (*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(DTYPE)h(*value,)477 5381 y(char)h(*comment,)e(>)j(int)f(*status\))0 5601 y Fi(2)81 b Fj(W)-8 b(rite)44 b(a)g(k)m(eyw)m(ord)f(with)g(a)h(n)m(ull) f(or)g(unde\014ned)e(v)-5 b(alue)43 b(\(i.e.,)48 b(the)c(v)-5 b(alue)43 b(\014eld)g(in)g(the)g(k)m(eyw)m(ord)h(is)f(left)227 5714 y(blank\).)70 b(The)40 b(\014rst)f(routine)h(simply)g(app)s(ends)e (a)j(new)e(k)m(eyw)m(ord)i(whereas)f(the)g(second)g(routine)h(will)p eop end %%Page: 42 50 TeXDict begin 42 49 bop 0 299 a Fj(42)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(up)s(date)d(the)h(v)-5 b(alue)29 b(and)e(commen)m(t)i(\014elds)e(of)h(the)g(k)m(eyw)m(ord)g(if)g(it)g (already)h(exists,)g(otherwise)f(it)h(app)s(ends)227 668 y(a)g(new)g(k)m(eyw)m(ord.)40 b(A)29 b(n)m(ull)g(p)s(oin)m(ter)g (ma)m(y)g(b)s(e)g(en)m(tered)g(for)g(the)g(commen)m(t)g(parameter)h(in) e(whic)m(h)h(case)h(the)227 781 y(k)m(eyw)m(ord)h(commen)m(t)h(\014eld) d(will)i(b)s(e)f(unmo)s(di\014ed)e(or)j(left)g(blank.)95 1024 y Fe(int)47 b(fits_write_key_null)c(/)k(ffpkyu)286 1137 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h (int)g(*status\))95 1363 y(int)g(fits_update_key_null)c(/)k(ffukyu)286 1476 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h (int)g(*status\))0 1719 y Fi(3)81 b Fj(W)-8 b(rite)40 b(\(app)s(end\))e(a)h(COMMENT)g(or)g(HISTOR)-8 b(Y)38 b(k)m(eyw)m(ord)i(to)f(the)g(CHU.)h(The)e(commen)m(t)i(or)f(history)227 1832 y(string)31 b(will)f(b)s(e)g(con)m(tin)m(ued)h(o)m(v)m(er)h(m)m (ultiple)f(k)m(eyw)m(ords)g(if)f(it)h(is)f(longer)h(than)f(70)i(c)m (haracters.)95 2075 y Fe(int)47 b(fits_write_comment)c(/)48 b(ffpcom)286 2188 y(\(fitsfile)e(*fptr,)g(char)g(*comment,)g(>)h(int)g (*status\))95 2414 y(int)g(fits_write_history)c(/)48 b(ffphis)286 2527 y(\(fitsfile)e(*fptr,)g(char)g(*history,)g(>)h(int)g (*status\))0 2770 y Fi(4)81 b Fj(W)-8 b(rite)29 b(the)g(D)m(A)-8 b(TE)29 b(k)m(eyw)m(ord)g(to)g(the)g(CHU.)f(The)g(k)m(eyw)m(ord)h(v)-5 b(alue)29 b(will)f(con)m(tain)i(the)f(curren)m(t)f(system)g(date)227 2883 y(as)k(a)g(c)m(haracter)h(string)e(in)g('yyyy-mm-ddThh:mm:ss')e (format.)44 b(If)31 b(a)h(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(already)g (exists)227 2996 y(in)c(the)f(header,)i(then)e(this)g(routine)h(will)g (simply)f(up)s(date)g(the)h(k)m(eyw)m(ord)g(v)-5 b(alue)28 b(with)f(the)h(curren)m(t)g(date.)95 3239 y Fe(int)47 b(fits_write_date)d(/)j(ffpdat)286 3352 y(\(fitsfile)f(*fptr,)g(>)h (int)g(*status\))0 3595 y Fi(5)81 b Fj(W)-8 b(rite)34 b(a)g(user)f(sp)s(eci\014ed)g(k)m(eyw)m(ord)h(record)f(in)m(to)h(the)g (CHU.)g(This)e(is)i(a)g(lo)m(w{lev)m(el)i(routine)e(whic)m(h)f(can)h(b) s(e)227 3708 y(used)f(to)h(write)f(an)m(y)h(arbitrary)f(record)g(in)m (to)i(the)e(header.)50 b(The)32 b(record)i(m)m(ust)f(conform)g(to)h (the)g(all)g(the)227 3821 y(FITS)c(format)h(requiremen)m(ts.)95 4064 y Fe(int)47 b(fits_write_record)c(/)48 b(ffprec)286 4177 y(\(fitsfile)e(*fptr,)g(char)g(*card,)g(>)i(int)f(*status\))0 4420 y Fi(6)81 b Fj(Up)s(date)34 b(an)g(80-c)m(haracter)j(record)e(in)f (the)g(CHU.)h(If)f(a)h(k)m(eyw)m(ord)f(with)h(the)f(input)g(name)g (already)h(exists,)227 4533 y(then)e(it)h(is)f(o)m(v)m(erwritten)h(b)m (y)f(the)g(v)-5 b(alue)34 b(of)f(card.)49 b(This)32 b(could)h(mo)s (dify)f(the)i(k)m(eyw)m(ord)f(name)g(as)h(w)m(ell)g(as)227 4646 y(the)c(v)-5 b(alue)30 b(and)e(commen)m(t)j(\014elds.)40 b(If)29 b(the)g(k)m(eyw)m(ord)h(do)s(esn't)f(already)h(exist)g(then)g (a)f(new)g(k)m(eyw)m(ord)h(card)227 4759 y(is)h(app)s(ended)d(to)j(the) g(header.)95 5002 y Fe(int)47 b(fits_update_card)d(/)j(ffucrd)286 5115 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*card,)g(>)i (int)f(*status\))0 5358 y Fi(7)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m (erwrite\))i(the)f(commen)m(t)g(\014eld)f(of)h(an)f(existing)h(k)m(eyw) m(ord.)95 5601 y Fe(int)47 b(fits_modify_comment)c(/)k(ffmcom)286 5714 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h (int)g(*status\))p eop end %%Page: 43 51 TeXDict begin 43 50 bop 0 299 a Fh(5.5.)72 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)f(I/O)g(R)m (OUTINES)1011 b Fj(43)0 555 y Fi(8)81 b Fj(W)-8 b(rite)33 b(the)f(ph)m(ysical)h(units)f(string)g(in)m(to)h(an)f(existing)h(k)m (eyw)m(ord.)46 b(This)32 b(routine)g(uses)g(a)g(lo)s(cal)i(con)m(v)m (en)m(tion,)227 668 y(sho)m(wn)e(in)g(the)h(follo)m(wing)h(example,)g (in)e(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)f (square)g(brac)m(k)m(ets)227 781 y(in)e(the)h(b)s(eginning)f(of)g(the)h (k)m(eyw)m(ord)g(commen)m(t)g(\014eld.)239 1051 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)95 1277 y(int)h (fits_write_key_unit)c(/)k(ffpunt)286 1390 y(\(fitsfile)f(*fptr,)g (char)g(*keyname,)g(char)g(*unit,)g(>)i(int)f(*status\))0 1660 y Fi(9)81 b Fj(Rename)30 b(an)h(existing)g(k)m(eyw)m(ord,)g (preserving)f(the)g(curren)m(t)h(v)-5 b(alue)30 b(and)g(commen)m(t)i (\014elds.)95 1931 y Fe(int)47 b(fits_modify_name)d(/)j(ffmnam)286 2043 y(\(fitsfile)f(*fptr,)g(char)g(*oldname,)g(char)g(*newname,)g(>)h (int)g(*status\))0 2314 y Fi(10)f Fj(Delete)37 b(a)e(k)m(eyw)m(ord)g (record.)54 b(The)34 b(space)i(o)s(ccupied)e(b)m(y)h(the)g(k)m(eyw)m (ord)g(is)g(reclaimed)h(b)m(y)e(mo)m(ving)i(all)g(the)227 2427 y(follo)m(wing)e(header)f(records)f(up)g(one)h(ro)m(w)f(in)h(the)f (header.)48 b(The)32 b(\014rst)g(routine)g(deletes)i(a)f(k)m(eyw)m(ord) g(at)h(a)227 2540 y(sp)s(eci\014ed)23 b(p)s(osition)h(in)g(the)g (header)f(\(the)i(\014rst)e(k)m(eyw)m(ord)h(is)g(at)g(p)s(osition)g (1\),)i(whereas)e(the)g(second)g(routine)227 2652 y(deletes)30 b(a)f(sp)s(eci\014cally)g(named)f(k)m(eyw)m(ord.)41 b(Wild)29 b(card)f(c)m(haracters)i(ma)m(y)f(b)s(e)f(used)g(when)f(sp)s(ecifying)i (the)227 2765 y(name)23 b(of)g(the)f(k)m(eyw)m(ord)h(to)h(b)s(e)e (deleted.)38 b(The)22 b(third)g(routine)h(deletes)g(the)g(\(next\))h(k) m(eyw)m(ord)f(that)g(con)m(tains)227 2878 y(the)31 b(literal)h(c)m (haracter)g(string)e(sp)s(eci\014ed)g(b)m(y)g(the)h('string')f(argumen) m(t.)95 3148 y Fe(int)47 b(fits_delete_record)c(/)48 b(ffdrec)286 3261 y(\(fitsfile)e(*fptr,)g(int)142 b(keynum,)94 b(>)47 b(int)g(*status\))95 3487 y(int)g(fits_delete_key)d(/)j(ffdkey) 286 3600 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h(int)g (*status\))95 3826 y(int)g(fits_delete_str)d(/)j(ffdstr)286 3939 y(\(fitsfile)f(*fptr,)g(char)g(*string,)g(>)h(int)g(*status\))0 4285 y Ff(5.5)135 b(Primary)46 b(Arra)l(y)f(or)g(IMA)l(GE)f(Extension)i (I/O)f(Routines)0 4538 y Fj(These)22 b(routines)g(read)h(or)f(write)h (data)g(v)-5 b(alues)23 b(in)f(the)g(primary)g(data)h(arra)m(y)g (\(i.e.,)j(the)c(\014rst)g(HDU)h(in)f(a)h(FITS)e(\014le\))0 4650 y(or)32 b(an)g(IMA)m(GE)h(extension.)47 b(There)31 b(are)i(also)g(routines)f(to)h(get)g(information)f(ab)s(out)g(the)g (data)h(t)m(yp)s(e)g(and)e(size)0 4763 y(of)c(the)g(image.)41 b(Users)27 b(should)f(also)i(read)f(the)g(follo)m(wing)h(c)m(hapter)g (on)f(the)g(CFITSIO)e(iterator)k(function)d(whic)m(h)0 4876 y(pro)m(vides)33 b(a)h(more)f(`ob)5 b(ject)35 b(orien)m(ted')f (metho)s(d)f(of)g(reading)g(and)g(writing)g(images.)51 b(The)32 b(iterator)j(function)e(is)0 4989 y(a)e(little)i(more)e (complicated)h(to)g(use,)f(but)f(the)h(adv)-5 b(an)m(tages)32 b(are)f(that)h(it)f(usually)g(tak)m(es)h(less)f(co)s(de)g(to)g(p)s (erform)0 5102 y(the)37 b(same)f(op)s(eration,)j(and)c(the)i(resulting) f(program)g(often)h(runs)e(faster)i(b)s(ecause)f(the)g(FITS)g(\014les)g (are)h(read)0 5215 y(and)30 b(written)g(using)g(the)h(most)f(e\016cien) m(t)i(blo)s(c)m(k)f(size.)0 5375 y(C)25 b(programmers)h(should)f(note)h (that)g(the)h(ordering)e(of)h(arra)m(ys)g(in)g(FITS)f(\014les,)i(and)e (hence)h(in)g(all)g(the)g(CFITSIO)0 5488 y(calls,)40 b(is)d(more)g(similar)h(to)f(the)h(dimensionalit)m(y)g(of)f(arra)m(ys)g (in)g(F)-8 b(ortran)38 b(rather)f(than)f(C.)h(F)-8 b(or)38 b(instance)g(if)f(a)0 5601 y(FITS)28 b(image)i(has)e(NAXIS1)h(=)f(100)i (and)e(NAXIS2)h(=)f(50,)i(then)e(a)h(2-D)h(arra)m(y)f(just)f(large)i (enough)e(to)i(hold)e(the)0 5714 y(image)k(should)d(b)s(e)h(declared)h (as)f(arra)m(y[50][100])k(and)c(not)h(as)f(arra)m(y[100][50].)p eop end %%Page: 44 52 TeXDict begin 44 51 bop 0 299 a Fj(44)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(The)h(`datat)m(yp)s(e')h(parameter)g(sp)s (eci\014es)e(the)i(data)g(t)m(yp)s(e)f(of)g(the)g(`n)m(ulv)-5 b(al')32 b(and)f(`arra)m(y')h(p)s(oin)m(ters)f(and)f(can)i(ha)m(v)m(e)0 668 y(one)h(of)g(the)g(follo)m(wing)h(v)-5 b(alues:)46 b(TBYTE,)33 b(TSBYTE,)f(TSHOR)-8 b(T,)32 b(TUSHOR)-8 b(T,)32 b(TINT,)h(TUINT,)f(TLONG,)0 781 y(TLONGLONG,)27 b(TULONG,)g(TULONGLONG,)f(TFLO)m(A)-8 b(T,)28 b(TDOUBLE.)f(Automatic)h (data)f(t)m(yp)s(e)g(con)m(v)m(er-)0 894 y(sion)34 b(is)g(p)s(erformed) f(if)h(the)g(data)h(t)m(yp)s(e)g(of)f(the)g(FITS)g(arra)m(y)g(\(as)h (de\014ned)e(b)m(y)h(the)h(BITPIX)e(k)m(eyw)m(ord\))i(di\013ers)0 1007 y(from)d(that)i(sp)s(eci\014ed)e(b)m(y)g('datat)m(yp)s(e'.)49 b(The)33 b(data)g(v)-5 b(alues)33 b(are)g(also)h(automatically)i (scaled)d(b)m(y)g(the)g(BSCALE)0 1120 y(and)d(BZER)m(O)g(k)m(eyw)m(ord) h(v)-5 b(alues)31 b(as)f(they)h(are)f(b)s(eing)g(read)h(or)f(written)g (in)h(the)f(FITS)g(arra)m(y)-8 b(.)0 1339 y Fi(1)81 b Fj(Get)33 b(the)f(data)h(t)m(yp)s(e)f(or)g(equiv)-5 b(alen)m(t)34 b(data)f(t)m(yp)s(e)f(of)g(the)h(image.)47 b(The)32 b(\014rst)f (routine)h(returns)f(the)h(ph)m(ysical)227 1451 y(data)46 b(t)m(yp)s(e)f(of)h(the)f(FITS)f(image,)51 b(as)45 b(giv)m(en)h(b)m(y)f (the)g(BITPIX)g(k)m(eyw)m(ord,)50 b(with)44 b(allo)m(w)m(ed)j(v)-5 b(alues)46 b(of)227 1564 y(BYTE)p 492 1564 28 4 v 33 w(IMG)23 b(\(8\),)i(SHOR)-8 b(T)p 1215 1564 V 32 w(IMG)23 b(\(16\),)i(LONG)p 1934 1564 V 33 w(IMG)e(\(32\),)i(LONGLONG)p 2921 1564 V 33 w(IMG)e(\(64\),)i(FLO)m(A)-8 b(T)p 3684 1564 V 33 w(IMG)227 1677 y(\(-32\),)31 b(and)c(DOUBLE)p 1043 1677 V 33 w(IMG)h(\(-64\).)42 b(The)27 b(second)h(routine)f(is)h (similar,)h(except)g(that)f(if)g(the)g(image)h(pixel)227 1790 y(v)-5 b(alues)33 b(are)g(scaled,)g(with)f(non-default)h(v)-5 b(alues)32 b(for)g(the)h(BZER)m(O)f(and)g(BSCALE)f(k)m(eyw)m(ords,)j (then)e(the)227 1903 y(routine)j(will)g(return)e(the)i('equiv)-5 b(alen)m(t')36 b(data)f(t)m(yp)s(e)g(that)g(is)f(needed)h(to)g(store)g (the)g(scaled)g(v)-5 b(alues.)53 b(F)-8 b(or)227 2016 y(example,)29 b(if)e(BITPIX)g(=)g(16)h(and)f(BSCALE)f(=)h(0.1)h(then)f (the)h(equiv)-5 b(alen)m(t)28 b(data)g(t)m(yp)s(e)g(is)f(FLO)m(A)-8 b(T)p 3659 2016 V 33 w(IMG.)227 2129 y(Similarly)25 b(if)f(BITPIX)g(=)g (16,)i(BSCALE)e(=)g(1,)i(and)d(BZER)m(O)h(=)g(32768,)k(then)c(the)g (the)h(pixel)f(v)-5 b(alues)25 b(span)227 2242 y(the)31 b(range)g(of)f(an)g(unsigned)g(short)g(in)m(teger)h(and)f(the)h (returned)e(data)i(t)m(yp)s(e)g(will)f(b)s(e)g(USHOR)-8 b(T)p 3572 2242 V 32 w(IMG.)95 2461 y Fe(int)47 b(fits_get_img_type)c (/)48 b(ffgidt)286 2574 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*bitpix,)f (int)h(*status\))95 2799 y(int)g(fits_get_img_equivtype)42 b(/)48 b(ffgiet)286 2912 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*bitpix,)f (int)h(*status\))0 3131 y Fi(2)81 b Fj(Get)34 b(the)g(n)m(um)m(b)s(er)e (of)i(dimensions,)g(and/or)g(the)g(size)g(of)g(eac)m(h)h(dimension)e (in)g(the)h(image)h(.)50 b(The)33 b(n)m(um)m(b)s(er)227 3244 y(of)h(axes)f(in)g(the)g(image)i(is)e(giv)m(en)h(b)m(y)f(naxis,)h (and)f(the)g(size)h(of)f(eac)m(h)i(dimension)d(is)h(giv)m(en)h(b)m(y)f (the)h(naxes)227 3357 y(arra)m(y)d(\(a)g(maxim)m(um)g(of)f(maxdim)g (dimensions)g(will)g(b)s(e)g(returned\).)95 3576 y Fe(int)47 b(fits_get_img_dim)d(/)j(ffgidm)286 3689 y(\(fitsfile)f(*fptr,)g(>)h (int)g(*naxis,)f(int)h(*status\))95 3914 y(int)g(fits_get_img_size)c(/) 48 b(ffgisz)286 4027 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(long)f (*naxes,)e(int)i(*status\))95 4253 y(int)g(fits_get_img_sizell)c(/)k (ffgiszll)286 4366 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j (LONGLONG)d(*naxes,)h(int)h(*status\))95 4592 y(int)g (fits_get_img_param)c(/)48 b(ffgipr)286 4705 y(\(fitsfile)e(*fptr,)g (int)h(maxdim,)e(>)j(int)f(*bitpix,)e(int)i(*naxis,)f(long)h(*naxes,) 334 4818 y(int)g(*status\))95 5043 y(int)g(fits_get_img_paramll)c(/)k (ffgiprll)286 5156 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j(int)f (*bitpix,)e(int)i(*naxis,)f(LONGLONG)g(*naxes,)334 5269 y(int)h(*status\))0 5488 y Fi(3)81 b Fj(Create)23 b(a)f(new)g(primary)f (arra)m(y)i(or)f(IMA)m(GE)i(extension)e(with)g(a)h(sp)s(eci\014ed)f (data)h(t)m(yp)s(e)f(and)g(size.)38 b(If)22 b(the)h(FITS)227 5601 y(\014le)30 b(is)g(curren)m(tly)f(empt)m(y)h(then)g(a)g(primary)f (arra)m(y)h(is)g(created,)h(otherwise)f(a)g(new)f(IMA)m(GE)i(extension) f(is)227 5714 y(app)s(ended)f(to)i(the)g(\014le.)p eop end %%Page: 45 53 TeXDict begin 45 52 bop 0 299 a Fh(5.5.)72 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)f(I/O)g(R)m (OUTINES)1011 b Fj(45)95 555 y Fe(int)47 b(fits_create_img)d(/)j (ffcrim)286 668 y(\()h(fitsfile)d(*fptr,)h(int)h(bitpix,)f(int)h (naxis,)f(long)h(*naxes,)f(>)h(int)g(*status\))95 894 y(int)g(fits_create_imgll)c(/)48 b(ffcrimll)286 1007 y(\()g(fitsfile)d(*fptr,)h(int)h(bitpix,)f(int)h(naxis,)f(LONGLONG)g (*naxes,)g(>)h(int)g(*status\))0 1257 y Fi(4)81 b Fj(Cop)m(y)39 b(an)f(n-dimensional)h(image)h(in)f(a)g(particular)h(ro)m(w)f(and)f (column)h(of)g(a)g(binary)f(table)i(\(in)f(a)g(v)m(ector)227 1369 y(column\))31 b(to)g(or)f(from)g(a)h(primary)e(arra)m(y)i(or)g (image)g(extension.)227 1518 y(The)c('cell2image')k(routine)d(will)g (app)s(end)e(a)i(new)f(image)i(extension)f(\(or)g(primary)f(arra)m(y\)) h(to)h(the)e(output)227 1631 y(\014le.)43 b(An)m(y)31 b(W)m(CS)g(k)m(eyw)m(ords)g(asso)s(ciated)h(with)f(the)g(input)f (column)h(image)h(will)f(b)s(e)f(translated)i(in)m(to)g(the)227 1744 y(appropriate)j(form)g(for)g(an)f(image)j(extension.)55 b(An)m(y)35 b(other)g(k)m(eyw)m(ords)g(in)g(the)g(table)h(header)f (that)h(are)227 1857 y(not)28 b(sp)s(eci\014cally)h(related)f(to)h (de\014ning)e(the)g(binary)g(table)i(structure)e(or)h(to)g(other)g (columns)g(in)f(the)h(table)227 1970 y(will)j(also)g(b)s(e)f(copied)h (to)g(the)g(header)f(of)g(the)h(output)f(image.)227 2118 y(The)i('image2cell')k(routine)c(will)h(cop)m(y)g(the)g(input)e(image)j (in)m(to)f(the)g(sp)s(eci\014ed)f(ro)m(w)g(and)g(column)g(of)h(the)227 2231 y(curren)m(t)e(binary)g(table)h(in)f(the)h(output)f(\014le.)44 b(The)31 b(binary)f(table)j(HDU)f(m)m(ust)f(exist)h(b)s(efore)f (calling)i(this)227 2344 y(routine,)h(but)f(it)h(ma)m(y)f(b)s(e)g(empt) m(y)-8 b(,)35 b(with)e(no)g(ro)m(ws)g(or)g(columns)g(of)g(data.)50 b(The)33 b(sp)s(eci\014ed)f(column)h(\(and)227 2457 y(ro)m(w\))e(will)h (b)s(e)e(created)h(if)g(it)g(do)s(es)g(not)g(already)g(exist.)43 b(The)30 b('cop)m(yk)m(ey\015ag')j(parameter)e(con)m(trols)h(whic)m(h) 227 2570 y(k)m(eyw)m(ords)26 b(are)g(copied)g(from)f(the)g(input)g (image)h(to)g(the)g(header)f(of)h(the)f(output)g(table:)39 b(0)26 b(=)f(no)h(k)m(eyw)m(ords)227 2683 y(will)k(b)s(e)g(copied,)g(1) h(=)e(all)i(k)m(eyw)m(ords)f(will)g(b)s(e)f(copied)h(\(except)i(those)e (k)m(eyw)m(ords)g(that)h(w)m(ould)e(b)s(e)g(in)m(v)-5 b(alid)227 2796 y(in)30 b(the)h(table)g(header\),)g(and)f(2)g(=)g(cop)m (y)i(only)e(the)h(W)m(CS)f(k)m(eyw)m(ords.)95 3045 y Fe(int)47 b(fits_copy_cell2image)286 3158 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(char)i(*colname,)e(long)i(rownum,)334 3271 y(>)h(int)e(*status\))95 3497 y(int)h(fits_copy_image2cell)286 3610 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(char)i(*colname,) e(long)i(rownum,)334 3723 y(int)g(copykeyflag)e(>)i(int)g(*status\))0 3973 y Fi(5)81 b Fj(W)-8 b(rite)40 b(a)f(rectangular)g(subimage)g(\(or) g(the)g(whole)g(image\))h(to)f(the)g(FITS)f(data)h(arra)m(y)-8 b(.)67 b(The)38 b(fpixel)h(and)227 4085 y(lpixel)30 b(arra)m(ys)g(giv)m (e)h(the)f(co)s(ordinates)g(of)f(the)h(\014rst)f(\(lo)m(w)m(er)i(left)f (corner\))g(and)f(last)h(\(upp)s(er)e(righ)m(t)i(corner\))227 4198 y(pixels)h(in)f(FITS)g(image)h(to)g(b)s(e)f(written)g(to.)95 4448 y Fe(int)47 b(fits_write_subset)c(/)48 b(ffpss)286 4561 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(long)i (*lpixel,)334 4674 y(DTYPE)f(*array,)g(>)i(int)f(*status\))0 4924 y Fi(6)81 b Fj(W)-8 b(rite)39 b(pixels)g(in)m(to)g(the)g(FITS)f (data)h(arra)m(y)-8 b(.)66 b('fpixel')39 b(is)f(an)g(arra)m(y)h(of)g (length)g(NAXIS)f(whic)m(h)g(giv)m(es)i(the)227 5036 y(co)s(ordinate)k(of)f(the)g(starting)g(pixel)g(to)h(b)s(e)e(written)h (to,)j(suc)m(h)d(that)g(fpixel[0])h(is)f(in)f(the)h(range)g(1)g(to)227 5149 y(NAXIS1,)34 b(fpixel[1])f(is)g(in)f(the)g(range)h(1)g(to)g (NAXIS2,)g(etc.)48 b(The)32 b(\014rst)g(pair)g(of)h(routines)f(simply)g (writes)227 5262 y(the)40 b(arra)m(y)g(of)g(pixels)f(to)i(the)e(FITS)g (\014le)h(\(doing)g(data)g(t)m(yp)s(e)g(con)m(v)m(ersion)h(if)e (necessary\))h(whereas)g(the)227 5375 y(second)c(routines)g(will)g (substitute)f(the)h(appropriate)g(FITS)f(n)m(ull)g(v)-5 b(alue)37 b(for)e(an)m(y)h(elemen)m(ts)h(whic)m(h)f(are)227 5488 y(equal)41 b(to)g(the)f(input)g(v)-5 b(alue)40 b(of)h(n)m(ulv)-5 b(al)40 b(\(note)h(that)g(this)f(parameter)h(giv)m(es)h(the)e(address)f (of)i(the)f(n)m(ull)227 5601 y(v)-5 b(alue,)36 b(not)f(the)f(n)m(ull)g (v)-5 b(alue)35 b(itself)7 b(\).)53 b(F)-8 b(or)35 b(in)m(teger)h(FITS) d(arra)m(ys,)j(the)f(FITS)e(n)m(ull)h(v)-5 b(alue)35 b(is)f(de\014ned)f(b)m(y)227 5714 y(the)26 b(BLANK)f(k)m(eyw)m(ord)h (\(an)g(error)f(is)g(returned)f(if)i(the)f(BLANK)h(k)m(eyw)m(ord)g(do)s (esn't)f(exist\).)40 b(F)-8 b(or)26 b(\015oating)p eop end %%Page: 46 54 TeXDict begin 46 53 bop 0 299 a Fj(46)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(p)s(oin)m(t)c(FITS)f(arra)m(ys)h(the)g(sp)s (ecial)g(IEEE)f(NaN)i(\(Not-a-Num)m(b)s(er\))g(v)-5 b(alue)26 b(will)g(b)s(e)f(written)h(in)m(to)h(the)f(FITS)227 668 y(\014le.)66 b(If)38 b(a)h(n)m(ull)f(p)s(oin)m(ter)h(is)f(en)m(tered)h (for)g(n)m(ulv)-5 b(al,)41 b(then)d(the)h(n)m(ull)f(v)-5 b(alue)39 b(is)g(ignored)g(and)e(this)i(routine)227 781 y(b)s(eha)m(v)m(es)31 b(the)g(same)g(as)f(\014ts)p 1189 781 28 4 v 33 w(write)p 1424 781 V 33 w(pix.)95 1020 y Fe(int)47 b(fits_write_pix)d(/)k(ffppx)286 1133 y(\(fitsfile)e (*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(LONGLONG)h(nelements,)334 1246 y(DTYPE)g(*array,)g(int)h(*status\);)95 1471 y(int)g (fits_write_pixll)d(/)j(ffppxll)286 1584 y(\(fitsfile)f(*fptr,)g(int)h (datatype,)e(LONGLONG)g(*fpixel,)h(LONGLONG)g(nelements,)334 1697 y(DTYPE)g(*array,)g(int)h(*status\);)95 1923 y(int)g (fits_write_pixnull)c(/)48 b(ffppxn)286 2036 y(\(fitsfile)e(*fptr,)g (int)h(datatype,)e(long)i(*fpixel,)e(LONGLONG)h(nelements,)334 2149 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e(>)j(int)f(*status\);)95 2375 y(int)g(fits_write_pixnullll)c(/)k(ffppxnll)286 2488 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(LONGLONG)g(*fpixel,)h (LONGLONG)g(nelements,)334 2601 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e (>)j(int)f(*status\);)0 2839 y Fi(7)81 b Fj(Set)24 b(FITS)g(data)i (arra)m(y)f(elemen)m(ts)h(equal)f(to)g(the)g(appropriate)f(n)m(ull)h (pixel)g(v)-5 b(alue.)39 b(F)-8 b(or)25 b(in)m(teger)h(FITS)e(arra)m (ys,)227 2952 y(the)34 b(FITS)e(n)m(ull)h(v)-5 b(alue)34 b(is)f(de\014ned)f(b)m(y)h(the)h(BLANK)f(k)m(eyw)m(ord)h(\(an)f(error)g (is)g(returned)f(if)h(the)h(BLANK)227 3065 y(k)m(eyw)m(ord)23 b(do)s(esn't)g(exist\).)39 b(F)-8 b(or)23 b(\015oating)g(p)s(oin)m(t)g (FITS)f(arra)m(ys)g(the)h(sp)s(ecial)g(IEEE)f(NaN)h(\(Not-a-Num)m(b)s (er\))227 3178 y(v)-5 b(alue)34 b(will)f(b)s(e)g(written)g(in)m(to)h (the)g(FITS)e(\014le.)49 b(Note)34 b(that)g('\014rstelem')g(is)f(a)h (scalar)g(giving)g(the)f(o\013set)h(to)227 3291 y(the)d(\014rst)e (pixel)i(to)g(b)s(e)f(written)g(in)h(the)f(equiv)-5 b(alen)m(t)32 b(1-dimensional)f(arra)m(y)g(of)g(image)g(pixels.)95 3530 y Fe(int)47 b(fits_write_null_img)c(/)k(ffpprn)286 3643 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(firstelem,)g(LONGLONG)h (nelements,)f(>)i(int)g(*status\))0 3881 y Fi(8)81 b Fj(Read)33 b(a)h(rectangular)h(subimage)f(\(or)g(the)g(whole)g(image\)) h(from)e(the)h(FITS)f(data)h(arra)m(y)-8 b(.)52 b(The)33 b(fpixel)h(and)227 3994 y(lpixel)c(arra)m(ys)g(giv)m(e)h(the)f(co)s (ordinates)g(of)f(the)h(\014rst)f(\(lo)m(w)m(er)i(left)f(corner\))g (and)f(last)h(\(upp)s(er)e(righ)m(t)i(corner\))227 4107 y(pixels)d(to)h(b)s(e)e(read)h(from)g(the)g(FITS)f(image.)41 b(Unde\014ned)25 b(FITS)h(arra)m(y)i(elemen)m(ts)g(will)f(b)s(e)f (returned)g(with)227 4220 y(a)k(v)-5 b(alue)30 b(=)e(*n)m(ullv)-5 b(al,)31 b(\(note)f(that)g(this)f(parameter)h(giv)m(es)g(the)g(address) e(of)h(the)h(n)m(ull)f(v)-5 b(alue,)30 b(not)g(the)f(n)m(ull)227 4333 y(v)-5 b(alue)36 b(itself)7 b(\))37 b(unless)e(n)m(ulv)-5 b(al)36 b(=)g(0)g(or)f(*n)m(ulv)-5 b(al)37 b(=)e(0,)j(in)d(whic)m(h)g (case)i(no)f(c)m(hec)m(ks)h(for)e(unde\014ned)f(pixels)227 4446 y(will)d(b)s(e)f(p)s(erformed.)95 4685 y Fe(int)47 b(fits_read_subset)d(/)j(ffgsv)286 4798 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(*fpixel,)g(long)g(*lpixel,)g(long)h(*inc,)334 4911 y(DTYPE)f(*nulval,)g(>)h(DTYPE)g(*array,)f(int)h(*anynul,)e(int)i (*status\))0 5149 y Fi(9)81 b Fj(Read)32 b(pixels)h(from)f(the)g(FITS)g (data)h(arra)m(y)-8 b(.)48 b('fpixel')33 b(is)g(the)f(starting)h(pixel) g(lo)s(cation)h(and)e(is)h(an)f(arra)m(y)h(of)227 5262 y(length)h(NAXIS)f(suc)m(h)g(that)h(fpixel[0])g(is)f(in)g(the)h(range)f (1)h(to)g(NAXIS1,)g(fpixel[1])g(is)g(in)f(the)g(range)h(1)f(to)227 5375 y(NAXIS2,)c(etc.)41 b(The)28 b(nelemen)m(ts)h(parameter)f(sp)s (eci\014es)g(the)g(n)m(um)m(b)s(er)f(of)h(pixels)h(to)g(read.)39 b(If)28 b(fpixel)g(is)g(set)227 5488 y(to)36 b(the)f(\014rst)f(pixel,)j (and)e(nelemen)m(ts)g(is)g(set)h(equal)g(to)f(the)g(NAXIS1)h(v)-5 b(alue,)37 b(then)d(this)h(routine)g(w)m(ould)227 5601 y(read)28 b(the)g(\014rst)f(ro)m(w)h(of)g(the)h(image.)41 b(Alternativ)m(ely)-8 b(,)31 b(if)d(nelemen)m(ts)h(is)f(set)g(equal)h (to)f(NAXIS1)g(*)h(NAXIS2)227 5714 y(then)h(it)h(w)m(ould)f(read)h(an)f (en)m(tire)h(2D)g(image,)h(or)f(the)f(\014rst)g(plane)g(of)h(a)g(3-D)g (datacub)s(e.)p eop end %%Page: 47 55 TeXDict begin 47 54 bop 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 b(COMPRESSION)2567 b Fj(47)227 555 y(The)38 b(\014rst)g(2)h(routines)f (will)h(return)f(an)m(y)h(unde\014ned)d(pixels)j(in)f(the)h(FITS)e (arra)m(y)i(equal)g(to)h(the)e(v)-5 b(alue)227 668 y(of)36 b(*n)m(ullv)-5 b(al)36 b(\(note)g(that)g(this)f(parameter)h(giv)m(es)g (the)g(address)e(of)i(the)f(n)m(ull)g(v)-5 b(alue,)37 b(not)f(the)f(n)m(ull)g(v)-5 b(alue)227 781 y(itself)7 b(\))34 b(unless)d(n)m(ulv)-5 b(al)32 b(=)g(0)g(or)h(*n)m(ulv)-5 b(al)32 b(=)g(0,)h(in)f(whic)m(h)g(case)h(no)f(c)m(hec)m(ks)h(for)f (unde\014ned)e(pixels)i(will)h(b)s(e)227 894 y(p)s(erformed.)42 b(The)31 b(second)h(2)f(routines)h(are)f(similar)h(except)g(that)g(an)m (y)g(unde\014ned)d(pixels)i(will)h(ha)m(v)m(e)h(the)227 1007 y(corresp)s(onding)d(n)m(ullarra)m(y)g(elemen)m(t)i(set)f(equal)g (to)g(TR)m(UE)g(\(=)f(1\).)95 1272 y Fe(int)47 b(fits_read_pix)e(/)i (ffgpxv)286 1385 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(*fpixel,)g(LONGLONG)f(nelements,)334 1497 y(DTYPE)h(*nulval,)g (>)h(DTYPE)g(*array,)f(int)h(*anynul,)e(int)i(*status\))95 1723 y(int)g(fits_read_pixll)d(/)j(ffgpxvll)286 1836 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(LONGLONG)f(*fpixel,)h (LONGLONG)f(nelements,)334 1949 y(DTYPE)h(*nulval,)g(>)h(DTYPE)g (*array,)f(int)h(*anynul,)e(int)i(*status\))95 2175 y(int)g (fits_read_pixnull)c(/)48 b(ffgpxf)286 2288 y(\(fitsfile)e(*fptr,)g (int)94 b(datatype,)46 b(long)g(*fpixel,)g(LONGLONG)f(nelements,)334 2401 y(>)j(DTYPE)e(*array,)g(char)g(*nullarray,)f(int)i(*anynul,)f(int) g(*status\))95 2627 y(int)h(fits_read_pixnullll)c(/)k(ffgpxfll)286 2739 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(LONGLONG)f (*fpixel,)h(LONGLONG)f(nelements,)334 2852 y(>)j(DTYPE)e(*array,)g (char)g(*nullarray,)f(int)i(*anynul,)f(int)g(*status\))0 3117 y Fi(10)g Fj(Cop)m(y)36 b(a)g(rectangular)h(section)g(of)g(an)e (image)j(and)d(write)h(it)h(to)f(a)h(new)e(FITS)g(primary)g(image)j(or) e(image)227 3230 y(extension.)49 b(The)32 b(new)g(image)i(HDU)g(is)e (app)s(ended)f(to)j(the)f(end)f(of)h(the)g(output)f(\014le;)i(all)g (the)f(k)m(eyw)m(ords)227 3343 y(in)39 b(the)f(input)g(image)i(will)f (b)s(e)f(copied)h(to)g(the)g(output)f(image.)66 b(The)38 b(common)h(W)m(CS)g(k)m(eyw)m(ords)g(will)227 3456 y(b)s(e)34 b(up)s(dated)f(if)i(necessary)g(to)g(corresp)s(ond)e(to)j(the)e(co)s (ordinates)h(of)g(the)g(section.)54 b(The)34 b(format)h(of)g(the)227 3569 y(section)29 b(expression)e(is)g(same)g(as)h(sp)s(ecifying)f(an)g (image)h(section)h(using)d(the)i(extended)f(\014le)g(name)g(syn)m(tax) 227 3682 y(\(see)32 b("Image)f(Section")h(in)e(Chapter)g(10\).)42 b(\(Examples:)f("1:100,1:200",)36 b("1:100:2,)d(1:*:2",)g("*,)f(-*"\).) 95 3947 y Fe(int)47 b(fits_copy_image_section)42 b(/)47 b(ffcpimg)286 4059 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f (char)i(*section,)e(int)i(*status\))0 4399 y Ff(5.6)135 b(Image)46 b(Compression)0 4650 y Fj(CFITSIO)29 b(transparen)m(tly)h (supp)s(orts)f(the)h(2)h(metho)s(ds)f(of)g(image)i(compression)e (describ)s(ed)g(b)s(elo)m(w.)0 4811 y(1\))45 b(The)f(en)m(tire)i(FITS)e (\014le)h(ma)m(y)g(b)s(e)f(externally)i(compressed)e(with)g(the)h(gzip) g(or)g(Unix)f(compress)h(utilit)m(y)0 4924 y(programs,)37 b(pro)s(ducing)d(a)j(*.gz)g(or)f(*.Z)g(\014le,)h(resp)s(ectiv)m(ely)-8 b(.)59 b(When)36 b(reading)g(compressed)f(\014les)h(of)g(this)g(t)m(yp) s(e,)0 5036 y(CFITSIO)43 b(\014rst)h(uncompresses)f(the)i(en)m(tire)g (\014le)g(in)m(to)g(memory)g(b)s(efore)f(p)s(erforming)f(the)i (requested)f(read)0 5149 y(op)s(erations.)c(Output)28 b(\014les)g(can)h(b)s(e)f(directly)i(written)e(in)g(the)h(gzip)g (compressed)g(format)g(if)f(the)h(user-sp)s(eci\014ed)0 5262 y(\014lename)35 b(ends)e(with)i(`.gz'.)54 b(In)34 b(this)g(case,)j(CFITSIO)c(initially)j(writes)e(the)h(uncompressed)e (\014le)i(in)f(memory)0 5375 y(and)j(then)g(compresses)g(it)h(and)f (writes)g(it)h(to)g(disk)f(when)f(the)i(FITS)f(\014le)g(is)g(closed,)k (th)m(us)36 b(sa)m(ving)j(user)d(disk)0 5488 y(space.)59 b(Read)36 b(and)g(write)h(access)g(to)g(these)g(compressed)f(FITS)g (\014les)g(is)g(generally)i(quite)e(fast)h(since)g(all)g(the)0 5601 y(I/O)28 b(is)g(p)s(erformed)e(in)i(memory;)h(the)f(main)g (limitation)i(with)e(this)f(tec)m(hnique)i(is)f(that)h(there)f(m)m(ust) g(b)s(e)f(enough)0 5714 y(a)m(v)-5 b(ailable)33 b(memory)d(\(or)h(sw)m (ap)f(space\))h(to)g(hold)f(the)h(en)m(tire)g(uncompressed)e(FITS)h (\014le.)p eop end %%Page: 48 56 TeXDict begin 48 55 bop 0 299 a Fj(48)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(2\))42 b(CFITSIO)d(also)j(supp)s(orts)d(the)j (FITS)e(tiled)h(image)i(compression)e(con)m(v)m(en)m(tion)i(in)e(whic)m (h)f(the)i(image)g(is)0 668 y(sub)s(divided)30 b(in)m(to)j(a)f(grid)g (of)g(rectangular)i(tiles,)f(and)f(eac)m(h)h(tile)g(of)g(pixels)f(is)g (individually)g(compressed.)45 b(The)0 781 y(details)c(of)f(this)g (FITS)g(compression)g(con)m(v)m(en)m(tion)i(are)e(describ)s(ed)f(at)i (the)g(FITS)e(Supp)s(ort)f(O\016ce)i(w)m(eb)g(site)0 894 y(at)c(h)m(ttp://\014ts.gsfc.nasa.go)m(v/\014ts)p 1230 894 28 4 v 37 w(registry)-8 b(.h)m(tml,)38 b(and)d(in)g(the)g (fpac)m(kguide)h(p)s(df)e(\014le)h(that)h(is)g(included)e(with)0 1007 y(the)h(CFITSIO)f(source)h(\014le)h(distributions)e(Basically)-8 b(,)39 b(the)c(compressed)g(image)i(tiles)f(are)g(stored)f(in)g(ro)m (ws)g(of)0 1120 y(a)42 b(v)-5 b(ariable)42 b(length)g(arra)m(y)h (column)e(in)g(a)h(FITS)f(binary)g(table,)46 b(ho)m(w)m(ev)m(er)c (CFITSIO)f(recognizes)i(that)f(this)0 1233 y(binary)37 b(table)i(extension)f(con)m(tains)h(an)e(image)i(and)e(treats)i(it)f (as)g(if)g(it)g(w)m(ere)g(an)g(IMA)m(GE)g(extension.)64 b(This)0 1346 y(tile-compressed)37 b(format)f(is)f(esp)s(ecially)i(w)m (ell)g(suited)e(for)h(compressing)f(v)m(ery)h(large)h(images)g(b)s (ecause)e(a\))i(the)0 1458 y(FITS)28 b(header)h(k)m(eyw)m(ords)h (remain)f(uncompressed)e(for)i(rapid)g(read)g(access,)h(and)f(b)s (ecause)g(b\))g(it)g(is)h(p)s(ossible)e(to)0 1571 y(extract)f(and)e (uncompress)g(sections)i(of)f(the)g(image)h(without)e(ha)m(ving)i(to)f (uncompress)f(the)h(en)m(tire)g(image.)41 b(This)0 1684 y(format)34 b(is)g(also)h(m)m(uc)m(h)e(more)h(e\013ectiv)m(e)j(in)c (compressing)h(\015oating)h(p)s(oin)m(t)e(images)i(than)f(simply)f (compressing)0 1797 y(the)39 b(image)i(using)d(gzip)i(or)f(compress)g (b)s(ecause)g(it)h(appro)m(ximates)g(the)g(\015oating)g(p)s(oin)m(t)f (v)-5 b(alues)39 b(with)g(scaled)0 1910 y(in)m(tegers)32 b(whic)m(h)e(can)g(then)g(b)s(e)g(compressed)g(more)h(e\016cien)m(tly) -8 b(.)0 2070 y(Curren)m(tly)41 b(CFITSIO)e(supp)s(orts)h(3)h(general)i (purp)s(ose)c(compression)i(algorithms)i(plus)d(one)i(other)f(sp)s (ecial-)0 2183 y(purp)s(ose)31 b(compression)i(tec)m(hnique)h(that)f (is)g(designed)g(for)g(data)g(masks)g(with)g(p)s(ositiv)m(e)h(in)m (teger)g(pixel)f(v)-5 b(alues.)0 2296 y(The)40 b(3)g(general)h(purp)s (ose)e(algorithms)i(are)f(GZIP)-8 b(,)41 b(Rice,)j(and)39 b(HCOMPRESS,)g(and)h(the)g(sp)s(ecial)h(purp)s(ose)0 2409 y(algorithm)33 b(is)f(the)g(IRAF)g(pixel)g(list)h(compression)f (tec)m(hnique)g(\(PLIO\).)g(There)g(are)g(2)g(v)-5 b(arian)m(ts)33 b(of)f(the)g(GZIP)0 2522 y(algorithm:)46 b(GZIP)p 681 2522 V 33 w(1)33 b(compresses)f(the)h(arra)m(y)g(of)g(image)h(pixel)f (v)-5 b(alue)33 b(normally)g(with)g(the)f(GZIP)h(algorithm,)0 2635 y(while)26 b(GZIP)p 460 2635 V 32 w(2)g(\014rst)f(sh)m(u\017es)g (the)g(b)m(ytes)i(in)e(all)h(the)g(pixel)g(v)-5 b(alues)26 b(so)g(that)g(the)g(most-signi\014can)m(t)h(b)m(yte)f(of)g(ev)m(ery)0 2748 y(pixel)h(app)s(ears)e(\014rst,)i(follo)m(w)m(ed)h(b)m(y)e(the)g (less)h(signi\014can)m(t)g(b)m(ytes)g(in)f(sequence.)39 b(GZIP)p 2944 2748 V 33 w(2)26 b(ma)m(y)h(b)s(e)f(more)g(e\013ectiv)m (e)0 2861 y(in)36 b(cases)h(where)e(the)h(most)h(signi\014can)m(t)f(b)m (yte)h(in)f(most)g(of)g(the)g(image)i(pixel)e(v)-5 b(alues)36 b(con)m(tains)h(the)g(same)f(bit)0 2974 y(pattern.)41 b(In)29 b(principle,)h(an)m(y)g(n)m(um)m(b)s(er)f(of)h(other)g (compression)g(algorithms)h(could)f(also)h(b)s(e)e(supp)s(orted)f(b)m (y)i(the)0 3086 y(FITS)g(tiled)h(image)g(compression)g(con)m(v)m(en)m (tion.)0 3247 y(The)k(FITS)g(image)h(can)g(b)s(e)f(sub)s(divided)e(in)m (to)k(an)m(y)f(desired)f(rectangular)h(grid)f(of)h(compression)f (tiles.)57 b(With)0 3360 y(the)32 b(GZIP)-8 b(,)33 b(Rice,)h(and)e (PLIO)f(algorithms,)j(the)e(default)h(is)f(to)h(tak)m(e)h(eac)m(h)g(ro) m(w)e(of)h(the)f(image)i(as)e(a)h(tile.)47 b(The)0 3472 y(HCOMPRESS)25 b(algorithm)i(is)g(inheren)m(tly)f(2-dimensional)h(in)f (nature,)i(so)e(the)h(default)f(in)g(this)g(case)i(is)e(to)h(tak)m(e)0 3585 y(16)h(ro)m(ws)g(of)f(the)h(image)h(p)s(er)d(tile.)41 b(In)27 b(most)h(cases)g(it)g(mak)m(es)h(little)g(di\013erence)f(what)f (tiling)i(pattern)f(is)f(used,)h(so)0 3698 y(the)33 b(default)g(tiles)g (are)g(usually)g(adequate.)48 b(In)32 b(the)h(case)g(of)g(v)m(ery)g (small)g(images,)i(it)e(could)g(b)s(e)f(more)g(e\016cien)m(t)0 3811 y(to)h(compress)f(the)h(whole)f(image)i(as)e(a)h(single)g(tile.)48 b(Note)34 b(that)f(the)f(image)i(dimensions)d(are)i(not)g(required)e (to)0 3924 y(b)s(e)d(an)g(in)m(teger)i(m)m(ultiple)f(of)f(the)h(tile)g (dimensions;)g(if)f(not,)i(then)e(the)g(tiles)i(at)f(the)f(edges)h(of)g (the)f(image)i(will)f(b)s(e)0 4037 y(smaller)i(than)f(the)h(other)f (tiles.)0 4197 y(The)41 b(4)g(supp)s(orted)f(image)i(compression)f (algorithms)h(are)g(all)g('loss-less')h(when)d(applied)h(to)h(in)m (teger)h(FITS)0 4310 y(images;)25 b(the)c(pixel)g(v)-5 b(alues)20 b(are)h(preserv)m(ed)f(exactly)j(with)d(no)g(loss)h(of)f (information)h(during)e(the)i(compression)g(and)0 4423 y(uncompression)34 b(pro)s(cess.)54 b(In)34 b(addition,)j(the)e (HCOMPRESS)f(algorithm)i(supp)s(orts)d(a)i('lossy')h(compression)0 4536 y(mo)s(de)41 b(that)h(will)g(pro)s(duce)f(larger)h(amoun)m(t)g(of) g(image)h(compression.)74 b(This)41 b(is)g(ac)m(hiev)m(ed)j(b)m(y)d(sp) s(ecifying)h(a)0 4649 y(non-zero)32 b(v)-5 b(alue)32 b(for)f(the)g(HCOMPRESS)f(\\scale")k(parameter.)44 b(Since)31 b(the)g(amoun)m(t)h(of)g(compression)f(that)h(is)0 4762 y(ac)m(hiev)m(ed)g(dep)s(ends)d(directly)i(on)f(the)h(RMS)f(noise)h(in) f(the)h(image,)h(it)f(is)g(usually)f(more)g(con)m(v)m(en)m(tion)j(to)e (sp)s(ecify)0 4875 y(the)f(HCOMPRESS)e(scale)i(factor)h(relativ)m(e)g (to)f(the)g(RMS)f(noise.)41 b(Setting)30 b(s)f(=)g(2.5)i(means)e(use)g (a)h(scale)h(factor)0 4988 y(that)h(is)f(2.5)i(times)e(the)h (calculated)h(RMS)e(noise)h(in)f(the)g(image)i(tile.)44 b(In)31 b(some)g(cases)h(it)g(ma)m(y)g(b)s(e)f(desirable)g(to)0 5100 y(sp)s(ecify)h(the)g(exact)i(scaling)f(to)g(b)s(e)e(used,)h (instead)h(of)f(sp)s(ecifying)g(it)g(relativ)m(e)j(to)d(the)h (calculated)h(noise)e(v)-5 b(alue.)0 5213 y(This)37 b(ma)m(y)h(b)s(e)f (done)g(b)m(y)h(sp)s(ecifying)f(the)h(negativ)m(e)i(of)d(desired)g (scale)i(v)-5 b(alue)38 b(\(t)m(ypically)i(in)d(the)h(range)g(-2)g(to)0 5326 y(-100\).)0 5486 y(V)-8 b(ery)43 b(high)g(compression)f(factors)i (\(of)f(100)h(or)f(more\))g(can)g(b)s(e)f(ac)m(hiev)m(ed)j(b)m(y)d (using)h(large)g(HCOMPRESS)0 5599 y(scale)31 b(v)-5 b(alues,)31 b(ho)m(w)m(ev)m(er,)h(this)e(can)g(pro)s(duce)f(undesirable)g(\\blo)s (c)m(ky")j(artifacts)f(in)f(the)g(compressed)g(image.)42 b(A)0 5712 y(v)-5 b(ariation)27 b(of)g(the)f(HCOMPRESS)f(algorithm)i (\(called)h(HSCOMPRESS\))c(can)i(b)s(e)g(used)f(in)h(this)g(case)h(to)g (apply)p eop end %%Page: 49 57 TeXDict begin 49 56 bop 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 b(COMPRESSION)2567 b Fj(49)0 555 y(a)26 b(small)h(amoun)m(t)f(of)h(smo) s(othing)f(of)g(the)g(image)h(when)e(it)i(is)f(uncompressed)f(to)h (help)g(co)m(v)m(er)i(up)d(these)h(artifacts.)0 668 y(This)36 b(smo)s(othing)h(is)g(purely)f(cosmetic)j(and)d(do)s(es)h(not)g(cause)g (an)m(y)h(signi\014can)m(t)g(c)m(hange)g(to)f(the)g(image)i(pixel)0 781 y(v)-5 b(alues.)0 941 y(Floating)34 b(p)s(oin)m(t)f(FITS)e(images)j (\(whic)m(h)e(ha)m(v)m(e)i(BITPIX)e(=)g(-32)h(or)g(-64\))g(usually)f (con)m(tain)i(to)s(o)f(m)m(uc)m(h)g(\\noise")0 1054 y(in)k(the)g(least) i(signi\014can)m(t)f(bits)f(of)h(the)f(man)m(tissa)h(of)g(the)f(pixel)h (v)-5 b(alues)37 b(to)h(b)s(e)f(e\013ectiv)m(ely)j(compressed)d(with)0 1167 y(an)m(y)d(lossless)g(algorithm.)52 b(Consequen)m(tly)-8 b(,)35 b(\015oating)g(p)s(oin)m(t)e(images)i(are)f(\014rst)f(quan)m (tized)h(in)m(to)h(scaled)g(in)m(teger)0 1280 y(pixel)26 b(v)-5 b(alues)25 b(\(and)g(th)m(us)g(thro)m(wing)h(a)m(w)m(a)m(y)h(m)m (uc)m(h)e(of)h(the)f(noise\))h(b)s(efore)f(b)s(eing)g(compressed)g (with)g(the)h(sp)s(eci\014ed)0 1393 y(algorithm)d(\(either)g(GZIP)-8 b(,)23 b(Rice,)i(or)d(HCOMPRESS\).)f(This)h(tec)m(hnique)h(pro)s(duces) e(m)m(uc)m(h)h(higher)g(compression)0 1506 y(factors)33 b(than)e(simply)g(using)g(the)h(GZIP)g(utilit)m(y)h(to)f(externally)h (compress)f(the)f(whole)h(FITS)f(\014le,)i(but)e(it)h(also)0 1619 y(means)d(that)h(the)g(original)g(\015oating)g(v)-5 b(alue)30 b(pixel)f(v)-5 b(alues)30 b(are)g(not)f(exactly)i(preserv)m (ed.)40 b(When)29 b(done)g(prop)s(erly)-8 b(,)0 1732 y(this)33 b(in)m(teger)h(scaling)f(tec)m(hnique)h(will)f(only)f (discard)h(the)f(insigni\014can)m(t)i(noise)f(while)g(still)g (preserving)f(all)i(the)0 1844 y(real)43 b(information)f(in)g(the)h (image.)77 b(The)42 b(amoun)m(t)g(of)h(precision)f(that)h(is)f (retained)h(in)e(the)i(pixel)f(v)-5 b(alues)43 b(is)0 1957 y(con)m(trolled)37 b(b)m(y)d(the)i("quan)m(tization)h(lev)m(el")g (parameter,)g(q.)54 b(Larger)35 b(v)-5 b(alues)36 b(of)f(q)f(will)i (result)f(in)f(compressed)0 2070 y(images)h(whose)e(pixels)h(more)f (closely)i(matc)m(h)g(the)e(\015oating)i(p)s(oin)m(t)e(pixel)h(v)-5 b(alues,)35 b(but)e(at)h(the)g(same)g(time)g(the)0 2183 y(amoun)m(t)j(of)f(compression)g(that)h(is)f(ac)m(hiev)m(ed)i(will)f(b) s(e)e(reduced.)58 b(Users)36 b(should)f(exp)s(erimen)m(t)i(with)e (di\013eren)m(t)0 2296 y(v)-5 b(alues)25 b(for)g(this)g(parameter)g(to) h(determine)f(the)g(optimal)h(v)-5 b(alue)25 b(that)h(preserv)m(es)f (all)h(the)f(useful)f(information)h(in)0 2409 y(the)k(image,)h(without) f(needlessly)g(preserving)f(all)h(the)g(\\noise")h(whic)m(h)e(will)h(h) m(urt)f(the)h(compression)f(e\016ciency)-8 b(.)0 2569 y(The)38 b(default)g(v)-5 b(alue)38 b(for)g(the)g(quan)m(tization)i (scale)g(factor)f(is)f(4.0,)j(whic)m(h)d(means)g(that)g(scaled)h(in)m (teger)h(pixel)0 2682 y(v)-5 b(alues)41 b(will)h(b)s(e)e(quan)m(tized)i (suc)m(h)f(that)h(the)f(di\013erence)h(b)s(et)m(w)m(een)f(adjacen)m(t)i (in)m(teger)f(v)-5 b(alues)42 b(will)f(b)s(e)g(1/4th)0 2795 y(of)35 b(the)h(noise)f(lev)m(el)i(in)e(the)g(image)h(bac)m (kground.)55 b(CFITSIO)34 b(uses)g(an)h(optimized)h(algorithm)g(to)g (accurately)0 2908 y(estimate)41 b(the)e(noise)h(in)f(the)g(image.)68 b(As)39 b(an)g(example,)k(if)c(the)g(RMS)g(noise)g(in)g(the)h(bac)m (kground)e(pixels)i(of)0 3021 y(an)35 b(image)h(=)f(32.0,)j(then)d(the) h(spacing)f(b)s(et)m(w)m(een)h(adjacen)m(t)g(scaled)g(in)m(teger)h (pixel)e(v)-5 b(alues)36 b(will)f(equal)h(8.0)g(b)m(y)0 3134 y(default.)63 b(Note)38 b(that)h(the)e(RMS)h(noise)g(is)f(indep)s (enden)m(tly)g(calculated)j(for)d(eac)m(h)i(tile)f(of)g(the)g(image,)j (so)d(the)0 3247 y(resulting)24 b(in)m(teger)i(scaling)f(factor)g(ma)m (y)g(\015uctuate)g(sligh)m(tly)g(for)f(eac)m(h)i(tile.)40 b(In)23 b(some)i(cases)g(it)f(ma)m(y)h(b)s(e)f(desirable)0 3360 y(to)29 b(sp)s(ecify)f(the)h(exact)h(quan)m(tization)h(lev)m(el)f (to)f(b)s(e)f(used,)g(instead)h(of)g(sp)s(ecifying)f(it)h(relativ)m(e)i (to)e(the)g(calculated)0 3472 y(noise)e(v)-5 b(alue.)40 b(This)27 b(ma)m(y)g(b)s(e)g(done)f(b)m(y)h(sp)s(ecifying)g(the)g (negativ)m(e)i(of)f(desired)e(quan)m(tization)j(lev)m(el)g(for)d(the)h (v)-5 b(alue)0 3585 y(of)29 b(q.)40 b(In)28 b(the)i(previous)e (example,)i(one)f(could)g(sp)s(ecify)g(q)g(=)f(-8.0)j(so)e(that)h(the)f (quan)m(tized)g(in)m(teger)i(lev)m(els)f(di\013er)0 3698 y(b)m(y)k(exactly)j(8.0.)54 b(Larger)35 b(negativ)m(e)i(v)-5 b(alues)35 b(for)f(q)h(means)f(that)h(the)g(lev)m(els)h(are)f(more)g (coarsely)h(spaced,)g(and)0 3811 y(will)31 b(pro)s(duce)e(higher)h (compression)g(factors.)0 3971 y(When)h(\015oating)g(p)s(oin)m(t)g (images)h(are)f(b)s(eing)g(quan)m(tized,)h(one)f(m)m(ust)g(also)h(sp)s (ecify)e(what)h(quan)m(tization)h(metho)s(d)0 4084 y(is)g(to)h(b)s(e)e (used.)44 b(The)32 b(default)g(algorithm)g(is)g(called)h(\\SUBTRA)m (CTIVE)p 2567 4084 28 4 v 33 w(DITHER)p 2965 4084 V 33 w(1".)46 b(A)32 b(second)g(v)-5 b(ariation)0 4197 y(called)30 b(\\SUBTRA)m(CTIVE)p 982 4197 V 33 w(DITHER)p 1380 4197 V 33 w(2")g(is)f(also)h(a)m(v)-5 b(ailable,)32 b(whic)m(h)d(do)s(es)g (the)h(same)f(thing)h(except)g(that)g(an)m(y)0 4310 y(pixels)g(with)g (a)g(v)-5 b(alue)31 b(of)f(0.0)h(are)f(not)g(dithered)g(and)f(instead)h (the)g(zero)h(v)-5 b(alues)30 b(are)h(exactly)g(preserv)m(ed)f(in)g (the)0 4423 y(compressed)e(image.)41 b(This)27 b(is)h(in)m(tended)f (for)h(the)g(sp)s(ecial)g(case)h(where)f(\\bad)f(pixels")i(in)e(the)h (image)i(ha)m(v)m(e)f(b)s(een)0 4536 y(arti\014cally)k(set)f(to)g(zero) g(to)h(indicate)f(that)g(they)g(ha)m(v)m(e)h(no)e(v)-5 b(alid)32 b(v)-5 b(alue.)44 b(It)32 b(is)f(not)h(curren)m(tly)g(supp)s (orted)d(with)0 4649 y(HCOMPRESS,)h(and)h(if)g(requested)h(while)f (using)g(HCOMPRESS,)f(it)i(will)g(b)s(e)e(replaced)i(with)f(\\SUBTRA)m (C-)0 4762 y(TIVE)p 234 4762 V 32 w(DITHER)p 631 4762 V 33 w(1".)50 b(One)33 b(ma)m(y)h(also)g(turn)e(o\013)h(dithering)g (completely)i(with)e(the)h(\\NO)p 3151 4762 V 33 w(DITHER")f(option,)0 4875 y(but)d(this)g(is)g(not)h(recommended)f(b)s(ecause)g(it)h(can)g (cause)g(larger)g(systematic)h(errors)e(in)g(measuremen)m(ts)g(of)h (the)0 4988 y(p)s(osition)f(or)h(brigh)m(tness)f(of)g(ob)5 b(jects)32 b(in)e(the)g(compressed)g(image.)0 5148 y(There)37 b(are)g(3)h(metho)s(ds)e(for)h(sp)s(ecifying)g(all)h(the)g(parameters)f (needed)g(to)h(write)f(a)h(FITS)e(image)j(in)d(the)i(tile)0 5261 y(compressed)28 b(format.)41 b(The)28 b(parameters)g(ma)m(y)h (either)g(b)s(e)f(sp)s(eci\014ed)g(at)h(run)e(time)i(as)g(part)f(of)h (the)g(\014le)f(name)h(of)0 5373 y(the)e(output)f(compressed)h(FITS)e (\014le,)j(or)f(the)g(writing)f(program)h(ma)m(y)g(call)h(a)f(set)g(of) g(help)s(er)f(CFITSIO)f(subrou-)0 5486 y(tines)36 b(that)g(are)g(pro)m (vided)f(for)h(sp)s(ecifying)f(the)h(parameter)g(v)-5 b(alues,)37 b(or)f(\\compression)g(directiv)m(e")i(k)m(eyw)m(ords)0 5599 y(ma)m(y)c(b)s(e)e(added)h(to)g(the)h(header)f(of)g(eac)m(h)h (image)h(HDU)e(to)h(sp)s(ecify)f(the)g(compression)g(parameters.)50 b(These)33 b(3)0 5712 y(metho)s(ds)d(are)g(describ)s(ed)g(b)s(elo)m(w.) p eop end %%Page: 50 58 TeXDict begin 50 57 bop 0 299 a Fj(50)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(1\))23 b(A)m(t)g(run)e(time,)k(when)c(sp)s (ecifying)h(the)h(name)f(of)g(the)h(output)f(FITS)f(\014le)i(to)g(b)s (e)e(created,)k(the)e(user)e(can)i(indicate)0 668 y(that)32 b(images)g(should)e(b)s(e)h(written)g(in)g(tile-compressed)i(format)e (b)m(y)h(enclosing)g(the)f(compression)h(parameters)0 781 y(in)e(square)g(brac)m(k)m(ets)i(follo)m(wing)g(the)e(ro)s(ot)h (disk)f(\014le)g(name)h(in)f(the)h(follo)m(wing)g(format:)191 1034 y Fe([compress)45 b(NAME)i(T1,T2;)f(q[z])h(QLEVEL,)e(s)j(HSCALE])0 1287 y Fj(where)191 1540 y Fe(NAME)142 b(=)47 b(algorithm)f(name:)94 b(GZIP,)46 b(Rice,)h(HCOMPRESS,)e(HSCOMPRSS)g(or)i(PLIO)620 1653 y(may)g(be)h(abbreviated)c(to)j(the)g(first)g(letter)f(\(or)h(HS)g (for)g(HSCOMPRESS\))191 1766 y(T1,T2)94 b(=)47 b(tile)g(dimension)e (\(e.g.)i(100,100)f(for)g(square)h(tiles)f(100)h(pixels)f(wide\))191 1879 y(QLEVEL)g(=)h(quantization)e(level)h(for)h(floating)f(point)g (FITS)h(images)191 1992 y(HSCALE)f(=)h(HCOMPRESS)f(scale)g(factor;)g (default)g(=)h(0)h(which)e(is)h(lossless.)0 2245 y Fj(Here)31 b(are)g(a)f(few)h(examples)f(of)h(this)f(extended)h(syn)m(tax:)191 2498 y Fe(myfile.fit[compress])185 b(-)48 b(use)f(the)g(default)e (compression)g(algorithm)g(\(Rice\))1432 2611 y(and)i(the)g(default)e (tile)i(size)g(\(row)f(by)i(row\))191 2837 y(myfile.fit[compress)42 b(G])48 b(-)f(use)g(the)g(specified)e(compression)g(algorithm;)191 2950 y(myfile.fit[compress)d(R])239 b(only)46 b(the)h(first)f(letter)h (of)g(the)g(algorithm)191 3062 y(myfile.fit[compress)42 b(P])239 b(should)46 b(be)h(given.)191 3175 y(myfile.fit[compress)42 b(H])191 3401 y(myfile.fit[compress)g(R)48 b(100,100])141 b(-)47 b(use)g(Rice)g(and)g(100)g(x)g(100)g(pixel)f(tiles)191 3627 y(myfile.fit[compress)c(R;)48 b(q)f(10.0])f(-)i(quantization)c (level)j(=)g(\(RMS-noise\))e(/)i(10.)191 3740 y(myfile.fit[compress)42 b(R;)48 b(qz)f(10.0])f(-)i(quantization)c(level)i(=)i(\(RMS-noise\))d (/)i(10.)1050 3853 y(also)g(use)g(the)f(SUBTRACTIVE_DITHER_2)d (quantization)h(method)191 3966 y(myfile.fit[compress)e(HS;)47 b(s)h(2.0])94 b(-)h(HSCOMPRESS)45 b(\(with)i(smoothing\))2005 4079 y(and)f(scale)h(=)g(2.0)g(*)h(RMS-noise)0 4332 y Fj(2\))29 b(Before)g(calling)g(the)f(CFITSIO)e(routine)i(to)h(write)f (the)g(image)h(header)f(k)m(eyw)m(ords)g(\(e.g.,)j(\014ts)p 3335 4332 28 4 v 32 w(create)p 3603 4332 V 34 w(image\))0 4445 y(the)37 b(programmer)g(can)g(call)i(the)e(routines)g(describ)s (ed)f(b)s(elo)m(w)h(to)h(sp)s(ecify)f(the)g(compression)g(algorithm)i (and)0 4558 y(the)g(tiling)h(pattern)f(that)g(is)g(to)g(b)s(e)f(used.) 65 b(There)38 b(are)i(routines)e(for)h(sp)s(ecifying)f(the)h(v)-5 b(arious)39 b(compression)0 4670 y(parameters)31 b(and)e(similar)i (routines)f(to)i(return)d(the)h(curren)m(t)h(v)-5 b(alues)30 b(of)h(the)f(parameters:)95 4924 y Fe(int)47 b (fits_set_compression_type\()o(fit)o(sfil)o(e)42 b(*fptr,)k(int)h (comptype,)e(int)i(*status\))95 5036 y(int)g (fits_set_tile_dim\(fitsfile)41 b(*fptr,)46 b(int)h(ndim,)f(long)h (*tilesize,)e(int)i(*status\))95 5149 y(int)g (fits_set_quantize_level\(fi)o(tsf)o(ile)41 b(*fptr,)46 b(float)h(qlevel,)f(int)h(*status\))95 5262 y(int)g (fits_set_quantize_method\(f)o(its)o(file)41 b(*fptr,)46 b(int)h(method,)f(int)h(*status\))95 5375 y(int)g (fits_set_quantize_dither\(f)o(its)o(file)41 b(*fptr,)46 b(int)h(dither,)f(int)h(*status\))95 5488 y(int)g (fits_set_dither_seed\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(seed,)g(int)f (*status\))95 5601 y(int)h(fits_set_dither_offset\(fit)o(sfi)o(le)42 b(*fptr,)k(int)h(offset,)e(int)i(*status\))95 5714 y(int)g (fits_set_lossy_int\(fitsfil)o(e)42 b(*fptr,)k(int)h(lossy_int,)e(int)i (*status\))p eop end %%Page: 51 59 TeXDict begin 51 58 bop 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 b(COMPRESSION)2567 b Fj(51)286 555 y Fe(this)47 b(forces)f(integer)g (image)g(to)h(be)h(converted)d(to)i(floats,)f(then)h(quantized)95 668 y(int)g(fits_set_huge_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(huge,)f(int)h(*status\);)286 781 y(this)g(should)f(be)h(called) f(when)h(the)g(compressed)e(image)h(size)h(is)g(more)g(than)f(4)i(GB.) 95 894 y(int)f(fits_set_hcomp_scale\(fitsf)o(ile)41 b(*fptr,)46 b(float)h(scale,)f(int)h(*status\))95 1007 y(int)g (fits_set_hcomp_smooth\(fits)o(fil)o(e)42 b(*fptr,)k(int)h(smooth,)f (int)h(*status\))668 1120 y(Set)g(smooth)f(=)i(1)f(to)g(apply)g (smoothing)e(when)i(uncompressing)d(the)j(image)95 1346 y(int)g(fits_get_compression_type\()o(fit)o(sfil)o(e)42 b(*fptr,)k(int)h(*comptype,)e(int)i(*status\))95 1458 y(int)g(fits_get_tile_dim\(fitsfile)41 b(*fptr,)46 b(int)h(ndim,)f (long)h(*tilesize,)e(int)i(*status\))95 1571 y(int)g (fits_get_quantize_level\(fi)o(tsf)o(ile)41 b(*fptr,)46 b(float)h(*level,)f(int)h(*status\))95 1684 y(int)g (fits_get_hcomp_scale\(fitsf)o(ile)41 b(*fptr,)46 b(float)h(*scale,)e (int)i(*status\))0 1956 y Fj(Sev)m(eral)33 b(sym)m(b)s(olic)f(constan)m (ts)h(are)f(de\014ned)e(for)i(use)f(as)h(the)g(v)-5 b(alue)33 b(of)f(the)f(`compt)m(yp)s(e')i(parameter:)44 b(GZIP)p 3802 1956 28 4 v 32 w(1,)0 2069 y(GZIP)p 227 2069 V 32 w(2,)j(RICE)p 604 2069 V 32 w(1,)f(HCOMPRESS)p 1333 2069 V 32 w(1)d(or)g(PLIO)p 1800 2069 V 32 w(1.)78 b(En)m(tering)43 b(NULL)g(for)g(compt)m(yp)s(e)g(will)g(turn)f(o\013)h(the)0 2182 y(tile-compression)32 b(and)e(cause)h(normal)f(FITS)g(images)h(to) g(b)s(e)f(written.)0 2342 y(There)20 b(are)g(also)i(de\014ned)d(sym)m (b)s(olic)h(constan)m(ts)i(for)e(the)g(quan)m(tization)i(metho)s(d:)36 b(\\SUBTRA)m(CTIVE)p 3507 2342 V 32 w(DITHER)p 3904 2342 V 33 w(1",)0 2455 y(\\SUBTRA)m(CTIVE)p 726 2455 V 33 w(DITHER)p 1124 2455 V 32 w(2",)c(and)e(\\NO)p 1664 2455 V 33 w(DITHER".)0 2615 y(3\))g(CFITSIO)e(will)i(uses)f(the)h(v)-5 b(alues)29 b(of)h(the)g(follo)m(wing)g(k)m(eyw)m(ords,)h(if)e(they)h (are)g(presen)m(t)f(in)g(the)h(header)f(of)h(the)0 2728 y(image)k(HDU,)g(to)g(determine)f(ho)m(w)g(to)h(compress)f(that)g(HDU.) h(These)f(k)m(eyw)m(ords)g(o)m(v)m(erride)i(an)m(y)e(compression)0 2841 y(parameters)e(that)g(w)m(ere)g(sp)s(eci\014ed)e(with)h(the)h (previous)f(2)g(metho)s(ds.)95 3112 y Fe(FZALGOR)94 b(-)47 b('RICE_1')f(,)h('GZIP_1',)f('GZIP_2',)f('HCOMPRESS_1',)f('PLIO_1',)h ('NONE')95 3225 y(FZTILE)142 b(-)47 b('ROW',)g('WHOLE',)e(or)i ('\(n,m\)')95 3338 y(FZQVALUE)f(-)h(float)g(value)f(\(default)g(=)h (4.0\))95 3451 y(FZQMETHD)f(-)h('SUBTRACTIVE_DITHER_1',)42 b('SUBTRACTIVE_DITHER_2',)f('NO_DITHER')95 3564 y(FZDTHRSD)46 b(-)h('CLOCK',)f('CHECKSUM',)f(1)i(-)h(10000)95 3677 y(FZINT2F)94 b(-)h(T,)47 b(or)h(F:)94 b(Convert)46 b(integers)g(to)h (floats,)f(then)g(quantize?)95 3790 y(FZHSCALE)g(-)h(float)g(value)f (\(default)g(=)h(0\).)95 b(Hcompress)45 b(scale)h(value.)0 4061 y Fj(No)23 b(sp)s(ecial)f(action)i(is)e(required)f(b)m(y)h(soft)m (w)m(are)i(when)d(read)h(tile-compressed)h(images)g(b)s(ecause)f(all)h (the)f(CFITSIO)0 4174 y(routines)35 b(that)g(read)g(normal)g (uncompressed)f(FITS)g(images)i(also)g(transparen)m(tly)g(read)e (images)j(in)d(the)h(tile-)0 4287 y(compressed)28 b(format;)h(CFITSIO)e (essen)m(tially)j(treats)f(the)f(binary)g(table)h(that)f(con)m(tains)i (the)e(compressed)g(tiles)0 4400 y(as)j(if)f(it)h(w)m(ere)g(an)f(IMA)m (GE)h(extension.)0 4560 y(The)f(follo)m(wing)i(2)e(routines)h(are)f(a)m (v)-5 b(ailable)33 b(for)d(compressing)h(or)f(or)g(decompressing)h(an)f (image:)95 4832 y Fe(int)47 b(fits_img_compress\(fitsfile)41 b(*infptr,)46 b(fitsfile)f(*outfptr,)g(int)i(*status\);)95 4945 y(int)g(fits_img_decompress)c(\(fitsfile)i(*infptr,)h(fitsfile)f (*outfptr,)h(int)g(*status\);)0 5216 y Fj(Before)30 b(calling)h(the)f (compression)f(routine,)h(the)g(compression)f(parameters)h(m)m(ust)f (\014rst)g(b)s(e)g(de\014ned)f(in)h(one)h(of)0 5329 y(the)e(3)h(w)m(a)m (y)g(describ)s(ed)e(in)h(the)g(previous)g(paragraphs.)39 b(There)28 b(is)g(also)h(a)f(routine)h(to)f(determine)h(if)f(the)g (curren)m(t)0 5442 y(HDU)j(con)m(tains)h(a)e(tile)i(compressed)e(image) i(\(it)f(returns)e(1)i(or)f(0\):)95 5714 y Fe(int)47 b(fits_is_compressed_image\(f)o(its)o(file)41 b(*fptr,)46 b(int)h(*status\);)p eop end %%Page: 52 60 TeXDict begin 52 59 bop 0 299 a Fj(52)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(A)g(small)g(example)g(program)f(called)i ('imcop)m(y')f(is)g(included)f(with)g(CFITSIO)f(that)i(can)f(b)s(e)g (used)g(to)h(compress)0 668 y(\(or)44 b(uncompress\))g(an)m(y)g(FITS)g (image.)83 b(This)43 b(program)h(can)h(b)s(e)e(used)h(to)g(exp)s (erimen)m(t)h(with)f(the)g(v)-5 b(arious)0 781 y(compression)30 b(options)h(on)f(existing)i(FITS)d(images)j(as)e(sho)m(wn)g(in)g(these) h(examples:)0 1085 y Fe(1\))95 b(imcopy)46 b(infile.fit)f ('outfile.fit[compress]')334 1310 y(This)i(will)f(use)h(the)g(default)f (compression)f(algorithm)g(\(Rice\))h(and)h(the)334 1423 y(default)f(tile)h(size)f(\(row)h(by)g(row\))0 1649 y(2\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(GZIP]')334 1875 y(This)47 b(will)f(use)h(the)g(GZIP)g(compression)e(algorithm)g (and)i(the)g(default)334 1988 y(tile)g(size)f(\(row)h(by)g(row\).)94 b(The)47 b(allowed)f(compression)f(algorithms)g(are)334 2101 y(Rice,)h(GZIP,)h(and)g(PLIO.)94 b(Only)46 b(the)h(first)g(letter) f(of)h(the)g(algorithm)334 2214 y(name)g(needs)f(to)h(be)g(specified.)0 2439 y(3\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(G)47 b(100,100]')334 2665 y(This)g(will)f(use)h(the)g(GZIP)g(compression)e (algorithm)g(and)i(100)g(X)g(100)g(pixel)334 2778 y(tiles.)0 3004 y(4\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(R)47 b(100,100;)f(qz)h(10.0]')334 3230 y(This)g(will)f(use)h(the)g(Rice)g (compression)e(algorithm,)g(100)h(X)i(100)f(pixel)334 3343 y(tiles,)f(and)h(quantization)e(level)h(=)h(RMSnoise)f(/)h(10.0)g (\(assuming)e(the)334 3456 y(input)h(image)h(has)g(a)g(floating)f (point)g(data)h(type\).)f(By)h(specifying)334 3569 y(qz)g(instead)f(of) h(q,)g(this)g(means)f(use)h(the)g(subtractive)e(dither2)334 3681 y(quantization)g(method.)0 3907 y(5\))95 b(imcopy)46 b(infile.fit)f(outfile.fit)334 4133 y(If)i(the)g(input)g(file)f(is)h (in)h(tile-compressed)43 b(format,)j(then)h(it)g(will)f(be)334 4246 y(uncompressed)f(to)i(the)g(output)f(file.)94 b(Otherwise,)45 b(it)i(simply)f(copies)334 4359 y(the)h(input)f(image)h(to)g(the)g (output)f(image.)0 4585 y(6\))95 b(imcopy)46 b ('infile.fit[1001:1500,20)o(01:2)o(500])o(')89 b(outfile.fit)334 4811 y(This)47 b(extracts)e(a)j(500)f(X)g(500)g(pixel)f(section)g(of)h (the)g(much)g(larger)334 4924 y(input)f(image)h(\(which)f(may)h(be)g (in)g(tile-compressed)d(format\).)93 b(The)334 5036 y(output)46 b(is)h(a)h(normal)e(uncompressed)e(FITS)j(image.)0 5262 y(7\))95 b(imcopy)46 b('infile.fit[1001:1500,20)o(01:2)o(500])o(')89 b(outfile.fit.gz)334 5488 y(Same)47 b(as)g(above,)f(except)g(the)h (output)f(file)h(is)g(externally)e(compressed)334 5601 y(using)h(the)h(gzip)g(algorithm.)p eop end %%Page: 53 61 TeXDict begin 53 60 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(53)0 555 y Ff(5.7)135 b(ASCI)t(I)45 b(and)f(Binary)h(T)-11 b(able)45 b(Routines)0 805 y Fj(These)36 b(routines)g(p)s(erform)f (read)i(and)e(write)i(op)s(erations)g(on)f(columns)g(of)h(data)g(in)f (FITS)g(ASCI)s(I)e(or)j(Binary)0 918 y(tables.)47 b(Note)33 b(that)g(in)e(the)i(follo)m(wing)g(discussions,)f(the)g(\014rst)g(ro)m (w)g(and)f(column)h(in)g(a)g(table)h(is)g(at)f(p)s(osition)h(1)0 1031 y(not)e(0.)0 1191 y(Users)k(should)g(also)i(read)e(the)h(follo)m (wing)h(c)m(hapter)g(on)e(the)h(CFITSIO)e(iterator)j(function)f(whic)m (h)f(pro)m(vides)h(a)0 1304 y(more)i(`ob)5 b(ject)39 b(orien)m(ted')g(metho)s(d)f(of)g(reading)g(and)g(writing)g(table)h (columns.)63 b(The)37 b(iterator)j(function)d(is)i(a)0 1417 y(little)e(more)f(complicated)h(to)f(use,)h(but)e(the)g(adv)-5 b(an)m(tages)38 b(are)d(that)i(it)f(usually)f(tak)m(es)i(less)e(co)s (de)h(to)g(p)s(erform)0 1530 y(the)h(same)f(op)s(eration,)j(and)c(the)i (resulting)f(program)g(often)h(runs)e(faster)i(b)s(ecause)f(the)g(FITS) g(\014les)g(are)h(read)0 1643 y(and)30 b(written)g(using)g(the)h(most)f (e\016cien)m(t)i(blo)s(c)m(k)f(size.)0 1930 y Fd(5.7.1)112 b(Create)38 b(New)f(T)-9 b(able)0 2136 y Fi(1)81 b Fj(Create)40 b(a)f(new)g(ASCI)s(I)e(or)i(bin)m(table)h(table)g(extension.)68 b(If)39 b(the)g(FITS)g(\014le)g(is)g(curren)m(tly)g(empt)m(y)h(then)f (a)227 2249 y(dumm)m(y)25 b(primary)f(arra)m(y)i(will)g(b)s(e)f (created)i(b)s(efore)e(app)s(ending)f(the)i(table)g(extension)h(to)f (it.)40 b(The)25 b(tblt)m(yp)s(e)227 2361 y(parameter)39 b(de\014nes)e(the)h(t)m(yp)s(e)h(of)f(table)h(and)e(can)i(ha)m(v)m(e)g (v)-5 b(alues)39 b(of)f(ASCI)s(I)p 2924 2361 28 4 v 31 w(TBL)g(or)g(BINAR)-8 b(Y)p 3659 2361 V 34 w(TBL.)227 2474 y(The)29 b(naxis2)g(parameter)h(giv)m(es)g(the)g(initial)g(n)m(um) m(b)s(er)e(of)h(ro)m(ws)g(to)h(b)s(e)f(created)h(in)f(the)g(table,)h (and)f(should)227 2587 y(normally)h(b)s(e)f(set)h(=)g(0.)40 b(CFITSIO)29 b(will)h(automatically)i(increase)f(the)e(size)i(of)f(the) g(table)g(as)g(additional)227 2700 y(ro)m(ws)d(are)g(written.)40 b(A)27 b(non-zero)g(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g(ma)m(y)g(b)s(e)f (sp)s(eci\014ed)g(to)i(reserv)m(e)f(space)h(for)e(that)i(man)m(y)227 2813 y(ro)m(ws,)41 b(ev)m(en)e(if)g(a)g(few)m(er)g(n)m(um)m(b)s(er)e (of)i(ro)m(ws)f(will)h(b)s(e)f(written.)66 b(The)38 b(tunit)g(and)g (extname)i(parameters)227 2926 y(are)e(optional)g(and)f(a)h(n)m(ull)f (p)s(oin)m(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)h(if)g(they)f(are)h(not)f (de\014ned.)61 b(The)37 b(FITS)f(Standard)227 3039 y(recommends)29 b(that)h(only)g(letters,)h(digits,)g(and)e(the)g(underscore)g(c)m (haracter)i(b)s(e)e(used)g(in)g(column)g(names)227 3152 y(\(the)c(tt)m(yp)s(e)g(parameter\))g(with)e(no)h(em)m(b)s(edded)f (spaces.)40 b(T)-8 b(railing)24 b(blank)g(c)m(haracters)i(are)e(not)h (signi\014can)m(t.)95 3503 y Fe(int)47 b(fits_create_tbl)d(/)j(ffcrtb) 286 3616 y(\(fitsfile)f(*fptr,)g(int)h(tbltype,)e(LONGLONG)h(naxis2,)g (int)g(tfields,)g(char)h(*ttype[],)334 3729 y(char)g(*tform[],)e(char)i (*tunit[],)e(char)i(*extname,)e(int)i(*status\))0 3967 y Fi(2)81 b Fj(Cop)m(y)30 b(the)g(structure)f(of)i(an)f(op)s(en)f (table)i(to)g(a)f(new)g(table,)h(optionally)g(cop)m(ying)g(zero)g(or)f (more)g(ro)m(ws)g(from)227 4080 y(the)38 b(input)e(table.)61 b(This)37 b(is)g(useful)f(in)h(cases)h(where)f(a)g(task)h(will)f (\014lter)g(ro)m(ws)g(from)g(the)g(input)f(b)s(efore)227 4193 y(transferring)25 b(to)h(the)g(output,)g(so)g(a)f(\\pristine")h (output)f(table)i(with)e(zero)h(ro)m(ws)f(is)h(desired)f(to)h(start.)39 b(The)227 4306 y(input)29 b(\014le)h(m)m(ust)g(b)s(e)g(op)s(en)f(and)g (p)s(oin)m(t)i(to)f(a)h(binary)e(table)i(extension.)41 b(The)30 b(output)f(\014le)h(m)m(ust)g(b)s(e)g(op)s(en)227 4419 y(for)25 b(writing;)i(a)f(new)e(extension)i(is)f(created)i(with)d (the)i(same)f(table)h(structure)f(as)g(the)h(input.)38 b(Optionally)-8 b(,)227 4531 y(a)30 b(range)f(of)h(nro)m(ws)e(ma)m(y)i (b)s(e)e(copied)i(starting)g(from)e(\014rstro)m(w,)i(similar)f(to)h (\014ts)p 2952 4531 V 32 w(cop)m(y)p 3165 4531 V 34 w(ro)m(ws\(\).)41 b(The)28 b(v)-5 b(alue)227 4644 y(nro)m(ws)30 b(ma)m(y)h(b)s(e)f(0.)41 b(Note)32 b(that)f(the)f(\014rst)g(ro)m(w)g(in)g(a)h(table)g(is)g(at)g (ro)m(w)f(=)g(1.)95 4882 y Fe(int)47 b(fits_copy_hdutab)d(/)j(ffcpht) 286 4995 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(LONGLONG)h (firstrow,)334 5108 y(LONGLONG)g(nrows,)g(>)h(int)g(*status\))0 5396 y Fd(5.7.2)112 b(Column)39 b(Information)f(Routines)0 5601 y Fi(1)81 b Fj(Get)30 b(the)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(or) f(columns)g(in)h(the)g(curren)m(t)f(FITS)g(table.)41 b(The)29 b(n)m(um)m(b)s(er)f(of)i(ro)m(ws)g(is)f(giv)m(en)i(b)m(y)227 5714 y(the)j(NAXIS2)f(k)m(eyw)m(ord)h(and)e(the)i(n)m(um)m(b)s(er)e(of) h(columns)g(is)g(giv)m(en)h(b)m(y)f(the)h(TFIELDS)e(k)m(eyw)m(ord)i(in) f(the)p eop end %%Page: 54 62 TeXDict begin 54 61 bop 0 299 a Fj(54)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(header)g(of)h(the)g(table.)95 834 y Fe(int)47 b(fits_get_num_rows)c(/)48 b(ffgnrw)286 946 y(\(fitsfile)e(*fptr,)g(>)h(long)g(*nrows,)f(int)h(*status\);)95 1172 y(int)g(fits_get_num_rowsll)c(/)k(ffgnrwll)286 1285 y(\(fitsfile)f(*fptr,)g(>)h(LONGLONG)f(*nrows,)g(int)g(*status\);)95 1511 y(int)h(fits_get_num_cols)c(/)48 b(ffgncl)286 1624 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*ncols,)f(int)h(*status\);)0 1902 y Fi(2)81 b Fj(Get)25 b(the)f(table)i(column)e(n)m(um)m(b)s(er)f (\(and)h(name\))h(of)f(the)h(column)f(whose)g(name)g(matc)m(hes)i(an)e (input)g(template)227 2015 y(name.)48 b(If)32 b(casesen)i(=)e(CASESEN)g (then)g(the)h(column)f(name)h(matc)m(h)h(will)f(b)s(e)f(case-sensitiv)m (e,)k(whereas)227 2128 y(if)27 b(casesen)h(=)e(CASEINSEN)g(then)h(the)g (case)h(will)f(b)s(e)f(ignored.)40 b(As)27 b(a)g(general)h(rule,)f(the) g(column)g(names)227 2241 y(should)j(b)s(e)f(treated)j(as)e(case)i (INsensitiv)m(e.)227 2401 y(The)26 b(input)g(column)g(name)g(template)i (ma)m(y)f(b)s(e)f(either)h(the)g(exact)h(name)e(of)h(the)f(column)g(to) i(b)s(e)d(searc)m(hed)227 2514 y(for,)k(or)f(it)h(ma)m(y)g(con)m(tain)h (wild)e(card)g(c)m(haracters)i(\(*,)g(?,)f(or)f(#\),)h(or)f(it)h(ma)m (y)g(con)m(tain)h(the)e(in)m(teger)i(n)m(um)m(b)s(er)227 2626 y(of)j(the)f(desired)f(column)h(\(with)g(the)h(\014rst)e(column)h (=)g(1\).)46 b(The)32 b(`*')h(wild)f(card)g(c)m(haracter)h(matc)m(hes)h (an)m(y)227 2739 y(sequence)h(of)g(c)m(haracters)h(\(including)f(zero)g (c)m(haracters\))i(and)d(the)h(`?')53 b(c)m(haracter)36 b(matc)m(hes)g(an)m(y)f(single)227 2852 y(c)m(haracter.)42 b(The)29 b(#)h(wildcard)f(will)h(matc)m(h)h(an)m(y)e(consecutiv)m(e)j (string)e(of)f(decimal)i(digits)f(\(0-9\).)43 b(If)29 b(more)227 2965 y(than)43 b(one)f(column)h(name)f(in)g(the)h(table)h (matc)m(hes)f(the)g(template)h(string,)i(then)c(the)h(\014rst)e(matc)m (h)j(is)227 3078 y(returned)28 b(and)h(the)g(status)h(v)-5 b(alue)30 b(will)f(b)s(e)g(set)h(to)g(COL)p 2171 3078 28 4 v 32 w(NOT)p 2408 3078 V 32 w(UNIQUE)f(as)h(a)f(w)m(arning)g(that) h(a)g(unique)227 3191 y(matc)m(h)e(w)m(as)g(not)f(found.)39 b(T)-8 b(o)27 b(\014nd)f(the)h(other)g(cases)h(that)g(matc)m(h)g(the)g (template,)h(call)f(the)g(routine)f(again)227 3304 y(lea)m(ving)g(the)e (input)f(status)h(v)-5 b(alue)26 b(equal)f(to)h(COL)p 1950 3304 V 32 w(NOT)p 2187 3304 V 32 w(UNIQUE)f(and)f(the)h(next)h (matc)m(hing)g(name)f(will)227 3417 y(then)30 b(b)s(e)g(returned.)40 b(Rep)s(eat)30 b(this)h(pro)s(cess)f(un)m(til)g(a)h(status)g(=)f(COL)p 2628 3417 V 32 w(NOT)p 2865 3417 V 32 w(F)m(OUND)i(is)e(returned.)227 3576 y(The)36 b(FITS)g(Standard)g(recommends)g(that)i(only)e(letters,)k (digits,)f(and)d(the)h(underscore)f(c)m(haracter)j(b)s(e)227 3689 y(used)31 b(in)g(column)g(names)g(\(with)h(no)f(em)m(b)s(edded)f (spaces\).)45 b(T)-8 b(railing)32 b(blank)f(c)m(haracters)i(are)e(not)h (signi\014-)227 3802 y(can)m(t.)95 4081 y Fe(int)47 b(fits_get_colnum)d (/)j(ffgcno)286 4193 y(\(fitsfile)f(*fptr,)g(int)h(casesen,)e(char)i (*templt,)e(>)j(int)f(*colnum,)334 4306 y(int)g(*status\))95 4532 y(int)g(fits_get_colname)d(/)j(ffgcnn)286 4645 y(\(fitsfile)f (*fptr,)g(int)h(casesen,)e(char)i(*templt,)e(>)j(char)e(*colname,)334 4758 y(int)h(*colnum,)f(int)g(*status\))0 5036 y Fi(3)81 b Fj(Return)30 b(the)i(data)g(t)m(yp)s(e,)h(v)m(ector)g(rep)s(eat)f(v) -5 b(alue,)32 b(and)f(the)h(width)f(in)g(b)m(ytes)h(of)g(a)g(column)f (in)g(an)h(ASCI)s(I)e(or)227 5149 y(binary)35 b(table.)56 b(Allo)m(w)m(ed)37 b(v)-5 b(alues)36 b(for)f(the)h(data)g(t)m(yp)s(e)f (in)g(ASCI)s(I)f(tables)i(are:)51 b(TSTRING,)35 b(TSHOR)-8 b(T,)227 5262 y(TLONG,)36 b(TFLO)m(A)-8 b(T,)36 b(and)f(TDOUBLE.)i (Binary)e(tables)i(also)g(supp)s(ort)d(these)i(t)m(yp)s(es:)52 b(TLOGICAL,)227 5375 y(TBIT,)37 b(TBYTE,)f(TLONGLONG,)g(TCOMPLEX)g(and) g(TDBLCOMPLEX.)g(The)g(negativ)m(e)j(of)e(the)227 5488 y(data)29 b(t)m(yp)s(e)g(co)s(de)f(v)-5 b(alue)29 b(is)f(returned)f(if) h(it)h(is)f(a)h(v)-5 b(ariable)29 b(length)g(arra)m(y)f(column.)40 b(Note)30 b(that)f(in)e(the)i(case)227 5601 y(of)i(a)g('J')g(32-bit)i (in)m(teger)f(binary)e(table)h(column,)g(this)g(routine)g(will)g (return)f(data)h(t)m(yp)s(e)g(=)g(TINT32BIT)227 5714 y(\(whic)m(h)40 b(in)f(fact)h(is)f(equiv)-5 b(alen)m(t)41 b(to)f(TLONG\).)f(With)h(most)g(curren)m(t)f(C)g(compilers,)j(a)d(v)-5 b(alue)40 b(in)f(a)h('J')p eop end %%Page: 55 63 TeXDict begin 55 62 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(55)227 555 y(column)29 b(has)g(the)h(same)f(size)h(as)g(an)f('in)m (t')h(v)-5 b(ariable,)31 b(and)d(ma)m(y)i(not)g(b)s(e)e(equiv)-5 b(alen)m(t)31 b(to)f(a)g('long')g(v)-5 b(ariable,)227 668 y(whic)m(h)30 b(is)h(64-bits)g(long)g(on)g(an)f(increasing)h(n)m (um)m(b)s(er)e(of)h(compilers.)227 826 y(The)22 b('rep)s(eat')h (parameter)g(returns)f(the)g(v)m(ector)i(rep)s(eat)f(coun)m(t)g(on)f (the)h(binary)f(table)h(TF)m(ORMn)f(k)m(eyw)m(ord)227 939 y(v)-5 b(alue.)60 b(\(ASCI)s(I)35 b(table)j(columns)e(alw)m(a)m(ys) i(ha)m(v)m(e)g(rep)s(eat)e(=)g(1\).)60 b(The)36 b('width')g(parameter)h (returns)f(the)227 1052 y(width)30 b(in)g(b)m(ytes)h(of)g(a)f(single)h (column)g(elemen)m(t)h(\(e.g.,)g(a)f('10D')h(binary)e(table)h(column)f (will)h(ha)m(v)m(e)h(width)227 1165 y(=)d(8,)i(an)e(ASCI)s(I)f(table)i ('F12.2')i(column)e(will)g(ha)m(v)m(e)g(width)f(=)g(12,)i(and)e(a)h (binary)e(table'60A')k(c)m(haracter)227 1278 y(string)44 b(column)g(will)g(ha)m(v)m(e)h(width)e(=)h(60\);)52 b(Note)45 b(that)f(CFITSIO)f(supp)s(orts)f(the)i(lo)s(cal)h(con)m(v)m(en)m(tion) 227 1391 y(for)d(sp)s(ecifying)f(arra)m(ys)i(of)f(\014xed)f(length)h (strings)f(within)h(a)g(binary)f(table)h(c)m(haracter)i(column)d(using) 227 1504 y(the)g(syn)m(tax)g(TF)m(ORM)g(=)g('rAw')f(where)g('r')h(is)g (the)g(total)h(n)m(um)m(b)s(er)d(of)i(c)m(haracters)h(\(=)f(the)g (width)f(of)227 1617 y(the)f(column\))g(and)e('w')i(is)f(the)h(width)f (of)g(a)h(unit)f(string)g(within)g(the)h(column.)65 b(Th)m(us)37 b(if)h(the)h(column)227 1730 y(has)34 b(TF)m(ORM)h(=)f('60A12')j(then)d (this)g(means)g(that)h(eac)m(h)g(ro)m(w)g(of)f(the)h(table)g(con)m (tains)g(5)g(12-c)m(haracter)227 1843 y(substrings)23 b(within)h(the)g(60-c)m(haracter)j(\014eld,)f(and)d(th)m(us)h(in)g (this)g(case)h(this)g(routine)f(will)g(return)f(t)m(yp)s(eco)s(de)227 1955 y(=)f(TSTRING,)g(rep)s(eat)g(=)g(60,)j(and)d(width)f(=)h(12.)39 b(\(The)22 b(TDIMn)g(k)m(eyw)m(ord)h(ma)m(y)g(also)g(b)s(e)f(used)f(to) i(sp)s(ecify)227 2068 y(the)29 b(unit)e(string)h(length;)i(The)e(pair)g (of)g(k)m(eyw)m(ords)g(TF)m(ORMn)g(=)g('60A')i(and)e(TDIMn)f(=)h ('\(12,5\)')j(w)m(ould)227 2181 y(ha)m(v)m(e)g(the)f(same)g(e\013ect)h (as)e(TF)m(ORMn)h(=)f('60A12'\).)43 b(The)29 b(n)m(um)m(b)s(er)f(of)i (substrings)e(in)h(an)m(y)h(binary)f(table)227 2294 y(c)m(haracter)36 b(string)e(\014eld)f(can)h(b)s(e)g(calculated)i(b)m(y)d(\(rep)s (eat/width\).)53 b(A)34 b(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)h(b)s(e)e (giv)m(en)i(for)227 2407 y(an)m(y)c(of)g(the)f(output)g(parameters)h (that)g(are)g(not)f(needed.)227 2565 y(The)46 b(second)g(routine,)k (\014t)p 1188 2565 28 4 v 33 w(get)p 1341 2565 V 34 w(eqcolt)m(yp)s(e)d (is)f(similar)h(except)g(that)f(in)g(the)g(case)i(of)e(scaled)h(in)m (teger)227 2678 y(columns)35 b(it)g(returns)f(the)h('equiv)-5 b(alen)m(t')37 b(data)f(t)m(yp)s(e)f(that)h(is)f(needed)f(to)i(store)g (the)f(scaled)h(v)-5 b(alues,)37 b(and)227 2791 y(not)28 b(necessarily)h(the)f(ph)m(ysical)g(data)g(t)m(yp)s(e)g(of)g(the)g (unscaled)f(v)-5 b(alues)29 b(as)e(stored)h(in)g(the)f(FITS)g(table.)41 b(F)-8 b(or)227 2904 y(example)38 b(if)g(a)g('1I')g(column)f(in)g(a)h (binary)f(table)h(has)g(TSCALn)d(=)j(1)f(and)g(TZER)m(On)f(=)i(32768,)j (then)227 3017 y(this)29 b(column)f(e\013ectiv)m(ely)k(con)m(tains)d (unsigned)f(short)g(in)m(teger)i(v)-5 b(alues,)29 b(and)f(th)m(us)h (the)f(returned)g(v)-5 b(alue)29 b(of)227 3130 y(t)m(yp)s(eco)s(de)34 b(will)f(b)s(e)g(TUSHOR)-8 b(T,)32 b(not)h(TSHOR)-8 b(T.)33 b(Similarly)-8 b(,)34 b(if)f(a)h(column)f(has)f(TTYPEn)g(=)h('1I')h (and)227 3243 y(TSCALn)29 b(=)h(0.12,)i(then)e(the)h(returned)e(t)m(yp) s(eco)s(de)i(will)f(b)s(e)g(TFLO)m(A)-8 b(T.)95 3519 y Fe(int)47 b(fits_get_coltype)d(/)j(ffgtcl)286 3632 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e(long)h (*repeat,)334 3744 y(long)h(*width,)f(int)g(*status\))95 3970 y(int)h(fits_get_coltypell)c(/)48 b(ffgtclll)286 4083 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e (LONGLONG)g(*repeat,)334 4196 y(LONGLONG)h(*width,)f(int)i(*status\))95 4422 y(int)g(fits_get_eqcoltype)c(/)48 b(ffeqty)286 4535 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e(long)h (*repeat,)334 4648 y(long)h(*width,)f(int)g(*status\))95 4874 y(int)h(fits_get_eqcoltypell)c(/)k(ffeqtyll)286 4986 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e (LONGLONG)g(*repeat,)334 5099 y(LONGLONG)h(*width,)f(int)i(*status\))0 5375 y Fi(4)81 b Fj(Return)29 b(the)h(displa)m(y)g(width)f(of)h(a)h (column.)40 b(This)29 b(is)h(the)g(length)h(of)f(the)g(string)g(that)h (will)f(b)s(e)f(returned)g(b)m(y)227 5488 y(the)34 b(\014ts)p 514 5488 V 32 w(read)p 718 5488 V 33 w(col)g(routine)f(when)f(reading)h (the)h(column)e(as)i(a)f(formatted)h(string.)49 b(The)32 b(displa)m(y)i(width)227 5601 y(is)29 b(determined)g(b)m(y)g(the)g (TDISPn)f(k)m(eyw)m(ord,)i(if)f(presen)m(t,)h(otherwise)f(b)m(y)g(the)g (data)h(t)m(yp)s(e)f(of)h(the)f(column.)p eop end %%Page: 56 64 TeXDict begin 56 63 bop 0 299 a Fj(56)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_get_col_display_width)41 b(/)47 b(ffgcdw)286 668 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j (int)f(*dispwidth,)e(int)h(*status\))0 934 y Fi(5)81 b Fj(Return)27 b(the)i(n)m(um)m(b)s(er)e(of)i(and)e(size)j(of)e(the)h (dimensions)f(of)g(a)h(table)g(column)g(in)f(a)g(binary)g(table.)41 b(Normally)227 1047 y(this)28 b(information)h(is)f(giv)m(en)h(b)m(y)f (the)h(TDIMn)f(k)m(eyw)m(ord,)h(but)e(if)i(this)f(k)m(eyw)m(ord)g(is)g (not)h(presen)m(t)f(then)g(this)227 1160 y(routine)j(returns)e(naxis)h (=)g(1)h(and)f(naxes[0])h(equal)g(to)g(the)g(rep)s(eat)f(coun)m(t)h(in) f(the)h(TF)m(ORM)g(k)m(eyw)m(ord.)95 1427 y Fe(int)47 b(fits_read_tdim)d(/)k(ffgtdm)286 1539 y(\(fitsfile)e(*fptr,)g(int)h (colnum,)e(int)i(maxdim,)f(>)i(int)f(*naxis,)334 1652 y(long)g(*naxes,)f(int)g(*status\))95 1878 y(int)h(fits_read_tdimll)d (/)j(ffgtdmll)286 1991 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i (maxdim,)f(>)i(int)f(*naxis,)334 2104 y(LONGLONG)f(*naxes,)f(int)i (*status\))0 2370 y Fi(6)81 b Fj(Deco)s(de)33 b(the)g(input)f(TDIMn)h (k)m(eyw)m(ord)g(string)f(\(e.g.)50 b('\(100,200\)'\))37 b(and)32 b(return)g(the)h(n)m(um)m(b)s(er)e(of)i(and)f(size)227 2483 y(of)c(the)g(dimensions)f(of)h(a)g(binary)f(table)h(column.)40 b(If)27 b(the)h(input)f(tdimstr)g(c)m(haracter)i(string)f(is)g(n)m (ull,)g(then)227 2596 y(this)d(routine)f(returns)f(naxis)h(=)h(1)f(and) g(naxes[0])i(equal)e(to)i(the)e(rep)s(eat)h(coun)m(t)g(in)f(the)g(TF)m (ORM)h(k)m(eyw)m(ord.)227 2709 y(This)30 b(routine)g(is)h(called)g(b)m (y)f(\014ts)p 1350 2709 28 4 v 33 w(read)p 1555 2709 V 33 w(tdim.)95 2975 y Fe(int)47 b(fits_decode_tdim)d(/)j(ffdtdm)286 3088 y(\(fitsfile)f(*fptr,)g(char)g(*tdimstr,)g(int)h(colnum,)e(int)i (maxdim,)f(>)i(int)e(*naxis,)334 3201 y(long)h(*naxes,)f(int)g (*status\))95 3427 y(int)h(fits_decode_tdimll)c(/)48 b(ffdtdmll)286 3540 y(\(fitsfile)e(*fptr,)g(char)g(*tdimstr,)g(int)h (colnum,)e(int)i(maxdim,)f(>)i(int)e(*naxis,)334 3653 y(LONGLONG)g(*naxes,)f(int)i(*status\))0 3919 y Fi(7)81 b Fj(W)-8 b(rite)23 b(a)g(TDIMn)f(k)m(eyw)m(ord)h(whose)f(v)-5 b(alue)23 b(has)g(the)f(form)g('\(l,m,n...\)')40 b(where)22 b(l,)i(m,)g(n...)38 b(are)23 b(the)g(dimensions)227 4032 y(of)31 b(a)g(m)m(ultidimensional)g(arra)m(y)g(column)f(in)g(a)h (binary)e(table.)95 4298 y Fe(int)47 b(fits_write_tdim)d(/)j(ffptdm)286 4411 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h (*naxes,)f(>)h(int)g(*status\))95 4637 y(int)g(fits_write_tdimll)c(/)48 b(ffptdmll)286 4750 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(int)i (naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 5048 y Fd(5.7.3)112 b(Routines)38 b(to)f(Edit)g(Ro)m(ws)g(or)g(Columns) 0 5262 y Fi(1)81 b Fj(Insert)32 b(or)h(delete)i(ro)m(ws)e(in)g(an)g (ASCI)s(I)f(or)h(binary)f(table.)50 b(When)33 b(inserting)h(ro)m(ws)f (all)h(the)f(ro)m(ws)g(follo)m(wing)227 5375 y(ro)m(w)24 b(FR)m(O)m(W)i(are)e(shifted)f(do)m(wn)h(b)m(y)g(NR)m(O)m(WS)g(ro)m (ws;)j(if)c(FR)m(O)m(W)j(=)d(0)i(then)e(the)h(blank)g(ro)m(ws)g(are)g (inserted)227 5488 y(at)31 b(the)e(b)s(eginning)g(of)h(the)f(table.)42 b(Note)31 b(that)f(it)g(is)f(*not*)i(necessary)f(to)g(insert)f(ro)m(ws) h(in)f(a)h(table)g(b)s(efore)227 5601 y(writing)g(data)g(to)g(those)h (ro)m(ws)e(\(indeed,)h(it)g(w)m(ould)f(b)s(e)g(ine\016cien)m(t)i(to)f (do)g(so\).)41 b(Instead)29 b(one)h(ma)m(y)g(simply)227 5714 y(write)h(data)g(to)g(an)m(y)g(ro)m(w)f(of)h(the)f(table,)i (whether)e(that)h(ro)m(w)f(of)h(data)g(already)g(exists)g(or)f(not.)p eop end %%Page: 57 65 TeXDict begin 57 64 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(57)227 555 y(The)40 b(\014rst)g(delete)i(routine)e(deletes)i(NR)m (O)m(WS)f(consecutiv)m(e)h(ro)m(ws)f(starting)g(with)f(ro)m(w)g(FIRSTR) m(O)m(W.)227 668 y(The)d(second)g(delete)h(routine)f(tak)m(es)h(an)f (input)f(string)h(that)h(lists)f(the)g(ro)m(ws)g(or)g(ro)m(w)g(ranges)g (\(e.g.,)k('5-)227 781 y(10,12,20-30'\),)32 b(whereas)26 b(the)g(third)g(delete)h(routine)f(tak)m(es)h(an)f(input)f(in)m(teger)j (arra)m(y)e(that)h(sp)s(eci\014es)f(eac)m(h)227 894 y(individual)35 b(ro)m(w)h(to)g(b)s(e)f(deleted.)58 b(In)35 b(b)s(oth)f(latter)j (cases,)i(the)c(input)g(list)h(of)g(ro)m(ws)g(to)g(delete)h(m)m(ust)f (b)s(e)227 1007 y(sorted)i(in)g(ascending)g(order.)62 b(These)38 b(routines)f(up)s(date)g(the)h(NAXIS2)g(k)m(eyw)m(ord)h(to)f (re\015ect)g(the)g(new)227 1120 y(n)m(um)m(b)s(er)29 b(of)i(ro)m(ws)f(in)g(the)h(table.)95 1357 y Fe(int)47 b(fits_insert_rows)d(/)j(ffirow)286 1470 y(\(fitsfile)f(*fptr,)g (LONGLONG)f(firstrow,)h(LONGLONG)f(nrows,)h(>)i(int)f(*status\))95 1695 y(int)g(fits_delete_rows)d(/)j(ffdrow)286 1808 y(\(fitsfile)f (*fptr,)g(LONGLONG)f(firstrow,)h(LONGLONG)f(nrows,)h(>)i(int)f (*status\))95 2034 y(int)g(fits_delete_rowrange)c(/)k(ffdrrg)286 2147 y(\(fitsfile)f(*fptr,)g(char)g(*rangelist,)f(>)j(int)e(*status\)) 95 2373 y(int)h(fits_delete_rowlist)c(/)k(ffdrws)286 2486 y(\(fitsfile)f(*fptr,)g(long)g(*rowlist,)g(long)g(nrows,)g(>)i (int)f(*status\))95 2712 y(int)g(fits_delete_rowlistll)42 b(/)48 b(ffdrwsll)286 2824 y(\(fitsfile)e(*fptr,)g(LONGLONG)f (*rowlist,)h(LONGLONG)f(nrows,)h(>)i(int)f(*status\))0 3061 y Fi(2)81 b Fj(Insert)36 b(or)h(delete)i(column\(s\))e(in)g(an)g (ASCI)s(I)f(or)h(binary)f(table.)62 b(When)37 b(inserting,)i(COLNUM)e (sp)s(eci\014es)227 3174 y(the)28 b(column)g(n)m(um)m(b)s(er)f(that)h (the)g(\(\014rst\))g(new)f(column)h(should)f(o)s(ccup)m(y)h(in)g(the)g (table.)41 b(NCOLS)26 b(sp)s(eci\014es)227 3287 y(ho)m(w)35 b(man)m(y)g(columns)f(are)h(to)g(b)s(e)f(inserted.)53 b(An)m(y)35 b(existing)h(columns)e(from)g(this)h(p)s(osition)f(and)g (higher)227 3400 y(are)c(shifted)f(o)m(v)m(er)h(to)g(allo)m(w)g(ro)s (om)f(for)g(the)h(new)e(column\(s\).)41 b(The)29 b(index)f(n)m(um)m(b)s (er)g(on)h(all)h(the)f(follo)m(wing)227 3513 y(k)m(eyw)m(ords)34 b(will)f(b)s(e)g(incremen)m(ted)h(or)f(decremen)m(ted)h(if)f(necessary) h(to)g(re\015ect)g(the)f(new)g(p)s(osition)g(of)h(the)227 3626 y(column\(s\))26 b(in)f(the)h(table:)39 b(TBCOLn,)26 b(TF)m(ORMn,)h(TTYPEn,)e(TUNITn,)h(TNULLn,)g(TSCALn,)f(TZE-)227 3739 y(R)m(On,)43 b(TDISPn,)g(TDIMn,)g(TLMINn,)g(TLMAXn,)g(TDMINn,)g (TDMAXn,)h(TCTYPn,)e(TCRPXn,)227 3852 y(TCR)-10 b(VLn,)29 b(TCDL)-8 b(Tn,)30 b(TCR)m(OTn,)f(and)h(TCUNIn.)95 4089 y Fe(int)47 b(fits_insert_col)d(/)j(fficol)286 4201 y(\(fitsfile)f (*fptr,)g(int)h(colnum,)e(char)i(*ttype,)f(char)h(*tform,)334 4314 y(>)h(int)e(*status\))95 4540 y(int)h(fits_insert_cols)d(/)j (fficls)286 4653 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(ncols,)f (char)h(**ttype,)334 4766 y(char)g(**tform,)e(>)j(int)f(*status\))95 4992 y(int)g(fits_delete_col)d(/)j(ffdcol\(fitsfile)d(*fptr,)i(int)h (colnum,)f(>)h(int)g(*status\))0 5229 y Fi(3)81 b Fj(Cop)m(y)29 b(column\(s\))i(b)s(et)m(w)m(een)f(HDUs.)41 b(If)30 b(create)p 1783 5229 28 4 v 34 w(col)h(=)f(TR)m(UE,)g(then)f(new)h(column\(s\))g (will)g(b)s(e)g(inserted)f(in)227 5342 y(the)35 b(output)g(table,)i (starting)f(at)g(p)s(osition)f(`outcolumn',)i(otherwise)f(the)f (existing)h(output)f(column\(s\))227 5455 y(will)c(b)s(e)f(o)m(v)m (erwritten)i(\(in)e(whic)m(h)g(case)h(they)g(m)m(ust)f(ha)m(v)m(e)i(a)f (compatible)g(data)g(t)m(yp)s(e\).)227 5601 y(The)43 b(\014rst)f(form)g(copies)i(a)f(single)h(column)e(incoln)m(um)h(to)h (outcoln)m(um.)79 b(Cop)m(ying)43 b(within)f(the)i(same)227 5714 y(HDU)29 b(is)f(p)s(ermitted.)39 b(The)27 b(second)h(form)f (copies)i(ncols)f(columns)f(from)h(the)g(input,)f(starting)i(at)f (column)p eop end %%Page: 58 66 TeXDict begin 58 65 bop 0 299 a Fj(58)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(incoln)m(um)k(to)h(the)f(output,)h(starting) g(at)g(outcoln)m(um.)52 b(F)-8 b(or)35 b(the)g(second)f(form,)g(the)h (input)e(and)g(output)227 668 y(m)m(ust)e(b)s(e)e(di\013eren)m(t)i (HDUs.)227 826 y(If)21 b(outcoln)m(um)h(is)f(greater)i(than)d(the)i(n)m (um)m(b)s(er)e(of)h(column)g(in)g(the)h(output)e(table,)25 b(then)20 b(the)i(new)f(column\(s\))227 939 y(will)32 b(b)s(e)f(app)s(ended)f(to)j(the)f(end)f(of)g(the)h(table.)46 b(Note)33 b(that)f(the)g(\014rst)f(column)g(in)h(a)g(table)g(is)g(at)h (coln)m(um)227 1052 y(=)h(1.)51 b(The)33 b(standard)g(indexed)g(k)m (eyw)m(ords)h(that)g(related)h(to)f(the)g(columns)g(\(e.g.,)i(TDISPn,)e (TUNITn,)227 1165 y(TCRPXn,)c(TCDL)-8 b(Tn,)29 b(etc.\))43 b(will)30 b(also)i(b)s(e)d(copied.)95 1440 y Fe(int)47 b(fits_copy_col)e(/)i(ffcpcl)286 1553 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(int)i(incolnum,)e(int)i(outcolnum,)334 1666 y(int)g(create_col,)e(>)i(int)g(*status\);)95 1892 y(int)g(fits_copy_cols)d(/)k(ffccls)286 2005 y(\(fitsfile)e(*infptr,)f (fitsfile)h(*outfptr,)f(int)i(incolnum,)e(int)i(outcolnum,)334 2117 y(int)g(ncols,)f(int)h(create_col,)e(>)i(int)g(*status\);)0 2393 y Fi(4)81 b Fj(Cop)m(y)30 b('nro)m(ws')g(consecutiv)m(e)j(ro)m(ws) d(from)g(one)h(table)g(to)g(another,)g(b)s(eginning)f(with)g(ro)m(w)g ('\014rstro)m(w'.)41 b(These)227 2505 y(ro)m(ws)31 b(will)h(b)s(e)e (app)s(ended)g(to)i(an)m(y)f(existing)h(ro)m(ws)g(in)e(the)i(output)e (table.)44 b(Note)33 b(that)f(the)f(\014rst)f(ro)m(w)i(in)f(a)227 2618 y(table)h(is)e(at)h(ro)m(w)g(=)f(1.)227 2776 y(The)44 b Fe(fits_copy_selrows)39 b Fj(form)44 b(copies)h(only)f(selected)h(ro) m(ws)f(to)h(the)g(output.)81 b(Whic)m(h)44 b(ro)m(ws)h(are)227 2889 y(transferred)37 b(is)g(determined)h(b)m(y)f(an)g(arra)m(y)h(of)g (\015ags,)i Fe(row_status[])p Fj(,)c(whic)m(h)h(could)h(b)s(e)f (returned)f(b)m(y)227 3002 y Fe(fits_find_rows\(\))16 b Fj(or)k(constructed)h(b)m(y)f(the)h(user.)36 b(FITS)20 b(ro)m(w)g(N)h(is)f(copied)h(if)f Fe(row_status[N-first_row])227 3115 y Fj(is)31 b(non-zero.)95 3390 y Fe(int)47 b(fits_copy_rows)d(/)k (ffcprw)286 3503 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f (LONGLONG)h(firstrow,)334 3616 y(LONGLONG)g(nrows,)g(>)h(int)g (*status\);)95 3842 y(int)g(fits_copy_selrows)c(/)48 b(ffcpsr)286 3955 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f (LONGLONG)h(firstrow,)334 4068 y(LONGLONG)g(nrows,)g(char)g (*row_status,)f(>)i(int)g(*status\);)0 4343 y Fi(5)81 b Fj(Mo)s(dify)37 b(the)g(v)m(ector)i(length)f(of)f(a)h(binary)e(table) i(column)f(\(e.g.,)k(c)m(hange)e(a)e(column)g(from)g(TF)m(ORMn)g(=)227 4456 y('1E')31 b(to)h('20E'\).)g(The)e(v)m(ector)i(length)e(ma)m(y)h(b) s(e)f(increased)h(or)f(decreased)h(from)f(the)g(curren)m(t)h(v)-5 b(alue.)95 4731 y Fe(int)47 b(fits_modify_vector_len)42 b(/)48 b(ffmvec)286 4844 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e (LONGLONG)h(newveclen,)f(>)i(int)g(*status\))0 5153 y Fd(5.7.4)112 b(Read)38 b(and)h(W)-9 b(rite)36 b(Column)j(Data)e (Routines)0 5375 y Fj(The)e(follo)m(wing)h(routines)g(write)f(or)g (read)g(data)h(v)-5 b(alues)36 b(in)f(the)g(curren)m(t)g(ASCI)s(I)f(or) h(binary)g(table)h(extension.)0 5488 y(If)d(a)g(write)g(op)s(eration)h (extends)f(b)s(ey)m(ond)f(the)h(curren)m(t)g(size)h(of)f(the)g(table,)i (then)e(the)g(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g(in)g(the)0 5601 y(table)i(will)g(automatically)i(b)s(e)c(increased)i(and)e(the)i (NAXIS2)f(k)m(eyw)m(ord)h(v)-5 b(alue)35 b(will)f(b)s(e)g(up)s(dated.) 51 b(A)m(ttempts)0 5714 y(to)31 b(read)f(b)s(ey)m(ond)g(the)h(end)e(of) i(the)f(table)i(will)e(result)h(in)f(an)g(error.)p eop end %%Page: 59 67 TeXDict begin 59 66 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(59)0 555 y(Automatic)37 b(data)e(t)m(yp)s(e)g(con)m(v)m(ersion)i (is)e(p)s(erformed)e(for)i(n)m(umerical)g(data)h(t)m(yp)s(es)f (\(only\))h(if)f(the)g(data)h(t)m(yp)s(e)f(of)0 668 y(the)43 b(column)f(\(de\014ned)f(b)m(y)h(the)h(TF)m(ORMn)f(k)m(eyw)m(ord\))h (di\013ers)f(from)g(the)g(data)h(t)m(yp)s(e)g(of)f(the)h(arra)m(y)g(in) f(the)0 781 y(calling)k(routine.)84 b(ASCI)s(I)43 b(and)h(binary)g (tables)h(supp)s(ort)e(the)i(follo)m(wing)h(data)f(t)m(yp)s(e)g(v)-5 b(alues:)70 b(TSTRING,)0 894 y(TBYTE,)35 b(TSBYTE,)f(TSHOR)-8 b(T,)33 b(TUSHOR)-8 b(T,)34 b(TINT,)h(TUINT,)f(TLONG,)g(TLONGLONG,)h (TULONG,)0 1007 y(TULONGLONG,)42 b(TFLO)m(A)-8 b(T,)43 b(or)f(TDOUBLE.)h(Binary)f(tables)h(also)g(supp)s(ort)d(TLOGICAL)i (\(in)m(ternally)0 1120 y(mapp)s(ed)29 b(to)i(the)g(`c)m(har')g(data)g (t)m(yp)s(e\),)g(TCOMPLEX,)f(and)g(TDBLCOMPLEX.)0 1280 y(Note)c(that)g(it)g(is)f(*not*)h(necessary)f(to)h(insert)f(ro)m(ws)g (in)g(a)g(table)h(b)s(efore)f(writing)g(data)h(to)g(those)f(ro)m(ws)g (\(indeed,)h(it)0 1393 y(w)m(ould)h(b)s(e)g(ine\016cien)m(t)i(to)f(do)f (so\).)41 b(Instead,)28 b(one)g(ma)m(y)g(simply)f(write)g(data)h(to)h (an)m(y)e(ro)m(w)h(of)g(the)f(table,)j(whether)0 1506 y(that)h(ro)m(w)f(of)h(data)g(already)g(exists)g(or)f(not.)0 1666 y(Individual)g(bits)i(in)f(a)h(binary)e(table)i('X')g(or)g('B')g (column)f(ma)m(y)h(b)s(e)f(read/written)h(to/from)g(a)g(*c)m(har)g (arra)m(y)g(b)m(y)0 1779 y(sp)s(ecifying)k(the)f(TBIT)h(datat)m(yp)s (e.)57 b(The)35 b(*c)m(har)i(arra)m(y)f(will)g(b)s(e)f(in)m(terpreted)h (as)g(an)g(arra)m(y)g(of)g(logical)i(TR)m(UE)0 1892 y(\(1\))d(or)g(F) -10 b(ALSE)34 b(\(0\))h(v)-5 b(alues)35 b(that)g(corresp)s(ond)e(to)i (the)g(v)-5 b(alue)35 b(of)f(eac)m(h)i(bit)e(in)g(the)h(FITS)e('X')i (or)g('B')g(column.)0 2005 y(Alternativ)m(ely)-8 b(,)30 b(the)c(v)-5 b(alues)27 b(in)e(a)i(binary)e(table)i('X')g(column)f(ma)m (y)h(b)s(e)e(read/written)i(8)f(bits)g(at)h(a)f(time)h(to/from)0 2118 y(an)j(arra)m(y)h(of)g(8-bit)g(in)m(tegers)g(b)m(y)g(sp)s (ecifying)f(the)h(TBYTE)f(datat)m(yp)s(e.)0 2278 y(Note)25 b(that)g(within)e(the)h(con)m(text)i(of)e(these)g(routines,)i(the)e (TSTRING)f(data)h(t)m(yp)s(e)g(corresp)s(onds)f(to)h(a)h(C)e('c)m (har**')0 2391 y(data)35 b(t)m(yp)s(e,)h(i.e.,)h(a)e(p)s(oin)m(ter)f (to)i(an)e(arra)m(y)h(of)g(p)s(oin)m(ters)f(to)h(an)g(arra)m(y)g(of)g (c)m(haracters.)54 b(This)34 b(is)g(di\013eren)m(t)h(from)0 2503 y(the)d(k)m(eyw)m(ord)h(reading)f(and)f(writing)h(routines)g (where)g(TSTRING)f(corresp)s(onds)g(to)h(a)h(C)e('c)m(har*')j(data)f(t) m(yp)s(e,)0 2616 y(i.e.,)g(a)e(single)h(p)s(oin)m(ter)f(to)h(an)f(arra) m(y)g(of)g(c)m(haracters.)45 b(When)30 b(reading)i(strings)e(from)h(a)g (table,)i(the)e(c)m(har)h(arra)m(ys)0 2729 y(ob)m(viously)h(m)m(ust)f (ha)m(v)m(e)h(b)s(een)f(allo)s(cated)i(long)f(enough)e(to)i(hold)f(the) h(whole)f(FITS)f(table)i(string.)46 b(See)33 b(section)0 2842 y(4.5)e(\(\\Dealing)i(with)d(Character)h(Strings"\))g(for)f(more)g (information.)0 3002 y(F)-8 b(or)41 b(complex)g(and)f(double)g(complex) h(data)g(t)m(yp)s(es,)j Fe(nelements)38 b Fj(is)i(the)h(n)m(um)m(b)s (er)e(of)h(n)m(umerical)h(pairs;)46 b(the)0 3115 y(n)m(um)m(b)s(er)29 b(of)i(\015oats)g(or)f(doubles)g(stored)g(b)m(y)g(arra)m(y+)h(m)m(ust)f (b)s(e)g Fe(2*nelements)p Fj(.)0 3275 y(F)-8 b(or)38 b(the)g(logical)i(data)e(\(TLOGICAL\),)g(the)g(C)f(storage)i(t)m(yp)s (e)f(is)f(a)h Fe(char)f Fj(single-b)m(yte)i(c)m(haracter.)64 b(A)38 b(FITS)0 3388 y(v)-5 b(alue)28 b(of)g(`)p Fe(T)p Fj('rue)g(reads)f(as)h(1)g(and)f(`)p Fe(F)p Fj(')h(reads)g(as)g(0;)h (other)f(non-FITS)f(c)m(haracters)i(are)f(preserv)m(ed)g(un)m (translated.)0 3548 y(Numerical)33 b(data)g(v)-5 b(alues)33 b(are)g(automatically)j(scaled)d(b)m(y)f(the)h(TSCALn)e(and)h(TZER)m (On)f(k)m(eyw)m(ord)i(v)-5 b(alues)33 b(\(if)0 3661 y(they)e(exist\).)0 3822 y(In)36 b(the)h(case)h(of)f(binary)f(tables)i(with)f(v)m(ector)h (elemen)m(ts,)i(the)d Fe(firstelem)e Fj(parameter)i(de\014nes)f(the)h (starting)0 3934 y(elemen)m(t)28 b(\(b)s(eginning)e(with)g(1,)i(not)e (0\))h(within)f(the)h(cell)g(\(a)h(cell)f(is)g(de\014ned)e(as)h(the)h (in)m(tersection)h(of)f(a)f(ro)m(w)h(and)f(a)0 4047 y(column)h(and)g (ma)m(y)h(con)m(tain)g(a)g(single)g(v)-5 b(alue)28 b(or)f(a)h(v)m (ector)g(of)g(v)-5 b(alues\).)40 b(The)27 b Fe(firstelem)e Fj(parameter)i(is)h(ignored)0 4160 y(when)i(dealing)i(with)f(ASCI)s(I)f (tables.)45 b(Similarly)-8 b(,)32 b(in)f(the)h(case)g(of)g(binary)e (tables)i(the)g('nelemen)m(ts')g(parameter)0 4273 y(sp)s(eci\014es)e (the)g(total)i(n)m(um)m(b)s(er)c(of)i(v)m(ector)i(v)-5 b(alues)30 b(to)h(b)s(e)e(read)h(or)g(written)g(\(con)m(tin)m(uing)i (on)e(subsequen)m(t)f(ro)m(ws)h(if)0 4386 y(required\))g(and)g(not)g (the)h(n)m(um)m(b)s(er)e(of)h(table)i(cells.)0 4655 y Fi(1)81 b Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(an)g(ASCI)s(I)e (or)h(binary)f(table)j(column.)0 4924 y(The)38 b(\014rst)f(routine)h (simply)g(writes)g(the)g(arra)m(y)h(of)f(v)-5 b(alues)39 b(to)g(the)f(FITS)g(\014le)g(\(doing)g(data)h(t)m(yp)s(e)g(con)m(v)m (ersion)0 5036 y(if)h(necessary\))h(whereas)f(the)h(second)f(routine)h (will)f(substitute)h(the)f(appropriate)g(FITS)g(n)m(ull)g(v)-5 b(alue)41 b(for)f(all)0 5149 y(elemen)m(ts)34 b(whic)m(h)f(are)g(equal) h(to)f(the)g(input)f(v)-5 b(alue)34 b(of)f(n)m(ulv)-5 b(al)33 b(\(note)h(that)f(this)g(parameter)g(giv)m(es)i(the)e(address)0 5262 y(of)40 b(n)m(ulv)-5 b(al,)44 b(not)c(the)g(n)m(ull)g(v)-5 b(alue)41 b(itself)7 b(\).)72 b(F)-8 b(or)40 b(in)m(teger)i(columns)e (the)g(FITS)g(n)m(ull)g(v)-5 b(alue)40 b(is)h(de\014ned)e(b)m(y)h(the)0 5375 y(TNULLn)32 b(k)m(eyw)m(ord)i(\(an)g(error)e(is)i(returned)e(if)h (the)h(k)m(eyw)m(ord)f(do)s(esn't)g(exist\).)51 b(F)-8 b(or)34 b(\015oating)g(p)s(oin)m(t)f(columns)0 5488 y(the)h(sp)s(ecial) h(IEEE)f(NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)35 b(will)f(b)s(e)g(written)g(in)m(to)i(the)e(FITS)g(\014le.)52 b(If)34 b(a)h(n)m(ull)f(p)s(oin)m(ter)0 5601 y(is)f(en)m(tered)g(for)g (n)m(ulv)-5 b(al,)34 b(then)f(the)g(n)m(ull)g(v)-5 b(alue)33 b(is)g(ignored)g(and)g(this)g(routine)f(b)s(eha)m(v)m(es)i(the)f(same)g (as)h(the)f(\014rst)0 5714 y(routine.)41 b(The)29 b(third)g(routine)h (simply)f(writes)h(unde\014ned)d(pixel)k(v)-5 b(alues)30 b(to)g(the)g(column.)41 b(The)29 b(fourth)g(routine)p eop end %%Page: 60 68 TeXDict begin 60 67 bop 0 299 a Fj(60)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(\014lls)d(ev)m(ery)i(column)e(in)h(the)g (table)g(with)g(n)m(ull)f(v)-5 b(alues,)29 b(in)e(the)h(sp)s(eci\014ed) f(ro)m(ws)h(\(ignoring)g(an)m(y)g(columns)g(that)g(do)0 668 y(not)j(ha)m(v)m(e)g(a)g(de\014ned)e(n)m(ull)h(v)-5 b(alue\).)0 828 y(The)36 b Fe(fits_write_cols\(\))c Fj(v)-5 b(arian)m(t)38 b(writes)e(m)m(ultiple)i(columns)e(in)g(a)h(single)g (pass,)h(whic)m(h)f(ma)m(y)g(b)s(e)f(signi\014-)0 941 y(can)m(tly)c(faster)e(for)g(large)i(data)f(\014les.)40 b(The)30 b(\\c)m(h)m(unk")h(size)g(is)g(determined)e(automatically)34 b(based)c(up)s(on)e(CFIT-)0 1054 y(SIO's)23 b(bu\013er)h(sizes.)39 b(Only)24 b(whole)g(ro)m(ws)g(can)h(b)s(e)f(written,)i(of)e(an)m(y)h(t) m(yp)s(e)f(except)h(TBIT)f(or)g(TSTRING.)g(F)-8 b(or)25 b(this)0 1167 y(v)-5 b(arian)m(t,)36 b(datat)m(yp)s(e,)g(coln)m(um,)f (arra)m(y)f(and)f(n)m(ulv)-5 b(al)34 b(are)h(arra)m(ys)f(of)g(the)g (equiv)-5 b(alen)m(t)35 b(single-column)f(parameter)0 1280 y(\(i.e.)42 b Fe(datatype[i])27 b Fj(is)k(the)f(data)h(t)m(yp)s(e) g(of)f(column)h Fe(i)p Fj(\).)95 1501 y Fe(int)47 b(fits_write_col)d(/) k(ffpcl)286 1614 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i (colnum,)f(LONGLONG)f(firstrow,)334 1727 y(LONGLONG)h(firstelem,)f (LONGLONG)g(nelements,)g(DTYPE)i(*array,)e(>)j(int)f(*status\))95 1952 y(int)g(fits_write_colnull)c(/)48 b(ffpcn)286 2065 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i(colnum,)f(LONGLONG)f (firstrow,)286 2178 y(LONGLONG)h(firstelem,)f(LONGLONG)g(nelements,)g (DTYPE)i(*array,)f(DTYPE)g(*nulval,)286 2291 y(>)i(int)f(*status\))143 2517 y(int)g(fits_write_col_null)c(/)k(ffpclu)334 2630 y(\(fitsfile)e(*fptr,)h(int)h(colnum,)f(LONGLONG)g(firstrow,)f (LONGLONG)h(firstelem,)382 2743 y(LONGLONG)f(nelements,)g(>)j(int)f (*status\))143 2969 y(int)g(fits_write_nullrows)c(/)k(ffprwu)334 3081 y(\(fitsfile)e(*fptr,)h(LONGLONG)g(firstrow,)f(LONGLONG)h (nelements,)f(>)i(int)g(*status\))95 3307 y(int)g(fits_write_cols)d(/)j (ffpcln)286 3420 y(\(fitsfile)f(*fptr,)g(int)h(ncols,)f(int)h (*datatype,)e(int)i(*colnum,)e(LONGLONG)h(firstrow,)334 3533 y(LONGLONG)g(nrows,)g(DTYPE)g(**array,)g(DTYPE)g(**nulval,)f(int)i (*status\))0 3867 y Fi(2)81 b Fj(Read)33 b(elemen)m(ts)i(from)e(an)g (ASCI)s(I)f(or)i(binary)e(table)i(column.)50 b(The)33 b(data)h(t)m(yp)s(e)g(parameter)g(sp)s(eci\014es)f(the)227 3980 y(data)i(t)m(yp)s(e)g(of)g(the)f(`n)m(ulv)-5 b(al')35 b(and)f(`arra)m(y')i(p)s(oin)m(ters.)52 b(The)34 b(caller)i(is)e (required)g(to)h(allo)s(cate)i(the)d(storage)227 4093 y(of)g Fe(array)d Fj(b)s(efore)i(calling.)51 b(Unde\014ned)32 b(arra)m(y)i(elemen)m(ts)g(will)g(b)s(e)e(returned)g(with)h(a)h(v)-5 b(alue)34 b(=)f(*n)m(ullv)-5 b(al,)227 4206 y(\(note)31 b(that)f(this)g(parameter)g(giv)m(es)h(the)f(address)f(of)h(the)g(n)m (ull)f(v)-5 b(alue,)31 b(not)f(the)g(n)m(ull)f(v)-5 b(alue)31 b(itself)7 b(\))31 b(unless)227 4319 y(n)m(ulv)-5 b(al)32 b(=)f(0)h(or)f(*n)m(ulv)-5 b(al)32 b(=)f(0,)h(in)f(whic)m(h)g(case)i (no)e(c)m(hec)m(king)i(for)e(unde\014ned)e(pixels)j(will)f(b)s(e)g(p)s (erformed.)227 4431 y(The)36 b(second)g(routine)g(is)g(similar)g (except)h(that)g(an)m(y)f(unde\014ned)e(pixels)i(will)h(ha)m(v)m(e)g (the)f(corresp)s(onding)227 4544 y(n)m(ullarra)m(y)31 b(elemen)m(t)h(set)f(equal)g(to)g(TR)m(UE)f(\(=)h(1\).)227 4688 y(Reading)g(data)g(as)g(TSTRING)e(v)-5 b(alues)31 b(is)f(di\013eren)m(t)h(than)f(for)g(other)h(data)g(t)m(yp)s(es)f(as)h (describ)s(ed)e(ab)s(o)m(v)m(e.)227 4832 y(An)m(y)e(column,)g (regardless)f(of)g(it's)h(in)m(trinsic)g(data)g(t)m(yp)s(e,)g(ma)m(y)g (b)s(e)e(read)i(as)f(a)g(string.)40 b(It)26 b(should)f(b)s(e)h(noted) 227 4945 y(ho)m(w)m(ev)m(er)32 b(that)f(reading)f(a)h(n)m(umeric)f (column)g(as)h(a)g(string)f(is)g(10)i(-)e(100)i(times)f(slo)m(w)m(er)g (than)f(reading)h(the)227 5058 y(same)22 b(column)g(as)f(a)h(n)m(um)m (b)s(er)e(due)h(to)i(the)e(large)i(o)m(v)m(erhead)g(in)e(constructing)h (the)g(formatted)g(strings.)37 b(The)227 5171 y(displa)m(y)26 b(format)g(of)f(the)h(returned)e(strings)h(will)h(b)s(e)f(determined)g (b)m(y)g(the)h(TDISPn)e(k)m(eyw)m(ord,)j(if)e(it)h(exists,)227 5284 y(otherwise)32 b(b)m(y)f(the)g(data)h(t)m(yp)s(e)f(of)g(the)g (column.)43 b(The)30 b(length)i(of)f(the)g(returned)f(strings)h(\(not)g (including)227 5396 y(the)26 b(n)m(ull)f(terminating)i(c)m(haracter\))g (can)f(b)s(e)f(determined)g(with)g(the)h(\014ts)p 2703 5396 28 4 v 32 w(get)p 2855 5396 V 34 w(col)p 2999 5396 V 34 w(displa)m(y)p 3311 5396 V 33 w(width)f(routine.)227 5509 y(The)30 b(follo)m(wing)i(TDISPn)d(displa)m(y)i(formats)f(are)h (curren)m(tly)f(supp)s(orted:)418 5714 y Fe(Iw.m)142 b(Integer)p eop end %%Page: 61 69 TeXDict begin 61 68 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(61)418 555 y Fe(Ow.m)142 b(Octal)47 b(integer)418 668 y(Zw.m)142 b(Hexadecimal)45 b(integer)418 781 y(Fw.d)142 b(Fixed)47 b(floating)e(point)418 894 y(Ew.d)142 b(Exponential)45 b(floating)h(point)418 1007 y(Dw.d)142 b(Exponential)45 b(floating)h(point)418 1120 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)e(not)i(lost,)f(else)h(Ew.d)227 1332 y Fj(where)24 b(w)h(is)f(the)h(width)f(in)g(c)m(haracters)i(of)f (the)g(displa)m(y)m(ed)g(v)-5 b(alues,)27 b(m)d(is)h(the)f(minim)m(um)g (n)m(um)m(b)s(er)g(of)g(digits)227 1445 y(displa)m(y)m(ed,)31 b(and)e(d)h(is)f(the)i(n)m(um)m(b)s(er)d(of)i(digits)g(to)h(the)f(righ) m(t)h(of)f(the)g(decimal.)41 b(The)29 b(.m)h(\014eld)g(is)g(optional.) 227 1590 y(The)g Fe(fits_read_cols\(\))25 b Fj(v)-5 b(arian)m(t)31 b(read)e(m)m(ultiple)i(columns)e(in)g(a)i(single)f(pass,)g(whic)m(h)f (ma)m(y)h(b)s(e)g(signif-)227 1703 y(ican)m(tly)k(faster)f(for)f(large) i(data)f(\014les.)47 b(The)31 b(\\c)m(h)m(unk")j(size)f(is)f (determined)g(automatically)j(based)e(up)s(on)227 1816 y(CFITSIO's)23 b(bu\013er)g(sizes.)39 b(Only)23 b(whole)h(ro)m(ws)g (can)g(b)s(e)f(read,)i(of)g(an)m(y)f(t)m(yp)s(e)g(except)h(TBIT)e(or)h (TSTRING.)227 1929 y(F)-8 b(or)24 b(this)f(v)-5 b(arian)m(t,)26 b(datat)m(yp)s(e,)g(coln)m(um,)f(arra)m(y)f(and)e(n)m(ulv)-5 b(al)24 b(are)f(arra)m(ys)h(of)f(the)g(equiv)-5 b(alen)m(t)25 b(single-column)227 2042 y(parameter)31 b(\(i.e.)42 b Fe(datatype[i])27 b Fj(is)k(the)f(data)h(t)m(yp)s(e)g(of)f(column)h Fe(i)p Fj(\).)95 2270 y Fe(int)47 b(fits_read_col)e(/)i(ffgcv)286 2383 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(int)i(colnum,)f (LONGLONG)f(firstrow,)g(LONGLONG)h(firstelem,)334 2496 y(LONGLONG)g(nelements,)f(DTYPE)h(*nulval,)g(DTYPE)g(*array,)g(int)h (*anynul,)e(int)i(*status\))95 2721 y(int)g(fits_read_colnull)c(/)48 b(ffgcf)286 2834 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i (colnum,)f(LONGLONG)f(firstrow,)g(LONGLONG)h(firstelem,)286 2947 y(LONGLONG)g(nelements,)f(DTYPE)h(*array,)g(char)h(*nullarray,)d (int)j(*anynul,)f(int)h(*status\))95 3173 y(int)g(fits_read_cols)d(/)k (ffgcvn)286 3286 y(\(fitsfile)e(*fptr,)g(int)h(ncols,)f(int)h (*datatype,)e(int)i(*colnum,)e(LONGLONG)h(firstrow,)334 3399 y(LONGLONG)g(nrows,)g(DTYPE)g(**nulval,)f(DTYPE)i(**array,)e(int)i (**anynul,)e(int)i(*status\))0 3684 y Fd(5.7.5)112 b(Ro)m(w)37 b(Selection)h(and)h(Calculator)f(Routines)0 3903 y Fj(These)21 b(routines)f(all)i(parse)f(and)f(ev)-5 b(aluate)23 b(an)d(input)g (string)h(con)m(taining)i(a)e(user)f(de\014ned)g(arithmetic)i (expression.)0 4016 y(The)29 b(\014rst)f(3)i(routines)f(select)i(ro)m (ws)e(in)g(a)h(FITS)e(table,)j(based)e(on)g(whether)g(the)g(expression) g(ev)-5 b(aluates)31 b(to)f(true)0 4129 y(\(not)e(equal)f(to)h(zero\))g (or)f(false)h(\(zero\).)41 b(The)27 b(other)g(routines)g(ev)-5 b(aluate)29 b(the)e(expression)g(and)f(calculate)k(a)d(v)-5 b(alue)0 4242 y(for)26 b(eac)m(h)i(ro)m(w)f(of)g(the)g(table.)40 b(The)26 b(allo)m(w)m(ed)j(expression)d(syn)m(tax)i(is)e(describ)s(ed)g (in)g(the)h(ro)m(w)g(\014lter)g(section)g(in)g(the)0 4355 y(`Extended)32 b(File)h(Name)g(Syn)m(tax')g(c)m(hapter)g(of)f (this)g(do)s(cumen)m(t.)46 b(The)32 b(expression)g(ma)m(y)h(also)g(b)s (e)e(written)i(to)g(a)0 4468 y(text)h(\014le,)h(and)e(the)h(name)f(of)h (the)f(\014le,)i(prep)s(ended)c(with)i(a)h('@')g(c)m(haracter)h(ma)m(y) f(b)s(e)f(supplied)f(for)h(the)h('expr')0 4581 y(parameter)d(\(e.g.)42 b('@\014lename.txt'\).)g(The)30 b(expression)g(in)g(the)g(\014le)h(can) f(b)s(e)g(arbitrarily)g(complex)h(and)f(extend)0 4694 y(o)m(v)m(er)35 b(m)m(ultiple)g(lines)g(of)f(the)g(\014le.)53 b(Lines)33 b(that)i(b)s(egin)f(with)g(2)g(slash)g(c)m(haracters)i (\('//'\))g(will)f(b)s(e)e(ignored)i(and)0 4807 y(ma)m(y)c(b)s(e)f (used)f(to)i(add)f(commen)m(ts)h(to)h(the)e(\014le.)0 5034 y Fi(1)81 b Fj(Ev)-5 b(aluate)38 b(a)f(b)s(o)s(olean)g(expression) g(o)m(v)m(er)h(the)g(indicated)f(ro)m(ws,)i(returning)d(an)h(arra)m(y)h (of)f(\015ags)g(indicating)227 5147 y(whic)m(h)31 b(ro)m(ws)g(ev)-5 b(aluated)32 b(to)f(TR)m(UE/F)-10 b(ALSE.)31 b(Up)s(on)f(return,)g(*n)p 2518 5147 28 4 v 33 w(go)s(o)s(d)p 2743 5147 V 33 w(ro)m(ws)g(con)m (tains)i(the)f(n)m(um)m(b)s(er)f(of)227 5260 y(ro)m(ws)h(that)g(ev)-5 b(aluate)32 b(to)f(TR)m(UE.)95 5488 y Fe(int)47 b(fits_find_rows)d(/)k (fffrow)286 5601 y(\(fitsfile)e(*fptr,)93 b(char)47 b(*expr,)f(long)h (firstrow,)e(long)i(nrows,)286 5714 y(>)h(long)e(*n_good_rows,)f(char)h (*row_status,)92 b(int)47 b(*status\))p eop end %%Page: 62 70 TeXDict begin 62 69 bop 0 299 a Fj(62)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(2)81 b Fj(Find)29 b(the)i(\014rst)f(ro)m(w)g (whic)m(h)g(satis\014es)h(the)g(input)e(b)s(o)s(olean)h(expression)95 777 y Fe(int)47 b(fits_find_first_row)c(/)k(ffffrw)286 890 y(\(fitsfile)f(*fptr,)93 b(char)47 b(*expr,)f(>)i(long)e(*rownum,)g (int)h(*status\))0 1112 y Fi(3)81 b Fj(Ev)-5 b(aluate)35 b(an)f(expression)h(on)f(all)h(ro)m(ws)g(of)f(a)h(table.)54 b(If)34 b(the)g(input)g(and)g(output)g(\014les)g(are)h(not)g(the)f (same,)227 1225 y(cop)m(y)i(the)g(TR)m(UE)f(ro)m(ws)g(to)h(the)f (output)g(\014le;)j(if)d(the)g(output)g(table)h(is)f(not)h(empt)m(y)-8 b(,)37 b(then)e(this)g(routine)227 1338 y(will)28 b(app)s(end)e(the)i (new)f(selected)i(ro)m(ws)e(after)h(the)g(existing)h(ro)m(ws.)39 b(If)27 b(the)h(\014les)g(are)f(the)h(same,)h(delete)g(the)227 1451 y(F)-10 b(ALSE)30 b(ro)m(ws)h(\(preserv)m(e)f(the)h(TR)m(UE)f(ro)m (ws\).)95 1673 y Fe(int)47 b(fits_select_rows)d(/)j(ffsrow)286 1785 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)93 b(char)46 b(*expr,)94 b(>)48 b(int)f(*status)e(\))0 2007 y Fi(4)81 b Fj(Calculate)28 b(an)f(expression)f(for)h(the)f(indicated)i (ro)m(ws)e(of)h(a)g(table,)i(returning)d(the)h(results,)g(cast)h(as)f (datat)m(yp)s(e)227 2120 y(\(TSHOR)-8 b(T,)32 b(TDOUBLE,)h(etc\),)h(in) e(arra)m(y)-8 b(.)48 b(If)31 b(n)m(ulv)-5 b(al==NULL,)33 b(UNDEFs)g(will)f(b)s(e)g(zero)s(ed)g(out.)47 b(F)-8 b(or)227 2233 y(v)m(ector)37 b(results,)f(the)f(n)m(um)m(b)s(er)e(of)i (elemen)m(ts)i(returned)c(ma)m(y)j(b)s(e)e(less)h(than)g(nelemen)m(ts)g (if)g(nelemen)m(ts)h(is)227 2346 y(not)c(an)g(ev)m(en)h(m)m(ultiple)f (of)g(the)g(result)g(dimension.)44 b(Call)33 b(\014ts)p 2392 2346 28 4 v 32 w(test)p 2570 2346 V 34 w(expr)e(to)h(obtain)h(the) f(dimensions)f(of)227 2459 y(the)g(results.)95 2681 y Fe(int)47 b(fits_calc_rows)d(/)k(ffcrow)286 2794 y(\(fitsfile)e(*fptr,) 93 b(int)47 b(datatype,)f(char)g(*expr,)g(long)h(firstrow,)334 2907 y(long)g(nelements,)e(void)h(*nulval,)g(>)h(void)g(*array,)94 b(int)46 b(*anynul,)g(int)h(*status\))0 3129 y Fi(5)81 b Fj(Ev)-5 b(aluate)33 b(an)g(expression)f(and)h(write)f(the)h(result)g (either)g(to)h(a)f(column)f(\(if)h(the)g(expression)f(is)h(a)g (function)227 3242 y(of)d(other)g(columns)g(in)f(the)h(table\))h(or)f (to)g(a)h(k)m(eyw)m(ord)f(\(if)g(the)g(expression)f(ev)-5 b(aluates)32 b(to)e(a)g(constan)m(t)i(and)227 3354 y(is)f(not)f(a)h (function)f(of)h(other)f(columns)h(in)f(the)g(table\).)42 b(In)30 b(the)h(former)e(case,)j(the)f(parName)f(parameter)227 3467 y(is)40 b(the)g(name)f(of)h(the)g(column)f(\(whic)m(h)h(ma)m(y)g (or)f(ma)m(y)h(not)g(already)g(exist\))h(in)m(to)f(whic)m(h)g(to)g (write)g(the)227 3580 y(results,)e(and)f(parInfo)e(con)m(tains)j(an)f (optional)g(TF)m(ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue)38 b(if)e(a)h(new)f(column)h(is)f(b)s(eing)227 3693 y(created.)42 b(If)28 b(a)h(TF)m(ORM)h(v)-5 b(alue)29 b(is)g(not)g(sp)s(eci\014ed)g (then)f(a)i(default)f(format)g(will)h(b)s(e)e(used,)h(dep)s(ending)e (on)227 3806 y(the)35 b(expression.)54 b(If)34 b(the)h(expression)f(ev) -5 b(aluates)37 b(to)e(a)g(constan)m(t,)i(then)e(the)g(result)f(will)h (b)s(e)f(written)h(to)227 3919 y(the)28 b(k)m(eyw)m(ord)g(name)f(giv)m (en)h(b)m(y)g(the)f(parName)h(parameter,)h(and)d(the)i(parInfo)e (parameter)i(ma)m(y)g(b)s(e)f(used)227 4032 y(to)k(supply)e(an)h (optional)i(commen)m(t)f(for)f(the)g(k)m(eyw)m(ord.)42 b(If)29 b(the)i(k)m(eyw)m(ord)g(do)s(es)f(not)g(already)h(exist,)g (then)227 4145 y(the)f(name)f(of)h(the)g(k)m(eyw)m(ord)g(m)m(ust)f(b)s (e)g(preceded)g(with)g(a)h('#')f(c)m(haracter,)j(otherwise)e(the)f (result)h(will)g(b)s(e)227 4258 y(written)h(to)g(a)g(column)f(with)g (that)h(name.)95 4480 y Fe(int)47 b(fits_calculator)d(/)j(ffcalc)286 4593 y(\(fitsfile)f(*infptr,)f(char)i(*expr,)f(fitsfile)f(*outfptr,)h (char)g(*parName,)334 4706 y(char)h(*parInfo,)e(>)95 b(int)47 b(*status\))0 4927 y Fi(6)81 b Fj(This)38 b(calculator)k (routine)e(is)f(similar)h(to)g(the)g(previous)f(routine,)j(except)f (that)f(the)g(expression)f(is)h(only)227 5040 y(ev)-5 b(aluated)42 b(o)m(v)m(er)f(the)f(sp)s(eci\014ed)g(ro)m(w)g(ranges.)70 b(nranges)39 b(sp)s(eci\014es)h(the)g(n)m(um)m(b)s(er)f(of)h(ro)m(w)h (ranges,)i(and)227 5153 y(\014rstro)m(w)30 b(and)g(lastro)m(w)h(giv)m (e)h(the)f(starting)g(and)f(ending)g(ro)m(w)g(n)m(um)m(b)s(er)f(of)i (eac)m(h)g(range.)95 5375 y Fe(int)47 b(fits_calculator_rng)c(/)k (ffcalc_rng)286 5488 y(\(fitsfile)f(*infptr,)f(char)i(*expr,)f (fitsfile)f(*outfptr,)h(char)g(*parName,)334 5601 y(char)h(*parInfo,)e (int)i(nranges,)e(long)i(*firstrow,)e(long)i(*lastrow)334 5714 y(>)95 b(int)47 b(*status\))p eop end %%Page: 63 71 TeXDict begin 63 70 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(63)0 555 y Fi(7)81 b Fj(Ev)-5 b(aluate)36 b(the)f(giv)m(en)h (expression)f(and)g(return)f(dimension)g(and)h(t)m(yp)s(e)g (information)g(on)g(the)h(result.)54 b(The)227 668 y(returned)37 b(dimensions)f(corresp)s(ond)g(to)j(a)e(single)i(ro)m(w)e(en)m(try)h (of)f(the)h(requested)f(expression,)j(and)d(are)227 781 y(equiv)-5 b(alen)m(t)26 b(to)f(the)g(result)f(of)g(\014ts)p 1380 781 28 4 v 33 w(read)p 1585 781 V 32 w(tdim\(\).)40 b(Note)25 b(that)g(strings)f(are)h(considered)f(to)h(b)s(e)f(one)g (elemen)m(t)227 894 y(regardless)31 b(of)g(string)f(length.)41 b(If)30 b(maxdim)g(==)g(0,)h(then)f(naxes)g(is)h(optional.)95 1159 y Fe(int)47 b(fits_test_expr)d(/)k(fftexp)286 1272 y(\(fitsfile)e(*fptr,)g(char)g(*expr,)g(int)h(maxdim)f(>)i(int)f (*datatype,)e(long)h(*nelem,)g(int)h(*naxis,)334 1385 y(long)g(*naxes,)f(int)g(*status\))0 1682 y Fd(5.7.6)112 b(Column)39 b(Binning)f(or)f(Histogramming)i(Routines)0 1902 y Fj(The)30 b(follo)m(wing)j(routines)e(ma)m(y)g(b)s(e)g(useful)f (when)g(p)s(erforming)g(histogramming)h(op)s(erations)h(on)e (column\(s\))i(of)0 2015 y(a)f(table)g(to)g(generate)h(an)e(image)i(in) e(a)h(primary)e(arra)m(y)i(or)f(image)i(extension.)0 2280 y Fi(1)81 b Fj(Calculate)27 b(the)e(histogramming)h(parameters)g (\(min,)h(max,)f(and)f(bin)g(size)h(for)f(eac)m(h)i(axis)f(of)f(the)h (histogram,)227 2393 y(based)38 b(on)g(a)g(v)-5 b(ariet)m(y)39 b(of)f(p)s(ossible)g(input)f(parameters.)64 b(If)37 b(the)h(input)f (names)h(of)g(the)g(columns)g(to)h(b)s(e)227 2506 y(binned)d(are)i(n)m (ull,)h(then)e(the)h(routine)f(will)h(\014rst)f(lo)s(ok)h(for)f(the)h (CPREF)f(=)g("NAME1,)j(NAME2,)h(...")227 2619 y(k)m(eyw)m(ord)34 b(whic)m(h)f(lists)h(the)g(preferred)e(columns.)50 b(If)32 b(not)i(presen)m(t,)h(then)e(the)g(routine)h(will)g(assume)f(the)227 2732 y(column)d(names)h(X,)f(Y,)h(Z,)f(and)g(T)g(for)g(up)g(to)h(4)f (axes)h(\(as)g(sp)s(eci\014ed)f(b)m(y)g(the)h(NAXIS)f(parameter\).)227 2885 y(MININ)39 b(and)f(MAXIN)h(are)g(input)e(arra)m(ys)i(that)g(giv)m (e)h(the)f(minim)m(um)e(and)h(maxim)m(um)h(v)-5 b(alue)39 b(for)f(the)227 2998 y(histogram,)30 b(along)f(eac)m(h)g(axis.)40 b(Alternativ)m(ely)-8 b(,)32 b(the)c(name)g(of)h(k)m(eyw)m(ords)f(that) h(giv)m(e)g(the)f(min,)h(max,)g(and)227 3110 y(binsize)f(ma)m(y)g(b)s (e)f(giv)m(e)h(with)f(the)h(MINNAME,)h(MAXNAME,)f(and)f(BINNAME)h(arra) m(y)g(parameters.)40 b(If)227 3223 y(the)33 b(v)-5 b(alue)34 b(=)e(DOUBLENULL)-10 b(V)g(ALUE)33 b(and)g(no)f(k)m(eyw)m(ord)i(names)e (are)h(giv)m(en,)i(then)e(the)g(routine)g(will)227 3336 y(use)i(the)f(TLMINn)g(and)g(TLMAXn)g(k)m(eyw)m(ords,)j(if)d(presen)m (t,)i(or)f(the)f(actual)i(min)e(and/or)h(max)g(v)-5 b(alues)227 3449 y(in)30 b(the)h(column.)227 3602 y(The)d(\\d")g(v)m(ersion)h(has)e (double)h(precision)g(\015oating)h(p)s(oin)m(t)f(outputs)g(as)g(noted)g (in)g(the)g(calling)h(signature.)227 3715 y(The)h(v)m(ersion)h(without) f(\\d")h(has)f(single)h(precision)g(\015oating)g(p)s(oin)m(t)f (outputs.)227 3868 y(BINSIZEIN)k(is)h(an)g(arra)m(y)g(giving)h(the)f (binsize)g(along)h(eac)m(h)g(axis.)55 b(If)34 b(the)h(v)-5 b(alue)36 b(=)e(DOUBLENULL-)227 3981 y(V)-10 b(ALUE,)38 b(and)e(a)i(k)m(eyw)m(ord)f(name)g(is)h(not)f(sp)s(eci\014ed)f(with)h (BINNAME,)h(then)f(this)g(routine)g(will)h(\014rst)227 4094 y(lo)s(ok)d(for)f(the)g(TDBINn)g(k)m(eyw)m(ord,)i(or)f(else)g (will)f(use)g(a)h(binsize)f(=)g(1,)h(or)g(a)f(binsize)g(that)h(pro)s (duces)e(10)227 4207 y(histogram)e(bins,)f(whic)m(h)g(ev)m(er)h(is)g (smaller.)95 4472 y Fe(int)47 b(fits_calc_binning[d])143 4585 y(Input)g(parameters:)239 4698 y(\(fitsfile)e(*fptr,)94 b(/*)47 b(IO)g(-)h(pointer)d(to)j(table)e(to)h(be)g(binned)667 b(*/)286 4811 y(int)47 b(naxis,)333 b(/*)47 b(I)g(-)h(number)e(of)h (axes/columns)e(in)i(the)g(binned)f(image)94 b(*/)286 4924 y(char)47 b(colname[4][FLEN_VALUE],)137 b(/*)47 b(I)h(-)f(optional)f(column)g(names)428 b(*/)286 5036 y(double)46 b(*minin,)237 b(/*)47 b(I)h(-)f(optional)f(lower)g(bound)h (value)f(for)h(each)f(axis)95 b(*/)286 5149 y(double)46 b(*maxin,)237 b(/*)47 b(I)h(-)f(optional)f(upper)g(bound)h(value,)f (for)h(each)f(axis)h(*/)286 5262 y(double)f(*binsizein,)f(/*)i(I)h(-)f (optional)f(bin)h(size)f(along)h(each)f(axis)429 b(*/)286 5375 y(char)47 b(minname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional) d(keywords)h(for)h(min)333 b(*/)286 5488 y(char)47 b (maxname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional)d(keywords)h (for)h(max)333 b(*/)286 5601 y(char)47 b(binname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional)d(keywords)h(for)h(binsize)141 b(*/)143 5714 y(Output)46 b(parameters:)p eop end %%Page: 64 72 TeXDict begin 64 71 bop 0 299 a Fj(64)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)286 555 y Fe(int)47 b(*colnum,)237 b(/*)47 b(O)g(-)h(column)e(numbers,)f(to)j(be)f(binned)f(*/)286 668 y(long)h(*naxes,)237 b(/*)47 b(O)g(-)h(number)e(of)h(bins)g(in)g (each)g(histogram)e(axis)h(*/)286 781 y(float[double])f(*amin,)237 b(/*)47 b(O)g(-)h(lower)e(bound)g(of)i(the)e(histogram)g(axes)g(*/)286 894 y(float[double])f(*amax,)237 b(/*)47 b(O)g(-)h(upper)e(bound)g(of)i (the)e(histogram)g(axes)g(*/)286 1007 y(float[double])f(*binsize,)93 b(/*)47 b(O)g(-)h(width)e(of)h(histogram)e(bins/pixels)g(on)i(each)g (axis)g(*/)286 1120 y(int)g(*status\))0 1371 y Fi(2)81 b Fj(Cop)m(y)26 b(the)h(relev)-5 b(an)m(t)28 b(k)m(eyw)m(ords)f(from)g (the)g(header)f(of)h(the)g(table)h(that)f(is)g(b)s(eing)f(binned,)h(to) g(the)g(the)g(header)227 1484 y(of)e(the)h(output)e(histogram)i(image.) 40 b(This)24 b(will)i(not)f(cop)m(y)h(the)f(table)h(structure)f(k)m (eyw)m(ords)g(\(e.g.,)j(NAXIS,)227 1597 y(TF)m(ORMn,)j(TTYPEn,)f (etc.\))44 b(nor)31 b(will)g(it)g(cop)m(y)h(the)f(k)m(eyw)m(ords)g (that)h(apply)e(to)i(other)f(columns)g(of)g(the)227 1710 y(table)g(that)g(are)f(not)h(used)e(to)i(create)g(the)f(histogram.)42 b(This)29 b(routine)h(will)g(translate)h(the)g(names)f(of)g(the)227 1823 y(W)-8 b(orld)27 b(Co)s(ordinate)e(System)h(\(W)m(CS\))g(k)m(eyw)m (ords)g(for)g(the)g(binned)e(columns)h(in)m(to)i(the)f(form)f(that)h (is)g(need)227 1936 y(for)h(a)g(FITS)g(image)h(\(e.g.,)h(the)e(TCTYPn)f (table)i(k)m(eyw)m(ord)f(will)g(b)s(e)g(translated)g(to)h(the)f(CTYPEn) f(image)227 2049 y(k)m(eyw)m(ord\).)95 2300 y Fe(int)47 b(fits_copy_pixlist2image)286 2413 y(\(fitsfile)f(*infptr,)141 b(/*)47 b(I)g(-)h(pointer)e(to)h(input)f(HDU)h(*/)334 2526 y(fitsfile)f(*outfptr,)93 b(/*)47 b(I)g(-)h(pointer)e(to)h(output) f(HDU)h(*/)334 2639 y(int)g(firstkey,)332 b(/*)47 b(I)g(-)h(first)e (HDU)h(keyword)f(to)h(start)f(with)h(*/)334 2752 y(int)g(naxis,)476 b(/*)47 b(I)g(-)h(number)e(of)h(axes)g(in)g(the)g(image)f(*/)334 2865 y(int)h(*colnum,)380 b(/*)47 b(I)g(-)h(numbers)e(of)h(the)g (columns)e(to)j(be)f(binned)94 b(*/)334 2978 y(int)47 b(*status\))380 b(/*)47 b(IO)g(-)g(error)g(status)f(*/)0 3229 y Fi(3)81 b Fj(W)-8 b(rite)36 b(a)f(set)h(of)f(default)h(W)m(CS)f (k)m(eyw)m(ords)g(to)h(the)f(histogram)h(header,)g(IF)f(the)g(W)m(CS)g (k)m(eyw)m(ords)h(do)f(not)227 3342 y(already)40 b(exist.)69 b(This)38 b(will)i(create)h(a)e(linear)h(W)m(CS)f(where)g(the)h(co)s (ordinate)g(t)m(yp)s(es)f(are)h(equal)g(to)g(the)227 3455 y(original)32 b(column)e(names.)95 3707 y Fe(int)47 b(fits_write_keys_histo)239 3820 y(\(fitsfile)e(*fptr,)237 b(/*)47 b(I)h(-)f(pointer)f(to)h(table)f(to)i(be)f(binned)666 b(*/)286 3933 y(fitsfile)46 b(*histptr,)93 b(/*)47 b(I)h(-)f(pointer)f (to)h(output)f(histogram)f(image)i(HDU)285 b(*/)286 4046 y(int)47 b(naxis,)476 b(/*)47 b(I)h(-)f(number)f(of)h(axes)g(in)g(the)g (histogram)e(image)285 b(*/)286 4159 y(int)47 b(*colnum,)380 b(/*)47 b(I)h(-)f(column)f(numbers)g(of)h(the)g(binned)f(columns)332 b(*/)286 4271 y(int)47 b(*status\))0 4523 y Fi(4)81 b Fj(Up)s(date)29 b(the)i(W)m(CS)f(k)m(eyw)m(ords)g(in)g(a)g(histogram)h (image)g(header)f(that)h(giv)m(e)g(the)f(lo)s(cation)i(of)e(the)g (reference)227 4636 y(pixel)h(\(CRPIXn\),)f(and)g(the)h(pixel)f(size)h (\(CDEL)-8 b(Tn\),)31 b(in)f(the)h(binned)e(image.)227 4785 y(The)j(\\d")g(v)m(ersion)h(has)e(double)h(precision)g(\015oating) h(p)s(oin)m(t)f(inputs)f(as)h(noted)g(in)g(the)g(calling)h(signature.) 227 4898 y(The)d(v)m(ersion)h(without)f(\\d")h(has)f(single)h (precision)g(\015oating)g(p)s(oin)m(t)f(inputs.)95 5149 y Fe(int)47 b(fits_rebin_wcs[d])239 5262 y(\(fitsfile)e(*fptr,)237 b(/*)47 b(I)h(-)f(pointer)f(to)h(table)f(to)i(be)f(binned)523 b(*/)286 5375 y(int)47 b(naxis,)476 b(/*)47 b(I)h(-)f(number)f(of)h (axes)g(in)g(the)g(histogram)e(image)142 b(*/)286 5488 y(float[double])45 b(*amin,)380 b(/*)47 b(I)g(-)h(first)e(pixel)h (include)e(in)j(each)e(axis)381 b(*/)286 5601 y(float[double])45 b(*binsize,)236 b(/*)47 b(I)g(-)h(binning)e(factor)g(for)h(each)f(axis) 572 b(*/)286 5714 y(int)47 b(*status\))p eop end %%Page: 65 73 TeXDict begin 65 72 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(65)0 555 y Fi(5)81 b Fj(Bin)33 b(the)h(v)-5 b(alues)35 b(in)e(the)h(input)f(table)h(columns,)h(and)e (write)h(the)g(histogram)h(arra)m(y)f(to)g(the)g(output)g(FITS)227 668 y(image)e(\(histptr\).)227 815 y(The)g(\\d")g(v)m(ersion)h(has)e (double)h(precision)g(\015oating)h(p)s(oin)m(t)f(inputs)f(as)h(noted)g (in)g(the)g(calling)h(signature.)227 928 y(The)d(v)m(ersion)h(without)f (\\d")h(has)f(single)h(precision)g(\015oating)g(p)s(oin)m(t)f(inputs.) 95 1169 y Fe(int)47 b(fits_make_hist[d])143 1282 y(\(fitsfile)e(*fptr,) 190 b(/*)47 b(I)g(-)h(pointer)e(to)h(table)f(with)h(X)g(and)g(Y)h (cols;)285 b(*/)191 1395 y(fitsfile)45 b(*histptr,)h(/*)h(I)g(-)h (pointer)e(to)h(output)f(FITS)h(image)619 b(*/)191 1508 y(int)47 b(bitpix,)380 b(/*)47 b(I)g(-)h(datatype)d(for)i(image:)f(16,) h(32,)g(-32,)g(etc)238 b(*/)191 1621 y(int)47 b(naxis,)428 b(/*)47 b(I)g(-)h(number)e(of)h(axes)g(in)g(the)g(histogram)e(image)190 b(*/)191 1734 y(long)47 b(*naxes,)332 b(/*)47 b(I)g(-)h(size)e(of)i (axes)e(in)h(the)g(histogram)f(image)285 b(*/)191 1847 y(int)47 b(*colnum,)332 b(/*)47 b(I)g(-)h(column)e(numbers)g(\(array)g (length)g(=)h(naxis\))190 b(*/)191 1960 y(float[double])44 b(*amin,)333 b(/*)47 b(I)g(-)h(minimum)d(histogram)h(value,)g(for)h (each)f(axis)142 b(*/)191 2073 y(float[double])44 b(*amax,)333 b(/*)47 b(I)g(-)h(maximum)d(histogram)h(value,)g(for)h(each)f(axis)142 b(*/)191 2186 y(float[double])44 b(*binsize,)189 b(/*)47 b(I)g(-)h(bin)f(size)f(along)h(each)f(axis)810 b(*/)191 2298 y(float[double])44 b(weight,)285 b(/*)47 b(I)g(-)h(binning)d (weighting)h(factor)g(\(FLOATNULLVALUE)d(*/)1098 2411 y(/*)238 b(for)47 b(no)g(weighting\))1143 b(*/)191 2524 y(int)47 b(wtcolnum,)284 b(/*)47 b(I)g(-)h(keyword)e(or)h(col)g(for)g (weight)284 b(\(or)47 b(NULL\))g(*/)191 2637 y(int)g(recip,)428 b(/*)47 b(I)g(-)h(use)f(reciprocal)e(of)i(the)g(weight?)f(0)h(or)g(1) 239 b(*/)191 2750 y(char)47 b(*selectrow,)140 b(/*)47 b(I)g(-)h(optional)d(array)i(\(length)f(=)h(no.)g(of)477 b(*/)1098 2863 y(/*)47 b(rows)g(in)g(the)g(table\).)93 b(If)47 b(the)g(element)f(is)h(true)95 b(*/)1098 2976 y(/*)47 b(then)g(the)f(corresponding)f(row)i(of)g(the)g(table)f(will)h (*/)1098 3089 y(/*)g(be)g(included)f(in)h(the)g(histogram,)e(otherwise) g(the)95 b(*/)1098 3202 y(/*)47 b(row)g(will)f(be)i(skipped.)93 b(Ingnored)45 b(if)j(*selectrow)d(*/)1098 3315 y(/*)i(is)g(equal)f(to)i (NULL.)1335 b(*/)191 3428 y(int)47 b(*status\))0 3758 y Ff(5.8)135 b(Utilit)l(y)47 b(Routines)0 4012 y Fd(5.8.1)112 b(File)39 b(Chec)m(ksum)f(Routines)0 4231 y Fj(The)33 b(follo)m(wing)h(routines)f(either)h(compute)f(or)h(v)-5 b(alidate)34 b(the)g(c)m(hec)m(ksums)f(for)g(the)h(CHDU.)g(The)e(D)m(A) -8 b(T)g(ASUM)0 4344 y(k)m(eyw)m(ord)33 b(is)f(used)f(to)i(store)f(the) h(n)m(umerical)f(v)-5 b(alue)33 b(of)f(the)g(32-bit,)i(1's)f(complemen) m(t)g(c)m(hec)m(ksum)g(for)f(the)g(data)0 4457 y(unit)26 b(alone.)40 b(If)25 b(there)h(is)h(no)e(data)i(unit)f(then)f(the)h(v)-5 b(alue)27 b(is)f(set)g(to)h(zero.)40 b(The)26 b(n)m(umerical)g(v)-5 b(alue)27 b(is)f(stored)g(as)g(an)0 4569 y(ASCI)s(I)20 b(string)i(of)h(digits,)h(enclosed)f(in)e(quotes,)k(b)s(ecause)d(the)g (v)-5 b(alue)23 b(ma)m(y)f(b)s(e)f(to)s(o)i(large)g(to)g(represen)m(t)f (as)g(a)h(32-bit)0 4682 y(signed)28 b(in)m(teger.)41 b(The)27 b(CHECKSUM)g(k)m(eyw)m(ord)i(is)f(used)f(to)h(store)h(the)f (ASCI)s(I)e(enco)s(ded)i(COMPLEMENT)f(of)0 4795 y(the)f(c)m(hec)m(ksum) h(for)f(the)h(en)m(tire)g(HDU.)g(Storing)f(the)h(complemen)m(t,)h (rather)e(than)g(the)h(actual)g(c)m(hec)m(ksum,)h(forces)0 4908 y(the)k(c)m(hec)m(ksum)h(for)f(the)h(whole)f(HDU)h(to)g(equal)g (zero.)47 b(If)31 b(the)i(\014le)f(has)g(b)s(een)f(mo)s(di\014ed)g (since)i(the)f(c)m(hec)m(ksums)0 5021 y(w)m(ere)39 b(computed,)i(then)e (the)g(HDU)g(c)m(hec)m(ksum)h(will)f(usually)f(not)h(equal)h(zero.)66 b(These)39 b(c)m(hec)m(ksum)g(k)m(eyw)m(ord)0 5134 y(con)m(v)m(en)m (tions)34 b(are)f(based)f(on)g(a)g(pap)s(er)f(b)m(y)h(Rob)g(Seaman)g (published)f(in)h(the)g(pro)s(ceedings)g(of)g(the)h(AD)m(ASS)f(IV)0 5247 y(conference)h(in)e(Baltimore)j(in)d(No)m(v)m(em)m(b)s(er)i(1994)h (and)d(a)h(later)h(revision)f(in)f(June)g(1995.)47 b(See)32 b(App)s(endix)e(B)i(for)0 5360 y(the)f(de\014nition)f(of)g(the)h (parameters)f(used)g(in)g(these)h(routines.)0 5601 y Fi(1)81 b Fj(Compute)33 b(and)g(write)h(the)g(D)m(A)-8 b(T)g(ASUM)35 b(and)e(CHECKSUM)g(k)m(eyw)m(ord)h(v)-5 b(alues)34 b(for)f(the)h(CHDU)g(in)m(to)h(the)227 5714 y(curren)m(t)d(header.)46 b(If)32 b(the)g(k)m(eyw)m(ords)h(already)g (exist,)g(their)g(v)-5 b(alues)32 b(will)h(b)s(e)e(up)s(dated)g(only)h (if)h(necessary)p eop end %%Page: 66 74 TeXDict begin 66 73 bop 0 299 a Fj(66)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(\(i.e.,)i(if)f(the)f(\014le)h(has)f(b)s(een) f(mo)s(di\014ed)h(since)g(the)h(original)h(k)m(eyw)m(ord)e(v)-5 b(alues)31 b(w)m(ere)g(computed\).)95 809 y Fe(int)47 b(fits_write_chksum)c(/)48 b(ffpcks)286 922 y(\(fitsfile)e(*fptr,)g(>)h (int)g(*status\))0 1175 y Fi(2)81 b Fj(Up)s(date)28 b(the)h(CHECKSUM)e (k)m(eyw)m(ord)i(v)-5 b(alue)29 b(in)f(the)h(CHDU,)g(assuming)f(that)h (the)f(D)m(A)-8 b(T)g(ASUM)30 b(k)m(eyw)m(ord)227 1288 y(exists)36 b(and)f(already)h(has)f(the)h(correct)g(v)-5 b(alue.)56 b(This)35 b(routine)g(calculates)j(the)e(new)f(c)m(hec)m (ksum)h(for)f(the)227 1401 y(curren)m(t)40 b(header)g(unit,)j(adds)c (it)i(to)g(the)f(data)h(unit)f(c)m(hec)m(ksum,)k(enco)s(des)c(the)g(v) -5 b(alue)41 b(in)m(to)g(an)f(ASCI)s(I)227 1514 y(string,)31 b(and)f(writes)g(the)h(string)f(to)h(the)g(CHECKSUM)e(k)m(eyw)m(ord.)95 1767 y Fe(int)47 b(fits_update_chksum)c(/)48 b(ffupck)286 1880 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 2133 y Fi(3)81 b Fj(V)-8 b(erify)35 b(the)f(CHDU)h(b)m(y)g(computing)f(the)h (c)m(hec)m(ksums)g(and)f(comparing)h(them)f(with)g(the)h(k)m(eyw)m (ords.)53 b(The)227 2246 y(data)34 b(unit)f(is)g(v)m(eri\014ed)g (correctly)h(if)f(the)h(computed)f(c)m(hec)m(ksum)g(equals)h(the)f(v)-5 b(alue)34 b(of)f(the)g(D)m(A)-8 b(T)g(ASUM)227 2359 y(k)m(eyw)m(ord.)64 b(The)37 b(c)m(hec)m(ksum)i(for)f(the)g(en)m(tire)g(HDU)h(\(header)f (plus)f(data)i(unit\))e(is)h(correct)h(if)f(it)h(equals)227 2472 y(zero.)47 b(The)32 b(output)f(D)m(A)-8 b(T)g(A)m(OK)34 b(and)d(HDUOK)i(parameters)f(in)g(this)g(routine)g(are)g(in)m(tegers)i (whic)m(h)e(will)227 2585 y(ha)m(v)m(e)k(a)f(v)-5 b(alue)35 b(=)f(1)h(if)f(the)h(data)g(or)f(HDU)h(is)g(v)m(eri\014ed)f(correctly) -8 b(,)38 b(a)d(v)-5 b(alue)35 b(=)f(0)h(if)f(the)h(D)m(A)-8 b(T)g(ASUM)36 b(or)227 2698 y(CHECKSUM)29 b(k)m(eyw)m(ord)g(is)h(not)f (presen)m(t,)h(or)f(v)-5 b(alue)30 b(=)f(-1)h(if)f(the)h(computed)f(c)m (hec)m(ksum)h(is)f(not)h(correct.)95 3064 y Fe(int)47 b(fits_verify_chksum)c(/)48 b(ffvcks)286 3177 y(\(fitsfile)e(*fptr,)g (>)h(int)g(*dataok,)f(int)h(*hduok,)e(int)i(*status\))0 3431 y Fi(4)81 b Fj(Compute)40 b(and)g(return)g(the)h(c)m(hec)m(ksum)g (v)-5 b(alues)41 b(for)g(the)g(CHDU)g(without)g(creating)h(or)f(mo)s (difying)f(the)227 3544 y(CHECKSUM)33 b(and)h(D)m(A)-8 b(T)g(ASUM)35 b(k)m(eyw)m(ords.)52 b(This)33 b(routine)h(is)g(used)f (in)m(ternally)i(b)m(y)f(\013v)m(c)m(ks,)i(but)d(ma)m(y)227 3656 y(b)s(e)d(useful)g(in)g(other)g(situations)h(as)g(w)m(ell.)95 3910 y Fe(int)47 b(fits_get_chksum/)d(/ffgcks)286 4023 y(\(fitsfile)i(*fptr,)g(>)h(unsigned)f(long)g(*datasum,)g(unsigned)f (long)i(*hdusum,)334 4136 y(int)g(*status\))0 4389 y Fi(5)81 b Fj(Enco)s(de)23 b(a)h(c)m(hec)m(ksum)g(v)-5 b(alue)24 b(in)m(to)g(a)g(16-c)m(haracter)j(string.)38 b(If)23 b(complm)h(is)f(non-zero)i(\(true\))f(then)f(the)h(32-bit)227 4502 y(sum)30 b(v)-5 b(alue)31 b(will)f(b)s(e)g(complemen)m(ted)h(b)s (efore)f(enco)s(ding.)95 4755 y Fe(int)47 b(fits_encode_chksum)c(/)48 b(ffesum)286 4868 y(\(unsigned)e(long)g(sum,)h(int)g(complm,)f(>)h (char)g(*ascii\);)0 5122 y Fi(6)81 b Fj(Deco)s(de)24 b(a)f(16-c)m(haracter)j(c)m(hec)m(ksum)e(string)f(in)m(to)g(a)h (unsigned)e(long)h(v)-5 b(alue.)39 b(If)23 b(is)g(non-zero)g(\(true\).) 39 b(then)23 b(the)227 5235 y(32-bit)33 b(sum)d(v)-5 b(alue)32 b(will)g(b)s(e)f(complemen)m(ted)h(after)g(deco)s(ding.)44 b(The)31 b(c)m(hec)m(ksum)h(v)-5 b(alue)32 b(is)g(also)g(returned)227 5348 y(as)f(the)f(v)-5 b(alue)31 b(of)g(the)f(function.)95 5601 y Fe(unsigned)46 b(long)h(fits_decode_chksum)42 b(/)48 b(ffdsum)525 5714 y(\(char)e(*ascii,)g(int)h(complm,)f(>)h (unsigned)f(long)h(*sum\);)p eop end %%Page: 67 75 TeXDict begin 67 74 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(67)0 555 y Fd(5.8.2)112 b(Date)38 b(and)g(Time)g(Utilit)m(y)f(Routines)0 774 y Fj(The)29 b(follo)m(wing)i(routines)f(help)f(to)i(construct)f(or)f(parse)h(the)g (FITS)f(date/time)i(strings.)41 b(Starting)30 b(in)f(the)h(y)m(ear)0 887 y(2000,)k(the)d(FITS)g(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(\(and)h(the)f(v)-5 b(alues)32 b(of)f(other)h(`D)m(A)-8 b(TE-')33 b(k)m(eyw)m(ords\))f(m)m(ust)f(ha)m(v)m(e)i(the)0 1000 y(form)j('YYYY-MM-DD')k(\(date)e(only\))f(or)g ('YYYY-MM-DDThh:mm:ss.ddd...')61 b(\(date)38 b(and)e(time\))h(where)0 1113 y(the)30 b(n)m(um)m(b)s(er)f(of)i(decimal)g(places)g(in)f(the)g (seconds)g(v)-5 b(alue)31 b(is)f(optional.)42 b(These)30 b(times)h(are)f(in)g(UTC.)g(The)g(older)0 1226 y('dd/mm/yy')d(date)g (format)g(ma)m(y)h(not)f(b)s(e)f(used)g(for)h(dates)h(after)f(01)h(Jan) m(uary)e(2000.)42 b(See)27 b(App)s(endix)e(B)i(for)g(the)0 1339 y(de\014nition)j(of)h(the)f(parameters)h(used)e(in)h(these)h (routines.)0 1599 y Fi(1)81 b Fj(Get)23 b(the)f(curren)m(t)f(system)i (date.)38 b(C)22 b(already)g(pro)m(vides)g(standard)f(library)h (routines)g(for)f(getting)j(the)e(curren)m(t)227 1712 y(date)k(and)e(time,)j(but)d(this)h(routine)g(is)g(pro)m(vided)g(for)f (compatibilit)m(y)k(with)c(the)h(F)-8 b(ortran)26 b(FITSIO)e(library)-8 b(.)227 1825 y(The)30 b(returned)f(y)m(ear)j(has)e(4)g(digits)h (\(1999,)i(2000,)g(etc.\))95 2085 y Fe(int)47 b (fits_get_system_date/ffgsd)o(t)286 2198 y(\()h(>)f(int)g(*day,)g(int)f (*month,)g(int)h(*year,)f(int)h(*status)f(\))0 2458 y Fi(2)81 b Fj(Get)34 b(the)g(curren)m(t)g(system)f(date)i(and)e(time)h (string)g(\('YYYY-MM-DDThh:mm:ss'\).)53 b(The)33 b(time)i(will)f(b)s(e) 227 2571 y(in)26 b(UTC/GMT)g(if)g(a)m(v)-5 b(ailable,)29 b(as)e(indicated)f(b)m(y)g(a)g(returned)f(timeref)h(v)-5 b(alue)27 b(=)e(0.)40 b(If)26 b(the)g(returned)e(v)-5 b(alue)227 2684 y(of)31 b(timeref)g(=)g(1)g(then)f(this)h(indicates)g (that)h(it)f(w)m(as)g(not)g(p)s(ossible)f(to)h(con)m(v)m(ert)i(the)d (lo)s(cal)i(time)g(to)f(UTC,)227 2797 y(and)f(th)m(us)g(the)h(lo)s(cal) g(time)g(w)m(as)g(returned.)95 3057 y Fe(int)47 b (fits_get_system_time/ffgst)o(m)286 3170 y(\(>)h(char)e(*datestr,)f (int)95 b(*timeref,)45 b(int)i(*status\))0 3431 y Fi(3)81 b Fj(Construct)26 b(a)i(date)g(string)f(from)g(the)g(input)f(date)i(v) -5 b(alues.)40 b(If)27 b(the)g(y)m(ear)h(is)g(b)s(et)m(w)m(een)f(1900)i (and)e(1998,)j(inclu-)227 3544 y(siv)m(e,)38 b(then)c(the)i(returned)d (date)j(string)f(will)g(ha)m(v)m(e)i(the)e(old)g(FITS)f(format)i (\('dd/mm/yy'\),)h(otherwise)227 3656 y(the)32 b(date)f(string)g(will)h (ha)m(v)m(e)g(the)g(new)e(FITS)h(format)g(\('YYYY-MM-DD'\).)36 b(Use)31 b(\014ts)p 3229 3656 28 4 v 33 w(time2str)h(instead)227 3769 y(to)f(alw)m(a)m(ys)h(return)e(a)g(date)h(string)g(using)f(the)g (new)g(FITS)g(format.)95 4030 y Fe(int)47 b(fits_date2str/ffdt2s)286 4143 y(\(int)g(year,)f(int)h(month,)f(int)h(day,)g(>)g(char)g (*datestr,)e(int)i(*status\))0 4403 y Fi(4)81 b Fj(Construct)34 b(a)i(new-format)f(date)h(+)f(time)h(string)f (\('YYYY-MM-DDThh:mm:ss.ddd...'\).)57 b(If)34 b(the)i(y)m(ear,)227 4516 y(mon)m(th,)d(and)e(da)m(y)h(v)-5 b(alues)32 b(all)h(=)e(0)h(then) g(only)g(the)g(time)g(is)g(enco)s(ded)f(with)h(format)g ('hh:mm:ss.ddd...'.)227 4629 y(The)j(decimals)h(parameter)g(sp)s (eci\014es)e(ho)m(w)i(man)m(y)f(decimal)h(places)g(of)f(fractional)i (seconds)e(to)h(include)227 4742 y(in)30 b(the)h(string.)41 b(If)29 b(`decimals')j(is)f(negativ)m(e,)h(then)f(only)f(the)h(date)g (will)f(b)s(e)g(return)f(\('YYYY-MM-DD'\).)95 5002 y Fe(int)47 b(fits_time2str/fftm2s)286 5115 y(\(int)g(year,)f(int)h (month,)f(int)h(day,)g(int)g(hour,)f(int)h(minute,)f(double)g(second,) 286 5228 y(int)h(decimals,)f(>)h(char)g(*datestr,)e(int)i(*status\))0 5488 y Fi(5)81 b Fj(Return)44 b(the)g(date)i(as)f(read)f(from)h(the)g (input)e(string,)49 b(where)44 b(the)h(string)g(ma)m(y)g(b)s(e)f(in)h (either)g(the)g(old)227 5601 y(\('dd/mm/yy'\))29 b(or)f(new)f (\('YYYY-MM-DDThh:mm:ss')k(or)d('YYYY-MM-DD'\))j(FITS)d(format.)40 b(Null)227 5714 y(p)s(oin)m(ters)31 b(ma)m(y)f(b)s(e)g(supplied)f(for)h (an)m(y)h(un)m(w)m(an)m(ted)g(output)f(date)h(parameters.)p eop end %%Page: 68 76 TeXDict begin 68 75 bop 0 299 a Fj(68)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_str2date/ffs2dt)286 668 y(\(char)g(*datestr,)e(>)i(int)g(*year,)f(int)h(*month,)f(int)h (*day,)f(int)h(*status\))0 908 y Fi(6)81 b Fj(Return)30 b(the)h(date)h(and)f(time)h(as)f(read)g(from)g(the)h(input)e(string,)h (where)g(the)h(string)f(ma)m(y)h(b)s(e)e(in)h(either)h(the)227 1020 y(old)d(or)f(new)g(FITS)g(format.)40 b(The)28 b(returned)f(hours,) h(min)m(utes,)h(and)f(seconds)g(v)-5 b(alues)29 b(will)f(b)s(e)g(set)h (to)g(zero)227 1133 y(if)k(the)h(input)e(string)h(do)s(es)g(not)h (include)f(the)g(time)h(\('dd/mm/yy')f(or)h('YYYY-MM-DD'\))j(.)c (Similarly)-8 b(,)227 1246 y(the)36 b(returned)e(y)m(ear,)j(mon)m(th,)g (and)d(date)i(v)-5 b(alues)36 b(will)f(b)s(e)g(set)h(to)g(zero)g(if)f (the)g(date)h(is)f(not)h(included)e(in)227 1359 y(the)29 b(input)f(string)h(\('hh:mm:ss.ddd...'\).)40 b(Null)29 b(p)s(oin)m(ters)f(ma)m(y)i(b)s(e)e(supplied)f(for)i(an)m(y)g(un)m(w)m (an)m(ted)g(output)227 1472 y(date)i(and)f(time)h(parameters.)95 1711 y Fe(int)47 b(fits_str2time/ffs2tm)286 1824 y(\(char)g(*datestr,)e (>)i(int)g(*year,)f(int)h(*month,)f(int)h(*day,)f(int)h(*hour,)286 1937 y(int)g(*minute,)f(double)g(*second,)f(int)i(*status\))0 2225 y Fd(5.8.3)112 b(General)39 b(Utilit)m(y)e(Routines)0 2444 y Fj(The)30 b(follo)m(wing)i(utilit)m(y)f(routines)g(ma)m(y)g(b)s (e)e(useful)h(for)g(certain)h(applications.)0 2683 y Fi(1)81 b Fj(Return)30 b(the)h(revision)g(n)m(um)m(b)s(er)f(of)h(the)g (CFITSIO)f(library)-8 b(.)42 b(The)31 b(revision)g(n)m(um)m(b)s(er)f (will)h(b)s(e)f(incremen)m(ted)227 2796 y(with)i(eac)m(h)i(new)e (release)i(of)f(CFITSIO.)e(The)h(3)h(\014elds)f(of)g(the)h(v)m(ersion)g (string)f(M.xx.yy)i(are)e(con)m(v)m(erted)227 2909 y(to)f(a)g(\015oat)g (as:)41 b(M)31 b(+)f(.01*xx)i(+)e(.0001*yy)-8 b(.)95 3148 y Fe(float)47 b(fits_get_version)c(/)48 b(ffvers)e(\()h(>)h(float) e(*version\))0 3388 y Fi(2)81 b Fj(W)-8 b(rite)34 b(an)g(80-c)m (haracter)i(message)e(to)g(the)g(CFITSIO)e(error)h(stac)m(k.)51 b(Application)34 b(programs)f(should)g(not)227 3501 y(normally)e(write) f(to)i(the)e(stac)m(k,)i(but)e(there)g(ma)m(y)h(b)s(e)f(some)h (situations)g(where)f(this)g(is)h(desirable.)95 3740 y Fe(void)47 b(fits_write_errmsg)c(/)48 b(ffpmsg)e(\(char)g(*err_msg\)) 0 3979 y Fi(3)81 b Fj(Con)m(v)m(ert)31 b(a)g(c)m(haracter)h(string)e (to)h(upp)s(ercase)e(\(op)s(erates)j(in)e(place\).)95 4219 y Fe(void)47 b(fits_uppercase)d(/)j(ffupch)g(\(char)f(*string\))0 4458 y Fi(4)81 b Fj(Compare)43 b(the)i(input)e(template)i(string)f (against)h(the)g(reference)f(string)g(to)h(see)g(if)f(they)g(matc)m(h.) 82 b(The)227 4571 y(template)36 b(string)f(ma)m(y)g(con)m(tain)g (wildcard)f(c)m(haracters:)51 b('*')35 b(will)g(matc)m(h)g(an)m(y)g (sequence)g(of)f(c)m(haracters)227 4684 y(\(including)j(zero)h(c)m (haracters\))g(and)e(')10 b(?')60 b(will)38 b(matc)m(h)f(an)m(y)g (single)h(c)m(haracter)g(in)f(the)g(reference)g(string.)227 4797 y(The)e('#')h(c)m(haracter)h(will)f(matc)m(h)g(an)m(y)g (consecutiv)m(e)h(string)f(of)f(decimal)i(digits)f(\(0)g(-)f(9\).)57 b(If)35 b(casesen)h(=)227 4910 y(CASESEN)c(=)h(TR)m(UE)h(then)f(the)g (matc)m(h)i(will)e(b)s(e)g(case)h(sensitiv)m(e,)i(otherwise)e(the)f (case)i(of)e(the)h(letters)227 5023 y(will)g(b)s(e)f(ignored)h(if)g (casesen)g(=)g(CASEINSEN)e(=)h(F)-10 b(ALSE.)34 b(The)f(returned)f(MA) -8 b(TCH)34 b(parameter)h(will)227 5136 y(b)s(e)30 b(TR)m(UE)g(if)g (the)g(2)h(strings)f(matc)m(h,)h(and)f(EXA)m(CT)g(will)g(b)s(e)g(TR)m (UE)g(if)g(the)g(matc)m(h)h(is)f(exact)i(\(i.e.,)g(if)e(no)227 5249 y(wildcard)k(c)m(haracters)i(w)m(ere)f(used)e(in)h(the)h(matc)m (h\).)53 b(Both)35 b(strings)g(m)m(ust)f(b)s(e)f(68)j(c)m(haracters)f (or)g(less)f(in)227 5362 y(length.)95 5601 y Fe(void)47 b(fits_compare_str)c(/)48 b(ffcmps)334 5714 y(\(char)e(*templt,)g(char) h(*string,)e(int)i(casesen,)f(>)h(int)g(*match,)f(int)h(*exact\))p eop end %%Page: 69 77 TeXDict begin 69 76 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(69)0 555 y Fi(5)81 b Fj(Split)30 b(a)i(string)f(con)m(taining)h(a)g(list)f(of)g(names)g(\(t)m(ypically)j (\014le)d(names)g(or)g(column)f(names\))i(in)m(to)g(individual)227 668 y(name)23 b(tok)m(ens)g(b)m(y)g(a)g(sequence)g(of)g(calls)g(to)h (\014ts)p 1814 668 28 4 v 32 w(split)p 2018 668 V 33 w(names.)38 b(The)22 b(names)h(in)f(the)h(list)g(m)m(ust)f(b)s(e)g (delimited)227 781 y(b)m(y)45 b(a)f(comma)i(and/or)e(spaces.)83 b(This)44 b(routine)g(ignores)h(spaces)g(and)f(commas)h(that)g(o)s (ccur)f(within)227 894 y(paren)m(theses,)36 b(brac)m(k)m(ets,)h(or)e (curly)f(brac)m(k)m(ets.)54 b(It)35 b(also)g(strips)f(an)m(y)h(leading) g(and)f(trailing)h(blanks)f(from)227 1007 y(the)d(returned)e(name.)227 1156 y(This)h(routine)g(is)h(similar)f(to)h(the)g(ANSI)f(C)g('strtok')h (function:)227 1305 y(The)37 b(\014rst)f(call)i(to)g(\014ts)p 1033 1305 V 32 w(split)p 1237 1305 V 33 w(names)f(has)g(a)g(non-n)m (ull)f(input)g(string.)61 b(It)37 b(\014nds)e(the)i(\014rst)f(name)h (in)g(the)227 1418 y(string)26 b(and)f(terminates)h(it)h(b)m(y)e(o)m(v) m(erwriting)i(the)f(next)g(c)m(haracter)h(of)f(the)g(string)f(with)h(a) g(n)m(ull)f(terminator)227 1530 y(and)31 b(returns)g(a)h(p)s(oin)m(ter) f(to)i(the)e(name.)45 b(Eac)m(h)32 b(subsequen)m(t)f(call,)j(indicated) e(b)m(y)f(a)h(NULL)g(v)-5 b(alue)32 b(of)g(the)227 1643 y(input)f(string,)i(returns)e(the)h(next)h(name,)f(searc)m(hing)h(from) f(just)g(past)g(the)g(end)f(of)i(the)f(previous)g(name.)227 1756 y(It)f(returns)e(NULL)h(when)g(no)g(further)f(names)h(are)h (found.)143 2008 y Fe(char)47 b(*fits_split_names\(char)42 b(*namelist\))0 2259 y Fj(The)30 b(follo)m(wing)i(example)f(sho)m(ws)f (ho)m(w)g(a)h(string)f(w)m(ould)h(b)s(e)e(split)i(in)m(to)g(3)g(names:) 191 2511 y Fe(myfile[1][bin)44 b(\(x,y\)=4],)h(file2.fits)93 b(file3.fits)191 2624 y(^^^^^^^^^^^^^^^^^^^^^^)c(^^^^^^^^^^)k (^^^^^^^^^^)382 2737 y(1st)47 b(name)619 b(2nd)47 b(name)190 b(3rd)47 b(name)0 2988 y Fi(6)81 b Fj(T)-8 b(est)34 b(that)g(the)g(k)m (eyw)m(ord)g(name)f(con)m(tains)i(only)e(legal)j(c)m(haracters)f (\(A-Z,0-9,)h(h)m(yphen,)d(and)g(underscore\))227 3101 y(or)e(that)g(the)f(k)m(eyw)m(ord)h(record)f(con)m(tains)i(only)e (legal)i(prin)m(table)f(ASCI)s(I)e(c)m(haracters)95 3353 y Fe(int)47 b(fits_test_keyword)c(/)48 b(fftkey)e(\(char)g(*keyname,)g (>)h(int)g(*status\))95 3579 y(int)g(fits_test_record)d(/)j(fftrec)f (\(char)h(*card,)f(>)h(int)g(*status\))0 3830 y Fi(7)81 b Fj(T)-8 b(est)25 b(whether)f(the)h(curren)m(t)f(header)h(con)m(tains) g(an)m(y)g(NULL)g(\(ASCI)s(I)e(0\))j(c)m(haracters.)40 b(These)24 b(c)m(haracters)j(are)227 3943 y(illegal)37 b(in)d(the)h(header,)g(but)f(they)g(will)h(go)g(undetected)g(b)m(y)f (most)h(of)g(the)f(CFITSIO)f(k)m(eyw)m(ord)i(header)227 4056 y(routines,)29 b(b)s(ecause)f(the)h(n)m(ull)f(is)g(in)m(terpreted) g(as)h(the)f(normal)g(end-of-string)h(terminator.)41 b(This)27 b(routine)227 4169 y(returns)h(the)g(p)s(osition)h(of)g(the)g (\014rst)f(n)m(ull)g(c)m(haracter)i(in)f(the)f(header,)h(or)g(zero)g (if)g(there)g(are)g(no)f(n)m(ulls.)40 b(F)-8 b(or)227 4282 y(example)37 b(a)f(returned)f(v)-5 b(alue)37 b(of)f(110)h(w)m (ould)f(indicate)h(that)g(the)f(\014rst)f(NULL)h(is)g(lo)s(cated)h(in)f (the)g(30th)227 4395 y(c)m(haracter)28 b(of)f(the)g(second)f(k)m(eyw)m (ord)h(in)f(the)h(header)f(\(recall)i(that)f(eac)m(h)h(header)e(record) h(is)f(80)h(c)m(haracters)227 4508 y(long\).)45 b(Note)33 b(that)f(this)g(is)f(one)h(of)g(the)g(few)f(CFITSIO)f(routines)h(in)h (whic)m(h)f(the)h(returned)e(v)-5 b(alue)32 b(is)g(not)227 4620 y(necessarily)g(equal)e(to)i(the)e(status)h(v)-5 b(alue\).)95 4872 y Fe(int)47 b(fits_null_check)d(/)j(ffnchk)g(\(char)f (*card,)g(>)h(int)g(*status\))0 5124 y Fi(8)81 b Fj(P)m(arse)25 b(a)g(header)g(k)m(eyw)m(ord)g(record)g(and)f(return)g(the)h(name)g(of) g(the)g(k)m(eyw)m(ord,)i(and)d(the)h(length)h(of)f(the)g(name.)227 5237 y(The)34 b(k)m(eyw)m(ord)h(name)f(normally)h(o)s(ccupies)f(the)h (\014rst)e(8)i(c)m(haracters)g(of)g(the)f(record,)i(except)f(under)e (the)227 5349 y(HIERAR)m(CH)e(con)m(v)m(en)m(tion)h(where)e(the)h(name) f(can)h(b)s(e)f(up)f(to)i(70)g(c)m(haracters)h(in)e(length.)95 5601 y Fe(int)47 b(fits_get_keyname)d(/)j(ffgknm)286 5714 y(\(char)g(*card,)f(>)h(char)g(*keyname,)e(int)i(*keylength,)e (int)i(*status\))p eop end %%Page: 70 78 TeXDict begin 70 77 bop 0 299 a Fj(70)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(9)81 b Fj(P)m(arse)29 b(a)h(header)f(k)m(eyw)m (ord)h(record,)f(returning)g(the)g(v)-5 b(alue)30 b(\(as)g(a)f(literal) i(c)m(haracter)g(string\))e(and)g(commen)m(t)227 668 y(strings.)40 b(If)27 b(the)g(k)m(eyw)m(ord)h(has)f(no)g(v)-5 b(alue)28 b(\(columns)f(9-10)i(not)f(equal)f(to)h('=)g('\),)g(then)f(a) h(n)m(ull)f(v)-5 b(alue)28 b(string)227 781 y(is)j(returned)e(and)h (the)g(commen)m(t)i(string)e(is)g(set)h(equal)g(to)g(column)f(9)h(-)g (80)g(of)g(the)f(input)g(string.)95 1034 y Fe(int)47 b(fits_parse_value)d(/)j(ffpsvc)286 1147 y(\(char)g(*card,)f(>)h(char)g (*value,)f(char)g(*comment,)g(int)h(*status\))0 1401 y Fi(10)f Fj(Construct)40 b(a)g(prop)s(erly)f(formated)i(80-c)m (haracter)i(header)d(k)m(eyw)m(ord)g(record)g(from)g(the)g(input)f(k)m (eyw)m(ord)227 1514 y(name,)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)25 b(and)e(k)m(eyw)m(ord)h(commen)m(t)g(strings.)38 b(Hierarc)m(hical)26 b(k)m(eyw)m(ord)e(names)f(\(e.g.,)j("ESO)227 1627 y(TELE)e(CAM"\))i(are)f(supp)s(orted.)37 b(The)25 b(v)-5 b(alue)25 b(string)g(ma)m(y)h(con)m(tain)g(an)f(in)m(teger,)i (\015oating)f(p)s(oin)m(t,)g(logical,)227 1739 y(or)31 b(quoted)f(c)m(haracter)i(string)e(\(e.g.,)j("12",)f("15.7",)h("T",)e (or)g("'NGC)g(1313'"\).)143 1993 y Fe(int)47 b(fits_make_key)d(/)k (ffmkky)334 2106 y(\(const)e(char)h(*keyname,)e(const)h(char)h(*value,) f(const)g(char)h(*comment,)430 2219 y(>)g(char)g(*card,)f(int)h (*status\))0 2472 y Fi(11)f Fj(Construct)26 b(an)h(arra)m(y)g(indexed)f (k)m(eyw)m(ord)h(name)f(\(R)m(OOT)g(+)h(nnn\).)38 b(This)26 b(routine)g(app)s(ends)f(the)i(sequence)227 2585 y(n)m(um)m(b)s(er)i (to)i(the)g(ro)s(ot)g(string)f(to)h(create)h(a)f(k)m(eyw)m(ord)g(name)f (\(e.g.,)i('NAXIS')f(+)f(2)h(=)f('NAXIS2'\))95 2838 y Fe(int)47 b(fits_make_keyn)d(/)k(ffkeyn)286 2951 y(\(char)f(*keyroot,)e (int)i(value,)f(>)h(char)g(*keyname,)e(int)i(*status\))0 3205 y Fi(12)f Fj(Construct)41 b(a)h(sequence)f(k)m(eyw)m(ord)h(name)g (\(n)f(+)g(R)m(OOT\).)g(This)g(routine)g(concatenates)j(the)e(sequence) 227 3318 y(n)m(um)m(b)s(er)20 b(to)j(the)e(fron)m(t)h(of)g(the)f(ro)s (ot)h(string)g(to)g(create)h(a)f(k)m(eyw)m(ord)g(name)g(\(e.g.,)j(1)d (+)f('CTYP')g(=)g('1CTYP'\))95 3684 y Fe(int)47 b(fits_make_nkey)d(/)k (ffnkey)286 3797 y(\(int)f(value,)f(char)h(*keyroot,)e(>)i(char)g (*keyname,)e(int)i(*status\))0 4050 y Fi(13)f Fj(Determine)41 b(the)g(data)f(t)m(yp)s(e)h(of)f(a)h(k)m(eyw)m(ord)f(v)-5 b(alue)41 b(string.)70 b(This)39 b(routine)i(parses)e(the)i(k)m(eyw)m (ord)f(v)-5 b(alue)227 4163 y(string)28 b(to)h(determine)f(its)g(data)h (t)m(yp)s(e.)40 b(Returns)27 b('C',)h('L',)h('I',)f('F')h(or)f('X',)g (for)g(c)m(haracter)i(string,)e(logical,)227 4276 y(in)m(teger,)k (\015oating)g(p)s(oin)m(t,)e(or)h(complex,)g(resp)s(ectiv)m(ely)-8 b(.)95 4530 y Fe(int)47 b(fits_get_keytype)d(/)j(ffdtyp)286 4642 y(\(char)g(*value,)f(>)h(char)g(*dtype,)e(int)i(*status\))0 4896 y Fi(14)f Fj(Determine)39 b(the)f(in)m(teger)h(data)g(t)m(yp)s(e)f (of)g(an)g(in)m(teger)h(k)m(eyw)m(ord)f(v)-5 b(alue)39 b(string.)63 b(The)37 b(returned)g(datat)m(yp)s(e)227 5009 y(v)-5 b(alue)36 b(is)f(the)g(minim)m(um)f(in)m(teger)i(datat)m (yp)s(e)g(\(starting)g(from)f(top)g(of)g(the)g(follo)m(wing)i(list)e (and)g(w)m(orking)227 5122 y(do)m(wn\))c(required)e(to)i(store)g(the)g (in)m(teger)h(v)-5 b(alue:)191 5375 y Fe(Data)47 b(Type)285 b(Range)239 5488 y(TSBYTE:)236 b(-128)47 b(to)g(127)239 5601 y(TBYTE:)332 b(128)47 b(to)g(255)239 5714 y(TSHORT:)236 b(-32768)46 b(to)i(32767)p eop end %%Page: 71 79 TeXDict begin 71 78 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(71)239 555 y Fe(TUSHORT:)236 b(32768)46 b(to)i(65535)239 668 y(TINT)380 b(-2147483648)45 b(to)i(2147483647)239 781 y(TUINT)380 b(2147483648)45 b(to)i(4294967295)239 894 y(TLONGLONG)140 b(-9223372036854775808)43 b(to)k(9223372036854775807)80 1167 y Fj(The)30 b(*neg)h(parameter)g (returns)e(1)i(if)f(the)h(input)e(v)-5 b(alue)31 b(is)g(negativ)m(e)h (and)e(returns)f(0)i(if)f(it)h(is)g(non-negativ)m(e.)95 1441 y Fe(int)47 b(fits_get_inttype)d(/)j(ffinttyp)286 1554 y(\(char)g(*value,)f(>)h(int)g(*datatype,)e(int)i(*neg,)f(int)h (*status\))0 1827 y Fi(15)f Fj(Return)35 b(the)g(class)h(of)g(an)f (input)g(header)g(record.)56 b(The)35 b(record)g(is)g(classi\014ed)h (in)m(to)h(one)e(of)h(the)f(follo)m(wing)227 1940 y(categories)d(\(the) e(class)g(v)-5 b(alues)30 b(are)f(de\014ned)f(in)h(\014tsio.h\).)41 b(Note)31 b(that)e(this)h(is)f(one)h(of)f(the)g(few)g(CFITSIO)227 2053 y(routines)i(that)f(do)s(es)h(not)f(return)f(a)i(status)g(v)-5 b(alue.)334 2327 y Fe(Class)94 b(Value)619 b(Keywords)95 2439 y(TYP_STRUC_KEY)92 b(10)j(SIMPLE,)46 b(BITPIX,)g(NAXIS,)g(NAXISn,) g(EXTEND,)g(BLOCKED,)1002 2552 y(GROUPS,)g(PCOUNT,)g(GCOUNT,)g(END)1002 2665 y(XTENSION,)g(TFIELDS,)f(TTYPEn,)h(TBCOLn,)g(TFORMn,)g(THEAP,)1002 2778 y(and)h(the)g(first)f(4)i(COMMENT)e(keywords)f(in)i(the)g(primary) f(array)1002 2891 y(that)h(define)f(the)h(FITS)g(format.)95 3004 y(TYP_CMPRS_KEY)92 b(20)j(The)47 b(keywords)f(used)g(in)i(the)e (compressed)f(image)i(or)g(table)1002 3117 y(format,)f(including)f (ZIMAGE,)h(ZCMPTYPE,)f(ZNAMEn,)h(ZVALn,)1002 3230 y(ZTILEn,)g(ZBITPIX,) g(ZNAXISn,)f(ZSCALE,)h(ZZERO,)g(ZBLANK)95 3343 y(TYP_SCAL_KEY)140 b(30)95 b(BSCALE,)46 b(BZERO,)g(TSCALn,)g(TZEROn)95 3456 y(TYP_NULL_KEY)140 b(40)95 b(BLANK,)46 b(TNULLn)95 3569 y(TYP_DIM_KEY)188 b(50)95 b(TDIMn)95 3681 y(TYP_RANG_KEY)140 b(60)95 b(TLMINn,)46 b(TLMAXn,)g(TDMINn,)g(TDMAXn,)g(DATAMIN,)f (DATAMAX)95 3794 y(TYP_UNIT_KEY)140 b(70)95 b(BUNIT,)46 b(TUNITn)95 3907 y(TYP_DISP_KEY)140 b(80)95 b(TDISPn)95 4020 y(TYP_HDUID_KEY)d(90)j(EXTNAME,)46 b(EXTVER,)g(EXTLEVEL,)f (HDUNAME,)g(HDUVER,)h(HDULEVEL)95 4133 y(TYP_CKSUM_KEY)f(100)94 b(CHECKSUM,)46 b(DATASUM)95 4246 y(TYP_WCS_KEY)141 b(110)94 b(WCS)47 b(keywords)f(defined)g(in)h(the)g(the)g(WCS)f(papers,)g (including:)1002 4359 y(CTYPEn,)g(CUNITn,)g(CRVALn,)g(CRPIXn,)g (CROTAn,)f(CDELTn)1002 4472 y(CDj_is,)h(PVj_ms,)g(LONPOLEs,)f(LATPOLEs) 1002 4585 y(TCTYPn,)h(TCTYns,)g(TCUNIn,)g(TCUNns,)g(TCRVLn,)f(TCRVns,)h (TCRPXn,)1002 4698 y(TCRPks,)g(TCDn_k,)g(TCn_ks,)g(TPVn_m,)g(TPn_ms,)f (TCDLTn,)h(TCROTn)1002 4811 y(jCTYPn,)g(jCTYns,)g(jCUNIn,)g(jCUNns,)g (jCRVLn,)f(jCRVns,)h(iCRPXn,)1002 4924 y(iCRPns,)g(jiCDn,)94 b(jiCDns,)46 b(jPVn_m,)g(jPn_ms,)f(jCDLTn,)h(jCROTn)1002 5036 y(\(i,j,m,n)g(are)h(integers,)e(s)i(is)h(any)f(letter\))95 5149 y(TYP_REFSYS_KEY)d(120)j(EQUINOXs,)f(EPOCH,)g(MJD-OBSs,)f (RADECSYS,)g(RADESYSs,)g(DATE-OBS)95 5262 y(TYP_COMM_KEY)140 b(130)47 b(COMMENT,)f(HISTORY,)f(\(blank)h(keyword\))95 5375 y(TYP_CONT_KEY)140 b(140)47 b(CONTINUE)95 5488 y(TYP_USER_KEY)140 b(150)47 b(all)g(other)g(keywords)95 5714 y(int)g(fits_get_keyclass)c (/)48 b(ffgkcl)e(\(char)g(*card\))p eop end %%Page: 72 80 TeXDict begin 72 79 bop 0 299 a Fj(72)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(16)46 b Fj(P)m(arse)28 b(the)g('TF)m(ORM')g (binary)f(table)h(column)g(format)f(string.)40 b(This)27 b(routine)g(parses)g(the)h(input)f(TF)m(ORM)227 668 y(c)m(haracter)38 b(string)d(and)g(returns)g(the)g(in)m(teger)i(data)g(t)m(yp)s(e)f(co)s (de,)h(the)f(rep)s(eat)g(coun)m(t)g(of)g(the)f(\014eld,)i(and,)227 781 y(in)e(the)f(case)i(of)f(c)m(haracter)h(string)f(\014elds,)g(the)g (length)g(of)g(the)g(unit)f(string.)54 b(See)34 b(App)s(endix)f(B)i (for)g(the)227 894 y(allo)m(w)m(ed)41 b(v)-5 b(alues)38 b(for)h(the)f(returned)g(t)m(yp)s(eco)s(de)h(parameter.)65 b(A)39 b(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)g(b)s(e)f(giv)m(en)h(for)g (an)m(y)227 1007 y(output)30 b(parameters)h(that)g(are)g(not)f(needed.) 143 1264 y Fe(int)47 b(fits_binary_tform)c(/)48 b(ffbnfm)334 1377 y(\(char)e(*tform,)g(>)i(int)f(*typecode,)e(long)h(*repeat,)g (long)g(*width,)382 1490 y(int)h(*status\))143 1716 y(int)g (fits_binary_tformll)c(/)k(ffbnfmll)334 1829 y(\(char)f(*tform,)g(>)i (int)f(*typecode,)e(LONGLONG)g(*repeat,)h(long)g(*width,)382 1942 y(int)h(*status\))0 2199 y Fi(17)f Fj(P)m(arse)38 b(the)f('TF)m(ORM')h(k)m(eyw)m(ord)g(v)-5 b(alue)37 b(that)h(de\014nes) e(the)h(column)g(format)h(in)e(an)h(ASCI)s(I)f(table.)62 b(This)227 2312 y(routine)29 b(parses)g(the)g(input)f(TF)m(ORM)h(c)m (haracter)h(string)f(and)g(returns)e(the)i(data)h(t)m(yp)s(e)f(co)s (de,)h(the)f(width)227 2425 y(of)f(the)f(column,)h(and)f(\(if)h(it)g (is)f(a)h(\015oating)g(p)s(oin)m(t)g(column\))f(the)h(n)m(um)m(b)s(er)e (of)h(decimal)i(places)f(to)g(the)f(righ)m(t)227 2538 y(of)39 b(the)f(decimal)h(p)s(oin)m(t.)65 b(The)38 b(returned)f(data)i (t)m(yp)s(e)f(co)s(des)g(are)h(the)g(same)f(as)h(for)f(the)g(binary)g (table,)227 2651 y(with)26 b(the)h(follo)m(wing)h(additional)f(rules:) 38 b(in)m(teger)28 b(columns)e(that)h(are)f(b)s(et)m(w)m(een)h(1)g(and) f(4)g(c)m(haracters)i(wide)227 2764 y(are)i(de\014ned)e(to)j(b)s(e)d (short)i(in)m(tegers)g(\(co)s(de)g(=)g(TSHOR)-8 b(T\).)29 b(Wider)g(in)m(teger)i(columns)e(are)h(de\014ned)e(to)j(b)s(e)227 2877 y(regular)39 b(in)m(tegers)g(\(co)s(de)g(=)f(TLONG\).)h(Similarly) -8 b(,)41 b(Fixed)e(decimal)g(p)s(oin)m(t)f(columns)g(\(with)h(TF)m (ORM)227 2990 y(=)c('Fw.d'\))g(are)h(de\014ned)d(to)j(b)s(e)e(single)i (precision)f(reals)h(\(co)s(de)f(=)g(TFLO)m(A)-8 b(T\))35 b(if)g(w)g(is)g(b)s(et)m(w)m(een)g(1)h(and)227 3103 y(7)42 b(c)m(haracters)h(wide,)h(inclusiv)m(e.)75 b(Wider)41 b('F')h(columns)f(will)h(return)e(a)i(double)f(precision)h(data)g(co)s (de)227 3216 y(\(=)32 b(TDOUBLE\).)h('Ew.d')f(format)g(columns)g(will)g (ha)m(v)m(e)i(dataco)s(de)f(=)e(TFLO)m(A)-8 b(T,)33 b(and)e('Dw.d')i (format)227 3329 y(columns)45 b(will)h(ha)m(v)m(e)h(dataco)s(de)f(=)f (TDOUBLE.)g(A)h(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(giv)m(en)i (for)e(an)m(y)g(output)227 3441 y(parameters)31 b(that)g(are)g(not)f (needed.)95 3699 y Fe(int)47 b(fits_ascii_tform)d(/)j(ffasfm)286 3812 y(\(char)g(*tform,)f(>)h(int)g(*typecode,)e(long)i(*width,)e(int)i (*decimals,)334 3925 y(int)g(*status\))0 4183 y Fi(18)f Fj(Calculate)32 b(the)f(starting)g(column)g(p)s(ositions)f(and)g(total) i(ASCI)s(I)d(table)j(width)d(based)i(on)f(the)h(input)e(arra)m(y)227 4295 y(of)e(ASCI)s(I)e(table)i(TF)m(ORM)g(v)-5 b(alues.)40 b(The)26 b(SP)-8 b(A)m(CE)27 b(input)e(parameter)i(de\014nes)f(ho)m(w)h (man)m(y)f(blank)h(spaces)227 4408 y(to)40 b(lea)m(v)m(e)i(b)s(et)m(w)m (een)e(eac)m(h)g(column)g(\(it)g(is)f(recommended)g(to)h(ha)m(v)m(e)h (one)e(space)h(b)s(et)m(w)m(een)g(columns)f(for)227 4521 y(b)s(etter)31 b(h)m(uman)e(readabilit)m(y\).)95 4779 y Fe(int)47 b(fits_get_tbcol)d(/)k(ffgabc)286 4892 y(\(int)f(tfields,)f (char)g(**tform,)g(int)h(space,)f(>)h(long)g(*rowlen,)334 5005 y(long)g(*tbcol,)f(int)g(*status\))0 5262 y Fi(19)g Fj(P)m(arse)27 b(a)g(template)h(header)e(record)g(and)g(return)g(a)g (formatted)h(80-c)m(haracter)j(string)c(suitable)h(for)f(app)s(end-)227 5375 y(ing)40 b(to)f(\(or)h(deleting)g(from\))f(a)g(FITS)g(header)g (\014le.)67 b(This)38 b(routine)h(is)g(useful)g(for)f(parsing)h(lines)g (from)227 5488 y(an)33 b(ASCI)s(I)f(template)i(\014le)f(and)g (reformatting)h(them)f(in)m(to)h(legal)h(FITS)d(header)h(records.)49 b(The)32 b(format-)227 5601 y(ted)i(string)g(ma)m(y)g(then)f(b)s(e)g (passed)h(to)g(the)g(\014ts)p 1880 5601 28 4 v 32 w(write)p 2114 5601 V 33 w(record,)h(\013mcrd,)f(or)g(\014ts)p 3007 5601 V 32 w(delete)p 3270 5601 V 34 w(k)m(ey)h(routines)e(to)227 5714 y(app)s(end)c(or)h(mo)s(dify)g(a)h(FITS)e(header)h(record.)p eop end %%Page: 73 81 TeXDict begin 73 80 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(73)95 555 y Fe(int)47 b(fits_parse_template)c (/)k(ffgthd)286 668 y(\(char)g(*templt,)e(>)j(char)e(*card,)g(int)h (*keytype,)f(int)h(*status\))0 932 y Fj(The)31 b(input)g(templt)h(c)m (haracter)h(string)f(generally)h(should)d(con)m(tain)j(3)f(tok)m(ens:) 44 b(\(1\))33 b(the)f(KEYNAME,)g(\(2\))h(the)0 1045 y(V)-10 b(ALUE,)37 b(and)f(\(3\))i(the)f(COMMENT)g(string.)59 b(The)37 b(TEMPLA)-8 b(TE)36 b(string)h(m)m(ust)f(adhere)h(to)h(the)e (follo)m(wing)0 1158 y(format:)0 1421 y Fi(-)80 b Fj(The)32 b(KEYNAME)h(tok)m(en)h(m)m(ust)f(b)s(egin)f(in)h(columns)f(1-8)i(and)e (b)s(e)g(a)h(maxim)m(um)g(of)g(8)g(c)m(haracters)h(long.)49 b(A)227 1534 y(legal)30 b(FITS)e(k)m(eyw)m(ord)h(name)f(ma)m(y)h(only)f (con)m(tain)i(the)f(c)m(haracters)g(A-Z,)g(0-9,)h(and)e('-')h(\(min)m (us)f(sign\))h(and)227 1647 y(underscore.)40 b(This)27 b(routine)i(will)g(automatically)i(con)m(v)m(ert)f(an)m(y)f(lo)m(w)m (ercase)i(c)m(haracters)f(to)g(upp)s(ercase)d(in)227 1760 y(the)k(output)f(string.)42 b(If)30 b(the)h(\014rst)f(8)h(c)m (haracters)h(of)f(the)g(template)h(line)f(are)g(blank)f(then)h(the)g (remainder)227 1873 y(of)g(the)f(line)h(is)g(considered)f(to)h(b)s(e)f (a)g(FITS)g(commen)m(t)h(\(with)g(a)g(blank)f(k)m(eyw)m(ord)g(name\).)0 2137 y Fi(-)80 b Fj(The)26 b(V)-10 b(ALUE)26 b(tok)m(en)h(m)m(ust)e(b)s (e)h(separated)g(from)f(the)i(KEYNAME)f(tok)m(en)h(b)m(y)f(one)g(or)g (more)g(spaces)g(and/or)227 2250 y(an)g('=')g(c)m(haracter.)41 b(The)25 b(data)h(t)m(yp)s(e)g(of)g(the)g(V)-10 b(ALUE)26 b(tok)m(en)g(\(n)m(umeric,)h(logical,)j(or)c(c)m(haracter)h(string\))f (is)227 2363 y(automatically)35 b(determined)c(and)h(the)g(output)f (CARD)h(string)g(is)g(formatted)g(accordingly)-8 b(.)47 b(The)31 b(v)-5 b(alue)227 2476 y(tok)m(en)34 b(ma)m(y)f(b)s(e)f (forced)g(to)i(b)s(e)e(in)m(terpreted)g(as)h(a)g(string)g(\(e.g.)48 b(if)33 b(it)g(is)f(a)h(string)g(of)f(n)m(umeric)h(digits\))g(b)m(y)227 2588 y(enclosing)g(it)f(in)f(single)h(quotes.)45 b(If)31 b(the)h(v)-5 b(alue)32 b(tok)m(en)g(is)g(a)g(c)m(haracter)h(string)e (that)i(con)m(tains)f(1)g(or)g(more)227 2701 y(em)m(b)s(edded)39 b(blank)g(space)h(c)m(haracters)h(or)e(slash)h(\('/'\))h(c)m(haracters) g(then)e(the)g(en)m(tire)i(c)m(haracter)g(string)227 2814 y(m)m(ust)31 b(b)s(e)e(enclosed)i(in)f(single)h(quotes.)0 3078 y Fi(-)80 b Fj(The)28 b(COMMENT)g(tok)m(en)h(is)f(optional,)i(but) e(if)g(presen)m(t)g(m)m(ust)g(b)s(e)g(separated)g(from)g(the)h(V)-10 b(ALUE)28 b(tok)m(en)h(b)m(y)227 3191 y(a)i(blank)f(space)h(or)f(a)h ('/')g(c)m(haracter.)0 3455 y Fi(-)80 b Fj(One)29 b(exception)h(to)f (the)g(ab)s(o)m(v)m(e)i(rules)d(is)h(that)g(if)g(the)g(\014rst)g (non-blank)f(c)m(haracter)i(in)f(the)g(\014rst)f(8)h(c)m(haracters)227 3568 y(of)24 b(the)h(template)g(string)f(is)g(a)g(min)m(us)g(sign)g (\('-'\))h(follo)m(w)m(ed)h(b)m(y)e(a)g(single)h(tok)m(en,)h(or)e(a)h (single)f(tok)m(en)h(follo)m(w)m(ed)227 3681 y(b)m(y)k(an)g(equal)h (sign,)g(then)f(it)g(is)h(in)m(terpreted)f(as)h(the)f(name)g(of)h(a)f (k)m(eyw)m(ord)h(whic)m(h)f(is)g(to)h(b)s(e)e(deleted)i(from)227 3793 y(the)h(FITS)e(header.)0 4057 y Fi(-)80 b Fj(The)32 b(second)g(exception)h(is)f(that)h(if)f(the)g(template)h(string)f (starts)h(with)e(a)i(min)m(us)e(sign)h(and)f(is)h(follo)m(w)m(ed)i(b)m (y)227 4170 y(2)f(tok)m(ens)g(\(without)g(an)f(equals)h(sign)g(b)s(et)m (w)m(een)g(them\))f(then)g(the)h(second)f(tok)m(en)i(is)e(in)m (terpreted)h(as)g(the)227 4283 y(new)f(name)h(for)f(the)h(k)m(eyw)m (ord)g(sp)s(eci\014ed)f(b)m(y)h(\014rst)f(tok)m(en.)48 b(In)32 b(this)g(case)i(the)f(old)g(k)m(eyw)m(ord)g(name)f(\(\014rst) 227 4396 y(tok)m(en\))c(is)e(returned)e(in)i(c)m(haracters)h(1-8)g(of)g (the)f(returned)e(CARD)j(string,)g(and)e(the)h(new)f(k)m(eyw)m(ord)i (name)227 4509 y(\(the)35 b(second)e(tok)m(en\))j(is)e(returned)e(in)i (c)m(haracters)h(41-48)h(of)e(the)g(returned)e(CARD)i(string.)51 b(These)34 b(old)227 4622 y(and)i(new)f(names)h(ma)m(y)h(then)f(b)s(e)f (passed)g(to)i(the)f(\013mnam)g(routine)g(whic)m(h)g(will)g(c)m(hange)h (the)f(k)m(eyw)m(ord)227 4735 y(name.)0 4998 y(The)30 b(k)m(eyt)m(yp)s(e)h(output)f(parameter)h(indicates)g(ho)m(w)g(the)f (returned)g(CARD)g(string)g(should)g(b)s(e)f(in)m(terpreted:)382 5262 y Fe(keytype)857 b(interpretation)382 5375 y(-------)475 b(-------------------------)o(----)o(---)o(----)o(----)o(---)o(----)o (--)525 5488 y(-2)572 b(Rename)46 b(the)h(keyword)f(with)h(name)f(=)i (the)f(first)f(8)h(characters)e(of)j(CARD)1193 5601 y(to)f(the)g(new)g (name)g(given)f(in)h(characters)e(41)j(-)f(48)g(of)g(CARD.)p eop end %%Page: 74 82 TeXDict begin 74 81 bop 0 299 a Fj(74)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)525 555 y Fe(-1)572 b(delete)46 b(the)h(keyword)f(with)h (this)f(name)h(from)g(the)f(FITS)h(header.)573 781 y(0)572 b(append)46 b(the)h(CARD)g(string)f(to)h(the)g(FITS)g(header)f(if)h (the)1193 894 y(keyword)f(does)h(not)g(already)e(exist,)h(otherwise)g (update)1193 1007 y(the)h(keyword)f(value)g(and/or)g(comment)g(field)h (if)g(is)g(already)f(exists.)573 1233 y(1)572 b(This)47 b(is)g(a)g(HISTORY)f(or)h(COMMENT)f(keyword;)g(append)g(it)h(to)g(the)g (header)573 1458 y(2)572 b(END)47 b(record;)f(do)h(not)g(explicitly)e (write)h(it)i(to)f(the)g(FITS)f(file.)0 1708 y Fj(EXAMPLES:)30 b(The)g(follo)m(wing)i(lines)e(illustrate)i(v)-5 b(alid)31 b(input)e(template)j(strings:)286 1958 y Fe(INTVAL)46 b(7)i(/)f(This)g(is)g(an)g(integer)f(keyword)286 2071 y(RVAL)524 b(34.6)142 b(/)239 b(This)46 b(is)i(a)f(floating)f(point)g (keyword)286 2184 y(EVAL=-12.45E-03)92 b(/)47 b(This)g(is)g(a)g (floating)f(point)g(keyword)g(in)h(exponential)e(notation)286 2296 y(lval)i(F)g(/)h(This)f(is)g(a)g(boolean)f(keyword)859 2409 y(This)h(is)g(a)g(comment)f(keyword)g(with)h(a)g(blank)f(keyword)g (name)286 2522 y(SVAL1)h(=)g('Hello)f(world')142 b(/)95 b(this)47 b(is)g(a)g(string)f(keyword)286 2635 y(SVAL2)94 b('123.5')g(this)47 b(is)g(also)f(a)i(string)e(keyword)286 2748 y(sval3)94 b(123+)h(/)g(this)47 b(is)g(also)f(a)i(string)e (keyword)g(with)g(the)h(value)g('123+)189 b(')286 2861 y(#)48 b(the)f(following)e(template)h(line)g(deletes)g(the)h(DATE)g (keyword)286 2974 y(-)h(DATE)286 3087 y(#)g(the)f(following)e(template) h(line)g(modifies)g(the)h(NAME)f(keyword)g(to)h(OBJECT)286 3200 y(-)h(NAME)e(OBJECT)0 3449 y Fi(20)g Fj(T)-8 b(ranslate)32 b(a)g(k)m(eyw)m(ord)g(name)f(in)m(to)h(a)g(new)f(name,)h(based)f(on)g (a)h(set)f(of)h(patterns.)43 b(This)31 b(routine)g(is)h(useful)227 3562 y(for)j(translating)h(k)m(eyw)m(ords)g(in)e(cases)i(suc)m(h)f(as)h (adding)e(or)h(deleting)h(columns)f(in)g(a)g(table,)j(or)d(cop)m(ying) 227 3675 y(a)41 b(column)g(from)f(one)h(table)g(to)g(another,)j(or)c (extracting)j(an)d(arra)m(y)h(from)f(a)h(cell)h(in)e(a)h(binary)f (table)227 3788 y(column)31 b(in)m(to)g(an)g(image)g(extension.)42 b(In)30 b(these)h(cases,)h(it)f(is)g(necessary)g(to)g(translate)h(the)f (names)f(of)h(the)227 3901 y(k)m(eyw)m(ords)f(asso)s(ciated)i(with)d (the)h(original)h(table)g(column\(s\))f(in)m(to)g(the)g(appropriate)g (k)m(eyw)m(ord)g(name)g(in)227 4014 y(the)37 b(\014nal)f(\014le.)58 b(F)-8 b(or)37 b(example,)i(if)d(column)h(2)f(is)h(deleted)g(from)e(a)i (table,)i(then)d(the)h(v)-5 b(alue)36 b(of)h('n')f(in)g(all)227 4127 y(the)c(TF)m(ORMn)g(and)f(TTYPEn)f(k)m(eyw)m(ords)i(for)g(columns) f(3)h(and)f(higher)h(m)m(ust)f(b)s(e)g(decremen)m(ted)i(b)m(y)e(1.)227 4240 y(Ev)m(en)j(more)g(complex)h(translations)f(are)h(sometimes)f (needed)g(to)h(con)m(v)m(ert)g(the)f(W)m(CS)g(k)m(eyw)m(ords)g(when)227 4353 y(extracting)e(an)f(image)g(out)g(of)f(a)h(table)g(column)g(cell)g (in)m(to)h(a)e(separate)i(image)f(extension.)227 4501 y(The)g(user)f(passes)i(an)f(arra)m(y)g(of)h(patterns)f(to)h(b)s(e)e (matc)m(hed.)44 b(Input)30 b(pattern)h(n)m(um)m(b)s(er)f(i)i(is)f (pattern[i][0],)227 4614 y(and)j(output)f(pattern)h(n)m(um)m(b)s(er)f (i)h(is)g(pattern[i][1].)53 b(Keyw)m(ords)34 b(are)g(matc)m(hed)h (against)g(the)f(input)f(pat-)227 4727 y(terns.)41 b(If)30 b(a)g(matc)m(h)i(is)e(found)f(then)h(the)h(k)m(eyw)m(ord)g(is)f (re-written)h(according)g(to)g(the)g(output)f(pattern.)227 4876 y(Order)41 b(is)h(imp)s(ortan)m(t.)76 b(The)41 b(\014rst)h(matc)m (h)h(is)f(accepted.)77 b(The)41 b(fastest)i(matc)m(h)g(will)f(b)s(e)g (made)g(when)227 4989 y(templates)32 b(with)e(the)h(same)f(\014rst)g(c) m(haracter)i(are)f(group)s(ed)e(together.)227 5137 y(Sev)m(eral)j(c)m (haracters)f(ha)m(v)m(e)h(sp)s(ecial)f(meanings:)466 5375 y Fe(i,j)47 b(-)g(single)f(digits,)g(preserved)f(in)j(output)e (template)466 5488 y(n)h(-)h(column)e(number)g(of)h(one)g(or)g(more)g (digits,)f(preserved)f(in)i(output)f(template)466 5601 y(m)h(-)h(generic)e(number)g(of)h(one)g(or)g(more)g(digits,)e (preserved)h(in)h(output)f(template)466 5714 y(a)h(-)h(coordinate)d (designator,)g(preserved)g(in)i(output)f(template)p eop end %%Page: 75 83 TeXDict begin 75 82 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(75)466 555 y Fe(#)47 b(-)h(number)e(of)h(one)g (or)g(more)g(digits)466 668 y(?)g(-)h(any)f(character)466 781 y(*)g(-)h(only)e(allowed)g(in)h(first)g(character)e(position,)g(to) j(match)e(all)657 894 y(keywords;)f(only)i(useful)f(as)h(last)g (pattern)e(in)j(the)f(list)227 1121 y Fj(i,)31 b(j,)f(n,)g(and)g(m)g (are)h(returned)e(b)m(y)i(the)f(routine.)227 1268 y(F)-8 b(or)27 b(example,)g(the)f(input)f(pattern)h("iCTYPn")g(will)g(matc)m (h)h("1CTYP5")g(\(if)f(n)p 3003 1268 28 4 v 32 w(v)-5 b(alue)26 b(is)g(5\);)i(the)e(output)227 1381 y(pattern)31 b("CTYPEi")f(will)h(b)s(e)f(re-written)h(as)f("CTYPE1".)42 b(Notice)32 b(that)f("i")g(is)g(preserv)m(ed.)227 1528 y(The)f(follo)m(wing)i(output)e(patterns)g(are)h(sp)s(ecial:)227 1675 y("-")h(-)e(do)h(not)f(cop)m(y)h(a)g(k)m(eyw)m(ord)g(that)g(matc)m (hes)g(the)g(corresp)s(onding)e(input)h(pattern)227 1822 y("{")i(-)f(if)f(matc)m(h)h(o)s(ccurs,)f(outrec)h(will)g(ha)m(v)m(e)h ("-KEYNAME")227 1969 y("+")f(-)g(cop)m(y)g(the)f(input)g(unc)m(hanged) 227 2116 y(The)f(inrec)h(string)g(could)g(b)s(e)f(just)g(the)h(8-c)m (har)h(k)m(eyw)m(ord)f(name,)g(or)f(the)h(en)m(tire)h(80-c)m(har)g (header)f(record.)227 2229 y(Characters)h(9)g(-)f(80)h(in)g(the)f (input)g(string)g(simply)g(get)h(app)s(ended)e(to)i(the)g(translated)g (k)m(eyw)m(ord)f(name.)227 2376 y(Up)s(on)25 b(return,)g(outrec)h(will) f(ha)m(v)m(e)i(the)e(con)m(v)m(erted)i(string,)f(starting)g(from)f(the) g(pattern[i][1])i(pattern)f(and)227 2489 y(applying)36 b(the)f(n)m(umerical)h(substitutions)f(as)h(describ)s(ed)e(ab)s(o)m(v)m (e.)57 b(If)35 b(the)h(output)f(pattern)g(is)h("{")g(then)227 2602 y(the)g(resulting)g(outrec)h(will)f(b)s(e)f("-KEYNAME",)k(whic)m (h)d(ma)m(y)g(indicate)h(to)g(the)f(calling)h(routine)f(that)227 2715 y(KEYNAME)31 b(is)f(to)h(b)s(e)f(deleted.)227 2862 y(If)h(n)p 375 2862 V 33 w(range)g(=)g(0,)i(then)e(only)h(k)m(eyw)m (ords)f(with)h('n')f(equal)h(to)g(n)p 2410 2862 V 32 w(v)-5 b(alue)32 b(will)g(b)s(e)f(considered)g(as)h(a)g(pattern)227 2975 y(matc)m(h.)70 b(If)39 b(n)p 722 2975 V 32 w(range)h(=)f(+1,)j (then)e(all)g(v)-5 b(alues)40 b(of)g('n')f(greater)i(than)e(or)h(equal) g(to)g(n)p 3269 2975 V 33 w(v)-5 b(alue)40 b(will)g(b)s(e)f(a)227 3088 y(matc)m(h,)32 b(and)e(if)g(-1,)h(then)f(v)-5 b(alues)31 b(of)g('n')f(less)g(than)h(or)f(equal)h(to)g(n)p 2530 3088 V 32 w(v)-5 b(alue)31 b(will)g(matc)m(h.)0 3328 y Fe(int)47 b(fits_translate_keyword\()286 3441 y(char)g(*inrec,)380 b(/*)47 b(I)h(-)f(input)f(string)g(*/)286 3554 y(char)h(*outrec,)332 b(/*)47 b(O)h(-)f(output)f(converted)f(string,)h(or)h(*/)1241 3667 y(/*)238 b(a)47 b(null)g(string)f(if)h(input)g(does)f(not)95 b(*/)1241 3780 y(/*)238 b(match)46 b(any)h(of)g(the)g(patterns)f(*/)286 3893 y(char)h(*patterns[][2],/*)c(I)48 b(-)f(pointer)f(to)h(input)f(/)i (output)e(string)g(*/)1241 4006 y(/*)238 b(templates)45 b(*/)286 4119 y(int)i(npat,)524 b(/*)47 b(I)h(-)f(number)f(of)h (templates)f(passed)g(*/)286 4231 y(int)h(n_value,)380 b(/*)47 b(I)h(-)f(base)g('n')g(template)e(value)h(of)i(interest)d(*/) 286 4344 y(int)i(n_offset,)332 b(/*)47 b(I)h(-)f(offset)f(to)h(be)g (applied)f(to)h(the)g('n')g(*/)1241 4457 y(/*)238 b(value)46 b(in)i(the)e(output)h(string)f(*/)286 4570 y(int)h(n_range,)380 b(/*)47 b(I)h(-)f(controls)f(range)g(of)h('n')g(template)f(*/)1241 4683 y(/*)238 b(values)46 b(of)h(interest)f(\(-1,0,)g(or)h(+1\))g(*/) 286 4796 y(int)g(*pat_num,)332 b(/*)47 b(O)h(-)f(matched)f(pattern)g (number)g(\(0)h(based\))f(or)h(-1)g(*/)286 4909 y(int)g(*i,)620 b(/*)47 b(O)h(-)f(value)f(of)i(i,)f(if)g(any,)g(else)f(0)i(*/)286 5022 y(int)f(*j,)620 b(/*)47 b(O)h(-)f(value)f(of)i(j,)f(if)g(any,)g (else)f(0)i(*/)286 5135 y(int)f(*m,)620 b(/*)47 b(O)h(-)f(value)f(of)i (m,)f(if)g(any,)g(else)f(0)i(*/)286 5248 y(int)f(*n,)620 b(/*)47 b(O)h(-)f(value)f(of)i(n,)f(if)g(any,)g(else)f(0)i(*/)286 5361 y(int)f(*status\))380 b(/*)47 b(IO)g(-)h(error)e(status)g(*/)80 5601 y Fj(Here)25 b(is)f(an)g(example)g(of)g(some)h(of)f(the)g (patterns)g(used)f(to)i(con)m(v)m(ert)g(the)f(k)m(eyw)m(ords)h(asso)s (ciated)g(with)f(an)g(image)227 5714 y(in)30 b(a)h(cell)h(of)e(a)h (table)g(column)f(in)m(to)i(the)e(k)m(eyw)m(ords)h(appropriate)f(for)h (an)f(IMA)m(GE)h(extension:)p eop end %%Page: 76 84 TeXDict begin 76 83 bop 0 299 a Fj(76)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)191 555 y Fe(char)47 b(*patterns[][2])c(=)48 b({{"TSCALn",)92 b("BSCALE")i(},)h(/*)47 b(Standard)e(FITS)i(keywords)e (*/)143 668 y({"TZEROn",)93 b("BZERO")141 b(},)143 781 y({"TUNITn",)93 b("BUNIT")141 b(},)143 894 y({"TNULLn",)93 b("BLANK")141 b(},)143 1007 y({"TDMINn",)93 b("DATAMIN")45 b(},)143 1120 y({"TDMAXn",)93 b("DATAMAX")45 b(},)143 1233 y({"iCTYPn",)93 b("CTYPEi")g(},)i(/*)47 b(Coordinate)e(labels)h (*/)143 1346 y({"iCTYna",)93 b("CTYPEia")45 b(},)143 1458 y({"iCUNIn",)93 b("CUNITi")g(},)i(/*)47 b(Coordinate)e(units)i(*/) 143 1571 y({"iCUNna",)93 b("CUNITia")45 b(},)143 1684 y({"iCRVLn",)93 b("CRVALi")g(},)i(/*)47 b(WCS)g(keywords)f(*/)143 1797 y({"iCRVna",)93 b("CRVALia")45 b(},)143 1910 y({"iCDLTn",)93 b("CDELTi")g(},)143 2023 y({"iCDEna",)g("CDELTia")45 b(},)143 2136 y({"iCRPXn",)93 b("CRPIXi")g(},)143 2249 y({"iCRPna",)g("CRPIXia")45 b(},)143 2362 y({"ijPCna",)93 b("PCi_ja")g(},)143 2475 y({"ijCDna",)g("CDi_ja")g(},)143 2588 y({"iVn_ma",)g("PVi_ma")g(},)143 2700 y({"iSn_ma",)g("PSi_ma")g (},)143 2813 y({"iCRDna",)g("CRDERia")45 b(},)143 2926 y({"iCSYna",)93 b("CSYERia")45 b(},)143 3039 y({"iCROTn",)93 b("CROTAi")g(},)143 3152 y({"WCAXna",)g("WCSAXESa"},)143 3265 y({"WCSNna",)g("WCSNAMEa"}};)0 3497 y Fi(21)46 b Fj(T)-8 b(ranslate)26 b(the)f(k)m(eyw)m(ords)g(in)g(the)g(input)e(HDU)j (in)m(to)g(the)f(k)m(eyw)m(ords)g(that)h(are)f(appropriate)g(for)f(the) h(output)227 3610 y(HDU.)33 b(This)e(is)g(a)h(driv)m(er)f(routine)h (that)g(calls)h(the)e(previously)h(describ)s(ed)e(routine)i(for)f(all)h (k)m(eyw)m(ords)g(in)227 3723 y(the)f(HDU.)227 3868 y(It)g(is)f(allo)m (w)m(ed)i(for)f(infptr)e(and)h(outfptr)f(to)j(p)s(oin)m(t)e(to)h(the)g (same)f(HDU.)227 4014 y(If)c(an)m(y)g(output)g(matc)m(hed)g(patterns)g (are)h(of)f(the)g(form)g("-KEYNAME")h(then)f(this)g(routine)g(will)g (attempt)227 4127 y(to)41 b(delete)f(the)g(k)m(eyw)m(ord)g(KEYNAME.)g (It)g(is)g(not)f(an)h(error)f(if)h(KEYNAME)f(is)h(not)g(presen)m(t)f (in)h(the)227 4240 y(output)30 b(HDU.)0 4472 y Fe(int)47 b(fits_translate_keywords\()143 4585 y(fitsfile)f(*infptr,)141 b(/*)47 b(I)g(-)h(pointer)e(to)h(input)f(HDU)h(*/)143 4698 y(fitsfile)f(*outfptr,)93 b(/*)47 b(I)g(-)h(pointer)e(to)h(output) f(HDU)h(*/)143 4811 y(int)g(firstkey,)332 b(/*)47 b(I)g(-)h(first)e (HDU)h(record)f(number)g(to)h(start)g(with)f(*/)143 4924 y(char)h(*patterns[][2],/*)c(I)k(-)h(pointer)e(to)h(input)f(/)i(output) e(keyword)g(templates)f(*/)143 5036 y(int)i(npat,)524 b(/*)47 b(I)g(-)h(number)e(of)h(templates)e(passed)h(*/)143 5149 y(int)h(n_value,)380 b(/*)47 b(I)g(-)h(base)e('n')h(template)f (value)g(of)h(interest)f(*/)143 5262 y(int)h(n_offset,)332 b(/*)47 b(I)g(-)h(offset)e(to)h(be)g(applied)f(to)h(the)g('n')g(*/)1193 5375 y(/*)238 b(value)47 b(in)g(the)g(output)f(string)g(*/)143 5488 y(int)h(n_range,)380 b(/*)47 b(I)g(-)h(controls)d(range)i(of)g ('n')g(template)e(*/)1098 5601 y(/*)238 b(values)46 b(of)h(interest)f (\(-1,0,)g(or)h(+1\))g(*/)143 5714 y(int)g(*status\))380 b(/*)47 b(IO)g(-)h(error)e(status)g(*/)p eop end %%Page: 77 85 TeXDict begin 77 84 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(77)0 555 y Fi(22)46 b Fj(P)m(arse)35 b(the)g(input)f(string)h(con)m(taining)h(a)f(list)h(of)f(ro)m(ws)f(or)h (ro)m(w)g(ranges,)h(and)e(return)g(in)m(teger)i(arra)m(ys)f(con-)227 668 y(taining)27 b(the)f(\014rst)f(and)g(last)i(ro)m(w)f(in)f(eac)m(h)i (range.)40 b(F)-8 b(or)26 b(example,)i(if)d(ro)m(wlist)i(=)e("3-5,)k (6,)e(8-9")h(then)d(it)i(will)227 781 y(return)34 b(n)m(umranges)h(=)g (3,)h(rangemin)f(=)g(3,)i(6,)g(8)e(and)g(rangemax)g(=)g(5,)i(6,)g(9.)55 b(A)m(t)36 b(most,)h('maxranges')227 894 y(n)m(um)m(b)s(er)31 b(of)h(ranges)f(will)h(b)s(e)g(returned.)43 b('maxro)m(ws')32 b(is)g(the)g(maxim)m(um)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)f(the)h (table;)227 1007 y(an)m(y)e(ro)m(ws)f(or)g(ranges)g(larger)h(than)f (this)g(will)g(b)s(e)g(ignored.)40 b(The)29 b(ro)m(ws)g(m)m(ust)g(b)s (e)f(sp)s(eci\014ed)h(in)f(increasing)227 1120 y(order,)33 b(and)f(the)g(ranges)h(m)m(ust)f(not)g(o)m(v)m(erlap.)48 b(A)33 b(min)m(us)e(sign)i(ma)m(y)g(b)s(e)e(use)h(to)h(sp)s(ecify)f (all)h(the)g(ro)m(ws)f(to)227 1233 y(the)h(upp)s(er)d(or)j(lo)m(w)m(er) h(b)s(ound,)d(so)i("50-")h(means)e(all)i(the)f(ro)m(ws)f(from)g(50)h (to)h(the)e(end)g(of)h(the)f(table,)j(and)227 1346 y("-")d(means)e(all) h(the)g(ro)m(ws)f(in)g(the)h(table,)g(from)f(1)h(-)g(maxro)m(ws.)191 1581 y Fe(int)47 b(fits_parse_range)c(/)48 b(ffrwrg\(char)c(*rowlist,)i (LONGLONG)f(maxrows,)h(int)h(maxranges,)e(>)334 1694 y(int)i(*numranges,)e(long)h(*rangemin,)f(long)i(*rangemax,)e(int)i (*status\))191 1920 y(int)g(fits_parse_rangell)c(/)k(ffrwrgll\(char)d (*rowlist,)i(LONGLONG)f(maxrows,)h(int)h(maxranges,)e(>)334 2033 y(int)i(*numranges,)e(LONGLONG)g(*rangemin,)g(LONGLONG)h (*rangemax,)f(int)i(*status\))0 2268 y Fi(23)f Fj(Chec)m(k)37 b(that)g(the)g(Header)g(\014ll)g(b)m(ytes)g(\(if)g(an)m(y\))g(are)g (all)h(blank.)59 b(These)36 b(are)h(the)g(b)m(ytes)g(that)g(ma)m(y)h (follo)m(w)227 2381 y(END)e(k)m(eyw)m(ord)g(and)f(b)s(efore)g(the)h(b)s (eginning)f(of)h(data)g(unit,)g(or)g(the)g(end)f(of)g(the)h(HDU)g(if)g (there)f(is)h(no)227 2494 y(data)31 b(unit.)191 2730 y Fe(int)47 b(ffchfl\(fitsfile)c(*fptr,)k(>)g(int)g(*status\))0 2965 y Fi(24)f Fj(Chec)m(k)30 b(that)g(the)f(Data)i(\014ll)e(b)m(ytes)h (\(if)g(an)m(y\))g(are)g(all)g(zero)g(\(for)f(IMA)m(GE)i(or)e(BINAR)-8 b(Y)30 b(T)-8 b(able)30 b(HDU\))h(or)e(all)227 3078 y(blanks)g(\(for)g (ASCI)s(I)f(table)i(HDU\).)g(These)f(\014le)g(b)m(ytes)h(ma)m(y)f(b)s (e)g(lo)s(cated)h(after)g(the)f(last)h(v)-5 b(alid)29 b(data)h(b)m(yte)227 3191 y(in)g(the)h(HDU)g(and)f(b)s(efore)g(the)g (ph)m(ysical)h(end)f(of)h(the)f(HDU.)191 3427 y Fe(int)47 b(ffcdfl\(fitsfile)c(*fptr,)k(>)g(int)g(*status\))0 3662 y Fi(25)f Fj(Estimate)35 b(the)e(ro)s(ot-mean-squared)h(\(RMS\))f (noise)h(in)f(an)g(image.)51 b(These)33 b(routines)g(are)h(mainly)f (for)g(use)227 3775 y(with)25 b(the)g(Hcompress)g(image)i(compression)e (algorithm.)40 b(They)24 b(return)g(an)h(estimate)i(of)e(the)h(RMS)f (noise)227 3888 y(in)38 b(the)f(bac)m(kground)h(pixels)f(of)h(the)g (image.)64 b(This)36 b(robust)h(algorithm)i(\(written)f(b)m(y)f(Ric)m (hard)h(White,)227 4001 y(STScI\))e(\014rst)f(attempts)i(to)g(estimate) h(the)f(RMS)e(v)-5 b(alue)37 b(as)g(1.68)g(times)g(the)f(median)g(of)h (the)f(absolute)227 4114 y(di\013erences)26 b(b)s(et)m(w)m(een)h (successiv)m(e)g(pixels)f(in)g(the)g(image.)41 b(If)25 b(the)h(median)g(=)f(0,)j(then)d(the)h(algorithm)h(falls)227 4227 y(bac)m(k)h(to)f(computing)g(the)g(RMS)f(of)h(the)g(di\013erence)g (b)s(et)m(w)m(een)h(successiv)m(e)g(pixels,)f(after)h(sev)m(eral)g (N-sigma)227 4340 y(rejection)e(cycles)g(to)g(remo)m(v)m(e)g(extreme)g (v)-5 b(alues.)39 b(The)25 b(input)e(parameters)j(are:)38 b(the)25 b(arra)m(y)g(of)g(image)i(pixel)227 4452 y(v)-5 b(alues)30 b(\(either)h(\015oat)f(or)g(short)f(v)-5 b(alues\),)31 b(the)f(n)m(um)m(b)s(er)e(of)i(v)-5 b(alues)30 b(in)g(the)g(arra)m(y)-8 b(,)31 b(the)f(v)-5 b(alue)30 b(that)g(is)g(used)227 4565 y(to)h(represen)m(t)g(n)m(ull)f(pixels)h(\(en)m(ter)g(a)g(v)m(ery) g(large)g(n)m(um)m(b)s(er)e(if)h(there)h(are)g(no)f(n)m(ull)g (pixels\).)191 4801 y Fe(int)47 b(fits_rms_float)d(\(float)i(fdata[],)f (int)i(npix,)g(float)f(in_null_value,)907 4914 y(>)h(double)f(*rms,)h (int)g(*status\))191 5027 y(int)g(fits_rms_short)d(\(short)i(fdata[],)f (int)i(npix,)g(short)f(in_null_value,)907 5140 y(>)h(double)f(*rms,)h (int)g(*status\))0 5375 y Fi(26)f Fj(W)-8 b(as)33 b(CFITSIO)d(compiled) h(with)h(the)f(-D)p 1612 5375 28 4 v 34 w(REENTRANT)g(directiv)m(e)i (so)e(that)h(it)g(ma)m(y)h(b)s(e)d(safely)j(used)d(in)227 5488 y(m)m(ulti-threaded)d(en)m(vironmen)m(ts?)40 b(The)26 b(follo)m(wing)i(function)e(returns)f(1)i(if)f(y)m(es,)i(0)f(if)f(no.) 40 b(Note,)28 b(ho)m(w)m(ev)m(er,)227 5601 y(that)35 b(ev)m(en)g(if)g(the)f(-D)p 991 5601 V 34 w(REENTRANT)f(directiv)m(e)j (w)m(as)f(sp)s(eci\014ed,)g(this)f(do)s(es)g(not)h(guaran)m(tee)h(that) f(the)227 5714 y(CFITSIO)29 b(routines)h(are)h(thread-safe,)g(b)s (ecause)g(some)f(compilers)h(ma)m(y)g(not)g(supp)s(ort)d(this)j (feature.)p eop end %%Page: 78 86 TeXDict begin 78 85 bop 0 299 a Fj(78)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fe(int)47 b(fits_is_reentrant\(void\))p eop end %%Page: 79 87 TeXDict begin 79 86 bop 0 1225 a Fg(Chapter)65 b(6)0 1687 y Fm(The)77 b(CFITSIO)f(Iterator)i(F)-19 b(unction)0 2180 y Fj(The)41 b(\014ts)p 325 2180 28 4 v 33 w(iterate)p 614 2180 V 34 w(data)i(function)e(in)h(CFITSIO)e(pro)m(vides)i(a)g (unique)e(metho)s(d)i(of)g(executing)h(an)e(arbitrary)0 2293 y(user-supplied)35 b(`w)m(ork')i(function)f(that)h(op)s(erates)g (on)g(ro)m(ws)f(of)h(data)g(in)f(FITS)g(tables)h(or)f(on)h(pixels)f(in) h(FITS)0 2406 y(images.)i(Rather)24 b(than)e(explicitly)j(reading)e (and)g(writing)g(the)g(FITS)g(images)h(or)f(columns)g(of)g(data,)i(one) f(instead)0 2518 y(calls)36 b(the)g(CFITSIO)d(iterator)k(routine,)g (passing)e(to)h(it)g(the)f(name)g(of)h(the)f(user's)g(w)m(ork)g (function)g(that)h(is)f(to)0 2631 y(b)s(e)30 b(executed)h(along)g(with) f(a)h(list)g(of)f(all)h(the)f(table)i(columns)e(or)g(image)h(arra)m(ys) g(that)g(are)f(to)h(b)s(e)f(passed)g(to)h(the)0 2744 y(w)m(ork)37 b(function.)61 b(The)37 b(CFITSIO)e(iterator)k(function)e (then)g(do)s(es)g(all)h(the)f(w)m(ork)g(of)h(allo)s(cating)h(memory)e (for)0 2857 y(the)28 b(arra)m(ys,)h(reading)f(the)g(input)e(data)j (from)e(the)h(FITS)f(\014le,)h(passing)g(them)g(to)g(the)g(w)m(ork)g (function,)g(and)f(then)0 2970 y(writing)36 b(an)m(y)h(output)f(data)h (bac)m(k)h(to)f(the)f(FITS)g(\014le)g(after)h(the)g(w)m(ork)g(function) f(exits.)59 b(Because)38 b(it)f(is)g(often)0 3083 y(more)g(e\016cien)m (t)i(to)f(pro)s(cess)f(only)g(a)h(subset)f(of)g(the)g(total)i(table)g (ro)m(ws)e(at)h(one)f(time,)j(the)e(iterator)g(function)0 3196 y(can)31 b(determine)f(the)h(optim)m(um)f(amoun)m(t)h(of)f(data)h (to)g(pass)f(in)g(eac)m(h)i(iteration)f(and)f(rep)s(eatedly)h(call)g (the)g(w)m(ork)0 3309 y(function)f(un)m(til)h(the)f(en)m(tire)i(table)f (b)s(een)e(pro)s(cessed.)0 3469 y(F)-8 b(or)37 b(man)m(y)f (applications)h(this)e(single)i(CFITSIO)d(iterator)k(function)d(can)h (e\013ectiv)m(ely)j(replace)e(all)g(the)f(other)0 3582 y(CFITSIO)g(routines)i(for)f(reading)h(or)f(writing)h(data)g(in)f(FITS) g(images)i(or)e(tables.)64 b(Using)37 b(the)h(iterator)h(has)0 3695 y(sev)m(eral)32 b(imp)s(ortan)m(t)e(adv)-5 b(an)m(tages)32 b(o)m(v)m(er)g(the)f(traditional)g(metho)s(d)f(of)h(reading)f(and)g (writing)g(FITS)g(data)h(\014les:)136 3961 y Fc(\017)46 b Fj(It)33 b(cleanly)h(separates)g(the)f(data)h(I/O)f(from)f(the)h (routine)g(that)h(op)s(erates)f(on)g(the)g(data.)49 b(This)32 b(leads)h(to)227 4074 y(a)e(more)g(mo)s(dular)e(and)h(`ob)5 b(ject)31 b(orien)m(ted')h(programming)e(st)m(yle.)136 4268 y Fc(\017)46 b Fj(It)27 b(simpli\014es)f(the)h(application)h (program)f(b)m(y)f(eliminating)i(the)f(need)g(to)g(allo)s(cate)i (memory)e(for)f(the)h(data)227 4381 y(arra)m(ys)e(and)f(eliminates)i (most)e(of)h(the)f(calls)i(to)f(the)g(CFITSIO)d(routines)j(that)g (explicitly)h(read)e(and)g(write)227 4494 y(the)31 b(data.)136 4689 y Fc(\017)46 b Fj(It)32 b(ensures)e(that)i(the)g(data)g(are)g(pro) s(cessed)f(as)h(e\016cien)m(tly)h(as)e(p)s(ossible.)44 b(This)31 b(is)g(esp)s(ecially)i(imp)s(ortan)m(t)227 4801 y(when)44 b(pro)s(cessing)g(tabular)h(data)h(since)f(the)g (iterator)h(function)e(will)h(calculate)i(the)e(most)g(e\016cien)m(t) 227 4914 y(n)m(um)m(b)s(er)36 b(of)i(ro)m(ws)g(in)f(the)h(table)g(to)g (b)s(e)f(passed)g(at)i(one)e(time)i(to)f(the)g(user's)e(w)m(ork)i (function)f(on)h(eac)m(h)227 5027 y(iteration.)136 5222 y Fc(\017)46 b Fj(Mak)m(es)39 b(it)e(p)s(ossible)g(for)g(larger)h(pro)5 b(jects)37 b(to)h(dev)m(elop)g(a)g(library)e(of)i(w)m(ork)f(functions)f (that)i(all)g(ha)m(v)m(e)h(a)227 5335 y(uniform)29 b(calling)j (sequence)f(and)f(are)h(all)g(indep)s(enden)m(t)e(of)i(the)f(details)i (of)e(the)h(FITS)e(\014le)i(format.)0 5601 y(There)f(are)h(basically)h (2)g(steps)e(in)h(using)f(the)h(CFITSIO)e(iterator)j(function.)42 b(The)30 b(\014rst)g(step)h(is)g(to)g(design)g(the)0 5714 y(w)m(ork)26 b(function)f(itself)h(whic)m(h)f(m)m(ust)h(ha)m(v)m (e)g(a)g(prescrib)s(ed)e(set)i(of)g(input)f(parameters.)39 b(One)25 b(of)h(these)g(parameters)1905 5942 y(79)p eop end %%Page: 80 88 TeXDict begin 80 87 bop 0 299 a Fj(80)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(is)f(a)g(structure)g(con)m(taining)i(p)s(oin)m(ters)d(to)i (the)f(arra)m(ys)h(of)f(data;)h(the)f(w)m(ork)h(function)e(can)i(p)s (erform)d(an)m(y)i(desired)0 668 y(op)s(erations)k(on)h(these)f(arra)m (ys)h(and)e(do)s(es)h(not)g(need)g(to)h(w)m(orry)f(ab)s(out)g(ho)m(w)g (the)h(input)e(data)i(w)m(ere)f(read)g(from)0 781 y(the)e(\014le)f(or)g (ho)m(w)h(the)f(output)g(data)h(get)h(written)e(bac)m(k)h(to)h(the)e (\014le.)0 941 y(The)24 b(second)h(step)g(is)f(to)i(design)e(the)h (driv)m(er)g(routine)f(that)i(op)s(ens)e(all)h(the)g(necessary)g(FITS)f (\014les)h(and)f(initializes)0 1054 y(the)41 b(input)g(parameters)g(to) h(the)g(iterator)g(function.)73 b(The)41 b(driv)m(er)g(program)g(calls) h(the)g(CFITSIO)e(iterator)0 1167 y(function)30 b(whic)m(h)g(then)g (reads)g(the)h(data)g(and)f(passes)g(it)h(to)g(the)g(user's)e(w)m(ork)i (function.)0 1327 y(The)20 b(follo)m(wing)i(2)f(sections)g(describ)s(e) f(these)h(steps)g(in)f(more)g(detail.)39 b(There)20 b(are)h(also)g(sev) m(eral)h(example)f(programs)0 1440 y(included)30 b(with)g(the)g (CFITSIO)f(distribution)h(whic)m(h)g(illustrate)i(ho)m(w)e(to)h(use)f (the)h(iterator)g(function.)0 1789 y Ff(6.1)135 b(The)45 b(Iterator)h(W)-11 b(ork)45 b(F)-11 b(unction)0 2043 y Fj(The)42 b(user-supplied)f(iterator)j(w)m(ork)f(function)f(m)m(ust)g (ha)m(v)m(e)i(the)f(follo)m(wing)h(set)f(of)g(input)e(parameters)i (\(the)0 2156 y(function)30 b(can)h(b)s(e)e(giv)m(en)j(an)m(y)f (desired)e(name\):)95 2429 y Fe(int)47 b(user_fn\()f(long)h(totaln,)e (long)i(offset,)f(long)g(firstn,)g(long)h(nvalues,)716 2542 y(int)g(narrays,)e(iteratorCol)g(*data,)94 b(void)47 b(*userPointer)d(\))136 2815 y Fc(\017)i Fj(totaln)24 b({)f(the)f(total)j(n)m(um)m(b)s(er)c(of)h(table)i(ro)m(ws)e(or)g (image)i(pixels)f(that)g(will)f(b)s(e)g(passed)g(to)h(the)g(w)m(ork)f (function)227 2928 y(during)29 b(1)i(or)g(more)f(iterations.)136 3129 y Fc(\017)46 b Fj(o\013set)d({)f(the)h(o\013set)f(applied)g(to)h (the)f(\014rst)f(table)i(ro)m(w)f(or)g(image)h(pixel)f(to)h(b)s(e)e (passed)g(to)i(the)f(w)m(ork)227 3241 y(function.)55 b(In)34 b(other)i(w)m(ords,)g(this)f(is)g(the)g(n)m(um)m(b)s(er)f(of)h (ro)m(ws)h(or)f(pixels)g(that)h(are)f(skipp)s(ed)f(o)m(v)m(er)i(b)s (efore)227 3354 y(starting)30 b(the)g(iterations.)42 b(If)28 b(o\013set)j(=)e(0,)h(then)f(all)h(the)f(table)i(ro)m(ws)e(or)g (image)i(pixels)e(will)h(b)s(e)e(passed)h(to)227 3467 y(the)i(w)m(ork)f(function.)136 3668 y Fc(\017)46 b Fj(\014rstn)26 b({)i(the)f(n)m(um)m(b)s(er)f(of)i(the)f(\014rst)g(table)h(ro)m(w)f(or) g(image)i(pixel)e(\(starting)i(with)e(1\))h(that)f(is)h(b)s(eing)e (passed)227 3781 y(in)k(this)h(particular)f(call)i(to)f(the)g(w)m(ork)f (function.)136 3982 y Fc(\017)46 b Fj(n)m(v)-5 b(alues)35 b({)g(the)f(n)m(um)m(b)s(er)g(of)g(table)h(ro)m(ws)g(or)f(image)i (pixels)e(that)h(are)g(b)s(eing)f(passed)g(in)g(this)h(particular)227 4095 y(call)h(to)g(the)f(w)m(ork)f(function.)54 b(n)m(v)-5 b(alues)35 b(will)g(alw)m(a)m(ys)h(b)s(e)e(less)h(than)f(or)h(equal)g (to)h(totaln)g(and)e(will)h(ha)m(v)m(e)227 4208 y(the)f(same)f(v)-5 b(alue)34 b(on)f(eac)m(h)h(iteration,)i(except)e(p)s(ossibly)f(on)g (the)g(last)h(call)h(whic)m(h)e(ma)m(y)g(ha)m(v)m(e)i(a)e(smaller)227 4321 y(v)-5 b(alue.)136 4522 y Fc(\017)46 b Fj(narra)m(ys)31 b({)g(the)g(n)m(um)m(b)s(er)f(of)h(arra)m(ys)g(of)g(data)h(that)f(are)g (b)s(eing)g(passed)f(to)i(the)f(w)m(ork)g(function.)42 b(There)30 b(is)227 4635 y(one)h(arra)m(y)g(for)f(eac)m(h)i(image)f(or) f(table)i(column.)136 4835 y Fc(\017)46 b Fj(*data)31 b({)e(arra)m(y)h(of)f(structures,)g(one)h(for)f(eac)m(h)h(column)f(or)g (image.)42 b(Eac)m(h)29 b(structure)g(con)m(tains)h(a)g(p)s(oin)m(ter) 227 4948 y(to)h(the)g(arra)m(y)g(of)f(data)h(as)g(w)m(ell)g(as)g(other) g(descriptiv)m(e)g(parameters)g(ab)s(out)f(that)h(arra)m(y)-8 b(.)136 5149 y Fc(\017)46 b Fj(*userP)m(oin)m(ter)26 b({)g(a)f(user)f(supplied)g(p)s(oin)m(ter)h(that)h(can)f(b)s(e)f(used)h (to)g(pass)g(ancillary)h(information)f(from)g(the)227 5262 y(driv)m(er)h(function)g(to)g(the)g(w)m(ork)g(function.)39 b(This)25 b(p)s(oin)m(ter)h(is)g(passed)g(to)g(the)h(CFITSIO)d (iterator)j(function)227 5375 y(whic)m(h)37 b(then)f(passes)g(it)h(on)g (to)g(the)f(w)m(ork)h(function)f(without)h(an)m(y)g(mo)s(di\014cation.) 59 b(It)37 b(ma)m(y)g(p)s(oin)m(t)f(to)i(a)227 5488 y(single)29 b(n)m(um)m(b)s(er,)f(to)h(an)f(arra)m(y)h(of)g(v)-5 b(alues,)29 b(to)g(a)g(structure)f(con)m(taining)i(an)e(arbitrary)g(set)h(of)g (parameters)227 5601 y(of)e(di\013eren)m(t)h(t)m(yp)s(es,)g(or)f(it)h (ma)m(y)f(b)s(e)g(a)g(n)m(ull)g(p)s(oin)m(ter)g(if)g(it)h(is)f(not)g (needed.)40 b(The)26 b(w)m(ork)h(function)g(m)m(ust)g(cast)227 5714 y(this)k(p)s(oin)m(ter)f(to)h(the)g(appropriate)f(data)h(t)m(yp)s (e)g(b)s(efore)f(using)f(it)i(it.)p eop end %%Page: 81 89 TeXDict begin 81 88 bop 0 299 a Fh(6.1.)72 b(THE)30 b(ITERA)-8 b(TOR)30 b(W)m(ORK)g(FUNCTION)2021 b Fj(81)0 555 y(The)23 b(totaln,)k(o\013set,)g(narra)m(ys,)e(data,)h(and)d(userP)m(oin)m(ter)i (parameters)f(are)g(guaran)m(teed)h(to)g(ha)m(v)m(e)g(the)f(same)g(v)-5 b(alue)0 668 y(on)35 b(eac)m(h)i(iteration.)57 b(Only)34 b(\014rstn,)i(n)m(v)-5 b(alues,)37 b(and)d(the)i(arra)m(ys)f(of)h(data) g(p)s(oin)m(ted)f(to)h(b)m(y)f(the)h(data)g(structures)0 781 y(ma)m(y)31 b(c)m(hange)g(on)g(eac)m(h)g(iterativ)m(e)i(call)f(to)f (the)f(w)m(ork)h(function.)0 941 y(Note)43 b(that)g(the)f(iterator)h (treats)g(an)f(image)h(as)f(a)g(long)h(1-D)g(arra)m(y)f(of)h(pixels)f (regardless)g(of)g(it's)h(in)m(trinsic)0 1054 y(dimensionalit)m(y)-8 b(.)52 b(The)33 b(total)j(n)m(um)m(b)s(er)c(of)i(pixels)g(is)g(just)f (the)h(pro)s(duct)e(of)i(the)g(size)h(of)e(eac)m(h)i(dimension,)g(and)0 1167 y(the)e(order)g(of)g(the)g(pixels)g(is)g(the)g(same)g(as)g(the)h (order)e(that)h(they)h(are)f(stored)g(in)g(the)g(FITS)f(\014le.)48 b(If)33 b(the)g(w)m(ork)0 1280 y(function)27 b(needs)g(to)h(kno)m(w)f (the)h(n)m(um)m(b)s(er)e(and)h(size)h(of)g(the)f(image)i(dimensions)d (then)h(these)h(parameters)g(can)g(b)s(e)0 1393 y(passed)i(via)h(the)f (userP)m(oin)m(ter)i(structure.)0 1553 y(The)e(iteratorCol)i(structure) e(is)g(curren)m(tly)h(de\014ned)e(as)h(follo)m(ws:)0 1780 y Fe(typedef)46 b(struct)94 b(/*)47 b(structure)e(for)i(the)g (iterator)e(function)h(column)g(information)f(*/)0 1893 y({)143 2005 y(/*)i(structure)f(elements)f(required)h(as)h(input)f(to)h (fits_iterate_data:)c(*/)95 2231 y(fitsfile)j(*fptr;)332 b(/*)48 b(pointer)d(to)j(the)f(HDU)f(containing)f(the)i(column)f(or)i (image)e(*/)95 2344 y(int)286 b(colnum;)e(/*)48 b(column)e(number)g(in) h(the)g(table;)f(ignored)g(for)h(images)189 b(*/)95 2457 y(char)238 b(colname[70];)44 b(/*)k(name)e(\(TTYPEn\))g(of)h(the)g (column;)f(null)g(for)h(images)285 b(*/)95 2570 y(int)h(datatype;)188 b(/*)48 b(output)e(data)g(type)h(\(converted)e(if)i(necessary\))e(*/)95 2683 y(int)286 b(iotype;)e(/*)48 b(type:)e(InputCol,)f(InputOutputCol,) f(or)j(OutputCol)e(*/)95 2909 y(/*)j(output)e(structure)f(elements)h (that)g(may)h(be)g(useful)f(for)h(the)g(work)g(function:)e(*/)95 3135 y(void)238 b(*array;)189 b(/*)47 b(pointer)f(to)h(the)g(array)f (\(and)h(the)g(null)g(value\))f(*/)95 3247 y(long)238 b(repeat;)189 b(/*)47 b(binary)f(table)h(vector)f(repeat)g(value;)g (set)238 b(*/)1050 3360 y(/*)g(equal)46 b(to)i(1)f(for)g(images)810 b(*/)95 3473 y(long)238 b(tlmin;)f(/*)47 b(legal)g(minimum)e(data)i (value,)f(if)h(any)477 b(*/)95 3586 y(long)238 b(tlmax;)f(/*)47 b(legal)g(maximum)e(data)i(value,)f(if)h(any)477 b(*/)95 3699 y(char)238 b(unit[70];)93 b(/*)47 b(physical)f(unit)g(string)g (\(BUNIT)h(or)g(TUNITn\))189 b(*/)95 3812 y(char)238 b(tdisp[70];)45 b(/*)i(suggested)e(display)h(format;)g(null)h(if)g (none)190 b(*/)0 4038 y(})47 b(iteratorCol;)0 4264 y Fj(Instead)34 b(of)g(directly)g(reading)g(or)g(writing)g(the)f(elemen)m (ts)j(in)d(this)h(structure,)g(it)h(is)e(recommended)h(that)g(pro-)0 4377 y(grammers)c(use)g(the)h(access)h(functions)d(that)i(are)g(pro)m (vided)f(for)g(this)h(purp)s(ose.)0 4538 y(The)25 b(\014rst)g(\014v)m (e)h(elemen)m(ts)h(in)f(this)f(structure)h(m)m(ust)f(b)s(e)g(initially) j(de\014ned)c(b)m(y)i(the)g(driv)m(er)f(routine)h(b)s(efore)f(calling)0 4650 y(the)f(iterator)h(routine.)38 b(The)23 b(CFITSIO)f(iterator)j (routine)f(uses)f(this)g(information)h(to)g(determine)g(what)f(column)0 4763 y(or)32 b(arra)m(y)h(to)h(pass)e(to)h(the)g(w)m(ork)f(function,)h (and)f(whether)g(the)g(arra)m(y)h(is)g(to)g(b)s(e)f(input)g(to)h(the)f (w)m(ork)h(function,)0 4876 y(output)g(from)g(the)h(w)m(ork)f (function,)h(or)g(b)s(oth.)49 b(The)33 b(CFITSIO)f(iterator)i(function) f(\014lls)h(in)f(the)g(v)-5 b(alues)34 b(of)g(the)0 4989 y(remaining)c(structure)g(elemen)m(ts)i(b)s(efore)e(passing)g(it)h(to)g (the)g(w)m(ork)f(function.)0 5149 y(The)d(arra)m(y)g(structure)g (elemen)m(t)i(is)e(a)g(p)s(oin)m(ter)g(to)h(the)g(actual)g(data)g(arra) m(y)g(and)e(it)i(m)m(ust)f(b)s(e)f(cast)j(to)e(the)h(correct)0 5262 y(data)k(t)m(yp)s(e)f(b)s(efore)f(it)i(is)f(used.)41 b(The)31 b(`rep)s(eat')g(structure)g(elemen)m(t)h(giv)m(e)g(the)g(n)m (um)m(b)s(er)d(of)i(data)h(v)-5 b(alues)31 b(in)g(eac)m(h)0 5375 y(ro)m(w)f(of)g(the)g(table,)i(so)e(that)h(the)f(total)i(n)m(um)m (b)s(er)c(of)i(data)h(v)-5 b(alues)30 b(in)g(the)g(arra)m(y)h(is)f(giv) m(en)h(b)m(y)f(rep)s(eat)g(*)g(n)m(v)-5 b(alues.)0 5488 y(In)36 b(the)g(case)i(of)e(image)i(arra)m(ys)f(and)e(ASCI)s(I)g (tables,)k(rep)s(eat)e(will)g(alw)m(a)m(ys)g(b)s(e)f(equal)h(to)g(1.)59 b(When)37 b(the)f(data)0 5601 y(t)m(yp)s(e)k(is)f(a)h(c)m(haracter)h (string,)h(the)e(arra)m(y)g(p)s(oin)m(ter)f(is)h(actually)h(a)f(p)s (oin)m(ter)f(to)i(an)e(arra)m(y)h(of)g(string)f(p)s(oin)m(ters)0 5714 y(\(i.e.,)31 b(c)m(har)e(**arra)m(y\).)42 b(The)29 b(other)g(output)g(structure)f(elemen)m(ts)j(are)e(pro)m(vided)g(for)f (con)m(v)m(enience)k(in)c(case)i(that)p eop end %%Page: 82 90 TeXDict begin 82 89 bop 0 299 a Fj(82)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(information)36 b(is)g(needed)f(within)g(the)h(w)m(ork)g (function.)56 b(An)m(y)35 b(other)h(information)g(ma)m(y)g(b)s(e)f (passed)h(from)f(the)0 668 y(driv)m(er)30 b(routine)h(to)g(the)f(w)m (ork)h(function)f(via)h(the)f(userP)m(oin)m(ter)h(parameter.)0 828 y(Up)s(on)g(completion,)j(the)e(w)m(ork)h(routine)f(m)m(ust)g (return)f(an)h(in)m(teger)h(status)f(v)-5 b(alue,)34 b(with)d(0)i(indicating)g(success)0 941 y(and)e(an)m(y)g(other)g(v)-5 b(alue)32 b(indicating)g(an)f(error)g(whic)m(h)g(will)g(cause)h(the)f (iterator)i(function)e(to)h(immediately)g(exit)0 1054 y(at)27 b(that)f(p)s(oin)m(t.)39 b(Return)25 b(status)i(v)-5 b(alues)26 b(in)f(the)h(range)h(1)f({)g(1000)i(should)c(b)s(e)i(a)m(v)m (oided)h(since)f(these)h(are)f(reserv)m(ed)0 1167 y(for)d(use)g(b)m(y)h (CFITSIO.)e(A)i(return)e(status)i(v)-5 b(alue)24 b(of)g(-1)g(ma)m(y)g (b)s(e)f(used)f(to)j(force)f(the)f(CFITSIO)f(iterator)j(function)0 1280 y(to)i(stop)g(at)g(that)h(p)s(oin)m(t)e(and)g(return)g(con)m(trol) i(to)f(the)g(driv)m(er)f(routine)h(after)g(writing)f(an)m(y)h(output)f (arra)m(ys)h(to)h(the)0 1393 y(FITS)e(\014le.)40 b(CFITSIO)26 b(do)s(es)g(not)i(considered)f(this)g(to)h(b)s(e)e(an)h(error)g (condition,)i(so)e(an)m(y)g(further)f(pro)s(cessing)h(b)m(y)0 1506 y(the)k(application)g(program)f(will)h(con)m(tin)m(ue)h(normally) -8 b(.)0 1837 y Ff(6.2)135 b(The)45 b(Iterator)h(Driv)l(er)g(F)-11 b(unction)0 2087 y Fj(The)33 b(iterator)h(driv)m(er)f(function)g(m)m (ust)h(op)s(en)e(the)i(necessary)f(FITS)g(\014les)g(and)g(p)s(osition)g (them)g(to)h(the)g(correct)0 2200 y(HDU.)23 b(It)f(m)m(ust)g(also)i (initialize)g(the)e(follo)m(wing)i(parameters)e(in)g(the)h(iteratorCol) h(structure)d(\(de\014ned)g(ab)s(o)m(v)m(e\))j(for)0 2313 y(eac)m(h)31 b(column)f(or)g(image)h(b)s(efore)e(calling)j(the)e (CFITSIO)e(iterator)j(function.)40 b(Sev)m(eral)31 b(`constructor')g (routines)0 2426 y(are)g(pro)m(vided)f(in)g(CFITSIO)f(for)h(this)g (purp)s(ose.)136 2670 y Fc(\017)46 b Fj(*fptr)30 b({)h(The)f (\014ts\014le)g(p)s(oin)m(ter)g(to)i(the)e(table)h(or)g(image.)136 2853 y Fc(\017)46 b Fj(coln)m(um)30 b({)f(the)h(n)m(um)m(b)s(er)e(of)h (the)h(column)f(in)g(the)g(table.)42 b(This)28 b(v)-5 b(alue)30 b(is)f(ignored)g(in)g(the)h(case)g(of)g(images.)227 2966 y(If)j(coln)m(um)h(equals)g(0,)g(then)g(the)f(column)g(name)h (will)f(b)s(e)g(used)g(to)h(iden)m(tify)g(the)f(column)h(to)g(b)s(e)e (passed)227 3079 y(to)f(the)g(w)m(ork)f(function.)136 3261 y Fc(\017)46 b Fj(colname)32 b({)e(the)g(name)h(\(TTYPEn)e(k)m (eyw)m(ord\))i(of)f(the)h(column.)40 b(This)29 b(is)i(only)f(required)f (if)h(coln)m(um)h(=)f(0)227 3374 y(and)g(is)g(ignored)h(for)f(images.) 136 3556 y Fc(\017)46 b Fj(datat)m(yp)s(e)29 b({)g(The)e(desired)h (data)g(t)m(yp)s(e)g(of)h(the)f(arra)m(y)g(to)h(b)s(e)e(passed)h(to)h (the)f(w)m(ork)g(function.)40 b(F)-8 b(or)28 b(n)m(umer-)227 3669 y(ical)h(data)f(the)f(data)h(t)m(yp)s(e)g(do)s(es)f(not)g(need)g (to)h(b)s(e)f(the)g(same)h(as)f(the)h(actual)g(data)g(t)m(yp)s(e)g(in)f (the)g(FITS)g(\014le,)227 3782 y(in)h(whic)m(h)h(case)g(CFITSIO)e(will) i(do)g(the)f(con)m(v)m(ersion.)42 b(Allo)m(w)m(ed)30 b(v)-5 b(alues)29 b(are:)40 b(TSTRING,)28 b(TLOGICAL,)227 3895 y(TBYTE,)37 b(TSBYTE,)f(TSHOR)-8 b(T,)36 b(TUSHOR)-8 b(T,)37 b(TINT,)f(TLONG,)h(TULONG,)f(TFLO)m(A)-8 b(T,)38 b(TDOU-)227 4008 y(BLE.)33 b(If)g(the)g(input)f(v)-5 b(alue)33 b(of)g(data)h(t)m(yp)s(e)f(equals)g(0,)i(then)d(the)h (existing)h(data)g(t)m(yp)s(e)f(of)g(the)g(column)g(or)227 4121 y(image)f(will)f(b)s(e)e(used)h(without)g(an)m(y)h(con)m(v)m (ersion.)136 4303 y Fc(\017)46 b Fj(iot)m(yp)s(e)37 b({)f(de\014nes)e (whether)h(the)h(data)g(arra)m(y)g(is)g(to)g(b)s(e)f(input)g(to)h(the)g (w)m(ork)f(function)h(\(i.e,)i(read)d(from)227 4416 y(the)42 b(FITS)e(\014le\),)k(or)d(output)g(from)g(the)g(w)m(ork)g(function)g (\(i.e.,)k(written)c(to)h(the)f(FITS)g(\014le\))g(or)g(b)s(oth.)227 4529 y(Allo)m(w)m(ed)30 b(v)-5 b(alues)29 b(are)f(InputCol,)g (OutputCol,)h(or)f(InputOutputCol.)38 b(V)-8 b(ariable-length)30 b(arra)m(y)f(columns)227 4642 y(are)h(supp)s(orted)e(as)i(InputCol)e (or)i(InputOutputCol)d(t)m(yp)s(es,)j(but)f(ma)m(y)h(not)g(b)s(e)e (used)h(for)g(an)h(OutputCol)227 4755 y(t)m(yp)s(e.)0 4999 y(After)h(the)f(driv)m(er)g(routine)g(has)g(initialized)j(all)e (these)f(parameters,)h(it)g(can)g(then)f(call)h(the)g(CFITSIO)e (iterator)0 5112 y(function:)95 5357 y Fe(int)47 b (fits_iterate_data\(int)42 b(narrays,)k(iteratorCol)f(*data,)h(long)g (offset,)286 5470 y(long)h(nPerLoop,)e(int)i(\(*workFn\)\()e(\),)i (void)g(*userPointer,)d(int)j(*status\);)136 5714 y Fc(\017)f Fj(narra)m(ys)31 b({)f(the)h(n)m(um)m(b)s(er)e(of)h(columns)g(or)h (images)g(that)g(are)g(to)g(b)s(e)f(passed)g(to)h(the)f(w)m(ork)h (function.)p eop end %%Page: 83 91 TeXDict begin 83 90 bop 0 299 a Fh(6.3.)72 b(GUIDELINES)30 b(F)m(OR)h(USING)f(THE)g(ITERA)-8 b(TOR)30 b(FUNCTION)1200 b Fj(83)136 555 y Fc(\017)46 b Fj(*data)32 b({)f(p)s(oin)m(ter)f(to)h (arra)m(y)g(of)f(structures)g(con)m(taining)i(information)f(ab)s(out)f (eac)m(h)h(column)g(or)f(image.)136 750 y Fc(\017)46 b Fj(o\013set)31 b({)f(if)f(p)s(ositiv)m(e,)i(this)f(n)m(um)m(b)s(er)e (of)i(ro)m(ws)f(at)h(the)g(b)s(eginning)f(of)h(the)f(table)i(\(or)f (pixels)f(in)h(the)f(image\))227 863 y(will)i(b)s(e)f(skipp)s(ed)f(and) g(will)i(not)g(b)s(e)e(passed)h(to)h(the)g(w)m(ork)f(function.)136 1058 y Fc(\017)46 b Fj(nP)m(erLo)s(op)38 b(-)h(sp)s(eci\014es)e(the)i (n)m(um)m(b)s(er)e(of)h(table)h(ro)m(ws)g(\(or)f(n)m(um)m(b)s(er)f(of)i (image)g(pixels\))g(that)g(are)g(to)g(b)s(e)227 1171 y(passed)29 b(to)h(the)f(w)m(ork)h(function)e(on)h(eac)m(h)i (iteration.)42 b(If)28 b(nP)m(erLo)s(op)h(=)g(0)g(then)g(CFITSIO)f (will)i(calculate)227 1284 y(the)22 b(optim)m(um)g(n)m(um)m(b)s(er)e (for)h(greatest)j(e\016ciency)-8 b(.)39 b(If)21 b(nP)m(erLo)s(op)g(is)h (negativ)m(e,)k(then)21 b(all)i(the)f(ro)m(ws)f(or)h(pixels)227 1397 y(will)36 b(b)s(e)f(passed)g(at)h(one)g(time,)i(and)c(the)i(w)m (ork)g(function)f(will)h(only)f(b)s(e)g(called)i(once.)56 b(If)35 b(an)m(y)h(v)-5 b(ariable)227 1510 y(length)33 b(arra)m(ys)g(are)g(b)s(eing)f(pro)s(cessed,)h(then)g(the)f(nP)m(erLo)s (op)h(v)-5 b(alue)33 b(is)f(ignored,)i(and)e(the)h(iterator)h(will)227 1623 y(alw)m(a)m(ys)e(pro)s(cess)e(one)h(ro)m(w)f(of)h(the)f(table)i (at)f(a)g(time.)136 1818 y Fc(\017)46 b Fj(*w)m(orkFn)f(-)f(the)h(name) f(\(actually)i(the)f(address\))f(of)g(the)g(w)m(ork)h(function)f(that)h (is)f(to)h(b)s(e)f(called)h(b)m(y)227 1931 y(\014ts)p 354 1931 28 4 v 33 w(iterate)p 643 1931 V 34 w(data.)136 2126 y Fc(\017)h Fj(*userP)m(oin)m(ter)34 b(-)f(this)g(is)g(a)g(user)f (supplied)g(p)s(oin)m(ter)h(that)g(can)g(b)s(e)g(used)f(to)h(pass)g (ancillary)h(information)227 2239 y(from)f(the)g(driv)m(er)g(routine)g (to)h(the)f(w)m(ork)g(function.)48 b(It)33 b(ma)m(y)h(p)s(oin)m(t)f(to) h(a)f(single)h(n)m(um)m(b)s(er,)e(an)h(arra)m(y)-8 b(,)35 b(or)227 2352 y(to)c(a)g(structure)f(con)m(taining)i(an)e(arbitrary)g (set)h(of)g(parameters.)136 2547 y Fc(\017)46 b Fj(*status)30 b(-)f(The)f(CFITSIO)f(error)h(status.)41 b(Should)27 b(=)h(0)h(on)g(input;)f(a)h(non-zero)h(output)e(v)-5 b(alue)29 b(indicates)227 2660 y(an)i(error.)0 2927 y(When)f(\014ts)p 392 2927 V 32 w(iterate)p 680 2927 V 35 w(data)h(is)f(called)h(it)f (\014rst)g(allo)s(cates)i(memory)e(to)h(hold)e(all)i(the)f(requested)g (columns)g(of)g(data)0 3040 y(or)f(image)i(pixel)e(arra)m(ys.)41 b(It)29 b(then)g(reads)g(the)h(input)e(data)i(from)f(the)g(FITS)f (tables)i(or)g(images)g(in)m(to)g(the)g(arra)m(ys)0 3153 y(then)h(passes)h(the)g(structure)f(with)g(p)s(oin)m(ters)h(to)g(these) g(data)h(arra)m(ys)f(to)g(the)g(w)m(ork)g(function.)44 b(After)32 b(the)g(w)m(ork)0 3266 y(function)37 b(returns,)g(the)h (iterator)g(function)f(writes)g(an)m(y)g(output)g(columns)f(of)h(data)h (or)f(images)h(bac)m(k)g(to)g(the)0 3379 y(FITS)31 b(\014les.)46 b(It)32 b(then)g(rep)s(eats)g(this)g(pro)s(cess)g(for)f(an)m(y)i (remaining)f(sets)g(of)h(ro)m(ws)f(or)g(image)h(pixels)f(un)m(til)h(it) f(has)0 3491 y(pro)s(cessed)27 b(the)i(en)m(tire)g(table)f(or)g(image)i (or)e(un)m(til)g(the)g(w)m(ork)g(function)g(returns)f(a)h(non-zero)h (status)f(v)-5 b(alue.)40 b(The)0 3604 y(iterator)33 b(then)f(frees)g(the)h(memory)e(that)i(it)g(initially)g(allo)s(cated)h (and)e(returns)f(con)m(trol)i(to)g(the)f(driv)m(er)g(routine)0 3717 y(that)f(called)h(it.)0 4060 y Ff(6.3)135 b(Guidelines)46 b(for)f(Using)h(the)f(Iterator)h(F)-11 b(unction)0 4312 y Fj(The)34 b(totaln,)i(o\013set,)h(\014rstn,)d(and)f(n)m(v)-5 b(alues)35 b(parameters)f(that)h(are)f(passed)g(to)h(the)f(w)m(ork)g (function)g(are)h(useful)0 4425 y(for)f(determining)g(ho)m(w)g(m)m(uc)m (h)g(of)h(the)f(data)h(has)f(b)s(een)f(pro)s(cessed)h(and)f(ho)m(w)h(m) m(uc)m(h)g(remains)g(left)h(to)g(do.)52 b(On)0 4538 y(the)36 b(v)m(ery)h(\014rst)f(call)h(to)g(the)f(w)m(ork)h(function)f(\014rstn)f (will)h(b)s(e)g(equal)h(to)g(o\013set)g(+)f(1;)k(the)c(w)m(ork)g (function)g(ma)m(y)0 4650 y(need)31 b(to)g(p)s(erform)f(v)-5 b(arious)31 b(initialization)i(tasks)f(b)s(efore)e(starting)i(to)f(pro) s(cess)g(the)g(data.)43 b(Similarly)-8 b(,)32 b(\014rstn)d(+)0 4763 y(n)m(v)-5 b(alues)29 b(-)f(1)h(will)f(b)s(e)g(equal)g(to)h (totaln)h(on)e(the)g(last)h(iteration,)i(at)e(whic)m(h)f(p)s(oin)m(t)g (the)g(w)m(ork)h(function)e(ma)m(y)i(need)0 4876 y(to)k(p)s(erform)f (some)h(clean)h(up)d(op)s(erations)i(b)s(efore)g(exiting)h(for)e(the)h (last)h(time.)48 b(The)33 b(w)m(ork)f(function)h(can)g(also)0 4989 y(force)e(an)f(early)h(termination)g(of)g(the)g(iterations)g(b)m (y)g(returning)e(a)i(status)g(v)-5 b(alue)30 b(=)g(-1.)0 5149 y(The)f(narra)m(ys)g(and)g(iteratorCol.datat)m(yp)s(e)j(argumen)m (ts)e(allo)m(w)g(the)g(w)m(ork)f(function)g(to)h(double)f(c)m(hec)m(k)i (that)f(the)0 5262 y(n)m(um)m(b)s(er)k(of)i(input)f(arra)m(ys)h(and)f (their)g(data)i(t)m(yp)s(es)e(ha)m(v)m(e)i(the)f(exp)s(ected)g(v)-5 b(alues.)57 b(The)35 b(iteratorCol.fptr)i(and)0 5375 y(iteratorCol.coln)m(um)d(structure)d(elemen)m(ts)h(can)g(b)s(e)f(used) f(if)i(the)f(w)m(ork)h(function)f(needs)g(to)h(read)f(or)g(write)h(the) 0 5488 y(v)-5 b(alues)38 b(of)h(other)f(k)m(eyw)m(ords)h(in)e(the)i (FITS)e(\014le)h(asso)s(ciated)i(with)e(the)g(arra)m(y)-8 b(.)65 b(This)37 b(should)g(generally)j(only)0 5601 y(b)s(e)e(done)h (during)e(the)i(initialization)j(step)d(or)g(during)e(the)i(clean)h(up) e(step)g(after)i(the)f(last)g(set)h(of)f(data)g(has)0 5714 y(b)s(een)f(pro)s(cessed.)64 b(Extra)39 b(FITS)e(\014le)i(I/O)f (during)f(the)i(main)f(pro)s(cessing)g(lo)s(op)h(of)f(the)h(w)m(ork)g (function)f(can)p eop end %%Page: 84 92 TeXDict begin 84 91 bop 0 299 a Fj(84)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(seriously)h(degrade)h(the)f(sp)s(eed)f(of)h(the)h(program.)42 b(Note)33 b(that)e(the)h(b)s(eha)m(vior)f(of)g(the)g Fe(fits_iterate_data\(\))0 668 y Fj(is)f(unde\014ned)f(if)h(narra)m(ys) g(is)h(zero.)0 828 y(If)h(v)-5 b(ariable-length)35 b(arra)m(y)e (columns)g(are)g(b)s(eing)f(pro)s(cessed,)h(then)g(the)g(iterator)h (will)f(op)s(erate)h(on)f(one)g(ro)m(w)g(of)0 941 y(the)j(table)g(at)g (a)g(time.)57 b(In)34 b(this)i(case)g(the)g(the)f(rep)s(eat)h(elemen)m (t)h(in)e(the)h(in)m(teratorCol)h(structure)e(will)h(b)s(e)e(set)0 1054 y(equal)d(to)g(the)g(n)m(um)m(b)s(er)e(of)h(elemen)m(ts)i(in)e (the)h(curren)m(t)f(ro)m(w)g(that)h(is)g(b)s(eing)f(pro)s(cessed.)0 1214 y(One)j(imp)s(ortan)m(t)g(feature)h(of)f(the)h(iterator)h(is)e (that)h(the)f(\014rst)g(elemen)m(t)i(in)e(eac)m(h)h(arra)m(y)g(that)g (is)f(passed)g(to)h(the)0 1327 y(w)m(ork)f(function)g(giv)m(es)h(the)f (v)-5 b(alue)33 b(that)h(is)f(used)f(to)h(represen)m(t)g(n)m(ull)g(or)g (unde\014ned)d(v)-5 b(alues)34 b(in)e(the)h(arra)m(y)-8 b(.)49 b(The)0 1440 y(real)41 b(data)g(then)g(b)s(egins)f(with)g(the)g (second)h(elemen)m(t)h(of)f(the)f(arra)m(y)h(\(i.e.,)k(arra)m(y[1],)g (not)c(arra)m(y[0]\).)73 b(If)40 b(the)0 1553 y(\014rst)e(arra)m(y)h (elemen)m(t)h(is)f(equal)g(to)g(zero,)j(then)c(this)g(indicates)i(that) f(all)h(the)e(arra)m(y)h(elemen)m(ts)h(ha)m(v)m(e)g(de\014ned)0 1666 y(v)-5 b(alues)33 b(and)f(there)h(are)g(no)g(unde\014ned)d(v)-5 b(alues.)48 b(If)33 b(arra)m(y[0])h(is)f(not)g(equal)g(to)g(zero,)i (then)d(this)h(indicates)g(that)0 1779 y(some)h(of)g(the)g(data)h(v)-5 b(alues)34 b(are)g(unde\014ned)d(and)j(this)f(v)-5 b(alue)35 b(\(arra)m(y[0]\))h(is)d(used)g(to)i(represen)m(t)f(them.)51 b(In)33 b(the)0 1892 y(case)i(of)e(output)g(arra)m(ys)h(\(i.e.,)i (those)e(arra)m(ys)g(that)g(will)g(b)s(e)f(written)g(bac)m(k)h(to)h (the)e(FITS)g(\014le)g(b)m(y)h(the)g(iterator)0 2005 y(function)h(after)i(the)f(w)m(ork)f(function)h(exits\))h(the)f(w)m (ork)g(function)f(m)m(ust)h(set)g(the)g(\014rst)f(arra)m(y)h(elemen)m (t)h(to)g(the)0 2118 y(desired)g(n)m(ull)g(v)-5 b(alue)37 b(if)g(necessary)-8 b(,)40 b(otherwise)e(the)f(\014rst)g(elemen)m(t)h (should)e(b)s(e)h(set)g(to)h(zero)g(to)g(indicate)g(that)0 2230 y(there)30 b(are)h(no)e(n)m(ull)h(v)-5 b(alues)31 b(in)e(the)h(output)g(arra)m(y)-8 b(.)42 b(CFITSIO)28 b(de\014nes)h(2)h(v)-5 b(alues,)31 b(FLO)m(A)-8 b(TNULL)e(V)g(ALUE)31 b(and)0 2343 y(DOUBLENULL)-10 b(V)g(ALUE,)37 b(that)f(can)h(b)s(e)e (used)g(as)i(default)f(n)m(ull)g(v)-5 b(alues)36 b(for)g(\015oat)h(and) e(double)h(data)h(t)m(yp)s(es,)0 2456 y(resp)s(ectiv)m(ely)-8 b(.)60 b(In)35 b(the)i(case)g(of)f(c)m(haracter)i(string)e(data)h(t)m (yp)s(es,)h(a)e(n)m(ull)h(string)f(is)g(alw)m(a)m(ys)i(used)d(to)i (represen)m(t)0 2569 y(unde\014ned)28 b(strings.)0 2729 y(In)33 b(some)h(applications)g(it)g(ma)m(y)g(b)s(e)f(necessary)h(to)g (recursiv)m(ely)g(call)h(the)f(iterator)h(function.)50 b(An)33 b(example)h(of)0 2842 y(this)27 b(is)g(giv)m(en)h(b)m(y)f(one)h (of)f(the)h(example)f(programs)g(that)h(is)f(distributed)f(with)h (CFITSIO:)f(it)i(\014rst)e(calls)i(a)g(w)m(ork)0 2955 y(function)38 b(that)g(writes)h(out)f(a)g(2D)h(histogram)g(image.)65 b(That)38 b(w)m(ork)g(function)g(in)f(turn)g(calls)j(another)e(w)m(ork) 0 3068 y(function)29 b(that)h(reads)g(the)f(`X')i(and)e(`Y')h(columns)f (in)g(a)h(table)h(to)f(calculate)i(the)d(v)-5 b(alue)31 b(of)e(eac)m(h)i(2D)f(histogram)0 3181 y(image)i(pixel.)41 b(Graphically)-8 b(,)32 b(the)e(program)g(structure)g(can)h(b)s(e)f (describ)s(ed)f(as:)48 3442 y Fe(driver)46 b(-->)h(iterator)e(-->)i (work1_fn)f(-->)h(iterator)e(-->)i(work2_fn)0 3703 y Fj(Finally)-8 b(,)42 b(it)d(should)e(b)s(e)h(noted)g(that)h(the)g (table)g(columns)f(or)g(image)i(arra)m(ys)f(that)g(are)f(passed)g(to)h (the)g(w)m(ork)0 3816 y(function)c(do)h(not)g(all)g(ha)m(v)m(e)h(to)f (come)h(from)e(the)h(same)g(FITS)f(\014le)g(and)g(instead)h(ma)m(y)g (come)h(from)e(an)m(y)h(com-)0 3929 y(bination)d(of)g(sources)g(as)h (long)f(as)h(they)f(ha)m(v)m(e)h(the)f(same)h(length.)49 b(The)32 b(length)i(of)f(the)g(\014rst)f(table)i(column)f(or)0 4042 y(image)f(arra)m(y)f(is)f(used)f(b)m(y)i(the)f(iterator)i(if)e (they)h(do)f(not)h(all)g(ha)m(v)m(e)h(the)e(same)h(length.)0 4377 y Ff(6.4)135 b(Complete)47 b(List)e(of)g(Iterator)i(Routines)0 4627 y Fj(All)36 b(of)f(the)g(iterator)h(routines)f(are)g(listed)h(b)s (elo)m(w.)54 b(Most)36 b(of)f(these)h(routines)e(do)h(not)g(ha)m(v)m(e) i(a)e(corresp)s(onding)0 4740 y(short)30 b(function)g(name.)0 5001 y Fi(1)81 b Fj(Iterator)32 b(`constructor')h(functions)e(that)i (set)f(the)g(v)-5 b(alue)32 b(of)g(elemen)m(ts)h(in)f(the)g (iteratorCol)h(structure)e(that)227 5114 y(de\014ne)k(the)h(columns)f (or)h(arra)m(ys.)56 b(These)36 b(set)g(the)g(\014ts\014le)f(p)s(oin)m (ter,)i(column)e(name,)j(column)d(n)m(um)m(b)s(er,)227 5227 y(datat)m(yp)s(e,)28 b(and)e(iot)m(yp)s(e,)i(resp)s(ectiv)m(ely)-8 b(.)41 b(The)25 b(last)i(2)g(routines)f(allo)m(w)h(all)g(the)f (parameters)h(to)f(b)s(e)g(set)g(with)227 5340 y(one)31 b(function)f(call)i(\(one)f(supplies)e(the)i(column)f(name,)h(the)f (other)h(the)f(column)g(n)m(um)m(b)s(er\).)95 5601 y Fe(int)47 b(fits_iter_set_file\(iterato)o(rCo)o(l)42 b(*col,)k(fitsfile)g(*fptr\);)p eop end %%Page: 85 93 TeXDict begin 85 92 bop 0 299 a Fh(6.4.)72 b(COMPLETE)29 b(LIST)g(OF)i(ITERA)-8 b(TOR)29 b(R)m(OUTINES)1638 b Fj(85)95 555 y Fe(int)47 b(fits_iter_set_colname\(iter)o(ato)o(rCol)41 b(*col,)46 b(char)h(*colname\);)95 781 y(int)g (fits_iter_set_colnum\(itera)o(tor)o(Col)41 b(*col,)47 b(int)g(colnum\);)95 1007 y(int)g(fits_iter_set_datatype\(ite)o(rat)o (orCo)o(l)42 b(*col,)k(int)h(datatype\);)95 1233 y(int)g (fits_iter_set_iotype\(itera)o(tor)o(Col)41 b(*col,)47 b(int)g(iotype\);)95 1458 y(int)g(fits_iter_set_by_name\(iter)o(ato)o (rCol)41 b(*col,)46 b(fitsfile)g(*fptr,)477 1571 y(char)h(*colname,)e (int)i(datatype,)93 b(int)47 b(iotype\);)95 1797 y(int)g (fits_iter_set_by_num\(itera)o(tor)o(Col)41 b(*col,)47 b(fitsfile)e(*fptr,)477 1910 y(int)i(colnum,)f(int)h(datatype,)93 b(int)47 b(iotype\);)0 2155 y Fi(2)81 b Fj(Iterator)38 b(`accessor')h(functions)e(that)g(return)g(the)g(v)-5 b(alue)38 b(of)f(the)g(elemen)m(t)i(in)e(the)g(iteratorCol)i(structure) 227 2268 y(that)31 b(describ)s(es)f(a)h(particular)f(data)h(column)g (or)f(arra)m(y)95 2514 y Fe(fitsfile)46 b(*)h (fits_iter_get_file\(iterato)o(rCol)41 b(*col\);)95 2739 y(char)47 b(*)h(fits_iter_get_colname\(i)o(ter)o(ator)o(Col)41 b(*col\);)95 2965 y(int)47 b(fits_iter_get_colnum\(itera)o(tor)o(Col)41 b(*col\);)95 3191 y(int)47 b(fits_iter_get_datatype\(ite)o(rat)o(orCo)o (l)42 b(*col\);)95 3417 y(int)47 b(fits_iter_get_iotype\(itera)o(tor)o (Col)41 b(*col\);)95 3643 y(void)47 b(*)h(fits_iter_get_array\(ite)o (rat)o(orCo)o(l)42 b(*col\);)95 3868 y(long)47 b (fits_iter_get_tlmin\(itera)o(tor)o(Col)41 b(*col\);)95 4094 y(long)47 b(fits_iter_get_tlmax\(itera)o(tor)o(Col)41 b(*col\);)95 4320 y(long)47 b(fits_iter_get_repeat\(iter)o(ato)o(rCol) 41 b(*col\);)95 4546 y(char)47 b(*)h(fits_iter_get_tunit\(ite)o(rat)o (orCo)o(l)42 b(*col\);)95 4772 y(char)47 b(*)h (fits_iter_get_tdisp\(ite)o(rat)o(orCo)o(l)42 b(*col\);)0 5017 y Fi(3)81 b Fj(The)29 b(CFITSIO)g(iterator)j(function)95 5262 y Fe(int)47 b(fits_iterate_data\(int)42 b(narrays,)94 b(iteratorCol)44 b(*data,)i(long)h(offset,)573 5375 y(long)f(nPerLoop,) 573 5488 y(int)h(\(*workFn\)\()e(long)h(totaln,)g(long)h(offset,)f (long)g(firstn,)1289 5601 y(long)g(nvalues,)g(int)h(narrays,)e (iteratorCol)g(*data,)1289 5714 y(void)h(*userPointer\),)p eop end %%Page: 86 94 TeXDict begin 86 93 bop 0 299 a Fj(86)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)573 555 y Fe(void)46 b(*userPointer,)573 668 y(int)h(*status\);)p eop end %%Page: 87 95 TeXDict begin 87 94 bop 0 1225 a Fg(Chapter)65 b(7)0 1687 y Fm(W)-19 b(orld)77 b(Co)6 b(ordinate)78 b(System)f(Routines)0 2180 y Fj(The)36 b(FITS)g(comm)m(unit)m(y)h(has)f(adopted)h(a)g(set)g (of)g(k)m(eyw)m(ord)g(con)m(v)m(en)m(tions)h(that)f(de\014ne)f(the)h (transformations)0 2293 y(needed)30 b(to)i(con)m(v)m(ert)g(b)s(et)m(w)m (een)f(pixel)g(lo)s(cations)h(in)e(an)h(image)h(and)e(the)g(corresp)s (onding)g(celestial)j(co)s(ordinates)0 2406 y(on)25 b(the)h(sky)-8 b(,)27 b(or)e(more)g(generally)-8 b(,)29 b(that)d(de\014ne)e(w)m(orld)h (co)s(ordinates)i(that)e(are)h(to)g(b)s(e)f(asso)s(ciated)i(with)e(an)m (y)h(pixel)0 2518 y(lo)s(cation)h(in)e(an)h(n-dimensional)f(FITS)g (arra)m(y)-8 b(.)40 b(CFITSIO)24 b(is)h(distributed)g(with)g(a)h(a)g (few)f(self-con)m(tained)i(W)-8 b(orld)0 2631 y(Co)s(ordinate)30 b(System)g(\(W)m(CS\))g(routines,)g(ho)m(w)m(ev)m(er,)i(these)e (routines)g(DO)f(NOT)h(supp)s(ort)e(all)j(the)f(latest)h(W)m(CS)0 2744 y(con)m(v)m(en)m(tions,)38 b(so)c(it)h(is)g(STR)m(ONGL)-8 b(Y)34 b(RECOMMENDED)h(that)g(soft)m(w)m(are)h(dev)m(elop)s(ers)e(use)g (a)h(more)g(robust)0 2857 y(external)c(W)m(CS)g(library)-8 b(.)40 b(Sev)m(eral)32 b(recommended)e(libraries)g(are:)95 3138 y Fe(WCSLIB)47 b(-)95 b(supported)45 b(by)i(Mark)g(Calabretta)95 3251 y(WCSTools)f(-)h(supported)f(by)h(Doug)g(Mink)95 3364 y(AST)g(library)f(-)i(developed)d(by)i(the)g(U.K.)g(Starlink)e (project)0 3644 y Fj(More)30 b(information)f(ab)s(out)g(the)g(W)m(CS)g (k)m(eyw)m(ord)h(con)m(v)m(en)m(tions)h(and)d(links)h(to)h(all)g(of)f (these)g(W)m(CS)g(libraries)h(can)0 3757 y(b)s(e)g(found)f(on)h(the)h (FITS)e(Supp)s(ort)g(O\016ce)h(w)m(eb)g(site)i(at)f(h)m (ttp://\014ts.gsfc.nasa.go)m(v)j(under)29 b(the)h(W)m(CS)h(link.)0 3917 y(The)40 b(functions)h(pro)m(vided)g(in)f(these)i(external)f(W)m (CS)g(libraries)h(will)f(need)g(access)h(to)f(the)h(W)m(CS)f(k)m(eyw)m (ords)0 4030 y(con)m(tained)36 b(in)f(the)h(FITS)e(\014le)i(headers.)55 b(One)35 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(pass)f(this)g (information)h(to)g(the)f(external)0 4143 y(library)c(is)f(to)i(use)f (the)g(\014ts)p 942 4143 28 4 v 32 w(hdr2str)f(routine)h(in)g(CFITSIO)e (\(de\014ned)h(b)s(elo)m(w\))h(to)h(cop)m(y)g(the)f(header)g(k)m(eyw)m (ords)0 4256 y(in)m(to)k(one)e(long)i(string,)f(and)f(then)g(pass)g (this)h(string)f(to)i(an)e(in)m(terface)i(routine)f(in)f(the)h (external)g(library)f(that)0 4369 y(will)d(extract)h(the)f(necessary)f (W)m(CS)h(information)g(\(e.g.,)h(the)f('w)m(cspih')g(routine)f(in)g (the)h(W)m(CSLIB)f(library)h(and)0 4482 y(the)h('astFitsChan')g(and)f ('astPutCards')g(functions)g(in)g(the)h(AST)e(library\).)0 4763 y Fi(1)81 b Fj(Concatenate)38 b(the)f(header)f(k)m(eyw)m(ords)h (in)f(the)g(CHDU)h(in)m(to)h(a)f(single)g(long)g(string)f(of)h(c)m (haracters.)60 b(Eac)m(h)227 4876 y(80-c)m(haracter)28 b(\014xed-length)c(k)m(eyw)m(ord)h(record)g(is)g(app)s(ended)d(to)k (the)f(output)f(c)m(haracter)i(string,)g(in)e(order,)227 4989 y(with)h(no)f(in)m(terv)m(ening)i(separator)f(or)g(terminating)h (c)m(haracters.)40 b(The)24 b(last)i(header)e(record)h(is)f(terminated) 227 5101 y(with)33 b(a)g(NULL)f(c)m(haracter.)49 b(This)32 b(routine)h(allo)s(cates)i(memory)d(for)h(the)g(returned)e(c)m (haracter)j(arra)m(y)-8 b(,)35 b(so)227 5214 y(the)c(calling)h(program) e(m)m(ust)g(free)h(the)f(memory)g(when)g(\014nished.)227 5375 y(There)c(are)h(2)f(related)h(routines:)39 b(\014ts)p 1514 5375 V 32 w(hdr2str)25 b(simply)h(concatenates)j(all)e(the)f (existing)h(k)m(eyw)m(ords)g(in)f(the)227 5488 y(header;)40 b(\014ts)p 682 5488 V 32 w(con)m(v)m(ert)p 1003 5488 V 34 w(hdr2str)35 b(is)i(similar,)h(except)f(that)g(if)f(the)h(CHDU)f (is)h(a)f(tile)i(compressed)e(image)227 5601 y(\(stored)28 b(in)g(a)f(binary)g(table\))i(then)e(it)h(will)g(\014rst)f(con)m(v)m (ert)i(that)f(header)g(bac)m(k)g(to)g(that)g(of)g(a)g(normal)g(FITS)227 5714 y(image)k(b)s(efore)e(concatenating)j(the)d(k)m(eyw)m(ords.)1905 5942 y(87)p eop end %%Page: 88 96 TeXDict begin 88 95 bop 0 299 a Fj(88)1169 b Fh(CHAPTER)29 b(7.)112 b(W)m(ORLD)31 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(R)m(OUTINES)227 555 y Fj(Selected)h(k)m(eyw)m(ords)e(ma)m(y)h(b)s(e)e(excluded)h(from)g (the)g(returned)f(c)m(haracter)j(string.)40 b(If)27 b(the)i(second)f (param-)227 668 y(eter)h(\(no)s(commen)m(ts\))g(is)f(TR)m(UE)g (\(nonzero\))h(then)e(an)m(y)i(COMMENT,)f(HISTOR)-8 b(Y,)27 b(or)h(blank)g(k)m(eyw)m(ords)227 781 y(in)i(the)h(header)f(will)h(not) f(b)s(e)g(copied)h(to)g(the)g(output)f(string.)227 924 y(The)25 b('exclist')j(parameter)e(ma)m(y)g(b)s(e)f(used)g(to)h(supply) e(a)i(list)h(of)e(k)m(eyw)m(ords)h(that)h(are)f(to)g(b)s(e)f(excluded)g (from)227 1037 y(the)k(output)g(c)m(haracter)h(string.)41 b(Wild)29 b(card)g(c)m(haracters)h(\(*,)g(?,)f(and)g(#\))g(ma)m(y)g(b)s (e)f(used)g(in)h(the)g(excluded)227 1150 y(k)m(eyw)m(ord)h(names.)41 b(If)29 b(no)g(additional)i(k)m(eyw)m(ords)f(are)g(to)g(b)s(e)f (excluded,)h(then)f(set)h(nexc)g(=)f(0)h(and)f(sp)s(ecify)227 1263 y(NULL)i(for)f(the)g(the)h(**exclist)i(parameter.)95 1478 y Fe(int)47 b(fits_hdr2str)286 1591 y(\(fitsfile)f(*fptr,)g(int)h (nocomments,)d(char)j(**exclist,)e(int)i(nexc,)286 1704 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i(*status\))95 1930 y(int)g(fits_convert_hdr2str)c(/)k(ffcnvthdr2str)286 2043 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e (int)i(nexc,)286 2155 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i (*status\))0 2371 y Fi(2)81 b Fj(The)24 b(follo)m(wing)j(CFITSIO)d (routine)i(is)f(sp)s(eci\014cally)h(designed)f(for)h(use)f(in)g (conjunction)g(with)g(the)h(W)m(CSLIB)227 2484 y(library)-8 b(.)40 b(It)27 b(is)h(not)f(exp)s(ected)h(that)g(applications)g (programmers)f(will)h(call)g(this)f(routine)h(directly)-8 b(,)29 b(but)d(it)227 2597 y(is)33 b(do)s(cumen)m(ted)g(here)g(for)g (completeness.)50 b(This)33 b(routine)g(extracts)h(arra)m(ys)g(from)e (a)i(binary)e(table)i(that)227 2710 y(con)m(tain)i(W)m(CS)e (information)h(using)f(the)g(-T)-8 b(AB)36 b(table)f(lo)s(okup)f(con)m (v)m(en)m(tion.)55 b(See)35 b(the)f(do)s(cumen)m(tation)227 2822 y(pro)m(vided)c(with)g(the)h(W)m(CSLIB)f(library)g(for)g(more)h (information.)95 3038 y Fe(int)47 b(fits_read_wcstab)334 3151 y(\(fitsfile)e(*fptr,)h(int)h(nwtb,)g(wtbarr)f(*wtb,)g(int)h (*status\);)0 3477 y Ff(7.1)180 b(Self-con)l(tained)46 b(W)l(CS)f(Routines)0 3728 y Fj(The)21 b(follo)m(wing)i(routines)e(DO)g (NOT)g(supp)s(ort)f(the)h(more)h(recen)m(t)g(W)m(CS)f(con)m(v)m(en)m (tions)j(that)d(ha)m(v)m(e)i(b)s(een)e(appro)m(v)m(ed)0 3841 y(as)34 b(part)g(of)g(the)g(FITS)f(standard.)50 b(Consequen)m(tly)-8 b(,)35 b(the)f(follo)m(wing)i(routines)d(ARE)h(NO) m(W)h(DEPRECA)-8 b(TED.)0 3953 y(It)30 b(is)g(STR)m(ONGL)-8 b(Y)30 b(RECOMMENDED)h(that)g(soft)m(w)m(are)g(dev)m(elop)s(ers)f(not)h (use)f(these)g(routines,)g(and)g(instead)0 4066 y(use)g(an)g(external)i (W)m(CS)e(library)-8 b(,)31 b(as)f(describ)s(ed)f(in)i(the)f(previous)g (section.)0 4227 y(These)21 b(routines)g(are)g(included)f(mainly)h(for) g(bac)m(kw)m(ard)g(compatibilit)m(y)j(with)c(existing)i(soft)m(w)m (are.)39 b(They)21 b(supp)s(ort)0 4339 y(the)30 b(follo)m(wing)i (standard)d(map)g(pro)5 b(jections:)41 b(-SIN,)30 b(-T)-8 b(AN,)31 b(-AR)m(C,)g(-NCP)-8 b(,)30 b(-GLS,)g(-MER,)h(and)e(-AIT)h (\(these)0 4452 y(are)f(the)g(legal)h(v)-5 b(alues)29 b(for)f(the)h(co)s(ordt)m(yp)s(e)f(parameter\).)41 b(These)28 b(routines)h(are)g(based)f(on)g(similar)h(functions)f(in)0 4565 y(Classic)j(AIPS.)f(All)h(the)g(angular)f(quan)m(tities)i(are)f (giv)m(en)g(in)f(units)g(of)g(degrees.)0 4781 y Fi(1)81 b Fj(Get)41 b(the)f(v)-5 b(alues)41 b(of)g(the)f(basic)h(set)g(of)f (standard)g(FITS)f(celestial)k(co)s(ordinate)e(system)g(k)m(eyw)m(ords) f(from)227 4894 y(the)33 b(header)f(of)h(a)f(FITS)g(image)i(\(i.e.,)g (the)f(primary)f(arra)m(y)g(or)h(an)f(IMA)m(GE)i(extension\).)47 b(These)33 b(v)-5 b(alues)227 5006 y(ma)m(y)35 b(then)f(b)s(e)g(passed) f(to)i(the)g(\014ts)p 1462 5006 28 4 v 32 w(pix)p 1618 5006 V 32 w(to)p 1730 5006 V 34 w(w)m(orld)f(and)g(\014ts)p 2321 5006 V 32 w(w)m(orld)p 2573 5006 V 33 w(to)p 2686 5006 V 33 w(pix)g(routines)g(that)h(p)s(erform)e(the)227 5119 y(co)s(ordinate)f(transformations.)42 b(If)30 b(an)m(y)h(or)f(all) i(of)f(the)g(W)m(CS)f(k)m(eyw)m(ords)h(are)g(not)g(presen)m(t,)g(then)g (default)227 5232 y(v)-5 b(alues)26 b(will)f(b)s(e)f(returned.)38 b(If)24 b(the)i(\014rst)e(co)s(ordinate)i(axis)f(is)g(the)g (declination-lik)m(e)j(co)s(ordinate,)f(then)e(this)227 5345 y(routine)31 b(will)f(sw)m(ap)h(them)f(so)h(that)g(the)f (longitudinal-lik)m(e)j(co)s(ordinate)e(is)f(returned)g(as)g(the)h (\014rst)e(axis.)227 5488 y(The)34 b(\014rst)g(routine)h(\(\013gics\))h (returns)e(the)h(primary)f(W)m(CS,)g(whereas)h(the)g(second)g(routine)f (returns)g(the)227 5601 y(particular)24 b(v)m(ersion)h(of)f(the)g(W)m (CS)f(sp)s(eci\014ed)g(b)m(y)h(the)g('v)m(ersion')h(parameter,)h(whic)m (h)d(m)m(uc)m(h)h(b)s(e)f(a)h(c)m(haracter)227 5714 y(ranging)31 b(from)f('A')h(to)g('Z')f(\(or)h(a)g(blank)f(c)m(haracter,)i(whic)m(h)e (is)g(equiv)-5 b(alen)m(t)32 b(to)f(calling)h(\013gics\).)p eop end %%Page: 89 97 TeXDict begin 89 96 bop 0 299 a Fh(7.1.)113 b(SELF-CONT)-8 b(AINED)30 b(W)m(CS)g(R)m(OUTINES)1984 b Fj(89)227 555 y(If)35 b(the)h(\014le)f(uses)g(the)g(new)m(er)h('CDj)p 1454 555 28 4 v 32 w(i')g(W)m(CS)f(transformation)h(matrix)g(k)m(eyw)m (ords)f(instead)h(of)f(old)h(st)m(yle)227 668 y('CDEL)-8 b(Tn')37 b(and)f('CR)m(OT)-8 b(A2')38 b(k)m(eyw)m(ords,)h(then)e(this)f (routine)h(will)g(calculate)j(and)c(return)g(the)h(v)-5 b(alues)227 781 y(of)33 b(the)g(equiv)-5 b(alen)m(t)35 b(old-st)m(yle)f(k)m(eyw)m(ords.)49 b(Note)34 b(that)g(the)f(con)m(v)m (ersion)h(from)e(the)i(new-st)m(yle)g(k)m(eyw)m(ords)227 894 y(to)e(the)f(old-st)m(yle)h(v)-5 b(alues)31 b(is)g(sometimes)g (only)g(an)g(appro)m(ximation,)h(so)e(if)h(the)g(appro)m(ximation)h(is) e(larger)227 1007 y(than)37 b(an)h(in)m(ternally)g(de\014ned)e (threshold)h(lev)m(el,)k(then)c(CFITSIO)f(will)i(still)g(return)e(the)i (appro)m(ximate)227 1120 y(W)m(CS)32 b(k)m(eyw)m(ord)h(v)-5 b(alues,)33 b(but)e(will)h(also)h(return)e(with)h(status)g(=)f(APPR)m (O)m(X)p 2908 1120 V 34 w(W)m(CS)p 3149 1120 V 33 w(KEY,)g(to)i(w)m (arn)f(the)227 1233 y(calling)k(program)e(that)h(appro)m(ximations)g (ha)m(v)m(e)g(b)s(een)f(made.)52 b(It)35 b(is)f(then)g(up)f(to)i(the)f (calling)i(program)227 1346 y(to)30 b(decide)g(whether)e(the)h(appro)m (ximations)h(are)g(su\016cien)m(tly)f(accurate)i(for)e(the)g (particular)g(application,)227 1458 y(or)46 b(whether)e(more)i(precise) g(W)m(CS)f(transformations)h(m)m(ust)f(b)s(e)g(p)s(erformed)f(using)g (new-st)m(yle)j(W)m(CS)227 1571 y(k)m(eyw)m(ords)31 b(directly)-8 b(.)95 1824 y Fe(int)47 b(fits_read_img_coord)c(/)k(ffgics)286 1937 y(\(fitsfile)f(*fptr,)g(>)h(double)f(*xrefval,)g(double)g (*yrefval,)334 2050 y(double)g(*xrefpix,)f(double)i(*yrefpix,)e(double) h(*xinc,)g(double)g(*yinc,)334 2163 y(double)g(*rot,)h(char)f (*coordtype,)f(int)i(*status\))95 2389 y(int)g (fits_read_img_coord_versio)o(n)42 b(/)47 b(ffgicsa)286 2502 y(\(fitsfile)f(*fptr,)g(char)g(version,)g(>)h(double)f(*xrefval,)g (double)g(*yrefval,)334 2615 y(double)g(*xrefpix,)f(double)i(*yrefpix,) e(double)h(*xinc,)g(double)g(*yinc,)334 2728 y(double)g(*rot,)h(char)f (*coordtype,)f(int)i(*status\))0 2981 y Fi(2)81 b Fj(Get)30 b(the)f(v)-5 b(alues)30 b(of)f(the)h(standard)e(FITS)h(celestial)j(co)s (ordinate)e(system)f(k)m(eyw)m(ords)h(from)f(the)g(header)g(of)h(a)227 3094 y(FITS)23 b(table)i(where)e(the)h(X)g(and)g(Y)g(\(or)g(RA)g(and)f (DEC\))h(co)s(ordinates)h(are)f(stored)g(in)f(2)h(separate)h(columns) 227 3207 y(of)30 b(the)f(table)h(\(as)g(in)f(the)h(Ev)m(en)m(t)g(List)g (table)g(format)f(that)h(is)g(often)f(used)g(b)m(y)g(high)g(energy)g (astroph)m(ysics)227 3320 y(missions\).)71 b(These)40 b(v)-5 b(alues)40 b(ma)m(y)h(then)f(b)s(e)f(passed)h(to)h(the)f(\014ts) p 2511 3320 V 33 w(pix)p 2668 3320 V 32 w(to)p 2780 3320 V 34 w(w)m(orld)g(and)g(\014ts)p 3383 3320 V 32 w(w)m(orld)p 3635 3320 V 33 w(to)p 3748 3320 V 33 w(pix)227 3432 y(routines)31 b(that)f(p)s(erform)f(the)i(co)s(ordinate)g(transformations.)95 3685 y Fe(int)47 b(fits_read_tbl_coord)c(/)k(ffgtcs)286 3798 y(\(fitsfile)f(*fptr,)g(int)h(xcol,)f(int)h(ycol,)f(>)i(double)e (*xrefval,)334 3911 y(double)g(*yrefval,)f(double)i(*xrefpix,)e(double) h(*yrefpix,)f(double)h(*xinc,)334 4024 y(double)g(*yinc,)g(double)g (*rot,)h(char)f(*coordtype,)f(int)i(*status\))0 4277 y Fi(3)81 b Fj(Calculate)42 b(the)g(celestial)h(co)s(ordinate)f (corresp)s(onding)e(to)i(the)f(input)f(X)h(and)g(Y)g(pixel)g(lo)s (cation)i(in)e(the)227 4390 y(image.)95 4643 y Fe(int)47 b(fits_pix_to_world)c(/)48 b(ffwldp)286 4756 y(\(double)e(xpix,)h (double)f(ypix,)g(double)g(xrefval,)g(double)g(yrefval,)334 4869 y(double)g(xrefpix,)g(double)g(yrefpix,)f(double)h(xinc,)h(double) f(yinc,)334 4982 y(double)g(rot,)h(char)f(*coordtype,)f(>)j(double)e (*xpos,)g(double)g(*ypos,)334 5095 y(int)h(*status\))0 5348 y Fi(4)81 b Fj(Calculate)42 b(the)g(X)f(and)f(Y)h(pixel)h(lo)s (cation)g(corresp)s(onding)e(to)i(the)f(input)f(celestial)k(co)s (ordinate)e(in)f(the)227 5461 y(image.)95 5714 y Fe(int)47 b(fits_world_to_pix)c(/)48 b(ffxypx)p eop end %%Page: 90 98 TeXDict begin 90 97 bop 0 299 a Fj(90)1169 b Fh(CHAPTER)29 b(7.)112 b(W)m(ORLD)31 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(R)m(OUTINES)286 555 y Fe(\(double)46 b(xpos,)h(double)f(ypos,)g(double)g(xrefval,)g (double)g(yrefval,)334 668 y(double)g(xrefpix,)g(double)g(yrefpix,)f (double)h(xinc,)h(double)f(yinc,)334 781 y(double)g(rot,)h(char)f (*coordtype,)f(>)j(double)e(*xpix,)g(double)g(*ypix,)334 894 y(int)h(*status\))p eop end %%Page: 91 99 TeXDict begin 91 98 bop 0 1225 a Fg(Chapter)65 b(8)0 1687 y Fm(Hierarc)-6 b(hical)76 b(Grouping)h(Routines)0 2180 y Fj(These)34 b(functions)h(allo)m(w)h(for)e(the)h(creation)h(and) e(manipulation)h(of)g(FITS)f(HDU)h(Groups,)h(as)f(de\014ned)e(in)h("A)0 2293 y(Hierarc)m(hical)f(Grouping)c(Con)m(v)m(en)m(tion)j(for)e(FITS")h (b)m(y)f(Jennings,)g(P)m(ence,)h(F)-8 b(olk)32 b(and)e(Sc)m(hlesinger:) 0 2453 y(h)m(ttps://\014ts.gsfc.nasa.go)m (v/registry/grouping/grouping.p)s(df)0 2613 y(A)38 b(group)g(is)g(a)g (collection)j(of)d(HDUs)h(whose)f(asso)s(ciation)h(is)g(de\014ned)d(b)m (y)i(a)h Fa(gr)-5 b(ouping)40 b(table)p Fj(.)65 b(HDUs)38 b(whic)m(h)0 2726 y(are)46 b(part)f(of)g(a)g(group)g(are)h(referred)e (to)i(as)f Fa(memb)-5 b(er)47 b(HDUs)d Fj(or)h(simply)g(as)g Fa(memb)-5 b(ers)p Fj(.)86 b(Grouping)45 b(table)0 2839 y(mem)m(b)s(er)40 b(HDUs)i(ma)m(y)f(themselv)m(es)h(b)s(e)f(grouping)f (tables,)45 b(th)m(us)40 b(allo)m(wing)j(for)e(the)g(construction)g(of) g(op)s(en-)0 2952 y(ended)30 b(hierarc)m(hies)h(of)f(HDUs.)0 3112 y(Grouping)c(tables)i(con)m(tain)g(one)f(ro)m(w)g(for)f(eac)m(h)i (mem)m(b)s(er)e(HDU.)i(The)e(grouping)g(table)i(columns)e(pro)m(vide)h (iden-)0 3225 y(ti\014cation)i(information)f(that)g(allo)m(ws)h (applications)f(to)g(reference)g(or)g("p)s(oin)m(t)g(to")g(the)g(mem)m (b)s(er)f(HDUs.)40 b(Mem-)0 3338 y(b)s(er)27 b(HDUs)h(are)g(exp)s (ected,)h(but)e(not)h(required,)f(to)i(con)m(tain)g(a)f(set)g(of)g (GRPIDn/GRPLCn)f(k)m(eyw)m(ords)h(in)f(their)0 3451 y(headers)j(for)h (eac)m(h)g(grouping)g(table)g(that)g(they)g(are)g(referenced)g(b)m(y)-8 b(.)41 b(In)30 b(this)h(sense,)g(the)g(GRPIDn/GRPLCn)0 3563 y(k)m(eyw)m(ords)d("link")g(the)g(mem)m(b)s(er)f(HDU)h(bac)m(k)g (to)g(its)g(Grouping)f(table.)41 b(Note)29 b(that)f(a)f(mem)m(b)s(er)g (HDU)h(need)g(not)0 3676 y(reside)i(in)g(the)g(same)g(FITS)f(\014le)i (as)f(its)g(grouping)g(table,)h(and)e(that)i(a)f(giv)m(en)h(HDU)g(ma)m (y)g(b)s(e)e(referenced)h(b)m(y)g(up)0 3789 y(to)h(999)h(grouping)e (tables)h(sim)m(ultaneously)-8 b(.)0 3949 y(Grouping)22 b(tables)i(are)f(implemen)m(ted)g(as)g(FITS)f(binary)g(tables)h(with)g (up)e(to)j(six)e(pre-de\014ned)g(column)g(TTYPEn)0 4062 y(v)-5 b(alues:)36 b('MEMBER)p 752 4062 28 4 v 34 w(XTENSION',)20 b('MEMBER)p 1789 4062 V 33 w(NAME',)h('MEMBER)p 2620 4062 V 34 w(VERSION',)f('MEMBER)p 3590 4062 V 34 w(POSITION',)0 4175 y('MEMBER)p 451 4175 V 34 w(URI)p 653 4175 V 32 w(TYPE')g(and)g('MEMBER)p 1601 4175 V 34 w(LOCA)-8 b(TION'.)20 b(The)f(\014rst)h(three)g(columns)g(allo)m(w)i(mem)m(b)s(er)e(HDUs)0 4288 y(to)28 b(b)s(e)f(iden)m(ti\014ed)g(b)m(y)g(reference)h(to)g (their)f(XTENSION,)g(EXTNAME)g(and)g(EXTVER)g(k)m(eyw)m(ord)g(v)-5 b(alues.)40 b(The)0 4401 y(fourth)29 b(column)h(allo)m(ws)i(mem)m(b)s (er)d(HDUs)i(to)g(b)s(e)f(iden)m(ti\014ed)g(b)m(y)g(HDU)h(p)s(osition)f (within)g(their)g(FITS)g(\014le.)40 b(The)0 4514 y(last)f(t)m(w)m(o)g (columns)e(iden)m(tify)h(the)g(FITS)f(\014le)h(in)f(whic)m(h)h(the)g (mem)m(b)s(er)f(HDU)h(resides,)i(if)d(di\013eren)m(t)i(from)e(the)0 4627 y(grouping)30 b(table)h(FITS)f(\014le.)0 4787 y(Additional)25 b(user)f(de\014ned)f("auxiliary")j(columns)e(ma)m(y)h(also)g(b)s(e)f (included)g(with)g(an)m(y)h(grouping)f(table.)39 b(When)25 b(a)0 4900 y(grouping)i(table)i(is)f(copied)g(or)f(mo)s(di\014ed)g(the) h(presence)g(of)f(auxiliary)i(columns)e(is)h(alw)m(a)m(ys)h(tak)m(en)g (in)m(to)f(accoun)m(t)0 5013 y(b)m(y)j(the)g(grouping)g(supp)s(ort)f (functions;)h(ho)m(w)m(ev)m(er,)i(the)e(grouping)g(supp)s(ort)f (functions)g(cannot)i(directly)g(mak)m(e)0 5126 y(use)e(of)h(this)f (data.)0 5286 y(If)44 b(a)h(grouping)f(table)h(column)f(is)h(de\014ned) e(but)h(the)g(corresp)s(onding)g(mem)m(b)s(er)f(HDU)j(information)e(is) h(un-)0 5399 y(a)m(v)-5 b(ailable)41 b(then)c(a)i(n)m(ull)f(v)-5 b(alue)39 b(of)f(the)g(appropriate)h(data)f(t)m(yp)s(e)h(is)f(inserted) g(in)g(the)g(column)g(\014eld.)64 b(In)m(teger)0 5512 y(columns)26 b(\(MEMBER)p 811 5512 V 34 w(POSITION,)f(MEMBER)p 1771 5512 V 34 w(VERSION\))h(are)h(de\014ned)f(with)g(a)h(TNULLn)f(v)-5 b(alue)27 b(of)g(zero)0 5625 y(\(0\).)41 b(Character)27 b(\014eld)f(columns)h(\(MEMBER)p 1607 5625 V 34 w(XTENSION,)f(MEMBER)p 2600 5625 V 33 w(NAME,)i(MEMBER)p 3388 5625 V 34 w(URI)p 3590 5625 V 32 w(TYPE,)1905 5942 y(91)p eop end %%Page: 92 100 TeXDict begin 92 99 bop 0 299 a Fj(92)1338 b Fh(CHAPTER)29 b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)0 555 y Fj(MEMBER)p 426 555 28 4 v 33 w(LOCA)-8 b(TION\))30 b(utilize)i(an)e(ASCI)s(I)f(n)m(ull)h(c)m(haracter)i(to)f(denote)g(a)g (n)m(ull)f(\014eld)g(v)-5 b(alue.)0 715 y(The)23 b(grouping)g(supp)s (ort)f(functions)h(b)s(elong)h(to)g(t)m(w)m(o)h(basic)f(categories:)40 b(those)24 b(that)h(w)m(ork)e(with)h(grouping)f(table)0 828 y(HDUs)j(\(\013gt**\))j(and)c(those)h(that)h(w)m(ork)f(with)f(mem)m (b)s(er)h(HDUs)g(\(\013gm**\).)41 b(Tw)m(o)26 b(functions,)h(\014ts)p 3360 828 V 32 w(cop)m(y)p 3573 828 V 34 w(group\(\))0 941 y(and)40 b(\014ts)p 314 941 V 33 w(remo)m(v)m(e)p 626 941 V 34 w(group\(\),)k(ha)m(v)m(e)e(the)f(option)g(to)h(recursiv)m (ely)f(cop)m(y/delete)j(en)m(tire)e(groups.)71 b(Care)41 b(should)0 1054 y(b)s(e)33 b(tak)m(en)h(when)f(emplo)m(ying)h(these)g (functions)f(in)g(recursiv)m(e)h(mo)s(de)f(as)g(p)s(o)s(orly)g (de\014ned)f(groups)h(could)g(cause)0 1167 y(unpredictable)25 b(results.)39 b(The)25 b(problem)g(of)h(a)g(grouping)f(table)i (directly)f(or)g(indirectly)g(referencing)g(itself)g(\(th)m(us)0 1280 y(creating)41 b(an)f(in\014nite)f(lo)s(op\))i(is)e(protected)i (against;)46 b(in)39 b(fact,)44 b(neither)39 b(function)h(will)g (attempt)h(to)f(cop)m(y)h(or)0 1393 y(delete)32 b(an)e(HDU)h(t)m(wice.) 0 1749 y Ff(8.1)135 b(Grouping)45 b(T)-11 b(able)45 b(Routines)0 2003 y Fi(1)81 b Fj(Create)34 b(\(app)s(end\))f(a)h(grouping)f(table)i (at)f(the)g(end)f(of)h(the)g(curren)m(t)f(FITS)g(\014le)h(p)s(oin)m (ted)g(to)g(b)m(y)g(fptr.)49 b(The)227 2116 y(grpname)28 b(parameter)h(pro)m(vides)g(the)g(grouping)f(table)h(name)g(\(GRPNAME)g (k)m(eyw)m(ord)g(v)-5 b(alue\))29 b(and)f(ma)m(y)227 2229 y(b)s(e)42 b(set)h(to)g(NULL)f(if)g(no)g(group)g(name)g(is)h(to)g (b)s(e)e(sp)s(eci\014ed.)76 b(The)42 b(groupt)m(yp)s(e)g(parameter)g (sp)s(eci\014es)227 2341 y(the)c(desired)g(structure)f(of)h(the)g (grouping)f(table)i(and)e(ma)m(y)i(tak)m(e)g(on)f(the)g(v)-5 b(alues:)56 b(GT)p 3355 2341 V 33 w(ID)p 3490 2341 V 33 w(ALL)p 3705 2341 V 32 w(URI)227 2454 y(\(all)35 b(columns)e (created\),)j(GT)p 1274 2454 V 33 w(ID)p 1409 2454 V 33 w(REF)d(\(ID)h(b)m(y)g(reference)g(columns\),)g(GT)p 2904 2454 V 33 w(ID)p 3039 2454 V 33 w(POS)e(\(ID)i(b)m(y)g(p)s (osition)227 2567 y(columns\),)48 b(GT)p 801 2567 V 32 w(ID)p 935 2567 V 33 w(ALL)c(\(ID)g(b)m(y)f(reference)i(and)e(p)s (osition)g(columns\),)48 b(GT)p 3028 2567 V 32 w(ID)p 3162 2567 V 33 w(REF)p 3383 2567 V 33 w(URI)c(\(ID)g(b)m(y)227 2680 y(reference)35 b(and)e(FITS)g(\014le)i(URI)e(columns\),)j(and)d (GT)p 2129 2680 V 33 w(ID)p 2264 2680 V 33 w(POS)p 2481 2680 V 32 w(URI)h(\(ID)g(b)m(y)g(p)s(osition)g(and)g(FITS)f(\014le)227 2793 y(URI)e(columns\).)95 3072 y Fe(int)47 b(fits_create_group)c(/)48 b(ffgtcr)286 3185 y(\(fitsfile)e(*fptr,)g(char)g(*grpname,)g(int)h (grouptype,)e(>)i(int)g(*status\))0 3463 y Fi(2)81 b Fj(Create)26 b(\(insert\))g(a)f(grouping)g(table)h(just)f(after)h(the)f (CHDU)h(of)g(the)f(curren)m(t)g(FITS)g(\014le)g(p)s(oin)m(ted)g(to)h(b) m(y)g(fptr.)227 3576 y(All)k(HDUs)f(b)s(elo)m(w)g(the)g(the)g (insertion)g(p)s(oin)m(t)f(will)i(b)s(e)e(shifted)g(do)m(wn)m(w)m(ards) g(to)i(mak)m(e)g(ro)s(om)e(for)g(the)h(new)227 3689 y(HDU.)23 b(The)e(grpname)h(parameter)g(pro)m(vides)f(the)h(grouping)g(table)g (name)g(\(GRPNAME)h(k)m(eyw)m(ord)f(v)-5 b(alue\))227 3802 y(and)25 b(ma)m(y)i(b)s(e)e(set)h(to)h(NULL)e(if)h(no)g(group)f (name)h(is)g(to)g(b)s(e)f(sp)s(eci\014ed.)39 b(The)25 b(groupt)m(yp)s(e)h(parameter)g(sp)s(eci-)227 3915 y(\014es)g(the)h (desired)f(structure)g(of)h(the)f(grouping)g(table)i(and)e(ma)m(y)h (tak)m(e)h(on)e(the)h(v)-5 b(alues:)39 b(GT)p 3355 3915 V 33 w(ID)p 3490 3915 V 33 w(ALL)p 3705 3915 V 32 w(URI)227 4028 y(\(all)c(columns)e(created\),)j(GT)p 1274 4028 V 33 w(ID)p 1409 4028 V 33 w(REF)d(\(ID)h(b)m(y)g(reference)g (columns\),)g(GT)p 2904 4028 V 33 w(ID)p 3039 4028 V 33 w(POS)e(\(ID)i(b)m(y)g(p)s(osition)227 4141 y(columns\),)29 b(GT)p 782 4141 V 33 w(ID)p 917 4141 V 33 w(ALL)f(\(ID)g(b)m(y)g (reference)h(and)e(p)s(osition)h(columns\),)h(GT)p 2897 4141 V 33 w(ID)p 3032 4141 V 33 w(REF)p 3253 4141 V 32 w(URI)f(\(ID)h(b)m(y)f(ref-)227 4253 y(erence)g(and)e(FITS)h(\014le)g (URI)g(columns\),)h(and)e(GT)p 1976 4253 V 33 w(ID)p 2111 4253 V 33 w(POS)p 2328 4253 V 32 w(URI)h(\(ID)g(b)m(y)g(p)s (osition)g(and)g(FITS)f(\014le)h(URI)227 4366 y(columns\))k(.)95 4645 y Fe(int)47 b(fits_insert_group)c(/)48 b(ffgtis)286 4758 y(\(fitsfile)e(*fptr,)g(char)g(*grpname,)g(int)h(grouptype,)e(>)i (int)g(*status\))0 5036 y Fi(3)81 b Fj(Change)20 b(the)h(structure)f (of)h(an)g(existing)g(grouping)g(table)g(p)s(oin)m(ted)g(to)g(b)m(y)g (gfptr.)37 b(The)20 b(groupt)m(yp)s(e)g(parameter)227 5149 y(\(see)27 b(\014ts)p 532 5149 V 32 w(create)p 800 5149 V 35 w(group\(\))e(for)h(v)-5 b(alid)26 b(parameter)g(v)-5 b(alues\))26 b(sp)s(eci\014es)g(the)f(new)g(structure)h(of)f(the)h (grouping)227 5262 y(table.)44 b(This)30 b(function)h(only)g(adds)g(or) g(remo)m(v)m(es)h(grouping)f(table)h(columns,)f(it)h(do)s(es)f(not)g (add)g(or)g(delete)227 5375 y(group)26 b(mem)m(b)s(ers)f(\(i.e.,)k (table)e(ro)m(ws\).)40 b(If)26 b(the)g(grouping)g(table)h(already)g (has)f(the)h(desired)e(structure)h(then)227 5488 y(no)35 b(op)s(erations)f(are)h(p)s(erformed)e(and)h(function)g(simply)h (returns)e(with)h(a)h(\(0\))g(success)g(status)g(co)s(de.)53 b(If)227 5601 y(the)32 b(requested)g(structure)g(c)m(hange)h(creates)g (new)f(grouping)g(table)h(columns,)f(then)g(the)g(column)g(v)-5 b(alues)227 5714 y(for)30 b(all)i(existing)f(mem)m(b)s(ers)f(will)g(b)s (e)g(\014lled)g(with)g(the)h(n)m(ull)f(v)-5 b(alues)31 b(appropriate)f(to)h(the)g(column)f(t)m(yp)s(e.)p eop end %%Page: 93 101 TeXDict begin 93 100 bop 0 299 a Fh(8.1.)72 b(GR)m(OUPING)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)2235 b Fj(93)95 555 y Fe(int)47 b(fits_change_group)c(/)48 b(ffgtch)286 668 y(\(fitsfile)e(*gfptr,)f(int)i(grouptype,)e(>)j(int)f(*status\))0 905 y Fi(4)81 b Fj(Remo)m(v)m(e)41 b(the)e(group)g(de\014ned)f(b)m(y)h (the)h(grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)g(gfptr,)h(and)e (optionally)i(all)f(the)227 1018 y(group)29 b(mem)m(b)s(er)f(HDUs.)41 b(The)28 b(rmopt)h(parameter)g(sp)s(eci\014es)g(the)g(action)h(to)g(b)s (e)e(tak)m(en)i(for)f(all)h(mem)m(b)s(ers)227 1131 y(of)d(the)g(group)g (de\014ned)e(b)m(y)i(the)g(grouping)g(table.)40 b(V)-8 b(alid)28 b(v)-5 b(alues)27 b(are:)40 b(OPT)p 2848 1131 28 4 v 32 w(RM)p 3030 1131 V 33 w(GPT)26 b(\(delete)j(only)e(the)227 1244 y(grouping)33 b(table\))i(and)e(OPT)p 1259 1244 V 32 w(RM)p 1441 1244 V 33 w(ALL)g(\(recursiv)m(ely)h(delete)h(all)f (HDUs)g(that)g(b)s(elong)f(to)h(the)g(group\).)227 1357 y(An)m(y)d(groups)g(con)m(taining)i(the)e(grouping)g(table)h(gfptr)e (as)i(a)f(mem)m(b)s(er)g(are)g(up)s(dated,)f(and)h(if)g(rmopt)g(==)227 1470 y(OPT)p 431 1470 V 32 w(RM)p 613 1470 V 33 w(GPT)21 b(all)h(mem)m(b)s(ers)f(ha)m(v)m(e)h(their)f(GRPIDn)g(and)g(GRPLCn)f(k) m(eyw)m(ords)h(up)s(dated)f(accordingly)-8 b(.)227 1582 y(If)36 b(rmopt)g(==)g(OPT)p 985 1582 V 32 w(RM)p 1167 1582 V 33 w(ALL,)g(then)g(other)h(groups)e(that)i(con)m(tain)h(the)e (deleted)h(mem)m(b)s(ers)f(of)g(gfptr)227 1695 y(are)31 b(up)s(dated)e(to)i(re\015ect)g(the)g(deletion)g(accordingly)-8 b(.)95 1932 y Fe(int)47 b(fits_remove_group)c(/)48 b(ffgtrm)286 2045 y(\(fitsfile)e(*gfptr,)f(int)i(rmopt,)f(>)i(int)f(*status\))0 2282 y Fi(5)81 b Fj(Cop)m(y)28 b(\(app)s(end\))g(the)h(group)f (de\014ned)g(b)m(y)h(the)f(grouping)h(table)h(p)s(oin)m(ted)e(to)i(b)m (y)e(infptr,)h(and)f(optionally)i(all)227 2395 y(group)g(mem)m(b)s(er)h (HDUs,)g(to)h(the)f(FITS)f(\014le)g(p)s(oin)m(ted)h(to)h(b)m(y)e (outfptr.)41 b(The)31 b(cp)s(opt)f(parameter)h(sp)s(eci\014es)227 2508 y(the)c(action)h(to)f(b)s(e)f(tak)m(en)h(for)g(all)g(mem)m(b)s (ers)f(of)g(the)h(group)f(infptr.)38 b(V)-8 b(alid)28 b(v)-5 b(alues)26 b(are:)40 b(OPT)p 3443 2508 V 32 w(GCP)p 3674 2508 V 32 w(GPT)227 2621 y(\(cop)m(y)d(only)g(the)f(grouping)g (table\))h(and)e(OPT)p 1887 2621 V 32 w(GCP)p 2118 2621 V 33 w(ALL)h(\(recursiv)m(ely)h(cop)m(y)g(ALL)e(the)i(HDUs)f(that)227 2734 y(b)s(elong)24 b(to)g(the)g(group)f(de\014ned)g(b)m(y)g(infptr\).) 38 b(If)23 b(the)h(cp)s(opt)g(==)f(OPT)p 2618 2734 V 32 w(GCP)p 2849 2734 V 32 w(GPT)h(then)f(the)h(mem)m(b)s(ers)f(of)227 2847 y(infptr)i(ha)m(v)m(e)h(their)g(GRPIDn)f(and)g(GRPLCn)g(k)m(eyw)m (ords)h(up)s(dated)e(to)i(re\015ect)g(the)g(existence)h(of)f(the)f(new) 227 2960 y(grouping)f(table)g(outfptr,)h(since)f(they)g(no)m(w)g(b)s (elong)g(to)g(the)g(new)g(group.)38 b(If)23 b(cp)s(opt)h(==)f(OPT)p 3460 2960 V 32 w(GCP)p 3691 2960 V 32 w(ALL)227 3073 y(then)29 b(the)g(new)g(grouping)g(table)h(outfptr)e(only)h(con)m (tains)i(p)s(oin)m(ters)e(to)h(the)f(copied)g(mem)m(b)s(er)g(HDUs)h (and)227 3185 y(not)38 b(the)g(original)g(mem)m(b)s(er)f(HDUs)h(of)g (infptr.)61 b(Note)39 b(that,)h(when)d(cp)s(opt)g(==)g(OPT)p 3301 3185 V 32 w(GCP)p 3532 3185 V 33 w(ALL,)g(all)227 3298 y(mem)m(b)s(ers)h(of)h(the)f(group)g(de\014ned)f(b)m(y)i(infptr)e (will)i(b)s(e)e(copied)i(to)g(a)g(single)g(FITS)f(\014le)h(p)s(oin)m (ted)f(to)h(b)m(y)227 3411 y(outfptr)30 b(regardless)h(of)f(their)h (\014le)f(distribution)g(in)g(the)h(original)g(group.)95 3648 y Fe(int)47 b(fits_copy_group)d(/)j(ffgtcp)286 3761 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(cpopt,)f(>)h (int)g(*status\))0 3998 y Fi(6)81 b Fj(Merge)40 b(the)f(t)m(w)m(o)h (groups)e(de\014ned)g(b)m(y)h(the)g(grouping)g(table)g(HDUs)h(infptr)e (and)g(outfptr)h(b)m(y)f(com)m(bining)227 4111 y(their)30 b(mem)m(b)s(ers)f(in)m(to)i(a)f(single)g(grouping)f(table.)42 b(All)30 b(mem)m(b)s(er)f(HDUs)h(\(ro)m(ws\))h(are)f(copied)g(from)f (infptr)227 4224 y(to)f(outfptr.)39 b(If)26 b(mgopt)i(==)e(OPT)p 1419 4224 V 32 w(MR)m(G)p 1669 4224 V 34 w(COPY)g(then)g(infptr)g(con)m (tin)m(ues)i(to)g(exist)g(unaltered)e(after)i(the)227 4337 y(merge.)57 b(If)36 b(the)f(mgopt)i(==)e(OPT)p 1474 4337 V 31 w(MR)m(G)p 1723 4337 V 34 w(MO)m(V)i(then)e(infptr)f(is)i (deleted)h(after)f(the)g(merge.)57 b(In)35 b(b)s(oth)227 4450 y(cases,)d(the)e(GRPIDn)h(and)e(GRPLCn)h(k)m(eyw)m(ords)g(of)h (the)g(mem)m(b)s(er)e(HDUs)i(are)g(up)s(dated)e(accordingly)-8 b(.)95 4687 y Fe(int)47 b(fits_merge_groups)c(/)48 b(ffgtmg)286 4799 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(mgopt,)f(>) h(int)g(*status\))0 5036 y Fi(7)81 b Fj("Compact")24 b(the)f(group)g(de\014ned)f(b)m(y)h(grouping)f(table)i(p)s(oin)m(ted)f (to)h(b)m(y)f(gfptr.)38 b(The)22 b(compaction)j(is)e(ac)m(hiev)m(ed)227 5149 y(b)m(y)37 b(merging)h(\(via)g(\014ts)p 1034 5149 V 32 w(merge)p 1303 5149 V 34 w(groups\(\)\))f(all)h(direct)g(mem)m(b)s (er)f(HDUs)g(of)h(gfptr)e(that)i(are)g(themselv)m(es)227 5262 y(grouping)i(tables.)70 b(The)40 b(cmopt)g(parameter)h(de\014nes)e (whether)g(the)i(merged)f(grouping)f(table)i(HDUs)227 5375 y(remain)j(after)h(merging)f(\(cmopt)h(==)f(OPT)p 1852 5375 V 32 w(CMT)p 2099 5375 V 32 w(MBR\))h(or)f(if)g(they)h(are)f (deleted)h(after)g(merging)227 5488 y(\(cmopt)31 b(==)f(OPT)p 916 5488 V 32 w(CMT)p 1163 5488 V 32 w(MBR)p 1409 5488 V 34 w(DEL\).)g(If)g(the)h(grouping)e(table)j(con)m(tains)f(no)f (direct)h(mem)m(b)s(er)e(HDUs)227 5601 y(that)i(are)f(themselv)m(es)h (grouping)e(tables)i(then)e(this)h(function)f(do)s(es)h(nothing.)40 b(Note)31 b(that)g(this)e(function)227 5714 y(is)i(not)f(recursiv)m(e,) h(i.e.,)h(only)f(the)f(direct)h(mem)m(b)s(er)f(HDUs)h(of)f(gfptr)g(are) h(considered)f(for)g(merging.)p eop end %%Page: 94 102 TeXDict begin 94 101 bop 0 299 a Fj(94)1338 b Fh(CHAPTER)29 b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)95 555 y Fe(int)47 b(fits_compact_group)c(/)48 b(ffgtcm)286 668 y(\(fitsfile)e(*gfptr,)f(int)i(cmopt,)f(>)i(int)f(*status\))0 900 y Fi(8)81 b Fj(V)-8 b(erify)21 b(the)h(in)m(tegrit)m(y)h(of)e(the)g (grouping)g(table)h(p)s(oin)m(ted)f(to)h(b)m(y)f(gfptr)g(to)h(mak)m(e)g (sure)e(that)i(all)g(group)f(mem)m(b)s(ers)227 1013 y(are)31 b(accessible)i(and)d(that)h(all)g(links)g(to)g(other)g(grouping)f (tables)i(are)f(v)-5 b(alid.)42 b(The)30 b(\014rstfailed)g(parameter) 227 1126 y(returns)c(the)i(mem)m(b)s(er)e(ID)h(\(ro)m(w)h(n)m(um)m(b)s (er\))e(of)i(the)f(\014rst)f(mem)m(b)s(er)h(HDU)h(to)g(fail)g(v)m (eri\014cation)g(\(if)g(p)s(ositiv)m(e)227 1239 y(v)-5 b(alue\))36 b(or)e(the)h(\014rst)e(group)h(link)g(to)i(fail)f(\(if)f (negativ)m(e)j(v)-5 b(alue\).)54 b(If)34 b(gfptr)g(is)g(successfully)h (v)m(eri\014ed)f(then)227 1352 y(\014rstfailed)d(con)m(tains)g(a)g (return)e(v)-5 b(alue)31 b(of)g(0.)95 1584 y Fe(int)47 b(fits_verify_group)c(/)48 b(ffgtvf)286 1697 y(\(fitsfile)e(*gfptr,)f (>)j(long)f(*firstfailed,)d(int)j(*status\))0 1929 y Fi(9)81 b Fj(Op)s(en)23 b(a)j(grouping)f(table)h(that)g(con)m(tains)g (the)g(mem)m(b)s(er)e(HDU)i(p)s(oin)m(ted)f(to)h(b)m(y)f(mfptr.)38 b(The)25 b(grouping)g(table)227 2042 y(to)39 b(op)s(en)e(is)h (de\014ned)f(b)m(y)h(the)g(grpid)f(parameter,)j(whic)m(h)e(con)m(tains) h(the)f(k)m(eyw)m(ord)h(index)e(v)-5 b(alue)39 b(of)f(the)227 2155 y(GRPIDn/GRPLCn)d(k)m(eyw)m(ord\(s\))g(that)h(link)f(the)g(mem)m (b)s(er)f(HDU)h(mfptr)f(to)i(the)f(grouping)f(table.)55 b(If)227 2268 y(the)30 b(grouping)f(table)h(resides)f(in)h(a)f(\014le)h (other)f(than)h(the)f(mem)m(b)s(er)g(HDUs)h(\014le)f(then)g(an)h (attempt)g(is)g(\014rst)227 2381 y(made)f(to)h(op)s(en)e(the)h(\014le)g (readwrite,)h(and)e(failing)i(that)g(readonly)-8 b(.)40 b(A)29 b(p)s(oin)m(ter)g(to)h(the)f(op)s(ened)f(grouping)227 2494 y(table)k(HDU)f(is)f(returned)f(in)h(gfptr.)227 2639 y(Note)35 b(that)g(it)f(is)g(p)s(ossible,)g(although)h(unlik)m (ely)f(and)f(undesirable,)h(for)g(the)g(GRPIDn/GRPLCn)f(k)m(ey-)227 2752 y(w)m(ords)k(in)g(a)g(mem)m(b)s(er)g(HDU)h(header)f(to)h(b)s(e)e (non-con)m(tin)m(uous,)k(e.g.,)g(GRPID1,)g(GRPID2,)g(GRPID5,)227 2865 y(GRPID6.)i(In)29 b(suc)m(h)g(cases,)i(the)f(grpid)f(index)g(v)-5 b(alue)31 b(sp)s(eci\014ed)e(in)g(the)h(function)f(call)j(shall)e(iden) m(tify)g(the)227 2978 y(\(grpid\)th)36 b(GRPID)f(v)-5 b(alue.)57 b(In)34 b(the)i(ab)s(o)m(v)m(e)h(example,)g(if)f(grpid)e(==) h(3,)j(then)d(the)g(group)g(sp)s(eci\014ed)g(b)m(y)227 3091 y(GRPID5)c(w)m(ould)g(b)s(e)e(op)s(ened.)95 3323 y Fe(int)47 b(fits_open_group)d(/)j(ffgtop)286 3436 y(\(fitsfile)f (*mfptr,)f(int)i(grpid,)f(>)i(fitsfile)d(**gfptr,)h(int)h(*status\))0 3668 y Fi(10)f Fj(Add)38 b(a)h(mem)m(b)s(er)f(HDU)i(to)f(an)g(existing) g(grouping)g(table)h(p)s(oin)m(ted)e(to)i(b)m(y)e(gfptr.)66 b(The)38 b(mem)m(b)s(er)g(HDU)227 3781 y(ma)m(y)30 b(either)g(b)s(e)f (p)s(oin)m(ted)g(to)h(mfptr)f(\(whic)m(h)g(m)m(ust)h(b)s(e)e(p)s (ositioned)i(to)g(the)f(mem)m(b)s(er)g(HDU\))i(or,)f(if)f(mfptr)227 3894 y(==)36 b(NULL,)g(iden)m(ti\014ed)g(b)m(y)g(the)g(hdup)s(os)e (parameter)i(\(the)h(HDU)g(p)s(osition)f(n)m(um)m(b)s(er,)g(Primary)f (arra)m(y)227 4007 y(==)f(1\))i(if)f(b)s(oth)f(the)h(grouping)g(table)g (and)g(the)g(mem)m(b)s(er)f(HDU)h(reside)g(in)g(the)g(same)g(FITS)f (\014le.)54 b(The)227 4120 y(new)27 b(mem)m(b)s(er)f(HDU)h(shall)g(ha)m (v)m(e)h(the)f(appropriate)g(GRPIDn)f(and)g(GRPLCn)g(k)m(eyw)m(ords)h (created)h(in)f(its)227 4233 y(header.)44 b(Note)33 b(that)f(if)g(the)g (mem)m(b)s(er)e(HDU)j(is)e(already)h(a)g(mem)m(b)s(er)f(of)h(the)g (group)f(then)g(it)h(will)g(not)g(b)s(e)227 4346 y(added)e(a)h(second)f (time.)95 4578 y Fe(int)47 b(fits_add_group_member)42 b(/)48 b(ffgtam)286 4691 y(\(fitsfile)e(*gfptr,)f(fitsfile)h(*mfptr,)g (int)h(hdupos,)f(>)h(int)g(*status\))0 5020 y Ff(8.2)135 b(Group)45 b(Mem)l(b)t(er)f(Routines)0 5256 y Fi(1)81 b Fj(Return)28 b(the)i(n)m(um)m(b)s(er)e(of)h(mem)m(b)s(er)g(HDUs)h(in) f(a)h(grouping)f(table)h(gfptr.)40 b(The)29 b(n)m(um)m(b)s(er)f(of)i (mem)m(b)s(er)e(HDUs)227 5369 y(is)j(just)e(the)i(NAXIS2)g(v)-5 b(alue)31 b(\(n)m(um)m(b)s(er)e(of)h(ro)m(ws\))h(of)g(the)f(grouping)g (table.)95 5601 y Fe(int)47 b(fits_get_num_members)c(/)k(ffgtnm)286 5714 y(\(fitsfile)f(*gfptr,)f(>)j(long)f(*nmembers,)e(int)h(*status\))p eop end %%Page: 95 103 TeXDict begin 95 102 bop 0 299 a Fh(8.2.)72 b(GR)m(OUP)31 b(MEMBER)g(R)m(OUTINES)2295 b Fj(95)0 555 y Fi(2)81 b Fj(Return)34 b(the)h(n)m(um)m(b)s(er)f(of)i(groups)e(to)i(whic)m(h)f (the)g(HDU)h(p)s(oin)m(ted)f(to)h(b)m(y)f(mfptr)f(is)i(link)m(ed,)h(as) e(de\014ned)f(b)m(y)227 668 y(the)27 b(n)m(um)m(b)s(er)f(of)h (GRPIDn/GRPLCn)f(k)m(eyw)m(ord)i(records)e(that)i(app)s(ear)e(in)g(its) i(header.)39 b(Note)28 b(that)g(eac)m(h)227 781 y(time)37 b(this)g(function)f(is)g(called,)k(the)c(indices)h(of)g(the)f (GRPIDn/GRPLCn)g(k)m(eyw)m(ords)h(are)g(c)m(hec)m(k)m(ed)h(to)227 894 y(mak)m(e)29 b(sure)e(they)g(are)h(con)m(tin)m(uous)g(\(ie)h(no)e (gaps\))h(and)f(are)h(re-en)m(umerated)g(to)h(eliminate)g(gaps)f(if)f (found.)95 1228 y Fe(int)47 b(fits_get_num_groups)c(/)k(ffgmng)286 1341 y(\(fitsfile)f(*mfptr,)f(>)j(long)f(*nmembers,)e(int)h(*status\))0 1563 y Fi(3)81 b Fj(Op)s(en)26 b(a)i(mem)m(b)s(er)f(of)h(the)f (grouping)h(table)g(p)s(oin)m(ted)g(to)g(b)m(y)g(gfptr.)39 b(The)27 b(mem)m(b)s(er)g(to)i(op)s(en)e(is)g(iden)m(ti\014ed)h(b)m(y) 227 1676 y(its)i(ro)m(w)g(n)m(um)m(b)s(er)e(within)h(the)g(grouping)h (table)g(as)g(giv)m(en)g(b)m(y)g(the)f(parameter)h('mem)m(b)s(er')f (\(\014rst)h(mem)m(b)s(er)227 1788 y(==)g(1\))g(.)41 b(A)30 b(\014ts\014le)f(p)s(oin)m(ter)h(to)h(the)f(op)s(ened)f(mem)m(b) s(er)g(HDU)i(is)f(returned)f(as)h(mfptr.)39 b(Note)31 b(that)g(if)f(the)227 1901 y(mem)m(b)s(er)e(HDU)h(resides)g(in)f(a)h (FITS)f(\014le)g(di\013eren)m(t)h(from)f(the)h(grouping)f(table)h(HDU)h (then)e(the)h(mem)m(b)s(er)227 2014 y(\014le)i(is)f(\014rst)g(op)s (ened)f(readwrite)i(and,)f(failing)h(this,)g(op)s(ened)e(readonly)-8 b(.)95 2236 y Fe(int)47 b(fits_open_member)d(/)j(ffgmop)286 2349 y(\(fitsfile)f(*gfptr,)f(long)i(member,)f(>)h(fitsfile)f(**mfptr,) f(int)i(*status\))0 2570 y Fi(4)81 b Fj(Cop)m(y)27 b(\(app)s(end\))f(a) i(mem)m(b)s(er)f(HDU)h(of)f(the)h(grouping)e(table)j(p)s(oin)m(ted)e (to)h(b)m(y)f(gfptr.)39 b(The)27 b(mem)m(b)s(er)g(HDU)h(is)227 2683 y(iden)m(ti\014ed)33 b(b)m(y)g(its)h(ro)m(w)f(n)m(um)m(b)s(er)e (within)i(the)g(grouping)g(table)g(as)h(giv)m(en)g(b)m(y)e(the)i (parameter)f('mem)m(b)s(er')227 2796 y(\(\014rst)j(mem)m(b)s(er)f(==)g (1\).)58 b(The)35 b(cop)m(y)i(of)f(the)g(group)f(mem)m(b)s(er)g(HDU)i (will)f(b)s(e)f(app)s(ended)f(to)j(the)f(FITS)227 2909 y(\014le)29 b(p)s(oin)m(ted)g(to)g(b)m(y)f(mfptr,)h(and)f(up)s(on)f (return)g(mfptr)h(shall)h(p)s(oin)m(t)f(to)i(the)f(copied)g(mem)m(b)s (er)f(HDU.)h(The)227 3022 y(cp)s(opt)e(parameter)h(ma)m(y)g(tak)m(e)h (on)e(the)g(follo)m(wing)i(v)-5 b(alues:)40 b(OPT)p 2465 3022 28 4 v 32 w(MCP)p 2708 3022 V 32 w(ADD)29 b(whic)m(h)e(adds)f(a)i (new)f(en)m(try)227 3135 y(in)d(gfptr)g(for)f(the)i(copied)f(mem)m(b)s (er)g(HDU,)h(OPT)p 1907 3135 V 31 w(MCP)p 2149 3135 V 33 w(NADD)g(whic)m(h)f(do)s(es)g(not)g(add)f(an)h(en)m(try)h(in)e (gfptr)227 3247 y(for)i(the)h(copied)f(mem)m(b)s(er,)h(and)f(OPT)p 1536 3247 V 32 w(MCP)p 1779 3247 V 32 w(REPL)g(whic)m(h)g(replaces)h (the)f(original)h(mem)m(b)s(er)f(en)m(try)g(with)227 3360 y(the)31 b(copied)g(mem)m(b)s(er)e(en)m(try)-8 b(.)95 3582 y Fe(int)47 b(fits_copy_member)d(/)j(ffgmcp)286 3695 y(\(fitsfile)f(*gfptr,)f(fitsfile)h(*mfptr,)g(long)g(member,)g (int)h(cpopt,)f(>)i(int)f(*status\))0 3916 y Fi(5)81 b Fj(T)-8 b(ransfer)34 b(a)i(group)f(mem)m(b)s(er)f(HDU)i(from)f(the)h (grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)f(infptr)g(to)h(the)f (grouping)227 4029 y(table)i(p)s(oin)m(ted)f(to)h(b)m(y)f(outfptr.)58 b(The)35 b(mem)m(b)s(er)h(HDU)h(to)f(transfer)g(is)g(iden)m(ti\014ed)g (b)m(y)g(its)h(ro)m(w)f(n)m(um)m(b)s(er)227 4142 y(within)42 b(infptr)f(as)i(sp)s(eci\014ed)f(b)m(y)g(the)h(parameter)g('mem)m(b)s (er')f(\(\014rst)g(mem)m(b)s(er)g(==)f(1\).)78 b(If)42 b(tfopt)h(==)227 4255 y(OPT)p 431 4255 V 32 w(MCP)p 674 4255 V 33 w(ADD)26 b(then)f(the)h(mem)m(b)s(er)e(HDU)i(is)g(made)f(a)h (mem)m(b)s(er)f(of)g(outfptr)g(and)g(remains)g(a)h(mem)m(b)s(er)227 4368 y(of)34 b(infptr.)51 b(If)34 b(tfopt)g(==)g(OPT)p 1339 4368 V 32 w(MCP)p 1582 4368 V 32 w(MO)m(V)h(then)f(the)g(mem)m(b)s (er)f(HDU)i(is)f(deleted)h(from)e(infptr)g(after)227 4481 y(the)e(transfer)f(to)h(outfptr.)95 4702 y Fe(int)47 b(fits_transfer_member)c(/)k(ffgmtf)286 4815 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(long)i(member,)e(int)i(tfopt,)334 4928 y(>)h(int)e(*status\))0 5149 y Fi(6)81 b Fj(Remo)m(v)m(e)31 b(a)e(mem)m(b)s(er)g(HDU)h(from)f(the)h(grouping)f(table)h(p)s(oin)m (ted)f(to)h(b)m(y)g(gfptr.)40 b(The)29 b(mem)m(b)s(er)f(HDU)i(to)h(b)s (e)227 5262 y(deleted)37 b(is)e(iden)m(ti\014ed)h(b)m(y)f(its)h(ro)m(w) g(n)m(um)m(b)s(er)f(in)g(the)h(grouping)f(table)h(as)g(sp)s(eci\014ed)f (b)m(y)h(the)f(parameter)227 5375 y('mem)m(b)s(er')41 b(\(\014rst)g(mem)m(b)s(er)g(==)f(1\).)74 b(The)41 b(rmopt)g(parameter) h(ma)m(y)f(tak)m(e)i(on)e(the)h(follo)m(wing)g(v)-5 b(alues:)227 5488 y(OPT)p 431 5488 V 32 w(RM)p 613 5488 V 33 w(ENTR)d(Y)34 b(whic)m(h)e(remo)m(v)m(es)j(the)e(mem)m(b)s(er)g(HDU)h(en)m(try)f (from)g(the)g(grouping)g(table)h(and)f(up-)227 5601 y(dates)40 b(the)f(mem)m(b)s(er's)f(GRPIDn/GRPLCn)g(k)m(eyw)m(ords,)k(and)c(OPT)p 2687 5601 V 32 w(RM)p 2869 5601 V 33 w(MBR)h(whic)m(h)g(remo)m(v)m(es)h (the)227 5714 y(mem)m(b)s(er)30 b(HDU)h(en)m(try)g(from)f(the)g (grouping)g(table)i(and)d(deletes)j(the)e(mem)m(b)s(er)g(HDU)h(itself.) p eop end %%Page: 96 104 TeXDict begin 96 103 bop 0 299 a Fj(96)1338 b Fh(CHAPTER)29 b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)95 555 y Fe(int)47 b(fits_remove_member)c(/)48 b(ffgmrm)286 668 y(\(fitsfile)e(*gfptr,)f(long)i(member,)f(int)h(rmopt,)f(>)h(int)g (*status\))p eop end %%Page: 97 105 TeXDict begin 97 104 bop 0 1225 a Fg(Chapter)65 b(9)0 1687 y Fm(Sp)6 b(ecialized)77 b(CFITSIO)f(In)-6 b(terface)0 1937 y(Routines)0 2429 y Fj(The)28 b(basic)h(in)m(terface)i(routines)e (describ)s(ed)e(previously)i(are)g(recommended)f(for)h(most)g(uses,)g (but)f(the)h(routines)0 2542 y(describ)s(ed)h(in)g(this)h(c)m(hapter)g (are)h(also)f(a)m(v)-5 b(ailable)34 b(if)c(necessary)-8 b(.)43 b(Some)31 b(of)g(these)g(routines)g(p)s(erform)e(more)i(sp)s(e-) 0 2655 y(cialized)e(function)d(that)i(cannot)f(easily)h(b)s(e)e(done)h (with)f(the)h(basic)h(in)m(terface)g(routines)f(while)f(others)h (duplicate)0 2767 y(the)j(functionalit)m(y)i(of)e(the)g(basic)h (routines)f(but)f(ha)m(v)m(e)i(a)g(sligh)m(tly)g(di\013eren)m(t)g (calling)g(sequence.)41 b(See)31 b(App)s(endix)0 2880 y(B)g(for)f(the)g(de\014nition)g(of)h(eac)m(h)h(function)e(parameter.)0 3279 y Ff(9.1)135 b(FITS)44 b(File)i(Access)e(Routines)0 3545 y Fd(9.1.1)112 b(File)39 b(Access)0 3794 y Fi(1)81 b Fj(Op)s(en)37 b(an)i(existing)i(FITS)d(\014le)h(residing)g(in)g(core) h(computer)f(memory)-8 b(.)68 b(This)38 b(routine)h(is)h(analogous)g (to)227 3907 y(\014ts)p 354 3907 28 4 v 33 w(op)s(en)p 577 3907 V 32 w(\014le.)55 b(The)35 b('\014lename')g(is)g(curren)m(tly) h(ignored)f(b)m(y)g(this)g(routine)g(and)g(ma)m(y)g(b)s(e)g(an)m(y)g (arbitrary)227 4020 y(string.)78 b(In)42 b(general,)47 b(the)c(application)h(m)m(ust)f(ha)m(v)m(e)h(preallo)s(cated)g(an)e (initial)i(blo)s(c)m(k)g(of)f(memory)f(to)227 4133 y(hold)i(the)h(FITS) f(\014le)h(prior)f(to)h(calling)h(this)e(routine:)70 b('memptr')44 b(p)s(oin)m(ts)g(to)i(the)e(starting)i(address)227 4246 y(and)39 b('memsize')i(giv)m(es)g(the)f(initial)h(size)f(of)g(the) g(blo)s(c)m(k)g(of)g(memory)-8 b(.)69 b('mem)p 2958 4246 V 33 w(reallo)s(c')41 b(is)f(a)g(p)s(oin)m(ter)f(to)227 4359 y(an)c(optional)i(function)d(that)i(CFITSIO)e(can)h(call)h(to)g (allo)s(cate)i(additional)e(memory)-8 b(,)37 b(if)e(needed)f(\(only)227 4472 y(if)41 b(mo)s(de)e(=)h(READ)m(WRITE\),)i(and)e(is)g(mo)s(deled)g (after)h(the)f(standard)g(C)g('reallo)s(c')i(function;)j(a)c(n)m(ull) 227 4585 y(p)s(oin)m(ter)g(ma)m(y)g(b)s(e)f(giv)m(en)i(if)e(the)h (initial)h(allo)s(cation)h(of)e(memory)f(is)h(all)g(that)g(will)g(b)s (e)f(required)g(\(e.g.,)227 4698 y(if)35 b(the)g(\014le)g(is)g(op)s (ened)f(with)h(mo)s(de)f(=)h(READONL)-8 b(Y\).)36 b(The)e('deltasize')j (parameter)e(ma)m(y)h(b)s(e)e(used)g(to)227 4811 y(suggest)g(a)f(minim) m(um)f(amoun)m(t)h(of)g(additional)h(memory)f(that)g(should)f(b)s(e)g (allo)s(cated)j(during)d(eac)m(h)i(call)227 4924 y(to)d(the)f(memory)f (reallo)s(cation)j(function.)40 b(By)30 b(default,)g(CFITSIO)e(will)i (reallo)s(cate)j(enough)c(additional)227 5036 y(space)44 b(to)g(hold)f(the)h(en)m(tire)g(curren)m(tly)f(de\014ned)g(FITS)f (\014le)i(\(as)f(giv)m(en)i(b)m(y)e(the)h(NAXISn)e(k)m(eyw)m(ords\))227 5149 y(or)g(1)f(FITS)g(blo)s(c)m(k)h(\(=)f(2880)i(b)m(ytes\),)i(whic)m (h)d(ev)m(er)g(is)f(larger.)74 b(V)-8 b(alues)43 b(of)e(deltasize)i (less)f(than)f(2880)227 5262 y(will)31 b(b)s(e)f(ignored.)42 b(Since)31 b(the)g(memory)g(reallo)s(cation)i(op)s(eration)e(can)g(b)s (e)f(computationally)i(exp)s(ensiv)m(e,)227 5375 y(allo)s(cating)27 b(a)e(larger)g(initial)h(blo)s(c)m(k)f(of)g(memory)-8 b(,)26 b(and/or)f(sp)s(ecifying)f(a)h(larger)h(deltasize)g(v)-5 b(alue)25 b(ma)m(y)g(help)227 5488 y(to)i(reduce)f(the)g(n)m(um)m(b)s (er)e(of)i(reallo)s(cation)i(calls)f(and)f(mak)m(e)h(the)f(application) h(program)f(run)e(faster.)40 b(Note)227 5601 y(that)29 b(v)-5 b(alues)29 b(of)f(the)h(memptr)f(and)f(memsize)j(p)s(oin)m(ters) e(will)h(b)s(e)e(up)s(dated)g(b)m(y)i(CFITSIO)d(if)j(the)f(lo)s(cation) 227 5714 y(or)j(size)g(of)f(the)h(FITS)f(\014le)g(in)g(memory)g(should) g(c)m(hange)h(as)g(a)g(result)f(of)g(allo)s(cating)j(more)e(memory)-8 b(.)1905 5942 y(97)p eop end %%Page: 98 106 TeXDict begin 98 105 bop 0 299 a Fj(98)1003 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_open_memfile)c(/)48 b(ffomem)286 668 y(\(fitsfile)e(**fptr,)f(const)i(char)f(*filename,)f (int)i(mode,)g(void)f(**memptr,)334 781 y(size_t)g(*memsize,)f(size_t)i (deltasize,)334 894 y(void)g(*\(*mem_realloc\)\(void)42 b(*p,)47 b(size_t)f(newsize\),)f(int)i(*status\))0 1147 y Fi(2)81 b Fj(Create)49 b(a)g(new)f(FITS)g(\014le)h(residing)f(in)h (core)g(computer)g(memory)-8 b(.)96 b(This)48 b(routine)g(is)h (analogous)h(to)227 1260 y(\014ts)p 354 1260 28 4 v 33 w(create)p 623 1260 V 34 w(\014le.)40 b(In)29 b(general,)i(the)e (application)h(m)m(ust)f(ha)m(v)m(e)i(preallo)s(cated)g(an)e(initial)h (blo)s(c)m(k)g(of)f(memory)227 1373 y(to)38 b(hold)e(the)h(FITS)f (\014le)h(prior)f(to)h(calling)i(this)d(routine:)54 b('memptr')36 b(p)s(oin)m(ts)h(to)g(the)g(starting)h(address)227 1486 y(and)h('memsize')i(giv)m(es)g(the)f(initial)h(size)f(of)g(the)g(blo)s (c)m(k)g(of)g(memory)-8 b(.)69 b('mem)p 2958 1486 V 33 w(reallo)s(c')41 b(is)f(a)g(p)s(oin)m(ter)f(to)227 1599 y(an)f(optional)g(function)f(that)h(CFITSIO)e(can)i(call)h(to)f(allo)s (cate)i(additional)e(memory)-8 b(,)40 b(if)d(needed,)j(and)227 1712 y(is)34 b(mo)s(deled)f(after)h(the)g(standard)f(C)g('reallo)s(c')i (function;)g(a)f(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)g(b)s(e)f(giv)m(en)h (if)g(the)g(initial)227 1824 y(allo)s(cation)i(of)d(memory)g(is)h(all)g (that)g(will)f(b)s(e)g(required.)48 b(The)33 b('deltasize')j(parameter) d(ma)m(y)h(b)s(e)f(used)f(to)227 1937 y(suggest)i(a)f(minim)m(um)f (amoun)m(t)h(of)g(additional)h(memory)f(that)g(should)f(b)s(e)g(allo)s (cated)j(during)d(eac)m(h)i(call)227 2050 y(to)d(the)f(memory)f(reallo) s(cation)j(function.)40 b(By)30 b(default,)g(CFITSIO)e(will)i(reallo)s (cate)j(enough)c(additional)227 2163 y(space)41 b(to)g(hold)e(1)i(FITS) e(blo)s(c)m(k)h(\(=)g(2880)i(b)m(ytes\))f(and)e(v)-5 b(alues)41 b(of)f(deltasize)h(less)g(than)f(2880)h(will)g(b)s(e)227 2276 y(ignored.)f(Since)28 b(the)f(memory)h(reallo)s(cation)i(op)s (eration)e(can)g(b)s(e)f(computationally)i(exp)s(ensiv)m(e,)g(allo)s (cat-)227 2389 y(ing)36 b(a)f(larger)h(initial)h(blo)s(c)m(k)e(of)h (memory)-8 b(,)37 b(and/or)e(sp)s(ecifying)g(a)h(larger)g(deltasize)h (v)-5 b(alue)36 b(ma)m(y)f(help)g(to)227 2502 y(reduce)f(the)g(n)m(um)m (b)s(er)e(of)i(reallo)s(cation)i(calls)f(and)e(mak)m(e)i(the)f (application)h(program)f(run)e(faster.)52 b(Note)227 2615 y(that)29 b(v)-5 b(alues)29 b(of)f(the)h(memptr)f(and)f(memsize)j (p)s(oin)m(ters)e(will)h(b)s(e)e(up)s(dated)g(b)m(y)i(CFITSIO)d(if)j (the)f(lo)s(cation)227 2728 y(or)j(size)g(of)f(the)h(FITS)f(\014le)g (in)g(memory)g(should)g(c)m(hange)h(as)g(a)g(result)f(of)g(allo)s (cating)j(more)e(memory)-8 b(.)95 2981 y Fe(int)47 b (fits_create_memfile)c(/)k(ffimem)286 3094 y(\(fitsfile)f(**fptr,)f (void)i(**memptr,)334 3207 y(size_t)f(*memsize,)f(size_t)i(deltasize,) 334 3320 y(void)g(*\(*mem_realloc\)\(void)42 b(*p,)47 b(size_t)f(newsize\),)f(int)i(*status\))0 3573 y Fi(3)81 b Fj(Reop)s(en)34 b(a)i(FITS)e(\014le)h(that)h(w)m(as)f(previously)g (op)s(ened)g(with)f(\014ts)p 2414 3573 V 33 w(op)s(en)p 2637 3573 V 32 w(\014le)h(or)g(\014ts)p 3058 3573 V 33 w(create)p 3327 3573 V 34 w(\014le.)55 b(The)34 b(new)227 3685 y(\014ts\014le)i(p)s(oin)m(ter)h(ma)m(y)g(then)f(b)s(e)f(treated)j (as)e(a)h(separate)g(\014le,)h(and)e(one)h(ma)m(y)g(sim)m(ultaneously)g (read)f(or)227 3798 y(write)e(to)h(2)f(\(or)g(more\))g(di\013eren)m(t)g (extensions)g(in)g(the)g(same)g(\014le.)51 b(The)33 b(\014ts)p 2886 3798 V 32 w(op)s(en)p 3108 3798 V 32 w(\014le)h(routine)g(\(ab)s (o)m(v)m(e\))227 3911 y(automatically)k(detects)f(cases)f(where)e(a)i (previously)f(op)s(ened)f(\014le)i(is)f(b)s(eing)g(op)s(ened)f(again,)k (and)c(then)227 4024 y(in)m(ternally)e(call)f(\014ts)p 930 4024 V 33 w(reop)s(en)p 1229 4024 V 32 w(\014le,)g(so)f(programs)g (should)g(rarely)g(need)g(to)h(explicitly)h(call)g(this)e(routine.)95 4277 y Fe(int)47 b(fits_reopen_file)d(/)j(ffreopen)286 4390 y(\(fitsfile)f(*openfptr,)f(fitsfile)g(**newfptr,)g(>)j(int)f (*status\))0 4643 y Fi(4)81 b Fj(Create)24 b(a)g(new)f(FITS)g(\014le,)i (using)e(a)h(template)h(\014le)e(to)i(de\014ne)d(its)i(initial)h(size)g (and)e(structure.)37 b(The)24 b(template)227 4756 y(ma)m(y)i(b)s(e)f (another)g(FITS)g(HDU)h(or)f(an)g(ASCI)s(I)f(template)j(\014le.)39 b(If)25 b(the)g(input)g(template)h(\014le)g(name)f(p)s(oin)m(ter)227 4869 y(is)j(n)m(ull,)h(then)e(this)h(routine)f(b)s(eha)m(v)m(es)i(the)f (same)g(as)g(\014ts)p 2160 4869 V 32 w(create)p 2428 4869 V 35 w(\014le.)40 b(The)27 b(curren)m(tly)h(supp)s(orted)e(format) 227 4982 y(of)33 b(the)g(ASCI)s(I)e(template)j(\014le)e(is)h(describ)s (ed)e(under)g(the)i(\014ts)p 2350 4982 V 33 w(parse)p 2591 4982 V 32 w(template)h(routine)f(\(in)f(the)h(general)227 5095 y(Utilities)g(section\))95 5348 y Fe(int)47 b (fits_create_template)c(/)k(fftplt)286 5461 y(\(fitsfile)f(**fptr,)f (char)i(*filename,)e(char)i(*tpltfile)e(>)i(int)g(*status\))0 5714 y Fi(5)81 b Fj(P)m(arse)31 b(the)f(input)g(\014lename)g(or)g(URL)h (in)m(to)g(its)g(comp)s(onen)m(t)f(parts,)h(namely:)p eop end %%Page: 99 107 TeXDict begin 99 106 bop 0 299 a Fh(9.1.)72 b(FITS)30 b(FILE)g(A)m(CCESS)f(R)m(OUTINES)2244 b Fj(99)336 555 y Fc(\017)46 b Fj(the)31 b(\014le)f(t)m(yp)s(e)h(\(\014le://,)h (ftp://,)f(h)m(ttp://,)h(etc\),)336 700 y Fc(\017)46 b Fj(the)31 b(base)f(input)g(\014le)g(name,)336 845 y Fc(\017)46 b Fj(the)31 b(name)f(of)h(the)f(output)g(\014le)h(that)g (the)f(input)g(\014le)g(is)h(to)g(b)s(e)e(copied)i(to)g(prior)f(to)h (op)s(ening,)336 990 y Fc(\017)46 b Fj(the)31 b(HDU)g(or)f(extension)h (sp)s(eci\014cation,)336 1134 y Fc(\017)46 b Fj(the)31 b(\014ltering)f(sp)s(eci\014er,)336 1279 y Fc(\017)46 b Fj(the)31 b(binning)e(sp)s(eci\014er,)336 1424 y Fc(\017)46 b Fj(the)31 b(column)f(sp)s(eci\014er,)336 1569 y Fc(\017)46 b Fj(and)30 b(the)h(image)g(pixel)g(\014ltering)g(sp)s(eci\014er.)227 1755 y(A)k(n)m(ull)g(p)s(oin)m(ter)f(\(0\))i(ma)m(y)g(b)s(e)e(b)s(e)g (sp)s(eci\014ed)g(for)g(an)m(y)h(of)g(the)g(output)g(string)f(argumen)m (ts)h(that)h(are)f(not)227 1868 y(needed.)52 b(Null)34 b(strings)g(will)g(b)s(e)g(returned)f(for)h(an)m(y)g(comp)s(onen)m(ts)g (that)h(are)f(not)h(presen)m(t)f(in)g(the)g(input)227 1981 y(\014le)28 b(name.)39 b(The)27 b(calling)i(routine)e(m)m(ust)g (allo)s(cate)j(su\016cien)m(t)d(memory)g(to)h(hold)f(the)g(returned)f (c)m(haracter)227 2094 y(strings.)52 b(Allo)s(cating)37 b(the)d(string)g(lengths)h(equal)g(to)g(FLEN)p 2362 2094 28 4 v 33 w(FILENAME)f(is)g(guaran)m(teed)i(to)f(b)s(e)e(safe.)227 2207 y(These)d(routines)h(are)f(mainly)h(for)f(in)m(ternal)h(use)f(b)m (y)h(other)f(CFITSIO)f(routines.)95 2462 y Fe(int)47 b(fits_parse_input_url)c(/)k(ffiurl)286 2575 y(\(char)g(*filename,)e(>) i(char)g(*filetype,)e(char)h(*infile,)g(char)h(*outfile,)e(char)334 2688 y(*extspec,)g(char)i(*filter,)f(char)g(*binspec,)f(char)i (*colspec,)e(int)i(*status\))95 2914 y(int)g(fits_parse_input_filename) 41 b(/)48 b(ffifile)286 3027 y(\(char)f(*filename,)e(>)i(char)g (*filetype,)e(char)h(*infile,)g(char)h(*outfile,)e(char)334 3140 y(*extspec,)g(char)i(*filter,)f(char)g(*binspec,)f(char)i (*colspec,)e(char)i(*pixspec,)334 3253 y(int)g(*status\))0 3509 y Fi(6)81 b Fj(P)m(arse)33 b(the)f(input)g(\014lename)h(and)e (return)h(the)h(HDU)g(n)m(um)m(b)s(er)e(that)i(w)m(ould)f(b)s(e)g(mo)m (v)m(ed)i(to)f(if)f(the)h(\014le)f(w)m(ere)227 3622 y(op)s(ened)h(with) g(\014ts)p 878 3622 V 32 w(op)s(en)p 1100 3622 V 32 w(\014le.)49 b(The)33 b(returned)f(HDU)i(n)m(um)m(b)s(er)e(b)s(egins)h(with)g(1)g (for)g(the)g(primary)g(arra)m(y)-8 b(,)227 3734 y(so)40 b(for)f(example,)k(if)c(the)h(input)e(\014lename)i(=)f(`m)m (y\014le.\014ts[2]')i(then)e(hdun)m(um)e(=)i(3)h(will)g(b)s(e)f (returned.)227 3847 y(CFITSIO)j(do)s(es)i(not)g(op)s(en)f(the)g(\014le) h(to)h(c)m(hec)m(k)g(if)e(the)h(extension)h(actually)g(exists)f(if)g (an)f(extension)227 3960 y(n)m(um)m(b)s(er)e(is)i(sp)s(eci\014ed.)75 b(If)42 b(an)g(extension)h(name)f(is)h(included)e(in)h(the)h(\014le)f (name)g(sp)s(eci\014cation)h(\(e.g.)227 4073 y(`m)m (y\014le.\014ts[EVENTS]')i(then)e(this)h(routine)g(will)h(ha)m(v)m(e)g (to)f(op)s(en)g(the)g(FITS)f(\014le)h(and)f(lo)s(ok)i(for)f(the)227 4186 y(p)s(osition)31 b(of)f(the)h(named)f(extension,)i(then)e(close)i (\014le)e(again.)42 b(This)30 b(is)g(not)h(p)s(ossible)f(if)h(the)f (\014le)h(is)f(b)s(eing)227 4299 y(read)k(from)f(the)h(stdin)f(stream,) i(and)f(an)f(error)g(will)i(b)s(e)e(returned)f(in)i(this)f(case.)52 b(If)33 b(the)h(\014lename)g(do)s(es)227 4412 y(not)42 b(sp)s(ecify)g(an)g(explicit)h(extension)g(\(e.g.)76 b('m)m(y\014le.\014ts'\))43 b(then)f(hdun)m(um)e(=)h(-99)i(will)g(b)s (e)e(returned,)227 4525 y(whic)m(h)35 b(is)g(functionally)h(equiv)-5 b(alen)m(t)36 b(to)g(hdun)m(um)d(=)h(1.)55 b(This)34 b(routine)h(is)g(mainly)h(used)e(for)g(bac)m(kw)m(ard)227 4638 y(compatibilit)m(y)39 b(in)e(the)f(fto)s(ols)i(soft)m(w)m(are)g (pac)m(k)-5 b(age)39 b(and)d(is)g(not)h(recommended)g(for)f(general)i (use.)59 b(It)37 b(is)227 4751 y(generally)k(b)s(etter)e(and)g(more)g (e\016cien)m(t)i(to)f(\014rst)e(op)s(en)h(the)g(FITS)g(\014le)g(with)g (\014ts)p 3125 4751 V 32 w(op)s(en)p 3347 4751 V 33 w(\014le,)i(then)e (use)227 4864 y(\014ts)p 354 4864 V 33 w(get)p 507 4864 V 34 w(hdu)p 694 4864 V 31 w(n)m(um)c(to)i(determine)g(whic)m(h)f(HDU)h (in)f(the)h(\014le)f(has)g(b)s(een)g(op)s(ened,)h(rather)f(than)g (calling)227 4976 y(\014ts)p 354 4976 V 33 w(parse)p 595 4976 V 32 w(input)p 840 4976 V 32 w(url)30 b(follo)m(w)m(ed)i(b)m (y)e(a)h(call)g(to)h(\014ts)p 1967 4976 V 32 w(op)s(en)p 2189 4976 V 32 w(\014le.)143 5232 y Fe(int)47 b(fits_parse_extnum)c(/) 48 b(ffextn)334 5345 y(\(char)e(*filename,)f(>)j(int)f(*hdunum,)e(int)i (*status\))0 5601 y Fi(7)81 b Fj(P)m(arse)45 b(the)g(input)e(\014le)i (name)g(and)f(return)f(the)i(ro)s(ot)g(\014le)g(name.)83 b(The)44 b(ro)s(ot)h(name)g(includes)f(the)h(\014le)227 5714 y(t)m(yp)s(e)35 b(if)g(sp)s(eci\014ed,)h(\(e.g.)56 b('ftp://')37 b(or)e('h)m(ttp://'\))i(and)d(the)h(full)g(path)g(name,)h (to)g(the)f(exten)m(t)i(that)e(it)h(is)p eop end %%Page: 100 108 TeXDict begin 100 107 bop 0 299 a Fj(100)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(sp)s(eci\014ed)c(in)f(the)i(input)e (\014lename.)39 b(It)26 b(do)s(es)g(not)g(include)g(the)g(HDU)h(name)f (or)g(n)m(um)m(b)s(er,)g(or)g(an)m(y)h(\014ltering)227 668 y(sp)s(eci\014cations.)86 b(The)45 b(calling)h(routine)g(m)m(ust)f (allo)s(cate)i(su\016cien)m(t)f(memory)f(to)h(hold)f(the)g(returned)227 781 y(ro)s(otname)33 b(c)m(haracter)g(string.)46 b(Allo)s(cating)34 b(the)f(length)f(equal)h(to)f(FLEN)p 2817 781 28 4 v 33 w(FILENAME)h(is)f(guaran)m(teed)227 894 y(to)f(b)s(e)f(safe.)143 1119 y Fe(int)47 b(fits_parse_rootname)c(/)k(ffrtnm)334 1232 y(\(char)f(*filename,)f(>)j(char)f(*rootname,)e(int)h(*status\);)0 1457 y Fi(8)81 b Fj(T)-8 b(est)37 b(if)f(the)h(input)f(\014le)h(or)f(a) h(compressed)g(v)m(ersion)g(of)g(the)g(\014le)f(\(with)h(a)g(.gz,)j (.Z,)c(.z,)j(or)e(.zip)g(extension\))227 1570 y(exists)i(on)f(disk.)63 b(The)37 b(returned)g(v)-5 b(alue)38 b(of)g(the)h('exists')g(parameter) f(will)g(ha)m(v)m(e)i(1)e(of)g(the)g(4)g(follo)m(wing)227 1683 y(v)-5 b(alues:)370 1893 y Fe(2:)95 b(the)47 b(file)g(does)g(not)f (exist,)h(but)f(a)i(compressed)d(version)h(does)g(exist)370 2006 y(1:)95 b(the)47 b(disk)g(file)g(does)f(exist)370 2119 y(0:)95 b(neither)46 b(the)h(file)g(nor)g(a)g(compressed)e (version)h(of)h(the)g(file)g(exist)323 2232 y(-1:)94 b(the)47 b(input)g(file)f(name)h(is)g(not)g(a)g(disk)g(file)g(\(could)f (be)h(a)g(ftp,)g(http,)561 2344 y(smem,)g(or)g(mem)g(file,)f(or)h(a)h (file)e(piped)h(in)g(on)g(the)g(STDIN)f(stream\))143 2635 y(int)h(fits_file_exists)c(/)48 b(ffexist)334 2748 y(\(char)e(*filename,)f(>)j(int)f(*exists,)e(int)i(*status\);)0 2973 y Fi(9)81 b Fj(Flush)36 b(an)m(y)i(in)m(ternal)g(bu\013ers)e(of)i (data)g(to)g(the)f(output)g(FITS)g(\014le.)62 b(These)37 b(routines)g(rarely)g(need)g(to)i(b)s(e)227 3086 y(called,)i(but)36 b(can)i(b)s(e)f(useful)f(in)h(cases)i(where)d(other)i(pro)s(cesses)f (need)g(to)h(access)h(the)f(same)f(FITS)g(\014le)227 3199 y(in)j(real)i(time,)h(either)e(on)g(disk)f(or)g(in)g(memory)-8 b(.)71 b(These)41 b(routines)f(also)h(help)f(to)i(ensure)d(that)i(if)g (the)227 3312 y(application)c(program)d(subsequen)m(tly)h(ab)s(orts)f (then)h(the)g(FITS)f(\014le)h(will)g(ha)m(v)m(e)i(b)s(een)d(closed)h (prop)s(erly)-8 b(.)227 3425 y(The)43 b(\014rst)g(routine,)k(\014ts)p 1110 3425 V 33 w(\015ush)p 1332 3425 V 31 w(\014le)c(is)h(more)f (rigorous)h(and)f(completely)i(closes,)j(then)c(reop)s(ens,)i(the)227 3538 y(curren)m(t)31 b(HDU,)h(b)s(efore)e(\015ushing)g(the)h(in)m (ternal)g(bu\013ers,)f(th)m(us)h(ensuring)f(that)h(the)g(output)g(FITS) f(\014le)h(is)227 3650 y(iden)m(tical)38 b(to)e(what)f(w)m(ould)h(b)s (e)f(pro)s(duced)f(if)h(the)h(FITS)f(w)m(as)h(closed)g(at)g(that)g(p)s (oin)m(t)g(\(i.e.,)i(with)e(a)g(call)227 3763 y(to)g(\014ts)p 470 3763 V 33 w(close)p 689 3763 V 34 w(\014le\).)56 b(The)35 b(second)g(routine,)i(\014ts)p 1912 3763 V 33 w(\015ush)p 2134 3763 V 31 w(bu\013er)d(simply)h(\015ushes)f(the)h(in)m (ternal)h(CFITSIO)227 3876 y(bu\013ers)28 b(of)h(data)h(to)f(the)h (output)e(FITS)g(\014le,)i(without)f(up)s(dating)f(and)g(closing)i(the) f(curren)m(t)g(HDU.)h(This)227 3989 y(is)37 b(m)m(uc)m(h)g(faster,)i (but)e(there)g(ma)m(y)g(b)s(e)f(circumstances)i(where)e(the)h (\015ushed)f(\014le)h(do)s(es)f(not)h(completely)227 4102 y(re\015ect)31 b(the)g(\014nal)f(state)i(of)e(the)h(\014le)f(as)h (it)g(will)f(exist)i(when)d(the)h(\014le)h(is)f(actually)i(closed.)227 4247 y(A)f(t)m(ypical)h(use)e(of)h(these)g(routines)f(w)m(ould)g(b)s(e) g(to)h(\015ush)e(the)h(state)i(of)f(a)g(FITS)e(table)j(to)f(disk)f (after)h(eac)m(h)227 4360 y(ro)m(w)36 b(of)f(the)h(table)g(is)f (written.)55 b(It)36 b(is)f(recommend)g(that)h(\014ts)p 2392 4360 V 32 w(\015ush)p 2613 4360 V 32 w(\014le)f(b)s(e)g(called)h (after)g(the)f(\014rst)g(ro)m(w)227 4472 y(is)k(written,)i(then)d (\014ts)p 1023 4472 V 32 w(\015ush)p 1244 4472 V 31 w(bu\013er)g(ma)m (y)h(b)s(e)f(called)h(after)g(eac)m(h)h(subsequen)m(t)e(ro)m(w)g(is)h (written.)65 b(Note)227 4585 y(that)40 b(this)f(latter)h(routine)f (will)g(not)g(automatically)j(up)s(date)c(the)h(NAXIS2)g(k)m(eyw)m(ord) h(whic)m(h)e(records)227 4698 y(the)c(n)m(um)m(b)s(er)d(of)i(ro)m(ws)h (of)f(data)g(in)g(the)g(table,)i(so)f(this)f(k)m(eyw)m(ord)g(m)m(ust)g (b)s(e)f(explicitly)j(up)s(dated)d(b)m(y)h(the)227 4811 y(application)f(program)e(after)h(eac)m(h)h(ro)m(w)e(is)g(written.)95 5036 y Fe(int)47 b(fits_flush_file)d(/)j(ffflus)286 5149 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))95 5375 y(int)g (fits_flush_buffer)c(/)48 b(ffflsh)286 5488 y(\(fitsfile)e(*fptr,)g(0,) h(>)g(int)g(*status\))286 5714 y(\(Note:)94 b(The)47 b(second)f(argument)g(must)g(be)i(0\).)p eop end %%Page: 101 109 TeXDict begin 101 108 bop 0 299 a Fh(9.1.)72 b(FITS)30 b(FILE)g(A)m(CCESS)f(R)m(OUTINES)2199 b Fj(101)0 555 y Fi(10)81 b Fj(W)-8 b(rapp)s(er)37 b(functions)h(for)g(global)h (initialization)i(and)c(clean)m(up)i(of)f(the)g(lib)s(curl)f(library)h (used)f(when)g(ac-)227 668 y(cessing)42 b(\014les)g(with)f(the)g(HTTPS) g(or)g(FTPS)g(proto)s(cols.)74 b(If)41 b(an)g(HTTPS/FTPS)f(\014le)i (transfer)f(is)g(to)227 781 y(b)s(e)33 b(p)s(erformed,)g(it)h(is)g (recommended)f(that)h(y)m(ou)g(call)h(the)f(init)g(function)f(once)h (near)f(the)h(start)g(of)g(y)m(our)227 894 y(program)j(b)s(efore)g(an)m (y)g(\014le)p 1177 894 28 4 v 33 w(op)s(en)f(calls,)k(and)d(b)s(efore)f (creating)j(an)m(y)e(threads.)60 b(The)37 b(clean)m(up)g(function)227 1007 y(should)29 b(b)s(e)f(called)j(after)f(all)g(HTTPS/FTPS)e(\014le)i (accessing)g(is)g(completed,)h(and)d(after)i(all)h(threads)e(are)227 1120 y(completed.)40 b(The)24 b(functions)f(return)h(0)g(up)s(on)f (successful)h(initialization)j(and)d(clean)m(up.)39 b(These)24 b(are)g(NOT)227 1233 y(THREAD-SAFE.)95 1507 y Fe(int)47 b(fits_init_https)d(/)j(ffihtps)286 1620 y(\(\))95 1846 y(int)g(fits_cleanup_https)c(/)48 b(ffchtps)286 1958 y(\(\))0 2266 y Fd(9.1.2)112 b(Do)m(wnload)39 b(Utilit)m(y)e(F)-9 b(unctions)0 2488 y Fj(These)32 b(routines)h(do)f(not)h(need)g(to)g(b)s (e)f(called)i(for)e(normal)h(\014le)f(accessing.)49 b(They)33 b(are)g(primarily)f(in)m(tended)g(to)0 2601 y(help)g(with)g(debugging)g (and)g(diagnosing)h(issues)f(whic)m(h)g(o)s(ccur)g(during)f(\014le)i (do)m(wnloads.)46 b(These)32 b(routines)h(are)0 2714 y(NOT)d(THREAD-SAFE.)0 2988 y Fi(1)81 b Fj(T)-8 b(oggle)23 b(the)f(v)m(erb)s(osit)m(y)g(of)f(the)h(lib)s(curl)e(library)h (diagnostic)i(output)e(when)f(accessing)j(\014les)f(with)f(the)g(HTTPS) 227 3101 y(or)31 b(FTPS)e(proto)s(col.)42 b(`\015ag')31 b(=)f(1)h(turns)e(the)i(output)f(on,)g(0)h(turns)e(it)i(o\013)g(\(the)g (default\).)143 3375 y Fe(void)47 b(fits_verbose_https)c(/)k(ffvhtps) 382 3488 y(\(int)f(flag\))0 3762 y Fi(2)g Fj(If)38 b(`\015ag')h(is)g (set)g(to)g(1,)j(this)c(will)h(displa)m(y)g(\(to)h(stderr\))e(a)h (progress)f(bar)g(during)g(an)g(h)m(ttps)h(\014le)f(do)m(wnload.)227 3875 y(\(This)30 b(is)h(not)f(y)m(et)i(implemen)m(ted)f(for)f(other)g (\014le)h(transfer)f(proto)s(cols.\))42 b(`\015ag')31 b(=)f(0)h(b)m(y)f(default.)143 4149 y Fe(void)47 b (fits_show_download_progr)o(ess)41 b(/)48 b(ffshdwn)382 4262 y(\(int)e(flag\))0 4536 y Fi(3)g Fj(The)33 b(timeout)h(setting)h (\(in)e(seconds\))h(determines)f(the)h(maxim)m(um)f(time)h(allo)m(w)m (ed)h(for)e(a)h(net)g(do)m(wnload)f(to)227 4649 y(complete.)42 b(If)28 b(a)h(do)m(wnload)f(has)h(not)f(\014nished)f(within)h(the)h (allo)m(w)m(ed)h(time,)g(the)f(\014le)f(transfer)g(will)h(termi-)227 4762 y(nate)d(and)f(the)h(CFITSIO)e(calling)j(function)e(will)g(return) g(with)g(an)g(error.)39 b(Use)26 b(\014ts)p 3102 4762 V 32 w(get)p 3254 4762 V 34 w(timeout)h(will)e(see)227 4875 y(the)30 b(curren)m(t)g(timeout)g(setting)h(and)e(\014ts)p 1637 4875 V 33 w(set)p 1781 4875 V 33 w(timeout)i(to)f(c)m(hange)h(the) f(setting.)42 b(This)29 b(adjustman)m(t)g(ma)m(y)227 4988 y(b)s(e)h(particularly)h(useful)f(when)f(ha)m(ving)i(trouble)f(do) m(wnloading)h(large)g(\014les)g(o)m(v)m(er)h(slo)m(w)f(connections.)143 5262 y Fe(int)47 b(fits_get_timeout)c(/)48 b(ffgtmo)334 5375 y(\(\))143 5601 y(int)f(fits_set_timeout)c(/)48 b(ffstmo)334 5714 y(\(int)f(seconds,)e(>)j(int)f(*status\))p eop end %%Page: 102 110 TeXDict begin 102 109 bop 0 299 a Fj(102)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Ff(9.2)135 b(HDU)46 b(Access)e(Routines)0 795 y Fi(1)81 b Fj(Get)28 b(the)f(b)m(yte)h(o\013sets)g(in)f(the)g (FITS)f(\014le)i(to)f(the)h(start)g(of)f(the)g(header)g(and)g(the)g (start)h(and)e(end)h(of)g(the)g(data)227 908 y(in)34 b(the)g(CHDU.)g(The)f(di\013erence)h(b)s(et)m(w)m(een)h(headstart)f (and)f(dataend)h(equals)g(the)g(size)g(of)g(the)g(CHDU.)227 1021 y(If)e(the)h(CHDU)f(is)h(the)f(last)h(HDU)g(in)f(the)h(\014le,)g (then)f(dataend)g(is)g(also)i(equal)e(to)h(the)g(size)g(of)g(the)f(en)m (tire)227 1133 y(FITS)i(\014le.)55 b(Null)35 b(p)s(oin)m(ters)g(ma)m(y) g(b)s(e)f(input)g(for)h(an)m(y)g(of)g(the)g(address)f(parameters)i(if)e (their)h(v)-5 b(alues)36 b(are)227 1246 y(not)31 b(needed.)95 1502 y Fe(int)47 b(fits_get_hduaddr)d(/)j(ffghad)94 b(\(only)46 b(supports)g(files)g(up)h(to)h(2.1)f(GB)g(in)g(size\))334 1615 y(\(fitsfile)e(*fptr,)h(>)i(long)f(*headstart,)d(long)j (*datastart,)e(long)h(*dataend,)382 1728 y(int)h(*status\))95 1953 y(int)g(fits_get_hduaddrll)c(/)48 b(ffghadll)93 b(\(supports)45 b(large)i(files\))334 2066 y(\(fitsfile)e(*fptr,)h(>)i (LONGLONG)d(*headstart,)g(LONGLONG)h(*datastart,)382 2179 y(LONGLONG)f(*dataend,)h(int)h(*status\))0 2434 y Fi(2)81 b Fj(Create)31 b(\(app)s(end\))f(a)i(new)e(empt)m(y)i(HDU)f (at)h(the)f(end)f(of)i(the)f(FITS)f(\014le.)42 b(This)31 b(is)g(no)m(w)g(the)g(CHDU)g(but)f(it)227 2547 y(is)i(completely)g (empt)m(y)g(and)f(has)g(no)g(header)g(k)m(eyw)m(ords.)43 b(It)32 b(is)f(recommended)g(that)h(\014ts)p 3344 2547 28 4 v 32 w(create)p 3612 2547 V 34 w(img)g(or)227 2660 y(\014ts)p 354 2660 V 33 w(create)p 623 2660 V 34 w(tbl)e(b)s(e)g(used) g(instead)g(of)h(this)f(routine.)95 2916 y Fe(int)47 b(fits_create_hdu)d(/)j(ffcrhd)286 3028 y(\(fitsfile)f(*fptr,)g(>)h (int)g(*status\))0 3284 y Fi(3)81 b Fj(Insert)22 b(a)h(new)g(IMA)m(GE)h (extension)f(immediately)i(follo)m(wing)f(the)f(CHDU,)h(or)f(insert)g (a)g(new)f(Primary)h(Arra)m(y)227 3397 y(at)30 b(the)e(b)s(eginning)g (of)h(the)g(\014le.)40 b(An)m(y)29 b(follo)m(wing)h(extensions)f(in)g (the)f(\014le)h(will)g(b)s(e)f(shifted)g(do)m(wn)h(to)g(mak)m(e)227 3510 y(ro)s(om)36 b(for)h(the)f(new)g(extension.)59 b(If)36 b(the)h(CHDU)g(is)f(the)h(last)g(HDU)g(in)f(the)h(\014le)f(then)g(the)h (new)f(image)227 3623 y(extension)31 b(will)g(simply)e(b)s(e)h(app)s (ended)e(to)j(the)f(end)g(of)g(the)g(\014le.)41 b(One)30 b(can)g(force)h(a)g(new)e(primary)g(arra)m(y)227 3735 y(to)35 b(b)s(e)d(inserted)i(at)g(the)g(b)s(eginning)f(of)g(the)h(FITS) f(\014le)g(b)m(y)h(setting)h(status)e(=)h(PREPEND)p 3432 3735 V 32 w(PRIMAR)-8 b(Y)227 3848 y(prior)25 b(to)g(calling)i(the)e (routine.)38 b(In)25 b(this)f(case)i(the)f(old)g(primary)f(arra)m(y)i (will)f(b)s(e)f(con)m(v)m(erted)j(to)e(an)g(IMA)m(GE)227 3961 y(extension.)49 b(The)32 b(new)g(extension)i(\(or)f(primary)f (arra)m(y\))h(will)h(b)s(ecome)f(the)g(CHDU.)g(Refer)g(to)h(Chapter)227 4074 y(9)d(for)f(a)h(list)g(of)f(pre-de\014ned)f(bitpix)i(v)-5 b(alues.)95 4329 y Fe(int)47 b(fits_insert_img)d(/)j(ffiimg)286 4442 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(long)h (*naxes,)f(>)h(int)g(*status\))95 4668 y(int)g(fits_insert_imgll)c(/)48 b(ffiimgll)286 4781 y(\(fitsfile)e(*fptr,)g(int)h(bitpix,)e(int)i (naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 5036 y Fi(4)81 b Fj(Insert)30 b(a)g(new)g(ASCI)s(I)f(or)i(binary)f (table)h(extension)g(immediately)h(follo)m(wing)g(the)f(CHDU.)g(An)m(y) f(follo)m(wing)227 5149 y(extensions)36 b(will)g(b)s(e)f(shifted)g(do)m (wn)g(to)h(mak)m(e)g(ro)s(om)g(for)f(the)g(new)g(extension.)57 b(If)35 b(there)h(are)f(no)h(other)227 5262 y(follo)m(wing)c (extensions)g(then)e(the)h(new)f(table)h(extension)h(will)f(simply)f(b) s(e)g(app)s(ended)f(to)i(the)g(end)f(of)h(the)227 5375 y(\014le.)42 b(If)30 b(the)h(FITS)f(\014le)g(is)h(curren)m(tly)g(empt)m (y)g(then)f(this)g(routine)h(will)g(create)h(a)f(dumm)m(y)f(primary)f (arra)m(y)227 5488 y(b)s(efore)i(app)s(ending)f(the)i(table)h(to)f(it.) 44 b(The)31 b(new)g(extension)i(will)e(b)s(ecome)h(the)g(CHDU.)g(The)f (tunit)h(and)227 5601 y(extname)39 b(parameters)g(are)f(optional)i(and) e(a)g(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(giv)m(en)h(if)f(they)h (are)f(not)h(de\014ned.)227 5714 y(When)32 b(inserting)g(an)g(ASCI)s(I) f(table)i(with)e(\014ts)p 1847 5714 V 33 w(insert)p 2103 5714 V 33 w(atbl,)i(a)f(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)h(giv)m(en)g (for)f(the)g(*tb)s(col)p eop end %%Page: 103 111 TeXDict begin 103 110 bop 0 299 a Fh(9.2.)72 b(HDU)31 b(A)m(CCESS)e(R)m(OUTINES)2443 b Fj(103)227 555 y(parameter)23 b(in)f(whic)m(h)h(case)g(eac)m(h)h(column)e(of)h(the)g(table)g(will)g (b)s(e)f(separated)h(b)m(y)f(a)h(single)g(space)g(c)m(haracter.)227 668 y(Similarly)-8 b(,)29 b(if)d(the)h(input)f(v)-5 b(alue)27 b(of)g(ro)m(wlen)g(is)f(0,)i(then)f(CFITSIO)e(will)i(calculate)i(the)e (default)f(ro)m(wlength)227 781 y(based)39 b(on)g(the)g(tb)s(col)h(and) e(tt)m(yp)s(e)h(v)-5 b(alues.)67 b(Under)39 b(normal)g(circumstances,)j (the)d(nro)m(ws)f(paramen)m(ter)227 894 y(should)31 b(ha)m(v)m(e)i(a)f (v)-5 b(alue)32 b(of)f(0;)i(CFITSIO)d(will)i(automatically)j(up)s(date) 30 b(the)i(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(as)g(data)g(is)227 1007 y(written)26 b(to)h(the)f(table.)40 b(When)25 b(inserting)h(a)h (binary)e(table)h(with)g(\014ts)p 2596 1007 28 4 v 32 w(insert)p 2851 1007 V 33 w(btbl,)g(if)g(there)g(are)g(follo)m(wing)227 1120 y(extensions)f(in)f(the)h(\014le)f(and)g(if)g(the)h(table)g(con)m (tains)g(v)-5 b(ariable)25 b(length)g(arra)m(y)g(columns)f(then)g(p)s (coun)m(t)g(m)m(ust)227 1233 y(sp)s(ecify)30 b(the)h(exp)s(ected)g (\014nal)f(size)h(of)f(the)h(data)g(heap,)f(otherwise)h(p)s(coun)m(t)f (m)m(ust)h(=)f(0.)95 1490 y Fe(int)47 b(fits_insert_atbl)d(/)j(ffitab) 286 1603 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(rowlen,)h(LONGLONG)g (nrows,)g(int)h(tfields,)e(char)i(*ttype[],)334 1716 y(long)g(*tbcol,)f(char)g(*tform[],)f(char)i(*tunit[],)e(char)i (*extname,)e(>)j(int)f(*status\))95 1942 y(int)g(fits_insert_btbl)d(/)j (ffibin)286 2055 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(nrows,)h(int)h (tfields,)f(char)g(**ttype,)286 2168 y(char)h(**tform,)f(char)g (**tunit,)g(char)g(*extname,)g(long)g(pcount,)g(>)i(int)e(*status\))0 2425 y Fi(5)81 b Fj(Mo)s(dify)27 b(the)h(size,)h(dimensions,)f(and/or)f (data)i(t)m(yp)s(e)f(of)f(the)h(curren)m(t)g(primary)e(arra)m(y)i(or)g (image)h(extension.)227 2538 y(If)39 b(the)h(new)e(image,)44 b(as)39 b(sp)s(eci\014ed)g(b)m(y)g(the)g(input)g(argumen)m(ts,)j(is)d (larger)h(than)f(the)h(curren)m(t)f(existing)227 2651 y(image)30 b(in)e(the)g(FITS)g(\014le)g(then)g(zero)h(\014ll)f(data)h (will)g(b)s(e)f(inserted)g(at)h(the)f(end)g(of)g(the)h(curren)m(t)f (image)i(and)227 2764 y(an)m(y)35 b(follo)m(wing)h(extensions)f(will)g (b)s(e)f(mo)m(v)m(ed)i(further)d(bac)m(k)i(in)g(the)f(\014le.)54 b(Similarly)-8 b(,)36 b(if)f(the)g(new)f(image)227 2877 y(is)j(smaller)g(than)g(the)f(curren)m(t)h(image)h(then)e(an)m(y)h (follo)m(wing)h(extensions)f(will)g(b)s(e)f(shifted)h(up)e(to)m(w)m (ards)227 2990 y(the)h(b)s(eginning)f(of)h(the)g(FITS)f(\014le)h(and)f (the)h(image)h(data)f(will)h(b)s(e)e(truncated)g(to)i(the)f(new)f (size.)58 b(This)227 3103 y(routine)27 b(rewrites)g(the)h(BITPIX,)f (NAXIS,)g(and)f(NAXISn)g(k)m(eyw)m(ords)i(with)f(the)g(appropriate)g(v) -5 b(alues)27 b(for)227 3216 y(the)k(new)f(image.)95 3473 y Fe(int)47 b(fits_resize_img)d(/)j(ffrsim)286 3586 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(long)h(*naxes,)f (>)h(int)g(*status\))95 3812 y(int)g(fits_resize_imgll)c(/)48 b(ffrsimll)286 3925 y(\(fitsfile)e(*fptr,)g(int)h(bitpix,)e(int)i (naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 4183 y Fi(6)81 b Fj(Cop)m(y)43 b(the)h(data)h(\(and)e(not)h(the)g (header\))g(from)f(the)h(CHDU)g(asso)s(ciated)h(with)f(infptr)e(to)j (the)f(CHDU)227 4295 y(asso)s(ciated)34 b(with)e(outfptr.)47 b(This)32 b(will)g(o)m(v)m(erwrite)i(an)m(y)f(data)g(previously)g(in)f (the)h(output)f(CHDU.)h(This)227 4408 y(lo)m(w)39 b(lev)m(el)h(routine) e(is)g(used)f(b)m(y)h(\014ts)p 1510 4408 V 33 w(cop)m(y)p 1724 4408 V 33 w(hdu,)h(but)e(it)i(ma)m(y)f(also)h(b)s(e)f(useful)f(in) h(certain)h(application)227 4521 y(programs)30 b(that)h(w)m(an)m(t)g (to)g(cop)m(y)g(the)f(data)h(from)f(one)h(FITS)e(\014le)i(to)g(another) f(but)f(also)j(w)m(an)m(t)f(to)g(mo)s(dify)227 4634 y(the)h(header)g(k) m(eyw)m(ords.)46 b(The)32 b(required)f(FITS)g(header)h(k)m(eyw)m(ords)g (whic)m(h)g(de\014ne)f(the)h(structure)g(of)g(the)227 4747 y(HDU)f(m)m(ust)g(b)s(e)e(written)i(to)g(the)f(output)g(CHDU)h(b)s (efore)f(calling)i(this)e(routine.)95 5005 y Fe(int)47 b(fits_copy_data)d(/)k(ffcpdt)286 5118 y(\(fitsfile)e(*infptr,)f (fitsfile)h(*outfptr,)f(>)i(int)g(*status\))0 5375 y Fi(7)81 b Fj(Read)30 b(or)g(write)g(a)h(sp)s(eci\014ed)e(n)m(um)m(b)s (er)g(of)i(b)m(ytes)f(starting)h(at)g(the)g(sp)s(eci\014ed)e(b)m(yte)i (o\013set)g(from)f(the)g(start)h(of)227 5488 y(the)c(extension)g(data)f (unit.)39 b(These)26 b(lo)m(w)h(lev)m(el)h(routine)e(are)h(in)m(tended) f(mainly)g(for)g(accessing)i(the)e(data)h(in)227 5601 y(non-standard,)h(conforming)g(extensions,)h(and)e(should)g(not)h(b)s (e)g(used)f(for)g(standard)g(IMA)m(GE,)i(T)-8 b(ABLE,)227 5714 y(or)31 b(BINT)-8 b(ABLE)31 b(extensions.)p eop end %%Page: 104 112 TeXDict begin 104 111 bop 0 299 a Fj(104)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_read_ext)e(/)i(ffgextn)286 668 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(offset,)h(LONGLONG)g(nbytes,)f (void)i(*buffer\))95 781 y(int)g(fits_write_ext)d(/)k(ffpextn)286 894 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(offset,)h(LONGLONG)g(nbytes,)f (void)i(*buffer\))0 1158 y Fi(8)81 b Fj(This)34 b(routine)g(forces)h (CFITSIO)f(to)h(rescan)g(the)g(curren)m(t)g(header)f(k)m(eyw)m(ords)h (that)g(de\014ne)f(the)h(structure)227 1271 y(of)f(the)f(HDU)h(\(suc)m (h)g(as)f(the)h(NAXIS)f(and)g(BITPIX)g(k)m(eyw)m(ords\))h(so)f(that)h (it)g(reinitializes)i(the)d(in)m(ternal)227 1384 y(bu\013ers)26 b(that)h(describ)s(e)g(the)g(HDU)g(structure.)39 b(This)26 b(routine)h(is)g(useful)f(for)g(reinitializing)j(the)e(structure)227 1497 y(of)34 b(an)f(HDU)h(if)f(an)m(y)h(of)g(the)f(required)g(k)m(eyw)m (ords)g(\(e.g.,)j(NAXISn\))d(ha)m(v)m(e)i(b)s(een)e(mo)s(di\014ed.)48 b(In)33 b(practice)227 1610 y(it)e(should)e(rarely)h(b)s(e)f(necessary) h(to)h(call)g(this)f(routine)g(b)s(ecause)f(CFITSIO)g(in)m(ternally)i (calls)g(it)f(in)g(most)227 1723 y(situations.)95 1987 y Fe(int)47 b(fits_set_hdustruc)c(/)48 b(ffrdef)286 2100 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))141 b(\(DEPRECATED\))0 2439 y Ff(9.3)135 b(Sp)t(ecialized)46 b(Header)g(Keyw)l(ord)f(Routines) 0 2693 y Fd(9.3.1)112 b(Header)38 b(Information)h(Routines)0 2906 y Fi(1)81 b Fj(Reserv)m(e)29 b(space)g(in)e(the)i(CHU)f(for)g (MOREKEYS)f(more)h(header)g(k)m(eyw)m(ords.)41 b(This)27 b(routine)h(ma)m(y)h(b)s(e)f(called)227 3018 y(to)34 b(allo)s(cate)h(space)e(for)f(additional)i(k)m(eyw)m(ords)f(at)g(the)g (time)g(the)g(header)f(is)h(created)g(\(prior)g(to)g(writing)227 3131 y(an)m(y)h(data\).)51 b(CFITSIO)32 b(can)i(dynamically)g(add)f (more)g(space)h(to)g(the)g(header)f(when)f(needed,)j(ho)m(w)m(ev)m(er) 227 3244 y(it)c(is)g(more)f(e\016cien)m(t)i(to)f(preallo)s(cate)h(the)f (required)f(space)h(if)f(the)g(size)i(is)e(kno)m(wn)g(in)g(adv)-5 b(ance.)95 3509 y Fe(int)47 b(fits_set_hdrsize)d(/)j(ffhdef)286 3621 y(\(fitsfile)f(*fptr,)g(int)h(morekeys,)e(>)i(int)g(*status\))0 3886 y Fi(2)81 b Fj(Return)26 b(the)h(n)m(um)m(b)s(er)e(of)j(k)m(eyw)m (ords)f(in)f(the)h(header)g(\(not)h(coun)m(ting)g(the)f(END)g(k)m(eyw)m (ord\))h(and)e(the)h(curren)m(t)227 3999 y(p)s(osition)34 b(in)g(the)g(header.)50 b(The)34 b(p)s(osition)f(is)h(the)g(n)m(um)m(b) s(er)f(of)h(the)g(k)m(eyw)m(ord)g(record)f(that)i(will)f(b)s(e)f(read) 227 4112 y(next)k(\(or)g(one)f(greater)i(than)e(the)h(p)s(osition)f(of) h(the)g(last)g(k)m(eyw)m(ord)g(that)g(w)m(as)g(read\).)59 b(A)37 b(v)-5 b(alue)36 b(of)h(1)g(is)227 4224 y(returned)29 b(if)i(the)f(p)s(oin)m(ter)h(is)f(p)s(ositioned)h(at)g(the)f(b)s (eginning)g(of)g(the)h(header.)95 4489 y Fe(int)47 b(fits_get_hdrpos)d (/)j(ffghps)286 4602 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*keysexist,)e (int)i(*keynum,)e(int)i(*status\))0 4897 y Fd(9.3.2)112 b(Read)38 b(and)h(W)-9 b(rite)36 b(the)h(Required)h(Keyw)m(ords)0 5110 y Fi(1)81 b Fj(W)-8 b(rite)34 b(the)f(required)g(extension)h (header)e(k)m(eyw)m(ords)i(in)m(to)g(the)f(CHU.)h(These)f(routines)g (are)g(not)g(required,)227 5223 y(and)g(instead)g(the)g(appropriate)g (header)g(ma)m(y)g(b)s(e)g(constructed)g(b)m(y)g(writing)g(eac)m(h)h (individual)e(k)m(eyw)m(ord)227 5336 y(in)e(the)h(prop)s(er)e (sequence.)227 5488 y(The)21 b(simpler)g(\014ts)p 842 5488 28 4 v 33 w(write)p 1077 5488 V 33 w(imghdr)f(routine)i(is)f (equiv)-5 b(alen)m(t)23 b(to)f(calling)h(\014ts)p 2727 5488 V 32 w(write)p 2961 5488 V 33 w(grphdr)d(with)h(the)h(default)227 5601 y(v)-5 b(alues)37 b(of)f(simple)g(=)g(TR)m(UE,)g(p)s(coun)m(t)g(=) g(0,)i(gcoun)m(t)f(=)f(1,)i(and)e(extend)g(=)f(TR)m(UE.)i(The)e (PCOUNT,)227 5714 y(GCOUNT)43 b(and)g(EXTEND)g(k)m(eyw)m(ords)g(are)h (not)f(required)f(in)h(the)h(primary)e(header)h(and)f(are)i(only)p eop end %%Page: 105 113 TeXDict begin 105 112 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(105)227 555 y(written)38 b(if)f(p)s(coun)m(t)g(is)g(not)h(equal)f(to)i(zero,)h (gcoun)m(t)e(is)f(not)h(equal)g(to)g(zero)g(or)f(one,)j(and)c(if)i (extend)f(is)227 668 y(TR)m(UE,)k(resp)s(ectiv)m(ely)-8 b(.)74 b(When)41 b(writing)g(to)h(an)e(IMA)m(GE)i(extension,)i(the)e (SIMPLE)e(and)g(EXTEND)227 781 y(parameters)c(are)f(ignored.)56 b(It)35 b(is)g(recommended)g(that)h(\014ts)p 2342 781 28 4 v 32 w(create)p 2610 781 V 35 w(image)g(or)f(\014ts)p 3150 781 V 33 w(create)p 3419 781 V 34 w(tbl)g(b)s(e)g(used)227 894 y(instead)26 b(of)f(these)h(routines)g(to)g(write)f(the)h(required) e(header)i(k)m(eyw)m(ords.)39 b(The)25 b(general)h(\014ts)p 3377 894 V 33 w(write)p 3612 894 V 33 w(exthdr)227 1007 y(routine)31 b(ma)m(y)g(b)s(e)e(used)h(to)h(write)g(the)f(header)g(of)h (an)m(y)g(conforming)f(FITS)g(extension.)95 1252 y Fe(int)47 b(fits_write_imghdr)c(/)48 b(ffphps)286 1365 y(\(fitsfile)e(*fptr,)g (int)h(bitpix,)e(int)i(naxis,)f(long)h(*naxes,)f(>)h(int)g(*status\))95 1591 y(int)g(fits_write_imghdrll)c(/)k(ffphpsll)286 1704 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(LONGLONG)g (*naxes,)g(>)h(int)g(*status\))95 1930 y(int)g(fits_write_grphdr)c(/)48 b(ffphpr)286 2042 y(\(fitsfile)e(*fptr,)g(int)h(simple,)e(int)i (bitpix,)f(int)h(naxis,)f(long)h(*naxes,)334 2155 y(LONGLONG)f(pcount,) f(LONGLONG)h(gcount,)g(int)h(extend,)f(>)h(int)g(*status\))95 2381 y(int)g(fits_write_grphdrll)c(/)k(ffphprll)286 2494 y(\(fitsfile)f(*fptr,)g(int)h(simple,)e(int)i(bitpix,)f(int)h(naxis,)f (LONGLONG)g(*naxes,)334 2607 y(LONGLONG)g(pcount,)f(LONGLONG)h(gcount,) g(int)h(extend,)f(>)h(int)g(*status\))95 2833 y(int)g (fits_write_exthdr)c(/ffphext)286 2946 y(\(fitsfile)j(*fptr,)g(char)g (*xtension,)f(int)i(bitpix,)f(int)h(naxis,)f(long)h(*naxes,)334 3059 y(LONGLONG)f(pcount,)f(LONGLONG)h(gcount,)g(>)h(int)g(*status\))0 3417 y Fi(2)81 b Fj(W)-8 b(rite)30 b(the)g(ASCI)s(I)d(table)k(header)e (k)m(eyw)m(ords)g(in)m(to)i(the)e(CHU.)h(The)e(optional)j(TUNITn)d(and) h(EXTNAME)227 3530 y(k)m(eyw)m(ords)f(are)h(written)e(only)h(if)g(the)g (input)f(p)s(oin)m(ters)h(are)g(not)g(n)m(ull.)40 b(A)27 b(n)m(ull)h(p)s(oin)m(ter)g(ma)m(y)g(giv)m(en)h(for)f(the)227 3643 y(*tb)s(col)37 b(parameter)g(in)f(whic)m(h)g(case)i(a)e(single)h (space)g(will)g(b)s(e)f(inserted)g(b)s(et)m(w)m(een)h(eac)m(h)g(column) f(of)h(the)227 3756 y(table.)57 b(Similarly)-8 b(,)37 b(if)f(ro)m(wlen)f(is)h(giv)m(en)g(=)f(0,)i(then)e(CFITSIO)f(will)i (calculate)h(the)f(default)f(ro)m(wlength)227 3868 y(based)30 b(on)h(the)f(tb)s(col)h(and)f(tt)m(yp)s(e)h(v)-5 b(alues.)95 4114 y Fe(int)47 b(fits_write_atblhdr)c(/)48 b(ffphtb)286 4227 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(rowlen,)h(LONGLONG)g(nrows,)g (int)h(tfields,)e(char)i(**ttype,)334 4340 y(long)g(*tbcol,)f(char)g (**tform,)g(char)g(**tunit,)g(char)h(*extname,)e(>)i(int)g(*status\))0 4585 y Fi(3)81 b Fj(W)-8 b(rite)30 b(the)f(binary)g(table)h(header)e(k) m(eyw)m(ords)i(in)m(to)g(the)f(CHU.)g(The)g(optional)h(TUNITn)e(and)h (EXTNAME)227 4698 y(k)m(eyw)m(ords)35 b(are)g(written)g(only)g(if)f (the)h(input)f(p)s(oin)m(ters)g(are)h(not)g(n)m(ull.)53 b(The)35 b(p)s(coun)m(t)f(parameter,)i(whic)m(h)227 4811 y(sp)s(eci\014es)h(the)g(size)g(of)g(the)g(v)-5 b(ariable)38 b(length)f(arra)m(y)g(heap,)h(should)e(initially)i(=)f(0;)j(CFITSIO)c (will)h(au-)227 4924 y(tomatically)d(up)s(date)d(the)g(PCOUNT)f(k)m (eyw)m(ord)i(v)-5 b(alue)32 b(if)f(an)m(y)g(v)-5 b(ariable)32 b(length)g(arra)m(y)g(data)g(is)f(written)227 5036 y(to)g(the)e(heap.) 41 b(The)29 b(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(for)g(v)-5 b(ariable)30 b(length)g(v)m(ector)h(columns)e(should)g(ha) m(v)m(e)i(the)227 5149 y(form)c('Pt\(len\)')j(or)d('1Pt\(len\)')j (where)d(`t')h(is)g(the)g(data)g(t)m(yp)s(e)g(co)s(de)f(letter)i (\(A,I,J,E,D,)g(etc.\))42 b(and)27 b(`len')h(is)227 5262 y(an)g(in)m(teger)i(sp)s(ecifying)e(the)g(maxim)m(um)g(length)g(of)h (the)f(v)m(ectors)h(in)f(that)h(column)f(\(len)g(m)m(ust)g(b)s(e)g (greater)227 5375 y(than)36 b(or)g(equal)h(to)g(the)f(longest)i(v)m (ector)f(in)f(the)h(column\).)58 b(If)36 b(`len')g(is)h(not)f(sp)s (eci\014ed)g(when)f(the)h(table)227 5488 y(is)c(created)g(\(e.g.,)h (the)f(input)e(TF)m(ORMn)h(v)-5 b(alue)32 b(is)f(just)g('1Pt'\))i(then) e(CFITSIO)f(will)h(scan)h(the)f(column)227 5601 y(when)f(the)h(table)h (is)f(\014rst)f(closed)h(and)g(will)g(app)s(end)e(the)i(maxim)m(um)g (length)g(to)g(the)g(TF)m(ORM)g(k)m(eyw)m(ord)227 5714 y(v)-5 b(alue.)41 b(Note)30 b(that)f(if)f(the)h(table)g(is)g(subsequen) m(tly)f(mo)s(di\014ed)f(to)j(increase)f(the)g(maxim)m(um)f(length)h(of) g(the)p eop end %%Page: 106 114 TeXDict begin 106 113 bop 0 299 a Fj(106)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(v)m(ectors)39 b(then)e(the)g(mo)s(difying)g (program)g(is)g(resp)s(onsible)g(for)g(also)h(up)s(dating)e(the)i(TF)m (ORM)f(k)m(eyw)m(ord)227 668 y(v)-5 b(alue.)95 935 y Fe(int)47 b(fits_write_btblhdr)c(/)48 b(ffphbn)286 1048 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(nrows,)h(int)h(tfields,)f(char)g (**ttype,)334 1161 y(char)h(**tform,)e(char)i(**tunit,)e(char)i (*extname,)e(LONGLONG)h(pcount,)g(>)h(int)g(*status\))0 1427 y Fi(4)81 b Fj(Read)30 b(the)h(required)e(k)m(eyw)m(ords)i(from)f (the)h(CHDU)f(\(image)j(or)d(table\).)42 b(When)30 b(reading)h(from)f (an)g(IMA)m(GE)227 1540 y(extension)24 b(the)g(SIMPLE)e(and)h(EXTEND)g (parameters)h(are)f(ignored.)39 b(A)23 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m (y)g(b)s(e)e(supplied)227 1653 y(for)30 b(an)m(y)h(of)g(the)f(returned) f(parameters)i(that)g(are)g(not)f(needed.)95 1920 y Fe(int)47 b(fits_read_imghdr)d(/)j(ffghpr)286 2033 y(\(fitsfile)f(*fptr,)g(int)h (maxdim,)e(>)j(int)f(*simple,)e(int)i(*bitpix,)f(int)h(*naxis,)334 2146 y(long)g(*naxes,)f(long)g(*pcount,)g(long)g(*gcount,)g(int)h (*extend,)e(int)i(*status\))95 2372 y(int)g(fits_read_imghdrll)c(/)48 b(ffghprll)286 2485 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(int)f (*simple,)e(int)i(*bitpix,)f(int)h(*naxis,)334 2598 y(LONGLONG)f (*naxes,)f(long)i(*pcount,)f(long)g(*gcount,)g(int)h(*extend,)e(int)i (*status\))95 2823 y(int)g(fits_read_atblhdr)c(/)48 b(ffghtb)286 2936 y(\(fitsfile)e(*fptr,int)f(maxdim,)h(>)h(long)g(*rowlen,)e(long)i (*nrows,)334 3049 y(int)g(*tfields,)e(char)i(**ttype,)e(LONGLONG)h (*tbcol,)g(char)g(**tform,)g(char)h(**tunit,)334 3162 y(char)g(*extname,)93 b(int)47 b(*status\))95 3388 y(int)g (fits_read_atblhdrll)c(/)k(ffghtbll)286 3501 y(\(fitsfile)f(*fptr,int)f (maxdim,)h(>)h(LONGLONG)f(*rowlen,)f(LONGLONG)h(*nrows,)334 3614 y(int)h(*tfields,)e(char)i(**ttype,)e(long)i(*tbcol,)f(char)h (**tform,)e(char)i(**tunit,)334 3727 y(char)g(*extname,)93 b(int)47 b(*status\))95 3952 y(int)g(fits_read_btblhdr)c(/)48 b(ffghbn)286 4065 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(long)f (*nrows,)e(int)i(*tfields,)334 4178 y(char)g(**ttype,)e(char)i (**tform,)e(char)i(**tunit,)f(char)g(*extname,)334 4291 y(long)h(*pcount,)e(int)i(*status\))95 4517 y(int)g (fits_read_btblhdrll)c(/)k(ffghbnll)286 4630 y(\(fitsfile)f(*fptr,)g (int)h(maxdim,)e(>)j(LONGLONG)d(*nrows,)h(int)h(*tfields,)334 4743 y(char)g(**ttype,)e(char)i(**tform,)e(char)i(**tunit,)f(char)g (*extname,)334 4856 y(long)h(*pcount,)e(int)i(*status\))0 5155 y Fd(9.3.3)112 b(W)-9 b(rite)37 b(Keyw)m(ord)g(Routines)0 5375 y Fj(These)32 b(routines)h(simply)f(app)s(end)f(a)h(new)g(k)m(eyw) m(ord)h(to)h(the)e(header)h(and)f(do)g(not)h(c)m(hec)m(k)h(to)f(see)g (if)g(a)f(k)m(eyw)m(ord)0 5488 y(with)d(the)g(same)h(name)f(already)h (exists.)41 b(In)28 b(general)i(it)g(is)f(preferable)g(to)h(use)f(the)h (\014ts)p 3009 5488 28 4 v 32 w(up)s(date)p 3317 5488 V 32 w(k)m(ey)g(routine)f(to)0 5601 y(ensure)34 b(that)h(the)g(same)g (k)m(eyw)m(ord)g(is)f(not)h(written)g(more)g(than)f(once)h(to)h(the)e (header.)54 b(See)34 b(App)s(endix)f(B)i(for)0 5714 y(the)c (de\014nition)f(of)g(the)h(parameters)f(used)g(in)g(these)h(routines.)p eop end %%Page: 107 115 TeXDict begin 107 114 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(107)0 555 y Fi(1)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))f(a)g(new)g(k)m(eyw)m (ord)h(of)g(the)f(appropriate)g(data)h(t)m(yp)s(e)g(in)m(to)g(the)g (CHU.)f(A)h(n)m(ull)f(p)s(oin)m(ter)g(ma)m(y)227 668 y(b)s(e)35 b(en)m(tered)h(for)f(the)h(commen)m(t)h(parameter,)g(whic)m (h)e(will)h(cause)g(the)g(commen)m(t)g(\014eld)f(of)h(the)f(k)m(eyw)m (ord)227 781 y(to)43 b(b)s(e)e(left)i(blank.)76 b(The)41 b(\015t,)k(dbl,)f(cmp,)h(and)d(dblcmp)f(v)m(ersions)h(of)g(this)g (routine)g(ha)m(v)m(e)h(the)g(added)227 894 y(feature)33 b(that)g(if)g(the)f('decimals')i(parameter)f(is)g(negativ)m(e,)i(then)d (the)h('G')g(displa)m(y)g(format)g(rather)f(then)227 1007 y(the)i('E')f(format)h(will)f(b)s(e)g(used)f(when)g(constructing)i (the)g(k)m(eyw)m(ord)f(v)-5 b(alue,)35 b(taking)f(the)g(absolute)f(v)-5 b(alue)227 1120 y(of)34 b('decimals')h(for)e(the)h(precision.)51 b(This)33 b(will)h(suppress)d(trailing)k(zeros,)g(and)e(will)h(use)g(a) g(\014xed)f(format)227 1233 y(rather)e(than)f(an)g(exp)s(onen)m(tial)h (format,)g(dep)s(ending)e(on)h(the)h(magnitude)f(of)h(the)g(v)-5 b(alue.)95 1478 y Fe(int)47 b(fits_write_key_str)c(/)48 b(ffpkys)286 1591 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(char)g (*value,)g(char)h(*comment,)334 1704 y(>)h(int)e(*status\))95 1930 y(int)h(fits_write_key_[log,)c(lng])j(/)95 b(ffpky[lj])286 2042 y(\(fitsfile)46 b(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g (char)g(*comment,)334 2155 y(>)i(int)e(*status\))95 2381 y(int)h(fits_write_key_[flt,)c(dbl,)j(fixflg,)g(fixdbl])g(/)h (ffpky[edfg])286 2494 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE) g(numval,)g(int)h(decimals,)286 2607 y(char)g(*comment,)e(>)j(int)f (*status\))95 2833 y(int)g(fits_write_key_[cmp,)c(dblcmp,)i(fixcmp,)h (fixdblcmp])f(/)j(ffpk[yc,ym,fc,fm])286 2946 y(\(fitsfile)e(*fptr,)g (char)g(*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)286 3059 y(char)h(*comment,)e(>)j(int)f(*status\))0 3304 y Fi(2)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))e(a)i(string)f(v)-5 b(alued)29 b(k)m(eyw)m(ord)h(in)m(to)g(the)f(CHU)h(whic)m(h)e(ma)m(y)i (b)s(e)f(longer)h(than)e(68)i(c)m(haracters)227 3417 y(in)43 b(length.)80 b(This)42 b(uses)h(the)g(Long)h(String)e(Keyw)m (ord)h(con)m(v)m(en)m(tion)j(that)d(is)h(describ)s(ed)e(in)h(the`Lo)s (cal)227 3530 y(FITS)38 b(Con)m(v)m(en)m(tions')i(section)g(in)f (Chapter)f(4.)66 b(Since)38 b(this)h(uses)f(a)h(non-standard)f(FITS)g (con)m(v)m(en)m(tion)227 3643 y(to)45 b(enco)s(de)f(the)g(long)h(k)m (eyw)m(ord)f(string,)k(programs)43 b(whic)m(h)h(use)g(this)g(routine)g (should)f(also)h(call)i(the)227 3756 y(\014ts)p 354 3756 28 4 v 33 w(write)p 589 3756 V 33 w(k)m(ey)p 755 3756 V 33 w(longw)m(arn)26 b(routine)f(to)h(add)f(some)h(COMMENT)f(k)m(eyw)m (ords)g(to)h(w)m(arn)f(users)g(of)g(the)h(FITS)227 3868 y(\014le)43 b(that)h(this)e(con)m(v)m(en)m(tion)j(is)e(b)s(eing)f (used.)78 b(The)42 b(\014ts)p 2220 3868 V 32 w(write)p 2454 3868 V 33 w(k)m(ey)p 2620 3868 V 34 w(longw)m(arn)h(routine)g (also)h(writes)f(a)227 3981 y(k)m(eyw)m(ord)29 b(called)g(LONGSTRN)e (to)i(record)f(the)g(v)m(ersion)h(of)f(the)g(longstring)h(con)m(v)m(en) m(tion)h(that)f(has)f(b)s(een)227 4094 y(used,)35 b(in)f(case)i(a)f (new)e(con)m(v)m(en)m(tion)k(is)e(adopted)f(at)h(some)g(p)s(oin)m(t)f (in)h(the)f(future.)52 b(If)34 b(the)h(LONGSTRN)227 4207 y(k)m(eyw)m(ord)43 b(is)g(already)g(presen)m(t)g(in)g(the)f(header,)k (then)d(\014ts)p 2332 4207 V 32 w(write)p 2566 4207 V 33 w(k)m(ey)p 2732 4207 V 34 w(longw)m(arn)g(will)g(simply)f(return)227 4320 y(without)31 b(doing)f(an)m(ything.)95 4565 y Fe(int)47 b(fits_write_key_longstr)42 b(/)48 b(ffpkls)286 4678 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(char)g(*longstr,)g(char)g (*comment,)334 4791 y(>)i(int)e(*status\))95 5017 y(int)h (fits_write_key_longwarn)42 b(/)47 b(ffplsw)286 5130 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))0 5375 y Fi(3)81 b Fj(W)-8 b(rite)38 b(\(app)s(end\))d(a)i(n)m(um)m(b)s(ered)e (sequence)i(of)g(k)m(eyw)m(ords)g(in)m(to)g(the)g(CHU.)g(The)f (starting)h(index)f(n)m(um)m(b)s(er)227 5488 y(\(nstart\))30 b(m)m(ust)e(b)s(e)g(greater)i(than)f(0.)40 b(One)28 b(ma)m(y)i(app)s (end)d(the)h(same)i(commen)m(t)f(to)h(ev)m(ery)f(k)m(eyw)m(ord)g(\(and) 227 5601 y(eliminate)35 b(the)f(need)f(to)h(ha)m(v)m(e)g(an)f(arra)m(y) h(of)f(iden)m(tical)j(commen)m(t)e(strings,)g(one)f(for)h(eac)m(h)g(k)m (eyw)m(ord\))g(b)m(y)227 5714 y(including)24 b(the)h(amp)s(ersand)e(c)m (haracter)j(as)e(the)h(last)g(non-blank)f(c)m(haracter)i(in)e(the)g (\(\014rst\))h(COMMENTS)p eop end %%Page: 108 116 TeXDict begin 108 115 bop 0 299 a Fj(108)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(string)23 b(parameter.)38 b(This)22 b(same)h(string)f(will)h(then)f(b)s(e)g(used)f(for)h(the)h (commen)m(t)g(\014eld)f(in)g(all)i(the)e(k)m(eyw)m(ords.)227 668 y(One)32 b(ma)m(y)h(also)g(en)m(ter)f(a)h(n)m(ull)f(p)s(oin)m(ter)g (for)g(the)g(commen)m(t)h(parameter)g(to)f(lea)m(v)m(e)j(the)d(commen)m (t)h(\014eld)f(of)227 781 y(the)f(k)m(eyw)m(ord)g(blank.)95 995 y Fe(int)47 b(fits_write_keys_str)c(/)k(ffpkns)286 1107 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g(int)h(nstart,)e(int)i (nkeys,)334 1220 y(char)g(**value,)e(char)i(**comment,)e(>)i(int)g (*status\))95 1446 y(int)g(fits_write_keys_[log,)42 b(lng])47 b(/)g(ffpkn[lj])286 1559 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g (int)h(nstart,)e(int)i(nkeys,)334 1672 y(DTYPE)f(*numval,)g(char)h (**comment,)e(int)i(*status\))95 1898 y(int)g(fits_write_keys_[flt,)42 b(dbl,)47 b(fixflg,)f(fixdbl])g(/)h(ffpkne[edfg])286 2011 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g(int)h(nstart,)e(int)i (nkey,)334 2124 y(DTYPE)f(*numval,)g(int)h(decimals,)e(char)i (**comment,)e(>)i(int)g(*status\))0 2337 y Fi(4)81 b Fj(Cop)m(y)21 b(an)h(indexed)f(k)m(eyw)m(ord)i(from)e(one)h(HDU)h(to)f (another,)i(mo)s(difying)e(the)g(index)f(n)m(um)m(b)s(er)f(of)i(the)g (k)m(eyw)m(ord)227 2450 y(name)37 b(in)f(the)g(pro)s(cess.)58 b(F)-8 b(or)37 b(example,)i(this)d(routine)h(could)f(read)g(the)h (TLMIN3)f(k)m(eyw)m(ord)h(from)f(the)227 2563 y(input)30 b(HDU)h(\(b)m(y)g(giving)h(k)m(eyro)s(ot)f(=)g(`TLMIN')g(and)f(inn)m (um)f(=)h(3\))i(and)e(write)h(it)g(to)g(the)g(output)f(HDU)227 2676 y(with)36 b(the)g(k)m(eyw)m(ord)h(name)f(TLMIN4)g(\(b)m(y)g (setting)i(outn)m(um)d(=)h(4\).)58 b(If)36 b(the)g(input)f(k)m(eyw)m (ord)i(do)s(es)f(not)227 2789 y(exist,)c(then)e(this)g(routine)g (simply)g(returns)f(without)i(indicating)g(an)f(error.)95 3002 y Fe(int)47 b(fits_copy_key)e(/)i(ffcpky)286 3115 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(innum,)f(int)h (outnum,)334 3228 y(char)g(*keyroot,)e(>)i(int)g(*status\))0 3442 y Fi(5)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))f(a)h(`triple)f (precision')h(k)m(eyw)m(ord)g(in)m(to)g(the)g(CHU)f(in)g(F28.16)j (format.)41 b(The)29 b(\015oating)h(p)s(oin)m(t)227 3555 y(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(is)f(constructed)h(b)m(y)f (concatenating)j(the)d(input)g(in)m(teger)i(v)-5 b(alue)29 b(with)g(the)h(input)e(double)227 3668 y(precision)35 b(fraction)f(v)-5 b(alue)35 b(\(whic)m(h)f(m)m(ust)g(ha)m(v)m(e)i(a)e (v)-5 b(alue)35 b(b)s(et)m(w)m(een)f(0.0)i(and)d(1.0\).)53 b(The)34 b(\013gkyt)h(routine)227 3781 y(should)d(b)s(e)h(used)f(to)i (read)f(this)g(k)m(eyw)m(ord)h(v)-5 b(alue,)35 b(b)s(ecause)e(the)g (other)h(k)m(eyw)m(ord)f(reading)h(routines)f(will)227 3893 y(not)e(preserv)m(e)f(the)h(full)f(precision)h(of)f(the)h(v)-5 b(alue.)95 4107 y Fe(int)47 b(fits_write_key_triple)42 b(/)48 b(ffpkyt)286 4220 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g (long)g(intval,)g(double)g(frac,)334 4333 y(char)h(*comment,)e(>)i(int) g(*status\))0 4546 y Fi(6)81 b Fj(W)-8 b(rite)37 b(k)m(eyw)m(ords)f(to) h(the)f(CHDU)g(that)h(are)f(de\014ned)f(in)h(an)g(ASCI)s(I)e(template)j (\014le.)58 b(The)35 b(format)i(of)f(the)227 4659 y(template)c(\014le)f (is)f(describ)s(ed)f(under)g(the)i(\014ts)p 1788 4659 28 4 v 32 w(parse)p 2028 4659 V 33 w(template)g(routine.)95 4873 y Fe(int)47 b(fits_write_key_template)42 b(/)47 b(ffpktp)286 4986 y(\(fitsfile)f(*fptr,)g(const)g(char)h(*filename,)e (>)i(int)g(*status\))0 5269 y Fd(9.3.4)112 b(Insert)38 b(Keyw)m(ord)f(Routines)0 5488 y Fj(These)42 b(insert)h(routines)f(are) h(somewhat)g(less)f(e\016cien)m(t)i(than)f(the)f(`up)s(date')g(or)h (`write')g(k)m(eyw)m(ord)g(routines)0 5601 y(b)s(ecause)30 b(the)g(follo)m(wing)i(k)m(eyw)m(ords)e(in)g(the)g(header)g(m)m(ust)g (b)s(e)f(shifted)h(do)m(wn)f(to)i(mak)m(e)g(ro)s(om)f(for)g(the)g (inserted)0 5714 y(k)m(eyw)m(ord.)41 b(See)31 b(App)s(endix)d(B)j(for)f (the)h(de\014nition)f(of)g(the)h(parameters)g(used)e(in)h(these)h (routines.)p eop end %%Page: 109 117 TeXDict begin 109 116 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(109)0 555 y Fi(1)81 b Fj(Insert)26 b(a)h(new)f(k)m(eyw)m(ord)h(record)g(in)m(to)g (the)g(CHU)g(at)g(the)g(sp)s(eci\014ed)f(p)s(osition)h(\(i.e.,)i (immediately)f(preceding)227 668 y(the)j(\(k)m(eyn)m(um\)th)g(k)m(eyw)m (ord)g(in)f(the)g(header.\))95 921 y Fe(int)47 b(fits_insert_record)c (/)48 b(ffirec)286 1034 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(char)i (*card,)f(>)i(int)f(*status\))0 1286 y Fi(2)81 b Fj(Insert)24 b(a)h(new)g(k)m(eyw)m(ord)g(in)m(to)h(the)f(CHU.)g(The)g(new)f(k)m(eyw) m(ord)i(is)f(inserted)f(immediately)j(follo)m(wing)f(the)f(last)227 1399 y(k)m(eyw)m(ord)i(that)f(has)f(b)s(een)h(read)f(from)h(the)g (header.)39 b(The)25 b(`longstr')i(v)m(ersion)f(has)f(the)h(same)g (functionalit)m(y)227 1512 y(as)33 b(the)g(`str')f(v)m(ersion)h(except) h(that)f(it)g(also)g(supp)s(orts)e(the)h(lo)s(cal)i(long)f(string)g(k)m (eyw)m(ord)g(con)m(v)m(en)m(tion)h(for)227 1625 y(strings)29 b(longer)g(than)g(68)h(c)m(haracters.)41 b(A)29 b(n)m(ull)g(p)s(oin)m (ter)g(ma)m(y)g(b)s(e)g(en)m(tered)g(for)g(the)g(commen)m(t)g (parameter)227 1738 y(whic)m(h)d(will)f(cause)h(the)g(commen)m(t)h (\014eld)e(to)h(b)s(e)f(left)h(blank.)39 b(The)25 b(\015t,)h(dbl,)g (cmp,)h(and)e(dblcmp)f(v)m(ersions)i(of)227 1851 y(this)k(routine)g(ha) m(v)m(e)h(the)e(added)g(feature)i(that)f(if)g(the)g('decimals')h (parameter)f(is)g(negativ)m(e,)i(then)d(the)h('G')227 1964 y(displa)m(y)g(format)g(rather)f(then)g(the)h('E')f(format)h(will) g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)227 2077 y(taking)27 b(the)g(absolute)g(v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 2189 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 2302 y(the)31 b(v)-5 b(alue.)95 2555 y Fe(int)47 b(fits_insert_card)d (/)j(ffikey)286 2668 y(\(fitsfile)f(*fptr,)g(char)g(*card,)g(>)i(int)f (*status\))95 2894 y(int)g(fits_insert_key_[str,)42 b(longstr])k(/)h (ffi[kys,)f(kls])286 3007 y(\(fitsfile)g(*fptr,)g(char)g(*keyname,)g (char)g(*value,)g(char)h(*comment,)334 3120 y(>)h(int)e(*status\))95 3345 y(int)h(fits_insert_key_[log,)42 b(lng])47 b(/)g(ffiky[lj])286 3458 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(char) g(*comment,)334 3571 y(>)i(int)e(*status\))95 3797 y(int)h (fits_insert_key_[flt,)42 b(fixflt,)k(dbl,)h(fixdbl])f(/)h(ffiky[edfg]) 286 3910 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g (int)h(decimals,)334 4023 y(char)g(*comment,)e(>)i(int)g(*status\))95 4249 y(int)g(fits_insert_key_[cmp,)42 b(dblcmp,)k(fixcmp,)g(fixdblcmp]) f(/)i(ffik[yc,ym,fc,fm])286 4362 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)334 4474 y(char)h(*comment,)e(>)i(int)g(*status\))0 4727 y Fi(3)81 b Fj(Insert)32 b(a)i(new)f(k)m(eyw)m(ord)h(with)f(an)h(unde\014ned,)e (or)h(n)m(ull,)h(v)-5 b(alue)34 b(in)m(to)h(the)e(CHU.)h(The)f(v)-5 b(alue)34 b(string)f(of)h(the)227 4840 y(k)m(eyw)m(ord)d(is)g(left)g (blank)f(in)g(this)g(case.)95 5093 y Fe(int)47 b(fits_insert_key_null)c (/)k(ffikyu)286 5205 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g (*comment,)g(>)h(int)g(*status\))0 5495 y Fd(9.3.5)112 b(Read)38 b(Keyw)m(ord)g(Routines)0 5714 y Fj(Wild)31 b(card)f(c)m(haracters)i(ma)m(y)f(b)s(e)f(used)f(when)h(sp)s(ecifying)g (the)g(name)h(of)f(the)h(k)m(eyw)m(ord)g(to)g(b)s(e)f(read.)p eop end %%Page: 110 118 TeXDict begin 110 117 bop 0 299 a Fj(110)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(1)81 b Fj(Read)43 b(a)h(k)m(eyw)m(ord)g(v)-5 b(alue)43 b(\(with)h(the)f(appropriate)h(data)g(t)m(yp)s(e\))g(and)e (commen)m(t)j(from)e(the)g(CHU.)h(If)f(a)227 668 y(NULL)32 b(commen)m(t)h(p)s(oin)m(ter)f(is)h(giv)m(en)g(on)f(input,)f(then)h (the)g(commen)m(t)i(string)e(will)g(not)g(b)s(e)g(returned.)44 b(If)227 781 y(the)32 b(v)-5 b(alue)33 b(of)f(the)g(k)m(eyw)m(ord)g(is) g(not)h(de\014ned)d(\(i.e.,)k(the)e(v)-5 b(alue)33 b(\014eld)e(is)h (blank\))g(then)g(an)g(error)f(status)h(=)227 894 y(V)-10 b(ALUE)p 545 894 28 4 v 33 w(UNDEFINED)29 b(will)f(b)s(e)g(returned)e (and)h(the)h(input)f(v)-5 b(alue)28 b(will)h(not)f(b)s(e)f(c)m(hanged)h (\(except)h(that)227 1007 y(\013gkys)i(will)g(reset)g(the)f(v)-5 b(alue)31 b(to)g(a)g(n)m(ull)f(string\).)95 1252 y Fe(int)47 b(fits_read_key_str)c(/)48 b(ffgkys)286 1365 y(\(fitsfile)e(*fptr,)g (char)g(*keyname,)g(>)h(char)g(*value,)f(char)g(*comment,)334 1478 y(int)h(*status\);)95 1704 y(NOTE:)g(after)f(calling)g(the)h (following)e(routine,)h(programs)f(must)i(explicitly)e(free)382 1817 y(the)i(memory)f(allocated)f(for)i('longstr')e(after)i(it)g(is)g (no)g(longer)f(needed)g(by)382 1930 y(calling)g(fits_free_memory.)95 2155 y(int)h(fits_read_key_longstr)42 b(/)48 b(ffgkls)286 2268 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(**longstr,)e (char)h(*comment,)620 2381 y(int)h(*status\))95 2607 y(int)g(fits_free_memory)d(/)j(fffree)286 2720 y(\(char)g(*longstr,)e (>)i(int)g(*status\);)95 2946 y(int)g(fits_read_key_[log,)c(lng,)k (flt,)f(dbl,)h(cmp,)f(dblcmp])g(/)i(ffgky[ljedcm])286 3059 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(DTYPE)f(*numval,)g (char)h(*comment,)334 3172 y(int)g(*status\))95 3397 y(int)g(fits_read_key_lnglng)c(/)k(ffgkyjj)286 3510 y(\(fitsfile)f (*fptr,)g(char)g(*keyname,)g(>)h(LONGLONG)f(*numval,)f(char)i (*comment,)334 3623 y(int)g(*status\))0 3868 y Fi(2)81 b Fj(Read)36 b(a)h(sequence)f(of)h(indexed)e(k)m(eyw)m(ord)i(v)-5 b(alues)37 b(\(e.g.,)i(NAXIS1,)g(NAXIS2,)f(...\).)59 b(The)36 b(input)f(starting)227 3981 y(index)j(n)m(um)m(b)s(er)e (\(nstart\))j(m)m(ust)f(b)s(e)f(greater)i(than)e(0.)64 b(If)37 b(the)h(v)-5 b(alue)38 b(of)g(an)m(y)h(of)f(the)g(k)m(eyw)m (ords)g(is)g(not)227 4094 y(de\014ned)c(\(i.e.,)j(the)e(v)-5 b(alue)35 b(\014eld)f(is)h(blank\))g(then)f(an)g(error)h(status)g(=)f (V)-10 b(ALUE)p 3009 4094 V 33 w(UNDEFINED)36 b(will)f(b)s(e)227 4207 y(returned)21 b(and)h(the)h(input)e(v)-5 b(alue)23 b(for)f(the)g(unde\014ned)e(k)m(eyw)m(ord\(s\))k(will)e(not)h(b)s(e)e (c)m(hanged.)39 b(These)22 b(routines)227 4320 y(do)j(not)h(supp)s(ort) d(wild)i(card)h(c)m(haracters)g(in)f(the)h(ro)s(ot)f(name.)39 b(If)25 b(there)h(are)f(no)g(indexed)g(k)m(eyw)m(ords)h(in)f(the)227 4433 y(header)35 b(with)f(the)h(input)e(ro)s(ot)i(name)g(then)f(these)h (routines)g(do)f(not)h(return)e(a)i(non-zero)h(status)e(v)-5 b(alue)227 4546 y(and)30 b(instead)h(simply)f(return)f(nfound)f(=)i(0.) 95 4791 y Fe(int)47 b(fits_read_keys_str)c(/)48 b(ffgkns)286 4904 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(int)h(nstart,)e(int)i (nkeys,)334 5017 y(>)h(char)e(**value,)g(int)h(*nfound,)93 b(int)47 b(*status\))95 5243 y(int)g(fits_read_keys_[log,)c(lng,)j (flt,)h(dbl])g(/)g(ffgkn[ljed])286 5356 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(int)h(nstart,)e(int)i(nkeys,)334 5469 y(>)h(DTYPE)e (*numval,)f(int)i(*nfound,)f(int)h(*status\))0 5714 y Fi(3)81 b Fj(Read)37 b(the)h(v)-5 b(alue)38 b(of)g(a)g(\015oating)g(p)s (oin)m(t)g(k)m(eyw)m(ord,)i(returning)d(the)h(in)m(teger)h(and)e (fractional)i(parts)e(of)h(the)p eop end %%Page: 111 119 TeXDict begin 111 118 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(111)227 555 y(v)-5 b(alue)35 b(in)e(separate)i(routine)f(argumen)m(ts.)52 b(This)33 b(routine)h(ma)m(y)g(b)s(e)f(used)h(to)g(read)g(an)m(y)g(k)m (eyw)m(ord)h(but)e(is)227 668 y(esp)s(ecially)f(useful)d(for)i(reading) f(the)h('triple)g(precision')f(k)m(eyw)m(ords)h(written)g(b)m(y)f (\013pkyt.)95 929 y Fe(int)47 b(fits_read_key_triple)c(/)k(ffgkyt)286 1042 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h(long)g(*intval,)e (double)h(*frac,)334 1155 y(char)h(*comment,)e(int)i(*status\))0 1446 y Fd(9.3.6)112 b(Mo)s(dify)39 b(Keyw)m(ord)e(Routines)0 1666 y Fj(These)31 b(routines)h(mo)s(dify)f(the)h(v)-5 b(alue)32 b(of)g(an)g(existing)g(k)m(eyw)m(ord.)46 b(An)31 b(error)g(is)h(returned)e(if)i(the)g(k)m(eyw)m(ord)g(do)s(es)0 1778 y(not)43 b(exist.)77 b(Wild)43 b(card)g(c)m(haracters)h(ma)m(y)f (b)s(e)f(used)f(when)h(sp)s(ecifying)g(the)h(name)f(of)h(the)f(k)m(eyw) m(ord)h(to)h(b)s(e)0 1891 y(mo)s(di\014ed.)c(See)30 b(App)s(endix)f(B)i (for)f(the)g(de\014nition)g(of)h(the)f(parameters)h(used)f(in)g(these)h (routines.)0 2152 y Fi(1)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i (the)f(n)m(th)f(80-c)m(haracter)j(header)d(record)h(in)f(the)g(CHU.)95 2413 y Fe(int)47 b(fits_modify_record)c(/)48 b(ffmrec)286 2526 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(char)i(*card,)f(>)i(int)f (*status\))0 2786 y Fi(2)81 b Fj(Mo)s(dify)37 b(\(o)m(v)m(erwrite\))j (the)e(80-c)m(haracter)j(header)c(record)h(for)f(the)h(named)f(k)m(eyw) m(ord)h(in)g(the)g(CHU.)g(This)227 2899 y(can)31 b(b)s(e)f(used)f(to)i (o)m(v)m(erwrite)h(the)f(name)f(of)h(the)f(k)m(eyw)m(ord)h(as)g(w)m (ell)g(as)g(its)g(v)-5 b(alue)30 b(and)g(commen)m(t)i(\014elds.)95 3160 y Fe(int)47 b(fits_modify_card)d(/)j(ffmcrd)286 3273 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*card,)g(>)i (int)f(*status\))0 3534 y Fi(5)81 b Fj(Mo)s(dify)30 b(the)g(v)-5 b(alue)31 b(and)e(commen)m(t)i(\014elds)f(of)g(an)g(existing)h(k)m(eyw) m(ord)g(in)f(the)g(CHU.)h(The)e(`longstr')i(v)m(ersion)227 3647 y(has)41 b(the)h(same)f(functionalit)m(y)i(as)e(the)h(`str')f(v)m (ersion)h(except)g(that)g(it)g(also)g(supp)s(orts)d(the)j(lo)s(cal)g (long)227 3760 y(string)29 b(k)m(eyw)m(ord)h(con)m(v)m(en)m(tion)h(for) e(strings)f(longer)i(than)f(68)h(c)m(haracters.)41 b(Optionally)-8 b(,)31 b(one)e(ma)m(y)h(mo)s(dify)227 3872 y(only)e(the)g(v)-5 b(alue)28 b(\014eld)g(and)f(lea)m(v)m(e)j(the)e(commen)m(t)h(\014eld)e (unc)m(hanged)h(b)m(y)g(setting)g(the)g(input)f(COMMENT)227 3985 y(parameter)c(equal)h(to)f(the)g(amp)s(ersand)e(c)m(haracter)j (\(&\))f(or)g(b)m(y)g(en)m(tering)g(a)g(n)m(ull)g(p)s(oin)m(ter)g(for)f (the)h(commen)m(t)227 4098 y(parameter.)40 b(The)24 b(\015t,)i(dbl,)g (cmp,)f(and)g(dblcmp)e(v)m(ersions)j(of)f(this)g(routine)g(ha)m(v)m(e)h (the)f(added)f(feature)h(that)227 4211 y(if)h(the)h('decimals')g (parameter)g(is)f(negativ)m(e,)k(then)c(the)g('G')h(displa)m(y)f (format)h(rather)f(then)g(the)g('E')h(format)227 4324 y(will)i(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v) -5 b(alue,)30 b(taking)f(the)g(absolute)g(v)-5 b(alue)29 b(of)f('decimals')i(for)227 4437 y(the)37 b(precision.)60 b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) g(\014xed)e(format)i(rather)g(than)f(an)227 4550 y(exp)s(onen)m(tial)c (format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 b(alue.)95 4811 y Fe(int)47 b(fits_modify_key_[str,)42 b(longstr])k(/)h(ffm[kys,)f(kls])286 4924 y(\(fitsfile)g(*fptr,)g(char) g(*keyname,)g(char)g(*value,)g(char)h(*comment,)334 5036 y(>)h(int)e(*status\);)95 5262 y(int)h(fits_modify_key_[log,)42 b(lng])47 b(/)g(ffmky[lj])286 5375 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(DTYPE)g(numval,)g(char)g(*comment,)334 5488 y(>)i(int)e(*status\))95 5714 y(int)h(fits_modify_key_[flt,)42 b(dbl,)47 b(fixflt,)f(fixdbl])g(/)h(ffmky[edfg])p eop end %%Page: 112 120 TeXDict begin 112 119 bop 0 299 a Fj(112)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)286 555 y Fe(\(fitsfile)46 b(*fptr,)g(char)g(*keyname,)g (DTYPE)g(numval,)g(int)h(decimals,)334 668 y(char)g(*comment,)e(>)i (int)g(*status\))95 894 y(int)g(fits_modify_key_[cmp,)42 b(dblcmp,)k(fixcmp,)g(fixdblcmp])f(/)i(ffmk[yc,ym,fc,fm])286 1007 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(*numval,)g(int) g(decimals,)334 1120 y(char)h(*comment,)e(>)i(int)g(*status\))0 1434 y Fi(6)81 b Fj(Mo)s(dify)22 b(the)g(v)-5 b(alue)23 b(of)f(an)g(existing)i(k)m(eyw)m(ord)e(to)h(b)s(e)f(unde\014ned,)g(or)g (n)m(ull.)38 b(The)22 b(v)-5 b(alue)22 b(string)h(of)f(the)g(k)m(eyw)m (ord)227 1547 y(is)30 b(set)h(to)g(blank.)40 b(Optionally)-8 b(,)31 b(one)f(ma)m(y)h(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)e(unc) m(hanged)h(b)m(y)g(setting)h(the)f(input)227 1660 y(COMMENT)f (parameter)g(equal)g(to)g(the)g(amp)s(ersand)e(c)m(haracter)k(\(&\))e (or)f(b)m(y)h(en)m(tering)g(a)g(n)m(ull)g(p)s(oin)m(ter.)95 1974 y Fe(int)47 b(fits_modify_key_null)c(/)k(ffmkyu)286 2087 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h (int)g(*status\))0 2441 y Fd(9.3.7)112 b(Up)s(date)39 b(Keyw)m(ord)e(Routines)0 2690 y Fi(1)81 b Fj(These)29 b(up)s(date)g(routines)h(mo)s(dify)f(the)g(v)-5 b(alue,)31 b(and)e(optionally)i(the)f(commen)m(t)h(\014eld,)f(of)g(the)g(k)m(eyw)m (ord)g(if)f(it)227 2803 y(already)34 b(exists,)g(otherwise)f(the)g(new) f(k)m(eyw)m(ord)h(is)f(app)s(ended)f(to)j(the)f(header.)47 b(A)33 b(separate)g(routine)g(is)227 2916 y(pro)m(vided)c(for)g(eac)m (h)h(k)m(eyw)m(ord)f(data)h(t)m(yp)s(e.)41 b(The)28 b(`longstr')i(v)m (ersion)g(has)e(the)i(same)f(functionalit)m(y)h(as)g(the)227 3029 y(`str')h(v)m(ersion)g(except)h(that)g(it)f(also)h(supp)s(orts)c (the)j(lo)s(cal)h(long)g(string)e(k)m(eyw)m(ord)i(con)m(v)m(en)m(tion)h (for)d(strings)227 3142 y(longer)i(than)f(68)h(c)m(haracters.)45 b(A)31 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(en)m(tered)h(for)f (the)g(commen)m(t)i(parameter)e(whic)m(h)227 3255 y(will)i(lea)m(v)m(e) h(the)f(commen)m(t)g(\014eld)f(unc)m(hanged)g(or)g(blank.)46 b(The)31 b(\015t,)i(dbl,)f(cmp,)h(and)e(dblcmp)g(v)m(ersions)i(of)227 3367 y(this)d(routine)g(ha)m(v)m(e)h(the)e(added)g(feature)i(that)f(if) g(the)g('decimals')h(parameter)f(is)g(negativ)m(e,)i(then)d(the)h('G') 227 3480 y(displa)m(y)g(format)g(rather)f(then)g(the)h('E')f(format)h (will)g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)227 3593 y(taking)27 b(the)g(absolute)g(v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 3706 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 3819 y(the)31 b(v)-5 b(alue.)95 4133 y Fe(int)47 b (fits_update_key_[str,)42 b(longstr])k(/)h(ffu[kys,)f(kls])286 4246 y(\(fitsfile)g(*fptr,)g(char)g(*keyname,)g(char)g(*value,)g(char)h (*comment,)334 4359 y(>)h(int)e(*status\))95 4585 y(int)h (fits_update_key_[log,)42 b(lng])47 b(/)g(ffuky[lj])286 4698 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(char) g(*comment,)334 4811 y(>)i(int)e(*status\))95 5036 y(int)h (fits_update_key_[flt,)42 b(dbl,)47 b(fixflt,)f(fixdbl])g(/)h (ffuky[edfg])286 5149 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE) g(numval,)g(int)h(decimals,)334 5262 y(char)g(*comment,)e(>)i(int)g (*status\))95 5488 y(int)g(fits_update_key_[cmp,)42 b(dblcmp,)k (fixcmp,)g(fixdblcmp])f(/)i(ffuk[yc,ym,fc,fm])286 5601 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(*numval,)g(int)g (decimals,)334 5714 y(char)h(*comment,)e(>)i(int)g(*status\))p eop end %%Page: 113 121 TeXDict begin 113 120 bop 0 299 a Fh(9.4.)72 b(DEFINE)31 b(D)m(A)-8 b(T)g(A)32 b(SCALING)e(AND)h(UNDEFINED)h(PIXEL)d(P)-8 b(ARAMETERS)655 b Fj(113)0 555 y Ff(9.4)135 b(De\014ne)45 b(Data)h(Scaling)g(and)e(Unde\014ned)h(Pixel)h(P)l(arameters)0 805 y Fj(These)37 b(routines)g(set)h(or)f(mo)s(dify)g(the)g(in)m (ternal)h(parameters)g(used)e(b)m(y)i(CFITSIO)d(to)j(either)g(scale)h (the)e(data)0 918 y(or)f(to)h(represen)m(t)f(unde\014ned)d(pixels.)58 b(Generally)37 b(CFITSIO)d(will)j(scale)g(the)f(data)h(according)g(to)f (the)h(v)-5 b(alues)0 1031 y(of)35 b(the)f(BSCALE)g(and)g(BZER)m(O)h (\(or)g(TSCALn)d(and)i(TZER)m(On\))g(k)m(eyw)m(ords,)i(ho)m(w)m(ev)m (er)g(these)f(routines)f(ma)m(y)0 1144 y(b)s(e)e(used)h(to)h(o)m(v)m (erride)g(the)f(k)m(eyw)m(ord)h(v)-5 b(alues.)49 b(This)32 b(ma)m(y)i(b)s(e)f(useful)f(when)g(one)i(w)m(an)m(ts)f(to)h(read)f(or)g (write)h(the)0 1257 y(ra)m(w)e(unscaled)g(v)-5 b(alues)33 b(in)f(the)g(FITS)f(\014le.)47 b(Similarly)-8 b(,)33 b(CFITSIO)e(generally)i(uses)f(the)g(v)-5 b(alue)33 b(of)f(the)h(BLANK) 0 1370 y(or)40 b(TNULLn)f(k)m(eyw)m(ord)h(to)h(signify)e(an)h (unde\014ned)e(pixel,)43 b(but)c(these)h(routines)g(ma)m(y)g(b)s(e)f (used)g(to)i(o)m(v)m(erride)0 1483 y(this)32 b(v)-5 b(alue.)48 b(These)32 b(routines)g(do)h(not)f(create)i(or)f(mo)s(dify)e(the)i (corresp)s(onding)e(header)i(k)m(eyw)m(ord)f(v)-5 b(alues.)48 b(See)0 1596 y(App)s(endix)29 b(B)h(for)h(the)f(de\014nition)g(of)h (the)f(parameters)h(used)e(in)i(these)f(routines.)0 1827 y Fi(1)81 b Fj(Reset)26 b(the)g(scaling)g(factors)g(in)f(the)h(primary) f(arra)m(y)h(or)f(image)i(extension;)h(do)s(es)d(not)g(c)m(hange)i(the) f(BSCALE)227 1940 y(and)i(BZER)m(O)g(k)m(eyw)m(ord)h(v)-5 b(alues)28 b(and)g(only)g(a\013ects)i(the)e(automatic)j(scaling)e(p)s (erformed)e(when)g(the)h(data)227 2053 y(elemen)m(ts)f(are)f (written/read)g(to/from)g(the)g(FITS)f(\014le.)39 b(When)25 b(reading)h(from)f(a)h(FITS)f(\014le)g(the)h(returned)227 2166 y(data)i(v)-5 b(alue)28 b(=)f(\(the)h(v)-5 b(alue)28 b(giv)m(en)h(in)e(the)g(FITS)g(arra)m(y\))h(*)g(BSCALE)f(+)g(BZER)m(O.) g(The)g(in)m(v)m(erse)i(form)m(ula)227 2279 y(is)i(used)e(when)h (writing)g(data)h(v)-5 b(alues)31 b(to)g(the)f(FITS)g(\014le.)95 2511 y Fe(int)47 b(fits_set_bscale)d(/)j(ffpscl)286 2624 y(\(fitsfile)f(*fptr,)g(double)g(scale,)g(double)g(zero,)g(>)i(int)f (*status\))0 2856 y Fi(2)81 b Fj(Reset)39 b(the)f(scaling)i(parameters) e(for)h(a)f(table)h(column;)k(do)s(es)38 b(not)g(c)m(hange)i(the)e (TSCALn)f(or)h(TZER)m(On)227 2968 y(k)m(eyw)m(ord)29 b(v)-5 b(alues)29 b(and)e(only)i(a\013ects)g(the)g(automatic)h(scaling) f(p)s(erformed)e(when)g(the)i(data)g(elemen)m(ts)h(are)227 3081 y(written/read)i(to/from)g(the)g(FITS)f(\014le.)44 b(When)31 b(reading)g(from)g(a)h(FITS)f(\014le)g(the)h(returned)e(data) i(v)-5 b(alue)227 3194 y(=)25 b(\(the)i(v)-5 b(alue)26 b(giv)m(en)g(in)f(the)h(FITS)f(arra)m(y\))h(*)g(TSCAL)e(+)i(TZER)m(O.)e (The)h(in)m(v)m(erse)i(form)m(ula)f(is)f(used)g(when)227 3307 y(writing)31 b(data)g(v)-5 b(alues)30 b(to)i(the)e(FITS)g(\014le.) 95 3539 y Fe(int)47 b(fits_set_tscale)d(/)j(fftscl)286 3652 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(double)i(scale,)f(double)g (zero,)334 3765 y(>)i(int)e(*status\))0 3997 y Fi(3)81 b Fj(De\014ne)36 b(the)g(in)m(teger)i(v)-5 b(alue)36 b(to)h(b)s(e)e(used)h(to)h(signify)f(unde\014ned)e(pixels)i(in)g(the)g (primary)f(arra)m(y)i(or)f(image)227 4109 y(extension.)54 b(This)34 b(is)g(only)h(used)f(if)g(BITPIX)g(=)h(8,)h(16,)g(or)f(32.)54 b(This)34 b(do)s(es)g(not)h(create)h(or)e(c)m(hange)i(the)227 4222 y(v)-5 b(alue)31 b(of)g(the)f(BLANK)h(k)m(eyw)m(ord)g(in)f(the)g (header.)95 4454 y Fe(int)47 b(fits_set_imgnull)d(/)j(ffpnul)286 4567 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(nulval,)h(>)i(int)e(*status\))0 4799 y Fi(4)81 b Fj(De\014ne)36 b(the)g(string)g(to)g(b)s(e)f(used)g (to)i(signify)f(unde\014ned)e(pixels)i(in)f(a)h(column)g(in)g(an)f (ASCI)s(I)g(table.)58 b(This)227 4912 y(do)s(es)30 b(not)h(create)h(or) e(c)m(hange)i(the)e(v)-5 b(alue)31 b(of)g(the)f(TNULLn)g(k)m(eyw)m (ord.)95 5143 y Fe(int)47 b(fits_set_atblnull)c(/)48 b(ffsnul)286 5256 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(char)i (*nulstr,)f(>)h(int)g(*status\))0 5488 y Fi(5)81 b Fj(De\014ne)34 b(the)h(v)-5 b(alue)34 b(to)h(b)s(e)f(used)g(to)h(signify)f (unde\014ned)e(pixels)j(in)f(an)g(in)m(teger)i(column)e(in)g(a)g (binary)g(table)227 5601 y(\(where)29 b(TF)m(ORMn)f(=)g('B',)i('I',)f (or)f('J'\).)i(This)d(do)s(es)i(not)f(create)j(or)d(c)m(hange)i(the)e (v)-5 b(alue)29 b(of)g(the)g(TNULLn)227 5714 y(k)m(eyw)m(ord.)p eop end %%Page: 114 122 TeXDict begin 114 121 bop 0 299 a Fj(114)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_set_btblnull)c(/)48 b(fftnul)286 668 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h (nulval,)g(>)h(int)g(*status\))0 995 y Ff(9.5)135 b(Sp)t(ecialized)61 b(FITS)e(Primary)i(Arra)l(y)f(or)h(IMA)l(GE)e(Extension)j(I/O)306 1144 y(Routines)0 1394 y Fj(These)27 b(routines)h(read)f(or)h(write)g (data)g(v)-5 b(alues)28 b(in)g(the)f(primary)g(data)h(arra)m(y)h (\(i.e.,)g(the)f(\014rst)f(HDU)i(in)e(the)h(FITS)0 1507 y(\014le\))37 b(or)g(an)f(IMA)m(GE)h(extension.)60 b(Automatic)39 b(data)e(t)m(yp)s(e)g(con)m(v)m(ersion)g(is)g(p)s(erformed)e(for)h(if)h (the)g(data)g(t)m(yp)s(e)0 1620 y(of)c(the)g(FITS)f(arra)m(y)h(\(as)g (de\014ned)f(b)m(y)g(the)h(BITPIX)g(k)m(eyw)m(ord\))g(di\013ers)g(from) f(the)h(data)g(t)m(yp)s(e)g(of)g(the)g(arra)m(y)g(in)0 1733 y(the)c(calling)i(routine.)40 b(The)28 b(data)i(v)-5 b(alues)29 b(are)h(automatically)i(scaled)d(b)m(y)g(the)h(BSCALE)e(and) g(BZER)m(O)h(header)0 1846 y(v)-5 b(alues)25 b(as)h(they)f(are)g(b)s (eing)g(written)g(or)g(read)f(from)h(the)g(FITS)f(arra)m(y)-8 b(.)40 b(Unlik)m(e)26 b(the)f(basic)h(routines)e(describ)s(ed)g(in)0 1959 y(the)31 b(previous)g(c)m(hapter,)i(most)e(of)h(these)g(routines)f (sp)s(eci\014cally)h(supp)s(ort)d(the)j(FITS)e(random)h(groups)f (format.)0 2072 y(See)h(App)s(endix)d(B)j(for)f(the)h(de\014nition)f (of)g(the)h(parameters)g(used)e(in)h(these)h(routines.)0 2232 y(The)24 b(more)h(primitiv)m(e)h(reading)f(and)f(writing)h (routines)f(\(i.)40 b(e.,)26 b(\013ppr)p 2364 2232 28 4 v 32 w(,)g(\013ppn)p 2653 2232 V 31 w(,)g(\013ppn,)f(\013gp)m(v)p 3185 2232 V 33 w(,)h(or)f(\013gpf)p 3552 2232 V 32 w(\))g(simply)0 2345 y(treat)g(the)g(primary)e(arra)m(y)i(as)f(a)h(long)g (1-dimensional)g(arra)m(y)g(of)f(pixels,)i(ignoring)f(the)f(in)m (trinsic)h(dimensionalit)m(y)0 2458 y(of)30 b(the)g(arra)m(y)-8 b(.)42 b(When)30 b(dealing)h(with)e(a)i(2D)g(image,)g(for)f(example,)h (the)f(application)i(program)e(m)m(ust)g(calculate)0 2571 y(the)i(pixel)g(o\013set)g(in)f(the)h(1-D)h(arra)m(y)f(that)g (corresp)s(onds)e(to)i(an)m(y)g(particular)g(X,)g(Y)f(co)s(ordinate)i (in)e(the)g(image.)0 2684 y(C)25 b(programmers)h(should)f(note)h(that)g (the)h(ordering)e(of)h(arra)m(ys)g(in)g(FITS)f(\014les,)i(and)e(hence)h (in)g(all)g(the)g(CFITSIO)0 2797 y(calls,)40 b(is)d(more)g(similar)h (to)f(the)h(dimensionalit)m(y)g(of)f(arra)m(ys)g(in)g(F)-8 b(ortran)38 b(rather)f(than)f(C.)h(F)-8 b(or)38 b(instance)g(if)f(a)0 2910 y(FITS)28 b(image)i(has)e(NAXIS1)h(=)f(100)i(and)e(NAXIS2)h(=)f (50,)i(then)e(a)h(2-D)h(arra)m(y)f(just)f(large)i(enough)e(to)i(hold)e (the)0 3022 y(image)k(should)d(b)s(e)h(declared)h(as)f(arra)m (y[50][100])k(and)c(not)h(as)f(arra)m(y[100][50].)0 3183 y(F)-8 b(or)30 b(con)m(v)m(enience,)i(higher-lev)m(el)g(routines)d(are) h(also)h(pro)m(vided)e(to)h(sp)s(eci\014cally)h(deal)f(with)f(2D)i (images)f(\(\013p2d)p 3872 3183 V 0 3296 a(and)c(\013g2d)p 372 3296 V 33 w(\))h(and)f(3D)i(data)f(cub)s(es)f(\(\013p3d)p 1467 3296 V 59 w(and)g(\013g3d)p 1893 3296 V 33 w(\).)40 b(The)26 b(dimensionalit)m(y)i(of)f(the)g(FITS)f(image)i(is)e(passed)0 3408 y(b)m(y)36 b(the)h(naxis1,)h(naxis2,)h(and)d(naxis3)h(parameters)f (and)g(the)h(declared)f(dimensions)g(of)h(the)f(program)g(arra)m(y)0 3521 y(are)30 b(passed)g(in)f(the)h(dim1)g(and)f(dim2)h(parameters.)41 b(Note)31 b(that)f(the)g(dimensions)f(of)h(the)g(program)g(arra)m(y)g (ma)m(y)0 3634 y(b)s(e)35 b(larger)h(than)f(the)h(dimensions)f(of)h (the)g(FITS)e(arra)m(y)-8 b(.)58 b(F)-8 b(or)36 b(example)g(if)g(a)g (FITS)e(image)j(with)e(NAXIS1)h(=)0 3747 y(NAXIS2)g(=)g(400)h(is)f (read)g(in)m(to)h(a)g(program)f(arra)m(y)g(whic)m(h)g(is)g(dimensioned) f(as)i(512)g(x)f(512)h(pixels,)h(then)e(the)0 3860 y(image)g(will)f (just)f(\014ll)g(the)h(lo)m(w)m(er)h(left)f(corner)f(of)h(the)g(arra)m (y)g(with)f(pixels)h(in)f(the)h(range)g(1)g(-)g(400)g(in)g(the)f(X)h (an)0 3973 y(Y)g(directions.)54 b(This)34 b(has)h(the)g(e\013ect)h(of)f (taking)g(a)h(con)m(tiguous)f(set)h(of)f(pixel)g(v)-5 b(alue)35 b(in)f(the)h(FITS)f(arra)m(y)i(and)0 4086 y(writing)30 b(them)g(to)h(a)f(non-con)m(tiguous)h(arra)m(y)g(in)e(program)h(memory) g(\(i.e.,)i(there)e(are)h(no)m(w)f(some)g(blank)g(pixels)0 4199 y(around)f(the)i(edge)g(of)g(the)f(image)i(in)e(the)g(program)g (arra)m(y\).)0 4359 y(The)k(most)i(general)f(set)h(of)f(routines)f (\(\013pss)p 1560 4359 V 33 w(,)i(\013gsv)p 1836 4359 V 33 w(,)g(and)e(\013gsf)p 2273 4359 V 33 w(\))h(ma)m(y)h(b)s(e)e(used) g(to)h(transfer)g(a)g(rectangular)0 4472 y(subset)27 b(of)h(the)g(pixels)f(in)h(a)g(FITS)f(N-dimensional)h(image)h(to)f(or)g (from)f(an)g(arra)m(y)i(whic)m(h)e(has)g(b)s(een)g(declared)h(in)0 4585 y(the)h(calling)h(program.)40 b(The)28 b(fpixel)h(and)f(lpixel)h (parameters)g(are)g(in)m(teger)h(arra)m(ys)f(whic)m(h)f(sp)s(ecify)g (the)h(starting)0 4698 y(and)k(ending)f(pixel)i(co)s(ordinate)g(in)f (eac)m(h)h(dimension)f(\(starting)h(with)f(1,)h(not)g(0\))g(of)f(the)g (FITS)g(image)h(that)g(is)0 4811 y(to)f(b)s(e)e(read)g(or)h(written.)45 b(It)32 b(is)g(imp)s(ortan)m(t)g(to)h(note)f(that)h(these)f(are)g(the)g (starting)h(and)e(ending)g(pixels)h(in)g(the)0 4924 y(FITS)i(image,)k (not)d(in)f(the)h(declared)h(arra)m(y)f(in)f(the)h(program.)54 b(The)35 b(arra)m(y)g(parameter)g(in)g(these)g(routines)g(is)0 5036 y(treated)f(simply)e(as)h(a)f(large)i(one-dimensional)g(arra)m(y)f (of)f(the)h(appropriate)g(data)g(t)m(yp)s(e)g(con)m(taining)h(the)f (pixel)0 5149 y(v)-5 b(alues;)37 b(The)d(pixel)h(v)-5 b(alues)35 b(in)g(the)f(FITS)g(arra)m(y)h(are)g(read/written)g(from/to) h(this)e(program)h(arra)m(y)g(in)f(strict)0 5262 y(sequence)d(without)f (an)m(y)h(gaps;)g(it)g(is)f(up)f(to)j(the)e(calling)i(routine)e(to)i (correctly)f(in)m(terpret)g(the)g(dimensionalit)m(y)0 5375 y(of)d(this)f(arra)m(y)-8 b(.)41 b(The)27 b(t)m(w)m(o)i(FITS)e (reading)h(routines)f(\(\013gsv)p 2018 5375 V 61 w(and)g(\013gsf)p 2415 5375 V 61 w(\))h(also)g(ha)m(v)m(e)h(an)f(`inc')g(parameter)g (whic)m(h)0 5488 y(de\014nes)33 b(the)h(data)h(sampling)f(in)m(terv)-5 b(al)36 b(in)d(eac)m(h)j(dimension)d(of)h(the)h(FITS)e(arra)m(y)-8 b(.)53 b(F)-8 b(or)35 b(example,)h(if)e(inc[0]=2)0 5601 y(and)i(inc[1]=3)j(when)d(reading)h(a)g(2-dimensional)h(FITS)e(image,) 41 b(then)36 b(only)h(ev)m(ery)h(other)f(pixel)h(in)e(the)i(\014rst)0 5714 y(dimension)30 b(and)g(ev)m(ery)h(3rd)f(pixel)g(in)g(the)h(second) f(dimension)g(will)h(b)s(e)f(returned)f(to)i(the)f('arra)m(y')i (parameter.)p eop end %%Page: 115 123 TeXDict begin 115 122 bop 0 299 a Fh(9.5.)72 b(SPECIALIZED)29 b(FITS)g(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)32 b(OR)d(IMA)m(GE)j(EXTENSION) d(I/O)h(R)m(OUTINES)80 b Fj(115)0 555 y(Tw)m(o)29 b(t)m(yp)s(es)h(of)f (routines)g(are)h(pro)m(vided)e(to)i(read)f(the)h(data)g(arra)m(y)f (whic)m(h)g(di\013er)g(in)g(the)h(w)m(a)m(y)g(unde\014ned)d(pixels)0 668 y(are)38 b(handled.)60 b(The)37 b(\014rst)g(t)m(yp)s(e)g(of)g (routines)h(\(e.g.,)i(\013gp)m(v)p 2059 668 28 4 v 34 w(\))d(simply)g(return)f(an)h(arra)m(y)h(of)g(data)g(elemen)m(ts)g(in)0 781 y(whic)m(h)30 b(unde\014ned)f(pixels)h(are)h(set)g(equal)g(to)h(a)f (v)-5 b(alue)31 b(sp)s(eci\014ed)e(b)m(y)i(the)g(user)e(in)i(the)f(`n)m (ulv)-5 b(al')32 b(parameter.)41 b(An)0 894 y(additional)30 b(feature)f(of)g(these)h(routines)e(is)h(that)h(if)f(the)g(user)f(sets) h(n)m(ulv)-5 b(al)29 b(=)g(0,)h(then)e(no)h(c)m(hec)m(ks)h(for)f (unde\014ned)0 1007 y(pixels)c(will)g(b)s(e)g(p)s(erformed,)f(th)m(us)h (reducing)f(the)h(amoun)m(t)h(of)f(CPU)f(pro)s(cessing.)39 b(The)24 b(second)h(t)m(yp)s(e)g(of)g(routines)0 1120 y(\(e.g.,)36 b(\013gpf)p 413 1120 V 32 w(\))e(returns)e(the)i(data)g (elemen)m(t)g(arra)m(y)g(and,)g(in)f(addition,)h(a)g(c)m(har)g(arra)m (y)f(that)h(indicates)h(whether)0 1233 y(the)f(v)-5 b(alue)34 b(of)g(the)f(corresp)s(onding)g(data)h(pixel)g(is)g(unde\014ned)d(\(=)j (1\))g(or)g(de\014ned)e(\(=)i(0\).)51 b(The)33 b(latter)i(t)m(yp)s(e)f (of)0 1346 y(routines)d(ma)m(y)h(b)s(e)e(more)i(con)m(v)m(enien)m(t)h (to)f(use)f(in)g(some)g(circumstances,)i(ho)m(w)m(ev)m(er,)g(it)e (requires)g(an)g(additional)0 1458 y(arra)m(y)g(of)f(logical)j(v)-5 b(alues)31 b(whic)m(h)f(can)h(b)s(e)e(un)m(wieldy)h(when)g(w)m(orking)g (with)g(large)i(data)f(arra)m(ys.)0 1695 y Fi(1)81 b Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(the)g(FITS)f(data)h(arra)m (y)-8 b(.)95 1932 y Fe(int)47 b(fits_write_img)d(/)k(ffppr)286 2045 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(LONGLONG)g(firstelem,)g (LONGLONG)h(nelements,)334 2158 y(DTYPE)g(*array,)g(int)h(*status\);)95 2384 y(int)g(fits_write_img_[byt,)c(sht,)j(usht,)h(int,)f(uint,)h(lng,) f(ulng,)h(lnglng,)e(ulnglng,)h(flt,)h(dbl])f(/)286 2497 y(ffppr[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o(])286 2610 y(\(fitsfile)g(*fptr,)g(long)g(group,)g(LONGLONG)g(firstelem,)f (LONGLONG)h(nelements,)334 2723 y(DTYPE)g(*array,)g(>)i(int)f (*status\);)95 2949 y(int)g(fits_write_imgnull)c(/)48 b(ffppn)286 3061 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(LONGLONG)g (firstelem,)g(LONGLONG)h(nelements,)334 3174 y(DTYPE)g(*array,)g(DTYPE) h(*nulval,)e(>)j(int)f(*status\);)95 3400 y(int)g (fits_write_imgnull_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f (ulng,)h(lnglng,)e(ulnglng,)h(flt,)h(dbl])f(/)286 3513 y(ffppn[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o(])286 3626 y(\(fitsfile)g(*fptr,)g(long)g(group,)g(LONGLONG)g(firstelem,)525 3739 y(LONGLONG)g(nelements,)f(DTYPE)h(*array,)g(DTYPE)g(nulval,)g(>)h (int)g(*status\);)0 3976 y Fi(2)81 b Fj(Set)30 b(data)h(arra)m(y)g (elemen)m(ts)h(as)e(unde\014ned.)95 4213 y Fe(int)47 b(fits_write_img_null)c(/)k(ffppru)286 4326 y(\(fitsfile)f(*fptr,)g (long)g(group,)g(LONGLONG)g(firstelem,)f(LONGLONG)h(nelements,)334 4439 y(>)i(int)e(*status\))0 4675 y Fi(3)81 b Fj(W)-8 b(rite)32 b(v)-5 b(alues)30 b(in)m(to)i(group)e(parameters.)42 b(This)30 b(routine)g(only)h(applies)g(to)g(the)g(`Random)f(Group)s (ed')g(FITS)227 4788 y(format)22 b(whic)m(h)f(has)g(b)s(een)f(used)h (for)g(applications)h(in)f(radio)h(in)m(terferometry)-8 b(,)25 b(but)20 b(is)h(o\016cially)i(deprecated)227 4901 y(for)30 b(future)g(use.)95 5138 y Fe(int)47 b(fits_write_grppar_[byt,) 42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(ulnglng,)f (flt,)i(dbl])f(/)286 5251 y(ffpgp[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o (])286 5364 y(\(fitsfile)g(*fptr,)g(long)g(group,)g(long)h(firstelem,)e (long)i(nelements,)334 5477 y(>)h(DTYPE)e(*array,)g(int)h(*status\))0 5714 y Fi(4)81 b Fj(W)-8 b(rite)31 b(a)g(2-D)h(or)e(3-D)h(image)h(in)m (to)f(the)g(data)g(arra)m(y)-8 b(.)p eop end %%Page: 116 124 TeXDict begin 116 123 bop 0 299 a Fj(116)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_write_2d_[byt,)c(sht,)k(usht,)f (int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(ulnglng,)f(flt,)i(dbl])g(/)286 668 y(ffp2d[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o(])286 781 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(dim1,)g (LONGLONG)g(naxis1,)334 894 y(LONGLONG)g(naxis2,)f(DTYPE)i(*array,)f(>) h(int)g(*status\))95 1120 y(int)g(fits_write_3d_[byt,)c(sht,)k(usht,)f (int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(ulnglng,)f(flt,)i(dbl])g(/)286 1233 y(ffp3d[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o(])286 1346 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(dim1,)g (LONGLONG)g(dim2,)g(LONGLONG)g(naxis1,)334 1458 y(LONGLONG)g(naxis2,)f (LONGLONG)h(naxis3,)g(DTYPE)g(*array,)g(>)h(int)g(*status\))0 1716 y Fi(5)81 b Fj(W)-8 b(rite)31 b(an)g(arbitrary)f(data)h (subsection)f(in)m(to)i(the)e(data)h(arra)m(y)-8 b(.)95 1974 y Fe(int)47 b(fits_write_subset_[byt,)42 b(sht,)k(usht,)h(int,)f (uint,)h(lng,)f(ulng,)h(lnglng,)f(ulnglng,)f(flt,)i(dbl])f(/)286 2087 y(ffpss[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o(])286 2199 y(\(fitsfile)g(*fptr,)g(long)g(group,)g(long)h(naxis,)f(long)h (*naxes,)334 2312 y(long)g(*fpixel,)e(long)i(*lpixel,)e(DTYPE)i (*array,)f(>)h(int)g(*status\))0 2570 y Fi(6)81 b Fj(Read)30 b(elemen)m(ts)i(from)e(the)g(FITS)g(data)h(arra)m(y)-8 b(.)95 2828 y Fe(int)47 b(fits_read_img)e(/)i(ffgpv)286 2940 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(firstelem,) f(long)i(nelements,)334 3053 y(DTYPE)f(*nulval,)g(>)h(DTYPE)g(*array,)f (int)h(*anynul,)e(int)i(*status\))95 3279 y(int)g(fits_read_img_[byt,)c (sht,)k(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(ulnglng,)f (flt,)i(dbl])g(/)286 3392 y(ffgpv[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o (])286 3505 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(firstelem,)e (long)i(nelements,)334 3618 y(DTYPE)f(nulval,)g(>)i(DTYPE)e(*array,)g (int)h(*anynul,)e(int)i(*status\))95 3844 y(int)g(fits_read_imgnull)c (/)48 b(ffgpf)286 3957 y(\(fitsfile)e(*fptr,)g(int)94 b(datatype,)46 b(long)g(firstelem,)f(long)i(nelements,)334 4070 y(>)h(DTYPE)e(*array,)g(char)g(*nullarray,)f(int)i(*anynul,)f(int) g(*status\))95 4295 y(int)95 b(fits_read_imgnull_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)e(ulnglng,)h (flt,)h(dbl])f(/)334 4408 y(ffgpf[b,i,ui,k,uk,j,uj,jj)o(,uj)o(j,e,)o (d])334 4521 y(\(fitsfile)f(*fptr,)h(long)h(group,)f(long)h(firstelem,) e(long)h(nelements,)334 4634 y(>)i(DTYPE)e(*array,)g(char)g (*nullarray,)f(int)i(*anynul,)f(int)g(*status\))0 4892 y Fi(7)81 b Fj(Read)29 b(v)-5 b(alues)31 b(from)e(group)g(parameters.) 41 b(This)29 b(routine)g(only)h(applies)g(to)h(the)e(`Random)h(Group)s (ed')f(FITS)227 5005 y(format)22 b(whic)m(h)f(has)g(b)s(een)f(used)h (for)g(applications)h(in)f(radio)h(in)m(terferometry)-8 b(,)25 b(but)20 b(is)h(o\016cially)i(deprecated)227 5118 y(for)30 b(future)g(use.)95 5375 y Fe(int)95 b(fits_read_grppar_[byt,) 42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(ulnglng,)f (flt,)i(dbl])f(/)334 5488 y(ffggp[b,i,ui,k,uk,j,uj,jj)o(,uj)o(j,e,)o (d])334 5601 y(\(fitsfile)f(*fptr,)h(long)h(group,)f(long)h(firstelem,) e(long)h(nelements,)334 5714 y(>)i(DTYPE)e(*array,)g(int)h(*status\))p eop end %%Page: 117 125 TeXDict begin 117 124 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(117)0 555 y Fi(8)81 b Fj(Read)37 b(2-D)h(or)g(3-D)g(image)g(from)f(the)g(data)h(arra)m(y)-8 b(.)62 b(Unde\014ned)36 b(pixels)i(in)e(the)i(arra)m(y)g(will)f(b)s(e)g (set)g(equal)227 668 y(to)32 b(the)g(v)-5 b(alue)31 b(of)h('n)m(ulv)-5 b(al',)32 b(unless)f(n)m(ulv)-5 b(al=0)31 b(in)g(whic)m(h)g(case)h(no)f (testing)i(for)e(unde\014ned)e(pixels)i(will)h(b)s(e)227 781 y(p)s(erformed.)95 1049 y Fe(int)95 b(fits_read_2d_[byt,)43 b(sht,)k(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(ulnglng,)f (flt,)i(dbl])g(/)334 1162 y(ffg2d[b,i,ui,k,uk,j,uj,jj)o(,uj)o(j,e,)o (d])334 1275 y(\(fitsfile)e(*fptr,)h(long)h(group,)f(DTYPE)h(nulval,)e (LONGLONG)h(dim1,)g(LONGLONG)g(naxis1,)334 1387 y(LONGLONG)g(naxis2,)f (>)j(DTYPE)e(*array,)g(int)h(*anynul,)f(int)g(*status\))95 1613 y(int)95 b(fits_read_3d_[byt,)43 b(sht,)k(usht,)f(int,)h(uint,)f (lng,)h(ulng,)f(lnglng,)g(ulnglng,)f(flt,)i(dbl])g(/)334 1726 y(ffg3d[b,i,ui,k,uk,j,uj,jj)o(,uj)o(j,e,)o(d])334 1839 y(\(fitsfile)e(*fptr,)h(long)h(group,)f(DTYPE)h(nulval,)e (LONGLONG)h(dim1,)334 1952 y(LONGLONG)g(dim2,)g(LONGLONG)g(naxis1,)f (LONGLONG)h(naxis2,)g(LONGLONG)f(naxis3,)334 2065 y(>)j(DTYPE)e (*array,)g(int)h(*anynul,)e(int)i(*status\))0 2333 y Fi(9)81 b Fj(Read)30 b(an)g(arbitrary)h(data)g(subsection)f(from)g(the) g(data)i(arra)m(y)-8 b(.)95 2600 y Fe(int)95 b(fits_read_subset_[byt,) 42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(ulnglng,)f (flt,)i(dbl])f(/)334 2713 y(ffgsv[b,i,ui,k,uk,j,uj,jj)o(,uj)o(j,e,)o (d])334 2826 y(\(fitsfile)f(*fptr,)h(int)h(group,)f(int)h(naxis,)f (long)h(*naxes,)334 2939 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i (*inc,)f(DTYPE)h(nulval,)334 3052 y(>)h(DTYPE)e(*array,)g(int)h (*anynul,)e(int)i(*status\))95 3278 y(int)95 b (fits_read_subsetnull_[byt)o(,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,) f(ulng,)h(lnglng,)f(ulnglng,)f(flt,)i(dbl])f(/)334 3391 y(ffgsf[b,i,ui,k,uk,j,uj,jj)o(,uj)o(j,e,)o(d])334 3504 y(\(fitsfile)f(*fptr,)h(int)h(group,)f(int)h(naxis,)f(long)h(*naxes,) 334 3617 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f(>)i (DTYPE)e(*array,)334 3730 y(char)h(*nullarray,)d(int)j(*anynul,)f(int)h (*status\))0 4073 y Ff(9.6)135 b(Sp)t(ecialized)46 b(FITS)e(ASCI)t(I)g (and)g(Binary)h(T)-11 b(able)45 b(Routines)0 4328 y Fd(9.6.1)112 b(General)39 b(Column)f(Routines)0 4543 y Fi(1)81 b Fj(Get)31 b(information)f(ab)s(out)g(an)g(existing)h(ASCI)s(I)d(or)i(binary)f (table)i(column.)41 b(A)30 b(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)h(b)s(e)e (giv)m(en)227 4656 y(for)40 b(an)m(y)h(of)f(the)h(output)f(parameters)g (that)h(are)g(not)f(needed.)70 b(D)m(A)-8 b(T)g(A)g(TYPE)42 b(is)e(a)h(c)m(haracter)h(string)227 4769 y(whic)m(h)d(returns)e(the)i (data)g(t)m(yp)s(e)g(of)g(the)f(column)h(as)g(de\014ned)e(b)m(y)i(the)f (TF)m(ORMn)h(k)m(eyw)m(ord)g(\(e.g.,)j('I',)227 4882 y('J','E',)28 b('D',)g(etc.\).)41 b(In)27 b(the)g(case)g(of)g(an)g (ASCI)s(I)f(c)m(haracter)i(column,)g(t)m(yp)s(eco)s(de)f(will)g(ha)m(v) m(e)h(a)f(v)-5 b(alue)28 b(of)f(the)227 4994 y(form)g('An')g(where)f ('n')h(is)g(an)g(in)m(teger)i(expressing)d(the)h(width)g(of)g(the)g (\014eld)g(in)f(c)m(haracters.)41 b(F)-8 b(or)28 b(example,)227 5107 y(if)g(TF)m(ORM)h(=)e('160A8')k(then)d(\013gb)s(cl)g(will)g (return)f(t)m(yp)s(ec)m(har='A8')j(and)d(rep)s(eat=20.)41 b(All)29 b(the)f(returned)227 5220 y(parameters)j(are)g(scalar)g(quan)m (tities.)95 5488 y Fe(int)47 b(fits_get_acolparms)c(/)48 b(ffgacl)191 5601 y(\(fitsfile)d(*fptr,)h(int)h(colnum,)f(>)h(char)g (*ttype,)f(long)h(*tbcol,)239 5714 y(char)f(*tunit,)g(char)h(*tform,)f (double)g(*scale,)f(double)i(*zero,)p eop end %%Page: 118 126 TeXDict begin 118 125 bop 0 299 a Fj(118)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)239 555 y Fe(char)46 b(*nulstr,)g(char)g(*tdisp,)g(int)h (*status\))95 781 y(int)g(fits_get_bcolparms)c(/)48 b(ffgbcl)286 894 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(char)f(*ttype,)e(char)i (*tunit,)334 1007 y(char)g(*typechar,)e(long)h(*repeat,)g(double)g (*scale,)g(double)g(*zero,)334 1120 y(long)h(*nulval,)e(char)i(*tdisp,) f(int)94 b(*status\))95 1346 y(int)47 b(fits_get_bcolparmsll)c(/)k (ffgbclll)286 1458 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(char)f (*ttype,)e(char)i(*tunit,)334 1571 y(char)g(*typechar,)e(LONGLONG)g (*repeat,)h(double)g(*scale,)g(double)g(*zero,)334 1684 y(LONGLONG)g(*nulval,)f(char)i(*tdisp,)f(int)94 b(*status\))0 1937 y Fi(2)81 b Fj(Return)27 b(optimal)i(n)m(um)m(b)s(er)e(of)h(ro)m (ws)g(to)h(read)f(or)g(write)g(at)h(one)f(time)h(for)f(maxim)m(um)g (I/O)f(e\016ciency)-8 b(.)42 b(Refer)227 2050 y(to)25 b(the)g(\\Optimizing)g(Co)s(de")f(section)i(in)e(Chapter)g(5)g(for)g (more)h(discussion)f(on)g(ho)m(w)g(to)h(use)f(this)h(routine.)95 2416 y Fe(int)47 b(fits_get_rowsize)d(/)j(ffgrsz)286 2529 y(\(fitsfile)f(*fptr,)g(long)g(*nrows,)g(*status\))0 2782 y Fi(3)81 b Fj(De\014ne)22 b(the)g(zero)i(indexed)d(b)m(yte)i (o\013set)g(of)g(the)f('heap')h(measured)e(from)h(the)h(start)g(of)f (the)g(binary)g(table)h(data.)227 2895 y(By)30 b(default)g(the)f(heap)h (is)f(assumed)g(to)h(start)g(immediately)h(follo)m(wing)g(the)f (regular)f(table)i(data,)f(i.e.,)h(at)227 3008 y(lo)s(cation)38 b(NAXIS1)f(x)g(NAXIS2.)59 b(This)36 b(routine)g(is)h(only)f(relev)-5 b(an)m(t)38 b(for)e(binary)g(tables)h(whic)m(h)g(con)m(tain)227 3121 y(v)-5 b(ariable)25 b(length)g(arra)m(y)g(columns)f(\(with)g(TF)m (ORMn)g(=)g('Pt'\).)40 b(This)23 b(routine)i(also)g(automatically)i (writes)227 3234 y(the)35 b(v)-5 b(alue)35 b(of)g(theap)f(to)h(a)g(k)m (eyw)m(ord)g(in)g(the)f(extension)h(header.)53 b(This)34 b(routine)g(m)m(ust)h(b)s(e)f(called)h(after)227 3347 y(the)c(required)e(k)m(eyw)m(ords)h(ha)m(v)m(e)i(b)s(een)d(written)h (\(with)g(\013ph)m(bn\))f(but)h(b)s(efore)f(an)m(y)i(data)g(is)f (written)g(to)h(the)227 3460 y(table.)95 3713 y Fe(int)47 b(fits_write_theap)d(/)j(ffpthp)286 3826 y(\(fitsfile)f(*fptr,)g(long)g (theap,)g(>)i(int)f(*status\))0 4079 y Fi(4)81 b Fj(T)-8 b(est)37 b(the)f(con)m(ten)m(ts)i(of)f(the)g(binary)e(table)j(v)-5 b(ariable)37 b(arra)m(y)g(heap,)h(returning)e(the)g(size)h(of)g(the)g (heap,)h(the)227 4192 y(n)m(um)m(b)s(er)30 b(of)h(un)m(used)e(b)m(ytes) j(that)f(are)g(not)g(curren)m(tly)g(p)s(oin)m(ted)g(to)h(b)m(y)e(an)m (y)i(of)f(the)g(descriptors,)g(and)f(the)227 4304 y(n)m(um)m(b)s(er)d (of)h(b)m(ytes)h(whic)m(h)f(are)g(p)s(oin)m(ted)g(to)h(b)m(y)f(m)m (ultiple)h(descriptors.)40 b(It)28 b(also)h(returns)e(v)-5 b(alid)29 b(=)e(F)-10 b(ALSE)227 4417 y(if)31 b(an)m(y)f(of)h(the)f (descriptors)h(p)s(oin)m(t)f(to)h(in)m(v)-5 b(alid)31 b(addresses)f(out)g(of)h(range)g(of)f(the)h(heap.)95 4670 y Fe(int)47 b(fits_test_heap)d(/)k(fftheap)286 4783 y(\(fitsfile)e(*fptr,)g(>)h(LONGLONG)f(*heapsize,)f(LONGLONG)g (*unused,)h(LONGLONG)f(*overlap,)334 4896 y(int)i(*validheap,)e(int)i (*status\))0 5149 y Fi(5)81 b Fj(Re-pac)m(k)33 b(the)f(v)m(ectors)h(in) e(the)h(binary)f(table)i(v)-5 b(ariable)32 b(arra)m(y)g(heap)g(to)g (reco)m(v)m(er)i(an)m(y)e(un)m(used)e(space.)45 b(Nor-)227 5262 y(mally)-8 b(,)40 b(when)d(a)g(v)m(ector)i(in)e(a)g(v)-5 b(ariable)38 b(length)g(arra)m(y)f(column)g(is)g(rewritten)h(the)f (previously)g(written)227 5375 y(arra)m(y)d(remains)e(in)h(the)g(heap)f (as)h(w)m(asted)h(un)m(used)d(space.)49 b(This)32 b(routine)g(will)i (repac)m(k)f(the)g(arra)m(ys)g(that)227 5488 y(are)h(still)g(in)f(use,) h(th)m(us)f(eliminating)h(an)m(y)g(b)m(ytes)g(in)f(the)g(heap)g(that)h (are)g(no)f(longer)h(in)f(use.)49 b(Note)34 b(that)227 5601 y(if)f(sev)m(eral)h(v)m(ectors)g(p)s(oin)m(t)e(to)i(the)e(same)h (b)m(ytes)g(in)g(the)f(heap,)i(then)e(this)g(routine)h(will)g(mak)m(e)g (duplicate)227 5714 y(copies)e(of)g(the)g(b)m(ytes)f(for)h(eac)m(h)g(v) m(ector,)h(whic)m(h)e(will)h(actually)h(expand)e(the)g(size)i(of)e(the) h(heap.)p eop end %%Page: 119 127 TeXDict begin 119 126 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(119)95 555 y Fe(int)47 b(fits_compress_heap)c(/) 48 b(ffcmph)286 668 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 953 y Fd(9.6.2)112 b(Lo)m(w-Lev)m(el)39 b(T)-9 b(able)38 b(Access)f(Routines)0 1172 y Fj(The)g(follo)m(wing)j(2)e(routines)f (pro)m(vide)h(lo)m(w-lev)m(el)j(access)e(to)g(the)f(data)g(in)g(ASCI)s (I)e(or)i(binary)f(tables)h(and)g(are)0 1285 y(mainly)29 b(useful)f(as)i(an)f(e\016cien)m(t)h(w)m(a)m(y)g(to)g(cop)m(y)g(all)g (or)f(part)g(of)g(a)g(table)h(from)f(one)g(lo)s(cation)i(to)f(another.) 40 b(These)0 1397 y(routines)24 b(simply)g(read)g(or)h(write)f(the)h (sp)s(eci\014ed)e(n)m(um)m(b)s(er)g(of)i(consecutiv)m(e)h(b)m(ytes)f (in)f(an)g(ASCI)s(I)f(or)h(binary)g(table,)0 1510 y(without)g(regard)g (for)f(column)h(b)s(oundaries)e(or)i(the)g(ro)m(w)g(length)g(in)f(the)h (table.)40 b(These)23 b(routines)h(do)f(not)h(p)s(erform)0 1623 y(an)m(y)36 b(mac)m(hine)h(dep)s(enden)m(t)e(data)i(con)m(v)m (ersion)g(or)g(b)m(yte)f(sw)m(apping.)58 b(See)36 b(App)s(endix)e(B)j (for)f(the)g(de\014nition)g(of)0 1736 y(the)31 b(parameters)f(used)g (in)g(these)h(routines.)0 1958 y Fi(1)81 b Fj(Read)30 b(or)h(write)f(a)h(consecutiv)m(e)h(arra)m(y)f(of)g(b)m(ytes)f(from)g (an)h(ASCI)s(I)d(or)j(binary)e(table)95 2179 y Fe(int)47 b(fits_read_tblbytes)c(/)48 b(ffgtbb)286 2292 y(\(fitsfile)e(*fptr,)g (LONGLONG)f(firstrow,)h(LONGLONG)f(firstchar,)g(LONGLONG)h(nchars,)334 2405 y(>)i(unsigned)d(char)i(*values,)e(int)i(*status\))95 2631 y(int)g(fits_write_tblbytes)c(/)k(ffptbb)286 2744 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(firstrow,)h(LONGLONG)f(firstchar,)g (LONGLONG)h(nchars,)334 2857 y(unsigned)g(char)g(*values,)g(>)h(int)g (*status\))0 3141 y Fd(9.6.3)112 b(W)-9 b(rite)37 b(Column)h(Data)g (Routines)0 3360 y Fj(This)33 b(subsection)h(describ)s(es)g(sp)s (ecialized)h(routines)f(for)g(writing)g(data)g(to)h(FITS)e(tables.)53 b(Please)35 b(see)g(section)0 3473 y(9.6.4)d(\(\\Read)g(Column)d(Data)j (Routines"\))f(for)g(more)f(information)h(ab)s(out)f(ho)m(w)g(v)-5 b(alues)31 b(are)g(stored)f(in)g(C.)0 3695 y Fi(1)81 b Fj(W)-8 b(rite)28 b(elemen)m(ts)h(in)m(to)f(an)g(ASCI)s(I)d(or)j (binary)e(table)j(column)e(\(in)g(the)h(CDU\).)g(The)f(data)h(t)m(yp)s (e)f(of)h(the)f(arra)m(y)227 3807 y(is)k(implied)f(b)m(y)g(the)h (su\016x)e(of)i(the)f(routine)h(name.)95 4029 y Fe(int)47 b(fits_write_col_str)c(/)48 b(ffpcls)286 4142 y(\(fitsfile)e(*fptr,)g (int)h(colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG)h(firstelem,)334 4255 y(LONGLONG)g(nelements,)f(char)h(**array,)g(>)h(int)g(*status\))95 4481 y(int)g(fits_write_col_[log,byt,sh)o(t,u)o(sht,)o(int,)o(uin)o (t,ln)o(g,ul)o(ng,)o(lngl)o(ng,u)o(lng)o(lng,)o(flt,)o(dbl)o(,cmp)o (,dbl)o(cmp)o(])42 b(/)286 4593 y(ffpcl[l,b,i,ui,k,uk,j,uj,j)o(j,u)o (jj,e)o(,d,c)o(,m])286 4706 y(\(fitsfile)k(*fptr,)g(int)h(colnum,)e (LONGLONG)h(firstrow,)525 4819 y(LONGLONG)g(firstelem,)f(LONGLONG)g (nelements,)g(DTYPE)h(*array,)g(>)i(int)f(*status\))0 5041 y Fi(2)81 b Fj(W)-8 b(rite)36 b(elemen)m(ts)h(in)m(to)g(an)e(ASCI) s(I)f(or)i(binary)e(table)j(column)e(substituting)g(the)h(appropriate)f (FITS)g(n)m(ull)227 5154 y(v)-5 b(alue)31 b(for)f(an)m(y)h(elemen)m(ts) h(that)f(are)f(equal)h(to)g(the)g(n)m(ulv)-5 b(al)31 b(parameter.)95 5375 y Fe(int)47 b(fits_write_colnull_[log,)42 b(byt,)k(sht,)h(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g (ulnglng,)g(flt,)g(dbl])h(/)286 5488 y(ffpcn[l,b,i,ui,k,uk,j,uj,j)o (j,u)o(jj,e)o(,d])286 5601 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e (LONGLONG)h(firstrow,)f(LONGLONG)h(firstelem,)334 5714 y(LONGLONG)g(nelements,)f(DTYPE)h(*array,)g(DTYPE)g(nulval,)g(>)h(int)g (*status\))p eop end %%Page: 120 128 TeXDict begin 120 127 bop 0 299 a Fj(120)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(3)81 b Fj(W)-8 b(rite)27 b(string)g(elemen)m (ts)h(in)m(to)f(a)g(binary)f(table)h(column)f(\(in)h(the)f(CDU\))i (substituting)e(the)g(FITS)g(n)m(ull)g(v)-5 b(alue)227 668 y(for)30 b(an)m(y)h(elemen)m(ts)h(that)f(are)g(equal)f(to)i(the)e (n)m(ulstr)g(string.)95 921 y Fe(int)47 b(fits_write_colnull_str)42 b(/)48 b(ffpcns)286 1034 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e (LONGLONG)h(firstrow,)f(LONGLONG)h(firstelem,)334 1147 y(LONGLONG)g(nelements,)f(char)h(**array,)g(char)g(*nulstr,)g(>)h(int)g (*status\))0 1399 y Fi(4)81 b Fj(W)-8 b(rite)34 b(bit)f(v)-5 b(alues)33 b(in)m(to)h(a)g(binary)e(b)m(yte)h(\('B'\))i(or)e(bit)g (\('X'\))h(table)g(column)f(\(in)g(the)g(CDU\).)h(Larra)m(y)f(is)g(an) 227 1512 y(arra)m(y)25 b(of)g(c)m(haracters)h(corresp)s(onding)e(to)h (the)g(sequence)g(of)f(bits)h(to)g(b)s(e)f(written.)39 b(If)24 b(an)g(elemen)m(t)i(of)f(larra)m(y)227 1625 y(is)k(true)g (\(not)h(equal)f(to)h(zero\))g(then)f(the)g(corresp)s(onding)f(bit)h (in)g(the)g(FITS)f(table)i(is)f(set)h(to)g(1,)g(otherwise)227 1738 y(the)37 b(bit)g(is)g(set)g(to)g(0.)60 b(The)37 b('X')g(column)f(in)h(a)g(FITS)f(table)h(is)g(alw)m(a)m(ys)h(padded)e (out)h(to)g(a)g(m)m(ultiple)h(of)227 1851 y(8)f(bits)f(where)g(the)g (bit)h(arra)m(y)f(starts)h(with)f(the)h(most)f(signi\014can)m(t)h(bit)g (of)f(the)h(b)m(yte)g(and)e(w)m(orks)h(do)m(wn)227 1964 y(to)m(w)m(ards)h(the)g(1's)f(bit.)59 b(F)-8 b(or)37 b(example,)i(a)d('4X')h(arra)m(y)-8 b(,)39 b(with)d(the)h(\014rst)e (bit)i(=)e(1)i(and)f(the)g(remaining)h(3)227 2077 y(bits)31 b(=)g(0)h(is)f(equiv)-5 b(alen)m(t)33 b(to)f(the)g(8-bit)g(unsigned)e (b)m(yte)i(decimal)g(v)-5 b(alue)32 b(of)g(128)g(\('1000)i(0000B'\).)g (In)d(the)227 2189 y(case)h(of)f('X')g(columns,)g(CFITSIO)f(can)h (write)g(to)g(all)h(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)f(whether)f(they) h(are)g(formally)227 2302 y(v)-5 b(alid)34 b(or)f(not.)50 b(Th)m(us)32 b(if)i(the)f(column)g(is)h(de\014ned)e(as)h('4X',)i(and)e (one)g(calls)i(\013p)s(clx)e(with)g(\014rstbit=1)g(and)227 2415 y(n)m(bits=8,)i(then)f(all)g(8)h(bits)e(will)h(b)s(e)g(written)g (in)m(to)g(the)g(\014rst)f(b)m(yte)i(\(as)f(opp)s(osed)f(to)i(writing)e (the)h(\014rst)g(4)227 2528 y(bits)28 b(in)m(to)h(the)e(\014rst)g(ro)m (w)h(and)f(then)h(the)g(next)g(4)g(bits)f(in)m(to)i(the)f(next)g(ro)m (w\),)h(ev)m(en)f(though)f(the)h(last)h(4)f(bits)227 2641 y(of)j(eac)m(h)g(b)m(yte)g(are)f(formally)h(not)f(de\014ned)f(and) h(should)f(all)i(b)s(e)e(set)i(=)f(0.)41 b(It)30 b(should)f(also)j(b)s (e)d(noted)h(that)227 2754 y(it)k(is)e(more)h(e\016cien)m(t)i(to)e (write)g('X')h(columns)e(an)h(en)m(tire)h(b)m(yte)f(at)h(a)f(time,)h (instead)f(of)g(bit)g(b)m(y)g(bit.)48 b(An)m(y)227 2867 y(of)31 b(the)g(CFITSIO)e(routines)h(that)i(write)f(to)g(columns)f (\(e.g.)43 b(\014ts)p 2481 2867 28 4 v 33 w(write)p 2716 2867 V 33 w(col)p 2859 2867 V 33 w(b)m(yt\))32 b(ma)m(y)f(b)s(e)f(used) g(for)g(this)227 2980 y(purp)s(ose.)60 b(These)36 b(routines)i(will)f (in)m(terpret)h('X')f(columns)g(as)g(though)g(they)h(w)m(ere)f('B')h (columns)f(\(e.g.,)227 3093 y('1X')32 b(through)d('8X')j(is)e(equiv)-5 b(alen)m(t)32 b(to)f('1B',)h(and)e('9X')h(through)f('16X')i(is)e(equiv) -5 b(alen)m(t)32 b(to)f('2B'\).)95 3345 y Fe(int)47 b (fits_write_col_bit)c(/)48 b(ffpclx)286 3458 y(\(fitsfile)e(*fptr,)g (int)h(colnum,)e(LONGLONG)h(firstrow,)f(long)i(firstbit,)334 3571 y(long)g(nbits,)f(char)g(*larray,)g(>)h(int)g(*status\))0 3824 y Fi(5)81 b Fj(W)-8 b(rite)35 b(the)f(descriptor)g(for)f(a)h(v)-5 b(ariable)35 b(length)f(column)g(in)f(a)i(binary)e(table.)52 b(This)33 b(routine)g(can)i(b)s(e)e(used)227 3937 y(in)h(conjunction)g (with)f(\013gdes)h(to)h(enable)f(2)g(or)g(more)g(arra)m(ys)h(to)f(p)s (oin)m(t)g(to)h(the)f(same)g(storage)h(lo)s(cation)227 4050 y(to)c(sa)m(v)m(e)h(storage)g(space)f(if)f(the)h(arra)m(ys)g(are)g (iden)m(tical.)191 4302 y Fe(int)47 b(fits_write_descript)42 b(/)48 b(ffpdes)382 4415 y(\(fitsfile)d(*fptr,)h(int)h(colnum,)f (LONGLONG)f(rownum,)h(LONGLONG)g(repeat,)430 4528 y(LONGLONG)f(offset,) h(>)h(int)g(*status\))0 4818 y Fd(9.6.4)112 b(Read)38 b(Column)h(Data)f(Routines)0 5036 y Fj(Tw)m(o)28 b(t)m(yp)s(es)f(of)h (routines)f(are)h(pro)m(vided)f(to)h(get)h(the)e(column)h(data)g(whic)m (h)f(di\013er)g(in)g(the)h(w)m(a)m(y)h(unde\014ned)c(pixels)0 5149 y(are)40 b(handled.)66 b(The)39 b(\014rst)g(set)h(of)f(routines)g (\(\013gcv\))i(simply)e(return)f(an)h(arra)m(y)h(of)g(data)g(elemen)m (ts)g(in)f(whic)m(h)0 5262 y(unde\014ned)28 b(pixels)j(are)g(set)g (equal)g(to)g(a)g(v)-5 b(alue)31 b(sp)s(eci\014ed)f(b)m(y)h(the)f(user) g(in)g(the)h('n)m(ullv)-5 b(al')32 b(parameter.)41 b(If)30 b(n)m(ullv)-5 b(al)0 5375 y(=)22 b(0,)j(then)d(no)g(c)m(hec)m(ks)i(for) e(unde\014ned)e(pixels)j(will)g(b)s(e)f(p)s(erformed,)g(th)m(us)g (increasing)i(the)e(sp)s(eed)g(of)g(the)h(program.)0 5488 y(The)36 b(second)g(set)g(of)h(routines)e(\(\013gcf)7 b(\))38 b(returns)d(the)h(data)h(elemen)m(t)g(arra)m(y)g(and)e(in)h (addition)g(a)h(logical)h(arra)m(y)0 5601 y(of)33 b(\015ags)f(whic)m(h) g(de\014nes)g(whether)g(the)g(corresp)s(onding)g(data)h(pixel)f(is)h (unde\014ned.)44 b(See)33 b(App)s(endix)e(B)i(for)f(the)0 5714 y(de\014nition)e(of)h(the)f(parameters)h(used)e(in)h(these)h (routines.)p eop end %%Page: 121 129 TeXDict begin 121 128 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(121)0 555 y(An)m(y)39 b(column,)h(regardless)f (of)g(it's)g(in)m(trinsic)g(data)h(t)m(yp)s(e,)h(ma)m(y)e(b)s(e)f(read) g(as)h(a)g(string.)66 b(It)38 b(should)g(b)s(e)g(noted)0 668 y(ho)m(w)m(ev)m(er)32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g (as)h(a)f(string)h(is)f(10)h(-)g(100)g(times)g(slo)m(w)m(er)h(than)e (reading)g(the)h(same)0 781 y(column)g(as)h(a)g(n)m(um)m(b)s(er)e(due)h (to)h(the)g(large)h(o)m(v)m(erhead)f(in)g(constructing)g(the)g (formatted)g(strings.)44 b(The)31 b(displa)m(y)0 894 y(format)26 b(of)g(the)h(returned)d(strings)i(will)g(b)s(e)g (determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m(ord,)j(if)d(it)i (exists,)h(otherwise)e(b)m(y)0 1007 y(the)h(data)g(t)m(yp)s(e)f(of)h (the)f(column.)39 b(The)26 b(length)h(of)g(the)f(returned)f(strings)h (\(not)h(including)f(the)h(n)m(ull)f(terminating)0 1120 y(c)m(haracter\))38 b(can)e(b)s(e)g(determined)f(with)h(the)g(\014ts)p 1722 1120 28 4 v 33 w(get)p 1875 1120 V 34 w(col)p 2019 1120 V 33 w(displa)m(y)p 2330 1120 V 33 w(width)g(routine.)57 b(The)36 b(follo)m(wing)h(TDISPn)0 1233 y(displa)m(y)31 b(formats)f(are)h(curren)m(tly)f(supp)s(orted:)191 1480 y Fe(Iw.m)142 b(Integer)191 1593 y(Ow.m)g(Octal)46 b(integer)191 1706 y(Zw.m)142 b(Hexadecimal)45 b(integer)191 1818 y(Fw.d)142 b(Fixed)46 b(floating)g(point)191 1931 y(Ew.d)142 b(Exponential)45 b(floating)g(point)191 2044 y(Dw.d)142 b(Exponential)45 b(floating)g(point)191 2157 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)d(not)j(lost,)g(else)f(Ew.d)0 2404 y Fj(where)37 b(w)h(is)g(the)g(width)f(in)h(c)m(haracters)h(of)f (the)h(displa)m(y)m(ed)f(v)-5 b(alues,)41 b(m)c(is)h(the)g(minim)m(um)g (n)m(um)m(b)s(er)e(of)i(digits)0 2517 y(displa)m(y)m(ed,)31 b(and)f(d)g(is)g(the)h(n)m(um)m(b)s(er)e(of)h(digits)h(to)g(the)g(righ) m(t)g(of)g(the)f(decimal.)42 b(The)30 b(.m)g(\014eld)g(is)g(optional.)0 2764 y Fi(1)81 b Fj(Read)29 b(elemen)m(ts)i(from)e(an)g(ASCI)s(I)f(or)i (binary)f(table)h(column)f(\(in)h(the)f(CDU\).)i(These)e(routines)g (return)g(the)227 2877 y(v)-5 b(alues)25 b(of)g(the)g(table)g(column)g (arra)m(y)g(elemen)m(ts.)40 b(The)24 b(caller)i(is)f(required)f(to)h (allo)s(cate)i(the)e(storage)h Fe(array)227 2990 y Fj(b)s(efore)h (calling.)41 b(Unde\014ned)25 b(arra)m(y)i(elemen)m(ts)h(will)f(b)s(e)g (returned)e(with)i(a)g(v)-5 b(alue)27 b(=)f(n)m(ulv)-5 b(al,)29 b(unless)d(n)m(ulv)-5 b(al)227 3103 y(=)36 b(0)h(\(or)g(=)f(') h(')f(for)h(\013gcvs\))g(in)f(whic)m(h)g(case)i(no)e(c)m(hec)m(king)i (for)f(unde\014ned)d(v)-5 b(alues)37 b(will)f(b)s(e)g(p)s(erformed.)227 3216 y(The)30 b(an)m(yn)m(ul)h(parameter)f(is)h(set)g(to)g(true)f(if)g (an)m(y)h(of)g(the)f(returned)f(elemen)m(ts)j(are)f(unde\014ned.)227 3364 y(F)-8 b(or)22 b(the)f Fe(_log)f Fj(\(logical\))k(v)-5 b(arian)m(t,)24 b(the)d(C)f(storage)j(t)m(yp)s(e)e(is)g(a)g Fe(char)f Fj(single-b)m(yte)i(c)m(haracter.)39 b(A)21 b(FITS)f(v)-5 b(alue)227 3477 y(of)29 b(`)p Fe(T)p Fj('rue)e(reads)h (as)g(1)h(and)e(`)p Fe(F)p Fj(')i(reads)e(as)i(0;)g(other)g(non-FITS)e (c)m(haracters)i(are)g(preserv)m(ed)f(un)m(translated.)227 3625 y(F)-8 b(or)30 b(the)g Fe(_str)e Fj(\(string\))i(v)-5 b(arian)m(t)30 b(the)g(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)g(is)g(the)f (n)m(um)m(b)s(er)f(of)i(strings,)f(and)g(the)h(caller)227 3738 y(m)m(ust)44 b(allo)s(cate)i(storage)e(for)g(b)s(oth)e(the)i(arra) m(y)g(of)g(p)s(oin)m(ters)f Fe(array)f Fj(and)h(the)g(c)m(haracter)i (arra)m(y)f(data)227 3851 y(itself)30 b(\(use)f Fe (fits_get_col_display_wid)o(th)23 b Fj(or)29 b Fe(fits_get_coltype)24 b Fj(to)30 b(determine)f(the)g(n)m(um)m(b)s(er)f(of)227 3964 y(c)m(haracters\).)49 b(See)32 b(section)h(4.5)h(\(\\Dealing)h (with)d(Character)g(Strings"\))h(for)f(more)g(information.)47 b(Also,)227 4077 y(when)33 b(the)h Fe(_byt)e Fj(v)-5 b(arian)m(t)34 b(is)g(used)f(to)h(read)g(a)f(column)h(stored)g(in)f (the)h(\014le)f(as)h(string)f(data)i(\(TF)m(ORMn)227 4190 y(=)k('nA'\),)g(the)g(subroutine)f(will)h(read)f(the)h(c)m (haracter)h(b)m(ytes)g(\(instead)f(of)g(attempting)h(to)f(p)s(erform)f (a)227 4302 y(n)m(umerical)24 b(con)m(v)m(ersion)g(as)f(other)g(in)m (teger)i(v)-5 b(arian)m(ts)23 b(w)m(ould)g(do\),)i(with)e(no)f(attempt) i(at)g(n)m(ull)f(termination.)227 4451 y(F)-8 b(or)28 b(the)g Fe(_cmp)e Fj(and)g Fe(_dblcmp)g Fj(\(complex)i(and)f(double)g (complex\))h(v)-5 b(arian)m(ts,)29 b Fe(nelements)24 b Fj(is)k(the)f(n)m(um)m(b)s(er)227 4564 y(of)c(n)m(umerical)h(pairs;)h (the)e(n)m(um)m(b)s(er)f(of)h(\015oats)h(or)f(doubles)f(that)i(m)m(ust) f(b)s(e)f(pre-allo)s(cated)j(is)e Fe(2*nelements)p Fj(.)95 4924 y Fe(int)47 b(fits_read_col_str)c(/)48 b(ffgcvs)286 5036 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 5149 y(LONGLONG)g(nelements,)f(char)h (*nulstr,)g(>)h(char)g(**array,)e(int)i(*anynul,)334 5262 y(int)g(*status\))95 5488 y(int)g(fits_read_col_[log,byt,sht)o (,us)o(ht,i)o(nt,u)o(int)o(,lng)o(,uln)o(g,)41 b(lnglng,)46 b(ulnglng,)g(flt,)g(dbl,)h(cmp,)g(dblcmp])e(/)286 5601 y(ffgcv[l,b,i,ui,k,uk,j,uj,j)o(j,u)o(jj,e)o(,d,c)o(,m])286 5714 y(\(fitsfile)h(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)p eop end %%Page: 122 130 TeXDict begin 122 129 bop 0 299 a Fj(122)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)334 555 y Fe(LONGLONG)46 b(nelements,)f(DTYPE)h(nulval,)g (>)h(DTYPE)g(*array,)e(int)i(*anynul,)334 668 y(int)g(*status\))0 945 y Fi(2)81 b Fj(Read)39 b(elemen)m(ts)i(and)e(n)m(ull)h(\015ags)g (from)f(an)g(ASCI)s(I)g(or)g(binary)g(table)i(column)e(\(in)h(the)g (CHDU\).)g(These)227 1057 y(routines)29 b(return)e(the)i(v)-5 b(alues)29 b(of)g(the)g(table)h(column)e(arra)m(y)i(elemen)m(ts.)41 b(An)m(y)29 b(unde\014ned)d(arra)m(y)k(elemen)m(ts)227 1170 y(will)k(ha)m(v)m(e)h(the)f(corresp)s(onding)e(n)m(ullarra)m(y)i (elemen)m(t)h(set)f(equal)g(to)g(TR)m(UE.)g(The)f(an)m(yn)m(ul)h (parameter)g(is)227 1283 y(set)d(to)g(true)f(if)h(an)m(y)g(of)f(the)h (returned)e(elemen)m(ts)j(are)e(unde\014ned.)95 1560 y Fe(int)47 b(fits_read_colnull_str)42 b(/)48 b(ffgcfs)286 1673 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 1785 y(LONGLONG)g(nelements,)f(>)i(char)g (**array,)e(char)i(*nullarray,)e(int)i(*anynul,)334 1898 y(int)g(*status\))95 2124 y(int)g(fits_read_colnull_[log,byt)o(,sh)o (t,us)o(ht,i)o(nt,)o(uint)o(,lng)o(,ul)o(ng,l)o(ngln)o(g,u)o(lngl)o (ng,f)o(lt,)o(dbl,)o(cmp,)o(dbl)o(cmp])41 b(/)286 2237 y(ffgcf[l,b,i,ui,k,uk,j,uj,j)o(j,u)o(jj,e)o(,d,c)o(,m])286 2350 y(\(fitsfile)46 b(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,) 334 2463 y(LONGLONG)g(firstelem,)f(LONGLONG)g(nelements,)g(>)j(DTYPE)e (*array,)334 2576 y(char)h(*nullarray,)d(int)j(*anynul,)f(int)h (*status\))0 2852 y Fi(3)81 b Fj(Read)24 b(an)g(arbitrary)g(data)h (subsection)f(from)g(an)g(N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g (table)h(v)m(ector)h(column.)227 2965 y(Unde\014ned)21 b(pixels)i(in)f(the)h(arra)m(y)g(will)g(b)s(e)f(set)h(equal)h(to)f(the) g(v)-5 b(alue)23 b(of)g('n)m(ulv)-5 b(al',)25 b(unless)d(n)m(ulv)-5 b(al=0)23 b(in)f(whic)m(h)227 3078 y(case)37 b(no)e(testing)h(for)f (unde\014ned)e(pixels)i(will)h(b)s(e)f(p)s(erformed.)53 b(The)35 b(\014rst)g(and)f(last)i(ro)m(ws)g(in)f(the)g(table)227 3191 y(to)30 b(b)s(e)e(read)h(are)g(sp)s(eci\014ed)g(b)m(y)g (fpixel\(naxis+1\))g(and)g(lpixel\(naxis+1\),)i(and)d(hence)h(are)h (treated)g(as)f(the)227 3304 y(next)38 b(higher)f(dimension)g(of)h(the) f(FITS)g(N-dimensional)h(arra)m(y)-8 b(.)63 b(The)37 b(INC)h(parameter)g(sp)s(eci\014es)f(the)227 3417 y(sampling)31 b(in)m(terv)-5 b(al)31 b(in)f(eac)m(h)i(dimension)e(b)s(et)m(w)m(een)h (the)f(data)h(elemen)m(ts)h(that)f(will)g(b)s(e)e(returned.)95 3693 y Fe(int)47 b(fits_read_subset_[byt,)42 b(sht,)47 b(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(ulnglng,)f(flt,)i (dbl])g(/)286 3806 y(ffgsv[b,i,ui,k,uk,j,uj,jj,)o(ull)o(,e,d)o(])286 3919 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h (*naxes,)f(long)h(*fpixel,)334 4032 y(long)g(*lpixel,)e(long)i(*inc,)f (DTYPE)h(nulval,)e(>)j(DTYPE)e(*array,)g(int)h(*anynul,)334 4145 y(int)g(*status\))0 4421 y Fi(4)81 b Fj(Read)24 b(an)g(arbitrary)g(data)h(subsection)f(from)g(an)g(N-dimensional)h (arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h(column.)227 4534 y(An)m(y)34 b(Unde\014ned)e(pixels)i(in)g(the)f(arra)m(y)i(will)f (ha)m(v)m(e)h(the)f(corresp)s(onding)e('n)m(ullarra)m(y')j(elemen)m(t)g (set)f(equal)227 4647 y(to)40 b(TR)m(UE.)e(The)h(\014rst)e(and)h(last)i (ro)m(ws)e(in)h(the)f(table)i(to)f(b)s(e)f(read)h(are)g(sp)s(eci\014ed) e(b)m(y)i(fpixel\(naxis+1\))227 4760 y(and)i(lpixel\(naxis+1\),)47 b(and)41 b(hence)h(are)g(treated)g(as)g(the)g(next)g(higher)g (dimension)f(of)h(the)g(FITS)f(N-)227 4873 y(dimensional)i(arra)m(y)-8 b(.)78 b(The)41 b(INC)h(parameter)h(sp)s(eci\014es)f(the)h(sampling)f (in)m(terv)-5 b(al)44 b(in)e(eac)m(h)i(dimension)227 4986 y(b)s(et)m(w)m(een)31 b(the)g(data)g(elemen)m(ts)h(that)f(will)f (b)s(e)g(returned.)95 5262 y Fe(int)47 b(fits_read_subsetnull_[byt,)41 b(sht,)47 b(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(ulnglng,)f (flt,)i(dbl])g(/)286 5375 y(ffgsf[b,i,ui,k,uk,j,uj,jj,)o(ujj)o(,e,d)o (])286 5488 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f (long)h(*naxes,)334 5601 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i (*inc,)f(>)i(DTYPE)e(*array,)334 5714 y(char)h(*nullarray,)d(int)j (*anynul,)f(int)h(*status\))p eop end %%Page: 123 131 TeXDict begin 123 130 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(123)0 555 y Fi(5)81 b Fj(Read)35 b(bit)g(v)-5 b(alues)35 b(from)g(a)g(b)m(yte)h(\('B'\))g(or)f(bit)g (\(`X`\))h(table)g(column)f(\(in)g(the)g(CDU\).)h(Larra)m(y)g(is)f(an)f (arra)m(y)227 668 y(of)g(logical)i(v)-5 b(alues)34 b(corresp)s(onding)f (to)h(the)g(sequence)g(of)g(bits)g(to)g(b)s(e)f(read.)51 b(If)33 b(larra)m(y)h(is)g(true)f(then)h(the)227 781 y(corresp)s(onding)i(bit)h(w)m(as)g(set)h(to)f(1,)j(otherwise)d(the)g (bit)g(w)m(as)g(set)h(to)f(0.)61 b(The)37 b('X')g(column)g(in)f(a)i (FITS)227 894 y(table)e(is)e(alw)m(a)m(ys)i(padded)e(out)h(to)g(a)g(m)m (ultiple)g(of)g(8)g(bits)f(where)g(the)h(bit)g(arra)m(y)g(starts)g (with)f(the)h(most)227 1007 y(signi\014can)m(t)j(bit)e(of)h(the)g(b)m (yte)g(and)f(w)m(orks)g(do)m(wn)h(to)m(w)m(ards)g(the)g(1's)g(bit.)59 b(F)-8 b(or)37 b(example,)i(a)e('4X')h(arra)m(y)-8 b(,)227 1120 y(with)33 b(the)h(\014rst)e(bit)i(=)f(1)h(and)e(the)i(remaining)f (3)h(bits)f(=)g(0)h(is)f(equiv)-5 b(alen)m(t)35 b(to)f(the)g(8-bit)g (unsigned)e(b)m(yte)227 1233 y(v)-5 b(alue)31 b(of)f(128.)42 b(Note)31 b(that)g(in)e(the)i(case)g(of)f('X')g(columns,)g(CFITSIO)f (can)h(read)g(all)h(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)227 1346 y(whether)h(they)h(are)g(formally)g(v)-5 b(alid)33 b(or)f(not.)48 b(Th)m(us)31 b(if)i(the)f(column)h(is)f(de\014ned)f(as)i ('4X',)h(and)e(one)h(calls)227 1458 y(\013gcx)d(with)f(\014rstbit=1)f (and)h(n)m(bits=8,)g(then)g(all)h(8)f(bits)g(will)g(b)s(e)g(read)g (from)f(the)h(\014rst)g(b)m(yte)g(\(as)h(opp)s(osed)227 1571 y(to)39 b(reading)f(the)g(\014rst)g(4)g(bits)g(from)g(the)g (\014rst)f(ro)m(w)h(and)g(then)f(the)i(\014rst)e(4)h(bits)g(from)g(the) g(next)g(ro)m(w\),)227 1684 y(ev)m(en)g(though)f(the)g(last)i(4)e(bits) g(of)h(eac)m(h)g(b)m(yte)g(are)f(formally)h(not)g(de\014ned.)60 b(It)37 b(should)f(also)i(b)s(e)f(noted)227 1797 y(that)f(it)f(is)h (more)f(e\016cien)m(t)h(to)g(read)f('X')h(columns)e(an)h(en)m(tire)h(b) m(yte)g(at)g(a)f(time,)i(instead)e(of)h(bit)f(b)m(y)g(bit.)227 1910 y(An)m(y)29 b(of)g(the)h(CFITSIO)d(routines)i(that)g(read)g (columns)g(\(e.g.)42 b(\014ts)p 2520 1910 28 4 v 32 w(read)p 2724 1910 V 33 w(col)p 2867 1910 V 34 w(b)m(yt\))29 b(ma)m(y)h(b)s(e)e (used)g(for)h(this)227 2023 y(purp)s(ose.)60 b(These)36 b(routines)i(will)f(in)m(terpret)h('X')f(columns)g(as)g(though)g(they)h (w)m(ere)f('B')h(columns)f(\(e.g.,)227 2136 y('8X')32 b(is)e(equiv)-5 b(alen)m(t)32 b(to)f('1B',)h(and)e('16X')i(is)e(equiv) -5 b(alen)m(t)32 b(to)f('2B'\).)95 2400 y Fe(int)47 b (fits_read_col_bit)c(/)48 b(ffgcx)286 2513 y(\(fitsfile)e(*fptr,)g(int) h(colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG)h(firstbit,)334 2626 y(LONGLONG)g(nbits,)g(>)h(char)g(*larray,)e(int)i(*status\))0 2890 y Fi(6)81 b Fj(Read)31 b(an)m(y)h(consecutiv)m(e)i(set)e(of)g (bits)f(from)h(an)f('X')h(or)g('B')h(column)e(and)g(in)m(terpret)h (them)g(as)f(an)h(unsigned)227 3003 y(n-bit)h(in)m(teger.)48 b(n)m(bits)33 b(m)m(ust)f(b)s(e)g(less)h(than)g(16)g(or)g(32)g(in)f (\013gcxui)i(and)d(\013gcxuk,)j(resp)s(ectiv)m(ely)-8 b(.)49 b(If)32 b(nro)m(ws)227 3115 y(is)c(greater)h(than)f(1,)h(then)e (the)h(same)h(set)f(of)g(bits)g(will)g(b)s(e)f(read)h(from)f(eac)m(h)i (ro)m(w,)g(starting)g(with)e(\014rstro)m(w.)227 3228 y(The)j(bits)g(are)h(n)m(um)m(b)s(ered)e(with)h(1)h(=)f(the)h(most)f (signi\014can)m(t)i(bit)e(of)h(the)f(\014rst)g(elemen)m(t)i(of)e(the)h (column.)95 3492 y Fe(int)47 b(fits_read_col_bit_[usht,)42 b(uint])k(/)h(ffgcx[ui,uk])286 3605 y(\(fitsfile)f(*fptr,)g(int)h (colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG,)h(nrows,)334 3718 y(long)h(firstbit,)e(long)i(nbits,)f(>)h(DTYPE)g(*array,)e(int)i (*status\))0 3982 y Fi(7)81 b Fj(Return)27 b(the)i(descriptor)f(for)h (a)g(v)-5 b(ariable)29 b(length)g(column)f(in)h(a)g(binary)e(table.)41 b(The)28 b(descriptor)h(consists)g(of)227 4095 y(2)j(in)m(teger)g (parameters:)42 b(the)31 b(n)m(um)m(b)s(er)f(of)h(elemen)m(ts)i(in)d (the)h(arra)m(y)h(and)e(the)h(starting)h(o\013set)g(relativ)m(e)h(to) 227 4208 y(the)c(start)h(of)e(the)h(heap.)40 b(The)29 b(\014rst)f(pair)g(of)h(routine)g(returns)e(a)i(single)h(descriptor)e (whereas)h(the)g(second)227 4321 y(pair)34 b(of)h(routine)f(returns)g (the)g(descriptors)g(for)g(a)h(range)g(of)f(ro)m(ws)h(in)f(the)g (table.)54 b(The)34 b(only)g(di\013erence)227 4434 y(b)s(et)m(w)m(een) 42 b(the)f(2)g(routines)f(in)h(eac)m(h)h(pair)e(is)h(that)g(one)g (returns)f(the)h(parameters)g(as)g('long')g(in)m(tegers,)227 4547 y(whereas)30 b(the)h(other)g(returns)e(the)h(v)-5 b(alues)31 b(as)g(64-bit)g('LONGLONG')g(in)m(tegers.)95 4811 y Fe(int)47 b(fits_read_descript)c(/)48 b(ffgdes)286 4924 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(rownum,)g(>)h (long)g(*repeat,)525 5036 y(long)g(*offset,)e(int)i(*status\))95 5262 y(int)g(fits_read_descriptll)c(/)k(ffgdesll)286 5375 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(LONGLONG)h(rownum,)g(>)h (LONGLONG)f(*repeat,)525 5488 y(LONGLONG)g(*offset,)f(int)i(*status\)) 95 5714 y(int)g(fits_read_descripts)c(/)k(ffgdess)p eop end %%Page: 124 132 TeXDict begin 124 131 bop 0 299 a Fj(124)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)286 555 y Fe(\(fitsfile)46 b(*fptr,)g(int)h(colnum,)e (LONGLONG)h(firstrow,)f(LONGLONG)h(nrows)334 668 y(>)i(long)e(*repeat,) g(long)g(*offset,)g(int)h(*status\))95 894 y(int)g (fits_read_descriptsll)42 b(/)48 b(ffgdessll)286 1007 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(nrows)334 1120 y(>)i(LONGLONG)d(*repeat,)h(LONGLONG)f (*offset,)h(int)h(*status\))p eop end %%Page: 125 133 TeXDict begin 125 132 bop 0 1225 a Fg(Chapter)65 b(10)0 1687 y Fm(Extended)77 b(File)g(Name)g(Syn)-6 b(tax)0 2216 y Ff(10.1)136 b(Ov)l(erview)0 2466 y Fj(CFITSIO)30 b(supp)s(orts)f(an)j(extended)f(syn)m(tax)h(when)f(sp)s(ecifying)g(the) h(name)f(of)h(the)g(data)g(\014le)f(to)h(b)s(e)f(op)s(ened)g(or)0 2579 y(created)g(that)g(includes)f(the)h(follo)m(wing)h(features:)136 2813 y Fc(\017)46 b Fj(CFITSIO)40 b(can)i(read)f(IRAF)h(format)g (images)g(whic)m(h)f(ha)m(v)m(e)i(header)e(\014le)h(names)f(that)h(end) f(with)g(the)227 2926 y('.imh')d(extension,)i(as)e(w)m(ell)g(as)g (reading)f(and)g(writing)g(FITS)g(\014les,)i(This)e(feature)h(is)f (implemen)m(ted)h(in)227 3039 y(CFITSIO)29 b(b)m(y)i(\014rst)e(con)m(v) m(erting)k(the)d(IRAF)h(image)h(in)m(to)f(a)g(temp)s(orary)f(FITS)g (format)h(\014le)f(in)g(memory)-8 b(,)227 3152 y(then)35 b(op)s(ening)f(the)h(FITS)f(\014le.)54 b(An)m(y)35 b(of)g(the)g(usual)f (CFITSIO)g(routines)g(then)h(ma)m(y)g(b)s(e)f(used)g(to)i(read)227 3265 y(the)31 b(image)g(header)f(or)h(data.)41 b(Similarly)-8 b(,)31 b(ra)m(w)f(binary)g(data)h(arra)m(ys)f(can)h(b)s(e)f(read)g(b)m (y)g(con)m(v)m(erting)i(them)227 3378 y(on)f(the)f(\015y)g(in)m(to)h (virtual)g(FITS)f(images.)136 3557 y Fc(\017)46 b Fj(FITS)f(\014les)h (on)f(the)h(In)m(ternet)g(can)g(b)s(e)f(read)g(\(and)g(sometimes)i (written\))f(using)f(the)h(FTP)-8 b(,)46 b(HTTP)-8 b(,)227 3670 y(HTTPS,)30 b(FTPS,)g(or)g(R)m(OOT)g(proto)s(cols.)136 3849 y Fc(\017)46 b Fj(FITS)30 b(\014les)g(can)h(b)s(e)f(pip)s(ed)f(b)s (et)m(w)m(een)i(tasks)f(on)h(the)f(stdin)g(and)g(stdout)g(streams.)136 4028 y Fc(\017)46 b Fj(FITS)36 b(\014les)h(can)g(b)s(e)f(read)h(and)f (written)h(in)g(shared)f(memory)-8 b(.)60 b(This)36 b(can)h(p)s(oten)m (tially)i(ac)m(hiev)m(e)g(b)s(etter)227 4141 y(data)26 b(I/O)e(p)s(erformance)g(compared)h(to)h(reading)f(and)f(writing)g(the) h(same)h(FITS)e(\014les)g(on)h(magnetic)h(disk.)136 4320 y Fc(\017)46 b Fj(Compressed)30 b(FITS)f(\014les)i(in)f(gzip)h(or)f (Unix)g(COMPRESS)f(format)h(can)h(b)s(e)f(directly)h(read.)136 4499 y Fc(\017)46 b Fj(Output)28 b(FITS)h(\014les)g(can)g(b)s(e)g (written)g(directly)h(in)e(compressed)h(gzip)h(format,)g(th)m(us)e(sa)m (ving)i(disk)f(space.)136 4678 y Fc(\017)46 b Fj(FITS)26 b(table)h(columns)f(can)h(b)s(e)f(created,)i(mo)s(di\014ed,)f(or)f (deleted)h('on-the-\015y')g(as)g(the)g(table)g(is)f(op)s(ened)g(b)m(y) 227 4791 y(CFITSIO.)32 b(This)h(creates)i(a)e(virtual)h(FITS)f(\014le)g (con)m(taining)i(the)f(mo)s(di\014cations)f(that)h(is)g(then)f(op)s (ened)227 4904 y(b)m(y)e(the)f(application)i(program.)136 5083 y Fc(\017)46 b Fj(T)-8 b(able)29 b(ro)m(ws)e(ma)m(y)i(b)s(e)e (selected,)j(or)e(\014ltered)g(out,)g(on)g(the)g(\015y)f(when)g(the)h (table)h(is)f(op)s(ened)f(b)m(y)g(CFITSIO,)227 5196 y(based)22 b(on)f(an)g(user-sp)s(eci\014ed)g(expression.)38 b(Only)21 b(ro)m(ws)g(for)g(whic)m(h)h(the)g(expression)f(ev)-5 b(aluates)23 b(to)f('TR)m(UE')227 5309 y(are)31 b(retained)g(in)f(the)g (cop)m(y)i(of)e(the)h(table)g(that)g(is)f(op)s(ened)g(b)m(y)g(the)h (application)g(program.)136 5488 y Fc(\017)46 b Fj(Histogram)28 b(images)g(ma)m(y)f(b)s(e)f(created)h(on)f(the)h(\015y)f(b)m(y)g (binning)g(the)g(v)-5 b(alues)27 b(in)f(table)i(columns,)f(resulting) 227 5601 y(in)36 b(a)g(virtual)h(N-dimensional)f(FITS)g(image.)59 b(The)35 b(application)i(program)f(then)g(only)g(sees)g(the)h(FITS)227 5714 y(image)32 b(\(in)e(the)h(primary)e(arra)m(y\))j(instead)e(of)h (the)f(original)i(FITS)d(table.)1882 5942 y(125)p eop end %%Page: 126 134 TeXDict begin 126 133 bop 0 299 a Fj(126)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)39 b(latter)i(3)f(table)h(\014ltering)f(features)g(in)f (particular)h(add)f(v)m(ery)h(p)s(o)m(w)m(erful)f(data)i(pro)s(cessing) e(capabilities)0 668 y(directly)33 b(in)m(to)g(CFITSIO,)e(and)h(hence)h (in)m(to)g(ev)m(ery)g(task)g(that)g(uses)f(CFITSIO)f(to)i(read)f(or)h (write)f(FITS)g(\014les.)0 781 y(F)-8 b(or)29 b(example,)g(these)f (features)h(transform)e(a)h(v)m(ery)g(simple)g(program)g(that)g(just)g (copies)g(an)g(input)f(FITS)g(\014le)h(to)0 894 y(a)c(new)f(output)h (\014le)g(\(lik)m(e)h(the)f(`\014tscop)m(y')h(program)e(that)i(is)e (distributed)g(with)h(CFITSIO\))e(in)m(to)j(a)f(m)m(ultipurp)s(ose)0 1007 y(FITS)33 b(\014le)g(pro)s(cessing)g(to)s(ol.)51 b(By)33 b(app)s(ending)f(fairly)i(simple)f(quali\014ers)g(on)m(to)h (the)g(name)f(of)h(the)f(input)g(FITS)0 1120 y(\014le,)45 b(the)d(user)f(can)h(p)s(erform)e(quite)i(complex)h(table)f(editing)h (op)s(erations)f(\(e.g.,)k(create)d(new)e(columns,)k(or)0 1233 y(\014lter)32 b(out)h(ro)m(ws)f(in)g(a)g(table\))i(or)e(create)i (FITS)d(images)j(b)m(y)e(binning)f(or)h(histogramming)h(the)g(v)-5 b(alues)32 b(in)g(table)0 1346 y(columns.)47 b(In)32 b(addition,)h(these)g(functions)f(ha)m(v)m(e)i(b)s(een)e(co)s(ded)g (using)g(new)g(state-of-the)j(art)e(algorithms)g(that)0 1458 y(are,)e(in)f(some)h(cases,)g(10)h(-)e(100)i(times)f(faster)g (than)f(previous)g(widely)g(used)f(implemen)m(tations.)0 1619 y(Before)34 b(describing)f(the)h(complete)h(syn)m(tax)f(for)f(the) h(extended)f(FITS)g(\014le)g(names)g(in)g(the)h(next)g(section,)h(here) 0 1732 y(are)c(a)g(few)f(examples)h(of)f(FITS)g(\014le)g(names)h(that)f (giv)m(e)i(a)f(quic)m(k)g(o)m(v)m(erview)h(of)f(the)f(allo)m(w)m(ed)i (syn)m(tax:)136 2005 y Fc(\017)46 b Fe(myfile.fits)p Fj(:)38 b(the)30 b(simplest)h(case)g(of)g(a)g(FITS)e(\014le)i(on)f (disk)g(in)g(the)h(curren)m(t)f(directory)-8 b(.)136 2207 y Fc(\017)46 b Fe(myfile.imh)p Fj(:)i(op)s(ens)34 b(an)h(IRAF)g(format)g(image)i(\014le)e(and)f(con)m(v)m(erts)j(it)e(on) g(the)g(\015y)g(in)m(to)h(a)f(temp)s(orary)227 2320 y(FITS)30 b(format)h(image)g(in)f(memory)h(whic)m(h)f(can)g(then)g(b)s(e)g(read)g (with)g(an)m(y)h(other)g(CFITSIO)e(routine.)136 2521 y Fc(\017)46 b Fe(rawfile.dat[i512,512])p Fj(:)35 b(op)s(ens)30 b(a)g(ra)m(w)h(binary)e(data)i(arra)m(y)g(\(a)g(512)g(x)f(512)i(short)e (in)m(teger)h(arra)m(y)g(in)227 2634 y(this)i(case\))i(and)d(con)m(v)m (erts)j(it)e(on)g(the)g(\015y)g(in)m(to)h(a)f(temp)s(orary)g(FITS)f (format)h(image)i(in)d(memory)h(whic)m(h)227 2747 y(can)e(then)f(b)s(e) g(read)g(with)g(an)m(y)h(other)f(CFITSIO)f(routine.)136 2948 y Fc(\017)46 b Fe(myfile.fits.gz)p Fj(:)d(if)33 b(this)g(is)g(the)g(name)g(of)h(a)f(new)g(output)g(\014le,)h(the)f ('.gz')i(su\016x)d(will)h(cause)h(it)g(to)g(b)s(e)227 3061 y(compressed)c(in)g(gzip)h(format)g(when)e(it)i(is)g(written)f(to) h(disk.)136 3263 y Fc(\017)46 b Fe(myfile.fits.gz[events,)c(2])p Fj(:)35 b(op)s(ens)20 b(and)f(uncompresses)g(the)i(gzipp)s(ed)f(\014le) g(m)m(y\014le.\014ts)h(then)f(mo)m(v)m(es)227 3376 y(to)31 b(the)g(extension)g(with)f(the)h(k)m(eyw)m(ords)f(EXTNAME)h(=)f ('EVENTS')g(and)g(EXTVER)g(=)g(2.)136 3577 y Fc(\017)46 b Fe(-)p Fj(:)40 b(a)30 b(dash)f(\(min)m(us)g(sign\))h(signi\014es)g (that)g(the)g(input)f(\014le)g(is)h(to)g(b)s(e)f(read)h(from)f(the)h (stdin)f(\014le)h(stream,)g(or)227 3690 y(that)d(the)g(output)f(\014le) h(is)f(to)h(b)s(e)f(written)h(to)g(the)g(stdout)f(stream.)40 b(See)27 b(also)g(the)g(stream://)h(driv)m(er)e(whic)m(h)227 3803 y(pro)m(vides)37 b(a)f(more)h(e\016cien)m(t,)i(but)d(more)g (restricted)h(metho)s(d)f(of)h(reading)f(or)g(writing)h(to)g(the)f (stdin)g(or)227 3916 y(stdout)31 b(streams.)136 4117 y Fc(\017)46 b Fe(ftp://legacy.gsfc.nasa.go)o(v/te)o(st/v)o(ela)o(.fit) o(s)p Fj(:)k(FITS)37 b(\014les)h(in)g(an)m(y)h(ftp)e(arc)m(hiv)m(e)j (site)f(on)f(the)227 4230 y(In)m(ternet)31 b(ma)m(y)g(b)s(e)f(directly) h(op)s(ened)e(with)h(read-only)h(access.)136 4432 y Fc(\017)46 b Fe(http://legacy.gsfc.nasa.g)o(ov/s)o(oftw)o(are)o(/tes)o(t.fi)o(ts)p Fj(:)33 b(an)m(y)27 b(v)-5 b(alid)28 b(URL)f(to)h(a)g(FITS)e(\014le)i (on)f(the)227 4545 y(W)-8 b(eb)31 b(ma)m(y)g(b)s(e)f(op)s(ened)g(with)g (read-only)g(access.)136 4746 y Fc(\017)46 b Fe (root://legacy.gsfc.nasa.g)o(ov/t)o(est/)o(vel)o(a.fi)o(ts)p Fj(:)e(similar)36 b(to)g(ftp)f(access)i(except)f(that)g(it)g(pro-)227 4859 y(vides)30 b(write)h(as)f(w)m(ell)h(as)g(read)f(access)h(to)g(the) f(\014les)h(across)f(the)h(net)m(w)m(ork.)41 b(This)29 b(uses)h(the)h(ro)s(ot)f(proto)s(col)227 4972 y(dev)m(elop)s(ed)h(at)g (CERN.)136 5174 y Fc(\017)46 b Fe(shmem://h2[events])p Fj(:)j(op)s(ens)36 b(the)i(FITS)e(\014le)h(in)g(a)g(shared)f(memory)h (segmen)m(t)h(and)f(mo)m(v)m(es)h(to)g(the)227 5287 y(EVENTS)30 b(extension.)136 5488 y Fc(\017)46 b Fe(mem://)p Fj(:)65 b(creates)44 b(a)g(scratc)m(h)g(output)f(\014le)g(in)g(core)h(computer) f(memory)-8 b(.)79 b(The)43 b(resulting)g('\014le')h(will)227 5601 y(disapp)s(ear)25 b(when)f(the)i(program)f(exits,)i(so)f(this)f (is)h(mainly)f(useful)g(for)g(testing)i(purp)s(oses)c(when)i(one)g(do)s (es)227 5714 y(not)31 b(w)m(an)m(t)g(a)g(p)s(ermanen)m(t)f(cop)m(y)h (of)f(the)h(output)f(\014le.)p eop end %%Page: 127 135 TeXDict begin 127 134 bop 0 299 a Fh(10.1.)73 b(O)m(VER)-10 b(VIEW)2995 b Fj(127)136 555 y Fc(\017)46 b Fe(myfile.fits[3;)e (Images\(10\)])p Fj(:)c(op)s(ens)30 b(a)i(cop)m(y)g(of)g(the)g(image)g (con)m(tained)h(in)e(the)h(10th)g(ro)m(w)f(of)h(the)227 668 y('Images')38 b(column)f(in)g(the)g(binary)f(table)i(in)e(the)h (3th)g(extension)h(of)f(the)g(FITS)f(\014le.)60 b(The)37 b(virtual)g(\014le)227 781 y(that)31 b(is)g(op)s(ened)e(b)m(y)i(the)f (application)i(just)e(con)m(tains)h(this)f(single)h(image)h(in)e(the)h (primary)e(arra)m(y)-8 b(.)136 973 y Fc(\017)46 b Fe (myfile.fits[1:512:2,)d(1:512:2])p Fj(:)c(op)s(ens)30 b(a)h(section)h(of)g(the)f(input)f(image)i(ranging)f(from)f(the)h(1st) 227 1086 y(to)k(the)f(512th)h(pixel)f(in)g(X)g(and)g(Y,)g(and)f (selects)j(ev)m(ery)e(second)g(pixel)h(in)e(b)s(oth)g(dimensions,)i (resulting)227 1198 y(in)30 b(a)h(256)h(x)e(256)i(pixel)e(input)g (image)h(in)g(this)f(case.)136 1390 y Fc(\017)46 b Fe (myfile.fits[EVENTS][col)c(Rad)47 b(=)g(sqrt\(X**2)e(+)j(Y**2\)])p Fj(:)36 b(creates)27 b(and)d(op)s(ens)h(a)g(virtual)h(\014le)f(on)227 1503 y(the)h(\015y)f(that)i(is)f(iden)m(tical)h(to)g(m)m (y\014le.\014ts)f(except)g(that)h(it)f(will)g(con)m(tain)h(a)f(new)g (column)f(in)h(the)g(EVENTS)227 1616 y(extension)41 b(called)h('Rad')f (whose)f(v)-5 b(alue)41 b(is)g(computed)f(using)h(the)f(indicated)h (expression)g(whic)m(h)f(is)h(a)227 1729 y(function)30 b(of)h(the)f(v)-5 b(alues)31 b(in)f(the)h(X)f(and)g(Y)h(columns.)136 1920 y Fc(\017)46 b Fe(myfile.fits[EVENTS][PHA)c(>)47 b(5])p Fj(:)41 b(creates)33 b(and)d(op)s(ens)g(a)i(virtual)f(FITS)f (\014les)h(that)g(is)g(iden)m(tical)i(to)227 2033 y('m)m (y\014le.\014ts')40 b(except)h(that)f(the)f(EVENTS)g(table)h(will)g (only)f(con)m(tain)i(the)e(ro)m(ws)h(that)g(ha)m(v)m(e)g(v)-5 b(alues)40 b(of)227 2146 y(the)34 b(PHA)g(column)g(greater)h(than)e(5.) 52 b(In)33 b(general,)j(an)m(y)e(arbitrary)g(b)s(o)s(olean)f (expression)h(using)f(a)i(C)e(or)227 2259 y(F)-8 b(ortran-lik)m(e)31 b(syn)m(tax,)e(whic)m(h)f(ma)m(y)h(com)m(bine)g(AND)g(and)f(OR)f(op)s (erators,)i(ma)m(y)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)227 2372 y(from)g(a)h(table.)136 2564 y Fc(\017)46 b Fe (myfile.fits[EVENTS][bin)c(\(X,Y\)=1,2048,4])p Fj(:)34 b(creates)26 b(a)g(temp)s(orary)f(FITS)g(primary)f(arra)m(y)i(im-)227 2677 y(age)38 b(whic)m(h)e(is)h(computed)f(on)g(the)h(\015y)f(b)m(y)g (binning)f(\(i.e,)40 b(computing)c(the)h(2-dimensional)g(histogram\)) 227 2789 y(of)d(the)f(v)-5 b(alues)34 b(in)f(the)h(X)g(and)e(Y)i (columns)f(of)h(the)f(EVENTS)g(extension.)50 b(In)33 b(this)g(case)i(the)e(X)h(and)f(Y)227 2902 y(co)s(ordinates)h(range)g (from)f(1)h(to)g(2048)h(and)e(the)h(image)g(pixel)g(size)g(is)g(4)f (units)g(in)g(b)s(oth)g(dimensions,)h(so)227 3015 y(the)d(resulting)f (image)i(is)e(512)i(x)e(512)i(pixels)f(in)f(size.)136 3207 y Fc(\017)46 b Fj(The)31 b(\014nal)g(example)i(com)m(bines)f(man)m (y)f(of)h(these)g(feature)g(in)m(to)g(one)g(complex)g(expression)f (\(it)i(is)e(brok)m(en)227 3320 y(in)m(to)h(sev)m(eral)f(lines)g(for)f (clarit)m(y\):)370 3576 y Fe(ftp://legacy.gsfc.nasa.gov)o(/dat)o(a/s)o (ampl)o(e.fi)o(ts.)o(gz[E)o(VENT)o(S])370 3689 y([col)47 b(phacorr)f(=)h(pha)g(*)h(1.1)f(-)g(0.3][phacorr)e(>=)i(5.0)g(&&)g (phacorr)f(<=)h(14.0])370 3801 y([bin)g(\(X,Y\)=32])227 4057 y Fj(In)37 b(this)h(case,)j(CFITSIO)36 b(\(1\))j(copies)g(and)e (uncompresses)g(the)h(FITS)f(\014le)h(from)f(the)h(ftp)f(site)i(on)f (the)227 4170 y(legacy)g(mac)m(hine,)h(\(2\))e(mo)m(v)m(es)g(to)g(the)g ('EVENTS')f(extension,)i(\(3\))f(calculates)i(a)d(new)g(column)g (called)227 4283 y('phacorr',)30 b(\(4\))f(selects)h(the)f(ro)m(ws)g (in)f(the)h(table)h(that)f(ha)m(v)m(e)h(phacorr)e(in)g(the)h(range)g(5) g(to)h(14,)g(and)e(\014nally)227 4396 y(\(5\))35 b(bins)d(the)h (remaining)g(ro)m(ws)g(on)h(the)f(X)g(and)g(Y)g(column)g(co)s (ordinates,)i(using)d(a)i(pixel)f(size)h(=)f(32)h(to)227 4509 y(create)d(a)f(2D)g(image.)42 b(All)30 b(this)f(pro)s(cessing)g (is)h(completely)h(transparen)m(t)e(to)i(the)e(application)i(program,) 227 4622 y(whic)m(h)f(simply)g(sees)h(the)g(\014nal)f(2-D)h(image)h(in) e(the)g(primary)g(arra)m(y)h(of)f(the)h(op)s(ened)f(\014le.)0 4886 y(The)c(full)h(extended)g(CFITSIO)e(FITS)h(\014le)h(name)g(can)g (con)m(tain)h(sev)m(eral)g(di\013eren)m(t)g(comp)s(onen)m(ts)f(dep)s (ending)e(on)0 4998 y(the)31 b(con)m(text.)42 b(These)30 b(comp)s(onen)m(ts)h(are)g(describ)s(ed)e(in)h(the)g(follo)m(wing)i (sections:)0 5262 y Fe(When)47 b(creating)e(a)j(new)f(file:)143 5375 y(filetype://BaseFilename\(t)o(empl)o(ate)o(Name)o(\)[co)o(mpr)o (ess])0 5601 y(When)g(opening)e(an)j(existing)d(primary)h(array)g(or)i (image)e(HDU:)143 5714 y(filetype://BaseFilename\(o)o(utNa)o(me\))o ([HDU)o(loca)o(tio)o(n][I)o(mage)o(Sec)o(tion)o(][pi)o(xFi)o(lter)o(])p eop end %%Page: 128 136 TeXDict begin 128 135 bop 0 299 a Fj(128)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 668 y Fe(When)47 b(opening)e(an)j(existing)d(table)i(HDU:)143 781 y(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o(loca)o(tio)o (n][c)o(olFi)o(lte)o(r][r)o(owFi)o(lte)o(r][b)o(inSp)o(ec])0 1057 y Fj(The)35 b(\014let)m(yp)s(e,)j(BaseFilename,)h(outName,)g (HDUlo)s(cation,)g(ImageSection,)g(and)c(pixFilter)i(comp)s(onen)m(ts,) g(if)0 1170 y(presen)m(t,)27 b(m)m(ust)f(b)s(e)g(giv)m(en)h(in)f(that)g (order,)h(but)e(the)i(colFilter,)i(ro)m(wFilter,)g(and)c(binSp)s(ec)g (sp)s(eci\014ers)g(ma)m(y)i(follo)m(w)0 1283 y(in)j(an)m(y)h(order.)42 b(Regardless)31 b(of)g(the)g(order,)f(ho)m(w)m(ev)m(er,)i(the)f (colFilter)i(sp)s(eci\014er,)e(if)f(presen)m(t,)h(will)g(b)s(e)f(pro)s (cessed)0 1396 y(\014rst)g(b)m(y)g(CFITSIO,)f(follo)m(w)m(ed)j(b)m(y)e (the)h(ro)m(wFilter)h(sp)s(eci\014er,)e(and)f(\014nally)i(b)m(y)f(the)g (binSp)s(ec)f(sp)s(eci\014er.)0 1556 y(Multiple)40 b(colFilter)i(or)e (ro)m(wFilter)h(sp)s(eci\014cations)f(ma)m(y)g(app)s(ear)f(as)h (separated)g(brac)m(k)m(eted)h(expressions,)h(in)0 1669 y(an)m(y)c(order.)62 b(Multiple)39 b(colFilter)h(or)d(ro)m(wFilter)i (expressions)f(are)g(treated)g(in)m(ternally)h(as)f(a)g(single)g (e\013ectiv)m(e)0 1782 y(expression,)30 b(with)f(order)h(of)g(op)s (erations)g(determined)f(from)h(left)g(to)h(righ)m(t.)41 b(CFITSIO)28 b(do)s(es)i(not)g(supp)s(ort)e(the)0 1895 y(@\014lename.txt)j(complex)g(syn)m(tax)g(option)g(if)f(m)m(ultiple)h (expressions)f(are)h(also)h(used.)0 2248 y Ff(10.2)136 b(Filet)l(yp)t(e)0 2502 y Fj(The)37 b(t)m(yp)s(e)g(of)g(\014le)g (determines)g(the)g(medium)f(on)h(whic)m(h)g(the)g(\014le)g(is)h(lo)s (cated)g(\(e.g.,)i(disk)d(or)g(net)m(w)m(ork\))h(and,)0 2615 y(hence,)f(whic)m(h)e(in)m(ternal)h(device)g(driv)m(er)f(is)g (used)f(b)m(y)h(CFITSIO)f(to)i(read)f(and/or)g(write)g(the)g(\014le.)56 b(Curren)m(tly)0 2728 y(supp)s(orted)29 b(t)m(yp)s(es)h(are)382 3004 y Fe(file://)93 b(-)48 b(file)e(on)i(local)e(magnetic)g(disk)g (\(default\))430 3117 y(ftp://)93 b(-)48 b(a)f(readonly)f(file)g (accessed)g(with)h(the)g(anonymous)e(FTP)i(protocol.)907 3230 y(It)g(also)g(supports)93 b(ftp://username:password@)o(host)o(nam) o(e/..)o(.)907 3343 y(for)47 b(accessing)e(password-protected)e(ftp)k (sites.)382 3456 y(http://)93 b(-)48 b(a)f(readonly)f(file)g(accessed)g (with)h(the)g(HTTP)f(protocol.)93 b(It)907 3569 y(supports)45 b(username:password)e(just)k(like)g(the)g(ftp)g(driver.)907 3681 y(Proxy)f(HTTP)h(servers)f(are)h(supported)e(using)h(the)h (http_proxy)907 3794 y(environment)e(variable)g(\(see)i(following)e (note\).)334 3907 y(https://)93 b(-)48 b(a)f(readonly)f(file)g (accessed)g(with)h(the)g(HTTPS)f(protocol.)93 b(This)907 4020 y(is)47 b(available)e(only)i(if)g(CFITSIO)f(was)h(built)f(with)h (the)g(libcurl)907 4133 y(library)f(\(see)g(the)h(following)e(note\).) 334 4246 y(ftps://)94 b(-)h(a)47 b(readonly)f(file)g(accessed)g(with)h (the)g(FTPS)f(protocol.)93 b(This)907 4359 y(is)47 b(available)e(only)i (if)g(CFITSIO)f(was)h(built)f(with)h(the)g(libcurl)907 4472 y(library.)286 4585 y(stream://)93 b(-)48 b(special)e(driver)g(to) h(read)g(an)g(input)f(FITS)h(file)f(from)h(the)g(stdin)907 4698 y(stream,)f(and/or)g(write)g(an)h(output)f(FITS)h(file)g(to)g(the) g(stdout)143 4811 y(stream.)94 b(This)46 b(driver)g(is)i(fragile)d(and) i(has)g(limited)143 4924 y(functionality)d(\(see)j(the)g(following)e (note\).)286 5036 y(gsiftp://)93 b(-)48 b(access)e(files)g(on)h(a)h (computational)c(grid)j(using)f(the)h(gridftp)907 5149 y(protocol)e(in)j(the)e(Globus)h(toolkit)e(\(see)i(following)e(note\).) 382 5262 y(root://)93 b(-)48 b(uses)e(the)h(CERN)g(root)g(protocol)e (for)i(writing)f(as)h(well)g(as)907 5375 y(reading)f(files)g(over)h (the)g(network)e(\(see)i(following)e(note\).)334 5488 y(shmem://)93 b(-)48 b(opens)e(or)h(creates)f(a)i(file)e(which)h (persists)e(in)i(the)g(computer's)907 5601 y(shared)f(memory)g(\(see)h (following)e(note\).)430 5714 y(mem://)93 b(-)48 b(opens)e(a)i (temporary)d(file)i(in)g(core)f(memory.)94 b(The)47 b(file)p eop end %%Page: 129 137 TeXDict begin 129 136 bop 0 299 a Fh(10.2.)73 b(FILETYPE)3037 b Fj(129)907 555 y Fe(disappears)45 b(when)h(the)h(program)f(exits)h (so)g(this)f(is)i(mainly)907 668 y(useful)e(for)h(test)f(purposes)g (when)h(a)g(permanent)e(output)h(file)907 781 y(is)h(not)g(desired.)0 1021 y Fj(If)35 b(the)h(\014let)m(yp)s(e)g(is)f(not)h(sp)s(eci\014ed,)h (then)e(t)m(yp)s(e)h(\014le://)h(is)e(assumed.)56 b(The)35 b(double)g(slashes)h('//')h(are)f(optional)0 1134 y(and)30 b(ma)m(y)h(b)s(e)e(omitted)j(in)e(most)h(cases.)0 1421 y Fd(10.2.1)113 b(Notes)36 b(ab)s(out)j(HTTP)d(pro)m(xy)i(serv)m(ers)0 1640 y Fj(A)32 b(pro)m(xy)g(HTTP)f(serv)m(er)h(ma)m(y)h(b)s(e)e(used)g (b)m(y)h(de\014ning)f(the)h(address)f(\(URL\))i(and)e(p)s(ort)g(n)m(um) m(b)s(er)g(of)h(the)g(pro)m(xy)0 1753 y(serv)m(er)f(with)f(the)g(h)m (ttp)p 801 1753 28 4 v 33 w(pro)m(xy)g(en)m(vironmen)m(t)h(v)-5 b(ariable.)42 b(F)-8 b(or)31 b(example)191 1993 y Fe(setenv)46 b(http_proxy)f(http://heasarc.gsfc.nasa)o(.gov)o(:312)o(8)0 2233 y Fj(will)38 b(cause)g(CFITSIO)f(to)h(use)g(p)s(ort)f(3128)i(on)f (the)g(heasarc)g(pro)m(xy)g(serv)m(er)g(whenev)m(er)g(reading)g(a)g (FITS)f(\014le)0 2346 y(with)30 b(HTTP)-8 b(.)0 2633 y Fd(10.2.2)113 b(Notes)36 b(ab)s(out)j(HTTPS)d(and)j(FTPS)e(\014le)h (access)0 2852 y Fj(CFITSIO)33 b(dep)s(ends)g(up)s(on)g(the)h(a)m(v)-5 b(ailabilit)m(y)38 b(of)d(the)g(lib)s(curl)e(library)i(in)f(order)g(to) h(p)s(erform)e(HTTPS/FTPS)0 2965 y(\014le)d(access.)42 b(\(This)29 b(should)g(b)s(e)g(the)h(dev)m(elopmen)m(t)h(v)m(ersion)f (of)g(the)g(library)-8 b(,)31 b(as)f(it)g(con)m(tains)h(the)f(curl.h)f (header)0 3078 y(\014le)g(required)g(b)m(y)g(the)g(CFITSIO)f(co)s (de.\))40 b(The)29 b(CFITSIO)f('con\014gure')h(script)g(will)h(searc)m (h)f(for)g(this)g(library)g(on)0 3191 y(y)m(our)h(system,)h(and)f(if)g (it)h(\014nds)e(it)i(it)g(will)f(automatically)k(b)s(e)29 b(incorp)s(orated)i(in)m(to)g(the)g(build.)0 3351 y(Note)43 b(that)g(if)f(y)m(ou)g(ha)m(v)m(e)i(this)e(library)f(pac)m(k)-5 b(age)44 b(on)e(y)m(our)g(system,)k(y)m(ou)c(will)h(also)g(ha)m(v)m(e)g (the)f('curl-con\014g')0 3464 y(executable.)i(Y)-8 b(ou)31 b(can)h(run)d(the)i('curl-con\014g')h(executable)g(with)f(v)-5 b(arious)31 b(options)g(to)h(learn)f(more)g(ab)s(out)g(the)0 3577 y(features)g(of)f(y)m(our)h(lib)s(curl)e(installation.)0 3737 y(If)20 b(the)g(CFITSIO)f('con\014gure')i(succeeded)f(in)g (\014nding)f(a)i(usable)f(lib)s(curl,)i(y)m(ou)e(will)h(see)g(the)f (\015ag)h('-DCFITSIO)p 3766 3737 V 32 w(HA)-10 b(VE)p 4054 3737 V 33 w(CURL=1')0 3850 y(in)34 b(the)g(CFITSIO)f(Mak)m (e\014le)j(and)e(in)f(the)i(compilation)h(output.)52 b(If)33 b('con\014gure')i(is)f(unable)g(to)h(\014nd)d(a)j(usable)0 3963 y(lib)s(curl,)30 b(CFITSIO)f(will)h(still)i(build)d(but)h(it)h(w)m (on't)g(ha)m(v)m(e)g(HTTPS/FTPS)e(capabilit)m(y)-8 b(.)0 4123 y(The)32 b(lib)s(curl)g(pac)m(k)-5 b(age)34 b(is)f(normally)g (included)e(as)i(part)g(of)f(Xco)s(de)h(on)g(Macs.)48 b(Ho)m(w)m(ev)m(er)35 b(on)d(Lin)m(ux)g(platforms)0 4236 y(y)m(ou)f(ma)m(y)g(need)f(to)h(man)m(ually)h(install)f(it.)42 b(This)29 b(can)i(b)s(e)f(easily)i(done)e(on)g(Ubun)m(tu)g(Lin)m(ux)g (using)g(the)h('apt)g(get')0 4349 y(command)f(to)h(retriev)m(e)h(the)f (lib)s(curl4-op)s(enssl-dev)f(or)g(the)g(lib)s(curl4-gn)m(utls-dev)h (pac)m(k)-5 b(ages.)0 4509 y(When)27 b(accessing)h(a)f(\014le)g(with)g (HTTPS)e(or)i(FTPS,)f(the)h(default)g(CFITSIO)f(b)s(eha)m(vior)h(is)f (to)i(attempt)g(to)g(v)m(erify)0 4622 y(b)s(oth)f(the)g(host)g(name)h (and)e(the)i(SSL)e(certi\014cate.)42 b(If)27 b(it)g(cannot,)i(it)f (will)g(still)g(p)s(erform)e(the)h(\014le)g(access)i(but)e(will)0 4735 y(issue)j(a)h(w)m(arning)f(to)h(the)g(terminal)g(windo)m(w.)0 4895 y(The)36 b(user)f(can)i(o)m(v)m(erride)g(this)f(b)s(eha)m(vior)h (to)g(force)f(CFITSIO)f(to)i(only)f(allo)m(w)i(\014le)f(transfers)e (when)g(the)i(host)0 5008 y(name)47 b(and)e(SSL)h(certi\014cate)i(ha)m (v)m(e)g(b)s(een)e(successfully)g(v)m(eri\014ed.)89 b(This)46 b(is)g(done)h(b)m(y)f(setting)i(the)e(CFIT-)0 5121 y(SIO)p 160 5121 V 32 w(VERIFY)p 549 5121 V 33 w(HTTPS)29 b(en)m(vironmen)m(t)i (v)-5 b(ariable)31 b(to)g('T)-8 b(rue'.)41 b(ie.)g(in)30 b(a)h(csh)f(shell:)0 5281 y(seten)m(v)h(CFITSIO)p 662 5281 V 32 w(VERIFY)p 1051 5281 V 33 w(HTTPS)e(T)-8 b(rue)0 5441 y(the)31 b(default)f(setting)i(for)e(this)g(is)g('F)-8 b(alse'.)0 5601 y(CFITSIO)19 b(has)h(3)g(functions)g(whic)m(h)g(apply)g (sp)s(eci\014cally)h(to)g(HTTPS/FTPS)e(access:)37 b(\014ts)p 3079 5601 V 32 w(init)p 3247 5601 V 34 w(h)m(ttps,)22 b(\014ts)p 3655 5601 V 33 w(clean)m(up)p 3988 5601 V 33 w(h)m(ttps,)0 5714 y(and)37 b(\014ts)p 311 5714 V 33 w(v)m(erb)s(ose)p 640 5714 V 32 w(h)m(ttps.)63 b(It)38 b(is)f(recommended)h(that)g(y)m(ou)g(call)h(the)f(init)g(and)f(clean)m (up)h(functions)f(near)h(the)p eop end %%Page: 130 138 TeXDict begin 130 137 bop 0 299 a Fj(130)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(b)s(eginning)42 b(and)g(end)g(of)h(y)m(our)g(program)f(resp)s (ectiv)m(ely)-8 b(.)80 b(F)-8 b(or)44 b(more)e(information)h(ab)s(out)g (these)g(functions,)0 668 y(please)30 b(see)f(the)g('FITS)f(File)i (Access)g(Routines')g(section)f(in)g(the)g(preceding)g(c)m(hapter)g (\('Sp)s(ecialized)h(CFITSIO)0 781 y(In)m(terface)i(Routines'\).)0 1085 y Fd(10.2.3)113 b(Notes)36 b(ab)s(out)j(the)e(stream)h(\014let)m (yp)s(e)g(driv)m(er)0 1306 y Fj(The)e(stream)h(driv)m(er)f(can)h(b)s(e) f(used)g(to)h(e\016cien)m(tly)i(read)d(a)h(FITS)f(\014le)h(from)f(the)h (stdin)f(\014le)g(stream)h(or)g(write)0 1419 y(a)44 b(FITS)e(to)i(the)g (stdout)f(\014le)g(stream.)80 b(Ho)m(w)m(ev)m(er,)49 b(b)s(ecause)43 b(these)h(input)e(and)h(output)g(streams)g(m)m(ust)h(b) s(e)0 1532 y(accessed)30 b(sequen)m(tially)-8 b(,)31 b(the)e(FITS)f(\014le)g(reading)h(or)f(writing)h(application)h(m)m(ust) e(also)i(read)e(and)g(write)h(the)g(\014le)0 1645 y(sequen)m(tially)-8 b(,)33 b(at)e(least)g(within)f(the)h(tolerances)h(describ)s(ed)d(b)s (elo)m(w.)0 1805 y(CFITSIO)34 b(supp)s(orts)f(2)j(di\013eren)m(t)f (metho)s(ds)g(for)g(accessing)i(FITS)d(\014les)h(on)h(the)f(stdin)g (and)f(stdout)h(streams.)0 1918 y(The)c(original)i(metho)s(d,)f(whic)m (h)f(is)h(in)m(v)m(ok)m(ed)h(b)m(y)f(sp)s(ecifying)f(a)h(dash)f(c)m (haracter,)j("-",)g(as)d(the)h(name)g(of)g(the)g(\014le)0 2031 y(when)g(op)s(ening)g(or)h(creating)h(it,)g(w)m(orks)e(b)m(y)h (storing)g(a)g(complete)h(cop)m(y)g(of)f(the)g(en)m(tire)g(FITS)f (\014le)h(in)f(memory)-8 b(.)0 2144 y(In)35 b(this)g(case,)k(when)34 b(reading)i(from)f(stdin,)i(CFITSIO)d(will)i(cop)m(y)h(the)e(en)m(tire) i(stream)f(in)m(to)h(memory)e(b)s(efore)0 2257 y(doing)c(an)m(y)h(pro)s (cessing)f(of)h(the)f(\014le.)44 b(Similarly)-8 b(,)32 b(when)f(writing)g(to)h(stdout,)g(CFITSIO)d(will)j(create)h(a)f(cop)m (y)g(of)0 2370 y(the)h(en)m(tire)g(FITS)f(\014le)g(in)h(memory)-8 b(,)33 b(b)s(efore)f(\014nally)h(\015ushing)e(it)i(out)f(to)i(the)e (stdout)h(stream)g(when)e(the)i(FITS)0 2483 y(\014le)g(is)g(closed.)49 b(Bu\013ering)33 b(the)g(en)m(tire)h(FITS)e(\014le)h(in)g(this)f(w)m(a) m(y)i(allo)m(ws)g(the)f(application)i(to)e(randomly)g(access)0 2596 y(an)m(y)h(part)f(of)h(the)f(FITS)g(\014le,)i(in)e(an)m(y)h (order,)f(but)g(it)h(also)h(requires)e(that)h(the)f(user)g(ha)m(v)m(e)i (su\016cien)m(t)f(a)m(v)-5 b(ailable)0 2708 y(memory)30 b(\(or)g(virtual)g(memory\))g(to)h(store)f(the)g(en)m(tire)h(\014le,)f (whic)m(h)f(ma)m(y)i(not)f(b)s(e)f(p)s(ossible)g(in)h(the)g(case)h(of)f (v)m(ery)0 2821 y(large)h(\014les.)0 2981 y(The)e(new)m(er)g(stream)h (\014let)m(yp)s(e)g(pro)m(vides)f(a)h(more)f(memory-e\016cien)m(t)i (metho)s(d)e(of)h(accessing)h(FITS)d(\014les)h(on)h(the)0 3094 y(stdin)37 b(or)h(stdout)g(streams.)64 b(Instead)38 b(of)g(storing)g(a)g(cop)m(y)h(of)f(the)g(en)m(tire)h(FITS)e(\014le)h (in)g(memory)-8 b(,)40 b(CFITSIO)0 3207 y(only)32 b(uses)g(a)g(set)h (of)f(in)m(ternal)h(bu\013er)e(whic)m(h)h(b)m(y)g(default)g(can)g (store)h(40)g(FITS)e(blo)s(c)m(ks,)i(or)g(ab)s(out)e(100K)i(b)m(ytes)0 3320 y(of)f(the)f(FITS)g(\014le.)43 b(The)31 b(application)i(program)e (m)m(ust)g(pro)s(cess)g(the)h(FITS)e(\014le)i(sequen)m(tially)h(from)e (b)s(eginning)0 3433 y(to)h(end,)e(within)g(this)h(100K)h(bu\013er.)41 b(Generally)32 b(sp)s(eaking)f(the)g(application)h(program)f(m)m(ust)f (conform)h(to)h(the)0 3546 y(follo)m(wing)g(restrictions:)136 3817 y Fc(\017)46 b Fj(The)36 b(program)f(m)m(ust)h(\014nish)e(reading) i(or)g(writing)f(the)h(header)g(k)m(eyw)m(ords)g(b)s(efore)f(reading)h (or)g(writing)227 3930 y(an)m(y)31 b(data)g(in)f(the)h(HDU.)136 4129 y Fc(\017)46 b Fj(The)24 b(HDU)h(can)f(con)m(tain)i(at)e(most)h (ab)s(out)f(1400)h(header)f(k)m(eyw)m(ords.)39 b(This)24 b(is)g(the)g(maxim)m(um)g(that)h(can)f(\014t)227 4241 y(in)g(the)g(nominal)h(40)g(FITS)e(blo)s(c)m(k)i(bu\013er.)37 b(In)24 b(principle,)h(this)f(limit)h(could)f(b)s(e)g(increased)g(b)m (y)g(recompiling)227 4354 y(CFITSIO)29 b(with)h(a)h(larger)g(bu\013er)e (limit,)j(whic)m(h)e(is)g(set)h(b)m(y)f(the)h(NIOBUF)g(parameter)g(in)f (\014tsio2.h.)136 4553 y Fc(\017)46 b Fj(The)32 b(program)g(m)m(ust)f (read)h(or)g(write)h(the)f(data)g(in)g(a)g(sequen)m(tial)i(manner)d (from)h(the)g(b)s(eginning)f(to)i(the)227 4666 y(end)26 b(of)g(the)h(HDU.)g(Note)h(that)f(CFITSIO's)e(in)m(ternal)i(100K)g (bu\013er)e(allo)m(ws)j(a)e(little)j(latitude)e(in)f(meeting)227 4779 y(this)31 b(requiremen)m(t.)136 4978 y Fc(\017)46 b Fj(The)30 b(program)g(cannot)h(mo)m(v)m(e)h(bac)m(k)f(to)g(a)g (previous)f(HDU)h(in)f(the)h(FITS)e(\014le.)136 5176 y Fc(\017)46 b Fj(Reading)c(or)f(writing)f(of)h(v)-5 b(ariable)42 b(length)f(arra)m(y)h(columns)e(in)h(binary)f(tables)i(is) f(not)g(supp)s(orted)e(on)227 5289 y(streams,)29 b(b)s(ecause)f(this)g (requires)g(mo)m(ving)g(bac)m(k)h(and)f(forth)f(b)s(et)m(w)m(een)i(the) f(\014xed-length)g(p)s(ortion)g(of)g(the)227 5402 y(binary)i(table)h (and)f(the)g(follo)m(wing)i(heap)e(area)i(where)e(the)g(arra)m(ys)h (are)g(actually)h(stored.)136 5601 y Fc(\017)46 b Fj(Reading)25 b(or)g(writing)f(of)h(tile-compressed)h(images)g(is)e(not)h(supp)s (orted)e(on)h(streams,)i(b)s(ecause)f(the)g(images)227 5714 y(are)31 b(in)m(ternally)g(stored)g(using)f(v)-5 b(ariable)31 b(length)g(arra)m(ys.)p eop end %%Page: 131 139 TeXDict begin 131 138 bop 0 299 a Fh(10.2.)73 b(FILETYPE)3037 b Fj(131)0 555 y Fd(10.2.4)113 b(Notes)36 b(ab)s(out)j(the)e(gsiftp)h (\014let)m(yp)s(e)0 774 y Fj(DEPENDENCIES:)c(Globus)h(to)s(olkit)h (\(2.4.3)g(or)f(higher\))f(\(GT\))h(should)f(b)s(e)g(installed.)53 b(There)34 b(are)h(t)m(w)m(o)h(dif-)0 887 y(feren)m(t)31 b(w)m(a)m(ys)g(to)g(install)g(GT:)0 1047 y(1\))43 b(goto)h(the)f (globus)f(to)s(olkit)i(w)m(eb)e(page)i(www.globus.org)e(and)g(follo)m (w)h(the)g(do)m(wnload)g(and)e(compilation)0 1160 y(instructions;)0 1320 y(2\))j(goto)i(the)d(Virtual)i(Data)g(T)-8 b(o)s(olkit)45 b(w)m(eb)e(page)i(h)m(ttp://vdt.cs.wisc.edu/)g(and)e(follo)m(w)i(the)f (instructions)0 1433 y(\(STR)m(ONGL)-8 b(Y)31 b(SUGGESTED\);)0 1593 y(Once)23 b(a)h(globus)f(clien)m(t)h(has)f(b)s(een)g(installed)h (in)e(y)m(our)i(system)f(with)g(a)g(sp)s(eci\014c)g(\015a)m(v)m(our)h (it)f(is)g(p)s(ossible)g(to)h(compile)0 1706 y(and)30 b(install)h(the)g(CFITSIO)d(libraries.)41 b(Sp)s(eci\014c)30 b(con\014guration)h(\015ags)f(m)m(ust)h(b)s(e)e(used:)0 1866 y(1\))21 b({with-gsiftp[[=P)-8 b(A)g(TH]])22 b(Enable)f(Globus)f (T)-8 b(o)s(olkit)21 b(gsiftp)g(proto)s(col)g(supp)s(ort)d(P)-8 b(A)g(TH=GLOBUS)p 3532 1866 28 4 v 33 w(LOCA)g(TION)0 1979 y(i.e.)42 b(the)30 b(lo)s(cation)i(of)f(y)m(our)f(globus)g (installation)0 2139 y(2\))h({with-gsiftp-\015a)m(v)m(our[[=P)-8 b(A)g(TH])33 b(de\014nes)d(the)g(sp)s(eci\014c)g(Globus)h(\015a)m(v)m (our)f(ex.)41 b(gcc32)0 2300 y(Both)31 b(the)g(\015ags)f(m)m(ust)g(b)s (e)g(used)g(and)f(it)i(is)g(mandatory)f(to)h(set)g(b)s(oth)f(the)g(P)-8 b(A)g(TH)31 b(and)f(the)h(\015a)m(v)m(our.)0 2460 y(USA)m(GE:)g(T)-8 b(o)31 b(access)h(\014les)e(on)g(a)h(gridftp)f(serv)m(er)g(it)h(is)g (necessary)f(to)i(use)e(a)g(gsiftp)h(pre\014x:)0 2620 y(example:)41 b(gsiftp://remote)p 1003 2620 V 35 w(serv)m(er)p 1271 2620 V 34 w(fqhn/directory/\014lename)0 2780 y(The)f(gridftp)g (driv)m(er)g(uses)g(a)g(lo)s(cal)i(bu\013er)d(on)i(a)f(temp)s(orary)g (\014le)h(the)f(\014le)h(is)f(lo)s(cated)i(in)e(the)g(/tmp)h(direc-)0 2893 y(tory)-8 b(.)73 b(If)40 b(y)m(ou)h(ha)m(v)m(e)h(sp)s(ecial)g(p)s (ermissions)d(on)i(/tmp)g(or)g(y)m(ou)g(do)f(not)i(ha)m(v)m(e)g(a)f (/tmp)g(directory)-8 b(,)44 b(it)e(is)e(p)s(os-)0 3006 y(sible)d(to)h(force)g(another)g(lo)s(cation)g(setting)h(the)e(GSIFTP)p 2068 3006 V 32 w(TMPFILE)g(en)m(vironmen)m(t)h(v)-5 b(ariable)38 b(\(ex.)62 b(exp)s(ort)0 3119 y(GSIFTP)p 347 3119 V 32 w(TMPFILE=/y)m(our/lo)s(cation/y)m(ourtmp\014le\).)0 3279 y(Grid)34 b(FTP)g(supp)s(orts)f(m)m(ulti)h(c)m(hannel)h(transfer.) 52 b(By)35 b(default)f(a)h(single)g(c)m(hannel)g(transmission)f(is)g(a) m(v)-5 b(ailable.)0 3392 y(Ho)m(w)m(ev)m(er,)34 b(it)d(is)h(p)s (ossible)e(to)i(mo)s(dify)e(this)i(b)s(eha)m(vior)f(setting)h(the)f (GSIFTP)p 2691 3392 V 33 w(STREAMS)f(en)m(vironmen)m(t)h(v)-5 b(ari-)0 3505 y(able)31 b(\(ex.)41 b(exp)s(ort)30 b(GSIFTP)p 1016 3505 V 33 w(STREAMS=8\).)0 3790 y Fd(10.2.5)113 b(Notes)36 b(ab)s(out)j(the)e(ro)s(ot)g(\014let)m(yp)s(e)0 4009 y Fj(The)20 b(original)j(ro)s(otd)d(serv)m(er)h(can)h(b)s(e)e (obtained)h(from:)36 b Fe(ftp://root.cern.ch/root)o(/roo)o(td.t)o(ar.)o (gz)15 b Fj(but,)22 b(for)0 4122 y(it)33 b(to)h(w)m(ork)f(correctly)h (with)e(CFITSIO)g(one)h(has)f(to)i(use)e(a)i(mo)s(di\014ed)d(v)m (ersion)j(whic)m(h)e(supp)s(orts)f(a)i(command)0 4235 y(to)41 b(return)d(the)j(length)f(of)g(the)g(\014le.)70 b(This)39 b(mo)s(di\014ed)f(v)m(ersion)j(is)f(a)m(v)-5 b(ailable)42 b(in)e(ro)s(otd)f(sub)s(directory)g(in)h(the)0 4348 y(CFITSIO)29 b(ftp)h(area)h(at)286 4577 y Fe (ftp://legacy.gsfc.nasa.gov)o(/so)o(ftwa)o(re/f)o(its)o(io/c)o(/roo)o (t/r)o(ootd)o(.tar)o(.gz)o(.)0 4805 y Fj(This)j(small)g(serv)m(er)h(is) g(started)f(either)h(b)m(y)g(inetd)f(when)f(a)i(clien)m(t)h(requests)e (a)h(connection)h(to)f(a)f(ro)s(otd)h(serv)m(er)0 4918 y(or)30 b(b)m(y)g(hand)f(\(i.e.)42 b(from)30 b(the)g(command)g(line\).) 42 b(The)29 b(ro)s(otd)h(serv)m(er)h(w)m(orks)f(with)g(the)g(R)m(OOT)g (TNetFile)i(class.)0 5031 y(It)e(allo)m(ws)g(remote)h(access)f(to)h(R)m (OOT)e(database)h(\014les)f(in)g(either)h(read)g(or)f(write)h(mo)s(de.) 40 b(By)30 b(default)f(TNetFile)0 5144 y(assumes)38 b(p)s(ort)g(432)h (\(whic)m(h)f(requires)g(ro)s(otd)g(to)h(b)s(e)f(started)h(as)f(ro)s (ot\).)65 b(T)-8 b(o)39 b(run)e(ro)s(otd)h(via)h(inetd)f(add)g(the)0 5257 y(follo)m(wing)32 b(line)f(to)g(/etc/services:)95 5485 y Fe(rootd)238 b(432/tcp)0 5714 y Fj(and)30 b(to)h (/etc/inetd.conf,)i(add)d(the)g(follo)m(wing)i(line:)p eop end %%Page: 132 140 TeXDict begin 132 139 bop 0 299 a Fj(132)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)95 555 y Fe(rootd)47 b(stream)f(tcp)h(nowait)f(root)h (/user/rdm/root/bin/root)o(d)42 b(rootd)k(-i)0 829 y Fj(F)-8 b(orce)30 b(inetd)e(to)h(reread)f(its)h(conf)f(\014le)g(with)g Fe(kill)47 b(-HUP)g()p Fj(.)39 b(Y)-8 b(ou)28 b(can)h(also)g(start)g(ro)s(otd)f(b)m(y)g(hand)0 942 y(running)35 b(directly)i(under)d(y)m(our)j(priv)-5 b(ate)37 b(accoun)m(t)g(\(no)g(ro)s(ot)g(system)f(privileges)h(needed\).)59 b(F)-8 b(or)37 b(example)g(to)0 1054 y(start)e(ro)s(otd)g(listening)g (on)g(p)s(ort)f(5151)j(just)d(t)m(yp)s(e:)49 b Fe(rootd)e(-p)g(5151)33 b Fj(Notice)k(that)f(no)e(&)h(is)f(needed.)54 b(Ro)s(otd)0 1167 y(will)31 b(go)g(in)m(to)g(bac)m(kground)f(b)m(y)h(itself.)95 1441 y Fe(Rootd)47 b(arguments:)191 1554 y(-i)763 b(says)47 b(we)g(were)f(started)g(by)h(inetd)191 1667 y(-p)g(port#)476 b(specifies)45 b(a)j(different)d(port)i(to)g(listen)f(on)191 1780 y(-d)h(level)476 b(level)46 b(of)i(debug)e(info)h(written)e(to)j (syslog)1050 1893 y(0)f(=)h(no)f(debug)f(\(default\))1050 2005 y(1)h(=)h(minimum)1050 2118 y(2)f(=)h(medium)1050 2231 y(3)f(=)h(maximum)0 2505 y Fj(Ro)s(otd)29 b(can)f(also)h(b)s(e)f (con\014gured)g(for)g(anon)m(ymous)g(usage)h(\(lik)m(e)h(anon)m(ymous)e (ftp\).)40 b(T)-8 b(o)29 b(setup)f(ro)s(otd)g(to)h(accept)0 2618 y(anon)m(ymous)h(logins)h(do)g(the)f(follo)m(wing)i(\(while)f(b)s (eing)f(logged)i(in)e(as)g(ro)s(ot\):)143 2891 y Fe(-)48 b(Add)f(the)f(following)g(line)g(to)i(/etc/passwd:)239 3117 y(rootd:*:71:72:Anonymous)41 b(rootd:/var/spool/rootd:/b)o(in/)o (fals)o(e)239 3343 y(where)46 b(you)h(may)g(modify)f(the)h(uid,)f(gid)h (\(71,)g(72\))g(and)g(the)g(home)f(directory)239 3456 y(to)h(suite)f(your)h(system.)143 3681 y(-)h(Add)f(the)f(following)g (line)g(to)i(/etc/group:)239 3907 y(rootd:*:72:rootd)239 4133 y(where)e(the)h(gid)g(must)f(match)h(the)g(gid)g(in)g (/etc/passwd.)143 4359 y(-)h(Create)e(the)h(directories:)239 4585 y(mkdir)f(/var/spool/rootd)239 4698 y(mkdir)g (/var/spool/rootd/tmp)239 4811 y(chmod)g(777)h(/var/spool/rootd/tmp)239 5036 y(Where)f(/var/spool/rootd)d(must)k(match)f(the)h(rootd)g(home)f (directory)g(as)239 5149 y(specified)f(in)i(the)g(rootd)f(/etc/passwd)f (entry.)143 5375 y(-)j(To)f(make)f(writeable)g(directories)e(for)j (anonymous)f(do,)h(for)f(example:)239 5601 y(mkdir)g (/var/spool/rootd/pub)239 5714 y(chown)g(rootd:rootd)f (/var/spool/rootd/pub)p eop end %%Page: 133 141 TeXDict begin 133 140 bop 0 299 a Fh(10.3.)73 b(BASE)30 b(FILENAME)2739 b Fj(133)0 555 y(That's)42 b(all.)76 b(Sev)m(eral)43 b(additional)g(remarks:)64 b(y)m(ou)42 b(can)g(login)h(to)g(an)f(anon)m(ymous)f(serv)m(er)i(either)f(with)g (the)0 668 y(names)31 b("anon)m(ymous")h(or)f("ro)s(otd".)43 b(The)31 b(passw)m(ord)f(should)g(b)s(e)h(of)g(t)m(yp)s(e)g (user@host.do.main.)43 b(Only)30 b(the)h(@)0 781 y(is)e(enforced)f(for) h(the)f(time)i(b)s(eing.)39 b(In)28 b(anon)m(ymous)h(mo)s(de)f(the)g (top)h(of)g(the)g(\014le)f(tree)i(is)e(set)h(to)h(the)e(ro)s(otd)h (home)0 894 y(directory)-8 b(,)39 b(therefore)e(only)f(\014les)h(b)s (elo)m(w)f(the)h(home)f(directory)h(can)f(b)s(e)g(accessed.)60 b(Anon)m(ymous)36 b(mo)s(de)g(only)0 1007 y(w)m(orks)30 b(when)g(the)g(serv)m(er)h(is)f(started)h(via)g(inetd.)0 1296 y Fd(10.2.6)113 b(Notes)36 b(ab)s(out)j(the)e(shmem)i(\014let)m (yp)s(e:)0 1515 y Fj(Shared)34 b(memory)h(\014les)g(are)g(curren)m(tly) g(supp)s(orted)e(on)i(most)h(Unix)f(platforms,)h(where)f(the)g(shared)f (memory)0 1627 y(segmen)m(ts)d(are)g(managed)g(b)m(y)f(the)g(op)s (erating)h(system)g(k)m(ernel)f(and)g(`liv)m(e')i(indep)s(enden)m(tly)d (of)i(pro)s(cesses.)40 b(They)0 1740 y(are)34 b(not)g(deleted)h(\(b)m (y)f(default\))g(when)f(the)h(pro)s(cess)f(whic)m(h)h(created)h(them)f (terminates,)h(although)g(they)f(will)0 1853 y(disapp)s(ear)e(if)h(the) h(system)f(is)g(reb)s(o)s(oted.)49 b(Applications)34 b(can)g(create)h(shared)d(memory)h(\014les)g(in)g(CFITSIO)f(b)m(y)0 1966 y(calling:)143 2214 y Fe(fit_create_file\(&fitsfile)o(ptr,)41 b("shmem://h2",)j(&status\);)0 2462 y Fj(where)25 b(the)g(ro)s(ot)h (`\014le')f(names)h(are)f(curren)m(tly)g(restricted)h(to)g(b)s(e)f ('h0',)i('h1',)g('h2',)g('h3',)f(etc.,)i(up)d(to)g(a)h(maxim)m(um)0 2575 y(n)m(um)m(b)s(er)20 b(de\014ned)f(b)m(y)i(the)g(the)g(v)-5 b(alue)22 b(of)f(SHARED)p 1746 2575 28 4 v 33 w(MAXSEG)g(\(equal)h(to)f (16)h(b)m(y)f(default\).)38 b(This)20 b(is)h(a)g(protot)m(yp)s(e)0 2688 y(implemen)m(tation)30 b(of)f(the)g(shared)f(memory)g(in)m (terface)i(and)e(a)h(more)g(robust)f(in)m(terface,)j(whic)m(h)d(will)h (ha)m(v)m(e)h(few)m(er)0 2801 y(restrictions)h(on)f(the)h(n)m(um)m(b)s (er)e(of)i(\014les)f(and)g(on)g(their)g(names,)h(ma)m(y)g(b)s(e)f(dev)m (elop)s(ed)g(in)g(the)h(future.)0 2961 y(When)23 b(op)s(ening)h(an)f (already)h(existing)h(FITS)e(\014le)h(in)f(shared)g(memory)h(one)g (calls)g(the)g(usual)g(CFITSIO)e(routine:)143 3209 y Fe(fits_open_file\(&fitsfilep)o(tr,)41 b("shmem://h7",)j(mode,)j (&status\))0 3457 y Fj(The)26 b(\014le)h(mo)s(de)g(can)g(b)s(e)f(READ)m (WRITE)h(or)g(READONL)-8 b(Y)28 b(just)e(as)h(with)f(disk)h(\014les.)39 b(More)28 b(than)e(one)h(pro)s(cess)0 3570 y(can)35 b(op)s(erate)g(on)f (READONL)-8 b(Y)35 b(mo)s(de)f(\014les)h(at)g(the)f(same)h(time.)54 b(CFITSIO)33 b(supp)s(orts)f(prop)s(er)h(\014le)i(lo)s(c)m(king)0 3682 y(\(b)s(oth)27 b(in)h(READONL)-8 b(Y)29 b(and)e(READ)m(WRITE)h(mo) s(des\),)h(so)f(calls)h(to)f(\014ts)p 2572 3682 V 33 w(op)s(en)p 2795 3682 V 32 w(\014le)g(ma)m(y)g(b)s(e)f(lo)s(c)m(k)m(ed) j(out)e(un)m(til)0 3795 y(another)j(other)f(pro)s(cess)g(closes)i(the)e (\014le.)0 3956 y(When)g(an)g(application)i(is)e(\014nished)f (accessing)j(a)e(FITS)g(\014le)g(in)g(a)h(shared)e(memory)h(segmen)m (t,)i(it)f(ma)m(y)g(close)g(it)0 4068 y(\(and)j(the)g(\014le)g(will)g (remain)f(in)h(the)g(system\))g(with)g(\014ts)p 1955 4068 V 32 w(close)p 2173 4068 V 34 w(\014le,)h(or)f(delete)h(it)g(with) e(\014ts)p 3191 4068 V 33 w(delete)p 3455 4068 V 34 w(\014le.)51 b(Ph)m(ys-)0 4181 y(ical)36 b(deletion)g(is)f(p)s(ostp)s(oned)e(un)m (til)j(the)f(last)g(pro)s(cess)g(calls)h(\013clos/\013delt.)56 b(\014ts)p 2801 4181 V 32 w(delete)p 3064 4181 V 34 w(\014le)35 b(tries)h(to)f(obtain)h(a)0 4294 y(READ)m(WRITE)e(lo)s(c)m(k)g(on)f (the)g(\014le)h(to)g(b)s(e)e(deleted,)j(th)m(us)e(it)h(can)f(b)s(e)g (blo)s(c)m(k)m(ed)h(if)f(the)h(ob)5 b(ject)34 b(w)m(as)f(not)h(op)s (ened)0 4407 y(in)c(READ)m(WRITE)h(mo)s(de.)0 4567 y(A)i(shared)f (memory)h(managemen)m(t)h(utilit)m(y)g(program)f(called)h(`smem',)f(is) g(included)f(with)h(the)g(CFITSIO)e(dis-)0 4680 y(tribution.)39 b(It)27 b(can)g(b)s(e)f(built)h(b)m(y)g(t)m(yping)g(`mak)m(e)h(smem';)g (then)f(t)m(yp)s(e)g(`smem)f(-h')h(to)h(get)g(a)f(list)g(of)g(v)-5 b(alid)27 b(options.)0 4793 y(Executing)37 b(smem)f(without)g(an)m(y)h (options)g(causes)f(it)h(to)g(list)g(all)g(the)g(shared)e(memory)i (segmen)m(ts)g(curren)m(tly)0 4906 y(residing)c(in)g(the)g(system)h (and)e(managed)i(b)m(y)f(the)h(shared)e(memory)h(driv)m(er.)49 b(T)-8 b(o)34 b(get)g(a)g(list)g(of)f(all)h(the)g(shared)0 5019 y(memory)c(ob)5 b(jects,)32 b(run)d(the)h(system)h(utilit)m(y)g (program)f(`ip)s(cs)h([-a]'.)0 5351 y Ff(10.3)136 b(Base)45 b(Filename)0 5601 y Fj(The)31 b(base)g(\014lename)h(is)f(the)h(name)f (of)h(the)f(\014le)h(optionally)g(including)f(the)h(director/sub)s (directory)f(path,)h(and)0 5714 y(in)e(the)h(case)g(of)g(`ftp',)f(`h)m (ttp',)i(and)d(`ro)s(ot')j(\014let)m(yp)s(es,)e(the)h(mac)m(hine)g (iden)m(ti\014er.)41 b(Examples:)p eop end %%Page: 134 142 TeXDict begin 134 141 bop 0 299 a Fj(134)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 555 y Fe(myfile.fits)191 668 y(!data.fits)191 781 y(/data/myfile.fits) 191 894 y(fits.gsfc.nasa.gov/ftp/s)o(ampl)o(eda)o(ta/m)o(yfil)o(e.f)o (its.)o(gz)0 1120 y Fj(When)29 b(creating)h(a)f(new)f(output)h(\014le)g (on)g(magnetic)h(disk)e(\(of)i(t)m(yp)s(e)f(\014le://\))h(if)f(the)g (base)g(\014lename)g(b)s(egins)f(with)0 1233 y(an)34 b(exclamation)j(p)s(oin)m(t)d(\(!\))54 b(then)34 b(an)m(y)g(existing)i (\014le)e(with)g(that)h(same)g(basename)g(will)g(b)s(e)e(deleted)i (prior)f(to)0 1346 y(creating)h(the)f(new)g(FITS)f(\014le.)51 b(Otherwise)34 b(if)g(the)g(\014le)g(to)g(b)s(e)g(created)h(already)f (exists,)i(then)d(CFITSIO)g(will)0 1459 y(return)g(an)h(error)f(and)g (will)i(not)f(o)m(v)m(erwrite)h(the)f(existing)h(\014le.)52 b(Note)35 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f(')10 b(!',)36 b(is)e(a)0 1572 y(sp)s(ecial)28 b(UNIX)g(c)m(haracter,)j(so)d (if)f(it)i(is)f(used)f(on)g(the)h(command)g(line)g(rather)g(than)f(en)m (tered)h(at)h(a)f(task)h(prompt,)0 1685 y(it)j(m)m(ust)f(b)s(e)g (preceded)g(b)m(y)h(a)g(bac)m(kslash)g(to)g(force)g(the)g(UNIX)g(shell) f(to)h(pass)f(it)i(v)m(erbatim)f(to)g(the)g(application)0 1798 y(program.)0 1958 y(If)24 b(the)i(output)e(disk)h(\014le)g(name)g (ends)f(with)g(the)h(su\016x)f('.gz',)k(then)d(CFITSIO)e(will)i (compress)g(the)g(\014le)g(using)g(the)0 2071 y(gzip)g(compression)f (algorithm)h(b)s(efore)f(writing)g(it)h(to)g(disk.)38 b(This)23 b(can)i(reduce)f(the)g(amoun)m(t)h(of)f(disk)g(space)h(used)0 2184 y(b)m(y)34 b(the)h(\014le.)53 b(Note)36 b(that)f(this)g(feature)g (requires)f(that)h(the)f(uncompressed)g(\014le)g(b)s(e)g(constructed)h (in)f(memory)0 2297 y(b)s(efore)c(it)h(is)f(compressed)g(and)g(written) h(to)g(disk,)f(so)g(it)h(can)g(fail)g(if)f(there)h(is)f(insu\016cien)m (t)h(a)m(v)-5 b(ailable)33 b(memory)-8 b(.)0 2457 y(An)45 b(input)g(FITS)f(\014le)i(ma)m(y)g(b)s(e)f(compressed)g(with)h(the)f (gzip)h(or)g(Unix)f(compress)h(algorithms,)k(in)45 b(whic)m(h)0 2570 y(case)38 b(CFITSIO)e(will)i(uncompress)e(the)i(\014le)g(on)f(the) h(\015y)e(in)m(to)j(a)f(temp)s(orary)f(\014le)g(\(in)h(memory)f(or)g (on)h(disk\).)0 2683 y(Compressed)32 b(\014les)i(ma)m(y)g(only)f(b)s(e) g(op)s(ened)f(with)h(read-only)h(p)s(ermission.)49 b(When)33 b(sp)s(ecifying)g(the)h(name)f(of)h(a)0 2796 y(compressed)h(FITS)g (\014le)h(it)g(is)g(not)g(necessary)g(to)g(app)s(end)e(the)i(\014le)g (su\016x)e(\(e.g.,)39 b(`.gz')e(or)f(`.Z'\).)g(If)f(CFITSIO)0 2908 y(cannot)24 b(\014nd)e(the)h(input)f(\014le)i(name)f(without)g (the)g(su\016x,)h(then)f(it)h(will)g(automatically)i(searc)m(h)e(for)f (a)g(compressed)0 3021 y(\014le)36 b(with)f(the)h(same)g(ro)s(ot)g (name.)57 b(In)35 b(the)h(case)h(of)f(reading)g(ftp)f(and)g(h)m(ttp)h (t)m(yp)s(e)g(\014les,)h(CFITSIO)e(generally)0 3134 y(lo)s(oks)j(for)g (a)g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(\014rst,)h(b)s (efore)e(trying)h(to)h(op)s(en)e(the)h(uncompressed)e(\014le.)64 b(By)0 3247 y(default,)37 b(CFITSIO)e(copies)h(\(and)g(uncompressed)e (if)i(necessary\))g(the)g(ftp)f(or)h(h)m(ttp)g(FITS)f(\014le)g(in)m(to) i(memory)0 3360 y(on)f(the)g(lo)s(cal)h(mac)m(hine)f(b)s(efore)g(op)s (ening)f(it.)58 b(This)35 b(will)h(fail)g(if)g(the)g(lo)s(cal)h(mac)m (hine)g(do)s(es)e(not)h(ha)m(v)m(e)h(enough)0 3473 y(memory)g(to)h (hold)f(the)g(whole)h(FITS)e(\014le,)k(so)d(in)g(this)g(case,)k(the)c (output)g(\014lename)g(sp)s(eci\014er)g(\(see)h(the)g(next)0 3586 y(section\))32 b(can)f(b)s(e)e(used)h(to)h(further)e(con)m(trol)j (ho)m(w)e(CFITSIO)f(reads)h(ftp)g(and)g(h)m(ttp)g(\014les.)0 3746 y(If)i(the)h(input)f(\014le)h(is)g(an)g(IRAF)g(image)h(\014le)f (\(*.imh)g(\014le\))h(then)e(CFITSIO)f(will)j(automatically)h(con)m(v)m (ert)g(it)e(on)0 3859 y(the)27 b(\015y)g(in)m(to)h(a)g(virtual)f(FITS)f (image)j(b)s(efore)e(it)g(is)g(op)s(ened)g(b)m(y)g(the)g(application)i (program.)39 b(IRAF)27 b(images)i(can)0 3972 y(only)h(b)s(e)g(op)s (ened)g(with)g(READONL)-8 b(Y)31 b(\014le)f(access.)0 4132 y(Similarly)-8 b(,)32 b(if)f(the)g(input)f(\014le)i(is)f(a)g(ra)m (w)g(binary)f(data)i(arra)m(y)-8 b(,)33 b(then)d(CFITSIO)g(will)h(con)m (v)m(ert)i(it)e(on)g(the)h(\015y)e(in)m(to)0 4245 y(a)38 b(virtual)g(FITS)g(image)h(with)e(the)h(basic)h(set)f(of)g(required)f (header)h(k)m(eyw)m(ords)g(b)s(efore)g(it)g(is)g(op)s(ened)f(b)m(y)h (the)0 4358 y(application)32 b(program)f(\(with)g(READONL)-8 b(Y)31 b(access\).)44 b(In)30 b(this)h(case)h(the)f(data)g(t)m(yp)s(e)g (and)g(dimensions)f(of)h(the)0 4471 y(image)d(m)m(ust)f(b)s(e)f(sp)s (eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)g(the)f (\014lename)g(\(e.g.)41 b(ra)m(w\014le.dat[ib512,512]\).)j(The)0 4584 y(\014rst)30 b(c)m(haracter)i(\(case)f(insensitiv)m(e\))h (de\014nes)e(the)g(data)h(t)m(yp)s(e)g(of)f(the)h(arra)m(y:)239 4810 y Fe(b)429 b(8-bit)46 b(unsigned)g(byte)239 4923 y(i)381 b(16-bit)46 b(signed)g(integer)239 5036 y(u)381 b(16-bit)46 b(unsigned)g(integer)239 5149 y(j)381 b(32-bit)46 b(signed)g(integer)239 5262 y(r)h(or)g(f)143 b(32-bit)46 b(floating)g(point)239 5375 y(d)381 b(64-bit)46 b(floating)g(point)0 5601 y Fj(An)40 b(optional)h(second)f(c)m(haracter)i(sp)s(eci\014es)e (the)h(b)m(yte)f(order)g(of)g(the)h(arra)m(y)g(v)-5 b(alues:)60 b(b)40 b(or)g(B)h(indicates)g(big)0 5714 y(endian)30 b(\(as)g(in)g(FITS)f(\014les)h(and)f(the)h(nativ)m(e)i(format)e(of)g (SUN)g(UNIX)g(w)m(orkstations)h(and)f(Mac)h(PCs\))e(and)h(l)g(or)p eop end %%Page: 135 143 TeXDict begin 135 142 bop 0 299 a Fh(10.4.)73 b(OUTPUT)29 b(FILE)h(NAME)h(WHEN)g(OPENING)f(AN)h(EXISTING)f(FILE)876 b Fj(135)0 555 y(L)27 b(indicates)i(little)g(endian)e(\(nativ)m(e)j (format)d(of)h(DEC)g(OSF)f(w)m(orkstations)h(and)f(IBM)h(PCs\).)40 b(If)27 b(this)g(c)m(haracter)0 668 y(is)f(omitted)g(then)f(the)h(arra) m(y)g(is)g(assumed)f(to)h(ha)m(v)m(e)h(the)f(nativ)m(e)g(b)m(yte)h (order)e(of)h(the)f(lo)s(cal)i(mac)m(hine.)40 b(These)25 b(data)0 781 y(t)m(yp)s(e)35 b(c)m(haracters)h(are)g(then)e(follo)m(w)m (ed)j(b)m(y)d(a)i(series)f(of)g(one)g(or)g(more)g(in)m(teger)h(v)-5 b(alues)35 b(separated)h(b)m(y)e(commas)0 894 y(whic)m(h)41 b(de\014ne)f(the)h(size)h(of)f(eac)m(h)h(dimension)f(of)g(the)g(ra)m(w) g(arra)m(y)-8 b(.)74 b(Arra)m(ys)41 b(with)f(up)g(to)i(5)f(dimensions)g (are)0 1007 y(curren)m(tly)31 b(supp)s(orted.)41 b(Finally)-8 b(,)33 b(a)e(b)m(yte)h(o\013set)g(to)g(the)f(p)s(osition)h(of)f(the)g (\014rst)f(pixel)i(in)f(the)g(data)h(\014le)f(ma)m(y)h(b)s(e)0 1120 y(sp)s(eci\014ed)h(b)m(y)g(separating)i(it)f(with)f(a)h(':')48 b(from)33 b(the)h(last)g(dimension)f(v)-5 b(alue.)51 b(If)33 b(omitted,)j(it)e(is)f(assumed)g(that)0 1233 y(the)i(o\013set)h(=)f(0.)54 b(This)35 b(parameter)g(ma)m(y)h(b)s(e)e (used)g(to)i(skip)e(o)m(v)m(er)i(an)m(y)g(header)e(information)i(in)e (the)h(\014le)g(that)0 1346 y(precedes)30 b(the)h(binary)f(data.)41 b(F)-8 b(urther)30 b(examples:)95 1603 y Fe(raw.dat[b10000])521 b(1-dimensional)45 b(10000)h(pixel)g(byte)h(array)95 1715 y(raw.dat[rb400,400,12])233 b(3-dimensional)45 b(floating)g(point) h(big-endian)f(array)95 1828 y(img.fits[ib512,512:2880])89 b(reads)47 b(the)g(512)g(x)g(512)g(short)f(integer)g(array)g(in)1336 1941 y(a)i(FITS)e(file,)h(skipping)e(over)i(the)g(2880)g(byte)f(header) 0 2198 y Fj(One)25 b(sp)s(ecial)g(case)h(of)f(input)f(\014le)h(is)g (where)g(the)g(\014lename)g(=)g(`-')h(\(a)f(dash)g(or)g(min)m(us)f (sign\))h(or)g('stdin')g(or)g('stdout',)0 2311 y(whic)m(h)d (signi\014es)h(that)h(the)f(input)e(\014le)i(is)g(to)h(b)s(e)e(read)g (from)h(the)g(stdin)f(stream,)j(or)e(written)f(to)i(the)f(stdout)g (stream)0 2424 y(if)34 b(a)g(new)g(output)f(\014le)h(is)g(b)s(eing)g (created.)52 b(In)33 b(the)h(case)h(of)f(reading)h(from)e(stdin,)h (CFITSIO)f(\014rst)g(copies)i(the)0 2537 y(whole)g(stream)h(in)m(to)g (a)f(temp)s(orary)g(FITS)f(\014le)i(\(in)f(memory)g(or)g(on)g(disk\),)h (and)f(subsequen)m(t)f(reading)h(of)h(the)0 2650 y(FITS)c(\014le)h(o)s (ccurs)g(in)f(this)h(cop)m(y)-8 b(.)49 b(When)33 b(writing)g(to)g (stdout,)h(CFITSIO)d(\014rst)h(constructs)h(the)g(whole)g(\014le)g(in)0 2763 y(memory)h(\(since)i(random)d(access)j(is)e(required\),)i(then)e (\015ushes)f(it)i(out)g(to)g(the)f(stdout)h(stream)g(when)e(the)i (\014le)0 2876 y(is)30 b(closed.)42 b(In)29 b(addition,)i(if)f(the)g (output)g(\014lename)g(=)g('-.gz')i(or)e('stdout.gz')h(then)f(it)h (will)f(b)s(e)g(gzip)g(compressed)0 2989 y(b)s(efore)g(b)s(eing)g (written)g(to)h(stdout.)0 3149 y(This)25 b(abilit)m(y)j(to)e(read)g (and)f(write)h(on)g(the)g(stdin)g(and)f(stdout)h(steams)g(allo)m(ws)i (FITS)d(\014les)h(to)g(b)s(e)g(pip)s(ed)e(b)s(et)m(w)m(een)0 3262 y(tasks)42 b(in)f(memory)g(rather)g(than)h(ha)m(ving)g(to)g (create)h(temp)s(orary)e(in)m(termediate)i(FITS)d(\014les)i(on)f(disk.) 73 b(F)-8 b(or)0 3375 y(example)28 b(if)e(task1)i(creates)h(an)e (output)f(FITS)g(\014le,)i(and)f(task2)g(reads)g(an)g(input)f(FITS)g (\014le,)i(the)f(FITS)f(\014le)h(ma)m(y)0 3487 y(b)s(e)j(pip)s(ed)f(b)s (et)m(w)m(een)i(the)f(2)h(tasks)g(b)m(y)f(sp)s(ecifying)143 3744 y Fe(task1)47 b(-)g(|)g(task2)g(-)0 4001 y Fj(where)30 b(the)h(v)m(ertical)i(bar)e(is)f(the)h(Unix)g(piping)f(sym)m(b)s(ol.)42 b(This)30 b(assumes)g(that)i(the)f(2)g(tasks)g(read)g(the)g(name)g(of)0 4114 y(the)g(FITS)e(\014le)i(o\013)f(of)h(the)g(command)f(line.)0 4448 y Ff(10.4)136 b(Output)44 b(File)i(Name)f(when)g(Op)t(ening)g(an)g (Existing)h(File)0 4698 y Fj(An)36 b(optional)i(output)e(\014lename)h (ma)m(y)h(b)s(e)e(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h (follo)m(wing)g(the)f(base)g(\014le)0 4811 y(name)28 b(to)h(b)s(e)f(op)s(ened.)39 b(This)28 b(is)g(mainly)g(useful)g(in)g (those)g(cases)i(where)d(CFITSIO)g(creates)j(a)e(temp)s(orary)g(cop)m (y)0 4924 y(of)i(the)f(input)g(FITS)f(\014le)i(b)s(efore)f(it)h(is)f (op)s(ened)g(and)f(passed)h(to)h(the)g(application)h(program.)40 b(This)28 b(happ)s(ens)g(b)m(y)0 5036 y(default)i(when)g(op)s(ening)g (a)g(net)m(w)m(ork)h(FTP)g(or)f(HTTP-t)m(yp)s(e)g(\014le,)h(when)e (reading)h(a)h(compressed)f(FITS)g(\014le)g(on)0 5149 y(a)36 b(lo)s(cal)h(disk,)g(when)e(reading)h(from)g(the)g(stdin)f (stream,)j(or)d(when)g(a)i(column)e(\014lter,)j(ro)m(w)e(\014lter,)h (or)f(binning)0 5262 y(sp)s(eci\014er)29 b(is)g(included)g(as)h(part)f (of)g(the)h(input)f(\014le)g(sp)s(eci\014cation.)41 b(By)30 b(default)g(this)f(temp)s(orary)g(\014le)g(is)h(created)0 5375 y(in)g(memory)-8 b(.)41 b(If)29 b(there)h(is)g(not)g(enough)g (memory)g(to)h(create)g(the)g(\014le)f(cop)m(y)-8 b(,)31 b(then)f(CFITSIO)e(will)i(exit)h(with)f(an)0 5488 y(error.)45 b(In)32 b(these)g(cases)h(one)g(can)f(force)h(a)f(p)s(ermanen)m(t)g (\014le)g(to)h(b)s(e)e(created)i(on)f(disk,)g(instead)h(of)f(a)g(temp)s (orary)0 5601 y(\014le)38 b(in)f(memory)-8 b(,)40 b(b)m(y)d(supplying)f (the)i(name)g(in)f(paren)m(theses)h(immediately)h(follo)m(wing)g(the)e (base)h(\014le)g(name.)0 5714 y(The)30 b(output)g(\014lename)g(can)h (include)f(the)h(')10 b(!')41 b(clobb)s(er)30 b(\015ag.)p eop end %%Page: 136 144 TeXDict begin 136 143 bop 0 299 a Fj(136)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(Th)m(us,)48 b(if)d(the)g(input)f(\014lename)h(to)g(CFITSIO)f (is:)70 b Fe(file1.fits.gz\(file2.fit)o(s\))39 b Fj(then)44 b(CFITSIO)g(will)0 668 y(uncompress)39 b(`\014le1.\014ts.gz')j(in)m(to) f(the)f(lo)s(cal)h(disk)e(\014le)h(`\014le2.\014ts')h(b)s(efore)f(op)s (ening)f(it.)70 b(CFITSIO)38 b(do)s(es)i(not)0 781 y(automatically)33 b(delete)f(the)e(output)g(\014le,)h(so)g(it)g(will)f(still)i(exist)f (after)g(the)f(application)i(program)e(exits.)0 941 y(The)i(output)h (\014lename)g("mem://")i(is)e(also)h(allo)m(w)m(ed,)i(whic)m(h)c(will)i (write)f(the)g(output)f(\014le)h(in)m(to)h(memory)-8 b(,)35 b(and)0 1054 y(also)28 b(allo)m(w)g(write)f(access)h(to)g(the)f (\014le.)39 b(This)26 b('\014le')i(will)f(disapp)s(ear)f(when)g(it)h (is)g(closed,)h(but)e(this)h(ma)m(y)h(b)s(e)e(useful)0 1167 y(for)k(some)h(applications)g(whic)m(h)g(only)f(need)g(to)h(mo)s (dify)f(a)h(temp)s(orary)f(cop)m(y)h(of)f(the)h(\014le.)0 1327 y(In)k(some)i(cases,)h(sev)m(eral)f(di\013eren)m(t)g(temp)s(orary) e(FITS)h(\014les)g(will)g(b)s(e)f(created)i(in)f(sequence,)i(for)e (instance,)i(if)0 1440 y(one)f(op)s(ens)g(a)g(remote)h(\014le)f(using)g (FTP)-8 b(,)37 b(then)g(\014lters)g(ro)m(ws)g(in)g(a)h(binary)e(table)i (extension,)i(then)c(create)j(an)0 1553 y(image)f(b)m(y)f(binning)f(a)h (pair)g(of)g(columns.)60 b(In)36 b(this)h(case,)j(the)d(remote)h (\014le)f(will)g(b)s(e)f(copied)h(to)h(a)f(temp)s(orary)0 1666 y(lo)s(cal)j(\014le,)h(then)d(a)h(second)f(temp)s(orary)h(\014le)f (will)h(b)s(e)f(created)i(con)m(taining)g(the)e(\014ltered)h(ro)m(ws)f (of)h(the)g(table,)0 1779 y(and)c(\014nally)g(a)h(third)e(temp)s(orary) h(\014le)h(con)m(taining)g(the)g(binned)e(image)i(will)g(b)s(e)f (created.)57 b(In)34 b(cases)i(lik)m(e)h(this)0 1892 y(where)28 b(m)m(ultiple)h(\014les)f(are)h(created,)h(the)e(out\014le)h (sp)s(eci\014er)f(will)g(b)s(e)g(in)m(terpreted)h(the)f(name)g(of)h (the)f(\014nal)g(\014le)h(as)0 2005 y(describ)s(ed)g(b)s(elo)m(w,)i(in) f(descending)g(priorit)m(y:)136 2266 y Fc(\017)46 b Fj(as)29 b(the)g(name)g(of)g(the)g(\014nal)f(image)i(\014le)f(if)f(an)h(image)h (within)e(a)h(single)g(binary)f(table)i(cell)g(is)e(op)s(ened)g(or)h (if)227 2379 y(an)i(image)g(is)g(created)g(b)m(y)f(binning)g(a)g(table) i(column.)136 2568 y Fc(\017)46 b Fj(as)33 b(the)f(name)h(of)f(the)h (\014le)f(con)m(taining)i(the)e(\014ltered)g(table)i(if)e(a)h(column)f (\014lter)g(and/or)g(a)h(ro)m(w)f(\014lter)h(are)227 2681 y(sp)s(eci\014ed.)136 2870 y Fc(\017)46 b Fj(as)31 b(the)f(name)h(of)f(the)h(lo)s(cal)h(cop)m(y)f(of)f(the)h(remote)g(FTP) f(or)h(HTTP)e(\014le.)136 3059 y Fc(\017)46 b Fj(as)31 b(the)g(name)g(of)g(the)f(uncompressed)g(v)m(ersion)h(of)g(the)f(FITS)g (\014le,)h(if)g(a)g(compressed)f(FITS)g(\014le)h(on)g(lo)s(cal)227 3172 y(disk)f(has)g(b)s(een)g(op)s(ened.)136 3361 y Fc(\017)46 b Fj(otherwise,)31 b(the)g(output)f(\014lename)g(is)h(ignored.)0 3622 y(The)e(output)f(\014le)h(sp)s(eci\014er)g(is)g(useful)f(when)g (reading)h(FTP)g(or)g(HTTP-t)m(yp)s(e)g(FITS)f(\014les)h(since)g(it)h (can)f(b)s(e)g(used)0 3735 y(to)34 b(create)i(a)e(lo)s(cal)h(disk)e (cop)m(y)i(of)f(the)g(\014le)f(that)i(can)f(b)s(e)f(reused)g(in)g(the)h (future.)50 b(If)33 b(the)h(output)g(\014le)f(name)h(=)0 3848 y(`*')i(then)e(a)i(lo)s(cal)g(\014le)f(with)g(the)g(same)g(name)g (as)g(the)h(net)m(w)m(ork)f(\014le)g(will)h(b)s(e)e(created.)56 b(Note)36 b(that)f(CFITSIO)0 3961 y(will)30 b(b)s(eha)m(v)m(e)g (di\013eren)m(tly)h(dep)s(ending)d(on)i(whether)f(the)h(remote)g (\014le)g(is)g(compressed)f(or)h(not)g(as)g(sho)m(wn)f(b)m(y)h(the)0 4074 y(follo)m(wing)i(examples:)136 4309 y Fc(\017)46 b Fe(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(.gz\()o(*\))28 b Fj(-)35 b(the)g(remote)h(compressed)e(\014le)h(is)g(copied)g(to)227 4422 y(the)d(lo)s(cal)h(compressed)f(\014le)g(`m)m(y\014le.\014ts.gz',) i(whic)m(h)d(is)h(then)g(uncompressed)e(in)i(lo)s(cal)h(memory)e(b)s (efore)227 4535 y(b)s(eing)f(op)s(ened)g(and)g(passed)f(to)j(the)e (application)i(program.)136 4724 y Fc(\017)46 b Fe (ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(.gz\()o(myfi)o(le.)o (fits)o(\))33 b Fj(-)39 b(the)g(remote)h(compressed)f(\014le)227 4837 y(is)d(copied)g(and)f(uncompressed)g(in)m(to)h(the)g(lo)s(cal)h (\014le)f(`m)m(y\014le.\014ts'.)57 b(This)35 b(example)h(requires)g (less)g(lo)s(cal)227 4950 y(memory)21 b(than)g(the)g(previous)f (example)i(since)f(the)g(\014le)g(is)g(uncompressed)e(on)i(disk)g (instead)g(of)g(in)f(memory)-8 b(.)136 5139 y Fc(\017)46 b Fe(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(\(myf)o(ile.)o (fit)o(s.gz)o(\))24 b Fj(-)30 b(this)g(will)g(usually)g(pro)s(duce)f (an)227 5252 y(error)h(since)h(CFITSIO)e(itself)i(cannot)g(compress)f (\014les.)0 5488 y(The)36 b(exact)i(b)s(eha)m(vior)e(of)h(CFITSIO)e(in) h(the)h(latter)g(case)h(dep)s(ends)c(on)j(the)f(t)m(yp)s(e)h(of)g(ftp)f (serv)m(er)g(running)f(on)0 5601 y(the)c(remote)g(mac)m(hine)g(and)f (ho)m(w)g(it)h(is)f(con\014gured.)40 b(In)30 b(some)h(cases,)g(if)f (the)h(\014le)f(`m)m(y\014le.\014ts.gz')j(exists)e(on)f(the)0 5714 y(remote)38 b(mac)m(hine,)h(then)e(the)g(serv)m(er)g(will)h(cop)m (y)f(it)h(to)f(the)h(lo)s(cal)g(mac)m(hine.)61 b(In)36 b(other)h(cases)h(the)f(ftp)g(serv)m(er)p eop end %%Page: 137 145 TeXDict begin 137 144 bop 0 299 a Fh(10.5.)73 b(TEMPLA)-8 b(TE)30 b(FILE)g(NAME)h(WHEN)g(CREA)-8 b(TING)30 b(A)g(NEW)h(FILE)997 b Fj(137)0 555 y(will)36 b(automatically)j(create)e(and)f(transmit)g(a) g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(if)g(only)g(the)g (uncompressed)0 668 y(v)m(ersion)27 b(exists.)41 b(This)26 b(can)h(get)h(rather)f(confusing,)h(so)f(users)f(should)g(use)h(a)g (certain)h(amoun)m(t)g(of)f(caution)h(when)0 781 y(using)34 b(the)h(output)f(\014le)h(sp)s(eci\014er)f(with)h(FTP)f(or)h(HTTP)f (\014le)h(t)m(yp)s(es,)h(to)f(mak)m(e)h(sure)e(they)h(get)h(the)f(b)s (eha)m(vior)0 894 y(that)c(they)g(exp)s(ect.)0 1250 y Ff(10.5)136 b(T)-11 b(emplate)45 b(File)h(Name)g(when)e(Creating)j(a)e (New)g(File)0 1504 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g (created)g(with)g(a)f(call)i(to)g(\014ts)p 2101 1504 28 4 v 32 w(create)p 2369 1504 V 35 w(\014le,)g(the)f(name)g(of)g(a)g (template)h(\014le)e(ma)m(y)0 1617 y(b)s(e)h(supplied)g(in)h(paren)m (theses)g(immediately)h(follo)m(wing)g(the)g(name)f(of)g(the)g(new)f (\014le)h(to)h(b)s(e)e(created.)71 b(This)0 1730 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h(structure)f(of)h(one)f(or)h(more)g (HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m (y)0 1843 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case) i(the)f(newly)g(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e (same)g(k)m(eyw)m(ords)g(in)0 1956 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g (template)i(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b) s(e)f(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2069 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,) g(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h (FITS)f(k)m(eyw)m(ord)i(record.)0 2182 y(The)j(format)h(of)f(the)h (ASCI)s(I)e(template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m (wing)i(T)-8 b(emplate)31 b(Files)h(c)m(hapter.)0 2538 y Ff(10.6)136 b(Image)46 b(Tile-Compression)g(Sp)t(eci\014cation)0 2792 y Fj(When)28 b(sp)s(ecifying)g(the)h(name)g(of)f(the)h(output)f (FITS)g(\014le)g(to)h(b)s(e)f(created,)i(the)f(user)f(can)g(indicate)i (that)f(images)0 2905 y(should)d(b)s(e)h(written)g(in)g (tile-compressed)h(format)g(\(see)g(section)g(5.5,)h(\\Primary)e(Arra)m (y)h(or)f(IMA)m(GE)h(Extension)0 3018 y(I/O)f(Routines"\))i(b)m(y)e (enclosing)h(the)g(compression)f(parameters)h(in)f(square)g(brac)m(k)m (ets)i(follo)m(wing)g(the)f(ro)s(ot)f(disk)0 3131 y(\014le)j(name.)41 b(Here)31 b(are)g(some)g(examples)g(of)f(the)h(syn)m(tax)g(for)f(sp)s (ecifying)g(tile-compressed)i(output)e(images:)191 3410 y Fe(myfile.fit[compress])185 b(-)48 b(use)f(Rice)f(algorithm)g(and)h (default)e(tile)i(size)191 3636 y(myfile.fit[compress)42 b(GZIP])47 b(-)g(use)g(the)g(specified)e(compression)g(algorithm;)191 3748 y(myfile.fit[compress)d(Rice])238 b(only)46 b(the)h(first)g (letter)f(of)h(the)g(algorithm)191 3861 y(myfile.fit[compress)42 b(PLIO])238 b(name)46 b(is)i(required.)191 4087 y(myfile.fit[compress) 42 b(Rice)47 b(100,100])141 b(-)48 b(use)e(100)h(x)h(100)f(pixel)f (tile)h(size)191 4200 y(myfile.fit[compress)42 b(Rice)47 b(100,100;2])e(-)j(as)f(above,)f(and)h(use)g(noisebits)e(=)i(2)0 4556 y Ff(10.7)136 b(HDU)45 b(Lo)t(cation)g(Sp)t(eci\014cation)0 4811 y Fj(The)c(optional)h(HDU)h(lo)s(cation)g(sp)s(eci\014er)d (de\014nes)h(whic)m(h)g(HDU)h(\(Header-Data)i(Unit,)h(also)d(kno)m(wn)f (as)h(an)0 4924 y(`extension'\))36 b(within)d(the)i(FITS)e(\014le)h(to) h(initially)h(op)s(en.)51 b(It)34 b(m)m(ust)g(immediately)i(follo)m(w)f (the)f(base)h(\014le)f(name)0 5036 y(\(or)g(the)g(output)g(\014le)g (name)f(if)h(presen)m(t\).)52 b(If)33 b(it)h(is)g(not)g(sp)s(eci\014ed) g(then)f(the)h(\014rst)f(HDU)i(\(the)f(primary)f(arra)m(y\))0 5149 y(is)g(op)s(ened.)46 b(The)32 b(HDU)h(lo)s(cation)h(sp)s (eci\014er)e(is)h(required)f(if)g(the)h(colFilter,)i(ro)m(wFilter,)g (or)e(binSp)s(ec)e(sp)s(eci\014ers)0 5262 y(are)f(presen)m(t,)f(b)s (ecause)h(the)f(primary)f(arra)m(y)i(is)f(not)h(a)f(v)-5 b(alid)30 b(HDU)g(for)f(these)g(op)s(erations.)41 b(The)29 b(HDU)h(ma)m(y)g(b)s(e)0 5375 y(sp)s(eci\014ed)e(either)i(b)m(y)e (absolute)i(p)s(osition)f(n)m(um)m(b)s(er,)f(starting)i(with)e(0)i(for) e(the)h(primary)f(arra)m(y)-8 b(,)31 b(or)e(b)m(y)f(reference)0 5488 y(to)h(the)g(HDU)g(name,)g(and)f(optionally)-8 b(,)31 b(the)e(v)m(ersion)g(n)m(um)m(b)s(er)e(and)h(the)h(HDU)g(t)m(yp)s(e)g (of)f(the)h(desired)f(extension.)0 5601 y(The)k(lo)s(cation)h(of)f(an)g (image)i(within)d(a)i(single)f(cell)i(of)e(a)g(binary)g(table)h(ma)m(y) f(also)h(b)s(e)f(sp)s(eci\014ed,)g(as)g(describ)s(ed)0 5714 y(b)s(elo)m(w.)p eop end %%Page: 138 146 TeXDict begin 138 145 bop 0 299 a Fj(138)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)26 b(absolute)h(p)s(osition)f(of)g(the)h(extension)g(is)f (sp)s(eci\014ed)f(either)i(b)m(y)f(enclosed)h(the)g(n)m(um)m(b)s(er)e (in)h(square)f(brac)m(k)m(ets)0 668 y(\(e.g.,)k(`[1]')g(=)d(the)h (\014rst)f(extension)h(follo)m(wing)i(the)e(primary)e(arra)m(y\))j(or)f (b)m(y)f(preceded)h(the)g(n)m(um)m(b)s(er)e(with)i(a)g(plus)0 781 y(sign)37 b(\(`+1'\).)63 b(T)-8 b(o)38 b(sp)s(ecify)f(the)g(HDU)h (b)m(y)g(name,)h(giv)m(e)g(the)e(name)h(of)f(the)h(desired)f(HDU)h (\(the)f(v)-5 b(alue)38 b(of)g(the)0 894 y(EXTNAME)e(or)g(HDUNAME)h(k)m (eyw)m(ord\))g(and)f(optionally)h(the)f(extension)h(v)m(ersion)f(n)m (um)m(b)s(er)f(\(v)-5 b(alue)37 b(of)f(the)0 1007 y(EXTVER)27 b(k)m(eyw)m(ord\))i(and)e(the)h(extension)h(t)m(yp)s(e)e(\(v)-5 b(alue)29 b(of)f(the)g(XTENSION)f(k)m(eyw)m(ord:)40 b(IMA)m(GE,)29 b(ASCI)s(I)d(or)0 1120 y(T)-8 b(ABLE,)36 b(or)f(BINT)-8 b(ABLE\),)36 b(separated)f(b)m(y)g(commas)h(and)e(all)i(enclosed)g(in)f (square)g(brac)m(k)m(ets.)56 b(If)34 b(the)h(v)-5 b(alue)0 1233 y(of)34 b(EXTVER)f(and)f(XTENSION)h(are)h(not)f(sp)s(eci\014ed,)h (then)f(the)h(\014rst)e(extension)j(with)e(the)g(correct)i(v)-5 b(alue)34 b(of)0 1346 y(EXTNAME)39 b(is)g(op)s(ened.)67 b(The)38 b(extension)i(name)f(and)f(t)m(yp)s(e)i(are)f(not)h(case)g (sensitiv)m(e,)j(and)38 b(the)h(extension)0 1458 y(t)m(yp)s(e)29 b(ma)m(y)g(b)s(e)f(abbreviated)h(to)g(a)g(single)g(letter)h(\(e.g.,)h (I)d(=)g(IMA)m(GE)i(extension)f(or)f(primary)g(arra)m(y)-8 b(,)30 b(A)f(or)f(T)g(=)0 1571 y(ASCI)s(I)d(table)i(extension,)h(and)e (B)h(=)f(binary)g(table)h(BINT)-8 b(ABLE)27 b(extension\).)41 b(If)26 b(the)g(HDU)h(lo)s(cation)i(sp)s(eci\014er)0 1684 y(is)h(equal)h(to)g(`[PRIMAR)-8 b(Y]')32 b(or)f(`[P]',)g(then)f (the)h(primary)e(arra)m(y)i(\(the)g(\014rst)f(HDU\))h(will)g(b)s(e)f (op)s(ened.)0 1844 y(An)36 b(optional)j(p)s(ound)34 b(sign)j(c)m (haracter)i(\("#"\))f(ma)m(y)f(b)s(e)g(app)s(ended)e(to)i(the)g (extension)h(name)f(or)g(n)m(um)m(b)s(er)e(to)0 1957 y(signify)e(that)h(an)m(y)g(other)f(extensions)h(in)f(the)g(\014le)g (should)g(b)s(e)f(ignored)h(during)f(an)m(y)i(subsequen)m(t)e(\014le)i (\014ltering)0 2070 y(op)s(erations.)83 b(F)-8 b(or)45 b(example,)k(when)43 b(doing)i(ro)m(w)f(\014ltering)h(op)s(erations)f (on)h(a)f(table)i(extension,)i(CFITSIO)0 2183 y(normally)27 b(creates)i(a)e(cop)m(y)h(of)f(the)g(\014ltered)g(table)h(in)f(memory) -8 b(,)28 b(along)h(with)d(a)i(v)m(erbatim)f(cop)m(y)h(of)f(all)h(the)g (other)0 2296 y(extensions)h(in)g(the)g(input)f(FITS)g(\014le.)41 b(If)28 b(the)h(p)s(ound)e(sign)i(is)g(app)s(ended)e(to)j(the)f(table)h (extension)g(name,)f(then)0 2409 y(only)34 b(that)g(extension,)i(and)d (none)h(of)g(the)g(other)g(extensions)g(in)f(the)h(\014le,)h(will)g(b)m (y)e(copied)h(to)h(memory)-8 b(,)35 b(as)f(in)0 2522 y(the)d(follo)m(wing)g(example:)143 2780 y Fe(myfile.fit[events#][TIME) 41 b(>)48 b(10000])0 3038 y Fj(FITS)34 b(images)i(are)f(most)h (commonly)f(stored)g(in)g(the)g(primary)f(arra)m(y)h(or)g(an)g(image)h (extension,)h(but)d(images)0 3151 y(can)d(also)h(b)s(e)e(stored)h(as)h (a)f(v)m(ector)h(in)f(a)g(single)h(cell)g(of)f(a)h(binary)e(table)i (\(i.e.)43 b(eac)m(h)32 b(ro)m(w)f(of)g(the)h(v)m(ector)g(column)0 3263 y(con)m(tains)d(a)g(di\013eren)m(t)f(image\).)42 b(Suc)m(h)27 b(an)h(image)i(can)e(b)s(e)g(op)s(ened)f(with)h(CFITSIO)e (b)m(y)i(sp)s(ecifying)g(the)g(desired)0 3376 y(column)k(name)g(and)f (the)h(ro)m(w)g(n)m(um)m(b)s(er)f(after)h(the)g(binary)f(table)i(HDU)g (sp)s(eci\014er)e(as)h(sho)m(wn)g(in)f(the)h(follo)m(wing)0 3489 y(examples.)71 b(The)40 b(column)g(name)h(is)f(separated)h(from)f (the)h(HDU)g(sp)s(eci\014er)f(b)m(y)g(a)h(semicolon)g(and)f(the)h(ro)m (w)0 3602 y(n)m(um)m(b)s(er)29 b(is)h(enclosed)h(in)e(paren)m(theses.) 41 b(In)30 b(this)g(case)h(CFITSIO)d(copies)j(the)f(image)i(from)d(the) i(table)g(cell)g(in)m(to)0 3715 y(a)h(temp)s(orary)e(primary)h(arra)m (y)g(b)s(efore)g(it)h(is)f(op)s(ened.)43 b(The)30 b(application)j (program)e(then)g(just)g(sees)g(the)h(image)0 3828 y(in)i(the)h (primary)e(arra)m(y)-8 b(,)37 b(without)d(an)m(y)h(extensions.)53 b(The)34 b(particular)g(ro)m(w)h(to)g(b)s(e)e(op)s(ened)h(ma)m(y)h(b)s (e)f(sp)s(eci\014ed)0 3941 y(either)28 b(b)m(y)f(giving)h(an)f (absolute)h(in)m(teger)h(ro)m(w)f(n)m(um)m(b)s(er)e(\(starting)i(with)f (1)h(for)f(the)g(\014rst)g(ro)m(w\),)i(or)e(b)m(y)g(sp)s(ecifying)0 4054 y(a)33 b(b)s(o)s(olean)f(expression)g(that)h(ev)-5 b(aluates)34 b(to)f(TR)m(UE)g(for)f(the)g(desired)g(ro)m(w.)47 b(The)32 b(\014rst)f(ro)m(w)i(that)g(satis\014es)g(the)0 4167 y(expression)28 b(will)g(b)s(e)g(used.)39 b(The)28 b(ro)m(w)g(selection)i(expression)e(has)g(the)g(same)g(syn)m(tax)h(as)f (describ)s(ed)f(in)h(the)g(Ro)m(w)0 4280 y(Filter)k(Sp)s(eci\014er)d (section,)j(b)s(elo)m(w.)0 4440 y(Examples:)143 4698 y Fe(myfile.fits[3])44 b(-)k(open)e(the)h(3rd)g(HDU)g(following)e(the)i (primary)f(array)143 4811 y(myfile.fits+3)92 b(-)48 b(same)e(as)h (above,)f(but)h(using)g(the)g(FTOOLS-style)d(notation)143 4924 y(myfile.fits[EVENTS])f(-)k(open)g(the)g(extension)e(that)i(has)g (EXTNAME)e(=)j('EVENTS')143 5036 y(myfile.fits[EVENTS,)43 b(2])95 b(-)47 b(same)g(as)g(above,)f(but)h(also)g(requires)e(EXTVER)h (=)i(2)143 5149 y(myfile.fits[events,2,b])42 b(-)47 b(same,)f(but)h (also)g(requires)f(XTENSION)f(=)j('BINTABLE')143 5262 y(myfile.fits[3;)c(images\(17\)])h(-)i(opens)g(the)g(image)f(in)h(row)g (17)g(of)g(the)g('images')1527 5375 y(column)f(in)i(the)e(3rd)h (extension)f(of)h(the)g(file.)143 5488 y(myfile.fits[3;)d (images\(exposure)g(>)j(100\)])g(-)g(as)g(above,)f(but)h(opens)g(the)f (image)907 5601 y(in)h(the)g(first)f(row)h(that)g(has)g(an)g ('exposure')e(column)h(value)907 5714 y(greater)g(than)g(100.)p eop end %%Page: 139 147 TeXDict begin 139 146 bop 0 299 a Fh(10.8.)73 b(IMA)m(GE)31 b(SECTION)2744 b Fj(139)0 555 y Ff(10.8)136 b(Image)46 b(Section)0 811 y Fj(A)41 b(virtual)g(\014le)f(con)m(taining)i(a)f (rectangular)h(subsection)e(of)h(an)g(image)g(can)g(b)s(e)f(extracted)i (and)e(op)s(ened)g(b)m(y)0 924 y(sp)s(ecifying)32 b(the)h(range)g(of)g (pixels)g(\(start:end\))g(along)h(eac)m(h)g(axis)f(to)g(b)s(e)f (extracted)i(from)e(the)h(original)g(image.)0 1037 y(One)d(can)h(also)h (sp)s(ecify)e(an)h(optional)h(pixel)f(incremen)m(t)g (\(start:end:step\))h(for)f(eac)m(h)h(axis)f(of)g(the)g(input)e(image.) 0 1149 y(A)f(pixel)f(step)h(=)f(1)h(will)g(b)s(e)f(assumed)f(if)i(it)g (is)f(not)h(sp)s(eci\014ed.)39 b(If)27 b(the)h(start)g(pixel)g(is)f (larger)i(then)e(the)h(end)e(pixel,)0 1262 y(then)32 b(the)g(image)h(will)f(b)s(e)f(\015ipp)s(ed)f(\(pro)s(ducing)h(a)h (mirror)g(image\))h(along)g(that)f(dimension.)45 b(An)32 b(asterisk,)h('*',)0 1375 y(ma)m(y)39 b(b)s(e)e(used)h(to)h(sp)s(ecify) f(the)g(en)m(tire)h(range)g(of)f(an)h(axis,)i(and)c('-*')j(will)e (\015ip)g(the)g(en)m(tire)h(axis.)65 b(The)38 b(input)0 1488 y(image)31 b(can)f(b)s(e)f(in)g(the)h(primary)f(arra)m(y)-8 b(,)31 b(in)e(an)g(image)i(extension,)g(or)f(con)m(tained)g(in)g(a)g(v) m(ector)h(cell)g(of)f(a)g(binary)0 1601 y(table.)40 b(In)25 b(the)h(later)h(2)f(cases)h(the)f(extension)h(name)f(or)f(n)m(um)m(b)s (er)g(m)m(ust)h(b)s(e)f(sp)s(eci\014ed)g(b)s(efore)h(the)g(image)h (section)0 1714 y(sp)s(eci\014er.)0 1874 y(Examples:)95 2157 y Fe(myfile.fits[1:512:2,)43 b(2:512:2])i(-)95 b(open)47 b(a)h(256x256)d(pixel)i(image)668 2270 y(consisting)e(of)i(the)g(odd)g (numbered)f(columns)g(\(1st)g(axis\))h(and)668 2383 y(the)g(even)g (numbered)e(rows)i(\(2nd)g(axis\))f(of)h(the)g(image)f(in)i(the)668 2496 y(primary)e(array)g(of)i(the)e(file.)95 2721 y(myfile.fits[*,)e (512:256])i(-)h(open)g(an)g(image)g(consisting)e(of)i(all)g(the)g (columns)668 2834 y(in)g(the)g(input)g(image,)f(but)h(only)f(rows)h (256)g(through)f(512.)668 2947 y(The)h(image)f(will)h(be)g(flipped)f (along)g(the)h(2nd)g(axis)g(since)668 3060 y(the)g(starting)f(pixel)g (is)h(greater)f(than)h(the)g(ending)f(pixel.)95 3286 y(myfile.fits[*:2,)e(512:256:2])h(-)i(same)g(as)g(above)f(but)h (keeping)f(only)668 3399 y(every)h(other)f(row)h(and)g(column)f(in)h (the)g(input)f(image.)95 3625 y(myfile.fits[-*,)e(*])j(-)h(copy)e(the)h (entire)f(image,)g(flipping)g(it)h(along)668 3738 y(the)g(first)f (axis.)95 3963 y(myfile.fits[3][1:256,1:256)o(])c(-)47 b(opens)g(a)g(subsection)e(of)i(the)g(image)g(that)668 4076 y(is)g(in)h(the)e(3rd)h(extension)f(of)h(the)g(file.)95 4302 y(myfile.fits[4;)d(images\(12\)][1:10,1:10])e(-)48 b(open)e(an)h(image)g(consisting)286 4415 y(of)h(the)e(first)h(10)g (pixels)f(in)h(both)g(dimensions.)e(The)i(original)286 4528 y(image)g(resides)f(in)h(the)g(12th)f(row)h(of)g(the)g('images')f (vector)286 4641 y(column)g(in)i(the)f(table)f(in)h(the)g(4th)g (extension)e(of)i(the)g(file.)0 4924 y Fj(When)23 b(CFITSIO)f(op)s(ens) h(an)g(image)h(section)h(it)f(\014rst)f(creates)h(a)g(temp)s(orary)f (\014le)h(con)m(taining)h(the)e(image)i(section)0 5036 y(plus)30 b(a)h(cop)m(y)h(of)f(an)m(y)g(other)g(HDUs)g(in)g(the)g (\014le.)42 b(\(If)31 b(a)g(`#')g(c)m(haracter)h(is)f(app)s(ended)e(to) j(the)f(name)f(or)h(n)m(um)m(b)s(er)0 5149 y(of)i(the)g(image)i(HDU,)e (as)h(in)e("m)m(y\014le.\014ts[1#][1:200,1:200)q(]",)40 b(then)33 b(the)g(other)g(HDUs)h(in)e(the)h(input)g(\014le)g(will)0 5262 y(not)j(b)s(e)f(copied)i(in)m(to)f(memory\).)58 b(This)35 b(temp)s(orary)g(\014le)h(is)g(then)f(op)s(ened)h(b)m(y)f (the)h(application)h(program,)h(so)0 5375 y(it)32 b(is)g(not)f(p)s (ossible)h(to)g(write)g(to)g(or)f(mo)s(dify)g(the)h(input)e(\014le)i (when)f(sp)s(ecifying)g(an)g(image)i(section.)45 b(Note)33 b(that)0 5488 y(CFITSIO)27 b(automatically)32 b(up)s(dates)c(the)h(w)m (orld)f(co)s(ordinate)i(system)f(k)m(eyw)m(ords)g(in)f(the)h(header)g (of)g(the)g(image)0 5601 y(section,)h(if)f(they)g(exist,)h(so)f(that)g (the)g(co)s(ordinate)h(asso)s(ciated)g(with)e(eac)m(h)i(pixel)f(in)g (the)g(image)h(section)g(will)f(b)s(e)0 5714 y(computed)h(correctly)-8 b(.)p eop end %%Page: 140 148 TeXDict begin 140 147 bop 0 299 a Fj(140)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Ff(10.9)136 b(Image)46 b(T)-11 b(ransform)44 b(Filters)0 807 y Fj(CFITSIO)33 b(can)h(apply)g(a)h(user-sp)s(eci\014ed)e (mathematical)j(function)e(to)h(the)g(v)-5 b(alue)34 b(of)h(ev)m(ery)g(pixel)f(in)g(a)h(FITS)0 920 y(image,)29 b(th)m(us)e(creating)h(a)g(new)e(virtual)h(image)i(in)d(computer)h (memory)g(that)h(is)f(then)f(op)s(ened)h(and)f(read)h(b)m(y)g(the)0 1033 y(application)32 b(program.)40 b(The)30 b(original)i(FITS)d(image) j(is)e(not)h(mo)s(di\014ed)e(b)m(y)h(this)h(pro)s(cess.)0 1193 y(The)20 b(image)j(transformation)e(sp)s(eci\014er)f(is)h(app)s (ended)e(to)j(the)f(input)f(FITS)h(\014le)g(name)g(and)f(is)h(enclosed) h(in)e(square)0 1306 y(brac)m(k)m(ets.)42 b(It)29 b(b)s(egins)f(with)h (the)g(letters)i('PIX')e(to)h(distinguish)e(it)i(from)e(other)i(t)m(yp) s(es)f(of)g(FITS)f(\014le)h(\014lters)g(that)0 1419 y(are)36 b(recognized)i(b)m(y)e(CFITSIO.)e(The)i(image)h(transforming)f (function)f(ma)m(y)i(use)f(an)m(y)g(of)g(the)h(mathematical)0 1532 y(op)s(erators)44 b(listed)h(in)f(the)h(follo)m(wing)h('Ro)m(w)f (Filtering)g(Sp)s(eci\014cation')g(section)h(of)e(this)h(do)s(cumen)m (t.)82 b(Some)0 1645 y(examples)31 b(of)f(image)i(transform)e (\014lters)g(are:)48 1913 y Fe([pix)46 b(X)i(*)f(2.0])715 b(-)48 b(multiply)d(each)i(pixel)f(by)h(2.0)48 2026 y([pix)f (sqrt\(X\)])714 b(-)48 b(take)e(the)h(square)f(root)h(of)g(each)g (pixel)48 2139 y([pix)f(X)i(+)f(#ZEROPT)571 b(-)48 b(add)e(the)h(value) g(of)g(the)g(ZEROPT)f(keyword)48 2252 y([pix)g(X>0)h(?)h(log10\(X\))d (:)j(-99.])e(-)i(if)f(the)g(pixel)f(value)g(is)i(greater)1480 2365 y(than)e(0,)h(compute)f(the)h(base)g(10)g(log,)1480 2478 y(else)f(set)h(the)g(pixel)f(=)i(-99.)0 2746 y Fj(Use)24 b(the)g(letter)h('X')f(in)f(the)h(expression)g(to)g(represen)m(t)g(the) g(curren)m(t)f(pixel)h(v)-5 b(alue)24 b(in)f(the)h(image.)40 b(The)23 b(expression)0 2859 y(is)38 b(ev)-5 b(aluated)39 b(indep)s(enden)m(tly)e(for)g(eac)m(h)i(pixel)f(in)g(the)g(image)h(and) e(ma)m(y)h(b)s(e)g(a)g(function)f(of)h(1\))h(the)f(original)0 2971 y(pixel)32 b(v)-5 b(alue,)32 b(2\))g(the)f(v)-5 b(alue)32 b(of)f(other)h(pixels)f(in)g(the)g(image)i(at)f(a)f(giv)m(en) i(relativ)m(e)g(o\013set)f(from)f(the)g(p)s(osition)h(of)0 3084 y(the)d(pixel)f(that)h(is)g(b)s(eing)f(ev)-5 b(aluated,)30 b(and)e(3\))h(the)g(v)-5 b(alue)29 b(of)f(an)m(y)h(header)f(k)m(eyw)m (ords.)41 b(Header)29 b(k)m(eyw)m(ord)g(v)-5 b(alues)0 3197 y(are)31 b(represen)m(ted)f(b)m(y)g(the)h(name)f(of)h(the)f(k)m (eyw)m(ord)h(preceded)f(b)m(y)h(the)f('#')h(sign.)0 3357 y(T)-8 b(o)35 b(access)h(the)f(the)g(v)-5 b(alue)35 b(of)g(adjacen)m(t) h(pixels)f(in)f(the)h(image,)i(sp)s(ecify)e(the)g(\(1-D\))h(o\013set)g (from)e(the)h(curren)m(t)0 3470 y(pixel)c(in)f(curly)g(brac)m(k)m(ets.) 42 b(F)-8 b(or)31 b(example)48 3738 y Fe([pix)94 b(\(x{-1})46 b(+)i(x)f(+)h(x{+1}\))e(/)h(3])0 4006 y Fj(will)25 b(replace)g(eac)m(h) h(pixel)f(v)-5 b(alue)25 b(with)f(the)h(running)e(mean)i(of)f(the)h(v) -5 b(alues)25 b(of)g(that)g(pixel)g(and)f(it's)h(2)g(neigh)m(b)s(oring) 0 4119 y(pixels.)40 b(Note)30 b(that)g(in)e(this)g(notation)i(the)f (image)h(is)f(treated)g(as)g(a)g(1-D)h(arra)m(y)-8 b(,)30 b(where)e(eac)m(h)i(ro)m(w)f(of)g(the)g(image)0 4232 y(\(or)c(higher)f(dimensional)g(cub)s(e\))h(is)f(app)s(ended)f(one)h (after)h(another)g(in)f(one)h(long)g(arra)m(y)g(of)f(pixels.)39 b(It)25 b(is)f(p)s(ossible)0 4345 y(to)35 b(refer)f(to)h(pixels)f(in)g (the)g(ro)m(ws)g(ab)s(o)m(v)m(e)h(or)g(b)s(elo)m(w)f(the)g(curren)m(t)g (pixel)h(b)m(y)f(using)f(the)h(v)-5 b(alue)35 b(of)f(the)h(NAXIS1)0 4458 y(header)30 b(k)m(eyw)m(ord.)41 b(F)-8 b(or)32 b(example)48 4726 y Fe([pix)46 b(\(x{-#NAXIS1})f(+)i(x)h(+)f(x{#NAXIS1}\))e(/)i(3])0 4994 y Fj(will)34 b(compute)f(the)h(mean)f(of)g(eac)m(h)i(image)f (pixel)g(and)e(the)i(pixels)f(immediately)i(ab)s(o)m(v)m(e)f(and)f(b)s (elo)m(w)g(it)h(in)f(the)0 5107 y(adjacen)m(t)27 b(ro)m(ws)f(of)g(the)f (image.)41 b(The)25 b(follo)m(wing)i(more)f(complex)h(example)f (creates)h(a)f(smo)s(othed)g(virtual)g(image)0 5220 y(where)k(eac)m(h)h (pixel)g(is)g(a)f(3)h(x)f(3)h(b)s(o)m(xcar)g(a)m(v)m(erage)i(of)d(the)h (input)e(image)j(pixels:)95 5488 y Fe([pix)47 b(\(X)g(+)h(X{-1})e(+)i (X{+1})286 5601 y(+)g(X{-#NAXIS1})d(+)i(X{-#NAXIS1)e(-)i(1})h(+)f (X{-#NAXIS1)e(+)j(1})286 5714 y(+)g(X{#NAXIS1})d(+)i(X{#NAXIS1)f(-)h (1})g(+)h(X{#NAXIS1)d(+)i(1}\))g(/)h(9.])p eop end %%Page: 141 149 TeXDict begin 141 148 bop 0 299 a Fh(10.10.)73 b(COLUMN)30 b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)984 b Fj(141)0 555 y(If)31 b(the)h(pixel)g(o\013set)h(extends)f (b)s(ey)m(ond)f(the)h(\014rst)f(or)h(last)h(pixel)f(in)f(the)h(image,)i (the)e(function)g(will)g(ev)-5 b(aluate)33 b(to)0 668 y(unde\014ned,)28 b(or)j(NULL.)0 828 y(F)-8 b(or)39 b(complex)g(or)g (commonly)g(used)e(image)j(\014ltering)f(op)s(erations,)i(one)d(can)h (write)g(the)f(expression)h(in)m(to)g(an)0 941 y(external)i(text)h (\014le)f(and)f(then)g(imp)s(ort)g(it)h(in)m(to)h(the)e(\014lter)h (using)f(the)h(syn)m(tax)g('[pix)g(@\014lename.txt]'.)72 b(The)0 1054 y(mathematical)29 b(expression)e(can)g(extend)g(o)m(v)m (er)i(m)m(ultiple)e(lines)g(of)h(text)g(in)e(the)h(\014le.)40 b(An)m(y)27 b(lines)g(in)g(the)g(external)0 1167 y(text)h(\014le)e (that)i(b)s(egin)e(with)g(2)h(slash)f(c)m(haracters)i(\('//'\))h(will)e (b)s(e)f(ignored)h(and)f(ma)m(y)h(b)s(e)f(used)g(to)h(add)f(commen)m (ts)0 1280 y(in)m(to)31 b(the)g(\014le.)0 1440 y(By)c(default,)g(the)f (datat)m(yp)s(e)i(of)e(the)g(resulting)h(image)g(will)g(b)s(e)e(the)i (same)f(as)h(the)f(original)i(image,)g(but)e(one)g(ma)m(y)0 1553 y(force)31 b(a)g(di\013eren)m(t)g(datat)m(yp)s(e)g(b)m(y)f(app)s (ended)f(a)h(co)s(de)h(letter)h(to)f(the)f('pix')h(k)m(eyw)m(ord:)286 1786 y Fe(pixb)95 b(-)g(8-bit)46 b(byte)190 b(image)46 b(with)h(BITPIX)f(=)143 b(8)286 1898 y(pixi)95 b(-)47 b(16-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(16)286 2011 y(pixj)g(-)47 b(32-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(32)286 2124 y(pixr)g(-)47 b(32-bit)f(float)142 b(image)46 b(with)h(BITPIX)f(=)i(-32)286 2237 y(pixd)95 b(-)47 b(64-bit)f(float) 142 b(image)46 b(with)h(BITPIX)f(=)i(-64)0 2470 y Fj(Also)23 b(b)m(y)f(default,)j(an)m(y)d(other)h(HDUs)g(in)f(the)g(input)g(\014le) g(will)h(b)s(e)e(copied)i(without)g(c)m(hange)g(to)g(the)g(output)f (virtual)0 2583 y(FITS)k(\014le,)h(but)f(one)g(ma)m(y)h(discard)f(the)h (other)f(HDUs)h(b)m(y)f(adding)g(the)h(n)m(um)m(b)s(er)e('1')i(to)g (the)g('pix')f(k)m(eyw)m(ord)h(\(and)0 2696 y(follo)m(wing)32 b(an)m(y)f(optional)g(datat)m(yp)s(e)g(co)s(de)g(letter\).)42 b(F)-8 b(or)32 b(example:)239 2928 y Fe(myfile.fits[3][pixr1)90 b(sqrt\(X\)])0 3161 y Fj(will)23 b(create)i(a)e(virtual)g(FITS)f (\014le)h(con)m(taining)h(only)f(a)g(primary)f(arra)m(y)i(image)g(with) e(32-bit)i(\015oating)g(p)s(oin)m(t)f(pixels)0 3274 y(that)29 b(ha)m(v)m(e)h(a)f(v)-5 b(alue)30 b(equal)f(to)g(the)g(square)g(ro)s (ot)g(of)g(the)g(pixels)f(in)h(the)g(image)h(that)f(is)g(in)f(the)h (3rd)f(extension)i(of)0 3387 y(the)h('m)m(y\014le.\014ts')g(\014le.)0 3716 y Ff(10.10)136 b(Column)45 b(and)g(Keyw)l(ord)g(Filtering)h(Sp)t (eci\014cation)0 3966 y Fj(The)27 b(optional)i(column/k)m(eyw)m(ord)g (\014ltering)f(sp)s(eci\014er)f(is)h(used)f(to)i(mo)s(dify)e(the)h (column)g(structure)f(and/or)h(the)0 4079 y(header)38 b(k)m(eyw)m(ords)h(in)f(the)h(HDU)g(that)h(w)m(as)f(selected)h(with)e (the)h(previous)f(HDU)h(lo)s(cation)h(sp)s(eci\014er.)65 b(This)0 4192 y(\014ltering)42 b(sp)s(eci\014er)f(m)m(ust)h(b)s(e)f (enclosed)i(in)e(square)h(brac)m(k)m(ets)h(and)e(can)h(b)s(e)f (distinguished)g(from)h(a)g(general)0 4305 y(ro)m(w)d(\014lter)g(sp)s (eci\014er)f(\(describ)s(ed)g(b)s(elo)m(w\))h(b)m(y)g(the)g(fact)h (that)f(it)g(b)s(egins)f(with)h(the)g(string)g('col)h(')f(and)f(is)h (not)0 4418 y(immediately)30 b(follo)m(w)m(ed)g(b)m(y)e(an)g(equals)h (sign.)40 b(The)28 b(original)h(\014le)f(is)h(not)f(c)m(hanged)h(b)m(y) f(this)h(\014ltering)f(op)s(eration,)0 4531 y(and)c(instead)h(the)g(mo) s(di\014cations)g(are)g(made)g(on)f(a)h(cop)m(y)h(of)e(the)h(input)f (FITS)g(\014le)h(\(usually)g(in)f(memory\),)i(whic)m(h)0 4644 y(also)31 b(con)m(tains)g(a)g(cop)m(y)g(of)f(all)h(the)f(other)g (HDUs)h(in)f(the)g(\014le.)41 b(\(If)30 b(a)g(`#')h(c)m(haracter)g(is)f (app)s(ended)f(to)i(the)f(name)0 4757 y(or)d(n)m(um)m(b)s(er)e(of)i (the)g(table)g(HDU)h(then)e(only)h(the)g(primary)f(arra)m(y)-8 b(,)28 b(and)e(none)h(of)g(the)f(other)h(HDUs)h(in)e(the)h(input)0 4869 y(\014le)i(will)f(b)s(e)g(copied)h(in)m(to)g(memory\).)41 b(This)27 b(temp)s(orary)h(\014le)h(is)f(passed)g(to)h(the)g (application)h(program)e(and)g(will)0 4982 y(p)s(ersist)e(only)i(un)m (til)f(the)g(\014le)g(is)h(closed)f(or)g(un)m(til)h(the)f(program)g (exits,)i(unless)d(the)h(out\014le)h(sp)s(eci\014er)e(\(see)i(ab)s(o)m (v)m(e\))0 5095 y(is)i(also)i(supplied.)0 5255 y(The)f(column/k)m(eyw)m (ord)h(\014lter)f(can)g(b)s(e)g(used)f(to)i(p)s(erform)e(the)i(follo)m (wing)g(op)s(erations.)44 b(More)32 b(than)f(one)g(op)s(er-)0 5368 y(ation)g(ma)m(y)g(b)s(e)f(sp)s(eci\014ed)g(b)m(y)g(separating)h (them)f(with)h(commas)f(or)h(semi-colons.)136 5601 y Fc(\017)46 b Fj(Cop)m(y)36 b(only)g(a)g(sp)s(eci\014ed)g(list)g(of)g (columns)g(columns)f(to)i(the)f(\014ltered)g(input)f(\014le.)57 b(The)36 b(list)g(of)g(column)227 5714 y(name)41 b(should)e(b)s(e)g (separated)i(b)m(y)f(commas)h(or)f(semi-colons.)72 b(Wild)41 b(card)f(c)m(haracters)h(ma)m(y)g(b)s(e)f(used)p eop end %%Page: 142 150 TeXDict begin 142 149 bop 0 299 a Fj(142)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)227 555 y Fj(in)38 b(the)f(column)h(names)g(to)g(matc)m(h)g(m)m(ultiple)h (columns.)62 b(If)37 b(the)h(expression)g(con)m(tains)g(b)s(oth)f(a)h (list)h(of)227 668 y(columns)29 b(to)h(b)s(e)f(included)g(and)g (columns)g(to)h(b)s(e)e(deleted,)j(then)e(all)h(the)g(columns)f(in)g (the)h(original)g(table)227 781 y(except)36 b(the)e(explicitly)i (deleted)f(columns)f(will)h(app)s(ear)e(in)h(the)h(\014ltered)f(table)h (\(i.e.,)i(there)e(is)f(no)g(need)227 894 y(to)d(explicitly)h(list)f (the)g(columns)f(to)h(b)s(e)f(included)f(if)i(an)m(y)f(columns)h(are)f (b)s(eing)g(deleted\).)136 1068 y Fc(\017)46 b Fj(Delete)32 b(a)d(column)g(or)g(k)m(eyw)m(ord)h(b)m(y)f(listing)h(the)f(name)g (preceded)g(b)m(y)g(a)g(min)m(us)g(sign)g(or)g(an)g(exclamation)227 1181 y(mark)c(\(!\),)h(e.g.,)i('-TIME')d(will)g(delete)h(the)e(TIME)h (column)f(if)g(it)i(exists,)g(otherwise)f(the)g(TIME)f(k)m(eyw)m(ord.) 227 1294 y(An)35 b(error)f(is)h(returned)e(if)i(neither)f(a)i(column)e (nor)g(k)m(eyw)m(ord)h(with)g(this)f(name)h(exists.)54 b(Note)36 b(that)g(the)227 1407 y(exclamation)27 b(p)s(oin)m(t,)g(')10 b(!',)27 b(is)e(a)g(sp)s(ecial)h(UNIX)f(c)m(haracter,)j(so)d(if)g(it)h (is)f(used)f(on)h(the)g(command)g(line)g(rather)227 1520 y(than)33 b(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s (e)g(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)g(force)g(the)f(UNIX)h (shell)227 1633 y(to)d(ignore)g(it.)136 1808 y Fc(\017)46 b Fj(Rename)29 b(an)g(existing)g(column)f(or)h(k)m(eyw)m(ord)g(with)f (the)h(syn)m(tax)g('NewName)h(==)e(OldName'.)40 b(An)28 b(error)227 1920 y(is)j(returned)e(if)h(neither)h(a)f(column)g(nor)g(k) m(eyw)m(ord)h(with)f(this)h(name)f(exists.)136 2095 y Fc(\017)46 b Fj(App)s(end)37 b(a)j(new)f(column)f(or)i(k)m(eyw)m(ord)f (to)h(the)f(table.)68 b(T)-8 b(o)40 b(create)g(a)g(column,)h(giv)m(e)g (the)e(new)g(name,)227 2208 y(optionally)c(follo)m(w)m(ed)f(b)m(y)f (the)g(data)h(t)m(yp)s(e)f(in)f(paren)m(theses,)i(follo)m(w)m(ed)h(b)m (y)e(a)g(single)h(equals)f(sign)g(and)f(an)227 2321 y(expression)j(to)h (b)s(e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue)35 b(\(e.g.,)j('new)m (col\(1J\))f(=)e(0')g(will)h(create)g(a)f(new)g(32-bit)227 2434 y(in)m(teger)i(column)d(called)j('new)m(col')f(\014lled)f(with)g (zeros\).)55 b(The)35 b(data)g(t)m(yp)s(e)h(is)f(sp)s(eci\014ed)f (using)g(the)i(same)227 2547 y(syn)m(tax)j(that)g(is)f(allo)m(w)m(ed)i (for)e(the)g(v)-5 b(alue)39 b(of)f(the)g(FITS)f(TF)m(ORMn)h(k)m(eyw)m (ord)h(\(e.g.,)j('I',)d('J',)f('E',)h('D',)227 2660 y(etc.)66 b(for)38 b(binary)f(tables,)42 b(and)37 b('I8',)k(F12.3',)i('E20.12',)g (etc.)65 b(for)38 b(ASCI)s(I)f(tables\).)66 b(If)37 b(the)i(data)g(t)m (yp)s(e)227 2773 y(is)c(not)g(sp)s(eci\014ed)f(then)g(an)g(appropriate) h(data)g(t)m(yp)s(e)g(will)g(b)s(e)f(c)m(hosen)h(dep)s(ending)e(on)h (the)h(form)f(of)h(the)227 2885 y(expression)44 b(\(ma)m(y)g(b)s(e)f(a) h(c)m(haracter)i(string,)h(logical,)j(bit,)d(long)d(in)m(teger,)49 b(or)43 b(double)h(column\).)80 b(An)227 2998 y(appropriate)39 b(v)m(ector)i(coun)m(t)e(\(in)g(the)g(case)h(of)f(binary)f(tables\))i (will)f(also)h(b)s(e)e(added)g(if)h(not)g(explicitly)227 3111 y(sp)s(eci\014ed.)227 3255 y(When)26 b(creating)h(a)f(new)f(k)m (eyw)m(ord,)j(the)e(k)m(eyw)m(ord)g(name)g(m)m(ust)g(b)s(e)f(preceded)g (b)m(y)h(a)g(p)s(ound)e(sign)h('#',)j(and)227 3368 y(the)h(expression)f (m)m(ust)g(ev)-5 b(aluate)30 b(to)f(a)g(scalar)g(\(i.e.,)h(cannot)f(ha) m(v)m(e)h(a)f(column)f(name)g(in)g(the)h(expression\).)227 3481 y(The)j(commen)m(t)i(string)f(for)f(the)h(k)m(eyw)m(ord)h(ma)m(y)f (b)s(e)f(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h(follo)m (wing)227 3594 y(the)27 b(k)m(eyw)m(ord)g(name)f(\(instead)h(of)g (supplying)e(a)i(data)g(t)m(yp)s(e)g(as)f(in)g(the)h(case)g(of)g (creating)h(a)f(new)f(column\).)227 3707 y(If)e(the)h(k)m(eyw)m(ord)g (name)f(ends)g(with)g(a)h(p)s(ound)d(sign)i('#',)i(then)e(c\014tsio)i (will)e(substitute)h(the)f(n)m(um)m(b)s(er)f(of)i(the)227 3820 y(most)31 b(recen)m(tly)h(referenced)e(column)h(for)f(the)h(#)f(c) m(haracter)i(.)41 b(This)29 b(is)i(esp)s(ecially)h(useful)d(when)h (writing)227 3932 y(a)c(column-related)g(k)m(eyw)m(ord)g(lik)m(e)g (TUNITn)e(for)h(a)h(newly)f(created)h(column,)g(as)g(sho)m(wn)e(in)h (the)g(follo)m(wing)227 4045 y(examples.)227 4189 y(COMMENT)30 b(and)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)g(ma)m(y)h(also)h(b)s(e)e (created)h(with)f(the)h(follo)m(wing)g(syn)m(tax:)370 4393 y Fe(#COMMENT)46 b(=)h('This)g(is)g(a)g(comment)f(keyword')370 4506 y(#HISTORY)g(=)h('This)g(is)g(a)g(history)f(keyword')227 4710 y Fj(Note)d(that)f(the)f(equal)h(sign)f(and)f(the)i(quote)f(c)m (haracters)i(will)f(b)s(e)e(remo)m(v)m(ed,)45 b(so)d(that)f(the)h (resulting)227 4823 y(header)30 b(k)m(eyw)m(ords)h(in)f(these)h(cases)g (will)g(lo)s(ok)g(lik)m(e)h(this:)370 5027 y Fe(COMMENT)46 b(This)h(is)g(a)h(comment)d(keyword)370 5140 y(HISTORY)h(This)h(is)g(a) h(history)d(keyword)227 5344 y Fj(These)29 b(t)m(w)m(o)h(sp)s(ecial)f (k)m(eyw)m(ords)h(are)f(alw)m(a)m(ys)h(app)s(ended)d(to)j(the)f(end)f (of)h(the)g(header)g(and)f(will)h(not)g(a\013ect)227 5457 y(an)m(y)i(previously)f(existing)h(COMMENT)f(or)h(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords.)227 5601 y(It)j(is)f(p)s(ossible)h(to)g (delete)h(an)e(existing)i(k)m(eyw)m(ord)f(using)f(a)g(preceding)h Fe('-')p Fj(.)46 b(Either)33 b(of)f(these)h(examples)227 5714 y(will)e(delete)h(the)e(k)m(eyw)m(ord)h(named)f Fe(VEL)p Fj(.)p eop end %%Page: 143 151 TeXDict begin 143 150 bop 0 299 a Fh(10.10.)73 b(COLUMN)30 b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)984 b Fj(143)323 555 y Fe(-VEL;)323 668 y(-#VEL;)136 910 y Fc(\017)46 b Fj(Recompute)f(\(o)m(v)m(erwrite\))i(the)d(v)-5 b(alues)44 b(in)g(an)g(existing)i(column)e(or)g(k)m(eyw)m(ord)g(b)m(y)g (giving)i(the)e(name)227 1023 y(follo)m(w)m(ed)32 b(b)m(y)f(an)f (equals)h(sign)f(and)g(an)g(arithmetic)i(expression.)0 1297 y(The)23 b(expression)g(that)i(is)e(used)g(when)g(app)s(ending)f (or)h(recomputing)h(columns)f(or)h(k)m(eyw)m(ords)g(can)g(b)s(e)f (arbitrarily)0 1410 y(complex)36 b(and)g(ma)m(y)g(b)s(e)f(a)h(function) g(of)g(other)g(header)g(k)m(eyw)m(ord)g(v)-5 b(alues)36 b(and)f(other)h(columns)g(\(in)g(the)g(same)0 1523 y(ro)m(w\).)63 b(The)37 b(full)g(syn)m(tax)i(and)e(a)m(v)-5 b(ailable)40 b(functions)d(for)g(the)h(expression)f(are)h(describ)s(ed)f(b)s(elo)m (w)h(in)f(the)h(ro)m(w)0 1635 y(\014lter)30 b(sp)s(eci\014cation)i (section.)0 1796 y(If)27 b(the)h(expression)g(con)m(tains)g(b)s(oth)f (a)h(list)h(of)f(columns)f(to)h(b)s(e)g(included)e(and)i(columns)f(to)h (b)s(e)f(deleted,)j(then)d(all)0 1909 y(the)34 b(columns)g(in)g(the)g (original)h(table)g(except)g(the)f(explicitly)i(deleted)f(columns)e (will)i(app)s(ear)e(in)h(the)g(\014ltered)0 2021 y(table.)40 b(If)26 b(no)g(columns)f(to)i(b)s(e)f(deleted)g(are)h(sp)s(eci\014ed,)f (then)g(only)g(the)h(columns)e(that)i(are)f(explicitly)i(listed)f(will) 0 2134 y(b)s(e)k(included)g(in)g(the)h(\014ltered)f(output)h(table.)45 b(T)-8 b(o)32 b(include)f(all)i(the)e(columns,)h(add)f(the)h('*')g (wildcard)g(sp)s(eci\014er)0 2247 y(at)f(the)g(end)e(of)i(the)f(list,)i (as)e(sho)m(wn)g(in)g(the)h(examples.)0 2407 y(F)-8 b(or)33 b(complex)f(or)g(commonly)h(used)e(op)s(erations,)i(one)f(can)h(place)g (the)f(op)s(erations)g(in)m(to)h(an)f(external)h(text)g(\014le)0 2520 y(and)39 b(imp)s(ort)h(it)g(in)m(to)h(the)f(column)g(\014lter)g (using)f(the)h(syn)m(tax)h('[col)g(@\014lename.txt]'.)71 b(The)39 b(op)s(erations)i(can)0 2633 y(extend)35 b(o)m(v)m(er)h(m)m (ultiple)g(lines)f(of)g(the)g(\014le,)h(but)e(m)m(ultiple)i(op)s (erations)f(m)m(ust)f(still)i(b)s(e)e(separated)i(b)m(y)e(commas)0 2746 y(or)e(semi-colons.)47 b(An)m(y)32 b(lines)h(in)f(the)g(external)h (text)g(\014le)f(that)h(b)s(egin)e(with)h(2)h(slash)e(c)m(haracters)j (\('//'\))g(will)f(b)s(e)0 2859 y(ignored)d(and)g(ma)m(y)h(b)s(e)f (used)g(to)h(add)e(commen)m(ts)j(in)m(to)f(the)g(\014le.)0 3019 y(When)39 b(using)f(column)h(\014ltering)h(to)g(op)s(en)e(a)h (\014le)h(\\on)f(the)g(\015y)-8 b(,")42 b(it)e(is)f(p)s(ermitted)g(to)h (use)e(m)m(ultiple)i(column)0 3132 y(\014ltering)31 b(expressions.)40 b(F)-8 b(or)31 b(example,)g(the)g(syn)m(tax)95 3377 y Fe(filename.fits[col)44 b(*][col)i(-Y][col)f(Z=X+1])0 3622 y Fj(w)m(ould)30 b(b)s(e)g(treated)h(as)g(equiv)-5 b(alen)m(t)32 b(to)f(joining)f(the)h(expressions)f(with)g(semicolons,)i (or)95 3868 y Fe(filename.fits[col)44 b(*;)j(-Y;col)f(Z=X+1])0 4113 y Fj(Please)37 b(note)e(that)h(if)g(m)m(ultiple)g(column)f (\014ltering)g(expressions)g(are)h(used,)g(it)g(is)f(not)h(p)s (ermitted)f(to)h(also)g(use)0 4226 y(the)31 b Fe([col)46 b(@filename.txt])27 b Fj(syn)m(tax)k(in)f(an)m(y)g(of)h(the)f (individual)g(expressions.)0 4386 y(It)36 b(is)f(p)s(ossible)g(to)h (use)g(wildcard)f(syn)m(tax)h(to)g(delete)h(either)f(k)m(eyw)m(ords)g (or)f(columns)g(that)h(matc)m(h)h(a)f(pattern.)0 4499 y(Recall)c(that)f(to)g(delete)h(either)f(a)f(k)m(eyw)m(ord)h(or)f(a)h (column,)g(precede)f(its)h(name)f(with)g(a)h Fe('-')f Fj(c)m(haracter.)0 4659 y(Wildcard)d(patterns)f(are:)39 b Fe('*')p Fj(,)27 b(whic)m(h)f(matc)m(hes)i(an)m(y)f(string)f(of)h(c)m (haracters;)i Fe('?')p Fj(,)e(whic)m(h)f(matc)m(hes)h(an)m(y)g(single)0 4772 y(c)m(haracter;)32 b(and)e Fe('#')f Fj(whic)m(h)i(matc)m(hes)g(an) m(y)g(n)m(umerical)g(string.)40 b(F)-8 b(or)32 b(example)f(these)f (statemen)m(ts:)95 5017 y Fe(-VEL*;)333 b(#)47 b(remove)f(single)h (column)f(\(or)h(keyword\))e(beginning)g(with)i(VEL)95 5130 y(-VEL_?;)285 b(#)47 b(remove)f(single)h(column)f(\(or)h (keyword\))e(VEL_?)h(where)h(?)g(is)g(any)g(character)95 5243 y(-#DEC_*;)237 b(#)47 b(remove)f(single)h(keyword)e(beginning)h (with)g(DEC_)95 5356 y(-#TUNIT#;)189 b(#)47 b(remove)f(single)h (keyword)e(TUNIT)i(ending)f(w.)h(number)0 5601 y Fj(will)28 b(remo)m(v)m(e)h(the)e(columns)h(or)f(k)m(eyw)m(ords)h(as)f(noted.)40 b(Be)29 b(a)m(w)m(are)f(that)g(if)g(a)g Fe('#')e Fj(is)i(not)f(presen)m (t,)i(the)e(CFITSIO)0 5714 y(engine)k(will)g(c)m(hec)m(k)g(for)g (columns)f(with)g(the)g(giv)m(en)i(name)e(\014rst,)g(follo)m(w)m(ed)i (b)m(y)e(k)m(eyw)m(ords.)p eop end %%Page: 144 152 TeXDict begin 144 151 bop 0 299 a Fj(144)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)21 b(ab)s(o)m(v)m(e)i(expressions)e(will)g(only)h(delete)g (the)g Fa(\014rst)g Fj(item)g(whic)m(h)f(matc)m(hes)i(the)f(pattern.)37 b(If)21 b(follo)m(wing)i(columns)0 668 y(or)38 b(k)m(eyw)m(ords)f(in)h (the)g(same)g(CHDU)f(matc)m(h)i(the)f(pattern,)h(they)f(will)g(not)g(b) s(e)f(deleted.)63 b(T)-8 b(o)38 b(delete)h Fa(zer)-5 b(o)40 b(or)0 781 y(mor)-5 b(e)32 b Fj(k)m(eyw)m(ords)e(that)h(matc)m (h)h(the)e(pattern,)h(add)f(a)g(trailing)i Fe('+')p Fj(.)95 1077 y Fe(-VEL*+;)333 b(#)47 b(remove)f(all)h(columns)f(\(or)h (keywords\))e(beginning)g(with)i(VEL)95 1190 y(-VEL_?+;)285 b(#)47 b(remove)f(all)h(columns)f(\(or)h(keyword\))e(VEL_?)i(where)f(?) i(is)f(any)g(character)95 1303 y(-#DEC_*+;)237 b(#)47 b(remove)f(all)h(keywords)f(beginning)f(with)i(DEC_)95 1416 y(-#TUNIT#+;)189 b(#)47 b(remove)f(all)h(keywords)f(TUNIT)g (ending)g(w.)h(number)0 1712 y Fj(Note)c(that,)i(as)d(a)f(0-or-more)i (matc)m(hing)g(pattern,)h(this)e(form)f(will)g(succeed)h(if)g(the)f (requested)h(column)f(or)0 1825 y(k)m(eyw)m(ord)32 b(is)f(not)g(presen) m(t.)43 b(In)31 b(that)g(case,)i(the)e(deletion)i(expression)e(will)g (silen)m(tly)h(pro)s(ceed)f(as)h(if)f(no)g(deletion)0 1938 y(w)m(as)g(requested.)0 2098 y(Examples:)143 2439 y Fe([col)47 b(Time,)f(rate])667 b(-)47 b(only)g(the)g(Time)g(and)g (rate)f(columns)g(will)1670 2552 y(appear)h(in)g(the)g(filtered)e (input)i(file.)143 2778 y([col)g(Time,)f(*raw])667 b(-)47 b(include)f(the)h(Time)g(column)f(and)h(any)g(other)1670 2891 y(columns)f(whose)h(name)f(ends)h(with)g('raw'.)143 3117 y([col)g(-TIME,)f(Good)h(==)g(STATUS])141 b(-)47 b(deletes)f(the)h(TIME)g(column)f(and)1670 3230 y(renames)g(the)h (status)f(column)g(to)i('Good')143 3456 y([col)f(PI=PHA)f(*)h(1.1)g(+)h (0.2;)e(#TUNIT#\(column)e(units\))i(=)i('counts';*])1575 3569 y(-)f(creates)f(new)h(PI)g(column)f(from)h(PHA)g(values)1670 3681 y(and)g(also)g(writes)f(the)h(TUNITn)f(keyword)1670 3794 y(for)h(the)g(new)g(column.)94 b(The)47 b(final)f('*')1670 3907 y(expression)f(means)i(preserve)e(all)i(the)1670 4020 y(columns)f(in)h(the)g(input)g(table)f(in)h(the)1670 4133 y(virtual)f(output)g(table;)94 b(without)46 b(the)h('*')1670 4246 y(the)g(output)f(table)h(would)f(only)h(contain)1670 4359 y(the)g(single)f('PI')h(column.)143 4585 y([col)g(rate)f(=)i (rate/exposure;)c(TUNIT#\(&\))h(=)j('counts/s';*])1575 4698 y(-)f(recomputes)e(the)i(rate)g(column)f(by)h(dividing)1670 4811 y(it)h(by)f(the)g(EXPOSURE)e(keyword)h(value.)g(This)1670 4924 y(also)h(modifies)f(the)h(value)f(of)h(the)g(TUNITn)1670 5036 y(keyword)f(for)h(this)g(column.)f(The)h(use)f(of)i(the)1670 5149 y('&')f(character)f(for)h(the)f(keyword)g(comment)1670 5262 y(string)h(means)f(preserve)f(the)i(existing)1670 5375 y(comment)f(string)g(for)h(that)g(keyword.)e(The)1670 5488 y(final)i('*')g(preserves)e(all)i(the)g(columns)1670 5601 y(in)h(the)f(input)f(table)g(in)h(the)g(virtual)1670 5714 y(output)g(table.)p eop end %%Page: 145 153 TeXDict begin 145 152 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(145)0 555 y Ff(10.11)136 b(Ro)l(w)46 b(Filtering)g(Sp)t(eci\014cation)0 806 y Fj(When)29 b(en)m(tering)h(the)f(name)g(of)g(a)g(FITS)f(table)i (that)g(is)e(to)i(b)s(e)e(op)s(ened)h(b)m(y)f(a)i(program,)f(an)g (optional)h(ro)m(w)f(\014lter)0 919 y(ma)m(y)i(b)s(e)g(sp)s(eci\014ed)f (to)h(select)h(a)g(subset)e(of)h(the)g(ro)m(ws)f(in)h(the)g(table.)43 b(A)31 b(temp)s(orary)f(new)g(FITS)g(\014le)h(is)g(created)0 1032 y(on)40 b(the)f(\015y)g(whic)m(h)h(con)m(tains)h(only)e(those)h (ro)m(ws)g(for)f(whic)m(h)h(the)g(ro)m(w)f(\014lter)h(expression)f(ev) -5 b(aluates)42 b(to)e(true.)0 1145 y(The)29 b(primary)f(arra)m(y)i (and)f(an)m(y)g(other)h(extensions)g(in)f(the)g(input)g(\014le)g(are)h (also)g(copied)g(to)g(the)g(temp)s(orary)f(\014le.)0 1258 y(\(If)35 b(a)h(`#')f(c)m(haracter)i(is)e(app)s(ended)e(to)j(the)g (name)f(or)g(n)m(um)m(b)s(er)f(of)h(the)g(table)h(HDU)g(then)f(only)g (the)h(primary)0 1371 y(arra)m(y)-8 b(,)37 b(and)d(none)h(of)g(the)g (other)g(HDUs)h(in)e(the)i(input)e(\014le)g(will)i(b)s(e)e(copied)h(in) m(to)h(the)f(temp)s(orary)g(\014le\).)54 b(The)0 1484 y(original)30 b(FITS)f(\014le)g(is)g(closed)h(and)e(the)i(new)e (virtual)i(\014le)f(is)g(op)s(ened)f(b)m(y)h(the)h(application)g (program.)40 b(The)29 b(ro)m(w)0 1597 y(\014lter)37 b(expression)g(is)h (enclosed)g(in)f(square)g(brac)m(k)m(ets)i(follo)m(wing)g(the)e(\014le) h(name)f(and)g(extension)h(name)f(\(e.g.,)0 1710 y('\014le.\014ts[ev)m (en)m(ts][GRADE==50]')29 b(selects)d(only)f(those)h(ro)m(ws)f(where)f (the)h(GRADE)h(column)f(v)-5 b(alue)25 b(equals)g(50\).)0 1823 y(When)33 b(dealing)h(with)f(tables)g(where)g(eac)m(h)h(ro)m(w)f (has)g(an)g(asso)s(ciated)i(time)f(and/or)f(2D)g(spatial)i(p)s (osition,)f(the)0 1936 y(ro)m(w)e(\014lter)h(expression)e(can)i(also)g (b)s(e)f(used)f(to)i(select)h(ro)m(ws)e(based)g(on)g(the)g(times)h(in)f (a)g(Go)s(o)s(d)g(Time)g(In)m(terv)-5 b(als)0 2048 y(\(GTI\))31 b(extension,)g(or)f(on)h(spatial)g(p)s(osition)g(as)f(giv)m(en)i(in)e (a)g(SA)m(O-st)m(yle)i(region)f(\014le.)0 2344 y Fd(10.11.1)113 b(General)38 b(Syn)m(tax)0 2564 y Fj(The)32 b(ro)m(w)h(\014ltering)g (expression)g(can)g(b)s(e)f(an)h(arbitrarily)g(complex)g(series)g(of)g (op)s(erations)g(p)s(erformed)f(on)g(con-)0 2677 y(stan)m(ts,)39 b(k)m(eyw)m(ord)e(v)-5 b(alues,)38 b(and)e(column)g(data)i(tak)m(en)f (from)f(the)h(sp)s(eci\014ed)e(FITS)h(T)-8 b(ABLE)37 b(extension.)59 b(The)0 2790 y(expression)37 b(m)m(ust)h(ev)-5 b(aluate)39 b(to)g(a)f(b)s(o)s(olean)g(v)-5 b(alue)38 b(for)f(eac)m(h)i(ro)m(w)f(of)g(the)f(table,)k(where)c(a)h(v)-5 b(alue)39 b(of)e(F)-10 b(ALSE)0 2903 y(means)30 b(that)h(the)g(ro)m(w)f (will)h(b)s(e)f(excluded.)0 3063 y(F)-8 b(or)34 b(complex)g(or)g (commonly)f(used)g(\014lters,)h(one)g(can)g(place)g(the)g(expression)f (in)m(to)h(a)g(text)g(\014le)g(and)f(imp)s(ort)f(it)0 3176 y(in)m(to)38 b(the)e(ro)m(w)h(\014lter)g(using)f(the)h(syn)m(tax)g ('[@\014lename.txt]'.)61 b(The)36 b(expression)h(can)f(b)s(e)g (arbitrarily)h(complex)0 3289 y(and)27 b(extend)i(o)m(v)m(er)g(m)m (ultiple)g(lines)f(of)g(the)h(\014le.)40 b(An)m(y)28 b(lines)g(in)g(the)g(external)h(text)g(\014le)f(that)h(b)s(egin)f(with) g(2)g(slash)0 3402 y(c)m(haracters)k(\('//'\))g(will)f(b)s(e)f(ignored) g(and)g(ma)m(y)h(b)s(e)f(used)f(to)i(add)f(commen)m(ts)h(in)m(to)h(the) e(\014le.)0 3562 y(Keyw)m(ord)37 b(and)f(column)g(data)i(are)f (referenced)g(b)m(y)g(name.)60 b(An)m(y)37 b(string)f(of)h(c)m (haracters)i(not)e(surrounded)d(b)m(y)0 3675 y(quotes)41 b(\(ie,)j(a)d(constan)m(t)h(string\))f(or)f(follo)m(w)m(ed)i(b)m(y)f (an)f(op)s(en)g(paren)m(theses)h(\(ie,)j(a)d(function)f(name\))h(will)g (b)s(e)0 3788 y(initially)d(in)m(terpreted)e(as)h(a)g(column)f(name)g (and)g(its)h(con)m(ten)m(ts)h(for)e(the)h(curren)m(t)f(ro)m(w)g (inserted)g(in)m(to)i(the)e(ex-)0 3901 y(pression.)k(If)28 b(no)h(suc)m(h)g(column)g(exists,)h(a)g(k)m(eyw)m(ord)f(of)h(that)f (name)g(will)h(b)s(e)e(searc)m(hed)i(for)f(and)f(its)i(v)-5 b(alue)29 b(used,)0 4014 y(if)36 b(found.)55 b(T)-8 b(o)36 b(force)g(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)g(a)g(k)m(eyw)m (ord)g(\(in)g(case)g(there)g(is)g(b)s(oth)f(a)h(column)g(and)0 4127 y(k)m(eyw)m(ord)41 b(with)e(the)i(same)f(name\),)j(precede)d(the)h (k)m(eyw)m(ord)f(name)g(with)g(a)h(single)f(p)s(ound)e(sign,)43 b('#',)g(as)d(in)0 4240 y('#NAXIS2'.)g(Due)27 b(to)g(the)f (generalities)j(of)d(FITS)g(column)g(and)g(k)m(eyw)m(ord)h(names,)g(if) f(the)h(column)f(or)g(k)m(eyw)m(ord)0 4353 y(name)33 b(con)m(tains)h(a)f(space)h(or)f(a)g(c)m(haracter)h(whic)m(h)f(migh)m (t)h(app)s(ear)e(as)h(an)g(arithmetic)h(term)f(then)g(enclose)h(the)0 4465 y(name)c(in)g('$')i(c)m(haracters)g(as)e(in)g($MAX)i(PHA$)f(or)f (#$MAX-PHA$.)43 b(Names)31 b(are)f(case)i(insensitiv)m(e.)0 4626 y(T)-8 b(o)32 b(access)g(a)g(table)g(en)m(try)g(in)f(a)h(ro)m(w)f (other)h(than)f(the)g(curren)m(t)g(one,)h(follo)m(w)h(the)e(column's)h (name)f(with)g(a)h(ro)m(w)0 4738 y(o\013set)37 b(within)e(curly)g (braces.)57 b(F)-8 b(or)36 b(example,)i('PHA)p Fc(f)p Fj(-3)p Fc(g)p Fj(')g(will)e(ev)-5 b(aluate)38 b(to)e(the)g(v)-5 b(alue)36 b(of)g(column)f(PHA,)i(3)0 4851 y(ro)m(ws)28 b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s(eing)g(pro)s (cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g(absolute)h(ro)m(w)f (n)m(um)m(b)s(er,)g(only)h(a)0 4964 y(relativ)m(e)j(o\013set.)42 b(Ro)m(ws)31 b(that)g(fall)g(outside)g(the)f(table)h(will)g(b)s(e)f (treated)h(as)g(unde\014ned,)d(or)j(NULLs.)0 5124 y(When)36 b(using)f(ro)m(w)h(\014ltering)g(to)g(op)s(en)g(a)g(\014le)g(\\on)g (the)g(\015y)-8 b(,")38 b(it)e(is)g(p)s(ermitted)f(to)i(use)e(m)m (ultiple)i(ro)m(w)f(\014ltering)0 5237 y(expressions.)k(F)-8 b(or)31 b(example,)h(the)e(expression)95 5476 y Fe(filename.fits[#ROW) 43 b(>)48 b(5][X.gt.7])0 5714 y Fj(w)m(ould)30 b(b)s(e)g(treated)h(as)g (equiv)-5 b(alen)m(t)32 b(to)f(joining)f(the)h(expressions)f(with)g (logical)j(\\and")d(lik)m(e)i(this,)p eop end %%Page: 146 154 TeXDict begin 146 153 bop 0 299 a Fj(146)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)95 555 y Fe(filename.fits[\(#ROW)43 b(>)k(5\)&&\(X.gt.7\)])0 787 y Fj(Please)35 b(note)g(that)g(if)g(m)m(ultiple)g(ro)m(w)f (\014ltering)h(expressions)e(are)i(used,)g(it)g(is)f(not)h(p)s (ermitted)e(to)i(also)h(use)e(the)0 900 y Fe([@filename.txt])26 b Fj(syn)m(tax)31 b(in)f(an)m(y)h(of)f(the)h(individual)f(expressions.) 0 1060 y(Bo)s(olean)i(op)s(erators)f(can)g(b)s(e)f(used)f(in)i(the)f (expression)h(in)f(either)h(their)g(F)-8 b(ortran)31 b(or)f(C)h(forms.)40 b(The)30 b(follo)m(wing)0 1173 y(b)s(o)s(olean)g (op)s(erators)h(are)g(a)m(v)-5 b(ailable:)191 1429 y Fe("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)191 1542 y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)191 1655 y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)191 1767 y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 b(.AND.)h(&&)191 1880 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 b(~)0 2136 y Fj(Note)32 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)e(') 10 b(!',)33 b(is)e(a)g(sp)s(ecial)g(UNIX)h(c)m(haracter,)h(so)e(if)g (it)g(is)g(used)f(on)h(the)g(command)0 2249 y(line)i(rather)f(than)h (en)m(tered)g(at)g(a)g(task)g(prompt,)g(it)g(m)m(ust)f(b)s(e)g (preceded)h(b)m(y)f(a)h(bac)m(kslash)g(to)h(force)f(the)g(UNIX)0 2362 y(shell)e(to)g(ignore)g(it.)0 2522 y(The)h(expression)g(ma)m(y)i (also)f(include)f(arithmetic)i(op)s(erators)f(and)f(functions.)47 b(T)-8 b(rigonometric)34 b(functions)e(use)0 2635 y(radians,)23 b(not)g(degrees.)38 b(The)22 b(follo)m(wing)h(arithmetic)g(op)s (erators)g(and)e(functions)g(can)i(b)s(e)e(used)g(in)h(the)g (expression)0 2748 y(\(function)38 b(names)f(are)h(case)g(insensitiv)m (e\).)64 b(A)37 b(n)m(ull)h(v)-5 b(alue)38 b(will)f(b)s(e)g(returned)g (in)g(case)h(of)g(illegal)i(op)s(erations)0 2861 y(suc)m(h)30 b(as)h(divide)f(b)m(y)g(zero,)i(sqrt\(negativ)m(e\))h(log\(negativ)m (e\),)h(log10\(negativ)m(e\),)i(arccos\(.gt.)43 b(1\),)32 b(arcsin\(.gt.)42 b(1\).)191 3117 y Fe("addition")522 b(+)477 b("subtraction")d(-)191 3230 y("multiplication")234 b(*)477 b("division")618 b(/)191 3343 y("negation")522 b(-)477 b("exponentiation")330 b(**)143 b(^)191 3456 y("absolute)45 b(value")237 b(abs\(x\))g("cosine")714 b(cos\(x\))191 3569 y("sine")g(sin\(x\))237 b("tangent")666 b(tan\(x\))191 3681 y("arc)47 b(cosine")427 b(arccos\(x\))93 b("arc)47 b(sine")619 b(arcsin\(x\))191 3794 y("arc)47 b(tangent")379 b(arctan\(x\))93 b("arc)47 b(tangent")475 b(arctan2\(y,x\))191 3907 y("hyperbolic)45 b(cos")237 b(cosh\(x\))189 b("hyperbolic)45 b(sin")333 b(sinh\(x\))191 4020 y("hyperbolic)45 b(tan")237 b(tanh\(x\))189 b("round)46 b(to)h(nearest)f(int")h(round\(x\))191 4133 y("round)f(down)h(to)g (int")94 b(floor\(x\))141 b("round)46 b(up)h(to)h(int")285 b(ceil\(x\))191 4246 y("exponential")378 b(exp\(x\))237 b("square)46 b(root")476 b(sqrt\(x\))191 4359 y("natural)45 b(log")381 b(log\(x\))237 b("common)46 b(log")524 b(log10\(x\))191 4472 y("error)46 b(function")236 b(erf\(x\))h("complement)45 b(of)i(erf")190 b(erfc\(x\))191 4585 y("gamma)46 b(function")236 b(gamma\(x\))191 4698 y("modulus")570 b(x)48 b(\045)f(y)191 4811 y("bitwise)e(AND")381 b(x)48 b(&)f(y)286 b("bitwise)46 b(OR")524 b(x)47 b(|)h(y)191 4924 y("bitwise)d(XOR")381 b(x)48 b(^^)f(y)238 b(\(bitwise)46 b(operators)f(are)i(32-bit)f(int)h (only\))191 5036 y("random)f(#)h([0.0,1.0\)")e(random\(\))191 5149 y("random)h(Gaussian")188 b(randomn\(\))93 b("random)46 b(Poisson")332 b(randomp\(x\))191 5262 y("minimum")570 b(min\(x,y\))141 b("maximum")666 b(max\(x,y\))191 5375 y("cumulative)45 b(sum")237 b(accum\(x\))141 b("sequential)45 b(difference")g(seqdiff\(x\))191 5488 y("if-then-else")330 b(b?x:y)191 5601 y("angular)45 b(separation")g (angsep\(ra1,dec1,ra2,de2\))c(\(all)47 b(in)g(degrees\))191 5714 y("substring")474 b(strmid\(s,p,n\))44 b("string)i(search")237 b(strstr\(s,r\))p eop end %%Page: 147 155 TeXDict begin 147 154 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(147)0 555 y(The)30 b(bit)m(wise)h(op)s(erators)f(for)h(AND,)g(OR)f(and)g(X)m (OR)g(op)s(erate)h(up)s(on)e(32-bit)j(in)m(teger)f(expressions)f(only) -8 b(.)0 715 y(Three)30 b(di\013eren)m(t)h(random)f(n)m(um)m(b)s(er)f (functions)h(are)h(pro)m(vided:)41 b(random\(\),)30 b(with)h(no)f (argumen)m(ts,)h(pro)s(duces)f(a)0 828 y(uniform)g(random)f(deviate)k (b)s(et)m(w)m(een)e(0)g(and)f(1;)i(randomn\(\),)e(also)i(with)e(no)h (argumen)m(ts,)g(pro)s(duces)f(a)h(normal)0 941 y(\(Gaussian\))k (random)e(deviate)j(with)e(zero)h(mean)f(and)g(unit)f(standard)h (deviation;)j(randomp\(x\))d(pro)s(duces)f(a)0 1054 y(P)m(oisson)27 b(random)f(deviate)h(whose)f(exp)s(ected)h(n)m(um)m(b)s(er)e(of)h(coun) m(ts)h(is)g(X.)f(X)h(ma)m(y)g(b)s(e)e(an)m(y)i(p)s(ositiv)m(e)g(real)g (n)m(um)m(b)s(er)0 1167 y(of)k(exp)s(ected)f(coun)m(ts,)h(including)f (fractional)i(v)-5 b(alues,)31 b(but)f(the)g(return)g(v)-5 b(alue)31 b(is)f(an)g(in)m(teger.)0 1327 y(When)d(the)g(random)g (functions)f(are)i(used)e(in)h(a)h(v)m(ector)g(expression,)g(b)m(y)f (default)h(the)f(same)h(random)e(v)-5 b(alue)28 b(will)0 1440 y(b)s(e)g(used)f(when)h(ev)-5 b(aluating)30 b(eac)m(h)f(elemen)m (t)h(of)f(the)g(v)m(ector.)41 b(If)28 b(di\013eren)m(t)h(random)f(n)m (um)m(b)s(ers)f(are)i(desired,)f(then)0 1553 y(the)37 b(name)g(of)g(a)g(v)m(ector)i(column)e(should)e(b)s(e)i(supplied)e(as)i (the)h(single)f(argumen)m(t)g(to)h(the)f(random)f(function)0 1666 y(\(e.g.,)e("\015ux)c(+)h(0.1)i(*)e(random\(\015ux\)",)h(where)f ("\015ux")g(is)g(the)h(name)f(of)h(a)f(v)m(ector)i(column\).)44 b(This)31 b(will)g(create)0 1779 y(a)38 b(v)m(ector)i(of)e(random)f(n)m (um)m(b)s(ers)f(that)j(will)f(b)s(e)f(used)g(in)h(sequence)g(when)f(ev) -5 b(aluating)39 b(eac)m(h)g(elemen)m(t)h(of)e(the)0 1892 y(v)m(ector)32 b(expression.)0 2052 y(An)f(alternate)i(syn)m(tax)f (for)f(the)g(min)g(and)g(max)g(functions)g(has)g(only)g(a)h(single)g (argumen)m(t)g(whic)m(h)f(should)f(b)s(e)h(a)0 2165 y(v)m(ector)g(v)-5 b(alue)30 b(\(see)g(b)s(elo)m(w\).)41 b(The)29 b(result)g(will)h(b)s(e) e(the)i(minim)m(um/maxim)m(um)f(elemen)m(t)h(con)m(tained)h(within)e (the)0 2278 y(v)m(ector.)0 2438 y(The)35 b(accum\(x\))i(function)f (forms)f(the)h(cum)m(ulativ)m(e)i(sum)d(of)h(x,)h(elemen)m(t)h(b)m(y)e (elemen)m(t.)58 b(V)-8 b(ector)38 b(columns)e(are)0 2551 y(supp)s(orted)h(simply)h(b)m(y)g(p)s(erforming)f(the)i(summation)g (pro)s(cess)f(through)f(all)j(the)f(v)-5 b(alues.)65 b(Null)39 b(v)-5 b(alues)39 b(are)0 2664 y(treated)30 b(as)f(0.)41 b(The)29 b(seqdi\013\(x\))h(function)e(forms)h(the)g (sequen)m(tial)i(di\013erence)e(of)h(x,)f(elemen)m(t)i(b)m(y)e(elemen)m (t.)41 b(The)0 2777 y(\014rst)36 b(v)-5 b(alue)38 b(of)f(seqdi\013)g (is)g(the)g(\014rst)g(v)-5 b(alue)37 b(of)g(x.)61 b(A)37 b(single)h(n)m(ull)f(v)-5 b(alue)38 b(in)e(x)h(causes)h(a)f(pair)g(of)g (n)m(ulls)g(in)g(the)0 2889 y(output.)55 b(The)35 b(seqdi\013)g(and)g (accum)g(functions)g(are)h(functional)f(in)m(v)m(erses,)j(i.e.,)g (seqdi\013\(accum\(x\)\))f(==)e(x)g(as)0 3002 y(long)c(as)g(no)f(n)m (ull)g(v)-5 b(alues)31 b(are)g(presen)m(t.)0 3163 y(In)36 b(the)h(if-then-else)i(expression,)f("b?x:y",)i(b)c(is)h(an)g(explicit) h(b)s(o)s(olean)f(v)-5 b(alue)37 b(or)g(expression.)61 b(There)36 b(is)h(no)0 3275 y(automatic)d(t)m(yp)s(e)e(con)m(v)m (ersion)h(from)e(n)m(umeric)h(to)g(b)s(o)s(olean)g(v)-5 b(alues,)33 b(so)f(one)g(needs)f(to)i(use)e("iV)-8 b(al!=0")35 b(instead)0 3388 y(of)30 b(merely)g("iV)-8 b(al")32 b(as)e(the)g(b)s(o) s(olean)g(argumen)m(t.)41 b(x)30 b(and)f(y)h(can)g(b)s(e)f(an)m(y)h (scalar)h(data)g(t)m(yp)s(e)f(\(including)f(string\).)0 3548 y(The)22 b(angsep)g(function)f(computes)i(the)f(angular)g (separation)h(in)e(degrees)i(b)s(et)m(w)m(een)g(2)f(celestial)j(p)s (ositions,)e(where)0 3661 y(the)36 b(\014rst)f(2)h(parameters)g(giv)m (e)h(the)f(RA-lik)m(e)i(and)d(Dec-lik)m(e)j(co)s(ordinates)f(\(in)f (decimal)g(degrees\))h(of)f(the)g(\014rst)0 3774 y(p)s(osition,)31 b(and)e(the)i(3rd)f(and)g(4th)g(parameters)h(giv)m(e)h(the)e(co)s (ordinates)i(of)e(the)h(second)f(p)s(osition.)0 3934 y(The)38 b(substring)f(function)i(strmid\(S,P)-8 b(,N\))39 b(extracts)g(a)g(substring)f(from)g(S,)g(starting)h(at)g(string)g(p)s (osition)f(P)-8 b(,)0 4047 y(with)33 b(a)h(substring)f(length)h(N.)g (The)f(\014rst)g(c)m(haracter)j(p)s(osition)d(in)h(S)f(is)h(lab)s(eled) g(as)g(1.)51 b(If)33 b(P)g(is)h(0,)h(or)f(refers)f(to)0 4160 y(a)i(p)s(osition)g(b)s(ey)m(ond)f(the)h(end)e(of)i(S,)g(then)f (the)h(extracted)h(substring)d(will)i(b)s(e)f(NULL.)h(S,)f(P)-8 b(,)36 b(and)e(N)g(ma)m(y)i(b)s(e)0 4273 y(functions)30 b(of)g(other)h(columns.)0 4433 y(The)39 b(string)h(searc)m(h)h (function)e(strstr\(S,R\))h(searc)m(hes)h(for)f(the)g(\014rst)f(o)s (ccurrence)h(of)g(the)g(substring)f(R)h(in)f(S.)0 4546 y(The)c(result)h(is)f(an)h(in)m(teger,)i(indicating)f(the)e(c)m (haracter)i(p)s(osition)f(of)g(the)g(\014rst)e(matc)m(h)j(\(where)e(1)h (is)g(the)g(\014rst)0 4659 y(c)m(haracter)c(p)s(osition)e(of)h(S\).)f (If)g(no)h(matc)m(h)g(is)f(found,)g(then)g(strstr\(\))g(returns)f(a)i (NULL)f(v)-5 b(alue.)0 4819 y(The)37 b(follo)m(wing)i(t)m(yp)s(e)f (casting)g(op)s(erators)g(are)g(a)m(v)-5 b(ailable,)42 b(where)37 b(the)h(enclosing)g(paren)m(theses)g(are)g(required)0 4932 y(and)30 b(tak)m(en)h(from)f(the)h(C)f(language)h(usage.)42 b(Also,)31 b(the)g(in)m(teger)g(to)h(real)f(casts)g(v)-5 b(alues)30 b(to)i(double)e(precision:)764 5155 y Fe("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 b(x)764 5268 y("integer)f(to)i(real")190 b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)0 5491 y Fj(In)30 b(addition,)g(sev)m(eral)i (constan)m(ts)g(are)f(built)f(in)g(for)g(use)g(in)g(n)m(umerical)h (expressions:)382 5714 y Fe(#pi)667 b(3.1415...)284 b(#e)620 b(2.7182...)p eop end %%Page: 148 156 TeXDict begin 148 155 bop 0 299 a Fj(148)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)382 555 y Fe(#deg)619 b(#pi/180)380 b(#row)524 b(current)46 b(row)h(number)382 668 y(#null)428 b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 b(string)0 952 y Fj(A)40 b(string)f(constan)m(t)i(m)m(ust)e(b)s(e)g(enclosed)h(in)g(quotes)g(as) f(in)h('Crab'.)67 b(The)39 b("n)m(ull")i(constan)m(ts)f(are)g(useful)f (for)0 1065 y(conditionally)g(setting)g(table)g(v)-5 b(alues)38 b(to)g(a)g(NULL,)g(or)g(unde\014ned,)f(v)-5 b(alue)39 b(\(eg.,)i("col1==-99)f(?)62 b(#NULL)38 b(:)0 1178 y(col1"\).)0 1338 y(In)m(teger)31 b(constan)m(ts)h(ma)m(y)f(b)s(e) f(sp)s(eci\014ed)f(using)h(the)h(follo)m(wing)h(notation,)525 1591 y Fe(13245)142 b(decimal)46 b(integer)525 1703 y(0x12f3)94 b(hexidecimal)45 b(integer)525 1816 y(0o1373)94 b(octal)46 b(integer)525 1929 y(0b01001)g(binary)g(integer)0 2182 y Fj(Note)32 b(that)g(in)m(teger)g(constan)m(ts)g(are)f(only)g(allo)m (w)m(ed)i(to)e(b)s(e)g(32-bit,)h(i.e.)43 b(b)s(et)m(w)m(een)32 b(-2)2902 2153 y(^)2907 2182 y(\(31\))h(and)d(+2)3388 2153 y(^)3393 2182 y(\(31\).)44 b(In)m(teger)0 2295 y(constan)m(ts)30 b(ma)m(y)g(b)s(e)f(used)f(in)h(an)m(y)g(arithmetic)i(expression)e (where)f(an)h(in)m(teger)i(w)m(ould)e(b)s(e)f(appropriate.)41 b(Th)m(us,)0 2408 y(they)33 b(are)h(distinct)g(from)e(bitmasks)h (\(whic)m(h)h(ma)m(y)f(b)s(e)g(of)g(arbitrary)g(length,)i(allo)m(w)f (the)g("wildcard")f(bit,)i(and)0 2521 y(ma)m(y)c(only)f(b)s(e)g(used)g (in)g(logical)j(expressions;)d(see)h(b)s(elo)m(w\).)0 2681 y(There)c(is)g(also)i(a)e(function)g(for)h(testing)g(if)f(t)m(w)m (o)i(v)-5 b(alues)28 b(are)g(close)g(to)h(eac)m(h)f(other,)h(i.e.,)g (if)e(they)h(are)g("near")g(eac)m(h)0 2794 y(other)c(to)h(within)e(a)h (user)g(sp)s(eci\014ed)f(tolerance.)40 b(The)24 b(argumen)m(ts,)h(v)-5 b(alue)p 2502 2794 28 4 v 34 w(1)24 b(and)f(v)-5 b(alue)p 2979 2794 V 33 w(2)25 b(can)f(b)s(e)f(in)m(teger)i(or)f(real)0 2907 y(and)32 b(represen)m(t)h(the)g(t)m(w)m(o)h(v)-5 b(alues)33 b(who's)f(pro)m(ximit)m(y)i(is)f(b)s(eing)f(tested)h(to)h(b) s(e)e(within)g(the)h(sp)s(eci\014ed)f(tolerance,)0 3020 y(also)f(an)g(in)m(teger)g(or)g(real:)955 3303 y Fe(near\(value_1,)44 b(value_2,)h(tolerance\))0 3587 y Fj(When)24 b(a)i(NULL,)e(or)h (unde\014ned,)f(v)-5 b(alue)25 b(is)g(encoun)m(tered)g(in)g(the)f(FITS) g(table,)j(the)e(expression)g(will)g(ev)-5 b(aluate)26 b(to)0 3700 y(NULL)31 b(unless)f(the)h(unde\014ned)e(v)-5 b(alue)31 b(is)g(not)g(actually)h(required)e(for)h(ev)-5 b(aluation,)33 b(e.g.)43 b("TR)m(UE)31 b(.or.)43 b(NULL")0 3813 y(ev)-5 b(aluates)32 b(to)f(TR)m(UE.)g(The)f(follo)m(wing)h(t)m(w) m(o)h(functions)e(allo)m(w)i(some)f(NULL)f(detection)i(and)e(handling:) 430 4097 y Fe("a)47 b(null)f(value?")667 b(ISNULL\(x\))430 4209 y("define)45 b(a)j(value)e(for)h(null")190 b(DEFNULL\(x,y\))430 4322 y("declare)45 b(certain)h(value)g(null")h(SETNULL\(x,y\))0 4606 y Fj(ISNULL\(x\))24 b(returns)g(a)g(b)s(o)s(olean)h(v)-5 b(alue)25 b(of)f(TR)m(UE)h(if)f(the)h(argumen)m(t)g(x)f(is)g(NULL.)h (DEFNULL\(x,y\))h("de\014nes")0 4719 y(a)31 b(v)-5 b(alue)31 b(to)g(b)s(e)e(substituted)h(for)g(NULL)g(v)-5 b(alues;)31 b(it)g(returns)e(the)i(v)-5 b(alue)31 b(of)f(x)h(if)f(x)g(is)h(not)f (NULL,)h(otherwise)f(it)0 4832 y(returns)d(the)i(v)-5 b(alue)28 b(of)h(y)-8 b(.)40 b(SETNULL\(x,y\))28 b(allo)m(ws)i(NULL)e (v)-5 b(alues)29 b(to)g(b)s(e)f(inserted)g(in)m(to)h(a)g(v)-5 b(ariable;)30 b(if)e(x==y)-8 b(,)0 4945 y(a)34 b(NULL)g(v)-5 b(alue)35 b(is)f(returned;)g(otherwise)h(y)f(is)f(returned)g(\(x)h(and) g(y)g(m)m(ust)f(b)s(e)h(n)m(umerical,)h(and)f(x)f(m)m(ust)h(b)s(e)g(a)0 5058 y(scalar\).)0 5376 y Fd(10.11.2)113 b(Bit)36 b(Masks)0 5601 y Fj(Bit)g(masks)f(can)h(b)s(e)f(used)f(to)i(select)h(out)e(ro)m (ws)h(from)e(bit)i(columns)f(\(TF)m(ORMn)g(=)g(#X\))h(in)f(FITS)f (\014les.)55 b(T)-8 b(o)0 5714 y(represen)m(t)30 b(the)h(mask,)g (binary)-8 b(,)30 b(o)s(ctal,)i(and)e(hex)g(formats)g(are)h(allo)m(w)m (ed:)p eop end %%Page: 149 157 TeXDict begin 149 156 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(149)811 555 y Fe(binary:)142 b(b0110xx1010000101xxxx00)o(01)811 668 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))811 781 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))0 1052 y Fj(In)22 b(all)i(the)f(represen)m(tations,)j(an)c(x)h(or)g(X)g (is)g(allo)m(w)m(ed)i(in)d(the)h(mask)g(as)g(a)h(wild)e(card.)38 b(Note)25 b(that)e(the)g(x)g(represen)m(ts)0 1165 y(a)k(di\013eren)m(t) h(n)m(um)m(b)s(er)e(of)h(wild)f(card)h(bits)g(in)g(eac)m(h)h(represen)m (tation.)41 b(All)27 b(represen)m(tations)h(are)g(case)g(insensitiv)m (e.)0 1278 y(Although)41 b(bitmasks)g(ma)m(y)g(b)s(e)f(of)h(arbitrary)f (length)h(and)f(con)m(tain)i(a)g(wildcard,)h(they)e(ma)m(y)g(only)g(b)s (e)f(used)0 1390 y(in)c(logical)k(expressions,)e(unlik)m(e)f(in)m (teger)h(constan)m(ts)g(\(see)f(ab)s(o)m(v)m(e\))i(whic)m(h)d(ma)m(y)h (b)s(e)f(used)g(in)h(an)m(y)g(arithmetic)0 1503 y(expression.)0 1664 y(T)-8 b(o)28 b(construct)g(the)g(b)s(o)s(olean)f(expression)h (using)f(the)h(mask)f(as)h(the)g(b)s(o)s(olean)f(equal)h(op)s(erator)g (describ)s(ed)f(ab)s(o)m(v)m(e)0 1776 y(on)34 b(a)h(bit)g(table)h (column.)53 b(F)-8 b(or)35 b(example,)i(if)d(y)m(ou)h(had)f(a)h(7)g (bit)g(column)f(named)g(\015ags)h(in)f(a)h(FITS)f(table)i(and)0 1889 y(w)m(an)m(ted)31 b(all)g(ro)m(ws)g(ha)m(ving)g(the)f(bit)h (pattern)f(0010011,)k(the)c(selection)j(expression)d(w)m(ould)g(b)s(e:) 1336 2160 y Fe(flags)47 b(==)g(b0010011)191 2273 y(or)1336 2386 y(flags)g(.eq.)f(b10011)0 2657 y Fj(It)35 b(is)g(also)h(p)s (ossible)e(to)i(test)g(if)f(a)g(range)g(of)g(bits)g(is)g(less)g(than,)h (less)f(than)g(equal,)i(greater)f(than)e(and)h(greater)0 2770 y(than)30 b(equal)h(to)g(a)g(particular)g(b)s(o)s(olean)f(v)-5 b(alue:)1336 3040 y Fe(flags)47 b(<=)g(bxxx010xx)1336 3153 y(flags)g(.gt.)f(bxxx100xx)1336 3266 y(flags)h(.le.)f(b1xxxxxxx)0 3537 y Fj(Notice)32 b(the)f(use)f(of)h(the)f(x)g(bit)h(v)-5 b(alue)31 b(to)g(limit)g(the)f(range)h(of)g(bits)f(b)s(eing)g (compared.)0 3697 y(It)i(is)h(not)f(necessary)h(to)g(sp)s(ecify)f(the)h (leading)g(\(most)g(signi\014can)m(t\))h(zero)f(\(0\))g(bits)f(in)g (the)h(mask,)g(as)g(sho)m(wn)e(in)0 3810 y(the)g(second)f(expression)g (ab)s(o)m(v)m(e.)0 3970 y(Bit)44 b(wise)f(AND,)h(OR)e(and)g(NOT)h(op)s (erations)g(are)g(also)h(p)s(ossible)e(on)h(t)m(w)m(o)h(or)f(more)g (bit)g(\014elds)f(using)h(the)0 4083 y('&'\(AND\),)35 b(')p Fc(j)p Fj('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))34 b(op)s(erators.)51 b(All)34 b(of)f(these)h(op)s(erators)g(result)f(in)h (a)g(bit)f(\014eld)g(whic)m(h)0 4196 y(can)e(then)f(b)s(e)f(used)h (with)g(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 b(example:)1241 4467 y Fe(\(!flags\))45 b(==)j(b1101100)1241 4579 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)0 4850 y Fj(Bit)35 b(\014elds)f(can)g(b)s(e)f(app)s(ended)g(as)h(w)m(ell)h (using)f(the)g('+')g(op)s(erator.)53 b(Strings)33 b(can)i(b)s(e)e (concatenated)j(this)e(w)m(a)m(y)-8 b(,)0 4963 y(to)s(o.)0 5267 y Fd(10.11.3)113 b(V)-9 b(ector)36 b(Columns)0 5488 y Fj(V)-8 b(ector)37 b(columns)e(can)h(also)g(b)s(e)f(used)f(in)h (building)g(the)g(expression.)56 b(No)36 b(sp)s(ecial)g(syn)m(tax)f(is) h(required)e(if)i(one)0 5601 y(w)m(an)m(ts)46 b(to)f(op)s(erate)h(on)f (all)h(elemen)m(ts)g(of)f(the)h(v)m(ector.)86 b(Simply)44 b(use)h(the)g(column)g(name)g(as)g(for)g(a)g(scalar)0 5714 y(column.)d(V)-8 b(ector)32 b(columns)f(can)g(b)s(e)f(freely)h(in) m(termixed)h(with)e(scalar)i(columns)e(or)h(constan)m(ts)h(in)f (virtually)g(all)p eop end %%Page: 150 158 TeXDict begin 150 157 bop 0 299 a Fj(150)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(expressions.)40 b(The)29 b(result)g(will)g(b)s(e)g(of)g(the)g (same)h(dimension)e(as)i(the)f(v)m(ector.)42 b(Tw)m(o)29 b(v)m(ectors)i(in)e(an)g(expression,)0 668 y(though,)h(need)g(to)i(ha)m (v)m(e)f(the)g(same)g(n)m(um)m(b)s(er)e(of)h(elemen)m(ts)i(and)e(ha)m (v)m(e)h(the)g(same)g(dimensions.)0 828 y(Arithmetic)24 b(and)e(logical)k(op)s(erations)d(are)h(all)g(p)s(erformed)d(on)i(an)g (elemen)m(t)h(b)m(y)f(elemen)m(t)i(basis.)38 b(Comparing)23 b(t)m(w)m(o)0 941 y(v)m(ector)32 b(columns,)e(eg)h("COL1)f(==)g(COL2",) g(th)m(us)g(results)g(in)g(another)g(v)m(ector)i(of)e(b)s(o)s(olean)h (v)-5 b(alues)30 b(indicating)0 1054 y(whic)m(h)g(elemen)m(ts)i(of)e (the)h(t)m(w)m(o)h(v)m(ectors)f(are)g(equal.)0 1214 y(Sev)m(eral)e (functions)e(are)i(a)m(v)-5 b(ailable)30 b(that)e(op)s(erate)h(on)f(a)g (v)m(ector.)41 b(All)29 b(but)e(the)h(last)h(t)m(w)m(o)g(return)e(a)h (scalar)h(result:)191 1457 y Fe("minimum")284 b(MIN\(V\))475 b("maximum")714 b(MAX\(V\))191 1570 y("average")284 b(AVERAGE\(V\))f ("median")762 b(MEDIAN\(V\))191 1683 y("summation")188 b(SUM\(V\))475 b("standard)46 b(deviation")188 b(STDDEV\(V\))191 1796 y("#)47 b(of)g(values")94 b(NELEM\(V\))379 b("#)48 b(of)f(non-null)e(values")94 b(NVALID\(V\))191 1909 y("#)47 b(axes")333 b(NAXIS\(V\))379 b("axis)47 b(dimension")379 b(NAXES\(V,n\))191 2021 y("axis)46 b(pos'n")142 b(AXISELEM\(V,n\))d ("vector)46 b(element)g(pos'n")94 b(ELEMENTNUM\(V\))1670 2134 y("promote)46 b(to)h(array")285 b(ARRAY\(X,d\))0 2377 y Fj(where)40 b(V)h(represen)m(ts)g(the)g(name)g(of)h(a)f(v)m (ector)h(column)f(or)g(a)h(man)m(ually)f(constructed)g(v)m(ector)i (using)d(curly)0 2490 y(brac)m(k)m(ets)27 b(as)f(describ)s(ed)e(b)s (elo)m(w.)39 b(The)25 b(\014rst)g(6)h(of)g(these)g(functions)f(ignore)h (an)m(y)g(n)m(ull)f(v)-5 b(alues)26 b(in)f(the)h(v)m(ector)h(when)0 2603 y(computing)k(the)f(result.)41 b(The)30 b(STDDEV\(\))h(function)g (computes)f(the)h(sample)g(standard)e(deviation,)j(i.e.)42 b(it)31 b(is)0 2716 y(prop)s(ortional)f(to)h(1/SQR)-8 b(T\(N-1\))32 b(instead)f(of)g(1/SQR)-8 b(T\(N\),)31 b(where)f(N)h(is)f(NV)-10 b(ALID\(V\).)0 2876 y(The)31 b(SUM)h(function)f(literally)j(sums)d(all)h(the)g(elemen)m(ts)h(in)f (x,)g(returning)f(a)h(scalar)h(v)-5 b(alue.)45 b(If)31 b(V)h(is)g(a)g(b)s(o)s(olean)0 2989 y(v)m(ector,)40 b(SUM)c(returns)f (the)h(n)m(um)m(b)s(er)f(of)i(TR)m(UE)f(elemen)m(ts.)60 b(The)36 b(NELEM)g(function)g(returns)f(the)h(n)m(um)m(b)s(er)0 3102 y(of)h(elemen)m(ts)g(in)g(v)m(ector)h(V)e(whereas)h(NV)-10 b(ALID)36 b(return)g(the)h(n)m(um)m(b)s(er)e(of)h(non-n)m(ull)g(elemen) m(ts)i(in)e(the)h(v)m(ector.)0 3215 y(\(NELEM)28 b(also)h(op)s(erates)f (on)g(bit)f(and)g(string)h(columns,)g(returning)f(their)h(column)f (widths.\))40 b(As)27 b(an)h(example,)0 3328 y(to)42 b(test)g(whether)f(all)h(elemen)m(ts)h(of)f(t)m(w)m(o)g(v)m(ectors)h (satisfy)f(a)g(giv)m(en)g(logical)i(comparison,)g(one)e(can)g(use)f (the)0 3440 y(expression)668 3683 y Fe(SUM\()47 b(COL1)f(>)i(COL2)f(\)) g(==)g(NELEM\()f(COL1)h(\))0 3926 y Fj(whic)m(h)32 b(will)g(return)f (TR)m(UE)h(if)g(all)h(elemen)m(ts)g(of)f(COL1)g(are)g(greater)h(than)f (their)g(corresp)s(onding)f(elemen)m(ts)i(in)0 4039 y(COL2.)0 4199 y(The)25 b(NAXIS\(V\))i(function)e(returns)g(the)h(n)m(um)m(b)s (er)f(of)h(axes)g(of)g(the)g(v)m(ector,)j(for)c(example)i(a)f(2D)h (arra)m(y)f(w)m(ould)g(b)s(e)0 4312 y(NAXIS\(V\))34 b(==)f(2.)50 b(The)32 b(NAXES\(V,n\))i(function)f(returns)f(the)i(dimension)e(of)i (axis)g(n,)f(for)g(example)h(a)g(4x2)0 4425 y(arra)m(y)h(w)m(ould)f(ha) m(v)m(e)h(NAXES\(V,1\))h(==)d(4.)53 b(The)33 b(ELEMENTNUM\(V\))j(and)d (AXISELEM\(V,n\))h(functions)0 4538 y(return)42 b(v)m(ectors)j(of)f (the)g(same)g(size)g(as)g(the)f(input)g(v)m(ector)i(V.)f (ELEMENTNUM\(V\))g(returns)f(the)g(v)m(ector)0 4650 y(elemen)m(t)28 b(p)s(osition)e(for)g(eac)m(h)i(elemen)m(t)f(in)f(the)h(v)m(ector,)i (starting)e(from)e(1)i(in)f(eac)m(h)i(ro)m(w.)39 b(The)26 b(AXISELEM\(V,n\))0 4763 y(function)k(is)g(similar)h(but)f(returns)f (the)i(elemen)m(t)g(p)s(osition)g(of)f(axis)h(n)f(only)-8 b(.)0 4924 y(The)33 b(ARRA)-8 b(Y\(X,d\))35 b(function)e(promotes)h (scalar)g(v)-5 b(alue)34 b(X)f(to)h(a)g(v)m(ector)h(\(or)f(arra)m(y\))g (table)h(elemen)m(t.)51 b(X)33 b(ma)m(y)0 5036 y(b)s(e)h(an)m(y)h (scalar-v)-5 b(alued)36 b(item,)g(including)f(a)g(column,)g(an)g (expression,)g(or)g(a)g(constan)m(t)h(v)-5 b(alue.)54 b(The)34 b(resulting)0 5149 y(v)m(ector)39 b(or)e(arra)m(y)h(will)g(ha) m(v)m(e)g(the)g(same)g(scalar)g(v)-5 b(alue)38 b(replicated)g(in)m(to)h (eac)m(h)f(elemen)m(t)h(p)s(osition.)62 b(This)36 b(ma)m(y)0 5262 y(b)s(e)e(a)i(useful)e(w)m(a)m(y)i(to)g(construct)g(large)g(arra)m (ys)f(without)g(using)g(the)g(cum)m(b)s(ersome)g Fc(f)p Fj(v)m(ector)p Fc(g)i Fj(notation.)56 b(The)0 5375 y(dimensions)26 b(of)h(the)h(new)e(arra)m(y)h(are)h(giv)m(en)g(b)m(y)f(the)g(second)g (argumen)m(t,)h(d.)39 b(d)27 b(can)g(either)g(b)s(e)g(a)g(single)h (constan)m(t)0 5488 y(in)m(teger)g(v)-5 b(alue,)28 b(or)f(a)f(v)m (ector)j(of)d(up)g(to)h(\014v)m(e)g(dimensions)f(of)g(the)h(form)f Fc(f)p Fj(Nx,Ny)-8 b(,...)p Fc(g)p Fj(.)43 b(Th)m(us,)26 b(ARRA)-8 b(Y\(TIME,4\))0 5601 y(w)m(ould)28 b(promote)g(TIME)g(to)h(b) s(e)e(a)i(4-v)m(ector,)i(and)d(ARRA)-8 b(Y\(0,)30 b Fc(f)p Fj(2,3,1)p Fc(g)p Fj(\))h(w)m(ould)d(construct)h(an)f(arra)m(y)g(of)g (all)h(0's)0 5714 y(with)h(dimensions)g(2)20 b Fc(\002)g Fj(3)h Fc(\002)f Fj(1.)p eop end %%Page: 151 159 TeXDict begin 151 158 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(151)0 555 y(A)36 b(second)g(form)f(of)h(ARRA)-8 b(Y\(X,d\))37 b(can)f(b)s(e)f(used)g(where)g(X)h(is)g(a)g(v)m(ector)h(or)f(arra)m(y) -8 b(,)38 b(and)e(the)f(dimensions)g(d)0 668 y(merely)c(c)m(hange)h (the)e(dimensions)g(of)h(X)f(without)h(c)m(hanging)g(the)g(total)i(n)m (um)m(b)s(er)c(of)h(v)m(ector)j(elemen)m(ts.)42 b(This)30 b(is)0 781 y(a)g(w)m(a)m(y)g(to)g(re-dimension)f(an)h(existing)g(arra)m (y)-8 b(.)41 b(F)-8 b(or)31 b(example,)f(ARRA)-8 b(Y\()p Fc(f)p Fj(1,2,3,4)p Fc(g)p Fj(,2,2\))36 b(w)m(ould)29 b(transform)g(the)0 894 y(4-v)m(ector)k(in)m(to)e(a)g(2)20 b Fc(\002)g Fj(2)31 b(arra)m(y)-8 b(.)0 1054 y(T)g(o)32 b(sp)s(ecify)f(a)i(single)f(elemen)m(t)h(of)f(a)g(v)m(ector,)i(giv)m(e) f(the)f(column)f(name)h(follo)m(w)m(ed)h(b)m(y)f(a)g(comma-separated)h (list)0 1167 y(of)c(co)s(ordinates)g(enclosed)h(in)e(square)h(brac)m(k) m(ets.)41 b(F)-8 b(or)30 b(example,)g(if)e(a)h(v)m(ector)i(column)d (named)h(PHAS)f(exists)h(in)0 1280 y(the)e(table)g(as)g(a)g(one)g (dimensional,)h(256)g(comp)s(onen)m(t)f(list)g(of)g(n)m(um)m(b)s(ers)e (from)h(whic)m(h)h(y)m(ou)g(w)m(an)m(ted)g(to)g(select)i(the)0 1393 y(57th)j(comp)s(onen)m(t)g(for)f(use)g(in)g(the)h(expression,)f (then)h(PHAS[57])g(w)m(ould)f(do)h(the)f(tric)m(k.)45 b(Higher)32 b(dimensional)0 1506 y(arra)m(ys)41 b(of)h(data)f(ma)m(y)h (app)s(ear)f(in)f(a)i(column.)73 b(But)41 b(in)g(order)f(to)i(in)m (terpret)f(them,)j(the)e(TDIMn)e(k)m(eyw)m(ord)0 1619 y(m)m(ust)34 b(app)s(ear)g(in)g(the)g(header.)52 b(Assuming)34 b(that)h(a)f(\(4,4,4,4\))k(arra)m(y)c(is)h(pac)m(k)m(ed)g(in)m(to)g (eac)m(h)h(ro)m(w)e(of)g(a)h(column)0 1732 y(named)26 b(ARRA)-8 b(Y4D,)28 b(the)f(\(1,2,3,4\))i(comp)s(onen)m(t)e(elemen)m(t) g(of)g(eac)m(h)g(ro)m(w)g(is)f(accessed)i(b)m(y)e(ARRA)-8 b(Y4D[1,2,3,4].)0 1844 y(Arra)m(ys)33 b(up)e(to)j(dimension)e(5)h(are)f (curren)m(tly)h(supp)s(orted.)46 b(Eac)m(h)33 b(v)m(ector)h(index)e (can)h(itself)g(b)s(e)f(an)h(expression,)0 1957 y(although)39 b(it)g(m)m(ust)g(ev)-5 b(aluate)40 b(to)f(an)g(in)m(teger)h(v)-5 b(alue)39 b(within)f(the)h(b)s(ounds)d(of)j(the)g(v)m(ector.)67 b(V)-8 b(ector)40 b(columns)0 2070 y(whic)m(h)31 b(con)m(tain)h(spaces) g(or)f(arithmetic)h(op)s(erators)g(m)m(ust)f(ha)m(v)m(e)h(their)f (names)g(enclosed)h(in)f("$")h(c)m(haracters)h(as)0 2183 y(with)d($ARRA)-8 b(Y-4D$[1,2,3,4].)0 2343 y(A)45 b(more)f(C-lik)m(e)i (syn)m(tax)g(for)e(sp)s(ecifying)g(v)m(ector)j(indices)d(is)h(also)h(a) m(v)-5 b(ailable.)85 b(The)45 b(elemen)m(t)h(used)d(in)i(the)0 2456 y(preceding)28 b(example)h(alternativ)m(ely)i(could)d(b)s(e)g(sp)s (eci\014ed)g(with)f(the)i(syn)m(tax)g(ARRA)-8 b(Y4D[4][3][2][1].)45 b(Note)30 b(the)0 2569 y(rev)m(erse)40 b(order)f(of)h(indices)f(\(as)h (in)f(C\),)h(as)f(w)m(ell)i(as)e(the)h(fact)g(that)g(the)g(v)-5 b(alues)40 b(are)f(still)i(ones-based)e(\(as)h(in)0 2682 y(F)-8 b(ortran)39 b({)g(adopted)g(to)g(a)m(v)m(oid)h(am)m(biguit)m(y)g (for)f(1D)g(v)m(ectors\).)67 b(With)39 b(this)g(syn)m(tax,)i(one)e(do)s (es)f(not)h(need)f(to)0 2795 y(sp)s(ecify)30 b(all)h(of)g(the)f (indices.)41 b(T)-8 b(o)31 b(extract)h(a)f(3D)g(slice)g(of)g(this)f(4D) h(arra)m(y)-8 b(,)32 b(use)e(ARRA)-8 b(Y4D[4].)0 2955 y(V)g(ariable-length)33 b(v)m(ector)f(columns)e(are)g(not)h(supp)s (orted.)0 3115 y(V)-8 b(ectors)24 b(can)e(b)s(e)f(man)m(ually)h (constructed)h(within)e(the)h(expression)g(using)f(a)h(comma-separated) i(list)f(of)f(elemen)m(ts)0 3228 y(surrounded)35 b(b)m(y)j(curly)g (braces)h(\(')p Fc(fg)p Fj('\).)66 b(F)-8 b(or)38 b(example,)j(')p Fc(f)p Fj(1,3,6,1)p Fc(g)p Fj(')h(is)d(a)f(4-elemen)m(t)i(v)m(ector)g (con)m(taining)g(the)0 3341 y(v)-5 b(alues)26 b(1,)h(3,)g(6,)g(and)e (1.)40 b(The)25 b(v)m(ector)i(can)f(con)m(tain)h(only)f(b)s(o)s(olean,) g(in)m(teger,)j(and)c(real)h(v)-5 b(alues)26 b(\(or)g(expressions\).)0 3454 y(The)c(elemen)m(ts)i(will)f(b)s(e)f(promoted)h(to)g(the)g (highest)g(data)g(t)m(yp)s(e)g(presen)m(t.)38 b(An)m(y)22 b(elemen)m(ts)i(whic)m(h)f(are)g(themselv)m(es)0 3567 y(v)m(ectors,)40 b(will)d(b)s(e)f(expanded)g(out)h(with)g(eac)m(h)g(of) g(its)g(elemen)m(ts)i(b)s(ecoming)d(an)h(elemen)m(t)h(in)f(the)g (constructed)0 3680 y(v)m(ector.)0 4058 y Fd(10.11.4)113 b(Ro)m(w)36 b(Access)0 4295 y Fj(T)-8 b(o)32 b(access)g(a)g(table)g(en) m(try)g(in)f(a)h(ro)m(w)f(other)h(than)f(the)g(curren)m(t)g(one,)h (follo)m(w)h(the)e(column's)h(name)f(with)g(a)h(ro)m(w)0 4408 y(o\013set)41 b(within)f(curly)g(braces.)71 b(F)-8 b(or)41 b(example,)j Fe(PHA{-3})39 b Fj(will)h(ev)-5 b(aluate)42 b(to)g(the)e(v)-5 b(alue)41 b(of)g(column)f(PHA,)h(3)0 4521 y(ro)m(ws)28 b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s (eing)g(pro)s(cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g (absolute)h(ro)m(w)f(n)m(um)m(b)s(er,)g(only)h(a)0 4633 y(relativ)m(e)j(o\013set.)42 b(Ro)m(ws)31 b(that)g(fall)g(outside)g (the)f(table)h(will)g(b)s(e)f(treated)h(as)g(unde\014ned,)d(or)j (NULLs.)0 4794 y(Using)22 b(the)g(same)g(column)g(name)g(on)g(the)g (left)g(and)f(righ)m(t)i(side)e(of)h(the)h(equals)f(sign)g(while)f (using)h(the)g Fe(COLUMN{-N})0 4907 y Fj(notation)32 b(will)e(not)h(pro)s(duce)e(the)i(desired)f(result.)40 b(F)-8 b(or)31 b(example,)668 5197 y Fe(COUNT)47 b(=)g(COUNT{-1})e(+)j (1;)142 b(#)48 b(BAD)f(-)g(do)g(not)g(use)0 5488 y Fj(will)30 b(not)g(pro)s(duce)f(an)h(increasing)h(coun)m(ter.)41 b(Suc)m(h)29 b(recursiv)m(e)i(calculations)h(are)e(often)g(not)h(p)s (ossible)e(with)h(the)0 5601 y(calculator)41 b(syn)m(tax.)65 b(Ho)m(w)m(ev)m(er,)43 b(for)38 b(cases)i(where)e(the)h(user)e(wishes)h (a)h(ro)m(w)g(coun)m(ter,)i(the)e(sp)s(ecial)g(v)-5 b(ariable)0 5714 y Fe(#ROW)29 b Fj(can)i(b)s(e)f(utilized.)p eop end %%Page: 152 160 TeXDict begin 152 159 bop 0 299 a Fj(152)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fd(10.11.5)113 b(Go)s(o)s(d)38 b(Time)g(In)m(terv)-6 b(al)37 b(Filtering)h(and)g(Calculation)0 776 y Fj(There)27 b(are)h(t)m(w)m(o)g(functions)f(for)g(\014ltering)h(and)f(calculating)i (based)e(on)g(Go)s(o)s(d)h(Time)f(In)m(terv)-5 b(als,)29 b(or)e(GTIs.)39 b(GTIs)0 889 y(are)c(commonly)g(used)f(to)h(express)f (fragmen)m(ted)h(time)g(ranges)g(that)g(are)g(not)g(easy)g(to)g (express)f(with)g(a)h(single)0 1002 y(start)j(and)f(stop)h(time.)63 b(The)37 b(time)h(in)m(terv)-5 b(als)39 b(are)f(de\014ned)e(in)i(a)g (FITS)f(table)h(extension)g(whic)m(h)g(con)m(tains)h(2)0 1115 y(columns)30 b(giving)h(the)g(start)g(and)f(stop)g(time)h(of)g (eac)m(h)g(go)s(o)s(d)f(in)m(terv)-5 b(al.)0 1275 y(A)32 b(common)g(\014ltering)f(metho)s(d)h(in)m(v)m(olv)m(es)h(selecting)h (ro)m(ws)d(whic)m(h)h(ha)m(v)m(e)g(a)g(time)h(v)-5 b(alue)32 b(whic)m(h)f(lies)i(within)e(an)m(y)0 1388 y(GTI.)36 b(The)g(gti\014lter\(\))i(\014ltering)e(op)s(eration)h(accepts)g(only)f (those)h(ro)m(ws)f(of)g(the)h(input)e(table)i(whic)m(h)f(ha)m(v)m(e)h (an)0 1501 y(asso)s(ciated)g(time)f(whic)m(h)g(falls)g(within)f(one)g (of)h(the)g(time)g(in)m(terv)-5 b(als)37 b(de\014ned)d(in)h(a)h (separate)h(GTI)e(extension.)0 1614 y(gti\014lter\(a,b,c,d\))43 b(ev)-5 b(aluates)41 b(eac)m(h)g(ro)m(w)g(of)f(the)g(input)f(table)i (and)f(returns)f(TR)m(UE)h(or)g(F)-10 b(ALSE)39 b(dep)s(ending)0 1726 y(whether)30 b(the)g(ro)m(w)h(is)f(inside)g(or)h(outside)f(the)h (go)s(o)s(d)f(time)h(in)m(terv)-5 b(al.)42 b(The)30 b(syn)m(tax)h(is) 286 1994 y Fe(gtifilter\()45 b([)j("gtifile")d([,)i(expr)g([,)g ("STARTCOL",)e("STOPCOL")g(])j(])f(])g(\))191 2107 y(or)286 2220 y(gtifilter\()e([)j('gtifile')d([,)i(expr)g([,)g('STARTCOL',)e ('STOPCOL')g(])j(])f(])g(\))0 2487 y Fj(where)20 b(eac)m(h)h("[]")h (demarks)e(optional)h(parameters.)38 b(Note)21 b(that)g(the)g(quotes)f (around)g(the)g(gti\014le)i(and)d(ST)-8 b(AR)g(T/STOP)0 2600 y(column)33 b(are)h(required.)50 b(Either)34 b(single)g(or)g (double)f(quotes)h(ma)m(y)g(b)s(e)f(used.)50 b(In)33 b(cases)h(where)g(this)f(expression)0 2713 y(is)d(en)m(tered)g(on)g (the)g(Unix)g(command)g(line,)g(enclose)h(the)f(en)m(tire)h(expression) f(in)f(double)h(quotes,)g(and)g(then)f(use)0 2826 y(single)c(quotes)g (within)e(the)i(expression)f(to)h(enclose)g(the)g('gti\014le')h(and)d (other)i(terms.)38 b(It)25 b(is)f(also)h(usually)f(p)s(ossible)0 2939 y(to)38 b(do)e(the)h(rev)m(erse,)j(and)c(enclose)i(the)f(whole)g (expression)g(in)f(single)i(quotes)f(and)f(then)h(use)f(double)g (quotes)0 3052 y(within)d(the)g(expression.)50 b(The)33 b(gti\014le,)i(if)f(sp)s(eci\014ed,)f(can)h(b)s(e)f(blank)g(\(""\))i (whic)m(h)e(will)g(mean)h(to)g(use)f(the)h(\014rst)0 3165 y(extension)g(with)g(the)f(name)h("*GTI*")h(in)f(the)f(curren)m(t) h(\014le,)h(a)f(plain)f(extension)h(sp)s(eci\014er)f(\(eg,)j("+2",)g ("[2]",)0 3278 y(or)30 b("[STDGTI]"\))i(whic)m(h)e(will)h(b)s(e)f(used) f(to)j(select)g(an)e(extension)h(in)f(the)h(curren)m(t)f(\014le,)h(or)f (a)h(regular)g(\014lename)0 3391 y(with)f(or)h(without)f(an)h (extension)g(sp)s(eci\014er)f(whic)m(h)g(in)g(the)h(latter)h(case)f (will)g(mean)f(to)i(use)e(the)h(\014rst)e(extension)0 3504 y(with)37 b(an)g(extension)g(name)h("*GTI*".)62 b(Expr)36 b(can)h(b)s(e)g(an)m(y)g(arithmetic)i(expression,)f (including)f(simply)g(the)0 3616 y(time)f(column)g(name.)57 b(A)36 b(v)m(ector)h(time)g(expression)e(will)h(pro)s(duce)f(a)h(v)m (ector)h(b)s(o)s(olean)f(result.)57 b(ST)-8 b(AR)g(TCOL)0 3729 y(and)27 b(STOPCOL)f(are)i(the)g(names)g(of)g(the)g(ST)-8 b(AR)g(T/STOP)26 b(columns)i(in)f(the)h(GTI)g(extension.)41 b(If)27 b(one)h(of)g(them)0 3842 y(is)i(sp)s(eci\014ed,)g(they)h(b)s (oth)f(m)m(ust)g(b)s(e.)0 4002 y(In)21 b(its)h(simplest)g(form,)i(no)d (parameters)h(need)g(to)h(b)s(e)e(pro)m(vided)g({)h(default)g(v)-5 b(alues)22 b(will)h(b)s(e)e(used.)37 b(The)21 b(expression)0 4115 y("gti\014lter\(\)")33 b(is)e(equiv)-5 b(alen)m(t)31 b(to)334 4383 y Fe(gtifilter\()45 b("",)i(TIME,)f("*START*",)f ("*STOP*")h(\))0 4650 y Fj(This)31 b(will)g(searc)m(h)h(the)g(curren)m (t)f(\014le)g(for)g(a)h(GTI)f(extension,)h(\014lter)g(the)f(TIME)g (column)g(in)g(the)h(curren)m(t)f(table,)0 4763 y(using)j(ST)-8 b(AR)g(T/STOP)34 b(times)i(tak)m(en)f(from)g(columns)f(in)h(the)g(GTI)g (extension)g(with)g(names)f(con)m(taining)j(the)0 4876 y(strings)32 b("ST)-8 b(AR)g(T")33 b(and)e("STOP".)46 b(The)32 b(wildcards)f(\('*'\))j(allo)m(w)g(sligh)m(t)f(v)-5 b(ariations)33 b(in)f(naming)g(con)m(v)m(en)m(tions)0 4989 y(suc)m(h)38 b(as)g("TST)-8 b(AR)g(T")39 b(or)f("ST)-8 b(AR)g(TTIME".)65 b(The)37 b(same)i(default)g(v)-5 b(alues)38 b(apply)g(for)g(unsp)s(eci\014ed)f(parame-)0 5102 y(ters)f(when)f(the)h (\014rst)f(one)i(or)f(t)m(w)m(o)h(parameters)f(are)h(sp)s(eci\014ed.)56 b(The)36 b(function)f(automatically)k(searc)m(hes)e(for)0 5215 y(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)f(in)g(the)h(curren)m(t)f(and)g (GTI)g(extensions,)i(applying)f(a)f(relativ)m(e)j(time)e(o\013set,)i (if)0 5328 y(necessary)-8 b(.)0 5488 y(The)38 b(related)h(function,)g (gti\014nd\(a,b,c,d\),)i(is)e(similar)f(to)h(gti\014lter\(\))h(but)d (instead)h(of)h(returning)e(true/false,)0 5601 y(gti\014nd\(\))f (returns)e(the)i(GTI)f(n)m(um)m(b)s(er)f(that)i(brac)m(k)m(ets)h(the)f (requested)f(time)h(sample.)57 b(gti\014nd\(\))35 b(returns)g(the)0 5714 y(ro)m(w)30 b(n)m(um)m(b)s(er)e(in)i(the)g(GTI)g(table)g(that)h (matc)m(hes)g(the)f(time)g(sample,)h(or)f(-1)g(if)g(the)g(time)h (sample)f(is)f(not)h(within)p eop end %%Page: 153 161 TeXDict begin 153 160 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(153)0 555 y(an)m(y)30 b(GTI.)f(gti\014nd\(\))g(is)g(particularly)h(useful)f (when)f(en)m(tries)i(in)f(a)g(table)i(m)m(ust)e(b)s(e)f(categorized)k (b)m(y)d(whic)m(h)g(GTI)0 668 y(the)36 b(fall)h(within.)56 b(F)-8 b(or)37 b(example,)h(if)e(ev)m(en)m(ts)h(in)f(an)f(ev)m(en)m(t)j (list)e(m)m(ust)g(b)s(e)f(separated)i(b)m(y)e(go)s(o)s(d)h(time)h(in)m (terv)-5 b(al.)0 781 y(The)25 b(results)g(of)h(gti\014nd\(\))g(can)f(b) s(e)g(used)g(with)g(histogram)h(binning)e(tec)m(hniques)i(to)h(bin)d (an)i(ev)m(en)m(t)h(list)f(b)m(y)f(whic)m(h)0 894 y(GTI.)286 1188 y Fe(gtifind\()46 b("gtifile")f(,)j(expr)e([,)h("STARTCOL",)e ("STOPCOL")g(])j(\))0 1483 y Fj(The)33 b(requiremen)m(ts)g(for)f(sp)s (ecifying)h(the)h(gti\014le)g(are)f(the)g(same)h(as)f(for)g (gti\014lter\(\))i(as)e(describ)s(ed)f(ab)s(o)m(v)m(e.)50 b(Lik)m(e)0 1595 y(gti\014lter\(\),)31 b(the)e(expr)g(is)g(the)g (time-lik)m(e)i(expression)e(and)f(is)h(optional)h(\(defaulting)g(to)f (TIME\).)h(The)e(start)i(and)0 1708 y(stop)g(columns)h(default)f(to)h (ST)-8 b(AR)g(T)30 b(and)g(STOP)-8 b(.)0 1868 y(The)28 b(function,)h(gtio)m(v)m(erlap\(a,b,c,d,e\),)34 b(computes)28 b(the)h(o)m(v)m(erlap)h(b)s(et)m(w)m(een)f(a)g(user-requested)f(time)i (range)f(and)0 1981 y(the)i(en)m(tries)g(in)f(a)h(GTI.)f(The)g(cases)i (of)e(no)g(o)m(v)m(erlap,)j(partial)e(o)m(v)m(erlap,)h(or)f(o)m(v)m (erlap)h(of)e(man)m(y)h(GTIs)f(within)g(the)0 2094 y(user)37 b(requested)h(range)g(are)g(handled.)61 b(gtio)m(v)m(erlap\(\))41 b(is)d(v)m(ery)g(useful)f(for)h(calculating)h(exp)s(osure)e(times)i (and)0 2207 y(fractional)32 b(exp)s(osures)d(of)i(individual)f(time)h (bins,)e(sa)m(y)i(for)f(a)h(ligh)m(t)h(curv)m(e.)41 b(The)30 b(syn)m(tax)h(of)f(gtio)m(v)m(erlap\(\))k(is)286 2502 y Fe(gtioverlap\()45 b("gtifile")g(,)j(startExpr,)d(stopExpr)g([,)j ("STARTCOL",)c("STOPCOL")i(])h(\))191 2614 y(or)286 2727 y(gtioverlap\()e('gtifile')g(,)j(startExpr,)d(stopExpr)g([,)j ('STARTCOL',)c('STOPCOL')i(])h(\))0 3022 y Fj(The)27 b(requiremen)m(ts)g(for)h(sp)s(ecifying)f(the)h(gti\014le)g(are)g(the)g (same)g(as)f(for)h(gti\014lter\(\))h(as)f(describ)s(ed)e(ab)s(o)m(v)m (e.)41 b(Unlik)m(e)0 3135 y(gti\014lter\(\),)j(the)c(startExpr)f(and)f (stopExpr)h(are)h(not)g(optional.)69 b(startExpr)39 b(pro)m(vides)g(a)h (start)g(of)g(the)g(user)0 3247 y(requested)34 b(time)h(in)m(terv)-5 b(al.)53 b(startExpr)34 b(is)g(t)m(ypically)i(TIME,)e(but)f(can)i(b)s (e)e(an)m(y)h(v)-5 b(alid)35 b(expression.)52 b(Lik)m(ewise,)0 3360 y(stopExpr)39 b(pro)m(vides)i(the)f(stop)h(of)f(the)h(user)f (requested)g(time)h(in)m(terv)-5 b(al,)44 b(and)c(can)h(b)s(e)e(an)i (expression.)70 b(F)-8 b(or)0 3473 y(example,)31 b(for)f(a)h(ligh)m(t)h (curv)m(e)e(with)h(a)f(TIME)g(column)g(and)g(time)h(bin)f(size)h(of)g (1.0)g(seconds,)g(the)f(expression)286 3768 y Fe (gtioverlap\('gtifile',TIME,)o(TIM)o(E+1.)o(0\))0 4062 y Fj(w)m(ould)36 b(calculate)i(the)e(amoun)m(t)g(of)g(o)m(v)m(erlap)h (exp)s(osure)e(time)h(b)s(et)m(w)m(een)h(eac)m(h)f(one)g(second)g(time) h(bin)e(and)g(the)0 4175 y(GTI)e(in)f('gti\014le'.)50 b(In)32 b(this)h(case)h(the)f(time)g(bin)f(is)h(assumed)f(to)i(b)s (egin)e(at)i(the)f(time)g(sp)s(eci\014ed)f(b)m(y)h(TIME)g(and)0 4288 y(end)d(1)h(second)g(later.)43 b(Neither)31 b(startExpr)f(nor)h (stopExpr)e(are)j(required)d(to)j(b)s(e)e(constan)m(t,)i(and)f(a)g (ligh)m(t)h(curv)m(e)0 4401 y(is)h(not)h(required)f(to)h(ha)m(v)m(e)g (a)g(constan)m(t)h(bin)e(size.)50 b(F)-8 b(or)34 b(tables,)i(the)d(o)m (v)m(erlap)i(is)f(calculated)h(for)e(eac)m(h)i(en)m(try)e(in)0 4513 y(the)e(table.)0 4674 y(It)d(is)f(also)i(p)s(ossible)e(to)h (calculate)i(a)e(single)g(o)m(v)m(erlap)h(v)-5 b(alue,)29 b(whic)m(h)e(w)m(ould)h(t)m(ypically)h(b)s(e)e(placed)h(in)f(a)h(k)m (eyw)m(ord.)0 4787 y(F)-8 b(or)42 b(example,)j(a)d(w)m(a)m(y)g(to)g(to) g(compute)g(the)f(total)i(o)m(v)m(erlap)g(exp)s(osure)d(of)i(a)f (\014le)h(whose)f(TIME)g(column)g(is)0 4899 y(b)s(ounded)28 b(b)m(y)i(the)h(k)m(eyw)m(ords)g(TST)-8 b(AR)g(T)29 b(and)h(TSTOP)-8 b(,)30 b(o)m(v)m(erlapping)h(with)f(the)h(sp)s(eci\014ed)f(GTI,)g(w)m (ould)g(b)s(e)286 5194 y Fe(#EXPOSURE)46 b(=)h (gtioverlap\('gtifile',#TST)o(ART)o(,#TS)o(TOP\))0 5488 y Fj(The)26 b Fe(#EXPOSURE)f Fj(syn)m(tax)i(with)g(a)g(leading)h(+)e (ensures)g(that)i(the)f(requested)g(v)-5 b(alues)27 b(are)g(treated)h (as)f(k)m(eyw)m(ords.)0 5601 y(Otherwise,)41 b(a)e(column)g(named)f (EXPOSURE)g(will)h(b)s(e)g(created)g(with)g(the)g(\(constan)m(t\))i (exp)s(osure)d(v)-5 b(alue)39 b(in)0 5714 y(eac)m(h)32 b(en)m(try)-8 b(.)p eop end %%Page: 154 162 TeXDict begin 154 161 bop 0 299 a Fj(154)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fd(10.11.6)113 b(Spatial)38 b(Region)g(Filtering)0 775 y Fj(Another)g(common)g(\014ltering)g(metho)s(d)f(selects)i(ro)m (ws)f(based)g(on)f(whether)h(the)g(spatial)h(p)s(osition)e(asso)s (ciated)0 887 y(with)32 b(eac)m(h)i(ro)m(w)e(is)h(lo)s(cated)h(within)e (a)h(giv)m(en)g(2-dimensional)g(region.)48 b(The)32 b(syn)m(tax)h(for)f (this)h(high-lev)m(el)h(\014lter)0 1000 y(is)334 1262 y Fe(regfilter\()45 b("regfilename")f([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h ("wcs)e(cols")h(])g(])g(\))0 1524 y Fj(where)22 b(eac)m(h)i("[]")g (demarks)e(optional)i(parameters.)38 b(The)22 b(region)h(\014le)g(name) f(is)h(required)f(and)g(m)m(ust)g(b)s(e)g(enclosed)0 1637 y(in)34 b(quotes.)51 b(The)33 b(remaining)h(parameters)h(are)f (optional.)52 b(There)33 b(are)i(2)f(supp)s(orted)e(formats)i(for)f (the)h(region)0 1750 y(\014le:)62 b(ASCI)s(I)39 b(\014le)h(or)h(FITS)f (binary)g(table.)73 b(The)40 b(region)h(\014le)g(con)m(tains)h(a)f (list)g(of)g(one)g(or)g(more)g(geometric)0 1863 y(shap)s(es)30 b(\(circle,)j(ellipse,)g(b)s(o)m(x,)e(etc.\))44 b(whic)m(h)31 b(de\014nes)f(a)i(region)g(on)f(the)g(celestial)j(sphere)c(or)h(an)g (area)h(within)f(a)0 1975 y(particular)36 b(2D)g(image.)57 b(The)35 b(region)h(\014le)f(is)g(t)m(ypically)j(generated)e(using)f (an)g(image)i(displa)m(y)e(program)g(suc)m(h)0 2088 y(as)e(fv/PO)m(W)g (\(distribute)f(b)m(y)h(the)f(HEASAR)m(C\),)h(or)g(ds9)f(\(distributed) g(b)m(y)g(the)h(Smithsonian)f(Astroph)m(ysical)0 2201 y(Observ)-5 b(atory\).)69 b(Users)39 b(should)g(refer)g(to)h(the)g(do)s (cumen)m(tation)h(pro)m(vided)e(with)g(these)h(programs)f(for)h(more)0 2314 y(details)29 b(on)f(the)g(syn)m(tax)h(used)e(in)h(the)h(region)f (\014les.)40 b(The)28 b(FITS)f(region)i(\014le)f(format)h(is)f (de\014ned)f(in)h(a)g(do)s(cumen)m(t)0 2427 y(a)m(v)-5 b(ailable)33 b(from)d(the)g(FITS)g(Supp)s(ort)e(O\016ce)j(at)g(h)m (ttp://\014ts.gsfc.nasa.go)m(v/)k(registry/)c(region.h)m(tml)0 2587 y(In)21 b(its)h(simplest)g(form,)i(\(e.g.,)h (reg\014lter\("region.reg"\))h(\))c(the)g(co)s(ordinates)g(in)g(the)g (default)g('X')h(and)e('Y')h(columns)0 2700 y(will)43 b(b)s(e)g(used)f(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g (or)g(outside)g(the)g(area)h(sp)s(eci\014ed)e(in)h(the)g(region)h (\014le.)0 2813 y(Alternate)32 b(p)s(osition)e(column)g(names,)h(or)f (expressions,)h(ma)m(y)g(b)s(e)e(en)m(tered)i(if)g(needed,)f(as)h(in) 382 3075 y Fe(regfilter\("region.reg",)41 b(XPOS,)47 b(YPOS\))0 3337 y Fj(Region)37 b(\014ltering)f(can)g(b)s(e)f(applied)g (most)h(unam)m(biguously)f(if)h(the)g(p)s(ositions)g(in)f(the)h(region) g(\014le)g(and)f(in)h(the)0 3449 y(table)g(to)g(b)s(e)e(\014ltered)h (are)h(b)s(oth)e(giv)m(e)j(in)e(terms)g(of)g(absolute)h(celestial)i(co) s(ordinate)e(units.)54 b(In)35 b(this)g(case)h(the)0 3562 y(lo)s(cations)26 b(and)d(sizes)i(of)g(the)f(geometric)i(shap)s (es)e(in)g(the)g(region)h(\014le)f(are)h(sp)s(eci\014ed)f(in)g(angular) g(units)g(on)g(the)g(sky)0 3675 y(\(e.g.,)32 b(p)s(ositions)e(giv)m(en) i(in)e(R.A.)g(and)g(Dec.)42 b(and)30 b(sizes)h(in)f(arcseconds)g(or)h (arcmin)m(utes\).)41 b(Similarly)-8 b(,)31 b(eac)m(h)h(ro)m(w)0 3788 y(of)h(the)h(\014ltered)f(table)h(will)f(ha)m(v)m(e)i(a)e (celestial)j(co)s(ordinate)e(asso)s(ciated)g(with)f(it.)50 b(This)32 b(asso)s(ciation)j(is)e(usually)0 3901 y(implemen)m(ted)39 b(using)e(a)i(set)g(of)f(so-called)i('W)-8 b(orld)39 b(Co)s(ordinate)g(System')f(\(or)h(W)m(CS\))f(FITS)g(k)m(eyw)m(ords)g (that)0 4014 y(de\014ne)27 b(the)g(co)s(ordinate)h(transformation)g (that)g(m)m(ust)f(b)s(e)f(applied)h(to)h(the)g(v)-5 b(alues)27 b(in)g(the)h('X')g(and)e('Y')i(columns)0 4127 y(to)j(calculate)i(the)d (co)s(ordinate.)0 4287 y(Alternativ)m(ely)-8 b(,)30 b(one)d(can)g(p)s (erform)e(spatial)j(\014ltering)e(using)g(unitless)h('pixel')g(co)s (ordinates)h(for)e(the)h(regions)g(and)0 4400 y(ro)m(w)33 b(p)s(ositions.)49 b(In)33 b(this)g(case)h(the)f(user)g(m)m(ust)g(b)s (e)f(careful)h(to)h(ensure)f(that)g(the)h(p)s(ositions)f(in)g(the)g(2)g (\014les)h(are)0 4513 y(self-consisten)m(t.)54 b(A)34 b(t)m(ypical)i(problem)d(is)h(that)h(the)f(region)h(\014le)f(ma)m(y)h (b)s(e)e(generated)j(using)d(a)i(binned)d(image,)0 4626 y(but)g(the)h(un)m(binned)e(co)s(ordinates)i(are)g(giv)m(en)h(in)e(the) h(ev)m(en)m(t)i(table.)48 b(The)32 b(R)m(OSA)-8 b(T)33 b(ev)m(en)m(ts)h(\014les,)g(for)e(example,)0 4739 y(ha)m(v)m(e)f(X)f (and)f(Y)g(pixel)h(co)s(ordinates)g(that)h(range)f(from)f(1)h(-)g (15360.)42 b(These)30 b(co)s(ordinates)g(are)g(t)m(ypically)h(binned)0 4852 y(b)m(y)i(a)h(factor)g(of)f(32)h(to)g(pro)s(duce)e(a)i(480x480)i (pixel)d(image.)51 b(If)32 b(one)i(then)f(uses)g(a)g(region)h(\014le)f (generated)h(from)0 4965 y(this)c(image)i(\(in)f(image)g(pixel)g (units\))g(to)g(\014lter)f(the)h(R)m(OSA)-8 b(T)30 b(ev)m(en)m(ts)i (\014le,)f(then)f(the)h(X)g(and)f(Y)g(column)h(v)-5 b(alues)0 5077 y(m)m(ust)30 b(b)s(e)g(con)m(v)m(erted)i(to)f(corresp)s(onding)e (pixel)i(units)f(as)g(in:)382 5339 y Fe(regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))0 5601 y Fj(Note)h(that)f(this)f(binning)f (con)m(v)m(ersion)j(is)e(not)h(necessary)g(if)f(the)h(region)g(\014le)f (is)h(sp)s(eci\014ed)e(using)h(celestial)0 5714 y(co)s(ordinate)h (units)f(instead)g(of)g(pixel)h(units)f(b)s(ecause)g(CFITSIO)e(is)j (then)e(able)i(to)g(directly)g(compare)g(the)p eop end %%Page: 155 163 TeXDict begin 155 162 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(155)0 555 y(celestial)30 b(co)s(ordinate)f(of)e(eac)m(h)i(ro)m(w)f(in)f(the)h (table)g(with)g(the)f(celestial)k(co)s(ordinates)d(in)f(the)h(region)g (\014le)g(without)0 668 y(ha)m(ving)j(to)g(kno)m(w)f(an)m(ything)h(ab)s (out)f(ho)m(w)h(the)f(image)i(ma)m(y)f(ha)m(v)m(e)g(b)s(een)f(binned.)0 828 y(The)f(last)h("w)m(cs)g(cols")h(parameter)f(should)e(rarely)h(b)s (e)g(needed.)40 b(If)29 b(supplied,)f(this)i(string)f(con)m(tains)i (the)e(names)0 941 y(of)37 b(the)g(2)h(columns)f(\(space)h(or)f(comma)g (separated\))h(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)f (k)m(eyw)m(ords.)61 b(If)37 b(not)0 1054 y(supplied,)f(the)g(\014lter)g (will)h(scan)f(the)g(X)g(and)f(Y)h(expressions)g(for)g(column)f(names.) 58 b(If)35 b(only)h(one)h(is)f(found)e(in)0 1167 y(eac)m(h)e (expression,)e(those)h(columns)f(will)h(b)s(e)e(used,)h(otherwise)h(an) f(error)g(will)h(b)s(e)f(returned.)0 1327 y(These)g(region)h(shap)s(es) f(are)g(supp)s(orted)f(\(names)h(are)h(case)h(insensitiv)m(e\):)334 1591 y Fe(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)334 1704 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region) 334 1817 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 b(Rest)e(are)h(interiors)e(with)334 1930 y(Rectangle)236 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e (considered)334 2043 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) i(\))143 b(V)47 b(within)f(the)h(region)334 2156 y(Diamond)332 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))334 2269 y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))334 2382 y(Annulus)332 b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))334 2494 y(Ellipse)332 b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))334 2607 y(Elliptannulus)c(\() k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))334 2720 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))0 2984 y Fj(where)28 b(\(Xc,Yc\))j(is)d(the)h(co)s(ordinate)h(of)e(the)h (shap)s(e's)f(cen)m(ter;)j(\(X#,Y#\))e(are)g(the)g(co)s(ordinates)g(of) g(the)g(shap)s(e's)0 3097 y(edges;)39 b(Rxxx)c(are)g(the)h(shap)s(es')f (v)-5 b(arious)35 b(Radii)h(or)f(semima)5 b(jor/minor)36 b(axes;)i(and)d(Axxx)g(are)h(the)g(angles)g(of)0 3210 y(rotation)d(\(or)e(b)s(ounding)f(angles)i(for)f(Sector\))h(in)f (degrees.)44 b(F)-8 b(or)32 b(rotated)h(shap)s(es,)e(the)g(rotation)i (angle)f(can)g(b)s(e)0 3323 y(left)g(o\013,)h(indicating)f(no)f (rotation.)46 b(Common)31 b(alternate)i(names)e(for)h(the)f(regions)h (can)g(also)h(b)s(e)d(used:)43 b(rotb)s(o)m(x)0 3436 y(=)29 b(b)s(o)m(x;)g(rotrectangle)i(=)e(rectangle;)i(\(rot\)rhom)m (bus)e(=)f(\(rot\)diamond;)j(and)d(pie)h(=)f(sector.)42 b(When)28 b(a)i(shap)s(e's)0 3549 y(name)e(is)g(preceded)f(b)m(y)h(a)g (min)m(us)g(sign,)g('-',)i(the)e(de\014ned)e(region)j(is)f(instead)g (the)g(area)h(*outside*)g(its)f(b)s(oundary)0 3662 y(\(ie,)36 b(the)e(region)h(is)f(in)m(v)m(erted\).)53 b(All)34 b(the)g(shap)s(es)f (within)h(a)g(single)h(region)f(\014le)h(are)f(OR'd)f(together)j(to)e (create)0 3775 y(the)29 b(region,)i(and)d(the)i(order)f(is)g (signi\014can)m(t.)41 b(The)29 b(o)m(v)m(erall)i(w)m(a)m(y)g(of)e(lo)s (oking)h(at)g(region)g(\014les)f(is)g(that)h(if)f(the)h(\014rst)0 3888 y(region)f(is)g(an)g(excluded)g(region)g(then)f(a)i(dumm)m(y)d (included)h(region)i(of)f(the)g(whole)g(detector)h(is)f(inserted)f(in)h (the)0 4000 y(fron)m(t.)40 b(Then)25 b(eac)m(h)j(region)f(sp)s (eci\014cation)h(as)f(it)g(is)g(pro)s(cessed)f(o)m(v)m(errides)h(an)m (y)g(selections)i(inside)d(of)h(that)g(region)0 4113 y(sp)s(eci\014ed)36 b(b)m(y)g(previous)g(regions.)59 b(Another)37 b(w)m(a)m(y)g(of)g(thinking)f(ab)s(out)g(this)g(is)h(that) g(if)f(a)h(previous)f(excluded)0 4226 y(region)31 b(is)f(completely)i (inside)f(of)f(a)h(subsequen)m(t)e(included)h(region)h(the)g(excluded)f (region)h(is)f(ignored.)0 4386 y(The)44 b(p)s(ositional)i(co)s (ordinates)g(ma)m(y)f(b)s(e)g(giv)m(en)h(either)f(in)g(pixel)g(units,)j (decimal)e(degrees)g(or)f(hh:mm:ss.s,)0 4499 y(dd:mm:ss.s)25 b(units.)38 b(The)26 b(shap)s(e)f(sizes)i(ma)m(y)f(b)s(e)g(giv)m(en)h (in)e(pixels,)j(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)40 b(Lo)s(ok)0 4612 y(at)31 b(examples)g(of)f(region)h(\014le)g(pro)s (duced)d(b)m(y)i(fv/PO)m(W)h(or)g(ds9)f(for)g(further)f(details)i(of)g (the)f(region)h(\014le)f(format.)0 4772 y(There)h(are)g(three)h(lo)m (w-lev)m(el)i(functions)d(that)g(are)h(primarily)f(for)g(use)g(with)g (reg\014lter)g(function,)h(but)e(they)i(can)0 4885 y(b)s(e)j(called)i (directly)-8 b(.)59 b(They)35 b(return)g(a)h(b)s(o)s(olean)g(true)g(or) g(false)h(dep)s(ending)d(on)i(whether)f(a)i(t)m(w)m(o)g(dimensional)0 4998 y(p)s(oin)m(t)30 b(is)h(in)f(the)g(region)h(or)g(not.)41 b(The)30 b(p)s(ositional)h(co)s(ordinates)g(m)m(ust)f(b)s(e)g(giv)m(en) h(in)f(pixel)h(units:)191 5262 y Fe("point)46 b(in)h(a)h(circular)d (region")477 5375 y(circle\(xcntr,ycntr,radius)o(,Xco)o(lumn)o(,Yc)o (olum)o(n\))191 5601 y("point)h(in)h(an)g(elliptical)e(region")430 5714 y(ellipse\(xcntr,ycntr,xhl)o(f_w)o(dth,)o(yhlf)o(_wd)o(th,r)o (otat)o(ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))p eop end %%Page: 156 164 TeXDict begin 156 163 bop 0 299 a Fj(156)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 668 y Fe("point)46 b(in)h(a)h(rectangular)c(region")620 781 y(box\(xcntr,ycntr,xfll_wdth,)o(yfll)o(_wd)o(th,r)o(otat)o(ion)o (,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 1007 y(where)334 1120 y(\(xcntr,ycntr\))g(are)j(the)g(\(x,y\))f(position)g(of)h(the)g (center)f(of)h(the)g(region)334 1233 y(\(xhlf_wdth,yhlf_wdth\))42 b(are)47 b(the)g(\(x,y\))f(half)h(widths)f(of)h(the)g(region)334 1346 y(\(xfll_wdth,yfll_wdth\))42 b(are)47 b(the)g(\(x,y\))f(full)h (widths)f(of)h(the)g(region)334 1458 y(\(radius\))f(is)h(half)f(the)h (diameter)f(of)h(the)g(circle)334 1571 y(\(rotation\))e(is)i(the)g (angle\(degrees\))d(that)j(the)g(region)f(is)h(rotated)f(with)620 1684 y(respect)g(to)h(\(xcntr,ycntr\))334 1797 y(\(Xcoord,Ycoord\))d (are)j(the)g(\(x,y\))f(coordinates)f(to)i(test,)f(usually)g(column)620 1910 y(names)334 2023 y(NOTE:)g(each)h(parameter)e(can)i(itself)f(be)i (an)f(expression,)d(not)j(merely)f(a)620 2136 y(column)h(name)f(or)h (constant.)0 2443 y Fd(10.11.7)113 b(Example)38 b(Ro)m(w)f(Filters)191 2665 y Fe([)47 b(binary)f(&&)i(mag)f(<=)g(5.0])380 b(-)48 b(Extract)e(all)h(binary)f(stars)g(brighter)1766 2778 y(than)94 b(fifth)47 b(magnitude)e(\(note)h(that)1766 2891 y(the)h(initial)f(space)g(is)h(necessary)e(to)1766 3004 y(prevent)h(it)h(from)g(being)f(treated)g(as)h(a)1766 3117 y(binning)f(specification\))191 3343 y([#row)g(>=)h(125)g(&&)h (#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through) f(175)191 3569 y([IMAGE[4,5])f(.gt.)h(100])476 b(-)48 b(Extract)e(all)h(rows)f(that)h(have)g(the)1766 3681 y(\(4,5\))f(component)g(of)h(the)g(IMAGE)f(column)1766 3794 y(greater)g(than)g(100)191 4020 y([abs\(sin\(theta)e(*)j(#deg\)\)) f(<)i(0.5])e(-)i(Extract)e(all)h(rows)f(having)g(the)1766 4133 y(absolute)f(value)i(of)g(the)g(sine)g(of)g(theta)1766 4246 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h(angles)1766 4359 y(are)g(tabulated)e(in)i(degrees)191 4585 y([SUM\()f(SPEC)h(>)g (3*BACKGRND)e(\)>=1])94 b(-)48 b(Extract)e(all)h(rows)f(containing)f(a) 1766 4698 y(spectrum,)g(held)i(in)g(vector)f(column)1766 4811 y(SPEC,)g(with)h(at)g(least)f(one)h(value)g(3)1766 4924 y(times)f(greater)g(than)h(the)g(background)1766 5036 y(level)f(held)h(in)g(a)h(keyword,)d(BACKGRND)191 5262 y([VCOL=={1,4,2}])759 b(-)48 b(Extract)e(all)h(rows)f(whose)h (vector)f(column)1766 5375 y(VCOL)h(contains)e(the)i(3-elements)e(1,)i (4,)g(and)1766 5488 y(2.)191 5714 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g(expression)p eop end %%Page: 157 165 TeXDict begin 157 164 bop 0 299 a Fh(10.12.)113 b(BINNING)32 b(OR)e(HISTOGRAMMING)g(SPECIFICA)-8 b(TION)1223 b Fj(157)1766 555 y Fe(contained)45 b(within)h(the)h(text)g(file)1766 668 y(rowFilter.txt)191 894 y([gtifilter\(\)])855 b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)239 1007 y(extension,)92 b(filter)i(the)47 b(TIME)239 1120 y(column)f(in)h(the)g (current)f(table,)g(using)239 1233 y(START/STOP)f(times)h(taken)g(from) 239 1346 y(columns)f(in)j(the)f(GTI)94 b(extension)191 1571 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h (have)f(a)i(coordinate)1766 1684 y(\(as)f(given)f(in)h(the)g(X)h(and)f (Y)g(columns\))1766 1797 y(within)f(the)h(spatial)f(region)g(specified) 1766 1910 y(in)h(the)g(pow.reg)f(region)g(file.)191 2136 y([regfilter\("pow.reg",)c(Xs,)47 b(Ys\)])f(-)i(Same)f(as)g(above,)f (except)g(that)h(the)1766 2249 y(Xs)g(and)g(Ys)g(columns)f(will)h(be)g (used)f(to)1766 2362 y(determine)f(the)i(coordinate)e(of)i(each)1766 2475 y(row)g(in)g(the)g(table.)0 2811 y Ff(10.12)181 b(Binning)44 b(or)h(Histogramming)i(Sp)t(eci\014cation)0 3062 y Fj(The)22 b(optional)i(binning)e(sp)s(eci\014er)g(is)h(enclosed) h(in)f(square)f(brac)m(k)m(ets)j(and)d(can)h(b)s(e)f(distinguished)g (from)h(a)g(general)0 3175 y(ro)m(w)32 b(\014lter)h(sp)s(eci\014cation) g(b)m(y)f(the)h(fact)g(that)g(it)g(b)s(egins)f(with)g(the)g(k)m(eyw)m (ord)h('bin')f(not)h(immediately)g(follo)m(w)m(ed)0 3288 y(b)m(y)41 b(an)f(equals)i(sign.)72 b(When)41 b(binning)e(is)i(sp)s (eci\014ed,)i(a)e(temp)s(orary)g(N-dimensional)g(FITS)f(primary)g(arra) m(y)0 3401 y(is)j(created)h(b)m(y)f(computing)h(the)f(histogram)h(of)f (the)g(v)-5 b(alues)44 b(in)e(the)i(sp)s(eci\014ed)e(columns)h(of)g(a)h (FITS)e(table)0 3514 y(extension.)f(After)30 b(the)f(histogram)h(is)g (computed)f(the)h(input)e(FITS)h(\014le)h(con)m(taining)h(the)e(table)i (is)e(then)g(closed)0 3627 y(and)34 b(the)h(temp)s(orary)f(FITS)g (primary)g(arra)m(y)h(is)g(op)s(ened)f(and)g(passed)g(to)h(the)g (application)h(program.)54 b(Th)m(us,)0 3740 y(the)39 b(application)h(program)f(nev)m(er)g(sees)g(the)g(original)h(FITS)e (table)i(and)e(only)h(sees)h(the)f(image)h(in)e(the)h(new)0 3853 y(temp)s(orary)32 b(\014le)h(\(whic)m(h)g(has)f(no)h(additional)g (extensions\).)49 b(Ob)m(viously)-8 b(,)34 b(the)f(application)h (program)e(m)m(ust)h(b)s(e)0 3966 y(exp)s(ecting)e(to)g(op)s(en)f(a)h (FITS)e(image)j(and)e(not)g(a)h(FITS)f(table)h(in)f(this)g(case.)0 4126 y(The)g(data)h(t)m(yp)s(e)f(of)h(the)f(FITS)g(histogram)g(image)i (ma)m(y)f(b)s(e)f(sp)s(eci\014ed)f(b)m(y)h(app)s(ending)f('b')h(\(for)h (8-bit)g(b)m(yte\),)g('i')0 4239 y(\(for)g(16-bit)g(in)m(tegers\),)h ('j')f(\(for)g(32-bit)g(in)m(teger\),)i('r')d(\(for)h(32-bit)g (\015oating)h(p)s(oin)m(ts\),)e(or)h('d')f(\(for)h(64-bit)g(double)0 4351 y(precision)j(\015oating)i(p)s(oin)m(t\))e(to)h(the)g('bin')f(k)m (eyw)m(ord)h(\(e.g.)54 b('[binr)33 b(X]')i(creates)h(a)f(real)g (\015oating)g(p)s(oin)m(t)f(image\).)0 4464 y(If)g(the)i(data)f(t)m(yp) s(e)g(is)g(not)h(explicitly)g(sp)s(eci\014ed)e(then)h(a)g(32-bit)i(in)m (teger)f(image)g(will)f(b)s(e)g(created)h(b)m(y)e(default,)0 4577 y(unless)24 b(the)i(w)m(eigh)m(ting)g(option)g(is)f(also)h(sp)s (eci\014ed)e(in)h(whic)m(h)g(case)h(the)f(image)i(will)e(ha)m(v)m(e)h (a)g(32-bit)g(\015oating)g(p)s(oin)m(t)0 4690 y(data)31 b(t)m(yp)s(e)g(b)m(y)f(default.)0 4850 y(The)24 b(histogram)g(image)i (ma)m(y)f(ha)m(v)m(e)g(from)f(1)g(to)h(4)g(dimensions)e(\(axes\),)k (dep)s(ending)c(on)h(the)g(n)m(um)m(b)s(er)f(of)h(columns)0 4963 y(that)31 b(are)g(sp)s(eci\014ed.)40 b(The)30 b(general)h(form)f (of)g(the)h(binning)e(sp)s(eci\014cation)i(is:)48 5226 y Fe([bin{bijrd})92 b(Xcol=min:max:binsize,)42 b(Ycol=)47 b(...,)f(Zcol=...,)f(Tcol=...;)h(weight])0 5488 y Fj(in)39 b(whic)m(h)g(up)f(to)i(4)g(columns,)h(eac)m(h)f(corresp)s(onding)e(to)i (an)g(axis)f(of)h(the)f(image,)k(are)d(listed.)67 b(The)39 b(column)0 5601 y(names)27 b(are)h(case)h(insensitiv)m(e,)g(and)e(the)h (column)f(n)m(um)m(b)s(er)f(ma)m(y)i(b)s(e)f(giv)m(en)h(instead)g(of)g (the)g(name,)g(preceded)f(b)m(y)0 5714 y(a)32 b(p)s(ound)e(sign)i (\(e.g.,)i([bin)d(#4=1:512]\).)47 b(If)31 b(the)h(column)g(name)g(is)f (not)h(sp)s(eci\014ed,)g(then)f(CFITSIO)g(will)h(\014rst)p eop end %%Page: 158 166 TeXDict begin 158 165 bop 0 299 a Fj(158)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(try)37 b(to)h(use)f(the)g('preferred)f(column')i(as)f(sp)s (eci\014ed)g(b)m(y)g(the)g(CPREF)g(k)m(eyw)m(ord)h(if)f(it)g(exists)h (\(e.g.,)j('CPREF)0 668 y(=)i('DETX,DETY'\),)h(otherwise)g(column)f (names)g('X',)h('Y',)g('Z',)f(and)f('T')i(will)f(b)s(e)f(assumed)h(for) g(eac)m(h)h(of)0 781 y(the)37 b(4)h(axes,)i(resp)s(ectiv)m(ely)-8 b(.)62 b(In)37 b(cases)h(where)e(the)i(column)f(name)g(could)g(b)s(e)f (confused)h(with)g(an)g(arithmetic)0 894 y(expression,)30 b(enclose)i(the)f(column)f(name)g(in)g(paren)m(theses)h(to)g(force)g (the)f(name)h(to)g(b)s(e)f(in)m(terpreted)g(literally)-8 b(.)0 1054 y(In)31 b(addition)h(to)g(binning)f(b)m(y)g(a)h(FITS)f (column,)h(an)m(y)g(arbitrary)f(calculator)j(expression)e(ma)m(y)g(b)s (e)f(sp)s(eci\014ed)g(as)0 1167 y(w)m(ell.)42 b(Usage)31 b(of)g(this)f(form)g(w)m(ould)g(app)s(ear)g(as:)48 1381 y Fe([bin)94 b(Xcol\(arbitrary)44 b(expression\)=min:max:bins)o(ize,)d (...)47 b(])0 1596 y Fj(The)23 b(column)h(name)g(m)m(ust)f(still)i(b)s (e)e(sp)s(eci\014ed,)h(and)g(is)f(used)g(to)i(lab)s(el)f(co)s(ordinate) g(axes)h(of)f(the)g(resulting)f(image.)0 1709 y(The)30 b(expression)g(app)s(ears)g(immediately)i(after)e(the)h(name,)g (enclosed)g(in)f(paren)m(theses.)41 b(The)30 b(expression)g(ma)m(y)0 1822 y(use)h(an)m(y)i(com)m(bination)g(of)f(columns,)g(k)m(eyw)m(ords,) g(functions)g(and)f(constan)m(ts)i(and)e(allo)m(w)m(ed)j(b)m(y)d(the)h (CFITSIO)0 1935 y(calculator.)0 2095 y(The)d(column)f(name)h(\(and)g (optional)h(expression\))f(ma)m(y)h(b)s(e)e(follo)m(w)m(ed)j(b)m(y)e (an)g(equals)g(sign)g(and)g(then)f(the)i(lo)m(w)m(er)0 2208 y(and)f(upp)s(er)f(range)i(of)f(the)h(histogram,)h(and)e(the)h (size)g(of)g(the)g(histogram)g(bins,)f(separated)h(b)m(y)g(colons.)41 b(Spaces)0 2321 y(are)30 b(allo)m(w)m(ed)i(b)s(efore)e(and)f(after)i (the)f(equals)h(sign)f(but)f(not)h(within)g(the)g('min:max:binsize')h (string.)41 b(The)29 b(min,)0 2433 y(max)37 b(and)g(binsize)g(v)-5 b(alues)38 b(ma)m(y)g(b)s(e)f(in)m(teger)h(or)g(\015oating)g(p)s(oin)m (t)f(n)m(um)m(b)s(ers,)h(or)f(they)h(ma)m(y)f(b)s(e)g(the)h(names)f(of) 0 2546 y(k)m(eyw)m(ords)f(in)g(the)h(header)f(of)g(the)g(table.)59 b(If)36 b(the)g(latter,)k(then)c(the)g(v)-5 b(alue)37 b(of)f(that)h(k)m(eyw)m(ord)f(is)h(substituted)0 2659 y(in)m(to)31 b(the)g(expression.)0 2819 y(Default)37 b(v)-5 b(alues)36 b(for)g(the)g(min,)h(max)f(and)g(binsize)g(quan)m (tities)h(will)f(b)s(e)f(used)h(if)f(not)i(explicitly)g(giv)m(en)g(in)f (the)0 2932 y(binning)29 b(expression)h(as)h(sho)m(wn)f(in)g(these)h (examples:)191 3147 y Fe([bin)47 b(x)g(=)g(:512:2])94 b(-)47 b(use)g(default)f(minimum)g(value)191 3260 y([bin)h(x)g(=)g (1::2])190 b(-)47 b(use)g(default)f(maximum)g(value)191 3373 y([bin)h(x)g(=)g(1:512])142 b(-)47 b(use)g(default)f(bin)h(size) 191 3485 y([bin)g(x)g(=)g(1:])286 b(-)47 b(use)g(default)f(maximum)g (value)g(and)h(bin)g(size)191 3598 y([bin)g(x)g(=)g(:512])190 b(-)47 b(use)g(default)f(minimum)g(value)g(and)h(bin)g(size)191 3711 y([bin)g(x)g(=)g(2])334 b(-)47 b(use)g(default)f(minimum)g(and)h (maximum)f(values)191 3824 y([bin)h(x])524 b(-)47 b(use)g(default)f (minimum,)g(maximum)g(and)g(bin)h(size)191 3937 y([bin)g(4])524 b(-)47 b(default)f(2-D)h(image,)f(bin)h(size)g(=)g(4)h(in)f(both)g (axes)191 4050 y([bin])619 b(-)47 b(default)f(2-D)h(image)0 4264 y Fj(CFITSIO)31 b(will)i(use)f(the)h(v)-5 b(alue)33 b(of)g(the)g(TLMINn,)f(TLMAXn,)h(and)f(TDBINn)h(k)m(eyw)m(ords,)h(if)e (they)h(exist,)h(for)0 4377 y(the)j(default)f(min,)i(max,)g(and)e (binsize,)i(resp)s(ectiv)m(ely)-8 b(.)61 b(If)36 b(they)h(do)f(not)h (exist)g(then)f(CFITSIO)f(will)i(use)f(the)0 4490 y(actual)d(minim)m (um)e(and)h(maxim)m(um)g(v)-5 b(alues)32 b(in)g(the)g(column)f(for)h (the)g(histogram)h(min)e(and)h(max)g(v)-5 b(alues.)45 b(The)0 4603 y(default)34 b(binsize)f(will)h(b)s(e)f(set)h(to)h(1,)g (or)e(\(max)h(-)g(min\))f(/)h(10.,)i(whic)m(hev)m(er)e(is)g(smaller,)h (so)e(that)i(the)e(histogram)0 4716 y(will)e(ha)m(v)m(e)g(at)g(least)h (10)f(bins)f(along)h(eac)m(h)h(axis.)0 4876 y(Please)d(note)f(that)g (if)g(explicit)h(min)e(and)g(max)h(v)-5 b(alues)28 b(\(or)f (TLMINn/TLMAXn)g(k)m(eyw)m(ords\))i(are)f(not)g(presen)m(t,)0 4989 y(then)g(CFITSIO)g(m)m(ust)g(c)m(hec)m(k)j(ev)m(ery)e(v)-5 b(alue)30 b(of)e(the)h(binned)f(quan)m(tit)m(y)i(in)e(adv)-5 b(ance)30 b(to)f(determine)g(the)g(binning)0 5102 y(limits.)43 b(This)30 b(is)h(esp)s(ecially)h(relev)-5 b(an)m(t)32 b(for)f(binning)f(expressions,)h(whic)m(h)g(m)m(ust)f(b)s(e)h(ev)-5 b(aluated)32 b(m)m(ultiple)f(times)0 5215 y(to)40 b(determine)f(the)g (limits)g(of)g(the)g(expression.)67 b(Th)m(us,)40 b(it)f(is)g(alw)m(a)m (ys)i(advisable)e(to)h(sp)s(ecify)e(min)h(and)f(max)0 5328 y(limits)31 b(where)f(p)s(ossible.)0 5488 y(A)41 b(shortcut)g(notation)h(is)f(allo)m(w)m(ed)i(if)e(all)h(the)f (columns/axes)h(ha)m(v)m(e)g(the)f(same)g(binning)f(sp)s (eci\014cation.)74 b(In)0 5601 y(this)33 b(case)g(all)h(the)f(column)f (names)h(ma)m(y)g(b)s(e)f(listed)h(within)f(paren)m(theses,)i(follo)m (w)m(ed)h(b)m(y)d(the)h(\(single\))h(binning)0 5714 y(sp)s (eci\014cation,)d(as)g(in:)p eop end %%Page: 159 167 TeXDict begin 159 166 bop 0 299 a Fh(10.12.)113 b(BINNING)32 b(OR)e(HISTOGRAMMING)g(SPECIFICA)-8 b(TION)1223 b Fj(159)191 555 y Fe([bin)47 b(\(X,Y\)=1:512:2])191 668 y([bin)g(\(X,Y\))f(=)h(5])0 918 y Fj(The)31 b(optional)i(w)m(eigh)m(ting)h(factor)e(is)g(the)g (last)g(item)h(in)e(the)h(binning)f(sp)s(eci\014er)g(and,)h(if)f (presen)m(t,)i(is)e(separated)0 1031 y(from)38 b(the)g(list)h(of)f (columns)g(b)m(y)g(a)h(semi-colon.)65 b(As)39 b(the)f(histogram)h(is)f (accum)m(ulated,)k(this)c(w)m(eigh)m(t)i(is)e(used)0 1144 y(to)d(incremen)m(ted)f(the)g(v)-5 b(alue)35 b(of)f(the)g (appropriated)f(bin)h(in)f(the)h(histogram.)52 b(If)34 b(the)g(w)m(eigh)m(ting)i(factor)f(is)f(not)0 1257 y(sp)s(eci\014ed,)c (then)f(the)h(default)g(w)m(eigh)m(t)i(=)d(1)i(is)f(assumed.)39 b(The)30 b(w)m(eigh)m(ting)h(factor)g(ma)m(y)g(b)s(e)e(a)h(constan)m(t) i(in)m(teger)0 1370 y(or)d(\015oating)g(p)s(oin)m(t)g(n)m(um)m(b)s(er,) f(or)g(the)h(name)g(of)f(a)h(k)m(eyw)m(ord)g(con)m(taining)h(the)f(w)m (eigh)m(ting)i(v)-5 b(alue.)40 b(The)28 b(w)m(eigh)m(ting)0 1483 y(factor)35 b(ma)m(y)f(also)h(b)s(e)e(the)h(name)g(of)g(a)g(table) h(column)f(in)f(whic)m(h)h(case)h(the)f(v)-5 b(alue)34 b(in)g(that)g(column,)h(on)f(a)g(ro)m(w)0 1596 y(b)m(y)29 b(ro)m(w)f(basis,)i(will)f(b)s(e)f(used.)39 b(It)29 b(ma)m(y)g(also)h (b)s(e)e(an)h(expression,)g(enclosed)g(in)g(paren)m(thesis,)g(in)g (whic)m(h)f(case)i(the)0 1709 y(w)m(eigh)m(ting)i(v)-5 b(alue)31 b(will)g(b)s(e)e(ev)-5 b(aluated)32 b(for)e(eac)m(h)i(binned) d(ro)m(w)h(and)g(applied)g(accordingly)-8 b(.)0 1869 y(In)35 b(some)h(cases,)i(the)d(column)h(or)f(k)m(eyw)m(ord)h(ma)m(y)g (giv)m(e)h(the)f(recipro)s(cal)g(of)g(the)g(actual)h(w)m(eigh)m(t)g(v) -5 b(alue)36 b(that)g(is)0 1982 y(needed.)49 b(In)32 b(this)h(case,)i(precede)e(the)h(w)m(eigh)m(t)g(k)m(eyw)m(ord)g(or)f (column)g(name)g(b)m(y)g(a)g(slash)g('/')h(to)g(tell)g(CFITSIO)0 2095 y(to)40 b(use)e(the)i(recipro)s(cal)g(of)f(the)g(v)-5 b(alue)39 b(when)f(constructing)i(the)f(histogram.)68 b(An)38 b(expression,)j(enclosed)f(in)0 2208 y(paren)m(theses,)31 b(ma)m(y)g(also)g(app)s(ear)f(after)h(the)f(slash,)h(to)g(indicate)g (the)g(recipro)s(cal)g(v)-5 b(alue)31 b(of)g(the)f(expression.)0 2368 y(F)-8 b(or)25 b(complex)g(or)f(commonly)g(used)g(histograms,)i (one)e(can)h(also)g(place)g(its)f(description)g(in)m(to)h(a)g(text)g (\014le)f(and)g(im-)0 2481 y(p)s(ort)e(it)g(in)m(to)h(the)g(binning)e (sp)s(eci\014cation)i(using)e(the)i(syn)m(tax)f([bin)g (@\014lename.txt].)39 b(The)22 b(\014le's)g(con)m(ten)m(ts)i(can)e(ex-) 0 2594 y(tend)h(o)m(v)m(er)i(m)m(ultiple)f(lines,)h(although)f(it)g(m)m (ust)f(still)h(conform)f(to)h(the)g(no-spaces)g(rule)f(for)g(the)h (min:max:binsize)0 2707 y(syn)m(tax)35 b(and)f(eac)m(h)h(axis)g(sp)s (eci\014cation)h(m)m(ust)e(still)h(b)s(e)f(comma-separated.)55 b(An)m(y)34 b(lines)h(in)f(the)h(external)g(text)0 2819 y(\014le)27 b(that)g(b)s(egin)g(with)f(2)i(slash)e(c)m(haracters)j (\('//'\))g(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)i(b)s(e)e(used)g(to)i (add)e(commen)m(ts)i(in)m(to)0 2932 y(the)j(\014le.)0 3092 y(Examples:)191 3343 y Fe([bini)46 b(detx,)h(dety])762 b(-)47 b(2-D,)g(16-bit)f(integer)g(histogram)1861 3456 y(of)i(DETX)e(and)h(DETY)g(columns,)e(using)1861 3569 y(default)h(values)g(for)h(the)g(histogram)1861 3681 y(range)g(and)g(binsize)191 3907 y([bin)g(\(detx,)f(dety\)=16;)f (/exposure])g(-)i(2-D,)g(32-bit)f(real)h(histogram)e(of)i(DETX)1861 4020 y(and)g(DETY)g(columns)f(with)g(a)i(bin)f(size)f(=)i(16)1861 4133 y(in)g(both)e(axes.)h(The)f(histogram)g(values)1861 4246 y(are)h(divided)f(by)h(the)g(EXPOSURE)f(keyword)1861 4359 y(value.)191 4585 y([bin)h(time=TSTART:TSTOP:0.1])280 b(-)47 b(1-D)g(lightcurve,)e(range)h(determined)f(by)1861 4698 y(the)i(TSTART)f(and)h(TSTOP)g(keywords,)1861 4811 y(with)g(0.1)g(unit)g(size)f(bins.)191 5036 y([bin)h(pha,)f (time=8000.:8100.:0.1])90 b(-)47 b(2-D)g(image)g(using)f(default)g (binning)1861 5149 y(of)i(the)e(PHA)h(column)f(for)h(the)g(X)h(axis,) 1861 5262 y(and)f(1000)g(bins)g(in)g(the)g(range)1861 5375 y(8000.)g(to)g(8100.)f(for)h(the)g(Y)h(axis.)191 5601 y([bin)f(pha,)f(gti_num\(gtifind\(\)\)=1:2:1])41 b(-)48 b(a)f(2-D)g(image,)f(where)g(PHA)h(is)g(the)1861 5714 y(X)h(axis)e(and)h(the)g(Y)h(axis)e(is)i(an)f(expression)p eop end %%Page: 160 168 TeXDict begin 160 167 bop 0 299 a Fj(160)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)1861 555 y Fe(which)47 b(evaluates)e(to)i(the)g(GTI)g(number,)1861 668 y(as)h(determined)d(using)h(the)1861 781 y(GTIFIND\(\))g(function.) 191 1007 y([bin)h(time=0:4000:2000,)c(HR\()k(\(LC2/LC1\).lt.1.5)c(?)k (1)h(:)f(2)h(\)=1:2:1])d(-)j(a)f(2-D)1861 1120 y(histogram)f(which)g (determines)f(the)i(number)1861 1233 y(of)h(samples)d(in)j(two)e(time)h (bins)g(between)f(0)h(and)1861 1346 y(4000)g(and)g(separating)e (hardness)g(ratio,)1861 1458 y(evaluated)h(as)h(\(LC2/LC1\),)e(between) h(less)g(than)1861 1571 y(1.5)h(or)g(greater)f(than)h(1.5.)94 b(The)47 b(?:)1861 1684 y(conditional)e(function)h(is)h(used)f(to)i (decide)1861 1797 y(less)f(\(or)g(greater\))e(than)i(1.5)g(and)g (assign)1861 1910 y(HR)h(bin)e(1)i(or)f(2.)191 2136 y([bin)g (@binFilter.txt])616 b(-)47 b(Use)g(the)g(contents)f(of)h(the)g(text)f (file)1861 2249 y(binFilter.txt)f(for)h(the)h(binning)1861 2362 y(specifications.)p eop end %%Page: 161 169 TeXDict begin 161 168 bop 0 1225 a Fg(Chapter)65 b(11)0 1687 y Fm(T)-19 b(emplate)76 b(Files)0 2180 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f(call)i(to)g (\014ts)p 2101 2180 28 4 v 32 w(create)p 2369 2180 V 35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e(ma)m(y)0 2293 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h(follo)m (wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e(created.)71 b(This)0 2406 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h (structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m(y)0 2518 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f(newly)g (created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g(k)m(eyw) m(ords)g(in)0 2631 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g(template)i (FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b)s(e)f (\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2744 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,)g (where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h(FITS) f(k)m(eyw)m(ord)i(record.)0 2857 y(The)j(format)h(of)f(the)h(ASCI)s(I)e (template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m(wing)i (sections.)0 3188 y Ff(11.1)136 b(Detailed)46 b(T)-11 b(emplate)46 b(Line)f(F)-11 b(ormat)0 3438 y Fj(The)30 b(format)h(of)f(eac)m(h)i(ASCI)s(I)c(template)k(line)f(closely)h(follo) m(ws)f(the)g(format)g(of)f(a)h(FITS)f(k)m(eyw)m(ord)g(record:)95 3682 y Fe(KEYWORD)46 b(=)i(KEYVALUE)d(/)j(COMMENT)0 3926 y Fj(except)22 b(that)g(free)g(format)f(ma)m(y)h(b)s(e)f(used)f (\(e.g.,)25 b(the)d(equals)f(sign)h(ma)m(y)f(app)s(ear)g(at)h(an)m(y)g (p)s(osition)f(in)g(the)h(line\))g(and)0 4039 y(T)-8 b(AB)34 b(c)m(haracters)g(are)g(allo)m(w)m(ed)h(and)e(are)g(treated)h (the)g(same)f(as)h(space)f(c)m(haracters.)51 b(The)33 b(KEYV)-10 b(ALUE)33 b(and)0 4152 y(COMMENT)d(\014elds)g(are)h (optional.)43 b(The)30 b(equals)h(sign)f(c)m(haracter)j(is)d(also)i (optional,)g(but)e(it)h(is)f(recommended)0 4264 y(that)42 b(it)f(b)s(e)g(included)f(for)h(clarit)m(y)-8 b(.)75 b(An)m(y)41 b(template)i(line)e(that)h(b)s(egins)f(with)f(the)i(p)s (ound)d('#')i(c)m(haracter)i(is)0 4377 y(ignored)30 b(b)m(y)h(the)f (template)i(parser)e(and)g(ma)m(y)h(b)s(e)e(use)h(to)h(insert)g(commen) m(ts)g(in)m(to)g(the)g(template)h(\014le)e(itself.)0 4538 y(The)c(KEYW)m(ORD)g(name)g(\014eld)g(is)g(limited)h(to)g(8)f(c)m (haracters)h(in)f(length)h(and)e(only)h(the)g(letters)i(A-Z,)e(digits)h (0-9,)0 4650 y(and)h(the)g(h)m(yphen)f(and)h(underscore)g(c)m (haracters)h(ma)m(y)g(b)s(e)f(used,)g(without)h(an)m(y)f(em)m(b)s (edded)g(spaces.)40 b(Lo)m(w)m(ercase)0 4763 y(letters)22 b(in)f(the)h(template)g(k)m(eyw)m(ord)g(name)f(will)g(b)s(e)g(con)m(v)m (erted)i(to)f(upp)s(ercase.)36 b(Leading)22 b(spaces)f(in)g(the)h (template)0 4876 y(line)k(preceding)g(the)f(k)m(eyw)m(ord)h(name)g(are) g(generally)h(ignored,)g(except)f(if)g(the)g(\014rst)f(8)h(c)m (haracters)h(of)f(a)g(template)0 4989 y(line)f(are)h(all)g(blank,)g (then)f(the)g(en)m(tire)h(line)g(is)f(treated)h(as)f(a)h(FITS)e(commen) m(t)i(k)m(eyw)m(ord)g(\(with)f(a)h(blank)e(k)m(eyw)m(ord)0 5102 y(name\))31 b(and)f(is)g(copied)h(v)m(erbatim)g(in)m(to)g(the)g (FITS)e(header.)0 5262 y(The)37 b(KEYV)-10 b(ALUE)37 b(\014eld)g(ma)m(y)h(ha)m(v)m(e)g(an)m(y)g(allo)m(w)m(ed)h(FITS)e(data) h(t)m(yp)s(e:)54 b(c)m(haracter)39 b(string,)h(logical,)h(in)m(teger,)0 5375 y(real,)28 b(complex)g(in)m(teger,)h(or)d(complex)i(real.)40 b(In)m(teger)28 b(v)-5 b(alues)27 b(m)m(ust)f(b)s(e)g(within)g(the)h (allo)m(w)m(ed)i(range)e(of)g(a)g('signed)0 5488 y(long')h(v)-5 b(ariable;)29 b(some)f(C)e(compilers)i(only)f(suppp)s(ort)e(4-b)m(yte)j (long)g(in)m(tegers)g(with)f(a)g(range)h(from)e(-2147483648)0 5601 y(to)31 b(+2147483647,)k(whereas)30 b(other)h(C)f(compilers)h (supp)s(ort)e(8-b)m(yte)j(in)m(tegers)f(with)f(a)h(range)g(of)g(plus)e (or)i(min)m(us)0 5714 y(2**63.)1882 5942 y(161)p eop end %%Page: 162 170 TeXDict begin 162 169 bop 0 299 a Fj(162)2250 b Fh(CHAPTER)29 b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fj(The)23 b(c)m(haracter)h(string)f(v)-5 b(alues)24 b(need)f(not)g(b)s(e)g (enclosed)g(in)g(single)h(quote)g(c)m(haracters)g(unless)f(they)g(are)h (necessary)0 668 y(to)37 b(distinguish)e(the)i(string)f(from)f(a)i (di\013eren)m(t)g(data)f(t)m(yp)s(e)h(\(e.g.)59 b(2.0)38 b(is)e(a)g(real)h(but)f('2.0')h(is)f(a)h(string\).)58 b(The)0 781 y(k)m(eyw)m(ord)38 b(has)g(an)g(unde\014ned)d(\(n)m(ull\))k (v)-5 b(alue)38 b(if)g(the)g(template)h(record)f(only)g(con)m(tains)h (blanks)e(follo)m(wing)j(the)0 894 y("=")31 b(or)f(b)s(et)m(w)m(een)h (the)g("=")g(and)f(the)g("/")i(commen)m(t)f(\014eld)f(delimiter.)0 1054 y(String)c(k)m(eyw)m(ord)h(v)-5 b(alues)27 b(longer)g(than)f(68)h (c)m(haracters)h(\(the)f(maxim)m(um)f(length)h(that)g(will)g(\014t)f (in)g(a)h(single)g(FITS)0 1167 y(k)m(eyw)m(ord)41 b(record\))g(are)g(p) s(ermitted)f(using)g(the)h(CFITSIO)e(long)i(string)g(con)m(v)m(en)m (tion.)74 b(They)40 b(can)h(either)g(b)s(e)0 1280 y(sp)s(eci\014ed)28 b(as)i(a)f(single)h(long)f(line)h(in)e(the)i(template,)h(or)e(b)m(y)f (using)h(m)m(ultiple)h(lines)f(where)f(the)i(con)m(tin)m(uing)g(lines)0 1393 y(con)m(tain)i(the)e('CONTINUE')g(k)m(eyw)m(ord,)h(as)g(in)f(this) g(example:)95 1657 y Fe(LONGKEY)46 b(=)i('This)e(is)h(a)h(long)e (string)g(value)h(that)f(is)i(contin&')95 1770 y(CONTINUE)94 b('ued)46 b(over)h(2)g(records')f(/)h(comment)f(field)h(goes)f(here)0 2035 y Fj(The)29 b(format)h(of)g(template)h(lines)e(with)h(CONTINUE)e (k)m(eyw)m(ord)i(is)g(v)m(ery)g(strict:)41 b(3)30 b(spaces)g(m)m(ust)f (follo)m(w)i(CON-)0 2147 y(TINUE)f(and)g(the)g(rest)h(of)f(the)h(line)g (is)f(copied)h(v)m(erbatim)g(to)g(the)g(FITS)e(\014le.)0 2308 y(The)i(start)h(of)g(the)f(optional)i(COMMENT)e(\014eld)g(m)m(ust) h(b)s(e)e(preceded)i(b)m(y)f("/",)i(whic)m(h)e(is)h(used)f(to)h (separate)g(it)0 2421 y(from)e(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(\014eld.)41 b(Exceptions)30 b(are)h(if)f(the)h(KEYW)m(ORD)g (name)f(\014eld)g(con)m(tains)h(COMMENT,)0 2533 y(HISTOR)-8 b(Y,)30 b(CONTINUE,)g(or)g(if)g(the)h(\014rst)f(8)g(c)m(haracters)i(of) f(the)f(template)i(line)f(are)g(blanks.)0 2694 y(More)c(than)f(one)h (Header-Data)i(Unit)e(\(HDU\))g(ma)m(y)g(b)s(e)f(de\014ned)f(in)h(the)h (template)h(\014le.)39 b(The)26 b(start)h(of)g(an)f(HDU)0 2806 y(de\014nition)k(is)g(denoted)h(with)f(a)h(SIMPLE)e(or)i(XTENSION) e(template)j(line:)0 2967 y(1\))i(SIMPLE)f(b)s(egins)g(a)h(Primary)g (HDU)g(de\014nition.)50 b(SIMPLE)33 b(ma)m(y)h(only)g(app)s(ear)f(as)h (the)g(\014rst)f(k)m(eyw)m(ord)h(in)0 3080 y(the)e(template)i(\014le.) 45 b(If)32 b(the)g(template)i(\014le)e(b)s(egins)f(with)h(XTENSION)f (instead)h(of)g(SIMPLE,)g(then)f(a)i(default)0 3192 y(empt)m(y)d (Primary)e(HDU)i(is)g(created,)h(and)d(the)i(template)h(is)e(then)g (assumed)f(to)i(de\014ne)f(the)h(k)m(eyw)m(ords)f(starting)0 3305 y(with)h(the)h(\014rst)e(extension)i(follo)m(wing)h(the)f(Primary) f(HDU.)0 3466 y(2\))35 b(XTENSION)e(marks)g(the)i(b)s(eginning)e(of)h (a)h(new)e(extension)i(HDU)f(de\014nition.)52 b(The)33 b(previous)h(HDU)h(will)0 3578 y(b)s(e)30 b(closed)h(at)g(this)f(p)s (oin)m(t)h(and)e(pro)s(cessing)i(of)f(the)h(next)f(extension)h(b)s (egins.)0 3918 y Ff(11.2)136 b(Auto-indexing)45 b(of)g(Keyw)l(ords)0 4169 y Fj(If)31 b(a)h(template)g(k)m(eyw)m(ord)g(name)f(ends)g(with)g (a)g("#")h(c)m(haracter,)i(it)e(is)f(said)g(to)h(b)s(e)f ('auto-indexed'.)44 b(Eac)m(h)32 b("#")0 4282 y(c)m(haracter)i(will)f (b)s(e)f(replaced)i(b)m(y)e(the)h(curren)m(t)g(in)m(teger)h(index)e(v) -5 b(alue,)34 b(whic)m(h)f(gets)g(reset)h(=)e(1)h(at)h(the)e(start)i (of)0 4395 y(eac)m(h)h(new)f(HDU)g(in)g(the)g(\014le)g(\(or)g(7)h(in)e (the)h(sp)s(ecial)h(case)g(of)f(a)g(GR)m(OUP)h(de\014nition\).)51 b(The)33 b(FIRST)g(indexed)0 4508 y(k)m(eyw)m(ord)c(in)f(eac)m(h)h (template)h(HDU)f(de\014nition)f(is)g(used)f(as)i(the)f('incremen)m (tor';)j(eac)m(h)e(subsequen)m(t)f(o)s(ccurrence)0 4620 y(of)k(this)f(SAME)g(k)m(eyw)m(ord)h(will)g(cause)g(the)g(index)f(v)-5 b(alue)32 b(to)g(b)s(e)f(incremen)m(ted.)44 b(This)31 b(b)s(eha)m(vior)g(can)h(b)s(e)f(rather)0 4733 y(subtle,)d(as)g (illustrated)h(in)e(the)h(follo)m(wing)h(examples)f(in)f(whic)m(h)h (the)g(TTYPE)e(k)m(eyw)m(ord)i(is)g(the)g(incremen)m(tor)g(in)0 4846 y(b)s(oth)i(cases:)95 5111 y Fe(TTYPE#)47 b(=)g(TIME)95 5224 y(TFORM#)g(=)g(1D)95 5337 y(TTYPE#)g(=)g(RATE)95 5449 y(TFORM#)g(=)g(1E)0 5714 y Fj(will)26 b(create)i(TTYPE1,)e(TF)m (ORM1,)i(TTYPE2,)f(and)e(TF)m(ORM2)i(k)m(eyw)m(ords.)40 b(But)26 b(if)g(the)g(template)h(lo)s(oks)f(lik)m(e,)p eop end %%Page: 163 171 TeXDict begin 163 170 bop 0 299 a Fh(11.3.)73 b(TEMPLA)-8 b(TE)30 b(P)-8 b(ARSER)30 b(DIRECTIVES)1982 b Fj(163)95 555 y Fe(TTYPE#)47 b(=)g(TIME)95 668 y(TTYPE#)g(=)g(RATE)95 781 y(TFORM#)g(=)g(1D)95 894 y(TFORM#)g(=)g(1E)0 1202 y Fj(this)31 b(results)f(in)h(a)g(FITS)f(\014les)h(with)f(TTYPE1,)h (TTYPE2,)g(TF)m(ORM2,)h(and)e(TF)m(ORM2,)i(whic)m(h)f(is)g(probably)0 1315 y(not)g(what)f(w)m(as)h(in)m(tended!)0 1706 y Ff(11.3)136 b(T)-11 b(emplate)45 b(P)l(arser)h(Directiv)l(es)0 1968 y Fj(In)29 b(addition)i(to)f(the)g(template)i(lines)e(whic)m(h)g (de\014ne)f(individual)h(k)m(eyw)m(ords,)g(the)g(template)i(parser)d (recognizes)0 2081 y(3)h(sp)s(ecial)h(directiv)m(es)g(whic)m(h)f(are)g (eac)m(h)h(preceded)f(b)m(y)f(the)h(bac)m(kslash)h(c)m(haracter:)90 b Fe(\\include,)45 b(\\group)p Fj(,)29 b(and)48 2194 y Fe(\\end)p Fj(.)0 2354 y(The)37 b('include')h(directiv)m(e)i(m)m(ust) d(b)s(e)h(follo)m(w)m(ed)h(b)m(y)f(a)g(\014lename.)63 b(It)38 b(forces)g(the)g(parser)f(to)i(temp)s(orarily)f(stop)0 2467 y(reading)d(the)g(curren)m(t)g(template)h(\014le)f(and)f(b)s(egin) h(reading)g(the)g(include)f(\014le.)55 b(Once)35 b(the)g(parser)f(reac) m(hes)i(the)0 2579 y(end)f(of)h(the)g(include)f(\014le)h(it)g(con)m (tin)m(ues)g(parsing)g(the)f(curren)m(t)h(template)h(\014le.)56 b(Include)35 b(\014les)h(can)g(b)s(e)f(nested,)0 2692 y(and)30 b(HDU)h(de\014nitions)f(can)g(span)g(m)m(ultiple)h(template)h (\014les.)0 2853 y(The)f(start)h(of)g(a)g(GR)m(OUP)h(de\014nition)e(is) h(denoted)g(with)f(the)h('group')g(directiv)m(e,)h(and)f(the)f(end)h (of)f(a)i(GR)m(OUP)0 2965 y(de\014nition)k(is)h(denoted)f(with)g(the)h ('end')f(directiv)m(e.)63 b(Eac)m(h)39 b(GR)m(OUP)e(con)m(tains)i(0)f (or)f(more)h(mem)m(b)s(er)f(blo)s(c)m(ks)0 3078 y(\(HDUs)44 b(or)f(GR)m(OUPs\).)79 b(Mem)m(b)s(er)42 b(blo)s(c)m(ks)i(of)f(t)m(yp)s (e)g(GR)m(OUP)g(can)g(con)m(tain)h(their)f(o)m(wn)g(mem)m(b)s(er)f(blo) s(c)m(ks.)0 3191 y(The)32 b(GR)m(OUP)g(de\014nition)g(itself)h(o)s (ccupies)g(one)f(FITS)g(\014le)g(HDU)h(of)f(sp)s(ecial)h(t)m(yp)s(e)f (\(GR)m(OUP)h(HDU\),)h(so)e(if)h(a)0 3304 y(template)f(sp)s(eci\014es)e (1)h(group)e(with)h(1)h(mem)m(b)s(er)f(HDU)h(lik)m(e:)0 3613 y Fe(\\group)0 3725 y(grpdescr)46 b(=)h('demo')0 3838 y(xtension)f(bintable)0 3951 y(#)h(this)g(bintable)f(has)h(0)g (cols,)f(0)i(rows)0 4064 y(\\end)0 4373 y Fj(then)30 b(the)h(parser)e(creates)j(a)f(FITS)f(\014le)g(with)g(3)h(HDUs)g(:)0 4681 y Fe(1\))47 b(dummy)g(PHDU)0 4794 y(2\))g(GROUP)g(HDU)f(\(has)h(1) h(member,)d(which)i(is)g(bintable)e(in)j(HDU)f(number)f(3\))0 4907 y(3\))h(bintable)f(\(member)g(of)h(GROUP)f(in)h(HDU)g(number)f (2\))0 5215 y Fj(T)-8 b(ec)m(hnically)32 b(sp)s(eaking,)e(the)f(GR)m (OUP)i(HDU)f(is)g(a)g(BINT)-8 b(ABLE)30 b(with)g(6)g(columns.)40 b(Applications)31 b(can)f(de\014ne)0 5328 y(additional)23 b(columns)f(in)f(a)i(GR)m(OUP)f(HDU)h(using)f(TF)m(ORMn)f(and)h(TTYPEn) f(\(where)g(n)h(is)g(7,)i(8,)h(....\))39 b(k)m(eyw)m(ords)0 5441 y(or)30 b(their)h(auto-indexing)g(equiv)-5 b(alen)m(ts.)0 5601 y(F)d(or)26 b(a)f(more)g(complicated)h(example)f(of)g(a)h (template)g(\014le)f(using)f(the)h(group)f(directiv)m(es,)k(lo)s(ok)d (at)g(the)g(sample.tpl)0 5714 y(\014le)30 b(that)h(is)g(included)e(in)i (the)f(CFITSIO)f(distribution.)p eop end %%Page: 164 172 TeXDict begin 164 171 bop 0 299 a Fj(164)2250 b Fh(CHAPTER)29 b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Ff(11.4)136 b(F)-11 b(ormal)45 b(T)-11 b(emplate)46 b(Syn)l(tax)0 805 y Fj(The)30 b(template)i(syn)m(tax)f(can)f(formally)h(b)s(e)f (de\014ned)f(as)i(follo)m(ws:)191 1063 y Fe(TEMPLATE)45 b(=)j(BLOCK)e([)i(BLOCK)e(...)h(])334 1289 y(BLOCK)f(=)i({)f(HDU)g(|)h (GROUP)e(})334 1515 y(GROUP)g(=)i(\\GROUP)e([)h(BLOCK)g(...)g(])g (\\END)430 1741 y(HDU)f(=)i(XTENSION)d([)j(LINE)f(...)f(])i({)f (XTENSION)f(|)h(\\GROUP)f(|)i(\\END)f(|)g(EOF)g(})382 1967 y(LINE)f(=)i([)f(KEYWORD)f([)i(=)f(])h(])f([)g(VALUE)g(])g([)h(/)f (COMMENT)f(])191 2192 y(X)h(...)238 b(-)48 b(X)f(can)g(be)g(present)f (1)h(or)h(more)e(times)191 2305 y({)h(X)h(|)f(Y)h(})f(-)h(X)f(or)g(Y) 191 2418 y([)g(X)h(])238 b(-)48 b(X)f(is)g(optional)0 2676 y Fj(A)m(t)34 b(the)f(topmost)g(lev)m(el,)i(the)e(template)i (de\014nes)c(1)j(or)e(more)h(template)h(blo)s(c)m(ks.)49 b(Blo)s(c)m(ks)34 b(can)f(b)s(e)f(either)h(HDU)0 2789 y(\(Header)27 b(Data)h(Unit\))g(or)e(a)h(GR)m(OUP)-8 b(.)28 b(F)-8 b(or)27 b(eac)m(h)g(blo)s(c)m(k)g(the)g(parser)f(creates) i(1)f(\(or)g(more)f(for)h(GR)m(OUPs\))g(FITS)0 2902 y(\014le)j(HDUs.)0 3235 y Ff(11.5)136 b(Errors)0 3485 y Fj(In)24 b(general)h(the)f(\014ts) p 692 3485 28 4 v 33 w(execute)p 1019 3485 V 34 w(template\(\))i (function)e(tries)h(to)g(b)s(e)f(as)g(atomic)i(as)f(p)s(ossible,)g(so)f (either)h(ev)m(erything)0 3598 y(is)f(done)g(or)g(nothing)f(is)h(done.) 39 b(If)23 b(an)h(error)f(o)s(ccurs)h(during)f(parsing)g(of)h(the)g (template,)j(\014ts)p 3125 3598 V 33 w(execute)p 3452 3598 V 34 w(template\(\))0 3711 y(will)k(\(try)g(to\))h(delete)g(the)f (top)g(lev)m(el)h(BLOCK)e(\(with)h(all)g(its)h(c)m(hildren)e(if)h(an)m (y\))g(in)g(whic)m(h)f(the)h(error)f(o)s(ccurred,)0 3824 y(then)g(it)h(will)g(stop)f(reading)h(the)f(template)i(\014le)e(and)g (it)h(will)g(return)e(with)h(an)g(error.)0 4158 y Ff(11.6)136 b(Examples)0 4408 y Fj(1.)54 b(This)34 b(template)i(\014le)f(will)g (create)h(a)f(200)h(x)e(300)i(pixel)f(image,)j(with)c(4-b)m(yte)i(in)m (teger)g(pixel)f(v)-5 b(alues,)36 b(in)f(the)0 4521 y(primary)29 b(HDU:)95 4779 y Fe(SIMPLE)47 b(=)g(T)95 4891 y(BITPIX)g(=)g(32)95 5004 y(NAXIS)g(=)g(2)239 b(/)47 b(number)f(of)h(dimensions)95 5117 y(NAXIS1)g(=)g(100)95 b(/)47 b(length)f(of)h(first)g(axis)95 5230 y(NAXIS2)g(=)g(200)95 b(/)47 b(length)f(of)h(second)f(axis)95 5343 y(OBJECT)h(=)g(NGC)g(253)g(/)g(name)g(of)g(observed)f(object)0 5601 y Fj(The)35 b(allo)m(w)m(ed)i(v)-5 b(alues)36 b(of)f(BITPIX)g(are) h(8,)h(16,)h(32,)g(-32,)g(or)d(-64,)j(represen)m(ting,)f(resp)s(ectiv)m (ely)-8 b(,)39 b(8-bit)d(in)m(teger,)0 5714 y(16-bit)c(in)m(teger,)g (32-bit)f(in)m(teger,)h(32-bit)g(\015oating)f(p)s(oin)m(t,)g(or)f(64)h (bit)g(\015oating)g(p)s(oin)m(t)f(pixels.)p eop end %%Page: 165 173 TeXDict begin 165 172 bop 0 299 a Fh(11.6.)73 b(EXAMPLES)2993 b Fj(165)0 555 y(2.)39 b(T)-8 b(o)23 b(create)h(a)f(FITS)e(table,)26 b(the)c(template)i(\014rst)e(needs)g(to)i(include)e(XTENSION)g(=)g(T)-8 b(ABLE)23 b(or)f(BINT)-8 b(ABLE)0 668 y(to)31 b(de\014ne)e(whether)g (it)h(is)g(an)f(ASCI)s(I)g(or)g(binary)g(table,)i(and)f(NAXIS2)g(to)g (de\014ne)f(the)h(n)m(um)m(b)s(er)f(of)h(ro)m(ws)f(in)h(the)0 781 y(table.)50 b(Tw)m(o)34 b(template)g(lines)g(are)g(then)f(needed)f (to)i(de\014ne)f(the)g(name)h(\(TTYPEn\))e(and)h(FITS)g(data)h(format)0 894 y(\(TF)m(ORMn\))d(of)f(the)h(columns,)f(as)h(in)f(this)g(example:) 95 1154 y Fe(xtension)46 b(=)h(bintable)95 1267 y(naxis2)g(=)g(40)95 1380 y(ttype#)g(=)g(Name)95 1492 y(tform#)g(=)g(10a)95 1605 y(ttype#)g(=)g(Npoints)95 1718 y(tform#)g(=)g(j)95 1831 y(ttype#)g(=)g(Rate)95 1944 y(tunit#)g(=)g(counts/s)95 2057 y(tform#)g(=)g(e)0 2317 y Fj(The)26 b(ab)s(o)m(v)m(e)j(example)e (de\014nes)f(a)i(n)m(ull)f(primary)f(arra)m(y)h(follo)m(w)m(ed)i(b)m(y) e(a)g(40-ro)m(w)h(binary)e(table)i(extension)g(with)f(3)0 2430 y(columns)h(called)h('Name',)h('Np)s(oin)m(ts',)f(and)f('Rate',)i (with)e(data)h(formats)f(of)g('10A')i(\(ASCI)s(I)d(c)m(haracter)i (string\),)0 2543 y('1J')k(\(in)m(teger\))i(and)d('1E')i(\(\015oating)f (p)s(oin)m(t\),)h(resp)s(ectiv)m(ely)-8 b(.)50 b(Note)34 b(that)f(the)g(other)g(required)f(FITS)g(k)m(eyw)m(ords)0 2655 y(\(BITPIX,)37 b(NAXIS,)g(NAXIS1,)h(PCOUNT,)e(GCOUNT,)h(TFIELDS,)f (and)g(END\))h(do)g(not)g(need)f(to)h(b)s(e)f(ex-)0 2768 y(plicitly)j(de\014ned)d(in)i(the)f(template)i(b)s(ecause)f(their)g(v) -5 b(alues)38 b(can)g(b)s(e)f(inferred)f(from)i(the)f(other)h(k)m(eyw)m (ords)g(in)0 2881 y(the)d(template.)55 b(This)34 b(example)i(also)g (illustrates)f(that)h(the)f(templates)h(are)f(generally)h (case-insensitiv)m(e)h(\(the)0 2994 y(k)m(eyw)m(ord)29 b(names)g(and)g(TF)m(ORMn)f(v)-5 b(alues)30 b(are)f(con)m(v)m(erted)i (to)e(upp)s(er-case)g(in)f(the)h(FITS)g(\014le\))g(and)f(that)i(string) 0 3107 y(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(generally)g(do)f(not)h(need) f(to)h(b)s(e)f(enclosed)h(in)f(quotes.)p eop end %%Page: 166 174 TeXDict begin 166 173 bop 0 299 a Fj(166)2250 b Fh(CHAPTER)29 b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)p eop end %%Page: 167 175 TeXDict begin 167 174 bop 0 1225 a Fg(Chapter)65 b(12)0 1687 y Fm(Lo)6 b(cal)78 b(FITS)e(Con)-6 b(v)g(en)g(tions)0 2180 y Fj(CFITSIO)29 b(supp)s(orts)g(sev)m(eral)j(lo)s(cal)g(FITS)e (con)m(v)m(en)m(tions)i(whic)m(h)f(are)g(not)g(de\014ned)e(in)i(the)f (o\016cial)j(FITS)d(stan-)0 2293 y(dard)43 b(and)g(whic)m(h)g(are)h (not)g(necessarily)g(recognized)h(or)f(supp)s(orted)e(b)m(y)h(other)h (FITS)f(soft)m(w)m(are)i(pac)m(k)-5 b(ages.)0 2406 y(Programmers)36 b(should)f(b)s(e)g(cautious)i(ab)s(out)e(using)h(these)g(features,)i (esp)s(ecially)f(if)f(the)g(FITS)f(\014les)h(that)h(are)0 2518 y(pro)s(duced)31 b(are)i(exp)s(ected)g(to)g(b)s(e)f(pro)s(cessed)g (b)m(y)h(other)f(soft)m(w)m(are)i(systems)f(whic)m(h)f(do)h(not)f(use)h (the)f(CFITSIO)0 2631 y(in)m(terface.)0 2990 y Ff(12.1)136 b(64-Bit)45 b(Long)g(In)l(tegers)0 3246 y Fj(CFITSIO)37 b(supp)s(orts)g(reading)i(and)f(writing)h(FITS)f(images)i(or)f(table)h (columns)e(con)m(taining)i(64-bit)h(in)m(teger)0 3359 y(data)26 b(v)-5 b(alues.)40 b(Supp)s(ort)23 b(for)i(64-bit)i(in)m (tegers)g(w)m(as)f(added)e(to)j(the)e(o\016cial)i(FITS)e(Standard)f(in) i(Decem)m(b)s(er)g(2005.)0 3472 y(FITS)g(64-bit)i(images)g(ha)m(v)m(e)g (BITPIX)e(=)h(64,)h(and)e(the)h(64-bit)h(binary)e(table)i(columns)f(ha) m(v)m(e)h(TF)m(ORMn)e(=)h('K'.)0 3584 y(CFITSIO)35 b(also)i(supp)s (orts)e(the)i('Q')f(v)-5 b(ariable-length)38 b(arra)m(y)f(table)h (column)e(format)h(whic)m(h)f(is)g(analogous)i(to)0 3697 y(the)31 b('P')f(column)g(format)h(except)g(that)g(the)g(arra)m(y)g (descriptor)f(is)h(stored)f(as)h(a)f(pair)h(of)f(64-bit)i(in)m(tegers.) 0 3858 y(F)-8 b(or)33 b(the)f(con)m(v)m(enience)i(of)f(C)e (programmers,)h(the)h(\014tsio.h)f(include)g(\014le)g(de\014nes)f (\(with)h(a)h(t)m(yp)s(edef)f(statemen)m(t\))0 3970 y(the)39 b('LONGLONG')g(datat)m(yp)s(e)h(to)f(b)s(e)f(equiv)-5 b(alen)m(t)40 b(to)f(an)g(appropriate)g(64-bit)h(in)m(teger)g(datat)m (yp)s(e)f(on)g(eac)m(h)0 4083 y(platform.)g(Since)27 b(there)f(is)g(curren)m(tly)g(no)g(univ)m(ersal)h(standard)e(for)h(the) g(name)g(of)h(the)f(64-bit)h(in)m(teger)h(datat)m(yp)s(e)0 4196 y(\(it)33 b(migh)m(t)f(b)s(e)f(de\014ned)g(as)h('long)g(long',)i ('long',)f(or)f(')p 1832 4196 28 4 v 1865 4196 V 66 w(in)m(t64')h(dep)s (ending)d(on)i(the)g(platform\))g(C)g(programmers)0 4309 y(ma)m(y)24 b(prefer)f(to)i(use)e(the)h('LONGLONG')h(datat)m(yp)s(e)f (when)f(declaring)i(or)e(allo)s(cating)j(64-bit)f(in)m(teger)h(quan)m (tities)0 4422 y(when)33 b(writing)h(co)s(de)g(whic)m(h)f(needs)h(to)h (run)d(on)i(m)m(ultiple)g(platforms.)52 b(Note)35 b(that)f(CFITSIO)f (will)h(implicitly)0 4535 y(con)m(v)m(ert)h(the)e(datat)m(yp)s(e)h (when)f(reading)g(or)g(writing)h(FITS)e(64-bit)j(in)m(teger)f(images)h (and)d(columns)h(with)g(data)0 4648 y(arra)m(ys)40 b(of)h(a)f (di\013eren)m(t)h(in)m(teger)g(or)f(\015oating)h(p)s(oin)m(t)f(datat)m (yp)s(e,)k(but)c(there)g(is)g(an)g(increased)g(risk)g(of)g(loss)h(of)0 4761 y(n)m(umerical)31 b(precision)f(or)h(n)m(umerical)g(o)m(v)m (er\015o)m(w)h(in)e(this)g(case.)0 5120 y Ff(12.2)136 b(Long)44 b(String)i(Keyw)l(ord)f(V)-11 b(alues.)0 5375 y Fj(The)43 b(length)i(of)f(a)g(standard)g(FITS)f(string)h(k)m(eyw)m (ord)g(is)g(limited)h(to)g(68)f(c)m(haracters)i(b)s(ecause)e(it)g(m)m (ust)g(\014t)0 5488 y(en)m(tirely)35 b(within)e(a)h(single)h(FITS)e (header)g(k)m(eyw)m(ord)i(record.)50 b(In)33 b(some)i(instances)f(it)g (is)g(necessary)g(to)h(enco)s(de)0 5601 y(strings)29 b(longer)i(than)e(this)g(limit,)i(so)f(CFITSIO)e(supp)s(orts)g(a)h(lo)s (cal)i(con)m(v)m(en)m(tion)h(in)d(whic)m(h)h(the)f(string)h(v)-5 b(alue)30 b(is)0 5714 y(con)m(tin)m(ued)36 b(o)m(v)m(er)g(m)m(ultiple)f (k)m(eyw)m(ords.)55 b(This)34 b(con)m(tin)m(uation)i(con)m(v)m(en)m (tion)h(uses)e(an)f(amp)s(ersand)g(c)m(haracter)i(at)1882 5942 y(167)p eop end %%Page: 168 176 TeXDict begin 168 175 bop 0 299 a Fj(168)1741 b Fh(CHAPTER)30 b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)0 555 y Fj(the)c(end)f(of)h (eac)m(h)g(substring)f(to)h(indicate)h(that)f(it)h(is)e(con)m(tin)m (ued)i(on)e(the)h(next)g(k)m(eyw)m(ord,)h(and)e(the)h(con)m(tin)m (uation)0 668 y(k)m(eyw)m(ords)40 b(all)h(ha)m(v)m(e)g(the)f(name)g (CONTINUE)f(without)h(an)g(equal)g(sign)g(in)g(column)g(9.)69 b(The)40 b(string)f(v)-5 b(alue)0 781 y(ma)m(y)33 b(b)s(e)f(con)m(tin)m (ued)h(in)g(this)f(w)m(a)m(y)h(o)m(v)m(er)h(as)f(man)m(y)g(additional)g (CONTINUE)f(k)m(eyw)m(ords)h(as)f(is)h(required.)46 b(The)0 894 y(follo)m(wing)37 b(lines)e(illustrate)h(this)f(con)m(tin)m(uation) i(con)m(v)m(en)m(tion)h(whic)m(h)c(is)i(used)e(in)h(the)g(v)-5 b(alue)36 b(of)f(the)g(STRKEY)0 1007 y(k)m(eyw)m(ord:)0 1297 y Fe(LONGSTRN=)45 b('OGIP)i(1.0')189 b(/)48 b(The)f(OGIP)f(Long)h (String)f(Convention)f(may)i(be)g(used.)0 1410 y(STRKEY)94 b(=)47 b('This)g(is)g(a)g(very)g(long)g(string)f(keyword&')93 b(/)47 b(Optional)f(Comment)0 1523 y(CONTINUE)93 b(')48 b(value)e(that)h(is)g(continued)e(over)i(3)g(keywords)f(in)h(the)g(&)95 b(')0 1636 y(CONTINUE)e('FITS)47 b(header.')e(/)j(This)e(is)h(another)f (optional)g(comment.)0 1926 y Fj(It)29 b(is)g(recommended)f(that)h(the) g(LONGSTRN)f(k)m(eyw)m(ord,)i(as)f(sho)m(wn)f(here,)h(alw)m(a)m(ys)i(b) s(e)d(included)g(in)g(an)m(y)h(HDU)0 2039 y(that)i(uses)f(this)g (longstring)h(con)m(v)m(en)m(tion)i(as)e(a)f(w)m(arning)h(to)g(an)m(y)g (soft)m(w)m(are)g(that)g(m)m(ust)g(read)f(the)h(k)m(eyw)m(ords.)41 b(A)0 2152 y(routine)d(called)g(\014ts)p 712 2152 28 4 v 33 w(write)p 947 2152 V 33 w(k)m(ey)p 1113 2152 V 33 w(longw)m(arn)g(has)f(b)s(een)g(pro)m(vided)g(in)h(CFITSIO)d(to)k (write)e(this)h(k)m(eyw)m(ord)g(if)f(it)0 2265 y(do)s(es)30 b(not)h(already)g(exist.)0 2425 y(This)f(long)h(string)f(con)m(v)m(en)m (tion)i(is)f(supp)s(orted)d(b)m(y)j(the)f(follo)m(wing)i(CFITSIO)d (routines:)191 2716 y Fe(fits_write_key_longstr)89 b(-)48 b(write)e(a)i(long)e(string)g(keyword)g(value)191 2829 y(fits_insert_key_longstr)41 b(-)48 b(insert)e(a)h(long)g(string)f (keyword)g(value)191 2942 y(fits_modify_key_longstr)41 b(-)48 b(modify)e(a)h(long)g(string)f(keyword)g(value)191 3054 y(fits_update_key_longstr)41 b(-)48 b(modify)e(a)h(long)g(string)f (keyword)g(value)191 3167 y(fits_read_key_longstr)137 b(-)48 b(read)94 b(a)48 b(long)e(string)g(keyword)g(value)191 3280 y(fits_delete_key)425 b(-)48 b(delete)e(a)h(keyword)0 3571 y Fj(The)36 b(\014ts)p 320 3571 V 32 w(read)p 524 3571 V 33 w(k)m(ey)p 690 3571 V 34 w(longstr)g(routine)h(is)f(unique)f (among)i(all)h(the)e(CFITSIO)f(routines)h(in)g(that)h(it)g(in)m (ternally)0 3684 y(allo)s(cates)f(memory)d(for)h(the)f(long)h(string)g (v)-5 b(alue;)36 b(all)e(the)g(other)g(CFITSIO)e(routines)h(that)h (deal)g(with)g(arra)m(ys)0 3797 y(require)39 b(that)h(the)g(calling)h (program)e(pre-allo)s(cate)j(adequate)e(space)g(to)g(hold)f(the)h(arra) m(y)g(of)f(data.)69 b(Conse-)0 3909 y(quen)m(tly)-8 b(,)31 b(programs)f(whic)m(h)g(use)g(the)g(\014ts)p 1443 3909 V 32 w(read)p 1647 3909 V 33 w(k)m(ey)p 1813 3909 V 34 w(longstr)g(routine)g(m)m(ust)g(b)s(e)g(careful)g(to)h(free)g(the)f (allo)s(cated)0 4022 y(memory)g(for)g(the)h(string)f(when)g(it)h(is)f (no)g(longer)h(needed.)0 4183 y(The)f(follo)m(wing)i(2)e(routines)h (also)g(ha)m(v)m(e)h(limited)f(supp)s(ort)d(for)i(this)h(long)g(string) f(con)m(v)m(en)m(tion,)286 4473 y Fe(fits_modify_key_str)43 b(-)k(modify)f(an)i(existing)d(string)h(keyword)g(value)286 4586 y(fits_update_key_str)d(-)k(update)f(a)i(string)e(keyword)g(value) 0 4876 y Fj(in)24 b(that)h(they)f(will)h(correctly)g(o)m(v)m(erwrite)h (an)e(existing)h(long)g(string)f(v)-5 b(alue,)27 b(but)c(the)h(new)g (string)g(v)-5 b(alue)25 b(is)f(limited)0 4989 y(to)31 b(a)g(maxim)m(um)f(of)h(68)g(c)m(haracters)h(in)e(length.)0 5149 y(The)f(more)h(commonly)h(used)e(CFITSIO)f(routines)i(to)g(write)g (string)g(v)-5 b(alued)30 b(k)m(eyw)m(ords)g(\(\014ts)p 3254 5149 V 33 w(up)s(date)p 3563 5149 V 32 w(k)m(ey)h(and)0 5262 y(\014ts)p 127 5262 V 32 w(write)p 361 5262 V 33 w(k)m(ey\))j(do)e(not)h(supp)s(ort)d(this)i(long)h(string)g(con)m(v)m (en)m(tion)h(and)e(only)g(supp)s(ort)f(strings)h(up)f(to)i(68)g(c)m (har-)0 5375 y(acters)g(in)f(length.)48 b(This)31 b(has)h(b)s(een)g (done)g(delib)s(erately)h(to)g(prev)m(en)m(t)g(programs)f(from)g(inadv) m(erten)m(tly)i(writing)0 5488 y(k)m(eyw)m(ords)25 b(using)f(this)h (non-standard)e(con)m(v)m(en)m(tion)k(without)e(the)g(explicit)h(in)m (ten)m(t)g(of)f(the)f(programmer)h(or)f(user.)0 5601 y(The)36 b(\014ts)p 320 5601 V 32 w(write)p 554 5601 V 33 w(k)m(ey)p 720 5601 V 34 w(longstr)h(routine)f(m)m(ust)h(b)s(e)f (called)i(instead)e(to)i(write)e(long)h(strings.)59 b(This)36 b(routine)h(can)0 5714 y(also)31 b(b)s(e)f(used)g(to)h(write)f (ordinary)g(string)g(v)-5 b(alues)31 b(less)g(than)f(68)h(c)m (haracters)h(in)e(length.)p eop end %%Page: 169 177 TeXDict begin 169 176 bop 0 299 a Fh(12.3.)73 b(ARRA)-8 b(YS)30 b(OF)h(FIXED-LENGTH)g(STRINGS)e(IN)h(BINAR)-8 b(Y)32 b(T)-8 b(ABLES)871 b Fj(169)0 555 y Ff(12.3)136 b(Arra)l(ys)45 b(of)g(Fixed-Length)g(Strings)g(in)g(Binary)f(T)-11 b(ables)0 807 y Fj(CFITSIO)25 b(supp)s(orts)g(2)i(w)m(a)m(ys)g(to)g(sp) s(ecify)f(that)i(a)f(c)m(haracter)h(column)e(in)g(a)h(binary)f(table)i (con)m(tains)f(an)g(arra)m(y)g(of)0 920 y(\014xed-length)32 b(strings.)46 b(The)32 b(\014rst)f(w)m(a)m(y)-8 b(,)34 b(whic)m(h)e(is)g(o\016cially)i(supp)s(orted)c(b)m(y)i(the)h(FITS)e (Standard)g(do)s(cumen)m(t,)0 1033 y(uses)38 b(the)g(TDIMn)g(k)m(eyw)m (ord.)65 b(F)-8 b(or)39 b(example,)i(if)d(TF)m(ORMn)g(=)g('60A')h(and)f (TDIMn)g(=)g('\(12,5\)')i(then)e(that)0 1146 y(column)30 b(will)h(b)s(e)f(in)m(terpreted)g(as)h(con)m(taining)h(an)e(arra)m(y)h (of)g(5)f(strings,)h(eac)m(h)g(12)g(c)m(haracters)h(long.)0 1306 y(CFITSIO)j(also)j(supp)s(orts)c(a)j(lo)s(cal)h(con)m(v)m(en)m (tion)h(for)d(the)h(format)g(of)g(the)f(TF)m(ORMn)h(k)m(eyw)m(ord)g(v) -5 b(alue)37 b(of)g(the)0 1419 y(form)42 b('rAw')g(where)g('r')g(is)h (an)f(in)m(teger)i(sp)s(ecifying)e(the)g(total)j(width)c(in)h(c)m (haracters)i(of)f(the)f(column,)k(and)0 1532 y('w')36 b(is)g(an)g(in)m(teger)h(sp)s(ecifying)f(the)g(\(\014xed\))g(length)h (of)f(an)g(individual)f(unit)h(string)f(within)h(the)g(v)m(ector.)59 b(F)-8 b(or)0 1644 y(example,)29 b(TF)m(ORM1)f(=)f('120A10')j(w)m(ould) d(indicate)h(that)g(the)f(binary)g(table)h(column)f(is)g(120)i(c)m (haracters)f(wide)0 1757 y(and)42 b(consists)h(of)f(12)h(10-c)m (haracter)i(length)e(strings.)77 b(This)41 b(con)m(v)m(en)m(tion)k(is)d (recognized)i(b)m(y)e(the)g(CFITSIO)0 1870 y(routines)26 b(that)h(read)e(or)h(write)h(strings)e(in)h(binary)f(tables.)40 b(The)26 b(Binary)g(T)-8 b(able)27 b(de\014nition)e(do)s(cumen)m(t)h (sp)s(eci\014es)0 1983 y(that)i(other)f(optional)h(c)m(haracters)h(ma)m (y)e(follo)m(w)i(the)e(data)h(t)m(yp)s(e)f(co)s(de)g(in)g(the)g(TF)m (ORM)h(k)m(eyw)m(ord,)g(so)g(this)f(lo)s(cal)0 2096 y(con)m(v)m(en)m (tion)f(is)d(in)h(compliance)h(with)e(the)h(FITS)e(standard)h(although) h(other)g(FITS)f(readers)g(ma)m(y)h(not)g(recognize)0 2209 y(this)30 b(con)m(v)m(en)m(tion.)0 2550 y Ff(12.4)136 b(Keyw)l(ord)45 b(Units)h(Strings)0 2801 y Fj(One)37 b(limitation)j(of)d(the)h(curren)m(t)g(FITS)e(Standard)h(is)h(that)g (it)g(do)s(es)f(not)h(de\014ne)f(a)h(sp)s(eci\014c)f(con)m(v)m(en)m (tion)j(for)0 2914 y(recording)30 b(the)g(ph)m(ysical)h(units)f(of)g(a) g(k)m(eyw)m(ord)h(v)-5 b(alue.)41 b(The)30 b(TUNITn)f(k)m(eyw)m(ord)h (can)g(b)s(e)g(used)f(to)i(sp)s(ecify)f(the)0 3027 y(ph)m(ysical)36 b(units)f(of)g(the)h(v)-5 b(alues)36 b(in)f(a)g(table)i(column,)f(but)f (there)g(is)h(no)f(analogous)i(con)m(v)m(en)m(tion)g(for)e(k)m(eyw)m (ord)0 3140 y(v)-5 b(alues.)42 b(The)30 b(commen)m(t)h(\014eld)g(of)f (the)h(k)m(eyw)m(ord)g(is)g(often)g(used)f(for)g(this)g(purp)s(ose,)g (but)f(the)i(units)f(are)h(usually)0 3253 y(not)g(sp)s(eci\014ed)e(in)h (a)h(w)m(ell)g(de\014ned)f(format)g(that)h(FITS)f(readers)g(can)h (easily)g(recognize)h(and)e(extract.)0 3413 y(T)-8 b(o)27 b(solv)m(e)i(this)d(problem,)i(CFITSIO)d(uses)i(a)g(lo)s(cal)h(con)m(v) m(en)m(tion)h(in)e(whic)m(h)f(the)i(k)m(eyw)m(ord)f(units)f(are)i (enclosed)f(in)0 3526 y(square)20 b(brac)m(k)m(ets)j(as)e(the)f (\014rst)g(tok)m(en)i(in)f(the)f(k)m(eyw)m(ord)i(commen)m(t)f(\014eld;) j(more)d(sp)s(eci\014cally)-8 b(,)24 b(the)d(op)s(ening)f(square)0 3639 y(brac)m(k)m(et)28 b(immediately)g(follo)m(ws)f(the)g(slash)f('/') h(commen)m(t)h(\014eld)e(delimiter)h(and)f(a)g(single)h(space)g(c)m (haracter.)41 b(The)0 3752 y(follo)m(wing)32 b(examples)f(illustrate)g (k)m(eyw)m(ords)g(that)g(use)f(this)g(con)m(v)m(en)m(tion:)0 4018 y Fe(EXPOSURE=)713 b(1800.0)47 b(/)g([s])g(elapsed)f(exposure)f (time)0 4131 y(V_HELIO)h(=)763 b(16.23)47 b(/)g([km)g(s**\(-1\)])e (heliocentric)g(velocity)0 4244 y(LAMBDA)94 b(=)763 b(5400.)47 b(/)g([angstrom])e(central)h(wavelength)0 4357 y(FLUX)190 b(=)47 b(4.9033487787637465E-30)42 b(/)47 b([J/cm**2/s])e(average)h (flux)0 4622 y Fj(In)28 b(general,)h(the)g(units)e(named)h(in)g(the)h (IA)m(U\(1988\))i(St)m(yle)e(Guide)f(are)h(recommended,)f(with)g(the)h (main)f(excep-)0 4735 y(tion)j(that)g(the)f(preferred)g(unit)f(for)i (angle)g(is)f('deg')i(for)e(degrees.)0 4896 y(The)38 b(\014ts)p 322 4896 28 4 v 33 w(read)p 527 4896 V 33 w(k)m(ey)p 693 4896 V 33 w(unit)h(and)f(\014ts)p 1234 4896 V 32 w(write)p 1468 4896 V 33 w(k)m(ey)p 1634 4896 V 34 w(unit)g(routines)h(in)g(CFITSIO)e(read)i(and)f(write,)k(resp)s (ectiv)m(ely)-8 b(,)0 5008 y(the)31 b(k)m(eyw)m(ord)f(unit)g(strings)h (in)f(an)g(existing)h(k)m(eyw)m(ord.)0 5349 y Ff(12.5)136 b(HIERAR)l(CH)46 b(Con)l(v)l(en)l(tion)g(for)f(Extended)h(Keyw)l(ord)f (Names)0 5601 y Fj(CFITSIO)c(supp)s(orts)g(the)i(HIERAR)m(CH)g(k)m(eyw) m(ord)g(con)m(v)m(en)m(tion)i(whic)m(h)e(allo)m(ws)h(k)m(eyw)m(ord)f (names)g(that)h(are)0 5714 y(longer)35 b(than)f(8)h(c)m(haracters.)54 b(This)34 b(con)m(v)m(en)m(tion)i(w)m(as)f(dev)m(elop)s(ed)g(at)g(the)g (Europ)s(ean)e(Southern)g(Observ)-5 b(atory)p eop end %%Page: 170 178 TeXDict begin 170 177 bop 0 299 a Fj(170)1741 b Fh(CHAPTER)30 b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)0 555 y Fj(\(ESO\))k(and)g (allo)m(ws)h(c)m(haracters)h(consisting)f(of)f(digits)h(0-9,)i(upp)s (er)32 b(case)j(letters)h(A-Z,)e(the)h(dash)e('-')i(and)f(the)0 668 y(underscore)j(')p 493 668 28 4 v 33 w('.)63 b(The)37 b(comp)s(onen)m(ts)h(of)g(hierarc)m(hical)h(k)m(eyw)m(ords)f(are)g (separated)g(b)m(y)g(a)g(single)g(ASCI)s(I)e(space)0 781 y(c)m(harater.)42 b(F)-8 b(or)31 b(instance:)0 1038 y Fe(HIERARCH)46 b(ESO)g(INS)h(FOCU)g(POS)g(=)g(-0.00002500)e(/)j (Focus)e(position)0 1295 y Fj(Basically)-8 b(,)42 b(this)c(con)m(v)m (en)m(tion)h(uses)f(the)f(FITS)g(k)m(eyw)m(ord)h('HIERAR)m(CH')g(to)h (indicate)f(that)g(this)g(con)m(v)m(en)m(tion)0 1408 y(is)j(b)s(eing)f(used,)j(then)d(the)h(actual)h(k)m(eyw)m(ord)f(name)g (\()p Fe('ESO)47 b(INS)g(FOCU)g(POS')39 b Fj(in)i(this)f(example\))i(b) s(egins)e(in)0 1521 y(column)h(10.)74 b(The)41 b(equals)g(sign)g(marks) g(the)g(end)g(of)g(the)h(k)m(eyw)m(ord)f(name)g(and)g(is)g(follo)m(w)m (ed)i(b)m(y)e(the)g(usual)0 1634 y(v)-5 b(alue)37 b(and)e(commen)m(t)j (\014elds)e(just)f(as)i(in)f(standard)f(FITS)h(k)m(eyw)m(ords.)59 b(F)-8 b(urther)36 b(details)h(of)g(this)f(con)m(v)m(en)m(tion)0 1747 y(are)30 b(describ)s(ed)f(at)i(h)m(ttp://\014ts.gsfc.nasa.go)m (v/registry/hierarc)m(h)p 2323 1747 V 38 w(k)m(eyw)m(ord.h)m(tml)g(and) f(in)g(Section)g(4.4)i(of)e(the)0 1859 y(ESO)40 b(Data)i(In)m(terface)g (Con)m(trol)g(Do)s(cumen)m(t)g(that)f(is)g(link)m(ed)g(to)h(from)e(h)m (ttp://arc)m(hiv)m(e.eso.org/cms/to)t(ols-)0 1972 y(do)s(cumen)m (tation/eso-data-in)m(terface-con)m(t)q(rol.h)m(tml.)0 2133 y(This)32 b(con)m(v)m(en)m(tion)i(allo)m(ws)g(a)f(broader)f(range) h(of)g(k)m(eyw)m(ord)f(names)h(than)f(is)h(allo)m(w)m(ed)h(b)m(y)e(the) h(FITS)f(Standard.)0 2245 y(Here)f(are)g(more)f(examples)h(of)g(suc)m (h)f(k)m(eyw)m(ords:)0 2502 y Fe(HIERARCH)46 b(LONGKEYWORD)e(=)k(47.5)e (/)i(Keyword)e(has)h(>)g(8)g(characters)0 2615 y(HIERARCH)f (LONG-KEY_WORD2)d(=)48 b(52.3)f(/)g(Long)g(keyword)e(with)i(hyphen,)f (underscore)f(and)i(digit)0 2728 y(HIERARCH)f(EARTH)g(IS)h(A)h(STAR)e (=)i(F)f(/)h(Keyword)d(contains)h(embedded)f(spaces)0 2985 y Fj(CFITSIO)40 b(will)i(transparen)m(tly)g(read)g(and)f(write)g (these)i(k)m(eyw)m(ords,)i(so)d(application)h(programs)e(do)g(not)h(in) 0 3098 y(general)33 b(need)f(to)h(kno)m(w)f(an)m(ything)h(ab)s(out)f (the)g(sp)s(eci\014c)g(implemen)m(tation)i(details)f(of)g(the)f(HIERAR) m(CH)g(con-)0 3211 y(v)m(en)m(tion.)50 b(In)32 b(particular,)j (application)f(programs)e(do)h(not)h(need)e(to)i(sp)s(ecify)f(the)g (`HIERAR)m(CH')h(part)f(of)g(the)0 3324 y(k)m(eyw)m(ord)g(name)f(when)g (reading)g(or)g(writing)h(k)m(eyw)m(ords)f(\(although)h(it)g(ma)m(y)g (b)s(e)f(included)f(if)i(desired\).)46 b(When)0 3437 y(writing)35 b(a)g(k)m(eyw)m(ord,)h(CFITSIO)d(\014rst)h(c)m(hec)m(ks)i (to)f(see)g(if)g(the)g(k)m(eyw)m(ord)g(name)f(is)h(legal)h(as)f(a)g (standard)f(FITS)0 3550 y(k)m(eyw)m(ord)k(\(no)g(more)f(than)h(8)g(c)m (haracters)h(long)f(and)f(con)m(taining)i(only)e(letters,)k(digits,)f (or)e(a)g(min)m(us)e(sign)i(or)0 3663 y(underscore\).)68 b(If)39 b(so)h(it)g(writes)g(it)g(as)f(a)h(standard)f(FITS)g(k)m(eyw)m (ord,)k(otherwise)d(it)g(uses)f(the)h(hierarc)m(h)f(con-)0 3776 y(v)m(en)m(tion)34 b(to)f(write)g(the)f(k)m(eyw)m(ord.)48 b(The)32 b(maxim)m(um)g(k)m(eyw)m(ord)h(name)f(length)h(is)g(67)g(c)m (haracters,)i(whic)m(h)d(lea)m(v)m(es)0 3888 y(only)c(1)h(space)g(for)f (the)h(v)-5 b(alue)29 b(\014eld.)39 b(A)29 b(more)f(practical)i(limit)f (is)g(ab)s(out)f(40)h(c)m(haracters,)i(whic)m(h)d(lea)m(v)m(es)i (enough)0 4001 y(ro)s(om)e(for)h(most)f(k)m(eyw)m(ord)h(v)-5 b(alues.)41 b(CFITSIO)27 b(returns)g(an)h(error)h(if)f(there)h(is)f (not)h(enough)f(ro)s(om)h(for)f(b)s(oth)g(the)0 4114 y(k)m(eyw)m(ord)k(name)f(and)f(the)i(k)m(eyw)m(ord)f(v)-5 b(alue)32 b(on)f(the)h(80-c)m(haracter)h(card,)f(except)g(for)f (string-v)-5 b(alued)32 b(k)m(eyw)m(ords)0 4227 y(whic)m(h)f(are)h (simply)e(truncated)i(so)f(that)h(the)f(closing)i(quote)f(c)m(haracter) h(falls)e(in)g(column)g(80.)45 b(A)31 b(space)h(is)f(also)0 4340 y(required)f(on)g(either)h(side)f(of)h(the)f(equal)h(sign.)0 4673 y Ff(12.6)136 b(Tile-Compressed)46 b(Image)g(F)-11 b(ormat)0 4924 y Fj(CFITSIO)36 b(supp)s(orts)f(a)j(con)m(v)m(en)m(tion) i(for)d(compressing)h(n-dimensional)f(images)h(and)f(storing)h(the)g (resulting)0 5036 y(b)m(yte)i(stream)g(in)f(a)h(v)-5 b(ariable-length)41 b(column)e(in)g(a)h(FITS)f(binary)f(table.)69 b(The)39 b(general)i(principle)e(used)f(in)0 5149 y(this)c(con)m(v)m (en)m(tion)j(is)d(to)h(\014rst)f(divide)g(the)h(n-dimensional)f(image)i (in)m(to)f(a)g(rectangular)g(grid)f(of)h(subimages)f(or)0 5262 y(`tiles'.)57 b(Eac)m(h)35 b(tile)i(is)e(then)g(compressed)g(as)g (a)h(con)m(tin)m(uous)g(blo)s(c)m(k)f(of)h(data,)h(and)e(the)g (resulting)g(compressed)0 5375 y(b)m(yte)i(stream)h(is)f(stored)g(in)f (a)h(ro)m(w)g(of)g(a)h(v)-5 b(ariable)37 b(length)g(column)g(in)g(a)g (FITS)f(binary)g(table.)61 b(By)37 b(dividing)0 5488 y(the)j(image)g(in)m(to)g(tiles)h(it)f(is)f(generally)i(p)s(ossible)e (to)h(extract)h(and)d(uncompress)g(subsections)i(of)f(the)h(image)0 5601 y(without)d(ha)m(ving)h(to)g(uncompress)e(the)h(whole)g(image.)62 b(The)37 b(default)g(tiling)h(pattern)g(treats)g(eac)m(h)g(ro)m(w)f(of) h(a)0 5714 y(2-dimensional)e(image)g(\(or)f(higher)f(dimensional)h(cub) s(e\))g(as)g(a)g(tile,)j(suc)m(h)c(that)i(eac)m(h)g(tile)g(con)m(tains) g(NAXIS1)p eop end %%Page: 171 179 TeXDict begin 171 178 bop 0 299 a Fh(12.6.)73 b(TILE-COMPRESSED)28 b(IMA)m(GE)j(F)m(ORMA)-8 b(T)1838 b Fj(171)0 555 y(pixels)29 b(\(except)h(the)f(default)g(with)g(the)g(HCOMPRESS)e(algorithm)j(is)f (to)h(compress)f(the)g(whole)g(2D)h(image)g(as)0 668 y(a)35 b(single)g(tile\).)56 b(An)m(y)34 b(other)h(rectangular)h (tiling)g(pattern)f(ma)m(y)g(also)h(b)s(e)e(de\014ned.)52 b(In)34 b(the)h(case)h(of)f(relativ)m(ely)0 781 y(small)25 b(images)h(it)f(ma)m(y)g(b)s(e)f(su\016cien)m(t)h(to)h(compress)e(the)h (en)m(tire)g(image)h(as)f(a)g(single)h(tile,)h(resulting)d(in)h(an)f (output)0 894 y(binary)29 b(table)i(with)f(1)g(ro)m(w.)41 b(In)29 b(the)h(case)h(of)f(3-dimensional)h(data)g(cub)s(es,)e(it)i(ma) m(y)f(b)s(e)f(adv)-5 b(an)m(tageous)32 b(to)f(treat)0 1007 y(eac)m(h)i(plane)f(of)g(the)g(cub)s(e)f(as)h(a)g(separate)h(tile) g(if)f(application)h(soft)m(w)m(are)h(t)m(ypically)f(needs)f(to)g (access)i(the)e(cub)s(e)0 1120 y(on)e(a)h(plane)f(b)m(y)h(plane)f (basis.)0 1280 y(See)41 b(section)g(5.6)h(\\Image)f(Compression")f(for) g(more)h(information)g(on)f(using)g(this)g(tile-compressed)i(image)0 1393 y(format.)p eop end %%Page: 172 180 TeXDict begin 172 179 bop 0 299 a Fj(172)1741 b Fh(CHAPTER)30 b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)p eop end %%Page: 173 181 TeXDict begin 173 180 bop 0 1225 a Fg(Chapter)65 b(13)0 1687 y Fm(Optimizing)76 b(Programs)0 2180 y Fj(CFITSIO)22 b(has)h(b)s(een)f(carefully)i(designed)f(to)h(obtain)g(the)f(highest)h (p)s(ossible)e(sp)s(eed)h(when)f(reading)h(and)g(writing)0 2293 y(FITS)33 b(\014les.)51 b(In)33 b(order)h(to)g(ac)m(hiev)m(e)i (the)e(b)s(est)g(p)s(erformance,)g(ho)m(w)m(ev)m(er,)i(application)g (programmers)d(m)m(ust)h(b)s(e)0 2406 y(careful)24 b(to)h(call)g(the)f (CFITSIO)f(routines)g(appropriately)i(and)e(in)h(an)f(e\016cien)m(t)j (sequence;)h(inappropriate)c(usage)0 2518 y(of)31 b(CFITSIO)d(routines) j(can)f(greatly)i(slo)m(w)f(do)m(wn)f(the)h(execution)g(sp)s(eed)f(of)g (a)h(program.)0 2679 y(The)f(maxim)m(um)h(p)s(ossible)f(I/O)h(sp)s(eed) f(of)h(CFITSIO)e(dep)s(ends)g(of)i(course)g(on)f(the)h(t)m(yp)s(e)g(of) g(computer)g(system)0 2791 y(that)j(it)g(is)g(running)d(on.)50 b(T)-8 b(o)34 b(get)h(a)f(general)g(idea)g(of)g(what)f(data)i(I/O)e(sp) s(eeds)f(are)i(p)s(ossible)f(on)h(a)g(particular)0 2904 y(mac)m(hine,)j(build)e(the)g(sp)s(eed.c)g(program)g(that)h(is)g (distributed)e(with)h(CFITSIO)f(\(t)m(yp)s(e)i('mak)m(e)g(sp)s(eed')f (in)g(the)0 3017 y(CFITSIO)e(directory\).)54 b(This)33 b(diagnostic)j(program)e(measures)h(the)f(sp)s(eed)g(of)g(writing)h (and)f(reading)g(bac)m(k)i(a)0 3130 y(test)31 b(FITS)f(image,)i(a)f (binary)e(table,)j(and)d(an)i(ASCI)s(I)e(table.)0 3290 y(The)k(follo)m(wing)h(2)g(sections)g(pro)m(vide)g(some)f(bac)m (kground)g(on)h(ho)m(w)f(CFITSIO)f(in)m(ternally)i(manages)g(the)f (data)0 3403 y(I/O)g(and)g(describ)s(es)f(some)i(strategies)h(that)f (ma)m(y)g(b)s(e)e(used)h(to)h(optimize)g(the)g(pro)s(cessing)f(sp)s (eed)f(of)h(soft)m(w)m(are)0 3516 y(that)e(uses)f(CFITSIO.)0 3932 y Ff(13.1)136 b(Ho)l(w)45 b(CFITSIO)f(Manages)i(Data)g(I/O)0 4199 y Fj(Man)m(y)22 b(CFITSIO)e(op)s(erations)i(in)m(v)m(olv)m(e)i (transferring)d(only)h(a)g(small)g(n)m(um)m(b)s(er)f(of)h(b)m(ytes)g (to)g(or)g(from)f(the)h(FITS)f(\014le)0 4312 y(\(e.g,)31 b(reading)e(a)g(k)m(eyw)m(ord,)h(or)f(writing)g(a)g(ro)m(w)g(in)f(a)h (table\);)i(it)f(w)m(ould)e(b)s(e)g(v)m(ery)i(ine\016cien)m(t)g(to)f (ph)m(ysically)h(read)0 4425 y(or)i(write)h(suc)m(h)f(small)g(blo)s(c)m (ks)h(of)f(data)h(directly)g(in)f(the)g(FITS)g(\014le)g(on)g(disk,)h (therefore)f(CFITSIO)f(main)m(tains)0 4538 y(a)38 b(set)g(of)g(in)m (ternal)h(Input{Output)c(\(IO\))j(bu\013ers)f(in)g(RAM)h(memory)g(that) g(eac)m(h)h(con)m(tain)g(one)f(FITS)f(blo)s(c)m(k)0 4650 y(\(2880)27 b(b)m(ytes\))f(of)f(data.)40 b(Whenev)m(er)25 b(CFITSIO)f(needs)g(to)i(access)g(data)g(in)f(the)g(FITS)f(\014le,)j (it)e(\014rst)f(transfers)h(the)0 4763 y(FITS)30 b(blo)s(c)m(k)h(con)m (taining)h(those)f(b)m(ytes)g(in)m(to)g(one)g(of)f(the)h(IO)f (bu\013ers)f(in)h(memory)-8 b(.)42 b(The)30 b(next)g(time)h(CFITSIO)0 4876 y(needs)36 b(to)g(access)i(b)m(ytes)e(in)g(the)g(same)h(blo)s(c)m (k)f(it)h(can)f(then)g(go)h(to)f(the)h(fast)f(IO)f(bu\013er)g(rather)h (than)g(using)g(a)0 4989 y(m)m(uc)m(h)c(slo)m(w)m(er)i(system)e(disk)g (access)h(routine.)46 b(The)32 b(n)m(um)m(b)s(er)f(of)h(a)m(v)-5 b(ailable)35 b(IO)d(bu\013ers)f(is)h(determined)g(b)m(y)g(the)0 5102 y(NIOBUF)f(parameter)g(\(in)f(\014tsio2.h\))h(and)f(is)h(curren)m (tly)f(set)h(to)g(40)g(b)m(y)g(default.)0 5262 y(Whenev)m(er)24 b(CFITSIO)f(reads)g(or)h(writes)g(data)g(it)h(\014rst)e(c)m(hec)m(ks)i (to)g(see)f(if)g(that)g(blo)s(c)m(k)h(of)f(the)g(FITS)f(\014le)g(is)h (already)0 5375 y(loaded)33 b(in)m(to)g(one)f(of)g(the)g(IO)g (bu\013ers.)44 b(If)32 b(not,)h(and)e(if)h(there)g(is)g(an)g(empt)m(y)h (IO)e(bu\013er)g(a)m(v)-5 b(ailable,)35 b(then)d(it)h(will)0 5488 y(load)g(that)h(blo)s(c)m(k)f(in)m(to)g(the)g(IO)g(bu\013er)e (\(when)h(reading)h(a)g(FITS)f(\014le\))h(or)g(will)g(initialize)i(a)e (new)f(blo)s(c)m(k)i(\(when)0 5601 y(writing)j(to)h(a)g(FITS)f (\014le\).)62 b(If)37 b(all)h(the)g(IO)e(bu\013ers)h(are)g(already)h (full,)h(it)f(m)m(ust)g(decide)f(whic)m(h)g(one)h(to)g(reuse)0 5714 y(\(generally)c(the)f(one)g(that)g(has)f(b)s(een)g(accessed)i (least)f(recen)m(tly\),)i(and)d(\015ush)f(the)i(con)m(ten)m(ts)h(bac)m (k)g(to)f(disk)f(if)g(it)1882 5942 y(173)p eop end %%Page: 174 182 TeXDict begin 174 181 bop 0 299 a Fj(174)1876 b Fh(CHAPTER)30 b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)0 555 y Fj(has)h(b)s(een)g(mo)s (di\014ed)f(b)s(efore)h(loading)h(the)g(new)f(blo)s(c)m(k.)0 715 y(The)g(one)g(ma)5 b(jor)30 b(exception)i(to)f(the)f(ab)s(o)m(v)m (e)h(pro)s(cess)f(o)s(ccurs)g(whenev)m(er)g(a)g(large)i(con)m(tiguous)f (set)g(of)f(b)m(ytes)h(are)0 828 y(accessed,)37 b(as)d(migh)m(t)i(o)s (ccur)e(when)f(reading)i(or)f(writing)g(a)h(FITS)f(image.)54 b(In)34 b(this)g(case)h(CFITSIO)e(b)m(ypasses)0 941 y(the)i(in)m (ternal)h(IO)f(bu\013ers)f(and)g(simply)h(reads)g(or)g(writes)h(the)f (desired)g(b)m(ytes)g(directly)h(in)f(the)g(disk)g(\014le)g(with)0 1054 y(a)i(single)g(call)g(to)g(a)g(lo)m(w-lev)m(el)i(\014le)d(read)g (or)h(write)f(routine.)58 b(The)36 b(minim)m(um)g(threshold)f(for)h (the)h(n)m(um)m(b)s(er)e(of)0 1167 y(b)m(ytes)27 b(to)g(read)f(or)g (write)g(this)g(w)m(a)m(y)i(is)e(set)g(b)m(y)h(the)f(MINDIRECT)g (parameter)g(and)g(is)g(curren)m(tly)g(set)h(to)g(3)g(FITS)0 1280 y(blo)s(c)m(ks)36 b(=)g(8640)i(b)m(ytes.)58 b(This)35 b(is)h(the)g(most)g(e\016cien)m(t)i(w)m(a)m(y)f(to)g(read)e(or)h(write) h(large)g(c)m(h)m(unks)e(of)h(data.)59 b(Note)0 1393 y(that)34 b(this)f(fast)h(direct)g(IO)f(pro)s(cess)f(is)i(not)f (applicable)i(when)d(accessing)j(columns)e(of)h(data)g(in)f(a)g(FITS)g (table)0 1506 y(b)s(ecause)f(the)h(b)m(ytes)g(are)g(generally)g(not)g (con)m(tiguous)g(since)g(they)g(are)f(in)m(terlea)m(v)m(ed)j(b)m(y)e (the)f(other)h(columns)f(of)0 1619 y(data)i(in)e(the)h(table.)49 b(This)33 b(explains)g(wh)m(y)f(the)h(sp)s(eed)f(for)h(accessing)h (FITS)e(tables)i(is)f(generally)h(slo)m(w)m(er)g(than)0 1732 y(accessing)e(FITS)e(images.)0 1892 y(Giv)m(en)i(this)g(bac)m (kground)f(information,)h(the)g(general)g(strategy)h(for)e(e\016cien)m (tly)i(accessing)g(FITS)e(\014les)g(should)0 2005 y(b)s(e)e(apparen)m (t:)41 b(when)28 b(dealing)j(with)e(FITS)g(images,)i(read)e(or)h(write) g(large)g(c)m(h)m(unks)g(of)g(data)g(at)g(a)g(time)g(so)g(that)0 2118 y(the)25 b(direct)g(IO)f(mec)m(hanism)g(will)h(b)s(e)f(in)m(v)m (ok)m(ed;)k(when)c(accessing)i(FITS)e(headers)g(or)g(FITS)g(tables,)j (on)d(the)h(other)0 2230 y(hand,)35 b(once)g(a)g(particular)g(FITS)f (blo)s(c)m(k)i(has)e(b)s(een)g(loading)i(in)m(to)f(one)g(of)g(the)g(IO) f(bu\013ers,)h(try)g(to)g(access)h(all)0 2343 y(the)30 b(needed)g(information)g(in)g(that)g(blo)s(c)m(k)h(b)s(efore)f(it)g (gets)h(\015ushed)d(out)j(of)f(the)g(IO)f(bu\013er.)40 b(It)30 b(is)g(imp)s(ortan)m(t)g(to)0 2456 y(a)m(v)m(oid)e(the)f (situation)g(where)f(the)h(same)g(FITS)e(blo)s(c)m(k)i(is)g(b)s(eing)f (read)g(then)g(\015ushed)f(from)h(a)h(IO)f(bu\013er)f(m)m(ultiple)0 2569 y(times.)0 2729 y(The)30 b(follo)m(wing)i(section)f(giv)m(es)h (more)e(sp)s(eci\014c)h(suggestions)g(for)f(optimizing)i(the)e(use)g (of)h(CFITSIO.)0 3095 y Ff(13.2)136 b(Optimization)46 b(Strategies)0 3352 y Fj(1.)d(Because)32 b(the)f(data)g(in)g(FITS)f (\014les)h(is)g(alw)m(a)m(ys)h(stored)f(in)g("big-endian")h(b)m(yte)f (order,)g(where)f(the)h(\014rst)f(b)m(yte)0 3465 y(of)g(n)m(umeric)h(v) -5 b(alues)30 b(con)m(tains)i(the)e(most)h(signi\014can)m(t)g(bits)f (and)g(the)g(last)i(b)m(yte)e(con)m(tains)i(the)e(least)i(signi\014can) m(t)0 3578 y(bits,)e(CFITSIO)f(m)m(ust)h(sw)m(ap)g(the)g(order)f(of)h (the)h(b)m(ytes)f(when)f(reading)h(or)g(writing)g(FITS)g(\014les)g (when)f(running)0 3690 y(on)k(little-endian)i(mac)m(hines)f(\(e.g.,)i (Lin)m(ux)d(and)g(Microsoft)i(Windo)m(ws)e(op)s(erating)h(systems)g (running)d(on)j(PCs)0 3803 y(with)c(x86)h(CPUs\).)0 3963 y(On)21 b(relativ)m(ely)k(new)d(CPUs)g(that)h(supp)s(ort)d("SSSE3")i (mac)m(hine)h(instructions)f(\(e.g.,)k(starting)d(with)f(In)m(tel)h (Core)g(2)0 4076 y(CPUs)e(in)h(2007,)j(and)d(in)f(AMD)i(CPUs)e(b)s (eginning)g(in)h(2011\))i(signi\014can)m(tly)f(faster)f(4-b)m(yte)h (and)e(8-b)m(yte)i(sw)m(apping)0 4189 y(algorithms)k(are)g(a)m(v)-5 b(ailable.)42 b(These)26 b(faster)h(b)m(yte)g(sw)m(apping)f(functions)g (are)h(not)g(used)e(b)m(y)i(default)f(in)g(CFITSIO)0 4302 y(\(b)s(ecause)33 b(of)g(p)s(oten)m(tial)h(co)s(de)f(p)s (ortablilit)m(y)h(issues\),)g(but)e(users)g(can)h(enable)g(them)f(on)h (supp)s(orted)e(platforms)0 4415 y(b)m(y)38 b(adding)f(the)h (appropriate)f(compiler)i(\015ags)e(\(-mssse3)i(with)e(gcc)i(or)f(icc)g (on)g(lin)m(ux\))g(when)e(compiling)j(the)0 4528 y(sw)m(appro)s(c.c)30 b(source)g(\014le,)g(whic)m(h)g(will)g(allo)m(w)i(the)e(compiler)g(to)h (generate)h(co)s(de)e(using)f(the)h(SSSE3)f(instruction)0 4641 y(set.)41 b(A)28 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(do)g (this)f(is)g(to)h(con\014gure)f(the)g(CFITSIO)f(library)h(with)g(the)g (follo)m(wing)i(command:)95 4928 y Fe(>)96 b(./configure)44 b(--enable-ssse3)0 5215 y Fj(Note,)37 b(ho)m(w)m(ev)m(er,)h(that)d(a)g (binary)f(executable)j(\014le)e(that)g(is)g(created)h(using)e(these)h (faster)g(functions)g(will)g(only)0 5328 y(run)29 b(on)h(mac)m(hines)h (that)g(supp)s(ort)e(the)h(SSSE3)f(mac)m(hine)i(instructions.)0 5488 y(F)-8 b(or)36 b(faster)f(2-b)m(yte)i(sw)m(aps)e(on)g(virtually)g (all)h(x86-64)h(CPUs)e(\(ev)m(en)h(those)g(that)f(do)g(not)h(supp)s (ort)d(SSSE3\),)j(a)0 5601 y(v)-5 b(arian)m(t)26 b(using)e(only)g(SSE2) g(instructions)h(exists.)39 b(SSE2)24 b(is)h(enabled)f(b)m(y)h(default) g(on)f(x86)p 3066 5601 28 4 v 34 w(64)h(CPUs)f(with)h(64-bit)0 5714 y(op)s(erating)30 b(systems)f(\(and)g(is)g(also)i(automatically)h (enabled)d(b)m(y)g(the)g({enable-ssse3)i(\015ag\).)41 b(When)30 b(running)d(on)p eop end %%Page: 175 183 TeXDict begin 175 182 bop 0 299 a Fh(13.2.)73 b(OPTIMIZA)-8 b(TION)29 b(STRA)-8 b(TEGIES)2186 b Fj(175)0 555 y(x86)p 143 555 28 4 v 34 w(64)31 b(CPUs)g(with)f(32-bit)i(op)s(erating)g (systems,)f(these)g(faster)h(2-b)m(yte)g(sw)m(apping)f(algorithms)g (are)h(not)f(used)0 668 y(b)m(y)f(default)h(in)f(CFITSIO,)f(but)h(can)g (b)s(e)g(enabled)g(explicitly)i(with:)0 951 y Fe(./configure)45 b(--enable-sse2)0 1234 y Fj(Preliminary)f(testing)h(indicates)g(that)g (these)f(SSSE3)f(and)g(SSE2)g(based)h(b)m(yte-sw)m(apping)h(algorithms) g(can)0 1347 y(b)s(o)s(ost)31 b(the)h(CFITSIO)e(p)s(erformance)h(when)f (reading)i(or)f(writing)h(FITS)f(images)h(b)m(y)g(20\045)g(-)g(30\045)g (or)f(more.)45 b(It)0 1460 y(is)36 b(imp)s(ortan)m(t)g(to)g(note,)i(ho) m(w)m(ev)m(er,)h(that)d(compiler)g(optimization)i(m)m(ust)e(b)s(e)f (turned)f(on)i(\(e.g.,)j(b)m(y)d(using)f(the)0 1573 y(-O1)f(or)g(-O2)g (\015ags)g(in)g(gcc\))h(when)e(building)g(programs)h(that)g(use)g (these)g(fast)g(b)m(yte-sw)m(apping)h(algorithms)f(in)0 1686 y(order)d(to)h(reap)f(the)h(full)f(b)s(ene\014t)g(of)g(the)h (SSSE3)e(and)h(SSE2)g(instructions;)h(without)f(optimization,)j(the)e (co)s(de)0 1799 y(ma)m(y)f(actually)h(run)d(slo)m(w)m(er)i(than)f(when) g(using)g(more)g(traditional)i(b)m(yte-sw)m(apping)f(tec)m(hniques.)0 1959 y(2.)54 b(When)34 b(dealing)h(with)g(a)g(FITS)e(primary)h(arra)m (y)h(or)g(IMA)m(GE)g(extension,)i(it)e(is)f(more)h(e\016cien)m(t)h(to)f (read)g(or)0 2072 y(write)c(large)g(c)m(h)m(unks)f(of)g(the)h(image)g (at)h(a)e(time)h(\(at)h(least)f(3)g(FITS)f(blo)s(c)m(ks)g(=)g(8640)i(b) m(ytes\))f(so)g(that)g(the)f(direct)0 2185 y(IO)j(mec)m(hanism)h(will)f (b)s(e)g(used)g(as)g(describ)s(ed)g(in)g(the)g(previous)g(section.)51 b(Smaller)34 b(c)m(h)m(unks)f(of)g(data)h(are)g(read)0 2298 y(or)d(written)g(via)h(the)f(IO)f(bu\013ers,)g(whic)m(h)h(is)g (somewhat)g(less)g(e\016cien)m(t)i(b)s(ecause)e(of)g(the)g(extra)h(cop) m(y)f(op)s(eration)0 2411 y(and)26 b(additional)h(b)s(o)s(okk)m(eeping) g(steps)g(that)g(are)g(required.)39 b(In)26 b(principle)g(it)h(is)g (more)f(e\016cien)m(t)i(to)g(read)e(or)h(write)0 2524 y(as)i(big)g(an)g(arra)m(y)h(of)f(image)h(pixels)f(at)h(one)f(time)g (as)h(p)s(ossible,)f(ho)m(w)m(ev)m(er,)h(if)f(the)h(arra)m(y)f(b)s (ecomes)g(so)g(large)h(that)0 2636 y(the)i(op)s(erating)g(system)f (cannot)h(store)g(it)g(all)h(in)e(RAM,)h(then)f(the)h(p)s(erformance)f (ma)m(y)h(b)s(e)f(degraded)g(b)s(ecause)0 2749 y(of)g(the)f(increased)h (sw)m(apping)f(of)g(virtual)h(memory)f(to)h(disk.)0 2910 y(3.)51 b(When)33 b(dealing)i(with)e(FITS)g(tables,)j(the)e(most)g(imp) s(ortan)m(t)g(e\016ciency)g(factor)h(in)e(the)h(soft)m(w)m(are)h (design)f(is)0 3022 y(to)j(read)f(or)g(write)g(the)g(data)h(in)f(the)g (FITS)g(\014le)g(in)g(a)g(single)h(pass)f(through)f(the)h(\014le.)58 b(An)36 b(example)h(of)f(p)s(o)s(or)0 3135 y(program)g(design)h(w)m (ould)f(b)s(e)g(to)h(read)g(a)f(large,)k(3-column)d(table)g(b)m(y)g (sequen)m(tially)h(reading)f(the)f(en)m(tire)i(\014rst)0 3248 y(column,)25 b(then)f(going)h(bac)m(k)f(to)h(read)e(the)h(2nd)g (column,)h(and)e(\014nally)h(the)g(3rd)f(column;)j(this)e(ob)m(viously) g(requires)0 3361 y(3)j(passes)g(through)g(the)g(\014le)g(whic)m(h)g (could)g(triple)g(the)h(execution)g(time)g(of)f(an)g(IO)f(limited)i (program.)40 b(F)-8 b(or)27 b(small)0 3474 y(tables)k(this)f(is)h(not)f (imp)s(ortan)m(t,)h(but)f(when)f(reading)h(m)m(ulti-megab)m(yte)j (sized)e(tables)g(these)g(ine\016ciencies)h(can)0 3587 y(b)s(ecome)d(signi\014can)m(t.)41 b(The)28 b(more)h(e\016cien)m(t)h (pro)s(cedure)d(in)i(this)f(case)i(is)e(to)i(read)e(or)h(write)g(only)f (as)h(man)m(y)g(ro)m(ws)0 3700 y(of)j(the)g(table)g(as)g(will)g(\014t)g (in)m(to)g(the)g(a)m(v)-5 b(ailable)34 b(in)m(ternal)e(IO)f(bu\013ers,) h(then)f(access)i(all)f(the)g(necessary)g(columns)0 3813 y(of)f(data)h(within)e(that)i(range)f(of)g(ro)m(ws.)43 b(Then)29 b(after)j(the)f(program)g(is)g(completely)h(\014nished)e (with)g(the)i(data)f(in)0 3926 y(those)i(ro)m(ws)e(it)i(can)f(mo)m(v)m (e)i(on)e(to)g(the)h(next)f(range)g(of)g(ro)m(ws)g(that)h(will)f(\014t) g(in)g(the)g(bu\013ers,)f(con)m(tin)m(uing)i(in)f(this)0 4039 y(w)m(a)m(y)c(un)m(til)f(the)f(en)m(tire)i(\014le)f(has)f(b)s(een) g(pro)s(cessed.)39 b(By)27 b(using)f(this)h(pro)s(cedure)e(of)i (accessing)h(all)g(the)e(columns)h(of)0 4152 y(a)j(table)g(in)f (parallel)h(rather)f(than)g(sequen)m(tially)-8 b(,)32 b(eac)m(h)e(blo)s(c)m(k)g(of)g(the)f(FITS)g(\014le)g(will)g(only)h(b)s (e)e(read)i(or)f(written)0 4264 y(once.)0 4425 y(The)g(optimal)h(n)m (um)m(b)s(er)e(of)i(ro)m(ws)f(to)i(read)e(or)g(write)h(at)g(one)g(time) g(in)f(a)h(giv)m(en)g(table)h(dep)s(ends)c(on)j(the)f(width)g(of)0 4538 y(the)c(table)h(ro)m(w)f(and)f(on)h(the)g(n)m(um)m(b)s(er)e(of)i (IO)g(bu\013ers)e(that)j(ha)m(v)m(e)g(b)s(een)e(allo)s(cated)j(in)e (CFITSIO.)e(The)h(CFITSIO)0 4650 y(Iterator)h(routine)f(will)g (automatically)j(use)c(the)h(optimal-sized)i(bu\013er,)e(but)g(there)g (is)g(also)g(a)h(CFITSIO)d(routine)0 4763 y(that)31 b(will)g(return)f (the)h(optimal)h(n)m(um)m(b)s(er)d(of)i(ro)m(ws)g(for)f(a)h(giv)m(en)h (table:)43 b(\014ts)p 2629 4763 V 32 w(get)p 2781 4763 V 34 w(ro)m(wsize.)g(It)31 b(is)g(not)g(critical)h(to)0 4876 y(use)h(exactly)j(the)e(v)-5 b(alue)34 b(of)g(nro)m(ws)f(returned) f(b)m(y)i(this)g(routine,)g(as)g(long)h(as)f(one)g(do)s(es)f(not)h (exceed)h(it.)51 b(Using)0 4989 y(a)37 b(v)m(ery)g(small)g(v)-5 b(alue)37 b(ho)m(w)m(ev)m(er)h(can)f(also)g(lead)g(to)h(p)s(o)s(or)d(p) s(erformance)h(b)s(ecause)g(of)h(the)g(o)m(v)m(erhead)h(from)e(the)0 5102 y(larger)31 b(n)m(um)m(b)s(er)e(of)i(subroutine)e(calls.)0 5262 y(The)36 b(optimal)h(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(returned)f (b)m(y)i(\014ts)p 1829 5262 V 32 w(get)p 1981 5262 V 34 w(ro)m(wsize)g(is)g(v)-5 b(alid)36 b(only)g(as)h(long)g(as)f(the)h (application)0 5375 y(program)27 b(is)g(only)g(reading)h(or)f(writing)g (data)h(in)f(the)g(sp)s(eci\014ed)f(table.)41 b(An)m(y)27 b(other)g(calls)i(to)f(access)g(data)g(in)f(the)0 5488 y(table)i(header)f(w)m(ould)f(cause)i(additional)g(blo)s(c)m(ks)f(of)g (data)g(to)h(b)s(e)e(loaded)i(in)m(to)g(the)f(IO)f(bu\013ers)g (displacing)h(data)0 5601 y(from)34 b(the)h(original)h(table,)h(and)d (should)f(b)s(e)h(a)m(v)m(oided)i(during)e(the)h(critical)h(p)s(erio)s (d)e(while)g(the)h(table)h(is)e(b)s(eing)0 5714 y(read)c(or)h(written.) p eop end %%Page: 176 184 TeXDict begin 176 183 bop 0 299 a Fj(176)1876 b Fh(CHAPTER)30 b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)0 555 y Fj(4.)39 b(Use)25 b(the)g(CFITSIO)e(Iterator)j(routine.)39 b(This)24 b(routine)h(pro)m(vides)f(a)i(more)e(`ob)5 b(ject)26 b(orien)m(ted')g(w)m(a)m(y)g(of)f(reading)0 668 y(and)34 b(writing)g(FITS)g(\014les)g(whic)m(h)h(automatically)i(uses)d(the)g (most)h(appropriate)g(data)g(bu\013er)e(size)i(to)h(ac)m(hiev)m(e)0 781 y(the)31 b(maxim)m(um)f(I/O)g(throughput.)0 941 y(5.)39 b(Use)24 b(binary)f(table)h(extensions)g(rather)f(than)h(ASCI)s(I)e (table)i(extensions)g(for)f(b)s(etter)h(e\016ciency)h(when)d(dealing)0 1054 y(with)37 b(tabular)h(data.)62 b(The)37 b(I/O)g(to)h(ASCI)s(I)e (tables)i(is)g(slo)m(w)m(er)g(b)s(ecause)g(of)f(the)h(o)m(v)m(erhead)h (in)e(formatting)h(or)0 1167 y(parsing)32 b(the)g(ASCI)s(I)f(data)i (\014elds)f(and)g(b)s(ecause)g(ASCI)s(I)f(tables)i(are)g(ab)s(out)f(t)m (wice)i(as)f(large)g(as)g(binary)e(tables)0 1280 y(that)g(ha)m(v)m(e)h (the)e(same)h(information)g(con)m(ten)m(t.)0 1440 y(6.)64 b(Design)39 b(soft)m(w)m(are)g(so)g(that)f(it)h(reads)f(the)g(FITS)f (header)h(k)m(eyw)m(ords)g(in)g(the)g(same)h(order)e(in)h(whic)m(h)g (they)0 1553 y(o)s(ccur)28 b(in)h(the)g(\014le.)40 b(When)28 b(reading)h(k)m(eyw)m(ords,)h(CFITSIO)d(searc)m(hes)i(forw)m(ard)g (starting)g(from)f(the)h(p)s(osition)g(of)0 1666 y(the)g(last)i(k)m (eyw)m(ord)e(that)h(w)m(as)g(read.)40 b(If)29 b(it)g(reac)m(hes)i(the)e (end)g(of)g(the)h(header)f(without)g(\014nding)f(the)h(k)m(eyw)m(ord,)h (it)0 1779 y(then)j(go)s(es)h(bac)m(k)g(to)h(the)e(start)h(of)g(the)g (header)f(and)g(con)m(tin)m(ues)h(the)g(searc)m(h)g(do)m(wn)f(to)h(the) g(p)s(osition)f(where)g(it)0 1892 y(started.)41 b(In)30 b(practice,)i(as)e(long)h(as)g(the)f(en)m(tire)i(FITS)d(header)h(can)h (\014t)f(at)h(one)g(time)g(in)f(the)g(a)m(v)-5 b(ailable)33 b(in)m(ternal)0 2005 y(IO)23 b(bu\013ers,)i(then)e(the)i(header)e(k)m (eyw)m(ord)i(access)g(will)f(b)s(e)g(relativ)m(ely)i(fast)e(and)g(it)g (mak)m(es)h(little)h(di\013erence)e(whic)m(h)0 2118 y(order)30 b(they)g(are)h(accessed.)0 2278 y(7.)40 b(Av)m(oid)29 b(the)e(use)h(of)f(scaling)i(\(b)m(y)f(using)f(the)h(BSCALE)e(and)h (BZER)m(O)h(or)f(TSCAL)g(and)g(TZER)m(O)f(k)m(eyw)m(ords\))0 2391 y(in)35 b(FITS)f(\014les)g(since)i(the)f(scaling)h(op)s(erations)f (add)f(to)i(the)f(pro)s(cessing)f(time)i(needed)e(to)i(read)f(or)g (write)g(the)0 2503 y(data.)k(In)24 b(some)h(cases)h(it)f(ma)m(y)g(b)s (e)f(more)g(e\016cien)m(t)i(to)g(temp)s(orarily)e(turn)g(o\013)h(the)f (scaling)i(\(using)e(\014ts)p 3490 2503 28 4 v 33 w(set)p 3634 2503 V 33 w(bscale)0 2616 y(or)30 b(\014ts)p 238 2616 V 33 w(set)p 382 2616 V 33 w(tscale\))j(and)c(then)h(read)h(or)f (write)h(the)f(ra)m(w)h(unscaled)f(v)-5 b(alues)31 b(in)f(the)g(FITS)g (\014le.)0 2777 y(8.)77 b(Av)m(oid)43 b(using)f(the)h(`implicit)g(data) h(t)m(yp)s(e)e(con)m(v)m(ersion')i(capabilit)m(y)g(in)e(CFITSIO.)f(F)-8 b(or)44 b(instance,)i(when)0 2889 y(reading)28 b(a)g(FITS)f(image)i (with)e(BITPIX)h(=)f(-32)i(\(32-bit)g(\015oating)g(p)s(oin)m(t)f (pixels\),)h(read)e(the)h(data)g(in)m(to)h(a)f(single)0 3002 y(precision)40 b(\015oating)h(p)s(oin)m(t)f(data)h(arra)m(y)f(in)g (the)g(program.)69 b(F)-8 b(orcing)41 b(CFITSIO)e(to)i(con)m(v)m(ert)g (the)f(data)h(to)g(a)0 3115 y(di\013eren)m(t)31 b(data)g(t)m(yp)s(e)f (can)h(slo)m(w)g(the)g(program.)0 3275 y(9.)57 b(Where)36 b(feasible,)i(design)e(FITS)f(binary)g(tables)h(using)f(v)m(ector)j (column)d(elemen)m(ts)i(so)f(that)g(the)g(data)h(are)0 3388 y(written)30 b(as)g(a)g(con)m(tiguous)h(set)f(of)g(b)m(ytes,)g (rather)g(than)f(as)h(single)g(elemen)m(ts)h(in)f(m)m(ultiple)g(ro)m (ws.)41 b(F)-8 b(or)30 b(example,)0 3501 y(it)36 b(is)g(faster)g(to)g (access)h(the)f(data)h(in)e(a)h(table)h(that)f(con)m(tains)h(a)f (single)g(ro)m(w)g(and)f(2)h(columns)f(with)h(TF)m(ORM)0 3614 y(k)m(eyw)m(ords)d(equal)h(to)g('10000E')h(and)e('10000J',)j(than) d(it)g(is)g(to)h(access)g(the)g(same)f(amoun)m(t)h(of)f(data)h(in)f(a)g (table)0 3727 y(with)40 b(10000)j(ro)m(ws)d(whic)m(h)h(has)f(columns)g (with)g(the)h(TF)m(ORM)g(k)m(eyw)m(ords)g(equal)g(to)g('1E')h(and)e ('1J'.)h(In)f(the)0 3840 y(former)27 b(case)i(the)f(10000)i(\015oating) f(p)s(oin)m(t)f(v)-5 b(alues)28 b(in)g(the)g(\014rst)f(column)h(are)g (all)h(written)f(in)f(a)h(con)m(tiguous)h(blo)s(c)m(k)0 3953 y(of)d(the)f(\014le)h(whic)m(h)f(can)h(b)s(e)f(read)g(or)g (written)h(quic)m(kly)-8 b(,)28 b(whereas)d(in)g(the)h(second)f(case)i (eac)m(h)g(\015oating)f(p)s(oin)m(t)f(v)-5 b(alue)0 4066 y(in)34 b(the)g(\014rst)f(column)g(is)h(in)m(terlea)m(v)m(ed)j(with)c (the)h(in)m(teger)i(v)-5 b(alue)34 b(in)g(the)g(second)g(column)f(of)h (the)g(same)h(ro)m(w)f(so)0 4179 y(CFITSIO)29 b(has)h(to)h(explicitly)h (mo)m(v)m(e)g(to)f(the)g(p)s(osition)f(of)h(eac)m(h)g(elemen)m(t)h(to)f (b)s(e)f(read)g(or)g(written.)0 4339 y(10.)45 b(Av)m(oid)33 b(the)f(use)f(of)h(v)-5 b(ariable)32 b(length)g(v)m(ector)h(columns)f (in)f(binary)g(tables,)i(since)f(an)m(y)g(reading)f(or)h(writing)0 4452 y(of)h(these)g(data)g(requires)f(that)h(CFITSIO)f(\014rst)f(lo)s (ok)j(up)d(or)i(compute)g(the)f(starting)i(address)e(of)g(eac)m(h)i(ro) m(w)f(of)0 4565 y(data)e(in)f(the)h(heap.)40 b(In)30 b(practice,)i(this)e(is)g(probably)g(not)h(a)f(signi\014can)m(t)i (e\016ciency)f(issue.)0 4725 y(11.)73 b(When)40 b(cop)m(ying)i(data)g (from)e(one)h(FITS)f(table)i(to)f(another,)j(it)e(is)e(faster)i(to)f (transfer)g(the)f(ra)m(w)h(b)m(ytes)0 4838 y(instead)28 b(of)h(reading)f(then)g(writing)g(eac)m(h)h(column)f(of)g(the)g(table.) 41 b(The)28 b(CFITSIO)e(routines)i(\014ts)p 3349 4838 V 33 w(read)p 3554 4838 V 32 w(tblb)m(ytes)0 4951 y(and)36 b(\014ts)p 310 4951 V 32 w(write)p 544 4951 V 33 w(tblb)m(ytes)i(will)f (p)s(erform)e(lo)m(w-lev)m(el)k(reads)e(or)f(writes)h(of)g(an)m(y)g (con)m(tiguous)g(range)g(of)g(b)m(ytes)g(in)0 5064 y(a)d(table)g (extension.)51 b(These)33 b(routines)h(can)f(b)s(e)g(used)g(to)h(read)f (or)h(write)g(a)f(whole)h(ro)m(w)g(\(or)g(m)m(ultiple)g(ro)m(ws)f(for)0 5176 y(ev)m(en)e(greater)h(e\016ciency\))h(of)e(a)g(table)h(with)e(a)h (single)h(function)e(call.)43 b(These)31 b(routines)g(are)g(fast)g(b)s (ecause)g(they)0 5289 y(b)m(ypass)36 b(all)h(the)g(usual)f(data)h (scaling,)i(error)d(c)m(hec)m(king)i(and)e(mac)m(hine)h(dep)s(enden)m (t)e(data)i(con)m(v)m(ersion)h(that)f(is)0 5402 y(normally)g(done)g(b)m (y)f(CFITSIO,)g(and)g(they)h(allo)m(w)h(the)g(program)e(to)i(write)f (the)g(data)g(to)h(the)f(output)f(\014le)h(in)0 5515 y(exactly)30 b(the)e(same)h(b)m(yte)g(order.)40 b(F)-8 b(or)29 b(these)f(same)h(reasons,)g(these)g(routines)f(can)g(corrupt)g (the)g(FITS)g(data)h(\014le)0 5628 y(if)36 b(used)e(incorrectly)j(b)s (ecause)f(no)f(v)-5 b(alidation)37 b(or)f(mac)m(hine)g(dep)s(enden)m(t) e(con)m(v)m(ersion)j(is)f(p)s(erformed)e(b)m(y)h(these)p eop end %%Page: 177 185 TeXDict begin 177 184 bop 0 299 a Fh(13.2.)73 b(OPTIMIZA)-8 b(TION)29 b(STRA)-8 b(TEGIES)2186 b Fj(177)0 555 y(routines.)55 b(These)35 b(routines)g(are)h(only)f(recommended)g(for)g(optimizing)h (critical)h(pieces)f(of)g(co)s(de)f(and)g(should)0 668 y(only)e(b)s(e)g(used)g(b)m(y)g(programmers)g(who)g(thoroughly)g (understand)e(the)j(in)m(ternal)g(format)g(of)f(the)h(FITS)e(tables)0 781 y(they)f(are)f(reading)h(or)f(writing.)0 941 y(12.)41 b(Another)30 b(strategy)g(for)g(impro)m(ving)f(the)h(sp)s(eed)e(of)i (writing)g(a)f(FITS)g(table,)i(similar)f(to)g(the)f(previous)g(one,)0 1054 y(is)j(to)g(directly)h(construct)f(the)f(en)m(tire)i(b)m(yte)f (stream)g(for)g(a)g(whole)g(table)g(ro)m(w)g(\(or)g(m)m(ultiple)h(ro)m (ws\))f(within)f(the)0 1167 y(application)g(program)e(and)g(then)h (write)g(it)g(to)g(the)g(FITS)f(\014le)h(with)f(\014ts)p 2520 1167 28 4 v 32 w(write)p 2754 1167 V 33 w(tblb)m(ytes.)41 b(This)29 b(a)m(v)m(oids)i(all)g(the)0 1280 y(o)m(v)m(erhead)f (normally)g(presen)m(t)f(in)g(the)h(column-orien)m(ted)g(CFITSIO)e (write)h(routines.)40 b(This)29 b(tec)m(hnique)h(should)0 1393 y(only)35 b(b)s(e)e(used)h(for)g(critical)i(applications)g(b)s (ecause)e(it)h(mak)m(es)h(the)e(co)s(de)h(more)f(di\016cult)h(to)g (understand)e(and)0 1506 y(main)m(tain,)38 b(and)d(it)h(mak)m(es)g(the) g(co)s(de)f(more)h(system)g(dep)s(enden)m(t)e(\(e.g.,)39 b(do)c(the)h(b)m(ytes)g(need)f(to)h(b)s(e)f(sw)m(app)s(ed)0 1619 y(b)s(efore)30 b(writing)g(to)h(the)g(FITS)f(\014le?\).)0 1779 y(13.)40 b(Finally)-8 b(,)29 b(external)e(factors)g(suc)m(h)e(as)i (the)f(sp)s(eed)f(of)i(the)f(data)h(storage)g(device,)h(the)f(size)g (of)f(the)g(data)h(cac)m(he,)0 1892 y(the)34 b(amoun)m(t)h(of)f(disk)g (fragmen)m(tation,)j(and)c(the)i(amoun)m(t)f(of)h(RAM)f(a)m(v)-5 b(ailable)37 b(on)d(the)g(system)g(can)h(all)g(ha)m(v)m(e)0 2005 y(a)k(signi\014can)m(t)g(impact)g(on)f(o)m(v)m(erall)j(I/O)d (e\016ciency)-8 b(.)66 b(F)-8 b(or)39 b(critical)h(applications,)i(the) c(en)m(tire)i(hardw)m(are)e(and)0 2118 y(soft)m(w)m(are)32 b(system)e(should)g(b)s(e)f(review)m(ed)i(to)h(iden)m(tify)e(an)m(y)h (p)s(oten)m(tial)h(I/O)e(b)s(ottlenec)m(ks.)p eop end %%Page: 178 186 TeXDict begin 178 185 bop 0 299 a Fj(178)1876 b Fh(CHAPTER)30 b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)p eop end %%Page: 179 187 TeXDict begin 179 186 bop 1882 5942 a Fj(179)p eop end %%Page: 180 188 TeXDict begin 180 187 bop 0 299 a Fj(180)2084 b Fh(APPENDIX)31 b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)0 1225 y Fg(App)5 b(endix)64 b(A)0 1687 y Fm(Index)77 b(of)h(Routines)50 2154 y Fj(\014ts)p 177 2154 28 4 v 32 w(add)p 356 2154 V 32 w(group)p 616 2154 V 33 w(mem)m(b)s(er)245 b(94)50 2267 y(\014ts)p 177 2267 V 32 w(ascii)p 380 2267 V 34 w(tform)579 b(72)50 2380 y(\014ts)p 177 2380 V 32 w(binary)p 465 2380 V 32 w(tform)496 b(72)50 2493 y(\014ts)p 177 2493 V 32 w(calculator)617 b(62)50 2606 y(\014ts)p 177 2606 V 32 w(calculator)p 596 2606 V 35 w(rng)450 b(62)50 2719 y(\014ts)p 177 2719 V 32 w(calc)p 359 2719 V 35 w(binning[d])419 b(63)50 2832 y(\014ts)p 177 2832 V 32 w(calc)p 359 2832 V 35 w(ro)m(ws)639 b(62)50 2945 y(\014ts)p 177 2945 V 32 w(c)m(hange)p 478 2945 V 34 w(group)473 b(92)50 3057 y(\014ts)p 177 3057 V 32 w(clean)m(up)p 509 3057 V 33 w(h)m(ttps)421 b(101)50 3170 y(\014ts)p 177 3170 V 32 w(clear)p 395 3170 V 34 w(errmark)467 b(32)50 3283 y(\014ts)p 177 3283 V 32 w(clear)p 395 3283 V 34 w(errmsg)515 b(32)50 3396 y(\014ts)p 177 3396 V 32 w(close)p 395 3396 V 34 w(\014le)668 b(35)50 3509 y(\014ts)p 177 3509 V 32 w(compact)p 541 3509 V 34 w(group)410 b(93)50 3622 y(\014ts)p 177 3622 V 32 w(compare)p 542 3622 V 34 w(str)530 b(68)50 3735 y(\014ts)p 177 3735 V 32 w(compress)p 569 3735 V 33 w(heap)379 b(118)50 3848 y(\014ts)p 177 3848 V 32 w(con)m(v)m(ert)p 498 3848 V 35 w(hdr2str)244 b(41,)31 b(88)50 3961 y(\014ts)p 177 3961 V 32 w(cop)m(y)p 390 3961 V 34 w(cell2image)383 b(45)50 4074 y(\014ts)p 177 4074 V 32 w(cop)m(y)p 390 4074 V 34 w(col)679 b(58)50 4187 y(\014ts)p 177 4187 V 32 w(cop)m(y)p 390 4187 V 34 w(cols)643 b(58)50 4299 y(\014ts)p 177 4299 V 32 w(cop)m(y)p 390 4299 V 34 w(data)568 b(103)50 4412 y(\014ts)p 177 4412 V 32 w(cop)m(y)p 390 4412 V 34 w(\014le)673 b(36)50 4525 y(\014ts)p 177 4525 V 32 w(cop)m(y)p 390 4525 V 34 w(group)561 b(93)50 4638 y(\014ts)p 177 4638 V 32 w(cop)m(y)p 390 4638 V 34 w(hdu)636 b(37)50 4751 y(\014ts)p 177 4751 V 32 w(cop)m(y)p 390 4751 V 34 w(hdutab)505 b(53)50 4864 y(\014ts)p 177 4864 V 32 w(cop)m(y)p 390 4864 V 34 w(header)526 b(37)50 4977 y(\014ts)p 177 4977 V 32 w(cop)m(y)p 390 4977 V 34 w(image2cell)383 b(45)50 5090 y(\014ts)p 177 5090 V 32 w(cop)m(y)p 390 5090 V 34 w(image)p 655 5090 V 34 w(section)252 b(47)50 5203 y(\014ts)p 177 5203 V 32 w(cop)m(y)p 390 5203 V 34 w(k)m(ey)611 b(108)50 5316 y(\014ts)p 177 5316 V 32 w(cop)m(y)p 390 5316 V 34 w(mem)m(b)s(er)470 b(95)50 5429 y(\014ts)p 177 5429 V 32 w(cop)m(y)p 390 5429 V 34 w(pixlist2image)268 b(64)50 5541 y(\014ts)p 177 5541 V 32 w(cop)m(y)p 390 5541 V 34 w(ro)m(ws)609 b(58)50 5654 y(\014ts)p 177 5654 V 32 w(cop)m(y)p 390 5654 V 34 w(selro)m(ws)508 b(58)50 5767 y(\014ts)p 177 5767 V 32 w(create)p 445 5767 V 35 w(disk\014le)457 b(34)50 5880 y(\014ts)p 177 5880 V 32 w(create)p 445 5880 V 35 w(\014le)617 b(34)1419 2267 y(\014ts)p 1546 2267 V 32 w(create)p 1814 2267 V 35 w(group)629 b(92)1419 2380 y(\014ts)p 1546 2380 V 32 w(create)p 1814 2380 V 35 w(hdu)659 b(102)1419 2493 y(\014ts)p 1546 2493 V 32 w(create)p 1814 2493 V 35 w(img)711 b(44)1419 2606 y(\014ts)p 1546 2606 V 32 w(create)p 1814 2606 V 35 w(mem\014le)549 b(98)1419 2719 y(\014ts)p 1546 2719 V 32 w(create)p 1814 2719 V 35 w(tbl)746 b(53)1419 2832 y(\014ts)p 1546 2832 V 32 w(create)p 1814 2832 V 35 w(template)510 b(98)1419 2945 y(\014ts)p 1546 2945 V 32 w(date2str)805 b(67)1419 3057 y(\014ts)p 1546 3057 V 32 w(deco)s(de)p 1848 3057 V 33 w(c)m(hksum)526 b(66)1419 3170 y(\014ts)p 1546 3170 V 32 w(deco)s(de)p 1848 3170 V 33 w(tdim)638 b(56)1419 3283 y(\014ts)p 1546 3283 V 32 w(delete)p 1809 3283 V 34 w(col)753 b(57)1419 3396 y(\014ts)p 1546 3396 V 32 w(delete)p 1809 3396 V 34 w(\014le)747 b(35)1419 3509 y(\014ts)p 1546 3509 V 32 w(delete)p 1809 3509 V 34 w(hdu)710 b(37)1419 3622 y(\014ts)p 1546 3622 V 32 w(delete)p 1809 3622 V 34 w(k)m(ey)730 b(43)1419 3735 y(\014ts)p 1546 3735 V 32 w(delete)p 1809 3735 V 34 w(record)615 b(43)1419 3848 y(\014ts)p 1546 3848 V 32 w(delete)p 1809 3848 V 34 w(ro)m(wlist)598 b(57)1419 3961 y(\014ts)p 1546 3961 V 32 w(delete)p 1809 3961 V 34 w(ro)m(wrange)502 b(57)1419 4074 y(\014ts)p 1546 4074 V 32 w(delete)p 1809 4074 V 34 w(ro)m(ws)683 b(57)1419 4187 y(\014ts)p 1546 4187 V 32 w(delete)p 1809 4187 V 34 w(str)756 b(43)1419 4299 y(\014ts)p 1546 4299 V 32 w(enco)s(de)p 1848 4299 V 33 w(c)m(hksum)526 b(66)1419 4412 y(\014ts)p 1546 4412 V 32 w(\014le)p 1694 4412 V 33 w(exists)714 b(100)1419 4525 y(\014ts)p 1546 4525 V 32 w(\014le)p 1694 4525 V 33 w(mo)s(de)764 b(35)1419 4638 y(\014ts)p 1546 4638 V 32 w(\014le)p 1694 4638 V 33 w(name)j(35)1419 4751 y(\014ts)p 1546 4751 V 32 w(\014nd)p 1731 4751 V 32 w(\014rst)p 1921 4751 V 32 w(ro)m(w)609 b(62)1419 4864 y(\014ts)p 1546 4864 V 32 w(\014nd)p 1731 4864 V 32 w(nextk)m(ey)636 b(40)1419 4977 y(\014ts)p 1546 4977 V 32 w(\014nd)p 1731 4977 V 32 w(ro)m(ws)763 b(61)1419 5090 y(\014ts)p 1546 5090 V 32 w(\015ush)p 1767 5090 V 32 w(bu\013er)631 b(100)1419 5203 y(\014ts)p 1546 5203 V 32 w(\015ush)p 1767 5203 V 32 w(\014le)746 b(100)1419 5316 y(\014ts)p 1546 5316 V 32 w(free)p 1722 5316 V 33 w(memory)438 b(110,)32 b(41)1419 5429 y(\014ts)p 1546 5429 V 32 w(get)p 1698 5429 V 34 w(acolparms)530 b(117)1419 5541 y(\014ts)p 1546 5541 V 32 w(get)p 1698 5541 V 34 w(b)s(colparms)521 b(117)1419 5654 y(\014ts)p 1546 5654 V 32 w(get)p 1698 5654 V 34 w(c)m(hksum)675 b(66)1419 5767 y(\014ts)p 1546 5767 V 32 w(get)p 1698 5767 V 34 w(col)p 1842 5767 V 34 w(displa)m(y)p 2154 5767 V 33 w(width)291 b(55)2912 2211 y(\014ts)p 3039 2211 V 32 w(get)p 3191 2211 V 34 w(colname)511 b(54)2912 2323 y(\014ts)p 3039 2323 V 32 w(get)p 3191 2323 V 34 w(coln)m(um)548 b(54)2912 2436 y(\014ts)p 3039 2436 V 32 w(get)p 3191 2436 V 34 w(colt)m(yp)s(e)h(55)2912 2549 y(\014ts)p 3039 2549 V 32 w(get)p 3191 2549 V 34 w(compression)p 3706 2549 V 33 w(t)m(yp)s(e)145 b(50)2912 2662 y(\014ts)p 3039 2662 V 32 w(get)p 3191 2662 V 34 w(eqcolt)m(yp)s(e)461 b(55)2912 2775 y(\014ts)p 3039 2775 V 32 w(get)p 3191 2775 V 34 w(errstatus)483 b(31)2912 2888 y(\014ts)p 3039 2888 V 32 w(get)p 3191 2888 V 34 w(hdrp)s(os)515 b(104)2912 3001 y(\014ts)p 3039 3001 V 32 w(get)p 3191 3001 V 34 w(hdrspace)483 b(38)2912 3114 y(\014ts)p 3039 3114 V 32 w(get)p 3191 3114 V 34 w(hdu)p 3378 3114 V 31 w(n)m(um)474 b(36)2912 3227 y(\014ts)p 3039 3227 V 32 w(get)p 3191 3227 V 34 w(hdu)p 3378 3227 V 31 w(t)m(yp)s(e)h(36)2912 3340 y(\014ts)p 3039 3340 V 32 w(get)p 3191 3340 V 34 w(hduaddr)452 b(102)2912 3453 y(\014ts)p 3039 3453 V 32 w(get)p 3191 3453 V 34 w(hduaddrll)402 b(102)2912 3566 y(\014ts)p 3039 3566 V 32 w(get)p 3191 3566 V 34 w(img)p 3371 3566 V 33 w(dim)502 b(44)2912 3678 y(\014ts)p 3039 3678 V 32 w(get)p 3191 3678 V 34 w(img)p 3371 3678 V 33 w(equivt)m(yp)s(e)268 b(44)2912 3791 y(\014ts)p 3039 3791 V 32 w(get)p 3191 3791 V 34 w(img)p 3371 3791 V 33 w(param)401 b(44)2912 3904 y(\014ts)p 3039 3904 V 32 w(get)p 3191 3904 V 34 w(img)p 3371 3904 V 33 w(size)513 b(44)2912 4017 y(\014ts)p 3039 4017 V 32 w(get)p 3191 4017 V 34 w(img)p 3371 4017 V 33 w(t)m(yp)s(e)480 b(44)2912 4130 y(\014ts)p 3039 4130 V 32 w(get)p 3191 4130 V 34 w(in)m(tt)m(yp)s(e)551 b(71)2912 4243 y(\014ts)p 3039 4243 V 32 w(get)p 3191 4243 V 34 w(k)m(ey)p 3358 4243 V 34 w(com)p 3553 4243 V 33 w(strlen)249 b(39)2912 4356 y(\014ts)p 3039 4356 V 32 w(get)p 3191 4356 V 34 w(k)m(ey)p 3358 4356 V 34 w(strlen)443 b(39)2912 4469 y(\014ts)p 3039 4469 V 32 w(get)p 3191 4469 V 34 w(k)m(eyclass)518 b(71)2912 4582 y(\014ts)p 3039 4582 V 32 w(get)p 3191 4582 V 34 w(k)m(eyname)488 b(69)2912 4695 y(\014ts)p 3039 4695 V 32 w(get)p 3191 4695 V 34 w(k)m(eyt)m(yp)s(e)526 b(70)2912 4808 y(\014ts)p 3039 4808 V 32 w(get)p 3191 4808 V 34 w(noise)p 3422 4808 V 33 w(bits)456 b(50)2912 4920 y(\014ts)p 3039 4920 V 32 w(get)p 3191 4920 V 34 w(n)m(um)p 3400 4920 V 32 w(cols)480 b(54)2912 5033 y(\014ts)p 3039 5033 V 32 w(get)p 3191 5033 V 34 w(n)m(um)p 3400 5033 V 32 w(groups)362 b(95)2912 5146 y(\014ts)p 3039 5146 V 32 w(get)p 3191 5146 V 34 w(n)m(um)p 3400 5146 V 32 w(hdus)437 b(36)2912 5259 y(\014ts)p 3039 5259 V 32 w(get)p 3191 5259 V 34 w(n)m(um)p 3400 5259 V 32 w(mem)m(b)s(ers)271 b(94)2912 5372 y(\014ts)p 3039 5372 V 32 w(get)p 3191 5372 V 34 w(n)m(um)p 3400 5372 V 32 w(ro)m(ws)446 b(54)2912 5485 y(\014ts)p 3039 5485 V 32 w(get)p 3191 5485 V 34 w(ro)m(wsize)503 b(118)2912 5598 y(\014ts)p 3039 5598 V 32 w(get)p 3191 5598 V 34 w(system)p 3496 5598 V 33 w(time)353 b(67)2912 5711 y(\014ts)p 3039 5711 V 32 w(get)p 3191 5711 V 34 w(tb)s(col)634 b(72)2912 5824 y(\014ts)p 3039 5824 V 32 w(get)p 3191 5824 V 34 w(tile)p 3350 5824 V 34 w(dim)522 b(50)p eop end %%Page: 181 189 TeXDict begin 181 188 bop 3764 299 a Fj(181)50 656 y(\014ts)p 177 656 28 4 v 32 w(get)p 329 656 V 34 w(timeout)554 b(101)50 769 y(\014ts)p 177 769 V 32 w(get)p 329 769 V 34 w(v)m(ersion)628 b(68)50 882 y(\014ts)p 177 882 V 32 w(hdr2str)c(41,)31 b(88)50 995 y(\014ts)p 177 995 V 32 w(init)p 345 995 V 33 w(h)m(ttps)641 b(101)50 1107 y(\014ts)p 177 1107 V 32 w(insert)p 432 1107 V 33 w(atbl)603 b(103)50 1220 y(\014ts)p 177 1220 V 32 w(insert)p 432 1220 V 33 w(btbl)597 b(103)50 1333 y(\014ts)p 177 1333 V 32 w(insert)p 432 1333 V 33 w(col)694 b(57)50 1446 y(\014ts)p 177 1446 V 32 w(insert)p 432 1446 V 33 w(cols)658 b(57)50 1559 y(\014ts)p 177 1559 V 32 w(insert)p 432 1559 V 33 w(group)576 b(92)50 1672 y(\014ts)p 177 1672 V 32 w(insert)p 432 1672 V 33 w(img)613 b(102)50 1785 y(\014ts)p 177 1785 V 32 w(insert)p 432 1785 V 33 w(k)m(ey)p 598 1785 V 34 w(n)m(ull)443 b(109)50 1898 y(\014ts)p 177 1898 V 32 w(insert)p 432 1898 V 33 w(k)m(ey)p 598 1898 V 34 w(TYP)396 b(109)50 2011 y(\014ts)p 177 2011 V 32 w(insert)p 432 2011 V 33 w(record)511 b(109)50 2124 y(\014ts)p 177 2124 V 32 w(insert)p 432 2124 V 33 w(ro)m(ws)624 b(57)50 2237 y(\014ts)p 177 2237 V 32 w(is)p 270 2237 V 33 w(reen)m(tran)m(t)603 b(77)50 2349 y(\014ts)p 177 2349 V 32 w(iterate)p 465 2349 V 35 w(data)593 b(85)50 2462 y(\014ts)p 177 2462 V 32 w(mak)m(e)p 415 2462 V 34 w(hist[d])572 b(65)50 2575 y(\014ts)p 177 2575 V 32 w(mak)m(e)p 415 2575 V 34 w(k)m(ey)687 b(70)50 2688 y(\014ts)p 177 2688 V 32 w(mak)m(e)p 415 2688 V 34 w(k)m(eyn)636 b(70)50 2801 y(\014ts)p 177 2801 V 32 w(mak)m(e)p 415 2801 V 34 w(nk)m(ey)g(70)50 2914 y(\014ts)p 177 2914 V 32 w(merge)p 446 2914 V 34 w(groups)525 b(93)50 3027 y(\014ts)p 177 3027 V 32 w(mo)s(dify)p 485 3027 V 32 w(card)535 b(111)50 3140 y(\014ts)p 177 3140 V 32 w(mo)s(dify)p 485 3140 V 32 w(commen)m(t)392 b(42)50 3253 y(\014ts)p 177 3253 V 32 w(mo)s(dify)p 485 3253 V 32 w(k)m(ey)p 650 3253 V 34 w(n)m(ull)f(112)50 3366 y(\014ts)p 177 3366 V 32 w(mo)s(dify)p 485 3366 V 32 w(k)m(ey)p 650 3366 V 34 w(TYP)344 b(111)50 3479 y(\014ts)p 177 3479 V 32 w(mo)s(dify)p 485 3479 V 32 w(name)540 b(43)50 3591 y(\014ts)p 177 3591 V 32 w(mo)s(dify)p 485 3591 V 32 w(record)459 b(111)50 3704 y(\014ts)p 177 3704 V 32 w(mo)s(dify)p 485 3704 V 32 w(v)m(ector)p 758 3704 V 35 w(len)360 b(58)50 3817 y(\014ts)p 177 3817 V 32 w(mo)m(v)-5 b(abs)p 502 3817 V 33 w(hdu)581 b(36)50 3930 y(\014ts)p 177 3930 V 32 w(mo)m(vnam)p 547 3930 V 33 w(hdu)536 b(36)50 4043 y(\014ts)p 177 4043 V 32 w(mo)m(vrel)p 476 4043 V 34 w(hdu)606 b(36)50 4156 y(\014ts)p 177 4156 V 32 w(n)m(ull)p 358 4156 V 33 w(c)m(hec)m(k)665 b(69)50 4269 y(\014ts)p 177 4269 V 32 w(op)s(en)p 399 4269 V 32 w(data)d(32)50 4382 y(\014ts)p 177 4382 V 32 w(op)s(en)p 399 4382 V 32 w(disk\014le)562 b(32)50 4495 y(\014ts)p 177 4495 V 32 w(op)s(en)p 399 4495 V 32 w(extlist)594 b(32)50 4608 y(\014ts)p 177 4608 V 32 w(op)s(en)p 399 4608 V 32 w(\014le)722 b(32)50 4721 y(\014ts)p 177 4721 V 32 w(op)s(en)p 399 4721 V 32 w(image)607 b(32)50 4833 y(\014ts)p 177 4833 V 32 w(op)s(en)p 399 4833 V 32 w(table)642 b(32)50 4946 y(\014ts)p 177 4946 V 32 w(op)s(en)p 399 4946 V 32 w(group)610 b(94)50 5059 y(\014ts)p 177 5059 V 32 w(op)s(en)p 399 5059 V 32 w(mem)m(b)s(er)519 b(95)50 5172 y(\014ts)p 177 5172 V 32 w(op)s(en)p 399 5172 V 32 w(mem\014le)530 b(97)50 5285 y(\014ts)p 177 5285 V 32 w(parse)p 417 5285 V 33 w(extn)m(um)521 b(99)50 5398 y(\014ts)p 177 5398 V 32 w(parse)p 417 5398 V 33 w(input)p 663 5398 V 32 w(\014lename)246 b(99)50 5511 y(\014ts)p 177 5511 V 32 w(parse)p 417 5511 V 33 w(input)p 663 5511 V 32 w(url)462 b(99)50 5624 y(\014ts)p 177 5624 V 32 w(parse)p 417 5624 V 33 w(range)602 b(77)50 5737 y(\014ts)p 177 5737 V 32 w(parse)p 417 5737 V 33 w(ro)s(otname)398 b(100)50 5850 y(\014ts)p 177 5850 V 32 w(parse)p 417 5850 V 33 w(template)472 b(72)50 5963 y(\014ts)p 177 5963 V 32 w(parse)p 417 5963 V 33 w(v)-5 b(alue)615 b(70)1475 543 y(\014ts)p 1602 543 V 32 w(pix)p 1758 543 V 33 w(to)p 1871 543 V 33 w(w)m(orld)653 b(89)1475 656 y(\014ts)p 1602 656 V 32 w(read)p 1806 656 V 33 w(2d)p 1935 656 V 33 w(TYP)567 b(117)1475 769 y(\014ts)p 1602 769 V 32 w(read)p 1806 769 V 33 w(3d)p 1935 769 V 33 w(TYP)g(117)1475 882 y(\014ts)p 1602 882 V 32 w(read)p 1806 882 V 33 w(atblhdr)598 b(106)1475 995 y(\014ts)p 1602 995 V 32 w(read)p 1806 995 V 33 w(btblhdr)592 b(106)1475 1107 y(\014ts)p 1602 1107 V 32 w(read)p 1806 1107 V 33 w(card)766 b(38)1475 1220 y(\014ts)p 1602 1220 V 32 w(read)p 1806 1220 V 33 w(col)828 b(61)1475 1333 y(\014ts)p 1602 1333 V 32 w(read)p 1806 1333 V 33 w(col)p 1949 1333 V 34 w(bit)p 2094 1333 V 637 w(123)1475 1446 y(\014ts)p 1602 1446 V 32 w(read)p 1806 1446 V 33 w(col)p 1949 1446 V 34 w(TYP)552 b(121)1475 1559 y(\014ts)p 1602 1559 V 32 w(read)p 1806 1559 V 33 w(coln)m(ull)679 b(61)1475 1672 y(\014ts)p 1602 1672 V 32 w(read)p 1806 1672 V 33 w(coln)m(ull)p 2098 1672 V 34 w(TYP)403 b(122)1475 1785 y(\014ts)p 1602 1785 V 32 w(read)p 1806 1785 V 33 w(cols)792 b(61)1475 1898 y(\014ts)p 1602 1898 V 32 w(read)p 1806 1898 V 33 w(descript)578 b(123)1475 2011 y(\014ts)p 1602 2011 V 32 w(read)p 1806 2011 V 33 w(descripts)542 b(123)1475 2124 y(\014ts)p 1602 2124 V 32 w(read)p 1806 2124 V 33 w(errmsg)669 b(32)1475 2237 y(\014ts)p 1602 2237 V 32 w(read)p 1806 2237 V 33 w(ext)769 b(103)1475 2349 y(\014ts)p 1602 2349 V 32 w(read)p 1806 2349 V 33 w(grppar)p 2103 2349 V 32 w(TYP)400 b(116)1475 2462 y(\014ts)p 1602 2462 V 32 w(read)p 1806 2462 V 33 w(img)746 b(116)1475 2575 y(\014ts)p 1602 2575 V 32 w(read)p 1806 2575 V 33 w(img)p 1985 2575 V 33 w(co)s(ord)539 b(89)1475 2688 y(\014ts)p 1602 2688 V 32 w(read)p 1806 2688 V 33 w(img)p 1985 2688 V 33 w(TYP)517 b(116)1475 2801 y(\014ts)p 1602 2801 V 32 w(read)p 1806 2801 V 33 w(imghdr)608 b(106)1475 2914 y(\014ts)p 1602 2914 V 32 w(read)p 1806 2914 V 33 w(imgn)m(ull)597 b(116)1475 3027 y(\014ts)p 1602 3027 V 32 w(read)p 1806 3027 V 33 w(imgn)m(ull)p 2134 3027 V 33 w(TYP)368 b(116)1475 3140 y(\014ts)p 1602 3140 V 32 w(read)p 1806 3140 V 33 w(k)m(ey)805 b(38)1475 3253 y(\014ts)p 1602 3253 V 32 w(read)p 1806 3253 V 33 w(k)m(ey)p 1972 3253 V 33 w(longstr)453 b(110)1475 3366 y(\014ts)p 1602 3366 V 32 w(read)p 1806 3366 V 33 w(k)m(ey)p 1972 3366 V 33 w(triple)514 b(111)1475 3479 y(\014ts)p 1602 3479 V 32 w(read)p 1806 3479 V 33 w(k)m(ey)p 1972 3479 V 33 w(unit)610 b(40)1475 3591 y(\014ts)p 1602 3591 V 32 w(read)p 1806 3591 V 33 w(k)m(ey)p 1972 3591 V 33 w(TYP)530 b(110)1475 3704 y(\014ts)p 1602 3704 V 32 w(read)p 1806 3704 V 33 w(k)m(eyn)754 b(40)1475 3817 y(\014ts)p 1602 3817 V 32 w(read)p 1806 3817 V 33 w(k)m(eys)p 2008 3817 V 33 w(TYP)494 b(110)1475 3930 y(\014ts)p 1602 3930 V 32 w(read)p 1806 3930 V 33 w(k)m(eyw)m(ord)610 b(38)1475 4043 y(\014ts)p 1602 4043 V 32 w(read)p 1806 4043 V 33 w(pix)814 b(47)1475 4156 y(\014ts)p 1602 4156 V 32 w(read)p 1806 4156 V 33 w(pixn)m(ull)665 b(47)1475 4269 y(\014ts)p 1602 4269 V 32 w(read)p 1806 4269 V 33 w(record)690 b(40)1475 4382 y(\014ts)p 1602 4382 V 32 w(read)p 1806 4382 V 33 w(str)831 b(38)1475 4495 y(\014ts)p 1602 4495 V 32 w(read)p 1806 4495 V 33 w(string)p 2067 4495 V 33 w(k)m(ey)544 b(39)1475 4608 y(\014ts)p 1602 4608 V 32 w(read)p 1806 4608 V 33 w(string)p 2067 4608 V 33 w(k)m(ey)p 2233 4608 V 33 w(com)350 b(39)1475 4721 y(\014ts)p 1602 4721 V 32 w(read)p 1806 4721 V 33 w(subset)689 b(46)1475 4833 y(\014ts)p 1602 4833 V 32 w(read)p 1806 4833 V 33 w(subset)p 2088 4833 V 32 w(TYP)248 b(117)32 b(122)1475 4946 y(\014ts)p 1602 4946 V 32 w(read)p 1806 4946 V 33 w(subsetn)m(ull)p 2237 4946 V 32 w(TYP)99 b(117)32 b(122)1475 5059 y(\014ts)p 1602 5059 V 32 w(read)p 1806 5059 V 33 w(tbl)p 1950 5059 V 33 w(co)s(ord)574 b(89)1475 5172 y(\014ts)p 1602 5172 V 32 w(read)p 1806 5172 V 33 w(tblb)m(ytes)g(119)1475 5285 y(\014ts)p 1602 5285 V 32 w(read)p 1806 5285 V 33 w(tdim)751 b(56)1475 5398 y(\014ts)p 1602 5398 V 32 w(read)p 1806 5398 V 33 w(w)m(cstab)668 b(88)1475 5511 y(\014ts)p 1602 5511 V 32 w(rebin)p 1837 5511 V 32 w(w)m(cs[d])g(64)1475 5624 y(\014ts)p 1602 5624 V 32 w(remo)m(v)m(e)p 1913 5624 V 35 w(group)601 b(93)1475 5737 y(\014ts)p 1602 5737 V 32 w(remo)m(v)m(e)p 1913 5737 V 35 w(mem)m(b)s(er)510 b(95)1475 5850 y(\014ts)p 1602 5850 V 32 w(reop)s(en)p 1900 5850 V 32 w(\014le)729 b(98)1475 5963 y(\014ts)p 1602 5963 V 32 w(rep)s(ort)p 1880 5963 V 32 w(error)672 b(32)1475 6075 y(\014ts)p 1602 6075 V 32 w(resize)p 1851 6075 V 34 w(img)700 b(103)2982 599 y(\014ts)p 3109 599 V 33 w(rms)p 3290 599 V 32 w(\015oat)750 b(77)2982 712 y(\014ts)p 3109 712 V 33 w(rms)p 3290 712 V 32 w(short)723 b(77)2982 825 y(\014ts)p 3109 825 V 33 w(select)p 3358 825 V 34 w(ro)m(ws)676 b(62)2982 938 y(\014ts)p 3109 938 V 33 w(set)p 3253 938 V 33 w(atbln)m(ull)612 b(113)2982 1051 y(\014ts)p 3109 1051 V 33 w(set)p 3253 1051 V 33 w(bscale)680 b(113)2982 1164 y(\014ts)p 3109 1164 V 33 w(set)p 3253 1164 V 33 w(btbln)m(ull)606 b(113)2982 1277 y(\014ts)p 3109 1277 V 33 w(set)p 3253 1277 V 33 w(compression)p 3767 1277 V 33 w(t)m(yp)s(e)274 b(50)2982 1390 y(\014ts)p 3109 1390 V 33 w(set)p 3253 1390 V 33 w(hdrsize)638 b(104)2982 1503 y(\014ts)p 3109 1503 V 33 w(set)p 3253 1503 V 33 w(hdustruc)566 b(104)2982 1616 y(\014ts)p 3109 1616 V 33 w(set)p 3253 1616 V 33 w(imgn)m(ull)622 b(113)2982 1728 y(\014ts)p 3109 1728 V 33 w(set)p 3253 1728 V 33 w(noise)p 3483 1728 V 33 w(bits)585 b(50)2982 1841 y(\014ts)p 3109 1841 V 33 w(set)p 3253 1841 V 33 w(tile)p 3411 1841 V 34 w(dim)651 b(50)2982 1954 y(\014ts)p 3109 1954 V 33 w(set)p 3253 1954 V 33 w(timeout)610 b(101)2982 2067 y(\014ts)p 3109 2067 V 33 w(set)p 3253 2067 V 33 w(tscale)696 b(113)2982 2180 y(\014ts)p 3109 2180 V 33 w(sho)m(w)p 3337 2180 V 32 w(do)m(wnload)p 3745 2180 V 33 w(progress)100 b(101)2982 2293 y(\014ts)p 3109 2293 V 33 w(split)p 3314 2293 V 33 w(names)653 b(69)2982 2406 y(\014ts)p 3109 2406 V 33 w(str2date)783 b(67)2982 2519 y(\014ts)p 3109 2519 V 33 w(str2time)778 b(67)2982 2632 y(\014ts)p 3109 2632 V 33 w(test)p 3288 2632 V 33 w(expr)752 b(63)2982 2745 y(\014ts)p 3109 2745 V 33 w(test)p 3288 2745 V 33 w(heap)695 b(118)2982 2858 y(\014ts)p 3109 2858 V 33 w(test)p 3288 2858 V 33 w(k)m(eyw)m(ord)599 b(69)2982 2970 y(\014ts)p 3109 2970 V 33 w(test)p 3288 2970 V 33 w(record)679 b(69)2982 3083 y(\014ts)p 3109 3083 V 33 w(time2str)778 b(67)2982 3196 y(\014ts)p 3109 3196 V 33 w(transfer)p 3449 3196 V 32 w(mem)m(b)s(er)448 b(95)2982 3309 y(\014ts)p 3109 3309 V 33 w(translate)p 3490 3309 V 34 w(k)m(eyw)m(ord)396 b(75)2982 3422 y(\014ts)p 3109 3422 V 33 w(up)s(date)p 3418 3422 V 32 w(card)626 b(42)2982 3535 y(\014ts)p 3109 3535 V 33 w(up)s(date)p 3418 3535 V 32 w(c)m(hksum)499 b(66)2982 3648 y(\014ts)p 3109 3648 V 33 w(up)s(date)p 3418 3648 V 32 w(k)m(ey)665 b(41)2982 3761 y(\014ts)p 3109 3761 V 33 w(up)s(date)p 3418 3761 V 32 w(k)m(ey)p 3583 3761 V 33 w(longstr)314 b(112)2982 3874 y(\014ts)p 3109 3874 V 33 w(up)s(date)p 3418 3874 V 32 w(k)m(ey)p 3583 3874 V 33 w(n)m(ull)483 b(42)2982 3987 y(\014ts)p 3109 3987 V 33 w(up)s(date)p 3418 3987 V 32 w(k)m(ey)p 3583 3987 V 33 w(TYP)391 b(112)2982 4100 y(\014ts)p 3109 4100 V 33 w(upp)s(ercase)713 b(68)2982 4212 y(\014ts)p 3109 4212 V 33 w(url)p 3254 4212 V 32 w(t)m(yp)s(e)788 b(35)2982 4325 y(\014ts)p 3109 4325 V 33 w(v)m(erb)s(ose)p 3438 4325 V 33 w(h)m(ttps)527 b(101)2982 4438 y(\014ts)p 3109 4438 V 33 w(v)m(erify)p 3364 4438 V 33 w(c)m(hksum)552 b(66)2982 4551 y(\014ts)p 3109 4551 V 33 w(v)m(erify)p 3364 4551 V 33 w(group)623 b(94)2982 4664 y(\014ts)p 3109 4664 V 33 w(w)m(orld)p 3362 4664 V 32 w(to)p 3474 4664 V 34 w(pix)616 b(89)2982 4777 y(\014ts)p 3109 4777 V 33 w(write)p 3344 4777 V 33 w(2d)p 3473 4777 V 32 w(TYP)502 b(115)2982 4890 y(\014ts)p 3109 4890 V 33 w(write)p 3344 4890 V 33 w(3d)p 3473 4890 V 32 w(TYP)g(115)2982 5003 y(\014ts)p 3109 5003 V 33 w(write)p 3344 5003 V 33 w(atblhdr)532 b(105)2982 5116 y(\014ts)p 3109 5116 V 33 w(write)p 3344 5116 V 33 w(btblhdr)526 b(106)2982 5229 y(\014ts)p 3109 5229 V 33 w(write)p 3344 5229 V 33 w(c)m(hksum)572 b(66)2982 5342 y(\014ts)p 3109 5342 V 33 w(write)p 3344 5342 V 33 w(col)761 b(60)2982 5454 y(\014ts)p 3109 5454 V 33 w(write)p 3344 5454 V 33 w(col)p 3487 5454 V 34 w(bit)571 b(120)2982 5567 y(\014ts)p 3109 5567 V 33 w(write)p 3344 5567 V 33 w(col)p 3487 5567 V 34 w(TYP)486 b(119)2982 5680 y(\014ts)p 3109 5680 V 33 w(write)p 3344 5680 V 33 w(col)p 3487 5680 V 34 w(n)m(ull)578 b(60)2982 5793 y(\014ts)p 3109 5793 V 33 w(write)p 3344 5793 V 33 w(coln)m(ull)612 b(60)2982 5906 y(\014ts)p 3109 5906 V 33 w(write)p 3344 5906 V 33 w(coln)m(ull)p 3636 5906 V 34 w(TYP)337 b(119)2982 6019 y(\014ts)p 3109 6019 V 33 w(write)p 3344 6019 V 33 w(cols)725 b(60)p eop end %%Page: 182 190 TeXDict begin 182 189 bop 0 299 a Fj(182)2084 b Fh(APPENDIX)31 b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)50 543 y Fj(\014ts)p 177 543 28 4 v 32 w(write)p 411 543 V 33 w(commen)m(t)313 b(42)50 656 y(\014ts)p 177 656 V 32 w(write)p 411 656 V 33 w(date)502 b(42)50 769 y(\014ts)p 177 769 V 32 w(write)p 411 769 V 33 w(descript)314 b(120)50 882 y(\014ts)p 177 882 V 32 w(write)p 411 882 V 33 w(errmark)356 b(32)50 995 y(\014ts)p 177 995 V 32 w(write)p 411 995 V 33 w(errmsg)404 b(68)50 1107 y(\014ts)p 177 1107 V 32 w(write)p 411 1107 V 33 w(ext)505 b(103)50 1220 y(\014ts)p 177 1220 V 32 w(write)p 411 1220 V 33 w(exthdr)367 b(105)50 1333 y(\014ts)p 177 1333 V 32 w(write)p 411 1333 V 33 w(grphdr)358 b(105)50 1446 y(\014ts)p 177 1446 V 32 w(write)p 411 1446 V 33 w(grppar)p 708 1446 V 32 w(TYP)136 b(115)50 1559 y(\014ts)p 177 1559 V 32 w(write)p 411 1559 V 33 w(hdu)520 b(37)50 1672 y(\014ts)p 177 1672 V 32 w(write)p 411 1672 V 33 w(history)397 b(42)50 1785 y(\014ts)p 177 1785 V 32 w(write)p 411 1785 V 33 w(img)482 b(115)50 1898 y(\014ts)p 177 1898 V 32 w(write)p 411 1898 V 33 w(img)p 590 1898 V 33 w(n)m(ull)300 b(115)50 2011 y(\014ts)p 177 2011 V 32 w(write)p 411 2011 V 33 w(img)p 590 2011 V 33 w(TYP)253 b(115)50 2124 y(\014ts)p 177 2124 V 32 w(write)p 411 2124 V 33 w(imghdr)344 b(105)50 2237 y(\014ts)p 177 2237 V 32 w(write)p 411 2237 V 33 w(imgn)m(ull)333 b(115)50 2349 y(\014ts)p 177 2349 V 32 w(write)p 411 2349 V 33 w(imgn)m(ull)p 739 2349 V 33 w(TYP)104 b(115)50 2462 y(\014ts)p 177 2462 V 32 w(write)p 411 2462 V 33 w(k)m(ey)540 b(41)50 2575 y(\014ts)p 177 2575 V 32 w(write)p 411 2575 V 33 w(k)m(ey)p 577 2575 V 34 w(longstr)188 b(107)50 2688 y(\014ts)p 177 2688 V 32 w(write)p 411 2688 V 33 w(k)m(ey)p 577 2688 V 34 w(longw)m(arn)100 b(107)50 2801 y(\014ts)p 177 2801 V 32 w(write)p 411 2801 V 33 w(k)m(ey)p 577 2801 V 34 w(n)m(ull)357 b(42)50 2914 y(\014ts)p 177 2914 V 32 w(write)p 411 2914 V 33 w(k)m(ey)p 577 2914 V 34 w(template)114 b(108)50 3027 y(\014ts)p 177 3027 V 32 w(write)p 411 3027 V 33 w(k)m(ey)p 577 3027 V 34 w(triple)249 b(108)50 3140 y(\014ts)p 177 3140 V 32 w(write)p 411 3140 V 33 w(k)m(ey)p 577 3140 V 34 w(unit)344 b(43)50 3253 y(\014ts)p 177 3253 V 32 w(write)p 411 3253 V 33 w(k)m(ey)p 577 3253 V 34 w(TYP)265 b(107)50 3366 y(\014ts)p 177 3366 V 32 w(write)p 411 3366 V 33 w(k)m(eys)p 613 3366 V 34 w(TYP)229 b(108)50 3479 y(\014ts)p 177 3479 V 32 w(write)p 411 3479 V 33 w(k)m(eys)p 613 3479 V 34 w(histo)278 b(64)50 3591 y(\014ts)p 177 3591 V 32 w(write)p 411 3591 V 33 w(n)m(ull)p 593 3591 V 33 w(img)345 b(46)50 3704 y(\014ts)p 177 3704 V 32 w(write)p 411 3704 V 33 w(n)m(ullro)m(ws)f(60)50 3817 y(\014ts)p 177 3817 V 32 w(write)p 411 3817 V 33 w(pix)549 b(46)50 3930 y(\014ts)p 177 3930 V 32 w(write)p 411 3930 V 33 w(pixn)m(ull)400 b(46)50 4043 y(\014ts)p 177 4043 V 32 w(write)p 411 4043 V 33 w(record)425 b(42)50 4156 y(\014ts)p 177 4156 V 32 w(write)p 411 4156 V 33 w(subset)f(45)50 4269 y(\014ts)p 177 4269 V 32 w(write)p 411 4269 V 33 w(subset)p 693 4269 V 32 w(TYP)151 b(116)50 4382 y(\014ts)p 177 4382 V 32 w(write)p 411 4382 V 33 w(tblb)m(ytes)310 b(119)50 4495 y(\014ts)p 177 4495 V 32 w(write)p 411 4495 V 33 w(tdim)486 b(56)50 4608 y(\014ts)p 177 4608 V 32 w(write)p 411 4608 V 33 w(theap)406 b(118)p eop end %%Page: 183 191 TeXDict begin 183 190 bop 3764 299 a Fj(183)50 543 y(\013asfm)276 b(72)50 656 y(\013bnfm)255 b(72)50 769 y(\013calc)311 b(62)50 882 y(\013calc)p 258 882 28 4 v 34 w(rng)145 b(62)50 995 y(\013ccls)320 b(58)50 1107 y(\013c)m(h)m(tps)246 b Fi(??)50 1220 y Fj(\013clos)315 b(35)50 1333 y(\013cmph)197 b(118)50 1446 y(\013cmps)258 b(68)50 1559 y(\013cmrk)j(32)50 1672 y(\013cmsg)j(32)50 1785 y(\013cop)m(y)280 b(37)50 1898 y(\013cp)s(cl)302 b(58)50 2011 y(\013cp)s(dt)235 b(103)50 2124 y(\013cp\015)319 b(36)50 2237 y(\013cphd)268 b(37)50 2349 y(\013cph)m(t)287 b(53)50 2462 y(\013cpimg)224 b(47)50 2575 y(\013cpky)k(108)50 2688 y(\013cprw)268 b(58)50 2801 y(\013cpsr)298 b(58)50 2914 y(\013crhd)237 b(102)50 3027 y(\013crim)284 b(44)50 3140 y(\013cro)m(w)277 b(62)50 3253 y(\013crtb)299 b(53)50 3366 y(\013dcol)h(57)50 3479 y(\013delt)310 b(35)50 3591 y(\013dhdu)257 b(37)50 3704 y(\013dk)m(ey)277 b(43)50 3817 y(\013dkinit)226 b(34)50 3930 y(\013dk)m(opn)218 b(32)50 4043 y(\013dopn)263 b(32)50 4156 y(\013drec)294 b(43)50 4269 y(\013dro)m(w)266 b(57)50 4382 y(\013drrg)293 b(57)50 4495 y(\013drws)272 b(57)50 4608 y(\013dstr)303 b(43)50 4721 y(\013dsum)247 b(66)50 4833 y(\013dt2s)294 b(67)50 4946 y(\013dtdm)248 b(56)50 5059 y(\013dt)m(yp)279 b(70)50 5172 y(\013eopn)274 b(32)50 5285 y(\013eqt)m(y)293 b(55)50 5398 y(\013esum)258 b(66)50 5511 y(\013exest)216 b(100)50 5624 y(\013extn)287 b(99)50 5737 y(\013\013rw)306 b(62)50 5850 y(\013\015md)283 b(35)50 5963 y(\013\015nm)g(35)50 6075 y(\013\015sh)277 b(100)785 543 y(\013\015us)327 b(100)785 656 y(\013free)175 b(110,)32 b(41)785 769 y(\013fro)m(w)339 b(61)785 882 y(\013g2d)p 984 882 V 324 w(117)785 995 y(\013g3d)p 984 995 V 324 w(117)785 1107 y(\013gab)s(c)327 b(72)785 1220 y(\013gacl)310 b(117)785 1333 y(\013gb)s(cl)301 b(117)785 1446 y(\013gcdw)309 b(55)785 1559 y(\013gcf)398 b(61)785 1672 y(\013gcf)p 956 1672 V 352 w(122)785 1785 y(\013gc)m(ks)345 b(66)785 1898 y(\013gcnn)324 b(54)785 2011 y(\013gcno)330 b(54)785 2124 y(\013gcrd)339 b(38)785 2237 y(\013gcv)378 b(61)785 2349 y(\013gcv)p 976 2349 V 332 w(121)785 2462 y(\013gcvn)327 b(61)785 2575 y(\013gcx)332 b(123)785 2688 y(\013gdes)293 b(123)785 2801 y(\013gdess)257 b(123)785 2914 y(\013gerr)354 b(31)785 3027 y(\013gextn)246 b(103)785 3140 y(\013ggp)p 984 3140 V 324 w(116)785 3253 y(\013ghad)273 b(102)785 3366 y(\013gh)m(bn)d(106)785 3479 y(\013ghdn)313 b(36)785 3591 y(\013ghdt)329 b(36)785 3704 y(\013ghpr)282 b(106)785 3817 y(\013ghps)g(104)785 3930 y(\013ghsp)328 b(38)785 4043 y(\013gh)m(tb)286 b(106)785 4156 y(\013gics)365 b(89)785 4269 y(\013gidm)314 b(44)785 4382 y(\013gidt)355 b(44)785 4495 y(\013giet)366 b(44)785 4608 y(\013gipr)354 b(44)785 4721 y(\013gisz)365 b(44)785 4833 y(\013gk)m(cl)356 b(71)785 4946 y(\013gk)m(csl)320 b(39)785 5059 y(\013gk)m(ey)333 b(38)785 5172 y(\013gkls)311 b(110)785 5285 y(\013gksl)357 b(39)785 5398 y(\013gkn)p 987 5398 V 321 w(110)785 5511 y(\013gknm)291 b(69)785 5624 y(\013gky)370 b(38)785 5737 y(\013gkyn)319 b(40)785 5850 y(\013gkyt)289 b(111)785 5963 y(\013gky)p 984 5963 V 324 w(110)785 6075 y(\013gmcp)299 b(95)1570 599 y(\013gmng)327 b(95)1570 712 y(\013gmop)g(95)1570 825 y(\013gmrm)311 b(95)1570 938 y(\013gmsg)342 b(32)1570 1051 y(\013gm)m(tf)363 b(95)1570 1164 y(\013gncl)383 b(54)1570 1277 y(\013gnrw)346 b(54)1570 1390 y(\013gnxk)352 b(40)1570 1503 y(\013gpf)375 b(116)1570 1616 y(\013gpf)p 1752 1616 V 375 w(116)1570 1728 y(\013gp)m(v)358 b(116)1570 1841 y(\013gp)m(v)p 1769 1841 V 358 w(116)1570 1954 y(\013gp)m(xv)d(47) 1570 2067 y(\013gp)m(xf)375 b(47)1570 2180 y(\013grec)383 b(40)1570 2293 y(\013grsz)342 b(118)1570 2406 y(\013gsdt)377 b(67)1570 2519 y(\013gsf)p 1737 2519 V 223 w(117)32 b(122)1570 2632 y(\013gsky)367 b(39)1570 2745 y(\013gskyc)327 b(39)1570 2858 y(\013gstm)352 b(67)1570 2970 y(\013gstr)392 b(38)1570 3083 y(\013gsv)415 b(46)1570 3196 y(\013gsv)p 1757 3196 V 203 w(117)32 b(122)1570 3309 y(\013gtam)343 b(94)1570 3422 y(\013gtbb)317 b(119)1570 3535 y(\013gtc)m(h)376 b(92)1570 3648 y(\013gtcl)399 b(55)1570 3761 y(\013gtcm)348 b(93)1570 3874 y(\013gtcp)373 b(93)1570 3987 y(\013gtcr)388 b(92)1570 4100 y(\013gtcs)g(89)1570 4212 y(\013gtdm)337 b(56)1570 4325 y(\013gthd)362 b(72)1570 4438 y(\013gtis)403 b(92)1570 4551 y(\013gtmg)343 b(93)1570 4664 y(\013gtmo)298 b(101)1570 4777 y(\013gtnm)337 b(94)1570 4890 y(\013gtop)368 b(94)1570 5003 y(\013gtrm)352 b(93)1570 5116 y(\013gtvf)388 b(94)1570 5229 y(\013gun)m(t)365 b(40)1570 5342 y(\013hdef)329 b(104)1570 5454 y(\016bin)349 b(103)1570 5567 y(\016cls)420 b(57)1570 5680 y(\016col)411 b(57)1570 5793 y(\016\014le)405 b(99)1570 5906 y(\016h)m(tps)306 b(101)1570 6019 y(\016img)330 b(102)2388 599 y(\016kls)215 b(109)2388 712 y(\016kyu)177 b(109)2388 825 y(\016ky)p 2565 825 V 228 w(109)2388 938 y(\016mem)g(98)2388 1051 y(\016nit)258 b(34)2388 1164 y(\016n)m(tt)m(yp)155 b(71)2388 1277 y(\016opn)222 b(32)2388 1390 y(\016rec)208 b(109)2388 1503 y(\016ro)m(w)225 b(57)2388 1616 y(\016tab)193 b(103)2388 1728 y(\016ter)258 b(85)2388 1841 y(\016url)f(99)2388 1954 y(\013k)m(eyn)208 b(70)2388 2067 y(\013mahd)169 b(36)2388 2180 y(\013mcom)155 b(42)2388 2293 y(\013mcrd)144 b(111)2388 2406 y(\013mkky)172 b(70)2388 2519 y(\013mkls)162 b(111)2388 2632 y(\013mkyu)124 b(112)2388 2745 y(\013mky)p 2618 2745 V 175 w(111)2388 2858 y(\013mnam)144 b(43)2388 2970 y(\013mnhd)163 b(36)2388 3083 y(\013mrec)155 b(111)2388 3196 y(\013mrhd)178 b(36)2388 3309 y(\013m)m(v)m(ec)194 b(58)2388 3422 y(\013nc)m(hk)205 b(69)2388 3535 y(\013nk)m(ey)j(70)2388 3648 y(\013omem)155 b(97)2388 3761 y(\013op)s(en)202 b(32)2388 3874 y(\013p2d)p 2593 3874 V 200 w(115)2388 3987 y(\013p3d)p 2593 3987 V 200 w(115)2388 4100 y(\013p)s(c)m(ks)217 b(66)2388 4212 y(\013p)s(cl)273 b(60)2388 4325 y(\013p)s(cln)222 b(60)2388 4438 y(\013p)s(cls)192 b(119)2388 4551 y(\013p)s(cl)p 2565 4551 V 228 w(120)2388 4664 y(\013p)s(clu)222 b(60)2388 4777 y(\013p)s(cn)247 b(60)2388 4890 y(\013p)s(cn)p 2591 4890 V 202 w(119)2388 5003 y(\013p)s(com)177 b(42)2388 5116 y(\013p)s(dat)207 b(42)2388 5229 y(\013p)s(des)166 b(120)2388 5342 y(\013p)s(extn)119 b(103)2388 5454 y(\013pgp)p 2593 5454 V 200 w(115)2388 5567 y(\013ph)m(bn)146 b(106)2388 5680 y(\013phext)122 b(105)2388 5793 y(\013phis)229 b(42)2388 5906 y(\013phpr)158 b(105)2388 6019 y(\013phps)g(105)3054 656 y(\013ph)m(tb)180 b(105)3054 769 y(\013pkls)205 b(107)3054 882 y(\013pkn)p 3262 882 V 215 w(108)3054 995 y(\013pktp)180 b(108)3054 1107 y(\013pky)264 b(41)3054 1220 y(\013pkyt)183 b(108)3054 1333 y(\013pkyu)213 b(42)3054 1446 y(\013pky)p 3259 1446 V 218 w(107)3054 1559 y(\013plsw)187 b(107)3054 1672 y(\013pmrk)200 b(32)3054 1785 y(\013pmsg)j(68)3054 1898 y(\013pn)m(ul)190 b(113)3054 2011 y(\013ppn)212 b(115)3054 2124 y(\013ppn)p 3265 2124 V 212 w(115)3054 2237 y(\013ppr)227 b(115)3054 2349 y(\013pprn)222 b(46)3054 2462 y(\013ppru)176 b(115)3054 2575 y(\013ppr)p 3250 2575 V 227 w(115)3054 2688 y(\013pp)m(x)264 b(46)3054 2801 y(\013pp)m(xn)213 b(46)3054 2914 y(\013prec)244 b(42)3054 3027 y(\013prwu)207 b(60)3054 3140 y(\013pscl)213 b(113)3054 3253 y(\013pss)288 b(45)3054 3366 y(\013pss)p 3235 3366 V 242 w(116)3054 3479 y(\013psv)m(c)239 b(70)3054 3591 y(\013ptbb)177 b(119)3054 3704 y(\013ptdm)198 b(56)3054 3817 y(\013pthp)177 b(118)3054 3930 y(\013pun)m(t)226 b(43)3054 4043 y(\013rdef)210 b(104)3054 4156 y(\013reop)s(en)145 b(98)3054 4269 y(\013rprt)253 b(32)3054 4382 y(\013rsim)192 b(103)3054 4495 y(\013rtnm)167 b(100)3054 4608 y(\013rwrg)228 b(77)3054 4721 y(\013s2dt)244 b(67)3054 4833 y(\013s2tm)219 b(67)3054 4946 y(\013shdwn)110 b(101)3054 5059 y(\013sn)m(ul)205 b(113)3054 5172 y(\013sro)m(w)231 b(62)3054 5285 y(\013stmo)173 b(101)3054 5398 y(\013texp)237 b(63)3054 5511 y(\013thdu)223 b(36)3054 5624 y(\013theap)143 b(118)3054 5737 y(\013tk)m(ey)243 b(69)3054 5850 y(\013tm2s)219 b(67)3054 5963 y(\013tn)m(ul)206 b(113)p eop end %%Page: 184 192 TeXDict begin 184 191 bop 0 299 a Fj(184)2084 b Fh(APPENDIX)31 b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)50 543 y Fj(\013topn)216 b(32)50 656 y(\013tplt)252 b(98)50 769 y(\013trec)247 b(69)50 882 y(\013tscl)216 b(113)50 995 y(\013ucrd)k(42)50 1107 y(\013ukls)192 b(112)50 1220 y(\013uky)251 b(41)50 1333 y(\013ukyu)200 b(42)50 1446 y(\013uky)p 255 1446 28 4 v 205 w(112)50 1559 y(\013up)s(c)m(h)205 b(68)50 1672 y(\013up)s(c)m(k)j(66)50 1785 y(\013urlt)251 b(35)50 1898 y(\013v)m(c)m(ks)232 b(66)50 2011 y(\013v)m(ers)241 b(68)50 2124 y(\013vh)m(tps)134 b(101)50 2237 y(\013wldp)205 b(89)50 2349 y(\013wrhdu)143 b(37)50 2462 y(\013xyp)m(x)206 b(89)p eop end %%Page: 185 193 TeXDict begin 185 192 bop 0 1225 a Fg(App)5 b(endix)64 b(B)0 1687 y Fm(P)-6 b(arameter)77 b(De\014nitions)0 2180 y Fe(anynul)142 b(-)47 b(set)g(to)g(TRUE)g(\(=1\))f(if)i(any)e (returned)g(values)g(are)h(undefined,)e(else)i(FALSE)0 2293 y(array)190 b(-)47 b(array)f(of)i(numerical)d(data)h(values)h(to)g (read)f(or)i(write)0 2406 y(ascii)190 b(-)47 b(encoded)f(checksum)f (string)0 2518 y(binspec)94 b(-)47 b(the)g(input)f(table)h(binning)e (specifier)0 2631 y(bitpix)142 b(-)47 b(bits)g(per)g(pixel.)f(The)h (following)e(symbolic)g(mnemonics)h(are)h(predefined:)716 2744 y(BYTE_IMG)141 b(=)i(8)47 b(\(unsigned)f(char\))716 2857 y(SHORT_IMG)93 b(=)i(16)47 b(\(signed)f(short)g(integer\))716 2970 y(LONG_IMG)141 b(=)95 b(32)47 b(\(signed)f(long)h(integer\))716 3083 y(LONGLONG_IMG)d(=)96 b(64)47 b(\(signed)f(long)g(64-bit)g (integer\))716 3196 y(FLOAT_IMG)93 b(=)47 b(-32)g(\(float\))716 3309 y(DOUBLE_IMG)e(=)i(-64)g(\(double\).)525 3422 y(Two)g(additional)e (values,)h(USHORT_IMG)f(and)i(ULONG_IMG)e(are)i(also)f(available)525 3535 y(for)h(creating)e(unsigned)h(integer)g(images.)93 b(These)47 b(are)g(equivalent)e(to)525 3648 y(creating)h(a)h(signed)f (integer)g(image)g(with)h(BZERO)f(offset)g(keyword)g(values)525 3760 y(of)h(32768)g(or)g(2147483648,)d(respectively,)h(which)h(is)h (the)g(convention)e(that)525 3873 y(FITS)i(uses)f(to)h(store)g (unsigned)e(integers.)0 3986 y(card)238 b(-)47 b(header)f(record)g(to)h (be)h(read)e(or)h(written)f(\(80)h(char)g(max,)f(null-terminated\))0 4099 y(casesen)94 b(-)47 b(CASESEN)f(\(=1\))g(for)h(case-sensitive)d (string)i(matching,)g(else)g(CASEINSEN)g(\(=0\))0 4212 y(cmopt)190 b(-)47 b(grouping)f(table)g("compact")f(option)h (parameter.)f(Allowed)h(values)g(are:)525 4325 y(OPT_CMT_MBR)f(and)i (OPT_CMT_MBR_DEL.)0 4438 y(colname)94 b(-)47 b(name)g(of)g(the)g (column)f(\(null-terminated\))0 4551 y(colnum)142 b(-)47 b(column)f(number)g(\(first)g(column)g(=)i(1\))0 4664 y(colspec)94 b(-)47 b(the)g(input)f(file)h(column)f(specification;)e (used)j(to)g(delete,)f(create,)f(or)j(rename)525 4777 y(table)e(columns)0 4890 y(comment)94 b(-)47 b(the)g(keyword)f(comment) g(field)g(\(72)h(char)f(max,)h(null-terminated\))0 5002 y(complm)142 b(-)47 b(should)f(the)h(checksum)f(be)h(complemented?)0 5115 y(comptype)f(-)h(compression)e(algorithm)g(to)i(use:)g(GZIP_1,)f (RICE_1,)f(HCOMPRESS_1,)g(or)i(PLIO_1)0 5228 y(coordtype-)e(type)i(of)g (coordinate)e(projection)g(\(-SIN,)h(-TAN,)g(-ARC,)h(-NCP,)525 5341 y(-GLS,)f(-MER,)h(or)g(-AIT\))0 5454 y(cpopt)190 b(-)47 b(grouping)f(table)g(copy)h(option)f(parameter.)f(Allowed)g (values)i(are:)525 5567 y(OPT_GCP_GPT,)d(OPT_GCP_MBR,)h(OPT_GCP_ALL,)f (OPT_MCP_ADD,)h(OPT_MCP_NADD,)525 5680 y(OPT_MCP_REPL,)f(amd)j (OPT_MCP_MOV.)1882 5942 y Fj(185)p eop end %%Page: 186 194 TeXDict begin 186 193 bop 0 299 a Fj(186)1822 b Fh(APPENDIX)31 b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(create_col-)45 b(If)i(TRUE,)f(then)h(insert)f(a)h(new)g(column)f(in)i(the)f(table,)f (otherwise)525 668 y(overwrite)f(the)i(existing)f(column.)0 781 y(current)94 b(-)47 b(if)g(TRUE,)g(then)f(the)h(current)f(HDU)h (will)f(be)i(copied)0 894 y(dataok)142 b(-)47 b(was)g(the)g(data)f (unit)h(verification)e(successful)g(\(=1\))h(or)525 1007 y(not)h(\(=)g(-1\).)94 b(Equals)47 b(zero)f(if)h(the)g(DATASUM)f (keyword)g(is)h(not)g(present.)0 1120 y(datasum)94 b(-)47 b(32-bit)f(1's)h(complement)e(checksum)h(for)g(the)h(data)g(unit)0 1233 y(dataend)94 b(-)47 b(address)f(\(in)h(bytes\))f(of)h(the)g(end)g (of)g(the)g(HDU)0 1346 y(datastart-)e(address)h(\(in)h(bytes\))f(of)h (the)g(start)f(of)h(the)g(data)g(unit)0 1458 y(datatype)f(-)h (specifies)e(the)i(data)g(type)f(of)i(the)f(value.)93 b(Allowed)46 b(value)h(are:)94 b(TSTRING,)525 1571 y(TLOGICAL,)45 b(TBYTE,)h(TSBYTE,)g(TSHORT,)g(TUSHORT,)g(TINT,)g(TUINT,)g(TLONG,)g (TULONG,)525 1684 y(TFLOAT,)g(TDOUBLE,)f(TCOMPLEX,)h(and)h(TDBLCOMPLEX) 0 1797 y(datestr)94 b(-)47 b(FITS)g(date/time)e(string:)h ('YYYY-MM-DDThh:mm:ss.dd)o(d',)41 b('YYYY-MM-dd',)525 1910 y(or)47 b('dd/mm/yy')0 2023 y(day)286 b(-)47 b(calendar)f(day)g (\(UTC\))h(\(1-31\))0 2136 y(decimals)f(-)h(number)f(of)h(decimal)f (places)g(to)h(be)h(displayed)0 2249 y(deltasize)d(-)j(increment)d(for) i(allocating)e(more)i(memory)0 2362 y(dim1)238 b(-)47 b(declared)f(size)g(of)h(the)g(first)g(dimension)e(of)i(the)g(image)f (or)i(cube)e(array)0 2475 y(dim2)238 b(-)47 b(declared)f(size)g(of)h (the)g(second)f(dimension)g(of)h(the)g(data)f(cube)h(array)0 2588 y(dispwidth)e(-)j(display)e(width)g(of)h(a)h(column)e(=)h(length)f (of)h(string)f(that)h(will)g(be)g(read)0 2700 y(dtype)190 b(-)47 b(data)g(type)f(of)h(the)g(keyword)f(\('C',)h('L',)f('I',)h('F') g(or)g('X'\))764 2813 y(C)g(=)h(character)d(string)764 2926 y(L)i(=)h(logical)764 3039 y(I)f(=)h(integer)764 3152 y(F)f(=)h(floating)d(point)h(number)764 3265 y(X)h(=)h(complex,)d (e.g.,)h("\(1.23,)g(-4.56\)")0 3378 y(err_msg)94 b(-)47 b(error)f(message)g(on)h(the)g(internal)f(stack)g(\(80)h(chars)f(max\)) 0 3491 y(err_text)g(-)h(error)f(message)g(string)g(corresponding)e(to)k (error)e(number)g(\(30)h(chars)f(max\))0 3604 y(exact)190 b(-)47 b(TRUE)g(\(=1\))f(if)h(the)g(strings)f(match)h(exactly;)525 3717 y(FALSE)f(\(=0\))h(if)g(wildcards)e(are)i(used)0 3830 y(exclist)94 b(-)47 b(array)f(of)i(pointers)d(to)i(keyword)f (names)g(to)i(be)f(excluded)e(from)i(search)0 3942 y(exists)142 b(-)47 b(flag)g(indicating)e(whether)g(the)i(file)g(or)g(compressed)e (file)i(exists)f(on)h(disk)0 4055 y(expr)238 b(-)47 b(boolean)f(or)h (arithmetic)e(expression)0 4168 y(extend)142 b(-)47 b(TRUE)g(\(=1\))f (if)h(FITS)g(file)g(may)g(have)f(extensions,)f(else)i(FALSE)f(\(=0\))0 4281 y(extname)94 b(-)47 b(value)f(of)i(the)e(EXTNAME)g(keyword)g (\(null-terminated\))0 4394 y(extspec)94 b(-)47 b(the)g(extension)e(or) i(HDU)g(specifier;)e(a)j(number)e(or)h(name,)f(version,)g(and)h(type)0 4507 y(extver)142 b(-)47 b(value)f(of)i(the)e(EXTVER)h(keyword)e(=)j (integer)e(version)f(number)0 4620 y(filename)h(-)h(full)g(name)f(of)h (the)g(FITS)g(file,)f(including)g(optional)f(HDU)i(and)g(filtering)e (specs)0 4733 y(filetype)h(-)h(type)g(of)g(file)f(\(file://,)g(ftp://,) g(http://,)f(etc.\))0 4846 y(filter)142 b(-)47 b(the)g(input)f(file)h (filtering)e(specifier)0 4959 y(firstchar-)g(starting)h(byte)g(in)h (the)g(row)g(\(first)f(byte)h(of)g(row)g(=)g(1\))0 5072 y(firstfailed)e(-)i(member)f(HDU)h(ID)g(\(if)g(positive\))f(or)h (grouping)e(table)i(GRPIDn)f(index)525 5185 y(value)g(\(if)h (negative\))f(that)g(failed)g(grouping)g(table)g(verification.)0 5297 y(firstelem-)f(first)h(element)g(in)h(a)h(vector)e(\(ignored)f (for)i(ASCII)g(tables\))0 5410 y(firstrow)f(-)h(starting)f(row)g (number)h(\(first)f(row)h(of)g(table)f(=)i(1\))0 5523 y(following-)d(if)i(TRUE,)g(any)f(HDUs)h(following)e(the)i(current)f (HDU)h(will)g(be)g(copied)0 5636 y(fpixel)142 b(-)47 b(coordinate)e(of)i(the)g(first)f(pixel)h(to)g(be)g(read)g(or)g (written)f(in)h(the)p eop end %%Page: 187 195 TeXDict begin 187 194 bop 3764 299 a Fj(187)525 555 y Fe(FITS)47 b(array.)93 b(The)47 b(array)g(must)f(be)i(of)f(length)f (NAXIS)g(and)h(have)g(values)f(such)525 668 y(that)h(fpixel[0])e(is)i (in)g(the)g(range)g(1)g(to)g(NAXIS1,)f(fpixel[1])f(is)i(in)h(the)525 781 y(range)e(1)i(to)f(NAXIS2,)f(etc.)0 894 y(fptr)238 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e(structure)h(describing)f(the)i (FITS)f(file.)0 1007 y(frac)238 b(-)47 b(factional)e(part)i(of)g(the)g (keyword)f(value)0 1120 y(gcount)142 b(-)47 b(number)f(of)h(groups)f (in)i(the)e(primary)g(array)h(\(usually)e(=)j(1\))0 1233 y(gfptr)190 b(-)47 b(fitsfile*)e(pointer)h(to)h(a)h(grouping)d(table)i (HDU.)0 1346 y(group)190 b(-)47 b(GRPIDn/GRPLCn)d(index)j(value)f (identifying)f(a)i(grouping)f(table)g(HDU,)h(or)525 1458 y(data)g(group)f(number)g(\(=0)h(for)g(non-grouped)e(data\))0 1571 y(grouptype)g(-)j(Grouping)d(table)i(parameter)e(that)i(specifies) e(the)i(columns)f(to)h(be)525 1684 y(created)f(in)h(a)g(grouping)f (table)g(HDU.)h(Allowed)f(values)g(are:)h(GT_ID_ALL_URI,)525 1797 y(GT_ID_REF,)e(GT_ID_POS,)g(GT_ID_ALL,)g(GT_ID_REF_URI,)f(and)j (GT_ID_POS_URI.)0 1910 y(grpname)94 b(-)47 b(value)f(to)i(use)e(for)h (the)g(GRPNAME)f(keyword)g(value.)0 2023 y(hdunum)142 b(-)47 b(sequence)f(number)g(of)h(the)g(HDU)g(\(Primary)e(array)i(=)g (1\))0 2136 y(hduok)190 b(-)47 b(was)g(the)g(HDU)g(verification)d (successful)h(\(=1\))i(or)525 2249 y(not)g(\(=)g(-1\).)94 b(Equals)47 b(zero)f(if)h(the)g(CHECKSUM)f(keyword)g(is)h(not)g (present.)0 2362 y(hdusum)142 b(-)47 b(32)g(bit)g(1's)g(complement)e (checksum)h(for)g(the)h(entire)f(CHDU)0 2475 y(hdutype)94 b(-)47 b(HDU)g(type:)f(IMAGE_HDU)g(\(0\),)g(ASCII_TBL)f(\(1\),)i (BINARY_TBL)e(\(2\),)i(ANY_HDU)f(\(-1\))0 2588 y(header)142 b(-)47 b(returned)f(character)f(string)h(containing)f(all)i(the)g (keyword)f(records)0 2700 y(headstart-)f(starting)h(address)f(\(in)i (bytes\))f(of)i(the)e(CHDU)0 2813 y(heapsize)g(-)h(size)g(of)g(the)g (binary)f(table)g(heap,)h(in)g(bytes)0 2926 y(history)94 b(-)47 b(the)g(HISTORY)f(keyword)g(comment)f(string)h(\(70)h(char)g (max,)g(null-terminated\))0 3039 y(hour)238 b(-)47 b(hour)g(within)f (day)h(\(UTC\))f(\(0)h(-)h(23\))0 3152 y(inc)286 b(-)47 b(sampling)f(interval)f(for)i(pixels)f(in)h(each)g(FITS)g(dimension)0 3265 y(inclist)94 b(-)47 b(array)f(of)i(pointers)d(to)i(matching)f (keyword)g(names)0 3378 y(incolnum)g(-)h(input)f(column)g(number;)g (range)h(=)g(1)h(to)f(TFIELDS)0 3491 y(infile)142 b(-)47 b(the)g(input)f(filename,)g(including)f(path)h(if)i(specified)0 3604 y(infptr)142 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e(structure)h (describing)f(the)i(input)f(FITS)h(file.)0 3717 y(intval)142 b(-)47 b(integer)f(part)g(of)i(the)f(keyword)e(value)0 3830 y(iomode)142 b(-)47 b(file)g(access)f(mode:)g(either)g(READONLY)g (\(=0\))g(or)i(READWRITE)d(\(=1\))0 3942 y(keyname)94 b(-)47 b(name)g(of)g(a)g(keyword)f(\(8)h(char)g(max,)g (null-terminated\))0 4055 y(keynum)142 b(-)47 b(position)f(of)h (keyword)f(in)h(header)f(\(1st)g(keyword)g(=)i(1\))0 4168 y(keyroot)94 b(-)47 b(root)g(string)f(for)h(the)g(keyword)e(name)i (\(5)g(char)g(max,)f(null-terminated\))0 4281 y(keysexist-)f(number)h (of)h(existing)f(keyword)g(records)f(in)j(the)f(CHU)0 4394 y(keytype)94 b(-)47 b(header)f(record)g(type:)h(-1=delete;)92 b(0=append)46 b(or)h(replace;)907 4507 y(1=append;)e(2=this)h(is)h(the) g(END)g(keyword)0 4620 y(longstr)94 b(-)47 b(arbitrarily)e(long)h (string)g(keyword)g(value)h(\(null-terminated\))0 4733 y(lpixel)142 b(-)47 b(coordinate)e(of)i(the)g(last)g(pixel)f(to)h(be)g (read)g(or)g(written)f(in)h(the)525 4846 y(FITS)g(array.)93 b(The)47 b(array)g(must)f(be)i(of)f(length)f(NAXIS)g(and)h(have)g (values)f(such)525 4959 y(that)h(lpixel[0])e(is)i(in)g(the)g(range)g(1) g(to)g(NAXIS1,)f(lpixel[1])f(is)i(in)h(the)525 5072 y(range)e(1)i(to)f (NAXIS2,)f(etc.)0 5185 y(match)190 b(-)47 b(TRUE)g(\(=1\))f(if)h(the)g (2)h(strings)e(match,)g(else)g(FALSE)h(\(=0\))0 5297 y(maxdim)142 b(-)47 b(maximum)f(number)g(of)h(values)f(to)h(return)0 5410 y(member)142 b(-)47 b(row)g(number)f(of)h(a)h(grouping)d(table)i (member)f(HDU.)0 5523 y(memptr)142 b(-)47 b(pointer)f(to)h(the)g(a)g (FITS)g(file)g(in)g(memory)0 5636 y(mem_realloc)e(-)i(pointer)f(to)h(a) h(function)d(for)i(reallocating)e(more)h(memory)p eop end %%Page: 188 196 TeXDict begin 188 195 bop 0 299 a Fj(188)1822 b Fh(APPENDIX)31 b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(memsize)94 b(-)47 b(size)g(of)g(the)g(memory)f(block)g(allocated)f(for)i(the)g (FITS)g(file)0 668 y(mfptr)190 b(-)47 b(fitsfile*)e(pointer)h(to)h(a)h (grouping)d(table)i(member)f(HDU.)0 781 y(mgopt)190 b(-)47 b(grouping)f(table)g(merge)g(option)g(parameter.)f(Allowed)h(values)g (are:)525 894 y(OPT_MRG_COPY,)e(and)j(OPT_MRG_MOV.)0 1007 y(minute)142 b(-)47 b(minute)f(within)g(hour)h(\(UTC\))f(\(0)h(-)h (59\))0 1120 y(month)190 b(-)47 b(calendar)f(month)g(\(UTC\))g(\(1)h(-) h(12\))0 1233 y(morekeys)e(-)h(space)f(in)i(the)e(header)h(for)f(this)h (many)g(more)f(keywords)0 1346 y(n_good_rows)f(-)i(number)f(of)h(rows)g (evaluating)e(to)i(TRUE)0 1458 y(namelist)f(-)h(string)f(containing)f (a)j(comma)e(or)h(space)f(delimited)g(list)g(of)i(names)0 1571 y(naxes)190 b(-)47 b(size)g(of)g(each)f(dimension)g(in)h(the)g (FITS)f(array)0 1684 y(naxis)190 b(-)47 b(number)f(of)h(dimensions)e (in)i(the)g(FITS)g(array)0 1797 y(naxis1)142 b(-)47 b(length)f(of)h (the)g(X/first)f(axis)h(of)g(the)g(FITS)f(array)0 1910 y(naxis2)142 b(-)47 b(length)f(of)h(the)g(Y/second)f(axis)g(of)i(the)e (FITS)h(array)0 2023 y(naxis3)142 b(-)47 b(length)f(of)h(the)g(Z/third) f(axis)h(of)g(the)g(FITS)f(array)0 2136 y(nbytes)142 b(-)47 b(number)f(of)h(bytes)g(or)g(characters)e(to)i(read)g(or)g (write)0 2249 y(nchars)142 b(-)47 b(number)f(of)h(characters)e(to)i (read)g(or)g(write)0 2362 y(nelements-)e(number)h(of)h(data)g(elements) e(to)j(read)e(or)h(write)0 2475 y(newfptr)94 b(-)47 b(returned)f (pointer)f(to)j(the)e(reopened)g(file)0 2588 y(newveclen-)f(new)i (value)f(for)h(the)g(column)f(vector)g(repeat)g(parameter)0 2700 y(nexc)238 b(-)47 b(number)f(of)h(names)g(in)g(the)g(exclusion)e (list)i(\(may)f(=)i(0\))0 2813 y(nfound)142 b(-)47 b(number)f(of)h (keywords)f(found)g(\(highest)g(keyword)g(number\))0 2926 y(nkeys)190 b(-)47 b(number)f(of)h(keywords)f(in)h(the)g(sequence) 0 3039 y(ninc)238 b(-)47 b(number)f(of)h(names)g(in)g(the)g(inclusion)e (list)0 3152 y(nmembers)h(-)h(Number)f(of)h(grouping)f(table)g(members) g(\(NAXIS2)g(value\).)0 3265 y(nmove)190 b(-)47 b(number)f(of)h(HDUs)g (to)g(move)g(\(+)g(or)g(-\),)g(relative)f(to)h(current)f(position)0 3378 y(nocomments)f(-)i(if)h(equal)e(to)h(TRUE,)g(then)f(no)h (commentary)e(keywords)h(will)h(be)g(copied)0 3491 y(noisebits-)e (number)h(of)h(bits)g(to)g(ignore)f(when)h(compressing)e(floating)g (point)h(images)0 3604 y(nrows)190 b(-)47 b(number)f(of)h(rows)g(in)g (the)g(table)0 3717 y(nstart)142 b(-)47 b(first)f(integer)g(value)0 3830 y(nullarray-)f(set)i(to)g(TRUE)g(\(=1\))f(if)i(corresponding)c (data)i(element)g(is)h(undefined)0 3942 y(nulval)142 b(-)47 b(numerical)e(value)i(to)g(represent)e(undefined)g(pixels)0 4055 y(nulstr)142 b(-)47 b(character)e(string)h(used)h(to)g(represent)e (undefined)h(values)g(in)h(ASCII)f(table)0 4168 y(numval)142 b(-)47 b(numerical)e(data)i(value,)f(of)h(the)g(appropriate)e(data)h (type)0 4281 y(offset)142 b(-)47 b(byte)g(offset)f(in)h(the)g(heap)f (or)i(data)e(unit)h(to)g(the)g(first)f(element)g(of)h(the)g(vector)0 4394 y(openfptr)f(-)h(pointer)f(to)h(a)g(currently)f(open)g(FITS)h (file)0 4507 y(overlap)94 b(-)47 b(number)f(of)h(bytes)g(in)g(the)g (binary)f(table)g(heap)h(pointed)f(to)h(by)g(more)g(than)f(1)525 4620 y(descriptor)0 4733 y(outcolnum-)f(output)h(column)g(number;)g (range)g(=)i(1)f(to)g(TFIELDS)f(+)i(1)0 4846 y(outfile)94 b(-)47 b(and)g(optional)e(output)i(filename;)e(the)i(input)f(file)h (will)f(be)i(copied)e(to)h(this)f(prior)525 4959 y(to)h(opening)f(the)h (file)0 5072 y(outfptr)94 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e (structure)h(describing)f(the)i(output)f(FITS)g(file.)0 5185 y(pcount)142 b(-)47 b(value)f(of)i(the)e(PCOUNT)h(keyword)e(=)j (size)e(of)i(binary)e(table)g(heap)0 5297 y(previous)g(-)h(if)g(TRUE,)g (any)f(previous)g(HDUs)h(in)g(the)g(input)f(file)h(will)f(be)i(copied.) 0 5410 y(repeat)142 b(-)47 b(length)f(of)h(column)f(vector)g(\(e.g.)h (12J\);)f(==)h(1)h(for)f(ASCII)f(table)0 5523 y(rmopt)190 b(-)47 b(grouping)f(table)g(remove)g(option)g(parameter.)f(Allowed)h (values)g(are:)525 5636 y(OPT_RM_GPT,)f(OPT_RM_ENTRY,)f(OPT_RM_MBR,)h (and)i(OPT_RM_ALL.)p eop end %%Page: 189 197 TeXDict begin 189 196 bop 3764 299 a Fj(189)0 555 y Fe(rootname)46 b(-)h(root)g(filename,)e(minus)h(any)h(extension)e(or)j(filtering)d (specifications)0 668 y(rot)286 b(-)47 b(celestial)e(coordinate)g (rotation)h(angle)g(\(degrees\))0 781 y(rowlen)142 b(-)47 b(length)f(of)h(a)h(table)e(row,)h(in)g(characters)e(or)i(bytes)0 894 y(rowlist)94 b(-)47 b(sorted)f(list)h(of)g(row)g(numbers)f(to)h(be) g(deleted)f(from)g(the)h(table)0 1007 y(rownum)142 b(-)47 b(number)f(of)h(the)g(row)g(\(first)f(row)h(=)h(1\))0 1120 y(rowrange)e(-)h(list)g(of)g(rows)f(or)i(row)f(ranges:)e ('3,6-8,12,56-80')f(or)j('500-')0 1233 y(row_status)e(-)i(array)g(of)g (True/False)e(results)h(for)h(each)f(row)h(that)g(was)g(evaluated)0 1346 y(scale)190 b(-)47 b(linear)f(scaling)g(factor;)g(true)g(value)h (=)g(\(FITS)g(value\))f(*)h(scale)f(+)i(zero)0 1458 y(second)142 b(-)47 b(second)f(within)g(minute)g(\(0)h(-)h(60.9999999999\))c(\(leap) i(second!\))0 1571 y(section)94 b(-)47 b(section)f(of)h(image)f(to)i (be)f(copied)f(\(e.g.)g(21:80,101:200\))0 1684 y(simple)142 b(-)47 b(TRUE)g(\(=1\))f(if)h(FITS)g(file)g(conforms)e(to)i(the)g (Standard,)f(else)g(FALSE)h(\(=0\))0 1797 y(space)190 b(-)47 b(number)f(of)h(blank)g(spaces)f(to)h(leave)f(between)g(ASCII)g (table)h(columns)0 1910 y(status)142 b(-)47 b(returned)f(error)g (status)g(code)h(\(0)g(=)g(OK\))0 2023 y(sum)286 b(-)47 b(32)g(bit)g(unsigned)f(checksum)f(value)0 2136 y(tbcol)190 b(-)47 b(byte)g(position)e(in)i(row)g(to)g(start)g(of)g(column)f(\(1st) h(col)g(has)g(tbcol)f(=)h(1\))0 2249 y(tdisp)190 b(-)47 b(Fortran)f(style)g(display)g(format)g(for)h(the)g(table)f(column)0 2362 y(tdimstr)94 b(-)47 b(the)g(value)f(of)h(the)g(TDIMn)g(keyword)0 2475 y(templt)142 b(-)47 b(template)f(string)g(used)g(in)h(comparison)e (\(null-terminated\))0 2588 y(tfields)94 b(-)47 b(number)f(of)h(fields) f(\(columns\))g(in)h(the)g(table)0 2700 y(tfopt)190 b(-)47 b(grouping)f(table)g(member)g(transfer)g(option)g(parameter.)f(Allowed) g(values)i(are:)525 2813 y(OPT_MCP_ADD,)d(and)j(OPT_MCP_MOV.)0 2926 y(tform)190 b(-)47 b(format)f(of)h(the)g(column)f (\(null-terminated\);)d(allowed)j(values)g(are:)525 3039 y(ASCII)g(tables:)94 b(Iw,)47 b(Aw,)g(Fww.dd,)f(Eww.dd,)f(or)j(Dww.dd) 525 3152 y(Binary)e(tables:)g(rL,)h(rX,)g(rB,)g(rI,)g(rJ,)f(rA,)h(rAw,) g(rE,)g(rD,)g(rC,)g(rM)525 3265 y(where)f('w'=width)g(of)h(the)g (field,)f('d'=no.)g(of)h(decimals,)e('r'=repeat)g(count.)525 3378 y(Variable)h(length)g(array)g(columns)g(are)h(denoted)f(by)h(a)g ('1P')g(before)f(the)h(data)f(type)525 3491 y(character)f(\(e.g.,)h ('1PJ'\).)94 b(When)47 b(creating)e(a)j(binary)e(table,)g(2)h(addition) f(tform)525 3604 y(data)h(type)f(codes)h(are)g(recognized)e(by)i (CFITSIO:)e('rU')i(and)g('rV')f(for)h(unsigned)525 3717 y(16-bit)f(and)h(unsigned)f(32-bit)g(integer,)f(respectively.)0 3942 y(theap)190 b(-)47 b(zero)g(indexed)e(byte)i(offset)f(of)h (starting)f(address)g(of)h(the)g(heap)525 4055 y(relative)f(to)h(the)g (beginning)e(of)i(the)g(binary)f(table)g(data)0 4168 y(tilesize)g(-)h(array)f(of)i(length)e(NAXIS)g(that)h(specifies)e(the)i (dimensions)e(of)525 4281 y(the)i(image)f(compression)f(tiles)0 4394 y(ttype)190 b(-)47 b(label)f(or)i(name)e(for)h(table)f(column)h (\(null-terminated\))0 4507 y(tunit)190 b(-)47 b(physical)f(unit)g(for) h(table)f(column)h(\(null-terminated\))0 4620 y(typechar)f(-)h (symbolic)f(code)g(of)h(the)g(table)g(column)f(data)g(type)0 4733 y(typecode)g(-)h(data)g(type)f(code)h(of)g(the)g(table)f(column.) 94 b(The)47 b(negative)e(of)525 4846 y(the)i(value)f(indicates)g(a)h (variable)f(length)g(array)g(column.)764 4959 y(Datatype)618 b(typecode)189 b(Mnemonic)764 5072 y(bit,)46 b(X)907 b(1)381 b(TBIT)764 5185 y(byte,)46 b(B)811 b(11)381 b(TBYTE)764 5297 y(logical,)45 b(L)668 b(14)381 b(TLOGICAL)764 5410 y(ASCII)46 b(character,)f(A)286 b(16)381 b(TSTRING)764 5523 y(short)46 b(integer,)g(I)381 b(21)g(TSHORT)764 5636 y(integer,)45 b(J)668 b(41)381 b(TINT32BIT)46 b(\(same)g(as)h (TLONG\))p eop end %%Page: 190 198 TeXDict begin 190 197 bop 0 299 a Fj(190)1822 b Fh(APPENDIX)31 b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)764 555 y Fe(long)46 b(long)h(integer,)e(K)191 b(81)381 b(TLONGLONG)764 668 y(real,)46 b(E)811 b(42)381 b(TFLOAT)764 781 y(double)46 b(precision,)f(D)238 b(82)381 b(TDOUBLE)764 894 y(complex,)45 b(C)668 b(83)381 b(TCOMPLEX)764 1007 y(double)46 b(complex,)f(M)286 b(163)381 b(TDBLCOMPLEX)0 1120 y(unit)238 b(-)47 b(the)g(physical)e (unit)i(string)f(\(e.g.,)g('km/s'\))g(for)h(a)g(keyword)0 1233 y(unused)142 b(-)47 b(number)f(of)h(unused)f(bytes)h(in)g(the)g (binary)f(table)g(heap)0 1346 y(urltype)94 b(-)47 b(the)g(file)g(type)f (of)h(the)g(FITS)g(file)g(\(file://,)e(ftp://,)h(mem://,)f(etc.\))0 1458 y(validheap-)g(returned)h(value)g(=)h(FALSE)g(if)g(any)g(of)g(the) g(variable)e(length)i(array)525 1571 y(address)f(are)h(outside)f(the)g (valid)h(range)f(of)h(addresses)f(in)h(the)g(heap)0 1684 y(value)190 b(-)47 b(the)g(keyword)f(value)g(string)g(\(70)h(char)g (max,)f(null-terminated\))0 1797 y(version)94 b(-)47 b(current)f(version)g(number)g(of)h(the)g(CFITSIO)f(library)0 1910 y(width)190 b(-)47 b(width)f(of)i(the)e(character)g(string)g (field)0 2023 y(xcol)238 b(-)47 b(number)f(of)h(the)g(column)f (containing)f(the)i(X)h(coordinate)d(values)0 2136 y(xinc)238 b(-)47 b(X)g(axis)g(coordinate)e(increment)g(at)j(reference)d(pixel)h (\(deg\))0 2249 y(xpix)238 b(-)47 b(X)g(axis)g(pixel)f(location)0 2362 y(xpos)238 b(-)47 b(X)g(axis)g(celestial)e(coordinate)g(\(usually) h(RA\))h(\(deg\))0 2475 y(xrefpix)94 b(-)47 b(X)g(axis)g(reference)e (pixel)i(array)f(location)0 2588 y(xrefval)94 b(-)47 b(X)g(axis)g(coordinate)e(value)h(at)i(the)f(reference)e(pixel)h (\(deg\))0 2700 y(ycol)238 b(-)47 b(number)f(of)h(the)g(column)f (containing)f(the)i(X)h(coordinate)d(values)0 2813 y(year)238 b(-)47 b(calendar)f(year)g(\(e.g.)h(1999,)f(2000,)g(etc\))0 2926 y(yinc)238 b(-)47 b(Y)g(axis)g(coordinate)e(increment)g(at)j (reference)d(pixel)h(\(deg\))0 3039 y(ypix)238 b(-)47 b(y)g(axis)g(pixel)f(location)0 3152 y(ypos)238 b(-)47 b(y)g(axis)g(celestial)e(coordinate)g(\(usually)h(DEC\))h(\(deg\))0 3265 y(yrefpix)94 b(-)47 b(Y)g(axis)g(reference)e(pixel)i(array)f (location)0 3378 y(yrefval)94 b(-)47 b(Y)g(axis)g(coordinate)e(value)h (at)i(the)f(reference)e(pixel)h(\(deg\))0 3491 y(zero)238 b(-)47 b(scaling)f(offset;)g(true)g(value)h(=)g(\(FITS)f(value\))h(*)g (scale)f(+)i(zero)p eop end %%Page: 191 199 TeXDict begin 191 198 bop 0 1225 a Fg(App)5 b(endix)64 b(C)0 1687 y Fm(CFITSIO)76 b(Error)h(Status)h(Co)6 b(des)0 2180 y Fj(The)28 b(follo)m(wing)h(table)g(lists)g(all)g(the)f(error)g (status)g(co)s(des)g(used)f(b)m(y)h(CFITSIO.)f(Programmers)h(are)g (encouraged)0 2293 y(to)37 b(use)e(the)h(sym)m(b)s(olic)h(mnemonics)e (\(de\014ned)g(in)h(the)g(\014le)g(\014tsio.h\))h(rather)e(than)h(the)g (actual)h(in)m(teger)h(status)0 2406 y(v)-5 b(alues)31 b(to)g(impro)m(v)m(e)g(the)g(readabilit)m(y)g(of)g(their)f(co)s(de.)48 2665 y Fe(Symbolic)45 b(Const)190 b(Value)237 b(Meaning)48 2778 y(--------------)187 b(-----)94 b(------------------------)o(----) o(---)o(----)o(----)o(--)1002 2891 y(0)191 b(OK,)47 b(no)g(error)48 3004 y(SAME_FILE)427 b(101)190 b(input)46 b(and)h(output)f(files)h(are) g(the)f(same)48 3117 y(TOO_MANY_FILES)187 b(103)j(tried)46 b(to)h(open)g(too)g(many)g(FITS)f(files)h(at)g(once)48 3230 y(FILE_NOT_OPENED)139 b(104)190 b(could)46 b(not)h(open)g(the)g (named)f(file)48 3343 y(FILE_NOT_CREATED)91 b(105)190 b(could)46 b(not)h(create)f(the)h(named)g(file)48 3456 y(WRITE_ERROR)331 b(106)190 b(error)46 b(writing)g(to)h(FITS)g(file)48 3569 y(END_OF_FILE)331 b(107)190 b(tried)46 b(to)h(move)g(past)g(end)g (of)g(file)48 3681 y(READ_ERROR)379 b(108)190 b(error)46 b(reading)g(from)h(FITS)f(file)48 3794 y(FILE_NOT_CLOSED)139 b(110)190 b(could)46 b(not)h(close)g(the)f(file)48 3907 y(ARRAY_TOO_BIG)235 b(111)190 b(array)46 b(dimensions)f(exceed)h (internal)g(limit)48 4020 y(READONLY_FILE)235 b(112)190 b(Cannot)46 b(write)g(to)i(readonly)d(file)48 4133 y(MEMORY_ALLOCATION) e(113)190 b(Could)46 b(not)h(allocate)f(memory)48 4246 y(BAD_FILEPTR)331 b(114)190 b(invalid)46 b(fitsfile)f(pointer)48 4359 y(NULL_INPUT_PTR)187 b(115)j(NULL)47 b(input)f(pointer)g(to)h (routine)48 4472 y(SEEK_ERROR)379 b(116)190 b(error)46 b(seeking)g(position)g(in)h(file)48 4585 y(BAD_NETTIMEOUT)187 b(117)j(bad)47 b(value)f(for)h(file)g(download)e(timeout)h(setting)48 4811 y(BAD_URL_PREFIX)235 b(121)142 b(invalid)46 b(URL)h(prefix)f(on)h (file)g(name)48 4924 y(TOO_MANY_DRIVERS)139 b(122)j(tried)46 b(to)h(register)f(too)h(many)g(IO)g(drivers)48 5036 y (DRIVER_INIT_FAILED)c(123)142 b(driver)46 b(initialization)e(failed)48 5149 y(NO_MATCHING_DRIVER)f(124)142 b(matching)45 b(driver)i(is)g(not)g (registered)48 5262 y(URL_PARSE_ERROR)187 b(125)142 b(failed)46 b(to)h(parse)g(input)f(file)h(URL)48 5375 y(RANGE_PARSE_ERROR)91 b(126)142 b(parse)46 b(error)h(in)g(range)f(list)48 5601 y(SHARED_BADARG)235 b(151)190 b(bad)47 b(argument)e(in)j(shared)e (memory)g(driver)48 5714 y(SHARED_NULPTR)235 b(152)190 b(null)47 b(pointer)e(passed)h(as)i(an)f(argument)1882 5942 y Fj(191)p eop end %%Page: 192 200 TeXDict begin 192 199 bop 0 299 a Fj(192)1589 b Fh(APPENDIX)31 b(C.)61 b(CFITSIO)29 b(ERR)m(OR)h(ST)-8 b(A)g(TUS)30 b(CODES)48 555 y Fe(SHARED_TABFULL)187 b(153)j(no)47 b(more)g(free)f(shared)g(memory)h(handles)48 668 y(SHARED_NOTINIT)187 b(154)j(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)48 781 y(SHARED_IPCERR)235 b(155)190 b(IPC)47 b(error)f(returned)g(by)h(a) g(system)f(call)48 894 y(SHARED_NOMEM)283 b(156)190 b(no)47 b(memory)f(in)h(shared)f(memory)h(driver)48 1007 y(SHARED_AGAIN)283 b(157)190 b(resource)45 b(deadlock)h(would)g(occur)48 1120 y(SHARED_NOFILE)235 b(158)190 b(attempt)46 b(to)h(open/create)e (lock)h(file)h(failed)48 1233 y(SHARED_NORESIZE)139 b(159)190 b(shared)46 b(memory)g(block)g(cannot)h(be)g(resized)f(at)h(the)g (moment)48 1458 y(HEADER_NOT_EMPTY)91 b(201)190 b(header)46 b(already)g(contains)f(keywords)48 1571 y(KEY_NO_EXIST)283 b(202)190 b(keyword)46 b(not)h(found)f(in)h(header)48 1684 y(KEY_OUT_BOUNDS)187 b(203)j(keyword)46 b(record)g(number)g(is)h (out)g(of)g(bounds)48 1797 y(VALUE_UNDEFINED)139 b(204)190 b(keyword)46 b(value)g(field)g(is)i(blank)48 1910 y(NO_QUOTE)475 b(205)190 b(string)46 b(is)h(missing)f(the)h(closing)f(quote)48 2023 y(BAD_INDEX_KEY)235 b(206)190 b(illegal)46 b(indexed)g(keyword)f (name)i(\(e.g.)f('TFORM1000'\))48 2136 y(BAD_KEYCHAR)331 b(207)190 b(illegal)46 b(character)f(in)i(keyword)f(name)h(or)g(card)48 2249 y(BAD_ORDER)427 b(208)190 b(required)45 b(keywords)h(out)h(of)g (order)48 2362 y(NOT_POS_INT)331 b(209)190 b(keyword)46 b(value)g(is)h(not)g(a)h(positive)d(integer)48 2475 y(NO_END)571 b(210)190 b(couldn't)45 b(find)i(END)g(keyword)48 2588 y(BAD_BITPIX)379 b(211)190 b(illegal)46 b(BITPIX)g(keyword)g(value)48 2700 y(BAD_NAXIS)427 b(212)190 b(illegal)46 b(NAXIS)g(keyword)g(value) 48 2813 y(BAD_NAXES)427 b(213)190 b(illegal)46 b(NAXISn)g(keyword)g (value)48 2926 y(BAD_PCOUNT)379 b(214)190 b(illegal)46 b(PCOUNT)g(keyword)g(value)48 3039 y(BAD_GCOUNT)379 b(215)190 b(illegal)46 b(GCOUNT)g(keyword)g(value)48 3152 y(BAD_TFIELDS)331 b(216)190 b(illegal)46 b(TFIELDS)g(keyword)f(value)48 3265 y(NEG_WIDTH)427 b(217)190 b(negative)45 b(table)i(row)g(size)48 3378 y(NEG_ROWS)475 b(218)190 b(negative)45 b(number)i(of)g(rows)f(in)i (table)48 3491 y(COL_NOT_FOUND)235 b(219)190 b(column)46 b(with)h(this)f(name)h(not)g(found)f(in)h(table)48 3604 y(BAD_SIMPLE)379 b(220)190 b(illegal)46 b(value)g(of)h(SIMPLE)f (keyword)48 3717 y(NO_SIMPLE)427 b(221)190 b(Primary)46 b(array)g(doesn't)g(start)g(with)h(SIMPLE)48 3830 y(NO_BITPIX)427 b(222)190 b(Second)46 b(keyword)g(not)h(BITPIX)48 3942 y(NO_NAXIS)475 b(223)190 b(Third)46 b(keyword)g(not)h(NAXIS)48 4055 y(NO_NAXES)475 b(224)190 b(Couldn't)45 b(find)i(all)g(the)g (NAXISn)f(keywords)48 4168 y(NO_XTENSION)331 b(225)190 b(HDU)47 b(doesn't)f(start)g(with)h(XTENSION)e(keyword)48 4281 y(NOT_ATABLE)379 b(226)190 b(the)47 b(CHDU)f(is)i(not)f(an)g (ASCII)f(table)g(extension)48 4394 y(NOT_BTABLE)379 b(227)190 b(the)47 b(CHDU)f(is)i(not)f(a)g(binary)f(table)g(extension)48 4507 y(NO_PCOUNT)427 b(228)190 b(couldn't)45 b(find)i(PCOUNT)f(keyword) 48 4620 y(NO_GCOUNT)427 b(229)190 b(couldn't)45 b(find)i(GCOUNT)f (keyword)48 4733 y(NO_TFIELDS)379 b(230)190 b(couldn't)45 b(find)i(TFIELDS)f(keyword)48 4846 y(NO_TBCOL)475 b(231)190 b(couldn't)45 b(find)i(TBCOLn)f(keyword)48 4959 y(NO_TFORM)475 b(232)190 b(couldn't)45 b(find)i(TFORMn)f(keyword)48 5072 y(NOT_IMAGE)427 b(233)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(IMAGE) f(extension)48 5185 y(BAD_TBCOL)427 b(234)190 b(TBCOLn)46 b(keyword)g(value)g(<)i(0)f(or)g(>)h(rowlength)48 5297 y(NOT_TABLE)427 b(235)190 b(the)47 b(CHDU)f(is)i(not)f(a)g(table)48 5410 y(COL_TOO_WIDE)283 b(236)190 b(column)46 b(is)h(too)g(wide)g(to)g (fit)g(in)g(table)48 5523 y(COL_NOT_UNIQUE)187 b(237)j(more)47 b(than)f(1)i(column)e(name)g(matches)g(template)48 5636 y(BAD_ROW_WIDTH)235 b(241)190 b(sum)47 b(of)g(column)f(widths)g(not)h (=)h(NAXIS1)p eop end %%Page: 193 201 TeXDict begin 193 200 bop 3764 299 a Fj(193)48 555 y Fe(UNKNOWN_EXT)331 b(251)190 b(unrecognizable)44 b(FITS)i(extension)g (type)48 668 y(UNKNOWN_REC)331 b(252)190 b(unknown)46 b(record;)g(1st)g(keyword)g(not)h(SIMPLE)f(or)h(XTENSION)48 781 y(END_JUNK)475 b(253)190 b(END)47 b(keyword)f(is)h(not)g(blank)48 894 y(BAD_HEADER_FILL)139 b(254)190 b(Header)46 b(fill)h(area)f (contains)g(non-blank)f(chars)48 1007 y(BAD_DATA_FILL)235 b(255)190 b(Illegal)46 b(data)g(fill)h(bytes)f(\(not)h(zero)g(or)g (blank\))48 1120 y(BAD_TFORM)427 b(261)190 b(illegal)46 b(TFORM)g(format)g(code)48 1233 y(BAD_TFORM_DTYPE)139 b(262)190 b(unrecognizable)44 b(TFORM)i(data)h(type)f(code)48 1346 y(BAD_TDIM)475 b(263)190 b(illegal)46 b(TDIMn)g(keyword)g(value)48 1458 y(BAD_HEAP_PTR)283 b(264)190 b(invalid)46 b(BINTABLE)f(heap)i (pointer)f(is)h(out)g(of)g(range)48 1684 y(BAD_HDU_NUM)331 b(301)190 b(HDU)47 b(number)f(<)h(1)48 1797 y(BAD_COL_NUM)331 b(302)190 b(column)46 b(number)g(<)i(1)f(or)g(>)h(tfields)48 1910 y(NEG_FILE_POS)283 b(304)190 b(tried)46 b(to)h(move)g(to)g (negative)f(byte)g(location)g(in)h(file)48 2023 y(NEG_BYTES)427 b(306)190 b(tried)46 b(to)h(read)g(or)g(write)g(negative)e(number)h(of) h(bytes)48 2136 y(BAD_ROW_NUM)331 b(307)190 b(illegal)46 b(starting)f(row)i(number)f(in)h(table)48 2249 y(BAD_ELEM_NUM)283 b(308)190 b(illegal)46 b(starting)f(element)h(number)g(in)h(vector)48 2362 y(NOT_ASCII_COL)235 b(309)190 b(this)47 b(is)g(not)g(an)g(ASCII)f (string)g(column)48 2475 y(NOT_LOGICAL_COL)139 b(310)190 b(this)47 b(is)g(not)g(a)g(logical)f(data)h(type)f(column)48 2588 y(BAD_ATABLE_FORMAT)d(311)190 b(ASCII)46 b(table)h(column)f(has)h (wrong)f(format)48 2700 y(BAD_BTABLE_FORMAT)d(312)190 b(Binary)46 b(table)g(column)g(has)h(wrong)g(format)48 2813 y(NO_NULL)523 b(314)190 b(null)47 b(value)f(has)h(not)g(been)f (defined)48 2926 y(NOT_VARI_LEN)283 b(317)190 b(this)47 b(is)g(not)g(a)g(variable)f(length)g(column)48 3039 y(BAD_DIMEN)427 b(320)190 b(illegal)46 b(number)g(of)h(dimensions)e(in)i(array)48 3152 y(BAD_PIX_NUM)331 b(321)190 b(first)46 b(pixel)h(number)f(greater) g(than)g(last)h(pixel)48 3265 y(ZERO_SCALE)379 b(322)190 b(illegal)46 b(BSCALE)g(or)h(TSCALn)f(keyword)g(=)h(0)48 3378 y(NEG_AXIS)475 b(323)190 b(illegal)46 b(axis)g(length)g(<)i(1)48 3604 y(NOT_GROUP_TABLE)330 b(340)142 b(Grouping)46 b(function)f(error) 48 3717 y(HDU_ALREADY_MEMBER)186 b(341)48 3830 y(MEMBER_NOT_FOUND)282 b(342)48 3942 y(GROUP_NOT_FOUND)330 b(343)48 4055 y(BAD_GROUP_ID)474 b(344)48 4168 y(TOO_MANY_HDUS_TRACKED)42 b(345)48 4281 y(HDU_ALREADY_TRACKED)138 b(346)48 4394 y(BAD_OPTION)570 b(347)48 4507 y(IDENTICAL_POINTERS)186 b(348)48 4620 y(BAD_GROUP_ATTACH)282 b(349)48 4733 y(BAD_GROUP_DETACH)g(350)48 4959 y(NGP_NO_MEMORY)426 b(360)238 b(malloc)46 b(failed)48 5072 y(NGP_READ_ERR)474 b(361)238 b(read)46 b(error)h(from)f(file)48 5185 y(NGP_NUL_PTR)522 b(362)238 b(null)46 b(pointer)g(passed)g(as)h (an)g(argument.)1575 5297 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f (of)1575 5410 y(template)f(file)g(raises)g(this)h(error)48 5523 y(NGP_EMPTY_CURLINE)234 b(363)k(line)46 b(read)h(seems)f(to)h(be)h (empty)e(\(used)1575 5636 y(internally\))p eop end %%Page: 194 202 TeXDict begin 194 201 bop 0 299 a Fj(194)1589 b Fh(APPENDIX)31 b(C.)61 b(CFITSIO)29 b(ERR)m(OR)h(ST)-8 b(A)g(TUS)30 b(CODES)48 555 y Fe(NGP_UNREAD_QUEUE_FULL)42 b(364)238 b(cannot)46 b(unread)g(more)g(then)h(1)g(line)g(\(or)g(single)1575 668 y(line)g(twice\))48 781 y(NGP_INC_NESTING)330 b(365)238 b(too)46 b(deep)h(include)f(file)h(nesting)e(\(infinite)1575 894 y(loop,)h(template)g(includes)f(itself)i(?\))48 1007 y(NGP_ERR_FOPEN)426 b(366)238 b(fopen\(\))45 b(failed,)h(cannot)g(open) h(template)e(file)48 1120 y(NGP_EOF)714 b(367)238 b(end)46 b(of)i(file)e(encountered)f(and)i(not)g(expected)48 1233 y(NGP_BAD_ARG)522 b(368)238 b(bad)46 b(arguments)g(passed.)g(Usually)f (means)1575 1346 y(internal)h(parser)g(error.)g(Should)g(not)h(happen) 48 1458 y(NGP_TOKEN_NOT_EXPECT)90 b(369)238 b(token)46 b(not)h(expected)e(here)48 1684 y(BAD_I2C)523 b(401)190 b(bad)47 b(int)g(to)g(formatted)e(string)h(conversion)48 1797 y(BAD_F2C)523 b(402)190 b(bad)47 b(float)f(to)h(formatted)f (string)g(conversion)48 1910 y(BAD_INTKEY)379 b(403)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(integer)48 2023 y(BAD_LOGICALKEY)187 b(404)j(can't)46 b(interpret)g(keyword)f (value)i(as)g(logical)48 2136 y(BAD_FLOATKEY)283 b(405)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(float)48 2249 y(BAD_DOUBLEKEY)235 b(406)190 b(can't)46 b(interpret)g(keyword)f (value)i(as)g(double)48 2362 y(BAD_C2I)523 b(407)190 b(bad)47 b(formatted)e(string)h(to)h(int)g(conversion)48 2475 y(BAD_C2F)523 b(408)190 b(bad)47 b(formatted)e(string)h(to)h (float)g(conversion)48 2588 y(BAD_C2D)523 b(409)190 b(bad)47 b(formatted)e(string)h(to)h(double)f(conversion)48 2700 y(BAD_DATATYPE)283 b(410)190 b(illegal)46 b(datatype)f(code)i(value)48 2813 y(BAD_DECIM)427 b(411)190 b(bad)47 b(number)f(of)h(decimal)f (places)g(specified)48 2926 y(NUM_OVERFLOW)283 b(412)190 b(overflow)45 b(during)i(data)f(type)h(conversion)48 3039 y(DATA_COMPRESSION_ERR)137 b(413)95 b(error)46 b(compressing)f (image)48 3152 y(DATA_DECOMPRESSION_ERR)c(414)95 b(error)46 b(uncompressing)f(image)48 3378 y(BAD_DATE)475 b(420)190 b(error)46 b(in)h(date)g(or)g(time)g(conversion)48 3604 y(PARSE_SYNTAX_ERR)91 b(431)190 b(syntax)46 b(error)g(in)i(parser)e (expression)48 3717 y(PARSE_BAD_TYPE)187 b(432)j(expression)45 b(did)i(not)g(evaluate)e(to)i(desired)f(type)48 3830 y(PARSE_LRG_VECTOR)91 b(433)190 b(vector)46 b(result)g(too)h(large)f (to)i(return)e(in)h(array)48 3942 y(PARSE_NO_OUTPUT)139 b(434)190 b(data)47 b(parser)f(failed)g(not)h(sent)f(an)h(out)g(column) 48 4055 y(PARSE_BAD_COL)235 b(435)190 b(bad)47 b(data)f(encounter)g (while)g(parsing)g(column)48 4168 y(PARSE_BAD_OUTPUT)91 b(436)190 b(Output)46 b(file)h(not)g(of)g(proper)f(type)48 4394 y(ANGLE_TOO_BIG)235 b(501)190 b(celestial)45 b(angle)i(too)f (large)h(for)g(projection)48 4507 y(BAD_WCS_VAL)331 b(502)190 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)g(value)48 4620 y(WCS_ERROR)427 b(503)190 b(error)46 b(in)h(celestial)f (coordinate)f(calculation)48 4733 y(BAD_WCS_PROJ)283 b(504)190 b(unsupported)45 b(type)h(of)h(celestial)f(projection)48 4846 y(NO_WCS_KEY)379 b(505)190 b(celestial)45 b(coordinate)g(keywords) h(not)h(found)48 4959 y(APPROX_WCS_KEY)187 b(506)j(approximate)45 b(wcs)i(keyword)e(values)h(were)h(returned)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF cfitsio-4.3.1/docs/fitsio.tex0000644000225700000360000126531314456514035015436 0ustar cagordonlhea\documentclass[11pt]{book} \input{html.sty} \htmladdtonavigation {\begin{rawhtml} FITSIO Home \end{rawhtml}} %\oddsidemargin=0.25in \oddsidemargin=0.00in \evensidemargin=0.00in \textwidth=6.5in %\topmargin=0.0in \textheight=8.75in \parindent=0cm \parskip=0.2cm \begin{document} \pagenumbering{roman} \begin{titlepage} \normalsize \vspace*{4.6cm} \begin{center} {\Huge \bf FITSIO User's Guide}\\ \end{center} \medskip \medskip \begin{center} {\LARGE \bf A Subroutine Interface to FITS Format Files}\\ \end{center} \begin{center} {\LARGE \bf for Fortran Programmers}\\ \end{center} \medskip \medskip \begin{center} {\Large Version 4.3\\} \end{center} \bigskip \vskip 2.5cm \begin{center} {HEASARC\\ Code 662\\ Goddard Space Flight Center\\ Greenbelt, MD 20771\\ USA} \end{center} \vfill \bigskip \begin{center} {\Large Jul 2023\\} \end{center} \vfill \end{titlepage} \clearpage \tableofcontents \chapter{Introduction } \pagenumbering{arabic} This document describes the Fortran-callable subroutine interface that is provided as part of the CFITSIO library (which is written in ANSI C). This is a companion document to the CFITSIO User's Guide which should be consulted for further information about the underlying CFITSIO library. In the remainder of this document, the terms FITSIO and CFITSIO are interchangeable and refer to the same library. FITSIO/CFITSIO is a machine-independent library of routines for reading and writing data files in the FITS (Flexible Image Transport System) data format. It can also read IRAF format image files and raw binary data arrays by converting them on the fly into a virtual FITS format file. This library was written to provide a powerful yet simple interface for accessing FITS files which will run on most commonly used computers and workstations. FITSIO supports all the features described in the official definition of the FITS format and can read and write all the currently defined types of extensions, including ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The FITSIO subroutines insulate the programmer from having to deal with the complicated formatting details in the FITS file, however, it is assumed that users have a general knowledge about the structure and usage of FITS files. The CFITSIO package was initially developed by the HEASARC (High Energy Astrophysics Science Archive Research Center) at the NASA Goddard Space Flight Center to convert various existing and newly acquired astronomical data sets into FITS format and to further analyze data already in FITS format. New features continue to be added to CFITSIO in large part due to contributions of ideas or actual code from users of the package. The Integral Science Data Center in Switzerland, and the XMM/ESTEC project in The Netherlands made especially significant contributions that resulted in many of the new features that appeared in v2.0 of CFITSIO. The latest version of the CFITSIO source code, documentation, and example programs are available on the World-Wide Web or via anonymous ftp from: \begin{verbatim} http://heasarc.gsfc.nasa.gov/fitsio ftp://legacy.gsfc.nasa.gov/software/fitsio/c \end{verbatim} \newpage Any questions, bug reports, or suggested enhancements related to the CFITSIO package should be sent to the FTOOLS Help Desk at the HEASARC: \begin{verbatim} http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp \end{verbatim} This User's Guide assumes that readers already have a general understanding of the definition and structure of FITS format files. Further information about FITS formats is available from the FITS Support Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the 'FITS Standard' gives the authoritative definition of the FITS data format. Other documents available at that Web site provide additional historical background and practical advice on using FITS files. The HEASARC also provides a very sophisticated FITS file analysis program called `Fv' which can be used to display and edit the contents of any FITS file as well as construct new FITS files from scratch. Fv is freely available for most Unix platforms, Mac PCs, and Windows PCs. CFITSIO users may also be interested in the FTOOLS package of programs that can be used to manipulate and analyze FITS format files. Fv and FTOOLS are available from their respective Web sites at: \begin{verbatim} http://fv.gsfc.nasa.gov http://heasarc.gsfc.nasa.gov/ftools \end{verbatim} \chapter{ Creating FITSIO/CFITSIO } \section{Building the Library} To use the FITSIO subroutines one must first build the CFITSIO library, which requires a C compiler. gcc is ideal, or most other ANSI-C compilers will also work. The CFITSIO code is contained in about 40 C source files (*.c) and header files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. The Fortran interface subroutines to the C CFITSIO routines are located in the f77\_wrap1.c, through f77\_wrap4.c files. These are relatively simple 'wrappers' that translate the arguments in the Fortran subroutine into the appropriate format for the corresponding C routine. This translation is performed transparently to the user by a set of C macros located in the cfortran.h file. Unfortunately cfortran.h does not support every combination of C and Fortran compilers so the Fortran interface is not supported on all platforms. (see further notes below). A standard combination of C and Fortran compilers will be assumed by default, but one may also specify a particular Fortran compiler by doing: \begin{verbatim} > setenv CFLAGS -DcompilerName=1 \end{verbatim} (where 'compilerName' is the name of the compiler) before running the configure command. The currently recognized compiler names are: \begin{verbatim} g77Fortran IBMR2Fortran CLIPPERFortran pgiFortran NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran CRAYFortran mipsFortran DECFortran vmsFortran CONVEXFortran PowerStationFortran AbsoftUNIXFortran AbsoftProFortran SXFortran \end{verbatim} Alternatively, one may edit the CFLAGS line in the Makefile to add the '-DcompilerName' flag after running the './configure' command. The CFITSIO library is built on Unix systems by typing: \begin{verbatim} > ./configure [--prefix=/target/installation/path] [--enable-sse2] [--enable-ssse3] > make (or 'make shared') > make install (this step is optional) \end{verbatim} at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, \begin{verbatim} > ./configure --prefix=/usr1/local \end{verbatim} will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). The optional --enable-sse2 and --enable-ssse3 flags will cause configure to attempt to build CFITSIO using faster byte-swapping algorithms. See the "Optimizing Programs" section of this manual for more information about these options. By default, the Makefile will be configured to build the set of Fortran-callable wrapper routines whose calling sequences are described later in this document. The 'make shared' option builds a shared or dynamic version of the CFITSIO library. When using the shared library the executable code is not copied into your program at link time and instead the program locates the necessary library code at run time, normally through LD\_LIBRARY\_PATH or some other method. The advantages of using a shared library are: \begin{verbatim} 1. Less disk space if you build more than 1 program 2. Less memory if more than one copy of a program using the shared library is running at the same time since the system is smart enough to share copies of the shared library at run time. 3. Possibly easier maintenance since a new version of the shared library can be installed without relinking all the software that uses it (as long as the subroutine names and calling sequences remain unchanged). 4. No run-time penalty. \end{verbatim} The disadvantages are: \begin{verbatim} 1. More hassle at runtime. You have to either build the programs specially or have LD_LIBRARY_PATH set right. 2. There may be a slight start up penalty, depending on where you are reading the shared library and the program from and if your CPU is either really slow or really heavily loaded. \end{verbatim} On HP/UX systems, the environment variable CFLAGS should be set to -Ae before running configure to enable "extended ANSI" features. It may not be possible to statically link programs that use CFITSIO on some platforms (namely, on Solaris 2.6) due to the network drivers (which provide FTP and HTTP access to FITS files). It is possible to make both a dynamic and a static version of the CFITSIO library, but network file access will not be possible using the static version. On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may be executed to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. Note that the getcwd function that is used in the group.c module may require that programs using CFITSIO be linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example link line in the next section of this document. On Windows IBM-PC type platforms the situation is more complicated because of the wide variety of Fortran compilers that are available and because of the inherent complexities of calling the CFITSIO C routines from Fortran. Two different versions of the CFITSIO dll library are available, compiled with the Borland C++ compiler and the Microsoft Visual C++ compiler, respectively, in the files cfitsiodll\_2xxx\_borland.zip and cfitsiodll\_3xxx\_vcc.zip, where '3xxx' represents the current release number. Both these dll libraries contain a set of Fortran wrapper routines which may be compatible with some, but probably not all, available Fortran compilers. To test if they are compatible, compile the program testf77.f and try linking to these dll libraries. If these libraries do not work with a particular Fortran compiler, then it may be necessary to modify the file "cfortran.h" to support that particular combination of C and Fortran compilers, and then rebuild the CFITSIO dll library. This will require, however, some expertise in mixed language programming. CFITSIO should be compatible with most current ANCI C and C++ compilers: Cray supercomputers are currently not supported. \section{Testing the Library} The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems type: \begin{verbatim} % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std \end{verbatim} On VMS systems, (assuming cc is the name of the C compiler command), type: \begin{verbatim} $ cc testprog.c $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib $ run testprog \end{verbatim} The testprog program should produce a FITS file called `testprog.fit' that is identical to the `testprog.std' FITS file included with this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. (There may be some minor formatting differences, such as the presence or absence of leading zeros, or 3 digit exponents in numbers, which can be ignored). The Fortran wrappers in CFITSIO may be tested with the testf77 program. On Unix systems the Fortran compiler is typically called 'gfortran'. - \begin{verbatim} % gfortran -o testf77 testf77.f -L. -lcfitsio -lz -lcurl % testf77 > testf77.lis % diff testf77.lis testf77.out % cmp testf77.fit testf77.std \end{verbatim} On machines running SUN O/S, Fortran programs must be compiled with the '-f' option to force double precision variables to be aligned on 8-byte boundaries to make the fortran-declared variables compatible with C. A similar compiler option may be required on other platforms. Failing to use this option may cause the program to crash on FITSIO routines that read or write double precision variables. On Windows platforms, linking Fortran programs with a C library often depends on the particular compilers involved. Some users have found the following commands work when using the Intel Fortran compiler: \begin{verbatim} ifort /libs.dll cfitsio.lib /MD testf77.f /Gm or possibly, ifort /libs:dll cfitsio.lib /MD /fpp /extfpp:cfortran.h,fitsio.h /iface:cvf testf77.f \end{verbatim} Also note that on some systems the output listing of the testf77 program may differ slightly from the testf77.std template if leading zeros are not printed by default before the decimal point when using F format. A few other utility programs are included with CFITSIO: \begin{verbatim} speed - measures the maximum throughput (in MB per second) for writing and reading FITS files with CFITSIO listhead - lists all the header keywords in any FITS file fitscopy - copies any FITS file (especially useful in conjunction with the CFITSIO's extended input filename syntax) cookbook - a sample program that performs common read and write operations on a FITS file. iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine \end{verbatim} The first 4 of these utility programs can be compiled and linked by typing \begin{verbatim} % make program_name \end{verbatim} \section{Linking Programs with FITSIO} When linking applications software with the FITSIO library, several system libraries usually need to be specified on the link comman Unix systems, the most reliable way to determine what libraries are required is to type 'make testprog' and see what libraries the configure script has added. The typical libraries that may need to be added are -lm (the math library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). These latter 2 libraries are not needed on VMS and Windows platforms, because FTP file access is not currently supported on those platforms. Note that when upgrading to a newer version of CFITSIO it is usually necessary to recompile, as well as relink, the programs that use CFITSIO, because the definitions in fitsio.h often change. \section{Getting Started with FITSIO} In order to effectively use the FITSIO library as quickly as possible, it is recommended that new users follow these steps: 1. Read the following `FITS Primer' chapter for a brief overview of the structure of FITS files. This is especially important for users who have not previously dealt with the FITS table and image extensions. 2. Write a simple program to read or write a FITS file using the Basic Interface routines. 3. Refer to the cookbook.f program that is included with this release for examples of routines that perform various common FITS file operations. 4. Read Chapters 4 and 5 to become familiar with the conventions and advanced features of the FITSIO interface. 5. Scan through the more extensive set of routines that are provided in the `Advanced Interface'. These routines perform more specialized functions than are provided by the Basic Interface routines. \section{Example Program} The following listing shows an example of how to use the FITSIO routines in a Fortran program. Refer to the cookbook.f program that is included with the FITSIO distribution for examples of other FITS programs. \begin{verbatim} program writeimage C Create a FITS primary array containing a 2-D image integer status,unit,blocksize,bitpix,naxis,naxes(2) integer i,j,group,fpixel,nelements,array(300,200) character filename*80 logical simple,extend status=0 C Name of the FITS file to be created: filename='ATESTFILE.FITS' C Get an unused Logical Unit Number to use to create the FITS file call ftgiou(unit,status) C create the new empty FITS file blocksize=1 call ftinit(unit,filename,blocksize,status) C initialize parameters about the FITS image (300 x 200 16-bit integers) simple=.true. bitpix=16 naxis=2 naxes(1)=300 naxes(2)=200 extend=.true. C write the required header keywords call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) C initialize the values in the image with a linear ramp function do j=1,naxes(2) do i=1,naxes(1) array(i,j)=i+j end do end do C write the array to the FITS file group=1 fpixel=1 nelements=naxes(1)*naxes(2) call ftpprj(unit,group,fpixel,nelements,array,status) C write another optional keyword to the header call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) C close the file and free the unit number call ftclos(unit, status) call ftfiou(unit, status) end \end{verbatim} \section{Legal Stuff} Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." \section{Acknowledgments} The development of many of the powerful features in CFITSIO was made possible through collaborations with many people or organizations from around the world. The following, in particular, have made especially significant contributions: Programmers from the Integral Science Data Center, Switzerland (namely, Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The use of `drivers' greatly simplified the low-level I/O, which in turn made other new features in CFITSIO (e.g., support for compressed FITS files and support for IRAF format image files) much easier to implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce O'Neel wrote the drivers for accessing FITS files over the network using the FTP, HTTP, and ROOT protocols. The ISDC also provided the template parsing routines (written by Jurek Borkowski) and the hierarchical grouping routines (written by Don Jennings). The ISDC DAL (Data Access Layer) routines are layered on top of CFITSIO and make extensive use of these features. Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the high-performance lexical parsing algorithm that is used to do on-the-fly filtering of FITS tables. This algorithm essentially pre-compiles the user-supplied selection expression into a form that can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) then wrote the parsing routines used by CFITSIO based on Lammers' design, combined with other techniques such as the CFITSIO iterator routine to further enhance the data processing throughput. This effort also benefited from a much earlier lexical parsing routine that was developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt (NASA/GSFC) implemented additional functions (median, average, stddev) and other enhancements to the lexical parser. The CFITSIO iterator function is loosely based on similar ideas developed for the XMM Data Access Layer. Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of Fortran-callable wrappers for all the CFITSIO routines, which in turn rely on the CFORTRAN macro developed by Burkhard Burow. The syntax used by CFITSIO for filtering or binning input FITS files is based on ideas developed for the AXAF Science Center Data Model by Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for further description of the AXAF Data Model. The file decompression code were taken directly from the gzip (GNU zip) program developed by Jean-loup Gailly and others. Doug Mink, SAO, provided the routines for converting IRAF format images into FITS format. Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to cfortran.h that are necessary to support 64-bit integer values when calling C routines from fortran programs. The cfortran.h macros were originally developed by Burkhard Burow (CERN). Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. In addition, many other people have made valuable contributions to the development of CFITSIO. These include (with apologies to others that may have inadvertently been omitted): Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. \chapter{ A FITS Primer } This section gives a brief overview of the structure of FITS files. Users should refer to the documentation available from the FITS Support Office, as described in the introduction, for more detailed information on FITS formats. FITS was first developed in the late 1970's as a standard data interchange format between various astronomical observatories. Since then FITS has become the defacto standard data format supported by most astronomical data analysis software packages. A FITS file consists of one or more Header + Data Units (HDUs), where the first HDU is called the `Primary HDU', or `Primary Array'. The primary array contains an N-dimensional array of pixels, such as a 1-D spectrum, a 2-D image, or a 3-D data cube. Six different primary datatypes are supported: Unsigned 8-bit bytes, 16, 32, and 64-bit signed integers, and 32 and 64-bit floating point reals. FITS also has a convention for storing unsigned integers (see the later section entitled `Unsigned Integers' for more details). The primary HDU may also consist of only a header with a null array containing no data pixels. Any number of additional HDUs may follow the primary array; these additional HDUs are called FITS `extensions'. There are currently 3 types of extensions defined by the FITS standard: \begin{itemize} \item Image Extension - a N-dimensional array of pixels, like in a primary array \item ASCII Table Extension - rows and columns of data in ASCII character format \item Binary Table Extension - rows and columns of data in binary representation \end{itemize} In each case the HDU consists of an ASCII Header Unit followed by an optional Data Unit. For historical reasons, each Header or Data unit must be an exact multiple of 2880 8-bit bytes long. Any unused space is padded with fill characters (ASCII blanks or zeros). Each Header Unit consists of any number of 80-character keyword records or `card images' which have the general form: \begin{verbatim} KEYNAME = value / comment string NULLKEY = / comment: This keyword has no value \end{verbatim} The keyword names may be up to 8 characters long and can only contain uppercase letters, the digits 0-9, the hyphen, and the underscore character. The keyword name is (usually) followed by an equals sign and a space character (= ) in columns 9 - 10 of the record, followed by the value of the keyword which may be either an integer, a floating point number, a character string (enclosed in single quotes), or a boolean value (the letter T or F). A keyword may also have a null or undefined value if there is no specified value string, as in the second example. The last keyword in the header is always the `END' keyword which has no value or comment fields. There are many rules governing the exact format of a keyword record (see the FITS Standard) so it is better to rely on standard interface software like FITSIO to correctly construct or to parse the keyword records rather than try to deal directly with the raw FITS formats. Each Header Unit begins with a series of required keywords which depend on the type of HDU. These required keywords specify the size and format of the following Data Unit. The header may contain other optional keywords to describe other aspects of the data, such as the units or scaling values. Other COMMENT or HISTORY keywords are also frequently added to further document the data file. The optional Data Unit immediately follows the last 2880-byte block in the Header Unit. Some HDUs do not have a Data Unit and only consist of the Header Unit. If there is more than one HDU in the FITS file, then the Header Unit of the next HDU immediately follows the last 2880-byte block of the previous Data Unit (or Header Unit if there is no Data Unit). The main required keywords in FITS primary arrays or image extensions are: \begin{itemize} \item BITPIX -- defines the datatype of the array: 8, 16, 32, 64, -32, -64 for unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, 64--bit signed integer, 32--bit IEEE floating point, and 64--bit IEEE double precision floating point, respectively. \item NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. \item NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. \end{itemize} FITS tables start with the keyword XTENSION = `TABLE' (for ASCII tables) or XTENSION = `BINTABLE' (for binary tables) and have the following main keywords: \begin{itemize} \item TFIELDS -- number of fields or columns in the table \item NAXIS2 -- number of rows in the table \item TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the name of the column \item TFORMn -- the datatype of the column \item TUNITn -- the physical units of the column (optional) \end{itemize} Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} for further information about the FITS format and related software packages. \chapter{FITSIO Conventions and Guidelines } \section{CFITSIO Size Limitations} CFITSIO places few restrictions on the size of FITS files that it reads or writes. There are a few limits, however, which may affect some extreme cases: 1. The maximum number of FITS files that may be simultaneously opened by CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default value is 1000, but this may be increased if necessary. Note that CFITSIO allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this amounts to more than 115K of memory for each opened file (or 115 MB for 1000 opened files). Note that the underlying operating system, may have a lower limit on the number of files that can be opened simultaneously. 2. By default, CFITSIO can handle FITS files up to 2.1 GB in size (2**31 bytes). This file size limit is often imposed by 32-bit operating systems. More recently, as 64-bit operating systems become more common, an industry-wide standard (at least on Unix systems) has been developed to support larger sized files (see http://ftp.sas.com/standards/large.file/). Starting with version 2.1 of CFITSIO, larger FITS files up to 6 terabytes in size may be read and written on supported platforms. In order to support these larger files, CFITSIO must be compiled with the '-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64' compiler flags. Some platforms may also require the `-D\_LARGE\_FILES' compiler flag. This causes the compiler to allocate 8-bytes instead of 4-bytes for the `off\_t' datatype which is used to store file offset positions. It appears that in most cases it is not necessary to also include these compiler flags when compiling programs that link to the CFITSIO library. If CFITSIO is compiled with the -D\_LARGEFILE\_SOURCE and -D\_FILE\_OFFSET\_BITS=64 flags on a platform that supports large files, then it can read and write FITS files that contain up to 2**31 2880-byte FITS records, or approximately 6 terabytes in size. It is still required that the value of the NAXISn and PCOUNT keywords in each extension be within the range of a signed 4-byte integer (max value = 2,147,483,648). Thus, each dimension of an image (given by the NAXISn keywords), the total width of a table (NAXIS1 keyword), the number of rows in a table (NAXIS2 keyword), and the total size of the variable-length array heap in binary tables (PCOUNT keyword) must be less than this limit. Currently, support for large files within CFITSIO has been tested on the Linux, Solaris, and IBM AIX operating systems. \section{Multiple Access to the Same FITS File} CFITSIO supports simultaneous read and write access to multiple HDUs in the same FITS file. Thus, one can open the same FITS file twice within a single program and move to 2 different HDUs in the file, and then read and write data or keywords to the 2 extensions just as if one were accessing 2 completely separate FITS files. Since in general it is not possible to physically open the same file twice and then expect to be able to simultaneously (or in alternating succession) write to 2 different locations in the file, CFITSIO recognizes when the file to be opened (in the call to fits\_open\_file) has already been opened and instead of actually opening the file again, just logically links the new file to the old file. (This only applies if the file is opened more than once within the same program, and does not prevent the same file from being simultaneously opened by more than one program). Then before CFITSIO reads or writes to either (logical) file, it makes sure that any modifications made to the other file have been completely flushed from the internal buffers to the file. Thus, in principle, one could open a file twice, in one case pointing to the first extension and in the other pointing to the 2nd extension and then write data to both extensions, in any order, without danger of corrupting the file, There may be some efficiency penalties in doing this however, since CFITSIO has to flush all the internal buffers related to one file before switching to the other, so it would still be prudent to minimize the number of times one switches back and forth between doing I/O to different HDUs in the same file. \section{Current Header Data Unit (CHDU)} In general, a FITS file can contain multiple Header Data Units, also called extensions. CFITSIO only operates within one HDU at any given time, and the currently selected HDU is called the Current Header Data Unit (CHDU). When a FITS file is first created or opened the CHDU is automatically defined to be the first HDU (i.e., the primary array). CFITSIO routines are provided to move to and open any other existing HDU within the FITS file or to append or insert a new HDU in the FITS file which then becomes the CHDU. \section{Subroutine Names} All FITSIO subroutine names begin with the letters 'ft' to distinguish them from other subroutines and are 5 or 6 characters long. Users should not name their own subroutines beginning with 'ft' to avoid conflicts. (The SPP interface routines all begin with 'fs'). Subroutines which read or get information from the FITS file have names beginning with 'ftg...'. Subroutines which write or put information into the FITS file have names beginning with 'ftp...'. \section{Subroutine Families and Datatypes} Many of the subroutines come in families which differ only in the datatype of the associated parameter(s) . The datatype of these subroutines is indicated by the last letter of the subroutine name (e.g., 'j' in 'ftpkyj') as follows: \begin{verbatim} x - bit b - character*1 (unsigned byte) i - short integer (I*2) j - integer (I*4, 32-bit integer) k - long long integer (I*8, 64-bit integer) e - real exponential floating point (R*4) f - real fixed-format floating point (R*4) d - double precision real floating-point (R*8) g - double precision fixed-format floating point (R*8) c - complex reals (pairs of R*4 values) m - double precision complex (pairs of R*8 values) l - logical (L*4) s - character string \end{verbatim} When dealing with the FITS byte datatype, it is important to remember that the raw values (before any scaling by the BSCALE and BZERO, or TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte columns (TFORMn = 'B') are interpreted as unsigned bytes with values ranging from 0 to 255. Some Fortran compilers support a non-standard byte datatype such as INTEGER*1, LOGICAL*1, or BYTE, which can sometimes be used instead of CHARACTER*1 variables. Many machines permit passing a numeric datatype (such as INTEGER*1) to the FITSIO subroutines which are expecting a CHARACTER*1 datatype, but this technically violates the Fortran-77 standard and is not supported on all machines (e.g., on a VAX/VMS machine one must use the VAX-specific \%DESCR function). One feature of the CFITSIO routines is that they can operate on a `X' (bit) column in a binary table as though it were a `B' (byte) column. For example a `11X' datatype column can be interpreted the same as a `2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can be more efficient to read and write whole bytes at a time, rather than reading or writing each individual bit. The double precision complex datatype is not a standard Fortran-77 datatype. If a particular Fortran compiler does not directly support this datatype, then one may instead pass an array of pairs of double precision values to these subroutines. The first value in each pair is the real part, and the second is the imaginary part. \section{Implicit Data Type Conversion} The FITSIO routines that read and write numerical data can perform implicit data type conversion. This means that the data type of the variable or array in the program does not need to be the same as the data type of the value in the FITS file. Data type conversion is supported for numerical and string data types (if the string contains a valid number enclosed in quotes) when reading a FITS header keyword value and for numeric values when reading or writing values in the primary array or a table column. CFITSIO returns status = NUM\_OVERFLOW if the converted data value exceeds the range of the output data type. Implicit data type conversion is not supported within binary tables for string, logical, complex, or double complex data types. In addition, any table column may be read as if it contained string values. In the case of numeric columns the returned string will be formatted using the TDISPn display format if it exists. \section{Data Scaling} When reading numerical data values in the primary array or a table column, the values will be scaled automatically by the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they are present in the header. The scaled data that is returned to the reading program will have \begin{verbatim} output value = (FITS value) * BSCALE + BZERO \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when reading from table columns). In the case of integer output values the floating point scaled value is truncated to an integer (not rounded to the nearest integer). The ftpscl and fttscl subroutines may be used to override the scaling parameters defined in the header (e.g., to turn off the scaling so that the program can read the raw unscaled values from the FITS file). When writing numerical data to the primary array or to a table column the data values will generally be automatically inversely scaled by the value of the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they they exist in the header. These keywords must have been written to the header before any data is written for them to have any effect. Otherwise, one may use the ftpscl and fttscl subroutines to define or override the scaling keywords in the header (e.g., to turn off the scaling so that the program can write the raw unscaled values into the FITS file). If scaling is performed, the inverse scaled output value that is written into the FITS file will have \begin{verbatim} FITS value = ((input value) - BZERO) / BSCALE \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when writing to table columns). Rounding to the nearest integer, rather than truncation, is performed when writing integer datatypes to the FITS file. \section{Error Status Values and the Error Message Stack} The last parameter in nearly every FITSIO subroutine is the error status value which is both an input and an output parameter. A returned positive value for this parameter indicates an error was detected. A listing of all the FITSIO status code values is given at the end of this document. The FITSIO library uses an `inherited status' convention for the status parameter which means that if a subroutine is called with a positive input value of the status parameter, then the subroutine will exit immediately without changing the value of the status parameter. Thus, if one passes the status value returned from each FITSIO routine as input to the next FITSIO subroutine, then whenever an error is detected all further FITSIO processing will cease. This convention can simplify the error checking in application programs because it is not necessary to check the value of the status parameter after every single FITSIO subroutine call. If a program contains a sequence of several FITSIO calls, one can just check the status value after the last call. Since the returned status values are generally distinctive, it should be possible to determine which subroutine originally returned the error status. FITSIO also maintains an internal stack of error messages (80-character maximum length) which in many cases provide a more detailed explanation of the cause of the error than is provided by the error status number alone. It is recommended that the error message stack be printed out whenever a program detects a FITSIO error. To do this, call the FTGMSG routine repeatedly to get the successive messages on the stack. When the stack is empty FTGMSG will return a blank string. Note that this is a `First In -- First Out' stack, so the oldest error message is returned first by ftgmsg. \section{Variable-Length Array Facility in Binary Tables} FITSIO provides easy-to-use support for reading and writing data in variable length fields of a binary table. The variable length columns have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the datatype code (e.g., I, J, E, D, etc.) and `len' is an integer specifying the maximum length of the vector in the table. If the value of `len' is not specified when the table is created (e.g., if the TFORM keyword value is simply specified as '1PE' instead of '1PE(400) ), then FITSIO will automatically scan the table when it is closed to determine the maximum length of the vector and will append this value to the TFORMn value. The same routines which read and write data in an ordinary fixed length binary table extension are also used for variable length fields, however, the subroutine parameters take on a slightly different interpretation as described below. All the data in a variable length field is written into an area called the `heap' which follows the main fixed-length FITS binary table. The size of the heap, in bytes, is specified with the PCOUNT keyword in the FITS header. When creating a new binary table, the initial value of PCOUNT should usually be set to zero. FITSIO will recompute the size of the heap as the data is written and will automatically update the PCOUNT keyword value when the table is closed. When writing variable length data to a table, CFITSIO will automatically extend the size of the heap area if necessary, so that any following HDUs do not get overwritten. By default the heap data area starts immediately after the last row of the fixed-length table. This default starting location may be overridden by the THEAP keyword, but this is not recommended. If additional rows of data are added to the table, CFITSIO will automatically shift the the heap down to make room for the new rows, but it is obviously be more efficient to initially create the table with the necessary number of blank rows, so that the heap does not needed to be constantly moved. When writing to a variable length field, the entire array of values for a given row of the table must be written with a single call to FTPCLx. The total length of the array is calculated from (NELEM+FELEM-1). One cannot append more elements to an existing field at a later time; any attempt to do so will simply overwrite all the data which was previously written. Note also that the new data will be written to a new area of the heap and the heap space used by the previous write cannot be reclaimed. For this reason it is advised that each row of a variable length field only be written once. An exception to this general rule occurs when setting elements of an array as undefined. One must first write a dummy value into the array with FTPCLx, and then call FTPCLU to flag the desired elements as undefined. (Do not use the FTPCNx family of routines with variable length fields). Note that the rows of a table, whether fixed or variable length, do not have to be written consecutively and may be written in any order. When writing to a variable length ASCII character field (e.g., TFORM = '1PA') only a single character string written. FTPCLS writes the whole length of the input string (minus any trailing blank characters), thus the NELEM and FELEM parameters are ignored. If the input string is completely blank then FITSIO will write one blank character to the FITS file. Similarly, FTGCVS and FTGCFS read the entire string (truncated to the width of the character string argument in the subroutine call) and also ignore the NELEM and FELEM parameters. The FTPDES subroutine is useful in situations where multiple rows of a variable length column have the identical array of values. One can simply write the array once for the first row, and then use FTPDES to write the same descriptor values into the other rows (use the FTGDES routine to read the first descriptor value); all the rows will then point to the same storage location thus saving disk space. When reading from a variable length array field one can only read as many elements as actually exist in that row of the table; reading does not automatically continue with the next row of the table as occurs when reading an ordinary fixed length table field. Attempts to read more than this will cause an error status to be returned. One can determine the number of elements in each row of a variable column with the FTGDES subroutine. \section{Support for IEEE Special Values} The ANSI/IEEE-754 floating-point number standard defines certain special values that are used to represent such quantities as Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. (See the Appendix in the FITS standard or the FITS User's Guide for a list of these values). The FITSIO subroutines that read floating point data in FITS files recognize these IEEE special values and by default interpret the overflow and infinity values as being equivalent to a NaN, and convert the underflow and denormalized values into zeros. In some cases programmers may want access to the raw IEEE values, without any modification by FITSIO. This can be done by calling the FTGPVx or FTGCVx routines while specifying 0.0 as the value of the NULLVAL parameter. This will force FITSIO to simply pass the IEEE values through to the application program, without any modification. This does not work for double precision values on VAX/VMS machines, however, where there is no easy way to bypass the default interpretation of the IEEE special values. This is also not supported when reading floating-point images that have been compressed with the FITS tiled image compression convention that is discussed in section 5.6; the pixels values in tile compressed images are represented by scaled integers, and a reserved integer value (not a NaN) is used to represent undefined pixels. \section{When the Final Size of the FITS HDU is Unknown} It is not required to know the total size of a FITS data array or table before beginning to write the data to the FITS file. In the case of the primary array or an image extension, one should initially create the array with the size of the highest dimension (largest NAXISn keyword) set to a dummy value, such as 1. Then after all the data have been written and the true dimensions are known, then the NAXISn value should be updated using the fits\_ update\_key routine before moving to another extension or closing the FITS file. When writing to FITS tables, CFITSIO automatically keeps track of the highest row number that is written to, and will increase the size of the table if necessary. CFITSIO will also automatically insert space in the FITS file if necessary, to ensure that the data 'heap', if it exists, and/or any additional HDUs that follow the table do not get overwritten as new rows are written to the table. As a general rule it is best to specify the initial number of rows = 0 when the table is created, then let CFITSIO keep track of the number of rows that are actually written. The application program should not manually update the number of rows in the table (as given by the NAXIS2 keyword) since CFITSIO does this automatically. If a table is initially created with more than zero rows, then this will usually be considered as the minimum size of the table, even if fewer rows are actually written to the table. Thus, if a table is initially created with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before closing the table, then NAXIS2 will remain equal to 20. If however, 30 rows of data are written to this table, then NAXIS2 will be increased from 20 to 30. The one exception to this automatic updating of the NAXIS2 keyword is if the application program directly modifies the value of NAXIS2 (up or down) itself just before closing the table. In this case, CFITSIO does not update NAXIS2 again, since it assumes that the application program must have had a good reason for changing the value directly. This is not recommended, however, and is only provided for backward compatibility with software that initially creates a table with a large number of rows, than decreases the NAXIS2 value to the actual smaller value just before closing the table. \section{Local FITS Conventions supported by FITSIO} CFITSIO supports several local FITS conventions which are not defined in the official FITS standard and which are not necessarily recognized or supported by other FITS software packages. Programmers should be cautious about using these features, especially if the FITS files that are produced are expected to be processed by other software systems which do not use the CFITSIO interface. \subsection{Support for Long String Keyword Values.} The length of a standard FITS string keyword is limited to 68 characters because it must fit entirely within a single FITS header keyword record. In some instances it is necessary to encode strings longer than this limit, so FITSIO supports a local convention in which the string value is continued over multiple keywords. This continuation convention uses an ampersand character at the end of each substring to indicate that it is continued on the next keyword, and the continuation keywords all have the name CONTINUE without an equal sign in column 9. The string value may be continued in this way over as many additional CONTINUE keywords as is required. The following lines illustrate this continuation convention which is used in the value of the STRKEY keyword: \begin{verbatim} LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. STRKEY = 'This is a very long string keyword&' / Optional Comment CONTINUE ' value that is continued over 3 keywords in the & ' CONTINUE 'FITS header.' / This is another optional comment. \end{verbatim} It is recommended that the LONGSTRN keyword, as shown here, always be included in any HDU that uses this longstring convention. A subroutine called FTPLSW has been provided in CFITSIO to write this keyword if it does not already exist. This long string convention is supported by the following FITSIO subroutines that deal with string-valued keywords: \begin{verbatim} ftgkys - read a string keyword ftpkls - write (append) a string keyword ftikls - insert a string keyword ftmkls - modify the value of an existing string keyword ftukls - update an existing keyword, or write a new keyword ftdkey - delete a keyword \end{verbatim} These routines will transparently read, write, or delete a long string value in the FITS file, so programmers in general do not have to be concerned about the details of the convention that is used to encode the long string in the FITS header. When reading a long string, one must ensure that the character string parameter used in these subroutine calls has been declared long enough to hold the entire string, otherwise the returned string value will be truncated. Note that the more commonly used FITSIO subroutine to write string valued keywords (FTPKYS) does NOT support this long string convention and only supports strings up to 68 characters in length. This has been done deliberately to prevent programs from inadvertently writing keywords using this non-standard convention without the explicit intent of the programmer or user. The FTPKLS subroutine must be called instead to write long strings. This routine can also be used to write ordinary string values less than 68 characters in length. \subsection{Arrays of Fixed-Length Strings in Binary Tables} CFITSIO supports 2 ways to specify that a character column in a binary table contains an array of fixed-length strings. The first way, which is officially supported by the FITS Standard document, uses the TDIMn keyword. For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that column will be interpreted as containing an array of 5 strings, each 12 characters long. FITSIO also supports a local convention for the format of the TFORMn keyword value of the form 'rAw' where 'r' is an integer specifying the total width in characters of the column, and 'w' is an integer specifying the (fixed) length of an individual unit string within the vector. For example, TFORM1 = '120A10' would indicate that the binary table column is 120 characters wide and consists of 12 10-character length strings. This convention is recognized by the FITSIO subroutines that read or write strings in binary tables. The Binary Table definition document specifies that other optional characters may follow the datatype code in the TFORM keyword, so this local convention is in compliance with the FITS standard, although other FITS readers are not required to recognize this convention. \subsection{Keyword Units Strings} One deficiency of the current FITS Standard is that it does not define a specific convention for recording the physical units of a keyword value. The TUNITn keyword can be used to specify the physical units of the values in a table column, but there is no analogous convention for keyword values. The comment field of the keyword is often used for this purpose, but the units are usually not specified in a well defined format that FITS readers can easily recognize and extract. To solve this deficiency, FITSIO uses a local convention in which the keyword units are enclosed in square brackets as the first token in the keyword comment field; more specifically, the opening square bracket immediately follows the slash '/' comment field delimiter and a single space character. The following examples illustrate keywords that use this convention: \begin{verbatim} EXPOSURE= 1800.0 / [s] elapsed exposure time V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity LAMBDA = 5400. / [angstrom] central wavelength FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux \end{verbatim} In general, the units named in the IAU(1988) Style Guide are recommended, with the main exception that the preferred unit for angle is 'deg' for degrees. The FTPUNT and FTGUNT subroutines in FITSIO write and read, respectively, the keyword unit strings in an existing keyword. \subsection{HIERARCH Convention for Extended Keyword Names} CFITSIO supports the HIERARCH keyword convention which allows keyword names that are longer than 8 characters. This convention was developed at the European Southern Observatory (ESO) and allows characters consisting of digits 0-9, upper case letters A-Z, the dash '-' and the underscore '\_'. The components of hierarchical keywords are separated by a single ASCII space charater. For instance: \begin{verbatim} HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position \end{verbatim} Basically, this convention uses the FITS keyword 'HIERARCH' to indicate that this convention is being used, then the actual keyword name ({\tt'ESO INS FOCU POS'} in this example) begins in column 10. The equals sign marks the end of the keyword name and is followed by the usual value and comment fields just as in standard FITS keywords. Further details of this convention are described at http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html and in Section 4.4 of the ESO Data Interface Control Document that is linked to from http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. This convention allows a broader range of keyword names than is allowed by the FITS Standard. Here are more examples of such keywords: \begin{verbatim} HIERARCH LONGKEYWORD = 47.5 / Keyword has > 8 characters HIERARCH LONG-KEY_WORD2 = 52.3 / Long keyword with hyphen, underscore and digit HIERARCH EARTH IS A STAR = F / Keyword contains embedded spaces \end{verbatim} CFITSIO will transparently read and write these keywords, so application programs do not in general need to know anything about the specific implementation details of the HIERARCH convention. In particular, application programs do not need to specify the `HIERARCH' part of the keyword name when reading or writing keywords (although it may be included if desired). When writing a keyword, CFITSIO first checks to see if the keyword name is legal as a standard FITS keyword (no more than 8 characters long and containing only letters, digits, or a minus sign or underscore). If so it writes it as a standard FITS keyword, otherwise it uses the hierarch convention to write the keyword. The maximum keyword name length is 67 characters, which leaves only 1 space for the value field. A more practical limit is about 40 characters, which leaves enough room for most keyword values. CFITSIO returns an error if there is not enough room for both the keyword name and the keyword value on the 80-character card, except for string-valued keywords which are simply truncated so that the closing quote character falls in column 80. A space is also required on either side of the equal sign. \section{Optimizing Code for Maximum Processing Speed} CFITSIO has been carefully designed to obtain the highest possible speed when reading and writing FITS files. In order to achieve the best performance, however, application programmers must be careful to call the CFITSIO routines appropriately and in an efficient sequence; inappropriate usage of CFITSIO routines can greatly slow down the execution speed of a program. The maximum possible I/O speed of CFITSIO depends of course on the type of computer system that it is running on. To get a general idea of what data I/O speeds are possible on a particular machine, build the speed.c program that is distributed with CFITSIO (type 'make speed' in the CFITSIO directory). This diagnostic program measures the speed of writing and reading back a test FITS image, a binary table, and an ASCII table. The following 2 sections provide some background on how CFITSIO internally manages the data I/O and describes some strategies that may be used to optimize the processing speed of software that uses CFITSIO. \subsection{Background Information: How CFITSIO Manages Data I/O} Many CFITSIO operations involve transferring only a small number of bytes to or from the FITS file (e.g, reading a keyword, or writing a row in a table); it would be very inefficient to physically read or write such small blocks of data directly in the FITS file on disk, therefore CFITSIO maintains a set of internal Input--Output (IO) buffers in RAM memory that each contain one FITS block (2880 bytes) of data. Whenever CFITSIO needs to access data in the FITS file, it first transfers the FITS block containing those bytes into one of the IO buffers in memory. The next time CFITSIO needs to access bytes in the same block it can then go to the fast IO buffer rather than using a much slower system disk access routine. The number of available IO buffers is determined by the NIOBUF parameter (in fitsio2.h) and is currently set to 40. Whenever CFITSIO reads or writes data it first checks to see if that block of the FITS file is already loaded into one of the IO buffers. If not, and if there is an empty IO buffer available, then it will load that block into the IO buffer (when reading a FITS file) or will initialize a new block (when writing to a FITS file). If all the IO buffers are already full, it must decide which one to reuse (generally the one that has been accessed least recently), and flush the contents back to disk if it has been modified before loading the new block. The one major exception to the above process occurs whenever a large contiguous set of bytes are accessed, as might occur when reading or writing a FITS image. In this case CFITSIO bypasses the internal IO buffers and simply reads or writes the desired bytes directly in the disk file with a single call to a low-level file read or write routine. The minimum threshold for the number of bytes to read or write this way is set by the MINDIRECT parameter and is currently set to 3 FITS blocks = 8640 bytes. This is the most efficient way to read or write large chunks of data. Note that this fast direct IO process is not applicable when accessing columns of data in a FITS table because the bytes are generally not contiguous since they are interleaved by the other columns of data in the table. This explains why the speed for accessing FITS tables is generally slower than accessing FITS images. Given this background information, the general strategy for efficiently accessing FITS files should now be apparent: when dealing with FITS images, read or write large chunks of data at a time so that the direct IO mechanism will be invoked; when accessing FITS headers or FITS tables, on the other hand, once a particular FITS block has been loading into one of the IO buffers, try to access all the needed information in that block before it gets flushed out of the IO buffer. It is important to avoid the situation where the same FITS block is being read then flushed from a IO buffer multiple times. The following section gives more specific suggestions for optimizing the use of CFITSIO. \subsection{Optimization Strategies} 1. Because the data in FITS files is always stored in "big-endian" byte order, where the first byte of numeric values contains the most significant bits and the last byte contains the least significant bits, CFITSIO must swap the order of the bytes when reading or writing FITS files when running on little-endian machines (e.g., Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). On fairly new CPUs that support "SSSE3" machine instructions (e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs beginning in 2011) significantly faster 4-byte and 8-byte swapping algorithms are available. These faster byte swapping functions are not used by default in CFITSIO (because of the potential code portablility issues), but users can enable them on supported platforms by adding the appropriate compiler flags (-mssse3 with gcc or icc on linux) when compiling the swapproc.c source file, which will allow the compiler to generate code using the SSSE3 instruction set. A convenient way to do this is to configure the CFITSIO library with the following command: \begin{verbatim} > ./configure --enable-ssse3 \end{verbatim} Note, however, that a binary executable file that is created using these faster functions will only run on machines that support the SSSE3 machine instructions. It will crash on machines that do not support them. For faster 2-byte swaps on virtually all x86-64 CPUs (even those that do not support SSSE3), a variant using only SSE2 instructions exists. SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems (and is also automatically enabled by the --enable-ssse3 flag). When running on x86\_64 CPUs with 32-bit operating systems, these faster 2-byte swapping algorithms are not used by default in CFITSIO, but can be enabled explicitly with: \begin{verbatim} ./configure --enable-sse2 \end{verbatim} Preliminary testing indicates that these SSSE3 and SSE2 based byte-swapping algorithms can boost the CFITSIO performance when reading or writing FITS images by 20\% - 30\% or more. It is important to note, however, that compiler optimization must be turned on (e.g., by using the -O1 or -O2 flags in gcc) when building programs that use these fast byte-swapping algorithms in order to reap the full benefit of the SSSE3 and SSE2 instructions; without optimization, the code may actually run slower than when using more traditional byte-swapping techniques. 2. When dealing with a FITS primary array or IMAGE extension, it is more efficient to read or write large chunks of the image at a time (at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism will be used as described in the previous section. Smaller chunks of data are read or written via the IO buffers, which is somewhat less efficient because of the extra copy operation and additional bookkeeping steps that are required. In principle it is more efficient to read or write as big an array of image pixels at one time as possible, however, if the array becomes so large that the operating system cannot store it all in RAM, then the performance may be degraded because of the increased swapping of virtual memory to disk. 3. When dealing with FITS tables, the most important efficiency factor in the software design is to read or write the data in the FITS file in a single pass through the file. An example of poor program design would be to read a large, 3-column table by sequentially reading the entire first column, then going back to read the 2nd column, and finally the 3rd column; this obviously requires 3 passes through the file which could triple the execution time of an I/O limited program. For small tables this is not important, but when reading multi-megabyte sized tables these inefficiencies can become significant. The more efficient procedure in this case is to read or write only as many rows of the table as will fit into the available internal I/O buffers, then access all the necessary columns of data within that range of rows. Then after the program is completely finished with the data in those rows it can move on to the next range of rows that will fit in the buffers, continuing in this way until the entire file has been processed. By using this procedure of accessing all the columns of a table in parallel rather than sequentially, each block of the FITS file will only be read or written once. The optimal number of rows to read or write at one time in a given table depends on the width of the table row, on the number of I/O buffers that have been allocated in FITSIO, and also on the number of other FITS files that are open at the same time (since one I/O buffer is always reserved for each open FITS file). Fortunately, a FITSIO routine is available that will return the optimal number of rows for a given table: call ftgrsz(unit, nrows, status). It is not critical to use exactly the value of nrows returned by this routine, as long as one does not exceed it. Using a very small value however can also lead to poor performance because of the overhead from the larger number of subroutine calls. The optimal number of rows returned by ftgrsz is valid only as long as the application program is only reading or writing data in the specified table. Any other calls to access data in the table header would cause additional blocks of data to be loaded into the I/O buffers displacing data from the original table, and should be avoided during the critical period while the table is being read or written. 4. Use binary table extensions rather than ASCII table extensions for better efficiency when dealing with tabular data. The I/O to ASCII tables is slower because of the overhead in formatting or parsing the ASCII data fields, and because ASCII tables are about twice as large as binary tables with the same information content. 5. Design software so that it reads the FITS header keywords in the same order in which they occur in the file. When reading keywords, FITSIO searches forward starting from the position of the last keyword that was read. If it reaches the end of the header without finding the keyword, it then goes back to the start of the header and continues the search down to the position where it started. In practice, as long as the entire FITS header can fit at one time in the available internal I/O buffers, then the header keyword access will be very fast and it makes little difference which order they are accessed. 6. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and TZERO keywords) in FITS files since the scaling operations add to the processing time needed to read or write the data. In some cases it may be more efficient to temporarily turn off the scaling (using ftpscl or fttscl) and then read or write the raw unscaled values in the FITS file. 7. Avoid using the 'implicit datatype conversion' capability in FITSIO. For instance, when reading a FITS image with BITPIX = -32 (32-bit floating point pixels), read the data into a single precision floating point data array in the program. Forcing FITSIO to convert the data to a different datatype can significantly slow the program. 8. Where feasible, design FITS binary tables using vector column elements so that the data are written as a contiguous set of bytes, rather than as single elements in multiple rows. For example, it is faster to access the data in a table that contains a single row and 2 columns with TFORM keywords equal to '10000E' and '10000J', than it is to access the same amount of data in a table with 10000 rows which has columns with the TFORM keywords equal to '1E' and '1J'. In the former case the 10000 floating point values in the first column are all written in a contiguous block of the file which can be read or written quickly, whereas in the second case each floating point value in the first column is interleaved with the integer value in the second column of the same row so CFITSIO has to explicitly move to the position of each element to be read or written. 9. Avoid the use of variable length vector columns in binary tables, since any reading or writing of these data requires that CFITSIO first look up or compute the starting address of each row of data in the heap. In practice, this is probably not a significant efficiency issue. 10. When copying data from one FITS table to another, it is faster to transfer the raw bytes instead of reading then writing each column of the table. The FITSIO subroutines FTGTBS and FTPTBS (for ASCII tables), and FTGTBB and FTPTBB (for binary tables) will perform low-level reads or writes of any contiguous range of bytes in a table extension. These routines can be used to read or write a whole row (or multiple rows) of a table with a single subroutine call. These routines are fast because they bypass all the usual data scaling, error checking and machine dependent data conversion that is normally done by FITSIO, and they allow the program to write the data to the output file in exactly the same byte order. For these same reasons, use of these routines can be somewhat risky because no validation or machine dependent conversion is performed by these routines. In general these routines are only recommended for optimizing critical pieces of code and should only be used by programmers who thoroughly understand the internal byte structure of the FITS tables they are reading or writing. 11. Another strategy for improving the speed of writing a FITS table, similar to the previous one, is to directly construct the entire byte stream for a whole table row (or multiple rows) within the application program and then write it to the FITS file with ftptbb. This avoids all the overhead normally present in the column-oriented CFITSIO write routines. This technique should only be used for critical applications, because it makes the code more difficult to understand and maintain, and it makes the code more system dependent (e.g., do the bytes need to be swapped before writing to the FITS file?). 12. Finally, external factors such as the type of magnetic disk controller (SCSI or IDE), the size of the disk cache, the average seek speed of the disk, the amount of disk fragmentation, and the amount of RAM available on the system can all have a significant impact on overall I/O efficiency. For critical applications, a system administrator should review the proposed system hardware to identify any potential I/O bottlenecks. \chapter{ Basic Interface Routines } This section defines a basic set of subroutines that can be used to perform the most common types of read and write operations on FITS files. New users should start with these subroutines and then, as needed, explore the more advance routines described in the following chapter to perform more complex or specialized operations. A right arrow symbol ($>$) is used to separate the input parameters from the output parameters in the definition of each routine. This symbol is not actually part of the calling sequence. Note that the status parameter is both an input and an output parameter and must be initialized = 0 prior to calling the FITSIO subroutines. Refer to Chapter 9 for the definition of all the parameters used by these interface routines. \section{FITSIO Error Status Routines \label{FTVERS}} \begin{description} \item[1 ] Return the current version number of the fitsio library. The version number will be incremented with each new release of CFITSIO. The 3 fields of the version string M.xx.yy are converted to a float as: M + .01*xx + .0001*yy. \end{description} \begin{verbatim} FTVERS( > version) \end{verbatim} \begin{description} \item[2 ] Return the descriptive text string corresponding to a FITSIO error status code. The 30-character length string contains a brief description of the cause of the error. \end{description} \begin{verbatim} FTGERR(status, > errtext) \end{verbatim} \begin{description} \item[3 ] Return the top (oldest) 80-character error message from the internal FITSIO stack of error messages and shift any remaining messages on the stack up one level. Any FITSIO error will generate one or more messages on the stack. Call this routine repeatedly to get each message in sequence. The error stack is empty when a blank string is returned. \end{description} \begin{verbatim} FTGMSG( > errmsg) \end{verbatim} \begin{description} \item[4 ]The FTPMRK routine puts an invisible marker on the CFITSIO error stack. The FTCMRK routine can then be used to delete any more recent error messages on the stack, back to the position of the marker. This preserves any older error messages on the stack. FTCMSG simply clears the entire error message stack. These routines are called without any arguments. \end{description} \begin{verbatim} FTPMRK FTCMRK FTCMSG \end{verbatim} \begin{description} \item[5 ] Print out the error message corresponding to the input status value and all the error messages on the FITSIO stack to the specified file stream (stream can be either the string 'STDOUT' or 'STDERR'). If the input status value = 0 then this routine does nothing. \end{description} \begin{verbatim} FTRPRT (stream, > status) \end{verbatim} \begin{description} \item[6 ] Write an 80-character message to the FITSIO error stack. Application programs should not normally write to the stack, but there may be some situations where this is desirable. \end{description} \begin{verbatim} FTPMSG(errmsg) \end{verbatim} \section{File I/O Routines} \begin{description} \item[1 ]Open an existing FITS file with readonly or readwrite access. This routine always opens the primary array (the first HDU) of the file, and does not move to a following extension, if one was specified as part of the filename. Use the FTNOPN routine to automatically move to the extension. This routine will also open IRAF images (.imh format files) and raw binary data arrays with READONLY access by first converting them on the fly into virtual FITS images. See the `Extended File Name Syntax' chapter for more details. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended filename syntax. \end{description} \begin{verbatim} FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) \end{verbatim} \begin{description} \item[2 ]Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not have the redundant blocksize argument. \end{description} \begin{verbatim} FTNOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[3 ]Open an existing FITS file with readonly or readwrite access and then move to the first HDU containing significant data, if a) an HDU name or number to open was not explicitly specified as part of the filename, and b) if the FITS file contains a null primary array (i.e., NAXIS = 0). In this case, it will look for the first IMAGE HDU with NAXIS > 0, or the first table that does not contain the strings `GTI' (Good Time Interval) or `OBSTABLE' in the EXTNAME keyword value. FTTOPN is similar, except it will move to the first significant table HDU (skipping over any image HDUs) in the file if a specific HDU name or number is not specified. FTIOPN will move to the first non-null image HDU, skipping over any tables. \end{description} \begin{verbatim} FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[4 ]Open and initialize a new empty FITS file. A template file may also be specified to define the structure of the new file (see section 4.2.4). The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended filename syntax. \end{description} \begin{verbatim} FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) \end{verbatim} \begin{description} \item[5 ]Close a FITS file previously opened with ftopen or ftinit \end{description} \begin{verbatim} FTCLOS(unit, > status) \end{verbatim} \begin{description} \item[6 ] Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the FITS primary array) \end{description} \begin{verbatim} FTMAHD(unit,nhdu, > hdutype,status) \end{verbatim} \begin{description} \item[7 ] Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array of 32-bit integers. \end{description} \begin{verbatim} FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) \end{verbatim} \begin{description} \item[8 ] Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than 32-bit integers. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update the number of rows as data is written to the table. \end{description} \begin{verbatim} FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) \end{verbatim} \begin{description} \item[9 ] Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than a 32-bit integer. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update the number of rows as data is written to the table. \end{description} \begin{verbatim} FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) \end{verbatim} \section{Keyword I/O Routines} \begin{description} \item[1 ]Put (append) an 80-character record into the CHU. \end{description} \begin{verbatim} FTPREC(unit,card, > status) \end{verbatim} \begin{description} \item[2 ] Put (append) a new keyword of the appropriate datatype into the CHU. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[3 ]Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of the header; it also returns a blank card value in this case. \end{description} \begin{verbatim} FTGREC(unit,key_no, > card,status) \end{verbatim} \begin{description} \item[4 ] Get a keyword value (with the appropriate datatype) and comment from the CHU \end{description} \begin{verbatim} FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) \end{verbatim} \begin{description} \item[5 ] Delete an existing keyword record. \end{description} \begin{verbatim} FTDKEY(unit,keyword, > status) \end{verbatim} \section{Data I/O Routines} The following routines read or write data values in the current HDU of the FITS file. Automatic datatype conversion will be attempted for numerical datatypes if the specified datatype is different from the actual datatype of the FITS array or table column. \begin{description} \item[1 ]Write elements into the primary data array or image extension. \end{description} \begin{verbatim} FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) \end{verbatim} \begin{description} \item[2 ] Read elements from the primary data array or image extension. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no checks for undefined pixels will be performed. The anyf parameter is set to true (= .true.) if any of the returned elements were undefined. \end{description} \begin{verbatim} FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[3 ] Write elements into an ASCII or binary table column. The `felem' parameter applies only to vector columns in binary tables and is ignored when writing to ASCII tables. \end{description} \begin{verbatim} FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) \end{verbatim} \begin{description} \item[4 ] Read elements from an ASCII or binary table column. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \end{description} \begin{verbatim} FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[5 ] Get the table column number and full name of the column whose name matches the input template string. See the `Advanced Interface Routines' chapter for a full description of this routine. \end{description} \begin{verbatim} FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) \end{verbatim} \chapter{ Advanced Interface Subroutines } This chapter defines all the available subroutines in the FITSIO user interface. For completeness, the basic subroutines described in the previous chapter are also repeated here. A right arrow symbol is used here to separate the input parameters from the output parameters in the definition of each subroutine. This symbol is not actually part of the calling sequence. An alphabetical list and definition of all the parameters is given at the end of this section. \section{FITS File Open and Close Subroutines: \label{FTOPEN}} \begin{description} \item[1 ]Open an existing FITS file with readonly or readwrite access. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended filename syntax. FTDOPN opens the file and also moves to the first HDU containing significant data, if no specific HDU is specified as part of the filename. FTTOPN and FTIOPN are similar except that they will move to the first table HDU or image HDU, respectively, if a HDU name or number is not specified as part of the filename. \end{description} \begin{verbatim} FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[2 ]Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not have the redundant blocksize argument. \end{description} \begin{verbatim} FTNOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[3 ] Reopen a FITS file that was previously opened with FTOPEN, FTNOPN, or FTINIT. The newunit number may then be treated as a separate file, and one may simultaneously read or write to 2 (or more) different extensions in the same file. The FTOPEN and FTNOPN routines (above) automatically detects cases where a previously opened file is being opened again, and then internally call FTREOPEN, so programs should rarely need to explicitly call this routine. \end{description} \begin{verbatim} FTREOPEN(unit, > newunit, status) \end{verbatim} \begin{description} \item[4 ]Open and initialize a new empty FITS file. The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended filename syntax. \end{description} \begin{verbatim} FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) \end{verbatim} \begin{description} \item[5 ] Create a new FITS file, using a template file to define its initial size and structure. The template may be another FITS HDU or an ASCII template file. If the input template file name is blank, then this routine behaves the same as FTINIT. The currently supported format of the ASCII template file is described under the fits\_parse\_template routine (in the general Utilities section), but this may change slightly later releases of CFITSIO. \end{description} \begin{verbatim} FTTPLT(unit, filename, tplfilename, > status) \end{verbatim} \begin{description} \item[6 ]Flush internal buffers of data to the output FITS file previously opened with ftopen or ftinit. The routine usually never needs to be called, but doing so will ensure that if the program subsequently aborts, then the FITS file will have at least been closed properly. \end{description} \begin{verbatim} FTFLUS(unit, > status) \end{verbatim} \begin{description} \item[7 ]Close a FITS file previously opened with ftopen or ftinit \end{description} \begin{verbatim} FTCLOS(unit, > status) \end{verbatim} \begin{description} \item[8 ] Close and DELETE a FITS file previously opened with ftopen or ftinit. This routine may be useful in cases where a FITS file is created, but an error occurs which prevents the complete file from being written. \end{description} \begin{verbatim} FTDELT(unit, > status) \end{verbatim} \begin{description} \item[9 ] Get the value of an unused I/O unit number which may then be used as input to FTOPEN or FTINIT. This routine searches for the first unused unit number in the range from with 99 down to 50. This routine just keeps an internal list of the allocated unit numbers and does not physically check that the Fortran unit is available (to be compatible with the SPP version of FITSIO). Thus users must not independently allocate any unit numbers in the range 50 - 99 if this routine is also to be used in the same program. This routine is provided for convenience only, and it is not required that the unit numbers used by FITSIO be allocated by this routine. \end{description} \begin{verbatim} FTGIOU( > iounit, status) \end{verbatim} \begin{description} \item[10] Free (deallocate) an I/O unit number which was previously allocated with FTGIOU. All previously allocated unit numbers may be deallocated at once by calling FTFIOU with iounit = -1. \end{description} \begin{verbatim} FTFIOU(iounit, > status) \end{verbatim} \begin{description} \item[11] Return the Fortran unit number that corresponds to the C fitsfile pointer value, or vice versa. These 2 C routines may be useful in mixed language programs where both C and Fortran subroutines need to access the same file. For example, if a FITS file is opened with unit 12 by a Fortran subroutine, then a C routine within the same program could get the fitfile pointer value to access the same file by calling 'fptr = CUnit2FITS(12)'. These routines return a value of zero if an error occurs. \end{description} \begin{verbatim} int CFITS2Unit(fitsfile *ptr); fitsfile* CUnit2FITS(int unit); \end{verbatim} \begin{description} \item[11] Parse the input filename and return the HDU number that would be moved to if the file were opened with FTNOPN. The returned HDU number begins with 1 for the primary array, so for example, if the input filename = `myfile.fits[2]' then hdunum = 3 will be returned. FITSIO does not open the file to check if the extension actually exists if an extension number is specified. If an extension *name* is included in the file name specification (e.g. `myfile.fits[EVENTS]' then this routine will have to open the FITS file and look for the position of the named extension, then close file again. This is not possible if the file is being read from the stdin stream, and an error will be returned in this case. If the filename does not specify an explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, which is functionally equivalent to hdunum = 1. This routine is mainly used for backward compatibility in the ftools software package and is not recommended for general use. It is generally better and more efficient to first open the FITS file with FTNOPN, then use FTGHDN to determine which HDU in the file has been opened, rather than calling FTEXTN followed by a call to FTNOPN. \end{description} \begin{verbatim} FTEXTN(filename, > nhdu, status) \end{verbatim} \begin{description} \item[12] Return the name of the opened FITS file. \end{description} \begin{verbatim} FTFLNM(unit, > filename, status) \end{verbatim} \begin{description} \item[13] Return the I/O mode of the open FITS file (READONLY = 0, READWRITE = 1). \end{description} \begin{verbatim} FTFLMD(unit, > iomode, status) \end{verbatim} \begin{description} \item[14] Return the file type of the opened FITS file (e.g. 'file://', 'ftp://', etc.). \end{description} \begin{verbatim} FTURLT(unit, > urltype, status) \end{verbatim} \begin{description} \item[15] Parse the input filename or URL into its component parts: the file type (file://, ftp://, http://, etc), the base input file name, the name of the output file that the input file is to be copied to prior to opening, the HDU or extension specification, the filtering specifier, the binning specifier, and the column specifier. Blank strings will be returned for any components that are not present in the input file name. \end{description} \begin{verbatim} FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) \end{verbatim} \begin{description} \item[16] Parse the input file name and return the root file name. The root name includes the file type if specified, (e.g. 'ftp://' or 'http://') and the full path name, to the extent that it is specified in the input filename. It does not include the HDU name or number, or any filtering specifications. \end{description} \begin{verbatim} FTRTNM(filename, > rootname, status) \end{verbatim} \begin{description} \item[16] Test if the input file or a compressed version of the file (with a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of the 'exists' parameter will have 1 of the 4 following values: \begin{verbatim} 2: the file does not exist, but a compressed version does exist 1: the disk file does exist 0: neither the file nor a compressed version of the file exist -1: the input file name is not a disk file (could be a ftp, http, smem, or mem file, or a file piped in on the STDIN stream) \end{verbatim} \end{description} \begin{verbatim} FTEXIST(filename, > exists, status); \end{verbatim} \section{HDU-Level Operations \label{FTMAHD}} When a FITS file is first opened or created, the internal buffers in FITSIO automatically point to the first HDU in the file. The following routines may be used to move to another HDU in the file. Note that the HDU numbering convention used in FITSIO denotes the primary array as the first HDU, the first extension in a FITS file is the second HDU, and so on. \begin{description} \item[1 ] Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the FITS primary array) \end{description} \begin{verbatim} FTMAHD(unit,nhdu, > hdutype,status) \end{verbatim} \begin{description} \item[2 ]Move to a new (existing) HDU forward or backwards relative to the CHDU \end{description} \begin{verbatim} FTMRHD(unit,nmove, > hdutype,status) \end{verbatim} \begin{description} \item[3 ] Move to the (first) HDU which has the specified extension type and EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype parameter may have a value of IMAGE\_HDU (0), ASCII\_TBL (1), BINARY\_TBL (2), or ANY\_HDU (-1) where ANY\_HDU means that only the extname and extver values will be used to locate the correct extension. If the input value of extver is 0 then the EXTVER keyword is ignored and the first HDU with a matching EXTNAME (or HDUNAME) keyword will be found. If no matching HDU is found in the file then the current HDU will remain unchanged and a status = BAD\_HDU\_NUM (301) will be returned. \end{description} \begin{verbatim} FTMNHD(unit, hdutype, extname, extver, > status) \end{verbatim} \begin{description} \item[4 ]Get the number of the current HDU in the FITS file (primary array = 1) \end{description} \begin{verbatim} FTGHDN(unit, > nhdu) \end{verbatim} \begin{description} \item[5 ] Return the type of the current HDU in the FITS file. The possible values for hdutype are IMAGE\_HDU (0), ASCII\_TBL (1), or BINARY\_TBL (2). \end{description} \begin{verbatim} FTGHDT(unit, > hdutype, status) \end{verbatim} \begin{description} \item[6 ] Return the total number of HDUs in the FITS file. The CHDU remains unchanged. \end{description} \begin{verbatim} FTTHDU(unit, > hdunum, status) \end{verbatim} \begin{description} \item[7 ]Create (append) a new empty HDU at the end of the FITS file. This new HDU becomes the Current HDU, but it is completely empty and contains no header keywords or data. It is recommended that FTIIMG, FTITAB or FTIBIN be used instead of this routine. \end{description} \begin{verbatim} FTCRHD(unit, > status) \end{verbatim} \begin{description} \item[8 ] Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array of 32-bit integers. \end{description} \begin{verbatim} FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) \end{verbatim} \begin{description} \item[9 ] Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than 32-bit integers. \end{description} \begin{verbatim} FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) \end{verbatim} \begin{description} \item[10] Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than a 32-bit integer. \end{description} \begin{verbatim} FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) \end{verbatim} \begin{description} \item[11] Resize an image by modifing the size, dimensions, and/or datatype of the current primary array or image extension. If the new image, as specified by the input arguments, is larger than the current existing image in the FITS file then zero fill data will be inserted at the end of the current image and any following extensions will be moved further back in the file. Similarly, if the new image is smaller than the current image then any following extensions will be shifted up towards the beginning of the FITS file and the image data will be truncated to the new size. This routine rewrites the BITPIX, NAXIS, and NAXISn keywords with the appropriate values for new image. The FTRSIMLL routine is identical to the FTRSIM routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array of 32-bit integers. \end{description} \begin{verbatim} FTRSIM(unit,bitpix,naxis,naxes,status) FTRSIMLL(unit,bitpix,naxis,naxesll,status) \end{verbatim} \begin{description} \item[12] Delete the CHDU in the FITS file. Any following HDUs will be shifted forward in the file, to fill in the gap created by the deleted HDU. In the case of deleting the primary array (the first HDU in the file) then the current primary array will be replace by a null primary array containing the minimum set of required keywords and no data. If there are more extensions in the file following the one that is deleted, then the the CHDU will be redefined to point to the following extension. If there are no following extensions then the CHDU will be redefined to point to the previous HDU. The output HDUTYPE parameter indicates the type of the new CHDU after the previous CHDU has been deleted. \end{description} \begin{verbatim} FTDHDU(unit, > hdutype,status) \end{verbatim} \begin{description} \item[13] Copy all or part of the input FITS file and append it to the end of the output FITS file. If 'previous' (an integer parameter) is not equal to 0, then any HDUs preceding the current HDU in the input file will be copied to the output file. Similarly, 'current' and 'following' determine whether the current HDU, and/or any following HDUs in the input file will be copied to the output file. If all 3 parameters are not equal to zero, then the entire input file will be copied. On return, the current HDU in the input file will be unchanged, and the last copied HDU will be the current HDU in the output file. \end{description} \begin{verbatim} FTCPFL(iunit, ounit, previous, current, following, > status) \end{verbatim} \begin{description} \item[14] Copy the entire CHDU from the FITS file associated with IUNIT to the CHDU of the FITS file associated with OUNIT. The output HDU must be empty and not already contain any keywords. Space will be reserved for MOREKEYS additional keywords in the output header if there is not already enough space. \end{description} \begin{verbatim} FTCOPY(iunit,ounit,morekeys, > status) \end{verbatim} \begin{description} \item[15] Copy the header (and not the data) from the CHDU associated with inunit to the CHDU associated with outunit. If the current output HDU is not completely empty, then the CHDU will be closed and a new HDU will be appended to the output file. This routine will automatically transform the necessary keywords when copying a primary array to and image extension, or an image extension to a primary array. An empty output data unit will be created (all values = 0). \end{description} \begin{verbatim} FTCPHD(inunit, outunit, > status) \end{verbatim} \begin{description} \item[16] Copy just the data from the CHDU associated with IUNIT to the CHDU associated with OUNIT. This will overwrite any data previously in the OUNIT CHDU. This low level routine is used by FTCOPY, but it may also be useful in certain application programs which want to copy the data from one FITS file to another but also want to modify the header keywords in the process. all the required header keywords must be written to the OUNIT CHDU before calling this routine \end{description} \begin{verbatim} FTCPDT(iunit,ounit, > status) \end{verbatim} \section{Define or Redefine the structure of the CHDU \label{FTRDEF}} It should rarely be necessary to call the subroutines in this section. FITSIO internally calls these routines whenever necessary, so any calls to these routines by application programs will likely be redundant. \begin{description} \item[1 ] This routine forces FITSIO to scan the current header keywords that define the structure of the HDU (such as the NAXISn, PCOUNT and GCOUNT keywords) so that it can initialize the internal buffers that describe the HDU structure. This routine may be used instead of the more complicated calls to ftpdef, ftadef or ftbdef. This routine is also very useful for reinitializing the structure of an HDU, if the number of rows in a table, as specified by the NAXIS2 keyword, has been modified from its initial value. \end{description} \begin{verbatim} FTRDEF(unit, > status) (DEPRECATED) \end{verbatim} \begin{description} \item[2 ]Define the structure of the primary array or IMAGE extension. When writing GROUPed FITS files that by convention set the NAXIS1 keyword equal to 0, ftpdef must be called with naxes(1) = 1, NOT 0, otherwise FITSIO will report an error status=308 when trying to write data to a group. Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) \end{verbatim} \begin{description} \item[3 ] Define the structure of an ASCII table (TABLE) extension. Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) \end{verbatim} \begin{description} \item[4 ] Define the structure of a binary table (BINTABLE) extension. Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) \end{verbatim} \begin{description} \item[5 ] Define the size of the Current Data Unit, overriding the length of the data unit as previously defined by ftpdef, ftadef, or ftbdef. This is useful if one does not know the total size of the data unit until after the data have been written. The size (in bytes) of an ASCII or Binary table is given by NAXIS1 * NAXIS2. (Note that to determine the value of NAXIS1 it is often more convenient to read the value of the NAXIS1 keyword from the output file, rather than computing the row length directly from all the TFORM keyword values). Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTDDEF(unit,bytlen, > status) (DEPRECATED) \end{verbatim} \begin{description} \item[6 ] Define the zero indexed byte offset of the 'heap' measured from the start of the binary table data. By default the heap is assumed to start immediately following the regular table data, i.e., at location NAXIS1 x NAXIS2. This routine is only relevant for binary tables which contain variable length array columns (with TFORMn = 'Pt'). This subroutine also automatically writes the value of theap to a keyword in the extension header. This subroutine must be called after the required keywords have been written (with ftphbn) and after the table structure has been defined (with ftbdef) but before any data is written to the table. \end{description} \begin{verbatim} FTPTHP(unit,theap, > status) \end{verbatim} \section{FITS Header I/O Subroutines} \subsection{Header Space and Position Routines \label{FTHDEF}} \begin{description} \item[1 ] Reserve space in the CHU for MOREKEYS more header keywords. This subroutine may be called to reserve space for keywords which are to be written at a later time, after the data unit or subsequent extensions have been written to the FITS file. If this subroutine is not explicitly called, then the initial size of the FITS header will be limited to the space available at the time that the first data is written to the associated data unit. FITSIO has the ability to dynamically add more space to the header if needed, however it is more efficient to preallocate the required space if the size is known in advance. \end{description} \begin{verbatim} FTHDEF(unit,morekeys, > status) \end{verbatim} \begin{description} \item[2 ] Return the number of existing keywords in the CHU (NOT including the END keyword which is not considered a real keyword) and the remaining space available to write additional keywords in the CHU. (returns KEYSADD = -1 if the header has not yet been closed). Note that FITSIO will attempt to dynamically add space for more keywords if required when appending new keywords to a header. \end{description} \begin{verbatim} FTGHSP(iunit, > keysexist,keysadd,status) \end{verbatim} \begin{description} \item[3 ] Return the number of keywords in the header and the current position in the header. This returns the number of the keyword record that will be read next (or one greater than the position of the last keyword that was read or written). A value of 1 is returned if the pointer is positioned at the beginning of the header. \end{description} \begin{verbatim} FTGHPS(iunit, > keysexist,key_no,status) \end{verbatim} \subsection{Read or Write Standard Header Routines \label{FTPHPR}} These subroutines provide a simple method of reading or writing most of the keyword values that are normally required in a FITS files. These subroutines are provided for convenience only and are not required to be used. If preferred, users may call the lower-level subroutines described in the previous section to individually read or write the required keywords. Note that in most cases, the required keywords such as NAXIS, TFIELD, TTYPEn, etc, which define the structure of the HDU must be written to the header before any data can be written to the image or table. \begin{description} \item[1 ] Put the primary header or IMAGE extension keywords into the CHU. There are 2 available routines: The simpler FTPHPS routine is equivalent to calling ftphpr with the default values of SIMPLE = true, pcount = 0, gcount = 1, and EXTEND = true. PCOUNT, GCOUNT and EXTEND keywords are not required in the primary header and are only written if pcount is not equal to zero, gcount is not equal to zero or one, and if extend is TRUE, respectively. When writing to an IMAGE extension, the SIMPLE and EXTEND parameters are ignored. \end{description} \begin{verbatim} FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) \end{verbatim} \begin{description} \item[2 ] Get primary header or IMAGE extension keywords from the CHU. When reading from an IMAGE extension the SIMPLE and EXTEND parameters are ignored. \end{description} \begin{verbatim} FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) \end{verbatim} \begin{description} \item[3 ] Put the ASCII table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string values are not blank. \end{description} \begin{verbatim} FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) \end{verbatim} \begin{description} \item[4 ] Get the ASCII table header keywords from the CHU \end{description} \begin{verbatim} FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) \end{verbatim} \begin{description} \item[5 ]Put the binary table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string values are not blank. The pcount parameter, which specifies the size of the variable length array heap, should initially = 0; FITSIO will automatically update the PCOUNT keyword value if any variable length array data is written to the heap. The TFORM keyword value for variable length vector columns should have the form 'Pt(len)' or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) and `len' is an integer specifying the maximum length of the vectors in that column (len must be greater than or equal to the longest vector in the column). If `len' is not specified when the table is created (e.g., the input TFORMn value is just '1Pt') then FITSIO will scan the column when the table is first closed and will append the maximum length to the TFORM keyword value. Note that if the table is subsequently modified to increase the maximum length of the vectors then the modifying program is responsible for also updating the TFORM keyword value. \end{description} \begin{verbatim} FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat, > status) \end{verbatim} \begin{description} \item[6 ]Get the binary table header keywords from the CHU \end{description} \begin{verbatim} FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) \end{verbatim} \subsection{Write Keyword Subroutines \label{FTPREC}} \begin{description} \item[1 ]Put (append) an 80-character record into the CHU. \end{description} \begin{verbatim} FTPREC(unit,card, > status) \end{verbatim} \begin{description} \item[2 ] Put (append) a COMMENT keyword into the CHU. Multiple COMMENT keywords will be written if the input comment string is longer than 72 characters. \end{description} \begin{verbatim} FTPCOM(unit,comment, > status) \end{verbatim} \begin{description} \item[3 ]Put (append) a HISTORY keyword into the CHU. Multiple HISTORY keywords will be written if the input history string is longer than 72 characters. \end{description} \begin{verbatim} FTPHIS(unit,history, > status) \end{verbatim} \begin{description} \item[4 ] Put (append) the DATE keyword into the CHU. The keyword value will contain the current system date as a character string in 'dd/mm/yy' format. If a DATE keyword already exists in the header, then this subroutine will simply update the keyword value in-place with the current date. \end{description} \begin{verbatim} FTPDAT(unit, > status) \end{verbatim} \begin{description} \item[5 ] Put (append) a new keyword of the appropriate datatype into the CHU. Note that FTPKYS will only write string values up to 68 characters in length; longer strings will be truncated. The FTPKLS routine can be used to write longer strings, using a non-standard FITS convention. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[6 ] Put (append) a string valued keyword into the CHU which may be longer than 68 characters in length. This uses the Long String Keyword convention that is described in the "Usage Guidelines and Suggestions" section of this document. Since this uses a non-standard FITS convention to encode the long keyword string, programs which use this routine should also call the FTPLSW routine to add some COMMENT keywords to warn users of the FITS file that this convention is being used. FTPLSW also writes a keyword called LONGSTRN to record the version of the longstring convention that has been used, in case a new convention is adopted at some point in the future. If the LONGSTRN keyword is already present in the header, then FTPLSW will simply return and will not write duplicate keywords. \end{description} \begin{verbatim} FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) \end{verbatim} \begin{description} \item[7 ] Put (append) a new keyword with an undefined, or null, value into the CHU. The value string of the keyword is left blank in this case. \end{description} \begin{verbatim} FTPKYU(unit,keyword,comment, > status) \end{verbatim} \begin{description} \item[8 ] Put (append) a numbered sequence of keywords into the CHU. One may append the same comment to every keyword (and eliminate the need to have an array of identical comment strings, one for each keyword) by including the ampersand character as the last non-blank character in the (first) COMMENTS string parameter. This same string will then be used for the comment field in all the keywords. (Note that the SPP version of these routines only supports a single comment string). \end{description} \begin{verbatim} FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) \end{verbatim} \begin{description} \item[9 ]Copy an indexed keyword from one HDU to another, modifying the index number of the keyword name in the process. For example, this routine could read the TLMIN3 keyword from the input HDU (by giving keyroot = "TLMIN" and innum = 3) and write it to the output HDU with the keyword name TLMIN4 (by setting outnum = 4). If the input keyword does not exist, then this routine simply returns without indicating an error. \end{description} \begin{verbatim} FTCPKY(inunit, outunit, innum, outnum, keyroot, > status) \end{verbatim} \begin{description} \item[10] Put (append) a 'triple precision' keyword into the CHU in F28.16 format. The floating point keyword value is constructed by concatenating the input integer value with the input double precision fraction value (which must have a value between 0.0 and 1.0). The FTGKYT routine should be used to read this keyword value, because the other keyword reading subroutines will not preserve the full precision of the value. \end{description} \begin{verbatim} FTPKYT(unit,keyword,intval,dblval,comment, > status) \end{verbatim} \begin{description} \item[11] Write keywords to the CHDU that are defined in an ASCII template file. The format of the template file is described under the ftgthd routine below. \end{description} \begin{verbatim} FTPKTP(unit, filename, > status) \end{verbatim} \begin{description} \item[12] Append the physical units string to an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed FTPUNT(unit,keyword,units, > status) \end{verbatim} \subsection{Insert Keyword Subroutines \label{FTIREC}} \begin{description} \item[1 ] Insert a new keyword record into the CHU at the specified position (i.e., immediately preceding the (keyno)th keyword in the header.) This 'insert record' subroutine is somewhat less efficient then the 'append record' subroutine (FTPREC) described above because the remaining keywords in the header have to be shifted down one slot. \end{description} \begin{verbatim} FTIREC(unit,key_no,card, > status) \end{verbatim} \begin{description} \item[2 ] Insert a new keyword into the CHU. The new keyword is inserted immediately following the last keyword that has been read from the header. The FTIKLS subroutine works the same as the FTIKYS subroutine, except it also supports long string values greater than 68 characters in length. These 'insert keyword' subroutines are somewhat less efficient then the 'append keyword' subroutines described above because the remaining keywords in the header have to be shifted down one slot. \end{description} \begin{verbatim} FTIKEY(unit, card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[3 ] Insert a new keyword with an undefined, or null, value into the CHU. The value string of the keyword is left blank in this case. \end{description} \begin{verbatim} FTIKYU(unit,keyword,comment, > status) \end{verbatim} \subsection{Read Keyword Subroutines \label{FTGREC}} These routines return the value of the specified keyword(s). Wild card characters (*, ?, or \#) may be used when specifying the name of the keyword to be read: a '?' will match any single character at that position in the keyword name and a '*' will match any length (including zero) string of characters. The '\#' character will match any consecutive string of decimal digits (0 - 9). Note that when a wild card is used in the input keyword name, the routine will only search for a match from the current header position to the end of the header. It will not resume the search from the top of the header back to the original header position as is done when no wildcards are included in the keyword name. If the desired keyword string is 8-characters long (the maximum length of a keyword name) then a '*' may be appended as the ninth character of the input name to force the keyword search to stop at the end of the header (e.g., 'COMMENT *' will search for the next COMMENT keyword). The ffgrec routine may be used to set the starting position when doing wild card searches. \begin{description} \item[1 ]Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of the header; it also returns a blank card value in this case. \end{description} \begin{verbatim} FTGREC(unit,key_no, > card,status) \end{verbatim} \begin{description} \item[2 ] Get the name, value (as a string), and comment of the nth keyword in CHU. This routine also checks that the returned keyword name (KEYWORD) contains only legal ASCII characters. Call FTGREC and FTPSVC to bypass this error check. \end{description} \begin{verbatim} FTGKYN(unit,key_no, > keyword,value,comment,status) \end{verbatim} \begin{description} \item[3 ] Get the 80-character header record for the named keyword \end{description} \begin{verbatim} FTGCRD(unit,keyword, > card,status) \end{verbatim} \begin{description} \item[4 ] Get the next keyword whose name matches one of the strings in 'inclist' but does not match any of the strings in 'exclist'. The strings in inclist and exclist may contain wild card characters (*, ?, and \#) as described at the beginning of this section. This routine searches from the current header position to the end of the header, only, and does not continue the search from the top of the header back to the original position. The current header position may be reset with the ftgrec routine. Note that nexc may be set = 0 if there are no keywords to be excluded. This routine returns status = 202 if a matching keyword is not found. \end{description} \begin{verbatim} FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) \end{verbatim} \begin{description} \item[5 ] Get the literal keyword value as a character string. Regardless of the datatype of the keyword, this routine simply returns the string of characters in the value field of the keyword along with the comment field. \end{description} \begin{verbatim} FTGKEY(unit,keyword, > value,comment,status) \end{verbatim} \begin{description} \item[6 ] Get a keyword value (with the appropriate datatype) and comment from the CHU \end{description} \begin{verbatim} FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) \end{verbatim} \begin{description} \item[7 ] Read a string-valued keyword and return the string length, the value string, and/or the comment field. The first routine, FTGKSL, simply returns the length of the character string value of the specified keyword. The second routine, FTGSKY, also returns up to maxchar characters of the keyword value string, starting with the firstchar character, and the keyword comment string. The length argument returns the total length of the keyword value string regardless of how much of the string is actually returned (which depends on the value of the firstchar and maxchar arguments). These routines support string keywords that use the CONTINUE convention to continue long string values over multiple FITS header records. Normally, string-valued keywords have a maximum length of 68 characters, however, CONTINUE'd string keywords may be arbitrarily long. \end{description} \begin{verbatim} FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) \end{verbatim} \begin{description} \item[8 ] Get a sequence of numbered keyword values. These routines do not support wild card characters in the root name. \end{description} \begin{verbatim} FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) \end{verbatim} \begin{description} \item[9 ] Get the value of a floating point keyword, returning the integer and fractional parts of the value in separate subroutine arguments. This subroutine may be used to read any keyword but is especially useful for reading the 'triple precision' keywords written by FTPKYT. \end{description} \begin{verbatim} FTGKYT(unit,keyword, > intval,dblval,comment,status) \end{verbatim} \begin{description} \item[10] Get the physical units string in an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. A blank string is returned if no units are defined for the keyword. \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed FTGUNT(unit,keyword, > units,status) \end{verbatim} \subsection{Modify Keyword Subroutines \label{FTMREC}} Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be modified. \begin{description} \item[1 ] Modify (overwrite) the nth 80-character header record in the CHU \end{description} \begin{verbatim} FTMREC(unit,key_no,card, > status) \end{verbatim} \begin{description} \item[2 ] Modify (overwrite) the 80-character header record for the named keyword in the CHU. This can be used to overwrite the name of the keyword as well as its value and comment fields. \end{description} \begin{verbatim} FTMCRD(unit,keyword,card, > status) \end{verbatim} \begin{description} \item[3 ] Modify (overwrite) the name of an existing keyword in the CHU preserving the current value and comment fields. \end{description} \begin{verbatim} FTMNAM(unit,oldkey,keyword, > status) \end{verbatim} \begin{description} \item[4 ] Modify (overwrite) the comment field of an existing keyword in the CHU \end{description} \begin{verbatim} FTMCOM(unit,keyword,comment, > status) \end{verbatim} \begin{description} \item[5 ] Modify the value and comment fields of an existing keyword in the CHU. The FTMKLS subroutine works the same as the FTMKYS subroutine, except it also supports long string values greater than 68 characters in length. Optionally, one may modify only the value field and leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&). The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[6 ] Modify the value of an existing keyword to be undefined, or null. The value string of the keyword is set to blank. Optionally, one may leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&). \end{description} \begin{verbatim} FTMKYU(unit,keyword,comment, > status) \end{verbatim} \subsection{Update Keyword Subroutines \label{FTUCRD}} \begin{description} \item[1 ] Update an 80-character record in the CHU. If the specified keyword already exists then that header record will be replaced with the input CARD string. If it does not exist then the new record will be added to the header. The FTUKLS subroutine works the same as the FTUKYS subroutine, except it also supports long string values greater than 68 characters in length. \end{description} \begin{verbatim} FTUCRD(unit,keyword,card, > status) \end{verbatim} \begin{description} \item[2 ] Update the value and comment fields of a keyword in the CHU. The specified keyword is modified if it already exists (by calling FTMKYx) otherwise a new keyword is created by calling FTPKYx. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[3 ] Update the value of an existing keyword to be undefined, or null, or insert a new undefined-value keyword if it doesn't already exist. The value string of the keyword is left blank in this case. \end{description} \begin{verbatim} FTUKYU(unit,keyword,comment, > status) \end{verbatim} \subsection{Delete Keyword Subroutines \label{FTDREC}} \begin{description} \item[1 ] Delete an existing keyword record. The space previously occupied by the keyword is reclaimed by moving all the following header records up one row in the header. The first routine deletes a keyword at a specified position in the header (the first keyword is at position 1), whereas the second routine deletes a specifically named keyword. Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be deleted (be careful!). \end{description} \begin{verbatim} FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) \end{verbatim} \section{Data Scaling and Undefined Pixel Parameters \label{FTPSCL}} These subroutines define or modify the internal parameters used by FITSIO to either scale the data or to represent undefined pixels. Generally FITSIO will scale the data according to the values of the BSCALE and BZERO (or TSCALn and TZEROn) keywords, however these subroutines may be used to override the keyword values. This may be useful when one wants to read or write the raw unscaled values in the FITS file. Similarly, FITSIO generally uses the value of the BLANK or TNULLn keyword to signify an undefined pixel, but these routines may be used to override this value. These subroutines do not create or modify the corresponding header keyword values. \begin{description} \item[1 ] Reset the scaling factors in the primary array or image extension; does not change the BSCALE and BZERO keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * BSCALE + BZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: BSCALE and BZERO must be declared as Double Precision variables). \end{description} \begin{verbatim} FTPSCL(unit,bscale,bzero, > status) \end{verbatim} \begin{description} \item[2 ] Reset the scaling parameters for a table column; does not change the TSCALn or TZEROn keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * TSCAL + TZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). \end{description} \begin{verbatim} FTTSCL(unit,colnum,tscal,tzero, > status) \end{verbatim} \begin{description} \item[3 ] Define the integer value to be used to signify undefined pixels in the primary array or image extension. This is only used if BITPIX = 8, 16, 32. or 64 This does not create or change the value of the BLANK keyword in the header. FTPNULLL is identical to FTPNUL except that the blank value is a 64-bit integer instead of a 32-bit integer. \end{description} \begin{verbatim} FTPNUL(unit,blank, > status) FTPNULLL(unit,blankll, > status) \end{verbatim} \begin{description} \item[4 ] Define the string to be used to signify undefined pixels in a column in an ASCII table. This does not create or change the value of the TNULLn keyword. \end{description} \begin{verbatim} FTSNUL(unit,colnum,snull > status) \end{verbatim} \begin{description} \item[5 ] Define the value to be used to signify undefined pixels in an integer column in a binary table (where TFORMn = 'B', 'I', 'J', or 'K'). This does not create or change the value of the TNULLn keyword. FTTNULLL is identical to FTTNUL except that the tnull value is a 64-bit integer instead of a 32-bit integer. \end{description} \begin{verbatim} FTTNUL(unit,colnum,tnull > status) FTTNULLL(unit,colnum,tnullll > status) \end{verbatim} \section{FITS Primary Array or IMAGE Extension I/O Subroutines \label{FTPPR}} These subroutines put or get data values in the primary data array (i.e., the first HDU in the FITS file) or an IMAGE extension. The data array is represented as a single one-dimensional array of pixels regardless of the actual dimensionality of the array, and the FPIXEL parameter gives the position within this 1-D array of the first pixel to read or write. Automatic data type conversion is performed for numeric data (except for complex data types) if the data type of the primary array (defined by the BITPIX keyword) differs from the data type of the array in the calling subroutine. The data values are also scaled by the BSCALE and BZERO header values as they are being written or read from the FITS array. The ftpscl subroutine MUST be called to define the scaling parameters when writing data to the FITS array or to override the default scaling value given in the header when reading the FITS array. Two sets of subroutines are provided to read the data array which differ in the way undefined pixels are handled. The first set of routines (FTGPVx) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGPFx) returns the data element array and, in addition, a logical array which defines whether the corresponding data pixel is undefined. The latter set of subroutines may be more convenient to use in some circumstances, however, it requires an additional array of logical values which can be unwieldy when working with large data arrays. Also for programmer convenience, sets of subroutines to directly read or write 2 and 3 dimensional arrays have been provided, as well as a set of subroutines to read or write any contiguous rectangular subset of pixels within the n-dimensional array. \begin{description} \item[1 ] Get the data type of the image (= BITPIX value). Possible returned values are: 8, 16, 32, 64, -32, or -64 corresponding to unsigned byte, signed 2-byte integer, signed 4-byte integer, signed 8-byte integer, real, and double. The second subroutine is similar to FTGIDT, except that if the image pixel values are scaled, with non-default values for the BZERO and BSCALE keywords, then this routine will return the 'equivalent' data type that is needed to store the scaled values. For example, if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is floating point, and -32 will be returned. There are 2 special cases: if the image contains unsigned 2-byte integer values, with BITPIX = 16, BSCALE = 1, and BZERO = 32768, then this routine will return a non-standard value of 20 for the bitpix value. Similarly if the image contains unsigned 4-byte integers, then bitpix will be returned with a value of 40. \end{description} \begin{verbatim} FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) \end{verbatim} \begin{description} \item[2 ] Get the dimension (number of axes = NAXIS) of the image \end{description} \begin{verbatim} FTGIDM(unit, > naxis,status) \end{verbatim} \begin{description} \item[3 ] Get the size of all the dimensions of the image. The FTGISZLL routine returns an array of 64-bit integers instead of 32-bit integers. \end{description} \begin{verbatim} FTGISZ(unit, maxdim, > naxes,status) FTGISZLL(unit, maxdim, > naxesll,status) \end{verbatim} \begin{description} \item[4 ] Get the parameters that define the type and size of the image. This routine simply combines calls to the above 3 routines. The FTGIPRLL routine returns an array of 64-bit integers instead of 32-bit integers. \end{description} \begin{verbatim} FTGIPR(unit, maxdim, > bitpix, naxis, naxes, int *status) FTGIPRLL(unit, maxdim, > bitpix, naxis, naxesll, int *status) \end{verbatim} \begin{description} \item[5 ]Put elements into the data array. The FTPPR[]LL routines accept 64-bit integers for fpixel and nelements. \end{description} \begin{verbatim} FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) FTPPR[BIJKED]LL(unit,group,fpixelll,nelementsll,values, > status) \end{verbatim} \begin{description} \item[6 ]Put elements into the data array, substituting the appropriate FITS null value for all elements which are equal to the value of NULLVAL. For integer FITS arrays, the null value defined by the previous call to FTPNUL will be substituted; for floating point FITS arrays (BITPIX = -32 or -64) then the special IEEE NaN (Not-a-Number) value will be substituted. The FTPPN[]LL routines accept 64-bit integers for fpixel and nelements. \end{description} \begin{verbatim} FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) FTPPN[BIJKED]LL(unit,group,fpixelll,nelementsll,values,nullval > status) \end{verbatim} \begin{description} \item[7 ]Set data array elements as undefined. FTPPRULL accepts 64-bit integers for fpixel and nelements. \end{description} \begin{verbatim} FTPPRU(unit,group,fpixel,nelements, > status) FTPPRULL(unit,group,fpixelll,nelementsll, > status) \end{verbatim} \begin{description} \item[8 ] Get elements from the data array. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no checks for undefined pixels will be performed. FTGPV[]LL accepts 64-bit integers for fpixel and nelements. \end{description} \begin{verbatim} FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) FTGPV[BIJKED]LL(unit,group,fpixelll,nelementsll,nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[9 ] Get elements and nullflags from data array. Any undefined array elements will have the corresponding flagvals element set equal to .TRUE. \end{description} \begin{verbatim} FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) \end{verbatim} \begin{description} \item[10] Put values into group parameters \end{description} \begin{verbatim} FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) \end{verbatim} \begin{description} \item[11] Get values from group parameters \end{description} \begin{verbatim} FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) \end{verbatim} The following 4 subroutines transfer FITS images with 2 or 3 dimensions to or from a data array which has been declared in the calling program. The dimensionality of the FITS image is passed by the naxis1, naxis2, and naxis3 parameters and the declared dimensions of the program array are passed in the dim1 and dim2 parameters. Note that the program array does not have to have the same dimensions as the FITS array, but must be at least as big. For example if a FITS image with NAXIS1 = NAXIS2 = 400 is read into a program array which is dimensioned as 512 x 512 pixels, then the image will just fill the lower left corner of the array with pixels in the range 1 - 400 in the X an Y directions. This has the effect of taking a contiguous set of pixel value in the FITS array and writing them to a non-contiguous array in program memory (i.e., there are now some blank pixels around the edge of the image in the program array). \begin{description} \item[11] Put 2-D image into the data array \end{description} \begin{verbatim} FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) \end{verbatim} \begin{description} \item[12] Put 3-D cube into the data array \end{description} \begin{verbatim} FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) \end{verbatim} \begin{description} \item[13] Get 2-D image from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. \end{description} \begin{verbatim} FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) \end{verbatim} \begin{description} \item[14] Get 3-D cube from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. \end{description} \begin{verbatim} FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) \end{verbatim} The following subroutines transfer a rectangular subset of the pixels in a FITS N-dimensional image to or from an array which has been declared in the calling program. The fpixels and lpixels parameters are integer arrays which specify the starting and ending pixels in each dimension of the FITS image that are to be read or written. (Note that these are the starting and ending pixels in the FITS image, not in the declared array). The array parameter is treated simply as a large one-dimensional array of the appropriate datatype containing the pixel values; The pixel values in the FITS array are read/written from/to this program array in strict sequence without any gaps; it is up to the calling routine to correctly interpret the dimensionality of this array. The two families of FITS reading routines (FTGSVx and FTGSFx subroutines) also have an 'incs' parameter which defines the data sampling interval in each dimension of the FITS array. For example, if incs(1)=2 and incs(2)=3 when reading a 2-dimensional FITS image, then only every other pixel in the first dimension and every 3rd pixel in the second dimension will be returned in the 'array' parameter. [Note: the FTGSSx family of routines which were present in previous versions of FITSIO have been superseded by the more general FTGSVx family of routines.] \begin{description} \item[15] Put an arbitrary data subsection into the data array. \end{description} \begin{verbatim} FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) \end{verbatim} \begin{description} \item[16] Get an arbitrary data subsection from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. \end{description} \begin{verbatim} FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) \end{verbatim} \begin{description} \item[17] Get an arbitrary data subsection from the data array. Any Undefined pixels in the array will have the corresponding 'flagvals' element set equal to .TRUE. \end{description} \begin{verbatim} FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) \end{verbatim} \section{FITS ASCII and Binary Table Data I/O Subroutines} \subsection{Column Information Subroutines \label{FTGCNO}} \begin{description} \item[1 ] Get the number of rows or columns in the current FITS table. The number of rows is given by the NAXIS2 keyword and the number of columns is given by the TFIELDS keyword in the header of the table. The FTGNRWLL routine is identical to FTGNRW except that the number of rows is returned as a 64-bit integer rather than a 32-bit integer. \end{description} \begin{verbatim} FTGNRW(unit, > nrows, status) FTGNRWLL(unit, > nrowsll, status) FTGNCL(unit, > ncols, status) \end{verbatim} \begin{description} \item[2 ] Get the table column number (and name) of the column whose name matches an input template name. The table column names are defined by the TTYPEn keywords in the FITS header. If a column does not have a TTYPEn keyword, then these routines assume that the name consists of all blank characters. These 2 subroutines perform the same function except that FTGCNO only returns the number of the matching column whereas FTGCNN also returns the name of the column. If CASESEN = .true. then the column name match will be case-sensitive. The input column name template (COLTEMPLATE) is (1) either the exact name of the column to be searched for, or (2) it may contain wild cards characters (*, ?, or \#), or (3) it may contain the number of the desired column (where the number is expressed as ASCII digits). The first 2 wild cards behave similarly to UNIX filename matching: the '*' character matches any sequence of characters (including zero characters) and the '?' character matches any single character. The \# wildcard will match any consecutive string of decimal digits (0-9). As an example, the template strings 'AB?DE', 'AB*E', and 'AB*CDE' will all match the string 'ABCDE'. If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to 237 as a warning that a unique match was not found. To find the other cases that match the template, simply call the subroutine again leaving the input status value equal to 237 and the next matching name will then be returned. Repeat this process until a status = 219 (column name not found) is returned. If these subroutines fail to match the template to any of the columns in the table, they lastly check if the template can be interpreted as a simple positive integer (e.g., '7', or '512') and if so, they return that column number. If no matches are found then a status = 219 error is returned. Note that the FITS Standard recommends that only letters, digits, and the underscore character be used in column names (with no embedded spaces in the name). Trailing blank characters are not significant. \end{description} \begin{verbatim} FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) \end{verbatim} \begin{description} \item[3 ] Get the datatype of a column in an ASCII or binary table. This routine returns an integer code value corresponding to the datatype of the column. (See the FTBNFM and FTASFM subroutines in the Utilities section of this document for a list of the code values). The vector repeat count (which is alway 1 for ASCII table columns) is also returned. If the specified column has an ASCII character datatype (code = 16) then the width of a unit string in the column is also returned. Note that this routine supports the local convention for specifying arrays of strings within a binary table character column, using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this routine will return datacode = 16, repeat = 60, and width = 12. (The TDIMn keyword may also be used to specify the unit string length; The pair of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the same effect as TFORMn = '60A12'). The second routine, FTEQTY is similar except that in the case of scaled integer columns it returns the 'equivalent' data type that is needed to store the scaled values, and not necessarily the physical data type of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be the code for an unsigned short integer, not a signed short integer. Similarly, if a column has TTYPEn = '1I' and TSCALn = 0.12, then the returned typecode will be the code for a 'real' column. \end{description} \begin{verbatim} FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) \end{verbatim} \begin{description} \item[4 ] Return the display width of a column. This is the length of the string that will be returned when reading the column as a formatted string. The display width is determined by the TDISPn keyword, if present, otherwise by the data type of the column. \end{description} \begin{verbatim} FTGCDW(unit, colnum, > dispwidth, status) \end{verbatim} \begin{description} \item[5 ] Get information about an existing ASCII table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). All the returned parameters are scalar quantities. \end{description} \begin{verbatim} FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) \end{verbatim} \begin{description} \item[6 ] Get information about an existing binary table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). DATATYPE is a character string which returns the datatype of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case of an ASCII character column, DATATYPE will have a value of the form 'An' where 'n' is an integer expressing the width of the field in characters. For example, if TFORM = '160A8' then FTGBCL will return DATATYPE='A8' and REPEAT=20. All the returned parameters are scalar quantities. \end{description} \begin{verbatim} FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) \end{verbatim} \begin{description} \item[7 ] Put (append) a TDIMn keyword whose value has the form '(l,m,n...)' where l, m, n... are the dimensions of a multidimensional array column in a binary table. \end{description} \begin{verbatim} FTPTDM(unit,colnum,naxis,naxes, > status) \end{verbatim} \begin{description} \item[8 ] Return the number of and size of the dimensions of a table column. Normally this information is given by the TDIMn keyword, but if this keyword is not present then this routine returns NAXIS = 1 and NAXES(1) equal to the repeat count in the TFORM keyword. \end{description} \begin{verbatim} FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) \end{verbatim} \begin{description} \item[9 ] Decode the input TDIMn keyword string (e.g. '(100,200)') and return the number of and size of the dimensions of a binary table column. If the input tdimstr character string is null, then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. This routine is called by FTGTDM. \end{description} \begin{verbatim} FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) \end{verbatim} \begin{description} \item[10] Return the optimal number of rows to read or write at one time for maximum I/O efficiency. Refer to the ``Optimizing Code'' section in Chapter 5 for more discussion on how to use this routine. \end{description} \begin{verbatim} FTGRSZ(unit, > nrows,status) \end{verbatim} \subsection{Low-Level Table Access Subroutines \label{FTGTBS}} The following subroutines provide low-level access to the data in ASCII or binary tables and are mainly useful as an efficient way to copy all or part of a table from one location to another. These routines simply read or write the specified number of consecutive bytes in an ASCII or binary table, without regard for column boundaries or the row length in the table. The first two subroutines read or write consecutive bytes in a table to or from a character string variable, while the last two subroutines read or write consecutive bytes to or from a variable declared as a numeric data type (e.g., INTEGER, INTEGER*2, REAL, DOUBLE PRECISION). These routines do not perform any machine dependent data conversion or byte swapping, except that conversion to/from ASCII format is performed by the FTGTBS and FTPTBS routines on machines which do not use ASCII character codes in the internal data representations (e.g., on IBM mainframe computers). \begin{description} \item[1 ] Read a consecutive string of characters from an ASCII table into a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of complications related to passing string variables between C and Fortran. \end{description} \begin{verbatim} FTGTBS(unit,frow,startchar,nchars, > string,status) \end{verbatim} \begin{description} \item[2 ] Write a consecutive string of characters to an ASCII table from a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of complications related to passing string variables between C and Fortran. \end{description} \begin{verbatim} FTPTBS(unit,frow,startchar,nchars,string, > status) \end{verbatim} \begin{description} \item[3 ] Read a consecutive array of bytes from an ASCII or binary table into a numeric variable (spanning columns and multiple rows if necessary). The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, then declare the array as INTEGER*4 ARRAY(5). \end{description} \begin{verbatim} FTGTBB(unit,frow,startchar,nchars, > array,status) \end{verbatim} \begin{description} \item[4 ] Write a consecutive array of bytes to an ASCII or binary table from a numeric variable (spanning columns and multiple rows if necessary) The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, then declare the array as INTEGER*4 ARRAY(5). \end{description} \begin{verbatim} FTPTBB(unit,frow,startchar,nchars,array, > status) \end{verbatim} \subsection{Edit Rows or Columns \label{FTIROW}} \begin{description} \item[1 ] Insert blank rows into an existing ASCII or binary table (in the CDU). All the rows FOLLOWING row FROW are shifted down by NROWS rows. If FROW or FROWLL equals 0 then the blank rows are inserted at the beginning of the table. These routines modify the NAXIS2 keyword to reflect the new number of rows in the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. \end{description} \begin{verbatim} FTIROW(unit,frow,nrows, > status) FTIROWLL(unit,frowll,nrowsll, > status) \end{verbatim} \begin{description} \item[2 ] Delete rows from an existing ASCII or binary table (in the CDU). The NROWS (or NROWSLL) is the number of rows are deleted, starting with row FROW (or FROWLL), and any remaining rows in the table are shifted up to fill in the space. These routines modify the NAXIS2 keyword to reflect the new number of rows in the table. \end{description} \begin{verbatim} FTDROW(unit,frow,nrows, > status) FTDROWLL(unit,frowll,nrowsll, > status) \end{verbatim} \begin{description} \item[3 ] Delete a list of rows from an ASCII or binary table (in the CDU). In the first routine, 'rowrange' is a character string listing the rows or row ranges to delete (e.g., '2-4, 5, 8-9'). In the second routine, 'rowlist' is an integer array of row numbers to be deleted from the table. nrows is the number of row numbers in the list. The first row in the table is 1 not 0. The list of row numbers must be sorted in ascending order. \end{description} \begin{verbatim} FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) \end{verbatim} \begin{description} \item[4 ] Insert a blank column (or columns) into an existing ASCII or binary table (in the CDU). COLNUM specifies the column number that the (first) new column should occupy in the table. NCOLS specifies how many columns are to be inserted. Any existing columns from this position and higher are moved over to allow room for the new column(s). The index number on all the following keywords will be incremented if necessary to reflect the new position of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, and TCUNIn. \end{description} \begin{verbatim} FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) \end{verbatim} \begin{description} \item[5 ] Modify the vector length of a binary table column (e.g., change a column from TFORMn = '1E' to '20E'). The vector length may be increased or decreased from the current value. \end{description} \begin{verbatim} FTMVEC(unit,colnum,newveclen, > status) \end{verbatim} \begin{description} \item[6 ] Delete a column from an existing ASCII or binary table (in the CDU). The index number of all the keywords listed above (for FTICOL) will be decremented if necessary to reflect the new position of the column(s) in the table. Those index keywords that refer to the deleted column will also be deleted. Note that the physical size of the FITS file will not be reduced by this operation, and the empty FITS blocks if any at the end of the file will be padded with zeros. \end{description} \begin{verbatim} FTDCOL(unit,colnum, > status) \end{verbatim} \begin{description} \item[7 ] Copy a column from one HDU to another (or to the same HDU). If createcol = TRUE, then a new column will be inserted in the output table, at position `outcolumn', otherwise the existing output column will be overwritten (in which case it must have a compatible datatype). Note that the first column in a table is at colnum = 1. \end{description} \begin{verbatim} FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); \end{verbatim} \subsection{Read and Write Column Data Routines \label{FTPCLS}} These subroutines put or get data values in the current ASCII or Binary table extension. Automatic data type conversion is performed for numerical data types (B,I,J,E,D) if the data type of the column (defined by the TFORM keyword) differs from the data type of the calling subroutine. The data values are also scaled by the TSCALn and TZEROn header values as they are being written to or read from the FITS array. The fttscl subroutine MUST be used to define the scaling parameters when writing data to the table or to override the default scaling values given in the header when reading from the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. In the case of binary tables with vector elements, the 'felem' parameter defines the starting pixel within the element vector. This parameter is ignored with ASCII tables. Similarly, in the case of binary tables the 'nelements' parameter specifies the total number of vector values read or written (continuing on subsequent rows if required) and not the number of table elements. Two sets of subroutines are provided to get the column data which differ in the way undefined pixels are handled. The first set of routines (FTGCV) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGCF) returns the data element array and in addition a logical array of flags which defines whether the corresponding data pixel is undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \begin{description} \item[1 ] Put elements into an ASCII or binary table column (in the CDU). (The SPP FSPCLS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCL[LBIJKEDCM]LL(unit,colnum,frow,felem,nelements,values, > status) \end{verbatim} \begin{description} \item[2 ] Put elements into an ASCII or binary table column (in the CDU) substituting the appropriate FITS null value for any elements that are equal to NULLVAL. For ASCII TABLE extensions, the null value defined by the previous call to FTSNUL will be substituted; For integer FITS columns, in a binary table the null value defined by the previous call to FTTNUL will be substituted; For floating point FITS columns a special IEEE NaN (Not-a-Number) value will be substituted. The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTPCN[SBIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCN[SBIJKED]LL(unit,colnum,(I*8) frow,(I*8) felem,nelements,values, nullval > status) \end{verbatim} \begin{description} \item[3 ] Put bit values into a binary byte ('B') or bit ('X') table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be written. If LRAY is true then the corresponding bit is set to 1, otherwise the bit is set to 0. Note that in the case of 'X' columns, FITSIO will write to all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTPCLX with fbit=1 and nbit=8, then all 8 bits will be written into the first byte (as opposed to writing the first 4 bits into the first row and then the next 4 bits into the next row), even though the last 4 bits of each byte are formally not defined. \end{description} \begin{verbatim} FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) \end{verbatim} \begin{description} \item[4 ] Set table elements in a column as undefined \end{description} \begin{verbatim} FTPCLU(unit,colnum,frow,felem,nelements, > status) \end{verbatim} \begin{description} \item[5 ] Get elements from an ASCII or binary table column (in the CDU). These routines return the values of the table column array elements. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. (Note: the ftgcl routine simple gets an array of logical data values without any checks for undefined values; use the ftgcfl routine to check for undefined logical elements). (The SPP FSGCVS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCV[BIJKEDCM]LL(unit,colnum,(I*8) frow, (I*8) felem, nelements, nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[6 ] Get elements and null flags from an ASCII or binary table column (in the CHDU). These routines return the values of the table column array elements. Any undefined array elements will have the corresponding flagvals element set equal to .TRUE. The ANYF parameter is set to true if any of the returned elements are undefined. (The SPP FSGCFS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGCF[BIJKED]LL(unit,colnum, (I*8) frow, (I*8) felem,nelements, > values,flagvals,anyf,status) \end{verbatim} \begin{description} \item[7 ] Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in each dimension between the data elements that will be returned. \end{description} \begin{verbatim} FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) \end{verbatim} \begin{description} \item[8 ] Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Any Undefined pixels in the array will have the corresponding 'flagvals' element set equal to .TRUE. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in each dimension between the data elements that will be returned. \end{description} \begin{verbatim} FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) \end{verbatim} \begin{description} \item[9 ] Get bit values from a byte ('B') or bit (`X`) table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be read. If LRAY is true then the corresponding bit was set to 1, otherwise the bit was set to 0. Note that in the case of 'X' columns, FITSIO will read all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTGCX with fbit=1 and nbit=8, then all 8 bits will be read from the first byte (as opposed to reading the first 4 bits from the first row and then the first 4 bits from the next row), even though the last 4 bits of each byte are formally not defined. \end{description} \begin{verbatim} FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) \end{verbatim} \begin{description} \item[10] Read any consecutive set of bits from an 'X' or 'B' column and interpret them as an unsigned n-bit integer. NBIT must be less than or equal to 16 when calling FTGCXI, and less than or equal to 32 when calling FTGCXJ; there is no limit on the value of NBIT for FTGCXD, but the returned double precision value only has 48 bits of precision on most 32-bit word machines. The NBITS bits are interpreted as an unsigned integer unless NBITS = 16 (in FTGCXI) or 32 (in FTGCXJ) in which case the string of bits are interpreted as 16-bit or 32-bit 2's complement signed integers. If NROWS is greater than 1 then the same set of bits will be read from sequential rows in the table starting with row FROW. Note that the numbering convention used here for the FBIT parameter adopts 1 for the first element of the vector of bits; this is the Most Significant Bit of the integer value. \end{description} \begin{verbatim} FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) \end{verbatim} \begin{description} \item[11] Get the descriptor for a variable length column in a binary table. The descriptor consists of 2 integer parameters: the number of elements in the array and the starting offset relative to the start of the heap. The first routine returns a single descriptor whereas the second routine returns the descriptors for a range of rows in the table. \end{description} \begin{verbatim} FTGDES(unit,colnum,rownum, > nelements,offset,status) FTGDESLL(unit,colnum,rownum, > nelementsll,offsetll,status) FTGDESS(unit,colnum,firstrow,nrows > nelements,offset, status) FTGDESSLL(unit,colnum,firstrow,nrows > nelementsll,offsetll, status) \end{verbatim} \begin{description} \item[12] Write the descriptor for a variable length column in a binary table. These subroutines can be used in conjunction with FTGDES to enable 2 or more arrays to point to the same storage location to save storage space if the arrays are identical. \end{description} \begin{verbatim} FTPDES(unit,colnum,rownum,nelements,offset, > status) FTPDESLL(unit,colnum,rownum,nelementsll,offsetll, > status) \end{verbatim} \section{Row Selection and Calculator Routines \label{FTFROW}} These routines all parse and evaluate an input string containing a user defined arithmetic expression. The first 3 routines select rows in a FITS table, based on whether the expression evaluates to true (not equal to zero) or false (zero). The other routines evaluate the expression and calculate a value for each row of the table. The allowed expression syntax is described in the row filter section in the earlier `Extended File Name Syntax' chapter of this document. The expression may also be written to a text file, and the name of the file, prepended with a '@' character may be supplied for the 'expr' parameter (e.g. '@filename.txt'). The expression in the file can be arbitrarily complex and extend over multiple lines of the file. Lines that begin with 2 slash characters ('//') will be ignored and may be used to add comments to the file. \begin{description} \item[1 ] Evaluate a boolean expression over the indicated rows, returning an array of flags indicating which rows evaluated to TRUE/FALSE \end{description} \begin{verbatim} FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) \end{verbatim} \begin{description} \item[2 ] Find the first row which satisfies the input boolean expression \end{description} \begin{verbatim} FTFFRW(unit, expr, > rownum, status) \end{verbatim} \begin{description} \item[3 ]Evaluate an expression on all rows of a table. If the input and output files are not the same, copy the TRUE rows to the output file; if the output table is not empty, then this routine will append the new selected rows after the existing rows. If the files are the same, delete the FALSE rows (preserve the TRUE rows). \end{description} \begin{verbatim} FTSROW(inunit, outunit, expr, > status) \end{verbatim} \begin{description} \item[4 ] Calculate an expression for the indicated rows of a table, returning the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If nulval==NULL, UNDEFs will be zeroed out. For vector results, the number of elements returned may be less than nelements if nelements is not an even multiple of the result dimension. Call FTTEXP to obtain the dimensions of the results. \end{description} \begin{verbatim} FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) \end{verbatim} \begin{description} \item[5 ]Evaluate an expression and write the result either to a column (if the expression is a function of other columns in the table) or to a keyword (if the expression evaluates to a constant and is not a function of other columns in the table). In the former case, the parName parameter is the name of the column (which may or may not already exist) into which to write the results, and parInfo contains an optional TFORM keyword value if a new column is being created. If a TFORM value is not specified then a default format will be used, depending on the expression. If the expression evaluates to a constant, then the result will be written to the keyword name given by the parName parameter, and the parInfo parameter may be used to supply an optional comment for the keyword. If the keyword does not already exist, then the name of the keyword must be preceded with a '\#' character, otherwise the result will be written to a column with that name. \end{description} \begin{verbatim} FTCALC(inunit, expr, outunit, parName, parInfo, > status) \end{verbatim} \begin{description} \item[6 ] This calculator routine is similar to the previous routine, except that the expression is only evaluated over the specified row ranges. nranges specifies the number of row ranges, and firstrow and lastrow give the starting and ending row number of each range. \end{description} \begin{verbatim} FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) \end{verbatim} \begin{description} \item[7 ]Evaluate the given expression and return dimension and type information on the result. The returned dimensions correspond to a single row entry of the requested expression, and are equivalent to the result of fits\_read\_tdim(). Note that strings are considered to be one element regardless of string length. If maxdim == 0, then naxes is optional. \end{description} \begin{verbatim} FTTEXP(unit, expr, maxdim > datatype, nelem, naxis, naxes, status) \end{verbatim} \section{Celestial Coordinate System Subroutines \label{FTGICS}} The FITS community has adopted a set of keyword conventions that define the transformations needed to convert between pixel locations in an image and the corresponding celestial coordinates on the sky, or more generally, that define world coordinates that are to be associated with any pixel location in an n-dimensional FITS array. CFITSIO is distributed with a couple of self-contained World Coordinate System (WCS) routines, however, these routines DO NOT support all the latest WCS conventions, so it is STRONGLY RECOMMENDED that software developers use a more robust external WCS library. Several recommended libraries are: \begin{verbatim} WCSLIB - supported by Mark Calabretta WCSTools - supported by Doug Mink AST library - developed by the U.K. Starlink project \end{verbatim} More information about the WCS keyword conventions and links to all of these WCS libraries can be found on the FITS Support Office web site at http://fits.gsfc.nasa.gov under the WCS link. The functions provided in these external WCS libraries will need access to the WCS information contained in the FITS file headers. One convenient way to pass this information to the external library is to use FITSIO to copy the header keywords into one long character string, and then pass this string to an interface routine in the external library that will extract the necessary WCS information (e.g., see the astFitsChan and astPutCards routines in the Starlink AST library). The following FITSIO routines DO NOT support the more recent WCS conventions that have been approved as part of the FITS standard. Consequently, the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED that software developers not use these routines, and instead use an external WCS library, as described above. These routines are included mainly for backward compatibility with existing software. They support the following standard map projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the legal values for the coordtype parameter). These routines are based on similar functions in Classic AIPS. All the angular quantities are given in units of degrees. \begin{description} \item[1 ] Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS image (i.e., the primary array or an image extension). These values may then be passed to the subroutines that perform the coordinate transformations. If any or all of the WCS keywords are not present, then default values will be returned. If the first coordinate axis is the declination-like coordinate, then this routine will swap them so that the longitudinal-like coordinate is returned as the first axis. If the file uses the newer 'CDj\_i' WCS transformation matrix keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then this routine will calculate and return the values of the equivalent old-style keywords. Note that the conversion from the new-style keywords to the old-style values is sometimes only an approximation, so if the approximation is larger than an internally defined threshold level, then CFITSIO will still return the approximate WCS keyword values, but will also return with status = 506, to warn the calling program that approximations have been made. It is then up to the calling program to decide whether the approximations are sufficiently accurate for the particular application, or whether more precise WCS transformations must be performed using new-style WCS keywords directly. \end{description} \begin{verbatim} FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) \end{verbatim} \begin{description} \item[2 ] Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS table where the X and Y (or RA and DEC coordinates are stored in 2 separate columns of the table. These values may then be passed to the subroutines that perform the coordinate transformations. \end{description} \begin{verbatim} FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) \end{verbatim} \begin{description} \item[3 ] Calculate the celestial coordinate corresponding to the input X and Y pixel location in the image. \end{description} \begin{verbatim} FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) \end{verbatim} \begin{description} \item[4 ] Calculate the X and Y pixel location corresponding to the input celestial coordinate in the image. \end{description} \begin{verbatim} FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) \end{verbatim} \section{File Checksum Subroutines \label{FTPCKS}} The following routines either compute or validate the checksums for the CHDU. The DATASUM keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. If there is no data unit then the value is set to zero. The numerical value is stored as an ASCII string of digits, enclosed in quotes, because the value may be too large to represent as a 32-bit signed integer. The CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. These checksum keyword conventions are based on a paper by Rob Seaman published in the proceedings of the ADASS IV conference in Baltimore in November 1994 and a later revision in June 1995. \begin{description} \item[1 ] Compute and write the DATASUM and CHECKSUM keyword values for the CHDU into the current header. The DATASUM value is the 32-bit checksum for the data unit, expressed as a decimal integer enclosed in single quotes. The CHECKSUM keyword value is a 16-character string which is the ASCII-encoded value for the complement of the checksum for the whole HDU. If these keywords already exist, their values will be updated only if necessary (i.e., if the file has been modified since the original keyword values were computed). \end{description} \begin{verbatim} FTPCKS(unit, > status) \end{verbatim} \begin{description} \item[2 ] Update the CHECKSUM keyword value in the CHDU, assuming that the DATASUM keyword exists and already has the correct value. This routine calculates the new checksum for the current header unit, adds it to the data unit checksum, encodes the value into an ASCII string, and writes the string to the CHECKSUM keyword. \end{description} \begin{verbatim} FTUCKS(unit, > status) \end{verbatim} \begin{description} \item[3 ] Verify the CHDU by computing the checksums and comparing them with the keywords. The data unit is verified correctly if the computed checksum equals the value of the DATASUM keyword. The checksum for the entire HDU (header plus data unit) is correct if it equals zero. The output DATAOK and HDUOK parameters in this subroutine are integers which will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the DATASUM or CHECKSUM keyword is not present, or value = -1 if the computed checksum is not correct. \end{description} \begin{verbatim} FTVCKS(unit, > dataok,hduok,status) \end{verbatim} \begin{description} \item[4 ] Compute and return the checksum values for the CHDU (as double precision variables) without creating or modifying the CHECKSUM and DATASUM keywords. This routine is used internally by FTVCKS, but may be useful in other situations as well. \end{description} \begin{verbatim} FTGCKS(unit, > datasum,hdusum,status) \end{verbatim} \begin{description} \item[5 ] Encode a checksum value (stored in a double precision variable) into a 16-character string. If COMPLEMENT = .true. then the 32-bit sum value will be complemented before encoding. \end{description} \begin{verbatim} FTESUM(sum,complement, > checksum) \end{verbatim} \begin{description} \item[6 ] Decode a 16 character checksum string into a double precision value. If COMPLEMENT = .true. then the 32-bit sum value will be complemented after decoding. \end{description} \begin{verbatim} FTDSUM(checksum,complement, > sum) \end{verbatim} \section{ Date and Time Utility Routines \label{FTGSDT}} The following routines help to construct or parse the FITS date/time strings. Starting in the year 2000, the FITS DATE keyword values (and the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' (date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the number of decimal places in the seconds value is optional. These times are in UTC. The older 'dd/mm/yy' date format may not be used for dates after 01 January 2000. \begin{description} \item[1 ] Get the current system date. The returned year has 4 digits (1999, 2000, etc.) \end{description} \begin{verbatim} FTGSDT( > day, month, year, status ) \end{verbatim} \begin{description} \item[2 ] Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). The time will be in UTC/GMT if available, as indicated by a returned timeref value = 0. If the returned value of timeref = 1 then this indicates that it was not possible to convert the local time to UTC, and thus the local time was returned. \end{description} \begin{verbatim} FTGSTM(> datestr, timeref, status) \end{verbatim} \begin{description} \item[3 ] Construct a date string from the input date values. If the year is between 1900 and 1998, inclusive, then the returned date string will have the old FITS format ('dd/mm/yy'), otherwise the date string will have the new FITS format ('YYYY-MM-DD'). Use FTTM2S instead to always return a date string using the new FITS format. \end{description} \begin{verbatim} FTDT2S( year, month, day, > datestr, status) \end{verbatim} \begin{description} \item[4 ] Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). If the year, month, and day values all = 0 then only the time is encoded with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many decimal places of fractional seconds to include in the string. If `decimals' is negative, then only the date will be return ('YYYY-MM-DD'). \end{description} \begin{verbatim} FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) \end{verbatim} \begin{description} \item[5 ] Return the date as read from the input string, where the string may be in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or 'YYYY-MM-DD') FITS format. \end{description} \begin{verbatim} FTS2DT(datestr, > year, month, day, status) \end{verbatim} \begin{description} \item[6 ] Return the date and time as read from the input string, where the string may be in either the old or new FITS format. The returned hours, minutes, and seconds values will be set to zero if the input string does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, the returned year, month, and date values will be set to zero if the date is not included in the input string ('hh:mm:ss.ddd...'). \end{description} \begin{verbatim} FTS2TM(datestr, > year, month, day, hour, minute, second, status) \end{verbatim} \section{General Utility Subroutines \label{FTGHAD}} The following utility subroutines may be useful for certain applications: \begin{description} \item[1 ] Return the starting byte address of the CHDU and the next HDU. \end{description} \begin{verbatim} FTGHAD(iunit, > curaddr, nextaddr) \end{verbatim} \begin{description} \item[2 ] Convert a character string to uppercase (operates in place). \end{description} \begin{verbatim} FTUPCH(string) \end{verbatim} \begin{description} \item[3 ] Compare the input template string against the reference string to see if they match. The template string may contain wildcard characters: '*' will match any sequence of characters (including zero characters) and '?' will match any single character in the reference string. The '\#' character will match any consecutive string of decimal digits (0 - 9). If CASESN = .true. then the match will be case sensitive. The returned MATCH parameter will be .true. if the 2 strings match, and EXACT will be .true. if the match is exact (i.e., if no wildcard characters were used in the match). Both strings must be 68 characters or less in length. \end{description} \begin{verbatim} FTCMPS(str_template, string, casesen, > match, exact) \end{verbatim} \begin{description} \item[4 ] Test that the keyword name contains only legal characters: A-Z,0-9, hyphen, and underscore. \end{description} \begin{verbatim} FTTKEY(keyword, > status) \end{verbatim} \begin{description} \item[5 ] Test that the keyword record contains only legal printable ASCII characters \end{description} \begin{verbatim} FTTREC(card, > status) \end{verbatim} \begin{description} \item[6 ] Test whether the current header contains any NULL (ASCII 0) characters. These characters are illegal in the header, but they will go undetected by most of the CFITSIO keyword header routines, because the null is interpreted as the normal end-of-string terminator. This routine returns the position of the first null character in the header, or zero if there are no nulls. For example a returned value of 110 would indicate that the first NULL is located in the 30th character of the second keyword in the header (recall that each header record is 80 characters long). Note that this is one of the few FITSIO routines in which the returned value is not necessarily equal to the status value). \end{description} \begin{verbatim} FTNCHK(unit, > status) \end{verbatim} \begin{description} \item[7 ] Parse a header keyword record and return the name of the keyword and the length of the name. The keyword name normally occupies the first 8 characters of the record, except under the HIERARCH convention where the name can be up to 70 characters in length. \end{description} \begin{verbatim} FTGKNM(card, > keyname, keylength, staThe '\#' character will match any consecutive string of decimal digits (0 - 9). tus) \end{verbatim} \begin{description} \item[8 ] Parse a header keyword record. This subroutine parses the input header record to return the value (as a character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then the value string is returned blank and the comment string is set equal to column 9 - 80 of the input string. \end{description} \begin{verbatim} FTPSVC(card, > value,comment,status) \end{verbatim} \begin{description} \item[9 ] Construct a properly formated 80-character header keyword record from the input keyword name, keyword value, and keyword comment strings. Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. The value string may contain an integer, floating point, logical, or quoted character string (e.g., "12", "15.7", "T", or "'NGC 1313'"). \end{description} \begin{verbatim} FTMKKY(keyname, value, comment, > card, status) \end{verbatim} \begin{description} \item[10] Construct a sequence keyword name (ROOT + nnn). This subroutine appends the sequence number to the root string to create a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') \end{description} \begin{verbatim} FTKEYN(keyroot,seq_no, > keyword,status) \end{verbatim} \begin{description} \item[11] Construct a sequence keyword name (n + ROOT). This subroutine concatenates the sequence number to the front of the root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') \end{description} \begin{verbatim} FTNKEY(seq_no,keyroot, > keyword,status) \end{verbatim} \begin{description} \item[12] Determine the datatype of a keyword value string. This subroutine parses the keyword value string (usually columns 11-30 of the header record) to determine its datatype. \end{description} \begin{verbatim} FTDTYP(value, > dtype,status) \end{verbatim} \begin{description} \item[13] Return the class of input header record. The record is classified into one of the following categories (the class values are defined in fitsio.h). Note that this is one of the few FITSIO routines that does not return a status value. \end{description} \begin{verbatim} Class Value Keywords TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY 20 The keywords used in the compressed image or table format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY 40 BLANK, TNULLn TYP_DIM_KEY 50 TDIMn TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY 70 BUNIT, TUNITn TYP_DISP_KEY 80 TDISPn TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY 100 CHECKSUM, DATASUM TYP_WCS_KEY 110 CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn (i,j,m,n are integers, s is any letter) TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY 140 CONTINUE TYP_USER_KEY 150 all other keywords class = FTGKCL (char *card) \end{verbatim} \begin{description} \item[14] Parse the 'TFORM' binary table column format string. This subroutine parses the input TFORM character string and returns the integer datatype code, the repeat count of the field, and, in the case of character string fields, the length of the unit string. The following datatype codes are returned (the negative of the value is returned if the column contains variable-length arrays): \end{description} \begin{verbatim} Datatype DATACODE value bit, X 1 byte, B 11 logical, L 14 ASCII character, A 16 short integer, I 21 integer, J 41 real, E 42 double precision, D 82 complex 83 double complex 163 FTBNFM(tform, > datacode,repeat,width,status) \end{verbatim} \begin{description} \item[15] Parse the 'TFORM' keyword value that defines the column format in an ASCII table. This routine parses the input TFORM character string and returns the datatype code, the width of the column, and (if it is a floating point column) the number of decimal places to the right of the decimal point. The returned datatype codes are the same as for the binary table, listed above, with the following additional rules: integer columns that are between 1 and 4 characters wide are defined to be short integers (code = 21). Wider integer columns are defined to be regular integers (code = 41). Similarly, Fixed decimal point columns (with TFORM = 'Fw.d') are defined to be single precision reals (code = 42) if w is between 1 and 7 characters wide, inclusive. Wider 'F' columns will return a double precision data code (= 82). 'Ew.d' format columns will have datacode = 42, and 'Dw.d' format columns will have datacode = 82. \end{description} \begin{verbatim} FTASFM(tform, > datacode,width,decimals,status) \end{verbatim} \begin{description} \item[16] Calculate the starting column positions and total ASCII table width based on the input array of ASCII table TFORM values. The SPACE input parameter defines how many blank spaces to leave between each column (it is recommended to have one space between columns for better human readability). \end{description} \begin{verbatim} FTGABC(tfields,tform,space, > rowlen,tbcol,status) \end{verbatim} \begin{description} \item[17] Parse a template string and return a formatted 80-character string suitable for appending to (or deleting from) a FITS header file. This subroutine is useful for parsing lines from an ASCII template file and reformatting them into legal FITS header records. The formatted string may then be passed to the FTPREC, FTMCRD, or FTDKEY subroutines to append or modify a FITS header record. \end{description} \begin{verbatim} FTGTHD(template, > card,hdtype,status) \end{verbatim} The input TEMPLATE character string generally should contain 3 tokens: (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The TEMPLATE string must adhere to the following format: \begin{description} \item[- ] The KEYNAME token must begin in columns 1-8 and be a maximum of 8 characters long. If the first 8 characters of the template line are blank then the remainder of the line is considered to be a FITS comment (with a blank keyword name). A legal FITS keyword name may only contain the characters A-Z, 0-9, and '-' (minus sign) and underscore. This subroutine will automatically convert any lowercase characters to uppercase in the output string. If KEYNAME = 'COMMENT' or 'HISTORY' then the remainder of the line is considered to be a FITS COMMENT or HISTORY record, respectively. \end{description} \begin{description} \item[- ] The VALUE token must be separated from the KEYNAME token by one or more spaces and/or an '=' character. The datatype of the VALUE token (numeric, logical, or character string) is automatically determined and the output CARD string is formatted accordingly. The value token may be forced to be interpreted as a string (e.g. if it is a string of numeric digits) by enclosing it in single quotes. If the value token is a character string that contains 1 or more embedded blank space characters or slash ('/') characters then the entire character string must be enclosed in single quotes. \end{description} \begin{description} \item[- ] The COMMENT token is optional, but if present must be separated from the VALUE token by a blank space or a '/' character. \end{description} \begin{description} \item[- ] One exception to the above rules is that if the first non-blank character in the template string is a minus sign ('-') followed by a single token, or a single token followed by an equal sign, then it is interpreted as the name of a keyword which is to be deleted from the FITS header. \end{description} \begin{description} \item[- ] The second exception is that if the template string starts with a minus sign and is followed by 2 tokens then the second token is interpreted as the new name for the keyword specified by first token. In this case the old keyword name (first token) is returned in characters 1-8 of the returned CARD string, and the new keyword name (the second token) is returned in characters 41-48 of the returned CARD string. These old and new names may then be passed to the FTMNAM subroutine which will change the keyword name. \end{description} The HDTYPE output parameter indicates how the returned CARD string should be interpreted: \begin{verbatim} hdtype interpretation ------ ------------------------------------------------- -2 Modify the name of the keyword given in CARD(1:8) to the new name given in CARD(41:48) -1 CARD(1:8) contains the name of a keyword to be deleted from the FITS header. 0 append the CARD string to the FITS header if the keyword does not already exist, otherwise update the value/comment if the keyword is already present in the header. 1 simply append this keyword to the FITS header (CARD is either a HISTORY or COMMENT keyword). 2 This is a FITS END record; it should not be written to the FITS header because FITSIO automatically appends the END record when the header is closed. \end{verbatim} EXAMPLES: The following lines illustrate valid input template strings: \begin{verbatim} INTVAL 7 This is an integer keyword RVAL 34.6 / This is a floating point keyword EVAL=-12.45E-03 This is a floating point keyword in exponential notation lval F This is a boolean keyword This is a comment keyword with a blank keyword name SVAL1 = 'Hello world' / this is a string keyword SVAL2 '123.5' this is also a string keyword sval3 123+ / this is also a string keyword with the value '123+ ' # the following template line deletes the DATE keyword - DATE # the following template line modifies the NAME keyword to OBJECT - NAME OBJECT \end{verbatim} \begin{description} \item[18] Parse the input string containing a list of rows or row ranges, and return integer arrays containing the first and last row in each range. For example, if rowlist = "3-5, 6, 8-9" then it will return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. At most, 'maxranges' number of ranges will be returned. 'maxrows' is the maximum number of rows in the table; any rows or ranges larger than this will be ignored. The rows must be specified in increasing order, and the ranges must not overlap. A minus sign may be use to specify all the rows to the upper or lower bound, so "50-" means all the rows from 50 to the end of the table, and "-" means all the rows in the table, from 1 - maxrows. \end{description} \begin{verbatim} FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) \end{verbatim} \chapter{ The CFITSIO Iterator Function } The fits\_iterate\_data function in CFITSIO provides a unique method of executing an arbitrary user-supplied `work' function that operates on rows of data in FITS tables or on pixels in FITS images. Rather than explicitly reading and writing the FITS images or columns of data, one instead calls the CFITSIO iterator routine, passing to it the name of the user's work function that is to be executed along with a list of all the table columns or image arrays that are to be passed to the work function. The CFITSIO iterator function then does all the work of allocating memory for the arrays, reading the input data from the FITS file, passing them to the work function, and then writing any output data back to the FITS file after the work function exits. Because it is often more efficient to process only a subset of the total table rows at one time, the iterator function can determine the optimum amount of data to pass in each iteration and repeatedly call the work function until the entire table been processed. For many applications this single CFITSIO iterator function can effectively replace all the other CFITSIO routines for reading or writing data in FITS images or tables. Using the iterator has several important advantages over the traditional method of reading and writing FITS data files: \begin{itemize} \item It cleanly separates the data I/O from the routine that operates on the data. This leads to a more modular and `object oriented' programming style. \item It simplifies the application program by eliminating the need to allocate memory for the data arrays and eliminates most of the calls to the CFITSIO routines that explicitly read and write the data. \item It ensures that the data are processed as efficiently as possible. This is especially important when processing tabular data since the iterator function will calculate the most efficient number of rows in the table to be passed at one time to the user's work function on each iteration. \item Makes it possible for larger projects to develop a library of work functions that all have a uniform calling sequence and are all independent of the details of the FITS file format. \end{itemize} There are basically 2 steps in using the CFITSIO iterator function. The first step is to design the work function itself which must have a prescribed set of input parameters. One of these parameters is a structure containing pointers to the arrays of data; the work function can perform any desired operations on these arrays and does not need to worry about how the input data were read from the file or how the output data get written back to the file. The second step is to design the driver routine that opens all the necessary FITS files and initializes the input parameters to the iterator function. The driver program calls the CFITSIO iterator function which then reads the data and passes it to the user's work function. Further details on using the iterator function can be found in the companion CFITSIO User's Guide, and in the iter\_a.f, iter\_b.f and iter\_c.f example programs. \chapter{ Extended File Name Syntax } \section{Overview} CFITSIO supports an extended syntax when specifying the name of the data file to be opened or created that includes the following features: \begin{itemize} \item CFITSIO can read IRAF format images which have header file names that end with the '.imh' extension, as well as reading and writing FITS files, This feature is implemented in CFITSIO by first converting the IRAF image into a temporary FITS format file in memory, then opening the FITS file. Any of the usual CFITSIO routines then may be used to read the image header or data. Similarly, raw binary data arrays can be read by converting them on the fly into virtual FITS images. \item FITS files on the Internet can be read (and sometimes written) using the FTP, HTTP, or ROOT protocols. \item FITS files can be piped between tasks on the stdin and stdout streams. \item FITS files can be read and written in shared memory. This can potentially achieve much better data I/O performance compared to reading and writing the same FITS files on magnetic disk. \item Compressed FITS files in gzip or Unix COMPRESS format can be directly read. \item Output FITS files can be written directly in compressed gzip format, thus saving disk space. \item FITS table columns can be created, modified, or deleted 'on-the-fly' as the table is opened by CFITSIO. This creates a virtual FITS file containing the modifications that is then opened by the application program. \item Table rows may be selected, or filtered out, on the fly when the table is opened by CFITSIO, based on an arbitrary user-specified expression. Only rows for which the expression evaluates to 'TRUE' are retained in the copy of the table that is opened by the application program. \item Histogram images may be created on the fly by binning the values in table columns, resulting in a virtual N-dimensional FITS image. The application program then only sees the FITS image (in the primary array) instead of the original FITS table. \end{itemize} The latter 3 features in particular add very powerful data processing capabilities directly into CFITSIO, and hence into every task that uses CFITSIO to read or write FITS files. For example, these features transform a very simple program that just copies an input FITS file to a new output file (like the `fitscopy' program that is distributed with CFITSIO) into a multipurpose FITS file processing tool. By appending fairly simple qualifiers onto the name of the input FITS file, the user can perform quite complex table editing operations (e.g., create new columns, or filter out rows in a table) or create FITS images by binning or histogramming the values in table columns. In addition, these functions have been coded using new state-of-the art algorithms that are, in some cases, 10 - 100 times faster than previous widely used implementations. Before describing the complete syntax for the extended FITS file names in the next section, here are a few examples of FITS file names that give a quick overview of the allowed syntax: \begin{itemize} \item {\tt 'myfile.fits'}: the simplest case of a FITS file on disk in the current directory. \item {\tt 'myfile.imh'}: opens an IRAF format image file and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 short integer array in this case) and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' suffix will cause it to be compressed in gzip format when it is written to disk. \item {\tt 'myfile.fits.gz[events, 2]'}: opens and uncompresses the gzipped file myfile.fits then moves to the extension which has the keywords EXTNAME = 'EVENTS' and EXTVER = 2. \item {\tt '-'}: a dash (minus sign) signifies that the input file is to be read from the stdin file stream, or that the output file is to be written to the stdout stream. \item {\tt 'ftp://legacy.gsfc.nasa.gov/test/vela.fits'}: FITS files in any ftp archive site on the Internet may be directly opened with read-only access. \item {\tt 'http://legacy.gsfc.nasa.gov/software/test.fits'}: any valid URL to a FITS file on the Web may be opened with read-only access. \item {\tt 'root://legacy.gsfc.nasa.gov/test/vela.fits'}: similar to ftp access except that it provides write as well as read access to the files across the network. This uses the root protocol developed at CERN. \item {\tt 'shmem://h2[events]'}: opens the FITS file in a shared memory segment and moves to the EVENTS extension. \item {\tt 'mem://'}: creates a scratch output file in core computer memory. The resulting 'file' will disappear when the program exits, so this is mainly useful for testing purposes when one does not want a permanent copy of the output file. \item {\tt 'myfile.fits[3; Images(10)]'}: opens a copy of the image contained in the 10th row of the 'Images' column in the binary table in the 3th extension of the FITS file. The application just sees this single image as the primary array. \item {\tt 'myfile.fits[1:512:2, 1:512:2]'}: opens a section of the input image ranging from the 1st to the 512th pixel in X and Y, and selects every second pixel in both dimensions, resulting in a 256 x 256 pixel image in this case. \item {\tt 'myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]'}: creates and opens a temporary file on the fly (in memory or on disk) that is identical to myfile.fits except that it will contain a new column in the EVENTS extension called 'Rad' whose value is computed using the indicated expression which is a function of the values in the X and Y columns. \item {\tt 'myfile.fits[EVENTS][PHA > 5]'}: creates and opens a temporary FITS files that is identical to 'myfile.fits' except that the EVENTS table will only contain the rows that have values of the PHA column greater than 5. In general, any arbitrary boolean expression using a C or Fortran-like syntax, which may combine AND and OR operators, may be used to select rows from a table. \item {\tt 'myfile.fits[EVENTS][bin (X,Y)=1,2048,4]'}: creates a temporary FITS primary array image which is computed on the fly by binning (i.e, computing the 2-dimensional histogram) of the values in the X and Y columns of the EVENTS extension. In this case the X and Y coordinates range from 1 to 2048 and the image pixel size is 4 units in both dimensions, so the resulting image is 512 x 512 pixels in size. \item The final example combines many of these feature into one complex expression (it is broken into several lines for clarity): \begin{verbatim} 'ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] [bin (X,Y)=32]' \end{verbatim} In this case, CFITSIO (1) copies and uncompresses the FITS file from the ftp site on the legacy machine, (2) moves to the 'EVENTS' extension, (3) calculates a new column called 'phacorr', (4) selects the rows in the table that have phacorr in the range 5 to 14, and finally (5) bins the remaining rows on the X and Y column coordinates, using a pixel size = 32 to create a 2D image. All this processing is completely transparent to the application program, which simply sees the final 2-D image in the primary array of the opened file. \end{itemize} The full extended CFITSIO FITS file name can contain several different components depending on the context. These components are described in the following sections: \begin{verbatim} When creating a new file: filetype://BaseFilename(templateName) When opening an existing primary array or image HDU: filetype://BaseFilename(outName)[HDUlocation][ImageSection] When opening an existing table HDU: filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] \end{verbatim} The filetype, BaseFilename, outName, HDUlocation, and ImageSection components, if present, must be given in that order, but the colFilter, rowFilter, and binSpec specifiers may follow in any order. Regardless of the order, however, the colFilter specifier, if present, will be processed first by CFITSIO, followed by the rowFilter specifier, and finally by the binSpec specifier. Multiple colFilter or rowFilter specifications may appear as separated bracketed expressions, in any order. Multiple colFilter or rowFilter expressions are treated internally as a single effective expression, with order of operations determined from left to right. CFITSIO does not support the @filename.txt complex syntax option if multiple expressions are also used. \section{Filetype} The type of file determines the medium on which the file is located (e.g., disk or network) and, hence, which internal device driver is used by CFITSIO to read and/or write the file. Currently supported types are \begin{verbatim} file:// - file on local magnetic disk (default) ftp:// - a readonly file accessed with the anonymous FTP protocol. It also supports ftp://username:password@hostname/... for accessing password-protected ftp sites. http:// - a readonly file accessed with the HTTP protocol. It supports username:password just like the ftp driver. Proxy HTTP servers are supported using the http_proxy environment variable (see following note). stream:// - special driver to read an input FITS file from the stdin stream, and/or write an output FITS file to the stdout stream. This driver is fragile and has limited functionality (see the following note). gsiftp:// - access files on a computational grid using the gridftp protocol in the Globus toolkit (see following note). root:// - uses the CERN root protocol for writing as well as reading files over the network. shmem:// - opens or creates a file which persists in the computer's shared memory. mem:// - opens a temporary file in core memory. The file disappears when the program exits so this is mainly useful for test purposes when a permanent output file is not desired. \end{verbatim} If the filetype is not specified, then type file:// is assumed. The double slashes '//' are optional and may be omitted in most cases. \subsection{Notes about HTTP proxy servers} A proxy HTTP server may be used by defining the address (URL) and port number of the proxy server with the http\_proxy environment variable. For example \begin{verbatim} setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 \end{verbatim} will cause CFITSIO to use port 3128 on the heasarc proxy server whenever reading a FITS file with HTTP. \subsection{Notes about the stream filetype driver} The stream driver can be used to efficiently read a FITS file from the stdin file stream or write a FITS to the stdout file stream. However, because these input and output streams must be accessed sequentially, the FITS file reading or writing application must also read and write the file sequentially, at least within the tolerances described below. CFITSIO supports 2 different methods for accessing FITS files on the stdin and stdout streams. The original method, which is invoked by specifying a dash character, "-", as the name of the file when opening or creating it, works by storing a complete copy of the entire FITS file in memory. In this case, when reading from stdin, CFITSIO will copy the entire stream into memory before doing any processing of the file. Similarly, when writing to stdout, CFITSIO will create a copy of the entire FITS file in memory, before finally flushing it out to the stdout stream when the FITS file is closed. Buffering the entire FITS file in this way allows the application to randomly access any part of the FITS file, in any order, but it also requires that the user have sufficient available memory (or virtual memory) to store the entire file, which may not be possible in the case of very large files. The newer stream filetype provides a more memory-efficient method of accessing FITS files on the stdin or stdout streams. Instead of storing a copy of the entire FITS file in memory, CFITSIO only uses a set of internal buffer which by default can store 40 FITS blocks, or about 100K bytes of the FITS file. The application program must process the FITS file sequentially from beginning to end, within this 100K buffer. Generally speaking the application program must conform to the following restrictions: \begin{itemize} \item The program must finish reading or writing the header keywords before reading or writing any data in the HDU. \item The HDU can contain at most about 1400 header keywords. This is the maximum that can fit in the nominal 40 FITS block buffer. In principle, this limit could be increased by recompiling CFITSIO with a larger buffer limit, which is set by the NIOBUF parameter in fitsio2.h. \item The program must read or write the data in a sequential manner from the beginning to the end of the HDU. Note that CFITSIO's internal 100K buffer allows a little latitude in meeting this requirement. \item The program cannot move back to a previous HDU in the FITS file. \item Reading or writing of variable length array columns in binary tables is not supported on streams, because this requires moving back and forth between the fixed-length portion of the binary table and the following heap area where the arrays are actually stored. \item Reading or writing of tile-compressed images is not supported on streams, because the images are internally stored using variable length arrays. \end{itemize} \subsection{Notes about the gsiftp filetype} DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. There are two different ways to install GT: 1) goto the globus toolkit web page www.globus.org and follow the download and compilation instructions; 2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ and follow the instructions (STRONGLY SUGGESTED); Once a globus client has been installed in your system with a specific flavour it is possible to compile and install the CFITSIO libraries. Specific configuration flags must be used: 1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support PATH=GLOBUS\_LOCATION i.e. the location of your globus installation 2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour ex. gcc32 Both the flags must be used and it is mandatory to set both the PATH and the flavour. USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: example: gsiftp://remote\_server\_fqhn/directory/filename The gridftp driver uses a local buffer on a temporary file the file is located in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). Grid FTP supports multi channel transfer. By default a single channel transmission is available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS environment variable (ex. export GSIFTP\_STREAMS=8). \subsection{Notes about the root filetype} The original rootd server can be obtained from: \verb-ftp://root.cern.ch/root/rootd.tar.gz- but, for it to work correctly with CFITSIO one has to use a modified version which supports a command to return the length of the file. This modified version is available in rootd subdirectory in the CFITSIO ftp area at \begin{verbatim} ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. \end{verbatim} This small server is started either by inetd when a client requests a connection to a rootd server or by hand (i.e. from the command line). The rootd server works with the ROOT TNetFile class. It allows remote access to ROOT database files in either read or write mode. By default TNetFile assumes port 432 (which requires rootd to be started as root). To run rootd via inetd add the following line to /etc/services: \begin{verbatim} rootd 432/tcp \end{verbatim} and to /etc/inetd.conf, add the following line: \begin{verbatim} rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i \end{verbatim} Force inetd to reread its conf file with "kill -HUP ". You can also start rootd by hand running directly under your private account (no root system privileges needed). For example to start rootd listening on port 5151 just type: \verb+rootd -p 5151+ Notice: no \& is needed. Rootd will go into background by itself. \begin{verbatim} Rootd arguments: -i says we were started by inetd -p port# specifies a different port to listen on -d level level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum \end{verbatim} Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root): \begin{verbatim} - Add the following line to /etc/passwd: rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false where you may modify the uid, gid (71, 72) and the home directory to suite your system. - Add the following line to /etc/group: rootd:*:72:rootd where the gid must match the gid in /etc/passwd. - Create the directories: mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmp Where /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry. - To make writeable directories for anonymous do, for example: mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub \end{verbatim} That's all. Several additional remarks: you can login to an anonymous server either with the names "anonymous" or "rootd". The password should be of type user@host.do.main. Only the @ is enforced for the time being. In anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed. Anonymous mode only works when the server is started via inetd. \subsection{Notes about the shmem filetype:} Shared memory files are currently supported on most Unix platforms, where the shared memory segments are managed by the operating system kernel and `live' independently of processes. They are not deleted (by default) when the process which created them terminates, although they will disappear if the system is rebooted. Applications can create shared memory files in CFITSIO by calling: \begin{verbatim} fit_create_file(&fitsfileptr, "shmem://h2", &status); \end{verbatim} where the root `file' names are currently restricted to be 'h0', 'h1', 'h2', 'h3', etc., up to a maximum number defined by the the value of SHARED\_MAXSEG (equal to 16 by default). This is a prototype implementation of the shared memory interface and a more robust interface, which will have fewer restrictions on the number of files and on their names, may be developed in the future. When opening an already existing FITS file in shared memory one calls the usual CFITSIO routine: \begin{verbatim} fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) \end{verbatim} The file mode can be READWRITE or READONLY just as with disk files. More than one process can operate on READONLY mode files at the same time. CFITSIO supports proper file locking (both in READONLY and READWRITE modes), so calls to fits\_open\_file may be locked out until another other process closes the file. When an application is finished accessing a FITS file in a shared memory segment, it may close it (and the file will remain in the system) with fits\_close\_file, or delete it with fits\_delete\_file. Physical deletion is postponed until the last process calls ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on the file to be deleted, thus it can be blocked if the object was not opened in READWRITE mode. A shared memory management utility program called `smem', is included with the CFITSIO distribution. It can be built by typing `make smem'; then type `smem -h' to get a list of valid options. Executing smem without any options causes it to list all the shared memory segments currently residing in the system and managed by the shared memory driver. To get a list of all the shared memory objects, run the system utility program `ipcs [-a]'. \section{Base Filename} The base filename is the name of the file optionally including the director/subdirectory path, and in the case of `ftp', `http', and `root' filetypes, the machine identifier. Examples: \begin{verbatim} myfile.fits !data.fits /data/myfile.fits fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz \end{verbatim} When creating a new output file on magnetic disk (of type file://) if the base filename begins with an exclamation point (!) then any existing file with that same basename will be deleted prior to creating the new FITS file. Otherwise if the file to be created already exists, then CFITSIO will return an error and will not overwrite the existing file. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. An input FITS file may be compressed with the gzip or Unix compress algorithms, in which case CFITSIO will uncompress the file on the fly into a temporary file (in memory or on disk). Compressed files may only be opened with read-only permission. When specifying the name of a compressed FITS file it is not necessary to append the file suffix (e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name without the suffix, then it will automatically search for a compressed file with the same root name. In the case of reading ftp and http type files, CFITSIO generally looks for a compressed version of the file first, before trying to open the uncompressed file. By default, CFITSIO copies (and uncompressed if necessary) the ftp or http FITS file into memory on the local machine before opening it. This will fail if the local machine does not have enough memory to hold the whole FITS file, so in this case, the output filename specifier (see the next section) can be used to further control how CFITSIO reads ftp and http files. If the input file is an IRAF image file (*.imh file) then CFITSIO will automatically convert it on the fly into a virtual FITS image before it is opened by the application program. IRAF images can only be opened with READONLY file access. Similarly, if the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program (with READONLY access). In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. rawfile.dat[ib512,512]). The first character (case insensitive) defines the datatype of the array: \begin{verbatim} b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point \end{verbatim} An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These datatype characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: \begin{verbatim} raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header \end{verbatim} One special case of input file is where the filename = `-' (a dash or minus sign) or 'stdin' or 'stdout', which signifies that the input file is to be read from the stdin stream, or written to the stdout stream if a new output file is being created. In the case of reading from stdin, CFITSIO first copies the whole stream into a temporary FITS file (in memory or on disk), and subsequent reading of the FITS file occurs in this copy. When writing to stdout, CFITSIO first constructs the whole file in memory (since random access is required), then flushes it out to the stdout stream when the file is closed. In addition, if the output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed before being written to stdout. This ability to read and write on the stdin and stdout steams allows FITS files to be piped between tasks in memory rather than having to create temporary intermediate FITS files on disk. For example if task1 creates an output FITS file, and task2 reads an input FITS file, the FITS file may be piped between the 2 tasks by specifying \begin{verbatim} task1 - | task2 - \end{verbatim} where the vertical bar is the Unix piping symbol. This assumes that the 2 tasks read the name of the FITS file off of the command line. \section{Output File Name when Opening an Existing File} An optional output filename may be specified in parentheses immediately following the base file name to be opened. This is mainly useful in those cases where CFITSIO creates a temporary copy of the input FITS file before it is opened and passed to the application program. This happens by default when opening a network FTP or HTTP-type file, when reading a compressed FITS file on a local disk, when reading from the stdin stream, or when a column filter, row filter, or binning specifier is included as part of the input file specification. By default this temporary file is created in memory. If there is not enough memory to create the file copy, then CFITSIO will exit with an error. In these cases one can force a permanent file to be created on disk, instead of a temporary file in memory, by supplying the name in parentheses immediately following the base file name. The output filename can include the '!' clobber flag. Thus, if the input filename to CFITSIO is: \verb+file1.fits.gz(file2.fits)+ then CFITSIO will uncompress `file1.fits.gz' into the local disk file `file2.fits' before opening it. CFITSIO does not automatically delete the output file, so it will still exist after the application program exits. In some cases, several different temporary FITS files will be created in sequence, for instance, if one opens a remote file using FTP, then filters rows in a binary table extension, then create an image by binning a pair of columns. In this case, the remote file will be copied to a temporary local file, then a second temporary file will be created containing the filtered rows of the table, and finally a third temporary file containing the binned image will be created. In cases like this where multiple files are created, the outfile specifier will be interpreted the name of the final file as described below, in descending priority: \begin{itemize} \item as the name of the final image file if an image within a single binary table cell is opened or if an image is created by binning a table column. \item as the name of the file containing the filtered table if a column filter and/or a row filter are specified. \item as the name of the local copy of the remote FTP or HTTP file. \item as the name of the uncompressed version of the FITS file, if a compressed FITS file on local disk has been opened. \item otherwise, the output filename is ignored. \end{itemize} The output file specifier is useful when reading FTP or HTTP-type FITS files since it can be used to create a local disk copy of the file that can be reused in the future. If the output file name = `*' then a local file with the same name as the network file will be created. Note that CFITSIO will behave differently depending on whether the remote file is compressed or not as shown by the following examples: \begin{itemize} \item `ftp://remote.machine/tmp/myfile.fits.gz(*)' - the remote compressed file is copied to the local compressed file `myfile.fits.gz', which is then uncompressed in local memory before being opened and passed to the application program. \item `ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)' - the remote compressed file is copied and uncompressed into the local file `myfile.fits'. This example requires less local memory than the previous example since the file is uncompressed on disk instead of in memory. \item `ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)' - this will usually produce an error since CFITSIO itself cannot compress files. \end{itemize} The exact behavior of CFITSIO in the latter case depends on the type of ftp server running on the remote machine and how it is configured. In some cases, if the file `myfile.fits.gz' exists on the remote machine, then the server will copy it to the local machine. In other cases the ftp server will automatically create and transmit a compressed version of the file if only the uncompressed version exists. This can get rather confusing, so users should use a certain amount of caution when using the output file specifier with FTP or HTTP file types, to make sure they get the behavior that they expect. \section{Template File Name when Creating a New File} When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described below. \section{Image Tile-Compression Specification} When specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format (see section 5.5, ``Primary Array or IMAGE Extension I/O Routines'') by enclosing the compression parameters in square brackets following the root disk file name. Here are some examples of the syntax for specifying tile-compressed output images: \begin{verbatim} myfile.fit[compress] - use Rice algorithm and default tile size myfile.fit[compress GZIP] - use the specified compression algorithm; myfile.fit[compress Rice] only the first letter of the algorithm myfile.fit[compress PLIO] name is required. myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 \end{verbatim} \section{HDU Location Specification} The optional HDU location specifier defines which HDU (Header-Data Unit, also known as an `extension') within the FITS file to initially open. It must immediately follow the base file name (or the output file name if present). If it is not specified then the first HDU (the primary array) is opened. The HDU location specifier is required if the colFilter, rowFilter, or binSpec specifiers are present, because the primary array is not a valid HDU for these operations. The HDU may be specified either by absolute position number, starting with 0 for the primary array, or by reference to the HDU name, and optionally, the version number and the HDU type of the desired extension. The location of an image within a single cell of a binary table may also be specified, as described below. The absolute position of the extension is specified either by enclosed the number in square brackets (e.g., `[1]' = the first extension following the primary array) or by preceded the number with a plus sign (`+1'). To specify the HDU by name, give the name of the desired HDU (the value of the EXTNAME or HDUNAME keyword) and optionally the extension version number (value of the EXTVER keyword) and the extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, or BINTABLE), separated by commas and all enclosed in square brackets. If the value of EXTVER and XTENSION are not specified, then the first extension with the correct value of EXTNAME is opened. The extension name and type are not case sensitive, and the extension type may be abbreviated to a single letter (e.g., I = IMAGE extension or primary array, A or T = ASCII table extension, and B = binary table BINTABLE extension). If the HDU location specifier is equal to `[PRIMARY]' or `[P]', then the primary array (the first HDU) will be opened. FITS images are most commonly stored in the primary array or an image extension, but images can also be stored as a vector in a single cell of a binary table (i.e. each row of the vector column contains a different image). Such an image can be opened with CFITSIO by specifying the desired column name and the row number after the binary table HDU specifier as shown in the following examples. The column name is separated from the HDU specifier by a semicolon and the row number is enclosed in parentheses. In this case CFITSIO copies the image from the table cell into a temporary primary array before it is opened. The application program then just sees the image in the primary array, without any extensions. The particular row to be opened may be specified either by giving an absolute integer row number (starting with 1 for the first row), or by specifying a boolean expression that evaluates to TRUE for the desired row. The first row that satisfies the expression will be used. The row selection expression has the same syntax as described in the Row Filter Specifier section, below. Examples: \begin{verbatim} myfile.fits[3] - open the 3rd HDU following the primary array myfile.fits+3 - same as above, but using the FTOOLS-style notation myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' column in the 3rd extension of the file. myfile.fits[3; images(exposure > 100)] - as above, but opens the image in the first row that has an 'exposure' column value greater than 100. \end{verbatim} \section{Image Section} A virtual file containing a rectangular subsection of an image can be extracted and opened by specifying the range of pixels (start:end) along each axis to be extracted from the original image. One can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the start pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. The input image can be in the primary array, in an image extension, or contained in a vector cell of a binary table. In the later 2 cases the extension name or number must be specified before the image section specifier. Examples: \begin{verbatim} myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image consisting of the odd numbered columns (1st axis) and the even numbered rows (2nd axis) of the image in the primary array of the file. myfile.fits[*, 512:256] - open an image consisting of all the columns in the input image, but only rows 256 through 512. The image will be flipped along the 2nd axis since the starting pixel is greater than the ending pixel. myfile.fits[*:2, 512:256:2] - same as above but keeping only every other row and column in the input image. myfile.fits[-*, *] - copy the entire image, flipping it along the first axis. myfile.fits[3][1:256,1:256] - opens a subsection of the image that is in the 3rd extension of the file. myfile.fits[4; images(12)][1:10,1:10] - open an image consisting of the first 10 pixels in both dimensions. The original image resides in the 12th row of the 'images' vector column in the table in the 4th extension of the file. \end{verbatim} When CFITSIO opens an image section it first creates a temporary file containing the image section plus a copy of any other HDUs in the file. This temporary file is then opened by the application program, so it is not possible to write to or modify the input file when specifying an image section. Note that CFITSIO automatically updates the world coordinate system keywords in the header of the image section, if they exist, so that the coordinate associated with each pixel in the image section will be computed correctly. \section{Image Transform Filters} CFITSIO can apply a user-specified mathematical function to the value of every pixel in a FITS image, thus creating a new virtual image in computer memory that is then opened and read by the application program. The original FITS image is not modified by this process. The image transformation specifier is appended to the input FITS file name and is enclosed in square brackets. It begins with the letters 'PIX' to distinguish it from other types of FITS file filters that are recognized by CFITSIO. The image transforming function may use any of the mathematical operators listed in the following 'Row Filtering Specification' section of this document. Some examples of image transform filters are: \begin{verbatim} [pix X * 2.0] - multiply each pixel by 2.0 [pix sqrt(X)] - take the square root of each pixel [pix X + #ZEROPT - add the value of the ZEROPT keyword [pix X>0 ? log10(X) : -99.] - if the pixel value is greater than 0, compute the base 10 log, else set the pixel = -99. \end{verbatim} Use the letter 'X' in the expression to represent the current pixel value in the image. The expression is evaluated independently for each pixel in the image and may be a function of 1) the original pixel value, 2) the value of other pixels in the image at a given relative offset from the position of the pixel that is being evaluated, and 3) the value of any header keywords. Header keyword values are represented by the name of the keyword preceded by the '\#' sign. To access the the value of adjacent pixels in the image, specify the (1-D) offset from the current pixel in curly brackets. For example \begin{verbatim} [pix (x{-1} + x + x{+1}) / 3] \end{verbatim} will replace each pixel value with the running mean of the values of that pixel and it's 2 neighboring pixels. Note that in this notation the image is treated as a 1-D array, where each row of the image (or higher dimensional cube) is appended one after another in one long array of pixels. It is possible to refer to pixels in the rows above or below the current pixel by using the value of the NAXIS1 header keyword. For example \begin{verbatim} [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] \end{verbatim} will compute the mean of each image pixel and the pixels immediately above and below it in the adjacent rows of the image. The following more complex example creates a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels: \begin{verbatim} [pix (X + X{-1} + X{+1} + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] \end{verbatim} If the pixel offset extends beyond the first or last pixel in the image, the function will evaluate to undefined, or NULL. For complex or commonly used image filtering operations, one can write the expression into an external text file and then import it into the filter using the syntax '[pix @filename.txt]'. The mathematical expression can extend over multiple lines of text in the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. When using column filtering to open a file ``on the fly,'' it is permitted to use multiple column filtering expressions. For example, the syntax \begin{verbatim} filename.fits[col *][col -Y][col Z=X+1] \end{verbatim} would be treated as equivalent to joining the expressions with semicolons, or \begin{verbatim} filename.fits[col *; -Y;col Z=X+1] \end{verbatim} Please note that if multiple column filtering expressions are used, it is not permitted to also use the \verb+[col @filename.txt]+ syntax in any of the individual expressions. By default, the datatype of the resulting image will be the same as the original image, but one may force a different datatype by appended a code letter to the 'pix' keyword: \begin{verbatim} pixb - 8-bit byte image with BITPIX = 8 pixi - 16-bit integer image with BITPIX = 16 pixj - 32-bit integer image with BITPIX = 32 pixr - 32-bit float image with BITPIX = -32 pixd - 64-bit float image with BITPIX = -64 \end{verbatim} Also by default, any other HDUs in the input file will be copied without change to the output virtual FITS file, but one may discard the other HDUs by adding the number '1' to the 'pix' keyword (and following any optional datatype code letter). For example: \begin{verbatim} myfile.fits[3][pixr1 sqrt(X)] \end{verbatim} will create a virtual FITS file containing only a primary array image with 32-bit floating point pixels that have a value equal to the square root of the pixels in the image that is in the 3rd extension of the 'myfile.fits' file. \section{Column and Keyword Filtering Specification} The optional column/keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. This filtering specifier must be enclosed in square brackets and can be distinguished from a general row filter specifier (described below) by the fact that it begins with the string 'col ' and is not immediately followed by an equals sign. The original file is not changed by this filtering operation, and instead the modifications are made on a copy of the input FITS file (usually in memory), which also contains a copy of all the other HDUs in the file. This temporary file is passed to the application program and will persist only until the file is closed or until the program exits, unless the outfile specifier (see above) is also supplied. The column/keyword filter can be used to perform the following operations. More than one operation may be specified by separating them with commas or semi-colons. \begin{itemize} \item Copy only a specified list of columns columns to the filtered input file. The list of column name should be separated by commas or semi-colons. Wild card characters may be used in the column names to match multiple columns. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table (i.e., there is no need to explicitly list the columns to be included if any columns are being deleted). \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME column if it exists, otherwise the TIME keyword. An error is returned if neither a column nor keyword with this name exists. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. \item Rename an existing column or keyword with the syntax 'NewName == OldName'. An error is returned if neither a column nor keyword with this name exists. \item Append a new column or keyword to the table. To create a column, give the new name, optionally followed by the datatype in parentheses, followed by a single equals sign and an expression to be used to compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit integer column called 'newcol' filled with zeros). The datatype is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is not specified then an appropriate datatype will be chosen depending on the form of the expression (may be a character string, logical, bit, long integer, or double column). An appropriate vector count (in the case of binary tables) will also be added if not explicitly specified. When creating a new keyword, the keyword name must be preceded by a pound sign '\#', and the expression must evaluate to a scalar (i.e., cannot have a column name in the expression). The comment string for the keyword may be specified in parentheses immediately following the keyword name (instead of supplying a datatype as in the case of creating a new column). If the keyword name ends with a pound sign '\#', then cfitsio will substitute the number of the most recently referenced column for the \# character . This is especially useful when writing a column-related keyword like TUNITn for a newly created column, as shown in the following examples. COMMENT and HISTORY keywords may also be created with the following syntax: \begin{verbatim} #COMMENT = 'This is a comment keyword' #HISTORY = 'This is a history keyword' \end{verbatim} Note that the equal sign and the quote characters will be removed, so that the resulting header keywords in these cases will look like this: \begin{verbatim} COMMENT This is a comment keyword HISTORY This is a history keyword \end{verbatim} These two special keywords are always appended to the end of the header and will not affect any previously existing COMMENT or HISTORY keywords. \item Recompute (overwrite) the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \end{itemize} The expression that is used when appending or recomputing columns or keywords can be arbitrarily complex and may be a function of other header keyword values and other columns (in the same row). The full syntax and available functions for the expression are described below in the row filter specification section. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table. If no columns to be deleted are specified, then only the columns that are explicitly listed will be included in the filtered output table. To include all the columns, add the '*' wildcard specifier at the end of the list, as shown in the examples. For complex or commonly used operations, one can also place the operations into an external text file and import it into the column filter using the syntax '[col @filename.txt]'. The operations can extend over multiple lines of the file, but multiple operations must still be separated by commas or semi-colons. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [col Time, rate] - only the Time and rate columns will appear in the filtered input file. [col Time, *raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME; Good == STATUS] - deletes the TIME column and renames the status column to 'Good' [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - creates new PI column from PHA values and also writes the TUNITn keyword for the new column. The final '*' expression means preserve all the columns in the input table in the virtual output table; without the '*' the output table would only contain the single 'PI' column. [col rate = rate/exposure, TUNIT#(&) = 'counts/s';*] - recomputes the rate column by dividing it by the EXPOSURE keyword value. This also modifies the value of the TUNITn keyword for this column. The use of the '&' character for the keyword comment string means preserve the existing comment string for that keyword. The final '*' preserves all the columns in the input table in the virtual output table. \end{verbatim} \section{Row Filtering Specification} When entering the name of a FITS table that is to be opened by a program, an optional row filter may be specified to select a subset of the rows in the table. A temporary new FITS file is created on the fly which contains only those rows for which the row filter expression evaluates to true. (The primary array and any other extensions in the input file are also copied to the temporary file). The original FITS file is closed and the new virtual file is opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name (e.g., 'file.fits[events][GRADE==50]' selects only those rows where the GRADE column value equals 50). When dealing with tables where each row has an associated time and/or 2D spatial position, the row filter expression can also be used to select rows based on the times in a Good Time Intervals (GTI) extension, or on spatial position as given in a SAO-style region file. \subsection{General Syntax} The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression must evaluate to a boolean value for each row of the table, where a value of FALSE means that the row will be excluded. For complex or commonly used filters, one can place the expression into a text file and import it into the row filter using the syntax '[@filename.txt]'. The expression can be arbitrarily complex and extend over multiple lines of the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then enclose the name in '\$' characters as in \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. When using row filtering to open a file ``on the fly,'' it is permitted to use multiple row filtering expressions. For example, the expression \begin{verbatim} filename.fits[#ROW > 5][X.gt.7] \end{verbatim} would be treated as equivalent to joining the expressions with logical ``and'' like this, \begin{verbatim} filename.fits[(#ROW > 5)&&(X.gt.7)] \end{verbatim} Please note that if multiple row filtering expressions are used, it is not permitted to also use the \verb+[@filename.txt]+ syntax in any of the individual expressions. %% %% Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: \begin{verbatim} "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ \end{verbatim} Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive). A null value will be returned in case of illegal operations such as divide by zero, sqrt(negative) log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). \begin{verbatim} "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(y,x) "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) "hyperbolic tan" tanh(x) "round to nearest int" round(x) "round down to int" floor(x) "round up to int" ceil(x) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "error function" erf(x) "complement of erf" erfc(x) "gamma function" gamma(x) "modulus" x % y "bitwise AND" x & y "bitwise OR" x | y "bitwise XOR" x ^^ y (bitwise operators are 32-bit int only) "random # [0.0,1.0)" random() "random Gaussian" randomn() "random Poisson" randomp(x) "minimum" min(x,y) "maximum" max(x,y) "cumulative sum" accum(x) "sequential difference" seqdiff(x) "if-then-else" b?x:y "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) "substring" strmid(s,p,n) "string search" strstr(s,r) \end{verbatim} The bitwise operators for AND, OR and XOR operate upon 32-bit integer expressions only. Three different random number functions are provided: random(), with no arguments, produces a uniform random deviate between 0 and 1; randomn(), also with no arguments, produces a normal (Gaussian) random deviate with zero mean and unit standard deviation; randomp(x) produces a Poisson random deviate whose expected number of counts is X. X may be any positive real number of expected counts, including fractional values, but the return value is an integer. When the random functions are used in a vector expression, by default the same random value will be used when evaluating each element of the vector. If different random numbers are desired, then the name of a vector column should be supplied as the single argument to the random function (e.g., "flux + 0.1 * random(flux)", where "flux" is the name of a vector column). This will create a vector of random numbers that will be used in sequence when evaluating each element of the vector expression. An alternate syntax for the min and max functions has only a single argument which should be a vector value (see below). The result will be the minimum/maximum element contained within the vector. The accum(x) function forms the cumulative sum of x, element by element. Vector columns are supported simply by performing the summation process through all the values. Null values are treated as 0. The seqdiff(x) function forms the sequential difference of x, element by element. The first value of seqdiff is the first value of x. A single null value in x causes a pair of nulls in the output. The seqdiff and accum functions are functional inverses, i.e., seqdiff(accum(x)) == x as long as no null values are present. In the if-then-else expression, "b?x:y", b is an explicit boolean value or expression. There is no automatic type conversion from numeric to boolean values, so one needs to use "iVal!=0" instead of merely "iVal" as the boolean argument. x and y can be any scalar data type (including string). The angsep function computes the angular separation in degrees between 2 celestial positions, where the first 2 parameters give the RA-like and Dec-like coordinates (in decimal degrees) of the first position, and the 3rd and 4th parameters give the coordinates of the second position. The substring function strmid(S,P,N) extracts a substring from S, starting at string position P, with a substring length N. The first character position in S is labeled as 1. If P is 0, or refers to a position beyond the end of S, then the extracted substring will be NULL. S, P, and N may be functions of other columns. The string search function strstr(S,R) searches for the first occurrence of the substring R in S. The result is an integer, indicating the character position of the first match (where 1 is the first character position of S). If no match is found, then strstr() returns a NULL value. The following type casting operators are available, where the enclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: \begin{verbatim} "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i \end{verbatim} In addition, several constants are built in for use in numerical expressions: \begin{verbatim} #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string \end{verbatim} A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). Integer constants may be specified using the following notation, \begin{verbatim} 13245 decimal integer 0x12f3 hexidecimal integer 0o1373 octal integer 0b01001 binary integer \end{verbatim} Note that integer constants are only allowed to be 32-bit, i.e. between -2^(31) and +2^(31). Integer constants may be used in any arithmetic expression where an integer would be appropriate. Thus, they are distinct from bitmasks (which may be of arbitrary length, allow the "wildcard" bit, and may only be used in logical expressions; see below). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, value\_1 and value\_2 can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: \begin{verbatim} near(value_1, value_2, tolerance) \end{verbatim} When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: \begin{verbatim} "a null value?" ISNULL(x) "define a value for null" DEFNULL(x,y) "declare certain value null" SETNULL(x,y) \end{verbatim} ISNULL(x) returns a boolean value of TRUE if the argument x is NULL. DEFNULL(x,y) "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. SETNULL(x,y) allows NULL values to be inserted into a variable; if x==y, a NULL value is returned; otherwise y is returned (x and y must be numerical, and x must be a scalar). \subsection{Bit Masks} Bit masks can be used to select out rows from bit columns (TFORMn = \#X) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: \begin{verbatim} binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) \end{verbatim} In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. Although bitmasks may be of arbitrary length and contain a wildcard, they may only be used in logical expressions, unlike integer constants (see above) which may be used in any arithmetic expression. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: \begin{verbatim} flags == b0010011 or flags .eq. b10011 \end{verbatim} It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: \begin{verbatim} flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx \end{verbatim} Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: \begin{verbatim} (!flags) == b1101100 (flags & b1000001) == bx000001 \end{verbatim} Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. \subsection{Vector Columns} Vector columns can also be used in building the expression. No special syntax is required if one wants to operate on all elements of the vector. Simply use the column name as for a scalar column. Vector columns can be freely intermixed with scalar columns or constants in virtually all expressions. The result will be of the same dimension as the vector. Two vectors in an expression, though, need to have the same number of elements and have the same dimensions. The only places a vector column cannot be used (for now, anyway) are the SAO region functions and the NEAR boolean function. Arithmetic and logical operations are all performed on an element by element basis. Comparing two vector columns, eg "COL1 == COL2", thus results in another vector of boolean values indicating which elements of the two vectors are equal. Several functions are available that operate on a vector. All but the last two return a scalar result: \begin{verbatim} "minimum" MIN(V) "maximum" MAX(V) "average" AVERAGE(V) "median" MEDIAN(V) "summation" SUM(V) "standard deviation" STDDEV(V) "# of values" NELEM(V) "# of non-null values" NVALID(V) "# axes" NAXIS(V) "axis dimension" NAXES(V,n) "axis pos'n" AXISELEM(V,n) "vector element pos'n" ELEMENTNUM(V) "promote to array" ARRAY(X,d) \end{verbatim} where V represents the name of a vector column or a manually constructed vector using curly brackets as described below. The first 6 of these functions ignore any null values in the vector when computing the result. The STDDEV() function computes the sample standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead of 1/SQRT(N), where N is NVALID(V). The NAXIS(V) function returns the number of axes of the vector, for example a 2D array would be NAXIS(V) == 2. The NAXES(V,n) function returns the dimension of axis n, for example a 4x2 array would have NAXES(V,1) == 4. The ELEMENTNUM(V) and AXISELEM(V,n) functions return vectors of the same size as the input vector V. ELEMENTNUM(V) returns the vector element position for each element in the vector, starting from 1 in each row. The AXISELEM(V,n) function is similar but returns the element position of axis n only. The SUM function literally sums all the elements in x, returning a scalar value. If x is a boolean vector, SUM returns the number of TRUE elements. The NELEM function returns the number of elements in vector x whereas NVALID return the number of non-null elements in the vector. (NELEM also operates on bit and string columns, returning their column widths.) As an example, to test whether all elements of two vectors satisfy a given logical comparison, one can use the expression \begin{verbatim} SUM( COL1 > COL2 ) == NELEM( COL1 ) \end{verbatim} which will return TRUE if all elements of COL1 are greater than their corresponding elements in COL2. The ARRAY(X,d) function promotes scalar value X to a vector (or array) table element. X may be any scalar-valued item, including a column, an expression, or a constant value. The resulting vector or array will have the same scalar value replicated into each element position. This may be a useful way to construct large arrays without using the cumbersome \{vector\} notation. The dimensions of the new array are given by the second argument, d. d can either be a single constant integer value, or a vector of up to five dimensions of the form \{Nx,Ny,...\}. Thus, ARRAY(TIME,4) would promote TIME to be a 4-vector, and ARRAY(0, \{2,3,1\}) would construct an array of all 0's with dimensions $2\times 3\times 1$. A second form of ARRAY(X,d) can be used where X is a vector or array, and the dimensions d merely change the dimensions of X without changing the total number of vector elements. This is a way to re-dimension an existing array. For example, ARRAY(\{1,2,3,4\},{2,2}) would transform the 4-vector into a $2\times 2$ array. To specify a single element of a vector, give the column name followed by a comma-separated list of coordinates enclosed in square brackets. For example, if a vector column named PHAS exists in the table as a one dimensional, 256 component list of numbers from which you wanted to select the 57th component for use in the expression, then PHAS[57] would do the trick. Higher dimensional arrays of data may appear in a column. But in order to interpret them, the TDIMn keyword must appear in the header. Assuming that a (4,4,4,4) array is packed into each row of a column named ARRAY4D, the (1,2,3,4) component element of each row is accessed by ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently supported. Each vector index can itself be an expression, although it must evaluate to an integer value within the bounds of the vector. Vector columns which contain spaces or arithmetic operators must have their names enclosed in "\$" characters as with \$ARRAY-4D\$[1,2,3,4]. A more C-like syntax for specifying vector indices is also available. The element used in the preceding example alternatively could be specified with the syntax ARRAY4D[4][3][2][1]. Note the reverse order of indices (as in C), as well as the fact that the values are still ones-based (as in Fortran -- adopted to avoid ambiguity for 1D vectors). With this syntax, one does not need to specify all of the indices. To extract a 3D slice of this 4D array, use ARRAY4D[4]. Variable-length vector columns are not supported. Vectors can be manually constructed within the expression using a comma-separated list of elements surrounded by curly braces ('\{\}'). For example, '\{1,3,6,1\}' is a 4-element vector containing the values 1, 3, 6, and 1. The vector can contain only boolean, integer, and real values (or expressions). The elements will be promoted to the highest datatype present. Any elements which are themselves vectors, will be expanded out with each of its elements becoming an element in the constructed vector. \subsection{Good Time Interval Filtering and Calculation} There are two functions for filtering and calculating based on Good Time Intervals, or GTIs. GTIs are commonly used to express fragmented time ranges that are not easy to express with a single start and stop time. The time intervals are defined in a FITS table extension which contains 2 columns giving the start and stop time of each good interval. A common filtering method involves selecting rows which have a time value which lies within any GTI. The gtifilter() filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in a separate GTI extension. gtifilter(a,b,c,d) evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is \begin{verbatim} gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) or gtifilter( [ 'gtifile' [, expr [, 'STARTCOL', 'STOPCOL' ] ] ] ) \end{verbatim} where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quotes may be used. In cases where this expression is entered on the Unix command line, enclose the entire expression in double quotes, and then use single quotes within the expression to enclose the 'gtifile' and other terms. It is also usually possible to do the reverse, and enclose the whole expression in single quotes and then use double quotes within the expression. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression "gtifilter()" is equivalent to \begin{verbatim} gtifilter( "", TIME, "*START*", "*STOP*" ) \end{verbatim} This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. The related function, gtifind(a,b,c,d), is similar to gtifilter() but instead of returning true/false, gtifind() returns the GTI number that brackets the requested time sample. gtifind() returns the row number in the GTI table that matches the time sample, or -1 if the time sample is not within any GTI. gtifind() is particularly useful when entries in a table must be categorized by which GTI the fall within. For example, if events in an event list must be separated by good time interval. The results of gtifind() can be used with histogram binning techniques to bin an event list by which GTI. \begin{verbatim} gtifind( "gtifile" , expr [, "STARTCOL", "STOPCOL" ] ) \end{verbatim} The requirements for specifying the gtifile are the same as for gtifilter() as described above. Like gtifilter(), the expr is the time-like expression and is optional (defaulting to TIME). The start and stop columns default to START and STOP. The function, gtioverlap(a,b,c,d,e), computes the overlap between a user-requested time range and the entries in a GTI. The cases of no overlap, partial overlap, or overlap of many GTIs within the user requested range are handled. gtioverlap() is very useful for calculating exposure times and fractional exposures of individual time bins, say for a light curve. The syntax of gtioverlap() is \begin{verbatim} gtioverlap( "gtifile" , startExpr, stopExpr [, "STARTCOL", "STOPCOL" ] ) or gtioverlap( 'gtifile' , startExpr, stopExpr [, 'STARTCOL', 'STOPCOL' ] ) \end{verbatim} The requirements for specifying the gtifile are the same as for gtifilter() as described above. Unlike gtifilter(), the startExpr and stopExpr are not optional. startExpr provides a start of the user requested time interval. startExpr is typically TIME, but can be any valid expression. Likewise, stopExpr provides the stop of the user requested time interval, and can be an expression. For example, for a light curve with a TIME column and time bin size of 1.0 seconds, the expression \begin{verbatim} gtioverlap('gtifile',TIME,TIME+1.0) \end{verbatim} would calculate the amount of overlap exposure time between each one second time bin and the GTI in 'gtifile'. In this case the time bin is assumed to begin at the time specified by TIME and end 1 second later. Neither startExpr nor stopExpr are required to be constant, and a light curve is not required to have a constant bin size. For tables, the overlap is calculated for each entry in the table. It is also possible to calculate a single overlap value, which would typically be placed in a keyword. For example, a way to to compute the total overlap exposure of a file whose TIME column is bounded by the keywords TSTART and TSTOP, overlapping with the specified GTI, would be \begin{verbatim} #EXPOSURE = gtioverlap('gtifile',#TSTART,#TSTOP) \end{verbatim} The \verb+#EXPOSURE+ syntax with a leading \+#+ ensures that the requested values are treated as keywords. Otherwise, a column named EXPOSURE will be created with the (constant) exposure value in each entry. \subsection{Spatial Region Filtering} Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is \begin{verbatim} regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) \end{verbatim} where each "[]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. There are 2 supported formats for the region file: ASCII file or FITS binary table. The region file contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. The FITS region file format is defined in a document available from the FITS Support Office at http://fits.gsfc.nasa.gov/ registry/ region.html In its simplest form, (e.g., regfilter("region.reg") ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in \begin{verbatim} regfilter("region.reg", XPOS, YPOS) \end{verbatim} Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: \begin{verbatim} regfilter("rosat.reg", X/32.+.5, Y/32.+.5) \end{verbatim} Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): \begin{verbatim} Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) \end{verbatim} where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semi-major/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. There are three functions that are primarily for use with SAO region files and the FSAOI task, but they can be used directly. They return a boolean true or false depending on whether a two dimensional point is in the region or not: \begin{verbatim} "point in a circular region" circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) "point in an elliptical region" ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) "point in a rectangular region" box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) where (xcntr,ycntr) are the (x,y) position of the center of the region (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region (radius) is half the diameter of the circle (rotation) is the angle(degrees) that the region is rotated with respect to (xcntr,ycntr) (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column names NOTE: each parameter can itself be an expression, not merely a column name or constant. \end{verbatim} \subsection{Example Row Filters} \begin{verbatim} [ binary && mag <= 5.0] - Extract all binary stars brighter than fifth magnitude (note that the initial space is necessary to prevent it from being treated as a binning specification) [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [IMAGE[4,5] .gt. 100] - Extract all rows that have the (4,5) component of the IMAGE column greater than 100 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a spectrum, held in vector column SPEC, with at least one value 3 times greater than the background level held in a keyword, BACKGRND [VCOL=={1,4,2}] - Extract all rows whose vector column VCOL contains the 3-elements 1, 4, and 2. [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the Xs and Ys columns will be used to determine the coordinate of each row in the table. \end{verbatim} \section{ Binning or Histogramming Specification} The optional binning specifier is enclosed in square brackets and can be distinguished from a general row filter specification by the fact that it begins with the keyword 'bin' not immediately followed by an equals sign. When binning is specified, a temporary N-dimensional FITS primary array is created by computing the histogram of the values in the specified columns of a FITS table extension. After the histogram is computed the input FITS file containing the table is then closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no additional extensions). Obviously, the application program must be expecting to open a FITS image and not a FITS table in this case. The data type of the FITS histogram image may be specified by appending 'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double precision floating point) to the 'bin' keyword (e.g. '[binr X]' creates a real floating point image). If the datatype is not explicitly specified then a 32-bit integer image will be created by default, unless the weighting option is also specified in which case the image will have a 32-bit floating point data type by default. The histogram image may have from 1 to 4 dimensions (axes), depending on the number of columns that are specified. The general form of the binning specification is: \begin{verbatim} [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] \end{verbatim} in which up to 4 columns, each corresponding to an axis of the image, are listed. The column names are case insensitive, and the column number may be given instead of the name, preceded by a pound sign (e.g., [bin \#4=1:512]). If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 axes, respectively. In cases where the column name could be confused with an arithmetic expression, enclose the column name in parentheses to force the name to be interpreted literally. In addition to binning by a FITS column, any arbitrary calculator expression may be specified as well. Usage of this form would appear as: \begin{verbatim} [bin Xcol(arbitrary expression)=min:max:binsize, ... ] \end{verbatim} The column name must still be specified, and is used to label coordinate axes of the resulting image. The expression appears immediately after the name, enclosed in parentheses. The expression may use any combination of columns, keywords, functions and constants and allowed by the CFITSIO calculator. The column name (and optional expression) may be followed by an equals sign and then the lower and upper range of the histogram, and the size of the histogram bins, separated by colons. Spaces are allowed before and after the equals sign but not within the 'min:max:binsize' string. The min, max and binsize values may be integer or floating point numbers, or they may be the names of keywords in the header of the table. If the latter, then the value of that keyword is substituted into the expression. Default values for the min, max and binsize quantities will be used if not explicitly given in the binning expression as shown in these examples: \begin{verbatim} [bin x = :512:2] - use default minimum value [bin x = 1::2] - use default maximum value [bin x = 1:512] - use default bin size [bin x = 1:] - use default maximum value and bin size [bin x = :512] - use default minimum value and bin size [bin x = 2] - use default minimum and maximum values [bin x] - use default minimum, maximum and bin size [bin 4] - default 2-D image, bin size = 4 in both axes [bin] - default 2-D image \end{verbatim} CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, if they exist, for the default min, max, and binsize, respectively. If they do not exist then CFITSIO will use the actual minimum and maximum values in the column for the histogram min and max values. The default binsize will be set to 1, or (max - min) / 10., whichever is smaller, so that the histogram will have at least 10 bins along each axis. Please note that if explicit min and max values (or TLMINn/TLMAXn keywords) are not present, then CFITSIO must check every value of the binned quantity in advance to determine the binning limits. This is especially relevant for binning expressions, which must be evaluated multiple times to determine the limits of the expression. Thus, it is always advisable to specify min and max limits where possible. A shortcut notation is allowed if all the columns/axes have the same binning specification. In this case all the column names may be listed within parentheses, followed by the (single) binning specification, as in: \begin{verbatim} [bin (X,Y)=1:512:2] [bin (X,Y) = 5] \end{verbatim} The optional weighting factor is the last item in the binning specifier and, if present, is separated from the list of columns by a semi-colon. As the histogram is accumulated, this weight is used to incremented the value of the appropriated bin in the histogram. If the weighting factor is not specified, then the default weight = 1 is assumed. The weighting factor may be a constant integer or floating point number, or the name of a keyword containing the weighting value. The weighting factor may also be the name of a table column in which case the value in that column, on a row by row basis, will be used. It may also be an expression, enclosed in parenthesis, in which case the weighting value will be evaluated for each binned row and applied accordingly. In some cases, the column or keyword may give the reciprocal of the actual weight value that is needed. In this case, precede the weight keyword or column name by a slash '/' to tell CFITSIO to use the reciprocal of the value when constructing the histogram. An expression, enclosed in parentheses, may also appear after the slash, to indicate the reciprocal value of the expression. For complex or commonly used histograms, one can also place its description into a text file and import it into the binning specification using the syntax '[bin @filename.txt]'. The file's contents can extend over multiple lines, although it must still conform to the no-spaces rule for the min:max:binsize syntax and each axis specification must still be comma-separated. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [bini detx, dety] - 2-D, 16-bit integer histogram of DETX and DETY columns, using default values for the histogram range and binsize [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX and DETY columns with a bin size = 16 in both axes. The histogram values are divided by the EXPOSURE keyword value. [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by the TSTART and TSTOP keywords, with 0.1 unit size bins. [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning of the PHA column for the X axis, and 1000 bins in the range 8000. to 8100. for the Y axis. [bin pha, gti_num(gtifind())=1:2:1] - a 2-D image, where PHA is the X axis and the Y axis is an expression which evaluates to the GTI number, as determined using the GTIFIND() function. [bin time=0:4000:2000, HR( (LC2/LC1).lt.1.5 ? 1 : 2 )=1:2:1] - a 2-D histogram which determines the number of samples in two time bins between 0 and 4000 and separating hardness ratio, evaluated as (LC2/LC1), between less than 1.5 or greater than 1.5. The ?: conditional function is used to decide less (or greater) than 1.5 and assign HR bin 1 or 2. [bin @binFilter.txt] - Use the contents of the text file binFilter.txt for the binning specifications. \end{verbatim} \chapter{Template Files } When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following sections. \section{Detailed Template Line Format} The format of each ASCII template line closely follows the format of a FITS keyword record: \begin{verbatim} KEYWORD = KEYVALUE / COMMENT \end{verbatim} except that free format may be used (e.g., the equals sign may appear at any position in the line) and TAB characters are allowed and are treated the same as space characters. The KEYVALUE and COMMENT fields are optional. The equals sign character is also optional, but it is recommended that it be included for clarity. Any template line that begins with the pound '\#' character is ignored by the template parser and may be use to insert comments into the template file itself. The KEYWORD name field is limited to 8 characters in length and only the letters A-Z, digits 0-9, and the hyphen and underscore characters may be used, without any embedded spaces. Lowercase letters in the template keyword name will be converted to uppercase. Leading spaces in the template line preceding the keyword name are generally ignored, except if the first 8 characters of a template line are all blank, then the entire line is treated as a FITS comment keyword (with a blank keyword name) and is copied verbatim into the FITS header. The KEYVALUE field may have any allowed FITS data type: character string, logical, integer, real, complex integer, or complex real. Integer values must be within the allowed range of a 'signed long' variable; some C compilers only suppport 4-byte long integers with a range from -2147483648 to +2147483647, whereas other C compilers support 8-byte integers with a range of plus or minus 2**63. The character string values need not be enclosed in single quote characters unless they are necessary to distinguish the string from a different data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has an undefined (null) value if the template record only contains blanks following the "=" or between the "=" and the "/" comment field delimiter. String keyword values longer than 68 characters (the maximum length that will fit in a single FITS keyword record) are permitted using the CFITSIO long string convention. They can either be specified as a single long line in the template, or by using multiple lines where the continuing lines contain the 'CONTINUE' keyword, as in this example: \begin{verbatim} LONGKEY = 'This is a long string value that is contin&' CONTINUE 'ued over 2 records' / comment field goes here \end{verbatim} The format of template lines with CONTINUE keyword is very strict: 3 spaces must follow CONTINUE and the rest of the line is copied verbatim to the FITS file. The start of the optional COMMENT field must be preceded by "/", which is used to separate it from the keyword value field. Exceptions are if the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the first 8 characters of the template line are blanks. More than one Header-Data Unit (HDU) may be defined in the template file. The start of an HDU definition is denoted with a SIMPLE or XTENSION template line: 1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as the first keyword in the template file. If the template file begins with XTENSION instead of SIMPLE, then a default empty Primary HDU is created, and the template is then assumed to define the keywords starting with the first extension following the Primary HDU. 2) XTENSION marks the beginning of a new extension HDU definition. The previous HDU will be closed at this point and processing of the next extension begins. \section{Auto-indexing of Keywords} If a template keyword name ends with a "\#" character, it is said to be 'auto-indexed'. Each "\#" character will be replaced by the current integer index value, which gets reset = 1 at the start of each new HDU in the file (or 7 in the special case of a GROUP definition). The FIRST indexed keyword in each template HDU definition is used as the 'incrementor'; each subsequent occurrence of this SAME keyword will cause the index value to be incremented. This behavior can be rather subtle, as illustrated in the following examples in which the TTYPE keyword is the incrementor in both cases: \begin{verbatim} TTYPE# = TIME TFORM# = 1D TTYPE# = RATE TFORM# = 1E \end{verbatim} will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the template looks like, \begin{verbatim} TTYPE# = TIME TTYPE# = RATE TFORM# = 1D TFORM# = 1E \end{verbatim} this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, which is probably not what was intended! \section{Template Parser Directives} In addition to the template lines which define individual keywords, the template parser recognizes 3 special directives which are each preceded by the backslash character: \verb+ \include, \group+, and \verb+ \end+. The 'include' directive must be followed by a filename. It forces the parser to temporarily stop reading the current template file and begin reading the include file. Once the parser reaches the end of the include file it continues parsing the current template file. Include files can be nested, and HDU definitions can span multiple template files. The start of a GROUP definition is denoted with the 'group' directive, and the end of a GROUP definition is denoted with the 'end' directive. Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member blocks of type GROUP can contain their own member blocks. The GROUP definition itself occupies one FITS file HDU of special type (GROUP HDU), so if a template specifies 1 group with 1 member HDU like: \begin{verbatim} \group grpdescr = 'demo' xtension bintable # this bintable has 0 cols, 0 rows \end \end{verbatim} then the parser creates a FITS file with 3 HDUs : \begin{verbatim} 1) dummy PHDU 2) GROUP HDU (has 1 member, which is bintable in HDU number 3) 3) bintable (member of GROUP in HDU number 2) \end{verbatim} Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications can define additional columns in a GROUP HDU using TFORMn and TTYPEn (where n is 7, 8, ....) keywords or their auto-indexing equivalents. For a more complicated example of a template file using the group directives, look at the sample.tpl file that is included in the CFITSIO distribution. \section{Formal Template Syntax} The template syntax can formally be defined as follows: \begin{verbatim} TEMPLATE = BLOCK [ BLOCK ... ] BLOCK = { HDU | GROUP } GROUP = \GROUP [ BLOCK ... ] \END HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] X ... - X can be present 1 or more times { X | Y } - X or Y [ X ] - X is optional \end{verbatim} At the topmost level, the template defines 1 or more template blocks. Blocks can be either HDU (Header Data Unit) or a GROUP. For each block the parser creates 1 (or more for GROUPs) FITS file HDUs. \section{Errors} In general the fits\_execute\_template() function tries to be as atomic as possible, so either everything is done or nothing is done. If an error occurs during parsing of the template, fits\_execute\_template() will (try to) delete the top level BLOCK (with all its children if any) in which the error occurred, then it will stop reading the template file and it will return with an error. \section{Examples} 1. This template file will create a 200 x 300 pixel image, with 4-byte integer pixel values, in the primary HDU: \begin{verbatim} SIMPLE = T BITPIX = 32 NAXIS = 2 / number of dimensions NAXIS1 = 100 / length of first axis NAXIS2 = 200 / length of second axis OBJECT = NGC 253 / name of observed object \end{verbatim} The allowed values of BITPIX are 8, 16, 32, -32, or -64, representing, respectively, 8-bit integer, 16-bit integer, 32-bit integer, 32-bit floating point, or 64 bit floating point pixels. 2. To create a FITS table, the template first needs to include XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary table, and NAXIS2 to define the number of rows in the table. Two template lines are then needed to define the name (TTYPEn) and FITS data format (TFORMn) of the columns, as in this example: \begin{verbatim} xtension = bintable naxis2 = 40 ttype# = Name tform# = 10a ttype# = Npoints tform# = j ttype# = Rate tunit# = counts/s tform# = e \end{verbatim} The above example defines a null primary array followed by a 40-row binary table extension with 3 columns called 'Name', 'Npoints', and 'Rate', with data formats of '10A' (ASCII character string), '1J' (integer) and '1E' (floating point), respectively. Note that the other required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, and END) do not need to be explicitly defined in the template because their values can be inferred from the other keywords in the template. This example also illustrates that the templates are generally case-insensitive (the keyword names and TFORMn values are converted to upper-case in the FITS file) and that string keyword values generally do not need to be enclosed in quotes. \chapter{ Summary of all FITSIO User-Interface Subroutines } Error Status Routines page~\pageref{FTVERS} \begin{verbatim} FTVERS( > version) FTGERR(status, > errtext) FTGMSG( > errmsg) FTRPRT (stream, > status) FTPMSG(errmsg) FTPMRK FTCMSG FTCMRK \end{verbatim} FITS File Open and Close Subroutines: page~\pageref{FTOPEN} \begin{verbatim} FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTNOPN(unit,filename,rwmode, > status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) FTREOPEN(unit, > newunit, status) FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) FTTPLT(unit, filename, tplfilename, > status) FTFLUS(unit, > status) FTCLOS(unit, > status) FTDELT(unit, > status) FTGIOU( > iounit, status) FTFIOU(iounit, > status) CFITS2Unit(fitsfile *ptr) (C routine) CUnit2FITS(int unit) (C routine) FTEXTN(filename, > nhdu, status) FTFLNM(unit, > filename, status) FTFLMD(unit, > iomode, status) FTURLT(unit, > urltype, status) FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) FTRTNM(filename, > rootname, status) FTEXIST(filename, > exist, status) \end{verbatim} HDU-Level Operations: page~\pageref{FTMAHD} \begin{verbatim} FTMAHD(unit,nhdu, > hdutype,status) FTMRHD(unit,nmove, > hdutype,status) FTGHDN(unit, > nhdu) FTMNHD(unit, hdutype, extname, extver, > status) FTGHDT(unit, > hdutype, status) FTTHDU(unit, > hdunum, status) FTCRHD(unit, > status) FTIIMG(unit,bitpix,naxis,naxes, > status) FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTRSIM(unit,bitpix,naxis,naxes,status) FTDHDU(unit, > hdutype,status) FTCPFL(iunit,ounit,previous, current, following, > status) FTCOPY(iunit,ounit,morekeys, > status) FTCPHD(inunit, outunit, > status) FTCPDT(iunit,ounit, > status) \end{verbatim} Subroutines to specify or modify the structure of the CHDU: page~\pageref{FTRDEF} \begin{verbatim} FTRDEF(unit, > status) (DEPRECATED) FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) FTDDEF(unit,bytlen, > status) (DEPRECATED) FTPTHP(unit,theap, > status) \end{verbatim} Header Space and Position Subroutines: page~\pageref{FTHDEF} \begin{verbatim} FTHDEF(unit,morekeys, > status) FTGHSP(iunit, > keysexist,keysadd,status) FTGHPS(iunit, > keysexist,key_no,status) \end{verbatim} Read or Write Standard Header Subroutines: page~\pageref{FTPHPR} \begin{verbatim} FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) \end{verbatim} Write Keyword Subroutines: page~\pageref{FTPREC} \begin{verbatim} FTPREC(unit,card, > status) FTPCOM(unit,comment, > status) FTPHIS(unit,history, > status) FTPDAT(unit, > status) FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) FTPKYU(unit,keyword,comment, > status) FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) FTCPKYinunit, outunit, innum, outnum, keyroot, > status) FTPKYT(unit,keyword,intval,dblval,comment, > status) FTPKTP(unit, filename, > status) FTPUNT(unit,keyword,units, > status) \end{verbatim} Insert Keyword Subroutines: page~\pageref{FTIREC} \begin{verbatim} FTIREC(unit,key_no,card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTIKYU(unit,keyword,comment, > status) \end{verbatim} Read Keyword Subroutines: page~\pageref{FTGREC} \begin{verbatim} FTGREC(unit,key_no, > card,status) FTGKYN(unit,key_no, > keyword,value,comment,status) FTGCRD(unit,keyword, > card,status) FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) FTGKEY(unit,keyword, > value,comment,status) FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) FTGKYT(unit,keyword, > intval,dblval,comment,status) FTGUNT(unit,keyword, > units,status) \end{verbatim} Modify Keyword Subroutines: page~\pageref{FTMREC} \begin{verbatim} FTMREC(unit,key_no,card, > status) FTMCRD(unit,keyword,card, > status) FTMNAM(unit,oldkey,keyword, > status) FTMCOM(unit,keyword,comment, > status) FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTMKYU(unit,keyword,comment, > status) \end{verbatim} Update Keyword Subroutines: page~\pageref{FTUCRD} \begin{verbatim} FTUCRD(unit,keyword,card, > status) FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTUKYU(unit,keyword,comment, > status) \end{verbatim} Delete Keyword Subroutines: page~\pageref{FTDREC} \begin{verbatim} FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) \end{verbatim} Define Data Scaling Parameters and Undefined Pixel Flags: page~\pageref{FTPSCL} \begin{verbatim} FTPSCL(unit,bscale,bzero, > status) FTTSCL(unit,colnum,tscal,tzero, > status) FTPNUL(unit,blank, > status) FTSNUL(unit,colnum,snull > status) FTTNUL(unit,colnum,tnull > status) \end{verbatim} FITS Primary Array or IMAGE Extension I/O Subroutines: page~\pageref{FTPPR} \begin{verbatim} FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) FTGIDM(unit, > naxis,status) FTGISZ(unit, maxdim, > naxes,status) FTGIPR(unit, maxdim, > bitpix,naxis,naxes,status) FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) FTPPRU(unit,group,fpixel,nelements, > status) FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) \end{verbatim} Table Column Information Subroutines: page~\pageref{FTGCNO} \begin{verbatim} FTGNRW(unit, > nrows, status) FTGNCL(unit, > ncols, status) FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colnam,colnum,status) FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) FTGCDW(unit,colnum, > dispwidth,status) FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) FTPTDM(unit,colnum,naxis,naxes, > status) FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) FTGRSZ(unit, > nrows,status) \end{verbatim} Low-Level Table Access Subroutines: page~\pageref{FTGTBS} \begin{verbatim} FTGTBS(unit,frow,startchar,nchars, > string,status) FTPTBS(unit,frow,startchar,nchars,string, > status) FTGTBB(unit,frow,startchar,nchars, > array,status) FTPTBB(unit,frow,startchar,nchars,array, > status) \end{verbatim} Edit Rows or Columns page~\pageref{FTIROW} \begin{verbatim} FTIROW(unit,frow,nrows, > status) FTDROW(unit,frow,nrows, > status) FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) FTMVEC(unit,colnum,newveclen, > status) FTDCOL(unit,colnum, > status) FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); \end{verbatim} Read and Write Column Data Routines page~\pageref{FTPCLS} \begin{verbatim} FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCN[BIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) FTPCLU(unit,colnum,frow,felem,nelements, > status) FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) FTGDES(unit,colnum,rownum, > nelements,offset,status) FTPDES(unit,colnum,rownum,nelements,offset, > status) \end{verbatim} Row Selection and Calculator Routines: page~\pageref{FTFROW} \begin{verbatim} FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) FTFFRW(unit, expr, > rownum, status) FTSROW(inunit, outunit, expr, > status ) FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) FTCALC(inunit, expr, outunit, parName, parInfo, > status) FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) FTTEXP(unit, expr, > datatype, nelem, naxis, naxes, status) \end{verbatim} Celestial Coordinate System Subroutines: page~\pageref{FTGICS} \begin{verbatim} FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) \end{verbatim} File Checksum Subroutines: page~\pageref{FTPCKS} \begin{verbatim} FTPCKS(unit, > status) FTUCKS(unit, > status) FTVCKS(unit, > dataok,hduok,status) FTGCKS(unit, > datasum,hdusum,status) FTESUM(sum,complement, > checksum) FTDSUM(checksum,complement, > sum) \end{verbatim} Time and Date Utility Subroutines: page~\pageref{FTGSDT} \begin{verbatim} FTGSDT( > day, month, year, status ) FTGSTM(> datestr, timeref, status) FTDT2S( year, month, day, > datestr, status) FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) FTS2DT(datestr, > year, month, day, status) FTS2TM(datestr, > year, month, day, hour, minute, second, status) \end{verbatim} General Utility Subroutines: page~\pageref{FTGHAD} \begin{verbatim} FTGHAD(unit, > curaddr,nextaddr) FTUPCH(string) FTCMPS(str_template,string,casesen, > match,exact) FTTKEY(keyword, > status) FTTREC(card, > status) FTNCHK(unit, > status) FTGKNM(unit, > keyword, keylength, status) FTMKKY(keyword, value,comment, > card, status) FTPSVC(card, > value,comment,status) FTKEYN(keyroot,seq_no, > keyword,status) FTNKEY(seq_no,keyroot, > keyword,status) FTDTYP(value, > dtype,status) class = FTGKCL(card) FTASFM(tform, > datacode,width,decimals,status) FTBNFM(tform, > datacode,repeat,width,status) FTGABC(tfields,tform,space, > rowlen,tbcol,status) FTGTHD(template, > card,hdtype,status) FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) \end{verbatim} \chapter{ Parameter Definitions } \begin{verbatim} anyf - (logical) set to TRUE if any of the returned data values are undefined array - (any datatype except character) array of bytes to be read or written. bitpix - (integer) bits per pixel: 8, 16, 32, -32, or -64 blank - (integer) value used for undefined pixels in integer primary array blank - (integer*8) value used for undefined pixels in integer primary array blocksize - (integer) 2880-byte logical record blocking factor (if 0 < blocksize < 11) or the actual block size in bytes (if 10 < blocksize < 28800). As of version 3.3 of FITSIO, blocksizes greater than 2880 are no longer supported. bscale - (double precision) scaling factor for the primary array bytlen - (integer) length of the data unit, in bytes bzero - (double precision) zero point for primary array scaling card - (character*80) header record to be read or written casesen - (logical) will string matching be case sensitive? checksum - (character*16) encoded checksum string colname - (character) ASCII name of the column colnum - (integer) number of the column (first column = 1) coltemplate - (character) template string to be matched to column names comment - (character) the keyword comment field comments - (character array) keyword comment fields compid - (integer) the type of computer that the program is running on complement - (logical) should the checksum be complemented? coordtype - (character) type of coordinate projection (-SIN, -TAN, -ARC, -NCP, -GLS, -MER, or -AIT) cube - 3D data cube of the appropriate datatype curaddr - (integer) starting address (in bytes) of the CHDU current - (integer) if not equal to 0, copy the current HDU datacode - (integer) symbolic code of the binary table column datatype dataok - (integer) was the data unit verification successful (=1) or not (= -1). Equals zero if the DATASUM keyword is not present. datasum - (double precision) 32-bit 1's complement checksum for the data unit datatype - (character) datatype (format) of the binary table column datestr - (string) FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', or 'dd/mm/yy' day - (integer) current day of the month dblval - (double precision) fractional part of the keyword value decimals - (integer) number of decimal places to be displayed dim1 - (integer) actual size of the first dimension of the image or cube array dim2 - (integer) actual size of the second dimension of the cube array dispwidth - (integer) - the display width (length of string) for a column dtype - (character) datatype of the keyword ('C', 'L', 'I', or 'F') C = character string L = logical I = integer F = floating point number errmsg - (character*80) oldest error message on the internal stack errtext - (character*30) descriptive error message corresponding to error number casesen - (logical) true if column name matching is case sensitive exact - (logical) do the strings match exactly, or were wildcards used? exclist (character array) list of names to be excluded from search exists - flag indicating whether the file or compressed file exists on disk extend - (logical) true if there may be extensions following the primary data extname - (character) value of the EXTNAME keyword (if not blank) fbit - (integer) first bit in the field to be read or written felem - (integer) first pixel of the element vector (ignored for ASCII tables) filename - (character) name of the FITS file flagvals - (logical array) True if corresponding data element is undefined following - (integer) if not equal to 0, copy all following HDUs in the input file fparm - (integer) sequence number of the first group parameter to read or write fpixel - (integer) the first pixel position fpixels - (integer array) the first included pixel in each dimension frow - (integer) beginning row number (first row of table = 1) frowll - (integer*8) beginning row number (first row of table = 1) gcount - (integer) value of the GCOUNT keyword (usually = 1) group - (integer) sequence number of the data group (=0 for non-grouped data) hdtype - (integer) header record type: -1=delete; 0=append or replace; 1=append; 2=this is the END keyword hduok - (integer) was the HDU verification successful (=1) or not (= -1). Equals zero if the CHECKSUM keyword is not present. hdusum - (double precision) 32 bit 1's complement checksum for the entire CHDU hdutype - (integer) type of HDU: 0 = primary array or IMAGE, 1 = ASCII table, 2 = binary table, -1 = any HDU type or unknown type history - (character) the HISTORY keyword comment string hour - (integer) hour from 0 - 23 image - 2D image of the appropriate datatype inclist (character array) list of names to be included in search incs - (integer array) sampling interval for pixels in each FITS dimension intval - (integer) integer part of the keyword value iounit - (integer) value of an unused I/O unit number iunit - (integer) logical unit number associated with the input FITS file, 1-300 key_no - (integer) sequence number (starting with 1) of the keyword record keylength - (integer) length of the keyword name keyroot - (character) root string for the keyword name keysadd -(integer) number of new keyword records which can fit in the CHU keysexist - (integer) number of existing keyword records in the CHU keyval - value of the keyword in the appropriate datatype keyvals - (array) value of the keywords in the appropriate datatype keyword - (character*8) name of a keyword lray - (logical array) array of logical values corresponding to the bit array lpixels - (integer array) the last included pixel in each dimension match - (logical) do the 2 strings match? maxdim - (integer) dimensioned size of the NAXES, TTYPE, TFORM or TUNIT arrays max_keys - (integer) maximum number of keywords to search for minute - (integer) minute of an hour (0 - 59) month - (integer) current month of the year (1 - 12) morekeys - (integer) will leave space in the header for this many more keywords naxes - (integer array) size of each dimension in the FITS array naxesll - (integer*8 array) size of each dimension in the FITS array naxis - (integer) number of dimensions in the FITS array naxis1 - (integer) length of the X/first axis of the FITS array naxis2 - (integer) length of the Y/second axis of the FITS array naxis3 - (integer) length of the Z/third axis of the FITS array nbit - (integer) number of bits in the field to read or write nchars - (integer) number of characters to read and return ncols - (integer) number of columns nelements - (integer) number of data elements to read or write nelementsll - (integer*8) number of data elements to read or write nexc (integer) number of names in the exclusion list (may = 0) nhdu - (integer) absolute number of the HDU (1st HDU = 1) ninc (integer) number of names in the inclusion list nmove - (integer) number of HDUs to move (+ or -), relative to current position nfound - (integer) number of keywords found (highest keyword number) no_keys - (integer) number of keywords to write in the sequence nparm - (integer) number of group parameters to read or write nrows - (integer) number of rows in the table nrowsll - (integer*8) number of rows in the table nullval - value to represent undefined pixels, of the appropriate datatype nextaddr - (integer) starting address (in bytes) of the HDU following the CHDU offset - (integer) byte offset in the heap to the first element of the array offsetll - (integer*8) byte offset in the heap to the first element of the array oldkey - (character) old name of keyword to be modified ounit - (integer) logical unit number associated with the output FITS file 1-300 pcount - (integer) value of the PCOUNT keyword (usually = 0) previous - (integer) if not equal to 0, copy all previous HDUs in the input file repeat - (integer) length of element vector (e.g. 12J); ignored for ASCII table rot - (double precision) celestial coordinate rotation angle (degrees) rowlen - (integer) length of a table row, in characters or bytes rowlenll - (integer*8) length of a table row, in characters or bytes rowlist - (integer array) list of row numbers to be deleted in increasing order rownum - (integer) number of the row (first row = 1) rowrange- (string) list of rows or row ranges to be deleted rwmode - (integer) file access mode: 0 = readonly, 1 = readwrite second (double)- second within minute (0 - 60.9999999999) (leap second!) seq_no - (integer) the sequence number to append to the keyword root name simple - (logical) does the FITS file conform to all the FITS standards snull - (character) value used to represent undefined values in ASCII table space - (integer) number of blank spaces to leave between ASCII table columns startchar - (integer) first character in the row to be read startno - (integer) value of the first keyword sequence number (usually 1) status - (integer) returned error status code (0 = OK) str_template (character) template string to be matched to reference string stream - (character) output stream for the report: either 'STDOUT' or 'STDERR' string - (character) character string sum - (double precision) 32 bit unsigned checksum value tbcol - (integer array) column number of the first character in the field(s) tdisp - (character) Fortran type display format for the table column template-(character) template string for a FITS header record tfields - (integer) number of fields (columns) in the table tform - (character array) format of the column(s); allowed values are: For ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd For binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count Note that the 'rAw' form is non-standard extension to the TFORM keyword syntax that is not specifically defined in the Binary Tables definition document. theap - (integer) zero indexed byte offset of starting address of the heap relative to the beginning of the binary table data tnull - (integer) value used to represent undefined values in binary table tnullll - (integer*8) value used to represent undefined values in binary table ttype - (character array) label for table column(s) tscal - (double precision) scaling factor for table column tunit - (character array) physical unit for table column(s) tzero - (double precision) scaling zero point for table column unit - (integer) logical unit number associated with the FITS file (1-300) units - (character) the keyword units string (e.g., 'km/s') value - (character) the keyword value string values - array of data values of the appropriate datatype varidat - (integer) size in bytes of the 'variable length data area' following the binary table data (usually = 0) version - (real) current revision number of the library width - (integer) width of the character string field xcol - (integer) number of the column containing the X coordinate values xinc - (double precision) X axis coordinate increment at reference pixel (deg) xpix - (double precision) X axis pixel location xpos - (double precision) X axis celestial coordinate (usually RA) (deg) xrpix - (double precision) X axis reference pixel array location xrval - (double precision) X axis coordinate value at the reference pixel (deg) ycol - (integer) number of the column containing the X coordinate values year - (integer) last 2 digits of the year (00 - 99) yinc - (double precision) Y axis coordinate increment at reference pixel (deg) ypix - (double precision) y axis pixel location ypos - (double precision) y axis celestial coordinate (usually DEC) (deg) yrpix - (double precision) Y axis reference pixel array location yrval - (double precision) Y axis coordinate value at the reference pixel (deg) \end{verbatim} \chapter{ FITSIO Error Status Codes } \begin{verbatim} Status codes in the range -99 to -999 and 1 to 999 are reserved for future FITSIO use. 0 OK, no error 101 input and output files are the same 103 too many FITS files open at once; all internal buffers full 104 error opening existing file 105 error creating new FITS file; (does a file with this name already exist?) 106 error writing record to FITS file 107 end-of-file encountered while reading record from FITS file 108 error reading record from file 110 error closing FITS file 111 internal array dimensions exceeded 112 Cannot modify file with readonly access 113 Could not allocate memory 114 illegal logical unit number; must be between 1 - 300, inclusive 115 NULL input pointer to routine 116 error seeking position in file 121 invalid URL prefix on file name 122 tried to register too many IO drivers 123 driver initialization failed 124 matching driver is not registered 125 failed to parse input file URL 126 parse error in range list 151 bad argument in shared memory driver 152 null pointer passed as an argument 153 no more free shared memory handles 154 shared memory driver is not initialized 155 IPC error returned by a system call 156 no memory in shared memory driver 157 resource deadlock would occur 158 attempt to open/create lock file failed 159 shared memory block cannot be resized at the moment 201 header not empty; can't write required keywords 202 specified keyword name was not found in the header 203 specified header record number is out of bounds 204 keyword value field is blank 205 keyword value string is missing the closing quote character 206 illegal indexed keyword name (e.g. 'TFORM1000') 207 illegal character in keyword name or header record 208 keyword does not have expected name. Keyword out of sequence? 209 keyword does not have expected integer value 210 could not find the required END header keyword 211 illegal BITPIX keyword value 212 illegal NAXIS keyword value 213 illegal NAXISn keyword value: must be 0 or positive integer 214 illegal PCOUNT keyword value 215 illegal GCOUNT keyword value 216 illegal TFIELDS keyword value 217 negative ASCII or binary table width value (NAXIS1) 218 negative number of rows in ASCII or binary table (NAXIS2) 219 column name (TTYPE keyword) not found 220 illegal SIMPLE keyword value 221 could not find the required SIMPLE header keyword 222 could not find the required BITPIX header keyword 223 could not find the required NAXIS header keyword 224 could not find all the required NAXISn keywords in the header 225 could not find the required XTENSION header keyword 226 the CHDU is not an ASCII table extension 227 the CHDU is not a binary table extension 228 could not find the required PCOUNT header keyword 229 could not find the required GCOUNT header keyword 230 could not find the required TFIELDS header keyword 231 could not find all the required TBCOLn keywords in the header 232 could not find all the required TFORMn keywords in the header 233 the CHDU is not an IMAGE extension 234 illegal TBCOL keyword value; out of range 235 this operation only allowed for ASCII or BINARY table extension 236 column is too wide to fit within the specified width of the ASCII table 237 the specified column name template matched more than one column name 241 binary table row width is not equal to the sum of the field widths 251 unrecognizable type of FITS extension 252 unrecognizable FITS record 253 END keyword contains non-blank characters in columns 9-80 254 Header fill area contains non-blank characters 255 Data fill area contains non-blank on non-zero values 261 unable to parse the TFORM keyword value string 262 unrecognizable TFORM datatype code 263 illegal TDIMn keyword value 301 illegal HDU number; less than 1 or greater than internal buffer size 302 column number out of range (1 - 999) 304 attempt to move to negative file record number 306 attempted to read or write a negative number of bytes in the FITS file 307 illegal starting row number for table read or write operation 308 illegal starting element number for table read or write operation 309 attempted to read or write character string in non-character table column 310 attempted to read or write logical value in non-logical table column 311 illegal ASCII table TFORM format code for attempted operation 312 illegal binary table TFORM format code for attempted operation 314 value for undefined pixels has not been defined 317 attempted to read or write descriptor in a non-descriptor field 320 number of array dimensions out of range 321 first pixel number is greater than the last pixel number 322 attempt to set BSCALE or TSCALn scaling parameter = 0 323 illegal axis length less than 1 340 NOT_GROUP_TABLE 340 Grouping function error 341 HDU_ALREADY_MEMBER 342 MEMBER_NOT_FOUND 343 GROUP_NOT_FOUND 344 BAD_GROUP_ID 345 TOO_MANY_HDUS_TRACKED 346 HDU_ALREADY_TRACKED 347 BAD_OPTION 348 IDENTICAL_POINTERS 349 BAD_GROUP_ATTACH 350 BAD_GROUP_DETACH 360 NGP_NO_MEMORY malloc failed 361 NGP_READ_ERR read error from file 362 NGP_NUL_PTR null pointer passed as an argument. Passing null pointer as a name of template file raises this error 363 NGP_EMPTY_CURLINE line read seems to be empty (used internally) 364 NGP_UNREAD_QUEUE_FULL cannot unread more then 1 line (or single line twice) 365 NGP_INC_NESTING too deep include file nesting (infinite loop, template includes itself ?) 366 NGP_ERR_FOPEN fopen() failed, cannot open template file 367 NGP_EOF end of file encountered and not expected 368 NGP_BAD_ARG bad arguments passed. Usually means internal parser error. Should not happen 369 NGP_TOKEN_NOT_EXPECT token not expected here 401 error attempting to convert an integer to a formatted character string 402 error attempting to convert a real value to a formatted character string 403 cannot convert a quoted string keyword to an integer 404 attempted to read a non-logical keyword value as a logical value 405 cannot convert a quoted string keyword to a real value 406 cannot convert a quoted string keyword to a double precision value 407 error attempting to read character string as an integer 408 error attempting to read character string as a real value 409 error attempting to read character string as a double precision value 410 bad keyword datatype code 411 illegal number of decimal places while formatting floating point value 412 numerical overflow during implicit datatype conversion 413 error compressing image 414 error uncompressing image 420 error in date or time conversion 431 syntax error in parser expression 432 expression did not evaluate to desired type 433 vector result too large to return in array 434 data parser failed not sent an out column 435 bad data encounter while parsing column 436 parse error: output file not of proper type 501 celestial angle too large for projection 502 bad celestial coordinate or pixel value 503 error in celestial coordinate calculation 504 unsupported type of celestial projection 505 required celestial coordinate keywords not found 506 approximate wcs keyword values were returned \end{verbatim} \end{document} cfitsio-4.3.1/docs/fitsio.doc0000644000225700000360000117537513472024437015412 0ustar cagordonlhea FITSIO - An Interface to FITS Format Files for Fortran Programmers William D Pence, HEASARC, NASA/GSFC Version 3.0 [Note: This file contains various formatting command symbols in the first column which are used when generating the LATeX version of this document.] *I. Introduction This document describes the Fortran-callable subroutine interface that is provided as part of the CFITSIO library (which is written in ANSI C). This is a companion document to the CFITSIO User's Guide which should be consulted for further information about the underlying CFITSIO library. In the remainder of this document, the terms FITSIO and CFITSIO are interchangeable and refer to the same library. FITSIO/CFITSIO is a machine-independent library of routines for reading and writing data files in the FITS (Flexible Image Transport System) data format. It can also read IRAF format image files and raw binary data arrays by converting them on the fly into a virtual FITS format file. This library was written to provide a powerful yet simple interface for accessing FITS files which will run on most commonly used computers and workstations. FITSIO supports all the features described in the official definition of the FITS format and can read and write all the currently defined types of extensions, including ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The FITSIO subroutines insulate the programmer from having to deal with the complicated formatting details in the FITS file, however, it is assumed that users have a general knowledge about the structure and usage of FITS files. The CFITSIO package was initially developed by the HEASARC (High Energy Astrophysics Science Archive Research Center) at the NASA Goddard Space Flight Center to convert various existing and newly acquired astronomical data sets into FITS format and to further analyze data already in FITS format. New features continue to be added to CFITSIO in large part due to contributions of ideas or actual code from users of the package. The Integral Science Data Center in Switzerland, and the XMM/ESTEC project in The Netherlands made especially significant contributions that resulted in many of the new features that appeared in v2.0 of CFITSIO. The latest version of the CFITSIO source code, documentation, and example programs are available on the World-Wide Web or via anonymous ftp from: - http://heasarc.gsfc.nasa.gov/fitsio ftp://legacy.gsfc.nasa.gov/software/fitsio/c - \newpage Any questions, bug reports, or suggested enhancements related to the CFITSIO package should be sent to the FTOOLS Help Desk at the HEASARC: - http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp - This User's Guide assumes that readers already have a general understanding of the definition and structure of FITS format files. Further information about FITS formats is available from the FITS Support Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the 'FITS Standard' gives the authoritative definition of the FITS data format. Other documents available at that Web site provide additional historical background and practical advice on using FITS files. The HEASARC also provides a very sophisticated FITS file analysis program called `Fv' which can be used to display and edit the contents of any FITS file as well as construct new FITS files from scratch. Fv is freely available for most Unix platforms, Mac PCs, and Windows PCs. CFITSIO users may also be interested in the FTOOLS package of programs that can be used to manipulate and analyze FITS format files. Fv and FTOOLS are available from their respective Web sites at: - http://fv.gsfc.nasa.gov http://heasarc.gsfc.nasa.gov/ftools - *II. Creating FITSIO/CFITSIO **A. Building the Library To use the FITSIO subroutines one must first build the CFITSIO library, which requires a C compiler. gcc is ideal, or most other ANSI-C compilers will also work. The CFITSIO code is contained in about 40 C source files (*.c) and header files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. The Fortran interface subroutines to the C CFITSIO routines are located in the f77\_wrap1.c, through f77\_wrap4.c files. These are relatively simple 'wrappers' that translate the arguments in the Fortran subroutine into the appropriate format for the corresponding C routine. This translation is performed transparently to the user by a set of C macros located in the cfortran.h file. Unfortunately cfortran.h does not support every combination of C and Fortran compilers so the Fortran interface is not supported on all platforms. (see further notes below). A standard combination of C and Fortran compilers will be assumed by default, but one may also specify a particular Fortran compiler by doing: - > setenv CFLAGS -DcompilerName=1 - (where 'compilerName' is the name of the compiler) before running the configure command. The currently recognized compiler names are: - g77Fortran IBMR2Fortran CLIPPERFortran pgiFortran NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran CRAYFortran mipsFortran DECFortran vmsFortran CONVEXFortran PowerStationFortran AbsoftUNIXFortran AbsoftProFortran SXFortran - Alternatively, one may edit the CFLAGS line in the Makefile to add the '-DcompilerName' flag after running the './configure' command. The CFITSIO library is built on Unix systems by typing: - > ./configure [--prefix=/target/installation/path] [--enable-sse2] [--enable-ssse3] > make (or 'make shared') > make install (this step is optional) - at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, - > ./configure --prefix=/usr1/local - will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). The optional --enable-sse2 and --enable-ssse3 flags will cause configure to attempt to build CFITSIO using faster byte-swapping algorithms. See the "Optimizing Programs" section of this manual for more information about these options. By default, the Makefile will be configured to build the set of Fortran-callable wrapper routines whose calling sequences are described later in this document. The 'make shared' option builds a shared or dynamic version of the CFITSIO library. When using the shared library the executable code is not copied into your program at link time and instead the program locates the necessary library code at run time, normally through LD\_LIBRARY\_PATH or some other method. The advantages of using a shared library are: - 1. Less disk space if you build more than 1 program 2. Less memory if more than one copy of a program using the shared library is running at the same time since the system is smart enough to share copies of the shared library at run time. 3. Possibly easier maintenance since a new version of the shared library can be installed without relinking all the software that uses it (as long as the subroutine names and calling sequences remain unchanged). 4. No run-time penalty. - The disadvantages are: - 1. More hassle at runtime. You have to either build the programs specially or have LD_LIBRARY_PATH set right. 2. There may be a slight start up penalty, depending on where you are reading the shared library and the program from and if your CPU is either really slow or really heavily loaded. - On HP/UX systems, the environment variable CFLAGS should be set to -Ae before running configure to enable "extended ANSI" features. It may not be possible to statically link programs that use CFITSIO on some platforms (namely, on Solaris 2.6) due to the network drivers (which provide FTP and HTTP access to FITS files). It is possible to make both a dynamic and a static version of the CFITSIO library, but network file access will not be possible using the static version. On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may be executed to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. Note that the getcwd function that is used in the group.c module may require that programs using CFITSIO be linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example link line in the next section of this document. On Windows IBM-PC type platforms the situation is more complicated because of the wide variety of Fortran compilers that are available and because of the inherent complexities of calling the CFITSIO C routines from Fortran. Two different versions of the CFITSIO dll library are available, compiled with the Borland C++ compiler and the Microsoft Visual C++ compiler, respectively, in the files cfitsiodll\_2xxx\_borland.zip and cfitsiodll\_3xxx\_vcc.zip, where '3xxx' represents the current release number. Both these dll libraries contain a set of Fortran wrapper routines which may be compatible with some, but probably not all, available Fortran compilers. To test if they are compatible, compile the program testf77.f and try linking to these dll libraries. If these libraries do not work with a particular Fortran compiler, then it may be necessary to modify the file "cfortran.h" to support that particular combination of C and Fortran compilers, and then rebuild the CFITSIO dll library. This will require, however, some expertise in mixed language programming. CFITSIO should be compatible with most current ANCI C and C++ compilers: Cray supercomputers are currently not supported. **B. Testing the Library The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems type: - % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std - On VMS systems, (assuming cc is the name of the C compiler command), type: - $ cc testprog.c $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib $ run testprog - The testprog program should produce a FITS file called `testprog.fit' that is identical to the `testprog.std' FITS file included with this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. (There may be some minor formatting differences, such as the presence or absence of leading zeros, or 3 digit exponents in numbers, which can be ignored). The Fortran wrappers in CFITSIO may be tested with the testf77 program. On Unix systems the fortran compilation and link command may be called 'f77' or 'g77', depending on the system. - % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket or % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) or % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) or % g77 -o testf77 -s testf77.f -lcfitsio -lcc_dynamic -lncurses (Mac OS-X) % testf77 > testf77.lis % diff testf77.lis testf77.out % cmp testf77.fit testf77.std - On machines running SUN O/S, Fortran programs must be compiled with the '-f' option to force double precision variables to be aligned on 8-byte boundaries to make the fortran-declared variables compatible with C. A similar compiler option may be required on other platforms. Failing to use this option may cause the program to crash on FITSIO routines that read or write double precision variables. On Windows platforms, linking Fortran programs with a C library often depends on the particular compilers involved. Some users have found the following commands work when using the Intel Fortran compiler: - ifort /libs.dll cfitsio.lib /MD testf77.f /Gm or possibly, ifort /libs:dll cfitsio.lib /MD /fpp /extfpp:cfortran.h,fitsio.h /iface:cvf testf77.f - Also note that on some systems the output listing of the testf77 program may differ slightly from the testf77.std template if leading zeros are not printed by default before the decimal point when using F format. A few other utility programs are included with CFITSIO: - speed - measures the maximum throughput (in MB per second) for writing and reading FITS files with CFITSIO listhead - lists all the header keywords in any FITS file fitscopy - copies any FITS file (especially useful in conjunction with the CFITSIO's extended input filename syntax) cookbook - a sample program that performs common read and write operations on a FITS file. iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine - The first 4 of these utility programs can be compiled and linked by typing - % make program_name - **C. Linking Programs with FITSIO When linking applications software with the FITSIO library, several system libraries usually need to be specified on the link command line. On Unix systems, the most reliable way to determine what libraries are required is to type 'make testprog' and see what libraries the configure script has added. The typical libraries that may need to be added are -lm (the math library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). These latter 2 libraries are not needed on VMS and Windows platforms, because FTP file access is not currently supported on those platforms. Note that when upgrading to a newer version of CFITSIO it is usually necessary to recompile, as well as relink, the programs that use CFITSIO, because the definitions in fitsio.h often change. **D. Getting Started with FITSIO In order to effectively use the FITSIO library as quickly as possible, it is recommended that new users follow these steps: 1. Read the following `FITS Primer' chapter for a brief overview of the structure of FITS files. This is especially important for users who have not previously dealt with the FITS table and image extensions. 2. Write a simple program to read or write a FITS file using the Basic Interface routines. 3. Refer to the cookbook.f program that is included with this release for examples of routines that perform various common FITS file operations. 4. Read Chapters 4 and 5 to become familiar with the conventions and advanced features of the FITSIO interface. 5. Scan through the more extensive set of routines that are provided in the `Advanced Interface'. These routines perform more specialized functions than are provided by the Basic Interface routines. **E. Example Program The following listing shows an example of how to use the FITSIO routines in a Fortran program. Refer to the cookbook.f program that is included with the FITSIO distribution for examples of other FITS programs. - program writeimage C Create a FITS primary array containing a 2-D image integer status,unit,blocksize,bitpix,naxis,naxes(2) integer i,j,group,fpixel,nelements,array(300,200) character filename*80 logical simple,extend status=0 C Name of the FITS file to be created: filename='ATESTFILE.FITS' C Get an unused Logical Unit Number to use to create the FITS file call ftgiou(unit,status) C create the new empty FITS file blocksize=1 call ftinit(unit,filename,blocksize,status) C initialize parameters about the FITS image (300 x 200 16-bit integers) simple=.true. bitpix=16 naxis=2 naxes(1)=300 naxes(2)=200 extend=.true. C write the required header keywords call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) C initialize the values in the image with a linear ramp function do j=1,naxes(2) do i=1,naxes(1) array(i,j)=i+j end do end do C write the array to the FITS file group=1 fpixel=1 nelements=naxes(1)*naxes(2) call ftpprj(unit,group,fpixel,nelements,array,status) C write another optional keyword to the header call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) C close the file and free the unit number call ftclos(unit, status) call ftfiou(unit, status) end - **F. Legal Stuff Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." **G. Acknowledgments The development of many of the powerful features in CFITSIO was made possible through collaborations with many people or organizations from around the world. The following, in particular, have made especially significant contributions: Programmers from the Integral Science Data Center, Switzerland (namely, Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The use of `drivers' greatly simplified the low-level I/O, which in turn made other new features in CFITSIO (e.g., support for compressed FITS files and support for IRAF format image files) much easier to implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce O'Neel wrote the drivers for accessing FITS files over the network using the FTP, HTTP, and ROOT protocols. The ISDC also provided the template parsing routines (written by Jurek Borkowski) and the hierarchical grouping routines (written by Don Jennings). The ISDC DAL (Data Access Layer) routines are layered on top of CFITSIO and make extensive use of these features. Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the high-performance lexical parsing algorithm that is used to do on-the-fly filtering of FITS tables. This algorithm essentially pre-compiles the user-supplied selection expression into a form that can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) then wrote the parsing routines used by CFITSIO based on Lammers' design, combined with other techniques such as the CFITSIO iterator routine to further enhance the data processing throughput. This effort also benefited from a much earlier lexical parsing routine that was developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt (NASA/GSFC) implemented additional functions (median, average, stddev) and other enhancements to the lexical parser. The CFITSIO iterator function is loosely based on similar ideas developed for the XMM Data Access Layer. Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of Fortran-callable wrappers for all the CFITSIO routines, which in turn rely on the CFORTRAN macro developed by Burkhard Burow. The syntax used by CFITSIO for filtering or binning input FITS files is based on ideas developed for the AXAF Science Center Data Model by Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for further description of the AXAF Data Model. The file decompression code were taken directly from the gzip (GNU zip) program developed by Jean-loup Gailly and others. Doug Mink, SAO, provided the routines for converting IRAF format images into FITS format. Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to cfortran.h that are necessary to support 64-bit integer values when calling C routines from fortran programs. The cfortran.h macros were originally developed by Burkhard Burow (CERN). Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. In addition, many other people have made valuable contributions to the development of CFITSIO. These include (with apologies to others that may have inadvertently been omitted): Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. *III. A FITS Primer This section gives a brief overview of the structure of FITS files. Users should refer to the documentation available from the FITS Support Office, as described in the introduction, for more detailed information on FITS formats. FITS was first developed in the late 1970's as a standard data interchange format between various astronomical observatories. Since then FITS has become the defacto standard data format supported by most astronomical data analysis software packages. A FITS file consists of one or more Header + Data Units (HDUs), where the first HDU is called the `Primary HDU', or `Primary Array'. The primary array contains an N-dimensional array of pixels, such as a 1-D spectrum, a 2-D image, or a 3-D data cube. Six different primary datatypes are supported: Unsigned 8-bit bytes, 16, 32, and 64-bit signed integers, and 32 and 64-bit floating point reals. FITS also has a convention for storing unsigned integers (see the later section entitled `Unsigned Integers' for more details). The primary HDU may also consist of only a header with a null array containing no data pixels. Any number of additional HDUs may follow the primary array; these additional HDUs are called FITS `extensions'. There are currently 3 types of extensions defined by the FITS standard: \begin{itemize} \item Image Extension - a N-dimensional array of pixels, like in a primary array \item ASCII Table Extension - rows and columns of data in ASCII character format \item Binary Table Extension - rows and columns of data in binary representation \end{itemize} In each case the HDU consists of an ASCII Header Unit followed by an optional Data Unit. For historical reasons, each Header or Data unit must be an exact multiple of 2880 8-bit bytes long. Any unused space is padded with fill characters (ASCII blanks or zeros). Each Header Unit consists of any number of 80-character keyword records or `card images' which have the general form: - KEYNAME = value / comment string NULLKEY = / comment: This keyword has no value - The keyword names may be up to 8 characters long and can only contain uppercase letters, the digits 0-9, the hyphen, and the underscore character. The keyword name is (usually) followed by an equals sign and a space character (= ) in columns 9 - 10 of the record, followed by the value of the keyword which may be either an integer, a floating point number, a character string (enclosed in single quotes), or a boolean value (the letter T or F). A keyword may also have a null or undefined value if there is no specified value string, as in the second example. The last keyword in the header is always the `END' keyword which has no value or comment fields. There are many rules governing the exact format of a keyword record (see the FITS Standard) so it is better to rely on standard interface software like FITSIO to correctly construct or to parse the keyword records rather than try to deal directly with the raw FITS formats. Each Header Unit begins with a series of required keywords which depend on the type of HDU. These required keywords specify the size and format of the following Data Unit. The header may contain other optional keywords to describe other aspects of the data, such as the units or scaling values. Other COMMENT or HISTORY keywords are also frequently added to further document the data file. The optional Data Unit immediately follows the last 2880-byte block in the Header Unit. Some HDUs do not have a Data Unit and only consist of the Header Unit. If there is more than one HDU in the FITS file, then the Header Unit of the next HDU immediately follows the last 2880-byte block of the previous Data Unit (or Header Unit if there is no Data Unit). The main required keywords in FITS primary arrays or image extensions are: \begin{itemize} \item BITPIX -- defines the datatype of the array: 8, 16, 32, 64, -32, -64 for unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, 64--bit signed integer, 32--bit IEEE floating point, and 64--bit IEEE double precision floating point, respectively. \item NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. \item NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. \end{itemize} FITS tables start with the keyword XTENSION = `TABLE' (for ASCII tables) or XTENSION = `BINTABLE' (for binary tables) and have the following main keywords: \begin{itemize} \item TFIELDS -- number of fields or columns in the table \item NAXIS2 -- number of rows in the table \item TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the name of the column \item TFORMn -- the datatype of the column \item TUNITn -- the physical units of the column (optional) \end{itemize} Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} for further information about the FITS format and related software packages. *V. FITSIO Conventions and Guidelines **A. CFITSIO Size Limitations CFITSIO places few restrictions on the size of FITS files that it reads or writes. There are a few limits, however, which may affect some extreme cases: 1. The maximum number of FITS files that may be simultaneously opened by CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default value is 1000, but this may be increased if necessary. Note that CFITSIO allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this amounts to more than 115K of memory for each opened file (or 115 MB for 1000 opened files). Note that the underlying operating system, may have a lower limit on the number of files that can be opened simultaneously. 2. By default, CFITSIO can handle FITS files up to 2.1 GB in size (2**31 bytes). This file size limit is often imposed by 32-bit operating systems. More recently, as 64-bit operating systems become more common, an industry-wide standard (at least on Unix systems) has been developed to support larger sized files (see http://ftp.sas.com/standards/large.file/). Starting with version 2.1 of CFITSIO, larger FITS files up to 6 terabytes in size may be read and written on supported platforms. In order to support these larger files, CFITSIO must be compiled with the '-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64' compiler flags. Some platforms may also require the `-D\_LARGE\_FILES' compiler flag. This causes the compiler to allocate 8-bytes instead of 4-bytes for the `off\_t' datatype which is used to store file offset positions. It appears that in most cases it is not necessary to also include these compiler flags when compiling programs that link to the CFITSIO library. If CFITSIO is compiled with the -D\_LARGEFILE\_SOURCE and -D\_FILE\_OFFSET\_BITS=64 flags on a platform that supports large files, then it can read and write FITS files that contain up to 2**31 2880-byte FITS records, or approximately 6 terabytes in size. It is still required that the value of the NAXISn and PCOUNT keywords in each extension be within the range of a signed 4-byte integer (max value = 2,147,483,648). Thus, each dimension of an image (given by the NAXISn keywords), the total width of a table (NAXIS1 keyword), the number of rows in a table (NAXIS2 keyword), and the total size of the variable-length array heap in binary tables (PCOUNT keyword) must be less than this limit. Currently, support for large files within CFITSIO has been tested on the Linux, Solaris, and IBM AIX operating systems. **B. Multiple Access to the Same FITS File CFITSIO supports simultaneous read and write access to multiple HDUs in the same FITS file. Thus, one can open the same FITS file twice within a single program and move to 2 different HDUs in the file, and then read and write data or keywords to the 2 extensions just as if one were accessing 2 completely separate FITS files. Since in general it is not possible to physically open the same file twice and then expect to be able to simultaneously (or in alternating succession) write to 2 different locations in the file, CFITSIO recognizes when the file to be opened (in the call to fits\_open\_file) has already been opened and instead of actually opening the file again, just logically links the new file to the old file. (This only applies if the file is opened more than once within the same program, and does not prevent the same file from being simultaneously opened by more than one program). Then before CFITSIO reads or writes to either (logical) file, it makes sure that any modifications made to the other file have been completely flushed from the internal buffers to the file. Thus, in principle, one could open a file twice, in one case pointing to the first extension and in the other pointing to the 2nd extension and then write data to both extensions, in any order, without danger of corrupting the file, There may be some efficiency penalties in doing this however, since CFITSIO has to flush all the internal buffers related to one file before switching to the other, so it would still be prudent to minimize the number of times one switches back and forth between doing I/O to different HDUs in the same file. **C. Current Header Data Unit (CHDU) In general, a FITS file can contain multiple Header Data Units, also called extensions. CFITSIO only operates within one HDU at any given time, and the currently selected HDU is called the Current Header Data Unit (CHDU). When a FITS file is first created or opened the CHDU is automatically defined to be the first HDU (i.e., the primary array). CFITSIO routines are provided to move to and open any other existing HDU within the FITS file or to append or insert a new HDU in the FITS file which then becomes the CHDU. **D. Subroutine Names All FITSIO subroutine names begin with the letters 'ft' to distinguish them from other subroutines and are 5 or 6 characters long. Users should not name their own subroutines beginning with 'ft' to avoid conflicts. (The SPP interface routines all begin with 'fs'). Subroutines which read or get information from the FITS file have names beginning with 'ftg...'. Subroutines which write or put information into the FITS file have names beginning with 'ftp...'. **E. Subroutine Families and Datatypes Many of the subroutines come in families which differ only in the datatype of the associated parameter(s) . The datatype of these subroutines is indicated by the last letter of the subroutine name (e.g., 'j' in 'ftpkyj') as follows: - x - bit b - character*1 (unsigned byte) i - short integer (I*2) j - integer (I*4, 32-bit integer) k - long long integer (I*8, 64-bit integer) e - real exponential floating point (R*4) f - real fixed-format floating point (R*4) d - double precision real floating-point (R*8) g - double precision fixed-format floating point (R*8) c - complex reals (pairs of R*4 values) m - double precision complex (pairs of R*8 values) l - logical (L*4) s - character string - When dealing with the FITS byte datatype, it is important to remember that the raw values (before any scaling by the BSCALE and BZERO, or TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte columns (TFORMn = 'B') are interpreted as unsigned bytes with values ranging from 0 to 255. Some Fortran compilers support a non-standard byte datatype such as INTEGER*1, LOGICAL*1, or BYTE, which can sometimes be used instead of CHARACTER*1 variables. Many machines permit passing a numeric datatype (such as INTEGER*1) to the FITSIO subroutines which are expecting a CHARACTER*1 datatype, but this technically violates the Fortran-77 standard and is not supported on all machines (e.g., on a VAX/VMS machine one must use the VAX-specific \%DESCR function). One feature of the CFITSIO routines is that they can operate on a `X' (bit) column in a binary table as though it were a `B' (byte) column. For example a `11X' datatype column can be interpreted the same as a `2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can be more efficient to read and write whole bytes at a time, rather than reading or writing each individual bit. The double precision complex datatype is not a standard Fortran-77 datatype. If a particular Fortran compiler does not directly support this datatype, then one may instead pass an array of pairs of double precision values to these subroutines. The first value in each pair is the real part, and the second is the imaginary part. **F. Implicit Data Type Conversion The FITSIO routines that read and write numerical data can perform implicit data type conversion. This means that the data type of the variable or array in the program does not need to be the same as the data type of the value in the FITS file. Data type conversion is supported for numerical and string data types (if the string contains a valid number enclosed in quotes) when reading a FITS header keyword value and for numeric values when reading or writing values in the primary array or a table column. CFITSIO returns status = NUM\_OVERFLOW if the converted data value exceeds the range of the output data type. Implicit data type conversion is not supported within binary tables for string, logical, complex, or double complex data types. In addition, any table column may be read as if it contained string values. In the case of numeric columns the returned string will be formatted using the TDISPn display format if it exists. **G. Data Scaling When reading numerical data values in the primary array or a table column, the values will be scaled automatically by the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they are present in the header. The scaled data that is returned to the reading program will have - output value = (FITS value) * BSCALE + BZERO - (a corresponding formula using TSCALn and TZEROn is used when reading from table columns). In the case of integer output values the floating point scaled value is truncated to an integer (not rounded to the nearest integer). The ftpscl and fttscl subroutines may be used to override the scaling parameters defined in the header (e.g., to turn off the scaling so that the program can read the raw unscaled values from the FITS file). When writing numerical data to the primary array or to a table column the data values will generally be automatically inversely scaled by the value of the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they they exist in the header. These keywords must have been written to the header before any data is written for them to have any effect. Otherwise, one may use the ftpscl and fttscl subroutines to define or override the scaling keywords in the header (e.g., to turn off the scaling so that the program can write the raw unscaled values into the FITS file). If scaling is performed, the inverse scaled output value that is written into the FITS file will have - FITS value = ((input value) - BZERO) / BSCALE - (a corresponding formula using TSCALn and TZEROn is used when writing to table columns). Rounding to the nearest integer, rather than truncation, is performed when writing integer datatypes to the FITS file. **H. Error Status Values and the Error Message Stack The last parameter in nearly every FITSIO subroutine is the error status value which is both an input and an output parameter. A returned positive value for this parameter indicates an error was detected. A listing of all the FITSIO status code values is given at the end of this document. The FITSIO library uses an `inherited status' convention for the status parameter which means that if a subroutine is called with a positive input value of the status parameter, then the subroutine will exit immediately without changing the value of the status parameter. Thus, if one passes the status value returned from each FITSIO routine as input to the next FITSIO subroutine, then whenever an error is detected all further FITSIO processing will cease. This convention can simplify the error checking in application programs because it is not necessary to check the value of the status parameter after every single FITSIO subroutine call. If a program contains a sequence of several FITSIO calls, one can just check the status value after the last call. Since the returned status values are generally distinctive, it should be possible to determine which subroutine originally returned the error status. FITSIO also maintains an internal stack of error messages (80-character maximum length) which in many cases provide a more detailed explanation of the cause of the error than is provided by the error status number alone. It is recommended that the error message stack be printed out whenever a program detects a FITSIO error. To do this, call the FTGMSG routine repeatedly to get the successive messages on the stack. When the stack is empty FTGMSG will return a blank string. Note that this is a `First In -- First Out' stack, so the oldest error message is returned first by ftgmsg. **I. Variable-Length Array Facility in Binary Tables FITSIO provides easy-to-use support for reading and writing data in variable length fields of a binary table. The variable length columns have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the datatype code (e.g., I, J, E, D, etc.) and `len' is an integer specifying the maximum length of the vector in the table. If the value of `len' is not specified when the table is created (e.g., if the TFORM keyword value is simply specified as '1PE' instead of '1PE(400) ), then FITSIO will automatically scan the table when it is closed to determine the maximum length of the vector and will append this value to the TFORMn value. The same routines which read and write data in an ordinary fixed length binary table extension are also used for variable length fields, however, the subroutine parameters take on a slightly different interpretation as described below. All the data in a variable length field is written into an area called the `heap' which follows the main fixed-length FITS binary table. The size of the heap, in bytes, is specified with the PCOUNT keyword in the FITS header. When creating a new binary table, the initial value of PCOUNT should usually be set to zero. FITSIO will recompute the size of the heap as the data is written and will automatically update the PCOUNT keyword value when the table is closed. When writing variable length data to a table, CFITSIO will automatically extend the size of the heap area if necessary, so that any following HDUs do not get overwritten. By default the heap data area starts immediately after the last row of the fixed-length table. This default starting location may be overridden by the THEAP keyword, but this is not recommended. If additional rows of data are added to the table, CFITSIO will automatically shift the the heap down to make room for the new rows, but it is obviously be more efficient to initially create the table with the necessary number of blank rows, so that the heap does not needed to be constantly moved. When writing to a variable length field, the entire array of values for a given row of the table must be written with a single call to FTPCLx. The total length of the array is calculated from (NELEM+FELEM-1). One cannot append more elements to an existing field at a later time; any attempt to do so will simply overwrite all the data which was previously written. Note also that the new data will be written to a new area of the heap and the heap space used by the previous write cannot be reclaimed. For this reason it is advised that each row of a variable length field only be written once. An exception to this general rule occurs when setting elements of an array as undefined. One must first write a dummy value into the array with FTPCLx, and then call FTPCLU to flag the desired elements as undefined. (Do not use the FTPCNx family of routines with variable length fields). Note that the rows of a table, whether fixed or variable length, do not have to be written consecutively and may be written in any order. When writing to a variable length ASCII character field (e.g., TFORM = '1PA') only a single character string written. FTPCLS writes the whole length of the input string (minus any trailing blank characters), thus the NELEM and FELEM parameters are ignored. If the input string is completely blank then FITSIO will write one blank character to the FITS file. Similarly, FTGCVS and FTGCFS read the entire string (truncated to the width of the character string argument in the subroutine call) and also ignore the NELEM and FELEM parameters. The FTPDES subroutine is useful in situations where multiple rows of a variable length column have the identical array of values. One can simply write the array once for the first row, and then use FTPDES to write the same descriptor values into the other rows (use the FTGDES routine to read the first descriptor value); all the rows will then point to the same storage location thus saving disk space. When reading from a variable length array field one can only read as many elements as actually exist in that row of the table; reading does not automatically continue with the next row of the table as occurs when reading an ordinary fixed length table field. Attempts to read more than this will cause an error status to be returned. One can determine the number of elements in each row of a variable column with the FTGDES subroutine. **I. Support for IEEE Special Values The ANSI/IEEE-754 floating-point number standard defines certain special values that are used to represent such quantities as Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. (See the Appendix in the FITS standard or the FITS User's Guide for a list of these values). The FITSIO subroutines that read floating point data in FITS files recognize these IEEE special values and by default interpret the overflow and infinity values as being equivalent to a NaN, and convert the underflow and denormalized values into zeros. In some cases programmers may want access to the raw IEEE values, without any modification by FITSIO. This can be done by calling the FTGPVx or FTGCVx routines while specifying 0.0 as the value of the NULLVAL parameter. This will force FITSIO to simply pass the IEEE values through to the application program, without any modification. This does not work for double precision values on VAX/VMS machines, however, where there is no easy way to bypass the default interpretation of the IEEE special values. This is also not supported when reading floating-point images that have been compressed with the FITS tiled image compression convention that is discussed in section 5.6; the pixels values in tile compressed images are represented by scaled integers, and a reserved integer value (not a NaN) is used to represent undefined pixels. **J. When the Final Size of the FITS HDU is Unknown It is not required to know the total size of a FITS data array or table before beginning to write the data to the FITS file. In the case of the primary array or an image extension, one should initially create the array with the size of the highest dimension (largest NAXISn keyword) set to a dummy value, such as 1. Then after all the data have been written and the true dimensions are known, then the NAXISn value should be updated using the fits\_ update\_key routine before moving to another extension or closing the FITS file. When writing to FITS tables, CFITSIO automatically keeps track of the highest row number that is written to, and will increase the size of the table if necessary. CFITSIO will also automatically insert space in the FITS file if necessary, to ensure that the data 'heap', if it exists, and/or any additional HDUs that follow the table do not get overwritten as new rows are written to the table. As a general rule it is best to specify the initial number of rows = 0 when the table is created, then let CFITSIO keep track of the number of rows that are actually written. The application program should not manually update the number of rows in the table (as given by the NAXIS2 keyword) since CFITSIO does this automatically. If a table is initially created with more than zero rows, then this will usually be considered as the minimum size of the table, even if fewer rows are actually written to the table. Thus, if a table is initially created with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before closing the table, then NAXIS2 will remain equal to 20. If however, 30 rows of data are written to this table, then NAXIS2 will be increased from 20 to 30. The one exception to this automatic updating of the NAXIS2 keyword is if the application program directly modifies the value of NAXIS2 (up or down) itself just before closing the table. In this case, CFITSIO does not update NAXIS2 again, since it assumes that the application program must have had a good reason for changing the value directly. This is not recommended, however, and is only provided for backward compatibility with software that initially creates a table with a large number of rows, than decreases the NAXIS2 value to the actual smaller value just before closing the table. **K. Local FITS Conventions supported by FITSIO CFITSIO supports several local FITS conventions which are not defined in the official FITS standard and which are not necessarily recognized or supported by other FITS software packages. Programmers should be cautious about using these features, especially if the FITS files that are produced are expected to be processed by other software systems which do not use the CFITSIO interface. ***1. Support for Long String Keyword Values. The length of a standard FITS string keyword is limited to 68 characters because it must fit entirely within a single FITS header keyword record. In some instances it is necessary to encode strings longer than this limit, so FITSIO supports a local convention in which the string value is continued over multiple keywords. This continuation convention uses an ampersand character at the end of each substring to indicate that it is continued on the next keyword, and the continuation keywords all have the name CONTINUE without an equal sign in column 9. The string value may be continued in this way over as many additional CONTINUE keywords as is required. The following lines illustrate this continuation convention which is used in the value of the STRKEY keyword: - LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. STRKEY = 'This is a very long string keyword&' / Optional Comment CONTINUE ' value that is continued over 3 keywords in the & ' CONTINUE 'FITS header.' / This is another optional comment. - It is recommended that the LONGSTRN keyword, as shown here, always be included in any HDU that uses this longstring convention. A subroutine called FTPLSW has been provided in CFITSIO to write this keyword if it does not already exist. This long string convention is supported by the following FITSIO subroutines that deal with string-valued keywords: - ftgkys - read a string keyword ftpkls - write (append) a string keyword ftikls - insert a string keyword ftmkls - modify the value of an existing string keyword ftukls - update an existing keyword, or write a new keyword ftdkey - delete a keyword - These routines will transparently read, write, or delete a long string value in the FITS file, so programmers in general do not have to be concerned about the details of the convention that is used to encode the long string in the FITS header. When reading a long string, one must ensure that the character string parameter used in these subroutine calls has been declared long enough to hold the entire string, otherwise the returned string value will be truncated. Note that the more commonly used FITSIO subroutine to write string valued keywords (FTPKYS) does NOT support this long string convention and only supports strings up to 68 characters in length. This has been done deliberately to prevent programs from inadvertently writing keywords using this non-standard convention without the explicit intent of the programmer or user. The FTPKLS subroutine must be called instead to write long strings. This routine can also be used to write ordinary string values less than 68 characters in length. ***2. Arrays of Fixed-Length Strings in Binary Tables CFITSIO supports 2 ways to specify that a character column in a binary table contains an array of fixed-length strings. The first way, which is officially supported by the FITS Standard document, uses the TDIMn keyword. For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that column will be interpreted as containing an array of 5 strings, each 12 characters long. FITSIO also supports a local convention for the format of the TFORMn keyword value of the form 'rAw' where 'r' is an integer specifying the total width in characters of the column, and 'w' is an integer specifying the (fixed) length of an individual unit string within the vector. For example, TFORM1 = '120A10' would indicate that the binary table column is 120 characters wide and consists of 12 10-character length strings. This convention is recognized by the FITSIO subroutines that read or write strings in binary tables. The Binary Table definition document specifies that other optional characters may follow the datatype code in the TFORM keyword, so this local convention is in compliance with the FITS standard, although other FITS readers are not required to recognize this convention. ***3. Keyword Units Strings One deficiency of the current FITS Standard is that it does not define a specific convention for recording the physical units of a keyword value. The TUNITn keyword can be used to specify the physical units of the values in a table column, but there is no analogous convention for keyword values. The comment field of the keyword is often used for this purpose, but the units are usually not specified in a well defined format that FITS readers can easily recognize and extract. To solve this deficiency, FITSIO uses a local convention in which the keyword units are enclosed in square brackets as the first token in the keyword comment field; more specifically, the opening square bracket immediately follows the slash '/' comment field delimiter and a single space character. The following examples illustrate keywords that use this convention: - EXPOSURE= 1800.0 / [s] elapsed exposure time V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity LAMBDA = 5400. / [angstrom] central wavelength FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux - In general, the units named in the IAU(1988) Style Guide are recommended, with the main exception that the preferred unit for angle is 'deg' for degrees. The FTPUNT and FTGUNT subroutines in FITSIO write and read, respectively, the keyword unit strings in an existing keyword. ***4. HIERARCH Convention for Extended Keyword Names CFITSIO supports the HIERARCH keyword convention which allows keyword names that are longer then 8 characters and may contain the full range of printable ASCII text characters. This convention was developed at the European Southern Observatory (ESO) to support hierarchical FITS keyword such as: - HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position - Basically, this convention uses the FITS keyword 'HIERARCH' to indicate that this convention is being used, then the actual keyword name ({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can contain any printable ASCII text characters, including spaces. The equals sign marks the end of the keyword name and is followed by the usual value and comment fields just as in standard FITS keywords. Further details of this convention are described at http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html and in Section 4.4 of the ESO Data Interface Control Document that is linked to from http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. This convention allows a much broader range of keyword names than is allowed by the FITS Standard. Here are more examples of such keywords: - HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character HIERARCH Earth is a star = F / Keyword contains embedded spaces - CFITSIO will transparently read and write these keywords, so application programs do not in general need to know anything about the specific implementation details of the HIERARCH convention. In particular, application programs do not need to specify the `HIERARCH' part of the keyword name when reading or writing keywords (although it may be included if desired). When writing a keyword, CFITSIO first checks to see if the keyword name is legal as a standard FITS keyword (no more than 8 characters long and containing only letters, digits, or a minus sign or underscore). If so it writes it as a standard FITS keyword, otherwise it uses the hierarch convention to write the keyword. The maximum keyword name length is 67 characters, which leaves only 1 space for the value field. A more practical limit is about 40 characters, which leaves enough room for most keyword values. CFITSIO returns an error if there is not enough room for both the keyword name and the keyword value on the 80-character card, except for string-valued keywords which are simply truncated so that the closing quote character falls in column 80. In the current implementation, CFITSIO preserves the case of the letters when writing the keyword name, but it is case-insensitive when reading or searching for a keyword. The current implementation allows any ASCII text character (ASCII 32 to ASCII 126) in the keyword name except for the '=' character. A space is also required on either side of the equal sign. **L. Optimizing Code for Maximum Processing Speed CFITSIO has been carefully designed to obtain the highest possible speed when reading and writing FITS files. In order to achieve the best performance, however, application programmers must be careful to call the CFITSIO routines appropriately and in an efficient sequence; inappropriate usage of CFITSIO routines can greatly slow down the execution speed of a program. The maximum possible I/O speed of CFITSIO depends of course on the type of computer system that it is running on. To get a general idea of what data I/O speeds are possible on a particular machine, build the speed.c program that is distributed with CFITSIO (type 'make speed' in the CFITSIO directory). This diagnostic program measures the speed of writing and reading back a test FITS image, a binary table, and an ASCII table. The following 2 sections provide some background on how CFITSIO internally manages the data I/O and describes some strategies that may be used to optimize the processing speed of software that uses CFITSIO. ***1. Background Information: How CFITSIO Manages Data I/O Many CFITSIO operations involve transferring only a small number of bytes to or from the FITS file (e.g, reading a keyword, or writing a row in a table); it would be very inefficient to physically read or write such small blocks of data directly in the FITS file on disk, therefore CFITSIO maintains a set of internal Input--Output (IO) buffers in RAM memory that each contain one FITS block (2880 bytes) of data. Whenever CFITSIO needs to access data in the FITS file, it first transfers the FITS block containing those bytes into one of the IO buffers in memory. The next time CFITSIO needs to access bytes in the same block it can then go to the fast IO buffer rather than using a much slower system disk access routine. The number of available IO buffers is determined by the NIOBUF parameter (in fitsio2.h) and is currently set to 40. Whenever CFITSIO reads or writes data it first checks to see if that block of the FITS file is already loaded into one of the IO buffers. If not, and if there is an empty IO buffer available, then it will load that block into the IO buffer (when reading a FITS file) or will initialize a new block (when writing to a FITS file). If all the IO buffers are already full, it must decide which one to reuse (generally the one that has been accessed least recently), and flush the contents back to disk if it has been modified before loading the new block. The one major exception to the above process occurs whenever a large contiguous set of bytes are accessed, as might occur when reading or writing a FITS image. In this case CFITSIO bypasses the internal IO buffers and simply reads or writes the desired bytes directly in the disk file with a single call to a low-level file read or write routine. The minimum threshold for the number of bytes to read or write this way is set by the MINDIRECT parameter and is currently set to 3 FITS blocks = 8640 bytes. This is the most efficient way to read or write large chunks of data. Note that this fast direct IO process is not applicable when accessing columns of data in a FITS table because the bytes are generally not contiguous since they are interleaved by the other columns of data in the table. This explains why the speed for accessing FITS tables is generally slower than accessing FITS images. Given this background information, the general strategy for efficiently accessing FITS files should now be apparent: when dealing with FITS images, read or write large chunks of data at a time so that the direct IO mechanism will be invoked; when accessing FITS headers or FITS tables, on the other hand, once a particular FITS block has been loading into one of the IO buffers, try to access all the needed information in that block before it gets flushed out of the IO buffer. It is important to avoid the situation where the same FITS block is being read then flushed from a IO buffer multiple times. The following section gives more specific suggestions for optimizing the use of CFITSIO. ***2. Optimization Strategies 1. Because the data in FITS files is always stored in "big-endian" byte order, where the first byte of numeric values contains the most significant bits and the last byte contains the least significant bits, CFITSIO must swap the order of the bytes when reading or writing FITS files when running on little-endian machines (e.g., Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). On fairly new CPUs that support "SSSE3" machine instructions (e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs beginning in 2011) significantly faster 4-byte and 8-byte swapping algorithms are available. These faster byte swapping functions are not used by default in CFITSIO (because of the potential code portablility issues), but users can enable them on supported platforms by adding the appropriate compiler flags (-mssse3 with gcc or icc on linux) when compiling the swapproc.c source file, which will allow the compiler to generate code using the SSSE3 instruction set. A convenient way to do this is to configure the CFITSIO library with the following command: - > ./configure --enable-ssse3 - Note, however, that a binary executable file that is created using these faster functions will only run on machines that support the SSSE3 machine instructions. It will crash on machines that do not support them. For faster 2-byte swaps on virtually all x86-64 CPUs (even those that do not support SSSE3), a variant using only SSE2 instructions exists. SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems (and is also automatically enabled by the --enable-ssse3 flag). When running on x86\_64 CPUs with 32-bit operating systems, these faster 2-byte swapping algorithms are not used by default in CFITSIO, but can be enabled explicitly with: - ./configure --enable-sse2 - Preliminary testing indicates that these SSSE3 and SSE2 based byte-swapping algorithms can boost the CFITSIO performance when reading or writing FITS images by 20\% - 30\% or more. It is important to note, however, that compiler optimization must be turned on (e.g., by using the -O1 or -O2 flags in gcc) when building programs that use these fast byte-swapping algorithms in order to reap the full benefit of the SSSE3 and SSE2 instructions; without optimization, the code may actually run slower than when using more traditional byte-swapping techniques. 2. When dealing with a FITS primary array or IMAGE extension, it is more efficient to read or write large chunks of the image at a time (at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism will be used as described in the previous section. Smaller chunks of data are read or written via the IO buffers, which is somewhat less efficient because of the extra copy operation and additional bookkeeping steps that are required. In principle it is more efficient to read or write as big an array of image pixels at one time as possible, however, if the array becomes so large that the operating system cannot store it all in RAM, then the performance may be degraded because of the increased swapping of virtual memory to disk. 3. When dealing with FITS tables, the most important efficiency factor in the software design is to read or write the data in the FITS file in a single pass through the file. An example of poor program design would be to read a large, 3-column table by sequentially reading the entire first column, then going back to read the 2nd column, and finally the 3rd column; this obviously requires 3 passes through the file which could triple the execution time of an I/O limited program. For small tables this is not important, but when reading multi-megabyte sized tables these inefficiencies can become significant. The more efficient procedure in this case is to read or write only as many rows of the table as will fit into the available internal I/O buffers, then access all the necessary columns of data within that range of rows. Then after the program is completely finished with the data in those rows it can move on to the next range of rows that will fit in the buffers, continuing in this way until the entire file has been processed. By using this procedure of accessing all the columns of a table in parallel rather than sequentially, each block of the FITS file will only be read or written once. The optimal number of rows to read or write at one time in a given table depends on the width of the table row, on the number of I/O buffers that have been allocated in FITSIO, and also on the number of other FITS files that are open at the same time (since one I/O buffer is always reserved for each open FITS file). Fortunately, a FITSIO routine is available that will return the optimal number of rows for a given table: call ftgrsz(unit, nrows, status). It is not critical to use exactly the value of nrows returned by this routine, as long as one does not exceed it. Using a very small value however can also lead to poor performance because of the overhead from the larger number of subroutine calls. The optimal number of rows returned by ftgrsz is valid only as long as the application program is only reading or writing data in the specified table. Any other calls to access data in the table header would cause additional blocks of data to be loaded into the I/O buffers displacing data from the original table, and should be avoided during the critical period while the table is being read or written. 4. Use binary table extensions rather than ASCII table extensions for better efficiency when dealing with tabular data. The I/O to ASCII tables is slower because of the overhead in formatting or parsing the ASCII data fields, and because ASCII tables are about twice as large as binary tables with the same information content. 5. Design software so that it reads the FITS header keywords in the same order in which they occur in the file. When reading keywords, FITSIO searches forward starting from the position of the last keyword that was read. If it reaches the end of the header without finding the keyword, it then goes back to the start of the header and continues the search down to the position where it started. In practice, as long as the entire FITS header can fit at one time in the available internal I/O buffers, then the header keyword access will be very fast and it makes little difference which order they are accessed. 6. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and TZERO keywords) in FITS files since the scaling operations add to the processing time needed to read or write the data. In some cases it may be more efficient to temporarily turn off the scaling (using ftpscl or fttscl) and then read or write the raw unscaled values in the FITS file. 7. Avoid using the 'implicit datatype conversion' capability in FITSIO. For instance, when reading a FITS image with BITPIX = -32 (32-bit floating point pixels), read the data into a single precision floating point data array in the program. Forcing FITSIO to convert the data to a different datatype can significantly slow the program. 8. Where feasible, design FITS binary tables using vector column elements so that the data are written as a contiguous set of bytes, rather than as single elements in multiple rows. For example, it is faster to access the data in a table that contains a single row and 2 columns with TFORM keywords equal to '10000E' and '10000J', than it is to access the same amount of data in a table with 10000 rows which has columns with the TFORM keywords equal to '1E' and '1J'. In the former case the 10000 floating point values in the first column are all written in a contiguous block of the file which can be read or written quickly, whereas in the second case each floating point value in the first column is interleaved with the integer value in the second column of the same row so CFITSIO has to explicitly move to the position of each element to be read or written. 9. Avoid the use of variable length vector columns in binary tables, since any reading or writing of these data requires that CFITSIO first look up or compute the starting address of each row of data in the heap. In practice, this is probably not a significant efficiency issue. 10. When copying data from one FITS table to another, it is faster to transfer the raw bytes instead of reading then writing each column of the table. The FITSIO subroutines FTGTBS and FTPTBS (for ASCII tables), and FTGTBB and FTPTBB (for binary tables) will perform low-level reads or writes of any contiguous range of bytes in a table extension. These routines can be used to read or write a whole row (or multiple rows) of a table with a single subroutine call. These routines are fast because they bypass all the usual data scaling, error checking and machine dependent data conversion that is normally done by FITSIO, and they allow the program to write the data to the output file in exactly the same byte order. For these same reasons, use of these routines can be somewhat risky because no validation or machine dependent conversion is performed by these routines. In general these routines are only recommended for optimizing critical pieces of code and should only be used by programmers who thoroughly understand the internal byte structure of the FITS tables they are reading or writing. 11. Another strategy for improving the speed of writing a FITS table, similar to the previous one, is to directly construct the entire byte stream for a whole table row (or multiple rows) within the application program and then write it to the FITS file with ftptbb. This avoids all the overhead normally present in the column-oriented CFITSIO write routines. This technique should only be used for critical applications, because it makes the code more difficult to understand and maintain, and it makes the code more system dependent (e.g., do the bytes need to be swapped before writing to the FITS file?). 12. Finally, external factors such as the type of magnetic disk controller (SCSI or IDE), the size of the disk cache, the average seek speed of the disk, the amount of disk fragmentation, and the amount of RAM available on the system can all have a significant impact on overall I/O efficiency. For critical applications, a system administrator should review the proposed system hardware to identify any potential I/O bottlenecks. *VII. Basic Interface Routines This section defines a basic set of subroutines that can be used to perform the most common types of read and write operations on FITS files. New users should start with these subroutines and then, as needed, explore the more advance routines described in the following chapter to perform more complex or specialized operations. A right arrow symbol ($>$) is used to separate the input parameters from the output parameters in the definition of each routine. This symbol is not actually part of the calling sequence. Note that the status parameter is both an input and an output parameter and must be initialized = 0 prior to calling the FITSIO subroutines. Refer to Chapter 9 for the definition of all the parameters used by these interface routines. **A. FITSIO Error Status Routines \label{FTVERS} >1 Return the current version number of the fitsio library. The version number will be incremented with each new > release of CFITSIO. - FTVERS( > version) - >2 Return the descriptive text string corresponding to a FITSIO error status code. The 30-character length string contains a brief > description of the cause of the error. - FTGERR(status, > errtext) - >3 Return the top (oldest) 80-character error message from the internal FITSIO stack of error messages and shift any remaining messages on the stack up one level. Any FITSIO error will generate one or more messages on the stack. Call this routine repeatedly to get each message in sequence. The error stack is empty > when a blank string is returned. - FTGMSG( > errmsg) - >4 The FTPMRK routine puts an invisible marker on the CFITSIO error stack. The FTCMRK routine can then be used to delete any more recent error messages on the stack, back to the position of the marker. This preserves any older error messages on the stack. FTCMSG simply clears the entire error message stack. > These routines are called without any arguments. - FTPMRK FTCMRK FTCMSG - >5 Print out the error message corresponding to the input status value and all the error messages on the FITSIO stack to the specified file stream (stream can be either the string 'STDOUT' or 'STDERR'). > If the input status value = 0 then this routine does nothing. - FTRPRT (stream, > status) - >6 Write an 80-character message to the FITSIO error stack. Application programs should not normally write to the stack, but there may be > some situations where this is desirable. - FTPMSG(errmsg) - **B. File I/O Routines >1 Open an existing FITS file with readonly or readwrite access. This routine always opens the primary array (the first HDU) of the file, and does not move to a following extension, if one was specified as part of the filename. Use the FTNOPN routine to automatically move to the extension. This routine will also open IRAF images (.imh format files) and raw binary data arrays with READONLY access by first converting them on the fly into virtual FITS images. See the `Extended File Name Syntax' chapter for more details. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended > filename syntax. - FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) - >2 Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not > have the redundant blocksize argument. - FTNOPN(unit,filename,rwmode, > status) - >3 Open an existing FITS file with readonly or readwrite access and then move to the first HDU containing significant data, if a) an HDU name or number to open was not explicitly specified as part of the filename, and b) if the FITS file contains a null primary array (i.e., NAXIS = 0). In this case, it will look for the first IMAGE HDU with NAXIS > 0, or the first table that does not contain the strings `GTI' (Good Time Interval) or `OBSTABLE' in the EXTNAME keyword value. FTTOPN is similar, except it will move to the first significant table HDU (skipping over any image HDUs) in the file if a specific HDU name or number is not specified. FTIOPN will move to the first non-null > image HDU, skipping over any tables. - FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) - >4 Open and initialize a new empty FITS file. A template file may also be specified to define the structure of the new file (see section 4.2.4). The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended > filename syntax. - FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) - >>5 Close a FITS file previously opened with ftopen or ftinit - FTCLOS(unit, > status) - >6 Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the > FITS primary array) - FTMAHD(unit,nhdu, > hdutype,status) - >7 Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array > of 32-bit integers. - FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) - >8 Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than 32-bit integers. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update > the number of rows as data is written to the table. - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) - >9 Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than a 32-bit integer. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update > the number of rows as data is written to the table. - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - **C. Keyword I/O Routines >>1 Put (append) an 80-character record into the CHU. - FTPREC(unit,card, > status) - >2 Put (append) a new keyword of the appropriate datatype into the CHU. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >3 Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of > the header; it also returns a blank card value in this case. - FTGREC(unit,key_no, > card,status) - >4 Get a keyword value (with the appropriate datatype) and comment from > the CHU - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) - >>5 Delete an existing keyword record. - FTDKEY(unit,keyword, > status) - **D. Data I/O Routines The following routines read or write data values in the current HDU of the FITS file. Automatic datatype conversion will be attempted for numerical datatypes if the specified datatype is different from the actual datatype of the FITS array or table column. >>1 Write elements into the primary data array or image extension. - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) - >2 Read elements from the primary data array or image extension. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no checks for undefined pixels will be performed. The anyf parameter is set to true (= .true.) if any of the returned > elements were undefined. - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) - >3 Write elements into an ASCII or binary table column. The `felem' parameter applies only to vector columns in binary tables and is > ignored when writing to ASCII tables. - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) - >4 Read elements from an ASCII or binary table column. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: - Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d - where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the > decimal. The .m field is optional. - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) - >5 Get the table column number and full name of the column whose name matches the input template string. See the `Advanced Interface Routines' > chapter for a full description of this routine. - FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) - *VIII Advanced Interface Subroutines This chapter defines all the available subroutines in the FITSIO user interface. For completeness, the basic subroutines described in the previous chapter are also repeated here. A right arrow symbol is used here to separate the input parameters from the output parameters in the definition of each subroutine. This symbol is not actually part of the calling sequence. An alphabetical list and definition of all the parameters is given at the end of this section. **A. FITS File Open and Close Subroutines: \label{FTOPEN} >1 Open an existing FITS file with readonly or readwrite access. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended filename syntax. FTDOPN opens the file and also moves to the first HDU containing significant data, if no specific HDU is specified as part of the filename. FTTOPN and FTIOPN are similar except that they will move to the first table HDU or image HDU, respectively, >if a HDU name or number is not specified as part of the filename. - FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) - >2 Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not > have the redundant blocksize argument. - FTNOPN(unit,filename,rwmode, > status) - >3 Reopen a FITS file that was previously opened with FTOPEN, FTNOPN, or FTINIT. The newunit number may then be treated as a separate file, and one may simultaneously read or write to 2 (or more) different extensions in the same file. The FTOPEN and FTNOPN routines (above) automatically detects cases where a previously opened file is being opened again, and then internally call FTREOPEN, so programs should rarely > need to explicitly call this routine. - FTREOPEN(unit, > newunit, status) - >4 Open and initialize a new empty FITS file. The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended > filename syntax. - FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) - >5 Create a new FITS file, using a template file to define its initial size and structure. The template may be another FITS HDU or an ASCII template file. If the input template file name is blank, then this routine behaves the same as FTINIT. The currently supported format of the ASCII template file is described under the fits\_parse\_template routine (in the general Utilities section), but this may change slightly later releases of > CFITSIO. - FTTPLT(unit, filename, tplfilename, > status) - >6 Flush internal buffers of data to the output FITS file previously opened with ftopen or ftinit. The routine usually never needs to be called, but doing so will ensure that if the program subsequently aborts, then the FITS file will > have at least been closed properly. - FTFLUS(unit, > status) - >>7 Close a FITS file previously opened with ftopen or ftinit - FTCLOS(unit, > status) - >8 Close and DELETE a FITS file previously opened with ftopen or ftinit. This routine may be useful in cases where a FITS file is created, but > an error occurs which prevents the complete file from being written. - FTDELT(unit, > status) - >9 Get the value of an unused I/O unit number which may then be used as input to FTOPEN or FTINIT. This routine searches for the first unused unit number in the range from with 99 down to 50. This routine just keeps an internal list of the allocated unit numbers and does not physically check that the Fortran unit is available (to be compatible with the SPP version of FITSIO). Thus users must not independently allocate any unit numbers in the range 50 - 99 if this routine is also to be used in the same program. This routine is provided for convenience only, and it is not required > that the unit numbers used by FITSIO be allocated by this routine. - FTGIOU( > iounit, status) - >10 Free (deallocate) an I/O unit number which was previously allocated with FTGIOU. All previously allocated unit numbers may be > deallocated at once by calling FTFIOU with iounit = -1. - FTFIOU(iounit, > status) - >11 Return the Fortran unit number that corresponds to the C fitsfile pointer value, or vice versa. These 2 C routines may be useful in mixed language programs where both C and Fortran subroutines need to access the same file. For example, if a FITS file is opened with unit 12 by a Fortran subroutine, then a C routine within the same program could get the fitfile pointer value to access the same file by calling 'fptr = CUnit2FITS(12)'. These routines return a value >of zero if an error occurs. - int CFITS2Unit(fitsfile *ptr); fitsfile* CUnit2FITS(int unit); - >11 Parse the input filename and return the HDU number that would be moved to if the file were opened with FTNOPN. The returned HDU number begins with 1 for the primary array, so for example, if the input filename = `myfile.fits[2]' then hdunum = 3 will be returned. FITSIO does not open the file to check if the extension actually exists if an extension number is specified. If an extension *name* is included in the file name specification (e.g. `myfile.fits[EVENTS]' then this routine will have to open the FITS file and look for the position of the named extension, then close file again. This is not possible if the file is being read from the stdin stream, and an error will be returned in this case. If the filename does not specify an explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, which is functionally equivalent to hdunum = 1. This routine is mainly used for backward compatibility in the ftools software package and is not recommended for general use. It is generally better and more efficient to first open the FITS file with FTNOPN, then use FTGHDN to determine which HDU in the file has been opened, rather than calling > FTEXTN followed by a call to FTNOPN. - FTEXTN(filename, > nhdu, status) - >>12 Return the name of the opened FITS file. - FTFLNM(unit, > filename, status) - >>13 Return the I/O mode of the open FITS file (READONLY = 0, READWRITE = 1). - FTFLMD(unit, > iomode, status) - >14 Return the file type of the opened FITS file (e.g. 'file://', 'ftp://', > etc.). - FTURLT(unit, > urltype, status) - >15 Parse the input filename or URL into its component parts: the file type (file://, ftp://, http://, etc), the base input file name, the name of the output file that the input file is to be copied to prior to opening, the HDU or extension specification, the filtering specifier, the binning specifier, and the column specifier. Blank strings will be returned for any components that are not present >in the input file name. - FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) - >16 Parse the input file name and return the root file name. The root name includes the file type if specified, (e.g. 'ftp://' or 'http://') and the full path name, to the extent that it is specified in the input filename. It does not include the HDU name or number, or any filtering >specifications. - FTRTNM(filename, > rootname, status) - >16 Test if the input file or a compressed version of the file (with a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of the 'exists' parameter will have 1 of the 4 following values: - 2: the file does not exist, but a compressed version does exist 1: the disk file does exist 0: neither the file nor a compressed version of the file exist -1: the input file name is not a disk file (could be a ftp, http, smem, or mem file, or a file piped in on the STDIN stream) - > - FTEXIST(filename, > exists, status); - **B. HDU-Level Operations \label{FTMAHD} When a FITS file is first opened or created, the internal buffers in FITSIO automatically point to the first HDU in the file. The following routines may be used to move to another HDU in the file. Note that the HDU numbering convention used in FITSIO denotes the primary array as the first HDU, the first extension in a FITS file is the second HDU, and so on. >1 Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the > FITS primary array) - FTMAHD(unit,nhdu, > hdutype,status) - >>2 Move to a new (existing) HDU forward or backwards relative to the CHDU - FTMRHD(unit,nmove, > hdutype,status) - >3 Move to the (first) HDU which has the specified extension type and EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype parameter may have a value of IMAGE\_HDU (0), ASCII\_TBL (1), BINARY\_TBL (2), or ANY\_HDU (-1) where ANY\_HDU means that only the extname and extver values will be used to locate the correct extension. If the input value of extver is 0 then the EXTVER keyword is ignored and the first HDU with a matching EXTNAME (or HDUNAME) keyword will be found. If no matching HDU is found in the file then the current HDU will remain unchanged > and a status = BAD\_HDU\_NUM (301) will be returned. - FTMNHD(unit, hdutype, extname, extver, > status) - >>4 Get the number of the current HDU in the FITS file (primary array = 1) - FTGHDN(unit, > nhdu) - >5 Return the type of the current HDU in the FITS file. The possible > values for hdutype are IMAGE\_HDU (0), ASCII\_TBL (1), or BINARY\_TBL (2). - FTGHDT(unit, > hdutype, status) - >6 Return the total number of HDUs in the FITS file. > The CHDU remains unchanged. - FTTHDU(unit, > hdunum, status) - >7 Create (append) a new empty HDU at the end of the FITS file. This new HDU becomes the Current HDU, but it is completely empty and contains no header keywords or data. It is recommended that FTIIMG, FTITAB or > FTIBIN be used instead of this routine. - FTCRHD(unit, > status) - >8 Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array > of 32-bit integers. - FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) - >9 Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than > 32-bit integers. - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) - >10 Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than > a 32-bit integer. - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - >11 Resize an image by modifing the size, dimensions, and/or datatype of the current primary array or image extension. If the new image, as specified by the input arguments, is larger than the current existing image in the FITS file then zero fill data will be inserted at the end of the current image and any following extensions will be moved further back in the file. Similarly, if the new image is smaller than the current image then any following extensions will be shifted up towards the beginning of the FITS file and the image data will be truncated to the new size. This routine rewrites the BITPIX, NAXIS, and NAXISn keywords with the appropriate values for new image. The FTRSIMLL routine is identical to the FTRSIM routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array > of 32-bit integers. - FTRSIM(unit,bitpix,naxis,naxes,status) FTRSIMLL(unit,bitpix,naxis,naxesll,status) - >12 Delete the CHDU in the FITS file. Any following HDUs will be shifted forward in the file, to fill in the gap created by the deleted HDU. In the case of deleting the primary array (the first HDU in the file) then the current primary array will be replace by a null primary array containing the minimum set of required keywords and no data. If there are more extensions in the file following the one that is deleted, then the the CHDU will be redefined to point to the following extension. If there are no following extensions then the CHDU will be redefined to point to the previous HDU. The output HDUTYPE parameter indicates the type of the new CHDU after > the previous CHDU has been deleted. - FTDHDU(unit, > hdutype,status) - >13 Copy all or part of the input FITS file and append it to the end of the output FITS file. If 'previous' (an integer parameter) is not equal to 0, then any HDUs preceding the current HDU in the input file will be copied to the output file. Similarly, 'current' and 'following' determine whether the current HDU, and/or any following HDUs in the input file will be copied to the output file. If all 3 parameters are not equal to zero, then the entire input file will be copied. On return, the current HDU in the input file will be unchanged, and the last copied HDU will be the > current HDU in the output file. - FTCPFL(iunit, ounit, previous, current, following, > status) - >14 Copy the entire CHDU from the FITS file associated with IUNIT to the CHDU of the FITS file associated with OUNIT. The output HDU must be empty and not already contain any keywords. Space will be reserved for MOREKEYS additional keywords in the output header if there is not already enough > space. - FTCOPY(iunit,ounit,morekeys, > status) - >15 Copy the header (and not the data) from the CHDU associated with inunit to the CHDU associated with outunit. If the current output HDU is not completely empty, then the CHDU will be closed and a new HDU will be appended to the output file. This routine will automatically transform the necessary keywords when copying a primary array to and image extension, or an image extension to a primary array. > An empty output data unit will be created (all values = 0). - FTCPHD(inunit, outunit, > status) - >16 Copy just the data from the CHDU associated with IUNIT to the CHDU associated with OUNIT. This will overwrite any data previously in the OUNIT CHDU. This low level routine is used by FTCOPY, but it may also be useful in certain application programs which want to copy the data from one FITS file to another but also want to modify the header keywords in the process. all the required header keywords must be written to the OUNIT CHDU before calling > this routine - FTCPDT(iunit,ounit, > status) - **C. Define or Redefine the structure of the CHDU \label{FTRDEF} It should rarely be necessary to call the subroutines in this section. FITSIO internally calls these routines whenever necessary, so any calls to these routines by application programs will likely be redundant. >1 This routine forces FITSIO to scan the current header keywords that define the structure of the HDU (such as the NAXISn, PCOUNT and GCOUNT keywords) so that it can initialize the internal buffers that describe the HDU structure. This routine may be used instead of the more complicated calls to ftpdef, ftadef or ftbdef. This routine is also very useful for reinitializing the structure of an HDU, if the number of rows in a table, as specified by the NAXIS2 keyword, > has been modified from its initial value. - FTRDEF(unit, > status) (DEPRECATED) - >2 Define the structure of the primary array or IMAGE extension. When writing GROUPed FITS files that by convention set the NAXIS1 keyword equal to 0, ftpdef must be called with naxes(1) = 1, NOT 0, otherwise FITSIO will report an error status=308 when trying to write data to a group. Note: it is usually simpler to call FTRDEF rather > than this routine. - FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) - >3 Define the structure of an ASCII table (TABLE) extension. Note: it > is usually simpler to call FTRDEF rather than this routine. - FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) - >4 Define the structure of a binary table (BINTABLE) extension. Note: it > is usually simpler to call FTRDEF rather than this routine. - FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) - >5 Define the size of the Current Data Unit, overriding the length of the data unit as previously defined by ftpdef, ftadef, or ftbdef. This is useful if one does not know the total size of the data unit until after the data have been written. The size (in bytes) of an ASCII or Binary table is given by NAXIS1 * NAXIS2. (Note that to determine the value of NAXIS1 it is often more convenient to read the value of the NAXIS1 keyword from the output file, rather than computing the row length directly from all the TFORM keyword values). Note: it > is usually simpler to call FTRDEF rather than this routine. - FTDDEF(unit,bytlen, > status) (DEPRECATED) - >6 Define the zero indexed byte offset of the 'heap' measured from the start of the binary table data. By default the heap is assumed to start immediately following the regular table data, i.e., at location NAXIS1 x NAXIS2. This routine is only relevant for binary tables which contain variable length array columns (with TFORMn = 'Pt'). This subroutine also automatically writes the value of theap to a keyword in the extension header. This subroutine must be called after the required keywords have been written (with ftphbn) and after the table structure has been defined > (with ftbdef) but before any data is written to the table. - FTPTHP(unit,theap, > status) - **D. FITS Header I/O Subroutines ***1. Header Space and Position Routines \label{FTHDEF} >1 Reserve space in the CHU for MOREKEYS more header keywords. This subroutine may be called to reserve space for keywords which are to be written at a later time, after the data unit or subsequent extensions have been written to the FITS file. If this subroutine is not explicitly called, then the initial size of the FITS header will be limited to the space available at the time that the first data is written to the associated data unit. FITSIO has the ability to dynamically add more space to the header if needed, however it is more efficient > to preallocate the required space if the size is known in advance. - FTHDEF(unit,morekeys, > status) - >2 Return the number of existing keywords in the CHU (NOT including the END keyword which is not considered a real keyword) and the remaining space available to write additional keywords in the CHU. (returns KEYSADD = -1 if the header has not yet been closed). Note that FITSIO will attempt to dynamically add space for more > keywords if required when appending new keywords to a header. - FTGHSP(iunit, > keysexist,keysadd,status) - >3 Return the number of keywords in the header and the current position in the header. This returns the number of the keyword record that will be read next (or one greater than the position of the last keyword that was read or written). A value of 1 is returned if the pointer is > positioned at the beginning of the header. - FTGHPS(iunit, > keysexist,key_no,status) - ***2. Read or Write Standard Header Routines \label{FTPHPR} These subroutines provide a simple method of reading or writing most of the keyword values that are normally required in a FITS files. These subroutines are provided for convenience only and are not required to be used. If preferred, users may call the lower-level subroutines described in the previous section to individually read or write the required keywords. Note that in most cases, the required keywords such as NAXIS, TFIELD, TTYPEn, etc, which define the structure of the HDU must be written to the header before any data can be written to the image or table. >1 Put the primary header or IMAGE extension keywords into the CHU. There are 2 available routines: The simpler FTPHPS routine is equivalent to calling ftphpr with the default values of SIMPLE = true, pcount = 0, gcount = 1, and EXTEND = true. PCOUNT, GCOUNT and EXTEND keywords are not required in the primary header and are only written if pcount is not equal to zero, gcount is not equal to zero or one, and if extend is TRUE, respectively. When writing to an IMAGE extension, the >SIMPLE and EXTEND parameters are ignored. - FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) - >2 Get primary header or IMAGE extension keywords from the CHU. When reading from an IMAGE extension the SIMPLE and EXTEND parameters are > ignored. - FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) - >3 Put the ASCII table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string >values are not blank. - FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) - >>4 Get the ASCII table header keywords from the CHU - FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) - >5 Put the binary table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string values are not blank. The pcount parameter, which specifies the size of the variable length array heap, should initially = 0; FITSIO will automatically update the PCOUNT keyword value if any variable length array data is written to the heap. The TFORM keyword value for variable length vector columns should have the form 'Pt(len)' or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) and `len' is an integer specifying the maximum length of the vectors in that column (len must be greater than or equal to the longest vector in the column). If `len' is not specified when the table is created (e.g., the input TFORMn value is just '1Pt') then FITSIO will scan the column when the table is first closed and will append the maximum length to the TFORM keyword value. Note that if the table is subsequently modified to increase the maximum length of the vectors then the modifying program is responsible for also updating the TFORM > keyword value. - FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat, > status) - >>6 Get the binary table header keywords from the CHU - FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) - ***3. Write Keyword Subroutines \label{FTPREC} >>1 Put (append) an 80-character record into the CHU. - FTPREC(unit,card, > status) - >2 Put (append) a COMMENT keyword into the CHU. Multiple COMMENT keywords > will be written if the input comment string is longer than 72 characters. - FTPCOM(unit,comment, > status) - >3 Put (append) a HISTORY keyword into the CHU. Multiple HISTORY keywords > will be written if the input history string is longer than 72 characters. - FTPHIS(unit,history, > status) - >4 Put (append) the DATE keyword into the CHU. The keyword value will contain the current system date as a character string in 'dd/mm/yy' format. If a DATE keyword already exists in the header, then this subroutine will > simply update the keyword value in-place with the current date. - FTPDAT(unit, > status) - >5 Put (append) a new keyword of the appropriate datatype into the CHU. Note that FTPKYS will only write string values up to 68 characters in length; longer strings will be truncated. The FTPKLS routine can be used to write longer strings, using a non-standard FITS convention. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >6 Put (append) a string valued keyword into the CHU which may be longer than 68 characters in length. This uses the Long String Keyword convention that is described in the "Usage Guidelines and Suggestions" section of this document. Since this uses a non-standard FITS convention to encode the long keyword string, programs which use this routine should also call the FTPLSW routine to add some COMMENT keywords to warn users of the FITS file that this convention is being used. FTPLSW also writes a keyword called LONGSTRN to record the version of the longstring convention that has been used, in case a new convention is adopted at some point in the future. If the LONGSTRN keyword is already present in the header, then FTPLSW will > simply return and will not write duplicate keywords. - FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) - >7 Put (append) a new keyword with an undefined, or null, value into the CHU. > The value string of the keyword is left blank in this case. - FTPKYU(unit,keyword,comment, > status) - >8 Put (append) a numbered sequence of keywords into the CHU. One may append the same comment to every keyword (and eliminate the need to have an array of identical comment strings, one for each keyword) by including the ampersand character as the last non-blank character in the (first) COMMENTS string parameter. This same string will then be used for the comment field in all the keywords. (Note that the SPP version of these routines only supports a single comment > string). - FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) - >9 Copy an indexed keyword from one HDU to another, modifying the index number of the keyword name in the process. For example, this routine could read the TLMIN3 keyword from the input HDU (by giving keyroot = "TLMIN" and innum = 3) and write it to the output HDU with the keyword name TLMIN4 (by setting outnum = 4). If the input keyword does not exist, then this routine simply > returns without indicating an error. - FTCPKY(inunit, outunit, innum, outnum, keyroot, > status) - >10 Put (append) a 'triple precision' keyword into the CHU in F28.16 format. The floating point keyword value is constructed by concatenating the input integer value with the input double precision fraction value (which must have a value between 0.0 and 1.0). The FTGKYT routine should be used to read this keyword value, because the other keyword reading > subroutines will not preserve the full precision of the value. - FTPKYT(unit,keyword,intval,dblval,comment, > status) - >11 Write keywords to the CHDU that are defined in an ASCII template file. The format of the template file is described under the ftgthd > routine below. - FTPKTP(unit, filename, > status) - >12 Append the physical units string to an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the > beginning of the keyword comment field. - VELOCITY= 12.3 / [km/s] orbital speed FTPUNT(unit,keyword,units, > status) - ***4. Insert Keyword Subroutines \label{FTIREC} >1 Insert a new keyword record into the CHU at the specified position (i.e., immediately preceding the (keyno)th keyword in the header.) This 'insert record' subroutine is somewhat less efficient then the 'append record' subroutine (FTPREC) described above because > the remaining keywords in the header have to be shifted down one slot. - FTIREC(unit,key_no,card, > status) - >2 Insert a new keyword into the CHU. The new keyword is inserted immediately following the last keyword that has been read from the header. The FTIKLS subroutine works the same as the FTIKYS subroutine, except it also supports long string values greater than 68 characters in length. These 'insert keyword' subroutines are somewhat less efficient then the 'append keyword' subroutines described above because the remaining > keywords in the header have to be shifted down one slot. - FTIKEY(unit, card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >3 Insert a new keyword with an undefined, or null, value into the CHU. > The value string of the keyword is left blank in this case. - FTIKYU(unit,keyword,comment, > status) - ***5. Read Keyword Subroutines \label{FTGREC} These routines return the value of the specified keyword(s). Wild card characters (*, ?, or \#) may be used when specifying the name of the keyword to be read: a '?' will match any single character at that position in the keyword name and a '*' will match any length (including zero) string of characters. The '\#' character will match any consecutive string of decimal digits (0 - 9). Note that when a wild card is used in the input keyword name, the routine will only search for a match from the current header position to the end of the header. It will not resume the search from the top of the header back to the original header position as is done when no wildcards are included in the keyword name. If the desired keyword string is 8-characters long (the maximum length of a keyword name) then a '*' may be appended as the ninth character of the input name to force the keyword search to stop at the end of the header (e.g., 'COMMENT *' will search for the next COMMENT keyword). The ffgrec routine may be used to set the starting position when doing wild card searches. >1 Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of > the header; it also returns a blank card value in this case. - FTGREC(unit,key_no, > card,status) - >2 Get the name, value (as a string), and comment of the nth keyword in CHU. This routine also checks that the returned keyword name (KEYWORD) contains only legal ASCII characters. Call FTGREC and FTPSVC to bypass this error > check. - FTGKYN(unit,key_no, > keyword,value,comment,status) - >>3 Get the 80-character header record for the named keyword - FTGCRD(unit,keyword, > card,status) - >4 Get the next keyword whose name matches one of the strings in 'inclist' but does not match any of the strings in 'exclist'. The strings in inclist and exclist may contain wild card characters (*, ?, and \#) as described at the beginning of this section. This routine searches from the current header position to the end of the header, only, and does not continue the search from the top of the header back to the original position. The current header position may be reset with the ftgrec routine. Note that nexc may be set = 0 if there are no keywords to be excluded. This routine returns status = 202 if a matching > keyword is not found. - FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) - >5 Get the literal keyword value as a character string. Regardless of the datatype of the keyword, this routine simply returns the string of characters in the value field of the keyword along with > the comment field. - FTGKEY(unit,keyword, > value,comment,status) - >6 Get a keyword value (with the appropriate datatype) and comment from > the CHU - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) - >7 Read a string-valued keyword and return the string length, the value string, and/or the comment field. The first routine, FTGKSL, simply returns the length of the character string value of the specified keyword. The second routine, FTGSKY, also returns up to maxchar characters of the keyword value string, starting with the firstchar character, and the keyword comment string. The length argument returns the total length of the keyword value string regardless of how much of the string is actually returned (which depends on the value of the firstchar and maxchar arguments). These routines support string keywords that use the CONTINUE convention to continue long string values over multiple FITS header records. Normally, string-valued keywords have a maximum length of 68 characters, however, > CONTINUE'd string keywords may be arbitrarily long. - FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) - >8 Get a sequence of numbered keyword values. These > routines do not support wild card characters in the root name. - FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) - >9 Get the value of a floating point keyword, returning the integer and fractional parts of the value in separate subroutine arguments. This subroutine may be used to read any keyword but is especially > useful for reading the 'triple precision' keywords written by FTPKYT. - FTGKYT(unit,keyword, > intval,dblval,comment,status) - >10 Get the physical units string in an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. A blank string is returned if no units are defined > for the keyword. - VELOCITY= 12.3 / [km/s] orbital speed FTGUNT(unit,keyword, > units,status) - ***6. Modify Keyword Subroutines \label{FTMREC} Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be modified. >>1 Modify (overwrite) the nth 80-character header record in the CHU - FTMREC(unit,key_no,card, > status) - >2 Modify (overwrite) the 80-character header record for the named keyword in the CHU. This can be used to overwrite the name of the keyword as > well as its value and comment fields. - FTMCRD(unit,keyword,card, > status) - >3 Modify (overwrite) the name of an existing keyword in the CHU > preserving the current value and comment fields. - FTMNAM(unit,oldkey,keyword, > status) - >>4 Modify (overwrite) the comment field of an existing keyword in the CHU - FTMCOM(unit,keyword,comment, > status) - >5 Modify the value and comment fields of an existing keyword in the CHU. The FTMKLS subroutine works the same as the FTMKYS subroutine, except it also supports long string values greater than 68 characters in length. Optionally, one may modify only the value field and leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&). The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >6 Modify the value of an existing keyword to be undefined, or null. The value string of the keyword is set to blank. Optionally, one may leave the comment field unchanged by setting the > input COMMENT parameter equal to the ampersand character (\&). - FTMKYU(unit,keyword,comment, > status) - ***7. Update Keyword Subroutines \label{FTUCRD} >1 Update an 80-character record in the CHU. If the specified keyword already exists then that header record will be replaced with the input CARD string. If it does not exist then the new record will be added to the header. The FTUKLS subroutine works the same as the FTUKYS subroutine, except > it also supports long string values greater than 68 characters in length. - FTUCRD(unit,keyword,card, > status) - >2 Update the value and comment fields of a keyword in the CHU. The specified keyword is modified if it already exists (by calling FTMKYx) otherwise a new keyword is created by calling FTPKYx. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >3 Update the value of an existing keyword to be undefined, or null, or insert a new undefined-value keyword if it doesn't already exist. > The value string of the keyword is left blank in this case. - FTUKYU(unit,keyword,comment, > status) - ***8. Delete Keyword Subroutines \label{FTDREC} >1 Delete an existing keyword record. The space previously occupied by the keyword is reclaimed by moving all the following header records up one row in the header. The first routine deletes a keyword at a specified position in the header (the first keyword is at position 1), whereas the second routine deletes a specifically named keyword. Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be deleted > (be careful!). - FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) - **F. Data Scaling and Undefined Pixel Parameters \label{FTPSCL} These subroutines define or modify the internal parameters used by FITSIO to either scale the data or to represent undefined pixels. Generally FITSIO will scale the data according to the values of the BSCALE and BZERO (or TSCALn and TZEROn) keywords, however these subroutines may be used to override the keyword values. This may be useful when one wants to read or write the raw unscaled values in the FITS file. Similarly, FITSIO generally uses the value of the BLANK or TNULLn keyword to signify an undefined pixel, but these routines may be used to override this value. These subroutines do not create or modify the corresponding header keyword values. >1 Reset the scaling factors in the primary array or image extension; does not change the BSCALE and BZERO keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * BSCALE + BZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: BSCALE and BZERO must be declared as Double Precision > variables). - FTPSCL(unit,bscale,bzero, > status) - >2 Reset the scaling parameters for a table column; does not change the TSCALn or TZEROn keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * TSCAL + TZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: TSCAL and TZERO must be declared as Double Precision > variables). - FTTSCL(unit,colnum,tscal,tzero, > status) - >3 Define the integer value to be used to signify undefined pixels in the primary array or image extension. This is only used if BITPIX = 8, 16, 32. or 64 This does not create or change the value of the BLANK keyword in the header. FTPNULLL is identical to FTPNUL except that the blank > value is a 64-bit integer instead of a 32-bit integer. - FTPNUL(unit,blank, > status) FTPNULLL(unit,blankll, > status) - >4 Define the string to be used to signify undefined pixels in a column in an ASCII table. This does not create or change the value > of the TNULLn keyword. - FTSNUL(unit,colnum,snull > status) - >5 Define the value to be used to signify undefined pixels in an integer column in a binary table (where TFORMn = 'B', 'I', 'J', or 'K'). This does not create or change the value of the TNULLn keyword. FTTNULLL is identical to FTTNUL except that the tnull > value is a 64-bit integer instead of a 32-bit integer. - FTTNUL(unit,colnum,tnull > status) FTTNULLL(unit,colnum,tnullll > status) - **G. FITS Primary Array or IMAGE Extension I/O Subroutines \label{FTPPR} These subroutines put or get data values in the primary data array (i.e., the first HDU in the FITS file) or an IMAGE extension. The data array is represented as a single one-dimensional array of pixels regardless of the actual dimensionality of the array, and the FPIXEL parameter gives the position within this 1-D array of the first pixel to read or write. Automatic data type conversion is performed for numeric data (except for complex data types) if the data type of the primary array (defined by the BITPIX keyword) differs from the data type of the array in the calling subroutine. The data values are also scaled by the BSCALE and BZERO header values as they are being written or read from the FITS array. The ftpscl subroutine MUST be called to define the scaling parameters when writing data to the FITS array or to override the default scaling value given in the header when reading the FITS array. Two sets of subroutines are provided to read the data array which differ in the way undefined pixels are handled. The first set of routines (FTGPVx) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGPFx) returns the data element array and, in addition, a logical array which defines whether the corresponding data pixel is undefined. The latter set of subroutines may be more convenient to use in some circumstances, however, it requires an additional array of logical values which can be unwieldy when working with large data arrays. Also for programmer convenience, sets of subroutines to directly read or write 2 and 3 dimensional arrays have been provided, as well as a set of subroutines to read or write any contiguous rectangular subset of pixels within the n-dimensional array. >1 Get the data type of the image (= BITPIX value). Possible returned values are: 8, 16, 32, 64, -32, or -64 corresponding to unsigned byte, signed 2-byte integer, signed 4-byte integer, signed 8-byte integer, real, and double. The second subroutine is similar to FTGIDT, except that if the image pixel values are scaled, with non-default values for the BZERO and BSCALE keywords, then this routine will return the 'equivalent' data type that is needed to store the scaled values. For example, if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is floating point, and -32 will be returned. There are 2 special cases: if the image contains unsigned 2-byte integer values, with BITPIX = 16, BSCALE = 1, and BZERO = 32768, then this routine will return a non-standard value of 20 for the bitpix value. Similarly if the image contains unsigned 4-byte integers, then bitpix will > be returned with a value of 40. - FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) - >>2 Get the dimension (number of axes = NAXIS) of the image - FTGIDM(unit, > naxis,status) - >3 Get the size of all the dimensions of the image. The FTGISZLL > routine returns an array of 64-bit integers instead of 32-bit integers. - FTGISZ(unit, maxdim, > naxes,status) FTGISZLL(unit, maxdim, > naxesll,status) - >4 Get the parameters that define the type and size of the image. This routine simply combines calls to the above 3 routines. The FTGIPRLL > routine returns an array of 64-bit integers instead of 32-bit integers. - FTGIPR(unit, maxdim, > bitpix, naxis, naxes, int *status) FTGIPRLL(unit, maxdim, > bitpix, naxis, naxesll, int *status) - >>5 Put elements into the data array - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) - >6 Put elements into the data array, substituting the appropriate FITS null value for all elements which are equal to the value of NULLVAL. For integer FITS arrays, the null value defined by the previous call to FTPNUL will be substituted; for floating point FITS arrays (BITPIX = -32 or -64) then the special IEEE NaN (Not-a-Number) value will be > substituted. - FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) - >>7 Set data array elements as undefined - FTPPRU(unit,group,fpixel,nelements, > status) - >8 Get elements from the data array. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no > checks for undefined pixels will be performed. - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) - >9 Get elements and nullflags from data array. Any undefined array elements will have the corresponding flagvals element > set equal to .TRUE. - FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) - >>10 Put values into group parameters - FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) - >>11 Get values from group parameters - FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) - The following 4 subroutines transfer FITS images with 2 or 3 dimensions to or from a data array which has been declared in the calling program. The dimensionality of the FITS image is passed by the naxis1, naxis2, and naxis3 parameters and the declared dimensions of the program array are passed in the dim1 and dim2 parameters. Note that the program array does not have to have the same dimensions as the FITS array, but must be at least as big. For example if a FITS image with NAXIS1 = NAXIS2 = 400 is read into a program array which is dimensioned as 512 x 512 pixels, then the image will just fill the lower left corner of the array with pixels in the range 1 - 400 in the X an Y directions. This has the effect of taking a contiguous set of pixel value in the FITS array and writing them to a non-contiguous array in program memory (i.e., there are now some blank pixels around the edge of the image in the program array). >>11 Put 2-D image into the data array - FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) - >>12 Put 3-D cube into the data array - FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) - >13 Get 2-D image from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will > be performed. - FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) - >14 Get 3-D cube from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will > be performed. - FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) - The following subroutines transfer a rectangular subset of the pixels in a FITS N-dimensional image to or from an array which has been declared in the calling program. The fpixels and lpixels parameters are integer arrays which specify the starting and ending pixels in each dimension of the FITS image that are to be read or written. (Note that these are the starting and ending pixels in the FITS image, not in the declared array). The array parameter is treated simply as a large one-dimensional array of the appropriate datatype containing the pixel values; The pixel values in the FITS array are read/written from/to this program array in strict sequence without any gaps; it is up to the calling routine to correctly interpret the dimensionality of this array. The two families of FITS reading routines (FTGSVx and FTGSFx subroutines) also have an 'incs' parameter which defines the data sampling interval in each dimension of the FITS array. For example, if incs(1)=2 and incs(2)=3 when reading a 2-dimensional FITS image, then only every other pixel in the first dimension and every 3rd pixel in the second dimension will be returned in the 'array' parameter. [Note: the FTGSSx family of routines which were present in previous versions of FITSIO have been superseded by the more general FTGSVx family of routines.] >>15 Put an arbitrary data subsection into the data array. - FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) - >16 Get an arbitrary data subsection from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will > be performed. - FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) - >17 Get an arbitrary data subsection from the data array. Any Undefined pixels in the array will have the corresponding 'flagvals' > element set equal to .TRUE. - FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) - **H. FITS ASCII and Binary Table Data I/O Subroutines ***1. Column Information Subroutines \label{FTGCNO} >1 Get the number of rows or columns in the current FITS table. The number of rows is given by the NAXIS2 keyword and the number of columns is given by the TFIELDS keyword in the header of the table. The FTGNRWLL routine is identical to FTGNRW except that the number of rows is returned as a 64-bit integer rather > than a 32-bit integer. - FTGNRW(unit, > nrows, status) FTGNRWLL(unit, > nrowsll, status) FTGNCL(unit, > ncols, status) - >2 Get the table column number (and name) of the column whose name matches an input template name. The table column names are defined by the TTYPEn keywords in the FITS header. If a column does not have a TTYPEn keyword, then these routines assume that the name consists of all blank characters. These 2 subroutines perform the same function except that FTGCNO only returns the number of the matching column whereas FTGCNN also returns the name of the column. If CASESEN = .true. then the column name match will be case-sensitive. The input column name template (COLTEMPLATE) is (1) either the exact name of the column to be searched for, or (2) it may contain wild cards characters (*, ?, or \#), or (3) it may contain the number of the desired column (where the number is expressed as ASCII digits). The first 2 wild cards behave similarly to UNIX filename matching: the '*' character matches any sequence of characters (including zero characters) and the '?' character matches any single character. The \# wildcard will match any consecutive string of decimal digits (0-9). As an example, the template strings 'AB?DE', 'AB*E', and 'AB*CDE' will all match the string 'ABCDE'. If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to 237 as a warning that a unique match was not found. To find the other cases that match the template, simply call the subroutine again leaving the input status value equal to 237 and the next matching name will then be returned. Repeat this process until a status = 219 (column name not found) is returned. If these subroutines fail to match the template to any of the columns in the table, they lastly check if the template can be interpreted as a simple positive integer (e.g., '7', or '512') and if so, they return that column number. If no matches are found then a status = 219 error is returned. Note that the FITS Standard recommends that only letters, digits, and the underscore character be used in column names (with no embedded >spaces in the name). Trailing blank characters are not significant. - FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) - >3 Get the datatype of a column in an ASCII or binary table. This routine returns an integer code value corresponding to the datatype of the column. (See the FTBNFM and FTASFM subroutines in the Utilities section of this document for a list of the code values). The vector repeat count (which is alway 1 for ASCII table columns) is also returned. If the specified column has an ASCII character datatype (code = 16) then the width of a unit string in the column is also returned. Note that this routine supports the local convention for specifying arrays of strings within a binary table character column, using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this routine will return datacode = 16, repeat = 60, and width = 12. (The TDIMn keyword may also be used to specify the unit string length; The pair of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the same effect as TFORMn = '60A12'). The second routine, FTEQTY is similar except that in the case of scaled integer columns it returns the 'equivalent' data type that is needed to store the scaled values, and not necessarily the physical data type of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be the code for an unsigned short integer, not a signed short integer. Similarly, if a column has TTYPEn = '1I' and TSCALn = 0.12, then the returned typecode > will be the code for a 'real' column. - FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) - >4 Return the display width of a column. This is the length of the string that will be returned when reading the column as a formatted string. The display width is determined by the TDISPn keyword, if present, otherwise by the data > type of the column. - FTGCDW(unit, colnum, > dispwidth, status) - >5 Get information about an existing ASCII table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). All the > returned parameters are scalar quantities. - FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) - >6 Get information about an existing binary table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). DATATYPE is a character string which returns the datatype of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case of an ASCII character column, DATATYPE will have a value of the form 'An' where 'n' is an integer expressing the width of the field in characters. For example, if TFORM = '160A8' then FTGBCL will return DATATYPE='A8' and REPEAT=20. All the returned parameters are scalar > quantities. - FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) - >7 Put (append) a TDIMn keyword whose value has the form '(l,m,n...)' where l, m, n... are the dimensions of a multidimensional array > column in a binary table. - FTPTDM(unit,colnum,naxis,naxes, > status) - >8 Return the number of and size of the dimensions of a table column. Normally this information is given by the TDIMn keyword, but if this keyword is not present then this routine returns NAXIS = 1 > and NAXES(1) equal to the repeat count in the TFORM keyword. - FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) - >9 Decode the input TDIMn keyword string (e.g. '(100,200)') and return the number of and size of the dimensions of a binary table column. If the input tdimstr character string is null, then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. This routine > is called by FTGTDM. - FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) - >10 Return the optimal number of rows to read or write at one time for maximum I/O efficiency. Refer to the ``Optimizing Code'' section > in Chapter 5 for more discussion on how to use this routine. - FTGRSZ(unit, > nrows,status) - ***2. Low-Level Table Access Subroutines \label{FTGTBS} The following subroutines provide low-level access to the data in ASCII or binary tables and are mainly useful as an efficient way to copy all or part of a table from one location to another. These routines simply read or write the specified number of consecutive bytes in an ASCII or binary table, without regard for column boundaries or the row length in the table. The first two subroutines read or write consecutive bytes in a table to or from a character string variable, while the last two subroutines read or write consecutive bytes to or from a variable declared as a numeric data type (e.g., INTEGER, INTEGER*2, REAL, DOUBLE PRECISION). These routines do not perform any machine dependent data conversion or byte swapping, except that conversion to/from ASCII format is performed by the FTGTBS and FTPTBS routines on machines which do not use ASCII character codes in the internal data representations (e.g., on IBM mainframe computers). >1 Read a consecutive string of characters from an ASCII table into a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of > complications related to passing string variables between C and Fortran. - FTGTBS(unit,frow,startchar,nchars, > string,status) - >2 Write a consecutive string of characters to an ASCII table from a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of > complications related to passing string variables between C and Fortran. - FTPTBS(unit,frow,startchar,nchars,string, > status) - >3 Read a consecutive array of bytes from an ASCII or binary table into a numeric variable (spanning columns and multiple rows if necessary). The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, > then declare the array as INTEGER*4 ARRAY(5). - FTGTBB(unit,frow,startchar,nchars, > array,status) - >4 Write a consecutive array of bytes to an ASCII or binary table from a numeric variable (spanning columns and multiple rows if necessary) The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, > then declare the array as INTEGER*4 ARRAY(5). - FTPTBB(unit,frow,startchar,nchars,array, > status) - ***3. Edit Rows or Columns \label{FTIROW} >1 Insert blank rows into an existing ASCII or binary table (in the CDU). All the rows FOLLOWING row FROW are shifted down by NROWS rows. If FROW or FROWLL equals 0 then the blank rows are inserted at the beginning of the table. These routines modify the NAXIS2 keyword to reflect the new number of rows in the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that > row of data already exists or not. - FTIROW(unit,frow,nrows, > status) FTIROWLL(unit,frowll,nrowsll, > status) - >2 Delete rows from an existing ASCII or binary table (in the CDU). The NROWS (or NROWSLL) is the number of rows are deleted, starting with row FROW (or FROWLL), and any remaining rows in the table are shifted up to fill in the space. These routines modify the NAXIS2 keyword to reflect the new number > of rows in the table. - FTDROW(unit,frow,nrows, > status) FTDROWLL(unit,frowll,nrowsll, > status) - >3 Delete a list of rows from an ASCII or binary table (in the CDU). In the first routine, 'rowrange' is a character string listing the rows or row ranges to delete (e.g., '2-4, 5, 8-9'). In the second routine, 'rowlist' is an integer array of row numbers to be deleted from the table. nrows is the number of row numbers in the list. The first row in the table is 1 not 0. The list of row numbers > must be sorted in ascending order. - FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) - >4 Insert a blank column (or columns) into an existing ASCII or binary table (in the CDU). COLNUM specifies the column number that the (first) new column should occupy in the table. NCOLS specifies how many columns are to be inserted. Any existing columns from this position and higher are moved over to allow room for the new column(s). The index number on all the following keywords will be incremented if necessary to reflect the new position of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, > and TCUNIn. - FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) - >5 Modify the vector length of a binary table column (e.g., change a column from TFORMn = '1E' to '20E'). The vector > length may be increased or decreased from the current value. - FTMVEC(unit,colnum,newveclen, > status) - >6 Delete a column from an existing ASCII or binary table (in the CDU). The index number of all the keywords listed above (for FTICOL) will be decremented if necessary to reflect the new position of the column(s) in the table. Those index keywords that refer to the deleted column will also be deleted. Note that the physical size of the FITS file will not be reduced by this operation, and the empty FITS blocks if any > at the end of the file will be padded with zeros. - FTDCOL(unit,colnum, > status) - >7 Copy a column from one HDU to another (or to the same HDU). If createcol = TRUE, then a new column will be inserted in the output table, at position `outcolumn', otherwise the existing output column will be overwritten (in which case it must have a compatible datatype). > Note that the first column in a table is at colnum = 1. - FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); - ***4. Read and Write Column Data Routines \label{FTPCLS} These subroutines put or get data values in the current ASCII or Binary table extension. Automatic data type conversion is performed for numerical data types (B,I,J,E,D) if the data type of the column (defined by the TFORM keyword) differs from the data type of the calling subroutine. The data values are also scaled by the TSCALn and TZEROn header values as they are being written to or read from the FITS array. The fttscl subroutine MUST be used to define the scaling parameters when writing data to the table or to override the default scaling values given in the header when reading from the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. In the case of binary tables with vector elements, the 'felem' parameter defines the starting pixel within the element vector. This parameter is ignored with ASCII tables. Similarly, in the case of binary tables the 'nelements' parameter specifies the total number of vector values read or written (continuing on subsequent rows if required) and not the number of table elements. Two sets of subroutines are provided to get the column data which differ in the way undefined pixels are handled. The first set of routines (FTGCV) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGCF) returns the data element array and in addition a logical array of flags which defines whether the corresponding data pixel is undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: - Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d - where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. >1 Put elements into an ASCII or binary table column (in the CDU). (The SPP FSPCLS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCL[LBIJKEDCM]LL(unit,colnum,frow,felem,nelements,values, > status) - >2 Put elements into an ASCII or binary table column (in the CDU) substituting the appropriate FITS null value for any elements that are equal to NULLVAL. For ASCII TABLE extensions, the null value defined by the previous call to FTSNUL will be substituted; For integer FITS columns, in a binary table the null value defined by the previous call to FTTNUL will be substituted; For floating point FITS columns a special IEEE NaN (Not-a-Number) value will be substituted. The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTPCN[SBIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCN[SBIJKED]LL(unit,colnum,(I*8) frow,(I*8) felem,nelements,values, nullval > status) - >3 Put bit values into a binary byte ('B') or bit ('X') table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be written. If LRAY is true then the corresponding bit is set to 1, otherwise the bit is set to 0. Note that in the case of 'X' columns, FITSIO will write to all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTPCLX with fbit=1 and nbit=8, then all 8 bits will be written into the first byte (as opposed to writing the first 4 bits into the first row and then the next 4 bits into the next row), even though the last 4 bits of each byte are formally > not defined. - FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) - >>4 Set table elements in a column as undefined - FTPCLU(unit,colnum,frow,felem,nelements, > status) - >5 Get elements from an ASCII or binary table column (in the CDU). These routines return the values of the table column array elements. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. (Note: the ftgcl routine simple gets an array of logical data values without any checks for undefined values; use the ftgcfl routine to check for undefined logical elements). (The SPP FSGCVS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCV[BIJKEDCM]LL(unit,colnum,(I*8) frow, (I*8) felem, nelements, nullval, > values,anyf,status) - >6 Get elements and null flags from an ASCII or binary table column (in the CHDU). These routines return the values of the table column array elements. Any undefined array elements will have the corresponding flagvals element set equal to .TRUE. The ANYF parameter is set to true if any of the returned elements are undefined. (The SPP FSGCFS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGCF[BIJKED]LL(unit,colnum, (I*8) frow, (I*8) felem,nelements, > values,flagvals,anyf,status) - >7 Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in > each dimension between the data elements that will be returned. - FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) - >8 Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Any Undefined pixels in the array will have the corresponding 'flagvals' element set equal to .TRUE. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in each dimension between the data elements that will be > returned. - FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) - >9 Get bit values from a byte ('B') or bit (`X`) table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be read. If LRAY is true then the corresponding bit was set to 1, otherwise the bit was set to 0. Note that in the case of 'X' columns, FITSIO will read all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTGCX with fbit=1 and nbit=8, then all 8 bits will be read from the first byte (as opposed to reading the first 4 bits from the first row and then the first 4 bits from the next row), even though the last 4 bits of > each byte are formally not defined. - FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) - >10 Read any consecutive set of bits from an 'X' or 'B' column and interpret them as an unsigned n-bit integer. NBIT must be less than or equal to 16 when calling FTGCXI, and less than or equal to 32 when calling FTGCXJ; there is no limit on the value of NBIT for FTGCXD, but the returned double precision value only has 48 bits of precision on most 32-bit word machines. The NBITS bits are interpreted as an unsigned integer unless NBITS = 16 (in FTGCXI) or 32 (in FTGCXJ) in which case the string of bits are interpreted as 16-bit or 32-bit 2's complement signed integers. If NROWS is greater than 1 then the same set of bits will be read from sequential rows in the table starting with row FROW. Note that the numbering convention used here for the FBIT parameter adopts 1 for the first element of the > vector of bits; this is the Most Significant Bit of the integer value. - FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) - >11 Get the descriptor for a variable length column in a binary table. The descriptor consists of 2 integer parameters: the number of elements in the array and the starting offset relative to the start of the heap. The first routine returns a single descriptor whereas the second routine > returns the descriptors for a range of rows in the table. - FTGDES(unit,colnum,rownum, > nelements,offset,status) FTGDESLL(unit,colnum,rownum, > nelementsll,offsetll,status) FTGDESS(unit,colnum,firstrow,nrows > nelements,offset, status) FTGDESSLL(unit,colnum,firstrow,nrows > nelementsll,offsetll, status) - >12 Write the descriptor for a variable length column in a binary table. These subroutines can be used in conjunction with FTGDES to enable 2 or more arrays to point to the same storage location to save > storage space if the arrays are identical. - FTPDES(unit,colnum,rownum,nelements,offset, > status) FTPDESLL(unit,colnum,rownum,nelementsll,offsetll, > status) - **I. Row Selection and Calculator Routines \label{FTFROW} These routines all parse and evaluate an input string containing a user defined arithmetic expression. The first 3 routines select rows in a FITS table, based on whether the expression evaluates to true (not equal to zero) or false (zero). The other routines evaluate the expression and calculate a value for each row of the table. The allowed expression syntax is described in the row filter section in the earlier `Extended File Name Syntax' chapter of this document. The expression may also be written to a text file, and the name of the file, prepended with a '@' character may be supplied for the 'expr' parameter (e.g. '@filename.txt'). The expression in the file can be arbitrarily complex and extend over multiple lines of the file. Lines that begin with 2 slash characters ('//') will be ignored and may be used to add comments to the file. >1 Evaluate a boolean expression over the indicated rows, returning an > array of flags indicating which rows evaluated to TRUE/FALSE - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) - >>2 Find the first row which satisfies the input boolean expression - FTFFRW(unit, expr, > rownum, status) - >3 Evaluate an expression on all rows of a table. If the input and output files are not the same, copy the TRUE rows to the output file; if the output table is not empty, then this routine will append the new selected rows after the existing rows. If the >files are the same, delete the FALSE rows (preserve the TRUE rows). - FTSROW(inunit, outunit, expr, > status) - >4 Calculate an expression for the indicated rows of a table, returning the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If nulval==NULL, UNDEFs will be zeroed out. For vector results, the number of elements returned may be less than nelements if nelements is not an even multiple of the result dimension. Call FTTEXP to obtain >the dimensions of the results. - FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) - >5 Evaluate an expression and write the result either to a column (if the expression is a function of other columns in the table) or to a keyword (if the expression evaluates to a constant and is not a function of other columns in the table). In the former case, the parName parameter is the name of the column (which may or may not already exist) into which to write the results, and parInfo contains an optional TFORM keyword value if a new column is being created. If a TFORM value is not specified then a default format will be used, depending on the expression. If the expression evaluates to a constant, then the result will be written to the keyword name given by the parName parameter, and the parInfo parameter may be used to supply an optional comment for the keyword. If the keyword does not already exist, then the name of the keyword must be preceded with a '\#' character, >otherwise the result will be written to a column with that name. - FTCALC(inunit, expr, outunit, parName, parInfo, > status) - >6 This calculator routine is similar to the previous routine, except that the expression is only evaluated over the specified row ranges. nranges specifies the number of row ranges, and firstrow >and lastrow give the starting and ending row number of each range. - FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) - >7 Evaluate the given expression and return dimension and type information on the result. The returned dimensions correspond to a single row entry of the requested expression, and are equivalent to the result of fits\_read\_tdim(). Note that strings are considered to be one element regardless of string length. >If maxdim == 0, then naxes is optional. - FTTEXP(unit, expr, maxdim > datatype, nelem, naxis, naxes, status) - **J. Celestial Coordinate System Subroutines \label{FTGICS} The FITS community has adopted a set of keyword conventions that define the transformations needed to convert between pixel locations in an image and the corresponding celestial coordinates on the sky, or more generally, that define world coordinates that are to be associated with any pixel location in an n-dimensional FITS array. CFITSIO is distributed with a couple of self-contained World Coordinate System (WCS) routines, however, these routines DO NOT support all the latest WCS conventions, so it is STRONGLY RECOMMENDED that software developers use a more robust external WCS library. Several recommended libraries are: - WCSLIB - supported by Mark Calabretta WCSTools - supported by Doug Mink AST library - developed by the U.K. Starlink project - More information about the WCS keyword conventions and links to all of these WCS libraries can be found on the FITS Support Office web site at http://fits.gsfc.nasa.gov under the WCS link. The functions provided in these external WCS libraries will need access to the WCS information contained in the FITS file headers. One convenient way to pass this information to the external library is to use FITSIO to copy the header keywords into one long character string, and then pass this string to an interface routine in the external library that will extract the necessary WCS information (e.g., see the astFitsChan and astPutCards routines in the Starlink AST library). The following FITSIO routines DO NOT support the more recent WCS conventions that have been approved as part of the FITS standard. Consequently, the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED that software developers not use these routines, and instead use an external WCS library, as described above. These routines are included mainly for backward compatibility with existing software. They support the following standard map projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the legal values for the coordtype parameter). These routines are based on similar functions in Classic AIPS. All the angular quantities are given in units of degrees. >1 Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS image (i.e., the primary array or an image extension). These values may then be passed to the subroutines that perform the coordinate transformations. If any or all of the WCS keywords are not present, then default values will be returned. If the first coordinate axis is the declination-like coordinate, then this routine will swap them so that the longitudinal-like coordinate is returned as the first axis. If the file uses the newer 'CDj\_i' WCS transformation matrix keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then this routine will calculate and return the values of the equivalent old-style keywords. Note that the conversion from the new-style keywords to the old-style values is sometimes only an approximation, so if the approximation is larger than an internally defined threshold level, then CFITSIO will still return the approximate WCS keyword values, but will also return with status = 506, to warn the calling program that approximations have been made. It is then up to the calling program to decide whether the approximations are sufficiently accurate for the particular application, or whether more precise WCS transformations must be > performed using new-style WCS keywords directly. - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - >2 Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS table where the X and Y (or RA and DEC coordinates are stored in 2 separate columns of the table. These values may then be passed to the subroutines that perform the > coordinate transformations. - FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - >3 Calculate the celestial coordinate corresponding to the input > X and Y pixel location in the image. - FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) - >4 Calculate the X and Y pixel location corresponding to the input > celestial coordinate in the image. - FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) - **K. File Checksum Subroutines \label{FTPCKS} The following routines either compute or validate the checksums for the CHDU. The DATASUM keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. If there is no data unit then the value is set to zero. The numerical value is stored as an ASCII string of digits, enclosed in quotes, because the value may be too large to represent as a 32-bit signed integer. The CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. These checksum keyword conventions are based on a paper by Rob Seaman published in the proceedings of the ADASS IV conference in Baltimore in November 1994 and a later revision in June 1995. >1 Compute and write the DATASUM and CHECKSUM keyword values for the CHDU into the current header. The DATASUM value is the 32-bit checksum for the data unit, expressed as a decimal integer enclosed in single quotes. The CHECKSUM keyword value is a 16-character string which is the ASCII-encoded value for the complement of the checksum for the whole HDU. If these keywords already exist, their values will be updated only if necessary (i.e., if the file has been modified > since the original keyword values were computed). - FTPCKS(unit, > status) - >2 Update the CHECKSUM keyword value in the CHDU, assuming that the DATASUM keyword exists and already has the correct value. This routine calculates the new checksum for the current header unit, adds it to the data unit checksum, encodes the value into an ASCII string, and writes > the string to the CHECKSUM keyword. - FTUCKS(unit, > status) - >3 Verify the CHDU by computing the checksums and comparing them with the keywords. The data unit is verified correctly if the computed checksum equals the value of the DATASUM keyword. The checksum for the entire HDU (header plus data unit) is correct if it equals zero. The output DATAOK and HDUOK parameters in this subroutine are integers which will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the DATASUM or CHECKSUM keyword is not present, or value = -1 > if the computed checksum is not correct. - FTVCKS(unit, > dataok,hduok,status) - >4 Compute and return the checksum values for the CHDU (as double precision variables) without creating or modifying the CHECKSUM and DATASUM keywords. This routine is used internally by > FTVCKS, but may be useful in other situations as well. - FTGCKS(unit, > datasum,hdusum,status) - >5 Encode a checksum value (stored in a double precision variable) into a 16-character string. If COMPLEMENT = .true. then the 32-bit > sum value will be complemented before encoding. - FTESUM(sum,complement, > checksum) - >6 Decode a 16 character checksum string into a double precision value. If COMPLEMENT = .true. then the 32-bit sum value will be complemented > after decoding. - FTDSUM(checksum,complement, > sum) - **L. Date and Time Utility Routines \label{FTGSDT} The following routines help to construct or parse the FITS date/time strings. Starting in the year 2000, the FITS DATE keyword values (and the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' (date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the number of decimal places in the seconds value is optional. These times are in UTC. The older 'dd/mm/yy' date format may not be used for dates after 01 January 2000. >1 Get the current system date. The returned year has 4 digits > (1999, 2000, etc.) - FTGSDT( > day, month, year, status ) - >2 Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). The time will be in UTC/GMT if available, as indicated by a returned timeref value = 0. If the returned value of timeref = 1 then this indicates that it was not possible to convert the local time to UTC, and thus the local >time was returned. - FTGSTM(> datestr, timeref, status) - >3 Construct a date string from the input date values. If the year is between 1900 and 1998, inclusive, then the returned date string will have the old FITS format ('dd/mm/yy'), otherwise the date string will have the new FITS format ('YYYY-MM-DD'). Use FTTM2S instead > to always return a date string using the new FITS format. - FTDT2S( year, month, day, > datestr, status) - >4 Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). If the year, month, and day values all = 0 then only the time is encoded with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many decimal places of fractional seconds to include in the string. If `decimals' > is negative, then only the date will be return ('YYYY-MM-DD'). - FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) - >5 Return the date as read from the input string, where the string may be in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or >'YYYY-MM-DD') FITS format. - FTS2DT(datestr, > year, month, day, status) - >6 Return the date and time as read from the input string, where the string may be in either the old or new FITS format. The returned hours, minutes, and seconds values will be set to zero if the input string does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, the returned year, month, and date values will be set to zero if the >date is not included in the input string ('hh:mm:ss.ddd...'). - FTS2TM(datestr, > year, month, day, hour, minute, second, status) - **M. General Utility Subroutines \label{FTGHAD} The following utility subroutines may be useful for certain applications: >>1 Return the starting byte address of the CHDU and the next HDU. - FTGHAD(iunit, > curaddr, nextaddr) - >>2 Convert a character string to uppercase (operates in place). - FTUPCH(string) - >3 Compare the input template string against the reference string to see if they match. The template string may contain wildcard characters: '*' will match any sequence of characters (including zero characters) and '?' will match any single character in the reference string. The '\#' character will match any consecutive string of decimal digits (0 - 9). If CASESN = .true. then the match will be case sensitive. The returned MATCH parameter will be .true. if the 2 strings match, and EXACT will be .true. if the match is exact (i.e., if no wildcard characters were used in the match). > Both strings must be 68 characters or less in length. - FTCMPS(str_template, string, casesen, > match, exact) - >4 Test that the keyword name contains only legal characters: A-Z,0-9, > hyphen, and underscore. - FTTKEY(keyword, > status) - >5 Test that the keyword record contains only legal printable ASCII > characters - FTTREC(card, > status) - >6 Test whether the current header contains any NULL (ASCII 0) characters. These characters are illegal in the header, but they will go undetected by most of the CFITSIO keyword header routines, because the null is interpreted as the normal end-of-string terminator. This routine returns the position of the first null character in the header, or zero if there are no nulls. For example a returned value of 110 would indicate that the first NULL is located in the 30th character of the second keyword in the header (recall that each header record is 80 characters long). Note that this is one of the few FITSIO routines in which the returned > value is not necessarily equal to the status value). - FTNCHK(unit, > status) - >7 Parse a header keyword record and return the name of the keyword and the length of the name. The keyword name normally occupies the first 8 characters of the record, except under the HIERARCH convention where the name can > be up to 70 characters in length. - FTGKNM(card, > keyname, keylength, staThe '\#' character will match any consecutive string of decimal digits (0 - 9). tus) - >8 Parse a header keyword record. This subroutine parses the input header record to return the value (as a character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then the value string is returned blank and the comment string is set equal to column 9 - 80 of the > input string. - FTPSVC(card, > value,comment,status) - >9 Construct a properly formated 80-character header keyword record from the input keyword name, keyword value, and keyword comment strings. Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. The value string may contain an integer, floating point, logical, or quoted character string (e.g., "12", "15.7", "T", > or "'NGC 1313'"). - FTMKKY(keyname, value, comment, > card, status) - >10 Construct a sequence keyword name (ROOT + nnn). This subroutine appends the sequence number to the root string to create > a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') - FTKEYN(keyroot,seq_no, > keyword,status) - >11 Construct a sequence keyword name (n + ROOT). This subroutine concatenates the sequence number to the front of the > root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') - FTNKEY(seq_no,keyroot, > keyword,status) - >12 Determine the datatype of a keyword value string. This subroutine parses the keyword value string (usually columns 11-30 > of the header record) to determine its datatype. - FTDTYP(value, > dtype,status) - >13 Return the class of input header record. The record is classified into one of the following categories (the class values are defined in fitsio.h). Note that this is one of the few FITSIO > routines that does not return a status value. - Class Value Keywords TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY 20 The keywords used in the compressed image or table format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY 40 BLANK, TNULLn TYP_DIM_KEY 50 TDIMn TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY 70 BUNIT, TUNITn TYP_DISP_KEY 80 TDISPn TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY 100 CHECKSUM, DATASUM TYP_WCS_KEY 110 CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn (i,j,m,n are integers, s is any letter) TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY 140 CONTINUE TYP_USER_KEY 150 all other keywords class = FTGKCL (char *card) - >14 Parse the 'TFORM' binary table column format string. This subroutine parses the input TFORM character string and returns the integer datatype code, the repeat count of the field, and, in the case of character string fields, the length of the unit string. The following datatype codes are returned (the negative of the value is returned > if the column contains variable-length arrays): - Datatype DATACODE value bit, X 1 byte, B 11 logical, L 14 ASCII character, A 16 short integer, I 21 integer, J 41 real, E 42 double precision, D 82 complex 83 double complex 163 FTBNFM(tform, > datacode,repeat,width,status) - >15 Parse the 'TFORM' keyword value that defines the column format in an ASCII table. This routine parses the input TFORM character string and returns the datatype code, the width of the column, and (if it is a floating point column) the number of decimal places to the right of the decimal point. The returned datatype codes are the same as for the binary table, listed above, with the following additional rules: integer columns that are between 1 and 4 characters wide are defined to be short integers (code = 21). Wider integer columns are defined to be regular integers (code = 41). Similarly, Fixed decimal point columns (with TFORM = 'Fw.d') are defined to be single precision reals (code = 42) if w is between 1 and 7 characters wide, inclusive. Wider 'F' columns will return a double precision data code (= 82). 'Ew.d' format columns will have datacode = 42, > and 'Dw.d' format columns will have datacode = 82. - FTASFM(tform, > datacode,width,decimals,status) - >16 Calculate the starting column positions and total ASCII table width based on the input array of ASCII table TFORM values. The SPACE input parameter defines how many blank spaces to leave between each column (it is recommended to have one space between columns for better human > readability). - FTGABC(tfields,tform,space, > rowlen,tbcol,status) - >17 Parse a template string and return a formatted 80-character string suitable for appending to (or deleting from) a FITS header file. This subroutine is useful for parsing lines from an ASCII template file and reformatting them into legal FITS header records. The formatted string may then be passed to the FTPREC, FTMCRD, or FTDKEY subroutines > to append or modify a FITS header record. - FTGTHD(template, > card,hdtype,status) - The input TEMPLATE character string generally should contain 3 tokens: (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The TEMPLATE string must adhere to the following format: >- The KEYNAME token must begin in columns 1-8 and be a maximum of 8 characters long. If the first 8 characters of the template line are blank then the remainder of the line is considered to be a FITS comment (with a blank keyword name). A legal FITS keyword name may only contain the characters A-Z, 0-9, and '-' (minus sign) and underscore. This subroutine will automatically convert any lowercase characters to uppercase in the output string. If KEYNAME = 'COMMENT' or 'HISTORY' then the remainder of the line is considered to be a FITS > COMMENT or HISTORY record, respectively. >- The VALUE token must be separated from the KEYNAME token by one or more spaces and/or an '=' character. The datatype of the VALUE token (numeric, logical, or character string) is automatically determined and the output CARD string is formatted accordingly. The value token may be forced to be interpreted as a string (e.g. if it is a string of numeric digits) by enclosing it in single quotes. If the value token is a character string that contains 1 or more embedded blank space characters or slash ('/') characters then the > entire character string must be enclosed in single quotes. >- The COMMENT token is optional, but if present must be separated from > the VALUE token by a blank space or a '/' character. >- One exception to the above rules is that if the first non-blank character in the template string is a minus sign ('-') followed by a single token, or a single token followed by an equal sign, then it is interpreted as the name of a keyword which is to be > deleted from the FITS header. >- The second exception is that if the template string starts with a minus sign and is followed by 2 tokens then the second token is interpreted as the new name for the keyword specified by first token. In this case the old keyword name (first token) is returned in characters 1-8 of the returned CARD string, and the new keyword name (the second token) is returned in characters 41-48 of the returned CARD string. These old and new names may then be passed to the FTMNAM subroutine which will change > the keyword name. The HDTYPE output parameter indicates how the returned CARD string should be interpreted: - hdtype interpretation ------ ------------------------------------------------- -2 Modify the name of the keyword given in CARD(1:8) to the new name given in CARD(41:48) -1 CARD(1:8) contains the name of a keyword to be deleted from the FITS header. 0 append the CARD string to the FITS header if the keyword does not already exist, otherwise update the value/comment if the keyword is already present in the header. 1 simply append this keyword to the FITS header (CARD is either a HISTORY or COMMENT keyword). 2 This is a FITS END record; it should not be written to the FITS header because FITSIO automatically appends the END record when the header is closed. - EXAMPLES: The following lines illustrate valid input template strings: - INTVAL 7 This is an integer keyword RVAL 34.6 / This is a floating point keyword EVAL=-12.45E-03 This is a floating point keyword in exponential notation lval F This is a boolean keyword This is a comment keyword with a blank keyword name SVAL1 = 'Hello world' / this is a string keyword SVAL2 '123.5' this is also a string keyword sval3 123+ / this is also a string keyword with the value '123+ ' # the following template line deletes the DATE keyword - DATE # the following template line modifies the NAME keyword to OBJECT - NAME OBJECT - >18 Parse the input string containing a list of rows or row ranges, and return integer arrays containing the first and last row in each range. For example, if rowlist = "3-5, 6, 8-9" then it will return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. At most, 'maxranges' number of ranges will be returned. 'maxrows' is the maximum number of rows in the table; any rows or ranges larger than this will be ignored. The rows must be specified in increasing order, and the ranges must not overlap. A minus sign may be use to specify all the rows to the upper or lower bound, so "50-" means all the rows from 50 to the end of the table, and "-" > means all the rows in the table, from 1 - maxrows. - FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) - *VI. The CFITSIO Iterator Function The fits\_iterate\_data function in CFITSIO provides a unique method of executing an arbitrary user-supplied `work' function that operates on rows of data in FITS tables or on pixels in FITS images. Rather than explicitly reading and writing the FITS images or columns of data, one instead calls the CFITSIO iterator routine, passing to it the name of the user's work function that is to be executed along with a list of all the table columns or image arrays that are to be passed to the work function. The CFITSIO iterator function then does all the work of allocating memory for the arrays, reading the input data from the FITS file, passing them to the work function, and then writing any output data back to the FITS file after the work function exits. Because it is often more efficient to process only a subset of the total table rows at one time, the iterator function can determine the optimum amount of data to pass in each iteration and repeatedly call the work function until the entire table been processed. For many applications this single CFITSIO iterator function can effectively replace all the other CFITSIO routines for reading or writing data in FITS images or tables. Using the iterator has several important advantages over the traditional method of reading and writing FITS data files: \begin{itemize} \item It cleanly separates the data I/O from the routine that operates on the data. This leads to a more modular and `object oriented' programming style. \item It simplifies the application program by eliminating the need to allocate memory for the data arrays and eliminates most of the calls to the CFITSIO routines that explicitly read and write the data. \item It ensures that the data are processed as efficiently as possible. This is especially important when processing tabular data since the iterator function will calculate the most efficient number of rows in the table to be passed at one time to the user's work function on each iteration. \item Makes it possible for larger projects to develop a library of work functions that all have a uniform calling sequence and are all independent of the details of the FITS file format. \end{itemize} There are basically 2 steps in using the CFITSIO iterator function. The first step is to design the work function itself which must have a prescribed set of input parameters. One of these parameters is a structure containing pointers to the arrays of data; the work function can perform any desired operations on these arrays and does not need to worry about how the input data were read from the file or how the output data get written back to the file. The second step is to design the driver routine that opens all the necessary FITS files and initializes the input parameters to the iterator function. The driver program calls the CFITSIO iterator function which then reads the data and passes it to the user's work function. Further details on using the iterator function can be found in the companion CFITSIO User's Guide, and in the iter\_a.f, iter\_b.f and iter\_c.f example programs. *IV. Extended File Name Syntax **A. Overview CFITSIO supports an extended syntax when specifying the name of the data file to be opened or created that includes the following features: \begin{itemize} \item CFITSIO can read IRAF format images which have header file names that end with the '.imh' extension, as well as reading and writing FITS files, This feature is implemented in CFITSIO by first converting the IRAF image into a temporary FITS format file in memory, then opening the FITS file. Any of the usual CFITSIO routines then may be used to read the image header or data. Similarly, raw binary data arrays can be read by converting them on the fly into virtual FITS images. \item FITS files on the Internet can be read (and sometimes written) using the FTP, HTTP, or ROOT protocols. \item FITS files can be piped between tasks on the stdin and stdout streams. \item FITS files can be read and written in shared memory. This can potentially achieve much better data I/O performance compared to reading and writing the same FITS files on magnetic disk. \item Compressed FITS files in gzip or Unix COMPRESS format can be directly read. \item Output FITS files can be written directly in compressed gzip format, thus saving disk space. \item FITS table columns can be created, modified, or deleted 'on-the-fly' as the table is opened by CFITSIO. This creates a virtual FITS file containing the modifications that is then opened by the application program. \item Table rows may be selected, or filtered out, on the fly when the table is opened by CFITSIO, based on an arbitrary user-specified expression. Only rows for which the expression evaluates to 'TRUE' are retained in the copy of the table that is opened by the application program. \item Histogram images may be created on the fly by binning the values in table columns, resulting in a virtual N-dimensional FITS image. The application program then only sees the FITS image (in the primary array) instead of the original FITS table. \end{itemize} The latter 3 features in particular add very powerful data processing capabilities directly into CFITSIO, and hence into every task that uses CFITSIO to read or write FITS files. For example, these features transform a very simple program that just copies an input FITS file to a new output file (like the `fitscopy' program that is distributed with CFITSIO) into a multipurpose FITS file processing tool. By appending fairly simple qualifiers onto the name of the input FITS file, the user can perform quite complex table editing operations (e.g., create new columns, or filter out rows in a table) or create FITS images by binning or histogramming the values in table columns. In addition, these functions have been coded using new state-of-the art algorithms that are, in some cases, 10 - 100 times faster than previous widely used implementations. Before describing the complete syntax for the extended FITS file names in the next section, here are a few examples of FITS file names that give a quick overview of the allowed syntax: \begin{itemize} \item {\tt 'myfile.fits'}: the simplest case of a FITS file on disk in the current directory. \item {\tt 'myfile.imh'}: opens an IRAF format image file and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 short integer array in this case) and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' suffix will cause it to be compressed in gzip format when it is written to disk. \item {\tt 'myfile.fits.gz[events, 2]'}: opens and uncompresses the gzipped file myfile.fits then moves to the extension which has the keywords EXTNAME = 'EVENTS' and EXTVER = 2. \item {\tt '-'}: a dash (minus sign) signifies that the input file is to be read from the stdin file stream, or that the output file is to be written to the stdout stream. \item {\tt 'ftp://legacy.gsfc.nasa.gov/test/vela.fits'}: FITS files in any ftp archive site on the Internet may be directly opened with read-only access. \item {\tt 'http://legacy.gsfc.nasa.gov/software/test.fits'}: any valid URL to a FITS file on the Web may be opened with read-only access. \item {\tt 'root://legacy.gsfc.nasa.gov/test/vela.fits'}: similar to ftp access except that it provides write as well as read access to the files across the network. This uses the root protocol developed at CERN. \item {\tt 'shmem://h2[events]'}: opens the FITS file in a shared memory segment and moves to the EVENTS extension. \item {\tt 'mem://'}: creates a scratch output file in core computer memory. The resulting 'file' will disappear when the program exits, so this is mainly useful for testing purposes when one does not want a permanent copy of the output file. \item {\tt 'myfile.fits[3; Images(10)]'}: opens a copy of the image contained in the 10th row of the 'Images' column in the binary table in the 3th extension of the FITS file. The application just sees this single image as the primary array. \item {\tt 'myfile.fits[1:512:2, 1:512:2]'}: opens a section of the input image ranging from the 1st to the 512th pixel in X and Y, and selects every second pixel in both dimensions, resulting in a 256 x 256 pixel image in this case. \item {\tt 'myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]'}: creates and opens a temporary file on the fly (in memory or on disk) that is identical to myfile.fits except that it will contain a new column in the EVENTS extension called 'Rad' whose value is computed using the indicated expression which is a function of the values in the X and Y columns. \item {\tt 'myfile.fits[EVENTS][PHA > 5]'}: creates and opens a temporary FITS files that is identical to 'myfile.fits' except that the EVENTS table will only contain the rows that have values of the PHA column greater than 5. In general, any arbitrary boolean expression using a C or Fortran-like syntax, which may combine AND and OR operators, may be used to select rows from a table. \item {\tt 'myfile.fits[EVENTS][bin (X,Y)=1,2048,4]'}: creates a temporary FITS primary array image which is computed on the fly by binning (i.e, computing the 2-dimensional histogram) of the values in the X and Y columns of the EVENTS extension. In this case the X and Y coordinates range from 1 to 2048 and the image pixel size is 4 units in both dimensions, so the resulting image is 512 x 512 pixels in size. \item The final example combines many of these feature into one complex expression (it is broken into several lines for clarity): - 'ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] [bin (X,Y)=32]' - In this case, CFITSIO (1) copies and uncompresses the FITS file from the ftp site on the legacy machine, (2) moves to the 'EVENTS' extension, (3) calculates a new column called 'phacorr', (4) selects the rows in the table that have phacorr in the range 5 to 14, and finally (5) bins the remaining rows on the X and Y column coordinates, using a pixel size = 32 to create a 2D image. All this processing is completely transparent to the application program, which simply sees the final 2-D image in the primary array of the opened file. \end{itemize} The full extended CFITSIO FITS file name can contain several different components depending on the context. These components are described in the following sections: - When creating a new file: filetype://BaseFilename(templateName) When opening an existing primary array or image HDU: filetype://BaseFilename(outName)[HDUlocation][ImageSection] When opening an existing table HDU: filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] - The filetype, BaseFilename, outName, HDUlocation, and ImageSection components, if present, must be given in that order, but the colFilter, rowFilter, and binSpec specifiers may follow in any order. Regardless of the order, however, the colFilter specifier, if present, will be processed first by CFITSIO, followed by the rowFilter specifier, and finally by the binSpec specifier. **A. Filetype The type of file determines the medium on which the file is located (e.g., disk or network) and, hence, which internal device driver is used by CFITSIO to read and/or write the file. Currently supported types are - file:// - file on local magnetic disk (default) ftp:// - a readonly file accessed with the anonymous FTP protocol. It also supports ftp://username:password@hostname/... for accessing password-protected ftp sites. http:// - a readonly file accessed with the HTTP protocol. It supports username:password just like the ftp driver. Proxy HTTP servers are supported using the http_proxy environment variable (see following note). stream:// - special driver to read an input FITS file from the stdin stream, and/or write an output FITS file to the stdout stream. This driver is fragile and has limited functionality (see the following note). gsiftp:// - access files on a computational grid using the gridftp protocol in the Globus toolkit (see following note). root:// - uses the CERN root protocol for writing as well as reading files over the network. shmem:// - opens or creates a file which persists in the computer's shared memory. mem:// - opens a temporary file in core memory. The file disappears when the program exits so this is mainly useful for test purposes when a permanent output file is not desired. - If the filetype is not specified, then type file:// is assumed. The double slashes '//' are optional and may be omitted in most cases. ***1. Notes about HTTP proxy servers A proxy HTTP server may be used by defining the address (URL) and port number of the proxy server with the http\_proxy environment variable. For example - setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 - will cause CFITSIO to use port 3128 on the heasarc proxy server whenever reading a FITS file with HTTP. ***2. Notes about the stream filetype driver The stream driver can be used to efficiently read a FITS file from the stdin file stream or write a FITS to the stdout file stream. However, because these input and output streams must be accessed sequentially, the FITS file reading or writing application must also read and write the file sequentially, at least within the tolerances described below. CFITSIO supports 2 different methods for accessing FITS files on the stdin and stdout streams. The original method, which is invoked by specifying a dash character, "-", as the name of the file when opening or creating it, works by storing a complete copy of the entire FITS file in memory. In this case, when reading from stdin, CFITSIO will copy the entire stream into memory before doing any processing of the file. Similarly, when writing to stdout, CFITSIO will create a copy of the entire FITS file in memory, before finally flushing it out to the stdout stream when the FITS file is closed. Buffering the entire FITS file in this way allows the application to randomly access any part of the FITS file, in any order, but it also requires that the user have sufficient available memory (or virtual memory) to store the entire file, which may not be possible in the case of very large files. The newer stream filetype provides a more memory-efficient method of accessing FITS files on the stdin or stdout streams. Instead of storing a copy of the entire FITS file in memory, CFITSIO only uses a set of internal buffer which by default can store 40 FITS blocks, or about 100K bytes of the FITS file. The application program must process the FITS file sequentially from beginning to end, within this 100K buffer. Generally speaking the application program must conform to the following restrictions: \begin{itemize} \item The program must finish reading or writing the header keywords before reading or writing any data in the HDU. \item The HDU can contain at most about 1400 header keywords. This is the maximum that can fit in the nominal 40 FITS block buffer. In principle, this limit could be increased by recompiling CFITSIO with a larger buffer limit, which is set by the NIOBUF parameter in fitsio2.h. \item The program must read or write the data in a sequential manner from the beginning to the end of the HDU. Note that CFITSIO's internal 100K buffer allows a little latitude in meeting this requirement. \item The program cannot move back to a previous HDU in the FITS file. \item Reading or writing of variable length array columns in binary tables is not supported on streams, because this requires moving back and forth between the fixed-length portion of the binary table and the following heap area where the arrays are actually stored. \item Reading or writing of tile-compressed images is not supported on streams, because the images are internally stored using variable length arrays. \end{itemize} ***3. Notes about the gsiftp filetype DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. There are two different ways to install GT: 1) goto the globus toolkit web page www.globus.org and follow the download and compilation instructions; 2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ and follow the instructions (STRONGLY SUGGESTED); Once a globus client has been installed in your system with a specific flavour it is possible to compile and install the CFITSIO libraries. Specific configuration flags must be used: 1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support PATH=GLOBUS\_LOCATION i.e. the location of your globus installation 2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour ex. gcc32 Both the flags must be used and it is mandatory to set both the PATH and the flavour. USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: example: gsiftp://remote\_server\_fqhn/directory/filename The gridftp driver uses a local buffer on a temporary file the file is located in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). Grid FTP supports multi channel transfer. By default a single channel transmission is available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS environment variable (ex. export GSIFTP\_STREAMS=8). ***4. Notes about the root filetype The original rootd server can be obtained from: \verb-ftp://root.cern.ch/root/rootd.tar.gz- but, for it to work correctly with CFITSIO one has to use a modified version which supports a command to return the length of the file. This modified version is available in rootd subdirectory in the CFITSIO ftp area at - ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. - This small server is started either by inetd when a client requests a connection to a rootd server or by hand (i.e. from the command line). The rootd server works with the ROOT TNetFile class. It allows remote access to ROOT database files in either read or write mode. By default TNetFile assumes port 432 (which requires rootd to be started as root). To run rootd via inetd add the following line to /etc/services: - rootd 432/tcp - and to /etc/inetd.conf, add the following line: - rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i - Force inetd to reread its conf file with "kill -HUP ". You can also start rootd by hand running directly under your private account (no root system privileges needed). For example to start rootd listening on port 5151 just type: \verb+rootd -p 5151+ Notice: no \& is needed. Rootd will go into background by itself. - Rootd arguments: -i says we were started by inetd -p port# specifies a different port to listen on -d level level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum - Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root): - - Add the following line to /etc/passwd: rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false where you may modify the uid, gid (71, 72) and the home directory to suite your system. - Add the following line to /etc/group: rootd:*:72:rootd where the gid must match the gid in /etc/passwd. - Create the directories: mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmp Where /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry. - To make writeable directories for anonymous do, for example: mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub - That's all. Several additional remarks: you can login to an anonymous server either with the names "anonymous" or "rootd". The password should be of type user@host.do.main. Only the @ is enforced for the time being. In anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed. Anonymous mode only works when the server is started via inetd. ***5. Notes about the shmem filetype: Shared memory files are currently supported on most Unix platforms, where the shared memory segments are managed by the operating system kernel and `live' independently of processes. They are not deleted (by default) when the process which created them terminates, although they will disappear if the system is rebooted. Applications can create shared memory files in CFITSIO by calling: - fit_create_file(&fitsfileptr, "shmem://h2", &status); - where the root `file' names are currently restricted to be 'h0', 'h1', 'h2', 'h3', etc., up to a maximum number defined by the the value of SHARED\_MAXSEG (equal to 16 by default). This is a prototype implementation of the shared memory interface and a more robust interface, which will have fewer restrictions on the number of files and on their names, may be developed in the future. When opening an already existing FITS file in shared memory one calls the usual CFITSIO routine: - fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) - The file mode can be READWRITE or READONLY just as with disk files. More than one process can operate on READONLY mode files at the same time. CFITSIO supports proper file locking (both in READONLY and READWRITE modes), so calls to fits\_open\_file may be locked out until another other process closes the file. When an application is finished accessing a FITS file in a shared memory segment, it may close it (and the file will remain in the system) with fits\_close\_file, or delete it with fits\_delete\_file. Physical deletion is postponed until the last process calls ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on the file to be deleted, thus it can be blocked if the object was not opened in READWRITE mode. A shared memory management utility program called `smem', is included with the CFITSIO distribution. It can be built by typing `make smem'; then type `smem -h' to get a list of valid options. Executing smem without any options causes it to list all the shared memory segments currently residing in the system and managed by the shared memory driver. To get a list of all the shared memory objects, run the system utility program `ipcs [-a]'. **B. Base Filename The base filename is the name of the file optionally including the director/subdirectory path, and in the case of `ftp', `http', and `root' filetypes, the machine identifier. Examples: - myfile.fits !data.fits /data/myfile.fits fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz - When creating a new output file on magnetic disk (of type file://) if the base filename begins with an exclamation point (!) then any existing file with that same basename will be deleted prior to creating the new FITS file. Otherwise if the file to be created already exists, then CFITSIO will return an error and will not overwrite the existing file. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. An input FITS file may be compressed with the gzip or Unix compress algorithms, in which case CFITSIO will uncompress the file on the fly into a temporary file (in memory or on disk). Compressed files may only be opened with read-only permission. When specifying the name of a compressed FITS file it is not necessary to append the file suffix (e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name without the suffix, then it will automatically search for a compressed file with the same root name. In the case of reading ftp and http type files, CFITSIO generally looks for a compressed version of the file first, before trying to open the uncompressed file. By default, CFITSIO copies (and uncompressed if necessary) the ftp or http FITS file into memory on the local machine before opening it. This will fail if the local machine does not have enough memory to hold the whole FITS file, so in this case, the output filename specifier (see the next section) can be used to further control how CFITSIO reads ftp and http files. If the input file is an IRAF image file (*.imh file) then CFITSIO will automatically convert it on the fly into a virtual FITS image before it is opened by the application program. IRAF images can only be opened with READONLY file access. Similarly, if the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program (with READONLY access). In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. rawfile.dat[ib512,512]). The first character (case insensitive) defines the datatype of the array: - b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point - An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These datatype characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: - raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header - One special case of input file is where the filename = `-' (a dash or minus sign) or 'stdin' or 'stdout', which signifies that the input file is to be read from the stdin stream, or written to the stdout stream if a new output file is being created. In the case of reading from stdin, CFITSIO first copies the whole stream into a temporary FITS file (in memory or on disk), and subsequent reading of the FITS file occurs in this copy. When writing to stdout, CFITSIO first constructs the whole file in memory (since random access is required), then flushes it out to the stdout stream when the file is closed. In addition, if the output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed before being written to stdout. This ability to read and write on the stdin and stdout steams allows FITS files to be piped between tasks in memory rather than having to create temporary intermediate FITS files on disk. For example if task1 creates an output FITS file, and task2 reads an input FITS file, the FITS file may be piped between the 2 tasks by specifying - task1 - | task2 - - where the vertical bar is the Unix piping symbol. This assumes that the 2 tasks read the name of the FITS file off of the command line. **C. Output File Name when Opening an Existing File An optional output filename may be specified in parentheses immediately following the base file name to be opened. This is mainly useful in those cases where CFITSIO creates a temporary copy of the input FITS file before it is opened and passed to the application program. This happens by default when opening a network FTP or HTTP-type file, when reading a compressed FITS file on a local disk, when reading from the stdin stream, or when a column filter, row filter, or binning specifier is included as part of the input file specification. By default this temporary file is created in memory. If there is not enough memory to create the file copy, then CFITSIO will exit with an error. In these cases one can force a permanent file to be created on disk, instead of a temporary file in memory, by supplying the name in parentheses immediately following the base file name. The output filename can include the '!' clobber flag. Thus, if the input filename to CFITSIO is: \verb+file1.fits.gz(file2.fits)+ then CFITSIO will uncompress `file1.fits.gz' into the local disk file `file2.fits' before opening it. CFITSIO does not automatically delete the output file, so it will still exist after the application program exits. In some cases, several different temporary FITS files will be created in sequence, for instance, if one opens a remote file using FTP, then filters rows in a binary table extension, then create an image by binning a pair of columns. In this case, the remote file will be copied to a temporary local file, then a second temporary file will be created containing the filtered rows of the table, and finally a third temporary file containing the binned image will be created. In cases like this where multiple files are created, the outfile specifier will be interpreted the name of the final file as described below, in descending priority: \begin{itemize} \item as the name of the final image file if an image within a single binary table cell is opened or if an image is created by binning a table column. \item as the name of the file containing the filtered table if a column filter and/or a row filter are specified. \item as the name of the local copy of the remote FTP or HTTP file. \item as the name of the uncompressed version of the FITS file, if a compressed FITS file on local disk has been opened. \item otherwise, the output filename is ignored. \end{itemize} The output file specifier is useful when reading FTP or HTTP-type FITS files since it can be used to create a local disk copy of the file that can be reused in the future. If the output file name = `*' then a local file with the same name as the network file will be created. Note that CFITSIO will behave differently depending on whether the remote file is compressed or not as shown by the following examples: \begin{itemize} \item `ftp://remote.machine/tmp/myfile.fits.gz(*)' - the remote compressed file is copied to the local compressed file `myfile.fits.gz', which is then uncompressed in local memory before being opened and passed to the application program. \item `ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)' - the remote compressed file is copied and uncompressed into the local file `myfile.fits'. This example requires less local memory than the previous example since the file is uncompressed on disk instead of in memory. \item `ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)' - this will usually produce an error since CFITSIO itself cannot compress files. \end{itemize} The exact behavior of CFITSIO in the latter case depends on the type of ftp server running on the remote machine and how it is configured. In some cases, if the file `myfile.fits.gz' exists on the remote machine, then the server will copy it to the local machine. In other cases the ftp server will automatically create and transmit a compressed version of the file if only the uncompressed version exists. This can get rather confusing, so users should use a certain amount of caution when using the output file specifier with FTP or HTTP file types, to make sure they get the behavior that they expect. **D. Template File Name when Creating a New File When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described below. **E. Image Tile-Compression Specification When specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format (see section 5.5, ``Primary Array or IMAGE Extension I/O Routines'') by enclosing the compression parameters in square brackets following the root disk file name. Here are some examples of the syntax for specifying tile-compressed output images: - myfile.fit[compress] - use Rice algorithm and default tile size myfile.fit[compress GZIP] - use the specified compression algorithm; myfile.fit[compress Rice] only the first letter of the algorithm myfile.fit[compress PLIO] name is required. myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 - **F. HDU Location Specification The optional HDU location specifier defines which HDU (Header-Data Unit, also known as an `extension') within the FITS file to initially open. It must immediately follow the base file name (or the output file name if present). If it is not specified then the first HDU (the primary array) is opened. The HDU location specifier is required if the colFilter, rowFilter, or binSpec specifiers are present, because the primary array is not a valid HDU for these operations. The HDU may be specified either by absolute position number, starting with 0 for the primary array, or by reference to the HDU name, and optionally, the version number and the HDU type of the desired extension. The location of an image within a single cell of a binary table may also be specified, as described below. The absolute position of the extension is specified either by enclosed the number in square brackets (e.g., `[1]' = the first extension following the primary array) or by preceded the number with a plus sign (`+1'). To specify the HDU by name, give the name of the desired HDU (the value of the EXTNAME or HDUNAME keyword) and optionally the extension version number (value of the EXTVER keyword) and the extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, or BINTABLE), separated by commas and all enclosed in square brackets. If the value of EXTVER and XTENSION are not specified, then the first extension with the correct value of EXTNAME is opened. The extension name and type are not case sensitive, and the extension type may be abbreviated to a single letter (e.g., I = IMAGE extension or primary array, A or T = ASCII table extension, and B = binary table BINTABLE extension). If the HDU location specifier is equal to `[PRIMARY]' or `[P]', then the primary array (the first HDU) will be opened. FITS images are most commonly stored in the primary array or an image extension, but images can also be stored as a vector in a single cell of a binary table (i.e. each row of the vector column contains a different image). Such an image can be opened with CFITSIO by specifying the desired column name and the row number after the binary table HDU specifier as shown in the following examples. The column name is separated from the HDU specifier by a semicolon and the row number is enclosed in parentheses. In this case CFITSIO copies the image from the table cell into a temporary primary array before it is opened. The application program then just sees the image in the primary array, without any extensions. The particular row to be opened may be specified either by giving an absolute integer row number (starting with 1 for the first row), or by specifying a boolean expression that evaluates to TRUE for the desired row. The first row that satisfies the expression will be used. The row selection expression has the same syntax as described in the Row Filter Specifier section, below. Examples: - myfile.fits[3] - open the 3rd HDU following the primary array myfile.fits+3 - same as above, but using the FTOOLS-style notation myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' column in the 3rd extension of the file. myfile.fits[3; images(exposure > 100)] - as above, but opens the image in the first row that has an 'exposure' column value greater than 100. - **G. Image Section A virtual file containing a rectangular subsection of an image can be extracted and opened by specifying the range of pixels (start:end) along each axis to be extracted from the original image. One can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the start pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. The input image can be in the primary array, in an image extension, or contained in a vector cell of a binary table. In the later 2 cases the extension name or number must be specified before the image section specifier. Examples: - myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image consisting of the odd numbered columns (1st axis) and the even numbered rows (2nd axis) of the image in the primary array of the file. myfile.fits[*, 512:256] - open an image consisting of all the columns in the input image, but only rows 256 through 512. The image will be flipped along the 2nd axis since the starting pixel is greater than the ending pixel. myfile.fits[*:2, 512:256:2] - same as above but keeping only every other row and column in the input image. myfile.fits[-*, *] - copy the entire image, flipping it along the first axis. myfile.fits[3][1:256,1:256] - opens a subsection of the image that is in the 3rd extension of the file. myfile.fits[4; images(12)][1:10,1:10] - open an image consisting of the first 10 pixels in both dimensions. The original image resides in the 12th row of the 'images' vector column in the table in the 4th extension of the file. - When CFITSIO opens an image section it first creates a temporary file containing the image section plus a copy of any other HDUs in the file. This temporary file is then opened by the application program, so it is not possible to write to or modify the input file when specifying an image section. Note that CFITSIO automatically updates the world coordinate system keywords in the header of the image section, if they exist, so that the coordinate associated with each pixel in the image section will be computed correctly. **H. Image Transform Filters CFITSIO can apply a user-specified mathematical function to the value of every pixel in a FITS image, thus creating a new virtual image in computer memory that is then opened and read by the application program. The original FITS image is not modified by this process. The image transformation specifier is appended to the input FITS file name and is enclosed in square brackets. It begins with the letters 'PIX' to distinguish it from other types of FITS file filters that are recognized by CFITSIO. The image transforming function may use any of the mathematical operators listed in the following 'Row Filtering Specification' section of this document. Some examples of image transform filters are: - [pix X * 2.0] - multiply each pixel by 2.0 [pix sqrt(X)] - take the square root of each pixel [pix X + #ZEROPT - add the value of the ZEROPT keyword [pix X>0 ? log10(X) : -99.] - if the pixel value is greater than 0, compute the base 10 log, else set the pixel = -99. - Use the letter 'X' in the expression to represent the current pixel value in the image. The expression is evaluated independently for each pixel in the image and may be a function of 1) the original pixel value, 2) the value of other pixels in the image at a given relative offset from the position of the pixel that is being evaluated, and 3) the value of any header keywords. Header keyword values are represented by the name of the keyword preceded by the '\#' sign. To access the the value of adjacent pixels in the image, specify the (1-D) offset from the current pixel in curly brackets. For example - [pix (x{-1} + x + x{+1}) / 3] - will replace each pixel value with the running mean of the values of that pixel and it's 2 neighboring pixels. Note that in this notation the image is treated as a 1-D array, where each row of the image (or higher dimensional cube) is appended one after another in one long array of pixels. It is possible to refer to pixels in the rows above or below the current pixel by using the value of the NAXIS1 header keyword. For example - [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] - will compute the mean of each image pixel and the pixels immediately above and below it in the adjacent rows of the image. The following more complex example creates a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels: - [pix (X + X{-1} + X{+1} + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] - If the pixel offset extends beyond the first or last pixel in the image, the function will evaluate to undefined, or NULL. For complex or commonly used image filtering operations, one can write the expression into an external text file and then import it into the filter using the syntax '[pix @filename.txt]'. The mathematical expression can extend over multiple lines of text in the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. By default, the datatype of the resulting image will be the same as the original image, but one may force a different datatype by appended a code letter to the 'pix' keyword: - pixb - 8-bit byte image with BITPIX = 8 pixi - 16-bit integer image with BITPIX = 16 pixj - 32-bit integer image with BITPIX = 32 pixr - 32-bit float image with BITPIX = -32 pixd - 64-bit float image with BITPIX = -64 - Also by default, any other HDUs in the input file will be copied without change to the output virtual FITS file, but one may discard the other HDUs by adding the number '1' to the 'pix' keyword (and following any optional datatype code letter). For example: - myfile.fits[3][pixr1 sqrt(X)] - will create a virtual FITS file containing only a primary array image with 32-bit floating point pixels that have a value equal to the square root of the pixels in the image that is in the 3rd extension of the 'myfile.fits' file. **I. Column and Keyword Filtering Specification The optional column/keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. This filtering specifier must be enclosed in square brackets and can be distinguished from a general row filter specifier (described below) by the fact that it begins with the string 'col ' and is not immediately followed by an equals sign. The original file is not changed by this filtering operation, and instead the modifications are made on a copy of the input FITS file (usually in memory), which also contains a copy of all the other HDUs in the file. This temporary file is passed to the application program and will persist only until the file is closed or until the program exits, unless the outfile specifier (see above) is also supplied. The column/keyword filter can be used to perform the following operations. More than one operation may be specified by separating them with commas or semi-colons. \begin{itemize} \item Copy only a specified list of columns columns to the filtered input file. The list of column name should be separated by commas or semi-colons. Wild card characters may be used in the column names to match multiple columns. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table (i.e., there is no need to explicitly list the columns to be included if any columns are being deleted). \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME column if it exists, otherwise the TIME keyword. An error is returned if neither a column nor keyword with this name exists. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. \item Rename an existing column or keyword with the syntax 'NewName == OldName'. An error is returned if neither a column nor keyword with this name exists. \item Append a new column or keyword to the table. To create a column, give the new name, optionally followed by the datatype in parentheses, followed by a single equals sign and an expression to be used to compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit integer column called 'newcol' filled with zeros). The datatype is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is not specified then an appropriate datatype will be chosen depending on the form of the expression (may be a character string, logical, bit, long integer, or double column). An appropriate vector count (in the case of binary tables) will also be added if not explicitly specified. When creating a new keyword, the keyword name must be preceded by a pound sign '\#', and the expression must evaluate to a scalar (i.e., cannot have a column name in the expression). The comment string for the keyword may be specified in parentheses immediately following the keyword name (instead of supplying a datatype as in the case of creating a new column). If the keyword name ends with a pound sign '\#', then cfitsio will substitute the number of the most recently referenced column for the \# character . This is especially useful when writing a column-related keyword like TUNITn for a newly created column, as shown in the following examples. COMMENT and HISTORY keywords may also be created with the following syntax: - #COMMENT = 'This is a comment keyword' #HISTORY = 'This is a history keyword' - Note that the equal sign and the quote characters will be removed, so that the resulting header keywords in these cases will look like this: - COMMENT This is a comment keyword HISTORY This is a history keyword - These two special keywords are always appended to the end of the header and will not affect any previously existing COMMENT or HISTORY keywords. \item Recompute (overwrite) the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \end{itemize} The expression that is used when appending or recomputing columns or keywords can be arbitrarily complex and may be a function of other header keyword values and other columns (in the same row). The full syntax and available functions for the expression are described below in the row filter specification section. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table. If no columns to be deleted are specified, then only the columns that are explicitly listed will be included in the filtered output table. To include all the columns, add the '*' wildcard specifier at the end of the list, as shown in the examples. For complex or commonly used operations, one can also place the operations into an external text file and import it into the column filter using the syntax '[col @filename.txt]'. The operations can extend over multiple lines of the file, but multiple operations must still be separated by commas or semi-colons. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: - [col Time, rate] - only the Time and rate columns will appear in the filtered input file. [col Time, *raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME; Good == STATUS] - deletes the TIME column and renames the status column to 'Good' [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - creates new PI column from PHA values and also writes the TUNITn keyword for the new column. The final '*' expression means preserve all the columns in the input table in the virtual output table; without the '*' the output table would only contain the single 'PI' column. [col rate = rate/exposure, TUNIT#(&) = 'counts/s';*] - recomputes the rate column by dividing it by the EXPOSURE keyword value. This also modifies the value of the TUNITn keyword for this column. The use of the '&' character for the keyword comment string means preserve the existing comment string for that keyword. The final '*' preserves all the columns in the input table in the virtual output table. - **J. Row Filtering Specification When entering the name of a FITS table that is to be opened by a program, an optional row filter may be specified to select a subset of the rows in the table. A temporary new FITS file is created on the fly which contains only those rows for which the row filter expression evaluates to true. (The primary array and any other extensions in the input file are also copied to the temporary file). The original FITS file is closed and the new virtual file is opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name (e.g., 'file.fits[events][GRADE==50]' selects only those rows where the GRADE column value equals 50). When dealing with tables where each row has an associated time and/or 2D spatial position, the row filter expression can also be used to select rows based on the times in a Good Time Intervals (GTI) extension, or on spatial position as given in a SAO-style region file. ***1. General Syntax The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression must evaluate to a boolean value for each row of the table, where a value of FALSE means that the row will be excluded. For complex or commonly used filters, one can place the expression into a text file and import it into the row filter using the syntax '[@filename.txt]'. The expression can be arbitrarily complex and extend over multiple lines of the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then enclose the name in '\$' characters as in \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: - "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ - Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive). A null value will be returned in case of illegal operations such as divide by zero, sqrt(negative) log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). - "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(y,x) "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) "hyperbolic tan" tanh(x) "round to nearest int" round(x) "round down to int" floor(x) "round up to int" ceil(x) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "modulus" x % y "random # [0.0,1.0)" random() "random Gaussian" randomn() "random Poisson" randomp(x) "minimum" min(x,y) "maximum" max(x,y) "cumulative sum" accum(x) "sequential difference" seqdiff(x) "if-then-else" b?x:y "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) "substring" strmid(s,p,n) "string search" strstr(s,r) - Three different random number functions are provided: random(), with no arguments, produces a uniform random deviate between 0 and 1; randomn(), also with no arguments, produces a normal (Gaussian) random deviate with zero mean and unit standard deviation; randomp(x) produces a Poisson random deviate whose expected number of counts is X. X may be any positive real number of expected counts, including fractional values, but the return value is an integer. When the random functions are used in a vector expression, by default the same random value will be used when evaluating each element of the vector. If different random numbers are desired, then the name of a vector column should be supplied as the single argument to the random function (e.g., "flux + 0.1 * random(flux)", where "flux' is the name of a vector column). This will create a vector of random numbers that will be used in sequence when evaluating each element of the vector expression. An alternate syntax for the min and max functions has only a single argument which should be a vector value (see below). The result will be the minimum/maximum element contained within the vector. The accum(x) function forms the cumulative sum of x, element by element. Vector columns are supported simply by performing the summation process through all the values. Null values are treated as 0. The seqdiff(x) function forms the sequential difference of x, element by element. The first value of seqdiff is the first value of x. A single null value in x causes a pair of nulls in the output. The seqdiff and accum functions are functional inverses, i.e., seqdiff(accum(x)) == x as long as no null values are present. In the if-then-else expression, "b?x:y", b is an explicit boolean value or expression. There is no automatic type conversion from numeric to boolean values, so one needs to use "iVal!=0" instead of merely "iVal" as the boolean argument. x and y can be any scalar data type (including string). The angsep function computes the angular separation in degrees between 2 celestial positions, where the first 2 parameters give the RA-like and Dec-like coordinates (in decimal degrees) of the first position, and the 3rd and 4th parameters give the coordinates of the second position. The substring function strmid(S,P,N) extracts a substring from S, starting at string position P, with a substring length N. The first character position in S is labeled as 1. If P is 0, or refers to a position beyond the end of S, then the extracted substring will be NULL. S, P, and N may be functions of other columns. The string search function strstr(S,R) searches for the first occurrence of the substring R in S. The result is an integer, indicating the character position of the first match (where 1 is the first character position of S). If no match is found, then strstr() returns a NULL value. The following type casting operators are available, where the enclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: - "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i - In addition, several constants are built in for use in numerical expressions: - #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string - A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, value\_1 and value\_2 can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: - near(value_1, value_2, tolerance) - When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: - "a null value?" ISNULL(x) "define a value for null" DEFNULL(x,y) - The former returns a boolean value of TRUE if the argument x is NULL. The later "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. ***2. Bit Masks Bit masks can be used to select out rows from bit columns (TFORMn = \#X) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: - binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) - In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: - flags == b0010011 or flags .eq. b10011 - It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: - flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx - Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: - (!flags) == b1101100 (flags & b1000001) == bx000001 - Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. ***3. Vector Columns Vector columns can also be used in building the expression. No special syntax is required if one wants to operate on all elements of the vector. Simply use the column name as for a scalar column. Vector columns can be freely intermixed with scalar columns or constants in virtually all expressions. The result will be of the same dimension as the vector. Two vectors in an expression, though, need to have the same number of elements and have the same dimensions. The only places a vector column cannot be used (for now, anyway) are the SAO region functions and the NEAR boolean function. Arithmetic and logical operations are all performed on an element by element basis. Comparing two vector columns, eg "COL1 == COL2", thus results in another vector of boolean values indicating which elements of the two vectors are equal. Eight functions are available that operate on a vector and return a scalar result: - "minimum" MIN(V) "maximum" MAX(V) "average" AVERAGE(V) "median" MEDIAN(V) "summation" SUM(V) "standard deviation" STDDEV(V) "# of values" NELEM(V) "# of non-null values" NVALID(V) - where V represents the name of a vector column or a manually constructed vector using curly brackets as described below. The first 6 of these functions ignore any null values in the vector when computing the result. The STDDEV() function computes the sample standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead of 1/SQRT(N), where N is NVALID(V). The SUM function literally sums all the elements in x, returning a scalar value. If x is a boolean vector, SUM returns the number of TRUE elements. The NELEM function returns the number of elements in vector x whereas NVALID return the number of non-null elements in the vector. (NELEM also operates on bit and string columns, returning their column widths.) As an example, to test whether all elements of two vectors satisfy a given logical comparison, one can use the expression - SUM( COL1 > COL2 ) == NELEM( COL1 ) - which will return TRUE if all elements of COL1 are greater than their corresponding elements in COL2. To specify a single element of a vector, give the column name followed by a comma-separated list of coordinates enclosed in square brackets. For example, if a vector column named PHAS exists in the table as a one dimensional, 256 component list of numbers from which you wanted to select the 57th component for use in the expression, then PHAS[57] would do the trick. Higher dimensional arrays of data may appear in a column. But in order to interpret them, the TDIMn keyword must appear in the header. Assuming that a (4,4,4,4) array is packed into each row of a column named ARRAY4D, the (1,2,3,4) component element of each row is accessed by ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently supported. Each vector index can itself be an expression, although it must evaluate to an integer value within the bounds of the vector. Vector columns which contain spaces or arithmetic operators must have their names enclosed in "\$" characters as with \$ARRAY-4D\$[1,2,3,4]. A more C-like syntax for specifying vector indices is also available. The element used in the preceding example alternatively could be specified with the syntax ARRAY4D[4][3][2][1]. Note the reverse order of indices (as in C), as well as the fact that the values are still ones-based (as in Fortran -- adopted to avoid ambiguity for 1D vectors). With this syntax, one does not need to specify all of the indices. To extract a 3D slice of this 4D array, use ARRAY4D[4]. Variable-length vector columns are not supported. Vectors can be manually constructed within the expression using a comma-separated list of elements surrounded by curly braces ('\{\}'). For example, '\{1,3,6,1\}' is a 4-element vector containing the values 1, 3, 6, and 1. The vector can contain only boolean, integer, and real values (or expressions). The elements will be promoted to the highest datatype present. Any elements which are themselves vectors, will be expanded out with each of its elements becoming an element in the constructed vector. ***4. Good Time Interval Filtering A common filtering method involves selecting rows which have a time value which lies within what is called a Good Time Interval or GTI. The time intervals are defined in a separate FITS table extension which contains 2 columns giving the start and stop time of each good interval. The filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in the GTI extension. A high level function, gtifilter(a,b,c,d), is available which evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) - where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quotes may be used. In cases where this expression is entered on the Unix command line, enclose the entire expression in double quotes, and then use single quotes within the expression to enclose the 'gtifile' and other terms. It is also usually possible to do the reverse, and enclose the whole expression in single quotes and then use double quotes within the expression. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression "gtifilter()" is equivalent to - gtifilter( "", TIME, "*START*", "*STOP*" ) - This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. ***5. Spatial Region Filtering Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) - where each "[]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. There are 2 supported formats for the region file: ASCII file or FITS binary table. The region file contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. The FITS region file format is defined in a document available from the FITS Support Office at http://fits.gsfc.nasa.gov/ registry/ region.html In its simplest form, (e.g., regfilter("region.reg") ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in - regfilter("region.reg", XPOS, YPOS) - Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) - Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): - Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semi-major/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. There are three functions that are primarily for use with SAO region files and the FSAOI task, but they can be used directly. They return a boolean true or false depending on whether a two dimensional point is in the region or not: - "point in a circular region" circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) "point in an elliptical region" ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) "point in a rectangular region" box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) where (xcntr,ycntr) are the (x,y) position of the center of the region (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region (radius) is half the diameter of the circle (rotation) is the angle(degrees) that the region is rotated with respect to (xcntr,ycntr) (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column names NOTE: each parameter can itself be an expression, not merely a column name or constant. - ***5. Example Row Filters - [ binary && mag <= 5.0] - Extract all binary stars brighter than fifth magnitude (note that the initial space is necessary to prevent it from being treated as a binning specification) [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [IMAGE[4,5] .gt. 100] - Extract all rows that have the (4,5) component of the IMAGE column greater than 100 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a spectrum, held in vector column SPEC, with at least one value 3 times greater than the background level held in a keyword, BACKGRND [VCOL=={1,4,2}] - Extract all rows whose vector column VCOL contains the 3-elements 1, 4, and 2. [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the Xs and Ys columns will be used to determine the coordinate of each row in the table. - **K. Binning or Histogramming Specification The optional binning specifier is enclosed in square brackets and can be distinguished from a general row filter specification by the fact that it begins with the keyword 'bin' not immediately followed by an equals sign. When binning is specified, a temporary N-dimensional FITS primary array is created by computing the histogram of the values in the specified columns of a FITS table extension. After the histogram is computed the input FITS file containing the table is then closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no additional extensions). Obviously, the application program must be expecting to open a FITS image and not a FITS table in this case. The data type of the FITS histogram image may be specified by appending 'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double precision floating point) to the 'bin' keyword (e.g. '[binr X]' creates a real floating point image). If the datatype is not explicitly specified then a 32-bit integer image will be created by default, unless the weighting option is also specified in which case the image will have a 32-bit floating point data type by default. The histogram image may have from 1 to 4 dimensions (axes), depending on the number of columns that are specified. The general form of the binning specification is: - [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] - in which up to 4 columns, each corresponding to an axis of the image, are listed. The column names are case insensitive, and the column number may be given instead of the name, preceded by a pound sign (e.g., [bin \#4=1:512]). If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 axes, respectively. In cases where the column name could be confused with an arithmetic expression, enclose the column name in parentheses to force the name to be interpreted literally. Each column name may be followed by an equals sign and then the lower and upper range of the histogram, and the size of the histogram bins, separated by colons. Spaces are allowed before and after the equals sign but not within the 'min:max:binsize' string. The min, max and binsize values may be integer or floating point numbers, or they may be the names of keywords in the header of the table. If the latter, then the value of that keyword is substituted into the expression. Default values for the min, max and binsize quantities will be used if not explicitly given in the binning expression as shown in these examples: - [bin x = :512:2] - use default minimum value [bin x = 1::2] - use default maximum value [bin x = 1:512] - use default bin size [bin x = 1:] - use default maximum value and bin size [bin x = :512] - use default minimum value and bin size [bin x = 2] - use default minimum and maximum values [bin x] - use default minimum, maximum and bin size [bin 4] - default 2-D image, bin size = 4 in both axes [bin] - default 2-D image - CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, if they exist, for the default min, max, and binsize, respectively. If they do not exist then CFITSIO will use the actual minimum and maximum values in the column for the histogram min and max values. The default binsize will be set to 1, or (max - min) / 10., whichever is smaller, so that the histogram will have at least 10 bins along each axis. A shortcut notation is allowed if all the columns/axes have the same binning specification. In this case all the column names may be listed within parentheses, followed by the (single) binning specification, as in: - [bin (X,Y)=1:512:2] [bin (X,Y) = 5] - The optional weighting factor is the last item in the binning specifier and, if present, is separated from the list of columns by a semi-colon. As the histogram is accumulated, this weight is used to incremented the value of the appropriated bin in the histogram. If the weighting factor is not specified, then the default weight = 1 is assumed. The weighting factor may be a constant integer or floating point number, or the name of a keyword containing the weighting value. Or the weighting factor may be the name of a table column in which case the value in that column, on a row by row basis, will be used. In some cases, the column or keyword may give the reciprocal of the actual weight value that is needed. In this case, precede the weight keyword or column name by a slash '/' to tell CFITSIO to use the reciprocal of the value when constructing the histogram. For complex or commonly used histograms, one can also place its description into a text file and import it into the binning specification using the syntax '[bin @filename.txt]'. The file's contents can extend over multiple lines, although it must still conform to the no-spaces rule for the min:max:binsize syntax and each axis specification must still be comma-separated. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: - [bini detx, dety] - 2-D, 16-bit integer histogram of DETX and DETY columns, using default values for the histogram range and binsize [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX and DETY columns with a bin size = 16 in both axes. The histogram values are divided by the EXPOSURE keyword value. [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by the TSTART and TSTOP keywords, with 0.1 unit size bins. [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning of the PHA column for the X axis, and 1000 bins in the range 8000. to 8100. for the Y axis. [bin @binFilter.txt] - Use the contents of the text file binFilter.txt for the binning specifications. - *V. Template Files When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following sections. **A Detailed Template Line Format The format of each ASCII template line closely follows the format of a FITS keyword record: - KEYWORD = KEYVALUE / COMMENT - except that free format may be used (e.g., the equals sign may appear at any position in the line) and TAB characters are allowed and are treated the same as space characters. The KEYVALUE and COMMENT fields are optional. The equals sign character is also optional, but it is recommended that it be included for clarity. Any template line that begins with the pound '\#' character is ignored by the template parser and may be use to insert comments into the template file itself. The KEYWORD name field is limited to 8 characters in length and only the letters A-Z, digits 0-9, and the hyphen and underscore characters may be used, without any embedded spaces. Lowercase letters in the template keyword name will be converted to uppercase. Leading spaces in the template line preceding the keyword name are generally ignored, except if the first 8 characters of a template line are all blank, then the entire line is treated as a FITS comment keyword (with a blank keyword name) and is copied verbatim into the FITS header. The KEYVALUE field may have any allowed FITS data type: character string, logical, integer, real, complex integer, or complex real. Integer values must be within the allowed range of a 'signed long' variable; some C compilers only suppport 4-byte long integers with a range from -2147483648 to +2147483647, whereas other C compilers support 8-byte integers with a range of plus or minus 2**63. The character string values need not be enclosed in single quote characters unless they are necessary to distinguish the string from a different data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has an undefined (null) value if the template record only contains blanks following the "=" or between the "=" and the "/" comment field delimiter. String keyword values longer than 68 characters (the maximum length that will fit in a single FITS keyword record) are permitted using the CFITSIO long string convention. They can either be specified as a single long line in the template, or by using multiple lines where the continuing lines contain the 'CONTINUE' keyword, as in this example: - LONGKEY = 'This is a long string value that is contin&' CONTINUE 'ued over 2 records' / comment field goes here - The format of template lines with CONTINUE keyword is very strict: 3 spaces must follow CONTINUE and the rest of the line is copied verbatim to the FITS file. The start of the optional COMMENT field must be preceded by "/", which is used to separate it from the keyword value field. Exceptions are if the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the first 8 characters of the template line are blanks. More than one Header-Data Unit (HDU) may be defined in the template file. The start of an HDU definition is denoted with a SIMPLE or XTENSION template line: 1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as the first keyword in the template file. If the template file begins with XTENSION instead of SIMPLE, then a default empty Primary HDU is created, and the template is then assumed to define the keywords starting with the first extension following the Primary HDU. 2) XTENSION marks the beginning of a new extension HDU definition. The previous HDU will be closed at this point and processing of the next extension begins. **B Auto-indexing of Keywords If a template keyword name ends with a "\#" character, it is said to be 'auto-indexed'. Each "\#" character will be replaced by the current integer index value, which gets reset = 1 at the start of each new HDU in the file (or 7 in the special case of a GROUP definition). The FIRST indexed keyword in each template HDU definition is used as the 'incrementor'; each subsequent occurrence of this SAME keyword will cause the index value to be incremented. This behavior can be rather subtle, as illustrated in the following examples in which the TTYPE keyword is the incrementor in both cases: - TTYPE# = TIME TFORM# = 1D TTYPE# = RATE TFORM# = 1E - will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the template looks like, - TTYPE# = TIME TTYPE# = RATE TFORM# = 1D TFORM# = 1E - this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, which is probably not what was intended! **C Template Parser Directives In addition to the template lines which define individual keywords, the template parser recognizes 3 special directives which are each preceded by the backslash character: \verb+ \include, \group+, and \verb+ \end+. The 'include' directive must be followed by a filename. It forces the parser to temporarily stop reading the current template file and begin reading the include file. Once the parser reaches the end of the include file it continues parsing the current template file. Include files can be nested, and HDU definitions can span multiple template files. The start of a GROUP definition is denoted with the 'group' directive, and the end of a GROUP definition is denoted with the 'end' directive. Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member blocks of type GROUP can contain their own member blocks. The GROUP definition itself occupies one FITS file HDU of special type (GROUP HDU), so if a template specifies 1 group with 1 member HDU like: - \group grpdescr = 'demo' xtension bintable # this bintable has 0 cols, 0 rows \end - then the parser creates a FITS file with 3 HDUs : - 1) dummy PHDU 2) GROUP HDU (has 1 member, which is bintable in HDU number 3) 3) bintable (member of GROUP in HDU number 2) - Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications can define additional columns in a GROUP HDU using TFORMn and TTYPEn (where n is 7, 8, ....) keywords or their auto-indexing equivalents. For a more complicated example of a template file using the group directives, look at the sample.tpl file that is included in the CFITSIO distribution. **D Formal Template Syntax The template syntax can formally be defined as follows: - TEMPLATE = BLOCK [ BLOCK ... ] BLOCK = { HDU | GROUP } GROUP = \GROUP [ BLOCK ... ] \END HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] X ... - X can be present 1 or more times { X | Y } - X or Y [ X ] - X is optional - At the topmost level, the template defines 1 or more template blocks. Blocks can be either HDU (Header Data Unit) or a GROUP. For each block the parser creates 1 (or more for GROUPs) FITS file HDUs. **E Errors In general the fits\_execute\_template() function tries to be as atomic as possible, so either everything is done or nothing is done. If an error occurs during parsing of the template, fits\_execute\_template() will (try to) delete the top level BLOCK (with all its children if any) in which the error occurred, then it will stop reading the template file and it will return with an error. **F Examples 1. This template file will create a 200 x 300 pixel image, with 4-byte integer pixel values, in the primary HDU: - SIMPLE = T BITPIX = 32 NAXIS = 2 / number of dimensions NAXIS1 = 100 / length of first axis NAXIS2 = 200 / length of second axis OBJECT = NGC 253 / name of observed object - The allowed values of BITPIX are 8, 16, 32, -32, or -64, representing, respectively, 8-bit integer, 16-bit integer, 32-bit integer, 32-bit floating point, or 64 bit floating point pixels. 2. To create a FITS table, the template first needs to include XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary table, and NAXIS2 to define the number of rows in the table. Two template lines are then needed to define the name (TTYPEn) and FITS data format (TFORMn) of the columns, as in this example: - xtension = bintable naxis2 = 40 ttype# = Name tform# = 10a ttype# = Npoints tform# = j ttype# = Rate tunit# = counts/s tform# = e - The above example defines a null primary array followed by a 40-row binary table extension with 3 columns called 'Name', 'Npoints', and 'Rate', with data formats of '10A' (ASCII character string), '1J' (integer) and '1E' (floating point), respectively. Note that the other required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, and END) do not need to be explicitly defined in the template because their values can be inferred from the other keywords in the template. This example also illustrates that the templates are generally case-insensitive (the keyword names and TFORMn values are converted to upper-case in the FITS file) and that string keyword values generally do not need to be enclosed in quotes. *IX Summary of all FITSIO User-Interface Subroutines Error Status Routines page~\pageref{FTVERS} - FTVERS( > version) FTGERR(status, > errtext) FTGMSG( > errmsg) FTRPRT (stream, > status) FTPMSG(errmsg) FTPMRK FTCMSG FTCMRK - FITS File Open and Close Subroutines: page~\pageref{FTOPEN} - FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTNOPN(unit,filename,rwmode, > status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) FTREOPEN(unit, > newunit, status) FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) FTTPLT(unit, filename, tplfilename, > status) FTFLUS(unit, > status) FTCLOS(unit, > status) FTDELT(unit, > status) FTGIOU( > iounit, status) FTFIOU(iounit, > status) CFITS2Unit(fitsfile *ptr) (C routine) CUnit2FITS(int unit) (C routine) FTEXTN(filename, > nhdu, status) FTFLNM(unit, > filename, status) FTFLMD(unit, > iomode, status) FTURLT(unit, > urltype, status) FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) FTRTNM(filename, > rootname, status) FTEXIST(filename, > exist, status) - HDU-Level Operations: page~\pageref{FTMAHD} - FTMAHD(unit,nhdu, > hdutype,status) FTMRHD(unit,nmove, > hdutype,status) FTGHDN(unit, > nhdu) FTMNHD(unit, hdutype, extname, extver, > status) FTGHDT(unit, > hdutype, status) FTTHDU(unit, > hdunum, status) FTCRHD(unit, > status) FTIIMG(unit,bitpix,naxis,naxes, > status) FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTRSIM(unit,bitpix,naxis,naxes,status) FTDHDU(unit, > hdutype,status) FTCPFL(iunit,ounit,previous, current, following, > status) FTCOPY(iunit,ounit,morekeys, > status) FTCPHD(inunit, outunit, > status) FTCPDT(iunit,ounit, > status) - Subroutines to specify or modify the structure of the CHDU: page~\pageref{FTRDEF} - FTRDEF(unit, > status) (DEPRECATED) FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) FTDDEF(unit,bytlen, > status) (DEPRECATED) FTPTHP(unit,theap, > status) - Header Space and Position Subroutines: page~\pageref{FTHDEF} - FTHDEF(unit,morekeys, > status) FTGHSP(iunit, > keysexist,keysadd,status) FTGHPS(iunit, > keysexist,key_no,status) - Read or Write Standard Header Subroutines: page~\pageref{FTPHPR} - FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) - Write Keyword Subroutines: page~\pageref{FTPREC} - FTPREC(unit,card, > status) FTPCOM(unit,comment, > status) FTPHIS(unit,history, > status) FTPDAT(unit, > status) FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) FTPKYU(unit,keyword,comment, > status) FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) FTCPKYinunit, outunit, innum, outnum, keyroot, > status) FTPKYT(unit,keyword,intval,dblval,comment, > status) FTPKTP(unit, filename, > status) FTPUNT(unit,keyword,units, > status) - Insert Keyword Subroutines: page~\pageref{FTIREC} - FTIREC(unit,key_no,card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTIKYU(unit,keyword,comment, > status) - Read Keyword Subroutines: page~\pageref{FTGREC} - FTGREC(unit,key_no, > card,status) FTGKYN(unit,key_no, > keyword,value,comment,status) FTGCRD(unit,keyword, > card,status) FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) FTGKEY(unit,keyword, > value,comment,status) FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) FTGKYT(unit,keyword, > intval,dblval,comment,status) FTGUNT(unit,keyword, > units,status) - Modify Keyword Subroutines: page~\pageref{FTMREC} - FTMREC(unit,key_no,card, > status) FTMCRD(unit,keyword,card, > status) FTMNAM(unit,oldkey,keyword, > status) FTMCOM(unit,keyword,comment, > status) FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTMKYU(unit,keyword,comment, > status) - Update Keyword Subroutines: page~\pageref{FTUCRD} - FTUCRD(unit,keyword,card, > status) FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTUKYU(unit,keyword,comment, > status) - Delete Keyword Subroutines: page~\pageref{FTDREC} - FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) - Define Data Scaling Parameters and Undefined Pixel Flags: page~\pageref{FTPSCL} - FTPSCL(unit,bscale,bzero, > status) FTTSCL(unit,colnum,tscal,tzero, > status) FTPNUL(unit,blank, > status) FTSNUL(unit,colnum,snull > status) FTTNUL(unit,colnum,tnull > status) - FITS Primary Array or IMAGE Extension I/O Subroutines: page~\pageref{FTPPR} - FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) FTGIDM(unit, > naxis,status) FTGISZ(unit, maxdim, > naxes,status) FTGIPR(unit, maxdim, > bitpix,naxis,naxes,status) FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) FTPPRU(unit,group,fpixel,nelements, > status) FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) - Table Column Information Subroutines: page~\pageref{FTGCNO} - FTGNRW(unit, > nrows, status) FTGNCL(unit, > ncols, status) FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colnam,colnum,status) FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) FTGCDW(unit,colnum, > dispwidth,status) FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) FTPTDM(unit,colnum,naxis,naxes, > status) FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) FTGRSZ(unit, > nrows,status) - Low-Level Table Access Subroutines: page~\pageref{FTGTBS} - FTGTBS(unit,frow,startchar,nchars, > string,status) FTPTBS(unit,frow,startchar,nchars,string, > status) FTGTBB(unit,frow,startchar,nchars, > array,status) FTPTBB(unit,frow,startchar,nchars,array, > status) - Edit Rows or Columns page~\pageref{FTIROW} - FTIROW(unit,frow,nrows, > status) FTDROW(unit,frow,nrows, > status) FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) FTMVEC(unit,colnum,newveclen, > status) FTDCOL(unit,colnum, > status) FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); - Read and Write Column Data Routines page~\pageref{FTPCLS} - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCN[BIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) FTPCLU(unit,colnum,frow,felem,nelements, > status) FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) FTGDES(unit,colnum,rownum, > nelements,offset,status) FTPDES(unit,colnum,rownum,nelements,offset, > status) - Row Selection and Calculator Routines: page~\pageref{FTFROW} - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) FTFFRW(unit, expr, > rownum, status) FTSROW(inunit, outunit, expr, > status ) FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) FTCALC(inunit, expr, outunit, parName, parInfo, > status) FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) FTTEXP(unit, expr, > datatype, nelem, naxis, naxes, status) - Celestial Coordinate System Subroutines: page~\pageref{FTGICS} - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) - File Checksum Subroutines: page~\pageref{FTPCKS} - FTPCKS(unit, > status) FTUCKS(unit, > status) FTVCKS(unit, > dataok,hduok,status) FTGCKS(unit, > datasum,hdusum,status) FTESUM(sum,complement, > checksum) FTDSUM(checksum,complement, > sum) - Time and Date Utility Subroutines: page~\pageref{FTGSDT} - FTGSDT( > day, month, year, status ) FTGSTM(> datestr, timeref, status) FTDT2S( year, month, day, > datestr, status) FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) FTS2DT(datestr, > year, month, day, status) FTS2TM(datestr, > year, month, day, hour, minute, second, status) - General Utility Subroutines: page~\pageref{FTGHAD} - FTGHAD(unit, > curaddr,nextaddr) FTUPCH(string) FTCMPS(str_template,string,casesen, > match,exact) FTTKEY(keyword, > status) FTTREC(card, > status) FTNCHK(unit, > status) FTGKNM(unit, > keyword, keylength, status) FTMKKY(keyword, value,comment, > card, status) FTPSVC(card, > value,comment,status) FTKEYN(keyroot,seq_no, > keyword,status) FTNKEY(seq_no,keyroot, > keyword,status) FTDTYP(value, > dtype,status) class = FTGKCL(card) FTASFM(tform, > datacode,width,decimals,status) FTBNFM(tform, > datacode,repeat,width,status) FTGABC(tfields,tform,space, > rowlen,tbcol,status) FTGTHD(template, > card,hdtype,status) FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) - *X. Parameter Definitions - anyf - (logical) set to TRUE if any of the returned data values are undefined array - (any datatype except character) array of bytes to be read or written. bitpix - (integer) bits per pixel: 8, 16, 32, -32, or -64 blank - (integer) value used for undefined pixels in integer primary array blank - (integer*8) value used for undefined pixels in integer primary array blocksize - (integer) 2880-byte logical record blocking factor (if 0 < blocksize < 11) or the actual block size in bytes (if 10 < blocksize < 28800). As of version 3.3 of FITSIO, blocksizes greater than 2880 are no longer supported. bscale - (double precision) scaling factor for the primary array bytlen - (integer) length of the data unit, in bytes bzero - (double precision) zero point for primary array scaling card - (character*80) header record to be read or written casesen - (logical) will string matching be case sensitive? checksum - (character*16) encoded checksum string colname - (character) ASCII name of the column colnum - (integer) number of the column (first column = 1) coltemplate - (character) template string to be matched to column names comment - (character) the keyword comment field comments - (character array) keyword comment fields compid - (integer) the type of computer that the program is running on complement - (logical) should the checksum be complemented? coordtype - (character) type of coordinate projection (-SIN, -TAN, -ARC, -NCP, -GLS, -MER, or -AIT) cube - 3D data cube of the appropriate datatype curaddr - (integer) starting address (in bytes) of the CHDU current - (integer) if not equal to 0, copy the current HDU datacode - (integer) symbolic code of the binary table column datatype dataok - (integer) was the data unit verification successful (=1) or not (= -1). Equals zero if the DATASUM keyword is not present. datasum - (double precision) 32-bit 1's complement checksum for the data unit datatype - (character) datatype (format) of the binary table column datestr - (string) FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', or 'dd/mm/yy' day - (integer) current day of the month dblval - (double precision) fractional part of the keyword value decimals - (integer) number of decimal places to be displayed dim1 - (integer) actual size of the first dimension of the image or cube array dim2 - (integer) actual size of the second dimension of the cube array dispwidth - (integer) - the display width (length of string) for a column dtype - (character) datatype of the keyword ('C', 'L', 'I', or 'F') C = character string L = logical I = integer F = floating point number errmsg - (character*80) oldest error message on the internal stack errtext - (character*30) descriptive error message corresponding to error number casesen - (logical) true if column name matching is case sensitive exact - (logical) do the strings match exactly, or were wildcards used? exclist (character array) list of names to be excluded from search exists - flag indicating whether the file or compressed file exists on disk extend - (logical) true if there may be extensions following the primary data extname - (character) value of the EXTNAME keyword (if not blank) fbit - (integer) first bit in the field to be read or written felem - (integer) first pixel of the element vector (ignored for ASCII tables) filename - (character) name of the FITS file flagvals - (logical array) True if corresponding data element is undefined following - (integer) if not equal to 0, copy all following HDUs in the input file fparm - (integer) sequence number of the first group parameter to read or write fpixel - (integer) the first pixel position fpixels - (integer array) the first included pixel in each dimension frow - (integer) beginning row number (first row of table = 1) frowll - (integer*8) beginning row number (first row of table = 1) gcount - (integer) value of the GCOUNT keyword (usually = 1) group - (integer) sequence number of the data group (=0 for non-grouped data) hdtype - (integer) header record type: -1=delete; 0=append or replace; 1=append; 2=this is the END keyword hduok - (integer) was the HDU verification successful (=1) or not (= -1). Equals zero if the CHECKSUM keyword is not present. hdusum - (double precision) 32 bit 1's complement checksum for the entire CHDU hdutype - (integer) type of HDU: 0 = primary array or IMAGE, 1 = ASCII table, 2 = binary table, -1 = any HDU type or unknown type history - (character) the HISTORY keyword comment string hour - (integer) hour from 0 - 23 image - 2D image of the appropriate datatype inclist (character array) list of names to be included in search incs - (integer array) sampling interval for pixels in each FITS dimension intval - (integer) integer part of the keyword value iounit - (integer) value of an unused I/O unit number iunit - (integer) logical unit number associated with the input FITS file, 1-300 key_no - (integer) sequence number (starting with 1) of the keyword record keylength - (integer) length of the keyword name keyroot - (character) root string for the keyword name keysadd -(integer) number of new keyword records which can fit in the CHU keysexist - (integer) number of existing keyword records in the CHU keyval - value of the keyword in the appropriate datatype keyvals - (array) value of the keywords in the appropriate datatype keyword - (character*8) name of a keyword lray - (logical array) array of logical values corresponding to the bit array lpixels - (integer array) the last included pixel in each dimension match - (logical) do the 2 strings match? maxdim - (integer) dimensioned size of the NAXES, TTYPE, TFORM or TUNIT arrays max_keys - (integer) maximum number of keywords to search for minute - (integer) minute of an hour (0 - 59) month - (integer) current month of the year (1 - 12) morekeys - (integer) will leave space in the header for this many more keywords naxes - (integer array) size of each dimension in the FITS array naxesll - (integer*8 array) size of each dimension in the FITS array naxis - (integer) number of dimensions in the FITS array naxis1 - (integer) length of the X/first axis of the FITS array naxis2 - (integer) length of the Y/second axis of the FITS array naxis3 - (integer) length of the Z/third axis of the FITS array nbit - (integer) number of bits in the field to read or write nchars - (integer) number of characters to read and return ncols - (integer) number of columns nelements - (integer) number of data elements to read or write nelementsll - (integer*8) number of data elements to read or write nexc (integer) number of names in the exclusion list (may = 0) nhdu - (integer) absolute number of the HDU (1st HDU = 1) ninc (integer) number of names in the inclusion list nmove - (integer) number of HDUs to move (+ or -), relative to current position nfound - (integer) number of keywords found (highest keyword number) no_keys - (integer) number of keywords to write in the sequence nparm - (integer) number of group parameters to read or write nrows - (integer) number of rows in the table nrowsll - (integer*8) number of rows in the table nullval - value to represent undefined pixels, of the appropriate datatype nextaddr - (integer) starting address (in bytes) of the HDU following the CHDU offset - (integer) byte offset in the heap to the first element of the array offsetll - (integer*8) byte offset in the heap to the first element of the array oldkey - (character) old name of keyword to be modified ounit - (integer) logical unit number associated with the output FITS file 1-300 pcount - (integer) value of the PCOUNT keyword (usually = 0) previous - (integer) if not equal to 0, copy all previous HDUs in the input file repeat - (integer) length of element vector (e.g. 12J); ignored for ASCII table rot - (double precision) celestial coordinate rotation angle (degrees) rowlen - (integer) length of a table row, in characters or bytes rowlenll - (integer*8) length of a table row, in characters or bytes rowlist - (integer array) list of row numbers to be deleted in increasing order rownum - (integer) number of the row (first row = 1) rowrange- (string) list of rows or row ranges to be deleted rwmode - (integer) file access mode: 0 = readonly, 1 = readwrite second (double)- second within minute (0 - 60.9999999999) (leap second!) seq_no - (integer) the sequence number to append to the keyword root name simple - (logical) does the FITS file conform to all the FITS standards snull - (character) value used to represent undefined values in ASCII table space - (integer) number of blank spaces to leave between ASCII table columns startchar - (integer) first character in the row to be read startno - (integer) value of the first keyword sequence number (usually 1) status - (integer) returned error status code (0 = OK) str_template (character) template string to be matched to reference string stream - (character) output stream for the report: either 'STDOUT' or 'STDERR' string - (character) character string sum - (double precision) 32 bit unsigned checksum value tbcol - (integer array) column number of the first character in the field(s) tdisp - (character) Fortran type display format for the table column template-(character) template string for a FITS header record tfields - (integer) number of fields (columns) in the table tform - (character array) format of the column(s); allowed values are: For ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd For binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count Note that the 'rAw' form is non-standard extension to the TFORM keyword syntax that is not specifically defined in the Binary Tables definition document. theap - (integer) zero indexed byte offset of starting address of the heap relative to the beginning of the binary table data tnull - (integer) value used to represent undefined values in binary table tnullll - (integer*8) value used to represent undefined values in binary table ttype - (character array) label for table column(s) tscal - (double precision) scaling factor for table column tunit - (character array) physical unit for table column(s) tzero - (double precision) scaling zero point for table column unit - (integer) logical unit number associated with the FITS file (1-300) units - (character) the keyword units string (e.g., 'km/s') value - (character) the keyword value string values - array of data values of the appropriate datatype varidat - (integer) size in bytes of the 'variable length data area' following the binary table data (usually = 0) version - (real) current revision number of the library width - (integer) width of the character string field xcol - (integer) number of the column containing the X coordinate values xinc - (double precision) X axis coordinate increment at reference pixel (deg) xpix - (double precision) X axis pixel location xpos - (double precision) X axis celestial coordinate (usually RA) (deg) xrpix - (double precision) X axis reference pixel array location xrval - (double precision) X axis coordinate value at the reference pixel (deg) ycol - (integer) number of the column containing the X coordinate values year - (integer) last 2 digits of the year (00 - 99) yinc - (double precision) Y axis coordinate increment at reference pixel (deg) ypix - (double precision) y axis pixel location ypos - (double precision) y axis celestial coordinate (usually DEC) (deg) yrpix - (double precision) Y axis reference pixel array location yrval - (double precision) Y axis coordinate value at the reference pixel (deg) - *XI. FITSIO Error Status Codes - Status codes in the range -99 to -999 and 1 to 999 are reserved for future FITSIO use. 0 OK, no error 101 input and output files are the same 103 too many FITS files open at once; all internal buffers full 104 error opening existing file 105 error creating new FITS file; (does a file with this name already exist?) 106 error writing record to FITS file 107 end-of-file encountered while reading record from FITS file 108 error reading record from file 110 error closing FITS file 111 internal array dimensions exceeded 112 Cannot modify file with readonly access 113 Could not allocate memory 114 illegal logical unit number; must be between 1 - 300, inclusive 115 NULL input pointer to routine 116 error seeking position in file 121 invalid URL prefix on file name 122 tried to register too many IO drivers 123 driver initialization failed 124 matching driver is not registered 125 failed to parse input file URL 126 parse error in range list 151 bad argument in shared memory driver 152 null pointer passed as an argument 153 no more free shared memory handles 154 shared memory driver is not initialized 155 IPC error returned by a system call 156 no memory in shared memory driver 157 resource deadlock would occur 158 attempt to open/create lock file failed 159 shared memory block cannot be resized at the moment 201 header not empty; can't write required keywords 202 specified keyword name was not found in the header 203 specified header record number is out of bounds 204 keyword value field is blank 205 keyword value string is missing the closing quote character 206 illegal indexed keyword name (e.g. 'TFORM1000') 207 illegal character in keyword name or header record 208 keyword does not have expected name. Keyword out of sequence? 209 keyword does not have expected integer value 210 could not find the required END header keyword 211 illegal BITPIX keyword value 212 illegal NAXIS keyword value 213 illegal NAXISn keyword value: must be 0 or positive integer 214 illegal PCOUNT keyword value 215 illegal GCOUNT keyword value 216 illegal TFIELDS keyword value 217 negative ASCII or binary table width value (NAXIS1) 218 negative number of rows in ASCII or binary table (NAXIS2) 219 column name (TTYPE keyword) not found 220 illegal SIMPLE keyword value 221 could not find the required SIMPLE header keyword 222 could not find the required BITPIX header keyword 223 could not find the required NAXIS header keyword 224 could not find all the required NAXISn keywords in the header 225 could not find the required XTENSION header keyword 226 the CHDU is not an ASCII table extension 227 the CHDU is not a binary table extension 228 could not find the required PCOUNT header keyword 229 could not find the required GCOUNT header keyword 230 could not find the required TFIELDS header keyword 231 could not find all the required TBCOLn keywords in the header 232 could not find all the required TFORMn keywords in the header 233 the CHDU is not an IMAGE extension 234 illegal TBCOL keyword value; out of range 235 this operation only allowed for ASCII or BINARY table extension 236 column is too wide to fit within the specified width of the ASCII table 237 the specified column name template matched more than one column name 241 binary table row width is not equal to the sum of the field widths 251 unrecognizable type of FITS extension 252 unrecognizable FITS record 253 END keyword contains non-blank characters in columns 9-80 254 Header fill area contains non-blank characters 255 Data fill area contains non-blank on non-zero values 261 unable to parse the TFORM keyword value string 262 unrecognizable TFORM datatype code 263 illegal TDIMn keyword value 301 illegal HDU number; less than 1 or greater than internal buffer size 302 column number out of range (1 - 999) 304 attempt to move to negative file record number 306 attempted to read or write a negative number of bytes in the FITS file 307 illegal starting row number for table read or write operation 308 illegal starting element number for table read or write operation 309 attempted to read or write character string in non-character table column 310 attempted to read or write logical value in non-logical table column 311 illegal ASCII table TFORM format code for attempted operation 312 illegal binary table TFORM format code for attempted operation 314 value for undefined pixels has not been defined 317 attempted to read or write descriptor in a non-descriptor field 320 number of array dimensions out of range 321 first pixel number is greater than the last pixel number 322 attempt to set BSCALE or TSCALn scaling parameter = 0 323 illegal axis length less than 1 340 NOT_GROUP_TABLE 340 Grouping function error 341 HDU_ALREADY_MEMBER 342 MEMBER_NOT_FOUND 343 GROUP_NOT_FOUND 344 BAD_GROUP_ID 345 TOO_MANY_HDUS_TRACKED 346 HDU_ALREADY_TRACKED 347 BAD_OPTION 348 IDENTICAL_POINTERS 349 BAD_GROUP_ATTACH 350 BAD_GROUP_DETACH 360 NGP_NO_MEMORY malloc failed 361 NGP_READ_ERR read error from file 362 NGP_NUL_PTR null pointer passed as an argument. Passing null pointer as a name of template file raises this error 363 NGP_EMPTY_CURLINE line read seems to be empty (used internally) 364 NGP_UNREAD_QUEUE_FULL cannot unread more then 1 line (or single line twice) 365 NGP_INC_NESTING too deep include file nesting (infinite loop, template includes itself ?) 366 NGP_ERR_FOPEN fopen() failed, cannot open template file 367 NGP_EOF end of file encountered and not expected 368 NGP_BAD_ARG bad arguments passed. Usually means internal parser error. Should not happen 369 NGP_TOKEN_NOT_EXPECT token not expected here 401 error attempting to convert an integer to a formatted character string 402 error attempting to convert a real value to a formatted character string 403 cannot convert a quoted string keyword to an integer 404 attempted to read a non-logical keyword value as a logical value 405 cannot convert a quoted string keyword to a real value 406 cannot convert a quoted string keyword to a double precision value 407 error attempting to read character string as an integer 408 error attempting to read character string as a real value 409 error attempting to read character string as a double precision value 410 bad keyword datatype code 411 illegal number of decimal places while formatting floating point value 412 numerical overflow during implicit datatype conversion 413 error compressing image 414 error uncompressing image 420 error in date or time conversion 431 syntax error in parser expression 432 expression did not evaluate to desired type 433 vector result too large to return in array 434 data parser failed not sent an out column 435 bad data encounter while parsing column 436 parse error: output file not of proper type 501 celestial angle too large for projection 502 bad celestial coordinate or pixel value 503 error in celestial coordinate calculation 504 unsupported type of celestial projection 505 required celestial coordinate keywords not found 506 approximate wcs keyword values were returned - \end{document} cfitsio-4.3.1/docs/quick.tex0000644000225700000360000030611013472024437015242 0ustar cagordonlhea\documentclass[11pt]{article} \input{html.sty} \htmladdtonavigation {\begin{rawhtml} FITSIO Home \end{rawhtml}} \oddsidemargin=0.20in \evensidemargin=0.20in \textwidth=15.5truecm \textheight=21.5truecm \title{CFITSIO Quick Start Guide} \author{William Pence \thanks{HEASARC, NASA Goddard Space Flight Center}} \date{January 2003} \begin{document} \maketitle \tableofcontents % =================================================================== \section{Introduction} This document is intended to help you quickly start writing C programs to read and write FITS files using the CFITSIO library. It covers the most important CFITSIO routines that are needed to perform most types of operations on FITS files. For more complete information about these and all the other available routines in the library please refer to the ``CFITSIO User's Reference Guide'', which is available from the CFITSIO Web site at {\tt http://heasarc.gsfc.nasa.gov/fitsio}. For more general information about the FITS data format, refer to the following web page: http://heasarc.gsfc.nasa.gov/docs/heasarc/fits.html FITS stands for Flexible Image Transport System and is the standard file format used to store most astronomical data files. There are 2 basic types of FITS files: images and tables. FITS images often contain a 2-dimensional array of pixels representing an image of a piece of the sky, but FITS images can also contain 1-D arrays (i.e, a spectrum or light curve), or 3-D arrays (a data cube), or even higher dimensional arrays of data. An image may also have zero dimensions, in which case it is referred to as a null or empty array. The supported datatypes for the image arrays are 8, 16, and 32-bit integers, and 32 and 64-bit floating point real numbers. Both signed and unsigned integers are supported. FITS tables contain rows and columns of data, similar to a spreadsheet. All the values in a particular column must have the same datatype. A cell of a column is not restricted to a single number, and instead can contain an array or vector of numbers. There are actually 2 subtypes of FITS tables: ASCII and binary. As the names imply, ASCII tables store the data values in an ASCII representation whereas binary tables store the data values in a more efficient machine-readable binary format. Binary tables are generally more compact and support more features (e.g., a wider range of datatypes, and vector columns) than ASCII tables. A single FITS file many contain multiple images or tables. Each table or image is called a Header-Data Unit, or HDU. The first HDU in a FITS file must be an image (but it may have zero axes) and is called the Primary Array. Any additional HDUs in the file (which are also referred to as `extensions') may contain either an image or a table. Every HDU contains a header containing keyword records. Each keyword record is 80 ASCII characters long and has the following format: \begin{verbatim} KEYWORD = value / comment string \end{verbatim} The keyword name can be up to 8 characters long (all uppercase). The value can be either an integer or floating point number, a logical value (T or F), or a character string enclosed in single quotes. Each header begins with a series of required keywords to describe the datatype and format of the following data unit, if any. Any number of other optional keywords can be included in the header to provide other descriptive information about the data. For the most part, the CFITSIO routines automatically write the required FITS keywords for each HDU, so you, the programmer, usually do not need to worry about them. % =================================================================== \section{Installing and Using CFITSIO} First, you should download the CFITSIO software and the set of example FITS utility programs from the web site at http://heasarc.gsfc.nasa.gov/fitsio. The example programs illustrate how to perform many common types of operations on FITS files using CFITSIO. They are also useful when writing a new program because it is often easier to take a copy of one of these utility programs as a template and then modify it for your own purposes, rather than writing the new program completely from scratch. To build the CFITSIO library on Unix platforms, `untar' the source code distribution file and then execute the following commands in the directory containing the source code: \begin{verbatim} > ./configure [--prefix=/target/installation/path] > make (or 'make shared') > make install (this step is optional) \end{verbatim} The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, \begin{verbatim} > ./configure --prefix=/usr1/local \end{verbatim} will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). Pre-compiled versions of the CFITSIO DLL library are available for PCs. On Macintosh machines, refer to the README.MacOS file for instructions on building CFITSIO using CodeWarrior. Any programs that use CFITSIO must of course be linked with the CFITSIO library when creating the executable file. The exact procedure for linking a program depends on your software environment, but on Unix platforms, the command line to compile and link a program will look something like this: \begin{verbatim} gcc -o myprog myprog.c -L. -lcfitsio -lm -lnsl -lsocket \end{verbatim} You may not need to include all of the 'm', 'nsl', and 'socket' system libraries on your particular machine. To find out what libraries are required on your (Unix) system, type {\tt'make testprog'} and see what libraries are then included on the resulting link line. \newpage % =================================================================== \section{Example Programs} Before describing the individual CFITSIO routines in detail, it is instructive to first look at an actual program. The names of the CFITSIO routines are fairly descriptive (they all begin with {\tt fits\_}, so it should be reasonably clear what this program does: \begin{verbatim} ---------------------------------------------------------------- #include #include 1: #include "fitsio.h" int main(int argc, char *argv[]) { 2: fitsfile *fptr; char card[FLEN_CARD]; 3: int status = 0, nkeys, ii; /* MUST initialize status */ 4: fits_open_file(&fptr, argv[1], READONLY, &status); fits_get_hdrspace(fptr, &nkeys, NULL, &status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(fptr, ii, card, &status); /* read keyword */ printf("%s\n", card); } printf("END\n\n"); /* terminate listing with END */ fits_close_file(fptr, &status); if (status) /* print any error messages */ 5: fits_report_error(stderr, status); return(status); } ---------------------------------------------------------------- \end{verbatim} This program opens the specified FITS file and prints out all the header keywords in the current HDU. Some other points to notice about the program are: \begin{enumerate} \item The {\tt fitsio.h} header file must be included to define the various routines and symbols used in CFITSIO. \item The {\tt fitsfile} parameter is the first argument in almost every CFITSIO routine. It is a pointer to a structure (defined in {\tt fitsio.h}) that stores information about the particular FITS file that the routine will operate on. Memory for this structure is automatically allocated when the file is first opened or created, and is freed when the file is closed. \item Almost every CFITSIO routine has a {\tt status} parameter as the last argument. The status value is also usually returned as the value of the function itself. Normally status = 0, and a positive status value indicates an error of some sort. The status variable must always be initialized to zero before use, because if status is greater than zero on input then the CFITSIO routines will simply return without doing anything. This `inherited status' feature, where each CFITSIO routine inherits the status from the previous routine, makes it unnecessary to check the status value after every single CFITSIO routine call. Generally you should check the status after an especially important or complicated routine has been called, or after a block of closely related CFITSIO calls. This example program has taken this feature to the extreme and only checks the status value at the very end of the program. \item In this example program the file name to be opened is given as an argument on the command line ({\tt arg[1]}). If the file contains more than 1 HDU or extension, you can specify which particular HDU to be opened by enclosing the name or number of the HDU in square brackets following the root name of the file. For example, {\tt file.fts[0]} opens the primary array, while {\tt file.fts[2]} will move to and open the 2nd extension in the file, and {\tt file.fit[EVENTS]} will open the extension that has a {\tt EXTNAME = 'EVENTS'} keyword in the header. Note that on the Unix command line you must enclose the file name in single or double quote characters if the name contains special characters such as `[' or `]'. All of the CFITSIO routines which read or write header keywords, image data, or table data operate only within the currently opened HDU in the file. To read or write information in a different HDU you must first explicitly move to that HDU (see the {\tt fits\_movabs\_hdu} and {\tt fits\_movrel\_hdu} routines in section 4.3). \item The {\tt fits\_report\_error} routine provides a convenient way to print out diagnostic messages about any error that may have occurred. \end{enumerate} A set of example FITS utility programs are available from the CFITSIO web site at \newline http://heasarc.gsfc.nasa.gov/docs/software/fitsio/cexamples.html. These are real working programs which illustrate how to read, write, and modify FITS files using the CFITSIO library. Most of these programs are very short, containing only a few 10s of lines of executable code or less, yet they perform quite useful operations on FITS files. Running each program without any command line arguments will produce a short description of how to use the program. The currently available programs are: \begin{quote} fitscopy - copy a file \newline listhead - list header keywords \newline liststruc - show the structure of a FITS file. \newline modhead - write or modify a header keyword \newline imarith - add, subtract, multiply, or divide 2 images \newline imlist - list pixel values in an image \newline imstat - compute mean, min, and max pixel values in an image \newline tablist - display the contents of a FITS table \newline tabcalc - general table calculator \end{quote} \newpage % =================================================================== \section{CFITSIO Routines} This chapter describes the main CFITSIO routines that can be used to perform the most common types of operations on FITS files. % =================================================================== {\bf \subsection{Error Reporting}} \begin{verbatim} void fits_report_error(FILE *stream, int status) void fits_get_errstatus(int status, char *err_text) float fits_get_version(float *version) \end{verbatim} The first routine prints out information about any error that has occurred. Whenever any CFITSIO routine encounters an error it usually writes a message describing the nature of the error to an internal error message stack and then returns with a positive integer status value. Passing the error status value to this routine will cause a generic description of the error and all the messages from the internal CFITSIO error stack to be printed to the specified stream. The {\tt stream} parameter is usually set equal to {\tt "stdout"} or {\tt "stderr"}. The second routine simply returns a 30-character descriptive error message corresponding to the input status value. The last routine returns the current CFITSIO library version number. % =================================================================== {\bf \subsection{File Open/Close Routines}} \begin{verbatim} int fits_open_file( fitsfile **fptr, char *filename, int mode, int *status) int fits_open_data( fitsfile **fptr, char *filename, int mode, int *status) int fits_open_table(fitsfile **fptr, char *filename, int mode, int *status) int fits_open_image(fitsfile **fptr, char *filename, int mode, int *status) int fits_create_file(fitsfile **fptr, char *filename, int *status) int fits_close_file(fitsfile *fptr, int *status) \end{verbatim} These routines open or close a file. The first {\tt fitsfile} parameter in these and nearly every other CFITSIO routine is a pointer to a structure that CFITSIO uses to store relevant parameters about each opened file. You should never directly read or write any information in this structure. Memory for this structure is allocated automatically when the file is opened or created, and is freed when the file is closed. The {\tt mode} parameter in the {\tt fits\_open\_xxxx} set of routines can be set to either {\tt READONLY} or {\tt READWRITE} to select the type of file access that will be allowed. These symbolic constants are defined in {\tt fitsio.h}. The {\tt fits\_open\_file} routine opens the file and positions the internal file pointer to the beginning of the file, or to the specified extension if an extension name or number is appended to the file name (see the later section on ``CFITSIO File Names and Filters'' for a description of the syntax). {\tt fits\_open\_data} behaves similarly except that it will move to the first HDU containing significant data if a HDU name or number to open is not explicitly specified as part of the filename. It will move to the first IMAGE HDU with NAXIS greater than 0, or the first table that does not contain the strings `GTI' (a Good Time Interval extension) or `OBSTABLE' in the EXTNAME keyword value. The {\tt fits\_open\_table} and {\tt fits\_open\_image} routines are similar except that they will move to the first significant table HDU or image HDU, respectively if a HDU name of number is not specified as part of the input file name. When opening an existing file, the {\tt filename} can include optional arguments, enclosed in square brackets that specify filtering operations that should be applied to the input file. For example, \begin{verbatim} myfile.fit[EVENTS][counts > 0] \end{verbatim} opens the table in the EVENTS extension and creates a virtual table by selecting only those rows where the COUNTS column value is greater than 0. See section 5 for more examples of these powerful filtering capabilities. In {\tt fits\_create\_file}, the {\tt filename} is simply the root name of the file to be created. You can overwrite an existing file by prefixing the name with a `!' character (on the Unix command line this must be prefixed with a backslash, as in \verb+`\!file.fit'+). If the file name ends with {\tt .gz} the file will be compressed using the gzip algorithm. If the filename is {\tt stdout} or {\tt "-"} (a single dash character) then the output file will be piped to the stdout stream. You can chain several tasks together by writing the output from the first task to {\tt stdout} and then reading the input file in the 2nd task from {\tt stdin} or {\tt "-"}. % =================================================================== {\bf \subsection{HDU-level Routines}} The routines listed in this section operate on Header-Data Units (HDUs) in a file. \begin{verbatim} _______________________________________________________________ int fits_get_num_hdus(fitsfile *fptr, int *hdunum, int *status) int fits_get_hdu_num(fitsfile *fptr, int *hdunum) \end{verbatim} The first routines returns the total number of HDUs in the FITS file, and the second routine returns the position of the currently opened HDU in the FITS file (starting with 1, not 0). \begin{verbatim} __________________________________________________________________________ int fits_movabs_hdu(fitsfile *fptr, int hdunum, int *hdutype, int *status) int fits_movrel_hdu(fitsfile *fptr, int nmove, int *hdutype, int *status) int fits_movnam_hdu(fitsfile *fptr, int hdutype, char *extname, int extver, int *status) \end{verbatim} These routines enable you to move to a different HDU in the file. Most of the CFITSIO functions which read or write keywords or data operate only on the currently opened HDU in the file. The first routine moves to the specified absolute HDU number in the FITS file (the first HDU = 1), whereas the second routine moves a relative number of HDUs forward or backward from the currently open HDU. The {\tt hdutype} parameter returns the type of the newly opened HDU, and will be equal to one of these symbolic constant values: {\tt IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL}. {\tt hdutype} may be set to NULL if it is not needed. The third routine moves to the (first) HDU that matches the input extension type, name, and version number, as given by the {\tt XTENSION, EXTNAME} (or {\tt HDUNAME}) and {\tt EXTVER} keywords. If the input value of {\tt extver} = 0, then the version number will be ignored when looking for a matching HDU. \begin{verbatim} _________________________________________________________________ int fits_get_hdu_type(fitsfile *fptr, int *hdutype, int *status) \end{verbatim} Get the type of the current HDU in the FITS file: {\tt IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL}. \begin{verbatim} ____________________________________________________________________ int fits_copy_hdu(fitsfile *infptr, fitsfile *outfptr, int morekeys, int *status) int fits_copy_file(fitsfile *infptr, fitsfile *outfptr, int previous, int current, int following, > int *status) \end{verbatim} The first routine copies the current HDU from the FITS file associated with infptr and appends it to the end of the FITS file associated with outfptr. Space may be reserved for {\tt morekeys} additional keywords in the output header. The second routine copies any HDUs previous to the current HDU, and/or the current HDU, and/or any HDUs following the current HDU, depending on the value (True or False) of {\tt previous, current}, and {\tt following}, respectively. For example, \begin{verbatim} fits_copy_file(infptr, outfptr, 0, 1, 1, &status); \end{verbatim} will copy the current HDU and any HDUs that follow it from the input to the output file, but it will not copy any HDUs preceding the current HDU. \newpage % =================================================================== \subsection{Image I/O Routines} This section lists the more important CFITSIO routines which operate on FITS images. \begin{verbatim} _______________________________________________________________ int fits_get_img_type(fitsfile *fptr, int *bitpix, int *status) int fits_get_img_dim( fitsfile *fptr, int *naxis, int *status) int fits_get_img_size(fitsfile *fptr, int maxdim, long *naxes, int *status) int fits_get_img_param(fitsfile *fptr, int maxdim, int *bitpix, int *naxis, long *naxes, int *status) \end{verbatim} Get information about the currently opened image HDU. The first routine returns the datatype of the image as (defined by the {\tt BITPIX} keyword), which can have the following symbolic constant values: \begin{verbatim} BYTE_IMG = 8 ( 8-bit byte pixels, 0 - 255) SHORT_IMG = 16 (16 bit integer pixels) LONG_IMG = 32 (32-bit integer pixels) LONGLONG_IMG = 64 (64-bit integer pixels) FLOAT_IMG = -32 (32-bit floating point pixels) DOUBLE_IMG = -64 (64-bit floating point pixels) \end{verbatim} The second and third routines return the number of dimensions in the image (from the {\tt NAXIS} keyword), and the sizes of each dimension (from the {\tt NAXIS1, NAXIS2}, etc. keywords). The last routine simply combines the function of the first 3 routines. The input {\tt maxdim} parameter in this routine gives the maximum number dimensions that may be returned (i.e., the dimension of the {\tt naxes} array) \begin{verbatim} __________________________________________________________ int fits_create_img(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status) \end{verbatim} Create an image HDU by writing the required keywords which define the structure of the image. The 2nd through 4th parameters specified the datatype, the number of dimensions, and the sizes of the dimensions. The allowed values of the {\tt bitpix} parameter are listed above in the description of the {\tt fits\_get\_img\_type} routine. If the FITS file pointed to by {\tt fptr} is empty (previously created with {\tt fits\_create\_file}) then this routine creates a primary array in the file, otherwise a new IMAGE extension is appended to end of the file following the other HDUs in the file. \begin{verbatim} ______________________________________________________________ int fits_write_pix(fitsfile *fptr, int datatype, long *fpixel, long nelements, void *array, int *status); int fits_write_pixnull(fitsfile *fptr, int datatype, long *fpixel, long nelements, void *array, void *nulval, int *status); int fits_read_pix(fitsfile *fptr, int datatype, long *fpixel, long nelements, void *nulval, void *array, int *anynul, int *status) \end{verbatim} Read or write all or part of the FITS image. There are 2 different 'write' pixel routines: The first simply writes the input array of pixels to the FITS file. The second is similar, except that it substitutes the appropriate null pixel value in the FITS file for any pixels which have a value equal to {\tt *nulval} (note that this parameter gives the address of the null pixel value, not the value itself). Similarly, when reading an image, CFITSIO will substitute the value given by {\tt nulval} for any undefined pixels in the image, unless {\tt nulval = NULL}, in which case no checks will be made for undefined pixels when reading the FITS image. The {\tt fpixel} parameter in these routines is an array which gives the coordinate in each dimension of the first pixel to be read or written, and {\tt nelements} is the total number of pixels to read or write. {\tt array} is the address of an array which either contains the pixel values to be written, or will hold the values of the pixels that are read. When reading, {\tt array} must have been allocated large enough to hold all the returned pixel values. These routines starts at the {\tt fpixel} location and then read or write the {\tt nelements} pixels, continuing on successive rows of the image if necessary. For example, to write an entire 2D image, set {\tt fpixel[0] = fpixel[1] = 1}, and {\tt nelements = NAXIS1 * NAXIS2}. Or to read just the 10th row of the image, set {\tt fpixel[0] = 1, fpixel[1] = 10}, and {\tt nelements = NAXIS1}. The {\tt datatype} parameter specifies the datatype of the C {\tt array} in the program, which need not be the same as the datatype of the FITS image itself. If the datatypes differ then CFITSIO will convert the data as it is read or written. The following symbolic constants are allowed for the value of {\tt datatype}: \begin{verbatim} TBYTE unsigned char TSBYTE signed char TSHORT signed short TUSHORT unsigned short TINT signed int TUINT unsigned int TLONG signed long TLONGLONG signed 8-byte integer TULONG unsigned long TFLOAT float TDOUBLE double \end{verbatim} \begin{verbatim} _________________________________________________________________ int fits_write_subset(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, DTYPE *array, > int *status) int fits_read_subset(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, long *inc, void *nulval, void *array, int *anynul, int *status) \end{verbatim} Read or write a rectangular section of the FITS image. These are very similar to {\tt fits\_write\_pix} and {\tt fits\_read\_pix} except that you specify the last pixel coordinate (the upper right corner of the section) instead of the number of pixels to be read. The read routine also has an {\tt inc} parameter which can be used to read only every {\tt inc-th} pixel along each dimension of the image. Normally {\tt inc[0] = inc[1] = 1} to read every pixel in a 2D image. To read every other pixel in the entire 2D image, set \begin{verbatim} fpixel[0] = fpixel[1] = 1 lpixel[0] = {NAXIS1} lpixel[1] = {NAXIS2} inc[0] = inc[1] = 2 \end{verbatim} Or, to read the 8th row of a 2D image, set \begin{verbatim} fpixel[0] = 1 fpixel[1] = 8 lpixel[0] = {NAXIS1} lpixel[1] = 8 inc[0] = inc[1] = 1 \end{verbatim} \newpage % =================================================================== \subsection{Table I/O Routines} This section lists the most important CFITSIO routines which operate on FITS tables. \begin{verbatim} __________________________________________________________________________ int fits_create_tbl(fitsfile *fptr, int tbltype, long nrows, int tfields, char *ttype[],char *tform[], char *tunit[], char *extname, int *status) \end{verbatim} Create a new table extension by writing the required keywords that define the table structure. The required null primary array will be created first if the file is initially completely empty. {\tt tbltype} defines the type of table and can have values of {\tt ASCII\_TBL or BINARY\_TBL}. Binary tables are generally preferred because they are more efficient and support a greater range of column datatypes than ASCII tables. The {\tt nrows} parameter gives the initial number of empty rows to be allocated for the table; this should normally be set to 0. The {\tt tfields} parameter gives the number of columns in the table (maximum = 999). The {\tt ttype, tform}, and {\tt tunit} parameters give the name, datatype, and physical units of each column, and {\tt extname} gives the name for the table (the value of the {\tt EXTNAME} keyword). The FITS Standard recommends that only letters, digits, and the underscore character be used in column names with no embedded spaces. It is recommended that all the column names in a given table be unique within the first 8 characters. The following table shows the TFORM column format values that are allowed in ASCII tables and in binary tables: \begin{verbatim} ASCII Table Column Format Codes ------------------------------- (w = column width, d = no. of decimal places to display) Aw - character string Iw - integer Fw.d - fixed floating point Ew.d - exponential floating point Dw.d - exponential floating point Binary Table Column Format Codes -------------------------------- (r = vector length, default = 1) rA - character string rAw - array of strings, each of length w rL - logical rX - bit rB - unsigned byte rS - signed byte ** rI - signed 16-bit integer rU - unsigned 16-bit integer ** rJ - signed 32-bit integer rV - unsigned 32-bit integer ** rK - signed 64-bit integer rE - 32-bit floating point rD - 64-bit floating point rC - 32-bit complex pair rM - 64-bit complex pair ** The S, U and V format codes are not actual legal TFORMn values. CFITSIO substitutes the somewhat more complicated set of keywords that are used to represent unsigned integers or signed bytes. \end{verbatim} The {\tt tunit} and {\tt extname} parameters are optional and may be set to NULL if they are not needed. Note that it may be easier to create a new table by copying the header from another existing table with {\tt fits\_copy\_header} rather than calling this routine. \begin{verbatim} _______________________________________________________________ int fits_get_num_rows(fitsfile *fptr, long *nrows, int *status) int fits_get_num_cols(fitsfile *fptr, int *ncols, int *status) \end{verbatim} Get the number of rows or columns in the current FITS table. The number of rows is given by the {\tt NAXIS2} keyword and the number of columns is given by the {\tt TFIELDS} keyword in the header of the table. \begin{verbatim} _______________________________________________________________ int fits_get_colnum(fitsfile *fptr, int casesen, char *template, int *colnum, int *status) int fits_get_colname(fitsfile *fptr, int casesen, char *template, char *colname, int *colnum, int *status) \end{verbatim} Get the column number (starting with 1, not 0) of the column whose name matches the specified template name. The only difference in these 2 routines is that the 2nd one also returns the name of the column that matched the template string. Normally, {\tt casesen} should be set to {\tt CASEINSEN}, but it may be set to {\tt CASESEN} to force the name matching to be case-sensitive. The input {\tt template} string gives the name of the desired column and may include wildcard characters: a `*' matches any sequence of characters (including zero characters), `?' matches any single character, and `\#' matches any consecutive string of decimal digits (0-9). If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to {\tt COL\_NOT\_UNIQUE} as a warning that a unique match was not found. To find the next column that matches the template, call this routine again leaving the input status value equal to {\tt COL\_NOT\_UNIQUE}. Repeat this process until {\tt status = COL\_NOT\_FOUND} is returned. \begin{verbatim} _______________________________________________________________ int fits_get_coltype(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status) int fits_get_eqcoltype(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status) \end{verbatim} Return the datatype, vector repeat count, and the width in bytes of a single column element for column number {\tt colnum}. Allowed values for the returned datatype in ASCII tables are: {\tt TSTRING, TSHORT, TLONG, TFLOAT, and TDOUBLE}. Binary tables support these additional types: {\tt TLOGICAL, TBIT, TBYTE, TINT32BIT, TCOMPLEX and TDBLCOMPLEX}. The negative of the datatype code value is returned if it is a variable length array column. These 2 routines are similar, except that in the case of scaled integer columns the 2nd routine, fit\_get\_eqcoltype, returns the 'equivalent' datatype that is needed to store the scaled values, which is not necessarily the same as the physical datatype of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be TUSHORT, not TSHORT. Or, if TSCALn or TZEROn are not integers, then the equivalent datatype will be returned as TFLOAT or TDOUBLE, depending on the size of the integer. The repeat count is always 1 in ASCII tables. The 'repeat' parameter returns the vector repeat count on the binary table TFORMn keyword value. (ASCII table columns always have repeat = 1). The 'width' parameter returns the width in bytes of a single column element (e.g., a '10D' binary table column will have width = 8, an ASCII table 'F12.2' column will have width = 12, and a binary table'60A' character string column will have width = 60); Note that this routine supports the local convention for specifying arrays of fixed length strings within a binary table character column using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this means that each row of the table contains 5 12-character substrings within the 60-character field, and thus in this case this routine will return typecode = TSTRING, repeat = 60, and width = 12. The number of substings in any binary table character string field can be calculated by (repeat/width). A null pointer may be given for any of the output parameters that are not needed. \begin{verbatim} ____________________________________________________________________________ int fits_insert_rows(fitsfile *fptr, long firstrow, long nrows, int *status) int fits_delete_rows(fitsfile *fptr, long firstrow, long nrows, int *status) int fits_delete_rowrange(fitsfile *fptr, char *rangelist, int *status) int fits_delete_rowlist(fitsfile *fptr, long *rowlist, long nrows, int *stat) \end{verbatim} Insert or delete rows in a table. The blank rows are inserted immediately following row {\tt frow}. Set {\tt frow} = 0 to insert rows at the beginning of the table. The first 'delete' routine deletes {\tt nrows} rows beginning with row {\tt firstrow}. The 2nd delete routine takes an input string listing the rows or row ranges to be deleted (e.g., '2,4-7, 9-12'). The last delete routine takes an input long integer array that specifies each individual row to be deleted. The row lists must be sorted in ascending order. All these routines update the value of the {\tt NAXIS2} keyword to reflect the new number of rows in the table. \begin{verbatim} _________________________________________________________________________ int fits_insert_col(fitsfile *fptr, int colnum, char *ttype, char *tform, int *status) int fits_insert_cols(fitsfile *fptr, int colnum, int ncols, char **ttype, char **tform, int *status) int fits_delete_col(fitsfile *fptr, int colnum, int *status) \end{verbatim} Insert or delete columns in a table. {\tt colnum} gives the position of the column to be inserted or deleted (where the first column of the table is at position 1). {\tt ttype} and {\tt tform} give the column name and column format, where the allowed format codes are listed above in the description of the {\tt fits\_create\_table} routine. The 2nd 'insert' routine inserts multiple columns, where {\tt ncols} is the number of columns to insert, and {\tt ttype} and {\tt tform} are arrays of string pointers in this case. \begin{verbatim} ____________________________________________________________________ int fits_copy_col(fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, int create_col, int *status); \end{verbatim} Copy a column from one table HDU to another. If {\tt create\_col} = TRUE (i.e., not equal to zero), then a new column will be inserted in the output table at position {\tt outcolumn}, otherwise the values in the existing output column will be overwritten. \begin{verbatim} __________________________________________________________________________ int fits_write_col(fitsfile *fptr, int datatype, int colnum, long firstrow, long firstelem, long nelements, void *array, int *status) int fits_write_colnull(fitsfile *fptr, int datatype, int colnum, long firstrow, long firstelem, long nelements, void *array, void *nulval, int *status) int fits_write_col_null(fitsfile *fptr, int colnum, long firstrow, long firstelem, long nelements, int *status) int fits_read_col(fitsfile *fptr, int datatype, int colnum, long firstrow, long firstelem, long nelements, void *nulval, void *array, int *anynul, int *status) \end{verbatim} Write or read elements in column number {\tt colnum}, starting with row {\tt firstsrow} and element {\tt firstelem} (if it is a vector column). {\tt firstelem} is ignored if it is a scalar column. The {\tt nelements} number of elements are read or written continuing on successive rows of the table if necessary. {\tt array} is the address of an array which either contains the values to be written, or will hold the returned values that are read. When reading, {\tt array} must have been allocated large enough to hold all the returned values. There are 3 different 'write' column routines: The first simply writes the input array into the column. The second is similar, except that it substitutes the appropriate null pixel value in the column for any input array values which are equal to {\tt *nulval} (note that this parameter gives the address of the null pixel value, not the value itself). The third write routine sets the specified table elements to a null value. New rows will be automatical added to the table if the write operation extends beyond the current size of the table. When reading a column, CFITSIO will substitute the value given by {\tt nulval} for any undefined elements in the FITS column, unless {\tt nulval} or {\tt *nulval = NULL}, in which case no checks will be made for undefined values when reading the column. {\tt datatype} specifies the datatype of the C {\tt array} in the program, which need not be the same as the intrinsic datatype of the column in the FITS table. The following symbolic constants are allowed for the value of {\tt datatype}: \begin{verbatim} TSTRING array of character string pointers TBYTE unsigned char TSHORT signed short TUSHORT unsigned short TINT signed int TUINT unsigned int TLONG signed long TLONGLONG signed 8-byte integer TULONG unsigned long TFLOAT float TDOUBLE double \end{verbatim} Note that {\tt TSTRING} corresponds to the C {\tt char**} datatype, i.e., a pointer to an array of pointers to an array of characters. Any column, regardless of it's intrinsic datatype, may be read as a {\tt TSTRING} character string. The display format of the returned strings will be determined by the {\tt TDISPn} keyword, if it exists, otherwise a default format will be used depending on the datatype of the column. The {\tt tablist} example utility program (available from the CFITSIO web site) uses this feature to display all the values in a FITS table. \begin{verbatim} _____________________________________________________________________ int fits_select_rows(fitsfile *infptr, fitsfile *outfptr, char *expr, int *status) int fits_calculator(fitsfile *infptr, char *expr, fitsfile *outfptr, char *colname, char *tform, int *status) \end{verbatim} These are 2 of the most powerful routines in the CFITSIO library. (See the full CFITSIO Reference Guide for a description of several related routines). These routines can perform complicated transformations on tables based on an input arithmetic expression which is evaluated for each row of the table. The first routine will select or copy rows of the table for which the expression evaluates to TRUE (i.e., not equal to zero). The second routine writes the value of the expression to a column in the output table. Rather than supplying the expression directly to these routines, the expression may also be written to a text file (continued over multiple lines if necessary) and the name of the file, prepended with a '@' character, may be supplied as the value of the 'expr' parameter (e.g. '@filename.txt'). The arithmetic expression may be a function of any column or keyword in the input table as shown in these examples: \begin{verbatim} Row Selection Expressions: counts > 0 uses COUNTS column value sqrt( X**2 + Y**2) < 10. uses X and Y column values (X > 10) || (X < -10) && (Y == 0) used 'or' and 'and' operators gtifilter() filter on Good Time Intervals regfilter("myregion.reg") filter using a region file @select.txt reads expression from a text file Calculator Expressions: #row % 10 modulus of the row number counts/#exposure Fn of COUNTS column and EXPOSURE keyword dec < 85 ? cos(dec * #deg) : 0 Conditional expression: evaluates to cos(dec) if dec < 85, else 0 (count{-1}+count+count{+1})/3. running mean of the count values in the previous, current, and next rows max(0, min(X, 1000)) returns a value between 0 - 1000 @calc.txt reads expression from a text file \end{verbatim} Most standard mathematical operators and functions are supported. If the expression includes the name of a column, than the value in the current row of the table will be used when evaluating the expression on each row. An offset to an adjacent row can be specified by including the offset value in curly brackets after the column name as shown in one of the examples. Keyword values can be included in the expression by preceding the keyword name with a `\#' sign. See Section 5 of this document for more discussion of the expression syntax. {\tt gtifilter} is a special function which tests whether the {\tt TIME} column value in the input table falls within one or more Good Time Intervals. By default, this function looks for a 'GTI' extension in the same file as the input table. The 'GTI' table contains {\tt START} and {\tt STOP} columns which define the range of each good time interval. See section 5.4.3 for more details. {\tt regfilter} is another special function which selects rows based on whether the spatial position associated with each row is located within in a specified region of the sky. By default, the {\tt X} and {\tt Y} columns in the input table are assumed to give the position of each row. The spatial region is defined in an ASCII text file whose name is given as the argument to the {\tt regfilter} function. See section 5.4.4 for more details. The {\tt infptr} and {\tt outfptr} parameters in these routines may point to the same table or to different tables. In {\tt fits\_select\_rows}, if the input and output tables are the same then the rows that do not satisfy the selection expression will be deleted from the table. Otherwise, if the output table is different from the input table then the selected rows will be copied from the input table to the output table. The output column in {\tt fits\_calculator} may or may not already exist. If it exists then the calculated values will be written to that column, overwriting the existing values. If the column doesn't exist then the new column will be appended to the output table. The {\tt tform} parameter can be used to specify the datatype of the new column (e.g., the {\tt TFORM} keyword value as in {\tt '1E', or '1J'}). If {\tt tform} = NULL then a default datatype will be used, depending on the expression. \begin{verbatim} _____________________________________________________________________ int fits_read_tblbytes(fitsfile *fptr, long firstrow, long firstchar, long nchars, unsigned char *array, int *status) int fits_write_tblbytes (fitsfile *fptr, long firstrow, long firstchar, long nchars, unsigned char *array, int *status) \end{verbatim} These 2 routines provide low-level access to tables and are mainly useful as an efficient way to copy rows of a table from one file to another. These routines simply read or write the specified number of consecutive characters (bytes) in a table, without regard for column boundaries. For example, to read or write the first row of a table, set {\tt firstrow = 1, firstchar = 1}, and {\tt nchars = NAXIS1} where the length of a row is given by the value of the {\tt NAXIS1} header keyword. When reading a table, {\tt array} must have been declared at least {\tt nchars} bytes long to hold the returned string of bytes. \newpage % =================================================================== \subsection{Header Keyword I/O Routines} \nopagebreak The following routines read and write header keywords in the current HDU. \nopagebreak \begin{verbatim} ____________________________________________________________________ int fits_get_hdrspace(fitsfile *fptr, int *keysexist, int *morekeys, int *status) \end{verbatim} \nopagebreak Return the number of existing keywords (not counting the mandatory END keyword) and the amount of empty space currently available for more keywords. The {\tt morekeys} parameter may be set to NULL if it's value is not needed. \begin{verbatim} ___________________________________________________________________________ int fits_read_record(fitsfile *fptr, int keynum, char *record, int *status) int fits_read_card(fitsfile *fptr, char *keyname, char *record, int *status) int fits_read_key(fitsfile *fptr, int datatype, char *keyname, void *value, char *comment, int *status) int fits_find_nextkey(fitsfile *fptr, char **inclist, int ninc, char **exclist, int nexc, char *card, int *status) int fits_read_key_unit(fitsfile *fptr, char *keyname, char *unit, int *status) \end{verbatim} These routines all read a header record in the current HDU. The first routine reads keyword number {\tt keynum} (where the first keyword is at position 1). This routine is most commonly used when sequentially reading every record in the header from beginning to end. The 2nd and 3rd routines read the named keyword and return either the whole record, or the keyword value and comment string. In each case any non-significant trailing blank characters in the strings are truncated. Wild card characters (*, ?, and \#) may be used when specifying the name of the keyword to be read, in which case the first matching keyword is returned. The {\tt datatype} parameter specifies the C datatype of the returned keyword value and can have one of the following symbolic constant values: {\tt TSTRING, TLOGICAL} (== int), {\tt TBYTE}, {\tt TSHORT}, {\tt TUSHORT}, {\tt TINT}, {\tt TUINT}, {\tt TLONG}, {\tt TULONG}, {\tt TFLOAT}, {\tt TDOUBLE}, {\tt TCOMPLEX}, and {\tt TDBLCOMPLEX}. Data type conversion will be performed for numeric values if the intrinsic FITS keyword value does not have the same datatype. The {\tt comment} parameter may be set equal to NULL if the comment string is not needed. The 4th routine provides an easy way to find all the keywords in the header that match one of the name templates in {\tt inclist} and do not match any of the name templates in {\tt exclist}. {\tt ninc} and {\tt nexc} are the number of template strings in {\tt inclist} and {\tt exclist}, respectively. Wild cards (*, ?, and \#) may be used in the templates to match multiple keywords. Each time this routine is called it returns the next matching 80-byte keyword record. It returns status = {\tt KEY\_NO\_EXIST} if there are no more matches. The 5th routine returns the keyword value units string, if any. The units are recorded at the beginning of the keyword comment field enclosed in square brackets. \begin{verbatim} _______________________________________________________________ int fits_write_key(fitsfile *fptr, int datatype, char *keyname, void *value, char *comment, int *status) int fits_update_key(fitsfile *fptr, int datatype, char *keyname, void *value, char *comment, int *status) int fits_write_record(fitsfile *fptr, char *card, int *status) int fits_modify_comment(fitsfile *fptr, char *keyname, char *comment, int *status) int fits_write_key_unit(fitsfile *fptr, char *keyname, char *unit, int *status) \end{verbatim} Write or modify a keyword in the header of the current HDU. The first routine appends the new keyword to the end of the header, whereas the second routine will update the value and comment fields of the keyword if it already exists, otherwise it behaves like the first routine and appends the new keyword. Note that {\tt value} gives the address to the value and not the value itself. The {\tt datatype} parameter specifies the C datatype of the keyword value and may have any of the values listed in the description of the keyword reading routines, above. A NULL may be entered for the comment parameter, in which case the keyword comment field will be unmodified or left blank. The third routine is more primitive and simply writes the 80-character {\tt card} record to the header. It is the programmer's responsibility in this case to ensure that the record conforms to all the FITS format requirements for a header record. The fourth routine modifies the comment string in an existing keyword, and the last routine writes or updates the keyword units string for an existing keyword. (The units are recorded at the beginning of the keyword comment field enclosed in square brackets). \begin{verbatim} ___________________________________________________________________ int fits_write_comment(fitsfile *fptr, char *comment, int *status) int fits_write_history(fitsfile *fptr, char *history, int *status) int fits_write_date(fitsfile *fptr, int *status) \end{verbatim} Write a {\tt COMMENT, HISTORY}, or {\tt DATE} keyword to the current header. The {\tt COMMENT} keyword is typically used to write a comment about the file or the data. The {\tt HISTORY} keyword is typically used to provide information about the history of the processing procedures that have been applied to the data. The {\tt comment} or {\tt history} string will be continued over multiple keywords if it is more than 70 characters long. The {\tt DATE} keyword is used to record the date and time that the FITS file was created. Note that this file creation date is usually different from the date of the observation which obtained the data in the FITS file. The {\tt DATE} keyword value is a character string in 'yyyy-mm-ddThh:mm:ss' format. If a {\tt DATE} keyword already exists in the header, then this routine will update the value with the current system date. \begin{verbatim} ___________________________________________________________________ int fits_delete_record(fitsfile *fptr, int keynum, int *status) int fits_delete_key(fitsfile *fptr, char *keyname, int *status) \end{verbatim} Delete a keyword record. The first routine deletes a keyword at a specified position (the first keyword is at position 1, not 0), whereas the second routine deletes the named keyword. \begin{verbatim} _______________________________________________________________________ int fits_copy_header(fitsfile *infptr, fitsfile *outfptr, int *status) \end{verbatim} Copy all the header keywords from the current HDU associated with infptr to the current HDU associated with outfptr. If the current output HDU is not empty, then a new HDU will be appended to the output file. The output HDU will then have the identical structure as the input HDU, but will contain no data. \newpage % =================================================================== \subsection{Utility Routines} This section lists the most important CFITSIO general utility routines. \begin{verbatim} ___________________________________________________________________ int fits_write_chksum( fitsfile *fptr, int *status) int fits_verify_chksum(fitsfile *fptr, int *dataok, int *hduok, int *status) \end{verbatim} These routines compute or validate the checksums for the currenrt HDU. The {\tt DATASUM} keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. The {\tt CHECKSUM} keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. The returned {\tt dataok} and {\tt hduok} parameters will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the {\tt DATASUM} or {\tt CHECKSUM} keyword is not present, or value = -1 if the computed checksum is not correct. \begin{verbatim} ___________________________________________________________________ int fits_parse_value(char *card, char *value, char *comment, int *status) int fits_get_keytype(char *value, char *dtype, int *status) int fits_get_keyclass(char *card) int fits_parse_template(char *template, char *card, int *keytype, int *status) \end{verbatim} {\tt fits\_parse\_value} parses the input 80-chararacter header keyword record, returning the value (as a literal character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then a null value string is returned and the comment string is set equal to column 9 - 80 of the input string. {\tt fits\_get\_keytype} parses the keyword value string to determine its datatype. {\tt dtype} returns with a value of 'C', 'L', 'I', 'F' or 'X', for character string, logical, integer, floating point, or complex, respectively. {\tt fits\_get\_keyclass} returns a classification code that indicates the classification type of the input keyword record (e.g., a required structural keyword, a TDIM keyword, a WCS keyword, a comment keyword, etc. See the CFITSIO Reference Guide for a list of the different classification codes. {\tt fits\_parse\_template} takes an input free format keyword template string and returns a formatted 80*char record that satisfies all the FITS requirements for a header keyword record. The template should generally contain 3 tokens: the keyword name, the keyword value, and the keyword comment string. The returned {\tt keytype} parameter indicates whether the keyword is a COMMENT keyword or not. See the CFITSIO Reference Guide for more details. \newpage % =================================================================== \section{CFITSIO File Names and Filters} \subsection{Creating New Files} When creating a new output file on magnetic disk with {\tt fits\_create\_file} the following features are supported. \begin{itemize} \item Overwriting, or 'Clobbering' an Existing File If the filename is preceded by an exclamation point (!) then if that file already exists it will be deleted prior to creating the new FITS file. Otherwise if there is an existing file with the same name, CFITSIO will not overwrite the existing file and will return an error status code. Note that the exclamation point is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. \item Compressed Output Files If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. One can also specify that any images written to the output file should be compressed using the newly developed `tile-compression' algorithm by appending `[compress]' to the name of the disk file (as in {\tt myfile.fits[compress]}). Refer to the CFITSIO User's Reference Guide for more information about this new image compression format. \item Using a Template to Create a New FITS File The structure of any new FITS file that is to be created may be defined in an ASCII template file. If the name of the template file is appended to the name of the FITS file itself, enclosed in parenthesis (e.g., {\tt 'newfile.fits(template.txt)'}) then CFITSIO will create a FITS file with that structure before opening it for the application to use. The template file basically defines the dimensions and data type of the primary array and any IMAGE extensions, and the names and data types of the columns in any ASCII or binary table extensions. The template file can also be used to define any optional keywords that should be written in any of the HDU headers. The image pixel values and table entry values are all initialized to zero. The application program can then write actual data into the HDUs. See the CFITSIO Reference Guide for for a complete description of the template file syntax. \item Creating a Temporary Scratch File in Memory It is sometimes useful to create a temporary output file when testing an application program. If the name of the file to be created is specified as {\tt mem:} then CFITSIO will create the file in memory where it will persist only until the program closes the file. Use of this {\tt mem:} output file usually enables the program to run faster, and of course the output file does not use up any disk space. \end{itemize} \subsection{Opening Existing Files} When opening a file with {\tt fits\_open\_file}, CFITSIO can read a variety of different input file formats and is not restricted to only reading FITS format files from magnetic disk. The following types of input files are all supported: \begin{itemize} \item FITS files compressed with {\tt zip, gzip} or {\tt compress} If CFITSIO cannot find the specified file to open it will automatically look for a file with the same rootname but with a {\tt .gz, .zip}, or {\tt .Z} extension. If it finds such a compressed file, it will allocate a block of memory and uncompress the file into that memory space. The application program will then transparently open this virtual FITS file in memory. Compressed files can only be opened with 'readonly', not 'readwrite' file access. \item FITS files on the internet, using {\tt ftp} or {\tt http} URLs Simply provide the full URL as the name of the file that you want to open. For example,\linebreak {\tt ftp://legacy.gsfc.nasa.gov/software/fitsio/c/testprog.std}\linebreak will open the CFITSIO test FITS file that is located on the {\tt legacy} machine. These files can only be opened with 'readonly' file access. \item FITS files on {\tt stdin} or {\tt stdout} file streams If the name of the file to be opened is {\tt 'stdin'} or {\tt '-'} (a single dash character) then CFITSIO will read the file from the standard input stream. Similarly, if the output file name is {\tt 'stdout'} or {\tt '-'}, then the file will be written to the standard output stream. In addition, if the output filename is {\tt 'stdout.gz'} or {\tt '-.gz'} then it will be gzip compressed before being written to stdout. This mechanism can be used to pipe FITS files from one task to another without having to write an intermediary FITS file on magnetic disk. \item FITS files that exist only in memory, or shared memory. In some applications, such as real time data acquisition, you may want to have one process write a FITS file into a certain section of computer memory, and then be able to open that file in memory with another process. There is a specialized CFITSIO open routine called {\tt fits\_open\_memfile} that can be used for this purpose. See the ``CFITSIO User's Reference Guide'' for more details. \item IRAF format images (with {\tt .imh} file extensions) CFITSIO supports reading IRAF format images by converting them on the fly into FITS images in memory. The application program then reads this virtual FITS format image in memory. There is currently no support for writing IRAF format images, or for reading or writing IRAF tables. \item Image arrays in raw binary format If the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program. In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. {\tt rawfile.dat[ib512,512]}). The first character inside the brackets defines the datatype of the array: \begin{verbatim} b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point \end{verbatim} An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These datatype characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: \begin{verbatim} raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header \end{verbatim} \end{itemize} \newpage \subsection{Image Filtering} \subsubsection{Extracting a subsection of an image} When specifying the name of an image to be opened, you can select a rectangular subsection of the image to be extracted and opened by the application program. The application program then opens a virtual image that only contains the pixels within the specified subsection. To do this, specify the the range of pixels (start:end) along each axis to be extracted from the original image enclosed in square brackets. You can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the starting pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. In the following examples, assume that {\tt myfile.fits} contains a 512 x 512 pixel 2D image. \begin{verbatim} myfile.fits[201:210, 251:260] - opens a 10 x 10 pixel subimage. myfile.fits[*, 512:257] - opens a 512 x 256 image consisting of all the columns in the input image, but only rows 257 through 512. The image will be flipped along the Y axis since the starting row is greater than the ending row. myfile.fits[*:2, 512:257:2] - creates a 256 x 128 pixel image. Similar to the previous example, but only every other row and column is read from the input image. myfile.fits[-*, *] - creates an image containing all the rows and columns in the input image, but flips it along the X axis. \end{verbatim} If the array to be opened is in an Image extension, and not in the primary array of the file, then you need to specify the extension name or number in square brackets before giving the subsection range, as in {\tt myfile.fits[1][-*, *]} to read the image in the first extension in the file. \subsubsection{Create an Image by Binning Table Columns} You can also create and open a virtual image by binning the values in a pair of columns of a FITS table (in other words, create a 2-D histogram of the values in the 2 columns). This technique is often used in X-ray astronomy where each detected X-ray photon during an observation is recorded in a FITS table. There are typically 2 columns in the table called {\tt X} and {\tt Y} which record the pixel location of that event in a virtual 2D image. To create an image from this table, one just scans the X and Y columns and counts up how many photons were recorded in each pixel of the image. When table binning is specified, CFITSIO creates a temporary FITS primary array in memory by computing the histogram of the values in the specified columns. After the histogram is computed the original FITS file containing the table is closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no extensions). The table binning specifier is enclosed in square brackets following the root filename and table extension name or number and begins with the keyword 'bin', as in: \newline {\tt 'myfile.fits[events][bin (X,Y)]'}. In this case, the X and Y columns in the 'events' table extension are binned up to create the image. The size of the image is usually determined by the {\tt TLMINn} and {\tt TLMAXn} header keywords which give the minimum and maximum allowed pixel values in the columns. For instance if {\tt TLMINn = 1} and {\tt TLMAXn = 4096} for both columns, this would generate a 4096 x 4096 pixel image by default. This is rather large, so you can also specify a pixel binning factor to reduce the image size. For example specifying , {\tt '[bin (X,Y) = 16]'} will use a binning factor of 16, which will produce a 256 x 256 pixel image in the previous example. If the TLMIN and TLMAX keywords don't exist, or you want to override their values, you can specify the image range and binning factor directly, as in {\tt '[bin X = 1:4096:16, Y=1:4096:16]'}. You can also specify the datatype of the created image by appending a b, i, j, r, or d (for 8-bit byte, 16-bit integers, 32-bit integer, 32-bit floating points, or 64-bit double precision floating point, respectively) to the 'bin' keyword (e.g. {\tt '[binr (X,Y)]'} creates a floating point image). If the datatype is not specified then a 32-bit integer image will be created by default. If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y' will be assumed for the 2 axes. Note that this binning specifier is not restricted to only 2D images and can be used to create 1D, 3D, or 4D images as well. It is also possible to specify a weighting factor that is applied during the binning. Please refer to the ``CFITSIO User's Reference Guide'' for more details on these advanced features. \newpage \subsection{Table Filtering} \subsubsection{Column and Keyword Filtering} The column or keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. It can be used to perform the following types of operations. \begin{itemize} \item Append a new column to a table by giving the column name, optionally followed by the datatype in parentheses, followed by an equals sign and the arithmetic expression to be used to compute the value. The datatype is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is not specified then a default datatype will be chosen depending on the expression. \item Create a new header keyword by giving the keyword name, preceded by a pound sign '\#', followed by an equals sign and an arithmetic expression for the value of the keyword. The expression may be a function of other header keyword values. The comment string for the keyword may be specified in parentheses immediately following the keyword name. \item Overwrite the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \item Select a set of columns to be included in the filtered file by listing the column names separated with semi-colons. Wild card characters may be used in the column names to match multiple columns. Any other columns in the input table will not appear in the filtered file. \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!) \item Rename an existing column or keyword with the syntax 'NewName == OldName'. \end{itemize} The column filtering specifier is enclosed in square brackets and begins with the string 'col'. Multiple operations can be performed by separating them with semi-colons. For complex or commonly used operations, you can write the column filter to a text file, and then use it by giving the name of the text file, preceded by a '@' character. Some examples: \begin{verbatim} [col PI=PHA * 1.1 + 0.2] - creates new PI column from PHA values [col rate = counts/exposure] - creates or overwrites the rate column by dividing the counts column by the EXPOSURE keyword value. [col TIME; X; Y] - only the listed columns will appear in the filtered file [col Time;*raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME; Good == STATUS] - deletes the TIME column and renames the STATUS column to GOOD [col @colfilt.txt] - uses the filtering expression in the colfilt.txt text file \end{verbatim} The original file is not changed by this filtering operation, and instead the modifications are made on a temporary copy of the input FITS file (usually in memory), which includes a copy of all the other HDUs in the input file. The original input file is closed and the application program opens the filtered copy of the file. \subsubsection{Row Filtering} The row filter is used to select a subset of the rows from a table based on a boolean expression. A temporary new FITS file is created on the fly (usually in memory) which contains only those rows for which the row filter expression evaluates to true (i.e., not equal to zero). The primary array and any other extensions in the input file are also copied to the temporary file. The original FITS file is closed and the new temporary file is then opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name. For example, {\tt 'file.fits[events][GRADE==50]'} selects only those rows in the EVENTS table where the GRADE column value is equal to 50). The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression also can be written into a text file and then used by giving the filename preceded by a '@' character, as in {\tt '[@rowfilt.txt]'}. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in {\tt \#NAXIS2}. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then inclose the name in '\$' characters as in {\tt \$MAX PHA\$} or {\tt \#\$MAX-PHA\$}. The names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, {\tt'PHA\{-3\}'} will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: \begin{verbatim} "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ \end{verbatim} Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive): \begin{verbatim} "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(x,y) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "modulus" i % j "random # [0.0,1.0)" random() "minimum" min(x,y) "maximum" max(x,y) "if-then-else" b?x:y \end{verbatim} The following type casting operators are available, where the inclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: \begin{verbatim} "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i \end{verbatim} Several constants are built in for use in numerical expressions: \begin{verbatim} #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string \end{verbatim} A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (For example, {\tt "col1==-99 ? \#NULL : col1"}). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, {\tt value\_1} and {\tt value\_2} can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: \begin{verbatim} near(value_1, value_2, tolerance) \end{verbatim} When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: \begin{verbatim} ISNULL(x) DEFNULL(x,y) \end{verbatim} The former returns a boolean value of TRUE if the argument x is NULL. The later "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. Bit masks can be used to select out rows from bit columns ({\tt TFORMn = \#X}) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: \begin{verbatim} binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) \end{verbatim} In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: \begin{verbatim} flags == b0010011 or flags .eq. b10011 \end{verbatim} It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: \begin{verbatim} flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx \end{verbatim} Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: \begin{verbatim} (!flags) == b1101100 (flags & b1000001) == bx000001 \end{verbatim} Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. \subsubsection{Good Time Interval Filtering} A common filtering method involves selecting rows which have a time value which lies within what is called a Good Time Interval or GTI. The time intervals are defined in a separate FITS table extension which contains 2 columns giving the start and stop time of each good interval. The filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in the GTI extension. A high level function, gtifilter(a,b,c,d), is available which evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is \begin{verbatim} gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) \end{verbatim} where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quote characters may be used. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression {\tt "gtifilter()"} is equivalent to \begin{verbatim} gtifilter( "", TIME, "*START*", "*STOP*" ) \end{verbatim} This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. \subsubsection{Spatial Region Filtering} Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is \begin{verbatim} regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) \end{verbatim} where each "[ ]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. The region file is an ASCII text file which contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. In its simpliest form, (e.g., {\tt regfilter("region.reg")} ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in \begin{verbatim} regfilter("region.reg", XPOS, YPOS) \end{verbatim} Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: \begin{verbatim} regfilter("rosat.reg", X/32.+.5, Y/32.+.5) \end{verbatim} Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): \begin{verbatim} Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) \end{verbatim} where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semimajor/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. \subsubsection{Example Row Filters} \begin{verbatim} [double && mag <= 5.0] - Extract all double stars brighter than fifth magnitude [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. \end{verbatim} \newpage \subsection{Combined Filtering Examples} The previous sections described all the individual types of filters that may be applied to the input file. In this section we show examples which combine several different filters at once. These examples all use the {\tt fitscopy} program that is distributed with the CFITSIO code. It simply copies the input file to the output file. \begin{verbatim} fitscopy rosat.fit out.fit \end{verbatim} This trivial example simply makes an identical copy of the input rosat.fit file without any filtering. \begin{verbatim} fitscopy 'rosat.fit[events][col Time;X;Y][#row < 1000]' out.fit \end{verbatim} The output file contains only the Time, X, and Y columns, and only the first 999 rows from the 'EVENTS' table extension of the input file. All the other HDUs in the input file are copied to the output file without any modification. \begin{verbatim} fitscopy 'rosat.fit[events][PI < 50][bin (Xdet,Ydet) = 16]' image.fit \end{verbatim} This creates an output image by binning the Xdet and Ydet columns of the events table with a pixel binning factor of 16. Only the rows which have a PI energy less than 50 are used to construct this image. The output image file contains a primary array image without any extensions. \begin{verbatim} fitscopy 'rosat.fit[events][gtifilter() && regfilter("pow.reg")]' out.fit \end{verbatim} The filtering expression in this example uses the {\tt gtifilter} function to test whether the TIME column value in each row is within one of the Good Time Intervals defined in the GTI extension in the same input file, and also uses the {\tt regfilter} function to test if the position associated with each row (derived by default from the values in the X and Y columns of the events table) is located within the area defined in the {\tt pow.reg} text region file (which was previously created with the {\tt fv/POW} image display program). Only the rows which satisfy both tests are copied to the output table. \begin{verbatim} fitscopy 'r.fit[evt][PI<50]' stdout | fitscopy stdin[evt][col X,Y] out.fit \end{verbatim} In this somewhat convoluted example, fitscopy is used to first select the rows from the evt extension which have PI less than 50 and write the resulting table out to the stdout stream. This is piped to a 2nd instance of fitscopy (with the Unix `$|$' pipe command) which reads that filtered FITS file from the stdin stream and copies only the X and Y columns from the evt table to the output file. \begin{verbatim} fitscopy 'r.fit[evt][col RAD=sqrt((X-#XCEN)**2+(Y-#YCEN)**2)][rad<100]' out.fit \end{verbatim} This example first creates a new column called RAD which gives the distance between the X,Y coordinate of each event and the coordinate defined by the XCEN and YCEN keywords in the header. Then, only those rows which have a distance less than 100 are copied to the output table. In other words, only the events which are located within 100 pixel units from the (XCEN, YCEN) coordinate are copied to the output table. \begin{verbatim} fitscopy 'ftp://heasarc.gsfc.nasa.gov/rosat.fit[events][bin (X,Y)=16]' img.fit \end{verbatim} This example bins the X and Y columns of the hypothetical ROSAT file at the HEASARC ftp site to create the output image. \begin{verbatim} fitscopy 'raw.fit[i512,512][101:110,51:60]' image.fit \end{verbatim} This example converts the 512 x 512 pixel raw binary 16-bit integer image to a FITS file and copies a 10 x 10 pixel subimage from it to the output FITS image. \newpage \section{CFITSIO Error Status Codes} The following table lists all the error status codes used by CFITSIO. Programmers are encouraged to use the symbolic mnemonics (defined in the file fitsio.h) rather than the actual integer status values to improve the readability of their code. \begin{verbatim} Symbolic Const Value Meaning -------------- ----- ----------------------------------------- 0 OK, no error SAME_FILE 101 input and output files are the same TOO_MANY_FILES 103 tried to open too many FITS files at once FILE_NOT_OPENED 104 could not open the named file FILE_NOT_CREATED 105 could not create the named file WRITE_ERROR 106 error writing to FITS file END_OF_FILE 107 tried to move past end of file READ_ERROR 108 error reading from FITS file FILE_NOT_CLOSED 110 could not close the file ARRAY_TOO_BIG 111 array dimensions exceed internal limit READONLY_FILE 112 Cannot write to readonly file MEMORY_ALLOCATION 113 Could not allocate memory BAD_FILEPTR 114 invalid fitsfile pointer NULL_INPUT_PTR 115 NULL input pointer to routine SEEK_ERROR 116 error seeking position in file BAD_URL_PREFIX 121 invalid URL prefix on file name TOO_MANY_DRIVERS 122 tried to register too many IO drivers DRIVER_INIT_FAILED 123 driver initialization failed NO_MATCHING_DRIVER 124 matching driver is not registered URL_PARSE_ERROR 125 failed to parse input file URL SHARED_BADARG 151 bad argument in shared memory driver SHARED_NULPTR 152 null pointer passed as an argument SHARED_TABFULL 153 no more free shared memory handles SHARED_NOTINIT 154 shared memory driver is not initialized SHARED_IPCERR 155 IPC error returned by a system call SHARED_NOMEM 156 no memory in shared memory driver SHARED_AGAIN 157 resource deadlock would occur SHARED_NOFILE 158 attempt to open/create lock file failed SHARED_NORESIZE 159 shared memory block cannot be resized at the moment HEADER_NOT_EMPTY 201 header already contains keywords KEY_NO_EXIST 202 keyword not found in header KEY_OUT_BOUNDS 203 keyword record number is out of bounds VALUE_UNDEFINED 204 keyword value field is blank NO_QUOTE 205 string is missing the closing quote BAD_KEYCHAR 207 illegal character in keyword name or card BAD_ORDER 208 required keywords out of order NOT_POS_INT 209 keyword value is not a positive integer NO_END 210 couldn't find END keyword BAD_BITPIX 211 illegal BITPIX keyword value BAD_NAXIS 212 illegal NAXIS keyword value BAD_NAXES 213 illegal NAXISn keyword value BAD_PCOUNT 214 illegal PCOUNT keyword value BAD_GCOUNT 215 illegal GCOUNT keyword value BAD_TFIELDS 216 illegal TFIELDS keyword value NEG_WIDTH 217 negative table row size NEG_ROWS 218 negative number of rows in table COL_NOT_FOUND 219 column with this name not found in table BAD_SIMPLE 220 illegal value of SIMPLE keyword NO_SIMPLE 221 Primary array doesn't start with SIMPLE NO_BITPIX 222 Second keyword not BITPIX NO_NAXIS 223 Third keyword not NAXIS NO_NAXES 224 Couldn't find all the NAXISn keywords NO_XTENSION 225 HDU doesn't start with XTENSION keyword NOT_ATABLE 226 the CHDU is not an ASCII table extension NOT_BTABLE 227 the CHDU is not a binary table extension NO_PCOUNT 228 couldn't find PCOUNT keyword NO_GCOUNT 229 couldn't find GCOUNT keyword NO_TFIELDS 230 couldn't find TFIELDS keyword NO_TBCOL 231 couldn't find TBCOLn keyword NO_TFORM 232 couldn't find TFORMn keyword NOT_IMAGE 233 the CHDU is not an IMAGE extension BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength NOT_TABLE 235 the CHDU is not a table COL_TOO_WIDE 236 column is too wide to fit in table COL_NOT_UNIQUE 237 more than 1 column name matches template BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 UNKNOWN_EXT 251 unrecognizable FITS extension type UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION END_JUNK 253 END keyword is not blank BAD_HEADER_FILL 254 Header fill area contains non-blank chars BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) BAD_TFORM 261 illegal TFORM format code BAD_TFORM_DTYPE 262 unrecognizable TFORM datatype code BAD_TDIM 263 illegal TDIMn keyword value BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range BAD_HDU_NUM 301 HDU number < 1 or > MAXHDU BAD_COL_NUM 302 column number < 1 or > tfields NEG_FILE_POS 304 tried to move to negative byte location in file NEG_BYTES 306 tried to read or write negative number of bytes BAD_ROW_NUM 307 illegal starting row number in table BAD_ELEM_NUM 308 illegal starting element number in vector NOT_ASCII_COL 309 this is not an ASCII string column NOT_LOGICAL_COL 310 this is not a logical datatype column BAD_ATABLE_FORMAT 311 ASCII table column has wrong format BAD_BTABLE_FORMAT 312 Binary table column has wrong format NO_NULL 314 null value has not been defined NOT_VARI_LEN 317 this is not a variable length column BAD_DIMEN 320 illegal number of dimensions in array BAD_PIX_NUM 321 first pixel number greater than last pixel ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 NEG_AXIS 323 illegal axis length < 1 NOT_GROUP_TABLE 340 Grouping function error HDU_ALREADY_MEMBER 341 MEMBER_NOT_FOUND 342 GROUP_NOT_FOUND 343 BAD_GROUP_ID 344 TOO_MANY_HDUS_TRACKED 345 HDU_ALREADY_TRACKED 346 BAD_OPTION 347 IDENTICAL_POINTERS 348 BAD_GROUP_ATTACH 349 BAD_GROUP_DETACH 350 NGP_NO_MEMORY 360 malloc failed NGP_READ_ERR 361 read error from file NGP_NUL_PTR 362 null pointer passed as an argument. Passing null pointer as a name of template file raises this error NGP_EMPTY_CURLINE 363 line read seems to be empty (used internally) NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single line twice) NGP_INC_NESTING 365 too deep include file nesting (infinite loop, template includes itself ?) NGP_ERR_FOPEN 366 fopen() failed, cannot open template file NGP_EOF 367 end of file encountered and not expected NGP_BAD_ARG 368 bad arguments passed. Usually means internal parser error. Should not happen NGP_TOKEN_NOT_EXPECT 369 token not expected here BAD_I2C 401 bad int to formatted string conversion BAD_F2C 402 bad float to formatted string conversion BAD_INTKEY 403 can't interpret keyword value as integer BAD_LOGICALKEY 404 can't interpret keyword value as logical BAD_FLOATKEY 405 can't interpret keyword value as float BAD_DOUBLEKEY 406 can't interpret keyword value as double BAD_C2I 407 bad formatted string to int conversion BAD_C2F 408 bad formatted string to float conversion BAD_C2D 409 bad formatted string to double conversion BAD_DATATYPE 410 illegal datatype code value BAD_DECIM 411 bad number of decimal places specified NUM_OVERFLOW 412 overflow during datatype conversion DATA_COMPRESSION_ERR 413 error compressing image DATA_DECOMPRESSION_ERR 414 error uncompressing image BAD_DATE 420 error in date or time conversion PARSE_SYNTAX_ERR 431 syntax error in parser expression PARSE_BAD_TYPE 432 expression did not evaluate to desired type PARSE_LRG_VECTOR 433 vector result too large to return in array PARSE_NO_OUTPUT 434 data parser failed not sent an out column PARSE_BAD_COL 435 bad data encounter while parsing column PARSE_BAD_OUTPUT 436 Output file not of proper type ANGLE_TOO_BIG 501 celestial angle too large for projection BAD_WCS_VAL 502 bad celestial coordinate or pixel value WCS_ERROR 503 error in celestial coordinate calculation BAD_WCS_PROJ 504 unsupported type of celestial projection NO_WCS_KEY 505 celestial coordinate keywords not found APPROX_WCS_KEY 506 approximate wcs keyword values were returned \end{verbatim} \end{document} cfitsio-4.3.1/docs/fitsio.toc0000644000225700000360000001625614456514035015422 0ustar cagordonlhea\contentsline {chapter}{\numberline {1}Introduction }{1} \contentsline {chapter}{\numberline {2} Creating FITSIO/CFITSIO }{3} \contentsline {section}{\numberline {2.1}Building the Library}{3} \contentsline {section}{\numberline {2.2}Testing the Library}{6} \contentsline {section}{\numberline {2.3}Linking Programs with FITSIO}{7} \contentsline {section}{\numberline {2.4}Getting Started with FITSIO}{7} \contentsline {section}{\numberline {2.5}Example Program}{8} \contentsline {section}{\numberline {2.6}Legal Stuff}{9} \contentsline {section}{\numberline {2.7}Acknowledgments}{10} \contentsline {chapter}{\numberline {3} A FITS Primer }{13} \contentsline {chapter}{\numberline {4}FITSIO Conventions and Guidelines }{15} \contentsline {section}{\numberline {4.1}CFITSIO Size Limitations}{15} \contentsline {section}{\numberline {4.2}Multiple Access to the Same FITS File}{16} \contentsline {section}{\numberline {4.3}Current Header Data Unit (CHDU)}{16} \contentsline {section}{\numberline {4.4}Subroutine Names}{16} \contentsline {section}{\numberline {4.5}Subroutine Families and Datatypes}{17} \contentsline {section}{\numberline {4.6}Implicit Data Type Conversion}{17} \contentsline {section}{\numberline {4.7}Data Scaling}{18} \contentsline {section}{\numberline {4.8}Error Status Values and the Error Message Stack}{18} \contentsline {section}{\numberline {4.9}Variable-Length Array Facility in Binary Tables}{19} \contentsline {section}{\numberline {4.10}Support for IEEE Special Values}{20} \contentsline {section}{\numberline {4.11}When the Final Size of the FITS HDU is Unknown}{21} \contentsline {section}{\numberline {4.12}Local FITS Conventions supported by FITSIO}{21} \contentsline {subsection}{\numberline {4.12.1}Support for Long String Keyword Values.}{21} \contentsline {subsection}{\numberline {4.12.2}Arrays of Fixed-Length Strings in Binary Tables}{22} \contentsline {subsection}{\numberline {4.12.3}Keyword Units Strings}{23} \contentsline {subsection}{\numberline {4.12.4}HIERARCH Convention for Extended Keyword Names}{23} \contentsline {section}{\numberline {4.13}Optimizing Code for Maximum Processing Speed}{24} \contentsline {subsection}{\numberline {4.13.1}Background Information: How CFITSIO Manages Data I/O}{24} \contentsline {subsection}{\numberline {4.13.2}Optimization Strategies}{25} \contentsline {chapter}{\numberline {5} Basic Interface Routines }{29} \contentsline {section}{\numberline {5.1}FITSIO Error Status Routines }{29} \contentsline {section}{\numberline {5.2}File I/O Routines}{30} \contentsline {section}{\numberline {5.3}Keyword I/O Routines}{32} \contentsline {section}{\numberline {5.4}Data I/O Routines}{33} \contentsline {chapter}{\numberline {6} Advanced Interface Subroutines }{35} \contentsline {section}{\numberline {6.1}FITS File Open and Close Subroutines: }{35} \contentsline {section}{\numberline {6.2}HDU-Level Operations }{38} \contentsline {section}{\numberline {6.3}Define or Redefine the structure of the CHDU }{41} \contentsline {section}{\numberline {6.4}FITS Header I/O Subroutines}{43} \contentsline {subsection}{\numberline {6.4.1}Header Space and Position Routines }{43} \contentsline {subsection}{\numberline {6.4.2}Read or Write Standard Header Routines }{43} \contentsline {subsection}{\numberline {6.4.3}Write Keyword Subroutines }{45} \contentsline {subsection}{\numberline {6.4.4}Insert Keyword Subroutines }{47} \contentsline {subsection}{\numberline {6.4.5}Read Keyword Subroutines }{47} \contentsline {subsection}{\numberline {6.4.6}Modify Keyword Subroutines }{49} \contentsline {subsection}{\numberline {6.4.7}Update Keyword Subroutines }{50} \contentsline {subsection}{\numberline {6.4.8}Delete Keyword Subroutines }{51} \contentsline {section}{\numberline {6.5}Data Scaling and Undefined Pixel Parameters }{51} \contentsline {section}{\numberline {6.6}FITS Primary Array or IMAGE Extension I/O Subroutines }{52} \contentsline {section}{\numberline {6.7}FITS ASCII and Binary Table Data I/O Subroutines}{56} \contentsline {subsection}{\numberline {6.7.1}Column Information Subroutines }{56} \contentsline {subsection}{\numberline {6.7.2}Low-Level Table Access Subroutines }{58} \contentsline {subsection}{\numberline {6.7.3}Edit Rows or Columns }{59} \contentsline {subsection}{\numberline {6.7.4}Read and Write Column Data Routines }{60} \contentsline {section}{\numberline {6.8}Row Selection and Calculator Routines }{64} \contentsline {section}{\numberline {6.9}Celestial Coordinate System Subroutines }{65} \contentsline {section}{\numberline {6.10}File Checksum Subroutines }{67} \contentsline {section}{\numberline {6.11} Date and Time Utility Routines }{68} \contentsline {section}{\numberline {6.12}General Utility Subroutines }{69} \contentsline {chapter}{\numberline {7} The CFITSIO Iterator Function }{77} \contentsline {chapter}{\numberline {8} Extended File Name Syntax }{79} \contentsline {section}{\numberline {8.1}Overview}{79} \contentsline {section}{\numberline {8.2}Filetype}{82} \contentsline {subsection}{\numberline {8.2.1}Notes about HTTP proxy servers}{82} \contentsline {subsection}{\numberline {8.2.2}Notes about the stream filetype driver}{83} \contentsline {subsection}{\numberline {8.2.3}Notes about the gsiftp filetype}{84} \contentsline {subsection}{\numberline {8.2.4}Notes about the root filetype}{84} \contentsline {subsection}{\numberline {8.2.5}Notes about the shmem filetype:}{86} \contentsline {section}{\numberline {8.3}Base Filename}{86} \contentsline {section}{\numberline {8.4}Output File Name when Opening an Existing File}{88} \contentsline {section}{\numberline {8.5}Template File Name when Creating a New File}{90} \contentsline {section}{\numberline {8.6}Image Tile-Compression Specification}{90} \contentsline {section}{\numberline {8.7}HDU Location Specification}{90} \contentsline {section}{\numberline {8.8}Image Section}{91} \contentsline {section}{\numberline {8.9}Image Transform Filters}{92} \contentsline {section}{\numberline {8.10}Column and Keyword Filtering Specification}{94} \contentsline {section}{\numberline {8.11}Row Filtering Specification}{97} \contentsline {subsection}{\numberline {8.11.1}General Syntax}{97} \contentsline {subsection}{\numberline {8.11.2}Bit Masks}{100} \contentsline {subsection}{\numberline {8.11.3}Vector Columns}{101} \contentsline {subsection}{\numberline {8.11.4}Good Time Interval Filtering and Calculation}{103} \contentsline {subsection}{\numberline {8.11.5}Spatial Region Filtering}{105} \contentsline {subsection}{\numberline {8.11.6}Example Row Filters}{107} \contentsline {section}{\numberline {8.12} Binning or Histogramming Specification}{109} \contentsline {chapter}{\numberline {9}Template Files }{113} \contentsline {section}{\numberline {9.1}Detailed Template Line Format}{113} \contentsline {section}{\numberline {9.2}Auto-indexing of Keywords}{114} \contentsline {section}{\numberline {9.3}Template Parser Directives}{115} \contentsline {section}{\numberline {9.4}Formal Template Syntax}{116} \contentsline {section}{\numberline {9.5}Errors}{116} \contentsline {section}{\numberline {9.6}Examples}{116} \contentsline {chapter}{\numberline {10} Summary of all FITSIO User-Interface Subroutines }{119} \contentsline {chapter}{\numberline {11} Parameter Definitions }{127} \contentsline {chapter}{\numberline {12} FITSIO Error Status Codes }{133} cfitsio-4.3.1/docs/fpackguide.pdf0000644000225700000360000042235014214470324016201 0ustar cagordonlhea%PDF-1.4 %äüöß 2 0 obj <> stream xœÍ\I‹äȾׯȳ¡Ê±(AWV•Á·±|h|òÌŒÇà¹Ìß÷[by±IÊrLCue¦¤ˆxË÷¾·d©}ûíéß7ÿfmn~5·_zúËïnÿ ïªÛ¯zýú¤ýôân^û—ùöõÇÛï?ôͨÛן¿mJïzSFY5ízÝ”S3üîÕÿÃGðÙªü®]}Í—ÝlêUÝÕÛn7õ¿Îêß[µÚŸá¶e‡{îû_¿þñéýëÓÕ†Ì4ÃV¼ÒyCZÓ†4¬ª–M›ýyÚÔŒ?µÝ§ü†Ûô´‡Án&X®wâúyŸÔ¦=Þµìv ¿®¸£~SóÁõ—áç ¶6/ËËToðN,w³˜pÊêûþ ò°´µjOÆlúmŸ=nÇ-øûpm÷bn³ÇŸ'k¿£Èy b‡5?pa…»0ô³”m„gH·aë“1ã­˜—å6O ü,·Â«k&~,ϸÝΛ™ñ'/Lò0ž åÙðÌbV¸q({7ãšF½X^ÓÜôŒ•¬ìmp÷š&XÕxX n¯a1âKàgï¹-úJa|º•7Ï2Jj‹‚1( –Ky}ºF„‡òÊYÚ3‹ðÈdÝâ8Kšq,HzÌ"N›dO¢aù¨(7$x']rÙgvüNjÑøF:“…÷?‚ÿËÆE l ÉŽôoçü©Þ'­öE[W&€.dÂ0bݟϨîüt«³Éðq–,W¶Q^òuŸÌ–V[Sh2 ð¡æÉ ÏjÕÀ!pÿô˜àlAôÓõ ;á…Œë«îY7kÊøô¦µ®7Âp$kÄE‡–ñ¸Ž+­? ¥Cøì.2èÚ¨°+þ̓ta“îNJ=t,–:-À1ù™x~&o–wÁ¿[Œ?c ïÿÙ4ëÈ× eÓø7Ý‹€l²›0ÈbQž.”Û€ò1TI 6eWË!DŠƒIanŒ.CÝ¡Ý̺áÇ! \×þåнÆÒMõRÉùd@¹ãä}?1‡›ó‹Yœ,/ 0ö2wC|z¬ §AMÚP›pì §}Ô-GA†º´!þ B“€êlq{‡h9rÖJxᙤ—|2K$_ÙÎu· ’ï WâÇý‚TFÀÉ —QŠÕü0É÷(/Ù)ƒJBÉ×BT³ÙöBþ‹Szƒ¸@o@넼L’×ÛÎÖlø?L“ˆnă›°S@'ÍWhÂsC¿¢¨é5¤;„ñ`š=~Œÿiy‡¢¸¬çæÁt ê0þcúÃß)±b¹zÞк{ 'p˜'ÌBö!d¡Iú&%ð·_žÔ‹¿ýVêOxR·g®_nzuð9½øçíÏ­ñ q±g}@(f™ù$JphÆÚAŠ<À0öcI‡V’ Õ%$›Mì`Ú­.È9!# xÅ1vÙˆV¿À}ˆäsp⥠®`¸L’©m1üº9ݱo* Zdݫɮ؉Õ*É¡Eqò¥È¶VIÈî»±™½39”"ä‘Öá2\püN¼Å=«ivKú ü™¡(“³è¿=íuÎ,£‚8{ ­âäp=–Š´ô3+˜·-m£ÊžµŠšL­*‹7PBº†%7çS…Ç®‰ŒÅ-§A½’ì˧bWY’¾E†kÙÌ´,e¸<êË´f!ÿk0¾(Z$0ù\· #ÂZ¼¸ ”ó˜ÁdšTÙúœ<ÈD²ŽŽóFtÓ¨Ê]&bv0‡Uƒð¼ä‹UF@&º*h·´2ï<À}Él­Â»Ú&\v2>4™ƒŒÉy>)ý#Ñk–iÿ'|D8ê9 ›‰I+ZÌk¨ÛFBBËÝ‘M¦Èx\Q‚” mh=º„·}e%\+Šñ#,>›(@4'2éP£¬ŠSbd5V†Ährn¯ ã_¿€éÛäÜw.p&O¾QÉÌ›)’ËìÀ±Ì—Èp—KäÊ  1>²XÕpµ#V’¯•îrªï _‹ÕUÒ;ÌlèúNOJ+‰LÍŽB¾CUÿT¾ŠÈ† &àôZ&S±Y„†¾þg°1yÃã(À±<ö„{³›&pß=S‰.:jI˜ NÕ #äIQ™ çÀiS¬hFÐ2Ûü*Ëbg„RâÀRsTô]°‚ë¨Uí+eòíÖR¾‹È6fme°¬Ú?Tn=lh°5B’ÖPfABÄ1|òæI$#±ÐÝTJ\ct6ÑMÏË Q‚^ù¢cFÞºl5Q†<Á¥¦-'Öõ9åà‚´0„Ô¹‹0s¥+“0Ô•“½´^Ø6ÝOmÅP­†€ „²`w-àÙ´¯…mÛs±{Ñ®¡Ë—JÞEvWt‘ºhL½aê‹&ðØkBã”L-a‡¡’DÿQD«T—åã×ݸ:Ê (NYdëK®Xø¤Ž!Ò5c…ü×äýNµ*[ QsÕ1¨Ãˆ˜‡`ÒegÞ³¶èÊÜ×XËfb%ãñê|…Ɉ(ª‡— ­g¹¨õª¥]„É‘®TnŠ0Þ¶¾ü„+;UñÍX°×>ÿ]M÷–o±aX[lÙaþ4ìdºÜȬ›2ÉfH-4>#Aær¯HÖaE)w©»½²^2Õe'O–Þãš3a[ßÒ )1bORAv+ÀçSý¥0)Aå™%ÅëCs6Së6³œ˜ssË79qʺaíˆ.Þ§ÃR5éC½ÔäJ)tEN› ä‚]• ü}‰îÐ^"äò®äI"×ÝdvÁÌ„d_;r‰X?rm¡ô—à°Ê'¼^sÁù¸!}hÉZ7á–grD¯;2qœÇ?±Ž¤ª²qà"Í5„–—½Æ ÐìÍêŃ!³ÿrlöå-!äÐøiÕ›¡,$çù(§C+¢6%ØœúBgÈ9Cù<=ÀOr¶IåÒ~Ù&BçLÂXècÅIœ5Cï§ŠYû¨©y±‰_š¨Sá0Ñi-Zþ>O¢BU6ÎÒ¨Ð(¼]LØÓ5ûž³d'8yqu´î6XF‹i ¥mF” Œ1T2 Q0íå*EóåbÕ¦Kó&e©OÖ¾Ì•Ø û  ­² ­O]^+<ÛÌtâúÍ-ýŒã²×i‚ò…Ž›–¥‹Õ,«O¨\ÏÑɺć@¦ Û£BsÛ|¦*Ës†gÐ:`x1Âj9')"`¿R*(d*ÇÓ(™ˆê½P{I°n!Ÿ¨3‰BH’“…䈻Ê|’ÔÙ\¤á3m'/¬KºVÉÉ¥*®)åÊRê _fž$Oq(<Å™—L¦Nsì뉗4·| _™¨&zén·>O FZà”£êV‡¶Š¨\Ö&ø`†p'±ç¤§êÙÀB¦˜uM †¡|J÷6ù°Ì£)0™´¤PCl÷h`õXöÅtö¡'™µ3ˆ@;"³[ãcb;=®CgR˜wx0âŽ]›}F93ÒY[ÀNK«²ÍÅ\-HÎá¸2°huÒ;óÕs¹Ùû‰‡6·Œãظé MéÎþ—ê²uÇã! ØëŦ*í5FÁ`‰F´(Š!)VZì(Â25Ž$OÞ>^dïÎY;b2˜!M-¡q[AÎeä°zM7‡~ª:õÓ\åè6íiWïI¯YÓšæá0¾ç"Ï'¾811ò Ïe­wìš¼¿­l)PŒê -63Èg5®£Ž¾øÊW(ꛃÖ×jîò;W©.fñzm ¦yðöØÏ*„ÔÑ ÖÖ%š¯A\A;?H—تÂW&¤iß…Áö³¼•”d!rÖ„åòcÁ­ªs$B±Í§z-:zz9ÎÃíÓ™Býܲ-V²;[ᢤÂwEt;ÕïUÖ [SGñL϶¢›ý8Žgí-ãxVakøN1úpœ0ªg‘ÖÀ.… I¤aV3ª]#:/jÜbÃAn\c1 ^‚OŠ>¢”K=“a´HB°As‡ô]äÓ_›‘R<4N§Z¢ÑŃÃÖn;C!€9ÍÕŽæ6yøbÀ)ÑíØÖäD´m†o*QL®'!¦gôÜ¢òåTb“'äO[_1&sâ,Í-ߢ]UIèi{œ†+æ²gT_liFòã@~!Û™Ü`Ò“-‰œèôÚ›e2)»®½¯*§®;Egª!º)?RfguÑ¢¢œSGŸ0ØqªÿŽ[åºùâÉø»Þsƒö†þ·íbû’ç°ë¹ÌÑgïꇾ9¬ð^Za3Ù\Lã7ðÌ“E#1·œ’-Ué8u«Ð-|®$ÿ䂘’áK5™xÉ(…ÉÝøüW%i§Ä½ŠÊP–l¦ÿ‘ý\qÑÝ/šýæYsî¶éHŒ¼iÊùYÉ"äKžËTI£6ÿy±ç;5é cmuý³ám+;ð=í’]ɹò²Îð¹¹Üg›s3¹„u¼íLúˆQ§âëÿÅo>²‘Î÷JÄ tp×cnÓŽ`H²såªí¿ÕéüËòµà;9·zL—ø÷U†ÑÛBòôCÐ#SÁò·ÿ†¡GÐ endstream endobj 3 0 obj 3784 endobj 5 0 obj <> stream xœÅZK‹õ¸Ý÷¯ð:p;zZ6\ Ý÷Èn’†,†¬’™@È2›ùû©‡%KV»›@èïŽ-K¥zœ:U’zÕÓo/ÿ™ü7k3…ÕL¿þôò—ßMÿŽOÕôë?^Þ?^VóºLÁø×yúøûôû§ž´ž>~þñªÜ¶\•UAÍ›¿ªE«íb¯ê¾ÍWuƒ—:\ =2·ÍØ«U<Žßó§ <º¸«yà3œ)>°ns8òbô¦õq"u³ž]i"|¤ÍU?a1šÅ1^ß6 ß±ÎûðÏE£\q¥7}5Â?ðÖYà ¿¤%a"\Òâ¬÷ÍÒ¦XÚ÷ÍX)É'ÆÑwžæç¡$6ˆ¸ÆõIPPÇŒJÁW<à†ßñCš)¿Ua3 Êûnʸë?ò®à%lDã=:©ìb´Z‰Ì÷×?¾<>^~èš^›W·7ý Ÿ5úFËH…¡o3³ ñ5Ä÷¼A7ÄQ”{d`kÑd7ÖàrÕ&êÙ_wàgØÁ¼Ø×•w`&íhú"[eõ6‚ÍÚì`¡ôÆ—_yØ­Õ7õFoô;¾^Å(܇S˜dŸQÞêCz…^F‰ô4Ï®Q78èE{ün-^HŠ(¾’4¯çô€tÕÎŽ@>(t^|r¨øø õEQ­ ´ÏÛ¦Ð$çË1«.ÑÑDõ6Â2ô#ŸÀÐ{qª,e·¥®ø™óyõöá“°2› ¤Ä°ÐÙɇ´Ã ‡ŽÄ(%±–*kg¿»«5N´$|ÝÏÛ˜Ï'#Ÿ2{q¯ö Öƒ‰ý¦þ)_^R˜0qÝѬ±dœAzV˜s“žW›YB·Üi¡f…·q 1íêd\P«³Åä[ÈQÅWó¬³0ŒpšÝ÷g=³SÈžVr[vF«È$’.§˜yld^Ùj†¡vV¦ì!©¹ûÄ2—/©çTªÎ4»h¦¿s1Qa« $# Y>c‹~Õ‰-JK7˜¼)í¼¡êö‘L·Ïú†˜“(˜:9_PŸ¾¾ú¼ˆ cÔ1PWcJíUâfÇj²7ì1d'3¯%Â_7-3ÎÏ+µRe‘ƒ¤Í—#vòÁ4iUsFP÷‡¤u<­_›q4í!Óû•›;`«²VcÝ.µwõµ/•(ùú—«À]AùÙç‡Ô#OÐèsC†´×(ƒAôD`‰:Ý€Bp­’žFœÑ„jG Â-°XwI_‚ÁSž};7E`G––õ\Ô;>²ué´GÐä‚8´cü¤Ê*æÂ;##»µ¤c«`m·a/©ó# 8< ”¹æ–3A·›ÝÁ¶iÍd·Š„¤¾IÞÒG‡A¦æ¾ÞEdîÏš³9æV„¼´³Ø¢<¤Ø¢y3©?)ênIry0Ì]fr!wQݤ•‘š£þ‚ïÂæ ¸ØªÞ°¦€­ÙêÿïꡞÔ+±ôÕÿ÷€ºø©5"-ükhü…ã!Ò°3¥Þ´×³GÕZ½:ô WrÎ|{(ä–ø ê1Êk{ÒzFlâXO-ã ‚«Îu.`etÕŒ…íyÑÂF_È»QŒ§P×,ÉS @(ÜBóÖÍ+*•bÖ ‚;7õx¼É¢‹ @x脌CYòð åXâ:sÅ›L*ä‘}ík(J9Žs‹„yÌ»ÏTÀXÒ½"2uú3ôAFpº cÀÝ÷ ˜nðæÀml§Ÿ(-öº+£Æhù¡I»‚ñ ›HÚ’ÒçÏÙÖaºG$§ ]C"0>µÀcTã\§¢] 3ò`Åço´Ÿì–RYˆlâÁ£žôÞ"’M^ÏärôðKöcbgÃÒX&»T5ó¾m.:„»`ÅR{LjçÈ uT=±r×ß:*ÂŽFÝò*ä¡PáA°6-²šÕ›Špž?†‰uðÈùDžÅ1KBjMP15‰´7Y¨¬Ìž’YvÜ#Ò i§ûYçä̱_uÌÄ(»‡XœQÖڷܽÊÊ rÕ¦˜Ô¥cѵٹÚAÀïèæªÎÏMtKYžu#])–t÷B}!MUdý(ãÔII’?/~82¤kŽ×¡WÆ®¥Ž÷ÍP쬼°ˆÊ&q°1'ûB¿ÈÍg©™#°ï‚DïGDŒ ƒÀ¼sðåó¸è|†§'©”ýZ( Níá–MéñQšº±ÂÁÁÀ@¬ØÀ(Š|r— pK>ºknѹپH.Ñžcäd‚•×Ìï1™¹}r¶|I âó£^Å„X/72§¶-‰¥õ× ¿ãA’„pqÒ¾U¹ÞO<ÀȧÏTçå òÐ Û Ù#V9J —!j b«|&ÞôL$$¦§6Ïé⓬«T{˜ßI%å¦ìg=‡†V4§4d-¹íð¢7érqî+IXfo¯Ú ϯ¼ê‘ (“¹Nä4{ŸG]\<ÜéÔëÔ`|÷W<§ÍÓŠí,B•Ù)òV)SÌH‡ëܰ÷S*,ßI ¢Ý± ‘´öô;‘†Ë¼82àøº¶Øjd8ŽA6IOè'‚¥Õñðßm‰i<¶ˆÓ÷Íë±\¶Æ˜+nŽÜÞ*ûŠ%ù7(¾Y²ø?Lÿ Aq endstream endobj 6 0 obj 3023 endobj 8 0 obj <> stream xœÝ\Ënì¸Ýû+zÀŽø% !àºm/²À@ƒì2 E€Ì&¿’Å*Vñ%Ù3Ù .pawëA±N:õ—uûïÓnKø·*}ó»¾ýúËÓ_ÿtûwþt¹ýúϧ×ϧ]¿˜›×îe½}þýöçí¦Ôíó?ßu<ëûb—õøÛç_žÞ?Ÿ~ªNU«yÑü\Eç~ÊÜÍv<¯w­ãu”=Ô=\ÊÝõû±Þ½<–·Ã©»qñk½Ïæ®Òÿúÿ_Çv7°†õx¶÷Å„ôëñ¬T><®B‡o¼jÅãâm—xæ]},û±ßíkZ|ëíïú .‘ò–¿ûìw³„“øMÓÅàˆp•puß?}ÑáÄüXñ>át½â#¦íXã “?Úåõ-RÇÛhϲ…ëÛð k^Ž 'øþó¸p˜Ê§¼,éÖ—íæU„BeHxŠtÓ?ÐÚE{¾2p:–ظuž¬²°É>lú£€x7Ä ‚ftßÇaçà â‡ÀGxT€ËÏ/ûšÖ.þ(.>ˆk°‡]â 6‰èüÛ6„]–@±¾8Å>H¨ðñi—ɩ닟à©ÞœðÜô8~Opû®¬uòm¤‚Á=­ûˆ¯á±5®xDb‹§°ùZ¿Œ­)SönØq½«ˆˆ@þ°‰v}¾^ßø±¸Â ÝEÈj§VÂFJ3·ø;ã‹À6\19@b§ ÇÄqñê*°æ‡Jk³p§R‘îÃ׸"¤°â>+p˜÷ ÏKŒîFŒa¡ É ýgƒ“ ÂW°˜”Ï o:Ý ,.œ ßÿÕ=Å,Á¯»“I1†rcæ#þ WŠ?Gÿ#°ÌÐêu¸<¿p<£¿p÷rBåîçζmîôs‘ Ž+#½°ñs¨­8^ü¬ñ¼U: o¸B½nAOõV˜œôÓ,郜‰÷‹óÖ—Ý#€aCA5µ€Û#ú`p¢ȱkØTyšµG#ݡ˦…›²0' ÕPoqÀ\PF†Kûn|¶Ó4ˆèzãU`6µƒ ‰Çn×ñ¼ÝÑ)ÑŸ_b²  RPcừ–wÍcb’qÿ\üV/wõ~h<üí°_@Ÿà}×Ð~¼“¢£铈f몞4Á,2ñë¡—ïE“°àd ²7Fb‚šù]8LY ´ ’pK®~˵HUmt“°6¢MRDe_IM!¡LðŽ._ÔOËB;Iôhóê¤çLHxß_Ì{Üï5Ѝô“Šuv³P´éq^Z)ç»h$«7 ‡ ×ïÒ"ü´qe’2šdȸY2â©DU”CÏZßíã°ˆó-nmÎĸº;­R 9‘ú`Ïbö£ç=µj‚™b%èæ&ž)+îeq?™4®P„A²`6Œ'¶«TU4d×ËÆÁù@6,FJìÊTŒ4Gþ¾°o`?ò¾¼ò÷Ñ(99‘@ªóä-™BR(¥e´ 3$²aò.HÇýºÄeê´lîÛªÖ]±šÁK3x¸Í7!¶/=Dˆ€<°žäôƒ…9¶ÈÞS4‚v l[agÌ3ãî³ly>ŸdÚ¼wÄiŒi;9ÄwâöVr¶IÄ%1ìf¦…üÞ“¾ø´Y+ù_Z*_÷E, Š»çœ#?E£)>¼m´TN  5¼¨Cç «}AACË$#ñrô·Ýn9u ŽHþGåƒtåf‰ÓBVUóÞÍFönbuó ‚ XCqèFÔÀT±N0˃v2•Å*,%‰üYd6\ìižsZœ7´«SăQ¦€ÈþÐ)Â&ð F‘+|?EÑÚT36¢ã½Žåw éŸ*©÷ì1m©h¡8çÁ.¬d#! ."ƒ yzKm:Œá…9u©{uK¢™1Èá‘¢B¡)ª\óœåS«X…Êç«&zÛ¸>e‚œ`gþ¦úÔ¥¯$°]ˆSœx,Œ ¹·ºXâr«½ 'h4pã³4rn½õºá‚?rm7ééç”tÄï==@âu“ÑéŒ}ÙùÕ/™Žv¿DDÎ99ð£0GUÆkdºM|®Ã0£b²ž`ô ÚV t#˜ ÌÅK»wTÔ¾é]§ì@´Å_ RJ,QÄmrxò¤ýl‘ >U?œr9&ƒGι¼í¸•ótª&ëDá¹è§Ü¼ v)»¢ðn`ÕÅ@Ĝ煠}>Šv™Ôµì¶5•NõãˆAª.lAÙãÛ÷^J°èàå%¾4J~Ș_¯ðĘõ­€e×½­B^{ÒøÎ>ǸÈj,n)žðjŽŠ0ÑÐø ?+±zÐ°ËøuBk„oS±²Ü"I,{耪"hÑÜ–ÛPÿÐØUã:xnóжB­ô?ʱ¸Ø”":K•tNëÉ o;æ5Š¥®Ôk; .ÇjË—0‡c­AGZHCqƒQ…”W`ÞuQTy¢Ìž*÷_Šxß,d²*ye¼ù{TçÑx=¦w7†5Ža tN&ç1äðÞ.硪þ[Šc<=ðÍ'_\Åi+J&Gûg¨°¦ ¢½jù VäR¹Ã`þœû’‘'XzДN@hcUic0÷ŒÃõû˜Mu’B^@0£¬¶€S.,z;V寠ÜÒœŒ¥ižFèH#ÉgUŽ”ù訪—ÁDª:‰jÅp(urÜBŸuòkN¤Ã§&Yä#Â3°iÄâG*¤Ï'²ÙÆ.#»YOŒA¯ñBRk¡¦-ØYïö½¥ñŽFÞñÄ¥ôÓ.=w§ê ŠEwÍàÃ:^(xÀHq¾¦0@·å° ÉÛ>¤hú3\ãbˆٗ&(äPêx[E2ä³Zp»$™3S~è%TÿTe~&&£T àAÑ#ó’yÏž…Sªï±­+ë6‰æ°¶Æªæ•m•(ŽÖ¡B`¥F^EŽi¯Ô¥µêÀYÔWË¢„< xß„€i‚0,<ýÖÂü(j*â±~Õéž_îåïm«‰•êê 4iޡߡ&{‘š¾P~åÀd}9Ú“©ÝWÛÎ7yçŠ~ƒ£hª£2vìGÖ2·6ö4בwœ$DY—ëÌœf²¬JùÔ¹C £IÊl“ï²Ì¹Å+ædœzüM‘‹O¼¾_’z,ñaó’t ³î *YWc ·´ùr§?¡à‚¿øöæ‡zSñ]ö ®?ÕÅœ˜½-Ñz‚ tRŠ<çg=U‡ìXÄ0Ô3ÐRuûâ,»‚Õ²TÌ?µ¸ñí Õ`›|UÀìpQ¯_Ù‡¯» JFð6]co=ÚE"êºxjJ+ßmkZŸµèí±Z¯T/b<#©:¶” yYßúãÔ´.}v«+:9é`Õå™ËMï8kØ/<ú“@%w¢û¥·¯Ø©uå13HŠ#b…Rë{‡ØÝ‚Î0P+ØŒ}~£˜'ç[ÈF[‰ åfÐyߥèo+ys ~§‹HŒ qÓ:X8V©åÒ\”Qª¯ô†sPßI¤Œg‹Ð›m¢Nš3”ÍZÖñc%v@Nî¼yÁ£ >”µlvY[-ouo®t­œ[9Ib†Ã j«,Ùj¸Éג̨"ÉZë‰3W¢âW"óRõ 2==Ê?oUIô^µej‘K±¨Ú$S¿GWË*êø¤dyGƒ3.Ù2:[oèúD…,&3­+'x¸“ugÿÚA v©¸#qÛ馸ÕégÈç«èµ“Ÿæ~ìªUà¢xÕnkc6§Äô›É6.xbF’EÕ+ªR”ìxÁ°)TÔåóìõF !Ð+=‹w¢ݯ~VBŒ3&F¡B|`£)ÀîJM˜20ðÄeäªA?µ¾íô~·".8£ó³/b´vyd*^œ®)©!‚,+¹›<¤yR9i"#­µ HM“±ŸT=0L3m eg8bÿŒ°|4!s+5Óª²Oj¶a±C·üN³)î$˜Mn†â­““áÅèö…±F‘âüSj$»«9Üïñú‘,„ÕkAúI®Š%¤Né gR`³ù@¤Ä Éã½íýÖFžw½¯%h^ÊFéz=–+¿ÅOO%¯VíLÀh&Œù W‡éÕ]öŠ…ç!nR–ýQê<ž¼Ë]6v1þÊpÉxù2EéTòBCÂú׼^I‰úÒ³>Ó3"%TRkËÉϪ æ\,,®Uœøæ"%i9öXoòuŽ>‹3³•*¿7Í)ÀË÷Ú™\çrB/%tD Š©÷ÒÌJÔ E•ƒÚò÷ý½ó6Í„Y’‚ÕÔbžvÈnt2èþMr^ ¾Ñ‘o3 iæw1l©uýNØ *Nã[q BË›>“÷wi¶¼¼9„9j y¸ª¢ÞH‘ê‘ËÐîùe}ÑÏÜXoÌ¥Ðj$æ©«.Ç+xÑG5µÙšç›¶CŽK3ÉÎ:½ ‘À_UãÓi,žNíêtÛ-ÿºóL ­,ÎЋuņ‚üûý°ô‚•” ⤷XŽ”é`¹eväLlç/ÆSÌ:”6Ó.Sð:tÒ-·}ûª=Ïrk?³ªéŒß}:[v†³Y³y½Ó†|•Íö†Xƹ_ѕÈWKÑ”ÜpXƒ³ÔÔÎÒßš¿—`X¹êÛ…¹áŸ½™ZYwæèþ¯ñvD™È›¤ý"T¦ÖÅp¦²Ÿƒ&fø­&cz¯7üª'§y÷èLô,KæÚ—¸†øÒâÀE&2ÀÔ¼™çBeºWM±ŸÏ}6Ò¯¶Kß•U1‚2šÑµXLük.|I§?jñƒþŽÄO·ÿÌØD endstream endobj 9 0 obj 3761 endobj 11 0 obj <> stream xœÍ[Io$» ¾ûWô9€;ZkŒ»íCn0à ·,@ò.ùû‘HŠ¢–RUÏx`»]¥’ÈÛG–ºêË^þ}QáߤÍe^Íå÷¿½üù—Ñ·êòû?^Þ>_Vsµ—Ùøëtùüëåú¢õåóïßoê±M7eÕ¬ãõ}ó7­¶W{³FÝÕ´½º›Ïú>û›}ßÖ›Zã-ô—|ýW˜i³qMs—Þ·å¦Þ¶W}ƒ¿ãÓpñ¸ìf¦]kâÚéJ|vXÏÃmúNO +Ìð“÷‹«Çç[…K„åtü{‚ßqÛ°+\AÙð«<Œrx™>ZÚÓ}Ós±?úûŒ—‡Ú„#ÅCðè ›Å°¢ØïI Ê„C¾m3-(÷þ0 á…í/Ÿzyÿ|ù­«dm®®R2 -ì=«Ö”ñ&|0üaÞÌ|s ­â¢4hÍR&ERƒ'|èÑË>øk&>㟋Ò×ä5ÑOO¿:·Y:_-xmؼqQ{kÐ"Œžéóí¦>᯻gµr?Iwau’åmí ¹„}Òq°,c&| —óù”fV+IÔ@1>J²¼U5BÇ´®WS»€% \NkFx<˜y¤GÙ(ei9džÎAG+TQ㎴Ä G·ó`÷ËešãO¹û›õÛç?»7LW/oXØLx˜Žæ†úqQaÓM[ØòGÔvà->¢‡°ñ8zo[ÚMÁ·ûúÞB4ìt’ßF‘›]UWÑ$“j;è ‹„…Âa}gÐ"’Èk*ÃÐŒG’Î6ªKÝÜ{†–Ð>¸új­#ÇnÝ–\bkT³ðŠáFëã–ÖhÉÀ R†L"?……¡ÓfØ…š÷m*\°n<Ón³×á«÷Ô½ªë|™ü°U©;¨×&χ$™±XÀ.@ôáÞÈŽÕÐUÊ. 2[¢x…¦YÍe¼ O²–ÜlÙ¼<Ä~» tôíö¬ýùë*o¨ìo"Ó+¼Gxƒ¥õì/*kh€¦³±ï#ÓKæ–l¤ÒÝYS,R:ZVjØ!b³µ-™k µ¢× êòðÆDkx{¨ïç1’‹to„ì%Þ£fa~Q‚vÊ €Ö¶‹è °-ûnÖæ|ë²s›ûè§ S^•M¬iÚ¸þJÎñŸ·›‚gpNEʇ+3Ê`¾iQ Èïðú”x×åSøq€œÐqå†8ÛÓ˜ÑTA€òâ!0Ô¼Ue£¸×µ _¸Ôæ”ù^éÁ¹¾à¤Â.NÑ¥œ³Ê!pd4))r‹…ç>J8’7+CÂÖe~‘á(“¥ü®˜Ñ ³@áAf¨Q¿¨ÖÏéͨ Îg!’n³Ý3°>Ý(Œ²ƒÃ'ÿŠJ¤Ê1‡æ:º—À³¢¼`w[˜H±u®a¬ôUuË߇œ?‚#xÔð„Meóo|3•‡…úàE…±ÙéDžôˆäfépDðlÃÝÞ6!Ÿšƒ3yÎY¦¤»\ˆ´ —8ú)\Ø¢nˆÃx§Ëôö:Å´²Ì«ÅMdÝpÜ €ç !"2 >¥áa2µÓA Ç5H~Ç>qP÷nÅq˜fá,©S`´Y'8£ŒÉ$œ@H¶¸!.œj#>‰4þ‘ÃÕS§1"åèŸÉDŒ'1f/#m"fbÎúÉóYmþ‡×•j˜ XDT±¢©›º,l‚¥»ª4,IW¦—ìÛÕ´`^*ó0TŠË°ÜÖr.Ù÷fnjÏPú†óô !]$â¼a¨•ëL…úLñ¬%øšÌõiƒ)jƒ{þ)êg$=U(P§–ÔÓfÌMšSÅ6ÉD ]ˆ„[¡i.‘‹8€ì®GÝÕžÌs¢'“‹ *k\±¦ï¤àCLh×f…”Û’iÇ}öú lÿ OÊšÿ)~){ô˜y¦Öðp(“nš|Õ­÷n̤Š0;¶~ü¡ò£DÔPÇJ·ÓIõÈ´Ì=ÈÍ® !1˜‡*4aƒcm<ð’ó~/Ó~v%®„ëêTD“qN"êÏ IƘ Çètæü»™>D,9FÙþ 2ÒAZni.E>*¬ü õUL—»:ùÀ#¦«ïmŠß5ún ´SÔ4A²’;'_åM¾ =Ê„ k¨É-g¨9û+˜Ô{½â(ÆöüP?4ëŸ!AùòŠŸƒJdËuj6ö½ v"MÖu¦W·he©]U›˜*ÊR³N˜0õËJ¥Í+“±q݈WxSDbÇYڨطÊÌ¿¨Bpø»¬Ãíø-<ÒÂCyÉKñãÔÒ´ÐõcsXö'»‹È·œWŸ}s5 ×&kòÙwÔqK±Q.×g|Þƒ8­ ÿåÎä“@‰.åT¦íø±óÎlPYRÁ.IcÖüÞsx(ò*ø>_B+ìkÓO×åbÓvC›6€ÎFñ6yçƒÊ@5tEgn ‹Ê”à z˜âøËõ$è…ãæÏ\*¥—¶ ­G& *A<çA”´nmÚ°%q–`Ò+¹7Ÿ£åž§ÓSƒbÅ6Kiòô}°¢ûˆ¸A™áXä{9Åò]˜ÈU*N—žê>2É}Š®+X5ûØ “"˜ø›Wá7tR“Åc§[®íÅÆâÕKâšÆÉ“5-2wϯ9®ìÖ°Æì‘Ü9}>„ÎÀ{ !e§¦>ÏŒ»qG…Hæ¥+}µuI-û´"?Ú˜ô)Ú¥4‘)ÚÜ-CQ.¥ó£I«ð&U èdû>iªo…û¥ôÆ6Ù0¼‚úÛ!àr&“Ãe‰˜³‘ýº>7ú¨?*iæ¯†Ž‹šÁÏE^eÙ 4î“JsŸM]gNâ‹#ψ&ámCXˆ“Á]ty¡UÛ1ùÈD@ë NÑù@ÕlV·É Ï’tÏ,ë#5%¨Í™RÅ¢Ê)ÅßÆã°²×NìYZµyÉ—¥u×v¢\ÚmM_¥mlXúsaÀàÁw Á¬SÛ0)2²Fh‚§KDô£»ó¢¾¬[‹uˆo¨SaVA> rlÐt¢×!“9¨µÈý;,êS;5³¬â(² þÅöÚ*>¬f¥*'!¡7‚ƒºo\Íàé2ÓçuÕPå‹íM?Pp”£ "¯$}Ž¨Î¶ aAN¥aN³Gwœ±O"cÑ–Îý€\‡¥«\0áú5uçJ$÷nUoÚ§MR{JŸJZþÕI`ž7ÂŒœG1!(ªí™¤WCÑ}s«ª©áPòe^Qus"Œî³ùÆ$@1å#â‘À —f˜Vnœ[Ž',!ûj0ð$æå,×,äí CŸFõ4 Ú¹|«:ï[$¼Þ4ò\PôÁWrþ.yÐl ¨Ä|«BP±x~ÕëNø’\ìOK¸Ô³º3ÎEXAÈò³J4³²ÊTˆ+­[ß)÷.܉€ W`y*'Ï‘²"f†$Qµxõ"Qqöóœ›R3Vµ¡¹$Œ|Aö÷Ú,¢gžÇ‚tö?EG (iáÑ‚e9’×qq›¡ò×àJr†žæ>¨‡F-¦J4^õ¶äÜ©;¾~¿Ó´T‘¼¼µ7UØ­lj~¿‰¡võüÓQ¸7¢ÅÈq!ÞÄ}¼õdì“‚üà·DöTÏT bU5=!ž¾3ñšDºÔéã“’l;Ø;©KIÔW[:Õ‚B¹>ys€ßý•[¾MêROf››]S½Å;=/Ãx«G~qï!Z>Ê ‚škmÀ)”xrÙüªpgrר¬MÀó8µÕ â1ËÆQ3[Wó-"äլ㉘·W£ÿzS;9±¥'×¾:ô¿~ãì³]?ˆƒ¯3—Lö ;9ýyºØi((h%ûãþýH‘^·/×>‹™Ê&SOµ b¸ic_ûïœìQ,Šý@V¾?$•Á¯ÁÖALlïÝÏXÚ$ëú¡„²É¬•7&\\Wu£ü©^ÁôviÞËýÿbÚì„°×¹OàÍs}6šVÑW“×îͪŒ ¨2اគ+½¨ºNzÚðŠ—I8ïG%Hó‰Qâ%:øÿü»t© åâµ¶rÖ¥ ].µyäöˆEQ¿ùÁw•n¨ežŽgxtr†Ä5“´J[b™¹fV«Èwoh†¼; Y¹¶ûZèCr"¶÷ƒÒs½‹3½|Ñ «Äx¤5 n0Ï¿ «l|!Zn&ŽHÇ#R¿]þ ®WTí endstream endobj 12 0 obj 3323 endobj 14 0 obj <> stream xœå\Kk-¹Þß_qÖ;­W«Lƒ}l/²0d²K&E ³Éߪ¤’ªôê>¾³„ÏñqwKªçW_UßåYÝþóãß·%ü·*}ó»¾ýö÷þÃí_éÛåöÛ?~¼}ýØõ³¹yíž×Û×ßnüT7¥n_¿þåE/Ç“yQŸË}Y'û¢ÞŽð«>Ü‹UÇ“‚ðív(ú¯[ÂÃÔ.[Þà²|;~åã/ͳáê_.æPþE¿Ú‡{­<ÛÑðQÃÂ=Ÿ|©øl·èc§%ðgøÊó]ÐÕ.ý=l¿¿‡Ë¶ðsKOz;¬†›ß'v°ËS{¨¼Jø©4œ ¯T‡zÑaïAo#þbáv££ã)Ê ³HÂ*zÍ+†³­eÍ¿~ýéÇÇ×_º6¢ô³mmD¡Äã.ðY÷E§ñ4¸Šç›7ï O¾ð=jÔüÓ–„­Ñ’ªíÇ¥@ÅIìŸIvpª{º$o=ÌZı—í(njՠʹ ð— W ¾³ ~ÔkÇv+ÙOiTT77WzxÉ*?÷IEÙNM¡Ù ßäõÍšÍD»`ÒdÊå‘÷ͯûþ¬+Íÿ”Åå- tT G;¸,]\YlO÷äÏi#É*“¾Áæp¹ôŸtC'¨E¨“§9 ÆÈ0QMŠy=)ÀAé°¯¼C`9Xx²YÐÚ³?ȹbdŒ*NÑØåi<]¿êÍ|š»Õ´WG&eWú£!ËN‡ƒÅhoS»ØšœaÌ=ÜÖö%.𗋦!UËÜ3=sÓF[ó©­ÕúÕÜáÿÕÉÂmáhÍuæS(ŸŽDñûlÜ(xD?i)HZ{4U/A/óIID‹Y‰ùÒ>sļîW¯Ÿ·J½)a…{ ìðÃptÆÃuQ© àŽ’;2áø,bÔ2Ę3¬”?Т¢MþÑóù+í}¨$å%îàhŠâÏXˆäìiIôОçøKqm Q`Sñ à*|1?¡mËHLdO•oL‹ ¹ãZ/ëZŒ%÷ڃЃas¯ÄæÊ{ÊÃYxöDÉ@J÷AOÏ·äŽ\ÙžÑ5[ˆÑIùÜd…åCç ‡[¥Kã3^[|:>»Ž*Xh€·$»ÜÎ4¬—Z¿ekf ¾¼™0„ö‹Œ.ŸœŒ}ù½ªÈaÊÏžÎáMÇ]Þ—==zË®ÌàW âø™Sч)²wÂd< üõÃ1%xõêª3-/köö3G‹ôØê©” ÷4Á1ÉÎ!uŽ5{•‡²@ÐÝPi<Ê s®%%”[l¤æƒXŒmlk"f¥šI»m¡t¹eRÈÁÞœò&ø…úg "0¸‡ÏPC ž¯Ì&(.Ûî1ƒܵk Ñä®2ýAØJõ)•gäûP[Ãh‘%“*"ìG^ܼŽêDÏ ³nTÀùI{Œâ„õ€7.îÿ{†®zÏx¡K4MmhõϪ.ͨT‰‹ûQT÷HÀzâ3h›_ÉSûÙCï/2ÖUu„V¶n†É$p6¥BîÖì)*p“ÈÚèVá³0S§·X0[-¤ÜÅa.Ù/ fCak  @ž©×å¶ÍõªwõÕÀ@ÀR{GZ·€ÇÙÿWZÿ’Ds(Âi mÚàýΙbu: ¯Æ7mv°×¯‹ˆ¯Nö«Ž­îLÓ°‰!®¢^Gìᄺ!ÀÉ~(ª“ºtü˜Ã6}ÃL_v3OÂFmíË(dì~þÅ2Šï·:˜Ø3(EÅsD3W˜ßÙÇ¡¸ÍšäOƹ Ü3AASb18þ/¨4ìB¾Ê~Få-H„%›u@]z„w-’D°Pb¹~ÔdË65WôâšQi~“ýtFq[ðÅÆrjx² x.–ÊRjf$©‚Ǫ%»éæpbm6ƒ<©EV³ã—ŠšÚ²`ªîK ¶ t Û¸ ²¨œv¦@½­4þ'3š© 8a7òy#BøP5Ú¦´hºú×üX‹w”²äK%MH-RÎ%©“åPV…MCe<Ôjhl{\ÍqIÎ˪ |•¬Ñ¶'Y@­¢Z‡ƒðUEµy Ojö ãÂÛCwožên¯+oÃÄùÉ 3+WÄßG D‚}ÅõL Š«©NùÂ;§­¶)"ˆ>äv•éÀ·¬!M²ÛÏêÃn,ì°+ÍÓ¥hćЬ #‘§áÔhU²KŠü§Üè*$‰l×T)Æô*1öbÆú÷1Òt9UÅŒôÂæK¢{r˜;,ïigóŒ`Pº‹R¥žæÉ-6cBY’‡B5íf*h½ôj"$Wm:S‡|Å݇¯q2¥)›.{г|¡J3{mEBtÓ¾Ü('g¦S6Â[DÙ#µÿW\ Œ7šqc¨n=‰Iãíþ× ï±CäR$ Ç!B ‘yÜpü-¥L°|õæu»Áï×ÌŠ ˆŸƒžð¶c•KzáÝ).j1ÑÄ_³6|è…„Ô¼Š¼$¯ó¡&U½yáÏCë¶#€‡î¯©Ø Vjo²±IšÂ&5¨œPÁ¨?âjU=, ¯(Ú9JawÖC ñÅNœ£˜Â/wûÁ4˦ÿ³%P)’Ædº“F§3_ Üàㆶçs¡ÙÜίÀÇ ²c7™ñ‰ã·CË9ékÃM×IئåÝ;:4rd¨C]ôæ>Ô þñEXñ^-P(äþ ‰b< ÚÊä¦|ývºOÒ¨iûùqheù@B”™2 –­íÏM9ùløI5„%¤- RÅ$ò›q8Ø«ƒ\n'S J«ÞëÁ ‡ŽŽ_ndÇç¾LÓ¦bäRŽtìˆÈ¨ú—dC üÖ“\4plÒ&FXQ¡t^7ª‘„á}ÖgÒ~ë–H쮊=¾íŪgªšeë’; rÏuSî|D7ÝRY§7­cþŒÔ™H?ñÜëaL?M¹è±ÔK© ¾?;þn{‘*Š×ùéËõ+–4a~°Þl²Gú—XÄøJsÛ Ô*”ÌÆS$£éèoÈÑHIA@õ«‡ÃõzøÄ‘"B Åú°Þh°Ç__ÌÛñõÏxÃ/·ÿIׯò endstream endobj 15 0 obj 3577 endobj 17 0 obj <> stream xœÕYK‹ãF¾Ï¯Ð9`§Ÿj „`Çcr[È!ä–l ‡@ö’¿Ÿzô£ºÕ’íÉB¼¹»ºº_}URg=üõòç àߨÍf3|ýõåÇï†?âS5|ýíåõýE›pC0þ<ï¿ ßßô õðþå§EÍ*(·N‹ñú²j·(£ÞÖ“YÔª×5ð‡VëÉÂ"X=®'·úžúöÁ×´þ¤XáóºZÚÀÒð/±pœ·(ÈÃÊ´¥j¿­3¬æ ¶ZV€Ž‡?Yãõ4-BëñžÒÊš iõ¶š€ûáTO§•âøx+ch3<æ¯FÃb÷¸ÐßIAjÔ ÿ±x‹µ«^L²ÔÏï?¼\ß_>÷ݤÍÙµnâÛE¥,Ü2Û£˜<ú’kA¼$]Tœx <¦¯hXt^ގׂYõTé½ÆÊ¸¤£ÅZ3i´ÐÌ IüƒX·FE²í£½<äÜz‚5ŸV­ÑÜ~\4\ʤµàÎLÊ.ñÊd»çk_œ–OÙu‚ÏÓ0ÎóÙ´>{aðï}eW(sL¿%·ê8ÔŽhe«+WGÝR’Ýus'™h †bcïg²?ž½8—¼Ë+QクrY͈éäSNõWƒÎH5:WVãXòv@S‘YVDë-ë‹7ª£þ0¦¦ øþÂè› š ²J*)B"M©ì˜j «'à(ÁÁœ ÂðטÝk4ôI8Ș@[G§…»= |þ¯|-ÐVa6Q«E"mëÈ2ň wñêª\Î~–\3Ž›HPCpOÕeŠðs‹NÚqÏlÎvýœxДݣÑÙ¯Q!B+¸(„¨fI㛆:„wcŒ2øDïVr?gyŒƒÚ'd »Z0︺@÷ Úê’ÌßÒ³”Æ×5ýÈ?æŠ?ÊàG»’Tܤ{µ%•s˯aÂøÊqÒ¯ÊVKÚçsåhÄÁlb˜Q ÓjÔ>i†|e²¼šlépœ¯:¤|5ƒîõÕxÿ½·atàR±Áóp¬ÑšÜ‚%Îá‘`ééäY3À90íDÀ6Ó#Ôž?F^ ±[}õꊡÁ".°+‰yegñÆ È£:\Â?¼íÝ5èÁÏ$@‘ùû9b}¬ÒÊWd‚B®àmBÊ„*FF ŸÆ˜Ïu"…¸IGÈß ÑÁ\Ê«Ú\u'Ó¹AUÌ{€SÂ9drA×ë´áȰa†n¬6,Ä©¶„)œwd8 ó˜¥ØÜ¢!ªüG1vŒ–wíÏðÜc¢J?Xnsð€=3]Ý5 ¶»€½ÀÔJ‰Ù¢¢ÒiÏÈöüµ;~ÖnIDÃ(Z# ÝŽÂScŠ¡˜Ê­l? cËD’rZõªB·? E­æ=X¯iQK £}£œÄ5°t¦òŸÙBK¼°6€~ÆòýëFølàÌŠ¾ ê2µŒ<¾´¥6*záósÏSÇl¨YÎZ¦fþÐó¾>ì´ésaÓ¹ó>LkϾ›>»û¢yËÆbÞIâcC5îÈó¸˜J<]ÁžeŠÒ ·}gê!ãNߢm8ælx£Ò¡1<Üj”DÔ jtÄ*Á“”ºÏ*C“¢Çõø9aN'm´ƒŽ¾‰€möÐü %ÉblĆKT¥]ê™Õ„/Ô€I-åKõ6oö.Ñ‚"›Ø’\µ³ãTRœzÊEYho£ò(Ýlm•ñH€‹¸œ"2v;ùåaL:×’ïu¼í°2h,/†xIr¢Y&³l,“lÆA¡Ã1iêÛkc?\Q¿^¸Iõ€šüããKl-LgW±Ø4PËÅ£Y¬bÓªwó¿ÛáÉ AÝ\" Ô½!/ÿ,=—n–æz K&õ°Õ‘¡´#ŒÀ³Š¼!©-£ðd¨·69©«Àpõv7=دcH]—ô+2ë·–í»€‡üµÏãºí¡Ëóã³'9$¶^Å)$q°bMvM5ƒ#W0˜s¤wz1çÔŒPÀÎ ²FE1*&N+V®ê Kß‹Ñ\Íìùt§¯.í® ÑP> stream xœí[K‹$¹¾÷¯¨³¡Ûz抄®ª.ƒokø`|³×`<ïÅßñ’zdVõxŒ1Ëæ”RÊâõ)"¤6oöô¯—ž ü7YwšWwúå//øÕéòÖœ~ùëËåËKœÞ–ÓlÍ›?}ùóé×÷x²áôåç?ž5þ÷ÆÛi g·Ww6Ó6Ílx?›ß¿o¯>õ^è÷ÇܶמæƒGÝ©ß[Oÿ~ÀHh`bìý°óæ ¾ðfÙ,Ñ€¶]ìºYè_…º?€Äÿôå·/_^~q3­žÄ=YËÜLÛkÀgÔ?í ©Í0Û«5Ò¶åLÜQë²Y`ÆÁÊ,¸sÀ£µgo˜ÀÝÅÍOg ù+›¡Ÿgó(džd @1ži&|ïñ;þi7{vŽ&rðÛ‚$àòØy¥™4\— q¥æ¢´f(¬¹h¯$S‡*r²ÜË6 >!¦LZè{ÙÖ3KÀ€®æ³»)9†;aòÛërVSLÝ "ǘD¼ÙÛf‰'"C¯ ÃÃÈ c®‘E¦f$ê#¬ï-㯗ÌÄ¡ÌóÛÔˆC!’È"Ín*ï*ZNJ]àÍM‡£5¸"u\óÉ ÕèÌÚ5¶:~µ8 È8)U¸ö i$´ÊRÔ”Õ:YÄÈúõ3RŠh¹bA<“̧ÈÛBŒ)'­²§\I&³ y¸î¤3q+"âÉ* Ñ w†÷ûÀš•>…·Ð¢‚截·WYxmZw)ÇJë¿&Œ1‚\”$êL¦ÞÚUá/že~OàÊŸÑkq9ù¢,`F?cªlŽ„`ÇIJ^ƒD"ñ;K\Ư`y™krõd£*=árÒÛ…²‡¬÷ Ë@€2Ï ·VV« ÚÎÚ¢5í›k5û¬ý¿/gf— ë]"k ƒTBÈp™U¦&ïª=¡ß(”º—„}Y˜¨¢ զ›pÒ“ž½[®ì¬g5¼ÈãŸÛ³‘ŒcIâ!¢q)pÉ[fèw…:n®v9íäq®^ú¡…ø6è\Ñýf>»qrÁ\^àe Ž,tEµì4±ÂúOã\µk7íš2Cå0õ®G´a 58á2o¨«dOmXCTü\”ÁªøÝoPóirè©__¬ oQZ?ý¾j}qv†K¯n}‰ÁeJØË„pÏ„©¥K¯ʽº ç^"m„È8æV!œz™PéÕíD¸ôá00ÌD˜[…pêeB¥W·áÒË„ÃTÈÂoE”z„„ô”V&'=LÌDø0“£–"(½B$÷êv&›{‰°Ÿ Yü]ˆr“H=¥•È¥&f¥}n)‚Ò+Dr¯ng²¹— »õm-„©¥K¯ʽº çÞÊ^•Wt&§vV£6ŠWÃ:-æaÔ N¦yX'5¬wµ±‡×ÞÔºií­¯UvݺKm¦•ÕkKk ¸1œÚkÝ7fÓ@JƒU5.´€S;w‹•—¶Ž_;\åÃÚoZWl\ öªÚŠ‹(8 ®Â´t*`à_Æ™„)°è){þT”ûv¡<°wô&\X!3œÌÒ‚ÙœÛ (÷¢ BõCz²kª "¤ì'möÆå¨ü™,Ç9ófÇsÍ›ÄO»ñ ¬%@œë‡cð½È EW“²ªõdTŽ0jq2HÔoJ ™%†d×Ì“µï@–¢¤©#ÅU‘8ð€pê‚b²"&,)!¿Žbo$2ƒÀQFª¯@ ”€è¡T‡l.ÈæÌi FLïÄYŠ!NÂ!Tî¢10N ‹…,’fUgl´ ·»R‘UÌY·Í*X´cÁ•¢¶gÏ‹8¦:ÍðüU»¶¬ÑÓRÈ?/ÈÖY"¾ˆáÉDaûc³+÷ÉW7 tï68ß ´¸ÏYX,ÿòòaåGîa£ûàLº_!Q L£ÌƳÓdH¼ÁV+€—‘ pðc" æÒ»°½F½jx‹7"FÕâeù3È<)aä!Íi1²#úp©)"䧈ðxuÁMÊ­$ÊwI À‰¨ÐË&ÀFO–îpôhmþx^ïRήç…/yFŒ5%˜öic†g+m¦‹P ´øçqDY1äŸd8d±÷íµR‹Ã¤ÖN^³ÅÙ³FØL@e¬&ÈnžVÛët 7†]ãSÁ~»ÞˆèXŒ».`k¼Ú2˜¤ò²qÁ ýÕ#”ÞP2N—N+ê[U†3j* ¾){÷=X2:U’ÔÒ=–Ãb†ÞJ"vd^Þó)-rÞ*ad3h“”¹!¤5{ú½qù cq’›õ%9‘r]žG̺)k§MÒG|àÚdèÛ /Vb \=L®Ghåê3ùDzM±D[Ñ H-=?LÙ÷²çGK–³’Ws%49?øOPÞ~Öá,ÉM܉¨CCŽ¹Ž `ÌnÑùâŒ,e¿&m€ B½ Gñv¥ý]÷jïù{AÍ\‹ñ;ß³Š7|!«,N‚†ÊƒÈ,=›¯s^yª¿ñå#¶iDZÿ‘¢¨Ê^eœDIÇb.5òµ`|Z™ŠÒ‘\¸}&©’ÂÆ~†‚—a¼™Ûó¡w*k>¸º9×§P ˜ù¶W{źþ"Ê'®%>ºÓ^S9¼2 ‚+—W鯲É^uß(ßSRÇrú2 x»Õ¨;,Ü*§Æ©—OSK¯n§3ÈÒË„g«±¹¥K¯ʽº ç^&lfxfÂÔR„¥Wå^Ý΄s/¶1€‡%ÂÜ*„S/*½º—^&ì§·rÚÏ-EXz…PîÕíL8÷V2VšìĤvœªÝbÕÀ^m;ÖRk¦Qy-ÞVoŒñ6æÒÚa­óƘjŵÑH¿(N™ÞÀ•ý ÌTÁÀÖ”&{ƒlknž¿ëùýˆÞ:¿ÎõãÎï<ÒÚo=¿G²ƒ¼7É+V5ôn¾ò>ŸãÃÏó?XG˜ûu<{1ÀrüQTüK FxáθêhŒ3ï „F™>Z'ßü7ÕîT:¥T^Ö6ÛH5Äúƒ{°2½ëë ÀE¬;çÈëØTG¶óÔ¥ˆc²aþ·ÀÇ Müÿ-‡ïs˾ø/¾åÄ“Ùÿ/ß °kìK±G`ó!\ØuJWƒ¾õVÊäžFÛ+ZB·¢ôg¼Ž=¤„øŸþ~Ê3¨ëÒê£ig×O˘Á™–’ézÄ„Çw‹üý‡T;"FúòH]Ü]Dœ×5™½ueÎ0ÛŃ셖2ËeÌh©ààèÂ:l<ºbüh ZÜŒ¸Ï÷OÞõߥµ7ârm&œÇ¶Uü\•sä žóÐgqü˜›ÙõµÜÅ2â,„KÇ7Ä·4Ç‘ÎÓ½ÃC‚XŠ„H»ƒ®¡rö8âiB©¢^Ò¡G®M8¡Ã“î²V8ý¨¾™êÍÇ’úC")³ð.äñÔFæg.”uÔ…¯Rú÷å˜:UžmQAËô“—,KUr©:Û¬«Çv;üÞ™»ÅþßCF¡§n}QVâv]X ˆN-ÆFΔf˜3Ÿ-RmÎeÀšÎ„mͱ‡h1ZÿJ’êüAXEh.9€ )>vý(¢âÝ!W¬XŸ+ø±Ö>uTÅÚÑ=©(씇Ý8²Rº¿â(¬?c™øËßøƒŸNÿ¢šˆƒ endstream endobj 21 0 obj 3587 endobj 23 0 obj <> stream xœ½\Ik+ÛÞûWhs¦ž@4Ø’È.‰!‹U&y¼Íûû©á UghÉæ&\°­V÷ê|UõÕÐ×¼ÚÓ//ÿ9ø7[wZ6wúùo/üÕéßñª9ýü—÷Ï—i~]O‹5¯þôù×Ó¯ïîdÃéóïº8gœñÆ;¿‡‹¹íóÅ®f5Ë~vþb7ãíd&¸jàOv¯Â.¾ïg Ÿæ}¹˜ën/xöfÅQüìŒwãÏc{7íëŬü•ù€ñ,ÜBÏ8ëx¬æüóço_>>_~×Ûɼn¯ïÄž`ã´K+²wkp™ï4ü_wøvk/ÎìgØÞã&³À¶½Â‡=¸‹›ùéu?ó¾lÉ-ÆÇQ¶ ¬Ï.w£ÛøqÐ ,î}÷4ÜcaoWœFh—@c̼˜øÕ¬? y6ÏX9­‡&ÅMäå©àBÚ?ÌáÞiøå¿äõÜv7¥{è~7YÞ;Ë& bŽÒÈk‡›Í,^t prÆá.ÓëT ­.m÷ªNR.˜®ƒD§$¾àXÐb¾>È÷xbüÝLGwƒß,G’¢ciÜò3t:4‹:Ér\ÉEç—'Ä4M âZL(pX Ìwl\+-xv.Ž<ÛšíÕUƒ[‡50 @`ÐÕ—$Jç²Òvð2̽’0p€„t×D”ôjå†ç¹áÖáfG?õÈÓÅ­ns[ðâ¬ey‘½iñ³7{¸=Þê| ქٙ1؃#pØ8/¨$ý霻‚ŒÝæ("?oü£ˆî8جø Ä¿ÅAí'lé …§wd‘`ãó¾Â~­í‚…ÜÒÍŽ$ŽV5>Ò™¼¡àø™w —¼\º¥ÅÛ“\ð_~z1¯ó鵯ßÿæÅœÎÔî§“õ+|OþuúÃ{~‚{ôÞùLYÌCt͸„ÞÓ\ž$çscÝ¢½982øÁ¦rH!xl;Âä“›f1æ38~ÀUÂ×ãqùkÜÍÙC„4\GxƒÔÂÝ_Âé@Î]iÿ¿pŠ(Ýü½àÈ„¿‡>JÅrŸ@©$Qj–×¥³u”öç?Ç6ÕØ¤ÓšYâAϱàEóŽ"dª_š7ÜýŒpc<ÁMx/<´Žôd±§iµí¹%8#â\Nv¯s”=_c¿ãŒø.‚S@j@À ÉËS΀œê²žá£8øvâa@0×^Ï+IÀÂÑ£Ñ\S³yŒ¯Ó-¤sH;±"©Ó¬$ƒ9ºÛ¤¤Ì´¢ŠÓ‚7dÃÑnšéŸS4äÒÕd´ª2pÜB:…¥,YÖ"-Ìà'ÔOJ½>ðëÓ¼¾†Ú¶®d ®ä;ép¢° Ua /²=æ ä§imn®°7?ñi_E8õhñ)â´iûÎðód ¤Áޏ ñ|ñ룟Ò&\„F–L1´säØñüóѼjcÔR,ûémášWïÀ`4l_+€ T/é€QÎÜÕ(Ñz̲XÚñ½,‰ˆý;5J ã7)í&tÓIÇŸ¥„¦j’j ÇTt"‰Y½çŸ×8àÞ{´«‹ôÞEIq@a|¤–<›DRÁòƵœëÔ—ÞÓ5«ßS ¿ŽZ(-W24YÏï,ÅR¢%ÔXña§ 0{«ÐÑE ;{8À@˜ ;먊Ô)T‚¨¶98Þ÷U†i$ÜøÝn×ìW”ÏYÌu{a™Kö¨ä80KM“ ž£wp_vcmõØ¢í-.0èäÑ[ÍŽ:ßHk î„m©eÂd)Â@ЧþÈ ¹~Ž˜¼ ñS$ð OÚJÔjä¥ LG‰„;蚔Ω‘,Ò}d…j»õ¨ÊÙ¿6£DIÇ£‰«d5À%j¤k ëá3‹›Ø’SâÑ4¥âÚ³oÅl”0–Ì4¢@:¦%îë£èoäõ·È½²¿êÉ[­ü¶ŽýKa4w­» æÙ¢F°5( OI¶°$‹)TAªØñ®úñ³¦B¿ù[þ[æ9ø(x¯Aìu“*¹u>BØ_ŽøøTî’sj¥>Ü4›´I¡““£„5‚7fø=XÄ%‘ÄÞæžÙ?äG2®áÁ‡ñ‡öAIæãž§bºî8åU½Ü}¤Ü…WEˆñw2ë^i^žÏhÍFªPtÜÃÉo=r“|H6˜dFŸ DˆšÝyK$ŒF×Úìzqâ£è*„½ÎRÌ&Yb³e3G‹P(k<0‹b˜]P=ʶ ïu„˜°nN|Àj»˜iNwð¶“t#?‚ æp-‹9Ì=ó§ºÅ’ab¢n2ª¸†t¦v½]NažŠÏÞ0'âÖANS®³•žÿ(N΋˜'Ìq}>ƒÓ?îQÂÒ¥]1×—=D(äPSˆ¯r<©C?>jhôiC‹ÓÒÔ’‰ ðÃ…µYQèøQéÓ‡†ŸHG Òéò©D,ˆŒü«ä~àÊéóð‘Í$°ôRYË ÞÈüÀ“§Þ1>òœƒ:áâ×­´¥-ê&]dªæØN ð2Ž;Aa±Ž‹N“¾1„§;^óæ®{^îö¤¥bsÑAÀƒéÀ9†kɸ×¥þ6Î4aÊóAãp_:ƈL³ò^Åè P›WI(,u251rËì,[Nœ*=ø«ü8©M¾¹Niìnʼn`‰Œ ÞϤiÙò·¯²Ü±R“ˆCžÈ½ÝZ“ò•ôÊ!ÌÒF'8;2´“*fIÛÖÈ-jõ™ãêœo6¬°¬”4ç'+M¹-ž‘טÆfjºÅp~ã$1[ƒ„ÕpÑÁK£1µØYgt}¢Ö:ÒÌC Lß¶iÚZHˆp•BƒÄô˦õ¼Cë¾IëS¿B\Oþnº¤î(ŽÊKaÛ3×Å@ö˜’ÍÚÏ+¬[ŽV‚o¼jû,Ñ6%r¦ÂXpú 9càW'æEcû@o‘öš\·Ð¢8™ÖJÜM)Ê‚%¸– ÊAaL§æx–åÁžâ VÕ4r$û"ç¨Ó"\3>΋tÓ+~Ž»²R•D•bÈvBpŽœÃåÀDÝÄdÇ=®ÙÑq:]Ƽ©Æ4VÇžªTfiZ3}D…lAà¶jt6³«4ò}(µ5M[þw=î ›BÁ6›˜J”ߪEGoŸs ÉôPëcÔÇÄ…ú)‰ªF1Jά :® ~n¹î¤=¼J~rJ×úÚ—ôµƒžò(åý‰ÊðNKžzXîiÜüsIÇ#p[›gŠ)l 8“œ>%ãå(·ºåáãk¶Ü率&÷Ÿ Ä7ž@É9%ï3Ú"¿ \ÓÓ¦úqíS3i>X/’å©.<´·»¦Ê]tI£JodjÖ­^Pádª-ysÅdFÎ> TR8ãBÝ‘n@™¹È]È"Ø(wUÞëí“ BÅc{ÃÌ¡/³<Ïém4f{¢Úo4À°·}Z±q^ðïÊn3á’\³kGMLCNñTæH;ìÒ òzúž—g¦¦ë;;­­,¨ ‚¤² ïù¨h»ÏP*Ñüô“|`øú/LØ K/³èhüG4ðö1Rýº‚à”xÐú ‚Zã³s‚„ªÑ_çjkWçÞ¾Ì*sá’¨d6ÌåpLœçwe2=™õ/í:½"díÙê–nIދֱlŽi™ÔòR‡R¹U¶núÖ±qˆÝž*ØY4듯j,¾ŽQ2µ‘WUuѵ›¹ßÜ0r5‹Cªó*ÖîK•£‘½²uy­±[̼j©ï³¹ÈKÙüjùâQMt>[/…}¹9覴’ã÷°žxù¬g›tÙ/¨¬b¯á!e¶¾ µjK¥ä3È|Ê÷'îâÅ,”!I/@¢K záæ°HÔ.ê;–"½§QµR÷iJ–ŒÌ¶%ö^n]Õ‡ã~ÀFR¹×϶)û&‹Œu’:NSÎ@&{¬¾o˜óìÔªþL)³ã]Õ¹w¹VDbÌ‚ßr-WhJ“ùJv7ÿ¯çִ›pä5íT'C¿-ä¼µRÖ‹f¨© )s‘ó}¢]Ú´U€õêBk)k˵WéñF"ƒ÷ézmˆÛ§^I‹ëTšÛìö„åÖ/ü-RU=:ü­iÍ-QRòî„Ò‰w0‡¥ª*9l=³É'%©²nÎhW!™|å¾/ãïé‘n§ÓmåeÜ#+bFM³¾h‘4ËO{Q„R¶á–—â{ Úãv^è4¥ìëå(úò_ÒŸMõß¹\‚Ë ç¿;ýpÍG endstream endobj 24 0 obj 3899 endobj 26 0 obj <> stream xœÅ\Kä¸ ¾÷¯¨s€êX/[ ºª»ä–d€‚Üò‚l€ì%?$%J¤$»Ü½‡Å³cË’(>?’ª™^Íå/ÿ½LðßlìeYíåç¿¿üù7—ÿä·Óåç¾Ü¼„ù5^^çË¿]~ûi.Æ\~üã/·ÉÙÇæÜ;ov¹Ù0½oWcnfÚ®ðþ4öf>Íc 7c·¿þøýËÇ—?4«›9¾.—9ί®,oiyk¶%Â&›½ÙvºúÛô€‡i¶ÎØižfó¶­°/ìÛNöø >Ü·ÿ¸Z$Ç!q |7›)s¸0|ˆ>}ŸÏ£éÏk]i×ûæ )pì’§5à¥Kó€†Ùâ\&§X“ÎöåÁ´AaNbÍ÷²àú¼Ì¯þòÓ‹ Ë«ÍOÿ¾üI=ÿôâ¦IŒÕ'æÊyòù§r¬cõ F¢ b,1¡!&b‚"&(bBCLÄELPÄMŒ›áe!†ž1y”¶/cõ©SÇÄs&¦ŒÕ§BLKÄEŒiˆ1‚£ˆ1ŠÓc1Fc1FÖ,•‰IO•ÅíëX}bbĘxNÄÔ±úÄÄÔ1¥3B›;Š;ŽŠ»Š{5ܱ­5­ ›#Ò|mv-Qj¢6 ³§£RFR„CËÖÚÝšš9Ò}-ÿFá®Ç£Í×ìÙ’Ô%±0óÞI»ë]‚4„ÞF¥föF£Ã‘Xsžð€ÂQ,á(E“þÝ|ÛþÜ‹in ÓF‹ÔéæãD©D¯¼ä5P¥¸µ·¿›lÓ6+ÒäAy`= UçgÆ´!âîK=&1˜hÑPÙ ’•)’ü öðèOÍ' äý!‹g¤›(¹2³0½Áü˜Ã§ó#aHm:<$gW\¡ƒ>hM”ZŸsCX5qŒN™N%N„#òH 电!9À„5Gàü‚>@n¦yx>$}Gß)‡ Á‰$“sØ*EcY‚p°òÖ, :.’ýÈÂNIc@¦Óiq,µ¤åî²F¡wnÅí [Y²iÈd0IfmÉB ÀªM`ÅÁ·Ãùçy ëÄ´É2©!›ä—Õ!AÀI½¯ºBßÈÃçɰ‡i¦¶Nró…+¬þfHÀS5êûÜĵŽi´#Õ4ò†`’W?àðÀ8¼ôr."®&)-–Lø{=È=´n,-Ϧ F?%ö±I’ùì°hr‰û(-2ò"²‘Ñ¡Y´$>„1k-Æ9²p>,N·ˆÝšIB·„²¡ÂEK}ÝW¹·ôx'áŠPÛmõ‚ßÚÆVàpä(¾4U±±Â²,ºÀâh$¥o‰H²âÄ­Và§ÓÜ=¿ºoÞj;h©–êízÒÑ•250”£„2}¥»V"Câƒ+aÙ™G:(º)—ä–‘ùèv¨“‡Æi,%;æÄ þGõAdEuü†ý[`÷†_}ÕôÆðb¥ ÷¤¶éü6‡D&ɹb\uéu¥U F ú¦¨ñ˜¶0;È ªí{EÏ4¥•ëQ/csV&§ \QÃE‹`˜ª3µ”-Íuä׈i+ªgº2M0:uVñW~(¸ï0ÌC1½m^û.á]; /+»´5ó ÇöÈLìXO„·© «è•¾€UŽïK~4´r9–A/÷[<øh:ˆ(£³†Çð”6­œN–µ¥°)Xe ~RB³¡xtqT±{V—Ú"®xø6«ésäi¥·*Ýú”oû«¶;Äq·kaÌiaµbÇ{›KœlïâTITb€ÛeÆrÒ£û9ö0ðŽ´ ntú(þy'`í” ²Ï“ÍŒ…à²þ£¡«º–açCú¬#a–¤f6®]¨´ýìr#æ™›lQKÆž›”ç=ms :ÿ˜õ‚UU…ÞäËaäÁ‰×Z²ÚviÍŒCý¾‡Ÿ"èáÙUËØ%‹ä:Ÿ¿Æ£\®°ÔD(¡Òb¾è¿k!@†ÅÞùö¨q•¶UÙ7p#BœÅEÅÄ–Ýd ˜¢†èÇèœçs„+i ¦ëCøð¬bP\8ÛœQ.tW‡:áM‡O7Çôh£›.D¥³X¶Ð‰pþJ‡Bt0L5mÂ-† б¾1ï5hK1ir3>éÒHª”B ч‘'NæW¶”R·šJ¹Žó–’ácQùTlÂVè}k~Öé¾w¨>6öKNEfz„³¸lG¹`]_èT6ÅP_‡MiEpþ•rMµPS%ËŒËì%Ç 2†¤ÍŸÅIsr¸‡«vã—YÁG!S_½ƒ¡]OpŒwªuø¡ÒåVÚµLŒŸÚ.?*ŽóPò&ôp3'n†Ø!s¸ƒr>-P+Ê»‘ ë¾4Úæä7{<Æl~°+^=«¼E)L(ZÜ—šWê€.KÚ²ªd¤ä‹CuÓ¶¸¾XÐUü]Ù‘C-×:#âsæ-U‹çU±¬Hè°’ƒÔÈ„¶¦A¤jÅd;j>6+­3 ñ]I¿è¢qmØÑ,‰¥êCÕÙêl¿:›vB~zCÞÄ^CT¹r˜V¨x–‘8º»]k¨q¶=ÖÖâåx9^÷à¥Ã¤O?4Ü®ì9èDö˜ŽueÆx¿•Ò#^;²‹±Ã‘tŸ,(më•0)Z_?„qI¸‚€Ö˜úºø “J§v­—]?;àµô Î`Ç_3=,¸yí`6v×&oQÍ‹&¯ž!jï$ã<8q-:£­Cn¿‘½gàµTF8Ýüü¾Â•®ôyÜEjú-&v¨AYô8m6âZôZ¼ÿ³äÏ…¾·\½ï°›Τli0"ੵX‘ s.[|ù;@ÇxEÙp¶¹ÌOÞ‰ä_"F§CÁª¢ð{.šÏ›·jÕ8Ù’­ ö³¼I4l’bª“M†“³rÔ36hë_s7HêsFä˜"xÉ8¥ç>Å¡ÊØ|Á^ŒO^ëà%rT5b]ã¨ø³3tÅË”ÆâÎH@ÀüÄxø|…ÿŒÍ@‰ƃq6ÏG‹ùí4cÕ‹Þ7 6w,Ö[²g"iÒ4XpÆ >óÆÇ癌¸N72€–ñmŒ°v²Í´å+!žÞÕ‚ý¸ØšL_ÖgNÅP>ˆK‹F¸EAfÎd¸@v–›P]ƪ>žìÒ6ÎlXÂ<@ÜûF]Šlñ¡ñôø'8ÝŠ—ý@ujaÐ7>dXT¸.g@ñ»Äݤ»{Ú0±±/Å’ûÖ·UB^•JªÖ{ŒË¤QÌEÇ|ƒÙÿ½ÙÈ¡I4úiÌ=¬O°qÅ7šë‘ê»”sd”Z¡Pq0NèLwßc\¾R¸¦º jë2ìëu}}|ÝI8ï,á¦FPç›×s´ŸãÒO–5ç ëJ+v髵íÕ$;÷úÜ­b®œlËæÓŒêl¬À˜¦#"©ˆ ¹a׈DC*Û†5 •5÷ Kp§7>èu&ÿ€ý [3Íü~mªèwžœV•3¾ˆiÛêΠúó¤Ù—Ôcî ·¥“Rð üH_€7ÙÇUçݶUåé²;C¨l«m§‚_4“ˑ˹,ÚR|Ǫ”ïyU©—I»µ5XŒT§«0%2k0ÿLË»ÌT™«¬M‹ž¬!yOà0žó¾/ȶí)>˜Deºps Ãy©5+Û†üWÄYüx,¸¼þ¶î²ý†%Vø¼WfVôÓ ß"êovtcäÒ#“úŸh†Lm©!Ÿ8œ½Êc]_‹Íã6ö9Û„ YQJòõÈP"'ãU'~y¯ë¬=O¸›…#«p¤ýÉÙGçÚ*Ž1†Ãdq¢Õܲ'¢Õ‚pìÔ×Ìšò´A,2¹>T oûļ1«µu£;ÇŒEj6¬[S*ÁüV‚ne ~•#ñxfA髳6ó>m÷DVG¦­2ø¶Í>JÎ6PJÎÉyÕ3'§vè»]š…p8£%¶ï¸ñ-À¼^‚ÿ«bdQu`p׺æñê‚~”¿¢K—ˆ¤.5 UÝ\‘­‡ö†¨ÝÊÝ¥£>£1ƒ‹âƒKÈ;åÝ»àDF¢c ˜.‹q8*?®¥ÇŸÐåO®>IH¤ú[#˜õ,3Pê]Ç${ŒªwÛþ`°ë¡û<2…uýv±½wÛ–å´Šÿº!ðàìòw`Å!jëJÀ8Aý™Ð5tÅP¾°ó<µO‡*Ã\·¹ŠŒwü¹£ßJa÷Ÿ‘À#`–΀úmâ×ϸüy À} endstream endobj 27 0 obj 3947 endobj 29 0 obj <> stream xœµ\K‹-¹ Þ÷¯8ë@wʯ² n?N »I.d1d—L d™Mþ~,Ë’åç©î™00twU¹lé“ôéQw{Q—ÿ>ýç²Åÿv¥/þЗ_þþô—ß]þÿº]~ùÇÓë÷'·¿„‹×îe¿|ÿÛå÷wuQêòý§¯æãv\·c3›×ÛíÙ\Uú¿Ñ·pÝÞ¶°í·g{ÕoðÇíífÜUï7³ÃÏz‡¿»ëöz{VW¼ŸÞ|ü-ÞQúªîðŠ·úX#®d\y¿=kXÆÃ²Ïj»Wþba'ßT6„›0ycG|.”Ä;ãyÒ½bñ®rƒJjß½ãæ¼ Ï”®À¦ñ~:ªŽrÙðýô˜N?ÄeÂvÀ¶ÝHy;¾#½ñY+„‰¯yg‰™ø`>¾BÇñª¾ß´/ûÀ[ÜTþªtZ!j¿ýõûŸ>¾?ý0Ä„Ò/¶ÅÄq³ €¸¸±7£ÅÇØx"—_Ú@äÜóY¤BâÑéOé¸ï›Ïx3·ôš¥ì¶pST……ú‹ƒÚ¤N¢âAXúEV£Aì•.E£¨¶Õ4XÜhhúUÈù„$²­¹‘÷Jhj !,Ÿ^m=r¢$ŽÆ&éG­â޼“šU{©‘åõ; ºßVÈá3‘¥„ÊÝ&——µÀ8âs³'HqÁ?Kh »Êìùy«CB2[á#ï¬ùTBú•ÒžmöÛµ…eÍ”WfåŒ^ô9\>¤ñÓeÛ‚»ç¨òbç}ò¾»—ƒÅmî'xâû?‡ÝYÞ{7Ý6¸+²÷›»DÏÿ¬²Ë‹ò8*¬ë u1³ÂL!’™ŒXD±"Œ$d¡UT›Mþ(ZO¨ŽUì­l Ÿ°”Ç}ÒuúcÌ”eZƒ-‡ŠíöYÌGzó¤q׺d‚$Çç>Bœ`):Ñ æ`†+\&#gпQl…—Ó —r}˜§ Š®³U:(¤ò ]·ü(¹”*€z–÷CÐDøÁõâÔ _^»ríX³4)qצ£v= IùÁÁ Yýn€ýtøÁ}¿Ú"žÚ“WqÄe‘•(&Œ³±Õ8,4R÷k|˜>¸çµí›°a+—ˆ,;3JÄe¦_¨š)CH#+ʱô$»ù¿£)… òÖ] îÈz‡Â‚=#ç/ŽÉaøsÇQÍâYÝ& I±=>àӔǑ»»WÞH—dæŸÐ“¸-]«‘¨È9m`á àP„ᑜððÒ¹åÄXþ(¿tWŽõã`Iç(¡-a"-’M Ã{I¤±æÔîH4ö=[öp2ɵ¦û"5 G÷‹£DèI#ìÔÞã/jgWCz5üçg‹K7 Iì¶•Rå7·= š5‚—pˆÙahÑóϼ“¸ÙMgz†¢¥„¶Îñ2¡‚â,;SgñåL¼–€GÏ*éCz‰ž;…ÆÓ$®”LbÏ{²ñ¨ð„æW³ÌòI|ÑlLNä™Â³òc¼ÿP°tñm}Ç@=ftW÷²•rÌ$\L[Ô”µÐQ.I#)ÎV„îtÙH˜làp o$°/w¶žÿ´ ß®S.T (É Þæ‘ [gE¨BçꨵNÎêT˜+^œT'åjq| ¾/‰?èR‘‚žƒ¡{LÅô<^ýiò€±›¾šoñîØÔmwðgà–çä=àvH"Ô+üaNÅúÃ7ŒˆV¦£Ú%£§L¬ —’|ÉR®…uªc†KÌì¾ãDÙDt1ú&‹±"± -ßg˜ ÏNØ ¤Âal–QeùéTQÚkR)T uvly=™L«³Þ|X?õĵÏO÷âÌ6Léï=7°ÉïQ2­¶6¾«©!“#h*L¹°±¹?ŸðT¡n‰×ù•Ïg…­;¤+ѯº*-cWŽÒÜ{gÒÊ¿^þ4§n2ȯׯºâ›…ý¶°#ÔÃl¡‰ü® œäBŸÐ–аQK8Ø­cL§9‚‘u§%í­Žt"6NjŽòhsB\kòK•$13‰.I=äîm'a–Vwu¢!è®LòzM‚Å4hTôäèÓq“%´ï¨R*‹Ç7ÚÀúJe/Iz¹$Šý¯ŠÚ²×Ô±‹:’°IKEÈ’XërG„³±›*{#4=fБM˜ T«¸w줂ïC«üÜ\x˜wQE-¥j&T²Y@ÙŽuÎøKÑ|òh…Bp㪠!ÝïL›­ZÒf²i†ú.=Å!kx¡)‰OÆiëød}´DžÆqS’5am-îÉ—8²¡#ÒÙó 4¾˜¥¹È>>ôÇÜ F)&QHv|òN«z˜¨íW¼3fDŽçªñ*lB.°K@e€qZ%Ò/MZºÍ~ÔY·y¸Stn÷j¢PšB_äXqÇ­ê–p1®'àg“Áq¢¹(`ÔbšÁû‘ÍŸ(~¬=g=;6›Ì œ!xŒ*²Y‡$Oc’Ÿ˜”%W”d_ Z+Ýý—õ8v!úðœÚ­ñ²¬ ˆô|¶l^Å-Q ê nö"ÓcÓYfµ¯·½í^]Õ,ú[Î.úLQtM+šP <…—fDëZ@™Ò“–' ›¶Øa¢t´0KrûÚÀU±{r#“Á‰á¸uûMÃ)a0x™ýtôìÔUeœv“ W’‰Æ˜·‘pNO•MØÏ7ô¦õʾUª.ea}?×¼Í&›cŠï6¦/¡†«o7¥?;ù_UK ¬^¾ Z·C1Ç Sž‘7JàOxÒÊÂñ5ÔW~~ÒVçŸÿuù³øíç'£`§\“¿Ç«‡QòÉ´ª>4¯Š?ÓªtW)×äï´ªxWõ6þ5¯š~æUó•¼ _“¿óªåI\Õ¹Èóªég^5_É«ð5ù;¯ZžÄU Ô8óªég^5_É«ð5ù;¯ZžÄU•/rM?óªùJ^…¯ÉßyÕòd­-ˆÔŽé‰{R÷N#îmqÒã²BA-©ÉRµŽ¥D[]TXm- Á\‹ä;-"k ´ÈªuYv%¬¢·<‰îÞ‚$J{Khë-QÓ#³qªÚÅ<Ë”þ:Uð™7춘fõO@FÊ@PAJår¤ºKÊ:Ñ«*hä>§»¾ÍbƒÞC’O 9m…_ª`Nà?ój³µL<ŸîVåÝB|ä¾ãŽaúûÍ.‹«úȧØÞé–éÛœìØ×D–qwᢻYDÈ™'Ox;¸ÿÇ«¥þÉ´[d”^GÏb¯Cç\}¦Üê®^|³ÕYV®}ˆ‚TrRÖŽ…$YªÇßò÷Çüï¸`ÓÏíW™&}Tâùµm»˜“ª”PBBŽsù‘Òø‡=½­ú·!–¦oÍ(íž|—±*fÄÓ¶ Vº`à ·RÂÃ*"ÙO˜wú”ζ2}âgTÿsnoÕÎ?WH>"µdÓ‹y ª«*Uaª´x{xÁ•H(Pž×õ;öRªrP3 CÏë Âmî»x*ÀB®nE5ãmÍñÔä»2[ÿÍè)á¨ö³¾@.H¿bY"64ýÚs¸ÂV–Jj&ÿrH=Q£¬[ËK¿Œ_³JR§8϶=Ûûä‹’J¯¨ç½ìèp[\~Ñè¢AЦ¸÷°y/窸’ÚÕ€#6%H еDòãvYý©påÒ«A¡¾WÞþ×XXÓXXwüûᔎ‰ÈnH‰›Õ¤‡¤CãÎwóiív&úE/Æ 5±}8‚C>5jØúß8ØLG2—ÿ(Õ|6™øÍᯣÓYªMêv˜ä¦…'ÎáÍ ј£ÙþLï¾Üpmy©æ«¿š™ãP&7 äl;d!½\VoÍàºÚ†Êÿ &ÀÓ™hÒk¥cë›rD2‹FVþ­9œ´˜6ë?Ž“[¤}p—åã3Åß´Ëþ½¶—™Å-cX-ú×RdÛŽÜ»Ac¶^šîu0¥4Âû×ÿØ×ð‹ƒN³ž\›ôÇ­˜±~] ,î7ÖsU~¬Q·úT+žéE]ö­Ìœ`;J}pyæ‡Ëÿ*]ò­ endstream endobj 30 0 obj 4102 endobj 32 0 obj <> stream xœµ[Mo$¹ ½ûWô9@;%©Tª¸Ûv€Ü61Ã"§dw  {Ù¿’¢$RR©Ëž ;3î®’(òññCôôlN¿?ý÷4Á‹±§p±§ß~zúÛNÿáO§Óo¿<Ý>žüò¼ž‚õÏËé㟧?¾›“1§Ÿ¼Ú0Ý7®ö¶9wµ~zÝŒ¿N÷iÙÎóÕNÛÙØ«yß.ù3ø;àçîjèÏê°¹åê¦ø} _Þ6³¤Åàù¾ØÖëäÌžÂgx±<?˜fxÄzxÄÀ¦V¼vÛBzð>­q_7o&I”¥¦uÊO,Ì;>éÖí "Ùí _ÍÛ9ð¦ÎÞI¯› QgcêuAQrgð}>¹‡ížÏ§qÕ(=,·N—iŽÏG%­±âéu<ìkÙáˆFXRÏ;[ÑÿøóÓÛÇÓ]dû†rÀ“'h:z53¼BŸ{fVãðù^ÆExÁ¾³n³ ÙuCMÑ[q'ƒzâ×h¯½“sZüÚÀÞ²STmqðÖú÷Í.ÙÚÄ`ƒ¨²ÑKàßLÞ—•ý-lÛÈBH(vЏ÷ÒªTJˆ”€0 ä­ŠsîòíøïYí?eð„Á Qð©R˜¤˜Ûy½á0XAê,^oâJD¹ð™[Xá³DèDl•ÞD³ ÛjѸøöÂzæ»Ì  A/@ƒ–üÏ ‹ a?ûg[ÇË ó‰Ú8° K.š¢Ç'ý­Â Ih~Á îø¼¯$ùR¢ÎKŠ3è×ൄæÍE³*Á¥ñçb~ÉâYоºƒNM/ä¤àH}h®ƒDˆŠ+^”¹³ èú±W`ùØŽÁë£,³Í÷"”Š¡‚þ‡¨W&Çy½w…«ÌêÞEl(`Ç5°ÁSïIÇÚñ¿èjÂ!»h<ð`À,îÇ™KÞ1Gùtuþ«²@ã?È~ê[ô7(³e´»²½_N9‹JêvÂÔV“Jxd…ƒÙbüŒ~iÖÏEü²X2e ß„–Ä¥kG‹˜h^Ô¿]ôždVøSc‰‘àcÉ~ÕÝI %0¾æ‚J37‘©Š·3”î9Ý9?êe bH%E2] Ÿ0ZDó]»|9·ŒÏÔ`¡Ø¹—cÈ©2ļtäõBfÎa¦“_î=DÅÔ:Èãl‹3út>fwåçu%Q¿(‘Éù½<:Kœ|sŽ â‚#i›9>¨°Ê™V°£ mݵ:Á,åÃÌϯK“ùQêF m<'XDúîc²®±Á¢¾ÑÑ#qc왥#)Mb›rÞbj- .¾¬"¨d æ@èØ\u=à²çªO§‹çç<–w1„õÂÓ"ñEËð+ ¥~cr=r\“Çã'²¾KÝFœ-×ßX0 ¢½ˆ”z‹U 6rl«rÝ(Œ DŒF§ ÷†Ît) Ä8µ9~öà]ê}¢¯;•ý*_ÝI 2]æ¬÷’X½ª˜w²j§ªük1~—eª™aß]H útÌÒ)`ÀõŒœ|¤È Ú>¸Ö~è*´ãWê£xAåÀ½@Žö,m"q ß:xy!ˉs¨‘ĈV|û6t>à¸Ùª$­ðû󲓊‰‚ ‹`uô2[ð±…‘;<É[(HK—OÅ#2&»˜­Dõ”´›5‘ýÿˆ¢„U?ù)´|”b¿¸³V6Õñß‘À¨xtè¨xát{àã%À ;µxÊÖh‰¹4M„dC8×¶ }qJ3.jò²ÎÝáœ1zØ ŠÞOFÊý Wå2’´Á.þÚQ›Wé±³I)#ÛÙ»Šcxe»Š£}MÑÉ$íZÒ]Š«ƒÃ…Bª¹¢X6k¹&dÍ4p!Þ¡{º*úD>ÄŽÚnä±2J2n{‰Þ=Qé] G·ó.øã-½Š² bº’Ï«"IÓD̬‰ç–m.F™Ü7dYmò„-!³*ø±wïx7z5‹@+‰n9¨6&Ók$.ºÇyÞw*´%ñw:nÉ|fN]e];Xù§Ì¹«P8¥âÒª^“ô¬˜|…M›#îåIiÙTÃ7è7º)Í® ÛÜË1N¹Ñ8_ùLË­¹£êŠLs#F˜×:á  Ê=ƒ‹"¡&ÍúLoÒ/”T®[¥‰ƒ<üQ›“È rÜ– Ǧ–P¦á¥™r6YÜ“VÞ@ÕÁ/7ª­M“¸WX"^«¥, {ôªƒpÑ$Z¢¤ˆ+õN‡˜s›†f9]¹fQmË,™hö\•̱dwò'›ô™µ¼’- ­n¢ž™§é9ÔÃ37œñ4ƒ~hL&>:S ŸqÚ&O¶Ì=jÄÊ1Á! 6Ж8s7·ÍäÉÒAXº8¡ÈçmÄT ¾1žV€}æ8¡ƒ+yÿYðå—tû6(ˆÜÚD&ˆ&N™8ó"’7©Ú()A¦âÌå>Š.ibýÖÆ™¯OÂŒ˜f\`”!9Yœ¹jF¦Û¹jO;¦ä£dƒNtêx ßO3’'FØ{—÷¹UÝö^SŸªç‘«¸e'³-½›_eýI{_¹ý»¨Ð§ÉºÏPÂ_–Õz现ÈY¶„Mëíp‰d ¹‰Ë­b°¨[pACú²‰¢xz&j>P˜Ó4ÅɃ—¼³“Y™^Uýg±¼0¹ç6tr8\>í?~}š ¿ü]©ä/zšNgóìO¿žŒÏ.þðïÓ_;·¶z“÷mBz¼â®8›o›;HV'ÿƒ£ßQ_• ¡í;e[ª]½êë“ìvó×Ëý Î⟅2´D…4ˆÎ¸¹›¨¸tnåU6§ÇùÁSs°±Ež9®[`»EÝ'õÐC” ƒHå:3å‰ùÚI!E‘ì÷œØíåø…Ç ÃÁ³©SÖ›Ã|âЀˆP:Û½ F©$)~[žl§‡{PÌbÞõ„s¹–,õÉ=á×=pUÛ‹OOøª›¦[ÝØ­+ák§ ¨‡Ö¾Þžp_ñ(•àé•»§¼o’ü‘¦sÎlõeóM&æ”—óð…«¦ñ c9ä¼SgðcpÔk7©qV…vÈŒ]tؘsð”ðk™ X)ó”Âí¸Àµ…¶¼k«p/êMÿGéÒû@zŸ‰#ƒ¦#|ê—8 ‰poR}¼s…Ð6£4z¶ ”œsŔ۽ô‘€½4C ÍÞ<µìݹ߯[…¬R 9dñ¨è]|¾Æ’ê.ÃI;g‡/R ]ÍàªLQu÷ ¹°ÔÁ°ü "ÁIWDã”LÝgáŒÛnC$„ÎÜGsÆX.·4ÜŸx ÝŒ5^sØqÙ…¿Ÿr‘Ž«˜‰ñbÊ(Þœ>}l6©Îxƒ‰(ç1Sœ³dÚ›xL5-ÅXu…0þE¾',e2ÎΡ§Ž¿î'?CŒ,íØ‡º{uòB¦ûû GkNcv¤ßx6§г, ÀŸ¯ÖY·}ü+¾òÃé‘ZJñ endstream endobj 33 0 obj 3071 endobj 35 0 obj <> stream xœÝ[I«l¹ Þß_QëÀ­x<j8µÈ®áB/šì’dHoò÷#ɶ<»Nݼ¦!tcªÊ£>IŸ$û>q–§ÿ|üû$à¿IªÓ¼ªÓoÿøùO§ù_Åé·|ܾ>ìt^N³g}úúÛéÏOu’æôõë/õÜôEìb—‹°b÷M^”Zñ„V«ô+¹)y‘V^·O£å FÁ-–mºH¦m¾ˆþ_wiáwqÛ>¡–Q×mž.JÓl#§MXg+1Áüy“ —ÜÅŸ?•Æ1ýúËÇþõñSK˜i^œ(Rœà”EÀ1±ùœýGµÑ~Ðl,6Sìž±Y°Y±¹rsÃæN©çÍŽÍ)°qÛè°„TãÓNS€¾^‰«Iç¢ßðÐrÂfÆráï+Ï–× ¨¼AåÝŠÎË; $rgDŒÈä|ò²÷öÜ)Á'/ºËÕ,n-©dØQ© Å:(ƒÒ|4w|´“Œ1n v/ŒþÉ•kКóüÒâbs+pØÙ΢´Û•o` B«T‹³@¿ŽZÝdì¾¶@æÍÔqØss~懤m¨;]üž­ãÆÝ4œ\ Y’Fº¯¬åGoïôä×°ÍV{Ãzh[·øšw'Ûîn³¡µ<›ã”¤„R 'SÃ^ٜǒ±9ÛìúAËÚµÌw Ë û$ÿ¥w–𖌛k6oš­dPñ\²„ö­x^M@N&OY7q!NÆK^M÷+‰-N{Þ]̆î¡åúŽ#:*HUÛØÈôôÿÑ}c_‰¾}ïugtÕë~Ž»_x£X {9¬FÅqÐY‹îмo‘Lp̳ÃN™,r°ãBOřДcĽ·x‚‘ì}ëV ‰Ÿ’ŠHnÕEú:VĽػÑ-®ãî±í:½Cªz Ô„>QÜÒ‚¥Tc3îý(5Î]5îÉÈš¹Zç !í¨wVQSÆUÓyv¿›ÜDªq1ç×ùtT#HÓ6SWƒ,ϯƘ7ÜÇ®óvG~}oÜóï©Ñ5MwÛÙ©úzºm1êÍÇF;ëwH•b£sD* ú¤ÊGñ³–cþ5fSŽ’ê³p˜.©>yÝäêRðyØ-šzŠÁ¯Oª>tÕh®OR:-Báj°µéGÈò>¥Å"ûNß!’X¯~Ònr¢êIû`ö–ªAøaö”½àhú}X†‡Õ`!(ãïB)Kkʸ ~ÀRZc¶©qÔ¶PÅ/Ãf4Ò/…Ç·²/,ûôåÐæ¯" 9•x#±Ih†åT~-³'2†Up7¿5ä¾´µ™ÏÓÉZÅ1ìDá ñ~à䌽©0©«)ëÏÙ€5dY `ƒc-HâVó­ÅÉC ërSà5‡šÚ©¡ÞäôvgÓ˜Ñ:¢­ d²Ú2•ɈöÕ31«¼vï›¶X-­q«™¶qgšƒˆÕLÍNGoÐ RI¦$šd£mšVf ~ÈhE«O¸;:6o‚~•¡ò¢ äy-P0¯ÄØ0Éÿ £Yé7°sg÷dxZ¶ìÕ.¨I– núY ¡ŽxŠCG¢w»é4ˆ0sÇyFA!ɤ¡õ=ýzUKò‹#E?úYA¡Oß•y…d÷s„ã<‚I`NÌ?`•ލ¤K½@fcÝl•ŽeV{¶å± $QXÎݬq24]4Fo½‰é + ]Äݱ1\¼Y¢3§K-ûMÝŠM¯g‰)ÔTž+@ÕóŠŽn©!@‹ªøÌH†X̉¡I'¤A 8¨Û•°j˜hJ‡l¯¸bDÔ g%øœA·I*ÔÊÓl`Tí1ZKnHâ?n'¤Kosc¬¦µbH í®i»Ä°ÉA“./ÀÇȧžF«nâë”# $ÎMîcª¾m:WLb”Uø˜ôèOhÈo>ÈÿT¢IF¯™}=x ®*3‡ÉÕÏæ7rV—P×Ì”ª÷´P®Q¾Â¢‡tCÅ¡ñÃA+µMƒ&èe9«÷ªIYºVõx’A‚+*c1‡×heœóÌT¯ˆ4¼'A ´=g: •Mj/ýÒ®} W q)*$¢·ÄBÔ)ˆ'µµ‘ž+Oƒ¤^d{L_ԽߴɘM0.Љ% §hAoUÌ^%c!'ÉW‚Ì¿äÓGð!¶*ÏÏŸŠò’œ8aéºÒÆ:wÀþá>Ù¨mHgÜä·&&ô„Ç(nFa4Ã4,_é:çÈ8iÔø¦Ê`Íb3|Zž'¯` Hp/»LæÓyV.D\‡A™ßIãŒê(¼  $íý»1EQIv4DQ©š_¯D‚sD³ÿ4ZúGTRNKlxYQÖþŠ(Õ-ѸŒªƒU^ï}“‹|þ– ”{£œòM÷M…$ò*OÖô)õZ±À’ÍjÕå·åõÉ­ÂÅ.¾dè\+9îáÞÖß8¶ë‡~eØ)RIw.RRiÇ;£V[…’v2úÈÙIÿ‡w¤ý@™4§¯îL}ZšÜ˜2I—¸WI‹ý¢ [^”Eièó+¤…XŒ†â€w¹^ES×Ô2¡”U +jQUüÇ•ì0Š²Þ¼hK­Nƒ!çq3þy*%œS¦u*#Öº)¹C=”\cn̘ÝÚyi’Ò&¼Á·WÓájÓPh§ÂñÃL,…ègˆ÷´Öa¼(2zÓd/æØ÷€Ž.Õlï(Ÿ»ê#ïz€W¹T޶MÁ&×so À]¦´v ràµ2æç&®ô+ûžÓ"©é‹ð]sB•&jO.n^ "§äA>Ÿ¼þ1“2'ô“Ü`µtŒ )ï™K{,Ì»¹dÍ÷µ)poCŠÛkÅHž¼ | ´¶³©œ*f='ócajÚ¼Ï}XÖá¢]²‡hárÀ©.#R>ŠTJé”óß çž.Óç½#•Ú4ˆ7óöz¯ñö{Åï7ïså**ʤûw:S ëý‘ÞøÂ9ëèÚ‘·±ì³Œß?¼ÐmFö-e’K±£¼|.ŸôºU'bSñ¹j°õ:ŒÖØdPì•Ò†—Êï<é:ߢ÷êÿM݈ú›†)1Å­œÝhõ-Ñ¢«Ò_ÔiÈð5qøw+Ù-V Ð­Z¯øµ?ÕËzÕßQS‡uPã7|iE}æßµ8Þ¥WDo\Tt™H„ÌkÛ$C*€Ë.ã”ËÆ“W­˜dyl¡o(Ï–K÷Ù$ª•º¯IÖ¼E‰Y«;¦ûË:¥_<®lËÙQ²Tøn$õ\E@ú÷Xé¥ýûÜ™˜aî-àû“þ¿¢‚£œåiÉ—¢W1¼‹ýtú/q?ט endstream endobj 36 0 obj 2810 endobj 45 0 obj <> stream xœíPi4Ô}Î#¦Æ’(¥Â_˜¨˜ÿÐŒELÖ!{ÙšÌ`3cÌhhFÙ—²o‰ÊZQbR)TL˜(в”%KÙµØw¯zžzNç}>¼ç¼ßÞóÞ¿/÷uý®û:×}ËË É$š•PB(ƒ†àušîcJ&‘Í--ðnt"– €àÚ¨ E Á…œÆ»HPøÏI`Æ»BáæXÂ_ø'ñ]€Ázáø?¹þX“Þt¼¡p®âïAS,J`ö òwüþ~vŽT<G&ýþVëê’ÀY% (©"ÔµµF]U•õïJC’+Pùsò×2M'„Uø‡°ŠÀoFkj¬è÷Ÿêñ$Üï\ŸäBÆHn€ `©T¬\»£  œEÏð w®L"ÓÖF Æ\ÉTè÷ÐîóùT8íPà¸_à'üHNú~KâB§Rñ$Ús¬Åü‰] D<€Ç3ð.Ðø`µrM{|™^:µ8ع){¡¬Tô]«Ù-±¯PËYm!G‘c~г®@~©ç]žê”€+¦ÖsŸ^êD¾(^áŠ6.n¸ V ú¼—#BïdRP!¯SûBe–*Ĭ7© Xìo“pC;ÒÎä^¨ŠŽ‡¬(| ¯V,ÚõL2®Åa„GXPäÆM’‘°–åõƒ‹•Ù›Å|¬k%£ÀW÷Ì<ÎÔR¤±ëɨ٠ÖÁœ×‹hǤLë  )dë:ß{´ëù2sâzùÈÔ[€ò6³ÀÎÅ.‹þ™Gë×%ò‡U½P±ª˜ÝHèÂLr__åoï4h³R\ ;¦ö˜ÆËB*2t:Ænû~+S¨°éÉ8öÉVöÈÃýÜàµË¿àÝS¥ýÎ'R^Ï´Uy)]5uÃúäÇáöCGn6„= &·ö)ÞEs|n5ëŽt„3¤mï³]b¾ñhK8£üB¢GŠìba×o0ºôéÉôÜ£KV/8}Vìþ/f`Ïœ¦ÒÆzåBR¾Y°^ð5аOµã;¦Ýü¼õ­™³ÿ¸ïåºl½þ^ªHk§ rëáóËNcªlø>´s¾8Ì\‹ÄŠÁ¾CJ©ÍR† ‰fÚBŒfm,ÊhòÉ5ÑyÐYúqà–x­âIí¦ådc…íÚô®˜©î{#ÌÕE\XÂS³ÁƒW‡¥ëo†}U«ÚˆP6ƒ\ìdÍÄBÕ_¿ÕGøŽÏÁ r¯õaÒFümé{$«gÀ!±YˆEà^HÙüñýN'‹e»ÒÇv_Ïi¬Š³eogJ鋳[»¿×\I«éÞ»…ÈpF¾Mã½Úô’!ìÅP1 ûÈS ¢ÞÔ’ûps>o²ó:/£F‡ïî»|ä”ývBÃ4y:eÈ ‰?šTMüÖ<Ѻ»Æ«ð&ÆgŽ ¸¹,’‡Çë Û¹ ˆâõï»Ök’-j·­÷eØ4`׎nÂ$ÌC Ô¢â¤ê Êç½I [¦ŽõCZNÆ[°/IÛÝ»!æjjbMq )W ½ÞÎ÷³îØë¸È+¥”ŠªÜ¤æÙœÃOõ^x|¯T9™‡+·Í•sáâ·)hüdqÙèË¢<ÅŸ~v§ñ‘(Ê ‰ôò,Ú¹/«Ãn…e”‰ù=íÏ7( Éñb ¤rrv³†ûã>7ì‰Y.v‡bv¡É.þ°üà›Ó5ýo²:óXëŽÙvizfsså3òª»íŒ ùC¦©©R:i´î ûAiV%Ÿ˜ïJ7Á¬*ÙqûJ`ð)çJ(‡}e‡%÷ä¸eÔxDt¯Ñ¾„å^"ܡɘiôFÁ®µl>F0ð8E•x—(y'‰K|{tIÛñ5³ºzø]ëì×å„Öº}SÉ&ñÏj.%«(…ŸÚÙ—íÉÐXèb‹EKÛ±oV,ÈÁ*ž;ÑOM¶-·-Éñ®Y¬_®[ü(.‹‰Và—u˜ù|'·ÃŸ»n0XËN?K³Fܽ¨›½µy²þ¶_Jzh½MÁWâ¹·þµ»¶Ns%LÓð—ªa÷9ÏÄaõ¨{ëpn‹8aÈ[;Ü´F`‹é^Ç,;üž9XÜдüJwÐ`lƒ€s¹pR³eÌÂtЪÀq€Õ2¶ÕUVwä‘Mf= ™·˜èÈÒ^‹¯ð€ÃÏC>Ç5Ëy_©Vž=oýNA_9ÁÄêl|Ž?Bn¬2.´äÉÅ^mø·§í‰³Š§(áÕlÉòá¥'…ѸP.ÏÐ`Ïæ÷cÈi“ì·aõшÁ2×–™Ö3Nß™¿$%›}i{Šò±ÝÞ+ÑËé žŒ·€ÕÌ]/ÏŸÊ–­4œmL ³T.U¾êgdTQ.­VP|šÕY‰A–±;ÄžsnÞ"5⟔e’|¤-6‚¸ÿ#M`œã”Äm;Æ›X‚FǤ‚ëóFÆ7s>ío‹ ¿l¥‚fyÔm*xètuà(ÒÑWÿ fôÜÈd’úVõëg>-{î’LíàEJÇ–Sïp ¥}ÏSÚÚ[ÞËp—$Älÿ/Oq/#æÝÉlc¶ Õut Ÿbj£“ŸiÊŽôMe8ž?xfZôœ¿•ß0 z ’;“£'ðÔ”ø°­/ø}fÏ«EZ›P"ɆÂ܆å”G¸!¤op¶]fâÇS&UsÔhT椑“çs]ûó®> endobj 48 0 obj <> stream xœ]ËjÃ0E÷úŠY¦‹ ÙIZ F’¼èƒºýY»‚X²¼ðßW´….$Î0sï\†žÚskt oÞÊ Ú(³]¼DèqÔ†T5(-íʿœ„#4j»u8µf°MCè{ìÍÁ¯°9*Û㡯^¡×f„Íç©‹u·8wÅ MF8…CôyîELH³jÛªØÖaÝFÉßÀÇêê\W%Š´ g'$zaF$ cšË…4ê_ïPý ¿„“UœdìaÇ#×…÷‰w™ï3ï ?&>~ÊÞ7—´%á'=ÈÅû˜<ß*GNaµAø½§³.Éòû%Çvæ endstream endobj 49 0 obj <> endobj 50 0 obj <> stream xœí¶ePeÍÒp‰»4îp qwwwwwwwwmœ†ÆiÜÝ¡qww·ÆÝžW.÷Æ7?&bþMÌ!‚`Õ®ÊZ™»*$„¢v¶ÎÊö& 4 ´ôœY C'E;[E3kG=ýçz&€±…‘3ÀÐÄ̆î>‡MLaèä ,þg€þ¿þ™ k`c û¿ ú_3Tl-\L$„Ì ôŸƯu2ÎŽî-úÏ>~þüï_:Ž&Æv¶Ö_³íÜ^4 ¬ìFvÀ?Ñ>±0ùüŸs%lMíŒÿ‰±‹ýÿd u±¶þ/[òÿÓ–ðq>'ØXX{ü?œnbküŸt"¶FvƶfFV€££̧ï'±¼¶Æ&îw#s­­ó瀽‹³ÀÔÎæe†OFþ töÿ&Á¿€@gô/`ÐYý XtNöF&ÿ`ÐÙþ ØtÆÿË¿€@§òEŸN_ô)òáÓÄñ‹>U\ìœMœ>“¶þ·YŸVb_ô©eñEŸNj_ô)eoâha÷eÆð©&üU†O5ù/úT3²³±ù*ã§žì}ê |ѧžÒ}J9Y8™|Š }ѧ˜â}ŠÙ|ѧ“Ü×Ûøt’þ¢O§¯˜LŸ>Î_ôé£üEŸ>_ôécgûU4¦OS;—¯ê2} Ù}ѧë} ~ˆO!g·¯¹ÌŸJž&Žÿ6𕹣É×nÌŸf¦_ôifýEŸff_ôéeoàhbkmbú•ó§œû}Êy|Çÿ¬p´03ÿZÂòiéùEŸŽ¦_Ç‚åÓÐí‹>íÌ=ìÍM¾N/˧¢é—ñç•ú< Övÿ6áÓSó‹>ýÄ¿èÓOä‹8þÙÚõ«¬ŸfN_é°þãöUÖO7‡/úts2qý75ÖO5©/ú4“ù¢O+“ÿ(ë?—Òâß^ügw£ü¢O9Õ¯ üifoíòuÙþçÊ~ ²} Z~ѧ ¡£‘•‰ó¼26æÿç‹acù§´ÿîÓYý‹>}M\ þí9û?°±øÏú³q|™ýǾìô_þsãÏ–N§ðEÿt[㿡쟩X›8}¥Ïþ™ƒÙgÓu6ùº'ì,ÿÄ7qr¶ø7öÏ l>[‹“íWoagû'Ó¯SÇþßíÇÈÄöߤþiŸ­ÚÑÉÈÎñë-q|f!ùE ÿuyÍ ¬ÿûHþÇ÷€‘‹ãçáwþ¯¯¢Ï„þ—M->[¤‰‰»‰L|ôq·–I«p†cuÞtÞskòò‚gkÊe#ëÛDîb°Ë)d,„½ž lI“U-p_Šo¦ŒÊãþ˜@dÀhõ{WŒ8Bõxýaû¡Ó ±5LeŽ=kðTêNák;ŠŠ"¬"õ"ñYcÛàÉ®Ÿt}£€åwd: xiPž8QS·dãyí`¸oEŶ’NÑpÈBŠÆ„4¼»±µý ²xça׊¯6YUp^/ˆIÛïýu|p5( à4nN6`·•:S€‘ VuÓ¶Gû½Eçù/¢jŽøc-qUA’­<‰³ˆÁ‘•àï™0:í ôCº“ŽÞòÚš)žÄ;GQo¶®ñoàC,Šh¾¡ü jtø!!ZܯS{tÁÓâ hF  aoÔk<†ºÐ@à·h#6Õm¾tØAB3ðqPì…>‚ɧC –W&bnÉÕ±J™ÀG_)ÿÛp¬³S§©:IÆIõ&BFöO_—ƒ:p~dÈoq.‰ýbIL ö”]Žd~ÁVÁœ½JÆgyÓ2+ÐæM·¿Ì,ñf¡§PÃ3žÌØ4l–#À#Û\+6üâG•A3#£37·ÆMÑó5A_:˜fócD^_´ª·¤¢𣄠6EŠP{ƒ^÷8TÍ¿Cã¹7eÏ^øTBjN[ ®…°ø(kFéý•€x©ßgÄyº²CÈ™cß/.Ü~N;k%]d¼öñÍN‘G¦mÁ¨Üi¿p1mV`X´±ÙkB×åÓ<âVŸ‰ŽÁ• „~CÆËÕŒßg®‡/Ö y’ST/‰¦Æzꤾ%L[œ‘P‡øžO†4FÏŸQÎ }ÆSà´©ïs¶[ÐÅ£9É'­[Z¤ßwý@å%p—j*ŸÝœ—¨Ø®Ó{‰… _Š€BFµ>Z^©ï’0„+šOÙeªo)´“úðÛI›®ã>®3]ý¹‘îíÑ †üRQ=Žg)q-Ð@ÛÛ{6ÊbG-à1.Sª4¢»’%k5b‹Tg.ßñ&ªÀà¯S÷A¼ñƒ‰úèè¯DSÉ.ekS•9×û¤âžoíA²8ªCyóõj‹Ž//ÙöéuKVÊ[ùH¤šK¢[sñLpZ»x Ô˜u,)†6d…=z˜añ™ÓÕJqÔvDÊ.ƺ*Çsñ ¹)à˜‡ ž73Ów ¦þKäÀ­¦ëP. tð7*ƶßjŠ"1F$Ã\FÜ^nà6™û½¹¾ .›, ¬Í¹‚¿,ð{Ý͹ • SÊJø|Ü"CÕd1 pàL(Ã×m¸$4Ÿ#SV=ŽÖvfAž¡óO\úå“êå&¯DDP¾ýR|´%!o”ÿCµ ubÅHm * i3ßÓÓò}É¥—ÎÜX6{<çtôÅÚÝÿùI’Êîæýý•ìð@y_5F(#‚ðtE„Ïy#}O­ˆ'X(ÆØ®…»@Mdœ÷EôvN1;\œ™89!к‚-tÙG” ‰ hç\\Ð n²ŸÄ ªsý"´Ý¯`¢X¦ð ;ù¤§Q$²•r8†]'Æs)³•<È\c+ÿ(üD )­•‘ÎeÀÎf¢)Pîf'=‡›^W\K`zÓÔ6(\5Ì ån*ŽŒIŠ™ÎÙá÷HÄôTan%·‡üÒ(Áù#QÖ-îmŽo"e›¥j„ûl«ŒTFžI¿GÅ`nUÎ=¦Ï.ý‡ilÛ¤žì@£ÑPõqȯÉi=Od!ÊT;ƒƒäþ¹­–Œøß)¾;ÆŠŠú*‡ºˆ{Ó;VoœNùîQ—ž¯‡¶ÒÝšüa]@nì—túØÀ÷:rB9?'ªi#¦ì½<º\­ðPhL¾a½¤ÀVVÊÔs•ý˜¨³¯O7@'26ë’FE y•ðûqaá¯[¿s&µ–ÑKK».YuÓí1×ù™ì;« ¬ÝX(@>‘6ÎÃö99¦5¨œ¿¾ÓÍV@á‡Ô* t¦uújXîÂbzpÇåOºçßa$QØ G¿2©5Š1‹vÐLœ±Tè^oO°pò»ÉÔê#Òàò÷¦ºÇŵ`õòæßºPŒuœ%½‰ˆÕäªÂÇy=ÞÂRå×o°/â6_¶¿£Y¶Šå—2teX]Sô&j‘RRUD^´øÃ@¡ú ´Ç_ØÐ[qÇ©/¯›‡æ`¹G¡äEꔀä}§‰Œ2’…Ldî)¾ÆÖ<®réÎýöÎ,ªéð·9ìÝ·‰ZÈm]ÏäÛÚ´&H'בƒ&Áý›ü/×”ú;ý‰3± ø¯Úr=“_ýp{bÍÄ1Ï®¯ Tp|Æ–!ÔÂЫÞ5ÆÜz ò¯±ŒE—…ßÉÈAHmý‹%ô¬ÁéYß›ht!˜ì É|…†Ù­K– 8‡‚;*LM—âhãH½6a!NžUBëÒZàþ†‘É9½‚ʉ¤Ž¨<Ùñ”A~Z°Ï„13g)×`8‹ãª~ó0äÀO63íææ›‘32 tmT~T¥Í¿6bÉO+8o¿FZ1»¦ ±íÿ#VÉÙoÕ#|¹gîZÍ ¬ÉB¼¬޽:'ñˆÝæmzT°¤¶$™1QŸÂ‰øÇs¸©ó´©º¯àÇ£—ûØÕ¦Ò³›È¸œt"ë¨.™c?œ÷)i(YÖÎÉõÃZ8‘˜ˆxº¾®Žg1­’+ú ¥ñœ£ï»a|Þx,¹ ÍuÒ½w:–zÈ­Ð*éL¸«ÜÔÑÖï!!Ë%ÿiø­Õ‚‘Š¡î÷*Ü"÷Ùû`C€6‡fFˆ¤Eg°ûÙ\¶Ô{@¿ª†%î­¯qØ-jçÜ(ÙÉhTÈèiÍ?m/9Š–?.ûk-¸ņŸ äÆÖˆ#צ…ÿÐfߺW›äw¤3ïq,‰¦¥ŒÜþ’ñJDŒÛq]qê®þÕ/ga­KÓàë´ƒ›Ü³:D¼Wî,!ÐÄ«­ô]¯¥ ¸Êì´%4Œ¾Q=]ÿ}¹Æ^­ˆÂýW¤¿!›¨ðyK)jÙÔ"šù¾·D?שǯ`|Õ„™Ì´°™”¿ —óJ5i’ñÚ&õƒwNläøj#Ûvšù•çY¦§´¤²hû™q:×Gfš·R1` ÎËÖ £R˜­8à½Îµ@Äüù ;»éX…cɵ&¨:†“ßÓršƒ”&Óxùäd Åñ~4 N)Õ~{âO­ 8zªª¾ÏÙEÍ Ã¶#ºö›§_h!¨÷W–óM”`¬ý$À·z•Üá´S³Ãº•ë< :z2J ›„Ë‚Ñ媴ž÷-€Àó6D¡sÖ™?ë¢ü¡OÄSùdÛëyGÓ:E†"ôÊò-–ü{'WeCåm€R ßâTþîþÁÌÅwiKÓ´ [á'Zñhº`»„¢SÌGÄSòQš… Ffí—Ój(r²Uúbë5²]¦s#¡‡RÖ̳PlDLÐãÚØ¡äØHäé P÷¨FÈVøê©ZísX 3Ì@zÖuC -–íl¿SÅ®LIØ"Á™Ì¡µÔN%×PõÖbmÞWßO¡åjø`ÛwqêRùNœHµµ‡{PRxÁvMˆ÷ð$dj}?IÊÏ?U>‰8+p}®KÊ3+Ma5 ¬@~…m £˜'ÃüôáŽhÇ¥mLm@m·¬¶‰¡èsŸ7dªg‡`èëóO™ÃgÎ'ÖL×Õmª~³H”-§‡œ t‰0ScvÂ"ÙÀÜTÔœX£¬ÛfΤµk};VÄË\ظ7FÜl¬º\“òíP`Sªªsé• {MÍÓ †=‡ˆA«Ò’Œÿž%nMU¬BçÈT‚5‹ÄI8ÅûK(R+‹¬ö‡NÙÚáYãGKóÂâ`7ðJŒãðÙá`.ª>Y‚]Zœ¦Þ‘ˆ m ß^+¿“}ée_•Lq°(8– Ï2¤5Êëù®¨;Ù†ƒµ\Ί3c˜ý\OÙ®wNNœÂg7^Ú¥,¥d4˜Å®DB%! \TØPÎÞVªJÁlÕ ‹æ¢ã›%Á0Íšó½ ×¥†T;X³òg”9,ÖÐ’•;çúšvºó²’{g5¼J”%ÊâáX‡,lBE§ðËKÖ˜ácCm©Ôþ½„ñ‚¸Ó#á0v¡4c´0—6Ü¡½»Y2Ÿ9>d•ýOä­ùü¤ãÞ¸(ã„{£c4=fûíµì̤†Jˆò27A/Û:{;"ðïppõ”|å¤^³áåý›ê-“…íô›&ï<¨I” -æP¤î_eùãÀêcé ;¦“ço[½zTN²Èã´MÍr?\§]%×êëÖ5‚삹ÈêY¹_Äà61lqÍ"oeF99A¥kþ"†OBåÛÄÞqñJvoœE_² 5\lB‚òW‚ÉÏË0M5ö¬¥w¨RpžãHÍÖ%$¨ùdM7ý¯ˆ“ívâØ7zê~]Å/»°~sMmÊ|C•}}¥{ŠíØð#òü=nàý$öòîQÚÔP§]é~-N¨8Ž>Sù$×K› Ëäß™ä‹Ã“®é²ó»ÂHÞ-Ä çâ©5ga[-æqZ—_$.m©¨ò×OáâîBp/an~(ü3àÑ# kô"5öÕlŽ?G+sœ«„˜„û=Ãѽ¡µe+,ZÉ`ݦ¯c•xÅ~%‹@pdO¨ M÷6 µ–¯ïõL7»Ú—>Ç´aEnºFÓ¤ö"˜S gãq#R‚&|ÎêX6•Áz»ç—gr¯ éfr|œ’1•¡WB¹_ 7VQ?O9àlD@ªÙ¯¹©ÓßÈã;Ì‹G=H¡¥iyÜñëz¥]x¤OrÊßnJ ˳Ô iî€Aé}üù&Ûø!L„ŸÎu"w©ƒŽô ­ü,ðwä€Õ• ЧeÛ†iÕ’üÚ‘Lœá§w_b„ªÆ‹+’ûøŽ†r‹Šâ1e±½¯)ZmF9uCÅ ¨þàçVä:3ýä;# ¨Y;ò1ƒê·![œïìHžÅ?}²b…ïCOri—Š/¼­ ‡,<¤ù³$¯bj¯Nþ¬ãmVóW:7ǃ­–]ZƒÓ L«ØpDŠ£ˆ Apc¨]Ê‹îe†º4»J˼cÙgZG23¥Zâÿ‰/R ‰hüúëQ Ç£f(b=‚Ÿp~1•­¾†\zíÚNV@…á:⨞õ;Ì(ŒÕ4÷þ »þ)üaÑ>´ç¸…Õ{V£n³„«!GÛ°1¥÷e†]2´Ä¹)%âúþO£‡dÊZ†3<œ ÎÒ`œ¦|q€\‰‚ÆÒ–*ï„ÈÈ©'ÙÑ6öɈôSÍñ´¢Ì^™6Xœ‰ÈÞ–bv¢ „®¼Âì:ç¢Pdú9£ef7´1áØ£ù:Ð )-À¿´Ÿ=Ìô1’{ù Q6³ãZˆ±ÑFŘÚE™2£4FRˆS÷å KYÎeáË(g@OÏ~¤pÄ65iy“ž3*w‰Ù¾øæKårdHVqÞ gøé ŒRfO¾Uú>¨Þ{´Ýø>à`œSpׂ‰VÑ£tÄÅ'¬;à£mìu¸{Õâö”nÃ÷# Ì_$÷ó¼[ÎOE0¾¤‹npó휎¦zÙ…òÊ2t.÷ÒG¹ñ¡4W ÃÇïPš!G¯¥µüœ¬´¥…ZŠØ h Ø# 4ïôwâ®þ.¶©â6¢ðÀ7ËÓšŸD-*줼ï•Sá¤pß;)¡© Œ|Ž%;72ÓÆRÍ/jíºîÙìaøéî㺂?ãü›xaòïÐJÓ‹¡¯œNù•É£ @‘}ƒLÕMû.ýÓF"™y·¿6”aåã C| á¨_:¾|Œ_YÂww ªqp½çøMkÑ9ÑBG™@«&3+g<Š#Épôƒ—¦É.‡ÇÀE)s¤ø!þÔ©xs߉¨™ÑíRåÇÁýÜPFæéðakÉ‚ã oŠRé– ÅxSލžƒYFz>©˜Í0òïPV œ¢Qž»(×®(’9¢õ“à<Î~äûK5ÔM¿¸…” -RØ uJ–оʚƤ^+#Ü`ƒv*,+sé*â…‚ÃýšîZã+neg)ÖꇞÎPCþeô£#1Ó½ÙÊßi‘2Û;ÿ*ê&™Ò~‰b9åºOâÖ_ƒWRlît]Só4} ‹'[§vze4€­ß:óãHP(çëñ4iÎmòxê+ v¹?³j· x ®©¤ ‡µãòýÞ”SÖ¾+ÄÎkYÌ´æz¸†€e†ç:¡Ü-gý€ÃAÆÎjFJä"‡›.ÐËȳvªhM )Ðì@–Ps~~’w¾ÙXüNk`Tžµ’C¤¯ø§·_ùFúÇÇ7?SôíPè±FPH¡fþ¬^–ÞhßJHǰ!<ÆäÅp^3>X7é~ Ò7±Q5¤ææ‹ÚºÖy¹8 ! ÷ÚŒEW¦ºîç¿òSðäM Ñ´«Cèê©:Bh& 5/W†[ªUhøº^Їx“Æ.6/n1³`EI£Q,}¸Zä’9®Dñ¹QÇ…¬•ÔB%³ÜÎìOIn8YôJz0r“/ˆÊÂßî›Y¥*ü`“./³‡w‘e7Y#žk\†©ÄA Aåòût•CKß@‰9ƒ+üMs¨%Ëa•—Ê!>`Û8k‹e÷b¤6aµìÄ„íªÏIëŒú!éq1ØF½ÕÁ>ÛLÒp mçXSŸ‚ ¹þ“Ø ”u½Æ¥ª™Žœš‚½|ѯÏÊ)¨7ÂþÀ};Ò°•²Âóê˜e÷Þêó{ad-w2àz ¤®àè’ìŽFN“ÜJ@j­b.f’‰[8Ú’¶¨¿¤Làßøñ¹‹n¨Ù1Ô­?LOüéuêU³øéÛb!E£yË5`¹[­…õÓmê&úôJFºÿF^€dÏõS‹ΈDט½-è™pïyˆp~Ó!ÅÍV†]T vw~ ™ž>lF ¼Ž*h¤.§êX_[ ¯3?K7ŠÂ™¨ÚŒ2±Ët‰=‰!°ÀjXEúë|9¬”Sçe”íøˆòëWÙÆ|ê‘ÎËá^ÈJXÔî;ã%WŒÄbÀzC–Uñ¯—éßlÚð@h;0ó°á×ò@™ÄKOŒÍþˆáô¥ÐÍh6Ó}ˆtA§þpâ[]±eG†ùÝ:VǨƒndy'ÝTšìŒØw˜pHCÈmíGÓδ…:£×®˜ây„l®øk”|qDfº`j3ýç¾(îÏÞJvÝjeÀ\†ÃäÖ™¾ª¦~…‰®GÃ:fƒM“ÄoñN®éÏwzrd8éŽk6„Ó¿a¢ö,Awš J°7×h´ƒrÏ$*ä×£!æ±T3覈V1™g]ImÊ-Äìý¸wÖiÄñù{ ¶Uû1¹’ƒ_8I;—D>Šø-ð`›Â‚t$°Ž°‡†Jø¶‚Cå3gSám°n9Þ›œÏPúf™§³†‰2ºeu²»¡)õµ.©4«gË1 Xy¿RX)}4Ö¡­{Á_Ó"¶i}6!÷ ûï]l’”)?…ˆ_†¬(®Þ%9kahâæ›Ö†ÜF,èmðV‡ZâÓ.Ç ÅAÄödN1 .ŠÂaù–¤ûÈ!ªC ³ ô#D&…-¾‰Ç9$¹0åœP²p€áù  ÿ)}M`K<ÒŸY®RÄtƒ jhC.:Я ¦™Ã±d¨5%Í«²3JýjD³|™p)âpø~ŒÂu ³ ˜&vLô6­$1HšZ`î…ø¥ú;òÀ­Ä–ªNnÖw2söw}ÏMC¨(–š¨ð¨ïåøãÎä®\ä@¬ËÁãüöHˆPâ¦b$¸Ö®ON0ö¯ñgÀ¯÷)KšÊÃÌíXhŒéÀd§0*:6È~wŒ!žA«1ÛÉ)džX̃©Ø:"«Px—ºãnˆ’æ¹HÃÍûåyN?U¥sƒL!>Î]@ëÇpÁ ‹ÉiåÃÂ,¢m"è¹®¬vçôÅ‹~À¿Ò´)xíã®ÇÉzF³ƒZtª#Þ^âçAÜç¦R@ûlLXŸè'ôž‘2…žâ¶ ‘my'Y#`Jzi*»š¬–䦌p;Ö-?ìb,÷¢5|¼Óa»‚qò*’+¤-‹Ž%"ÐŒw ªP50ê-+–pú`‰©xZ`d¢â€çd#Lv]’ÞýV¼GõRg+º2u ¨ <™FHW·äÂd[Sl¸‡eY3–‡Lûò6ÿ§-ɤ’î›zœ¾ WûNƒú±eÛ‘a¹œdÿ‘ÿG 9æ3K€äÌá¤:ûÂf×ìTÙ}“±|ÉŸŸªÒ< [Wëw¢qÖ ¿·2bQ–˜þ.óèRÈÈ1!ûÀoŽ^dš˜8pÔaçê_ßRŽwνÜ#¶m¤ÙNMz¡XÍä¾]áòbµ“ŒÜ Èè:r¡ôJA§X‡oeÉ9³Q郇‹œ…›|·„#èf| á…ÇÏWnf0ßÐ’6J{s~Òפ![ÓíSX™Ï£˜lÔc>}„Z§!›äµµÙ#É,°hñDA>DjÛkA´Ç‚åK‹*ƒ§Ov˜lǨ ë\ǻΓzÝG.عþ`O¨'«&ª´V€cѹŠÿ´¥Zì¡´Z·„ÑÚ;CÌ:ºü¨6²Ý9Ÿ„þq‡®$SGQÎ~°åFýc©Ëÿ–A| lw“Êí„éd|’./å¯Ô»_»Ttú°£¡ga’j¯"rå»'(ð.;Ï*M%\œ ô¬¼Ã™Ino jýßl"ûë•§·Û—[èÝPq3VO¡´>0Wlk©7ÛWÔ§™ !^ŸN~‚´$í>{'óK¹Éª„TmͦúÎ#~}eìIÅT0ªG·:9½­ƒ(i·³¿ˆDìE† ê—™hí ul­¯'CZóû$i]•9p÷ò-÷þ»v K„è®§ùI%>iS1 ßEØ4^\8åΗ½e`g èb¢'x4Ü^Úå -eóµdh*–D¬¼È’¯{²*—+"däÎED¿Û+F…©pçѦ³Ô±ŒŠKøl¸ÉØÖ¶UÑYÉ ƒ–O*õoÝNºÍÔv†îo”6€Ñ84x8±žÝ Rñ“߆ǥýtOâtÏA `Ö¶Ó)R /XÑ"ÏC<þÍÎ8Ûgî ­Î.5.û¦b³«}>ýosÜpÔ›ûeÒ`¾•ÂUÄÌ^ô™ho©¸ºòÑQ± ±º÷ÆÄ¨‚êg¿†[~€ÙŒÞïPgù[û_ÖËÚq×ܶAÅö¹L¡%Å…0Éɺ² zZõŸô$—Z å¶ uß%¢–ô§- …¸s×2êcš¼ß)1Ôª9wÙglØ ÌܯCJ`Øé1#ò›§©G•è] ØÆÓ>İÊ&BÔæ«±!$É$»k…]¶!„ŸX;?Œ/uµ Y†¼¡V,“sK“Í›ï2nøE›«×LÇ>Xä]uo ðŸ_ ùgÐqíÆÄ#§“”AY-Ô{˜zÿ¤-oA2½xáÍÛ˜ääXÿ„@o±R™ë±WŠìÈN(¹PÝòhBÕ/ ¨b]ûHáÆ€Üq^AºÀå¤ÈÕÖ”dÒÙ 0.Y…é ZîÂDv…Ûó§)œvÂåá5ÛÌàä¾0à·w¨ËøqIA†— Þ´¨ŽCíýªcˆ·qdàˆÑÈêv†p‰@“A4<Œú0ÒQ¢ïC°èf¹¾—œNŒÃŠÿ˳¨ÅÄ€žoZ²ýMÀKJv}Ÿü&Ú`–S3Úð'âøz7ßGïý‘D+z—’xà7Ÿç %m([Ù} öQ¡R1ë°²äìŽ3g((¼~òa¾Æú-Lvpo¸[퇈 çh¼‘Ž*Cý1'¥µÀF°<µÂÔ£ŠÒŽh¿Û|ʤ‚ˆ-«ÌÅobä¾42T¿8*O»û„Žˆ+ M `ŽÊP¡Âüƒo? LVd¦T‹P¢íæ%Þ$vØMg.hE–bs”½p—]RëÐ0.ÛÎ2Á~aèUH”œ ›] ý63ë4 Žùîê³S*³ýîµA¡%¤€À~aÌ~kÏá¿i¨ˆ»°¥ ZËÁοMŸ‡ ÁÞ¯ ›=×Ôœ‡èdžÎµþ¤8¹^îmƒÜX—Àœè³÷¹›“oÕÛ„%KS¯N;þC ·"‚[„u:ü²&\¢s9þ=„ˆRÈŸ |)µ3Š͉À&iëÇFÞå :§ˆº×AÍËI³kìK\-ÚþfÄó ¢X\r$ý芰ýüt2ÑM {£shÛsŽ¿Þ[ú·l»Ì"Ÿ•¢¢Ž0¯tç t“fèåúÐàC›Ùôk*ƒþÄÙI2üzÏqý72¼?=ž´¢–MàË]‹Ít”½FFÈ#Ð1càFÊ>¬ègQo#ê ´¹YfíÛ7}Ç ,êc‡Æ•‡(fe.fJ6ÓÚD×ÓÀt¬ÙŒ7Gl`y úHz2ÝBH¼ð°’m…ož}FS)¼ô˜ï¨·^;}®? 2†JÀ`NUURܺÊþЂäe³pA8÷›LÅØœÇ')üЧá§x¸°CÅDÔ®›fò!¬¦ ùÑ)·%§’tL©ß ÷Þ•ÛÊðR>h6©(Ô#(¥jâýHY¹n(yŒ9Y-¹ùmNŸ¢~7­Ò>â:âVæ÷¹Ñ|Á–³opïÏÉ¿…f eS™¯ºlæjrFǯ…F%hW~@ý]϶½”pT%ÈþžzCq C‘$ÿl-ñž8Y»iÛzµŠ1·×Ÿ÷ð–ºENâM=ú˵̻̎Û'T?Âwk´~œBvµ\hW±çÎÆ»U Òƒ!ðÑ#hßM”4¹rFvOÒe*i[’‹ßJGþ“¦’Í‚j&ÚmS1ÝfíÔŸß8öÏÁ–ãiF’0+ÊV½è˜t].“I°¯É‹¨îÒ@ø!ÊÕ¥aâ#ClfÍŒ ‚‘¢Wz V!ýÕ®–Š3wÀBd òTÎþ¨ Ý}'î‰ÏéYÕc‚Ú+º3.·NK/Ã#€©Õš¶¹<rÓ›8­w\? /S:làD+x«¸„šI‰Ü=Çѱ¯Ø”/­;€i@]J;XÌ¢Öe~ŒaG°dü¦¶*/ш: _éF$“¢.¹,}J€s«$OØñÕÊÿã̉FZÍRp1,÷yeÏ*üÈv°÷š2®ZË"§Ÿ3@ûóíRŽCúm;Àˆ'DK„‡þÐ`iÌ5zý×xÖæd! èhS·ùåŠé^B1ùA4n¬°[ã–)%}©Ö4“b‚“°UQõõnð&?Õ®7~×KÔÇ9hÇ›¯GlÎ`J|øôÉÛô±Âì@C¨½:Çå Þ=Vç’›—Ÿ/Ã\„ýì >ÙVpô..š,År02Ï‹kÏ~Gµ»›Ø\m°P›[g¹ÌfŽ€H¿í%ê*ªš 9u³zU”ëB8³ÓQœpJPg«Cy×"·ÇëÄ \Ü5¸ñͪWÀ"Ùa¯Ó¨L›­hŽ‹4^µŽJw´g‰¿‘(Mg÷ƒ4þò$£˜½‹:‚¬©q—= °+ZB—÷*¶ùtDép‚ uT´nuøåÏ·}„›Ëí>Û.zq®Ûm¼œÖø=xîæËžAy9/ýZžT·ï8'rè“— ÊÔffHñV¥«ÊTñr‘z8ÂFxm¾—ƒ!–;Œ*É•”Ú¥ö¼cØöA¹Ó6tÝî' T§}“qln§?îV-Ñ.ÉœLütpX\v…¡ôÛw³iøÈS›†&Õ~ u¼hóÓAEþ½ ·= Ûâgs­¿ s)&3-Эjˆy F­8ÓL é@ë÷ªé?ò½!ä¬r¿â·½Þªžæì¬ºÆ3÷ÇŸ 5¥w†K­W0ú1ñ GU!d©­S2Œ¾MV*òçÑJ2#¢¹ìLI2b`™1&],«6¥0 :›œ[ ¨@˜âÇ“)«–9Ž k‹ÝáÄ ªÕ&ùüöñâ~ã•”ÓäFŒuŠÏÖKîáŒ-LÌpö]îI‚dÅ lŸjU,föDQŽÿ™Ú¶^¥£ü"Ó{Æ=fû/‘…nzZ)µœ¾Mß>êÃxßsˆ½ žÁá1O¨~md’:C¨Ú%ù"i3P)QÓæ¡=ä8Å k@ò ÔóLÑ=í‹i Ñ€Ä"fgÜ6-TŸ'QßâûáfvŠ7?‚«NB7þ©®®kÿµRzÏH mèZ]±êÂsòJ+y2ªæ3t^oQc^ìeú žšˆçÞîêTŒí¬¼þ_¬—¼TsÃèø}‚nÌbÛêñ¶™~§ç××8Ek²3gpÛÌJL–Œ«]?|Çb‹kÒ¶ š`èÿ_~þÿÿß`dmbàèlgcàhõGòq6 endstream endobj 51 0 obj 15770 endobj 52 0 obj <> endobj 53 0 obj <> stream xœ]”ËŽ›@E÷|ËÉbý‚±dYòc,y‘‡âä0´¤Æ ÿ}¸u+q’…­KS]}nUSÙö°;tí”}ûú§ôÜvÍoý}¬czŠ—¶KŒM›¶žôIþëk5$Ù¼÷ø¸MñzèÎýr™d_çw·i|¤/ë¦?ÅIöylâØv—ôåûö8?ïÃð3^c7¥y²Z¥M<Ïy>Vçê3Ùõzhæ×íôx·<¾=†˜Zy6D©û&Þ†ªŽcÕ]b²ÌóUºÜïWIìšÿÞ-tËé\ÿ¨Æ9ÔÌ¡yî‹Õ¬­è2‡v¢ í©t Þ@¢­Ä—\‡~£öÐ æ ÐkÑAô†ë’sËxYßqÝB¿3 ½''´É¿€&uò[0ò{0òpòÛ-4ù½Ä“ßï!›!¿ÝC“ßË:ù8òï Éï%žü^Î"ñ6kKþlVùE“ß×%¿%¿“­?ò[ò—èÕúƒÇ’߉&¿ƒwK~~KþBö*?8-ù ÔÓjý…™ü%´S~p:ò[ÑzÖÐz í“£‡yöõrÅ3,Ž>œäÐ>ˆ¦/çkp_}8Ñôá$Ï½”¨§£O/÷Ùë·.O/çyí|xú𨭧€ó¼~ ’‡¬Äè·ž‚Äè· gmþªòzz r>½8‰¥'9àÃæñ!§FLÐ;¯Ár=êCâõNáîúp¸SA}ÀS(ÿå‚ÿ@?õêGöiOà3ÐÏf'H' Ffåï—Ö÷qœÇ› T™k˜hmÓ?Cwèl“ß/»ƒFÏ endstream endobj 54 0 obj <> endobj 55 0 obj <> stream xœí“ePœß— ƒ  xãh܃· Á]wwwI‡àîÐÜÝ5hpØžÿÌü˜™ý²Uûmkß®êzŸsÏ9ïsOÝKK)eoç¢îé`d¾g(lM\UímíÄíÁfvvX˜ ˜L]&æ– ;4¶ÿ¬ÀÂæhl*Æ ÿ°ÿ{àß”ŒmÍlÿ³ã¿–5ì@Ž®æ²’. ;ìá|)R4vqytÙaŸºÁ~ÿù¦ïdnlfoö|É·÷x³yø¬œ\@—öÇÅåû¿çÊÚYØ8þ}f®ÿ±›”+ü/U†ÿ¡ÊøoM`™Æ¶ °çÿI®¹Ù°}´3µ7ÙY8¸yÆNNÆžhì°éqps¼™¹ÀÜÃÔ ÀöÞÎÞVppuñXØ;¡ý›,Àfåé`en÷oáE8lNÿ'lùà°YþÜ6{;óÀæânÿòØþ>›Ù?À`sÿ€ì°²‚É8;›¾tÂdÀæÎÎ/˜ñ ÁŒ<^¦ô_JaFÿ¥&d œ‹ùËÞ€0/Ç‚‰_†s{!˜˜× Á¤¼Ì^6Ë“Rz!˜è…`R/“ú/“†I¹X9™¿HsÀ”l_¦ôòN˜’é Á”L^¦äùB0©‚ùH¾ÌGû…`>Ê/óQ{!˜‹Â Á\$^NÌEæ…`.š/sQ!˜‹ê Á\,^†Ã“Qy!˜ŒÎ Ád¤_&#ûB0—““q}!˜Œƒ¹“©¹Ý¿¬ÿv[L]œ` ÿºª°«ôŸl›ÌÍ=ÌMуÅPûhº…tÍ[$3œj‚ 'óî[ ¸‹s^-åxgM<Ǿ͇Hp!ǽv0G/…ÚÔÁõ~õËRÔ¸Û‹ ®yꌕÁ¬ÍfßkÛs^¢£Uå:ð„L@¶B)Ûð4ä±xÑUYæiŽ›Šyû·ýB9Ĭ©qÙ^½Q@Ž—²pÿb6«w‡‰]\b'‡)¬FÌÏ÷Е‡ƒç¬ÑGÅ>Þô)ì¾zÌG[í¨BSÖöåËŸxÒOÉÕº çž{åÖàRT ´÷aIF¤„4½´Î+ÇiY„п^ÿf“ÅsS/thûGj¦”’Œ/žŽ|½/IÜì!ˆÃ÷àAÜšZÝJQApÉ\¨ï-mf± ê´–^vWÂ@èðñÏI¶7¼ežçdLU´é¹ïø Šx«‚ —Ü£¥‘_‰Ê4ˆ æ ~$¸kP#@j¼úp®µÝTUÈž{±š]/ª,®èºs¸"'Z´PALF|¦ÚÖ€›+ܦ»AX7Ì> 5ÓØB޲r]Ãûã=ÆÝ™qéפ噓Fôغð¸„Û§ªzŠ?¿Ò;_ƒg¤®ÓkC à%Ž1ü¦$:"øç‡8H~5¸ùñ5SÅÏ©>ü<ÑA7ë,m﫽†à¾×èŽgÖF®@.6£+ÃD×þü ­5r¯ªÄéæã¾Êvà’)žVÂ%OÀ—j»¶ÿe¾yÃéä[%WFA¯Vy‡ø”5ÏÅXS§nf—в?_\÷3ò>r !ò$c=Î"ÈÐÍùë”iLºÌêÊ:~¤eb?ÊW+›Mƒd9ý^ÏÝ¡ªWBRÞ;$_9úGVÑ m,7hff‹dç†LL²ýº·ì¼|AU>Ä"=×·×òáÒ·é¡ ;¼yð³{RhI"fiÜ£ú rå4rgpö×à¤)ŸÒC͸ŸþíQ¬T#ˆO1M†ÍŸæAÂF5uù0ù•íR©Š>Ñ·&5–0·.ó¸åîÐ~uå)žaï¦'zŽ\³køçMWWÜGÒÓ[mH´4Ž~ìòqŒã{dž"öøÊt–A°¹a±auãË:p[¦GŽˆAÓÈpðb&÷È ™7?ÿª8IôwkóAk–&$Øõ€Ù±Åg“`ÕL¼Ñ~·é£7”cU×±½Ôç 1šiϥ˱Þ2Ñ[·2±†¸»N~aÖÓü0½ÊŲgŒs+“xÐVµ ò«ŠÞ2hCÍ)õqÉV}¬žvµ¨ˆ’ŸÚ¨÷MeûâÓ†Dù…ÃUÀ+6lnÄ÷Ä¡«¾¾‰4ê[Tò¢…kô¦)&¯f]žé\ÙÉô´D_îÓQK)ú-o96ïû2¦k7­c§ƒN´€/W__thŠ€k8¤ìÊ¿v·ñ¢ÜpyÔc8iFË?åW?Æ_> 8~=qÏKæWYaÖпvm8Za XLÍ_D:ÚÖþ!,48k¬Ì½Cu„«£àúyh`zaÍ»¿|)oehV›L£V)D±íªE0Û/*Kbu ¶ƒh÷MÌJ ç—-³²uŠ€$à~/~K@HÞ>Kq¹Í çfëÊrû‹©«=¾«ÖË!Œ»sjEúËK°­šp›€’=JÒ,„€ba¹]ŸoÊdß v²‚L+ÓÆÄ*ñ'KˆÂѼHùàøl´N£ç•ÖÍŸ(=7Ï?cJäùvµt²ˆ5sLíò({'ÑïG‹uÜMØâ·q)ŒÛв>è,x¾GŒÖÒKV…²è¥Q!¨y­R“ìa''hxfôö!EÉÓP4嫘d2¡KN>éȶ 0<•ÑÓO8#Ö#Æ? OúÏÞÏ“Öá%Gªüï·qRÖÙWNèN~+΋ãòLCÜÔÓ牉$ît­Tù˃ ãoZq¯˜ëó$ñÇt‰‹óæ~¯Ò/óðŸi°µg6>^ÈZ¹˜ å+åiW3\Î>„><…z³Ëš‰:R‘ÆEàg}£&­©ŸLõžvÅl>Û_êø]tÀĪœBù“** Ù@:”¾«q·l¯þòàW 9læÛQ6ÌÍúÝ éìå“&¯`µ (êvV»¹Úê^TxŽ$$£Ðü0ò¹÷<‰CØ&Þ»{®ªýzJ ¢ï€6<¢ÅÞ¸Š$³“#9[`›™e¬,°#ýX^UnYSP“ /©ºì¼I/Šötb‚/2zNôo #Eõ"þYÌZœœ7}ouµ™çÒt&¬¤àó§S ÑQ—"îHrHÕPy›ø`ñ”¹ãéNx”õúSÊÀÅÿÆ÷& šîˆïëŸ\º%¿Zqȸ$Y{Jz”y7ÆÍõS3ìƒýdýj=ÂDæã² ÀÃwš•¿ üù qlñš_Ãdx'™;¢¤åjÌ LÞZ=õ“ %¿â6l)d„K·+&»–§û#?vê5õkKMÈY"ò†ž7¯4j³pèif€Õ “hÛôŽ:ÊYî Ò¢YFeuxÄuq+8…Vz4:‡¡áÐuwׯŸV&ùù OvåÑîàùy‘"ŠÈÔÇpžÄÎÏ‚ÄCmw_p ‚Ï“58Æ©ÝÒÎçúêY¾ùbI b.a£ùá¯9Ÿ.»CÈâ‹ú>tþøå¢/ã„x‡ŸJì>Ç@ˆõ!«`´RYYã3}œ§³ú-Kò7T?tRBq" Ën7l[>öcx8N2ŠnO¡Aú¦*r>_™uC‘Þs£Rß:k¢mŸfXp´çk“h§ˆlë¨OêîõD–ÇS:Y’³È˜ð³ß7j>Ñr7VMc„¯€®„àWUévàî¤üѲþªÔ-mFQ¥FÝt ÿ«lm.K.r'µa„ÛéQïÊù`è­×ŒRè"kWìHü"ßúžH0ø\½ªUˆäÃnÆlx2”ú›ÿÊøCáAh>”Õ•XS5ÜG³AP€Ó„WçÏ[5B×Àd¿r„ýo£^‰4;¦g3‰V6 ÷a¬ku^É¡¤¢ÞB2ñ¯˜Ã@ùë/[~}Ò ö™}—’>Ò|I‡ž9f7ÆÍaD°å:ßL4•dʧ}(BþY¹¹ÃchšbL?jc»fËõ¡–´Ñ0ûåE2\cW g˺ ®ìÖj&€£»äWWšEAµeXÓ¡ 9(²·ÿðp%œð#8xhiý}S‚ãáÎ7© Aöî:Ã8+’LÔpgäSè·Z‹þŠoç÷îʱñp:î׬w>¶H™ÕÉp2ÈF#‰Ò0°&L^²Œ=½ƒ÷àÔb¤à¦K­ð<ᤉz¦UŒ)î@™YÈjE#T¶¯H&Jûy¹1 9êÍYŸYˆBóóº% -^‹ÇQAނֆê|®z£—m¶åÅ,ÜÕùâO•õNØ kn½ì³árg­OU¢j¼BR—…càwg ‘½n÷Ø?ºÊX^ßx?OBS1¼OñÈTBO”¾ÔÕ;­\sË+Ýâ…Pê³|âµI'·?é¦È²‰øè‚a¼ƒŽ[Ø+›rñ“óMVs úþ–;0æ¡TïMˆá@®äŸõBâýšåìÖößV‘8†Á„v¹ïk'…±L<°Æb)å€.…cÓËÇá'?CÑcÚIG°Þ†Ÿ¦¢0ɘ9nGžÏ–Õ@WÓ†°§KjîýesÑ]Þý@p¥0HôÛ^b6@*‹r[å~cQ…¡Çßo’F!šó‰EY\Ýæ™n…9îSv?Íú°4Ëì{%$=÷ùæ(Ï”ð>rx£y#Žp_or:P­‚Q• n—ƼJJ‹gw-Á=K{vìs*>œ §ü~b£5Ëã˜*wn.ý£ØHÚPËMGQˆäÊÑŸMç@å MFOÖïl© º%R ~ª%÷@ºtÇÇ8ï¼½[è¶V¬ ªZn•¿?i¸Å-ôQ忼 aĉ,+8Ý6añþ±ñv¡×-Æ“nò©¸jã—y;yÄîÑ}Q֛͎=¥×i»ᄼl~§ë`ïqjìêÕ½ é~¢kÏU|À·‹=Uà œ Éìʳ·®í=TMç²ÁXŠxYK¬³â2Ù«¥î†œH§49©~‹‹ÈЍx˯غÄh ¢¼k~7>‡ÚðïÐÄ•7µt•`S¥¦…0Ò⣠¿Ÿ]•¥K,eúŽú=·Jc>Öi$yêGBFã”31MJÊé—•.V~~$yX(ù€ôâŸQ®ˆ ãøŠ—1`ÃÈ zü}givF¡ýj톫ӽv+›Œm®Ó†Þ‚áÅPF¼ EåÄò’¡‹k›æÞHžá±kgGwšÕ ~v|ÊDOt· C·Š¹ïZÍÈòžØçÌ-Jl½¦ä£­_jt”Û¥’¾¨ÇOSFG¥å§$£Ýª¹ Ìc?¤F+ ò ?¤ (2p™_Q¢õ"–äûØ}¢EÂå–è4nU°à¦B„Ä3?•«p­ÉIkýÈÞ‘1¥Oýñ#´itq‰MT¸ ’8ÝpýÆ>7eá͘)nP¤a&×>\‹¢Ð“”i"8mqß­lËé†NpUŒÆ®âÒkñÈ»nóï"òöj’áù—ü$'¨äaé’`©GäÀur‡÷¦Uàc ìò‰vþT¶Àû­0i9•уݤ@´áŒ§¶§í—Ï“Nôø6y5É+Ôy>©ÝÐ;Þàçö ÓGë¢ìl ðff¼#¤dÙðñE5`ÈzBŠú‡3TÓ6{ÅãH=×¹)u(¼‹\í‹N+Ö‰m—¦p7xl³~ðT™5ò*ot2e:P”¨1±Äl°J AÅá R;/–óûÛL+“~³½·Úkâý»¾ÛÔǹsŠgƒÛîë å˜2®É‰ç'©ÈPÁÃl­6ŒsÌÜùmüÊLw’×dÄ&SI#ŸN*ªV­§bPça¢i9{ºü¹àµúdé¶Ä4 ·á¸O²¶ ËŸ®9¨Qü°ßRÛ|[œïŸ³ša“J—¯Ô¤"Žûl`ª¹Mlý0­7D”7'Tù·«c™ c²pÔ§ˆÄÞw&WA6ÓDÚµ©í¹ëþ6}Oî}¹u¼ì_ŠH+q$«øhïÓEÒS ÖKõî¨äï§S„ãÚŒæ…ÝŠ ø-À$q1’³ží?ŸÝ»§y Š,ÝÛ-ŽíL*œ–ù´Ò·)4¡[Wôëµ®*ÀúdGõáªÉEiô p>¸Ø²r/"‹ /1bJkB)Ï2sqTóƒ'—•Qö)øœ_nÍ•«ŠûÛ]#O[ª† ùšFߢXÊ6—;”…¯ûèÍÚäí^ÊkF4””Æ tr4l®ó\¹Ù÷ãXL=ò"ب–©×ô6,[÷±´.û¯I›³ÇñmäÌ ê)60¿€¤C¦Ó6¡•?Jß9¿}XzƼŽÒ,h•aÈø´ã-FÍÌ<éÍll²š¤‹u›§ºïaº8a• íie˜˜ä9I_§¶-|dôæêÛOÌ~x3îñnÈ*çpWØG•‡Ö´Ý8ÐÑ~cL_Å;ÀìÕ<Á†;í׳ܳÃb¥‰4FfZ oé‹Jݪ>º±ø_5‰À y !Ø«Ì/T¬€Úès0)IELÛT ü]š¿H\b¡ÞTô]°"a¬$]P¶‘UÌtHÀ}J×¾"nèêº^âí…b)|6wÄÄʙ澘ò6e¦}°‹¢øæ$˜«ÖÐÔwÓ`òÙ SÃè8+ JMÙnÆ¥q:NñÍš‡:‘ÉÒ±øâSÀÑOÌ·/úxùö@å é¶cöúª,ú À±[Ž"§uëË’ûcè&ëIê–]Ž©<Ò2ÜQa™Žë8(¨‡ Ò4¨èØê:dãµ÷t­‰„_ïøšÃ¦ÌÊÙQ9Ž•éÌÉW´³ÜÅÖ¤3k–š>ìˆÑ¸²Œ‡Õ£¶Ê£â¹±žô8rÝþ6{ؤÔjëBí³ì… F]©ÿHü«ú±‚#±2 ç}‹lÖSÞ®Õe®Ça£ûYj»„Ü铹áG“9U¬é&ê¯AR› .`’#¸:îÿÔ¼´Ž`xû‡¹ðó”Åñ~0ñ—vË‹è‘RÌ(Å>&¥±<ÝOY¾Ê·üàynÜ &ùVФqñž2Phêi5DÊ@!­'hv‘ša½ç«×tΣBñž´’rÉéú–eàÑŸW‚©i9Bˆ<\æb?mçz¾_Í—–îM‚û%d“ô¥VYv5—ÒììùKðyQ¾uþDT±¿zMÞÝ–y5«î×Ú‹MO-‚ûi®V»ã×ì{|`‰$¹ðhDXž~˜CÛ8ŽJl† !°Ú|&…8Ù{ø®†­N“/Óð>IŸA`*Êá‚|ϫ֒ûְ啨ß!ûEè(Ò“l¦"·ð8˜þ›ý”üZá1œRç靖·ŒÙrÉùD'.9í|¦¡ËyÞ`³“°Ú÷Ê êàD¾ ÊWÞ翞hC’KæL„…‘eõ—u>Ço²sÓ¿j 3»àpÔ@êŒl˜ÅÛŸ"kÒá]ȨÚËx¬:·bÐP‚cçób—…>ž7ÃÐÈ1ÞÞÒ8=³ ~2?LðMÑh½Öšö“W¨\©wÍP-¼ *Á¥Z~B˜ n§3æä*;÷â LÍ^9¢–\ª¥C÷ò¥v˜Î»Dº¿þÚÌD¨ÐÛdJ˜ëáK¾úìuÞJ<ÅÈ£-&NÐ*`u¨xÁà‘…“_ìÜà¡LZÔÿþ˜ö<5eŠ_*?ðÓIýè'«@Åu2²6s˜®í‘­¨~–›?«J<ÜF†F7„ÖUúâþüÀ}WòT†.å¶=¥Í¡.jɼïÔ+ ×™DÖK;Lè8é°º5wÊ­3)ÑúÖ‚®~L(XhÚÒÁèˆAG&ظÿ±x¬æ…Ì8»9wå“S‰šÁ‘Ýi+7ð¡MØyk'û6·HÂöMŸÂQi1êFø™ßfrêlNyZ%TjÜÕSqÁâ&óPÂÿçäŸ3 =Q“ˆŽzÐMÚ·ÜïÕ~åi„6µ&^Ñž5ÞàQxf]‚ k&±8.ñ§D8šËŽ„O? öQE¯0V†_ùøòt…œßz¢ðÐ%i›JKS.žW«Ha´$†ü€ÿÜÄgP²{Þ» ­0.ˆÞêoO·èk~lbu ÑÇ_¨?©ðTu'£´ö{Ȫ¨âLågqš8\eS§>À}Th¯M_¢‚`è_oÞ7† /Æ'œ·"'&þE¥ôëŠF¸cÆÏ™•ä°új9C®a]«cUŒ;gþbÿ3³vs ŒøóQp¥\²M0K<š!ê_aYƒè?$9ñË?UR‡Že=عÀl_ï2«H…‹q§³êÃïÝµŠ¾“P"Z6âªUâwÅè„ ±7éZ³ÄñÀò&¡¥¿B$ éf’æ‚‘'^é^†ôT ”Юgtý;Ö)߬kÅG8QGºŒÈ65:æ­@=à†S‹(°)8ÂzTŸd´(`èc?ûø¦ü€¢\qÿ³1–L¶¹ uÖTòëUI#“ C4æRË>ùwˆøð„‚Œ‘=ôHÓùÑ¡“¹gëüMP¾÷^è…âÉŽ@Ûô'¾EøÞÅ`x0rÀýjë•nøíÒ7ì*O(tÅb¼g=MgTe%ö&ñKO…UJ‚SJ0¿+F u.‚…bP7XnU…]rn„ÑPš¶Û9äÿQå|£[uoíÒâ7Ú†„m”÷ÜI»¦r º-’™t¶v¸M=“FÍ7äm¸ÄJÅVªYÊà {±ž`>•or½RÕ¾U#éùÝïIo|h=±wg“g¸ÉOÏ=k©¢ùÎÅ,¯ëžüº¨$Ôƒ(‚¦ˆµ(´™-o¾{ª0@?—k]ÍQãSØJFäYXuÅdï¨ß,ß¾ Ô±\2Ωë{rîØ¹ámot+ÊV7.Ãr¦ÅN3ùÀ§ŸƒÎsÅ>†±Ëèã”óÀf"V ·ä2îJ€«rôàŠ–ÂEàxŶ9 ž/¢OßÉÚvò2°óFcFÉ€e†0>çÞÛr†ß^LEÝ'ªoS‚¸ê Mçtt~‡á¹‚Os^}·ljl¼¾Ü¯\jñ?6 özX^W¯+O]˜¾)(y‚@²6±ë¾ûjy¯ŽþA1á•IóÊh–^‚&„ÀU‚…O!ìj~%! ‚òõuãÌGóÛ4Í!ޱm6…^}'}­ÒìB]ÿ^ùËÃyÖa£uÁ-Ó½wg"vÅOÛTW±«Xµ¦Vk)\5­–*ùÜÓç©¥úŸ»ã› Þ³j•_Ó>¨ìü’0¨¼&[9"íQöx3*Ö߯‚JÆÕ˰ƦÏ4f­]$$;2ž!D[[‹¢k×êt‹[Úù”hñ^¿BÛË/3÷Z{ÓmWHŸCýöÙvË%”jÕ’—%3dØ¥•+€{ô›üÜ+ª”[Õ«~½”Ìsùz>ÐLF +ùñ Ë ã1 “¯œûéo $RŒ#-Þê•UBš Ä4'Q0„ªâ÷–ìÙú(ˆzêHO²9·ÚUµXFwoT¯Û1Ä‹zþ³ÅÐ\Ý0[Ô*25óÉýÖG¨ÃÕÄz󜘗XñÂ^J¸‚6 L›Ù º×LÖhX%p;µÔc†¢å4÷'þõ‚!¯NÓ'L/”ƒŸt‘¯·áŠËC9‘ÚwVòEÓd-ëfû q5±†þFÍb ‹½<éÐNI…bWúÂÙ®µ?÷d Äåt ²_9Ï]ÅB±ö?Έ‰—s§…+É÷z$ýD"|iáÏ¥Ô¥y©hã*ÏŒ”kÐ@å³¢f±oÛÊ26ò6L•gˆ3îzùŠá€ó¡=k2üGdÕ.BmO=`n~ò¢ÝFö ÌÔÒtŠn9á#J“›“H…˜çoÿ~Õë…œ0W÷;ê(0Uâ²^‚Eº<“×ÅÞå'#‘R¨ÿ XÉʽ^^=ìßú,†YqUò'I˜YB’ôC9Ú¼*8eõ\¿«Æä_…Íêq,~°ÝBáMßEaðCšŠŠرýÌbA«ÀîÑu´8‘ä„§S \›uÛõ(vUh|_’e~W§¸½”8zø{ q}$÷øu™a‰$$ÏK*ý}ìU²GLcúÚJ™lÍW§ŠªEY¦€Ätã> endobj 58 0 obj <> stream xœ]“ÁnÛ0Dïú ÓC ‰"¥08v øÐ$¨Û%ÚS-ü÷åì0-Ѓ!¹;z»\æ›ývïÇ%ÿSp‹:~î:ÝBïÔÑGŸ•Z c¿¤•ü÷—nÎò˜{¸_wÙûÓ´Zeùxv]Â]=¬‡éè¾eù{\ýY=üÚâúp›çOwq~QEÖ¶jp§èó½›ßº‹Ë%ëq?Äãq¹?Æ”?ï³SZÖ%Qúip×¹ë]èüÙe«¢hÕj·k3ç‡ÿÎlJ9žúß]ˆ¡e - ½m£Ö¢ ]‰®Ÿ  umEW%tM-ñ s è'ÆègîKîšZö_ø]‰ßÐg½e®ø¿2^vÜ·Q—÷+hòW¯Ð‰¹eâ‡gIþ¦†&³†Nü`(ÉoÄ'ñ?C“¿–\ò×CþJÈ_£‡eâßA“¿–˜Ä^éÄM~M~ƒþhò[‰!¿§&¿…§&¿A:ñË>ù ú¦ÉoÅŸüVüÉo…'ñשfÍ,ú¢YƒE¿4k0¸ËŠ5ÄW¬Áânªt¢YCDÆ ¦‰ÃHâÍ|ºêo!Ä1—‡%óɽSß<ÍH“ßÚ`ãz endstream endobj 59 0 obj <> endobj 60 0 obj <> stream xœåykX[×µàÞûIèt èx$@æi@„08ˆ—¶1$~aÇÎÃ4‰c?›ä:/7ÎMÓ4u’Z8IƒÇq›Ì|ém^s›Þï~ÓäÚms3&Ä™¶éÌdl1k ÇvÓÌ÷Íï›÷ˆsÎÚk¯½öÚëµ×æ„§gCH…惄ám©žžvBèm„pÒðŽ0ÿê.àK‘Ú‘©ÑmùÎ_Ž›L2ºu×ÈŽw_»!%Ð$}< Mu‘j„²€GÅ »zJ mÚ9cÛ·}"/d¡„öª­“ÃSO”AûaÚÞ¸mêóÚ0?â'ÛBµ:柡ýB ÂÔäL¸Y£åÑþ©éÐÔå?t;@³×÷Hî&N¤\þ3H|IÆÑv´uƻψt˜1Áj~Œ^qWÆJÄL‘s$áê#è»ð[ ¿ âï “è™èXôz {°‹þéÑn‰‡¬EªåÏ%“ƒhµ¡!äE¿Gn‰VðôõötwuvøÛoYÛÖº¦Å×ìõ¸›W}]íêšêªÊŠòÒ‡½¸(?Ïš›cÉ6› )ZN£NT*ä 2©„eFE‹wX#¬ÕâóÓ¶%ˆÀuˆÁ(ï4~P$ão¤€rä&J!F)\£Ä_‹j‹‹x…¼ã¶ð‹x}G/À‡Ý–>>²$ÂkE˜µŠDh˜Í0‚÷ÆÜ|òžˆwÇØ¼gÐ ü”Š&KSHQ\„J•Eò-S 8¿‹É÷Ô,”H§0¹ž@0âïèõ¸fs_qQKDmq‹]¨Id‘6Ed"K~œŠŽò Eæ-rhhЦ Z‚½&cçÏüü¾ˆÖ)°¸#»?6ÀÊC‘"‹Û±Q®­×æiýzJ‘är~þK˱,}v#&ÇHs¹/½ Þùy¯…÷ÎΗç†,‘–©Z‚ã|DbµÀ¨ë€§Ð!óœØPÿ%öZ2ÂVm_m6”ÇâŒÿí3¾¸(â³ÅLßÝܸ< %»EóE–©HŠ¥ñš=©Xžñ®^qH|X$¥)‚‡ã£"›ÎÌ{æÝ1(/KGïYä\¾´°Š7¾àD«PŸ›§6_Y=ó½Á‘ˆiЄHá{æˆÐî³ô†ú¨£† .ÁtfqÆiêîmí²´v¬ï­Š ë ìØ\ÏMl,½Æp¹HBnßKŒLr€à½Xká‘å&ÀÍÂE,uÕÆZ¾Ñ 5ˆ)à=!wœŽ¶o`*¡îÔä[á&¥MàÓä3šû̱«¸ˆ@7ŸF$P¥úVº˜\È€#ÀFDQ]¨Ïó½–¥Ï2ÆG/]U¨å¸2DÇmÕ}Cë:ešºWT™¯Íx½r#ÍbûZÓwSwËJ7?Ÿ`iíš§Ì-q†$o‰ êÂB•Ö(F?g‹7A -Æóü‚ ÐX£a;oi Î[ºzkEjÈ wwÓ¹’P+nín,.‚dÖ¸`Áû;¼¿k}ïYÊ®ýݽg&Mƒ} 9Ð×{–GH±„b)’6xÚ œ:¡‘ ÒÏ ͉½¬ˆÛˉ¸„FË$†ãVppl 'ˆ8z• c cÈß>HísGߨü`õq” ?Á–zÐŽ¥~©*¢°„#JK#Å»(ÞÃK)^žSqqÑîyÎcùÒP,nïÈ  ¤ªd²/`ä¨=#c3–ʤ’kÏ0@´ÀP´„¢ÏȤ™WjÏ`ŠwjÍÚ\³Öì&|4?“ô|õ¬›}‡&P<ÊÞÊžBR´ó%)îÄ/âDCÒ$ÅHÂâN†HC‘ù¬$…•0,‘&@ÍPR !Œ†Å,vAi±‡–ðI:¨Þ¶þ2G¿³ºÎátbƒ£ÿMîÝ2î§ûX‡Åç›âÛ`Ûg{³´¤²\ŽË±.̬¿ò4ó»GÁ“xâÑè¦wÄ ݽü[ÅÞ‚rÑ÷„Î`*rxWÖ,LÇn]·Ž´j7hÉlÂÞ¢lV(2š]ÆvãQãIãi£ä=ãE㲑4b£1/¹™r›2bd䌃Æ)ãœñ‚Qj\\¾ d³|F£ÁoNUû%&ååQ%£©TJ8ärÂj¸%×}oÇŽþ¥¤jGÿö¥2ÇRi ê§îïO^UOœeYD/³cK¶šèR² ]Q©W3–l;¹{Ýá†ô&^àæv¬›m6™šg{¶Ñž—»§x}gÉúþ?Ï•—ݺíÞ0^9þX0xr¢fó6UÓ›ª×=ôHç v#TÓräÒ$,+ÁyŸ`‰D¡”ù¡ÈeýŒ¹–Ê\KÚ$\í Rj¸´$׬3—ƒ”›É%|Ç•Bütô"þÕ‘#GØÈ‘˜®§A×}ÀŸAuBÆ<ÆÕxï † ’½ ®`F˜ àÅå/^¦˜48ì¸\ ”ª²þ~˜¥ÊÙß_Z¢ÇN<Í”Ÿ¹ò^ŠäÒW¼Èû; [+ÔÿE葳(kù÷Br¢ÖgͪÈ"…€ « ‰ ø iJ­/‘£UNNFÑÆB$¤e€OÙ³ho¢B‹Ú²ŒQ—A2Àz/äûè[²|R.3‡¶Tj­/'1±0“É@IÈUærV;œ6­SëÄ›­©ÌÒÚœKÚj­Ói³•–ôÛúmfíªŠÊŠJ©LeŒ…±3yÖ¼T}Öi-ZgrÖ§ê+*ëqe²SËü‚µZµYýÔ§¥p°KHJÆp=±tV®§G=•Ò ?û&èÜ\ä,­,/Z£kðO4ŽRCemɪâqç•OT¯_k-*uØroIÃøêU1ÖŸ]…@W*¨Ž‚g–ì%d77Ï‘)ýœž¤èsôA=³GsTCŒ›f‹†Y¥Ä«x5ƒÑz”øD"ILLKY¤œ”H“dLÊ€t.¼â½×WtÞ¢Æp ð^Ù*;±a­³,‰ ùþèPô®|üOO÷\¨š~nvד¼K"ÏD—Ü'ñ¬}ò«çö]ØUý¿þ„Ô¾ó¢}ßF&´é,R€¥*ä*_&öõN)ÉÊÒ:ˆ‹L’=ä($!%ׇ ‡k‰–7ëý*ê¹™ çu9WÜj0 ø/ØÈ1XbƒtêÃå+ñ¦³34Þ2±YGÜ/F¿ÂÒâàÉéL¿¿Y—äk÷%7 &ü)óÜ•næ¹#i¡£ È_ße¤&¥bS«âH,¿¾½•mdý(Õ¢à®ÆÞÕëV“-6Üb볩5ÕºÃzŸ•]eÆ«ð.æCPó`.(¨wfi½(i.‰$ÙýY9œA£5Vù’THK.ºªö²²›SÔ„¦†÷ýîÏŒ•ÝUe5¹ÒsŠÊàC[ÞúyáÕÿܵ»#ÿ|åd_Uß$ËL%$+;*Vu¯æŸ;¾åÀ-&Ì®nÚTcÔä59µÂ–[l¯.Díþ©k0\ÞÇbMɆ¶Î ÄÊgb|¿”è´P4"Û!»OÆåaù½ræv|“Ü™—iIèK [àd~1-¨Å"äÍ|HX‘ çÜòn9‘ËÑIåiåëJ)9%[™(c¼ödšM¹>ñjß‚R-Kd ,à  b‘ŽæFWuõJf¤©®ª¿Ÿ†\•³ºº´„jÑMõ›±ŒæB-vÊ1sôþ{_|ÿú—Ñü.þÓPtRòö•IŒ:®>Ds>þéרûIº bŽÓ4`Ëz „ØöDãÁLÙ}ñ)¶EE ΂ߙØØï=BÑžì£ÙävóA3Q˜ÓÍ…f¦:§©½Jeö¢œ¹’“&õ›RSt*¤²äŒ§¸%g<Ò°6?å0€z‹)·Ä6år-Þ¦/ïq £-yb8„!Lz}çfïú»»óØš«í›ŒÅ=wv™+Ïg·6•È$EÕ«Små™E¿$ÿ‰Ê|~ù æJº‘õ › » óÆ/Wû¤Ò¤¤L‰Ü›~ŒF,I’r}é‚RíCé8]å×§& ?D‹kDwçhâƒØlñ| q:hÒëO.w®;8x/] xºèáÚó§jnѨ¿'ßÓî1¤zo©xòIHu8=úÉ‘«áö6™B%9 åÔŠ’“blûŸ%"AÈ–Éh%¡\£R]«&ÔE—AE¡¹®¢¸®¦€Úç¯Ëмr§Žü×xiñSü§·Þ‚â‚É:ò.Äê‹‚msØVT…ö ½[ x—þ€žlÕãÍx¦ôžRÒ\zk)ɩą™XÁ¤CÝÉëx’ß’—‡|:©FÙ¢P8|È4hš2Í™X“C')ögóùÇòI~~6Çù%P°ÑÄŠt‰ Lª®Ž% 1e\_±Ý˜+³ÑEh ÷XU¯ä@Å4ýê³6gõÔ÷Ç7=4½6餪¼u¨ºfØWàìÝÕ,Ü5\÷ÁÏÛç·¶¨Ÿ”Ù›ºí_ÚnÙÚÐp`{ .oÛÝc7Ö¶™*²•Ú‚†’²ºÂ¬dm~CpíOgº†=)ÅUfÕCöj«QËz·QÛÐz·ò®YPŸPÌÆÞìuÙ$˜½ë2Èn1ôÈ–$Ü’Ô—{Ði#Žã9†ãrÓ›‘+tþDÎ䧪¸nÏßþM{O9—{=sóVÓÒt×KÓÛît_ýýŸ?Ͷv³Ð0Ñ^ìh¯n˜ô“¬#¿<äqúåQ¬ÇiÑ?D?¹ë©¡¼‚á§n¿ëCùyCO‹û)¬£|Œ‡@hÜMæ q;»A'ÓjÙ`Ùbaj$¸<KL:Ó¬i¯‰…ÝÔŒÍæ ›4Å‹’ç’I²ÕŸžÅ%£D]‰_Ê|ûnŠ9X€5ÏË’Yê1Ö¥2©ÌY¿i}¿x-|ªÎ. þ1ûix²%?š}ãÍW²\›[òó[Æ\ƒ‚™dG?Ž~²n(½Ònfå¶Z_»íˬNM×D?þfêïGK‹GtÇÎÇòì#ß?â+M<³Ô Ö©ì¹lšSÌaó½f6׋P^šÊ‹ç L£Ù‹KÖ$ÆÓp,{Ñ¥ÅVfÖ®þ×åNËÍ«ý%«G×½øuî24ôlnìš»µ˜¼ì­3ÐÌuõ0Óusæ:ºêˆíó{ÁN^•G6tLspÁ-}ãLKN_™ÍÜ›IvfìË ·©÷«ÉîÄùDâ&Ý$H˜<8Å([ÞS\T,+¤àƒ F¡(¶"Øã/éˆù­V‰ÙŸÎIüÜEÅe™çTpbˆö‹gª•m]4gÿŠ©›Æ ¶rŠZ)ú21¦ºÙÎàFkÛö5•ýkÊTsÂæ‡Çf~rWSû}§ïyiÚ͵‡Ö­fˆ/aÕÚ!üß{ŽŽV§ÕåohqøŽüêð‰î®ê~èƒ9þÇÌ5{†6ÝÕ;«ü짘W°Ý&Ý/%lzJ:aÓRÒˆÉdN•{gRL*ö(Ž*XE*Ó™Áq9­]c6tÞá0ÄÒwl98~&üÚŒzÑŒ©zVç­ï¾océ‹*.Iú¬L£VIF}O¸³jk!sËÐnôjN@)¸<Ë‘·Äa%Èp뵯Ôv<‡Ñ$þû8¬Fõ„ƒÙ1+‡ÖrKÆ(‹QÇa‚ÔLQfÐ*¦&³@3‡%(ƒ9‡¥?‡eèÏÌ›q8峋qXŽ2ØKqX‰ªØ+qX…6JVÅáDô/’cqXîN4MNíš óùÃ|YII%ß ò¾@¸ˆo™¶ó [·ò"Á ?š Mïí|[K£§³¡»¥ý~|†ðáé@0´-0½…Ÿ¹q|ÛøPh:Ÿœà×NNLv†Fg·¦f†CÁÐ4_ÌßDpSs]hz†Â¥ö’J{Ù×7‘þ„ÉGÇg¡i@ŽOð=ö.;ï„Ca>0仯 l‰ÈáÐt8Ä“á1sóìôøLp|˜Î6c¿&~ÓäôÔdL†®phGˆ_‡C3“cáðTñsçN{ N< ´öáÉmŽoë ïš C3㣰pûXxÛÖ6hbŸgi®W™wr ³5FSÄÏ„BFð.C%𫨅PÞ>Š"€ZÐPÙj@[áÇ_ÇaFl…à‚÷q,¥lƒQm:aL7ÀíˆVbã"}î0P€6„¶Á{mÜ$ùÖùÛ`ü8í¡ßü' w­øžÇBvÛ*òk€™†3!Î1 tÅ¢T߯áÛ{׉=3×ð¥ Õ˜t÷M#¿ë¿M1Š\Â"ïå¸È»(ºD*¿8’j!,Î6!RuÃŒí0㌧:ûšrXä†vŒó$Àcq}n]O‹Åq+k›™ÿZûÔ÷¦Áû&oÐC—(Ýqε">,úí[S¨vÚ)þì@s#çá8_»mÊÿÛqaˆŒ)Q!ÑÊ£@³¸]ä¹ <«-®¡ Ñß©†f¯[cL7Ë˼â;1[oàC-KßtìŠô3qùGÄybZ›‚ç$è=$jÛ.bGÅ5Žƒ Ǻ^>j±Ñ8îfiVd¹q=ÿ?çfâU¼ó.!(gØ«øK¾éÞ|Óóš¾ð–›~þØçÏ~Îl¹|ð2yõ2~ê26^ÞpyËe†ýÌýQ|ê]6ý—­¦O>®3ýëÇY¦ßýÖkRþ ¿õ¦š~sÉkzõÒ/.ýú#\rVx/y ¦s8Õã$Ôƒ“UÓs±î£ž©û°çÕ9N…¡žA¸Éòœú‚*ÕË/âÔ3P&Ÿ$G;°î̇u¦E¬†™e÷ÿ‘ð‘ÿ£¹"IùýÎ}ùÕ|ˆß×9MoM¾µç-fàÉ7ö¼Á¼þ3üS¿Õ4uóçKÎ_8ÏLŸ;O4çLçˆãœëÜä¹Óç.ž“œ}ÞjâKý‹S‹s‹ñßbr—{ó/û_ž{9ò2;÷Rä%¢yÁõÂåÄ›¶S>Ó\äX„D""ïGÇi×iòÄó‘çÉ…çßž8žs=GN>‹/œzÿiÐ` *ÃjH!žÜ<ÜSpC‘†9A‡ý'OL`9n5=쵚J"ô±ÇS3¼TžÂãj­÷ïŒË&̓§|ýAFx0³Ô+<˜j„‡JãÕ<àxÀõÀž.? Ѽ‚UP™©žÜØjúnײéâ1\r ›Ž9Ž‘Éc{ŽÁA;Êe(_þ¨!ÃË)9BÚž<Ì”šC¦CŽCŒpˆKör¯c%«D%p3` å=ï=KÁÏ¥xÞm5XSkÚ¿¯Î´ïÞZÓ}k–M'÷bî^þÞ’{™’{ðž»±p·\å3L‚oMÀŽ =iNCÌÉôHÁ ƒÐ7÷ÙåKXvÆdõŠ€`JÎðnZï3mô–š6À{=¼“Ë’z$˜éa˘žEœð’±Ö¤aðYœ† gÊMÂ"¼ôùÞE¬ra§ßhºÜ±ÜA„Žò*¯Ð‘›ï}Ï/¶á6o¦©Õë3ù±QX×€Ê[@0ÜÍpŸöâ‹ÞË^2çÅ©eº-Öôpeš‚Á‡6™4.Í€f†ÕhšvÍ¤æ¨æ¢fY#sb¼á'R±/âc Ý]6[ë¢l¹³5"÷oˆàý‘Ü.ú:ÖG¤û#¨gý†ÞŒôí=|5f¶Fʺz#ƒ™}­‘ æà2RQcßLx&> endobj 63 0 obj <> stream xœ]’Mnƒ0F÷œÂËt FBH ‹þ¨´ ö"c²àöõÌÐVêôl3zò8,ësmú9|u£j`]o´ƒi¼;â ·Þ2ºW󺢿Z„¾¶Y¦†Útcžá›?›f·ˆÍQWx§Áõæ&6eã×ÍÝÚ/ÀÌ" ŠBhè|Ÿ§Ö>·„Tµ­µ?îçeëKþï‹ÓZ²Š5L¶UàZsƒ ¢BäUU`ô¿³8á’k§>[ç£ÒG£hw)<ÇÄq„¼#NwÈ s‰¼çL…œ'gäŒ9A~ä|Š| Ψç‘÷%ò‰ù„\rOr8s~|a¦žçžeÄûè&Ù?EÉþiŒ¼úcO¹úcOÉþeØ?ÍÙ?Cg¹úéכ«ÄYÿŒH¨»s~<ô h.8‘Þ€ø}4v´XFß7C£™ endstream endobj 64 0 obj <> endobj 65 0 obj <> stream xœí{ xTÕµð>g3™œ<˜™dÂ#$9IŒ!0$i"`ÊL’IIL[l&ó ÉÌ83!"Ò`½€¨-¶j|T‘k}"×"RM¬Vêã"m­Òïö×Öªx¹þM)·—öZ„Ã]{Ÿ3™Iˆ€ûýÿ 3³ÏÞk¯÷Z{íeŒ†{¼$•¬#@¬înWÈZri!ä B8“{UT®žÐùsÿ?Š/´¼»··ÂCà3yby×j߉§¾³áVBRnêôº<÷Ö}÷2q}f'NT($|nÄç‹:»£×^•<±ŸCøÜÒt»ÈäÊÆçñyj·ëÚÐøFŸ‡ðY¸º½={Âó 1¦2çýP0½ŠÜp’…Gèz(ì ùŽ¿#¤É@ˆØ‰s¾é á9}æAuIúd)%5-}œÁhÊ ÿO½¸d€ìÃ÷Kd¹{Ÿ|8} Îlåw’õ¤g^æöq›øé8÷9BÞBÈdl7ŸTâ,!¿yr”s’]ˆ£ŠË䪒tš„]B«0 ö“YBDØ/´ ®‹à§ ~Á›Èë$ pï‘y>†JØ-Ô éä=ØÛÈGHí46“‡Èä%“ ’>~ ߊ3¯Šûɽøâú~n ÷r÷w#9@îŸG¶pP®}äïäFpò}è—•¼ùqíÇý÷’ˆ@ÄœD~Î!÷H«ƒ}çÀtñ{!}HÙIÒ è2“ ‘ ÕØ#ÜËÜîv²•¼ß‚kàn½P(<&Ì#›U @;ÙŒ¸ï¥{t>n5ÊNßk(v¾Whç¶‘…ö¤Äý *ÒÜÅ·¢D>²?½:Ê4›[›SºšCö'ÍÊp?bHZ‹R„dŽÖ'ÉN2úÉfÄÄäÕÍÿŽ;ïÞG™7sßãÿNöC)!>á0êš`öòl’N€çˆE6ìà‹žÖ+®”_[š?Ý2êQ6$É;HËŽ´ÕòÀÉ“-W ÙâÒâäP¤ß!¾ºÅ÷§[´\)ï8a¯Ó°ÚÛëp®íJÒ'œÆy{[£DwˆEøÏѾCvwÊ7n.¬¾Ùà­žŽj#>¥_ð‰a6J"“¬©Â§D÷)§ûx”í}{èÄðöÐÛCåÆ|cQ¾1ß'ãÈ>þ‘ÒŸ”þÉ_úŒÿç0yt™$ƒ\bÉÒ9ÝÆtã@ê]ÇëISZ²>¥>Óp|¨â(",›3ttïÑ4¾ª|g»™ã–qÆBã%èÌ8¨4^ÎUVd žë¯¿sûà`ÍÓ=/½Â?tâ[ü–¶¼ðЉºÌ[¼ž¿ÐÌ3 ø«¸é^j˜.êÇÁãÄÈíÖo”RôÉ(€Þ`J§tçìÅUUH{è蜽CÆ*¤ý•v¾9ߘ™5›3\<ÃX8£ÒÈõrk”õ "{öxpãFq‹òóÍ'¶njº÷ßð훹Ëióä9e±ðúžL&—[³' ’ôÌAQ?~+·vçM) 㑾>‡ÊÍ7ÔU&É&!ëEÄÌ%oÐß$šçÄÁTîù ƒ¦Ô['g›y½YOð¦qöɨ´£C{&JâàÑ¡ƒ†Ãø>z'Ê­%ssB9[s~s$GœKærsù¹æ¹Ù¢%©L_–l‘‚$Èù 9˜¼ì´°9?U;s–9+”QÃõœTÊ¡†“„¾ã;S÷?»âÕ÷¯W*G•W¹’ãpIüÃ7Ý;˜Î_}Õ ¯^rÉ“S-Ü¥œÄepµÊï÷ÞµëÉ-T¦5(Ót”I"Ed·µxb^ÊøätòøxÝ`ºQÞ÷ÜäÁÂã­ãSÉx˜@ý?ô™ö‹Q¬7ÞFw02gÜ{ðèñ£C†WP6c•±ŠÊ(Ï)Ï-Ï+—ËóË æ[s¬¹Ö<«lÍ·´ä´ä¶äµÈ-ù--Å¡âõ9s7æm”7æ¯/¸­xkñ‘âÜØÖØ¦Ø†öÜö¼v¹=?”Ê É¡üu¹ëòÖÉëò',CýÄ<í2nº?* ãà’™•ù3˜&Í`ñÈ¿ðÞö‚÷  ÌÝ}Óö}'>åøGïjÆé}áªÿ:ÂWúÖtD~·«¤ñÄ Û|®—Üó¢©ï–ÒÒmÅÅÇ©/O~¯¢®ŠÉ!뜴T>=¥-/#4IjËËË­‘Rró3ÙÀm27˜7M4 ƒE¨¼)¹RJ^viÍÖ§'é3 ìS Ç÷b2:ˆ^PU¥y†AùÛaÃßÓlÂü0ýÏÆñUIì{iÁNRŒ1níž,MN™œZŠÎaI±¤ÎNž-ÍN™š"™»ˆŸ"MI™šQ–Yfžš5%wJ^‰\’QñiCÊ†Ô i& <¯“t) iãÀadÃd!'¹¸¬dnÉ·KúJÖ•ÜV²µäHÉ„eÝÎÌ ›ÇåræL*µxóCTkWÊQWdÁ-M]µiSÇs÷>üßÿvÕË]¾W\ß½Õû„õ‰»ÿøKß.aî“S¦8VG~úÔ{6Ý÷Laá 3f,½bAKѸ‹îüî–í¹¬à ùæ£~¤Üš©KI"Æؘ>¼;IÒ鉾ÞDõFãõµ÷í7híjÉx ƒGë«|g ¬ñ0?Ïa¹ïQÌ:Ï­Ï( »LÆ}/œØ)´?és‹"£‡ñ ‡ÞD2ךv»IHßv“Dí6í6)É”FæeÚ'ެЙé(5S¹5e\¶!{]ömÙ[³Eœ1=Å"´€Fh>jæPÓý-O¿òÊÓ-÷7-|xÙ å·ÜtN·èAaÆöiÓ>Ü¿ÿÃiÓ¶]tw9—Ι¸êBÆ×;øõ$Q0gŸÅdÇM$Œ8šèXš{‡&8š0w_…ü§)d¾µpbjN²iCFÖà8¼¸p xwòà¸=“r.žHô© :“I¶—PŸeA;IJ¸r€f£ªògÚ§®›ºu* 0 i{¼Ï6ùeŒ7LTÁ3°\{øÎ;~øŽ;P”c®íW\±¥õ§»ªv^ÿËãÇyýΪþ²×Þ}÷µWß}÷OÊÊÇ9¹O[¦îùÙ7Ý\5œÀUw¸·QyË0}ÂÎÝ¥ÖÉ¢KÕ?®ã6’»Òu»%>#‰$%‹ú´q)x.Ø!9¯D‰­—.]°#O¾xéRv4î5±tt°âøápŠ{Æjn1o5Ã2z.êr8zJÒÓ‘ú-ÿÉ÷B®LyspÇŽ'÷è2ïiéto>^onnzþ‰X=€úÍ 3GֻǮÆê]íæ_™ùÑù3*tMZ¨çL³ëx´k†nÐDSL·NH6»Lfûv¬h‰ÎX8wâ²F×—Ô§ïKî“úRÖ¤ö¥õ¥÷ë3ôט¶N<2ј!1t‹éMT/å#wlâÎÛ·o¿ýgRùOå/œÞ;ôúë‡þãµW?¾OyMRþŒ‡Jž™Ü¥ÌG/CÝô íDG>µƒQÞÈñ"ý^Gtœ‘] äg¢NÄ2RH’ámÍ|D5_¦sÁ³ó›t‚ÚpïxVÙTTÅOb½öa'²õûóøXà÷ñøuüø‡x=%” ɘuÍÜ$˜$\L.æJ Dõ3È ®ª…r}=©çàêÅy:«~1YÌ-…¥B‹ÞG|œüÂr±S×®ï!Qn ¬zÄëtëÉznl6‰tý¤Ÿ»‹¿îîïÒ=&>ªÛ¡Qÿžþ¤þrL•É´P¸ìeîjîê—•oÚ;aû§[Y½€~-ÌG¿6c†iµ³ëÉx}Ö¸LA¯‡,I×8‰VtÔq Ê´¦Õ¤ÇÂϰ1} YO¥ß•Lv‹\Ùœ¯8¬Ð¢áp&“˜nnôc`I*îͳ5ç0Aó•$têyzzø?…öO·Â›ªo?ûêèÜÎ)/¡1W#´¾š†õÕ ÂSd7ÖWzÔ×W!qC²5¹%¹=9”ŒÄ3*™K¾4€/Š]—ù1«·ï¼îž–»W|{Üœ¿‘<=»KþjÓ£ÏÆo–´âÔÑ{¾>~ÙÄ{K·’“xýuÍÄ›¢O4áM°Ì3Ésx=‚" ‘k„Cd0 ï<óÉs‚\ÃßBÞA˜kø7IÝ#|„0»Ée¢DÊø*ò®ÓW¹oLC\*WÁÝÇWðàièƒëàÂTÁ' ˆóÅûĽâ^›L¼!ñD­ äʽ`æ³ð—ÞC'aAãùîaþ9Œá»µ1p?ÖÆ€ójcÇ;µ±HRÉm¬Ãšìum¬Ç3ñ-mœ‚÷½ƒÚ8Ít?ë\¤“K2¶hcIÉø66!ã÷H‘’‘¡òŒ÷µ1G²ÌFm̽¹XΗicÇvm,’ æojcÉ4G´±ž˜7jãRm~\§U›?ÔÆé¤svŽ66¬Ùëµ±‘ègÿ¨6Zö/ïŒÊSÜ%rEyy¥Ü±Z®ñG#Ѱ×Õm‘w©lëê’[)TDnõF¼áU^O©tÊÖ™t«Óµª{E0°\®qužfcw…kq^#]åÞˆì {e@õttùݲ'Øíòb0m®@¤&\™ð˜0\ì GüÁ€\QZY©N'ø‚¤E!:£ÑPuY™çWõ”F‚=a·× /÷–¼ÑzFy R .O‰x½r‡·+Ø[R*ŸÇ¥rC×êPgDöw‡‚á¨×#ûÂÁnÙö®ÒX‰Ñ`êQ5”HF’âÔQ2—¬²6¬fiú_Ò©9k[Ê£(û#’Kކ]o·+¼RúFc‘¤o¸Ûaê÷GäNoØ‹´–‡]Ý‚²£X¸ 5†z¶ÈÑ ì ¬–Ch0Ü숢Æü¨—ìF¦%„Œvzczr»ƒÝ!§ÑNÄŽZö"¨½¦’‚Dæ‘]‘HÐíw!=Ét÷t{QW”òãów¡‘¦PŒlƒÜôE{Qý%Œ“°7zzÜ^†ÆãGÁü=Q/åA±Á‚fvwõx('½þhg°'ŠÌtû5B”BXU%¢í‰ <Ç"w{©ÔsH§%†…Ò, †åˆí€Ð~dUiÊ¢ QEG%UuŒPo':Ö)¨|=áô²ž  ZäHOÇ ¯;Jg¨|¾`:È xüTŽHµ$9«#¸ÊË$P½ˆ10ì`ÍQg©UBqP×äH§««KêðjZC60J\#ä Ð/Ârw0ìSl9º:äõ¹P©ÊÔÈÕn×jŒÜîñûüÔÑ\]Qt= R—ÇÃ$WUGÔF¾zº\a‰òx#þ寯r5VqõP—‘DèŽ?‘Ñ”(J 0…¹ºÆF í‰ñdžìºVËþ7—¨8a/í–3X:ˆPER»ÄÂË>ç ³M½Á°'" Ça¥[ hØ0•¡eµxéðb$Q¬=hª“UAÿ0cÞk£1²+Âðrutyé‚*;b¦)n”NWTîtE£70B'ÔëâÞí‘{á8«cN•ðLV»hT3³Q#¹ä.š=0Vb€!—{¥k9 †qJÔU?ŸS … Yôvù(Sóìr}s“Snk®w.±µÚeG›ÜÒÚ¼ØQg¯“ lmø\`‘—8œóš9e„hµ59—ÊÍõ²­i©¼ÀÑTg‘íW¶´ÚÛÚ¤æVÙ±°¥ÑaÇ9GSmã¢:GSƒ\ƒûššr£c¡Ã‰HÍl«†Êao£ÈÚ[kçᣭÆÑèp.µHõgâDæZe›Übku:j5ÚZå–E­-ÍmvÄQ‡h›Mõ­HžЎB ¢Úæ–¥­Ž†yN nrâ¤Er¶Úêì m­ ,2"kF‘[eRŠ\"Ù¾˜nn›gkl”kÎ6g«Ý¶ÂRí445/´KõÍ‹šêlNGs“\cGQl5v•7¥¶ÑæXh‘ël m Tœ ¦ŠW‡D74؛쭶F‹ÜÖb¯uÐêÑÑj¯u2HÔ=j¢‘±[ÛÜÔf¿bN \Œ„EZ2ÏÎH 6üWË8câ7¡¸³¹Õ9ÌÊG›Ý"ÛZmÔ"õ­ÍÈ.µgs=ó€E¨Oj¼&_j#:wªw Ý­ Xg·5"Â6ÊNH#`Ñ»ì׺½¡(õm-¸ÕÔÈÒ¨š;-ÌkÕ$€.ÜÀÀUçØ%Œ,vê¨Ù-~`ÓãØ¢¦^–>лñ$RS¯g•3`„¦’`X ÒdÒë°HÇ#°;¨žyrÄÕ…Äp"…¹ÒÕ…Û"ÃlŽ()v†Â~ÜÒöG1™È®œ û¯ÓŽá°vL1 且J<9¨ü‡½‘žRþUÞ®Õ¥¦gãÄÀZ­[©Ï­Ž• Qy9Cî F%¬èJeIb×y—Ng[Ë^˜:HRë ù\ê )^ÉçXI§ÖAZ’w3L‘Ø™1F/X¤ó©•äX­$}=j%IµÃV+IjÀžW­$]ÀZIŠ×Jò9ÖJÒˆºàj%étµ’|öµ’”P+%†ïˆr ÏsLª\’´rI>¯rIÁ.»7^è’I åó.™¤ Z2IZÉ$Ÿ{É$.™äs)™¤1K&ùó”L’Ó¶xáüfʶmÞ9UGR\ò󩎤Xu$ŸOu$%VGò9UGÒ˜Õ‘|>ÕuÖ2\øH§-|äÏQøHg.|ä³(|$VøŒ¬>» ‰Æà­¬hJñ§ôŒ«²^ÿJ™3ȵ¥¡ÎP™–ÆFuÎH- ’YMÂÄO–“N%2™Bܤ+H9¾+qÔ2©A˜(‰à'L¼ÄEº‰g$€ð¥8²‘.|ˤuW„=yñ׋{Vá·!¥³ :s˜ª)­BZôOfMùpážÏG±G+pßbÒƒn„u1l^¶ÃÅ$’K¿CÓxý'ãþ Rw±µÑxÚ–rÄ÷ÊÓ¬Ž=»˜qA¼AFµù¬Äw"ôØ|l‡*kT³•=ŠœW“2|{4øU_ŠpAü £4^¶7Ìä.E^ÜSŸ€-¦‡˜-Nµ8]£ºõ2ûxQKAÒ‹°ÔFÇS®¬F˜N¶Ók!Æw”Ù“j ÌvP XWÒÊh9â>Ô3‡N'„ï±dWmæÂQ¢ÖNõf‰L?·tVráãrl{ÇeöãŠÄFQ6C½¬›éz%ÎÑŸÅ •¬…áëfØâÞïgâ\U)År¨‹yê»1£õùL™b\Jšqs1=#éŒÖÇX¼Y4{w±}þÓdsiØ:a–g],¯ÄñÆf"Ë—ѧ‡WËs^&EŒR/“ÊÃöŒq Ë=z‡„k±Ó¶ ÁËÔ˜iu¾t°x&ðÚ£ÅAÌOV᪠yɵLÏ-’CøVO/˨Þá‰vWyŽÍHcFJ'Ëð2ûh9ɬ#[Ùšçd¬ãZqe1>Õál³‹­ÐõKpL16“E —Š£¿)î¥8CqËì™>-@ø&ÄE÷ÚÉ•Œ†±µ!gÍ8¦¸âl#þÚ58º£gá37Z…ªôšp—“ÅÝGyQ9uâ|œêH®ŒbŒ³…øÔŠøçi«6Äí`ø(ÿVÑq“Ƨª¹V†êˆb¦8k‘£FöDgáo µ1}Ú˜Ì*·ML†z\We±3TK¨Õâo Ò¦ È—“iRrjfG*OÛO©.`P*gÍš•é8Ž¥TÓ¥ÊÕÿâaÊmLþF|ËL~'Î8™mlˆ?†7æ; å[bÚXÄä³1=43 5 Žj‘ê³qØãZ¬RËôEíF9¯c”lL#mcJÖh±¼C¦ÐÀä³3M52è6Ô£áÃ3ª?:˜¬µš®Uœªß«>ј ÝZ&#µìHÕ®ù”én¤ÔNKÿq)T Ø´ïÚŭߤY7Æ“QvŽ¡•%,í ÊÆlÝ6#õ,~jœ/ö°xX¤ùgó0g#õ‹£ÜÙäWŒöH Ö1jÔ8lÖ† !¯š»ìx®¹Ù=':œ·GžÜ‰Uc¼M¬;- ¹6±P³pƒíŸUoKꙿë$Öncݰc·cµ–U½ñêCÍÝê(±êõ°ú\­#ÃUIÕÁáʤ—­ÆÏôÖ; ޏçQÊ.vö[†iÅ΢8.µ®t±jR‹Œ¡ÍÓŸPÒ)7Ã;ïU*½lÕ**_Kç¯uŽõNµ<¦ b²ŒU9$ê?ÌìÒîR~¦aZO–jxÃ$v/‹ë„j@í«u²zÜû(¶j2º«@u°ü Lüð|Pï+ðGÞ«€?dÂïûá]Þ1ÁÿY ¿{þMß"øo×·Äkáíxë7Ùâ[ ü&ÞTà× üJ_*°¿ÞØ—+¾¡À¾\ø× x]WÖÅW&Ã/²`¯/+ðs^RàE~¦À ìQ`·Ï+ðœ7‰ƒ <û¼8 À³Ï,Ÿ}ž]'<óÓ"ñ™eÖ“ðŒUøiìRàé~Ø©ÀS ìPà' <éI‡íO‰Û=ðÄ6“øDl3ÁãÈôãÇà1Uà6ÁC üøÁtñÇð`:ü³¶"ÈÖ~x@-÷§Š[¸?îûÑDñ>üè^ƒø£‰p¯î‘ànîêOïR ? îÄMwö÷§‹wLÛÓá‡Çà·=/þ@Û6/o{n['lþ~‘¸yl¶ ß/‚ï)pë-¥â­ ÜR 7£˜7Û`ÓM)â¦L¸)6âÄFl@Mm(‚õFø'nü®Q¼QïáÖ)Ч€õäwÖ®¿£ÀÚµp½Ö8Íâš"¸NÕ \›½©°J‚¢Ç r ÂÇàšcR ¨@@®|X©À c¸¢ ü t®…åøàSÀ«€G· ¸ª¡ý\ Ëø¦W)°ôJI\z ®”`IÖDqI,V`R^TN3´q±m´fÂó3Ä+hIfšÄ& Q¸²@ùƒ8?9i¢ÃóÒ Aú~°÷Cµüt±öÔ<¶`U`®—_f/Ï„ËæŒ/3ÁœÙiâëÉq0; ª¨RàÒY™â¥Ç`ÖLƒ8+fÎHg`F \’ •iPñ±Bo¤@yYŠXže)P:=Y,5Àôd°TÀ´©Eâ4L-1‰S‹ ÄSŠ‹Ä)6(.‚‹‹RÄ‹ÇAQ \¤@¡ã åÌ7ì¼c‹"äz ' &£'+} &ÕÀD|˜¨ÀŒGMW 7eM³™ d(`B“F”ÕX†µ0Îé ¤¥f‰i ¤"tj¤(  Y=‚éHÊ\ÐÌ€³ Ïütà @à8ÏúïqÓþ7¼ÈWÍÀ_9ÿ¬ÀA endstream endobj 66 0 obj 8297 endobj 67 0 obj <> endobj 68 0 obj <> stream xœ]‘ÏnÂ0 ÆïyŠÙ5)P@ª*1 Rû£u{€’¸,ÒšFi8ôíÇl“vHõsìÏ?gÇæÔX²W?ªïÕ¦ñæð \e2çÚ¨pÒW cYÔ¶ó`hl?–%ËÞbn ~拃/ðÀ²¯Á{å‹cãöæÜ `¬ª¸†>öyêÜs7@–TËFÇ´ ó2Jþ Þg> endobj 70 0 obj <> stream xœí| \TUþø9÷Ü;èE03õ âsÑÔ,y ‚"è0¾z2Ì 0 3³3Hf¶kjf>*Ãõ‘š«è¢™µ†V®µYi™ÕÖÚÚV[jf®®µýÓ-dŽ¿ï9÷ÎD3µÇ~>®Ãœ{Î÷|ßßïùž¯–×]iCíÐýˆ ‘– ³kAéÄ „Ð[áhK•Wv]Ù+0þ >´ÄUZQ]bEˆÀ;Ú\Z^SÒ¶À;!ña„¢×—ÙÌÖbÃS©uëƒËØu„Á{¼÷,«ðN¿·Çâpxx|]¹ÓbÞ¹²þq„®[ë‹*ÌÓ]ûÐ,¡Îƒà]q˜+lן=ÙÞM°¹œïmè·çš¸‹­»Ü6WÉ×â‡ðþ1B£áa?í`¨cï%]X›¶rx»ö"£¢;ÆÄÆuº®óõ]nèÚ­»Ò#>¡gb¯Þ}úö믔<ðÆ”ÔAiƒ‡Ü4tØð›GÜrëÈôŒÌ,úþÁih'ÚÏ_P=Z…ëà­¦3k…gÑT 3{ð~<_suèkô>@ÎCûI½ˆðh” ³}( è[lBÛÇPƒ‡†éD$æ‹ÛE£¸S<.@CDx@,=8•¬“&JuðJ^¢Ñ¨;Ú‰?Eô9ARÉ.1KŒ@Ÿ’¤*`o ±­G3€—ìD³„‚föJÐ xœ°~¯Æïw/àÙè ú=…´¹ö£³h61 ³À/S…à/à:ûW ˆ¤ƒXFTèsÀ=Ð*æ¿»’ÒAþ|feZ¯Û©‹ K*Lcux>¥{ ­Eï“;ÈoÈGxŽ˜ nsÐbU¤-Ü+Ø] ®ÙÙ3ƒaªÅ"\NˆEaÅ€û5&ÐÜ.A¢´ >ÕºHi8žCæ§lµ+:6ZL†ý€!l&H“¤¡©0š¶¢gÑR‹&.¯nˆtv®ƒÌ‹ñBá,:@²P_T"ž]£„jÚ¦“D"`¤W"· ‰¹Öm#ÇOVöMé1@ßâU‰ S¶¡qÛÚ×(;ÏŸ7Yì"MÙ&ݰ$¶Ù&&&¾Øâáú1ã&+Û|†, «¡( æ 'ýÁ4̲ø#ºMJ„?¹EÛK™òPäC Ê´ jC·ÓZrVZÙ²FǨQ‰=¢zÜA–7½-¼åDkÃ"¾ûÆ­ëˬ‰È ÒAÔ {Ä|ž#¢ïY!Öw²A:XOsê}C8¬rÔª,Ð4Ü£LìÞô4)9·ƒŒozU:¸âœ³~…øb|Dü?^@2l'=p*N =H‚Põ_ü}òýy†oÝ=/K¾Îdkc<‹þÖÏÓ÷°O:©Œ£ç„EM»¤ƒëÙzéù£"ëŠPbT´Q8AAQ‘¨GJ\§Ø$œ/DEF§¦ séßñ'vº„¾FŸÀ<|ö¿­¶£3Ï~÷ÝYó²ƒø‘:߬ x9®À¼<'ûïwÑ·é_é{ôíDÆ?Б²€N8êd5¤ÑQ‘Bo•ÿ-|ðú‰¯¿þå—¯ã.ØH·Òcð<… ¥<ºF_Ð8_k9ëéít5]CoÇëq1< U| díˆnÝp§Ž $ ÷ÇQ Q MlŒG iƒz%”᎛žuKÆÌò×ðŠãG*}û>`îÜ„]qKî£exVm±o¾tðƒC _ |§çÍž=‡'/ô ©Çc€À‹G/—úB0«ºÆÓÔ5ÐuÂs `òÆþê>¦çõ gx UëØ…‹¸ãÝÊ/Μù¢òÝ;îþ  ¸ß…S¦ ¼û.º—¢Ò½wÝý~N^ƒKq^3J¥+vºá!~Ç,MÆûlÂý¾û…-M«™óe×ûŽÖ#|þ4íJ¶Ð-\ð;²¥)ƒnY¼˜óù&øËIÀ^6¤G””–ÈæîKwáŒÜ·©±^ôäìÌáîð«é7ÂͺhÔžoBlLt§„^BÚ è!ÂÍ5•UÓ—<8wè/è-ÇÓáÇNâ×?û¿z qŸ¶?JNêbP$·W¨,-" ™8§Y+^G uuƒÖ¸v;¶Ãµ†¢ÚÙ,[öÀìZÒ Üõý©MV3ÎÂmàÉ2ÓØýÇ_lù/uá’vÃ~…Ç3…ƒÿ…1KèÂÄv>]øóë‹þ4yÊ‹EßÐã8üèþ× KïY°±p×m»÷´µŸß„eÜgÒO^]¶}ëjÕ®ý€Ð¡#£¸ºbõ JjÚ Á©Â–Õ·pýªnÍšUõº˜åãÊ,‹›’É_翸™ñèìe”ÈâBË¥‡hÊèX†cU ai·€qÂô7Vz­ÕÕÕÝôÇ+Žù²öÁ‰ëónß<þ£CBjÉŒbχÛûæù~[_bþ˺?¿=kARR}ïÞM\ç«€Þ  ×‘¥ãŽ sUËå÷ÂOlp9ç­¬«»yÍÔ§¶ãµø¡Îg^³f÷zaƹµ[J,_“M ÷SÀ­ äÖ|}ë† º˜ïO©:¹m”VspgŒ‰ΔÓ+©% ñº9³tóæ—­©‘VÓWûÖÎÏ_±æ=¡h1¾EÅñøÕª_uL‹ŽÂG§ –.™7wî¼%ÕUUºèSôæO?£ÃNï?Ž_ñç€Îà¿mTêš%ªñÏRžöù¬ fѼâÈñãG>o’}ï<:oî£uG?úäˆÉ6bàˆUðÊD–˜£!·47à Ó ¸X¸§is).Išd¨­™°»ÜñRÁ_¿»ÅØé?õõõÕø‘aËr«k32ߺ1åËWîØàêJOrÙnß #…Ù\w€ÿ6|Œvf¯çöÙ>›z ç1Áiª.a–0A½c¢RÉo! jk! |­qîeHߟ’føC 9!1¦FÌ"mñèÜZ]Ì ¿\<ž[Èûrr¸XZž$€C;›5‡öÖŽedaМ•+æÎY±bΡÿþ÷ЇgÎO¿ñÆñ/÷í=±Šî£§è¿é^¨C;B%zðÅrû€³s¨Ÿ´H¿qdvöœuÏ>».ga¶áñÂÏé·¸ÃɱŠi[ú÷?zàÀÑþýë{öÇÀÑxX‚Ê+HNr^û4Njd¨þ7‡$ÒR‰áñ¹s–.3÷ñºc§&­ÌÍ]4úëR׺^8rä×ÚÔ:aľ?Þ·÷ãOÒ#ôD×nÒ÷ûóK·[Šñ0L°ˆ‡[êv?–À±\ªf–®% "«^¹®Ž%ÿ½uuÌ\~ËîxšøÙÈï—:Oñ𢦖P+^`ÎÝ·n©\½ycÉÔûkëJ§Íz|ãÆ¡«++Èü{«ÎaÆ}r3®°zÝÊ—þÀ\Z|/Ï+÷I@‡Ÿµ‰ŒZBi–hò!ŽüùŸ÷'™M¾­:¹>$£à“£V«A´Jvž0õ@µ¹´¡ÁWK¾U‚µ±¿°×7Tƒ—f|;–Ûb¦Iœ:}wÀ“ðdÜạnØ&ljC¾kì/uoB"j<ÌöÖ€¿ê!?·’ƒÄ‹å ”îœðø“Ój+Þú =ç+ú»Çù·Ò•õ÷,p¼õܹï~UZÿÚÁ÷WYlÝ;÷ÿ°áÃÏ&¿kÈ~ð>ǽݯðòæ×?ïå—q«V³§òz…1|F0m;ãÛœžë.nì/>×iyþ)Ôò¼ð…ïz¡f ÒÎ)©;?§¢ø9¥–€‰jÜãiá8L¨þ‹:q%ž‡+è#t] %Ÿ«Æ×\zÜ©Ž.£÷Óûh-ÐZ :Ùø¢¸þ‡z$bÁ¶vÇO?½jm¢çih´òë÷ßÿš,hºƒ~L?ÀýpOÎïùF¯p@¶!Z*“DMh  P>6”´ZvøìQÍvìàhË.#mqˆPœ_ÿÔç×ï¤O³Úýðç •hñ4û€ #¿fûÇ‚ìËà âû»`ö'„ㄱuï¼½ç·ëèw{>üDZ¨©–LežÚ¦©*íEç£q-¢ì>3$5–$t<´{©w4ÝB_Æ#ÙzȸÁÛ Œ)Îù–>†gí¡ÑìÁÒå¯âp.ù>õýï¤9Âh!Žþ/æø’oA¶®Z-Í‚ÅÆ f~Å ½Â›¾ûô9ŒÃè7g'<}×ø§ŠV54¬Ê}d «µíОþ×èEÙãÀ†U«zöbvg¾Û¥Õ{Ph®ýð¢E/„Ÿ#§O4Ž oÁç¨*©k©‡Î¥ó¨/Ä5ø¼Ý±èwÚ«ksÜ]pBïÀ5ƒý7­¡_}´·[÷ê= ,÷®]^·ß¡Ÿ|%x6³Ë¿|5ÑE /ÿ½T‡PÕ„¾ó»q=Þüg°ÒÁsÄþ;Ð`€eµ‡Nóœ0D-3èÜÃ`mÙrn-ÓÑ\$e“uÚ¹V`Ïñwçîc²nÓ×õ<†n|IüN U"ä’ÊHæ¶iÂó4 ïx쥗žó=)%6%šR7ѵ¸hz÷à~$& ͬ R½i7ó'1ú>Ô|*ôÌa5Yȵ¤Å)Ãòÿj" ÜWÕÕj2ßÖËŠµþû³L/o5 —f½€í{Tp4ý]pú6‰E›š>zlIôß9´sᵇz x¹¼y°Ú™·àá9B ½Åéþ«îåg毋Qöÿ~ß?Tž¥ÎÀsÏ÷¤Gh ¦’:¯n^-=ᯤB.Q~aüu”–£?SﯙGò$Ý Üþ/¸ ¿ù•o;Šæ Õ¾œ¦£Â;¾Õ3Xì¼5ß³q#>ý7ß aÀ!Š6êbšìø¨ï[ß!Á÷ øÄ @#Äa%‚ÿtL¶oÅ^:€—„EàX\´cÇ3[RÇOMª2zrò„­wÔ½‘>¾ B˜¤£?²Âö»‰SÒîºqŠ#;s×Л^Y“7âÄä´Î±7Rãç5ø5rá¹/áµÝ»)E¼¿,˜î9ñL扻;Ü|uoÃû¬ïÌ߸Óßse7~ÝQPAm‚X„Â*h×ÐÖl‹Vm¶hD·‹=Ñvñ42ЧP„ç–´•JõðAh;nDÏÝa. •Š£ídùùÓâRô¦ ,½ƒV‹"›è@6áAÔO´#‡¸­zJxÝ뉓÷R4OXŽnØbL^Fá Œ—€ÖÏ¢~ žÅRd#gÃ9õ #0{¤©h»n0àyÕHÅŒt›´x2 µ¢íü¹°nh„tžþ4 ·>5L.ÐÔµA{`î6¡Ö?Ù‹  ñkÀ{¾wÂw´‘¼‡<`‡ô( !Z>€hŽÃ=á^;OÇKàÙŠÿ)D …2áaa…°K8$4’~ä&RF$¯’ÏEx‹8Nt‹«Ä}’N(Y¥¥ÒéMN×M§×™tUº‡tõº}ºCºïÂú„M [VöBØÛa§ÚmRÚŒnãh³¾Í¡6ß´m×6»­Q³\6êË<ƒg·H´œYZ„ ߬Ÿ}=\¬ýöý}ÀÖrÈïµ±pOicóÏhcƯkc Îì´±îǵ1Ë ÚN®ÛG?ûhã4¨ãkÚ8…wü^G¡¶1"PÄ"ä?<0¦½6†œ;B ¨Ml©6&0ïÔÆ"Œ—kc ]»GëP¯Ø´q‡µq8— Û'‹»SG ²áË´q$Š~^G¡è›c3®·½´Ì«ô±ôURLUŠk” »×ãuÛÌz%×aIRÒËË#ƒò(F›Ç殲Y“ä ¶f[M檊©NG©’a.»ÈÆ,ÛTóÄJÅRfv”Ú<ŠÙmSìÅUY\n·(Vg…ÙîðÚ%Óé°Ú›5ÃéœÖêB«“mnÝéPR’RSU¶ÞrO‰ÓÌyAÖ2¯×5,9Ù óU•Ig¥Ûb+qºKmI›7›ƒ1V™°ý(}<6›Rl+wV÷MR.C°$eTy«Ì£Ø+\N·×fUJÜÎ %Ým«ÒXñÓàŠ¬TJF–ƒÔAD³¢²°†<à’?ò…v»l“+-(Û=²YñºÍV[…Ù=Mq–´Ä"Ëãlî »‡ÛÁîQÊlnÐ*u› ºd±`h ô¬W¼NÅì¨Q\`9Øà,ö‚Æì ³b¦e€ô–Ùüz²Xœ.gÞ2ÀZf–UúÄs•Ä÷dVÅìñ8-v3Г­NKe…Íá5{?%ör0R†‘oP %ÞjP|_Î‰Ûær;­•Gcµƒ`öâJ¯ñ 7Û 3[Ê+­Œ“j»·ÌYéf*ì!FÁ­ªÐVzž‰£W*lLj™;ˆ§LBCÏh&;ÝŠÇvh;°ª‰ß‚4cк˜¢½²ª:N¨º ë‚ Ì %•n´ñV§âqêOeñT›ÅËf˜|%Îrp6&ÆÎäð “e 3;«l\Õ‹8'p8½`:ˬâ z€º¦xÊÌåår±MÓ°Qbn&§Ó~áV*œn[«b+Þ—­Ä „’T¦š¯V˜k Z`»Õ^bgŽf.÷‚ëÁš­V.¹ª: f7ðUYnvËŒÕæ±—:8¥j¬Â&æ¡f ñ°~~<-)1”2à 3—·Ž@Ûãç#ˆ Øs”×(ö7—™8nûËy˦HfxØÀçln¾©Úé¶z”ø@Æ3Úþ9ž…m6}ÇO„©âÕ!³ £ ùczž^)gÈÌeÐc®Ñiâ {ÐDg7³ ¿Ð0~LœŸ„^ž”cà$@€tø“É9ãâ烸 ©Àh °2)·Ð WÒ¹…Ì"ÙÆ`—Ù³ ›{ÀÐ'3^¾Æ/³›»Ð;ŠíÖÌ2¤çÂBÆLÈÍ`Á» Ó-6——ù¶ÜjjäiTÍzîµjå€ÀUçøŽ%ˆ,~ê¨Ù-x`³ãX¯¦^ž>À»á$RS¯µÊÐÃR‰Ó-;Y2©¶{x¤ÃXáTÏ<Åc.b°‹E‡‚\i.‡mž›ÍJö†.·¶T»í^H&йfÝö{´cØ­S\%(£L*ÿn›Ç§”½ÊV^“°nv–qNì¨Õ*4ѹú,ÞaþRÁ«”räV§W†Š.I‘e^q]uét¹%ﵩƒdµR®¤’ƒur…u|a¤%y ÇäñŸ­¨Á‚E¾šZIñ×Jò¯£V’U;üdµ’¬ìUÕJò5¬•ä`­¤\a­$7« ® V’/V+)—_+É!µRhø6+—à<‡$q­Ê%Y+—”«*—äfìò{ãµ.™d‡S¹ê’I¾¦%“¬•LÊ•—LrË’I¹’’InµdR~LÉ$›Ò'Ž]ÀØNϹ¢êHJ~5Ց쯎”«©ŽäÐêH¹¢êHnµ:R®¦:bÎÚ,P…|ÑÂGù…|éÂG¹ŒÂGæ…OóÚᇠ¯~$/ä$øJºdç*¹Ú>Ížl‡ 2=ÉUæJÖÒXHË,ÐC™È‰\¨¹‘•¢2äE êƒ,¨/|§ ð¤Â¨ ”0^äÙU =Ìæ"À'Á(•ã c—‡¿ÙàÛ{ªà· åË :8@Õ”ª€ûgº€f|˜aÏ£˜£©°o"ª Àš96ßaæ)€Å¿]S xí§À~'P7óµ–x 9†!“sg…U§m.ðLû;.r"—Î<99Ç) c*<¡üûˆN _W5çÕìÊ4é= CÉðX5ø*€O8'|»A76¾×͵˜8l°';›_«~Ë^è?lñdãֶΨ`™m¯Å¦Q°R0e|§Ö\œo/×Ó€›ï`þİVµÐJK9‚YÙÌ#/& Ok²«V4Ã(TkƆŒ\Å#_V¼]û(oÝÞA™í°"ó‘—Ï0/«àºžsN°ÀñÂ$ÇñUplÁx°sžÊøšM“«”SqhV×kvW­¥RS}Lõg=çËÉ­ïàû]ZÌ©œ€Õ«ù˜]ó3Ç¡jZÖpz9-ýÉÂᘪØý´Ê»êËþ˜eÖŠñ’xn93köíá|Y`Y“OæQ`­àX¼|ůŸ•k‘Ô'ÀcË>Œ/ø¯êýŒbP'lÆÅ£Æ ,|·Ÿ+—ÀË}­V½|U¥!_‚‚^‹f pVɱ¨:©æ>PƳŽWÓLŸ •È/ƒ»™WªÜVrêC¬ÃÆÜžª­å âÝú‹È¡È™Ì3ˆÂ1«ñ â¶kZmnýKKíלʭ+àÑ^ÎWÐë‚Us}T\4”ð¬íÐ$´…P´òߌ†ž3ML Ç§ÂøíÇü¸\Ël~ Y´Æ°‡N&;3`tòÌ´Ah. jàÂLàx¯ žf°þX j,4„îS¸ÌfιÌsss_Sµ¡ž%æKØÓÉO9E³}ÿæË±…—ŸDìä4k%5ÓÔ¥ö2Ôhg‹J鼄óhÕ<©œû©;0£rÊtj ±y¨×ùOP3?íì2ñØaû/*§&˜RmÎU.§èçl,¼޶š¸s9>Æ¿ž×Glœ¯ñ©jÎȱ31Ì g&p”Çߨìøp…\Ÿé\f•Û|.C6¬«²8ª%TŽ2á{Ðf£€/×£dÒ õÜŽLž,¾ŸQáTÎ 4+³qK’¦K•¦ÿ‰Ê…\þ—ê;\‹÷ü#Q°Ó s:ì-é*þÍU2×Ë4ø$sÞ¬¼jJâõ« æšWc­ÿ+³ ÿ•ÿï¦ÕÿÞþ>öÿ¦¸ðg§pÿÈóç(iŒ!ß'’ïRÈkÉÙr†’o)ù‰ä›òŸZòu"ùê¡té+JN×’×’Säd#ù%'†‘/3ÈqJ¾H!Ç>/”ŽÕ’ÏðóBrôH²t´‘I&‡)ùŒ’OSÈ?cÈ'µäcJ>Š&ÿ˜I>|‘¢äÿ`&9ø·QÒÁ™äo£Èûïu‘Þ§ä½.䯔¼KÉ;”¼MÉZòÖþnÒ[”ìïFÞL!oPòúœ(éõÈkqäUJöPò %¡äeJ^¢d7%¦d%/RòBy~n¢ô<%;w¼(í¤dGÃÒŽÉŽûņ祆;Gž' #ÅçÉvJþTKž¥äJ¶Qò4%[­ä©²es¢´ÅJ6×GK›I}4ù#0ýÇF²‰’”ÔQ²!š¬§äë"¤?¤uäI+Y kkÉJV?ÑNZMÉíȪ•¥UV²rE¤´²3YI–Ëä÷”,«m/-£¤¶=y6=^K–>!-íC‹ 6’G–¼(=BÉ’ÅwJK^$Kî/J”ßI%’…”<¼ Iz˜’Iä!ó¡t2ÿÁpi~ y0œÌƒ‰yV2457‘̉"P2ûwQÒlJ~E~KÉý”Ì¢däùûfΔî£dæLr¯•Ì0ÅJ3É=”ÔP2=‚T·#U2©¤ÄÛH<ÄÝH~ÓH\”8)qPRÞƒL£djT†4µØ))›IJ᥄%VJ,”SbFŠÉ]íÈ”ÜNÉm”L™,KSÉd™LŠë,MJ!)™”'dS,)Ä‘RáuÄCÆî(§d\8) $l¤”OÉØH’GÉXCÉèÜHitG’Ûµ½”IrÚ“Q”d×C-É¢$S e6’ŒIú2’’[)¹eD´tK qsiD4¹yx{éæ‘ç;áíÉ0J†RrÓé¦F2dp¤4$† N —G’´p2¨ImORn —R(¹1œ L—¶'Éá$i@[))’ hKô)¤¿D©¿•ôë-õK$}£IŸÞ‰RŸtÒ;‘ôJ —zu ‰á¤'% ”Äw =@ÎÑD±’ÐÍJº¶'7€o ¤K#¹>ƒt†—Δ\g%@S(‰ƒMqI,%1”t¤$¢)‰Y£2HäLÒÁJ"(iß.NjOI;€nGÂ)‘#I[JÚXJÂbˆÎJDXÁb ÌJxI%x'¶ÎYˆûÿ/ü _šKþtý?ú d endstream endobj 71 0 obj 9574 endobj 72 0 obj <> endobj 73 0 obj <> stream xœ]”Í®›0…÷<…—·‹+ðæFŠÒäFÊ¢?jÚ à¤H ByûúÌq›ª б™¾ãaÈ·‡Ýaè—üë<¶Ç°¨s?ts¸÷¹ ê.ýi£º¾]ÒJîíµ™²<æ·%\Ãy\¯³ü[|v[æ‡zÙtã)|Èò/sæ~¸¨—Ûc\ïÓô+\ð¨"«kÕ…s¬ó©™>7×KÖë¡‹ûåñSžßSPFÖš(íØ…ÛÔ´an†KÈÖEQ«õ~_gaèþ{æWL9ÛŸÍCu - çë¨èrm¹¯¡õº¤® =õºb®~m$fŘô†ÚB¤.¡·Ì•:;ÑVÞûÎ:ôžú-j]ˆöšüu4ù=¼hò{ÔÑä¯$†ü^4ù+©C~NMþïÕä·ð¥ÉovÐä÷²OþJrÉ_Á£&%1ä÷à7‰ß§ ,&ù@ “|¼C'8CµMò36þYOòéŃÓÐK/&õBR/$†^J©K/NÞ /¦Ð²O/geè¥ÄyZz)±oé¡“¥‡J4=ø´©`°ô`¥=XpÚô-¡w6õ=µä¯D“ß‚ß’ß ùãVÔ©R'õß¶Ý?Ï LŽúäô?½Áš>ê¹Ô ÑôaÑGñˆ0pi²0zø7üiÕÞç9޳ü@dŽ1ÁýÔߟÌ4NH“ë7iÓ% endstream endobj 74 0 obj <> endobj 75 0 obj <> stream xœå8kx[Õ‘3÷¡·-ù?£«(~$²%GÎ;Ntc[Š“ø ²C°dKŽbËXr jóÚ€Iš”†ð%l_@hšëЇ¦I ,K»Pد¯-…«`miûQ"ïœ+Ù$YÚî·ÝïÛ{¯Î½3sæÌÌ™™3ç\ņGÂ`‚1àAîÉ ŠÜð<¦÷lIo¬#ø ×Ý;´e ´òWµZq˶½Ÿ–ÍCãzÃ3}á`hõê§Wd[HÆÒ>"<XCxáóûb×]'>Åðm„—n‹ôu×Í!|?Ã‚× íå'xÂO. ÂC×<ðá¯èBC‘hì(ŽXeÖ?4ºoË·ç ›!ÒÍ.†s¼ j´:½ÁhJI5[ÒÒáÿ×%>sáFÑ Y°Q}^t +!®˜~ŸaŸ=ãWLÿéÓ úÄ\,†àUäàà[ð!ü~GàexñBn,A+"|HøÝèA_‚Ÿ£ ëNÃÝðìÀì&°íðùg¾ Ûà.ø.†_`­Ÿûa?Ö¢wº &–òð–øÏâÍ´¾‚~¨ÓðQÙÛáookminjܸa}Ãeõuë|ÞÚšêµ²gÍêªU+W,_¶tÉ¢ —³¼¬´¤¸h¾}žÍš“™f1§¦ zV# <‡Pæµû’RP„b{]]9ÃíA"/ ‰H¾‹y) ²IsÊÄÙ{ §œà”g9Ñ"UAUy™äµKÊ µvi;›ý冀wHÊ” oPa¡XER±Ùh„äÍé«• H^Å·½oܨ%yFC½&l(/ƒ ƒ‘@#AJ©}ˆ<½U€+õ®œà@—ÂÔ*|‘7RššýÞÚ|›­£¼¬^Iµ×ª]P£ŠT45ŠV)õ3ÓáNi¢ìôøîI t¦=¼Ò¯ðA;Î{ÇÇw)ie½VY°ólÍ<¬”Ùk½ŠƒImh™ÕÓð™JTÄ"‹]ÿh:ö©÷/¦“M‘åc` Ü;>î³K¾ñÀxprz¬Û.Yìã&Óø—< M~59ýäùŠow‡b ôáÊäd}- JFó&¿Âù¤¾ Qèç±Û–çÛÒ:fxšþZ7#ÈäS›MüÎIº QÆšý \‚îüc » `=§gz²ÚYÏØLÏìð€¢ÙÐêW„¢úÝK>¾3¨ŒuS>me¡°[”Ô?æÛìãéiÒ W‡Ê+‘Uõ¡~I‹É-4ê”)lȸEERÿ˜xMå“‚â´ti…Ä09^»7ümïË!Ry™RçH„¾Í¯ÈµÈÁdŒ¼. PˆúkÕð).û’i¯ž'3ËÛßêW‡$‡)™5 z’£—·–i–¼ãÚ„ L–½Ù*§ÏL,–ò¯„ÅÐQ˘³k(¯Š½ãþP¯b ä‡h¥õJþ|›"wP€;ìþpK4òЂ3¤Î¦jT¸š6C«½¡¹Ó¿ÃMf( $o¸6ÉÇð‹„Š,jêf¤iJrjêòm¶ÄU^ÆQ·”TL#tÌ©u3]|U¢q$F%1_æ°œ—üö°½ÃÞ')r“ŸÍ¹GõrҪϓ±j»»ÀYä&°Q÷ œ©øù:WY§â³hÝ%Ýõ3ÝÒ¸ÎÞÐ:΄ۓi§*ªW€¥°¼<-_]ýl=Û}AZÄ´¢Õõ<>!Ël-÷±e;n¯Û[ýU*7Uów2]éЀ mÕåeT̪'ìx{󄌷·vú[èxv{›ÿ‡\M ºcb>õùK´W¨TŽQ‘!C˜¤Bt*þq`LíT‚Š÷L"¨4Ý ¡g’KÐ,34ŽhB‚&«4vQ”rúÈÇT¿½RˆÅ熎¾ñ@ËqÈ&д¯!ïØ×L §1){¸Z1Ú«ÝÃèž]ÃèZÊ ÌÆò²ã¯ýãœr¶=r@çb.$¶ÓiZ Î WÕ1­àœrOhÄWªŽñ@\"‹Œ|L«q}Zu ½2Í–VdK³ÕrR|>ÞïÛ?y¬Vxm»0Bgµnñ·—Ãô¹DoªË˳Å̙ͅ¹èãDØH»(y<£É„ 4åŠf̧rÊí™B×æÍ••.Ë”;}…ks¥kQ84Ú–Ø–,^ÃUº³çd9Ñ>/•+D[·'þÎ4©µ_õõ›z¿QåÙ[·ò2‡¿Ïßðé­ü '[×Üò¤&uÆ«r _éžËee¦röyN®Äž™™EÖ/..Á̹dýnÉâbf=>Ài^È_×ÒéìÚ\TÑ}w¸¼³¹&‡CŒ¿­á°°dÍeó K ûöO©°R»pñÒ¬¥ ®¬¶/ì¸þ'Ú2Ëë—JÜKsãW j¼~ÞùW¯ÞÓ:oaçžžÉÉù—IëÖé÷…û…°„"~\atå».^,DQ‹.ãI>£µv´vo-_[ë³×Í™SµÎ"Jb…È‹K™2-uKÙt{Òš ,Ež¦rÈ›9"}m–µ©J×Tš³©Ê„Kp³HN`Qóà’ÅNŽM[[Ä\D>Q½±,+•·Ï+.±§òÚT>+3[õ>±ñúËòÐ}þ×²Š—Í³..Îã¿2­øjäÇ?×fØ ¤¹¹¥¥ås·† š‚µÍ¡ÿ©|ã ÛêUKÛVÍÍt´îܸ¥¹…e«ÝY©öUå©ëF.w={:~]qÕ‚,ͽƒFè »—rzöšœ Ý•,É_íä/ .“ËúçbZòóÍó²g½’Ñdè² Åb°ÈùMù\~~Ns9`³‡š…å0yÆEiœðÄŒXnÌYöj²,•î¥ËÄTžºé‡c²ïÖ^ßÿµíõ©ñ7Mÿ5}¿nÚ–‚y†u;¾•Ùt× 7ìzùKë—o]ŸÚÚóäD|<Ji¸£ßÃì=BëíËôíd„ÛdW¯¾F°Ö ™F£áj°E§Õ5è ™zÃk4u:=êõG§Œœ‘× 7×)ZÞ'04ƒ2^0h‘ô:³F§/1ÛM _9g…šói•.­ËÍ•i+6ïrìr<ƒ›wåXË3l®6Բچ6=òøk;âoÓ×ÏÍèŒßŠ÷áoÛâ[Åç?ý6žŽwž§OkÄ‘øü‹d¿É…Zí^ª œ^ü¨öÂ!*N4Cácñc*(ž©Du˜š) T²HWŽpq›âWhGN~¢;Åò¾Žâx›ØI~™r!t‚ %S…é!o2å¦w6iPcîÒ Y]|ÆŒdUð5´žÑ6 ÒÔ'²åªQ3s©p[üø't³9‘̉ÿtçŽ×_¿cÇNîáøÃñ±;èîŒ3þ𻯿ùÖ[SS‰šs;Åi;}+¥’=ËåTè”̬"æfj;uÌóf}jNÓ•™©ÍèÒóÚtª‡Ìž)ÕçÌ0fÕ•D1¤D̬ھú OÝö/ñ_â™]ÏÞì‰ÿü–[î}èÖüÁM_Û¹.>_ô®|°o`s¼k€¼¹šìØGvhA–jRQäRÅ.ñxT<'NSiÆÎwŽ›æx‰« í„.‘GÕ·êüg6;0Dzá¬ê~V•³¸O⿌oZ…à_ Á³gÕ}à+¤gé1B«¼d‚. ÒÑ ,E4‹q”t ¢(tFôçôÓz^ÒWè9½ ëÒ¦óÆ. ¢ØªzÝšJÊ=z.ªÈHž´§Ù¾Âïÿ—}º —Å$zÏ~zËÙ³ü̆]dƒOý/áV¹.lÂzMè6¡hÊ2™x?âVÀ«/¬,:Ÿa `m 6 f^™G3ðLƇÜ¡ ÌȘcBý•+ÅÊF>Åélyx*+g÷ƒÍdaebSÀÍ^6ÌžC{ó—8q AÜûñ1†.>Íx‡N#êùßÕUT­¨Ìù>Í©˜òzåõ “ {—cï"¬/í(í/å/7ö¹uF,ÞTTä„Miêr6šëÒÒV97ê7êöê8®Ñó ©u…iNqA÷<¹‹‹ç ¦ 8Æ*ƒH«A­a‰'ÕwšS ¦)¦©ž:Tw¹ù%Es1±¯Ñ†çg6i1±IgQŸ3WöÔŽ¿´û½ø/b᜻F«ºjç{‚Û—¹¶tû«KÚ¿8:óiQüõìá §µ2ËÝÜ¿tÉж@wùï\ó슮H/­©Xê-/4§XËVµ\ííÞ»¹|âÉÂMWæ:–Í­ð,,LM±•¯n"Å©¦øÕš²LNã>ÓîÓrZ-èaŒzgH…Eü¬°°¢––\hKÔÔN‹SQQ¨¸\qJüóÉ?ßIõêg´˜ÿ„‹(7Êiü:'Òâ†1PàC˜ì'Œ$²¼P…²z¢ÄŸ¡ Å_$ ¦¼l¡¼ÔCËqàÉœCaÏkt:#Šf ê°Fèò`Gq/ÅSTmä9…uˆ"tiyq¦>86ÏV†ÍEV œÿrü—ücB0>v6ÎÓâP׿ËêÍ "Ø¿+ŠZ¾;A:Îó]ªéêù†$.ª¨T…½Œ%\%㡳êß+pÉØ™XßÇAËN y…uZ^ËëÁ`1pCЍOÈÃ|­ë¢%?-¢(ê….äõI%ÉŠ;[ãÔã„CÕ™XàÔîàŸ;ßÅ…Î?Àý˜&?q6þXÒjiï9* Nt™«>kâ¿»Ÿ}|ö‚¿Né¤w?F©ú°0ArœæÑó÷]ø·Û¥ÃÑY¶–N²»a+ ²G Ž*øjªj»èÔ§,x˜¼H>€2øüwãY®–î!n’û”¯à‡ùW„Aáᤧ3C·ª!¼I8°€‹v$àüÊ$F-ÀËgíÌÚ„`& “£ˆ$a¬MÂdÂ]IX¤ýå›IXC¿“„µ°þ5 ë ×&a=¤b{6’ =³ÿJ;q4 §@$áTXÃvô„æ:“0Â\>/ s ã—'aÖðr ”ÿB¡€ÿfÖ@1ÿTÖÂøw’°J…W’° D! a¹(%a\)ú“p ¼*~' §Â š»j"C;†û·ôŤҞ’»¢b™ÔIuÁX™T?Øã”ÖnÛ&© Qi8 o‡œÒúújoËÚ¶úÆRT J±á`(<¾ZŠô^<~}wx8ë J"ƒ‘êȶÐÚhOx0–Ê¥Kz%Öýy´ËÃÃQFXä¬XætÆÁÊ/ôw ¢YléÆÂÃDì”Ú­N©) Ƥà`Hj›ØØÛÛßV‰=ááX˜#±>2{ëÈp4ÔßôE³³©‰ E6´ÆÂÛÃÒ†`,ŽFûb±¡•.×µ×^ë &™{ˆ×Ùpý­¾ØŽ¡p(íß2H³wöŶ­'ƒ£døˆª‘¬¹Ðƒ¾È i[‚§LІÃ%ù½á™64Ùî‰9#Ã[\×ö_ÝïJÈëÜâúL “’Ôó†Z‰C°†¡¶@Äè{¡z`½ÝPA÷2‚Z !z×A8ʪ§zÒN‚ÖÂ6º¥ $DU,Lï0½·«cçzUMµ£…Æ´Üìë¤_åR‹wxÃ0@ïa¸šhèý›ú×ÓønUëé'þAêÝ ¾#¤-B¶…H_”¸ÃD ©¼”«öü­±Òìèÿ.ßå*Ot–cÙÇüç$O~žŒ åGÓ?æ¡D,¶¨Rbªìg¿*»8ZU®&u$óQLÕ6¨rµ}ŽÆFÒØKã™G?ãìQeÇOHŽÜ—ôöVÚƒ†U B긙¹EIó ËÉaÊÊÈE~hU­Û®êÜ Òcjޱ¾>‚•´¹àZõvÏÅ’{’r*4@œÿÓq1Z1CªÃj¼·o"öNUæEs}ÒCƒê:`¹`Ž ßüµô©ïÄJÚv‘Yöfcg¬&íïUõ$¼6DÏù=¬zÛ©R·¨sì§öt¡},b[’´K­™±åâùü_êæ“'";¼ŸsÉy–󸑝Êú¡oÚê99Ç5¾ßõ>çzÏó÷$:`5.üNûoW¿Û~â‚cUVéû¸€PpÁøî;yÖ¡w÷rßÑ›|ÊÛ8úÖÞ·½Å¿ø&ÊoJó}çÎâ$–Ê+Þ°Xoàëgò¬¿9Sj}mõ«í¿^Í·}_á§­ç~:ýSîÐËG_æ~ô\•U~.#Ï÷ÌÓyVùéŒß$ÚŽ=UeDIÖŸ®²šOaà‰ÔÈ…'K­®“øƒyVó ë‰Ñ{OOϳ6>1úg>Içe+µCÔŽ¢(…—GóãxŒw“¬üÇ×Y­kç`¸¨qÐHÏ.jjG©¢ö"µsÔ¦©é@Æ9«°Ä§©²~›ZÓ‘À‘3G><"È“8÷˜%Ãw|ú4ÊY&³ï±ÃÔ}8pøÌá ºi'3K`/µCÔŽb‰<_€G,H ="<ô@©µéPà÷àÁ«ô@ÓÜØÁ}?<ÈW¬MÅù¤v>4QãÉ<;¹}T}E»\ˆ–ûÇîßw?¿ï>¼÷žRkàŒxñÀkø}plm>Zˆ±‘ž£Ô8¨PñSêsˆžûTêK*nNrE‹œÍ›ïöÜÍ™÷£y¿k¿gÿèþCûÏí×Lbº\¸»Äúå»J¬ûè}nšw[wsìáÚ}h·`>iäñ4àØ7Ÿ9Ý׸ »n¦PåÉ×–Y·GK­#Ñ\kŒZ´)ÝúÌÅlZ VÌÁìceÖÑS„î¥vˆOóÎ:–[@ÑÏ”+|eÖ!ŸÛ¡6HIš‡9í¹•9íÚJ¾]CÙÓÝ5ߤ ÖÕ”kz 0††ïrWùæ['1CÎÅ+}¹ÖMnk§/ÏšáNo‘oÜ|û$êd[¾d5óØJVµPknškÝè›k]ïsZG°FNbêã¾R+…Ú$_mLõ]æ+°ž«Ÿ®çšê±Þg´zêë¸:_¶u/ÃjöúÎù¦}BA(¿=ÛÕž†æv‹ÛÜÎ!´£Ú­f¹Ë> endobj 78 0 obj <> stream xœ]‘Moƒ0 †ïüŠ»CE ôKBH--‡}ht?€&¦C! é¿Øî6iÐcû}ÇŽËúT›ÞÇonT xÑõF;˜Æ»S ®pëM”¤B÷Ê?"ú«¡µQ¼Í[¤IJ¹ÙSâ­D^q>AΘWÈkæ#ò†8%ý–xMùqV!ï9Ošs†|d͹d>#ŸXCw™OÈß…šD²{N¸ÿ¬Dæþ³5=üñBîèg´BÝ c¥EÒ> endobj 80 0 obj <> stream xœí•gT“ÛÖ¨é %ôº€zï%TA& %@( „ÞDŠT‘¢€ôÞ«€ H¥WiR¤‰ ½WoöùÎÙÙgÜ÷ÇýwÇ}3FFž™¹æzÖ\k—‹M ‰ð4ôsƒÀ‚BR@]¸«—Ç#k„PH&ƒvp[O  ÌŽ ýg†ÙƒZÃÿúŸÀ_ ºÖ®0 èÅþõîEÀBèG“¯c퉂ûÍ…Ð3‚хПÿü²@Á¬í?L¶’Ò   ’’@°0ý%.ô¿çBöH äV`çåöïUAj^..ÿ²¼±äþ×xt’µ+ÜÅïÿCØýw¤Š°EÚÁ@ˆ¨Ð…²ö#B· "* á;˜/ækë "žè!@7/Ï  =Eü—"B"`Åþ… È †‚#íþŽAnÖ¶˜ ú7ˆAˆ¿A òüÄ Ôß žåo‚0åÑmya­c‹!´ ChG ¡5Ü0„ö°Eº 1.`´Œ‡‹µÇ?F ìÿQíä!´”¦ h){ ¡¥¬1„–òÆZÊ Ýc”‡-õ6¢íþAh;? ¡Í\1„¶rÁZÊCh)OLã„ÑZzBk9c­å鈂afF«ùbmdôÂl‰0ZÊCh©‡BK)c-¥!´”æ0 •a­dYÚÉÑÏ͆Ùá¿6Áû§é¯}´FÁ.0{ÌáAË©bHìß9(¸ƒã?’ЖŠÿ¢ÿº¶^(tªç¿.!úºü‡íá.0 æ ³%N S¼ÓËùIÆÖ¢’ª ³Ë¿li¢šýæßRA½ß(v3œ7®,ú›ð›•IY“svOʳ,£óõAŘÚÛOÒq€Ú¡l¡Ÿ­?=æ8]ˆ«sÝÄÂGSW^°]·Ri‘‹“<˜æÜi,ïÛZ ÖnxQtâ a‘iãÊÆ«Ùû$ÛM=ÙÂR””"4²˜$%®:ó)©=ŒzYc„FÀEŸŽ¯ ‡Ú«‰õLƒ$ F¯Ô,Þä…Þý†åÝàY\F>xÇÚHü8­\ëØCÀQä]’cÑÿõ»öº…/ELÓz©K*1y´ì‡ÜNÂÕ k;ÿ´0B2eüÇ Ôôf¬ï›l÷3œ߇óÅôjã†|ˆÔû?Gàû[ïò ——8Iæµ#»Â¿4g’®;É¿õ”Æñ5D¨ò¬Ã(Ë)/‡î€FY‰[&÷Hû‰!T§0ES:,aq—ð»}75Ì•%% /_ÖQy-.ê‰|e§ïyèÔÝ ]§K®ë?1žüúRqì ,ê,Ñ,+&°™µÅ²5Ff+2 ÉðY&›Þ ‘ãTV)´!ðõæ‰r,Fñz†X&Ê*¥`‚áET_*¯CÂL…Ã,wè&%ë,[~ ŠvZE·Ó(й¼ê\Ûz-ÇÕÁÞÚÐXrðäv••Ë"HÕkº@ˆOªÉ¬pÔ480Ÿtr—Ù|õØ$½¢Ì}nëµ &ÇÅ)s1 K›òÑ“ ȵ ¬òü~$õggLA°…aFüšc‹Sî¸\íiøÑ¯D¨C|A+Ÿ\µ£[ljÈÔžR2…+_¡DÀ˜»Œ5}Êqè¾—Äf‚³”¿Þ6†€òj+U(§‚Í?Ï…x™˜ñë ¼Õ>z…ÅB³}[zçÛSÆRw­þïÊ«’Ï™¤ˆó³“¬[iÏ78ÄIC×8òïìG1²<~Àôëî]ñ²Ðêƒ+-Ô€H(ž4L–øu®t)©€?º£#žcGÓ‘ž6kÝ‚浯9é2LEÆ÷ŸD_ºc Ó@ò#cð»^R¦~Ì_"n)1õ¾¼õ¤ÔÒ¹KÓîV‰³sÏ‚ÁLš ý™­*ñn•®UWH¼“îNùûëÆ‘lß@åwó ’w#œKv•D9Je­ÊÇM×k@`Ü4lq>É“Sí? L±rÞÎµŠ¶»8¦_eHSÉ<Þ)•–Bû†ˆûgB¬ûê‚÷ëwÉ´ 6Ʋ.!ïãÌ{öˆ_×hb…Æ‹â%ÒpEh%ªvo.Àøž¤>E‚A¨ô>ËPø¬]˜³Žb#Ø\µ!0Có³XÑ. /¦oŽáǽKªÇ.bµk•«œl¼#ÚZç™F¨äŒà'½CâˆÕ®‚±I ì+ïN}Ú…á‹øqM\Ï Só,¶™Ešã{ï+o0Œ,èÛÖ]ñ¢¥W±þK#ˆÞ~rþnQÏ‹Ð+¹zfš‰u´5ëÓáy‹øÕ´€šF2¸Hq¢l¸û ym¯w¡‰—’öCóLÀ2uâ|åŽNýå´õ]êz™q:9™·uœÉJšš;áøpcB°¦<¾»®h4æO³^¾o·ùþ|þËQé(õDB½:ê_v›èô2vš,ZürïºõåØð7yÓTèý/7Ós$H˜è3«•¸wĪðŸ}¦ÐÆŒ´ Rrí¹TyÿwÜë «~yjdBáÂàŠoÌXvé€CwZð}ÅÃ"7{ú™ÁÔ‰TüâÔ_÷o´M¬¡½ú·šÏG%¢Ùƒÿüù¸ñ-z²à‚æ>ÿ3ÁÌþwOS·u›¨Ø2'|ØÇå(ÈWìkǸ®½Ò¿mà a÷¬@¡T%þ»:‰T£§5¸"e¯âﻌ çæ–\\!äöýÒ ±Ò¶k÷‚qŒ‹zÖÀ´õì¸^¦ž2"’ðI>ïý—þ¾½¹£ùöó4—Ÿi}ÕµàMÕäõ–d\“Ù+Ï>`Kj=ŪÑk¥YÈH":ê¾[rad ž^‘a~]<¨¨¼[¤š íÕ;ýÁB)kûÆÝK4WÖ y@Ý]ŸÂ›ã®o+q\Á%Šýt|O\Þ°Û& QÔTÝÉ(îä"[îØ_bHñ–ÚÍnu<²Âe'q1sž®k£zg/¡€¿MãKÒâ³Ñ§®°÷ª{t=i6QkjT»5·.X^£ûä¾VUw®óØ·Ý:•L_U-’ /9M Ãs¸uÔ.z ŒŠþ#dFv~³Ú.sþ±àÀN㥶è×ú…^ãjM6âM¸bSã? 7_¾~=2—„~µPTÕ6b½¥S+8¤Îwí•ëì. ÍÊÌž|FGǶ¹||’öfÿ¸¥ûëÕbL\ó×ý]‹F«!Õ×LXõ]G"Î$#-n¨5ÒéÉÚléEÃúæêIdD'8çAÏ·…Ÿ“äüòÏai&'ÝÎXœ¥ö<ØTà=§±“g4Ñ3p´bpiP¿éey)ò“j™QÒý2–ÒºN™{º¼¢¨9åÆ`UìÔî'û„±C2´·¬/ñùU 5ƒjßâg«x›ó´²Çœ.#ZÃöô¶Ð=É›“þî)Î÷éoÎèɶ¨÷±ü¸¬’+G=q±â«u )2y >mÚúˆ" °H‰Z¢•Ãé­+!m£QܺE“…YNBmž=d¦ï³nÑjÁÙЉÖ<â| b¶úo$sú””±-cdEî¿VÖ Ž»c6^³%JÉúŸPVÓ:†µ=P/‘J{ùñ(xKzà©‚?Õéå§—Çf‘+¾Óv0 &›/(•¡ƒßYeãLQôÔ¬bÏÿ¤¼™m4škÌz”—²ÍoQû£é[ö(zýŽçN™kx”(D¤àssÈI7—žN÷L<è›Z^¨éÙç‡S…_rê~vüÑðBCƒ¯e a9Ȫz˜«¾TÞ‰?oÉr¬QJþÜ“Üßh ƒ0OfÓÒ¸àúÉwŽK¹•a‹gù¹¡ë„ô4ö¬cÝ„= ï{4A7˹ôùa”ÕÝãÉ€¶Þœ:ïì°¨ßB«§“ö(È?ûÂ/ªÇ3XAß‹ËüSs·—w;Ĺuð+iªŒIþÝŒ·¹äz²•v ƒe»Bë­UöY|_/]0*ù  ÛžŸ8» ²5Ùìý›½»•ÞSÕŒ —¦ýt\ó×”âLÒRË Ô ÕɆÔrV–ns‘ÇùÎvÊE„íÌ1ÊEGýÍ3ÀdziéââöÝÁ6îöÒ°]rÿ±è”MžK«õy;çͺî¬\{vh¼Ï²N–ɽ¬öM&06/.ô\×Ð'Ý_‘ä8æqE†•PojÓ«÷|ëñ<鳊ý¯"®)Ü¢:,ý½¤[tl÷€tJ–mjBëç@J&æ§!÷ÖáZ¢DĹ:/~7ôY6]URìÅ6Çd«]±#a¦D8%&™¬ø ?œo”š³¢z¬é&…žÆùuÒµvsiKÿæÓ69ßš>`oÁãÕMTUkûu©ü,Ähæv9•ù¦œôOé¿ Itþ´!„ &”žQ(„/¶}z§-Brg îÈ”u¦”,²®àX––NöæNó ™¶À±#‡×ERÌ8¥ÃF˜Ù›yWDFä§âfðX›Ô¨o¨f]÷öRê~‚h½1áS¤ó øöÔ·Ÿ÷2׈~îVÓo&¼f¯¸°¶¥‹b)ÖÁ,&a÷}wõD.Í£ÔÇÑ¥ð5]•Þ•v9n¼š¾­îÀF Û šÖ,òXË*p!µZµ&³çãÂoõù7ßã‚þ(™Ò©øˆ> ( ‹‰!¡8AÚˆ',vû=šµ»1êsaépyíwÚ‰€jj£„oú¤º®üŒ} Û~Û{à¹kÄ:7RÕ÷JÕ$¶âGúþF IKzêšúþ‡>w\g¡ ÷Š[Þãèä’¶yü|sÓÌYwãö«pmæ í*žlÞ]ûøðÉÖÚèp”ûkã$yjÍ–/o¸GY€–×®A B$%EY½øÐ¥xP~½“önÐ ¾ÖW TÈG§Ÿ‚€µ\?* dËü:æ?„xˆËNX¿»o36,8Ú“&"-bnOíi;ª-͘;¦Ùí˜ òB^‡å²¶x,Ð=T—ÚWy~íKª¸-zæFMÞž­PÕ¢pÀ3œeÊ^5'YF4¸û*(¿Zÿj)Tô%%bÅ+ϯÁ滆Ô¬!^Ù^ö“wq%œ¹¼%þõì®<ÅÂîÙüêr~ÐíEÇÂÊHÊÅì&ŠáÍè8ñFÁ2"r+RïýºµæDg×$±ÿÓ‚ËZýÈIƒ×Ë ]?«œ-“ãc÷Ë3^Zy1NãÄ*i¯cÀ ®^G'÷Sç[®’éW’yø2a¶€7%ÌuD†¾:–zý¾/nƒ—Ï %Ö§ªëÍ•\FÉ·5Ž`‹­éIzΧë×N›5´Ò »‰? øà? }»tQ·=Œkq6ì~èo]ø9…õ‚õmr-Ny7ýjUx£Øá†ý‚®—´—èÜ7¼gž0¸¹fÏËÇìx+,]h@ö&”d4jÞXœoªÔT†°£)T¡Ó䪈‰Ðò‘]à¦))kk`ÑMà °ë•<ýìŽC/ôuþ„)8pÎ;YÓvo«v07b.ÔBò¶RÙÇu:Eð`ª­¾Žó~³œÙïæÜóce­—j×ì¶v sy+“úr#½ÅÇý1E8 5”ûoiDŠLi_KõL¿Ö[8ž)s€rÁ§Ð¨£w3±_ZyXá‹r!yK°dXÙƒYGò ÁÛÄêÜR o2ÄuÂÕÊÕøEŽÚAˆâ$¼ª_¯l!ì“ø;êÜݱç/ù>—”:[™ÆâÞ™W Ñ:Q™É,¶™åÄ1 £«öT ŦjÛ/%—:5Ë,Þ{¢ xî¿>¥Fð¼hü‡Ù„=Ûƒ´é0“©ÓR•ïÁøEéL§*•.å\€=y2ƒÙNŠm›$,õI:Bs¼<ÿPûö7=¡/kTVê“YÓ¥œ‹¨È…äס¢ÄºbËXÂNmf8íceoõðŠÙ¥‘ÓlÆYVÊdŽ÷vúm{“‡€9^€[ãöhk‰çëôŒ•N_eZIÄ@—Ôz•„ía¥tùYŠCGÙÄž®”ÞBÑ€Úuê{eIX³$¦¥žá&«8…VYõ@GÅX”ÉÄn»•ÎËyØBÅÒfÏÌA`‰-nA¼ø 8›iw¥×ffNRÀ塦 í ÀT®ddð3¿5¼ð )+^äÇB„öë¦ú T¡Å1õõ `o{­FÁ¤&§ˆs&ÔªçH^Û—¤€‘²ï ]ìÏtGUƒ[ sCnòßC‚© ¾„A®„3-üµ+ZQ‰ºUaZ*Œ3¤Ð; ¿»ëZ\d£^DªÄ(žBaðY§§ I® e5rÞVTO^ Åï´úÀa©åÔÜu€ïKO¤Ç.Ü*tÇëw¾òT¸÷ˆ>IKÎPÌbÈ4)r‘Ðxâ¹\ SÉö˜s„«â…W4ÙÍ è—TFo1W16uÿB_xn¨YÏ6 ¼ïßÉ»«²ý[žžZ²Ö´êEq–žÏJ¿]Ì ©í½}-a F!pEåÇ™íò%® IëçÓÈÕv¦’Æ< ¥Šb{5vø#á:‰Ålûß™t é¬fÝq8šï3¶èn5n$nõ´ãe£îëü‚Ä’ÎU 3”ÖP¢^j/ÝuáŒaGàñN͈à¶Ý£Ò€jˆ0òlgâô— ¶­OÕîÀ—[ïÛÏ Y?}›Ö¥ Æß#`#€…Îák¶Ø)?öëLÜdà7gØ„H>xÿ™ bnvw.͇Àœ¢´çUÓÔÖöDõUÑÛ`sÇ8²+Ž˜ z^Ð(ýËo¨! 9îö¹-È»5eI[ºÆËŸžq}¹«ŒyÌöÝP©œˆ†+wì‰rÇ8¡F|ðHæØ›ó1ï\yÛlúd„hé*N6¨:Þ†#\Ü=­Ez:*½ùkáÜW×s^i (íóKOîÙÕ:\!õ$^—"Ù*ëãÑ®›Ôº»,.þˆVùs´éE,/~xLÐn¼‘˜0‹â£ö·øÖ*©ÁÁ*ž™Qbeåô-ﵬH·æh}Ó溤ÔžÄ7`­;˜¨Ø*^ -+³_ï#\©¬~Žäß‘b꺃?Î)åÞ¹·v§îŽoéÁ=N÷U^©ÛbäFþ­Ð=Í^Ђ·Õr–DzCrÝ/Ò1îëm&mM5-ŽŒ(n¤'ŸÖל>O/!hÈ-2æê©¼ÔüCÕDãhÃ’—z4üT#5’I$a°é튇â";,5n÷”²[¡¤6í=]ýT#9ûó•G[øðkº¡> endobj 83 0 obj <> stream xœ]“M›0†ïü ·‡x0°‘"¤l²‘r臚ö˜¤HƒrÈ¿_ϼnWê!Ñž½5äÛÃîàÇ%ÿ¦þÈ‹9~|›î¡gsâËè3Kfû%=éíæ,½ÇÇmáëÁŸ§õ:ËƳÛæi3L'þ’åßÃÀaôóô{{ŒÏÇû<¿ó•ýbЬmÍÀç8çk7뮜k×óaˆÇãòxŽ-Ÿ¿3Òg‹(ý4ðmîz¿p¶.ŠÖ¬÷û6c?üwæ´œÎýŸ.ÄRK‹¢´mdR¦7á\;e·®”k­©•'Ü€Iø5{áXk6¨©„_ñ¾Þ‚uþü"ü†zͰGÎMd[ ›Ì·È_שß¡‘¹u#ìRprg›ô=*›$«…C£óáPï„“ÃV89ˆ¿…C© §3áP¿F&8”’“àЈ3!)÷EÈ_)#%wAÈï´ùd äwâBÈ_iÍêóŽ´$‡R< ¤9ààô=Hü Îêr¥-’5“ïàïúšþB\]ýXtge[GÏæß5O³´éïÈÛ$ endstream endobj 84 0 obj <> endobj 85 0 obj <> stream xœí’w4\ë»Ç½%ˆè Aˆ2Æ5‘¨Q#‰H´ cŒ: ctQ‚ z—ˆÞ‰½wF'D% qQwÎùýNÜsï?w­ûß]÷Ýkíµ?ßý¼Ïûy÷»xÕQŽ˜ÇžNH\BpßÖÁÂÕEæè¢ŒBZ$$©˜XÚÂ1 „µ­#5ðïIBŒ°¢>€Ùþ;øWðgÁ}˜ü/ ÿzkàhëìŠÐTH$r1G†AÛzL$«‚Í×ßOP4f‰rDz^T++£<Þb YY€XB’–#Üd$žÿ÷ZMG+@ò_»°tuú÷N@uW$ò/S¡š þуPs°EzþJŽ–ÿ €jŽp”¥­£5@" €¡Ñ0Oj §“„@Þ €­£%€ð€Û€âŽ( a ÀÉó`…BSÿ© 16hâÏô¯@tB mQ–¿0èâƒ_”H€V¿B¨ÿ Ò ì7È€ðß Úÿ9õ@ Ã„ÐD°¹Xô§É4l/ˆàáxAÌL0îÿiE‚Œël.6+I°±ñt²A\4“$(!/ˆ ¤~A%· "(y^AÉý/úljÁ]Ñh„#毟…pœ³•-@ <pêØ@%ª^þÎ[&ˆFÕTtE Ù‡ìãÆ:ÆÙ)¯Æ¦ZéÓ‘¬é ÈwŠ(r'3eš¢:ûJâî$ß4]ƒÃÕ!¥Wƒg ‘ôÃéëÍë.süHê²L'é ±äå`^|3“öešG¢Óü[µ2ØÍ?ê`I%»ëŒ@":K·£Õ­Ü-'M7‰éi¯:jÑßÖg—“=iÏf`r1èåz%1Z òÉëÜÇçPŒÌ·–Që=—Í;Q‡&d¼Øå†L¹Ucò‹@(ÑxR°äÚ«€¦i¿ ›nr³èŒÓg¸-ò“¬‘ûcÊÉ.)-oãI¸íQ èòròŽM¢Ãæä·$¿xDÖö„YzE‡Åbn²Ï[EõDùG¥{³™×kJ•Zn’%C)ÜÛù™Ãõ‹•ªì§fÌ7´N5V›Ú ûõ>œ°ÒŽÈ… Ű?ý¬”â"½Žx\n'§a‡·³DVü‚µ± ¼!'1Š}ÖGÆ„¨S=ŒÃ™gò)­E4LpG¦¿äµœ¾6>µ2ÒשámI5UkÑéhëКnG©›:@ £œ2NQvó Ö²;Id¿"ˆÇçžÉD5û€hŸ<º”0ŠU¹‘€t?Y+ÛŸ‚Šûcçõæb}bOÃÓ‹¦õcHë/aå8]Å¡¼ë=î,,úšAJÞpTå„wÃ3´"8’kô޹¼P}¼ÐöBÿf-Kú&Éå–¦±ýWpZ—µ*9êra[z”̦*Ë:,MÓ2бM“›úBÊ™¦ø¹UþHF?ãÙný…De¾êï+ÎP›©â$øüÝÕ?©ÂÕ±m7Ã^mÕ—H>f š•ŸxN¾­ mõAàë­ÎTc³ÉML·ŽQÀ)lhu‚Ý v¯¼ªË”fàõUåE[ ÌE³ÖŸH´Ütè9×í—-úíúß:ð/”Ø¿êKx ‰ÿê³Ò® §?(D÷n£°#]å»#E4»÷â–u*Ê3™Å 3m»›øìåï}×´¸â{Oü»IYGÔ"ûÌ^?éKYÜñÀkè= ÅG°ì¾†·i‹·×qµ÷ÈnûOÍï(ûBu3ƒÏ~F~Uó5üAôiV[@?ÌÀ“¨ýyÞC!΢C9ñÐÙ¤Òb¸óÝ©#*@»B1:Ïãnˆ‹ù<½6Ô1GĹ~ öb«¾M'òÐ*ôp5'??" 2`,9 Pöp6cpÎW9¢AöÍV×ñ;x“t«dgRG wö‰›\ÑSÌV.ÅËÁ’$F|³V¢ëL)XììúI'Ø£Šê5Öž%¤7kv °1G¢/„ Ý}pT\ow¤Þ×#œ*Ãy˜žÄïИ†ºÑ‘æ³¼TÜ5 ¦ŠQž”÷š™ô}°AL¿wZƒ>å{ñóÝJîf™Ò}›>3‰?ÎJg‰zë¬D«®­æÄÙeä"Rža½x[Å9 f_úýïÌ7jÞc¿×û°ÔOQÇ4Ìmûcܾó“Ôèx—wÒÙóÇ2B£ìw=T|µ†Sši±P³ì^™*»Ïj ¼nDA|]e*ña¥ëÁ<¯ŒƒíMWŽUºèƉ°¢¾ž×R;2y;o]‹ó'fK ™,Ì~èEûÅýPwië]øp£›)û“¸ý-ñsÍ‘ÔñÔÝw-~lLΟsí/måâW˵8õËYµ°Gtc†‰‹äã—:<6)šB%‹’nÝ–r½¦˜e³[QôzH­K<éJì Ã®ª9Ï©'ážorÚ L.åÝN¤ƒ8Mù&Úî#ÝVVœºAðÍx^<^0;iáêåŠÊÖ{ +¨ÙÓ»u‚,ίÛe׌óUêL0ï+DíFÂz„Gˆ£KZ«È¤v3 ÑZh•5æ×Ÿù–œù>›Â`šFq…œ&©Î;*Ê›y*“²R.à ­‚ÕPŽk˜±Hu?î_lŠÓáKx«Sû)v$ù¼v±¬VWËrúRA’í¢ÓŽ`à\xÕC×M‹Í]l3‹•Áã#Ï?"ËižyÍÌ8ûסwÞ<¸ÆhÕ‰';l-S5ýÙ’n„‚¯œNaŠÞO*æD×ɼ°Z¹Iøù×;üÚòj-±îŠ,Ìqs–ÝŒ»2òEɲŽä·—1¢JÝs3ÖÐ÷4GúeèµÂ⪠o*ƒƒú«šQ{<)ƒ{=z²3‡ºG¨Æbœh—½n‰úçÄÚÎñ¹˜‡ÊË”1½ àÐÞe†Âj§ÚþÁÃÕ¶‡f<ƒBÃ42h7Ò¡!§w«!ò1IáÉØh}b;ûOÚx{×ñÃͳoŸªYj±—«;nägk«É=D ÆŽ6’B¾(hÕ¼–1îY¥Æ¾þqH¿ÃñëmüÀÒ1b^ùH¤º5à£ÒLÂT{{1£ä/xžËšÝüv‡‹˜âÊÁp"÷M£%az,ÏžŸYñ7¶üËÖ.$ïÈ=èo8ï…²Zô‚µ×óp\+˜©Sø¹ÉÿáfUè¸ÃZÌýô^V3²+&Ó3AÅm|_à* W§@¹Ó±ïWxë½ß¯ÌêÞÙ5aõÇš•!’ï¬á'Ÿ³ ÒÊ0Ý*vj‰2p=1®ÅLJ}+IÍÂL £Ëª-ž^ÎzùëiôшÃî·¯f5cþ–Œ§q¨ø¼ ÊÍX†€F$(þñ¦í6ë,¯=¡°¬ÒgÕ;÷ÝËó Á²˜  ¼7Äîã¨ÙkCKÏ6Üu]–Á8÷ssñvVÅ<-£\Ï·Xay¦ˆ/¢Mi18î0¦Ê/ýg–®Ä1ùn°ø@pX·œ9è”±ÎgoíeHžQ+‰9+Ó;˛ꕟr³¦tO çÀY‘ëÜäât±fúBß$Óö°m’6Ø0Î~’¤½ÆÁlÑ<_÷…O¯×ûêêýÜíÁÔÞtí±Ê.Ê£¹½™åwî5÷Ò³KðÖ¯bÜ…Žlî„”µ:ãÀœ0ÔÕŠ®kˆ›·¡*QyZ|†ûÏ ÛW?r³Pzåm½~ÏÜÆðvR$Í‘Ñd{u84 ˜—Ó;^­É­9aÒËü0l8ù2’lŸ_Ä­0[sÚ!ÝRZ ;Ì =hýñE”ZòE¼Èº‡ë`ßyÖHžèŠ».U »$n«É™*Ïin°e%]u—e›FÔr¡¶©Ïâ^L¶þݨÌç’™Oj M²)c¦¡²(…ëqnžÛ¾³:Sç g>pšƒNhˆ&ø^ù¥í²|ܹ–BÅPÓù#¸´Ø€’ß[Û<ûrâm‰J¥´O†!æÈ)SK*±¼õÀÞ†ÔK2OVº¡×s­¯ÿn3E cµsµŒ+IvWªDùßÐÉ.´(åá«Jî"«gù¬3¼qaîƒÙÈÇ©ÔÅÖ æÉK}6o×C…³±Á[)/Çr[/Mñ™Ò#—o3õÛÒì°>÷ûðÅùαt Þ^q¥üGàÎûí_­d£Jîøg¡'Õ)ÅvAg8ƒ¹†÷l¸Ðám™q‚8µƒ]⥒š²â¾»0úIÓw÷HË×3n- ´sô—¢}O:ƒõí3ù¯c `pÊnÿÞCÇq°©(HÓa¤š¼,’Hq5˜Kîþ)•êÝ÷ÅãÃ>JÙ÷`Ì’¹”·«ÊHueíó¥±]C+'TÒ—§pÚQŠ“í}›_0ÒNÔ sn…±£LÒbÛÁ M²žÛ,B- ‘7–té5µ)Àl7Ûž''êrð›•ÖŠdÙðÕÆŽ‘+&~j‚X7lºFÞ­a#[¬(QÔ•êÙÞA‘o‡v¤_ß‹SwsøCJ£ºÑu¢F—­rR•ïDß(Ù'§üe ØÓˆj`l4/¿,¹[*….¼{êõEéÊՙ͌²Š=åòN-n§³Ñ’Å„·H¼‚ì `0R¿q²’Œ±€jÞWÌ‘v²;ά¹?{š…LýQS`:"bORW—§ï6(.ZˆS6ª-z¸ÆÎ`bUÞã³|éãØ´ÒZñP-ïì¬c}y)jT)ÙߥɅõÉi=ª[}ðIØC×íqá¹ÛYp É•°,bß<–5©ÝÕ<‹ ÛŽKJU4eqWYugÿ‘OÝÒŽ–”;R}¡"Ó bÃ2ãñ Ìï!‹7¬\žmÅ·×óíxs—@Ÿ")mJj’6V|­nçfïdAJv «ó}+Ì5uCýþJ1™~žÜ-==‚û_q)áŽlþV¥ÆÔÿËñÿ þo4€#04åCÛÿ©Üó endstream endobj 86 0 obj 4353 endobj 87 0 obj <> endobj 88 0 obj <> stream xœ]’Knƒ0†÷œÂËta“ !%$H,úPi@ì!E*Æ2dÁíë™I[© ¬ožþ™q\Ö§ÚösüêGÝÀ,ºÞÓxóÄ®½T"L¯ç»E§ZÅ¡¶Y¦†ÚvcžGñ[ˆM³_Äê`Æ ÌGä=s…|`>!¹O‚\²‡|b?õ9³\1£6%9g‹|×}ëϰbý)å°þïU¬?-‘YÿÿK±þŒ˜õgx¯býYFüO ÇŠ{ÿY—Ð7ïêèqÐŽp;½ñû€Üè°Œ¾oP4¥Ó endstream endobj 89 0 obj <> endobj 90 0 obj <> stream xœÝ| \UU¾ÿZ{í½Ï8çðF„ H" „Š8<åa€¯òuä„qÀç˜8^SS#G1ïè8Ó”cf”ŽšbeÖ5§¬©¦)oVc‘Óm̺ «û[kïÃ+kæsïÿÿ¹ŸÏåxö^{íµ~ë÷ûþžkÁÇÆ†&2£fD½¢ÖQÿò7O!„^CÛ*–5*>ºÖ_Cû#„„”Êú%µÝnT„h1O.©YYùõ±__„çcE)U.‡³.wk*B±†÷c« #’ÖéŠ €çUµ+ÞôÿL‚çñð¼ªÆ]áØôõ®nx>Ìžk+ê?‡á}| <+uŽZ×¥û/ÜÏ3àñZ½ÛÓxZ÷=BSsÙûúWý†ã/wÁ³!Ý0èÃða?fhÊìY ¢$ëô£Éìãëg±Úüƒ‚CBÆ…ˆT¢¢cFÄÆÅL¸mTâè¤ä”1©i·§7>cÂDôã§ãß¼g£° }ŸNtÞ |\'>‡7ã }õÀu=úÉËx´ŽÃÜ9bô¶ =|f ù 5‘cèMt½­Ïp¹øM…?j›ûW!Çáé4\W“ãdŽÄµèQüP\ kºÑZîB)P~]¼½¯£ðÙEnh3ÎÖÿ Ãh º†v WÐ]Ð~~(òU×ÀÑu Ô!L*aÜ ¶íÆëÑEä6ÂÈKÒEaP=  ´í‘.J»p¿(}o.wʺ‚ávÃc„bô&Ì_ÊÉG§ “Ñ¡on¯šn’‹ÆÁÃ¥«h> |#Ýä‘ÀÐs:Y‰€Q¢b9(Ä8Ú¼27jtâGÅ¢S¢}V*ß?cŽ8Lš{P ?HbõÅØ˜K?öòÒèÄé3æ(88/W#›·(:Ëæ@“=A7ôçåòwlÕƒR,ü+XtP©¨R°<3á‹kÂhÐym«¤G!zéPä1$bhdpë¥õ‚ˆ’»Þêƒ,ou¿Õâo²ÆFY£ªDÔã!Ãz>¡­:ßï¾n˜Ÿ`tâØ@Á€FØýå6QhC›Äßë%CŽHD‘l*4ýîž×22ùžnkFF šˆc¢ãÒ­°†°öî¹ï\ùͳô]ü!nýÙ}{Þ:Eþó!àõ÷‹sÀ†Q8ʳǡ ‚[ Ûä #XÞêƒ_ Ýêܧ}8Â-† „Û,S‡[®Á"]V[ÏrùZ÷eËUø\»j˰ÂÂQAi©cÇúâY-(-Õ¦KÂ1ѲNœÓóñ‰§æœ¬­>}7½IßÃÊWoÛ)nß´áI‹°à.ù¹WÆg<7jÎÀþØŒíô/gö?qâ„OÄxnÃì>Â~ô¤¸_–ðpéÛîTUe)8Íc…/¾Ò?b<½@3èyU÷§AÖX5%ÛÃÌ[|NZЖГA[‰e«á8ió·™‘œf¹Ö•Ú­ f¡×®Z¾¹šë•$*5(8‹¢É(ÆNû×RÚCßDZX¼swqÁŽù¿{áè“‹vee€ãq|Æß–øbÖ„Þ8iâŒõ K½ôK䯨C|%½9‚¬ø”þˆQo2€=Ë›oÕÕ3©+UÕéµI]Ý©\­ÜéÖ n¿Ÿ.XÐtþÒùz’~IOµôîûÙâÎ ‹Zð ç {!ľ4M¶Çè"CÛŒ‘mãoEŠmA­–öØèç­“ñd,xBwÏe €â¦d®_&¿`½ƒZ„EPÁ^PÒo#f>Xtò¥”Žº?}yíÚó5ŽÁÓvÒÖíܹîþM›¤Ã/ÄÆÓégÎ¥ôÛ¿M¯ã&¼¯ÂÛ"{k^xôÑ~ÿ»§rµß£Á_‡×Ñ¢nxX›ÎºÅò`@›ó\Ÿv]Gømp6F#Kd„¥§«§ œ‹qÍôwõúU í²e¨ŽÌXF‹OÀ*«Ì,Ï ×z»FÍNü+¶Ð¿]~¦xÞ ŽÇž=úØ»ó™·o·øÑ«ŸwÓ¯åõÔ1÷ï; –èÅÔ„‚Q 6ÚÃÈo ¶¶s[HkDûˆÀˆarí9‚ù–Æcë­«)ö·“Q2N’I²˜,%Ëɺd}²!Ù˜lÊD™8SÈ$™b¦”)gê2õ™†Lc¦©•à¡ÄXbZˆâ…ÂBãBÓ^´ïö’½â^i¯¼W·W¿×°×¸×ô4z?-Ážbxa¹GÚ¤Cm}ŒAÀ‚L0­«GM×X2ƒD&¥Ç¦1—Ǿx} Ïxíy¥Cl*ìœvãb‡Jw3Øá8°Ã‘hŠ=ù·B?àÓ&GnQ„·Å´ÊíO$ù#g‰ Ñ‘†ÈpXì­nk0‹âݪ“3¹ >ÄAn2 §÷ûK:ó$Lô;öÐ/¾Yòö’Ê—8th×îÝ[öl¿îñª•(xK›IdüËÿÛq#ΦßÞºíçíVÕzVù‚¢¼ÿìêG9ÿjlÇcCË´_ÀÃaëñ‡‡sÊñÄ!††ñoýÑíö0É‚Íú#2ÞŠñ•O2H²Ÿipô¼œÊò-è™/`8æÅÎt°T1þBE^G×v²àùÄ3r@ûK*Zz’É…–âΧTŒ/Æ2äŽxÔd·û˜_Spd„Þ èŒÁ‘ÙÃ#BŒ¦ˆH1mÁ'Å€-'C¶ZÅ­±Ç­í#‡M‘Ãt¨d˜ì[ “¢óFB†z™%Po µÐoX¦±gX½öèû%¨Fǯs£q_Ö‰äÊ‘*'YHÂéÜçÈë%ûÊÖ¬ž÷Ü´ÍÛºÿXväž%ÇÊWÝÿ>oï/Þ{õ®bÆá¤¤;˦O‹ñ Û³æÀј˜ãéés›Ç¾‘;Öþêé(.ëÀ¸ìÔ„ìAZ¤ooÄ’—IifµLâuÒB ¾gȲÞráÁÞáDÏr?ó;z?Ölµhoí'ìS¥`Y'‹ÁDÔ±›$b“`AÀ¦`i 61»™Œ:½Î¬×ë²:‹ztJ´–P —óÌ€gO·ãäI—Sƒ5ü¤/u½ö•¾ú<7úΈÑ|{„˺J\­[†Wêd^ŒÆ âíÆ»ÄYF=„3ƒcÀð/Í€ÅÔ;/ÒNúüEÜIݯá/.êýko'~‘f S…º?Ìd%°»Bâ½€£Y‘²n(j3Úl›p›ñ÷‘VSh¤¿^oD”>Æ€"l)QXÕ+ÕÌÏáey_ó>âmÄFñ«ã®š€ñ½;ØúËÇÿöÅ/Ö¯ÛI§á>ùnýúÑëô?i¾p¶÷ƒÕÛ~±Y¨¤wÔ¯¹×yà¥g7ÿ2 èü¾sçé³À§Ìõk÷7rm‹mP[#:4Î`gžRµ¸”Ú§kVºž%“éË8£ç4Π/ƒ®o®íèשºNºû®…Û}e^iã `>$=+W™‡÷‘oL=tô9: ¨Ü¸(B<¶3[lâú£QöÜf€¹Éf1ê¡P’R}Æ[Q„!-@…M5:ñ˜ P‰£0’–Ï·þëžm´¾úýÍÏ_•’{ÏïܰaÇßÿàß{Wù¶ÁšÇ9/Ù§b&£>V§7±›A/É’.V–%+J¢‹‰Ýˆ`B&‹)Û¤—‘ ÃÙ¤×I _q¢œŒ&SÀi.÷\ÖÌ´ûŸ7Óq3Óñ>’h ‘âñH’ Å™æ˜V+¥å&ÛûéýôB˜>Jˆ•FécMéÂLa®~ŽÉ%x °7^fÅxÖ»x*.~—fáߥ¿ MïákÒÅÞ×…´Þìž+ÂúÞ5$˜á¾0(Õlw¤=PÐQ›ŸŒü :’j£‹°¤Øt¾×ÐJTÈWÊX«%.*ÆêÏ‹ålŇÑ÷¯žý-râY8—£ô›ÀÁô›7—KÉt'm†tþ0Û–bTËò8ÄØhôk{|ˆÍÏ êÐða².мU!LJ µèÕO_$[‹üŠÃCŠÂòb,צ4—O?h-¿{Îó(ìû“ãçöLâ|Ù8Γ._ãÉØäSìSRÄ)ENÑ¥èS )ÆSfPfpfHfhfXæ°ÌðÌá™ͤYl–šåf]³¾ÙÐll6µµ·„´„¶„µ k oÞEËA¡8ÆÊsb u@#-¿®ž¶ÑýxzþŒ‰gL+Èx챨ŠÌB¹:5ïý°w¹°îKÏêOz× ë¾ªgwqÑ¢I™ùÞ<7 °ðG‰öƒ/AöcÖãæSF,ÈhšXW~ìÃR¹”.gã%¸JÖÏGóý£ÀSalÙ;àïN¨þ´tñfšøúQâë7Ó´}Û0qÁ,Úø”™á0 áX¨1êrª†…?V÷#lC˜[¸è¸ÓKëþÀóÏyâÞ'Ç30ÂÊ›ûw8/©þ? °X X˜Ñ{¢^ ‚ŽpÇÈMƒ=àb’ z"`É(Ëb²QF)>*6^gIsñ³^„Ô óÏ<#$½ÑŒCH°>ÄÐ8}‚a,Î cõã ¾~:ø sß((IAŸà½Ö˜YP XÄ~GéõvúÍ à¼zợ¤øž/‰ÿwµ½^ ØäoTg¿Í¨CaŠ9ÄO‡Ž„è¶Ú¢¶('†oqÜÖâƒCÄP_£lÎUD9ðŽÛC( SSUõv]¾ÖÃ’ÛõY3l¼0±O‰LQR¢R¢÷¡}xŸ°Ï¸Ï´?h_ð¾}¡ûÂ|çØ§ó‚¥ÉDœ®ðÊ1ökÂñÉ¿úõªš]Oá矟øLóo_»ù÷oñý;œ¼»òèœ-g&Ç)BÚ½õ®ú7_H(ì]wÀ¹ðÅýGO ¿åØÛ;ããKKSw¨ºÚ²NƒÚ7ý‹}2¯Ëb#´Â,6 3^•áÀg i³âgÐcb[l+ejQ7,ÃwL€.#:e$(¯kHQ¦Ä}jT 2‹V‘Ò ÌÔ]¨¢0˜óÐ2mp ŒY6‚Õi׿=¿ å@íÃ÷üñ$ý®§ú­¥ž×«Ú;š¶×¼q û|8븴ÿõ‰“6Ü[Q2æÏ^ühôèw r7¯®_¦„&ß÷Êij³:U´izžj5G ‹7Ûÿ ÃÖˆ ­~´áwzä©ÛâC‘lž"ÛlQSoS‹ÏÔT¾EîRl¹x•ÉÍÔðÁuè»û>þ' ¾8FÛ̧§‘»6®Ûø`˦µ;¯~Vx lñ¾œ‡7%îªíúüó®šÖäN!ãü;ïœ?ÿî{ôƒÚ>ìHRâþƒú5 æá X‡õx¬»¶«9ží_¦r9`m÷—·ÚÐV3³OƒÍ/—ØïáÎíÝ;§ ôÐÖm=´íÊ·×?¿rý:ùð½·/¾ÿþÅ·ßÛCÿHÿ^¢oâјi&‰­û";û‚½„ …£{XˆÙ@¶ú¶¶ûöH(²Ù¦„˜e9,Ÿw¥ª¶›s0'ž T>ââaߘFZ7m¸ÿîß°©÷ãÄG*_ýë•sÎö¤ÎN!ùí÷Þ¿øÖŸßV”έíßèôÌì²mìxV@-w.@Üñ~î±7èuÄ(Ç‘H±¢H²e1°ÍÐæ³É$JÖ ƒLŒÄŠÂ}‰14U´Ž 0F˜S†«µ9‹CÖ ~aáˆE¶ öé¯:¼[‹ìC’0«‘¬¼\’ûÊ'á»âºÒsï*Z]ñâ9¼ï:–ÕûÆÛl{Hx1À}€Vá•¿šß»Yºø—?î<*Ìí½úóû×m†=]ýš4É6Ø‘GÚýä=°AóÑ!b“Qˆ‘U¦ª)XMÁ²` މÒo·#M֯߰¯mçÎ6Ùv™Nüô:áÓ«øôGâ®nð÷]€Q ø{8ºöºá±PŽ…„†‘àa¬&˶Xói hQ›€,F#‚£-dÄpv,Ô}ò¤Z°"öÚk^¸KK_§ÎŽe5íX4îâ ½ß ëÕj™qàG2J·‡J±Ày±ž-Á„H’g4ŠÔ±x¯&:¨\û|‚Uܰ!Tµ…<Ùûù›‚¾7]º8ëÆ:¶#ÁhºW\)îÄÛЯ xŸô+1 a" ׇA*e‡Ñüœ_kh'¶1êIí1üšó8ÍÅÇÄ4·ƒ5:ð1j=躘ë:öM9öØ3j‹—Û"F·ÙZ#ÚãŸH 1¸-"pD„Ÿ!"pX4‰ð‹ŠL»îæç<&iÇ8쉨Q2Ö{>зaŒ‰=þÞ`BÕÆoØ´ãaúêºí_¿qáëíëZ÷Rzù2ý~oQóÊUÍkW¯lδ=ð@{ÛÖͻʣ¯=tᡵ‡£¢^ÙûêåÏî;‹¯¸ï¾«šµý_%®ƒ½¾ í³çùûú€&Œ&Á`†zÊlC6K°Ÿ±›Õâãëãìëë“mñ÷A¾†­ºÓVßSþV‹Ÿ˰6½­À7ÏŸ(êy¯ò2…³Á›(î×z¶ocy:L´,³z«Þjõ‰óóo-°ØæúYÞ–u8¹zÈ5Žm– ¿%M©ˆNz`ÞÎÚ;çM¡%§q!žrW5 ßM(.Þ½ K,îÙIjT_=²–C³@dJ³‡K( l«oÀVýqßv|šœnµ™¦‹HdÈ¿}é$¶¯^×òÈ ü²üùç“Úç>ûë«•íø«jnÙ¸­÷¬ll)›M_¢ŸC*9;£¥ÿsìwøâb¨éçØÃI°N¯Óƒ ²õGÐ)rD‚VÄHÎ3²’@+úº‡:áñz_àX2^ŸG¦ég“9z¹GßDVéó™«°¨‰£>&£{×ë{ŽÂòaqñã=ní ±œnàãϳgìôÁê:âµ!˜zà‹R°,k"³ŒlØ@r =b”õ’Hd–å\ÄNyºK­º¾™ó⛨…Ø #—=ô ‰B°z–6!##$gÃNë Ûe‰(O&¬žèÞÒïAïñü°Ä—åz¢EIˆïŽqžÀy8ÿmøR\ÔSNž¼¹ÇômÓ—/Qv[ IâSøw:Y)¢xH“ºYÈak§ø§ã@œŽçˆQ7?$¥äÅ#tÁºà9<耵‹Oò3“¹ö¤¡çCz¤gçCz&Óa¶”’ˆuHœ$E I:?³ò=–U­Q~D@U±ïà¼ô]uv€µÂŽž³½‹…_ª¿>¦òó«8{€¾Mø½ˆ6e‰Æ0œzzË7Ë“ØÙx tÛ#Ã5fó9!áܹÞwÙ=‚óÆ(áåÞ 5Æ5ýÌóþ¾Ëîohó#m­~í!(Õö|Q=&}–^ŒŒÂÛp÷öÛù9Jž=\¯Öx³õ¬öhc1‹ÉHfç(ìÌúGb®žÅÜC:‚ØCälÏ5Ýc¾í”.î¾éîØ-n翃BBùªÜ]±ÐoÒ7(RÏÿ$èüæÇžïÿ!ö[* 4¤ïë‚yºZ:|À_á!U„Å ¨ îWÐ!´­ÆWÐi´m€}Êþ7F×ÑfÞwA…è: •ËÈö›Q-ônï,¹­†žQ î@»ð´ÏÃNè´ªÐqÈRÝh<;¡'F6ñ¿Œa?qð)F?GOaÀUx?¦B!±bâ$‘¯DYÌ;ÅO¥yÒAéÏ•ÇË/È×t«t‡Àׯëw Š0|eL46ß3ɦ¦Ÿ™Þ6 æs¾¹ÁügŸRŸ=>ù.ð}Ô÷s¿¿r¿]~]Ñ2Ëò†Ä$”u™jùÔΓfc+Tò"ôaß>¼öa‡aäB­-À8·Ö&ÐïÑÚ"´×km ™Avµ-#_´Wk³S×ßimØûq­ícØÞ×Ú¾èvcböd€§ãÆýZ#Å´Hk HojÖÚú7imÚkmØ™˜^ÑÚ2 7}¤µõ(ÚÔ£µMh‚9BkûøÇ™çhm_Ty_Ž»~eCõ’ªFedE‚’š’’¦,^©dW7z\ŽÚD¥ ®"Iɪ©QJÙ(Rêò¸–¹œIÆ\×=ŽYMJE•£n‰Ë£8\JuRß´¸¦ºBqºkÕuÞ1eŽ:Rä®sg»ÝK‡ö }žåjðT»ë”Ô¤´4õ{5`d¥»iöªë'$';¡YS’ÇÝÔPáªt7,q%Õ¹óù0Æ­O$e¤ÇåR»jÜË’”Bˆ$£±20çPTÊ}ÐGÿäÑøßY²r5°¨468œ®ZGÃRÅ]9”ŠÑ8ÃÕP[íáÂè*Wƒ ÖZÒà¨kt9•ʦÀS¢ÒèVu+•zÀ&¸7‚ÀÕuK`• `šl¬riˆ;**ܵõ0œ h¬ê’«ÎGsH¢€˜Sqx<îŠj¬V4պꌟÊêÀx$£È'(eîÊÆå€ytç¤ÁUßàv6U¸8g5V½¸©ÑÅy4!´TQÓädœ,¯n¬r753µÕÚBl|ƒ %mòÀx&N¢RëâRsýzª¬‘ÈÖLv7(èFW«šøC–fÌÙzt£_hy•»ö‡˜*›ê`AŸèt+w¢âiZ|«¢‘õ¨×€I2*ÜuÎj&‡g‚ÑX¯‹ÝË\\ÕŠ8}FPçn5xÔ^¦•ú~ Pß)ž*µØ¥¡l€‘;Éé®»hPjÝ ®[Š­4®¬wU:`¡$•©Áok+ýZ·³º²šš£¦L@ÔátrÉUè˜9€¯¦G_ÈéòT/©ãl,©YY_åa“˜…:*€ˆ‡Íðò㺒jqN0GÍCˆhó¼¼ôSëjV*ÕƒLDjp±?oæcYÃÃÀdºñºˆ ìÎ¥ °ÜÝàô(Ñ}¾ÍÖö¾P¢™ëFsØ@;…šÏ,v71ªM &Ä2wuc®à5Š£¾\̱¸ÆÅ^¨òå!Š©r4*UPtÕ Æ–ë·p§ÒTçÔŽW¢U J³w ól®:¦(‡RÃ"ø‹w`½£b©c ¾Xçî‹ÿ¼a Z ‚°èª©dLMÍSòKŠË•²’üòÙY¥yJA™2£´dVAn^®UÏщÊì‚ò©%3ËQšU\>W)ÉW²Šç*Ó Šs•¼93JóÊÊ”’R¥ hFaAôçÎÌ-(ž¢düâ’r¥° ¨ ˆ–—ð©©‚¼2F¬(¯4g*$ ¸JÞ,6¹ljVa¡’]P^V^š—UÄÆ2t¦—1Œfçf•”+Ùy JVvažÊˆ’S˜UP”¨äfeMÉ+ë_„ ÓÄ釃M˜’WœWšU˜¨”ÍÈË)` À± 4/§œì‰BÎnNIqYÞ3¡Æy—…LÍãK€Yð/‡sÆÅ/qò’Òò>Vf”å%*Y¥eŒ…üÒ`—éf0gžLyÅ¿LG¬ï‡Ö£ØlMÀܼ¬B XÆØøÁX°®¼®úFfÛšs«á‘‡R5~&r«Uƒ˜ð”:p\µ7ÁžÁ³xæQ#\¿s±”œ¨…_>Àº!©á×¹ÌQÐÃB ø‡›“åÕîékÝZÞó8j`1˜Õ7 ⥣¦yúØìPÞ„XßP S–7T7B0QMÐÛP½JKÅ Zª*[e(ÿ .O=dªêe®š•I0¶å3ÎIu”[µšè¾ŠÆ ÞÚ¨,áÄ 8eIŠñ'ëµäåÕK«“«!F­Hª¯ªOÖ%ÊJ¼­D ¨-]G#RÐHTàž u~ JƒÖb¡ lÓÕz#Œv!ìe¡·ÕÁø$he¡ø(¨´–‡?¹àî‚9Ëàê„‘F” ­{€Â,ØÓ(0» Úu0ÇÅg88}¨ÔÁµÆ,ºÕ0NùnX×Áß ¥SÆ©0 E0ª¾Ùðu£¥ÿpÜ?z?‹óïUÝœ§T" >çygÝšf%ïUiÔÐc5‚|`w˜ ’©ã—Áø$ç†{Èìâs8:I@ÃsòPó¢åÕÚµÄÞ1 ¸¸&]€¥-‡±Lgÿo4Átj¼åÊ*rh äù‡VgD£ÿ¶úÿ†%ßí~™«5þÞÁu\ËQ] }nÐì?â…I6ƒÓ«åÔúmP¥]Åß¹4¹–ðU긅99JþÖÕ·šªaÕš9_nÎaŸ_¯Ù¹º‚¨6j®æV¡ÊR¡!í¥ÙȹlãUÁ-¤^£î¥ÀF«¼«–äâ^£Zpô+‰æšcsüîá|UÀ‡&Ÿjƒ`•µœJ#ãŧZ5šìã±æçŒÿFðÕÎÙŠý˜°žz¸ºa•&Îg?7N.A#·µÅð¶‘¿õ®ñã+$j¾Tœ5q**&˹ TqŸoÔ©å}%òÒod•*·MÃÄÚaíZ®O¯®ûý׳DŽÄ>9“yÜQ8eÕTÚÕªƒµÿÓR{‘S¹­ï³èÆ!V×/ÑrŽGí?µ‚×*y̬Ó$t XÑɯlD~gHÜ#*8=uÌ@;®Ñ¢¤WC|m'ç¸Zãt÷Îrm–(ºydè×ÁÀXÔÀ#Ëš7xõúJ?bcÀÀy —Ù¡ijq_ÜöÚšŠ†É?¡O7Ï1ЦûZ~ïÿŒ.Aòzž·šDIƒú©¹ “•}ü×rï«æ¾ìhŒ÷F-ê©=*§ Sç´:oþb«¨x5Ÿç•ÈÉ9eúª€ÆǤ©ÒúÄP·Õv½k ÅÇóe㜃,ÌÁut+~š“Áë ÅåV<&jz¯áóª"ª7hÈÅù«D×Ûãé³L¯ß Í".-Þ¹i`9—ÊÉçGß"/F÷É=tïͺѬMõÂ!yf1÷{÷^›4ðjb¼­¾b.´‚ã\§yt=|Ô,æà‘ÕÕ7c þUžÚcªx¤WøÝ£ñèâõãö¢Jw«ÎÞ6ñQƒ¾ªÊäêð¿ë³=½9»ßë¼Å*ˆš¾¤A›1˜b=·è¥p]¢iLÍ‹uÛ¡õÇÿˆõãR-Ö|¤QË‹•}HMEy|T Olx*G³¡ž,åï  Oz®ÞÌ‚§\èÍåzÉâoØûhÍ(– ™œ–J£®Œö\èa´þÌž¦Ãøb Åææ¡9|< VÆG–rÚEÐ[÷Ÿ­:÷ªœ•hZfí~*I–* ÿY}+—qù á£pùË¡§œë& è{ézmg §PÔgG3¹|Y‡¾B6ÇPdxö, •ŽÓã<—¯”Å)»¥$^jƒµs+ëð®0…Ë—Ç‘*ä£ËÇ<_Ð×£Úc—5GÃV¥©Ú½j…ÐÍá22ÍÞ «æi6•ű,…ê!Œÿ~)T diל˜õk¿XÓnNŸ®K¸•ý•ÙÜóø¨,®ë²>ò¹ÿiœÏ`a^=ÎÔ쳤³ÁøzýÈ;*-ïÚƒ5˜Ëí©Pã°¬LW]y×*ø~§±/nÎÜ«Çþªt`ý™8 Ö¬Ô(<…­2®¿WÏjÎêßó ¬án•¹¼»dµ¦ï¯~½Õ‡»Õ½ÑÀê×ÉëtµôôU%jþp÷U&ËùÛþœ®îkùˆû=_W•¬I›1”–Z_:xµÀVóÜÍŸÊPCwˆõ<ß««,çíF­2aò5icYÿª!»â†!»ª¤¯,ÿÿ®ïzmOUÍfõd’F·y÷gý˜0ÔÓ­Ú!Zï·>FmZ‡2 – àÜ©i\=)ckÿçkÉï¥ðMæ<:yå—Ä«ðzè\Qª ¾¿Ý…nñó¼ÐŒíœ/e…ã@ÔŠ\›ùÿÕA¡íϯ6dƒ«•·-üê‡vÃÕ—·}}1EÊŠÅ>h <™Q,\M(®FNÏÀGé‘/\u¼-ó1o‹¼Ÿð÷`û\J(%½kH%7)¹‘Jþó(ùn ùöúVé[J¾=)^ÿf®t}+¹Þ,~s-Núf.ùÆ.^‹#ÿ:Yúû òu2ùJ¾¢äo©äjù²•t‹Ý”tw~Áþ½øÅòù§ôy+¹â$¥ä³O‡IŸQòé0ò %——’)ù÷£äÒG¡Ò¥ä£Pòa+ù %Pòç÷¥?Sò~ y¯•¼û§@é]Jþ´Í$ý)¼³†¼=\„‡‹È[”¼ùG£ô&%4’ ”¼AÉù¬ÒùpòoAäuJ^k%ç¶ÄJç(y•’³kÈ+”¼LÉK”œÙí#uQrš’S”¼HÉI w2€œ0“ã8*§äÇæK8JþÐ,;+›OŽÙÅ£±äJžo%-YÒs”Û‘äY u˜’gœä“üÞ—´‘§)yŠÚ{Éï(y’’ßÚH%O<î+=‘J÷%°J$¬ä7Ž–~³†<:šüš’ý”üŠ’}{C¥}N²÷—io(ù¥…ü«‘ì¡äXäJvûö]IR;%»’H¬ßÖJZ>*µRò0ØÖÃGÉÃÍâ·b¥óÉN»¸ƒ’_P²ž·%Å’£%‹<Ò>@¶™ÈVèØê$[´-±ä+ÙLÉ&J6Rrÿ«t?%¬ä_(YOÉÏ­ÙÒÏËÈ:JšWµ÷­‘ÖRrß²&‚üŒ’Õ¾d%Ë)YFIS£Yjò#MÙßͤñ¤è±]l ä^Jê)qוIîVRW;Rª+#µ#I %KSÉ=”T§’ªdÉQRI‰‹'%‹#¤ J#‹´8‚8(YDÉBJÜe’ø’ùN2ïr7<Ü@î2°è9d6%³(™9,Tš™JÊ))£¤”’;×””bJŠðh©ˆ’£dúH2­ Dš6Ž䨤‚25/DšJÉxšâ$ùð””ä…\èÈGr²­RŽät v»AÌÎò“²­$»S@ð”e÷•²üHV'> OöL³d÷%öNÜ O™fƒ”i&™ØnwŠwP2X˜|ƒL¢dâH2’ 8ÃIÆ “ÆO'ã(;:@KIútr{J˜tût’·4JRa`*%càõ˜0’F’¡•B’ ARÒQ2:Ñ_@Fw lÙD‹UJô'‰ŒÝVqÔm±Ò(Jnƒ‘·Å’a‚”@ÉHJâ)‰ó#±AÙRláGb(‰öó“¢)‰RFKQkˆ2šDN'°r%Ã) lÃ)ZJÂ( ¥$„’` œO‚GKAÙ$0À"Ž&âãüˆ æÛ(±‚äÖlb,VbQ±óó5K~~ÄOÅÎ×Ç(ùš‰¯Š`çc$>€ÝaÑl ff[ãD%FÄH‰!ˆè-DG‰ ¤eJ¤B@8rƒÐ!L À£ ²܉¶áQÿw~Ðÿ6ÿßáè¿ßÑú$ endstream endobj 91 0 obj 11979 endobj 92 0 obj <> endobj 93 0 obj <> stream xœ]“Ë®Ú0†÷y /OG‰oÉABH‹^TÚ‰¡‘J™°àíë~·•º}¶gìÏO¹;îã°”_ãÔ¢.ÃØÇpŸ± ê®ÃXh£ú¡[òHþ»[;eÊ==ïK¸ÇË´^å·´v_âS½lûé>å—Ø‡8ŒWõòcwJãÓcž…[U›êÃ%íó©?··PJÖë±OËÃò|M)ÿ¾?ç ŒŒ5Uº©÷¹íBlÇk(ÖUµQëÃaS„±ÿoͯ˜r¾t?Û˜Bu ­*SmaWƒ­p½;òìÉ\ Û-¸á¼¿ 7¼bŒì¹%KîG²œ»#Kü^ØÀïœ×àûëŠÎï`úר_Ó¿‘ú;œ¥éß¼éï ˜þwÔô÷pÐô÷pÓô÷’K'1ô¯÷`ú×âC'LÿFèïoè_ã^†þΆþuÎõGL®?œ ý½0ý Ü ý­ÌÓßà{™\ÜÑÐßÓ߈O®¿œKÿ´œ8×_ö§ƒ\Kÿõ±ôoðlöG®¥¿ÇÝ-ýîhéßà{Ùü~P+›ë/ûÓßá\K‡:Ø\xZúû­<òüšñÜÑÚHuS IÓJï k†1¨¿=O3Òä÷¤ õŒ endstream endobj 94 0 obj <> endobj 95 0 obj <> endobj 96 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 16 0 obj <>/Contents 17 0 R>> endobj 19 0 obj <>/Contents 20 0 R>> endobj 22 0 obj <>/Contents 23 0 R>> endobj 25 0 obj <>/Contents 26 0 R>> endobj 28 0 obj <>/Contents 29 0 R>> endobj 31 0 obj <>/Contents 32 0 R>> endobj 34 0 obj <>/Contents 35 0 R>> endobj 44 0 obj <> endobj 37 0 obj <> >> endobj 38 0 obj <> >> endobj 39 0 obj <> >> endobj 40 0 obj <> >> endobj 41 0 obj <> >> endobj 42 0 obj <> >> endobj 43 0 obj <> endobj 97 0 obj <> endobj 98 0 obj < /Creator /Producer /CreationDate(D:20211021215143-04'00')>> endobj xref 0 99 0000000000 65535 f 0000134892 00000 n 0000000019 00000 n 0000003874 00000 n 0000135068 00000 n 0000003895 00000 n 0000006989 00000 n 0000135230 00000 n 0000007010 00000 n 0000010842 00000 n 0000135374 00000 n 0000010863 00000 n 0000014259 00000 n 0000135520 00000 n 0000014281 00000 n 0000017931 00000 n 0000135666 00000 n 0000017953 00000 n 0000019967 00000 n 0000135812 00000 n 0000019989 00000 n 0000023649 00000 n 0000135958 00000 n 0000023671 00000 n 0000027643 00000 n 0000136129 00000 n 0000027665 00000 n 0000031685 00000 n 0000136275 00000 n 0000031707 00000 n 0000035882 00000 n 0000136421 00000 n 0000035904 00000 n 0000039048 00000 n 0000136585 00000 n 0000039070 00000 n 0000041953 00000 n 0000136907 00000 n 0000137072 00000 n 0000137232 00000 n 0000137383 00000 n 0000137533 00000 n 0000137689 00000 n 0000137854 00000 n 0000136731 00000 n 0000041975 00000 n 0000044425 00000 n 0000044447 00000 n 0000044645 00000 n 0000044961 00000 n 0000045144 00000 n 0000061026 00000 n 0000061049 00000 n 0000061249 00000 n 0000061940 00000 n 0000062467 00000 n 0000071841 00000 n 0000071863 00000 n 0000072060 00000 n 0000072582 00000 n 0000072947 00000 n 0000080529 00000 n 0000080551 00000 n 0000080745 00000 n 0000081148 00000 n 0000081406 00000 n 0000089790 00000 n 0000089812 00000 n 0000090007 00000 n 0000090388 00000 n 0000090622 00000 n 0000100283 00000 n 0000100305 00000 n 0000100508 00000 n 0000101113 00000 n 0000101556 00000 n 0000107516 00000 n 0000107538 00000 n 0000107737 00000 n 0000108113 00000 n 0000108352 00000 n 0000115067 00000 n 0000115089 00000 n 0000115281 00000 n 0000115786 00000 n 0000116129 00000 n 0000120592 00000 n 0000120614 00000 n 0000120810 00000 n 0000121216 00000 n 0000121475 00000 n 0000133541 00000 n 0000133564 00000 n 0000133761 00000 n 0000134314 00000 n 0000134712 00000 n 0000134837 00000 n 0000137973 00000 n 0000138094 00000 n trailer < ] /DocChecksum /0DC1D785EAC9EDFB93739662C3A6ECF0 >> startxref 138335 %%EOF cfitsio-4.3.1/docs/quick.pdf0000644000225700000360000070665613472024437015236 0ustar cagordonlhea%PDF-1.4 %Çì¢ 5 0 obj <> stream xœí[Ér7ßú+êX51 bIlGKÖB{ƶD:|pø`“4gbDj¡dË?/Q¨ª»z!Mi"Ã!5¼|™H ^7R¨FòùïÉÅâà¹oί²y‚ç‹× •*4ùÏÉEóà•B£¼ÐÊRsüÛ¢o¬-}ã¤Ö5Ç‹ŸÚ‡ÝR ë] íãN §)Æöð¸ä!W*«û]·4’DÐí³N‰àUtí»±ø?ÜFG‡äI§£ˆ.˜ö¿ÜiisGÆûö-×4.FÓþÂI2¡}SòP¬# elûã#µ^Ç;ÕžŽ™gœ *ÐÏÇ_cêX ¥D´VóÜl z—øyŠIÿˆÚÚ‡¾¤ˆ^KëÚ))¥¢œL¹UˆŠVN»Ø^`V:#Cû}gŒ uÖ¬ª¢Ð^v<¶Ô„…òúRcuP7ž‡SŠôAhCC¨³_t$tÐÆÍMiéMªÛ,!Gè|a•¶X¬JÔËÎ`eœ²XA4§0)ŪKáÈëÛ?yRNïZ]jȵ¤tÔš17 G‚ðäzáT°r.ÅóJâ=dñÐ;µ/y³<‘c马ƦkaI“M+% ¥ª ¯°¤}ŒÃª8 ðŠi5 É.ŽÿþS«ºeÔ(¦19"Iân‘zhFøÐÃë 1D€t )¾$×4±zcò¤³BɨmÝ…HÀû%O;‹‘†6,,aX „i54¦ciË\¶'ÐW™äŠV°W ’4*úH>á8ËÔ'WKZõuŽkÕ=TN¹ zøÈôX,q­O§Mê2ò,5³Œdvõ1CÇ€l=«cN¦E;ÛçbÚ︹Ғh}!ÍÆ…ôÑUÆ…|Ä}YcÚ÷¬&‚<ú iY³™p” í«2õjñÎx,šÏ0Ж2x¬qiï1oSgUËYz·n}B´iB…¿¨L(¯¬öaXY–meeó¢¦ÉTEÌç.`aUû[j%N3¨À>ñ gL!Qki¶ÎÊÕ³‚Þ†Zo—¤œð®Y*&É2KÛ 4óÞÖe,v@yï¡×Ì_Xˆ1&1<¦`ù'ò9sƒ„!J/yÿˆ·ùŠw2™ž\}èèmgÕyð˴Ȩ3¨Áz<ȶD}¡U$­4llW’;+\§î'6ÚZÝ’iV’»ÊwTe̘ªO(WºÎ&Uj$ÙÁìLP¤ Šc›½wÖ–m~‘tRs‚“ÃÄJ4¨+C†l¨p”±AѶêa¯/:¹¹_ØUò¨àRõkH”ÔÐäZïúÎ0‹ C¢êå‹–†±¸¸@âžad«Ã=žÖ’ :Þ çcùVk€Êí¶Ð’)€zÚéö+ì ¸ù¿–ØBc´Ñ 7¿³c†|ýZ©´ãƒŽ?õX¬VÜ#”;šÜv+õ¬» šëùK/9·ºÕ!x~CRäÆz D£Âx|z2€©ñ탎GÖ.Ìp‹Á]1Ž9†dÍîå©ûU‚ÚX¥‚s5•Ë ²£^ÿ_ȸ›†mÕV’¡æ>€¹bU–Ÿ¤¹»æ*Ì™«yæY»ì^gž9õcWzª~‰j²jW©"qká<649œg<ŽÊ9œG´%œ·ÍÁ.F«ô_õ²À¬Ÿ;Z2n-•šÆ×ŒgDGrç¯G> stream xœµ]Y]Çq~'Œü†A^r¯¡9<½w ȃì8¶’ŽÍŒÀ !) ‘j¡læ×§ªz«Þî½C1DΜ­·Z¾úªºõýÕ¾‰«ÿM?ûèñŸÝÕÝö«ßÃw¾$è«ô×ó·W¿¹‡„¾zSÚÊ«›—âÛâÊÛM_Y#6©¯nÞ>úëA¯…nêðõqßœ‘Âëû£›B~:ÊÍh©Íá‡ãõ¾+µ²‡ûã5< ‚V‡Çk ÍHêÏá³›wÊšô¥¯jÛ¡±¯ËmwZ[h(¿òß7ÿ†½ö0Ž-ìA`¯% Àuón~ý×à ´º9/vuxu¼6›Ö:ø¬Üœsêð#ÜvÛÂNåÛÐUé·}w:¥á¢{šï¿ÅXëáþ·åþ»#L‰1ÚCïá£;ÎÅØñõZ|CC×~‚azoáþ½Ò^êšÝs{Ri¼¨\Ø´’éuó…“ìw>Ôú›Üîûüf8|<*º(àMƒCTa‡þð=®œ”ðœå#/}~T®…pøŽ=Yšøˆý0›G.`ÜÎò~ÞI8`­”’fÌ‹m‡ÏýÌ… ø¥Ýú 6¥{wð²õ[ðîðÛ#J‡Ú-ŠÈñÍ Ü÷õQöqú]í–ú—VY WVφÔ³‡<×ì­8×» ×Ëúį¥^:áù8Z/…Îß‘6KH0šµ–¿£ºÎú :µË8º=âÌ9ë@-Q•ÂnW€'Ð…–רïêD”5«¢ÃÕÁ‚hj¾öi!½Ó«¹× <»ÐLœA¤ûÆHX›Ò§¡Ïbw©Ï$Oêâð:ü¾åÝ&A‚K÷KŸžM¹“¸GxßYèìv¼›D¢ÊºðöíY6¨A÷Gåq€êðsÑ›ª_ìë0UFxX˶ ³ šà$eÎj’ÃF[¨ ¨elìiÔbß‹rOc#y—fS2‹{•ž(dn¢º™]nb÷y)P‡¥P*‹]}R%˜=€Káì&Á61MHÖŸ—0Iµ#U´™B½©£bGCRN6½Ê:—'Ô˜¨pyÉvÛ/6Š(|ƒ l•÷úÓ`iÓEíQ_“ì{ç¼ FòXÓ/qÁðƒ!­R¹K©­Þ¬—gdÀï4&hÚ‚—ƒÉýÈ,nj_í’IbÖ_ÍúKüˆ¥þã¯C—;ás9˜ÙûjÄ’5Ð=§ÉwhŽà×^ŽHcoªœ=ÁÕÀ>·V(Š¯Þ¼*æz"¨®>¾‡†`¹WefẂëÝt2ÃZA'­Þã”´j•¥öM‘ÕÒ‘•=Nýníqo%q=’<èàxßìÞ‚º–cˆ<ÏÖ2Êø³º”Lãp>Qp@{ÄÚ3cŸÍ:N¹qŠ»¬„@ ÿ$Bx§Ý7xÝ“ñ\:­L‘ÄÅ3\ ¨¼Fª¥5 5,+6üº6œ~HÓ0ñfð-°wNö®¾™¥Shâ[’I NKØ,’(öæ ¤›¿'ÇŒæ-N«ÖL¤ª!|VŸd¢zÛ’ø&ú}}~"¡·­)Kj¦@%‰#`µz ŸÓôdv Izš tÀ§Lò·&£{ú:58}kŠO0ÛPIV˜=ðG„Mèôýá›c'·ËûOzGù3ZNÀE®AÒÌFO b½È„£¢‚M‹Ïtp¤Öl÷“!ãÓø™_Íà]@3ŠÊq…Ð"€:ÐA\S&üo¸Ñ’ ÑõrÑ@ˆFÞzàÃPÜFÔÃfííȶ¦H I¦±6ß±98)gË2 ÎÞå+¡)¦cTHg¢˜ÇÁuÞц£òt!d+f!bñjgkЇžÂq҇ǺS&±Ž1¸ëÌ$z¡Ù7ªÅJ8¯v¹ÐM·bþø-áa¡aa(©&BúÜ U"ßÃÃýqe+Ç>2˜dxGoȨßl€dÒ°õˆÚ'°^üôºóÄÌÈT„?º^øÀïœÅˆoÃC V ƒN5€}³cºaanÁƒ†¶'}žÒŽlþší,Ó–ì8h.£%—ák °Èg'&\Mè³Ä ¹àgS«‹í³á–™~˜™QAQ~á;E~/@ØMÀ,+±Yšìý79SCRßUZöÔCf˱yÉå–-ç;³å»)‚¥Á?˜:ÇÄ¢¸;ºÿŠi)¸lº¹Êð|Ó}¥läÐDqïjˆÂm¢t,s¸†Àb(ÉÕaÖ÷itË,öŠÌJç,s/å/Õ %)¤\že#mò~ÒEî¶&I¬’’é´+Ê7D#zô©H§ì|.pæñÁ3ÜuN9Ÿ—VR›s‚É#NÑÒ\h¾ŒŒèy= x!0&2 ½5äÝl¯Ò3hk&„'÷bÊÄþ¢,;³[*|A{Ú/d²FƵ4ÆR±²A³Ñ/?oP⻤¢Fµ%Í=Ím“Ðu,§'KK*Åúì; óRáç@†Æ Õáéa ·Ñ!áŒ{‰ïÃ'Sb“Q’y€,'Tß-‚R%™éËÒ €Ò T °•u˜iŸÒ–wÙëÜÁ\Â!¥=H€‰©30°U”ŸKϲhIÏ‘t4ç=;íúÁ8Q é¾&æ§%Kž–D"¬A^WíäÒ’D[{­¥&eœ‚Šú̼PàY¿x?6‡Ñ‰>Ï£•TÛÀ–o–jdŒóŒ%¼[ES¹þŸ½‚–ö^+†ã>‰¹a–Y*r{ÓåÈÈ0›“ ¢}øêHÞF‚ §s&9“ Í]ì¨wŠh" 30ø-Æ3<û=ð…•/ ¯ß,oÄŒ&þw’šl²”qBàxbûò”~tÉ–-8{5rG¯ÝZD©É">ˆ¯ÆðèÎn·ÉŠ8 e¡a¤ÒMè&wr òé4Ÿ?})‡GšÓo4Ñ’çFochˆV¡:“€âMB#bSVpºM«D£Å•sž„$¬ïÁB!zUü˜ o²FU­È[;Q"Ñ úWµ‰w6”9s ˆÌã÷'ñ3}"a“8-8yÑgñs¤™~ÃÑC¹±Î]Ñ ÆåÈIŒD ¦­Àü/¡ ’ Ïi ’¦i¨/¸Ä®IÕanƶåÁÇLPT6GXö—FZ§$½` úŸM”±pë´–Qi‘WSßB‚ ˆÄîE°±£ÂR>é(€]´±§4‘X)4ÆzñAEC×eHûîy¼ÇÓ9yLO¨÷qÕ[·°â€qòñã¬(âþhšÇÛJ ¢ëlʈø<>üÕFZ•TÈ•¦R©®ÛšA‹Ãüë«^X(Ï 踱àö¡3ˆey¾+†„Šç´»”» XÚ€ú‰“. %x*×{Ì ›¢u¡0(“™ïÛeb6qRÔ4›†…`Ýw+Ñ'D ±oɺ g'õ¬©Ìà•Z¾âϢ߂tQÆ2m0VNƒ«Båžé„~ä<ïV²_á×y5^¤20h™1ß}Ñ3­hºÅ $“è™6w2Ä ¦ËÜó˜+›æXÃÏ}uJàüϪ”†„AÇaÔ&&\G“!ªiV×”ÛÊùmEð–{ÝØš×’{λc—GKëû ý6„™¡U¦e¤G'\s7­ûÌê8ÚN˜´¤ÕŸ@•1®1—ñÚhÅ#,sŸ2 µcÜXó·jºÀf–â‡.Ç.¸œÍÒBvTïg¹h#ˆ|G»R‹4c¦g­¯?E#!‚J¦†Ý"‰%ÇTÆå£å«XîÜ¢­¾(ðÒVQßsµ±‹ÜÔG[×qÒ§!NGØ™˜øÂWG,¼<}üÛŠY¾Æ)Þ0·õ5ÖÉ͇YDE¥É ³êÝÔ± Û ¼ÖdUkpŠ\$|—µ=ÖS2£kcJÉåÏ™9¾iJ˜I°¨XòØW$`Áº˜]3€ØâI}éåy3e✈£BqÓ ŸÆ·%Ú¼®:v¼µÊ«jÓXÌ·p©™©Šã µ@¢•ï=næhJ~ÁcèêæšC6§ä RQþ¦TÔ/HXÙ G ±*K“‘Ž›Sx‹´6ó) Ëåµ&[|bb (Ë¢Ž›NúsÕ…&ùý^!Ó>YЄehQë”K@}/®"÷dwHž-MJ¯M¹›¢w+ŸÒçÿ ´~ ë_ žþp”ñL^·ƒ—~ ú9& dS¿96iðîL|8—ÙT.¢AÌÒþ¡„rµoʵíXªsV5¢‰‹\eƤæLr%;jÚ¢Í6 Ú…˜êKj:í¸—éE¢Ž/aN]Ü Ü' °eÅ'Y6‚yƒ³"˜÷Š 3!oö–ÇùjxÀt ÚõU-GöeQ4cßÚmŸµ^#%;ÿÎØ”ÁÂg—„\tÖ€ŽòK% ³Zˆ¾ºOrŒé¶Ù†Õ®öý?«U×ÑZv x÷” ®<È’L{'E †½žb\éø×;31+ˆYÆÀ¹ÚjR—q£é\e™vÛr¹*f™IåýËòÿ4ëLèÙ>&Æ.rÆ›*l$ù†Ôü@.6¢4Ü÷“žòo1©ãí¿¡  •6àO_bÌusœBNåjr7úð?c¬Ê•èÌÑ9”¬1å+{†I Ó–…Ñ€ù9 LÕlj ®˜ÂeƒKÖâ5zÉuÁÖ s… X o g_W^oíX€œ° ¶™Ê?Å"ᤈ DQë¬Á-ßpÃòð¼6[jªò4• z>×SôÑÕP>|éOqw‘’ A¾›D<üŠ;¥ö¤¾H´žž(lU/NT¬°u¬ðžŠ½îU)žÿ»8ß}wîÄîOXG^òÞñù5ZÄJd` ¬¬Ús¢ÉõÛ?X\‡²ÁŽ*hY[0ùžC›kŒi³Å -PYÔ™•êŠV0®(àh¥îª)^ätÝaµ0K?/›mµ™ÑÛTÛ²]qÕî?…nË»_gûï#Î*§ºý;4„©ÿU7¡ÿå˜w¦ã xփ‚p³{šµ†厛TÓ|tótäY| ÏdyÁGÇGi;>:&ªŒO½­í}[.²ýø?åÛ)ÏŽøá8Ù>ÿ®\¬»ôg;éKÄÛ‘KÍÙxÄ]ä`¯%(D§½6¢ðñ¬^RGc&F!2öбM‰1t'Æ6-ÅY±qßDP¿\_z%ML¼5Å7øeŒ }ý1)Ÿu åËô×,C¼ª‹Å™á”òAóœÕë öµt1þËÉ8Mç…¨ˆÎ齨Y¶Q2"ź´—fÛŠË‘"ìbü3 É Àì˜YSµÝ™òßì”c»ðÄÄv^Þ­ Ρ"`x#WŠæÍ¥-a°2l»š‰vÝ¢ÂP ÞZjЉÄØ_]haˆ†Ñ25zwl*í¹¡m´ã’Lg)AfŽò´ï€ÔL?}•[hw²‹MÅD“Ô{Ÿ çœ.çÌÅ©²ž\K_Âè.ýÇ>µÚÀ‡9€}g@ƒÝ.Móó%:eF¢‡!]zožª‹zñkÉ™œ³øžñ­LÏô£«ÆCO¤âؼ&ùÒŽ */W‹ƒÃBnk‡KJÂÌ¥üî¸Dç92 „É©–2™¦Å™FuIÏœ±ñ®ð¹,'2EÏçE]m,Éý.…cjZ;|)Àï§‹o½¸¯º5œ6ÕÒ=ïlq[G÷Œçw²SX±éö‰lùÅi¤LRÄ):—&ŒåÊçèA˜;¯ u®½£cr–[b‰…N: ‰­¼=n78yDŒ p^]?Q‡\ù̉66–zÙ;ŠÍʾR©¥ØÒníOteTN-}?×Ñ<å SÍãÇÖÈ$á/„Qg:º2‹ØlkCm9ý&Ïý%Aiþb®uá‰ðv K)&Õ=¤™Ñãs9©0ºw×ÝÙ0-§ÖŸOÀ²Kñ6±næÁöò"²?yºÝ·Þ¥8îKçÏÃ4}r;vL« Œ½ s¾f°y]MÓ,C8!ŒïŸÊlüÞå]Þ"ßhó-CðŸFëwò¬Ï¨ 1#ÔÒDÇ…Šm†m³0(Ú6Û­šó`'a}2Ý4ÒÖtg;,g'äôÑ%»òîpaÖ"mãA¿Ÿå¸I,äìS9:@”'ŽÓž–ÛÕºŠš…dô8¿wDh¶ƒíÏ’œÁ G1a¥l%¸ÀE9‘Rò(GYÊOY’–©€ÿ3Ùr:úßMN[¢ƒ´¯ÈS¯ZsÞZûž¼®¥üm9˰ gñç d›–RŸ*.FÓ›TbÜg†„ ۴̸ۇ€)1±Ê·åé©4t.j'élO‡ËûÙ»sŸØÆ©^Mršýö­”Ѩ‡üu±ËYb爛[܈YÜ&êÿQ íª§6®(V‹Ô&Là"õÀÄ:¹«\ªOtõïný þý?5·2‰endstream endobj 28 0 obj 5961 endobj 34 0 obj <> stream xœ­[YoÇ~'ô#ø¦À;ìû0à‰ã$±hm )S„$.mŠ’üïSÕguOÏîZ¤ Ë«žž>êüê˜_NÙÌOþ›þñîäì;{zuwÂNÿÿ]ürÂÄÓô¿‹w§>‡I\r5KeÄéùÏ'ñm~ê̬Næ³P§çïN~؈i˹°3—›o'6[-¸S››i+à]¡üæF•°Þ›ÍûIÌõæÅ$gnç›·ð‹qÁUúÅ…ß\—_d«i+˜-ãämòüž[7[e7ßãû’9“6w¯ËFé%nTXÔÂ-¥Ü|=q¸„ƒ•þ ƒ³ãZ:z¥ó0jŒ’›çu2áŸð“9nœ?ÿ)耦³gž#l£½;=vrþ‡`9[k Là/¹ùuÚâQ Spî-Ÿµ¶FÑ`[gß|'0lróÛ$Ã;|³›ôæƵ•¡¯½ž¶zVÊ0“çà_•×@ç´RL¨?óãÝ$íìá›xcë8“H²¼Zy–ãN?tX ¡L:±š¾®Ë¾‚çÊÎÚ  4® Á ¾Å£K™”ŽÏŸ×âøG¥áà!èñš?#gðœOa`AàçÇIøY0š¨¬¼gÒnÖF‡'7u3¼2ó—!x5)x.¤‚—๛A/àT( Œ37¨Dç— 4?ãÆ8Y“—>M[`®4óïbŒävs·¶Ü%ò{­Êé­Z’QJžÈèP⟧ë(•—ŠWÓÌ'ÄEëòu,RÒ r„ç†)QTx°…e¥dÌáÅ·ùæ[.ÐLD\UF ¸“ë:Ät:ð%1TyKçïâ|ØÞðDE: ¬YTfbó2‘EXXt±.‰ëÀýµŠB’X˼ƒÍÀîiÅ$’úë¶å˼ê,€ÿ5ÇÌüÇÕÉQˆ¬Z ÷E™7çծЦ×@k3Á$ü¼BDœl‡ïá_+ƒ5pÁln>ñÄ;< ‚-,Àd¹®·Ñt¶Øjp+‚9ªæ¶)•Höþs4Y¦å1½jéÛ­‹"(áåü­rÔ_DŸÈ[HD *\@¥•±¶W„JD"Â¯× 4ç ãTv8¨€}8À=¥As«àûG¬å®UHT.ð]Æ¢X£’‘ Boƒ-Ýlî¦æòs ¬7¨¤ˆ6Å3lJan:°dÔ˜"+˜Ö ™x)xP\üëâŽø ¹cKÑF‰2à‚%Ïf¡gìMkp@iÅ©2)„ä`j²>_YD9o¤ùŠäTi»©Ï¦01{ŸgØzÕ£Ïëd:OàšƒQPFáA¹¦7J¢&,¯Ç&LŠV=ܲµé/ZBáeø<êV!Eã±QT)6IUDb‰h`ÌV8¸ ó¨ØS¸‰äCwK¦’³Ìþ‚¸gáêB¸ãÍ„*‚¸lèõD0;”eUÆ{Pšè¢¢}Ñø‹%é"‰¤×žÞ ÆT€$ׄfðTlPÞï&|ïˆÁ_õ^×­ä'¥”p³¤ÈƒX«:ˆk½)÷Uœ¢A¢ Ñ/²hF#=1±JÙX€SŠ*<*D‘ÎæêNŠh°ã%·A±—; *q²Ft#<Ñ' êe ˆS”‚ b-¸àkÊ hE€’ÍÍ8J‹ÌžðW¥ÐwfÈj²Æ-Õ¸tÈ¥—BªýïFÑU´òÄÆc€‚£džJiERI@E#ï §-ÝœT)ÖÄQQ¸ýÌTîû†ìRˆù "‚_«ÍÌÐŽ"ŽûjI Ò NnW”Æ £^"+} ܂٭T}Yì|bi–ñl„Uð^’úpûÖª/ ¦VnÝ`¶ó*Æõ:FOØzaDQ§>Æ@Ïš‘ݯ!6°j›Œ›FpK­(ÓPÞ´®‡ÈVgÛK|Ò¸÷‹ÃåñBQ#”ÊÐÅAq¹÷ž<ŸœŠAήZÉ—u…ûê—öç½G_³Î¨äÌ¿®ˆÑ%8÷¾ |þ¼nI&Ö!šØ¿—C_ÙÅí¿áiA'¤/h Ý»Ù|?qpΘùXŒOùµ#ŒÚãæ­}¥j |Aký¿¼"±5׺;=MXLÚ5cYÖ]²Uzö¢¤H’§³7ÅS¾Â-D0ÔÄ{#‹æìrèÉh…D‹ô”®ò[Ö™/ë‘d'ƒL}2ìâ±³S}fØ5ôÏ9Ç%×äšbÄ0‘úôx túuô¢üz÷ìý÷éRŠê²ÝQŒLrl€–>Ö@yÍÈÂ~lˆ-}4‰BBÌ«]³O$‹[Ë`ÁÕÐI7ɶ%„­Kî<:Dâí2µ³“~™vÀËhÔ¡<º =$¹ñÑÇéYxјÃz–™E*ø&4‰. ljr[%c64%»öD“]N+f]¶J{@8˜¦‘tuoOêsêÿžâQl@8t¹jÄ×Ðn´ã7s¦óƒ:Hwoï˺O¨ËÓ]t–p&X¨í»ÿ¤HbQA„Uœ5ß\Ä¿mÉÚLǃ#lÞæ}J ò™UÕ:™¼Çi‘¤uqÅ©Ð4JC…ßí<Ä$H] {Ò•¨ná)øvzí;𵈠HÞôØØ VöŽ rƼšI»žŒ„‹e”w?õ ‰–þDDh—t ™–eÙ˜Ç_/ˆbm3€©¦1<þg0´„”õ„¸‘ÁL„oŠ;×5" %]Ì:¯èGÄb-2Þ}ŽˆfÅš}²H(å<¹¿dÆS‰s˜Æ!õÚm¥]–Ïo“‡K˜Œ "=¸ÓeÕ™bµmº~‹ÿuòX–Q¶I8 Z¤¦µKÛÝŠíõÅ/H& GŠèQ*ãc<!¶àÀ·Wi…%HûT~}EqT¼a8D8…€ÕË.ýñÅŠ?>Ò “]Ë .ƒ€Ž“ð) Ü%æt†çJW×<ÖÜ(gpTÌ3Ȉ>/Z(dºÝÂàÒy7iy¡DÈù¬¹ZÁu(‹=Fwˆà"d‡FN$Ú,1“UÏL z5'ÃÚÜ.2›+‰ŠÄ\Õ8éB§³*6#™§n·Í¶h9Éà´æ®¿ÈÃÀf©+ÃÏVtVk:ñlOêóõÜmÕ‘adÜé]8U!ÝO«õž æ%Å8ñ€à€{jo‰¦&¡ÆÛwÌê”­eVj™8£z—9¦DW¹+3ÎVR¿‘¨ÀGaÕ~rÒ”3tØ¢ÖÕ7P‰Æ¯¥˜1rUÍY°¾õ¤dA‚[›GaÉjQã&C¡r5-äN­6wl…£Ù˜¦¨ÎQ }x$K‹eI‘/ÏdÙvo[éd¢¥ÖÊŠqkLîŽÐTávS)Ô]º&-4­<Ë“ì-Æu…d}Øcf÷ÅaÒ‰ás~ïpÕã_øpÉŠåi-±;«Ý‚Æ…‘ºRÉ$»E0ÙñŸX¹}ý&¡½È…‚%Q¡V³¬âñÜ#†£ 'ÃzADô ÇÂɳxÆR í!bœ‘k¼(UÔ“V3›k“·$ˆ[Î¥0ûrhÎKKf-æø-@ àrDZH ø9%9„O}2àÅMí[2›ÍáѾCƒ“çhŒWWå­ax*c0 :ã“MˆHû`EP€=y=ÐBÒ›»ð´©4¥Yˆ©‡B*]­4çâ­-Rš6 ,2.X÷ï0ºqžY8Ô7•èš‘ºHK’ó©\íA¬O+©ÑR¾€€+ë‚Å{x8o#´œ®g‡ÓÄ×ß¼ôQMf9ßTKØ &\'Ù]óÀ¨q˜-j«˜XbìqZÆñϵàu\ÏšN™¢pÁ¶—†$ŠJ›G‹i²$þgò¥î["Á#Øù™U÷Qô 2©,@yL›)’Gh¹s‡ôÐPG2ÂÁ èz÷VÎù>†±W2ÆBï& ††[³²-ž |=ó>»$$‚ñrP·Ì»Ÿ‡þ;§4êòWJ¨PR^ú¢$4æ%‰*4<˜dÕB˜²±Â7ƒAÏàöNÕ¾µHãâP¨Æãîy¢Ò¤vÝÝ‹þJÛw /Û%lø?šZv†6¿&çF;èIÐ| ,«¶žÇìæÊå9]·âÐ#‹Üð |¶e<äV[Ê䬣¯-¨!ŠÀŨñ.v÷Ô_h5Ï_-OÄH\’à’¨zäž4^.MälÛ  Y„E®QùROø0fZkˆWÌÏF»aÕ:Bˆ‹ÊØ8gšCì´UTϸéLsîͳ«Ò©õ"MœØM‘>þÿ^¿ýXûø§íΫD–G¹êË¢èEV£=Ø'¤|¨Ì,{³¢bþç ¥òg*››$8žÎw=bw“ŠIÃC] Ç%ã7Q sPKÁ&UW‘3 ò· Å)`^ËòßîGV¥{·i’L»¡H¥‡‹ðbØ-ÎzVŸÍSéÞ¨Ïß6ï¦Áa!…t6ÔJÉ5==ìN¯þîÀî7eð®¾J‹Åð¥;ºýòmJ½GmÙÛ¡²†üwò,{€€nLkIò·PˆÝ™ (€˜’]„ÛbNÇ«l7 0µ[=‡¼0æÝëÆ‚h¿éÊ20?‡Ëy ïHî #—±bX3*c_ ­4ª÷ÓÁ©‰j‘²P÷ªÕ~}ž””tëÇtæ¶Þ º.êÅž&7 ê–>V’(‰ ˜ûò™o­¦¾`Ž SÆfù(~MÌ?ùTËÇJòÄáú’/?¿^®ŸB_àL_&&ŸœÍþ‘±sãÔñ}­CŸW¶KY#£ŽÏ™r,Àž¶<§}ïCÆÏú:¨–"]Œ)Ià¶ ÷¹Çq>´¨(\‹ûrÇÍ0ý Õ÷ _º¬m@ùƒoE*-75€Ý+;ÈH„TÆAÿ>$(x…Æ/ØpH(?W}²Ü ö;L—ïç½Úÿ…&ãÖÕtÿí`FiÌÞá m$ˆ'uþ…Æ‚®[°8bâƒqÙ‘Cq~ÖèPØ¢¼™Qfjø~ÃO0í^Ù•"&MUvãg[#ÙÍ ô£¿¨z ß¢ÍB˜7¼Ä%Gö…/¦ýÀ‰¨@µÞ£ºÖm“›c ‹šd|P̰£\Äîåm£‡`Q†"Ø—Œ¹Œàþ›ó“ÿÿhø³hendstream endobj 35 0 obj 4366 endobj 39 0 obj <> stream xœí[ioÇÍç…ÄBAŒYY;š¾g,Ç€u$V ù &)’)R<¤0Fþ{ªúªê™¢äƒc„ší髪_½ªî®y·ìZ±ìð¿øïÖáâþn¹{ºè–…ÿï.Þ-„¯°Œÿl.n@%¡—B·J[¹Üx½­Å²·­^Z#Z©—‡‹—Z­…®ªy²’P¿sCóÏÕTÊôC³¹R­pý šÃU×ZÛ»Á5Ç«5Ö•zhà}] ÍÎj­zѺN7ßA¯m'µvÍ öe¬ÔÊ6G0BçŒÍ®ÒÚ¦÷Jön<ô4 Í)žóbMY²,ÊZNë]` Hµš.kAÏÛILšÜ‘üæ¶Œ‰¦@®†T¬÷]âøµžhÌ=‚q5Œ~L¶; ÈÌ׳tå#ùƒLé§™½r”4™âWË­]g þû¾+oA†÷£|É)À–{êóü0RŽÁÙé¸&g i'⯠+ï/h}wj¢ æÊÜ|X3ƒÓššix¶ÅÝá5ÙÎr†ùê;H³ Áº‘Õsm×y9••Ù׫š€'\UUýT[5ßíz÷ÈÒ 5'«ëmÖ Ïk Qb—‚ºrI]¡$yØêÔ@=®}ñgŽ*’w˜9‰úý ˜*þ~\>Þü x|ô–Îø3átåP¿Å-®K€£¾ù±’¢µ}¸ÞFf*îþð–š]á0àµñ’iîÞW íß³»¦Ø«6=»}¡ë¤,Ä'µ[$*©1j›Üûëᨠü„‡D>Àã=±ËªxA&Ò©½sޮ᫼”ÚÎ…QÚ¸y"N i‘!湸©O%³×̲÷ikG{tø-–&Ùü˜e?á®"›Ÿñ=›+*ŒvÛå˜Et$™fÜOÖ3ðn±$Ï`z´ig)±ƒ…PÈÍT`Ÿ ”}ÕB õ\Ȥ¯gÍrÿ¿V=­/ÙÚ™€š¹mH|]ûHã:Á‹Ò½^f=ç8ü¼M&Re~êÄüØlÊòY<¸ë ŠÓ&;§ÀÌk'Z H&ñ}œ€(‘¤¬öÛf ³9¢È©PûŠ~ö*'0“¥º”‡£p%Šç–Ðï¥*‰ÒF0´ð siÅ#…îר¨r ðÕJ^aâ†&z#üʃG˜£ï¿0ÂÔþë¢kîrâÁ_ýÃ-·"{ö¶#GƒÜ§EŒëß0à?j`ûÉ[ÜÔê»î²+]½ûÑø}£.D4bÃ1´äŸKÑWé“*|u–Ï ÙmxÐr&“ôFä÷;…#:ˆð‚rãRŒ77ϧJÚDxÈþ¥/8'ãÈ'Þbt|Q;kIŸäØÑÉê\zÙF×c–¹=ŒEZØ$ʬòâ››èʤ/Ê€;$S^þEû<‹õWˆ¥Ïñä9IÅÒclåÏþ‹(ƒðưœqIhgá}úÞNÍ7+É£}ô%£hŸw•ž0¬ƒìªÑT¹K(ÉxH4@Tq8~T!/½$å¿–ú~ñO1¿2endstream endobj 40 0 obj 3707 endobj 44 0 obj <> stream xœÅ\YsÇ‘Þg¬Þ4³ÁtÝUáK–-:VÞ•{7BVÄ‚* (êð¯ßÌ:³ª²g ò†Cf£§»Î<¾ü2«¿;]öâtÁÿå/ßœœ}éN¯ß,§„ÿ®O¾;ñÓüÏå›ÓÏá!ááÎ>,Aœžs’Þ§B¨½Õ§Öˆ½Ô§çoN¾Úüv»“Úì¥r›ek6ÏàO ¿ªÍüõv»3{­u0›+øAÙ½¶ðC¼ Þnî¶;å÷ÚH»¹…ÇßmwboŒ³róíVîsjóýVí½·R´[?l\yå7¯°s¿7p“¼›^q*¡ýõ¾æ¾¨àù­½‡×||ú¦tBÆ^”ƒ^Ȱú™•ËúóåVÃ-©ô0„Wõ>Ž:6F–•’Úáò´Gî·;½WJI/q¡îqDf¯´Š~ƒ/ã[Ýâ/oà—½µÎê: kLJî·_ŸÿéDzhaÁ>¿‚}mcÞCßvXêÍ9쬼zó:ÍZ:ÑZö¹e+—0pÕ–ÿzß^,»`Ű yºNؼ¤Á¤•|Ù^¾©?þßlÕ²W"øÒ~ ÎxW¦¼Q|šy'?neØËEã.¨.–üçínåÖ9l[YØF­qlE˜aDJš(^œÄî®÷z÷Q(„”Y<ðê »†AfÚfÝÂM”ëUX‘ŠO:˜‘éG^E¡ÂÆaËnÛ–à›8;P`XÑA¥Ê*·Fžá£Ìç;éõd­µÔ]opð [{¼â+-£|›ÄÞ¡äT±/¿Ã~^³Æ¡.bçzû·ÃáÃä××M ³–+Ð[-CÞEt ¡¯{“ôûmÚT­Q‡·­é»¦DìYÏóŒ²nIµð5µwEİc ¨°öäN åü“dÄ¢6€G³ÆlžãÞxàÑóöû‹Ô€],}à?±-ð°jƒµ#Û×ö”ӫκ*¹€ÌhÐ`ìØ…@”ì¦]@§”Y±Î‡˜Ï»¶°õm0jé–aYå`@²Í¸¼°Z±ƒlo“ŸÖZ0{A>­Îuê-T¶(úÁímü·[ ¢—jÞ” v–d”1VQ[ÐS€;– ¶¼§hoâ-Ö[oþ·Þdîͬ*íF'¯ê»Iâ„{k?™ñ¦âø×û&¯äéàî¢édK©ƒ#ªÃ6Aöß.š< vÒ€“E¢žL*I,8N´O;XCMeû½Ü‚;ÔÆºØ(ZŽOšˆ%uð{Ò¿ —w,þþ¢uœÔ{… ª½ƒ1þÝé°ô¦œü|lÂã^c7ïpT&j:«0¥K#ú­N à÷¾(À!”¢úSvÚ«ŠÈ$€Ž ´4J—õ¼õ'à –„4Reö¢~mÂd™{H“'‚‚ MdÓÎï 1ƒ:&#š…Rûd‘‰!Äuú;Aàåi\&“<'1a`ÜÅ‹ÈÈÛé2­¶¤'  3è"jm .zý3v· u€4!¢^-&AK?Kgaz;meô «2þ§úhô×ÐǃŽÒËÅÖPZlrÚ®~n“o÷8¯4OÂÜØ> Íx)Èhä †7²Ç õ°»‰à¤ß5ᚃÀËp1‡„«.úAŠ£-0QD$.¶-t‚çÙX®]‘x¥ðfh/‹Q£vÌDKšëhdЬYïø’£QÁOSL‡o±Aë@æþ{ -ª¨_¥Ñ l»Ývx®3¹y¡ÀfEÓºÇÆÕŒUÇ[BEmV¡u™ð£éÇütµÔb´Ô‚iÑ`f§‡¹Jw•2ɘŒ‰Œf•ÑMè#óÎ…œLÕš\$NR0ŠSÜÄŠâ€<ï³p*.R ">“’¬—N4@ŒŒEG½E7 z <¿0TsTHúøK¬D„0p¹j%2J㧬—d+VÒ’$î7Œc!?¿íMM¯[ñ!;°·8ìELlr@·èŽó½, v•WܨnqõâãØ®)O4Êbn4bK£²Ä}W2Ð4Af5c?väî¯ð@}ëfŸU>Á(+]„Q 5bÅ’äFW”>5E)0ˆTg´ ²ò¥w–IR)ˆÒqÆ3ü@î(ñß6E˜q(g_Ê@gÎ`üÚjí¢ÕU‘ŒC›¯p4ÔËnD½ùu½™ZíÓq)DË­þmKs5Æ'tK¨4 àáôÀ¯|"'Vä9Í–òõ· /£ãä–Œh5Ù &³€Ñ+dNáÐqȈøøæ³­Àµ‚8â÷0*$Þfö‰âzË9Š‘!îîYÉ’Ù9´Kãõ=Újï&s û+ýà}HøUâCcÑ&â43RÈHô»£M˰Š0KŽÓ‰¯ñG{ׯ;1žLу‹R/H΄peÃ$Àqd§{¬#+‚'ö| ¬‹¼A=æKJwÇURŽ}÷Ï邞lÇœ$(ó:JÉw>"!,ÑxùŽá;º†¦qA¥ ŠH8” •žI½%öG‚¬A€TSÈÍ­\Y2‘QŸme·o…‚™[‡å͘.Œ½èg…­€`ŸlíKÖ•7Æxí¨M^ *÷7ä7çÐôv JÀ%f†mì¹,~}›ÝEµO½–Èó6AFé%x>s/Äep-åïܾOþûd³y“^„s62eÀþ°…=tÞT“)ÃÅ‹#²°‚Yµ~V%Üœ0K|a¿g4˜½f„ c|Ó<ä·íò&]ê\’ïîÛ%yíûöì»v—xÞ¥]v½¶*&kzšß`Xz!ó2šøcA_¹ åL†+¢õ~étôÌ«€Ç!D½AöEcÑC'ýRŸÅ‰ÛM£°šlfÆ8ý^æ›ýVæ›ýNæ›ï8%ˆ ¬möh‚ úÈm\6¡ÅÍ1g?ë…‚b &–(qЉÅï@ä›ÄDÃÄ;4RZ—á©ñ[ˆf²šú"P]x‹¥c=R_·P% µèè ç5ÌP†“;†ßYó»´§qí’¤ œ‘_Q¨H}Zü+wóÏíæy½ùâb ,WâQIô2êóAÉXóÐ?Æ ±Xˆ=·“¯ô[ˆt•!pIJ¯‰.Ö„€]T £>mkþ?Ýò#O6åwíòónÿ „Áâÿßb꺂Eÿ¨{ \þµµKîþyê/_´g?:¸óHi ž€C.´Ô,•¢ÉL{~•µÒv¥×IÆÁD2HÎÉ¢’`¸ ÈJµ‡B%(€þv(wÌÉ„ñ\&ÌP.Š(u#gD8Û¼¿Ô^¹ÚºŸðÁ%º±>j™€â=ólôq& gûò<ÞdâsDE„×Êa[lä@8Kx%¸—R¡"—ÂÕé‘Ý<0a,z½‡ÜÔêœHØÀ¥xÊtár%ؘå—o,¡á#“xÌÅ^¬¶ ‘3*j\WŨ  Geý``PÖêÑìL)0v¬¬ÕϹfôhy²Ÿ¬!–½´5¬‘òXUYØD²‚dh„_ÌA $ÝÕJ3¦ªhFS—"4‡ž?_|”‘Ÿ¨Ñ6lddê³_·gkí@cÈÁàŸÿÇÉù¿}>Hv~¼TÕä@N»Ã–:y=Q‰%lú“§)±Ô.UT :vI;ùU6÷”ÝN|¦±]Ø'Ú y›©—¬kÆ”µ’nxï†l½ñ"ºÂÈìŒÁ-· úXq*IfŒÁÓXè'p øêƒ‹œƒ©3ð¥¢;}^«4§¥ö h-à$õ“ÕD+躤|_sPrë~¹¬±`¡†·„EíÆ@’_®¼Ž]'ߊ]eyË9VnÉú„ˆ[Ò¢4?\=žœ,á¡­?ºŽò’·²¸¨=©G¨ó=èõ#¤3!ŠÓùÖƒ\-¦‹a¹Ò…¬LfF–ØÊLþ¯OàŸç¿?ý—“OŸŸ~±z o¨Ë>½`uâ*éÓ¾78BÔy¬DVÑÐ'*ãeúú¨I¬_}Ô.VjÐQ¿ÆÁ¡Šqƒ/¤\ O%Á%KH£=þ ‡Ù1“$ògWJjóOY)<™ºéö7ó¶ þ‡zó¾ÝlÙÍfäÑýfäíÞO[Ÿ†yÕÆþžª# Žäϟ渑BC⎅¾ÜÑ7¦—„Ē?•«jòo þÈ)3—å-nïõP”cú¢¾J¯â6N`"Îô ð8{f‚Œ‚ˆG¼ü¯h¬ŒBÒÉ$÷…íX,Z¶*éiüë£Î¥æ~ÝQK0Ktȯ8m¼çôöþ˜G‰| 1¯9̵±˜D9»’JÔY‘ÎÆF/bû«äÅJeÒ„Æ&´KŠd€õ ¾œã¥Lä/Z“ñ¸fªìòçthÞ»1*õã ¨Ž”Jg0ë/$Žë“ëæ‰dF{lc{ë2'w­í‰ R‰,k¶XžÝ³ýË’8̨ˆgáZ JÎ÷DúÅÚ8Ò£ûÙÄHb–| ©´ˆŒ¬r|8rQ„Y‰âò¸ü[¶`¬{ñ`ö.gçQB.kýˆ8‘H~_:Ϩ§ÒÉv`ëw8—Ñíä0RCª,­Õž™:ü%E’é·<È'aìö¢ÐáòˆÝ˜ƒx<¶‹uQµ¶þC+P‹£5‘XJÇ2³Ý4¼¯Þyˆ1>†¤Ldé›´íÈßÄ2¤@¬IÄŸ¤v¤¥«™´º¼ÜÖü,›Ã¥Ñv¥:V)×S:tw½qx=ÐÉ(díŠlè¿—U<ƒ†ñ¿Õ Ssï¦â…VØVaÏuŸé ûÒts?¸/÷‹ítd¶™«€o“ÌÈþüåYO¢eÈ–ã’z²ÒöÙvúGwZ䄤óEÌ'°Ñ3ì4x+º ãîÔ+›ˆ=‹túÓXø•]­b¿/áG—™¬ÙV¬ ö ®ãk†# Ò£uÁ¥b£µO‰Ì¾È¡á¡¾˜ª]c¦mGè °©-ûp°+6AÉλWõ»NIé]^Çž•Ê‹EÆ`´?bÉpM>·**àcŠ3ñ,k+¿pÜ!ÙòŽÖl²´l¡Í­“¨ù‡@ “ÄÛôÒ"V¨¯k–÷öõt~iŒ¼=ÇïqilÏ1Õ:;Ž¿#º‰~Ô Éh—ãÙ÷ólËC#U_àÄSQõaRµúuj%ë»"tðÖ Ïõ*þ«ŸúÔmšboùgŸþrúRˆÙ aE™•¦~A–ês¤µ Fc摲]ê)JÜ›DýÈ7JˆŒ—ÏA™ð§>̈grÓsìÂ¤Ä ˜ôõwYŠÊ2rGz§ã¥(ïø -‡8é”Û¯«B u›¿{0´]¦¬>åmË.Ò¬—t–`>Ìö#þna³ÍFÀ€–´µÒbÞµn§Áˆ‚°bOµ&}Ë÷ò@ÐõdsZš$†ûœÙË£…ymÖÏìÖ¡‹mkÖ¬D/x•-i#AÄ·{u?\3´@CV3Ťj(ma&æÖ¿òTá­X«à3¯¹€âØ—¡HÇ݉Zn¹š=[õ_#{FúO…­ÂÈÄO­0õÈ)ˆ±Àúh95™ë¾8+·ùЇÅ-–úõXs)ߪ{|ÓÕXijßf¹0IþV)ÙÎÅiâ½ðˆ2~¼Ì¹Ñ¨õ\@üˆ3îÓçó cZô Dp®ûaN'ÓH–w¿6“?rr¬X3ÖÆ-œ'ªG¨ù £¡ß?I_­ˆAmœ3St'; žv•€+\æ\¦Ê²°}u§¤ì-êT a˜®µ-“–†¢— (]¬Ñ1@§É·m¢<\ÂEQéÌCŽê9”ýPÌŽ­ð H«zâ j]J5ÿé§ +§Ã½QâMW3uOÃoè  &¦ÈXaÞH)´žóš‚Û|H§¸ÄÞ8Ü%Æöª-Æ.±bÖ²ÏÚ±,\­d8hÅcõV˜TÂ5ÛöÃa\>¥¯dÄGÍtß±ÝÖYùþEfM¹ïªa¢Åƒï†øå+q,ôìì]æ!Y›ÙÈá4î.EÚdÙ]´÷„_VøÈ «•åyÝ«y^ÝaèDoò£e\:G>Öó’3‚ã„¶|xUJ¾^èfÆî£Ÿ‚A æÃbjˤ.v®Í&ß8–¬j$›¬-~ËHõæÐ¦­Ú«dš’‘ù}¬Y¾cfK0MíJP#G‡ÍNd,*Ð|Å_9 ¯BðÐ’Z'Ö`—2Ÿð'‘é‡|ÂjJQ 2&/©ž O¾ LçÐ~Õ%Ž,_JVç§m-3=°Ÿ„aHçÀ«nýîgB¸¸ÇKz×dÞWN‰ÉKœm@> stream xœí\YoÇÎ3á±ðÓ¬áMßÓ>d[_ à š”)#"%Q¢Ÿª>«{jvI“²Ä ,­æè®î®ã«k^n¦Ql&üúûôâèÁWnsþêhÚ| ÿ½<áMúëôbóþ1<$ôFèQi+7Ç?Å·Åf¶£ÞX#F©7ÇGß z»BºQ¨áƒ­€¿œÕÃGÛga¥m§Ñ5)3‡«Öj5|½ÝI[jŸbÖÃçð€u£7zøj+Gk''‡çðkrZÛá:¾$`‚×pÑÀëføi«ÆIH¡‡Ëzû ^´Ö¯`p-ÐæßÇÇEͰÌÑO^à¢$¬ÏøysüéÑñ;ßEúÜ,&5<Ýį̂µö8s ÆÚéi™‡Ó­r£6ÆÐO¶fxÿi' $Âbg+P£ášr¸‚!$)çᬾXïÃ'p¦ /Ji/+-?©ó¨ìzóv 6­Nþ”Î÷e¸{e-ž’]ƽD®NwÃy/à8ñ—³ œ½˜\Ú­pÿë:G|þ§Âiz?J©éžÃt×õùH¨Sª¡¡Ý©tÝ|I^é6ÿ5<,+dÚ<|¯çE™²oFZYBÁ FkŸ3ÂÒQ8+“À3ƒ»‰0“‡ÁEäA§_GO拉;a‡qÓµV³ »@î\àVÍ#È8­Î‰9œÌa¬¡'‡ƒ2Ë›¸®]ZØ.¼6ɸ¾ÊTø.*ýœ w`Ç@ðq%8ª™ÌðÛv7ÁiJë\^é‚ÿ”BjDäGD…AžGÑh7§ãíx‚™m 7$rȱ„9ê@¨Z2iàÁ$Ò¨€I¼6~x«Ž÷,ÏÓ°ZÞÒ1ÝMÊ4¢íd‚F”~´ª* šØÝéÞ°¦YˆAåk†…4]á^Ke…¦?ŸÇ÷¥rxU95Z‰j^›”D&„A½p7ô­Æ /éi’ ’ÒPÈM(£ÐÞ¢Â@R,Ü¿D… zv8/ïÄUIß¨Ä vnyU?)Èá(ž0¾÷p:AuÁsÓ4‡3Æ[ ' *$a‚•ÿÄ… ïªpøqœ«òð÷åá'åÆUz.OuUžy<Ô«•«êÅOËEÜk£F?»árñU}òu¹xU/>)OêÅ‹rñ]X3ÈäOåÂe3žþA7àu½Â]¼æ({¼ÍWñlPt‰yºÛYœ—³(›ßí{¡&=r’~í§x(W U—tÅù,î¸7áæ0Òi¹ÿ”é*ï =ÿ'S‘óÿž#¤2ůÜíö¸ðŒÂ<똸YcXpÊíOëçæÈÈiý”cÁ™ät~¬WŸ•‹kDjkÀ Y²}?s›B¶¯ÒOØ ¡)Ëñ¶Üç ™c#¼ßì$hè ^Ñn-‘",‡,œ,°|%ÀƒÀÙ,¸-ç…N</,]Ån°SÆ×ˆ4£'ýCeìz‘pö9.Zõ;[èæªnðñë:~#v…¡’/ gT€²!ôɱ.Éy·ñD%Ì(~‡€ªØï&~@Hš¨+!䛉¼’&X†2Aç@%¥~§ÈqØ>k—ÂÙZ12äªp*9uŽOwR¸#ˆÈ,Ež°x ‘FoQ‘•.¬ZÚ¾—B‰ÉI_7™V20ÔuÊ„Þ>þº 3.”çóY˜‰ïÜHp±…é€òf.]”ÆÚô)â€UžôÀÈ™ÙL±,™â`£í,RòÖaÂ&gqñ€BOÆÁ® ,¬.'„a/R–X:]ó½jŽø„"F!x–'9äWXjj fdÁ¢MÀ^)­‚Ù+^çáÉfgÓÜ þ„ž2öJÖÙ‘LgHh]&PS«ò@Â,äE_” ÙeÉš•×âÃÏÊ#˜Ó³+©ÓEöª"_Ø'kB 5dØ5wö÷ú‹ùè;¦;Iº¯Yüq]rc^Ð’ââÄzÌÕE,¬1­±m’hL°O«¹;ô¬»„×ÿ¾ŒÌÎ@±Ó¤¶ò 3P˜õÎVö´0Åó|·2O«Šþh+KÎñÇ•5ÞúnbƒÉ,x=P`{Â]¼æ$¡­¥¼[Y`—¤K¹ÕPAoÁ½[ÄqúF‹TèÎV¶“¦ƒíà Ó è³ èóÀZÅ(ÎIm.Ø_´>nwÖO˜i&á¦÷ÃZ¦V’N°ä¤„–øÔɲyŸìº~ôfª¶‰Ï倛ej9JN3ͧµ·>‰c)+˜ttè1| !!C¾µø£¯İ­ê{8*‹åP˜ãK30h† ÔT:ºÚ¥y3ŒÆ+»,H´ÆÜ¶ QMSHÝÞC…Å¢p#¦&r¸«ºy‚<×ð°Ùe2›«&ë"aC.áÁ‡_K Òþ~&¬N$§µI¢ë†ÁXL¤”!g?cW¥›kv"ÅJMKIÐ2°)éç-k—ú±Œ7O‚p>)¯Å ¿})mÛÜ”w¢uA’vˆz³ÐÅ·Í ¥²F®žáò‰Êb­gH‚Ê8,ecmF*¶[¦Á0^¤L¨E8h´ñØ4|»õS&1÷G‘3&|Ö­£ ›g5+T¥Z:5w2¥ h¬¦Î¨$›™ä$†¤5#Û»šùfÁ>K+µ¥T«d®5 -`„3«ê§"&jœYÖq+-и²Y¶½}}ËýEш“Æ©#&Çe÷€´jJi}È8³zêÌXtÉŒâ;¤Ì‚°Á)# K=f'*J¹¨Øï3xÉZm©}éúɘ¼ž-îî²Ù!¤]µçuär‘óSÖ¡÷Ãòsv…eÔum ™SÅúÀ˜¼&n)¹AëG;cG\‚¨F@Vš «)¹bå‚¥5LT³§&*syóìJkèJïE_æ·pØÑ÷|u«Ÿ9pVAÍ»(ù¨S™ꬕ|’ú_ùZ¿:E3Y$™”’®Öbã£Å"¯gyK‘Òøš%ù&~ a×<üjæ}O}Y㥭ԗIJÎôYv—W}4ÁÈ ÷_RÎjËB™ë¡úynqXœ ÿÖ^ŽõðøèË£—àï9|a‡?¤!%l„sáïÓ‹£÷=xôÙæõÕõ“£ßlÄуOð÷¿øþzôáæoGm¾\ýöCWÖ•¾ý ­‹$@pAðÂÇju‰Aqñ uÚgn×@;Ö×6´×ŽÎ_+íÜÅF“НVFøN+¡W›´nù5„XUl†Å§”`>u)m)j'>r,ÕªCúÉ*r ‰s’+Îb«-ÌUdô«ºùëÏ÷j¤îÃzõóúóõç§õÙo÷ÚNyµ€T-¹AUãW¨…âïáŽùÿî>Â?ŽóslPÃ45‹m·’d´.ê¡ó·%‰¥Liµ„+™†ôA@§$Ü@kÌžDÑNf\%÷|7¡ŒÜ–üÕ_k-NÁµjÚê8xUöp›`uŒ7´\Ÿ×±†ÐTh¿l%ùɨ5W<+òA ,5â§×†^Í.Mø€N±pXl¤Á‘ïÌŠ¢ªä¦ýîª \â> BšZóŽ×+i1 ŽUÆ}j¯³G°±y«y6zŠf?Äa9%Ç ø†àj¾ôÁãfbe­Žf‡>W ,¬Ü`æC¯E¹ +P•úÍE¶41L;R-z—“=@«³ ­ó„"Cie²pûáLýaIe£á½IÚÄî¹UÄn£s´¦[ÓmÆýÀ`’Q»!»ï³:΄u"t5Àº²·õ«¨'sÓƒõ'ôªÃ¨ÌÔ6Ú=Ø«y•Ê=}•ÀÖØ˜Ú:܈¬ßPZ„¢N;ßòµÑ¤I`¥ûRji¹KÚZÒvÄô_zß'ŒœwÑ¿–hÛ›@Š2-Ò¨}ßËãÎN;á§ÜÊdhЯšù²À·8ÈŠƒoSQù• .,Òr(SØkh$¬\'ûxÒ>r›©#aNƒùk4tÝv™öT÷gòû*%Ø1eº JèÜ _¢Ã¡¸4¾‰ ´”Xd܆4 mg÷á3fMÍå^K~ûð³dy ’åy'“ñõv6Eÿky¢)ämY‹!ö¬2]>¬–ã|ÿï³³°DÈ%Ž6DÍÚó1üI ÌühÜ–P’1aWÓw\?#ÐOŽ ùŒq9AàñÛÉëœÊ—ofÕ6G7´[¡Ö<[jîûng¦r6"4ÒhêA"1z\Ç“BuÀRë…§<‹'ô+ùêÞãm¹Õ~™®…LØóDúön?1&âîA]ÍoÑÍèkxÑ=?oE ­oœb)Ì‚â³B'[ër²=Fr$^¹Ðô(O ¾Ÿd»`H—ëÂ¥~èª)šŽW[wxÓÉyùM?^p)ñ={½|=ƒ#Ò~Û¯á{ëž?~ç#·ÐNºÍ0…r¦Ù¨ˆ+îà ØÑ}=Ý ¦é X%yÄ& #0 Ÿlåð!ì¬×úáŸÛà"îDRÕ„ö¥ËÏÐô_g]ä¾Â<5>XëÏ1Àù–Ç£Ä$Wzj¼ÀŠxD`>Ð"õ‡W»÷Ck’ŸmÄÔìBì(ߥýI1AtBtÎû5 ”òõãŸh›åc’w¡ðí¡´â _wçDæ>ŸÁ€c“HÁ³˜ZƨHçéómÙÄÚ>‰F”ˆ9â?{¢°mbÏÛ ±÷ö‚°ZéIgd Åe¶.Òz!–j? ¡ï×áé>ÌĦv0ЇqûÉÓZ¥L°ö/5ÌÃÆ1ÿ.ÕRÑt9µrÏ-_íõ¶tôxoP›—È5&Æ„»ˆðÞVa=ÃLjȄ×áÛ³˜mE º"zÒ¢Úà?fÓœ]¸Š"ßU÷¯e9©8úº&ÏÛòˆ¦"ŽÇˆñ«o+UyÙ¹ DéÐ¤Žžï ,)ªçk)óÚçî‹ }8@ÈÂoàâBll¡°ãË£ÿ²œ¿:endstream endobj 50 0 obj 5066 endobj 54 0 obj <> stream xœí]ûoÇ‘¾Ÿyù#ÿâÝÀ»š~L?¸,[±t°³E;,æD†4LRÔƒ:;}ªúYÕÓ3»’(Á‚ «ålO?««¾úªºýìpØŠÃÿ—þ}rypçk{xöâ`8ü þvðì@„‡éŸ'—‡w pðdë/þ~߇Îlõ¡ÅVêã˃ïWXoÆ­Öã(VÏ×½UjÔnõb½ÛqtV¯^®7JŒ[_ÔÖ9#Åêx=®Ç÷´Wk¹µÖªÕ)•#¼'IáóZßÃê”…êNêó§ëtÛa°ªÐðPH‰]PrÀN¬®hÑX…4[1ØÕ“P\*~¸ZK»õ RóV©ÐæÏ¹ƒP‘Ò0J¤ƒe"Ï€5’M3¤½duâëV¸ÕÙz„Q§Jçaþ~Ê?ƒj¬ð0»Gð+<ó^¬`3ÎãX>ÄwìVJµz´"ýÇ.‘—Éd¥¯B+œMX9«½tòrýÃÑÿ¨An¥98:•ÇÁ KzçÐH›†=>-ÊP$Ä ³zµ5Ô-l˜á lÞm¥Pµð¯ëÍ€£±ÞôêJó&mžk#áçØc?æ-sûhWÝ„Ÿžc‹ÐéÒ ã;Á¡K)YÝ]cO¥q« ´­Ô08œ‚MšƒP0rïâT<¬›àhí4ŒC®>^ËT‰Íêsì¢÷NûÕ=ü …­Ä%ÓW–ÉÈïV›þ8ÅWd RÑwÐX\7'@|¿\Çö¿€ŒQ£Â²Zx¬cõËZ…¦DšK”þßÈ\ÿÿZzønmž§,²'©gP]\=“W/õý†ö3×½]oŒõaD´Î;Eq‚ï|-=U7ÃŒPˆN¯Ks Nq¦€<=¯Ú§nn«%¸é|3ôeù“Zk¢› Uôû¾ä$îC¬S率)z8Œhʼ¯”ß‹¦-+Îü(œ}Ø×ãì—ɾ‚NØ,ü‰–CŸÅÞ§•q¥é,4÷Ø^&w g©ïn`eVcú ¹8%‹o/Àq‚¤LÆJŸD•zª`êzÑt–ù¶Ù L݉B‡ÃMf2œózè2Äí&D?~"Û?hÙl‚ên¨Æ(¡¦y€‡[`R'î»E€7þ¢FÚšr[?OæÏ+$M›…hK`¸Yi>Ñ1²å¼‰ÚEzk”wÔ©#°áuͺ,®Ð"ûÚYlð±¸BƒÂ5ÐŒÙZIÜ'ØÃçö3žÍ÷ÚÅpØ;ïµSHmÓ^×ΈmJÈê€;¨Õ¿‘ïr¯Ý°ºuï}ªkAõ´V1½À_ð\õO$û´³>§©1Ð(¢Ú%ú€E#… ÛVÈÖ™çÄŸŽ&8«7­Ð¬©Y?EËh‘æ«Ü/æøàK¨Í¹—ŠZ]! ¡Š®ÆŒE˜k$ª!¾„oQÅßÖ~È x5Ђ\]Õªòí±±d²‘¢ïS5ƒÂ£oÛÚãY sú9ÿ}^¬ðæ8†ˆ„¥Z¼ 'ÈJ§~ IšžX@ã®Ä2…l?ZÂ*ÆqGš·LÁO hŒ[§Jâùí×Â(—èì ‘ðcŽ%"3AÌ,iB´9¯#J<[çY—ß ÁåG|Iw…ãµ$¸ÅÍ`•å§|"I¬ã!A>ö ô_¯¥¤K“‡ƒ% ¤“s4˜Òå å‘ÓÿIú=¨Ä ;ó˜Ke cù…H²1Y̱OBåˆQ må™»±Ñ®Qƒ}ê fþ©¥Gª©úcyÊ£îKá÷ùëb¬¿~XÂÆ=h<Ëx´.„ƒ‹˜‘`ôÁ0K¤ ìüæH|Øld$ý¾;2·Î8"‚ÛDç˵äÖUEê'Lj£¿)¨¿ÙÑñç‹ðS{Øuvu…šrõß&ˆh`xu—×:§ôÓϽ®³s •4»](+÷vŠ[f·) ët]ÃLËŒª£(XbYx=òŒ^éÍJH؃ žPáל'*Å›œª¾Æèxõ™_Uâu…<ùÎLÈcŒLC‰ õòê:F®Gb?*%ÔK(.ª”½èîû“š.Bòanzeû™#ÃØ˜+2ÉàpvÝ5UÃaà>ÙàÇó›e¤ºgEÏ ÓD*Æ,{Û†é¢ÜÑ‚g§`ˆqly”&àAyÅKH…ÄZ9›ÆJHÑLÕìÚ Ýô,N61û½ ,ôu‹Ûβ¨[®;H¢ø?I¤1éÓ´Q4:ŸLSvöYê.áHkQâJyj,Ý7éDü•Žj–ù!4"©Àik’ÿ$ VÞsŸøõ‰ÚÅú¢[ãXVJ#¬ˆ|Ì|åÑRá/ÄcÉÑ¿|ʲl¸äwÅ9S{Êp7EúHfQ[ÖÑ3މtÀ›Ý+#¶ò öŠt2ìWÂÇ1¯< „sÛ® RëŠÈ6pû'h…f•ǺFAPI“'ôŠzã]‰‘õöe£˜Í- ”úèæ¶ñÄÆíã1 y>5ñ”m¥“ŽÊéS³¨+¤äô_'ÐFÒ,Ÿ‰2íÔ˜þg5{J ’SÇ.¹><¤Ä·®Ò"ì©e‰*¬ë’ f+j `aPa™’o…gëÊÒ••½ãhl(P`ýAiqS[ü`©EaY‹”r†¢ú\{Îo@2œœoé#à¯è58»Þ[íàm$4¯`²…„é_ÝÇÖ5|ŠÓ€p<~ wÃFŒP#ò’Gv¾yi1Ä®¢ 9¬ùÑEä çV_ãä *8þ¡¨±o` Ƈ~Ú؃U[œ~ü„‘TøbRXU‚2ñ.18ï.cÁ·è”iÝ ÓM-ô:™Áè&›±ÃPL˜1Î@ÉÓ@fÿ5ÉS´óÙ´ærXR㯟 Cöu®*uú~ ¥ó0ßÉŒ%ÍõÇó1RåŒÐQ›¦MÉcµ‚Tf×ú¡—ðW_γ5Rö«Í?•Ô&e|‹IÓ,îœGJYw%µÚ·Õ €B"<· ?¢‘?²‚ø±h öóüǾ…y9Ò\¯eäíGaù‹s­o]0,ù ~× Fq”5Mâ­[î¯B5¬¦iÑ”(.'y !Ò…2ŒJlCà'梌Q"ÿsZ~ý±Ôpƒ—¼0:œA«Å_kU°ë(…·ßé+V2Ë‹Ši3† —?•‡„¼îûçåáG0ƒÑžÊ?^±ÅR¤úólè&_‘‡—´Mí]@÷û·ù"Æ ¤!D 9œtÌ^ï`ݵ,*5*#©R®|nIH¸,Â\z‚h,QÂ/ÙH–Éã,$Q4ÞT,.šðïO,‚­™Ç~Úè¨&†L¯„{ú,!Ë—¬`½Zõ_?®_{aåÿÄ œ²¤"Ξ;¤wÛÅìŸaœõ µOÒC<Ã]÷Þ¥ Òü­ !žó¦Ñ/+!ÕxI™P­›ŽýÔúYÎ ¨Q/§º¥>¤#vèðµþiÈšKGEñéÃZ)æ —É¥‘ÇkT| lƒ Ê‚HrEñëâE,³è£ òÕ?vX^¬'þ³ã:ΰw)xG¹ TÔÆ~lï\—Bßø·º:ŽŽÔèrMéQ“ Çã‡Æ¿a°3± Í|3‚Åb"’KÙ^jˆ÷¶Õàd!Eö!v|žð½ƒ'½[+øÑW£ÂÁÛîÐùìf€ÄgL¤éXlakÈfGÜj–c § ú·;TùÛ¯>&ÌGóß›÷ÆÛ¢ÄN0—ž•»ÍOFõu2=”í-É:Û÷¬têâ6/²>¤Ü4‡ I sGƒùvÀS/ d¨æ:Yl‡¸Ñ¸`Χ,<ÊZbᛲðñÀвŽÜÍ”Ãï8½p=Ešµ]8E¬ª¦¥÷Iôtž% Œ«îœÀkKöa{’6Ze+÷Ì”LÛ^åÒ-àüo¬O‡ó‚3„xrà !ré¸9Ñrœ<>fWÆŽŠPã±LcÚ‘uҨʜêÂÍÌl ãÜÞöÇ=.£{Ïä+R êbvB¦Ó“WI±»pÁ ¹¾ÖÄSîo(ãz„ßE Nº©)ae,=ÛÝž(¦S%³M֚߇¹É£è&¼Ç.É™#FF³”Úd¬ÇI29 ŒÓDÐ)U¸’ 7qÓÝfTÓ —ƒ"ÓĦ^èoñ.žÖ{“ëiñaCb$·âÒv/ðR•pnÅ7øgr?Ö™€ 1ÊwÑIÕÓäò­iô7ÝÀSé®®KÊ~7 Ó=GŽù"áú{c½(PcvÖpm/ÁîÓ ›+ªØ³(mËÄ*Ü5²×9<0eÄ.ÞæØ9!¹p†qÀÛÄÜiƺ¢ÏÈ”Nn„Iw6øËÈ 8&Gßš«wä×7^{ÊÔ$Oé’G« ;²Í@ ñyR‡øU(ù¶%;©„“ÎCŒše '’'ìº7¥ –¸™ ­ù¿–®†{‡r•DÞè_Ô¯Wé³úôcf®ýõÓ= —ïìê…ÏÂIhôÜî^¸_{úiýúMJÀiQ’•êM‘0òtYÖ'µŽE/â·ù{'Äî9À¬›w>>‰‡¤ät|±›wë²|¾d™3Ü›-NÆê÷b/uÌ&Ê}oõrÞŒ;óͯ˜AÊùÒ ÑpvùŠz'꘺ð¡ƒTð›uñnºäû4&·|êìç»70LvY€Þ-í3|àJ #u±ÎéKé¾™Kª‹GÐl“M$¨ª[Ì&Jtð^¾Df}“/AO¯b×9ràsÑä÷ËNLX¢Lëâý“)·¤¹^º¾Ro˜3Ê‘pÛ}Ògá¼Qçøfòzßðнè’‚ž'IX…wÛkÒ\þ¯ˆì>²J#ðO6Ÿ§ØE×M¤‰ß 3I*›þ‡G’ÓÆÙf5^'â­äuŽzêu6§(ÑÄŽÈä³WRGuFjöv†‚L¤bø)H-É}Æ“Ý^ï’øF±ße}Ä Mzøe}øšûüð/´dWšTô]}ç¨W{µ¸_túÑ5e{jÎyçLÕÅL q ùZ÷Ü6GH·ÑK=°3i! Í£Ašºék×yÅ|ÔÚåûmž"–!H¯ss -´ñØM;Ü¡©ùÞP¯üJ ¶_ÏÙ+ŒÓªèоÖ=¸©ªhÏDü¯£à9½0ƒat6{ €î«ƒ•7¬endstream endobj 55 0 obj 5895 endobj 59 0 obj <> stream xœíZmܶîçE~„>’áÕ‰ïd‹ÈÅ®}EÔñEÅåÞløÎ{ö½åþ}fHQJÔîÚ¾ú!1¢ÓR9>œyfF«®eU‡ÿú¿G‹½ŸLuvµèªðÿÙâã‚ùUÿçè¢Ú_A'f¡¥ucÕêtÞf•Õ­¬´b-—ÕêbñK}Û(Ù-D}بú¼á­1FÔ7ÍRµRJ§ê“f)´k•rõºœ6Kÿ®þ ópGç‘0²íp¶Õ1ŒŽïÖ¿áå/·pi»Ž±ðà\ ¹°Âfƒü Ð-uó?…_–·œã˜¢µVsV¿¥âJ¸ãBÖð= ?tßÓÀ*ßæ S¶UZ`Â/œ‘×A:Ù !¯¯š%ÍëwQC¨ œÁ¸V ·Ü´Jv™ê.ѵ‚KQÿŠR·RqÏ ¤‚¬¾CÍãK3œ§˜†ù%gãÀÛ8§H¯œ¡âü(#YFšù8 NfžÕ¢2^‹A §$ ¼ä¶í˜ zxß,;Ï8ÝË‚zA8hõ,`¨c:âÇÂÔ½xBÐà± ˜j­Œ[µ6Zzx†mT«2q££Ð†Ù¹©Ž»Zª%ˆd†Ùðú¬@¤lý3üj{M–°ÍqÈŽW«ï«'¿ÔÿCÇ oƒQüï€ðìñüe×Îy?2]ifØšN1“¿8×ÑHöÕMë`[Äÿõ„¸¥ÜñÖFp}õÌå]À[)l>Ò¶®±ÕC5H™Cõîü‡Þ’*æ ;dz$Âo^¯rœà¡ †öz€Ò[¼àéG3E;û.÷x¹Œ¯…§oê$òéÐú.5^WåžçÔúK­Ð~ÔO†ÆÓôöåÐx? àX§Ñ9¿øÐø!“(hHáߦçÇCãMi÷%ANèì`¼ð³³ƒ…zÌø¦#⮲^q÷'­xKD»J}ß4TÆžs‰æ\û´£4Ú*œö˜MÜ´½Ygœû™Àc±9' O5øos5Œß)Ô Zy®ñŠ?$˜‡ ‡Y)?]Ôüо;#¥!>“ø«þÖ0ù#t´š¿¦[2¼l*EºÞœíÀœÃ,ê-ùGÜ&4ã É9JÖ-ë ÒŒÑ¦>@ïoá?Q¯¼³´öþ5ÎBÁ²¿I >; ü—M.E°V(ñq0à釴ûß/RãóØˆ£>_-^->VBzÛÖUK¼Z¢Ô•2Bá_`Žû‹½ƒªëO7'‹½Wl±÷/ûÿúþ<«þ´x~P½še”¹è‘Q¢÷–Âá<-ãT¾D~–Dþ9;A¼CãH÷:õü.Ý”ng×,¹žøøk–€+kò5¯’¤ûéöûtt‰ÝXgVÍë4°_\öi„oSëOéö?ÛõóÚV?¾^óúøµ”¬3ÿo#­+ %œ;oîƒvðë³?ˆÙó]»Ž‰Ûà|¿€¸áe=p±û){Ø‹ðüLŒÜHdžÆÓ„0‘ž¾Œ¤I‡Ú³_HËrjˆ!½)‰“Æ»,Í<’Ö#föÄ Œ²ˆ[\Z¢ÓК[ôŸ“Ôú>Ý’ÖûÔ—háé({¨wˆ(Û½*-÷°Ô˜óÌHúÊ/€mÃÇöðZè|>D.#tO68M@™ D´.•„fñ G<>$¾ã™yŒO+ €ñË ° „··™Þ çáæa1~TBî'º\"d1:Ë7oS wZÚ„óºÖCã] ‡ \g™ Ân³úï0Ÿèüúvhw8ã_LZ®ð¸/‡Ì×q`tMˆ‘“îtÊ3õœî$Í¡¢´¦kõ0t¼IåБÆnã”4„§)†Ä.SŸwÓH y §ó a¿Û‹/}ihêWÈç"Sá„Lûl¨°”qCèVµUØBUŸí U!–ïüÖa’•l¹]²³AI]Ü#L¼æYÚ“Ø9‹ë|Ü}—äJ¯¥WÞö=¹›¦s1ÇÛ+LØa³±5½óÉ’{YÈ›ÇCN8äƒ1ã¯Gç0aÕÑg9à}’9!8\kï‘g)uá{ J HZ%¦£ÔçÅy<û’µ¤ˆº´DWеZÂR =dßQéaI§·ÀjÆa·{÷5áa‹Õl#N%>‘Q¿éý߈;l26z™Nk¡ùtC5è!ÖR8QÆãäóRbç4¾¼%“Üg§Sš¥X¹ÿìÌ]—5ø:œ¬ÙÎþœ\ÌnùÖú¯›s2Ã¥z×]JÈ”¿ÃÏåØ4UBÙ–óß×ͤ>=°¹`¿¥ñ|47öÊðÀ¯¿@b´»"nâ‘ò+VöG!0…Y¸÷ž$ˆ\SqžXbϜߕÅ3ýêÄ–¬x­7}.&Ö!|E;Õ!¢í%!ê M„ô©µDCÖ~È9^2Äô„ýæ•-}“ÚΧ?··ýbr{ûkâ;£Ø zwÎå¿Î:³ó€d£!ãÏ‚$ltÚ¾m’{…^NŽHþ f"ØY6döcFlÄOºÀ­¦ð£¾_y€ &ßôqMl£_Lâç8NWKÁlkúíµáûKÿ]«Åïäµqendstream endobj 60 0 obj 2615 endobj 64 0 obj <> stream xœí\Y“ܶÎó”~Ä<’. …DRy°lÙ^—­øXWœ²S®ñîj¥Ê^ÒîJ¶}ºhàÌì!ùŒ+#.`ãëF÷‡_.YÇ— ÿþ=8]<úÊ./lù1üÿxñrÁ}…åðÏÁéòñ>TâjÉyç´Ëýg‹ð4_ö¦SK£y'Ôrÿtñ]£ZÖIç¬ê›®å”=çP¸â\È®oöÚ•è´SZ6§­êÖ5k¸ê5g®9O i›£v%{Ö1éèC ‚bLè¾ùT°®3V6_µ+hK Ñœç®[7µh®ð.WΈæ…’5Í™¿)¹†~ È «šK(cÎIþßýOñ…{Aç˜ãøÂ‚uš;·Üÿl±ÿÞwÍ>tÞÙž3ÙýL[*b·HÝf‘’(ocö6æáÃ4ßàOv§>‹+Sm2˜å”§“Q‚¶2wEõs2&a°9 ÓýjÃB\oœ÷ܶlSßDþÜ:9¬K¯ ï˜Þǽ՘"¹`$¢ŽÏ@ðw?{»àßh«Êíx?·3 ¢‡x- f6"ëã67+Z N¨P’:¡Å¾°Ô¦“:`ì6Šñ°""kUÃñaÎ\¯ÇÜƒŠ™ê‰‰%è’6¶t¸ý,ªÙx4½ë–gŸªA">6Rb,0ˆW˜°c~^ÛØâàÉfµâùQDð4.$<#1zzÕhçíÒq¨†¨§aôªi=ª¡Z ¡BÜVÉ4>\Ñáx7§ ¨øNxüLóûKBy¦¹‘U¢÷È#up!(D ` n¸iyÏÀ ¯†<]ý æÆê}FjÌm"yð‚Ò>ÓÓ4Õïçùÿ6’èþëšoNbŒ§¹´l*e[Ä1ØÀ €r¤¡"[ÜËNx:fÂ!¥ 1‰ÌܘŒo§ÐÄSdĈb_ERh:ëÆ›õ,§ï+•ãÜøÉyI+¥{ÐÓÉ”_gm©0§ge/È:SÕƒ¢½õ}|¨ 61+-‰ ‡ö™[ï)L€?·¢€.ù‘Ì2´Úz†–@¬ ¤ÕƒÊ:4áUN.BŠNK¯ËÛú~0YÎPæDUqR¤I1èÒb/è{óØTBŸØÔ Kð„(­%­zX/‰¤2=ÏÐL`2õF/rÕë\š¦fœBÇ'v²OTn.E.w—âåéF^)¦GÔìEIÍrEšhÝê©I-“ÿrÙ+9ƒ QªE4×›*²ÜAï$“žõ=Uy]¡2Ñ«ÀÄHÝÏ;K,Ðÿ#·á'bÁˆNG¯p¨V‘ÆÝÖáŽyqÞßJr­Ù:,ñs`+*(V¯ŠzÎG„z$_1 $ÁMùVÁ5Pæ®;ét½˜,)©ë–51­ù‘\ô°X@”+HÞ xžÕƒä@n˜4íY-¦sR,1—R(¯%ѹVÔtN­¡íš ጓ}¿¯ï7ß«ZÚL¯ú˜¸ÃÌx΀¨mÙáe˜}Ç]±¼gö¿ê s)»¹™c½¿27sÅ?uææ8Sß!½wLBêÉQR†«ôgR™À˜›{Í©S ˜·‘2Ç# …eRÈ4câÉ™Rªæ¾¼ v&faš"œ ³ ®Ã$n‡”a¯æ7š2î™5ñÓœgÌoi"?È á¡òjS&v$—ÈÅXÞ¯™¦êFPR„+ÿÐ'­’ xJH•2ãÅ]lj 1ÈÎ.YRW›y°ãà"°äL=²À.ˆ:;ö’,=וµ¹úPt"`á½ ïè@ír:ƒìrsR$ÄxFäøAö‚Ê$/íš9*,Ê­H/‰U ÃE”ƒ]]3âÙEÇ!1gçFCEC\ðI>âÈ›£"sˆÎÀw÷QòLf¶yÙŸ.úo®äBM×EÕ1ξ&Í…Y¼®:t›K”-U<ÑÆr»‘`«mf´UçJ3¥Ör¿u±Ù­KÙ3±Q±iÕ[ï­ÞÞ~‡•âM¶HÆßbÈ–’…D—u´ëÓ¾r8g’üÁÙLRÕÒjŸ§?r DzÂ÷OÂ8¡ló[û“7óé#á¸Pqº"Œ¬øsq^؆š›E­Ö›ÌÔ>IüøÓ 0– ËêZ÷«2h«§kÝç0c4XÂ÷[ *à '¸žà3Î{†¹!º›X#vÛ<òçµtùVŠ…¼u[0UÒ dGêdcþ4Käy²3-EΗçp(f°Q:76·ÎÇ£Y÷wj›Ü‰² ¯S®±†ãýBš>§4²cNU¤ºÐ×Ï«Ì8"œpÚ¬-ÝPTU#³Žüµýö×ö[m¢›ZûpÊ}~-µ4ìÔå*i“®L;ûÙd“nûañ Ñ29-ÅòmïÏnvȪ…sñݨw¾Ó!êÉŽYñšÓÏ¥LÏŽ#Y„ÈxSO¥Ô¼äà}TБŽu÷d˜ÕrRxZ+<£STÝâ iMiï‡5!­kÓNüìum²~ÝmÅæålô:žÊ³ïPG}û×ø“§’(Þï÷Ó¿Š"õdä£n¥J“t„ç€êyU† ÐÓlÿ¤º¼CŸ›¾Tq]ÃìëÚèN(2Èǯˆ˜ÆÀì…ÁÜƥðF>[1²'ãx›Kî38„ Ì¢Gˆ ç¡=±ðåâÿ]ž:endstream endobj 65 0 obj 4174 endobj 69 0 obj <> stream xœÍ\[o·~Wó#ô–s k³¼“R iœ4…‘´¶‚¶H‚À¶dÙ­,9¶åÄÿ¾3$‡îrWçHR9^q¹¼ ç›+É_ÇAŽø_þ÷Ù«ƒO¹Ã³·ãá×ðÿÙÁ/"V8Ìÿ<{uøÅ1T’J†0qxüü }-½ô¡Un°þðøÕÁ›—Û#µ¹ÀŸwÛ##‚Ü<Ç¿_æBµy ?Ã8 ±ùÿ|ƒ?§øóNð'¾xMŸ¥Ê¿áŸ?nð·m0½†V%ô潯SáËZx^ ¡/mÍ0 »¹W Ÿ×š¯Ká»Zø¦Þ‡‰žÜE­ ‰H2Š8—ôþIó~­ðCo §³Þ…f3º¬ß\”³ZsišôørûÓñß”’ƒô¸´Ç'°”¿Õ÷§ ñQ+CÉ¥øõ‘”a£8<j0v”©$ŽOMF&ÇHÁ >ÅîRQá«^á_ª9#ÀuðX¼yß#V]¿“±Ø¢^•ÂóZø¾·’ç“¥Ú¥çLŒ{½ö*㽩…ìý‡fºympApL\><8¾×E¦ê÷xÑãÅZxµ2×%@à»{½º ¬¯*5~ÜÒ#Nó“GÂsÑt2I ûI3hM|øh{4>ŒnDvÖðFH šRã ÀÀ™Hom%ÅæWìÇy@3–êA);j˜£œsHG5ÀÈd‚§²ƒq*¶xN5>Qá§Møpt:˜øEn^ƒ°ÄÉk?)â7(Ë´´‘¹?§ÔæEýšºÖzó¼‡n­Û|"ªz¯6Çiû16eñ»:‡WH`kÕqg[“©#•Þ 0*/)©‚h;§ªyNØ2¢Ü$›¾ÑÈ$7+™Èƒ'µ½2¬?mGøhàæ}¤–°pD6‹’KÀ$HnáíDZ½`4-%’!7#­ÏýáûD[dÓÒôÇyñ¤§Õr‚òr”A±áà‚+ßHN\ǫԄt‚õU»¨=”ÆÞâ*ã¬Ü|J£¤U iL‚6"§}\™µe Ä€j›j)ãfÖ j;˜°IÄJ§¬âåÜ[xe…Qðʰ!¢D•l4=™†I_Û¹¨¯Ùx®ê#›Ï„Ùã“-¨j`ë'`5€5𤴨¬¥÷´úR¹`‹jЄ¬a°½L³@Q¿„ešåX–ÆÃèø²žG0Èõ5¡¡E³´«hN¼b‰õ¬äxxFH‹ÊÎ'8ÕC‘ŒŸËüySõuæ%%+à'!Š—=Ô ÃSä¸*{Qù¼6ô %¢ñE¥Ë‹ÚcxÞ ¶ŠÓ©ÀIIÔiµË“ª¯ó")uý"IÆÅ¿¤Å—ˆ3V7µ‘µ&3™w­çéÂd ´x÷ŠU‹:3H߇²ì=sl+ëÇâô€IÄôËå Ùäêò‰ôCè×yÉ:±±e›ÿd–ZÅ3“à+à@͹ÒÓt¹±.öJ-²Eèd¸eS™ÞœtEKÓ2É>Æ»Ek˜%Ä”õ9“6øþœ) ¨é4bH% à™Žì‰üþŠ*¿±Ä´èè“‹ªE.3+€-é>¡1Bв›üË•;Š„½¯4„w¨§½Aо³À€Vì=î°'㺗UÊ3-ÁŸ™‚ÞÁ4@@¡>êèýz ¶hÑ„>CMø¯gž%â``'ÉÞ#FœðŽþ4Ñ_êh¹)–ì+”÷Ä;Ì”bôc:å;œ¨7ÁwÏèAnö2r3³™˜ßð´²ã̲h½‰ZÆX˜»80$°3­[F`d2±4²‰Ó¢+†cÑ‹¤]p¥žr…I £§@„HZ„V´q™TÖý Ÿ=µµ¸®ÑâfY‰3P^ÌÄb¥‹á£ZxÑc}´ ‚7w5’x572‰v†FµvaâÌ4š¨€à¹%Ü[J@CÔ5‘¦÷Ý(Ø9eÍæ3xT#út›ok…ïëãÃÂ|¸j8=X  P˜ÙÖq'Jïe˜¡miTõ]ä¯+ùû„šŸXd–‰c@ã,õaŒ™ YZz nîæ¿Ì#+À4!¯¹¼'; Æ÷EF¥lÕ×aÊB'Õ¯¡J`”t Íù;CŠH|CHi SÚIkáò+y+­æä8úkm°©*R£cŽÌÄ{AjäÜéž|D+€›5Ô¦MR¼FPç&Ëc©]`f€bÚ¦dubB§¦7–Å´oPØ·’1ÂÔµ’‘ë§N5G 2ºVjfƒaa%:Ö-Ž„7Æ~'>vŠ¢æzÐÚãÞFÍÜxÁEèL¬š£Z*Ø–›²ré&K'gL=ìâ@èÑÃìWŒùÜ?S-ŠzN²å1Ÿ˜×»#­ñ ²g°;Ìy§\Èf ©5f–² ß¦Rö¤JÙž¢lL˜Nا|“cf1PfT 0zÏ"û˜§wÝÚqXµ¢¨ç‘jéUŒT·J7N„{„_•o3` ‰^ºj¤g/ÊT;îù±Œ¢÷ó`• ÌÝЮü­6ú¹aq¹ÆžäÓY³ØG´t–ô˜œÉ ‰D·ŒÇ/ŽÏQ2Gº~ò«-XA X¬]ϼþ¸Jàná*3:L‚í•ì`Ñ©l¸$$%µ´e½LænHÉÍ–§xRn”+8Ú0î›”£‡ü²Ç"à™›ŠÛòó¤¬ô‡%í$ß]ààWÃ*Ò‹"Ò÷«d›Z‚Ÿmê†A˜!B.Å®¹Ð1rO5A]Ôñu°½”/T£°g¥ð²ñµj OŠš¨Tc`@šktHqöIáEX 3s~SäH1_¥!¢Å·-| ÏwИPjšbIEÿ̹Ýhßãöß·4%3ÕJ’»oñãgÊñe¼äÁ©òÝÅrx+&}õNá-n ¡ Tæ‡6Çdohø–"º1/?Ë&²¾wñ0çp4zóÏlïfÅ/º˜ºW5<6±ÙÖådXAS® ^N%¡…w¦FÖÛ-(“Çd}vö tE$Èqj5)%<‡NkÈ`Ü\¨½Rhè99Q83œ )[pp;ú|ÆûÌL}Öè¦ÔN0¹šüÍ¥ðhò·À\– ]˜NÜü„¬q+ZC æÅÉ.ãüÄlO …d‘”-ö.7×®fº møEw<$q¿Ä`H&*—™ê"\+Iˆ»zVêhG2g™k&{/r(¦x¿ËžrðX­aÇ6¨ÔähYÑ:?Ù_äØ!­½ê®‹6·vcw]Ïf,M]%äoÝ5øUÌb,$ÖZ™™k®‰e ©Eç÷s](X¾” ,v)îP ÿqŠi’Ÿ7Óœ®û®ÂL·Š´Ý$×e†!„ØYÂá( ±H\^mÒ%eóý!샙³Ž½&5cý,3)sB.“ž2žUˆx›BídÈXÃbLsÉxËXŠÌ§Ž µkz&„Sð·Õ‚ó4-¹Ð ²W\⥬žãN"£bLé«-¬ˆóÕK#øÔ8M"t½mdmÊóaRµŠɃût÷B¨ñe %Ml˜»¥©7Yç€ãS·G—ð ­~™þ’sïZÄ•¦'ú»­?ÛÙëQ6ɫΦîbª­nåÆÇjݱ–þ´-›¢?k÷z+gÑy˜hœFaP#µÝ©ÀŸŸp‡v4îjÞ&½ZHȦ ‡ôÃBv´Ý°k&fËàn%k¹Œ1ÿ”ß}^?ýW)ü¦>.…b[ŽÜ«¹IKrUö °¨Ba!„4`…7&¬c¸Ð@Ë0`H£ZÕ«Y÷þ'¥{¼’\87ÆOLpÕ@ýr6Z@Óãvj&C¡1ÎÈa@!á@lUá BLÛÅ®¸´z¨ik¶VNÓÀÍð:ESº;2Šàï1§A ¾OÎ$¡i\GSÝ¥g „fgdZ‘QÛ0‰1?úðç×üTz7ýÞÇu~ÄM ÙFšwØ+à«DcÐÜAÅ'™@N´Ø$‰Ú‚“Å:5F¶½ÀéCˆ‘Þu·¥K7Œ.8j뤛>×uëÙñ§öTÕ=]C41¢ÐL¯«7¼ kíœÀi=nûWí¶§×ÉéÇqÏð)ðý¨g QDÕ-ïBW£Š¶‹ç´{eó_vðNZÚß<45ÊÒ“ÓØíb¸8‡1뾤¾šÍ Ìžªç‰ÚÎò‰šnˆ±z{í—7!Ÿ-îr„AEí>š•½c ;+Ò¨zÎwy(ÙÁëåÍz¸£|“,ÎFÛEE³eŠÍG 7Q. PyHÚ’¹Â„1ÚhúLˆÕ‚ `© Šj³ksÐh9Ž›¶!Xcn{ШêXí3ÍÙøl×5ÆSZ!'à‰šÎb&¢ô}[(wöÒö4%'šãNOˆÄˆüêÞƒxâ)$Ü_*ɧçE‚*1®Xú¸2+«€¦žBcÏí²91&Ô’s?Ír‹l¯JTˆL)†…€U ®¯°{\LŒ ‚0u ›tTŒÞã~ìfcE®·š‡DjÛ~Úäö©mä^b6`ñT-œ5è…¬U#,—¶!±Æ&îι;ÅèµmD`Ó!Ë&uÒxl;Db|ÖôÈ—š@–˜È(ןÐ49 Ä8¢Ý“ZŸ)Úøë6žJ.¾~þÙÿ^}¾¼J/{"¹çý÷Åê¹3Aº?ª»É ¾ƒ ž)êwÛ&;ÿüP\…Óÿ8ydÍ}º’?‚eÍÇhåä”áæ üù7þ—<ÀýÃsi#ntªß’ßRÎ}+æmŸÐélù(ÕyÑØ§3󇊧™ã87ƒIUã Ìj<Ü“ëTzgþû…CØ¿÷¿âÏw¥ê£L”½{;éý²gº/¤Ç÷Í`ÒG8¢2aâm7Y—zèúfcû¾%N:ìE:²¾ÃüKG… nÁK§ØkçecäÃ:Ž‡Ä l_×qìk¡‡<íÝtÝ ·WïT Û¹ç…`«·€%Ç7¿ß­_w+Äf93Ðò€ßPìÜœ1ÆêŽþÿý³%£endstream endobj 70 0 obj 4438 endobj 74 0 obj <> stream xœÝXÉ’ÜD嬯ÐQ"PMíËÆšÃØc†îÙ"f³ÇË8þÌZTUju3 ¶xÂÝj©*ëUf¾—YzÕRÂZŠñ{uÕ<3íÙ]CÛïáÿYóªa~@¿VWí£% bîGk—§M˜Íà– ‚·Z1Âe»¼jŽºgý@‰uÔPÝô’HÉ8ïŽ{Õ­ûAI¸!Xw?_ãO˜.T÷¾1¬á] ÷4•ÝEω1FtozA¬ÕœÁAqA”r`qPBJMš#/V\Waº£¸†yð@:ÕÁÏ·ùçeZï8¢ShÕtwýÀ`I£“y.d4WÙüø&®£Ð´ò?Oq·Ìo>O8Ï‹§iÕ}ÏÁŒ6ÝW¶ðOtËà"Îd÷w.ÀT^ðª8ÑÚhéÁãÆ2TV¨–¡hÅ8ÇÒÚܰ8”²¸SÍ©óxÀ½ à÷/—?6–Ôôå‚=n˜*Û½ë…ÇSX,~ÀŽpˆw±NØ‚S2íA0Sܼ¯Ž‹”ƒªÀxñ<ã®LÑA(JoæóÅàtÛ€IË9y…p$chçɲ9l^µ°%ë“|À Æ(ÄζZXÿ ¼y´h?·o^¿=i~kYsð~<úõ[øZ"œŠgÄ0çR.MH¹—šê¹¨Â\§)OsOgs7v«{8 ²ç“»‡3 p+÷¼.˜ðx¼¹~xIÍçˆ-¦¹ÍØœü}Éž™X¢‘ékçÂ8]i~~›Óâ*¹"ŒëyÝÄìÁ1LÂИ¤@7AÛ¡©K Ç=X”e;«æ£¤žâ1*úœ‹-Np ÝU )d.CŒ{3Ì2œàY:/qŠ"œÚâ®n eR¤šÔuå<›½Îk?%ÍLˆï^tãÝüüzŠßàÇEú|NJþ*qí†}40|;˜ºu*\\1#¦³ãZÇò~‡\Úç•I~ÁÑÈ8]öc˜À@¬Å™Ï{ ÈÖêT—{v*B†#@aük:d[èôözb¬²5”{ ©ODÞ2jö ªµu¢êOQiÌ‘‡šÛ‘°¶0÷#c¹·OI§Ý݇ƒÂ%è„o'|0È0Þ û·h‡ÍߣáBÑendstream endobj 75 0 obj 1699 endobj 79 0 obj <> stream xœí\Ys·Îó–+¿awUÚÎTDYJèÈIl3‰S’+ÅK$+â!¢ôïÓ³1ƒY.M)rªl—W# ŽFŸ_70~7gŸ3ü7þ¹:{ò½™]ÍØüðßÑìÝŒûóøÇþé|k:q5ç¼sZ‹ùΛYÍç¶ïÔ¼×¼j¾s:{µPKÖI猲‹nÉ;)-ç ½\q.dg;Kë:Ëìbw©:«3‹½¥èzÓ ±xëôÚ.—+iYÇD¿Ø^®D§ÒrñæVŒ èðWè`Œ“‹ï—+Õ1 ãÏÃÚBšÅŸT‹Å5¾åÊõbqâ§7ýâÌ¿”\Ã:Ðä„Q‹+hcÎIþÓÎ7¸[ ûïsw+X§¹só—³G¯`+ÙË™\/WºSJ9 Ó‹Î è ^KÞi#ð4ì–RБ™ûùéz <±½àeðùR}+©€±=p$6ÓÉÓŒe4®¨€Kð¾4Ò²ï´Ò‹SdgüV~©jº•=2¡¬Fz_ H`>`>¼D¾J©\¢ÃH BEâ…•ŒŸOšŽ3½xæfœã‹K|2½AÁòÎ:*°SÞÿP¨àéÅ-D'¤£ #7¥¡#ÓFy€\Reù ·eá–$÷—¨ ÂÉNXP÷Pðc =eàCd‹M-+D ï=Kaš¹"•çñHLŠ&¸B¾ø®Zépò½@·á6j‹Ó*’Â8•o—Þ Žjø*nr%4tw6ìõß°hþs Yþïc`ÖÕëéŸM;×ýÈr­•-ÜÁKðôýX€8A”º@²nʰi©ã 3Òç~gYov„‘IÃôƒÅ`•fÇ|òŸ•4Aùˆ r¿ÍÝZyÈãî6 ¶ã|w ©ï©I²FôíÑ )pLÉ(’,ÕÊ_œQí =½C¯Jèá.h”U<)7™,ªzgt¨ÀLÎIj‹±_‡Ükʦ…mîuR÷¡~†½˜ÄklD P SËÒHL¤4 (m¸é²@yBž÷àÆdRdƽ¡×Ùy²ÈFHÐØTÍžIÀΑ£5Š)WoO4Vè;kú\#ÞWu‘Õ­|zç0:@Ï„" *X¨é” .ÎtÐ O_Ók†/Äü€1ÒM)Â:T¿KÇ‚ÕdïK’ ß—+ß„ÐKpxÅu‘d"2ú±ÚÆ:Jîr€o¤û•…œÅº"8«7üžÄ  DûÉß/AC!~Z¢o¦r2u©‹_š§ýÏJ×’)šXGO³(æYyÜn=â´ÏwfßÍÞÍ¥òi,›¯ðA¡­1;×Bƒõ[¬[nmÏžl;¿¾¼9œ=ùçœÏžü ¶þö þØþzþ›Ùóíùw“õÌšöTÏTð\Ëà*¾¢¹SÝ*/ ´«aµÇž°ë­æVÿR@ÜÓÒú}yü×ݼÐLÈÿ/4…ÙqS-妖e]•¡V cøš­%úpÁEŒ ¢: ƒÎÑn„>©ÕÛ>â[]!_{Fs´¤Ž¢é=th¹oÒ:À[B¨‰P]Ì­Ø×¸˜8ˆÈUH”½õ!± µé}í2ˆ™WÅi˜Ãy;ŸðvúÝÈÛú€î5æªS*¨òì(ÊÜ¿-ã Ñ'µìB:à‘‘ 5kË!°kê31Ò"W …>î³Ç,঄ɋҗ8pB/‚#œŒŒ Ÿ_ö! :ªûä:,õÆæØUô6–¦üæk(;Т*õ(åû˜ê`T¿®´#¸ö|—§hmú\m†qµ9Õ†c9ÏÐÀ#ØÄ$.ñÐ ‚ ¦Þ¤ å‹Ü\G—¡-ó“Ãp”èê n‡Àƒdo9 =u¹; NÏoj73…ê#K›!Žw–à³\<ÇŸ[ZÜkâÚ=ñ…M¯–´€˜Qñ74C'>H@N êèÕ%[ÌûFÚˆÕÙi‰!¬5Ì›qËù®K˜ƒÿƒé•Ï&šùËéR¡Bɶ¯Â€/}ÉxÃúN¤Ïõ( êÑCUGE ‘¬yaz’âv0šƒûÇrè sA¶ô“ ÝÃZ¦, }7¸; n±çîŽ\:+&0é‹ÀÊ슂dÕdJɺϡÐï« ú†J;ðH%£ŽËal §ÂÉ+ÍeSÅüÍqe‰V×ÊO$\ATR½ˆ™ÊÈr¸Gç®Âs08_aâ‚ÀkaҚȞJ¶"aË=pˆ8¼ÊkFÅúRð¬Ë̱±®2‡Æ‰ÄG¢G[ëHBæÞp$Bªfv®Œá!ù§ñ#Nø÷#G€jµcGb&¦¡èÑ’pXÜ3u\t»šÙïVrCñ@ÒXíêÌÜk£äSæEjP×1¤˜ 1;4•@šU!PÇ•_/²÷èøiIéy¤t? èZcEgñ,Q„ •ƒ9Ò¯—y•ª³â¸ã‘:ß÷È£¦¦5œ·Ž}N×)>DK"(ž¿ô<ÁÑ:gŽÍ8Þƒ21Þ©·—#©ÖùÝDtÿ<\T•Öo0¤3ëËl6”šÉ~e)¡“ªrå¤ä¨Ü¤â§é7‚J@,÷ëDŸÝUY'Ò›Ôî{ÅÖ#±µY wÁœ¢hžcnò#þ` ÀT5–èßâÏó©úª ßâLÃs(T}j€ñJëñ9T¶°::AfJNXÆÑ)ˆTjx?Ê_ «ïGy›SŠæ–ëi +¢¾}ìA2Þ‰³¼Ú¢‰n’ƒ–ЯÊÕ RyYk éŽ+,=œ×¤S¬˜ñÞymͺ&cJ‚Ê#Z€h]‹7)á¦>eþÁ\e‘¸qeÆ3¸:œ]XÚëƒE@[Œ7ÅÚ"•çÈyF‡ºlR±jUÉk=Ì Ko-VëK.è3\F©Éz­î1ïèª|<¦‹÷ /iªuvˆðµkžôUŠëçÕ²Îéü§ÕÀh¹éÛéÿÁ„4½.2Õ¹ìÓ[ÛÈ)X ãEïI)0AcX–ܸL9"Wõ©ž?!êM³î×:“C5â*ËúжÖòëxÈïyƒx=^¸Å ¼ƒ´Ú­?²½ëvðÏ­'¶õ ;¯ÝšúŽEº»±îr'–H¤7>WSá ¶6ÁtR7F‚U¥kâòF>Qãw›Çhδï~²ÞTÞu&«üWÍâÑñ7_c 3£W3¸ãQêÒµ±l.ꓜ֕ËÉ{©œñr¦V¸üp¾Õ¸-Ó k’8ß¡7;ýÁŽþÂÆ¸j|VºæPW ëËõ àõ‹ ˜˜^]÷øÈó1ð3Â0v©€WïíÄQõµl ःâÂuX‹¹ûþbq¿ïÇJ0‚Åi* ka‘m¬Ÿ¦k¨2–P’dZV¾Ñ'‚J×œä ž.E‚~è^Ÿl˜Ž´$®>8XGã»uèAbTƱ}<øh9¼½¶_HZÝ8æbk'~¯‘ß­¹Ž¡t8×X A"ÏðÃÏLÏÆ8lcYÇz÷âS ±5ßàÈåÍp@ÞQ o –ž¤æ’K?ž±rô¢5¼yµd±×exsõƒV¶ª¸fßü¬pwõOßx±¶sZ¬žaýë‡5¦O%&:¦ÛþOŽÜA–„kî·éʃÆz$<†KÊçIȽ_”®,t*ge'-©ãqn$Õă0 ®(ÃaM)×1w~)3¾Áž'T`¿EVÑÊÝJýå_§Èü·-]ÜoUF¯Â®)ÕŠœTÚ™®Ž\Td4..,}w…ÁÀ`ràñžFIrÀC@ ;ñ5]9o^´^»ÙkÊ`rY=^™¾j û²ÅÿꋲoEÝžÞDúö£IZjáE\P¢ž…›²þsM—N_˜Œ¯ŸVŠª"×õ‰hÏ[x}'¯P÷/Zv1õ!HÙ*îïù&ûóŸ)òbs½³Ö¦Ï¨Œw²K¡œŸ”;~Nf¡¯åЭ²³ —o]ºÞµ*9ø’ÅWµ’“_‹-"þø¿Ä¿Š<~Ç·ò& ‹Ë²x¿LßEù¨TÏÔ¿V“u!„Œ'ñíq‰ëMAû"¦T0ÎÛjz¯¥ÖPœÂs×"³· Ïœ)$Êû•„±Æ‚}ÙxŒ¢Kô`¿+ŒD§ïß$™¶-)6ÛÃ$ÃÏvØ"¤úÀ,}KV“‘ÚÏÔµä>2®¸÷r$m£½Žµ¶»ßÚÄ[:w.Ÿ¿,Ëü8Zf/;æëÁà’Á[£Á7Ù¡_µh,„“hQ¸"§§ 4|\Ö*†ý0"æ*ïd£u»ðÿ¡¸kíñg…Úm‚Чè[þ“|¢[}Ey×Ǿ?øæýýóÈý‹o59ê;EûÍ'­Ìâ#Ú|Ñ~ñ­n,Ú?Ñö¹Q}iÑŽ¾ÄPX)œ¯¤w¨<ÀàK ’Ñùk“ïfÿkï,­endstream endobj 80 0 obj 4154 endobj 84 0 obj <> stream xœíkoTǵŸ·ù+õCw{¹óž©TU „Š@§­ÔT‰±mÅ^¶ô×÷œyž¹wîú…ÓP¡(뻳sgΜ÷kx3ï;6ïñ¿øwçxvï¹™ïŸÎúù7ðÿþìÍŒù óøgçxþÕLâF:×;6ßz5 o³9Sªcz®븜oÏþµx»\‰ÅÃåŠõÒtÎ-VË•âýBà0Ç]ß3¶x¹\q˜b­^æÁ3˜ß;x6‹Wyð¨Ì<ɃÛeð,–ÁuÜ÷k.^ç“ÖÎëÆzÿÞú댉N)gç[g[w⌨qX~’̧ºÿQȶӂâ8¾.ƒGyp¯ ¾Ç•lç¬!çÙníù6V§øî£ÐætŠ•ì»Þöl¾âf¾µ uá¾ãÒõL-¶ðû~ÀvŠ9xW,^à÷»eÒ÷áàÛ8Œl²Ø-sÿ¢÷¯Z‡|›Ëàö¥q´ÛBÇiD‡“d¥rrz”ukѳò{y§%ç-˜ ÌMjí·HtT`Þ*£_—ǧáQ »x^F¿«4@m¿T`‘-Ò çÈ BëÎpP³ž NËÏ]~É3Œ®Sz¾B5¥{¦ßGšðc+ŸïE{š8ÔSG ¥Bø¯™Ö„a›ÈÏÜ˃°´ÚoQÞ9hRý´Eõã­ÞµV²'yµÉÙ{‘!˜¼– dìPÖÙ„ é,lÉ)1÷ÆàÇ; ¿*p7’ÑoØ[ý 3¼F8‹ŠÄá"i<§Äl*­tFázHÖO¯¿žØsÓFkŠ\é@»[E€#¦í´E¥ýÖÌúÀ4›Må@a4(ø¶ˆ3AþÉh!¦=Ü׃H޹—´vÔ[/3ÁÏý3ºDÒ qá{Ï™¥îÚŠƒœ3çæ+¡;†^Ix­`,ë=o¨NJÝãy$<1ÎÃJµãÇy°NQ+eűNçÈD-Hëlzy{©¼†„ݤSþ¬„æÆ}gP»Åw=vÞgl´mW2<¢t &):8‰K¿. !„@2Ù P²Üõ‹jm´ŒˆâB ¢³ÖAÆâ{†Ž**Ç+"ï8î9_ÈÖeÉÃ%ïŒ1ÂÏX×À¡FêUǹl`Sô¼“JP·—ÂKGNâ Eœoa&×鵿×h^~ã&ˆRƒj§^ÜŸ,9¸|ñæù L8ƒSÒ«3ç`9ºBä>ÃlÜ«g@&)Òiëò"b'¯è #¾ c|C)V<í 6»H è(T° àˆ‚‹æ^’­MjB¢RCÙAÏôÆ1ñg“$Lu\˜ %—~·B7Ü‚4oQ³« sFXï¡R`âLX—.N% œVzO__qŠ/½C0jò.®ô²Ì>*`âBíå’X¼ôøÀ EdJ,nœ.g&àì‡uƒõj2cÀ¥²0ê}2ÊX²¢…"³"à‘K¸aeñ%@½y;.¥Üš=›½™£ÔûôÄ xÏu§í\jíÿîϾz4»÷è»ùÙÛó½Ù½ÌÙìÞ·øñÕßîßGæ¿›=|4vÅL5ì8nÓñiú•ÅõùPYì6ìÜý:° >€ý åóWq·åC½Ýè‚€zêQGF:¬jQ-e^$ F(֞ř$‰¨ƒ`##Ëå‡ U€ìбss *-¤õ9JêùFë½nظ.™Å篘•>°ã*æŸq?"Û§D„3ªŸ§?.;¹žG¶kíŒÞ®ÅR½85ÑHvã‰Þöâ7½!R½•Ìù7Þ¹M…wT+§z+à©mÄavâsª…OjÛÀû9=ËL³ÎÁq=Ù‡¥')^%Ký°¨bÝqèVâ¯ÓöÌÄwUfGjå=Ò;yðUK “H½„ªw[Ù"¢Ä‡y×ÁFëÖšäõw­Ý-ù©(4…äwÈûÁ)w‹“,ñB?N$ÑtZæþ°¬y$.úë2ÉNf’£O‰I¦Z”6k4݃£ÈäwÏ%`ä9‰½¯Í£ä‚`ªÁN•0è°€†9i‰÷‰MÑ£kBH‘ž{—q}xbU—¢_ZBÖ´<ÒÆX0ÈÊ›ãW¸Fšª6Ô)| ^©q.¤Púª!ÈÆé}ïc¡:²ÈDT͈;‘VT®ò„ë;Dé„¿Ïɶd'rŠ*NSÎ4©8Ë:Æ0Œ‡4Ú`Ò—Á¦ÖŠ”øÁØúnÊp‡KÅai¯n¹Òåaú€,võ‘¦AÓ1õ˜ªè EªZ;¦jp„uø{"*°Ì©2‘¨@½+À¢–ôCˆu4)!Q½ ã¥ý%ñ÷~Y ÿd§!%M`­*ZtœM„ùójð¢ é­'¨þ¾Ä.c¾ž¤ï±7ács’œû9BN31"æÎón Ñ,çJe¦Üµ'\+«¤ŒÏ*M±°PP©®,ÁÉÏWº+,´òòr1ÔàEËcZµ Í*‘º ¡'RXÍ4¦’D ·ËJŠê}XF—ÇåñEU e6et "dÙr†$òpÆIp+™ 4Ε$CL*5'Qsc-/„ö4iIÍ¥TéèJ—ÙC`†sÚš¤}.“­(š­døÆÔ‹Z"t|ŽÅ>Çb¿áX¬ö¦K­¸ÞÞ¯×ô¨N+z0 àzзäR'G·ªºŽ+{ ®{’õšEå·­8¯ªòޱãêÜYdùÄ)uÁ˜8þ«0†iººÜ0‰(8T•tJ”ö¢£>Hp&1|^÷dÆ‘”8ƒŽ…Rû¬_øJàmžÚ@F´è^VŠØs™1ÙÈAÂLÿd¯ ÑÙ›Ø ¼ÜTT5}ôŠ zCUu(&ñk«|e¤njV¼LÎŒ‡æ–VÙX TB8j¾ ÚQ· !ÚaäiX\&¦&Œ´¿Ä¾fE•Yq«°)¹Ö‡©å‰¬N¨Ù®ÁXZrQw7$\À°i’ÑÜÉžùiò̳×u$êD“í¥N¨9¨MæyÃØì`{D˰SÎâ*—l” íTªuHbHy?ŸêË*ÏIJ°¤…ŸLÌýÜBb%YBô£5ëBc`ÂF¥áäŽf©sÆzuÕnëàPå5je>.Íò÷ :j6òª/Ê#}²9¯J˜©êƒäŽù~GÒìE¾v’’ºU£Åkì†X•Ü·2Ž:S³mj-í+[^kiÙìrt}agLn’÷O–¹¬&hPeŽø@ƒÞÃB߬H¼ýsmU˜×7ªå3ø=mÍjØ,Úkª zÅEФ-g8d#×ð3¡Ë)ñä.îe(ÿQVryJ“çDk\¬îÇ}HûþŒWA0ºÓÊ;SÌãÊð £y’ÌÉ¡D ‘ÒWV&×”¡’4êÉ8xöfUÕ7xè+]Õ;àÀöèœo¼/ÿ‹jõåå• õ¡â’÷³ (ÞÙyiíÜ­œ9W@‰¤c[…WV"]¨yŸAÿô œƒErm‡5РP;Ôj†xˆøugè%V! a@B°?aç®õÖ`ÛkŒÅO‰w`É?âX0WÓ^e_Ò¤ˆGkw £e×V:oH=ì¼ÅwS±Š`ÁëT¦"! 8–ƒÈbõ&ïD4ú“ÁŠ$ûÐRQeIÂéžuŒíŒN¬Ó ÝjGÔØÈy¡I€Ð#äý©¥†<Ä–S÷ŒXÀFg3¥ÔË<Xñrÿ”Ùÿ/H?v×Jä# p œè+¦ âÆÁù ˆ«eÄ_€Iß”ÞÒP•Y4¸»ÞóëHðseÁà4QÚ†Õ|iC? à ¦à¡ »nìãoAé¶&<ÕZylõkmvÆLúšyáTlt§å"#t¬íúìãec}ú6µ9ã…|·Á:™µ‹ Y¬xwGõ!C(Ó‹YÆo…e N£ÀQÌð‡ ô.äûÒÝrå°ý‹Ç& *„ø¨±é[ûF)Œ«ÜØÞë¦;-ŠÅ+HÊæ<òê™[\q2{ZÕ“€/êig#Þ(ºÔe¼î„žÉ ÄÂ_ÛäPà¹AJ ‰¼ŠýCô¦°tj]è.†l3^8c|sÔRˆÏ¦&æ#~QF‰} «q²K*rÁB’pºï+üã&¿ªÌ®woè\®lWç|¤WnL.ÚÀR¾{‚Nº iÎ_–ð¯Ñ`-SyÛ¬5tMÈŒãvôÍÍDä†ôÒ½o?¼0ùÁñæ ç>ž–Xüqœ¼(#zãÛª˜ü6/ÊÓ¸ *\”yÒxëb€¹Õa¥[´>`—ü}+gTIÏÊ`™Yò"Í®CS’!1Ö÷Œ¨•¯ªP¦Íe½ÅÖ%`iFKûA”œ›Ð81K›ŽlIzL››4|}u~5·1æGyg‡õ¢xvi~„ Ñt£`gð2gð0†yIâBV÷R³“·µ´w ¹íií©~Ù§¥7àB»!˜EÈßì%ÀùЛ»DÞ7šN” S{™ûy¡Â颣^Û܆æÖéùðn(šLü¼*"/1ûQœ‘õå€Å+3æ{W•¥ñáäð²FS ÒieÀ/ZõíÊÕ\×,NU[ÊAßdHóá?&Ñõ.=Æ“WítW_#m׈®’zó÷ØÕ­&ª`TV—²š0Od Òíü¡^h™EwÁÝÐrǬ7„½a¼Å£»õòfìF¦‰`TodÁ´G0ùŒ¡¬’¼r¥ÆZÊsdëzÓÓädlަ[IÝ *—¾ŽúºéGcU¢*;T¹ 3aiÊfú`½²»‡Dgm¸ºÊxf亟hs3WÝPÜÔâÏu_jJ•’øõ¿wô?WÓ›,Çz‰š;¡ðÏmqp4¦‹°„åÿÉ•$$έ˜×oCÈÑ4ß>„0\÷užˆôƒ‰*„¿TVª#¶TlÜòQ笈2ÞUõlêŸáÝ›62ÔSë iŸ›õ?7ëbÍúþש:øÿӈܼðº®ì@$]Á׺K`þ_“[ŠƒNd.æ’ŽÛÄõ?yÑî9õº2†AÜ|€.r vlŠàzÅÿlö_¦ Ùendstream endobj 85 0 obj 4437 endobj 89 0 obj <> stream xœí]IsGröÖÀxB³k¯¶c¢VNˆ”DAaÙCÇ$ˆK Rœñ¯wfÖ–Ù]ýû PzèW]k®_f%^ƒ:ñ¿üÿŸ=ºÿ$?ÿÛÑxü%ü{~ôúHQƒãü¿Ÿ=~pôO†iœÔñÙ³£ô¶:Ö£¼=öN ÚŸýzôç“ËÍ©ÆQ©“ëÍ©¦)FrU>ßœ:=Âçpò‡úðMkùK}øª÷ð¼=|[~¼9µS„ÏñF£¿o-_Ö‡½^´‡0¦ã0ÅÀ^º/95Á/†ô·^§rIåã»ö1¿eMüõ–tñvƒ§i´œ¾¢SüG;uÉ åãÏíãuk{Ñmû±$d[O•œ›bðwÆýç1îý'*ryzªF3 Œlà`F•NäÉætâ4†wÒÖ*­a,3@7ZáPÚÉáAØÁ œ~…lâk&ÖôEkJl,îUyz¾q¬yþÍ1(‹¤bFk1Z„ΕaS¢=…™+wòÛÆè!„ ò×ÚX Ôò)ŒSN“a0Vóù·÷òXÖEö0M –t3EÖ7öÈväjBÑÙÀÆ$rÓ°C½\µÆyÏã°ÛPaSÝÆBŽXMN°R £Zb! HŠKR%– @ŠŽ‘ÚƒÖòá6úlÿ¥ÿì½ôùvFzØZ>î½nêCÝ£ùµy&y¡Ø@ŸöøèQ{øíV>:ù‘&Ï ëãÆ‰Oã31ábn³Þå”ÊÇG­í·âèÚ¤ŠKªUöãV=í å¨xüÝ*È/Zù•U0†&þv>ŽZŸ'ì<ÎïƒÏ†±QLµMó5ÓW+ØARnÑï…w¿KÆçm5b„‰scÇÄ÷–Âÿ5)l$f úAñ>cÓ¦=$âè÷ª¯Ò5°É¾ÎµQ–¦¾Mˆ™ýU¡Dõ /XpË(1€fI‘ØI§‰„Ô ê¯ ÝK„;Fü{ǵcÝ|µ.8òá°îª˜:߸žw6*–€?iøe»!oõ:4Ôf½…tá°ï»ª¶îòϨø-ŒMv‚#¸CØ1>;‚ë|^ÀeÍuEYã,µ‘?¢CëB›?ÎKÅŠf H ]M‡?ÐÎõB‡á¦ Œ15rSQvey»úd:ùE'9¹÷ …¹n„Á ý—ì””å8(¯¸¸gùI¨h=¯Si^S• t8Œv‰XLèÚì3u, Üñltµ“©˜·@êUFÖ >c Š ·N,LdùpeKÏ,WųsŽ#ù*_lÔ÷ …œ§ÉqkÁ0™aU¢¾Á^f> ›é‰/6ð! `˜×`â4Í#Ü@œQð«î0• „§‚>Q:}@@ÕjS8)z­5Hz? £lÓq6ecînö9í+ßšžýsžÃz¨.3Ó¥…ïÍžÈWµàá^Éod^xÔE¸ZK¦ò?âû8ؼlê kr‰m™³~‘ÉÅ "ú/\î¼CÈCá> ˜ žå8AKLÐêðu@-8OÚØÀhŸøçá_„èh€þDé²"ʘŸ˜Îlê·\7­íOmÔÝŒp J:B½pà Âð†¿ ´Á䛓Z¦Ö3cðHzt‡ë‹ vÑBÖ ÄãL ºÔŽžWµµ—H„#€W†ùt V°ZÔM=£"C”ÅEe},<ö¼â%^;#l"L-Dj'¤ÆÈhUø’VòýÇ"Êæ‹Œr/ͺÿzOH å'ÌkQ  ¬¶(à%-¯ƒ\Yùö"Ç,p—,7= A&èÇæXEzû‡÷û¾ ôU}ÈäÈ“ (.ìu4íLzÖ’£Âáü :«2“š_¨œ£ì ²CÇð¦Ì¼þ8›FšÓ3f’×¢N³–uѺó ÌÍŲ¥,%t”HiÚb03a$Y‰\»½Ð³dܤ¸Ça.Å~Ö$»lÝäV&’ÒwàLfc§ÏGD®#e z-¦÷‚¥\äáhÄU:6¡ËÂe»£ÑDVzSp20<$Šý#ó¾"žFjJ>Ä0Ó5ކËZÅR?Û`,Úƒ cÄúpG 6*—"Œ¼‘€`G´‰RX"\dÞ¤ ž/³p)ÙטN8jбæÐmÐ6X2ƒû=‡êXšäaÐý¨F§ßaXe>|¥î*ó ,Z¨C_iA>NÝ6Ü?,ý7Ϫ:…fÔ;zvF;󌛆 3.£¤Å]W ØE‡ ».¯6Œ™ÐûÁ‚Þ]¥>0ÏC.(ÖoB°íNgŠø×ÅJÒmr<ŠWúÍ6‹BQÜKžŽ`T‚s·eùqƒÙ†diÏ.}ÔŽ-Å$ÕdZn7»}ѱF¶å#r¶ì‚ßÝ o^‰³Ë-H`“k …êÊõ'Ì+‚§œ&£Æ¦«T‡Û+˜>9N{Ú+t½3lB$|°dÓ5ºY`pRb»~Ù§t¬NuW5ë¡Ý™’ªíïÙôÓfO·›îG>J@;:)hEY Šf½0ÎøŽ£ÓŠKö{9Z1 ÒI×–ðMa.Ý‘î 1ŸM‘c[¤¼ÀëŒ"n¤ßI¹ð—ú¡ä›Ð:âÁWÝÐìGJÒ¹mްfJuîÖÖB‹g$žÕ£ÀÃ3†’!waÅYؘ íÕÞ°qâPn*Oñº/!²t*ɱƒ¯Ö¸4 U5£¡a""©x”¬ËêÝœŠ|d½¤™HtÝ'±ˆx~?…¨õ<ó7ÓªïBȓй•p_CÛtúÐ+¥eñC¾Vl¢¨3¶9 Šç‹Y"eÇ%T}—H½©lŸ1lafÆtûVÖ±YFæòýVã±ÚÛ½øÎÖÀ¦ 3»¦ÉÜû· 0—·Ý¿È(ñ.! ‚îD—‹„¬Í©Š¯Ú_KÛe[>R‰ó 3¹qØ7’ô;Y—Ï7"í­Vu·DihÖùm&veè-ôYq,MKzc1_Ñ”Œw Q3L¶c€ìŸÍRÞ*²Æ®˜êEôSä¤d‹c¨~Æ4+‘ šMV$ÊDÏÀ–ï9/„"ãy+èWƒÇ>‰ŽR3â ØÊ„¿\·ƒË$*q°ä"[ðuÍ lï÷ ‚T-gf"<«Ú›q~5©ºCá+¬'ÐÊRéáû•ªK ð"6ßWLÄì˜Bþ+ùUv™aÜP*:"v<ù„’áoFLéÊ„ö{tŽß( ØÕÒhìA·–óóMÛf×ò Û‘vùJÀ®Y(6<òùZÍÈÌÖÇ%×Êå=æIÜŒçºw Ê ˆ1Êä,ÁŒ%Ó{œñ‹ã—׿Q Æs|ôdúD±s+›•‰]•ú-: /Q·“à]cÆjW+,B¤×­È…IÚû{hkVH²Üø¾I¦ÌéµÀ6£KkR†Ñfë–7×nhUMïÞ½ìm0f´â_Ah²0ŒjئLm²šy¿’ƒv‰õK#BTé߀‚}Aå›yºp`¹VCA0¿˜+ücús®/pÕrIº]¿j“`q$‰›k«jMÛæ_鉱¼Ëà[/YÍ?º¾å>ç”ò\ö`&ª—Z!% ãÖ_Ä»Ó"º8‹˜Š›ÇTNˆvV8NŠtÄÕ߈¸¸¥²Õr{w£vÊ6I,¼ñçÓ µ ™$®EóeÃë¼j<Ðȱ» nnsxä?¨nH)4sðê¿hT›•¼nž¿¡ÓwïÔwî4,ì™×г"/䋺iúr©W@þ7–LÃ"Õ¥àrË;'Xê…è-RìáÀ×Í?ìÙmp­ÇXYb :.R¡¶u»Ð¥¿ä²‡sš·aþ÷ŸVd»T¥šn09ÛEß¹=^" tœ¦ùæÐI Ì*ûõ(ü¢]Äžz&YîX¯Äò™¥…Ä„Ì,oä/ ™mz¹èm|ÿ´äK’;+÷tja‡YVéAÙmœçPxyÌLN>;H¿‘'†^-Ùà„Õôó\o¯ÒdÕY§;·‡æ"|a¬*ÕÊ >nv'ûó ?6¼‹ýY„ïÛG½î²£«J£9+=5QÊ+Jç:ä”kJIÇ:§Ûw‹Æ<}Ã3ÒÊÓ–EYÊÁè-µ×òU’.‰ ´'PÉ«ý¹¤ùkˆm÷ñõšìI—7Ìj‰ÃzÕá0W»%hÌK:³Þ.{ !›*>RQëïŽþ†/Y¹endstream endobj 90 0 obj 6091 endobj 94 0 obj <> stream xœíÛn·±Ï§ýˆóÃZ/oK²E_’‹hyhŠ@¾%Dzìº_ß^‡ÜÙs“åÔ…ähÍåò2÷Îð—õ8ˆõˆÿ¥¿_­ü`×ϯWãúÏðÿóÕ/+:¬ÓŸÇ¯Ö_ŸA'é¡eð£ë³g«øµX»iÐëɈAêõÙ«Õ?O~Þœªò#ï›Â¿‡q¢}½ü³oç¶™Ž›ÙÁƒ¶ýp©£ÕâÖíàÕÿô„ÿ:ûËJz98@çÙ“ˆÀÛÍÌcµríH·íгzsÜH¸ñÓ¸óS¡c¼‹x‰Ôt‰?o7§Fxè.Ožá¿_¦FurÝÒ^ý_œ<ÅŸ7¥sÙcüçþ\àÏO'øû¬¼~Yÿ¶4^×F¶çEi„iµÑÃ(¦“{¥ñYíùº4¾­oJã}ØíèNa?±ñ²YR„† ûˆï¯¸…nJã«Úfr€;KFzQߟ—FX‘cXÓ=nõL%+9 “Τüºv|ÚÌ®=PŽÇÉsc;{¦›vz2)ÁHî{ÕÀ4?¶»N}#é 9Œ:ÒÞ4ÊJ{,àGOpÍàœk¼©•dÚäǰ!ô0ýjNØ5Ó%…`~E6>§ÿën"Ü’Ù걯Дêç €} ü>4ðíûÞïdÒÖ™þ÷8ÂÆÁ¨åËŠlí‘hÜNÜžÀ~:•vÂû£YðIa¼‹òô¶<}QCÇ3ß!˜ŸóaK™?<øA8jaŸ*€‚•@zp* 懛S18çÁê•`i £ Þv’} BJ©”Ò@6h+€¸4@Ê>°Þ$DÃxõË‹¬µŠ4½Ý(˜v’½ÒÁl%I~£–¯nê˜ÚÓd'—‹­;Ú¸§o쓇÷&ÓìqV«4š“Gu„n…Ré“!5EXvÞÊdaœŒŽÛ‘ ‡+e(J<‡Å–½Û¨ð$ÈZÎ 5Ùâ Š Ðu[Ü œ ¦Ë uˆÒ„]/#¤øOä@k‘`ÒhS¤9­p¯:áu­ÞèŒWìœðª@ÏfÌ)Iƽª8|T7·•ñŽƒ^ÖAgT<ŠLÄVÐU—·‰z¶£F‘rÊw6U¢xe 4Eñ¹ ¬Å½zšùý{¤ëÄXpˆ<É2" b2O¿E|xoüÉïjk`u†8[Aü?ˆ13"RÖ~Œ7!3](`F­Ä"-Æ%¹½Ø„+*-¢’š4 Ä„ÏpÙe‘ºmgDˆ(pG 6ã3‚lÍßm• ªáÛ·œfúP%6ëO°ò`MÆ=ßJç-Õök’¬ñº ÎÓH 1ÕæžÆÂŠ,rÄLB!Rñ·(#"ãnƒ¿ƒò¾óöÖ ÎN ÚwBÔ‚‹tB{t Ò$v|’>‘v¨*ŠÓúVdXŸåDfUÒ?’m&(4µ¤0‰ó­÷gn$Ò wµÈeq“.ÌV6pQ©XLr“J?ÈÑPå‡0‘‰Ø¬HBÚF~€àŽó4‚25`¦:â\h5´t[M{©Ê£R[dóIÂy‘®<«) ™*"2zÕÊÌ4JÀ®Q{qÚS«1ÒÎqkUŠ'éä`„Çœh/òéu…[•ñ½ô2ãè6I` Hhã—”BšŽQ²äàwßž­¾_ý²кº=Å9J˜Ä­Í¨=þ}üjõõÃÕƒ‡[¿}sótõàǵX=ø¾þû7ðçáŸÖ¿Y}ûpýýQb Ö!Ì‚“„0qµÁÞ4Bu›+ÕÊ\~CfŸ>Á†4 ]6;b½GÄ?Ÿo“ÔjðDPCR¹éi«ÑŒ—œ 6§^¡]äNÎÄß ?9—¯.jÙ¯òÜd3í“}q©ÞX(_ÁbËŽì ”"áZÖLÌë-‹9ÖŒD æÑ ± A”)á5r«ðâVôº.¸vld‹ðèªu²åPýÈÀø>T ¶`9™ž[¤8ÖTƒ%„Ú(Añ~Õ‚ya0r1æØÅÜö[4. ï/7=¢±ƒâEêÎ 4¦´¢˜²“ æÄ¡1sX°¦ ¾Š«Ä€ØñäŸLhÌYÆ”I¬ê5˜o»ÌÔÔxˆ•J‘v¨•ªÝ(îÄPíMçÖ´ÈôÒ½IrBJax_x ð‰WÆH¢âæœú£ŸLDÍI[3qÆ8bxŸƒRÁ:ìÜÒ;S:çc–EbTÑ%§S)iœ5ÖSÔŸGª<ß,ë6/ P!Bû×ÕÙ½/'¼´ã—Þý[oÝõcžÖVņ$g÷¢˜l48^<&">™."NzÖ£ƒÂäùØâcFîÛƒF½á–SÇ{ÍÍÜ­6PÌœ}ɪј »ó„òããJ>mø–é{SûÎbË9”Õƒ—ÌAlGV‰fn Y5qät–rYº´F\‰Ž4Žñ‹º3ž-An\’›ÌÓÎ%ÝÁ©×ɶ}H7x´LÚ³oª±‹úôuT£60°«J…“BPއÙÙJOAç§ð P+ÕôW1$¥Ð:™|q≫a-Vžì"USÐËßmAû“?Ájá3ú8–‡R­ª#¶:»ñj³hYw–(†‰ý¡îgdÕóØ'/æž'9Ô~þ^â‚O%3ÜTü½™QÅ…#´ó¦%ƪhj Þg#Žqâ>޽q¥ÃÈÃüGÄ8rì)ÿ½"D›t§ÄéÚi)Ý]Éöü¼\ ‰6D¯#éþ¸ñ!ÚìØõ¦œ/dÓYʬ”æsGÃyžbYÒ×·VP‘X<=ôK§ö5žópiÑÐešÃ¨ƒƒþá;åM(M{æ“5ꪻ+#ÔQö”(€‹Ä#þ˜…d@Æ"Ïç/´ÛÒ9”´*£)•ˆèmŽ3¯BR¥³†|ÎÖ#ø&1ôHé}Íö%p~¿fjª¶f¶žj)\q+úoMÙÀ\|ôØàøP=Âf_Ó”±‘ÒÄB $5šX@(I[S¬W²ž¹ÖÊ–4O…”Z^–˜[÷­ÞKÃ6¼3~¨s ,mÏçY;3ñšÔÅWeMÜ™Á¶áׄ<Ú³Lm)öÈ9}©ìmòA²$Q“Å\ÿ›[›óJ°èh¥.æ•RdHÁÂÎ ')±2ïimBË[éEÖèj±^p'뀇鉔þ¢„ j2猇`WÅ%S£>“ØÈkDeTH(;ïI%K ž€’~ާû¢0$:ÄÊ0çÒŒUPÏ¥ÛäržÞ2vŸÏÞ© º‹ SHœÏ¾)EÐ/Éh*DZÊ:ùັʪ”úÊ×ɉš}¡vi=šYO‘?ÉV‰òõ†^êÐ+›šCBòsÇ‘†œˆ×#¦qèV¨û@›|ÚTÍ•š—1ZMŠŽÊ>lœ°øíòKÇQW-›µØ›lA÷¾(_ðÆJP¿ýz„‹bÎËhxö åó8 ú|Æ,&X&s뛑‡:ØÇ¦ÐD6˜j|MpÙÛãM¸,B‡ å)ê^\LêbÀq¶3#ãySíÝ–ÊéS½–ï„È€æRŽ:¥@ù/àÏÒE\¥:}ä·Â‰3áškË%ꎞMHU‚юsj¸ºÂ!˜Q9‚H¥‡haú1T‘q)Z4QHz²_´º¼tAÑ;JR{> stream xœÍio·ñ»¡oy/ðÛ,%w hÒMa$­-£(š"¥X"ë)–ÕÄýõ^Cîì;"·h‚(ûvy ‡sÏ?Ÿö:íñßøÿ‹7'Ÿ>ó§W÷'ýé×ðßÕÉÏ'ŠœÆÿ]¼9ýü ©ÞtS?©Ó³W'¡·:]gOÝ :mOÏÞœücu·Þ µÃ Vçëaõv½±1ƒéç›õFwÎygW?®-´SZ¯Þ­M7ŽN+öûÓ™auݮ׺óÞ›Õ¿Ö†žxÓ{lÚwÃ0²‘^0ì4@ËÕ¾OÂeù]ïœvÒqdm,ެ°ß8Ð$ýØ Ö¬¶0È+œSuð_œÓÓΩL7¸au»ÖúõfõP¾ß¤Ý`áÓ&!¿æåþºÞôÖÆOŽ…}´ƒ>ð1ØÎ;°›G}à¤nO ›;ÝOSþŽ«y‡@ØNéåÅG˜ïŸg>1=‚C8»„-_ž:#!¬hlœa v€ìUÛ†ýÜ¿Î}:x«M§•Y­7¦ó£V6Áª‰,✊Í¿{52@âŽk7"%!%¬~)£²ø fDÈ&adƒsÁÄÄ\o Í 5…Pó^ßVˆ3=¤ ‹ s-§´O#9ÇGR3#2éȽÈO¤Z2¯—8$ k0ŒZ^ äó«@:œ~ó×ôj&ðeäÏæÁõjÎëør&é{pÐz{e÷óé‰ïŽa¡ÙÞù¹Õ·kÕMÓh'öùâ=©Îî`’e»†Î Mt$3?MÕ2â+wÞÌÚ!®qíò{K x(´^hu[D¯QžÚ•eª‹Ä†€jXkï¹ØÄq/9»Åå3ñCÂñƒëu@E$QïiËÌ4Ëtklg•]DgÒ}…ïJ§½D¬+ ưy$®#ô ì|Ç÷ ‘Ûí‚e$Ò<v^74'ïÉe}鯹¡Õ[øˆÔc5ÁôR‚ç}V˜q^6†¡nÍ´(ô‚YàhŒ)ØBã£W®7ñ‚õSâ…w8©ë”2\eÔü;÷f³Guk¬µ ²TO;3p©ÏÈÛ>ÊDÛ¥Wf= ÿ4ö~ìmœ$ £Öy@£ž›ø±š’´¿‚~‰.ëF]EoD“—l$Ôð“¡6®þXÌWk|òί¾Aœ“–>+ߟ—BøÇ¬¾Ck4­©„Õu‘ŸÌ€ñ= R¶£ R¶¬ÀåÕLOF@,‘¶h¤àw¯’è„k´LŠy‰¤í°È˜Ïô‚›íGR}/³vy_øû~úLOÜPös`ë7ôÆèžôxÁÚòÛóYx sÔÆ¸™Ü2Ç+l ¦ž ôƒté\œðq»9¸¶ÓcÚÖ&¡ýP zYbgöÂm¡ùÊtÐcƒ±—5€¯D/¡±¸õㆊ±È-üót皀ú´Ÿ|ñ dp'Š (Äì1æbp{ÉÑÿ:’ ¸ƒ• U¹8ÑÏû"ü‡Œ!ݨž0üJïuáAn°ãgíÝê§ÀÈ-+ä‰Á*d†(· Þ`cL¢½þ£èF‰%åÌ,M¤ì}ut «èý’ël\ú •—·­XAŽ@SEÒpœ±žL#øÎ4ØL‹GÛ*C‚ÇïMÜ`A‹#Rú~\¶§¢‰²(M‚o g’ÅJ»HL=t®1¼ƒÄ÷d1 @?ßã´f H‰m,0Ÿš²÷¡\IÜ!ÏÍ6ÁHwÁ5bدíêøËu£úe*-¥Æà6&srôÌ9ö*Î[ì(Qâ `m%’Ðú¶ˆ¦·’l{Ÿ^ŠrvÜLyÔJ³aHÄ{¡f±¤Êý æNã£0C}5%GÉ>ã‚QtÛrw_{ˆ¾q$"U§ú™_;Œä×.Øü,þ¢b¡‘Ÿ‘LÇèWVE0Kb¦$oc1‚h³˜Q¥ Cl+"PnJ.ÏE„HñÑ$žìã PfîˆéEsùXãÆŽv›/‘Þí †ÚàÌ`sÑPy'v—‚±n¡]â–n½•Büìtâ]k'ó@KzÚ®ÍBXæ¶ yEÞWöaÔdЖ5=(DX1£ízºy&Øaaµ$¯]C¦±×“@¨€¯ g4¼æAú ó¢šÒµ†ÍˆtRQ©ê ìËÝÝË" –Mƒ}úñ ÿ­ Pô¶ŸD!=¢ŸäR’Çïv¿|_^Þå—?î’á@îýØgòw;¶rhÇotX>Ô‰¹!ñêYžöüù-þùvÌÉŽlÍ ¯âŸs9ÑSˆ’"¦˜§WJžØèµä¼•^^HØù‘÷!M!Œ{nbÌuáuyY—«Ø½÷ ÍÛÒòZr(*8æÝó]ÊÚáéÉÙ'ǟ㟿'D‡N_ÂHÀ&ˆYôWD‰p•?àú)…0dþŒX)ÃA{ý'üó]nú,‚"cÚ„2{ÙÒ}Ô;•¶õGM†ãELèô]"Al’hî7`æ^Â̰Ú?#?e: )×ñóëÏ…‘ÎE»É¶šüiÚ6ù×eòƒ—ŠÎ眊Ç$ê[˜¸ý€ï‡‡3âïMæ¥$W+6æ;vÃ_í”ó ÎË ÒÚ£ý†].¡–cðþ•Ìg ×£·’w´uÞ¢X á:&Ö¾Èûö"·ÿ—_HñœóÖ’bú*rz˜F”ÝWÛ)˜ªm¨y"c±€™Ûól ÏÈP†;—ˆà!÷éqöÜÚ=\‡—`Ü'»ƒ~#8´Åpy¬OÂj̨É,ÏnC7}æWÉU-'¢ŽeܶUؾuÆx~žÄ€ó`yjöuÞ÷)(žíVfcF‹UœSúvRdßo)xÆìOp$¢3Z ÷쌊°/ø‘uL¤H¤+£'•åQÓ2lðÄÎEÒÆÌf\†!ùkLO…$U–MÏC‰šØAñ¥”e }â"½Ó—KuÊá³u ÷; €÷X1RÒýàÄØègÏTúbæ,ŽƒaP„-‘t)ú› …Aj"Wª) 2[§W¬fi‘°ÃŽˆsúŽ*¢@”÷!™×èêuP83à‘+؆’-Æ2mƒô6UÜŒ`…¹Ð‰ËÄý’ä í½å$ÝóòxVÒÏÊÛoÊ#Ë&|Û.h_ibky@ŠQPCIÈb)ʘàíO0Îr«”N°Š:9=P™ ˆÁt1‚9€×U_9ÛRX›Í{'ðÁ9EÐv±MpôÓf3f $·Ñ^Qö?IMïiË—t¢ƒÀ³˜0f’{)— AîÛº´ê †Ã=ì¢ G,( OîËSŠiÆ´®É¤s`¼¢TLì«Ã@ÁóÐT ’¦…SîµÉ]kEÄX[ôc§´È_Ìx 9ñå_* yw Ò²PøOMõg¯*áRÚWtˆ”À –žT%fýÓ&Kx ‘žBÀÉòé±T’ç;~eù·–‰ yÅÀ[â,4q1Pm7‹e&L3IY½ªJ0ä-YN˜•œF7O×#I”°¯«X=/×óÖ2›§L!ë³—3&KÖGÃSP3EWÊ IcÖu0òúf¹©å2ªëÀy@Ó½eu–ÜC®D?/•oÅ„ä¢äŠE—µ~¨«“Ê[ÅÚ¾d )äáÅ*¨4mV/ÿ9´qÝŽM'ÍŒñÂÄnÕq©¡·êÑ ÉMëÍÿõ„Á+Ô]¶õ=³¼ É­FzlSœ(¶¼‹5ð¸œZy¦i¸PÓ¦C€÷:©=–%ù!ëÃs ˜ž.rょ·9ûKîê%}~%åÑXnî~wË›L¶T;;°€¢˜ËcƒÜIÓ• Ý“C%Yâý÷奨²!‡À`d1ù œ2ÞŸ9kËNsp¸‰ÞxZ´ŽÃ&zÓ® 4Kø•§*~-mï*$¥Ç'5m©i˜y-r®$™a¸¸—p+æ½$ò@Õ[Ò*ð=s`Ž$ó‹lÞäŸùgS±Fdþ6Sø% ±Wîƒ8ãþX}ÊÂÁa2§Ðv¢°ß† "uR¢‰Ôo*JüIJ¶M;ÒnÍQ ? Æ Ä­{‡ÑÁ¶öxô]Tð–¼Ö|7ù¿áØy}…Ów š­´o*¤¤úçÊÛͶEæN»B†õr@fXphfÍ«U¤(#³Y|‚¢z±ô®.= î«]é¹H‘‰W> Eý)¬ü¾íz¨ƒ0 ;+­ê\LSÎ4,DÚ˜GUJb¹ký,ñ‹|Ø“e4hB¬½â Seù¾PÃqלobÜÞ—¢‡{žÏ—“ìóû5¹oÆç““ÙåEyò\¬Í Úä`Nóƪó’´9:á†|nÀ§I¸Á· (Ö€ÒóZñ|£Q>GF²Ö{†1ˆqê}¡}_¹âb^¯:K–X§$ºRÅaŠÂ`ôÃŽi¹Õ‰²ËÚ¿›wdyp6 ¼?:oÖïˆ2Ö¹h]Ý<ñÝNJñ2œ åK cMcƒ/3‡Cþ£eNŒ‡Sã±y15P…J¤z:ñ=˜cù6%À²·uP¢I Æ3ëØHß³‹é3Æ‚³ØY¯x„m!Ã9I]:Ã+Õ`£©5…"ãêxÊmÄ‚›Ÿe­T‰Šð0~Z/ò6¨î€™Vuó¬ížÈËcò3”RrÉVk–@jj°Ï×Õ94FkG¤¬–š…œ†q›?[èðÀF¤–³çëåÀ7ÍâT;éyýSÒ7Œ]+Z GQ^£QË×ùXJ1 EU4;µ×ËzðÒÎí~­ãß;"kœIfõ¡d» À©£Î1Ôh‹!Á8Y¼æAÏK² AÆ`š1‹Á´¤œÒßË»>U\•hD6^ºkÀ‚ ‡¨M ýžc$¯3946·qC¸aIÊ…qëÃ@r‰Ú® ä•š…¯0«²Ý{~¹Y(‘×nbh Ij.òyLºD%m›RxM•йã©WÛ{ªˆª<íš8Ý&ñíM½~ÑBª7ð Ãð1d–YËo"AìšrH¨±û™'Þ²ô•è{X¾ï!\Û©œçtæ Ì…Š œÏ¬„ÁL•­±/þ½dB`‰Šmùd»¦«rúÚÜ~† ˜àÓêE¾5äËPábÅ“@‡ÇQ5“ªJÓE>x*Xñ~?3ÙÚ¬‹Ý$ƒ]=?+ÁVïfŒAœ¼¹¦$’VŠGýåkz¤k€*ža'm.Ë>Ú*ŠÖ[ ôù… U±$¿‘EGǼ!ãB¼ 5O+.=ã®Pq+ZúÒµ”ñž‚B­‹Záe(>DŽ>J–Æ<êŒ#­U-kƒE‡êÚ2 DïøuVûõ\¯IÏq¯N %4䧦 µ)K(ÑÕíXŒ¶ïJ{f&iÎëDê¿JÎãš—’“Õ‰óÿlŽ7pI¹PqØâ ¶È–ŠF ¿/bV²£ [`‰´üá1¶ˆà!>I‘åCÈäø{Ϊž­“<}=[,]f7»ñÏX„[‰-6rÂ.ø¹Rè1w« å’ ÔªŠ;mèy»·Uïúr¥`¨Vc7,YD!µE56{ s^Í-øŠéu“زZù…‡É%Ð*ž.UÞ-ToÍ`X(†I!¦¹¾DƤîx%‹êˆ}. bN¢Èç¹È’)ù(ÙV·P ý=r'?Öt‘Ý/MÆ1ë5?NZ&/ .ÀÐé0û£v7†ž¹°O’Ïa¸@g<‘[¦Z°IUœº,ÜÄFG€Qă˕òIÚæ¼¨òsË?PÌd¼+/£›€¨¨köÅËJš¢úR½ëÚÏ(Ȱ>ÒNä -UÇÚ—æÒ:E\X¸” M©ªæºVøx5H<Íî[ûocNç/öýñÜ0Ù¯>^‡ýêËF…SâmŒïrå~[}cäUîÎÎKªO§N¦¶$ÓF¢¬¡Ò„ؤ¨}~¿¾-óWîK]éæ1Íåºú1Ä8fQ´™Lfýö\‹ËÏvPòcไǙb’Mªj—øNOŠš²]\y¨:ƒ(‘sfLîJLJD`ŒÊ‰ÀqÌÌX]e–€:ÖI‹¡ =Íú“pÏÑUçá¢TU›âu>OHo¼Æ®±ß™Õ_ÝôOV´ÆûC>FMs¸‘tŒTÑnó92æ0ç›”¦Ú©‹5‚{ÊÜ™{À.™zD•¯`hð»@3¢"ƒ ,¹lãºà%}yvòWø÷?¬=XBendstream endobj 100 0 obj 5192 endobj 104 0 obj <> stream xœÍ\{sG±ço‘¡">‡Xë÷,Eî… G¦È-®"ɲ‰Ž,¿ øîLϳ{¶÷œ#•ÊñjwvýüuOÏ~·?b„ÿò¿Ç{÷ºý³ç{ãþgáÿ³½ïöDl°Ÿÿ9¾Øÿä04’S¸3Lã$ö亮ž·ƒÞ·F Rï^ìýyõp} VWðój}`Ä4L“\}ŸÂÏy¹ÆQˆÕ1üy?Oë{—ë=¹aònuþ~ ?Ïà纾ûzždÃ{»H¯ÚÍËzµüI¹ù‡¿Þnv”ûB ÆL~ÿð$¬ã¸ÎçEžTîæ&jÆ)Üp«ÿ —*fR«qú°:½2ôß4rŒoZoþ¾µüC½ù»vó°Þüª ~Ì-ù¼Þ|Ñn^Ô›—åu³zÙž‘÷áR+;8­—‘hV@´ÃßîþøÏ‰ßE¥Á¾^e)=<‚G?®?2ÏC˜ÕG†š5*=­¡½òôÓHÀ•¨Ç6Ïa}`å¤Ã_·`ãÔá&Ryá¤Èqœ\™ç­(„ñÝH\Ò…U^@$&H ÐF%êåUünü½½0ëá§­‡ƒº"Ñ&1vL&êÕêÝ•®tê;ÝÄáÚ®>®7?nMi¯ÂXnoãáIãáŽ#ÍdÜi-·±¹õtÄ’“vóN“I4è³뀡×,ÇoÚåÛöy¯wZ7½;£öóqãÓjloªíª™˜)¬Æ©{e.Ç7ѯ›º"f%³÷3ŽW„gYf¹Ñ/Ș…i+:òÍN ×Ëå\Ï íùú&è{]‰wv+úþ~šÉ}S·¾ŠÃ›Ë×À‰/ZÝY½ùªˆn 2ïÈRVãž®•9+¶=ªÐ¥ù¢n:iïÌâc¶í9ÇåbV±@E$4„1Ô«×ù*i;çf"Nˆ¨”õ6ʽ&zßÈÉúÔ$´èÉÃmLëñ€ M›ŽŠÝî™\._·×nÚk·¤ù˜ÉD²aåj^òEU˜£Ê‡«¬e­»Á½+ÞÝEÄ“ý°*d…ªÑÌøÕ´ˆxN†"MFL:áœ=‹žg/á±½|Ü<_ƒKO¨éËþèšþU{~É zÑø÷ + ×3MÚŠyÕêü|X•­1ë s"wP,ž÷~\ý’xмrJŽì>þ“˜Øu.¿G~)-wµË/¹Ñ¬¿" (—[ÛûEúýê[–KoZÛW¬ñ¼&“Ìm GO*§Ž›¸ xçá‘iÈï“ô7Ax^}Zµ†¨Ã(Ô:¼õ!g3›ùCn ¢Ñ ?I/ƒ®g¶Ê1…_ÍxÞp7 8™[öóLû ‡ïÝœ#۔Ɣ˜É[AÊ‹Yƒ~€ÏÊÚÁëGËFc…HeVcÞV½ydU¨-äanÑÈí}àtðFdû–Þç…µ40íònÓLÔÃàeGVœÞHÉ Çq0½KKXŽZÅ*OÙ‡ý ~ JJ.ãðóQy­‰a³¨éµÒdŽŽ_p2ø÷·zó£z%Ö¼¾ÓqüFùòνzW­NG”)ŒÀù’S¬fßvÁ±’ÄZË¿•<æd¸L¸{9Ó È"‹f¼}Ä]ÀéSB 4o›'³²-råÝiÙûò’£<]9ò¸éênSùcޝכ‡¤î3iðVßxÉ’°ƒYæp6ÚҖFfDE+ /*¢|Ýyª˜ö¸ÛüúEEŽ—]ËG]Ë–5)?Øo!õ²^pXlq³™þ—„yF½¬Í¨¤Î;_«ÁZmM˜¬õŠà꜕0´VvRÒ»j#HA…#ôeǤîáRO&>ømPJOžh!­dŠ>¬uVÇF­³'­£ÓµWa¢|k§@_åàœ*m¡ 7í©D\ pÙÚHÜ'šíóŠNPR`’Ñ/VË‘o³‰%0ë˜T. PÛ6?fòW´_1­1¾'à)Œ¨ãÄ 4â³è×ä4…!Š_Ë«W£ÄKsÂæ©±ÊdEažt@ÂH‰{ƒùI©(Ý:hm4z=3Í §X; bdN*7E+ ™Ô¦iYV†NÑ ¥&£1©ÂhÑî+ðm‡Ì*is[cDfHñy|êu%]'¶§µ%h}:ŒSsM-mƒp‰\Ë"ë]²'ø™¤ìƒÞÞLÑfÙ•¹Šœçx‹”ü’šTõ&YOè\À¡¹)ˆÀÄ·©«PaôHî³ͧc*Ç´YÀ&‰nëD}"Ÿ 4½\KRá¢7ðbBá—®œ öÑU8÷ æäç ѫᚋm™a{$ø¦µ9¯R­§ œZÇa  %MJÏÑU˜(ÑýoµBi4ë  $ð½>VYOK¤'OAŒÍ‹w,Xnng4µË½FA‹³Ävð®‹Ú‰:¡³1Ö¹b P¾#ŠÌ¬A³›I¶%ùSÔ ¬äx (þ˜7y¥‰Š¸Xfr:ðÊÁ‰Àý| PÎë©V#~=†.„nÎÀdï³ÄNÄÇ€UåîÿDfè¯IªƒÇlR–RúN£h㋆¸”‹›ä Fiš—ç Ò‹ã"dG”p §±eÎ%€‚&¨µ³¦`õšù—l»å\ž¿‰kÑAœa_$øÞà9Xùë-z“ßΠ/ oÀ?¶, ox¦½±Y*eçl†Ù‰E°»ÙÐØwgC•‰b¹ÍFÖ. }¤.vªkÙ$_iµúv­â‹‚ˆg‘IðuZF£v´6Ò´6>)m`˜e“Ÿ—¸èÚ"Vñaêã"=¬Xp­Ð¨Œ¢m|KPÀ…ÅõIƒI ¦ ‹Èn—‘ä„„±ƒb¼²âYY7x–$ú)FM«¥`en…pýJŸ5Á®$8¥ˆäxÕcW¿5‚©µ¨éd_­å´KÊôBÖm”Ñ(í"ÍÈ^ƒ‡¢~¾XèÏvÆEN pjƒvCÜ 3¸ !ò ~9žêUzQNG°>¸°vŠuk5Fe ËO=ž*ôŸŒ·u°je€@…·HüY"É4™eà“×ß›‡Qa‰„HÂ"ëÈ*,« ’_%\§iý‹0¦R/[f—¼v,n05 Qóÿ—†6MêŒÑ±fùqFƒÕ¢-Á |Åa§JË??F`• †¾Ò¾V2RÄ'¬dÖnV!©‡äCÌÕZÞ_+I´Q H:õ[úÌYpË4HïìC!KÀ@œ›E„ŸÍ-!Ýy˜ºIy€ñFUª‰€Þ–ÃO÷~Æ © 7Oš"&% ážÇPºLZ<+‡ÉFýÃd7qëZ.ùc‚ËÓTˆNd¬:ÿpicE¢AÁ|ƳÒ_;Êé— %Q©þ%‰˜¨ B朞4 ó¤½Ãa—Y«À“4‡ÃLìã Ü––ïƒßFp¿m`£ò¦ÏëÍû}Ò¤g,›vs2ôÙëBöн2§ƒÐ;ÙA(ÂFW•27s]ðé*ªv•ˆ€Ä‚1:’tañ™S–ŒÎÏ'©Ä0°“Ÿ¬á5i=XL ˆB,€9d: _d>ÎkºGÙ"ÝmŽw³K—Š»&k…¯F”Á¼ª9A;$Œyµ>gn¡û=¨ì€6ß"P…JãÁ± Äð­¦}”í†;…ÐI|àÄa“ÎÄH¸ï@@Í1Ÿ†iL’F( ŒôNó°– {àUåçAu„üŽáyPKüfzzMESafòÑô,ü4¤d£ „¸‘„ÁvŒKiÆÖ)²%Ý„ŠÈyß!Çá‚Iswªgè1zé!°Ï«ÐÝdÜäѶõò¬*°¯²›¸V²+°&¸1‰óUP ÛGy&¨˜é°]þ¼íK=äpž+Äð¯͈&fÞs †hÛŒ~ßfôÅæ2œ±‘bVýR”dKª’ÿT¤w›ÎS¶ÄgP$“tŒÝŸø ½|9—2k—µ0kP—+"ù1ƒ51coÀìÛ’«­CÄþaÏ4 Éü£ºT|o땊Н3 èRJ5ù– HR0±I‹oA®9.6áÏ ùWšü¥Z8;wrcŽGàF+<ΜÎÝUòs웟ޕ„®Fѹ¡[—À³a‰FUqX¢ÇdÜ;ñ¼Ú¼k ÊDbèR¶³@†ò²d´01ÿü/ dâî÷R|Ák~…•@Æq³@ûÉÛ6îJ&«dh4%mù!tçÜ@6_ÊLÑ]í6¯»D32•–Bì'-¼®rÊù`WpêéÑ‚+˜†ÉŽÂ2ð¥ýƒ¡ç“'€¤ëÚmˆwÀsÊÛ¨ d·!o.o+µ¸U4¢Ü8ˆb‘Z™0¯*#óö•¡\ÍŸäåiZ0oB .Q‚—h?!ÍjCyHžko£*wÙ+mÑÎøâ^_ÌG/ Ý·*,Š÷Â#Mÿˆ5µŽ—î»ØšÿMšOšRQgÇ'eÓ½d§BH<íP>‘‹°X,¨J5=H*¶¾ÙÄÿÀ" Sy;P^k‡jnòæ5ߨ躖”s3Òy®ÔbcÑ¥PX¿¹!W ¶@Žs$‘3)[ö›ˆ°Ö}Yé;81“Þ™ÅÇÕÚÐì@õ‘˜TVÜ6›­ÉûÍSg‡rêcÛn.B³Ê‚œèì“‹¥›¹Ë¢tR:2­t&GÇÏÖPCwÒÐn]%ª ›±×Ž™J¨qú}s†úrsæb'û/7êGðéÖ㺛\OðV%¸¸÷åÞwûà¥ã·|àBŽPnÿÚàÉ<|è“{÷|¾sýâtïÞ÷ÅÞ½_ÁÏ'_|þyð‹ýïíݰÿå-?úOØ` Ò‡ƒÚ zŒoÓé¦àË+‚PJÿV¤ýÚ‚–NmÏΞ°{»Š$Ì  \¦=¯*•¥0Íl¨ú&{¶»†"`‚1ËÙõ-›å%.ñ«]¢›V§Q6ë;p„6•·m:o6)@ë7ã#\:¸½øOx(M›§b&Jæ…l â6—Ÿ‚†Ä¡»¡Xn4úyÞ4Ûb}ÇBø,BcÈöo+«{—ÔåR)Õ{-ÕËÅ=\z Õ”"3¾ ‘gißZ:|La3Fµ’:N¡ÅεÃÉÅ`¬ßp¶!ób'™e»nfjØ1+…¤³Hb)b&Ÿ³…éHåê;w )ñöDÛ I)(WÏ=´‚¨…TÕoÖl£ZÚÎG–b'œgæ*®(n†ÊA ­J¯ ÈhN~ ÿ5œÝ[VERf³«¿…Y®žd TmÒ¶©.X´o à ïL8BUÉ’üíbЧ0²Õûl:Þ•nª·1H³tçýWƒ‚ y•qq·m¢¾+\ä:Z5?ò¼M-6£ÑÙï¦9vn¯’ÁniæˆE~éý£†TŸÑB^a‡IL}fn)âÍx`Þl6*AÁ5ß6Í¥A³‡WØôz¸5Fö5õ2?ìý|` çÖÆ:á<¾|ŸÀx„Ú&aÀ1$dÜ<{¼}è¡}ã}Уo æ>ùÇáêT˲ô‘v‰­ë“6´¹MÅ; É]Õ!‹\ÐÉ0ð·¥WµPåÜ;\Tê ž޵ k èÉ^etnL&EâÖ“>·e¶>.¹[…49bPÊb½‡ÏØN1ôM¤ ^jÑÅç ƒÛºšTÄ!Ž—°ÇÌК;?i¯A.šrDÊKbk]}ÛÔZyýl:„l a©ÕÙM¶ã®–[C´Gçz,7¥’l 8ÃÖ%Ì3Ý}BÚb‚¯Ö4Õñ@¢ÉoßTB@†”Õ/–ÝgÞî˜emA¤ 0°‡ÝRf«)­³÷eGýïÅÒ¾8ÌmY|ÄØ,>Ýb¢\èY™Îý rðÎÀÃZqF‹µURum¸Jåÿ`ãÞ¢¤ …P|/‚é‘Ëù›8QKäõä¿ìà´ä¨ úät¤LÍ·—χl¨(ŸYRb U^ÐØjá8KR?Ø–ó¾ltýzU% léèŒTi© ¯-H†“cã!Ô¨’‡J‘ÉV%£:éÏ·(CÁs§å§Cbú,Î9aNýÆê}»ÛöTC\Ëcm3_²[á™F8µ™¾¬u~Ú'¶ã‡·ê'´ÑçˆógáZKôý©_×›w6ÐQCC_¯«Lp á|T‹ßʨªÏñ«} ÝG²†r³~o¡ï‡~ óqb¿«EXËÕoÃøã]þ¤Ô6oZ ñŽÒ%Äé·8‰ÖÅS‹Pg€êÏhùå®#%QíÉ—x0bÔ}ÖÁ^êîŸVéëÝd·Ð¦_S©bu5Ö3v§zñûaÉ[šÜÞð9Šœ+á±Õ<ùM·wK~·Z‰–)™‰94jߘÿ èkù)ý—*æäñòÏ®i;472X,yq©!|ôò]ƨTÿÕ¦ªl'lÞydž Å›‘žÞµ)ŒijÝcÝb°f‚ÜhTZ¤òíÒqº˜îúrïŸÎÉLendstream endobj 105 0 obj 5755 endobj 109 0 obj <> stream xœíXKoE¾¯"~Ãg"ïdúÝ}à 8 V‰ Èöú±Â»v'Æÿ>Uý¬žé]"Kä€b3®®úꫪy·¶ñ¿øïùnñêµY^½_ŒËàÿ«Å»óËøÏùnù털ƒ•ÁŽ-×—‹ð6[Z=È¥Vlàr¹Þ-þè¶ýJt{üyèWйÁ9Þ]âßÛ¸(º÷ð3Œ#cÝ[üó.ðç6øó6 Ÿeá›ôg÷”w/ò.(åp˜µº{ÓåÕ˲ºÍ‹eñ=‘´ð ˜!‚7E’Jv/[šïZšïóâ 8btðlüÂâm‘ÜçÅ+䣗¼Ì‹Û–NrÛ‡¼x_oóâ#µC:38«*;þ\ÿ´pªÑÑõb¸/zj‹ˆ+‰Iø(…Ø”ÏËãu‘=iÀÇ“üˆF­ø8Š/WL J9Œû|–ÅÚ†¸xú~õa³à.Ó}Èûût¶•¿æ’¤ âÌ¢MqñºHžÒX¦{¼@>œzä!œÏà‹ÇLEä¢" ì©¢Aa÷¢²YjËî¹ÔѼ¡'ùüg_‚>âAÿ}$í7‘44¤'K¬q;‚ ¶é‹ˆ¸eÿ3ȃA^½f–6!+6ŠA@àj21ʯ`,ì¡_pGèA OŒsÔÏ FsïV 5ƈŽûGt…„@B·½B³’‚‡^ `Ç`ñÁãi w¥Sµza”×yWö£^=JÐ+ ;Áºý ‘ ãtQº¡Jƒy3.nÃÛ³)Ð ¬9ǺØ&¼Èƒ¸pŠ€5 î,k’©ކx(@RÚ(OE˜8 /-^.øÃáÉ\WPåY¹FÃ&¢…‰#±û3nÂùä źçî4˜ùŧ¡á†Åã4oX,ÜšËXÃl4pŒì,¥I$­. ¶á% ÿU*_B¸qÙÑ ç+Ô£µÑɳc‚Ú“Åö=gà%ƒ1= à-;a¯Çž»3)A.&GƒP"0½ÅEI©ãÙˆNõ]8m¬Þ«€/|—È#Ä|*‘ˆ¡¬/@C„NË9åðÃajxò±†ª;ɺ]P®µÿk_'„ƒ`IÙ½h+OÛ:“y¨¡ò"w=MfÄ)1lèWZx`@X—Ìk¾…v2IËÔ‚o#¶¹·–tã €0)ÊÅÃ47díî{GñK3²‡C‰f¦‹ztÔ&øM*ëÍE1hÇg œå;qmÉáÃYas¸UÝþEÄ“<‰éNJÇG’œØ&Y”°„m ²sê¿h±2Ò DOŠœl€i‚]/ðr2ôŠØ´f`­äȱ*£HU‚û aN°:£•š^„?Þ!p¶fÒûBYŸ0瘗RiCQ7!ɚ͋æ&¤E’{Aß›DÏ(=äúÔRE®ˆ•ZH;°±&áàt_õñÊhòäm Îv„»WŒT`„9)|á(•Ë3‚îºP?É3Ä?¶ºÐ³2ÞFýU_¹A`£«’óAH…Ž,ÌŽë%ÇÈÁ$K6‡5¸¡¦xÁ SìK?²9ˆmí=ÒóX#‘LJ"&ºï{`&c%K‚f~4kþà˜Ÿ§˜S9»+–´£¥$-H‘‰Pb *ëé¥È:(ƒyšŒb”u|Ô[w¥ø„yœTЧáˆY©Ó"Ñ÷êb€}°@b7nJUÄF9VÅtÙic(Šx¦ø›yK=H >ïVmÂôÛVCuHÊŸ9vÕÓ`’}ôã\÷ušÕmÇN_BËÁñ á—Ñþ¾jùË,ü`ãǬðAð>}·2þ\¼ çŠÖP`䦹tû“ºÓ­;͈à–!>0= R„‰]ÇÇ¿4­cÎûß”—~Ï‹?–Å_ó";:ûÂ:uL]áñ–¤â»Ü’ÊÔ¢52›8ðjÚ?gös*Hð”kß F&'Ü ðOšˆÔáHíÏ)¡4Ãhû¼ÛüÑg­ÞvVB/•¯ù±Wª-·"M'Òñv±„/[,ù¼Î&Rk rÌúÞRÄ ÂEx  F"0"á…ƒ\ÌÀ€´žˆv6§¢&y÷×Ä͸ýDÊAC¸R¹;Œq%u J4£Ÿ·~%P¨m˜]RûFáheˆ/¶pül|9úî•ôŸ?“žÄ¥fhœÿл•Æ—“û/<¥Åf¨BIeè?™Ñ´Ú“þ yò[—ªùK9D³Â;gÖÊŽuÒŸ³äÚjÂÈMMI‡Io”E7QSœƒR'ÈZu-Ω¢-dÐÁûÓâæg¯0­ÈŽ‘¤Ø¬ÕõÐ.SlýUÇ·Ê–~ŠQS"ìª9ø¶`‘Ä­4ŠáƒOMñqš†šÉQ^ú0kgïg_©ð%<”Kß©T(KªZ-Dý]µ¯r“yèYÓÃ@Rrl¹’ÆEâÄà Û+Üþn½øþûq"¤endstream endobj 110 0 obj 1916 endobj 114 0 obj <> stream xœíko·±Ÿ…üˆú¡wo½|“Š¢vÜÄmš6©‚¶h‹B‘c[°-;¶•Fÿ¾3Ã×p—{:ÝÉiPAΫ%—ç=C~·±ñ¿ôïù«“û_¹Õ³w'ãêSøÿÙÉw'‚:¬Ò?ç¯VN¡“Ð+!†`Œ\>=‰_‹•·ƒ^Y#©W§¯Nþ¾Ö›qP!8í×ÃF Jy!Öv³BªÁ¯?ÛlÕ`Ýèôú[lžÎ6zðfÝúÉFB«‘¬ñ-|áá+׿ßlå`„öµ_ÓQÖ‰õ¿72 Æ µ~ @èq”ÆãçrÊ ƒo•õL¾~L#eÄú>쥰ë?B¹þj³Õè””|°« Þ{l:P´Jg×—Ô¨„aÀ½ƒwcJüóôwˆCXÂâPް˜V§ŸŸœ~ü÷õ)¢Æy1ªõóÍÖ Zë€cm•4ƒÑzýÆ·`2ë—0¶sNÕ‡×å e˜‹Üpdz£]?ƒfíDö[\„R:Hïªvz¿½òVŠÙ$ OPóS€~kø`±]*ÜXCXWð©ô'‡µD ]‚T&ð8¥ÊÆM4™qÞ€d¤``ØñEã Ö|½ÙŽƒ”°ý6Ò‘”.¢™ÁÃÎ+w-–•¶´ž p%R nð˜çô °ËyàªvdS¦GÔYJs€té•´ƒ¢ûl#ן #ygÃúkøk À‚Ñ‘ødàÄ·Mpl‘¸LðœÁxåG!Ðß@0ÀÇMóòϾÛ~lºÞÌŒpí‡KGwtC¡¤~ÒF‚’ƒÏôtôÌý]ÀG Â¥鮺â"¶q[¡€°Gs”\…t¢ºK”‚*¶ ñ#2:BñFB"¶Ò»çøƒÂ†„@쌟­ßàÏþœçÏbë?ÖΧåíE}ùžÔ뙩õey£kk†ÑÇååÓúõ›òò}}Y¾Éí‹òò²(bH±á_Ôöº¸ëúò‡.¿ü/x¾Ê÷$ ú?ÀKn§Ýæl&ʶ<Ыúøº’ÍÛäüøböû¶+É÷Ê#–A™SÖ~(ì®ü¬÷òª‡×lòcÏØ iIk•%ðW¨ˆ|ݘ%¾pž)侚€UèQà0¬ëÄŠ ®´IÊC·³¡^mXAR«õ7hn ÚHËô<Ù`:xR‰Oq¶mÜøiТ0«qV2•س)žÅÚë;QÏzô¨Ø—óÄl>ü¸Q ôhUÃÌÂ~ [nðÁÔfIõS»Ë’ÈÞZgu²‡ˆ_¡ð [ÈÙ&ÜÏ,-Ñ¿ ¬Û°~„ˆ† ¾ C€æ -¦èÅÍØDs#!]$âˆ)Åm8'<ëEÌ–ÖAÌVŒŠD‘0Eˆ1$p”дC8$ÃÊÄ;`´¯ÆŽÎT¨¤ s«R!çMcÏÚÁ;`lD:¬Ó&ë À »zÅh‚ÙàGÛk™8ŠÑŽÔ‘#"X„Z¿1(µ€ß93Kß~S(ï³y\½[ÉF@NqÝXîe¡·áÂh…ØÁªIx‘-†ãt«•CÏ,;>öõy%ºL­=ãU£™;Š<Ù\“$Ý™ÅNM‚×µï»F}L%¶)ˆ>[šùM儳–7'D]x¯2syU¿Š<@&[•Æò©„ìµÈÿ\ï‰ÔŽ{ŒÅ(¼rr ˜¢x1T|(<Ðwø¦Ã«’ßSú¦ =×ìLè+-‰ŠZ:.dzÕj¦D±æ"›DÉ…Ž—WŸºN {9¤Ézä…è#ÄGÇüÿNÑÿ¢Í)ÂYœ;Ž·rdîùR&2˜?eV‡ü.)óE+%¯;Dysh©¼ìĖ쇅Oz¤uC`äºÈá3dÊ´%Ô~Ù 9‰BM¼„I |U‘õ}ÑqiOz~ß[ˈ8çêåH¥ÑòÞ\'½êÍyÉÉd¾;>h–§Œ)Fèæ ¸Ñ‚2f2fm½ló²eÌÊ…c™¾ÿiG‡¡&U»›\Ç|Ùëù®.T¬÷Ž_6£O4ÁD¥ìæ=Dž0\4ñpÑc¢KN¹½†ä[D­¨ZçùBωr.3!u™ÿ²éÃåG [igj¸*“tÍÆ›,v˜ÿ‹Æå\œ5«`uˆƒÉ‚‹.!MÅ‚ŸÒ~2©¡sþ½›ó;òDLÑÛj(¥s'…:X*ä8kKKà½Ä˜ïÎíåžÎ°ûxûÊ íý ¤ìÏÑæfÚÀrœX6«£wzG"&Œf Ž/½Ð~„\¶¸ù:4õùÝ€ì¨)LèŽ|  W`¾m)0þG5°Ì‚Êqû-æ pz(ÃÃeÛ1ôl¾Èµ i(–]d5L]hP¼ÕÊâ+…b;PéG]Úd‰$!c˜§ún“9ÕÆºÍÜf „³”+Õ xÁxSñÃ0‘ÔI \ÔÚ4Êæ=ð'ÈLžÀ$Î:€m!TÉáJÀ”ìQtOèW“iÁjš {y‰@V£5Í@¼€£ 9 ¯žâ|Ýæ‚r*ÇÙŒ•Y/'eà ÕÞiFùh¿PÀ¢)ýëj$ôQ’p즆¾c´rÕ#áÊ™ž(¶’”pÝ¥Aò\ Éu ÝúÝ÷Zg”io¯S"6C ½3j‰[st,Á†ýU`L*!Aº…œµõJr¹ŸI3€3 c<+yâ ±_ö¸ˆµìÊ5/4 ì<Úae†nÖ¿-2Ü&$´:a±°UúXA)gu¡4+Po§b4·¨Ù¾É P‚݉1$½£ ê.’Mó- pZ\›Áìæ„S^2®Ë%ɹZÄÚB•n]ÁÜBázY¿¯1Y Xü ýNêG*Å 4¯hyÞH匳w•@-zF.ôcºÆËy~˜ÔÌ<©¢«ô4º¾M ±^­Gئå¶ÿÛ'Ó^ùòˆ%ÓÛfíð›TOK}©ÂF‘M+ØBÁsQé£W›Ýˆ’\;ƒÕÒ‚Ñ‹•öbðíÔ.á"α¢ *"L(nžŸm&úв™Xê1u:©Î†geìÏ-,(AÉ®áò¬­nºH’]ÅYeöX !×°NI¶R¥$F£g¨®=ÏHôÏâjÇÑ炬~Ĉ»¿¨8HXÕšSq§J¥pÊri B]Ñ•$="eêZ3I•ý¼rqRŽHEfNgØ5MkG½`Ôüä±NŠ˜Òà³±½©-›l&²L-¹‹&Å#ˆE^<",ºAa" þŸ9çù 7gIMñL>ëD$$M—öÄÆóV•0,Õ}Œ%>yÙ=‰P7´Ì}ù†¸‡-†Œµ_£àB¥­m”r‡jùy-¶ótò¥-wŒ…K$ñøœU.I‡¾¹ï½ÕRm¦»Ñíº¬]ÛŠ?œVßµ yÉS®¢K¢\ |}ªŒŠÐÎ|„-wÙ²e”Še $âl©·•‘t³æ<¾Ú3eB%:;-{×:NV0Ö¯<›Ù™ÄŸTæCb‘)Gß}g¦ôŒ\¡t,ïOÇnZvjuF®2[²×rû>·ÑážÔòÖ¡#t<<6É’oCDZüq–_:GÕ+¡;ÔækÝ5Žøè”(sat¨†" wxcÚ­Áƒðû:_Š×¿ÏO5SÃ8orT§¶1c3Ü›’4m«Ñ¢‹±Öá´–·dËG=q…a#É-Z éH©cг–oGKˆé/¬~–¶!§%h¢˜l@ãE•ò~«‡1ÔÂ1´Å‹|KøOU°®-jJјÑ1v6eÞûj;]µ!!DkT\§ÂËê½^ õäUŒ4;k?º€že Â*:°yKŒwTFDª¹Í)QÒš b —€!FØ|b<Î5@3!Õq-€Û6îÂ&ìºÕ¬NΉ¡8Û^^ã§<ð/w•üú0Œ¾DˆO‹|ùsMíÔ—_Õ—ËË/êËOk–*6ÖÆÏëãk¿O›!óãÃúø›Ú·ŽÐu©X¢ P# ¿BPÁˆšúU̳Ásãu´Ñ=ü†ÅhïíÖµÒlÆœ¹Lºc«ôØœ&¸åÔq.F-_”—»§f1åx†ã _ßÀ¥çqû»°è–‡º x³ß¼öÏùžÏ÷áÓûpåÅ~{,¿Ù“&Ž‚%OöIW´1t=èŠÁG¥ïÞL² †–A{ØíõíŸnmý×ݬl›#?8Ì?˜ÝöÄLŽjŸV‹‰A’æ“$Lçûý0‹;\Â¥(j%‹€wŸUƒb[Ž1;í)QóØÖxfM¢Åóûä­Q°$(‡8Ñ1ÌF¥P%™mÍLëg5sC§ Ëfx#ÚŠ®Ó/€[<2hëÉy³™äQ&ÌÐå–¥(~4@UïK,qÐa)¹ÝŽ™¶UGŸ'èMß šYµÉ€F¯ÂÇ„òE‰×ëJ®hòãU.J-Fbe‚¿Á^èÍ ~VÁÀÅCëNÀªÄăüí÷ÙY—ʣܭDlÈSÿ‡á‘Fw…áñ~½o^O:s¾°ÎÎåLŠv”‰öoç8°ž@¾ÙSP6rÓbƒÀiLéYÂ)v2áh‡1)V·È1<݈ëZÝ LPØÕ£,I ±óµ´Œ•/×*³¶ˆk—Q1N{Ç'7p¼’0§#ɨ,–þØi˜L#ãXÎ ói"7^žªƒYÊžòKWížbq1̉âï°£ž}X¹èpÆXŸ<&Ù„Äx²‰ ÀBæ&ê¥bÑJ‡Ó`[0"}‡G›ØÿÑ®­”ñæ"Ý(UÌy=•ºÞ_³À j½&’ ŠÎ"AX†ê.³à@JL‚²Íݵá©%‘{”±#å¢ó™vl6‘ê&#£«x‡ ‡M2 X"iŬ2QšXW²˜W1 sGJ6LS³ƒË°09@/cĬ“QžÚqñ"Á®„=ìkåT˜%UT!Ýh4~ÒD£¥ñd¢¼nÍÒ6½-l•:…®'—.Ü$ú…ÞE Hw?ðAnºÃ¡¹û ÷Y¹’k./†žú¯XÉÎ'fÕÀ ʇ{W‹Ð(l2µ%K;NÀï—}Èù”Y®<ß:ÑÝÖŽy!ÍT°vÌ ÚVÝÓ•ó]EZoÙÏÊ®v J Û~ê`dǾÚcl_³_×nìÎà {¸§»/]Ó˜dšÞRNt ¯Á€íeÎæœœÓt±š‰K…°tâé¶s¶Iw-ãu.Kr!·ß¶¼7ûBB Ê”…äÑð6+3§´¦¶ršßµ ZYò‚.–ˆõøûмRÉþ(âG7Ù¯>½,D$8½üȼ„Aa(ˆÒ+ñš§ÜT`Ú³S×R%È4ô0rQt½ñ.6¶ÕÊ©Ùu±Ð¯;íz€‡ƒÚvW¡GÖp(êœ!‹+E푉r]Fˆg&uÊK²:ÅÅZ°I]†r˜ÇU‹uÊGonâ°$ßsº r¡§å³n÷‘ ÞÜ 73óUGþycm*?î«8C1Q4‰€U):I.Ù,Ø£³®ªû–À ðnçbN$zã0°’_VKìÀÃ{Þ¨Îÿ²Vz”]œèùt™\WÖ7%ŠoëÚªx>1k¦ó\gS&oÈcó Ìô‚ØáØ"‰Ì»»â3~œPu*~{‚…Ù41»,îÀØ,¼™ÎÃ㆗@~“<˜FÍô|Ý@ÂïÝÅ=··»l– Ç-0¾+Î÷¨ØEú(À±Ìa@¥DÁ—Ýq+[²"ýr„ɧ„˜Và³C•MÚ͹je:Öá]Ôôë•fÅdý} Ýÿ-…îž|yòÝ ˜ÕÓÅÛ[|ÔÀçÁìЯò~ðøäþã?¬Þ¿½úöäþ_VâäþgøóàOáŸÇŸ¬~vòèñêËÅ+¾'æIºâ[ò’€QÈþ£[¾¿È ‡eà,,Û~xà¬C[¿®$=(3I¡á’ëg€%fúDµÄæ÷-0u'iÀn¨^*L8uàZiŠÈíu1ßíDB·¢©ØÂ{ûö `e¯ÝLX¸}ÔIÔ8vïˆB[Ñʆ\–ÄXÝêä²$N®ì]TÜí—) ¼5e­—±]áÅEàõð½é[y%h" *ÄïQu½€ëK«/ à’\º¦ÐÄ#xâ©{è¨ â²<Çy$ŒÌ»s Žà%eD–i“¸:–9ûÉU?‹•&®íž<­¯Z’¾¬„º¤—aòàK×¾ñö£ò[šNy¶ ÙƒBöÝâÅÆóI ÒTbçOÎçŸLÎ’¶>‚m&Wí§¸ûfáüâL Ǩ¢[6ųËTYׯrî˜ê EW#œûŒàã[ÌjK‡²„Åã¯acŠöüòä?¿%Ÿendstream endobj 115 0 obj 5170 endobj 119 0 obj <> stream xœí\Ys$Å~—ý#ôÆ ±jºînÞ° Ž0+Âá0BH{Å®¤eA‹÷ß;³ÎÌ®ª94»8‚¡Õ]]GÖ—wVÿx:âtÄãÿ/¯O>úÆ>ùéd<ýü÷ääÇáœÆÿ]^ŸþéÉî ó8‹ÓóÇ'ámq:ÙAŸZ#©OϯOþ½ú~}¦òæyš¬ÿ{G!øãþÏ®y;2\kä .ŒpüÅ^C§ÅÁ Ý0OfTïô€ÿ9ÿû‰œå0Ávž_… µÑp[­>l½ô²Õý«|ó¬qœ‘P¤û›Ò2Ó@­®òó ö|ÓÍ7­‰<ªFzu™o>-ï\䛯J˲Ìç” ¸¡JÚÁÈ02ø ë3]^´<*w,02ƒ ±£ ]¿Æ»Í;~•fgüìÂcœ<îTœì]F…_õ8¶»¬ZŽ~wʪ/KËÛ|óš­ªš À P_ÏžŸ¶î}ý§÷þ®çïÖéÒW›aRóXÐS÷eÜ‹H{·2ªÉ‡áñ³ÖBÈ’›-_P‚{fö÷ÉŒ ÷åó>* vtfÔú=3¾£Ì¸Y¾¢$Qžêa÷^%ö³[má»­šì0ΠÖ,ÔȽô>úê²Ó2ݼj tO4ÔÌÈq‘.90"2(ߪΤ„˜ç{#ã:oöUn÷8Kãï)¥b»ëüó¨CˆûÀ%!cWyþ[À¥!Q©•W ñ"F.:§%Ù0ÆÁÙ >£>¥Ô€Ë»Ô– <2é…ÈǶ„RKáîô0Ë…¥ÕYÀ¼‡VÙ݆h ø§^ÀÕ²mSçÇ·õ‹}R6¬ Ë÷þ-|×D%§òݤïо {€¥3Ì(iAôÂB`ÿ¹Õ9ç§¥4öÙÚßñÔs•rÚ Æi`Sã78@Éh›Xë¬ö ì}d¯y XTz6¥7¼ç<޵$ —¢Œ_äóµòMq8 -…”Ør¤Tn¶À*r†kçÒÒ„Qök;h[»‰·”ˆ«pJᶦYá‚è ­ù]W* Ó2tåAZºV~È.ŒG#·Žs™û¸+ÏÉ*⥖ w³i¬t~§¨ËѬ>[ D‘žW†0¦Wßæ{N 5N«sĉ›¤È«”žºñ!5'Èÿ1z‘„p$½/°2AX*6kŽ€÷<(–¬ˆHØU+hõ«ç%Wc‘¢=uYç ºr~WS›ÿ’ÉåQ´ ÉM4H¼¦Â2:œÒ`Ô_ÞÇiÙ|YŽŠfN¢¨qθvo‚°ý! ×H"€ŸR+4—œLòý½H†a·,Áh…î`œ„êB?mûú(vÀM©ø¢5ÕSE è¨Å@EåñE-sŒ2)ªÀðIâ|31ž¡o^P€BcM_Dc«ÒS¸û(™¬Ù$bŽÔñ€f­VzõU6"8qFv†}éX9´u0?yÖMÂz§œ©yÝ2ÓY0­²ò[6-,Ý I{}²&Ææ¥H¤»CÁ:õ5n»5”ÏæG¥íFAùÇÁÄdBøm覮Äï$ñÙ4›VRt/௅2 Š l±7*ÇyîCÑ+çöÌœ¢LEpÛp!*åÎTq†( FÑ~cÞ'äŸüz iBŽ Çi·P¦¶·;ã /9W–»àJ¶à’òu3@yq%QÉne¢WZ9¡_ /[»è÷»'WކpQá“§¿ì09PTæÄYªQæ>µåÎ’éójkýQl—kÈ“Y@ïo< pzãIb®€meTŽÆûZ€Ù 3aâ1=ÍT¡Ba4Ç1кңñh\Ü8gK ÌçéêXJ~Æ»q(Aì72sÃÍÆJy‰ 4¢žiOO˜¬Ùkt¥i6]2äe˳ÈþZÚòN%!L¥p¿!=ÈÌÄ /PÆ6õÑ*¨JšÈ$”ôÃÜìZ1=H ££à—ËÍ%œ1o×Êë¬Z™¢ä)í"ݬ>ÁUõöÕZ®¾…ÿ¾æÀ˜nŸQ°øFqÃvN{,# È9Y[éÅòjÅFfÂÖÚ÷ì˜Ì”bávÖÎáÑ9RŽºÇS ÉK'ÎyÞŸ›¨Ëú”ÂÌ\(Ý"À/q#´’Ø.½}IaJ mb”wöH´ø†.q®\à­†¸ÙÞjвüRìŽLçå"„F€ »ÁkŸ©À½)VË"PêÅU3PÚTß8»âÊX4 „}žXiL`Ë×à ‰³MýæwþÍs²[Clƒ["lŒ³-é™g°ºÑS¢©±ž-z•År²ÔÃŽ·:mr>¶H™œœ‡.#¿ár#¼È•K+ûëpiàÎ٭ξ‡Úw=£c\š,˜éåH8[$Í»†VªC—MÒè\?„ÏJ¢Šµ])è T›`Ö#üwÊí¦iP–ËcÝÒ$Œf¹BC`ñViÚ²åAŽJ7»2`«ÎãUIº\±ôÊÒP—ãÝYÇ·tž*†°ãYë&zu¸…%ª[ÉE™]ieË‚ÓI +y;tÑGêc¸ès„ p64DOYÀ›ýFô=¼{®ÑŸ"'O6ª¯¦&#Í? s‘ÁèlêíÚÕQ³X†}[ìòCCºÔfmpW&ï­(‚m,a$µgÈ&STe¢2£ƒKB¼žsœÃL_„É4ãý¤'â¬p‘…újMè]¬ ²à쇙÷d…ugMˆùµšÌRϤ”5ÆX…«sõ%‹C(Æ|›¤‹…í£;Æ/þºF9iÁ÷$C4ØÃ¸0 ]Al JcÑ1D$êô®¯ùK[ L>öqD­v®·´¤ùÕýØGY¹Ü -vLˆ,»&„6AC-ö¢N¢Œb{ïM%1$üà`¿ìžÜî…\|\|ƒ¢õ#9y»agù®íµ·l‚…·i¸ÔÖ¡çí•DÌû¤7ZÄ}’½m0Žàn''Ç–(évUEý"ÌÔw_â&”ÑÂZä@üWE£‡ä|hÝP¯ƒôÖ¬ÆH&A iÇjäY04€áéHذΫ»´zs”'lê,ù>Ù5Xµ³ÄøŠK;?/y_¤+;ùŠŸ†°D¢é‰ƒ?goô@Žžh,]LÞƒ`3Æc@ó6[MXé•Ý+ùˆ›ÆÂŸ7­XTa’Lq½4ë™i›(Ñͽlqžûµg~U4rR¶Ñ‘ߦë«d&vÇòC7ìP1ô6L†ß]‹/:1ì½Ø#F"Ð èöóÔVM­¨GÓ½¬_¹õÂ10ÁLªæx°«¯ ç0Ëâ IÌŠ™ºܲ©úC3-ÜÌÒj°Ãtú»u¾;ÐàèÒ =‹«<“àN£È§ÍÞ|\ð¾Ç8YøëU—’ÜF©LNs÷+IJF#EÀ:ôf÷7…² ã…Vzýˆ%ðu½É"lÐR>²Ù žÊ§".I†ç‚£´‹B ª[Z;ÛXñ6äÃb¢„/÷‡¾Tƒ$2õ³âÏËåÂýó&sp‘¹ ûz°$óyHu“/~£ÅÝËã8gKG%Â_äq¤þ«Ðݤå.ø™oµ þ½peg Pºš`âõÒX¢4+¬,¬úŒ„K¨ Ö“7µâFÒ#žD Q›ÊؤÁ°­ÝÎ(mb?Oà„N>³Ž\.fŒT*U.©“ÆÄšÄÞ4üôdcìvm…O«YÒLW)ߺf R)AbCt„‘@ž”w“ʺNy·ÔÊGž7e[¥Æ<Ì®‡&r…¶[žZh/Ù™xÝìê#)Y'¿wÐ Ðk±:e¦£ôvb7‡䙵)ÞîžkšF“€…#jœŸ ßp”¿#éÙlG "”ãµ—QLvâ;”@ù2Û=ævß¼ÞÈŠƒšulÞvÎYÔ±Í8Þ2½Ï«0—µ§éi£¸šê~Mi´+¥ôYëëµÑÄžh‡/9Š2‡—…‰KCÎmÆÖ5I:Â!TKm:陸è¡GÍRž€5KŒV}N»D-dPBRÁu¦¼U ä;_µ•óþÛ µRIO‘Â[*mÓ!#yR€eM6dÿ·n8ß@¢|ˆnzpÑëüt_áqÍ fÐ>g|½5¼d^͡Ұ¶KøÖ«(ÀY©<‘¿{W[Ô½µ·ì[¶¤M]¦è{·-+…ú¹‡ Äú}*HšCaU¨Õq6U·ÍÀ"ÔÌ~§ÅÏ R¶Ï]…]}1Øî“÷E¶êìGÄ]¯r¿Q¾È²±¬¾~V ­Ž•ñ·kžr“´•›rž“èç<þ\H‘u¼!5žc‹…]-™ÝŠ…t°"€a’Â8‚Om²þ^›5xâ/ošþÊiN±Uó‡5h %¤pm¡Õ>QÈ+5×…Chq8;X×õCnÉ–àÒ.ôIÉä Ëm:–%©µ¸ >@zRIÜph2rÜ¢.醖Š÷êè@jN Ä9ļ”­Î’©’²S¨ Xû’ô ö(„M.U¦K•t7*/t2(ìNšAèïHÑy"‰QƒsŸÏB€ïâ?žrÏÏB—€ŸòÚXžž*ÂáÆ„åÉÖÊÀ/¾x ¹{Ì+¾ƒSÁk6d±ÁE½ÿýÏ2†#ºÀ“Õ÷Mv;¬5í_)z¬£ñ±qkºlKù÷ƒúßö9Â÷¤dÈþRÞØr í"­k:!!Þš:ƒ•O—2—_œœø¾´ê}iÕÛ*­:¤8Æ€ÔW,¼ÈW­/F¿Ê÷ø—jÃÓr„í.ŽÙVùÀ¾ZY…<éKwù&‰æ†‹¾T[à}{Ðõåÿ±Ê_B§—¿ìŠßËÅßö÷;« ©·‘ê[›B„$(˜–S®È‘á(-¾ðéùÉ?àßÿl XÖendstream endobj 120 0 obj 4636 endobj 124 0 obj <> stream xœÍXYo7~ú#ô¸[T 9¼_{ iß(OIQ8r õ¡XvƒþûÎð¦v×j (‚È»ÃÙáðã7ùyÍ™Xsú—þînV¯ÞØõ§ÓНÆÿŸVŸW"(¬ÓŸÝÍúû-* ‡æ¹ëíÕ*~-P$™„µÑ‚ZooVï†GÅœ3Ú ñI)0\À¬µ2‰@ªáa”¤e©ÓJø(5ó^Ž2|#3ÎÀX;|Áã³ÖÃݨ‡ûq£˜”ÊÃpIæ,SZ¶ÒjdWž¦jQ^ ¥šÌ«a‹æÐïŰ¯ ä3hôY ßTicì4nÓÚ;+E]ØV&¬ŸF8¬”Ã!cuÛO' ÓÆ´^V0ñ%ƒUv"hd0óÒ¤™–Ö›Œ4b¾ŒôÅøûöוäœhÀ×ÛK$­[Z&xÜWe˜w&c€ûáˆR‡J“fæ"í>D¼.[áªÚet_A±¢^ò¯±_MD0t'#åÛè—B²¾ŠNÕÞO§¦un¤Àu™õFȰÇq½ÉO­EI+—‰à,y±/™êeìÆY•2•('²‹dŽ|ã ùææ±ÑÖ@ý¸ÆaedÒ<_¿£Wàcå]œ,¬ ìÀñõýXhW?ù²B™liyV˜Fˆ+aœ –'¹ù¡’ºEð–ß,°ZÚ•§´°üaÆRú'“v¼ o2µb4¸¡ýWÅ(’¸ò¬ˆh­Àqh…ˆEpYIi×opzf 2³aÏ ‡£ÏÆ8mHZ à‡,‡òê ø¶ l2B }¨?Ѓò˜njátE?¼üóµÊ½^3ÝÜÌ4¢Õ}¸¤h•x±¢Åü§¹ü_O¹Ìe¦¿xæù] G%]o饪4+†Üs–B‹ìøˆC‰²šÕa¸¢÷CÆdÔÐlG?wôC©–B*ÑqO?‹2ÀŽAF&©âäá«ê硪ðô´æu!3ZW˜¾-C‡ª;gä87Ý}bWžŒ»ÄÄæCžªpVóºÑGÊjÕÇ»ªõ8çNµwlg‡ÐMÇÑù-8˜³å7^‡íuÁ‹äF!Óîb"M~ž}FºXý²8æÈ¾iU»eJ‘ÚäùC¨Ž;é{#X¬u–¸.ÔOJï¥z\S™Q pGjé>«†N„j9)¶Ôe±”Ô 7ÍÀ=æL*xQG˜gÌM –Ã@7šnRg©hY‹eË=[Úkœm¸g›ˆÛ¦Áæ„öÎ ì½äðz´Gʧ£Š5~xQõ΀š>¢y$žºÆ‘ÒÄ®kÚo_¦® sáhl†5ÛŸîiNMq3Ü”ú„¥tÄ”"­ßÓ.ZO@4Br˳žï*z˜±;x¬Ã Z0nŠ2j¶ 'ã©IƦí¼I~=BsB|K Ša\¨Ø©mna'¢ÎÀ‘Y!÷u:·ž!¸f:Þ}ÄE™åÓXÃÝãÜxÃ@:4â9cdø…¼w^p xÎøÿ‚âÂykq9ͺñr0y&8æÎ“A$=º ¥a®þ¦>Õ•¡Þ=4ÌYÊzÎÆÔ“Ïà–H[øwQÇdˆ~;£ù…òÌzÙð0­0óp6>¯§O‘âi•ã%£¨§.ªöƧ·náχß?œLs41ÛàW²MþÔ~`⦣üREŽÎ —¤¾È i9íÇÌU_#êDüåÛò@©ÁÌèÁ/%Òko{Ä<ÔJYK¦ÄÀa–B°Nçɰ¿ehhaø«)Œ87e¨Îd`>8d˜¯ÌOè·W—³4…ã|î¶¢äåØ l§ »NéŠ@NØMßMÏ5»ä’HÛCš"r>­oÎ._ö*aïë5H¾¶RjöÄ|¬?ÛrìêĤT@H 4´‘&t!3éª{?›ù;F!„àüv l—Ͷ­ûáÆHŠ>ïÅÛ4×ÝÏõm½±d&³îàšZaꈀ*bÔ4úÓvõþû¼¸—Ìendstream endobj 125 0 obj 1527 endobj 129 0 obj <> stream xœíÙnÇ1ÏŒ?bß½<úø;·zôêhX}ÿ½8aÂ*ý:½\}z “„^ ÑÆÈÕñ/Gñi±ò¶×+kD/õêøòèÇN¯‡^£Ó¾ë×¢WÊ Ñ¹õF©zß}cÆu×ëiÎváƒ5¾]¯¥Á=M÷f½Qvì½ÖÝwøì ¤ì®âfR¹îf-{ëŒL+ëÑʺ̳üå9ŽŒƒ»W04Œ£ÿ8þ3žÎÃyûqžN½ã¸:þêèø£»cØ»w^ ª{¼Þ˜^k=X]öÎ9Km”½q?Âã,n¥a¢(O˧ë5àÀ[)êÃWkàm”D" Ò0]<¯XŸÆµ„$ #D¶7Út—ë œÝ:@4nÅ–Û(i u72û9|ía=¸|ð%¢U)=f8œRÝI^:Ø)\) »ƒé> sã(º?­ñ“³®{€[ûQ .!4|ÿ°B'ÀªûÂ&{©ÆîÑÚ$\J¥UõyÀ†] ö@ez…ºœ–`©@1{ êã3 c˜9iå€E*ºâdËê£)°:ᬃ øïóÄHr¤¸‰Àl€ü}„éŸIù!ûq„‹÷Ã\ƾ^þ±ïd>l×ÚÙÃ#pi¢Óâà‰®½Ôÿô†¨FY‰êàÛ·€5P;[é ©ù&‚¾ª7vñOP^!»ƒŒ„é²ûÿ~’£<$Äó+þxɧœJ;-“ãŸOóÈ\A¥oê€÷(€ó—2ú¤]_ÕÁæÌ‹2`èá»Êà/uæó2x]_–Á{€‚aD<†£ÅÁg ¤ˆ"E–Õù¤5xS+JZçxGån¢¢ºÅí¼.×Q¯(<ñ†Ë¼§ÖÅo/+¨xQsL>iaò™™HxQ'â=@}owtV¿?i-_¯êàÓÉž{ì‡Wˆ:lª$!×™g•[ %ð óǰ£æP”Ð'Ûâ„Ñâ1É y·“Ù(~¼™=†s‘‰Ì˜R¸·Ai•ÕØÜœ²ƒ%ö3¢À‚¡ÓÖ½ødêš™ i]ZÕXCL2\‹[=yÙ´ƒt‚hwP²Š”{%=0’Ñ=Àì“ 25äÎ*H8/9ÂÁ²­ƒc.}ºK0¦·ì øµt4´XÜh):‰ÁBΜñ¾ÂãìxZ.ƒ†Ø0"a¡ ›¼L*h@g O÷è„­VѳŠjò5Š+Ž ÜÒ—kÙ}³°Ý¿_£õXQ½*Ó“:Æ åÅ[Ö•GwìûÒç•´?©+•“чõã÷õã×en› à UZ¬¹§kHÃ}ïM „¿®%<%Á÷™ØßgÅ]˜¹ FPô§›÷N“-ði (Aç Ÿ7A*5tñ/ŠÿÑ ‹`¹Šì jøfV<Þ|9W¥*à”¥^Uó^,ñÜM<j6­€…¶tš®`º„˜§”T²û¹áûÕUîáÒpaà‹ xìÃäR€¨/ÂÜR=X[!_O¢0Ê qCư•ÄóYRèÂÌ ÙWPàC—eàãgéà•,ÒAi"Pé5¶‹ÆdÄ·&“LD„T™h#P¹^ä³*˜ ò7Ò‚€,¿ÿäSÏ5 '—ÂîRB-©!†¡·Å–Gäü¸?>«Âà/Eïsa‘¿¦ÜTThß{T”—‚ðÉreIFÆæ2B‚dÜ2!WŽ¡!$jÈ÷ÀÇGM(ü*®Ùñ{Ây¸Ã°Ý¯åï?Y D“i8€ öx€€Å³ ÒÜi&ñ,Ú”:Sã< á€6íÔ†€:<Ìü@¶´Ë7xTÀ£“ÝWðÞ6üm™¦@þý:篠›ªB ¤/@,˜)égidt¸¤]aœÄÏ  fš?†˜CƒXH -‘‹ˆüçÂwµ^f†Öc¡¥ Êøex4ȧò³€oDX89ćQ›çë¦:=¡f®FAJ¨a‘ÌZ6ߣˆ8ôëÅ|‚e— ÆéE°ÔS75X’㞨…tšh ©A÷ƒ™Ã¹-8»ÜA”[Ѫ-fOH±ðÚL—ãôÂ%uò _ð"k3u+U•&à?0@>2·©3#ö²0ð£jÐi¾ýjÈ3;_z8¬‘‹d,½xl%½=Ù²¢¥+Z-Þt‚G‡XI’ydÂÕšÑ`œíÔ¤-Ú–Ü•Z_û"çH·0(øw™ßŒ·"hD«’/"Á9\”:²P‡)æ79ÿM¦+_O¨ž(´Ÿ×!Zm$ñ*¨{•¡ãá𖆨áÛæ¾DUÙKµrç!_|æt Fb…xt® ªáó¸ZDEúë»&Sâ÷©LwhG š²ÑDvE´ÝsÆ=šqqf\dlßK¶¼\´Ç‰ŽG¥º-Ë–û[ <½»c':ÚÆŒsçù”¦2rHÛòbÒ7°ÐñP/fKbxNxÂPóç*h“à`^§Ðmƒ×‘Fi¶¤ð:åâ“EN')‹1C2NÄú’a¯GkNWóÌ ì™Msþ¬Lm™ëÖ2SýÞ¸‹aP‹AÍ–=˜È"'ܳ¨1R`Ë“ÐÞ<¼x³ÞIlBª%/ùœ‹íI¬i£´’ÜrÎ,šÝDS­Œƒ ¹ Žyõ[¢å¡#ÊSa?Ç=I¿?â6CϺ,Q…nqêͲñ“–:ã ¤NϰyÍ,a)f¡§pp@UÑÞw!Ú9‘ñ¯áR‰«yÀ´b¢H½°£¸&wÎ4Û’ÏDˆ€äFa‹ 1¸ Zjh¿kÙ?\“@’B!¼$ b<ÀvIßô¼ÁOt–„ëÏðhÝ|ða䱺-þ·Šê¡ziÃMÐ`-?ˆ;~Yw¼_ï*JÊú.B18ò8âÞ*(džV3^È,tð‹´š´³ w°‹š!ªÌqHqÂd¥¾@ ‚I-ªC6»á,Èβ &OJZ‚A¨§YËÛ Dš(U͸‡¾wÞ Z?¸çd4dŒ:Ȭ1»`‰°ËDY®YÙD¾LiCàŒû¿siRÕt4Žæz¤Oû5U`ÎûÄüäo ¿0üÿ0߱绩ę“ßžWˆàÙ÷êO‹à9)ŠT uõH»/$°·A<^œ´]òÖû c—剂ŠYáÎùm±)ÇJsÑË™^´Öd°3Ù…jM*N÷×·)RzÊΞ¹à {>䜛ç6tÈ_`ÇR%pÜÃ!—(çÞ?>úöèÅ s’¡~ƒf3­_)iµKë?}pôñƒ¯W×/oÎ>þa%Ž>þ|úÍgðëÁç«ßݰúv±ä~âi¦’{¡†^IÜLñXtßà“Ê˃Zêå{Ø¢Ì~].ö¸õ’ÄÍ^|÷¨º-9Òm·”X¥Q+¸ÚÔô¢óÁÀ*Eš!æF„nògË»bQ:e]}ÍÀ5®pÖú"×iq»`ÆsÍ‘ñt”dKÚÝШ@+Ôïš+\§zZbA"Õä’ciÖÚ£Ö:·Ýe)XÞ6³ÒR"58,„½¤Œ!P$ÙÉÏ9)pÄc¦&ÅXü°˜÷1H+Šš‘BAó«Ä£}Œ¤A Û[²ê±¹+ˆNéz‘ÍCâ2xý[Rë[’çF…2&‰q÷Ñ&‘˜£f•ƒïDJs(2¥a²RJ€Ú- ˆxßú ’oQ´ò˜RÐ@MŒºEòñí8ì<"–!L‰dÏø²ù\º %Xįâ=Õ²¸A;2‘'‚$Ǹo#àÎ8%ö$¦5O?ëA‡`4+Q„ƒ„úÿó­cìK+á¤e h3?‚¦àD.V)’ä"®­£á4ÆLy³r‘f@Œ@1ûEÉS ïí(ö’<°7ºv2kV‹;• gñäXŒY:fê—4I¡%4Í𙃲¥P™ÐÝœó‘Ú&ÁáÄø€î^ð(râD±,IþЧ”˜‰ˆ²Í°tY9Ùá¬\ÌéKsçôU›âôš#ÍXÀï@#2€tSl6‹ûÐ Âç´ ØßᜅaPJ=Ñç°~ðLO°Jß´m¡ ÝÆC"µÛE¼™ÒÆ.î&!ÐÐZ Õ[¹ ¹nŶä a D¹êOƒ.5é'®…ŸÉS*”æi R5‡i{‡³¶/ è|C? yl8Ò™ö°,:3óö^=F‹ÿ$à‹(„Vís¾mlfX8“Y` Ý6t´J]?–´ó^ýäFÑB†"TK_+úzÌTÓê×&U"¬³5?-çÌüöVm²QÃQ¹šÚÑ£4wz2Á¤sB†|ëb‡¡Ž¬Ó$ýA.Î;E0¥<éÈne…‘ð^Ê­^[Ùèñì®õ¤–¢õÎ…,Œ®"‰×r˜ü…–Ìæ•|ð?¬7Ðp,pQ”t’4iR&e‡¥˜ô3²äñ½Äàå•ó¸Ffð;"ëtÌisßL‰¥ñIQ-“B;¸:êøÅŒ2¼ãøCh$Ôv§W·¥>'d†åáúüÞ RâE5ÎkÁ’CêÒ`³aÉb6JT*n”鲚ûù O}íÝjø–½¼Ìê`ï Á.:Ù6pˆà_H‡4ÖÌ=¥É}éMkÛÝm©¡Ž½>ŒEP`ÑÔÎ úÞŽLcäm)P­»/Ja±O#œÒÈÖ;ÌŒ†™¼„U±òHE„uñEf­|5ÓÍ£ ÔßîBÆð¼ÜAÄõñEt2æƒsüíÑEËŠendstream endobj 130 0 obj 5042 endobj 134 0 obj <> stream xœµ\YsÇ‘ö3Báý ã'Îl­®³«üfÉ²Í {weÂaGXŠ0ð ’D‰KÉ¿~3ë̪Îê€T8d û¨3óË/êïwó$v3þ/ý½z{öÅ_—Ý‹ÎæÝá¿gߟ‰ðÀ.ý¹z»ûòz'ô¤´•»‹çgñm±svÒ;kÄ$õîâíÙ?÷æp.„\&¡ö_üY¬Þÿáp®&'¬TûLJyZŒš•Ù_„«Öjµr8—жÔ>= …Óûÿì2yÓ´ðê ¦úðû7á—zÿ n/jRÊïÿzUÚ±¿„Ûbq^ìßB›v™µ÷ð$¼c­Ýÿ¯8˜’äÁ›8c¾Æ&Ý´è%wn”Kc—±óYëý9­…©¿;œÏ“±Jº:š'-¡Íwÿ•RÀ¤LXH©§Ex¿»øóÙÅâòÍ“ò~Ñn?áD”b/šÂ`I±]µÌN`r’jú…G½\4LEOÎÌó£:דÐÞJ4¶´X˜ž„u0rÿ'/¦9¬LgѤ™8y$ìâ E£§j3oòøÂl=LRNbʦ9:ŸÉÏ^„9Âê+ïòÿ-. NñåáÜLZÃnAS~ )q »IÛýU¹ö'£`[%yðò``–°,ÎJ£“تÂ÷±Q;[œ&6å=.̹¶vLçÚ^?à£vZœÜßB»ïë3±‹E©ý]½ØÜ?ׯMZþ¬^}“‡ó,vl¬ çÙR h-*NåE¼ÛM*MPæx­ø¥å4¿Rnƒl‹É˜öþ5vr2û°©pß{²Xµíºq ¥o¶Ðd;Pù‹kPòçØÒ J Á¼‡-ÀuH(±©¯/ξ9û~§@0hœãå Êí`—Ô¤âЗϾxü—ÝïÞ?;ûâï;qöÅŸðÿ¾ü߯àÏãßï~uöõãÝ7C|jÇ›ñIy‹ÍÛÙÀ4#B]•q¾«ƒV^6SZ?0œ“Vb‰ý²sÒÊ4z^GI¶ãMü©´Ú±¯´´ÂÍ"ïm”ò’$bŽ qèMk§¢¢D9Gˆ®¿nÐi”6‡PùªÜIò hˆâŽ£œ±“u»s¡ ùY“A—¡¾ Lè`gMžF|טË ‚œ+i@?$U”÷6ˆžß!PN°³*Ì–´RGRû¼®mLIÃÒŠ+Û줂þ¹„YdÄIÿÇÁpûƒ?ñá´?h')%X™ÿ;€2;22B²äj§útâÄ>‡`öR–ÉCµý£üÆW±1«ŠxøìÓÚÒÓ´„^LãÔõþ·i Èu¡ÈnÅþkÜ5­XŸÐ ÂoYøc°³éºÐ“whã»Ô „§aãö„új°c_Îy5Ã{4\ui w´„Üì1€YŠpâÄLä&Œl&«fTón¥Õ`â¢_•_õÚ5Ur¼¶,pŸ6¶ÀhØÞŸqvK†¼ ²hÇjct7jgeŠÝlª>7û“¬¤R8®¢FÚp‡lc¢´H÷nÿí¾´÷›üà·X Œt6¬¹#ã¿Ió6d8ϸëíÈ&DÆÙÀûÀºdÞa¼QqqØ$-Ëê´[‘Êá`fž¸®pù3®·¾'ê#káÇÆVÒÍR²Ð'ËíÄqŠˆÃÐxÂáU½×jñ‡dƒD<­›”'ÙR“*ÝŒÀ U`ƒkDúF^šf$¥–lñ-ŽOOH†¯8à©û>Ä)`eId()÷€ÃáB뇥$H“°Ã·¾¨Xý$ ¡Z6pÛœ`* 4¤†…#"NDãƒDxž%Á7“Ì‚_E &­G|!‰hêNZW—H´ÂÑkáQå~R¾"8–U Z;JJ€Ó dÄd»Ì)Aƒððò&껹' ]ð£ÎÁ<‚v62·ÿ¼‡`—ÁÛ„5ÑÉþ†=ìåÊ ˜ñE½ÿ¤¶L%g!R¼Ð(;€,Zc2ÄÛz ð38×HüÐÅR‰š,ËÀæ“®ˆ@2^ OPXµ±ÞáÊi=0C#à[y¯@^P(Pq ö7hž»¾¬®ÊÖulAKϳ`ʙӪò6 Jöûj ȃ¨. 0ã»!DfÆÝk–(TÍ`*dày«ECéfy8²Tf‰^©"®; °LBÁÚ‚bº7Eû$WDa_/Ùô‚NÁû´ !¾È©;¯D–°°,î²âYþÔ,²3ŽÐ½Š`í–i±Å•‹$#i·ÿÛAÂKªýÿÀnqî°%¹#4¾ñŸWkÁì‘Ųø yaã6›PÇÚ‘!-Isj1™.œô.p*⦅s‹n)………­É{þ©Ä¹#[Ó47"ÑIA‘J¡‹8q`C(!QÈVÒFv\Æ(=÷K2C»§·ŠaÕ¯MvtŒ²¶YÓ2ݾŒxGi>Ó ‚ß ìÀ?é–ô.bîì8¾ý96¦¡1ÓÈK˜1Ыft­]äÄâ£kÊêð‘âÃ×ê’„¼(@¹²òŸê5ëˆÃa.-7~U öÁÍEœ£¾sT:TN Kó:•´ËB%< ˜Ó’.=Þx™¼(@¥*á·±aéÔKŒ¸k7H/ tØ’¡»"L ÿˆ^¼w š±"½r,DÏæa2h–ïÚ"íf5MœF`ƒe8ÂJžö&e…õoq ©Nu#“fO‰paì"Ëp :EûIä쮚öJ ªt‘«Cj©.õ—[ó|›Ì¥‰uSbI+hXã —0bU¥ø´ˆ‰]GÞ»°H1¼,ËcBÄ à‚z@„‘T±Æîk'€È0b,ˆ))Bìbè­ñ|¦Œ§Ð‰¨ÕFÔWëuŽŒRYo·Üôh¬5pÄÚf­;šcÈ–ä ¬#³øÀ¯ãø¼ ‘?V $»D#sÐ5ˆú¿Ë¨ËýLLÄQ7ù¦†¶\,’wQ Ö\´ýIUBò$Êè Ht‚_ÐWý_ÙIÎ#(6¨E¤åÖo;ëÅXͺc[£¼–Œb̯oËKÃZ7r£u QÓKcwÌ‹6­*~i†qÐ4HïÛÑz­tPâªK‚ÕÙËÍ\ : £ay,ÉÛÙ÷íâZà.hŸ˃Ž7×|il¢V6yK1̃Mdñ½ÅÛ†r6ðòš¸OàÆ-Ð Ê6‰e½¬BÚ´ ÂEgÜnêÖrM‚¡„Ü­Y ã„é´œk(q๽@ΈÑ8íÂâ…xr¤NÏ1ÿ«‚[q•a„h¥:Ï®¥{„~…¡A#k «†0Qô°t`ÿfºSãØIœú(qMÀ/EÝpѵYÆqšä8àºa ˆ}†.¬f˜8Qg<j"#‰ë„%¼+L¸='Tß^I*TUVÐ  Öm+ÐÎusãˆ[i%[NBCO”’¯¨T²,• €§ä퓚´ŽàD°×-ß°òZw ØJ—Û’‡VÆMŒ±P˜ËÁFJ;u&»™•C˜‡à²Š^Qƒ§)Å´’b­Z*"¼+j|•^Öœç ÅÆ¼ëXd¸ÓÆ"‰gÀÄ]¸ðÎMZ}£ÈÝÛœÃO£nYÃq4,Þìç)×+›8mvùœm½9Á·êB—&¾í% Á½Iô¯Éî‡#¨§%NrŠÀÜð”t™3Âk:‹›óë* 4”·àh{lH>¥é#¤Ö`»Ñ4íúé’8æS^©H-Ÿî­=!*§ÐmD @ˆx`°rÖ2ûec!Tðºýµeã((¶VÛ¥Ûšµã+ åœ?ǼmÍXüè«¶f©–èåŸÌÙ8¬Ë‹£¨Xâr˜XÂ6ôžL­4»_ ›ÒM [Ÿ"«.N‰."4ôܶ¾:0Lk¶$ˆG©öûHG‡CÆ&'’æ0´µÇ ãÅ(Ô0h¬]÷Q™aÆà"ñXYy›!éË|šXÙí¡)‘hÌ¥´>x0ÿÚpºw~ÀJZ©ä/íaå&AË,¥%ålüLÖ˜†gÑ5M"p¤È«¢J´wÄ„®˜6ÁŒ{÷¯rïŸëàݧéïJ³¸`V„¤5Æ F~е¿Ç(g\ŽÖ^ó± .?=ž9ŠÖ0Â2£æ”8•·…U)ÅJ*{RÌWÏ1íè)WÁ*I·¹±ôçZ2É–µ¾)IèT.ž\ R‘/^Õ‹·åbÑ]½ýŽëü®õïòE6 Fû·‡²”0 àÙ¹ý_‘Ž9?/ó€·Thž'%E+~XQC;L é3]_UDÔÎóÕq --èÔ\94m:òQ»@eŠJ„ÖËά×1˜-HecÖ¬³FãqÆÂkGƒ E†¯[-Âw¬e’5¡S(­rÕ¼!û7÷ËxÛÌ.iÒ»£˜}™ôkE 5S Ÿ+¨,=ÆÅ §%àé î=€c>ÿ6º«&ž»°¨%GS/ËÉR,L´cƒÑä¼ÚeýyqpËR¨d¯— E·ñ2h%_‘x6‡G¢ê'”ä‘ÖÈ k0ªçKüI…vã7þÁÕ¿5µõ²õyˆ¿Ž~àÚ Ñ”ŠÇ‹ÜcûÕ+Kê¾ ok¶Úµ²öä¢ÄÄÞG†ÚúÚt²–9Äœ¥·:¸,­”ØHd:OÁ8¢Ø'Vs¶u X-NU£Š ÓÓFÒåâúíj¥c¨¸‹+ÑgHnÖ¼‹z@ ¤n0ùçï@wŸÔ‰Ñ|Œ2ŽØ¡ˆQL‘Ä8 ¶Š—«¯½·2'[²]ºNйî™]ÏŽó‘Yè%­Þ×{q²Àû2ÌôiýÙpú%kÙ6æÜŒ;êlŒóª­3J—†uqúÙÎyIëÚµÍ!j’û/3ÐíÚª!•Ëmnð·‚(‹ê„ÚÛ4ðA¡W•6~]vƒp¥\'[È+ág-â6îô¨x,”ùšÖáužÊõI—RiœŽY´å¢$®Íѧ¹üãóôƒuˆIøÐ£âTÜ4‡ÞÒÅ÷ñ’Ò¯éÈ;¬—“ËW<0Îë&ÕÞ/¹æ[Ç9Ü÷Ó!„t¼£ñÜHþý¨¦cIøâ‚ºW©¨DŽÔ§Ærð'q‰w]Žs!Uî]›£§9TLòÝëÜm‰:ZJÍâ$0CìaKOa6ã S“Ç+JRÐ&ñÀè¦\Ötì~ɨ5kκ¤’Â4Í2Žã¼:r„m#1åôl®ÙýèBjƒÃC|Ú€_¨\ ™¦±âðÅ›Eoé)ce^›šjÏ~‘Xt‚b-¢ÈM¥-Cm¬ØÃr²¥«”“ºÁ¨«©1PÉ×+o•57Í”«µÒ]-Ø!Âñ``™{¥;“–+š·à_Ghab|«yU<±)8ÕWÊ¥½÷=Ú£ñÃ[F¬«¬SeûÑèDÒ¤âfõ5ª$ À}™¡u–æºTGRùÜꌶ€'jQöC£è°§liœ4¨²Ët“‡­|­å9Ðý„S 6üÌ÷ù)ŽðKçÃçî™ÄgB”]p”Î6/ºfÆíÊ媢8®’Û°8Ux} _íËÆ¼Ëâ¤jšuh™)f-5«bu®˜-À"a64F§Ô¼wSþ xµ¨Mù)“Q±ìú“0Ìü1Ìt@‘È9õ}h*­Åù©9BÎ}&;g§C*[?ø![à¾ý5À’é¶î•éÎ階2ŽŒšƒ>á´hx¼;žïŃÜ/¥„y;!]¢† …KÑåWf (·«aã ˆw.ä%á¬kñÄaS×."mœŒ®blðãpRR²@#ØÓ.5ÓáÙ{*Éà éî¸ 1ù÷ÌêÌ|[v;ÒÁ“e%0-åò±I@íM Õ{ +¶êù…Ll2B9XŽúÀŽ©†šŽ¢4_ô‹Í|õL¥*1ˆOBNÍ%4£‰ïR$ÊéSÞ²‘hÝ=Æñú,¶V›ß‹ˆD½¤* œñßP2ÆxT)*9Âìt›-ïüÇS=acè¬IJbXyé´mª$½ýGœ®´®¬u“V%…=òR4%]«Ïy¾-©»ýoËÕ‡“¤îBÐZ|šÔRás)G7ñ )Йî8ù}“wù¼íðt俲 7¶±DXìCNdÍK8¨±…]ÝGÌrܬ?%âvŽ}Ó*Ô(>ó¶;ôùŠHŸÀÂ÷áDšÁ ³¶=ÙÜj±^­F·q|3Ôæo¦à7a‹Ÿæ"Î\DrŒöMƒ²Ü‰ âï+ôݬùèÒxyô-ï s„&qY¤:ñeJÎ91X45S‰Ðý6× @ÃÑÀý=Ý`=ܱx/%A%ØJŸk$›$1‚'™»qüˆ¦]_ÈÉ}àN0æ6ÇRxs?ý«;Û•¾½Fd•DIÉÁ(â2viUæøb÷u*Oª3ßm ±QÛH—•9Ob=kf»»ˆ £5QÄ¡5ÑgOŽù}øFÖ[K·íå5‡ÕÓ7Úæ†¸“ÌÿT<Ü> stream xœÅ\[“·qÎóFUù §òÂsR:ÃÁð[äHSNÉ’Öå*›yXr)’%r—"¹¢È_ŸîÆ­1ƒ™3G$-»,­ç` ðu÷×àçÝ8ˆÝˆÿMÿ~üòâþ÷n÷ôÍŸûüïéÅÏ‚ìÒ¿¿Ü}u „Þ 1cäîòÇ‹ø¶Øy;è5bzwùòâ{s‚Ó~?Ä ”b/G!¤üþ[xæŒnÿêp”nÐZËýl¤Óû›ƒ¬3rÿœÞu¶>yz8ª †Ñ¸ýׇ£”Q^í…vF9§êoà1%öo±0£Õé×`óJêщý7=í<ëâEþ#Îl´z£Pöÿ.ÿWÃÃú a WCŽƒ!ì.ÿ|qùÿØÿ zt—àÙáhðƒ®4ü%¤„5,†¶ûÛƒÁuP~ÐFÚ¶I~ï9 ìðÓ3;Zœ¹á+G·¿ÂÎ4ýùE}éE~é ü,Ô`¬Ý¿ƒçŨjŸo°)ÞJÁf?PþBzh;~y {ü#ö4ް±Ïa‡  \ìôðMyˆ]}}yñÝÅÏ;¥O˜9âu~g` :~õàâþƒÿݽ}}÷äâþßvââþã?¾úËá_þk÷/_?Ø}·ÏÉ|<¥–q˜qp2ô¶ÌóUü“òðfÃä­ýçLÞ†éä»+ÿ¢<|ÒL~†Rh¥BÙÅ/9vjÿGB† …ÿrÖí€Ì>Öeýý‡Š±Øþ£@ªe°& Ö ÃRi@¦)P7jÿš„Vé Îs›ëÔäá*¢uzÿËÁ€Yé©MzÙ ›°ŒNÝŒ(çÊÞ½‡v&¢ÉÖØõpœ·žu𯨫”±AÕ¾ØHå¨ *bT¤QèX77µïWñO jå®>RfÆ€»r”£‚ÜQ, lmF’]cD#» >ÌÀôÄÅeßÅÖò%þb­w–ª 4H¡ôãÛi'òÆ]ã/õOѬ1kxKÂ$Ü úû÷1` ìSÙ)5ß, Â¢¶«ÝàŒ ضúómœfðQOÞt´Û{l¶G®ÃkI•â³§q‘ÇÑϰOÐŽØ÷ ùCZ·ºv ûá¬Nû{.ƒ›²äõ5[SÚ x˜†ñJæ!¤õ4âKl¤` é€OëR! ¹ŒD 2à>ÆNÙÐgW>Øîþt8ޏÎ.X°ëGíPÈ _góA#ÜÓ·Þí(‹ á€.ËPþ¸=(ß5Y­Äù£í#ÆÑ &p¦Ò:—m«ŠÙV\_…ß%²ŽÀ•ÔD:æøxU‡»«OQ*„©Ø¼•W-LP¶¥¡I\µßo€Ú8²Õ¿›Í')úºQNA¸ c¹?¤Ñ’‘P¶±>vPÈeŽ8½²_ÿv0=“‚bãì(AÖãBÁn"J2d–Žï‘ÖIsàÄûŒv¶33áO}äõKo&J'SpFnBp OP#«Õ=ýª<›kÀ !bŸ–‡jËçrÒ[wc™‡l÷¾?EøÊjø—AnëÈ/{´èu‡YÐÞ¢ÿêMìœ@ÞrÉÄ1H ÌÌÄ=Г7œ5ø¥À#©H™<¦2’I[F¼߉~ª­è¢€HõˆbÝ€,‰£6ž¬Ú½¬/xG Œ 0Ñ&/°xô}Pûˆ¯dû8ó#°Û›Ô­j€MŸ?†>î¹*Ò£&.…ëÙh¿:‡"’èÓU‹§@„Qnr’=ªZ׿ÁIP€J°‡ˆS´0ŽøÎÌ‘Ùg2ËÁˆ¤N—LËóEÕ™/f쑌Tšnk£N:LÚ‹ê9Q„… ¾ÁÈU]/Oî%ÐUKö©°ôµ£ËpÍ«Í zÕêBìÈ8róÕF­ÁÒ ÐÅhO+»ôYW‡¾¾ó°àyc‡¢ žVñ¡Qwc >?|”ºƒån‹«]óIX ?Šùtÿ¾:^¶éµ*O¿2Ô3²ŒyÅ]·²a\ŒÈ"a>Î#ØUv·Àê‘×bPeKö&n pÄ€Á™ÇÜÄÞ°Ò|wµíãƒrÔ?î¶Ž60m÷Q:5‘ƒOh½ÓìwTzB.+½Ü·Ø–T­#Gì<%Öã™Eµ´®+ß^ ±k¸RyÔ™2“ܸÄœ ¦­²O 2ËÞ p›=døFgê}êHÙŽG—¬Ç]× Õ/›í )k˜²EJz.0ÃZ}o™1B§âYE³Ž Š·üÎ}èêbç>ok4 ;PÝ¥ìZçi}ëÙ2#¦˜žç÷˜4´_­uÏXÇq«LÔ.‡P kyV_Dª Ä€úx5cõ ˜:¾s‹Ëçv´Û(RkÖYcU¢sÈe#b-hI}R¤W`1ˆ‘+`œó˜@•a“qóW­}ëºô7É¡]¬P¦áquŸ¢LT›>¾GX:K÷ ³µóÎkWw-Tq„wçA6Ôúm !iêäAÓǶJy•&¶¡â² áÏ–ï0gØG`3ºÞ7 uULBEìÏÖ£‰nqª“þ™Ù] K²ýˆ#⨨àטt—µç9ŸdU¹á½üë Þ‰_W;}›¸´œ(l䦧TcÔC°é÷ÊÃj7Ù;9¨(KÂZ÷Ôþd>ï*Fâ9IÉØ/=”þÏŽŸÒ ~ΰLÁO3Ñ·=ÍÛ'ÃZ˜ã˜CG‰ÄïçHÍ!‰%§"/ ðÖr¶„”¬‹àúΗØ7úÑž“¶²Óè‚ òi¯ºžøÁΓFo;‘‘…¬šgä}SœƒÓög½ßnt9ÀÖ×_Ûê°ÿ%͇ÑAÿ3®N|\ÍXÔÙÂMÅàÇ (3ˆ°äIYL¦{$Íæ°”ë(X;"l€gR¶óø,Ý_7à‘Úx–À%MÀoàáí»Î¤Ð’©@ö`q]¤‰‚‹¦ÓDò¼K¡YY³îÞR#2…F΢Õr|&÷¹ ZòÏÝ×#Ë‚6ü ØEïE£rW9ûÆ)F£’ñ©b95Œ EKQ«ÅeÆà 1a"©pøù›ØvLS'Aàð+ÍŒwNÙ¦dûrDŸéè©Pó—s±ˆ3 }ÁþE¬îãÿ¥`,›TÅ:ÑwR{$+åWÔ„wQNó6ùáMyxÕ‹G²‡M`¢D;QR„Ãä"›í¼ŸÛ9qZô•Ö;6`nØ”ÞÇaÓÕéŒyîç9›ë'?|\ÞïÍìIðMïç‡~X´|U¯¥ÝÓfñO´Hu’¬ËëU%zŒ#œ«õüõµâˆLi­d¢Á£ËŒtÏ3ÛʡϺæµÉ¦¨²Û”HÄ0r{´w®ŸòhM‰1Ï!o oð tÊÖg6Ò¬ó’Ë×¼Í6%ü¢)µ˜à,FŸ¸äç?߯¢ áUãÌÍŒ0à¶õ]º^Žý…ÊVœHlòpHGÆ×§€?MSŽp–ÀÈdpCþ{âÎMÁàóÝq‹;“.»3üÊwËu/ñPXÚU¿@3¿ Í´œò9·ûÕEùÝý‚• ¤5ƒeé½7Å2ã~2‹r³.MX)u&ÛÖ“agçºgÎî:-»3rÍâž@ÃZ)Ê”IYÀÐìEa¡Cá~ÚÒY0êtŸË¦œòcÙÚÜgá²>±ùŠ­ !¹Ž¾¥w>Y„ÃbV³-b 6ÏùÁ–ÐÜ=ž,žŸJº8­¯÷ð¡õùˆõó‰7'Ò€ÒÁÃ}Y﫸Þ+¾r¬42m<ÂÀòÌMò˜r7ÏÒêûHù­§pˆ© ±)øéÕ¶=<$±\Ÿ:#%i:õ­…û$IüȤ‡1¢ÕM8MÊ O%ïW f ÷‚'qô—1‡cM¿L„wÒUKóôM'îÛ”3d<?/Nšçz1º'¤øíJ©–è‚‹ÿC>½L‘IÃ̳üæ“ïáKŠ.ÏÇ(¥Âüë n.¦˜ÒúÞÖÒ„¦ÔrS)fšÿ¦Èº¶ž(Õªf§F&lÕ•v‰1Ø{Å.æ»OE¡‡™]ÕXæݨ›`ÛùêQ¸FSê?æ Nç‹´uDŠ…ÉE·º5æt&˜ê&v‘^eÀ^fÒ!¿ yí<Ëyåü¥õËùKöaÌŸ¨M™–˜$ø'zÿ:­`*ÈùÍâ ´Ô´2y¦B °d«}™*Ä€‹ßÄ4=z5ðѱ¾„k¾ëj:Õ6Ó\g~ £ÖAQ¹Pi2£Ts@EJ%ørµ…MËš0t*CµȤ¡yzw]E€I`œO§ê1‡®Þ8Q¸so•˜ÖÆ>ñ¿@¼8“¯½síÂBM휘úYð€ýIRC(T¶É^Áæ D†'ºzV #›ü%X©F™ðH€¦²ÐÖ´ üPä¥ àUš6ŸµÖ†¨¤Qó)#f—+Ú³ó o.UÕce¶0­W3nÝ#è]~3 8tå•“ÂZ ~¸…éˆ&¨f5ù_ÝrY˜)K}.TpszÄ´=–Ý¢ÿnD[yS!1qã°`¿ú¤r¯6>Šr¢¢°àdò±„@W®`U,ãG´Fás:Ø‘€&¿;(b¦SõÏüÿ–]·Gr¬ÅL0„oK.»Œƒý O nˆ“-"1«iý+JæyÀڼ̤wl¥ÿA›%.B¨G„è| ÙҜÒ¾ÖÌK´z®%K;q8Îá6a19˜ ²¾¡@FIèÚ„-µ½ñ+ZM|Û~ïò!šX·•á:%$^KÊT!]sÆbjÞQÿÄ2´g'¨ß?Ù M]ñãaõµ_{yhVå•_rK\»)dJáð³ë&™«I±eQŠHŽ¥Ÿ]¼ñy¤|É*l™ G@)ˆˆ[¾Lá Õ8óŒdÏSUAž"Š— 3u?M¶Ù&¢Ónb @ÿœR*1Ö±¢\i2eI3Sq2x=‹ˆ©’²QÙÓ’‰\÷®â1ªë)0YtNËi¶àg¦_ï–¥¶‰å-W^2o$ù˜¼j §Zë)¡»º$æ!íï ?ƺ\e ú‹Rʧ2m„0÷ùK™Q^´æ\%§ÇÉèËL`kyÔR ÊDètaVÎs±ë¥ãõeóîbŒ5ÝÉÍÂy"g°ZDÅΟ²Á{i¦îÉ;Ü®Fy™ãè?öŽÇNA–;˜Z\©íî»°Ý"1…®?À­‘­È.³í«J–Ž06eꈯ|ðØø îî  Sö‹—dáÑË/ŠV¨kEÁv$Ê´Vk€mS>¹VÈ ¥/•QÕwhð»=ÿ@¬k–§¹gâ71\ îlÂb5yùm9×To®™4Eƒ[ æ¹fεØWôsï y0¾ª{LèjhÅN}þ!7å–Êëë‰EÔ4+<•ž²Ð9kðí²(Yd×+À§gr& ‰»jæ;f¼u˜b%œXÿùɘ&v°–~¶ƒgy1* {^‚ØÍÑþuc¼¤CŽFùŒ×iŒ»‡aP)|ª»@”øçLéB;ùzb—•ÔÔ‡¬–®¦V_t>³›Z…V,1±¡LrVŠŸË$[”†"Iýã†`K?óÈU>Êþ¬=…§Æ/XB¦g&'é;Õ=¤À¨0Mq©~RŤ¦tëÏ¿?|x0ŸD‰`vÅ' !¬šÚýõ° dÊã[®|¯ä­/±ðL·§ÙåE¨Œ8',TîOøÁ"hßeÞ×ÓÕEºðï‡rKÇäÃi¹`4ùm Z·ÑsÒÕ°¶oàó12Ëwà?x`ˆ\f¬Í?ã&˜èf®ë9å0G÷² VÛðqW#?ª)‡ç=}õìT9>¯qZâõéJ³ì.uè;ÀØäá!÷åTR`—|ŠŠ-cölî`cÛÖÉÏלt/I×iÖÝîÓWå ß8 Ë/‡j±šO|ƒmïAƒ3îÊ¡w„èûú]Ä‚]!Ä>*ó[רúxÜ^õᦫ€ÙS\pbFÁ¯:¨RÏÁr,[ ³ó¿˜N1‡¯ëãr1‚aDµlÖ”; f¨-ÁÁQR”íôä ¡ŒÉÔÆÛé\÷Ú‘ÃÁ±T¢ýdÅäU}޳´*V7ž}–VÎÂÕ=]ó@+tâ^4¦wðh3²v™èàX¼{±—c›—°b壎¬ªÑæ¶„ä 8®w'Gh&ðíámú’Ö[_áç;î:ÊUìõ}U*±Ô²á ¹"¿oNAqøn˜9Š·•üZ´&Hî )ºÆ¹§Ä!5>ê©£2Äë;tË¢[›ÓLKù+?r[‚xú>A—Ò™ÿøh ÏWÉæó²µU66áõ/Ù—¾SÜpLó[½Ð¬ÐÒõJÅYÅKïfº¶Gé·ÇOgÇš~ý&3®d4ã-GîÝ~Ñ}¾<3`ꛕ Ãô.¶dWåð$¿5.aubÙ§Féç|-n‰Æ +›‹AzÛz5U;`3ÝSpQbÔ“JGÕIaưºåŸgÝ|nÈj°sÚ';zu(‡—–Q Øöç/£4±l-$áPçKÆâ—‡xï…X,'f6B@{>Å…ªRºPõä­fŒ—ŸÅ4æušÊ¬eÚÛ¦íK›ëK|hÇ!×#åO4j9Êa¢“1¡®´9Å]¹ñ%ã\G”¾¨¥ݳÎ]¿‡yLù‹E[˜°Ôn.ÑýÓñøÅCËiíµî9¦åDt7~–7N”|Q>1Ýå›§Ò¡Ý—®Ó ™˜Ø6»@!¼°ÿ©ãŠñÓ`ï"¬rŒ~×­7ä÷S ¦±çq½º¼îPÎÆ»>ø[^MÊlÓñí&@k%ZW5h "Œ’ÊÑÑq.)W £è( þîâÿ²ÚÒÀendstream endobj 142 0 obj 5222 endobj 146 0 obj <> stream xœÕZ[o·~Wý#Î[v Ÿ ï}HÚ¸H&m¢?È>²¬Z7K–ëô×g†×á.÷ÈŠÕ¢±`{Åå’Î7ß\È·6ñ ßôÿËóƒÏ°›“›¶ù+ü=9x{ÀC‡MúïåùæËCèÄ´Lžy¾9|u¿æÎådÔÆh> µ9ìjk»Åyg°Ñ€N¸~· V.­7¸ ÒMJ²:_㢹É`‘ÒÓ‰Š,iW¬Q0D–åb|~øÍð~’Þƒúw n"\üÚk•Õ‚ÃZîÂÎ6i^¼B}IØÐ,”f>ïö&{PG$ :Šê¤{y>J6IîÝpÛÌšWVæA¶Y‚-€Wkï¢ /â®iapdáE™ ’¶Ui—öqYZöîUg~»Ã!ù¤Lí‡Àb›È$o‰o[àæZËžA>#ûå`V°ÕÛQ†99QfÅj‡yÐNPÆèƒ¦ŠAžU{“nø7|€jñ¼&/ã^ÃÎz¿Žñ¼x²Ue Š·Fþ“°dTž~ÊõË)†8É¿ î?ÿAxÊcÂ:ø8cù–àhc$¶Aióã«úxZÏêãq|T2InÝÕG2î»úø¬~FÆ}Qu}äõQÔÏߣïóÒwdÆìÂLVäùy,:e[ 6¤˜žL´ ÃDì|pá8+êFVÏæ Æô¨KÏB_3qáz5Äë®à—åÙĪ{¨f‡Õºë.Tä¯wK6†Ö»ØúaÌPË`»9ƒ`O²y½÷Ùýû)®EGŸâ¬ØëS”…"DÀ3^ÛAH¥ý:·'Î&º´àÀÒ£0ÞÀŽ»øfO(þæv¼FLRl€ ›++8 3¸bÕÛÆ¸Rãic’š{ð¬¹7½¿¨ïozôz—FØkå<;2ç/Íœ©ñ¸±K°,pÎà›¾=8üã3œPq¯&ÆÑªå`êÛ2‹†ŸR# %Øo];èž-ïbÿÚɘ¤±0k-’FíöSEûoèê!åE!ÿU…”(¤øë幎«ºDY𘷠ìŸc ñÛd|UˆO½ì9åw½Ý¸('U‘W¥ñ²7so7²Œ»ª3ƒò¨ß± ®‚ËÃÜ\ò,iÇôðe\¤iÒF’2¦–&[WJ°‚”ƱÚt­bP1xƒé‡›çN§5cØ ËHÿ6i΀-ýS^-ŒR¦t§L©¿p6Ä;4þŽ! ‡§#&R° ðGæ0·ïÇ40„SûS%œÇbžï:‰~\›_ÏÆ\¬Z\¬……eéïCë¤+Ÿ-rFæYÎŽ åçÆÂ…„ÅÌÿ4bÌæ”¾Ã…óFþ`,0 ,…‡ï€¯È®ý‡C®Ö± à ¦%]âýM0Fî¥Hp5‚Ñ@µJ¿uËȬTkéf·¨ Í+n!ú7˜Áet¢1 $Xåï¸&€ óÏ5•"†ÙX›°,թ礶Bv$l‹Í!*1|‹ýL¨Wj«X=–EJ´:”õ–Å»úA}"Ðb7L|Çz’ÈAN€3Éüï‰Ü<ó} +µ‡¼Ô6:¸É¿$hšÉ›ŒÌ¯‚5‹j´v”ï{Ô¨˜ w„ÒÓ¨PâüP›¾MØ Knk`KP#Æ U24qaå·{ð±î£ ›yq·ŽDÌÓa_á\˜ó|D™8#̃… Ê`À´“˜˜Œ_¶¥§½ð®ƒâÖŠÒ+´K@œÇAþ&wÞˆÖHIÜ·Âj¼$H(Òèä”fÃÒý²ŒK¼{’[r[ý.­WY‚ºËˆ¬I“l?®ÊÁ´ïIé#Š£Ì°R!ˆóDÆ5¶üÙ5ö&2m==ü2&ÆÚ&BØJ®—õƒ²XÌ¢•%ÆCe)S„×H «AެCŠ©…3®æT‹ Î êpÆCðàé»–Ñ- á¡F`—‹P·í"1aÀ;] ¬P+B±þHcñ* UâÕ¹ñ"^  MæC»(-‘½ß ¹à\°î±Pr N R G[:#üjᙵ©„£R7HÁkqN¿!2ô^öÓ'Rú¿K4MЦ!³æ‰Câ¸Bx[BGëÁq˜>ËŸä‡Ïò%IÓ{²ÎìнŸÌzv¶ŒÖg7ypáLÁšsC ùÊ}¤|s‰zs)ç$šçƒZç1Ëx^dµˆ¡ ðý|‰l ál©~œ6Å·Ùg¼_bÉXß+é ûbx?èiL3=ÉÚFØ«Cж¿“bã=ƒY?ü ƒ_bá¢I‰úW!hy!Ô µ_‰`g·ÓZ­w9IÐõ’mÀw ]sŠ.3¶a±ÌqÛÇšˆ9Ø_Cž—ÕÉGo!‘¯*²/Kô¾s#%‘*T•b9ªCM½ä ;|¦À„[X*§|¸§BÝS‡ÄÒéyð°(vëm°*]  o§‰ ×âvZøHënƒëþ@¹YÙw._øÊýÈÞù\ssmy­\6Y™•Üóè²\¬‚>ãT¨ý•´5íC‘û陜uºáF2ä‚áënS¼)ŠvSÌì𪫄Y %ƒ­ß;ÒЂÉzúŠ«Ž-¸A¯žá§¨E¼*&ƒÇ»,ÿ;ç_óðóp _„î‹[0»±sì|^É€zݽˆPµÉôÑHŽ¿„Áèù9]lîÉV5Ø;]õæüÐ[çY¾Â£èÉ|{ß&_„;N×#¸¢Gñ׋Gì{ÔŒ\†øxå] ªŽòÈE>µ§HϺ§¢Ñ= Ì¡îåÿ‰îò>„Naqï.DVZ{"‚IÌnlk/ù³mtàšj²ÝŽÙÍÎÙÅÍ£¦¯òXPðŸ±mZJ³ã ¯WÐá.Ç·t7y§yºt,BPó¸¼ÑwàëI¯±Þµs³„@:˜ÄsÏëÊ*bÈ}ٛʯëûãdî~&¹öšßÀ[Jlד.§©½n!•¨æ´‹Ž–jf@#×…#"æ`§DÍ7ï…˜Œïv1ÀÿSk\Rx¯ÉÎÿž1¿®c–ÆÓh)µXØçYO­«ëÖ¾iL05^ÕÆ.ßw¯CUͼoöµª+/™Ü·îÈùŒg¸Ý¬vßòº«ð£Úw·‚ª°ùý­Àx} /¾úD "=jìÿÕáÁ?àçW÷endstream endobj 147 0 obj 3253 endobj 151 0 obj <> stream xœ½\YoÇ~ü#øæ]Ã;éû0_ ˆ[¤(SŠI.ÍC’ÿ}ªú¬îéÙƒbÃör¦Ïêª¯Ž®šßOØÄOþ“þÿúúÅŸþeO.ï_°“¿Â¿—/~ÁCƒ“ô¿××'ßœB#®N8Ÿ¼Öâäô×±7?qfR'FóI¨“Óë?¯ôšMÒ{«ÜjZóIJÇùJ®7œ 9¹Õ똴WZ®®×jb\X¿:ƒ_NsæW—±·võf½‘ŽMLúÕ_à½VÆñÕ»0¤5««ðÃh·zXoÔÄ•7ºÀCÏ-_Ýá4B®j—›µ˜ŒÕ"L¢Ú½:ýîÌÀ^'Ï<Ç 6iîýÉéß_œ~û‘°è ˜³vÒüÉqcZÀ>VßÃzá±–rõ¦ô°‹““uZÊØd˜–ÆÂv7ðÞzeW¯×z‚} [*é`Åeüøéœ• IôØYѽ•«{Ü3|õZ!Wçá—Z¥·Â*¤$l{·wº-ôñ†‚‰7ÒCcåÄœâ¯8µžŒPi ŽiZ:8AºDOëÍ-/ËèeEé\wFz—àßpøÖ"?½]o4L ¼†üâBàôpΓ6¹Ç©´¶À ·¸(< Gš¾.¿ÞÁJ`L‰[aH»ú×$„0°üòþ&N TFúÃK8i$ž ôæí’`!vÒ@ð›úôl­0‰1Ö„£ÀA4 ½…78½®Ñ"4,{áu¤36¹\Ç™”›´É+±‡ }=P÷üö LH$êxí—a'ea±_· r"u쫼µ7k<~É€ÉéÀGê‡÷ÈWgukw(ì Í<ïïuþ‰¡™ÏËÀ-Xíe\-þi¹K ð:.¡B™I§Çå#<ÖÞçµçl?ãéß• ¶„ª9üvRàæ7i÷.ab&"#&þÒš<䀃ÚïcŽÜ¬²é6>dÌvÌ!™ ÌX…ä#ƒ:@¢»ò‘Q«$Õ&u`)òéA /áŽ(iŽçG¤ªóµ)SL¢ÄJœÉ<‘ƒV"ÃþL\Çm}C~n,Dm¹¹Ž\¤C {ô%ƒ2mÓyÜ&ÞM ¿2—T<…²QBøÕiÄeŠëmeÁ²Nw‚y[U¶®üW˜³neÈ Ý^pä´ª¤î¥HÙä6°rÞcàe¾ƒ— |K>ì:äˆÔ&ø— "¨‚ žˆ ïGÐM΢2écÅsÜÁŽäöÊ”BhcF‹Ä…6.)Ì†é ‡!¿*°”屨8³tÇìÕP¦€AùvËLhƒ"ŒYFJâ-­7#HÆÑ5Ÿ’«­÷DÑ#[C“¹š.73Ôâ= äf-GØ^9ö³Ê¢¥YFáÿwžû£°:±vˆ‡FÄ;r¸JÖ(`¹IpýéŽ44ù¢#ï4G÷^£Ùazu@Ø3‹Kˆg†ú„¦æ9ùxå—Ua&BˆVdfR/¾ªÇ@Ë\Ô³ýeTåç>áC ùu—¸C2ÜY‡º­š2€éJ›€|°½¢éŽéK«aŸ” ·‘’½LûĸtÌÚŸ`xUÛ ›7"„k†¯&J¯®ãQ'Èoçe!R£UÛzF†©ºýËÜQ”†½ y J«±î¨ÂÑ+‘´Ö„ jIÌQM6ò;!üc«/âÚ„"q>4âñ ÃHÀÞߊ¡]YìaÄüFs»z¹ö,Ûåaí’Ï ó¼†¹ÉxÛHC¶k"£»¹ÁÞCŽÞ@È‘,`W·‚mkÇì^Äð† í\»D1à^pÏ} *bCèE*³—Îï–žEum„­«N ï:äOˆ…v a³jµÒPa·C¬Ž“‰wöÕ@aŒlr‚¼r`k€©â©vÈ’É®†t­¬©Á|‹Mxà®]X¦˜Ë^gØ`â-Z>Út#ƒ‡¬œÈ×Cj±2w‚¤`=P~_ã|è § “ LÔèžhþv¸Mt2«?ãRÿÀjæ8 ›¼ÏæU0ô+W^‘_q>àŠù $¦Yqt«Þâ¼Ç8%óâyœC“‡Hb/&Ψ€Õ9“½Ã;–¿¡ÆN<'®A¡Ê§/Ÿ">U; ü àåÝ9ï#ÃqœÅEC&¹È3;›¥²ñ;Sà=’›¸ °ÝÌoµ s§EZ޾C\ƒWbÑÊ&ÆNv»%GŸbÉBÊÞ÷xÙøan.e3hÇŠèå»Þ™™QÖ[9sÁ"HZ÷qc€¢žÅ‰Zýr7R7ÄûN, HÖÈZêS "U„’Ù "*â¶ŠN:t­\ì9 ùćˆLo¥ºà!‡¨1£4êýdäô.| fl`°Ã06˜ÏÌï7ŸÝ?fvy1๙^îX6 ¶w¤O·  `ŠBø5ì½S1šÌ`O ¶ó3Ì#ru‚™xñŒ‹(À‘c¿DŠ´Ÿç>_ÀTŸ9 `ç µAÊè`S9èx.p7ˆ9»‘-0bÞzI3ï’‡áŠwIA:ß–T¦FO1”[ûZ8´!fFuÁ×t–µv"¡JáX卑q%ÂYK‚X·1œÒ¸œëvÖ%)wÀ´ F‘–«ú#¶ƒÓÈÔÂmi Ûã†[lŸœv’Uí4öª7XߢCâ3ïGÅì9³¼Æï´óZ‰±¥HR!{»/bëMäNH[oè*·aLêSÔ‰JG"ùäSÔá)–XD«b¦M0:Þ› ßÜ›Éxo–莾zÀŠ`y6éu]€ D@ò6@n0CF·rÆL¦õùP>GÑËlB-E/1¾h¢JƒGCkÿŠúècŠ•_gh%ßOÀßÅà(çê`¯!¶Ñ{cÝäàA¿ nŸ@÷ÕÏ¥1îvÅð?è3€›ÿåOVÚ¡²°ñVR”‡·oZyyøU}X[šú°Žù Æô.Í(-£ZØ–÷·µÓ›òð¦>„­hpÿ¼AúÜ¿®fÒ‚Ášƒ¿?ÇïnËÃwuìåá›ú(«¹6ø}}úXžÇŸñ¶»<½®?cüN*0äËUäeíDæšÊÏx»€ cÐÐ?' |âùâu?ÐR—ã‰%æçINÞÒóD¿‰´>îYÏb_]šñföÐ,Jm>îášL\I%Hsùáe³®¼„×åý¶¾¿)ÉÁ¿k¶> y€l÷2ñ@P¦™ È\¿v'÷êýÍ-n"žòU¥J8Ü·éèóCÜN8‹Øü‘’$Æ‹–œO‡òðíœb^¶òû*U m²Äu6„;·ö„ën¹MÿH»#ántÎè9ç–¢¾où>3SÑ«1™¤Å]¦Y± ~IP¹,zMÄÌr¦À O×´#Ò?•»ëßès†§^©ŒÝ%‡ß7kK"sI¿¥Ýóà D|›{>Òðô.ëê÷qâËüÓ…dŽŠåȦØ:3<´û“A,^7+0c»/Ðz–E 8+P|q„=ô³‘î³ê¢ûfDþ‹ªù~ízK': ÿo–Q'# ŸÝ]ØàŸÕg°¸áïWU ˆ?÷¬€67N³‚‰÷Øø£‘†ŠkxÀ—Ô‡VNg²/2ó‹¢’³Daˆ¹zÖ,”h`"^E]¢Çø ¦XJ;Aô8 HfÞS}VSXvâáFìýH**ó=¯ :â§™!@ðc‘È{*òÃÚ†ÛIu±¢îÒ³¤v]Z¦ì«îV\àÄKRµ7Ò*’›Ó€w¤É'$åj–ÐI¶rO3 ¸˜¤êX/ªu¾ÑÄûñ’Û¸?ë-–h”{úó!³“¬71KzkòW”À*°ù§7ÛVVò¬!9†(^ïg—Y³»#J4pãVh$Ž˜ßáäùðôG0ƒÛÎÌÈíZî½æì¥‘¹|Sè5_ îgF×\€z4ôV©ø($2º+xÕúŒéá°OUÁ$p[M\âé¿* 8¿þ‚Úʨ`_Ô‡¯uÞkj¬T´å )±BXiîGi~å ‹–c_kÊàoø2#â¾”˜Ï†¢F®(sNÖøJtL„‚ ³”!=-'ÓÛ±£TÚEc'@Ó°®iïçºBN|ØC 9E-äü6̨…u´h3–, \SÀIê(ßD5ëƒ-QÔòȰ©óŠ©Tɵ£-›òHÌððççk8)Zt˜@ˆñ VÎ*#š’Ë›ZúySêAã{ [#Cú fàéÚ㕪ÈKušç¥åU>ïNdúpcH½èU¨V£Ö*Ð:y,KU•~Ò”fàüÀ/#ì)©JÂÆBJ36‰.oî;“á< Í…9#ÎMCùi_[]4Åws3*TBØè”êU®“û CÉœfNÊ䔈erDnço–_#š ÿ fÞG-á[žýýZ+ðsDÎ4–°GHH°ú8·8CÞ°d ò (IŒç³F­#5Adó²± 2°ÔÄ¥šP‚ÆYdÛ•—¢9·ÑÚy*™3£‘«¿¬1¯Çè&;5Uøq8™ÓÖ̪͜8b^"n©ƒi¬B¥íz§áóÖTLý°¼k˜(/^ÌŒ•”òfV°Š_7à 5"5“4)zŠ˜“QÓ¢¾‹mx­}•Dµ¹x]ib6‡®ã±kû£Yä\µçûÈ«¢©ÕrKöŠÏv>%…§‘[>?13O5åRX©÷á.;øñJ6X-URÐÁÚ eœßI Ýc«à1‘]‹vJghÙX.M­ |  &y?Î8µ-8Ï¥M²so°;h”ŸJògeņd(Ø vé1k{95´Ë í"Ñ “ÖÒN’ý·(«ÄŸÂàêå¬)5Ëåt´èÁ™IY?7lG.ñ¸D,Œ­‘f"Q+…ðIÔ©|[©E°šÔ4W˜Ò)0‘ÏÄÐÌiZÅIH±Çc‹ís345£·-ÐËÀÈqFæTg% Ý3Õ ’ˆ9C££Í¥#±¼‹žh¸ƒ~€xêgëRçu–HºÇ9I«ËL½úšã±î!U4þY®T?˜oÑ9QM¼*×ÅñRÍlÀ䆿SýÚª¶«”o ]ŠqÑ”\cý (‹Þ[[y}̆ú ¥;·,Ñ~Ÿ[Ö~‚ÄCh¦iq›Â}Z§0ËJm‹ fIЉ0­(ü´£FOŸÕ´õ¹Ý›ð}˜~ʱsq›_6Ň™jÔG-‰$Àv´EE±\Ö¬ð#V<­Œ9lÀåd\þ 4§U1Tc Öîo ÄÂ=K–ò~P+JSrCæÝP÷Eª’(<É7 ´)¨1ÇÖó”cÕ'vÿbº- W'Fa9—oJëKeB_©Ù|¦ýÂ9UÂÅ9:WtÚô&QïY9ÑÄdXÌ[&v á²T-œƒŽbÌiT'àÇ2p´C Êê11»ÆÀ›»ýO`í"¼DuXÖ×B¾ŒïGl»puá‘ÑJf¨Sб£Ï œhxçtFc5ˆˆ§•ìyÛ|.è6®Eöm©ÇAcl²íÂÏÖt –úè¿a -z qS¡LeLOŽœrcû…„ÔžÉÁseZXIuç;ЇÃáX¯ïMáÏ8©ä2N΢§ÇïyÈô©1=øÒX®JLŸ5:Äd*Ÿ8ùä  Ú1s&/K‘ô‚x-¢¨0Ïn»Žú’JfÉ/×¥ÖþÛj7öv¥—pÞÉħ?ÖAIƒà.ðÆRâMåM€@‚¼Q“Áƒ˜/g* ÔéB]áoö`øa‘Ôåí7NFºhy¯#œ¤¤(n“ímåÖ'­w»ŠÇâò& ‹a•$yHöŸæV̆oÇ̾ZÔ’4﹩Ñ_*œ>4š˜4øX‡Æ8¦ßÕjtüÉ*…AæcÀ?—¯ÂËú€æ¾x÷]yro¤…÷á·g,¡ÏÖ-îïÐÆÎšNÓ`p?­ èúBÉl¸ªÞu­ž<¦gJ¶§ºãOææ6²„îø®]¥ÍDQË¥ÁLÍ>š5ú5±Ã%®ß…¿_Oà½u1ÓŠšxc_Ä—ýÔáS–J-‘1“j_^ (\“€U-´@÷ÁÄÎ÷§/þ ÿü‹‡\§endstream endobj 152 0 obj 5227 endobj 156 0 obj <> stream xœ½[ÙnÇ}'üD^xà÷¾ȃ/°a+ŽÌ$?P¤,)±HÙÚ¬|}ªz­î鹋($FìËYz©®:uj™ßOÙÌOþ“þ{õòäóöôÙëvú üÿÙÉï'<¯‰ŒU“âÃéfÆ8Œ”´Ü„Iµœ…X,§Y¨´³÷Ü—5²NöFƒlãÓ~µ0IB**Ù§Ó/ß/g¦@.®áÔ‰´×Ï!íÔò°z ñ§ÁUÅ)//Êt>nÞâ5B°äâó:ìÓxwrw’蘭ÂfEôZ% ௫<+¾V‡®ÜÖ]Áp(€m’À–KTeñª*|’¿VQ¬Ï–ºC”l†;€&œIØš°³Vvó¶ 4‰ÍYµ9‡÷=*ܺŠ{1kx’H蘭†™jc½0ðÔ«4¬”Ua’0$ì\I¿¢Á;öì=ìZ´:•§|7I˜ÅIG®Á’ñY@o×_¯ñÁxþuÙ#‰ˆÞ”ËÞpÉ/¢†;xÍñ¬âdµ¸ßp* v§2vÏñ]¢ZQ?«R>Åe@ÂËFé‚Eà8ÉNoFo£}{;ã´#£*?Ðæ=…¿…%Å£¦'IU7LDôåâ£qo¨yå)T ãH·ª­R ù=¾"5îS¶”,œáguÊb¸"iÀþÔæñ¦¨Óûp°Д®¾ló ¡VIô.oøy«;¨¦’‡ÉVoQ `ZþsÚâ¥õ†¨ô—‰mô–:xäñTF›ÓÓxÖÜÌà&|‡j $è@ùpðÙ€uõDˆ^/„™Ž÷É@l7uØ›õÛxíÚ‡˜½3t;äÌ«p*•>a⋳­S g¤ùXÚuìÝ,Ÿ¸Nš`xkhÞù÷ÛViˆÞÁ;*ËNÏ«"þ'@ªµt'U—ÈFEÂC@O!PÌ®8ù²Q²cPnbýy¡»}­ˆq½ê³£bpJkÐÓ;pôÉõ¾Áë ý³1h&\#w6Ï«[âjz'ùu(,†L`w­pAQ+Ù¯À7G°µ4NGA3{Z4[òÞe൦LžÞA– KáàÀ!Àt‰B½œ÷@ÿ$neÉö²AH= sÔøøÍè>—VK o¤/·Î¬¹ð¬.#½þ@ èý$<üÉwnà:IÔlÎòž}— 6”Õ}´òü9.Óõ2 ¢kÊ£ˆŠÝËq–ÏOc©mœ¶…Ü3X—^4 Tb€’ÛÊÀA‚@>Êp7Þ@s kŠ?*Ͻ+¿nÏý‚>ªÓ=©?_”‡àE‘#¯˜¯þ\=/Ö‹ànÈ,ùêY¾ÅÒ…˜ ÐåÓ€ nñhËò¢X ¡V¶41Ž’ï´ôvØH¬­“­òHiÄ+6Šzdа‡ñ~ôv"^ñmU‘dÌ’[ª8yÝZ´Š¢ÇUîVVw¶DÈwÕÐÌQÇ#ìñ £*´*s%Ì1aK—èȹ%{4:&–5ð’G3Ž&µtãˆ_¥¨GQ6v—€ÄíŠBh]È8ž"ürÔõ\Z%Ûyx "!ü…ÃOŒ­g©„±ØâIHU¦F!#²€ÖÀàǬ4"*5b¤W­&ú¶1€¼Nrõ²¾Ù„?’û ¹^3D}Ë¥tNÂ8*Ûˆ j/Y5àö“b:ÄóÕO;oQ½*ùóJ!ŠÎœ`žEËa•‰o¾Çý€ÿú¶ êý ê#(Y;é›chÁ*YÂh‚Í|}_P°sž ò¼7¸l×+ô\€}­QÙC]>A’©þ¨X.à¹ä-á`󉺫.CD•_èYË1ˆ!Iƒ)â ‘³qrÍåh׃DDYî%õ!qpelïƒpt»naHùÁù+™dÍ´l #äìàÚ«hþœ“,a,©¼üåH[%à/ÓçÞM@=¬‘’¬Ï6̶8œ³â1DÅ ÷æIaÅ)KÀqF;EbßãàØX0¥¯'Ï!€Ö…ãö¤k\9QU©;í+ ÕaÍš V¹!¤x[¤-øûJÌ~(¿­ïS ò°…Ÿ‚mø.&g8(,ã»á~áGÌŒ¼»gµ_Ô‹?¯­ô]µª²úÓÇŸH'L¹:Ú“u ¢%‰;)š4Jºº´>@JÉ>ß6Fw9ÌŠrÞÄŠ@O»†¾§Éw8“´`Ø*n…h|±t€ D‡„­^L0l%@1 †ax Éaz‡¢á44ƒFù£€0Ñó'ÞÕØtOà2ð4_ ð“æÎª»À ÉÇ‚ÉnVצ:Ÿ×1ôT$r¹"º7$í¶Õ0ƒ+dM„RXâ"6ÍÇÖfO.{M[PŒðŸ¥¦õB q”z´ðÂ9ÂŒA úÄáÊ?W˜´&jˆkk+] %nªåH ²ÚsiÌ ¹‰?Ô¸ Þ=$*oÃ)jNñ2ÉÕ. mT‚¤"®›ÊìÒ17Ö«MÅvcÚŸð‘šw!HÚÇ0ð ÚJP¥q"!a¯í:ÁW1¤Üg4&ºÜ}ñEYb5YfAù…»”Æw9NŒ“\"$)ûµeíBI‚èoÖiª¦}­GFвÍa”ð,Š Õ´å…b]ìù¬z eþèE½zÓø%°J6 J!59ùy}õañ‰˜ÑÌì$NÝx€Õ˜ Ú™Ÿ±àßt *Þ×A9p’1†ˆÉ“—2IdzYÃéæ…×vT ²u…J>Þ”Fìƒ_œŽ.Ù?n>ª4Ê€ŽDµVXÝ 7°è-¤z#`á:yÍ$_ô«Xƒî& Ï 6wHá£\Di qbÿ÷®@N/*Q+tn)2¤»ßDoòH­ZJÁæ&4o\AWYUÓë‹«Õµb«©jì}Ô5gwI dŸÔä  †ÀÍ(£éxHÙ]4A"?Q8B?ÈH6úÅÄ9”H²Ÿ*´%rÉZm–xV9< ¤÷+àEGÚÐ)SVêÁú€­r–ÛF±Õü(<"fÎ(¿º­4´FÇ43ÌS Úg;"4‹d ª14Ù+àÁ"ä+v–êÉÛy‹ÜçˆYôýÛÁ;ã g{½ÍÒ³Yzm<ÃSKR¹ïNÛ|óõà=2v½£ÄQ1mŠÌu<;JµdÛ¹»‡sÆÈôX¥8ëëÁ C 8±ÀÕ‡ PÇz†®-ò1à[†ìh±ÞÈn6:ŒÜǬ·Iq"9 õ•HNxà)ƒ ‡<%?{¯þTu°eH?Íâ5|–8oi&|ìÝ*\—ìV”X–Â; ÿå ±º—ž&<+>|¶’;µ01É€Ì)~åf÷¬ –%´\Ú^¾1 «Ð½˜ÜV­ôSµÍ­GҬǩ±‰(m[I@a¯’„® ”º¸ÐgrF|æú¼G–ghÿFªúì‹~J[I©¹lIŒô  ]”ÓíÚþ„Õ(R {d&P=Īªü儹k|zI³œÇ–ÿóD¯û~8ÑöÞDLt—šÀ>î¦ðÚ‰2lE$$º¤Qe¯5êP}“<ÖfBA ÞÛñ¤+´‡–®f‹õÍ\ŸhóUì-×’ÇbqMšýE8,d±Î§§6וXû.Õæë“þc ¥ÛïmêGj½…0wÙŠZ¥«~}§ËëÜ[S‡Õ³o˜ ë{„îO‚*GìÑi«ƒ,%Úíø‰Q‹ÑÝ?3>d¹>å'`¡(4h‰R ´sä û¢æz’Ä)‘òð2|n)6£ŽvQqW/£¡5FS˜òABýeŒ“yà¯1»G_÷jĵö~5@]øE‡O®¢u¦ƒîǬ2Ò[¯Þ ]Ú…üO}N-*±š_Að`òríF×¢’p±óÆûBÈü²QD°º†°Ö7Ô6é’òÛÆ„&qg`Ѝ‘@?9oóLyè]ÉÿÔSÕEËcp+c¯}⚈|§®©3i¿­æ„8iZ©4Ä®˜ð†`›ýÈ5\Ã3x>WÛ²Œ …&Â.kYŽuºYz²ÔJ‰6ƒ$žPIé¦oR–39ë¸÷eCI3¾ˆþE=ƒþûɽ"¦E®5åŠ|·9(·†j‡¿3šëðå (&?VîÙuStŸla°R>êäc &JÓb½ ™ÚNO…Þëx?†|а ;ãA ÿ*ԤÌÒÎu ¸½3jàéÓ]JH FÍÏ{Vfó î‘kÆi¾|¥U!½ý—ø6ãrÐ>-…˜$ÔÒ÷¸A-æ_÷œU¾ýHwÉêP^J”dɇµ+N¸'mT rY|°’:-ü¢Õ¦ú§Qg¨¢mBðç}tƒR<ˆ=fqºÖÔäšžô«‹“Â?ÿ‘ž:óendstream endobj 157 0 obj 4366 endobj 161 0 obj <> stream xœ½\[s]µ~Ï0Ó¿àN؇֛­»T†™RJ ´\ fÚð`ìÄÉÛ!‰Còï»ÖÒmioéØNLËÎÑ‘´¥¥o}ë¦í_–Y,øOúïÉù½÷¿qgÏï-‡ÿŸÝûåž é?'ç=‚NB1cäÁÑÃ{q´8ðvÖÖˆYꃣó{ßOf·Ì*§ý4ïĬ”bÒ»C!¤šýt´óaö‹ŸŽwzöfYÜôÓNÎÖY)§'4À?=Ø*¿Ì‹´Ó}èh´õbzL?;Ëú½ØêYè`% Æ œ˜žíå,•º¹ ‡9Áúô²Hã<ú·ea£sX‚ÀmÉe6"„ƒ£Þ;z7£`0@/Þ9ØFóU஌œ1}¼;4³6Òùé:=©®à£÷Né0Ób¤ƒÅÀî`ݰÀc˜c.hl-=Oc‡%„é»Ãe¶°&èü?)å§×0Y¹é×t³yà£çe(³h ‡¦ðØû(¬7 —²@¶V¦š×Ê7гYí-—ëád@¦rÁ{›DêW"µ*ø,Ò£ø ±¨é Më`輜³Ó œ·Öàp¹3°:9;çȱt>Ç}XëéX•„þJPïgøUÍôóNÑHsç _㦤”Ö‘Ô|6&Ô0LIS†¦|§>³¬ãÈOI¥y¥Ò|ôãÜ=ÃU€‰žãqhŸžâÁ@B{žé¤|*½Ã¥ÄžH•¡v|Žm€_˜ ‹=±?Íb“l?—´Ì,]g5¶HˆAŸÖËbO­íP²jñ([6as¾ µ(ÐËÄqt TQ7{ÍIãZ.ê’ã–¬„çÆ‡ø”Î@Ú²{'|z(hí˜~•‘(pŒƒƒÉ´TÒäÓÃ)Nkÿ÷w¦YÙ-Îû¨yžŠ{>Ì›> ¦_dÜ{ꀯøÄ'§Ç¾±ð – Ôð6¸Î#R´„Õ˜¯ö>íÉJ±ÖPe‰Íô)RO𰘿!‰ƒ†é;üÙC³î·†ô¢±Z\åbý×£u®=Eé)$âÛ8 dOB¾qÀŸu¯Í ³²p›v­Q_s+“j}æËxÊ[Ÿ„gp•°oÁxìã–• ‰÷ŠS¥ÍSÔQhUqåš1ø˜õ%“,טL;ʘÖÙêøw¶hæ*6ÃG8J æç3œÛ¥˜’%àÇð Z€ªôí¸DmIþ?Å…É”Ñv˜Ì;Í ŸÙÚÛËØˆÒ{Êgeê”ÏqÓ°È=J ´3×Bc5Ië“ P«WVæ[(ˆíÅkª´µpÔ1ÕÁG?ÄI$‰¿nv¿²V=¸¹µ]2§.ÉЫÆyvVè<J™™îw;Ós ð#vNúðÑNr K Çs¨ÇÆ–„ÇÂÍqüˆ‡}±6•8 ÅÂŒ¼±k‘ €ž8¤±‘ØÀbÏ­¿£@êx p““èî‚»¦ÁÿyŸQq—IZ¤Ð"ÂÐØÂÊ"·ÜÖÄæ_´ÌÍ:6øôÖ)2Ô2aôùˆHP-ùÀ/ªY=.KÞõÊG€Sº“4Ì+~tmï¤cÙ®”užâ,Y°‘|–p¤*XWKSCh<ñÒéÚ´åî雽º±ÌYÁAÙ@58²õÓv¹ ½åF`±5¨©1@$Ç1ùMi¬q¶·. ?Ó YYð}„-To=¡«ü…AýªÝöî×ZMºÃ6SävÆæÖ–{o™(’'ð‚ (ƒÇMd6^[:ÝFìèVoÜ=ÄoO;z:p’N]›ÚïUKð]Ï4ueF|#fòÓv×y³­ïÙJiÖ¦VÓ’ÄÐô¼­Ç˜fl™– ˆa›ÍÏ}¸húµsŠhÒèDà[¸\õ´ý T²;ªfx5ïBÐWíLîIµåÓLÁ.°™ÝU˜…¯{.R‹‹‹äÂw›a‡# "˜"f;f ”pµ“æ¢\DP2‘”u\pŽWè¥@§Â^«§7Nmò%iõ-G7òuQæÇC⊎sb/-W@&g¢Ø\ ô¬CºÖ ÜQý/®š³ûCDG÷wˆXg³³ ÿS9‘"ÁÊ|›èOqpßG¤:0_aÚ ;}ƒgムà|“Zkœã칎.jè)ºt®—5A  ÂôÃÔ‰ÈfN×å Ÿ€&ÂLï¼²€âÝ]Y¹ŒÝb±ø Ïq“B`ª¢6æž ¢Úø NZæ¤íirfjc ÇÚŽ^BÇÐãúHßÀ9ÓÕÚu©ATvÜ[ËÐÌ…\;€¿¯¼4´F2uÊ~HßͰg¤^¶/÷ØÏwóé€@ؓߙڞg±zH~æj=$‰³´¥RÚÓÀ…γm&X[Õ§n •\|'æSBé É¡ø·UWú £­µï³wùàA†®Ñ­ã3Xyg?ì ŒòZL˜2 aÇh+Æœ­ùI§.½¹ CæqšYäXƒŽA“»Ü0uÚ}‹ç}V¡XÝ…±ÕãѾò1‹sÏãš 8íuep8Þ5n Kú‚·À/ê¼<#ÝOL1Ëtä;¯œ³ä[œìj%(ÛþånïÍiÓþÞuEZñQN]7á’m逬CȦÊoï'ºÙ  âµR2'ãfé‹ÈTÕ`)¤6³[›Ì§!ßdœ½0¦}œwSƹB€¬¦ÞÒ¨'Ç  ëÐÚ¼AÖ-Iu9ÇþÎ],øº ÎYÌ^/»Û ­öTÈ´û|ö§Ï5é@fS¹¾äر³Ýe¥œ¥H2ñÙôégéÐ=z´Æ–‡‹ÙüC7¥Ò ZÞÊ ÞŸ XûÒR»M¶E*˜XeçBªè÷Þ: ªæ¾4MÝËHLJ*¹^ÂÊ•ê—:¹²ž³QŸàüŽô»öëðÚ°–À6ØÛ+#Yõ،ĭc#4Juò‰}!* öíE/ˆ««nï¾H¨G$ðFÖê úq­6£ö±Ê[C݇iׇ”}ÈD½-,GB„Þ‚ò¤¯Ú¬Üê(ZæÞ…wz“*—!æMBŽÑBÛ‘.CÌó¶ÆœV†(§ñ˜Tf'ÈÔ€!¹W÷ê.&UÄqÂ3s—»!ó2£!!V¦ÿ336ýqàÖ¼w/’¤8Œ¥£_ÛɈ_¹©FQjS,Ffùº‚ Sy}•¦j²© O¹Âv!Ül]n-š§aŠnœEŸ"žÌŠ¢·øB’e .”/{›Ê0x’H›#øjCôÝ¢W+s×)-IÈåþClóÿŸ¬8ì­ÍÊo1Ѳ?3þõ¨ÛÀ SÇÎ"¥`4§8jvîšGÁô\ˆn¬ë±,~HÌ1úˆ¹ä06ɹ¾ÿ…wv*:÷V³‹Mþ¸½]9‘å¼^Ò&½âñ&çØÈN;_n¬‰1n•™fšRÚ6S<&ºú¢ù¸W=w›ÁºcÖÅæßúN´º%u‚÷R`§oÅût±'¬\e(­³'ÈÈõœ ;UÅ|ëªaæUìIÁ´àÔn24åÇ{7—®KìöÌÇèFÝ’WÇ»5MCYžÈÀŽ_íéJÜmƒ`Æ_qìE)‚<›È.¶õîÎ&½VšnÚ¬t†Keÿq×¹§36s-·vóV§¹ä32so„ݲ(ëç¶©ôuj mˆ…Õ1#ÉÚÜ#ºÁË é.ð5/ƒÜ*8IeÄÖH×WVÞÀmC00*X4ªMŸtk±Ó î§Wïf/b#fnŠ©ì9Mc‰cQDÏÂÖHŒ†É©¿\„Ú_ƈ‘‡]‡˜9I¡T·bXÌOUt]„eI—.âJ[mšŠu‘¦U¦„?'Y)§»08Íïó4©Ðmw~¤ >‹k^ÙŒ»LèKw-ü‘»«r†Éí[gRÅë.3 ñìîì¥&¾„d ›—aòÅ7M©ÔRuû²Xõº¶¼/w2YT17K_“ß%hþ°æ»ð£Rt=ŠeÁª:°ªJ|{µ^yjk/x-Á¤KþUyÆÅaØEô›9•ë•o`d‹Å«Ulý¶¯àI±}J”š“ìþPyxgã4)Mk>b³Éºï)ž6– †܇ڄ$èê8ÌÏÓM'X_ã¸æÚ% _5­·*Ž  eLˆv=¸Æ›¢'Èq†/ïø Ë4 4üNá ¾© Ö‰Ö%žxóRÛÑ]£‡t“H÷ßôY¥¹÷›´<;{1ð¦ïi¥ûH×½iÔÏ •UúIáÈž]…éˆ\|ýcC¯ö¸déÀ16º&ŠÂÃ4œ ½\˜ÓÒµ0Ï,Jw雬©ø,#Ì­®7­J n¡úÒýÆÎ«æªã¸ðÉn\ÕqO‹N@¬KB%ƒÊò½÷ýú%VäûU~†—Éèqm5|ø2B wîFV¹¼*¤ð]$,‘efL÷uR˜×¦†˜Æ0”ìOœgƒ>ʦ3ÇãÖ¾Tºþw‹Ô)…´ëÌpråŽKÕR®Rží4Ü5ǰZ{Ê_³·K;(˲^4·)é]츑am³Ôê£Âɰ ?ªî%Q›Æ´Ä¤Ã²¯N“6ÝRz¯H%…pÃȯÐÌø5ë}ÔõåJ€V„ýáœDÓrã: Ïh_Ö _KTï4ð¤ø]wI?ÅÅsþKõnß͈ wŸ|åùaShÖP«ù\n*)t?ž:î²ïÊÐw®"ý¹IÚÈІþ†‰\½‡û=¬…êl¤Ç˜þ2Š£yù¿ã…vŠèkü3"Ÿâ×0ËRïÁG_yøÓŒÿ‚Oð8jü#Í9-e‚·Fd’¥ñGJú:hW&<)¿?«ƒ”ÆãÚø¢4>¨Ïq•ž²)½ß¥]°½}†äÜÕG_ÖOJãUmïIõ?° ±,ÿ¶Îo’K>mžÊª¹ñeoúg œ¶)õž®þ9ú=·>jž”a𬠃èZbÖÚX–Èà:Ù oŒóú±@™’ë¹õuùHVOX;¯/'œ–]>®ã^ö»=+¨Î²d<“\G0 د¸Znð¼êêHÕÙL·‘Pd=>Ï$y²ÙdDåü¤¬ä?uD¥§¯jã·¥ñ»ÚøMiü¤ ïçì^—Æ_|lñ{ZÕãeO§º”XÕc^!ÆCøbÁeRÚo„ŽŠúÿUÅóAZþð—²Øýô_üLá”^VLqÙƒDÝÀëª5×!îI»•Ç^ôDqz=â®1.ÊbÇ÷x^Tï"MÇOíéæcúû^‚yÖa>A*kg¥ÌW™‰ó:>ìÉðÉ~vþ´‚ýš94[Ù¤ÍCL­ƒG Îü"âÞðÍBóìŸÝûüó?±ÕÅ>endstream endobj 162 0 obj 4604 endobj 166 0 obj <> stream xœµ\é·‘ÿ®ø ¹ßgÞ.îlSvÙÜÙåË{Î.Ôù5þ¹Å?/F®ËººóKüýÿ¼Ä?á´ qþüù;üóÿ\áŸ÷øç‡Ã…uz[Vq~ý(ÞÇ.â‹7‡ MÎmaÄØø¢6¾-j#ŒkV·xgÏ*÷Ÿ5÷}˜m¼÷¼Þ{YçuY2ôm}òEi|;zý& ×—›ï“õÀ„ð0K?yàçúö§z™–¤•ÃÉæÖ×åò‡Ëÿ¼'œZÔvv!Ôb¶Už]>‚üÈõäÆ7•¾ïGô½-oúMñ»J÷¯ŽþñhøG´û@c¡q"ùþóŽXH¡gµ×ÏFÄÊsÁgIgäÙ…ö"SVÚHÔ¹X\àï ßàŸ¿•ù…?ÿÅžÿ¥¼þ<ª]|¿¿H¿a¹ß•>.ë¿5þ³4~WAì„1 ~Q±{D· g‹ÇŒ®}ã›»ŠÝ7õ£É¿[ìÒ6·âa¼‹;ùz´ºãL{G:|äqîF²€L¢Cn3O ä¾ÜúîÅâÏ3X„ðþ˜ü±»“¦û¤X l 4CYKWòU|8w“›l F5\ãôzbº#¨i¡§'#£PçúÓ¨{¢D˜åJWOëèõõW£Ž8?5—¸ÏÙ’MÖ`°=öóûOMÂ1ºa¹'#;]»_F´ü@µÛ@x&J†=™ÅlÓzëˆëÿý}á(й ŽF6„ AMY'VLÇ¢õ¶ÆMÇÇ´:Ü0½(¥½„‘åb­U°Ý¦þ¸©¯^A;LûE*qþI¼£=¶¦§±wµA龜7øŠ #ÞÔWpp¤À²öúúÚl6ÏŸÁÉ+8¯Ç ¿¤ÒA×îÒF?<€ ýLúV‹sV)Úa7'¸-£¾\ÇQŠM.¬õ. EÂÁää6îâ*,?R:¼å+þ;u°/àÎKà,@±kÜaò$RCÁ%ºÙYáp½ìƒÝdõwœØ*Âd9ëÏjeguTÉÛf7DÉ¡Fû‘Ÿ3ðИˆ+­€&£Õ!ê³dí|ÊAW«U-­™»ª ¼­Q7yÑN1-Žò¿[ ÿ£ºYE ÛU¸“¦¶I‘è#¤¤Ý¥ÕƵòÓÌYÑo‹¥y]8 ²åV|$î;ê‡BàÇÌK–7bÀWõòm½D³àHÿt ¯€€}ƒ„uðÊ*B&<æW䨩`§Á¿?/³#{[7h‚jÍ©ÚS¹ÀÕ;²l=aÀð/Ã+`/4͉ã ˦Qð2Ù+‚Ó±.R*ë·óï…Ï@”´€Ñ@ ß×U?«üY1ê"%ñnžM½KX´°ô‹r÷míðžô`ËÔiuÈÖp_f¶¾M,ÈuaÁŽs4`YYGoø¤IJºÐzm J©²5g)m K«“>>“§€DÞ¶EiuþõA 9Ò •FfØ<€¼ÜöAµ\Uâ¢PÐfܧ2V¯Sî/BάQ–;°ÙNˆ@¯ÈóÖûŽ þLÒÁ§šÅl¥ÐÙîÙŒl öZ K³ dšÊTyrEò±±ÙŒø™m“TÕ?·PÉj]q¸GiƒŒ›€ØEbÜ8:uœVj ÿWƒ)Ä©Œ}ůµ„ xÖN;#:zÚkatj¨kƶ‡½aªKÃ9Oo2}8bA½‰]‹ñK¶Zü1£ì›xÜ(xäƒóó×{—¿{pn軬¸ÕÎÚsÍJ`)a‚órz7`ùqª|„±hM=ØPÐÊ[Ú½¼ÿ"\Âp [gÂ2`:R® g_Ãtº±×nàWºåéA 0îtWÑcßD/° Ý [T÷Þ‘1j"`ßÙhŽ Ðá…m`àR ÎfÒYM^G_^Û ¸k華 u7\ù }’ ¾AJib\¦·Î8¥‡C€ø˜õ’#V“ÙQÌáŒqÞ¸îy³æEiv"8^ˆÍ<+ˆ1Ž·9–’HR‡FQ8äû•½YÜ*²Ž}Èöp½¸ÆöMê'lÎF)ù°*“~‘ño‹Õúš@ÝÚKiþ@ Ê« ˆiCÐádÊSмäAKgp5ý% ©ù5q®^mÀ7#Ô€»îý‚kt‘OÔÓDT¿Kêh5Á :¸üÜ‘`Ãõ¾öåÛtø4;BâvMaÊ*Ãxß¿®ÍɃâþáq «òDÅÉ‘ªKaŽnR„À¸ºÈAa ÀÃÞ §9Øé–mXEW15ÀwMxÔ†-W!Š^e¨—Ñ}Û6@#^±OÒ¶%â±£–"PÑËIjIûâ`À{û¾ïl ú•ÙBép7úäsô&fä|b %æNAŠ0Í"ÕØ8P7Gq)!|Úé‚ʤ¼Pß{w‹:åZw4e¤¹‰¦ Þ¾ ¤! ¯SøÃaà/±òÛž”Ü=-Ó^æ(ÄX0¢µn”sxJn`þˆ>þ‘Ð’øz942 ¥'"pyÿ—û(…ãouIŽ›b>:L†ÆY¸h$žÆ1ÚU’4 xÒš Ëš;Dë_.õàÍáãÞ–ÇyLJº5hÖ+¦!ðWâ=KYŒ Ô˜¥GLu3Ô¼³0¢gƒóGU­ôb×_•î#¢1°yœM \<ÞñÑìDV‹€x ’uÞÆ§Wa:G£ …ÊÛÒ’™xc8{ÌsD€BmmƬUn®p‡°3o8uÞ‚@ Žuæ~RsÛZlsr \àOB4 àš€YTmº…¦WPÎuù‰më°«Š §;S/r°ªpØ3š¡u…¹¡¨Ý3fƒ:c;ZdF#²ÐU„&%ˆoÔ8 ° ªñ©Ä×D“Xœ‰{> §)“0Þ!¿ò0ÅUw ‹§XxXð)ú~!É›FcÀÕ>Ç#÷„(Ò³MÑ ²ƒù‰3ÍU=6&U/ä£@õÙÑËNî°ûèD MÈ]å°í?¹ÑWH"ä±âØ->ïf…œÿ{PaL ÿª¸"^wõ]ƒû,‹µ K‹Ï›ê¨÷>Ë ªc¦v"-dãÌ÷‰P^ÅPá97ˆ^fÛ5t³¶é¦ æÜUÀ­.Y^Y#_Ä£) ‹)’‰;K㎠&}]I00cë´(Æfùå„ù¹}UE± ዟ³ˆ_S'á^Ñ—Ÿœ¯¹ÿZHÄ3×}^üMi|0êèݨñf¿£jãƒÒHJ?î—Æ/k㟨–¤õ¡d)Þþ¢Þþ¢4šæ3-lÊ:±Pk„ÖììÇÄî2“âj­Y²7;sÕ¦ÀˆÚ±Äu* ø£sßôµ54@\2æ¾>Ÿ@êx„1­¥²ù ç Fý×A–Ÿ ð‡Ÿ hJ¹ìj%æÁ¾Rq0vÌyþªªÕà/2C4rÍ‘³ SáÁ–ÞGatÔƒÖ’)õe€"_ÅrLÝrÀ=r„‰ ßÔ¤ûqšÌiT[QjDz¼HR6ÎvòQ <³VWïNñÁ …&k€s|€ŠÈsw|mþÌ­2¬ãTøPc­w~ÔN¶( ìPŽB€f$BòÛòÛº³ó„µŸsÄèÇIãäŸWÃMÒêkÜb΋½í˜d‹°BIÅd&Ó9ã‹íyN<²ƒpÃÈ’Í’èQÏáxãÃh¹sîNÛc&Ä£œiýÏ.–º–ä= ‘·™4¸8çR˜€çêû"®ÏbDazm'ÇÈŒ+{X‡ƒüLûýAz¸6¦õ»2,ÚNÒ/9øüàTbÝiƒ Çu^Dj*¹^žkÐ!§{Fø¶¢ëýT`Zc38T@næ›øµ#³]Xÿ“ÞV2©®Ç+%šœüèåÁÑ1¹Š†æO‡ù+<‚ÖÃUø ¬‹K>éfza|RŤÏQïð×rå†È;¹ZŒ§y$L±¬+òÞÖhê0áàžÎHÁUšDU„=ÔFñÜH6ºB‡”âUbã=ò­…·Ì²z{,p2¥XH>Á,¡—»á“q"«‹˜ŠÒ oŠ ×`jðwd=]v94Ûq7¶d•ûBÒgã<5h5à”pJåϪíY6¿Ï檮NM¬ »ŸÑ×gy±Ò<Jt8±­¥F´|S#Ëâò¦s(¦¥)9õ!uΉ‡ì—zøCOrÓ˦{O’øz,¤6¼ž¯!UFžä¬»oü0jü¡\ÕS0#ÇÍcÔ:|säR ¬šPÚ-B”# sîó¨j-!’XÞ4U(`šfȰ%`¢û”«ÙÄØxëXnûjh,U‰¡¬TÚ‰í  ‰¼¥Üa+â–Z¬ÁuaKu¬pN$sJRöYŸ˜É$á û¦šó¡vAž +·p…Ä’z;'eçë Í“y„EüÈøþjÈ,$ì#É¡Z>ê˜TBE¤" e±q¿äÝý¼)ÙSí‘ffd ãë~„¼ T¹N‚Þ­¬ ‹¾ ©…é}¹R ¦1®Ì".AËj?G¤a„]I™¹Q_5` Þ“XW£ 1³qYUŸÆ°;¾]Wãn¼7sFLu«ˆËk‘æ ¨š²ÝÿNŸú¨ÓôÙÝñ ô>DjÙa´R01®”åE]+)»ƒ4$iìÙ=x¯ŒßiTHlÑ(¿q¡•~)@d±˜-Ÿ#Óµ(ãÓ\-ƒvb×üF˜ óˆU„»©»¸ù‚f*¿ W)äÔj×èŸ3DÄ*m‰˜ÑjÅQH†Æö2-¸  êÿ¬[ÔбÞÜÂò½,šó8îÄ?M3ò”ºñ|?›Õ•(JÜ5­IŽB?ÌOj›NÊä Ôm˜YÛá ø>D¼§Õ&[,ýÜ7 á!Z|•&ÑX\ãÚ3C'[ÈX;b¹5r°o*SÀÃF-’-%0¨`)·X)ÞÊä*¦"ÉŒtî\mc@uS¡"+ˆEŠ]‡%r<4,œfZHgTŒÃêá›#dIQ^U»pWÇ6†ÒÜHèRhê.š¯uij¢•60æ=µ~ЍéG'*žâè’ü[Ö÷âxñîØíl.+‘J“9_û%<ÐÛ¶or5ÇÐ$°ÉÅ-ªÈÕqEüää4ÈY¬TÇÃ@¯8÷:#ÚeIÌ bƒäéZ#A½ßÖ.må1[‰éNîEà06X"p¿-ñ®¿×pXý"ÇÿÔÆoJ#ù¨Š<ì7èuQä$.¢+q†äÁc†äÕmÐ[oM¤{| ö&6YÑþáà€=ÏN¢iÖåpS>kwÊQiô­5©Þã€ö'üN²ý}õR¼ã~‰ÄQP#,zÁárÔ}iüÀÚ¨,ÚÜY×Ǭ`q¸$Ø8ðI~‘‚O¹Ï] ¦[N¤ÖØR#êq®Vrùà¶•Ä¥g½‰À0°”‡Ï«ökˆ$‘ަŸÆHç{Ö¢×÷ƒÿ1ö ,ÕÝÁç 7!\}õY¤–—Ápr«ÔÁæúïµÇ­¶ ŠI७så¡°&š=€à$)9døA8æ:áJ#‡þ0O¬‡.ž/e‚jÈC§”˜¦Ií|B[Z@9ÖÉè±êÔ*,véSxí³‚ÝaÁ¦õÄÌSV¾6gžb üŽê”žjÁz‘ÜͧŰý™À| 60ËèÛÚúu÷,¢ÎOw“Fc¾«¢1§ªÇ¶:²q5ÖyÌ:Pž5Ïg//êå·õÙ~¼ßálÍlð³˜{Ø\C¦ÈG¯N©Í‘;Û •|üë´ßWÚ0ɤ ö@»hrVžz:^Üeªð«w‘ŠYÒ˜µÂaÖhHr'Õ@ÆC©|Ù½ãG0ÂñRÁ5ýŽögV½§V÷Ó\ÏÞ.½®=™‘òØÇÏÝV%C DJ;ñ<ÆŠùÞt¨}ˆ,óÇbTŸÑ‰ÞÔJ–Ó¯nÄBy-±°{§|!}Jç®ð1·~VEqò¶M!vŽ !¬lÃ]£|‹ÄÔtHhëV¦Œ¡bY'.ê7‡Crˆ8ºäQ´¾ÐF¼Ç)—¡güª4)¾›3;V-â'µöTôŽ4™>¦¡¥ Eq©†ßÔÏÆh<~K Åh”w\Ã?©ÃÜ«áÇÏÔRóZyÁmZWŸÌ€â_ǰJ{͑ϡ…‰æ'.JÏj¿gðÑ ñŸíy¿¼ž{ ÇÃÈ1üO¢Ä£l#p¼îôq, ¨Èt$R«yìÅcðmã‚ §û’gþº«.¿CaHok±ý׊ ?O%|ïT\Ð §ãµZK²ŽEþTúÆ;â­ÅÂ’©q(”ê¿ÿb…Ÿ‡gJ •°prWÑÉ«Ëag'1¸ð)cjcr^,Z˜ƒ#±«Mˆ­üãP H5[á²æü 1äiVPÂ>)2òÉJ‡U¨H64SNÊfÀÄÂa½Ãö°F2FK•.#¦NWñÄ¦Ü 8UkÅ;LúÓZõûÜxrùS‹«oaËÇcÙ‹ØhMÊ0[Þ™|ç1Љ‹_ö ©ŽÍ{)ððóä“<õ\Æ…:0I:˜²Ú5'‹ž6ŸÛ鿱Ðgñb} Å<í×äb¹ LaÒè´m ä ¦,˲Y‰QôDÍNJÝ8rÞ7P„|´ˆÌO7 1âÚÕn¨˜Á©£rõ­y˜¤Qú;Ó0s<ødøè4 ÐÏ–€rÂCVÿ„ÿB yøÃM…¹ê I¿¨…S—ЗÖû«Ë{ÿ ÿþ?äAýendstream endobj 167 0 obj 5562 endobj 171 0 obj <> stream xœ½\{oÇïßD>k£ 醧Û÷]¸ˆ'uá:uª¢Ò%YVCJÖˉ Ÿ½3ûœ½›#¥Ä.‚ÈÔroóžßÌébÞ6bÞâñßÃÍlï;7?¹šµóoàÿ“ÙÅLø óøÏáfþh&‰Fš¾íÅ|ÿÕ,<-`H5JέÔóýÍìûÅ£¥n”Æ.Η+éš¾³ >šÅz)çœZà ­…”‹>[®”q¶~Òø­k´‘–L»\®pM݇'®—ªé:+…"~i[½¸‚‡µlŒ5‹ÃÑÚ6Z‰ÅKºÁ žkŒYÜ,W¦ëÞà†œ•ñRéÅ΄V,NÓ-Îâ˜êâœR‹×e¡´ºÖd¡Ÿ–«¶‘R¹ÞâUÓ\rÁ2—œ„|ÌûŸ“{Åž«¬•¿8jšw‰Ì°Ò“3ÿµÿ§™ìUc$Àþ0<¯kÓ(³øzÙ‹ÆuŠ2È ×4mŸ¥í*™üˆ_ Xü¯£\ÿÈœ£S’®‹KlðkMT³öh`‚é W؇Uà@RètéD¼w+ðN+â­õ|%àn¦ïÂÝâ–ºwµ¯ €Î?†ÕA*6à6¶µ‹¼kÚÖQéCíèšVèÚ¹ù«Ô¿Ìêaý¼J責À…©Þ.n@ä‡NGWÇÑ—E4@iú,!}÷¾“=µ R6½èûù í’úœÁdq?n¦m+ì³Â]áLÑN8ò6~}Œ,ê{¸±0 Â× ex2óI™ù¢š)[Ïœ/ò |-°¬ïý±ÂàYyü<^—ŽóàE™Y]# ®óà=Ü]õõÈFñrÈþÏLê½`§ ÏËÇ'ƒ¹áü¿-¾È‘!(ç¶•óýg³ý‘üë̃«|š+¼aÏ¡IXyk OÎè5$\}uÙùz;cž•™ûc>‡ëgjv¬+*•æÁ|nM¶]¾?àè½·]¬vsS¶®,bϹ›Ïvqó󊛞>A\Óèç3cÑy«Jhåyx9Žæ Õo»­|†“täv'·fò7;˜üc2Yþ’cMaâ5'ƒ;ýŸdÀoYÝýä2ðÍ.xHe¹¬\—|1‘„‡•$¬pÒ*ë|6¸çY0àW+{Sëð9G–½ß–™ßqìý9þÌWBË"nGefvªÓµjÕ%R‘§šd$¥ð—#ó‰}U?&zˆ\õâã2úqEP ¥V&óy–•é„ѲÓLï³Ho qFºÑ¤{Ý…R˜ÿoóà>s‡ŽuùË’ýM|Ã1HÂO”¿I¿~‰÷û碌 ªuñÓª|íÊCËJ*D+@fåâ¿w†ùÊÊ–@ãù2Ä%NÂmá$Qoˆª@… mšŸƒk˜ÎW%2‹á¾´Î‘Œ¤Š HèZ‚7ŒºG~ñižÓ¸ìl É–Ñ-Ü?ÅCCj¦Ÿ ¥¦ ñ‰OÒ‡2-¯†þßjŸJê “<$CšfŽŽÛ @å[ ä’î=žâz]'[üçXAA.h¬Ò¿ rCÑiNBÊÎåö)¼§^²)ÍÎóÚ6ѳ7ceñd ¥R !{2˜iåR"éD7N$[oÐ|®“]äªí|ÖS2£×e‰A~"«6¼Õy-KñcçlJ#1ÓÀäeAf-žL0^—$§JG|©¶hSJú M8 ®RÓqŽ|)¨mVRÏç¥Ö?\VÃ9„/?àÓ @u>'DËB'Õ:¦!ˆfÙù›¥j%œp*Xe!GЄFb(ØÔûxé™IÜGÄhE”…VTâ6¥Â~LF½ßá ôÖÐíey TSÂM~ (¹Ê:kD¡³W¯×œœm£\‡›mM¼ ÈS4=ã7ý´IöY­³#‰Áézø އ§*v°MÒ~X±ó†ŒfÙ>EÇ) ÀI­sç|ºM5¯TC²f MÈ’+­hâ ÕyW²—[<ÐXÆ‘žeîpêœù!Ù ÏÉÊq)OHé ‚)l4üŤ¥‘\­ò1gv {óÃ7•ñ"Üõ×îüÃv°‹œû˜qùáÃpNc$¼ lRí¼ÇÈ‹„8)µ¶Æž 6I¼Õ¸ ®CÅHÏ’h:Z`¼kÒ6ˆí/!”–­QÔ5‡†ÒKÖA¨là^²9a½²Q€kt–¢w7e]rÔl¿V°¦R Á>ô0w‰ÚBÍ]<šXI È0cxQ®û!ŠNUaÌkÀÑþƒšJð§GÓÞjoÚ+¹Múv2´ Ű10²Ô ÷ úïú~dîâ…ˆ,í„-ý2œ&b#µÏ>˜‚¡lhÌ ½ƒl% ý/Ò´ÀvIY†â…Ž“6­ï ŠE¼‹L5Ìë6˜ÝüX q¤ö!{íØ½ÕÒö±büÚ«A$Lí%§‹Ó®ðCú†T$Ä.‚8r¢‡/!l99»n­`œAŠ*£”ðÎuå.&t¦ÀËIV'Øêon%ÉCo— ?µôÜצywÇÍ=Êp”~„Dùt ò`œöXÊï 1-A®¸ìý%‡ò]r8Ú!]œr(B…*)\ÓÒŒ ¢Þ,cq€àå’oÒá×ÃL›ëš,ÆyîÁˆGÜÞrƒW·ˈ³u­ÇÊ÷x°ö®0Rbæjt~`ІÀ;ìéà6fpRq:±zá5¤\ oÿ Ì|à±_»ø7Oy4¢¤,qž9}“IsŒp”óëm~.Ï)èR¨Wˆ–È-‘ð²ŧ ý<…O:r—fE‚¥3,ä:ã ^‰)Á”ƒ3¥«Hw•EælDØÓËýǼ³»S ¬Ÿ,¹¬dŒÐCI_«×dÐÞ;ÒËÄe´ ›î‚™8¯ÈUä6“K»Ë-änÄÞZðÀq´¦¦h¥å¡ÙKºxÔwpØ[!ãÙÉ¢äð‰œµÐ莟&OÓÛZËÍ’þ:sV¼ã0ãVXŽlÆ´ßIðAðqš¿¸ÉŸÁ7tâmc‘ÚªQ“n _/lÚpl"ŠyÊͼ¡ƒãeÃR’Jãm-ñ6JzªaA ƒ|šõ¼®Íï*ÿºNâ\Ç||{:¿Ìßü£èg EwÕU'Qi<<ò¾šé ]nB;6O`Ñî]d Ø¢DÈЙy°‰vÕUõ—Qv^c`°Â{€Á:gXª%ü}¡õýµÞxiÝùÒù¦z>œ˜e0¼ ´kD†ãj@){H· @[W°ÙÁ/ÈcžÜ(x2R©øDÐ包z¡É؉ê)‹®e†hº| -º¶àQ»êÆdQ…¨€.Ú[½øZYSÊ—ƒº€í±Å„Àb8ç‡åîU\ívºˆŽ‘c&ô¼­uvÁ¶˜0¸Öæqª%¬%®Ò‹ªi¿Å!²_í,“ô%Xx÷eî àëFÆÍ«÷rú&€þ[û"Êö'±—@"›9ÔYö­ïC¦ª—dK°±Ù}±‚ƒI9´H+“ÎúóÖ*_Ôæ†èô­§úc‘šïyaâÛ¤œ[–¯¤=’¡.µDE4&÷QÝá+–õ”áÚTyfÄÙ‹²Ä™»‰ï^—þ®2Ÿ§ÆHÍã.×Ô)nÅ&.©Ã—mçÓO’?²! ÿ—¥g ]¿U(àt…§eòó<¸?¹BqÄudS/î^ã4”m‹$dÛÑjI¢uOpÅäJ¯Ê·lÀ¶læ{vXÑË dÙ¯Ëägy4~9E>öš0‹ djÈ|º¿r%»ÜwŠ*À ÀKc?ˆ¢-_ãâd*¡ÔÖ=º4MË8©m_k&vHU pÞg]Š+p¢MÛ÷ ®x4(¢ (ØMËÉWd`9ãÏÆ-Wl/yœ­ÚŒêÐ9f‹EämG:0yø}¼UжXE7Àó ûE¶/ŸûÒ²Ý_¦ºÄ)f ªGÁVYZI_jiÔÜ á2½ú“>¾Oõ×vÒGü’ÛÒ±)v7‚”â¦in3% Ëý”aç†í„¨ÏEjÅFïq·&gi1fëd½Éd Hñc 0H!×ÔЪ]'ˤ{¥?¦Ûž>FvÛ”Ý^²»]ò4<ËYr1¤ëò LILY¤¬ÿj»Ç*Žá(PŒ/ ŒàÍ5GÌc´×V×l¹â6ºáV 7òÀàÔõê+bŒãj…t««Š¯Œ8ð ÷IÅ ‘ïÝ & Îlè8ÍDsNÂò©ŒÓüZ×»c÷aw›îCm¸îCðøbä¨È=Ñ¢5HîªMí:ŸÇÐÛjëßø¼ †›ð¼J¥+Û­­ò]‘1¤ö¿jõqíÜÝü¸ä¿WMœfž ö &¶BN½4èû1%,Tú1ïegWGÚåBµ6tçaºm«Dø„ËU΋tp¡ÿxk.«E#»a£åM ï“h ÝTmiqXiH1Èa:5Á>)ÙMË0×`5Ýü‘¦V …ùÃ;ăzÏ/V‹íFz<®4ìæq–Œ~py[ݳX˯èIÞÓI\ ãîƒòñyÎ…±uß Ãi Ña<ù)ÍMêìMƒ Ô¸upÔŒýû•Á3*çu#Žå}o—®f"Å~ ÖÑ«Á l_æíh0Gš|ÀˆQLhœÁÂáâ–Eš¬ri2g–©ü;öM†ø×BîöñGÈ <~šÞ«ñ^ó8`ü(yʳ"XDVê/aÉÔÆ$ÅšÆ_p!㤃ˆöà ô~ ­e²šô&€©S|9Šò¶F_ÛÓ×Gƽ`¸çȳìès=Eºhª†_É)ÏqkÀ7yhü:½šërõ¡ÕiM¨(uí] A žàR:LÄmÜ,îì—¡ö$½£D«4òcΆÕ|­(¾]¾F%,–Ÿ —­#8n3VÉ2”Þ»Š> stream xœ½\kGý¾øG,A"÷¢ÜÉô»'$¢Ød‚0)Fh½ï’Ø»~`cóë©êgUOÏÌ]‡@d¼ÛÓÓêzœ:]ã—§ã NGü/ý}ñüäÓGîôêõÉxú{øsuòòD„§é¯‹ç§_œA'á¡e˜ÆIœž==‰o‹So}j¤>={~òíîb¯­…”»ó½ÙÝìZaƒÙ=Ù”´‘v÷´J=kwÿÜËÁ9§ §tƒÑ£Úýk¯ï­Ð/ucÕß^ÁûZJúÝ-<À_•”Š?Âz’¤;.äNi)U^—§z2»Ë´D5Íß–Jï^Ԯ鹖<½?ˆÁgéKq7vÒ°˜Ø B¦}9¥v×uÈ, ãñ¹ùÂàÿÞËi£Q°=XœÙ½Ý=À >í%Éì ‡¬G«F0ÎAAÏitJÙÇyˆÜh¾QÄí^¹F˜vïö?ûã‰ý`5œýÙ%œv9¾çûƒ¬uV§¶Éè¸#?f÷Ol¤räqžÛrÝÀŒ‚ôK‡å„=q)XOâ4ãT_‰Ga%´už–ƒ¶äipg¸ÙCÚíA(èä㦣X½]-ûOJë•4Qîh'Œ?íæZ @IŒ‘T^ÄEiЪÌÕ¾Êè÷Z5À§—iJ%È”·T{¸=¥ãnŒã¢¨UU°O`d ú #3m$+¿Å.n…ÉƵøe{G»¨sT{Çß`}ÊØA™lî°Ö`ý]ƒe‹ú,ý€§ùé#91&ô`O OÒ"ž-.uGÎ4Í[17¾ªw¥õm¯ë³òÓ›úø»ÒøÚ(J#ˆVû(··¥ñ¼ö<~LÉÆœ<üŒ&“o{c’¿êÍ^esÑ{çñ>·Faó€q˜Ü`QÌ\ÞƒcsΚ›CÖ̬9:J~œ&µûj/w_߇0yü?ÔIÐ'tïYE´ÔGr§Ÿ]Jœ ì^m¼éyÖËÚˆólà(× · ëºjÿklÁIӠѱ;ÜÛš?Ú3›®= 'ЦíÜ)¿•¢?»{ !κÝо=üOí΢”Bïþš]›$^Eñ$† 1GÎáâYñéÅ+£$ÁËÉQ“÷¯éñé•wÞí#žµ›lŽZÒ‰yxæ!ø§[n‰{²9b†Õ>Ïæ?ÅàëÒ>@)8TÝMš¡Ô¢f`;E;m}@EÔc4¸¾ ì«ÕzmUhŸk¸mÏÍ`èÕ(· K (š“ÿcÊhð(³ÉK fƒ»Æ¶hfaÄ™¢òUû©Ûk_æ,? HqàœÆ F=–ƒ/°ç%QÀ7U«ÊôTñ2% ê)zM­½’ÀƒóÕÞ=áÈoªŒ«ú ÍÌt:¯ ,ÌŒ°-EÖ2”Îi®Öq«óØQÆÝÎ*îy´WràÚƒFÞÇ‚XcÈÂÌûJRö¯¢lçÞû£ªä3óYѺîQK|ô^õñm´®,û¬Ââ´7ÁŠÆ1=ánŒ¤´ÇUfƒU{úRc'à[ ,,©  ²§^€¤=…äÔçñß: Ñ‹é@Ú™®o¡­ D º  []&Ú‚J•MÌÚFñžýRa w£pÔÑâˆ)PÂC¶~~ôɆõpL¨e×Ó¾hŸJ"ÚìÞa~mz©_ÆÈ×\­ˆ#%Q¿eÿèÌ:Ú„TÍŠÁˆ© ChÆP_`õum|Xváç»òB°Ô—P,øáÉÙ¯¾Ý}‰“ݯC<(ï}U¿îMVWÀ§ÍÏ?)ïǃ`obš¢@Üä¢@ˆ¹®gC#äOIïõäZ“TÎ;êEð¹sƒÒ²Ï TyS§#=ÉgËИbÀ¨ìÍÑÌAu2ŒN¢•S“›h⨎ÇA˜éò)þqÛ¶C¨ 1òöbÐO“sÑ^qJ’ýå1FÊÃNƒÈÀ2tpû4ï^„Ð<& ëõ‚¬§hóº†5âVªkâ!±„»Ž£ÃÁ`+;nætpc÷ªbÌPM«> lBȵÎgnÂ;ÆÈöµ´DêÆ€,ç óá¹C=膪hQ/Ž¸Ö·Ì¸iŒæYå6Õ¡õ®ÄU^õ¯1g•Dm²aN;¡úiNw[‡Ý$ú ÓЬvhÒ˜ ¸;—’(ô£ðXZc…Ì`Fás R…ýâó㧆CŒnÏ·TÃG¶Äµ¹Ÿ"c¢%,cÆC5”šsîb¤gÌ­cgBGŸtw¯ÏŠz]%‘$4Ë©jÊ§Rà:‘–{¿÷»W¨M1ŠA“/ö¸Na,ß°ö°aK#.#IÊ;½û!f ñ n W2cÌC¶˜„[LÈÚ#cót?e³ ýfò¤ËWwbÅà1ÑŸ·dD:fLºfŒ±FÀnÞ/Êì­Wð< †goÆXT2çGzGMŽ¡Ñ&ó^@2I:=´&½œÌ~â¬à›ßü¹4>ªbt™ç‚nðóúã/j‡oXk@ º—–ÐT°)Ï©ñLä´DÍ] jHžÞadˆ‚4‰!@0gGs¶ñ]{ªc]£ÑXÝ8J À€*|<}‰þ_/ù®dÛæH$œaOÛˆÖ4h(ú +4÷©üõÈæ‘2ƒ>ú^F"ãeÔÌ-ã€õµkî„d„óöë"ëØl‰8ƆÁ“—8`YÆšþåÄ´K’®eC1ìà_ÇŠà JJ=W>š$ŸÁ¹B\FÞŒÏǯ.jãØË_ÞÑžk½ºu'ï6²ÑѱB²Äç!NÓ<´ÃÀГé_€èlÀ/j¦F×»>¤è#ä?‡Òø[h„HäÉŸlœÇ¶Àý¶׿i2g”ã5J #Œ‚"S¬v ^g>ÖƒÞürn»êøM3‘® ÷x}Û°Ò¸‘àûqèÐx…0E¦J‰È6§xå­«ÒŸ&Êä999ß2J Ãár-;X-›$jyÑF£I=V’¢µfå~̧Š"¾ A¢m¹HÈ[6Å6²G&¥;+¼ŽhÀéJT¼ñ)w§€Jh`̃ý$¢˜Z4«Ìús¾gC¾è.É%f€Þ¿(­ó¾H-QjYTÍ=$¹¡$Bt©$AÃooÍ$kÖ)°§ ¬*®†¿&w¶ùð8÷L$/vkeC¦¿âݯRdñšu¦¢ƒ¸î‚qÏÓöé-k M"Èm!Ò[nBËl¹HBYªi”‚ ØÍ>­dMº”Æ:ÑÄs²"NO´•°©L¦Ø@öu}ñ%¹è™~Æc #¹¼:tR ‰¦vj**í¹òô~àMÔ‡• e|x—‚ŠÿO„øÍz„Ø"ž7ÂFïLÐÿH×Ož×#º®k÷C?áÈKß­ïAlìa»±»‡£¢§l5S“R\¿v¡Äaë~w©"ÒÀ¤¸#e[[ ùVu9=M9Ô*LºÕóÒÙ—s¼Òa«èe;‚öe²AUÉæ,0É@"=:Qês©Ã~YÖ9ÏžsüZ¨—¯ô?­Cȳq Ø@(,XÿVhþé@,oýú>ª¢ —jGBü¬N¦;º 4&–p¯}êÇ+p(ŠÊ—þeôÑn ðœ×jÇ¥ª¶Æ›”È »UL'ø¿±œHÔÑ;<ÓŒ;‘?^ùËEœï\Ä¥“#oââíˆáœ_à2ÌKùÃd'&üç¦èÇÂ[*^\`ûg'ÿþ É endstream endobj 177 0 obj 4229 endobj 181 0 obj <> stream xœÅ\[“5’~ïåGôúa8‡q¥»ô0 c6˜µ{_xhÜÐ8h» 3ÌØ±~2S·”J:ç´iÇT×Qé’ÊË—é—óuç+þ“þÿüåÙÇOÝùÍßÏÖóÏáß›³_Î58Oÿ{þòüÏ—ÐHx³„5ˆóËÏâ×â\*³(ynX¤>¿|yöÍîÛÝþB-ë*Äî?÷r Á{»û±¼¼­/¯ÊË›úòïåå·ûý…þð»?•·ðd”€g»û¾¼õ{Q^®£—¬åÊ[Ƨï.ÿëL¨Å˜àÏ/¿<»ü¨YÏõÛÛòòª¾¼)/af ðìv€G¹ŽçºŽæzä¥hèC£ÝÑG®ô²ŽùæÆDú|üTxÎ 8àBêEˆÎ/¯þ¼×‹RÂØÝ‹½\œsj÷è"Hh£vÀ ­u0» ¡ÖBJ hjxµkdg£Õîyixµ7»WøC€†Öèm¤…Î.” ‹±–½®Ã¼Ž´ñiD©4v’¿îg„¿_cwð• ÔNÆ[` ±û×^†E®F±ÖeþÈ^.RªÝoµ[øZÀ·ÎÊJ’4'+èt¥Á?ÌŸÿ7EJ Ëý0)ìîn_–i’'ø+lŠ‘„uü‚ý¸À¨0””z÷¬N 6gM_ì‘Ôª Ú€v¾Y“);ètÚÁU” +ÐÖ7ÐÕÖw±uî´é%N D -^§¦ÒM[\—ÎpòJŠEÿ¢ÔÛUÆUÄϬsyðeßpQ ŒÖ™4ÒVB§vo÷ÞaC±{ 5þîst!SK\Û’zM’e¹dA;®‰Ì^Aó—áajºýS‡ #¡çÝçÐ'Ÿt4X@¶’ø¨Vbê``Å»Kx‚5•ï_îl+|C¼fp»/Å|Ð+J‹"$É‹ó¸wÐf+å Ï¿BW ´Ç?÷Ö-Aà ¯íƒ_M ¹pФó3Ô1*Xàv6Ûúx|öÝ+xôÞk‹,—t×HOR´w8Ró$aŠwã%ÎÌZgu~ôÎfT«$•Ãô×mUoy«JK’bz½Ìã·hó@ˆØõÓÚSÄ9´ƒ8Ë;•ØqU@y%#ïáœËìê몋%ªÏ•Ó@¡ÕWÏËSU“•)§­s·W.²â¿h{]d(%ˆ‹Ø[¶èÒÿsü\+Mz1Q€µ»*½óÅ"H€AЬ¡t¬Šìã`ÍnàþÀÔ°K£ '¥)ŒÎ Ó±[cMZˆ—0ÂOU½(_¥•HüU‚õYÛ•…[µF½Èú® «–Ž÷ªÕx™è YRÇbU-UQ‡^hÖ]7*„hÓZfföÁßsaÿH„®°Ï¸ ŸÃäÚg͸’Ä%‰_IB‘ÊJ2Ù0oÒ0_ Gû V—„•aÝî¡UL›œV}‹ÃÚEVû(@?6]66Ü‚- |çxƒÖ”çYå? ¨ t é÷\LÙ7²ØÂ/ŽKDNÖ"rò5çïÄŒT{5ø·K€pÂú¤—–o|Ô:Vrãüº5ßlVckMxZNkÃ?Ãrd&íÎ 6ü²rù34Α&Ó¶8Ê÷õŽÒm-//ëËOË˯ÊÓ—õçG|H"Õñ!¿ª/¿nÊ©ÆïÛ¡2¾Ë{!è|0h$·ÔR‘[Lrêƒ èŸHEbKÊBN¬5¨‰YGC+¯íq‡—E¿#(E½±D‹iáà?³RN/jÝâ­»:C^)^©‚óüÛnÀ«6Å1Rñ†P€‰;F Ø %þV,Ø]‡=¢jÜØ ¤ 2º£ks£bŽí—’e¬‰áž~lœ~ í(à6ÜÁ.”ÈtÅD½ŒyeæÊ=ͪBÜVw0s§“ÇÞ:¼™c`QÃÇU¶HæYE1—{´wïÀSP–ëë¡ÿgUg³_Hüc¾øëh^Ñkoó_‚~È¿èOQJÜ÷œÅ ï_!3ý¬ë»pôð#&N˜•^#{?AfÔàmû¾rIgˆbþCyøˆŠ0Þ„‚ŒÅÀuË}l=‡¼€:*Ü¥¨<&:·‘Ÿü½V-d¯–Bsi= …­bä ¶b³óL+ÔˆÍ[$›"®ËÒc|A[Ž 69Ä&ÕžÒÜ )bOK¥OÑÚ[БÁªJpùD¯²j_æ•–/в‹X}À¦½Ôøù ¬4,_aU+8¢°OÝV­ˆ˜Éêȉ Ý0âž.vý3¶ö$Ì5FÄÿ¢±& *›{¥SÓ´Fa¨¦°×%ÕØ†ä%¦h/05œßJFVNo£§y³§V!%Y™žeÌßÄó‹?ùÀ±›ìÏÅ]õ AËSf%)«d§ø™ûº±Ü€x¢jÂ}ÿh¿MLÒ¼bêˇÛT‘nm4Ÿ4ž¶~Xq‡±–±2S\,Ìß$«;Zs¯ÐSkåÈk ÝÀcùÔUéë‰dlV¢ùðÛínÎ2m·´±Òìªh³sU‘Œ‘4Ɇ"ãŸ@¥"µå E¼ÀkŒ:wš}ɽA8î£øº1”Šü­TÅ¿rË€®Ä&h:ºÿòYeUý ÌÎ{ã`¸ ”hG…™jÄ„IH¡NZxëÐÞ'š¹—}3T\Ò b©Vïo»Q¦åN©¾Ž dic÷šbÆÞD¬  ÒÑW-‡½/ÎËûV¿Jóau¾[yG”v‚¼ÛëÌN÷»$ `)x>Ô:ŒC%#87´"C°xÓ"±FMd—a†ÏÇåƒÆEÒœ¤÷‰ðj#_§ï\ÀK¥Ö5eÄ"MZãÀ§¡,54‹UæªTZôà ±öê¡Ò|.Üâû@–¼º†·ýJü>åíTÎÕðFm¢ðy =‘Ï)]àû@ s‡Y@ô~(Ìð`+óg9_7jW IˆáyÏ.y–GxQòUS„þœÄû~8é|$dÄ´ÄÆÇ¦ìõД4¹ªÌËY‹NC¨u>“Ô£ò¯¾)ßTn"¯2/u“®Âßo’ûRâ`['ê(`¶×#ã’©.§Ëî“ ˆôhEàÞÁ v)qÅs³†úü0ê¡Q~y”3Î5”ëJÙ—ã…é°ÃòQ'ß´øãJ׊ødÕƒ|4زRN’¦|Ú@µD…–4ݣů<2, Ñë²úUtTKÓ¦â¬V¼OƒÉT;ªÆ‘_¦ÑQêÚ,›=œjÉÅæ'¦ZªÏC؇E^3ŽC¯%QÏ4,ÏoKG>J:4;ٗ¨ÊÃŬ¹KŸ¯{” Ót‹=ó±ŠÀ2,¥B~|ˆï¯ð¹µ–÷$®T³óëw3{Âù\W9¥›«Ñù¹ƒA íL‹õÎÂt#÷­?æXR,qå³óí¬À5f\—ל¥© O4Nò$³>ÎmXöï._ÑN³ÃYóHsÀ´çA–\QþóÀÇ…¬ÑSf2Ò@j¼ëåïq hRµi›éá±Ê,Öˆ´ +2Á&¬f/¾Ô¹P‰:Çc¸È˜g~C¹(*]Œˆ(λuÚצâ5•›Ž8²‡ÜuõÀ:÷‡R-oçÌä¦GO¹ÕbqþïàÍ?Š1Þàíè#EŶïÞåïÂ!9­ù¹¿ÁIåŒ4ÆÈ|oÃÓLbð-­)aù0a|‹·q$fÅ`y¹î„Œ~2l-¤¿eì™nà„Hg8#NÙÇC4ÄH¡zªÀ­Átný¶=”<Œ4$QŠG0œÊO+oõô¼dVÒ¯ÝTFF±Ú‘Í,2;4¼¢8Î(ç›sL¬pB¾c̶ïN‘Zaºª¼w”¯@/5!&¬çRƒJ£©qOÛõ±^2,BV_´§ ’RLöGù,˜y½tÒšßÓë̓ØuIÝ&‘-GÒÏq-ÇnC$tâB5nSÁÛ(—Û²‰“¢\YŽã+¨¤‡ñ•6Q±)Ïu’H)=«ªk C>–yìL;[S”‰ ñP|,æ“¶Åîˆ';׃n§zò%Uw‘ź:ªß{ŠÊZkVÆ—‰4ˆ¥7çøIç ¦b ¶àÞa=uEAþ,ç'A¬’¢ˆcñw¼’“òïAÙì,zœt6`›¯hê22Ôf÷ å³¥{ì:<ŽŠM‰û; [±Aj$)«ApÓ äêûhÈÿÅ‘1L«xZ;žºIû ÒgÝ៟!"ÁÐiÂr~Ò(r·t›Hìuc°hq¶½~fÊJ¹ðZÇc¼*Ög‹áEǼ1ZŠmé?MV;;|ŒÓÇÈ{Ê€0zÜÕg‹¬åÙÌF _¢çoYrzæPSÀê*¡Ú099(ÑiÄ$‚/‹åèzÔn|œéðûï(”Â↑ì¡å)ß”§4Ï0ä>º‚bx Ѭ§2NÆHé¹U»κàN»N×ûážÑiHÛXÙ]mìþ5vÑZlà‚vñ’CMžÑSXøƒtb½ªífß\.À> stream xœ½]Y“·‘~gèGLðEݱœRá,`ß´kï®÷aeKtÈ ÛC…xŒ$Ò"ýë7gHTwóp0HöTW¡päñå— ÌÏWë"®Vü“þüòÞWßnWÏ~½·^ý7ü}vïç{"Üp•þ{üòê?ÂMÒÕů^\=|z/>-®„´‹vWÖˆE꫇/ïýõðËñZžà?ÏðŸ§ðϲ®B~Ä_à?oÊ-áæ¿Ž×Ú;¼ëp¿\}R„väâ½s¶m-_|Q.Ög^Õ¯oÊÅ—õb½ިݶ¬Âþz¼6 éÕá|”ëá/´éüì»rñ®^ü¥\ÄGWŸ·Ã—zG?þíXnþûÃÿŽÊÀµ^—Õ­âêZÊeÝüvõðÖÿ7ì×æÄªÏ¡­Ekí Œ_Ã'!%ŽT/Ji/Ã"¬j1F’ïoކ¡¶Ec° ¥ èúýcX!%·EJ•˶mqv„ó}˽0¬ºµn³¡mòþŸŽ×+´%í¶áÄ(¹B_ÌœÁ¥É-½9ªÅ¹M)¹ôJ¼ãU½›}‘z¶zúl÷Bü1ug³:õQ*MÞQ¯¥ç6a±sº¶YyXઊ3ð0Ìôæ½hg:L¤™êÜì3èC?%á[å_Ôf^ä[žqñ¥ßo<(}Xänð͘Òëuz‹‡Oyr-TìèüÏa„Wòð6¶» Gžæž¹Å×(ìBèÀ«úùæåH eÒ.™K´CÂ,Öì|t r²¾‡}Ç} M»Ê8ü*\éÅ8ÛËÅ8wNË0¿é…nÓä¹Û$ׯ×ÅÈ ¡Mš’(™oë\csQT¬¤5ò ”í`:M’ª‰vµ'僬å ²äý5œÖgI Á}ùW*Œ°o±ŒÆ}¨Ú¦ï–(æÎ¡#KRþ± †Â›5 [ Ã{Qî!ƒàtæ†4vðë£<|›‘›8üg\e ÿø¨aÐFáG .Õy™&ñ^0ÒRç«H?Η–òn„-vs`ÖEM|Ñóª2µŸI6ËC‡ƒ¤É j`¼‹st[Õ š^â2_qè#›.kÕ6ˆë`8ðVÖ3BõGxÕ§ªIg˜4èѦ‰z=Ù[ØFGs™aÍ&Ü 73['n4ÝÙ@+”Ê-kŽÒæV³–†4öÜØMôߪA.½¬Î{¨ð£èô*B¿ÓÏLGU‘· LJÝWÆÂඃ„;.˜V‰ëÜkµA†!’ ê"ûîNpódn†E¬çIÏ&4ƒC<ϸ‡›lcOƒÝµÁµÂ<®«9¼'8厙þ*‡³-Þ£eYƒe©3Ap:Ø5·„n#˜¥‹D$w]àYtd–IXå 2ånvÕ’¡v4ìàÜÏçóoÐòxŒ÷p¤ï#¢ ¯ÓG ¥ XÓ ðmëÆûjÝ© †±êˆ*pMÕÆðGVlá?ˆõý îú#¶^ñ›#ôtsðéû("ä/y4Ç·~¬ ÞIä·Þù¨Š:AìÀD¹ÜðÖ Þ×îÈŽcowÓçÔŒ'‹©ÿ¨ê÷u dájàß•\„°>C.<àl²>ÀÆ`Uµth Ô}2k`ˆ»>!Jv`ç'ˆ?®o«ámfRi0ö£Zf«™¢û69 Ã;ÓîÆãd§gaÒjˆö»35ä.¡»ØUdÁǶQ!ÍADɈf¯‡K .ç\k´p–JglÂ6ˆ(õGZd4ˆ·ÄN¡üìˆ ÷¾¾IŽð¦éœðÎß’ÅO5€=IÀ%Ž¿µñDìÈ‚`o8W†6$`ÏoDò‚º½Õ°ýUšŽÀ212i\­u'ž!‰[ ëuW¾+†nD #OÈ11bÊ=.M 5ÏÇùØ pŒ0,é[œ`Løž£úÞ윉òk‹hjÏ1BA—©5 ”}zÇôîǶ›„Ê ›G¯©³œi¿õ!4y{«,ä¨S¬3‡æ°üð€LÆ©4¸X_YzBÈ?+ŸÖ‹?–‹/êÅ7L¦á—ú5&2jVaÌ °ï¬/"Œý«rq9»!òJ ãUޏ€ÞW—§$Ü‹k´š¹Ûw‘¯!P²Ñ¬wNí–‹³ Ún=b±hV”¦y,®r3Ãß‹ ºœJ"§\ 󤬖¨§¿6”–V“¾ÌröpÇ_B›V´~Ó¢èÔѨ—'~hŸhY¯¢C£oC]h9/©UXB¶Õ#qU|¶†Ð¾ïŒ=5,Œ¡Xb”\kãùË ò–¨7ºV °{Ú…î•áÊ™HwR" d†l€ñÒz„ë£Ûv E˜*³•×F$-™a ËS‹1vB¡ÉêÁ{üØcS\¦o¨ßÏF.,æ¼'ÁÈ©¤‡ïmé7Ñÿ vÅ̧‰*ÔŠÜY°níÊŒúTMNqU˜Ô ­²ã¥Ó(ÁJàrÌœ¢t¨ª Ë3sŠt{×)âƒKâAæ1J{1:86÷øª2Õ-LÄŽÂHQï(7ÉÓsx™gƒÚÌ]GœEžÛK±1€àv<§,`MnÆJ•Òª<„LÉ>gU #y 7],G¢<ì’‹Lß Ýy$]Fcµ…´G‘Ã>;`˜¨«OÑiò)hR64m®5>éFê‡køÀƒÜ`òa¦Z‘˜°Á31–†*Ú,Õ ³é²¢•ËK)T-¢øÃDo3ñŠNü±~ÿM¹ø]óP®|øáì‡öÎ5ËZ™ð-Š¿óë¶fY›c O¤kyvì “œ_yEïlGˆª±UÈr©œìÉ Às*ƒ•îc8&)&>{°:˜A$ÑÈÖs|Ù@È US À”0Ìæb…™:‡TÍÐ÷qÎ#ǨšF²Ï{i…{¬ývÖæ5Ý{‚C±Ò]ò3óñd¯IÃçàEÜ^6ÅøXj –,V3YéÚ"η½øärg·40:í]˜ O¨—4Õš¡5ê¤BÎK¸ÆvM¸2Ï]š‚¡ñC¨Ý¦EEdâj»ÍÄœ.n„ ~¬ª¶ðŸåß©1Ë´†³»‰„)<Ÿ$0ð^a}/ƒá¡ÑO`aÄéAû@;ó¡ÆW$åÎUòÞÕRGf Iö»R~\NBáÔ×ÑÊDO“ï òÐKòœv¥òN@¢ ÙN¶¼gÕf1¢Òh·óI’)™zB÷–rȉ‹Å½ Ù|ɛﴫŒŒk®!žúùŠSµ*¸jJ¢+ùÚm¦èkaþ’uÉ iCœûËÉO“yÖ„³iì{t7Âò¾‚d³94@0B[gzhý.äÀ±! ›ÖH¥e奣vÐ!yhÉqš’ÖI4Îß:RêÊàŒàíAâ­±Îh¿ä£„¢ìvP냎2Óxbñc„¤>®#ûUùûõÈ$ØþúöUùPTvÓ”zð¡>ƒÙD·f©m§˜gpH„‹a#(Cœo'¤S–¹m]„(>Ã9Ю j±ž&LÏØžbÈé^Ù˜fE%yî÷tG³£m»ãŠ«!úw&+ £tv o+LÏñ§p3§Žì‰›ZiÇ%܉D²û£n½8a;Úýfø@®Ð‰“•$™…7Ø7Ц ¤ñ=Oó*ïºØ»a²!#?G$I ŒÁÇ|øhABý‘qçä ¢KDö›‚8K“(ó©+‚Õ¿¤+~‚žÁ«•IÂÒözR}IþN7ÆŽè´Åi’n{!{Í¿>ú5.Cm*ù‘U ú€*gy\¹Æíù&´ßI)É Ã”˜+»…-)õÉwdÇbWWwÇdÔ]É)žÆ²,v°y`¢° Ê®I·˜hYÊžÒMœÕ§U{”a®ìóêIXm¢ÿñ¹˜Ìɱ¤ÎžnUl¬ñù‚"qbwSN:ø&'¢²¢×Ñóàê ¸ÉÀ_-ü]C*1yX5ö&ÁÕìàJ9ª0ŽßS`pb†Μá!QÜ-[ù’‘Ñ'Ýp«œé-þ%Æ9ìT ¶n´q+(ᯠŠI°±®àuaî‹ªÊžÎÆÕ%À°ÅÖéU3øƒ¹ˆÛÁ¯áǾÌYçjjª4­áõ. UÄz=׎EuÏÞnT4á¤F'ÉÀvHÈvñjÚ¥3Íîë¸kÞŸÜ Õ²%Ú¹ø|ÞÜ òÄæðŽ:™Y³ls•§ÒÙ!f´;*¤Ïw{ª“ß'ž+)…à6“j%Åͼȉ´¾"mg 3j´BJ#ÄÏtoßëc9OEê|±v8ýAïìçI£ü`(’&áS@‘íC²í{àöZeç‘pw„ *<6Ä65˜õbn;Ÿ†q.©ŸQ@’ôs˜키œbZÚƒ8|M4sO»ÍJ1äoE[[³ŠžIl¨–äòµUööù,øb·ÐjéE•”)eÇ}醄ÿ§kÿÚ dëÁ¯åb=¯ñMýz)É~KöˆÈzX"æ ¬ lyÝŽðU½S•‹’{Ñ¿qMӺ؟ì[ød­Ÿ<{‘îpÀCòüßQgÄEÍÛ&ô[fsð¼Ù.ýÆã­1d=Ÿž˜å1g·".²;;‘â~í–©‹G;:Ú‡×täŠÇ\åÑXø 7”%ç;(5šnwPb»C> nB˜E¾ õ{àÎ:Î1ž¹iÍ8A–1~Xæš`äsßS›¹ÆcxÊ{˜\g¨çõ^M63NZ‹ >ChW5½¤þË~ë€[·/u·€ß'Ù¦\9è#ùt¥°š—œLfÉÅž»¸!b(ch5ˆìÀR:qÇ¥ÍeC¡¢0ÖÎ`š‹ä¢È‰Œ¤€3×8оo°?1…Õìúõ.åœòþÆg«+µçÓìBfMjAñ·É°g!qˆ£H{m¦Š;n’ôÙ=žPÌÈ[!D س,ž‘ØŒ³2c>˜$ÊÀÇÕdH“ql’áÛçQ9¬GOMìCªBÜ\0M²nDl1øÔp§LÇYE´ùL…“'ÅäòñSoý2Ù¬ £+a×ì,ŽñCòò¡f¼Û‡×¦ ™H1MàÙñNä•:UèÅÉ*[ ,šêtp®6äž'¼qeôfXIu;ñ2ÍB°n  ¤¹¦ íT,pÓÀ«÷à °;'(6]1…Íîöã1cím&†ª—B©ß9iLÙ6X™"é¶1¯©ç™ÁØëxBÆ£?JIðÕ¸I<ƒ,Ýd_©GUàRŒDSÚ‚+ô¿¶?d~޳qíÞ´®Ø¢¤iu8<=–®Z LhŽÉá$¤½ûQ‡ºDÅGžñœy_~ÙÎe:x?4õàC!ˆ‰ Ê%ÅóEdj%VÛ –Lg·gú’aÝúNšxuî„]&]¨¨u²{¹>M*(XM`Ê«›­ÅêÜAÎã`lùKâ.¶ápÒ O]veÛÕËž›Ä}ÞÀ¬vÕ°üžO?" wöÉ=c ix9îC:PÔ<)%¤N¼l°Ì~V©p GK¡‘÷6F0lzÄSØâ)^·ÂÉ‘ì„sˡ¸S0/ž‚·´çªh8›®Eã—ä¿Ý¼3±³'_™ncÊ'Øx} 1üƒ %›*e7v½E ?1T3Ý—JúÙ¿]uÞ¶†4ÙMð4¦+°£ ¹¤=cs°åËŽ•Hå%ù6´4é÷pœrà”¾†ÜÀéme¡Î®]Þ6Ìì‰öyç Ñîö‰ötOííô(hÈ)Ü£Žf'é$ó˜«Ï™zUœ*¥[ë[ý¡]’QPb£ôËÉM¿R C»ücêT‚.*—Ö*(2$rÀ´³Å§Šë®ž;bÎÕ¤u5<ÅBN·mâ·x®,¦ß5“"¼3šç¯oÖ!L‹Ó®¤—à½ÙÏ`"pRǰgý©4#74NÞ­Ïä;hK‰É„ èƒàß —~VtÉ”5‹ÜÕU˜äš•å_C÷ÈÅÞK†å*ivœ‚Ö°eáÒ¼eÅiVÙ—eûôÉŸ³x!kHzàÒ£JG¼žwyä´™k߃ sÐÙ×2ÇEBº„ÜùÁÄ„ìÅCÆá\µXÔ0üÊ(vμÆ}‡Ímñ_Ξu9Köh$¨´Ò!¤]ïøÍí]ã>"ØÃ•Ä‘ŠuTxÇïÞûüùÓ\Mendstream endobj 187 0 obj 6078 endobj 191 0 obj <> stream xœÕ\mo·þ®æGÐÜÒ†¯K®“uÒ¤E ©"4)’|-Yv{’ü"ù¥èï _‡ÜÙ;)±AΧÝ%—œyfæásÏ÷Å ÷þ—þ}t±÷ñ‘Û?¹'öÿÿŸï=ß“áýôÏ£‹ýÏŽá!5Á•a“Ü?~¼[Ë}©ÆÁøýÑÊA™ý㋽V߬õê ?žâÇ%| BH¹º^'å äêÇÕúÐjènÒ«ïËr}¨à’÷ãêîË)Üÿ'½o•€öfõãz}èüè±³OˇØ+¼@Œ«¯ËÅËÚëYíõY¹ÿ´ÞS.žÕ‹h$<ü¡V/ëÕçõëMüj´_Ô«/Ú׊ :¶ÝÕüõ¼ö@FsU¿Ö9ütü·=©k'¿üÕÞñ½V_5²oSzúEbfî×öª½/&ÒVU  Šô8ZxôWTÑëz•´:­>K îÝ(5P!¿Á·eŒçåªf´ö7Ó Óv(÷‡z¨÷QR˜e;âtñ’Ú{€=˜ëI¹ø‚UõSNºØÑcXsýà³/šÁ˜É “· À ¯x2SëQ2'½z„×e'ÅØÎ‹Òq„vúíÌŽiû #£Ñÿ,`õ°´&ؾálò”N¼SCg&gsÙÃm³#ìá%«œÓY¿zϸg“‡4F¨ì!?+fîúÑ-kéÑ-ñ÷¿+÷Ol¥‹O:Õ¡«2«¿R7‘ï?¡æÃ4êt*­ öQ§¯9—ÉŽã)UtŽN×Í8z;õÓ{ _.á+˜Õ…e²²Ó]ÎóÿLkñÙìf>/x‘}Mì+û#½~×s?Š€™æA‘zø¸iGƒÿÔQÃIÒŃNŽÖ[]×u ñóù}Q<ö&Ë=¶z–§\þ{ß›™+¯÷ÞÞÊ•ßaJ×Å´Z­V…ƇÑ_{ôŒö×Ôj/Šh/;½ÝÑh s™AP¹}ó·\ól#1î ¢òë%É:¢EpÖó·K|ä*9÷á(”û у÷wóF'Té¼~|$=]fxÊ ¹Ü*EôSXb†0ç¼=/Þ1“Éø&• ¢´6°@qYG¡TôQ„¢`ºùñƒµœs( z9 mR‚0=€î®µ¨¢ÜY3„CíEx[íUŒ$Ú ±tp§µeyÅe½v²¶é5N'¯4 ÖØÐÍc|•ŒÈ3ÝPðqØ•„/nTô섌žd’žÒfõíh;Ú4¼[Ÿ»\+úd¾K¦ù |fPÚeà£ß¯%ÃL«##°SCUxP@ Ç}µN ªñrʇy¤—99ÒyÇa¡{MÓvÒÓûqRB.h{KR.ƒ`²&«{«*ÂלåQr~ɹ¢+àÞFë¥1Åv8åÃ8çÃÂ’pêIƒÞ™% zª@e §È]ºó5µò’OP :h Ü¢ü$œ~S J©Ñ¹þ»²ø8UF²> H;Ž‹ö‹¦ŸRòøGЉžÂ`_­­àšïRÌ ÕqSûG A4X:Ql}ZõSU®Ý¼¥ËHQÖ Ú(: :Ê‹ Ù2‚t \"zD‹ù,ÐÞ¿"Þ4ÂËŒøÎ]| r=—A¥M˜GR”vÓØ4u=uÊ(mndÅ]Œ‡®šŽâw9iU”¯,cŠQûö6°OSÀ³§'#²VÀnò´ä*ð…6éÌM9‡M¨ô®Š©"Oš¿x`H›ä`F1²`ÝÝÙ°xLZ5öˆ"ÊØâÞqúçQ¼˜œ ÓÌvÙM3a>O§WGh7²oû€ˆ-«û®®ººTåUp©t´ œ%Jò”ë÷¼7÷%œ1á08Ð ÐH;°Y¿úr ÂvÞ–©I ZI^w8ò§{šôVœÉ¨*ÞЃ³Î¤Cxú©Ì‹ÁC9ˆï#…ùU3œvpÕs\UÃX"ä“xZ_¿òI À~‘ÀwÄ,Afa#g4 Bfr!3/ô eæïÖ ­´œÎH –>²î†CxÅZË_¸öçq>@ÿZ'¼ H oƒ¦ï«Öf#¸BÔìç3ºiжLü(qÈpãã2 Æ`lœF‘ߪӰ7T²bp*[@ÃæLT{ÏøÒp4„˜†O-°£ÏjóZ "8ûEºFai=sêѵ„Ѱ"è¿e¥Jmˆ0NSœ;î á!™Y n~ß!UyÂpœs3–¾Ü‡ñ©1hwÑϧ— S¸ZëDò0d8!–­þ€ožBO'– ‘RK|Ÿ[Æ%ë 9÷»ÝåËL úXù"¹yG]ççq6*Úa勃øPŸ‰\E ^OÚOZr±ÖˆJ ‡ëŽxa,fX¦hó@lÕèÜÁ¦àW–Ÿ´ÖÝaš°º¬ÎÄ;â“"É3ŽvÄ%Ê¡Å?ÑÛŒ"Œ«û¾î9N{&ÄH OØÅwð´s^~½‹Î SÞqæ% C¨ÇÄlw®&Ö ¼cB¡¢½ÂÊµ×¬ÅØÞ³ÚphëµSê³ð"J¿Ý (/61û^ C™-Ï‹C×ãnŠ+" Òä¼5ƒxWÐ!è £#‘ÙArõã0 9÷õݪ\è ¤Ù„Á»~PzÉÜθ¼‹3À0†Ü(Šrüš–È…aYíÒ(€8ñ–Ç$\ƒxRÙ G³¥bå3%üß[Ûž_Ws!á¡èoÆR±Ã{eÔ‡š.B\ »£ïÖ:ˆÊWAŠzÓ§s·›•vËivk;UÉ•î€^ÐøSLÓê èÕZ‡k’§0Ã!óNùHåm:’,…é\&æœN 8˜ežP0Lžª#(wfí!Ç ‡”T’Â|F‡fIœ@ðFY7i:„™m`ûK™8`»@|ycÕŸ7ª)ŽDûG97d åçÙ•|'œ¥ÀlÌØä1>"vé¬îâMMµbg2JlÚf‰ƒ .Eí,•—1jÙÂÄäím€ºlÄ›ö=:­rÞõÖYž6úwxcÉF6RÑÎÃ’Uµ˜ÀÉBê¼e%õÆÕ2:Îæ;*Gp†'Âbõ¸{IuBh{ë’º±“ßå[róaþ-Æ_¯²gƒÒί@_èL`–MöSVPwדdâÂ:g"dNŠCbŠÁGkcÀàÑ,˜I±„”·õ­.SœÅ ‘$>ÿqØFâ~Îö =™P p˜ Âþ J©noyÆÜîE2 =úàjGoʪu*P¯¶]$vÃÆDJTr×·'*a¸ãÒ265̓6ñP‘ ¢\ê¦â¿YããrÄ6ÞÖ]Y½N}¾½Ç ú„ÊØ7Å}ßTbÍ2”„F3Þ§fÄç³á€±Ö-f·IÙàÿù±«~Q‰OÃçò¸¸¿%o¨íÕ-º´ î“3a6?NÀ±@;‚øìÔt©õ« B‘4IÚ-k/‡µƒŸóõ¼ðos\³FlD¼L#ÔjÕ0äGk‰süqP©–w0lЦ1B)mK€Ø>n›‘Œ™§rP¹FµŒ2ù$1u.&=7_" ŽŸØÒlû ²”ø‰rQ[¢Y·ûK^¼¼DH\Ò¢ ±6¯5Ä-¾Lá,f‰ª”`£vY ?x0„1¬d³³0:ˆgk”Â(¢ºdRÎÕëâòYÏd]ðèd\•Ö³"`qÙ ´d5u«û(q’yIƒU#iýŠ$æZLß4KÙGw‡8D²ŸÙø††%I¡‘@xM7ÈH°h“$ÿÒÀT+öl2‰R‰Š‚ÈÚU’p×.ôøÁW݆TÉHÍ—¿X®"±aaÕX¾­û'!a+&Ó æ”ßIL…âQ‘]Y¥9"ØýÞ™@›Ÿ RÓô„B“{Va:_rY›úTÆ•Üý©÷™\U:«„ÒÆ‹Î„€Lû%¬éá‚€Fòœ¨æ¦—yL}†u‘Œ@RcØÄâÐÞÓ·Jb·²7ÔŽ]Hëo¡o»¨ÉÀ·L´3æºë¹ ½”¤/%~Ȇ›"R'"ÀÖ}G¯gl5ºÆC \™;PÄEÂåÍ{šêÞ@ŸÊ‡lÀdaëC9ÅñTL*ƒ¿ÂÍ#Öå?ãÄMLHÆi¶qàƒ8T³\£IönìŽN¿-nWˆaHûÀφ±¬ðX§J´XnQ+C0°”Z­P/ø=þ ±`=x’T…Ëî\[UµxR$WµÛÒ'©ÈåâOpÁ¥‹P…›Ks¿X3µ4µ6„”ìÕŒGÍ“qÌŽÜßÔû›:ÜZÊVÈô9Y×},Ø«åãí²\tµ¹¥h—°8JhÏåLïí/84¿®³­åf7õþ‡ö3îõ¥üÙÐÊnÕÌ4—Õòu·¤Âz^%Fên3ÆÂ¼4¼-KWrU­tS—1ÔÀC€“à¡‚C«uüXM–*#ë¯LÄ‹¡¶ðIr}¯¡p³aö÷‚Æ XN9É‘¹Ô’°ð5»O+ªK“÷^³ËO.!«ZæáÕºaâ^ͼ\[C"È®Šm¢æ¹—;áPü’õ†3‚*4<È1ùà ^qSa›ŸUXÅãêXLŠÐù •–ä'>ÈTÊzçÌ„‰y|âk×›87äË.v–<ä“h/,463yAƒ× òbÂêY «;kýO–°—ûÝÌÞ–fOä…BÚõã×ÜLrÈÙpO6h¬.&ÿîÇÓ™Œãy¹Þˆ âç`>ËìH‚îŸø «‘Á&gº)nô¬<\˜%ÜxSù ôH™_=$ÎWS6¾µ*ø¼ZûNÈ“©<[‚òrD/·û)Š™k|ĉ ù «¹0ÙuŒ¿è÷9ÜvÏ-‰ϛƯe¯ñ˜õ¢›Æ‹v†¼_r£ßpód ÓÀ ù s‘+WƒòO.h?À uT¦†¯Y[lðÅñÞßá¿ÿË=­endstream endobj 192 0 obj 4479 endobj 196 0 obj <> stream xœ¥VKoÛ0 ¾ûW=ÉC­H–Òq‚ Ã†m©²27M‚åÕ$]ûó'ÊÖ«Ö’`EÆ¡(Šü>’òcL0 |ºßf ÆU5¯ŒõÎ ö kÃ^ôö€+«ô§o^å«é;<ŽÃ°ÉM°cö.PzýÙ¯ºv8Zå"„³ã~¡fåš:µú'8}áÚx%úê¶9Þü&’YÅq–ËRq;õp&[” ØâlEo¯å¶œ-K/Í“-éM–v8æg'öw[SÏ«ƒ‡¾®~èmüˆ:× 3z×A¿k õé`#â9@0?ë ßngõkûr?õòt ¾Ï<ð§“[‘2±î˜Ùõœ‡Æ‹F?ö_Dºúï²õ¿ dwº£qèŠõ‘èφàÀ: Ô%¯^Z‹½äcÊÝ×Ü g\^%±¼c2Ìó¶)YR ")À~XGßäç/Çùe endstream endobj 197 0 obj 767 endobj 201 0 obj <> stream xœÝ\iÇ‘ýÎå؀٥U—ò>°ò¯DÛ2¼¶VÛ\ÐvxhH›3C‘"%þñ‘gdVVu÷ˆv‚¤šìª¬<âxñ"²¾9c3?cøOúÿ“«;Ÿ|eÏ.ßÜag¿/ï|s‡‡ÎÒÿž\ýû9ÜÄÕç³×Zœ}'>ÍÏœ™Õ™Ñ|êìüêÎÞØ,½·Êíæ‰ÏR:ΡqϹ³Û}6íÙ¬¥eŽïnâ­BÚÝÕ$ÕÌ¥S»Ç“˜Õb÷"øº“0¥ð.´ Ë“ûxR®¾`Çœ¼íë:öe˜)}Y[Rœ{ /ˆÝ ©òÈ-7µßǸ곒,oÄ]ø‡†U×°¸éæ—øV7 è ÑÊÅ‚ ¬¼àºþLFZ~N '­'ƒ"7’õ‹C-1yö®~ }¼Í'¯–æa¿žP$„c ;”éü)¨ÏÝú¢2ß:Égý"*Y¢ Á2 —ü-¾ÚÎÌ{[c¬Qð ´yüþ£UL[¡…)’glè$IŸå._ ËÓ0½Viáð*Ž“ñ°…î4º4¸‹œ¨ÂóôàÔPw{•kÞôÝ$ü,˜–aõ‡Õ×´Wòþ›°}ž{xhÆ L‘ï‰8âî‘}µºYL­³ù.$ ïÎû @IÄ-,•–DÑoÂ[A¬$“øxÐÁu«´ŽÍvö.h‹d00‘•e¨Y?-ûù´ÊV•ÏAÏ#µñ²Š*1K¥ ¼‚…!1D Üç:‹öXe¿ sß¡0® ˆ*ÚhÁƒ@ƒŠ>É—^æüŠ iþA! qÖÜÆÀ çUn¤ÿ{â5Æ’‚¶~ 68-¨€ í%˜ÇÞñà0œUt³W,xÚØè4…§N“#T0Y¾ÆÉ3ÆQ£`ØÞƒz…Žojã“ÒxS_•ÆòÕÈQk63 (½té‡Qòp//'Ý ãNÖθº›öÅ‹™Öª¤Õ¹,²«µÛß:´K§‚ÖÚúàp£æ;Á©Yo,v0X¯™ñ¸Á0öÏjO¿žÐšXp'ÑÊzp‡IzCëŸjä†?Fã†,ê;è}©FÁW”†;5÷:“úgš‡µ´±±Þeù’68k†v3{Nnˆ™¿©Þ²Ù³Vu4ÈŒ}KÁ0bh-‰^¾­®˜Ìdìï .ª»=´÷rLÂAUí€d½}ÝûnŽ&‹ÝœšFÊ.={o2BFmGE9ëð›¢Ã¨âaFA¯qoP._—V¼ô-ߎ#Dß/Û~•¨(>òvdUæÚ¸mF¶€£Gп‡¹­ZpÓY‘@bezÛâÿìÁuˆâŸne÷÷‹ÞC÷zBž®2ê‰ð¨Å¦E z÷IÂ=NºƒïB`q‘ð#‡à¼>–ü55´¬ä»(‚ïñÊ«âñó€…LhþŒ¶qMOÂêØFa#Âw3D›ßÑ*‹p ë¢"øb²ÖÑSds[ŒE$ظ^ÎÕ§a6ñÙ®ÅïÞ7‡,Y†œ­Ç;Ó{·Âö.ÄAA\`:ŒpG&=í–帵¹¸‡×­Íˆ·_¤ŽF6Cîâž•›ßÕÖÆkjz–ãyTÒAæÆ›Òâ X;X©ó‘º*Ïjã¿•Æ£ÆÿÚÇÏkãë’qRW0pú|"ú^neõV6j|TïE¨1­-0¼¨µÈx©¤ëLr¾|1ºwd”AVAÕa£œ£2ÍÇþMóÒ;gˆ¨Õ7À$:ACÜ?jÝH%P’Àdé–¨YÀ pHºuwŸ€Ûy þFF¾*êÇ îCŸ&ŽË­|htgËœð/!VkŽ"ç`×!PhÍp/Y?òîvÎ<ºŒCˆÕWª´0QÀôÌ\±ËÕFâ9°\·ÄƶáŒÉ ·-›îá½ñ_|¸5ò™…!¹ZýhIU`ƒãì,5”7$Þ0nZ&Q»——ù>¾l2¸…¿L‚þùø“hŸj?÷RÍM'šWäÛGÖqLQŒâ‘å67ˆ#É8þÀœ$/sWÚï X=²Š[aìv'¬Ç¯Š41qÒ‡Õ‘¥º n>ˆ(DZrp!cìü,…Úýöêsä§!Xñ»?O$B—ÄǶé°|7 È¿4«ÔãÂëåiµ¼ÞÅÔ±Ú%ð8%°BUW¡bÊEŒ³lݦˆ¸Ò•ö¢E= ,FPÞ°[RqD°Ä0¦¸˜A°:â È[8<ÀË9¤1Çø Òþ—¡®/kã “\؆é¬-üò°6>3\UæxûÛn„ÉžŽÐ[>?®³xæoƵ2Ùý2΢B3“ü¡!Üê£ ­î…ûQª:ˆ™//ê½—ÍäË%8Ã{—à .WÀ™ŸÍisÎKUÛAæj.ªð£’·üŒJåó0ê,DÇÉŒPÔEâ QZ• #~ܨxÍÊl±ç×ë?£Ƥ&WaóeÌ*‚FØ)‘Äùc…%ÂHâ`¸$ܯ£¾èýÀ±³ÐÒªInéÔòV[€D¦@¬û¶d‘ [ø.ÖÖ½GÝØK‰âZ°‘à-‡FYŠ>þ® ñ‹e ü£l ÌE¼ôÎ åqª¿Ä‡T€#ƒҺ!<1ÐÞ Ë(àÄIrZ°hP\4ä sá=wÂáO"÷½’‘]A~7 ߬E,Âa®u…>'ŒFÃÅP­u¼™Gƒ^OÉl…m¼åìs÷TxB9«»DÀñe„ÒR!§SXda™Âº© ÐJµXJ ;2fÌX ’îFsàÐtpeIȋ鰲ÂoÅk³tŒ.>ñ?aª-Ì«ŽŽ^G—ÔǼ£¤Ñú$–˜J$hª yßÉÛdå·3MÃãŸ%(ÛqcnC—£eãp›: í¼†8“imkoÑp [Œ¥ð¢õ™`¡Ûëú3AÞë~QZ‘P/W„ï$˜ö²4¶|ãh$äñÍ‘ü,é ]FC¶u®_O=úî0ùÏÈk§&v!`?D;˜úÀœ+zƒùcH×T·^ ÕøƒÙƒ€x‘y'ĕڥ\QádùPô±ŠM¶™Ü\Ù6Ä4‹@f•6;ª²'{7¨Æh‹l•’mÖe)Iüx9ÒøïIg†%:’¬áG Ø52ëë.0Z˜VE.Êj6iX»6B_9Àa†º"âvž-ß=¨ vGÈüìÅr‡JƒHÅÃ@gHéÀû"NDen!ØïBMnLÈÂÚ¼›Àt‚¹¶èmƒ‰"~lU1etÛX<oŒæž×å_ÅõŒÍ¶S—œ6>šo[ I™Þ|d*8€D~ƒ/Ü+G™¹¶x%-ÃÁlK‚1y#ÝF€b„Í|qÈ™ñ6¸hkÛâvYnÉv¡Ä—¥ÓÊš»Ux¯??M±„¢ˆ«îñj(Þ,“fM5P-J1tœ[M¼oÌ•YžuS½Îw™z¢.ù&5vFëSªWsþ ä#ý'|o•“Œ4sãÎ|`ï jBÍ ©ÞŸ{ˆtUËSÿ¤åöþ¡vy sÅcP–ªË±D»Vˆ„žGáÎbÔI‘c‰µ×`B}ç6.¦FIò%OfŒøŠ¦Êh„ÃPµE#°AwE•Ê¢:ôZ‡[0µ#ùºGP苯ž7mHAŽ‹§ÉÙUD¦=Ò²ÃΉl]´A¬‰•ôî®–ô*JDM䮳¶Ç8áªÆ¡* +xJyEcî¡ÞbŠáVº×˜Õbvb‚"8;I‹7©ã!á÷{bxé ‚8Ë5Ÿ‘É»ÖO, .`Šû®o=Õ» %¸8.|ƒQ‹åeu>ŒáÈ<ÞöP±yѰ8gϘ-ZàA´ÿjøEäÄ{bÄŽýN@™_C¬å[Ÿnæø›ãžÝ“DeŠt¦­=^šæÞbÀñ™ì  Ý!¸Dúa¹Nù¤ò÷Ì).Cæú¢^Š…ÐÅHSîF”ôðtq'·Õ0?‹¯ÉÔ_#Šæ?¸‡@Êåä;ò”V¹ .Š£â·ïqUñ¬âî¿Ê¥ix?ÉüßÛ;Ûà.ß„ØG¯wp‹#£LË›)$lÙ’ËÂ_(¨Si‚Ä0h |yEG :ôiȦª1“ÝwIn‘Ø_VýƒÆCæFk ÃÚ,ÁÚšíŠ}}à„Í!b6Ù¹¡b÷ì) ?³ÂÄÅÁ(9ƒHlTäöj¶ æ4OŠ8·N‘©ø} º¹Œ~¡£¬ÄƒÌë]Œã>ÐʼnS~tñ&jwp;³.–™õ%ïqN)â;îLT’µÓΪ¤‡Þ÷Y•ÿ±÷êaX€¾(Y_•Æ_Õ;?/¿÷›!LNN솥Z$Ý—FrFöAiü¬\ݯ?ÿ¡öOê°>*­ÕFQÿu8’zd?…šI@Ñ?§¿æg>K ªHÀr E НŽ(Wѵ#ê«ÈbÐûzØ,éà˜ÈÓrë§õwN™|­×ÝÊ¡àñgÿS©áyÂ?Ö`™ÿ¨OìÄ8 ÜÙ2 E/Ô¸xž»Û ϗǼÚO-¤¢ø‹mŽ“6Xph쌟Ü;õ¨n$@ú#gädäÂeª<×W¸rÎ3Ëè±ÊÏc\ŒŸc:©’ßIJšx±rqü£æH‘¡p®Mö¬èÃM-\y>32þæSÜucÚ°ÕZ1+áUó°òl9¹’Ö{•QhÎ¥ˆÙu‘˃Iì>Îkƒ¶Ü%’J¦ò¦¥£ŸtHRŸ»‰Å É‹¡7à1`ØJþ§°~™¿¥[×~³+%ÙȈmG ¹Ö‚ û©¯ é5¯LýÖÙÓP¦ÖU$°Í/"fË_ƒô“ÔéãLAyš3ßÐ8T6„j!)¨@4D~+.â㚥§±¢H¤O»4'«èW£ ké‚b¨±]¤9´™ÉDÇb“Uì¤ã©˜á‡ÒH`«ŽO€Àö!ô]«U\Hw*_>&³†©MáŸv~SO´Øþúk:Uåå£ ÌT!s®Hª2HЦ‘¬WúThyT…;¶<˜…j³è§;ÜÔVâzD6RŸr(αr/Éñ¾—ÉŠñ†P½½qylÖJLDÀ˜8¤¸ G°H„aHD!Š%qnÁ>w4ÉbÆ…¸é?}ñ“}Þﶉ}ÁÇÁB¸ðùÜd9…Âøóýó;ÿ ÿüW£žÜendstream endobj 202 0 obj 5132 endobj 206 0 obj <> stream xœ¥VKo7 ¾/ú#æÖ™"#KÔ;@m‘¾P ˆ»‡ŽÛ»6?oçß—”F¢f;뢈ՒE‘?ÎûN ÕIúŸ¾/nW'§¾Û=®d÷~v«÷+• ºéëâ¶û~FQ"¢Œª[oWy·ê‚¦sV 0ÝúvuÖo‡Q÷7ôØ#ˆCpý#þR*Õ_æžôø<ŒVÆþkZo§MY•Í_ÒÏ“ú¸¦Ç=6ôx,«lü¼¨BQW»¥x¶Göá]nÚí^Ä>6‡7{vIme¾hVdõIpÀ…7ª1|dCv¾¯†b)ò›zྪÏX}ÕDQü°ìn8_ÿº‚„uXÒõ%qß„Svœ/¹~[O¾™åÌ8+ÈôMÏâ?yù"/ý_,}3ðú[^*6v,=ç%¢ÇDŒ#Æ6ŠÛ¶ ÕCS¦Yër_m)-'§*´°!(áL7‚FÇÓµ¦Ôø dB(jŒ“ä„÷>Á¬ÖRÚ j@ÿ4ŒR€ó ms¸ÎygþÅÇ»âãŠ|D,å<©M´|Äo¡ÓŒÆÓÞE ¼¨í!O†ŠmSEœÂºÂ]Òq<¦YÌ@ÔØ!=hƒxµÛß¼¯¹Eã­$ÀØ´‘o)%B¯õa„tW¼Áõ÷ÉÄ”/í£Kü€Ái Éß'%VV×tñE6é") è¼?4%ô¿SM©>®ÿƒ½~—šE" 4Ëš¶{¬ÿU6ô*LɉִùÞ¤`ÑÙ!#þ»æùÏô¯†Q¡ÆzÀ³¡„^¥Ÿ9\e|ÿC† (CŽÓtìF…Hpr¤ ñt_ à£djtjP¦Ý;àT1†ˆ2´KUdá}ÞÍè ‹!¡µ‰Ð~3ØgKëÍQ”–Ã¨Ä ÄØü…3=ÞÞa‚_¢%…±Z|ˆÉ*÷û|Ìa›[KmþÛjýÍ— ·uh}š¦¹KMÜ:ý´ôPÕfì9 m])VC6y¶d)—„/ëpSË{ ãÏÂhȺŽî29\•ÉOB¢od©Lºx6ìÍc°™àWÃÂàÝV!;ÚK<®œˆ*ÆÿÍã$bRë ª¦_îù¦ûHMÆí´h:ŠéŒâ1€=¤ò¨V&ñ¨Å~€Ûõ‰´Q"tAû°0dž æöy7$¶ˆm”›A'œ@Â;Ñã3ƒ‹d”½ÆÃç)>0)6‡Ÿo©5hXtU¿-Yy¹‰B5/7%WùR5„ Ók¤6VhP“bñE™(Ê4L~Ÿê›0‹_?¢ãp¾ÿ…¨5D­UAR5ѹF†F@9¤LéˆY½Ûôzq9q¹>×R5\ Ž6ŒJºœÃEcùµ?Ô<•Ô5±„œÛ,“¦¡î·œ„ç©;'Þú2Ñœœï>÷!Bw†#Dµ C3.½í¢Ô±jy‘ùN¢C àŸ>BÂÐÞ<½k ãà §äzÏÀ* XFû(îF Fx—·h4÷ƒ%ý«õê5þÿíùendstream endobj 207 0 obj 1157 endobj 211 0 obj <> stream xœÍ\YsÜ6~Wí˜GÎÖCÉGÙ²­K±FÞd“-—¬ÑUÖŒäÉŽòëÓ tƒlÎey¸"“@ãú¾¾Pþ4ÈR1ÈìŸæï³éÎo‹Áåb'¼‚ÿ/w>í'0hþ:›žAH¨P©T&Œ/vêÖbPšT Œi®ãéÎo‰Ž„È‹TÈäùPÀ_…QÉËáH¦¥0¹Lö‡YZh™IŒ]©1J&ÇÃQ}çªjrQªäL‘VZ%/†¶>+ªd>e©6¹’Æ? ]šä$²"/\)ŒšV¦òý ˜Ã=Ôk¥„NN‡2EY‰¦,W:y@Á…m®¡¹iVP¬n¡P¤²2É%Ï¡£Ì€Üæ¬òB(ý¿ñ¿-V% —VY%,V9À¦«r0>Øÿó·zÙE)2™\ G:UJUú‚µV©Ö"¹°#ØÒ†ÕÉ L²( ‰·CY&_°›k_1«û3™I.í*ª´*5¬`.M.`å:ù€c†íà% ©s, ª ““ž,HÀ=ê:%s„ò<ÍéZ¸ü2KxTP˜Ke ˆ¤ªrúh×î¨,S™çÝiØžíØøö€ã4$j ö,Œ$æeš P¸ ’¯'‹Š»ò£èÄ®£L•¬PPw­€‡G;¨Jó¬ͱšW25²KOÀ6^ÂL%S€’CŸ YѨCQ:ã µü' 9èYjGÍ`€29²Jé"`Vã0»¬q³E¹)DS«QÆXS$õj2A¥n…kHºî0 }+D™Œ`mRfYi×=ò  ö™åõúk&D^sK n†1Y­Mv,Ԩֵ㒡ª,”›.hM[µQo…¢?Z‡Ê[€¡O‡2³þ®°&#a:7±A9k2¾3NÇšúª,m_i–‰RRIŸT-r½ÿžeg5øXÈŽn±TÆ9 ©‹T™~‹µk3šö¹Žn5ö´p† 3“–JxC¸FO¦A©›—+Dá÷¡í¶J­Ds×`c<øÝH•¥6V—º‚¶cÛƒ_°¼ Y’?ó}£ðCÜa „)§û~­N÷ß–< î¢ÑË¢h¦o Uß¾ùÕhÞ #öí¿ÕWVc>µJ¡Yû釶vˆÚÅB †f²eiÂaEô(ù]ÇŠk?êóP:yá•àXu¿ŠÉÚïÿZkgNԽŮ;ñ1”ÀhÆ.Ãyf]‡%«rv@ˆ±Á9t&ä‡]Y*”¶TÐxâœ<(a‚n³véu¼NòЦ£¼€©d 0¹mè%ƒ:¢X´¥óAÖ[Ô„¸8 “9ߣ*ð„žÛwWmUÜÑY7¹¾2 ð->µäU•…å&H<`!°‘› R‡*ù)ÔŸcýi(œaá5Wxé í²ƒ5ÔYÐÈN%þQ·g*V ç„ÅŒ¼73ˆ$I!dM…—çê·)üûuÄZMÑ¢XO°P½*lj™Y°·îM îÑ>*YÆ]¶ê7­S .Hµ2Œ dD¦,µ‡aÞ¯±qŠÊ9³5(g.—8…sl4§’B7[#U¶\¾³à]ûÃÚla|7ïí«ÝÙ4O&M­*2§Ä¾g8”¨­×V±fvÇY1˜¼ÎJ‹'o°Dâ¶§}Sx‡…Ô£@ ´$9gZ^sž…xŽE3fY9 ÏqN8üU\Ñwù"ÿ8Eõ94Å﹜FÔ?Þ‡Þ ½±?~õµ-zjaË ÛR6Þ¦M”D¢î¹õ]s L(lDTò–#âœRê$ˆ¨¹—¼EL§¡žÀ†fðˆ=½ …û(9…Ç ù0»>òi0i³¯èø÷~¥Ñ¬‰¢ž-ãµkDÔÄÞÂÇW÷z ¿ñ¯É„ ™C®BrÏ8 Ñ6nXrg\£{Î ×çùеÇót…î­mÅÛCïÒ“·±ðn øgµÿn㯿1þØéœÃ?VYDÅ{Á§%¥ñ’“òŸñ¾–¸®÷ç·áÇ¡2Š…Ý ìGû—åŽð~u éz* Þ;®á©«ÙKˆãJb²ú"¨ô^>C¨è‰é}°ß"TL9.>GÚÚ€)ÑÆh¿à%Ï9VØäá'²)ÖuWcDíöb¿Ò£½J¬Ó.¿R{ç ˜»LÖ×Þ nxoú”Á÷©}ö¯3è —§‘ýßÜõ ‡'ÉÏÑŸ.Ë*7s7VÅÝ ŠI$“v&Ï<µð+èW—%!ÉûÙt•“ñ#B8áVĆœ‡Û5e «Û î@Më(oë„’ ¬éÜsÍçœd|ža©¼‰Ál®£qZ¼ö: Ã`$Î VîúxÍ‘×ç…3n•ÈÙz­\ÏûB‡ðl6pt¬2 <âqÔÆ¶Éõzœ·1Þ»ƒà™’˜Rî‡Ú7vwm ¾ê°!96žÐQrío¸Fh1K’MÞ€ÙÈ?§¤´ ~é7Éh˜Qo—ÆÞÓÑŒ†àHöG¬AæV‡8\wÁíK€â­V+›WË;«-|‡Òy„“H%IPÝNã(Èax= ÂÞèlÀK¶?oB£¬Ça0•Øê¸èëñYš±³)Wt°´tÌó6ü˜¸¯cø×É Ê_»ÛYpˆ`O×ÏY°{ÖHa䥭ۈÆÛ*O·G¼¢ª|žÞëANÚ‘ž“À¥¸2ùÅÅʆr„Ô5y” m”­:×rB£ ±"ï·ï8þ‘Ê ŽÊ?04ßn‡··Üµ ünUájóÃν@&¦ïbó9v©¾èå(GŽžnCËf%—ˆñ]W‡­ymOwBŠ8ât'‘Oh¥ Ê݈ҹ1²‹ Ë\™Å,9‚B®ÙT´BN8jøÝP‹Q~ÏæHÚÙ˰D†'ËþÜOAXZq&ÔgÙÍÓŸ\ÖÊvŸ2«ÒÀ‹&–yÊ5ºáV4‰Œ0¤¸ÕÃëSÌI݆úǘ¦W1C Ï⥠)dˆÕdTÿ3,¼âÌ uþ§mYÏ3"µ@sY•9?¥õ3f×¥‰\uGÁf¼/”܉*Ù¬øD#ÏtÕë35òµ¥þuOŸ‰÷dùæ” æˆd«”qý¸Öu1§s7É™ôNï8ØËn ³÷YôXÓ‘–pû”EGÉ…Où>p€M¸­ÜœSH‚ÍŠS–{4ª8/kvã¨Ï䜪ïÊ´« [n}ó¯cLìZ—ÆÖf*ìp«‹®Âº»©U7.+. >Ö¦òeùtøË <¥:ãºæì•¹²ßÜ.Ö¹1#Tk|vwÏfg¨Žw‘äÒÓéÕ_aùÂ8è"Eé†ýûŽ"ÀkÑ»îÇv$3b¼Éáùd£»'Þœ[<æ=Ž“ÿ6Ñ'„åêï’q`Ôa¿- |DSboïָʗøN—œ}.Í×É+]·;W÷•¶1©ñi“/‰%1¯•ÝJÜF€ú¹t7q–TÿbŒ~îì,~ ÊÒºloirߦàç+.Ìâ-坸anßùo©¯8%a0›W²÷ºë_£?¢#b¿‰ º=±gu Œ.¹‰<†Â/œ6Î#Õiiq ¯gá¡î uüéD~ žþØóÓÄÛ65dÿõ³÷Ø®Jô/¸zŒš³n§•â3ª-Õi]l¬­Ûãgïo#µð^ƒ·ßÛµ¡–ßjV÷YÝžST¼=±§6è³?l³Íëû͆%/F#Å:áÝlM;yÜÚçˆø¶÷o5eár”ìÎØÓÛ„ªoAèŠkÕøWÆ–#c|“×±Q˜ý]–°äž{˜ŸC£“8Œ¼°¬çeN²Mf7”sn‘ÑÉRµœrÍÙÃÂõ¿‰æ¿:_ÿ+ÉU#}ê˜1ø4±u;Ýùç G¥¤ªÌDÈ¡†,ßýó /Æ;?ß¿¸óÔ•endstream endobj 212 0 obj 3207 endobj 216 0 obj <> stream xœÝ\ësÚ8ÿÎ_Á·ÂÍ@-?ÀžëÝL4I›4inÚ›NJÍ4Hs¹¿þ,[ÒîÚk zÓ©kV²-ýö½’úXµš¢jÉ?êßÁ°òú´]½™T¬ê^ø÷¦òXQ‡ªúg0¬n÷ÃNvRšˆjÿº?-ªÝ-Ë®¶<Ñ´ÝjXùTÛ®7œÚ–¼ìÊË—ðÒ´,!jïåÏŽ¼ü%/;ò²o:Ÿ†—–ë6-Q³åo«Þ°›Aàû­Z;¼µG6Ýš·ÝAû!^ñÆ/HOÏò›ß® Lû7h¿0Ä1GqŠ¿ ϸA;|»‡Æ9 ?i[áØÝÚwnœ/†ø Ä{n—0ø7¹a|ë:¾|ôQ«-_¥;ŒõPÈL.Hý†KCý»ÿ®"œ¦ç~µXéÿ–ÃâcÍɸ¡£~ºmËâëcÇ6†øÄ[`Â¥d‚ÞûKÀ['ùõz"‚à‰ üá ök`zÁ«¯ú1Q".aîJ¸"HûæÓÐÓ µyéêΚàËÆš–ÆêJ=¸ˆ‹À Äúž8|¿çXÑí×ubˆ·œ¦"â<{-/¨}DžGj…Ì šUZÒ<ü¢5"þnWiIËöU^e«Ü\Ÿ8Kr…&ðʧ0×kÀÿ ²î¹ LY––);㺡?)²3ÛFâ#Í81?ÏÃжÍ*VáE¶Mû´÷±¢jâ!žGÖ$ÂvMJHŸÉ°wMùÁº—0ìk{XwMû´Ÿs èY;ÂóÀÚ)€ÕY;¬(¨ÙÎ8² ;ÆŸa'™e(ÜU |bÚw ýØÏ€üèÿ*(ï•@Ù[Ê{ÿg”#W÷Ö˜ßÈXš~R9qÔ‡ n­jpro9'×â¡!î¦M´¿ Ô£¬+4ö  Þ5îQÔ?Àwë:ÞØÏ6Ñ(WÍ ëì!ê”{ü+ÇÔ+¡…Cn…âÇgˆàذù_fô…`ðQɤgÛ~ $µ 8Ž ñ+—6ƹ1ŸÂeá‡i@„›HûÞ·æãYi0ª‡Lä@sÃØ6P zçù>'¯(#dÓ V{†dšÊx>sü¹ƒŒ‚Ói=Â3«Î<×ï,J¯¹ö'<¤ìDj¤k'S R†ê41—£™æ½g ÍQ]ç4‡JшµÙ$qy–½T>Ï*Œ(Š<2D”è,Ósv ’q2<vläì(•<á¾ ¼YI÷|ØÙö1Ç‹€þ{ÂP¥tnÿŠ*ˆú<8iÁ˜§ðù,×·Hé{$J@ µ†Jƒ¾í1q›2‘©d0å¨=NÐXsH+$K‹¬XÉrB0QaI€IrÁD®žˆ2RkÕ™ /5=/‚®DšËHfÀ«“‡Ê-wò=ÒŠ«z܇î.ÖG_-ç,Um (ã‘5LwÙwBœá «oÔÕ –ïcMÃ)âÊV÷IX¥ÚÏ™ 5Éé0ŒÀ‚ì-D˜i"¾ãžhÉ%ú”dlá2È–¡miOP1¡\¸HÄAA÷¡}×ϸ°aÿ ‹H/TÄ´eˆÈ_îpðËçK ÕCˆ=ÿ¤|wb±™$¾·Ð÷žë[È¿íükoÿdÆ8³&—®®*â Â_†w_t`,«Ú—l¡Œ½«Yk¯ÃBhÁà»Wߢ4þ§á»ö l.¾¤h™YG%¶Ç·oÌ’ì&Õ^gÄ;2ñ1‚XlÄÛœ#>æ ^êªØÃ7&¸Ïà›·IZ$Ñž+:§–%så¦oÀž'eH"D‹ƒå¯ ®×°;ð¦Ü;ﶺ@v3¦yîáõ¬Ÿ@°³Ûf³˜+ѥРԎxñ‹SÄÛj±‚‹²Ò!‡à8!vòDX€~/ÈôÔÔ7‡\Oò€˜†´œ€å›rüÁ»•ÈLlf[¸–X„æ ¼‚´xiÔecÑIÀ¹;W±ž ª6å0á8Í[¸?@¦æªåbt¨ªö¼×wÆÉ*t C¢¬ë\óW]=–ìR-»iœ…ý?ž†6;Ì`ç]¿þð¢Ð;…HVtiñH f”¶H^àöëÌB¬:5üÚÉf•]Àªï¦óL ЖcvþBOXõ­ýo®QÕ<ø‰kPå×@c­ö2Nsœcù“3ƒöô ŒôP]„çØœ¢ÌgŸÃ Œô„î‚Rþƒ Õî0é¥Dö@ÎXª‚%uv•‹-(¨9,Ï€ØH…‹|ˆ!…òOã"QN¤Xaüç»Z±Ðóhê“„ÞÄP½É‰]Ó¹lî22w>L/HP*uPg$·ÔΠK®}Êqzvé½záÞÉ„”a^ü¹–ïN¦ð~n#>èv]yã:ŸèDBâ;Mß×Bò¹ž‡¸µarè\y€M¿¤ÈG2è1­x«oVÍN³ˆÝpnšÝ5óÚ îØÜÜe¤4˜JÙAtHõD™dboÞEaÏz#ÔRŒ+Vò4‘Æ$™Ä6”²’O¥¥|^î£H ߈A+92¸¢U¶Æ:\7ûpA"91Zqb|‘T\•B(³GfŒø–&»Ù¬j"T²Q‘—l)Õ l­ Ð8ö€);9ÖYI¸‰]˜r+tñ%púîp Ñsé f±ß šž­ý{BUy ¨_Ãn7…‚´ohgF(ºæ§4Ÿ*%täotØù¢¢=Sewì+gñ&®Ö¢2Yf™<ì Kl¹#«žŒÌÕ$¦â8^Ekteª|¥áT8ŠÙV@®9e¹â&qIÔ‚š©Ì&4 Ž»€™ŠPï™J"ŒÌÔÏ(wÄh·*[Óf ¾ä\JnI|™`¤»-ާuŒŽ¼ ùsº«@J<¦‚`ùuþÄÄ5*JmŸhbÀ¯O…ÿß‘†#›¶-ª GýÏ#Ñ«œºW êž|¢Ó¯|ÿüÓ ?(endstream endobj 217 0 obj 2457 endobj 221 0 obj <> stream xœÕ[kS7ýî_áv§¸û~Ì´ÓB)-–˜¶iÚÉ8€©1Cþ}¥]I÷ÞÝ£µƒ!ÓN&›µVÒjï9÷)å}?…ý@ÿ1ÿž\õ¾9Êûç‹^ÐßUÏ{ï{aÕ¡oþ9¹êoU§¨T-£2(ÃþxÚ«G‡ý2…Yõ³4EI|Õ{38nă}ÙÕ—·ê2 ‚0l韯õe캼n$yŒ‚pëßÁp#•eQdƒLÝe¬ݹ9néù¥k<£ÆÓáFêGÂ]«ÆH¿#ÑãÛƒ&®ñÔô r=ˆÞi‡ì^È5ªéÓ°•E>˜£wž»Æ 5Ò’/©ñž”…º/ôœöù=Ý^Õ·I\ Þ‰¥Ø[ý)A©fHõ÷ÙÖ©ýÀ{ë²ó²ÉÿÇ?õÂx”¦eÑï÷Æ_½©AÞÔ—ý#ýóP_~·jªëËKuÉ’ñ '¤gô|¶²xg† “Âl‚Ð…˜¤ç„É-'œíùÑð ŒÙ ™i”ˆ1îU€åìãçDH¹z{ûŽðš!hÜ:ÁªtsßiéKba˜!ÄŠÿ bghuÔx…çâEvuka›6j•ñÔá—I‚Qîvhñ=p:7–ønÛ¶õeÏ]Þº¶C×Yñ J‹!]"}Lã‚,k»Q™x-l”g2ìßt¯hжkÜ£Æ=ò H·K9cÕð-”ѧmŽÍTL÷”ÍLå6Íô´ïì:„¶ÎîËÎ5ý LãÈÒ:‚/ ˜êÊtu;GÒ&ÁbpÚí1a#óa7Èž@𑆭ˆæJpÓ!\ÝmIÞ®sä‘3¾vl’+‹”-\CÂõQJåøÎcm`ãS….K8'Mº@ï\ƒ`°uÍgb|²2Ekº%@Š’1«ºÆ­gD1"·º ÒD|±ÝÊöóð4²ûOái86õ¸¸¥€¶}  `ê÷;äÔ%ÍÓ ÙË„.~ÆEjíå$(G&üeÒ[fo Ü31'e¹OQÏi7ßdŠÕЯÿúÍ‘þHF¤0z,#™ìYàÿe|Ä F¼CW°–8ÎAEÛc]ˆHc}çÔiË^8T^r@DFÁàáéâú5³"²SÂûavÕÆ Z§…B”“5ÉLëð°:X¿8°þÖ 'Ð 6@-¿E2¸#Ëtƒ}BÒœ¡¢Ç£`=çíž0ØkÖ9j~AÓ!³ cgâ9C›¥[ÖÌܶ0¡Ø¾R* ŒÿtÚæª"õj*P)/£0_uNÂâ‰C¤™«&>4“ÌfÚ¹ÞY ¬€‡œ¬wap¾{¾¬N!ãS–cÙÖ‘¬ˆõƒ œöÞTH¬öP„çÃî2Ä3#äq‹©&-š$“W°¦BnšÝp!d«nÐûRl6û4Í ëÍwÙMÂÅ”±eÝAmpYȪ.íò±‘Ф–×"“ ;@q×¶µÌÎV–ƒ¼¯ÒÜcXc23$åy·”—jY žpÇ{±ä$¨7§q¨î=3‘Â0å~°ÓGƒ¿Ô|/Š) wÇ«¬¹Fî³t±Ý“ä7Uþúiäã¥%^_ü«ì¼ã\‘ÜjbtÛ5”väΈ–ÑàÎëÉæšCi•ôõ\1*PÃɡԘÓZ¹ÅahºÍg`4æ‚Xvgáuµ{gÁ¨HúA ¤ Iʆ[Ó²*‹÷üÍF˜ç£¬atVPy³\’ÅG± *ÛZ°dÀ¶ý¨XöÊÚÂfg=•L© S"á¢ÁuíoàŽ}× Úþa\$~Ës­Úílj¸ÓëãÌ;á.> stream xœíšÛrÛ6†ïõº«Ô1O"/“Øñ$ulÇVNÓédÉvÝʲ"˧·/@Ø]ò§(ÙIÚf2™Ð¸A|{‚_º¾§º¾ùWþ_tž»gW¿»£ÿŸu¾tT.Ð-ÿŒ/ºÏFZ(Èt‹—ù™êŽN;Åݪ›žJü ›ÄÊ ¢îè¢ó{ïYöžšÃ–9|ÒÏ÷•ê½4?÷Ìad¿™Ã¶9|ì"5 <_õ"óÛï/ËÒ4é…úÔÏBsiì::¦ë3×ø 5.ûƒØOõ¨wî®ÏÄõ²ñ„®qŽOÜYÞ{¦GõþFÝ»Æ[j¼t jœè÷Άù8oÐËM]ã55ê'Å*ó²tÈE¯tkà{Fö\Ì{gs…)ë™è—½u)ûÇèUG…^giw´Ûýºï®ù¹o;æÓ~î„w-òBØrüÄGÜ£ŸÜ7å>O­6Ü™bŒéô¸o ‡Iâ mÓ£‰6á©P€Ayq`4ÁX{.Ó¨/î}'R7øP©‚ßü©è ¢ü±˜‰òÔ]iÏ[á[sxæ°n ˜…°1å8MÑä'ÑM‰N )_ÑÏù‰€«­5ŠŒµ¶øíÜG¥Ëއ14Ë!AüŒÞsR¾Ru,¯_" Üõ0 lyfg9Í,Õï¡ÞÏ‘^•¸ý!ëýÒNw³†Ù7£7b¢7«¢h‰8aØÙ&—Ƚh&—þÈähÄÒóÕ_sI67^…À0úÚ<ׄ¸Õ 1û‘!NЈ¯]£ôu48Ûç ç–ÌyèÌä<½5yö£èA>q&§4m˜–âÁÀ“P­ït}¹ºñžçü™Q¦c¼Ÿb—8x ]g£°X4®7Éyò¼o—¯õà†¾fU­o=34° ¤‹d ÒEr=§H¿4šÀsô LrŽt‚ÌxŒFwE£#ã×LÂ(?»Ÿ ê´ÖZYDNjÖ±ç²Æ×\žN¾sôËØÅ× ï›­# Ž4Ñ7 HØðW…ˆ[Òé b¿†o üïgb³µßûN ø®¢ÛOÎÔöÔ0Gy䄜IæÂ{Vy!§Ï”ÑÌ,ËAŒv¨¯ûQ¾¤€/¸@ó³ uœ?²°¦%›?² È‘‰D†Ù3€l½¹¯8<@¡v()89;$ŠÃÜÑ@ Ñ#PHg¹ó)š:¯•”üô¡”‚¡§T–µfå’ÛÆCiáÌê4›bÑR5Ðå°°,V³öö%šÃ tûã=hÕÚʚǛÔCém¶{É5þ£SvJ¿>H[¢Èc<ïG.Ô„0e ±Þ£W]"º£ ûà†JŸó(qŒzºj˜óú@îPäY ÛÛìkÕ–ÖÀì‰çBØfÏ¢hÌ Ȥÿ²P? g¢˜Å±i 奰H{ƒ‰å,׿°mëàšVY`„³„”ØD4ÔOÈ‹ÆÃÀìú”Ec™ÏÔóÄ¢”\Ü2p%sçÚ±ë®î¸6—GÂÏÆì·7ÛTºáóWIK¡êu›jÉX9å}Âå0{UŽ)BNÏ”‘ÊúI¿ôp K4Ð…Pób¤q%¦Ú:¥•ÝFH¬BÐ6¼¯(D~‡ÜZXCöçOîì­Uæ-l›ŠÃ©ÛgjÏámð{¤#>E·Ãå¾(ÁØÛÛ<ÊB=«©Ÿv äfX Q/8óþÓ¬¡ÞB[FrålýD˜(«³~Í%˜«ëŠ.=.„µÛÛŒ<Ûhj+ ¬¡匞ð]™âÂdßÔû­kü³]q¬;X_YaüŒœþfà›^Û~ fgï…pîõ¥½7¸~¶EZrÌ«%²âs1õ\¹Í`aÑæ*—htÐÇ´—“ÊÊæ©s°;6ôV™P˜Ý—œ^:á2½Ø\aÕl–\Áp•VžIeEÊd«ÕÂÁ1ÆSn4e?Û0 —6Uä-¹Æ­˜˜±«¿`:6ʲ8‘°ZÛKÖØ|ï<é‘£ûÎ }H¢e x›Oý¶à¡ËmÚÀ­›ñ ô¾lú—ÑsÔç„8µjUòÿÕîUÚ¯ ˜1£=t›ÛZy!Ë¿^YâÛÀ¶añ»Á·b×5v›‘•ïm¶Êx#ƒ=È_õ]Y½ŠœåÀ0+ëÒñyäé¤tÖÖLÛ#•å ãä·U­ïæšÝ® ÅÓ÷n@²ðÃÉ*TøÕÿÚÕ>þKJyM,ŸAl¡s ØW83Ñ»Lr£’ܧÎ+åúöAÁfŽœ}2Y%ÎR[šJ¦À-å"7$ë5'±6 }²ñþ_úÎJ Ï3ã[q½bÝeÅÊf¬—:ë'•ÛMÿRUžª”Y=Pqꩤ;’@gkE÷Q?ÖIslä·G7úß?ÛàŠéendstream endobj 227 0 obj 1819 endobj 4 0 obj <> /Contents 5 0 R >> endobj 26 0 obj <> /Contents 27 0 R >> endobj 33 0 obj <> /Contents 34 0 R >> endobj 38 0 obj <> /Contents 39 0 R >> endobj 43 0 obj <> /Contents 44 0 R >> endobj 48 0 obj <> /Contents 49 0 R >> endobj 53 0 obj <> /Contents 54 0 R >> endobj 58 0 obj <> /Contents 59 0 R >> endobj 63 0 obj <> /Contents 64 0 R >> endobj 68 0 obj <> /Contents 69 0 R >> endobj 73 0 obj <> /Contents 74 0 R >> endobj 78 0 obj <> /Contents 79 0 R >> endobj 83 0 obj <> /Contents 84 0 R >> endobj 88 0 obj <> /Contents 89 0 R >> endobj 93 0 obj <> /Contents 94 0 R >> endobj 98 0 obj <> /Contents 99 0 R >> endobj 103 0 obj <> /Contents 104 0 R >> endobj 108 0 obj <> /Contents 109 0 R >> endobj 113 0 obj <> /Contents 114 0 R >> endobj 118 0 obj <> /Contents 119 0 R >> endobj 123 0 obj <> /Contents 124 0 R >> endobj 128 0 obj <> /Contents 129 0 R >> endobj 133 0 obj <> /Contents 134 0 R >> endobj 140 0 obj <> /Contents 141 0 R >> endobj 145 0 obj <> /Contents 146 0 R >> endobj 150 0 obj <> /Contents 151 0 R >> endobj 155 0 obj <> /Contents 156 0 R >> endobj 160 0 obj <> /Contents 161 0 R >> endobj 165 0 obj <> /Contents 166 0 R >> endobj 170 0 obj <> /Contents 171 0 R >> endobj 175 0 obj <> /Contents 176 0 R >> endobj 180 0 obj <> /Contents 181 0 R >> endobj 185 0 obj <> /Contents 186 0 R >> endobj 190 0 obj <> /Contents 191 0 R >> endobj 195 0 obj <> /Contents 196 0 R >> endobj 200 0 obj <> /Contents 201 0 R >> endobj 205 0 obj <> /Contents 206 0 R >> endobj 210 0 obj <> /Contents 211 0 R >> endobj 215 0 obj <> /Contents 216 0 R >> endobj 220 0 obj <> /Contents 221 0 R >> endobj 225 0 obj <> /Contents 226 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 26 0 R 33 0 R 38 0 R 43 0 R 48 0 R 53 0 R 58 0 R 63 0 R 68 0 R 73 0 R 78 0 R 83 0 R 88 0 R 93 0 R 98 0 R 103 0 R 108 0 R 113 0 R 118 0 R 123 0 R 128 0 R 133 0 R 140 0 R 145 0 R 150 0 R 155 0 R 160 0 R 165 0 R 170 0 R 175 0 R 180 0 R 185 0 R 190 0 R 195 0 R 200 0 R 205 0 R 210 0 R 215 0 R 220 0 R 225 0 R ] /Count 41 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 24 0 obj <> endobj 25 0 obj <> endobj 31 0 obj <> endobj 32 0 obj <> endobj 36 0 obj <> endobj 37 0 obj <> endobj 41 0 obj <> endobj 42 0 obj <> endobj 46 0 obj <> endobj 47 0 obj <> endobj 51 0 obj <> endobj 52 0 obj <> endobj 56 0 obj <> endobj 57 0 obj <> endobj 61 0 obj <> endobj 62 0 obj <> endobj 66 0 obj <> endobj 67 0 obj <> endobj 71 0 obj <> endobj 72 0 obj <> endobj 76 0 obj <> endobj 77 0 obj <> endobj 81 0 obj <> endobj 82 0 obj <> endobj 86 0 obj <> endobj 87 0 obj <> endobj 91 0 obj <> endobj 92 0 obj <> endobj 96 0 obj <> endobj 97 0 obj <> endobj 101 0 obj <> endobj 102 0 obj <> endobj 106 0 obj <> endobj 107 0 obj <> endobj 111 0 obj <> endobj 112 0 obj <> endobj 116 0 obj <> endobj 117 0 obj <> endobj 121 0 obj <> endobj 122 0 obj <> endobj 126 0 obj <> endobj 127 0 obj <> endobj 131 0 obj <> endobj 132 0 obj <> endobj 138 0 obj <> endobj 139 0 obj <> endobj 143 0 obj <> endobj 144 0 obj <> endobj 148 0 obj <> endobj 149 0 obj <> endobj 153 0 obj <> endobj 154 0 obj <> endobj 158 0 obj <> endobj 159 0 obj <> endobj 163 0 obj <> endobj 164 0 obj <> endobj 168 0 obj <> endobj 169 0 obj <> endobj 173 0 obj <> endobj 174 0 obj <> endobj 178 0 obj <> endobj 179 0 obj <> endobj 183 0 obj <> endobj 184 0 obj <> endobj 188 0 obj <> endobj 189 0 obj <> endobj 193 0 obj <> endobj 194 0 obj <> endobj 198 0 obj <> endobj 199 0 obj <> endobj 203 0 obj <> endobj 204 0 obj <> endobj 208 0 obj <> endobj 209 0 obj <> endobj 213 0 obj <> endobj 214 0 obj <> endobj 218 0 obj <> endobj 219 0 obj <> endobj 223 0 obj <> endobj 224 0 obj <> endobj 228 0 obj <> endobj 229 0 obj <> endobj 20 0 obj <> endobj 240 0 obj <> endobj 18 0 obj <> endobj 241 0 obj <> endobj 16 0 obj <> endobj 14 0 obj <> endobj 12 0 obj <> endobj 242 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 136 0 obj <> endobj 243 0 obj <> endobj 29 0 obj <> endobj 244 0 obj <> endobj 22 0 obj <> endobj 21 0 obj <> endobj 230 0 obj <>stream xœcd`ab`dddsö Ž4±T~H3þaú!ËÜÝýcåTÖnæn–¹ß_ }·ünÃÿÝR€…‘ÑÍ;*Í9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMÛ윟[PZ’Z¤à›Ÿ’Z”—X dggõg0000230v10122-ãûÏT÷˜aí‚Ró¤~WÖ2§ar7ÇŒyÓ.¨›Ð8A>bAÄüðùß5KÌž8}R÷|Ž…ÓëZ:»šëå~«Îü®Ú;ƒuN͌ʪ꺪ŽÞ†îv¹™¿~«<­ŸÜÙÓÒ-YWQ_Z6½mV«üw-ÿßšþÕ­õ-Ýå’¥óêgLêí™<]î»ÊÓ®ÚöŒ®zÉF-ÖªÙusæÎš1§§éi×¹®ií»fpð/þi¿„í·è4öý\/¸÷Oááa`ðv( endstream endobj 19 0 obj <> endobj 231 0 obj <>stream xœ­zTT×öþGæ^»2¹Ôܱw½$EÝXEª€té0”aÊžz/3Cq@@ *v_Œ1Æn4¶—˜¢‰9—^ò?ÐøÖËË{ëýþkÖæ¶svû¾oêÚ…‰D’…«ÖMž$ü5’(âuáß»cý¯ŠÖD+è)†ž]kM(´æçôCê>hb_J,-^±ea@`dðvoŸÐÁ£Ž¤Þ¥S“¨%Ôdj)µŒšJ-§¦Q+¨éÔJjµŠšI}D͢©þ” Õ…²¥P]©”5ˆ¢)Žb¨íT7j0ÕBõ æP=)ªµ“ú€êMP}¨¾”Õ²¦¤Ô[K½-ê.êAm!a"7ƒÈFt·‹[—3âUâ]—u5[õ±J•t‘JÐÌd&ª[ÿnáÝÎwŸ×ÝØcsç=K{yôú®÷¢Þ7û¼×çj߉}›ûÙõ3÷ûÕÚÃúŠôà[óÞúÝò¶õÛo×_g#±YdsÐ6nÀìͬø|Pô;=ß¹Ëõç®É¦ ¦¯œ3¤ÿ°!/‡®6zØáa·‡~u;¢aÄç#¾I2rËȲQ²Q>£¾2úò˜¸±óǽÿ»h•Õ»5,h³…_fU·Ú‰ù¡­+Ù”+¹|¾`¼{¿Íµuñ+“\×ɽeme´ôgoµü.Ä$A¶þýÁìkXœ+[…o²¸ŸÄIQ#Cåh ý}ÓÄ¥‹6Î.ëÍ«äf~’ITyí¾+æ}ѽ5ê%î…ûÅ"ܳ?CÝP¯¿CRa'Ö¶€¡àDÙŠCÍÆF8ûÃÊ]Ë]a-ñ£78„m sÙºs30¯ƒ…îÝó¿ð÷ØúϦVñžŸÚ]Hœ¾V¤%~ÚW.WÄ)2<ñ2t89tfk4§ä,´7‰‘¸³ÖĨ˜þ2å…AÈ cƒ7Ò¶KêôWȾàJ{„BéTÙ 2ä@w_™E…YZ'XD§^ð»Å­Zç²E!W*!>‰ÛlçU·éè8°Å«ñt<»bw4OF¡™ß!b²!#NŠ, <‹€ùoÚƒZÐ1´qÏÇHôpiébA•L!貎ªÁ,h¼‰·m 6[¿¼Œ ïö—ÞF Ñ#¶ªåHU 0W?žŠ­p¯gÚ¹{öÊb ³¾kZt“×À ?}‡X$û=î:×mkX¸Lúì‡ õp%C±UÖæóª¨öhéÊ¡ZÔµ”ßÁv÷Aìá#¶óZ1 u›‘C–É` ε­—Èq˜•Y’¬vßF³È¢“%m¶m8YH²J#Ç»IŠÁ*X’„eð*`ð,ð×Tg„¹û¼ôqmë<Ö¯Œ~•–¯’²‹ÍAÖ ux šŒçÉð[ÿ̶ç%¿·#Ûœ‡Ëa-‹ö¯Éšs‹#V{o \·v$ÓçÜ+oŽ5‡¬÷ÜE…„nó}?fñ’¿r:Œöœd%}V·íÂû13t,~÷{61ŸíÛ_e’é‘‹‡ÐàëèÌ‚"õøìî·š¦m¢Y%` :gA5{DhÐC´Å,nŒrØ`I0žºÏ'>±í¬4Ã#úYŽï ™K¦ËýÆr“Q²¤£¦Y šë ±Œ1KP˜UÛ¹×…l|í±/ˆwEJËkØ}yéåýþÒƒhþ M$UüðË htœJAL€1ÆTlέ®ö«r]à½Ô5–“^G]h,{ œàtƒ¶YW Ð ¤JvÑvêœ:Á@í9ÁÀf :Ôaàz3fó7[ç°m‡þu‹’Zý Rkûàq{µí ÇC^­ iîÓßf¿2}fÂŽqÜt”ÞizO  fûBÌÓ‰}š Jnâg”X×”†FÑäGéCä6°&åhXÈlòqŸ;ÓûôWœ*O“šL$Gʰ É9iZmI §Ó®¸ä€ÛA‘d.}èoŸ÷ߟ+ÛQí‘é–ÉH¯Ûç,Í;3 ¶|ß}Ô%m²ŸŽÓ&fhaò ­Dö#-€@Šâã8•2!Q©ò¬Ü1$”½=—ÚûT„ɪƒ*ŸÇ’÷=H@$Ñ€‚-ü‹5A’}«ûKcøGؼ°F÷`² ³@†Ð ©iŸÜòÒ¬Wû>šÞ„ªéGz¹—l-mÆ]±41`9ÞRÛ"›kÎýòx2eàÞÄ”@¿‰Q¾Õ'FŒúÏÀS°vCÓðT´îê­ò³{HEÉ_Sr3e@4Ë úé2`#;~8‹†Yð0´2X¢™í?xŒ’ û WѸÏÓøº+•W.r§ƒ×ÓD}z-…ÇE\‡ä8oA{,íip졘o埳uºœë\™E⣲#0ï óÁ‡˜ÔYë8Cqô_^óÔù‚Ðâ^¸µ$uBè„Dè.øëk:PUn k"eA´H‡‰àÞd'ÓhxŽ•…þ0)㈌T ¢ñ¨?²1=ÍqÉ‚™ÊæcúªóÌ PM‘á±ô\˜„ÆŸ:Py¾Š#^Ü>è¤ z(Fa‚åúœ›\¹`Õb“Ìi·ªœ¾©ï´J%ŸÃ ;¾IöÛ7ÛwDÏQuì˜ —ÜȰˆJøX1? Ýg³J‹ö_´G¨z§&BÀY%Ð`½&'" Q­TÊGàLÜU+òH¶êlË ˜$”¿Æ^ à®õ'DH_€TEžŽ‘Mz¬.%ò 5+5[ÀKÑ×T˜é êÊﲈö¡®hÌ}1:‰F³ïn¶ß Xg¼¹c¹»Ëë aÛc·Ú]YýðùÕÏ®åÈ´™d½= ¿†Þ—È’[Õž'½SÁ“˜]Gq>²Jí0«X¦¿£‡lñQK^­`V1+ v‚‹.B0«NcŠ$ß N‰›„³lF£je®F ÷Š0%vj6©CÀvvXU…êì¸4EŽFÄtœb3RrÉ®R_]ßá%lÐz ×…\U®/²Æ¿Ø¤Åê“/èÒÓòDu6Ïq}ª\8d›úvÏÝcв _cÅ£Ã&ë¦ëŽOÐÌËWÍý¥ÑrtÿK6ս­ãÇù·e§‚íéµÁ ùåÁ49ÑDÈ5x×{4l.tföb§eþ†¨òÊbCynJ³VVQ{$‡ˆ›#§=¦È¼héQù&Õ‡ª•þó·o„­Ì{Ï‚/\:ÔØ\Â%£Yì(züÂí.[¶Õ=ÙtÍN'™'îvîÌã‡ó3Y´Ùefo¹-hÛ •/ ¼7¬ƒíÚ6=!:!!)_ÂÇlЕÿcý-¤C4ý2lLOÌŠƒx[¢+4 µ°·]ÄÒ°+Õÿ@'% üdåaQ<»{ïÞ#eå–º}ÍB©ý5A$®tqBÕ™q¤o‰NˆKQ¬šk3÷ÇDAä¥ÛBAA–¡ýzÍ2u4ì'm ×Ï@«i^ý=fmœVƒÚiãÚ5ê]@N”ë,Úr¨‚&u™@óaúä<(SUÍÇŸWydÊ6gÊó¢I¾%&Æ 2|·ö”ÎDdAƒfw‡‘ºÐ*æ˜È üpòj"$‹JˆB;‚æó½XôY§Îj¶§fZ«Í̯hf¤1¡M›¿øJ›ùKæº:EFËô¸EÛh(mNaé“™epê‚Ê<Ë·é×Á6ðR¯Þé²ËÏs‡¸€wYH=‘{z(&:ÙŠ@®»ç: ÷+vÛ¥…|D,Qâ‹H¶u( ~7½ò¿áj,oÕ$òH¢”þ4Æ|±¤S4¹™Šïña}î‰ù©¤JË/´h á5øD‚“.LˆŽESE:±:%~$ÖØ`12)³Õ©¤ìÊë¡„ëOÔàs˜šïƒÆ¶‰lRâbw(âÂÖ,^)¤ãŠ(¶¤fš )( ‹ówiò>zaßéÓeÄ ˆªæI½YDdÜÆ'b„I#·M¥ð‡8&¨8¼²ÜP´ûÓy à~ïb ÷Åo}?𤿀jÔ3;;TjnçÄåñ^Àl˜ºMG3ï4Ϻ ñ®%È$β¼*¤Á•|Ùm1R´ŽaM*²1Ï}-eTt 8 oïGήŽt¨ÆáÐ\!ãë´4Rü£KZ\ÉRÛÐg¦æ Mk/mÛÉ«Bª×ÚÞqü êÿ($¾ìU!â¹’ Mr$h;gÓa9˜ù·H×ÅwóølVŽlL^Drø*‘âÓ‰O^Rº=#‘àê¶^‰rPCŠml‰ºK”øj¢Äq÷][1C,ê.yƒmÛ3™¸µä’ Lúžd—ÑhÔkbäz3«±-=R·ÓµÜa î>t f±ô»ÑHrñàžj³ »b7šä‡Zåïèæ*$myÈÞ }ªÓDöÕëÎU4ZöÖœ ÐÐcqɉ"»Œ|£éTÉÏ®£˜Ö)lb®FA¶ú_•¤ šM©J«¦­ä/ƒPD§¥h5© ~|Û3›¬x­&˜|È(‘ñGè h~A’ÒG³E½vÀÅ/À)PÖ6~fþF´ ½ËM¼D<Ž¢Y“Œß;<#uż;œüðóX"õ{Dâ’ì$]J¢Z‘¤–ù Ÿ °Üw‡Öû†KPÇhl:sϼ˜Ùx ‡¬²ÃÊ[g™…¶rë q«'zÂ"W<ŽtËñ<OÃÛˆN›ˆ'¡Åh9‡¦"…¿fÇá_£|”‹F~z÷¶gábüÎÌw!7¹cÜbAÓîešD¨ë¥'Äh± ã$Ü 1’¯> /€ä.^ÁLhaxEU¡¬Þ«fÇ36 á0=Çï&¾þŸ4GS³·]hoáÐÑbŽ.³h®õDÔí¾ý5~G†_¾1køKQ¡"•v4t%h* Ù⤆§ ¼­­;s¯A©uå±ðkhÁµÚcý¥¿ `4Ÿ?”Vh« ̲ÌÜÒÊF`À¨Ð@oL°,)>4À˜Ñ™lCÀ>U 0O/_¾^]\*«ÛS—V,L @¯‘+SäÏDåÅf—d”ÅW{„oUlsãÜjÜôaÀL\¼øƒ­&Oó.Y\Läða¤­à—çi _åë îÌÂï×£Þ¨ûO-7jc[6Ur*×ÂG]!Y뛺ËÕ ¥EIñïìÈÅ-Çí­? —•ÜG]aºÃ¢Ícd¯‡eíu(êP¨bÞ¥±o·fÂÖÕÑÞŒý(y“dŠþÍÒÈ6¾Dô îq:f±‚«AVó^|[Þ_…BÑKåÒP ¹&}¶® Àä?bñ`Á_Ÿd)|™^y¡Z{BWFp¨¶Ã Ë”i 2é©ü^¶:Øàh ²TšÕ\G„Â,­“*­O•]DŸ^Ü@|r=çmXü–eUÇ 8cûÙ‰o ÷Mx–K:§U€"§³cDÎí=Y²FŸÌù¬ó¯Ú¶o éÉÄ3§™u|Á@Y޲%þ³(Fú´"ywr¥—1(› ³hó™;ç¥ÙÀ­=¡º¨©Ód'êU?ëÔÞÏfhu9hõúšã–í½üïvë;Ôå‡ewf:q°yá×|H»WÜŸûy9ñ˯ÈKðËxÁ/׳„<L»$N_‘ yA\Aª!*˜òHC@@dxÐÆS§¯¿ø˜“¶µNìZR¶sgHÈÎe!UUeeB$èzâøÙFdW/ª3£Ì‡(Ó,nØ:›mC’ˆöQQ>š^PƒÆA1I¼lµQ reHbl‡Ø¡œ»ŸdŸþ9"Ÿ°$†;=ò÷´HÒ,¿85‡$l Û väãéí£€N)IW¡ &ÑËK‚˜,d5º”t¢R¯œËμÐÒ¤3 q§*ˆ ^¥‹à¾D“-‡8'*xîmÇÒZQ5«`74jÕ¯*ê}ñäõ!Möi¥Œ WUjÏêŒDXViª„«¼ < ”Fò¥‡8kµâ,šÅCǾ?Þ w7£ußï?Hï^4‚L€èGO‘¤ˆÓ t•®ƒykÕÛÁuÞ¯yìU´Š”ˆ‰[>l]ÎþóŽëÌ`&ìYÿ0„m[‡å×ê(nñwØüúŠªOµãWA˜wŽ_iŒAD%©j^ѶËÛó:E~{ãYuÌíØÅÄ*GpíØÞ'‚öóD1m¿ÚdD¤©ò tiiù”ÄÎá_^´wéµÿ¿Þü_ß,àåûÀ.Çåõ[†kÿü–á÷®bÂìíÎ+þ5Düëâ¼âÓû³Ýì¯öÓ^Vt8ïoÃÒ´+TIÄycÛ¶Ùài|œ&UNúÛÝg ¼ÝyKÚ“ÂU·M¸ã4!×Ûô¡ –µÙáé¼\£'ÂFÿo®¾©)¹^È©­ÕFŸ¨OÈ—ŒÔ<4›O³Aïµ¥w´í8*ô·¼Ìˆæ¿¡þ&4ß$Føû칃®>‘AAEu†üìt‚i:­V Œb•¾É W®’ÅÇù¦b’Ó”i9w¿DÝ9´áíÿå6²°J~héÝÇfë¦GÈãÉòGý¥mÈÝfËh”ŽúÖµ”5)¶›¸wpñ+‹1îÎj8·õð,üH$hLú+6 fÑS$þæïä>é”o±x‰×&ÇpõÀר•àNQÙ ·Hït£ú‡G…‡`•…+ö‚M„Has”·ÿjg‚~‚3ÂŒü'×s "´è‰˜ä_²YÂ$ÁÈ`¥÷už²„ –ìÀÛªé ³.äåf¤ß€<½îyô, Û1Üe0‚I—C‡à`6×BÃIýÉÌ©¥ù÷œEV/oùƒèþK1Zß:­ , ŒÜÁ5´9jc´I¹`› ú4mÓ€'±ÿ ¼‚ÛZû— =€Ê„í/½Žfòάónå(b>þ¤éÊÕ‹®óp\íÙbØÏëƒKÌ“)§'zÏnb¤Î¥É‰Ë‰¯6öy¸vçtûц<_ú3²úæî/uòƒžM\„1:{E#3Ê­Œjö?ìWÑì1vó7Ξ¾ðüÝ3Õ¿jîØIÝ“{¥üp!€ËŸ À_x1ºÂúÒ8n˜óÚ(Ýž@î@fU‘%¤ ,Ú?Ñcé‰m_‘f¸78_?dÂô§SÖo‰tqå¶¹„ºÁ|÷ûz êúñ¾¦3¥îû Îàw!²ŽÂ8ÍÆúŠ£{ój kÔl/rÉõM] Î̬íc§r˜‚7ÑÙF4±3ˆNµzˆùBdË¢PI~  #ÃÞrÞ Í“tŠ•ái’¨I«Óç’.6'1K­Š“«¸÷ð)+¼æßŸ •ÄF@xx È·ÄO´Âó$1‡òehšd.nÒ¨Uñ ´•g%æêórôÜmtÊ ­ùÓSxú–mßÛšö§½Êð²#_øÞÿšøÆŸÐ3¯²7š-ˆy‚ôOžï®0XŸjÙôä¾åþ“M-ý¥ÿ0¢bt‘E=ƒ3ÆB,u\:'ñC-,n¡§¦9µÄOÕdjR©()©¨ÜU¬pWo™rü]Ô/Iæb9Dÿœuõ)áì».-‰Yî¼³séoljœÿJyxk½R«Ö&àgŽ1ê÷k<[vwM—ôs¦±8aéd˜‹ë‹£özìIj‰cžtÅ}Ê•÷ íŸk>+³³R°ƒ€Oi{D›˜%4?w…]rÒøòù-ÄT©¿pxIi:Ðj¹ mŽ.3ƒéìÆ,ü@ *4‰šîî½€šÑ¹JqëJÔ‹UÍY±Ã`c‹ïÞCÇ?=t³á’±ö¡@†^j‚H˜™S§Cæˆà„”dJ¶~¬Ë× q„·ßÙŠèç>ý’ܡ軋VÙ­â–¾°v ¶ÍÕß×Å9(˜iwV~ÿÕÙý5õÜåÕg£×pá´î>Óæ‰ö±·TgÀÂÜk¬®=ÃÔËÞ›Ĺ¾Ïšœ ü÷¯* ¨ÛXïµbݪä`f…>;q{O݉c-&²òž$ýqëBt‹}Þmßþ‘¨ü7xûºÚþþG¾vxý+¬$”°í¤\¸—ÈŽÀéør1óölyT…wxl‚BÁiÔ5ä§Vg|~á¼,W[=“‘’š"Ÿ5w_]沿¶¸¢\ —ÿå¶Ž·XoüÕÞ úþŒÝÃÉ,шº¨"ÜYû¢µ€&Z°-@}P¿¼Îç(õŠ„ÉK°t · w‰Çb"ææà^'±Õ9Üçþòl`ÒSõ‚£®Ïjrtùñ§&ëSOŒ/—›ŸÝí/Å(éX@ÖϮԖWŒuÐÄœq¿ŽÇ`jÕ’åÛKcK…1ðA7ˆå,ÇÏ4þÁ5Ñ‘‘‘²e ÃÞ%(ëBG‚"7²Š9é?ñô?á€7­CÑļ&¤gá†õZ¬V£>Ó?!õ§P**P—Dʾ}Oì xž^„ûb븎ˆ)R•éÙ>EÒ³\ ê’‹Äp¯³>ä&ÔÍ„..¿E§ÌˆºŒò/#Ê,æ¿"\SªÑ†rQ’hÐhÎ6æ{3|üDl­¿™øâÄ᪦ݲìÇ"öóuþ‹_Pž‡lñt¼ÅS±#^ƒ8ür:v1£à¢¬<õ¬…B&;¢¹DòP5¤¨f¸O ™ ^ŽßF“Ñd†¡hzÍÃ]°âÝäÉË| ¥@¶ø ‘ ŒÝµuå&E80 WßGb$>{ÿjõáhû:Y^éŸ"†GŸùÑ'¼•ŽÉ.•d¥f@®mž¼ :Y A\Hä*çàÈôMA\v\´<>.!sº0ÂDbsÔ ÛhyLœ<5©(I††,òe‰Êdˆ·UCP ‡ÿƒ?°ŠÉKÈ+ÌÉÍËŽCœÚÄõ¾fŸ¦JSéU™Àæäå(3£2;Ë ëß(BÝÅ(ëÙÆ±¿ŽÖˆßù-†îˆÄ,#:؈D¼U£˜Ÿ€¢XTýŠËqU£I>”„‡CD,‡kp ûšÈ7I,D P’Ïýñï9–$¢Ö /‹ÑÊ'BgxÝ凳‡2â¶Épé_µ ¼˜ÆÖ‰Ñ¡mÕ5Ä#½‹»#+É÷÷Ïï®K5pÛÔŠˆfv”Ç•”–î>»¾Én"î± ‹8,ù§iÓŸ­€®Óo¢¿-#豤Õj5±+>Úê$S(ÈâÊv´É½yÑCö¹¿¨ÂÜôÌì7MEJƒ¼ÝPobæ3^JÌüëõùßho…•ô¶’¤¶R盿>3‹ì‡Éþ»Ý#o ‹w‡<ýòÐYXÉ%*£ "3cŠÌ?‡½ ûÔÖD¿ãþì·ñcÝÑ; ïUZ}F”ƒŠÅ¨ ­fÏà⵴™&ðJ1¯D™¬©MF¿RyüOõb'Pœâû‹ùå­NlZž€„Œ eb• *ÿý·)q¤NÔíZ$?5;[Ïu²AŒnøƒpA'šZmL¢†»(ó®˜wEWY¸•rËç çogºÁjX´m¢ï┹ð>ÌO¼oÞþ÷®† ZïKãoª/§Ý€› öÆWYXcŽüV~žÀY¸—2O” ײÌP—"KFgÛÃ> endobj 232 0 obj <>stream xœ•X T×¶­¶¥«TD¥­ jºpBQ‰8c⢉â„"(BQQp@î>ÝL‚‚Ì“(S‡Jœˆš§otÅ FML4/ÆsŠ\ÞÏ¿ 1/yïýõ×_µ nõ¹÷œ½÷Ù§dLÿ~ŒL&cW8yNw0ýh+’I£ûI¯ËxÿúN÷j30—ƒyÿÆÑüCKl†ÞCÐa(#—É–¸z9‡íˆ‹ в™älg3}ΜÙ6‹¶Doñ µYá°Ý7Šþ²ÍfmØ–à€¨¸7lmÛfãfz"ÒÆ- 2 "&À¿/¶sØöÑQ6+Âü"B†™êæ¼Ã%bIäÒ¨è÷bvú.õ‹Ûâ¿2`Õû«݂׮sß¶ýÍ·Þ˜>cæ,G†YÅŒcV3ã™5Œ-³–™È¬c&1îÌzf2ãÁx2NÌTfãÌld3.Ì4f ãÀ,e¦3ï23™eÌ,Æ‘y“YÁ¬d¬kfcÉ(™á ϼÆL¥éaX&šù»l…ì“~^ýÚå#åqýÇ÷¿f6Ü,ÎLTŠÓìrö)—2Àl@Ò€'ƒ1ƒ¶ ºoîl^38ÑbšÅÁ!ŽCR†²Cç ý|Øöa?Y·T[~¢ S^ø›lŸ;cñ[¿ø‡ ˆø¼3Ðh‰ zù ÂJÙÖ&òj¶RÉP pQ[©ãÄ%À¢ìAÇ•Úâ˜*Rºäßavo˜8e½›g¸Jy–,L4S³]™à/.Öâ7ù sS´6#æ‹–8­ðŽ%,N´RJX% â1—±Ï æzÏ÷Z1Y@Å.™Â.Á]îÛYŸGUÏ52=ÊŸ £–üøö—xêx ÊÉUž¸b®Wµ>5¾°¸}@†“ñ* éVR£¤4ʪq8fâp¹Ô€¡<ŽœöœÌ&o9L ÖdèÉøÎýú9Q‘CÄ•'J@æë68_+~Ð\ÜÍм»$¨8Ö7 C”*z®ùz&A”~eWÑ^ÒtÈ»3»§ó…w@«=˜¨zoõŠSï,kb öÄŽø_¤w4à*4Ã!ÈÔïŠ?»tÂA2’ ^i ó`v™Çeõù}wà1|˜ŠÌ•?úøëÃgè†àû%D™«×–W¡7T}u$ëEc”d[-_"CZÎtn¥¼ƒ;ðs õúÜÜÆ¦3%À]ûp%±$c\<–íUùMBBè¡»NsH ¹’m jÝßNþé1 híð¿pý¶¸(Aù}K\~/k€Ð£ÿWнü=ÕTå:³ÏÊh•Ç¢£(ïÄc¼ZMTa3È àÈT¬ëT<ÍöY$ˆX«V,:à3Yµ³qª¡Â) æDÅ6L2û‡ÌTó/hÁ»-¿Éîå™>=Ç­ë4ó%ZXQ°{Mœ…Îìr´øQ¥ÓÅí†PίzçñãÕÅgÝ{¸lÙà¥R¶¡KÞþ*éöëôm†v¨‡«`Ô˜¶ë¨)@©ˆ%¿ošˆ¯ÓŒèžË÷üôj3ŠúÔçÐ €2hÕp"…¥§Ø§Y(‘h– é@¥ó’ô@tÿò˜$£4ªÚ²¾Ù÷&î£ßLûD‘?sÙa¹®'Px§>t]ºJ¿GŸ\ \¤— Ÿ±&<¥h!Ö_ž”±¸íä V[Švíƒê“îî唌IwâW\8 ¢Ç„ßnÙ§JÎM†½ÀEBR”@dl,(È4ÀÑb•JަÚCÎ@pUø mËκ JÁÿxHƼš ¹f…u`1ú‹Ò@ÑÒ„íÉ8vc‡•rO÷˜³|ÕŽKá™ÀåBÎQ½?Ù Í,ð‡5ð¸§rjoË*Eˆ…Pÿ¨ð=!I!àŽÇ7vùtÆß„oû]ø £ñÔÝžÂ/ÿi aÿ̧ ÎÙ”?:2L$[ˆN ÓðpÍ C×) Ù™ÙLR#þ&â‚"Ù Šû¢·Kcx´‰-®U+t7Nš¤á?'ÇX›¯£o~Úvþ¶ê¬Ú“]¶®–ªúH”d #7-ó*p"¡ ÕE@l2Äè95[x\“¨]ò~p$•(±Â율ت®ÓA]äG]eѹÇüHDä€u>d§fs}ŠÖ¤¼»XÞMƒ¤ç¤ºh ¥Ý®‹„ 6D›‚duè4š$FK²ˆkÌ>!:ívð_Ãnºæ"[¼´ ƒÓº¹d݈±xØ´ÌOë§óƒm°ÙÜ» í{fîJÛ_Öå–™ÿŒxIŽüåo&ŽN3£•Ú.âªho´¬ÆóqÎ2õ®ià]~xÿ]uRQtÊJã!^X©§§+å(¨-þˆØ¹‹”™›ëbUU7ŸˆÍ×T•Õú#ÀÝ©ó] SÜ.ÖÌdÂÈ)84îúgbSs‰jNç§²S¦ÅGxn©kEgäžJ5©’ïŸ+*ÅIsx<ˆê’‚f8As**¶hÜ ÀimÙʸòä¼”}ú,M‚tÀÛȈlE€½ì À„Úç¨Ì°õ-ôúêM`ð}öÇ/Д¥'65É:.q'g‚ÊchƒF¸Ð…¡ìzФíËãúCí…(+‘.Éño¨ãq¾–“›‘ùXSÚj=tÉ4 a¦zæÂ푃)ôÓSRfÛ°CÖ¬QT„ë\µ!BA³•.ºÉ¢q%Vdâ®Ø@ðkª¢†3út(‡ Ú"jظØô =è3 ÏP†ýÈkfþjE…þ²¡ª¡M[C×,f_Qn{±ôº×tþµmí­ÒÛÿÙoü…žg"›W˜_WÈ)[u¸?…v/z{”ýwd‚ӆБBéä1=Vwòx'ía@»¨a]¸¿êç.ànÿÑß3CÔFéM ²}\ÊÌMíãR$…ùŸ¸dhƒ}º”ý:@X*CJ,ý\ZÕ3&Ê+Ú+déb°Þ Z}bjVZi.Ôq5‘eÁa¡±þž¢ß¥»ºÎ3iÁo£©lICeõÔ”8á09öHSø¸ÝÚ8À½èÂe¬!KѸ±þn*¾ož@.3w/ìÓiã“Uá®^±ž´§ €Û?| ùº|&Gø#Á¢$ïM°)Nú+UÛ%ý ò½j&ýüç$VÙѰÁ#cë(b;v&CF|;']>YV^%ldqy†YŽ/y’ÊÆÇù­[@#[¾qÎU4Ç›Åì*8!%¡œÅ¯#^Q㬔rVŽçºù„#:} }(ÎòK ˆÖéÂ4‘-Í#aj¬ç©™h†3½šÁÆÁ.}œ!4UG;'±RrÏÙûôº<°>Y¥‚t‡…½¾2µ,Õ•À•‹ŠJ8*?½bZÎ@¾®@{\£×A4×cgÞᦎáZƒo÷YÂÄïå’u„%Ùp¬*éö†SÂûÆõKè6gÍO†‘‘?NFGœÑò2¿ ’wi“w' 1^n!ËèŠ1:´>-Ôô74蛋k*b¥2‰éæLBs·¢±×.B{yw#~Ëã62ÚßG2‰¼O¶  ‡;qªpúªzú“ËüjpªôûtkWâMxWS¿jý¤éòµò‹Ô­\k|¯~yÚ|X .)3|—lrr‰vO¶Ù¯ð¸ƒºú?M@æ±R>Ã"¿D­ø‹á¡¶é²"K-õàç ì÷iVyz:h3U{c!–ó©‹­8Q]ÜÔØ6ÏŽ0¾ÄLe»P}Çäæ-GšÂjÂŽ^7?šŒ¦f©íM‘š‘rÐEA‰ÉÝ¢jÓoÒWäm¡Çñ•¬)þUÖh|Z„žŒÄ¥ÀɰÀy1Ì'Sj܉·§>½iĨ&Ëêï\PŽ‹Q]X)IÀCèÆÏ„kmmpíáCxwÓ&xw¦@,öóí‘§µåTÆwÞ»!FÔìÉNäëµÉÚÄEäÇUTä–•îªóÞ£ÖmVÅñ-^Dë9~Ý<¿"¿ê(!,(i+ÄÀž´!œ²›‰×8ŸŽôì\ˆjt¹wñƉÄ+ïÖªÖV®‚)N»w²~sfB=@vÚÑŒC\q§Z«¨B3XèïN^#æÛÛ/]\JMù¦&Á!b•«ú2ˆp² ÚsÊJ¹ø«p ‹Ž†y+×Â[dŽ€SbxäNœþ>æž“~_’Õªž¡$ÕH“J'šTc_¯¨b•§hü\jT«‚«ƒ¨s‚÷`ãàÖè®êïÉyœWBe$F·?^'$«C£·Ã*8p3¹Y{8ñº.}ïuU>¦"[Þ7'>BË{Tüšä FIëyâdRŽ‹øé*}‡ÁÔùNkTåW°ÊçÙÒ5¾5°Ö×'(Èǧ.¨¥ÙXÛú»ß¢cÓ·X^m÷~†×ŸÍo³RÞ–l¥<™Pµ%km-\¶n©ìúñ³çÁdt©*-´¯ì0.ïõ‡‰:ÝþÕ¦ÍkÚ—eÑ6D¦:O»¬Æ»8ZèØX{e‘œòÉCÚàKbŽî)§â¼Â—Œ[@¦¡]¢JWéѯ¬ñ²^kœe0dRµ·¼ñIRXãœ.4{Žò·ï; ÝMTËî]5‹´½ÅD:DuÏæÿᨈ!ItÏB³ìû8¸»=÷ˆ½Zq.•¢ô"½è휩 öÒ½OYÙïdEï4 j1¥àÇ>ï gM^ëþÿ§gƒY*²DFœµhõ¡JšõíÄT–XÓþ*Ã-èöåäÕ«ºJ:eÈ!#ǨîeüŸÛí)ZÏjýIƒ‰ªíÚZÓ˜obþi÷¿¾5ðíû²Rvü¯o¾îèª-Ù9ÿ?¿9ø?a_x6wðØà®ÚùdZjÌ·M!®œòþ¿¿gn%´à ãIZÑ`y’ŠéJfƒ£­”=èŠßó…, ¢¸%óh™xÎx™rµVS˜·¶sÁ¥a eõ]¾WÆÑdŽ#IW)…¹Yï4-|yƒÊ‰ðôs‰6¶·Éàèµ°ÀWø™\á=`GCbÞîj¸ ;'v~ 'ÚÂ"[Uï~¤ût+Üï`þ÷¦ÏKŠäwg…åC-wãqfã—§ü–n Þªjào«Zá÷“CQÁeî”Í®÷6«”f¿¿ÙmÑH2OäqÖý‡Ø™ÙâÆJY°”¯‹wtnkø ¼¸Ùö»ÝìÜNß»w¶¥®èU¥ÑAvä¸ÿßTçóŠ-uu-¦mR$$‰­E2܇ƒäøK·œ/ìð-< šï6ž !·S]¤ÈƒNýÅB®'—j¶5õ%‚;àeßlcJ?P3~ÇÔ‹²ó8— J.åbÿ5;,ß{0!i!ì¦2;Q!6œii«AÅ—WEøžCvÜQ³1Ø~ÅôÕ'÷”U7–œ:ã›·'Mu¼¬þ°¸íK. Xê²X ÞÄ7~)vZÇI‹ú*Nš5ÜÂ×ëME·§Ihé_§wÚ¨þŒ?ó׋oŸ‡ÜÝ]4ΠyËßñ©ÚQßV^ýÁ÷Ã)zU]eë¡*à¾H]¾5^G¬Æ% ~Z­.Y·_§ÝO†²'!. T­ :óÛyªa¸p´^BMVy94qm!U›}ƒvxN¶ŠVgéí¿é }@•¬/µ(%—"Kêõ‡Ñ)‰rå¹´øgâdiŽâ˜6=,F§Û³OE~êyÏLM”ÍýMîÿʼFøêhv'³Ê'ôYž€¯˜õü2íãq¨åyùÖYÜŠci_¤÷æ‘û„L ]¯ Q«p[™|X[Klû-š•gjïÓБ,Ap‹^Ÿä `}axÖj³4Àí…„Ýi£Þ+¾$Çv(SÕÐ~.›vŒG0óAù«L$æ‘®éç}UFÃñ2zø³>G#÷xXùæ½7q(Îúá1Z¨,w;&Y¸©XA¼3Yq *©öŸ]d> 1ÓÜ•æƒõæ ó?³ËÊ÷ endstream endobj 15 0 obj <> endobj 233 0 obj <>stream xœW TTW¶}eA½'"âð¢Äø œg$ÒIˆQGEEÅ¡@I™•y¬:U ó<#–"…¢QŒCkÔh'Q£Ë!f šNBÎ#—tÿûMV:ý^·X‹ªºõî¹ûì³Ï>2Æh#“ÉX{ÇE›lÞ–þ(Ž–‰o ÇȤþ:¡;ÎLå`jÔøÖˆýðe(n‚³Ì¹Læ°ÊÕ>pOD—wˆådû)–6óçϵ\èïä³Ó-ÀÒÑ-ÄÛÓß-„¾ñ³tÜéã1Ór¡ŸŸå:éÁ–ë<ƒ=ƒÂ<=úζôßâdéèáÀ0Ìô€@û=‹—9‡, ]¶Ïme¸{ÄNÕžkœ¼Öù8¯ßàç?gÖ6o϶ýìaœ˜ñÌZf3‘qf&1ë™ Ìf#3•qa61‹˜éÌfÆžÙÂ,f–0ÖŒ3‹±a–1³™Œ-ó7fãȬfF2£3fcÎ c†3#žyƒ™AbŒ_æcÙJÙÙ#ìpU>A~ÙhˆQ¼ÑçÆoPŒQ²6lgÍ55Pm2ÖDgòÛ S+Óóƒn4“™Eš²zÈ'æ‹Ì]Ì÷›Ì<ÌtضaÝâ ³nc0ˆ&zÊQ†ÛQ&`ÿ­ûY2ÀÞÑûAƒÄ.ÞXÅ^Î%¹é b+t·á]ŸB…š38 ‹Ì½ö«'Ê‚¤ú?7°fÿðv “X/¾©—Õ¡)梩\¬Æ@G[¿ 6d®í8òù|ÚàÜÇ/p˜@td-OÞø þ§¤^YÞxªØBýž¢ÀR/pWnŽð‚Ù¿åÓc˜hº”âŠ2t7È.£•¨m–wÇvÛò*|`ï|fYåB° ñd&™@vwœB¦ E34)JÔŒ…2ŽL'¼‹ ¬€ÙÅÎW¼|/ ð}Á§­¯Þ}™}îv«%‹uqY \è*•F²Ñ€ôâÈzÙOÉtzA1 ãƒÀ{„mZUØ($–j´û ƒ”%aÙpH(ÈÐAa©p¸ä”÷y(‹ 84-ÎìÕï+VºóIß½2gMœá®=…2”§/ Ò Ú¨L‰}eZAÉ kî­.Ö€ Jeÿ¤üÜ,G/qã d<:»)4“]'ONávß'u¬ÕƒÛwZ.ÞÚÝ\Øåþ~kàz…TF冧 XlèÃðŽ’wwä» Šµ%xÑe :NÕEŠÉ=,î2°ú\¢[£ûêéúj(ÒVx ï‘Sÿù9Kë†B˵ý.?Ø%®æ_¥z»`ûj»’«.øK~'A,;ézÀ/•wà¾Aо£À…éÆÖ1N*E#ÊYyUãèð½^êIàF×$𢱢QO'1R±õº—ÐL×K¨—x!=`ÀÚv&©Lä 21^4ã3 Ò2¯g`½Ôjp‡= †uôluyR‚4I±J2d_0(BÔKè–X {é¦+,.î–®Kª‹BÈÔe•r}’Õw@·‡8˜Ï(JÍøH: @E±t‡¨ÞÙ¬³EHŽUŽ%y„Åã Š`µ}þ&Äfº§ƒM?•—š˜ I NIФ, kGK¤Ý!ê¥t·/¸‚ïnœÑ34#"-¡,r(…2K»°xT)Ì •ÞZ”CjzF±$cQÞ£{5ÚêeÇh‚Ü¥î ÂsüóE—‰•31Išëv4¢º¶¦¬¡$¡xŽ Ïª„àn4yÎWîdÉÛdö"Ÿ…ܾO>;ÛÜRªÜª„6EY&”—ÅA¤r• ¡‚#²‹üŒ¹¾[Üõ§¿B¦îûC÷\þ]ÞFÉEñãp{^NVæS°0°kh&¶ƒ?ØAT9TjÇr¶Ç„Ü6Ƈÿ%1w³?>AOrT—’–É1[ TP±Gu_CÔÂ7½ík»’Åæs}´ ò+êZääee~)äLò¡YWA PIYR‚š¾ÔJÛ)“q°qó«LøÃ†Þ·XœEÖѶ7):2!aX¨ØK:ÔQYk†#ô\6<ìP†´™Ê—hŒr2ÚØM¥¨Ô]§ÒWKeLÚ³¤¿„ÞÔã†6ªª˜#5îü;ËÍlQIQIaiÛÆ 1´ ]qŽ™ñŒŒqÚîë®<äÊ?s®¸™~gdøòí°.x—ÒÏuk¬/,…]g"ËûoO¶êÅkY¹Ä…xqŸžŸ–yU"®:ù•¡m…¨””DMŠT‡È¬•*#˜"H1rê­Œ«,:öLHŠŽ HжÛîë°’!bÒuÚÚ\hàôÁeþ~Áa>[[Ü.=8§¥T0S¨ÌÑÛ@MÄR4‘‹Þ8ÏØMt’¾g™5mOV€ÓOuhq$ŽÌèP'i4µF™’u‚8·cû«ÊòZ6}qXB=KÞúÖ'¡Mr•ÎI—dé¥Ô[ûÅg;Z²£Æž3vâlbIƽ˜ƒZKô'•.,:ü.E"Kd=Ïx·Õ›¢hs æ€ÃÿNÝLyƒ²îbGz4AK„~÷JyûØÞ*&¶ÊÑÐ=‡ÍÑh÷Ñßí¥ä½®€Pfor„zŸ&¸•¢B÷y¯Uø¢—¤!¬}pj@šF 在gÅøž¯s¢µš<°¨„ô ¥xŸ…r­öpZ±®T[L‹DH;šŽ@xBh:*ØjÐAeJM²V¡\ÏIe«icAç|¿Ï¹Å=—‹›p/_‘Uµ w·µ*ÝšóÖJ–`Î2ŒXþ8 §á´S]E!ñ€&%*Q¹wÅò0Wºc‚G_TÖéš´'ËêKŽ/7ÐBÌ"¦ÚÍ«ž3Ñ Ýæõ½ömZÉ»+ðk½‰€I &cÈ$âE¼Ð’Xáº,Ñ ½ÒC®ó+`U燮Ÿ&}C­ÓÇ©›n´Ü¼]ÕA Â%UÍöks©æOŽ™·Ù!Èg½ÊN2:r&Aªå‚lïóPØJϤýÿ#ßWà»_?ú™éÈ|eÏô>õPü¹}á›b'Ö0ér˜K¬•D‰íŠ>¯K¶Å·Ÿß=ŠQÇdu0¸+ýßÀü™½¡@*Á ŸÝl ¨ÎVÖV¦éR’R’!Š Ë?|8¿¤¬2⨛Ê=,"Lp¯ôÈÚDÑÖ¿¿Ä/Û½ÙG¹?<›ꚪbWÙàDÇXÇ9][†«ð‡çï>Y[”+¸V®„Ù; I«Êˆn ºœ©-ÈÉãpP:o Ÿœ> Ÿ<~ Û¶ƒ­ò"qå?½åâí½–ºÌQ^®^Éd.˜h}˜Oè±Þ0¬¥´9ü xXÊÍèzým8Ͻû8 =Ưaú©¦ŸûEö;üR4ÂÑèò½µ> Ëèroó9çý@SÜ?sŸåŧF…k¢4ʤÍ~a°®Ç?OlO¸C=-èRž Äzúœ›:ßi½Æ–¼+ùžy1RŶp¼ ’cp·œoÚ]çáîçãéYçÓtR_×$Åd9­ÞŽ?øÇO šÖÎÕ^ÿè(N“d4ÚÐÍ6Ê.?ÃOŸÉ1C\ÅO.O¹ ù\›¾£³óñV2²LH MI¿ëB'Vr )šØ8Aµ%¨lóÉ©tÀ·À†È–ÕoÍTžs9’øSÈËÐ\uyX^TM lâTaï£ÙDY‹ãM1¤î{åúœ V›•-äädåUU}´íA”46Ìú{W×7ŽÏˆ¬Jʈ™—¤OÎÉðsÉœytÏ盤ØGb›Y(Ë|„ã»ßó„LS)îé~„cð1üîIÆfšøäK¿Îœ›Eôz[¹*›N¢Ø×eű§éÅnþÿÒ »¿Ô‰¡,7q-1!öÉøæG‚8ï/z¯ K¨Ç€ÛÐñ!¸† ¯r'v¶õ%ÎÿO=ë£Þ4Ý¢iª†[¯ÇHym ó‡uGߟ¼ûZŸ{œ#F·.õ= x´´`%LÇ0W`e÷Ï]9Qj÷—ìÿ»¡ÄnD¢?&Gêe­È£—ã"üO5éò‘óåÍm'¯ÑR¬O© òL>{8¯ê£‡õE-—v~<– %vv$ŒÅQßNÎrê2hßJ˜³S@¹Ä¯„ óÉ™‘z¸Yi?×ñÞ4Þ'ôGP&æ£In© ¥þ¨¿ã³²i¾hy)€L9­ JS稳97Ån”6ÚìÌ›E9Yé_R;ÆáríˆVQüœœg[¸emY•Ÿ—‘!äR‹Ø8#®ÜåÌÄA¸ø¹,Ûåx óÏI»5ÛŸYZq¼Ão÷Ö£Çn?ww½ßÉÞzì—ÈÔ²_Ke—Åår1®{=(Ò@ÇGfG…'GG& =¦ÿ²MЦž@m‘›W’–SÞÿ[ÊTC ½d$ËñE7ËרÁWX¸’È©¼páªÅqhOoÌãzʉRÅ6ë~†Vºº Yª„1ýé4Á«hÑf]D tÂrQ‡¾tÒM Kp:Ÿ`©ôZ+Ž~õ‚”y£ ¾ãÐÄòJã©+§o4¬¨«/;ÝìWæ—&4žnO+îyËövíÝUJâOöÅÆÑÎa±_œ÷š$'QÀaÇâˆæzÙç8¥Î“éã\·ƒa–§sU² ê –k ¨qw p³~¹Îôó¿øêåÙ o‰uµð¤úãËðw×þ Q£ùNïl>yàpÍñ’ӱǶfÍM7 ¸§ààú¼½>{ÕžêhÍ>M²:1 ™ÛŸ¥¯QE…A\AaýLòwKІï4L*ª4iAj8-Ξ5Æ*X Âõ¦º’s§è pr£5jHжØã ëÀ5gkQ‚.E—\4ÄîW’ª’1¥Ù:JY!7¿¾åf¼gãÈ]«ò?ôQ¶ç5–×ï­Þå¿;b«ísqÎì|Šæh6ï1³Ó5ÞW¥4‹Îí^”K2²pG©‚lË` &($˜Í-5x,ËÔe¦ƒµ¦f ó¿*Ø£ endstream endobj 13 0 obj <> endobj 234 0 obj <>stream xœcd`ab`dddsö Ž´±T~H3þaú!ËÜÝý#ñG*k7s7ËÜï÷„¾Û ~·áÿn)ÀÀÂÈèæ•æœ_PY”™žQ¢ á¬©`hii®à˜›Z”™œ˜§à›X’‘š›Xää(ç'g¦–Tê)8æä(t+¥§•¥¦€mvÎÏ-(-I-RðÍOI-ÊK,²3‹³ú3™»˜™fñýgv`X»à‡Ô|Æï G™¿¯ù^"º´òtü’Ê¥•½Ý“»9æNŸ=knýÄÆ~ù† ÅÓ~3íþ®rZbjÿŒ‰Ýó8&v.Éû­ª1ë»vEùÝ’•ݵ5}µì³~ëü}Z7¥µ»(Z_]S1£uj»üwŸß*Þíu­Ý’­½Eë侫¾«ùmÀÚÆÞÞ2¥dq÷²îþ…s8øŠÿ´_Àö[h2ûN®'Ü;gñð00¸‰F endstream endobj 11 0 obj <> endobj 235 0 obj <>stream xœµ”{PTçÆÏÙ{Ž Ù£ÙƒÍL5blKÄA Bb©\.ÊnË å¾ìîËeeÑpÝ–…]H@.‰PAŠ¢!˜š –ã¨525ޱ¾ƒ{Öë´ÓþÓ™þwÎÌ÷¼ßó¾ßû{HÂAD$)ö s÷°½Ä¯$ùU"þ9 pÌÔyGp¢ÀÉ¡{“ó4’-C›ŸBk—InÙéŸ’šž”¨tyÅßÕÅÝÛÛËÅW!OOŠ“q.!2e¢\!S ?É.á)qIreöZßäd—0»"Ã%Lž!OWÉwÝ»Ú?E‘š©”§»„¤ì’§sA,åÒ3ƒdÙqòíIÉŠ^óx Þ!‰÷‰5„I[w"ˆ!B‰ Ä2b9ñ ±Lè…  ñ#ù>Ù-Z/§^ J¨Û[ÔŽ~bR\$þ‰.»Kn‰%–ܱóXùU&(n‚âßEe¸Ê.®oçþ$pù†â½Œî¶¯*päès†’H›é¨’r´¥b:À #`Ñ2Vz[>aQ(ýÓ—£gÎÔí•âüÿrò·:³ä.™{ú…œ›¦Ð›(Or£ÿÚC誤ÅeûJ!•áZ L¦Úv[jGŒ'·.«TªC”?ûuTœ´ÃyhîÙKûiö°÷;-4ñ+ûvŠþÈûIªiϨ€ÍÞêφ¥è;¯¶×‹ÝhÛnsÚ@þqh„.øØjmmè`ÜiÄp´ÒÅÕC,âé%<¨Lã·ù|+yü&Z3MñKù9I_•~Rj¥ÓµþÀÁnxR+®“¾Z™ŸÀ.DÓ;·G¨¶ÆR›ÚÖ=Œy_[’2-/>`"äòw×O#‘T˜Ñ¬A0rŒm3§Mäáó(vbª…âLažýÑ}‰]QuÑÀxGqƼVsc£y rÙÖO›ú9zJîÎÆÑø÷/x‹Ùô}úøGúÒª ŸÓì©lˆN8ÆÔ4ÅXIã·ïŠ.KÚ'?+7‚ð¢œ6ö€´.tHÒÖ(!Š´ê²Â±ÞS¨­´öCù K7˜„‘¤i#!ä‚ Ì.ƒº6¹.ˆœ£Wƒ¶¬8G‘*&9« Xè®ê6gÕfç¨ 9ù¡øáÑ¡³áYÉþ_…-È:3ÒBvO¡¨‹ú™Kòã!6£1ÇÜj¬³N¾=¸/Zû<~?ówW䈜mÈ©¦¦4E:M¾†Í ˆPDºq½Š6^8Ö{2wWëãÚ©Fäo"mS¨ø Å/G¹’– 0ÞŠ˜Å‹±øõðRìü£¢Ð“GѼ_]UZ¬U«µlš×V¥ ÙKÈ—5ÒåF‰¹_iê€9ØW—' ›/ª÷6}bFV=7N^§‡ÎKÐoÄhÑÜô­nWðJÿ3‰¿ª,Œg:èxM¡¿t/'6WÌ,Ù`Ì÷¶Ü_sà«EF j£?ª¨>,#OÀŽ12Àbìeïæ©;gL?Z~ƒDäY ùñ ‹ª5%-S•ª0g™;›,-R,Å¡Ÿ×” X´=†jP¸î ŒÁÇvxƒÊô},ï@?¬:ïØ¿äæù fQ¹Ðü¸ÀàÖÇ ãQN,¹K­›û—ø±s9/û·Ú²wöíÊ»ÑüK£ÿ!·¨›"BÕ<ÿ++Ùx'šº³ŒŸ‘4 ZMÇÊ…C1Z-DCD@†}³ÇuM{`/¨5ÅÚüêçŒ=yÐUj P¹Â6 f… ­¯„Bš]1 ušƒÙÕ¨N®MÀÏ/„9ã7xµº*ìŠã`J­@Ï#ÅáC9Š\øÙYŸ[UVÐWêëÑF¾Á½¹Ð ÏÕk °¢ªªôõÌýHQ™æŸ5‘SÈ0Eñ%pQýׄ©Ø‹þ-‘ð.pñR‚ CàVí×ÐçóeÆ ¸ ÇNXÇz¾­øÆƒ¿‘ì ¦,Dœ†)ø“°’ß4œjœ<Þù)ô˜Ҹ¾6 6A lŸ‚Ð,, ÎJ„à<º3‹­äÐ,Ú}‘âƒÑ&I¦X“Sü^á¾’¢0PƒCÄí­ãŸ[Ìœ.£'à&ƒè×.`3¯¬ßq*›-õ]YÆ”"-è4R㹑£À\:°Î3Ò7l‹£°Ê1ƒ'é-·_ý½hF‹¯MšÉs×й`„%9º21…zh’_ê}{ þe`bäï¼[¿àØ.µÕžÌV•)%#-OîqÕÏÎû•k·¾÷ýjM£ôrÛè×ðgfÚ{ÌíeßP¿¸Îâúfs½­+£.³ôž©Þs³ 棉\×,M8Ã*¢“4©:f‰°?>ÍØRRˆ±ì m}bâIé^&§E¦'§‰§ÅñO (J endstream endobj 9 0 obj <> endobj 236 0 obj <>stream xœ}•yPwÇ»˜î4šd<*Ú=)oÄ”.¢o¢Þ`"È1ƒ09GaúÍ7à ×r(µHD<’h(³P¨åjÅd£ëf7[Ñ*êÍø£Öýa6ÆÚ­Úê?ºûß{¿÷ý¼÷},ãìİ,+ Zâ=þ5×þkŸádŸ)²Ó±Ú±ÅÜdàæ|jímŒšŒ«ÞBÏIŒŒe×nÚ IÔ%ÇìÖ*ç,P.ñññV®ŠW'ÇDª”*m´:^¥¥?qÊ`MdŒZ«óT®Š‹SŸHQ©SÔÉÕQ/ShâSµêde &JœÀ0Ìä€äµë´©T‘Qê-Ûb‚Cbf6ÌÌcæ3Û™ÌBf5³†ù˜YËx10™¥Ì2f3ó6-‡á˜ æ;v3ûƒÓ'Éé®,Aö•ó ç:çç.rùn7ø‚õø 3ñ…“¥‚ɰ9Üml÷{Êq™ƒu,WX%ã‘|IÊÒ aÞ{¾ÞrÚ¦²˜¸“…‹ÉBü=~Â÷+ƒ¢Ü<(È•Ä<¢œ·Œ0ÀÏ!ÞÃX‰Uèû§ ËƒD¬MY`(¾LVqâ 6Bɀͮ´°ÿìCî– b¶âïçÝ6›¥³©ú¤”ÚœêŠzss[ìñÿ«¢sD Y9á³]’¸ë¥GöФ•SçÝ$$q¦n°A ôÁ oã²àÍá´g Í6¼ÜÌâÔA ±Êìç+c9IòoË!T;Í…fÃZ¡ÅtZá<ôÀy!•ó7”±ô÷¤ô€·hÅJÜ;÷€§°«å¦âs*äè5Ud:o•Ód·¨ˆø¹Í¾à¥ŽRq¯âLañׂK1l‡DÐÀJ£ÚÈ'ä¾7eï7pĉLÉ›MVQ±^—Kx].Ìáþ."¸æþ½–«­bMD³¦øb£ñ7™ó¬vÁ†>ÇÙŸûQ°ÊÐÝ>_JQb Nn˜½ä>ãÒÁ¥qFþzǵáª.˜[›ø©*!òøc†ù×}&ÏbŸÙÉþÒQý2üÂî¯øÂFÎ;tõ*ýÅK>àÈ„q>çà#yÂÁz·i*3›’†á!´—ÔñFO9º–¸Ø¸­¹ÇzD|ÎÑë,•ÃÕ6ÎI†»ívÅ… ¦ÂÅvA }vA¬‰Oâ†+ƱáB³ €bk3õA}ú í5ðì +½.fXŽß³°ç¾Âˆþû´ð1¬PÀ œRý¬=¼,øA>;i8VÙPÒÜ”^~(ÿ¨$ˆu7.[Oß;æ-†q[ kò‚ã7Gëvƒš÷{”Ú?Ð×zµ^0…5Gv_×_uO¼¢ â>IÌËŒ€K]ÂŽFÅÒÀ°ÝQÝ'+û¯µ ='ŠÚL<½UyeõC#V¶ý&ª†eøŸ)Ò5­iÈ«4·žZwÙïý% È»dúß¼žâ¤VäÊ‹¤B½^’2óÅ$ß ´pà7ù]Çù¸hdàúÙké!õâ+<XPÓ9ÚÒ'à Žß erùÅ7}é\Î÷"ÓÈÔ'‹~Ø5h.Ws8áûsnÇØâu‰Ú´˜ø˜£éÀ'̪Æ`Ü…|…­»3iƒXy @÷{5©Õ¸ÆÂž¸‰ú~™}2f)ŠŠÀeüÓí?ùûÞsÉ[dÊOî£èÜ5Zg>½dÈÊR×…Äì„poLìŠëƒëðo¬V˜qöݶsp º7‰3Íátk„ɰ:–[ÇJsGæX†O¨"óГø?2›x‘0†siû/Gœ…^¸O ƒä±‚ÈÉ$”cf㌿þ2ŠÓ‘Ãäy‡œ“økd²óÎ3+¾c±·Óø#èkÁÞ™=¾T®}÷q àBþríCúF¿†¶ÂÊ3B ™X¾ú{àG‹Ñ«¹ Ìú£’Þ êÝ·§ÅÂV8ØŸ~›'ËŠYí>(ü„Ç\œú tÆw•$“¬\ï±>\ø¼/åËÀïMT©µ¥éå™"ΪVDŒ5>4ó|}k]û™›– }%ôÖŒ£iÜ4];qæö)…¼Ø>¦¨×ÕjSÓuÚTkzC}­µA omý•’ÿ²È?B4R‹kŸ”­†c§E»œûµy¨û{4²Ý=x»Gfßø÷?bÈÏÍâ7¨¶5m†és||çÄ™Ã:Tbç§§òþ|ðd^ofYþÕ”“[ ˜Øå·T9ïKTêÉ"õÀçIRšHB9Q:f6·V ÆB0ÕžéÝðÝáà‘½ûxôRú¹l«¨ºZ±·B_h€àªíUZsò MkN´ñß\z8:ø™\-Ò0fàK¡°FüuaQ·à[X¼LmÖɱB16"?D’\¬òJô­jAO°ÒuP"Õ@hù±³Üþ‚ìM’¼ÇØk¼¡Wê‘x›†û° œ q–ƒz¨°•[èIô€ê„JâûÒØÙ/¾´¦Nº©dÔ£k’éè1 Å }SZrµçt±ÍH¥½ ’´Gš¦¡}8nUURYæÓÒÒ%ú´àbÏäˆë«í5öš.Ц º qͦü¢³":qßÞèØÝ±§}×ô ]ÙaÈäuº‚¬W ­Ð)Õи}]ßÅO̰8ü-¤¾5%r^ÊÙÞìwÞtÖiÜÞ°”¹¹õWºM`˜¼n:€ endstream endobj 137 0 obj <> endobj 237 0 obj <>stream xœcd`ab`dddwö Ž441UH3þaú!ËÜý»ï‡ÿÏ&Önæn–%? }·ünÊÿ]_€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMX휟[PZ’Z¤à›Ÿ’Z”ÇÀÀÀ’–ÅŸÎÀÃËPÂÇÀ t(Æý OËø~tüî[ð#mñÌùŒßsÎ1_ÿã¸h÷åî…‹—Ì»hñÅþ =ýýÝ9¦5w׫E8wÊýöfïÖí®.̯­-(ðiçhiéjlœØ=µK~[ǃ²nuŽßQìÝÝ™ûÓ¶åži^ÕÍ1}r÷´©­Ý=ò6Òv4­ï˜ÖÝÛ½Žã»{÷Êî}SëÎz/M™ökm÷¥îå|ÿE3õ+è"îÍÌß&ŠÎìžW^Þ]Q+÷ÏŠ½¶»bþüîy3倎?¼àûûùŒ‡ˆ3ÿðÿÞ'úÍø‘ÒoF3#%…Ç&_¾3>xòEêÃŒ?2À|x[´ûh÷Úð +¼§dws46v7@|p«mCÜ”ô¾†îÎî Žß@ævGô6Îð<]¸©á7Wf·Kw>ÇoönçîÒâ¢ÊÊ’b×ö¶®ööîVކ©ÝSß?Ùw¹Wî;0|^vÏ^º|æÌeËNõsLšÔ3âý„>³Ýï9øJþ´_Èö[`ûf®Ür\,æóy87Ïâáa`•BþÇ endstream endobj 30 0 obj <> endobj 238 0 obj <>stream xœz\SWßÿ ›ëVèUPŸ{ݶj[w'®ë@QTPÙ+HB Ìä„ö$Ì0±nʼn#¨­q¶¶Z[Åj§ÚÚçÄúÿüO øÖç}Þ Ú{ïÉ9ç7¿ßï¹áöv‡Ãá-õðôœ6Õü¿L#8¦‘v¦qÓQœißë• ?ô·oùžÑÑä1æ ‚S\gÅê­K#"ãøA‚Qï.}oÔ´¹s?åæÏÚµ3|”ÇNA ØN¾µ!bW¿ îƒQn¡¡£Ö›?=j½´??Ö·uí¥a‘1þ(ˆÝþüp‚ |ÜÂ7/‰Ø²4Ò{YÔrþŠèŸÄ¸Ç®î\%ò[·Ë#~÷ÿO÷¬ X¸>hC°gÈÆÐMa^³?=gÌܱ®ãæŸ?aÁÄ…ï.zoñ¤­“·MÙþ¾Ï¾î˜*ž&™.‘0sAŒ!>%æc‰µ„+1ŽXGÌ#Æë‰ Äb"áI¼Kl$Þ#6“/b2±™XBL!¶K‰÷ obñ±•XN|H¬ ¦ÓˆOˆé„;1ƒXIÌ$V³ˆÕÄlƒøˆXCÌ!†΄áBp‰á„=1‚p F$ñ/‚G0E°DbÑ—Mô#æý‰Äb!1XD "ƒ 7b±p$¶N„ñáKÐÄPÂÇ O&$žsb8¿ÙM³ÓpûpeÜöÓìË\dÏÉT^_^ïWÊ›ªîc×gCŸûF÷ý«Ÿ¼ß/ýô7 ø×€3Ù9ƒ8ƒ¼³¾p9étìù§Ï–D|Ê ánže\yÜû½ÇIÈ›ÌÿÄ'H$b,뚤Γ…_ÓÐ *ÉRóø( aÇ’> ­Uì24a!œà ­ |ë£(ü¨”²U$ìb Ò8Äâh¼n ¾û‡ušh `ŸÂM¿¡M‚˜7™WtYk€>ÇŒPbÜŠ`‚3M'h8„ü®Ò#Ø/Ä};Ž„#è«•GÏ€vêöšˆË XRjÞC (cë:¥¤Ó«È^îQ’ÐárÇ=ãÖk®¬;*¢‘Œ… ù]ÃïÝkg²xáTüÊÀ¹`„5F®)†â?ø Ù#ûÞECÓOS ´ûégèÈ híæq÷Ù׮ݼuuåÔ<»±=„"<ÁZ¼eYZc±ZÜí¼JPÍŽA‰ÒÓ®pN’Î¥ºÒæ@óãj¼y ßE—Ð*>¯çìg›‰W™Ý”h0å8ðúe®IdºG—š°¸´¤”4F‘ ü`ývífœ[46a8Z‰VAü/ ©ï;žì‰rW°)ï¹Fûjê¬?á$øÞ£?;.ŸßîZÂfÅgŠÕ tZ³]ˆo€àõ®¬Tã Ü‡®PC_ºxöÊ‹KfN^¾rù‚ÀÇ'4ÁþÐÎ#ò&@AÎ/?A'8hú¯£·úÄ…±N¿Ô+JüßÈáNýÊa²Ç›—p?öçÓº ¨Aµ/ˆôˆ NNf—ðD fŸy£ÌYXÈC:ã’$ $¹U‚ ¾"÷ææ7±Oy 2(Ä ™¥HÏë™ý–¹—MîÚG)[Ù)!{®  ‡=†£à,8sœ„\XÄë‚o"i8Çæ?4çÙ“esgZÇÜÝ£ ròõ€Ûwîé(ºÀ`el<£ôXŸ$ÔBp¦†íÕñ9Œ0[èŽ[gM¯¹{ÙXƒ|P ôyóiÊÔtJù¶«7›f, D±|òí-Õ}OsVw£®þÕD«Bt P·É²‹Ã¥¬|@Zòê (€;ÍU2ìmb`ïŸ#òÉÉÆèÛ‡è[˜7€ž2cÑ+÷ØŠ RDôº>ÐkaÞuúx×À©6ErMKpLz9¦ÍX=‰8è.âÀ»ú7Fô8«„<ô¬(H tÀ¥T½”e2 œ›pŽËd¼Ó†nWà ¸Û6ö óröÜ4QòVPÎdçdç€2ªZ¤å b$!«?ßö¼ãþ¹̆§ë ›r œ2S"״ݼež/Äá¾JÆE[FÛJnA§”dzmÂqÙ¡¸+… VbLFÊ.Ĥ )%éO;´Z™–ˆz>® ìeÔ‘-È’.AV~¹¡æ±ª$«’R‘9^-¨OvrQ|9(- «,»’êŽý4ÃsƒãyãŽèãk²k¢+CO*JßÓ;“r²’YÊ»¹ñ!·cÛÆ :Ú¸°þEÃ)ÐÓa¿ÙA‘8÷f˜ýmåq(U8ÀŠJ^i7bN´ÃL,Ösõœì]Èg°…²zÈÒ]ësÌXEvºZ™Iu7xÌyƒ¸ð äÓs‡ƒdI]wîõé¦3u¬Û„E/j»‰ êcÛäAöEï¢Áh–Ã.Û]ØÇš± ”ýê@ƒ"º¹ ~ֳƮ®¢ÔAh€=¼C‚Ù°3 Wþ³Æ:Õ¤Äâ–¥­aœZwÂ,dÄ?HÚb›÷Öb«Hަâ¢\S½­—½³m•ÒÒ)Ýc»2õïY\9¸ý c1ȦšùLû œ#þKe.EA {RãRB]”dZ…\—RñLq®y{™6’p z@éü¹ üpÏ…D T9y ˜ª‰+çGÆÇEíÜ·«õù1è\˜Íô0ÛÛF݉äÐúp*NRS˜ÔÑ67@Í^z㇓zȃ#tŸ9« ¬VªZ§©¿=ø ÅŸ¢‘3PÿÇCGÈîûUÓÕµÇaƒs£ Öà|=br eòðÔp\›I'fÀ"…:©š¤€Ú`µWšØN)/$¶Ë˜݉š¢T¼ÂíW‘gvBž Ø?'E\”RŠAI^^I–ú;¨.:K©:£È·~XÊkÒuåßLÒ¥ò([·á! l¾¦uZUÐtñÇgVþ¸ÝÆka&]C­±Beˆ·òGÓ ²R ´ ”ºh£Qþ¨’×Ý5®[’swrþuŠÒƒLoÈ0©ßÓI§Öú`¿²#g²…>™ôgÛáºz= Cì—ñ6øÌY¸ìÓ›?߸vãjëO[Ž>kƒ±ØßëM·hÙ^IV$ >îfì¹ú³Æ™"T$\Ý™QX¦¬. EYX“º†×3bto Pv1¢‘—á;Îù[°â&×4n u ’«~ECQ¿É1óøb¤¡ó‰'5æ´ŠKÎ¥°1›7Ê#Àb°ø”ø{Ju™.¹}éü €Õ?Õ£^ÚŒ°‡&^¤ááX=ò@±‘è:¬‹„pue<Ì ?”GÏ|ì”ì4x΃vp½ðxñ¥Æ¢à.h–—zmÃ+­`YâÆÄ Q±ÓAOôá\Ó«¿<âBµ™² ìUVO÷¾ LzþîfmU™þò< ž·pûLfÓDyÚ'ôÂßjþN袨« C$îN Ü7\¡Â,T!uûɳgnOE‚^ܹSÚ‹ŸCÚ6Yi’ÚÿIþ|dŦM;VLƱ0w¸ËÐíÂùËpûeÇú‹"3/ùìâº[Üþ¥p½q牳Ž=sîð¶Më}}½Øit–†POoßêh×ÇëY]Quv±JY•R(MUQ}•¨qc¢·2h;+. ¬Ø¨÷—-ž½C\*b‘(–Ç„ %ü|™›ø$R³^­ïÀw^µ×wjs“»³r –“É $gšÅ–¬$±D©™ ;³$»€‚ýÐzââ#GË󛚴lMY>¸ ¨èfù.Þ1Ñ¢”XÝ¿{çÀ<ÄÒ¥P¡îO¬d“‹ãö¥-/oο¯>¾Ç©&HqP2ꄳ3Óód…  ÓØwà::„œ„ú¤sòÓà:8ÚÀW'‹ÏWjŸ‚ /\™¿›µ ¡4F²õ‘³¼T©*‘”ÆQš*#+­«½YJ›cáƒ\Ó"xœ¶–À5oÁéÿr ó8ޱªú-]¢Ç“awãN£·1œŠñèùôèÚ­Þ>릲KIèBÞRa‡¨ï=@}´üÿƃƒI§S÷0WoM•± ì+AXEˆ&L/Þ¨+ÕŸhЉ˜Ÿ‡)ÙdÅžøpüì'¯bdõ´°§¶î?w„þÏWàý=ƒí¦á´UßéU-¨ è•ð'm ?†tzaRØëc*#"bb""*côúÊJ=ÓÝÏ\ƒe×ü¯™'o…u´>õ[!˜IyíX;?Â;»n³³.ý°²\©Q–‡tI)älÑR•ê’¦|æ`˜A|k)êÖ㎫‡eŬßÁÈÜå”Ó ×òEþÍà„ËéÖ“7aßÒ÷CÕLVLaª¶[9[õ\Z|X2ã×¼±È'wñüÙŸwÿ6šÍVþ"(É z»ádfqÄ+“}#¦“=Mí|ŸñÀ?*0Ò?³¿p Ë”db0ʹ”^ ‰Äć/ú‚ã÷ÃþW'“é÷·úÆŠµFèb„ÎÝâÁù-ªwÄ[NG\:¥^½ÎÜþ‡üµ6Ì~¸aÚµ™i_ AžCs/ÉñA/D¢ÙhŠ|e]p¥ tZ;¥Þ½tV/•í}ŸüænZOC-®ék›>”ìQw0Ñ ÚÿCqнz)ú‘åîåµiå™3ðÇ3~Û¨ßH4èчϟ?z ýCy}ñf¬,…;K.º×õƒ^1Ô¼Ãd™×•›$ÖýYè¹yÝñÖeu ™]ˆ.%l-JÙaætÍéyË$“‹só?FîÇÉÖ©)ð/õÀ¥T€ü–žòò48žmƒýÌ?æÓ6Ži<­h‚8@…Ø>ŽÚy±]Íä±Õ“± €…óœZ;8TU¿’ARž¨»ãÜ}cÐ’†i-$§‡ù%ìŽ`$û"ʃA“FÇPGÀF¸ÊÀ)4)¹¦ì‹ÂnÂ<¿W3"}Ñ÷ÉkR¼”Ø©W·Ao¥Z^%r¬è„ +ºmh[šf GY‘rÎË4ª7ýo•zϪÈ[ÚœÀj¬Ý\ò1)+Ðf垃 Ù±²Ëö9‡âTŠ\~-ÈÅÏ«AN³•hÀ–v8ûòk(íð²œ&†?Ð%pôƒ} ,1' ÿ— â¨èramVÓÐpnŽÿ @>ŒÓ+”í—ü9¿>„ý!9£ÙyyÅûù0XF¢W‚Ý­BƒB­TãßlgU¾2W¡¹.í—O}yÿì'n³Ü×/µ45©ÅÀ9j¼€³zörC«ƒP$@v”7k4…õLlïÃ%†KÚòÌLPB™ÍgзdjYœY(»³« +¬íàùCi´–Ÿsá5S;}Ö/[.÷Kß”ƒ>ÌôaT~`w¦Ÿ*ª3éý +/ó`æ9Õ5Õ9Õ™ìóà,ÕYô0Ì4ÀíÇ£FOó1¦ù8äX ;é%ÇÚδüúÞ…­^ë=|—°_‡ÒßÔk¨³ï¡~¨ÿGó]×ßòuãôûâØUkŸôlŸ>þåîÊKn:f>j¢ç¸· ¯üðôÂê5+Ü7Ì1ã-¼¯ƒjl‰ãO~âÂpÓU:ëDP^Öüá‰Y¾ÅÈ×Y%ÉŠÕƒS®ÒPp=Üñ¿°2·¶àà½:`Â=l†i¬¥“ÐàïNÆ  Š-ËÎÉQcQP§â ãÃBÊ—a¶ãŒ[ßè£S×8q'ÌÁé@>žíΜÑ:Æ qÙ´ë¦/î<ºÙvëˆ^ ,ckƒ‹6c.¤P*@HË9å¹qýKœtpÌ 8á£å4›¼¹&;øý%YÔ š›Œu'Ëᇓ¶þd äå´DH€K(HWÊ$h€ó¸·Þ]HÊA``3(b¿ ãÐoÛÏH1Ò’Š+‰×5fÕe2ep Ãïo¹†âºøÝ2Ã8 `¸Ã!¸ áÂ{&{º%¬6ÄŸº§!ªé@Mc#ƒ.ÙÿãþäÝ%ƒ)ç±ãÅ««:¾3<ìXuÕÂZÃzúó„#>`3Øì³mU"µŠi$áù¨ý*%§ÕÙy ŠÒGk„ò€ôís..„T"³ÇŒê  ¦Œ9Àƒ+Nn€ÖˆßÐø: V¸›·7ý”´lsRrš $PLëtÕE-_yÞB} ˜ –‡¾˜ñç!»„U‹€ˆVãÏÍ¥nد/Ø´œ'Ol/ ¬´öýïv¯í´§6ú‹$É©Ò ¦$¥ñšÊŸÏAûÏÚü¢"‚"4­W´Ã1í0£Žmç4·µ·ý‰¹¦¥¯‡ÐÙ™9ýË%atŠH–Æ Ú¿—§')Ò@Š‹¨L\Q[ŽÕ;üîúΞK[¶ìYëæÖ²öÔ©–Kw˜™Ëh™¨îèÑŠº¢¢ŠH__Q¤ŒEM÷è{»Û¶zû¯[¼à³ '[\¼k©?z¨¼¡¸¸<ÌÏW!3[›Îä«å´™¦šßS‰éÂÜâ­y svÉÝ Õ€ªÍÑæ±]`ÿ08¶w>í›?1(ü³ÄTœ(»ðìt}YK=8Cµða•6ÚÛ}CHµD§«Òè‹Ò ÒÔLþDîg€zùYHhTŒL”Ä¢ñóÀt°‹Ú 6¨÷1N %ôÛð¨ËŠý˜²½‚—hûmxjÓíÅmр⧠“%…)9,œƒ8¥h–3÷ ˜*Á-H¨dµ°¦îÀ==ßzvÚð_œ£m?´Áå8WÇ™âèŒL3¹¡æ­œ…P¿®wZ> Ý®(FËÐH4 CŸ á@äG=yx¡^’â3@R⟄%1 p |ïÅËßõÇ’ÖT±«ÐMzÛÎË÷?øØÑu®®>ëw˜ùDgŽí‘\ÆÀDÐE¹Å¹¸ú²Aý. ^šY«úÔc~³78ËÃUî™Q "®Hó ¸â$¢ÂÔbxÎZD¬•¥$¤¡K:?ÈÀÁ·QJwî"Á{÷‚½ùõÊϵŒ!höÆÎ:q&È”¶¸¼T#ËW¨X¾æã½Q%æ¶7Çðz,&Å|œ'Ÿ¾@Û¯;œ"aÿ^Å U'íc {/2<åõX3L`Ü^p.Ä o`N «i8Ædh Kæ@ŒH2Ecx=àÇ ±¤ 6ãÁEVÜx-Ðr.š¦pá;¯?¤Ó ’51€Jâã’³“²RYøðïs’òâ+‹¶TSž—^¡fm]››¯ras-ñØ&–¥'eÄ¥¡¥57½<í »?óÝ% ñ¯çïUçª2s›åRœ[ç_î’î½äË”¿Ç¢)½®Ý­ç½æJ¯¾a­Ó¹Øf›Á7mè‹™Bt­7pîš^вÜTa!ò44ÐÝY’œœâ©”‚êlµ*·ˆù³ýÏ5%òL .ÕM¹y¶,—µq7µÿ‹ð€)Ý™ò÷as­Éçõ :·Lp4ƒOLŠ$!ÓÌ¿W¤ˆ•$»Ä•Æk+sK‹Õæ©MÔs¸Çv•ÁL0]é:aUXJš(˜t¯®Èºõõq6/§Àüº§<¾D=zr\زçÐÞòÚê1Ï9e„ŸáÜ 7ô­‡!;d?Ñò­„5/Ñ0híŸÃáË@”G/X‰ƒù.œ`üíÎíèÝ•¨ï‹xÊüÓ-ß44&{³òÊ<Îl”Z«®Æ©·qfijÊT°DPÓx HÄ’-J R…©ÑaÕʶV 9™)äÊaÀçLøaÁù”“€*¯õ|•œE#³0in¤à,¨É8äÙp¸¦t¯ªÆ*ÐL /±[Òð>®v}ùB”*Ã(î?Û+Q¤+cxm~yZiÅ!õ£L§ëTžíD&ÛVFSÉžèX èõº§^þ^Äë]À¢ÏtÀR#÷‹‹´<95 H)ó[>µæem×)µ(‚AròÒéŸï9x¥íøUð ûO¸‹¢¾óçÎÞ£OÔX{s±<—)=~¢ñ< |µ}Ærïuîžos5n»zpÌ«~kíêì@@Åc±U‘Žå1£Àî ¦vÒ®Ò#‚ !Šm B+x  ñ ‹Çñ5~ÒÞ/eUjp è©'<ìÛÒýeûKOªª­¡kˆV%±Ñ*d—©hëbï™—Í_:ÚñiŒ4î2Ë>¢Ûöë/€sÔ%_ ê¿|ëŠà©ÖlOIjAFÓØxÓüîú©Ÿ0I`d ÅW(Ö§K§œ~72sœüíô'ëÖlX=u×ÂÂQlNN®h{ÞYNÿe–þ{úìæ¶Kî –RÁþœGðwó ê/é2I™815-5… ‹ˆK±–MÎO(J(ê‚@$ˆ â…’ð¬*Å¥â²BuŽ:—iÐ×–•€'/–'hc÷: /«ÒhKë+Ay—ð' ¦>8î´qÀ Zž¸‡ç§420½Žõ>±%‘$îÙ®˜¿ô’’ÄDÑ M™ ¤Ð¼NІ|øÒ½äY]Ûh€³ Žg:6¡Ò¢ïL.t ðMñ‹1‹«Û{TiTÁ‹‚¦ò윂<¦®éP9&cN¯[²rÞ²O?ŠX•w>{1/{±^P+ “ïžóp9´‡C~{¹/þŠú2 M°mÈ'Q\.ÏÐרékÑ¿¡cÿñÿ½Xâ6 endstream endobj 23 0 obj <> endobj 239 0 obj <>stream xœ­V{P×Þ5’]¡Š{µ½u7Ó Š¯j­Zl‹PTåÚB±ˆ•‡ `È#$ù%ˆ¼‚ $° U…ÖŠ·z¯Öޭ޽ÚÑÚw­Ö³™ÃLïFlëÌmû×Ìd’™³{Î÷ý¾Ç!‰ñã’$]CB}?¼…¿“³ã„À[%Žp“€ÛøÎgÝfMAªÉh•š÷!!ÉÕÁ›•©ÙéI ‰*Ùì@Ù"_ße²€òô¤¸ØYH¬*Q¾#V%þQÈ”qIrUöY€B! u>±S*ß)Oß%ßæÜ9P¹#5C%O—…(·ÉÓS‚˜¢ L]•¾:Hµ&6nÛ?ä ‰¡IaŠyñ±xƒ˜I¼IxaÄ,b6Nø¯+‰UÄ Äjb ±–XL/!Ä$bº éAfwÇ%»!ñ—t_9^ï2Ç¥G:UZEyR»èUô?'”MøÒµÆõ“‰ž¿«÷_$ãÀ£Í¼ÔH óëMv䀮¸8'Þ™ž¿]•è§§Ô»¥Vè†NhÒéhž 5ìæ¡*eƲ>ÄLGÕÒÓxî¾½-hžÞi¬‚ê-=Ç¡JᆖæwS! ®Ük£±]¨g+¾æ‚ÕR÷_Æ-Çâ!„¿YH4þ Š¿"¶£ n@›²Se“×l‚³:WIë¿•b/µ‹‚ºXYÉáFj‹ÖŠÛô ýÐ5úAçÉÖªá8‡‚©Ÿ?95òAMäçüÉÊH=O‹G oj›0ÇB¶ÝD]7%BJbдçïcìé-ÃSñäû³‘òüñGäÁâLÁl‚X‹ê½´ý ±†-GÚOž¨ë‚a8’ܘÔkˆ€Xˆ‡7Ó£•[¶dÆ‚s—;«‰ Þ1Ÿ'‡ï «Äáïx…©‡Êü"­¶ ˜ðOæC‡¼ái¼¿Œ—à(¼-Ç/¢·ÐòŸÐ 4áTææAQž+Äó°[ÀL —ⵃèê@Áƒ7¾à—¶pÆ<ƒ¦h”™¹1nñFͳ3mäÃ+¨é¦UáeÌI¾Tkš}ûG@£‰hÜ7hšâóv ß”±UÎPx¶“ìKåÅ1ÜhâRè'Xûûg{€þôì"q+iÐâåQòÖÎ\^#¡Á‰º?Æ©±³<:d'‘ì6жI‹P£”¦ãÒñ  ±LúŽ®ÂΡ†»ÔwÕŠ%œ TJ—ä+|بPj7Vô±è)Z¶p–Ñ6©e¸Œ^V4K¯ÕñÜh¯Sû±*…ð©»à-ÊÉ¥‡|xéá´e3GªÐ,$eõ”NŸ“;éTóîfss]{ÇŽö¨ ±±!*V_ŠŸûm k 'á0´èGDÅdR¯k«º¼6\v‚êãÑñ1P‘6‰ðãUfôýÿ=“´·ôœ(’Ãp:E$S Kª»9¤»M}[•¼t ëRuòv*{ŒuŠÍK˜ ³"VѧÞÙ¢rP/Ì|$ž Û¢xP$sx_Ù–§‚µjØÛ` $–ÒŠêni~<·žÂîxäùâ7P÷“aŸÔÊ£þJ‚1h~ E|u¹kÀÆÕ§v%º *M"ä¾n§i$A“QcÉá÷úëË?PÚój¹Ã]}P m¡²iuEVs­é€¹!—K‰R'$²©MÛjÅZ™ôjD{‚i§Ó)E$™¬Ù9qñð½òûP4y<¼z$ëX| Öù&̃LH†BcJy–Uœ†©¬®²†¾W¼ß5Yöú®®ÑZgú6ÌQ©`Î"î8öc:‡~y¨_Ô|Ÿ€¾3¦Ýäž(n§`þ¬»×@d¢"ŒÖ£o¤c}òHL£¦ÿcy?ñIÌ“t’Ÿ‚ž»…î}gæ™'D¢/™¯­Ÿ~ŸÒßãI×ñ,ÿÞ¿ÇC_é p¾Yü~"J)Ï>ä&½ ò}%íñ°VŠh¢ûå}ñg¡ èÏënµ”CµØÉ…zN³^±S!«n,¬/h*¸XÜ[x®à–tÒ˜¬c0H¡ÕXÙ°¯ÒØf o"OÀ>K¢×ãgY:#—xTZÈ $r­·AeÚw¶ìP¨ÒSRšÓùö––vÏÂ!¢!ÏW‹†4ÿÊL¯Ñl8&ÑNâù©à’²÷8ABMH¼q,´‘ÃçÑõóâ½ÆáË4Âþü"½>¿ˆÍË>P³ýíÝoŸ˜/úk²…^¯õm.Óp½Ñ5h¢òzV¥îP’Ao‡7è Hÿ…~XÌßBV_åy@çBa&‡Ã©L(¬®0ª+Øšƒ{ó:·á³½âÂýú‡wÛÙÎÅœ‰ª ®[lžþJcÚy8F_8}þsÄœšë]Ë–f4Õ@×B…ù7dÏëÁÌŸªæ8ôA½~à7ÕŒ=ÃÍÈßÉa°E‚‚M lß%(=­)/ª¨º~¹þ+­{[bVjjjCj§¥®ÎÀºg49V4ak=J©’â­Õïze"ë:~Y£ÛK¹›Û“Û$‚ø/ØyßQ endstream endobj 245 0 obj <>stream 2014-05-12T15:50:46-04:00 2014-05-12T15:50:46-04:00 dvips\(k\) 5.96.1 Copyright 2007 Radical Eye Software quick.dvi endstream endobj 2 0 obj <>endobj xref 0 246 0000000000 65535 f 0000180856 00000 n 0000227596 00000 n 0000180491 00000 n 0000173605 00000 n 0000000015 00000 n 0000002628 00000 n 0000180922 00000 n 0000186676 00000 n 0000211291 00000 n 0000186344 00000 n 0000209096 00000 n 0000186106 00000 n 0000208453 00000 n 0000185712 00000 n 0000203699 00000 n 0000185322 00000 n 0000198600 00000 n 0000184608 00000 n 0000189046 00000 n 0000184370 00000 n 0000188389 00000 n 0000188047 00000 n 0000223225 00000 n 0000180963 00000 n 0000180993 00000 n 0000173773 00000 n 0000002648 00000 n 0000008681 00000 n 0000187421 00000 n 0000214535 00000 n 0000181100 00000 n 0000181130 00000 n 0000173935 00000 n 0000008702 00000 n 0000013140 00000 n 0000181184 00000 n 0000181214 00000 n 0000174097 00000 n 0000013161 00000 n 0000016940 00000 n 0000181268 00000 n 0000181298 00000 n 0000174267 00000 n 0000016961 00000 n 0000022617 00000 n 0000181352 00000 n 0000181382 00000 n 0000174437 00000 n 0000022638 00000 n 0000027776 00000 n 0000181425 00000 n 0000181455 00000 n 0000174607 00000 n 0000027797 00000 n 0000033764 00000 n 0000181509 00000 n 0000181539 00000 n 0000174777 00000 n 0000033785 00000 n 0000036472 00000 n 0000181593 00000 n 0000181623 00000 n 0000174947 00000 n 0000036493 00000 n 0000040739 00000 n 0000181666 00000 n 0000181696 00000 n 0000175117 00000 n 0000040760 00000 n 0000045270 00000 n 0000181750 00000 n 0000181780 00000 n 0000175279 00000 n 0000045291 00000 n 0000047062 00000 n 0000181823 00000 n 0000181853 00000 n 0000175449 00000 n 0000047083 00000 n 0000051309 00000 n 0000181896 00000 n 0000181926 00000 n 0000175619 00000 n 0000051330 00000 n 0000055839 00000 n 0000181980 00000 n 0000182010 00000 n 0000175789 00000 n 0000055860 00000 n 0000062023 00000 n 0000182053 00000 n 0000182083 00000 n 0000175959 00000 n 0000062044 00000 n 0000066472 00000 n 0000182126 00000 n 0000182156 00000 n 0000176129 00000 n 0000066493 00000 n 0000071758 00000 n 0000182199 00000 n 0000182230 00000 n 0000176293 00000 n 0000071780 00000 n 0000077609 00000 n 0000182274 00000 n 0000182305 00000 n 0000176467 00000 n 0000077631 00000 n 0000079621 00000 n 0000182349 00000 n 0000182380 00000 n 0000176633 00000 n 0000079643 00000 n 0000084887 00000 n 0000182424 00000 n 0000182455 00000 n 0000176807 00000 n 0000084909 00000 n 0000089619 00000 n 0000182510 00000 n 0000182541 00000 n 0000176973 00000 n 0000089641 00000 n 0000091242 00000 n 0000182585 00000 n 0000182616 00000 n 0000177139 00000 n 0000091264 00000 n 0000096380 00000 n 0000182660 00000 n 0000182691 00000 n 0000177313 00000 n 0000096402 00000 n 0000102104 00000 n 0000186961 00000 n 0000213641 00000 n 0000182746 00000 n 0000182777 00000 n 0000177487 00000 n 0000102126 00000 n 0000107422 00000 n 0000182845 00000 n 0000182876 00000 n 0000177661 00000 n 0000107444 00000 n 0000110771 00000 n 0000182944 00000 n 0000182975 00000 n 0000177827 00000 n 0000110793 00000 n 0000116094 00000 n 0000183019 00000 n 0000183050 00000 n 0000177993 00000 n 0000116116 00000 n 0000120556 00000 n 0000183116 00000 n 0000183147 00000 n 0000178159 00000 n 0000120578 00000 n 0000125256 00000 n 0000183191 00000 n 0000183222 00000 n 0000178325 00000 n 0000125278 00000 n 0000130914 00000 n 0000183301 00000 n 0000183332 00000 n 0000178491 00000 n 0000130936 00000 n 0000135344 00000 n 0000183400 00000 n 0000183431 00000 n 0000178665 00000 n 0000135366 00000 n 0000139669 00000 n 0000183475 00000 n 0000183506 00000 n 0000178831 00000 n 0000139691 00000 n 0000145193 00000 n 0000183563 00000 n 0000183594 00000 n 0000178997 00000 n 0000145215 00000 n 0000151367 00000 n 0000183649 00000 n 0000183680 00000 n 0000179163 00000 n 0000151389 00000 n 0000155942 00000 n 0000183724 00000 n 0000183755 00000 n 0000179329 00000 n 0000155964 00000 n 0000156805 00000 n 0000183810 00000 n 0000183841 00000 n 0000179495 00000 n 0000156826 00000 n 0000162032 00000 n 0000183885 00000 n 0000183916 00000 n 0000179661 00000 n 0000162054 00000 n 0000163285 00000 n 0000183984 00000 n 0000184015 00000 n 0000179827 00000 n 0000163307 00000 n 0000166588 00000 n 0000184059 00000 n 0000184090 00000 n 0000179993 00000 n 0000166610 00000 n 0000169141 00000 n 0000184145 00000 n 0000184176 00000 n 0000180159 00000 n 0000169163 00000 n 0000171668 00000 n 0000184220 00000 n 0000184251 00000 n 0000180325 00000 n 0000171690 00000 n 0000173583 00000 n 0000184295 00000 n 0000184326 00000 n 0000188591 00000 n 0000189648 00000 n 0000198936 00000 n 0000204046 00000 n 0000208655 00000 n 0000209361 00000 n 0000211552 00000 n 0000213870 00000 n 0000215218 00000 n 0000223498 00000 n 0000184514 00000 n 0000185156 00000 n 0000186250 00000 n 0000187299 00000 n 0000187941 00000 n 0000226163 00000 n trailer << /Size 246 /Root 1 0 R /Info 2 0 R /ID [<87F918090A2088B2D86167079CAFF9CC><87F918090A2088B2D86167079CAFF9CC>] >> startxref 227801 %%EOF cfitsio-4.3.1/docs/cfitsio.tex0000644000225700000360000177423614456514035015612 0ustar cagordonlhea\documentclass[11pt]{book} \input{html.sty} \htmladdtonavigation {\begin{rawhtml} FITSIO Home \end{rawhtml}} \oddsidemargin=0.00in \evensidemargin=0.00in \textwidth=6.5in %\topmargin=0.0in \textheight=8.75in \parindent=0cm \parskip=0.2cm \begin{document} \pagenumbering{roman} \begin{titlepage} \normalsize \vspace*{4.0cm} \begin{center} {\Huge \bf CFITSIO User's Reference Guide}\\ \end{center} \medskip \medskip \begin{center} {\LARGE \bf An Interface to FITS Format Files}\\ \end{center} \begin{center} {\LARGE \bf for C Programmers}\\ \end{center} \medskip \medskip \begin{center} {\Large Version 4.3 \\} \end{center} \bigskip \vskip 2.5cm \begin{center} {HEASARC\\ Code 662\\ Goddard Space Flight Center\\ Greenbelt, MD 20771\\ USA} \end{center} \vfill \bigskip \begin{center} {\Large Jul 2023\\} \end{center} \vfill \end{titlepage} \clearpage \tableofcontents \chapter{Introduction } \pagenumbering{arabic} \section{ A Brief Overview} CFITSIO is a machine-independent library of routines for reading and writing data files in the FITS (Flexible Image Transport System) data format. It can also read IRAF format image files and raw binary data arrays by converting them on the fly into a virtual FITS format file. This library is written in ANSI C and provides a powerful yet simple interface for accessing FITS files which will run on most commonly used computers and workstations. CFITSIO supports all the features described in the official definition of the FITS format and can read and write all the currently defined types of extensions, including ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The CFITSIO routines insulate the programmer from having to deal with the complicated formatting details in the FITS file, however, it is assumed that users have a general knowledge about the structure and usage of FITS files. CFITSIO also contains a set of Fortran callable wrapper routines which allow Fortran programs to call the CFITSIO routines. See the companion ``FITSIO User's Guide'' for the definition of the Fortran subroutine calling sequences. These wrappers replace the older Fortran FITSIO library which is no longer supported. The CFITSIO package was initially developed by the HEASARC (High Energy Astrophysics Science Archive Research Center) at the NASA Goddard Space Flight Center to convert various existing and newly acquired astronomical data sets into FITS format and to further analyze data already in FITS format. New features continue to be added to CFITSIO in large part due to contributions of ideas or actual code from users of the package. The Integral Science Data Center in Switzerland, and the XMM/ESTEC project in The Netherlands made especially significant contributions that resulted in many of the new features that appeared in v2.0 of CFITSIO. \section{Sources of FITS Software and Information} The latest version of the CFITSIO source code, documentation, and example programs are available on the Web or via anonymous ftp from: \begin{verbatim} http://heasarc.gsfc.nasa.gov/fitsio ftp://legacy.gsfc.nasa.gov/software/fitsio/c \end{verbatim} Any questions, bug reports, or suggested enhancements related to the CFITSIO package should be sent to the FTOOLS Help Desk at the HEASARC: \begin{verbatim} http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp \end{verbatim} This User's Guide assumes that readers already have a general understanding of the definition and structure of FITS format files. Further information about FITS formats is available from the FITS Support Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the 'FITS Standard' gives the authoritative definition of the FITS data format. Other documents available at that Web site provide additional historical background and practical advice on using FITS files. The HEASARC also provides a very sophisticated FITS file analysis program called `Fv' which can be used to display and edit the contents of any FITS file as well as construct new FITS files from scratch. Fv is freely available for most Unix platforms, Mac PCs, and Windows PCs. CFITSIO users may also be interested in the FTOOLS package of programs that can be used to manipulate and analyze FITS format files. Fv and FTOOLS are available from their respective Web sites at: \begin{verbatim} http://fv.gsfc.nasa.gov http://heasarc.gsfc.nasa.gov/ftools \end{verbatim} \section{Acknowledgments} The development of the many powerful features in CFITSIO was made possible through collaborations with many people or organizations from around the world. The following in particular have made especially significant contributions: Programmers from the Integral Science Data Center, Switzerland (namely, Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The use of `drivers' greatly simplified the low-level I/O, which in turn made other new features in CFITSIO (e.g., support for compressed FITS files and support for IRAF format image files) much easier to implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce O'Neel wrote the drivers for accessing FITS files over the network using the FTP, HTTP, and ROOT protocols. Also, in 2009, Bruce O'Neel was the key developer of the thread-safe version of CFITSIO. The ISDC also provided the template parsing routines (written by Jurek Borkowski) and the hierarchical grouping routines (written by Don Jennings). The ISDC DAL (Data Access Layer) routines are layered on top of CFITSIO and make extensive use of these features. Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, Italy, implemented the I/O driver routines for accessing FITS files on the computational grids using the gridftp protocol. Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the high-performance lexical parsing algorithm that is used to do on-the-fly filtering of FITS tables. This algorithm essentially pre-compiles the user-supplied selection expression into a form that can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) then wrote the parsing routines used by CFITSIO based on Lammers' design, combined with other techniques such as the CFITSIO iterator routine to further enhance the data processing throughput. This effort also benefited from a much earlier lexical parsing routine that was developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt (NASA/GSFC) implemented additional functions (median, average, stddev) and other enhancements to the lexical parser. The CFITSIO iterator function is loosely based on similar ideas developed for the XMM Data Access Layer. Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of Fortran-callable wrappers for all the CFITSIO routines, which in turn rely on the CFORTRAN macro developed by Burkhard Burow. The syntax used by CFITSIO for filtering or binning input FITS files is based on ideas developed for the AXAF Science Center Data Model by Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for further description of the AXAF Data Model. The file decompression code were taken directly from the gzip (GNU zip) program developed by Jean-loup Gailly and others. The new compressed image data format (where the image is tiled and the compressed byte stream from each tile is stored in a binary table) was implemented in collaboration with Richard White (STScI), Perry Greenfield (STScI) and Doug Tody (NOAO). Doug Mink (SAO) provided the routines for converting IRAF format images into FITS format. Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to cfortran.h that are necessary to support 64-bit integer values when calling C routines from fortran programs. The cfortran.h macros were originally developed by Burkhard Burow (CERN). Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. In addition, many other people have made valuable contributions to the development of CFITSIO. These include (with apologies to others that may have inadvertently been omitted): Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Gretchen Green, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, Richard Mathar, John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, Philippe Prugniel, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, Rob Seaman, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. \section{Legal Stuff} Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." \chapter{ Creating the CFITSIO Library } \section{Building the Library} The CFITSIO code is contained in about 40 C source files (*.c) and header files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. CFITSIO is written in ANCI C and should be compatible with most existing C and C++ compilers. Cray supercomputers are currently not supported. \subsection{Unix Systems} The CFITSIO library is built on Unix systems by typing: \begin{verbatim} > ./configure [--prefix=/target/installation/path] [--enable-reentrant] [--enable-sse2] [--enable-ssse3] > make (or 'make shared') > make install (this step is optional) \end{verbatim} at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, \begin{verbatim} > ./configure --prefix=/usr1/local \end{verbatim} will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). All the available configure options can be seen by entering the command \begin{verbatim} > ./configure --help \end{verbatim} Some of the more useful options are described below: The --enable-reentrant option will attempt to configure CFITSIO so that it can be used in multi-threaded programs. See the "Using CFITSIO in Multi-threaded Environments" section, below, for more details. The --enable-sse2 and --enable-ssse3 options will cause configure to attempt to build CFITSIO using faster byte-swapping algorithms. See the "Optimizing Programs" chapter of this manual for more information about these options. The --with-gsiftp-flavour and --with-gsiftp options enable support for the Globus Toolkit gsiftp protocal. See the "Extended File Name Syntax" chapter for more information. The --with-bzip2 option enables support for reading FITS files that have been externally compressed by the bzip2 algorithm. This requires that the CFITSIO library, and all applications program that use CFITSIO, to be linked to include the libbz2 library. The 'make shared' option builds a shared or dynamic version of the CFITSIO library. When using the shared library the executable code is not copied into your program at link time and instead the program locates the necessary library code at run time, normally through LD\_LIBRARY\_PATH or some other method. The advantages of using a shared library are: \begin{verbatim} 1. Less disk space if you build more than 1 program 2. Less memory if more than one copy of a program using the shared library is running at the same time since the system is smart enough to share copies of the shared library at run time. 3. Possibly easier maintenance since a new version of the shared library can be installed without relinking all the software that uses it (as long as the subroutine names and calling sequences remain unchanged). 4. No run-time penalty. \end{verbatim} The disadvantages are: \begin{verbatim} 1. More hassle at runtime. You have to either build the programs specially or have LD_LIBRARY_PATH set right. 2. There may be a slight start up penalty, depending on where you are reading the shared library and the program from and if your CPU is either really slow or really heavily loaded. \end{verbatim} On Mac OS X platforms the 'make shared' command works like on other UNIX platforms, but a .dylib file will be created instead of .so. If installed in a nonstandard location, add its location to the DYLD\_LIBRARY\_PATH environment variable so that the library can be found at run time. On HP/UX systems, the environment variable CFLAGS should be set to -Ae before running configure to enable "extended ANSI" features. By default, a set of Fortran-callable wrapper routines are also built and included in the CFITSIO library. If these wrapper routines are not needed (i.e., the CFITSIO library will not be linked to any Fortran applications which call FITSIO subroutines) then they may be omitted from the build by typing 'make all-nofitsio' instead of simply typing 'make'. This will reduce the size of the CFITSIO library slightly. It may not be possible to statically link programs that use CFITSIO on some platforms (namely, on Solaris 2.6) due to the network drivers (which provide FTP and HTTP access to FITS files). It is possible to make both a dynamic and a static version of the CFITSIO library, but network file access will not be possible using the static version. \subsection{VMS} On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may be executed to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. Note that the getcwd function that is used in the group.c module may require that programs using CFITSIO be linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example link line in the next section of this document. \subsection{Windows PCs} A precompiled DLL version of CFITSIO (not necessarily the latest version) is available on the CFITSIO web site. The CFITSIO library may also be built from the source code using the CMake build system. See the "README.win" file in the CFITSIO source distribution for more information. \subsection{Macintosh PCs} When building on Mac OS-X, users should follow the Unix instructions, above. See the README.MacOS file for instructions on building a Universal Binary that supports both Intel and PowerPC CPUs. \section{Testing the Library} The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems, type: \begin{verbatim} % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std \end{verbatim} On VMS systems, (assuming cc is the name of the C compiler command), type: \begin{verbatim} $ cc testprog.c $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib $ run testprog \end{verbatim} The test program should produce a FITS file called `testprog.fit' that is identical to the `testprog.std' FITS file included with this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. (There may be some minor format differences, such as the presence or absence of leading zeros, or 3 digit exponents in numbers, which can be ignored). The Fortran wrappers in CFITSIO may be tested with the testf77 program on Unix systems with: \begin{verbatim} % gfortran -o testf77 testf77.f -L. -lcfitsio -lz -lcurl % testf77 > testf77.lis % diff testf77.lis testf77.out % cmp testf77.fit testf77.std \end{verbatim} On machines running SUN O/S, Fortran programs must be compiled with the '-f' option to force double precision variables to be aligned on 8-byte boundarys to make the fortran-declared variables compatible with C. A similar compiler option may be required on other platforms. Failing to use this option may cause the program to crash on FITSIO routines that read or write double precision variables. Also note that on some systems, the output listing of the testf77 program may differ slightly from the testf77.std template, if leading zeros are not printed by default before the decimal point when using F format. A few other utility programs are included with CFITSIO; the first four of this programs can be compiled an linked by typing `make program\_name' where `program\_name' is the actual name of the program: \begin{verbatim} speed - measures the maximum throughput (in MB per second) for writing and reading FITS files with CFITSIO. listhead - lists all the header keywords in any FITS file fitscopy - copies any FITS file (especially useful in conjunction with the CFITSIO's extended input filename syntax). cookbook - a sample program that performs common read and write operations on a FITS file. iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine \end{verbatim} \section{Linking Programs with CFITSIO} When linking applications software with the CFITSIO library, several system libraries usually need to be specified on the link command line. On Unix systems, the most reliable way to determine what libraries are required is to type 'make testprog' and see what libraries the configure script has added. The typical libraries that need to be added are -lm (the math library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). These latter 2 libraries are not needed on VMS and Windows platforms, because FTP file access is not currently supported on those platforms. Note that when upgrading to a newer version of CFITSIO it is usually necessary to recompile, as well as relink, the programs that use CFITSIO, because the definitions in fitsio.h often change. \section{Using CFITSIO in Multi-threaded Environments} CFITSIO can be used either with the POSIX pthreads interface or the OpenMP interface for multi-threaded parallel programs. When used in a multi-threaded environment, the CFITSIO library *must* be built using the -D\_REENTRANT compiler directive. This can be done using the following build commands: \begin{verbatim} >./configure --enable-reentrant > make \end{verbatim} A function called fits\_is\_reentrant is available to test whether or not CFITSIO was compiled with the -D\_REENTRANT directive. When this feature is enabled, multiple threads can call any of the CFITSIO routines to simultaneously read or write separate FITS files. Multiple threads can also read data from the same FITS file simultaneously, as long as the file was opened independently by each thread. This relies on the operating system to correctly deal with reading the same file by multiple processes. Different threads should not share the same 'fitsfile' pointer to read an opened FITS file, unless locks are placed around the calls to the CFITSIO reading routines. Different threads should never try to write to the same FITS file. \section{Getting Started with CFITSIO} In order to effectively use the CFITSIO library it is recommended that new users begin by reading the ``CFITSIO Quick Start Guide''. It contains all the basic information needed to write programs that perform most types of operations on FITS files. The set of example FITS utility programs that are available from the CFITSIO web site are also very useful for learning how to use CFITSIO. To learn even more about the capabilities of the CFITSIO library the following steps are recommended: 1. Read the following short `FITS Primer' chapter for an overview of the structure of FITS files. 2. Review the Programming Guidelines in Chapter 4 to become familiar with the conventions used by the CFITSIO interface. 3. Refer to the cookbook.c, listhead.c, and fitscopy.c programs that are included with this release for examples of routines that perform various common FITS file operations. Type 'make program\_name' to compile and link these programs on Unix systems. 4. Write a simple program to read or write a FITS file using the Basic Interface routines described in Chapter 5. 5. Scan through the more specialized routines that are described in the following chapters to become familiar with the functionality that they provide. \section{Example Program} The following listing shows an example of how to use the CFITSIO routines in a C program. Refer to the cookbook.c program that is included with the CFITSIO distribution for other example routines. This program creates a new FITS file, containing a FITS image. An `EXPOSURE' keyword is written to the header, then the image data are written to the FITS file before closing the FITS file. \begin{verbatim} #include "fitsio.h" /* required by every program that uses CFITSIO */ main() { fitsfile *fptr; /* pointer to the FITS file; defined in fitsio.h */ int status, ii, jj; long fpixel = 1, naxis = 2, nelements, exposure; long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ short array[200][300]; status = 0; /* initialize status before calling fitsio routines */ fits_create_file(&fptr, "testfile.fits", &status); /* create new file */ /* Create the primary array image (16-bit short integer pixels */ fits_create_img(fptr, SHORT_IMG, naxis, naxes, &status); /* Write a keyword; must pass the ADDRESS of the value */ exposure = 1500.; fits_update_key(fptr, TLONG, "EXPOSURE", &exposure, "Total Exposure Time", &status); /* Initialize the values in the image with a linear ramp function */ for (jj = 0; jj < naxes[1]; jj++) for (ii = 0; ii < naxes[0]; ii++) array[jj][ii] = ii + jj; nelements = naxes[0] * naxes[1]; /* number of pixels to write */ /* Write the array of integers to the image */ fits_write_img(fptr, TSHORT, fpixel, nelements, array[0], &status); fits_close_file(fptr, &status); /* close the file */ fits_report_error(stderr, status); /* print out any error messages */ return( status ); } \end{verbatim} \chapter{ A FITS Primer } This section gives a brief overview of the structure of FITS files. Users should refer to the documentation available from the FITS Support OFfice, as described in the introduction, for more detailed information on FITS formats. FITS was first developed in the late 1970's as a standard data interchange format between various astronomical observatories. Since then FITS has become the standard data format supported by most astronomical data analysis software packages. A FITS file consists of one or more Header + Data Units (HDUs), where the first HDU is called the `Primary HDU', or `Primary Array'. The primary array contains an N-dimensional array of pixels, such as a 1-D spectrum, a 2-D image, or a 3-D data cube. Six different primary data types are supported: Unsigned 8-bit bytes, 16-bit, 32-bit, and 64-bit signed integers, and 32 and 64-bit floating point reals. FITS also has a convention for storing 16, 32-bit, and 64-bit unsigned integers (see the later section entitled `Unsigned Integers' for more details). The primary HDU may also consist of only a header with a null array containing no data pixels. Any number of additional HDUs may follow the primary array; these additional HDUs are called FITS `extensions'. There are currently 3 types of extensions defined by the FITS standard: \begin{itemize} \item Image Extension - a N-dimensional array of pixels, like in a primary array \item ASCII Table Extension - rows and columns of data in ASCII character format \item Binary Table Extension - rows and columns of data in binary representation \end{itemize} In each case the HDU consists of an ASCII Header Unit followed by an optional Data Unit. For historical reasons, each Header or Data unit must be an exact multiple of 2880 8-bit bytes long. Any unused space is padded with fill characters (ASCII blanks or zeros). Each Header Unit consists of any number of 80-character keyword records or `card images' which have the general form: \begin{verbatim} KEYNAME = value / comment string NULLKEY = / comment: This keyword has no value \end{verbatim} The keyword names may be up to 8 characters long and can only contain uppercase letters, the digits 0-9, the hyphen, and the underscore character. The keyword name is (usually) followed by an equals sign and a space character (= ) in columns 9 - 10 of the record, followed by the value of the keyword which may be either an integer, a floating point number, a character string (enclosed in single quotes), or a boolean value (the letter T or F). A keyword may also have a null or undefined value if there is no specified value string, as in the second example, above The last keyword in the header is always the `END' keyword which has no value or comment fields. There are many rules governing the exact format of a keyword record (see the FITS Standard) so it is better to rely on standard interface software like CFITSIO to correctly construct or to parse the keyword records rather than try to deal directly with the raw FITS formats. Each Header Unit begins with a series of required keywords which depend on the type of HDU. These required keywords specify the size and format of the following Data Unit. The header may contain other optional keywords to describe other aspects of the data, such as the units or scaling values. Other COMMENT or HISTORY keywords are also frequently added to further document the data file. The optional Data Unit immediately follows the last 2880-byte block in the Header Unit. Some HDUs do not have a Data Unit and only consist of the Header Unit. If there is more than one HDU in the FITS file, then the Header Unit of the next HDU immediately follows the last 2880-byte block of the previous Data Unit (or Header Unit if there is no Data Unit). The main required keywords in FITS primary arrays or image extensions are: \begin{itemize} \item BITPIX -- defines the data type of the array: 8, 16, 32, 64, -32, -64 for unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, 32--bit IEEE floating point, and 64--bit IEEE double precision floating point, respectively. \item NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. \item NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. \end{itemize} FITS tables start with the keyword XTENSION = `TABLE' (for ASCII tables) or XTENSION = `BINTABLE' (for binary tables) and have the following main keywords: \begin{itemize} \item TFIELDS -- number of fields or columns in the table \item NAXIS2 -- number of rows in the table \item TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the name of the column \item TFORMn -- the data type of the column \item TUNITn -- the physical units of the column (optional) \end{itemize} Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} for further information about the FITS format and related software packages. \chapter{ Programming Guidelines } \section{CFITSIO Definitions} Any program that uses the CFITSIO interface must include the fitsio.h header file with the statement \begin{verbatim} #include "fitsio.h" \end{verbatim} This header file contains the prototypes for all the CFITSIO user interface routines as well as the definitions of various constants used in the interface. It also defines a C structure of type `fitsfile' that is used by CFITSIO to store the relevant parameters that define the format of a particular FITS file. Application programs must define a pointer to this structure for each FITS file that is to be opened. This structure is initialized (i.e., memory is allocated for the structure) when the FITS file is first opened or created with the fits\_open\_file or fits\_create\_file routines. This fitsfile pointer is then passed as the first argument to every other CFITSIO routine that operates on the FITS file. Application programs must not directly read or write elements in this fitsfile structure because the definition of the structure may change in future versions of CFITSIO. A number of symbolic constants are also defined in fitsio.h for the convenience of application programmers. Use of these symbolic constants rather than the actual numeric value will help to make the source code more readable and easier for others to understand. \begin{verbatim} String Lengths, for use when allocating character arrays: #define FLEN_FILENAME 1025 /* max length of a filename */ #define FLEN_KEYWORD 72 /* max length of a keyword */ #define FLEN_CARD 81 /* max length of a FITS header card */ #define FLEN_VALUE 71 /* max length of a keyword value string */ #define FLEN_COMMENT 73 /* max length of a keyword comment string */ #define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ #define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ Note that FLEN_KEYWORD is longer than the nominal 8-character keyword name length because the HIERARCH convention supports longer keyword names. Access modes when opening a FITS file: #define READONLY 0 #define READWRITE 1 BITPIX data type code values for FITS images: #define BYTE_IMG 8 /* 8-bit unsigned integers */ #define SHORT_IMG 16 /* 16-bit signed integers */ #define LONG_IMG 32 /* 32-bit signed integers */ #define LONGLONG_IMG 64 /* 64-bit signed integers */ #define FLOAT_IMG -32 /* 32-bit single precision floating point */ #define DOUBLE_IMG -64 /* 64-bit double precision floating point */ The following 4 data type codes are also supported by CFITSIO: #define SBYTE_IMG 10 /* 8-bit signed integers, equivalent to */ /* BITPIX = 8, BSCALE = 1, BZERO = -128 */ #define USHORT_IMG 20 /* 16-bit unsigned integers, equivalent to */ /* BITPIX = 16, BSCALE = 1, BZERO = 32768 */ #define ULONG_IMG 40 /* 32-bit unsigned integers, equivalent to */ /* BITPIX = 32, BSCALE = 1, BZERO = 2147483648 */ #define ULONGLONG_IMG 80 /* 64-bit unsigned integers, equivalent to */ /* BITPIX = 64, BSCALE = 1, BZERO = 9223372036854775808*/ Codes for the data type of binary table columns and/or for the data type of variables when reading or writing keywords or data: DATATYPE TFORM CODE #define TBIT 1 /* 'X' */ #define TBYTE 11 /* 8-bit unsigned byte, 'B' */ #define TLOGICAL 14 /* logicals (int for keywords */ /* and char for table cols 'L' */ #define TSTRING 16 /* ASCII string, 'A' */ #define TSHORT 21 /* signed short, 'I' */ #define TLONG 41 /* signed long, */ #define TLONGLONG 81 /* 64-bit long signed integer 'K' */ #define TFLOAT 42 /* single precision float, 'E' */ #define TDOUBLE 82 /* double precision float, 'D' */ #define TCOMPLEX 83 /* complex (pair of floats) 'C' */ #define TDBLCOMPLEX 163 /* double complex (2 doubles) 'M' */ The following data type codes are also supported by CFITSIO: #define TINT 31 /* int */ #define TSBYTE 12 /* 8-bit signed byte, 'S' */ #define TUINT 30 /* unsigned int 'V' */ #define TUSHORT 20 /* unsigned short 'U' */ #define TULONG 40 /* unsigned long */ #define TULONGLONG 80 /* unsigned long long 'W' */ The following data type code is only for use with fits\_get\_coltype #define TINT32BIT 41 /* signed 32-bit int, 'J' */ HDU type code values (value returned when moving to new HDU): #define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ #define ASCII_TBL 1 /* ASCII table HDU */ #define BINARY_TBL 2 /* Binary table HDU */ #define ANY_HDU -1 /* matches any type of HDU */ Column name and string matching case-sensitivity: #define CASESEN 1 /* do case-sensitive string match */ #define CASEINSEN 0 /* do case-insensitive string match */ Logical states (if TRUE and FALSE are not already defined): #define TRUE 1 #define FALSE 0 Values to represent undefined floating point numbers: #define FLOATNULLVALUE -9.11912E-36F #define DOUBLENULLVALUE -9.1191291391491E-36 Image compression algorithm definitions #define RICE_1 11 #define GZIP_1 21 #define GZIP_2 22 #define PLIO_1 31 #define HCOMPRESS_1 41 #define NOCOMPRESS -1 #define NO_DITHER -1 #define SUBTRACTIVE_DITHER_1 1 #define SUBTRACTIVE_DITHER_2 2 \end{verbatim} \section{Current Header Data Unit (CHDU)} The concept of the Current Header and Data Unit, or CHDU, is fundamental to the use of the CFITSIO library. A simple FITS image may only contain a single Header and Data unit (HDU), but in general FITS files can contain multiple Header Data Units (also known as `extensions'), concatenated one after the other in the file. The user can specify which HDU should be initially opened at run time by giving the HDU name or number after the root file name. For example, 'myfile.fits[4]' opens the 5th HDU in the file (note that the numbering starts with 0), and 'myfile.fits[EVENTS] opens the HDU with the name 'EVENTS' (as defined by the EXTNAME or HDUNAME keywords). If no HDU is specified then CFITSIO opens the first HDU (the primary array) by default. The CFITSIO routines which read and write data only operate within the opened HDU, Other CFITSIO routines are provided to move to and open any other existing HDU within the FITS file or to append or insert new HDUs in the FITS file. \section{Function Names and Variable Datatypes} Most of the CFITSIO routines have both a short name as well as a longer descriptive name. The short name is only 5 or 6 characters long and is similar to the subroutine name in the Fortran-77 version of FITSIO. The longer name is more descriptive and it is recommended that it be used instead of the short name to more clearly document the source code. Many of the CFITSIO routines come in families which differ only in the data type of the associated parameter(s). The data type of these routines is indicated by the suffix of the routine name. The short routine names have a 1 or 2 character suffix (e.g., 'j' in 'ffpkyj') while the long routine names have a 4 character or longer suffix as shown in the following table: \begin{verbatim} Long Short Data Names Names Type ----- ----- ---- _bit x bit _byt b unsigned byte _sbyt sb signed byte _sht i short integer _lng j long integer _lnglng jj 8-byte LONGLONG integer (see note below) _usht ui unsigned short integer _ulng uj unsigned long integer _ulnglng ujj unsigned long long integer _uint uk unsigned int integer _int k int integer _flt e real exponential floating point (float) _fixflt f real fixed-decimal format floating point (float) _dbl d double precision real floating-point (double) _fixdbl g double precision fixed-format floating point (double) _cmp c complex reals (pairs of float values) _fixcmp fc complex reals, fixed-format floating point _dblcmp m double precision complex (pairs of double values) _fixdblcmp fm double precision complex, fixed-format floating point _log l logical (int) _str s character string \end{verbatim} The logical data type corresponds to `int' for logical keyword values, and `byte' for logical binary table columns. In other words, the value when writing a logical keyword must be stored in an `int' variable, and must be stored in a `char' array when reading or writing to `L' columns in a binary table. Implicit data type conversion is not supported for logical table columns, but is for keywords, so a logical keyword may be read and cast to any numerical data type; a returned value = 0 indicates false, and any other value = true. The `int' data type may be 2 bytes long on some old PC compilers, but otherwise it is nearly always 4 bytes long. Some 64-bit machines, like the Alpha/OSF, define the `short', `int', and `long' integer data types to be 2, 4, and 8 bytes long, respectively. Because there is no universal C compiler standard for the name of the 8-byte integer datatype, the fitsio.h include file typedef's 'LONGLONG' to be equivalent to an appropriate 8-byte integer data type on each supported platform. For maximum software portability it is recommended that this LONGLONG datatype be used to define 8-byte integer variables rather than using the native data type name on a particular platform. On most 32-bit Unix and Mac OS-X operating systems LONGLONG is equivalent to the intrinsic 'long long' 8-byte integer datatype. On 64-bit systems (which currently includes Alpha OSF/1, 64-bit Sun Solaris, 64-bit SGI MIPS, and 64-bit Itanium and Opteron PC systems), LONGLONG is simply typedef'ed to be equivalent to 'long'. Microsoft Visual C++ Version 6.0 does not define a 'long long' data type, so LONGLONG is typedef'ed to be equivalent to the '\_\_int64' data type on 32-bit windows systems when using Visual C++. A related issue that affects the portability of software is how to print out the value of a 'LONGLONG' variable with printf. Developers may find it convenient to use the following preprocessing statements in their C programs to handle this in a machine-portable manner: \begin{verbatim} #if defined(_MSC_VER) /* Microsoft Visual C++ */ printf("%I64d", longlongvalue); #elif (USE_LL_SUFFIX == 1) printf("%lld", longlongvalue); #else printf("%ld", longlongvalue); #endif \end{verbatim} Similarly, the name of the C utility routine that converts a character string of digits into a 8-byte integer value is platform dependent: \begin{verbatim} #if defined(_MSC_VER) /* Microsoft Visual C++ */ /* VC++ 6.0 does not seem to have an 8-byte conversion routine */ #elif (USE_LL_SUFFIX == 1) longlongvalue = atoll(*string); #else longlongvalue = atol(*string); #endif \end{verbatim} When dealing with the FITS byte data type it is important to remember that the raw values (before any scaling by the BSCALE and BZERO, or TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte columns (TFORMn = 'B') are interpreted as unsigned bytes with values ranging from 0 to 255. Some C compilers define a 'char' variable as signed, so it is important to explicitly declare a numeric char variable as 'unsigned char' to avoid any ambiguity One feature of the CFITSIO routines is that they can operate on a `X' (bit) column in a binary table as though it were a `B' (byte) column. For example a `11X' data type column can be interpreted the same as a `2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can be more efficient to read and write whole bytes at a time, rather than reading or writing each individual bit. The complex and double precision complex data types are not directly supported in ANSI C so these data types should be interpreted as pairs of float or double values, respectively, where the first value in each pair is the real part, and the second is the imaginary part. \section{Support for Unsigned Integers and Signed Bytes} Although FITS does not directly support unsigned integers as one of its fundamental data types, FITS can still be used to efficiently store unsigned integer data values in images and binary tables. The convention used in FITS files is to store the unsigned integers as signed integers with an associated offset (specified by the BZERO or TZEROn keyword). For example, to store unsigned 16-bit integer values in a FITS image the image would be defined as a signed 16-bit integer (with BITPIX keyword = SHORT\_IMG = 16) with the keywords BSCALE = 1.0 and BZERO = 32768. Thus the unsigned values of 0, 32768, and 65535, for example, are physically stored in the FITS image as -32768, 0, and 32767, respectively; CFITSIO automatically adds the BZERO offset to these values when they are read. Similarly, in the case of unsigned 32-bit integers the BITPIX keyword would be equal to LONG\_IMG = 32 and BZERO would be equal to 2147483648 (i.e. 2 raised to the 31st power). The CFITSIO interface routines will efficiently and transparently apply the appropriate offset in these cases so in general application programs do not need to be concerned with how the unsigned values are actually stored in the FITS file. As a convenience for users, CFITSIO has several predefined constants for the value of BITPIX (USHORT\_IMG, ULONG\_IMG, ULONGLONG\_IMG) and for the TFORMn value in the case of binary tables (`U', `V', and `W') which programmers can use when creating FITS files containing unsigned integer values. The following code fragment illustrates how to write a FITS 1-D primary array of unsigned 16-bit integers: \begin{verbatim} unsigned short uarray[100]; int naxis, status; long naxes[10], group, firstelem, nelements; ... status = 0; naxis = 1; naxes[0] = 100; fits_create_img(fptr, USHORT_IMG, naxis, naxes, &status); firstelem = 1; nelements = 100; fits_write_img(fptr, TUSHORT, firstelem, nelements, uarray, &status); ... \end{verbatim} In the above example, the 2nd parameter in fits\_create\_img tells CFITSIO to write the header keywords appropriate for an array of 16-bit unsigned integers (i.e., BITPIX = 16 and BZERO = 32768). Then the fits\_write\_img routine writes the array of unsigned short integers (uarray) into the primary array of the FITS file. Similarly, a 32-bit unsigned integer image may be created by setting the second parameter in fits\_create\_img equal to `ULONG\_IMG' and by calling the fits\_write\_img routine with the second parameter = TULONG to write the array of unsigned long image pixel values. An analogous set of routines are available for reading or writing unsigned integer values and signed byte values in a FITS binary table extension. When specifying the TFORMn keyword value which defines the format of a column, CFITSIO recognizes 4 additional data type codes besides those already defined in the FITS standard: `U' meaning a 16-bit unsigned integer column, `V' for a 32-bit unsigned integer column, `W' for a 64-bit unsigned integer column, and 'S' for a signed byte column. These non-standard data type codes are not actually written into the FITS file but instead are just used internally within CFITSIO. The following code fragment illustrates how to use these features: \begin{verbatim} unsigned short uarray[100]; unsigned int varray[100]; int colnum, tfields, status; long nrows, firstrow, firstelem, nelements, pcount; char extname[] = "Test_table"; /* extension name */ /* define the name, data type, and physical units for 4 columns */ char *ttype[] = { "Col_1", "Col_2", "Col_3", "Col_4" }; char *tform[] = { "1U", "1V", "1W", "1S"}; /* special CFITSIO codes */ char *tunit[] = { " ", " ", " ", " " }; ... /* write the header keywords */ status = 0; nrows = 1; tfields = 3 pcount = 0; fits_create_tbl(fptr, BINARY_TBL, nrows, tfields, ttype, tform, tunit, extname, &status); /* write the unsigned shorts to the 1st column */ colnum = 1; firstrow = 1; firstelem = 1; nelements = 100; fits_write_col(fptr, TUSHORT, colnum, firstrow, firstelem, nelements, uarray, &status); /* now write the unsigned longs to the 2nd column */ colnum = 2; fits_write_col(fptr, TUINT, colnum, firstrow, firstelem, nelements, varray, &status); ... \end{verbatim} Note that the non-standard TFORM values for the 3 columns, `U', `V', and `W' tell CFITSIO to write the keywords appropriate for unsigned 16-bit, unsigned 32-bit and unsigned 64-bit integers, respectively (i.e., TFORMn = '1I' and TZEROn = 32768 for unsigned 16-bit integers, TFORMn = '1J' and TZEROn = 2147483648 for unsigned 32-bit integers, and TFORMn = '1K' and TZEROn = 9223372036854775808 for unsigned 64-bit integers). The 'S' TFORMn value tells CFITSIO to write the keywords appropriate for a signed 8-bit byte column with TFORMn = '1B' and TZEROn = -128. The calls to fits\_write\_col then write the arrays of unsigned integer values to the columns. \section{Dealing with Character Strings \label{character-strings}} The character string values in a FITS header or in an ASCII column in a FITS table extension are generally padded out with non-significant space characters (ASCII 32) to fill up the header record or the column width. When reading a FITS string value, the CFITSIO routines will strip off these non-significant trailing spaces and will return a null-terminated string value containing only the significant characters. Leading spaces in a FITS string are considered significant. If the string contains all blanks, then CFITSIO will return a single blank character, i.e, the first blank is considered to be significant, since it distinguishes the string from a null or undefined string, but the remaining trailing spaces are not significant. Similarly, when writing string values to a FITS file the CFITSIO routines expect to get a null-terminated string as input; CFITSIO will pad the string with blanks if necessary when writing it to the FITS file. The FITS standard does not require trailing spaces to be treated in this way, but it does allow a more seamless transition from the FORTRAN FITS world where trailing spaces are often treated as insignificant. Users who wish the greatest fidelity when transferring strings can use the \verb+_byt+ variants of column readers and writers (functions fits\_\{read,write\}\_col\_byt). These routines will transfer the raw fixed-length vectors of character bytes of the column, including any trailing blanks of course. The \verb+_byt+ variants make no attempt to null-terminate any elements. A NULL string would be indicated by its first character being a NUL byte. When calling CFITSIO routines that return a character string it is vital that the size of the char array be large enough to hold the entire string of characters, otherwise CFITSIO will overwrite whatever memory locations follow the char array, possibly causing the program to execute incorrectly. This type of error can be difficult to debug, so programmers should always ensure that the char arrays are allocated enough space to hold the longest possible string, {\bf including} the terminating NULL character. The fitsio.h file contains the following defined constants which programmers are strongly encouraged to use whenever they are allocating space for char arrays: \begin{verbatim} #define FLEN_FILENAME 1025 /* max length of a filename */ #define FLEN_KEYWORD 72 /* max length of a keyword */ #define FLEN_CARD 81 /* length of a FITS header card */ #define FLEN_VALUE 71 /* max length of a keyword value string */ #define FLEN_COMMENT 73 /* max length of a keyword comment string */ #define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ #define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ \end{verbatim} For example, when declaring a char array to hold the value string of FITS keyword, use the following statement: \begin{verbatim} char value[FLEN_VALUE]; \end{verbatim} Note that FLEN\_KEYWORD is longer than needed for the nominal 8-character keyword name because the HIERARCH convention supports longer keyword names. \section{Implicit Data Type Conversion} The CFITSIO routines that read and write numerical data can perform implicit data type conversion. This means that the data type of the variable or array in the program does not need to be the same as the data type of the value in the FITS file. Data type conversion is supported for numerical and string data types (if the string contains a valid number enclosed in quotes) when reading a FITS header keyword value and for numeric values when reading or writing values in the primary array or a table column. CFITSIO returns status = NUM\_OVERFLOW if the converted data value exceeds the range of the output data type. Implicit data type conversion is not supported within binary tables for string, logical, complex, or double complex data types. In addition, any table column may be read as if it contained string values. In the case of numeric columns the returned string will be formatted using the TDISPn display format if it exists. \section{Data Scaling} When reading numerical data values in the primary array or a table column, the values will be scaled automatically by the BSCALE and BZERO (or TSCALn and TZEROn) header values if they are present in the header. The scaled data that is returned to the reading program will have \begin{verbatim} output value = (FITS value) * BSCALE + BZERO \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when reading from table columns). In the case of integer output values the floating point scaled value is truncated to an integer (not rounded to the nearest integer). The fits\_set\_bscale and fits\_set\_tscale routines (described in the `Advanced' chapter) may be used to override the scaling parameters defined in the header (e.g., to turn off the scaling so that the program can read the raw unscaled values from the FITS file). When writing numerical data to the primary array or to a table column the data values will generally be automatically inversely scaled by the value of the BSCALE and BZERO (or TSCALn and TZEROn) keyword values if they they exist in the header. These keywords must have been written to the header before any data is written for them to have any immediate effect. One may also use the fits\_set\_bscale and fits\_set\_tscale routines to define or override the scaling keywords in the header (e.g., to turn off the scaling so that the program can write the raw unscaled values into the FITS file). If scaling is performed, the inverse scaled output value that is written into the FITS file will have \begin{verbatim} FITS value = ((input value) - BZERO) / BSCALE \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when writing to table columns). Rounding to the nearest integer, rather than truncation, is performed when writing integer data types to the FITS file. \section{Support for IEEE Special Values} The ANSI/IEEE-754 floating-point number standard defines certain special values that are used to represent such quantities as Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. (See the Appendix in the FITS standard or the FITS User's Guide for a list of these values). The CFITSIO routines that read floating point data in FITS files recognize these IEEE special values and by default interpret the overflow and infinity values as being equivalent to a NaN, and convert the underflow and denormalized values into zeros. In some cases programmers may want access to the raw IEEE values, without any modification by CFITSIO. This can be done by calling the fits\_read\_img or fits\_read\_col routines while specifying 0.0 as the value of the NULLVAL parameter. This will force CFITSIO to simply pass the IEEE values through to the application program without any modification. This is not fully supported on VAX/VMS machines, however, where there is no easy way to bypass the default interpretation of the IEEE special values. This is also not supported when reading floating-point images that have been compressed with the FITS tiled image compression convention that is discussed in section 5.6; the pixels values in tile compressed images are represented by scaled integers, and a reserved integer value (not a NaN) is used to represent undefined pixels. \section{Error Status Values and the Error Message Stack} Nearly all the CFITSIO routines return an error status value in 2 ways: as the value of the last parameter in the function call, and as the returned value of the function itself. This provides some flexibility in the way programmers can test if an error occurred, as illustrated in the following 2 code fragments: \begin{verbatim} if ( fits_write_record(fptr, card, &status) ) printf(" Error occurred while writing keyword."); or, fits_write_record(fptr, card, &status); if ( status ) printf(" Error occurred while writing keyword."); \end{verbatim} A listing of all the CFITSIO status code values is given at the end of this document. Programmers are encouraged to use the symbolic mnemonics (defined in fitsio.h) rather than the actual integer status values to improve the readability of their code. The CFITSIO library uses an `inherited status' convention for the status parameter which means that if a routine is called with a positive input value of the status parameter as input, then the routine will exit immediately without changing the value of the status parameter. Thus, if one passes the status value returned from each CFITSIO routine as input to the next CFITSIO routine, then whenever an error is detected all further CFITSIO processing will cease. This convention can simplify the error checking in application programs because it is not necessary to check the value of the status parameter after every single CFITSIO routine call. If a program contains a sequence of several CFITSIO calls, one can just check the status value after the last call. Since the returned status values are generally distinctive, it should be possible to determine which routine originally returned the error status. CFITSIO also maintains an internal stack of error messages (80-character maximum length) which in many cases provide a more detailed explanation of the cause of the error than is provided by the error status number alone. It is recommended that the error message stack be printed out whenever a program detects a CFITSIO error. The function fits\_report\_error will print out the entire error message stack, or alternatively one may call fits\_read\_errmsg to get the error messages one at a time. \section{Variable-Length Arrays in Binary Tables} CFITSIO provides easy-to-use support for reading and writing data in variable length fields of a binary table. The variable length columns have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the data type code (e.g., I, J, E, D, etc.) and `len' is an integer specifying the maximum length of the vector in the table. The 'P' type variable length columns use 32-bit array length and byte offset values, whereas the 'Q' type columns use 64-bit values, which may be required when dealing with large arrays. CFITSIO supports a local convention that interprets the 'P' type descriptors as unsigned 32-bit integers, which provides a factor of 2 greater range for the array length or heap address than is possible with 32-bit 'signed' integers. Note, however, that other software packages may not support this convention, and may be unable to read thees extended range variable length records. If the value of `len' is not specified when the table is created (e.g., if the TFORM keyword value is simply specified as '1PE' instead of '1PE(400) ), then CFITSIO will automatically scan the table when it is closed to determine the maximum length of the vector and will append this value to the TFORMn value. The same routines that read and write data in an ordinary fixed length binary table extension are also used for variable length fields, however, the routine parameters take on a slightly different interpretation as described below. All the data in a variable length field is written into an area called the `heap' which follows the main fixed-length FITS binary table. The size of the heap, in bytes, is specified by the PCOUNT keyword in the FITS header. When creating a new binary table, the initial value of PCOUNT should usually be set to zero. CFITSIO will recompute the size of the heap as the data is written and will automatically update the PCOUNT keyword value when the table is closed. When writing variable length data to a table, CFITSIO will automatically extend the size of the heap area if necessary, so that any following HDUs do not get overwritten. By default the heap data area starts immediately after the last row of the fixed-length table. This default starting location may be overridden by the THEAP keyword, but this is not recommended. If additional rows of data are added to the table, CFITSIO will automatically shift the the heap down to make room for the new rows, but it is obviously be more efficient to initially create the table with the necessary number of blank rows, so that the heap does not needed to be constantly moved. When writing row of data to a variable length field the entire array of values for a given row of the table must be written with a single call to fits\_write\_col. The total length of the array is given by nelements + firstelem - 1. Additional elements cannot be appended to an existing vector at a later time since any attempt to do so will simply overwrite all the previously written data and the new data will be written to a new area of the heap. The fits\_compress\_heap routine is provided to compress the heap and recover any unused space. To avoid having to deal with this issue, it is recommended that rows in a variable length field should only be written once. An exception to this general rule occurs when setting elements of an array as undefined. It is allowed to first write a dummy value into the array with fits\_write\_col, and then call fits\_write\_col\_nul to flag the desired elements as undefined. Note that the rows of a table, whether fixed or variable length, do not have to be written consecutively and may be written in any order. When writing to a variable length ASCII character field (e.g., TFORM = '1PA') only a single character string can be written. The `firstelem' and `nelements' parameter values in the fits\_write\_col routine are ignored and the number of characters to write is simply determined by the length of the input null-terminated character string. The fits\_write\_descript routine is useful in situations where multiple rows of a variable length column have the identical array of values. One can simply write the array once for the first row, and then use fits\_write\_descript to write the same descriptor values into the other rows; all the rows will then point to the same storage location thus saving disk space. When reading from a variable length array field one can only read as many elements as actually exist in that row of the table; reading does not automatically continue with the next row of the table as occurs when reading an ordinary fixed length table field. Attempts to read more than this will cause an error status to be returned. One can determine the number of elements in each row of a variable column with the fits\_read\_descript routine. \section{Multiple Access to the Same FITS File} CFITSIO supports simultaneous read and write access to different HDUs in the same FITS file in some circumstances, as described below: \begin{itemize} \item Multi-threaded programs When CFITSIO is compiled with the -D\_REENTRANT directive (as can be tested with the fits\_is\_reentrant function) different threads can call any of the CFITSIO routines to simultaneously read or write separate FITS files. Multiple threads can also read data from the same FITS file simultaneously, as long as the file was opened independently by each thread. This relies on the operating system to correctly deal with reading the same file by multiple processes. Different threads should not share the same 'fitsfile' pointer to read an opened FITS file, unless locks are placed around the calls to the CFITSIO reading routines. Different threads should never try to write to the same FITS file. \item Multiple read access to the same FITS file within a single program/thread A single process may open the same FITS file with READONLY access multiple times, and thus create multiple 'fitsfile*' pointers to that same file within CFITSIO. This relies on the operating system's ability to open a single file multiple times and correctly manage the subsequent read requests directed to the different C 'file*' pointers, which actually all point to the same file. CFITSIO simply executes the read requests to the differnet 'fitsfile*' pointers the same as if they were physically different files. \item Multiple write access to the same FITS file within a single program/thread CFITSIO supports opening the same FITS file multiple times with WRITE access, but it only physically opens the file (at the operating system level) once, on the first call to fits\_open\_file. If fits\_open\_file is subsequently called to open the same file again, CFITSIO will recognize that the file is already open, and will return a new 'fitsfile*' pointer that logically points to the first 'fitsfile*' pointer, without actually opening the file a second time. The application program can then treat the 2 'fitsfile*' pointers as if they point to different files, and can seemingly move to and write data to 2 different HDUs within the same file. However, each time the application program switches which 'fitsfile*' pointer it is writing to, CFITSIO will flush any internal buffers that contain data written to the first 'fitsfile*' pointer, then move to the HDU that the other 'fitsfile*' pointer is writing to. Obviously, this may add a significant amount of computational overhead if the application program uses this feature to frequently switch back and forth between writing to 2 (or more) HDUs in the same file, so this capability should be used judiciously. Note that CFITSIO will not allow a FITS file to be opened a second time with READWRITE access if it was opened previously with READONLY access. \end{itemize} \section{When the Final Size of the FITS HDU is Unknown} It is not required to know the total size of a FITS data array or table before beginning to write the data to the FITS file. In the case of the primary array or an image extension, one should initially create the array with the size of the highest dimension (largest NAXISn keyword) set to a dummy value, such as 1. Then after all the data have been written and the true dimensions are known, then the NAXISn value should be updated using the fits\_update\_key routine before moving to another extension or closing the FITS file. When writing to FITS tables, CFITSIO automatically keeps track of the highest row number that is written to, and will increase the size of the table if necessary. CFITSIO will also automatically insert space in the FITS file if necessary, to ensure that the data 'heap', if it exists, and/or any additional HDUs that follow the table do not get overwritten as new rows are written to the table. As a general rule it is best to specify the initial number of rows = 0 when the table is created, then let CFITSIO keep track of the number of rows that are actually written. The application program should not manually update the number of rows in the table (as given by the NAXIS2 keyword) since CFITSIO does this automatically. If a table is initially created with more than zero rows, then this will usually be considered as the minimum size of the table, even if fewer rows are actually written to the table. Thus, if a table is initially created with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before closing the table, then NAXIS2 will remain equal to 20. If however, 30 rows of data are written to this table, then NAXIS2 will be increased from 20 to 30. The one exception to this automatic updating of the NAXIS2 keyword is if the application program directly modifies the value of NAXIS2 (up or down) itself just before closing the table. In this case, CFITSIO does not update NAXIS2 again, since it assumes that the application program must have had a good reason for changing the value directly. This is not recommended, however, and is only provided for backward compatibility with software that initially creates a table with a large number of rows, than decreases the NAXIS2 value to the actual smaller value just before closing the table. \section{CFITSIO Size Limitations} CFITSIO places very few restrictions on the size of FITS files that it reads or writes. There are a few limits, however, that may affect some extreme cases: 1. The maximum number of FITS files that may be simultaneously opened by CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default value is 1000, but this may be increased if necessary. Note that CFITSIO allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this amounts to more than 115K of memory for each opened file (or 115 MB for 1000 opened files). Note that the underlying operating system, may have a lower limit on the number of files that can be opened simultaneously. 2. It used to be common for computer systems to only support disk files up to 2**31 bytes = 2.1 GB in size, but most systems now support larger files. CFITSIO can optionally read and write these so-called 'large files' that are greater than 2.1 GB on platforms where they are supported, but this usually requires that special compiler option flags be specified to turn on this option. On linux and solaris systems the compiler flags are '-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64'. These flags may also work on other platforms but this has not been tested. Starting with version 3.0 of CFITSIO, the default Makefile that is distributed with CFITSIO will include these 2 compiler flags when building on Solaris and Linux PC systems. Users on other platforms will need to add these compiler flags manually if they want to support large files. In most cases it appears that it is not necessary to include these compiler flags when compiling application code that call the CFITSIO library routines. When CFITSIO is built with large file support (e.g., on Solaris and Linux PC system by default) then it can read and write FITS data files on disk that have any of these conditions: \begin{itemize} \item FITS files larger than 2.1 GB in size \item FITS images containing greater than 2.1 G pixels \item FITS images that have one dimension with more than 2.1 G pixels (as given by one of the NAXISn keyword) \item FITS tables containing more than 2.1E09 rows (given by the NAXIS2 keyword), or with rows that are more than 2.1 GB wide (given by the NAXIS1 keyword) \item FITS binary tables with a variable-length array heap that is larger than 2.1 GB (given by the PCOUNT keyword) \end{itemize} The current maximum FITS file size supported by CFITSIO is about 6 terabytes (containing 2**31 FITS blocks, each 2880 bytes in size). Currently, support for large files in CFITSIO has been tested on the Linux, Solaris, and IBM AIX operating systems. Note that when writing application programs that are intended to support large files it is important to use 64-bit integer variables to store quantities such as the dimensions of images, or the number of rows in a table. These programs must also call the special versions of some of the CFITSIO routines that have been adapted to support 64-bit integers. The names of these routines end in 'll' ('el' 'el') to distinguish them from the 32-bit integer version (e.g., fits\_get\_num\_rowsll). \chapter{Basic CFITSIO Interface Routines } This chapter describes the basic routines in the CFITSIO user interface that provide all the functions normally needed to read and write most FITS files. It is recommended that these routines be used for most applications and that the more advanced routines described in the next chapter only be used in special circumstances when necessary. The following conventions are used in this chapter in the description of each function: 1. Most functions have 2 names: a long descriptive name and a short concise name. Both names are listed on the first line of the following descriptions, separated by a slash (/) character. Programmers may use either name in their programs but the long names are recommended to help document the code and make it easier to read. 2. A right arrow symbol ($>$) is used in the function descriptions to separate the input parameters from the output parameters in the definition of each routine. This symbol is not actually part of the C calling sequence. 3. The function parameters are defined in more detail in the alphabetical listing in Appendix B. 4. The first argument in almost all the functions is a pointer to a structure of type `fitsfile'. Memory for this structure is allocated by CFITSIO when the FITS file is first opened or created and is freed when the FITS file is closed. 5. The last argument in almost all the functions is the error status parameter. It must be equal to 0 on input, otherwise the function will immediately exit without doing anything. A non-zero output value indicates that an error occurred in the function. In most cases the status value is also returned as the value of the function itself. \section{CFITSIO Error Status Routines} \begin{description} \item[1 ] Return a descriptive text string (30 char max.) corresponding to a CFITSIO error status code.\label{ffgerr} \end{description} \begin{verbatim} void fits_get_errstatus / ffgerr (int status, > char *err_text) \end{verbatim} \begin{description} \item[2 ] Return the top (oldest) 80-character error message from the internal CFITSIO stack of error messages and shift any remaining messages on the stack up one level. Call this routine repeatedly to get each message in sequence. The function returns a value = 0 and a null error message when the error stack is empty. \label{ffgmsg} \end{description} \begin{verbatim} int fits_read_errmsg / ffgmsg (char *err_msg) \end{verbatim} \begin{description} \item[3 ] Print out the error message corresponding to the input status value and all the error messages on the CFITSIO stack to the specified file stream (normally to stdout or stderr). If the input status value = 0 then this routine does nothing. \label{ffrprt} \end{description} \begin{verbatim} void fits_report_error / ffrprt (FILE *stream, status) \end{verbatim} \begin{description} \item[4 ]The fits\_write\_errmark routine puts an invisible marker on the CFITSIO error stack. The fits\_clear\_errmark routine can then be used to delete any more recent error messages on the stack, back to the position of the marker. This preserves any older error messages on the stack. The fits\_clear\_errmsg routine simply clears all the messages (and marks) from the stack. These routines are called without any arguments. \label{ffpmrk} \label{ffcmsg} \end{description} \begin{verbatim} void fits_write_errmark / ffpmrk (void) void fits_clear_errmark / ffcmrk (void) void fits_clear_errmsg / ffcmsg (void) \end{verbatim} \section{FITS File Access Routines} \begin{description} \item[1 ] Open an existing data file. \label{ffopen} \begin{verbatim} int fits_open_file / ffopen (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_diskfile / ffdkopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_data / ffdopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_table / fftopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_image / ffiopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_extlist / ffeopn (fitsfile **fptr, char *filename, int iomode, char *extlist, > int *hdutype, int *status) \end{verbatim} The iomode parameter determines the read/write access allowed in the file and can have values of READONLY (0) or READWRITE (1). The filename parameter gives the name of the file to be opened, followed by an optional argument giving the name or index number of the extension within the FITS file that should be moved to and opened (e.g., \verb-myfile.fits+3- or \verb-myfile.fits[3]- moves to the 3rd extension within the file, and \verb-myfile.fits[events]- moves to the extension with the keyword EXTNAME = 'EVENTS'). The fits\_open\_diskfile routine is similar to the fits\_open\_file routine except that it does not support the extended filename syntax in the input file name. This routine simply tries to open the specified input file on magnetic disk. This routine is mainly for use in cases where the filename (or directory path) contains square or curly bracket characters that would confuse the extended filename parser. The fits\_open\_data routine is similar to the fits\_open\_file routine except that it will move to the first HDU containing significant data, if a HDU name or number to open was not explicitly specified as part of the filename. In this case, it will look for the first IMAGE HDU with NAXIS greater than 0, or the first table that does not contain the strings `GTI' (Good Time Interval extension) or `OBSTABLE' in the EXTNAME keyword value. The fits\_open\_table and fits\_open\_image routines are similar to fits\_open\_data except they will move to the first significant table HDU or image HDU in the file, respectively, if a HDU name or number is not specified as part of the filename. The fits\_open\_extlist routine opens the file and attempts to move to a 'useful' HDU. If after opening the file CFITSIO is pointing to null primary array, then CFITSIO will attempt to move to the first extension that has an EXTNAME or HDUNAME keyword value that matches one of the names in the input extlist space-delimited list of names (wildcards are permitted). If that fails, then CFITSIO simply moves to the 2nd HDU in the file. Upon return, the type of the HDU is returned in *hdutype, as described in \ref{ffmahd} HDU Access Routines. IRAF images (.imh format files) and raw binary data arrays may also be opened with READONLY access. CFITSIO will automatically test if the input file is an IRAF image, and if, so will convert it on the fly into a virtual FITS image before it is opened by the application program. If the input file is a raw binary data array of numbers, then the data type and dimensions of the array must be specified in square brackets following the name of the file (e.g. 'rawfile.dat[i512,512]' opens a 512 x 512 short integer image). See the `Extended File Name Syntax' chapter for more details on how to specify the raw file name. The raw file is converted on the fly into a virtual FITS image in memory that is then opened by the application program with READONLY access. Programs can read the input file from the 'stdin' file stream if a dash character ('-') is given as the filename. Files can also be opened over the network using FTP or HTTP protocols by supplying the appropriate URL as the filename. The HTTPS and FTPS protocols are also supported if the CFITSIO build includes the libcurl library. (If the CFITSIO 'configure' script finds a usable libcurl library on your system, it will automatically be included in the build.) The input file can be modified in various ways to create a virtual file (usually stored in memory) that is then opened by the application program by supplying a filtering or binning specifier in square brackets following the filename. Some of the more common filtering methods are illustrated in the following paragraphs, but users should refer to the 'Extended File Name Syntax' chapter for a complete description of the full file filtering syntax. When opening an image, a rectangular subset of the physical image may be opened by listing the first and last pixel in each dimension (and optional pixel skipping factor): \begin{verbatim} myimage.fits[101:200,301:400] \end{verbatim} will create and open a 100x100 pixel virtual image of that section of the physical image, and \verb+myimage.fits[*,-*]+ opens a virtual image that is the same size as the physical image but has been flipped in the vertical direction. When opening a table, the filtering syntax can be used to add or delete columns or keywords in the virtual table: \verb-myfile.fits[events][col !time; PI = PHA*1.2]- opens a virtual table in which the TIME column has been deleted and a new PI column has been added with a value 1.2 times that of the PHA column. Similarly, one can filter a table to keep only those rows that satisfy a selection criterion: \verb-myfile.fits[events][pha > 50]- creates and opens a virtual table containing only those rows with a PHA value greater than 50. A large number of boolean and mathematical operators can be used in the selection expression. One can also filter table rows using 'Good Time Interval' extensions, and spatial region filters as in \verb-myfile.fits[events][gtifilter()]- and \verb-myfile.fits[events][regfilter( "stars.rng")]-. Finally, table columns may be binned or histogrammed to generate a virtual image. For example, \verb-myfile.fits[events][bin (X,Y)=4]- will result in a 2-dimensional image calculated by binning the X and Y columns in the event table with a bin size of 4 in each dimension. The TLMINn and TLMAXn keywords will be used by default to determine the range of the image. A single program can open the same FITS file more than once and then treat the resulting fitsfile pointers as though they were completely independent FITS files. Using this facility, a program can open a FITS file twice, move to 2 different extensions within the file, and then read and write data in those extensions in any order. \end{description} \begin{description} \item[2 ] Create and open a new empty output FITS file. \label{ffinit} \begin{verbatim} int fits_create_file / ffinit (fitsfile **fptr, char *filename, > int *status) int fits_create_diskfile / ffdkinit (fitsfile **fptr, char *filename, > int *status) \end{verbatim} An error will be returned if the specified file already exists, unless the filename is prefixed with an exclamation point (!). In that case CFITSIO will overwrite (delete) any existing file with the same name. Note that the exclamation point is a special UNIX character so if it is used on the command line it must be preceded by a backslash to force the UNIX shell to accept the character as part of the filename. The output file will be written to the 'stdout' file stream if a dash character ('-') or the string 'stdout' is given as the filename. Similarly, '-.gz' or 'stdout.gz' will cause the file to be gzip compressed before it is written out to the stdout stream. Optionally, the name of a template file that is used to define the structure of the new file may be specified in parentheses following the output file name. The template file may be another FITS file, in which case the new file, at the time it is opened, will be an exact copy of the template file except that the data structures (images and tables) will be filled with zeros. Alternatively, the template file may be an ASCII format text file containing directives that define the keywords to be created in each HDU of the file. See the 'Extended File Name Syntax' section for a complete description of the template file syntax. The fits\_create\_diskfile routine is similar to the fits\_create\_file routine except that it does not support the extended filename syntax in the input file name. This routine simply tries to create the specified file on magnetic disk. This routine is mainly for use in cases where the filename (or directory path) contains square or curly bracket characters that would confuse the extended filename parser. \end{description} \begin{description} \item[3 ] Close a previously opened FITS file. The first routine simply closes the file, whereas the second one also DELETES the file, which can be useful in cases where a FITS file has been partially created, but then an error occurs which prevents it from being completed. Note that these routines behave differently than most other CFITSIO routines if the input value of the `status' parameter is not zero: Instead of simply returning to the calling program without doing anything, these routines effectively ignore the input status value and still attempt to close or delete the file. \label{ffclos} \label{ffdelt} \end{description} \begin{verbatim} int fits_close_file / ffclos (fitsfile *fptr, > int *status) int fits_delete_file / ffdelt (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[4 ]Return the name, I/O mode (READONLY or READWRITE), and/or the file type (e.g. 'file://', 'ftp://') of the opened FITS file. \label{ffflnm} \label{ffflmd} \label{ffurlt} \end{description} \begin{verbatim} int fits_file_name / ffflnm (fitsfile *fptr, > char *filename, int *status) int fits_file_mode / ffflmd (fitsfile *fptr, > int *iomode, int *status) int fits_url_type / ffurlt (fitsfile *fptr, > char *urltype, int *status) \end{verbatim} \section{HDU Access Routines} The following functions perform operations on Header-Data Units (HDUs) as a whole. \begin{description} \item[1 ] Move to a different HDU in the file. The first routine moves to a specified absolute HDU number (starting with 1 for the primary array) in the FITS file, and the second routine moves a relative number HDUs forward or backward from the current HDU. A null pointer may be given for the hdutype parameter if it's value is not needed. The third routine moves to the (first) HDU which has the specified extension type and EXTNAME and EXTVER keyword values (or HDUNAME and HDUVER keywords). The extname parameter may contain wildcards, as accepted by fits\_compare\_str(). The hdutype parameter may have a value of IMAGE\_HDU, ASCII\_TBL, BINARY\_TBL, or ANY\_HDU where ANY\_HDU means that only the extname and extver values will be used to locate the correct extension. If the input value of extver is 0 then the EXTVER keyword is ignored and the first HDU with a matching EXTNAME (or HDUNAME) keyword will be found. If no matching HDU is found in the file then the current HDU will remain unchanged and a status = BAD\_HDU\_NUM will be returned. \label{ffmahd} \label{ffmrhd} \label{ffmnhd} \end{description} \begin{verbatim} int fits_movabs_hdu / ffmahd (fitsfile *fptr, int hdunum, > int *hdutype, int *status) int fits_movrel_hdu / ffmrhd (fitsfile *fptr, int nmove, > int *hdutype, int *status) int fits_movnam_hdu / ffmnhd (fitsfile *fptr, int hdutype, char *extname, int extver, > int *status) \end{verbatim} \begin{description} \item[2 ] Return the total number of HDUs in the FITS file. This returns the number of completely defined HDUs in the file. If a new HDU has just been added to the FITS file, then that last HDU will only be counted if it has been closed, or if data has been written to the HDU. The current HDU remains unchanged by this routine. \label{ffthdu} \end{description} \begin{verbatim} int fits_get_num_hdus / ffthdu (fitsfile *fptr, > int *hdunum, int *status) \end{verbatim} \begin{description} \item[3 ] Return the number of the current HDU (CHDU) in the FITS file (where the primary array = 1). This function returns the HDU number rather than a status value. \label{ffghdn} \end{description} \begin{verbatim} int fits_get_hdu_num / ffghdn (fitsfile *fptr, > int *hdunum) \end{verbatim} \begin{description} \item[4 ] Return the type of the current HDU in the FITS file. The possible values for hdutype are: IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL. \label{ffghdt} \end{description} \begin{verbatim} int fits_get_hdu_type / ffghdt (fitsfile *fptr, > int *hdutype, int *status) \end{verbatim} \begin{description} \item[5 ] Copy all or part of the HDUs in the FITS file associated with infptr and append them to the end of the FITS file associated with outfptr. If 'previous' is true (not 0), then any HDUs preceding the current HDU in the input file will be copied to the output file. Similarly, 'current' and 'following' determine whether the current HDU, and/or any following HDUs in the input file will be copied to the output file. Thus, if all 3 parameters are true, then the entire input file will be copied. On exit, the current HDU in the input file will be unchanged, and the last HDU in the output file will be the current HDU. \label{ffcpfl} \end{description} \begin{verbatim} int fits_copy_file / ffcpfl (fitsfile *infptr, fitsfile *outfptr, int previous, int current, int following, > int *status) \end{verbatim} \begin{description} \item[6 ] Copy the current HDU from the FITS file associated with infptr and append it to the end of the FITS file associated with outfptr. Space may be reserved for MOREKEYS additional keywords in the output header. \label{ffcopy} \end{description} \begin{verbatim} int fits_copy_hdu / ffcopy (fitsfile *infptr, fitsfile *outfptr, int morekeys, > int *status) \end{verbatim} \begin{description} \item[7 ] Write the current HDU in the input FITS file to the output FILE stream (e.g., to stdout). \label{ffwrhdu} \end{description} \begin{verbatim} int fits_write_hdu / ffwrhdu (fitsfile *infptr, FILE *stream, > int *status) \end{verbatim} \begin{description} \item[8 ] Copy the header (and not the data) from the CHDU associated with infptr to the CHDU associated with outfptr. If the current output HDU is not completely empty, then the CHDU will be closed and a new HDU will be appended to the output file. An empty output data unit will be created with all values initially = 0). \label{ffcphd} \end{description} \begin{verbatim} int fits_copy_header / ffcphd (fitsfile *infptr, fitsfile *outfptr, > int *status) \end{verbatim} \begin{description} \item[9 ] Delete the CHDU in the FITS file. Any following HDUs will be shifted forward in the file, to fill in the gap created by the deleted HDU. In the case of deleting the primary array (the first HDU in the file) then the current primary array will be replace by a null primary array containing the minimum set of required keywords and no data. If there are more extensions in the file following the one that is deleted, then the the CHDU will be redefined to point to the following extension. If there are no following extensions then the CHDU will be redefined to point to the previous HDU. The output hdutype parameter returns the type of the new CHDU. A null pointer may be given for hdutype if the returned value is not needed. \label{ffdhdu} \end{description} \begin{verbatim} int fits_delete_hdu / ffdhdu (fitsfile *fptr, > int *hdutype, int *status) \end{verbatim} \section{Header Keyword Read/Write Routines} These routines read or write keywords in the Current Header Unit (CHU). Wild card characters (*, ?, or \#) may be used when specifying the name of the keyword to be read: a '?' will match any single character at that position in the keyword name and a '*' will match any length (including zero) string of characters. The '\#' character will match any consecutive string of decimal digits (0 - 9). When a wild card is used the routine will only search for a match from the current header position to the end of the header and will not resume the search from the top of the header back to the original header position as is done when no wildcards are included in the keyword name. The fits\_read\_record routine may be used to set the starting position when doing wild card searches. A status value of KEY\_NO\_EXIST is returned if the specified keyword to be read is not found in the header. \subsection{Keyword Reading Routines} \begin{description} \item[1 ] Return the number of existing keywords (not counting the END keyword) and the amount of space currently available for more keywords. It returns morekeys = -1 if the header has not yet been closed. Note that CFITSIO will dynamically add space if required when writing new keywords to a header so in practice there is no limit to the number of keywords that can be added to a header. A null pointer may be entered for the morekeys parameter if it's value is not needed. \label{ffghsp} \end{description} \begin{verbatim} int fits_get_hdrspace / ffghsp (fitsfile *fptr, > int *keysexist, int *morekeys, int *status) \end{verbatim} \begin{description} \item[2 ] Return the specified keyword. In the first routine, the datatype parameter specifies the desired returned data type of the keyword value and can have one of the following symbolic constant values: TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TLONGLONG, TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX. Within the context of this routine, TSTRING corresponds to a 'char*' data type, i.e., a pointer to a character array. Data type conversion will be performed for numeric values if the keyword value does not have the same data type. If the value of the keyword is undefined (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED will be returned. The second routine returns the keyword value as a character string (a literal copy of what is in the value field) regardless of the intrinsic data type of the keyword. The third routine returns the entire 80-character header record of the keyword, with any trailing blank characters stripped off. The fourth routine returns the (next) header record that contains the literal string of characters specified by the 'string' argument. If a NULL comment pointer is supplied then the comment string will not be returned. \label{ffgky} \label{ffgkey} \label{ffgcrd} \end{description} \begin{verbatim} int fits_read_key / ffgky (fitsfile *fptr, int datatype, char *keyname, > DTYPE *value, char *comment, int *status) int fits_read_keyword / ffgkey (fitsfile *fptr, char *keyname, > char *value, char *comment, int *status) int fits_read_card / ffgcrd (fitsfile *fptr, char *keyname, > char *card, int *status) int fits_read_str / ffgstr (fitsfile *fptr, char *string, > char *card, int *status) \end{verbatim} \begin{description} \item[3 ] Read a string-valued keyword and return the string length, the value string, and/or the commment length and comment field. These routines support the reading of long string keyword values of arbitrary length which use the CONTINUE convention. The first two routines, ffgkcsl and ffgskyc are the newer versions of the second two. They provide all the functionality of the older routines, but have the added capability of returning the length of comment strings (if any), and reading multi-line comment strings of arbitrary length. They are recommended for use in the future. ffgksl and ffgsky are maintained for backwards-compatibility. The first routine, ffgkcsl, simply returns the lengths of the character string value and comment string (if any) of the specified keyword. These lengths are particularly helpful for allocating dynamic memory when retrieving the strings in the ffgskyc function. To create an array large enough to hold the full string, one should allocate a size equal to the returned length + 1 (for the trailing NULL). The second routine, ffgskyc, is for retrieving the value string and optional comment string, both of which may be of arbitrary length spreading over multiple lines with the CONTINUE keyword convention. It will return up to maxchar characters of the keyword value string, starting with the firstchar character. Similarly, maxcomchar determines the maximum number of characters to return for the comment string. (The valuelen and comlen arguments return the total length of their respective strings regardless of what is actually returned as determined from the firstchar and max(com)char arguments.) If NULL is passed for either the value or comm string pointer, its max(com)char setting is irrelevant since the corresponding string will not be returned. The ffgksl routine is the earlier version of ffgkcsl. It only returns the value string length and not the comment string length. ffgsky, the earlier version of ffgskyc, does return both the value string and comment string. However it will only return up to the first FLEN\_COMMENT-1 characters of the comment. It can read comments across multiple lines, but not of arbitrary length. \label{ffgkcsl} \label{ffgskyc} \label{ffgksl} \label{ffgsky} \end{description} \begin{verbatim} int fits_get_key_com_strlen / ffgkcsl (fitsfile *fptr, const char *keyname, int *length, int *comlength, int *status); int fits_read_string_key_com / ffgskyc (fitsfile *fptr, const char *keyname, int firstchar, int maxchar, int maxcomchar, char *value, int *valuelen, char *comm, int *comlen, int *status); int fits_get_key_strlen / ffgksl (fitsfile *fptr, const char *keyname, int *length, int *status); int fits_read_string_key / ffgsky (fitsfile *fptr, const char *keyname, int firstchar, int maxchar, char *value, int *valuelen, char *comm, int *status); \end{verbatim} \begin{description} \item[4 ] Return the nth header record in the CHU. The first keyword in the header is at keynum = 1; if keynum = 0 then these routines simply reset the internal CFITSIO pointer to the beginning of the header so that subsequent keyword operations will start at the top of the header (e.g., prior to searching for keywords using wild cards in the keyword name). The first routine returns the entire 80-character header record (with trailing blanks truncated), while the second routine parses the record and returns the name, value, and comment fields as separate (blank truncated) character strings. If a NULL comment pointer is given on input, then the comment string will not be returned. \label{ffgrec} \label{ffgkyn} \end{description} \begin{verbatim} int fits_read_record / ffgrec (fitsfile *fptr, int keynum, > char *card, int *status) int fits_read_keyn / ffgkyn (fitsfile *fptr, int keynum, > char *keyname, char *value, char *comment, int *status) \end{verbatim} \begin{description} \item[5 ] Return the next keyword whose name matches one of the strings in 'inclist' but does not match any of the strings in 'exclist'. The strings in inclist and exclist may contain wild card characters (*, ?, and \#) as described at the beginning of this section. This routine searches from the current header position to the end of the header, only, and does not continue the search from the top of the header back to the original position. The current header position may be reset with the ffgrec routine. Note that nexc may be set = 0 if there are no keywords to be excluded. This routine returns status = KEY\_NO\_EXIST if a matching keyword is not found. \label{ffgnxk} \end{description} \begin{verbatim} int fits_find_nextkey / ffgnxk (fitsfile *fptr, char **inclist, int ninc, char **exclist, int nexc, > char *card, int *status) \end{verbatim} \begin{description} \item[6 ] Return the physical units string from an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. A null string is returned if no units are defined for the keyword. \label{ffgunt} \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed int fits_read_key_unit / ffgunt (fitsfile *fptr, char *keyname, > char *unit, int *status) \end{verbatim} \begin{description} \item[7 ] Concatenate the header keywords in the CHDU into a single long string of characters. This provides a convenient way of passing all or part of the header information in a FITS HDU to other subroutines. Each 80-character fixed-length keyword record is appended to the output character string, in order, with no intervening separator or terminating characters. The last header record is terminated with a NULL character. These routine allocates memory for the returned character array, so the calling program must free the memory when finished. The cleanest way to do this is to call the fits\_free\_memory routine. There are 2 related routines: fits\_hdr2str simply concatenates all the existing keywords in the header; fits\_convert\_hdr2str is similar, except that if the CHDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of the corresponding normal FITS image before concatenating the keywords. Selected keywords may be excluded from the returned character string. If the second parameter (nocomments) is TRUE (nonzero) then any COMMENT, HISTORY, or blank keywords in the header will not be copied to the output string. The 'exclist' parameter may be used to supply a list of keywords that are to be excluded from the output character string. Wild card characters (*, ?, and \#) may be used in the excluded keyword names. If no additional keywords are to be excluded, then set nexc = 0 and specify NULL for the the **exclist parameter. \label{ffhdr2str} \end{description} \begin{verbatim} int fits_hdr2str / ffhdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) int fits_convert_hdr2str / ffcnvthdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) int fits_free_memory / fffree (char *header, > int *status); \end{verbatim} \subsection{Keyword Writing Routines} \begin{description} \item[1 ] Write a keyword of the appropriate data type into the CHU. The first routine simply appends a new keyword whereas the second routine will update the value and comment fields of the keyword if it already exists, otherwise it appends a new keyword. Note that the address to the value, and not the value itself, must be entered. The datatype parameter specifies the data type of the keyword value with one of the following values: TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE. Within the context of this routine, TSTRING corresponds to a 'char*' data type, i.e., a pointer to a character array. A null pointer may be entered for the comment parameter in which case the keyword comment field will be unmodified or left blank. \label{ffpky} \label{ffuky} \end{description} \begin{verbatim} int fits_write_key / ffpky (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, char *comment, > int *status) int fits_update_key / ffuky (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, char *comment, > int *status) \end{verbatim} \begin{description} \item[2 ] Write a keyword with a null or undefined value (i.e., the value field in the keyword is left blank). The first routine simply appends a new keyword whereas the second routine will update the value and comment fields of the keyword if it already exists, otherwise it appends a new keyword. A null pointer may be entered for the comment parameter in which case the keyword comment field will be unmodified or left blank. \label{ffpkyu} \label{ffukyu} \end{description} \begin{verbatim} int fits_write_key_null / ffpkyu (fitsfile *fptr, char *keyname, char *comment, > int *status) int fits_update_key_null / ffukyu (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \begin{description} \item[3 ] Write (append) a COMMENT or HISTORY keyword to the CHU. The comment or history string will be continued over multiple keywords if it is longer than 70 characters. \label{ffpcom} \label{ffphis} \end{description} \begin{verbatim} int fits_write_comment / ffpcom (fitsfile *fptr, char *comment, > int *status) int fits_write_history / ffphis (fitsfile *fptr, char *history, > int *status) \end{verbatim} \begin{description} \item[4 ] Write the DATE keyword to the CHU. The keyword value will contain the current system date as a character string in 'yyyy-mm-ddThh:mm:ss' format. If a DATE keyword already exists in the header, then this routine will simply update the keyword value with the current date. \label{ffpdat} \end{description} \begin{verbatim} int fits_write_date / ffpdat (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[5 ]Write a user specified keyword record into the CHU. This is a low--level routine which can be used to write any arbitrary record into the header. The record must conform to the all the FITS format requirements. \label{ffprec} \end{description} \begin{verbatim} int fits_write_record / ffprec (fitsfile *fptr, char *card, > int *status) \end{verbatim} \begin{description} \item[6 ]Update an 80-character record in the CHU. If a keyword with the input name already exists, then it is overwritten by the value of card. This could modify the keyword name as well as the value and comment fields. If the keyword doesn't already exist then a new keyword card is appended to the header. \label{ffucrd} \end{description} \begin{verbatim} int fits_update_card / ffucrd (fitsfile *fptr, char *keyname, char *card, > int *status) \end{verbatim} \begin{description} \item[7 ] Modify (overwrite) the comment field of an existing keyword. \label{ffmcom} \end{description} \begin{verbatim} int fits_modify_comment / ffmcom (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \begin{description} \item[8 ] Write the physical units string into an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. \label{ffpunt} \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed int fits_write_key_unit / ffpunt (fitsfile *fptr, char *keyname, char *unit, > int *status) \end{verbatim} \begin{description} \item[9 ] Rename an existing keyword, preserving the current value and comment fields. \label{ffmnam} \end{description} \begin{verbatim} int fits_modify_name / ffmnam (fitsfile *fptr, char *oldname, char *newname, > int *status) \end{verbatim} \begin{description} \item[10] Delete a keyword record. The space occupied by the keyword is reclaimed by moving all the following header records up one row in the header. The first routine deletes a keyword at a specified position in the header (the first keyword is at position 1), whereas the second routine deletes a specifically named keyword. Wild card characters may be used when specifying the name of the keyword to be deleted. The third routine deletes the (next) keyword that contains the literal character string specified by the 'string' argument.\label{ffdrec} \label{ffdkey} \end{description} \begin{verbatim} int fits_delete_record / ffdrec (fitsfile *fptr, int keynum, > int *status) int fits_delete_key / ffdkey (fitsfile *fptr, char *keyname, > int *status) int fits_delete_str / ffdstr (fitsfile *fptr, char *string, > int *status) \end{verbatim} \section{Primary Array or IMAGE Extension I/O Routines} These routines read or write data values in the primary data array (i.e., the first HDU in a FITS file) or an IMAGE extension. There are also routines to get information about the data type and size of the image. Users should also read the following chapter on the CFITSIO iterator function which provides a more `object oriented' method of reading and writing images. The iterator function is a little more complicated to use, but the advantages are that it usually takes less code to perform the same operation, and the resulting program often runs faster because the FITS files are read and written using the most efficient block size. C programmers should note that the ordering of arrays in FITS files, and hence in all the CFITSIO calls, is more similar to the dimensionality of arrays in Fortran rather than C. For instance if a FITS image has NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just large enough to hold the image should be declared as array[50][100] and not as array[100][50]. The `datatype' parameter specifies the data type of the `nulval' and `array' pointers and can have one of the following values: TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TULONGLONG, TFLOAT, TDOUBLE. Automatic data type conversion is performed if the data type of the FITS array (as defined by the BITPIX keyword) differs from that specified by 'datatype'. The data values are also automatically scaled by the BSCALE and BZERO keyword values as they are being read or written in the FITS array. \begin{description} \item[1 ] Get the data type or equivalent data type of the image. The first routine returns the physical data type of the FITS image, as given by the BITPIX keyword, with allowed values of BYTE\_IMG (8), SHORT\_IMG (16), LONG\_IMG (32), LONGLONG\_IMG (64), FLOAT\_IMG (-32), and DOUBLE\_IMG (-64). The second routine is similar, except that if the image pixel values are scaled, with non-default values for the BZERO and BSCALE keywords, then the routine will return the 'equivalent' data type that is needed to store the scaled values. For example, if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is FLOAT\_IMG. Similarly if BITPIX = 16, BSCALE = 1, and BZERO = 32768, then the the pixel values span the range of an unsigned short integer and the returned data type will be USHORT\_IMG. \label{ffgidt} \end{description} \begin{verbatim} int fits_get_img_type / ffgidt (fitsfile *fptr, > int *bitpix, int *status) int fits_get_img_equivtype / ffgiet (fitsfile *fptr, > int *bitpix, int *status) \end{verbatim} \begin{description} \item[2 ] Get the number of dimensions, and/or the size of each dimension in the image . The number of axes in the image is given by naxis, and the size of each dimension is given by the naxes array (a maximum of maxdim dimensions will be returned). \label{ffgidm} \label{ffgisz} \label{ffgipr} \end{description} \begin{verbatim} int fits_get_img_dim / ffgidm (fitsfile *fptr, > int *naxis, int *status) int fits_get_img_size / ffgisz (fitsfile *fptr, int maxdim, > long *naxes, int *status) int fits_get_img_sizell / ffgiszll (fitsfile *fptr, int maxdim, > LONGLONG *naxes, int *status) int fits_get_img_param / ffgipr (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, long *naxes, int *status) int fits_get_img_paramll / ffgiprll (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, LONGLONG *naxes, int *status) \end{verbatim} \begin{description} \item[3 ]Create a new primary array or IMAGE extension with a specified data type and size. If the FITS file is currently empty then a primary array is created, otherwise a new IMAGE extension is appended to the file. \label{ffcrim} \end{description} \begin{verbatim} int fits_create_img / ffcrim ( fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_create_imgll / ffcrimll ( fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \begin{description} \item[4 ] Copy an n-dimensional image in a particular row and column of a binary table (in a vector column) to or from a primary array or image extension. The 'cell2image' routine will append a new image extension (or primary array) to the output file. Any WCS keywords associated with the input column image will be translated into the appropriate form for an image extension. Any other keywords in the table header that are not specifically related to defining the binary table structure or to other columns in the table will also be copied to the header of the output image. The 'image2cell' routine will copy the input image into the specified row and column of the current binary table in the output file. The binary table HDU must exist before calling this routine, but it may be empty, with no rows or columns of data. The specified column (and row) will be created if it does not already exist. The 'copykeyflag' parameter controls which keywords are copied from the input image to the header of the output table: 0 = no keywords will be copied, 1 = all keywords will be copied (except those keywords that would be invalid in the table header), and 2 = copy only the WCS keywords. \label{copycell} \end{description} \begin{verbatim} int fits_copy_cell2image (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, > int *status) int fits_copy_image2cell (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, int copykeyflag > int *status) \end{verbatim} \begin{description} \item[5 ] Write a rectangular subimage (or the whole image) to the FITS data array. The fpixel and lpixel arrays give the coordinates of the first (lower left corner) and last (upper right corner) pixels in FITS image to be written to. \label{ffpss} \end{description} \begin{verbatim} int fits_write_subset / ffpss (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[6 ] Write pixels into the FITS data array. 'fpixel' is an array of length NAXIS which gives the coordinate of the starting pixel to be written to, such that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, etc. The first pair of routines simply writes the array of pixels to the FITS file (doing data type conversion if necessary) whereas the second routines will substitute the appropriate FITS null value for any elements which are equal to the input value of nulval (note that this parameter gives the address of the null value, not the null value itself). For integer FITS arrays, the FITS null value is defined by the BLANK keyword (an error is returned if the BLANK keyword doesn't exist). For floating point FITS arrays the special IEEE NaN (Not-a-Number) value will be written into the FITS file. If a null pointer is entered for nulval, then the null value is ignored and this routine behaves the same as fits\_write\_pix. \label{ffppx} \label{ffppxn} \end{description} \begin{verbatim} int fits_write_pix / ffppx (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, DTYPE *array, int *status); int fits_write_pixll / ffppxll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, DTYPE *array, int *status); int fits_write_pixnull / ffppxn (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status); int fits_write_pixnullll / ffppxnll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status); \end{verbatim} \begin{description} \item[7 ] Set FITS data array elements equal to the appropriate null pixel value. For integer FITS arrays, the FITS null value is defined by the BLANK keyword (an error is returned if the BLANK keyword doesn't exist). For floating point FITS arrays the special IEEE NaN (Not-a-Number) value will be written into the FITS file. Note that 'firstelem' is a scalar giving the offset to the first pixel to be written in the equivalent 1-dimensional array of image pixels. \label{ffpprn} \end{description} \begin{verbatim} int fits_write_null_img / ffpprn (fitsfile *fptr, LONGLONG firstelem, LONGLONG nelements, > int *status) \end{verbatim} \begin{description} \item[8 ] Read a rectangular subimage (or the whole image) from the FITS data array. The fpixel and lpixel arrays give the coordinates of the first (lower left corner) and last (upper right corner) pixels to be read from the FITS image. Undefined FITS array elements will be returned with a value = *nullval, (note that this parameter gives the address of the null value, not the null value itself) unless nulval = 0 or *nulval = 0, in which case no checks for undefined pixels will be performed. \label{ffgsv} \end{description} \begin{verbatim} int fits_read_subset / ffgsv (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, long *inc, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[9 ] Read pixels from the FITS data array. 'fpixel' is the starting pixel location and is an array of length NAXIS such that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, etc. The nelements parameter specifies the number of pixels to read. If fpixel is set to the first pixel, and nelements is set equal to the NAXIS1 value, then this routine would read the first row of the image. Alternatively, if nelements is set equal to NAXIS1 * NAXIS2 then it would read an entire 2D image, or the first plane of a 3-D datacube. The first 2 routines will return any undefined pixels in the FITS array equal to the value of *nullval (note that this parameter gives the address of the null value, not the null value itself) unless nulval = 0 or *nulval = 0, in which case no checks for undefined pixels will be performed. The second 2 routines are similar except that any undefined pixels will have the corresponding nullarray element set equal to TRUE (= 1). \label{ffgpxv} \label{ffgpxf} \end{description} \begin{verbatim} int fits_read_pix / ffgpxv (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) int fits_read_pixll / ffgpxvll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) int fits_read_pixnull / ffgpxf (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) int fits_read_pixnullll / ffgpxfll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[10] Copy a rectangular section of an image and write it to a new FITS primary image or image extension. The new image HDU is appended to the end of the output file; all the keywords in the input image will be copied to the output image. The common WCS keywords will be updated if necessary to correspond to the coordinates of the section. The format of the section expression is same as specifying an image section using the extended file name syntax (see "Image Section" in Chapter 10). (Examples: "1:100,1:200", "1:100:2, 1:*:2", "*, -*"). \label{ffcpimg} \end{description} \begin{verbatim} int fits_copy_image_section / ffcpimg (fitsfile *infptr, fitsfile *outfptr, char *section, int *status) \end{verbatim} \section{Image Compression} CFITSIO transparently supports the 2 methods of image compression described below. 1) The entire FITS file may be externally compressed with the gzip or Unix compress utility programs, producing a *.gz or *.Z file, respectively. When reading compressed files of this type, CFITSIO first uncompresses the entire file into memory before performing the requested read operations. Output files can be directly written in the gzip compressed format if the user-specified filename ends with `.gz'. In this case, CFITSIO initially writes the uncompressed file in memory and then compresses it and writes it to disk when the FITS file is closed, thus saving user disk space. Read and write access to these compressed FITS files is generally quite fast since all the I/O is performed in memory; the main limitation with this technique is that there must be enough available memory (or swap space) to hold the entire uncompressed FITS file. 2) CFITSIO also supports the FITS tiled image compression convention in which the image is subdivided into a grid of rectangular tiles, and each tile of pixels is individually compressed. The details of this FITS compression convention are described at the FITS Support Office web site at http://fits.gsfc.nasa.gov/fits\_registry.html, and in the fpackguide pdf file that is included with the CFITSIO source file distributions Basically, the compressed image tiles are stored in rows of a variable length array column in a FITS binary table, however CFITSIO recognizes that this binary table extension contains an image and treats it as if it were an IMAGE extension. This tile-compressed format is especially well suited for compressing very large images because a) the FITS header keywords remain uncompressed for rapid read access, and because b) it is possible to extract and uncompress sections of the image without having to uncompress the entire image. This format is also much more effective in compressing floating point images than simply compressing the image using gzip or compress because it approximates the floating point values with scaled integers which can then be compressed more efficiently. Currently CFITSIO supports 3 general purpose compression algorithms plus one other special-purpose compression technique that is designed for data masks with positive integer pixel values. The 3 general purpose algorithms are GZIP, Rice, and HCOMPRESS, and the special purpose algorithm is the IRAF pixel list compression technique (PLIO). There are 2 variants of the GZIP algorithm: GZIP\_1 compresses the array of image pixel value normally with the GZIP algorithm, while GZIP\_2 first shuffles the bytes in all the pixel values so that the most-significant byte of every pixel appears first, followed by the less significant bytes in sequence. GZIP\_2 may be more effective in cases where the most significant byte in most of the image pixel values contains the same bit pattern. In principle, any number of other compression algorithms could also be supported by the FITS tiled image compression convention. The FITS image can be subdivided into any desired rectangular grid of compression tiles. With the GZIP, Rice, and PLIO algorithms, the default is to take each row of the image as a tile. The HCOMPRESS algorithm is inherently 2-dimensional in nature, so the default in this case is to take 16 rows of the image per tile. In most cases it makes little difference what tiling pattern is used, so the default tiles are usually adequate. In the case of very small images, it could be more efficient to compress the whole image as a single tile. Note that the image dimensions are not required to be an integer multiple of the tile dimensions; if not, then the tiles at the edges of the image will be smaller than the other tiles. The 4 supported image compression algorithms are all 'loss-less' when applied to integer FITS images; the pixel values are preserved exactly with no loss of information during the compression and uncompression process. In addition, the HCOMPRESS algorithm supports a 'lossy' compression mode that will produce larger amount of image compression. This is achieved by specifying a non-zero value for the HCOMPRESS ``scale'' parameter. Since the amount of compression that is achieved depends directly on the RMS noise in the image, it is usually more convention to specify the HCOMPRESS scale factor relative to the RMS noise. Setting s = 2.5 means use a scale factor that is 2.5 times the calculated RMS noise in the image tile. In some cases it may be desirable to specify the exact scaling to be used, instead of specifying it relative to the calculated noise value. This may be done by specifying the negative of desired scale value (typically in the range -2 to -100). Very high compression factors (of 100 or more) can be achieved by using large HCOMPRESS scale values, however, this can produce undesirable ``blocky'' artifacts in the compressed image. A variation of the HCOMPRESS algorithm (called HSCOMPRESS) can be used in this case to apply a small amount of smoothing of the image when it is uncompressed to help cover up these artifacts. This smoothing is purely cosmetic and does not cause any significant change to the image pixel values. Floating point FITS images (which have BITPIX = -32 or -64) usually contain too much ``noise'' in the least significant bits of the mantissa of the pixel values to be effectively compressed with any lossless algorithm. Consequently, floating point images are first quantized into scaled integer pixel values (and thus throwing away much of the noise) before being compressed with the specified algorithm (either GZIP, Rice, or HCOMPRESS). This technique produces much higher compression factors than simply using the GZIP utility to externally compress the whole FITS file, but it also means that the original floating value pixel values are not exactly preserved. When done properly, this integer scaling technique will only discard the insignificant noise while still preserving all the real information in the image. The amount of precision that is retained in the pixel values is controlled by the "quantization level" parameter, q. Larger values of q will result in compressed images whose pixels more closely match the floating point pixel values, but at the same time the amount of compression that is achieved will be reduced. Users should experiment with different values for this parameter to determine the optimal value that preserves all the useful information in the image, without needlessly preserving all the ``noise'' which will hurt the compression efficiency. The default value for the quantization scale factor is 4.0, which means that scaled integer pixel values will be quantized such that the difference between adjacent integer values will be 1/4th of the noise level in the image background. CFITSIO uses an optimized algorithm to accurately estimate the noise in the image. As an example, if the RMS noise in the background pixels of an image = 32.0, then the spacing between adjacent scaled integer pixel values will equal 8.0 by default. Note that the RMS noise is independently calculated for each tile of the image, so the resulting integer scaling factor may fluctuate slightly for each tile. In some cases it may be desirable to specify the exact quantization level to be used, instead of specifying it relative to the calculated noise value. This may be done by specifying the negative of desired quantization level for the value of q. In the previous example, one could specify q = -8.0 so that the quantized integer levels differ by exactly 8.0. Larger negative values for q means that the levels are more coarsely spaced, and will produce higher compression factors. When floating point images are being quantized, one must also specify what quantization method is to be used. The default algorithm is called ``SUBTRACTIVE\_DITHER\_1''. A second variation called ``SUBTRACTIVE\_DITHER\_2'' is also available, which does the same thing except that any pixels with a value of 0.0 are not dithered and instead the zero values are exactly preserved in the compressed image. This is intended for the special case where ``bad pixels'' in the image have been artifically set to zero to indicate that they have no valid value. It is not currently supported with HCOMPRESS, and if requested while using HCOMPRESS, it will be replaced with ``SUBTRACTIVE\_DITHER\_1''. One may also turn off dithering completely with the ``NO\_DITHER'' option, but this is not recommended because it can cause larger systematic errors in measurements of the position or brightness of objects in the compressed image. There are 3 methods for specifying all the parameters needed to write a FITS image in the tile compressed format. The parameters may either be specified at run time as part of the file name of the output compressed FITS file, or the writing program may call a set of helper CFITSIO subroutines that are provided for specifying the parameter values, or ``compression directive'' keywords may be added to the header of each image HDU to specify the compression parameters. These 3 methods are described below. 1) At run time, when specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format by enclosing the compression parameters in square brackets following the root disk file name in the following format: \begin{verbatim} [compress NAME T1,T2; q[z] QLEVEL, s HSCALE] \end{verbatim} where \begin{verbatim} NAME = algorithm name: GZIP, Rice, HCOMPRESS, HSCOMPRSS or PLIO may be abbreviated to the first letter (or HS for HSCOMPRESS) T1,T2 = tile dimension (e.g. 100,100 for square tiles 100 pixels wide) QLEVEL = quantization level for floating point FITS images HSCALE = HCOMPRESS scale factor; default = 0 which is lossless. \end{verbatim} Here are a few examples of this extended syntax: \begin{verbatim} myfile.fit[compress] - use the default compression algorithm (Rice) and the default tile size (row by row) myfile.fit[compress G] - use the specified compression algorithm; myfile.fit[compress R] only the first letter of the algorithm myfile.fit[compress P] should be given. myfile.fit[compress H] myfile.fit[compress R 100,100] - use Rice and 100 x 100 pixel tiles myfile.fit[compress R; q 10.0] - quantization level = (RMS-noise) / 10. myfile.fit[compress R; qz 10.0] - quantization level = (RMS-noise) / 10. also use the SUBTRACTIVE_DITHER_2 quantization method myfile.fit[compress HS; s 2.0] - HSCOMPRESS (with smoothing) and scale = 2.0 * RMS-noise \end{verbatim} 2) Before calling the CFITSIO routine to write the image header keywords (e.g., fits\_create\_image) the programmer can call the routines described below to specify the compression algorithm and the tiling pattern that is to be used. There are routines for specifying the various compression parameters and similar routines to return the current values of the parameters: \label{ffsetcomp} \label{ffgetcomp} \begin{verbatim} int fits_set_compression_type(fitsfile *fptr, int comptype, int *status) int fits_set_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) int fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status) int fits_set_quantize_method(fitsfile *fptr, int method, int *status) int fits_set_quantize_dither(fitsfile *fptr, int dither, int *status) int fits_set_dither_seed(fitsfile *fptr, int seed, int *status) int fits_set_dither_offset(fitsfile *fptr, int offset, int *status) int fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status) this forces integer image to be converted to floats, then quantized int fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); this should be called when the compressed image size is more than 4 GB. int fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status) int fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status) Set smooth = 1 to apply smoothing when uncompressing the image int fits_get_compression_type(fitsfile *fptr, int *comptype, int *status) int fits_get_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) int fits_get_quantize_level(fitsfile *fptr, float *level, int *status) int fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status) \end{verbatim} Several symbolic constants are defined for use as the value of the `comptype' parameter: GZIP\_1, GZIP\_2, RICE\_1, HCOMPRESS\_1 or PLIO\_1. Entering NULL for comptype will turn off the tile-compression and cause normal FITS images to be written. There are also defined symbolic constants for the quantization method: ``SUBTRACTIVE\_DITHER\_1'', ``SUBTRACTIVE\_DITHER\_2'', and ``NO\_DITHER''. 3) CFITSIO will uses the values of the following keywords, if they are present in the header of the image HDU, to determine how to compress that HDU. These keywords override any compression parameters that were specified with the previous 2 methods. \begin{verbatim} FZALGOR - 'RICE_1' , 'GZIP_1', 'GZIP_2', 'HCOMPRESS_1', 'PLIO_1', 'NONE' FZTILE - 'ROW', 'WHOLE', or '(n,m)' FZQVALUE - float value (default = 4.0) FZQMETHD - 'SUBTRACTIVE_DITHER_1', 'SUBTRACTIVE_DITHER_2', 'NO_DITHER' FZDTHRSD - 'CLOCK', 'CHECKSUM', 1 - 10000 FZINT2F - T, or F: Convert integers to floats, then quantize? FZHSCALE - float value (default = 0). Hcompress scale value. \end{verbatim} No special action is required by software when read tile-compressed images because all the CFITSIO routines that read normal uncompressed FITS images also transparently read images in the tile-compressed format; CFITSIO essentially treats the binary table that contains the compressed tiles as if it were an IMAGE extension. The following 2 routines are available for compressing or or decompressing an image: \begin{verbatim} int fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); int fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); \end{verbatim} Before calling the compression routine, the compression parameters must first be defined in one of the 3 way described in the previous paragraphs. There is also a routine to determine if the current HDU contains a tile compressed image (it returns 1 or 0): \begin{verbatim} int fits_is_compressed_image(fitsfile *fptr, int *status); \end{verbatim} A small example program called 'imcopy' is included with CFITSIO that can be used to compress (or uncompress) any FITS image. This program can be used to experiment with the various compression options on existing FITS images as shown in these examples: \begin{verbatim} 1) imcopy infile.fit 'outfile.fit[compress]' This will use the default compression algorithm (Rice) and the default tile size (row by row) 2) imcopy infile.fit 'outfile.fit[compress GZIP]' This will use the GZIP compression algorithm and the default tile size (row by row). The allowed compression algorithms are Rice, GZIP, and PLIO. Only the first letter of the algorithm name needs to be specified. 3) imcopy infile.fit 'outfile.fit[compress G 100,100]' This will use the GZIP compression algorithm and 100 X 100 pixel tiles. 4) imcopy infile.fit 'outfile.fit[compress R 100,100; qz 10.0]' This will use the Rice compression algorithm, 100 X 100 pixel tiles, and quantization level = RMSnoise / 10.0 (assuming the input image has a floating point data type). By specifying qz instead of q, this means use the subtractive dither2 quantization method. 5) imcopy infile.fit outfile.fit If the input file is in tile-compressed format, then it will be uncompressed to the output file. Otherwise, it simply copies the input image to the output image. 6) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit This extracts a 500 X 500 pixel section of the much larger input image (which may be in tile-compressed format). The output is a normal uncompressed FITS image. 7) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit.gz Same as above, except the output file is externally compressed using the gzip algorithm. \end{verbatim} \section{ASCII and Binary Table Routines} These routines perform read and write operations on columns of data in FITS ASCII or Binary tables. Note that in the following discussions, the first row and column in a table is at position 1 not 0. Users should also read the following chapter on the CFITSIO iterator function which provides a more `object oriented' method of reading and writing table columns. The iterator function is a little more complicated to use, but the advantages are that it usually takes less code to perform the same operation, and the resulting program often runs faster because the FITS files are read and written using the most efficient block size. \subsection{Create New Table} \begin{description} \item[1 ]Create a new ASCII or bintable table extension. If the FITS file is currently empty then a dummy primary array will be created before appending the table extension to it. The tbltype parameter defines the type of table and can have values of ASCII\_TBL or BINARY\_TBL. The naxis2 parameter gives the initial number of rows to be created in the table, and should normally be set = 0. CFITSIO will automatically increase the size of the table as additional rows are written. A non-zero number of rows may be specified to reserve space for that many rows, even if a fewer number of rows will be written. The tunit and extname parameters are optional and a null pointer may be given if they are not defined. The FITS Standard recommends that only letters, digits, and the underscore character be used in column names (the ttype parameter) with no embedded spaces. Trailing blank characters are not significant. \label{ffcrtb} \end{description} \begin{verbatim} int fits_create_tbl / ffcrtb (fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char *ttype[], char *tform[], char *tunit[], char *extname, int *status) \end{verbatim} \begin{description} \item[2 ] Copy the structure of an open table to a new table, optionally copying zero or more rows from the input table. This is useful in cases where a task will filter rows from the input before transferring to the output, so a ``pristine'' output table with zero rows is desired to start. The input file must be open and point to a binary table extension. The output file must be open for writing; a new extension is created with the same table structure as the input. Optionally, a range of nrows may be copied starting from firstrow, similar to fits\_copy\_rows(). The value nrows may be 0. Note that the first row in a table is at row = 1. \label{ffcpht} \end{description} \begin{verbatim} int fits_copy_hdutab / ffcpht (fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, > int *status) \end{verbatim} \subsection{Column Information Routines} \begin{description} \item[1 ] Get the number of rows or columns in the current FITS table. The number of rows is given by the NAXIS2 keyword and the number of columns is given by the TFIELDS keyword in the header of the table. \label{ffgnrw} \end{description} \begin{verbatim} int fits_get_num_rows / ffgnrw (fitsfile *fptr, > long *nrows, int *status); int fits_get_num_rowsll / ffgnrwll (fitsfile *fptr, > LONGLONG *nrows, int *status); int fits_get_num_cols / ffgncl (fitsfile *fptr, > int *ncols, int *status); \end{verbatim} \begin{description} \item[2 ] Get the table column number (and name) of the column whose name matches an input template name. If casesen = CASESEN then the column name match will be case-sensitive, whereas if casesen = CASEINSEN then the case will be ignored. As a general rule, the column names should be treated as case INsensitive. The input column name template may be either the exact name of the column to be searched for, or it may contain wild card characters (*, ?, or \#), or it may contain the integer number of the desired column (with the first column = 1). The `*' wild card character matches any sequence of characters (including zero characters) and the `?' character matches any single character. The \# wildcard will match any consecutive string of decimal digits (0-9). If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to COL\_NOT\_UNIQUE as a warning that a unique match was not found. To find the other cases that match the template, call the routine again leaving the input status value equal to COL\_NOT\_UNIQUE and the next matching name will then be returned. Repeat this process until a status = COL\_NOT\_FOUND is returned. The FITS Standard recommends that only letters, digits, and the underscore character be used in column names (with no embedded spaces). Trailing blank characters are not significant. \label{ffgcno} \label{ffgcnn} \end{description} \begin{verbatim} int fits_get_colnum / ffgcno (fitsfile *fptr, int casesen, char *templt, > int *colnum, int *status) int fits_get_colname / ffgcnn (fitsfile *fptr, int casesen, char *templt, > char *colname, int *colnum, int *status) \end{verbatim} \begin{description} \item[3 ] Return the data type, vector repeat value, and the width in bytes of a column in an ASCII or binary table. Allowed values for the data type in ASCII tables are: TSTRING, TSHORT, TLONG, TFLOAT, and TDOUBLE. Binary tables also support these types: TLOGICAL, TBIT, TBYTE, TLONGLONG, TCOMPLEX and TDBLCOMPLEX. The negative of the data type code value is returned if it is a variable length array column. Note that in the case of a 'J' 32-bit integer binary table column, this routine will return data type = TINT32BIT (which in fact is equivalent to TLONG). With most current C compilers, a value in a 'J' column has the same size as an 'int' variable, and may not be equivalent to a 'long' variable, which is 64-bits long on an increasing number of compilers. The 'repeat' parameter returns the vector repeat count on the binary table TFORMn keyword value. (ASCII table columns always have repeat = 1). The 'width' parameter returns the width in bytes of a single column element (e.g., a '10D' binary table column will have width = 8, an ASCII table 'F12.2' column will have width = 12, and a binary table'60A' character string column will have width = 60); Note that CFITSIO supports the local convention for specifying arrays of fixed length strings within a binary table character column using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this means that each row of the table contains 5 12-character substrings within the 60-character field, and thus in this case this routine will return typecode = TSTRING, repeat = 60, and width = 12. (The TDIMn keyword may also be used to specify the unit string length; The pair of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the same effect as TFORMn = '60A12'). The number of substrings in any binary table character string field can be calculated by (repeat/width). A null pointer may be given for any of the output parameters that are not needed. The second routine, fit\_get\_eqcoltype is similar except that in the case of scaled integer columns it returns the 'equivalent' data type that is needed to store the scaled values, and not necessarily the physical data type of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be TUSHORT, not TSHORT. Similarly, if a column has TTYPEn = '1I' and TSCALn = 0.12, then the returned typecode will be TFLOAT. \label{ffgtcl} \end{description} \begin{verbatim} int fits_get_coltype / ffgtcl (fitsfile *fptr, int colnum, > int *typecode, long *repeat, long *width, int *status) int fits_get_coltypell / ffgtclll (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, LONGLONG *width, int *status) int fits_get_eqcoltype / ffeqty (fitsfile *fptr, int colnum, > int *typecode, long *repeat, long *width, int *status) int fits_get_eqcoltypell / ffeqtyll (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, LONGLONG *width, int *status) \end{verbatim} \begin{description} \item[4 ] Return the display width of a column. This is the length of the string that will be returned by the fits\_read\_col routine when reading the column as a formatted string. The display width is determined by the TDISPn keyword, if present, otherwise by the data type of the column. \label{ffgcdw} \end{description} \begin{verbatim} int fits_get_col_display_width / ffgcdw (fitsfile *fptr, int colnum, > int *dispwidth, int *status) \end{verbatim} \begin{description} \item[5 ] Return the number of and size of the dimensions of a table column in a binary table. Normally this information is given by the TDIMn keyword, but if this keyword is not present then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. \label{ffgtdm} \end{description} \begin{verbatim} int fits_read_tdim / ffgtdm (fitsfile *fptr, int colnum, int maxdim, > int *naxis, long *naxes, int *status) int fits_read_tdimll / ffgtdmll (fitsfile *fptr, int colnum, int maxdim, > int *naxis, LONGLONG *naxes, int *status) \end{verbatim} \begin{description} \item[6 ] Decode the input TDIMn keyword string (e.g. '(100,200)') and return the number of and size of the dimensions of a binary table column. If the input tdimstr character string is null, then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. This routine is called by fits\_read\_tdim. \label{ffdtdm} \end{description} \begin{verbatim} int fits_decode_tdim / ffdtdm (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, long *naxes, int *status) int fits_decode_tdimll / ffdtdmll (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, LONGLONG *naxes, int *status) \end{verbatim} \begin{description} \item[7 ] Write a TDIMn keyword whose value has the form '(l,m,n...)' where l, m, n... are the dimensions of a multidimensional array column in a binary table. \label{ffptdm} \end{description} \begin{verbatim} int fits_write_tdim / ffptdm (fitsfile *fptr, int colnum, int naxis, long *naxes, > int *status) int fits_write_tdimll / ffptdmll (fitsfile *fptr, int colnum, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \subsection{Routines to Edit Rows or Columns} \begin{description} \item[1 ] Insert or delete rows in an ASCII or binary table. When inserting rows all the rows following row FROW are shifted down by NROWS rows; if FROW = 0 then the blank rows are inserted at the beginning of the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead one may simply write data to any row of the table, whether that row of data already exists or not. The first delete routine deletes NROWS consecutive rows starting with row FIRSTROW. The second delete routine takes an input string that lists the rows or row ranges (e.g., '5-10,12,20-30'), whereas the third delete routine takes an input integer array that specifies each individual row to be deleted. In both latter cases, the input list of rows to delete must be sorted in ascending order. These routines update the NAXIS2 keyword to reflect the new number of rows in the table. \label{ffirow} \label{ffdrow} \label{ffdrws} \label{ffdrrg} \end{description} \begin{verbatim} int fits_insert_rows / ffirow (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) int fits_delete_rows / ffdrow (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) int fits_delete_rowrange / ffdrrg (fitsfile *fptr, char *rangelist, > int *status) int fits_delete_rowlist / ffdrws (fitsfile *fptr, long *rowlist, long nrows, > int *status) int fits_delete_rowlistll / ffdrwsll (fitsfile *fptr, LONGLONG *rowlist, LONGLONG nrows, > int *status) \end{verbatim} \begin{description} \item[2 ] Insert or delete column(s) in an ASCII or binary table. When inserting, COLNUM specifies the column number that the (first) new column should occupy in the table. NCOLS specifies how many columns are to be inserted. Any existing columns from this position and higher are shifted over to allow room for the new column(s). The index number on all the following keywords will be incremented or decremented if necessary to reflect the new position of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, and TCUNIn. \label{fficol} \label{fficls} \label{ffdcol} \end{description} \begin{verbatim} int fits_insert_col / fficol (fitsfile *fptr, int colnum, char *ttype, char *tform, > int *status) int fits_insert_cols / fficls (fitsfile *fptr, int colnum, int ncols, char **ttype, char **tform, > int *status) int fits_delete_col / ffdcol(fitsfile *fptr, int colnum, > int *status) \end{verbatim} \begin{description} \item[3 ] Copy column(s) between HDUs. If create\_col = TRUE, then new column(s) will be inserted in the output table, starting at position `outcolumn', otherwise the existing output column(s) will be overwritten (in which case they must have a compatible data type). The first form copies a single column incolnum to outcolnum. Copying within the same HDU is permitted. The second form copies ncols columns from the input, starting at column incolnum to the output, starting at outcolnum. For the second form, the input and output must be different HDUs. If outcolnum is greater than the number of column in the output table, then the new column(s) will be appended to the end of the table. Note that the first column in a table is at colnum = 1. The standard indexed keywords that related to the columns (e.g., TDISPn, TUNITn, TCRPXn, TCDLTn, etc.) will also be copied. \label{ffcpcl} \label{ffccls} \end{description} \begin{verbatim} int fits_copy_col / ffcpcl (fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, int create_col, > int *status); int fits_copy_cols / ffccls (fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, int ncols, int create_col, > int *status); \end{verbatim} \begin{description} \item[4 ] Copy 'nrows' consecutive rows from one table to another, beginning with row 'firstrow'. These rows will be appended to any existing rows in the output table. Note that the first row in a table is at row = 1. The \verb|fits_copy_selrows| form copies only selected rows to the output. Which rows are transferred is determined by an array of flags, \verb|row_status[]|, which could be returned by \verb|fits_find_rows()| or constructed by the user. FITS row N is copied if \verb|row_status[N-first_row]| is non-zero. \label{ffcprw} \label{ffcpsr} \end{description} \begin{verbatim} int fits_copy_rows / ffcprw (fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, > int *status); int fits_copy_selrows / ffcpsr (fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, char *row_status, > int *status); \end{verbatim} \begin{description} \item[5 ] Modify the vector length of a binary table column (e.g., change a column from TFORMn = '1E' to '20E'). The vector length may be increased or decreased from the current value. \label{ffmvec} \end{description} \begin{verbatim} int fits_modify_vector_len / ffmvec (fitsfile *fptr, int colnum, LONGLONG newveclen, > int *status) \end{verbatim} \subsection{Read and Write Column Data Routines} The following routines write or read data values in the current ASCII or binary table extension. If a write operation extends beyond the current size of the table, then the number of rows in the table will automatically be increased and the NAXIS2 keyword value will be updated. Attempts to read beyond the end of the table will result in an error. Automatic data type conversion is performed for numerical data types (only) if the data type of the column (defined by the TFORMn keyword) differs from the data type of the array in the calling routine. ASCII and binary tables support the following data type values: TSTRING, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TULONGLONG, TFLOAT, or TDOUBLE. Binary tables also support TLOGICAL (internally mapped to the `char' data type), TCOMPLEX, and TDBLCOMPLEX. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. Individual bits in a binary table 'X' or 'B' column may be read/written to/from a *char array by specifying the TBIT datatype. The *char array will be interpreted as an array of logical TRUE (1) or FALSE (0) values that correspond to the value of each bit in the FITS 'X' or 'B' column. Alternatively, the values in a binary table 'X' column may be read/written 8 bits at a time to/from an array of 8-bit integers by specifying the TBYTE datatype. Note that within the context of these routines, the TSTRING data type corresponds to a C 'char**' data type, i.e., a pointer to an array of pointers to an array of characters. This is different from the keyword reading and writing routines where TSTRING corresponds to a C 'char*' data type, i.e., a single pointer to an array of characters. When reading strings from a table, the char arrays obviously must have been allocated long enough to hold the whole FITS table string. See section \ref{character-strings} (``Dealing with Character Strings'') for more information. For complex and double complex data types, \verb+nelements+ is the number of numerical pairs; the number of floats or doubles stored by \+array+ must be \verb+2*nelements+. For the logical data (TLOGICAL), the C storage type is a \verb+char+ single-byte character. A FITS value of `\verb+T+'rue reads as 1 and `\verb+F+' reads as 0; other non-FITS characters are preserved untranslated. Numerical data values are automatically scaled by the TSCALn and TZEROn keyword values (if they exist). In the case of binary tables with vector elements, the \verb+firstelem+ parameter defines the starting element (beginning with 1, not 0) within the cell (a cell is defined as the intersection of a row and a column and may contain a single value or a vector of values). The \verb+firstelem+ parameter is ignored when dealing with ASCII tables. Similarly, in the case of binary tables the 'nelements' parameter specifies the total number of vector values to be read or written (continuing on subsequent rows if required) and not the number of table cells. \begin{description} \item[1 ] Write elements into an ASCII or binary table column. \end{description} The first routine simply writes the array of values to the FITS file (doing data type conversion if necessary) whereas the second routine will substitute the appropriate FITS null value for all elements which are equal to the input value of nulval (note that this parameter gives the address of nulval, not the null value itself). For integer columns the FITS null value is defined by the TNULLn keyword (an error is returned if the keyword doesn't exist). For floating point columns the special IEEE NaN (Not-a-Number) value will be written into the FITS file. If a null pointer is entered for nulval, then the null value is ignored and this routine behaves the same as the first routine. The third routine simply writes undefined pixel values to the column. The fourth routine fills every column in the table with null values, in the specified rows (ignoring any columns that do not have a defined null value). The \verb+fits_write_cols()+ variant writes multiple columns in a single pass, which may be significantly faster for large data files. The ``chunk'' size is determined automatically based upon CFITSIO's buffer sizes. Only whole rows can be written, of any type except TBIT or TSTRING. For this variant, datatype, colnum, array and nulval are arrays of the equivalent single-column parameter (i.e. \verb+datatype[i]+ is the data type of column \verb+i+). \label{ffpcl} \label{ffpcn} \label{ffpclu} \label{ffpcln} \begin{verbatim} int fits_write_col / ffpcl (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) int fits_write_colnull / ffpcn (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status) int fits_write_col_null / ffpclu (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, > int *status) int fits_write_nullrows / ffprwu (fitsfile *fptr, LONGLONG firstrow, LONGLONG nelements, > int *status) int fits_write_cols / ffpcln (fitsfile *fptr, int ncols, int *datatype, int *colnum, LONGLONG firstrow, LONGLONG nrows, DTYPE **array, DTYPE **nulval, int *status) \end{verbatim} \begin{description} \item[2 ] Read elements from an ASCII or binary table column. The data type parameter specifies the data type of the `nulval' and `array' pointers. The caller is required to allocate the storage of \verb+array+ before calling. Undefined array elements will be returned with a value = *nullval, (note that this parameter gives the address of the null value, not the null value itself) unless nulval = 0 or *nulval = 0, in which case no checking for undefined pixels will be performed. The second routine is similar except that any undefined pixels will have the corresponding nullarray element set equal to TRUE (= 1). Reading data as TSTRING values is different than for other data types as described above. Any column, regardless of it's intrinsic data type, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the data type of the column. The length of the returned strings (not including the null terminating character) can be determined with the fits\_get\_col\_display\_width routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. The \verb+fits_read_cols()+ variant read multiple columns in a single pass, which may be significantly faster for large data files. The ``chunk'' size is determined automatically based upon CFITSIO's buffer sizes. Only whole rows can be read, of any type except TBIT or TSTRING. For this variant, datatype, colnum, array and nulval are arrays of the equivalent single-column parameter (i.e. \verb+datatype[i]+ is the data type of column \verb+i+). \label{ffgcv} \label{ffgcf} \label{ffgcvn} \end{description} \begin{verbatim} int fits_read_col / ffgcv (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *nulval, DTYPE *array, int *anynul, int *status) int fits_read_colnull / ffgcf (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, char *nullarray, int *anynul, int *status) int fits_read_cols / ffgcvn (fitsfile *fptr, int ncols, int *datatype, int *colnum, LONGLONG firstrow, LONGLONG nrows, DTYPE **nulval, DTYPE **array, int **anynul, int *status) \end{verbatim} \subsection{Row Selection and Calculator Routines} These routines all parse and evaluate an input string containing a user defined arithmetic expression. The first 3 routines select rows in a FITS table, based on whether the expression evaluates to true (not equal to zero) or false (zero). The other routines evaluate the expression and calculate a value for each row of the table. The allowed expression syntax is described in the row filter section in the `Extended File Name Syntax' chapter of this document. The expression may also be written to a text file, and the name of the file, prepended with a '@' character may be supplied for the 'expr' parameter (e.g. '@filename.txt'). The expression in the file can be arbitrarily complex and extend over multiple lines of the file. Lines that begin with 2 slash characters ('//') will be ignored and may be used to add comments to the file. \begin{description} \item[1 ] Evaluate a boolean expression over the indicated rows, returning an array of flags indicating which rows evaluated to TRUE/FALSE. Upon return, *n\_good\_rows contains the number of rows that evaluate to TRUE. \label{fffrow} \end{description} \begin{verbatim} int fits_find_rows / fffrow (fitsfile *fptr, char *expr, long firstrow, long nrows, > long *n_good_rows, char *row_status, int *status) \end{verbatim} \begin{description} \item[2 ] Find the first row which satisfies the input boolean expression \label{ffffrw} \end{description} \begin{verbatim} int fits_find_first_row / ffffrw (fitsfile *fptr, char *expr, > long *rownum, int *status) \end{verbatim} \begin{description} \item[3 ]Evaluate an expression on all rows of a table. If the input and output files are not the same, copy the TRUE rows to the output file; if the output table is not empty, then this routine will append the new selected rows after the existing rows. If the files are the same, delete the FALSE rows (preserve the TRUE rows). \label{ffsrow} \end{description} \begin{verbatim} int fits_select_rows / ffsrow (fitsfile *infptr, fitsfile *outfptr, char *expr, > int *status ) \end{verbatim} \begin{description} \item[4 ] Calculate an expression for the indicated rows of a table, returning the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If nulval==NULL, UNDEFs will be zeroed out. For vector results, the number of elements returned may be less than nelements if nelements is not an even multiple of the result dimension. Call fits\_test\_expr to obtain the dimensions of the results. \label{ffcrow} \end{description} \begin{verbatim} int fits_calc_rows / ffcrow (fitsfile *fptr, int datatype, char *expr, long firstrow, long nelements, void *nulval, > void *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[5 ]Evaluate an expression and write the result either to a column (if the expression is a function of other columns in the table) or to a keyword (if the expression evaluates to a constant and is not a function of other columns in the table). In the former case, the parName parameter is the name of the column (which may or may not already exist) into which to write the results, and parInfo contains an optional TFORM keyword value if a new column is being created. If a TFORM value is not specified then a default format will be used, depending on the expression. If the expression evaluates to a constant, then the result will be written to the keyword name given by the parName parameter, and the parInfo parameter may be used to supply an optional comment for the keyword. If the keyword does not already exist, then the name of the keyword must be preceded with a '\#' character, otherwise the result will be written to a column with that name. \label{ffcalc} \end{description} \begin{verbatim} int fits_calculator / ffcalc (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, > int *status) \end{verbatim} \begin{description} \item[6 ] This calculator routine is similar to the previous routine, except that the expression is only evaluated over the specified row ranges. nranges specifies the number of row ranges, and firstrow and lastrow give the starting and ending row number of each range. \label{ffcalcrng} \end{description} \begin{verbatim} int fits_calculator_rng / ffcalc_rng (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, int nranges, long *firstrow, long *lastrow > int *status) \end{verbatim} \begin{description} \item[7 ]Evaluate the given expression and return dimension and type information on the result. The returned dimensions correspond to a single row entry of the requested expression, and are equivalent to the result of fits\_read\_tdim(). Note that strings are considered to be one element regardless of string length. If maxdim == 0, then naxes is optional. \label{fftexp} \end{description} \begin{verbatim} int fits_test_expr / fftexp (fitsfile *fptr, char *expr, int maxdim > int *datatype, long *nelem, int *naxis, long *naxes, int *status) \end{verbatim} \subsection{Column Binning or Histogramming Routines} The following routines may be useful when performing histogramming operations on column(s) of a table to generate an image in a primary array or image extension. \begin{description} \item[1 ] Calculate the histogramming parameters (min, max, and bin size for each axis of the histogram, based on a variety of possible input parameters. If the input names of the columns to be binned are null, then the routine will first look for the CPREF = "NAME1, NAME2, ..." keyword which lists the preferred columns. If not present, then the routine will assume the column names X, Y, Z, and T for up to 4 axes (as specified by the NAXIS parameter). MININ and MAXIN are input arrays that give the minimum and maximum value for the histogram, along each axis. Alternatively, the name of keywords that give the min, max, and binsize may be give with the MINNAME, MAXNAME, and BINNAME array parameters. If the value = DOUBLENULLVALUE and no keyword names are given, then the routine will use the TLMINn and TLMAXn keywords, if present, or the actual min and/or max values in the column. The ``d'' version has double precision floating point outputs as noted in the calling signature. The version without ``d'' has single precision floating point outputs. BINSIZEIN is an array giving the binsize along each axis. If the value = DOUBLENULLVALUE, and a keyword name is not specified with BINNAME, then this routine will first look for the TDBINn keyword, or else will use a binsize = 1, or a binsize that produces 10 histogram bins, which ever is smaller. \label{calcbinning} \end{description} \begin{verbatim} int fits_calc_binning[d] Input parameters: (fitsfile *fptr, /* IO - pointer to table to be binned */ int naxis, /* I - number of axes/columns in the binned image */ char colname[4][FLEN_VALUE], /* I - optional column names */ double *minin, /* I - optional lower bound value for each axis */ double *maxin, /* I - optional upper bound value, for each axis */ double *binsizein, /* I - optional bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ Output parameters: int *colnum, /* O - column numbers, to be binned */ long *naxes, /* O - number of bins in each histogram axis */ float[double] *amin, /* O - lower bound of the histogram axes */ float[double] *amax, /* O - upper bound of the histogram axes */ float[double] *binsize, /* O - width of histogram bins/pixels on each axis */ int *status) \end{verbatim} \begin{description} \item[2 ] Copy the relevant keywords from the header of the table that is being binned, to the the header of the output histogram image. This will not copy the table structure keywords (e.g., NAXIS, TFORMn, TTYPEn, etc.) nor will it copy the keywords that apply to other columns of the table that are not used to create the histogram. This routine will translate the names of the World Coordinate System (WCS) keywords for the binned columns into the form that is need for a FITS image (e.g., the TCTYPn table keyword will be translated to the CTYPEn image keyword). \label{copypixlist2image} \end{description} \begin{verbatim} int fits_copy_pixlist2image (fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU keyword to start with */ int naxis, /* I - number of axes in the image */ int *colnum, /* I - numbers of the columns to be binned */ int *status) /* IO - error status */ \end{verbatim} \begin{description} \item[3 ] Write a set of default WCS keywords to the histogram header, IF the WCS keywords do not already exist. This will create a linear WCS where the coordinate types are equal to the original column names. \label{writekeyshisto} \end{description} \begin{verbatim} int fits_write_keys_histo (fitsfile *fptr, /* I - pointer to table to be binned */ fitsfile *histptr, /* I - pointer to output histogram image HDU */ int naxis, /* I - number of axes in the histogram image */ int *colnum, /* I - column numbers of the binned columns */ int *status) \end{verbatim} \begin{description} \item[4 ] Update the WCS keywords in a histogram image header that give the location of the reference pixel (CRPIXn), and the pixel size (CDELTn), in the binned image. The ``d'' version has double precision floating point inputs as noted in the calling signature. The version without ``d'' has single precision floating point inputs. \label{rebinwcs} \end{description} \begin{verbatim} int fits_rebin_wcs[d] (fitsfile *fptr, /* I - pointer to table to be binned */ int naxis, /* I - number of axes in the histogram image */ float[double] *amin, /* I - first pixel include in each axis */ float[double] *binsize, /* I - binning factor for each axis */ int *status) \end{verbatim} \begin{description} \item[5 ] Bin the values in the input table columns, and write the histogram array to the output FITS image (histptr). The ``d'' version has double precision floating point inputs as noted in the calling signature. The version without ``d'' has single precision floating point inputs. \label{makehist} \end{description} \begin{verbatim} int fits_make_hist[d] (fitsfile *fptr, /* I - pointer to table with X and Y cols; */ fitsfile *histptr, /* I - pointer to output FITS image */ int bitpix, /* I - datatype for image: 16, 32, -32, etc */ int naxis, /* I - number of axes in the histogram image */ long *naxes, /* I - size of axes in the histogram image */ int *colnum, /* I - column numbers (array length = naxis) */ float[double] *amin, /* I - minimum histogram value, for each axis */ float[double] *amax, /* I - maximum histogram value, for each axis */ float[double] *binsize, /* I - bin size along each axis */ float[double] weight, /* I - binning weighting factor (FLOATNULLVALUE */ /* for no weighting) */ int wtcolnum, /* I - keyword or col for weight (or NULL) */ int recip, /* I - use reciprocal of the weight? 0 or 1 */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will */ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow */ /* is equal to NULL. */ int *status) \end{verbatim} \section{Utility Routines} \subsection{File Checksum Routines} The following routines either compute or validate the checksums for the CHDU. The DATASUM keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. If there is no data unit then the value is set to zero. The numerical value is stored as an ASCII string of digits, enclosed in quotes, because the value may be too large to represent as a 32-bit signed integer. The CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. These checksum keyword conventions are based on a paper by Rob Seaman published in the proceedings of the ADASS IV conference in Baltimore in November 1994 and a later revision in June 1995. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Compute and write the DATASUM and CHECKSUM keyword values for the CHDU into the current header. If the keywords already exist, their values will be updated only if necessary (i.e., if the file has been modified since the original keyword values were computed). \label{ffpcks} \end{description} \begin{verbatim} int fits_write_chksum / ffpcks (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[2 ] Update the CHECKSUM keyword value in the CHDU, assuming that the DATASUM keyword exists and already has the correct value. This routine calculates the new checksum for the current header unit, adds it to the data unit checksum, encodes the value into an ASCII string, and writes the string to the CHECKSUM keyword. \label{ffupck} \end{description} \begin{verbatim} int fits_update_chksum / ffupck (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[3 ] Verify the CHDU by computing the checksums and comparing them with the keywords. The data unit is verified correctly if the computed checksum equals the value of the DATASUM keyword. The checksum for the entire HDU (header plus data unit) is correct if it equals zero. The output DATAOK and HDUOK parameters in this routine are integers which will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the DATASUM or CHECKSUM keyword is not present, or value = -1 if the computed checksum is not correct. \label{ffvcks} \end{description} \begin{verbatim} int fits_verify_chksum / ffvcks (fitsfile *fptr, > int *dataok, int *hduok, int *status) \end{verbatim} \begin{description} \item[4 ] Compute and return the checksum values for the CHDU without creating or modifying the CHECKSUM and DATASUM keywords. This routine is used internally by ffvcks, but may be useful in other situations as well. \label{ffgcks} \end{description} \begin{verbatim} int fits_get_chksum/ /ffgcks (fitsfile *fptr, > unsigned long *datasum, unsigned long *hdusum, int *status) \end{verbatim} \begin{description} \item[5 ] Encode a checksum value into a 16-character string. If complm is non-zero (true) then the 32-bit sum value will be complemented before encoding. \label{ffesum} \end{description} \begin{verbatim} int fits_encode_chksum / ffesum (unsigned long sum, int complm, > char *ascii); \end{verbatim} \begin{description} \item[6 ] Decode a 16-character checksum string into a unsigned long value. If is non-zero (true). then the 32-bit sum value will be complemented after decoding. The checksum value is also returned as the value of the function. \label{ffdsum} \end{description} \begin{verbatim} unsigned long fits_decode_chksum / ffdsum (char *ascii, int complm, > unsigned long *sum); \end{verbatim} \subsection{Date and Time Utility Routines} The following routines help to construct or parse the FITS date/time strings. Starting in the year 2000, the FITS DATE keyword values (and the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' (date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the number of decimal places in the seconds value is optional. These times are in UTC. The older 'dd/mm/yy' date format may not be used for dates after 01 January 2000. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Get the current system date. C already provides standard library routines for getting the current date and time, but this routine is provided for compatibility with the Fortran FITSIO library. The returned year has 4 digits (1999, 2000, etc.) \label{ffgsdt} \end{description} \begin{verbatim} int fits_get_system_date/ffgsdt ( > int *day, int *month, int *year, int *status ) \end{verbatim} \begin{description} \item[2 ] Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). The time will be in UTC/GMT if available, as indicated by a returned timeref value = 0. If the returned value of timeref = 1 then this indicates that it was not possible to convert the local time to UTC, and thus the local time was returned. \end{description} \begin{verbatim} int fits_get_system_time/ffgstm (> char *datestr, int *timeref, int *status) \end{verbatim} \begin{description} \item[3 ] Construct a date string from the input date values. If the year is between 1900 and 1998, inclusive, then the returned date string will have the old FITS format ('dd/mm/yy'), otherwise the date string will have the new FITS format ('YYYY-MM-DD'). Use fits\_time2str instead to always return a date string using the new FITS format. \label{ffdt2s} \end{description} \begin{verbatim} int fits_date2str/ffdt2s (int year, int month, int day, > char *datestr, int *status) \end{verbatim} \begin{description} \item[4 ] Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). If the year, month, and day values all = 0 then only the time is encoded with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many decimal places of fractional seconds to include in the string. If `decimals' is negative, then only the date will be return ('YYYY-MM-DD'). \end{description} \begin{verbatim} int fits_time2str/fftm2s (int year, int month, int day, int hour, int minute, double second, int decimals, > char *datestr, int *status) \end{verbatim} \begin{description} \item[5 ] Return the date as read from the input string, where the string may be in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or 'YYYY-MM-DD') FITS format. Null pointers may be supplied for any unwanted output date parameters. \end{description} \begin{verbatim} int fits_str2date/ffs2dt (char *datestr, > int *year, int *month, int *day, int *status) \end{verbatim} \begin{description} \item[6 ] Return the date and time as read from the input string, where the string may be in either the old or new FITS format. The returned hours, minutes, and seconds values will be set to zero if the input string does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, the returned year, month, and date values will be set to zero if the date is not included in the input string ('hh:mm:ss.ddd...'). Null pointers may be supplied for any unwanted output date and time parameters. \end{description} \begin{verbatim} int fits_str2time/ffs2tm (char *datestr, > int *year, int *month, int *day, int *hour, int *minute, double *second, int *status) \end{verbatim} \subsection{General Utility Routines} The following utility routines may be useful for certain applications. \begin{description} \item[1 ] Return the revision number of the CFITSIO library. The revision number will be incremented with each new release of CFITSIO. The 3 fields of the version string M.xx.yy are converted to a float as: M + .01*xx + .0001*yy. \label{ffvers} \end{description} \begin{verbatim} float fits_get_version / ffvers ( > float *version) \end{verbatim} \begin{description} \item[2 ] Write an 80-character message to the CFITSIO error stack. Application programs should not normally write to the stack, but there may be some situations where this is desirable. \label{ffpmsg} \end{description} \begin{verbatim} void fits_write_errmsg / ffpmsg (char *err_msg) \end{verbatim} \begin{description} \item[3 ] Convert a character string to uppercase (operates in place). \label{ffupch} \end{description} \begin{verbatim} void fits_uppercase / ffupch (char *string) \end{verbatim} \begin{description} \item[4 ] Compare the input template string against the reference string to see if they match. The template string may contain wildcard characters: '*' will match any sequence of characters (including zero characters) and '?' will match any single character in the reference string. The '\#' character will match any consecutive string of decimal digits (0 - 9). If casesen = CASESEN = TRUE then the match will be case sensitive, otherwise the case of the letters will be ignored if casesen = CASEINSEN = FALSE. The returned MATCH parameter will be TRUE if the 2 strings match, and EXACT will be TRUE if the match is exact (i.e., if no wildcard characters were used in the match). Both strings must be 68 characters or less in length. \label{ffcmps} \end{description} \begin{verbatim} void fits_compare_str / ffcmps (char *templt, char *string, int casesen, > int *match, int *exact) \end{verbatim} \begin{description} \item[5 ]Split a string containing a list of names (typically file names or column names) into individual name tokens by a sequence of calls to fits\_split\_names. The names in the list must be delimited by a comma and/or spaces. This routine ignores spaces and commas that occur within parentheses, brackets, or curly brackets. It also strips any leading and trailing blanks from the returned name. This routine is similar to the ANSI C 'strtok' function: The first call to fits\_split\_names has a non-null input string. It finds the first name in the string and terminates it by overwriting the next character of the string with a null terminator and returns a pointer to the name. Each subsequent call, indicated by a NULL value of the input string, returns the next name, searching from just past the end of the previous name. It returns NULL when no further names are found. \label{splitnames} \end{description} \begin{verbatim} char *fits_split_names(char *namelist) \end{verbatim} The following example shows how a string would be split into 3 names: \begin{verbatim} myfile[1][bin (x,y)=4], file2.fits file3.fits ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ 1st name 2nd name 3rd name \end{verbatim} \begin{description} \item[6 ] Test that the keyword name contains only legal characters (A-Z,0-9, hyphen, and underscore) or that the keyword record contains only legal printable ASCII characters \label{fftkey} \label{fftrec} \end{description} \begin{verbatim} int fits_test_keyword / fftkey (char *keyname, > int *status) int fits_test_record / fftrec (char *card, > int *status) \end{verbatim} \begin{description} \item[7 ] Test whether the current header contains any NULL (ASCII 0) characters. These characters are illegal in the header, but they will go undetected by most of the CFITSIO keyword header routines, because the null is interpreted as the normal end-of-string terminator. This routine returns the position of the first null character in the header, or zero if there are no nulls. For example a returned value of 110 would indicate that the first NULL is located in the 30th character of the second keyword in the header (recall that each header record is 80 characters long). Note that this is one of the few CFITSIO routines in which the returned value is not necessarily equal to the status value). \label{ffnchk} \end{description} \begin{verbatim} int fits_null_check / ffnchk (char *card, > int *status) \end{verbatim} \begin{description} \item[8 ] Parse a header keyword record and return the name of the keyword, and the length of the name. The keyword name normally occupies the first 8 characters of the record, except under the HIERARCH convention where the name can be up to 70 characters in length. \label{ffgknm} \end{description} \begin{verbatim} int fits_get_keyname / ffgknm (char *card, > char *keyname, int *keylength, int *status) \end{verbatim} \begin{description} \item[9 ] Parse a header keyword record, returning the value (as a literal character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then a null value string is returned and the comment string is set equal to column 9 - 80 of the input string. \label{ffpsvc} \end{description} \begin{verbatim} int fits_parse_value / ffpsvc (char *card, > char *value, char *comment, int *status) \end{verbatim} \begin{description} \item[10] Construct a properly formated 80-character header keyword record from the input keyword name, keyword value, and keyword comment strings. Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. The value string may contain an integer, floating point, logical, or quoted character string (e.g., "12", "15.7", "T", or "'NGC 1313'"). \label{ffmkky} \end{description} \begin{verbatim} int fits_make_key / ffmkky (const char *keyname, const char *value, const char *comment, > char *card, int *status) \end{verbatim} \begin{description} \item[11] Construct an array indexed keyword name (ROOT + nnn). This routine appends the sequence number to the root string to create a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') \label{ffkeyn} \end{description} \begin{verbatim} int fits_make_keyn / ffkeyn (char *keyroot, int value, > char *keyname, int *status) \end{verbatim} \begin{description} \item[12] Construct a sequence keyword name (n + ROOT). This routine concatenates the sequence number to the front of the root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') \label{ffnkey} \end{description} \begin{verbatim} int fits_make_nkey / ffnkey (int value, char *keyroot, > char *keyname, int *status) \end{verbatim} \begin{description} \item[13] Determine the data type of a keyword value string. This routine parses the keyword value string to determine its data type. Returns 'C', 'L', 'I', 'F' or 'X', for character string, logical, integer, floating point, or complex, respectively. \label{ffdtyp} \end{description} \begin{verbatim} int fits_get_keytype / ffdtyp (char *value, > char *dtype, int *status) \end{verbatim} \begin{description} \item[14] Determine the integer data type of an integer keyword value string. The returned datatype value is the minimum integer datatype (starting from top of the following list and working down) required to store the integer value: \end{description} \begin{verbatim} Data Type Range TSBYTE: -128 to 127 TBYTE: 128 to 255 TSHORT: -32768 to 32767 TUSHORT: 32768 to 65535 TINT -2147483648 to 2147483647 TUINT 2147483648 to 4294967295 TLONGLONG -9223372036854775808 to 9223372036854775807 \end{verbatim} \begin{description} \item[ ] The *neg parameter returns 1 if the input value is negative and returns 0 if it is non-negative.\label{ffinttyp} \end{description} \begin{verbatim} int fits_get_inttype / ffinttyp (char *value, > int *datatype, int *neg, int *status) \end{verbatim} \begin{description} \item[15] Return the class of an input header record. The record is classified into one of the following categories (the class values are defined in fitsio.h). Note that this is one of the few CFITSIO routines that does not return a status value. \label{ffgkcl} \end{description} \begin{verbatim} Class Value Keywords TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY 20 The keywords used in the compressed image or table format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY 40 BLANK, TNULLn TYP_DIM_KEY 50 TDIMn TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY 70 BUNIT, TUNITn TYP_DISP_KEY 80 TDISPn TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY 100 CHECKSUM, DATASUM TYP_WCS_KEY 110 WCS keywords defined in the the WCS papers, including: CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn (i,j,m,n are integers, s is any letter) TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs, DATE-OBS TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY 140 CONTINUE TYP_USER_KEY 150 all other keywords int fits_get_keyclass / ffgkcl (char *card) \end{verbatim} \begin{description} \item[16] Parse the 'TFORM' binary table column format string. This routine parses the input TFORM character string and returns the integer data type code, the repeat count of the field, and, in the case of character string fields, the length of the unit string. See Appendix B for the allowed values for the returned typecode parameter. A null pointer may be given for any output parameters that are not needed. \label{ffbnfm} \end{description} \begin{verbatim} int fits_binary_tform / ffbnfm (char *tform, > int *typecode, long *repeat, long *width, int *status) int fits_binary_tformll / ffbnfmll (char *tform, > int *typecode, LONGLONG *repeat, long *width, int *status) \end{verbatim} \begin{description} \item[17] Parse the 'TFORM' keyword value that defines the column format in an ASCII table. This routine parses the input TFORM character string and returns the data type code, the width of the column, and (if it is a floating point column) the number of decimal places to the right of the decimal point. The returned data type codes are the same as for the binary table, with the following additional rules: integer columns that are between 1 and 4 characters wide are defined to be short integers (code = TSHORT). Wider integer columns are defined to be regular integers (code = TLONG). Similarly, Fixed decimal point columns (with TFORM = 'Fw.d') are defined to be single precision reals (code = TFLOAT) if w is between 1 and 7 characters wide, inclusive. Wider 'F' columns will return a double precision data code (= TDOUBLE). 'Ew.d' format columns will have datacode = TFLOAT, and 'Dw.d' format columns will have datacode = TDOUBLE. A null pointer may be given for any output parameters that are not needed. \label{ffasfm} \end{description} \begin{verbatim} int fits_ascii_tform / ffasfm (char *tform, > int *typecode, long *width, int *decimals, int *status) \end{verbatim} \begin{description} \item[18] Calculate the starting column positions and total ASCII table width based on the input array of ASCII table TFORM values. The SPACE input parameter defines how many blank spaces to leave between each column (it is recommended to have one space between columns for better human readability). \label{ffgabc} \end{description} \begin{verbatim} int fits_get_tbcol / ffgabc (int tfields, char **tform, int space, > long *rowlen, long *tbcol, int *status) \end{verbatim} \begin{description} \item[19] Parse a template header record and return a formatted 80-character string suitable for appending to (or deleting from) a FITS header file. This routine is useful for parsing lines from an ASCII template file and reformatting them into legal FITS header records. The formatted string may then be passed to the fits\_write\_record, ffmcrd, or fits\_delete\_key routines to append or modify a FITS header record. \label{ffgthd} \end{description} \begin{verbatim} int fits_parse_template / ffgthd (char *templt, > char *card, int *keytype, int *status) \end{verbatim} The input templt character string generally should contain 3 tokens: (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The TEMPLATE string must adhere to the following format: \begin{description} \item[- ] The KEYNAME token must begin in columns 1-8 and be a maximum of 8 characters long. A legal FITS keyword name may only contain the characters A-Z, 0-9, and '-' (minus sign) and underscore. This routine will automatically convert any lowercase characters to uppercase in the output string. If the first 8 characters of the template line are blank then the remainder of the line is considered to be a FITS comment (with a blank keyword name). \end{description} \begin{description} \item[- ] The VALUE token must be separated from the KEYNAME token by one or more spaces and/or an '=' character. The data type of the VALUE token (numeric, logical, or character string) is automatically determined and the output CARD string is formatted accordingly. The value token may be forced to be interpreted as a string (e.g. if it is a string of numeric digits) by enclosing it in single quotes. If the value token is a character string that contains 1 or more embedded blank space characters or slash ('/') characters then the entire character string must be enclosed in single quotes. \end{description} \begin{description} \item[- ] The COMMENT token is optional, but if present must be separated from the VALUE token by a blank space or a '/' character. \end{description} \begin{description} \item[- ] One exception to the above rules is that if the first non-blank character in the first 8 characters of the template string is a minus sign ('-') followed by a single token, or a single token followed by an equal sign, then it is interpreted as the name of a keyword which is to be deleted from the FITS header. \end{description} \begin{description} \item[- ] The second exception is that if the template string starts with a minus sign and is followed by 2 tokens (without an equals sign between them) then the second token is interpreted as the new name for the keyword specified by first token. In this case the old keyword name (first token) is returned in characters 1-8 of the returned CARD string, and the new keyword name (the second token) is returned in characters 41-48 of the returned CARD string. These old and new names may then be passed to the ffmnam routine which will change the keyword name. \end{description} The keytype output parameter indicates how the returned CARD string should be interpreted: \begin{verbatim} keytype interpretation ------- ------------------------------------------------- -2 Rename the keyword with name = the first 8 characters of CARD to the new name given in characters 41 - 48 of CARD. -1 delete the keyword with this name from the FITS header. 0 append the CARD string to the FITS header if the keyword does not already exist, otherwise update the keyword value and/or comment field if is already exists. 1 This is a HISTORY or COMMENT keyword; append it to the header 2 END record; do not explicitly write it to the FITS file. \end{verbatim} EXAMPLES: The following lines illustrate valid input template strings: \begin{verbatim} INTVAL 7 / This is an integer keyword RVAL 34.6 / This is a floating point keyword EVAL=-12.45E-03 / This is a floating point keyword in exponential notation lval F / This is a boolean keyword This is a comment keyword with a blank keyword name SVAL1 = 'Hello world' / this is a string keyword SVAL2 '123.5' this is also a string keyword sval3 123+ / this is also a string keyword with the value '123+ ' # the following template line deletes the DATE keyword - DATE # the following template line modifies the NAME keyword to OBJECT - NAME OBJECT \end{verbatim} \begin{description} \item[20] Translate a keyword name into a new name, based on a set of patterns. This routine is useful for translating keywords in cases such as adding or deleting columns in a table, or copying a column from one table to another, or extracting an array from a cell in a binary table column into an image extension. In these cases, it is necessary to translate the names of the keywords associated with the original table column(s) into the appropriate keyword name in the final file. For example, if column 2 is deleted from a table, then the value of 'n' in all the TFORMn and TTYPEn keywords for columns 3 and higher must be decremented by 1. Even more complex translations are sometimes needed to convert the WCS keywords when extracting an image out of a table column cell into a separate image extension. The user passes an array of patterns to be matched. Input pattern number i is pattern[i][0], and output pattern number i is pattern[i][1]. Keywords are matched against the input patterns. If a match is found then the keyword is re-written according to the output pattern. Order is important. The first match is accepted. The fastest match will be made when templates with the same first character are grouped together. Several characters have special meanings: \begin{verbatim} i,j - single digits, preserved in output template n - column number of one or more digits, preserved in output template m - generic number of one or more digits, preserved in output template a - coordinate designator, preserved in output template # - number of one or more digits ? - any character * - only allowed in first character position, to match all keywords; only useful as last pattern in the list \end{verbatim} i, j, n, and m are returned by the routine. For example, the input pattern "iCTYPn" will match "1CTYP5" (if n\_value is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". Notice that "i" is preserved. The following output patterns are special: "-" - do not copy a keyword that matches the corresponding input pattern "--" - if match occurs, outrec will have "-KEYNAME" "+" - copy the input unchanged The inrec string could be just the 8-char keyword name, or the entire 80-char header record. Characters 9 - 80 in the input string simply get appended to the translated keyword name. Upon return, outrec will have the converted string, starting from the pattern[i][1] pattern and applying the numerical substitutions as described above. If the output pattern is "--" then the resulting outrec will be "-KEYNAME", which may indicate to the calling routine that KEYNAME is to be deleted. If n\_range = 0, then only keywords with 'n' equal to n\_value will be considered as a pattern match. If n\_range = +1, then all values of 'n' greater than or equal to n\_value will be a match, and if -1, then values of 'n' less than or equal to n\_value will match.\label{translatekey} \end{description} \begin{verbatim} int fits_translate_keyword( char *inrec, /* I - input string */ char *outrec, /* O - output converted string, or */ /* a null string if input does not */ /* match any of the patterns */ char *patterns[][2],/* I - pointer to input / output string */ /* templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *pat_num, /* O - matched pattern number (0 based) or -1 */ int *i, /* O - value of i, if any, else 0 */ int *j, /* O - value of j, if any, else 0 */ int *m, /* O - value of m, if any, else 0 */ int *n, /* O - value of n, if any, else 0 */ int *status) /* IO - error status */ \end{verbatim} \begin{description} \item[ ] Here is an example of some of the patterns used to convert the keywords associated with an image in a cell of a table column into the keywords appropriate for an IMAGE extension: \end{description} \begin{verbatim} char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ {"TZEROn", "BZERO" }, {"TUNITn", "BUNIT" }, {"TNULLn", "BLANK" }, {"TDMINn", "DATAMIN" }, {"TDMAXn", "DATAMAX" }, {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ {"iCTYna", "CTYPEia" }, {"iCUNIn", "CUNITi" }, /* Coordinate units */ {"iCUNna", "CUNITia" }, {"iCRVLn", "CRVALi" }, /* WCS keywords */ {"iCRVna", "CRVALia" }, {"iCDLTn", "CDELTi" }, {"iCDEna", "CDELTia" }, {"iCRPXn", "CRPIXi" }, {"iCRPna", "CRPIXia" }, {"ijPCna", "PCi_ja" }, {"ijCDna", "CDi_ja" }, {"iVn_ma", "PVi_ma" }, {"iSn_ma", "PSi_ma" }, {"iCRDna", "CRDERia" }, {"iCSYna", "CSYERia" }, {"iCROTn", "CROTAi" }, {"WCAXna", "WCSAXESa"}, {"WCSNna", "WCSNAMEa"}}; \end{verbatim} \begin{description} \item[21] Translate the keywords in the input HDU into the keywords that are appropriate for the output HDU. This is a driver routine that calls the previously described routine for all keywords in the HDU. It is allowed for infptr and outfptr to point to the same HDU. If any output matched patterns are of the form "-KEYNAME" then this routine will attempt to delete the keyword KEYNAME. It is not an error if KEYNAME is not present in the output HDU. \end{description} \begin{verbatim} int fits_translate_keywords( fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU record number to start with */ char *patterns[][2],/* I - pointer to input / output keyword templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *status) /* IO - error status */ \end{verbatim} \begin{description} \item[22] Parse the input string containing a list of rows or row ranges, and return integer arrays containing the first and last row in each range. For example, if rowlist = "3-5, 6, 8-9" then it will return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. At most, 'maxranges' number of ranges will be returned. 'maxrows' is the maximum number of rows in the table; any rows or ranges larger than this will be ignored. The rows must be specified in increasing order, and the ranges must not overlap. A minus sign may be use to specify all the rows to the upper or lower bound, so "50-" means all the rows from 50 to the end of the table, and "-" means all the rows in the table, from 1 - maxrows. \label{ffrwrg} \end{description} \begin{verbatim} int fits_parse_range / ffrwrg(char *rowlist, LONGLONG maxrows, int maxranges, > int *numranges, long *rangemin, long *rangemax, int *status) int fits_parse_rangell / ffrwrgll(char *rowlist, LONGLONG maxrows, int maxranges, > int *numranges, LONGLONG *rangemin, LONGLONG *rangemax, int *status) \end{verbatim} \begin{description} \item[23] Check that the Header fill bytes (if any) are all blank. These are the bytes that may follow END keyword and before the beginning of data unit, or the end of the HDU if there is no data unit. \label{ffchfl} \end{description} \begin{verbatim} int ffchfl(fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[24] Check that the Data fill bytes (if any) are all zero (for IMAGE or BINARY Table HDU) or all blanks (for ASCII table HDU). These file bytes may be located after the last valid data byte in the HDU and before the physical end of the HDU. \label{ffcdfl} \end{description} \begin{verbatim} int ffcdfl(fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[25] Estimate the root-mean-squared (RMS) noise in an image. These routines are mainly for use with the Hcompress image compression algorithm. They return an estimate of the RMS noise in the background pixels of the image. This robust algorithm (written by Richard White, STScI) first attempts to estimate the RMS value as 1.68 times the median of the absolute differences between successive pixels in the image. If the median = 0, then the algorithm falls back to computing the RMS of the difference between successive pixels, after several N-sigma rejection cycles to remove extreme values. The input parameters are: the array of image pixel values (either float or short values), the number of values in the array, the value that is used to represent null pixels (enter a very large number if there are no null pixels). \label{imageRMS} \end{description} \begin{verbatim} int fits_rms_float (float fdata[], int npix, float in_null_value, > double *rms, int *status) int fits_rms_short (short fdata[], int npix, short in_null_value, > double *rms, int *status) \end{verbatim} \begin{description} \item[26] Was CFITSIO compiled with the -D\_REENTRANT directive so that it may be safely used in multi-threaded environments? The following function returns 1 if yes, 0 if no. Note, however, that even if the -D\_REENTRANT directive was specified, this does not guarantee that the CFITSIO routines are thread-safe, because some compilers may not support this feature.\label{reentrant} \end{description} \begin{verbatim} int fits_is_reentrant(void) \end{verbatim} \chapter{ The CFITSIO Iterator Function } The fits\_iterate\_data function in CFITSIO provides a unique method of executing an arbitrary user-supplied `work' function that operates on rows of data in FITS tables or on pixels in FITS images. Rather than explicitly reading and writing the FITS images or columns of data, one instead calls the CFITSIO iterator routine, passing to it the name of the user's work function that is to be executed along with a list of all the table columns or image arrays that are to be passed to the work function. The CFITSIO iterator function then does all the work of allocating memory for the arrays, reading the input data from the FITS file, passing them to the work function, and then writing any output data back to the FITS file after the work function exits. Because it is often more efficient to process only a subset of the total table rows at one time, the iterator function can determine the optimum amount of data to pass in each iteration and repeatedly call the work function until the entire table been processed. For many applications this single CFITSIO iterator function can effectively replace all the other CFITSIO routines for reading or writing data in FITS images or tables. Using the iterator has several important advantages over the traditional method of reading and writing FITS data files: \begin{itemize} \item It cleanly separates the data I/O from the routine that operates on the data. This leads to a more modular and `object oriented' programming style. \item It simplifies the application program by eliminating the need to allocate memory for the data arrays and eliminates most of the calls to the CFITSIO routines that explicitly read and write the data. \item It ensures that the data are processed as efficiently as possible. This is especially important when processing tabular data since the iterator function will calculate the most efficient number of rows in the table to be passed at one time to the user's work function on each iteration. \item Makes it possible for larger projects to develop a library of work functions that all have a uniform calling sequence and are all independent of the details of the FITS file format. \end{itemize} There are basically 2 steps in using the CFITSIO iterator function. The first step is to design the work function itself which must have a prescribed set of input parameters. One of these parameters is a structure containing pointers to the arrays of data; the work function can perform any desired operations on these arrays and does not need to worry about how the input data were read from the file or how the output data get written back to the file. The second step is to design the driver routine that opens all the necessary FITS files and initializes the input parameters to the iterator function. The driver program calls the CFITSIO iterator function which then reads the data and passes it to the user's work function. The following 2 sections describe these steps in more detail. There are also several example programs included with the CFITSIO distribution which illustrate how to use the iterator function. \section{The Iterator Work Function} The user-supplied iterator work function must have the following set of input parameters (the function can be given any desired name): \begin{verbatim} int user_fn( long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *data, void *userPointer ) \end{verbatim} \begin{itemize} \item totaln -- the total number of table rows or image pixels that will be passed to the work function during 1 or more iterations. \item offset -- the offset applied to the first table row or image pixel to be passed to the work function. In other words, this is the number of rows or pixels that are skipped over before starting the iterations. If offset = 0, then all the table rows or image pixels will be passed to the work function. \item firstn -- the number of the first table row or image pixel (starting with 1) that is being passed in this particular call to the work function. \item nvalues -- the number of table rows or image pixels that are being passed in this particular call to the work function. nvalues will always be less than or equal to totaln and will have the same value on each iteration, except possibly on the last call which may have a smaller value. \item narrays -- the number of arrays of data that are being passed to the work function. There is one array for each image or table column. \item *data -- array of structures, one for each column or image. Each structure contains a pointer to the array of data as well as other descriptive parameters about that array. \item *userPointer -- a user supplied pointer that can be used to pass ancillary information from the driver function to the work function. This pointer is passed to the CFITSIO iterator function which then passes it on to the work function without any modification. It may point to a single number, to an array of values, to a structure containing an arbitrary set of parameters of different types, or it may be a null pointer if it is not needed. The work function must cast this pointer to the appropriate data type before using it it. \end{itemize} The totaln, offset, narrays, data, and userPointer parameters are guaranteed to have the same value on each iteration. Only firstn, nvalues, and the arrays of data pointed to by the data structures may change on each iterative call to the work function. Note that the iterator treats an image as a long 1-D array of pixels regardless of it's intrinsic dimensionality. The total number of pixels is just the product of the size of each dimension, and the order of the pixels is the same as the order that they are stored in the FITS file. If the work function needs to know the number and size of the image dimensions then these parameters can be passed via the userPointer structure. The iteratorCol structure is currently defined as follows: \begin{verbatim} typedef struct /* structure for the iterator function column information */ { /* structure elements required as input to fits_iterate_data: */ fitsfile *fptr; /* pointer to the HDU containing the column or image */ int colnum; /* column number in the table; ignored for images */ char colname[70]; /* name (TTYPEn) of the column; null for images */ int datatype; /* output data type (converted if necessary) */ int iotype; /* type: InputCol, InputOutputCol, or OutputCol */ /* output structure elements that may be useful for the work function: */ void *array; /* pointer to the array (and the null value) */ long repeat; /* binary table vector repeat value; set */ /* equal to 1 for images */ long tlmin; /* legal minimum data value, if any */ long tlmax; /* legal maximum data value, if any */ char unit[70]; /* physical unit string (BUNIT or TUNITn) */ char tdisp[70]; /* suggested display format; null if none */ } iteratorCol; \end{verbatim} Instead of directly reading or writing the elements in this structure, it is recommended that programmers use the access functions that are provided for this purpose. The first five elements in this structure must be initially defined by the driver routine before calling the iterator routine. The CFITSIO iterator routine uses this information to determine what column or array to pass to the work function, and whether the array is to be input to the work function, output from the work function, or both. The CFITSIO iterator function fills in the values of the remaining structure elements before passing it to the work function. The array structure element is a pointer to the actual data array and it must be cast to the correct data type before it is used. The `repeat' structure element give the number of data values in each row of the table, so that the total number of data values in the array is given by repeat * nvalues. In the case of image arrays and ASCII tables, repeat will always be equal to 1. When the data type is a character string, the array pointer is actually a pointer to an array of string pointers (i.e., char **array). The other output structure elements are provided for convenience in case that information is needed within the work function. Any other information may be passed from the driver routine to the work function via the userPointer parameter. Upon completion, the work routine must return an integer status value, with 0 indicating success and any other value indicating an error which will cause the iterator function to immediately exit at that point. Return status values in the range 1 -- 1000 should be avoided since these are reserved for use by CFITSIO. A return status value of -1 may be used to force the CFITSIO iterator function to stop at that point and return control to the driver routine after writing any output arrays to the FITS file. CFITSIO does not considered this to be an error condition, so any further processing by the application program will continue normally. \section{The Iterator Driver Function} The iterator driver function must open the necessary FITS files and position them to the correct HDU. It must also initialize the following parameters in the iteratorCol structure (defined above) for each column or image before calling the CFITSIO iterator function. Several `constructor' routines are provided in CFITSIO for this purpose. \begin{itemize} \item *fptr -- The fitsfile pointer to the table or image. \item colnum -- the number of the column in the table. This value is ignored in the case of images. If colnum equals 0, then the column name will be used to identify the column to be passed to the work function. \item colname -- the name (TTYPEn keyword) of the column. This is only required if colnum = 0 and is ignored for images. \item datatype -- The desired data type of the array to be passed to the work function. For numerical data the data type does not need to be the same as the actual data type in the FITS file, in which case CFITSIO will do the conversion. Allowed values are: TSTRING, TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TLONG, TULONG, TFLOAT, TDOUBLE. If the input value of data type equals 0, then the existing data type of the column or image will be used without any conversion. \item iotype -- defines whether the data array is to be input to the work function (i.e, read from the FITS file), or output from the work function (i.e., written to the FITS file) or both. Allowed values are InputCol, OutputCol, or InputOutputCol. Variable-length array columns are supported as InputCol or InputOutputCol types, but may not be used for an OutputCol type. \end{itemize} After the driver routine has initialized all these parameters, it can then call the CFITSIO iterator function: \begin{verbatim} int fits_iterate_data(int narrays, iteratorCol *data, long offset, long nPerLoop, int (*workFn)( ), void *userPointer, int *status); \end{verbatim} \begin{itemize} \item narrays -- the number of columns or images that are to be passed to the work function. \item *data -- pointer to array of structures containing information about each column or image. \item offset -- if positive, this number of rows at the beginning of the table (or pixels in the image) will be skipped and will not be passed to the work function. \item nPerLoop - specifies the number of table rows (or number of image pixels) that are to be passed to the work function on each iteration. If nPerLoop = 0 then CFITSIO will calculate the optimum number for greatest efficiency. If nPerLoop is negative, then all the rows or pixels will be passed at one time, and the work function will only be called once. If any variable length arrays are being processed, then the nPerLoop value is ignored, and the iterator will always process one row of the table at a time. \item *workFn - the name (actually the address) of the work function that is to be called by fits\_iterate\_data. \item *userPointer - this is a user supplied pointer that can be used to pass ancillary information from the driver routine to the work function. It may point to a single number, an array, or to a structure containing an arbitrary set of parameters. \item *status - The CFITSIO error status. Should = 0 on input; a non-zero output value indicates an error. \end{itemize} When fits\_iterate\_data is called it first allocates memory to hold all the requested columns of data or image pixel arrays. It then reads the input data from the FITS tables or images into the arrays then passes the structure with pointers to these data arrays to the work function. After the work function returns, the iterator function writes any output columns of data or images back to the FITS files. It then repeats this process for any remaining sets of rows or image pixels until it has processed the entire table or image or until the work function returns a non-zero status value. The iterator then frees the memory that it initially allocated and returns control to the driver routine that called it. \section{Guidelines for Using the Iterator Function} The totaln, offset, firstn, and nvalues parameters that are passed to the work function are useful for determining how much of the data has been processed and how much remains left to do. On the very first call to the work function firstn will be equal to offset + 1; the work function may need to perform various initialization tasks before starting to process the data. Similarly, firstn + nvalues - 1 will be equal to totaln on the last iteration, at which point the work function may need to perform some clean up operations before exiting for the last time. The work function can also force an early termination of the iterations by returning a status value = -1. The narrays and iteratorCol.datatype arguments allow the work function to double check that the number of input arrays and their data types have the expected values. The iteratorCol.fptr and iteratorCol.colnum structure elements can be used if the work function needs to read or write the values of other keywords in the FITS file associated with the array. This should generally only be done during the initialization step or during the clean up step after the last set of data has been processed. Extra FITS file I/O during the main processing loop of the work function can seriously degrade the speed of the program. Note that the behavior of the \verb|fits_iterate_data()| is undefined if narrays is zero. If variable-length array columns are being processed, then the iterator will operate on one row of the table at a time. In this case the the repeat element in the interatorCol structure will be set equal to the number of elements in the current row that is being processed. One important feature of the iterator is that the first element in each array that is passed to the work function gives the value that is used to represent null or undefined values in the array. The real data then begins with the second element of the array (i.e., array[1], not array[0]). If the first array element is equal to zero, then this indicates that all the array elements have defined values and there are no undefined values. If array[0] is not equal to zero, then this indicates that some of the data values are undefined and this value (array[0]) is used to represent them. In the case of output arrays (i.e., those arrays that will be written back to the FITS file by the iterator function after the work function exits) the work function must set the first array element to the desired null value if necessary, otherwise the first element should be set to zero to indicate that there are no null values in the output array. CFITSIO defines 2 values, FLOATNULLVALUE and DOUBLENULLVALUE, that can be used as default null values for float and double data types, respectively. In the case of character string data types, a null string is always used to represent undefined strings. In some applications it may be necessary to recursively call the iterator function. An example of this is given by one of the example programs that is distributed with CFITSIO: it first calls a work function that writes out a 2D histogram image. That work function in turn calls another work function that reads the `X' and `Y' columns in a table to calculate the value of each 2D histogram image pixel. Graphically, the program structure can be described as: \begin{verbatim} driver --> iterator --> work1_fn --> iterator --> work2_fn \end{verbatim} Finally, it should be noted that the table columns or image arrays that are passed to the work function do not all have to come from the same FITS file and instead may come from any combination of sources as long as they have the same length. The length of the first table column or image array is used by the iterator if they do not all have the same length. \section{Complete List of Iterator Routines} All of the iterator routines are listed below. Most of these routines do not have a corresponding short function name. \begin{description} \item[1 ] Iterator `constructor' functions that set the value of elements in the iteratorCol structure that define the columns or arrays. These set the fitsfile pointer, column name, column number, datatype, and iotype, respectively. The last 2 routines allow all the parameters to be set with one function call (one supplies the column name, the other the column number). \label{ffiterset} \end{description} \begin{verbatim} int fits_iter_set_file(iteratorCol *col, fitsfile *fptr); int fits_iter_set_colname(iteratorCol *col, char *colname); int fits_iter_set_colnum(iteratorCol *col, int colnum); int fits_iter_set_datatype(iteratorCol *col, int datatype); int fits_iter_set_iotype(iteratorCol *col, int iotype); int fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, char *colname, int datatype, int iotype); int fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, int colnum, int datatype, int iotype); \end{verbatim} \begin{description} \item[2 ] Iterator `accessor' functions that return the value of the element in the iteratorCol structure that describes a particular data column or array \label{ffiterget} \end{description} \begin{verbatim} fitsfile * fits_iter_get_file(iteratorCol *col); char * fits_iter_get_colname(iteratorCol *col); int fits_iter_get_colnum(iteratorCol *col); int fits_iter_get_datatype(iteratorCol *col); int fits_iter_get_iotype(iteratorCol *col); void * fits_iter_get_array(iteratorCol *col); long fits_iter_get_tlmin(iteratorCol *col); long fits_iter_get_tlmax(iteratorCol *col); long fits_iter_get_repeat(iteratorCol *col); char * fits_iter_get_tunit(iteratorCol *col); char * fits_iter_get_tdisp(iteratorCol *col); \end{verbatim} \begin{description} \item[3 ] The CFITSIO iterator function \label{ffiter} \end{description} \begin{verbatim} int fits_iterate_data(int narrays, iteratorCol *data, long offset, long nPerLoop, int (*workFn)( long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *data, void *userPointer), void *userPointer, int *status); \end{verbatim} \chapter{ World Coordinate System Routines } The FITS community has adopted a set of keyword conventions that define the transformations needed to convert between pixel locations in an image and the corresponding celestial coordinates on the sky, or more generally, that define world coordinates that are to be associated with any pixel location in an n-dimensional FITS array. CFITSIO is distributed with a a few self-contained World Coordinate System (WCS) routines, however, these routines DO NOT support all the latest WCS conventions, so it is STRONGLY RECOMMENDED that software developers use a more robust external WCS library. Several recommended libraries are: \begin{verbatim} WCSLIB - supported by Mark Calabretta WCSTools - supported by Doug Mink AST library - developed by the U.K. Starlink project \end{verbatim} More information about the WCS keyword conventions and links to all of these WCS libraries can be found on the FITS Support Office web site at http://fits.gsfc.nasa.gov under the WCS link. The functions provided in these external WCS libraries will need access to the WCS keywords contained in the FITS file headers. One convenient way to pass this information to the external library is to use the fits\_hdr2str routine in CFITSIO (defined below) to copy the header keywords into one long string, and then pass this string to an interface routine in the external library that will extract the necessary WCS information (e.g., the 'wcspih' routine in the WCSLIB library and the 'astFitsChan' and 'astPutCards' functions in the AST library). \begin{description} \item[1 ] Concatenate the header keywords in the CHDU into a single long string of characters. Each 80-character fixed-length keyword record is appended to the output character string, in order, with no intervening separator or terminating characters. The last header record is terminated with a NULL character. This routine allocates memory for the returned character array, so the calling program must free the memory when finished. There are 2 related routines: fits\_hdr2str simply concatenates all the existing keywords in the header; fits\_convert\_hdr2str is similar, except that if the CHDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of a normal FITS image before concatenating the keywords. Selected keywords may be excluded from the returned character string. If the second parameter (nocomments) is TRUE (nonzero) then any COMMENT, HISTORY, or blank keywords in the header will not be copied to the output string. The 'exclist' parameter may be used to supply a list of keywords that are to be excluded from the output character string. Wild card characters (*, ?, and \#) may be used in the excluded keyword names. If no additional keywords are to be excluded, then set nexc = 0 and specify NULL for the the **exclist parameter. \label{hdr2str} \end{description} \begin{verbatim} int fits_hdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) int fits_convert_hdr2str / ffcnvthdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) \end{verbatim} \begin{description} \item[2 ] The following CFITSIO routine is specifically designed for use in conjunction with the WCSLIB library. It is not expected that applications programmers will call this routine directly, but it is documented here for completeness. This routine extracts arrays from a binary table that contain WCS information using the -TAB table lookup convention. See the documentation provided with the WCSLIB library for more information. \label{wcstab} \end{description} \begin{verbatim} int fits_read_wcstab (fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); \end{verbatim} \section{ Self-contained WCS Routines} The following routines DO NOT support the more recent WCS conventions that have been approved as part of the FITS standard. Consequently, the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED that software developers not use these routines, and instead use an external WCS library, as described in the previous section. These routines are included mainly for backward compatibility with existing software. They support the following standard map projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the legal values for the coordtype parameter). These routines are based on similar functions in Classic AIPS. All the angular quantities are given in units of degrees. \begin{description} \item[1 ] Get the values of the basic set of standard FITS celestial coordinate system keywords from the header of a FITS image (i.e., the primary array or an IMAGE extension). These values may then be passed to the fits\_pix\_to\_world and fits\_world\_to\_pix routines that perform the coordinate transformations. If any or all of the WCS keywords are not present, then default values will be returned. If the first coordinate axis is the declination-like coordinate, then this routine will swap them so that the longitudinal-like coordinate is returned as the first axis. The first routine (ffgics) returns the primary WCS, whereas the second routine returns the particular version of the WCS specified by the 'version' parameter, which much be a character ranging from 'A' to 'Z' (or a blank character, which is equivalent to calling ffgics). If the file uses the newer 'CDj\_i' WCS transformation matrix keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then this routine will calculate and return the values of the equivalent old-style keywords. Note that the conversion from the new-style keywords to the old-style values is sometimes only an approximation, so if the approximation is larger than an internally defined threshold level, then CFITSIO will still return the approximate WCS keyword values, but will also return with status = APPROX\_WCS\_KEY, to warn the calling program that approximations have been made. It is then up to the calling program to decide whether the approximations are sufficiently accurate for the particular application, or whether more precise WCS transformations must be performed using new-style WCS keywords directly. \label{ffgics} \end{description} \begin{verbatim} int fits_read_img_coord / ffgics (fitsfile *fptr, > double *xrefval, double *yrefval, double *xrefpix, double *yrefpix, double *xinc, double *yinc, double *rot, char *coordtype, int *status) int fits_read_img_coord_version / ffgicsa (fitsfile *fptr, char version, > double *xrefval, double *yrefval, double *xrefpix, double *yrefpix, double *xinc, double *yinc, double *rot, char *coordtype, int *status) \end{verbatim} \begin{description} \item[2 ] Get the values of the standard FITS celestial coordinate system keywords from the header of a FITS table where the X and Y (or RA and DEC) coordinates are stored in 2 separate columns of the table (as in the Event List table format that is often used by high energy astrophysics missions). These values may then be passed to the fits\_pix\_to\_world and fits\_world\_to\_pix routines that perform the coordinate transformations. \label{ffgtcs} \end{description} \begin{verbatim} int fits_read_tbl_coord / ffgtcs (fitsfile *fptr, int xcol, int ycol, > double *xrefval, double *yrefval, double *xrefpix, double *yrefpix, double *xinc, double *yinc, double *rot, char *coordtype, int *status) \end{verbatim} \begin{description} \item[3 ] Calculate the celestial coordinate corresponding to the input X and Y pixel location in the image. \label{ffwldp} \end{description} \begin{verbatim} int fits_pix_to_world / ffwldp (double xpix, double ypix, double xrefval, double yrefval, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *coordtype, > double *xpos, double *ypos, int *status) \end{verbatim} \begin{description} \item[4 ] Calculate the X and Y pixel location corresponding to the input celestial coordinate in the image. \label{ffxypx} \end{description} \begin{verbatim} int fits_world_to_pix / ffxypx (double xpos, double ypos, double xrefval, double yrefval, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *coordtype, > double *xpix, double *ypix, int *status) \end{verbatim} \chapter{ Hierarchical Grouping Routines } These functions allow for the creation and manipulation of FITS HDU Groups, as defined in "A Hierarchical Grouping Convention for FITS" by Jennings, Pence, Folk and Schlesinger: https://fits.gsfc.nasa.gov/registry/grouping/grouping.pdf A group is a collection of HDUs whose association is defined by a {\it grouping table}. HDUs which are part of a group are referred to as {\it member HDUs} or simply as {\it members}. Grouping table member HDUs may themselves be grouping tables, thus allowing for the construction of open-ended hierarchies of HDUs. Grouping tables contain one row for each member HDU. The grouping table columns provide identification information that allows applications to reference or "point to" the member HDUs. Member HDUs are expected, but not required, to contain a set of GRPIDn/GRPLCn keywords in their headers for each grouping table that they are referenced by. In this sense, the GRPIDn/GRPLCn keywords "link" the member HDU back to its Grouping table. Note that a member HDU need not reside in the same FITS file as its grouping table, and that a given HDU may be referenced by up to 999 grouping tables simultaneously. Grouping tables are implemented as FITS binary tables with up to six pre-defined column TTYPEn values: 'MEMBER\_XTENSION', 'MEMBER\_NAME', 'MEMBER\_VERSION', 'MEMBER\_POSITION', 'MEMBER\_URI\_TYPE' and 'MEMBER\_LOCATION'. The first three columns allow member HDUs to be identified by reference to their XTENSION, EXTNAME and EXTVER keyword values. The fourth column allows member HDUs to be identified by HDU position within their FITS file. The last two columns identify the FITS file in which the member HDU resides, if different from the grouping table FITS file. Additional user defined "auxiliary" columns may also be included with any grouping table. When a grouping table is copied or modified the presence of auxiliary columns is always taken into account by the grouping support functions; however, the grouping support functions cannot directly make use of this data. If a grouping table column is defined but the corresponding member HDU information is unavailable then a null value of the appropriate data type is inserted in the column field. Integer columns (MEMBER\_POSITION, MEMBER\_VERSION) are defined with a TNULLn value of zero (0). Character field columns (MEMBER\_XTENSION, MEMBER\_NAME, MEMBER\_URI\_TYPE, MEMBER\_LOCATION) utilize an ASCII null character to denote a null field value. The grouping support functions belong to two basic categories: those that work with grouping table HDUs (ffgt**) and those that work with member HDUs (ffgm**). Two functions, fits\_copy\_group() and fits\_remove\_group(), have the option to recursively copy/delete entire groups. Care should be taken when employing these functions in recursive mode as poorly defined groups could cause unpredictable results. The problem of a grouping table directly or indirectly referencing itself (thus creating an infinite loop) is protected against; in fact, neither function will attempt to copy or delete an HDU twice. \section{Grouping Table Routines} \begin{description} \item[1 ]Create (append) a grouping table at the end of the current FITS file pointed to by fptr. The grpname parameter provides the grouping table name (GRPNAME keyword value) and may be set to NULL if no group name is to be specified. The grouptype parameter specifies the desired structure of the grouping table and may take on the values: GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns). \label{ffgtcr} \end{description} \begin{verbatim} int fits_create_group / ffgtcr (fitsfile *fptr, char *grpname, int grouptype, > int *status) \end{verbatim} \begin{description} \item[2 ]Create (insert) a grouping table just after the CHDU of the current FITS file pointed to by fptr. All HDUs below the the insertion point will be shifted downwards to make room for the new HDU. The grpname parameter provides the grouping table name (GRPNAME keyword value) and may be set to NULL if no group name is to be specified. The grouptype parameter specifies the desired structure of the grouping table and may take on the values: GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns) \label{ffgtis}. \end{description} \begin{verbatim} int fits_insert_group / ffgtis (fitsfile *fptr, char *grpname, int grouptype, > int *status) \end{verbatim} \begin{description} \item[3 ]Change the structure of an existing grouping table pointed to by gfptr. The grouptype parameter (see fits\_create\_group() for valid parameter values) specifies the new structure of the grouping table. This function only adds or removes grouping table columns, it does not add or delete group members (i.e., table rows). If the grouping table already has the desired structure then no operations are performed and function simply returns with a (0) success status code. If the requested structure change creates new grouping table columns, then the column values for all existing members will be filled with the null values appropriate to the column type. \label{ffgtch} \end{description} \begin{verbatim} int fits_change_group / ffgtch (fitsfile *gfptr, int grouptype, > int *status) \end{verbatim} \begin{description} \item[4 ]Remove the group defined by the grouping table pointed to by gfptr, and optionally all the group member HDUs. The rmopt parameter specifies the action to be taken for all members of the group defined by the grouping table. Valid values are: OPT\_RM\_GPT (delete only the grouping table) and OPT\_RM\_ALL (recursively delete all HDUs that belong to the group). Any groups containing the grouping table gfptr as a member are updated, and if rmopt == OPT\_RM\_GPT all members have their GRPIDn and GRPLCn keywords updated accordingly. If rmopt == OPT\_RM\_ALL, then other groups that contain the deleted members of gfptr are updated to reflect the deletion accordingly. \label{ffgtrm} \end{description} \begin{verbatim} int fits_remove_group / ffgtrm (fitsfile *gfptr, int rmopt, > int *status) \end{verbatim} \begin{description} \item[5 ]Copy (append) the group defined by the grouping table pointed to by infptr, and optionally all group member HDUs, to the FITS file pointed to by outfptr. The cpopt parameter specifies the action to be taken for all members of the group infptr. Valid values are: OPT\_GCP\_GPT (copy only the grouping table) and OPT\_GCP\_ALL (recursively copy ALL the HDUs that belong to the group defined by infptr). If the cpopt == OPT\_GCP\_GPT then the members of infptr have their GRPIDn and GRPLCn keywords updated to reflect the existence of the new grouping table outfptr, since they now belong to the new group. If cpopt == OPT\_GCP\_ALL then the new grouping table outfptr only contains pointers to the copied member HDUs and not the original member HDUs of infptr. Note that, when cpopt == OPT\_GCP\_ALL, all members of the group defined by infptr will be copied to a single FITS file pointed to by outfptr regardless of their file distribution in the original group. \label{ffgtcp} \end{description} \begin{verbatim} int fits_copy_group / ffgtcp (fitsfile *infptr, fitsfile *outfptr, int cpopt, > int *status) \end{verbatim} \begin{description} \item[6 ] Merge the two groups defined by the grouping table HDUs infptr and outfptr by combining their members into a single grouping table. All member HDUs (rows) are copied from infptr to outfptr. If mgopt == OPT\_MRG\_COPY then infptr continues to exist unaltered after the merge. If the mgopt == OPT\_MRG\_MOV then infptr is deleted after the merge. In both cases, the GRPIDn and GRPLCn keywords of the member HDUs are updated accordingly. \label{ffgtmg} \end{description} \begin{verbatim} int fits_merge_groups / ffgtmg (fitsfile *infptr, fitsfile *outfptr, int mgopt, > int *status) \end{verbatim} \begin{description} \item[7 ]"Compact" the group defined by grouping table pointed to by gfptr. The compaction is achieved by merging (via fits\_merge\_groups()) all direct member HDUs of gfptr that are themselves grouping tables. The cmopt parameter defines whether the merged grouping table HDUs remain after merging (cmopt == OPT\_CMT\_MBR) or if they are deleted after merging (cmopt == OPT\_CMT\_MBR\_DEL). If the grouping table contains no direct member HDUs that are themselves grouping tables then this function does nothing. Note that this function is not recursive, i.e., only the direct member HDUs of gfptr are considered for merging. \label{ffgtcm} \end{description} \begin{verbatim} int fits_compact_group / ffgtcm (fitsfile *gfptr, int cmopt, > int *status) \end{verbatim} \begin{description} \item[8 ]Verify the integrity of the grouping table pointed to by gfptr to make sure that all group members are accessible and that all links to other grouping tables are valid. The firstfailed parameter returns the member ID (row number) of the first member HDU to fail verification (if positive value) or the first group link to fail (if negative value). If gfptr is successfully verified then firstfailed contains a return value of 0. \label{ffgtvf} \end{description} \begin{verbatim} int fits_verify_group / ffgtvf (fitsfile *gfptr, > long *firstfailed, int *status) \end{verbatim} \begin{description} \item[9 ] Open a grouping table that contains the member HDU pointed to by mfptr. The grouping table to open is defined by the grpid parameter, which contains the keyword index value of the GRPIDn/GRPLCn keyword(s) that link the member HDU mfptr to the grouping table. If the grouping table resides in a file other than the member HDUs file then an attempt is first made to open the file readwrite, and failing that readonly. A pointer to the opened grouping table HDU is returned in gfptr. Note that it is possible, although unlikely and undesirable, for the GRPIDn/GRPLCn keywords in a member HDU header to be non-continuous, e.g., GRPID1, GRPID2, GRPID5, GRPID6. In such cases, the grpid index value specified in the function call shall identify the (grpid)th GRPID value. In the above example, if grpid == 3, then the group specified by GRPID5 would be opened. \label{ffgtop} \end{description} \begin{verbatim} int fits_open_group / ffgtop (fitsfile *mfptr, int grpid, > fitsfile **gfptr, int *status) \end{verbatim} \begin{description} \item[10] Add a member HDU to an existing grouping table pointed to by gfptr. The member HDU may either be pointed to mfptr (which must be positioned to the member HDU) or, if mfptr == NULL, identified by the hdupos parameter (the HDU position number, Primary array == 1) if both the grouping table and the member HDU reside in the same FITS file. The new member HDU shall have the appropriate GRPIDn and GRPLCn keywords created in its header. Note that if the member HDU is already a member of the group then it will not be added a second time. \label{ffgtam} \end{description} \begin{verbatim} int fits_add_group_member / ffgtam (fitsfile *gfptr, fitsfile *mfptr, int hdupos, > int *status) \end{verbatim} \section{Group Member Routines} \begin{description} \item[1 ] Return the number of member HDUs in a grouping table gfptr. The number of member HDUs is just the NAXIS2 value (number of rows) of the grouping table. \label{ffgtnm} \end{description} \begin{verbatim} int fits_get_num_members / ffgtnm (fitsfile *gfptr, > long *nmembers, int *status) \end{verbatim} \begin{description} \item[2 ] Return the number of groups to which the HDU pointed to by mfptr is linked, as defined by the number of GRPIDn/GRPLCn keyword records that appear in its header. Note that each time this function is called, the indices of the GRPIDn/GRPLCn keywords are checked to make sure they are continuous (ie no gaps) and are re-enumerated to eliminate gaps if found. \label{ffgmng} \end{description} \begin{verbatim} int fits_get_num_groups / ffgmng (fitsfile *mfptr, > long *nmembers, int *status) \end{verbatim} \begin{description} \item[3 ] Open a member of the grouping table pointed to by gfptr. The member to open is identified by its row number within the grouping table as given by the parameter 'member' (first member == 1) . A fitsfile pointer to the opened member HDU is returned as mfptr. Note that if the member HDU resides in a FITS file different from the grouping table HDU then the member file is first opened readwrite and, failing this, opened readonly. \label{ffgmop} \end{description} \begin{verbatim} int fits_open_member / ffgmop (fitsfile *gfptr, long member, > fitsfile **mfptr, int *status) \end{verbatim} \begin{description} \item[4 ]Copy (append) a member HDU of the grouping table pointed to by gfptr. The member HDU is identified by its row number within the grouping table as given by the parameter 'member' (first member == 1). The copy of the group member HDU will be appended to the FITS file pointed to by mfptr, and upon return mfptr shall point to the copied member HDU. The cpopt parameter may take on the following values: OPT\_MCP\_ADD which adds a new entry in gfptr for the copied member HDU, OPT\_MCP\_NADD which does not add an entry in gfptr for the copied member, and OPT\_MCP\_REPL which replaces the original member entry with the copied member entry. \label{ffgmcp} \end{description} \begin{verbatim} int fits_copy_member / ffgmcp (fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, > int *status) \end{verbatim} \begin{description} \item[5 ]Transfer a group member HDU from the grouping table pointed to by infptr to the grouping table pointed to by outfptr. The member HDU to transfer is identified by its row number within infptr as specified by the parameter 'member' (first member == 1). If tfopt == OPT\_MCP\_ADD then the member HDU is made a member of outfptr and remains a member of infptr. If tfopt == OPT\_MCP\_MOV then the member HDU is deleted from infptr after the transfer to outfptr. \label{ffgmtf} \end{description} \begin{verbatim} int fits_transfer_member / ffgmtf (fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, > int *status) \end{verbatim} \begin{description} \item[6 ]Remove a member HDU from the grouping table pointed to by gfptr. The member HDU to be deleted is identified by its row number in the grouping table as specified by the parameter 'member' (first member == 1). The rmopt parameter may take on the following values: OPT\_RM\_ENTRY which removes the member HDU entry from the grouping table and updates the member's GRPIDn/GRPLCn keywords, and OPT\_RM\_MBR which removes the member HDU entry from the grouping table and deletes the member HDU itself. \label{ffgmrm} \end{description} \begin{verbatim} int fits_remove_member / ffgmrm (fitsfile *gfptr, long member, int rmopt, > int *status) \end{verbatim} \chapter{ Specialized CFITSIO Interface Routines } The basic interface routines described previously are recommended for most uses, but the routines described in this chapter are also available if necessary. Some of these routines perform more specialized function that cannot easily be done with the basic interface routines while others duplicate the functionality of the basic routines but have a slightly different calling sequence. See Appendix B for the definition of each function parameter. \section{FITS File Access Routines} \subsection{File Access} \begin{description} \item[1 ] Open an existing FITS file residing in core computer memory. This routine is analogous to fits\_open\_file. The 'filename' is currently ignored by this routine and may be any arbitrary string. In general, the application must have preallocated an initial block of memory to hold the FITS file prior to calling this routine: 'memptr' points to the starting address and 'memsize' gives the initial size of the block of memory. 'mem\_realloc' is a pointer to an optional function that CFITSIO can call to allocate additional memory, if needed (only if mode = READWRITE), and is modeled after the standard C 'realloc' function; a null pointer may be given if the initial allocation of memory is all that will be required (e.g., if the file is opened with mode = READONLY). The 'deltasize' parameter may be used to suggest a minimum amount of additional memory that should be allocated during each call to the memory reallocation function. By default, CFITSIO will reallocate enough additional space to hold the entire currently defined FITS file (as given by the NAXISn keywords) or 1 FITS block (= 2880 bytes), which ever is larger. Values of deltasize less than 2880 will be ignored. Since the memory reallocation operation can be computationally expensive, allocating a larger initial block of memory, and/or specifying a larger deltasize value may help to reduce the number of reallocation calls and make the application program run faster. Note that values of the memptr and memsize pointers will be updated by CFITSIO if the location or size of the FITS file in memory should change as a result of allocating more memory. \label{ffomem} \end{description} \begin{verbatim} int fits_open_memfile / ffomem (fitsfile **fptr, const char *filename, int mode, void **memptr, size_t *memsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status) \end{verbatim} \begin{description} \item[2 ] Create a new FITS file residing in core computer memory. This routine is analogous to fits\_create\_file. In general, the application must have preallocated an initial block of memory to hold the FITS file prior to calling this routine: 'memptr' points to the starting address and 'memsize' gives the initial size of the block of memory. 'mem\_realloc' is a pointer to an optional function that CFITSIO can call to allocate additional memory, if needed, and is modeled after the standard C 'realloc' function; a null pointer may be given if the initial allocation of memory is all that will be required. The 'deltasize' parameter may be used to suggest a minimum amount of additional memory that should be allocated during each call to the memory reallocation function. By default, CFITSIO will reallocate enough additional space to hold 1 FITS block (= 2880 bytes) and values of deltasize less than 2880 will be ignored. Since the memory reallocation operation can be computationally expensive, allocating a larger initial block of memory, and/or specifying a larger deltasize value may help to reduce the number of reallocation calls and make the application program run faster. Note that values of the memptr and memsize pointers will be updated by CFITSIO if the location or size of the FITS file in memory should change as a result of allocating more memory. \label{ffimem} \end{description} \begin{verbatim} int fits_create_memfile / ffimem (fitsfile **fptr, void **memptr, size_t *memsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status) \end{verbatim} \begin{description} \item[3 ] Reopen a FITS file that was previously opened with fits\_open\_file or fits\_create\_file. The new fitsfile pointer may then be treated as a separate file, and one may simultaneously read or write to 2 (or more) different extensions in the same file. The fits\_open\_file routine (above) automatically detects cases where a previously opened file is being opened again, and then internally call fits\_reopen\_file, so programs should rarely need to explicitly call this routine. \label{ffreopen} \end{description} \begin{verbatim} int fits_reopen_file / ffreopen (fitsfile *openfptr, fitsfile **newfptr, > int *status) \end{verbatim} \begin{description} \item[4 ] Create a new FITS file, using a template file to define its initial size and structure. The template may be another FITS HDU or an ASCII template file. If the input template file name pointer is null, then this routine behaves the same as fits\_create\_file. The currently supported format of the ASCII template file is described under the fits\_parse\_template routine (in the general Utilities section) \label{fftplt} \end{description} \begin{verbatim} int fits_create_template / fftplt (fitsfile **fptr, char *filename, char *tpltfile > int *status) \end{verbatim} \begin{description} \item[5 ] Parse the input filename or URL into its component parts, namely: \begin{itemize} \item the file type (file://, ftp://, http://, etc), \item the base input file name, \item the name of the output file that the input file is to be copied to prior to opening, \item the HDU or extension specification, \item the filtering specifier, \item the binning specifier, \item the column specifier, \item and the image pixel filtering specifier. \end{itemize} A null pointer (0) may be be specified for any of the output string arguments that are not needed. Null strings will be returned for any components that are not present in the input file name. The calling routine must allocate sufficient memory to hold the returned character strings. Allocating the string lengths equal to FLEN\_FILENAME is guaranteed to be safe. These routines are mainly for internal use by other CFITSIO routines. \label{ffiurl} \end{description} \begin{verbatim} int fits_parse_input_url / ffiurl (char *filename, > char *filetype, char *infile, char *outfile, char *extspec, char *filter, char *binspec, char *colspec, int *status) int fits_parse_input_filename / ffifile (char *filename, > char *filetype, char *infile, char *outfile, char *extspec, char *filter, char *binspec, char *colspec, char *pixspec, int *status) \end{verbatim} \begin{description} \item[6 ] Parse the input filename and return the HDU number that would be moved to if the file were opened with fits\_open\_file. The returned HDU number begins with 1 for the primary array, so for example, if the input filename = `myfile.fits[2]' then hdunum = 3 will be returned. CFITSIO does not open the file to check if the extension actually exists if an extension number is specified. If an extension name is included in the file name specification (e.g. `myfile.fits[EVENTS]' then this routine will have to open the FITS file and look for the position of the named extension, then close file again. This is not possible if the file is being read from the stdin stream, and an error will be returned in this case. If the filename does not specify an explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, which is functionally equivalent to hdunum = 1. This routine is mainly used for backward compatibility in the ftools software package and is not recommended for general use. It is generally better and more efficient to first open the FITS file with fits\_open\_file, then use fits\_get\_hdu\_num to determine which HDU in the file has been opened, rather than calling fits\_parse\_input\_url followed by a call to fits\_open\_file. \label{ffextn} \end{description} \begin{verbatim} int fits_parse_extnum / ffextn (char *filename, > int *hdunum, int *status) \end{verbatim} \begin{description} \item[7 ]Parse the input file name and return the root file name. The root name includes the file type if specified, (e.g. 'ftp://' or 'http://') and the full path name, to the extent that it is specified in the input filename. It does not include the HDU name or number, or any filtering specifications. The calling routine must allocate sufficient memory to hold the returned rootname character string. Allocating the length equal to FLEN\_FILENAME is guaranteed to be safe. \label{ffrtnm} \end{description} \begin{verbatim} int fits_parse_rootname / ffrtnm (char *filename, > char *rootname, int *status); \end{verbatim} \begin{description} \item[8 ]Test if the input file or a compressed version of the file (with a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of the 'exists' parameter will have 1 of the 4 following values: \begin{verbatim} 2: the file does not exist, but a compressed version does exist 1: the disk file does exist 0: neither the file nor a compressed version of the file exist -1: the input file name is not a disk file (could be a ftp, http, smem, or mem file, or a file piped in on the STDIN stream) \end{verbatim} \label{ffexist} \end{description} \begin{verbatim} int fits_file_exists / ffexist (char *filename, > int *exists, int *status); \end{verbatim} \begin{description} \item[9 ]Flush any internal buffers of data to the output FITS file. These routines rarely need to be called, but can be useful in cases where other processes need to access the same FITS file in real time, either on disk or in memory. These routines also help to ensure that if the application program subsequently aborts then the FITS file will have been closed properly. The first routine, fits\_flush\_file is more rigorous and completely closes, then reopens, the current HDU, before flushing the internal buffers, thus ensuring that the output FITS file is identical to what would be produced if the FITS was closed at that point (i.e., with a call to fits\_close\_file). The second routine, fits\_flush\_buffer simply flushes the internal CFITSIO buffers of data to the output FITS file, without updating and closing the current HDU. This is much faster, but there may be circumstances where the flushed file does not completely reflect the final state of the file as it will exist when the file is actually closed. A typical use of these routines would be to flush the state of a FITS table to disk after each row of the table is written. It is recommend that fits\_flush\_file be called after the first row is written, then fits\_flush\_buffer may be called after each subsequent row is written. Note that this latter routine will not automatically update the NAXIS2 keyword which records the number of rows of data in the table, so this keyword must be explicitly updated by the application program after each row is written. \label{ffflus} \end{description} \begin{verbatim} int fits_flush_file / ffflus (fitsfile *fptr, > int *status) int fits_flush_buffer / ffflsh (fitsfile *fptr, 0, > int *status) (Note: The second argument must be 0). \end{verbatim} \begin{description} \item[10 ] Wrapper functions for global initialization and cleanup of the libcurl library used when accessing files with the HTTPS or FTPS protocols. If an HTTPS/FTPS file transfer is to be performed, it is recommended that you call the init function once near the start of your program before any file\_open calls, and before creating any threads. The cleanup function should be called after all HTTPS/FTPS file accessing is completed, and after all threads are completed. The functions return 0 upon successful initialization and cleanup. These are NOT THREAD-SAFE. \label{ffihtps} \end{description} \begin{verbatim} int fits_init_https / ffihtps () int fits_cleanup_https / ffchtps () \end{verbatim} \subsection{Download Utility Functions} These routines do not need to be called for normal file accessing. They are primarily intended to help with debugging and diagnosing issues which occur during file downloads. These routines are NOT THREAD-SAFE. \begin{description} \item[1 ] Toggle the verbosity of the libcurl library diagnostic output when accessing files with the HTTPS or FTPS protocol. `flag' = 1 turns the output on, 0 turns it off (the default). \label{ffvhtps} \end{description} \begin{verbatim} void fits_verbose_https / ffvhtps (int flag) \end{verbatim} \begin{description} \item[2] If `flag' is set to 1, this will display (to stderr) a progress bar during an https file download. (This is not yet implemented for other file transfer protocols.) `flag' = 0 by default. \label{ffshdwn} \end{description} \begin{verbatim} void fits_show_download_progress / ffshdwn (int flag) \end{verbatim} \begin{description} \item[3] The timeout setting (in seconds) determines the maximum time allowed for a net download to complete. If a download has not finished within the allowed time, the file transfer will terminate and the CFITSIO calling function will return with an error. Use fits\_get\_timeout will see the current timeout setting and fits\_set\_timeout to change the setting. This adjustmant may be particularly useful when having trouble downloading large files over slow connections. \label{ffgtmo} \end{description} \begin{verbatim} int fits_get_timeout / ffgtmo () int fits_set_timeout / ffstmo (int seconds, > int *status) \end{verbatim} \section{HDU Access Routines} \begin{description} \item[1 ] Get the byte offsets in the FITS file to the start of the header and the start and end of the data in the CHDU. The difference between headstart and dataend equals the size of the CHDU. If the CHDU is the last HDU in the file, then dataend is also equal to the size of the entire FITS file. Null pointers may be input for any of the address parameters if their values are not needed. \label{ffghad} \end{description} \begin{verbatim} int fits_get_hduaddr / ffghad (only supports files up to 2.1 GB in size) (fitsfile *fptr, > long *headstart, long *datastart, long *dataend, int *status) int fits_get_hduaddrll / ffghadll (supports large files) (fitsfile *fptr, > LONGLONG *headstart, LONGLONG *datastart, LONGLONG *dataend, int *status) \end{verbatim} \begin{description} \item[2 ] Create (append) a new empty HDU at the end of the FITS file. This is now the CHDU but it is completely empty and has no header keywords. It is recommended that fits\_create\_img or fits\_create\_tbl be used instead of this routine. \label{ffcrhd} \end{description} \begin{verbatim} int fits_create_hdu / ffcrhd (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[3 ] Insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = PREPEND\_PRIMARY prior to calling the routine. In this case the old primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. Refer to Chapter 9 for a list of pre-defined bitpix values. \label{ffiimg} \end{description} \begin{verbatim} int fits_insert_img / ffiimg (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_insert_imgll / ffiimgll (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \begin{description} \item[4 ] Insert a new ASCII or binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. If the FITS file is currently empty then this routine will create a dummy primary array before appending the table to it. The new extension will become the CHDU. The tunit and extname parameters are optional and a null pointer may be given if they are not defined. When inserting an ASCII table with fits\_insert\_atbl, a null pointer may given for the *tbcol parameter in which case each column of the table will be separated by a single space character. Similarly, if the input value of rowlen is 0, then CFITSIO will calculate the default rowlength based on the tbcol and ttype values. Under normal circumstances, the nrows paramenter should have a value of 0; CFITSIO will automatically update the number of rows as data is written to the table. When inserting a binary table with fits\_insert\_btbl, if there are following extensions in the file and if the table contains variable length array columns then pcount must specify the expected final size of the data heap, otherwise pcount must = 0. \label{ffitab} \label{ffibin} \end{description} \begin{verbatim} int fits_insert_atbl / ffitab (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char *ttype[], long *tbcol, char *tform[], char *tunit[], char *extname, > int *status) int fits_insert_btbl / ffibin (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, char **tform, char **tunit, char *extname, long pcount, > int *status) \end{verbatim} \begin{description} \item[5 ] Modify the size, dimensions, and/or data type of the current primary array or image extension. If the new image, as specified by the input arguments, is larger than the current existing image in the FITS file then zero fill data will be inserted at the end of the current image and any following extensions will be moved further back in the file. Similarly, if the new image is smaller than the current image then any following extensions will be shifted up towards the beginning of the FITS file and the image data will be truncated to the new size. This routine rewrites the BITPIX, NAXIS, and NAXISn keywords with the appropriate values for the new image. \label{ffrsim} \end{description} \begin{verbatim} int fits_resize_img / ffrsim (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_resize_imgll / ffrsimll (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \begin{description} \item[6 ] Copy the data (and not the header) from the CHDU associated with infptr to the CHDU associated with outfptr. This will overwrite any data previously in the output CHDU. This low level routine is used by fits\_copy\_hdu, but it may also be useful in certain application programs that want to copy the data from one FITS file to another but also want to modify the header keywords. The required FITS header keywords which define the structure of the HDU must be written to the output CHDU before calling this routine. \label{ffcpdt} \end{description} \begin{verbatim} int fits_copy_data / ffcpdt (fitsfile *infptr, fitsfile *outfptr, > int *status) \end{verbatim} \begin{description} \item[7 ] Read or write a specified number of bytes starting at the specified byte offset from the start of the extension data unit. These low level routine are intended mainly for accessing the data in non-standard, conforming extensions, and should not be used for standard IMAGE, TABLE, or BINTABLE extensions. \label{ffgextn} \end{description} \begin{verbatim} int fits_read_ext / ffgextn (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) int fits_write_ext / ffpextn (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) \end{verbatim} \begin{description} \item[8 ] This routine forces CFITSIO to rescan the current header keywords that define the structure of the HDU (such as the NAXIS and BITPIX keywords) so that it reinitializes the internal buffers that describe the HDU structure. This routine is useful for reinitializing the structure of an HDU if any of the required keywords (e.g., NAXISn) have been modified. In practice it should rarely be necessary to call this routine because CFITSIO internally calls it in most situations. \label{ffrdef} \end{description} \begin{verbatim} int fits_set_hdustruc / ffrdef (fitsfile *fptr, > int *status) (DEPRECATED) \end{verbatim} \section{Specialized Header Keyword Routines} \subsection{Header Information Routines} \begin{description} \item[1 ] Reserve space in the CHU for MOREKEYS more header keywords. This routine may be called to allocate space for additional keywords at the time the header is created (prior to writing any data). CFITSIO can dynamically add more space to the header when needed, however it is more efficient to preallocate the required space if the size is known in advance. \label{ffhdef} \end{description} \begin{verbatim} int fits_set_hdrsize / ffhdef (fitsfile *fptr, int morekeys, > int *status) \end{verbatim} \begin{description} \item[2 ] Return the number of keywords in the header (not counting the END keyword) and the current position in the header. The position is the number of the keyword record that will be read next (or one greater than the position of the last keyword that was read). A value of 1 is returned if the pointer is positioned at the beginning of the header. \label{ffghps} \end{description} \begin{verbatim} int fits_get_hdrpos / ffghps (fitsfile *fptr, > int *keysexist, int *keynum, int *status) \end{verbatim} \subsection{Read and Write the Required Keywords} \begin{description} \item[1 ] Write the required extension header keywords into the CHU. These routines are not required, and instead the appropriate header may be constructed by writing each individual keyword in the proper sequence. The simpler fits\_write\_imghdr routine is equivalent to calling fits\_write\_grphdr with the default values of simple = TRUE, pcount = 0, gcount = 1, and extend = TRUE. The PCOUNT, GCOUNT and EXTEND keywords are not required in the primary header and are only written if pcount is not equal to zero, gcount is not equal to zero or one, and if extend is TRUE, respectively. When writing to an IMAGE extension, the SIMPLE and EXTEND parameters are ignored. It is recommended that fits\_create\_image or fits\_create\_tbl be used instead of these routines to write the required header keywords. The general fits\_write\_exthdr routine may be used to write the header of any conforming FITS extension. \label{ffphpr} \label{ffphps} \end{description} \begin{verbatim} int fits_write_imghdr / ffphps (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_write_imghdrll / ffphpsll (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) int fits_write_grphdr / ffphpr (fitsfile *fptr, int simple, int bitpix, int naxis, long *naxes, LONGLONG pcount, LONGLONG gcount, int extend, > int *status) int fits_write_grphdrll / ffphprll (fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG *naxes, LONGLONG pcount, LONGLONG gcount, int extend, > int *status) int fits_write_exthdr /ffphext (fitsfile *fptr, char *xtension, int bitpix, int naxis, long *naxes, LONGLONG pcount, LONGLONG gcount, > int *status) \end{verbatim} \begin{description} \item[2 ] Write the ASCII table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input pointers are not null. A null pointer may given for the *tbcol parameter in which case a single space will be inserted between each column of the table. Similarly, if rowlen is given = 0, then CFITSIO will calculate the default rowlength based on the tbcol and ttype values. \label{ffphtb} \end{description} \begin{verbatim} int fits_write_atblhdr / ffphtb (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char **ttype, long *tbcol, char **tform, char **tunit, char *extname, > int *status) \end{verbatim} \begin{description} \item[3 ] Write the binary table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input pointers are not null. The pcount parameter, which specifies the size of the variable length array heap, should initially = 0; CFITSIO will automatically update the PCOUNT keyword value if any variable length array data is written to the heap. The TFORM keyword value for variable length vector columns should have the form 'Pt(len)' or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) and `len' is an integer specifying the maximum length of the vectors in that column (len must be greater than or equal to the longest vector in the column). If `len' is not specified when the table is created (e.g., the input TFORMn value is just '1Pt') then CFITSIO will scan the column when the table is first closed and will append the maximum length to the TFORM keyword value. Note that if the table is subsequently modified to increase the maximum length of the vectors then the modifying program is responsible for also updating the TFORM keyword value. \label{ffphbn} \end{description} \begin{verbatim} int fits_write_btblhdr / ffphbn (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, char **tform, char **tunit, char *extname, LONGLONG pcount, > int *status) \end{verbatim} \begin{description} \item[4 ] Read the required keywords from the CHDU (image or table). When reading from an IMAGE extension the SIMPLE and EXTEND parameters are ignored. A null pointer may be supplied for any of the returned parameters that are not needed. \label{ffghpr} \label{ffghtb} \label{ffghbn} \end{description} \begin{verbatim} int fits_read_imghdr / ffghpr (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, long *naxes, long *pcount, long *gcount, int *extend, int *status) int fits_read_imghdrll / ffghprll (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, LONGLONG *naxes, long *pcount, long *gcount, int *extend, int *status) int fits_read_atblhdr / ffghtb (fitsfile *fptr,int maxdim, > long *rowlen, long *nrows, int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, char *extname, int *status) int fits_read_atblhdrll / ffghtbll (fitsfile *fptr,int maxdim, > LONGLONG *rowlen, LONGLONG *nrows, int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, char *extname, int *status) int fits_read_btblhdr / ffghbn (fitsfile *fptr, int maxdim, > long *nrows, int *tfields, char **ttype, char **tform, char **tunit, char *extname, long *pcount, int *status) int fits_read_btblhdrll / ffghbnll (fitsfile *fptr, int maxdim, > LONGLONG *nrows, int *tfields, char **ttype, char **tform, char **tunit, char *extname, long *pcount, int *status) \end{verbatim} \subsection{Write Keyword Routines} These routines simply append a new keyword to the header and do not check to see if a keyword with the same name already exists. In general it is preferable to use the fits\_update\_key routine to ensure that the same keyword is not written more than once to the header. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Write (append) a new keyword of the appropriate data type into the CHU. A null pointer may be entered for the comment parameter, which will cause the comment field of the keyword to be left blank. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffpkyx} \end{description} \begin{verbatim} int fits_write_key_str / ffpkys (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status) int fits_write_key_[log, lng] / ffpky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_write_key_[flt, dbl, fixflg, fixdbl] / ffpky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_write_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffpk[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \begin{description} \item[2 ] Write (append) a string valued keyword into the CHU which may be longer than 68 characters in length. This uses the Long String Keyword convention that is described in the`Local FITS Conventions' section in Chapter 4. Since this uses a non-standard FITS convention to encode the long keyword string, programs which use this routine should also call the fits\_write\_key\_longwarn routine to add some COMMENT keywords to warn users of the FITS file that this convention is being used. The fits\_write\_key\_longwarn routine also writes a keyword called LONGSTRN to record the version of the longstring convention that has been used, in case a new convention is adopted at some point in the future. If the LONGSTRN keyword is already present in the header, then fits\_write\_key\_longwarn will simply return without doing anything. \label{ffpkls} \label{ffplsw} \end{description} \begin{verbatim} int fits_write_key_longstr / ffpkls (fitsfile *fptr, char *keyname, char *longstr, char *comment, > int *status) int fits_write_key_longwarn / ffplsw (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[3 ] Write (append) a numbered sequence of keywords into the CHU. The starting index number (nstart) must be greater than 0. One may append the same comment to every keyword (and eliminate the need to have an array of identical comment strings, one for each keyword) by including the ampersand character as the last non-blank character in the (first) COMMENTS string parameter. This same string will then be used for the comment field in all the keywords. One may also enter a null pointer for the comment parameter to leave the comment field of the keyword blank. \label{ffpknx} \end{description} \begin{verbatim} int fits_write_keys_str / ffpkns (fitsfile *fptr, char *keyroot, int nstart, int nkeys, char **value, char **comment, > int *status) int fits_write_keys_[log, lng] / ffpkn[lj] (fitsfile *fptr, char *keyroot, int nstart, int nkeys, DTYPE *numval, char **comment, int *status) int fits_write_keys_[flt, dbl, fixflg, fixdbl] / ffpkne[edfg] (fitsfile *fptr, char *keyroot, int nstart, int nkey, DTYPE *numval, int decimals, char **comment, > int *status) \end{verbatim} \begin{description} \item[4 ]Copy an indexed keyword from one HDU to another, modifying the index number of the keyword name in the process. For example, this routine could read the TLMIN3 keyword from the input HDU (by giving keyroot = `TLMIN' and innum = 3) and write it to the output HDU with the keyword name TLMIN4 (by setting outnum = 4). If the input keyword does not exist, then this routine simply returns without indicating an error. \label{ffcpky} \end{description} \begin{verbatim} int fits_copy_key / ffcpky (fitsfile *infptr, fitsfile *outfptr, int innum, int outnum, char *keyroot, > int *status) \end{verbatim} \begin{description} \item[5 ]Write (append) a `triple precision' keyword into the CHU in F28.16 format. The floating point keyword value is constructed by concatenating the input integer value with the input double precision fraction value (which must have a value between 0.0 and 1.0). The ffgkyt routine should be used to read this keyword value, because the other keyword reading routines will not preserve the full precision of the value. \label{ffpkyt} \end{description} \begin{verbatim} int fits_write_key_triple / ffpkyt (fitsfile *fptr, char *keyname, long intval, double frac, char *comment, > int *status) \end{verbatim} \begin{description} \item[6 ]Write keywords to the CHDU that are defined in an ASCII template file. The format of the template file is described under the fits\_parse\_template routine. \label{ffpktp} \end{description} \begin{verbatim} int fits_write_key_template / ffpktp (fitsfile *fptr, const char *filename, > int *status) \end{verbatim} \subsection{Insert Keyword Routines} These insert routines are somewhat less efficient than the `update' or `write' keyword routines because the following keywords in the header must be shifted down to make room for the inserted keyword. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Insert a new keyword record into the CHU at the specified position (i.e., immediately preceding the (keynum)th keyword in the header.) \label{ffirec} \end{description} \begin{verbatim} int fits_insert_record / ffirec (fitsfile *fptr, int keynum, char *card, > int *status) \end{verbatim} \begin{description} \item[2 ] Insert a new keyword into the CHU. The new keyword is inserted immediately following the last keyword that has been read from the header. The `longstr' version has the same functionality as the `str' version except that it also supports the local long string keyword convention for strings longer than 68 characters. A null pointer may be entered for the comment parameter which will cause the comment field to be left blank. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffikyx} \end{description} \begin{verbatim} int fits_insert_card / ffikey (fitsfile *fptr, char *card, > int *status) int fits_insert_key_[str, longstr] / ffi[kys, kls] (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status) int fits_insert_key_[log, lng] / ffiky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_insert_key_[flt, fixflt, dbl, fixdbl] / ffiky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_insert_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffik[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \begin{description} \item[3 ] Insert a new keyword with an undefined, or null, value into the CHU. The value string of the keyword is left blank in this case. \label{ffikyu} \end{description} \begin{verbatim} int fits_insert_key_null / ffikyu (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \subsection{Read Keyword Routines} Wild card characters may be used when specifying the name of the keyword to be read. \begin{description} \item[1 ] Read a keyword value (with the appropriate data type) and comment from the CHU. If a NULL comment pointer is given on input, then the comment string will not be returned. If the value of the keyword is not defined (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED will be returned and the input value will not be changed (except that ffgkys will reset the value to a null string). \label{ffgkyx} \label{ffgkls} \end{description} \begin{verbatim} int fits_read_key_str / ffgkys (fitsfile *fptr, char *keyname, > char *value, char *comment, int *status); NOTE: after calling the following routine, programs must explicitly free the memory allocated for 'longstr' after it is no longer needed by calling fits_free_memory. int fits_read_key_longstr / ffgkls (fitsfile *fptr, char *keyname, > char **longstr, char *comment, int *status) int fits_free_memory / fffree (char *longstr, > int *status); int fits_read_key_[log, lng, flt, dbl, cmp, dblcmp] / ffgky[ljedcm] (fitsfile *fptr, char *keyname, > DTYPE *numval, char *comment, int *status) int fits_read_key_lnglng / ffgkyjj (fitsfile *fptr, char *keyname, > LONGLONG *numval, char *comment, int *status) \end{verbatim} \begin{description} \item[2 ] Read a sequence of indexed keyword values (e.g., NAXIS1, NAXIS2, ...). The input starting index number (nstart) must be greater than 0. If the value of any of the keywords is not defined (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED will be returned and the input value for the undefined keyword(s) will not be changed. These routines do not support wild card characters in the root name. If there are no indexed keywords in the header with the input root name then these routines do not return a non-zero status value and instead simply return nfound = 0. \label{ffgknx} \end{description} \begin{verbatim} int fits_read_keys_str / ffgkns (fitsfile *fptr, char *keyname, int nstart, int nkeys, > char **value, int *nfound, int *status) int fits_read_keys_[log, lng, flt, dbl] / ffgkn[ljed] (fitsfile *fptr, char *keyname, int nstart, int nkeys, > DTYPE *numval, int *nfound, int *status) \end{verbatim} \begin{description} \item[3 ] Read the value of a floating point keyword, returning the integer and fractional parts of the value in separate routine arguments. This routine may be used to read any keyword but is especially useful for reading the 'triple precision' keywords written by ffpkyt. \label{ffgkyt} \end{description} \begin{verbatim} int fits_read_key_triple / ffgkyt (fitsfile *fptr, char *keyname, > long *intval, double *frac, char *comment, int *status) \end{verbatim} \subsection{Modify Keyword Routines} These routines modify the value of an existing keyword. An error is returned if the keyword does not exist. Wild card characters may be used when specifying the name of the keyword to be modified. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Modify (overwrite) the nth 80-character header record in the CHU. \label{ffmrec} \end{description} \begin{verbatim} int fits_modify_record / ffmrec (fitsfile *fptr, int keynum, char *card, > int *status) \end{verbatim} \begin{description} \item[2 ] Modify (overwrite) the 80-character header record for the named keyword in the CHU. This can be used to overwrite the name of the keyword as well as its value and comment fields. \label{ffmcrd} \end{description} \begin{verbatim} int fits_modify_card / ffmcrd (fitsfile *fptr, char *keyname, char *card, > int *status) \end{verbatim} \begin{description} \item[5 ] Modify the value and comment fields of an existing keyword in the CHU. The `longstr' version has the same functionality as the `str' version except that it also supports the local long string keyword convention for strings longer than 68 characters. Optionally, one may modify only the value field and leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&) or by entering a null pointer for the comment parameter. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffmkyx} \end{description} \begin{verbatim} int fits_modify_key_[str, longstr] / ffm[kys, kls] (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status); int fits_modify_key_[log, lng] / ffmky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_modify_key_[flt, dbl, fixflt, fixdbl] / ffmky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_modify_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffmk[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \begin{description} \item[6 ] Modify the value of an existing keyword to be undefined, or null. The value string of the keyword is set to blank. Optionally, one may leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&) or by entering a null pointer. \label{ffmkyu} \end{description} \begin{verbatim} int fits_modify_key_null / ffmkyu (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \subsection{Update Keyword Routines} \begin{description} \item[1 ] These update routines modify the value, and optionally the comment field, of the keyword if it already exists, otherwise the new keyword is appended to the header. A separate routine is provided for each keyword data type. The `longstr' version has the same functionality as the `str' version except that it also supports the local long string keyword convention for strings longer than 68 characters. A null pointer may be entered for the comment parameter which will leave the comment field unchanged or blank. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffukyx} \end{description} \begin{verbatim} int fits_update_key_[str, longstr] / ffu[kys, kls] (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status) int fits_update_key_[log, lng] / ffuky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_update_key_[flt, dbl, fixflt, fixdbl] / ffuky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_update_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffuk[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \section{Define Data Scaling and Undefined Pixel Parameters} These routines set or modify the internal parameters used by CFITSIO to either scale the data or to represent undefined pixels. Generally CFITSIO will scale the data according to the values of the BSCALE and BZERO (or TSCALn and TZEROn) keywords, however these routines may be used to override the keyword values. This may be useful when one wants to read or write the raw unscaled values in the FITS file. Similarly, CFITSIO generally uses the value of the BLANK or TNULLn keyword to signify an undefined pixel, but these routines may be used to override this value. These routines do not create or modify the corresponding header keyword values. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Reset the scaling factors in the primary array or image extension; does not change the BSCALE and BZERO keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * BSCALE + BZERO. The inverse formula is used when writing data values to the FITS file. \label{ffpscl} \end{description} \begin{verbatim} int fits_set_bscale / ffpscl (fitsfile *fptr, double scale, double zero, > int *status) \end{verbatim} \begin{description} \item[2 ] Reset the scaling parameters for a table column; does not change the TSCALn or TZEROn keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * TSCAL + TZERO. The inverse formula is used when writing data values to the FITS file. \label{fftscl} \end{description} \begin{verbatim} int fits_set_tscale / fftscl (fitsfile *fptr, int colnum, double scale, double zero, > int *status) \end{verbatim} \begin{description} \item[3 ] Define the integer value to be used to signify undefined pixels in the primary array or image extension. This is only used if BITPIX = 8, 16, or 32. This does not create or change the value of the BLANK keyword in the header. \label{ffpnul} \end{description} \begin{verbatim} int fits_set_imgnull / ffpnul (fitsfile *fptr, LONGLONG nulval, > int *status) \end{verbatim} \begin{description} \item[4 ] Define the string to be used to signify undefined pixels in a column in an ASCII table. This does not create or change the value of the TNULLn keyword. \label{ffsnul} \end{description} \begin{verbatim} int fits_set_atblnull / ffsnul (fitsfile *fptr, int colnum, char *nulstr, > int *status) \end{verbatim} \begin{description} \item[5 ] Define the value to be used to signify undefined pixels in an integer column in a binary table (where TFORMn = 'B', 'I', or 'J'). This does not create or change the value of the TNULLn keyword. \label{fftnul} \end{description} \begin{verbatim} int fits_set_btblnull / fftnul (fitsfile *fptr, int colnum, LONGLONG nulval, > int *status) \end{verbatim} \section{Specialized FITS Primary Array or IMAGE Extension I/O Routines} These routines read or write data values in the primary data array (i.e., the first HDU in the FITS file) or an IMAGE extension. Automatic data type conversion is performed for if the data type of the FITS array (as defined by the BITPIX keyword) differs from the data type of the array in the calling routine. The data values are automatically scaled by the BSCALE and BZERO header values as they are being written or read from the FITS array. Unlike the basic routines described in the previous chapter, most of these routines specifically support the FITS random groups format. See Appendix B for the definition of the parameters used in these routines. The more primitive reading and writing routines (i. e., ffppr\_, ffppn\_, ffppn, ffgpv\_, or ffgpf\_) simply treat the primary array as a long 1-dimensional array of pixels, ignoring the intrinsic dimensionality of the array. When dealing with a 2D image, for example, the application program must calculate the pixel offset in the 1-D array that corresponds to any particular X, Y coordinate in the image. C programmers should note that the ordering of arrays in FITS files, and hence in all the CFITSIO calls, is more similar to the dimensionality of arrays in Fortran rather than C. For instance if a FITS image has NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just large enough to hold the image should be declared as array[50][100] and not as array[100][50]. For convenience, higher-level routines are also provided to specifically deal with 2D images (ffp2d\_ and ffg2d\_) and 3D data cubes (ffp3d\_ and ffg3d\_). The dimensionality of the FITS image is passed by the naxis1, naxis2, and naxis3 parameters and the declared dimensions of the program array are passed in the dim1 and dim2 parameters. Note that the dimensions of the program array may be larger than the dimensions of the FITS array. For example if a FITS image with NAXIS1 = NAXIS2 = 400 is read into a program array which is dimensioned as 512 x 512 pixels, then the image will just fill the lower left corner of the array with pixels in the range 1 - 400 in the X an Y directions. This has the effect of taking a contiguous set of pixel value in the FITS array and writing them to a non-contiguous array in program memory (i.e., there are now some blank pixels around the edge of the image in the program array). The most general set of routines (ffpss\_, ffgsv\_, and ffgsf\_) may be used to transfer a rectangular subset of the pixels in a FITS N-dimensional image to or from an array which has been declared in the calling program. The fpixel and lpixel parameters are integer arrays which specify the starting and ending pixel coordinate in each dimension (starting with 1, not 0) of the FITS image that is to be read or written. It is important to note that these are the starting and ending pixels in the FITS image, not in the declared array in the program. The array parameter in these routines is treated simply as a large one-dimensional array of the appropriate data type containing the pixel values; The pixel values in the FITS array are read/written from/to this program array in strict sequence without any gaps; it is up to the calling routine to correctly interpret the dimensionality of this array. The two FITS reading routines (ffgsv\_ and ffgsf\_ ) also have an `inc' parameter which defines the data sampling interval in each dimension of the FITS array. For example, if inc[0]=2 and inc[1]=3 when reading a 2-dimensional FITS image, then only every other pixel in the first dimension and every 3rd pixel in the second dimension will be returned to the 'array' parameter. Two types of routines are provided to read the data array which differ in the way undefined pixels are handled. The first type of routines (e.g., ffgpv\_) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the `nulval' parameter. An additional feature of these routines is that if the user sets nulval = 0, then no checks for undefined pixels will be performed, thus reducing the amount of CPU processing. The second type of routines (e.g., ffgpf\_) returns the data element array and, in addition, a char array that indicates whether the value of the corresponding data pixel is undefined (= 1) or defined (= 0). The latter type of routines may be more convenient to use in some circumstances, however, it requires an additional array of logical values which can be unwieldy when working with large data arrays. \begin{description} \item[1 ] Write elements into the FITS data array. \label{ffppr} \label{ffpprx} \label{ffppn} \label{ffppnx} \end{description} \begin{verbatim} int fits_write_img / ffppr (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, int *status); int fits_write_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffppr[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status); int fits_write_imgnull / ffppn (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status); int fits_write_imgnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffppn[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status); \end{verbatim} \begin{description} \item[2 ]Set data array elements as undefined. \label{ffppru} \end{description} \begin{verbatim} int fits_write_img_null / ffppru (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, > int *status) \end{verbatim} \begin{description} \item[3 ] Write values into group parameters. This routine only applies to the `Random Grouped' FITS format which has been used for applications in radio interferometry, but is officially deprecated for future use. \label{ffpgpx} \end{description} \begin{verbatim} int fits_write_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffpgp[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, > DTYPE *array, int *status) \end{verbatim} \begin{description} \item[4 ] Write a 2-D or 3-D image into the data array. \label{ffp2dx} \label{ffp3dx} \end{description} \begin{verbatim} int fits_write_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffp2d[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG naxis1, LONGLONG naxis2, DTYPE *array, > int *status) int fits_write_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffp3d[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG dim2, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[5 ] Write an arbitrary data subsection into the data array. \label{ffpssx} \end{description} \begin{verbatim} int fits_write_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffpss[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[6 ] Read elements from the FITS data array. \label{ffgpv} \label{ffgpvx} \label{ffgpf} \label{ffgpfx} \end{description} \begin{verbatim} int fits_read_img / ffgpv (fitsfile *fptr, int datatype, long firstelem, long nelements, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) int fits_read_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffgpv[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, DTYPE nulval, > DTYPE *array, int *anynul, int *status) int fits_read_imgnull / ffgpf (fitsfile *fptr, int datatype, long firstelem, long nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) int fits_read_imgnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffgpf[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[7 ] Read values from group parameters. This routine only applies to the `Random Grouped' FITS format which has been used for applications in radio interferometry, but is officially deprecated for future use. \label{ffggpx} \end{description} \begin{verbatim} int fits_read_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffggp[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, > DTYPE *array, int *status) \end{verbatim} \begin{description} \item[8 ] Read 2-D or 3-D image from the data array. Undefined pixels in the array will be set equal to the value of 'nulval', unless nulval=0 in which case no testing for undefined pixels will be performed. \label{ffg2dx} \label{ffg3dx} \end{description} \begin{verbatim} int fits_read_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffg2d[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, LONGLONG naxis1, LONGLONG naxis2, > DTYPE *array, int *anynul, int *status) int fits_read_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffg3d[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, LONGLONG dim2, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[9 ] Read an arbitrary data subsection from the data array. \label{ffgsvx} \label{ffgsfx} \end{description} \begin{verbatim} int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffgsv[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, int group, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, DTYPE nulval, > DTYPE *array, int *anynul, int *status) int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffgsf[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, int group, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \section{Specialized FITS ASCII and Binary Table Routines} \subsection{General Column Routines} \begin{description} \item[1 ] Get information about an existing ASCII or binary table column. A null pointer may be given for any of the output parameters that are not needed. DATATYPE is a character string which returns the data type of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case of an ASCII character column, typecode will have a value of the form 'An' where 'n' is an integer expressing the width of the field in characters. For example, if TFORM = '160A8' then ffgbcl will return typechar='A8' and repeat=20. All the returned parameters are scalar quantities. \label{ffgacl} \label{ffgbcl} \end{description} \begin{verbatim} int fits_get_acolparms / ffgacl (fitsfile *fptr, int colnum, > char *ttype, long *tbcol, char *tunit, char *tform, double *scale, double *zero, char *nulstr, char *tdisp, int *status) int fits_get_bcolparms / ffgbcl (fitsfile *fptr, int colnum, > char *ttype, char *tunit, char *typechar, long *repeat, double *scale, double *zero, long *nulval, char *tdisp, int *status) int fits_get_bcolparmsll / ffgbclll (fitsfile *fptr, int colnum, > char *ttype, char *tunit, char *typechar, LONGLONG *repeat, double *scale, double *zero, LONGLONG *nulval, char *tdisp, int *status) \end{verbatim} \begin{description} \item[2 ] Return optimal number of rows to read or write at one time for maximum I/O efficiency. Refer to the ``Optimizing Code'' section in Chapter 5 for more discussion on how to use this routine. \label{ffgrsz} \end{description} \begin{verbatim} int fits_get_rowsize / ffgrsz (fitsfile *fptr, long *nrows, *status) \end{verbatim} \begin{description} \item[3 ] Define the zero indexed byte offset of the 'heap' measured from the start of the binary table data. By default the heap is assumed to start immediately following the regular table data, i.e., at location NAXIS1 x NAXIS2. This routine is only relevant for binary tables which contain variable length array columns (with TFORMn = 'Pt'). This routine also automatically writes the value of theap to a keyword in the extension header. This routine must be called after the required keywords have been written (with ffphbn) but before any data is written to the table. \label{ffpthp} \end{description} \begin{verbatim} int fits_write_theap / ffpthp (fitsfile *fptr, long theap, > int *status) \end{verbatim} \begin{description} \item[4 ] Test the contents of the binary table variable array heap, returning the size of the heap, the number of unused bytes that are not currently pointed to by any of the descriptors, and the number of bytes which are pointed to by multiple descriptors. It also returns valid = FALSE if any of the descriptors point to invalid addresses out of range of the heap. \label{fftheap} \end{description} \begin{verbatim} int fits_test_heap / fftheap (fitsfile *fptr, > LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, int *validheap, int *status) \end{verbatim} \begin{description} \item[5 ] Re-pack the vectors in the binary table variable array heap to recover any unused space. Normally, when a vector in a variable length array column is rewritten the previously written array remains in the heap as wasted unused space. This routine will repack the arrays that are still in use, thus eliminating any bytes in the heap that are no longer in use. Note that if several vectors point to the same bytes in the heap, then this routine will make duplicate copies of the bytes for each vector, which will actually expand the size of the heap. \label{ffcmph} \end{description} \begin{verbatim} int fits_compress_heap / ffcmph (fitsfile *fptr, > int *status) \end{verbatim} \subsection{Low-Level Table Access Routines} The following 2 routines provide low-level access to the data in ASCII or binary tables and are mainly useful as an efficient way to copy all or part of a table from one location to another. These routines simply read or write the specified number of consecutive bytes in an ASCII or binary table, without regard for column boundaries or the row length in the table. These routines do not perform any machine dependent data conversion or byte swapping. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Read or write a consecutive array of bytes from an ASCII or binary table \label{ffgtbb} \label{ffptbb} \end{description} \begin{verbatim} int fits_read_tblbytes / ffgtbb (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, > unsigned char *values, int *status) int fits_write_tblbytes / ffptbb (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, unsigned char *values, > int *status) \end{verbatim} \subsection{Write Column Data Routines} This subsection describes specialized routines for writing data to FITS tables. Please see section \ref{specialized-read-column-data} (``Read Column Data Routines'') for more information about how values are stored in C. \begin{description} \item[1 ] Write elements into an ASCII or binary table column (in the CDU). The data type of the array is implied by the suffix of the routine name. \label{ffpcls} \end{description} \begin{verbatim} int fits_write_col_str / ffpcls (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, char **array, > int *status) int fits_write_col_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,ulnglng,flt,dbl,cmp,dblcmp] / ffpcl[l,b,i,ui,k,uk,j,uj,jj,ujj,e,d,c,m] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[2 ] Write elements into an ASCII or binary table column substituting the appropriate FITS null value for any elements that are equal to the nulval parameter. \label{ffpcnx} \end{description} \begin{verbatim} int fits_write_colnull_[log, byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffpcn[l,b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status) \end{verbatim} \begin{description} \item[3 ] Write string elements into a binary table column (in the CDU) substituting the FITS null value for any elements that are equal to the nulstr string. \label{ffpcns} \end{description} \begin{verbatim} int fits_write_colnull_str / ffpcns (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, char **array, char *nulstr, > int *status) \end{verbatim} \begin{description} \item[4 ] Write bit values into a binary byte ('B') or bit ('X') table column (in the CDU). Larray is an array of characters corresponding to the sequence of bits to be written. If an element of larray is true (not equal to zero) then the corresponding bit in the FITS table is set to 1, otherwise the bit is set to 0. The 'X' column in a FITS table is always padded out to a multiple of 8 bits where the bit array starts with the most significant bit of the byte and works down towards the 1's bit. For example, a '4X' array, with the first bit = 1 and the remaining 3 bits = 0 is equivalent to the 8-bit unsigned byte decimal value of 128 ('1000 0000B'). In the case of 'X' columns, CFITSIO can write to all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls ffpclx with firstbit=1 and nbits=8, then all 8 bits will be written into the first byte (as opposed to writing the first 4 bits into the first row and then the next 4 bits into the next row), even though the last 4 bits of each byte are formally not defined and should all be set = 0. It should also be noted that it is more efficient to write 'X' columns an entire byte at a time, instead of bit by bit. Any of the CFITSIO routines that write to columns (e.g. fits\_write\_col\_byt) may be used for this purpose. These routines will interpret 'X' columns as though they were 'B' columns (e.g., '1X' through '8X' is equivalent to '1B', and '9X' through '16X' is equivalent to '2B'). \label{ffpclx} \end{description} \begin{verbatim} int fits_write_col_bit / ffpclx (fitsfile *fptr, int colnum, LONGLONG firstrow, long firstbit, long nbits, char *larray, > int *status) \end{verbatim} \begin{description} \item[5 ] Write the descriptor for a variable length column in a binary table. This routine can be used in conjunction with ffgdes to enable 2 or more arrays to point to the same storage location to save storage space if the arrays are identical. \label{ffpdes} \end{description} \begin{verbatim} int fits_write_descript / ffpdes (fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG repeat, LONGLONG offset, > int *status) \end{verbatim} \subsection{Read Column Data Routines \label{specialized-read-column-data}} Two types of routines are provided to get the column data which differ in the way undefined pixels are handled. The first set of routines (ffgcv) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. If nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (ffgcf) returns the data element array and in addition a logical array of flags which defines whether the corresponding data pixel is undefined. See Appendix B for the definition of the parameters used in these routines. Any column, regardless of it's intrinsic data type, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the data type of the column. The length of the returned strings (not including the null terminating character) can be determined with the fits\_get\_col\_display\_width routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \begin{description} \item[1 ] Read elements from an ASCII or binary table column (in the CDU). These routines return the values of the table column array elements. The caller is required to allocate the storage \verb+array+ before calling. Undefined array elements will be returned with a value = nulval, unless nulval = 0 (or = ' ' for ffgcvs) in which case no checking for undefined values will be performed. The anynul parameter is set to true if any of the returned elements are undefined. For the \verb+_log+ (logical) variant, the C storage type is a \verb+char+ single-byte character. A FITS value of `\verb+T+'rue reads as 1 and `\verb+F+' reads as 0; other non-FITS characters are preserved untranslated. For the \verb+_str+ (string) variant the number of elements is the number of strings, and the caller must allocate storage for both the array of pointers \verb+array+ and the character array data itself (use \verb+fits_get_col_display_width+ or \verb+fits_get_coltype+ to determine the number of characters). See section \ref{character-strings} (``Dealing with Character Strings'') for more information. Also, when the \verb+_byt+ variant is used to read a column stored in the file as string data (TFORMn = 'nA'), the subroutine will read the character bytes (instead of attempting to perform a numerical conversion as other integer variants would do), with no attempt at null termination. For the \verb+_cmp+ and \verb+_dblcmp+ (complex and double complex) variants, \verb+nelements+ is the number of numerical pairs; the number of floats or doubles that must be pre-allocated is \verb+2*nelements+. \label{ffgcvx} \end{description} \begin{verbatim} int fits_read_col_str / ffgcvs (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, char *nulstr, > char **array, int *anynul, int *status) int fits_read_col_[log,byt,sht,usht,int,uint,lng,ulng, lnglng, ulnglng, flt, dbl, cmp, dblcmp] / ffgcv[l,b,i,ui,k,uk,j,uj,jj,ujj,e,d,c,m] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE nulval, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[2 ] Read elements and null flags from an ASCII or binary table column (in the CHDU). These routines return the values of the table column array elements. Any undefined array elements will have the corresponding nullarray element set equal to TRUE. The anynul parameter is set to true if any of the returned elements are undefined. \label{ffgcfx} \end{description} \begin{verbatim} int fits_read_colnull_str / ffgcfs (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, > char **array, char *nullarray, int *anynul, int *status) int fits_read_colnull_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,ulnglng,flt,dbl,cmp,dblcmp] / ffgcf[l,b,i,ui,k,uk,j,uj,jj,ujj,e,d,c,m] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[3 ] Read an arbitrary data subsection from an N-dimensional array in a binary table vector column. Undefined pixels in the array will be set equal to the value of 'nulval', unless nulval=0 in which case no testing for undefined pixels will be performed. The first and last rows in the table to be read are specified by fpixel(naxis+1) and lpixel(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INC parameter specifies the sampling interval in each dimension between the data elements that will be returned. \label{ffgsvx2} \end{description} \begin{verbatim} int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffgsv[b,i,ui,k,uk,j,uj,jj,ull,e,d] (fitsfile *fptr, int colnum, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, DTYPE nulval, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[4 ] Read an arbitrary data subsection from an N-dimensional array in a binary table vector column. Any Undefined pixels in the array will have the corresponding 'nullarray' element set equal to TRUE. The first and last rows in the table to be read are specified by fpixel(naxis+1) and lpixel(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INC parameter specifies the sampling interval in each dimension between the data elements that will be returned. \label{ffgsfx2} \end{description} \begin{verbatim} int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, ulnglng, flt, dbl] / ffgsf[b,i,ui,k,uk,j,uj,jj,ujj,e,d] (fitsfile *fptr, int colnum, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[5 ] Read bit values from a byte ('B') or bit (`X`) table column (in the CDU). Larray is an array of logical values corresponding to the sequence of bits to be read. If larray is true then the corresponding bit was set to 1, otherwise the bit was set to 0. The 'X' column in a FITS table is always padded out to a multiple of 8 bits where the bit array starts with the most significant bit of the byte and works down towards the 1's bit. For example, a '4X' array, with the first bit = 1 and the remaining 3 bits = 0 is equivalent to the 8-bit unsigned byte value of 128. Note that in the case of 'X' columns, CFITSIO can read all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls ffgcx with firstbit=1 and nbits=8, then all 8 bits will be read from the first byte (as opposed to reading the first 4 bits from the first row and then the first 4 bits from the next row), even though the last 4 bits of each byte are formally not defined. It should also be noted that it is more efficient to read 'X' columns an entire byte at a time, instead of bit by bit. Any of the CFITSIO routines that read columns (e.g. fits\_read\_col\_byt) may be used for this purpose. These routines will interpret 'X' columns as though they were 'B' columns (e.g., '8X' is equivalent to '1B', and '16X' is equivalent to '2B'). \label{ffgcx} \end{description} \begin{verbatim} int fits_read_col_bit / ffgcx (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, LONGLONG nbits, > char *larray, int *status) \end{verbatim} \begin{description} \item[6 ] Read any consecutive set of bits from an 'X' or 'B' column and interpret them as an unsigned n-bit integer. nbits must be less than 16 or 32 in ffgcxui and ffgcxuk, respectively. If nrows is greater than 1, then the same set of bits will be read from each row, starting with firstrow. The bits are numbered with 1 = the most significant bit of the first element of the column. \label{ffgcxui} \end{description} \begin{verbatim} int fits_read_col_bit_[usht, uint] / ffgcx[ui,uk] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG, nrows, long firstbit, long nbits, > DTYPE *array, int *status) \end{verbatim} \begin{description} \item[7 ] Return the descriptor for a variable length column in a binary table. The descriptor consists of 2 integer parameters: the number of elements in the array and the starting offset relative to the start of the heap. The first pair of routine returns a single descriptor whereas the second pair of routine returns the descriptors for a range of rows in the table. The only difference between the 2 routines in each pair is that one returns the parameters as 'long' integers, whereas the other returns the values as 64-bit 'LONGLONG' integers. \label{ffgdes} \end{description} \begin{verbatim} int fits_read_descript / ffgdes (fitsfile *fptr, int colnum, LONGLONG rownum, > long *repeat, long *offset, int *status) int fits_read_descriptll / ffgdesll (fitsfile *fptr, int colnum, LONGLONG rownum, > LONGLONG *repeat, LONGLONG *offset, int *status) int fits_read_descripts / ffgdess (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows > long *repeat, long *offset, int *status) int fits_read_descriptsll / ffgdessll (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows > LONGLONG *repeat, LONGLONG *offset, int *status) \end{verbatim} \chapter{ Extended File Name Syntax } \section{Overview} CFITSIO supports an extended syntax when specifying the name of the data file to be opened or created that includes the following features: \begin{itemize} \item CFITSIO can read IRAF format images which have header file names that end with the '.imh' extension, as well as reading and writing FITS files, This feature is implemented in CFITSIO by first converting the IRAF image into a temporary FITS format file in memory, then opening the FITS file. Any of the usual CFITSIO routines then may be used to read the image header or data. Similarly, raw binary data arrays can be read by converting them on the fly into virtual FITS images. \item FITS files on the Internet can be read (and sometimes written) using the FTP, HTTP, HTTPS, FTPS, or ROOT protocols. \item FITS files can be piped between tasks on the stdin and stdout streams. \item FITS files can be read and written in shared memory. This can potentially achieve better data I/O performance compared to reading and writing the same FITS files on magnetic disk. \item Compressed FITS files in gzip or Unix COMPRESS format can be directly read. \item Output FITS files can be written directly in compressed gzip format, thus saving disk space. \item FITS table columns can be created, modified, or deleted 'on-the-fly' as the table is opened by CFITSIO. This creates a virtual FITS file containing the modifications that is then opened by the application program. \item Table rows may be selected, or filtered out, on the fly when the table is opened by CFITSIO, based on an user-specified expression. Only rows for which the expression evaluates to 'TRUE' are retained in the copy of the table that is opened by the application program. \item Histogram images may be created on the fly by binning the values in table columns, resulting in a virtual N-dimensional FITS image. The application program then only sees the FITS image (in the primary array) instead of the original FITS table. \end{itemize} The latter 3 table filtering features in particular add very powerful data processing capabilities directly into CFITSIO, and hence into every task that uses CFITSIO to read or write FITS files. For example, these features transform a very simple program that just copies an input FITS file to a new output file (like the `fitscopy' program that is distributed with CFITSIO) into a multipurpose FITS file processing tool. By appending fairly simple qualifiers onto the name of the input FITS file, the user can perform quite complex table editing operations (e.g., create new columns, or filter out rows in a table) or create FITS images by binning or histogramming the values in table columns. In addition, these functions have been coded using new state-of-the art algorithms that are, in some cases, 10 - 100 times faster than previous widely used implementations. Before describing the complete syntax for the extended FITS file names in the next section, here are a few examples of FITS file names that give a quick overview of the allowed syntax: \begin{itemize} \item {\tt myfile.fits}: the simplest case of a FITS file on disk in the current directory. \item {\tt myfile.imh}: opens an IRAF format image file and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 short integer array in this case) and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' suffix will cause it to be compressed in gzip format when it is written to disk. \item {\tt myfile.fits.gz[events, 2]}: opens and uncompresses the gzipped file myfile.fits then moves to the extension with the keywords EXTNAME = 'EVENTS' and EXTVER = 2. \item {\tt -}: a dash (minus sign) signifies that the input file is to be read from the stdin file stream, or that the output file is to be written to the stdout stream. See also the stream:// driver which provides a more efficient, but more restricted method of reading or writing to the stdin or stdout streams. \item {\tt ftp://legacy.gsfc.nasa.gov/test/vela.fits}: FITS files in any ftp archive site on the Internet may be directly opened with read-only access. \item {\tt http://legacy.gsfc.nasa.gov/software/test.fits}: any valid URL to a FITS file on the Web may be opened with read-only access. \item {\tt root://legacy.gsfc.nasa.gov/test/vela.fits}: similar to ftp access except that it provides write as well as read access to the files across the network. This uses the root protocol developed at CERN. \item {\tt shmem://h2[events]}: opens the FITS file in a shared memory segment and moves to the EVENTS extension. \item {\tt mem://}: creates a scratch output file in core computer memory. The resulting 'file' will disappear when the program exits, so this is mainly useful for testing purposes when one does not want a permanent copy of the output file. \item {\tt myfile.fits[3; Images(10)]}: opens a copy of the image contained in the 10th row of the 'Images' column in the binary table in the 3th extension of the FITS file. The virtual file that is opened by the application just contains this single image in the primary array. \item {\tt myfile.fits[1:512:2, 1:512:2]}: opens a section of the input image ranging from the 1st to the 512th pixel in X and Y, and selects every second pixel in both dimensions, resulting in a 256 x 256 pixel input image in this case. \item {\tt myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]}: creates and opens a virtual file on the fly that is identical to myfile.fits except that it will contain a new column in the EVENTS extension called 'Rad' whose value is computed using the indicated expression which is a function of the values in the X and Y columns. \item {\tt myfile.fits[EVENTS][PHA > 5]}: creates and opens a virtual FITS files that is identical to 'myfile.fits' except that the EVENTS table will only contain the rows that have values of the PHA column greater than 5. In general, any arbitrary boolean expression using a C or Fortran-like syntax, which may combine AND and OR operators, may be used to select rows from a table. \item {\tt myfile.fits[EVENTS][bin (X,Y)=1,2048,4]}: creates a temporary FITS primary array image which is computed on the fly by binning (i.e, computing the 2-dimensional histogram) of the values in the X and Y columns of the EVENTS extension. In this case the X and Y coordinates range from 1 to 2048 and the image pixel size is 4 units in both dimensions, so the resulting image is 512 x 512 pixels in size. \item The final example combines many of these feature into one complex expression (it is broken into several lines for clarity): \begin{verbatim} ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] [bin (X,Y)=32] \end{verbatim} In this case, CFITSIO (1) copies and uncompresses the FITS file from the ftp site on the legacy machine, (2) moves to the 'EVENTS' extension, (3) calculates a new column called 'phacorr', (4) selects the rows in the table that have phacorr in the range 5 to 14, and finally (5) bins the remaining rows on the X and Y column coordinates, using a pixel size = 32 to create a 2D image. All this processing is completely transparent to the application program, which simply sees the final 2-D image in the primary array of the opened file. \end{itemize} The full extended CFITSIO FITS file name can contain several different components depending on the context. These components are described in the following sections: \begin{verbatim} When creating a new file: filetype://BaseFilename(templateName)[compress] When opening an existing primary array or image HDU: filetype://BaseFilename(outName)[HDUlocation][ImageSection][pixFilter] When opening an existing table HDU: filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] \end{verbatim} The filetype, BaseFilename, outName, HDUlocation, ImageSection, and pixFilter components, if present, must be given in that order, but the colFilter, rowFilter, and binSpec specifiers may follow in any order. Regardless of the order, however, the colFilter specifier, if present, will be processed first by CFITSIO, followed by the rowFilter specifier, and finally by the binSpec specifier. Multiple colFilter or rowFilter specifications may appear as separated bracketed expressions, in any order. Multiple colFilter or rowFilter expressions are treated internally as a single effective expression, with order of operations determined from left to right. CFITSIO does not support the @filename.txt complex syntax option if multiple expressions are also used. \section{Filetype} The type of file determines the medium on which the file is located (e.g., disk or network) and, hence, which internal device driver is used by CFITSIO to read and/or write the file. Currently supported types are \begin{verbatim} file:// - file on local magnetic disk (default) ftp:// - a readonly file accessed with the anonymous FTP protocol. It also supports ftp://username:password@hostname/... for accessing password-protected ftp sites. http:// - a readonly file accessed with the HTTP protocol. It supports username:password just like the ftp driver. Proxy HTTP servers are supported using the http_proxy environment variable (see following note). https:// - a readonly file accessed with the HTTPS protocol. This is available only if CFITSIO was built with the libcurl library (see the following note). ftps:// - a readonly file accessed with the FTPS protocol. This is available only if CFITSIO was built with the libcurl library. stream:// - special driver to read an input FITS file from the stdin stream, and/or write an output FITS file to the stdout stream. This driver is fragile and has limited functionality (see the following note). gsiftp:// - access files on a computational grid using the gridftp protocol in the Globus toolkit (see following note). root:// - uses the CERN root protocol for writing as well as reading files over the network (see following note). shmem:// - opens or creates a file which persists in the computer's shared memory (see following note). mem:// - opens a temporary file in core memory. The file disappears when the program exits so this is mainly useful for test purposes when a permanent output file is not desired. \end{verbatim} If the filetype is not specified, then type file:// is assumed. The double slashes '//' are optional and may be omitted in most cases. \subsection{Notes about HTTP proxy servers} A proxy HTTP server may be used by defining the address (URL) and port number of the proxy server with the http\_proxy environment variable. For example \begin{verbatim} setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 \end{verbatim} will cause CFITSIO to use port 3128 on the heasarc proxy server whenever reading a FITS file with HTTP. \subsection{Notes about HTTPS and FTPS file access} CFITSIO depends upon the availability of the libcurl library in order to perform HTTPS/FTPS file access. (This should be the development version of the library, as it contains the curl.h header file required by the CFITSIO code.) The CFITSIO 'configure' script will search for this library on your system, and if it finds it it will automatically be incorporated into the build. Note that if you have this library package on your system, you will also have the 'curl-config' executable. You can run the 'curl-config' executable with various options to learn more about the features of your libcurl installation. If the CFITSIO 'configure' succeeded in finding a usable libcurl, you will see the flag '-DCFITSIO\_HAVE\_CURL=1' in the CFITSIO Makefile and in the compilation output. If 'configure' is unable to find a usable libcurl, CFITSIO will still build but it won't have HTTPS/FTPS capability. The libcurl package is normally included as part of Xcode on Macs. However on Linux platforms you may need to manually install it. This can be easily done on Ubuntu Linux using the 'apt get' command to retrieve the libcurl4-openssl-dev or the libcurl4-gnutls-dev packages. When accessing a file with HTTPS or FTPS, the default CFITSIO behavior is to attempt to verify both the host name and the SSL certificate. If it cannot, it will still perform the file access but will issue a warning to the terminal window. The user can override this behavior to force CFITSIO to only allow file transfers when the host name and SSL certificate have been successfully verified. This is done by setting the CFITSIO\_VERIFY\_HTTPS environment variable to 'True'. ie. in a csh shell: setenv CFITSIO\_VERIFY\_HTTPS True the default setting for this is 'False'. CFITSIO has 3 functions which apply specifically to HTTPS/FTPS access: fits\_init\_https, fits\_cleanup\_https, and fits\_verbose\_https. It is recommended that you call the init and cleanup functions near the beginning and end of your program respectively. For more information about these functions, please see the 'FITS File Access Routines' section in the preceding chapter ('Specialized CFITSIO Interface Routines'). \subsection{Notes about the stream filetype driver} The stream driver can be used to efficiently read a FITS file from the stdin file stream or write a FITS to the stdout file stream. However, because these input and output streams must be accessed sequentially, the FITS file reading or writing application must also read and write the file sequentially, at least within the tolerances described below. CFITSIO supports 2 different methods for accessing FITS files on the stdin and stdout streams. The original method, which is invoked by specifying a dash character, "-", as the name of the file when opening or creating it, works by storing a complete copy of the entire FITS file in memory. In this case, when reading from stdin, CFITSIO will copy the entire stream into memory before doing any processing of the file. Similarly, when writing to stdout, CFITSIO will create a copy of the entire FITS file in memory, before finally flushing it out to the stdout stream when the FITS file is closed. Buffering the entire FITS file in this way allows the application to randomly access any part of the FITS file, in any order, but it also requires that the user have sufficient available memory (or virtual memory) to store the entire file, which may not be possible in the case of very large files. The newer stream filetype provides a more memory-efficient method of accessing FITS files on the stdin or stdout streams. Instead of storing a copy of the entire FITS file in memory, CFITSIO only uses a set of internal buffer which by default can store 40 FITS blocks, or about 100K bytes of the FITS file. The application program must process the FITS file sequentially from beginning to end, within this 100K buffer. Generally speaking the application program must conform to the following restrictions: \begin{itemize} \item The program must finish reading or writing the header keywords before reading or writing any data in the HDU. \item The HDU can contain at most about 1400 header keywords. This is the maximum that can fit in the nominal 40 FITS block buffer. In principle, this limit could be increased by recompiling CFITSIO with a larger buffer limit, which is set by the NIOBUF parameter in fitsio2.h. \item The program must read or write the data in a sequential manner from the beginning to the end of the HDU. Note that CFITSIO's internal 100K buffer allows a little latitude in meeting this requirement. \item The program cannot move back to a previous HDU in the FITS file. \item Reading or writing of variable length array columns in binary tables is not supported on streams, because this requires moving back and forth between the fixed-length portion of the binary table and the following heap area where the arrays are actually stored. \item Reading or writing of tile-compressed images is not supported on streams, because the images are internally stored using variable length arrays. \end{itemize} \subsection{Notes about the gsiftp filetype} DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. There are two different ways to install GT: 1) goto the globus toolkit web page www.globus.org and follow the download and compilation instructions; 2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ and follow the instructions (STRONGLY SUGGESTED); Once a globus client has been installed in your system with a specific flavour it is possible to compile and install the CFITSIO libraries. Specific configuration flags must be used: 1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support PATH=GLOBUS\_LOCATION i.e. the location of your globus installation 2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour ex. gcc32 Both the flags must be used and it is mandatory to set both the PATH and the flavour. USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: example: gsiftp://remote\_server\_fqhn/directory/filename The gridftp driver uses a local buffer on a temporary file the file is located in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). Grid FTP supports multi channel transfer. By default a single channel transmission is available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS environment variable (ex. export GSIFTP\_STREAMS=8). \subsection{Notes about the root filetype} The original rootd server can be obtained from: \verb-ftp://root.cern.ch/root/rootd.tar.gz- but, for it to work correctly with CFITSIO one has to use a modified version which supports a command to return the length of the file. This modified version is available in rootd subdirectory in the CFITSIO ftp area at \begin{verbatim} ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. \end{verbatim} This small server is started either by inetd when a client requests a connection to a rootd server or by hand (i.e. from the command line). The rootd server works with the ROOT TNetFile class. It allows remote access to ROOT database files in either read or write mode. By default TNetFile assumes port 432 (which requires rootd to be started as root). To run rootd via inetd add the following line to /etc/services: \begin{verbatim} rootd 432/tcp \end{verbatim} and to /etc/inetd.conf, add the following line: \begin{verbatim} rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i \end{verbatim} Force inetd to reread its conf file with \verb+kill -HUP +. You can also start rootd by hand running directly under your private account (no root system privileges needed). For example to start rootd listening on port 5151 just type: \verb+rootd -p 5151+ Notice that no \& is needed. Rootd will go into background by itself. \begin{verbatim} Rootd arguments: -i says we were started by inetd -p port# specifies a different port to listen on -d level level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum \end{verbatim} Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root): \begin{verbatim} - Add the following line to /etc/passwd: rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false where you may modify the uid, gid (71, 72) and the home directory to suite your system. - Add the following line to /etc/group: rootd:*:72:rootd where the gid must match the gid in /etc/passwd. - Create the directories: mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmp Where /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry. - To make writeable directories for anonymous do, for example: mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub \end{verbatim} That's all. Several additional remarks: you can login to an anonymous server either with the names "anonymous" or "rootd". The password should be of type user@host.do.main. Only the @ is enforced for the time being. In anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed. Anonymous mode only works when the server is started via inetd. \subsection{Notes about the shmem filetype:} Shared memory files are currently supported on most Unix platforms, where the shared memory segments are managed by the operating system kernel and `live' independently of processes. They are not deleted (by default) when the process which created them terminates, although they will disappear if the system is rebooted. Applications can create shared memory files in CFITSIO by calling: \begin{verbatim} fit_create_file(&fitsfileptr, "shmem://h2", &status); \end{verbatim} where the root `file' names are currently restricted to be 'h0', 'h1', 'h2', 'h3', etc., up to a maximum number defined by the the value of SHARED\_MAXSEG (equal to 16 by default). This is a prototype implementation of the shared memory interface and a more robust interface, which will have fewer restrictions on the number of files and on their names, may be developed in the future. When opening an already existing FITS file in shared memory one calls the usual CFITSIO routine: \begin{verbatim} fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) \end{verbatim} The file mode can be READWRITE or READONLY just as with disk files. More than one process can operate on READONLY mode files at the same time. CFITSIO supports proper file locking (both in READONLY and READWRITE modes), so calls to fits\_open\_file may be locked out until another other process closes the file. When an application is finished accessing a FITS file in a shared memory segment, it may close it (and the file will remain in the system) with fits\_close\_file, or delete it with fits\_delete\_file. Physical deletion is postponed until the last process calls ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on the file to be deleted, thus it can be blocked if the object was not opened in READWRITE mode. A shared memory management utility program called `smem', is included with the CFITSIO distribution. It can be built by typing `make smem'; then type `smem -h' to get a list of valid options. Executing smem without any options causes it to list all the shared memory segments currently residing in the system and managed by the shared memory driver. To get a list of all the shared memory objects, run the system utility program `ipcs [-a]'. \section{Base Filename} The base filename is the name of the file optionally including the director/subdirectory path, and in the case of `ftp', `http', and `root' filetypes, the machine identifier. Examples: \begin{verbatim} myfile.fits !data.fits /data/myfile.fits fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz \end{verbatim} When creating a new output file on magnetic disk (of type file://) if the base filename begins with an exclamation point (!) then any existing file with that same basename will be deleted prior to creating the new FITS file. Otherwise if the file to be created already exists, then CFITSIO will return an error and will not overwrite the existing file. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. An input FITS file may be compressed with the gzip or Unix compress algorithms, in which case CFITSIO will uncompress the file on the fly into a temporary file (in memory or on disk). Compressed files may only be opened with read-only permission. When specifying the name of a compressed FITS file it is not necessary to append the file suffix (e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name without the suffix, then it will automatically search for a compressed file with the same root name. In the case of reading ftp and http type files, CFITSIO generally looks for a compressed version of the file first, before trying to open the uncompressed file. By default, CFITSIO copies (and uncompressed if necessary) the ftp or http FITS file into memory on the local machine before opening it. This will fail if the local machine does not have enough memory to hold the whole FITS file, so in this case, the output filename specifier (see the next section) can be used to further control how CFITSIO reads ftp and http files. If the input file is an IRAF image file (*.imh file) then CFITSIO will automatically convert it on the fly into a virtual FITS image before it is opened by the application program. IRAF images can only be opened with READONLY file access. Similarly, if the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program (with READONLY access). In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. rawfile.dat[ib512,512]). The first character (case insensitive) defines the data type of the array: \begin{verbatim} b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point \end{verbatim} An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These data type characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: \begin{verbatim} raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header \end{verbatim} One special case of input file is where the filename = `-' (a dash or minus sign) or 'stdin' or 'stdout', which signifies that the input file is to be read from the stdin stream, or written to the stdout stream if a new output file is being created. In the case of reading from stdin, CFITSIO first copies the whole stream into a temporary FITS file (in memory or on disk), and subsequent reading of the FITS file occurs in this copy. When writing to stdout, CFITSIO first constructs the whole file in memory (since random access is required), then flushes it out to the stdout stream when the file is closed. In addition, if the output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed before being written to stdout. This ability to read and write on the stdin and stdout steams allows FITS files to be piped between tasks in memory rather than having to create temporary intermediate FITS files on disk. For example if task1 creates an output FITS file, and task2 reads an input FITS file, the FITS file may be piped between the 2 tasks by specifying \begin{verbatim} task1 - | task2 - \end{verbatim} where the vertical bar is the Unix piping symbol. This assumes that the 2 tasks read the name of the FITS file off of the command line. \section{Output File Name when Opening an Existing File} An optional output filename may be specified in parentheses immediately following the base file name to be opened. This is mainly useful in those cases where CFITSIO creates a temporary copy of the input FITS file before it is opened and passed to the application program. This happens by default when opening a network FTP or HTTP-type file, when reading a compressed FITS file on a local disk, when reading from the stdin stream, or when a column filter, row filter, or binning specifier is included as part of the input file specification. By default this temporary file is created in memory. If there is not enough memory to create the file copy, then CFITSIO will exit with an error. In these cases one can force a permanent file to be created on disk, instead of a temporary file in memory, by supplying the name in parentheses immediately following the base file name. The output filename can include the '!' clobber flag. Thus, if the input filename to CFITSIO is: \verb+file1.fits.gz(file2.fits)+ then CFITSIO will uncompress `file1.fits.gz' into the local disk file `file2.fits' before opening it. CFITSIO does not automatically delete the output file, so it will still exist after the application program exits. The output filename "mem://" is also allowed, which will write the output file into memory, and also allow write access to the file. This 'file' will disappear when it is closed, but this may be useful for some applications which only need to modify a temporary copy of the file. In some cases, several different temporary FITS files will be created in sequence, for instance, if one opens a remote file using FTP, then filters rows in a binary table extension, then create an image by binning a pair of columns. In this case, the remote file will be copied to a temporary local file, then a second temporary file will be created containing the filtered rows of the table, and finally a third temporary file containing the binned image will be created. In cases like this where multiple files are created, the outfile specifier will be interpreted the name of the final file as described below, in descending priority: \begin{itemize} \item as the name of the final image file if an image within a single binary table cell is opened or if an image is created by binning a table column. \item as the name of the file containing the filtered table if a column filter and/or a row filter are specified. \item as the name of the local copy of the remote FTP or HTTP file. \item as the name of the uncompressed version of the FITS file, if a compressed FITS file on local disk has been opened. \item otherwise, the output filename is ignored. \end{itemize} The output file specifier is useful when reading FTP or HTTP-type FITS files since it can be used to create a local disk copy of the file that can be reused in the future. If the output file name = `*' then a local file with the same name as the network file will be created. Note that CFITSIO will behave differently depending on whether the remote file is compressed or not as shown by the following examples: \begin{itemize} \item \verb+ftp://remote.machine/tmp/myfile.fits.gz(*)+ - the remote compressed file is copied to the local compressed file `myfile.fits.gz', which is then uncompressed in local memory before being opened and passed to the application program. \item \verb+ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)+ - the remote compressed file is copied and uncompressed into the local file `myfile.fits'. This example requires less local memory than the previous example since the file is uncompressed on disk instead of in memory. \item \verb+ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)+ - this will usually produce an error since CFITSIO itself cannot compress files. \end{itemize} The exact behavior of CFITSIO in the latter case depends on the type of ftp server running on the remote machine and how it is configured. In some cases, if the file `myfile.fits.gz' exists on the remote machine, then the server will copy it to the local machine. In other cases the ftp server will automatically create and transmit a compressed version of the file if only the uncompressed version exists. This can get rather confusing, so users should use a certain amount of caution when using the output file specifier with FTP or HTTP file types, to make sure they get the behavior that they expect. \section{Template File Name when Creating a New File} When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following Template Files chapter. \section{Image Tile-Compression Specification} When specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format (see section 5.5, ``Primary Array or IMAGE Extension I/O Routines'') by enclosing the compression parameters in square brackets following the root disk file name. Here are some examples of the syntax for specifying tile-compressed output images: \begin{verbatim} myfile.fit[compress] - use Rice algorithm and default tile size myfile.fit[compress GZIP] - use the specified compression algorithm; myfile.fit[compress Rice] only the first letter of the algorithm myfile.fit[compress PLIO] name is required. myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 \end{verbatim} \section{HDU Location Specification} The optional HDU location specifier defines which HDU (Header-Data Unit, also known as an `extension') within the FITS file to initially open. It must immediately follow the base file name (or the output file name if present). If it is not specified then the first HDU (the primary array) is opened. The HDU location specifier is required if the colFilter, rowFilter, or binSpec specifiers are present, because the primary array is not a valid HDU for these operations. The HDU may be specified either by absolute position number, starting with 0 for the primary array, or by reference to the HDU name, and optionally, the version number and the HDU type of the desired extension. The location of an image within a single cell of a binary table may also be specified, as described below. The absolute position of the extension is specified either by enclosed the number in square brackets (e.g., `[1]' = the first extension following the primary array) or by preceded the number with a plus sign (`+1'). To specify the HDU by name, give the name of the desired HDU (the value of the EXTNAME or HDUNAME keyword) and optionally the extension version number (value of the EXTVER keyword) and the extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, or BINTABLE), separated by commas and all enclosed in square brackets. If the value of EXTVER and XTENSION are not specified, then the first extension with the correct value of EXTNAME is opened. The extension name and type are not case sensitive, and the extension type may be abbreviated to a single letter (e.g., I = IMAGE extension or primary array, A or T = ASCII table extension, and B = binary table BINTABLE extension). If the HDU location specifier is equal to `[PRIMARY]' or `[P]', then the primary array (the first HDU) will be opened. An optional pound sign character ("\#") may be appended to the extension name or number to signify that any other extensions in the file should be ignored during any subsequent file filtering operations. For example, when doing row filtering operations on a table extension, CFITSIO normally creates a copy of the filtered table in memory, along with a verbatim copy of all the other extensions in the input FITS file. If the pound sign is appended to the table extension name, then only that extension, and none of the other extensions in the file, will by copied to memory, as in the following example: \begin{verbatim} myfile.fit[events#][TIME > 10000] \end{verbatim} FITS images are most commonly stored in the primary array or an image extension, but images can also be stored as a vector in a single cell of a binary table (i.e. each row of the vector column contains a different image). Such an image can be opened with CFITSIO by specifying the desired column name and the row number after the binary table HDU specifier as shown in the following examples. The column name is separated from the HDU specifier by a semicolon and the row number is enclosed in parentheses. In this case CFITSIO copies the image from the table cell into a temporary primary array before it is opened. The application program then just sees the image in the primary array, without any extensions. The particular row to be opened may be specified either by giving an absolute integer row number (starting with 1 for the first row), or by specifying a boolean expression that evaluates to TRUE for the desired row. The first row that satisfies the expression will be used. The row selection expression has the same syntax as described in the Row Filter Specifier section, below. Examples: \begin{verbatim} myfile.fits[3] - open the 3rd HDU following the primary array myfile.fits+3 - same as above, but using the FTOOLS-style notation myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' column in the 3rd extension of the file. myfile.fits[3; images(exposure > 100)] - as above, but opens the image in the first row that has an 'exposure' column value greater than 100. \end{verbatim} \section{Image Section} A virtual file containing a rectangular subsection of an image can be extracted and opened by specifying the range of pixels (start:end) along each axis to be extracted from the original image. One can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the start pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. The input image can be in the primary array, in an image extension, or contained in a vector cell of a binary table. In the later 2 cases the extension name or number must be specified before the image section specifier. Examples: \begin{verbatim} myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image consisting of the odd numbered columns (1st axis) and the even numbered rows (2nd axis) of the image in the primary array of the file. myfile.fits[*, 512:256] - open an image consisting of all the columns in the input image, but only rows 256 through 512. The image will be flipped along the 2nd axis since the starting pixel is greater than the ending pixel. myfile.fits[*:2, 512:256:2] - same as above but keeping only every other row and column in the input image. myfile.fits[-*, *] - copy the entire image, flipping it along the first axis. myfile.fits[3][1:256,1:256] - opens a subsection of the image that is in the 3rd extension of the file. myfile.fits[4; images(12)][1:10,1:10] - open an image consisting of the first 10 pixels in both dimensions. The original image resides in the 12th row of the 'images' vector column in the table in the 4th extension of the file. \end{verbatim} When CFITSIO opens an image section it first creates a temporary file containing the image section plus a copy of any other HDUs in the file. (If a `\#' character is appended to the name or number of the image HDU, as in "myfile.fits[1\#][1:200,1:200]", then the other HDUs in the input file will not be copied into memory). This temporary file is then opened by the application program, so it is not possible to write to or modify the input file when specifying an image section. Note that CFITSIO automatically updates the world coordinate system keywords in the header of the image section, if they exist, so that the coordinate associated with each pixel in the image section will be computed correctly. \section{Image Transform Filters} CFITSIO can apply a user-specified mathematical function to the value of every pixel in a FITS image, thus creating a new virtual image in computer memory that is then opened and read by the application program. The original FITS image is not modified by this process. The image transformation specifier is appended to the input FITS file name and is enclosed in square brackets. It begins with the letters 'PIX' to distinguish it from other types of FITS file filters that are recognized by CFITSIO. The image transforming function may use any of the mathematical operators listed in the following 'Row Filtering Specification' section of this document. Some examples of image transform filters are: \begin{verbatim} [pix X * 2.0] - multiply each pixel by 2.0 [pix sqrt(X)] - take the square root of each pixel [pix X + #ZEROPT - add the value of the ZEROPT keyword [pix X>0 ? log10(X) : -99.] - if the pixel value is greater than 0, compute the base 10 log, else set the pixel = -99. \end{verbatim} Use the letter 'X' in the expression to represent the current pixel value in the image. The expression is evaluated independently for each pixel in the image and may be a function of 1) the original pixel value, 2) the value of other pixels in the image at a given relative offset from the position of the pixel that is being evaluated, and 3) the value of any header keywords. Header keyword values are represented by the name of the keyword preceded by the '\#' sign. To access the the value of adjacent pixels in the image, specify the (1-D) offset from the current pixel in curly brackets. For example \begin{verbatim} [pix (x{-1} + x + x{+1}) / 3] \end{verbatim} will replace each pixel value with the running mean of the values of that pixel and it's 2 neighboring pixels. Note that in this notation the image is treated as a 1-D array, where each row of the image (or higher dimensional cube) is appended one after another in one long array of pixels. It is possible to refer to pixels in the rows above or below the current pixel by using the value of the NAXIS1 header keyword. For example \begin{verbatim} [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] \end{verbatim} will compute the mean of each image pixel and the pixels immediately above and below it in the adjacent rows of the image. The following more complex example creates a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels: \begin{verbatim} [pix (X + X{-1} + X{+1} + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] \end{verbatim} If the pixel offset extends beyond the first or last pixel in the image, the function will evaluate to undefined, or NULL. For complex or commonly used image filtering operations, one can write the expression into an external text file and then import it into the filter using the syntax '[pix @filename.txt]'. The mathematical expression can extend over multiple lines of text in the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. By default, the datatype of the resulting image will be the same as the original image, but one may force a different datatype by appended a code letter to the 'pix' keyword: \begin{verbatim} pixb - 8-bit byte image with BITPIX = 8 pixi - 16-bit integer image with BITPIX = 16 pixj - 32-bit integer image with BITPIX = 32 pixr - 32-bit float image with BITPIX = -32 pixd - 64-bit float image with BITPIX = -64 \end{verbatim} Also by default, any other HDUs in the input file will be copied without change to the output virtual FITS file, but one may discard the other HDUs by adding the number '1' to the 'pix' keyword (and following any optional datatype code letter). For example: \begin{verbatim} myfile.fits[3][pixr1 sqrt(X)] \end{verbatim} will create a virtual FITS file containing only a primary array image with 32-bit floating point pixels that have a value equal to the square root of the pixels in the image that is in the 3rd extension of the 'myfile.fits' file. \section{Column and Keyword Filtering Specification} The optional column/keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. This filtering specifier must be enclosed in square brackets and can be distinguished from a general row filter specifier (described below) by the fact that it begins with the string 'col ' and is not immediately followed by an equals sign. The original file is not changed by this filtering operation, and instead the modifications are made on a copy of the input FITS file (usually in memory), which also contains a copy of all the other HDUs in the file. (If a `\#' character is appended to the name or number of the table HDU then only the primary array, and none of the other HDUs in the input file will be copied into memory). This temporary file is passed to the application program and will persist only until the file is closed or until the program exits, unless the outfile specifier (see above) is also supplied. The column/keyword filter can be used to perform the following operations. More than one operation may be specified by separating them with commas or semi-colons. \begin{itemize} \item Copy only a specified list of columns columns to the filtered input file. The list of column name should be separated by commas or semi-colons. Wild card characters may be used in the column names to match multiple columns. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table (i.e., there is no need to explicitly list the columns to be included if any columns are being deleted). \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME column if it exists, otherwise the TIME keyword. An error is returned if neither a column nor keyword with this name exists. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. \item Rename an existing column or keyword with the syntax 'NewName == OldName'. An error is returned if neither a column nor keyword with this name exists. \item Append a new column or keyword to the table. To create a column, give the new name, optionally followed by the data type in parentheses, followed by a single equals sign and an expression to be used to compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit integer column called 'newcol' filled with zeros). The data type is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the data type is not specified then an appropriate data type will be chosen depending on the form of the expression (may be a character string, logical, bit, long integer, or double column). An appropriate vector count (in the case of binary tables) will also be added if not explicitly specified. When creating a new keyword, the keyword name must be preceded by a pound sign '\#', and the expression must evaluate to a scalar (i.e., cannot have a column name in the expression). The comment string for the keyword may be specified in parentheses immediately following the keyword name (instead of supplying a data type as in the case of creating a new column). If the keyword name ends with a pound sign '\#', then cfitsio will substitute the number of the most recently referenced column for the \# character . This is especially useful when writing a column-related keyword like TUNITn for a newly created column, as shown in the following examples. COMMENT and HISTORY keywords may also be created with the following syntax: \begin{verbatim} #COMMENT = 'This is a comment keyword' #HISTORY = 'This is a history keyword' \end{verbatim} Note that the equal sign and the quote characters will be removed, so that the resulting header keywords in these cases will look like this: \begin{verbatim} COMMENT This is a comment keyword HISTORY This is a history keyword \end{verbatim} These two special keywords are always appended to the end of the header and will not affect any previously existing COMMENT or HISTORY keywords. It is possible to delete an existing keyword using a preceding \verb+'-'+. Either of these examples will delete the keyword named \verb+VEL+. \begin{verbatim} -VEL; -#VEL; \end{verbatim} \item Recompute (overwrite) the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \end{itemize} The expression that is used when appending or recomputing columns or keywords can be arbitrarily complex and may be a function of other header keyword values and other columns (in the same row). The full syntax and available functions for the expression are described below in the row filter specification section. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table. If no columns to be deleted are specified, then only the columns that are explicitly listed will be included in the filtered output table. To include all the columns, add the '*' wildcard specifier at the end of the list, as shown in the examples. For complex or commonly used operations, one can place the operations into an external text file and import it into the column filter using the syntax '[col @filename.txt]'. The operations can extend over multiple lines of the file, but multiple operations must still be separated by commas or semi-colons. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. When using column filtering to open a file ``on the fly,'' it is permitted to use multiple column filtering expressions. For example, the syntax \begin{verbatim} filename.fits[col *][col -Y][col Z=X+1] \end{verbatim} would be treated as equivalent to joining the expressions with semicolons, or \begin{verbatim} filename.fits[col *; -Y;col Z=X+1] \end{verbatim} Please note that if multiple column filtering expressions are used, it is not permitted to also use the \verb+[col @filename.txt]+ syntax in any of the individual expressions. It is possible to use wildcard syntax to delete either keywords or columns that match a pattern. Recall that to delete either a keyword or a column, precede its name with a \verb+'-'+ character. Wildcard patterns are: \verb+'*'+, which matches any string of characters; \verb+'?'+, which matches any single character; and \verb+'#'+ which matches any numerical string. For example these statements: \begin{verbatim} -VEL*; # remove single column (or keyword) beginning with VEL -VEL_?; # remove single column (or keyword) VEL_? where ? is any character -#DEC_*; # remove single keyword beginning with DEC_ -#TUNIT#; # remove single keyword TUNIT ending w. number \end{verbatim} will remove the columns or keywords as noted. Be aware that if a \verb+'#'+ is not present, the CFITSIO engine will check for columns with the given name first, followed by keywords. The above expressions will only delete the {\it first} item which matches the pattern. If following columns or keywords in the same CHDU match the pattern, they will not be deleted. To delete {\it zero or more} keywords that match the pattern, add a trailing \verb|'+'|. \begin{verbatim} -VEL*+; # remove all columns (or keywords) beginning with VEL -VEL_?+; # remove all columns (or keyword) VEL_? where ? is any character -#DEC_*+; # remove all keywords beginning with DEC_ -#TUNIT#+; # remove all keywords TUNIT ending w. number \end{verbatim} Note that, as a 0-or-more matching pattern, this form will succeed if the requested column or keyword is not present. In that case, the deletion expression will silently proceed as if no deletion was requested. Examples: \begin{verbatim} [col Time, rate] - only the Time and rate columns will appear in the filtered input file. [col Time, *raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME, Good == STATUS] - deletes the TIME column and renames the status column to 'Good' [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - creates new PI column from PHA values and also writes the TUNITn keyword for the new column. The final '*' expression means preserve all the columns in the input table in the virtual output table; without the '*' the output table would only contain the single 'PI' column. [col rate = rate/exposure; TUNIT#(&) = 'counts/s';*] - recomputes the rate column by dividing it by the EXPOSURE keyword value. This also modifies the value of the TUNITn keyword for this column. The use of the '&' character for the keyword comment string means preserve the existing comment string for that keyword. The final '*' preserves all the columns in the input table in the virtual output table. \end{verbatim} \section{Row Filtering Specification} When entering the name of a FITS table that is to be opened by a program, an optional row filter may be specified to select a subset of the rows in the table. A temporary new FITS file is created on the fly which contains only those rows for which the row filter expression evaluates to true. The primary array and any other extensions in the input file are also copied to the temporary file. (If a `\#' character is appended to the name or number of the table HDU then only the primary array, and none of the other HDUs in the input file will be copied into the temporary file). The original FITS file is closed and the new virtual file is opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name (e.g., 'file.fits[events][GRADE==50]' selects only those rows where the GRADE column value equals 50). When dealing with tables where each row has an associated time and/or 2D spatial position, the row filter expression can also be used to select rows based on the times in a Good Time Intervals (GTI) extension, or on spatial position as given in a SAO-style region file. \subsection{General Syntax} The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression must evaluate to a boolean value for each row of the table, where a value of FALSE means that the row will be excluded. For complex or commonly used filters, one can place the expression into a text file and import it into the row filter using the syntax '[@filename.txt]'. The expression can be arbitrarily complex and extend over multiple lines of the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then enclose the name in '\$' characters as in \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. When using row filtering to open a file ``on the fly,'' it is permitted to use multiple row filtering expressions. For example, the expression \begin{verbatim} filename.fits[#ROW > 5][X.gt.7] \end{verbatim} would be treated as equivalent to joining the expressions with logical ``and'' like this, \begin{verbatim} filename.fits[(#ROW > 5)&&(X.gt.7)] \end{verbatim} Please note that if multiple row filtering expressions are used, it is not permitted to also use the \verb+[@filename.txt]+ syntax in any of the individual expressions. %% %% Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: \begin{verbatim} "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ \end{verbatim} Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive). A null value will be returned in case of illegal operations such as divide by zero, sqrt(negative) log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). \begin{verbatim} "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(y,x) "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) "hyperbolic tan" tanh(x) "round to nearest int" round(x) "round down to int" floor(x) "round up to int" ceil(x) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "error function" erf(x) "complement of erf" erfc(x) "gamma function" gamma(x) "modulus" x % y "bitwise AND" x & y "bitwise OR" x | y "bitwise XOR" x ^^ y (bitwise operators are 32-bit int only) "random # [0.0,1.0)" random() "random Gaussian" randomn() "random Poisson" randomp(x) "minimum" min(x,y) "maximum" max(x,y) "cumulative sum" accum(x) "sequential difference" seqdiff(x) "if-then-else" b?x:y "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) "substring" strmid(s,p,n) "string search" strstr(s,r) \end{verbatim} The bitwise operators for AND, OR and XOR operate upon 32-bit integer expressions only. Three different random number functions are provided: random(), with no arguments, produces a uniform random deviate between 0 and 1; randomn(), also with no arguments, produces a normal (Gaussian) random deviate with zero mean and unit standard deviation; randomp(x) produces a Poisson random deviate whose expected number of counts is X. X may be any positive real number of expected counts, including fractional values, but the return value is an integer. When the random functions are used in a vector expression, by default the same random value will be used when evaluating each element of the vector. If different random numbers are desired, then the name of a vector column should be supplied as the single argument to the random function (e.g., "flux + 0.1 * random(flux)", where "flux" is the name of a vector column). This will create a vector of random numbers that will be used in sequence when evaluating each element of the vector expression. An alternate syntax for the min and max functions has only a single argument which should be a vector value (see below). The result will be the minimum/maximum element contained within the vector. The accum(x) function forms the cumulative sum of x, element by element. Vector columns are supported simply by performing the summation process through all the values. Null values are treated as 0. The seqdiff(x) function forms the sequential difference of x, element by element. The first value of seqdiff is the first value of x. A single null value in x causes a pair of nulls in the output. The seqdiff and accum functions are functional inverses, i.e., seqdiff(accum(x)) == x as long as no null values are present. In the if-then-else expression, "b?x:y", b is an explicit boolean value or expression. There is no automatic type conversion from numeric to boolean values, so one needs to use "iVal!=0" instead of merely "iVal" as the boolean argument. x and y can be any scalar data type (including string). The angsep function computes the angular separation in degrees between 2 celestial positions, where the first 2 parameters give the RA-like and Dec-like coordinates (in decimal degrees) of the first position, and the 3rd and 4th parameters give the coordinates of the second position. The substring function strmid(S,P,N) extracts a substring from S, starting at string position P, with a substring length N. The first character position in S is labeled as 1. If P is 0, or refers to a position beyond the end of S, then the extracted substring will be NULL. S, P, and N may be functions of other columns. The string search function strstr(S,R) searches for the first occurrence of the substring R in S. The result is an integer, indicating the character position of the first match (where 1 is the first character position of S). If no match is found, then strstr() returns a NULL value. The following type casting operators are available, where the enclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: \begin{verbatim} "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i \end{verbatim} In addition, several constants are built in for use in numerical expressions: \begin{verbatim} #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string \end{verbatim} A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). Integer constants may be specified using the following notation, \begin{verbatim} 13245 decimal integer 0x12f3 hexidecimal integer 0o1373 octal integer 0b01001 binary integer \end{verbatim} Note that integer constants are only allowed to be 32-bit, i.e. between -2\^(31) and +2\^(31). Integer constants may be used in any arithmetic expression where an integer would be appropriate. Thus, they are distinct from bitmasks (which may be of arbitrary length, allow the "wildcard" bit, and may only be used in logical expressions; see below). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, value\_1 and value\_2 can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: \begin{verbatim} near(value_1, value_2, tolerance) \end{verbatim} When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: \begin{verbatim} "a null value?" ISNULL(x) "define a value for null" DEFNULL(x,y) "declare certain value null" SETNULL(x,y) \end{verbatim} ISNULL(x) returns a boolean value of TRUE if the argument x is NULL. DEFNULL(x,y) "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. SETNULL(x,y) allows NULL values to be inserted into a variable; if x==y, a NULL value is returned; otherwise y is returned (x and y must be numerical, and x must be a scalar). \subsection{Bit Masks} Bit masks can be used to select out rows from bit columns (TFORMn = \#X) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: \begin{verbatim} binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) \end{verbatim} In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. Although bitmasks may be of arbitrary length and contain a wildcard, they may only be used in logical expressions, unlike integer constants (see above) which may be used in any arithmetic expression. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: \begin{verbatim} flags == b0010011 or flags .eq. b10011 \end{verbatim} It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: \begin{verbatim} flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx \end{verbatim} Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: \begin{verbatim} (!flags) == b1101100 (flags & b1000001) == bx000001 \end{verbatim} Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. \subsection{Vector Columns} Vector columns can also be used in building the expression. No special syntax is required if one wants to operate on all elements of the vector. Simply use the column name as for a scalar column. Vector columns can be freely intermixed with scalar columns or constants in virtually all expressions. The result will be of the same dimension as the vector. Two vectors in an expression, though, need to have the same number of elements and have the same dimensions. Arithmetic and logical operations are all performed on an element by element basis. Comparing two vector columns, eg "COL1 == COL2", thus results in another vector of boolean values indicating which elements of the two vectors are equal. Several functions are available that operate on a vector. All but the last two return a scalar result: \begin{verbatim} "minimum" MIN(V) "maximum" MAX(V) "average" AVERAGE(V) "median" MEDIAN(V) "summation" SUM(V) "standard deviation" STDDEV(V) "# of values" NELEM(V) "# of non-null values" NVALID(V) "# axes" NAXIS(V) "axis dimension" NAXES(V,n) "axis pos'n" AXISELEM(V,n) "vector element pos'n" ELEMENTNUM(V) "promote to array" ARRAY(X,d) \end{verbatim} where V represents the name of a vector column or a manually constructed vector using curly brackets as described below. The first 6 of these functions ignore any null values in the vector when computing the result. The STDDEV() function computes the sample standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead of 1/SQRT(N), where N is NVALID(V). The SUM function literally sums all the elements in x, returning a scalar value. If V is a boolean vector, SUM returns the number of TRUE elements. The NELEM function returns the number of elements in vector V whereas NVALID return the number of non-null elements in the vector. (NELEM also operates on bit and string columns, returning their column widths.) As an example, to test whether all elements of two vectors satisfy a given logical comparison, one can use the expression \begin{verbatim} SUM( COL1 > COL2 ) == NELEM( COL1 ) \end{verbatim} which will return TRUE if all elements of COL1 are greater than their corresponding elements in COL2. The NAXIS(V) function returns the number of axes of the vector, for example a 2D array would be NAXIS(V) == 2. The NAXES(V,n) function returns the dimension of axis n, for example a 4x2 array would have NAXES(V,1) == 4. The ELEMENTNUM(V) and AXISELEM(V,n) functions return vectors of the same size as the input vector V. ELEMENTNUM(V) returns the vector element position for each element in the vector, starting from 1 in each row. The AXISELEM(V,n) function is similar but returns the element position of axis n only. The ARRAY(X,d) function promotes scalar value X to a vector (or array) table element. X may be any scalar-valued item, including a column, an expression, or a constant value. The resulting vector or array will have the same scalar value replicated into each element position. This may be a useful way to construct large arrays without using the cumbersome \{vector\} notation. The dimensions of the new array are given by the second argument, d. d can either be a single constant integer value, or a vector of up to five dimensions of the form \{Nx,Ny,...\}. Thus, ARRAY(TIME,4) would promote TIME to be a 4-vector, and ARRAY(0, \{2,3,1\}) would construct an array of all 0's with dimensions $2\times 3\times 1$. A second form of ARRAY(X,d) can be used where X is a vector or array, and the dimensions d merely change the dimensions of X without changing the total number of vector elements. This is a way to re-dimension an existing array. For example, ARRAY(\{1,2,3,4\},{2,2}) would transform the 4-vector into a $2\times 2$ array. To specify a single element of a vector, give the column name followed by a comma-separated list of coordinates enclosed in square brackets. For example, if a vector column named PHAS exists in the table as a one dimensional, 256 component list of numbers from which you wanted to select the 57th component for use in the expression, then PHAS[57] would do the trick. Higher dimensional arrays of data may appear in a column. But in order to interpret them, the TDIMn keyword must appear in the header. Assuming that a (4,4,4,4) array is packed into each row of a column named ARRAY4D, the (1,2,3,4) component element of each row is accessed by ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently supported. Each vector index can itself be an expression, although it must evaluate to an integer value within the bounds of the vector. Vector columns which contain spaces or arithmetic operators must have their names enclosed in "\$" characters as with \$ARRAY-4D\$[1,2,3,4]. A more C-like syntax for specifying vector indices is also available. The element used in the preceding example alternatively could be specified with the syntax ARRAY4D[4][3][2][1]. Note the reverse order of indices (as in C), as well as the fact that the values are still ones-based (as in Fortran -- adopted to avoid ambiguity for 1D vectors). With this syntax, one does not need to specify all of the indices. To extract a 3D slice of this 4D array, use ARRAY4D[4]. Variable-length vector columns are not supported. Vectors can be manually constructed within the expression using a comma-separated list of elements surrounded by curly braces ('\{\}'). For example, '\{1,3,6,1\}' is a 4-element vector containing the values 1, 3, 6, and 1. The vector can contain only boolean, integer, and real values (or expressions). The elements will be promoted to the highest data type present. Any elements which are themselves vectors, will be expanded out with each of its elements becoming an element in the constructed vector. \subsection{Row Access} To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, \verb+PHA{-3}+ will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Using the same column name on the left and right side of the equals sign while using the \verb+COLUMN{-N}+ notation will not produce the desired result. For example, \begin{verbatim} COUNT = COUNT{-1} + 1; # BAD - do not use \end{verbatim} will not produce an increasing counter. Such recursive calculations are often not possible with the calculator syntax. However, for cases where the user wishes a row counter, the special variable \verb+#ROW+ can be utilized. \subsection{Good Time Interval Filtering and Calculation} There are two functions for filtering and calculating based on Good Time Intervals, or GTIs. GTIs are commonly used to express fragmented time ranges that are not easy to express with a single start and stop time. The time intervals are defined in a FITS table extension which contains 2 columns giving the start and stop time of each good interval. A common filtering method involves selecting rows which have a time value which lies within any GTI. The gtifilter() filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in a separate GTI extension. gtifilter(a,b,c,d) evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is \begin{verbatim} gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) or gtifilter( [ 'gtifile' [, expr [, 'STARTCOL', 'STOPCOL' ] ] ] ) \end{verbatim} where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quotes may be used. In cases where this expression is entered on the Unix command line, enclose the entire expression in double quotes, and then use single quotes within the expression to enclose the 'gtifile' and other terms. It is also usually possible to do the reverse, and enclose the whole expression in single quotes and then use double quotes within the expression. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression "gtifilter()" is equivalent to \begin{verbatim} gtifilter( "", TIME, "*START*", "*STOP*" ) \end{verbatim} This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. The related function, gtifind(a,b,c,d), is similar to gtifilter() but instead of returning true/false, gtifind() returns the GTI number that brackets the requested time sample. gtifind() returns the row number in the GTI table that matches the time sample, or -1 if the time sample is not within any GTI. gtifind() is particularly useful when entries in a table must be categorized by which GTI the fall within. For example, if events in an event list must be separated by good time interval. The results of gtifind() can be used with histogram binning techniques to bin an event list by which GTI. \begin{verbatim} gtifind( "gtifile" , expr [, "STARTCOL", "STOPCOL" ] ) \end{verbatim} The requirements for specifying the gtifile are the same as for gtifilter() as described above. Like gtifilter(), the expr is the time-like expression and is optional (defaulting to TIME). The start and stop columns default to START and STOP. The function, gtioverlap(a,b,c,d,e), computes the overlap between a user-requested time range and the entries in a GTI. The cases of no overlap, partial overlap, or overlap of many GTIs within the user requested range are handled. gtioverlap() is very useful for calculating exposure times and fractional exposures of individual time bins, say for a light curve. The syntax of gtioverlap() is \begin{verbatim} gtioverlap( "gtifile" , startExpr, stopExpr [, "STARTCOL", "STOPCOL" ] ) or gtioverlap( 'gtifile' , startExpr, stopExpr [, 'STARTCOL', 'STOPCOL' ] ) \end{verbatim} The requirements for specifying the gtifile are the same as for gtifilter() as described above. Unlike gtifilter(), the startExpr and stopExpr are not optional. startExpr provides a start of the user requested time interval. startExpr is typically TIME, but can be any valid expression. Likewise, stopExpr provides the stop of the user requested time interval, and can be an expression. For example, for a light curve with a TIME column and time bin size of 1.0 seconds, the expression \begin{verbatim} gtioverlap('gtifile',TIME,TIME+1.0) \end{verbatim} would calculate the amount of overlap exposure time between each one second time bin and the GTI in 'gtifile'. In this case the time bin is assumed to begin at the time specified by TIME and end 1 second later. Neither startExpr nor stopExpr are required to be constant, and a light curve is not required to have a constant bin size. For tables, the overlap is calculated for each entry in the table. It is also possible to calculate a single overlap value, which would typically be placed in a keyword. For example, a way to to compute the total overlap exposure of a file whose TIME column is bounded by the keywords TSTART and TSTOP, overlapping with the specified GTI, would be \begin{verbatim} #EXPOSURE = gtioverlap('gtifile',#TSTART,#TSTOP) \end{verbatim} The \verb+#EXPOSURE+ syntax with a leading \+#+ ensures that the requested values are treated as keywords. Otherwise, a column named EXPOSURE will be created with the (constant) exposure value in each entry. \subsection{Spatial Region Filtering} Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is \begin{verbatim} regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) \end{verbatim} where each "[]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. There are 2 supported formats for the region file: ASCII file or FITS binary table. The region file contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. The FITS region file format is defined in a document available from the FITS Support Office at http://fits.gsfc.nasa.gov/ registry/ region.html In its simplest form, (e.g., regfilter("region.reg") ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in \begin{verbatim} regfilter("region.reg", XPOS, YPOS) \end{verbatim} Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: \begin{verbatim} regfilter("rosat.reg", X/32.+.5, Y/32.+.5) \end{verbatim} Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): \begin{verbatim} Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) \end{verbatim} where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semimajor/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. There are three low-level functions that are primarily for use with regfilter function, but they can be called directly. They return a boolean true or false depending on whether a two dimensional point is in the region or not. The positional coordinates must be given in pixel units: \begin{verbatim} "point in a circular region" circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) "point in an elliptical region" ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) "point in a rectangular region" box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) where (xcntr,ycntr) are the (x,y) position of the center of the region (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region (radius) is half the diameter of the circle (rotation) is the angle(degrees) that the region is rotated with respect to (xcntr,ycntr) (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column names NOTE: each parameter can itself be an expression, not merely a column name or constant. \end{verbatim} \subsection{Example Row Filters} \begin{verbatim} [ binary && mag <= 5.0] - Extract all binary stars brighter than fifth magnitude (note that the initial space is necessary to prevent it from being treated as a binning specification) [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [IMAGE[4,5] .gt. 100] - Extract all rows that have the (4,5) component of the IMAGE column greater than 100 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a spectrum, held in vector column SPEC, with at least one value 3 times greater than the background level held in a keyword, BACKGRND [VCOL=={1,4,2}] - Extract all rows whose vector column VCOL contains the 3-elements 1, 4, and 2. [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the Xs and Ys columns will be used to determine the coordinate of each row in the table. \end{verbatim} \section{ Binning or Histogramming Specification} The optional binning specifier is enclosed in square brackets and can be distinguished from a general row filter specification by the fact that it begins with the keyword 'bin' not immediately followed by an equals sign. When binning is specified, a temporary N-dimensional FITS primary array is created by computing the histogram of the values in the specified columns of a FITS table extension. After the histogram is computed the input FITS file containing the table is then closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no additional extensions). Obviously, the application program must be expecting to open a FITS image and not a FITS table in this case. The data type of the FITS histogram image may be specified by appending 'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double precision floating point) to the 'bin' keyword (e.g. '[binr X]' creates a real floating point image). If the data type is not explicitly specified then a 32-bit integer image will be created by default, unless the weighting option is also specified in which case the image will have a 32-bit floating point data type by default. The histogram image may have from 1 to 4 dimensions (axes), depending on the number of columns that are specified. The general form of the binning specification is: \begin{verbatim} [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] \end{verbatim} in which up to 4 columns, each corresponding to an axis of the image, are listed. The column names are case insensitive, and the column number may be given instead of the name, preceded by a pound sign (e.g., [bin \#4=1:512]). If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 axes, respectively. In cases where the column name could be confused with an arithmetic expression, enclose the column name in parentheses to force the name to be interpreted literally. In addition to binning by a FITS column, any arbitrary calculator expression may be specified as well. Usage of this form would appear as: \begin{verbatim} [bin Xcol(arbitrary expression)=min:max:binsize, ... ] \end{verbatim} The column name must still be specified, and is used to label coordinate axes of the resulting image. The expression appears immediately after the name, enclosed in parentheses. The expression may use any combination of columns, keywords, functions and constants and allowed by the CFITSIO calculator. The column name (and optional expression) may be followed by an equals sign and then the lower and upper range of the histogram, and the size of the histogram bins, separated by colons. Spaces are allowed before and after the equals sign but not within the 'min:max:binsize' string. The min, max and binsize values may be integer or floating point numbers, or they may be the names of keywords in the header of the table. If the latter, then the value of that keyword is substituted into the expression. Default values for the min, max and binsize quantities will be used if not explicitly given in the binning expression as shown in these examples: \begin{verbatim} [bin x = :512:2] - use default minimum value [bin x = 1::2] - use default maximum value [bin x = 1:512] - use default bin size [bin x = 1:] - use default maximum value and bin size [bin x = :512] - use default minimum value and bin size [bin x = 2] - use default minimum and maximum values [bin x] - use default minimum, maximum and bin size [bin 4] - default 2-D image, bin size = 4 in both axes [bin] - default 2-D image \end{verbatim} CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, if they exist, for the default min, max, and binsize, respectively. If they do not exist then CFITSIO will use the actual minimum and maximum values in the column for the histogram min and max values. The default binsize will be set to 1, or (max - min) / 10., whichever is smaller, so that the histogram will have at least 10 bins along each axis. Please note that if explicit min and max values (or TLMINn/TLMAXn keywords) are not present, then CFITSIO must check every value of the binned quantity in advance to determine the binning limits. This is especially relevant for binning expressions, which must be evaluated multiple times to determine the limits of the expression. Thus, it is always advisable to specify min and max limits where possible. A shortcut notation is allowed if all the columns/axes have the same binning specification. In this case all the column names may be listed within parentheses, followed by the (single) binning specification, as in: \begin{verbatim} [bin (X,Y)=1:512:2] [bin (X,Y) = 5] \end{verbatim} The optional weighting factor is the last item in the binning specifier and, if present, is separated from the list of columns by a semi-colon. As the histogram is accumulated, this weight is used to incremented the value of the appropriated bin in the histogram. If the weighting factor is not specified, then the default weight = 1 is assumed. The weighting factor may be a constant integer or floating point number, or the name of a keyword containing the weighting value. The weighting factor may also be the name of a table column in which case the value in that column, on a row by row basis, will be used. It may also be an expression, enclosed in parenthesis, in which case the weighting value will be evaluated for each binned row and applied accordingly. In some cases, the column or keyword may give the reciprocal of the actual weight value that is needed. In this case, precede the weight keyword or column name by a slash '/' to tell CFITSIO to use the reciprocal of the value when constructing the histogram. An expression, enclosed in parentheses, may also appear after the slash, to indicate the reciprocal value of the expression. For complex or commonly used histograms, one can also place its description into a text file and import it into the binning specification using the syntax [bin @filename.txt]. The file's contents can extend over multiple lines, although it must still conform to the no-spaces rule for the min:max:binsize syntax and each axis specification must still be comma-separated. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [bini detx, dety] - 2-D, 16-bit integer histogram of DETX and DETY columns, using default values for the histogram range and binsize [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX and DETY columns with a bin size = 16 in both axes. The histogram values are divided by the EXPOSURE keyword value. [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by the TSTART and TSTOP keywords, with 0.1 unit size bins. [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning of the PHA column for the X axis, and 1000 bins in the range 8000. to 8100. for the Y axis. [bin pha, gti_num(gtifind())=1:2:1] - a 2-D image, where PHA is the X axis and the Y axis is an expression which evaluates to the GTI number, as determined using the GTIFIND() function. [bin time=0:4000:2000, HR( (LC2/LC1).lt.1.5 ? 1 : 2 )=1:2:1] - a 2-D histogram which determines the number of samples in two time bins between 0 and 4000 and separating hardness ratio, evaluated as (LC2/LC1), between less than 1.5 or greater than 1.5. The ?: conditional function is used to decide less (or greater) than 1.5 and assign HR bin 1 or 2. [bin @binFilter.txt] - Use the contents of the text file binFilter.txt for the binning specifications. \end{verbatim} \chapter{Template Files } When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following sections. \section{Detailed Template Line Format} The format of each ASCII template line closely follows the format of a FITS keyword record: \begin{verbatim} KEYWORD = KEYVALUE / COMMENT \end{verbatim} except that free format may be used (e.g., the equals sign may appear at any position in the line) and TAB characters are allowed and are treated the same as space characters. The KEYVALUE and COMMENT fields are optional. The equals sign character is also optional, but it is recommended that it be included for clarity. Any template line that begins with the pound '\#' character is ignored by the template parser and may be use to insert comments into the template file itself. The KEYWORD name field is limited to 8 characters in length and only the letters A-Z, digits 0-9, and the hyphen and underscore characters may be used, without any embedded spaces. Lowercase letters in the template keyword name will be converted to uppercase. Leading spaces in the template line preceding the keyword name are generally ignored, except if the first 8 characters of a template line are all blank, then the entire line is treated as a FITS comment keyword (with a blank keyword name) and is copied verbatim into the FITS header. The KEYVALUE field may have any allowed FITS data type: character string, logical, integer, real, complex integer, or complex real. Integer values must be within the allowed range of a 'signed long' variable; some C compilers only suppport 4-byte long integers with a range from -2147483648 to +2147483647, whereas other C compilers support 8-byte integers with a range of plus or minus 2**63. The character string values need not be enclosed in single quote characters unless they are necessary to distinguish the string from a different data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has an undefined (null) value if the template record only contains blanks following the "=" or between the "=" and the "/" comment field delimiter. String keyword values longer than 68 characters (the maximum length that will fit in a single FITS keyword record) are permitted using the CFITSIO long string convention. They can either be specified as a single long line in the template, or by using multiple lines where the continuing lines contain the 'CONTINUE' keyword, as in this example: \begin{verbatim} LONGKEY = 'This is a long string value that is contin&' CONTINUE 'ued over 2 records' / comment field goes here \end{verbatim} The format of template lines with CONTINUE keyword is very strict: 3 spaces must follow CONTINUE and the rest of the line is copied verbatim to the FITS file. The start of the optional COMMENT field must be preceded by "/", which is used to separate it from the keyword value field. Exceptions are if the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the first 8 characters of the template line are blanks. More than one Header-Data Unit (HDU) may be defined in the template file. The start of an HDU definition is denoted with a SIMPLE or XTENSION template line: 1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as the first keyword in the template file. If the template file begins with XTENSION instead of SIMPLE, then a default empty Primary HDU is created, and the template is then assumed to define the keywords starting with the first extension following the Primary HDU. 2) XTENSION marks the beginning of a new extension HDU definition. The previous HDU will be closed at this point and processing of the next extension begins. \section{Auto-indexing of Keywords} If a template keyword name ends with a "\#" character, it is said to be 'auto-indexed'. Each "\#" character will be replaced by the current integer index value, which gets reset = 1 at the start of each new HDU in the file (or 7 in the special case of a GROUP definition). The FIRST indexed keyword in each template HDU definition is used as the 'incrementor'; each subsequent occurrence of this SAME keyword will cause the index value to be incremented. This behavior can be rather subtle, as illustrated in the following examples in which the TTYPE keyword is the incrementor in both cases: \begin{verbatim} TTYPE# = TIME TFORM# = 1D TTYPE# = RATE TFORM# = 1E \end{verbatim} will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the template looks like, \begin{verbatim} TTYPE# = TIME TTYPE# = RATE TFORM# = 1D TFORM# = 1E \end{verbatim} this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, which is probably not what was intended! \section{Template Parser Directives} In addition to the template lines which define individual keywords, the template parser recognizes 3 special directives which are each preceded by the backslash character: \verb+ \include, \group+, and \verb+ \end+. The 'include' directive must be followed by a filename. It forces the parser to temporarily stop reading the current template file and begin reading the include file. Once the parser reaches the end of the include file it continues parsing the current template file. Include files can be nested, and HDU definitions can span multiple template files. The start of a GROUP definition is denoted with the 'group' directive, and the end of a GROUP definition is denoted with the 'end' directive. Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member blocks of type GROUP can contain their own member blocks. The GROUP definition itself occupies one FITS file HDU of special type (GROUP HDU), so if a template specifies 1 group with 1 member HDU like: \begin{verbatim} \group grpdescr = 'demo' xtension bintable # this bintable has 0 cols, 0 rows \end \end{verbatim} then the parser creates a FITS file with 3 HDUs : \begin{verbatim} 1) dummy PHDU 2) GROUP HDU (has 1 member, which is bintable in HDU number 3) 3) bintable (member of GROUP in HDU number 2) \end{verbatim} Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications can define additional columns in a GROUP HDU using TFORMn and TTYPEn (where n is 7, 8, ....) keywords or their auto-indexing equivalents. For a more complicated example of a template file using the group directives, look at the sample.tpl file that is included in the CFITSIO distribution. \section{Formal Template Syntax} The template syntax can formally be defined as follows: \begin{verbatim} TEMPLATE = BLOCK [ BLOCK ... ] BLOCK = { HDU | GROUP } GROUP = \GROUP [ BLOCK ... ] \END HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] X ... - X can be present 1 or more times { X | Y } - X or Y [ X ] - X is optional \end{verbatim} At the topmost level, the template defines 1 or more template blocks. Blocks can be either HDU (Header Data Unit) or a GROUP. For each block the parser creates 1 (or more for GROUPs) FITS file HDUs. \section{Errors} In general the fits\_execute\_template() function tries to be as atomic as possible, so either everything is done or nothing is done. If an error occurs during parsing of the template, fits\_execute\_template() will (try to) delete the top level BLOCK (with all its children if any) in which the error occurred, then it will stop reading the template file and it will return with an error. \section{Examples} 1. This template file will create a 200 x 300 pixel image, with 4-byte integer pixel values, in the primary HDU: \begin{verbatim} SIMPLE = T BITPIX = 32 NAXIS = 2 / number of dimensions NAXIS1 = 100 / length of first axis NAXIS2 = 200 / length of second axis OBJECT = NGC 253 / name of observed object \end{verbatim} The allowed values of BITPIX are 8, 16, 32, -32, or -64, representing, respectively, 8-bit integer, 16-bit integer, 32-bit integer, 32-bit floating point, or 64 bit floating point pixels. 2. To create a FITS table, the template first needs to include XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary table, and NAXIS2 to define the number of rows in the table. Two template lines are then needed to define the name (TTYPEn) and FITS data format (TFORMn) of the columns, as in this example: \begin{verbatim} xtension = bintable naxis2 = 40 ttype# = Name tform# = 10a ttype# = Npoints tform# = j ttype# = Rate tunit# = counts/s tform# = e \end{verbatim} The above example defines a null primary array followed by a 40-row binary table extension with 3 columns called 'Name', 'Npoints', and 'Rate', with data formats of '10A' (ASCII character string), '1J' (integer) and '1E' (floating point), respectively. Note that the other required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, and END) do not need to be explicitly defined in the template because their values can be inferred from the other keywords in the template. This example also illustrates that the templates are generally case-insensitive (the keyword names and TFORMn values are converted to upper-case in the FITS file) and that string keyword values generally do not need to be enclosed in quotes. \chapter{ Local FITS Conventions } CFITSIO supports several local FITS conventions which are not defined in the official FITS standard and which are not necessarily recognized or supported by other FITS software packages. Programmers should be cautious about using these features, especially if the FITS files that are produced are expected to be processed by other software systems which do not use the CFITSIO interface. \section{64-Bit Long Integers} CFITSIO supports reading and writing FITS images or table columns containing 64-bit integer data values. Support for 64-bit integers was added to the official FITS Standard in December 2005. FITS 64-bit images have BITPIX = 64, and the 64-bit binary table columns have TFORMn = 'K'. CFITSIO also supports the 'Q' variable-length array table column format which is analogous to the 'P' column format except that the array descriptor is stored as a pair of 64-bit integers. For the convenience of C programmers, the fitsio.h include file defines (with a typedef statement) the 'LONGLONG' datatype to be equivalent to an appropriate 64-bit integer datatype on each platform. Since there is currently no universal standard for the name of the 64-bit integer datatype (it might be defined as 'long long', 'long', or '\_\_int64' depending on the platform) C programmers may prefer to use the 'LONGLONG' datatype when declaring or allocating 64-bit integer quantities when writing code which needs to run on multiple platforms. Note that CFITSIO will implicitly convert the datatype when reading or writing FITS 64-bit integer images and columns with data arrays of a different integer or floating point datatype, but there is an increased risk of loss of numerical precision or numerical overflow in this case. \section{Long String Keyword Values.} The length of a standard FITS string keyword is limited to 68 characters because it must fit entirely within a single FITS header keyword record. In some instances it is necessary to encode strings longer than this limit, so CFITSIO supports a local convention in which the string value is continued over multiple keywords. This continuation convention uses an ampersand character at the end of each substring to indicate that it is continued on the next keyword, and the continuation keywords all have the name CONTINUE without an equal sign in column 9. The string value may be continued in this way over as many additional CONTINUE keywords as is required. The following lines illustrate this continuation convention which is used in the value of the STRKEY keyword: \begin{verbatim} LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. STRKEY = 'This is a very long string keyword&' / Optional Comment CONTINUE ' value that is continued over 3 keywords in the & ' CONTINUE 'FITS header.' / This is another optional comment. \end{verbatim} It is recommended that the LONGSTRN keyword, as shown here, always be included in any HDU that uses this longstring convention as a warning to any software that must read the keywords. A routine called fits\_write\_key\_longwarn has been provided in CFITSIO to write this keyword if it does not already exist. This long string convention is supported by the following CFITSIO routines: \begin{verbatim} fits_write_key_longstr - write a long string keyword value fits_insert_key_longstr - insert a long string keyword value fits_modify_key_longstr - modify a long string keyword value fits_update_key_longstr - modify a long string keyword value fits_read_key_longstr - read a long string keyword value fits_delete_key - delete a keyword \end{verbatim} The fits\_read\_key\_longstr routine is unique among all the CFITSIO routines in that it internally allocates memory for the long string value; all the other CFITSIO routines that deal with arrays require that the calling program pre-allocate adequate space to hold the array of data. Consequently, programs which use the fits\_read\_key\_longstr routine must be careful to free the allocated memory for the string when it is no longer needed. The following 2 routines also have limited support for this long string convention, \begin{verbatim} fits_modify_key_str - modify an existing string keyword value fits_update_key_str - update a string keyword value \end{verbatim} in that they will correctly overwrite an existing long string value, but the new string value is limited to a maximum of 68 characters in length. The more commonly used CFITSIO routines to write string valued keywords (fits\_update\_key and fits\_write\_key) do not support this long string convention and only support strings up to 68 characters in length. This has been done deliberately to prevent programs from inadvertently writing keywords using this non-standard convention without the explicit intent of the programmer or user. The fits\_write\_key\_longstr routine must be called instead to write long strings. This routine can also be used to write ordinary string values less than 68 characters in length. \section{Arrays of Fixed-Length Strings in Binary Tables} CFITSIO supports 2 ways to specify that a character column in a binary table contains an array of fixed-length strings. The first way, which is officially supported by the FITS Standard document, uses the TDIMn keyword. For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that column will be interpreted as containing an array of 5 strings, each 12 characters long. CFITSIO also supports a local convention for the format of the TFORMn keyword value of the form 'rAw' where 'r' is an integer specifying the total width in characters of the column, and 'w' is an integer specifying the (fixed) length of an individual unit string within the vector. For example, TFORM1 = '120A10' would indicate that the binary table column is 120 characters wide and consists of 12 10-character length strings. This convention is recognized by the CFITSIO routines that read or write strings in binary tables. The Binary Table definition document specifies that other optional characters may follow the data type code in the TFORM keyword, so this local convention is in compliance with the FITS standard although other FITS readers may not recognize this convention. \section{Keyword Units Strings} One limitation of the current FITS Standard is that it does not define a specific convention for recording the physical units of a keyword value. The TUNITn keyword can be used to specify the physical units of the values in a table column, but there is no analogous convention for keyword values. The comment field of the keyword is often used for this purpose, but the units are usually not specified in a well defined format that FITS readers can easily recognize and extract. To solve this problem, CFITSIO uses a local convention in which the keyword units are enclosed in square brackets as the first token in the keyword comment field; more specifically, the opening square bracket immediately follows the slash '/' comment field delimiter and a single space character. The following examples illustrate keywords that use this convention: \begin{verbatim} EXPOSURE= 1800.0 / [s] elapsed exposure time V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity LAMBDA = 5400. / [angstrom] central wavelength FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux \end{verbatim} In general, the units named in the IAU(1988) Style Guide are recommended, with the main exception that the preferred unit for angle is 'deg' for degrees. The fits\_read\_key\_unit and fits\_write\_key\_unit routines in CFITSIO read and write, respectively, the keyword unit strings in an existing keyword. \section{HIERARCH Convention for Extended Keyword Names} CFITSIO supports the HIERARCH keyword convention which allows keyword names that are longer than 8 characters. This convention was developed at the European Southern Observatory (ESO) and allows characters consisting of digits 0-9, upper case letters A-Z, the dash '-' and the underscore '\_'. The components of hierarchical keywords are separated by a single ASCII space charater. For instance: \begin{verbatim} HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position \end{verbatim} Basically, this convention uses the FITS keyword 'HIERARCH' to indicate that this convention is being used, then the actual keyword name ({\tt'ESO INS FOCU POS'} in this example) begins in column 10. The equals sign marks the end of the keyword name and is followed by the usual value and comment fields just as in standard FITS keywords. Further details of this convention are described at http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html and in Section 4.4 of the ESO Data Interface Control Document that is linked to from http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. This convention allows a broader range of keyword names than is allowed by the FITS Standard. Here are more examples of such keywords: \begin{verbatim} HIERARCH LONGKEYWORD = 47.5 / Keyword has > 8 characters HIERARCH LONG-KEY_WORD2 = 52.3 / Long keyword with hyphen, underscore and digit HIERARCH EARTH IS A STAR = F / Keyword contains embedded spaces \end{verbatim} CFITSIO will transparently read and write these keywords, so application programs do not in general need to know anything about the specific implementation details of the HIERARCH convention. In particular, application programs do not need to specify the `HIERARCH' part of the keyword name when reading or writing keywords (although it may be included if desired). When writing a keyword, CFITSIO first checks to see if the keyword name is legal as a standard FITS keyword (no more than 8 characters long and containing only letters, digits, or a minus sign or underscore). If so it writes it as a standard FITS keyword, otherwise it uses the hierarch convention to write the keyword. The maximum keyword name length is 67 characters, which leaves only 1 space for the value field. A more practical limit is about 40 characters, which leaves enough room for most keyword values. CFITSIO returns an error if there is not enough room for both the keyword name and the keyword value on the 80-character card, except for string-valued keywords which are simply truncated so that the closing quote character falls in column 80. A space is also required on either side of the equal sign. \section{Tile-Compressed Image Format} CFITSIO supports a convention for compressing n-dimensional images and storing the resulting byte stream in a variable-length column in a FITS binary table. The general principle used in this convention is to first divide the n-dimensional image into a rectangular grid of subimages or `tiles'. Each tile is then compressed as a continuous block of data, and the resulting compressed byte stream is stored in a row of a variable length column in a FITS binary table. By dividing the image into tiles it is generally possible to extract and uncompress subsections of the image without having to uncompress the whole image. The default tiling pattern treats each row of a 2-dimensional image (or higher dimensional cube) as a tile, such that each tile contains NAXIS1 pixels (except the default with the HCOMPRESS algorithm is to compress the whole 2D image as a single tile). Any other rectangular tiling pattern may also be defined. In the case of relatively small images it may be sufficient to compress the entire image as a single tile, resulting in an output binary table with 1 row. In the case of 3-dimensional data cubes, it may be advantageous to treat each plane of the cube as a separate tile if application software typically needs to access the cube on a plane by plane basis. See section 5.6 ``Image Compression'' for more information on using this tile-compressed image format. \chapter{ Optimizing Programs } CFITSIO has been carefully designed to obtain the highest possible speed when reading and writing FITS files. In order to achieve the best performance, however, application programmers must be careful to call the CFITSIO routines appropriately and in an efficient sequence; inappropriate usage of CFITSIO routines can greatly slow down the execution speed of a program. The maximum possible I/O speed of CFITSIO depends of course on the type of computer system that it is running on. To get a general idea of what data I/O speeds are possible on a particular machine, build the speed.c program that is distributed with CFITSIO (type 'make speed' in the CFITSIO directory). This diagnostic program measures the speed of writing and reading back a test FITS image, a binary table, and an ASCII table. The following 2 sections provide some background on how CFITSIO internally manages the data I/O and describes some strategies that may be used to optimize the processing speed of software that uses CFITSIO. \section{How CFITSIO Manages Data I/O} Many CFITSIO operations involve transferring only a small number of bytes to or from the FITS file (e.g, reading a keyword, or writing a row in a table); it would be very inefficient to physically read or write such small blocks of data directly in the FITS file on disk, therefore CFITSIO maintains a set of internal Input--Output (IO) buffers in RAM memory that each contain one FITS block (2880 bytes) of data. Whenever CFITSIO needs to access data in the FITS file, it first transfers the FITS block containing those bytes into one of the IO buffers in memory. The next time CFITSIO needs to access bytes in the same block it can then go to the fast IO buffer rather than using a much slower system disk access routine. The number of available IO buffers is determined by the NIOBUF parameter (in fitsio2.h) and is currently set to 40 by default. Whenever CFITSIO reads or writes data it first checks to see if that block of the FITS file is already loaded into one of the IO buffers. If not, and if there is an empty IO buffer available, then it will load that block into the IO buffer (when reading a FITS file) or will initialize a new block (when writing to a FITS file). If all the IO buffers are already full, it must decide which one to reuse (generally the one that has been accessed least recently), and flush the contents back to disk if it has been modified before loading the new block. The one major exception to the above process occurs whenever a large contiguous set of bytes are accessed, as might occur when reading or writing a FITS image. In this case CFITSIO bypasses the internal IO buffers and simply reads or writes the desired bytes directly in the disk file with a single call to a low-level file read or write routine. The minimum threshold for the number of bytes to read or write this way is set by the MINDIRECT parameter and is currently set to 3 FITS blocks = 8640 bytes. This is the most efficient way to read or write large chunks of data. Note that this fast direct IO process is not applicable when accessing columns of data in a FITS table because the bytes are generally not contiguous since they are interleaved by the other columns of data in the table. This explains why the speed for accessing FITS tables is generally slower than accessing FITS images. Given this background information, the general strategy for efficiently accessing FITS files should be apparent: when dealing with FITS images, read or write large chunks of data at a time so that the direct IO mechanism will be invoked; when accessing FITS headers or FITS tables, on the other hand, once a particular FITS block has been loading into one of the IO buffers, try to access all the needed information in that block before it gets flushed out of the IO buffer. It is important to avoid the situation where the same FITS block is being read then flushed from a IO buffer multiple times. The following section gives more specific suggestions for optimizing the use of CFITSIO. \section{Optimization Strategies} 1. Because the data in FITS files is always stored in "big-endian" byte order, where the first byte of numeric values contains the most significant bits and the last byte contains the least significant bits, CFITSIO must swap the order of the bytes when reading or writing FITS files when running on little-endian machines (e.g., Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). On relatively new CPUs that support "SSSE3" machine instructions (e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs beginning in 2011) significantly faster 4-byte and 8-byte swapping algorithms are available. These faster byte swapping functions are not used by default in CFITSIO (because of potential code portablility issues), but users can enable them on supported platforms by adding the appropriate compiler flags (-mssse3 with gcc or icc on linux) when compiling the swapproc.c source file, which will allow the compiler to generate code using the SSSE3 instruction set. A convenient way to do this is to configure the CFITSIO library with the following command: \begin{verbatim} > ./configure --enable-ssse3 \end{verbatim} Note, however, that a binary executable file that is created using these faster functions will only run on machines that support the SSSE3 machine instructions. For faster 2-byte swaps on virtually all x86-64 CPUs (even those that do not support SSSE3), a variant using only SSE2 instructions exists. SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems (and is also automatically enabled by the --enable-ssse3 flag). When running on x86\_64 CPUs with 32-bit operating systems, these faster 2-byte swapping algorithms are not used by default in CFITSIO, but can be enabled explicitly with: \begin{verbatim} ./configure --enable-sse2 \end{verbatim} Preliminary testing indicates that these SSSE3 and SSE2 based byte-swapping algorithms can boost the CFITSIO performance when reading or writing FITS images by 20\% - 30\% or more. It is important to note, however, that compiler optimization must be turned on (e.g., by using the -O1 or -O2 flags in gcc) when building programs that use these fast byte-swapping algorithms in order to reap the full benefit of the SSSE3 and SSE2 instructions; without optimization, the code may actually run slower than when using more traditional byte-swapping techniques. 2. When dealing with a FITS primary array or IMAGE extension, it is more efficient to read or write large chunks of the image at a time (at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism will be used as described in the previous section. Smaller chunks of data are read or written via the IO buffers, which is somewhat less efficient because of the extra copy operation and additional bookkeeping steps that are required. In principle it is more efficient to read or write as big an array of image pixels at one time as possible, however, if the array becomes so large that the operating system cannot store it all in RAM, then the performance may be degraded because of the increased swapping of virtual memory to disk. 3. When dealing with FITS tables, the most important efficiency factor in the software design is to read or write the data in the FITS file in a single pass through the file. An example of poor program design would be to read a large, 3-column table by sequentially reading the entire first column, then going back to read the 2nd column, and finally the 3rd column; this obviously requires 3 passes through the file which could triple the execution time of an IO limited program. For small tables this is not important, but when reading multi-megabyte sized tables these inefficiencies can become significant. The more efficient procedure in this case is to read or write only as many rows of the table as will fit into the available internal IO buffers, then access all the necessary columns of data within that range of rows. Then after the program is completely finished with the data in those rows it can move on to the next range of rows that will fit in the buffers, continuing in this way until the entire file has been processed. By using this procedure of accessing all the columns of a table in parallel rather than sequentially, each block of the FITS file will only be read or written once. The optimal number of rows to read or write at one time in a given table depends on the width of the table row and on the number of IO buffers that have been allocated in CFITSIO. The CFITSIO Iterator routine will automatically use the optimal-sized buffer, but there is also a CFITSIO routine that will return the optimal number of rows for a given table: fits\_get\_rowsize. It is not critical to use exactly the value of nrows returned by this routine, as long as one does not exceed it. Using a very small value however can also lead to poor performance because of the overhead from the larger number of subroutine calls. The optimal number of rows returned by fits\_get\_rowsize is valid only as long as the application program is only reading or writing data in the specified table. Any other calls to access data in the table header would cause additional blocks of data to be loaded into the IO buffers displacing data from the original table, and should be avoided during the critical period while the table is being read or written. 4. Use the CFITSIO Iterator routine. This routine provides a more `object oriented' way of reading and writing FITS files which automatically uses the most appropriate data buffer size to achieve the maximum I/O throughput. 5. Use binary table extensions rather than ASCII table extensions for better efficiency when dealing with tabular data. The I/O to ASCII tables is slower because of the overhead in formatting or parsing the ASCII data fields and because ASCII tables are about twice as large as binary tables that have the same information content. 6. Design software so that it reads the FITS header keywords in the same order in which they occur in the file. When reading keywords, CFITSIO searches forward starting from the position of the last keyword that was read. If it reaches the end of the header without finding the keyword, it then goes back to the start of the header and continues the search down to the position where it started. In practice, as long as the entire FITS header can fit at one time in the available internal IO buffers, then the header keyword access will be relatively fast and it makes little difference which order they are accessed. 7. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and TZERO keywords) in FITS files since the scaling operations add to the processing time needed to read or write the data. In some cases it may be more efficient to temporarily turn off the scaling (using fits\_set\_bscale or fits\_set\_tscale) and then read or write the raw unscaled values in the FITS file. 8. Avoid using the `implicit data type conversion' capability in CFITSIO. For instance, when reading a FITS image with BITPIX = -32 (32-bit floating point pixels), read the data into a single precision floating point data array in the program. Forcing CFITSIO to convert the data to a different data type can slow the program. 9. Where feasible, design FITS binary tables using vector column elements so that the data are written as a contiguous set of bytes, rather than as single elements in multiple rows. For example, it is faster to access the data in a table that contains a single row and 2 columns with TFORM keywords equal to '10000E' and '10000J', than it is to access the same amount of data in a table with 10000 rows which has columns with the TFORM keywords equal to '1E' and '1J'. In the former case the 10000 floating point values in the first column are all written in a contiguous block of the file which can be read or written quickly, whereas in the second case each floating point value in the first column is interleaved with the integer value in the second column of the same row so CFITSIO has to explicitly move to the position of each element to be read or written. 10. Avoid the use of variable length vector columns in binary tables, since any reading or writing of these data requires that CFITSIO first look up or compute the starting address of each row of data in the heap. In practice, this is probably not a significant efficiency issue. 11. When copying data from one FITS table to another, it is faster to transfer the raw bytes instead of reading then writing each column of the table. The CFITSIO routines fits\_read\_tblbytes and fits\_write\_tblbytes will perform low-level reads or writes of any contiguous range of bytes in a table extension. These routines can be used to read or write a whole row (or multiple rows for even greater efficiency) of a table with a single function call. These routines are fast because they bypass all the usual data scaling, error checking and machine dependent data conversion that is normally done by CFITSIO, and they allow the program to write the data to the output file in exactly the same byte order. For these same reasons, these routines can corrupt the FITS data file if used incorrectly because no validation or machine dependent conversion is performed by these routines. These routines are only recommended for optimizing critical pieces of code and should only be used by programmers who thoroughly understand the internal format of the FITS tables they are reading or writing. 12. Another strategy for improving the speed of writing a FITS table, similar to the previous one, is to directly construct the entire byte stream for a whole table row (or multiple rows) within the application program and then write it to the FITS file with fits\_write\_tblbytes. This avoids all the overhead normally present in the column-oriented CFITSIO write routines. This technique should only be used for critical applications because it makes the code more difficult to understand and maintain, and it makes the code more system dependent (e.g., do the bytes need to be swapped before writing to the FITS file?). 13. Finally, external factors such as the speed of the data storage device, the size of the data cache, the amount of disk fragmentation, and the amount of RAM available on the system can all have a significant impact on overall I/O efficiency. For critical applications, the entire hardware and software system should be reviewed to identify any potential I/O bottlenecks. \appendix \chapter{Index of Routines } \begin{tabular}{lr} fits\_add\_group\_member & \pageref{ffgtam} \\ fits\_ascii\_tform & \pageref{ffasfm} \\ fits\_binary\_tform & \pageref{ffbnfm} \\ fits\_calculator & \pageref{ffcalc} \\ fits\_calculator\_rng & \pageref{ffcalcrng} \\ fits\_calc\_binning[d] & \pageref{calcbinning} \\ fits\_calc\_rows & \pageref{ffcrow} \\ fits\_change\_group & \pageref{ffgtch} \\ fits\_cleanup\_https & \pageref{ffihtps} \\ fits\_clear\_errmark & \pageref{ffpmrk} \\ fits\_clear\_errmsg & \pageref{ffcmsg} \\ fits\_close\_file & \pageref{ffclos} \\ fits\_compact\_group & \pageref{ffgtcm} \\ fits\_compare\_str & \pageref{ffcmps} \\ fits\_compress\_heap & \pageref{ffcmph} \\ fits\_convert\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ fits\_copy\_cell2image & \pageref{copycell} \\ fits\_copy\_col & \pageref{ffcpcl} \\ fits\_copy\_cols & \pageref{ffccls} \\ fits\_copy\_data & \pageref{ffcpdt} \\ fits\_copy\_file & \pageref{ffcpfl} \\ fits\_copy\_group & \pageref{ffgtcp} \\ fits\_copy\_hdu & \pageref{ffcopy} \\ fits\_copy\_hdutab & \pageref{ffcpht} \\ fits\_copy\_header & \pageref{ffcphd} \\ fits\_copy\_image2cell & \pageref{copycell} \\ fits\_copy\_image\_section & \pageref{ffcpimg} \\ fits\_copy\_key & \pageref{ffcpky} \\ fits\_copy\_member & \pageref{ffgmcp} \\ fits\_copy\_pixlist2image & \pageref{copypixlist2image} \\ fits\_copy\_rows & \pageref{ffcprw} \\ fits\_copy\_selrows & \pageref{ffcpsr} \\ fits\_create\_diskfile & \pageref{ffinit} \\ fits\_create\_file & \pageref{ffinit} \\ \end{tabular} \begin{tabular}{lr} fits\_create\_group & \pageref{ffgtcr} \\ fits\_create\_hdu & \pageref{ffcrhd} \\ fits\_create\_img & \pageref{ffcrim} \\ fits\_create\_memfile & \pageref{ffimem} \\ fits\_create\_tbl & \pageref{ffcrtb} \\ fits\_create\_template & \pageref{fftplt} \\ fits\_date2str & \pageref{ffdt2s} \\ fits\_decode\_chksum & \pageref{ffdsum} \\ fits\_decode\_tdim & \pageref{ffdtdm} \\ fits\_delete\_col & \pageref{ffdcol} \\ fits\_delete\_file & \pageref{ffdelt} \\ fits\_delete\_hdu & \pageref{ffdhdu} \\ fits\_delete\_key & \pageref{ffdkey} \\ fits\_delete\_record & \pageref{ffdrec} \\ fits\_delete\_rowlist & \pageref{ffdrws} \\ fits\_delete\_rowrange & \pageref{ffdrrg} \\ fits\_delete\_rows & \pageref{ffdrow} \\ fits\_delete\_str & \pageref{ffdkey} \\ fits\_encode\_chksum & \pageref{ffesum} \\ fits\_file\_exists & \pageref{ffexist} \\ fits\_file\_mode & \pageref{ffflmd} \\ fits\_file\_name & \pageref{ffflnm} \\ fits\_find\_first\_row & \pageref{ffffrw} \\ fits\_find\_nextkey & \pageref{ffgnxk} \\ fits\_find\_rows & \pageref{fffrow} \\ fits\_flush\_buffer & \pageref{ffflus} \\ fits\_flush\_file & \pageref{ffflus} \\ fits\_free\_memory & \pageref{ffgkls}, \pageref{ffhdr2str} \\ fits\_get\_acolparms & \pageref{ffgacl} \\ fits\_get\_bcolparms & \pageref{ffgbcl} \\ fits\_get\_chksum & \pageref{ffgcks} \\ fits\_get\_col\_display\_width & \pageref{ffgcdw} \\ \end{tabular} \begin{tabular}{lr} fits\_get\_colname & \pageref{ffgcnn} \\ fits\_get\_colnum & \pageref{ffgcno} \\ fits\_get\_coltype & \pageref{ffgtcl} \\ fits\_get\_compression\_type & \pageref{ffgetcomp} \\ fits\_get\_eqcoltype & \pageref{ffgtcl} \\ fits\_get\_errstatus & \pageref{ffgerr} \\ fits\_get\_hdrpos & \pageref{ffghps} \\ fits\_get\_hdrspace & \pageref{ffghsp} \\ fits\_get\_hdu\_num & \pageref{ffghdn} \\ fits\_get\_hdu\_type & \pageref{ffghdt} \\ fits\_get\_hduaddr & \pageref{ffghad} \\ fits\_get\_hduaddrll & \pageref{ffghad} \\ fits\_get\_img\_dim & \pageref{ffgidm} \\ fits\_get\_img\_equivtype & \pageref{ffgidt} \\ fits\_get\_img\_param & \pageref{ffgipr} \\ fits\_get\_img\_size & \pageref{ffgisz} \\ fits\_get\_img\_type & \pageref{ffgidt} \\ fits\_get\_inttype & \pageref{ffinttyp} \\ fits\_get\_key\_com\_strlen & \pageref{ffgkcsl} \\ fits\_get\_key\_strlen & \pageref{ffgksl} \\ fits\_get\_keyclass & \pageref{ffgkcl} \\ fits\_get\_keyname & \pageref{ffgknm} \\ fits\_get\_keytype & \pageref{ffdtyp} \\ fits\_get\_noise\_bits & \pageref{ffgetcomp} \\ fits\_get\_num\_cols & \pageref{ffgnrw} \\ fits\_get\_num\_groups & \pageref{ffgmng} \\ fits\_get\_num\_hdus & \pageref{ffthdu} \\ fits\_get\_num\_members & \pageref{ffgtnm} \\ fits\_get\_num\_rows & \pageref{ffgnrw} \\ fits\_get\_rowsize & \pageref{ffgrsz} \\ fits\_get\_system\_time & \pageref{ffdt2s} \\ fits\_get\_tbcol & \pageref{ffgabc} \\ fits\_get\_tile\_dim & \pageref{ffgetcomp} \\ \end{tabular} \newpage \begin{tabular}{lr} fits\_get\_timeout & \pageref{ffgtmo} \\ fits\_get\_version & \pageref{ffvers} \\ fits\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ fits\_init\_https & \pageref{ffihtps} \\ fits\_insert\_atbl & \pageref{ffitab} \\ fits\_insert\_btbl & \pageref{ffibin} \\ fits\_insert\_col & \pageref{fficol} \\ fits\_insert\_cols & \pageref{fficls} \\ fits\_insert\_group & \pageref{ffgtis} \\ fits\_insert\_img & \pageref{ffiimg} \\ fits\_insert\_key\_null & \pageref{ffikyu} \\ fits\_insert\_key\_TYP & \pageref{ffikyx} \\ fits\_insert\_record & \pageref{ffirec} \\ fits\_insert\_rows & \pageref{ffirow} \\ fits\_is\_reentrant & \pageref{reentrant} \\ fits\_iterate\_data & \pageref{ffiter} \\ fits\_make\_hist[d] & \pageref{makehist} \\ fits\_make\_key & \pageref{ffmkky} \\ fits\_make\_keyn & \pageref{ffkeyn} \\ fits\_make\_nkey & \pageref{ffnkey} \\ fits\_merge\_groups & \pageref{ffgtmg} \\ fits\_modify\_card & \pageref{ffmcrd} \\ fits\_modify\_comment & \pageref{ffmcom} \\ fits\_modify\_key\_null & \pageref{ffmkyu} \\ fits\_modify\_key\_TYP & \pageref{ffmkyx} \\ fits\_modify\_name & \pageref{ffmnam} \\ fits\_modify\_record & \pageref{ffmrec} \\ fits\_modify\_vector\_len & \pageref{ffmvec} \\ fits\_movabs\_hdu & \pageref{ffmahd} \\ fits\_movnam\_hdu & \pageref{ffmnhd} \\ fits\_movrel\_hdu & \pageref{ffmrhd} \\ fits\_null\_check & \pageref{ffnchk} \\ fits\_open\_data & \pageref{ffopen} \\ fits\_open\_diskfile & \pageref{ffopen} \\ fits\_open\_extlist & \pageref{ffopen} \\ fits\_open\_file & \pageref{ffopen} \\ fits\_open\_image & \pageref{ffopen} \\ fits\_open\_table & \pageref{ffopen} \\ fits\_open\_group & \pageref{ffgtop} \\ fits\_open\_member & \pageref{ffgmop} \\ fits\_open\_memfile & \pageref{ffomem} \\ fits\_parse\_extnum & \pageref{ffextn} \\ fits\_parse\_input\_filename & \pageref{ffiurl} \\ fits\_parse\_input\_url & \pageref{ffiurl} \\ fits\_parse\_range & \pageref{ffrwrg} \\ fits\_parse\_rootname & \pageref{ffrtnm} \\ fits\_parse\_template & \pageref{ffgthd} \\ fits\_parse\_value & \pageref{ffpsvc} \\ \end{tabular} \begin{tabular}{lr} fits\_pix\_to\_world & \pageref{ffwldp} \\ fits\_read\_2d\_TYP & \pageref{ffg2dx} \\ fits\_read\_3d\_TYP & \pageref{ffg3dx} \\ fits\_read\_atblhdr & \pageref{ffghtb} \\ fits\_read\_btblhdr & \pageref{ffghbn} \\ fits\_read\_card & \pageref{ffgcrd} \\ fits\_read\_col & \pageref{ffgcv} \\ fits\_read\_col\_bit\_ & \pageref{ffgcx} \\ fits\_read\_col\_TYP & \pageref{ffgcvx} \\ fits\_read\_colnull & \pageref{ffgcf} \\ fits\_read\_colnull\_TYP & \pageref{ffgcfx} \\ fits\_read\_cols & \pageref{ffgcvn} \\ fits\_read\_descript & \pageref{ffgdes} \\ fits\_read\_descripts & \pageref{ffgdes} \\ fits\_read\_errmsg & \pageref{ffgmsg} \\ fits\_read\_ext & \pageref{ffgextn} \\ fits\_read\_grppar\_TYP & \pageref{ffggpx} \\ fits\_read\_img & \pageref{ffgpv} \\ fits\_read\_img\_coord & \pageref{ffgics} \\ fits\_read\_img\_TYP & \pageref{ffgpvx} \\ fits\_read\_imghdr & \pageref{ffghpr} \\ fits\_read\_imgnull & \pageref{ffgpf} \\ fits\_read\_imgnull\_TYP & \pageref{ffgpfx} \\ fits\_read\_key & \pageref{ffgky} \\ fits\_read\_key\_longstr & \pageref{ffgkls} \\ fits\_read\_key\_triple & \pageref{ffgkyt} \\ fits\_read\_key\_unit & \pageref{ffgunt} \\ fits\_read\_key\_TYP & \pageref{ffgkyx} \\ fits\_read\_keyn & \pageref{ffgkyn} \\ fits\_read\_keys\_TYP & \pageref{ffgknx} \\ fits\_read\_keyword & \pageref{ffgkey} \\ fits\_read\_pix & \pageref{ffgpxv} \\ fits\_read\_pixnull & \pageref{ffgpxf} \\ fits\_read\_record & \pageref{ffgrec} \\ fits\_read\_str & \pageref{ffgcrd} \\ fits\_read\_string\_key & \pageref{ffgsky} \\ fits\_read\_string\_key\_com & \pageref{ffgskyc} \\ fits\_read\_subset & \pageref{ffgsv} \\ fits\_read\_subset\_TYP & \pageref{ffgsvx} \pageref{ffgsvx2}\\ fits\_read\_subsetnull\_TYP & \pageref{ffgsfx} \pageref{ffgsfx2} \\ fits\_read\_tbl\_coord & \pageref{ffgtcs} \\ fits\_read\_tblbytes & \pageref{ffgtbb} \\ fits\_read\_tdim & \pageref{ffgtdm} \\ fits\_read\_wcstab & \pageref{wcstab} \\ fits\_rebin\_wcs[d] & \pageref{rebinwcs} \\ fits\_remove\_group & \pageref{ffgtrm} \\ fits\_remove\_member & \pageref{ffgmrm} \\ fits\_reopen\_file & \pageref{ffreopen} \\ fits\_report\_error & \pageref{ffrprt} \\ fits\_resize\_img & \pageref{ffrsim} \\ \end{tabular} \begin{tabular}{lr} fits\_rms\_float & \pageref{imageRMS} \\ fits\_rms\_short & \pageref{imageRMS} \\ fits\_select\_rows & \pageref{ffsrow} \\ fits\_set\_atblnull & \pageref{ffsnul} \\ fits\_set\_bscale & \pageref{ffpscl} \\ fits\_set\_btblnull & \pageref{fftnul} \\ fits\_set\_compression\_type & \pageref{ffsetcomp} \\ fits\_set\_hdrsize & \pageref{ffhdef} \\ fits\_set\_hdustruc & \pageref{ffrdef} \\ fits\_set\_imgnull & \pageref{ffpnul} \\ fits\_set\_noise\_bits & \pageref{ffsetcomp} \\ fits\_set\_tile\_dim & \pageref{ffsetcomp} \\ fits\_set\_timeout & \pageref{ffgtmo} \\ fits\_set\_tscale & \pageref{fftscl} \\ fits\_show\_download\_progress & \pageref{ffshdwn} \\ fits\_split\_names & \pageref{splitnames} \\ fits\_str2date & \pageref{ffdt2s} \\ fits\_str2time & \pageref{ffdt2s} \\ fits\_test\_expr & \pageref{fftexp} \\ fits\_test\_heap & \pageref{fftheap} \\ fits\_test\_keyword & \pageref{fftkey} \\ fits\_test\_record & \pageref{fftrec} \\ fits\_time2str & \pageref{ffdt2s} \\ fits\_transfer\_member & \pageref{ffgmtf} \\ fits\_translate\_keyword & \pageref{translatekey} \\ fits\_update\_card & \pageref{ffucrd} \\ fits\_update\_chksum & \pageref{ffupck} \\ fits\_update\_key & \pageref{ffuky} \\ fits\_update\_key\_longstr & \pageref{ffukyx} \\ fits\_update\_key\_null & \pageref{ffukyu} \\ fits\_update\_key\_TYP & \pageref{ffukyx} \\ fits\_uppercase & \pageref{ffupch} \\ fits\_url\_type & \pageref{ffurlt} \\ fits\_verbose\_https & \pageref{ffvhtps} \\ fits\_verify\_chksum & \pageref{ffvcks} \\ fits\_verify\_group & \pageref{ffgtvf} \\ fits\_world\_to\_pix & \pageref{ffxypx} \\ fits\_write\_2d\_TYP & \pageref{ffp2dx} \\ fits\_write\_3d\_TYP & \pageref{ffp3dx} \\ fits\_write\_atblhdr & \pageref{ffphtb} \\ fits\_write\_btblhdr & \pageref{ffphbn} \\ fits\_write\_chksum & \pageref{ffpcks} \\ fits\_write\_col & \pageref{ffpcl} \\ fits\_write\_col\_bit & \pageref{ffpclx} \\ fits\_write\_col\_TYP & \pageref{ffpcls} \\ fits\_write\_col\_null & \pageref{ffpclu} \\ fits\_write\_colnull & \pageref{ffpcn} \\ fits\_write\_colnull\_TYP & \pageref{ffpcnx} \\ fits\_write\_cols & \pageref{ffpcln} \\ \end{tabular} \newpage \begin{tabular}{lr} fits\_write\_comment & \pageref{ffpcom} \\ fits\_write\_date & \pageref{ffpdat} \\ fits\_write\_descript & \pageref{ffpdes} \\ fits\_write\_errmark & \pageref{ffpmrk} \\ fits\_write\_errmsg & \pageref{ffpmsg} \\ fits\_write\_ext & \pageref{ffgextn} \\ fits\_write\_exthdr & \pageref{ffphps} \\ fits\_write\_grphdr & \pageref{ffphpr} \\ fits\_write\_grppar\_TYP & \pageref{ffpgpx} \\ fits\_write\_hdu & \pageref{ffwrhdu} \\ fits\_write\_history & \pageref{ffphis} \\ fits\_write\_img & \pageref{ffppr} \\ fits\_write\_img\_null & \pageref{ffppru} \\ fits\_write\_img\_TYP & \pageref{ffpprx} \\ fits\_write\_imghdr & \pageref{ffphps} \\ fits\_write\_imgnull & \pageref{ffppn} \\ fits\_write\_imgnull\_TYP & \pageref{ffppnx} \\ fits\_write\_key & \pageref{ffpky} \\ fits\_write\_key\_longstr & \pageref{ffpkls} \\ fits\_write\_key\_longwarn & \pageref{ffplsw} \\ fits\_write\_key\_null & \pageref{ffpkyu} \\ fits\_write\_key\_template & \pageref{ffpktp} \\ fits\_write\_key\_triple & \pageref{ffpkyt} \\ fits\_write\_key\_unit & \pageref{ffpunt} \\ fits\_write\_key\_TYP & \pageref{ffpkyx} \\ fits\_write\_keys\_TYP & \pageref{ffpknx} \\ fits\_write\_keys\_histo & \pageref{writekeyshisto} \\ fits\_write\_null\_img & \pageref{ffpprn} \\ fits\_write\_nullrows & \pageref{ffpclu} \\ fits\_write\_pix & \pageref{ffppx} \\ fits\_write\_pixnull & \pageref{ffppxn} \\ fits\_write\_record & \pageref{ffprec} \\ fits\_write\_subset & \pageref{ffpss} \\ fits\_write\_subset\_TYP & \pageref{ffpssx} \\ fits\_write\_tblbytes & \pageref{ffptbb} \\ fits\_write\_tdim & \pageref{ffptdm} \\ fits\_write\_theap & \pageref{ffpthp} \\ \end{tabular} \newpage \begin{tabular}{lr} ffasfm & \pageref{ffasfm} \\ ffbnfm & \pageref{ffbnfm} \\ ffcalc & \pageref{ffcalc} \\ ffcalc\_rng & \pageref{ffcalcrng} \\ ffccls & \pageref{ffccls} \\ ffchtps & \pageref{ffchtps} \\ ffclos & \pageref{ffclos} \\ ffcmph & \pageref{ffcmph} \\ ffcmps & \pageref{ffcmps} \\ ffcmrk & \pageref{ffpmrk} \\ ffcmsg & \pageref{ffcmsg} \\ ffcopy & \pageref{ffcopy} \\ ffcpcl & \pageref{ffcpcl} \\ ffcpdt & \pageref{ffcpdt} \\ ffcpfl & \pageref{ffcpfl} \\ ffcphd & \pageref{ffcphd} \\ ffcpht & \pageref{ffcpht} \\ ffcpimg & \pageref{ffcpimg} \\ ffcpky & \pageref{ffcpky} \\ ffcprw & \pageref{ffcprw} \\ ffcpsr & \pageref{ffcpsr} \\ ffcrhd & \pageref{ffcrhd} \\ ffcrim & \pageref{ffcrim} \\ ffcrow & \pageref{ffcrow} \\ ffcrtb & \pageref{ffcrtb} \\ ffdcol & \pageref{ffdcol} \\ ffdelt & \pageref{ffdelt} \\ ffdhdu & \pageref{ffdhdu} \\ ffdkey & \pageref{ffdkey} \\ ffdkinit & \pageref{ffinit} \\ ffdkopn & \pageref{ffopen} \\ ffdopn & \pageref{ffopen} \\ ffdrec & \pageref{ffdrec} \\ ffdrow & \pageref{ffdrow} \\ ffdrrg & \pageref{ffdrrg} \\ ffdrws & \pageref{ffdrws} \\ ffdstr & \pageref{ffdkey} \\ ffdsum & \pageref{ffdsum} \\ ffdt2s & \pageref{ffdt2s} \\ ffdtdm & \pageref{ffdtdm} \\ ffdtyp & \pageref{ffdtyp} \\ ffeopn & \pageref{ffopen} \\ ffeqty & \pageref{ffgtcl} \\ ffesum & \pageref{ffesum} \\ ffexest & \pageref{ffexist} \\ ffextn & \pageref{ffextn} \\ ffffrw & \pageref{ffffrw} \\ ffflmd & \pageref{ffflmd} \\ ffflnm & \pageref{ffflnm} \\ ffflsh & \pageref{ffflus} \\ \end{tabular} \begin{tabular}{lr} ffflus & \pageref{ffflus} \\ fffree & \pageref{ffgkls}, \pageref{ffhdr2str} \\ fffrow & \pageref{fffrow} \\ ffg2d\_ & \pageref{ffg2dx} \\ ffg3d\_ & \pageref{ffg3dx} \\ ffgabc & \pageref{ffgabc} \\ ffgacl & \pageref{ffgacl} \\ ffgbcl & \pageref{ffgbcl} \\ ffgcdw & \pageref{ffgcdw} \\ ffgcf & \pageref{ffgcf} \\ ffgcf\_ & \pageref{ffgcfx} \\ ffgcks & \pageref{ffgcks} \\ ffgcnn & \pageref{ffgcnn} \\ ffgcno & \pageref{ffgcno} \\ ffgcrd & \pageref{ffgcrd} \\ ffgcv & \pageref{ffgcv} \\ ffgcv\_ & \pageref{ffgcvx} \\ ffgcvn & \pageref{ffgcvn} \\ ffgcx & \pageref{ffgcx} \\ ffgdes & \pageref{ffgdes} \\ ffgdess & \pageref{ffgdes} \\ ffgerr & \pageref{ffgerr} \\ ffgextn & \pageref{ffgextn} \\ ffggp\_ & \pageref{ffggpx} \\ ffghad & \pageref{ffghad} \\ ffghbn & \pageref{ffghbn} \\ ffghdn & \pageref{ffghdn} \\ ffghdt & \pageref{ffghdt} \\ ffghpr & \pageref{ffghpr} \\ ffghps & \pageref{ffghps} \\ ffghsp & \pageref{ffghsp} \\ ffghtb & \pageref{ffghtb} \\ ffgics & \pageref{ffgics} \\ ffgidm & \pageref{ffgidm} \\ ffgidt & \pageref{ffgidt} \\ ffgiet & \pageref{ffgidt} \\ ffgipr & \pageref{ffgipr} \\ ffgisz & \pageref{ffgisz} \\ ffgkcl & \pageref{ffgkcl} \\ ffgkcsl & \pageref{ffgkcsl} \\ ffgkey & \pageref{ffgkey} \\ ffgkls & \pageref{ffgkls} \\ ffgksl & \pageref{ffgksl} \\ ffgkn\_ & \pageref{ffgknx} \\ ffgknm & \pageref{ffgknm} \\ ffgky & \pageref{ffgky} \\ ffgkyn & \pageref{ffgkyn} \\ ffgkyt & \pageref{ffgkyt} \\ ffgky\_ & \pageref{ffgkyx} \\ ffgmcp & \pageref{ffgmcp} \\ \end{tabular} \begin{tabular}{lr} ffgmng & \pageref{ffgmng} \\ ffgmop & \pageref{ffgmop} \\ ffgmrm & \pageref{ffgmrm} \\ ffgmsg & \pageref{ffgmsg} \\ ffgmtf & \pageref{ffgmtf} \\ ffgncl & \pageref{ffgnrw} \\ ffgnrw & \pageref{ffgnrw} \\ ffgnxk & \pageref{ffgnxk} \\ ffgpf & \pageref{ffgpf} \\ ffgpf\_ & \pageref{ffgpfx} \\ ffgpv & \pageref{ffgpv} \\ ffgpv\_ & \pageref{ffgpvx} \\ ffgpxv & \pageref{ffgpxv} \\ ffgpxf & \pageref{ffgpxf} \\ ffgrec & \pageref{ffgrec} \\ ffgrsz & \pageref{ffgrsz} \\ ffgsdt & \pageref{ffdt2s} \\ ffgsf\_ & \pageref{ffgsfx} \pageref{ffgsfx2} \\ ffgsky & \pageref{ffgsky} \\ ffgskyc & \pageref{ffgskyc} \\ ffgstm & \pageref{ffdt2s} \\ ffgstr & \pageref{ffgcrd} \\ ffgsv & \pageref{ffgsv} \\ ffgsv\_ & \pageref{ffgsvx} \pageref{ffgsvx2}\\ ffgtam & \pageref{ffgtam} \\ ffgtbb & \pageref{ffgtbb} \\ ffgtch & \pageref{ffgtch} \\ ffgtcl & \pageref{ffgtcl} \\ ffgtcm & \pageref{ffgtcm} \\ ffgtcp & \pageref{ffgtcp} \\ ffgtcr & \pageref{ffgtcr} \\ ffgtcs & \pageref{ffgtcs} \\ ffgtdm & \pageref{ffgtdm} \\ ffgthd & \pageref{ffgthd} \\ ffgtis & \pageref{ffgtis} \\ ffgtmg & \pageref{ffgtmg} \\ ffgtmo & \pageref{ffgtmo} \\ ffgtnm & \pageref{ffgtnm} \\ ffgtop & \pageref{ffgtop} \\ ffgtrm & \pageref{ffgtrm} \\ ffgtvf & \pageref{ffgtvf} \\ ffgunt & \pageref{ffgunt} \\ ffhdef & \pageref{ffhdef} \\ ffibin & \pageref{ffibin} \\ fficls & \pageref{fficls} \\ fficol & \pageref{fficol} \\ ffifile & \pageref{ffiurl} \\ ffihtps & \pageref{ffihtps} \\ ffiimg & \pageref{ffiimg} \\ \end{tabular} \begin{tabular}{lr} ffikls & \pageref{ffikyx} \\ ffikyu & \pageref{ffikyu} \\ ffiky\_ & \pageref{ffikyx} \\ ffimem & \pageref{ffimem} \\ ffinit & \pageref{ffinit} \\ ffinttyp & \pageref{ffinttyp} \\ ffiopn & \pageref{ffopen} \\ ffirec & \pageref{ffirec} \\ ffirow & \pageref{ffirow} \\ ffitab & \pageref{ffitab} \\ ffiter & \pageref{ffiter} \\ ffiurl & \pageref{ffiurl} \\ ffkeyn & \pageref{ffkeyn} \\ ffmahd & \pageref{ffmahd} \\ ffmcom & \pageref{ffmcom} \\ ffmcrd & \pageref{ffmcrd} \\ ffmkky & \pageref{ffmkky} \\ ffmkls & \pageref{ffmkyx} \\ ffmkyu & \pageref{ffmkyu} \\ ffmky\_ & \pageref{ffmkyx} \\ ffmnam & \pageref{ffmnam} \\ ffmnhd & \pageref{ffmnhd} \\ ffmrec & \pageref{ffmrec} \\ ffmrhd & \pageref{ffmrhd} \\ ffmvec & \pageref{ffmvec} \\ ffnchk & \pageref{ffnchk} \\ ffnkey & \pageref{ffnkey} \\ ffomem & \pageref{ffomem} \\ ffopen & \pageref{ffopen} \\ ffp2d\_ & \pageref{ffp2dx} \\ ffp3d\_ & \pageref{ffp3dx} \\ ffpcks & \pageref{ffpcks} \\ ffpcl & \pageref{ffpcl} \\ ffpcln & \pageref{ffpcln} \\ ffpcls & \pageref{ffpcls} \\ ffpcl\_ & \pageref{ffpclx} \\ ffpclu & \pageref{ffpclu} \\ ffpcn & \pageref{ffpcn} \\ ffpcn\_ & \pageref{ffpcnx} \\ ffpcom & \pageref{ffpcom} \\ ffpdat & \pageref{ffpdat} \\ ffpdes & \pageref{ffpdes} \\ ffpextn & \pageref{ffgextn} \\ ffpgp\_ & \pageref{ffpgpx} \\ ffphbn & \pageref{ffphbn} \\ ffphext & \pageref{ffphpr} \\ ffphis & \pageref{ffphis} \\ ffphpr & \pageref{ffphpr} \\ ffphps & \pageref{ffphps} \\ \end{tabular} \begin{tabular}{lr} ffphtb & \pageref{ffphtb} \\ ffpkls & \pageref{ffpkls} \\ ffpkn\_ & \pageref{ffpknx} \\ ffpktp & \pageref{ffpktp} \\ ffpky & \pageref{ffpky} \\ ffpkyt & \pageref{ffpkyt} \\ ffpkyu & \pageref{ffpkyu} \\ ffpky\_ & \pageref{ffpkyx} \\ ffplsw & \pageref{ffplsw} \\ ffpmrk & \pageref{ffpmrk} \\ ffpmsg & \pageref{ffpmsg} \\ ffpnul & \pageref{ffpnul} \\ ffppn & \pageref{ffppn} \\ ffppn\_ & \pageref{ffppnx} \\ ffppr & \pageref{ffppr} \\ ffpprn & \pageref{ffpprn} \\ ffppru & \pageref{ffppru} \\ ffppr\_ & \pageref{ffpprx} \\ ffppx & \pageref{ffppx} \\ ffppxn & \pageref{ffppxn} \\ ffprec & \pageref{ffprec} \\ ffprwu & \pageref{ffpclu} \\ ffpscl & \pageref{ffpscl} \\ ffpss & \pageref{ffpss} \\ ffpss\_ & \pageref{ffpssx} \\ ffpsvc & \pageref{ffpsvc} \\ ffptbb & \pageref{ffptbb} \\ ffptdm & \pageref{ffptdm} \\ ffpthp & \pageref{ffpthp} \\ ffpunt & \pageref{ffpunt} \\ ffrdef & \pageref{ffrdef} \\ ffreopen & \pageref{ffreopen} \\ ffrprt & \pageref{ffrprt} \\ ffrsim & \pageref{ffrsim} \\ ffrtnm & \pageref{ffrtnm} \\ ffrwrg & \pageref{ffrwrg} \\ ffs2dt & \pageref{ffdt2s} \\ ffs2tm & \pageref{ffdt2s} \\ ffshdwn & \pageref{ffshdwn} \\ ffsnul & \pageref{ffsnul} \\ ffsrow & \pageref{ffsrow} \\ ffstmo & \pageref{ffgtmo} \\ fftexp & \pageref{fftexp} \\ ffthdu & \pageref{ffthdu} \\ fftheap & \pageref{fftheap} \\ fftkey & \pageref{fftkey} \\ fftm2s & \pageref{ffdt2s} \\ fftnul & \pageref{fftnul} \\ \end{tabular} \newpage \begin{tabular}{lr} fftopn & \pageref{ffopen} \\ fftplt & \pageref{fftplt} \\ fftrec & \pageref{fftrec} \\ fftscl & \pageref{fftscl} \\ ffucrd & \pageref{ffucrd} \\ ffukls & \pageref{ffukyx} \\ ffuky & \pageref{ffuky} \\ ffukyu & \pageref{ffukyu} \\ ffuky\_ & \pageref{ffukyx} \\ ffupch & \pageref{ffupch} \\ ffupck & \pageref{ffupck} \\ ffurlt & \pageref{ffurlt} \\ ffvcks & \pageref{ffvcks} \\ ffvers & \pageref{ffvers} \\ ffvhtps & \pageref{ffvhtps} \\ ffwldp & \pageref{ffwldp} \\ ffwrhdu & \pageref{ffwrhdu} \\ ffxypx & \pageref{ffxypx} \\ \end{tabular} \chapter{Parameter Definitions } \begin{verbatim} anynul - set to TRUE (=1) if any returned values are undefined, else FALSE array - array of numerical data values to read or write ascii - encoded checksum string binspec - the input table binning specifier bitpix - bits per pixel. The following symbolic mnemonics are predefined: BYTE_IMG = 8 (unsigned char) SHORT_IMG = 16 (signed short integer) LONG_IMG = 32 (signed long integer) LONGLONG_IMG = 64 (signed long 64-bit integer) FLOAT_IMG = -32 (float) DOUBLE_IMG = -64 (double). Two additional values, USHORT_IMG and ULONG_IMG are also available for creating unsigned integer images. These are equivalent to creating a signed integer image with BZERO offset keyword values of 32768 or 2147483648, respectively, which is the convention that FITS uses to store unsigned integers. card - header record to be read or written (80 char max, null-terminated) casesen - CASESEN (=1) for case-sensitive string matching, else CASEINSEN (=0) cmopt - grouping table "compact" option parameter. Allowed values are: OPT_CMT_MBR and OPT_CMT_MBR_DEL. colname - name of the column (null-terminated) colnum - column number (first column = 1) colspec - the input file column specification; used to delete, create, or rename table columns comment - the keyword comment field (72 char max, null-terminated) complm - should the checksum be complemented? comptype - compression algorithm to use: GZIP_1, RICE_1, HCOMPRESS_1, or PLIO_1 coordtype- type of coordinate projection (-SIN, -TAN, -ARC, -NCP, -GLS, -MER, or -AIT) cpopt - grouping table copy option parameter. Allowed values are: OPT_GCP_GPT, OPT_GCP_MBR, OPT_GCP_ALL, OPT_MCP_ADD, OPT_MCP_NADD, OPT_MCP_REPL, amd OPT_MCP_MOV. create_col- If TRUE, then insert a new column in the table, otherwise overwrite the existing column. current - if TRUE, then the current HDU will be copied dataok - was the data unit verification successful (=1) or not (= -1). Equals zero if the DATASUM keyword is not present. datasum - 32-bit 1's complement checksum for the data unit dataend - address (in bytes) of the end of the HDU datastart- address (in bytes) of the start of the data unit datatype - specifies the data type of the value. Allowed value are: TSTRING, TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX datestr - FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', or 'dd/mm/yy' day - calendar day (UTC) (1-31) decimals - number of decimal places to be displayed deltasize - increment for allocating more memory dim1 - declared size of the first dimension of the image or cube array dim2 - declared size of the second dimension of the data cube array dispwidth - display width of a column = length of string that will be read dtype - data type of the keyword ('C', 'L', 'I', 'F' or 'X') C = character string L = logical I = integer F = floating point number X = complex, e.g., "(1.23, -4.56)" err_msg - error message on the internal stack (80 chars max) err_text - error message string corresponding to error number (30 chars max) exact - TRUE (=1) if the strings match exactly; FALSE (=0) if wildcards are used exclist - array of pointers to keyword names to be excluded from search exists - flag indicating whether the file or compressed file exists on disk expr - boolean or arithmetic expression extend - TRUE (=1) if FITS file may have extensions, else FALSE (=0) extname - value of the EXTNAME keyword (null-terminated) extspec - the extension or HDU specifier; a number or name, version, and type extver - value of the EXTVER keyword = integer version number filename - full name of the FITS file, including optional HDU and filtering specs filetype - type of file (file://, ftp://, http://, etc.) filter - the input file filtering specifier firstchar- starting byte in the row (first byte of row = 1) firstfailed - member HDU ID (if positive) or grouping table GRPIDn index value (if negative) that failed grouping table verification. firstelem- first element in a vector (ignored for ASCII tables) firstrow - starting row number (first row of table = 1) following- if TRUE, any HDUs following the current HDU will be copied fpixel - coordinate of the first pixel to be read or written in the FITS array. The array must be of length NAXIS and have values such that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, etc. fptr - pointer to a 'fitsfile' structure describing the FITS file. frac - factional part of the keyword value gcount - number of groups in the primary array (usually = 1) gfptr - fitsfile* pointer to a grouping table HDU. group - GRPIDn/GRPLCn index value identifying a grouping table HDU, or data group number (=0 for non-grouped data) grouptype - Grouping table parameter that specifies the columns to be created in a grouping table HDU. Allowed values are: GT_ID_ALL_URI, GT_ID_REF, GT_ID_POS, GT_ID_ALL, GT_ID_REF_URI, and GT_ID_POS_URI. grpname - value to use for the GRPNAME keyword value. hdunum - sequence number of the HDU (Primary array = 1) hduok - was the HDU verification successful (=1) or not (= -1). Equals zero if the CHECKSUM keyword is not present. hdusum - 32 bit 1's complement checksum for the entire CHDU hdutype - HDU type: IMAGE_HDU (0), ASCII_TBL (1), BINARY_TBL (2), ANY_HDU (-1) header - returned character string containing all the keyword records headstart- starting address (in bytes) of the CHDU heapsize - size of the binary table heap, in bytes history - the HISTORY keyword comment string (70 char max, null-terminated) hour - hour within day (UTC) (0 - 23) inc - sampling interval for pixels in each FITS dimension inclist - array of pointers to matching keyword names incolnum - input column number; range = 1 to TFIELDS infile - the input filename, including path if specified infptr - pointer to a 'fitsfile' structure describing the input FITS file. intval - integer part of the keyword value iomode - file access mode: either READONLY (=0) or READWRITE (=1) keyname - name of a keyword (8 char max, null-terminated) keynum - position of keyword in header (1st keyword = 1) keyroot - root string for the keyword name (5 char max, null-terminated) keysexist- number of existing keyword records in the CHU keytype - header record type: -1=delete; 0=append or replace; 1=append; 2=this is the END keyword longstr - arbitrarily long string keyword value (null-terminated) lpixel - coordinate of the last pixel to be read or written in the FITS array. The array must be of length NAXIS and have values such that lpixel[0] is in the range 1 to NAXIS1, lpixel[1] is in the range 1 to NAXIS2, etc. match - TRUE (=1) if the 2 strings match, else FALSE (=0) maxdim - maximum number of values to return member - row number of a grouping table member HDU. memptr - pointer to the a FITS file in memory mem_realloc - pointer to a function for reallocating more memory memsize - size of the memory block allocated for the FITS file mfptr - fitsfile* pointer to a grouping table member HDU. mgopt - grouping table merge option parameter. Allowed values are: OPT_MRG_COPY, and OPT_MRG_MOV. minute - minute within hour (UTC) (0 - 59) month - calendar month (UTC) (1 - 12) morekeys - space in the header for this many more keywords n_good_rows - number of rows evaluating to TRUE namelist - string containing a comma or space delimited list of names naxes - size of each dimension in the FITS array naxis - number of dimensions in the FITS array naxis1 - length of the X/first axis of the FITS array naxis2 - length of the Y/second axis of the FITS array naxis3 - length of the Z/third axis of the FITS array nbytes - number of bytes or characters to read or write nchars - number of characters to read or write nelements- number of data elements to read or write newfptr - returned pointer to the reopened file newveclen- new value for the column vector repeat parameter nexc - number of names in the exclusion list (may = 0) nfound - number of keywords found (highest keyword number) nkeys - number of keywords in the sequence ninc - number of names in the inclusion list nmembers - Number of grouping table members (NAXIS2 value). nmove - number of HDUs to move (+ or -), relative to current position nocomments - if equal to TRUE, then no commentary keywords will be copied noisebits- number of bits to ignore when compressing floating point images nrows - number of rows in the table nstart - first integer value nullarray- set to TRUE (=1) if corresponding data element is undefined nulval - numerical value to represent undefined pixels nulstr - character string used to represent undefined values in ASCII table numval - numerical data value, of the appropriate data type offset - byte offset in the heap or data unit to the first element of the vector openfptr - pointer to a currently open FITS file overlap - number of bytes in the binary table heap pointed to by more than 1 descriptor outcolnum- output column number; range = 1 to TFIELDS + 1 outfile - and optional output filename; the input file will be copied to this prior to opening the file outfptr - pointer to a 'fitsfile' structure describing the output FITS file. pcount - value of the PCOUNT keyword = size of binary table heap previous - if TRUE, any previous HDUs in the input file will be copied. repeat - length of column vector (e.g. 12J); == 1 for ASCII table rmopt - grouping table remove option parameter. Allowed values are: OPT_RM_GPT, OPT_RM_ENTRY, OPT_RM_MBR, and OPT_RM_ALL. rootname - root filename, minus any extension or filtering specifications rot - celestial coordinate rotation angle (degrees) rowlen - length of a table row, in characters or bytes rowlist - sorted list of row numbers to be deleted from the table rownum - number of the row (first row = 1) rowrange - list of rows or row ranges: '3,6-8,12,56-80' or '500-' row_status - array of True/False results for each row that was evaluated scale - linear scaling factor; true value = (FITS value) * scale + zero second - second within minute (0 - 60.9999999999) (leap second!) section - section of image to be copied (e.g. 21:80,101:200) simple - TRUE (=1) if FITS file conforms to the Standard, else FALSE (=0) space - number of blank spaces to leave between ASCII table columns status - returned error status code (0 = OK) sum - 32 bit unsigned checksum value tbcol - byte position in row to start of column (1st col has tbcol = 1) tdisp - Fortran style display format for the table column tdimstr - the value of the TDIMn keyword templt - template string used in comparison (null-terminated) tfields - number of fields (columns) in the table tfopt - grouping table member transfer option parameter. Allowed values are: OPT_MCP_ADD, and OPT_MCP_MOV. tform - format of the column (null-terminated); allowed values are: ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd Binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count. Variable length array columns are denoted by a '1P' before the data type character (e.g., '1PJ'). When creating a binary table, 2 addition tform data type codes are recognized by CFITSIO: 'rU' and 'rV' for unsigned 16-bit and unsigned 32-bit integer, respectively. theap - zero indexed byte offset of starting address of the heap relative to the beginning of the binary table data tilesize - array of length NAXIS that specifies the dimensions of the image compression tiles ttype - label or name for table column (null-terminated) tunit - physical unit for table column (null-terminated) typechar - symbolic code of the table column data type typecode - data type code of the table column. The negative of the value indicates a variable length array column. Datatype typecode Mnemonic bit, X 1 TBIT byte, B 11 TBYTE logical, L 14 TLOGICAL ASCII character, A 16 TSTRING short integer, I 21 TSHORT integer, J 41 TINT32BIT (same as TLONG) long long integer, K 81 TLONGLONG real, E 42 TFLOAT double precision, D 82 TDOUBLE complex, C 83 TCOMPLEX double complex, M 163 TDBLCOMPLEX unit - the physical unit string (e.g., 'km/s') for a keyword unused - number of unused bytes in the binary table heap urltype - the file type of the FITS file (file://, ftp://, mem://, etc.) validheap- returned value = FALSE if any of the variable length array address are outside the valid range of addresses in the heap value - the keyword value string (70 char max, null-terminated) version - current version number of the CFITSIO library width - width of the character string field xcol - number of the column containing the X coordinate values xinc - X axis coordinate increment at reference pixel (deg) xpix - X axis pixel location xpos - X axis celestial coordinate (usually RA) (deg) xrefpix - X axis reference pixel array location xrefval - X axis coordinate value at the reference pixel (deg) ycol - number of the column containing the X coordinate values year - calendar year (e.g. 1999, 2000, etc) yinc - Y axis coordinate increment at reference pixel (deg) ypix - y axis pixel location ypos - y axis celestial coordinate (usually DEC) (deg) yrefpix - Y axis reference pixel array location yrefval - Y axis coordinate value at the reference pixel (deg) zero - scaling offset; true value = (FITS value) * scale + zero \end{verbatim} \chapter{CFITSIO Error Status Codes } The following table lists all the error status codes used by CFITSIO. Programmers are encouraged to use the symbolic mnemonics (defined in the file fitsio.h) rather than the actual integer status values to improve the readability of their code. \begin{verbatim} Symbolic Const Value Meaning -------------- ----- ----------------------------------------- 0 OK, no error SAME_FILE 101 input and output files are the same TOO_MANY_FILES 103 tried to open too many FITS files at once FILE_NOT_OPENED 104 could not open the named file FILE_NOT_CREATED 105 could not create the named file WRITE_ERROR 106 error writing to FITS file END_OF_FILE 107 tried to move past end of file READ_ERROR 108 error reading from FITS file FILE_NOT_CLOSED 110 could not close the file ARRAY_TOO_BIG 111 array dimensions exceed internal limit READONLY_FILE 112 Cannot write to readonly file MEMORY_ALLOCATION 113 Could not allocate memory BAD_FILEPTR 114 invalid fitsfile pointer NULL_INPUT_PTR 115 NULL input pointer to routine SEEK_ERROR 116 error seeking position in file BAD_NETTIMEOUT 117 bad value for file download timeout setting BAD_URL_PREFIX 121 invalid URL prefix on file name TOO_MANY_DRIVERS 122 tried to register too many IO drivers DRIVER_INIT_FAILED 123 driver initialization failed NO_MATCHING_DRIVER 124 matching driver is not registered URL_PARSE_ERROR 125 failed to parse input file URL RANGE_PARSE_ERROR 126 parse error in range list SHARED_BADARG 151 bad argument in shared memory driver SHARED_NULPTR 152 null pointer passed as an argument SHARED_TABFULL 153 no more free shared memory handles SHARED_NOTINIT 154 shared memory driver is not initialized SHARED_IPCERR 155 IPC error returned by a system call SHARED_NOMEM 156 no memory in shared memory driver SHARED_AGAIN 157 resource deadlock would occur SHARED_NOFILE 158 attempt to open/create lock file failed SHARED_NORESIZE 159 shared memory block cannot be resized at the moment HEADER_NOT_EMPTY 201 header already contains keywords KEY_NO_EXIST 202 keyword not found in header KEY_OUT_BOUNDS 203 keyword record number is out of bounds VALUE_UNDEFINED 204 keyword value field is blank NO_QUOTE 205 string is missing the closing quote BAD_INDEX_KEY 206 illegal indexed keyword name (e.g. 'TFORM1000') BAD_KEYCHAR 207 illegal character in keyword name or card BAD_ORDER 208 required keywords out of order NOT_POS_INT 209 keyword value is not a positive integer NO_END 210 couldn't find END keyword BAD_BITPIX 211 illegal BITPIX keyword value BAD_NAXIS 212 illegal NAXIS keyword value BAD_NAXES 213 illegal NAXISn keyword value BAD_PCOUNT 214 illegal PCOUNT keyword value BAD_GCOUNT 215 illegal GCOUNT keyword value BAD_TFIELDS 216 illegal TFIELDS keyword value NEG_WIDTH 217 negative table row size NEG_ROWS 218 negative number of rows in table COL_NOT_FOUND 219 column with this name not found in table BAD_SIMPLE 220 illegal value of SIMPLE keyword NO_SIMPLE 221 Primary array doesn't start with SIMPLE NO_BITPIX 222 Second keyword not BITPIX NO_NAXIS 223 Third keyword not NAXIS NO_NAXES 224 Couldn't find all the NAXISn keywords NO_XTENSION 225 HDU doesn't start with XTENSION keyword NOT_ATABLE 226 the CHDU is not an ASCII table extension NOT_BTABLE 227 the CHDU is not a binary table extension NO_PCOUNT 228 couldn't find PCOUNT keyword NO_GCOUNT 229 couldn't find GCOUNT keyword NO_TFIELDS 230 couldn't find TFIELDS keyword NO_TBCOL 231 couldn't find TBCOLn keyword NO_TFORM 232 couldn't find TFORMn keyword NOT_IMAGE 233 the CHDU is not an IMAGE extension BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength NOT_TABLE 235 the CHDU is not a table COL_TOO_WIDE 236 column is too wide to fit in table COL_NOT_UNIQUE 237 more than 1 column name matches template BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 UNKNOWN_EXT 251 unrecognizable FITS extension type UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION END_JUNK 253 END keyword is not blank BAD_HEADER_FILL 254 Header fill area contains non-blank chars BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) BAD_TFORM 261 illegal TFORM format code BAD_TFORM_DTYPE 262 unrecognizable TFORM data type code BAD_TDIM 263 illegal TDIMn keyword value BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range BAD_HDU_NUM 301 HDU number < 1 BAD_COL_NUM 302 column number < 1 or > tfields NEG_FILE_POS 304 tried to move to negative byte location in file NEG_BYTES 306 tried to read or write negative number of bytes BAD_ROW_NUM 307 illegal starting row number in table BAD_ELEM_NUM 308 illegal starting element number in vector NOT_ASCII_COL 309 this is not an ASCII string column NOT_LOGICAL_COL 310 this is not a logical data type column BAD_ATABLE_FORMAT 311 ASCII table column has wrong format BAD_BTABLE_FORMAT 312 Binary table column has wrong format NO_NULL 314 null value has not been defined NOT_VARI_LEN 317 this is not a variable length column BAD_DIMEN 320 illegal number of dimensions in array BAD_PIX_NUM 321 first pixel number greater than last pixel ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 NEG_AXIS 323 illegal axis length < 1 NOT_GROUP_TABLE 340 Grouping function error HDU_ALREADY_MEMBER 341 MEMBER_NOT_FOUND 342 GROUP_NOT_FOUND 343 BAD_GROUP_ID 344 TOO_MANY_HDUS_TRACKED 345 HDU_ALREADY_TRACKED 346 BAD_OPTION 347 IDENTICAL_POINTERS 348 BAD_GROUP_ATTACH 349 BAD_GROUP_DETACH 350 NGP_NO_MEMORY 360 malloc failed NGP_READ_ERR 361 read error from file NGP_NUL_PTR 362 null pointer passed as an argument. Passing null pointer as a name of template file raises this error NGP_EMPTY_CURLINE 363 line read seems to be empty (used internally) NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single line twice) NGP_INC_NESTING 365 too deep include file nesting (infinite loop, template includes itself ?) NGP_ERR_FOPEN 366 fopen() failed, cannot open template file NGP_EOF 367 end of file encountered and not expected NGP_BAD_ARG 368 bad arguments passed. Usually means internal parser error. Should not happen NGP_TOKEN_NOT_EXPECT 369 token not expected here BAD_I2C 401 bad int to formatted string conversion BAD_F2C 402 bad float to formatted string conversion BAD_INTKEY 403 can't interpret keyword value as integer BAD_LOGICALKEY 404 can't interpret keyword value as logical BAD_FLOATKEY 405 can't interpret keyword value as float BAD_DOUBLEKEY 406 can't interpret keyword value as double BAD_C2I 407 bad formatted string to int conversion BAD_C2F 408 bad formatted string to float conversion BAD_C2D 409 bad formatted string to double conversion BAD_DATATYPE 410 illegal datatype code value BAD_DECIM 411 bad number of decimal places specified NUM_OVERFLOW 412 overflow during data type conversion DATA_COMPRESSION_ERR 413 error compressing image DATA_DECOMPRESSION_ERR 414 error uncompressing image BAD_DATE 420 error in date or time conversion PARSE_SYNTAX_ERR 431 syntax error in parser expression PARSE_BAD_TYPE 432 expression did not evaluate to desired type PARSE_LRG_VECTOR 433 vector result too large to return in array PARSE_NO_OUTPUT 434 data parser failed not sent an out column PARSE_BAD_COL 435 bad data encounter while parsing column PARSE_BAD_OUTPUT 436 Output file not of proper type ANGLE_TOO_BIG 501 celestial angle too large for projection BAD_WCS_VAL 502 bad celestial coordinate or pixel value WCS_ERROR 503 error in celestial coordinate calculation BAD_WCS_PROJ 504 unsupported type of celestial projection NO_WCS_KEY 505 celestial coordinate keywords not found APPROX_WCS_KEY 506 approximate wcs keyword values were returned \end{verbatim} \end{document} cfitsio-4.3.1/docs/quick.toc0000644000225700000360000000340313472024437015226 0ustar cagordonlhea\contentsline {section}{\numberline {1}Introduction}{2} \contentsline {section}{\numberline {2}Installing and Using CFITSIO}{3} \contentsline {section}{\numberline {3}Example Programs}{4} \contentsline {section}{\numberline {4}CFITSIO Routines}{6} \contentsline {subsection}{\numberline {4.1}Error Reporting}{6} \contentsline {subsection}{\numberline {4.2}File Open/Close Routines}{6} \contentsline {subsection}{\numberline {4.3}HDU-level Routines}{7} \contentsline {subsection}{\numberline {4.4}Image I/O Routines}{9} \contentsline {subsection}{\numberline {4.5}Table I/O Routines}{12} \contentsline {subsection}{\numberline {4.6}Header Keyword I/O Routines}{19} \contentsline {subsection}{\numberline {4.7}Utility Routines}{22} \contentsline {section}{\numberline {5}CFITSIO File Names and Filters}{23} \contentsline {subsection}{\numberline {5.1}Creating New Files}{23} \contentsline {subsection}{\numberline {5.2}Opening Existing Files}{24} \contentsline {subsection}{\numberline {5.3}Image Filtering}{26} \contentsline {subsubsection}{\numberline {5.3.1}Extracting a subsection of an image}{26} \contentsline {subsubsection}{\numberline {5.3.2}Create an Image by Binning Table Columns}{26} \contentsline {subsection}{\numberline {5.4}Table Filtering}{28} \contentsline {subsubsection}{\numberline {5.4.1}Column and Keyword Filtering}{28} \contentsline {subsubsection}{\numberline {5.4.2}Row Filtering}{29} \contentsline {subsubsection}{\numberline {5.4.3}Good Time Interval Filtering}{32} \contentsline {subsubsection}{\numberline {5.4.4}Spatial Region Filtering}{32} \contentsline {subsubsection}{\numberline {5.4.5}Example Row Filters}{34} \contentsline {subsection}{\numberline {5.5}Combined Filtering Examples}{36} \contentsline {section}{\numberline {6}CFITSIO Error Status Codes}{38} cfitsio-4.3.1/docs/fitsio.ps0000644000225700000360000317267714456514035015274 0ustar cagordonlhea%!PS-Adobe-2.0 %%Creator: dvips(k) 5.998 Copyright 2018 Radical Eye Software %%Title: fitsio.dvi %%CreationDate: Tue Jul 18 17:37:53 2023 %%Pages: 142 %%PageOrder: Ascend %%BoundingBox: 0 0 596 842 %%DocumentFonts: CMBX12 CMR12 CMR10 CMBX10 CMSL10 CMTT10 CMSY10 CMMI10 %%+ CMR8 %%DocumentPaperSizes: a4 %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o fitsio.ps fitsio.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2023.07.18:1337 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /dir 0 def/dyy{/dir 0 def}B/dyt{/dir 1 def}B/dty{/dir 2 def}B/dtt{/dir 3 def}B/p{dir 2 eq{-90 rotate show 90 rotate}{dir 3 eq{-90 rotate show 90 rotate}{show}ifelse}ifelse}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT)(LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse} forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{ BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat {BDot}imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B /M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M} B/g{0 M}B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{ 0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMR8 %!PS-AdobeFont-1.0: CMR8 003.002 %%Title: CMR8 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMR8. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR8 known{/CMR8 findfont dup/UniqueID known{dup /UniqueID get 5000791 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR8 def /FontBBox {-36 -250 1070 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR8.) readonly def /FullName (CMR8) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 40 /parenleft put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9928A7C95D3A6E9B 8E92F84CA0AA44461D2F4FA0F8B81C6F5B7BE98C9712BE166610465CF689DFAF 27C875C029C0116DE61C21DA0092D029E7DBEDFDDEE3D67E6936623AB53FA2AF 18BEDDD7AC19A19CADB6ED6CA7A26E6044BE414FFF59C0B98D5819A6B881F9AB 7AD0D03BDD5CD309C67811D5CF0B93F6FDC9AE64F74ED4E81F2E18D880BD842A DAFD0BDF06300201C6946087FC0B999447BC370200BFB8CA420B668B32EBC242 6DB1546A7164CF55B332FE9D239B65F532B69EF9F4F93828A44C8F5C526126F8 B7A369114CA68D4F98638121F4E17F351723D9F1A902FCF087F94AFD23876517 2D15B482AF2D68C3F31FFA864E031596E597882578AC7FB0DAE2A713B065B374 3E2E72519ED6D50CBCA40A7275A7109A4F3ED8A4566AD8832890D3D1F4899850 9B757442B7EA355175CD5D6D8B4152ED2D7EEB4CE30F174FF672140354046A45 7098EC45B9DF3DF5CF7B417E201DA88308CEF4CED8E8903AF24FB8DD0187352D 25738519ECBC70304F8F620CC45D2586619205DA3955696FAFFE2082402B3502 CB682F410DE5FFE80A4DA3D3BCF02E35BD577D0DE55E7B8A33B7A2FD5136B5DD A0BCB61F8E7F4363C21F890CF287304DDB8FCE7FE207C0D160B81E7EA662BED2 DFF8C444E19C91E72254257CD87240A70F1A964FA54ED9ECF27E27A57DACC3DE EABB92C085030870C6CF5C40B6E47F5C0AEB30E84A73ECDABB2D754EF6EA28BB 16EBD6636BC288E62F4A38BFB55F5F4DD20FDD77D767F6CB52F9513E8EB75413 07F1877B2C01278675177499E4E8EB09F2657821613F5C7643FC064293EC6E9E B519FFAEEA36B19C9D1302CF91FCBF87FCB57C5F995CB6712BB3D8681EB6F05B B2A4195A3C73CB4ABCCFB958EAC533BD89560D2790CDE1444C0F2E4EF27A529C F01052964E56F6D76A190E5FF45934BB711A3406284AF130D4DC0D8112BB3752 762CA0200CA262359D4F54C0CCFA9A50DE18C7DB14419E2990ADDC4A54B94978 D9174CA39434022FA77FB30179EF805E2189C35919F5EBE215EE2A00B4407826 CE56329C5586D8B414770BA5D45513C3AF1931D632FCE69B4CA504944E03362C 74A1177C6398A61A12DAA0F156543E2A8E9969C4308B7ACC21A5ECAC8F172541 1B1316A88C0C163E574FFD3CD22FF08488662FCF2F9344BC25D02146F36CA6F9 E2D0130C654B7485EEA9A110A33AA0C769121F81821E9A2BD062FAC158359D44 3F9D9947200EF1EDDD5860F10438B162A69683957300C75AF7546C70C97AB2EE 37EAAF0089E2623F787F252569B06C665FDB45EC9681C0774ACFBA76B98C4E89 7EB12AA5F8798FFC110B49C25E3A483ABE83B0BCC6DF0578403ADC369E013762 C9D08FC94D949BAE636ACA9F36F4E3F02296775A062077B011A705B6F1784D36 A926622CB3847533D7ACB24A4EBABB14593B5D8E1DAE2BFEF8A51835C8D4E76D 7543C126A4271C59A5881A5AF89331694F84489CA66725995DC3070F306EA447 CF30F63CD476A46D528EC1FFBFB8EACFA2BEEDCF54C92CE2BD26DEA5827186BD 3A4D1709415CEE7D51D671357B4A5D11E835F63521B9824EE5282E58F05A8ACC FD249461181A38C2F47BAC4E79BE368D64F886AA493C61CBCB2ED401C8AFBA61 59CA6F6216D941A92AC52ACB3D7ECC28D6A58EF4CC70BA6DE23E80937AB38E89 6F05FDD15B954C0826636267EDAF9F2BB466BF79D2E10EED9B04297E6BC93069 79581ADD1A9D9FAE9306F46AC95B98C60A2E53D60CF1AA4069BE301E17E25070 F98DD67BD8642B1D07571A32766072E48BF27E1576FFEED300D7313A358A823B 49C8F135961B7E259095C9BB67F996CE0B90E95344F203922F47E11753F70D38 2ECB615403490310CEE6C03AFA97DA2F47ED47125D110FA69725BA0018F6A40B 29A307FDB3E52322A77A0102E6F57654CF1E96A134D13860D83AFA0A41112D3F 2247A09ACF7D06713BE443FA27C7E7220E875965D53030FE7D2D62EFD2F1DB87 5FB091FEAF599BA8C5167525899E578AB341BFE2BC4E53A047093168AE189237 EA55F055514EFA939DAE9E859CB5FBCF37D99484F44FE5AA5FA386B28BB642F5 5DBAF059A50FE96C7C6D834531D64F1F2E99AB2E96EE74D149178B1C0618495E 293973D9A03E1790654B67C0882376ABEC17D74785B3737D81644F28B3BC6FFF F92FE29126995A07E0BC5EF3A4B93789A103C428943E045B8D1A5063AE71E806 568D48072E53DEA85253B01DF0BB7367A6BE4DD7BE514AD74E3F77C825ABA405 64DAFA25EAFF8F63344B5F6B523629776CEB090B546469F6A6008DE43072DD3C DEF51F62731037D1FBD0C038A1E9B669849EB3BEBA281624F13D20B61917A109 A0A7871A73F7BAA18077360B38A4625C5DB9AB9E43BDEEB856FD0E2D3AA2E075 267B978B9EB47F2369302E87DBD5D5B422830BEC32411FE75D584C58650EFB1D 136FEB92B94BF8939FD63AFB7349C7511E5E46AA7324F8B1FFCA9C2A9E9720C0 A720918E8E860F137567D386AC29870FD990BD69465B3A3D2A0ECF2753578AD7 80DC87EBB319EB5AFE0B6F6FF8616EA30C51425FE3ECBC5F8D0B0BEFDEF32FA7 D168B4E85C804B7326A0942CFDE732B1171C643452B7099B31649CA2C38B62FB 46EBDF7180004C549B53F88021D029452C2B37D8C565BCDB0B11541039A13C0A E45D4B68C7907B8BF08C6F41F564B62BB554235D50330E78DD02795516D969C9 66119D718798120442CB7EB9877FF84EC69DAE25F8559DCE3BD8042959F695F8 2F99845B1B5680DDCF181D806CC4903E077D1FF5E60918EB34C0B1E028422B71 CA63EFBF3F4F3CD813CE831EB54265A555BDD35AD7D723F9CFBDAB29C54F8AFF 2D35C6A3299E0A2DB470C7B141B1E3E10DABB7873AE302926BA8743278FAA8C0 DC6174501D6A289CF980A3F55F2DD5C3A514E7E7F13133C35D2697D64C25130C DB78FC997968D6B3BC929E8A31B6D212C5128E4412632BC52B3A1049F7F2F61B C74AE9A6AD19B9E2E240617E2882F7D29ED3A4279439107AF9AEBEE47CE85DE5 CE9595A96A118ACF1EB1F5929930321AF7732E351E18C6AD378508E37B4C327B 0E06AAE21278AFA9255AFE5C022034DA2968D260879B4B38E7EE2E11A593DC3F CE71ABA050C004473324CAB6F3C50E85DEDA3E9A27388D8FD3A8F6E42A79670E F7549CFAD4CCB337A6E0BAA4846ABCA059F1E1933CF11DC0FFBFF550CC4A1B47 CF7BCE0875FA747AA854534960F757884505A5AEE0330179A9547A4AE3E68479 7A457DE83326DC30B67F27CFD4AB697601CEE352F72F0966B3CEE3EA24683BEF 6D23AD51B8432C3F0DD0D0F80791E1091F38988B7A54E466A9AC7810DE8B7893 6B0AA6356597891D56190A7660BC7F657BC559E0525D41EC228078F2FBF89C6C 72D666DAD838CBF0861FBF0A1D4ECC069AA49DFBAE5C56B781A1D5D79DAAC256 13E3F9B928A2394FC71691E4355642764459714412D6F8EF803FC5F7353822DE 6CCBB8FBE5AA1F2C7F4D384039D85E7728527DF9FE0239E2CF8BCB7411C000B7 1FE660AE6A2A19229E5E8776CC83EFF3C27403935756463EB4721C51FE0B1197 86C2F17842A0FB639F28083DFD4F1E86D7D3BEFA922514ABF489C5CCE93D6F72 D2EAAE14F6CBA2BE4BBE7D7EA8EA19DB3A87350D4A52064137C3D15A5B05B03B 70B1DA7328D10713B83974C390C3270AF5A9A47C0BFBFABB9F31063B0CCFBB10 0F236C74446688198EFF039110F6FF42FA9F82D463AD3958B5FD205BDF85DE20 FE3F0C7AEEF350AEE6DBC1DE2E2DA4F4599956F59D6F121F7086DC120416E180 52DBBC4E56C09746938698860F30007091E1CC0351B43990E47208ED495310F5 7BA9C6AB3CA10A3F1B318FD47C1CE3B9FF1304321F9623E32D315AA9CE64B35B F841E6C62B5B2488A311C94937879E5E0E170FA77AF0AC75C5E6E9F3E8F825AA 09C1702682E14FDFA72D27901C5BDE009B1E52E8C4511C6F6336251BD45261F7 401CA3DAE7C4B0CAEB91B9954BF4A97C48ECE7FAD401351D59DDAE9DA94E2335 74A2B880E4749D3D7026CB5299F16C204B6E00A20A6619C34922C7D3FB50F127 3157CFC08DCC5164C8023CD1B6C3556C73CB8E4ADA845339CA9BABA1457ECEE6 ECB9849DF1F0FEBC89E5F97C92978A500196520839CEBA6C0FD2E3D27BB4B4F0 93CB2BB565F4627C6DB62DD0E084E627D69B5DEF42EF094381B62C0D67EFD197 301B132420F51A41561E6106870147E0D597078435BE3819ACF0DE28AD779847 F3D2CF667DA06955D53E0204CEA2935E9E984E76963D3079EC092031E2A10E61 1227E5EE6770DD4D745A52655369EBA06A19BD7D95BBA271E488241199D1008E 36EA99F8DFD2A9F87B06B070158B466AA4C6EA3BA77DB0F853F0BF9A304EA291 34069714368E0B94DFCBA3BE5EDB6C8204DFA7EAF5C3406F60A7056407D1BF6C CB85C1F432F97D821F5518BBA79AF8453A568FB2C2D025A70CEC75F46C545011 ACE3A99B2582793BA1DC655230AE2EFD24DE20A01D4A441AFFAB7771F223FA6B 9169849E727E494247F67D6E1EA9DCA06A082FE2094BD548AD7F08B565145634 E7ED832FEC1378306DDC796303392ADB0CBA130B63B38ED57B7828B47732853A 893E8836FE19CCF27002AE92C2B2CACFDF8A42F1B8066E033B965D2E9157FDF8 E1264B40813C1A4CE424274AA3528A4F09B3B53DD4D23789A68B3D17BC1398AE 0ADA2C2168427A49846DE0216908C2FFFEF4F13C1ECA12AD341E238EE46E6DC2 B71B54C52659632911F901660261E493AE2483D64E119D9924489779B62BC9FB A052E822FD8D83178E09ADC825DF0DA07FCE7AD68EEB29FAA275A13691B4A5A5 B0BC0499CD6307610CD6209583C1152C559A2760823F8DC0B9B990BFFE7B7E9F 3969B968AFEAADB9FC0F1410EBBAA0DB979CF153F0B8C978405F8E6F2B6406D7 AAFBF4A655A15DD6D1E9A7EAE10EF89264659B09283F50B734236885FC09FBE5 98D780012FA77FCB19F15BDC522CC7312546C0730EF5225DEA8C22A3BC6554EF 4FE73B9AEB5C2F7DBD474221760E5F539A064AC450591BCF3499E3968F2CBD6B F15BA2B37080A4129B66D4C2188524F025414F14DB3F96049A8B0E5EB2BBE7A1 AD64A988FE875FE4FE5186BB4F5DDA16983CB052D474B7D72F3E8965663EB50E 015C72407C3437142D3D7DBC055FA627139488DBC5A0F98D805C2143D99F491A 167E07AF60EC9F17C36289368D740B632CB919A0E74C412B76CE7A5906D5200F 9E79CEB9C65ADA3A0F23E8947E834AE7A329A9F0AA7A6BF545B1D7B4666C6522 CFF268634EA06DB3A82D91A4C0A9B227E79961212881A54A6762C335DE7E0831 130C45D94394D21C049B9D189ED955438C2151514F17BFC67E431DD9A8349202 2F616AEC1C7B19F63D5000EB4771370924BD4B9053FE78B5E4A244B9A149D66D A8BF3B398396D2233E92E4A5FDC70FAADEADAFD255193D688842DBA865CF6154 C9348D590F3FEB135D4B7BD4D76A52CB140888247CAFAB25ED51F4D187041CA0 ABD956F83A5661CEC171B52AF92F9ADE27973B560C802E1E0FF51C4003D1289A CDD09F8EDA8AFDFF666D35418CEADF3B0BE298F0D1E5C8E024D6A2017A7E71F3 3A9FEC9930F1118101E040339F9D41379170928DDF5B5875212B271DC843F612 E0C21C67263186E3D6929160464D4D5C8928E14D0845762C36FFBDE548188E20 3B6BAFE5EECA0385142F01216FB8A90C43A472C1D4447FE5C7C78CC088FC72E7 3FAFA062C338BDE8A430FDF1951B107D8D73FF9376FACDE5900BA362C66F8C1D 947F9545C5C13A53E4479B1C1A50472C05E8F8C266C6D4F4EB08E97B3B1BA972 26973B844545089C5732322BCC9A5A8FC972FA0D7DB8BD85D2F515ADE65DA479 0224F7EA2276CFED0B75B2C23AE7377F86F1F6F205D6FE19377D87E782143697 984E731F83CA888199CEB425643C259D4FB8B58DD69A96085198306494BB497E FE7C9954EF35B679BBE3847A9C73507874F71FC97665E2A58BA41407A1745247 44A79B588D969D11CE4B863CDA655DAA53CEA5C3C263B345E782006CE9831D49 603D2D95DE9E370D617F5928BA416C362BB2B4DEF16A5D44BD24B34257765F3B 6223B3F9B54DAED69A90C7050AB97B06693D253C6894CBD7B497DA449F1D9B7C D91B421891EC0724F59C82B9CB288DC42F2D2D7A7F22EE3D910E15953D7766AE 276DABED3820390BAF2700C4653E1C77FE63DB71A66D93ED293E25B8412A1EFF 809554BF04ED0DE83F7F190883ED793803CAD2C34A66524D3A580ACDF3C13B22 08F18905E7A4A16DA9ED2A112462FB9FFE481EC2069E484E8BBFC19D594153B7 3DED4C11762223B7586483B06BC164D824D1A6FCAE80A35DE0DB8B33396771DF 76DC5C05578EF1BE00A70BAF3D951A01C87328DB2B0DAD6E1B4C21F37D1BC0C5 A929BDE5EADF20DA60C4DE2E3C151005814F24824D33B95F700E09A0207EB602 3EF60DEB1622B91DB99A855A8F1DA96358F05CFCEDBDDDFC8446AE3391BEEC41 966E594E28D052DD5ADA49DFF65E79540EBE5329DFD86C23CC800F95221B9C18 CBBF941D2FA47EF1EF59A89DB5DD188E75EE94AD2A79E2221107E5992C00D531 2E00B544895A9204656867E3DE9D4CDB64B920B5CCA9A73E6514B36CABAE01BF 94C15603B86780190595560F792E5EF01650074EA4A9BBC6ED284B9AC2020641 DCBCEE0ED27FE58171DFE104EEE4202759E594159DF45113C00236127A46FB35 9EC705F21C0E456C1F0F924594C09AC64D4377C5FEEF764BA4A09ABA8D09DEB1 FC13B0CD202B2F04CF5D73DEAB65C36C2FA7C0DC236BEEF6D23BFFC9C493DC8E 1831F19EEF81EEDD976E43BAC6B5CED13F901DE59835FC75490EA528A72CEB77 24C38B258EC38B9E6B97F85CA8C10D8809BBE55A6FAA12456FCAC786942E123C 06D1E55F7ED04400088BEC968BC5081DC7A1B1B65166E7821679F76694F235FC 6854C8776AF855B83445D9FF919B1D80E98DE0741D06D6C5EEDB3E3EA6392530 F1BA817737D8162F7B3A36AC2A03190CDEC654383E31934C3E0A012B639532C6 26FEBE9B412F1C92D1943B7C18CEF510729D501349644C97F087F2F840074AE6 D8CD0FB2E620FFC908BFCD938B675A0A4A687F7FBE8F3DD06A62D7B6DE7DF3E2 49D367D60B10061EA86CD512F5A1BE8950D83C62695E130128E0037B62552D17 064319BBB9B1FAB9D79705E5D68AAE9B36EA14BF1A59A863BDB8DAD9AB5D7B8A E30E2B499F952D65877C8E38EDD7DB29F9579D09E629AC188DB6A6403AB4BA3A D358B3770D727A2B77D84B6C9EC17E29D88E3421F9B7D2D822EB78BB8BB50692 8C46DD6F9BBEF2E848A2B5669B200019802AD19661537A84D3514AEC5AA47445 2C791E01DCEDF18D9506367241255FFADEEA6183F51A9F42448A7DE413C08359 52DAD2A60FD606AFE14702BD3B0EC448720FE63438D020DEDFCDE3582FC31DF1 17B25FC152789D2F17FD60B8209D292D2152DCF8D28B5ADC04F6659BBB746CDF 145163361823CA343763AA951C640B5D4A99B7787105A1609EDD6A596EFC3F6F 2FC33D0D499DBE56C6668E137715D435D6B683E0113647B2765AB0F3D98AC717 5B33C3EDDE18506E73B4E392B022F30480BD30F59B2E3A59D93017296C3156B4 B5722E1955777716388AA987B2665669716F866FE6BDAD5E74A523CC03915F26 9B7B231F5D9B1F61DF7CB01ED3F27070E36547B263855DF5B2E3ABD2ACC440B9 0826E1DF4743FAE6668B61F72C8700992755522AB11C765981A9BEE0D040039D 6C2D64ABED527082C97CA606127AF5C0CD4A423CFD22E135E3FC281A1DFB8B5A A27428BD620E6D9AD648463A82FED0129AFCD5D0DA54F9A6F694250450E05CC9 0C22953EA70B8E53901964DE19A3F17485855FE390BD5271ACF3B6B9F800D465 E6F0C0032262CD73C5AFFF2D0ACA39CD806718F3617BC009F9CAB5E5CB6616A4 BCAA8A5C4BF77FD7B641AB79F6D8F3630B503FF6193F8462C6E08C0E62ECEE01 BF644803F2030D7D7F0F4C7C20AE6897A5152F896389B74F939A8123A7A2494F 301D07706B01600ACD60D84236E6D2CDB1E5D02AC300216DB172A026C49AD933 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMMI10 %!PS-AdobeFont-1.0: CMMI10 003.002 %%Title: CMMI10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMMI10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMMI10 known{/CMMI10 findfont dup/UniqueID known{dup /UniqueID get 5087385 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMMI10 def /FontBBox {-32 -250 1048 750 }readonly def /PaintType 0 def /FontInfo 10 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI10.) readonly def /FullName (CMMI10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def /ascent 750 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 58 /period put dup 59 /comma put dup 62 /greater put dup 73 /I put dup 84 /T put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 119 /w put dup 120 /x put dup 121 /y put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3C05EF98F858322DCEA45E0874C5 45D25FE192539D9CDA4BAA46D9C431465E6ABF4E4271F89EDED7F37BE4B31FB4 7934F62D1F46E8671F6290D6FFF601D4937BF71C22D60FB800A15796421E3AA7 72C500501D8B10C0093F6467C553250F7C27B2C3D893772614A846374A85BC4E BEC0B0A89C4C161C3956ECE25274B962C854E535F418279FE26D8F83E38C5C89 974E9A224B3CBEF90A9277AF10E0C7CAC8DC11C41DC18B814A7682E5F0248674 11453BC81C443407AF41AF8A831A85A700CFC65E2181BCBFBC7878DFBD546AC2 1EF6CC527FEEA044B7C8E686367E920F575AD585387358FFF41BCB212922791C 7B0BD3BED7C6D8F3D9D52D0F181CD4D164E75851D04F64309D810A0DEA1E257B 0D7633CEFE93FEF9D2FB7901453A46F8ACA007358D904E0189AE7B7221545085 EDD3D5A3CEACD6023861F13C8A345A68115425E94B8FDCCEC1255454EC3E7A37 404F6C00A3BCCF851B929D4FE66B6D8FD1C0C80130541609759F18EF07BCD133 78CBC4A0D8A796A2574260C6A952CA73D9EB5C28356F5C90D1A59DC788762BFF A1B6F0614958D09751C0DB2309406F6B4489125B31C5DD365B2F140CB5E42CEE 88BE11C7176E6BBC90D24E40956279FBDC9D89A6C4A1F4D27EC57F496602FBC4 C854143903A53EF1188D117C49F8B6F2498B4698C25F2C5E8D8BD833206F88FC BD5B495EB993A26B6055BD0BBA2B3DDFD462C39E022D4A1760C845EA448DED88 98C44BAAB85CD0423E00154C4741240EB3A2290B67144A4C80C88BE3D59AD760 E553DAC4E8BA00B06398B1D0DFE96FB89449D4AE18CE8B27AFE75D2B84EFDB44 143FD887F8FB364D000651912E40B0BAEDDA5AD57A3BC0E411E1AD908C77DCE3 981985F98E258A9BB3A1B845FC4A21BCC54559E51BC0E6C22F0C38540F8C9490 88A0E23EA504FA79F8960CC9D58611C519D3ACDC63FB2FBCAE6674357D7F2285 4BCC9F54D3DA421D744D3A341DA3B494BB526C0734E1A8FC71501745399F7683 FD17EC3044419A88C3979FD2ABA5B0130907B145A8462AAF0A9B511D2C8A7C7F 347FF6AC057E6512902BFD2918E2CD31DE615F5D643764E900B60287670AE18F FDE15545D8BC69591A8CBBB275AFFC9B14BD68DF0AAB32268FB84844D4DBC7BB C591C1AC5102C50A9C7BAAA848DA88B0519F0F5F0813BF055CF0E3C86F633A04 B779D2E8E656DB1E09A66A85FE21CA8BA5523F472A229E83F2C4E91ABA46C733 F3C7B5775B06C97782BC225C46385BEBDC61572458EFC5CF4190AB7A9C1C92DA 29F84BAACF552089195966E3AD9E57CC914D20B6962BE80429A16D4DF1ECAA66 36C4343FADF0B2B48F12E2EB8443C4AA29D00949255F3968617F98B8ABD4CC12 048B838EE243A21AC808BD295195E4AE9027005F52258BFCA915C8D9AED9A2C0 80814F79CF943FBE3594C530A22A92E11BE80FCEC1684C4F56712D5846B0749C 9B54A979B315222F209DEE72583B03093EC38F7C5B9F9BCB21DBE8EDDAE9BE8B 75ACE6B12A31083AC8348EC84D1D29D2297A266284B7E9734E207DAF59A25F4E 4AA38509E993C5394FED76E6A2F25462685C4C86C6E8CFC9863338EC1428BDFC 74616BB1BC8948B0ED4C87C15B4405F3A7796F9DB3798FFFE8BD0A94E834817B D5E9812E308D0CC920470A6F2CD088FCB80462BF7CB3F039A7DF3DAF5B2B5355 E083A385CD2EAF0FC181E40E96DD7E9AB9EF5C7E6866A13B8A54718E950FE097 EF0951A357114F18CE9933D28B3A77AA71E3CE884661F13284BCED5D5FD1A86D 543E588FF473DC2CF9A4DC312500135F29C2D0174B32018C8DBD40EF9A232883 710A1F2AB2CD11312300ACDF789A9B7B93D2035D81D1C84984D92D78A53A00C6 EDA94B24BBAC1AD17774A4E07E6F74ABD90415965616AD540C8ECD8C3A44EE4F 7F4F6BB6238C5062D63FA59B7BF08BE93FAEA70A2AB08FBEAAF7DBF56B95FD93 03CA406543BA6C9527D0DF01F5108D31A51778A5EB1C93F27B72B46146A353A2 01CACBC829603B9989A87CF64528682CCBA0562A8165B185C58A5C6BB72F5E89 500ACCAAB8ECEFBB2640E99EAEEC4EA979AA793D013D61D8ACF8784FF8D9398F F6A252A709324FB39509F0B3A4E725E82F53543383C6765BE556CC897C758208 AA3AD37B0406E4A79F8F0A6C1983FC73E71CD858C0DB66ED66D5D992978614EE 1EA91EBE191E082EBA1FC040AF19A2202575C2EBEB8058833E3520FA03D2F915 85C1ED337E457B9FEEB0C6EF2735EFDA6E0D05FA641BCF698AC6B97751E8306C 4DF00A39B8581FF53DB8F8525FDB196D85950906CCB59B8EF171349AA3B567B1 6A00819947A995FB383C3C1709C9A2C113B2E40BB832B7D4A0FBA0B16A2C455F 55809CC425C403E9668DC66BE45B71A81C332FD4DB279D22A2959962304A8F18 085893DAC61317D24A8F198FDAB95F3B86F0AFD35047B868A9A17037A2829A02 BAB042F75F349E197A7EED41984C2859754CAFD0251439921C248B463B516951 2E1322C80D73F9CBCAA63A585450275AC2492E4D3FB78E800F788254DB5E610D CF788DF5C70FF99892BCDF16133E34B24B77C8F097F546B87C603DDB8998B66E BACB68BA27462AF54AA405682EC96D701F0D474DECD5F95CA2102DF639EB169E D518162C2BAE45FF698B6DE15FC6E7DE48C336C40A670FD26952A6BAB09115E1 991F0073419F2CC2A1C08BE91096936AA0C37E4ED3CCCEE235476074B8FF1125 6BDE3701F85532D8BB64CCC927CC335281C95EA689706F0AC717DC2CF680C754 E5EFD7FA4BB8880B2B727A964C876D4A223069D4E6001771F0E23EAD2A4BBC80 E76675297B2EF05F52BF4E71B3EE2BE3048CF088C79540113C66AE98B2FD3CB1 B0741A215FD070882C52765009D7D711DAA2508F19AE7DDA15229A856AC49BC3 4DDF40814FF96500E4B9B02D412E94623C5FDCC76C0FB8E42DF56A904FE49D65 1DA7C53901B2EA71AB658A464D3ABDE27D9DB8D9E0B48F64E61A2495AD5D8DAB B5E72424AD017DF37964AF911BD7FA21A5EB4775DC8E95EF0C0EB856B00D89D7 8172A1DE8530767D317B8256103E53CFB877E10686A04F5A08F8DC58D843DEBA FD5F40597588663D103689F6EB3EB14D06E18C8078F2538B43E712DF491FC5C6 AF639256C8C6134B64D560D8476DEA6329D995E46CC4BC78841C59E73648B47E BFA7DE0846422F738454AE77E822A083405289247BD7C478BE4974F742CD6051 E99FBB1D1B3FBABFEE855174734EE45E87D0AADF32B1283B911162A9955847FD 38944D70584FAA6B1A7191C5C134B73F98EB632B69E2F0C0F94156787C34C8A3 7622A029D58F9626B74F8A8A1F3803E0BC20E0EADEB1E99B70F1BD9F980FB751 2A842843DE42EB142A84D5D3138629AE9EAF6F3479C423E8829C8816FA6EFA27 DCE5580E65AA9854B1C64163DC318420CD993C15BFD76A8BA1182860A6B03D6D 22B8CF43CFE6C8AB27C64842E239CAE707D3086BADDE1D7C94E3BC96319470D6 8D26915C575CFDD03271D6BB9DE86A0EB6EEA6E768B224A626C62A9AB48A6EDB 44F70BB5AF991CDF9736D65933E81CC57A78F623F33EC9AF535F2F25FA4EEC90 D50DB7E87F31E971A75A33A301CA6013EEC5A4E179D695B33DADF2C98364434A 42926776000B610E17524162253F6FA638D6581C18F99EA0BD1D2E24D2424ADF C05010D08192485153DD03930C7BF45237593E484F9851E6D464FA10FECA5D9E 0C8CCC97DE029030900CDBB491C5CF226DBF903CFE7735D939C3FDF3A20B70CE 66579B28B99313FEE914E295388C7BC8E055A2E54EA3A8206D3C8F4F7C0BA5E6 E519419FD8CE215F7B8E9BEC604A9E3FE272A0328A24E31997C8A91E0946BCF1 6943A97CBED2AB9FC636B49828BBB8B89E0BBC2653796431224895ABA5DAC41E 1854BD9764E86147FD7624F736F40DE3B7582EDDFD15C2BDE3F22B5A54D7DF10 B87A1301CE85CFC061689A890A321412A13314AE96DCD3EDA75035FDD8F4AB9B 897A2C68263A68457032C469987970648BA2D88B1C5375DFEAA35A917B8A952E EE670427942AEDB3CB599C5746180E392837D371E15D860620ABDB6AA7772C40 A5E346661673ACA530BE3D8E3FFB895E5DA3DC23B1B43C080C77F7E47847F0F3 F3AA5CA9E4BF75FC5EBD18D19F21A7DAA3B11CABC6E4070A15F7DBC8B05EB6AA A02EF1B078EB66D61D6AFE41DA9B36FE7EC9EF94D1EA26282A9871E2CACB3126 2AD49C2D9B50A6E47D8F2CCAD50992D1B430979A45FD9E76182A19964BB2A1F6 51779A2B258DC1DF4C2F3074621286831F3848AC152DDD2BA561E6586ADA88D3 598A2CE2CD048F027CE0008B828BD915887D7785341E8305DF2346ADB76BE99F 87B02173BDC334E9221C8DF54114A6B24C1C5340299512FA6C8C51AB4C8778CE 178CEF531C6D1B5FF0A1BE8EFF767F959BD4C345C52699A29A17B2A230842BF6 4B011217D6D24EDAC3F6D53482786F1CA33169B90ECD499407D37CE9B70DDF78 7B7547B32952535BA9ACD1E244447AE3FCED3AF28717083CF9590A09780984D6 AF0743C82AE4FB3E2BB2856A4153A3967A023FFC35382D6C22D84A924900B6A6 3DDD400E6D2418DA6C27F2FA34C075C902B89EBAE658B3C9A18EEE449DA5A379 337DE95CB7AB3F0970CF1A5D8FAD8090E495570FDFB2FBBA79244780D8035547 C5A55BB21A2270F724BF5D442CDC5BB9F09BE0CAE59B1C2270F0BDACE698F2C5 DE8F66BFB9634904B161F5BA2B1950048300D69BABD312D58D89C4ED527AF7BA 7DA2478EDC2CDEE3473DD8A8ED9D891CD1FC21F23013228BB3281B71FCE959BD 6F8E9059D682A7FCC5265A0620992D4FA8D78377EB34CE3ECA070EE3707239BC 98907DB0120CE42ABA32CF97127E28382BDDFD685674279F588D4F951216C355 821361790F64C2CC720DE97E8ECB57326C43EE47367628E05769E106868B54F4 C33C9951908DF6FC4F5ED2C7787BD8FA591BBB3E9C6C1DA94CC5E38D9B20C886 7D237572FF46DD896A4D6163408EA6CEFAC398EE041EAE29D577E75326CA17A6 B072D47A7B13EC441CE6DAA042ECD02134CBFA6809A435050413817193DAEB16 A5882C8AEA44BCF36E74E9ECCDFE7E19FF5A5DD7A94E5AB4F8702C3DA7F42325 23C808670A0490F5B373DADE40814FF9650241D3D69C91FBC5ECE728F827D9BF C928602E05477903449E079164CA39859C4BCA60C579F490AA455F82B5050BB3 969AFB478E0D4A257B3356EA3CD62051FCE6C6B1929CFF85BFDF166BEF658E10 3A55E007F38EBBB248B3F0B8ED1925106B499B762E45113AE1AC9DE09644C84B 9C08034B297314EE69BC32DB6E7D7FB9913CE5AC17E7335979E9DCCE2BAB3725 1976155551F9706A576FE0E3ADCCF72C87683291528ECB749CB0ED291966E239 B5E3630676BD409E08F85BC1AEC9A2D4135376284A96EA24431243BD6FE8B966 95F11A4BB53F392E0AEFEA623064FF8A7002367B0A515635CB2D2DDFB9B4A8D7 FE721754E81BBA548848A235B91AD4E4F7DB19CCE2F61D277FC00AB956EB93BE 44AB4970CA56BF59506C94ED160FB1E25D3DF2988A532BDB787BFB8539D22986 FDC378AC31444E63C4727FEE121A43751043849E6DCAC5B59D0FC703AAFBBFD4 E8B7C268F21615AD02CE9DABEFA27B5FE6A6441B619539CAB1F810F1263447AA 633F5DAF483752EF1A0421740E3A811D2D2898CBF53E7F686C9223FD7235F02D 6F90D2D48CC20AB87778DE3C6FB335E0F0EC20B5DC5B65223FE117526DE2C72F FE839DF93CB2A7D66CD900CB325F891E311BEC932F703FB4FEFA29DB8B9C88DD 375EC71B3D58C7BC59ADA91971A3BDA1ADEA629CE6CC92BD542CDDFAA7706FB2 6CDDE2DF07E56D6741916AE8E8744339816F3E6C38062747AA9FDA2A2678A6B7 EFEA870AA3A4D71B25EE3013EAB1DBA34401B867C7A41AE51E0421D41D3BB83C E120C8FEABA6E5DEC53A689C21426D4BBCB68CB37568761C360E6D4E3596FB7D F4DEC7918E58C0293D12D6DDA7E9DCDAAD7C939F55CD1BC4A228B31E9A904156 DA6B40B08E6ACE674618B768DD681C772A3E55FE096CF949CF3B0460ABDCD891 D17B37B355B29AB5137899C036F31DA026244FA25FB798FBE5105BDA29F46538 D3D3AC1001A7BCECE64DE94FFE6C354166A0F97256137BDFA07F6E22A3D1D2F4 9588DBAE95E895BC5E64DDCBBAA8D0A22C229B42CB717FC711E7E9DF793DF80B 9F14754585A3C7E17F37B32924B9F9870DA8635E3E18BD1DCD81EDF01834D9C6 B33F23C956C2FCBFA47D84422F583459D827D1E120B97694D12F1F54D02379C0 D288F7104F3FFCF4F76E3494F4ACBD1BE3A15543CC680924C78A473F8E311ADF 8FE00A04C6C393DE61AD3EDA5BC031E2353076A2489391B52632387CA28A7B93 FBB065A6EF3658AE80B1ADA47E9B2539E73A71FA75645F85ED8ECC257FB4CF26 B6C912DE9D0F9899E70BECCB934AD32CF49A093371A9F73DE6255EBC39DE1E7F 00D0CBDABD4D0383977E694890E71FBE5C376BE5F3A80C28987417504F515C50 909F3D31178BB9B1D085BE514F71B910A9085BD6122DDC72A150BFE266920E49 5661BCB4BAB51D6DEFE32B616963DBD989FCDD1637B294CE4E288655FBEFA1BF 7F25BBF8CF17C2D5FD161A7C2CC9CC7490D9BF15A1D35B3BFA43ADE256E88BDA BD490D92907C57BAC408A575EC84D6AEE070148C7C9A91C03B09FDBD792E8FF0 C0B886AAD2EDD86541E5E579359D40E3AC312ACD3D8FD49F71BD533DDF8859B1 BAF17F1884E331DD07CEEF93B71D492AEBAADF7A263450A7A72210CE630A0D37 BF024BDC09ACC882816B8C22C62AE38A3A8D0F6EBC2B1B2C0B8161A8B076DD5D 4B779C0788546BB4CF57332230D237856B00D79C28A7C01D11F44B7304F69075 94B97A745DA43D1BE561372CE611C345A843834E46AD9DDB16CABCD3FA33D6F1 F6B5C0497F5EE5400B305CDC16A7EC286AA4D45D0EEBB9DA06AC9C5294D68EC9 E4DC3CA2B92CE8FC0526184A86EDC7AB34D67E60AC12D9CA8FD300235EC968BA 92C6FBDA47572BC5600F25249F60AD287CBDAE980E747FCBE7EE5CD323E733F0 63553B494D3DDEB9CC1480B5C3BB79A28E419AA65B18CB297AB383419E890E2A CE6F98C9900CCB4675280A10CF060B8D220DDA1BE55DFA65715EABCC1AFAA271 B1F8732341613E17B231231A0D24D4D7FC198AE04D89A99C4536217769C6FBD9 5EE24A6302F97438F7C0E311C878F674B4477A5ADA3952CDE4055AC408B8174E 86F8FB797646DFFFE0ECA25D1BAB9A9F71F3926D3D85AA63E7A8C931D71E79E0 AF1EAC26FADE468F4FF7F3861D14C10E3BE1F9EAFD6D3A544E8108D5DAB5B180 3950C74818BC8AF4758A108F462EF1826647A49667F5E482038C54716856D9BC 35F29922846D2148F92F943E951D7438C73D6A60459A8003174036C64E1629CD 155D47FD04B03C023AD67CD5A70C98AB556EEAB8C48169706E5B352F6505D580 AC945171BFE62E81F8F500438AC3B64D857BA5BC54C2C4BBB237F8FA51296255 E66A92A61FE13FDE781D393557EB72CEBAD86511035F775FAC39A0479CCD400F 226709118F887F47CC2ECC8F79816D4A945B2845F50AFD62D8C9A9BBF4739496 9E644BC9F7B04803B7EE75A09EAE94365F6F374B4FCEB0B506C76297564B9B6B 8B812BC3A33929AA94692572B010E6210AEAA312BDFC88BF302244AB9D587A9B 919823FD01DE12438D960944D1977800FEB49E638C32E5B188B1CA033E0C37EE A142F746367888AA119535F0CCAF7EAA461B790EB089D2D6962E28A398439BB7 9C9943654D7A2D765B46BC0DD1F915327F369162E1BA1BA83110B93F442905E0 523BFF5E279508A98568CD5CFD18FABBE9D17265A9042537872831BF5F1F340A 8D3E6DEA1D9675E87B3425FAA0172DBEFD7C28E30906B9FBA65517C9B58FB6BD E0D474E69BB90B0D130A32C4130974A1C961CF064A5BE8EC1056858553FFCF7C 0D78627BDE04E5D0B9F6F72F92B61A915DFF7AFE7DC3807891D039AECEAC3F50 0A09579E661D3DC3022206061E0250B09A05CF198DF82D4F28FCD2A85F717630 90740F78F242019C349B65C2A455597DEE127E914C372C6EA0E250402117B903 1D7D6FC7153D77458569B2E0E6FB978B06AAD616BBEB70B58E0BCAE1013D4405 873D2AA3C41309993563E652BCF2B244451D8FA1305BD9BC2C57BCEA7F065670 A5059B0B17303312E8B787E02152FA92480CDED118924A9D490B2BCBF9A560A0 D4B55DC4968ACE1019CC2840E1AA0596F8E8D4BF7119B047E55B0FA01C69B9A9 F79DA6C9C9B49EAD94943613151247423679B7A29AD2C71BD077306FB9EE0AAF 9AE4B268C8BEDF3CAE8CE885ED53184F9BF2F55AA05933071F536B7180F6301C A04438DB5BE00037A8145A4476A817526E0890BF693AD4BAABE7DEF8EFD91F84 A5CE71D987EFBE47F1A081B8EA09254B0494FA0635D1BB6C788ED879ECA1BA50 4163FFD0618B20A0D5107746B8B37D349DD891CF3D5D5E6A39264561C1520337 3AD02F33854BD550D8DED71ACC6A9E29A0DF2079E7F0EE2BC997B7B8DC1405B3 239085C647255F199016CAD211409DC8D791B4138D1EEEC4D9E93B56FCC84BB7 3B181ED10567C2475CA6AA48E0C1B28F1FA2BE9FC1F785C0D8780162C9E2DE2F 4448A086E2070BDA2CA69A7F238C06815770A69E21E9482E3CD58E237264E4EA 63622EDFA8E6EDE9A4A8D2DF2426CC6F2C8DCC26A25D945AC8E54496D569B641 2B7C1115F177F2FE0805B042DE14235A9BFC49CA54D16EA27C7BAAAFE065ADB7 43E3A7534E02F326C00BD568AE608C4C17C1AD3BBC14D5FBA2D984E1A62CB5AC 3B03FB3834F1D856350D3050613FD2C27A6FF7D3A835D2A71CB1156853635D1F 236E3406731B7F56BB321475D1125143C50E9C8CE3F589778F33E8669B8D2267 1BDBA5447B670BDEFFB87DD409BB78DDF18368083E4730C5BC2B6D2657669BBC 228072D17DF0DB5996968F5F727BAF117B5019A332C10D46957C4D7F5A7280CA 29D82891BA138C6ADC9CCC4EEC7B88BA7AD98B16C36B9B66175D56583EF8292F 66373F62A354BE84117F423B4A542DAEEFD989AC1CB1A351C28B964FA715515E DA0F573D284B64ED8499B7E1A6E96C2F978BF070F2C9583543C5449406CE6514 B07BD070D9B5321EE18DD2A0B1F614C25B3731DE0E6F94726928514FF82A1138 F54B4BF8728C85AF1194738855119B2721132E6DCC532FF977CC0B55349C39D2 AE68FE04A5261E481BC0E1BCC38B35A557143792A55C9F8034468424576ADBC2 38351962E5E3B8572D234ACDBC6AF90F4D95406BF34479D9EED1DD9D47373EDA 43CC478DA097B062CAEFA56C829E090137092FF012A72BC1A7C5AA2770213E4E B3610625AFCCB621FDD5020DC9F042D9FF25E2852D671D43174F73E26043ED31 24D73BA74B9AC8AD7B55BBC7A3D6C7D684AF5B64BA81C614F39882639E04A1A1 8D4267C8464EFA420A38EFE83138AB3AA350558FDE6B4851BF456C23E9D9FF45 4CC274E3451413FDB9CEC4756523C67BD10AE64D047CBC4AE66A231C135D73E8 D3ED67D5219FC766838B45FCEC12D6B50A23A678FA9BE112092C49499D599E70 5A882AF83CB88A882146BF8629C8D8489BFC68FEB4DC881FF6A14F58FD4BC0DD AC5BD35A21132D03BEE9A54E85CC1F92CD6DF750786B3599297395BD119A0049 06E8E4DAAE290F458729639C0DD07ECA3795EDB3760872CBAB248A2B5BA2264E 9F7B0173A2C4F2491BE959F1418F54C1A74FFC743EE3895E1F5866C55F93546F 7CA28D7EF631F41853605D89AA54B825735B89EB837ECA8EE067953E300CCA44 FA66182901AC8DD788DD068D3ECA6F193D7918C2630943DA8E4E99A786717706 09F0F08CAFF3ECBE6A7FB5C8F0AF2E1D0E254841657A0889B3C9272AD5997A04 112410C138CFDAD7CBE315AFFB8C7716E0504C413A677AC15E7E7E0BAE11630B D9139F4D68F13ED2C2A15D00566600478BFD668F97C05F88DAEF073AE438DD74 42F0C55AAB5708FD952D93AECC8C5E5446980376B66A737D092A27FDF6BB46DB 5B8CE851B9807C903920F1CCADA19DEB31626729FAF0E54BC9E7BC45E15245DA 24767FDF0C6628952DD6EB94587DAA025B4C3C7E2F18066BAA441DF177B14C44 FBAB1CDE758892C7D28CE1B98499999D881602EF0A71EA12F6BC4074701C6553 7E178406C351731500436CB1586E0F41FF52A860F6B3563F4D5D45279F3A4D48 0196EB1FE855E05AF253A1A370E2CBAC0B6A7DB01F50F8E6AF172B6D7A23A33C DB14B6E03D892DB4941B680F8A435546631B6AD807847B69144E44E683BD092E A909ED98282CA5C2B1FD677DC823A811141A5926F28EF76119F821F6F90F86AB 4C862AD62BEB640DA79CDEF394D744C5A306D084D116512D373CFBE41718B0CF 42967980FBB4B9D56121926570228B956DC575FC7EF8D02230746FD2689D5928 247C2BF48F81B7B6AD5532EFAB4362F65E8EAA47413CD3EB936E61A40E2A16A1 EE68D2AC5F57AEA25676B0ADE4EBB4206634648E6DC5F5F3819642EF83F23404 EE218A29CC170AEC36AA6947EAD97AE98163E286293627A9DD053B0428720BC2 32B0E8D6BB156410478FA51E90BB10595E35671969AD367F63D1360263CB5277 EA9EB8CE749F444CFCA0D708EE1ADCD00C268AB52FB9764EE2DCAA880476D311 CD7E992FA4914E5EE3054E1BF43914F8DAD9039B594FAD2BDF3E309411FC9DCF B570D1F681CEE038C01B2EF9851D96F087607D7746C591457763CE457147F6AF E536FA02B200A0A713D5272EDD6B512C407B1CAAA36335C00C6DEBD71C8BDAB6 FFAFBCB2858E65BD6AF4143AF8F74A09F0CA5B0369A97F28FE122197B4C72014 1C1D6DBED5FB1D2CD524A99C64D532F25F6FCEDE22EC7F048E5DA26AC7D0ABD2 1328B289DAB11E4C39E5A7FBCCB52DABF0D77DED007B7F8E0274C7C56FC349FF EA4A23B62F9D89EC7E1AE3254D3208D806541477F324EBCEDE34A6B086F3D767 2FBB9045F10702251EFDCB2F11505CB36F4CA94FA85F47F152C7261D9A48AFF0 5F43DF3D8BCF89544C2EDDBB4AD2ADC8D00550BD7A804C3D4E5EAC6A3FE3EACB 60D54A37525993DA26CE1E71B59D77ED5ACF8D9D492643D120BCFD808C48D9E4 DE9794CADFF971D482F726C99375A04FFEA5869C73598A2537746863E2FF5E69 C1D5C2AADF0E96CC425558D27E9A29FC41DBE06B65AA7DA948B855FEB1A0C182 207B4077E7F5CCDD8248638BF9860F1FBC2111A7094D4580F5BAE7484DB497B0 BC605C6DB73D2F8CEE83C4997DECC46F1894AAE93F2905246DCCB66D7DE4B3EE 57CF0224CF7627CD31A1BF5DA887F72AD474C8BCB1BE3433079487426D714F89 3DC3E9CD1702891B290BFF56EEA49E4DD48C3717771B7BFC827B6AF4A539261E 2B719CA9D0A8380801C3F5791A377DA998C1BF4258C2EE59DDC293255F4898D0 E0010C61FD469683443AC8EAC74155D3FCE2A5FEC3BD8AFF49065930150D0AB4 682B86E95782D76238A0F9770DEBB0AC240B08BADCC5AC565D6B797CCC4D56EF 7077D6CE9AF19C52E999E081FACE576BE59CD1AE2493DD0DB31C419135FBA15C B515424C828D7FF50D459F7F24845FB5592140219EC645A2AE5884A19D67ABE5 DF02A203CE5C27438A50A697CD25C38E73040A66D8C9DBF9C6CC63FCB0FB3D09 79E9E80C058D7EE2A385BEA3AD351D8ED2526968ABD125D26941BFC0173EBA1B 36C2F94B72CE50231191A111046F04DA385EA2C3A8D022829EBE9E5A12CD151A C3C95FBB13CB7BF787892B15CF6BEBB1803C810C555FCE446C62BCF47B7334A9 0E96864158523C655807B81C8C85D8B72D427BE8B1DA9F8BE926D43EAFC8CF5B B9D2AC2D581A981DA012CBDE1112603C939C614E4466FDC826FD4BE4A6A6DEA9 BA0858E536EB2BC55919C67D4FA0636E06157A6922F35E217133CFBD3B808B7F 4F16B6369231CF78166A662448CFEA903AED4C63AFD716088B6E8F5CC8F5C4F2 692D3B063EFDC5E31F16B00810D129674A3CB185D00C68067D8A4653AB6DEA12 7D7CBB2D199BE7E826569CAB3523678EEF72061F79335DD1F37253386713905E 51F1283641C19F38720DE4734D2AC87C4524C537238F11FFF00797CE487BF4F8 467EC942952A39469F040FA091E314FAC9631C35722BF81A08623163ED2DB636 198B256DA0908E25B7D845C58094B9BB8CCBDF41828C578EAF501BBC100A43F6 4B86F61FF336486EDDE3DCAEC806327F932FD238AF7B0427FA8D1E070601822F 9F82AB994BBE77FD22040E1E404F7941B883140579B05DF2BCD673A5DF5E707F 165630A0CD0CE3857EC2F5AF334BF78BF1CB670D3C08B88D4B6B3362F50FF03E 479B228F502D3B21D24938917E0C0779B0B25F209C43DC8925E8FA899E7AEEA5 094C0856A5199BC810845EA03CA5164A60220D1ECC8866BD0B867FD8762BF2A2 1E9CA76103B19064CA769F3DF65A6CF556889624CE695D0D1DB483A0CACE7FA7 DABF7BE77380D2821B9BFF47A778EF5DB89C97B370FF6F83543FF7F8DE17FDEA 89CAA5FD789E686D99296F758B3F2C030C54DD76EB4273BDF9C6D0C639CD9335 FC9035E447BEA327BD3E7CADD2656C807368DFD911A447BB15D24042A123D483 71A82BF008A80763E09843ED94C83FEF6585E9A2D77C35381BD9C117A85C68BE 5A219BC17DFC77BCF3E5FE0E66F8E76BC68479419E8726457E7E9A12A7E4F36C 1731883C506BD906056F7D244B8A169979E4CA492FE7F82054B498E5227829F3 A87C9FFCB46A51D01D8D64C2789A0B08CB24197D740A75141703CA8DF65FE870 F554F63AA4F414F98F5EB617B2AEE29C11F01C2F392BC2E6B426010C43811038 1B7EE7748494BC33FF331AFFBAF4596F0BAECDB0319EB442C6D7F13B427D332F 52ADB1D583FA4D89D2EDD5640F536A583774FA05D913CEB2D229C60CCD45AEDB 1A6829D0984D6CEFA4CAF6B3ABFB7800FE9D5CEEA1E9E4845FA8910A7FD2DFE7 5E5B07482D91ACFB11C53552451527C9ADBE6F636E04F53974E31EA0F860D58C 88130003B2AFC887C132CDACFDFF0A7414A7A6AC1559A0A2C6D0FD881B06DCA5 48D41AC5E8DF18F9B67E5020841C8FDBA92AF916916AEFC3D0676AF33E04CE53 8F8C2147FFF2AFD2228CF7ACDE33C7B1C2F3E2C202FE87B5783487A3D071E450 C13E28929E219C2EAF776A906BF3F0BD12F216A4C861AAC23D94F97A4E4240F1 4BAA7DC6620F8AA1F6CA4B22F31275D704C7F11DEBDF6F3899F721F78882C530 0B9C5B0AFF25ACAC4F2C05776886D2993C2C9852070A485CCE7372DAC3BBB955 4D40796D093DC2ECFED304729B7D56FCBF12DD9B9E3153BB60780E85801AD450 8C8CC6516630D5D2399B255104A34CCD11E9A901D808B1EF323F8BA751F6F96A 4F8BFC3FFFE90166FACFBC056F00FED251B6CF7FA5DDC5CCA10A63970755A9A1 03406D8CCC5AD21EC0018A9E7C0DD859C281C425B2A01EEC518FF40C0E984199 32F3691D57DB28660649298CC84EFF31E437046643777DF4D82BE2EA43E46CFA D2CA217729977291BCD016C9D7C1EFC45EB7FABE348B161FE41251E3BBF936B9 A9336575410585ED1CA7178B32633139AD0DD0F364DDEE3C80F899F13A5C405C 3DD7BF3CA427B3D281DCA792B0554847A7573098333A4B7FB8E09989B350E97C 9549C3E3C65721497AB38FCD62855904DDB4B27952C374EFE0D948D905EBECDE 0761A0658830AE2C078975DE7F5247E977E01458910D1B656318F95C63475D4A 9B01F0CE00BD0856DF65EA549224DAD7190E0E2ACB9271723101F937518C09F8 44AD70E78ACE820B7AB6CFA00E3A558D83E1E2144212F5CF18AD1255FC795452 5E3C53FB83F41174869E0AB9A07C0AFF1412FDB8F016E6B1DA5504B4645B8EFA 701D1CDFA7100CF7607F9142E81053CE3AA731890F7278E69728C89FB9F140B9 061574873E7BC950B4FD27CC32A8043998D75CA967ABD0F1A218AD2CC8F57172 6B8D0812EEEBCADACEC955898F20A7B0143E2376B2BCE81E7B64290556155855 9F13A3B7A3212A5E5EB8BD69859C9D362AB4C04989D63D543D53B8C5132F7890 E350BCDD3ECC568A1999098FF975FAA15163B3769B8645363A50275D913B28AA 8F7191E2B97462889DF510CDE4EE309F16F083E5DA58CC904207A98B6F8A615C 5B0C60DF1E3AF537B2DBA25BDE00BA193B32531484F2FFE25EA1C586FBE47956 C456A0175F30D2585693E648E421FAF3745FE532C7A6A14935EFBEB54F2B0262 26B3D2429BCDBFBB2BF4BDBC8E4596F2A2E5F766C1169BD793B1F301389F36C3 0BA3A97B019EDC0712D301F44C8B3442208FF1FF81A494148A2FD4D2BA6AB21B F4CD27B606ED0F174DEA1E902A9C3E39F2BD4FE86DB1E35F8574C39F6F39B876 26EA056846D1E9A36DD8DAEDEF1A5E4CC33371F2BCA775B6CB9BAD9503F2CE70 97346240D95D5216E6AFC6058339943EF533BECD43926FE12C1270465CD98892 8E0F29F47E685AF910D49817A84D698F53FAFD127845D137C078374BB4F21526 C00498FD71A897DBA030864AA22CDA370B0E5D0A9166720B074EE0729E815FC7 D8CDC3D6EC5E76C7472A7CB2D31083DD1F59DD5650417FB79D3D2FB3E38FC82A 7A1149E6A39C0A5F19D7189490A4048E40A0BADDDA9974C32873E0DD6CFC6414 F933F76A67DCFD5E92980047FF18DCBCF16EF96A36CCCF22D075C9B21942A71A D554F268019F48E3519C953AB13949B74448452665257AC288F88A997761508E 8E97F94A431E8811260C6573D9641B9816B92A7FE36043C3E1717B5BEFECD0A1 51152979A54605B9C415F868DF4993905236C243E2DF460AFAE9E0CA4E2C7D8B C37F915F37B2E6A089AE3C05BDEF09ACCE70BD6C86E6300ACC56D898A09B412C 932C749D47DF16CDD337A931B41E51B6E119DC041DF735E6AA4E486EE826BE5C B8EF449F569415ACCA57CDFBE6F00DA1A82145BCE2F8747461A8B1EC4BD2B0D5 A4E818A3E25E64AC3521750EA70D861401E8205E2C291191C16473904C425793 9FE813AE893CF9DAF0DF56C0E6C31BB367C8324E3E47354813F5FBDDD61C9743 900008D87A6BF0C38CF56C87E22A7130021BE284535A18FF54E58EA96BDA27B8 BDE678D0712508C2777C2FCBE097F0142D6609FA4C66DE3D8525A28F6AEF5011 E6167706CCC81D3BEACF22FA47E6AD0AD501FE6AC5A7C546BBC7ECD3ACAF8D66 7E08559C07207D15E96E42A987D9EBB88EFC080F52A82C17AB3D09659FDB04A2 C952E4323E81B249BF28748A15B4C4914CB47EBCFFDD3CAB97C91905B65D66AF 2D54C1DB47E0626B18FD1499F69E993C22F24083D4A750EFC936175DC8DD9640 5C5046356C20AE3B80D7FEF2BAB8A8646E33CC376CD5CF0C64FBF9B98ADD5B0F 5E1E85028067A89DF272EC73D3678E98D32E7A4485C01C546FDD0F76404D2B0D 70D409FB486828864E87FD997E17250BCA8EA1675789EF9FF715390B5232FF20 F75571315347745931EFD45FE1EFFAFE7525FA6C5F3E2DDED8FAF25B918EAC25 B2049A501AAB579957D3E4F250FCB2A656ACF7EBDB75F878D7F72B79 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.0: CMBX12 003.002 %%Title: CMBX12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMBX12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMBX12 known{/CMBX12 findfont dup/UniqueID known{dup /UniqueID get 5000769 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMBX12 def /FontBBox {-53 -251 1139 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMBX12.) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2D43A151FEE81296FBE 0CF37DF6A338C826464BA5198991445EC4BE80971DB687336AE8F74B516E333D 2D8AB74D362C559AAE6ACFAE49AEEF4F52E28C869222C1301D041E7A0BC1B608 1BF728EF9E98F3A12EB2714E7F16B14E055FE1FA0EEFB058860ACADEDA9D0E4C 42E3C6F1E4869471BFAA3760175F3FBD842755A9D7847EBF605F18293B42F557 FBE2715002669091BB033E1AAD657532F34F7C66E4F04D63ABB07E6CB9D9AEAE 78EDE8B79DD9BC87A1FF445EAA05B5572BB880E69F4DE1F82D7F0E9980AB0C18 22C448B0B1722D3CC33C56FF287CECB80658B3AF5E7675BE82CEFF3DAD5942EE A03C955FF979E41E54BCFB5316A9AB8945C403A73180D0961416EC9C92F49811 4B91BC4C788392994587517718521E416D469F69952149FF7F9224377EBA1065 4A727BF806A112A7B45B0A1BA1D5A23683960575368D9EAC8C04753BF7465AF7 95F25C258C63E4FDFFD0B412FD381946AA38C0B961652BCEC30322C47BF4755D 9F91880688AF066E32FFB22E1A52DE741307AD3ED830D6BAA1D1F562919666DC 5E8FD9862AC8600B0AE0BC7FC779252AAC57248744ACC8A8AAFA836BCF09B0DF 9253DFBB1CB77EA8A59D42D1B18FF25E9AED72FA62FEC3F126F030F5D7DED9C3 CF60FE890BA4A48E39E687BFFAEAB96AE542A6387F6624486037C8924002A511 BEE5FBFD780AC1D4BEC3FBC47A930BAD0280D444259528B6C565DE11DE36BB65 9BADC55C1EDA1A80458E98896D782DFB5C137897419602809F9BF8CA39F00C68 EFB9E076FB324C2963F23CBFED28B9EF70EAA4E4B903225D1F199A7162AB239A D92D71C18B1B682D04C6A48926275BCB16D413B2A0E953E1257E0B12D8B717CE 2EC84CFBC046A4338A69F454A469B12118E562B4F56C5FFB3CA5D357513E6FFE 947A564B229C7FD873057D5C7CDF03E958294A1003B37D8DF565A70A00A3734B 0138AE5277D383D10C2BD853EF806D3CCDC47739F0E374A3DF3B63638B949ED6 4EC25869DC1C0B1F4DBDFFCC97382841D8F10F3635C792139A1EC462FDBA379C BE0990CA2E70FE73137AFBBF30CA54954D7E7377CC50BDD780DDD4C7FDC77AD2 F3EB1169F14A0041F18160F43C24FAF556DB5D621709FBC544CE55424F7446D4 6AC07A51C8CD5161AB0AD5084A96FB35D77F1CA155147DEF8D7A590EA6939514 D4A226588295CE0007BA8A550895511C8D80BBE5CDFB8A50D249C3BDCA974415 F5557914A9B805782F399E4078DDB6264F1A49A9A5BA45E284A5196E9828EBA8 481D357B8D9E6ECA631A6204439FDFACE7D7E6A2392726107CB7D2517CD19A24 FBE592C119626DB221BBB635B6EB84845C16A9585282E34958B961F4A543AF9D 419B6A9105BF185FC767712D923437BE08A9C0EB92AB6792DBDC671029B6FCA6 7F717FCE379C0F3B51C6CF042A762ED04898FBB4B0105C3C4ADDDC18C51BAA3B 70A93666669547081D9246732CFF74C83EE90DA17F5B4F8BAF47FE4D81590988 2858C9B96071341FA0A0D23BDD4947FC9BC2297913CFBD4FD6CA4303AB3179AE 0203F1BD502065F90CE9BEA3B52DAFE4A29446082EA0E6B1D7AF1F31D0AD02CC 9A7FACE2CA86E5FE0F6A425B28A5940ECA306891CECDB3CFC7A5BBC76B5D9E8A C754379ADE80B4D72CE493010317BF21A0CF4A0A55C1246218839DCA3F4D626D 1F4161D38F54AD5142C1CEE95C61D8BB10FAD4B772F4955777AFDE8AE5A837C2 A2BBB11D0BF5DA2E63D0B75ED421DBA9C789B281B01846B65DC572BA69591969 21265DB722AE86BD8CAA3D887C975A617ACEDDFB7AAB341F47532AC0F354A530 7662C089DA3939588774FFA16FC4A52555DED6D6F51DE718BF5F345C23C90198 17B77CB8B5D53A5CE7A79F3E286B6A59F3F6178AC8BF15C0A15C1A8A95D03B60 30EBE53DE328CE085CD9A1D49C69AA299C5B58B24334A546F6E274C1B534DC8F 3289553F560C2F81E413ADB92FA0E7DD1C2F39D5FD268EBA97AB7335ECF28257 96B4EADB7D0778706CB41C7E9C882760E7670936774A1088FFB2011115FDADB3 B69EBD5108760762521C25C968C3E282DC3400001AC8FB1EA27FF643E3025950 1D617BB8BB321281708E496277E11DD3AE0023DA9F25AD06B39C7CF527FED27B 57397E88D3DF70EE4FCCEFC8A0927D6B05517E571B3E70ECC99F3CBA32CCD4DE B8BF22626B6C94FE65598A88AB90D238461EBD9A098DADEA4091AF1CDD7560EC 8E1B9BC2321686E1759E6B8A270C8CB4A254F7368039602EAEAB86ED21CDED91 8F2DB9889F46981C494C7EAF5E819B91C129F0740B8002B510014985E5791F59 B16879CC6521D8E9F1C4C1890AC85A78022BE614BEFF318AB2616F0C3F02405E BB425D1555472A2642BA7686E431DC3FB8A1688B76660D9957C3FDE8D58109AC 21B1234C9DDF3F0FAF93BCF7B2F88A001F23162E1A13E5E9118D51B485B70A91 D0CBC39CF44413FD8686D9030782DAB58064F5B987E0402AF5B264B17BD31BD4 FDF63951BECD73ACA6138854EF35B062D01F33073850D9C09A818828C581241F A625AB3638081DD0F00F946BE5450D38489CECEA4E66B4D85CC8AE0157E2AEE4 A22A9313829F24D573101D84CC1784D1CED7DFAD5DD966601370C6CCBB723082 A86BBAF0A5D867D0D2E3CA16E14E5109A29EF02649C47E12E88B3B397D65CACA DEB9940B92100744D686066F8250FF30E5F13D81428EE238A2E4E07ACE0F5C38 7D79D4A336D0D26AF9C2B84088ED8ECDF94A1E3FADB45AFDAB46CAD6FF950B0F 07AA2CDF82374DA76C56D29C80138841EB13F0D02ADD32F88B23E282ECC845F9 BB9AAECE9CDC644AC2D49577A92307A83A99434F6493156DF25DBF0FCF2EC21E 8C50A312C3D19E0609C0038554CF4FEF3ACEB7A833FD54B06EF0D617C2971C89 E4C06075B09B84A4F78A82152B9A9C540B1D881313C2C74F20ED064A9606EC2C B56D7BB4797F1EEF4A9B13579CCF311FA4A4DFA62D80FDB7F535CC6526D1AAE5 45C008EAF024B48C377522F74D939A475970533E645B1BFA81997549AFF26F67 2AAE6C2EFA357DB3B525276EF330905688777057F4E4CBF584520A534A8587E5 5A8360891E75A15205E8ADAC4A4E5A6E27D0C4A7D492216E4BC023AB027F37AF A8DC7579BA50204D5F45A51460C5BD8A5A7F87668CA6451137F2F59E117BBE28 5C40820882A5546FA76F0CF49F8A6EC445F0647CC3227C400F56E7E9B84A6975 E85E243CC1666DBAFF4E07EEAF3AF71BDACB30DAEA792F2B8504CAB071544F01 5D66243D529C479D276FE22F7E275D9E7FA9C6EECA18716B2F213916E32C1D94 6E32397B41AC6779543218E506569E3544803BBF9B404A983EBA62A494187B30 8D3DFA4E1237A2E5E08224A60492C09ADAD8775B7CDB830520829BA164209ACB BCDEB2D574CEBFB7AE4BE72DF4EB1945FEF2458761AD8DCC0D378AEB7DA002C6 9C14A665DAAA532B0ABA98D7BFB5A6151FF6703385AF7AE8FD315A492FCCDBCB B825707F9566B3B4943A3C61C3DEFDC31A843A2D67AB06891F3E110DD8C73D3B B5E4151B51D9F13905D7D94DB9ABBFCAF35F43B6EEE256B1A80ED6D1739D8D5E 8C767F6F0E8704C5345D028A2A6DAFD9BB7AA048B8B895FE9423A7ACE858BADD 595CB074A128DAFE08FDFFD6BDAC0114159A702FDCBF8013804B0CAEAD7AF38E FAF086A3248AD4FCA1401A85AE2F72E3E6956DC0996FE8ADB18F89B14A208A15 13F81AF73D0DB72F78C4DA634ADE3C73756CAE6AF2E149C26316DFD93370BE1A FB4A79F77A67C07CB0A53C78367F21661D4AFE9E27328E077B522B50FD9AE2E3 DA087BE481515B5DD7BF894A96A84A6C78874100505B7DDE1D22EFCE8D58B3AB 313AB5495F72E2CA4E6AE22C0CB854302B9990372F1661D9F0A517F90686F248 C5643008B3D29F7296E5C8FD4049886662EFDD4106E17C879F5D41CE84F87E89 F6A3117C968B95A35940CC29C43E1E0DEF51C1E46B676301F40D59615C3F73DD DE37B72FF7105DB84227DA5241583272AB1C3CD97AE11C1EE98FFDB5E5F44844 8FC41BEA5C54B26341AFF6830D9D0A5A2901B0653D8BD0746838194D240FF753 E99750D3383373F453723D86BE97B571B8B84D8696089B5CFDD53E6C562A2197 A8C4FB0CC690C27761A816B441029D3D306245052E0C41B53025D8CB7267CFE3 C17FDFE348E765326F91AEB700CC49162DF748171214252CBC821493DD01AA20 417D66DF47EBEFFF3E9BB2B0A2BE7D9B8C68BD570FC2EB0FA54CECC318F04C43 19598BDE93F2F13DC7847354C99059AB20593EE51E94F9D4E9241869D605AAF4 9D9B5FD88C3798A039A67993C5EC68B6326B132E647F67EACCA7F7AE7F718D85 12666E90D7C73EF210E344964A38228B236679A2B18F5E081234CAA2458F8D83 3F0CA308D19663CB12EB904076EF88E556407C33C9380A6A3D68A9EFE65387C1 A1BCD2D26DFD2AC0881EC30E81C0A4E76C244A2BD822EE88C4A60B480D107E68 90E419A1F512E865BA922A7830909BC2611A80931CB2E9344529586726614D94 3AC5200FB9FF68AD9686506C5EFA8788C0AD0251AFE7F95E84683380CDB421C5 B1A783B6D5F3A6BD1BC1C14B363DB01C87C0796DCDD5BECF41A1A9F43183CF6B 82C2AE49F0BFDC5DEF7729F2E638EE6EA9E4D059EB9BB1B992AD8C82D501A550 1BF73CBBFE740179B54E193E84A55DCD61B343C1852780FFB44248FC9426AC94 AA2B3FE20FBA30F6C4D1E0FF3EDCDD8C0F57CCB50CDB0EFE2E04A8927E239C1D 9B026C7929BB48461D4D695FFC766C8A0E545B1BCC2AA068D1865333108E7985 2D93F9B00EA0A90939D0D3840D59B6CC0CE2C147B2E1A9A4F14270FE3ACF51D5 99F7349106165AD627CBBB0ABA01ECC6D3A14C1DC1ED23A9DB9865BB4396C51A 31ECD001EAC94B33C34E29C5611148EF3E55DD61813470B8F3CE32564C749414 3C93C77EA5A3538A0B5AE3FC4DA32813B06772E0E48E25BB39F3F6FDCC077E86 F86FA50E18FD19EB2F37311CE87F18F3BC85CE7FD71CA92D5C3264E34E04A2E5 70C79D99F54D6C6D9D527AE45EBB48411221134587D2253E7C8ED7658EDCA34E 5E768DD14E0200470F73C44D006CE8CB35DE1CA3EC10ADC668B0662A7774C891 84EC95A31DD872F0728D9F65CA80940080E04630BE4DEC77A2C49E3913C39978 BF145F8832AF2C4385EBCDB15F9D32C22CBA0CF950877717D6F1591D7C0B8047 8C9BFCB16AF7124ED83137695F3D69228DB633053208C29E0ABA1B06A7FB3EE7 5625CB44927E2DA6E038A6E62DEBDA2D96A03177982D8FA33BAAF4426E05F4B7 9C1748B3FF7691F9888E7FF864A10B9DF761A41E6B5CFAD2BDD7E1C4924AC97B F4B352705316DD1A58637CC12D71C18A5CA691AB2AA8F171590EC24582B1123E 94D4DC587D8F99E18A711776BF4013C96446BFECFEE4C809EA94B169088024DE 0CBD20199A915AA406F0BD5F3D63D1467C49B4691AEBBB35ED6624F2D7BB74BC E80FD92B9FD04DD9C2BE9B6FD29EC7EC07FAB447511C61DD299C783BC09AE2A4 7B3CBCA6A20C6631D06D0B2E2482A50612BB7C29B7E7D0A205EB0E8436702581 596BC996ABD58CD8D5BAAE4B1478195CAFF98FE0141287296C4EFB8D2E7A8442 F0A3AA9F9264329982532295A176BA1867EF732BBAC49AF485D9D0F7130F617E 7F7DEEF935874D55A22240F8EDE4F247D5F73481373A392D40A8076BD91079E1 1CE5998BA13D48D56B49A92B4A18430E316405D2E2E391B496A1934671FF1785 AF42BA3B2D14B8E04014437FD194455C50289DFBA61B5C377BCBDADA48E82DEE 4E70EF5E9DC03064907BCB8BE4D59DE069FB0C0CB140DA54708E630767313F9F 744594AD8A499CFEF733E640A11FD74E46A749F9C7D18D49251BF85C6EB4668D 67598C31A8F90922FEAEAD4B83B6E7184567DC798E4BA1C4C9B3461A478D63CA 054F13B502DACB674EB49D6BB935E5EC82BF99FDA7D47C581AD7F940DF4FC6FA 6C6D25D647033AC69505F0CAC58DE99087F365531A6283CB89CB644688963C3B 8B2203A94294E58739EF23C7803630A1F9121D62BE1977DE2F41687C8CAF87FE CBD7AD3B98E0D95C8C6E1A7CCB0E09465AA874DC90A0F5DB2C5E7C130297FD39 EFE63B0350B5139D09E6864D22C3F1150B29196E40EEF9723E71158B7ECFB8E4 C426FEDCD439420B7F1C251FADA347C9A2C49738B5A17922E1EA93CA7B125B76 57449EAA9C1D591CAD327D0E98EF2D44D614EE9ED49DD31ACAC0B956620B6BA5 5BF6D08CA7541059D5ED2EF00AE2EE95488F5645BF6837D9241C0D3959B7580F C9ECB2BCF3E65C07D52EC9CFB21C11CD4C883E44C173214C900C44D2E1E43DD1 CE8DFE3DA93C38B548BC4EC46FF91F30CFB97525E1FD4E77686433B20BABF8D2 848C1CDF1BCF185CFD7A81D2D4BB826E837E2AF35CFC4F419F698DB0C43E9F9C B0FB628AC9A3CBE9B1FF4A067016E70333E78B32AB2D89C483834B31F5808FDB 77492E099F1504DABCA5722C7860CDCEDB2DDEB512FFCC7D287F4945FD711F28 87BC3D36173566B81FC2C1290C717A09697DAC6072408E20926D39270121CE58 3EF97CE12EDD7F87F2C8CFE36C3C0400869C0D813B71C425343EE0CDF717BDD8 409D5297D0F8F7FDEB0257C0A391F5635E0DB1116058942FF3E7C94D5F2873A7 A3B0ADAFC3835AF2BE474E6741319BC6695FB37F59AEE388F81F6E66F910000B 72E6BA7531B4378CEFEEDC79CCF4947BA1703823B5AB4F4AD73D9615C66C489D 99D68E49C9BF765B7FC547BAB9640D51D5A7A2396507AB5A4DFF3D14F52422CD 8FCFEAA06A56C6C7FFCD29C9A7A59DDD2A909A9363FE5F1E9629616D25ED38CB E754C059E4379318CC491C3B1A90128693AC53F80F8210FAEA7EE638902A7D3C 82B95B3F5AE340EC1B648DBB9FB679D6E80B7F426D8671FE7136D97F51E2D2F3 C9CE9183E4061CA40091A2A70DBB9ECBB19CE3F65ADD0FB346B54BAB182E2CD0 EAF4C0F402C25573FB344EA771B297BEB615FCD0595172E84ED2A62FF8962634 23C19076C2A9ECEED5135994EB397303A9619C76DC55E032DA83FBA441BD484A 59F70A5110A8927F6239A14D4E223E189A5462E4A92EAEFFA4B961A2A32B320F C2B4E8C1821FA67A655B5042C15E4DE1FB3652B55078DB123573C4E986B19DB0 1C5131F3DFAB271C30A5476B4A19D8FC922E31879C34BAED94C07A4841B8209C 403369FB8E842610D1EB4662B6171A4465FD0E819964F62EC5B0ADC92F08CF90 1DE0B410FFBAD16F6D355E8AD72CCF67961EDB6CDA82398021007C2D0462E893 75EB0710AE4A6CDD15077C9DEFC5774EF4A657734D703CE42174259B58E5277E 0DF26BF59AF8D1A3E7DC12E3C12AA4B67CF35B19962F6950C2020B698D971B35 82FF84E72F72FBB0C54A112BADBAE6C4CAA358BDE6A705AB59332C3850CA3D25 C7564499BC1319121CE0D93218210C68080AFF33420E3CB3A48BF9EB66BC07C8 A79D8CD8E78C200FF7CFA3DAED0B9E87E6141C88B436D8FCBA50AC195FCBB9BC 9512B95FE3A37FFAAB39850FCEBD4D50A243EA416E73F53B4B00F3B6EAE0CA06 0693AFFEF215D00BFCAD02E45496D7C8F5E99EB9096FC4300D038C1AFD31EC4C 5ACA6B72C1BE7204E37A4CBBCB1EC26AB87F2FF82DE20601025169A5FBD2D060 62B5B2DBC288C79C33B596832AA18D730AD572C6EDFABCBD36DEA87C0F323C3D 6E537AD3B43C6F3A905597570A8C6B0B4A5E08C08EAFF9731E745F2BA8ED0C0E 1ADF7821CFCD4E38F3F4C243CAD31D9F8FC68B9043740852B4CCBDD37BF728E5 648215961FA82A0C847ADCC5187331D0863A4573BE520C02CAE14AED4F06B3F1 FB4A318AB54CD86DEC824707B29F858FD726A167F2333855C0575EAF4EBEA0B6 754B1775F967140641FC06F82B191244186FF347A351FBD8FA62E8C978B21F6A E124929876488AFA97FAD1A68A0C3496BCA768F4AF8016D7A65BBA3AAFD7F5FE E75FE714FFF3D54D09C9747ACA01CEFD260985C6E87477C9C7843343C7E9E3F4 0537D461EF019E046DB8A6F08DC7B007337B688E610C55A35496196C01E6F8C3 C7ACEA49F6AFA7FD9CC809E9916813F64BB5704664DD21422F8F32477EB874E4 D86593B4D4050C116B8861EFDC6BE1ABCBF942F0BBBF4E4241C418DD1263F252 B16F904E5B650CFC5763390916625B28ECE4C39C55CA937E28093E66A9837BBD 98666F090E8E06F1934736F800CDD0E78706E3F1CE6D2EE55CC48D1302770DDB A139EEEFCF8353D4473D89EAD552B810E0F1737A6636D15265E0FA2699BA04F5 2CE3D02727B4A66137C2C074C9858FCB9B06A9EE669FD1178067FA9D85C9CB04 14FAFBA40AB77645D00ADCEE277F011A5E886E7C7CF2E2432A651867549E25B6 E0DA6FFE0F5EACC8BCD48526BA17221EAEFF14E706659482333C68E66FCEFC2D 945BE2F64734419B4B5B233184DC3D3DB275D097D34A58DAEE5F3D174B36B094 85A0437DA0D00DC95090CE531DB1344024273F9A2435F36FD0326B554B3FB1AD A38E82E43D3D6B1540E67EB20A97E7409AB7CA2FACF9877F22AEA53B4D2C3CB2 69933A6BF33E7A2C84745FCACE2017C95204C9230B383D6B24707FA0CC2DDD86 B8DB5218F20EBF95FA203E3C1E084F9FAB2ED40D31E3B26D7437365ACF4739DC 5F85781CFC2FEB6A67C0B2DAA2C780921D5ED3F2E706E1DAB2AB5958D1A3190F 9C60BE732222CE992A89184231D0D86CDDE024CD77B71A8971D439EA47A344A8 85AB2BE014A66F045D9B46D72880716E925D1EADA7D107CCC0DC489D1799B6EC F88F5BA0087D32BAF62299803498F475356474A21FABD36D0D0E40868C49E638 A35E375E28D44E06D90162FAFC98DE2EA17166ADC7571C7B2B66251A6294EAE9 1B8B3028103718BB60A09CF6B5B60956A3CABDEFD78069489FA1F43C51EE0447 A6A0569DF666889D9C69E8B5E9F35D81498ABEADFC0F01E0C745720A473131B2 7C55EBB2A773823AF7127AA81C0F7A776884BA075A2460D0767789F5E4A4714E 39D5A1955DAA03CEDBC5AF8A1AF8CC99C0511040CC0D0D571E30B461C313DE40 ACC7C6536D5D32E7A0002DF52F555F8257E0CF00AF2F97B285CBFF920DE6E737 051C55625AD12D06651D0682D5DBF2F4B96EA0999D027D19D9E8C29C2BD222AC 3F7419450287D7B5C97A66143F6AC6542252F2B9E896549C80ACA384169F0F72 FEA5F35E03CD2475E31C4067DF5CDB18158C7915CC321E58BEC4AD86154558D8 E4DC400252B20E3F3E62D0E9C4D50503D2C58D661B0F0CB9B06B02FC0FE4EC0B 42E9A539A05A2D7031E404AAFA86D9A7AAEE57A2A359D5A431139FC7912B89AC FEA1B03E56B0669F8F3786E0D05A732085FFE8E74B631F40083B8B89D3A7D835 6A5AF9A4B801F953F7208787C42C82C16861918E0B3506CAD6E675EF2899769B 0927CB347A56D26488CF2354A70466FB24A516A3CF7B367F83223D84D7F01933 993EBF0E8F6D3B3D166C20D702C5FBBEB68CD71F1ADB13503F0A034F222D3C44 CBE4414509E6DBDCB7E9B31101E00667D88C9CB76B4DDCE39F3E5908BFB39AA4 9CD99C766B6AE6203F9996BBC7E9207F44C420A6F155CD66211D93886CA31648 F3E80D344B5FA96B74048C3467988F5D6CA1373960359425968AE53D96D504BF BB0FA3D22DB7BB7E47EA7CF33DB1E9FD0F8660466F72793270A5CD65F4FCBA35 B386E88B724C9A926D823D7F98A0BC36D7475E8334C7D75B57F082EF2D1E747F 29E256F974A3DC142CD32194D03E6D76E82A6E7C2151F8F637952C034E7C7FF6 9DAB764D52A24A1A405E816B53975DE902383E1184966CC56D94E9322085C8DF BF4DE55A0B6328A458580980EC2C74F5678C5C652F531B7273B8706DB863C057 91D66907DD4F2DA8055208046BADE0A44E7D26F36BB89091A95EE18BE89BEAB3 FFA1CEA79C59CA85C113BBBFE3F1092BA3F5B94FC6D14AB51F7B70F09F1693D4 F7CD40281BE53E7ED5B36C3AD33E1B31E92C89A8D90BECB5CF73F4372867A63C 38D5B24C7AC47C45837634C0EDE9C4575693F826F53AF8531E533B1A4E494A63 D6DCAF1446F54C82961CFB98AB72117E9D0B57CBC254FB02D65C43927199287A 4FECCBB1989158A0BAFA1F6738750F255E158711DB24978A4C8BA835512AA0C6 108A4C47433A70F0823D4DD165CE4103019F381DDEE8127D1AC75368D118ACB6 CF340F59F9D31A2D8FF25955C9CC48F763359CA264FC96B075B33FF002FD11B1 BCB3CC7B0827B387623B54B21F508D59F581EEB3DAED3110CA3271A30ED5BC95 2B75169E35B7EDC21772506294F6C4B81B54E5910942FF36D92655DF27159B90 81FC64854BFBE265A9D5D4DB8B5714A12E297CBB42A1EE12032E12EA7831B44E A689536D51AE0E1ED55B70BC00797D5394372B5B6C342A30F4B9A88EEACBE203 B6AA13E118454D3596BCBD4538E59105189BBB63345CDAEADD61F10707492EA3 BFD28C0F0689EB4C4075FD018FE99AB4E5B8053204EAF7B52B59713BBC64FAC3 D02536D3E35B88C0150189992FAA4A22954C90F0476314308994E7EB7130D84E 4110E6317A93D862F2CA67A8DFFF49F9C0ABB8C33D3A49D6D436D9D853EEF72C 9C25DF16BA4EB748DDEABF04C6DBFC384ABED4453E7F3E886537FDBBFD359098 68A652C28E336A248A36422238D350F86FA328369CB9E3FDB79469F70901FDC3 2C7E605A81197EFB62AB21CFF008E1BD3221FF7868248044A39EB5809DE0C59B 99B9F2BBE46440866C5047557F3248EF0E045FACDBFC4040A3686EED2824C998 1B8471A58FE24FC37A8ABDE457922CB775F348AB4A5A797E87B93D5E8F86C12A 54EFA4A7E3410E1DBB3189B16E5AA18733C32ADC61EF6AA4528D02CF8F933ED9 58D3C0E6C6C3C349A1EA0C2CF8B969F6A5578D4E15B53F419AE0398810CC4C54 FBEF3D6AD0AB24B6286B3763E9F27797F32C1C7F201D28778B4D79E33E4F0D15 CEDD01628C100D2BE27834C1AC19BE9AAF9292CF9246E13128FB2085AA3906B7 AA716D606D811EFC061643BA71993D110DFBE5A472B1BEDC9D70F9E2E67B9AB8 F7993578454C5FCB3269E065AD66167E95E9DC8F503BE6FF3FF70D9FEDF0E4A1 A01F2AA0F25E684510704E73333E8D59E5D869CD5DB9865B25AE17554CDA8062 562A47057925DEE742311FE4BE2626D1A7C597910AF3B70AE2756DCBEF452FD8 C4A4108223A6FD9A222909AAD466981E839223FBCBCA5495CBBD5A9235FC4A4F C061E6CBBE25321F3D02358B39AFDD92651373EECD368335A1F37653A138FC84 162669220700D8B560CBA3B9F89C95BF06B842E9F6B753F61486875EBCF7BF2C 7388FD0AD9DD182C293A00CAB24E72FA5EF90F0272C951DAE63E70BA09537AE7 FE68C6B98BEB1830624440DA215786B56F61FD92F5323C48054E47E3340527D1 DBB83DE31CB28BD997D0E63749146B1C2412CDAAF4C4CB3B8B9D663838CF112B 1468671A0B11615CEC1E0DCD65751E41B4231DE7A612F442734CCA51017ABB77 AE2E38A88D50818AF69716569FBC0138449B3D6F4DA80D6A4857FE84968A3841 CB35F49FFBDBF88F41990C98FFEAF4261EAEC23551CC754C85225A1CF8584AFB 3B6765E9959656F1A784A3120556A56563B4E5CC0FC6C00EA2C46E661FDA6FCC 56FEFC379B4B36C42EDD8F0D25B5D8CCB0E3FB5C99C8689CB2802036294C55F9 AEF9796BBF9F925939C1CF46C86C41EDA1D8C36F65D75C8D00719A783B5954FC 36AE64F531C9BF1C472836D51387F5687EA431869433842ADA68D0DC2FA24A77 59C0C49574EDC6B53DB6E12B7D7D9D1CC471D0B9853AECB584E75C40E99DADAB ABE058EAB8100F629AF59281F5D884990D2371EB1CDCDC00B46AB32EB5BBB301 E5BF28539D7474DD1D37E1547AC6DBE0928CB2F8345E659754BD51C3AF5FEE15 7C3E963D634BC7FC21BF7B5CB5F0CB273FE82F5681E81A1687F28D1403EC85D4 349250F4D69C9FC376875DD2FD4CE1D5F275002B97C55151F20BA162FF007223 A3DE99A5B51060ED8172A49B2CF548E1918C7D0191C001141FEE64D3BAF67A2A 1B5476B6BDB121EE863A655072248E99459975768D146F2D8D7321F9A64131A6 CA8473712F70ACF347522E8D21AD027C11AA42CE9CDAA2BCFA9ED5CADF9A1648 7327DC3C1566EB2F25F0C21F1B6D63919DB6A80211C559EE723B8B8CDCC905AB FD7F3E83BB83D2CBEEDEB02C81C5A04DC66B00FF724CFFE941077945A9E1C536 0E96FE72862D6495BF27CA0415EEFB677959F00C256EA5863E83B2A5FB18183C B498CDE6A3BA4BB60A727BEBD800E2A40078291DDA7B3B637ECD67AF123E188B 2BA400F311F7BD2E857FF045BE283478BD103041561B4D3A610462CF3449E13C E84CF455D370575572678B29F41752AE89831F9385B2BAC74A2E58E921A53EF8 3B9235D6EE560D3C7D771529EA818E40527C36448C09073A73F51FC784F88177 C6D5B5AFB0FF137F1D5BE1F8E81F82A520639E9712B73EAC440938FDC16D0988 D7FB1695B5840F6F35135A81932AEB27C4F4E571A61D597F8CA417226F2E9FC7 A640639109AB9F8A0388ED9D2B2C80A33EC32B59D9BDA484D201388D9EA03A62 04B1298BAF98B37666E1FEA3C4EB185EAB68D5B2DF6B6300338AC419A70C352D CBD07B10B1DECD2A79F061C19444C3B828C1366D1E29A726D05797EC265F7CC3 26BF389AB365E2643B2D3359514B48EB259C4A6D0CFAA8BDA8A24A0BF6F1B81E 2E2EB787845526CF835F99087A6B579A562498127C1E49D036887385D4024F18 03C769B00C5DC1099A33446FC9D29B92002977D23C7BA31C2A7270BDDE64F690 4DBFC721E3FDD4354BEE8A0FBB6E2BF11AD20474E6CD62B8F780B4C1C2EB9CDC 6571E3C1D4269EF71AEDE942F7F543F69B881D92FE99CC40037D8A445193490C 82B5012ABFF56ABA917802DADF0291150EBFB1617446A540941D7F7C225827FE 9140DDCCC943FD94CA72A3DA706047B9404292FA5AA7C6EC76FC93A082BC5DE6 06EC9D22524256B6A1D5384ADC5C517F0E539B95D98C596FC8F4FEB2C582B87A 593823D9DC872037EC919FBCD1AC6CF1B975B20D6E911A2E54B7E1D0111CFFF0 508CF98E31F38FF180298C6165C774AA8B790711A4F1D89AE5EDDA73F9F5331E 4A84B25452DBBD16E80237ECB49E7EC5D7E373B211E9E6480733EFB093995856 E9660A8B28CFC5650C075A1FE0C3B50B8E7212C7BDF4AC84CC38B73959CD6365 518548929AD9590CC9C45852417BF8AF2598DA89B3946AC44216A9FF41C8667A E7203D5C4A6BC2527C223BFAC13278D013A364B17B4C8EF8088B96FE8AA07C0D 1F11372130109B521BE08A44B91CF77CC75A318BBDA5812A2EE35A06A3FDEEFF AAB52D112BF1D26F128626FB6E6618473689584871CD7B22707E9884A1D5B48D 213C5086B9261F589E9659EEBD74CCA2B9BFB1232DEF37336AFA5AC56978AD10 A8DA769D4A0C6E0D261AB9F326CBC50B5E828AB8A17DB154E874723FFE2F51C5 373E76253BA4F45DF19AF54BE2AA35539159FD5B79EEEEEA1FD8DE3A9022C068 D4FD720775A2C5AF8C853FB08F688B57B1460927CA7D3B763851F6B6A007DAA5 9DC0D0A25218A0F2C2A2602595C009D8949985AF80C083F5DFEBA569DA23A7F7 06A9D207CB920F57CCE183BFE6144C367D545BC984701A866960F4A5690F5A4F DBE4B4EBA241AF941EBC9E41BCAC4AB5659FDDE4A3BB131312E6D3484A4FF8B8 B5E3B0189FFC37FE4A0723020180F2197A5002738F234E383F2B20B66910BB02 03E8975DA320BDC4A7DEAB908B294B466FF2923C7115B8D2EDB318B40E896044 95ABE4813FB12C9418D5014EB4569287B8CD08F06637882EE3CF2E5FAEE0E709 62C81C1FBBBDD615E44CCEC58A810703AE8DB9BC0B0FCBEE64907DE1EF9EABF1 1CE334E64A048D92576382E3C229B980D3A8F031719BA4ADAC09C21829CF93A8 515203A07C2AC85EFC67E0F1938F7B83FE35F8450F276680D631E025B91B45E6 CDFE5EB3109915C4D3E52088C3DC8030AD2427CDEBAAAC19E821856C995B9285 C287B1F8E07B3A2C95737E28F433B3EB16B85DE26C2658C821479E1ECC298015 FAA546328937239A2191405579CE080B22CA96E5599FC0DA8EC0F3B37ABF0EE1 DD1915BAF9D53A2FD969B0353ACDECB5232A9E31AA24E9CCD3C543BD2DEBC642 C8973EC0C50BF6E1184AF1B056BBEB6B2A57C31CFE46CFCA2D91BE7DA76E01AC B8D6D5B8D19754C451611C9A80D5BB3D23A6D6F04D113D005D9292B21E764EBF 83D739141DF5256459289B99AB01DE0BFFC79630B044D664D123FA1599C43A32 7E9E396B46D667F554A4F89C44883B61BF3D8D1993C45D79780EC2EA47539EC4 CCE9690F901A50B844417ED6581CDD8EC4A20FF50F6DD3EAB642DF7746E791BC 7B73A20892CCB998CD6CC090BDE0F63D1B046CF2EEAC42DAF62B050C0A2C58FC 3B24960AD4226A4B5067934219BE58005C628F18390FC12550993750A5915F6E 9FCD54A8B130AA13A5FDBFE775F6B48D1FE672B4CB5C3A88B2D9913DDC083ECF 6BABCAED2AE09E4EBB0C127C099F915494213CAFE7FB86EB63B0078175B0DEBB BED4B09B739780E9C9F8EAE3FDA3828ADCDACCFCBDB18524CC3D10E7008FF502 ACA74DD1DE021E67D65110E20DEE68F89752C91A497D061384AAD49CAAEC816C B1A4B9DA93A0EB57B062E8DD9DBD7F2F6E16DEC412F38AA4B19DF06F4B2927DC 82FCEE882F0D603279EACC9F56B96E8189F06D5CB85DF66DF9164D8F4D321F2F 83ED0CAA62E069A43519C7A9A09F37AA76794140CE04960E6059F6BE2651F706 D56BB531BD642C43FB5AF96858CC7A67B687C649B74D5980697649585A288237 FC97AABCC5302C0D977465F61DDD4FD826B10CC459BED21C3D915DFEB552712A A979AE8A6642476E7A0F88413453FB921EC002C86720FD62D4207953577C882D 5D1428BBE9B513D171E50DA2646B40C512BF9AFB028A68EE4F9C9D1C06428F9A 11858B7BB4CF9D181B1FC0ACF5E5B9646CCF5904C4B86EBFD1FC5F9E12CA5C26 585CA657D34E93D64B5A53DD846D458D26DD1FAB7B23B3DFDED56C921D1E906E 1021C93979D42336C3900672C2B04B8A2624F15B93CA7CBA94CE306D6EF45FCB 0E8ADAA16E22D8C50A6FBDCE1036C4BDA0ACD256DCA1011BC20B0D3E240EB4FA F216166BE301CEF730706E45E8E6A3EC346131DFA897FB55B8898D6C48BC49E8 F0B3ED1F5E7831A2DD2A3CB9171A58BA5F88384D27456AFC8E79B3B0172793A3 5A3CF51B5CA21252C5C5DB2CFF832FC9CE4BBF22641B59D6D3F3FD9A6E64DF86 75F8F28C17744945EABB7A1644586449F14C0B09D036CE60E0F2EC8AC51617B0 95EF1BDA930F2D179F8CD34D8FD61B33D90A9769779067B38510F45873E2C874 A387E97971845E2F442C3D9BA206595009C6881053D303F3A00FBEE07D9A23B8 556586598F509A3DF054FE77C25FCA9C6454E5DD0B0D796873B148D5F581A176 0B8487951F49013BEA9FFA16A072946F13CBC4430967741F4ECD06CAEDDA8889 AFD705BC587826D7F1CC662904CEA2D724322D81B8A8BF88791206BF4BA89441 6FF682C3EEEB22853587D6558C9CCD568B552A10B512D5EF118DD5FBE94E4463 EE476534600A8799DE90F3DD1689B2A601F5E88A4B77FF83BA8DAE8709BD4218 1568A10B536F6875837B2BB4511DCA237FC8EC74403D883326C8F1A8786E8F16 64D742FEA43F36242DA81CB494369CF7D8F69723CBC7BDFF287741596DD26D56 58A7FCCA56F4E84FC0AAB8147BA66F9C98B2734B791E0BBA5FFF10CBF56609A6 8F4275FE8C0961232FB6C51C0D1F8A6206CDA3FE159E501574132789E04B9DAA 9A84D052015C8D77B50CC3F9071E408AD290A34B2C9C7A3854210DA6C34F254C D48AE4A44C5D5C9B20E73ABE13D03320EBDCA2AD9C5054FED8A4C7A122C02044 E7919853A4FB21A6527231436BE769CB695EBF2BC0327B23A01CF039DFF41F18 BA5D458D000894CE80890815D8F8CD841A024756266D700DBD7DB71D59A65B09 6A027263819E80AE155B2A792361B6E398A6DABAA53469AC988FF0B0214BCE0E 6A5FEB06660A119E286225A20062EE28AB515135A84526A896DC125456294C11 4C3BC08FA1E563B9358E3145B3CB41885F7B9A48C871A9205A41EF8153D9BE77 5D7A8C4EDB996E3A15CBBF5B9B8C50FB3C2A23E06C16C2E98B8CD5D34D59C088 7F14616BF270985463FBF59775E327A3E8C04D410B8C2411D2B24B4B76C98C59 58730D6106E02AA0ED44E1010AA5283AA54FFEF9A1BB68AA5C805A1C78CBC31D 2D34D695B9D8F6DE93EB6E0F10158E735CD0E6DC2E89A295A166ADE734A04D88 B3B87C8120B0371B41D89226D1AF2F04C4AA12673789EBA451B36F754534463F 25D7CB282365ED5F3AF9792C4E65900C23A6B31DCB3322DF2CB3C4CECEBD0A35 05C414DD4E19C454F4B37F261F130290607F292FFFF4B7CEC75616450D4EA534 D9707676F910AA9AF13D99F061D843F93BDA4B9AE03A4B8BBA9B414A251DD6D7 A852A7E27B02A7419703CD2E6F1E3874B88987708CE7F390B2FEBBF999D26539 809768C989C198FD5E166327861B13AAAFD4C5F113C5EEFE2F2EDECBC5E53101 0B935DA530F570DD3FA78CF3BF7AFA77968C4B1D0991B46AF2F6ABDC2CA6B9D0 8DE830B6273A185BDC197EA627089D71EA1BA1323550254ECE807F8CF2E1329D FC155B45B59AA3F2BBDFABE575217F423494A676CEF94EA11BFDCE72F74FBA29 F478C8D02FD4BC5FBA21C7D3A007648467389FEA7D020BA8D6ED4AF570360ED2 82FBE4B0D53FDD06DCAB5D5F01BD0B608362E30F2B9C150345857C06246150CB 18A538ABBFD6E42362F9B45DF5B3EB8BEBEFA61BA82047BD968088D95A86CE60 60519B5FDC433BC8B9D4A6A197AF4911FE35E5CB2709D534CF9D338BC64E56C0 177F1B609002AA8B4DB1776AE0A8A62572DF1B98EC8114AC2260036A41AF02CE CC121A1FCFF525D1555EB4AB02573700EE03EAE32FF7152363682C26B2D94155 A2E471DCA8857A1A630065F8F4BB75DCDE79F3C3FD56929549ADE0012CB9596A 29039ACE95C1D431CB981536BDD77ED295EAD4A486386243CF5D6BDDBE62ED88 A912BED3BBBA140880B19D99FA350CE01E6EE53BD1AA263098B76DFF94F4F7B4 5C00A80839805180444A1CDCF5A561849F58C9BE1003A3B51F602C9BCAF633E3 B28416242B1E7D4965D11B99A8D0E370C5651675F8CF6F36F254F8BB27703842 5BAD6E9AFFD59451AA18E834FE353FB581BBD1EC3DB769AC7C1EAF4730C6A5CA 5BA380E7BB6F1AE51736E16213A7365DB4BC88608B845805C397B926D8CE41F4 55CE512214891704B953D0C4FE55410F951FA599E7A07D68042592DB3571760B 9934FE4FC64680A33D40340DD11FDB7683D22180A7E564A2430D8B218FF77AF3 50A58FCBE0D0E6218801EA517FD1020207318A51E85B0D78BB0ACFD15BEE2851 40160E05D0FDA677BB43D662DCE9410FCFC0F510144D87E12ECA850D396AB703 B3FA7BF6ECABDA802A18B23DCE287CD844C308A2C88AD5F39EF9CF47E78AAD5C EBE220C64405C2D8F6FEE3196D67A920FF3511380ED2830EB4C5D094FCEB4EA2 9945C29F6B9189E3CB3BE64555B36CDA01005435EC1A9C512F18FFF4057E5C52 45C906A3037B8A983233C3D3E7D18BD7CD2AD2FED9BDA402D7597C697DFD1146 ED8CFB9C05E077D01D4EFE26A1601880BB0DC889E820321A313EAEE4171693EF 2A317C6D51539F097376A8A6DF0A960658E525BAE9BED1137CFD0D984C15C2D4 59002A142641ACF554D1A58B2DDDD885F1E8FECD5E34FA2B8FB1B86E9D154648 8B7E05AB0C3CD6B5BC0A7DFC21CC07E0C32FB85D84889E5D20CBE36EAA91A458 F539B7A2C4BA66790300F7C9A54C7CCB0C5B3B8103D7569B7A97682F88A4D249 7AD44F1AF19CA9E535D63E0FDDE3567D4190225826879150A78EAE095D9DA739 83A3750AD778618242A9E025AB29CF4030A7C4D5947F3747A8A3FBF3C2B2752C D78AB22255FAFC66EACC985BE2AA8AFF53E537515580E55B9070AEA104F1DFCC 0578C3210743B6027E1C11655F31052D3860817B8898CF81EA1D36D2023B58F5 237BB7C7B7C58C87698CEFD85CA1D5F93C7C802CC3988158B3B6BE5D9D5C87DE 3E451BB6B6BD57A0E0A92AAC57C307953F28ABF4C28D58F8ED6EC3D1D092BB27 9A44501C27C80BF2FF97B22E9CB0B3C1B5F1A80E78C7D315252DFEABDFDCE703 A412C8C9C85E346AD0BCB540FF5D87833E68CD941D47B763C624A5221B5327B0 E897351A5F65D074CC584C1C51794672AB55902314A17FB2556C664E438C19E8 3B1253399A8F3295DA212864B45996FFEFCA19DF66CB663B354470B5A670345E FD3F83C11EB83F78A7A28126DC64FE9B6F4BF31F625AA79669B0A9D365F2F837 D9C6A3B474210A0C82F54F627AACB989416E6AA9FABD193A8B929FF571AA603E 48273E8AC43C1D3D5D120552DB49DD5235875656EBA4FD4EED8B003CB0977418 30A3EFB2A357ED091EB552433721BF97D46293861670A577F59E8877E434AAFE 3F97200AE924775E3EC9CA761EE33BE85179C93D1ABD400B985ED4E6213A0448 B109C167157605548C14F906F98BC7B927B04E127D8B0ADCE344874CD6A24C78 2DDC0930594092197D5A4DAB064FBB08C68C542B790CFEFF9F4D79EE607F4207 FA53868F302DD609331F4CE448CEDE1C98C20D920CBF73F9941F52BF911FC935 BD7D773F4D177047068B69BE03F1F0BEB3AE8EB8650E657D9EF19AC35D6C815E 870E73DD910BE853BD6A992F138F492950BA040E1A6018BD1A2CB7AA08CAAAF9 F0DD3E07E4B79792A04A4332AE7D03BC19708863892E08C0E1C63F07B9BAD1BA 9A50582E200FDB0C6E93E65F2ABB91DB5B6314932394161816A7DFB8C530619C 13856E232756B8BC7A74581C050AD9E429F995989D84BF01097A189FCE99BE4D FE68BC922E76D4B2CB5DB693F5128297018FCF735C5F474CAD251B51E9CF4438 6DFF6311B636022BF8B77971995E3ECC74026C87D58DB9C72D758CCA71661509 C5870981E6B746850A1CC7E1EB73071EF8F29E953E7CE9FFC00E147BC5327169 8A2F9E19E120038321271AF0D697BBA78DDC61EC0848F9898E4BC02FDACC4D71 519E0417C847D01AC930C6B4CE292BE655116BF55271E310757F7FCA1AB209D3 8DD38B08E987EDA95D847EBE2D32304476EBDA0378C7038B1E9DC7DC5093A966 A82C89C0D1B460EEB08E3F6D3D95E24B9D043A9914D7D01045A5FD58CE26E4FF 87A84E0F9E8D10517D907648A66493682EFCC62BA6A62433999E987B1F8E7C1D 5CB1187C852402AAEA6ADB3B0AA43F17BC3099B5C764AB2F17D4ECC434F7058C 94E86DDED33EEFB1D1DFE2D3F725F8051F687EE44952D0872A2DB2E08BA576E8 0D39CCCCD81D28BEDE22CD982FAE7BAAE2A0DFFD5DC93231F7E98AD5CF6ADCB1 59F657FF4D70D7C7128BB9030292A696467698D0FA1337F496EE5019564A7C7E C36122245FDCC748D8B45314279A63EBF27F20B6982E85C4E6185AFA995760AF 75C88B0D89A6EC77F1B15EB623A1E1F73F925E5DFD91343938AB2DE907DF4CB2 B063B72A235D24D985497342656E48CDFB0CD254ADFA05503E20E550B2318251 2D0BCDD68C7EA4E129907B0D7353692E8FCE296CCCFA2EE7A699F0373AB9BD7C A95DCA5516FAD517F19A518CEBF98E8EF876D73AB1650FE77D03691D05183229 87A88585DFBD317CD65B2686683DBF4A1961F2A31819B243BED008541A6D7F7A 0027FC303202A3EE7F7D0E45BFB48364FE411BCA5B5999DD3A19EBFAD94B00FC 1779555E182D34011D02314ADEF66DCFCFFDD84F53C7151DF8458F9A3B619E8A 9737FDE81E2389314828BA0C78793A67B242CB084D63BF187D8A93FE3A0DCF4F C27111BBDA4D80A8A9F5240391E6E5C67E120FF879A9BB5842FCD41DA2F2599A 8E9E9CA33A437D16E7B49F024035B12B78C5A4B4CC9DAFB17A5C84C1F67B5E18 F873B96FB8D18C3E5D30B1260E277F0EB9EA42814894F98B64D8C5E564E8D3C4 D8377BDC9EA5AEC87846D550021DE093EB32F7F9A4DC24F6FD8386F6BA883630 7B73142D3A6860CB6B78031CBE266E65AD3811EFDBD1FEE23DFA0F6E25C64BA5 63E2435D29EE1169910751A0FBDD7626BFE1B0A076B47FBC89963AB9729708C3 A9B36D7D69CDF0F8C0C8668B19AADBF3FF316B1FFC44BEF969657F79E5E263B5 144A61FF11B69B0670E0024AD99DBD73C86F324267F2D6742CC38AE0D83A0E6C 57C82A49EB81BD2386B324FADE61413713ECD0A4A360791B3E6B81E191B89298 A7CEE8B8B492F29127A4F98C5569AAAC7F25FABE8469EF90129C016933A6B73C 157F2F15CE47B00CE92CBBB393E46752532D44A77747F53C428A6B632236277C D7B9A4F19F15830DF7B27F32F6D0E312C6DEFCBB8937EE5BED27FE67BEF27282 8BF36B199F2BBC1671551C9E40717351FD606B742DE039E29108E251BEDF969C E45B281363D657E4A11F3CE54FC663F9AA6FE5EF0E00F8DE402ECD4FBA57D6A0 B87E9D34D0AAA2D993B8E5EEB652AC345DE657BD258EE9E41DE71B4D6CD1EB47 8C6FB859B8501931E1CEE0BB36CC117F68FF309CF1BF17DAC80A8CAEC96C13C1 6051C6388A586ABC104FE83C388E0852A499893BDB0F8FBFF9F6EA2E292D2A6A 463BFD7512D515030F620F2933A369A70FE7C92F62DE254576D87DF67AA7B46A B9EB64253262F4F630AF2D06DC7A911815F31D34F13E166F8E64D562A0FE74D0 6A8BE94FA27CB5E9A8B4E3DC779E1F18CC690845D82B0B32DD4CC4797548741C 3B85355C90E01187EFC798078B4470CF6C8FDB960B9C78C255AA3EFA6C8A753E 002A89BA14637EA765BAC054AA33CBB54A19B36F195C15792821A7AB212DDD6E 4CC7D8897EC3A6047E835D7F07DD3AC215B30A0781E2A1770D7F474C275F9448 37C3B206EC15BA70468ED8F1191E0465B8CD3BA55CD3724F5F80D6DEB419F33F 67364769C514493F0B101C438FE442FAB3F3D45DCDC6A5AC10EB9CFCA26CD37B 1CEB9A95B8DADE0855F62C5E5601AFC030F78415E3A5A74C7EB82B3C48E779AA EBD8C5622A9B5BB1710631AB796062007CE0B8AA31F8D98B9A1E9FE07613E420 A488E8B5683F6670C85A1DFDDD8D7729ADB53DFC0BE477EE79A7DB93AAF51A15 0D231B80D5D4B218A53C180D18117145D367B40CB779689405BF249B7B1E2B1E A041F6BEEDD77650B9107094A13066492293568F83451532D851AC79A56EA450 5F331578BEA76C2B31B484E02D131CCFA722266A13D85EF3E077E2D7E1A25920 93E555168EA668FAE1AD5B562F102A5E6B0539AF2AF2DAF88FCCB30E8B3B76D1 FF22ACB2E0161F364E488948A72E3C383B6498FAFB544D82AAEE41588800C21B 2415EBEACD6E0D598C74BC860BEF8977D690B54670984114440E279B5B45B58C 2E334C8CA160DEE724D6831D068FC83F1B421B71A584B30890C2C650C4FD6740 1DDA3E022D4C6E274EB881EC464EDE590EA5223B8C88DC69BF64F86A80317F12 16539DCB188A53E13B0C78F76671363A7C3E7461E0FC1F2C0B2C1344078ACFA3 5B487F86015CE9B6593019186C50AEE0E4A5E0B0E23951A681EDE8E480FEF19A 95B579C4F4442406AA4B33AE60548B50081801DE995FD426C0F8C437DA355595 09C9C098CAE938AD0BA2A25E13C12DDF84B3346A93D8EB7C9F401D8314055482 3D572700DFF0F430091EB2ED92A726B5C74C99B2D7E58A7D3D06321D6DB8B657 D8EACEBE9DCC92A8247A792B65A83F0B447847C5F52C31B00E09352A13B9A616 12A26C0BDAB90C97CC0A10ED8A93C384D9E045B45A5B0FCF938C23C94442457E 7D410D9DBA50728D08331BE676369DEEF3ABF182C67D2200AE4ABAFA620D8A58 E89FE34AB03570AF159A0B5B5D17A6D41C0760656164C93574EDC5A4FF59166D CCEA3F6043FD28134961CEEE56E25A6FF6EFBF13697656046CE73C2FEE3BDFDB C754D272EF6ED4AC91A2822E1D2EABC411AC00D81E2F3D3C9A049399776ACB34 4238EDD9856FF01F5CBF9D858C73A13ED3DD6EE4BB5882D611E02D50A1CC5041 B0F9D82524BC5E437C0518B6A7CC9B24ECCBB081643D5D40BF1BF4E3779417BD 4858D8C79AFE226F180A16EBB922B60D87FDE2A2610DECA951255259FE2C1B0B 7A3FF3E432D45103C7E477450BCE74FDDBC4A089283BF6052DE66388BC195EFF BE92AEC207E080EF7640A3D86FF0F5339FD097D46325DED93B3EB44C41F55376 ED3ADE9CDF48D66B76519EBA58BB96EC20A72A5DDB370031F990B6283ADABD0D 78DFADC9ED71506F7959584BEFEB34D8F787632F9A1000E25EDE7CDCC515E604 D6B69FF0AC35B47B0DB3865F3B876028B1F46FD03D5EC063D73CE5FA8739CFF3 B1B9848AF6D9AE337052181E33B1A412B0E6E053BA70595C91709384C3970D40 FCBA42BBB2770D81DA410ACF15CCED52DDF4A25BDFD675EB2B3A24DCF00B0AB2 173911CACAB635F751C950A1EAED8BB5B10F49E9536EFADC117074A92745F15D E324C0342D15AEC4B9135FA441BCAD8F5BEA5ACF9B788034AF2DED00DB1D8A56 1BD52289D4300F64210D0CF4B7C375321CF2EEB31BCDAEA5BA2EB94FEF21F61B 8C474E12F5BD58A6EC330ED4505A738B470F6DEAEE44FFF3CF4E5A12EDB76236 D0768EF832794754E309F70E14F698045EB67BE2B179080D529859EFB4BC4CA4 F3C449214A781C6F1A5F3F48ADB5C7147C1C4D6DB3CF58B4668FC211E38F3512 A271FD6A4221F80670BEB6502465633C1D8419DDDD6FC8FCF176A6FA1FF08AA5 133D6D20C7244E4271E51C5CFEC3878622B2C1A6A6E205CE490CE18E53E706C9 B01F6928B70BD78C67CDE665F5DD0CE0C1D6944B64E70AD71FD208B7F2C3B18F DF15C9700EBD43633921D75DF06087829FC0DFAE046CE3D33368031C9CE323F8 928BD6F765C26B492CDB926EADA4832EF2D403ED9696CEB09F7EEA632C3E069B 52733D4A6A0FD66D1F16AA5661B56674CB044BB0377D1ECDF25D3129A1DAA4C1 11240C4908A7EC799EE8E1EB174B7145F2FD1FCB9C7ACD2EEEE13A76A50F61CB C4DCE2A163F2E3F969DDA510A235668825248EF47921BA2351E611D3968613FD 2BDB84EF2E67364D75A07383C1A3E7BFC4F401D169AC92C99AB2658509B3B307 5284D80A26F0EFC109C321387A3A59DD15A374DB14E1C84050E54361ADD4001D DB6EA0D44B2135BFD71794256D99E4BB3D918AFEEAD0C034029F35F2B0F370A8 F7C3FE3E90B5CA1CFA6C00B80F7803D50D1AA963B2B41A0370F41A4E884E5F94 219C47A5D29BC2F321DA2F7EFFC80DC81B571E6E07869C36A99C44BB1D288D01 C4974340F648B500FEB8255354DB31323F29D0F2D8E82A58402BFAE96C4FB4C1 5089E9086BB963E73B84FC370F22FA3EC845B323EE80F1B7E60A1DBEF5C74BB5 154CA647377A390367590029DDC23BF2C8EB093AD5121541A3D65DFC96D915CD 0328D91CC80D7F85267A3E80F352EDCB48BEA545F15C58B1746D9295E83CA809 232EE639EF34D62EAC12242495A4C700123C063C0B79D5CEFCB6E8399110D21E E9EDCA21C8014370EE3029AEEE45D534B806CBCBE92A69EC4A4DD824EBEB81A1 56F4E76B8E84AEFA71B2EDEC781D7EEE9B630EFDCA19B266C9478DAF39335175 0F3D6ADEC2D006A6041DFBBE81A4342943FA431CF480D72847A4E352F2172024 5170B296B8F9DD81FAF24778649039799AD577C28D42A9C862E6957AEEF5C17D 83825165B14A55A087284A82788AA3D785CE9F2A0B5098BF7FCEEE02BB05060C BFBBCCC4297204D8120DDC74F113B1F943D571A173D013B2AB12CD4BC9905ED3 38B61979C7ACD74D21CCED0F20CECA258427E51020F11D659F8127453A29467C 233182A6205DD213BC6A4934ADD6CC1EBAD7D466D7D9B3233B9398E107D07B3F 34670026B3984F8DC5099D18CD79620EBD8FDD80071734C1FB5B5682BA00B358 5B58625AD6B743096EBA6A1064050AB9E2ACC5C526F4C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMSY10 %!PS-AdobeFont-1.0: CMSY10 003.002 %%Title: CMSY10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMSY10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMSY10 known{/CMSY10 findfont dup/UniqueID known{dup /UniqueID get 5096651 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMSY10 def /FontBBox {-29 -960 1116 775 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMSY10.) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 2 /multiply put dup 15 /bullet put dup 102 /braceleft put dup 103 /braceright put dup 106 /bar put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CD06DFE1BE899059C588357426D7A0 7B684C079A47D271426064AD18CB9750D8A986D1D67C1B2AEEF8CE785CC19C81 DE96489F740045C5E342F02DA1C9F9F3C167651E646F1A67CF379789E311EF91 511D0F605B045B279357D6FC8537C233E7AEE6A4FDBE73E75A39EB206D20A6F6 1021961B748D419EBEEB028B592124E174CA595C108E12725B9875544955CFFD 028B698EF742BC8C19F979E35B8E99CADDDDC89CC6C59733F2A24BC3AF36AD86 1319147A4A219ECB92D0D9F6228B51A97C29547000FCC8A581BE543D73F1FED4 3D08C53693138003C01E1D216B185179E1856E2A05AA6C66AABB68B7E4409021 91AA9D8E4C5FBBDA55F1BB6BC679EABA06BE9795DB920A6343CE934B04D75DF2 E0C30B8FD2E475FE0D66D4AA65821864C7DD6AC9939A04094EEA832EAD33DB7A 11EE8D595FB0E543D0E80D31D584B97879B3C7B4A85CC6358A41342D70AD0B97 C14123421FE8A7D131FB0D03900B392FDA0ABAFC25E946D2251F150EC595E857 D17AE424DB76B431366086F377B2A0EEFD3909E3FA35E51886FC318989C1EF20 B6F5990F1D39C22127F0A47BC8461F3AFDF87D9BDA4B6C1D1CFD7513F1E3C3D3 93BEF764AA832316343F9FE869A720E4AA87AE76FA87A833BBC5892DE05B867F 10FA225E233BCFA9BB51F46A6DF22ADCEACC01C3CD1F54C9AEFA25E92EFAC00D 7E2BA427C25483BA42A199F4D2E43DFCE79A7156F7417ACF78E41FCA91E6C9EF B933450D851B73A6AB6AEA7EE4C710CB5C14270D1674FA334686653793FCB31B 491E870D3C2BC654D2C1DE463EC9BA29D7371AA1078800EF93D3F66263A2EBBB F5723697BF7448BD0D2E301544BECF497FD475B85DFEF52AF4F8F8BE445CABE6 019318806D10C5952157FF8F8286C1EE701545C8F60EFA854EAE66835A2046A6 915D395F1E0366EFE0C0391583FE001FF16D82A2E2DA5F57754A2C6F69306E36 356ECF8EFC3F1188AD6FCD2427E0580C97A5B69B4E0E09B85EEDE142F5ADD2F0 5DE51D6DB72B127412A0D57106C19CA493048A4F815129ABE767D51715B1515D 9C21067CB5BC88741B7298C83EAE36A866DFA87D8981F179B1C31292F56BBB64 3C430779468AAF07C8A8B4934E1E775FE3F35186BD1FA6EE3689C1C750678AF1 FBF9B23195A124C5C991FE670AC0C86FD39D2B07B9A319E74EFD498B45820252 720ECDF7294F7B0B137CEB86D33BFCEB8606985A3260FD669E461C8BE94216C5 D434FD8854F44EE66E5A289A9F9E32BC36AF645D53F96652602BAED418C8D726 BD04A1B4617551FE4DEF54083D414F7DCE004E6BB2DC9C2EF7CE232B254BA2C5 7DCBD36C2072ED46FF711F121A701E2284BF1B718B3164382B8F453D68FA0377 DFE106503B8401D4DB87F5402A3AC9A442FA060B0610A9524D530C7157C26B56 AC970FCC1D5655FFFFA39246E6420CF97D08ADFB7B05822679BD40C638DDF0E7 A97BFE8918B611A145AC965C203F1428812F9D340AF499B3A915B22BE798594E 0F520109FC81E452180AE45B170FF999C5FC2761C6CECD8742A5A6FC97F16743 AD4EFCC6572A6D3F3E4E330C5CB2FF6FEA48A5B64DD3DBE943BD9918D4A18E18 CBCF598AEFBB6AB3CD2CBC9BFD6099272F6543F3E532E0E21E614BD2880B1023 0AC234CB705827BF016DB84E00E8C255FDEFA0101A842929540B7B4AA8A089BD 5EFF05B72356B6BC3727817823B5CDBB1B963103000D7F2A4E2A1472FC3E614B 5CBCB6D6D784023173DEFEBFA8F9ED87EC1A0A9EE98CA59CFC964CF943DC683F E9E00DA718C4425A705A69D99988EC6F152525C790912C2E46A2381A569424AB 54DF4798BC2D7E7A361E7991641D4B756CE2A7FF4A2848927092C59C2C4B8809 E13AB84FB6B111E680D7FB9F2FFC2C5C66B0B501E4447C2E46C10E2F6124476F A140C404CFE2DC9E0199BF61E035CEB481D438139A9630934E541D261FFD2906 4CAD99E20655FA746AFB81EDBB5601F5FD6B1D6832A01D585E2C55053F6A7378 4DAACCAC7608DBDADAAE732D66B3E7F87E79756337C1A961E53A4651BE7C77F4 038B89C87F650C54A2A90EB7F1D525BB353F33318551EE8D84A6A83C718EA5A4 B2AC0F7306B1E095819B87015A90CA3ED739B09061782C28CDB36BA4BD5E5308 5CBB70414E4112193DAC4A1FA30996327230D1E021F3CD8115E12D239D93FFDC B645910EB29E40D830E7BAF2DB255FD7C4E776557BB38157917D993EAC245837 A3B515147043574157B8342D829C7228CCEA843ABC89D1785A9672A5923FC4CD 2F3FF27E6FCACF84E2D3136CA2C0FD3EF1EE7354CD04C38B5FB874553646ED2D CEDF7E362EADD04B18051F20A8FB0DE18E152385B9D05F98A3A7EF177824E246 455ABE69E2F700EB78185CCFC07E3B4C6FA301112528D977367D30D0D5D59EDE FAEB706DDC970A9E296236C725B2B55B09B9C336B8E23CBA5FB8692D56F33B03 16294E5FC7FAA42E96395A57CE51CA8DDD77442F142E2E576B778373FB31C81C 16840BB422CA827E30A81829648BDF1CA36700EA32AD888D097C1FE0A05B2D9F 483AEE40269DF09AF0D1AD3DF80C45DDC59C2A03FBB661C79B87853737C6D352 67626B657321B16198DBD6DB98A092F17878AE4698121E1006E53D6F9B0A3BE2 3FB68828EF854A0CDBAA68B37ABCA6AD4A3D809AAF0BAB1697A81FE59C98C472 1E33CD70A75A22C249DD11D76C2575ED3370A25892A16D2FD569CDA70C130770 93F493C7D47D6F9A5424A7A542BAD726BFC3AB225DCEBBE6AC4BE006F8C7C0EA 051424B08305BF2D951AB2986AAFEA04E078CA79B399585BFF0F1ADCED02E15B 8765EB6BF6A8E4D0901EFF2C3AA104924EAD9637A35D877E0C51A3C37DA78CD4 8643C8CE6DCDDE3F116A6C2390F948E5371BEB5AD2E87B41C5F01FB5C196C436 6E256A88D082E3F46E4EFFBF605B2EFF1E9D9AD5EE4DDC323A137CD9451EDEE0 06F7D82898D71FAF2362C0FCF1F726F97F820305B7CE20728CA08C63575083A7 84BA28B7DE2B916432475510E274C12FFD1660A717F51DACFDF0A102D85224E0 D6DB607BB72569ABB8A7BC6A10354CBBC01732EFE35B72062DF269CB25EA3DE6 DC603B04C90C5912D2C38D7A5ACDCDD3F6F116D884F0D8C528F69D5D47BA20DB 0A9E585C7D8CC3C324FE8A1DF150279F7E8FB43BDB720E624E5E9918032C02CD 8020636AE5C38DA2484B7F4B34163E0D0A561B43B80E97746DC05C871AB620EC C5D47101ECED4A7E25F291184BEF8B80024AA7BB456C1B83A907652B331DEA34 754226C39C6889EBEEFDAD081E01EF8FE47751987667836FDE4C8BB8A3FD4406 1E643B4EA37BD370734D1A2DB17C2F4B74B4ED75098B433601F75A88C9A37A05 CCB157EF6E32023BFA33973F3E655A4D58289136996FCFA61EEABD70791B6523 1FF5DE71AB8A17038923118A5EED8D59C4C58D246FFA9BB26472346B40C8741F 153D19CAFF20DD2A86C6DB89154A630FB1761929FC3F0448EE2F089C1C953E02 905BA8DE75D101A982A611056C4B237596C10951DD98BAB838B742D3CF7DE718 617DB72E5268583223E37E029D1C8FD3F1D21690151F76B76C52C725CA135CA2 8666553E863CE188BFC9B99AF56AC2DB5BFEBEB12FB563D00244EB89E478657A 98AF2E1223C1ABC25A4500E8119B86EB3C26B8A2F3505A3E5610F89B7C34E278 53FA0A54A7F46D84A35EFEC36AE660A9E3C37EE3864106702DE5AF6C45ABF64B 888A4A51323138CE77DB935576FE6B4824B6942DF80625098CE1B5B32B234F1D 052A9D6039697118A9D793793775D8729D8574A2E74D7109C7B7E23BC5E2E87A CA8E019203952A4892544E1AD3D4EDD22971611358AB230E9A2ABDF00A288501 A01B67C42B33F6B78C39562DB50F4663B922D9BE0D8A150311AE44B83C1F129F 07337323E9A23211EE58E16043E127C6F9574019179F5635648A011266677B56 B5D0201A4E1470B952A1579B57AB2329CD4C615395023C653F784D36B5EE3672 10D191F29EA508CE84763CA4CE7C2C5229E38E241255A5CABCD6C7CBAED901A2 CA53B5E24111921CDDF83578D33D463D70EDACA0E470D8F592303FB6BFD68B4D 3F3BE2D7C5EC8BBF10C90111A33E205F2649B56E8443F6FAA6C721C66575AE12 D4C40F1F46CF9E9DA675AB5D5840D938780CD9E4AD6736ECBEB6A4397613586F 849B51048AC5F9405E03E14540A5E5582F61CDCDB57EDDF95A8C6705F433EE16 648F098C03DED8A2AD94AE3DE202D629B9422ABB031318D48F2C85F9DBFA17BE 84708AA3B6C9F81F4508F7A5CB7B6646AB8722ECF817877B77D473F577556DAA 2BA0ABACFCF5DEA7498C47328E873019A956FBB250FD9D8885D21D368FA70CBD 2709D2DA44EE7A9869963EAB48789541906DE49FAE785ECE1F18A22C7E7ED204 9768896B78E9EB7A2BD6EEC1B26083940656ECD689D92942CC8AF05CBF82AED0 B45A7DF4DD7AA6526FB597322560B9ED3087A65B5EEF1371C328A021411BFE3B D9B5088B2F1AAE381FFED52D2D1E02CD0DA78683E3B06171CBE94BE9760005D7 135893D7CC2DB097F6AC664D9594CF1C650F84DA80D2EDE04802DBA33CE3DAFE EB7A37E8AEFA4FDA6252FF21E8673DD98E67124D5DBC7BACF361E57077B71939 C1D1FB923E4E35C075CD1BCBE0E80DAEA1320D55B43EAB45D9B26C366B278782 7519FDC482D98839BF0DF2E7C3A56A1C1A3FC0E57A75CA414F6536C1FE8EB7A0 4ADFEE3BEDA0F53BE8CF5F64230784A797133E8CD46BCCB3BF38BCE38A73CCE2 9E073ADE792F7128231DDD1F63E6156ADB2609C200837C2E8A2D93D2A7BC9171 050C709A71E44E32B1B03C92EB5CF1D3BAB1C38E027DC4ED9AED633D98CD7486 3F773ACF8AE332631CF2ABE6D606607593FE862ADE31803964E3F4DC3CE3A271 C76BDD95C87CDB3B87BC26FC7A16D567EEC62E6FF0D471B4853DB8A94D4CACF8 843824F818083F10E88D52FC4253E8203292CB40F1414AE7E51DD7347007C342 CD70E8E9F2D2A13D71213B841DDEAAB208AD9EA644591C15DEB084165F9DF24B B91D3BBEEC2E34E38EF16A0C3F00700A7BDCBBFED2EC0D09601AD6538288DB50 3478B051B5E16B604A0341FE621A58718D960D699D3FAD284310DCF54EB13175 19A75A539EE98E804AEA24689D3540F0F12951A3C01FACCE9A7BAF4D0DAFA946 FF65A4D2A4C39969607272C6886F44E90ABE27CA3A1F12A29D9B32E60E8E34F0 17C5FE43D0E69A99A922D98909B2BBCD145E59A5E7F5426B3988F73B09A525F6 8BD4915663C1301323180E760BE81CB874B020FDA3AE63340E4261E4F3E4949B CC0966BDC4426190BE9F5D77F76A72AD925662E5FE1CEF9CCAB68F0BD33DA003 F11EB91AC4502FBD6AE48DA0F9D07C35B96B103E379B8A83A05FE728F1716194 1F650F75BEBADB2E3810388F3E2DC7B19F1BA9E32925F2FD9F19F4E8701F3E4E 4069125D7C401144740691E7A460021A47B1E27997FC1DDABEC5BD0EE0B20194 2D579C7D6727AA124083242BDA46D8E116E2751C5F298851A62B60AEBE82A929 9B9F2492BA35690D1EFD16215B8EF14E7A3803B93C28FA41D971B05B6AF3B593 E74AD1E68A5FCE12A86E63B78BFEA87D3949FD164F12277A4688BE96356791CB 8671C49365608F3EDECC109321AF92B4C29CAF073DA3A7D73E913D0D83FAC5EB BD884D4C686056404DAAAD6F82F94F803FA1FB0DD8908D1DF08FB87A8BB83027 04DE0CBB1C6FEB6B517FBD7CF065120079E608CE41893C2BC96A347826CCDFD5 C69E161217F2127A59F1A6F22037641613F191F22D5B4CDCBCC2EE5615623404 ABA7BE6C5FE475481615B2AC1A2412E54688DD21E44CC9AF5F16E634AFCA389C 4D740B7B51BB141BFAD1080E7C726C1606A28ED492E6BDE9F800EFACD1513909 84E98CEB6A0B7A2A6F3E1D1DCC3B2552795E0932673E59ECC56DDD37A1D52BA6 C3F0E905978AB568941A163F4CE3AAB5C5B16F86016EC47BA6F3F7AAAA77C3B6 09C8C3ABDB6D514A76ECD37C37AA88B5860630B3406B494F7725975596F84777 D9CF48686EC9C5DBCC1D78513F591C7C10AB9D153B3D41426B7BF668B0D04503 56BCB686258462C1DC61095724B9F3312316262FD7C1AEC6E54DE7E5A7BD8EFF 035299B8FD8A4A7B0F51404F4A760F4D8B4C0FB7A32FA4B2383AB6E9C78FDEDB FE6A5788D38A6701B123630C2A6D820A684166FBBC83DB17069494FBD411B333 CB37E2491C5BD035A33867A6D3A3D420CC31ACF43AA07182CAAE67E40EC63663 B678F71D4C6E0EC3A0AAF904CD3AA66E0DE5E3CDE049E94249B39A1C06E3CE9A F974B2484BB2CDA14282B9511E505B3C89F9C802218AE40D1A7541335C5736DD CD565D4B9F4CC78F3A393737EDB4FBD0DA299E21CCFEBA5478EEF013F0552A8B 0BB11FF46CCDB784E8BDCF730A16363E66572049E42C695886EAB42A9AD9094C B635DF4B5B9BD9B9AE8455DFA3EEFC77653190F9A8B1E93B7281C2A21EA7DDA9 33484745BDF7E3DD63C7AC66C286C9A5A698A5E4D7A91710B7FF943FB23609B6 4B442F83CB795788FAB5E9CF3F75D5487DA26170E4561C7941C910B088C3B86D F844B0F340CF82786A3FCF347048463EBD2006281A816627065DDA6CD4D3AC5E 2024BC96C7D896381BBB567951E7A1F29D4E95351298B000D29E5F3D0448CB5A CFDAE1BADE9403B90371C3A07D208948AFA022A69C519434B6813086ADF518D5 88E0B92072A44BA1B3EBB630A13B7AB90992E85B6D67361C8D96F3E0D826FF37 17B67E4B1EB7BADFD98D7F4FD17BECE740ADF13C141EBF0A91CB105DABB32FE0 55086D56A0D358841D15FD349E6B95512E4EDF4C430216FF85C2ABE995E4B40A A6044CC8820AD885C07E052B3F91C2E9A1D163BFFD210F7BE95B923E2500DB50 2075106DB541C267BD450B25B670CE80BCD068D4DBFF2D82634175B61FBD3BC3 406131F44C7D6F18D375D1F2270829DDF29DC14DBB58A30AC193245D18DE91F8 AB88AB548D8138605BB5A50073295534E314366E26665AE70482B890E4101D6B 60E4F3B37ABCA1346DAAE8FDB8DD9C832EFF3E73BA470E2BACE7B8515CB43388 C27AF99FF9322175CF8D4947E6B3846AFF5163E972156847F58A66660EC8A3A6 5FB47C9F637B4CBB4C73B6A080B0CF6FD1E9665E92032540570FFCC747C67C50 822811AADC404BC7ECD1673E8AA6C3A2F1D82F39430B58C29145E2F1B679C46E 94EDC711883F1E4EA84117A54757E8895A40401A26E1437B39A2F65CAADD6E02 D71FA8AF7453668DC613F326A3344F74AD7AC67569AF399385500ABDA5EDD3BA 343CC5EDD4B558467626850E752B9959FEF1454E53E7A3DCBC2255AD8F6AB4FE 894455118A61C58840CB68A925ACCAD75CEACE863D806916228F0614191A1CD5 DC9BAE256018615AA3725834519449B0A88B4F396654E74099C007930ADB1327 DD119BF799FE3B0B223E1EDA04FE2DA7A1C879143E1C33B6C6344F4BA033AD6F 8E88C33DEF1977796B454BAB2494C930F492A518E8198C708A75FFEF8C49C324 A718AB59B889DED521229E741FFE53F98EBE88B0405AD523254FD3FA4BBE96DA DA1C27C1C979A0DD4E61C3B1F4C4DE01E42F1C4435EECFC02D97994BC8AF5270 E7CB1458D76ED0229C5FFB4A23B8716018F9050970895D51722CDE8F2EA3D947 DFF374D84915D5C5D16463A6FFCD079D1ED416C4347BF831FF0C4ADFB61295DC 4D5785BB0852BF472CFC97EC174491CAF961AB90629F055E75DAA6D9898E8653 5BCF379816CAE46FEA62E7BE8E9B953466E51828172C4DBD0E1BBAD1CE28B5B1 02B3E36403BE80B49A47446A6677FCED438F01D60EB10F478C89528FA337D0D8 88D3FC123C076507ACDAF783A9A6E24ED73BF24B6E0F11C13E532DE5F70B15A0 657F5ED27D204449A841ED19E01432CFFE928E921321113780D036D34F2797DE D4459CFD15BB117B5C9745EF3CD2B296D91FAD48C80B136D94476967E255F808 AD2B5D522ADEC64176833756510391815A1D4A8DA1D0AEE7CAD36A1D161889F2 3347D5B6BC503300FDDD48F594F391D5FB42C42113C538E707C16EE24A3F375E 7C506E8F49CE50FF9DEF3B4A4C1BEB3848EAA3477349833BA22D2A9012287D8B A8C4CB4307A1188ACC0E6E9338E1559BE5FAFF381BD82A6C71C267409468B3C0 2C1A29F4281D565836EAE57F680490FEA4A952FF64C8CD11C377C294DCD1EC25 CEFB2B6DCE959D0208F85B6E32E9B44FD455F9B134A5306D95EA29F37BB8B86D 9E592159338E1293F449380E13C21AE42E6D6952083BFD432F72DFB7B6F9257F 5784C683A6E9ACD72334E0EA8060A81E14EE32300055040E24B49810DFA14691 6C24BF2DE490536C01F7E874AEEF98A27529489EC334D0CD71D022C7F2BBB98A F39D6C0A24CF29DB0E4545C4D32475724F30A87F09B0440D5DB8F6D6FE35EF4A E22528DAAFC1EF6D0EC88A1B219DB61417DA4DBA42721255EC9BC5BE05026051 19D8A0F096F8D68C40B3503B07497CD44A236137AB06B407CA6F5F9EE2F4E99D 735EA287E2C3641BAADF92681D7D2794DD2B3C8D22F78C22D1E3AB2B40478AB8 1EA3AD94008B0D3A5C125EFD6410D27BDD3C8BD16760A91B021C3011332D045E 943A0FCE3EE596985F76817964430053449F5D3233033BAFA7ED9006FE3F8F03 7CF09FCECF6F9848B4911E308C2DBDC25125EEFCF25224F0FDBD646314EE17C2 08BDB63DFD830CE806A0D5D052D625AD620D280CA2784B6AEDA6506A0259806F 5D5C7B85E8F7BA376815E2F2215497C3AC9F73E6CE583B5078FEDDD2EAB2D715 7C1FE58B7AA299FEFF8F9B74132E774432D66B6F51CBFD2D501CF98755BF1710 67716A231B625079AD782207EEB1BC4F8FB30618FE4B98CE3474535899364083 B1A82A67CD5E9033553583A876BC1DAC1F7930DC099D806B1E27389125E1B15C BB1C66AD365F820FE2A7FCA56F38F9C8BB1658172DA09AB74E85D6DF8F81455E 28532112209876E18F8816DC08CC1EA309027B54F73921BFACC25D7255F26202 20C3FCB8E515C7F79EA3054A9B5AC4EDD0AE44B896169E458932B4B8E3EFCA58 679F2F0B9FBFBC4E524C762D07DCFC8BD7229068C1BF9CB2459B251A59600C8C EA5B5D9A1DCEBEBEB971D77F197D2C10067E6D4C013C60B8EB15C457602F3654 379B45E1CCF06CD4A72D50AEAB4F56AA49FFDB41A137F6EB9AC761F4582E18AC E8384F4B9CD7E26FB8A061431204F100081B243EF021572943842B32EE0A1434 3D615BE9A784FCEA05B8B846DDBB604AE63EB9901008B6D8469EC51784D53D21 42AAD960B0272DEF6A7CC0C48218F5ADAFB33DB55F35AC8998EA798171E0EFA0 9AEAFE35DCBFD62B28F52B14D8ACE54352B1E9E1E97171961E0873004EF1B289 3197CC5D8F426CEC68E7E00FCF5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMTT10 %!PS-AdobeFont-1.0: CMTT10 003.002 %%Title: CMTT10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMTT10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMTT10 known{/CMTT10 findfont dup/UniqueID known{dup /UniqueID get 5000832 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMTT10 def /FontBBox {-4 -233 537 696 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMTT10.) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 33 /exclam put dup 34 /quotedbl put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /backslash put dup 93 /bracketright put dup 94 /asciicircum put dup 95 /underscore put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /braceleft put dup 124 /bar put dup 125 /braceright put dup 126 /asciitilde put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794DDF2E5ECEBA191DB82B3 7A69521B0C4D40495B5D9CE7A3AF33D17EE69979B82B715BAD8A5904C5DE0260 6C15950CCF6E188A0CDF841EB68E5A2F88253E382140F87C87E55C9EA93B8C89 14A36CDF630D6BE7CD36DBDCE22B21778E8648B97B7EC6742EB5114BDF0454B0 0EA7B1FE236C84C0E5308C871F67B973892890557AA12E00B2C20C71F516C397 3F3BBD14A1D0149CA064391056E45E9470FC7F6F556ABC82653B3C8049AB5CF4 BA83C8F2158C236B2FFD4208846013BAF4165E8BB8D334C8FF2E8D74AF5DAB2F D44788869B08399421AAA900ECC6A2D594641C121660D4B5F512938994C18DD0 FCD9B008F68F0351D21ED735B2740CB1E0C1CCD25EB548C35B844601D98828DB 556F71D07E081A593FF12DAF83676492A0FFE16E95717A07082B43A966C1EE8F 8A59E1255E1705C43A23CF29A5E4A6547C93F1680A870EE7BAD8CF74D838CD5E F806911D8FE4262ED8E7F5BC58B92C9C6D74F8AD45FBB021EC7E97393018B9DB B1B84E7B243ADB05ADD3F1DB3692ADC5D47FEC7DF93080669E63281F1576B673 125EDF08016664BE73364F65389F7C3B66623AD1754ECBEF9E5CE6948D933787 A5674279ACB2EBECD3B4E6361419AB32028A27670C9F3E18B746A10B00AF6D77 4EC00E3BE521C02A99AE5BAA98F793EB1228952BE67934B91472E01AF7B816BC 56D7F19F631A1927846D800C107B1E9CBFF9D2DD513B4A8CE2E0DFD77B1ED178 E43FA7052765E9FAF89989D490D8FEF6C536EC0D4AE27A74F474B98DA9E6B92F 15E063DB260571979A5DE2423920CE1F59F56EB11E00E3BB9D466A8263E1E385 2014BEFDA8D1EA3EDA04BE32AEE6CD15C5C010A1DF7F705A2C0C18E87C8DCCE9 05D9163181CBA56C0FAC8C06A2990554C8E759D076B01BBEADE3B5FB8B551390 6C8E4A2A1C6E7D9C708614626F3770C0AB7DD2027469C77975C27576065862AD 04E5E50CEBE907E3E991FA0C627302C0E207B4D5992BEBAB5853AD1C0D271728 C76F40A79392ACCA7358F948AC65DC823CFDA59E1FF69CEBB6B7EC3CF21669E4 70D999508F9C49E2D9F8818CA53C977D93E15FBBBAF75B1E84F0BA62BCC4BAFA 4EEC82D804C8A8C0210F3E5E258BB1F6921AF02BA9861BAD5C3D5FC8CEFABA8A A607E547B802096F7AEB09FBA99C83C9A494B94408DD607CA6561A6E6660C473 62CF8D35F31D052F6C6C8138A8E1430CBA7EA6973D6D510C1A06B3FBD79D9364 240C1A00272DA44B89A9FE8D5BF36DC1B5EBB4A78ADBE9C5EDB485F093D9517D 69E1AC9A8E6C9D7C324E3797CFEAD9A18E82E03F69B2CED7D5DDCD1A218BF2E2 ED2293AE999FE2A4B5213A10083EE0407BCF8007670B8C737EAB30311C868D84 121149ACB4A27F3ED6C0C181C98AAAF51B105F264B5672D7F745131ABAB5BEA4 0C9B43C0DD9116D6DC61F90BE72018F290D26D5E9D341055CAF09C9F45333CDB D45B7954271767F638EEC499F7B53C2CC5774EA7A7F024C4CABFB93D9CB1856A 0C671A4ECA7C62EA5242648A84E7F3AFB9547A0AFC29593CFCE6D8B873A78157 D337CABD291431C0A2CE1F37E0CD7340567AC206FF98E4B5A6410F70F750451C 550EFB54AA259A1B236CA9CB730D2CEF125EC65D959441F7CC9768F777B44844 CC9842A307C72B740680ACBBF6AA35FA7A94825069BF7696ED81A371A9E5475A 9D997F2DFAD339AADF797F7E03E654234455AC3D17702A420EE0A597BA31BDE4 FEB8DBA7C61D311CC90441A620164DC22DC2D373973EF84CC553453AB1B3337F 7B39983B8DFFB3A9425F119B45C1CD37A76F905777B3154CA6200792F1759D06 E017890F4041A385F2238E3C48B6C8EE6F5258463FDBFF7AC762F6C4363926D6 50F004D473B7B7F73CA686B559C2885F1AA761653C727A77D73431E9D110E76A 2E55C68CD50F43997C9B2FC4710F8C8540909829E215678E63BB8363C4B8AF05 9986102BB36580D9CA95CD216B7C321822CB41B2E0422CD077F3B55E0246FDB2 44D5976F67296B5B0BE4B06F6E43535C21164E6C5089C3E9BA2D6B30888C57DE 49DC8D9D46C0D5EDC47ACF2C03B72DE3B69512508539019B759280BABEA12BC9 385308A0395C4CD33182A10A5A229743379C2075D82D8BFCE4A66E1AA087A091 8F5372684FA5037D1B92D50CD9CB4F50AD4F8EE7D51F1C9E63C721CB5B9BD011 6F0A8DD4FDCD2B008F223A1036D90F0F3B252487DE7898F9AFBB3A9D9CD49E0C EF4ADAD5155A98D2125ED5A3D3907F67301649519419F33CD942E8DDEAC1BDA0 E90C431B198F646766A8FA9F8D1561B57E126EF604838C0C1966655CF31FB7EB C8CCC434FC1C96046D38203E1791EC824A3D7AED85C029288D4608CA7668A2BE 484C99639F121845B22EEFCE0A3B808261921AA042AE19E641769E91277BEC29 4594082CCB3058F90FAC4A700A8A827ACA00FCF574ABC8EB7DBCECD97F2B22C0 0AA19E8739B81AF8C6F621D69B8E6F29BAE233FBA655A0AF5BDFD7F5C6B9167C 6BC7AB693D45EF2AD999F5DA3CEFA39BA48A17EE6D9F2C4DAB91AE3F0044DC3F 5D5506CE4675AA928B0092D6F173644F91295216D8BBB14CDDE0AD524A4D545C 1B5E284A3BF0396664081CFB4F186A84A0D24D61E82F4767C1E55A0642720CF3 909FA1AB8EAB78030B59BEA067DEDBD2F1D0340E790AB2777DB18248521934A8 BB38A58B7F633DEA4291B0D5D13E9A882C974697CC6D3B49E030C94EA29B5506 CC29C44D01B4751B453A46A9F6BF3BF135AE87A4CE232AF57B66578310DE41E0 2A6AC422117F1963C4D7CC306BD25A6E724E51921779F22F029733122E23E2F0 CB340008813ABB104380C80A492B3FC6D0BB07CB8D8409E9576891EF6E5C9D08 EB8320DFA31BAFFBD336D0C2BBC3D3B2D30368B9860768FC080D30569C7F7811 0EBEDA2962476113625EEB555490B8CE4C5F99D74ED10F738C61854CFF8B41C6 9402E56BE8856144A1A05D0B05F4CB7EF728B2F4F5A439F18C3B68CEFA41E59A D8308ADC92EC1289DC84CF48D2CDEFF509A145BF945E1E00D552D329EBD2A7C4 21D58082CC8FA790E981F4AC8EAB99950678FD3A7DA3DF13778681B208DD71A0 7C3CBD0664B37C9EDC6B601D79A2C51FB54DAEE849F93209793849104E722D3F 52DFAF7047EEEDDFE744787A5801E4AC2C3D58EC5DDC15FCEE03990C53B0C57A FC54F125A04C8E4A0ADAA725808C587E7DAFB9F784FA2875689979D316DC22BD AA36B306A1ABCF907B63C6476737B746099973CAEA8C1E2C5C41F27E0F7DE8D7 F0D942E34E92F43FE902653D4D2EBB6F3B9F7928B1550A82AF234D45D028F429 067652BD3D391BF423AE72B9CB1E8D91E898161BE3A7849D456A861A2046711E E934DC59442AE7D81661CE8EF727D8D7DDC0270E937E40F896AEAE6171661431 C1025C53172F9D366834BA0054FBFD84503FBAE328B6FDEA180F8EA35B1DA937 5CC3B8F00C206908C2FFFFA6A7AC6915D15EA44BDCF29E2BFCFD4A849535F19B 0D307C696BE8205C7D84B9C77F02EF27D911056EDBB4080E4D3ED72788666CAD CD91B0ECE27A177DB23320A7FA9C31408B4D02D2A4B1CC6DDE1A6CAC3D8EC1EC 2226EC98E51046D1EC26FA20EE62D24747D83CF4941DCE5CCEEC0DBE387149CD E05B19FFCAFC0D117F9A3E60DCD4C815228D98EF95EB559AD0ACC0D50FFDF714 56C3C812EA5ADBB013BBD956A7C4CC0ED7D3E25D5C9AF5E626F18297F75D4957 F5B0B33379114B903FE98BCF35C3FF76FEE1D9AEB711F2962276531F7380EE3F E368720E0292A170A15C5539B1FC7BB954EE2624B504CB8C805B8D31AC38307F 0513606F09211AE64DAC447693B2A0AD15E9A64C34F5A911ECD0ABCA90E9791D 67C6BD202B0858EF96E7722305B8AC02B01AB1706CC6AE875A8DDD15EE349046 EAA65005E7866B506EDFB7A5A2AFD5C9E9DCC821A79EE9C1EA2C7BBA32A40BC7 CEC26DB1AC473C8C3960ACEC581B37D6569E8C8C42950BAB7930B65E1570E3F8 9A7FA719F1DCFDA45A3BF2AAB32C9A93BA3552608A61C623DE59BCB346E87EF5 9CF025A87803161221C5C1C6F6B3403712C76E9D755C7BD68D7F2DC03C14CDF0 C1BBED1D648B905B4B17037B7263C1EA7A7F06FAAC4E09E08483A8D714C19861 327CD9C32DDF850302DD6DDE24912D00C22ECDF3CDFB18FA831A41A7488EC203 F564CFE30D506F0829A96D35A7E09C3DCD107D589B627A15B55C5D6649126BEC 60B88C55ECCBB4E680265D9EAB4CE22965D3B1AF759B01ACB0D0E6C92B6B4EFD A81E6A648708979487FC591CF09631310D46891423F4EC159A73E30D8DD147A4 B0EACF6D45D18CD16CEB8176F03ABCB41F2234747B9733C8FAF34AE5D43D3BA5 0CE0FACFC9B087F84FB6C68678BC6E76022B1526D6E5B3A48EC1A110BD75F45F 1C4DC6D39F254976453F57DF873B7D635C80C42026DE020E5BAFE0DA0D54D1E1 DC634D2621BA184347E5252F645A6A1DB7657C48124186F0E4C644077457C24D 55753C651A9A7B6349867641464B515B821349C795A645420508673B93750D0C 7A3B33EB1F09782033742AE8F3A23FC02284E6C03818FADD1731361542E3FA3E 75B8D52B668C3E18A4AE967D0FC3157083D952AFB8144D549E69EAAC51C279C5 E5D88A0D9D53013DFFB4352A1598FF84DCDE6FA32FC377306B9B92C0F96EE149 8CD55E7B2445B86CCA7A547FA732D52D59025129FD8C6333AC0DF4F0CFF6287E F2036D5DBBB3B91B92F12FEBE0B61A313A4DB5A9CF0BB3DDB781A56FEBFFACCB 8CB9D1D3DBDBC4CB6AAE6769E470582403CB920630221B68BCB625CD4605FA8F D3D5B7A1A28D15E44B38E92E906C138E72C15B86F64C38E23BF0440052A8C914 54397F49DBED99D0AF7CEA3B0A05FF37C2D7EAE1412567E6776333237C31E3C0 49949EC8BFD6E0F6446CE2D4DCD2C1524A288818CC5D159BF8463A847AE4A2B9 CC8C58F822804B81B13BF4F2DEB6229C4F51F093075581791D02C36A13B855A0 34900AA7CD4F1A797652656FE3A8425A38F421C4CC0ACA1CDD44FA6B31219276 1CDE1CD63D6A58CE705CB56CCA1260F9B86E989019071563A9B4C274A87558CA 6EF1660D574EDA276801F0057740E2C3B80D253D697736484D892CE1AB128B8A DECD69712F5E70E895FBAA927E8194D792A04AB6CE205E04E38A433BBB793FB4 E8BBC4279D58A223C6673D909D6AFECD246E66A52F4CB35E5931D24C828489BD 4ECAF621A220D8ECF702BEB01C4FC7510197D3F6D15321EC87175ADBA6434ECD 2B5A306E91375CAD22CD94301763E4A8B981472890422C5488FCD523C9CB17DC ED22FBF12D5F7525D0D6BCFE8CE85B0DFB1D6F989C267FFBA0A996D309E4A934 3DB54A9D29C88B9D55D7300DA3D46419256C5A07A2A529A8DE8BD1727281F5FE 97033D861E0531B14E811378EC1AF1CC7EE9BA2B07D935843D3053F673979F8C FAFD59D555B56CE338F606747238B22BD62C42BB7238FEA335678D474A643570 A9E7B4970E8C541CE9DBC7BF70ED7BA33639D6744A18379455029E934C95E2EF 639C4848CE9A0879B51649FAB023A71782444B451F92A34CB8A124270CCF86D4 D18EEF5C1D2B2A29012613851C49F50702D63BACF95EE2AB4D72B375E0A62615 E0991E130A67ECBA9E05329B740708F1CB148724C3A6E5E3AEC1F88EBCA398D2 1CA8827C977D72734310233176D1AE26C55CF2CEACA62223315C28FCF6305C7E A22414D4739A059F552F1F9372CCCA5FED4F9AC987942848EB498900269511F3 F408CBEA0659B954F5F1B18AE4FB270213646F9B28AE4439D2BA2D3E0AAAA780 5E530E4EFC8A060EB979E12191044509DA0C14397AFF949E12DC970658D5EAF5 4EA963F5BC1407A32F3837CA6A24B7F3D60EB8E6222B702E25ED903F9D21AE50 664A095009BDEAF4B78DAF94E5A55D48366CABF07791A1684B2F54EA69070844 4F031AF8DF416C2D3679F8BA038B0DC9DD0400CA6B34667BCBBC07E62C1668A8 35A8C57C9048A7227E672E89681B54D662079A189A9E96A3CA96D8DD10189B04 1DA49BA2729F1CA585B1BD5C467295285D52E47CA904235A1A3E48EFAE9EB6F6 01374125CE89D53C276858668CF45D2F092DDCAA52418E0BB94C2B8266B4D88A 5D911507BB1DDA3D8F6E7C14A91CA11AE799EC42E993098E18CADA70BD2A1D82 2C39326C6E3F9E84CD9758B9AE43D79BF99E6A0CD713E95B3D9B7DB90D127DE0 DAFEBF850CAAACBD860B5DEF2082F1ADA64B44B193C4A1417BE221FDCA36456C BE5934C8CE3ED55AE3A11697C2D682B7D0F72D48976451D205783BE25DBD2507 39C14FFB4BB828DFD187104F38A7F11D5F0698C11E8C1D4F107CACE573FDC4B1 C56FDAE47024D6FD16A2FEABB434CA320300FC4B6C1B6CA08F76C60B7C08A665 99F404DBA8A2A1EB18EF6750E4EC186E31561A3F080BA6562967546715859481 7BA782940F5C5D06626D6F6A412CA7C13820EC7C1DF23E15E5829F698CF617BE D940523E4EE4ADECEC48C24297DBAD528BA1DCE7AC335A1D15D55415B108EFC8 6D45030D27B3EA63B2B4CD771DBE66AE0218ABB1153D4B7482289D1313CEF184 5C960B1E3C3C953912CC6F4521D1E15636C1545EEE457EFB87B88C9E43CC2F38 6BC4BC96969F4FF28ABB06F4454C01CEF1B6DC538F1E832FC1666D977E5A881B F72F1B4C7DD4BE167A5535F1163A0706F9A0B26400178DF8A128FB5EBE6A7B81 E478AD183EC06622B591337B9F1872AAEA356F4FC67EE767B34CB5A4D90702D9 39FB846947F4096FB3DCF16EC81455164783BA0B5D723060DAFF411B68307E81 7BEA1D9A47A5AA3D648E618C83C60F060029E6EC4D46B045FA7415BAB2AD0AA5 ED9C729C24136F6AF61E6409C0B5CA760B16225641E268A68CFB8260BBEAFC77 6626EBD97195E77CAB425CFB0096D805D9EE699E41680D095AE9FA10122A7882 2F00F495C9EB2102DF0D3E61833BC0A2E468C5CF7AB430FDB7C0BE3DF2C0D230 1580BAA25D65F599378D873165482A1FBB224AEA89C6BCCFBDBA42AE1C5DCF41 06969F585CD3B737D1388D6359F5468D88FCD2279BDB270F6A858FB7D2ABDEFE 5EE8FB79FA437F8F50237B92C307B73B0DCB808D07A9C3255CB9B3B17039CE5A 288103D05D132863FB522A02CEE3839EF9AF7F07D99732F0B8B384745369FB3E 7901166478F4A16076A1504C5E98D17408494E270BBF4470ED12B4332422679F 759F1D93984D7E506D16950DB6C2682FE1379EFFA6F6C95DD71F6E55BE3EF6AF E0CB25388EEB436E6527806FC75484133F6E561DEB979D5C1FFEFDAF2A6D964E 03BAE0BD593C2992AD84569C81050F7A793C5263E50C2F50B98C4CC703EAE17A 6AEDAACE312DAFAF5278D125B6EFC5587484F61DAFF46B87B7C9B1EEDECA4859 314A9A9E2248467DE1E54D90DD671660B9040B3E0DD982260822177EFD757266 74A16C83A7FB168016A320D3DF3BD7726F1F4EC90EE5DFE810C96B099FD4368D 906AE4699049EFD37E8EF058D4B97BF71106445AADD4FC6E90615A0066823A36 673B8DE32322BBE861AE251226B4385AB28702831270DBD25D666FBB0AD7B96E A44E891EA1EAF0F87013AFC982E33D67A28E96E0C9CB99B9E4192536830D9901 931A8CAFA41289633B20BA3BD7AA3414B6DA8D57CCF2FBE39920CC06361F075B CC40335DB9A0071CFF77F6B7BB47F3100DBDC9C4A58C2B81EC99E8E966AF3390 E3FBCC28BA1D79961C8A1584266454DF772FBA99664D74D4A89FC82FFEDFCFE1 4C9E4A04291E803D142E37E7ACA66AB279378F2F192FFB2B5BBAD18B95F03136 2CB594A3D6D3F8576B90A6C4DAD6D6C8EE07AF682F925F01D0B26CBA347C03BE F3B0585CF4539FDC66915E22117078CC94D621F31DCB3E021998A5D6EE94CA4B E214D07517283D56973D8E4367392BF6C1150DEBF459D141AE0941C1C8C5CFBE E735D796E365A1B0F60BB4CF2801EAFE4889EE5F338D3C4885368281B3C95CCE 251C28A90D318A8A0384439B38D63B94757252062EA44E88509FDD2E75FAAB71 7329622828B2785C1A8B26351BC74237A6BF99216652ACBD4CCF54CFC8AC72A6 46342F1E32D4318E7E27C7B2DAC943B3E72C472FC6F1DDA8684AA922516A672C E969C047E318B5E3B1270C1BEB1C4071A15BC81B29B268C679B41FC5E381BE33 DD95F0D68118CBB60C521E5CB2BA46A10E50E9238163713290DF6DD8A27D3813 F871C07E725D4518013D9A84CEC96782541E5580E33C2EBCDB18F08EB4655A46 507A8526DB26C854928B81FD502B0CCE4A68943C12078F57C10F4E85FBEE1025 46D925B8B3B447D4920410FEEB9844FABE985F9228FDD9F58392F2F3BD650E49 2E3AD5A14984874DF4572816931885CE8A448EC95BBF40DDF4F85653AD90A88C C4A879C0C7596E61997B972E8A55E57B17F802C738E5C7A8FBF6424F8B131B23 CEE3EA3747DB066246C250EAD335A76FA166ABF75120CECB59076AB31A51F176 57176CBE8C802A97B0542A5CFD6D5E6D7EC848B923012E45D9F065BFFA0D03E6 788B68BA4DE51DA37994948F859D41C28BA939C3A82BFDB44DA585AE80B8CD7B A6EEA79B70BFB4864E06F06A9751BD2D2A209D150D7135E0A25D67263EDD2A7C C63B5B76ADB05D44BD5BC0BB3EBCE2E74E1AE5F7DE07A59D90C932DAA2553505 27F2AFC05F7CEB39E1C7E54F69FB0BBB069959F2FBD11709F8E81F6E7CA06DBA 1CBDD8E7A78487462596DA288B50B295E46F4C3D9BA862688C68859734B232A7 4B371D2BD786924F186524765E789EEAA30B20C069322D42C893A30BF1BD2C46 F8F3732DDFE80B8FC1789239345944D8B457824FD80D11184E73FBA30EB80A9F 2FD466826D4E666E3A835B98A1D4AE5D17053A6A648E26E77BD08F9A3E02956A AE82C4929E9666F539079846527D0E326FE7CBBF86E3722BA3E53F8A5121080B ACF8D3C67A2A1DF624B9DB92105D3C833F5A6ECEC108E026E1D3D968967A1447 15CEFDD09123D56606134BC3449404ADAB1330C9238DE48F3CDFBC91EB86D7B3 8B85B5BA97376A0673E434DBFF19798EA90BFBD94493E2D21976F8106FC0C276 C81C9B9F7D4A68120DDA56FC6EC65FFA40DB78A60A05EC270A106DEEBD2CB92B F0622BD2B1D43771DF39AAD3ECB655F317AB483F7290C148690903AAA636583C 99DE3DBA99EFE20773D3D8DDD816A28D7BD8881DE570BAF5C7A30679179E1214 FCFED81605FE56AEA21C1894167F93D648B474352A65C0756F812F97AB435ADD 22C031A21714A626DE35308AC51CD676DB1748DD2773532294FA77CFB2AAFD32 A72BB7A045F12B4934A768F89217233DBBD69B900B28492A26713CA5D61A9042 A982CB071F1F875718FAC168E4E275860DB6369B8114E1BDD4801110B62C3E3E CF140554C826967A99F4E9726526E87D57BF845CE38E33893E5F9788769B6A4B A4577C38C8D45AF2EDC9F4FA7DD9979AB8E14FF5D8956233AB4C02982BE8E561 C63B7BC314793F634DB6F086E1A60D9FC3B69D3A7C20A99FBF3CB028CDBCEB60 E803C8DC3C5F0CCAC030905E72BBAC052520CB0E40E23B46B2150DE67F61E4B1 8C4D55904B7F90DDE4A4A78B11AE1009DE46DA396791B1C0EA63FB6897FDFA0F 42474042E7E9B06A703A7C6E672AC6705506F3C0B6861BC85CEBB9DC9CE89372 88DBC4F96661C812D31312FDBD0E6AFA59D5E0D41E963C93AE5F9D6562A5BDB2 EF35BEAF99FC9B83D0F6E963F0BBE59633708BABA1C0C474D507E7DD8C3FC2A0 0E05F058D68121D18C24FD704053E9568C1E110FF28D77255EF61C590A82774A 36F918A82ABEA5D650537545756AF0D00E5531E48A9EF82A048F9ABF657FD6E6 7A86F4EC045CF79F55472FC309009C30F1C3566B750DD4192CF586DE51D718CE 4E3203A1196B6C1B2C006DA31157A6A6DD46B4D1B3339108E2D9247B3769DE84 CA991F28D39B289A4F3AA3556BA6774225E83D3E036A9C7CF02AFF6ED9D3947E C669D9690A6B0607463E910C0D29608F8FACDD5CC249BAC915531365E910E062 8C0916C9A80195D4C3A837B0242CC141677B2C582F9C1085BC3584B742F6A17A C122BD3C37CD6584C8D40E7F673FB8B37B3D86A625B0F2987083E14E0E85B2B4 4CB39E84CCE637E8414538034A2B8DDD282DB19BB49971CBB107D16C3B6E8641 129AAF973C7B5548E265975B0F2A90CFA0BDCDB9800F9F13D7AE2DE432FD56FE F121AFD9D4146B47DEDA2CFC1099B1C9DAB8E89FE32554EAED0738F19E704157 D1A34793E173D032F16245239666AD054A9D6942EDC98B21EB7BF54F5C2B1EBD CE86CDC4D01C9D05ED97A4A38F3F28273DF70C21DB2925BCA2B4E479414E99F7 5FCFF8E6AF113C0C43B061AA6CB3FBDFD957BEAF2BFDC1947F8A69DD669AFF10 99E3D76DD5A4945962C6B1B9D8AB6640504BE4A5D372ECEFF0B5C6F4457709CB 0C0B62B3A7A743AFE1C00B37934F1ED8A45FC5AC174336A3F6F0D4386F3DB83C CF9143F3A1A431342A27B66A287D2BA92A6CE6C7DBBF62CD6792231B90603D75 10079164273D164E13868F7442FD4D56DF7C21D7CDACD60B6DAEE2521AB9B4F8 2C1E5EF603450BC562A195E9F1CC903DBB5EDD926DED61EB7DAD9A91018ACD85 8E992234AC9D62CF763D2629F7CF9DCB210F48CDD474BC04C426E2CECCDCBBDD D02819085642CC479A7551AC5123CCEBA6C81DB91F6A27E49ADC764433697176 4C8F6A20247B49CE410988A3940B5A7593797D8A4F67CCA9C991D6790A819B52 AAAD0CE9206955843D46ECE2BFAB537F81BE41B6B6B86D86D1979AB37E177D41 6C865EDEBE02288055452DA705EBAC5D4AFE97D78954E3B28DFF4D0BA7F68091 844E7E681A3282F7FC211E13A7C644170B7CC7787D549409C688B1419D3454DE BF570A46CB6F67CA472BDD5A7B8E16D11A40B488136291D57736A445C9C25EAC A42686BD3320E18FD75743B0B3C78EA9652D67879F3C114B8A5E8B6E99DE9C6D 9A6CBD0990E3CFB656D0A3750533B6406B6E4F61160966AD4165B00477B8B501 D4F5B5588C9C4F88668DA9986CF0A4655707C0E19F4369AD260BA4E5F609BD30 646213E8AD59DC1FC6C35CA80607ED028EF33FDAFB8101F25522059EBA068ECB 55D5B090D680EA3CF483FFBF44E686EE3924694FD82DFF58B3F228223DF2B2AD AEDB5CC749C4B2F54C33425A5B674C0A3C4911728B598303CE6A18A4D5D85DBA 9094E105CAAD0F7391273F4E0FA93AE99076AF27F0B2A858284EB11050DF759A B7FDEA1FC7B70491FAB93D6E15AC08C38D8F20F5F793C089AB91123A01080548 802256F9B2667F310CBBE92862923F3119B8DC47A3D0E704AA7C37E63715D5F0 01EB120BF36C723F0F77FB88A2FC7AD0509BD6DB28E2E057E05A99D9969F3913 787C334514D0136514B9C8364ABD5E890FB400B34650D6B02C13601F6E733390 1B8625E9528AA3E4A8496813687BB411670B10C94E35AB1661B14E8877CDEDD1 1680D5A7F7A701EE281D40A90AAB6D00D30539E1B0D9EDEC9711F4EDFE7E4BF6 43E63A8CFFC8027A67E904BA587A0B33795352B8057E8F3D4D3EDFF75891A1A6 B9B23604BD9F35A475A2BEBFAB5153D461C07824578B1B5370926C4ECA10ED72 B8AA80104B4E0A36030309B41C4DAC2B4ECBB370B685B687EA872452C1956802 8F08AA0313E0BF5E84B7D4E07907787E83DB7DEBE0A07E40969EBFF6D397E0AC 30205649C933A94C5CF53A7AE7AE268BA379FAB7929975425DF74660B49E571C 1BDE7D5E9A26CC7107E99558F90AC41F7D7A2AEBA96ECF1173CC7E8A9C109802 186AC9C475950B058CB249FEAE07E1C10CB6420412C672FEE56262D0BD65048C AB5EB395752344A096B4C8A969075E5097220816ADFE6796A4713EF7A3E40DB1 FA5DAD6FCB4AF346C1FF3752585854C18C871EAEBA8B1BDBB21A0E912CF4F75D 566F9123E268E792144FE20B24436949E390AC737DC9BE22D70C47C5C68B55CC 6B9BD17AAA6E4774F79C579E31310F35084808F6F1115CA55BDEAF26E630E5D1 0C7D7281C405CFD48C478C457CF37D5D21D8CFAC0022154E1325ED7E7D9A238D B6937066FC0F884F0C8A2E52A40C234EA3666415B37E79DF04C373C5E98DC38F 2458BC03E20A874C61E9C65CBE5BB0CBB09845F475EE91D3A789CC4D1E3F74B8 16DB60C84DF6C7804457B00128944046044230C8B030AA6D8BBEC3C886399E7C DC62884EC2652F2428F6955AB676DF8518E1D75ADFEB9C29EB4D9A4C7942212C 07203BB13E465F42EB5E8F516F4F18B9C177FE7D536B4D467A147297996B9063 1029DF29E739D1A9DB992C1B98FB6EE5479E68779E5A24BB4C05C70C79223CC9 B85EE37408A99D9A7403D0D24CF484919A5BC731A13BE98B56CC23394F9F3DDC 47323EEA5B227BBE9312E2074193AC1DED29E570950AF946A09D12F52C841721 27B0CAEC834A391C1E2DB2D736FDC92B3DCBB1FC128034E8A2381145C6426AC0 317E796BFE0ED1459EF793864DADFAF394DC051DCB5F1E409050E41B3D90D821 94447BF370C7CCE0A391899D08B9CEB3673274A23EED41CB5575C8896C8D3EF9 9F2DA10F70DFAA9BC0356ECEC7CCBB9EDED943EB85F3998786CB1A305920B7C5 0F7F154C0F22A6B53C186C3225BD58863FE1D9DF38FE913EF330CE80EFBBC43E DEE10A0DC03F64F0E4CA387130D5783E8A1D74EC5E65D8691708D655B69B0D75 7063B34BE04A4423C0514D6D7E8AC8A8CA198E5DDE9FE491A846BAC77C8CB95A 39BD4A352A12C62DF10F9D4EB04305EB2C683AC3B4A9EC143167C7A506DF61EA AFBF31298EF5100910F62F31F50185F8000EAB4825599225DD33ECA9005C4CC2 042016FB9C02418CFEFDE691DDDAF317A96F4AAFF639DF1EEAA31A84A5DEA1B0 4540B756B0B4FCC4F51D80EF8CD0DA91E38D2FC1121054E9732A0A0ACE182624 166722D9D6384AEEDCD7E6F3DC49987BA683180D8424ED60C600D143EC9B3803 E12459BE9A3563AFBE340864EDE14D416EC3D3F4BD0D3261E4C3DDB32922D953 3229BE070175C21FC6F94A9B0AE96AB31605BBAEE010D939EE89AB91738C8F45 10CE2906877AFD2E5F39E7C45CE1454D1C167BA90C2CF192AC834A4D1605BD94 6D9EFA985E106984CBB4ED442042586391FBF386F79999855B4812C437458063 12660E29DA28D77760EDE77C45D84E758EF3D265D2AB232A7F63F86DC8DD3534 01CFC76BEE8425B16131F483104ECBB582FC38DE857F05AC7D8FA2428962BA07 2FF35FC1FE7EE7E2D1A6CE661CAAB28D906E17D9918648D16339B87792FDF8D3 B04EFBB83861FF4610343298BE567E5A97B8E41911E88CCDB6710E29F24D1FAC 22F85455B4B17D6CCB61DE8E639E0667E46DCD004F5ADFC2F6CABA1B4180A25D E36C1A57DA64335544DAC4F790634C28C10F6AC8DBA8B6B0143FB00E7E3273F7 1D221F65291473CDFC71BB4F3C911DB6F5B02DD38A296934DCC471EA9DEF3941 9861D6F9D72FA13168DF02CB8880043139329C14B0D93DB8752C4E006C8FAAAB 7434BF31F2EE305EEC12A2F8581D86A2F93A22C6A16E7255B84937A97541F875 3A6737AEEAD8CC05C55278CD05A93FF79A573F08EE662D1451B7C29293FD3219 FF1F07B5EDD449F95D802AE6EE9461525B57B47AD676226CB0AF3C6C0E23CA49 8FE6744C36AA9A45F26B4E891691FFC7680B32B0F6C4422584579C7A13444C38 4C9067787825B07042E63B9C6FCBDE652C60D5D8574423A43CCA948E5B638CA7 813E94BB204CEE5BD7257B98D25F0207709974F33A9635621C3464137BE43708 97921345C6FAE91B6E974413EE5F3AD54966FEC1930A04A06B170EC02D88C95E 74FC4791588B9C5E8325DBA166CD541AC0148BF212BA9B24171312DFA9D8D946 B413C86FDEB625C874A94B986CA795379CD5B4061D2FE3C3A44355629714EE5A 3E6681C38B6C63557220661C4F7C6B38DD78B2D53021E9C3AAC3ECD21293590F E10CB86944EDAB1FFE5380E71276C60EAB7E9F1DAF306CB780BFC491511FFF59 EFCF82AF7044F013A1FDE387B201745FCC384A1744B16A299F59BCBAF2746733 C66F9D61CACD3AFF06739F388BF17F8292B8D7CA97C74386C93517AD89CDD358 18F35429A323958C0A528989A483DC1C8283F934AD2D560FAC2BC019A171E538 8AE1FA57FBAB7E9DFCE6483A0FB077A3A9EF1B9A39AA6B40211BEC3A46F1FEA6 11304E85DE80D20B8F155A2EE61B251535B10F4125F42E96F7E69CF3842F626E A34211CD49F42E03C74C1847E4DAF520D1A63FE74CB64B9D8314B8D1EF27DA97 E9FA4832346E86C1A47229298B3BBB52D079539970EFB2D13C85A1FDDB9DB567 0FDF672B9F3D74BB0798233CDC7A5057B697A11FFEBAFCBDC096A3AD9FBEDC38 8D8DDE21EE771251614E6540F835B394D80A2AEF21B41B6BFB1B762366DD8795 96EE306285FCA61F798F7C5A42C6E8A030BA7EECB8EC0BD769645FA3CC20DE1A 9107BD487278F660E74259BAB36599164D75D76C85777BA55226FDAF8D0D5204 0E030A10E035D32A32CCAB9F4C9D5C29ED4054CED2C59E5AC4177C736158B095 E800D8FF594A7E58589188F31AE61C754621CF48BF115F9DC62DB1D2C8807075 8F0955CEFA77F9E16A142D71DB3B36D27C78D824C85FD1B6E73566EC486937FE 85441BC81737AE4594EA4BA70404081783D86D7F782E996047C8C2333E1C00D5 260BCB452CD4F41A18368E2450F45F77C849DBF780D527C972FF1CB1D90E2155 B034450732E836A304C0C65A22DA2D3DC0DEFB51C62E5CF24A63F38CA9A7B725 6CF94CD6F2DEBC79AFC90912E05169B17C27CC63FE88C586A3039B246F6DFBEA C4DEAAEE8D94B91A3AE29A0F60470725430073E555AB6B69E97A1CECAF416959 EA671A353EEB40353A74C4397056796C948CAD4E34AA5649843F549DFC47F07E A46A2640A04E9E88F84803551A1858AD3C491CE4262EA7DE5CBC624CF9EDB79E D7649BBEAE2207CB7EF264D13487BAE1C05B47BE48EF0A1E423D52D626969F19 9BAF6C36A5F7ACA1EC5146751538C74BBC3A33408E950907D84A85745CB3C619 30890699C822D7FA30E4CE63A4B53C442D9BE56A99AC2EDD02C799E611050018 C6B95DFAA9355B146B1E3077C44DFFD62E1ADA32C5C21BAAA41D38C7782C1CF5 10ED256CE14FF1576E8BCAC3DAB51D9FC8035628C1B503D16659B2B761BB63B5 755C01509EE4433750EE5B0994E956B1567D5F1E9E0B7DB27681799299FEF9C8 C2AD946019AFC351D190BFA2C1B801DB3536BE9721DF544D11F39EA4D9F1DEC3 462E608F9CE48AB37F16A1874FE5F4AD980EBE76A345A50B2428C3DA1925ECC9 DF68179939E4EF14C760B1EA2E4212BCE7C0CDA8B34CF2990637829E8E951ECC 0AFC95875DB4F44B7703547C1D3CED8227C3F7AE582111EBC86A8908515FE091 2D12733064E9D215D4A4EB350DE11D3D3BBBF8AB4C628CDC2A8FB41FBFBC4048 AF83E702287BFD3D16F6FFE56CE24008B735B517D364E7BA4B02300B594DA978 0937CD3FFC89CECFAB77CE33651B05F18E56EAEC5779687619FC1878825B3776 89AE6FBE36BC60341E2AB511079FE8C9CFC57029CA387E28E78382CB0F318B8D 3FBDF6F5D8C097BF895955BAE8591CE021CCC49976EACA720179B72B68EC6AA2 427CA0A8808552F93676CD7156CC445787A052A784EA597E3E557B1141E32EA7 9758E599D3AC3A4A33A7ED2282B39DEB413CF1E63555953037FC11D9774E8281 E13DEE841B104551889CBBAFD08BA6485BD850957CC7D8355064C23CCFC09B86 15A1A2666DB274D772064661AD58CCF8B04336371080E88695461B7E0526CE77 0EB7596E6DBD17274E021441A6932317D5024AB0240C4944AAB762613A5DFC8D BBAFCC8C2A09C204E0558F49B3B9044BEBC0987548D105028693DC68DBB0A9E6 600C9045FF964A418772CF8D73808A59C278A9FE1825AF4EE6884E4E91216179 05E79DD583FFD06888AFCFD95E0CFAAFE51737076845363AAA1E59E1EDAD9D6A 0B392522EE77BDDCB6D191C7B797D203FDCF2DCDA4B6D4B74EBC6372A48B13E6 6D33C4973CABF2A3D8B91BD71421748308FA2147849025FBD2F1866908910C79 59635A0615DEA01BA7890B3AAD778D109AB6A785FF83E8734FA6AC6F7ECC990D 6DC1108D7D15164E248C6D1F0BC962C52AD2777B96487CE582456B2BB1BC33C3 3425403557E92A95DE74A982EA07396D0E7C5FF16C7BB1A54124A0DFC6FBFAF2 DBCBC7A2E723EE5B661FC62C2C396A3E3341DFE5031DE0E15E5BFE6C8305C555 728B93DDB0D2F998EB3D6E8526A25D77AFDB89149FDB6CBC03B80C71182E0393 E451562E199E075C5311A3674F372E6F0F2DE8954F04429B27A448442F0CA5D5 2404F4537FE01C9736A786163FDD429EEE672A60D52D5F58188549D9E9E5ED41 6C25FF8E53A97D859B18F91025B5501E09638D04DBEF22AA1D160B9CD4C94876 9EB9D8BB838455E647B8D4F4E5ADAC207E9C1F373C63B3987A07E0BEFE97EC54 4E24C1C0B953F3DAC89D066DC66CFCD3AF8AB505E6559BB8E9664C0647EA2030 65BB8F35D639EEFD9C0471BF83B8CE583C5288B12E164CCF57C31C326245A528 E45943DB79E305DCA23A2EFB82D1C752C7499CA8A01A7ECF7BF6B287350609F0 A2DC4FB958868D298978EB2FFDCDC4A0C8DCEF7066287EC7A53F7B350D5C37C4 E7C92A0D8232006FE5C7E3C22EB590C93A4096104BDF5117AE70DE4EDE2EF87C 11602CB8D4C3AF679D17FD5167C1AB635AE508EE90B912656E9121BDC481E2AC E7273B5576EF99038F2F07C7A23B5926DB6D9DEE504AB75DE45666AF661932EA 75AF60F39A6456EC731E53452B9BBDD951DF4E4FB7374B0F9371EAA6D4671432 461357C0C60F46C22A1A2B643CCAFCE21C74ED943AF4F5BA2478860F56042F0D F85BE9A9E810FB96E5A9D8A979CCFEFCBF1603F25AF1837A9191759387053011 7CDF0BD12C3417EF376F8E3DF06B3C48DB995618F372DA8705C9D04297D1B832 93C0316D8FAD1AA1F284BE4901E4B81079D76A018F871E3EA3B5BB46493652D2 5F7BDEE050F252308FCE5FFE339AE2230C3F5C9A28B875B2BF2A915EB1E23F2B C38B3A78F3E5DAC5B295BF326EE53B9BEA7D505F4CC01C6A8D06B90ABBFECF7C E71CDD427000179311C9D3BC851E294F95BE11F2F85A6BA3C217EBBB22761BEE D503CCB29BB09393917EB2F87567B4CEFC4024CD88761DBF9CEFBDCAACB1CDC2 AD3EC0B833F79B10FF2D912BCDA6C65E957ACFAE5D63ED379FF131919BCCF1E5 E88C26463F5B9587BCD7E153A12C696D8023B2E49A103C0C61560784A4FC0DC2 9A075F00072064FFC2C341DB19D82E11EED2648C7F6CD06270F93F4A2F5F8B75 858AD309A6D5E63B583A0E835D210F60FD71B9E159A8D639FE5E774D3754D41D B4B495EC984DA4AB7B831D13EB891A9C93150F3F50FCBBCCF047879CD4CE8F0A 0D8C9A90B89F14ADA6644B83E6D0B0890BDC8BCDC5EE6DB85CE8FA5F02DCF259 9DA572E0FBE9B2D9E2517667366B415441C6A1E56BBC5D0E6F88B2C03A17C2EF B13A2166C34D3C4C7D17DB62BAF7FDC49FB301D1AE0524D87D96955A2B38782B 62AACDE5B43E8D6646DDEE92C2C7EE93E4D892594C1D1BC58DB5E503F9A6E1F8 83165C19669F866924DCE4CDB53DF78E3A38177AB1507DA65916AF2A6F7CF34E E327C51527BA6E8358094F9EBA9957914BF0195E58ABC869E79A2E68C2BAB04D 75267D48E998F36CCA9A94117D1187146355E5E65A15A3D9C123F9199352D5E8 7AF96F0FD88C897A13A810DD3960B517462057C0463955471ADECC244B82A0D7 A93F3AA163855DBF547F7824231630C255F50311CBC7A48273A5FF91722480F6 782337A984344897E888C830DEB079EE3E7DA1312C95AD5E5078B63D1731102F C928820255CE8742C2A4B412AB6D662E40C7A767D06C73AFFF8C6336053078D1 7FCCAD175C7174016B054B3D09008D01D00D6D7FFBF6B39A053AF0181B718B90 ABC6DB0070BBF8B26D51D46599D8C2DD46A6F4A033FCB04E9EA807D3F3E9C45D 99FDC21412065FC11E2C9A0108B61BBDB87C9FB92CC6D4D32B254A45E391051B 9A9D77F5B2AB5452AE72B97B458B02742D74B5A946A9B778F28492F3CC5F3524 6645C9DC75BCC4FB2C994C86F91BCA6E3B20579C2219BFE0428668AED62D8470 92FAD9574363420F7F118A93ECC35F6FC174C74C016B503AD35710EFCF4C5CF9 02C7FD683D964E60A96FC687F611C496120255E3BD59EE81177B5AE8B6F69B41 BDBDFA0FCC571214D1F0DEFC52F9E41FF24747D2909AB62FDC59B498A76FB399 BF2B8F46AECA0FD74BA98994C540264997CC5615A0B601ADBE602E43ED5EFE81 9468A132227B985905AB5E0C8146B860B8E4D4CD3B33816377E08410ED37E146 803D54A10974EFD818ABE474DB1B187171D344AE88A717A333ECD8E45AB5FDCE 5E9F1DEF736B4B401C38C499FB8D374FA3BEC0931AB7A1AC2ED1CA55EE08D4D5 84D4D75043CDDC6F11795AD6C2765DE8E46324A8E32568903AF16EB7F7D42D6F 9EB34675EDDB76BBC74B8C66D9EAF9923844EE39FC4F8F36D444BDCCB32D5987 9E1A34023A8389C07A8A54BCFF045E57C596D9CBB7234F3D32CEF39A207C35C5 2EC594BC6D6F4D421DC37320E387499BAF6FF135F251328367021C8D48392B80 9CCE1B2FAD718580B126C50B243284A47C22D8F32C5F28F184E0D6A657EB6013 9BC8D85309A05A9A9302A61B9A49E8CC329F7E54AEB59BE426CA133C792FAAA4 C01FA639598C7B21A85E441636E19BC9CEA795158ECE11889F41D325BCD4EEBC 4AFEF80879C543CF28FE5E965E110C0322CFFF655A0C1D596A5ED2E2F831AD10 28219C8C0B7902D50E09C2D0041A2934A08A995E9171709ACE5B14B308B6D3E5 052A17FD842FA9ABCD527C53261FF5D874C5B805D1523FCFF4262F6E92112153 213154DBCBAC2959B6E5676A1735C26E2D174368745A1C8ECC5919AE8236BF03 CD207928040A8C5315B450948EA4D23B99F184137F464150D390E697E182B6CE 96ABEF0CB4125C8AD5D39081DE8A63FFC4F738FF4148E264BAC0F8890627DCE7 33BAA239C09323BACBFED301A71131799FDA54B04DB83697F29AB1CCB8FA6E01 DA5872D91E04392C1E635753DEA9C107357DB99D502CEDE64B65AAC691DFA7D6 53D366EACCC105D0BF34A4B6439AEE68BE5861A9F2F8B553F836B73D0B49EC4B 3E2AA6A55A026FD2258DD2E17BE18ED3AE93168243710DEE4C351D3568E39A5C DFA3ACE49BE65A86B2653BD63618B3BD1BD365BA7462140B4B9B2A81E0786410 46ABF80BF6DBA2E07503107A82A7DBC0B05A3005DF475E1BCA6417866555174F 08D6E401CC5EF31D8E2F2E89231D374AAD3467594BA95798DC4BB19A15A98FD4 D02EB96DEDE561B6A448F6772028022595A1C944D8EB4C9C0C04D3EBE1467157 99D8C5C72AD625DCD92856C1D793373784060513E260B587F3DC364C484C36AA 07BEE82A0E0BBE6F80D3467F02FE6635F508A6EE90FD293E81CF99CB3E52FA0A 763DE6CC0114A74458F738FAD91A088C9D25976F6286C8E0D2DD61A71643FB69 1415F21D1F6A95462F889DD443DEEF30D118FC756F917A5714C893CCDD7FE3A7 57286E3A15D5E87931196D64A026DA4A4C907C38BF95BDA599DC7A4F1967746E 4473ABBE80A5DD49CEA25B2BB8A9DFFC3537A1F5D4477EBF142103787818E09A E5D50417F82BA1C422B33BB66FC018C007987ACC6AAA798524FB776D7550E3DE 95B496B761D2B1EDB6B2BB0134A039D4BAAA83614B0058AEEF40A693D24AFE9E 7F97A02DBD8119651CE48E196A6F60043B34DC444DFE2ADC6E833E34E52B3455 A2A035DD0BA864612EB104C0C0D5E83D631BA37F10A7AAD7F630C19C6E8F6AC0 DDF3BD600808041AEA7CA46BC360F5DC1A8001FB2C962237E77ADFD7AE114290 F18B5DBD7456F3FA921B36CB4A6E90AAD8D12B27CDFEA15A81A590C1F3988660 BE432900B58B1CE7492672946CC32523CFDEA14777B4596330C7E93FE4C6E4C3 139C7EF73A4863A2A76863438CB15A31019289896D48AF13DD320428271374CD E901035EE605AB95C0033DD699D58B49129B0AB9C535E8CE5CE9F84389B3CBEF 33FEED3C1ED80371098ADAE53FC2B9A06515194632D184B8124C6BE8A25A5E16 9F23EFC9D3568513DACA3A97D8030E10D0DB62A117F573443D78994B623D7D39 0172E22566EED959B56B93A51AD64D9B36708881A2598C9422463D8BB16D5A78 94FB7535DD5E3BA93E6D2006789586C2441831522B2A87620835926DCA369367 F96E54DD0783CB5E0760E92B2119BF1EFB1B7CF18A70B87E5332CC6DFCF10CA3 F62A22A8E4E6818FC045B1B0FB0EDEFB230BE1834CA846F7C5E099A4C54C5F65 FA029ED16F0BC09AC2654C7A9B4114BE54DE04889A2EF322327817FBC8E6D0A6 F5F115A28A2759CEDE0CDA907192854912F402C9CE5790512F3B4B85DF290C6F 964EEC7BA3A5D2AF19417660F9FABBACD29CD3F1D0112E40C23C02D8A906CCDB 2757C309D8B89B88C3D3967D4BFC45472BF2FC58E888956C503F2774EDBC8C00 1E50E35497A0FA5131383AFB3CB8CC1DA2BD99C85AAF3A2346EA3DB89BC877B5 D37832226452483339333B2E4EF87E4B2985916DE138BC548D06CF247FD3BBF9 DC5BED8B1AB435814998EC910F71D300069C1EDED83E9346A85A3AEF295AF7D6 06C98C6454415056C21395D6FE6D636A1F316BA3E3AC963F9064532090840548 A62D1E3CAA038509C44B2762D363BA88C32EE1E82A65849278077875340644D3 38E445E3BF798205E90D6C19501246A2A77B93A65A82C21F763F7FB4AAC73823 FB377164F0E7683A8C143AE37F95D424C60C503640565ED52C9E79F720038392 5AAF1075DA2D9648C691139F1531F212B9BA66085AF612C0A6FCCBC49AD9A1AC ABD7BDE6998EE089283450DB280D71078671CE182F5C8D6B5BC6FD1EFA3D23FE 66C5FA9F47C81C84B81065B3AF067E617C2A49FA234EB71739D885EE2A088D60 F95439492707E02658BD498EBBF56F0435955718607D56B524345DD34292879D FB035E52B4E5C232771F6975285A56B6B3808C608B5408809069305E1DB194FE 33A29E71F16FDD2681288216A1A284919271D497D73E7F52A1A73788764063C9 44BD46F1E6F60A2A1709A06D653336A7845898E65524ABB1DD3EEAD1554B68C7 722AB41316562032D231946B27B2D809CB3AFEBB2D37B6BA50578A7F817B73FC FABCB63DF361EF5C24A607CD352757EEB7FE6EDF7BD7C1C0671B67064BC272C1 28F775A8012234BDF543AD5DFB86F64FDEB355F1D649AFBCF651BE1ED1DCA962 EF1F3235005A3CD6DC0B78DB6CA65A0373E1893114D6D4E5A5EF1FA6BE38E9AD AB6C62AB892E9AAD121AE50D5B185651FBA345909078FFE9FE7492EE182FC5C3 3F9717CE10169438F0FFFC3A84A84FF562B8D2F825E305891758D6B7E096C298 BD344F4BE443E423A0CE11E2428000032E06DEF85E3A5BCB9FFB8AE4687A539A F6B24E35385B10758D3CB03B34020341C9FDA67403C2298AE94C70A18FDC8BBF E7E0843F4BACE6D4F3A484B1C425084252E81A99414FE78175B23985846B1564 D02B333BD8209D16F89BF12970EBF251F32CC45D0D59737AA3C416EA61B74D23 75CD0040F8A289F1566CCA6B3B09ACC51AFD4BE9037483134687EE187C41E571 EF828AF4827ADC11BE88B28A0CA4E38F27DCFD55873CED7381EB4ED80A99524C 165FC25B21A0D982C650927023B246A122426C45ED4A730B66F160851B24F703 CCCA8BDFA289B0F957B87906EEA88F714497A11912D71355304483765ACF958B 3D114C33B1A78D3C2E667C7F12A3E345AD365CC31F8955AA214A4741E0AD8B06 40BB42258A561A5404402E6DD847A49621D5EB06FFD366EB14EB05E6140567B6 A3174BFBB7951F65248622426E41630FA9CE9782F77754CFF68E1D3BBDA2F8FF D00D99D23CB38F14645776BA3EAA34992055677E2FB4DF057A823548FB0C52AC 8A9511048C13F0B50FB20ECD37743D56F55379353FA48DDFF43D1C712C74476C 20391932824690F5EFC14869AB68DD533FE00F382469C1CF841B1E3C91285E47 CFD5B77615C6B710E9EEC208F90E27A363F41C4F0499935074B528682F33C1B3 7AA5C2F16CBA2FC1E0F87A0AAA3DC8BF4A6FBB91CDBE978062BAA77CC4B41F57 FFC2C9160AFF5DC1EFFF988ABB619D198CA98B2F9BBC97A34F86E0F7CC245AAD 91867351F98D6E93813BAD63F3557F1277F311B80E2E8DE6F16E34E0F5FF5FD4 10B68D52F11DD15EE620C15C64CD8392072419F74F8AF6FF61AB288E2807CFC6 6AC4603430B5424CE3F8DA182464DE9588169350908D368D15ECF34E90D8FE2B 85EF8FB0318A8CFB8EAAFB422EE66436DB534884A79348EDAF9A2AAB5DBC6B4D 224F6D0D41C718F86B83EB6807D3DF277BF391A95EFDDCFA4C2DD49E6FCE3A94 E4C4CA7A8363A8610A5CA5B7B13BDF3E4B5E95940C84D3699C7DD8C69CE3BC8F 1F513D39C25406A42FBC0D4F7926F5074D750B7929BCCC74B2A5A8D9326EA944 72768AD4DF13263D3D329FFCB2989A21A5BAE9C46EB0F28A5A5F2329F95797E4 A6A291DCECB13244146B8A1180C029610DA9B5C5242046D5C3BAD2AC9686F236 70B6B81AAF86F15D54AE46E75D39EE2548264452BC220416E57EBDEC45017949 2DC6718A3D14B931F38A389BFB88B14334447EF414D803100C3916FDF4F0A8D7 B68BE36F7B5AC9FEBB78162214DC349D6BA4F22D98A2FD90B9EF3A3038FB534D D6EB70EEEF1CD91A0487E88B1C0227FA7D1BADFC30DF34FB81E35DEDA1306C10 73CEBB33B7DA3C897752947CDED15C68243F7E1E9716D751B5CF68D32E9433EC 8317B6910DEDF297A1CFBF95C2FBB92EDA7CC2A5B853A5B3DBB1E2C869A13F8E 08FD2ECA621A75EFD69E2FE9CB5B10026901F535BF4E7F30C7A6AE3B00F55696 72FA49ED6B7A28F31DB28D2DF9CA1121E34036C6227BC244A8F22A48F29B7F3C 6FD319F8D8C398BF6D1DAF886FA3023C4B88777F963E74AA0C55B6EC65A38431 5E49F222F81AFD66DACA0F874E2FE897985C6C25347758A0D8608E6388D0EB1B 18FB22015E33B436CAF97804234749254718090DBD3C1801DB22823D0E172E45 978F25643F19AB284BB5A9E7BB776B37107C1BAD20BEADAC0E373254B3ED740E 4D0A32A6D2E8677F28970A49609FCBD876D5B8667ABCE147754178FC558D24C7 6FCD30FEF074372FB3FCE00DDB5B18A56300910F204C63E811985F5A3EBEC7F4 7A654939C8C2FCD6B3EFF62720368FC1264335DFF72C3A9B0E2D7B48E457941F 5DA2170F5448D870487D127779BDA70EC0DB3F1867C24561DDDE4DFF123D8551 280657FD211EFC9046FDFC083B03C04A7235EDFC207A00EFD54B962C94596101 8CFD7E202167DF4DB18E58919A83AA00A2678C370AE5F17623FD28D5158B8542 E5A28FFBC292BF1D2D236030187ED2838DC53B5E7E7536D898D88799418D9CAB 6C8C9EBAB0F089FFF4E2182AB7035FB6DC7A1DD60DD708728E65E7180CFD7B11 1E5C3A1B59B424931EB0854E08A29AE3B8FA326BD2EDE7AD52CAB7BD80F2074B 0054D51693EB90200F8D80BA4E00BD079DD54E311625373FF739251160E44EC3 6DA82F68B5F4A2B2CDFB8210F6577C22DC2B8800414F9F2ED2DEC8B5515D9D7E 9B11C9AD0101A0A5831C53AC007048D0DB8A377815595CF63B2F9B4AA6CD10AF D6802D71A97035F1B3C253CCD06A931F5B6A1BB87C05CF18332783033FB6A09A 1E92D5A657DD5F95969AB7BFF0C1A213843B1C247392E2316F3E4E85A8DA8048 F67CDBA7067FD19D3E6AE0268118AF722EE59FADE9624050D4DFDA25797C55D0 2E2C4C345DCB184D0706B2B3326CE2875FB12AB338892AC5054B51DBA189B2D3 780A6FE08E8E5A729C44D241FDD9074CF2869982E5ED9C80A77E57D90BED86D1 A49DF3D189EB13D2B25B1C176680304FE6FBD3FCBF4D37DFEF135B5CA76DF4AE 34F56E08926B653B76AB1D769CED9E41A017B3C6F6AE2F5DB2228DB4B476C11D 05C67986BC0FE0BA77E1B57A2B0B6DE4BFF8DF20DD19DC52CAC77C9A457685C2 3F255B5BEFB482136AF381FB2B52786A055F847141BC5292735A255AE3AFCCE2 62248B00DC1BBBC9D87799A72691D56D737C9143EB92D779470BBFB4150E5B8E 7CB3DB69B383352211F2BBBF0362F1F654F351E58B4CC642BCF4726E3BBFC4F9 EA7186583E117D73673905CBDD7B33127B3BE3F979031B6E0A858B205C4BD450 46FB47FE7EE3F6662FB9D6AF3484032AACF368E23E16AB67AAEF5D21EABDF65D 8B4414B902EFFF9B67701B836D91C20D92B5C18D980342E9BD9C834A4266FF14 DACEB9CDB91ADBC8377446B07192AB3401CFE6A35920ED5089720409E1951474 C33B5F87E617EAE9FA1B7C315335042A614794895DB545BAADF0939746DE346E 08258E8481F9A02A854E3773394C58FA1130E59128A3D9B229AAC8FC0D7F029A 4C2354983CF6985A495983CCAD4B00C8B22F818E49122CA60F34434BC713ECE5 27F7DE27339B9A46F0D9DE2A36056CE04B185760E8A43C4D61CDA9C9618010B3 E6B7B3A033A872EC36B3E67CBE583F1897F406AE6E08AC02BFEDD4BBA87897F8 BC3262A26AAB01EC30F482139EBD866859219D64F66D6755E26C2ACFE07A94FC 9D93C3E4761B8B9A37901611FA55FE882D9DF38787A488E9731057DE5DA081B7 D3052817F5BDAD299734960179E370A954FC694EE1CCDB9221AB1CD47F5D8317 ADF41385B22374FEB8697742F87E473E2D47DF10F793514C5CE04BE2C5C07984 BF6D9A16778EBF7C9E2DE1AFCAF44E45E0F419E94042DFBE37677D0BDFCA47F9 3D6B72642FD35B6568ED554D2CC8B4341F8FB81C33763C77EA401513125A5554 4C091EAFAFAFA7C19CEC41FFF244F013D8C6298EE0B9EBB7932E14541B4BC8CC C3F080415A8F016E2535780BA2FABB5753AFCBCB13DA8327317334D9E5605AFF E696E2879992B8F01C19227B3B31E923C14499ACFF83B5D8B73B300593EABC9A 892C6A90B66A0C492953E53D75CC57F8D9B8BBB6E19994FD03140DC1C868B51D BE73A61F7C685A3A9ACD538BF020C5363B1A146A83CB93E7B8637100DC6EAF1C 9B9422C4C0EBDC5181621AF1C3DF04F9F25730C40C3738D864F4089FF310B532 AC3E34974D87DF814F62F18C9766F2FCC22F2E8E2D1345AD1031D25FA6E379AA 4AFD6923CC92B3DB7880A7DCD2125B9AC32731E3FA2C3DAC501C85993E3BFC6E 3CB069A860FB2BD2F47E9A9A8F5AA5D90926A7D5B1AFA4AE370C650C18287C6E 4340DE71CC7027B28E54F398EBE74B101ACF563C54DF227F5857E435E9B332B1 A2CAB0E8D157F6BED371EA19CDBA98188697838808AB64F6AD8B8C0B611312A4 C52284A1D3BB62649934F3AF83E8680C4298107A9BA4937BC5DFC6E02B38D840 93798BE30797112D44C9AA9CF4E9437D11A8908D440743F16048B8F01E4DD644 8437F01748A496F0E1E95F1BF0A8A68CC3EC5D5687E8AB253207702CB2FB20AC 7A98D2D9ABD7156A270285E95138E27431FF37807872075A8E4B81988D59AB9B F4BA0E52D4B1D19047CBF5F66274B572A28BE387F4B580630F0C6199B63992DC 7C53B6E7B1CF6CCAF045CF09C8F7A0951921667A93C1493D749C2265ABD7F562 F595D537479000E76F5821EFE62FD197113165DF4289D5E1CBE9B05625A5F995 BB20409586D632BF2757C067AE77693E83A8921E04D3BAA94382B93A3E3693ED CA5A6C71D0073B78371D58BA0D2F016A43350F00343D6BEB95B49B7226ADEE5E BFBE8E2DEE5184187949A7CA9849127CA4E99CCDC1C550352D370567C62593CF 9DEA6F587EADAF2F04EE4F661D8FD7AE380827082C9AE060182AE0C63A3009E0 E1BEF1550620A0E462A0B8918BF60E06B61D3E435B428D615304AC3023E83772 C6B048A55AF204D70609174535E26D0E6B3A271D40AE1C2E5D73E0BF2ACB1C98 FD29B84C316F7496A482095BA784958039B6B7D2E9BE4FCC3FF4AD97B3CF54BE 7BDE581049257BA31BC9AABE7ECAA5701B91820A36C62FF7573346B9B30976F0 A43383030B52BAA6C11DC6C8B745414D41D4BDB61CB97F40BAD09BB4EB0D7209 2CBE2F02E4D808AFBA930C0BB8C106C5E59C922B770648FF3A3687FE55BD4ACF F0EF66BC4A2099BE15B16EB32ACF3A27497DA2E6142A2B9F13EA2A3A82EA7934 627D3971EFA6AC61B42599CB1FA51AB0DD8F4F7998B3CB5E543CE620E159D1A9 1B8121B319C0C3620C1355BD1F9F290174CD1D2AA05ADD70D60918BED9FA0A18 BB918CE247F51AF1B246A6515D62796B98F4F84D0F10F7234C1E6CDC520C5561 3C3D984560364932AA1AE0E2452FE7753916DC8B043F43EA00C2BFE47C868308 F390F7450AA754830F10AC9FEE0F230FAE46DC5CB40CA7E2B6E5CC8B22D64BA2 E82D011DE86FF52F012539ED02C4F58EF348976964AE729B949B77DF7ECEE7F3 F51E4202E26E21DCE18DC0FB0D31EFCFB0C188A52699AB1F0DC1CE623258DF54 B0332C84EEDA53BDF58809283A55C1B090503E2E1A0DA3E647832CF3231BB54D 0D6D6E4BB80425136FE1727EF3DC39205D1079C6414BB18C87AD7D3B445FADD1 ABFE8BE5E9B857942BA11EAA62316CD74848CC89E92D8697F20486F55EAB7468 FA49D3687C78B8C1A65C6D1D28860779F86A4068427E4BA5D8D5D4035B6FCA10 363AC21D2D9FA6CF465327CC19350184EB823B37AF8BF7501228FA813D9F022F 2FC12A96865C7AD4E799760C395A3FE61B5BA1369D12B045A8457FC32BB3CE24 2EE58564A0EA57A09F0EDC7223DB08C10951D4CC603E0F71859C4F05312FC832 5A2E34621E31787B0C9C762427803B6DD882EC59B545AB3CD8EE4700BF7E1834 C9431827E3C2A98DB9D2DD1E525EF0387BECA6CA7FA349040509E0C4D552BD3D DF1EA3E3B35C0BC7079A2C2ABE6C0DAE9EBEED559B413E34461642640A640244 A10E8F7A82506DB94CF83D2D44754FA3C2160821A7AD460762CDDF64D0960980 FC341EC9ACA3BFCA0600665311BAA75675E1D99CB2F24AC2DE674F06C03C6825 6B37946C533EB12A38FC2B31C52A60CBBB09B41BE98646966A43F0AF2402F4AA 57C0361DB95B1CCA33E4DF4E2EC2B42BF6DD85988CDA7E05BE6D949404DC878A 6B3B926A3A7ABDCB84836DEFBF5CAAF9EBD136B7CBC274729C142AA96FA6F20A 12010DBEE9AE0F53D568358ABAAA78477C9553F6C499188BCF09F0DDA2153035 2A47445EEC484F2A6BECB882E2CF121A04BAFA1A96FFED21ABF2903EBCE81DE7 DFE2787FCE858FAD5A9DC9F6BB6C520715C942D2A79D8EC549108474E00AF2D4 D466F695FF681F548F2829868172F14950E42CC66F826A3A6924A889C7AD044D DA06BDB19B3A49E60CBE7E9392DC77D06DC6600FC191717833206EBC349E3C64 AD0A7A3AA8EFB80C40A3B1CD93FBECA377367D539C0A0E91E2E6932BA2F50840 1FCB806459D2B4A164F7CA0FDADB88D91A4C3EA388FF62A402155A0E16B03435 F678283A1F28A5035804D3AE65019F31CB048D95BE60A97A6494F32BA9E17941 596545162A04FF0171A36F277F49DE998A3CBEB8F8C598AA96308CEF78ABB2C9 D8F3729FFCC82D8F529F017AE00AE9F8E5B02C8C1C687BC945059D72720C9716 9DD15F79C992F558874E9DA253B01B26F75F9F0ADB384B919F5A8427457B2EE9 7CBBC543066CB01F02276F0FA20A12FE9CE7E69DF74BB456A417588C22F82CD3 8AE7913A959E7D27B759C94D67FC55BC4D1FCFE739C50E5509B6F272B174A7AF 688A45DDF72B398B6B41A3D0BD3820791C943656C77FA49AE2447079BB4A61B3 397CE8F180621778693642D8493D2A3A1F2C54D475643671B1AA972F87902C62 8EA53B3EC372FFAE46CDA4DD79243DF892B2B49A3238028F41FDF9A1D904661A 5C89806C6E564789443F774A0D8F39D1925367747E62FF8F69279157D18DF644 A49318E7BD4F836ED366963BD57A5F704A55795567F23D2C1B07975A82B76EED 75ADCA889839536193CDE285933BB2495252D7B33C438D28349F30D71E5B9910 BBBFAA5D5F894E02EBB4F9076179115E5C082B34EED18535304B12ACAF3A5D77 C10AAACB24BF7CD17ADC52666EE8D730EBDF4659EA89EA088C1CB7D4CA4CED36 8A99AED7F997CE967808A477315F4919506B28C71805BB5AD4C797F5F98C81B5 3BD861F9F57D65662034C1D4E88F23A8092BB709FCF1D2F481534A4BBA20A18C 6BF85598FDF6480AEC0989533CD11BD25DF8C28ED16E6E8F75B91CCB41400602 DB164070B89F38B4FAD6867886DF305D45B8FD57C72489096E0CC2153D26AE41 7498546C6964461FD455441EF6BE1AE922D0E2A62253067BEBB65E926AE232EB D76AA7976EC599E9835E21E1D9EDABC53081E80F7F1B338F5A5F7D4E619FD6C8 2CDD33A1299C5DB13E7F5BB3765BE54EF46A2A5E4DB5A00D30609A085920C7EB 68DE604375D37EB9A0622783F2332E6FBB4262D268B79F5E939A99572214F969 C63AF218A2C6AD6180E819E880D9A78B0128E93E004B6510769015A724F64DF8 0E37A8DA8E541E836CFA5EFF5692585AE779045D6D4E2EDC8580502A5557AA7C 7C21EB7DD58225EF9676F2134E0B1D6038CD9CC41AA0BFE88DB3E2F1C8360576 3FF3557F29EEE84D0D14DFA2801DD9E8BC3AB5DCBBBFEC020FAB62671845574D 46C4BCF1455888C25EC9DCE45EA37E89DC6CF152503F9D118B9280A89C8A0C29 5E83F0DA2851A04DEC6AB0AF04B0EC40D17470605A874778D089F5150A19DC33 E29CD339F738111CAD30E1C542749C2CF8C23AF56212429CEC5F369D8D7EF956 5E3B00E83062875E4CBB17185D672241E2CE4B0E5CDAF8820F8B3D0B999CA50C 995EE9678A23B8E00AD23D18482C30DE5425384E2F7E68A8D7A1FB279B9B0502 D6C40FF8DF5137E9AC0FE1300EA255AE4D6B39AEED6F9E15711AF84C1E913D79 8F3A0095B43C875CC40262D707A05BFBAFABCBAB5071834CAA3678C5FF44BD45 6E11A024FA94D01981BE7AA5FB84450F7052E60006BA5CBCF8E11D7C859B464B 98FF90852E1B3AA5BE061C3A827B015EF5C7289C4D0D291B5BCA7E532F57ED10 48075D98290BAC772D84B07B1F7502B4DB59BF49EEE890EE61DDA21CFFDE7220 AEADC068CD3936952CC4735D59EE4747DB9E4DC5AED7F8B096B96D94FF5504B7 503CC1545182BDFF265410169208710DB4B7AAC094271076F36B90BB64202084 603747B336927227B88B4E036C6E359FD01838625A62F8D790C782A738D11AC9 624F0D4E1C3958B7FB28833B83CC9F54FF98EFC2D10674171B50335BFEFDB342 AD1344F973335E8F8AB6D483A8C75BC8B33DB9C49506DA009813979E6C9F5BF0 1885290C2B7F622EAD2B998CCCA6FD5818B6F9596A8087C73D95DBB1ECC3F414 8B2807A89C2734B2740E518A59ADC20ECCF98CE1C9803855A750C180B6E2B354 80D8ACD8F95FE36C1218E851258DDA90704E43F4366EC0D1A519A8685078CD28 B258F3DD351EA10519F0383F0A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMSL10 %!PS-AdobeFont-1.0: CMSL10 003.002 %%Title: CMSL10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMSL10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMSL10 known{/CMSL10 findfont dup/UniqueID known{dup /UniqueID get 5000798 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMSL10 def /FontBBox {-62 -250 1123 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMSL10.) readonly def /FullName (CMSL10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -9.46 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7 5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99 8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716 EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C 02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D 46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A 4B60D020D325E4C2450F3BCF59223103D20DB6943DE1BA6FC8D4362C3CE32E0D DCE118A7394CB72B56624142B74A3863C1D054C7CB14F89CBAFF08A4162FC384 7FEDA760DD8E09028C461D7C8C765390E13667DD233EA2E20063634941F668C0 C14657504A30C0C298F341B0EC9D1247E084CC760B7D4F27874744CDC5D76814 25E2367955EA15B0B5CD2C4A0B21F3653FCC70D32D6AC6E28FB470EB246D6ED5 7872201EF784EE43930DC4801FC99043C93D789F5ED9A09946EC104C430B5581 299CB76590919D5538B16837F966CF6B213D6E40238F55B4E0F715DBD2A8B8B8 80A4B633D128EB01BB783569E827F83AF61665C0510C7EA8E6FC89A30B0BC0EB 5A53E5E67EF62D8855F6606E421BD351916549C569C7368AAFB714E22A023584 8B1D6B52FC6F635E44058690002C6BA02CEC21C54CC8875B408A8BB84F445894 5D6B3E4841CA20AF852A660FE9C832F773691DC6F7197FF3DEAEE97418A5ED2F F2AE65300416227CD3BB03C29003C770CD7D2A7A2E4C1DCA193651C2CDDBF93B 966938788694BFB562AB0010268955FC3555E5984CCAB0A9B7590C77C9BC713E A29E5BD7193A4E971D1752DDD0F0AA4648E7E87BBCE66A1E836C715C408B07A5 9EB56BEFD4596706CF839BA4CFA90CAD4038C1E006B51913279A2C31FBEE5BD4 A7D74F9103CE6124F5B439CB860987DF44FE17EF88EF1BF62C67060D25696BCD 94ADF08F04E349CEBDF9D3389D870D94CC05E393B3F4362A13A6A672EE5E8F5A DFE7046AFE3EBAEA58FFEBA4A47BF61F92E2003756DA643CCF2C9DFCCAB62669 E3C2A18D690B64D907F50BCA155A85E47C3A6954C6FF7ACA36D8DFCE777B7929 5F5D5F787B9C247ABF13D6D7B4A8F06BA25CCB342F8A5071325CDA86AD71BA23 8A9695C7D1D50D0AAC267AB7CDBA7AAF46A264B7B081B7E79AD937FEE4969FD5 155A99E652461EFFB4BD010E5885631E2B2497D6B8C43CE77D7D47FE201DD46E 4482FFDCE150A1183C22C004A0AF0E1F42AA6804E038E1DFC8B0A3CE26B52038 44D2E7F759DA5C252489E5525963D68BC27C82247BEB18818C7D4CF0BC5CC97D 8C701034B8DF798DD4CE36C3F8B1FD40B2DA14EA75583852875031AF8C909EE0 04495FDCD04B05A5EFEBA56A8CAC1F57F1B8AB91FB25C81CD51EE69D6E0F52CC A0E12CF7E3187D67DF71A599FFD895FAA7BF80E2E6B96592BE77AE96905BAF0F F547355A36C443797DDA7C414AA606CF9153E03450B77D1BA4088D739DF55F07 111B9E11AF37F45B6EDE6D7AC126E05886A57C83886DA87761BE600DEECD1344 8A82BD652BE7ABFE6A0F50ED7C6F4EE12CDFD80CA7A5518692F267C51C3FE76C 567BB8DDBE09A2AF901F79AD02B435287CB8057B3D5EE6655071F67B00438728 C4C3EBD648BAF650993AFE5E2B29074A99ED0FB725D9B8CE8B0292B08A280214 C3AF252BEEAD30C88F72E322FAC3E9D78A1038F5DFC41F7BF1AE3744A0677094 51B77C2D630B67853FE5E975A395C06A4D4DA744040B272C2B88D8B7ED3A2C01 66F503C9DFD3C7DDAC865900D2A4F2CDF517F449851DB1963468D0266D7A3E58 9F6B2A1843E6444274F16A9930302DACD8D2BC4588765099A86BCCD8A31DF0E6 2853114DFF2D19F812F19AE6C2E419D7AC1BC024D1195074FD0C6717BFB389A4 4D5428E7BB2E4F9E9FDEDED7BDCBDD3460805AEA0B5F6460C2FDF19273CE5BA7 5D3AAE0DB94C6AFA8339646191C23B0149E7CBF136FC4C844E025A38935DF256 0A0A6466A45EE8B9B23B6A055856FB084F87C73BA28F1883E3B184CD813C72F9 233B78CA4E125ABD26F29B92CD9DF39D6FDC2A217E2B6B45D9B0A4D536790A5D BC0903069565A442FA7466414D948AC432C6B75D8D0E1DBB217CA3DC38A52DEF 62E9D5AE9E753956C13819D93148C7683BE4F71B80BC066D8C19FC807FB1C086 B49215DCF56A91A42089F0D063B9981925691F7DDE3237403AC714F5CC3ACA88 DB2F1DD205578C00472FD70C8BA4F752E3923ACF3164D442A6B639902ED060D0 C5777BC20F9A3BDA60FA3BC986C38136FBD2E8F910E32EF36377C9CC187F4AFA CCEC423DB925B378522B748BDF12D523804CABA83CB5A7ED69FAB9AAB75EE8FC 38D9866E3754C4E2F2B9AEFA804044D878DED0E114EA0E9682FCF38F6628E63D FE1C1B5615E54FAE8684566EDC4B616F76EEFD6207E0386F06D3BFFA26425F24 303CC7C8A8D7021E7D09B202616988287838C3DBCE3179B4FB5C726E603A47F2 8248CB508F327D1291CF3F08F7C88298DC2D0F778D24304EFCF6E074182BF5B1 8E6551811FD6991971692108E289B61053D6DCBA2925B3903E8916EBD09D97A2 C6D08E89DE4C0CDF7185E1E00DF456B249F0BFC686E04FDAAD2772DC2C39DD53 9C23A41471267F53A87E5C2B8CBCDB66CE0B9844BC506428E6150B48D2FA6363 4FDB2CEDFBAE0B7DBCE4D83E29B2955F8966272CB865EDB360C8A8C19EC62A29 03066483E4083524A1E8D80FE3867BC1AA91753C26ACBE8489AB0E3330206212 93E07ED473DBF457EB8489E66FB4B8ED8A9EA8911CF9308CFE3E6D6F36810EE8 91CCB11BD548617B2C683C354452B9229E7C9E68828BBEC324420DF7C188CCE0 FBB514547553A7E9B38AC265783891F42DA472388569C8E7594F7E8810895A27 06E456902A8D9F65CA808F1FD475D011C4572F8A654BA01D67942226A663D179 95149FFF41A9F55AE84EEB9A6A39C017D7E4FD6EFEEE7FF3CE847CDB064A4954 9DCD273B810E0F259501BA4003A3EC1ABA6E13D24C0B57FF82D6DF077833B6A2 7EA54801BA81DB961C261689C0887FAD83771E55D3D137AFBB21779397E11972 6C6CA922F45AFA5C0526863A5AD8B9C0775CCBA17FFD37A44CED4710884DBC31 5C9D3F5441595B86CF7CA2EEE42AE87896E9E60EBF5F35C2B7FDBF9A9CDAE262 3F48396F0F741E9DDF1D4FEF75E68AFB020D06CC29B3A7B2ED819D1AABC12B91 CA2A65F1AFDDA2F3FB322E0268DBBA024663E49EFF076455338FE31A16B04EC1 797EAB0B49AFFB906A0690A1E8E2F5314773E1CCFFF43E6FB3875AC907F0C5D0 DCB9BCC127014D472463560CA0CB1C2CE614D94177C7A52A5B089316689C8112 CA57E35D716D956DBF9013B1E5B9626456B1433C8C15FA906458F957133B9E19 8D46DC3AC015F7602538C2AE3927C6DDBACF38E59220C2F5AF36B68DE9117C51 04CF7DF32B1AF55B87D1D8A5F4BCFEC66F63B32B6548DEDA3AAB06C5310E4757 78AFF947DA22809B360FE535506A554DDDE5A6F2411246653710ECE5CD3185BE 730520A766C47E1ED01890059882BE1432586864E1A86A7F586438C8DD35C00F 021A741ED47E0F16DB6070ED0C50038632CA4AC2975578A8372A080CC0447C79 CEABDF2BCD5E78564247B0F0025F556DA8FB62125227849EACFB724A4AE3EF57 90C07A5B27D2E59425F56BF8AD84C5F5310FEB1BC73D536339FC2E6A5BE2DAFD 97FC835E0D52F680F80ACA37DB498AACF152B9B44626CD89E3302C3EE1623EE0 F998FA78305960AAB9F483F731F5F67A8C963C23DB8E48FB804EF8B86FAFE7F9 4C09641915FA7E3930AC922682313408BC1607C76751CEEAFD660206A39CF394 40ABE2A313AB7D5FD6444E219DC5C26734D322BA268D330AC17959A390D6C8E7 3A155095BDD66516DAD5D65519A7FB871ECDA77061EFB21F359158B4470EF79B 362C35C06B85C9A9505C8361939C6AC013F2CFE8EEF46FD8CB4452AAB3EF1FA7 DC066557BADC2ADDDF7DDC2A0E1DD4A357E27A2073427EACF9B9035DA5272136 7DF37E26D96ED4B2ACD60596E039BCB15E259C72FEB3344E3EEE3D4F17DF4233 04C1416BCADE80BD483DD8C9AF979E1C7D50C4CF015870703F88B92C4FE46AB8 DE6717B55C460C805B391B84333097E116F4A51F631FAFAB34CFC925BEE8B72B C9FD5F5A79D8F2295FBFAE649DC6AB47794AC7D73431FFE5BE992F2B5AC67049 B5208251C0E442385A9FACF25E3A98D7F5D4C2A1ABDC600AABE84769CA83350F 9B87F71CEAD3600E02FF9AC03C1B5C21C84F911511A0CF0111BAC7605EE31229 3C526A79D943D92E1CC3C38ABE82D560CFD4172F318030852A5FCC0534B8B3FE D7365987C8B48A072907B26CDC2108130A33233E8E0BB5FDF14FB55098A10EA2 B51AD9EFB119F82B08D256D396D3263FBD9DBF172D43A90ACD1A31F3E89E8571 74BE98B9560E2CD661A2F93C69FEA3FF26B00772AE2C2C24B98D3D122EA2AA8A 44652CCDF4EF4F01CA7D62A976E23E8A86291F43BFAF38FD9C325E70F9C36CB5 A181DAD30156E98339E6A0498D3420B7BB3B4E651A9090D4A17604AE386273A8 3D4AE8CC18345E6E19DF06BA848F203F74B161D6A8882991CBA7385F308696A1 BEEB0130D938A764B98A2001A38489B1334025EA848CA44A116D64926D460D64 01159E77EA7ED9ECE7BA77635BE564A4ED89315BDFF54ACE6AA1A26591D13CD4 6D6425CA7933769B842192858D10998509396829263290A3A7CFEBBDA3EE6CDD DF1E492AECDFF7941B53573F01F623CA0A5ECC9D05A3D0954F7AE8CE94AC3B2A CD4E27519B2E16F033EB732AA024BBAF74626DB55DC74B1FDDB07FAE98B4AC5C 683CFD8744F361838D343B657EBF52DEEE7AEA7565C5BEEFE455DDDBC4DCCA7D 87D6D769C5ECCF14118A14A85A86865777C8E28F953160D5E82844AE54D541DF 550D5F1519E183E0C42BE88F0458CE8087F2CD4B1B49A8E9E3D127C4A4CB74A6 2E73BF4CC317781D03FF04BC36AC0E4AF99E2ACAD20F6F8029DE8A035DAB40DB 17D237850BCDD05931FF4B0FE2D0B79EC5A88FE0236271CCB075BD194AA25AFB 3FB93A5206F61A14602E4EB6F1C31C654527CE0C02D04314DF9AFD710D0EBB9E F8721B97F5FB18E27507E1F800B5509A58A1A8296C72B7B73F99B6CFE42E9C2F B63B3555475E562672645CD374BCDE937A9B05A157FB3E74C8297507253E957B 1A9DC421946734CEFA3D5EE357DAC7E9DE17A5BDDEF6B2D2A740BC58128FC514 61154664412BA1C05209EC992A77B7CA45AB7C0EEBF590A5B5652866008CDEF7 124A3003AE6A7CF9DF3C72750CBD281358CD2FF25B162B78CBB971DB3477F8D2 ECA3EE9CBC90323B2C236E375337EA0848CD7CB5781A2B0A42DE7E4D99DB2746 0B26796CEE129D23C76794B7CE21C13C7D4A998B752C8CF43A4821B736EBE246 D2A2BD7BA3351FBCD1B0A501EC1EAABE60D06DA2FE39BE1F0AD629769FDDC933 F9D02F9686EC8C2D7455C26AF4DD3F6860B2289E3A30E1C254AD17D731CB73B2 BF4DFE90CAEECE3ED0CD3FB4C8F4C7BE1C056AB4E9B95781A8968E3CC1010003 75DFBC4AB9F6B27C5A9AD88D94441A8ADF09EB275E5F0E5E6F3BFEA0FA8C308A 8593ABA0645ECA8FDC3F0E264B35D4B0DDB86B93CD8A047FC409E18196B501C3 B003622999C47BAC04FD1ABD8AD359C977766E9643EF3BD6385306B08EE3E13E 7DA5A06AE33D17A3D574C6390DB6E9429754B210F0C349C359559C7EAA2350BD F61D4D8A92B1AF697BC620FA0351E67E0D9F41A95A47EE0BF210C2C48691901F F905F65693DCB85BE412F097480F6A7266AE0A928729DA0F691CBFFF3B276EA7 322BCD2206D96E3DAFDFB992CA8F2955F0E8B882729DFF840569D12E4DA1775E 523AA734552AAB6F2F16B89B39F1A3FF0E07EA08D13E612F201716C67F327017 6C041760DA30374434808273062C1FFA2C47B3FB578807BC26537F542040FF77 66C995EF3E8B08B09FCD3EE89C30F157158A739606D2CEAA26694A4F1CEA6633 B54933141CB85C60AB262E2D4E824A3B85C2BEF810DD774F296AB37D0BAE7182 5648CD18556ACB124246A75474B232D712C2358908B5D9A76F82C626BFDE01A1 093B8FA6AA0B32F2CDEF737B28BC0448FF816DDB5812131DA0DD5979D77C3838 B978CC3F6778A4BFCE9A7087EFB19749285AE4C92B99A6649DA349A2E0889D72 6D4FC664522F06C8C4D86D30BA43ED4E42211217D01636A4E17E2A132D26F394 EC34EA12D84594AED9C6CDBBC0908860F39B240FA7D7B3003DB10322498691CF A294C0FC7ACC0BAD1EED3E9D60AAE3F7429695892D1A21CEBF062C6129B33966 8B2EF6E932F9891DE6028B81C5E9B23278D35B7F0D83989BCBA25E20E9D503DE 144DC485F09A4EFA1268AC5E4B551C5B2F1D51E9B9B9C0FEE585204F869D0BE0 7287D7570A12940A47C1F51AC6134F03B415C30E147C49F89228855D093EE55F 172711F37776E97A99CC4B36E2F10713E36FB279FD3FA5A0EB9F3938F42E2BB9 254EB8F0C0F30391735019E02BFDA21D9813C6A22279B898EAF01AA892B14DC6 5912B9275167AB46EBC420836CC1A5F38A4EB47C039A7BCA62BC3FCE4199FC71 011DD6E5FFA0F3D7F04AC02AF91B9249B9F993AE346572329DA852115BEF8460 B94690E790003586F473F37EAB5AC2922F5F663EE2C3C0C336A8DB71650631AC 0A923A389AC911CB215EC2EC7D50CF8AEFD59EBFFA53A9F1FFB7E6215F17093E 3975F186FE23BB5FA5474C11408FABD223E1E6F62035B5A5C1AEFD8899F00FFB E729C2D5FD551E80716CEA4E8281660286A802AAE8D5834F37F2EAC46297E57E 993B09251DD7789D3467417E393B7DEABD06676B96241B0E43ED1A1A9FC3B12E 0D34B2B0792B79AA648FE9450C3B209FB6D7D91F50C52A5DAB0BC81A8B698BD9 18946EFF691912D7348D48FE68CD876FC6F71F81165D0C3272DA1A992308D9E0 ED6D0A4DAD679AF495F62B78D462B463BD4A40931172290C615B3B3B6B47E45F CEBB85E0A6AB6832067CA6D403C239530D07F199788AA4DD52553836851C5228 1072406F6D7323A334E7A7FCA588897C4FBA6D4F7DEB65525EFB74E539C988C3 A685A98752F7198E77E456A545F0D23A1BEF81EF58B02D289CF980A3F17BEC8A 6F83DD90C4A917EB0E5E2B444A608E2E9D2FF80620E16AC1D7775C0A10C1299B BEE0E1AB24C50647E5CA1DA65CFF3B2C295F0644CA7826E1DC6FADEA93D66A20 DE852F20AD224D28DB900519EB1569837139C833F24B799F7EBE3FDC14235323 1D0BCD4991C861F38DF413A5A5588B73AEC3BBFDB885CE17BB3E97B4E6A79761 93EC8418C2BC4725CD61B5E30C07352F647C3FD50083878C13CFAC241DDCB082 E53703D182068727F9EB6FACEC25F6D901D7309ED7370867E34E267519E22D62 4FC7093448BD0D6B1C43D318A3E14C92032325C132AE0FF7ED707E1FA4A955FB F5224BE0045CB14ECC321D0F333FE24EEFCC504F7C756451D7693C3E6CA87526 4912E1B6DB935BDE76FBFAFCA4ED473F1D2618812CFF25A6859C626A216603C1 361BE3E071FCFEC2D4BF2FEBDE07DBD56A1BFF8303901168FA06488BA6B76F36 95B0A90D7724E9ADB567C2ADC65CF3482CF47FD1D16F70AA19A97D0F9EFC611C AEA5E1ACCDA7FB2DF05E9480936281484BC329F0B771775E73F7FD72FE3F45F0 50ADBD03932B38F37A8F0A66B2F739EA3AC8811C8F514E68C5643E4AFF485C81 88475A523D7FCCA5C8809BD49846C77795A38DC6406082000236A4D2628B5932 AB7916D44EC2210CB941B143FB218EDE899E4C47E0081BD91A7BAA1D80F1562B A19D442C49D1295FE662395CA9143CB136751300AB9F9341255A9BA1323DDE0B DB92E2D787DB0F57D7600215E8FC23ED8E1F0D3764780499D425D7824DE64B3F 988AB0C9ED06E600942526F12590D8A239B8AC70E319262AF6A41B2D45B2C200 5DDD22E105A1F4AE4D2529C9B9A1CFBA75207C66D0B692FE7C9CEED9A54EE660 7CA1534C4D5B05FC33F83790ECFD7641DF3FB94289E2A1F6E611ADF045E0AF3C 46E2F650CC36E969855BFA34B66B0C13481151129AA93F8003F666C963A5086C 8F7DA89ED6D2616BEC5F71C3D5C65C821419AF3C96D8B886441B1B129C103CE9 71961454C9E8EEAB50A684882F5AFA6776BEB4765C6ED70B686F135C483E6923 656E924A1A3AE8B1C8F2534E57EF4B62EB5F60AD32CE002FE7F15CBA8F8D641E 848C586A3C6883B9E80168018E04A8BA99621D80DC7A610C3D0373172253EFC7 39D756DF796BEBCF86194A56E68366D6B183B9D280D500A2507D68D4F087873C 9696261BA4B1504F28F2E2081983545DB432BC23B3E4DE6BD05255B88DBA72E3 B7790CA90ECEA5CD733A8B4DFB8275386B0DC0984C1383635675696AECECD71E 9E1C957D9C75A7C96112FD17B755519A6DCB7B3ADF5FA30F144B7E90C100E54E C0AF02BBBF04D8B240F822BA1ECC933993B92DA4B46114BE8A1D8A5B37E4714E D45185324D9E12D44D1CB1926C66A16A038163C98C54B75F5A8F269108DB7CCE 04D6EFC59FAC6770C806A6864D4577AC6B2EE3FF22DFA9A5C980821F07BEE4F6 939F8F56077400E80789EEF1C8A1776BC9B57D116744856E689AD1DA36F6326E F6FFE6A20AF9B7C58604922C7D98550E2E5C7CF1823BB2FA0835133950FB8A86 76CAC230274F91682F11435254D75908EF4251372FBAB9ED419507150F035CF3 AB2AE67F6945C89051008793259254CC43D46C45D744FC121E107E5CA701FE17 E935235429BDE4AB9E1586F4C8E49778021BE157D3A2E2DA8E66D8C8285EC811 A30D3D401B387D3CA28EF41678A073BA8AFE225A949C411187F90522641B90EC 1E538080594E49B12A8D329B1E5DDBC7A4DE7AD271ACFEA0148A0C57BC39CC21 1ED81070A6BE322F6EBC3B7C18FD250368869528EF9A767B0102669CB93FADC0 4B5C8E7768856136FC1542CB71205AC63A7F0BD45402FE649B656A2CA86CFB8E E2224982645D5509DE91A96BBF82EFEF01E287251EC22DAEA7943EBAA65E5D97 BBAF684BFB41CFF8E7D2EC1381DF32EEF9FFC18F5EAE87DFCA9B5CB7E78AED9C 1C48EF88D6C7D0B7D9F08F3B01D0B5DEFF9F2F427020E7CF6FA7EA9ECDBC80F8 86D4AF0942835D5C06243810EA2C6830EF971AF3BA2AC7A8B04CA2D32CDD53F0 0DA973D0F18957A6B9689AA16751F62F8A8FA7049B25338B9586AFCADE266ED0 1C2AD6A2DEEC2B8EC0A2CB679320A21F8DDBC628F804B0AD85D30F4F948E345B EFA63C31A42245A4BED2FCD2AAAE835070AD3E39135C5087D0AC3A24E905E27A 870B25385590DCA9A135D20D823595D422B6DC084EFBFBF3210EBD6D1AA33B5F 7AD7BCAC4C95FEB7730CA65190E0AFE96EEA6C7AB7A276209DDF8F2525A1B493 6A5FC42D07AFDD285FA8135360822C71DE151417E015AC9ADD37CA6A8D20F5FD 8DCD69EA6B778FC1650BA5B7469F6930CA3B237A4718757CC8F702D0DCAE0AC7 176DAA317BDA09905AD25803F4A047C0A475875AF9590433F944B6C6E2C4FDBD 62957D5F092D19ADFBDD135738857976C161F7848B84CCC55BE7C24394510D0C AA023A87BD023429ADE96747844EA76C0991B66D0D163AB8D0957EEE688278C4 2FDA841E4FFC49C57DB26975DB027D9FA5B56C8EC15B4871F88689A7E58B37A6 DFCE971911C88DC88FFB06B3005B8C3600BC7698DD62E4CAB19C19ACE1595A47 13D1B1A8D41EB58A27390225ADEB8330B4C25FE6C77BED3E2F9800A20A50E973 5B25D8EC7C976A34B38856BCF159E5BEDB50117E8375D80C8B85877F7341BA6D 6B46B8A934648AE27BFF055FE544BC0D3C1A2146CDFD254FEF939593C092EFC7 C4D05776D259E59AA9817084459636F751E0846E52335A980F5EFD40634AA6C4 49F4D9DF674D28C633E617EE78C02C818654A6A70D32630FCDFAD9458A9DE983 7D710A56F17FA5C54166CC454B3D99B2B109F2FD59AD220AD364D965CA47BA05 3A411BA3582DFBBB7C4BEB3A07A455F32C17BF7F51E5545F06B6E72ED65871D7 D550007EDDC088CF3E6371A9428DFDA59273027DA2B58C38BB8577C7DD6835F5 89045B89E7DAB46D20927B2E08C5462DFEF30227124B285F7BA5F78507C548DB F056D5086ED0DB7A2F293D6BFD6715FC5E9324EB49CE4628CA18305A926D42BD 2D6C266CA3255E23373A0FADCDEE4BA5F9BBC6231491F8EFA8E42BC6AEDCB95E A28AA2AA0BBAA1155188F6953088BA23C0470F6799DF92F05CA2B9F36ADE5160 CC6032DC70E509F508B495C138D9AE10EC4CB2219F65FF5851D076029DC7D0B5 9A54E00E26EA9DF2D97184E209D950FDFB089B8A0D4286A602096E350601EF43 9D5EEF291FC3715C59F212055416DBF35C2B10E67623ED53EEF063DD8C0F0008 2E1F9B387E4F94D5036BEE5B31274735A23E4CFFA7DBF5E19ABC5C35F780BB1C 5AADD189303A2BB4EA00161103317A22DE28BD349CFD9A296506D4CEEC92F1F4 E993F5879824764E40D4C339884A2B27A0B865510896B0133C61E678CB5916F2 B22AC7F8DE5321F46ECED7DA1922A72BB000AE520759A99C77F48B6B394288DA C1589BA5AC353FE06DA88DEF453E4DCE0461C1179346649C815FBE5C7C055644 1B52C03015686130AC4B974ED6B8F5280B4326D555149DA5C84380E74A2F9FCB 489F16E097DBF900C6F922B1A8B6A239F0F4DE5605AC35BD4A479527BB9306AD 5F29B155E0EB7357075AC442FAC6C5915CB6C0E3E240674D4BF87F1EC6838E23 A3FB983B9122538D39FA410C70CA3E81ABF906C9ACD2CBB1B63E7D2CEFE9151D 61A0D1F64B1FAD736E28F27737F5AAEE9A7E93C2210017CBCD810A7B6E2C6F38 07DA9F1C7AC5ACF360714CA057A390B990B28C818D789DBDAE93EC5541482F87 20296D5C5CD8A68D6649CEDA29FD7CC1A25450D822AFA6004AF2E5AF45B06594 DA6A60F780925A9118B2DA2D9BCE9BB40044FF724ED49B8CFA22A3631915DE3A C60444155147F75FE659CEBB151B042618F35B87064A257FD10B2E30F673063B 7825D751371D9DBD2B7D33BCC5A84870CAF1C8FA18D0B137CDC2C1B94A92CC06 29CE27FAFF06F8FAC047C0DCF3E0EF19AEF7B203077C37DE7CD355EB30183A28 0301ED3ED5620913F7558EBF646C3E28A6EDBC968C25E1916289E6910398FF69 E2123C6745CB86A2F30523C4755D6A1F78749A1713F0EAE7D1A8E9E3DD72BFAF E92DCD33C7DD73FB4D147959CB5B521C64614365A25FA9D30CDF632AAB6E0E30 E480876DD288CE9D059B533318C4C05777C5F9FCE908FC42AD040C29146C56D9 EF4BEC59A4B05A63402EE43782418C570BBB507038C1660FCFC9C4DC20F160B3 CD5335D79E612D23C653273A590750F336F3962DFAF45C6AF979E9D2A9F76D2E CE22C94CC32A636CC9F58028F2B7892DCF8F803A5F36DBF74228B1D08DC378E4 232C585E558630CAEDBFEE9EDC14EE68E4CBF4A3A4C6E96A30895836833B46F7 83AC7D0DF5D0DBA7429BC64C00B9B56E9CAF91C02E9A305D2EB320E79E30050D 606049B6B86170E76E296BBA3E4DFC3F407D73C0A0FCC5D2462975D8AF3CDC9B 84C72C182649DCEA78CC18DCF33A0341A21AA19D92B975A3AE1B2B3E34A48C54 6610F58CEEC2E489FDD5B46198B145DEB94E923D62F6AD18AAEAEB57DEB60382 A3BDB02E5E2B3A1E2C25BA5B75C38531D1E3923280B52CC141272024BA5B655E E678C1AB4972FB4B1AED5094C31A3FBC28ADDD62EEC788A474B5278FDDC7D208 CAE6B6EA378FCD29C31371F4AF52AEBE7E38DF51786309621E882AA0528EE1F6 F0CB43160A3517BBFEBADD7715E2B4AAB170B1BB2514A1088095561646C65CED 84CD5B5C5A5558ADB8BB5DF2B3CF9A53A3E4E83826BA124AB021516A4350D296 BC19825244F92699F12339028699C7806FC3AB824F6B060CCE2E9180528E3560 64997EDA3ABA1C6434F76BFC2DB8FBF00C67E6DDF06C0E1B73AEAEE317FFC764 2ADC87DA9B9C0E8A0C5F665C67F8F7ED387BF754F97C8658AE9187D53D87D1A6 69FF5F49AE9DE8BD120611BB48CDAB440F567DF400404808668DFA7F8197E907 05EE14E69167CB30AD0AC0DCAED93780F132AAA20508A11910BEFDE24A1FD5BB 4781686F1445DBE4C5A3C4795C7A06B98EAC79CF77F0018FB5CFD531967AEF5E 1D41A87EE3D81A804ECB8E3597CBF050B9AEEBD707CD7BC3A4958F1629643081 68D050ED87B7B26FA6149E0F8594DA4E0017DB57178469C949EE416508649AFD EC5148B594D59625201BCBE112C5C8CEF1394D9CC69E94F2B8BAB1992287425D 41250C8B25FC0289FE83D7725C3DCFEA5435335DB38A3B74780E9677222EF4EF 8C1CD98FE322DF899F11C518926C606D276F148AA0600D610E32BDC6393F987D 0897F215FFF2C923593895A79677CE4748C75C905C0757F8440DF75012237B13 E8F9F6189218BBFE66A7FF168DCFD7C20637614F1714FB418BF472F25898B187 8D84F1DE9DEF38451149F8F1C4CDB2307D0C0AB286507FFC79C25084A8EB0AF7 1AD914A3B07230012A5CCF8258B5AE6337BD537D3B2854C6EDC72CCC515933D1 FF8E3B179EB1A4BD95A42EB75D7A9F22F5B233F79549A208925032C47E049600 87127CF7DFD138FBDF82253E235930A6084624DB556B9FA958D7B71622059EC0 7851A45A21BA746166D311A8F7E079B5217B4056BC822EE75EEA939D657E27FB B595DC6D075968DF593902C15F5AA2AB8DF1A770C93AED09F39914C46DDDF942 A95D4BD79386FDAC1604741C714B98DC554F3BE6A7510C4B18E240955186DF66 891165D83D45C97FD187680C49100F35B9B86B9649CAA98B4281F4273B2547FA FFA14DB49C2705C5E655BA33C50322A95FB0D36AB88906B70CC6F65FF351CD28 D71204961E55E2EEE3DC268CAF47A979132D9D5A63A84EE16EE0D3DA44AFAF9D A7C63D5F7FBDF42500835F9CD769A73D7A6CC248B7BE273EB0FF781B3FAE27D6 612136D581AFCF791E6B403E2D7031DEEC8644033FAECC0966A6A4ADB3D9020B 524B534B858B8F5A66E026CBA3004465D31511A1002E8298B722029B0FE77B55 61B6D2C475AD715F849783FEC956D192DA66C884A85F21430C057D881C5FEB5A 656EB691A0C0A8A853791D59D01A95D89EDA88DC768811F01134092B4617A90F 45294EB793A43346E2ABDD1BB8C51AC2B937D6F3F8B5D8ABBDA54CF46F71FB02 58CA2C53016C7447E76AE9D8D85DC4F5223723BAA0D4A7A659C822B7A93C8004 B2A84B88CABAA15B7D6C05FAAFA1EF47EEBE58CDC78FC18768043E6DB4E43E5C 2C887033D7D1FF741DE33BC73D1CC445103CE0FCFCF4BE9317D5FED10D58A644 E27F8C3024F30B2BE9D13DF984B34D13C75839257334FD20EF43B67BFF6041DE 518D5D4CFB778BA08B742D8D37C0E7C6A6A78F0D9729C4E634394353ED36C3E1 38312D560DD42478D707E5C9D409D43C5C35679C756CE85174E57B40FD17364E BDE1B7D23FE760C8605E3AE03DB86F6261E7B246A14F4A4C2224BD4384589443 C729DD3D509E43E13E0B7F3D9EE853C07E5A7D7B3DDBEAD04A929DA76DC61DE0 52F07E635AB6168E1F1528FB7ED5EE76BCD08936B758ED818AB756369CFE9FEC 4EB46C2939F862D42705968009D997F3D618DB10174E09B24660CEB404A0FEA9 4294B3B55055B8897767E879966860E956AB15684D6669E36D894CA538F395B9 438444AFC3B00DF7B2465FB5F01FA3041EFD5EDD39BD1DF30C6963548BB63BE2 9DD4B665D72FFCF5840D303656785D012C06295BBB5FDFC7AC37A6D9E49FEAF6 F830D385E6D312022BC885A95B07343095EE7A0B76FC3FFAAF8CCF13B6DC4D8C 2277BD3B1E0B80635CB637259EAF9FE9333BC2309343ECFFBA369624C9C5A612 FAF0DE89EB4E33A0A82B72655E0DC87DEEF56F33F844CF8E067B1C6A1BF0A0F3 84DA8E696DC8202BA8DA518D3DDBFA9D798DCA1F9EDDFCD12D577DF5A86E3BCD 6FF8A9EE0F904570C9D2F00C572840EBFB84AFEDB543E10A7BDBDA2635E3B396 3EBC7D05A8A683024A1A7D3E7D6D254A75A4569305594C0B18298C4974E594CB FAA9A695DB48624A10FDB1C56A0DAC9002A5AB14699EE1F7199FDB1D0687721F 0E2A10DD36F27059E6290AECEFB86A318BA32EB817A8FFC5D5EB2BC923AFB5CA 8D7BF6FB0AD7B9F53A3C605B096C9C325981407A40AB1545FE7B02C13469C8F1 5F7ABFE8964BDF65BFC9D19AA07D907DDB3E6B11E29C60B5E9C40F0B69E8A674 AA55FBDA72140E81B0394E34DD9335BE16DB23ADCB922B6D614E715396579C41 84C0E621ADAB89AB6226D22D3D11F6997FCD8BC84B717877386BCC4752817411 ED68269FA1E65480006F89F51DCA36418944CE09E7A49CFB104BC1C7A390E2B6 A3A1DE9367185BC5EA7FD9780E2EFE3A194761184A31F3E121DB398623DB240E 1727F701C94C4360704FFBEB51F66C8FBD92C9D9B258308A9FA624B8C2F7B3C4 EB0B9A607923FCE56C81D51E94C01159180E470E6487CDDBFB5949439BF85616 0D2485F62EAAE430D668D965AFD0A733C9696A75EF2CBED9F50511B7A7441D32 B7948CE4D34F2AD4E1F6FEA60C4B7132F5ACF691077FA7D258A88FA8343E176B 85D6804A460D7B433D6671654DC2A9B3A78FDAD73E7C1AFD1F175EEF77E1DA85 2BFFBF3FBD121B1AF1AAB57E0EACE2C5D4535AD9E1043F4411BD3866201935A6 87EE72345D5F6D55006AD67B987CE7A53748F2FF0C23DF2000ECA03355BE6DA7 8FFF1D18B9C00D3215F7D94C5AC8EACD956ABB743DA4D99981F9921AD9150CD1 9CB9FBD855ABBC2E48D59AD4F0C7358CF427748EFFF4A73E627DE3C67B62C534 7DB36E37C91AE61E871BFBF412C817CE5F239AC1FEA2741208993BA98FF119A6 623ED908FDE1BE539D48B1442279C676C32CB65D5690B6B9E76946147A9273A4 13BF7D4B1066CF3B5B599FF5882BE94D73E995E1E77B381017AA13306FD0C40A B02E72C85214DE5978E8BE273F2A96C9F1629BE9C76BB8BCAA2CFDF5C7FCF3AF ECA77A779B71F0E4F946B9E8267FE7B6A74CDE3CC04F33704C72E80186616617 6B21655365C266D1ACB6AAFED2401B81CF0ED851D2E08B11391BE4F1D3F940AE EDB1928242786D8B4F67FBADAE077634DBA6B22F813FDF675558BC68DA1A1C61 4BCB4344E8787F0F2446673CE7023DB7FBDB080EC4797CE6603A7ABEA640663F E64C0E33716A47083CEFAA1A132FBF8731E9B97B95797E66859F50BEC599A492 046A05D9481EB5B6CD754227A5B335BDF88FC4FE77481274B40130BDC1CCEDA1 F5B88A48BCE7E309A9659F8C737D75732968C5C37369E81931607683FDDBD815 4DB7AEB89F3E4555B21BEC3F0E2DB87F0CC7EF5F955687C56AF1E7234D1EFDE9 4D744AAD98C03184A1E24772DEA9D2DE06F56F0C9BC5DDE183FD8D0785650169 6640685D57A3B34A93041461F68E6BC016EAC14BC3ACEB7FFCCF86D4668259ED E51E975718A710985CFD52C8C060D3AA85B96A5858EF8F55F353D6411C0143ED FA896146A089CD3167E7F503756BC12ECA6DFEF1566BA66CC2D840BC2B349BA5 D63E8BE4455BC86FA8A2296EC0827583390D0A51F62530A28E9A1ED830C9AB33 C3EE3015F3EC9AF8F044195613D3E057BCD2DE83902FF5C46334C103D057F6CD 3B78B51ABE00A0DEC990A27275F11393C1E16C035BB7AEA9022F62372DDBEE44 AA952C01A1053D9A32B17FFE3E9AE0B1106FC26B7A14F472D973BB912FCCD3B5 5B7DE1467DB6CAC9860673DC18F332425B970C7394405CECE9102AF258C7005D 3156E4780B33975EABC0C18CB87DE0BB50772C399BD829FC592C7C1CB35103BD 0D62C37CC036C6BE60275E49529CB12F5995F6B56680D18C8824C9C27AE4B75A DD3D4967DF24C0A016184292D4A5F9834DF0223E06D37289E75B61976ACEE71C E8A5EB96B247D5A3922C4BEBC3E1B5D3E2B1513BEB1544B7E062AC04071CEB57 9B042DE6FDC13CBAADD93DE69871B46F02B301EA3EB3DEA9F1E8E70C8F8C51CD 53FA659CBCACB4119664E07B46B76D75B78AB813A638C4D4612A3907BBC12CF7 DECA9E36C585572CB579FF4ED231B438123FEBE72C772629993589C35E6F5721 6756CF67259FAE3C57383F6B3C3C96A61F37EBA9B9EEF71566AE0C8226CCA95B 3BE2B1304F0F27C5F0E0F526598F0BE2995B9CA1B9C0BB2FA1B12A420D377758 26C9BBA85816111DDBBE8BE56B1BB348FF298D43DD366CA74581EC55F75F201F 3AA23E042F07451FB8CA31FDF5E92BCA9B89E8AFD7FE80D4F8635853662F5AD2 54FF17EB29DD6DC86642F4F268B9CA0E9644FB04F8E222C58D16E4988E403581 F508C15179FE9E9EC79640EC4E38C1ABC1297D45DF1B15370F49DEA0E8E82BD5 6639668C6CD6A23816ED332A7BF64780F03EF4904E473EA3E170363185615787 8047BA5B1053F6574F793B084C51390B9C6A32B15B2AA1A48F3CC87DDD5019A5 D231FECE2B02938A6D1F20C33835EAAA1541B1AC7767674FC75C9CDBB5A1C795 1B5C93D37FA03622444959EF388620D0B13D9F6A31954D048926A667EFB41029 F12667DDD8169211B4C4ABC51987D95DEEF76CB098ADFA4E935FCFADB97E5CB7 CBA188FDAC8FFBDCDDFF14D1EB633AE81AD6B65CC31361B3078772A522ABF9C6 6B37171B5390E37E17DF5790E1FF121B0BC8AE7592BF44A4454D3D902896B289 72DE53EA0BE83D8AAB025DD3810AE31F41D7713B6A6393DE1F30CCD5334FBF2F AEF6C3942FB365CAF0A18A57CE7D50D9E8C6BBB4C1BC1F0444054C552AE1B9EF DF2A4B35A9E7E6D8F3B0E585E4FE608C4B73483ED8371FFF652A5E1EEA27C3A1 AC8033E02E02690B823DC1BD5B3538CC4BE94E9CE8500B8D36F3A53DF0B6862B DCB9C6AEB6CA77969038EEB8DE0EA0E470C19158FBCEFE04600DDE7D6E19346F 91F3D587FB51817CBE1B898832903C3B0F5D74B3F7E667C871202B7A38223F47 B5B8E13E3EE85BABDDD9EE13B91BE44860BB02CA20CC639A78219BA9908370E8 0C2D9AC7146A2EFF4175AB5A2E50689097CF2D5D6787ABA678793FFACD389DB5 807AA70D42C2B4897CF78A86D80E1F6736EB30D3A1E787631324748C32560091 472542ED62AD2ADD9F00EF8D5609CF1F3D4EE16D502B281DDD59A2EDC2523318 2017C7C1BE7E06F182BB05F743D1521A07F5AB97E3515C1D9DAF73E743CC5B30 977CC0D1E364E8A74FFA78877DD0B7637039576102D7BF022A81836E4BE571C6 4F4AAE21F9875D30277AF3D4EC36D09BB412097B30D45DC758194E85F0F473AE 2039F97ACEFB9EFD245E010618ABEB396A804DB958AD3EFF6E8E2F8D9A41620C 233BD26AA6A06EBCC22E6BADF3FA2C389944429612085CE276A7571D75D3C521 69A03AF226C9141A8B21B55E680F93E7AB33212CFE6D6A340DF6F1844C084FFD 0D78178D3554C9653CF8E0F64361790CB87ED45D2BA985678003529C2854AFD1 A0EB66D7D126C878F381A767DB0101F50EABA4B10D84F0AF528FDEBA941A5D48 3551F75F324EFB3A57DEC364F86FAFD5745DFFD95EC9A5CEFBC61B26645F7305 59C85468180CC0959413A240A457399B77E57EFDAB737460CB2D595356DAEED4 8B31292C2A4129AC49B3B7BC2DFD4E30184E13CC9BB3A415335E290F6156B0B9 F38EBA44B98FB950ED23A07B2D1A98DD8796DF33F478D2A5C4EEEC9D9E65FF23 82EE9E67C5E990FEC7B4B08D40C5A49E58714817BBCF81B828BE72F6EA890729 53805F3A4B75BDE44F3DB678CF015B9933D8049B5654D9AF09052086D92355D2 13EF97F41BF2326BBD0D96F56BA0B08E04F93FDAE71B873D7BC06840CDABCA7B 6D880A9219E96F75D75FB43AFFBEFB4E8EED986C89ADB933D1E501BD8DF6FDC2 36E4972E1979C2ED0E15C4BA9AB077DF0A16A7C19839BE759D99ACC6226B821C EF05BA86364378947140FABA907FB735B0E7F747EE7DF8450ED66BA73AFA43EA 74AB9CEA6B4C5A96CBDA7404C6681BA0F9D26AEEC46DE3DA47506837055EA157 D6BD20F292B46D9CDC3363E8C19B20913C1662EE39425D64724741D7DCF0F0C5 B7C66DCA9CF27501DB6A7DC3DBFB464844F97E87A09B0ED04172F6D337407651 A836F1F4302FCE29BD3CA5952A923F5D37647C665095285A3DC76BC27AB33EE5 DC5BF1715DCE10234BBF282BB942959331088A6ED62C7F0F609E442BE14FF5FC 6587EFDB4F8F09CA08D043096004063A8A4DF6464AD680E64B0616439D3932E1 9944DBFEB50B9B57B3DD83EA0537BE48E95CAB49BFF62F42AEDB8E03632F2645 FE6A209CD56EC57BFEAF030273E6FE30A5C73C955DA7B1C2F9153F964C3D353F 976D7D00241580C47EED180C2C7DB761F29E69090751420C32FF34843550C10B 5B33119FD60198474895097C2B8EE5EBEB5B99CDBA9E78963B0E181136544BDD B4AE3A44B517A81BABF52811AD81BB9152B2E931C1907E83E7831C760B2A244B FBA480587ADC20E4BC0F806E4B14D624FAC23F13E291B3277FB8E01AB176BE75 E5402A583A87AC22D93BDA6EEA8E00A9EF239A3E557335AA399A751A55D0B032 B4857BA6EABF0C249C575C01ACBA6CED4D3586160E9930F09354479BFAA6B62E 504558A33285C25F59AEA2CB2F6AE27902A5728F9AEFC32752EA396CC16C9637 BD4E8AB0CD680014888232BBB26FEA212B01553B4286C332CFC6F3F49F17BDB0 AC61CF6CB0A86C031C4637A5C59FDE46C2C03D72B5DD479784EF72B6E42D8F58 82644DB88991868AD115453E6247E60B97822183F0FA787BE34AB52BF47DEFBE E0B4478CABB904FEF0274D27CD4BEC672825A27069DFADD477758FD6F7791E2E F132CED89946E9FC285EE083FEC0E8DF0FDB2DCC38DB7FB0A339F5FFC540B55A 0AD1CAC62E62C94EA2950B43877D415E2E351F277AF8CE984837A69EC315D27C 2EA3A90EC649919DFAEC9E5DE86F73FB84AA3E429200914634F2F5A275E41D57 E7C990347EA41654581A2DBF8D1EA09FA343513AECA8A58D4A08CD0B40C61693 2DA04D62F5978EA98E3056F3497932C5795ABB3E0B74D89D72773DB8382B2A02 51FEBDC10F44B370DEDB3A3FF5EB452B2AF5B4980F5C925F4883D3A81DE06C1B 5D76CE0A385B880FF141760D5AC354A6668D35A3F8B852A25DD5527E80AAB16B 88B01168D2DD80CB477C3C3A135BF04E71A4FD2921AEB03D681CF72E8BA193BC CCD7A9184B78E671B8F12DF97AF2CCC9E0535B3AC4949BB4BF6791BACA26FEE3 17FBCA563A56F769C4E73011AC56F7B26AF3D28D7BDED3BA49F075B9BBA26EA3 8EE4738CC78670306BF6249432E786BDE4A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMBX10 %!PS-AdobeFont-1.0: CMBX10 003.002 %%Title: CMBX10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMBX10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMBX10 known{/CMBX10 findfont dup/UniqueID known{dup /UniqueID get 5000768 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMBX10 def /FontBBox {-56 -250 1164 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMBX10.) readonly def /FullName (CMBX10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 12 /fi put dup 45 /hyphen put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 73 /I put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 120 /x put dup 121 /y put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2D43B233BABF23DF8DB B6C2BD2F04672F9A3B7FE430263E962F16A948319C51B8ADE6E8A80D3D88023A 6DEA4D271676C2C8615C4A0EA7DC8F6601610F398673A4D4B905F49EA868FEF6 39BE073001A36DEA6C08ED51452F062B971740019692E221F4455EDE46AF24B8 407A98B791F6AD525C72C09776247E194043281D04FE1CD1D8AD8DCEEC3045B4 F95B3B41CD3300768D8A049815348BD7AC1004F5500817E3A267D694AE108BAF 285B288FC5F28A03E9D34FE5D9B2F9A9BB26ADE66B1CF8EB5BE606E83D213C33 DE083C20D636EF780E761944FCE3B8A950B1E6E7568F33B557C6D59E0CEAF185 53E609A4F58AC4D5269116F958C4D115C44B5A6DABAB79D3BB6E60BDFCECE108 74CFBE258779F32C80CD7D9A7CEBA50A0966BD9961F71560119668C4A0C30A5D ED91ACB30940502B24F33906D6E0F16F81DA87EB6D7FC8B7853BE388C40D75C2 2CA8F94713AAA1561F5321CE97997CB4AF0E37F44E25B0F73CF4986422B1CD89 8F861CA623004ADB1C28268D7F8C484AA10C9519B6AEADC95AFAA3304D60E85D 718B2F67D2B734095E5A92C90785252C98067DC05137BE735220BBCB7C341D61 C4B98BFB1EAF883D38D7A93195A059EF82B42027F23B6CD633231D704B891A9B 03D11A646F13898F20321D7BC150C63FD6DC6BF9CAFD8DA759E95384B729A0B2 767B9F3E55C682F7A248BC1184F7D294CFFAE0B246DFCC8F215625DDD4F49F09 FA8D41CBF4A06152FEB152C61539ADF7E70A4D23AF8267D25CE3B12D39D62377 547E2528D18DC4134FA3BE0437EE0B3509223D71F06D44C6227D62BD01AC0A2A 3EDA975E894371C07CA1027B102549A7D552FFD25ED2DCC68E29E71BBAB43C62 57B0BFC6A953ABC2EF703F35D112F6B5460018CDCEAD17F149DBE5B52C2B9E10 9818EA6D97C8AC884F6841C9B600A7D868F59C1D80E98DE0741D06D69858EC84 1B33C6C9938B7E8A6FF6C12AD456EECBD3EBAF0D7331536B9F6422019FAFFFA4 822E79D6D89D6366DA636CB708894FEF904F366E295F1CB808E78E883913C4FB 1631248ED6A7CF1095C0C61C4F05E4B9DFC47533A5FD24540AD71A0E2907B98B 28085EB88ABFC3478C9644594C7DC4244ED5A7C1CA8D960B65497D56D174645A B88F12C2CF0A807DA314017984CF3C4FB7F47392A651EB9CFA961B28E2989893 9FC4D97171BD5338673F5D1CE2C3C08D48A1B77769F01D5058236C655FFD864B 80E28F900191D4EB349AA5E400A7B0A0FCA0F3E79D7A7C69775BF754329397B7 D18B20B2683CBC4A19729BA878B3C17EBA0A7E9EE297A5B67E915CAD92C8F356 582B8299DE6A58E73408F525F7EA895C48A8F0D626A06A96A50348DFBE479D89 4272576FBB0CD332193D28A8F11503BAE98F8E1D73CF5BCADF23DCD4E6586ABB 323568F5A34E359661074D50CD8D9DF27191FCE24F10225A5D721EFDE2547E1D CA998077D2340B1A4ADFFF570AA677CDF3305D5E3A394BB1626EB35074D4EEAC 2F037CA2EA389F7683FD17A8E07C12B4CB3BA8C249C9B12D297C618009F76717 0EBF5F2DD39A6BDA10A2E5A811D4E190660F5FDDBA29201B6F8042620397AB2C E59267A7247B0463891831A6F40582BC3F614E5167B646A8F53D8A31717DD9A1 9034034E705BA7884F0E0738307AF69D3517147C282747F2788462FDC4336A4F 9CD222908401A25F0A1F7B13B8DAE622DC965AD0BE62497420B70C04AF432237 E0FDD043456187658ED93B0F9822A3998511DF05E59CC85B7B9992CA0CE3B814 9723BAE70D2631F32B4BF93511F67179FFAD2075E1591CA5907A4C67701B56CF A5E5B02EB4A842BA1F18D6864E5677359C2FB4AF5BCBABAFB053F230CC129B45 8D15413F736EB07C571521C7DE2A13F2AC1C133D491B0A607197BE9AA1231D96 BED7968788246B2E4D2BD330F802810F5BDA3760FEA5210CFC6F54748FB1D921 5CC3624BBA5B8962AA7D94159651589540B17CF7A785F297264F9C1006D36928 6E2756D3B623A6087E4B106FBA76255903C624C07E18A1AF4E185A533C640711 86BB477A906ADD36EB6C8F4A12BC2F01B2B98412E4E105977640930CD998D990 0254A1E5E9843B7A8ADE0AF6D5871E6D3D666465AE69813A2E26333213FF6713 6F08D55A90C079A56E1B9AC655F720FC22B5AD8550FFF26DA7B0C5A0B60DDB05 64E8FAF684F3A455BA9BC9278043D79537D201D520E38750335A4C8FEA887377 879331B68DAD6B253F4FF9981D0F9B9550ED5179B15EEEB00E560A3DB6E5973B 63403E4E2F40A3D0B937246E9652000B917B1369741E0F913C14C2D2D6D1FCBE 2CEC4422177C58523715BD070002EC2E13D383A1DC8C84228862B6C5D3B65667 9FA97E175239BB7FE7E37E14B96DD7960A8AD49DF428CFC13B5D3CC22E245317 47B5244DA97F1DF954CED2D552477237CB23D037C0DE728E26C82738954EEA1F F34FE497DA005AF03746DD2ACF77F6E6F2C224862A1D18AF6F7A5DAF34564387 9E01DBFF49F8621C058C04C2B3F4F3033FF3E8A977B2CD6B2A3CA4A6C569B19F C5AC457AE9AF334DA66A730960C7565E93A2D373C0E3DE14646FFDA05DF4C6EB 6D4CA8ACCA3C3115764F77B842581760BFB9E5C0EBE55308B0577A8F4D968CE2 BA3361D79378D451DD150C34D7E901397AC63B33BD7DB13C50D678F5DE999238 4B4EA15BD449C46F262D931478F5685CDEEC4C4201FC3EFA607AFB8F27AF6751 125DE42D2FE2D31DE769B7E7FD8CC8C5D91343B537139A822A5BC4160BB5314E 37501F65B4FC35475FE9E03E34CBF6795AE86CE409500BD0799DE39FA69978B6 EC74D2197C03632D3F59B85F404DB31240968FA75059B2581B101E028CDECC2E 7E5E25DFA106E9B8ADB81E82BE9ED3BAA9D03EEB22B7B67AB1262DF6AF5F5EFD A5627EFEB84F3A5F92EF2557EDA2843D7D18C592635623CEAB14CC3620F33986 410D6DBAEF9F86E4E6682054540E2B01D8FF2161F10E66851A188BC15BD6666E 8D3F21709F196A31EE676D28A2D12639CC2E7020A52910F052E61A0710DF09B0 064171D05611451BD24FAD64716F141E1C41D3218A8115A3D73CA041D02B46D9 28C3D07DF0FB668E8E91409C8D0A26A65CD737C075E026AC0A974C9BE658199B 3B9D82ED95E4646977D8F60717DA4C68767DBD7E8320D5AA1D5DEB2E6B009759 8282F27D64F1F904830AAB501CDA4D9233FC2F12F77F0FBCC46E6B729C71F6D5 E6F3EA02EC35D1048394F4EF2177FC5EB726DE5EF2DE7997166B8BE5B5105D08 EAAC3481FC612665CA112D3F889A0E5B7843EFFCEFACA24A01B6AC2B7DDE02F4 A9295AA2409A3756BAAB44608DACBB56840060037869455BEBA46F10AFC68DD0 0563843DF111C6D34911CF13AA6023E5E899060B5EC60D0F78FDEF3E981151A9 24903EB13ED1A67EA1977449716D1A5A7EDE1A2E9465C9C2B20A58AF02D9F373 73E627CBF296B3A6A4670C39F3B5EA30D76F0362C81020A1777F0ADDBC6B52F7 213FEE1718214087837049CF2AF00407639657428B9E8B532F68B631611A3501 3D9DCA38090E227BD0D6D0FB4130EE866DB6B195C873AFD18DDB3B1E40F740C6 B3B375ADCBBF628A07A5FACED539FEDA3379D3B60216C2EA6629BE2F65199D82 FE3AE627D7C67270F3497AE75F7A9514968B5950E2D63C38DA240AF4E6CAE88E E25167D179108679876E7C80C85FE1D2BCC2EC9B88BE76A8F5736E8E6B3A9CF9 42E58A4ECB7914865E67C1468CF66D658206830B9380FE346DC2DC4BB56A92CE 4B5E4EA9036C177869315A2D9E6CFE97E3BFD7CBE0747D40CE5E8A3A0988576B 8AD2B1E4314C0D8A0CBCA08844A49F7E054D31BA7543730C0A7390BC4A288D10 CE29E389A4791305D3AC1BB6F77C805F1032787306F78FF76A20A9E629899F6D 13356768D33D7B9E294E8CD50CBFB9CA02A193922BD9B4372C912D1689B6644D 52CAA30F7421E8114D077288119AD9514EF21E5B9989CCE2ABA0C12549FDF493 FFB39736AC9EB72DAF45E4EA6057527FA9F5AA0A1A3F03C12F7482E465C766D3 760DA7714D56C91BDAED507A5572BEB51A895F8DD3BD5AAB042650154FC7E4E5 5EEA6194DF73AC5EE2CBD4EE26E29B1D2D0C458B4850BFE842DDF2EBB4E2A25D C6A11CA2D8F346E2B736DF88A3D57BC0380B52396A6C039212699F5D3342EB58 0C3DD5D01D5078479BD9FD10C07925556C0AB0F03606F33796BA72074549EDA6 E33644F62CA35207D7421D2727AD8419AD1772789D33405FCDDC9286BC34C974 A52297F5BBD2E541E8BB473F733AE5097BBC9D5FACF18DE4173B4711E28B23ED 16E0A6746A60F6FF903026A3900169EDA87D98396E762C2EC963D89197B8CD0C 25244806BE7CBF46BE60A8F9171731EADFC969C28679B025371E5572E52A0EF8 B3FD9B4638D03E20BFDEC9345E70B8166D38846DCA68E0D0B4B53629C7E7620B 45E0A610BCD07FEF8814CF915CFB11119F42407D1C6DC1E6353451D40A382C2E C74DF2A4889ED5A3495C3E973565F7178CA190D22C9693C10EB12C1E7A8679CE 4AFECFC964CC98111BA4ED2BA9B10292A71D5B11870EB08EB483922CE8628A06 05E7CF6DF93E112B60EF888AA8DB52994EC33DC7277D7B7A4F913AD30257261A D6EE80476A9A8D316D190BE6CE0046CBBCED365AB305495284FA921BE0638E00 63DB2AA4C5F163340BCCD1061B469504DEE350B82FBE1689C1B65D095405614B 35997D6F0DACA7190D64ABA351705B17B23FE2EE5996FCD607F49F54392463EC DD5B944A4B82FA2BE3E75E2946D483060DF99277340B0AB65A2042AD088E2B75 BBDAB869D1940F64B50D25078519D18748AD64AC5615EFAAF4F3105B0111AD40 70EE173ABE6A4ACE486B4E5999158A4377FDA6922FAA6E9305F48570D14BC81F BFF4C663E1EA9D1E050534F9315A663C4C5DA52CB02EA6408AA473C32CB0CD71 169BB43C0508A842F400240F0063243B4C459A1FCB3312C41C32ED0EE87F591A BCB6D5D3830AE4645CB4D40336DB4AB6540B52E70E1EA415CC6D886827EBC5B3 EC35CC5C136243B0C20B3C603B648B132B99D05F9B48263ACFA59A856BE74441 FECF5C6D1FE9D1F4F9942F460961901E16017144C37E83C6822177B2A6C47ECC 6C47A1104460665E5BCFCF08874008302750EB991CD98D0D8D22B921F90B99B9 05EE7C39F2BC2A7798157503743C9F2F267BDBE2E8A4CDA7317F81DBF8962E1C EC02822CC7F770FD4D08D335904375BF0C6DAA0510771627ECB9EE69C0F47D30 69A87052989DF80D9F4F19F75B070C3689AB3BE0966453F9D56CED6C1745B50D 813AE6D7E44B73423AB3778ABE4CD2C4DF40E14C5A426043F7057E2DFA2DAA70 EA6723F1C7967FECB1E7C1C0CA283334163FBE31C32254490170C3513580A552 19A5DD75E6C4ADCB12D33517A03318A6BBC7E4214266E125140D8C40F78A0340 1F95D9FBEC4DCC55B71E89375AA94B0D55646F6C069561480407D0A3AC127024 D7D1E9ED6B599A2A8766B8792F46D35508B66F302D289405B101A3C6BADA680D 8C56E2A00B766A4CB155446F862FCF17537A2BE85418E20CD77C4F1F69F70BC6 17BB5DA8FAA876D0E8BABE273A19C04A8697B3E3CF4725E2C77C8761A9243F24 96F8AE96399996001A57FD75106745AB4646FB9C6421F1D4EBF3BE533BD11AE8 14BFBD6D308376B26E08E4ADA490DDCCA94BE8240403D5EB0FE3549061DFB668 4105B4FE77189546619B6BCF3F9723E278E98D50A17DB8A4C46744FA21760635 5B332689316BD17C966D466AE737FE3ED7ABC443ADD88D4823A10BC9747ABDEE 027515AC353A420523F85298029475D8BFD83A2CD00C02CA07974BAA581D2215 A850E6E4C0A5E17E0EDF91C63FAC18C70093F40FEEAF0350B403E2806F4EAE96 BF616A805616EE55C4657418C26CAF54187A6684821B86A76F15088AC4D5B551 66C3CA8DC61E9810858D1204F899C7E3A1754F483134609F6EEE6364B1CC04FD 92C86EF194FA3249601AD722D75D1D395CD15A93C768EC60A486AE885683364F 93DA00A865C1035F913FDA69E7D9A0422880FB81EC23C00427F07A5EA3CCB613 83C859958AC53FAEA26A6BB39ABA068863CCE3D447720BC31A5136E08EE58963 093AF587A72112D55853A1048A2B1695DB2D7F13CC924F2F0902071260C33ED6 30893A04577C0ACF0681C0FEC23E5404F844A83BB5A2F8DE1F0792196139993C 1152094BC36A6AE5BAB4B8281E506F485F0BAEEBBE71E174B7CED1E52A8242F9 DBDF3E0FBA296538D964EB5B7A4E23B1BB0F59872C9D4FE8498203E3AC08B71E D2B965AA6CD5D20DA6C83FDC86F4A5D68A58A72C5BB9BFE9BC755C56B24025CE 6F24443D3CF32CD711D3D94C7C1DC275DDAE3341D840090F97CB6CAEF274C94F 9F3BD3AAB3F98BA8A7B5CE5E48D1462DAAB37BEB1C10B410E8D33FA42D898183 BD4F807112D78AA94509E33C179BF7C9E82E55AA7D09E128A0DA06A330CF4AF8 5DC861498CE029CE8C1BD15C923A708F2E7AF98E4F7B34212A0CB417553C86EB 6DD46B0466F1A21D29FC5111226794ECFCA5DD4240C0B8D106CCD7EA6F03E133 BB7733F055D6FFA04EF5C6F872B4FDA3E42F0F036C4825543D75682ACF71B548 DED160ACD05625274799D0AE201305DA526E01A3D2A719B1B15C05CC09467F3A 5627860C0F36C503EE392E1786620F3F2287AFE56634E03566B9B1F537FD92A2 913166228791871A8F8CBA1A1DA634E8224058052A10FE1E67CBD3FD21A6C07E 243CBF58BDC78577847664EEA5225EB8D6679AB17C563848A9D4D58995EA3609 51C1443B752A070D9872FE1643F0677019235AC25DC2B29169D38308F2170A1A A0FDCC59E6602197D2815B914041FFC7106DAAAF30CD97400C6D0826A40385A4 C8520119A065CF32CF2FC5FBD8DFD29222528A7F96FDA533145846B3428F8239 E50277C366418D713F84B12A5FD4F904DC13DB1844A391FDAEB97643A6FD2945 942FD4FC5A4A35E184F23304B8B4D93D0C37EFCC4E106D4FCD0DA3E5D2117589 3FFC2BD1D121026562C55C455C3585050B9460891B006F62D9D9B66695C3D348 A467C14C0256FA9621CB056E7CD389505194FF463BCC4010897F9A690EA87D9D BB3ED4C174FBADB8A4744C6E4A44D773967FD703EC37672F9993DC48BCC8A060 6CEFE8E6B8F10886E15BA0466AF410B90DF0020FAB88BE493606B6A734EA85BB 926950EB10D2F2CFDBD182B0F133809612CCF6ACCAD049C8005A42FAF78368B9 E7684F98DE421BE0A3BC0FAEE024A7BE67E15C8394F17FE84DFD8156C2A3E94D 08259E15CC657E8CE3088395BF6B5F825764E141AE15EBD186DC049261623D26 8636705E06C6E4A1F8ACAEA59F91B042DF5DB9C2AB986A784384706A43E5F18E 42C29CC1CA86D4F247B3BBBC89F3633EE074DCA4AC15B1E33EE4822812A62E88 C32B0AA57249980EE17AFC1346074800FA529445D18649A0475246A25CF325A0 BDA06AAF392FD455218B13D9ED577D51A9500B9FB7860716A8E2FB3A8C4BE3B3 6656C6A5653AEF00184020ACA0BCCBF48BE3BF91E11C8658686C89848E714E6D DC158DCD1C1BC03B83FF94C60B1DC71CE8A86B46DBE661C9F8F4677F8A2C7CF1 E41A91EBDA2304735147BE66CDFF2673F09D408297302124C127F0B35690CAE9 CE1679120CC4D582FB69550AD34A047DDFCD9D411724554CCED753DB52D6AA7B 22B0C55EB698ADDBB0F8ED15C971AEF113C74B9E25DA29199237B98DA4023665 C2A63A837E4CAB38F8DF37DBAB5DC80C0AB25B56BCA5D899F1575E61ADF75676 F48EE26C054AD9A75FD88A3E17498AC26FD4DC8000A125D6DD423540B8A98779 B28CE97C9CAFAC45693FF43249E4B559E7F19FB349F94B60AAAAF05B5FBF244E 982B4B51D997DA5811CD43E1917DA885DD96133A5CE1A290DBBFD88AF285A879 D3136C41C839FD2276760A7B4F21F4026AADCDAB3F113FCCCA9588C7FB72643E AB8F6D8AEAD1DC3DCA6E436B3DF24E7DC6AD37137B49327871EA80F3B8AEE932 D20D9A5B4779DFFAD7B3E5D447023D6433575F8F5AF589D7E094DA3786555D0C 046A427ADF128E00AC7B458D5A131A130D6F49A7ABF47833791F172D69FE6393 EAE0E90E7FF7BC2333D4E0215D5201E4B209591782F8A664335F67B9DDE36DBA 793EC77E5EB405862D14EAB6A99218B3F66F11EA2F345629C402BD8FD9CA0AC8 FB5A2E119DAA9F80083C9BC54F4586C44320993CB5D9CBDC8F8522001F82A16C E307F175B794F4426E5D273581A6D2844444D82093FB03482B270D693391DEA7 CB26D4A418E48A2989167B7DCE251F0D53D5C9B29D359A568FEDB965DF31CBF3 900392FE739A2B43BFA2363CA74FA72668FC761D1A17B9C0B56D6172499CDDCC 90EA538A5526FD5AFF81D04BFEA703E5DA963B11042723106704021C1B90557C B7AA96E076842E2C5F929FDA6D05E0B91B5548006EB4A6EB262077411083C2EE D51D0D237A85D6480DA41A9D8DC24EAEC0C849E0D53D9FE1E54ECD82C957B8B9 ED68D7B29A43F369C28272083B7B4E700546D293DEDAC7E74EEC946B4412B0B2 0639AB78E79402C787F50C4F78991DBC12D73F5B371BBA2CD9535EEF0550084F 40A4B2C4D178C0C001E63E08DAF15D064426F6F24C49E02AF5417D18BB7997D1 46CD6476615EE2F496EF2D2E5A6DE68ACABAEC2033F9F3689D9F8CA23483C81F 8E9CC42B7AF2BC3FA80B68FD37E3B87FC27AEB7AF6D2DFF9B4B7A60D26292AB2 36461A349D3BEFAAB8918729204873D7793A647387156252B5A1B975639E02C8 9715F8B4853B592ED9E467BA41B32363ED0D7557EA0AFB8EB093B4CB1FB3CCD9 3369A67A60448575C7CE305DE7C1B59DC21DB0132F2B67B7B31EA068C5942DBD 7D1BE9CBA33107AA60AD033EA5B3618B83BEBA01BC0DB592BCB0796AF520E8EF BAE6CBAA5DAB5897040D6CB1E3EEE78A98B59897138A084E64E116446EDAB213 46AF2FED3E303F05D7EE630434645AD21B410AF8C1808A79F96CFC56741F62B4 431AD2FD90CCF0A876EDDE18506E73B4E390C752DB45A2E8BB824F2E0310C59E 864A74877AB522D1B477F5A3D7ABF80CC031C2F2BE5D633E49E6D10EB6EB8434 F17B15274840BEB842587F3B9AED05B97DD603AAF94D5FA688675B55D40FA43C 6D97741D9FE5F54C7D441AA62D48801769531ED7EFB3C438EFB1B513E93686D7 1738FE955FD7C67F11323E059BCD0C4BEB275C26835080FD2AC78DE88BF65298 A8EB4181F48C420D219CED950E4C0FC0330B49547E593F961B2BA33F375B75AD 3EC510349E6F496EBDCD1206243547DEC26F9A61DA31D6CD94A54CC54EC81B0B 176D21AC6779041F73E5DBC0A2107B612B9B89E20C373A057CD51327757DF12D 01742E9AAFACF24F24D18733EAE10725F5FC08EF5B42BB4E018CBD983733DF08 E018AB3151658D98F325882A033464895EA4D374541DCC18D8A4547FEC9B7206 07AC80FBE732ECCE672D5A6EC117F5436B0C476C504EF844C1AC7D50EEA75A40 7543DB4109218B12EDCA321C46FAF5AB028343B05EC8749D3D46AA18834BE53E 378EABE227B936313A58950A110572C54D1B9B2BCD7F7B73A72A6BE8C328275C 93F92B93FFD7928C8F6D24B6C471BE685A850C35B267F877AD20CD6E242F7A13 FF7D796EAF445F8870E9593BE39DED366EBD62A2D5FB232390D7239CA97F447C 5617AEE05875422520CA2FE3B70D654CBA4A65F197A31ED82CC4A183ED86D278 180D66D97CE9B52FE24705604D6B61E916B27ACC7B6562FB568CFE3D6FF8324A E04AB88D33935FBAE571328911AA8D16133C85EEB531EC88BEF7F2FF559F1254 6E62683AA3563663F85CB5155A9563A3B3009F37669FADB586A6D968C773ED08 6ACF3526A8C9DAD081BD0A6803D8B14E755112D54CA969F0A1407C8FEDABE940 3B185234B1255A2F85ED31CAD545CBA80D61955FE1307D53A8436606D292CD1F 827CF41845BE0BF82132A47E66A414693E8968DD6F70752A9C9733F76ABF6CC1 4F198DBA7A8AEEFE81A9770813DF2B1B539CDA88BB644A361F830748415DF4D1 19CB70C9D8E4CB2646351A7610E9D59C2CBECDE4BC324C436303E25F8FA11403 FB104D2296B4AD009FFD8BB2E34ECAB2928659E5ECE5F23D716709150B83E66A 3A161EED1F9948A462A82B6F295F739B353C56CBFE28C0F991395F0B491A9A4C 1663424FA8C066B5436D54BDB9BB02BE12E2F6B422FDF15D13F0BD20EFFEC7CF 9F0B9DCD5BE324C611B087AE5DC680F5A10C5007ADBE32E24FDEE45D8A0C9C49 4449C69BC13B83065F0926787A6AF51D620A4B08C52DC55AFC5016FB2C4F72E6 59F9282B79BC3FA1308A6448B424DFC50A6AADA2C7458D8857AA53CC3FF0A4FC B3B2F24E2A1F06187FBBA32F88BCB54AA8B1B656C22E2E5B660AC80C94AF55F5 F1CFF40A298F1BCC155CDC51FEF9DD5444CA233093AAFA54FFA58AD89069E96C E2BB377DE0868240DE3669ED25ED90842B8F58CDB75221E9F052EE20C44470BA 5BFECD087218EA5ED31B1CACDCEA8E30C002ACC4D42E652543B0B5C900A42D12 4B6983B5CC389BA8A1038D30AA554490DBAAEE24C8A66F08FD91715C7A942BD5 229ECEC9A0453DF6B52822258F20C4027148117C547B60FE9F65A58D52BE0AF3 5C5806FE3370710F1A72D8C3318221BCF935CFDA487CBF3147024D6B823DF7D9 17260B670507BFB43E6ED108330754F4DADC600746F71F36010C9AC4EE4945CB DCBE85A8854D90E173A1EA4CE2AE7FD0C31167CF26116575F4B3D64B9BC13B77 48AEFC72ADCD6196E6FDF82F6D92A3F11C7EA1FEE81E086B9D705B1AA8697A50 0C943F702F820CCE6181B6120BCFA6668A5411221B1CE3D803AC542FEC3DE652 158637B3D9075BD4AEB1076EF38DF09636DEBC6974B464932404F3017E135ED1 0E446B4CCEA5FB269B7EB5AFE4321123A5E341E6E376A63E8F435E7B82AA62D3 616BC1FB3BF299EF2B4A66134050B3E102DEA12BCA028F402E9602317E39F759 D7ECB4262E8BBFE62567F2827FBB1272331F2F4F92BB942E126A927C59A5807D 25EB01581027815484BA6E80A7054DE61ED28EE040D6A19B05B2E385073E6A85 E1184C2837691CAB4D92D5704A37090340AAD3E186CFA193FB31F5EBE578D011 F2B3392400F7C8894D369A474082A2889BB0DE1E2E0D0646A3CB0E5628BF6C8D 599EB62602E25624AE69AEF32464B022ACFB8955443965DB567840FD9AD944D0 46BEFE04213E45FCA5D05382B5B600008196B72DDC410B43C22384EA190779DB 850E1F0C8DCB696CE529465BD1D261690E87B765C82C8EC81E00439C6D686215 CAE8D2A6759B3BA43B9BDA541D3F3F74BDCC5EA35F7C4AF039C7D12B6BA91692 18D70EF8769875B524F1A064F5474731EBA0B687076CCD14323034D9063CF404 AC2E77E5E3CA28061F91EBC607F70F182AE7219BFE341207F12B03968966A34F 5891EA3C22A09D010E11E6D49C77FC969D1EC519EE0EEA3AB47942F05174AEC1 2CDA3F68A6FC53FC2D2763963AA6485EB66391B6C8D23674B4813E517542ABE9 52D159905D49892B70588D7E33DE3D9F0ABC08466DD6A28B69ACB887498DCFA8 924BF2FA4EE3DFF22FAD630959393CDF7A777F4A675282381019B265EBF6E4DC 9D1DB2764AC374B8DD7552C7AA8AF24C247EA95D919FC5E16E564660A5BA95D0 E2154DBF74BBF68040C8C8FEB1EF2B5340A411BF5CF5CC741EE44851BC050EF5 7D02F7D384E448E4B5EAA0937EF2E8DDC7E29431FDA1ACB8B15DB19E9BC6775F 9F33A354F39792A7CE14BC4C7BB2AEE4D4C8D12A7AFE49E0E6F2A99A9B7E9291 2B573B7A605F448B2B9C9F0A7A5EA6E86E68589CEDE6537B6A314E14C3380F88 211D6263BC46395FC6C1F6F6E52CB85EE1F6E9EABFEEDE551CA7D54BFEC8A5A5 3660E975E20932FB0A42AB5ABECFFAD450BD2B9FB089EA0163863D8F1EB972E1 C4C4A341B7B15C3A53D5BCD1AE0160750BC3F280190480080AE5DDD8716B7193 431459C8E2D28704C118EE201D1489EB37F4E77BB3E1E2A3624FE3B54562EC92 A7F85D422DAEA4EE79A32C52FBE92DDE6FBC8C8FE71533C9CC4F5AD5EE87665B 4A9A9E06210D051B4E1CBE457FC66034DC0C98C6065A1D5CD5FCE14D6A06026F A30AFE8725F5CB0721391907737F7A14F73C8D1F0261BE1CB97D2394342AC118 40FFE4316F351AA77599F248781D02DD71535DB854C81E31DC424E008D85A929 F1F79782CE6F12FB25D94A4DA01F9E9EA19C80F8A06091474ADC9CF785BD74DA 723D89A0AD388572A582749A8497AFE8854B5FF31BD796C906398024E381D64E 02480F51B7C82A5CB73E94C999538CBC2AABE5097D32F82072AC9161C0FD404F DBB67285ED21580DDE5251430348CC31727021890B5F2DF3A242B730176F04B6 9FB1E640A4C07AFCFD6E9E7B3B124883777A75999EC0EB363B843B494C893F39 0995BF8720BE94E8731E75613E690BF94A09CEE3FF9E093B9E30DA99354D958D 49B86BDAE7C31461537BBF04435D61F06096B6EF7CCCB8A085E27EA8D1DDADD6 BB90E60B7EDD1C50F4CC8F669F66E1348700AD3535C2BD8696D484481C5F9C6C 810F6C4A2EAE4C85C73135133A1C8409C1FB94952BC33B5363F18FBF7EBF36A9 9CEC9EB1E01E30F806BB6D7A51DFADD25F98CA1F23F99613171B47F58F9A82B5 DAB61F7B64362FEED0084D2010400FD9D55AAF21022518C90D6BD0BCD92115E8 05280FCBC0A0F35816832182E1BD9D95FEC6166FFDF50B33758643F6E550D8B4 B2295A08F8BF6C8310144B6CD0179172C57272E5B4DA5BF152A0BFF3100B247B A47094088DC50A1C1FC1FA9E3A777879B20F6BF8494EAF7F94A1926B4D256C8F 73687C24CDC51ECC8D3E3F13FC162FE73AE0ED041D869242741A6EAC01E51B1F 1B135D8B20594AFAEE8394A16DD4971E63DEA454797F1B4C7C3C43186E6222F1 EEC1484EC1101EE50288D997E812262E430C238E15B8B9982CB48EB30854071D 2F1B782088F3264F27C3BEC9C1D103B38D44AE37826A16BA6D39F28528DFC4C6 E641B45D24E0F07405FE5441C2CC497B332E904266FCB2D943365CF7E5DE0883 F2C09E3C2AE5888FC0C6C48867A4F68D75929C922EF52A5A3DE0C2659ED0C8C6 526FDA570E25840141A9EBB16CC34DC0B3669E802C79875176CB8633A27097D4 78F2C4EF029145FD2BA152B209AEB3160C443A23373352DB3AB46E3177DDB1C5 28556ABED758A7730B052739631B8D77D595A551349495D32B7C4548402AC327 AE4FDB04E5DC9063F4DFF450CFE98939B157D8D8FBCBFB73C0D4FA5DA0CC4AB9 694E82F241015BA4D941E869D478D5B3FFD9EA7A53E89884BC9B1D802B2396CE 869B0039CC4384832400EA435474AD459BA2F911D46085F85763C25DAC75B58C D2DA83830BDC5D53A8718920894BCD5CAD7847C79E923873F4658D30C6483902 07A0A2DC2486BA43F96EECB74C466265BC8DC0D824FEF328A2D4413B7BED19A0 964BD86C79D167E08DC7D1CA2AAD009B2798C1D1E0785A9B7B2433B6BD77628D CDEF5C2CB68020A768E83A52A37EFA958C855ED3071A6DDCA0116997B939C599 3F36DAB2D5FB298BF97DA2BE167182120B8D189756678E58897586CE44E42163 21E247395C248DD04BF10264C178464F0BF3B472C1DD3FFA83653A23BBF8FC13 E90C2A0C7F687501D3C7EAAA1BFBEB3B791A81F56FEFC37FFF8417DC0EF0E44B 9B69965FE647DA22B9F411DE439C381143B3721DFA96F4DE812F6186A731D4FF 67A04277EE7ECE059637F1935A659917CEF1962D8CE52BDDF85641F095EF330C E2EDA9885829D4516C6AE6A4F0167F6CAFC19359F9E2D398374931C08D974584 8931734892825DBA73C1145309B4DCDDE1108324AA810AF6B9DCF2D977DC1211 934241B6E38E788F946221BF83E3418F0578F9002E110B1DBCED0568F4808826 42F545D9AC8F6DA8C0B12C70FFED1806A1060FFA58050C3B55C36BCCBB791FA2 915BC02F500C3DDB2BC7C394187699A474119C7E7DE5537FCFA57D2B57D1141B 5C00B97BE5F1527B0D45D2CB7B12937E31465D53D15C9B27835266E4EFD3E48D 5E9BBA0D152479B4066D7C3ECF066D2AA7EB3C8B059EEE6D191051A49A91D877 0613CCDAC78D5EC3FF5A626BC58697C2223BF8797A90B6DF06EFF82E7E526EA6 D8F829020ACF6C311D84D4D071C1F6E3D23C58339E906816108EFE733FD07320 57930A679AEC5A208E83E4CBFD52F13F2CED976136517B99F9914221614AD6A9 D5A502F255E73F9295A50493A9C69FF2B608EEE0DFA43A69AF97397C54D0AC64 B807BEEE8B12C59B43867CF78426F4C890D4E98D9DE885B074587B60902C509D 70195138B30259B4FF4CCA4BD972516A2404E6934710DCF368F1F5E480117028 E4D277E12829BC465BD4F0A64E3BC7DAD26CA50B13A576B6CFBD098FD3A078B4 19D275595D2F3EE7E09B6263D58BDEF302ED9D5381AD0FC97471C306D5B1DBB7 3531DB23F2EFF0686B56C534EAB2D77D7667B0308E39A41D26E06380AE07A67C 933044A653F865595750028EBB94EB9AAF42151A81FBB41458AA75F8DB653755 C0BC616894E63DC3EC7EF042C98C42E6B4BC9DB13F960BF3100D5E21458511D7 D21CF53E5D07F80AE205D24B39AA948665549A69AF5CE99E5302EBD7D424C8D3 33D6EF060E8122A639D94B0178EAA7061357BCC6E8078A53B445158DA67A1195 3DD0506811AD74C4122FFF915DE5E36D4AFB0B0212CDD740305DC8B9B3BEF169 A206B05F8295538E6FFF93D768DB71FAB6912244971A4350B8FF6D1AE31E9577 A660315296356F01307BB7F524E8E00F00B5971F639E84E2207BA0EB32B7C267 CBCAF9F0B4D3A1A598F19A8856869E81BA7C0F36776B54EAA86327FFF40BD9C5 A8652C95E47778F4E006F56AC5BDC4B4CD8C39AF81C028C777E7C72499BE60A3 0F3299F101C87EF0C4516F2FB377809532E4658E977FEACC5E6FE4AF15657843 058717A650EFEDC9F861F0527591413FD441A260F09D07C8897EF2C3941DF580 656C3AD9EC1F1F1ED68C0E54B18A54D87A600A67C30820BC4881D4A107A8264B 940ADBB05EB1D5EB60F8CCD51C344A009D30B12AF99120652505F6C4D35A9A72 2B10B0E40E1640748AC38FF56A5DC127421EB6B243B65BDE5BD382F6E073DFDE 87CCD38C00F26DD2ED3B1ACF00006DDEE953CA9B7E0339A52599E0028AD0649B 9A2B7689ACC0DDE6A7BA4A8F3EDF82BC53A8CA5656F79B42852F49E1BA71C639 C8F9BADE025391A40E7DA5F77B2C9BF050C817F067D6A88F30517CDB9A1FFAB8 1677496C26BA0746FABCE226FB1A1235ACEEDA29E28B621BF3EE1B548D4DE72A 17D1764BC3D1253089C680148067E832D08D6223939DB5BB12545F7250BFDFD8 59FD7CBFE909D3C086CF43FD63EBC772DA489C7B8330AC036C95E9D4C51798F8 F56671A76C7E942933FC49EC69C8A28410201A73770D02B515F0C8D4F478D007 7754D1644C6C6093A0825F85299FBF003F3B020B0D3997A4BF0D642D34E2D53A DE9D5A7155499BED1D5399F1A3073C3FCAB568EFCAACD991E61E6F1B91BECA3A F89CFC8934B144E78FB6FFCCFDA700F4631B64142998B25793E7F25CBE883A84 2A03009F6B3DA97A504A75E9B9FCAFE95FFCB65E6F486E7D9D2A4B11F77D119E 7C34F72D2B345E1C2443B4C44AF4BEC5187B153C0E9B86BB0068355C2007E893 3393800BAA45D3F5B381DAEA675D637B1668E155842DA8DD6CA9C42715E74BA8 DA94356F2FA11144262552EF847FB073583A473EF3FF5A9BEDCAC77F1CEA8CDF 7DD65D9E5FBC561D3795F57C9415783E22DC1DE08EFCFE07C0BB7D02CA45E378 3ED8617634263063A6471C5B63EE6ACF73F149D83FF3910A01B5628D1F9E95BB 25B6E3F1B692892174B29C9ABEAA60488E2C22C995A70F3F93A344352F82E0A4 DDCB7ED99937824D3569DC3477A2893F1FAA4A5A19A57138BE111CC31964F8B5 3D703E07D02B8E618E4FBA0A55E9C1AC11BBE12156AD7421155B13ED556A5AF6 B37FF508F11380957913A201EB8FA55432A23FAC88D7759DE8C6FE9001E8668C 2D63CE71C0E0490D98ECB83C353DF60BA0B711C265F674CEF628EB2897B685A1 BC6CB3E54EFC1901FAD8EBCEA33AD4AF382C828B77D9AD4E39E2A06EB7F405E7 E1CE6B18DFCD7249C24C3B63C5EE3F027CE76E77A23B16606F7C6994B00CD696 94F5E5AFEB9D67290B664D66F1AEAE9FCDE5BBCAB3731366C30EDAB09E9D9322 16389F4ED434AFC786DF8442A38E695E291D6DE44E49035B1AEED09C69C0F177 40DB6C3C0A804B8C3002E212AB2EB1F036C0051648B3097BC39C01A4D8FDFFA2 3102B185ADA83A25DADC21F526C954CFD354109B77C80E3739EEBAE40E98932D C1186EC1F9D0B5D532F032FDEAFE50B41D47D42B127D47EBEE46243B41808A4B 8E1EA9BBB7F545E2226F4469D151D0072FF8C190497BD9E69F439DBBDAA1F238 7F88B1FAC8099A67D9590F62B0FF8A1E143F4EBC2F610DE345E00F2462AD91CD DC55493CF4C3E7022D48BB036CFFA2C8C2443C0565DB51A50513E4C26FD93B80 F52027F415D59F0753EB916C69D015E9FB97A5B3344B654BFF1D4A7A54F868AC 4560F0354FFF37C768EECC0939025DE9E887B674E93CD2324742F026C9D12D21 CE234B38558EDA432E63AA3AF95912448F116386D887433404982CDA4BF3E3C1 9B509244046041CA85C051BB516776E4DE0853E899E5DDF3670D22AD5D968D7D ABD4C0113DE640EFD3E54464060D8EF87D1EA41FA78AD34CEEFC2FD37984B6B4 4A6CD31948EA28E817E7B9892545D2A5D351C88B9812213F8D7F3AB997078A0B BCADFDF34096CE7FA7626FF493A18137E1103238D9BACA1CD7F926DBD96208B2 766AD375EE6BE13EC62978F9AD2C98679D95E721CF196FFA6A0883F66EFE7766 E222207ED8B2B370B93AF2EA2F6DFFB48A1C09FF7DBBB8667E435C9FE2D95098 4F43E8AA3D9E2DEC06CA13F04739EB37D1324AE3C672C7F56DFCEAFD48E19682 0A06D04B81378C2251F532C35BB050DC727A672714BC8A4438D5C2E389F0AAD8 C9A4D3358A383AF79DD011B6C588B37FC0509544D9218AE84B5FFC2DC50E8680 B8F2C4955F7382AF43AFB8BC7D410888A4B8663C683A021BAFAE20AEDF094D8D 953B5DC77CD700EF7B271F8A8E8BDD06E60A6EC5F29CA105356268F6A970ABED AAEEFBB543A6D3929FD6A7F83F872DD862708ADF3AA492876950F4ABC81DDAF1 F96E4C8AA6F9297D04FE8BE5B9D2717D73465D1913E946E666C7C1753AE32685 B6258A1A1C4029A394FCF03135C91B19BDC4CA3F95555805F13A4633ACE1C03B E373015D0163D04C28FD794028EAC9FDB42C13DB45E7A3B8FE3F42AF850C0E62 A41D2EF3FBB2CA136B8D0B4B2A5AF36C564C89D2EC18285185BE550411CBB844 C639DA99B7814551D7D933D27169229B7553313F5EE126E1FABE2C8E7E015F63 0D384B502D41331AC1DE929A3B9FDB074E0A8781BF5C7A3590A1244B95DE2E28 D05A74C1DB02662E52C75BCDC4101D176CB0B889E33DF92F9AB6CCCEA9FBE268 E8988862B7FB935FFA7800C0F171D9EE640B37943069CA576894D8E45917DE8D D30CBAC75F15868621C135C494761F57F22766A8E815A21CC1428BD49D13B4BF 7185FDF23592E07E539E99565F3F545505F2C396F2EE4A38620DC64400FABFF5 423FC1A6D158F7FB0F307D40506408FCC0B0AFB547F7E9F02BE1CEC1F9128C3C 17D34ABB6F5E905DDA7274651CD7F7D30B381159820C69B17A0F0BD26D6E9199 D1115B82B5601AF711AF663287CEC69C9E0775F7D9B5595A8E2716AD6FB08665 03087CF360A26229C26A9D52DFBA89A67C96312B1DCCC88C5930231BE1C4D74E 09C097C6A0B71870066C66D7294E21DCD1C79D9EFEC345650D45F4C929A8655C 8FAB0E68F2097AEC3E5EAED04D21CF58D9D735787B892679C0A017FF8A7AFE39 202E51E33E029007AC9A3ED579BBD8F5B9BEE44C70B026D9BC7094F9C07EAC24 F0B65FACD576F8210A7797CCD7CC1F9DDE5153BA8FE51B3D4F237C8B31CD285B 312AB9239B853698A1AF8069CBCF0BD3B14E71A4CEB7F8B2602D8F8871FE1056 330C2C7EE34DB2E9BA60285284FEBC79674B6F837C1B5BBC2075FB5FDD5FD14B DE393D962C1FFD1DC3CACC9B6BAD366877BA86D3D3BE5E6423BD423D093888D7 8CB5E7DFB9F772BA19D33C83C332375BB57952D12E7193118188B8697EACC2CA 8F1F91EB73125B57DAE84822B0E0C4161CC4AD593103131B88DBE2E264ABA63F 75E1F2F5DC855B604D6C9EE8D2DACA9403FA53BCB4A42D7E40D79BCC68B5D4F0 D6E0C46866F0916BDD424F82B55BDE1CEB426EEAD40714823B3C1524F421BE10 DBC812BF9B17E520EE6F493064327A23DD095BA672CF9D7972B5FAA11B1F88B9 7179681258B4905FCBFA4FCE65179BEBCB0F43CF449F3DA6CD9F0F03245769F0 A14EB72AAD4B232549881873F13173099CC9AB0E570531C2977A673628DC44D1 FC27CD1A028213109C49E305763F08DA936707176E0EBF4E8E7CA2C6304AB2FC AA69424AC17CC4E401C86F3F29258C86C31983A87427B4C0A5068C8C7A16D7C7 3CE86F97D2D5D278ADA517F24C9B2547218BAC57E584FA3DEF25D866D6E5AEE9 16B21381F44F7B04D03F07C2C42322FB182C0AC7F2CA9B18C37267E1C901E8BB AA954828A59EE4FD0A2252A1F976B7A48101A6F9D7D7DE6A6E13D11DD0B4B209 16DAC303345C559599382C4E24760FCAB30E7BF44DBBA39DF4C6BE62CEA6A35B 2F2A3E98616AA3918A157FCE610C4B679EE367439DDCD20E3333F93C39123D22 7683F987A96CDEE59B6FC2B1C2CAB4C53916EF0F3449EE6C1EE230DB49EB50E1 F459D318348CBFAA3A2E4CC4AE7CE86697974F9E45AE5468512B4A490D02D638 2FE7D9DE30D0E5F15CE8D6CA9550A11077F72F4A0416289657B2913B5CFCFA2D C46F5E194E6E5BC07CA5215A7A83492D281D03D1DC047C030A3D505C6505F23B 2D429799034C9F278F8B12B70F09B088EFF4ECCF4CD63F9F7EBD9F4ACFCFA793 7A2E482C519C2F5EB5D7FC7C533DDCEAF07A10FD15B3674298A1B0B06151CD26 1B5EE00CAE37F25A7A06D2A2E2A775483039FBDDCC05BB8AC560E2AF4B13549D B06BA039F058AB6791FD78FC69136561DA75FC0E58D7F3FF47BC3589F04F1C9F A4935EA75AB4FFC48117CD8806B481616AB22E0AC6601932D966E142D6AAC5BF F1DCF39A7FE860CE9B4983321E19BBEEC9B6CFCABCEE39D01BE5D1E674B9A167 F1A69CD2BAA861D3A51CF6A1CFD84EC28D57E04A594BB41D8D168F17B58B8DB8 E3628A5A5725E20047A0FE1F6504C489979DA837BE45072F85E2BB93308806A0 A362CC6461AE606FD134C04177D2DB7289B1475725761EDBDC7B0A567C58E873 7EB1AF6F77962DCBE577B740B2F60A5595137D4B62EC2375C0CB7983029BA772 7E04BF1111214DCB1D1B7097830C4EC705AF71C3094CE30ACCD4E39AB90A436F 065D259B8213F929ED805E8E7EC17B8D4E73729A6AB34C9A7F67AA5CC6888AEC 55F4D8A963B565B32DBD3C36D81249E7BE1AA98B36C9F88A8F6F4E2D35E11203 B8F9848D34FB9D92737A57A75932A8DC78B123F1CCC3E38D9C991DF4D82AA8DA F796A63C0A1B66EF9B8F8DEE22702BE0D79C81597DFAEAF643BBF0E44366DDBF 77CBE0664B3E676CD464788B28A3A743D97D66C703A8CD444EB5BF0B7AA8EBD7 1E3DE4C2E1CB089BA4C9CB4D80BACF4BFC3B4EAED1DFE0B9F184096D6B739507 38E987BB27D0D284D232D4E0519A677A7568CB785CB30CAC3D4963EE8F0A1F05 BF185A9A1EB3D46EDB6100CC10E5B77B3DC3FE650157D380918B987C1682458B 5881F2910FA664F64725E098436CBFCEBCE71D93720ED179C913D282BB1D484C 2DD72FC4E8B17825F3170F874EE44908BF7E0F9B25F3B83258E6FFB1974A88EB 1D7342BE1039B992E51303B6F192984C31775625F72C8ACC31425F0E0431BCD6 ADF5A7B7D9DF817F76AD8F957377CB5EB50F0CCEDB66C548876206BE5950D6DF 9F3891C5AD3B6E6B00F5F583C9432C727E0F9CDFD53E36EF05ADE5F77BC8F976 9EDC2921629C9C8783F9989C05845F05AA61D5B8F562B5E802E02C8B885979A8 38DBF443494043A1982D0B357EC3816CB558BF60E2E7C4203062681DFB3A2B58 FC7CB77AB2A86E32A77F804B4240A3811911ED0C2CC81D10AB5D53A4F76BF778 4B6EF37E2F0D6AD0A5925845205D39F9BB05A7A1B93B6BDEFE500F5A392B1338 22398EEA9C0CE08C72D0E7402053ADD412017BA603BEA44CE46FE4D5F00C79EA B4F233B02DC96F1F12A706920D935007B9BB5C6C7101D3984B528E8CA4852708 E428BC51752537FD85CC027AD0D4A2B0CB06137AB6813C39B50ADC6E048EECFF 265619E546E1FD64D5D32A928FF6FC99D38476348844E688A0C9DB11E3F92DDE 3BAA26E55873E6C351C3F7A9C11E6DC7D7C52AF6B29C3ECF44450A358FB1EA2A 50F4E02B8DC51388B4A88264E2C97E1507323F0FBF85AD460166FEDDC7E8F002 495E18A3501C33AF14402836570D22C1F91AC9C83B5E0E7C92FCA1E7A6E05D04 6EE4520F4E3D7D4399339BADBD307E310B643597F65F616C687A14E86ACF636E B95A64CB80B8533BC5B0219EB7B749D1818D0C76B42297E28FE6C56796EAA440 933E5831B58E7B97DF6C65BD4AC1AC898B382598D1FE4D89400B6F34393B98A2 9DD34642ED9D3ABA2A9547A8860B1136F73C5781FFE679A3894BAE60B37FC2BC FB7AB41A5CCF5B2166CF436A3362F36ADAF8843390C47BB5605AB38637ED07E3 FB463F5530449AB024974AA3E378C058AB0C7C76E2853C84F3AFF51274359C0D B704D1156F3B60EB11E2304B8E55C7E2A90737E2989D530F93DD22E4F8F8AEBE F6DFC3972A79511125B1EB81EB754787EE58D4B6F2A04CC375D2EAF20E442C74 7E597363927BFD987AC23E3B50B16E4645A33F45DF6684D3DC06743E4858906E 7D8BEC5DB7798ADBF1917F6C9FEC3805869482B6EC62336A4CE004CEC7369017 676644FCAB5B3E3E97DDCEBBD7DEA5222623DE989FB09746BD3F36E2722B91F8 1527E986BD486B25F627079694A3DBA8FFB31D09A73C4BBF062B9C06A4B648EB 2546486D7050D1AC054C472E1E2A360D3F004EEC29D7B43E0A81274BB539326E 522C68D0A717A7A713CC3E6E7C7B4D6D2B1E26812670CEE639ECED6904489526 C2C2489D209D78E0194A0EF5ADEBD6EBBAC01236A0A5BC87AE8F4ED6E682034F 2F965F98D4D2324B2302220EEF854F149A36409E50224D693DA9C6DD5D17CFAF 109F3CED040B9C74149FECB5E7A0577273D85E2D2716BDE45CBDDCF1A9768E09 0AA9BB33E8B2D084F92C9E2140F0ABD9D1F543C68AFEDA97B52AA9881C9C3EBB FF6A7F0999145A84165A2E7AC1442640D51E5170AE081644B09050A12209954B 0E9E479716E04A8FD6918FDF52231C44816BE11856E2CC9BC42D7B33DB604F21 D96F8E171DDC4FC383E756F5A6EED0DF3851C0C4BDAA686DE983D32224CA8792 0ECEA96B56EBBC58742B40B67C4ACDA4AEF69EEE9F6F5F543DD5E04E989C9A0D C0959ABDFD64B074BDDC4BFB3002C70D794942ED3FF295C7D0435CEB5D20D260 78EF768EA9559DFC14737DE7310D2D22145951B51AFD36D507A7D80F20C562C8 72DD3F73B7BB8AD7A9C4973E52BA99007244F058645DA3D7F7A653655D65D48F D59770D5E99884DA1CA211D587CB2C374FEB6DDC63FC32E304D807B5D8E58639 11D76A90744ADE60CA9775754A700951AE362BA7D00082D3B2600875D6583684 DC1D8F9096CDE0FE56547BF15EF1EEAC0F0016D79D98769F099C8FF9025D24B7 9C5E3543340D3589143C020C4E18DEE3F3DA59530806E40EDC66A8BF9DC0B08C 890A359F0EAF2AA2595B616A463EE2DD9E49CBE5978A20B5B0B0BF4C8AF467C8 2D5687A3F7AECE772E4F9F7834934ED509325A11FDE5CD7E1BF42464C6C71B40 7842090E3499C67FD1A1E623B1881406C41CC303E5B33E39AD451195DA862B50 0C28833C639A0BD7482B4F350C907D052CE84CFBA42615768D66596818E63F0E 78D9FB0BA87B2740CACC6B8CA87EF3743777BD74BCE730A7A0C4EB72308B7FC6 66436D172F8CBE9AC3AFCB9A9156C23DE047367862A6F77C88F8E860F855BDAF 274684AFA6B55226FE789E699263CB770183BFF20FF5F6FC2EA525ECA5912861 36EED3E59167E3DCC2E86852F7741DAE620649B47AEA91E381391DCCF42389A2 60FBE186E5261AFF84D2EF65FB201832D3374FA9F4214F6F72F85BA7D0C7E16B ABDB29A020588E46D2D77E3D9D2868706266A88B6027F61C5C25F2653785ABBB 3AFB09ABFBA39F482A7913A338030563BA7C65062A394684FE612BB4E0DBC9A0 59CFFFA0CA4EDE04B29456A4EA4CBF1BCE8CD018D66F989EF6FC3C63E817C31D 79CA7F2CB15C3F53B583512D74DB04B5B812C77F9C005ED62514BB544DB19FE4 F4532BC9F5B6F87BFE6A8E776B49184B630FA426B7DB66A956F6C4B1A4DAB8EA CC8F29AB60355F943179B62FD17186BA210148ED9719D4A6C76BD3FCB3414818 EBEB19C9B16ED1E3241D016F27692315E7BA0BD093ECF27521CC2E02D789B536 E4151D18FB3A76A377EFB75E9128D293AD0E23C72B5B483FDE6F0E28EE1C8577 4E12E0DAAE1389AB289D5CA0DA09BAC694C795ECF17CAA963D54CDEBE7189A58 8F7DCFABA64075FEF45C7132CEB407600BBBE43F3A7404D33EF13A1D1D95A86D 7323ADE49D03DE0CD1D8F39F583A8849BF09859396C0900D1E1BB26347DD4719 3D23AAF91A509796D6DBDB0CA3751D44CAF67172D75FA53F5628673C4C7C501F 94159877838977BA1699E5F4F78CAC3DEC8E48D32BFB59842F443826302DA2B8 CC154C522B9930207F2E226DD015398181DA5497DA4655364DF39EFE671CD47D 7EF052413EB797805096266BADE2BAD26A9FFE54642D534664DB5F9C6C748BCE 61654D5417630E41CE49649A50CB3CB0659773AE7C4973201D782316C5606FCB 41F763F3BFB6E3B2DB2AACE06E17512953425AF6EC6C5E24BF5EE1E61CF396B7 1811F60319BB091F101237CE40AA34C8A7F4F5F1390A46C4BC404BC84ABC103C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMR10 %!PS-AdobeFont-1.0: CMR10 003.002 %%Title: CMR10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMR10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup /UniqueID get 5000793 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR10 def /FontBBox {-40 -250 1009 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR10.) readonly def /FullName (CMR10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 14 /ffi put dup 33 /exclam put dup 34 /quotedblright put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /exclamdown put dup 61 /equal put dup 62 /questiondown put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /quotedblleft put dup 93 /bracketright put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9B8591E5F01442D8 569672CF86B91C3F79C5DDC97C190EE0082814A5B5A2A5E77C790F087E729079 24A5AC880DDED58334DD5E8DC6A0B2BD4F04B17334A74BF8FF5D88B7B678A04A 2255C050CB39A389106B0C672A1912AFA86A49EFD02E61E6509E50EE35E67944 8FC63D91C3D2794B49A0C2993832BC4CDC8F7BD7575AD61BCDF42E2E421AA93E 3FF9E4FAD980256D8B377043A07FC75D6169338028692CCA8CD1FE92FD60AD26 D57B7519B80A8F8DCE9CEE5CDF720AF268D3C14099498A843D76E3B6C0328F24 D36EFE7F5C4E5B5C612786200C8DE3A41EE5F1FFAF4097653CFCDC8F4FD32E0B 03EDB3E413283B9EFB0AC33B055617005BC9B0057FD68C52D1B0E67F0C571685 767F2AA85ADE4E0104A1C777733D5E318A22A9944336E5B98D965E50D31F357A 8B6EA5A0EA98E1B027CE68C2EDB149EDDD04ED74A1B3D206D471A0C11C11449B DE190BBFEBC08C9E1B7513B43DA3134D6B11A2516E6E86B67F68C970A320D05E 94FEC57FB347606DF89989C33482BD09D011C55AA920319E7B26A205D3D0F004 22466F09C0482A164CFB27EF6ED2B040ECCC3DCAF345B5A73676F193D43123B7 72FD6CFC5E37930E61EBD5A6307E4DE70194E6384EC0D79DB6AD86D3B319A31C 8B0589D0FE28241D8ACE280D0530EE99C80723E560BB72AE9D53F4713181F491 344B06D3027BA4E9E94D4305BE1D817197C54C8FF56CD6964165F6448ECC8A8A 64B48B4F0FD69299A137589E2491A283509B21A3A5772F75B7602A9F60AE559B 07A58436D04222C73EAEA72DE9A5A441F88D27C11F4F91255EFE280E91A4ACAC 1E98A4E5E6C57B9AE86FD218C3CD8F24A4104156A80F13821384E529783C52C8 78B94AB3A0096090867ED32E8A30980E737922037F75F062BD83BF4F5929BC51 CC22AEE2DBBAAA001CFFBFF41D258424FAD888FFF1BEAB796A44E3126159E120 7E4025C676CF94888A1971AEF8B6764B3AF4A92D36FAF6FC56FD049710EE3782 BC2CD84FE2473F133BE03C1346B875463F126DCAB15C7A9BCC9A727D23611462 4E8D2BFD2466600285D79518712B8681ABCD69608E6AA9578F7BD771EC36E01A 5A17BC17E375020ECA59B43790ABEB9DF5F4FBBEF807E5699EFEAC563E1ACC5D EFA336E75DE6D8248E9381BB110884FDC89C2F9A41EBBC9A8A1F98E6A41F68BE EE30E25CA148C1EFF42DFF8C214A6537AB11F260B8C329A4947B5FC8DC9C5622 4DF7BF4FBFB00380D47BABB03BC30627AA74103E553F55278F538EDD8C1E64CE 0F1398CA0AB5A86630139B4A7E8FC02804CAFF3830114640AE50D2FDA3B561B5 C63AD7EE3347804CBB40FB1E77A6C89735DD870351C3A1811591AB493251B904 314F65791963C0412377C1D02362C5E9655F1C3D4803CD379A8EF24C48218C2E DF1165840462BF37DDE1B8D5FF09FA2C3B261E2F1A65ECFBE5D4EAD43B52C029 EEB3948CB8A252CBAF545C8FA1C31E920E23A12DD7222CEF2D2A513BD758EA13 DA33BF5FBF1D734653EB83DA2D374A5B9A0CE316F24EE375D6DF6BDA49954C2E DB25A88821193636119D469BA66E5DAA9C92520FD4F84426A4E54273FA469084 7517817A6EE3E21176D333825E88046F50B3CF6938AF9BA79A2F51398239EB91 1A2D07F7FCD948427FF62F40FF95E39FE1A1AA8451411563FD5388472251C155 69BDE9283B41900B21EB1190D06E6B13B7794FED020D2C1BDD205AE77B084BCE EF628249398B496DE85B406FC2E1939EF00DFC84C07E26CF72EC401BAAE756E5 7F6673216E7560D1C2A723CB405EE5CA474A07F61B81F8836482F73DC9516D67 CE0CB770EAD755B6B356198B4B97EBB29C63456953270CCC8D5650C1D006E69D 38DE2DFEAB27DAD50A817F0D645D30AF5B75A7B53CBD3D2B8D87BD0A7E525AF3 22F7ADDFCE31716914C2318260C2E2B4664893921B68C5A93334A361D94A759C 0D7B146D6FD94F0442D672BDA0F6432E18F3C5DFA37ADA378D95B75F413C9ED1 BB5C606A3EC7DFB3F796F59B0478C13FD1900381EFE0BB5242D5B5D34D03AF1D 4BDC93EAF8020E26CA23C8B0E7DDEBBC6762A557067A4CE05A524188A8F02E2F 3625DA38DFCF381727887F5646A3995A8A38A5FB1E5D5EBB395FDD0B7C8E71AD B48EEDB62AB2CE99D121435EFBBFCEEA69AE9ED8238B60CC7288DE33C766CDFE 15B767B4AE2E6CE0965E77272AC9F86023DA620548CFAC85BC751C44218A29C9 849F1C2DCBDFAD895B54E51A569952ED50F82DC8A19F367E7E44643854EFD6B3 FCAEB04E55E4661C82D31E2932611748480EF61FB2FBFB0CFB940BEA81AFCD84 4C6A6332D7A600170E38A8EAFCD4F93DC153C43175434C86BC747348FAC61B76 1FEC9027C1A193E55C80F1F20B5317AA0A05AAA36AE235F6E49F06E570FEE798 84857D7552EA92EF3EFAD52DE39C2F8F43C59E3A957B7B926FC95FC4B60186DF 7F3523EE2AB74E294C8C4BCD8B4975E84849E0FBDA6C0B0F24A636DFA578B122 CF97BC5089E21E9F5298D1C9F30CB8BAFF6A3A11BB4D9A0A5CF2B18D055C44CA 4FD4D8FE1AF3630907DE7E585AA811F9CD11FB2C8FC791851D651009FA5DF20B 3C33FD2FF848A9E3F5652BD294965A332DD3F246C91B0ADA34017FF2451D1394 F9C3C95AAC6EC8062BE98E8914D51DA6A164AD13938693D446044859D03A949D F9AC5DF4A000CDA98BB516D762CB9F6D44B5268FD0C26E88BC4A760C0F75A140 DEBDECA4F511128B7D2805872160C55236F0A0FA7637FF0D4E94AC079CD3C8A7 D03A5A56F26B0438B577C46011A10532FEBCAD14FBD6032E224F45691A726886 56F305231EB2FCDF59C8BBFCB5DBD2D093A0E84D62AC93A2312CA69295E937C4 8DBA1802B85F54B5E7E6D6216A918F911FF705D3B5CF055F1D873B96283A0B53 59344D910CD396D883F6F7836BA65FAB4393A773A8F6BC298069E5BA38210EED 49C9D920F718E3FCE692527DC7CCE6963BF744F2C91BC5952564196D60574E86 87A0FAB21F2DB2BD5A51D7FBD8FC19946D24E5A228462C4772F978E650ADCE3B 8D66B9C21279C531CA1C3A8ECE3420BB65837287A7222CC3673A2A5F8BBFDB60 C719CD073EF9A23675198462C7C87B24CC92D6AEE5C25AC63855CC3281494342 D28F3D2FDE0C183486769A4FD5B0143193D31FCB2C2A14E487BBD96D0BADBB64 D1B56021C363A795BF10E2DB448261C363A54A4AC1182B470C457AA82DF3F5D1 F4B329806141EBD53CAE309319B94133D7EBDC2D0453A905ADD207364371E178 0A95C2686E3B34C4A978BFC0EE968C39ABA00889BC5149162C2B54483D44FD3B 5CFF41F611C7E03B94945F414560E874D7CF27FFD0630890D7D7EA66CBD15448 229059E1C436BB33D69552B5367AB5D53591C4678D0C704DD3EA23F5D9E8A7AC 17D003C19E333E726FFFA2961F33C70F429085F7BFE3E2510F59B78F58B19CB4 01B48E184BAD9020FECCE3AF52048A056981DAEA02AE78197E65855DDB170616 F54278395D9EA50DC83761AE759F9CDEF9E1948E7002414FC05286ED793E6662 3347F2A9AF8917493D7305B92CF93E8E9185F70015F5594084298A6C2F9FD3C0 689F262AC9FEDC9B89577ECDE92F08D3142209FBCE7B5C0A840CC767BCA56C20 4E4E545E2BE4D21C53855CEE4CD0AB35D1A604C0FFFF77DBAE4289752276559F A05FEE65F45ECAF44E95E23FAB6052195C7948AF0B1126482D4E02D72BF8AB03 DE0F1A632F7672AD9DDE70EDC82AA993678A82BEAD0BC2649C4707FD8509810D 364B5C6FE0E10772E95288C622C2F06C634F4DF8C7FD1432BC9310D5F24FEE3F 7AB324863D6DABAA1576E70643CA79EF4D7DF4105093D66CEE0F3B87D2164A7F 26EA05F5C4645B22D3E1BFD2219657712C168FD90DE801FB0F32759E80DEC1E1 43CEEB19FED12D757205043FC98FEC62D6A8D8B97BC083B4A0E985AF7850D6FD 8716B9957C1C35A0675BC53DF672C425C79F43FDABAEE7D63F092CF271C9A9D7 C41F40C4189510987887942E60A412B3EEC84C9A6E1AC7D54D528F5604B72C08 94B7882621A5BF1F325B92FF96B80878CC550D1AE4D8196E41CB1251856609A5 C4D3BD05A922D0D45E039D9450DEF8490A3E924E41434194910BF60BA1B08BE1 B41824345627745541A4F1703E956328F6227D11C74946B38CFB096139979E56 4E723B889B44C6D78673868C89912F8B4F0B4B485F1587A637B630F92E6072D5 7F3B44EA6FD96BBD4FC28A6C1D90805E3BE3E42A7BC9C880762966C55BC04E01 204D083AE976FAE6F37C94F27E68F8C0F28D52B17F6C0FD7C9150701FD78F8CE B8E8DC9260E3974005EB5CA728171F482D765016C94D4ADFE4A42EF42212BC56 7E4EEEE8B0D2A7856CD4E44F55C0BAB762F92CB8D64C17022D4BF3A47C12F5E6 279FC23101FEE93753653CE8CEDC3B75C9CCB29BF1D4554C6120DE8EE750FCBB E38B5D915206974962E320362E59B3F21B3AB1875703191043D03284D4467346 CFF2F98CEB4845B73ED8E003E0DC94251B73E13A9B51A3F1430BCF6A21EB9B7A 65E17FA411F53BE6432F1506232B8159E008FA257F884A4A01AC53BE91754D78 BF14A5B0FBFB9C31BF4908355F8A762052968DF526D118708CCB0B7CB5BEE285 6DAB6CD2E3934178E60BECB11AAB5478623CF6C50C92F8BB5D1A583609028FA7 B8A53B791BDC9EF76A124F3F7641857E4BEA0837CB36176EC9A522EA7F41B8D3 63C37D1145367BD300F17B54522A834BBB74DE12BF9EB26ACE6F24A046D58F89 4D4B7DF74875F1A0C1C9D97BE0849593D7B398EB4B00BEBC8C8D1497B6EF831A A35380FFB7F1AFA4D888AA52C9482E8B1755CC209905F98F40D95B44D4DCBCB6 67423D1BC2F3560FF0A8B4F0CAC352A4EE2C1D946E45AAEC8A6AD40303F3382C DF0756BFA3B1ED64C169E56ED1C760F2FF0E24DC5C9F41306EF8D2628153D30A 5DCB0791126BEFD4947D7EF08301FE015F2B0008DFFCBF9F2D4D859FD43EC7D9 C5BE237E9BF6665B7B1BEBB362F0C0C3A8D86010B9C97FA741C97C2E0513386C 9C26C235B14DD2A58BFDAC7B5F63DB4DA6D5D37D0098175A9071590E1DF66A3D B8173A047C29D7D35557F06132CC920B5460B8AFC11D23D09A4E45D089F5EB51 963FA1A6256E359D485107FD143B2BF21FDE9DA5744BC2615E86C31C89470CF0 D06C6397D9FCCB316EA9989430240759D2C4945D941F159FC02327F34B042BAB B5C3A47C78E8C1A6FBCD396B1A51CC4B020B8AD401841EDABACECDB482D6EC5B 72D2BFEB4556720FADD49D07307C8B22ACB7E310CA4151A85C71EEF70E8D15DE B3B00F26E0E166C14647A65ADA228A3D1C89025BE059306565DB1B1EFC37D358 8C1EB024254AFD049BA977BD4C2C605050E17940A89D0D4C5D963E792320F5DB 3706682E03D25D9E02487247819551465092CC22B6B56E93F3AB528038FEC3F0 668F866707A19B0463BE706EC729D2EE1653AAC7E29BD25BFB3241D4792F5152 ED415B4E7FA92C2EE5A22E27E8B75542C492E56D811C192E95542A6FE0BFE5A5 69273C2ABED4300D491B92D2AECDD278404CB84B1BB1BD7AFEC858215837D118 C0E928BE7E07CFEEB51A6D21375B772B8248C994564014015232A0DA4BEA1754 3274F407FED0837A236371F1A32056240F2015B1E7F4B2CA72C6B58610A66F13 407CFFBA5E0A2893C1F572D50F51286E9133B5A84239C9493B0574E77D281D01 11D00683354A000C9700EAFBC1FD104EA19DFCB87470190E7E2CE26E3A6FD0FF 2620B87B82AC8686B6206B530F17E9348BC7D04B948348802CE53A312443DB87 4DBBA5313A6A2A8DAB8A1CC9A594FF8C299281C0A261C8CB2226B732FBEEDE40 2C6ACC74A1A61379E2E1CD5548CD908268A32FA83D8504C442EA0E183ADBF7FF 9FD09C037AB03516ECCA93FF048235BD11A25DB07F164512A079C5392AC7F889 CE96AE5C8D9580BCAFCC087C35E76EED1A671E87C12E3045E15A687134736DF8 DA984772AFD189D68571A2ED7256F1E204230E41D3D9DD876F938951714A3973 0CA9310489F8E807C1C7A4E51AEA5BC030610A5D7263FF7E0F9FDE3E5E37A362 5B919000BD94D978583B942EB79CF2BEAC33FEBC9A67272EB10865BA8FB75FD7 9D280AB59F91B96C16C982DE848D76D8FA8620DFD7C80B7DEAE7264350D6FB3A EF04794DA3305844A7CF718F6D1A4A3AFF6826173A076A1372ABFC54ED3AC6C2 09C9287FC830556CA694E21CA5342ECA7B10C90AFC4783D841D7B1E34FA3DB7A 2B706F3E21B0FBAB23E7257962FC3BC309CEA2C7239A9D6B44CC96825115ABD2 AF9A2566D2F3382C01569FBDB94C8D664A5DA0F7DC3DD140CA77C743D7BC1420 324ECF9E4780280EB119885E96A6C619CE3C0C8E1E264E2DEB137E5DC8149786 486D65667ECF47B1A1E20E9E6E4FC8323E0BC8E61BDD3BCDFC6575C69C03E31A EFFC290472CBBD049DE3F840AEE37A2486034240F80E75D8A79E0762377DF660 52B12EAA16D678990B11A9BFBC03C1D4FCDA9FD4FFBB3E88352438102F10B7C5 9F04C013B6575B5E948FAB58EA691984A0E54E6B9F3F505FFFEF74D06FA1CDF3 4B8A95904C8A2763AA8AF5B71D00F5DE09DC1CDF87A08B6D181453063E14C12D B7BB3775A6E2A901636273D9EEB833EA8CF20FD83AE899E28DADE10EEEC20BD7 BD93085A4B1AC80AC1AE8280C14767F1A487BD066007A0D050317BD081131A14 6EA0898ED59E46DA7B6254BDCCBC660686E2EDA0E77A705A653733BB5C5497D0 B130359F866CF293FB6EF0C2AC5BAA2DB0DED045E2DED3A2612D078333260359 16CF0CCB272D34767EA069E0F0B0D42327A18529D72E890EDA6195C2688438ED E9ACDBEED41E81CA8EB5E43C2B09CE266EFCA03F2D7FF57F12B06F9E54FCC6A6 546676F6FFC5B8B7D3F0982B6FF0D21D949309F0C0B175CC1D0976F8C55C6AED 6E821C39041E22D91AB30922F2B2EC2746BC7DAB484991542FBC82D87B487507 559AB466F73EE23C2D3194DC5CE4C9AE66D3164613AC5CBB3DB501B64DA7C91B C7ED2EE9027FC0906820B35D4F2CF66C4F9CE4A884B7C07155BCA884ECA5EB3A ABB83F84DB1F5639599DC7D3F51241AB5D95C3BCB7AB1EC90B4BC989F74FB354 04B2D7366A34D335A47B8C00C05CB423482BF6C7970A95545424A08AFF9A035B 7F83F52B65A9799CE76E303B85664B624C65E9CA58184C7BE2BB9D9C86A4DE5A 8165EE3DA2E652B5022EE7893896BABD88931DE1D538F615787645DF5ACBBA0B A8E5B899A37321AA7D4B283AC9234978C2DD81813A1EE5DB6EC170DAC1B6EF02 94892635B498765C07A38D2E9DB0B7581B11056C28278F89B0E60998379C07EB C0EAEDC32AA69B8B836F92A61AFD35688315B2C3F860632FC13E4BDFB63214BC 41CC6859EAB3AC3034449213CAB99FA1D216563419CD6D6CE4E1B56F33E6C654 7AA9DCB5B05FC068DF02AC32408C8010AD004F6CCA9887830927F8CBCD49CDB5 18CAC1EAFF815FF2F6F527F936948201565003022C6C7390B4E3C2B219FB4F76 9F12BD25CA7B3B61D1A2F8DFEE795D04D5428B42FB66E0C254AF7B7A10CEF7FD E5ADA5E217BE24851180E9A1700FBA66C7D2B0D7BFDE4F4EED1D24B821A40947 5620363657F6D048E651A689822CF815E72FC8AE9D835BE31D1DD8B54C9A717F 4DC319B4B59AE073936EA40B070524C7E71D5A7B64436DA107749746B516E29F E3BBCB8F8C473E706670E11E5B221716F315FF097CD1841D0069FA69EA1898FF 9F9EC2518C77806A19730C97F54BEAD604548D553D4A6EDB247853225E24E7E9 89D71F6BC94DB986467E755CCC99069B313F5745B02B4BB608A39F0A0A732B87 7EA2DED68219754BF1FBCA350327572D769C962EF9242132D93A5C8E9725D8D3 AAAEC15ED0F362471AA58488620156F3474FA59CA080EA96FE995D2B3DEEADF3 3141D157481C66507725ACA5953CBBE1ACEE7E3F02C72C6552D15EB3D612730E 61A06A43575568DC3CF3844BABF04CA767E2995196097015E0C4F622C4356B6B F41DBAFD797A4B9D7AC22332C552043EF98913D0D9B50CA6B7CDAF903BC5C04F D20A952BA5CC35B646ACD0A287C956B98C450051AF6AAF79DF37F8954473F8F6 652BF03AE2AE82B99D820CF93F5FC0BA17EBD7AF90313E70594EB5C354023BFA 07912408F1757319C7288E99872B907D5AB583B082EEED8AB079C63E38B07D11 6744856E689A479CB3A8BC081F33CB06755926204981DC0A45B3ACC18F6865BB EE2C50DB43B62E3630FC1D9B1FFB3BFFAA6D0A20C0381ADF48E4D916BEE85BA2 BB40F538F55C11D50F882B73913840B45161262BC8B0012694C3EF26452F9B77 2CD7C7AD6BFEEAFE31C8A721C2D46AA00C10681BA9970D09F1E10DDC250E2AC3 9A160EC8C9654FCEB36AC2B586E978D54744FC8A0E963D8EF6E228ADD22D093B B889C940206F504F14DD921D909BE06EC9BACBC23EB9E9D137FBC983570FFD2E CC5D2EB5D2A4A8604A4AD418B800EDC6B89809E0009760E9470F037FDD15E649 93E9C8FCD9436AF02447C7F5AC380FBE69D1405189E8DBFDACF0E7DAECFA095F E6AE1A2E9ACFC032BA9A5DEDE9DDEE22A88D9A1F1E0FD9BAE2D88FA168386D43 4B93EFF3AD84A9C05A80462BB3A940B2F7311CF7054F501BDD4F1347213C9327 5653B73E9D78866901235C66B0C49CBDE3A1BA3A11991E6B8443117745D96020 38F4A74D9676E4E99291D4420C57ADE4A8D5214D07B14916D83DF15114393048 FBE0DB83223F609ABE120AB877FEF549B6E2389487BB7ECF1979BCB0785DAD1A 2916961A1DA60AB491FC90BCD6578571226B4DFD204E75FF18FB5E72DFE8A028 C66F8576254930567A877DBD22F8372E7BA4F23F9497ED653906F5F67A66A1B2 51957AEB8D443550161075E5523F3D2AFF386E2640B276C3EC5EDAB74AC0DC94 7D975D7F5781A652BD13AA7F97ADDBE68847167997ACDD038E74E930D8248F0C 2CCBC094031C7147BD8D4DD664184695CF8C474845692540FE2B8A72CDF9DB62 BE05E15A05F59D56E5EDBE7C371BE5CB3B276FC7A03B5942057EC3136591A1B9 15E504DC497B663A9DD1729EFD1478C233B9317351D000DC0982F061BFF25A3A 8983E560AE31E321DFB137C77C0AEC704F8DA99024232F26AA6920D58CB17DE3 C1BC8E20988FBC4705E594569BEFC3F6666785B2FFA49367E3CC695F2A1EB846 DEB37E120B0F4C0783C0D54655C143C4F74DA0690C6D08D07ED225F361BC0F86 572D79540730791DCAC15823991FD5DF1AB8F25F84EF40C085B17C9070C59EE6 31DCE45AFA78440BDE4C69A4D954C2006070A2C310179851F2D39B1B5D3EDBAA 289570BE80F25D75116BBDA61F002B832F9EF2C32B53258B15A1174225168B28 EC3324C6EC61E5711811E658A1BA65C8D2D47CEC6071CD88DBCDE9CFD2BC34DF 1ECD2226AD588B50AF2399D171E99D8086DDE33E24640A767F249797B1B742CC F4E95A64E1AF8D88FB128194673CDEFD6A1672DD1D03B6749E729587C0CB7C6D 13BFC785759F35578D611E924CD89FF87DFBC5C93FA7BE150624825F7D137CBB FBFB1238C1A397826B8D1DF0A39EBDABA5F10B37FE8C27568E1C088F279A0E28 020DFD377694024FA154AB5C06EDC3CAAC3CB5A69297E1079F5C2F351D81614C D73ED708907A96F6F8FB0994D3247045E8D41028432E91C7ADB2F22061DD6BBF 5B9EB427971B1D2345F00273D3C40E7E5CBA521064BEDF90AE868789380DC127 C1A0158765DA54953C19A2E022CEF25DD7453272F2B7032D94FFB31DB5C7003E DAC0A5126F4B529BDF92550235270EA6787A4FC1CA67350CB7B552FFB89F111A CB176ED7AE7F92347CD6691BEE8B501930B0020327B371FFA17A8196187D1364 EB31556C24109CC4DF9E4ADEA85D9F8CF7F3725ED8FB8BE1784E12218319FF81 0F9F1DC085A1D1E767B8B0A8A28EB491FD849174B334C07A95206B16E8AF5B41 EB0926BB02ED897315FF9E96C3F7920BC73E5769AC791BD6624673711FB26D09 C83B0872B455F649BE708825C7BA991FB681A7A7C6EF675CA9936EBFC3B9D716 6876FF4ECA2EABD1ED2BB6C04679022D577AD0616D09DDA22195C4DDAE2ABCC6 9C34D3F1829CC39CE35C0622A779D7D816629D181B4473B3DA775D909B05A0FB EBC3637BA97F60349F62319612E284770432D63B1C903E50ABAD11D611E15D13 5E7C59933914DA968E467EB448368363CAF78B3B4FAB0D4D6E8DE5D2DC7EB0A2 484C7191BC0D321376590A4B3F66BE85057ACB94B7122C2587B942C189C8EAA6 59E2FAE89979DC4A1488C4D37BF9F6ECEE74B4C97E87EBBE81C83D74BE65567B 897147205B7C98854899BDB0024646C7E5688D0EBEACFF49D41B268840602CF8 66B59A47FB9AABCDA7CE8C08EBC35CEFE54A57F2F693E46822B22B9CC8A0E122 50DD51F60131BC8969A7E52B0C8783ADBD590AA5BE29A35A588D8C034D8F860F B59E6C2CAB886123919E6939C970D1FBB4CDEB59205FC60B33ED035D6E315495 C2252170A9637AC8D95A5BCEFAA9B540FD2F8AAD8D5078B388D27A6DEC10E752 92EA51550E89FF6276532271E10649FC4877240975AF7277961C6F077AC8B034 CE6C39121B9ACFC6BCDFD9A438C10DB2B8BD50C169AFD69C818410DF17A8898C 89F03C5FE16F44736C7C15FBF8489EDF6E2BA4BA6FB6E2057A8A193850B5C562 3DA087036A275AF573F4AAE1A864A7FC58DCC2F00B5F24401F96EF855732DD7D C86ADDD20D6B46D8E69E958B9B9B14B8D75C4BF0BF90C0C07E471D77C7D30E6C BF0C8089E81DFB3BE95EF7F5470A2501C6831C247034A9F3F0EE5526E98226A5 A37EB5DDC7A03F01C74FA1A72772A2D308CFC6BC4562A34C0FE0BB79A2DC3F72 529A51840828778E04AE9DB90DB883CE55D0BC85B15928408D23437FDA41EE93 515ABB8DD300CD6C99DABBD711F6443FB8190814994064908E4B11E74438E691 432F01EF8CDF5F4425C341CD7E1CF880F99229AB89E1F3C2A7034BD05D83CFC2 C4BDADF07095ADCF88A475AFE999BC600215894686001ADF08CCB343DA0BF7F9 36B049CC836C9758FB9ED3FA4E4999FA5413EEF693312CC83E48B77E53B02B22 244FD5004FFAB44507DFE77A4B16D18406A30531A5F0CF8BDA7DD8DC095AC79D 3D1E712C827516C1A6B493506AA80896FEA179E6AC2EAC2B346A76AF5570DE3E AE951A2D526B1C105215624881E11AB9F1CC61D772930FD330AB8C79E320B141 EEEB844EB92DFB848B2480C5EAACF126187DC786BF45182CD5488E3C4C053482 A25F7DA6404DCE15E7FCAF96E8CAD417C652C16B0FC62A9784F9985B662126CF 97B8EB2E3E6C224D04BAD22B19A6E4A92F0B87F288180C642BDA9DF253BDF562 28F8C0424BFCCC27C5DADC560AFA5C4701C91398605EF946FC808A155D779341 E9E55BE6A17AF80D1A37E2BA54D4C2D3463B820648DF71FCB2E7E8FE43EA25BA 69F691598F7481871C644A32BB54160B6BB10855A61851FEF1E34A2E868BBDAB D12521952D879A2D4EC5F788E46EFB2E4F8AA205A8802558ACC9C2D427E802FF DD048EE483EBD8B95AA1BB44B6BDCB3D86A8CDAA80463BCC001CB369A9ED8B4D 0FD2F2AC342A44198F426C64FECF383AB03CD1129F3AA81F21C287925BF53DB2 42EE35964913D132013F04FC1D88CEA61ED898C571006204AAEB8B857CB544E0 1D0385CC5A5F8FBBB402D1BFC270CB64AC696167685F9119C2718358A59944E5 FA8B3C8F48733359D5E05B7DA8C435A28E0502B2EC9965B506E2CEFCD57659C1 D82C95FF195AE80950D45FA840D36272C1B416EBD9FB9C5A32E9E1806EFC1D99 A530563D113F8BD2435B1B7DFB3532244FA23261C8E39A8F907FFE624B1AED5A A201548A2D29F95E29C1670C4C3A6F5474CBB4102ABD63608A121B7AAA86BFCF EDE7E81CDEC1DBA0B6B4C0BE77B742F66729E4796D517374188D449C867D7B28 D3BC8EE433BD69C55EB49363EFF7591511C808D758C9E86A55097551010C4230 0837F93F3E7EE4D11C6DC3B27ECC2018FDDB9C664B8C617742012A71D6CCBCBD 5ED3C665A977889F923426DCA37D652C3338755F135C333B872398270C65545F 99C9E634D4E7F41D7C255D50496A9FCFAC13492DF755A5A4E18EB9C6F21B2E82 D16E79B41025EB906A1392E4CA7D9B549B594C930E3EA1DCF804353D50277B73 7119F6BF954D1E7C034086D9D0ABB0E1343F742E8BC0904D58D90DA4A1E99E39 BE7E1118787A1272C059ABDC30CF9725C7E77758317B9B9DE5F20BEF25D1CDA4 D0510F06A63566E4EB2AC6CBB9EBE3EBA0C7901A36A94D6AD7EAA5544A1923D8 0EBCF885F400D54B000D43063FE89D2CE63263C3BF8ADA61A8CB29C913D8016C F281ADA1D1077FD50E78AF892C68B624879A8597F0A41F34B777DA7174CB3D7C 7A3B5924C52DB8A3F395400A3B080E5FCF828E0C0013B761D0226EB2B9642779 4F3AC345ADDC3E51E088286DD5DF48BAD53F1E9C3734B81C219EC91017462AD7 40B4CB60702A4959DF6B65296CA9C2086D6B4D2ACB389BC5900C4305D3CAD797 7A09FAB0C4870C8E6F613285A713A005746C49A595948D3CD79461408ED2E422 A9F2CD7DDEDF71DF510F10BE7D59AE43CA100B0588D5C5B3190939AAC4E33242 F66ED1D568C0F77F30F59EB176EDB222DFE6AA02F37B2F668A9D4B7BD1BC1C4A 0AA77C36DC34C69DF1F30C9EEA44AE2E34B6EDDC3CD0C8D39B370A97921FC7E4 16D29B1161BFEE78051A6C198C74F39BA3A0313A1EABFB4208896E4B107206F4 A15D810D4FC8E434FAAF3ABE21AC7C71862734E2062F24A09DE0145E7D101338 DB26219DDCD138C5490EA6EFA678894D2A65986A53FB65D4BED1EF2EC09D42FD 75CE506353494BF07E81764507E20F0DD56D530AAB80D294E64F0534ABBE7AB9 1AB7DB8A6E6CEF68A46FCC60A0C7896EB6135E602FE798C362F4A3148466CC74 4EE7F2654275C4771B8904EEEBCC2C0EDF00FCF17756073A09ABFA792C31C37A C9C62DCFDFD3084508A524C4F1A64173F51524F6A8252A4D8E545F5CCAB02E80 37B0380EEA857EDB7DD9DC1B256129412E936A628A9B0EA9AF81B603FE045441 4D54B03ACF1D9613DC02CCEA16C6214278CAB93C8822496F6B36B95233A97455 FD6B72E1EDE5E7EDDA6CA352DE7AFA79AB3C850B1A7B9B15C951E0B6FC5784C0 6E02CE497726992399F7151E5B2ACC53E63C1CA7AEE576DA5AB610015553C8B6 CBA6558F51CD5F7C9A433ABB0C95BA8A3D07B6195C0B9D8AA2604D8AC45225F0 FF4FA79AFE383E29ACFF6841AE45CB75CE8BFC7E107366EB90BF3DD04F0B85E3 93C1C5D27B0628E39F8376EDB6F6599C4EEA10133D4D90296EC338B5466AEA85 0672FE7CF41AE7F71727D7C1F0679C84ED5EA50C8799143FEB9090CCFA94F29D 6A004919D731D0DE9DB8BD45B3EB53DE34144417D786915E21A636A4B43428C0 D8613B1FCB93909AD6ECD8D13A38BE00353DCACB7F2DFAD339AADF797F33C85A 376B76C13415AE46CE10E5D2C6D27B9EB2020C908E115A8FE6B6131D6CEED0C0 2DF5AC2A6B2BCD4D19F6D700597E3DCBC09383A0F0ED2BC2AF34CE4239BCA460 CE12F7BF71ED2F4CDAAAF886D5D5A39CEABEFF8F6AB3F460AABE941AF86BAAB0 FE7F1AE459746F0E2AD096A85D28EEBB67813015B4508FCB8EE6AE105F2E003A 5AEC3E87839F9BC210FFD3A55AC270E339DC1C5ED4E23263F060236CEA575E07 0FB697D82FDA59D9E6F0A45D5CA84A4F2DD08FC513E834851A7C068B511DD5AD 347B7F3E82A454D26AECB0B2C59FB1492B030D00B86965F8882658A97D91D32D 824C0D088A06FC1FEF6249F3621058D47F835B17B52D59328050DF62DC4B348D 9372155D19DDD68E05948D06832620172BA8392E82738EEDDC0E090448B87713 D8E1F5A34F58422A71C82EA3566C08824368D7DFB08C7F23641191166E26BF7E 43EBC54CDF534D3623FC0DE3D84B42297802A7E2ADFFE140672C644575C35BC0 86D47E91CBF5027AC2D5CFFE395968526B8B6C9E21E5A11DA1F7F4533B40B692 3A64DFD1117817EE0F71D816E8AD7AED5D7A35F3A63F2DE2AD038ED53C5E7236 527517B57DD462C10BD9FE341461C61B6F00A263DE052224A64588B82DD7B032 EE9F84BDD752DB0463605C7AC29AA9F82FB2230C21DB0E099C46D346C9318519 217B261E26E9663C4CB3FB329EF522C36F878497FD3D51588A93BF7D159BCC73 F0654E8D8DC8EE4F06921F63C8C8CF208B999F9F0A88D124D51D9DC5F477D5E1 3B9CB1B47FCDBC6E5E67919DC204AD4827A122F2ECCA21900A626CDB130B36C7 7B1DE00AF950CC6BD1D202871BC2B15E436E6E81656F3515F91FD6FFA9D5D01B B4A84C6CB8BD1EDD728A4B9D07852E1620E099407A696A377D14DB576BBB7E22 D911A5F3C815ECD3C658A43625FEF951B7CF9EDA1A31D2AB7E9A6B2C30338C73 C2266420E17F95441D7F0F9A3A6D4FED74A8119142CE87D5B45D4D0D7294034C 12958B433DBB030F7B3F6AA9C69CCACF2E11B03E63A57AD6E973152E91C807D5 6093867DA27EF8E8275669DC138FD185D632E54B8BACA444F0A1F0482D4512E4 26BBD3E9514936A6C33B69BFA069F22DC3E7729C83BEDAB386C9B1927579FEC5 321D869E925A86273F9AA06931B10838AE33D1DA0C63B25017E9F22BDE449D65 F8CBF9CD2F48D8F71A0FECBF15E9B3F9F3B12C3DAABB1E2FFBADC23D99C28A2E 0B3C18CF82A9088F62AD66F6E0C02AE18A7BBF8F87B69017AF8FAC001683C729 D5B509325FA0517DDD01B57F7DA8F8402ABAE8A4330B5BE3234E5FCC03858ECC 28F48003E9C8CBBDF1C1489D6F3F7E4C01E847350BB8317995AFA912774E2BEC C1CC35C7A4EB2B5409535A82A12B83963DE4E9E0DD73A9A968F24557868F2D3F 35889CCCB7954504DA62AB5A814A132F9C1AE8E319AF5363953D316E43E4698D 58E4B158ACCAFA03CF1478E0579B5A6C09F6B99FDDD487182C29A206A6E7834B AA860C43185A50C20EEB168AEA77D29FCCB31643A5638BE9770112B42F1AD141 AAACEF16DD0645C018824ACCDE6228E99EFDE69F88526248445B017496E0B643 C6AB23C170508E30A0A01128599E35396409352FF10180AB63CE8D454594EF9D 879BB2E5DF9B83C57712AF2F1DACC09BC1EBC049F4EF1C96B1216E2C7BDB8F5C D929133B1F7A11B5FE197D87333D0347B8480F8A7D988371A1016D089DE6CC77 F846851316CBFB5E3476072300BB35995950CB00A54B71D543021D1F792EB071 9EC73ED5B33B415D7CDB60D4A219B282AF1AB7BEBB4546B9E2D3D563250E0BA6 B7C62773DCB0EA7DD3800E0F7C0DB031AE36B76E4162C494CF5002062780D703 4013E126A4533A83C852F3470C6944FEBA18AD546D9735E26A84C8B0E24C6D5B 85B26BA8AC9675939807F453F36D58B4DA385795A9BCA869EEDCA5BACA359698 F38CB1688A882DD6307EB5915BF5D013D3FCEB17BD5500D189A4D964780062A7 7406057E06100C8D5518316AC7A1B295726B65E960724072CC3A3DA3D41CF74C E1D0E744C866691C56DE01481368ADB4BD7AA9379DD21626CE05BBD0F83A3981 6DE15FD55D4303BC0EB3D5EA4FAD98DAA1A08C9262A6070F34DED9565834E17A 424FF151AE030EEDD3F122243805CF13F8ECA5C58B0C0A53E7514EA09DDB39AF C5DD0BF1D8B77BB189E10FFE4794589EAB4DE6021F0504FAE084A608DC8A00C2 E04D2D10BF00A362F41D16123C11F483570EE44EFF771BF530544921B6EAF5EE DB274F53F0B7DBFC5A52DEEA958250EBA553583102507D8D01E35B86A21744A1 BDD34B0135F0B2034244AAB4061FCEBEFDE9AE0E65E12AD6E49C8BEBFCCE28E8 918AF3B269EA09DC093D21B576DEE3132DBDFE285AEAA6964BD451010DBA91EA B28A99292E61375AA7980F681C750E467A0CD5A0D5D77D61C43D7EA08B96906E 755CE61A0956B7ECF2DFC7DB956C794ADF4A633D9A25779B2BA00FFFC14C15BA 7EDEFD7C176E2C76B49DDA472F77433003D18FAF1F95F0525C241E770CBDFF50 E34917E592D760D9BD5DB7B5240C17BFFFFA257E96DDA88FB205049FA006C3DC 676A9C4F985B435F00061075CA21034772696CC7D5EF546BAB2374429463CB8A 950E041EBB32287DE8026BFC0A1073E782B20F016372C0FC308746FEE438F9AF 97D74E83BD64065F546E872976C2BF2FBE1470D9B908567BC96E7D0E9F4AE814 DD1185ACB778B122368C85463C4974DAF2538CAC84FA0907F2E8455469EBEE59 F75B660BAC703815C25E7FA5DF50A35A7075E019BCBEB5A8B43329D5494F371D 3DEDACE54DB076C881896FC6E5B11B16C418B41C92092D567F1D1672ED846D15 3CF3C82A923423AA372F694465282F395EE9663EB412C6A7F39399054AA8204B 12E3DEE4A06A52F7FAE582ECE7B3DC0A4D0808B497ECBC21B4186BAAD7064515 EA4ECD8733EE0B20456E7B4B1FEAE49A291032463FBAC0EDEC8D26C8340D1711 F58E2A333D986CB0332F7E0CDABC01B327394AEBFCB0B0EF335541DBF0EB94CE 4F1B78DD2E4FA94A4BBC749008A871ECC0F45F114ADC911CC9E8DF67293E9087 8E23DBE188E7646F46F43BEB5FB779DF867C9A406A1D8E6CD8B6A828046D478A AB3C7CBFA6C8DC133DBCCE48B57FD462BB80C3E90F1E3BEBCB3C5AC835F13554 F080F7625224BB73585D50B63D8FDE633A6504608760D111F446CFA00D88F778 168F6AC31DE77B40AD1CB590120D53EF551F8F28B76CE11EBF49755F5755F019 E3F198177A106F25AF3E23DC8614627D8D696603D0019787046479ECB4598E7C 16BAAB5E9BB445674A0D9D9931D0A3F57F0B5EE618DF90B087A77EAA880FFAEB 6BD9BC4CA1B72A63D8E684054E5F5524E1B443011146AC6A86D79DFA50B8537F FFA1AB67E5122A0C6EEA5C418CB84F3C03D88CE39C6181422A4F2371E117F0F7 E213BA799EA44E051090C0DCC84E59CEE3D6546923A6DA991A368A18937D8285 14A85727DE95242BEB1C05E8273EAE74F573F745398AECCB2EA9792CBBFB9F79 768C6F235187C775B03FBE0D98087A5F740FE7270DFA76C70350D1B46E56992D 69FD0335E66DE06C5AF6531E5D841C465D718DD8AC144A789C1BF8D5244699A2 C7A1D6D42EB4D1BD879BE67EEC5B7093F59410005D91299E249404EEBD333BD5 CAF6111BEA76518418185635E85F267E3E6E1F2CE3F79FA15338045F9D1DECE7 0CDE2BB5DE09E826474FEC9BA85FCF21EAF02BC45BAB1435319556A795ADDE90 6055969E398B7605161A95D3DEA8EAC7D3536B483B7E435EBDB9632C600691C6 6774EE9447D90B509CDD74A983E1CB40E93F4C005FFDBF09C30EFECEC626FC4F 180CA47DA972FC0619DFC6A90D5AD2D8838F9D7E350B1DA554D8825F6A1DD6C4 4FF9D2589E4B36D49E1B67F41965F19741963189D7BA19E1888B0FADFB2E4471 74B08D5B533E46AB4B685E7A3930EA0A95D145DA21F184DE4A210980129D01CF 00AE2010BAB49921D9C50024374C124645AB26FC9132FA795E719F6CB0E37BB2 22FB8F4EB52E44CD27FDFC5FC464A1598912CDF85D1EAD58F0D72BAB0096D71B 3D7A5E1790FEF3B8E94039890907A689A66B1696B91E0FCCD087254AE16BED75 88B45F51DFB8A69E341C123C2E0E44F6A73C1F730F440370E650B2F47F1787A4 8413326179D08051EE4F5F091557D9592474ED9FACD9617B413C9443F6DBDC37 8970333D68C7090EAFE5B95D8D248A8458B1AAE5ECA028EA5D6DBD52D96102C0 3AD177251FEBBBCE6AA12178CACE7F4860EED94DD44761C555C7BE32A36E5141 07F6774584463A93FF85A984EB3744A2028F68A917178B9879880EABFAEBCD66 158902062C32CDCD97CAF39F957327D3AC5B18DAA723C7A816160C1A74C2CD4D 57CDD31B91F237D9AE56F675682EB3C03FE8804840346CC7AE23FE9EF829F6F1 647D33AA0E46931AD37BDC5B7861FF68C1CB2FF5B0F76353986EE815A935A344 D15BE8596F9935E47288F8F9FD7DD657EC61E602ED292961BDFAC55344417887 3D4D78E311E808621E1414E7AB8BE3AC0E1FE8FB45DB51E6557E949526D9F8D8 72A9ACFBC4D93BC3DFA1F82AB82DBBDAB9CA667D2A599130D2BD16253621931E 349D897BCAA28FFD12D823E2B9C5A3AF74438F0AB304E0BDFF636412EC50956D DDEFC5D31D3495FBBF26AE2AD8B5CB34D1717713835A62134B422BBB62A4D824 112E2923C7B43CA2CB0F50D4EE8A5367E6E2A8D22B5A6C35646E7E585DFD9669 F854C2EE58DA16B66EE91DC660F151C76940486722DB450B59ED0B2155C824B9 EC9EF520C4F3F69F041C7D00EEF293D33017A4C3669973CF2EAF18FD24F9E916 A934E4AFB565D273207090FD24F33AD9006D8ECC5C7C62D7CA6F3AEEC111EF9D 51CEB7761207D081E905B2C7259DE0DD10AE42C3BA73C70C746037C2271C886B 6FED288934C10E851AA4601E943AB565FE35829FEA3B21286580BD3806867982 D19A8970D8D1F433730A30F29A5697605F8A120A04A3E033924E7A4736ECB8DF E9F065FAF3B992CA917751F797B713AD8ADB28A4C5918199B7B94B7F72B17C37 E53BC7E0F1ACE3742822C6C962BFCC87C922EE3DC1F329F19BD1D8ABB57EF234 64A48C4ECE50A4A2D70047E05FC922EBB2F00F13443463074AF62A67654E9EF6 0224F588D71CE52D1FBF470BAFD45A81F3F35AD4085E77F0DB0B26482218EB8E FD5CF6A58A5D5C14F1E77AC0B0E8C77109DC42C2A02AC2C205174A056D40CB83 87218CD94E5D61F02C01AD7727D2B30FEEC310C124C2D906AC12A5B133F8F756 B0BDEF206D3585B71236BB5DB70DA9255B678B6FDD5E091D8A2E89E988E7690D AD92F8D4E24FB333ED97D744920F6EB444A75B6369A06A5A94F1DBB7A6310A36 F5BFC5E05128ED66294C20CB206BCB9EF5A4782129E55D1E6EBAEBD9840E09E1 633EF56FEF608F407538827A38452E0803D81C91FB63FAB8F5C0596D7DCAE8F3 15F13FF4EB95B84967A174F12733F3DB78D1431D551AFB7AD510D91FEF3FBC4A 1C76BC788ECE89C2BC644456689BABFAF9395D5768BE231D8BF9CF25D5544D45 7F1FA8A90C5EB635F0AF07D005D5C7EAFAC1F091F2BF355B84C143A8AF284D2E 438E9BDDE97716D1756A64FF6DADB68FAA8F4A9DF2D10A5F3DCC7EA24483B41C 062E80C7219695AFD10B694C457D2663271E544CD1CC0C98A8AF2A708DBD9ADD 3F26ED9DB69920DC044270174BC9590025D2F79E51D8B4A5AA089D297C7089DA 8A80553F052F9726E7F0FB30EEC18F89F1C4A70296146119510877E10F81FC60 BEC90742E6A43DB7F18912DE5125AD8CB5CA5FA925D4C034DB9DE74B686B0049 C6CB1EF9F20B2923AB3CFDC298EAD2AEC3D447A79F7724E90D790288769E02EC C3CEA6C1DBC9E82B4673D21F7CC59CEB5124B4C9735D42DBC7E84374AE813BBD 076B932F91E4C429280977D3333D4BA5EDF1E6884749898877231D5AF951E91F C9A978BBF4B727A71B84639777F9FEE83C400C6DF6B0771B32CCA2C9A7AC4DDC A023DF4362BAE745A31DE4A827CDBD450BB2141BB2A963153C8F5B6F6F750C12 2B5AF9A808918FF97F726355FDD822471FFD3DF1CEE92183CB6754D669509312 BF9B48F1F9725050D5117F4F2A398784C30EBA27202835EB30769F8161F871A2 A339FDDBA12E49F8D3BE82FAC01F1A052E2320B072FA9C67AF6586573D223A2E F10156C9E6B85FC076178A11175E9B0D29B63ABE2A19C7B06B4FD617AFC7CCF9 880C41B44CDB50C6D2C46A68203228382AA9FB1BB02F2AC33D89ADDE049A2986 A472EA0526B2A26C67FE9A1FE5D0BA2452CA8FF31B9F47281BC1B8FC37926437 86ED0093473E3F9930C36F774D364AA58037B275434400D98C4A598FB59E36E8 A614936BD1ADD894E42E2461C348B445B13B0F6C41A7D6B16A72F1A4D6672EBE EB4768A7C853F65124EAEC33385B289E4B740D45A16B7CB37AC3BAB926068D6F 5044B7EACE2A6D2EC912B33DEF840AB7AD7D37F4919469B325E05B33927735DD C8B3429239BEC3BF407DAB638111D8A4DD13C66060E1FEC412469E817AF0AE58 A82D9E203D354A1574B37B5499245903346FFD2D6B192E2F20934752A7BCB2D3 DAEF9103170F46E1DD8D7FA6C8957ACFFAE9AA1CF3B66CB369C8E4378C777769 003F2C86F0FEFEAFCD8D7779349EE3D73DCFEFDC3EADD57B4A3B291F8C16AF1C 9ACDC2F7E4FC35C5C4C1148B40FE0E15AD22D7D816B06B2DB9A6FCBAE33E0C72 7BF4088EC59FAC1488B6627227A44CD09539361CCC7BAC0FE3B5EC6266B8370B 9ADA0A6A47C4843FBB386C8A2CA6829F3CEEA2494A7276B336099D5398BA7FB3 7422163E2B9638BAD2E09118803D1979A9A62296A2D3EE7B2B9391CBB2966A2E 5CFD5BB8F283E4F584C6050BC43B35FE60F62A582DF2ED39C802EAA0DA02CBB0 5F580B003B64E33BE279CC760A59F7C0DA3029B0BF6EB1BFAFA8C0D2EFBEF207 03E60E40E9759604448980CDCA69F533C1B9D843AC49786819B8B1BD0507E683 BAAEBEC2E0EC805DF8721D6782C0DCE1AC5B0EF2735254AE1329972F0B9CA609 67EE7AE6EAB3CE4C76FC0F292E0A6285296B4358E31114790A7ED8F0A1A63DE9 261DD7DD623E52C75659ACB2EC3936690B638E452D2FDC6902BBEA6247D6F97E B55B130CB5C8B7F8F9B38EBFA9BA98BB9BBB31639D057002B8B5F5CE399E65A3 7B27DFB8FF190813FB6808C7BDF186AEDC629B877D86AC5B4F30270E34A996E0 94F8C45F7FC70C692030330F9DE0AF8D8B49E33C5B9E6DB53BD808A7590038C0 480C2542300CBA463409FABE1BD3C04DB990F20BEC2B61612EA100D983E87348 47449976704A0FCED0A544860187F078CC71E2E6ABBC276D7951979D5B2E7A9F D04A3E9C29A9AB227242F4EEED9DCE9112D1DFC51CE6CF8E5C5B28E323A4C1F6 2D203DFD0193E6163219507E55560F26EE8D03ACCAC7C5A31EC0C13473DDA456 E1B85458CBF01596327DE2DBE73061C8AF1345BD8DEFBF728A2FF532962B4006 12D4DA4E4304389E363F03BF43D43F4DB7AE8844D3BFDD64AB0D8D71FD70C321 6CE0FB4CC781A33C4CFFE22EC37CD113FC10731AD08E1D645C31FB43385CD4F3 3406E22D4320AE407BD6F0CB8CE2C7E5CF031D0DF0E5F7A928B399BD1398EA72 1C3D36FDDB497D942EEDBCDB438241C7BEE219F685EFB714C2C5E91FF444C273 7B6FCE88FF148458373DE20E2D6EB0894542005273AAA61DF7CDB25D638B1741 F48BF951623760998C4B2CE7C7204DEB037153F1363D729484ED98CE83C4E18D FB4D1251B607B306A3AE60672185575690A66F2F2F5802D813030499CA6E5EC3 EEF54C4625875B7292A9E1D0215DFCCBE83293F709A8C8B823EC7E9578027554 45B537A491A8FF07C15D9325D2BE3E972E8042FE4808EC9547A5E7B2BC6887DB F748472D61647155CFFDDAEBE99E45117AD82A11AB731EA398C027FE3B22B6DA 0D60F3F0372E4F8A137FBFE2AEFF6DAB49224A0733BC5AC88E51AC0F9E162CD8 F82CA7F8DE08AC67E999E2C7EF833B0F58A6F24C5D81E3D759E6C14DEFA6A2B9 793E248B3C9F02E311C42E1D99F4A86934135A2A388E3606429A247A7AAD84AB B2733C2F5E6A8BD1186B4C8B8B13603295507C74D1B16887998D0783A07744CA D769E90877555B1E9A52131D8E361DAE2977CF3CAC6917FF78863FA8D3C8B0A3 4F45C667F46759D70296BC2683C007D66F9C33F6C2C0D5833D29EF6E80D8D449 C3831B5474CADDEA0033DB80B531B8D98C3F06B198E922D844A72459027AC955 A2CBF10100E28E48F7CA4CF4E8A481D5603E3E756E28DC06D43D5C3F341F736D 62CF28F31F63CCB7CB0E8FFDD87A9F1AD2031EA1CAE763E41A3B9A7D08A57C50 91F2C36BBE448EC1FE91E574BAC1C128C2ADECC1C28FD934EA982A2CBFE18E30 070B83E72FC5C7F592A27901F11CF1592EA00F77FA68CD35822AA6E06842AD13 871B1C4ECF96FB5A2CCF62F04DAB8A95A35D176230A903EDE7C46F8DB92B3C30 E92DC73F1C65F9CD8DBBB42E22BE75E27AB51A4522F2755A902AAF29B39FD7DD FF296038CBA5719CB2B7620E847E088DD62EA351155124A3071B5BB2DB0CC215 AA08A81A5FA664913F0D0DFB12F53DCBC795B3F138EA9DAEBBEA085F7EE7CB30 6F25563F1A02B245F6D34B944B1252E3749286EB83D53A2796D2B2D059AE8C29 623D354563B863A657FE09CEA1E527B149E8627209AF424A89298B463CE9D658 CFBC77849E8FF63151BB62BB3E35050844A2C19282731D45356F298AB72322D9 35CE7F0A0D261D80CAE36CB1B35992300BB23403CF677C87BDB4A0D7FDD5EBBF D585A85D90208F9FA2F464BB6720F55735FFCF149B9EBA39C0BA64E4EA140E5E 11242E96ABBB3A9949E7B455044DE3476FECA4CF36223D177F0FC2F9E55B279B A7D94B299E5D55DD792AF710D518A16B8043BECB57D11586AB99694929EE7C9D C63EA85ECF73C70D0C31D381AE841A7074DC1622C573D17E673CDC5EE21279A0 65F1FD64376AA067A6A4C70456BFD4578348583AA4B478168AD253815BB32AC7 3F3FF5667B0744F897CD2D945D185207D26C4CF35449D20AA602EA406A785704 B04CE304935DDCAA6391AA3910B62E6796E4EE96B74676D5DF1ADF7FB03AB5F0 2A17F79FB544C8D7C940AA3BD6E8900F1E35E57274250275D84864FC5FB4AA3B B6FB8E7E8F6F399629A4782B16BFCA397609BCE9F55AA1B31F109C0F5A8C3810 1C3D492647F5C03194CDDEC3BA526B261373503BE767E935514A861D54517555 714C8095809B14DEF9A2F800138531AB5472D3A4661E915E231BC6D8BE0463E6 7B1A414495E8AEA435913BE0A1B6345D6D63B877957F2A54754C2088E3211346 8BB4C63C39018CE4C87BD848AC4DAF11A15011FAE7DF1A817D2868E6766689E4 E6A9B1F20EF89643221AE7E5D042E3DE2986C3B3835DF0838805FE663E82E734 EB0BBCF6A422BC08F305F2DC5AB8D76F61CA9ABD7655C583FD61322F1FB69E5C FA4462443D7BE0B7F783488CB88D374217F62007E13D621299D5974174E7E318 B63A7CE169EE74D06B48D2108B6B35B46146D9C23944E4C2D047784FADE2C089 F6EE999E0360FCFD88B09D28601A175FE92021A4A595D773C0542C5A6B478BC6 DB3C56AFDF2987126C66951A135CB715543501309518080774B7268C632B1731 3AF603FA8EE308D9E279A8C5647C1CAA7CC6A538460D805E7D2187C9A88DE760 5B4DD8B60AA812934DDDBEC2F6E59E7A82E2DABA553976286056E5A3BCAFB813 EFDB84C0010777BDB517CB45E78626ED818D225A88CD14B8F5AA4E22598343CA 661D20AA69578F3196EFEA87F9504AF02ACA71067397F3D5421F9F7B6CB32D0B 1EC45A237119DBCE537555D2367DA7A20DF23F168A3CC8715348961AAE880C6F B2B7BFDD862EF4FD149B457AE624E4E5046BD86145C690F5BE6E4DD3C751E3FD 6A0483585724ACCACD957E7C4716DB8FDDD40670A79711FB8E228B3C52C3AAF1 06FFCF358BA81088AA3778B4431BE87E72F72A21CEB70F6CBBBE4DE5BA7F4D91 2FF8C30F97A7E3B7831EAB0D1E08A8D4A9E2B5744402D426A57BA54064504ADE 5EE649AF5EA1BABDDA96B4D2C23333EAB6CB20DC8147A4D567B974DF00E53376 0B4000462EBA329B19A9CDE9521DDB9753C13707BB5AD045C01D26D6706C7A02 316281260345756E793AD78E80AA41DBB03ED78CC796469AC209CCDD31A6D24C 2CC41B3B7287591ABE3C1D6778CD14B4115889F0FE1C7DF7616E588B3342A080 42FF84470BF34723442E307A516E2392F897CBB76C79A3FB90868AFFE2921116 A7B1FF6974722C259C8B3B637854D3A444EE6032173F606903AC6BB850CE5D8C E2682001A3CD14D545A4B5A648C890BCB32458FEC0D85D273217FADF6666C8A3 B8BB3F6165335C2E8AF0DF728A879E31B15AE539A11C3DD78779607B5D03ABCE 37A25656DE8B90C9249A8E00EB6DEF64E8788C3CCE86EF8CACD0912666AA64F7 CD06405C9EE624EE8A56AA0B61700A223893DB17D3B868E664674A59D1C6033C 5BEA4BE55DD3F9BEC4F347FEA35AA14F9347B0F470E0319EBC8C7EEE2782B9CB 48E1EED48E7FACAD54B488ACE76022BCCA0F281EF9D65EFEEC2BEDED578908F5 2D02D6A8ECF2F22EB5349FC10CC67D51F185251498CC608E41A7909F0C52FCEB F091B6353449F630AB4C5BCAE6B55BC34C02A2E44225EC36D016D0E1D26EFB3B C026F28C3C1FE1E45A7616F0FD6CA94FF7ACBB452C34B0CA13FB40605B2646F4 9A8056ED9E31FF5443F773E01DB1B06D766EA0FB3602E67FD51107E4D3549EE0 075A3FF38CBE775B94018C82CBD58B3FF00B343C955F1209E88E66B0E08E5FE5 738D42A886FA5E6DE916ED4515043C4180499099EC7FAAEB3105B1E1FE65C8FF D95AF78C1A8CCE2BB08605E676895A7C384A80EF069F455BD9B69E72B7BFDF29 616BD3C66E1CC8862D0D535C386BCA9182C22E547DE059FC4B7103C520CB68F7 56624B014ED363599676EA043D2BE99B1E3A7777FC3EBACCE6EEA603618A170E 4D7A324C7BDEE3312A1811A049476910D5E6BB5B1246CA2EA664A1F4FB456E5C BE116BC3DF7D50F418BB818D2FA37B726F77AE8FAA7D8FEBBF684C344985C79F 5E77534681A44E7B71A959265DEFDDECCB5153733845EFEF36D5C484D82CA93F DCBF2E3ADE33C14BF242DD4146542B929086945D12993ED66A1D8A930D98343D 3A85C596B0D70124A54A7A09C80D3A63A56B1C61C25AF80C24634FAA6751CD90 4FC84A684884330AFB7E73F31F7DF6F56C7857392C4FE209D3F98CE63313ACF6 F07E45B73DC8CE2D75B18F62847E6CB49545BED416BDF9204D06DE3FFAEFF8DC F95FF3081EB4B3004B58DF44CC00CFED32D5609352EB3474ED11487DBD29CA3A CC2D6A6CBF81B09E5D6420A6797C336B118825A59CA55A1C877B2357A105CA7A CD6291C23E39BE2B7170FC0E491D4428C100D89C82345114A390A184DC90B0E7 C5FB15F95BE43E92DD7350ACAC42D42FF1674E2B7DE3DC24895C6F987ED85FF0 4D1FEA29D8120C3D645AE5B769B816E9A33B241D5A5C833BA9552807C5D83F57 D8B01D9620A4918265C978128CF2E949A4D118FFD55BEEC3DB30047555EBA131 E1F4E3D9C7AD4F53548076422ECCCAFBC1C58E0D71780484BEF55648DDC76DE6 F21F3E4A69666A88460700E4D1EB98AEA218B5B86E93B5D9C3F0B960364F4EAC CB95520C1C22C06FCDDC228E5000AA54FFB852823D2261AA9B3FBBC0EAE38328 5D436A623276AF425FF50F54DD6C51E8B8A19E38C5E7DA31E4FF531529C5FA9B B393D16807B759901BB19EEB3C174C65D412E71B2F44552BC4CCCD0AE645CCB1 07BBF43CDEF5D2A4BEDB485D940F3BA15D3D6E039AC7B4E2FE1BDDDBB101146F 9C29B5096E928FF3131162B6286814051F6BE3BB620559524CA9BBD54F2DEA39 DE945621914F84467B96B3528813EA5450BC834F818EEEFD8346A3C3EEA3AE92 590CFB69DE004D8E1A9C4719C3BAF54FF1D047B1C80773CF4F7BEDA178F3DDA2 FFD1F0B19234B0610ADDF0E3679D311871D54A89542A2A423EC6179D4EA77B57 3C4CB75904256F19A8D09D5C3E33AFFCF279EC48CA2DFEF4D0D38243095E0F91 75E45029497D92F1C31EF868C464CCB2D56C524D8FA1801DA0B23629A643A11F 292918B7565D930DF437F42B77F8089B8F8AE3262438965C3C117CA8D7C1DD42 3C5B50A803EA40F0CAAA05D08F8D10C706E360F2D54899DE872B73F829B94853 3EFDF0821943947494C9CC0D93AC9CBEBD8567C867FD80CE73589C5BB67E22DF EC66E5ED0BA9543CDB9404B4E03BB7C989097668BD081480678EA5DA7F275E92 23D3274A2F7D031F810AEDE3FB24352505A7E8AF3DB7E22D4DF34FCBFFD7DADE 8C677AFCB5830B617925B3726AF0DA17F0C04316A21B361CB9357546615E9958 E71A3B65652DC5129B61D0FAE2EA9380A4E632763C4EA5C6647446C77AE36B7B E5329054BE12790C09381593430328AA70E04DE8AE33F7311EEDBEE76928A35B F3ACFC67752CAA93B814B412D4B0C5FD2AE1B133BAE3D84D44D12B638D8E0B30 D8AF93DDE5F4B7A4D4A3190E714C8EDBACC740D32E4084278940F195041F076E 5608FD8C647874A56B6980DB67F2C41420875C23990DA228FB9330EBAE096F92 0D4BC27135BEB5579D6940F6EAF1957601BE9A11D40023D7AE8CF94D5FF9428B 6B265A63F4937D69907393EE09BDDEECE757DE74E08FBEA44DAA45D4D0D7EBFA 35A8A6D626C3192B7711279322AC3A7294E5083F0AE1DEB77B52CDFAD7917E37 4DB9F206B763EF8673365505FBAAAF00EA2E5F13205BA97BF580E5C9D31C6A34 00FCBE067E2A77C1E53E5E75A10667341A6B6738BB67A5D7ECCC0772CD1F9012 825E55A4E2F1E5D2B1E04039A1C1853F1D3E337A477C0BC578EE5D90D414F1C0 66D1616935BF02749D4619774651E769E9CF694D71B0ACC5EACCB2BF4113FDA5 B2B5F72F4568CF140FB03040A45701BB16F608B9145CF5B923AAC1D63BE49953 F068BCC25AC7919FAC49DAC681F56358AD27DFD337B41C48D7D0F2A339D2C872 C6AC7CD65374F495FC75F487F4D55475E686CF2F992E10F163D772A89DACBCEB 2EE2256D61BD6730D8C54DE0CECDD32647CD282D8DF96C46A3A52BC64F5F200C 92C09C543EDEA94B9141F25829394FFFD9949ACA7C392104154F948FC7BDF309 E1A648D9D547BB55B856D5519239638BA26F529B8FE4C3A4516BC922C9806587 1D95F47905DDEC00E1D51DE90B0CA187C2EF5616C3601E8A5CB70CC44A3D9317 A63623B6D0C8C6364F4A9AA4DC4765B06407E28CAB2FB368ADCE9D6F53FD33A2 6628065322ECC10BB3E43CEE447695DA3A65DF1F7F3F9C238DD59F8E494AAE69 7E93FE96DF910A7272ABEFBC9CDD88F9670D638726A8E21DEC7203B1D79DAFD0 19A93BCEB3AD60722779400E5EF564C51D0B8933B8011621BDE258D315791C1C B70C506A40A4350894D76B82F5B61CA873D616F385AD04E43486A73FC4ACA173 C2C2ACD61275E5A7CCCCFF029ECC47DA6A5BCDC33EFFFD3929B13A7AB95B4BD9 900C6E2E5D1B79BC77C6032D3F161705B07CF102372D534EBDA199598AFB6900 A9E60D191C320EA67E9B639DD5DE27C8D5F3EA3083CF55329F522FB82839F080 5749D72BE907173152F99F5D6E49748CD05281A20F649A17CA44AFDA39CD812D F176558844EF288BFEA39075372CC0041FE4BA125E9541C215AA3FFB225623CA 4996C145C4970FAE966769C4194E89A218FCE9B117460BAFEFE7F36131A73359 5854060789E6B204BA33D2E4C8B006DFC1F0088E4038031C3ACDB933B6FFB256 0AD582DB1537E41D0A1389EB6406B1E02CA8815AE96FB2219218A4741D6AC935 49BD86F5FBF1D5889688946D3E07555D67D3C4FE9F6A0825A8F16AD35697F07B 6CDA477934086C44FFC45402C9C4CDFBC21E737EE05E00D9A5D82203580A3DE8 F64C892632A6BB7D97CEAD41AD558E79218FB52181B064DEA990117F4C47A788 4B2EE05F12D49844839A5276044AAD7119B26B5439882144C229FED99C95C5F6 8E6713E7B52C7470359AB5BD89C0494AA2C2A7D4F13D8E8CD15C0DC433A5E892 838CB42695C8F9505F6C638B1D39A8EA48A9508030286A8B54B1C6DDD3C63AF5 484A2FE3EB3C33C20FB5C337EAB9D21FE34CD80A03FFF1CF56AEF65416FE7E54 A1F79947A8EDB771AEA90A0B548B9C73E38BAD47F016E2BDFC595DB4FF0B92A4 8E9CB1F11B1EEE03CBF6AC4E19C143506866CC07CB8E601B345BF60BCC09F701 A9AFA2E561A31D34EABB9A0A256B40C554879197D5206244ECF05E001ABE6573 A73C963C3D95225B093D614093C13A512EE5CC76E278D6C33AAFCFF10A4A7B02 C22BAAE4ABA3727516215436379E47BB875CD8674E2036FC0A727ABD48EF38BB 63462F70265E5F037214A9FBE2CCB624F973D09F443F38FF378A4A914F84ECFB 27D88F2C195D45CFCC94FF5F573FB23B97F4916EEC2EE48E81F987F95032DA85 FD867E49DC7F2BCAED085E2F7A98CBF24A2BCCE5BB71328527D15DEAC49C8A7D DFE0A8E40185FAF3B56C85DF90FF7D94B6EDD52EA47B47E992B6080A0C0D1583 36B651ED68AFC992A5D2AD2784F11F60BACE112A6DD4F23825851AFEC8286147 E56B09E8C6B2FAFF37928FDDD6F21513F9267A1644CC7470E7C339586A2D3645 6D24921A61AA6ACDE55B427C2C6449EC7C9A9AE204496E4BB951E244E9075E3F 4D5D9F3405924A391F1A182D04B30E5C9F836D20FCAA01476C20D6BC79EA3A19 63B9D6772D390A8D7020FDD4CBB7AF6559008F3A641EC47C8C3AE320FCC10908 A8DBA0796A6471339B95DF5CCC87B7AB65B1DACBA17BB43F65C34E87748212DD 6876FB2D44E6CA59B2DAC949ED962C4EA7EA640D7226547FF293DCE32E8F7A7B FA776D17F376AEA3DFA9F6CA60B90E9AE40480BEFBFE4D5EB1A9ECFD37837C75 74641DFAFF3A19BFE5CE53F27030C109F6DC853CE280807B99E888637F66AFCC 65053A8F007620A5384AE07C1B071A5BB05436A1606A914298F973883FF8AD21 97D531AE9D9E825BC5046DB8E75D0DE5C0ECAD582CC6CF03152EFB7AE4AF0B37 9EAFB60E6CCFBB396649B0561221ED130BAFD1659B7864FE3D13FE4CD4F0DD5D 052DC85A500806A0F86760FD20F4546E026FAAE6C104AEF2F42CAE1DA3EBEABD D557979350CB188E6B08D0AF9184DE85852C2BC19AC8DF103A74CBBC149B0489 B79A158F1A00E3D6A683E145C200A05808A7366C4023193CBA7305AB87D132C4 D216D904AC3DBD682D66F5C5CB272CB96086A5A6E2E6E31D10EFEDFAAC035ED7 33BB27AFB00E11AB3BC80051BBC3429DE12A2F0421BE5D36325B453D8DCC0D76 33BF39D39AADE018877574831FA0EE9114E0BE13242B5D1D37E8E0D9847629ED DFD33475FBC1416108E80932F53358EF7499F16A1BC23A84E99E95709274E8C0 DAA5B09E7F8D86A5E67D80513B19348C2718FD61DD12AE18DE4BD7050B73C3CD 901B299187E5D034F2DE65C1CFDBEEFC3FF9A43B693745E577F23CBF16FD6954 F8E6EDBB6F34C48183E28302B112C99395762E2CA39FC922B40F0A35F5111F53 A5E99B418B1C79B434DBF7241993B9EEEF8DC018E388F3C94872C3A4E962C980 C6830E9E96817730031EABD390ED320746CBE9771E7FA6A081484D7B6BA9D126 4A3CBCB8DF50946EF8A5D1EDB0F4C7075E73F7BFDBE729BF11F086E559F881A9 FA00620187A734BC055C90DF4257A4C2260FDD5F3240CAB8CE54270B7895D683 8B074348A3C249A1A417CA6A0BD8BC4A80F2BD48BC5EB62124BDDA4D572DE578 3CCB40DFDF0F49C50245834E4FFB0684D833938709AFC225F327309125949CBC 1D16564AE909C159EC53E615183797D6DB59C319007D5E362DD5B10902CFC86E 9DA92D5EFC1C4AE0035B4358BF003B6DE617029AC2290A76D591C107C5E6AB41 9751C82ECEEE79B0AA4191EC82A090AD9105C6A83E2A67FD2001BDFC2ABCAFA5 65BAA032895B5C0C9177E8AA04FF029D406CD93D7885E90C42D92955BB04ED95 F1E28F1C4B401300281F9AEEAB96F7F8B9FDA9DAF2D0B770F7DC166C85E64019 C93CA67FCB8FB1BE048B64AA6385BFE2EEE133B886AD15713CA4ECCC179152E1 B3B3E138C88CBB02603E35975FFB022CB03F23BE7208B439A3BDA34FA0EA1F24 54B049CBF27826FC966F569FA31CCC86EF835CF24324FB80A9ADC1FCD37BA450 EA44361A16E6DC1E249632D8B23E06267D9AB048A8E75BE05E7BD66A81D0B3EC 9200E9E47AFAAAFF3FF6E86128AB57AF6411791487A7E808BE1F245B9B96AD5E 3C9DF731E24D5CB30AC2C89B0AD3E256AE9BC5B2CE0385E1852556EA004B281D D10082ABA1A5659065AF65D9AC4B3A89FC38D9E00CF56D7303A9A49DEC34ACF0 D82A70E5D531DDD156E4A1BFAFEED96872F51BC820FE11B6A0DADE7C11DB6E09 258B457E821A5E975463D9AF69A47DF33A783310110D3344303FC715FFD495F3 715672B5146B4491E453F622152E79B7C89B0E2B6ADD3A86B7F6FD8B35F855D4 097E0717D903ABDA7A45A80F3ED847C8BEB637C348F670C1C78421D321BD63F4 BB3917E09F4940F62CDA612B9925DD4F3DE389214E2E6622A039B12C03E1CFA8 6327F6B2E17F6874422629677DCD558CA803102FB527FE08C3AECC32C7341949 C85BC49FCE9679549A4C512BF8131E89A6D723E935302CDE839D8ABBD40FB42B CC76A5FB6DD96F3F9BBE556A384B9BC90D38C500F4BA577C3C230FCBD0EAF513 F6A7365682358DCABAF97A9BE23F89665C5F6A73A7F7E46A3C4DD179AE564EDC 261BD255933AA52F0EC29DF0A6D9CFDB728981054C2EB522D3D83607B46771C5 ED2E642BE240B15EB821F4E4D4B606670253A72E63479DBF4C5514CAB52B8C39 0ADE9AD697112DF5805851350C45D65E40245DD70C079F17C746FFC46824CD4C 97ADEB4D7307570EFC44BF0BD89083497442F8830221A96B6B5711FD63BF7D49 8DADCB82E3AA9A07D057B13B56B8F1E85375CAB473C52E4B28A8BDB7E8CFE5E2 B4CCCB37DB473B89F217794733C377863580C8B40AAD4B0F885C95F4411DE634 C63EF8213DED0B9BE65CF4BB8A2D28013B99B731800E95A9B2FD5C3F2B46439B 6214E3402FF055B0AF704ACDC6C89DC4BD82FBDE5A73821F23AD619A83C1E295 427F85AE522B3A70277FBDCCE3280BF9262F8A4180EBD0A5979124260E04CBF2 AD858DDA2FE7D88301250BE8DB25E59CE84B8CA16AD3B4194DCB72E81241A7A3 DB9900DB3531971B5CE88AD94458726A803F2BAC4E19FB8E20966CC3F75AA8C0 375265C3B0DA9A78531D4BB582ECDB5F5AD0B9D189E02FB9EA561137C95E8876 6DD0C82BAA5830E5F24593577FC00BAF210FD4F58445118A7DB834DFD4BFE69C 3409F89FF32D7801775BF4E5C8A09066108455158AF639C66FA3EDF4CA0E5B73 2EC160C60DF679A3799CF94793A3B7FEC8E85A2B39CCE51FB7668D99E9B7227F 4CA0A50F86B5B967B464FF0C8CB7ACDAEF3889720A6E7364ECDBD0C44C591B55 AAE5C4C2F2C8169452CD64BD2BB65C137CA225DCBFD7A0D392624323D17FFCAE 1277CEACDB50B82C231B3B73BDB08C2FF328FD504977562F41901ACE1ACE41FA 72386C5D20BB643D9B7EC3B35E1F523DEA28987AB444FF130B2464867C9B4191 9562EFC07BA27E74AD8A952BE8B36ED60A7386846C94004BB3EEA02B69FFEF9D 0A3CDA1EF50461DC3B041E5E358888B8EE620C5FD8D3B80DD48375A3FEA039E2 24118677B2D3F66BE505D5B7C6105B283696E9BFEA31F59BB4EA6E1BF44D74B1 6D829C31F9A6EF52490EE906D200574965DA01B88377BC9FEBC6D02B76C30250 23E6E484CAF803DAD212F6763E6C3A7EC2D7A1E35D0C234E571D1EA7ED29B527 647CCBBBBEA5DCF178038A588340AD803A571D70D2145A9A1A3F05CD03831C4F 7FC840EE7E43C875B66435133FD1AD2A651EC44A9DCA955EC77ADD91C9820B8A F325E1B39C585B66A65AA174ECEC994AC71EBE522EABF8C76CE8E310C4C1A037 E56530F68EF3A08A402FAADB4AC5018C897B0446664DF426A0F8F42E1AE16AA0 10A1DA307932D9B3AF9DFAD44EF097FBBDBA2C44BC0A9F73E643D9E501067E05 9CF71D670DA1903B36A2A3702511DD2DFF3FB30B9C74741BFE4F04896603B8CB 4D0F4564613DD8C3D5416A8569DA9A563E566FACE73069CABBF3503029E12736 7422CACC3A8899D438DA21764155BE9D434CA8B18EF4517870CDDE8941DBE737 1AD1BD6ED62D7247102FEE7D58F8E273655AC1A9A4A7259E22F58E2BC3174FED BE8281CD054B619816187AFC0981B8434E8D1A62109AF7903F8FE5ED306582BB 32A439C2D8D9126B0EB143F02B970BBB2ABAE6984484F64DDF79789665C05A38 A6D3AB22E6C2264174FF0A607804B1ADC7755768DE8BD9A0E9DB243CF85DB5E1 BDEB37385FEF70EED662A7C72874D85E57BF596BE8028E6F35F1468E5C76E306 38665BD39CB12DDBF2CC779E6295BFBC784F491B8C62524F0DAF245C5E6581C2 10566939421E9E1EECAACC80C3D3654467926BD04A9657BF5D77F0FAE31B4201 32BF29E244FD8B44C0008D4ACB695CB6B6569C4F0999D9D9A291133FFB096F90 C7E5EFD91B9751C62596ABC6640B4F042FC83388DD096A0DA61C15F46FD36A71 79DD95C436E85F861F4866453589329352A5A75B589391A3BEDED04B4AE32435 8D6A5EAE4F67D7F6F4911316114469D79AD9E730ED40831105F19593F44D8599 19F7396D59FD8D30796241B41B482A343F1DB4D07DA0F935E9903A47062F701D 5AF7A1357BB8AE3CEB3FDE02C48DC63C1301B6B65A5BBE5C03DFB9A948FF4723 51657A479AD4DF66117DA9101C85AB27DFFD85903D72318F97D296E478AB6530 42EBFA3046ACF7CF3A2147379A2FA451582A49D8B71432B277E7AB4BB0575335 A33E3D5062B12274346D1DE15465327251A242CC2D8A77F3A525D606ECB3BA3C B1286C8ABADDE0F436625B2A1747AC3DDA87492F61FC45C21EF1C3FC60D8DBA6 DFFB5B9A45C50192973820FF63926AD7B7998180DD825F9D1B345DC39B58F56A 51CED5A69BE3191CD51BB4BD01F58E01D30133B4053BB151038FD90CF168090D 3900B42D7486F516FF46339955325265C0D5C45650E3BFB3B2D32782F149A5B0 38152F13F32ECFC68D0A0D9957BB36FF6BF06420BC3359E351A3F437EB2C58BF F85DCE93D853001ACDCEA6DE5514CF0776E64D6F1668A6D6359CF7FDDE2218F2 CAA8FCD74E74C7DCF5919912428F7AB777F6A1BA00C9E6FCBCE1B2B2DCBA4CDE D53443AE41B6F93674D4CC91DA0E40A6CF3AECC82D6E18D89612161B5BC0B415 8856452080435A73B97CAA25DAFB9B50DDED4CA49BAD6376D46AB68A56D0ECE4 5A53276251CD261B5EE00CAE37EA3E7C5BE9C6382399D4FB56D88F0BBF39A1DE B7DE9464D4AB5543455048B50AC970C827AABB85931E0782ED578F5C8D2F1C10 5B6314500C22370314EFBCE5B32880B8F96F5EDC538FC51490FF7E1CCAF72A19 E3FB992B02287204B83148440911B20B33C48810C94555542661920DD1E48E8F 0B128BE3FC378296BC09F8CCF45128E25237DFA2588072812CD45F65E84D6BF3 7824E95D07236F2B9E620C3E918A210DFA654B61218B4D73F8A977D4591216F6 774CAA4157591807F8BC29369D014AB9BB552185AB477011AA707C0619C566BF 6F0F7BF8D87A989B4C405EADE2B166B2A0EA5A3D0961E38A0811CE3958BC6C47 EA193492B3C988F63F6CAA8AAE39889623BA541C09EC420B3ED863126CFD9915 9F7195C0122DC0388EC27B6B6B731DD236B1EB68363B580FF068E561E4987B2F 37A873DB5D0EFFB7D41C16E4DE5DE62366BD568943DE1A68599E887075C95C33 3434AE78288B90B92F03A8080FAD87DAADEED67A16C7ED99A082D5436077E550 8B118B18CB6C654A152BC342ADF90B4683EC1A5987F4FE6F773CA51585B83EE5 A8C47C1E57551D0A827EF5E3242DB558B96CA0C0312782276B2BFA9988EF1B9B 7FF7F1A34594BEDE4BC27906061B299F4121A0DF6EF839A988B5006EDBD3673E 7BCF8D9506C61E749A0F4082007C2673B3A1F7D10F62DDD2F7547446D8D14467 96CD210D42BED4AA33233B10B5A727C07ECDCD2D92162881EAECB37AB7665683 BF024A46A686DCB2BCCD28CD3E4BE66706B9B7D287410CFC0E61802E8D9E3AFD 443AD79EC1AAC4A2AB1D1E96110C67F7FA95673440BA0F1184B76C0F29E03F9C 4D57C53F23892AAE7B017437DD3641E097CA75F991C16EBF16C1EF62DE5CE4AB 57F8B4CE5CEEB7E89DD0E1B1F079F3136EA8B4FDFF7FD2C43B2A1CB099B06535 7615E919884475C3F5F150C23FC7F84A5E86C6A230906D429D725482145E8A36 CD98B491AB15CFD994D480F411BC4119B291D6DF152B5E43464B9A9FFD81108E EB15AC532B923DC8B16CD2C9016445144AC2F41C3583D19D3ED38B50D89D703D 2CA83714A4DF1468F73475D92E5D5876BF37D67E8AAFEFB2120016A46A408315 F381B802A1DF551E2BE528D58172DE923C1F789EEB17A079850BFD0D95AC62B4 070899976473876C3D96BAC49306D858EEE3EDD34DD2B99FEF0EC830A9007D62 9B283F1103647472AABBA8AE7182D5C2DF390EF79B87CB789EEB6D5BA013273A CC94B562DA88A2BB4BB9BD46017BBB8C1EB1608A6E76B01DEFC40734E35C84AC 95FF9B90D6D5DD28461C0399FF4C2A8DAC7F179D4815FA42C53DC7E39ED54953 B9D3FDB68059981E4423277666056BE2FD8311F5B70C24787629B9F9466C783C 63CD96DE244B59F41917F8C53ADE5F1756B2547367FD76FC0E98B0C7801BDA5F FA1D7AA550D5A72AAD535402482B38F8E8E5EE50643A95CBFC146E8B12ED1A08 5F07461E03A45C1BDEEF9B010EBA7A9D68F745ACD93B33290683E4A1279047B4 9806355D6683319DB86E4E1518FCF8F38F0DBC37DCE2C4788C665BD30940874C 075A9B52448CC474490BA9B93420D0285F68DA9EA4FB1E3FC04FB99A6EC8BED2 08EB495911FBA7935E2A8769021BA56C62AA03C6DAFB6B6BF21FD140F1C468CF 60459A7E76A3FDD90A4FED60020B635A91A497F0D9AF1782CBFA923A75D0EACB C7134FB2ABEAABE2B12492069253B7827EF821C631F8FFF152DB464C3B289857 4F2ADFBA72DDACF1B23DD4EB3E437DA8C07DF42FD26E9286A985B468D4DD937F 3AB82CB0E7FD2C15C7A18E3D7CFE370D0EE4D2A0A575052D0D0EEAE44C2F14EA DD1488641D9E03084E22871DDC46711E7DCEAE5A0EF5CC0B70AC0D8E9ED1223D 5E0F01A91D11BFC039629B99FC2D7E9D934CBED2E4549416481F538683A73A1B 6DC0EA2DFF64691F69BFC2AD6FE742B1E55CBF58B3A15AFDED5DFFC20A72A532 FA0F6B6CDFCCEF72689B46CC595CB26F70DFB18158396DC485C5456C1758CC16 89590E191514729A441A4C756C4C1E3F2C709D1CDE88594E0423791B3B2CD13B 5BA235C4D615ECCB46670764D6B64BE57D9DD6D8DAEC77B1C787961138208DEE F8FFD35B3EB0ABFADB456BAACA834CC207B8259BE97A969E7F7ADDD62F056E62 597029FE5FC5F2B8BBB48C838AD9182C556504CAC2C368D598E25680D3A00F51 0EDBAFA60ADD08FE561AC14003B9CE8270855757AA6771A206A3F77E31B05420 0C90A4B1C99E73486C1EAB2FF496755EAA51C70AE02E602FDF209344376DEF5A 916F3913B12D3A0A8E92EB749EA89DB6BE24463910F07AD61832B4FB5E93A68E 0B1BAF8FB029AC1C702456DED94114BA5BE42D1D789523BB3A52EAF236851C0B 853E4E03C588361BD2109024ABEF62BD5DB65601A4649648DE8B90C748732356 A23AA02F1983A34A6975537706F5471357A42298576D7F6973C161BD4A7EFEEE 06213D5ED10444236C428B80350B46160DF9FEA41D04BF1177C9BA7D227890BD 0E371B30AFC5DD7DEE929EF07CA044A8E71F3EC11A7762DEA36D6D771C73F581 928AEC8C3628F254075159496B33F38AD3D0959B08F66B25BE9AEB828B9DA08F B4C7B87A609DB89A77BCED886BC3160593AC3C4461500B65B2F71CD533BF12B3 9FB764ED9C19E5677790B51231801BC689C33A4557CC647D8A1880DEE5B4032B D28ACB76B8FA6522B37BB6160CB0B23ECD79A7003BD83B27112E3A219ED9B99D EE66CB39ADC84DA9CE87D81DCFF2480BBDD812E3E6C5232ED771247369EDF53A C8E23D85F2F400DD864DBC1488AB3821273D63B8D416716A9F2A17B701503C4E A753420C20FABB60D4980891998BD1470E21C11F0535191844C82CAB54E58C8C C6237BD47833523A55CD9DD44AD6E6954DED4877E465AE6455882D3CF76B54D6 1E5B00 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.0: CMR12 003.002 %%Title: CMR12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (), with Reserved Font Name CMR12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR12 known{/CMR12 findfont dup/UniqueID known{dup /UniqueID get 5000794 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR12 def /FontBBox {-34 -251 988 750 }readonly def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR12.) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 48 /zero put dup 50 /two put dup 51 /three put dup 52 /four put dup 74 /J put dup 86 /V put dup 101 /e put dup 105 /i put dup 108 /l put dup 110 /n put dup 111 /o put dup 114 /r put dup 115 /s put dup 117 /u put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9C535A5E57376651 F6823308463DC4E0339C78699AC82C769542FD3B410E236AF8AF68CF124D9224 FD6EE92A38075CAAF82447C7AF41EF96F3ADF62F76FB425BEDE4C4124E7B1E0B 8BF254D91912D3A99557F5427907A56514C5A3EB961B94112077FE9417B70DA0 B2E1C1FA3E1D6F01D11F640CF848E45BE3E205258E64FE36AFBD4DF4E93F6B1A 966C8E7FBE2CC8FF43C1F67BF6C361678B5E90F4BA524FE8A4CAD6AB28183E6E CA6C9636E884845105595A2E40CDBE8D4807A81AF4DB77B31873FEB221BCADD4 2C4669459704CB58A7BC230FC59F867EEADE660E49AEEDEEB042BA9A7DD8193E 56C3A36A1F639F7EA512EE4BC6992F52C2FC82A890EFDA730105B0AF7B819295 EE00B48F64C2B5BCB275B1DD62F289CDAD4AD9B7EF057684642FA6FA6322C277 E779CAC36D78F7779CB6DE12638B3C65B70C6B5F8A8C6421A379719B8DD44973 5F52856A4A29B2ED37F2B1FBE6EF4B79B7C0CD6395C756A00FACD763C235914F 847D1D99831023CE1FD89EFEC83AA7E313131C0C197248605EF5BA773D0A4000 72F607551A8EA6F0FF19441ACA179177D1FF7B423FEBDF58B0C19CAE3C10EEF6 3538D8FC4762B77C5AA023A8186C40D0365A4487DC3564265B3DF908572DEAA2 57E29EC669DD72974F806EFF5ECAFA9ADF1F9D2A63087FB7BBD100F0F81C6FFB B1EA1C9DD46548AEDD147EE64B1B4894972DAE1DC3E8569D6A3CEF9F9E46DEB7 547E10BB2959D374A33E47C58F1B20419920AB485F166062FCCC08EB5CC9AC88 F388F0C0155027B727729488E44CCABB7064A1432E179189C4627453C5231535 47D1F2B8BA43069696830CBB6E5F9A135CF22D3D1FE490A3A63C088EA32FF444 24A2427BBA63033DFE2E06DF8CE67949B6AB02F26335A376B57376814D2A7DE7 64A4347577EBE9A6E33DD2FC214A09C6D889C8FFBF1D567032548851B8F97204 49E215CC7D222F593E1EF1439ED60AD922D41E0E9EFB5CA48F2FEFF75AC5FEE7 FB6676D8B8D4DB6885FBE8B61B586313E4DAFB09D94CEDC0507E93000104F3DD F83865A2C6F6A7DA8562BF86F5DB233CC9B53391273A1462E40876A8AC2B098A DBADD5A160DEAC061F86A5FCCAB495EF8A9D121AF07928EAFD56F618E4EAEA97 CF89A3AFD406FC9DE1E9769C1E1EB83BB883786BC075EB5DA2692CD59C4DD7C1 7FD2FF9B18AC740A390C1DB38670DEB18C67721A1DCD502FE7368F47DB4281D5 459B3F020595FA3B10544AAE9EF786A0645FB7C9BB29D091E1432CD878A05918 1665643005BFD9A4B0FFD347ADC84CE22D6F9AD4EDC05E8C7179DCB360AB57D1 6ABCD200A4B4AD56825DC345984D9A3DE11CDA5E9EC1E5006EE4181E4EFE0846 67D8C27BEE8F84A1E01947E945BBE988702DEB2240C4BED952E433E5305484E5 71965D3DE95C4115FF78CE9EC18E323C599727C8B93CDFBCD1CCA780DB8C81ED C4B5E596E1603624308972FFAE9A57B0EDB51FDDB6E23EDE2946F61BEB241345 2A192D8CAD53E823D687F9C64A70A4B4B703291FA6317C051DC6A44BCCE0288E 3839D726A8F2E39BFF429865E95C726E808E02CD06F36C1CC9AC77999F8E28BF CE9D74B699CA982479E9D0DD98EAB24D29C981EF0349721D6819549A39413801 F80182D567EE316E2F0AB208068E15693E4C399A381BF9BBA625E597E6E109B8 16F3A84C8EC92F2ADE288821092A421A8D3B907048FE947230810F0777EE2542 29A3485223FEA079B359034F70464DAD2F0E420271A4E0CCF57A0ABBC20AB327 0CA71B292126D395E0D083B19BEC6B48A9DE2BF470C3D01A8C3F52075BD4BE02 A0C518355814478202FD4762EC542F8E7B9B1F7824F0554660CEB83E35635E1E DF0D03C94C903ECB36B4948ED98B6324E0094EB1DF70863142D4ED3A932D7346 39D69F8F044B6084482D7748C27328AFD24A3A70B99D1F7D32CB984488672254 28B6A9E9DCA2C9FF6A1B311D72413404B3CE5428BDB7FF3C36357D7975184F56 FA6B32AD54C37D0AF7576663AB1397B80D4E998F0B4C4F6D90B483029EF2EDA9 D4C4204C1546EFF3100629453EAE01918D09FE104E626ABA38646F17B6A94CE8 116BC7A8D9C319434CA5B830859B4164DFADF1D7C3ECA5C78D8DEA930EA4AC3F 59DBBF3148C91A2E807FB934E3439D4F67C6DBBA9972854E6E3688E1E0A34B74 482217CFE031CD7B5DFEF727C3EF8DAEEEDA08F4C90289E62FB2AF2357EB2E45 4BC547980FD479101FFEEE477AAC6268DD659E8DD9E244676FD3C6909713B71A 323B211E571BE711D103FA23B5B9AF077D84E2D20FEE805E81D20C03501F0F17 C3B081946CD0FD577F00E50B76CC37CFA97A61B89C25DD43911B28857284BEBB 5BEC61FFE3A14C64BC5425A7A82326617F6F1FA4FEAE56071C9F559F91568179 46369B394A5CE96FB7420FF8AB7C61CB83492FA5AE4A4B0799578594C9EA67E1 E54498AA5CD6ABA34AD3417F04F5D8D664A7EB39D41E2D17643CAEBBCCD9C38C C5C9541641A09335EFBCE0D276A54253EFD68141807A66F1DFEB4BEA5889FFA3 4D20BD52012206A9F8D3E0F6AFC03FDBBDF3E51506EC6336E249CEFB571AB84C BDF8E471E3795C04E38A5306BA6D450D72E50910D1AC385BB06CCD4B8E433A32 5A4B7FACC976BB31FCAA1E62DB2C4FE06DDDE7367930E336B49F47DAD91C8735 9A35D80CA2E117E86B52E41E9278046ED923454989E48610ACB3B1663F197117 52659A9D7BFA561C7ACE0771794FC778675F83C5EDCB132AF124C7E6540A140B E0A268836C73A3C746DC964E482E63C56C0D396515283970FBFF182F9F684FE2 655FD8F5D057D22246DDC3FD11B77552DB4D90ADBAB77BBB1FB1592129DE0AEC F822D7D36E52BCDABBD560B403A5C56C5E1BE789C3AC049318C7FAC5E5861E42 FD66C3C0F46361078D7E036281682BCE9BBF77983C93ECBBEBA9B359769CA442 87FCA1B98F4EEC4935CC93B08AAADDF355C99816453587310F08C50B9BA3D107 5388A1F3AED2AE32BEFADF0285DA90436D1D7EA85D7B9B6DF2AC4B778CFADFF6 6EEE54D1A1C5DEE3CCA7EFF57A7C2931933CEED90CA26DAAB45E4388EC4DC366 B9E88518D6CF094861D2A59282044CC06E63EFB390A6DF4BA5EAC7CE39E1EE03 3D84099F5BE96612789AF3EDED07266EF10A0FC23EA1EA97040B6BAA63138B1A A9CB8F5DED781260962D7618EDB200C3ED976033E8967A8CC676E9C11F74BE34 343A7ECE7EE97E8F76F7E95517A6D6163527406EF5A669535CB2BF4031F29046 BB2D0FFFB47A576F5EAB1D00A582965C56F28C00B3BB7BE2CC8D8391F789070D 775EB775437F0CD53DA840BB3575104B63E4B0BF14E3F14B320EDEF65FD4CAF5 8596DA491BBCF3153DED3B718F833D106432DF8DB8B8E6B34D5308C9010A5DD0 7E0E53260BB84BAB3EA748E8D72F75901604F80F4416920D69B4B983DCDB72C5 E9928F01A4A85954FD74578AE336C782CDF81D1EB7EBCEBFBAE7ED8AB4862584 397928F502D65139CCD582CF0723C5262EE54B9D2B8C39614652A8A90E1C3B65 7D26B99DA298FE4B9A7E98848F619C9BB4FF9FD215B72F99506F06355B332689 37D80AFD9F9ACD8172CDC51FCD3A759ACA0F7D4EBB07840840EE42C2D5B8B257 2C6DB3A7657B75F2F0B9730A20112745703E2D0FE709436CA6A5F36F59E64D9E 37C0A23D6D289E1AC1DA273872F5FC5C3DA2B127F078A4D7AB3FD7E124455817 DDC796D54EF26A1FBFD539D3A21B86DD4477DA49213259ABB3FF241424F2BE5F 89151E02FF87E0BEE26E85C0E518D8BE7CC9214B8E9A9EA1DBB49C6C212CCF08 90C0F23E9858947EE344062EBD9C574979087439975EAD4E85CD7BFAD3C91CF1 EFF577843AF1427D06CB2F3BB519ED1591974218C43F0D2038665F9E2E3960B7 FE68CD3CB2DB6B36C7997C6B21EC11CF1DE049541001FFF26D14C255E3AE862C 5A5701292FD2FB3D04523D6E2F3547923BB117718DFB6E6520F0D0B5450C695B 8C9242CC8671B7284CB2E1E9EB097A3DB1B4D5E8EEB93B4DC7E38C0A10474665 54DDCBAF079B92EA494F6FA75A84C5AAFE280284D0823D7C22249A21044BB0E6 4062074ECD17B62E03EDF4945A294BFEFB51F5FD870D9D7230FC91B83C1D85A8 86CDDF326FC90E04362145D6E8630C50594484FB829DA18F5C078F2EE67D2F2B 08DFF39AE2E8C9741FA989AE494C7166F122D2C5F71B97C973B7CE8500E9F87E D59C30F2E99CC4D34713DAB680598F41955FBDC26A14CF1E73D6BD6B9AAC8D3B B998F2D0D647356CD236DEAD6561389ED3A6746221B0CF15D6648412B35A6B54 6A0EF5BBB34AA376D9BAF025BFC650C1B74333CE85413D0EBB2F4D082A26A5BC 3C0A25D2B12CB159F140E00E262F1CFECCB2C802FF94CD34DA0CE9B4B3830FB1 DA85B9B670D5169928990A2E9CC869891CA2FFAD9774E6B92549644DAA5FE00C A5BE4F5FF91A0B6D2FD8F96121D766391EC4ED3E73DADD476B7DAE1A50AFCD98 DB7E27E44D30416088D9BC07D4661D9ECEC0806830ABF14CE55AA3CA2DF66E8E 748B8ED46466F1EEB072AC0674FE6FED231E0DDA59ED7C42BC05EF00E176050A C4834D893DE42474EA20DB1E25059E84BD137EF65A02CC295B0FFDE4CDE95879 0FE88BDF2519ABAE7F8CC3E6386ED35E04A14F1E3861922645E3A3F43B48A5AA 1999A5EFE192515FCC625C829FF5A7B337AA422F5E920545F9BB269C869A821D 6C4C26DD2AE746EF0F0B4C1E7E9871ADB5270E1CA9BE28225F7A0370D4C52422 E25263EE101C4EC1C7811B05AD42F364844A56BB91EE72FC8ED53CC6954D2BD6 F945D739BE4C61E36143CE890FC0CBF2F610018D678ECF7CEAB18FF5A0E48F76 FDE2463D40A99380D679B3B76D39C664F4992D23E5988B0D1AF33DFB04894016 E852EFD1EFFE586153C0F31ADBDBDE3F73FB49C5EE64D0D02E1504248FAFAC3D 903FD44679BB09C30288139B41B1E90A10139CA3172677250B16535A1F3E5E4B 6F4264DE58896E66051FC677030A121C5A285C47B6129CB5A3998830CE070D21 2F093FC1B44089F603A21F45F60960F134A47226874C737EF6C085634B0A4A66 139420501351F737A73F39D960EC38420BE46E5B09D298E7C16B8E32F01507D4 0141FC52DA1DE718D634AD9C8B00E46EEEF84356759324D2B9A3473C5DA38DE9 E30182B87F91B6A7F7BACF29A93B44C879CCDEDB063F9D2E51E0F1FC9F018FE1 2433D85AF24B55DE3A61C4D0A2DA4FDE933F5F6FDF17E9FA9932BFC46E2D71F6 585EEF5B2E4E89E797A24B799D7F064DD1A817A53677FC9EB8CC3E7F93FE50E8 D50E3191052943FD6C98B573BDD1F6D70349E1F8011599E3F8FDF1D6E80A710E 51E434E85801617C6FD8ACCF1B77B4BFCCDD35CB4C0367F4EB4D8D9DE8284D5E B4F43E2F8320C2C5A9AE90ECBA7E65D377E91DB69FEF27069235366AD3E126C3 A73CE97F4C90BA00D206FA012C327FD69EE59AF4470A315B1799CDC0539BF90E 512C8FC3BEFE4D1B01D969EA9E3FEF976CD6E0FA4C9ECEC955B265CFD58AB8E5 F7371E479279EE14B689269205C5B506940606CF3E24A1E7EFF3CA96ED30AD6D E243DE57690C3D69A401AB3315FA49E4BF4ACD4DD1CA39272533E82EFDD508E5 1C2CD286CCC5DE1202C7C7F654521750632EB637F918667E2233A43DF75239EB F28F3129EB5DEE2FC5BFC331FF709B0FE9B327CBBCE98BCA2C861C6547E50407 1218CEBE6EB5F9BABA4F2E11BCC6FB553A544A567B459E06375102C69F8018DF BA6A227CFB13E2D74E6A521E01B74F2963E9A0A1C9FD87A88EE6356E3BFABF55 BABC751D2BF85E6712E8EF57914920775906662E4BA68FFA21AD422D34E15578 43CA0568B431101A1194F8AB1EF25E886BFCDFC10F4A5EBD9530816548BC298E AE4A0B6B52B8B59C644C409B4191B6F4203F52314F2675F02AEB65A72C66E92A 2AC703E15D8D381522C0AC30C165B822A9B8D18CAECC094EDE020756018DCF51 D0701B507519C4270B70D8CE94B436F640C15872F9B5B77892AA3D110E4D6A65 8F0815C61A5127BA25815378683F46E69E54A391A8675977E7DF9C2D4E6FA991 9F029E50CC2F266B31EE9F9F24452D5838905F330CB7E416B8AF836C5AC26AB8 BE2ECC6EA4BDAA08C30995709E225C21D35DB6369167602CBFA8DB2697635925 969002CD1BEE745DA2E56C17EF3F0C05E3847147F86963C37A221C8827195A8A 3D38993E4939AC915BFD9A212F5FF3F826F742B952018986F9FBDDB69C3AC65A 845F7F33C55D4BE60A1817EBBCA7E1538E8087E1BD5C083A320D52953BE65F31 E8339C612A510B59CE48D2EF7061560C4AD258E7DC59694493E3AC878246F37D 6DE89253EBC8830C6B209E818213C4AC4CF1F391AD91D57BE76FB0E2924A1407 E4A949C905E44F54EAED6419F13D59942C8079336A172D4758BEB5D3E786FB93 3CBE4FD2EB53E4E1DAC34E821EB30FD44BC6CB4298242C38F848FC23AEDC9733 52BE6F32E31E25F18301370F8936810B0566B664B042C7AE0D78ACF0A87E5BF6 F9B66E358168B2CEA30DCD940074F3ADB793CDB136161FE2522905E87B8E463F 95D4DAB7E14A3DF7BCCE8141C5A08FCFA2BCE9F2D1B05A7642E75877EB840149 AAB007CD239AE47AD115929427717F219B0A8907F0EC79ADE1B901DAEE87A2F8 39361DAB43DFFF69650F601B24061A9353CFD619FF9626F63275FD09A5B13BB4 8B3379EC4D147C41197E8387FC04DA7BE409524CEF74EA91DC066808A7FD0EF3 957A44E2503EDA67B1C61827479486134E922E560A673BF314D601C66003CD07 55569085AFC8428389A140EB976CCFB8F29E27587E46C413ABE2EFB51AF5913F 53EEB74063162E0BA1E24CEDCA320377D3E11BD374F0B44E132A5C35835B6E2C D32948EF9DC7931D104C1385709DA882DED6458319F21C2329938396BC074106 CB9CFB9E0A915F8DBC8435F386917AC87A2BA45D857EC30ECA66FB4044F5439E CDD556B82A0E43418D179AD883C85AC276E1190CEC242E3E1D86E725ADC39E46 BB6C47FE9E17E29F8EA81E870302A00D91434F3B7A05F243176E6EF1082541A1 B9052191EE5C2B8E94A2E02DB65FC769653CA8D1C07A13CB853544AEC7FC35C5 218DE3128AA31952DCE19C55C23FD69BCEA2C661F57B11B8F9E86BFA718D1521 3346E78C701A5E51923D6D937E62FDE3669B214D240538F069A100A542720A86 31DE88116DE775F7ACC2A49EA6C02A24408271A846990669F2AF60AFAB4C16F9 7F4E88E917F0FFDCE68F22998AC0AF2A60A73258C3A4BBC42A2F918123128195 196D0E150D79AC3CF4628503D1F3FC528265ED8324E56849A47B3B07C29940B9 1BC270071E221D355EA51E9942D3BD7F99816304FFFC8F5B036C953B38759341 ED5D7B9C8E6B70C409DD8362FD291201CC385E4A98D73E8518A4C0E544152563 82032FBD2FCB6E403D34B85ED4053A8CB619BDD4DE001F4C3007B1F317579651 E6D6662189CC2D95AB85D7473F65C5D7B4AC63B0FE928F3400035D5A9D443D0D F3532B99F3AC26CB25EA3CD64C341159061E02EFBC7C033C05CD919BBD827A6A BAD50D9C98DD94332DB4C7155F8A52013F9ECB7CCE3CFB3E667C57B022A0A753 A45E41A9D8229D5198031ABA3DAAC142AEA5FAB6694A6433629E15AE45A67FDA 34DE10D995ABCAF45FBB3B6B73E80D05F4C51F8C29D4B0F67C8A86432A6C5E86 F0126AB25A5CA2875B48C61CB8112A4CF9AA08F8B0157396CF63CBECDB8867CC AC10F060630C9BFBAD84B1FF01C814878F0C177F552BDC9BB181B14581C6E968 DAAAB2896FCFB745795C4D2C87CC15BAA041EF80C5BDC12EC1F5786BB41A5A21 073EE0BC436B346E014DB4099EDC67BC432E470A4B779FD556341061CA3F2BE8 EFA332637AEC878C2BB189CA3267B2BE5B8178E6B7889A33771F86276E6F0B8E 8E93B816AC7005575762EF4DE45E2794B7322F9B6D8E634FB8FF250D638EB502 818321B3C46DB51B8EC6C2EF1D05C716519A3BD6B12A67239898F8A012A3B5F1 9E59B54BABF9A72CF35A27CEF3AF07C2E4D6BF254DED2524F3068203896C931C 06398C1C3C2881CA864CFC4D243E945BFD8ACB9AD3AB8669A6912158FA150864 D96E34BDCE3142610E8A2BDD2A7DF6A26B718471AEF042F641D019829AFE8637 F8720D2DCC7342E0038D9B43B89953898AEBED5F09DEA465659EBCB83844DAAA 83C627DA47D46ED564CB5AF76309E2FD9E17724A0A893EA0A4329E978212DF25 C0E27E49B63FFEE33D72E04BFCFD84E8A39BFA23D8E7AF6987C87EE06686EA04 14FEE15429BAA6D979F242F4C431EEA7F8DE5A56B3CF11D1507DF22F7B2B4341 D7E72BE1CA8BEB4711ABA2BD032463EC1109E10E12D62D04BC1FA38CC0E6E3AC 0A6629378741E499FA56EFE26BD5D81A2A369BB6F2FDD36DF17CB0A386AE3CCE F9FF8FDC4A8972CE4C48E6647269D9433E76B12412CDCF9789789BFCB0C730C0 AC0378C1D874FC9A766D94D13F06FB2EFEBE97E38933D2F0B71984339FA9DDCB AD23EBB33DEB14341BE3E58999B740458C1D31C148008EBC95B1715FE66E4544 5721E1667C3125C6B2BBE0C6FFE6189426691A7771F75B76060DE2F326ED81A0 6403405A670AF7D7D694CD8E16EE63879F4C6F95A675EA0D2F5D01C7F3D7D838 53D81B570BEA4BFC8AC0279B7D1F7AC7B192873382E9F594B878F6E930591566 9B93F4116218F6F1C0F98A801786D767CED12CFFC95F3A573A726E0A81129869 01D0F89F2B249EC03137C3D05E95B9ADE0DB5941B2610317EB5A6967C88F5EAA 6F3AD85205C91B6BFBF5728DCC1CF564674AF97D467660F8F92005824615CC5B D8EABA48B0DE8871E416151AA005CF3393D136B87307C25B82188571D3161410 85A956927F583F34BBB23551C2C62138A2064D70EA258AB8C171886DBD0AAA9D 35B69196B6BB201477FD10F39BA156FCAEEBAC8B77A083BE199C7E86F173EAD1 6F61F4AAF088BB71CEB57FF0CCF01EF2937CD7BD4685143990BCEF2ABE5266AC 050B274635F92406E867B20048162DF4599F2820FD6EBD0465F634097AC8F836 E17B6D3740B71C2D21847A702489B239F6EF8F02EE7E486D9F9D0647BA8A3C7D B41EE31ADFBCAFC3D1854CE07BC3BFFE7FAAE38C3F849206E2DE9CAF52A5A7D6 BF8DD613A029AD2E5242C8E3499B1A666A662EC2D07C7F53BC1B19AC0B614A14 89F271AE9AD06115E0F188342E20D27F355B23874EFE655A696DA89A091886AA D09080318BF89A03ACD9B9E6E1E039B37B5C88F17579EAB32CF8619B39E91F9D 0922CBE43C2347EB3BB82558852D92D995D5F14ED59A308EEDEBD5594A6FA432 D598237172D1331EB90043662B0307A609E0378D316FDC2440241C76BD052EFB 7A806C2326A403ADD14A4457F85C2DA8D6E5E89D7C52B32BDB641F5146C6E8EF 226EE47E362D8F07D3479040089051A5BDDDC104CA3CB2673516BA61DC5259FE E4F9ACD9AF7922A972B4B11D9F97F5860C205314B55B63D5B05B6F68461553F6 74AAA475F1699C7BC7DF7034367DEE9FA5B06230EC58050F4282C4DC849EEFDC E4A2DF0CC5C0D4DD71BEE29AA08A9A1D1C8A6952665E034F93966D3D8746E6A4 E1B87A34158F72BF6AF182703DC53ACC510B839BA0D30A114B03AE9E4580FEA0 7898BCBAAB7F55FFEB3DF65D31A17092E5622EFBAEB050AF77C03499947062E3 0AB2724E042A796BED919D6B20CF7D725F06244A44D670D4A605BB89377E90EB A7470D58979386B7DA252B4BABEF2C61D8A07A577FB87F4308593EAAB3DBD4DC CA9BF7C39C49AF0FC4EBBAA2A83D876FD9E39F072EFE7BC02BC2B64464674B5A A7606E434318CD4AA8DBD50F78DF37847AF377B3CDD398DFC2D312F105258823 8678578406267B95493032BE79C40E914E6BFD3088A6E6A36EFD260C82B28DD9 2755B89D936803BD3896087AA292118FA9E5A62F64EF5974CD8E821E5DAB6D7E A7B7F2BB1F45423C0482170E375DC2B4336AE9080DEC9B67AAF54E186E363061 25D0805C41B86B2162018E573B99E0299E359E019AB1E05390CF03A823D8FC09 15BF1136CE47DFB8A9CC2EBA8664C279CEC216C9A0AC5FBDEADA05F714A23533 7D3FD8F57523055982026195CE819FD7A548F2D3D4653D143BB6977FDF163F03 DB8739F3B14379D6034726AA0C1A0F403751A4D3817E2C766C7B8CF6A764E1DA 52F3EBF045FA1568F4A56702D94DA948F585083B49D8C982F43DA91EB6968746 937465ADD9DF384EB17552847E3FB1F860BB7B66A6B02C0E9EFDD44D16F8EDE9 413043DBB3380589A7862AFFF381610CF66EBB48349D5695D01572F5BCF98BDC 21A0CB844930558CBF7046F7998280BB2F6570DADA9375D383EA71B0BC01AF71 00B41D3161AD6AD074665BEC701FA5AE108BED942D51B488136291D57736A445 EBA315D417844E206C5C8E1B0AB05E9422470BD4CF6F90F065FB13A3EB3E2FBD DA867D7E5436166535F510620BEAA7B85DBA01551FF3B2778C3FCB66D2770928 D375866328DF4FBED8DF3B4FBFE3E1B9F09B4FCAD829599A956C6E2757E84652 EE44DE26B7FB11A6755ADAD3CE479A97D231E169BDA9E6FC452594B472E5AE0B 439EFC837C35230DE828C55078FA7D49C0136E46CD70635D64E59794A4D394C2 28845F0A1D5CFD9CE6B5365A8B2139B4447FAC23BDB6F88C7E5D46BC86E4C2A8 8E160563D1D6F331858E8B0F379B7E778BBC35D310ABDDE2CAF3B8F019989D53 70E20B2A7E2F9E2945C730A9E3A8B9524DE3F12838171EFC7007303EE4CE5E84 DECC4EC0C39181106C7C3EEE6A3083CB4A7DC8AA0334192AB1EBB28B11229551 DC14178B61206A6251CBE9EB98DE1F41CC02A291192524801902BAAEA8B8E977 52F85693347AA2AA6C3E9B43C8C0DA6A5E1E83849277A39C5B5EDAC81CAA32E5 200F05E71324F5E376C99CA85A9D9054C16D0970446390BE750D34FF69FA5289 49E84B5219B00F9EF2389155DA155EBDD6D35D0A3718146FFF61B9657D29C640 349344E1FFA43B64D35BCF9986CEF358D97BC986D96631ABED765BA36AF94417 C972310916B9946F10AF8AAB37B925481C591F4E85ECC983312F77052D98B356 F2A0541EF41BCA2AA6A48BD3A37FFFB07CE7C933BD984E17B4AEC3FD3C3B07C4 DA43D96980004D0D97A8CA236AAE3DBEC0525C4BB911859ECB71AA52724AD006 64AE326374362DA1D266897860B873470AD1A9ADF0B7AF361BD44CC5AF587B2E AE824DE05EBAC3E8121525F820178DCA353745685EBD9AAEE5E3EC171ED8ACC7 D58DCCAA37BA237958217F7FFDD8A2608F04CBC038E49798F8CAA32A738358B4 3FBBF13A273B61104B7D109B1A3358C2D7D758CAA6BD4341B63739954E4E6690 D83417A80C3F5E515DDD71A3867D82E4081C2DC07F5FFB383CFC80F54E09 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont TeXDict begin 39158280 55380996 1000 600 600 (fitsio.dvi) @start /Fa 215[27 40[{}1 66.4176 /CMR8 rf /Fb 134[45 52 65 1[52 33 43 41 1[46 44 55 80 27 47 1[31 52 43 45 42 47 39 39 48 12[53 10[40 10[71 2[25 25 58[{}27 90.9091 /CMMI10 rf /Fc 133[50 59 59 81 59 62 44 44 46 1[62 56 62 93 31 59 1[31 62 56 34 51 62 50 62 54 9[116 85 86 78 62 84 1[77 84 88 106 67 88 1[42 88 88 70 74 86 81 80 85 6[31 1[56 56 56 56 56 56 56 56 1[56 31 37 32[62 12[{}58 99.6264 /CMBX12 rf /Fd 149[25 2[45 45 86[45 12[71 2[{}5 90.9091 /CMSY10 rf /Fe 133[60 71 71 97 71 75 52 53 55 1[75 67 75 112 37 71 1[37 75 67 41 61 75 60 75 65 9[139 102 103 94 75 100 1[92 101 105 128 81 105 1[50 105 106 85 88 103 97 96 102 6[37 67 67 67 67 67 67 67 67 67 67 67 37 45 3[52 52 27[75 78 11[{}63 119.552 /CMBX12 rf /Ff 129[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 1[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}93 90.9091 /CMTT10 rf /Fg 139[75 1[79 1[108 7[108 2[88 3[94 29[140 9[97 97 97 97 97 97 97 97 97 97 48[{}17 172.188 /CMBX12 rf /Fh 165[56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 1[33 68 71 59 62 69 66 64 68 6[25 45 45 45 45 45 45 45 45 45 45 45 25 30 45[{}38 90.9091 /CMSL10 rf /Fi 134[55 55 1[55 58 41 41 43 1[58 52 58 87 29 2[29 58 52 32 48 58 46 58 51 11[80 73 58 78 1[71 79 82 4[40 1[82 66 69 80 76 74 79 7[52 52 52 52 52 52 52 52 52 52 52 1[35 32[58 12[{}49 90.9091 /CMBX10 rf /Fj 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 45 25 56 68 68 93 68 68 66 51 67 71 62 71 68 83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 43 71 25 25 25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 76 45 76 45 25 18[76 51 51 53 11[{}93 90.9091 /CMR10 rf /Fk 138[65 1[46 46 2[59 65 1[33 2[33 3[52 14[88 11[60 21[59 59 59 1[59 1[33 46[{}15 119.552 /CMR12 rf /Fl 138[90 63 64 66 2[81 90 134 45 2[45 1[81 49 74 1[72 90 78 12[112 90 2[110 6[60 2[101 4[122 65[{}21 143.462 /CMBX12 rf /Fm 134[123 123 1[123 129 90 92 95 1[129 116 129 194 65 2[65 129 116 71 106 129 103 129 113 11[179 162 129 173 1[159 175 182 4[87 1[183 146 153 178 168 165 175 17[116 1[77 5[65 26[129 12[{}40 206.559 /CMBX12 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: a4 /setpagedevice where { pop << /PageSize [595 842] >> setpagedevice } { /a4 where { pop a4 } if } ifelse %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 861 1940 a Fm(FITSIO)76 b(User's)g(Guide)356 2399 y Fl(A)54 b(Subroutine)d(In)l(terface)i(to)g(FITS)h(F)-13 b(ormat)54 b(Files)1055 2659 y(for)g(F)-13 b(ortran)53 b(Programmers)1667 3155 y Fk(V)-10 b(ersion)38 b(4.3)1727 4058 y Fj(HEASAR)m(C)1764 4170 y(Co)s(de)30 b(662)1363 4283 y(Go)s(ddard)f(Space)i(Fligh)m(t)h(Cen)m(ter)1522 4396 y(Green)m(b)s(elt,)f(MD)h(20771)1857 4509 y(USA)1735 5309 y Fk(Jul)38 b(2023)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 0 299 a Fj(ii)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 0 1267 a Fm(Con)-6 b(ten)g(ts)0 1858 y Fi(1)84 b(In)m(tro)s(duction)3136 b(1)0 2118 y(2)119 b(Creating)34 b(FITSIO/CFITSIO)2405 b(3)136 2280 y Fj(2.1)94 b(Building)31 b(the)f(Library)58 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(3)136 2442 y(2.2)94 b(T)-8 b(esting)32 b(the)e(Library)j(.)46 b(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(6)136 2604 y(2.3)94 b(Linking)31 b(Programs)f(with)g(FITSIO)40 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 2766 y(2.4)94 b(Getting)32 b(Started)f(with)f(FITSIO)55 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 2928 y(2.5)94 b(Example)31 b(Program)86 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)131 b(8)136 3090 y(2.6)94 b(Legal)32 b(Stu\013)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 3252 y(2.7)94 b(Ac)m(kno)m(wledgmen)m(ts)30 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(10)0 3511 y Fi(3)119 b(A)35 b(FITS)f(Primer)2918 b(13)0 3771 y(4)84 b(FITSIO)34 b(Con)m(v)m(en)m(tions)h(and)g(Guidelines)1993 b(15)136 3933 y Fj(4.1)94 b(CFITSIO)29 b(Size)i(Limitations)42 b(.)k(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(15)136 4095 y(4.2)94 b(Multiple)32 b(Access)f(to)g(the)g(Same)f(FITS) g(File)h(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4257 y(4.3)94 b(Curren)m(t)30 b(Header)h(Data)h(Unit)e(\(CHDU\))87 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4419 y(4.4)94 b(Subroutine)29 b(Names)79 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4581 y(4.5)94 b(Subroutine)29 b(F)-8 b(amilies)33 b(and)c(Datat)m(yp)s (es)44 b(.)i(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(17)136 4742 y(4.6)94 b(Implicit)31 b(Data)h(T)m(yp)s(e)e(Con)m(v)m(ersion)65 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(17)136 4904 y(4.7)94 b(Data)32 b(Scaling)89 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(18)136 5066 y(4.8)94 b(Error)30 b(Status)g(V)-8 b(alues)32 b(and)d(the)i(Error)e(Message)j(Stac)m(k)44 b(.)i(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(18)136 5228 y(4.9)94 b(V)-8 b(ariable-Length)33 b(Arra)m(y)d(F)-8 b(acilit)m(y)34 b(in)c(Binary)g(T)-8 b(ables)26 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(19)136 5390 y(4.10)49 b(Supp)s(ort)29 b(for)h(IEEE)g(Sp)s(ecial)g(V)-8 b(alues)68 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(20)136 5552 y(4.11)49 b(When)31 b(the)f(Final)h(Size)g(of)g(the)f(FITS)g(HDU)h (is)f(Unkno)m(wn)k(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)136 5714 y(4.12)49 b(Lo)s(cal)32 b(FITS)d(Con)m(v)m(en)m(tions)j(supp)s(orted)c(b)m(y)j (FITSIO)72 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)1912 5942 y(iii)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 0 299 a Fj(iv)3311 b Fh(CONTENTS)345 555 y Fj(4.12.1)61 b(Supp)s(ort)29 b(for)h(Long)g(String)g(Keyw)m(ord)g (V)-8 b(alues.)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)345 716 y(4.12.2)61 b(Arra)m(ys)31 b(of)f(Fixed-Length)h(Strings)f(in)g(Binary)h(T)-8 b(ables)70 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)85 b(22)345 876 y(4.12.3)61 b(Keyw)m(ord)30 b(Units)h(Strings)i (.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(23)345 1037 y(4.12.4)61 b(HIERAR)m(CH)31 b(Con)m(v)m(en)m(tion)h(for) e(Extended)g(Keyw)m(ord)g(Names)83 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)85 b(23)136 1197 y(4.13)49 b(Optimizing)31 b(Co)s(de)f(for)g(Maxim)m(um)h(Pro)s(cessing)g(Sp)s(eed)44 b(.)i(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(24)345 1358 y(4.13.1)61 b(Bac)m(kground)31 b(Information:)41 b(Ho)m(w)31 b(CFITSIO)e(Manages)j(Data)g(I/O)91 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(24)345 1518 y(4.13.2)61 b(Optimization)32 b(Strategies)69 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(25)0 1771 y Fi(5)119 b(Basic)36 b(In)m(terface)e(Routines)2504 b(29)136 1931 y Fj(5.1)94 b(FITSIO)30 b(Error)f(Status)h(Routines)84 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(29)136 2092 y(5.2)94 b(File)32 b(I/O)e(Routines)e(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)85 b(30)136 2252 y(5.3)94 b(Keyw)m(ord)31 b(I/O)f(Routines)36 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(32)136 2412 y(5.4)94 b(Data)32 b(I/O)f(Routines)53 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(33)0 2665 y Fi(6)119 b(Adv)-6 b(anced)36 b(In)m(terface)e(Subroutines)2159 b(35)136 2826 y Fj(6.1)94 b(FITS)30 b(File)i(Op)s(en)d(and)g(Close)i(Subroutines:)76 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(35)136 2986 y(6.2)94 b(HDU-Lev)m(el)33 b(Op)s(erations)108 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(38)136 3146 y(6.3)94 b(De\014ne)31 b(or)f(Rede\014ne)g(the)h(structure)f(of)g(the)h (CHDU)99 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(41)136 3307 y(6.4)94 b(FITS)30 b(Header)h(I/O)f(Subroutines)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)345 3467 y(6.4.1)106 b(Header)31 b(Space)g(and)f(P)m(osition)h(Routines)60 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)345 3628 y(6.4.2)106 b(Read)31 b(or)f(W)-8 b(rite)32 b(Standard)d(Header)i(Routines)67 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)85 b(43)345 3788 y(6.4.3)106 b(W)-8 b(rite)32 b(Keyw)m(ord)e(Subroutines)116 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 85 b(45)345 3949 y(6.4.4)106 b(Insert)30 b(Keyw)m(ord)g(Subroutines)108 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)345 4109 y(6.4.5)106 b(Read)31 b(Keyw)m(ord)f(Subroutines)64 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)345 4270 y(6.4.6)106 b(Mo)s(dify)30 b(Keyw)m(ord)h(Subroutines)55 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(49)345 4430 y(6.4.7)106 b(Up)s(date)31 b(Keyw)m(ord)f(Subroutines)116 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(50)345 4591 y(6.4.8)106 b(Delete)33 b(Keyw)m(ord)d(Subroutines)87 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(51)136 4751 y(6.5)94 b(Data)32 b(Scaling)g(and)d(Unde\014ned)g(Pixel)i(P)m (arameters)113 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(51)136 4912 y(6.6)94 b(FITS)30 b(Primary)g(Arra)m(y)h(or)f(IMA)m(GE)h(Extension)g(I/O)f (Subroutines)117 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(52)136 5072 y(6.7)94 b(FITS)30 b(ASCI)s(I)f(and)h(Binary)g(T)-8 b(able)31 b(Data)h(I/O)e(Subroutines)d(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(56)345 5232 y(6.7.1)106 b(Column)30 b(Information)g(Subroutines)121 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(56)345 5393 y(6.7.2)106 b(Lo)m(w-Lev)m(el)33 b(T)-8 b(able)31 b(Access)g(Subroutines)60 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(58)345 5553 y(6.7.3)106 b(Edit)31 b(Ro)m(ws)f(or)h(Columns)106 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)85 b(59)345 5714 y(6.7.4)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(Column)f(Data)i(Routines)66 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(60)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 0 299 a Fh(CONTENTS)3334 b Fj(v)136 555 y(6.8)94 b(Ro)m(w)31 b(Selection)h(and)e(Calculator)i(Routines)95 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(64)136 717 y(6.9)94 b(Celestial)33 b(Co)s(ordinate)d(System)g(Subroutines)98 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(65)136 879 y(6.10)49 b(File)32 b(Chec)m(ksum)e(Subroutines)75 b(.)45 b(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(67)136 1041 y(6.11)80 b(Date)32 b(and)d(Time)i(Utilit)m(y)h(Routines)69 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(68)136 1204 y(6.12)49 b(General)32 b(Utilit)m(y)g(Subroutines)61 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(69)0 1464 y Fi(7)119 b(The)35 b(CFITSIO)e(Iterator)g(F)-9 b(unction)2154 b(77)0 1725 y(8)119 b(Extended)35 b(File)f(Name)h(Syn)m (tax)2330 b(79)136 1887 y Fj(8.1)94 b(Ov)m(erview)84 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(79)136 2049 y(8.2)94 b(Filet)m(yp)s(e)62 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)345 2211 y(8.2.1)106 b(Notes)32 b(ab)s(out)e(HTTP)g(pro)m(xy)g (serv)m(ers)k(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)345 2373 y(8.2.2)106 b(Notes)32 b(ab)s(out)e(the)h(stream)f(\014let)m(yp)s (e)h(driv)m(er)54 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(83)345 2536 y(8.2.3)106 b(Notes)32 b(ab)s(out)e(the)h(gsiftp)f(\014let)m(yp)s(e)83 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)345 2698 y(8.2.4)106 b(Notes)32 b(ab)s(out)e(the)h(ro)s(ot)f(\014let)m(yp)s(e)68 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)345 2860 y(8.2.5)106 b(Notes)32 b(ab)s(out)e(the)h(shmem)e(\014let)m(yp)s(e:)70 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(86)136 3022 y(8.3)94 b(Base)32 b(Filename)90 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(86)136 3184 y(8.4)94 b(Output)30 b(File)h(Name)g(when)f(Op)s(ening)f(an)h (Existing)h(File)81 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(88)136 3346 y(8.5)94 b(T)-8 b(emplate)32 b(File)g(Name)f(when)e(Creating)i(a)g(New)f(File)57 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(90)136 3508 y(8.6)94 b(Image)32 b(Tile-Compression)e(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)85 b(90)136 3670 y(8.7)94 b(HDU)32 b(Lo)s(cation)f(Sp)s (eci\014cation)47 b(.)e(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)85 b(90)136 3832 y(8.8)94 b(Image)32 b(Section)39 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)85 b(91)136 3994 y(8.9)94 b(Image)32 b(T)-8 b(ransform)29 b(Filters)54 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(92)136 4156 y(8.10)49 b(Column)30 b(and)g(Keyw)m(ord)g(Filtering)h(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)85 b(94)136 4318 y(8.11)49 b(Ro)m(w)31 b(Filtering)h(Sp)s(eci\014cation)82 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(97)345 4481 y(8.11.1)61 b(General)32 b(Syn)m(tax)44 b(.)i(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(97)345 4643 y(8.11.2)61 b(Bit)32 b(Masks)43 b(.)j(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(100)345 4805 y(8.11.3)61 b(V)-8 b(ector)32 b(Columns)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(101)345 4967 y(8.11.4)61 b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)h(and)d (Calculation)37 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)40 b(103)345 5129 y(8.11.5)61 b(Spatial)31 b(Region)h(Filtering)59 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(105)345 5291 y(8.11.6)61 b(Example)31 b(Ro)m(w)g(Filters)h (.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(107)136 5453 y(8.12)80 b(Binning)30 b(or)g(Histogramming)i(Sp)s (eci\014cation)f(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(109)0 5714 y Fi(9)84 b(T)-9 b(emplate)35 b(Files)2933 b(113)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 0 299 a Fj(vi)3311 b Fh(CONTENTS)136 555 y Fj(9.1)94 b(Detailed)33 b(T)-8 b(emplate)31 b(Line)g(F)-8 b(ormat)48 b(.)e(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(113)136 715 y(9.2)94 b(Auto-indexing)31 b(of)g(Keyw)m(ords)73 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(114)136 876 y(9.3)94 b(T)-8 b(emplate)32 b(P)m(arser)f(Directiv)m(es) 87 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(115)136 1036 y(9.4)94 b(F)-8 b(ormal)32 b(T)-8 b(emplate)32 b(Syn)m(tax)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)40 b(116)136 1196 y(9.5)94 b(Errors)63 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(116)136 1356 y(9.6)94 b(Examples)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(116)0 1607 y Fi(10)67 b(Summary)36 b(of)f(all)f(FITSIO)g(User-In)m(terface)h (Subroutines)1215 b(119)0 1858 y(11)67 b(P)m(arameter)35 b(De\014nitions)2563 b(127)0 2109 y(12)67 b(FITSIO)33 b(Error)i(Status)g(Co)s(des)2295 b(133)p eop end %%Page: 1 7 TeXDict begin 1 6 bop 0 1225 a Fg(Chapter)65 b(1)0 1687 y Fm(In)-6 b(tro)6 b(duction)0 2180 y Fj(This)33 b(do)s(cumen)m(t)i (describ)s(es)e(the)h(F)-8 b(ortran-callable)38 b(subroutine)33 b(in)m(terface)j(that)f(is)f(pro)m(vided)g(as)g(part)g(of)h(the)0 2293 y(CFITSIO)f(library)h(\(whic)m(h)h(is)g(written)g(in)f(ANSI)g (C\).)h(This)f(is)h(a)g(companion)g(do)s(cumen)m(t)f(to)i(the)e (CFITSIO)0 2406 y(User's)k(Guide)f(whic)m(h)h(should)e(b)s(e)h (consulted)h(for)f(further)g(information)h(ab)s(out)f(the)h(underlying) e(CFITSIO)0 2518 y(library)-8 b(.)50 b(In)32 b(the)i(remainder)f(of)g (this)h(do)s(cumen)m(t,)g(the)g(terms)f(FITSIO)f(and)h(CFITSIO)f(are)i (in)m(terc)m(hangeable)0 2631 y(and)c(refer)g(to)h(the)g(same)f (library)-8 b(.)0 2791 y(FITSIO/CFITSIO)31 b(is)j(a)f(mac)m(hine-indep) s(enden)m(t)g(library)g(of)h(routines)f(for)g(reading)h(and)f(writing)g (data)h(\014les)0 2904 y(in)c(the)g(FITS)g(\(Flexible)i(Image)f(T)-8 b(ransp)s(ort)29 b(System\))h(data)h(format.)41 b(It)31 b(can)f(also)h(read)g(IRAF)f(format)h(image)0 3017 y(\014les)40 b(and)e(ra)m(w)i(binary)f(data)h(arra)m(ys)g(b)m(y)g(con)m(v)m(erting)h (them)e(on)h(the)g(\015y)f(in)m(to)h(a)g(virtual)g(FITS)f(format)h (\014le.)0 3130 y(This)32 b(library)h(w)m(as)g(written)g(to)h(pro)m (vide)f(a)h(p)s(o)m(w)m(erful)f(y)m(et)h(simple)f(in)m(terface)h(for)f (accessing)i(FITS)d(\014les)h(whic)m(h)0 3243 y(will)j(run)e(on)h(most) h(commonly)g(used)e(computers)h(and)g(w)m(orkstations.)57 b(FITSIO)34 b(supp)s(orts)g(all)i(the)g(features)0 3356 y(describ)s(ed)j(in)g(the)h(o\016cial)i(de\014nition)d(of)h(the)g(FITS) f(format)i(and)e(can)h(read)g(and)f(write)h(all)h(the)f(curren)m(tly)0 3469 y(de\014ned)g(t)m(yp)s(es)h(of)g(extensions,)j(including)d(ASCI)s (I)e(tables)j(\(T)-8 b(ABLE\),)42 b(Binary)f(tables)h(\(BINT)-8 b(ABLE\))43 b(and)0 3582 y(IMA)m(GE)36 b(extensions.)56 b(The)34 b(FITSIO)g(subroutines)g(insulate)i(the)f(programmer)g(from)g (ha)m(ving)h(to)g(deal)f(with)0 3695 y(the)25 b(complicated)h (formatting)g(details)f(in)f(the)h(FITS)f(\014le,)i(ho)m(w)m(ev)m(er,)i (it)d(is)f(assumed)g(that)h(users)f(ha)m(v)m(e)i(a)f(general)0 3808 y(kno)m(wledge)31 b(ab)s(out)f(the)h(structure)f(and)g(usage)h(of) f(FITS)g(\014les.)0 3968 y(The)20 b(CFITSIO)f(pac)m(k)-5 b(age)23 b(w)m(as)e(initially)i(dev)m(elop)s(ed)e(b)m(y)f(the)h(HEASAR) m(C)g(\(High)h(Energy)e(Astroph)m(ysics)h(Science)0 4081 y(Arc)m(hiv)m(e)35 b(Researc)m(h)g(Cen)m(ter\))f(at)h(the)f(NASA)g(Go)s (ddard)e(Space)j(Fligh)m(t)g(Cen)m(ter)f(to)h(con)m(v)m(ert)g(v)-5 b(arious)34 b(existing)0 4194 y(and)25 b(newly)h(acquired)g (astronomical)i(data)e(sets)h(in)m(to)g(FITS)e(format)h(and)f(to)i (further)e(analyze)i(data)g(already)f(in)0 4307 y(FITS)h(format.)41 b(New)28 b(features)g(con)m(tin)m(ue)h(to)g(b)s(e)e(added)h(to)g (CFITSIO)f(in)g(large)i(part)f(due)g(to)g(con)m(tributions)h(of)0 4419 y(ideas)k(or)g(actual)h(co)s(de)f(from)f(users)g(of)h(the)g(pac)m (k)-5 b(age.)49 b(The)33 b(In)m(tegral)h(Science)f(Data)h(Cen)m(ter)f (in)g(Switzerland,)0 4532 y(and)g(the)g(XMM/ESTEC)h(pro)5 b(ject)34 b(in)f(The)g(Netherlands)g(made)g(esp)s(ecially)i (signi\014can)m(t)f(con)m(tributions)g(that)0 4645 y(resulted)c(in)g (man)m(y)h(of)f(the)h(new)f(features)g(that)h(app)s(eared)f(in)g(v2.0)i (of)e(CFITSIO.)0 4805 y(The)22 b(latest)i(v)m(ersion)f(of)g(the)f (CFITSIO)f(source)i(co)s(de,)h(do)s(cumen)m(tation,)i(and)21 b(example)j(programs)e(are)h(a)m(v)-5 b(ailable)0 4918 y(on)30 b(the)h(W)-8 b(orld-Wide)32 b(W)-8 b(eb)31 b(or)f(via)h(anon)m (ymous)f(ftp)g(from:)382 5178 y Ff(http://heasarc.gsfc.nasa)o(.go)o (v/fi)o(tsio)382 5291 y(ftp://legacy.gsfc.nasa.g)o(ov/)o(soft)o(ware)o (/fi)o(tsio)o(/c)1927 5942 y Fj(1)p eop end %%Page: 2 8 TeXDict begin 2 7 bop 0 299 a Fj(2)2452 b Fh(CHAPTER)30 b(1.)71 b(INTR)m(ODUCTION)0 555 y Fj(An)m(y)28 b(questions,)g(bug)f (rep)s(orts,)h(or)f(suggested)i(enhancemen)m(ts)f(related)g(to)h(the)e (CFITSIO)f(pac)m(k)-5 b(age)30 b(should)d(b)s(e)0 668 y(sen)m(t)k(to)g(the)g(FTOOLS)e(Help)h(Desk)h(at)g(the)g(HEASAR)m(C:) 382 928 y Ff(http://heasarc.gsfc.nasa)o(.go)o(v/cg)o(i-bi)o(n/f)o(tool) o(shel)o(p)0 1188 y Fj(This)40 b(User's)i(Guide)f(assumes)g(that)h (readers)f(already)g(ha)m(v)m(e)i(a)f(general)g(understanding)d(of)j (the)f(de\014nition)0 1301 y(and)31 b(structure)g(of)h(FITS)e(format)i (\014les.)44 b(F)-8 b(urther)32 b(information)f(ab)s(out)h(FITS)f (formats)g(is)h(a)m(v)-5 b(ailable)34 b(from)d(the)0 1413 y(FITS)37 b(Supp)s(ort)f(O\016ce)i(at)h Ff (http://fits.gsfc.nasa.g)o(ov)p Fj(.)57 b(In)37 b(particular,)j(the)e ('FITS)g(Standard')f(giv)m(es)0 1526 y(the)31 b(authoritativ)m(e)j (de\014nition)d(of)g(the)h(FITS)e(data)i(format.)43 b(Other)31 b(do)s(cumen)m(ts)g(a)m(v)-5 b(ailable)34 b(at)d(that)h(W)-8 b(eb)32 b(site)0 1639 y(pro)m(vide)e(additional)i(historical)f(bac)m (kground)g(and)e(practical)j(advice)g(on)e(using)g(FITS)f(\014les.)0 1799 y(The)d(HEASAR)m(C)f(also)i(pro)m(vides)f(a)h(v)m(ery)f (sophisticated)h(FITS)e(\014le)i(analysis)f(program)g(called)h(`Fv')g (whic)m(h)f(can)0 1912 y(b)s(e)31 b(used)f(to)i(displa)m(y)f(and)g (edit)g(the)h(con)m(ten)m(ts)g(of)g(an)m(y)f(FITS)g(\014le)g(as)g(w)m (ell)h(as)g(construct)f(new)g(FITS)f(\014les)h(from)0 2025 y(scratc)m(h.)56 b(Fv)36 b(is)f(freely)h(a)m(v)-5 b(ailable)37 b(for)e(most)h(Unix)f(platforms,)i(Mac)f(PCs,)g(and)f (Windo)m(ws)g(PCs.)54 b(CFITSIO)0 2138 y(users)29 b(ma)m(y)h(also)h(b)s (e)f(in)m(terested)g(in)g(the)g(FTOOLS)f(pac)m(k)-5 b(age)31 b(of)g(programs)e(that)h(can)h(b)s(e)e(used)g(to)i(manipulate)0 2251 y(and)f(analyze)i(FITS)d(format)i(\014les.)41 b(Fv)30 b(and)g(FTOOLS)f(are)i(a)m(v)-5 b(ailable)32 b(from)e(their)h(resp)s (ectiv)m(e)g(W)-8 b(eb)31 b(sites)g(at:)382 2511 y Ff (http://fv.gsfc.nasa.gov)382 2624 y(http://heasarc.gsfc.nasa)o(.go)o (v/ft)o(ools)p eop end %%Page: 3 9 TeXDict begin 3 8 bop 0 1225 a Fg(Chapter)65 b(2)0 1687 y Fm(Creating)77 b(FITSIO/CFITSIO)0 2216 y Fe(2.1)135 b(Building)45 b(the)h(Library)0 2467 y Fj(T)-8 b(o)43 b(use)g(the)g(FITSIO)f(subroutines)f(one)j(m)m(ust)e(\014rst)g(build)g (the)h(CFITSIO)f(library)-8 b(,)46 b(whic)m(h)d(requires)f(a)h(C)0 2580 y(compiler.)73 b(gcc)43 b(is)e(ideal,)j(or)d(most)h(other)f (ANSI-C)g(compilers)g(will)h(also)g(w)m(ork.)73 b(The)40 b(CFITSIO)g(co)s(de)h(is)0 2692 y(con)m(tained)25 b(in)f(ab)s(out)f(40) i(C)f(source)g(\014les)f(\(*.c\))j(and)d(header)h(\014les)g(\(*.h\).)39 b(On)23 b(V)-10 b(AX/VMS)25 b(systems)f(2)g(assem)m(bly-)0 2805 y(co)s(de)31 b(\014les)f(\(vmsieeed.mar)h(and)f(vmsieeer.mar\))h (are)g(also)g(needed.)0 2965 y(The)45 b(F)-8 b(ortran)46 b(in)m(terface)g(subroutines)e(to)i(the)f(C)g(CFITSIO)f(routines)h(are) g(lo)s(cated)i(in)e(the)g(f77)p 3538 2965 28 4 v 33 w(wrap1.c,)0 3078 y(through)22 b(f77)p 459 3078 V 33 w(wrap4.c)h(\014les.)38 b(These)22 b(are)h(relativ)m(ely)i(simple)d('wrapp)s(ers')f(that)i (translate)h(the)f(argumen)m(ts)g(in)f(the)0 3191 y(F)-8 b(ortran)26 b(subroutine)e(in)m(to)j(the)e(appropriate)h(format)g(for)f (the)g(corresp)s(onding)g(C)g(routine.)39 b(This)24 b(translation)j(is) 0 3304 y(p)s(erformed)19 b(transparen)m(tly)i(to)g(the)g(user)f(b)m(y)g (a)h(set)h(of)e(C)h(macros)g(lo)s(cated)h(in)e(the)h(cfortran.h)f (\014le.)38 b(Unfortunately)0 3417 y(cfortran.h)28 b(do)s(es)g(not)g (supp)s(ort)f(ev)m(ery)h(com)m(bination)i(of)e(C)g(and)f(F)-8 b(ortran)29 b(compilers)g(so)f(the)h(F)-8 b(ortran)28 b(in)m(terface)0 3530 y(is)i(not)h(supp)s(orted)e(on)h(all)h (platforms.)41 b(\(see)31 b(further)e(notes)i(b)s(elo)m(w\).)0 3690 y(A)f(standard)f(com)m(bination)j(of)e(C)f(and)h(F)-8 b(ortran)30 b(compilers)h(will)f(b)s(e)f(assumed)h(b)m(y)f(default,)i (but)e(one)h(ma)m(y)h(also)0 3803 y(sp)s(ecify)f(a)h(particular)f(F)-8 b(ortran)32 b(compiler)e(b)m(y)h(doing:)48 4064 y Ff(>)95 b(setenv)46 b(CFLAGS)g(-DcompilerName=1)0 4324 y Fj(\(where)33 b('compilerName')h(is)f(the)g(name)f(of)h(the)g(compiler\))h(b)s(efore) e(running)f(the)i(con\014gure)f(command.)47 b(The)0 4437 y(curren)m(tly)30 b(recognized)i(compiler)f(names)f(are:)48 4698 y Ff(g77Fortran)48 4811 y(IBMR2Fortran)48 4924 y(CLIPPERFortran)48 5036 y(pgiFortran)48 5149 y(NAGf90Fortran)48 5262 y(f2cFortran)48 5375 y(hpuxFortran)48 5488 y(apolloFortran)48 5601 y(sunFortran)48 5714 y(CRAYFortran)1927 5942 y Fj(3)p eop end %%Page: 4 10 TeXDict begin 4 9 bop 0 299 a Fj(4)1896 b Fh(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)48 555 y Ff(mipsFortran)48 668 y(DECFortran)48 781 y(vmsFortran)48 894 y(CONVEXFortran)48 1007 y(PowerStationFortran)48 1120 y(AbsoftUNIXFortran)48 1233 y(AbsoftProFortran)48 1346 y(SXFortran)0 1609 y Fj(Alternativ)m(ely)-8 b(,)42 b(one)c(ma)m(y)g(edit)g(the)f(CFLA)m(GS)h(line)f(in)h(the)f(Mak)m (e\014le)i(to)f(add)f(the)h('-DcompilerName')i(\015ag)0 1722 y(after)31 b(running)e(the)h('./con\014gure')h(command.)0 1882 y(The)f(CFITSIO)f(library)h(is)g(built)g(on)h(Unix)f(systems)g(b)m (y)g(t)m(yping:)48 2146 y Ff(>)95 b(./configure)45 b ([--prefix=/target/insta)o(llat)o(ion)o(/pat)o(h])764 2259 y([--enable-sse2])e([--enable-ssse3])48 2372 y(>)95 b(make)476 b(\(or)95 b('make)46 b(shared'\))48 2485 y(>)95 b(make)47 b(install)93 b(\(this)46 b(step)h(is)g(optional\))0 2749 y Fj(at)24 b(the)g(op)s(erating)g(system)g(prompt.)38 b(The)23 b(con\014gure)g(command)g(customizes)i(the)f(Mak)m(e\014le)h (for)f(the)g(particular)0 2861 y(system,)g(then)d(the)g(`mak)m(e')i (command)e(compiles)h(the)f(source)h(\014les)f(and)g(builds)f(the)h (library)-8 b(.)38 b(T)m(yp)s(e)21 b(`./con\014gure')0 2974 y(and)34 b(not)h(simply)f(`con\014gure')h(to)h(ensure)e(that)h (the)g(con\014gure)g(script)f(in)h(the)g(curren)m(t)f(directory)h(is)g (run)f(and)0 3087 y(not)29 b(some)g(other)g(system-wide)g(con\014gure)f (script.)40 b(The)29 b(optional)h('pre\014x')e(argumen)m(t)h(to)g (con\014gure)g(giv)m(es)h(the)0 3200 y(path)e(to)i(the)f(directory)g (where)f(the)h(CFITSIO)f(library)g(and)g(include)h(\014les)f(should)g (b)s(e)g(installed)i(via)f(the)g(later)0 3313 y('mak)m(e)j(install')f (command.)41 b(F)-8 b(or)31 b(example,)143 3577 y Ff(>)48 b(./configure)c(--prefix=/usr1/local)0 3841 y Fj(will)25 b(cause)h(the)f('mak)m(e)h(install')g(command)f(to)h(cop)m(y)g(the)f (CFITSIO)e(lib)s(c\014tsio)i(\014le)h(to)f(/usr1/lo)s(cal/lib)i(and)e (the)0 3953 y(necessary)33 b(include)e(\014les)i(to)f(/usr1/lo)s (cal/include)j(\(assuming)d(of)g(course)g(that)h(the)f(pro)s(cess)g (has)g(p)s(ermission)0 4066 y(to)f(write)g(to)g(these)g(directories\).) 0 4227 y(The)24 b(optional)i({enable-sse2)g(and)e({enable-ssse3)i (\015ags)e(will)h(cause)g(con\014gure)f(to)h(attempt)h(to)f(build)e (CFITSIO)0 4339 y(using)31 b(faster)h(b)m(yte-sw)m(apping)g (algorithms.)46 b(See)32 b(the)g("Optimizing)g(Programs")g(section)h (of)f(this)f(man)m(ual)h(for)0 4452 y(more)f(information)f(ab)s(out)g (these)h(options.)0 4613 y(By)37 b(default,)i(the)f(Mak)m(e\014le)g (will)g(b)s(e)e(con\014gured)g(to)i(build)e(the)h(set)h(of)f(F)-8 b(ortran-callable)40 b(wrapp)s(er)35 b(routines)0 4725 y(whose)30 b(calling)i(sequences)f(are)f(describ)s(ed)g(later)h(in)f (this)g(do)s(cumen)m(t.)0 4886 y(The)e('mak)m(e)h(shared')f(option)h (builds)e(a)i(shared)e(or)i(dynamic)f(v)m(ersion)h(of)f(the)h(CFITSIO)d (library)-8 b(.)40 b(When)28 b(using)0 4999 y(the)f(shared)f(library)h (the)g(executable)h(co)s(de)f(is)g(not)g(copied)g(in)m(to)h(y)m(our)f (program)g(at)g(link)g(time)g(and)g(instead)g(the)0 5111 y(program)g(lo)s(cates)i(the)f(necessary)g(library)f(co)s(de)h(at)g (run)e(time,)j(normally)f(through)e(LD)p 3065 5111 28 4 v 33 w(LIBRAR)-8 b(Y)p 3514 5111 V 34 w(P)g(A)g(TH)28 b(or)0 5224 y(some)j(other)f(metho)s(d.)41 b(The)29 b(adv)-5 b(an)m(tages)33 b(of)d(using)g(a)h(shared)e(library)h(are:)143 5488 y Ff(1.)95 b(Less)47 b(disk)f(space)h(if)g(you)g(build)f(more)h (than)f(1)i(program)143 5601 y(2.)95 b(Less)47 b(memory)f(if)h(more)g (than)f(one)h(copy)g(of)g(a)g(program)f(using)h(the)g(shared)334 5714 y(library)f(is)h(running)f(at)h(the)g(same)g(time)f(since)h(the)g (system)f(is)h(smart)p eop end %%Page: 5 11 TeXDict begin 5 10 bop 0 299 a Fh(2.1.)72 b(BUILDING)31 b(THE)f(LIBRAR)-8 b(Y)2507 b Fj(5)334 555 y Ff(enough)46 b(to)h(share)g(copies)f(of)h(the)g(shared)f(library)g(at)h(run)g(time.) 143 668 y(3.)95 b(Possibly)46 b(easier)g(maintenance)e(since)j(a)g(new) g(version)f(of)h(the)g(shared)334 781 y(library)f(can)h(be)g(installed) e(without)h(relinking)f(all)i(the)g(software)334 894 y(that)g(uses)f(it)i(\(as)e(long)h(as)g(the)g(subroutine)e(names)i(and) f(calling)334 1007 y(sequences)f(remain)h(unchanged\).)143 1120 y(4.)95 b(No)47 b(run-time)f(penalty.)0 1534 y Fj(The)30 b(disadv)-5 b(an)m(tages)32 b(are:)143 1949 y Ff(1.)47 b(More)g(hassle)f(at)h(runtime.)94 b(You)46 b(have)h(to)g(either)f (build)h(the)g(programs)286 2062 y(specially)f(or)h(have)f (LD_LIBRARY_PATH)e(set)j(right.)143 2175 y(2.)g(There)g(may)g(be)g(a)g (slight)f(start)h(up)g(penalty,)e(depending)h(on)h(where)f(you)h(are) 286 2288 y(reading)f(the)h(shared)f(library)g(and)h(the)g(program)f (from)g(and)h(if)g(your)g(CPU)g(is)286 2401 y(either)f(really)h(slow)f (or)h(really)f(heavily)g(loaded.)0 2815 y Fj(On)30 b(HP/UX)i(systems,)g (the)f(en)m(vironmen)m(t)h(v)-5 b(ariable)32 b(CFLA)m(GS)f(should)f(b)s (e)h(set)g(to)h(-Ae)g(b)s(efore)f(running)e(con-)0 2928 y(\014gure)h(to)h(enable)g("extended)g(ANSI")f(features.)0 3088 y(It)j(ma)m(y)g(not)g(b)s(e)f(p)s(ossible)g(to)h(statically)i (link)e(programs)f(that)h(use)g(CFITSIO)e(on)h(some)h(platforms)g (\(namely)-8 b(,)0 3201 y(on)28 b(Solaris)h(2.6\))h(due)e(to)h(the)g (net)m(w)m(ork)g(driv)m(ers)f(\(whic)m(h)h(pro)m(vide)g(FTP)f(and)g (HTTP)g(access)h(to)h(FITS)d(\014les\).)41 b(It)0 3314 y(is)33 b(p)s(ossible)f(to)i(mak)m(e)f(b)s(oth)g(a)g(dynamic)f(and)g(a) i(static)g(v)m(ersion)f(of)g(the)g(CFITSIO)e(library)-8 b(,)34 b(but)e(net)m(w)m(ork)i(\014le)0 3427 y(access)e(will)e(not)h(b) s(e)f(p)s(ossible)g(using)g(the)g(static)i(v)m(ersion.)0 3587 y(On)c(V)-10 b(AX/VMS)31 b(and)d(ALPHA/VMS)i(systems)f(the)h(mak)m (e)p 2100 3587 28 4 v 34 w(g\015oat.com)h(command)e(\014le)g(ma)m(y)h (b)s(e)f(executed)h(to)0 3700 y(build)35 b(the)i(c\014tsio.olb)g(ob)5 b(ject)37 b(library)f(using)g(the)g(default)h(G-\015oating)g(p)s(oin)m (t)g(option)f(for)g(double)g(v)-5 b(ariables.)0 3813 y(The)37 b(mak)m(e)p 405 3813 V 33 w(d\015oat.com)i(and)d(mak)m(e)p 1279 3813 V 34 w(ieee.com)j(\014les)f(ma)m(y)f(b)s(e)g(used)f(instead)i (to)g(build)e(the)h(library)g(with)g(the)0 3926 y(other)26 b(\015oating)i(p)s(oin)m(t)e(options.)39 b(Note)28 b(that)f(the)f (getcwd)h(function)f(that)h(is)f(used)f(in)h(the)h(group.c)f(mo)s(dule) f(ma)m(y)0 4039 y(require)44 b(that)i(programs)e(using)g(CFITSIO)f(b)s (e)h(link)m(ed)i(with)e(the)h(ALPHA$LIBRAR)-8 b(Y:V)e(AX)m(CR)i(TL.OLB) 0 4152 y(library)g(.)41 b(See)30 b(the)h(example)g(link)f(line)h(in)f (the)h(next)f(section)i(of)e(this)h(do)s(cumen)m(t.)0 4312 y(On)25 b(Windo)m(ws)h(IBM-PC)g(t)m(yp)s(e)g(platforms)f(the)h (situation)h(is)e(more)h(complicated)i(b)s(ecause)d(of)h(the)g(wide)g (v)-5 b(ariet)m(y)0 4425 y(of)43 b(F)-8 b(ortran)43 b(compilers)h(that) f(are)g(a)m(v)-5 b(ailable)45 b(and)d(b)s(ecause)h(of)g(the)g(inheren)m (t)g(complexities)i(of)d(calling)j(the)0 4538 y(CFITSIO)25 b(C)g(routines)h(from)g(F)-8 b(ortran.)40 b(Tw)m(o)26 b(di\013eren)m(t)h(v)m(ersions)f(of)g(the)h(CFITSIO)d(dll)i(library)g (are)g(a)m(v)-5 b(ailable,)0 4650 y(compiled)28 b(with)e(the)i(Borland) f(C++)f(compiler)i(and)e(the)i(Microsoft)g(Visual)g(C++)e(compiler,)i (resp)s(ectiv)m(ely)-8 b(,)30 b(in)0 4763 y(the)g(\014les)g(c\014tsio)s (dll)p 679 4763 V 33 w(2xxx)p 901 4763 V 34 w(b)s(orland.zip)f(and)g (c\014tsio)s(dll)p 1924 4763 V 33 w(3xxx)p 2146 4763 V 33 w(v)m(cc.zip,)j(where)e('3xxx')h(represen)m(ts)f(the)g(curren)m(t) 0 4876 y(release)44 b(n)m(um)m(b)s(er.)76 b(Both)43 b(these)g(dll)g (libraries)g(con)m(tain)h(a)f(set)g(of)f(F)-8 b(ortran)44 b(wrapp)s(er)d(routines)h(whic)m(h)g(ma)m(y)0 4989 y(b)s(e)37 b(compatible)i(with)e(some,)j(but)d(probably)g(not)g(all,)k(a)m(v)-5 b(ailable)40 b(F)-8 b(ortran)38 b(compilers.)63 b(T)-8 b(o)38 b(test)g(if)g(they)g(are)0 5102 y(compatible,)29 b(compile)f(the)f(program)g(testf77.f)h(and)f(try)f(linking)i(to)f (these)h(dll)e(libraries.)40 b(If)27 b(these)g(libraries)g(do)0 5215 y(not)22 b(w)m(ork)g(with)g(a)g(particular)g(F)-8 b(ortran)22 b(compiler,)j(then)c(it)i(ma)m(y)f(b)s(e)f(necessary)i(to)f (mo)s(dify)f(the)h(\014le)g("cfortran.h")0 5328 y(to)28 b(supp)s(ort)d(that)j(particular)f(com)m(bination)i(of)e(C)g(and)f(F)-8 b(ortran)28 b(compilers,)h(and)d(then)h(rebuild)f(the)h(CFITSIO)0 5441 y(dll)j(library)-8 b(.)41 b(This)30 b(will)g(require,)h(ho)m(w)m (ev)m(er,)h(some)e(exp)s(ertise)h(in)f(mixed)g(language)i(programming.) 0 5601 y(CFITSIO)f(should)g(b)s(e)g(compatible)j(with)d(most)i(curren)m (t)f(ANCI)g(C)f(and)h(C++)f(compilers:)44 b(Cra)m(y)33 b(sup)s(ercom-)0 5714 y(puters)d(are)g(curren)m(tly)h(not)f(supp)s (orted.)p eop end %%Page: 6 12 TeXDict begin 6 11 bop 0 299 a Fj(6)1896 b Fh(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y Fe(2.2)135 b(T)-11 b(esting)46 b(the)f(Library)0 805 y Fj(The)40 b(CFITSIO)e(library)i(should)f(b)s(e)g(tested)i(b)m(y)f (building)f(and)g(running)g(the)h(testprog.c)h(program)f(that)h(is)0 918 y(included)30 b(with)g(the)g(release.)42 b(On)30 b(Unix)g(systems)g(t)m(yp)s(e:)191 1154 y Ff(\045)47 b(make)g(testprog)191 1267 y(\045)g(testprog)f(>)h(testprog.lis)191 1380 y(\045)g(diff)g(testprog.lis)d(testprog.out)191 1493 y(\045)j(cmp)g(testprog.fit)e(testprog.std)0 1729 y Fj(On)30 b(VMS)g(systems,)g(\(assuming)h(cc)g(is)f(the)h(name)f(of)h (the)f(C)g(compiler)h(command\),)g(t)m(yp)s(e:)191 1965 y Ff($)47 b(cc)h(testprog.c)191 2078 y($)f(link)g(testprog,)e (cfitsio/lib,)g(alpha$library:vaxcrtl/l)o(ib)191 2191 y($)i(run)g(testprog)0 2427 y Fj(The)30 b(testprog)h(program)g(should)e (pro)s(duce)g(a)i(FITS)f(\014le)g(called)i(`testprog.\014t')g(that)f (is)f(iden)m(tical)j(to)e(the)f(`test-)0 2540 y(prog.std')25 b(FITS)f(\014le)g(included)g(with)g(this)h(release.)40 b(The)24 b(diagnostic)i(messages)g(\(whic)m(h)e(w)m(ere)h(pip)s(ed)f (to)h(the)g(\014le)0 2653 y(testprog.lis)h(in)e(the)h(Unix)f(example\)) i(should)d(b)s(e)h(iden)m(tical)j(to)e(the)g(listing)g(con)m(tained)h (in)e(the)h(\014le)f(testprog.out.)0 2766 y(The)30 b('di\013)7 b(')31 b(and)e('cmp')i(commands)f(sho)m(wn)g(ab)s(o)m(v)m(e)h(should)f (not)g(rep)s(ort)g(an)m(y)h(di\013erences)g(in)f(the)g(\014les.)41 b(\(There)0 2879 y(ma)m(y)35 b(b)s(e)e(some)h(minor)g(formatting)g (di\013erences,)i(suc)m(h)d(as)i(the)f(presence)g(or)g(absence)g(of)g (leading)h(zeros,)h(or)e(3)0 2992 y(digit)d(exp)s(onen)m(ts)f(in)g(n)m (um)m(b)s(ers,)g(whic)m(h)g(can)g(b)s(e)g(ignored\).)0 3152 y(The)f(F)-8 b(ortran)31 b(wrapp)s(ers)d(in)h(CFITSIO)f(ma)m(y)j (b)s(e)e(tested)h(with)g(the)g(testf77)h(program.)40 b(On)29 b(Unix)h(systems)g(the)0 3265 y(F)-8 b(ortran)31 b(compiler)g(is)f(t)m(ypically)j(called)e('gfortran'.)42 b(-)143 3501 y Ff(\045)48 b(gfortran)d(-o)i(testf77)f(testf77.f)f(-L.)i (-lcfitsio)f(-lz)h(-lcurl)143 3614 y(\045)h(testf77)d(>)j(testf77.lis) 143 3727 y(\045)g(diff)e(testf77.lis)f(testf77.out)143 3840 y(\045)j(cmp)f(testf77.fit)d(testf77.std)0 4076 y Fj(On)31 b(mac)m(hines)h(running)f(SUN)g(O/S,)h(F)-8 b(ortran)33 b(programs)e(m)m(ust)h(b)s(e)f(compiled)h(with)g(the)g('-f) 7 b(')32 b(option)h(to)f(force)0 4189 y(double)24 b(precision)g(v)-5 b(ariables)25 b(to)g(b)s(e)e(aligned)i(on)f(8-b)m(yte)i(b)s(oundaries)c (to)j(mak)m(e)g(the)g(fortran-declared)f(v)-5 b(ariables)0 4301 y(compatible)34 b(with)e(C.)g(A)h(similar)g(compiler)g(option)g (ma)m(y)g(b)s(e)f(required)g(on)g(other)h(platforms.)48 b(F)-8 b(ailing)34 b(to)f(use)0 4414 y(this)26 b(option)g(ma)m(y)g (cause)h(the)f(program)f(to)i(crash)e(on)h(FITSIO)f(routines)g(that)i (read)f(or)f(write)h(double)g(precision)0 4527 y(v)-5 b(ariables.)0 4687 y(On)27 b(Windo)m(ws)h(platforms,)g(linking)g(F)-8 b(ortran)28 b(programs)f(with)h(a)g(C)f(library)g(often)h(dep)s(ends)e (on)i(the)g(particular)0 4800 y(compilers)40 b(in)m(v)m(olv)m(ed.)71 b(Some)40 b(users)f(ha)m(v)m(e)i(found)d(the)i(follo)m(wing)i(commands) d(w)m(ork)h(when)f(using)g(the)h(In)m(tel)0 4913 y(F)-8 b(ortran)31 b(compiler:)0 5149 y Ff(ifort)46 b(/libs.dll)g(cfitsio.lib) e(/MD)j(testf77.f)f(/Gm)0 5375 y(or)h(possibly,)0 5601 y(ifort)f(/libs:dll)g(cfitsio.lib)e(/MD)j(/fpp)g (/extfpp:cfortran.h,fitsi)o(o.h)191 5714 y(/iface:cvf)e(testf77.f)p eop end %%Page: 7 13 TeXDict begin 7 12 bop 0 299 a Fh(2.3.)72 b(LINKING)30 b(PR)m(OGRAMS)h(WITH)f(FITSIO)2041 b Fj(7)0 555 y(Also)32 b(note)h(that)f(on)g(some)g(systems)f(the)h(output)g(listing)g(of)g (the)g(testf77)h(program)f(ma)m(y)g(di\013er)f(sligh)m(tly)i(from)0 668 y(the)f(testf77.std)i(template)g(if)e(leading)h(zeros)g(are)g(not)g (prin)m(ted)e(b)m(y)i(default)f(b)s(efore)g(the)g(decimal)i(p)s(oin)m (t)e(when)0 781 y(using)e(F)h(format.)0 941 y(A)f(few)h(other)f(utilit) m(y)i(programs)e(are)h(included)e(with)h(CFITSIO:)191 1216 y Ff(speed)46 b(-)i(measures)d(the)i(maximum)f(throughput)f(\(in)i (MB)g(per)g(second\))668 1329 y(for)g(writing)f(and)h(reading)f(FITS)g (files)h(with)f(CFITSIO)191 1555 y(listhead)f(-)j(lists)e(all)h(the)g (header)f(keywords)g(in)h(any)g(FITS)f(file)191 1780 y(fitscopy)f(-)j(copies)e(any)h(FITS)g(file)f(\(especially)f(useful)h (in)h(conjunction)811 1893 y(with)g(the)g(CFITSIO's)e(extended)h(input) g(filename)g(syntax\))191 2119 y(cookbook)f(-)j(a)f(sample)f(program)g (that)h(performs)e(common)i(read)f(and)811 2232 y(write)h(operations)e (on)i(a)g(FITS)g(file.)191 2458 y(iter_a,)f(iter_b,)g(iter_c)g(-)h (examples)f(of)h(the)g(CFITSIO)f(iterator)f(routine)0 2733 y Fj(The)30 b(\014rst)f(4)i(of)g(these)g(utilit)m(y)g(programs)f (can)h(b)s(e)f(compiled)h(and)e(link)m(ed)i(b)m(y)f(t)m(yping)143 3007 y Ff(\045)95 b(make)47 b(program_name)0 3359 y Fe(2.3)135 b(Linking)45 b(Programs)h(with)f(FITSIO)0 3612 y Fj(When)31 b(linking)g(applications)i(soft)m(w)m(are)f(with)f(the)g(FITSIO)f (library)-8 b(,)32 b(sev)m(eral)h(system)e(libraries)g(usually)g(need)0 3725 y(to)26 b(b)s(e)f(sp)s(eci\014ed)g(on)g(the)h(link)g(comman)f (Unix)h(systems,)h(the)e(most)h(reliable)h(w)m(a)m(y)f(to)h(determine)e (what)h(libraries)0 3838 y(are)32 b(required)f(is)g(to)i(t)m(yp)s(e)e ('mak)m(e)i(testprog')g(and)e(see)h(what)f(libraries)h(the)g (con\014gure)f(script)h(has)f(added.)43 b(The)0 3951 y(t)m(ypical)25 b(libraries)f(that)g(ma)m(y)g(need)f(to)h(b)s(e)f (added)g(are)g(-lm)h(\(the)g(math)f(library\))h(and)f(-lnsl)g(and)g (-lso)s(c)m(k)m(et)j(\(needed)0 4064 y(only)h(for)f(FTP)g(and)g(HTTP)g (\014le)h(access\).)41 b(These)26 b(latter)i(2)f(libraries)g(are)g(not) g(needed)f(on)g(VMS)h(and)f(Windo)m(ws)0 4177 y(platforms,)31 b(b)s(ecause)f(FTP)g(\014le)h(access)g(is)g(not)f(curren)m(tly)h(supp)s (orted)d(on)i(those)h(platforms.)0 4337 y(Note)i(that)g(when)e (upgrading)g(to)i(a)f(new)m(er)g(v)m(ersion)g(of)g(CFITSIO)f(it)h(is)g (usually)g(necessary)g(to)h(recompile,)h(as)0 4450 y(w)m(ell)d(as)g (relink,)g(the)f(programs)g(that)h(use)f(CFITSIO,)f(b)s(ecause)i(the)f (de\014nitions)g(in)g(\014tsio.h)h(often)f(c)m(hange.)0 4801 y Fe(2.4)135 b(Getting)46 b(Started)g(with)f(FITSIO)0 5055 y Fj(In)32 b(order)h(to)h(e\013ectiv)m(ely)i(use)d(the)g(FITSIO)f (library)h(as)h(quic)m(kly)g(as)f(p)s(ossible,)h(it)g(is)f(recommended) g(that)g(new)0 5168 y(users)d(follo)m(w)h(these)g(steps:)0 5328 y(1.)62 b(Read)38 b(the)f(follo)m(wing)i(`FITS)e(Primer')g(c)m (hapter)h(for)g(a)f(brief)g(o)m(v)m(erview)i(of)f(the)g(structure)e(of) i(FITS)f(\014les.)0 5441 y(This)25 b(is)h(esp)s(ecially)h(imp)s(ortan)m (t)g(for)e(users)h(who)f(ha)m(v)m(e)i(not)g(previously)e(dealt)i(with)f (the)g(FITS)f(table)i(and)f(image)0 5554 y(extensions.)0 5714 y(2.)41 b(W)-8 b(rite)32 b(a)f(simple)f(program)g(to)h(read)g(or)f (write)g(a)h(FITS)f(\014le)g(using)g(the)h(Basic)g(In)m(terface)h (routines.)p eop end %%Page: 8 14 TeXDict begin 8 13 bop 0 299 a Fj(8)1896 b Fh(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y Fj(3.)41 b(Refer)28 b(to)i(the)f(co)s(okb)s(o)s(ok.f)g(program)f(that)i (is)f(included)f(with)g(this)h(release)h(for)e(examples)i(of)f (routines)f(that)0 668 y(p)s(erform)h(v)-5 b(arious)30 b(common)h(FITS)f(\014le)g(op)s(erations.)0 828 y(4.)52 b(Read)34 b(Chapters)g(4)g(and)f(5)i(to)g(b)s(ecome)f(familiar)h(with)e (the)i(con)m(v)m(en)m(tions)h(and)d(adv)-5 b(anced)34 b(features)h(of)f(the)0 941 y(FITSIO)29 b(in)m(terface.)0 1101 y(5.)47 b(Scan)32 b(through)f(the)h(more)h(extensiv)m(e)g(set)g (of)g(routines)f(that)g(are)h(pro)m(vided)f(in)g(the)g(`Adv)-5 b(anced)32 b(In)m(terface'.)0 1214 y(These)22 b(routines)f(p)s(erform)g (more)h(sp)s(ecialized)h(functions)e(than)g(are)i(pro)m(vided)e(b)m(y)h (the)g(Basic)h(In)m(terface)g(routines.)0 1569 y Fe(2.5)135 b(Example)46 b(Program)0 1823 y Fj(The)32 b(follo)m(wing)i(listing)f (sho)m(ws)f(an)g(example)i(of)e(ho)m(w)h(to)g(use)f(the)g(FITSIO)g (routines)g(in)g(a)h(F)-8 b(ortran)33 b(program.)0 1936 y(Refer)38 b(to)h(the)g(co)s(okb)s(o)s(ok.f)f(program)g(that)h(is)f (included)f(with)h(the)h(FITSIO)e(distribution)g(for)h(examples)h(of)0 2049 y(other)31 b(FITS)e(programs.)286 2327 y Ff(program)46 b(writeimage)0 2552 y(C)238 b(Create)46 b(a)i(FITS)f(primary)e(array)i (containing)e(a)i(2-D)g(image)286 2778 y(integer)f (status,unit,blocksize,bit)o(pix,)o(nax)o(is,n)o(axes)o(\(2\))286 2891 y(integer)g(i,j,group,fpixel,nelement)o(s,ar)o(ray)o(\(300)o(,200) o(\))286 3004 y(character)g(filename*80)286 3117 y(logical)g (simple,extend)286 3343 y(status=0)0 3456 y(C)238 b(Name)47 b(of)g(the)g(FITS)g(file)f(to)i(be)f(created:)286 3569 y(filename='ATESTFILE.FITS')0 3794 y(C)238 b(Get)47 b(an)g(unused)g (Logical)e(Unit)i(Number)f(to)h(use)g(to)g(create)f(the)h(FITS)g(file) 286 3907 y(call)g(ftgiou\(unit,status\))0 4133 y(C)238 b(create)46 b(the)h(new)g(empty)g(FITS)f(file)286 4246 y(blocksize=1)286 4359 y(call)h(ftinit\(unit,filename,blo)o(cksi)o (ze,s)o(tat)o(us\))0 4585 y(C)238 b(initialize)45 b(parameters)g(about) i(the)g(FITS)f(image)h(\(300)f(x)i(200)f(16-bit)f(integers\))286 4698 y(simple=.true.)286 4811 y(bitpix=16)286 4924 y(naxis=2)286 5036 y(naxes\(1\)=300)286 5149 y(naxes\(2\)=200)286 5262 y(extend=.true.)0 5488 y(C)238 b(write)47 b(the)g(required)e(header)h (keywords)286 5601 y(call)h(ftphpr\(unit,simple,bitpi)o(x,na)o(xis,)o (nax)o(es,0)o(,1,e)o(xte)o(nd,s)o(tatu)o(s\))p eop end %%Page: 9 15 TeXDict begin 9 14 bop 0 299 a Fh(2.6.)72 b(LEGAL)30 b(STUFF)2995 b Fj(9)0 555 y Ff(C)238 b(initialize)45 b(the)i(values)f(in)i(the)e(image)h(with)f(a)i(linear)e(ramp)h (function)286 668 y(do)h(j=1,naxes\(2\))477 781 y(do)f(i=1,naxes\(1\)) 668 894 y(array\(i,j\)=i+j)477 1007 y(end)g(do)286 1120 y(end)g(do)0 1346 y(C)238 b(write)47 b(the)g(array)f(to)h(the)g(FITS)g (file)286 1458 y(group=1)286 1571 y(fpixel=1)286 1684 y(nelements=naxes\(1\)*naxes\(2)o(\))286 1797 y(call)g (ftpprj\(unit,group,fpixel)o(,nel)o(emen)o(ts,)o(arra)o(y,st)o(atu)o (s\))0 2023 y(C)238 b(write)47 b(another)f(optional)f(keyword)h(to)h (the)g(header)286 2136 y(call)g(ftpkyj\(unit,'EXPOSURE',1)o(500,)o ('Tot)o(al)41 b(Exposure)46 b(Time',status\))0 2362 y(C)238 b(close)47 b(the)g(file)f(and)h(free)g(the)g(unit)f(number)286 2475 y(call)h(ftclos\(unit,)d(status\))286 2588 y(call)j(ftfiou\(unit,) d(status\))286 2700 y(end)0 3059 y Fe(2.6)135 b(Legal)46 b(Stu\013)0 3314 y Fj(Cop)m(yrigh)m(t)37 b(\(Unpublished{all)g(righ)m (ts)g(reserv)m(ed)g(under)e(the)i(cop)m(yrigh)m(t)h(la)m(ws)f(of)g(the) g(United)g(States\),)j(U.S.)0 3427 y(Go)m(v)m(ernmen)m(t)30 b(as)g(represen)m(ted)e(b)m(y)h(the)g(Administrator)g(of)g(the)g (National)h(Aeronautics)g(and)e(Space)h(Adminis-)0 3540 y(tration.)42 b(No)31 b(cop)m(yrigh)m(t)g(is)g(claimed)g(in)f(the)h (United)f(States)h(under)e(Title)j(17,)f(U.S.)f(Co)s(de.)0 3700 y(P)m(ermission)g(to)g(freely)f(use,)h(cop)m(y)-8 b(,)31 b(mo)s(dify)-8 b(,)29 b(and)g(distribute)g(this)g(soft)m(w)m (are)i(and)e(its)h(do)s(cumen)m(tation)g(without)0 3813 y(fee)f(is)f(hereb)m(y)g(gran)m(ted,)i(pro)m(vided)e(that)h(this)f(cop) m(yrigh)m(t)i(notice)f(and)f(disclaimer)h(of)f(w)m(arran)m(t)m(y)i(app) s(ears)d(in)h(all)0 3926 y(copies.)0 4086 y(DISCLAIMER:)0 4246 y(THE)33 b(SOFTW)-10 b(ARE)32 b(IS)g(PR)m(O)m(VIDED)i('AS)f(IS')g (WITHOUT)f(ANY)i(W)-10 b(ARRANTY)33 b(OF)g(ANY)h(KIND,)f(EI-)0 4359 y(THER)42 b(EXPRESSED,)f(IMPLIED,)i(OR)e(ST)-8 b(A)g(TUTOR)g(Y,)43 b(INCLUDING,)f(BUT)h(NOT)e(LIMITED)h(TO,)0 4472 y(ANY)33 b(W)-10 b(ARRANTY)33 b(THA)-8 b(T)32 b(THE)g(SOFTW)-10 b(ARE)32 b(WILL)g(CONF)m(ORM)g(TO)g(SPECIFICA)-8 b(TIONS,)30 b(ANY)0 4585 y(IMPLIED)38 b(W)-10 b(ARRANTIES)37 b(OF)h(MER)m(CHANT)-8 b(ABILITY,)38 b(FITNESS)f(F)m(OR)h(A)g(P)-8 b(AR)g(TICULAR)38 b(PUR-)0 4698 y(POSE,)24 b(AND)i(FREEDOM)f(FR)m(OM)h(INFRINGEMENT,)g (AND)f(ANY)h(W)-10 b(ARRANTY)25 b(THA)-8 b(T)25 b(THE)g(DOC-)0 4811 y(UMENT)-8 b(A)g(TION)31 b(WILL)f(CONF)m(ORM)h(TO)e(THE)h(SOFTW) -10 b(ARE,)30 b(OR)g(ANY)h(W)-10 b(ARRANTY)31 b(THA)-8 b(T)30 b(THE)0 4924 y(SOFTW)-10 b(ARE)31 b(WILL)h(BE)g(ERR)m(OR)g (FREE.)g(IN)g(NO)g(EVENT)f(SHALL)g(NASA)h(BE)g(LIABLE)g(F)m(OR)g(ANY)0 5036 y(D)m(AMA)m(GES,)26 b(INCLUDING,)e(BUT)f(NOT)g(LIMITED)h(TO,)f (DIRECT,)g(INDIRECT,)g(SPECIAL)f(OR)h(CON-)0 5149 y(SEQUENTIAL)28 b(D)m(AMA)m(GES,)k(ARISING)d(OUT)g(OF,)h(RESUL)-8 b(TING)29 b(FR)m(OM,)h(OR)f(IN)h(ANY)g(W)-10 b(A)i(Y)30 b(CON-)0 5262 y(NECTED)25 b(WITH)g(THIS)f(SOFTW)-10 b(ARE,)25 b(WHETHER)g(OR)g(NOT)g(BASED)g(UPON)g(W)-10 b(ARRANTY,)26 b(CON-)0 5375 y(TRA)m(CT,)d(TOR)-8 b(T)23 b(,)g(OR)g(OTHER)-10 b(WISE,)22 b(WHETHER)i(OR)f(NOT)f(INJUR)-8 b(Y)24 b(W)-10 b(AS)23 b(SUST)-8 b(AINED)23 b(BY)h(PER-)0 5488 y(SONS)h(OR)i(PR)m (OPER)-8 b(TY)26 b(OR)g(OTHER)-10 b(WISE,)26 b(AND)h(WHETHER)g(OR)f (NOT)g(LOSS)f(W)-10 b(AS)26 b(SUST)-8 b(AINED)0 5601 y(FR)m(OM,)37 b(OR)e(AR)m(OSE)h(OUT)f(OF)h(THE)g(RESUL)-8 b(TS)35 b(OF,)h(OR)f(USE)h(OF,)g(THE)g(SOFTW)-10 b(ARE)35 b(OR)g(SER-)0 5714 y(VICES)29 b(PR)m(O)m(VIDED)j(HEREUNDER.")p eop end %%Page: 10 16 TeXDict begin 10 15 bop 0 299 a Fj(10)1851 b Fh(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y Fe(2.7)135 b(Ac)l(kno)l(wledgmen)l(ts)0 904 y Fj(The)29 b(dev)m(elopmen)m(t)h(of)g(man)m(y)f(of)h(the)f(p)s(o)m(w)m(erful)g (features)g(in)g(CFITSIO)f(w)m(as)i(made)f(p)s(ossible)g(through)f (collab-)0 1017 y(orations)35 b(with)f(man)m(y)h(p)s(eople)f(or)h (organizations)h(from)e(around)f(the)i(w)m(orld.)52 b(The)34 b(follo)m(wing,)j(in)d(particular,)0 1129 y(ha)m(v)m(e)e(made)e(esp)s (ecially)i(signi\014can)m(t)f(con)m(tributions:)0 1290 y(Programmers)25 b(from)h(the)f(In)m(tegral)i(Science)g(Data)g(Cen)m (ter,)g(Switzerland)f(\(namely)-8 b(,)28 b(Jurek)c(Bork)m(o)m(wski,)29 b(Bruce)0 1403 y(O'Neel,)34 b(and)e(Don)h(Jennings\),)f(designed)g(the) h(concept)g(for)f(the)h(plug-in)f(I/O)g(driv)m(ers)g(that)h(w)m(as)g (in)m(tro)s(duced)0 1515 y(with)i(CFITSIO)e(2.0.)56 b(The)34 b(use)h(of)g(`driv)m(ers')g(greatly)h(simpli\014ed)f(the)g(lo)m(w-lev)m (el)j(I/O,)d(whic)m(h)f(in)h(turn)f(made)0 1628 y(other)40 b(new)f(features)i(in)e(CFITSIO)f(\(e.g.,)45 b(supp)s(ort)38 b(for)h(compressed)h(FITS)f(\014les)h(and)f(supp)s(ort)f(for)i(IRAF)0 1741 y(format)32 b(image)g(\014les\))g(m)m(uc)m(h)f(easier)i(to)f (implemen)m(t.)44 b(Jurek)31 b(Bork)m(o)m(wski)h(wrote)g(the)g(Shared)e (Memory)i(driv)m(er,)0 1854 y(and)23 b(Bruce)i(O'Neel)g(wrote)f(the)g (driv)m(ers)g(for)f(accessing)j(FITS)d(\014les)h(o)m(v)m(er)h(the)f (net)m(w)m(ork)h(using)e(the)i(FTP)-8 b(,)24 b(HTTP)-8 b(,)0 1967 y(and)30 b(R)m(OOT)g(proto)s(cols.)0 2127 y(The)45 b(ISDC)g(also)h(pro)m(vided)f(the)h(template)h(parsing)e (routines)g(\(written)h(b)m(y)f(Jurek)g(Bork)m(o)m(wski\))i(and)e(the)0 2240 y(hierarc)m(hical)39 b(grouping)d(routines)h(\(written)h(b)m(y)f (Don)h(Jennings\).)60 b(The)37 b(ISDC)f(D)m(AL)i(\(Data)h(Access)f(La)m (y)m(er\))0 2353 y(routines)30 b(are)h(la)m(y)m(ered)h(on)e(top)h(of)f (CFITSIO)f(and)h(mak)m(e)h(extensiv)m(e)h(use)e(of)h(these)g(features.) 0 2513 y(Uw)m(e)25 b(Lammers)e(\(XMM/ESA/ESTEC,)h(The)g(Netherlands\))g (designed)g(the)g(high-p)s(erformance)f(lexical)j(pars-)0 2626 y(ing)42 b(algorithm)h(that)f(is)g(used)f(to)i(do)e(on-the-\015y)h (\014ltering)g(of)g(FITS)f(tables.)76 b(This)41 b(algorithm)i(essen)m (tially)0 2739 y(pre-compiles)36 b(the)g(user-supplied)e(selection)k (expression)d(in)m(to)i(a)f(form)g(that)g(can)g(b)s(e)f(rapidly)g(ev)-5 b(aluated)37 b(for)0 2852 y(eac)m(h)31 b(ro)m(w.)40 b(P)m(eter)31 b(Wilson)f(\(RSTX,)f(NASA/GSF)m(C\))i(then)e(wrote)h(the)g(parsing)f (routines)g(used)g(b)m(y)g(CFITSIO)0 2965 y(based)i(on)f(Lammers')h (design,)g(com)m(bined)g(with)g(other)g(tec)m(hniques)g(suc)m(h)g(as)g (the)g(CFITSIO)f(iterator)i(routine)0 3078 y(to)g(further)e(enhance)h (the)h(data)g(pro)s(cessing)f(throughput.)42 b(This)31 b(e\013ort)h(also)g(b)s(ene\014ted)e(from)h(a)h(m)m(uc)m(h)f(earlier)0 3191 y(lexical)25 b(parsing)f(routine)f(that)h(w)m(as)g(dev)m(elop)s (ed)g(b)m(y)g(Ken)m(t)g(Blac)m(kburn)f(\(NASA/GSF)m(C\).)i(More)g (recen)m(tly)-8 b(,)27 b(Craig)0 3304 y(Markw)m(ardt)i(\(NASA/GSF)m (C\))g(implemen)m(ted)g(additional)g(functions)f(\(median,)h(a)m(v)m (erage,)j(stddev\))c(and)g(other)0 3416 y(enhancemen)m(ts)j(to)g(the)g (lexical)h(parser.)0 3577 y(The)40 b(CFITSIO)g(iterator)i(function)e (is)h(lo)s(osely)h(based)f(on)f(similar)i(ideas)f(dev)m(elop)s(ed)g (for)g(the)g(XMM)g(Data)0 3690 y(Access)31 b(La)m(y)m(er.)0 3850 y(P)m(eter)25 b(Wilson)g(\(RSTX,)f(NASA/GSF)m(C\))h(wrote)g(the)f (complete)i(set)e(of)h(F)-8 b(ortran-callable)27 b(wrapp)s(ers)22 b(for)i(all)h(the)0 3963 y(CFITSIO)k(routines,)h(whic)m(h)g(in)g(turn)g (rely)g(on)h(the)f(CF)m(OR)-8 b(TRAN)31 b(macro)g(dev)m(elop)s(ed)g(b)m (y)f(Burkhard)f(Buro)m(w.)0 4123 y(The)h(syn)m(tax)i(used)e(b)m(y)h (CFITSIO)f(for)g(\014ltering)i(or)f(binning)e(input)h(FITS)h(\014les)g (is)g(based)f(on)h(ideas)h(dev)m(elop)s(ed)0 4236 y(for)41 b(the)g(AXAF)h(Science)g(Cen)m(ter)g(Data)h(Mo)s(del)e(b)m(y)g (Jonathan)g(McDo)m(w)m(ell,)47 b(An)m(tonella)c(F)-8 b(ruscione,)45 b(Aneta)0 4349 y(Siemigino)m(wsk)-5 b(a)27 b(and)e(Bill)i(Jo)m(y)m(e.)41 b(See)26 b(h)m (ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/journal/axa)q(f7.h)m(t)q(ml)32 b(for)25 b(further)0 4461 y(description)30 b(of)h(the)g(AXAF)g(Data)h (Mo)s(del.)0 4622 y(The)j(\014le)g(decompression)g(co)s(de)g(w)m(ere)h (tak)m(en)g(directly)g(from)e(the)i(gzip)f(\(GNU)h(zip\))g(program)f (dev)m(elop)s(ed)g(b)m(y)0 4735 y(Jean-loup)30 b(Gailly)i(and)e (others.)0 4895 y(Doug)h(Mink,)g(SA)m(O,)f(pro)m(vided)g(the)h (routines)f(for)g(con)m(v)m(erting)i(IRAF)f(format)g(images)g(in)m(to)g (FITS)f(format.)0 5055 y(Martin)j(Reinec)m(k)m(e)i(\(Max)f(Planc)m(k)f (Institute,)h(Garc)m(hing\)\))g(pro)m(vided)f(the)g(mo)s(di\014cations) f(to)i(cfortran.h)e(that)0 5168 y(are)d(necessary)h(to)f(supp)s(ort)e (64-bit)k(in)m(teger)f(v)-5 b(alues)29 b(when)f(calling)i(C)f(routines) g(from)f(fortran)h(programs.)39 b(The)0 5281 y(cfortran.h)30 b(macros)h(w)m(ere)g(originally)h(dev)m(elop)s(ed)e(b)m(y)h(Burkhard)e (Buro)m(w)h(\(CERN\).)0 5441 y(Julian)f(T)-8 b(a)m(ylor)31 b(\(ESO,)e(Garc)m(hing\))i(pro)m(vided)e(the)g(fast)h(b)m(yte-sw)m (apping)g(algorithms)h(that)f(use)f(the)h(SSE2)f(and)0 5554 y(SSSE3)g(mac)m(hine)i(instructions)f(a)m(v)-5 b(ailable)33 b(on)d(x86)p 1784 5554 28 4 v 34 w(64)h(CPUs.)0 5714 y(In)c(addition,)i(man)m(y)f(other)g(p)s(eople)g(ha)m(v)m(e)h(made)f(v) -5 b(aluable)29 b(con)m(tributions)f(to)h(the)f(dev)m(elopmen)m(t)h(of) f(CFITSIO.)p eop end %%Page: 11 17 TeXDict begin 11 16 bop 0 299 a Fh(2.7.)72 b(A)m(CKNO)m(WLEDGMENTS)2577 b Fj(11)0 555 y(These)30 b(include)g(\(with)h(ap)s(ologies)h(to)f (others)f(that)h(ma)m(y)g(ha)m(v)m(e)h(inadv)m(erten)m(tly)g(b)s(een)d (omitted\):)0 715 y(Stev)m(e)g(Allen,)g(Carl)f(Ak)m(erlof,)h(Keith)f (Arnaud,)g(Morten)g(Krabb)s(e)e(Barfo)s(ed,)j(Ken)m(t)f(Blac)m(kburn,)h (G)f(Bo)s(dammer,)0 828 y(Romk)m(e)h(Bon)m(tek)m(o)s(e,)i(Lucio)d (Chiapp)s(etti,)g(Keith)g(Costorf,)g(Robin)g(Corb)s(et,)g(John)e(Da)m (vis,)k(Ric)m(hard)e(Fink,)h(Ning)0 941 y(Gan,)g(Emily)e(Greene,)i(Jo)s (e)f(Harrington,)h(Cheng)e(Ho,)i(Phil)e(Ho)s(dge,)i(Jim)f(Ingham,)g(Y) -8 b(oshitak)j(a)29 b(Ishisaki,)f(Diab)0 1054 y(Jerius,)j(Mark)h (Levine,)g(T)-8 b(o)s(dd)30 b(Karak)-5 b(askian,)32 b(Edw)m(ard)f (King,)g(Scott)i(Ko)s(c)m(h,)e(Claire)h(Larkin,)f(Rob)h(Managan,)0 1167 y(Eric)38 b(Mandel,)i(John)d(Matto)m(x,)43 b(Carsten)37 b(Mey)m(er,)42 b(Emi)37 b(Miy)m(ata,)43 b(Stefan)38 b(Mo)s(c)m(hnac)m (ki,)j(Mik)m(e)f(Noble,)g(Oliv)m(er)0 1280 y(Ob)s(erdorf,)c(Cliv)m(e)i (P)m(age,)i(Arvind)35 b(P)m(armar,)j(Je\013)f(P)m(edelt)m(y)-8 b(,)40 b(Tim)c(P)m(earson,)j(Maren)e(Purv)m(es,)h(Scott)f(Randall,)0 1393 y(Chris)d(Rogers,)j(Arnold)e(Rots,)i(Barry)f(Sc)m(hlesinger,)h (Robin)e(Stebbins,)g(Andrew)f(Szymk)m(o)m(wiak,)k(Allyn)e(T)-8 b(en-)0 1506 y(nan)m(t,)31 b(P)m(eter)g(T)-8 b(eub)s(en,)30 b(James)g(Theiler,)h(Doug)g(T)-8 b(o)s(dy)g(,)31 b(Shiro)e(Ueno,)j (Stev)m(e)f(W)-8 b(alton,)33 b(Arc)m(hie)e(W)-8 b(arno)s(c)m(k,)32 b(Alan)0 1619 y(W)-8 b(atson,)32 b(Dan)f(Whipple,)f(Wim)h(Wimmers,)g(P) m(eter)g(Y)-8 b(oung,)31 b(Jianjun)e(Xu,)h(and)g(Nelson)h(Zarate.)p eop end %%Page: 12 18 TeXDict begin 12 17 bop 0 299 a Fj(12)1851 b Fh(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)p eop end %%Page: 13 19 TeXDict begin 13 18 bop 0 1225 a Fg(Chapter)65 b(3)0 1687 y Fm(A)78 b(FITS)f(Primer)0 2180 y Fj(This)23 b(section)j(giv)m (es)f(a)g(brief)e(o)m(v)m(erview)j(of)e(the)h(structure)e(of)i(FITS)e (\014les.)38 b(Users)24 b(should)g(refer)f(to)i(the)g(do)s(cumen-)0 2293 y(tation)33 b(a)m(v)-5 b(ailable)33 b(from)e(the)g(FITS)g(Supp)s (ort)e(O\016ce,)j(as)f(describ)s(ed)f(in)h(the)h(in)m(tro)s(duction,)f (for)g(more)h(detailed)0 2406 y(information)f(on)f(FITS)g(formats.)0 2566 y(FITS)37 b(w)m(as)g(\014rst)g(dev)m(elop)s(ed)h(in)f(the)g(late)i (1970's)g(as)f(a)f(standard)g(data)h(in)m(terc)m(hange)h(format)f(b)s (et)m(w)m(een)g(v)-5 b(ar-)0 2679 y(ious)38 b(astronomical)h(observ)-5 b(atories.)64 b(Since)37 b(then)g(FITS)g(has)h(b)s(ecome)g(the)g (defacto)g(standard)f(data)i(format)0 2791 y(supp)s(orted)29 b(b)m(y)h(most)h(astronomical)h(data)f(analysis)g(soft)m(w)m(are)g(pac) m(k)-5 b(ages.)0 2952 y(A)34 b(FITS)f(\014le)g(consists)h(of)g(one)g (or)g(more)g(Header)g(+)f(Data)i(Units)f(\(HDUs\),)i(where)d(the)h (\014rst)f(HDU)h(is)g(called)0 3065 y(the)j(`Primary)f(HDU',)i(or)f (`Primary)f(Arra)m(y'.)60 b(The)36 b(primary)g(arra)m(y)h(con)m(tains)h (an)e(N-dimensional)i(arra)m(y)f(of)0 3177 y(pixels,)32 b(suc)m(h)g(as)f(a)h(1-D)h(sp)s(ectrum,)e(a)h(2-D)h(image,)g(or)f(a)g (3-D)g(data)h(cub)s(e.)43 b(Six)31 b(di\013eren)m(t)h(primary)f(datat)m (yp)s(es)0 3290 y(are)g(supp)s(orted:)39 b(Unsigned)30 b(8-bit)h(b)m(ytes,)g(16,)g(32,)h(and)e(64-bit)h(signed)g(in)m(tegers,) h(and)d(32)j(and)d(64-bit)j(\015oating)0 3403 y(p)s(oin)m(t)d(reals.)41 b(FITS)29 b(also)i(has)e(a)h(con)m(v)m(en)m(tion)h(for)e(storing)h (unsigned)f(in)m(tegers)h(\(see)h(the)e(later)i(section)f(en)m(titled)0 3516 y(`Unsigned)h(In)m(tegers')h(for)f(more)g(details\).)43 b(The)31 b(primary)f(HDU)i(ma)m(y)f(also)h(consist)g(of)f(only)g(a)g (header)g(with)g(a)0 3629 y(n)m(ull)f(arra)m(y)h(con)m(taining)h(no)e (data)h(pixels.)0 3789 y(An)m(y)i(n)m(um)m(b)s(er)e(of)h(additional)i (HDUs)f(ma)m(y)g(follo)m(w)h(the)e(primary)g(arra)m(y;)i(these)f (additional)h(HDUs)f(are)g(called)0 3902 y(FITS)d(`extensions'.)41 b(There)30 b(are)h(curren)m(tly)f(3)h(t)m(yp)s(es)g(of)f(extensions)h (de\014ned)e(b)m(y)h(the)h(FITS)f(standard:)136 4171 y Fd(\017)46 b Fj(Image)31 b(Extension)g(-)g(a)f(N-dimensional)h(arra)m (y)g(of)g(pixels,)g(lik)m(e)g(in)f(a)h(primary)e(arra)m(y)136 4368 y Fd(\017)46 b Fj(ASCI)s(I)29 b(T)-8 b(able)31 b(Extension)g(-)f (ro)m(ws)h(and)e(columns)h(of)h(data)g(in)f(ASCI)s(I)f(c)m(haracter)j (format)136 4564 y Fd(\017)46 b Fj(Binary)31 b(T)-8 b(able)31 b(Extension)f(-)h(ro)m(ws)f(and)g(columns)g(of)h(data)g(in)f(binary)f (represen)m(tation)0 4833 y(In)k(eac)m(h)i(case)g(the)f(HDU)h(consists) g(of)f(an)g(ASCI)s(I)e(Header)i(Unit)h(follo)m(w)m(ed)g(b)m(y)f(an)g (optional)h(Data)g(Unit.)52 b(F)-8 b(or)0 4946 y(historical)37 b(reasons,)g(eac)m(h)f(Header)g(or)g(Data)h(unit)e(m)m(ust)g(b)s(e)g (an)g(exact)i(m)m(ultiple)f(of)g(2880)h(8-bit)f(b)m(ytes)g(long.)0 5059 y(An)m(y)30 b(un)m(used)g(space)g(is)h(padded)e(with)h(\014ll)g(c) m(haracters)i(\(ASCI)s(I)d(blanks)h(or)h(zeros\).)0 5219 y(Eac)m(h)i(Header)f(Unit)h(consists)g(of)f(an)m(y)g(n)m(um)m(b)s(er)f (of)i(80-c)m(haracter)i(k)m(eyw)m(ord)d(records)g(or)g(`card)h(images') g(whic)m(h)0 5332 y(ha)m(v)m(e)f(the)e(general)i(form:)95 5601 y Ff(KEYNAME)46 b(=)i(value)e(/)i(comment)d(string)95 5714 y(NULLKEY)h(=)334 b(/)48 b(comment:)d(This)i(keyword)f(has)g(no)i (value)1905 5942 y Fj(13)p eop end %%Page: 14 20 TeXDict begin 14 19 bop 0 299 a Fj(14)2398 b Fh(CHAPTER)30 b(3.)112 b(A)30 b(FITS)g(PRIMER)0 555 y Fj(The)35 b(k)m(eyw)m(ord)i (names)f(ma)m(y)g(b)s(e)g(up)f(to)h(8)h(c)m(haracters)g(long)g(and)e (can)h(only)h(con)m(tain)g(upp)s(ercase)e(letters,)k(the)0 668 y(digits)25 b(0-9,)i(the)e(h)m(yphen,)g(and)f(the)h(underscore)e(c) m(haracter.)41 b(The)24 b(k)m(eyw)m(ord)h(name)g(is)f(\(usually\))h (follo)m(w)m(ed)i(b)m(y)d(an)0 781 y(equals)29 b(sign)g(and)f(a)g (space)i(c)m(haracter)g(\(=)e(\))h(in)f(columns)h(9)g(-)f(10)i(of)f (the)f(record,)h(follo)m(w)m(ed)i(b)m(y)d(the)h(v)-5 b(alue)29 b(of)g(the)0 894 y(k)m(eyw)m(ord)34 b(whic)m(h)g(ma)m(y)g(b)s (e)f(either)h(an)g(in)m(teger,)i(a)e(\015oating)g(p)s(oin)m(t)g(n)m(um) m(b)s(er,)g(a)g(c)m(haracter)h(string)e(\(enclosed)i(in)0 1007 y(single)28 b(quotes\),)i(or)e(a)g(b)s(o)s(olean)g(v)-5 b(alue)28 b(\(the)g(letter)h(T)f(or)f(F\).)i(A)f(k)m(eyw)m(ord)g(ma)m (y)h(also)f(ha)m(v)m(e)h(a)g(n)m(ull)e(or)h(unde\014ned)0 1120 y(v)-5 b(alue)31 b(if)f(there)h(is)f(no)g(sp)s(eci\014ed)g(v)-5 b(alue)31 b(string,)g(as)f(in)g(the)h(second)f(example.)0 1280 y(The)c(last)h(k)m(eyw)m(ord)g(in)g(the)f(header)h(is)f(alw)m(a)m (ys)i(the)f(`END')g(k)m(eyw)m(ord)g(whic)m(h)g(has)f(no)g(v)-5 b(alue)27 b(or)g(commen)m(t)g(\014elds.)0 1393 y(There)k(are)g(man)m(y) g(rules)g(go)m(v)m(erning)h(the)g(exact)g(format)g(of)f(a)g(k)m(eyw)m (ord)h(record)f(\(see)h(the)f(FITS)f(Standard\))h(so)0 1506 y(it)c(is)g(b)s(etter)g(to)h(rely)f(on)g(standard)f(in)m(terface)j (soft)m(w)m(are)f(lik)m(e)g(FITSIO)e(to)i(correctly)g(construct)f(or)g (to)h(parse)f(the)0 1619 y(k)m(eyw)m(ord)k(records)f(rather)g(than)g (try)h(to)g(deal)g(directly)g(with)f(the)g(ra)m(w)h(FITS)e(formats.)0 1779 y(Eac)m(h)37 b(Header)g(Unit)f(b)s(egins)g(with)g(a)g(series)h(of) f(required)g(k)m(eyw)m(ords)g(whic)m(h)g(dep)s(end)f(on)h(the)g(t)m(yp) s(e)h(of)f(HDU.)0 1892 y(These)31 b(required)g(k)m(eyw)m(ords)h(sp)s (ecify)g(the)f(size)i(and)e(format)h(of)g(the)g(follo)m(wing)h(Data)g (Unit.)45 b(The)31 b(header)g(ma)m(y)0 2005 y(con)m(tain)h(other)f (optional)g(k)m(eyw)m(ords)g(to)h(describ)s(e)e(other)g(asp)s(ects)h (of)g(the)g(data,)g(suc)m(h)g(as)g(the)f(units)g(or)h(scaling)0 2118 y(v)-5 b(alues.)44 b(Other)31 b(COMMENT)g(or)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)i(are)g(also)g(frequen)m(tly)g(added)e(to)i (further)e(do)s(cumen)m(t)0 2230 y(the)h(data)g(\014le.)0 2391 y(The)36 b(optional)h(Data)h(Unit)f(immediately)g(follo)m(ws)h (the)e(last)h(2880-b)m(yte)i(blo)s(c)m(k)e(in)f(the)g(Header)h(Unit.)59 b(Some)0 2503 y(HDUs)31 b(do)f(not)h(ha)m(v)m(e)g(a)g(Data)h(Unit)f (and)f(only)g(consist)h(of)g(the)f(Header)h(Unit.)0 2664 y(If)24 b(there)i(is)f(more)g(than)f(one)h(HDU)h(in)f(the)g(FITS)f (\014le,)i(then)f(the)g(Header)h(Unit)f(of)g(the)g(next)g(HDU)h (immediately)0 2777 y(follo)m(ws)g(the)e(last)i(2880-b)m(yte)h(blo)s(c) m(k)e(of)g(the)f(previous)g(Data)j(Unit)d(\(or)h(Header)g(Unit)g(if)f (there)h(is)g(no)f(Data)i(Unit\).)0 2937 y(The)k(main)g(required)g(k)m (eyw)m(ords)g(in)g(FITS)g(primary)g(arra)m(ys)g(or)h(image)g (extensions)g(are:)136 3172 y Fd(\017)46 b Fj(BITPIX)33 b({)h(de\014nes)e(the)i(datat)m(yp)s(e)g(of)f(the)g(arra)m(y:)47 b(8,)35 b(16,)g(32,)g(64,)g(-32,)g(-64)g(for)e(unsigned)f(8{bit)i(b)m (yte,)227 3284 y(16{bit)27 b(signed)e(in)m(teger,)i(32{bit)g(signed)e (in)m(teger,)j(64{bit)e(signed)f(in)m(teger,)j(32{bit)e(IEEE)f (\015oating)h(p)s(oin)m(t,)227 3397 y(and)k(64{bit)i(IEEE)e(double)f (precision)i(\015oating)g(p)s(oin)m(t,)g(resp)s(ectiv)m(ely)-8 b(.)136 3585 y Fd(\017)46 b Fj(NAXIS)30 b({)h(the)g(n)m(um)m(b)s(er)e (of)h(dimensions)g(in)g(the)h(arra)m(y)-8 b(,)31 b(usually)f(0,)h(1,)g (2,)g(3,)g(or)g(4.)136 3773 y Fd(\017)46 b Fj(NAXISn)30 b({)h(\(n)f(ranges)g(from)g(1)h(to)g(NAXIS\))g(de\014nes)e(the)i(size)g (of)g(eac)m(h)g(dimension.)0 4008 y(FITS)e(tables)i(start)g(with)f(the) g(k)m(eyw)m(ord)g(XTENSION)g(=)f(`T)-8 b(ABLE')31 b(\(for)f(ASCI)s(I)f (tables\))i(or)f(XTENSION)f(=)0 4120 y(`BINT)-8 b(ABLE')32 b(\(for)e(binary)g(tables\))h(and)f(ha)m(v)m(e)i(the)e(follo)m(wing)i (main)e(k)m(eyw)m(ords:)136 4355 y Fd(\017)46 b Fj(TFIELDS)30 b({)h(n)m(um)m(b)s(er)e(of)h(\014elds)g(or)h(columns)f(in)g(the)g (table)136 4543 y Fd(\017)46 b Fj(NAXIS2)31 b({)g(n)m(um)m(b)s(er)e(of) h(ro)m(ws)h(in)f(the)g(table)136 4731 y Fd(\017)46 b Fj(TTYPEn)29 b({)i(for)f(eac)m(h)i(column)e(\(n)g(ranges)h(from)f(1)g (to)h(TFIELDS\))g(giv)m(es)g(the)g(name)f(of)h(the)f(column)136 4918 y Fd(\017)46 b Fj(TF)m(ORMn)31 b({)f(the)h(datat)m(yp)s(e)g(of)g (the)f(column)136 5106 y Fd(\017)46 b Fj(TUNITn)30 b({)g(the)h(ph)m (ysical)g(units)f(of)g(the)h(column)f(\(optional\))0 5341 y(Users)k(should)f(refer)h(to)h(the)f(FITS)g(Supp)s(ort)e(O\016ce) i(at)h Ff(http://fits.gsfc.nasa.gov)27 b Fj(for)34 b(further)f(infor-)0 5454 y(mation)e(ab)s(out)f(the)h(FITS)e(format)i(and)f(related)h(soft)m (w)m(are)h(pac)m(k)-5 b(ages.)p eop end %%Page: 15 21 TeXDict begin 15 20 bop 0 1225 a Fg(Chapter)65 b(4)0 1687 y Fm(FITSIO)76 b(Con)-6 b(v)g(en)g(tions)76 b(and)h(Guidelines)0 2216 y Fe(4.1)135 b(CFITSIO)44 b(Size)h(Limitations)0 2524 y Fj(CFITSIO)31 b(places)i(few)g(restrictions)g(on)g(the)f(size)i (of)e(FITS)g(\014les)h(that)g(it)g(reads)f(or)h(writes.)47 b(There)32 b(are)h(a)g(few)0 2636 y(limits,)e(ho)m(w)m(ev)m(er,)h(whic) m(h)e(ma)m(y)h(a\013ect)h(some)f(extreme)g(cases:)0 2797 y(1.)43 b(The)31 b(maxim)m(um)g(n)m(um)m(b)s(er)f(of)h(FITS)f(\014les)h (that)h(ma)m(y)g(b)s(e)e(sim)m(ultaneously)i(op)s(ened)f(b)m(y)g (CFITSIO)e(is)i(set)h(b)m(y)0 2910 y(NMAXFILES,)e(as)f(de\014ned)f(in)h (\014tsio2.h.)41 b(The)29 b(curren)m(t)g(default)g(v)-5 b(alue)30 b(is)f(1000,)j(but)c(this)h(ma)m(y)h(b)s(e)f(increased)0 3022 y(if)40 b(necessary)-8 b(.)72 b(Note)42 b(that)f(CFITSIO)e(allo)s (cates)j(NIOBUF)f(*)g(2880)h(b)m(ytes)f(of)g(I/O)f(bu\013er)g(space)h (for)f(eac)m(h)0 3135 y(\014le)d(that)h(is)f(op)s(ened.)61 b(The)37 b(default)g(v)-5 b(alue)38 b(of)f(NIOBUF)h(is)f(40)h (\(de\014ned)f(in)f(\014tsio.h\),)k(so)e(this)f(amoun)m(ts)g(to)0 3248 y(more)31 b(than)g(115K)i(of)e(memory)g(for)g(eac)m(h)i(op)s(ened) d(\014le)i(\(or)f(115)i(MB)f(for)f(1000)i(op)s(ened)d(\014les\).)44 b(Note)33 b(that)f(the)0 3361 y(underlying)k(op)s(erating)i(system,)h (ma)m(y)e(ha)m(v)m(e)i(a)e(lo)m(w)m(er)i(limit)f(on)f(the)g(n)m(um)m(b) s(er)f(of)h(\014les)g(that)h(can)f(b)s(e)g(op)s(ened)0 3474 y(sim)m(ultaneously)-8 b(.)0 3634 y(2.)54 b(By)35 b(default,)h(CFITSIO)d(can)i(handle)g(FITS)f(\014les)g(up)g(to)h(2.1)h (GB)g(in)e(size)i(\(2**31)h(b)m(ytes\).)54 b(This)34 b(\014le)h(size)0 3747 y(limit)41 b(is)g(often)f(imp)s(osed)g(b)m(y)g (32-bit)i(op)s(erating)e(systems.)71 b(More)41 b(recen)m(tly)-8 b(,)45 b(as)c(64-bit)g(op)s(erating)g(systems)0 3860 y(b)s(ecome)33 b(more)g(common,)g(an)g(industry-wide)e(standard)h(\(at) i(least)f(on)g(Unix)f(systems\))h(has)g(b)s(een)f(dev)m(elop)s(ed)0 3973 y(to)39 b(supp)s(ort)d(larger)i(sized)h(\014les)f(\(see)g(h)m (ttp://ftp.sas.com/standards/large.\014le/\).)69 b(Starting)38 b(with)f(v)m(ersion)0 4086 y(2.1)45 b(of)e(CFITSIO,)f(larger)i(FITS)f (\014les)g(up)g(to)h(6)g(terab)m(ytes)h(in)e(size)h(ma)m(y)g(b)s(e)f (read)g(and)g(written)h(on)f(sup-)0 4199 y(p)s(orted)f(platforms.)76 b(In)42 b(order)g(to)h(supp)s(ort)e(these)h(larger)h(\014les,)j (CFITSIO)41 b(m)m(ust)h(b)s(e)g(compiled)h(with)f(the)0 4312 y('-D)p 129 4312 28 4 v 34 w(LAR)m(GEFILE)p 696 4312 V 33 w(SOUR)m(CE')g(and)g(`-D)p 1491 4312 V 34 w(FILE)p 1736 4312 V 33 w(OFFSET)p 2137 4312 V 32 w(BITS=64')h(compiler)g (\015ags.)78 b(Some)43 b(platforms)0 4425 y(ma)m(y)c(also)g(require)f (the)g(`-D)p 1002 4425 V 34 w(LAR)m(GE)p 1358 4425 V 33 w(FILES')g(compiler)h(\015ag.)64 b(This)38 b(causes)g(the)h (compiler)g(to)g(allo)s(cate)h(8-)0 4538 y(b)m(ytes)k(instead)g(of)g (4-b)m(ytes)h(for)f(the)g(`o\013)p 1473 4538 V 33 w(t')g(datat)m(yp)s (e)h(whic)m(h)f(is)f(used)g(to)i(store)f(\014le)g(o\013set)h(p)s (ositions.)81 b(It)0 4650 y(app)s(ears)31 b(that)i(in)e(most)i(cases)g (it)f(is)g(not)g(necessary)h(to)f(also)h(include)f(these)g(compiler)h (\015ags)f(when)f(compiling)0 4763 y(programs)f(that)h(link)f(to)h(the) g(CFITSIO)e(library)-8 b(.)0 4924 y(If)21 b(CFITSIO)e(is)i(compiled)h (with)f(the)g(-D)p 1386 4924 V 33 w(LAR)m(GEFILE)p 1952 4924 V 34 w(SOUR)m(CE)f(and)g(-D)p 2654 4924 V 34 w(FILE)p 2899 4924 V 33 w(OFFSET)p 3300 4924 V 32 w(BITS=64)h(\015ags)0 5036 y(on)36 b(a)g(platform)g(that)g(supp)s(orts)e(large)j(\014les,)h (then)d(it)i(can)f(read)g(and)f(write)h(FITS)f(\014les)h(that)g(con)m (tain)h(up)e(to)0 5149 y(2**31)k(2880-b)m(yte)g(FITS)d(records,)j(or)d (appro)m(ximately)i(6)f(terab)m(ytes)h(in)f(size.)60 b(It)37 b(is)g(still)h(required)d(that)j(the)0 5262 y(v)-5 b(alue)30 b(of)f(the)g(NAXISn)f(and)h(PCOUNT)f(k)m(eyw)m(ords)h(in)g (eac)m(h)h(extension)g(b)s(e)e(within)h(the)g(range)h(of)f(a)g(signed)g (4-)0 5375 y(b)m(yte)c(in)m(teger)h(\(max)f(v)-5 b(alue)26 b(=)e(2,147,483,648\).)44 b(Th)m(us,)25 b(eac)m(h)h(dimension)e(of)h (an)f(image)i(\(giv)m(en)g(b)m(y)f(the)g(NAXISn)0 5488 y(k)m(eyw)m(ords\),)32 b(the)f(total)i(width)d(of)h(a)g(table)h (\(NAXIS1)g(k)m(eyw)m(ord\),)g(the)f(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g (in)f(a)h(table)h(\(NAXIS2)0 5601 y(k)m(eyw)m(ord\),)c(and)d(the)h (total)i(size)f(of)f(the)g(v)-5 b(ariable-length)28 b(arra)m(y)e(heap)g (in)g(binary)f(tables)i(\(PCOUNT)e(k)m(eyw)m(ord\))0 5714 y(m)m(ust)30 b(b)s(e)g(less)h(than)f(this)g(limit.)1905 5942 y(15)p eop end %%Page: 16 22 TeXDict begin 16 21 bop 0 299 a Fj(16)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fj(Curren)m(tly)-8 b(,)31 b(supp)s(ort)e(for)i(large)h(\014les)f (within)f(CFITSIO)f(has)i(b)s(een)f(tested)i(on)f(the)g(Lin)m(ux,)g (Solaris,)g(and)f(IBM)0 668 y(AIX)g(op)s(erating)h(systems.)0 1133 y Fe(4.2)135 b(Multiple)46 b(Access)e(to)i(the)f(Same)g(FITS)f (File)0 1409 y Fj(CFITSIO)35 b(supp)s(orts)g(sim)m(ultaneous)i(read)f (and)g(write)h(access)g(to)h(m)m(ultiple)f(HDUs)g(in)f(the)h(same)g (FITS)f(\014le.)0 1522 y(Th)m(us,)43 b(one)e(can)h(op)s(en)e(the)h (same)h(FITS)e(\014le)h(t)m(wice)i(within)d(a)i(single)f(program)g(and) g(mo)m(v)m(e)h(to)g(2)f(di\013eren)m(t)0 1635 y(HDUs)30 b(in)f(the)h(\014le,)g(and)f(then)g(read)h(and)e(write)i(data)g(or)g(k) m(eyw)m(ords)g(to)g(the)g(2)f(extensions)i(just)d(as)i(if)g(one)f(w)m (ere)0 1748 y(accessing)f(2)f(completely)h(separate)f(FITS)f(\014les.) 39 b(Since)27 b(in)f(general)h(it)g(is)g(not)g(p)s(ossible)f(to)h(ph)m (ysically)g(op)s(en)f(the)0 1861 y(same)36 b(\014le)g(t)m(wice)h(and)e (then)g(exp)s(ect)h(to)g(b)s(e)f(able)h(to)h(sim)m(ultaneously)f(\(or)g (in)f(alternating)i(succession\))g(write)0 1974 y(to)e(2)f(di\013eren)m (t)h(lo)s(cations)h(in)d(the)i(\014le,)g(CFITSIO)e(recognizes)j(when)d (the)h(\014le)g(to)h(b)s(e)f(op)s(ened)f(\(in)h(the)h(call)g(to)0 2087 y(\014ts)p 127 2087 28 4 v 32 w(op)s(en)p 349 2087 V 33 w(\014le\))29 b(has)f(already)h(b)s(een)f(op)s(ened)g(and)g (instead)h(of)g(actually)h(op)s(ening)e(the)h(\014le)g(again,)h(just)e (logically)0 2199 y(links)i(the)h(new)f(\014le)h(to)g(the)g(old)f (\014le.)42 b(\(This)30 b(only)h(applies)f(if)h(the)g(\014le)f(is)h(op) s(ened)f(more)g(than)g(once)i(within)e(the)0 2312 y(same)e(program,)g (and)f(do)s(es)h(not)f(prev)m(en)m(t)i(the)f(same)g(\014le)f(from)g(b)s (eing)h(sim)m(ultaneously)g(op)s(ened)f(b)m(y)g(more)h(than)0 2425 y(one)h(program\).)40 b(Then)28 b(b)s(efore)g(CFITSIO)f(reads)h (or)h(writes)g(to)g(either)g(\(logical\))j(\014le,)d(it)g(mak)m(es)h (sure)d(that)j(an)m(y)0 2538 y(mo)s(di\014cations)i(made)f(to)h(the)g (other)g(\014le)f(ha)m(v)m(e)i(b)s(een)e(completely)i(\015ushed)c(from) i(the)h(in)m(ternal)g(bu\013ers)f(to)h(the)0 2651 y(\014le.)44 b(Th)m(us,)30 b(in)h(principle,)h(one)f(could)g(op)s(en)g(a)h(\014le)f (t)m(wice,)i(in)e(one)h(case)g(p)s(oin)m(ting)g(to)g(the)f(\014rst)g (extension)h(and)0 2764 y(in)i(the)h(other)g(p)s(oin)m(ting)f(to)i(the) e(2nd)g(extension)i(and)d(then)i(write)f(data)i(to)f(b)s(oth)f (extensions,)i(in)e(an)m(y)h(order,)0 2877 y(without)25 b(danger)h(of)f(corrupting)h(the)f(\014le,)i(There)e(ma)m(y)h(b)s(e)f (some)h(e\016ciency)g(p)s(enalties)g(in)f(doing)h(this)f(ho)m(w)m(ev)m (er,)0 2990 y(since)j(CFITSIO)f(has)h(to)h(\015ush)d(all)j(the)f(in)m (ternal)h(bu\013ers)e(related)i(to)g(one)f(\014le)g(b)s(efore)g(switc)m (hing)g(to)h(the)f(other,)0 3103 y(so)i(it)h(w)m(ould)f(still)h(b)s(e)f (pruden)m(t)f(to)i(minimize)g(the)f(n)m(um)m(b)s(er)f(of)i(times)f(one) h(switc)m(hes)g(bac)m(k)g(and)e(forth)h(b)s(et)m(w)m(een)0 3216 y(doing)g(I/O)h(to)g(di\013eren)m(t)g(HDUs)g(in)f(the)g(same)h (\014le.)0 3680 y Fe(4.3)135 b(Curren)l(t)46 b(Header)f(Data)h(Unit)g (\(CHDU\))0 3957 y Fj(In)32 b(general,)j(a)f(FITS)e(\014le)i(can)f(con) m(tain)h(m)m(ultiple)g(Header)g(Data)h(Units,)f(also)g(called)g (extensions.)49 b(CFITSIO)0 4070 y(only)38 b(op)s(erates)h(within)f (one)g(HDU)h(at)g(an)m(y)g(giv)m(en)g(time,)i(and)d(the)g(curren)m(tly) g(selected)i(HDU)f(is)f(called)i(the)0 4183 y(Curren)m(t)f(Header)h (Data)h(Unit)f(\(CHDU\).)h(When)f(a)g(FITS)f(\014le)h(is)f(\014rst)g (created)i(or)f(op)s(ened)f(the)h(CHDU)g(is)0 4295 y(automatically)28 b(de\014ned)23 b(to)j(b)s(e)e(the)h(\014rst)f(HDU)i(\(i.e.,)h(the)e (primary)f(arra)m(y\).)40 b(CFITSIO)23 b(routines)i(are)g(pro)m(vided)0 4408 y(to)36 b(mo)m(v)m(e)h(to)g(and)e(op)s(en)g(an)m(y)h(other)g (existing)g(HDU)h(within)e(the)h(FITS)f(\014le)g(or)h(to)g(app)s(end)e (or)i(insert)f(a)h(new)0 4521 y(HDU)31 b(in)f(the)h(FITS)e(\014le)i (whic)m(h)f(then)g(b)s(ecomes)h(the)f(CHDU.)0 4986 y Fe(4.4)135 b(Subroutine)45 b(Names)0 5262 y Fj(All)26 b(FITSIO)f(subroutine)g(names)h(b)s(egin)f(with)h(the)g(letters)h('ft') f(to)h(distinguish)e(them)h(from)f(other)h(subroutines)0 5375 y(and)34 b(are)h(5)g(or)f(6)h(c)m(haracters)h(long.)54 b(Users)34 b(should)g(not)g(name)h(their)g(o)m(wn)f(subroutines)f(b)s (eginning)h(with)g('ft')0 5488 y(to)e(a)m(v)m(oid)i(con\015icts.)45 b(\(The)32 b(SPP)f(in)m(terface)i(routines)e(all)i(b)s(egin)e(with)h ('fs'\).)45 b(Subroutines)30 b(whic)m(h)h(read)h(or)g(get)0 5601 y(information)e(from)g(the)h(FITS)e(\014le)h(ha)m(v)m(e)i(names)e (b)s(eginning)f(with)h('ftg...'.)43 b(Subroutines)28 b(whic)m(h)i(write)g(or)h(put)0 5714 y(information)g(in)m(to)g(the)g (FITS)e(\014le)i(ha)m(v)m(e)g(names)g(b)s(eginning)e(with)h('ftp...'.)p eop end %%Page: 17 23 TeXDict begin 17 22 bop 0 299 a Fh(4.5.)72 b(SUBR)m(OUTINE)30 b(F)-10 b(AMILIES)30 b(AND)h(D)m(A)-8 b(T)g(A)g(TYPES)1697 b Fj(17)0 555 y Fe(4.5)135 b(Subroutine)45 b(F)-11 b(amilies)46 b(and)f(Datat)l(yp)t(es)0 805 y Fj(Man)m(y)h(of)g(the)g(subroutines)e (come)j(in)e(families)h(whic)m(h)g(di\013er)f(only)h(in)f(the)h(datat)m (yp)s(e)g(of)g(the)f(asso)s(ciated)0 918 y(parameter\(s\))34 b(.)47 b(The)32 b(datat)m(yp)s(e)i(of)f(these)g(subroutines)e(is)i (indicated)g(b)m(y)g(the)g(last)g(letter)h(of)f(the)g(subroutine)0 1031 y(name)d(\(e.g.,)j('j')d(in)g('ftpkyj'\))h(as)f(follo)m(ws:)382 1284 y Ff(x)47 b(-)h(bit)382 1397 y(b)f(-)h(character*1)c(\(unsigned)i (byte\))382 1510 y(i)h(-)h(short)e(integer)g(\(I*2\))382 1623 y(j)h(-)h(integer)e(\(I*4,)g(32-bit)g(integer\))382 1735 y(k)h(-)h(long)e(long)h(integer)f(\(I*8,)g(64-bit)g(integer\))382 1848 y(e)h(-)h(real)e(exponential)f(floating)h(point)g(\(R*4\))382 1961 y(f)h(-)h(real)e(fixed-format)f(floating)g(point)i(\(R*4\))382 2074 y(d)g(-)h(double)e(precision)f(real)i(floating-point)d(\(R*8\))382 2187 y(g)j(-)h(double)e(precision)f(fixed-format)g(floating)g(point)h (\(R*8\))382 2300 y(c)h(-)h(complex)e(reals)g(\(pairs)g(of)h(R*4)g (values\))382 2413 y(m)g(-)h(double)e(precision)f(complex)h(\(pairs)g (of)h(R*8)g(values\))382 2526 y(l)g(-)h(logical)e(\(L*4\))382 2639 y(s)h(-)h(character)d(string)0 2891 y Fj(When)23 b(dealing)h(with)f(the)g(FITS)g(b)m(yte)g(datat)m(yp)s(e,)j(it)e(is)f (imp)s(ortan)m(t)h(to)f(remem)m(b)s(er)g(that)h(the)f(ra)m(w)g(v)-5 b(alues)24 b(\(b)s(efore)0 3004 y(an)m(y)h(scaling)g(b)m(y)f(the)h (BSCALE)e(and)h(BZER)m(O,)g(or)h(TSCALn)d(and)i(TZER)m(On)f(k)m(eyw)m (ord)i(v)-5 b(alues\))25 b(in)f(b)m(yte)h(arra)m(ys)0 3117 y(\(BITPIX)37 b(=)f(8\))h(or)f(b)m(yte)i(columns)e(\(TF)m(ORMn)h (=)f('B'\))h(are)g(in)m(terpreted)g(as)g(unsigned)e(b)m(ytes)i(with)g (v)-5 b(alues)0 3230 y(ranging)40 b(from)f(0)i(to)f(255.)71 b(Some)40 b(F)-8 b(ortran)40 b(compilers)h(supp)s(ort)d(a)i (non-standard)f(b)m(yte)h(datat)m(yp)s(e)h(suc)m(h)f(as)0 3343 y(INTEGER*1,)34 b(LOGICAL*1,)g(or)f(BYTE,)g(whic)m(h)f(can)h (sometimes)h(b)s(e)e(used)g(instead)h(of)g(CHARA)m(CTER*1)0 3456 y(v)-5 b(ariables.)39 b(Man)m(y)23 b(mac)m(hines)g(p)s(ermit)g (passing)f(a)h(n)m(umeric)g(datat)m(yp)s(e)g(\(suc)m(h)g(as)g (INTEGER*1\))h(to)f(the)g(FITSIO)0 3569 y(subroutines)41 b(whic)m(h)i(are)g(exp)s(ecting)g(a)g(CHARA)m(CTER*1)h(datat)m(yp)s(e,) j(but)42 b(this)g(tec)m(hnically)j(violates)g(the)0 3682 y(F)-8 b(ortran-77)29 b(standard)d(and)g(is)h(not)g(supp)s(orted)e(on)i (all)h(mac)m(hines)f(\(e.g.,)j(on)c(a)i(V)-10 b(AX/VMS)27 b(mac)m(hine)h(one)f(m)m(ust)0 3795 y(use)j(the)h(V)-10 b(AX-sp)s(eci\014c)31 b(\045DESCR)e(function\).)0 3955 y(One)22 b(feature)h(of)g(the)g(CFITSIO)e(routines)i(is)f(that)i(they)f (can)g(op)s(erate)g(on)f(a)h(`X')h(\(bit\))f(column)g(in)f(a)h(binary)f (table)0 4068 y(as)35 b(though)e(it)i(w)m(ere)g(a)g(`B')g(\(b)m(yte\))g (column.)53 b(F)-8 b(or)35 b(example)g(a)f(`11X')i(datat)m(yp)s(e)f (column)f(can)h(b)s(e)f(in)m(terpreted)0 4181 y(the)28 b(same)h(as)f(a)g(`2B')i(column)e(\(i.e.,)i(2)e(unsigned)f(8-bit)i(b)m (ytes\).)41 b(In)27 b(some)i(instances,)g(it)f(can)h(b)s(e)e(more)h (e\016cien)m(t)0 4294 y(to)j(read)f(and)g(write)h(whole)f(b)m(ytes)h (at)g(a)g(time,)g(rather)g(than)f(reading)g(or)h(writing)f(eac)m(h)i (individual)d(bit.)0 4454 y(The)41 b(double)h(precision)g(complex)g (datat)m(yp)s(e)h(is)f(not)g(a)g(standard)f(F)-8 b(ortran-77)43 b(datat)m(yp)s(e.)76 b(If)41 b(a)i(particular)0 4567 y(F)-8 b(ortran)35 b(compiler)g(do)s(es)f(not)h(directly)g(supp)s(ort)e (this)i(datat)m(yp)s(e,)h(then)f(one)f(ma)m(y)h(instead)g(pass)f(an)h (arra)m(y)g(of)0 4680 y(pairs)d(of)h(double)f(precision)h(v)-5 b(alues)32 b(to)i(these)f(subroutines.)45 b(The)33 b(\014rst)e(v)-5 b(alue)33 b(in)f(eac)m(h)i(pair)e(is)h(the)g(real)g(part,)0 4792 y(and)d(the)g(second)h(is)f(the)h(imaginary)g(part.)0 5125 y Fe(4.6)135 b(Implicit)46 b(Data)g(T)l(yp)t(e)f(Con)l(v)l(ersion) 0 5375 y Fj(The)22 b(FITSIO)g(routines)h(that)h(read)e(and)h(write)g(n) m(umerical)g(data)h(can)f(p)s(erform)f(implicit)i(data)f(t)m(yp)s(e)g (con)m(v)m(ersion.)0 5488 y(This)i(means)g(that)h(the)g(data)g(t)m(yp)s (e)g(of)g(the)g(v)-5 b(ariable)26 b(or)g(arra)m(y)g(in)f(the)h(program) f(do)s(es)g(not)h(need)g(to)g(b)s(e)f(the)h(same)0 5601 y(as)i(the)f(data)h(t)m(yp)s(e)g(of)f(the)h(v)-5 b(alue)28 b(in)f(the)g(FITS)g(\014le.)40 b(Data)28 b(t)m(yp)s(e)g(con)m(v)m (ersion)h(is)e(supp)s(orted)f(for)h(n)m(umerical)h(and)0 5714 y(string)33 b(data)h(t)m(yp)s(es)f(\(if)h(the)g(string)f(con)m (tains)h(a)g(v)-5 b(alid)33 b(n)m(um)m(b)s(er)f(enclosed)i(in)f (quotes\))h(when)f(reading)g(a)h(FITS)p eop end %%Page: 18 24 TeXDict begin 18 23 bop 0 299 a Fj(18)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fj(header)g(k)m(eyw)m(ord)g(v)-5 b(alue)31 b(and)g(for)f(n)m (umeric)h(v)-5 b(alues)31 b(when)f(reading)h(or)g(writing)g(v)-5 b(alues)31 b(in)f(the)h(primary)f(arra)m(y)0 668 y(or)40 b(a)h(table)h(column.)70 b(CFITSIO)39 b(returns)h(status)g(=)h(NUM)p 2185 668 28 4 v 33 w(O)m(VERFLO)m(W)g(if)g(the)f(con)m(v)m(erted)i (data)f(v)-5 b(alue)0 781 y(exceeds)33 b(the)g(range)g(of)g(the)f (output)g(data)i(t)m(yp)s(e.)47 b(Implicit)33 b(data)g(t)m(yp)s(e)g (con)m(v)m(ersion)h(is)e(not)h(supp)s(orted)d(within)0 894 y(binary)g(tables)h(for)f(string,)g(logical,)k(complex,)d(or)f (double)g(complex)h(data)g(t)m(yp)s(es.)0 1054 y(In)g(addition,)h(an)m (y)f(table)h(column)f(ma)m(y)h(b)s(e)f(read)g(as)h(if)f(it)h(con)m (tained)g(string)f(v)-5 b(alues.)44 b(In)31 b(the)g(case)i(of)e(n)m (umeric)0 1167 y(columns)f(the)h(returned)e(string)h(will)h(b)s(e)f (formatted)h(using)e(the)i(TDISPn)e(displa)m(y)i(format)f(if)h(it)g (exists.)0 1496 y Fe(4.7)135 b(Data)46 b(Scaling)0 1746 y Fj(When)38 b(reading)f(n)m(umerical)i(data)f(v)-5 b(alues)38 b(in)f(the)h(primary)f(arra)m(y)h(or)g(a)g(table)h(column,)h(the)d(v)-5 b(alues)38 b(will)h(b)s(e)0 1859 y(scaled)f(automatically)j(b)m(y)c (the)h(BSCALE)f(and)g(BZER)m(O)h(\(or)g(TSCALn)d(and)i(TZER)m(On\))g (header)g(k)m(eyw)m(ord)0 1972 y(v)-5 b(alues)33 b(if)f(they)g(are)h (presen)m(t)g(in)f(the)g(header.)47 b(The)31 b(scaled)j(data)f(that)g (is)f(returned)f(to)i(the)g(reading)f(program)0 2085 y(will)f(ha)m(v)m(e)382 2316 y Ff(output)46 b(value)g(=)i(\(FITS)e (value\))g(*)i(BSCALE)e(+)h(BZERO)0 2546 y Fj(\(a)30 b(corresp)s(onding)e(form)m(ula)h(using)g(TSCALn)e(and)i(TZER)m(On)e (is)i(used)g(when)f(reading)h(from)g(table)h(columns\).)0 2659 y(In)h(the)i(case)g(of)f(in)m(teger)h(output)f(v)-5 b(alues)32 b(the)h(\015oating)g(p)s(oin)m(t)f(scaled)g(v)-5 b(alue)33 b(is)f(truncated)g(to)h(an)f(in)m(teger)h(\(not)0 2772 y(rounded)38 b(to)i(the)g(nearest)g(in)m(teger\).)70 b(The)39 b(ftpscl)g(and)g(fttscl)i(subroutines)d(ma)m(y)i(b)s(e)f(used) g(to)h(o)m(v)m(erride)h(the)0 2885 y(scaling)30 b(parameters)f (de\014ned)e(in)h(the)h(header)f(\(e.g.,)j(to)e(turn)f(o\013)h(the)f (scaling)i(so)f(that)g(the)g(program)f(can)h(read)0 2998 y(the)i(ra)m(w)f(unscaled)g(v)-5 b(alues)31 b(from)f(the)g(FITS)g (\014le\).)0 3158 y(When)44 b(writing)h(n)m(umerical)g(data)g(to)g(the) g(primary)f(arra)m(y)h(or)f(to)h(a)g(table)h(column)e(the)h(data)g(v)-5 b(alues)45 b(will)0 3271 y(generally)29 b(b)s(e)f(automatically)j(in)m (v)m(ersely)f(scaled)f(b)m(y)f(the)g(v)-5 b(alue)29 b(of)f(the)h (BSCALE)e(and)h(BZER)m(O)g(\(or)h(TSCALn)0 3384 y(and)h(TZER)m(On\))g (header)g(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(if)g(they)g(they)g(exist)g (in)f(the)h(header.)42 b(These)30 b(k)m(eyw)m(ords)h(m)m(ust)g(ha)m(v)m (e)0 3497 y(b)s(een)f(written)h(to)h(the)g(header)e(b)s(efore)h(an)m(y) h(data)f(is)g(written)h(for)e(them)i(to)f(ha)m(v)m(e)i(an)m(y)e (e\013ect.)44 b(Otherwise,)32 b(one)0 3610 y(ma)m(y)i(use)f(the)g (ftpscl)g(and)g(fttscl)h(subroutines)d(to)j(de\014ne)f(or)g(o)m(v)m (erride)h(the)f(scaling)i(k)m(eyw)m(ords)e(in)g(the)g(header)0 3723 y(\(e.g.,)h(to)f(turn)d(o\013)j(the)f(scaling)h(so)f(that)g(the)g (program)g(can)g(write)g(the)g(ra)m(w)g(unscaled)g(v)-5 b(alues)32 b(in)m(to)h(the)f(FITS)0 3836 y(\014le\).)43 b(If)30 b(scaling)i(is)f(p)s(erformed,)e(the)i(in)m(v)m(erse)h(scaled)g (output)e(v)-5 b(alue)32 b(that)f(is)g(written)g(in)m(to)h(the)f(FITS)f (\014le)h(will)0 3949 y(ha)m(v)m(e)430 4179 y Ff(FITS)46 b(value)h(=)g(\(\(input)f(value\))g(-)h(BZERO\))f(/)i(BSCALE)0 4410 y Fj(\(a)39 b(corresp)s(onding)d(form)m(ula)i(using)g(TSCALn)e (and)h(TZER)m(On)g(is)h(used)f(when)f(writing)i(to)h(table)g (columns\).)0 4523 y(Rounding)19 b(to)i(the)g(nearest)g(in)m(teger,)i (rather)e(than)f(truncation,)j(is)d(p)s(erformed)f(when)g(writing)h(in) m(teger)i(datat)m(yp)s(es)0 4636 y(to)31 b(the)g(FITS)e(\014le.)0 4965 y Fe(4.8)135 b(Error)46 b(Status)f(V)-11 b(alues)45 b(and)g(the)g(Error)g(Message)h(Stac)l(k)0 5215 y Fj(The)33 b(last)i(parameter)f(in)g(nearly)g(ev)m(ery)g(FITSIO)f(subroutine)g(is) h(the)g(error)f(status)h(v)-5 b(alue)35 b(whic)m(h)e(is)h(b)s(oth)f(an) 0 5328 y(input)j(and)f(an)i(output)f(parameter.)60 b(A)36 b(returned)f(p)s(ositiv)m(e)j(v)-5 b(alue)37 b(for)f(this)h(parameter)g (indicates)g(an)f(error)0 5441 y(w)m(as)31 b(detected.)42 b(A)30 b(listing)h(of)g(all)g(the)g(FITSIO)e(status)i(co)s(de)f(v)-5 b(alues)31 b(is)f(giv)m(en)i(at)f(the)f(end)g(of)h(this)f(do)s(cumen)m (t.)0 5601 y(The)22 b(FITSIO)g(library)g(uses)h(an)f(`inherited)h (status')g(con)m(v)m(en)m(tion)i(for)e(the)g(status)g(parameter)g(whic) m(h)g(means)f(that)0 5714 y(if)i(a)h(subroutine)f(is)g(called)i(with)e (a)h(p)s(ositiv)m(e)g(input)f(v)-5 b(alue)25 b(of)g(the)f(status)h (parameter,)h(then)f(the)f(subroutine)g(will)p eop end %%Page: 19 25 TeXDict begin 19 24 bop 0 299 a Fh(4.9.)72 b(V)-10 b(ARIABLE-LENGTH)31 b(ARRA)-8 b(Y)31 b(F)-10 b(A)m(CILITY)30 b(IN)h(BINAR)-8 b(Y)31 b(T)-8 b(ABLES)956 b Fj(19)0 555 y(exit)26 b(immediately)f (without)g(c)m(hanging)h(the)e(v)-5 b(alue)25 b(of)g(the)g(status)g (parameter.)39 b(Th)m(us,)25 b(if)g(one)f(passes)h(the)g(status)0 668 y(v)-5 b(alue)31 b(returned)e(from)h(eac)m(h)i(FITSIO)d(routine)h (as)h(input)f(to)h(the)f(next)h(FITSIO)e(subroutine,)h(then)g(whenev)m (er)0 781 y(an)39 b(error)g(is)h(detected)g(all)h(further)d(FITSIO)g (pro)s(cessing)h(will)h(cease.)69 b(This)39 b(con)m(v)m(en)m(tion)i (can)f(simplify)f(the)0 894 y(error)30 b(c)m(hec)m(king)j(in)d (application)i(programs)f(b)s(ecause)g(it)g(is)g(not)g(necessary)g(to)g (c)m(hec)m(k)i(the)e(v)-5 b(alue)31 b(of)g(the)g(status)0 1007 y(parameter)j(after)g(ev)m(ery)g(single)h(FITSIO)d(subroutine)g (call.)52 b(If)33 b(a)h(program)f(con)m(tains)i(a)f(sequence)g(of)g (sev)m(eral)0 1120 y(FITSIO)23 b(calls,)j(one)e(can)g(just)g(c)m(hec)m (k)h(the)f(status)g(v)-5 b(alue)24 b(after)h(the)f(last)g(call.)40 b(Since)24 b(the)g(returned)e(status)j(v)-5 b(alues)0 1233 y(are)36 b(generally)h(distinctiv)m(e,)i(it)d(should)f(b)s(e)g(p)s (ossible)g(to)h(determine)g(whic)m(h)f(subroutine)g(originally)i (returned)0 1346 y(the)31 b(error)f(status.)0 1506 y(FITSIO)i(also)i (main)m(tains)f(an)g(in)m(ternal)h(stac)m(k)g(of)f(error)g(messages)h (\(80-c)m(haracter)i(maxim)m(um)d(length\))g(whic)m(h)0 1619 y(in)j(man)m(y)g(cases)h(pro)m(vide)f(a)g(more)g(detailed)i (explanation)f(of)f(the)g(cause)h(of)f(the)g(error)g(than)f(is)h(pro)m (vided)g(b)m(y)0 1732 y(the)k(error)e(status)i(n)m(um)m(b)s(er)e (alone.)69 b(It)39 b(is)h(recommended)f(that)g(the)h(error)f(message)h (stac)m(k)h(b)s(e)e(prin)m(ted)g(out)0 1844 y(whenev)m(er)31 b(a)h(program)g(detects)g(a)g(FITSIO)e(error.)44 b(T)-8 b(o)32 b(do)f(this,)h(call)h(the)f(FTGMSG)g(routine)f(rep)s(eatedly)h (to)0 1957 y(get)h(the)g(successiv)m(e)g(messages)h(on)e(the)g(stac)m (k.)48 b(When)32 b(the)h(stac)m(k)g(is)g(empt)m(y)f(FTGMSG)h(will)g (return)e(a)h(blank)0 2070 y(string.)41 b(Note)31 b(that)g(this)f(is)g (a)g(`First)h(In)e({)i(First)f(Out')g(stac)m(k,)i(so)e(the)h(oldest)g (error)e(message)j(is)e(returned)f(\014rst)0 2183 y(b)m(y)h(ftgmsg.)0 2557 y Fe(4.9)135 b(V)-11 b(ariable-Length)46 b(Arra)l(y)f(F)-11 b(acilit)l(y)46 b(in)f(Binary)g(T)-11 b(ables)0 2815 y Fj(FITSIO)38 b(pro)m(vides)i(easy-to-use)h(supp)s(ort)d(for)h (reading)g(and)g(writing)h(data)g(in)f(v)-5 b(ariable)40 b(length)g(\014elds)f(of)h(a)0 2928 y(binary)35 b(table.)56 b(The)35 b(v)-5 b(ariable)36 b(length)f(columns)g(ha)m(v)m(e)i(TF)m (ORMn)e(k)m(eyw)m(ord)h(v)-5 b(alues)35 b(of)h(the)f(form)g (`1Pt\(len\)')0 3041 y(or)30 b(`1Qt\(len\)')h(where)f(`t')g(is)g(the)g (datat)m(yp)s(e)h(co)s(de)f(\(e.g.,)i(I,)e(J,)f(E,)h(D,)h(etc.\))42 b(and)29 b(`len')h(is)g(an)g(in)m(teger)h(sp)s(ecifying)0 3154 y(the)f(maxim)m(um)g(length)g(of)g(the)g(v)m(ector)h(in)f(the)g (table.)41 b(If)30 b(the)g(v)-5 b(alue)30 b(of)g(`len')g(is)g(not)g(sp) s(eci\014ed)f(when)g(the)h(table)0 3267 y(is)j(created)g(\(e.g.,)i(if)e (the)f(TF)m(ORM)h(k)m(eyw)m(ord)g(v)-5 b(alue)33 b(is)g(simply)f(sp)s (eci\014ed)g(as)h('1PE')g(instead)g(of)f('1PE\(400\))j(\),)0 3380 y(then)28 b(FITSIO)f(will)h(automatically)k(scan)c(the)g(table)h (when)f(it)g(is)h(closed)g(to)g(determine)f(the)g(maxim)m(um)h(length)0 3493 y(of)i(the)f(v)m(ector)i(and)e(will)h(app)s(end)d(this)j(v)-5 b(alue)30 b(to)i(the)e(TF)m(ORMn)g(v)-5 b(alue.)0 3653 y(The)25 b(same)h(routines)g(whic)m(h)f(read)h(and)f(write)h(data)g(in) f(an)h(ordinary)f(\014xed)g(length)h(binary)f(table)h(extension)h(are)0 3766 y(also)k(used)e(for)h(v)-5 b(ariable)31 b(length)g(\014elds,)e(ho) m(w)m(ev)m(er,)j(the)e(subroutine)f(parameters)i(tak)m(e)h(on)e(a)g (sligh)m(tly)h(di\013eren)m(t)0 3878 y(in)m(terpretation)h(as)e (describ)s(ed)g(b)s(elo)m(w.)0 4039 y(All)37 b(the)f(data)h(in)f(a)h(v) -5 b(ariable)37 b(length)f(\014eld)g(is)g(written)h(in)m(to)g(an)f (area)h(called)h(the)e(`heap')g(whic)m(h)g(follo)m(ws)i(the)0 4152 y(main)26 b(\014xed-length)g(FITS)f(binary)h(table.)40 b(The)25 b(size)i(of)g(the)f(heap,)h(in)f(b)m(ytes,)h(is)f(sp)s (eci\014ed)g(with)f(the)i(PCOUNT)0 4264 y(k)m(eyw)m(ord)21 b(in)f(the)h(FITS)f(header.)37 b(When)20 b(creating)i(a)f(new)f(binary) g(table,)j(the)e(initial)h(v)-5 b(alue)21 b(of)f(PCOUNT)g(should)0 4377 y(usually)31 b(b)s(e)f(set)i(to)g(zero.)44 b(FITSIO)30 b(will)h(recompute)h(the)f(size)h(of)g(the)f(heap)g(as)g(the)h(data)g (is)f(written)g(and)g(will)0 4490 y(automatically)d(up)s(date)c(the)i (PCOUNT)e(k)m(eyw)m(ord)h(v)-5 b(alue)26 b(when)e(the)h(table)h(is)f (closed.)40 b(When)25 b(writing)g(v)-5 b(ariable)0 4603 y(length)34 b(data)g(to)g(a)g(table,)i(CFITSIO)c(will)h(automatically)k (extend)c(the)h(size)g(of)g(the)g(heap)f(area)h(if)g(necessary)-8 b(,)0 4716 y(so)31 b(that)g(an)m(y)f(follo)m(wing)i(HDUs)f(do)f(not)h (get)h(o)m(v)m(erwritten.)0 4876 y(By)e(default)f(the)h(heap)f(data)i (area)f(starts)g(immediately)h(after)f(the)f(last)i(ro)m(w)e(of)h(the)g (\014xed-length)f(table.)42 b(This)0 4989 y(default)27 b(starting)g(lo)s(cation)i(ma)m(y)e(b)s(e)f(o)m(v)m(erridden)h(b)m(y)g (the)g(THEAP)f(k)m(eyw)m(ord,)i(but)f(this)f(is)h(not)g(recommended.)0 5102 y(If)34 b(additional)h(ro)m(ws)f(of)g(data)h(are)g(added)e(to)i (the)f(table,)j(CFITSIO)32 b(will)j(automatically)i(shift)c(the)i(the)f (heap)0 5215 y(do)m(wn)g(to)i(mak)m(e)f(ro)s(om)g(for)f(the)h(new)f(ro) m(ws,)i(but)e(it)i(is)e(ob)m(viously)i(b)s(e)e(more)h(e\016cien)m(t)h (to)f(initially)h(create)h(the)0 5328 y(table)31 b(with)e(the)h (necessary)g(n)m(um)m(b)s(er)f(of)h(blank)f(ro)m(ws,)h(so)g(that)g(the) g(heap)g(do)s(es)f(not)h(needed)g(to)g(b)s(e)f(constan)m(tly)0 5441 y(mo)m(v)m(ed.)0 5601 y(When)40 b(writing)h(to)g(a)g(v)-5 b(ariable)41 b(length)g(\014eld,)i(the)e(en)m(tire)h(arra)m(y)f(of)f(v) -5 b(alues)41 b(for)f(a)h(giv)m(en)h(ro)m(w)f(of)f(the)h(table)0 5714 y(m)m(ust)36 b(b)s(e)g(written)g(with)g(a)g(single)h(call)h(to)f (FTPCLx.)57 b(The)36 b(total)i(length)f(of)f(the)g(arra)m(y)h(is)f (calculated)i(from)p eop end %%Page: 20 26 TeXDict begin 20 25 bop 0 299 a Fj(20)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fj(\(NELEM+FELEM-1\).)44 b(One)30 b(cannot)i(app)s(end)d(more)i (elemen)m(ts)h(to)g(an)e(existing)i(\014eld)f(at)g(a)h(later)g(time;)g (an)m(y)0 668 y(attempt)j(to)f(do)g(so)g(will)g(simply)f(o)m(v)m (erwrite)j(all)e(the)g(data)h(whic)m(h)e(w)m(as)h(previously)g (written.)51 b(Note)35 b(also)f(that)0 781 y(the)g(new)g(data)g(will)h (b)s(e)e(written)h(to)h(a)f(new)g(area)g(of)g(the)h(heap)e(and)h(the)g (heap)g(space)g(used)f(b)m(y)h(the)g(previous)0 894 y(write)j(cannot)h (b)s(e)e(reclaimed.)62 b(F)-8 b(or)38 b(this)f(reason)g(it)h(is)f (advised)g(that)h(eac)m(h)g(ro)m(w)f(of)h(a)f(v)-5 b(ariable)38 b(length)f(\014eld)0 1007 y(only)c(b)s(e)g(written)g(once.)50 b(An)33 b(exception)h(to)g(this)f(general)h(rule)f(o)s(ccurs)g(when)f (setting)i(elemen)m(ts)h(of)e(an)g(arra)m(y)0 1120 y(as)38 b(unde\014ned.)63 b(One)37 b(m)m(ust)i(\014rst)e(write)h(a)h(dumm)m(y)e (v)-5 b(alue)39 b(in)m(to)g(the)g(arra)m(y)f(with)g(FTPCLx,)i(and)e (then)g(call)0 1233 y(FTPCLU)33 b(to)i(\015ag)f(the)f(desired)h(elemen) m(ts)h(as)e(unde\014ned.)49 b(\(Do)35 b(not)f(use)f(the)h(FTPCNx)f (family)h(of)g(routines)0 1346 y(with)28 b(v)-5 b(ariable)30 b(length)f(\014elds\).)40 b(Note)30 b(that)f(the)g(ro)m(ws)g(of)g(a)g (table,)h(whether)e(\014xed)g(or)h(v)-5 b(ariable)29 b(length,)h(do)f(not)0 1458 y(ha)m(v)m(e)j(to)f(b)s(e)e(written)i (consecutiv)m(ely)h(and)e(ma)m(y)h(b)s(e)f(written)g(in)g(an)m(y)h (order.)0 1619 y(When)40 b(writing)h(to)g(a)g(v)-5 b(ariable)41 b(length)g(ASCI)s(I)e(c)m(haracter)j(\014eld)e(\(e.g.,)45 b(TF)m(ORM)c(=)f('1P)-8 b(A'\))43 b(only)d(a)h(single)0 1732 y(c)m(haracter)33 b(string)f(written.)44 b(FTPCLS)30 b(writes)i(the)g(whole)f(length)h(of)g(the)g(input)e(string)i(\(min)m (us)f(an)m(y)h(trailing)0 1844 y(blank)37 b(c)m(haracters\),)42 b(th)m(us)37 b(the)h(NELEM)f(and)g(FELEM)h(parameters)g(are)g(ignored.) 62 b(If)37 b(the)h(input)e(string)i(is)0 1957 y(completely)28 b(blank)f(then)f(FITSIO)g(will)h(write)g(one)g(blank)f(c)m(haracter)j (to)e(the)g(FITS)f(\014le.)40 b(Similarly)-8 b(,)28 b(FTGCVS)0 2070 y(and)35 b(FTGCFS)g(read)g(the)h(en)m(tire)g(string)g(\(truncated) f(to)i(the)e(width)g(of)g(the)h(c)m(haracter)h(string)e(argumen)m(t)h (in)0 2183 y(the)31 b(subroutine)e(call\))j(and)e(also)h(ignore)g(the)f (NELEM)h(and)f(FELEM)g(parameters.)0 2343 y(The)35 b(FTPDES)h (subroutine)e(is)i(useful)f(in)g(situations)i(where)e(m)m(ultiple)i(ro) m(ws)e(of)h(a)g(v)-5 b(ariable)37 b(length)f(column)0 2456 y(ha)m(v)m(e)c(the)e(iden)m(tical)i(arra)m(y)f(of)g(v)-5 b(alues.)41 b(One)30 b(can)g(simply)g(write)h(the)f(arra)m(y)h(once)g (for)g(the)f(\014rst)g(ro)m(w,)g(and)g(then)0 2569 y(use)36 b(FTPDES)g(to)h(write)g(the)f(same)h(descriptor)g(v)-5 b(alues)36 b(in)m(to)i(the)e(other)h(ro)m(ws)f(\(use)h(the)f(FTGDES)h (routine)0 2682 y(to)f(read)f(the)h(\014rst)f(descriptor)g(v)-5 b(alue\);)39 b(all)d(the)g(ro)m(ws)f(will)h(then)f(p)s(oin)m(t)g(to)h (the)g(same)f(storage)i(lo)s(cation)g(th)m(us)0 2795 y(sa)m(ving)31 b(disk)f(space.)0 2955 y(When)35 b(reading)g(from)f(a)i (v)-5 b(ariable)35 b(length)h(arra)m(y)f(\014eld)g(one)g(can)g(only)h (read)e(as)i(man)m(y)f(elemen)m(ts)h(as)f(actually)0 3068 y(exist)i(in)e(that)i(ro)m(w)e(of)h(the)g(table;)k(reading)c(do)s (es)g(not)g(automatically)i(con)m(tin)m(ue)f(with)f(the)g(next)g(ro)m (w)g(of)g(the)0 3181 y(table)29 b(as)f(o)s(ccurs)g(when)f(reading)h(an) g(ordinary)g(\014xed)f(length)h(table)h(\014eld.)40 b(A)m(ttempts)29 b(to)g(read)f(more)g(than)g(this)0 3294 y(will)k(cause)h(an)e(error)h (status)g(to)g(b)s(e)f(returned.)44 b(One)32 b(can)g(determine)g(the)g (n)m(um)m(b)s(er)e(of)i(elemen)m(ts)h(in)f(eac)m(h)h(ro)m(w)0 3407 y(of)e(a)f(v)-5 b(ariable)31 b(column)g(with)f(the)g(FTGDES)h (subroutine.)0 3859 y Fe(4.10)136 b(Supp)t(ort)44 b(for)h(IEEE)g(Sp)t (ecial)h(V)-11 b(alues)0 4133 y Fj(The)26 b(ANSI/IEEE-754)h (\015oating-p)s(oin)m(t)h(n)m(um)m(b)s(er)d(standard)g(de\014nes)h (certain)h(sp)s(ecial)g(v)-5 b(alues)26 b(that)h(are)g(used)e(to)0 4246 y(represen)m(t)j(suc)m(h)g(quan)m(tities)h(as)f(Not-a-Num)m(b)s (er)h(\(NaN\),)h(denormalized,)f(under\015o)m(w,)e(o)m(v)m(er\015o)m (w,)j(and)d(in\014nit)m(y)-8 b(.)0 4359 y(\(See)31 b(the)g(App)s(endix) d(in)j(the)f(FITS)g(standard)f(or)i(the)g(FITS)e(User's)i(Guide)f(for)g (a)h(list)g(of)g(these)g(v)-5 b(alues\).)41 b(The)0 4472 y(FITSIO)26 b(subroutines)h(that)h(read)f(\015oating)i(p)s(oin)m(t)e (data)i(in)e(FITS)g(\014les)g(recognize)j(these)e(IEEE)e(sp)s(ecial)j (v)-5 b(alues)0 4585 y(and)27 b(b)m(y)h(default)h(in)m(terpret)f(the)h (o)m(v)m(er\015o)m(w)g(and)f(in\014nit)m(y)f(v)-5 b(alues)29 b(as)f(b)s(eing)g(equiv)-5 b(alen)m(t)29 b(to)g(a)g(NaN,)g(and)e(con)m (v)m(ert)0 4698 y(the)37 b(under\015o)m(w)e(and)i(denormalized)g(v)-5 b(alues)37 b(in)m(to)h(zeros.)60 b(In)36 b(some)i(cases)f(programmers)g (ma)m(y)g(w)m(an)m(t)h(access)0 4811 y(to)h(the)g(ra)m(w)f(IEEE)g(v)-5 b(alues,)41 b(without)e(an)m(y)f(mo)s(di\014cation)h(b)m(y)g(FITSIO.)e (This)h(can)g(b)s(e)g(done)g(b)m(y)h(calling)h(the)0 4924 y(FTGPVx)27 b(or)g(FTGCVx)h(routines)f(while)g(sp)s(ecifying)g (0.0)h(as)f(the)g(v)-5 b(alue)28 b(of)f(the)h(NULL)-10 b(V)g(AL)27 b(parameter.)40 b(This)0 5036 y(will)27 b(force)g(FITSIO)e (to)i(simply)f(pass)f(the)i(IEEE)f(v)-5 b(alues)26 b(through)g(to)h (the)f(application)i(program,)f(without)g(an)m(y)0 5149 y(mo)s(di\014cation.)63 b(This)37 b(do)s(es)g(not)h(w)m(ork)g(for)f (double)g(precision)h(v)-5 b(alues)38 b(on)g(V)-10 b(AX/VMS)38 b(mac)m(hines,)i(ho)m(w)m(ev)m(er,)0 5262 y(where)34 b(there)g(is)g(no)g(easy)h(w)m(a)m(y)g(to)g(b)m(ypass)f(the)g(default)h (in)m(terpretation)g(of)g(the)f(IEEE)f(sp)s(ecial)i(v)-5 b(alues.)53 b(This)0 5375 y(is)44 b(also)h(not)f(supp)s(orted)e(when)h (reading)h(\015oating-p)s(oin)m(t)h(images)h(that)e(ha)m(v)m(e)h(b)s (een)e(compressed)h(with)g(the)0 5488 y(FITS)33 b(tiled)h(image)g (compression)f(con)m(v)m(en)m(tion)j(that)e(is)f(discussed)g(in)g (section)h(5.6;)i(the)e(pixels)f(v)-5 b(alues)34 b(in)f(tile)0 5601 y(compressed)d(images)i(are)f(represen)m(ted)g(b)m(y)g(scaled)g (in)m(tegers,)h(and)e(a)i(reserv)m(ed)e(in)m(teger)j(v)-5 b(alue)31 b(\(not)g(a)g(NaN\))h(is)0 5714 y(used)e(to)h(represen)m(t)f (unde\014ned)e(pixels.)p eop end %%Page: 21 27 TeXDict begin 21 26 bop 0 299 a Fh(4.11.)73 b(WHEN)31 b(THE)f(FINAL)g(SIZE)f(OF)i(THE)f(FITS)f(HDU)i(IS)f(UNKNO)m(WN)978 b Fj(21)0 555 y Fe(4.11)136 b(When)44 b(the)h(Final)h(Size)f(of)g(the)g (FITS)f(HDU)h(is)g(Unkno)l(wn)0 805 y Fj(It)27 b(is)h(not)f(required)f (to)i(kno)m(w)f(the)h(total)h(size)f(of)f(a)h(FITS)e(data)i(arra)m(y)g (or)f(table)h(b)s(efore)f(b)s(eginning)f(to)i(write)g(the)0 918 y(data)k(to)f(the)g(FITS)f(\014le.)43 b(In)30 b(the)h(case)h(of)f (the)g(primary)f(arra)m(y)h(or)g(an)f(image)j(extension,)e(one)h (should)d(initially)0 1031 y(create)i(the)e(arra)m(y)h(with)e(the)i (size)g(of)f(the)g(highest)g(dimension)g(\(largest)i(NAXISn)d(k)m(eyw)m (ord\))i(set)g(to)g(a)f(dumm)m(y)0 1144 y(v)-5 b(alue,)26 b(suc)m(h)e(as)g(1.)39 b(Then)23 b(after)i(all)g(the)g(data)f(ha)m(v)m (e)i(b)s(een)d(written)h(and)g(the)g(true)g(dimensions)g(are)g(kno)m (wn,)h(then)0 1257 y(the)31 b(NAXISn)e(v)-5 b(alue)31 b(should)f(b)s(e)g(up)s(dated)f(using)h(the)h(\014ts)p 2051 1257 28 4 v 62 w(up)s(date)p 2389 1257 V 32 w(k)m(ey)h(routine)e (b)s(efore)g(mo)m(ving)i(to)f(another)0 1370 y(extension)g(or)f (closing)i(the)e(FITS)g(\014le.)0 1530 y(When)f(writing)g(to)g(FITS)g (tables,)h(CFITSIO)d(automatically)32 b(k)m(eeps)e(trac)m(k)g(of)f(the) g(highest)h(ro)m(w)f(n)m(um)m(b)s(er)e(that)0 1643 y(is)32 b(written)g(to,)h(and)e(will)h(increase)h(the)f(size)h(of)f(the)g (table)g(if)g(necessary)-8 b(.)46 b(CFITSIO)30 b(will)i(also)h (automatically)0 1756 y(insert)j(space)h(in)f(the)g(FITS)f(\014le)i(if) f(necessary)-8 b(,)39 b(to)e(ensure)e(that)i(the)f(data)h('heap',)h(if) e(it)h(exists,)h(and/or)f(an)m(y)0 1869 y(additional)29 b(HDUs)g(that)g(follo)m(w)g(the)g(table)g(do)f(not)h(get)g(o)m(v)m (erwritten)h(as)e(new)g(ro)m(ws)g(are)h(written)f(to)h(the)g(table.)0 2029 y(As)37 b(a)h(general)g(rule)f(it)h(is)f(b)s(est)g(to)h(sp)s (ecify)f(the)h(initial)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)f(=)g(0)g(when) g(the)g(table)h(is)g(created,)0 2142 y(then)g(let)h(CFITSIO)e(k)m(eep)i (trac)m(k)g(of)g(the)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(that)h(are)f (actually)i(written.)65 b(The)38 b(application)0 2255 y(program)e(should)f(not)i(man)m(ually)g(up)s(date)e(the)i(n)m(um)m(b)s (er)e(of)h(ro)m(ws)g(in)g(the)h(table)g(\(as)g(giv)m(en)g(b)m(y)f(the)h (NAXIS2)0 2368 y(k)m(eyw)m(ord\))j(since)f(CFITSIO)e(do)s(es)i(this)g (automatically)-8 b(.)69 b(If)38 b(a)i(table)f(is)g(initially)i (created)f(with)e(more)h(than)0 2481 y(zero)i(ro)m(ws,)j(then)c(this)h (will)f(usually)h(b)s(e)f(considered)g(as)h(the)g(minim)m(um)f(size)h (of)g(the)g(table,)j(ev)m(en)d(if)g(few)m(er)0 2594 y(ro)m(ws)30 b(are)g(actually)h(written)f(to)h(the)f(table.)41 b(Th)m(us,)30 b(if)f(a)i(table)f(is)g(initially)h(created)g(with)f(NAXIS2)g(=)g(20,)h (and)0 2706 y(CFITSIO)g(only)i(writes)f(10)i(ro)m(ws)e(of)h(data)g(b)s (efore)f(closing)i(the)f(table,)h(then)e(NAXIS2)h(will)g(remain)f (equal)h(to)0 2819 y(20.)50 b(If)33 b(ho)m(w)m(ev)m(er,)i(30)g(ro)m(ws) e(of)g(data)h(are)g(written)f(to)h(this)f(table,)i(then)e(NAXIS2)h (will)f(b)s(e)g(increased)g(from)g(20)0 2932 y(to)f(30.)44 b(The)31 b(one)g(exception)i(to)f(this)f(automatic)i(up)s(dating)d(of)h (the)h(NAXIS2)f(k)m(eyw)m(ord)h(is)f(if)g(the)h(application)0 3045 y(program)c(directly)g(mo)s(di\014es)f(the)i(v)-5 b(alue)28 b(of)g(NAXIS2)g(\(up)f(or)h(do)m(wn\))g(itself)h(just)e(b)s (efore)h(closing)h(the)f(table.)41 b(In)0 3158 y(this)28 b(case,)i(CFITSIO)d(do)s(es)h(not)h(up)s(date)e(NAXIS2)i(again,)h (since)f(it)g(assumes)f(that)h(the)f(application)i(program)0 3271 y(m)m(ust)i(ha)m(v)m(e)h(had)f(a)g(go)s(o)s(d)g(reason)h(for)f(c)m (hanging)h(the)f(v)-5 b(alue)33 b(directly)-8 b(.)47 b(This)31 b(is)h(not)h(recommended,)f(ho)m(w)m(ev)m(er,)0 3384 y(and)j(is)h(only)g(pro)m(vided)g(for)f(bac)m(kw)m(ard)h (compatibilit)m(y)i(with)e(soft)m(w)m(are)h(that)g(initially)g(creates) g(a)f(table)h(with)0 3497 y(a)d(large)h(n)m(um)m(b)s(er)e(of)h(ro)m (ws,)h(than)f(decreases)g(the)h(NAXIS2)f(v)-5 b(alue)34 b(to)h(the)f(actual)h(smaller)g(v)-5 b(alue)34 b(just)f(b)s(efore)0 3610 y(closing)e(the)g(table.)0 3941 y Fe(4.12)136 b(Lo)t(cal)45 b(FITS)e(Con)l(v)l(en)l(tions)k(supp)t(orted)d(b)l(y)h(FITSIO)0 4191 y Fj(CFITSIO)29 b(supp)s(orts)g(sev)m(eral)j(lo)s(cal)g(FITS)e (con)m(v)m(en)m(tions)i(whic)m(h)f(are)g(not)g(de\014ned)e(in)i(the)f (o\016cial)j(FITS)d(stan-)0 4304 y(dard)43 b(and)g(whic)m(h)g(are)h (not)g(necessarily)g(recognized)h(or)f(supp)s(orted)e(b)m(y)h(other)h (FITS)f(soft)m(w)m(are)i(pac)m(k)-5 b(ages.)0 4417 y(Programmers)36 b(should)f(b)s(e)g(cautious)i(ab)s(out)e(using)h(these)g(features,)i (esp)s(ecially)f(if)f(the)g(FITS)f(\014les)h(that)h(are)0 4530 y(pro)s(duced)31 b(are)i(exp)s(ected)g(to)g(b)s(e)f(pro)s(cessed)g (b)m(y)h(other)f(soft)m(w)m(are)i(systems)f(whic)m(h)f(do)h(not)f(use)h (the)f(CFITSIO)0 4642 y(in)m(terface.)0 4930 y Fc(4.12.1)113 b(Supp)s(ort)37 b(for)h(Long)g(String)f(Keyw)m(ord)h(V)-9 b(alues.)0 5149 y Fj(The)23 b(length)i(of)f(a)g(standard)f(FITS)g (string)h(k)m(eyw)m(ord)g(is)g(limited)h(to)f(68)h(c)m(haracters)g(b)s (ecause)f(it)g(m)m(ust)g(\014t)g(en)m(tirely)0 5262 y(within)35 b(a)h(single)h(FITS)e(header)h(k)m(eyw)m(ord)g(record.)57 b(In)35 b(some)h(instances)g(it)h(is)e(necessary)i(to)f(enco)s(de)g (strings)0 5375 y(longer)27 b(than)f(this)g(limit,)i(so)e(FITSIO)f (supp)s(orts)f(a)j(lo)s(cal)g(con)m(v)m(en)m(tion)h(in)e(whic)m(h)g (the)g(string)g(v)-5 b(alue)27 b(is)f(con)m(tin)m(ued)0 5488 y(o)m(v)m(er)34 b(m)m(ultiple)g(k)m(eyw)m(ords.)49 b(This)32 b(con)m(tin)m(uation)j(con)m(v)m(en)m(tion)h(uses)c(an)h(amp) s(ersand)f(c)m(haracter)i(at)g(the)f(end)g(of)0 5601 y(eac)m(h)c(substring)d(to)i(indicate)h(that)f(it)g(is)g(con)m(tin)m (ued)g(on)f(the)h(next)g(k)m(eyw)m(ord,)h(and)d(the)i(con)m(tin)m (uation)i(k)m(eyw)m(ords)0 5714 y(all)44 b(ha)m(v)m(e)h(the)f(name)f (CONTINUE)g(without)g(an)h(equal)g(sign)f(in)g(column)h(9.)80 b(The)43 b(string)h(v)-5 b(alue)43 b(ma)m(y)i(b)s(e)p eop end %%Page: 22 28 TeXDict begin 22 27 bop 0 299 a Fj(22)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fj(con)m(tin)m(ued)e(in)f(this)h(w)m(a)m(y)g(o)m(v)m(er)h(as)e (man)m(y)h(additional)g(CONTINUE)f(k)m(eyw)m(ords)g(as)h(is)f (required.)40 b(The)27 b(follo)m(wing)0 668 y(lines)k(illustrate)g (this)f(con)m(tin)m(uation)j(con)m(v)m(en)m(tion)f(whic)m(h)e(is)h (used)e(in)h(the)h(v)-5 b(alue)31 b(of)f(the)h(STRKEY)e(k)m(eyw)m(ord:) 0 920 y Ff(LONGSTRN=)45 b('OGIP)i(1.0')524 b(/)47 b(The)g(OGIP)g(Long)f (String)g(Convention)f(may)i(be)g(used.)0 1033 y(STRKEY)94 b(=)47 b('This)g(is)g(a)g(very)g(long)g(string)f(keyword&')93 b(/)47 b(Optional)f(Comment)0 1146 y(CONTINUE)93 b(')48 b(value)e(that)h(is)g(continued)e(over)i(3)g(keywords)f(in)h(the)g(&)95 b(')0 1259 y(CONTINUE)e('FITS)47 b(header.')e(/)j(This)e(is)h(another)f (optional)g(comment.)0 1511 y Fj(It)29 b(is)g(recommended)f(that)h(the) g(LONGSTRN)f(k)m(eyw)m(ord,)i(as)f(sho)m(wn)f(here,)h(alw)m(a)m(ys)i(b) s(e)d(included)g(in)g(an)m(y)h(HDU)0 1624 y(that)f(uses)e(this)h (longstring)h(con)m(v)m(en)m(tion.)42 b(A)27 b(subroutine)f(called)i (FTPLSW)f(has)g(b)s(een)f(pro)m(vided)h(in)f(CFITSIO)0 1737 y(to)31 b(write)g(this)f(k)m(eyw)m(ord)h(if)f(it)h(do)s(es)f(not)h (already)g(exist.)0 1897 y(This)23 b(long)i(string)g(con)m(v)m(en)m (tion)h(is)e(supp)s(orted)f(b)m(y)h(the)g(follo)m(wing)i(FITSIO)d (subroutines)g(that)i(deal)g(with)f(string-)0 2010 y(v)-5 b(alued)30 b(k)m(eyw)m(ords:)286 2262 y Ff(ftgkys)46 b(-)i(read)f(a)g(string)f(keyword)286 2375 y(ftpkls)g(-)i(write)e (\(append\))g(a)h(string)f(keyword)286 2488 y(ftikls)g(-)i(insert)e(a)h (string)g(keyword)286 2601 y(ftmkls)f(-)i(modify)e(the)h(value)f(of)h (an)h(existing)d(string)h(keyword)286 2714 y(ftukls)g(-)i(update)e(an)h (existing)f(keyword,)f(or)i(write)g(a)g(new)g(keyword)286 2827 y(ftdkey)f(-)i(delete)e(a)h(keyword)0 3079 y Fj(These)41 b(routines)f(will)h(transparen)m(tly)g(read,)j(write,)g(or)d(delete)h (a)f(long)g(string)g(v)-5 b(alue)41 b(in)g(the)g(FITS)f(\014le,)k(so)0 3192 y(programmers)36 b(in)g(general)h(do)f(not)h(ha)m(v)m(e)g(to)g(b)s (e)f(concerned)g(ab)s(out)g(the)g(details)i(of)e(the)h(con)m(v)m(en)m (tion)h(that)f(is)0 3304 y(used)32 b(to)i(enco)s(de)f(the)g(long)g (string)g(in)g(the)g(FITS)f(header.)48 b(When)33 b(reading)g(a)g(long)h (string,)g(one)f(m)m(ust)g(ensure)0 3417 y(that)h(the)f(c)m(haracter)i (string)f(parameter)g(used)e(in)h(these)h(subroutine)e(calls)j(has)e(b) s(een)f(declared)i(long)g(enough)0 3530 y(to)d(hold)f(the)h(en)m(tire)g (string,)g(otherwise)f(the)h(returned)e(string)h(v)-5 b(alue)31 b(will)g(b)s(e)f(truncated.)0 3690 y(Note)d(that)e(the)h (more)f(commonly)h(used)e(FITSIO)g(subroutine)h(to)h(write)f(string)g (v)-5 b(alued)25 b(k)m(eyw)m(ords)h(\(FTPKYS\))0 3803 y(do)s(es)38 b(NOT)g(supp)s(ort)f(this)h(long)h(string)g(con)m(v)m(en)m (tion)h(and)e(only)h(supp)s(orts)d(strings)i(up)g(to)h(68)g(c)m (haracters)h(in)0 3916 y(length.)i(This)30 b(has)g(b)s(een)g(done)h (delib)s(erately)g(to)h(prev)m(en)m(t)f(programs)g(from)f(inadv)m (erten)m(tly)i(writing)f(k)m(eyw)m(ords)0 4029 y(using)38 b(this)h(non-standard)e(con)m(v)m(en)m(tion)k(without)e(the)f(explicit) i(in)m(ten)m(t)g(of)f(the)g(programmer)f(or)h(user.)64 b(The)0 4142 y(FTPKLS)28 b(subroutine)g(m)m(ust)h(b)s(e)g(called)h (instead)g(to)g(write)f(long)h(strings.)40 b(This)28 b(routine)i(can)f(also)h(b)s(e)f(used)f(to)0 4255 y(write)j(ordinary)e (string)i(v)-5 b(alues)30 b(less)h(than)f(68)h(c)m(haracters)h(in)e (length.)0 4544 y Fc(4.12.2)113 b(Arra)m(ys)37 b(of)g(Fixed-Length)j (Strings)e(in)f(Binary)h(T)-9 b(ables)0 4763 y Fj(CFITSIO)25 b(supp)s(orts)g(2)i(w)m(a)m(ys)g(to)g(sp)s(ecify)f(that)i(a)f(c)m (haracter)h(column)e(in)g(a)h(binary)f(table)i(con)m(tains)f(an)g(arra) m(y)g(of)0 4876 y(\014xed-length)32 b(strings.)46 b(The)32 b(\014rst)f(w)m(a)m(y)-8 b(,)34 b(whic)m(h)e(is)g(o\016cially)i(supp)s (orted)c(b)m(y)i(the)h(FITS)e(Standard)g(do)s(cumen)m(t,)0 4989 y(uses)38 b(the)g(TDIMn)g(k)m(eyw)m(ord.)65 b(F)-8 b(or)39 b(example,)i(if)d(TF)m(ORMn)g(=)g('60A')h(and)f(TDIMn)g(=)g ('\(12,5\)')i(then)e(that)0 5102 y(column)30 b(will)h(b)s(e)f(in)m (terpreted)g(as)h(con)m(taining)h(an)e(arra)m(y)h(of)g(5)f(strings,)h (eac)m(h)g(12)g(c)m(haracters)h(long.)0 5262 y(FITSIO)40 b(also)i(supp)s(orts)d(a)i(lo)s(cal)h(con)m(v)m(en)m(tion)h(for)e(the)g (format)h(of)f(the)g(TF)m(ORMn)g(k)m(eyw)m(ord)g(v)-5 b(alue)42 b(of)f(the)0 5375 y(form)h('rAw')g(where)g('r')g(is)h(an)f (in)m(teger)i(sp)s(ecifying)e(the)g(total)j(width)c(in)h(c)m(haracters) i(of)f(the)f(column,)k(and)0 5488 y('w')36 b(is)g(an)g(in)m(teger)h(sp) s(ecifying)f(the)g(\(\014xed\))g(length)h(of)f(an)g(individual)f(unit)h (string)f(within)h(the)g(v)m(ector.)59 b(F)-8 b(or)0 5601 y(example,)47 b(TF)m(ORM1)d(=)f('120A10')j(w)m(ould)d(indicate)h (that)f(the)h(binary)e(table)i(column)f(is)g(120)h(c)m(haracters)0 5714 y(wide)32 b(and)g(consists)h(of)g(12)g(10-c)m(haracter)i(length)e (strings.)47 b(This)31 b(con)m(v)m(en)m(tion)k(is)d(recognized)i(b)m(y) e(the)h(FITSIO)p eop end %%Page: 23 29 TeXDict begin 23 28 bop 0 299 a Fh(4.12.)73 b(LOCAL)29 b(FITS)h(CONVENTIONS)f(SUPPOR)-8 b(TED)29 b(BY)i(FITSIO)1168 b Fj(23)0 555 y(subroutines)40 b(that)h(read)g(or)g(write)g(strings)f (in)h(binary)f(tables.)73 b(The)40 b(Binary)h(T)-8 b(able)42 b(de\014nition)e(do)s(cumen)m(t)0 668 y(sp)s(eci\014es)31 b(that)i(other)e(optional)i(c)m(haracters)g(ma)m(y)g(follo)m(w)g(the)e (datat)m(yp)s(e)i(co)s(de)f(in)f(the)h(TF)m(ORM)g(k)m(eyw)m(ord,)h(so)0 781 y(this)j(lo)s(cal)i(con)m(v)m(en)m(tion)h(is)e(in)f(compliance)i (with)e(the)h(FITS)f(standard,)h(although)g(other)g(FITS)f(readers)h (are)0 894 y(not)31 b(required)e(to)i(recognize)h(this)f(con)m(v)m(en)m (tion.)0 1183 y Fc(4.12.3)113 b(Keyw)m(ord)37 b(Units)h(Strings)0 1402 y Fj(One)f(de\014ciency)h(of)g(the)g(curren)m(t)g(FITS)f(Standard) f(is)i(that)h(it)f(do)s(es)f(not)h(de\014ne)f(a)i(sp)s(eci\014c)e(con)m (v)m(en)m(tion)j(for)0 1515 y(recording)30 b(the)g(ph)m(ysical)h(units) f(of)g(a)g(k)m(eyw)m(ord)h(v)-5 b(alue.)41 b(The)30 b(TUNITn)f(k)m(eyw) m(ord)h(can)g(b)s(e)g(used)f(to)i(sp)s(ecify)f(the)0 1628 y(ph)m(ysical)36 b(units)f(of)g(the)h(v)-5 b(alues)36 b(in)f(a)g(table)i(column,)f(but)f(there)g(is)h(no)f(analogous)i(con)m (v)m(en)m(tion)g(for)e(k)m(eyw)m(ord)0 1741 y(v)-5 b(alues.)42 b(The)30 b(commen)m(t)h(\014eld)g(of)f(the)h(k)m(eyw)m(ord)g(is)g (often)g(used)f(for)g(this)g(purp)s(ose,)g(but)f(the)i(units)f(are)h (usually)0 1854 y(not)g(sp)s(eci\014ed)e(in)h(a)h(w)m(ell)g(de\014ned)f (format)g(that)h(FITS)f(readers)g(can)h(easily)g(recognize)h(and)e (extract.)0 2014 y(T)-8 b(o)28 b(solv)m(e)h(this)e(de\014ciency)-8 b(,)30 b(FITSIO)c(uses)h(a)h(lo)s(cal)h(con)m(v)m(en)m(tion)h(in)d (whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)0 2127 y(square)20 b(brac)m(k)m(ets)j(as)e(the)f(\014rst)g(tok)m(en)i(in) f(the)f(k)m(eyw)m(ord)i(commen)m(t)f(\014eld;)j(more)d(sp)s (eci\014cally)-8 b(,)24 b(the)d(op)s(ening)f(square)0 2240 y(brac)m(k)m(et)28 b(immediately)g(follo)m(ws)f(the)g(slash)f('/') h(commen)m(t)h(\014eld)e(delimiter)h(and)f(a)g(single)h(space)g(c)m (haracter.)41 b(The)0 2352 y(follo)m(wing)32 b(examples)f(illustrate)g (k)m(eyw)m(ords)g(that)g(use)f(this)g(con)m(v)m(en)m(tion:)0 2602 y Ff(EXPOSURE=)713 b(1800.0)47 b(/)g([s])g(elapsed)f(exposure)f (time)0 2715 y(V_HELIO)h(=)763 b(16.23)47 b(/)g([km)g(s**\(-1\)])e (heliocentric)g(velocity)0 2828 y(LAMBDA)94 b(=)763 b(5400.)47 b(/)g([angstrom])e(central)h(wavelength)0 2941 y(FLUX)190 b(=)47 b(4.9033487787637465E-30)42 b(/)47 b([J/cm**2/s])e(average)h (flux)0 3191 y Fj(In)28 b(general,)h(the)g(units)e(named)h(in)g(the)h (IA)m(U\(1988\))i(St)m(yle)e(Guide)f(are)h(recommended,)f(with)g(the)h (main)f(excep-)0 3304 y(tion)j(that)g(the)f(preferred)g(unit)f(for)i (angle)g(is)f('deg')i(for)e(degrees.)0 3464 y(The)24 b(FTPUNT)g(and)g(FTGUNT)h(subroutines)f(in)g(FITSIO)f(write)i(and)f (read,)i(resp)s(ectiv)m(ely)-8 b(,)28 b(the)c(k)m(eyw)m(ord)h(unit)0 3577 y(strings)30 b(in)g(an)h(existing)g(k)m(eyw)m(ord.)0 3866 y Fc(4.12.4)113 b(HIERAR)m(CH)34 b(Con)m(v)m(en)m(tion)k(for)f (Extended)h(Keyw)m(ord)f(Names)0 4085 y Fj(CFITSIO)k(supp)s(orts)g(the) i(HIERAR)m(CH)g(k)m(eyw)m(ord)g(con)m(v)m(en)m(tion)i(whic)m(h)e(allo)m (ws)h(k)m(eyw)m(ord)f(names)g(that)h(are)0 4198 y(longer)35 b(than)f(8)h(c)m(haracters.)54 b(This)34 b(con)m(v)m(en)m(tion)i(w)m (as)f(dev)m(elop)s(ed)g(at)g(the)g(Europ)s(ean)e(Southern)g(Observ)-5 b(atory)0 4311 y(\(ESO\))34 b(and)g(allo)m(ws)h(c)m(haracters)h (consisting)f(of)f(digits)h(0-9,)i(upp)s(er)32 b(case)j(letters)h(A-Z,) e(the)h(dash)e('-')i(and)f(the)0 4424 y(underscore)j(')p 493 4424 28 4 v 33 w('.)63 b(The)37 b(comp)s(onen)m(ts)h(of)g(hierarc)m (hical)h(k)m(eyw)m(ords)f(are)g(separated)g(b)m(y)g(a)g(single)g(ASCI)s (I)e(space)0 4537 y(c)m(harater.)42 b(F)-8 b(or)31 b(instance:)0 4787 y Ff(HIERARCH)46 b(ESO)g(INS)h(FOCU)g(POS)g(=)g(-0.00002500)e(/)j (Focus)e(position)0 5036 y Fj(Basically)-8 b(,)42 b(this)c(con)m(v)m (en)m(tion)h(uses)f(the)f(FITS)g(k)m(eyw)m(ord)h('HIERAR)m(CH')g(to)h (indicate)f(that)g(this)g(con)m(v)m(en)m(tion)0 5149 y(is)j(b)s(eing)f(used,)j(then)d(the)h(actual)h(k)m(eyw)m(ord)f(name)g (\()p Ff('ESO)47 b(INS)g(FOCU)g(POS')39 b Fj(in)i(this)f(example\))i(b) s(egins)e(in)0 5262 y(column)h(10.)74 b(The)41 b(equals)g(sign)g(marks) g(the)g(end)g(of)g(the)h(k)m(eyw)m(ord)f(name)g(and)g(is)g(follo)m(w)m (ed)i(b)m(y)e(the)g(usual)0 5375 y(v)-5 b(alue)37 b(and)e(commen)m(t)j (\014elds)e(just)f(as)i(in)f(standard)f(FITS)h(k)m(eyw)m(ords.)59 b(F)-8 b(urther)36 b(details)h(of)g(this)f(con)m(v)m(en)m(tion)0 5488 y(are)30 b(describ)s(ed)f(at)i(h)m(ttp://\014ts.gsfc.nasa.go)m (v/registry/hierarc)m(h)p 2323 5488 V 38 w(k)m(eyw)m(ord.h)m(tml)g(and) f(in)g(Section)g(4.4)i(of)e(the)0 5601 y(ESO)40 b(Data)i(In)m(terface)g (Con)m(trol)g(Do)s(cumen)m(t)g(that)f(is)g(link)m(ed)g(to)h(from)e(h)m (ttp://arc)m(hiv)m(e.eso.org/cms/to)t(ols-)0 5714 y(do)s(cumen)m (tation/eso-data-in)m(terface-con)m(t)q(rol.h)m(tml.)p eop end %%Page: 24 30 TeXDict begin 24 29 bop 0 299 a Fj(24)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fj(This)h(con)m(v)m(en)m(tion)i(allo)m(ws)g(a)f(broader)f(range)h (of)g(k)m(eyw)m(ord)f(names)h(than)f(is)h(allo)m(w)m(ed)h(b)m(y)e(the)h (FITS)f(Standard.)0 668 y(Here)f(are)g(more)f(examples)h(of)g(suc)m(h)f (k)m(eyw)m(ords:)0 941 y Ff(HIERARCH)46 b(LONGKEYWORD)e(=)k(47.5)e(/)i (Keyword)e(has)h(>)g(8)g(characters)0 1054 y(HIERARCH)f(LONG-KEY_WORD2) d(=)48 b(52.3)f(/)g(Long)g(keyword)e(with)i(hyphen,)f(underscore)f(and) i(digit)0 1167 y(HIERARCH)f(EARTH)g(IS)h(A)h(STAR)e(=)i(F)f(/)h (Keyword)d(contains)h(embedded)f(spaces)0 1440 y Fj(CFITSIO)40 b(will)i(transparen)m(tly)g(read)g(and)f(write)g(these)i(k)m(eyw)m (ords,)i(so)d(application)h(programs)e(do)g(not)h(in)0 1553 y(general)33 b(need)f(to)h(kno)m(w)f(an)m(ything)h(ab)s(out)f(the) g(sp)s(eci\014c)g(implemen)m(tation)i(details)f(of)g(the)f(HIERAR)m(CH) g(con-)0 1666 y(v)m(en)m(tion.)50 b(In)32 b(particular,)j(application)f (programs)e(do)h(not)h(need)e(to)i(sp)s(ecify)f(the)g(`HIERAR)m(CH')h (part)f(of)g(the)0 1779 y(k)m(eyw)m(ord)g(name)f(when)g(reading)g(or)g (writing)h(k)m(eyw)m(ords)f(\(although)h(it)g(ma)m(y)g(b)s(e)f (included)f(if)i(desired\).)46 b(When)0 1892 y(writing)35 b(a)g(k)m(eyw)m(ord,)h(CFITSIO)d(\014rst)h(c)m(hec)m(ks)i(to)f(see)g (if)g(the)g(k)m(eyw)m(ord)g(name)f(is)h(legal)h(as)f(a)g(standard)f (FITS)0 2005 y(k)m(eyw)m(ord)k(\(no)g(more)f(than)h(8)g(c)m(haracters)h (long)f(and)f(con)m(taining)i(only)e(letters,)k(digits,)f(or)e(a)g(min) m(us)e(sign)i(or)0 2117 y(underscore\).)68 b(If)39 b(so)h(it)g(writes)g (it)g(as)f(a)h(standard)f(FITS)g(k)m(eyw)m(ord,)k(otherwise)d(it)g (uses)f(the)h(hierarc)m(h)f(con-)0 2230 y(v)m(en)m(tion)34 b(to)f(write)g(the)f(k)m(eyw)m(ord.)48 b(The)32 b(maxim)m(um)g(k)m(eyw) m(ord)h(name)f(length)h(is)g(67)g(c)m(haracters,)i(whic)m(h)d(lea)m(v)m (es)0 2343 y(only)c(1)h(space)g(for)f(the)h(v)-5 b(alue)29 b(\014eld.)39 b(A)29 b(more)f(practical)i(limit)f(is)g(ab)s(out)f(40)h (c)m(haracters,)i(whic)m(h)d(lea)m(v)m(es)i(enough)0 2456 y(ro)s(om)e(for)h(most)f(k)m(eyw)m(ord)h(v)-5 b(alues.)41 b(CFITSIO)27 b(returns)g(an)h(error)h(if)f(there)h(is)f(not)h(enough)f (ro)s(om)h(for)f(b)s(oth)g(the)0 2569 y(k)m(eyw)m(ord)k(name)f(and)f (the)i(k)m(eyw)m(ord)f(v)-5 b(alue)32 b(on)f(the)h(80-c)m(haracter)h (card,)f(except)g(for)f(string-v)-5 b(alued)32 b(k)m(eyw)m(ords)0 2682 y(whic)m(h)f(are)h(simply)e(truncated)i(so)f(that)h(the)f(closing) i(quote)f(c)m(haracter)h(falls)e(in)g(column)g(80.)45 b(A)31 b(space)h(is)f(also)0 2795 y(required)f(on)g(either)h(side)f(of) h(the)f(equal)h(sign.)0 3144 y Fe(4.13)136 b(Optimizing)45 b(Co)t(de)g(for)h(Maxim)l(um)f(Pro)t(cessing)g(Sp)t(eed)0 3397 y Fj(CFITSIO)22 b(has)h(b)s(een)f(carefully)i(designed)f(to)h (obtain)g(the)f(highest)h(p)s(ossible)e(sp)s(eed)h(when)f(reading)h (and)g(writing)0 3510 y(FITS)33 b(\014les.)51 b(In)33 b(order)h(to)g(ac)m(hiev)m(e)i(the)e(b)s(est)g(p)s(erformance,)g(ho)m (w)m(ev)m(er,)i(application)g(programmers)d(m)m(ust)h(b)s(e)0 3623 y(careful)24 b(to)h(call)g(the)f(CFITSIO)f(routines)g (appropriately)i(and)e(in)h(an)f(e\016cien)m(t)j(sequence;)h (inappropriate)c(usage)0 3736 y(of)31 b(CFITSIO)d(routines)j(can)f (greatly)i(slo)m(w)f(do)m(wn)f(the)h(execution)g(sp)s(eed)f(of)g(a)h (program.)0 3896 y(The)f(maxim)m(um)h(p)s(ossible)f(I/O)h(sp)s(eed)f (of)h(CFITSIO)e(dep)s(ends)g(of)i(course)g(on)f(the)h(t)m(yp)s(e)g(of)g (computer)g(system)0 4009 y(that)j(it)g(is)g(running)d(on.)50 b(T)-8 b(o)34 b(get)h(a)f(general)g(idea)g(of)g(what)f(data)i(I/O)e(sp) s(eeds)f(are)i(p)s(ossible)f(on)h(a)g(particular)0 4122 y(mac)m(hine,)j(build)e(the)g(sp)s(eed.c)g(program)g(that)h(is)g (distributed)e(with)h(CFITSIO)f(\(t)m(yp)s(e)i('mak)m(e)g(sp)s(eed')f (in)g(the)0 4235 y(CFITSIO)e(directory\).)54 b(This)33 b(diagnostic)j(program)e(measures)h(the)f(sp)s(eed)g(of)g(writing)h (and)f(reading)g(bac)m(k)i(a)0 4348 y(test)31 b(FITS)f(image,)i(a)f (binary)e(table,)j(and)d(an)i(ASCI)s(I)e(table.)0 4508 y(The)k(follo)m(wing)h(2)g(sections)g(pro)m(vide)g(some)f(bac)m (kground)g(on)h(ho)m(w)f(CFITSIO)f(in)m(ternally)i(manages)g(the)f (data)0 4621 y(I/O)g(and)g(describ)s(es)f(some)i(strategies)h(that)f (ma)m(y)g(b)s(e)e(used)h(to)h(optimize)g(the)g(pro)s(cessing)f(sp)s (eed)f(of)h(soft)m(w)m(are)0 4734 y(that)e(uses)f(CFITSIO.)0 5040 y Fc(4.13.1)113 b(Bac)m(kground)38 b(Information:)50 b(Ho)m(w)37 b(CFITSIO)h(Manages)h(Data)f(I/O)0 5262 y Fj(Man)m(y)22 b(CFITSIO)e(op)s(erations)i(in)m(v)m(olv)m(e)i (transferring)d(only)h(a)g(small)g(n)m(um)m(b)s(er)f(of)h(b)m(ytes)g (to)g(or)g(from)f(the)h(FITS)f(\014le)0 5375 y(\(e.g,)31 b(reading)e(a)g(k)m(eyw)m(ord,)h(or)f(writing)g(a)g(ro)m(w)g(in)f(a)h (table\);)i(it)f(w)m(ould)e(b)s(e)g(v)m(ery)i(ine\016cien)m(t)g(to)f (ph)m(ysically)h(read)0 5488 y(or)i(write)h(suc)m(h)f(small)g(blo)s(c)m (ks)h(of)f(data)h(directly)g(in)f(the)g(FITS)g(\014le)g(on)g(disk,)h (therefore)f(CFITSIO)f(main)m(tains)0 5601 y(a)38 b(set)g(of)g(in)m (ternal)h(Input{Output)c(\(IO\))j(bu\013ers)f(in)g(RAM)h(memory)g(that) g(eac)m(h)h(con)m(tain)g(one)f(FITS)f(blo)s(c)m(k)0 5714 y(\(2880)27 b(b)m(ytes\))f(of)f(data.)40 b(Whenev)m(er)25 b(CFITSIO)f(needs)g(to)i(access)g(data)g(in)f(the)g(FITS)f(\014le,)j (it)e(\014rst)f(transfers)h(the)p eop end %%Page: 25 31 TeXDict begin 25 30 bop 0 299 a Fh(4.13.)73 b(OPTIMIZING)29 b(CODE)h(F)m(OR)h(MAXIMUM)g(PR)m(OCESSING)f(SPEED)971 b Fj(25)0 555 y(FITS)30 b(blo)s(c)m(k)h(con)m(taining)h(those)f(b)m (ytes)g(in)m(to)g(one)g(of)f(the)h(IO)f(bu\013ers)f(in)h(memory)-8 b(.)42 b(The)30 b(next)g(time)h(CFITSIO)0 668 y(needs)36 b(to)g(access)i(b)m(ytes)e(in)g(the)g(same)h(blo)s(c)m(k)f(it)h(can)f (then)g(go)h(to)f(the)h(fast)f(IO)f(bu\013er)g(rather)h(than)g(using)g (a)0 781 y(m)m(uc)m(h)c(slo)m(w)m(er)i(system)e(disk)g(access)h (routine.)46 b(The)32 b(n)m(um)m(b)s(er)f(of)h(a)m(v)-5 b(ailable)35 b(IO)d(bu\013ers)f(is)h(determined)g(b)m(y)g(the)0 894 y(NIOBUF)f(parameter)g(\(in)f(\014tsio2.h\))h(and)f(is)h(curren)m (tly)f(set)h(to)g(40.)0 1054 y(Whenev)m(er)24 b(CFITSIO)f(reads)g(or)h (writes)g(data)g(it)h(\014rst)e(c)m(hec)m(ks)i(to)g(see)f(if)g(that)g (blo)s(c)m(k)h(of)f(the)g(FITS)f(\014le)g(is)h(already)0 1167 y(loaded)33 b(in)m(to)g(one)f(of)g(the)g(IO)g(bu\013ers.)44 b(If)32 b(not,)h(and)e(if)h(there)g(is)g(an)g(empt)m(y)h(IO)e(bu\013er) g(a)m(v)-5 b(ailable,)35 b(then)d(it)h(will)0 1280 y(load)g(that)h(blo) s(c)m(k)f(in)m(to)g(the)g(IO)g(bu\013er)e(\(when)h(reading)h(a)g(FITS)f (\014le\))h(or)g(will)g(initialize)i(a)e(new)f(blo)s(c)m(k)i(\(when)0 1393 y(writing)j(to)h(a)g(FITS)f(\014le\).)62 b(If)37 b(all)h(the)g(IO)e(bu\013ers)h(are)g(already)h(full,)h(it)f(m)m(ust)g (decide)f(whic)m(h)g(one)h(to)g(reuse)0 1506 y(\(generally)c(the)f(one) g(that)g(has)f(b)s(een)g(accessed)i(least)f(recen)m(tly\),)i(and)d (\015ush)f(the)i(con)m(ten)m(ts)h(bac)m(k)g(to)f(disk)f(if)g(it)0 1619 y(has)e(b)s(een)g(mo)s(di\014ed)f(b)s(efore)h(loading)h(the)g(new) f(blo)s(c)m(k.)0 1779 y(The)g(one)g(ma)5 b(jor)30 b(exception)i(to)f (the)f(ab)s(o)m(v)m(e)h(pro)s(cess)f(o)s(ccurs)g(whenev)m(er)g(a)g (large)i(con)m(tiguous)f(set)g(of)f(b)m(ytes)h(are)0 1892 y(accessed,)37 b(as)d(migh)m(t)i(o)s(ccur)e(when)f(reading)i(or)f (writing)g(a)h(FITS)f(image.)54 b(In)34 b(this)g(case)h(CFITSIO)e(b)m (ypasses)0 2005 y(the)i(in)m(ternal)h(IO)f(bu\013ers)f(and)g(simply)h (reads)g(or)g(writes)h(the)f(desired)g(b)m(ytes)g(directly)h(in)f(the)g (disk)g(\014le)g(with)0 2118 y(a)i(single)g(call)g(to)g(a)g(lo)m(w-lev) m(el)i(\014le)d(read)g(or)h(write)f(routine.)58 b(The)36 b(minim)m(um)g(threshold)f(for)h(the)h(n)m(um)m(b)s(er)e(of)0 2230 y(b)m(ytes)27 b(to)g(read)f(or)g(write)g(this)g(w)m(a)m(y)i(is)e (set)g(b)m(y)h(the)f(MINDIRECT)g(parameter)g(and)g(is)g(curren)m(tly)g (set)h(to)g(3)g(FITS)0 2343 y(blo)s(c)m(ks)36 b(=)g(8640)i(b)m(ytes.)58 b(This)35 b(is)h(the)g(most)g(e\016cien)m(t)i(w)m(a)m(y)f(to)g(read)e (or)h(write)h(large)g(c)m(h)m(unks)e(of)h(data.)59 b(Note)0 2456 y(that)34 b(this)f(fast)h(direct)g(IO)f(pro)s(cess)f(is)i(not)f (applicable)i(when)d(accessing)j(columns)e(of)h(data)g(in)f(a)g(FITS)g (table)0 2569 y(b)s(ecause)f(the)h(b)m(ytes)g(are)g(generally)g(not)g (con)m(tiguous)g(since)g(they)g(are)f(in)m(terlea)m(v)m(ed)j(b)m(y)e (the)f(other)h(columns)f(of)0 2682 y(data)i(in)e(the)h(table.)49 b(This)33 b(explains)g(wh)m(y)f(the)h(sp)s(eed)f(for)h(accessing)h (FITS)e(tables)i(is)f(generally)h(slo)m(w)m(er)g(than)0 2795 y(accessing)e(FITS)e(images.)0 2955 y(Giv)m(en)i(this)g(bac)m (kground)f(information,)h(the)g(general)g(strategy)h(for)e(e\016cien)m (tly)i(accessing)g(FITS)e(\014les)g(should)0 3068 y(no)m(w)36 b(b)s(e)g(apparen)m(t:)52 b(when)35 b(dealing)i(with)f(FITS)g(images,)j (read)d(or)g(write)g(large)i(c)m(h)m(unks)e(of)g(data)h(at)g(a)f(time)0 3181 y(so)30 b(that)h(the)f(direct)h(IO)e(mec)m(hanism)h(will)h(b)s(e)e (in)m(v)m(ok)m(ed;)j(when)d(accessing)j(FITS)d(headers)h(or)g(FITS)f (tables,)i(on)0 3294 y(the)k(other)g(hand,)g(once)g(a)g(particular)h (FITS)e(blo)s(c)m(k)h(has)f(b)s(een)g(loading)i(in)m(to)g(one)f(of)g (the)f(IO)h(bu\013ers,)g(try)f(to)0 3407 y(access)39 b(all)f(the)f(needed)g(information)h(in)f(that)h(blo)s(c)m(k)g(b)s (efore)f(it)h(gets)g(\015ushed)d(out)j(of)g(the)f(IO)g(bu\013er.)60 b(It)38 b(is)0 3520 y(imp)s(ortan)m(t)31 b(to)h(a)m(v)m(oid)g(the)f (situation)h(where)f(the)g(same)g(FITS)f(blo)s(c)m(k)i(is)f(b)s(eing)f (read)h(then)g(\015ushed)e(from)h(a)h(IO)0 3633 y(bu\013er)e(m)m (ultiple)i(times.)0 3793 y(The)f(follo)m(wing)i(section)f(giv)m(es)h (more)e(sp)s(eci\014c)h(suggestions)g(for)f(optimizing)i(the)e(use)g (of)h(CFITSIO.)0 4185 y Fc(4.13.2)113 b(Optimization)38 b(Strategies)0 4425 y Fj(1.)43 b(Because)32 b(the)f(data)g(in)g(FITS)f (\014les)h(is)g(alw)m(a)m(ys)h(stored)f(in)g("big-endian")h(b)m(yte)f (order,)g(where)f(the)h(\014rst)f(b)m(yte)0 4538 y(of)g(n)m(umeric)h(v) -5 b(alues)30 b(con)m(tains)i(the)e(most)h(signi\014can)m(t)g(bits)f (and)g(the)g(last)i(b)m(yte)e(con)m(tains)i(the)e(least)i(signi\014can) m(t)0 4650 y(bits,)e(CFITSIO)f(m)m(ust)h(sw)m(ap)g(the)g(order)f(of)h (the)h(b)m(ytes)f(when)f(reading)h(or)g(writing)g(FITS)g(\014les)g (when)f(running)0 4763 y(on)k(little-endian)i(mac)m(hines)f(\(e.g.,)i (Lin)m(ux)d(and)g(Microsoft)i(Windo)m(ws)e(op)s(erating)h(systems)g (running)d(on)j(PCs)0 4876 y(with)c(x86)h(CPUs\).)0 5036 y(On)i(fairly)h(new)f(CPUs)g(that)i(supp)s(ort)d("SSSE3")h(mac)m(hine)h (instructions)g(\(e.g.,)i(starting)f(with)e(In)m(tel)i(Core)f(2)0 5149 y(CPUs)21 b(in)h(2007,)j(and)d(in)f(AMD)i(CPUs)e(b)s(eginning)g (in)h(2011\))i(signi\014can)m(tly)f(faster)f(4-b)m(yte)h(and)e(8-b)m (yte)i(sw)m(apping)0 5262 y(algorithms)k(are)g(a)m(v)-5 b(ailable.)42 b(These)26 b(faster)h(b)m(yte)g(sw)m(apping)f(functions)g (are)h(not)g(used)e(b)m(y)i(default)f(in)g(CFITSIO)0 5375 y(\(b)s(ecause)c(of)f(the)h(p)s(oten)m(tial)g(co)s(de)g(p)s (ortablilit)m(y)g(issues\),)i(but)c(users)h(can)g(enable)h(them)f(on)h (supp)s(orted)d(platforms)0 5488 y(b)m(y)38 b(adding)f(the)h (appropriate)f(compiler)i(\015ags)e(\(-mssse3)i(with)e(gcc)i(or)f(icc)g (on)g(lin)m(ux\))g(when)e(compiling)j(the)0 5601 y(sw)m(appro)s(c.c)30 b(source)g(\014le,)g(whic)m(h)g(will)g(allo)m(w)i(the)e(compiler)g(to)h (generate)h(co)s(de)e(using)f(the)h(SSSE3)f(instruction)0 5714 y(set.)41 b(A)28 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(do)g (this)f(is)g(to)h(con\014gure)f(the)g(CFITSIO)f(library)h(with)g(the)g (follo)m(wing)i(command:)p eop end %%Page: 26 32 TeXDict begin 26 31 bop 0 299 a Fj(26)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)95 555 y Ff(>)96 b(./configure)44 b(--enable-ssse3)0 819 y Fj(Note,)37 b(ho)m(w)m(ev)m(er,)h(that)d(a)g(binary)f(executable)j (\014le)e(that)g(is)g(created)h(using)e(these)h(faster)g(functions)g (will)g(only)0 932 y(run)c(on)h(mac)m(hines)g(that)h(supp)s(ort)d(the)i (SSSE3)f(mac)m(hine)i(instructions.)45 b(It)33 b(will)f(crash)g(on)g (mac)m(hines)g(that)h(do)0 1045 y(not)e(supp)s(ort)d(them.)0 1205 y(F)-8 b(or)36 b(faster)f(2-b)m(yte)i(sw)m(aps)e(on)g(virtually)g (all)h(x86-64)h(CPUs)e(\(ev)m(en)h(those)g(that)f(do)g(not)h(supp)s (ort)d(SSSE3\),)j(a)0 1318 y(v)-5 b(arian)m(t)26 b(using)e(only)g(SSE2) g(instructions)h(exists.)39 b(SSE2)24 b(is)h(enabled)f(b)m(y)h(default) g(on)f(x86)p 3066 1318 28 4 v 34 w(64)h(CPUs)f(with)h(64-bit)0 1431 y(op)s(erating)30 b(systems)f(\(and)g(is)g(also)i(automatically)h (enabled)d(b)m(y)g(the)g({enable-ssse3)i(\015ag\).)41 b(When)30 b(running)d(on)0 1544 y(x86)p 143 1544 V 34 w(64)k(CPUs)g(with)f(32-bit)i(op)s(erating)g(systems,)f(these)g(faster) h(2-b)m(yte)g(sw)m(apping)f(algorithms)g(are)h(not)f(used)0 1657 y(b)m(y)f(default)h(in)f(CFITSIO,)f(but)h(can)g(b)s(e)g(enabled)g (explicitly)i(with:)0 1921 y Ff(./configure)45 b(--enable-sse2)0 2185 y Fj(Preliminary)f(testing)h(indicates)g(that)g(these)f(SSSE3)f (and)g(SSE2)g(based)h(b)m(yte-sw)m(apping)h(algorithms)g(can)0 2298 y(b)s(o)s(ost)31 b(the)h(CFITSIO)e(p)s(erformance)h(when)f (reading)i(or)f(writing)h(FITS)f(images)h(b)m(y)g(20\045)g(-)g(30\045)g (or)f(more.)45 b(It)0 2411 y(is)36 b(imp)s(ortan)m(t)g(to)g(note,)i(ho) m(w)m(ev)m(er,)h(that)d(compiler)g(optimization)i(m)m(ust)e(b)s(e)f (turned)f(on)i(\(e.g.,)j(b)m(y)d(using)f(the)0 2524 y(-O1)f(or)g(-O2)g (\015ags)g(in)g(gcc\))h(when)e(building)g(programs)h(that)g(use)g (these)g(fast)g(b)m(yte-sw)m(apping)h(algorithms)f(in)0 2636 y(order)d(to)h(reap)f(the)h(full)f(b)s(ene\014t)g(of)g(the)h (SSSE3)e(and)h(SSE2)g(instructions;)h(without)f(optimization,)j(the)e (co)s(de)0 2749 y(ma)m(y)f(actually)h(run)d(slo)m(w)m(er)i(than)f(when) g(using)g(more)g(traditional)i(b)m(yte-sw)m(apping)f(tec)m(hniques.)0 2910 y(2.)54 b(When)34 b(dealing)h(with)g(a)g(FITS)e(primary)h(arra)m (y)h(or)g(IMA)m(GE)g(extension,)i(it)e(is)f(more)h(e\016cien)m(t)h(to)f (read)g(or)0 3022 y(write)c(large)g(c)m(h)m(unks)f(of)g(the)h(image)g (at)h(a)e(time)h(\(at)h(least)f(3)g(FITS)f(blo)s(c)m(ks)g(=)g(8640)i(b) m(ytes\))f(so)g(that)g(the)f(direct)0 3135 y(IO)j(mec)m(hanism)h(will)f (b)s(e)g(used)g(as)g(describ)s(ed)g(in)g(the)g(previous)g(section.)51 b(Smaller)34 b(c)m(h)m(unks)f(of)g(data)h(are)g(read)0 3248 y(or)d(written)g(via)h(the)f(IO)f(bu\013ers,)g(whic)m(h)h(is)g (somewhat)g(less)g(e\016cien)m(t)i(b)s(ecause)e(of)g(the)g(extra)h(cop) m(y)f(op)s(eration)0 3361 y(and)26 b(additional)h(b)s(o)s(okk)m(eeping) g(steps)g(that)g(are)g(required.)39 b(In)26 b(principle)g(it)h(is)g (more)f(e\016cien)m(t)i(to)g(read)e(or)h(write)0 3474 y(as)i(big)g(an)g(arra)m(y)h(of)f(image)h(pixels)f(at)h(one)f(time)g (as)h(p)s(ossible,)f(ho)m(w)m(ev)m(er,)h(if)f(the)h(arra)m(y)f(b)s (ecomes)g(so)g(large)h(that)0 3587 y(the)i(op)s(erating)g(system)f (cannot)h(store)g(it)g(all)h(in)e(RAM,)h(then)f(the)h(p)s(erformance)f (ma)m(y)h(b)s(e)f(degraded)g(b)s(ecause)0 3700 y(of)g(the)f(increased)h (sw)m(apping)f(of)g(virtual)h(memory)f(to)h(disk.)0 3860 y(3.)51 b(When)33 b(dealing)i(with)e(FITS)g(tables,)j(the)e(most)g(imp) s(ortan)m(t)g(e\016ciency)g(factor)h(in)e(the)h(soft)m(w)m(are)h (design)f(is)0 3973 y(to)j(read)f(or)g(write)g(the)g(data)h(in)f(the)g (FITS)g(\014le)g(in)g(a)g(single)h(pass)f(through)f(the)h(\014le.)58 b(An)36 b(example)h(of)f(p)s(o)s(or)0 4086 y(program)g(design)h(w)m (ould)f(b)s(e)g(to)h(read)g(a)f(large,)k(3-column)d(table)g(b)m(y)g (sequen)m(tially)h(reading)f(the)f(en)m(tire)i(\014rst)0 4199 y(column,)25 b(then)f(going)h(bac)m(k)f(to)h(read)e(the)h(2nd)g (column,)h(and)e(\014nally)h(the)g(3rd)f(column;)j(this)e(ob)m(viously) g(requires)0 4312 y(3)h(passes)f(through)f(the)i(\014le)f(whic)m(h)g (could)h(triple)f(the)h(execution)g(time)g(of)g(an)f(I/O)g(limited)h (program.)38 b(F)-8 b(or)25 b(small)0 4425 y(tables)31 b(this)f(is)h(not)f(imp)s(ortan)m(t,)h(but)f(when)f(reading)h(m)m (ulti-megab)m(yte)j(sized)e(tables)g(these)g(ine\016ciencies)h(can)0 4538 y(b)s(ecome)d(signi\014can)m(t.)41 b(The)28 b(more)h(e\016cien)m (t)h(pro)s(cedure)d(in)i(this)f(case)i(is)e(to)i(read)e(or)h(write)g (only)f(as)h(man)m(y)g(ro)m(ws)0 4650 y(of)g(the)g(table)h(as)f(will)h (\014t)e(in)m(to)i(the)g(a)m(v)-5 b(ailable)31 b(in)m(ternal)f(I/O)f (bu\013ers,)f(then)h(access)h(all)g(the)f(necessary)g(columns)0 4763 y(of)i(data)h(within)e(that)i(range)f(of)g(ro)m(ws.)43 b(Then)29 b(after)j(the)f(program)g(is)g(completely)h(\014nished)e (with)g(the)i(data)f(in)0 4876 y(those)i(ro)m(ws)e(it)i(can)f(mo)m(v)m (e)i(on)e(to)g(the)h(next)f(range)g(of)g(ro)m(ws)g(that)h(will)f(\014t) g(in)g(the)g(bu\013ers,)f(con)m(tin)m(uing)i(in)f(this)0 4989 y(w)m(a)m(y)c(un)m(til)f(the)f(en)m(tire)i(\014le)f(has)f(b)s(een) g(pro)s(cessed.)39 b(By)27 b(using)f(this)h(pro)s(cedure)e(of)i (accessing)h(all)g(the)e(columns)h(of)0 5102 y(a)j(table)g(in)f (parallel)h(rather)f(than)g(sequen)m(tially)-8 b(,)32 b(eac)m(h)e(blo)s(c)m(k)g(of)g(the)f(FITS)g(\014le)g(will)g(only)h(b)s (e)e(read)i(or)f(written)0 5215 y(once.)0 5375 y(The)g(optimal)h(n)m (um)m(b)s(er)e(of)i(ro)m(ws)f(to)i(read)e(or)g(write)h(at)g(one)g(time) g(in)f(a)h(giv)m(en)g(table)h(dep)s(ends)c(on)j(the)f(width)g(of)0 5488 y(the)j(table)h(ro)m(w,)g(on)f(the)g(n)m(um)m(b)s(er)f(of)h(I/O)g (bu\013ers)f(that)i(ha)m(v)m(e)g(b)s(een)e(allo)s(cated)j(in)e(FITSIO,) f(and)h(also)h(on)f(the)0 5601 y(n)m(um)m(b)s(er)27 b(of)i(other)f (FITS)g(\014les)g(that)h(are)g(op)s(en)f(at)h(the)g(same)g(time)g (\(since)g(one)g(I/O)f(bu\013er)f(is)i(alw)m(a)m(ys)h(reserv)m(ed)0 5714 y(for)k(eac)m(h)h(op)s(en)f(FITS)f(\014le\).)53 b(F)-8 b(ortunately)g(,)37 b(a)e(FITSIO)e(routine)h(is)h(a)m(v)-5 b(ailable)36 b(that)f(will)f(return)g(the)g(optimal)p eop end %%Page: 27 33 TeXDict begin 27 32 bop 0 299 a Fh(4.13.)73 b(OPTIMIZING)29 b(CODE)h(F)m(OR)h(MAXIMUM)g(PR)m(OCESSING)f(SPEED)971 b Fj(27)0 555 y(n)m(um)m(b)s(er)32 b(of)i(ro)m(ws)g(for)g(a)g(giv)m(en) g(table:)49 b(call)35 b(ftgrsz\(unit,)g(nro)m(ws,)f(status\).)52 b(It)34 b(is)g(not)g(critical)h(to)g(use)e(exactly)0 668 y(the)f(v)-5 b(alue)32 b(of)f(nro)m(ws)g(returned)g(b)m(y)g(this)g (routine,)h(as)g(long)g(as)g(one)g(do)s(es)f(not)h(exceed)g(it.)45 b(Using)32 b(a)g(v)m(ery)f(small)0 781 y(v)-5 b(alue)32 b(ho)m(w)m(ev)m(er)i(can)e(also)h(lead)f(to)h(p)s(o)s(or)e(p)s (erformance)g(b)s(ecause)h(of)g(the)g(o)m(v)m(erhead)h(from)f(the)g (larger)g(n)m(um)m(b)s(er)0 894 y(of)f(subroutine)e(calls.)0 1054 y(The)36 b(optimal)h(n)m(um)m(b)s(er)f(of)g(ro)m(ws)h(returned)e (b)m(y)h(ftgrsz)h(is)g(v)-5 b(alid)37 b(only)f(as)h(long)g(as)g(the)f (application)i(program)0 1167 y(is)c(only)h(reading)g(or)f(writing)g (data)h(in)g(the)f(sp)s(eci\014ed)g(table.)54 b(An)m(y)34 b(other)h(calls)g(to)g(access)h(data)f(in)f(the)h(table)0 1280 y(header)26 b(w)m(ould)f(cause)i(additional)f(blo)s(c)m(ks)h(of)f (data)g(to)h(b)s(e)e(loaded)h(in)m(to)h(the)f(I/O)g(bu\013ers)f (displacing)h(data)g(from)0 1393 y(the)j(original)h(table,)g(and)e (should)f(b)s(e)h(a)m(v)m(oided)i(during)e(the)h(critical)h(p)s(erio)s (d)e(while)g(the)h(table)h(is)e(b)s(eing)g(read)h(or)0 1506 y(written.)0 1666 y(4.)39 b(Use)24 b(binary)f(table)h(extensions)g (rather)f(than)h(ASCI)s(I)e(table)i(extensions)g(for)f(b)s(etter)h (e\016ciency)h(when)d(dealing)0 1779 y(with)37 b(tabular)h(data.)62 b(The)37 b(I/O)g(to)h(ASCI)s(I)e(tables)i(is)g(slo)m(w)m(er)g(b)s (ecause)g(of)f(the)h(o)m(v)m(erhead)h(in)e(formatting)h(or)0 1892 y(parsing)30 b(the)h(ASCI)s(I)f(data)h(\014elds,)g(and)f(b)s (ecause)h(ASCI)s(I)e(tables)i(are)g(ab)s(out)g(t)m(wice)h(as)f(large)h (as)f(binary)f(tables)0 2005 y(with)g(the)h(same)f(information)h(con)m (ten)m(t.)0 2165 y(5.)64 b(Design)39 b(soft)m(w)m(are)g(so)g(that)f(it) h(reads)f(the)g(FITS)f(header)h(k)m(eyw)m(ords)g(in)g(the)g(same)h (order)e(in)h(whic)m(h)g(they)0 2278 y(o)s(ccur)33 b(in)g(the)g (\014le.)49 b(When)32 b(reading)i(k)m(eyw)m(ords,)g(FITSIO)e(searc)m (hes)i(forw)m(ard)e(starting)i(from)e(the)i(p)s(osition)f(of)0 2391 y(the)c(last)i(k)m(eyw)m(ord)e(that)h(w)m(as)g(read.)40 b(If)29 b(it)g(reac)m(hes)i(the)e(end)g(of)g(the)h(header)f(without)g (\014nding)f(the)h(k)m(eyw)m(ord,)h(it)0 2503 y(then)j(go)s(es)h(bac)m (k)g(to)h(the)e(start)h(of)g(the)g(header)f(and)g(con)m(tin)m(ues)h (the)g(searc)m(h)g(do)m(wn)f(to)h(the)g(p)s(osition)f(where)g(it)0 2616 y(started.)41 b(In)30 b(practice,)i(as)e(long)h(as)g(the)f(en)m (tire)i(FITS)d(header)h(can)h(\014t)f(at)h(one)g(time)g(in)f(the)g(a)m (v)-5 b(ailable)33 b(in)m(ternal)0 2729 y(I/O)g(bu\013ers,)h(then)f (the)h(header)f(k)m(eyw)m(ord)h(access)h(will)e(b)s(e)g(v)m(ery)h(fast) g(and)f(it)h(mak)m(es)g(little)h(di\013erence)f(whic)m(h)0 2842 y(order)c(they)g(are)h(accessed.)0 3002 y(6.)40 b(Av)m(oid)29 b(the)e(use)h(of)f(scaling)i(\(b)m(y)f(using)f(the)h (BSCALE)e(and)h(BZER)m(O)h(or)f(TSCAL)g(and)g(TZER)m(O)f(k)m(eyw)m (ords\))0 3115 y(in)35 b(FITS)f(\014les)g(since)i(the)f(scaling)h(op)s (erations)f(add)f(to)i(the)f(pro)s(cessing)f(time)i(needed)e(to)i(read) f(or)g(write)g(the)0 3228 y(data.)60 b(In)36 b(some)i(cases)f(it)g(ma)m (y)h(b)s(e)e(more)h(e\016cien)m(t)h(to)f(temp)s(orarily)g(turn)f(o\013) h(the)g(scaling)h(\(using)e(ftpscl)h(or)0 3341 y(fttscl\))32 b(and)d(then)h(read)h(or)f(write)h(the)f(ra)m(w)h(unscaled)f(v)-5 b(alues)31 b(in)f(the)g(FITS)g(\014le.)0 3501 y(7.)40 b(Av)m(oid)27 b(using)g(the)g('implicit)h(datat)m(yp)s(e)f(con)m(v)m (ersion')h(capabilit)m(y)h(in)d(FITSIO.)g(F)-8 b(or)28 b(instance,)g(when)e(reading)0 3614 y(a)f(FITS)e(image)j(with)e(BITPIX) g(=)g(-32)i(\(32-bit)g(\015oating)f(p)s(oin)m(t)f(pixels\),)j(read)d (the)h(data)g(in)m(to)g(a)g(single)g(precision)0 3727 y(\015oating)e(p)s(oin)m(t)e(data)i(arra)m(y)f(in)g(the)g(program.)37 b(F)-8 b(orcing)23 b(FITSIO)e(to)h(con)m(v)m(ert)i(the)e(data)g(to)h(a) f(di\013eren)m(t)g(datat)m(yp)s(e)0 3840 y(can)31 b(signi\014can)m(tly) g(slo)m(w)g(the)g(program.)0 4000 y(8.)57 b(Where)36 b(feasible,)i(design)e(FITS)f(binary)g(tables)h(using)f(v)m(ector)j (column)d(elemen)m(ts)i(so)f(that)g(the)g(data)h(are)0 4113 y(written)30 b(as)g(a)g(con)m(tiguous)h(set)f(of)g(b)m(ytes,)g (rather)g(than)f(as)h(single)g(elemen)m(ts)h(in)f(m)m(ultiple)g(ro)m (ws.)41 b(F)-8 b(or)30 b(example,)0 4226 y(it)36 b(is)g(faster)g(to)g (access)h(the)f(data)h(in)e(a)h(table)h(that)f(con)m(tains)h(a)f (single)g(ro)m(w)g(and)f(2)h(columns)f(with)h(TF)m(ORM)0 4339 y(k)m(eyw)m(ords)d(equal)h(to)g('10000E')h(and)e('10000J',)j(than) d(it)g(is)g(to)h(access)g(the)g(same)f(amoun)m(t)h(of)f(data)h(in)f(a)g (table)0 4452 y(with)40 b(10000)j(ro)m(ws)d(whic)m(h)h(has)f(columns)g (with)g(the)h(TF)m(ORM)g(k)m(eyw)m(ords)g(equal)g(to)g('1E')h(and)e ('1J'.)h(In)f(the)0 4565 y(former)27 b(case)i(the)f(10000)i(\015oating) f(p)s(oin)m(t)f(v)-5 b(alues)28 b(in)g(the)g(\014rst)f(column)h(are)g (all)h(written)f(in)f(a)h(con)m(tiguous)h(blo)s(c)m(k)0 4678 y(of)d(the)f(\014le)h(whic)m(h)f(can)h(b)s(e)f(read)g(or)g (written)h(quic)m(kly)-8 b(,)28 b(whereas)d(in)g(the)h(second)f(case)i (eac)m(h)g(\015oating)f(p)s(oin)m(t)f(v)-5 b(alue)0 4791 y(in)34 b(the)g(\014rst)f(column)g(is)h(in)m(terlea)m(v)m(ed)j(with)c (the)h(in)m(teger)i(v)-5 b(alue)34 b(in)g(the)g(second)g(column)f(of)h (the)g(same)h(ro)m(w)f(so)0 4903 y(CFITSIO)29 b(has)h(to)h(explicitly)h (mo)m(v)m(e)g(to)f(the)g(p)s(osition)f(of)h(eac)m(h)g(elemen)m(t)h(to)f (b)s(e)f(read)g(or)g(written.)0 5064 y(9.)52 b(Av)m(oid)35 b(the)g(use)e(of)i(v)-5 b(ariable)34 b(length)h(v)m(ector)h(columns)d (in)h(binary)g(tables,)i(since)e(an)m(y)h(reading)f(or)g(writing)0 5176 y(of)f(these)g(data)g(requires)f(that)h(CFITSIO)f(\014rst)f(lo)s (ok)j(up)d(or)i(compute)g(the)f(starting)i(address)e(of)g(eac)m(h)i(ro) m(w)f(of)0 5289 y(data)e(in)f(the)h(heap.)40 b(In)30 b(practice,)i(this)e(is)g(probably)g(not)h(a)f(signi\014can)m(t)i (e\016ciency)f(issue.)0 5450 y(10.)39 b(When)24 b(cop)m(ying)h(data)f (from)f(one)i(FITS)e(table)h(to)h(another,)g(it)g(is)f(faster)g(to)g (transfer)f(the)h(ra)m(w)g(b)m(ytes)h(instead)0 5562 y(of)h(reading)g(then)g(writing)g(eac)m(h)h(column)e(of)i(the)f(table.) 40 b(The)25 b(FITSIO)g(subroutines)g(FTGTBS)g(and)h(FTPTBS)0 5675 y(\(for)i(ASCI)s(I)f(tables\),)j(and)d(FTGTBB)i(and)e(FTPTBB)i (\(for)f(binary)f(tables\))i(will)g(p)s(erform)d(lo)m(w-lev)m(el)31 b(reads)d(or)p eop end %%Page: 28 34 TeXDict begin 28 33 bop 0 299 a Fj(28)1277 b Fh(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fj(writes)j(of)h(an)m(y)f(con)m(tiguous)i(range)f(of)f(b)m(ytes)h (in)f(a)h(table)g(extension.)53 b(These)34 b(routines)g(can)h(b)s(e)e (used)h(to)h(read)0 668 y(or)29 b(write)g(a)g(whole)g(ro)m(w)f(\(or)i (m)m(ultiple)f(ro)m(ws\))g(of)g(a)g(table)h(with)e(a)h(single)g (subroutine)f(call.)41 b(These)29 b(routines)g(are)0 781 y(fast)38 b(b)s(ecause)f(they)h(b)m(ypass)f(all)h(the)g(usual)f (data)h(scaling,)j(error)c(c)m(hec)m(king)i(and)e(mac)m(hine)h(dep)s (enden)m(t)e(data)0 894 y(con)m(v)m(ersion)41 b(that)g(is)e(normally)i (done)e(b)m(y)h(FITSIO,)f(and)g(they)h(allo)m(w)h(the)f(program)g(to)h (write)f(the)g(data)g(to)0 1007 y(the)34 b(output)g(\014le)g(in)g (exactly)i(the)e(same)h(b)m(yte)g(order.)51 b(F)-8 b(or)35 b(these)g(same)f(reasons,)i(use)e(of)g(these)h(routines)f(can)0 1120 y(b)s(e)f(somewhat)h(risky)f(b)s(ecause)g(no)g(v)-5 b(alidation)35 b(or)f(mac)m(hine)g(dep)s(enden)m(t)e(con)m(v)m(ersion)j (is)e(p)s(erformed)f(b)m(y)h(these)0 1233 y(routines.)40 b(In)27 b(general)h(these)h(routines)e(are)h(only)g(recommended)f(for)h (optimizing)h(critical)g(pieces)g(of)f(co)s(de)g(and)0 1346 y(should)e(only)i(b)s(e)f(used)f(b)m(y)i(programmers)e(who)h (thoroughly)h(understand)d(the)j(in)m(ternal)g(b)m(yte)g(structure)f (of)h(the)0 1458 y(FITS)i(tables)h(they)f(are)h(reading)g(or)f (writing.)0 1619 y(11.)41 b(Another)30 b(strategy)g(for)g(impro)m(ving) f(the)h(sp)s(eed)e(of)i(writing)g(a)f(FITS)g(table,)i(similar)f(to)g (the)f(previous)g(one,)0 1732 y(is)j(to)g(directly)h(construct)f(the)f (en)m(tire)i(b)m(yte)f(stream)g(for)g(a)g(whole)g(table)g(ro)m(w)g (\(or)g(m)m(ultiple)h(ro)m(ws\))f(within)f(the)0 1844 y(application)k(program)f(and)g(then)f(write)i(it)f(to)h(the)f(FITS)f (\014le)i(with)e(ftptbb.)51 b(This)33 b(a)m(v)m(oids)j(all)f(the)f(o)m (v)m(erhead)0 1957 y(normally)g(presen)m(t)g(in)f(the)h(column-orien)m (ted)h(CFITSIO)d(write)i(routines.)51 b(This)33 b(tec)m(hnique)h (should)f(only)h(b)s(e)0 2070 y(used)26 b(for)h(critical)i (applications,)g(b)s(ecause)d(it)i(mak)m(es)g(the)f(co)s(de)g(more)g (di\016cult)g(to)g(understand)e(and)i(main)m(tain,)0 2183 y(and)d(it)h(mak)m(es)h(the)f(co)s(de)g(more)f(system)h(dep)s (enden)m(t)f(\(e.g.,)k(do)c(the)h(b)m(ytes)g(need)g(to)g(b)s(e)f(sw)m (app)s(ed)g(b)s(efore)g(writing)0 2296 y(to)31 b(the)g(FITS)e (\014le?\).)0 2456 y(12.)53 b(Finally)-8 b(,)37 b(external)e(factors)h (suc)m(h)e(as)g(the)h(t)m(yp)s(e)f(of)h(magnetic)g(disk)f(con)m (troller)i(\(SCSI)d(or)i(IDE\),)g(the)f(size)0 2569 y(of)h(the)g(disk)g (cac)m(he,)j(the)d(a)m(v)m(erage)i(seek)f(sp)s(eed)e(of)h(the)g(disk,)h (the)f(amoun)m(t)h(of)f(disk)f(fragmen)m(tation,)k(and)d(the)0 2682 y(amoun)m(t)29 b(of)g(RAM)f(a)m(v)-5 b(ailable)31 b(on)e(the)f(system)h(can)g(all)g(ha)m(v)m(e)h(a)f(signi\014can)m(t)g (impact)h(on)e(o)m(v)m(erall)j(I/O)d(e\016ciency)-8 b(.)0 2795 y(F)g(or)36 b(critical)h(applications,)g(a)f(system)f (administrator)g(should)f(review)h(the)h(prop)s(osed)d(system)j(hardw)m (are)e(to)0 2908 y(iden)m(tify)d(an)m(y)g(p)s(oten)m(tial)g(I/O)g(b)s (ottlenec)m(ks.)p eop end %%Page: 29 35 TeXDict begin 29 34 bop 0 1225 a Fg(Chapter)65 b(5)0 1687 y Fm(Basic)77 b(In)-6 b(terface)77 b(Routines)0 2180 y Fj(This)27 b(section)h(de\014nes)f(a)h(basic)g(set)g(of)g (subroutines)e(that)i(can)g(b)s(e)f(used)g(to)h(p)s(erform)e(the)i (most)g(common)g(t)m(yp)s(es)0 2293 y(of)d(read)g(and)f(write)h(op)s (erations)g(on)g(FITS)f(\014les.)39 b(New)25 b(users)f(should)g(start)h (with)g(these)g(subroutines)f(and)g(then,)0 2406 y(as)33 b(needed,)h(explore)f(the)h(more)f(adv)-5 b(ance)33 b(routines)g (describ)s(ed)f(in)h(the)g(follo)m(wing)i(c)m(hapter)e(to)h(p)s(erform) e(more)0 2518 y(complex)f(or)f(sp)s(ecialized)i(op)s(erations.)0 2679 y(A)e(righ)m(t)g(arro)m(w)g(sym)m(b)s(ol)f(\()p Fb(>)p Fj(\))h(is)g(used)f(to)h(separate)h(the)e(input)g(parameters)h (from)f(the)h(output)f(parameters)h(in)0 2791 y(the)i(de\014nition)f (of)g(eac)m(h)i(routine.)44 b(This)30 b(sym)m(b)s(ol)i(is)f(not)h (actually)h(part)e(of)h(the)f(calling)i(sequence.)45 b(Note)32 b(that)0 2904 y(the)f(status)h(parameter)g(is)f(b)s(oth)g(an) g(input)f(and)h(an)g(output)g(parameter)h(and)e(m)m(ust)h(b)s(e)g (initialized)i(=)e(0)h(prior)0 3017 y(to)f(calling)h(the)f(FITSIO)e (subroutines.)0 3177 y(Refer)h(to)i(Chapter)d(9)i(for)f(the)h (de\014nition)f(of)g(all)i(the)e(parameters)h(used)e(b)m(y)i(these)g (in)m(terface)g(routines.)0 3511 y Fe(5.1)135 b(FITSIO)44 b(Error)h(Status)h(Routines)0 3751 y Fi(1)81 b Fj(Return)24 b(the)i(curren)m(t)f(v)m(ersion)h(n)m(um)m(b)s(er)e(of)i(the)f (\014tsio)h(library)-8 b(.)39 b(The)25 b(v)m(ersion)h(n)m(um)m(b)s(er)e (will)i(b)s(e)e(incremen)m(ted)227 3864 y(with)32 b(eac)m(h)i(new)e (release)i(of)f(CFITSIO.)e(The)h(3)h(\014elds)f(of)g(the)h(v)m(ersion)g (string)f(M.xx.yy)i(are)e(con)m(v)m(erted)227 3976 y(to)f(a)g(\015oat)g (as:)41 b(M)31 b(+)f(.01*xx)i(+)e(.0001*yy)-8 b(.)382 4234 y Ff(FTVERS\()46 b(>)h(version\))0 4491 y Fi(2)81 b Fj(Return)45 b(the)i(descriptiv)m(e)g(text)g(string)g(corresp)s (onding)e(to)i(a)g(FITSIO)e(error)h(status)h(co)s(de.)89 b(The)46 b(30-)227 4604 y(c)m(haracter)32 b(length)f(string)f(con)m (tains)i(a)f(brief)f(description)g(of)g(the)h(cause)g(of)f(the)h (error.)382 4861 y Ff(FTGERR\(status,)44 b(>)j(errtext\))0 5118 y Fi(3)81 b Fj(Return)40 b(the)h(top)g(\(oldest\))h(80-c)m (haracter)i(error)c(message)i(from)f(the)g(in)m(ternal)g(FITSIO)f(stac) m(k)i(of)f(error)227 5231 y(messages)29 b(and)f(shift)g(an)m(y)g (remaining)g(messages)h(on)f(the)g(stac)m(k)i(up)d(one)h(lev)m(el.)42 b(An)m(y)28 b(FITSIO)f(error)h(will)227 5344 y(generate)h(one)e(or)g (more)h(messages)g(on)f(the)g(stac)m(k.)41 b(Call)28 b(this)f(routine)g(rep)s(eatedly)g(to)h(get)h(eac)m(h)f(message)227 5457 y(in)i(sequence.)41 b(The)30 b(error)g(stac)m(k)i(is)f(empt)m(y)f (when)g(a)g(blank)g(string)h(is)f(returned.)382 5714 y Ff(FTGMSG\()46 b(>)h(errmsg\))1905 5942 y Fj(29)p eop end %%Page: 30 36 TeXDict begin 30 35 bop 0 299 a Fj(30)1747 b Fh(CHAPTER)30 b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(4)81 b Fj(The)33 b(FTPMRK)h(routine)g(puts)g(an)g(in)m (visible)h(mark)m(er)f(on)g(the)h(CFITSIO)d(error)i(stac)m(k.)54 b(The)33 b(FTCMRK)227 668 y(routine)41 b(can)g(then)g(b)s(e)f(used)g (to)h(delete)h(an)m(y)f(more)g(recen)m(t)h(error)e(messages)i(on)f(the) g(stac)m(k,)k(bac)m(k)c(to)227 781 y(the)32 b(p)s(osition)f(of)g(the)g (mark)m(er.)43 b(This)31 b(preserv)m(es)g(an)m(y)g(older)h(error)e (messages)i(on)f(the)h(stac)m(k.)44 b(FTCMSG)227 894 y(simply)23 b(clears)g(the)g(en)m(tire)h(error)e(message)i(stac)m(k.)40 b(These)23 b(routines)f(are)h(called)h(without)f(an)m(y)g(argumen)m (ts.)382 1152 y Ff(FTPMRK)382 1265 y(FTCMRK)382 1378 y(FTCMSG)0 1637 y Fi(5)81 b Fj(Prin)m(t)30 b(out)h(the)g(error)f (message)i(corresp)s(onding)e(to)h(the)g(input)f(status)h(v)-5 b(alue)31 b(and)f(all)i(the)f(error)f(messages)227 1750 y(on)g(the)h(FITSIO)e(stac)m(k)i(to)g(the)g(sp)s(eci\014ed)e(\014le)i (stream)f(\(stream)h(can)g(b)s(e)e(either)i(the)f(string)g('STDOUT')227 1863 y(or)h('STDERR'\).)f(If)g(the)h(input)e(status)i(v)-5 b(alue)31 b(=)f(0)h(then)f(this)g(routine)g(do)s(es)g(nothing.)334 2121 y Ff(FTRPRT)46 b(\(stream,)g(>)h(status\))0 2380 y Fi(6)81 b Fj(W)-8 b(rite)39 b(an)f(80-c)m(haracter)j(message)e(to)g (the)f(FITSIO)f(error)h(stac)m(k.)65 b(Application)39 b(programs)f(should)f(not)227 2493 y(normally)31 b(write)f(to)i(the)e (stac)m(k,)i(but)e(there)g(ma)m(y)h(b)s(e)f(some)h(situations)g(where)f (this)g(is)h(desirable.)382 2751 y Ff(FTPMSG\(errmsg\))0 3085 y Fe(5.2)135 b(File)46 b(I/O)f(Routines)0 3325 y Fi(1)81 b Fj(Op)s(en)34 b(an)h(existing)i(FITS)d(\014le)i(with)f (readonly)h(or)f(readwrite)h(access.)58 b(This)34 b(routine)i(alw)m(a)m (ys)h(op)s(ens)e(the)227 3438 y(primary)30 b(arra)m(y)i(\(the)f (\014rst)f(HDU\))i(of)f(the)h(\014le,)f(and)f(do)s(es)h(not)g(mo)m(v)m (e)h(to)g(a)f(follo)m(wing)i(extension,)f(if)f(one)227 3551 y(w)m(as)c(sp)s(eci\014ed)f(as)g(part)h(of)f(the)h(\014lename.)39 b(Use)27 b(the)g(FTNOPN)f(routine)g(to)h(automatically)j(mo)m(v)m(e)e (to)f(the)227 3664 y(extension.)44 b(This)31 b(routine)g(will)h(also)g (op)s(en)f(IRAF)g(images)i(\(.imh)e(format)h(\014les\))g(and)e(ra)m(w)i (binary)e(data)227 3776 y(arra)m(ys)e(with)f(READONL)-8 b(Y)28 b(access)h(b)m(y)e(\014rst)g(con)m(v)m(erting)i(them)e(on)g(the) h(\015y)f(in)m(to)h(virtual)g(FITS)f(images.)227 3889 y(See)43 b(the)g(`Extended)f(File)i(Name)f(Syn)m(tax')g(c)m(hapter)g (for)f(more)h(details.)78 b(The)42 b(FTDK)m(OPN)h(routine)227 4002 y(simply)37 b(op)s(ens)g(the)h(sp)s(eci\014ed)f(\014le)h(without)f (trying)h(to)g(in)m(terpret)g(the)g(\014lename)g(using)f(the)h (extended)227 4115 y(\014lename)31 b(syn)m(tax.)382 4374 y Ff(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b (blocksize,status\))382 4487 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 b(blocksize,status\))0 4745 y Fi(2)81 b Fj(Op)s(en)24 b(an)i(existing)h(FITS)e(\014le)h(with)f(readonly)h(or)g(readwrite)g (access)h(and)f(mo)m(v)m(e)h(to)f(a)h(follo)m(wing)g(extension,)227 4858 y(if)38 b(one)g(w)m(as)g(sp)s(eci\014ed)g(as)g(part)f(of)h(the)h (\014lename.)63 b(\(e.g.,)42 b('\014lename.\014ts+2')c(or)g ('\014lename.\014ts[2]')i(will)227 4971 y(mo)m(v)m(e)e(to)g(the)e(3rd)g (HDU)i(in)e(the)h(\014le\).)60 b(Note)37 b(that)h(this)e(routine)h (di\013ers)f(from)g(FTOPEN)g(in)g(that)h(it)227 5084 y(do)s(es)30 b(not)h(ha)m(v)m(e)h(the)e(redundan)m(t)f(blo)s(c)m(ksize) j(argumen)m(t.)382 5342 y Ff(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))0 5601 y Fi(3)81 b Fj(Op)s(en)31 b(an)h(existing)h (FITS)f(\014le)g(with)g(readonly)h(or)f(readwrite)h(access)g(and)f (then)g(mo)m(v)m(e)i(to)f(the)g(\014rst)e(HDU)227 5714 y(con)m(taining)c(signi\014can)m(t)g(data,)g(if)e(a\))i(an)e(HDU)h (name)g(or)f(n)m(um)m(b)s(er)f(to)i(op)s(en)f(w)m(as)h(not)g (explicitly)h(sp)s(eci\014ed)p eop end %%Page: 31 37 TeXDict begin 31 36 bop 0 299 a Fh(5.2.)72 b(FILE)30 b(I/O)h(R)m(OUTINES)2693 b Fj(31)227 555 y(as)31 b(part)g(of)g(the)g (\014lename,)h(and)e(b\))h(if)g(the)g(FITS)f(\014le)h(con)m(tains)h(a)g (n)m(ull)e(primary)g(arra)m(y)i(\(i.e.,)h(NAXIS)d(=)227 668 y(0\).)41 b(In)26 b(this)i(case,)h(it)f(will)g(lo)s(ok)g(for)f(the) h(\014rst)e(IMA)m(GE)j(HDU)f(with)f(NAXIS)g(>)h(0,)g(or)g(the)f (\014rst)g(table)h(that)227 781 y(do)s(es)g(not)g(con)m(tain)g(the)g (strings)g(`GTI')g(\(Go)s(o)s(d)f(Time)h(In)m(terv)-5 b(al\))29 b(or)f(`OBST)-8 b(ABLE')28 b(in)f(the)h(EXTNAME)227 894 y(k)m(eyw)m(ord)37 b(v)-5 b(alue.)61 b(FTTOPN)36 b(is)g(similar,)j(except)f(it)f(will)g(mo)m(v)m(e)i(to)e(the)g(\014rst) f(signi\014can)m(t)i(table)f(HDU)227 1007 y(\(skipping)26 b(o)m(v)m(er)g(an)m(y)g(image)h(HDUs\))g(in)e(the)h(\014le)g(if)f(a)h (sp)s(eci\014c)g(HDU)g(name)g(or)g(n)m(um)m(b)s(er)e(is)i(not)f(sp)s (eci\014ed.)227 1120 y(FTIOPN)30 b(will)h(mo)m(v)m(e)h(to)f(the)f (\014rst)g(non-n)m(ull)g(image)i(HDU,)f(skipping)f(o)m(v)m(er)h(an)m(y) g(tables.)382 1376 y Ff(FTDOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 1489 y(FTTOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 1602 y(FTIOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))0 1858 y Fi(4)81 b Fj(Op)s(en)38 b(and)i(initialize)j (a)e(new)e(empt)m(y)i(FITS)f(\014le.)70 b(A)41 b(template)h(\014le)e (ma)m(y)h(also)g(b)s(e)f(sp)s(eci\014ed)g(to)h(de\014ne)227 1971 y(the)34 b(structure)e(of)h(the)h(new)e(\014le)h(\(see)h(section)g (4.2.4\).)51 b(The)33 b(FTDKINIT)g(routine)g(simply)f(creates)j(the)227 2084 y(sp)s(eci\014ed)30 b(\014le)g(without)h(trying)f(to)h(in)m (terpret)g(the)g(\014lename)f(using)g(the)h(extended)f(\014lename)h (syn)m(tax.)382 2340 y Ff(FTINIT\(unit,filename,blo)o(cks)o(ize,)41 b(>)48 b(status\))382 2453 y(FTDKINIT\(unit,filename,b)o(loc)o(ksiz)o (e,)42 b(>)47 b(status\))0 2709 y Fi(5)81 b Fj(Close)31 b(a)f(FITS)g(\014le)g(previously)g(op)s(ened)g(with)g(ftop)s(en)g(or)g (ftinit)382 2965 y Ff(FTCLOS\(unit,)44 b(>)k(status\))0 3221 y Fi(6)81 b Fj(Mo)m(v)m(e)32 b(to)f(a)g(sp)s(eci\014ed)f (\(absolute\))h(HDU)g(in)g(the)f(FITS)g(\014le)g(\(nhdu)f(=)h(1)h(for)f (the)g(FITS)g(primary)f(arra)m(y\))382 3478 y Ff(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))0 3734 y Fi(7)81 b Fj(Create)30 b(a)f(primary)f(arra)m(y)i(\(if)g(none)f(already)g(exists\),)i(or)e (insert)g(a)h(new)f(IMA)m(GE)h(extension)g(immediately)227 3847 y(follo)m(wing)25 b(the)e(CHDU,)g(or)g(insert)g(a)g(new)g(Primary) f(Arra)m(y)h(at)h(the)f(b)s(eginning)f(of)h(the)g(\014le.)38 b(An)m(y)23 b(follo)m(wing)227 3960 y(extensions)29 b(in)g(the)g (\014le)f(will)h(b)s(e)f(shifted)h(do)m(wn)f(to)h(mak)m(e)h(ro)s(om)e (for)h(the)g(new)f(extension.)40 b(If)29 b(the)g(CHDU)227 4072 y(is)h(the)g(last)g(HDU)g(in)g(the)f(\014le)h(then)f(the)h(new)f (image)i(extension)f(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)g (end)227 4185 y(of)k(the)h(\014le.)52 b(One)33 b(can)h(force)h(a)g(new) e(primary)g(arra)m(y)i(to)g(b)s(e)e(inserted)h(at)h(the)f(b)s(eginning) f(of)h(the)h(FITS)227 4298 y(\014le)29 b(b)m(y)f(setting)i(status)e(=)h (-9)g(prior)e(to)j(calling)g(the)e(routine.)40 b(In)28 b(this)g(case)i(the)e(existing)i(primary)d(arra)m(y)227 4411 y(will)f(b)s(e)f(con)m(v)m(erted)i(to)g(an)e(IMA)m(GE)h (extension.)40 b(The)25 b(new)g(extension)i(\(or)f(primary)e(arra)m (y\))j(will)f(b)s(ecome)227 4524 y(the)32 b(CHDU.)f(The)g(FTI)s(IMGLL)f (routine)i(is)f(iden)m(tical)i(to)e(the)h(FTI)s(IMG)f(routine)g(except) h(that)f(the)h(4th)227 4637 y(parameter)25 b(\(the)g(length)g(of)f(eac) m(h)h(axis\))g(is)g(an)f(arra)m(y)h(of)f(64-bit)i(in)m(tegers)f(rather) f(than)g(an)g(arra)m(y)h(of)g(32-bit)227 4750 y(in)m(tegers.)382 5006 y Ff(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 5119 y(FTIIMGLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)41 b(>)47 b(status\))0 5375 y Fi(8)81 b Fj(Insert)30 b(a)i(new)f(ASCI)s(I) f(T)-8 b(ABLE)31 b(extension)h(immediately)h(follo)m(wing)f(the)g (CHDU.)g(An)m(y)f(follo)m(wing)i(exten-)227 5488 y(sions)26 b(will)g(b)s(e)f(shifted)g(do)m(wn)g(to)h(mak)m(e)h(ro)s(om)e(for)h (the)f(new)g(extension.)40 b(If)25 b(there)h(are)g(no)g(other)f(follo)m (wing)227 5601 y(extensions)32 b(then)f(the)h(new)f(table)h(extension)g (will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)f(end)g(of)h(the)f (\014le.)44 b(The)227 5714 y(new)33 b(extension)h(will)f(b)s(ecome)h (the)f(CHDU.)h(The)f(FTIT)-8 b(ABLL)33 b(routine)g(is)g(iden)m(tical)i (to)f(the)g(FTIT)-8 b(AB)p eop end %%Page: 32 38 TeXDict begin 32 37 bop 0 299 a Fj(32)1747 b Fh(CHAPTER)30 b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(routine)36 b(except)g(that)g(the)f(2nd)g(and)g(3rd)g (parameters)g(\(that)i(giv)m(e)g(the)e(size)h(of)g(the)f(table\))i(are) f(64-bit)227 668 y(in)m(tegers)43 b(rather)f(than)f(32-bit)i(in)m (tegers.)76 b(Under)41 b(normal)g(circumstances,)46 b(the)c(nro)m(ws)f (and)g(nro)m(wsll)227 781 y(paramen)m(ters)f(should)e(ha)m(v)m(e)j(a)f (v)-5 b(alue)40 b(of)f(0;)45 b(CFITSIO)38 b(will)h(automatically)k(up)s (date)38 b(the)i(n)m(um)m(b)s(er)e(of)227 894 y(ro)m(ws)31 b(as)f(data)h(is)g(written)f(to)h(the)g(table.)382 1160 y Ff(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o(ol,t) o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1273 y(status\))382 1386 y(FTITABLL\(unit,rowlenll,n)o(row)o(sll,)o(tfie)o (lds)o(,tty)o(pe,t)o(bco)o(l,tf)o(orm,)o(tun)o(it,e)o(xtna)o(me,)f(>) 716 1499 y(status\))0 1765 y Fi(9)81 b Fj(Insert)26 b(a)h(new)g(binary) f(table)h(extension)h(immediately)g(follo)m(wing)h(the)e(CHDU.)g(An)m (y)g(follo)m(wing)h(extensions)227 1878 y(will)39 b(b)s(e)f(shifted)g (do)m(wn)g(to)h(mak)m(e)g(ro)s(om)g(for)f(the)g(new)g(extension.)66 b(If)38 b(there)h(are)f(no)h(other)f(follo)m(wing)227 1991 y(extensions)f(then)g(the)f(new)g(bin)m(table)h(extension)h(will)f (simply)f(b)s(e)g(app)s(ended)e(to)k(the)e(end)g(of)h(the)g(\014le.)227 2104 y(The)23 b(new)g(extension)h(will)f(b)s(ecome)h(the)f(CHDU.)h(The) f(FTIBINLL)g(routine)g(is)g(iden)m(tical)i(to)f(the)g(FTIBIN)227 2217 y(routine)30 b(except)i(that)e(the)h(2nd)e(parameter)i(\(that)g (giv)m(es)g(the)g(length)f(of)h(the)f(table\))h(is)g(a)f(64-bit)i(in)m (teger)227 2329 y(rather)24 b(than)g(a)g(32-bit)h(in)m(teger.)40 b(Under)23 b(normal)h(circumstances,)i(the)e(nro)m(ws)f(and)h(nro)m (wsll)g(paramen)m(ters)227 2442 y(should)31 b(ha)m(v)m(e)i(a)f(v)-5 b(alue)32 b(of)f(0;)i(CFITSIO)d(will)i(automatically)j(up)s(date)30 b(the)i(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(as)g(data)g(is)227 2555 y(written)f(to)g(the)f(table.)382 2821 y Ff (FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o(,tfo)o(rm,)o(tuni)o(t,ex)o (tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 2934 y(FTIBINLL\(unit,nrowsll,tf)o(iel)o(ds,t)o(type)o(,tf)o(orm,)o(tuni)o (t,e)o(xtna)o(me,v)o(ari)o(dat)41 b(>)48 b(status\))0 3388 y Fe(5.3)135 b(Keyw)l(ord)46 b(I/O)f(Routines)0 3633 y Fi(1)81 b Fj(Put)30 b(\(app)s(end\))f(an)h(80-c)m(haracter)j (record)e(in)m(to)g(the)g(CHU.)382 3899 y Ff(FTPREC\(unit,card,)43 b(>)k(status\))0 4165 y Fi(2)81 b Fj(Put)28 b(\(app)s(end\))g(a)h(new)g (k)m(eyw)m(ord)g(of)g(the)g(appropriate)g(datat)m(yp)s(e)h(in)m(to)g (the)f(CHU.)g(The)f(E)h(and)f(D)i(v)m(ersions)227 4278 y(of)24 b(this)f(routine)g(ha)m(v)m(e)h(the)g(added)e(feature)i(that)g (if)f(the)g('decimals')i(parameter)f(is)f(negativ)m(e,)k(then)c(the)g ('G')227 4391 y(displa)m(y)30 b(format)g(rather)f(then)g(the)h('E')f (format)h(will)g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m (ord)h(v)-5 b(alue,)227 4504 y(taking)27 b(the)g(absolute)g(v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 4617 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 4730 y(the)31 b(v)-5 b(alue.)382 4996 y Ff(FTPKY[JKLS]\(unit,keyword)o (,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 5109 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o (omme)o(nt,)41 b(>)48 b(status\))0 5375 y Fi(3)81 b Fj(Get)37 b(the)f(n)m(th)f(80-c)m(haracter)k(header)d(record)g(from)f(the)h(CHU.) h(The)e(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g(at)227 5488 y(k)m(ey)p 365 5488 28 4 v 34 w(no)42 b(=)f(1;)49 b(if)42 b(k)m(ey)p 996 5488 V 34 w(no)g(=)f(0)i(then)e(this)h (subroutine)f(simple)h(mo)m(v)m(es)i(the)e(in)m(ternal)h(p)s(oin)m(ter) f(to)h(the)227 5601 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g (subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g(at)g (the)g(top)g(of)g(the)227 5714 y(header;)31 b(it)g(also)g(returns)e(a)i (blank)f(card)g(v)-5 b(alue)31 b(in)f(this)g(case.)p eop end %%Page: 33 39 TeXDict begin 33 38 bop 0 299 a Fh(5.4.)72 b(D)m(A)-8 b(T)g(A)32 b(I/O)f(R)m(OUTINES)2650 b Fj(33)382 555 y Ff(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))0 804 y Fi(4)81 b Fj(Get)31 b(a)g(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(\(with)h(the)f(appropriate)h(datat)m(yp)s(e\))g(and)f(commen)m(t)i (from)e(the)g(CHU)382 1052 y Ff(FTGKY[EDJKLS]\(unit,keywo)o(rd,)41 b(>)48 b(keyval,comment,status\))0 1301 y Fi(5)81 b Fj(Delete)32 b(an)e(existing)i(k)m(eyw)m(ord)f(record.)382 1550 y Ff(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 1881 y Fe(5.4)135 b(Data)46 b(I/O)g(Routines)0 2132 y Fj(The)32 b(follo)m(wing)i(routines)e(read)h(or)f(write)h(data)g(v)-5 b(alues)33 b(in)f(the)h(curren)m(t)f(HDU)i(of)e(the)h(FITS)f(\014le.)47 b(Automatic)0 2245 y(datat)m(yp)s(e)28 b(con)m(v)m(ersion)h(will)e(b)s (e)g(attempted)h(for)g(n)m(umerical)f(datat)m(yp)s(es)i(if)e(the)g(sp)s (eci\014ed)g(datat)m(yp)s(e)h(is)f(di\013eren)m(t)0 2357 y(from)j(the)g(actual)i(datat)m(yp)s(e)g(of)e(the)h(FITS)e(arra)m(y)i (or)f(table)i(column.)0 2606 y Fi(1)81 b Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(the)g(primary)e(data)j(arra)m(y)e(or)h(image) g(extension.)382 2855 y Ff(FTPPR[BIJKED]\(unit,group)o(,fp)o(ixel)o (,nel)o(eme)o(nts,)o(valu)o(es,)41 b(>)48 b(status\))0 3103 y Fi(2)81 b Fj(Read)30 b(elemen)m(ts)j(from)d(the)h(primary)e (data)j(arra)m(y)f(or)g(image)h(extension.)42 b(Unde\014ned)29 b(arra)m(y)j(elemen)m(ts)g(will)227 3216 y(b)s(e)f(returned)f(with)h(a) h(v)-5 b(alue)31 b(=)g(n)m(ullv)-5 b(al,)33 b(unless)d(n)m(ullv)-5 b(al)32 b(=)f(0)h(in)f(whic)m(h)g(case)h(no)f(c)m(hec)m(ks)i(for)e (unde\014ned)227 3329 y(pixels)h(will)f(b)s(e)f(p)s(erformed.)42 b(The)30 b(an)m(yf)i(parameter)f(is)g(set)h(to)g(true)f(\(=)g(.true.\)) 43 b(if)31 b(an)m(y)h(of)f(the)g(returned)227 3442 y(elemen)m(ts)h(w)m (ere)f(unde\014ned.)382 3691 y Ff(FTGPV[BIJKED]\(unit,group)o(,fp)o (ixel)o(,nel)o(eme)o(nts,)o(null)o(val)o(,)42 b(>)47 b(values,anyf,status\))0 3939 y Fi(3)81 b Fj(W)-8 b(rite)36 b(elemen)m(ts)h(in)m(to)f(an)f(ASCI)s(I)e(or)i(binary)g(table)h (column.)54 b(The)35 b(`felem')h(parameter)g(applies)f(only)g(to)227 4052 y(v)m(ector)d(columns)e(in)g(binary)g(tables)h(and)f(is)g(ignored) h(when)e(writing)i(to)g(ASCI)s(I)d(tables.)382 4301 y Ff(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o (ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))0 4549 y Fi(4)81 b Fj(Read)22 b(elemen)m(ts)h(from)e(an)g(ASCI)s(I)g(or)g (binary)g(table)i(column.)38 b(Unde\014ned)20 b(arra)m(y)i(elemen)m(ts) h(will)f(b)s(e)f(returned)227 4662 y(with)32 b(a)h(v)-5 b(alue)33 b(=)f(n)m(ullv)-5 b(al,)34 b(unless)e(n)m(ullv)-5 b(al)32 b(=)h(0)f(\(or)h(=)f(')h(')f(for)g(ftgcvs\))i(in)e(whic)m(h)g (case)i(no)e(c)m(hec)m(king)i(for)227 4775 y(unde\014ned)23 b(v)-5 b(alues)25 b(will)g(b)s(e)g(p)s(erformed.)37 b(The)24 b(ANYF)i(parameter)f(is)g(set)h(to)f(true)g(if)g(an)m(y)g(of)g(the)g (returned)227 4888 y(elemen)m(ts)32 b(are)f(unde\014ned.)227 5036 y(An)m(y)d(column,)h(regardless)f(of)g(it's)h(in)m(trinsic)f (datat)m(yp)s(e,)i(ma)m(y)e(b)s(e)f(read)h(as)g(a)h(string.)40 b(It)28 b(should)e(b)s(e)i(noted)227 5149 y(ho)m(w)m(ev)m(er)k(that)f (reading)f(a)h(n)m(umeric)f(column)g(as)h(a)g(string)f(is)g(10)i(-)e (100)i(times)f(slo)m(w)m(er)g(than)f(reading)h(the)227 5262 y(same)36 b(column)f(as)h(a)g(n)m(um)m(b)s(er)e(due)g(to)j(the)e (large)i(o)m(v)m(erhead)f(in)f(constructing)h(the)g(formatted)g (strings.)227 5375 y(The)i(displa)m(y)g(format)g(of)g(the)g(returned)f (strings)g(will)h(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m (ord,)j(if)227 5488 y(it)d(exists,)h(otherwise)f(b)m(y)f(the)g(datat)m (yp)s(e)h(of)f(the)h(column.)57 b(The)36 b(length)g(of)h(the)f (returned)f(strings)h(can)227 5601 y(b)s(e)29 b(determined)f(with)h (the)g(ftgcdw)g(routine.)40 b(The)28 b(follo)m(wing)j(TDISPn)c(displa)m (y)j(formats)f(are)g(curren)m(tly)227 5714 y(supp)s(orted:)p eop end %%Page: 34 40 TeXDict begin 34 39 bop 0 299 a Fj(34)1747 b Fh(CHAPTER)30 b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)418 555 y Ff(Iw.m)142 b(Integer)418 668 y(Ow.m)g(Octal)47 b(integer)418 781 y(Zw.m)142 b(Hexadecimal)45 b(integer)418 894 y(Fw.d)142 b(Fixed)47 b(floating)e(point)418 1007 y(Ew.d)142 b(Exponential)45 b(floating)h(point)418 1120 y(Dw.d)142 b(Exponential)45 b(floating)h(point)418 1233 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)e(not)i (lost,)f(else)h(Ew.d)227 1483 y Fj(where)24 b(w)h(is)f(the)h(width)f (in)g(c)m(haracters)i(of)f(the)g(displa)m(y)m(ed)g(v)-5 b(alues,)27 b(m)d(is)h(the)f(minim)m(um)g(n)m(um)m(b)s(er)g(of)g (digits)227 1595 y(displa)m(y)m(ed,)31 b(and)e(d)h(is)f(the)i(n)m(um)m (b)s(er)d(of)i(digits)g(to)h(the)f(righ)m(t)h(of)f(the)g(decimal.)41 b(The)29 b(.m)h(\014eld)g(is)g(optional.)382 1855 y Ff (FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o(m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o (nts)o(,nul)o(lval)o(,)42 b(>)1098 1968 y(values,anyf,status\))0 2228 y Fi(5)81 b Fj(Get)42 b(the)g(table)h(column)e(n)m(um)m(b)s(er)g (and)g(full)g(name)h(of)g(the)f(column)h(whose)f(name)h(matc)m(hes)h (the)f(input)227 2341 y(template)35 b(string.)48 b(See)33 b(the)h(`Adv)-5 b(anced)33 b(In)m(terface)h(Routines')f(c)m(hapter)h (for)f(a)g(full)g(description)g(of)g(this)227 2454 y(routine.)382 2714 y Ff(FTGCNN\(unit,casesen,colt)o(emp)o(late)o(,)42 b(>)47 b(colname,colnum,status\))p eop end %%Page: 35 41 TeXDict begin 35 40 bop 0 1225 a Fg(Chapter)65 b(6)0 1687 y Fm(Adv)-13 b(anced)78 b(In)-6 b(terface)77 b(Subroutines)0 2180 y Fj(This)31 b(c)m(hapter)h(de\014nes)f(all)h(the)g(a)m(v)-5 b(ailable)34 b(subroutines)d(in)g(the)h(FITSIO)e(user)h(in)m(terface.) 46 b(F)-8 b(or)33 b(completeness,)0 2293 y(the)43 b(basic)g (subroutines)e(describ)s(ed)g(in)i(the)f(previous)h(c)m(hapter)g(are)g (also)g(rep)s(eated)g(here.)77 b(A)43 b(righ)m(t)g(arro)m(w)0 2406 y(sym)m(b)s(ol)29 b(is)f(used)g(here)h(to)g(separate)h(the)f (input)f(parameters)h(from)f(the)h(output)g(parameters)g(in)f(the)h (de\014nition)0 2518 y(of)k(eac)m(h)h(subroutine.)47 b(This)32 b(sym)m(b)s(ol)h(is)g(not)g(actually)i(part)d(of)h(the)h (calling)g(sequence.)49 b(An)32 b(alphab)s(etical)i(list)0 2631 y(and)c(de\014nition)g(of)g(all)i(the)e(parameters)h(is)f(giv)m (en)i(at)f(the)f(end)g(of)h(this)f(section.)0 2961 y Fe(6.1)135 b(FITS)44 b(File)i(Op)t(en)e(and)h(Close)h(Subroutines:)0 3197 y Fi(1)81 b Fj(Op)s(en)30 b(an)i(existing)g(FITS)g(\014le)f(with)h (readonly)g(or)g(readwrite)g(access.)46 b(The)31 b(FTDK)m(OPN)i (routine)e(simply)227 3310 y(op)s(ens)h(the)g(sp)s(eci\014ed)g(\014le)h (without)f(trying)h(to)g(in)m(terpret)g(the)f(\014lename)h(using)f(the) g(extended)h(\014lename)227 3423 y(syn)m(tax.)41 b(FTDOPN)28 b(op)s(ens)e(the)i(\014le)g(and)f(also)i(mo)m(v)m(es)g(to)g(the)f (\014rst)f(HDU)h(con)m(taining)h(signi\014can)m(t)g(data,)227 3536 y(if)35 b(no)h(sp)s(eci\014c)f(HDU)h(is)f(sp)s(eci\014ed)f(as)i (part)f(of)g(the)h(\014lename.)55 b(FTTOPN)35 b(and)f(FTIOPN)h(are)h (similar)227 3649 y(except)26 b(that)f(they)g(will)g(mo)m(v)m(e)h(to)g (the)f(\014rst)f(table)h(HDU)h(or)e(image)i(HDU,)g(resp)s(ectiv)m(ely) -8 b(,)28 b(if)c(a)h(HDU)h(name)227 3762 y(or)31 b(n)m(um)m(b)s(er)e (is)h(not)h(sp)s(eci\014ed)e(as)i(part)f(of)h(the)f(\014lename.)382 3996 y Ff(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(blocksize,status\))382 4108 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 b(blocksize,status\))382 4334 y(FTDOPN\(unit,filename,rwm)o(ode) o(,)42 b(>)47 b(status\))382 4447 y(FTTOPN\(unit,filename,rwm)o(ode)o (,)42 b(>)47 b(status\))382 4560 y(FTIOPN\(unit,filename,rwm)o(ode)o(,) 42 b(>)47 b(status\))0 4794 y Fi(2)81 b Fj(Op)s(en)24 b(an)i(existing)h(FITS)e(\014le)h(with)f(readonly)h(or)g(readwrite)g (access)h(and)f(mo)m(v)m(e)h(to)f(a)h(follo)m(wing)g(extension,)227 4907 y(if)38 b(one)g(w)m(as)g(sp)s(eci\014ed)g(as)g(part)f(of)h(the)h (\014lename.)63 b(\(e.g.,)42 b('\014lename.\014ts+2')c(or)g ('\014lename.\014ts[2]')i(will)227 5020 y(mo)m(v)m(e)e(to)g(the)e(3rd)g (HDU)i(in)e(the)h(\014le\).)60 b(Note)37 b(that)h(this)e(routine)h (di\013ers)f(from)g(FTOPEN)g(in)g(that)h(it)227 5133 y(do)s(es)30 b(not)h(ha)m(v)m(e)h(the)e(redundan)m(t)f(blo)s(c)m(ksize) j(argumen)m(t.)382 5367 y Ff(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))0 5601 y Fi(3)81 b Fj(Reop)s(en)38 b(a)i(FITS)e(\014le)i(that)f(w)m(as)h(previously)f(op)s(ened)f(with)h (FTOPEN,)g(FTNOPN,)g(or)h(FTINIT.)e(The)227 5714 y(newunit)f(n)m(um)m (b)s(er)f(ma)m(y)j(then)e(b)s(e)g(treated)i(as)f(a)g(separate)g (\014le,)i(and)d(one)h(ma)m(y)h(sim)m(ultaneously)f(read)1905 5942 y(35)p eop end %%Page: 36 42 TeXDict begin 36 41 bop 0 299 a Fj(36)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)227 555 y Fj(or)36 b(write)g(to)g(2)g(\(or)g(more\))g (di\013eren)m(t)g(extensions)g(in)f(the)h(same)g(\014le.)56 b(The)35 b(FTOPEN)g(and)g(FTNOPN)227 668 y(routines)f(\(ab)s(o)m(v)m (e\))h(automatically)h(detects)f(cases)g(where)e(a)g(previously)h(op)s (ened)e(\014le)i(is)g(b)s(eing)f(op)s(ened)227 781 y(again,)c(and)e (then)g(in)m(ternally)h(call)g(FTREOPEN,)f(so)h(programs)e(should)h (rarely)g(need)g(to)h(explicitly)h(call)227 894 y(this)i(routine.)334 1136 y Ff(FTREOPEN\(unit,)44 b(>)j(newunit,)f(status\))0 1377 y Fi(4)81 b Fj(Op)s(en)24 b(and)g(initialize)k(a)e(new)f(empt)m(y) g(FITS)g(\014le.)39 b(The)25 b(FTDKINIT)g(routine)g(simply)g(creates)i (the)f(sp)s(eci\014ed)227 1490 y(\014le)31 b(without)f(trying)h(to)g (in)m(terpret)f(the)h(\014lename)g(using)e(the)i(extended)f(\014lename) h(syn)m(tax.)334 1732 y Ff(FTINIT\(unit,filename,bloc)o(ksi)o(ze,)41 b(>)48 b(status\))334 1845 y(FTDKINIT\(unit,filename,bl)o(ock)o(size)o (,)42 b(>)47 b(status\))0 2087 y Fi(5)81 b Fj(Create)24 b(a)g(new)f(FITS)g(\014le,)i(using)e(a)h(template)h(\014le)e(to)i (de\014ne)d(its)i(initial)h(size)g(and)e(structure.)37 b(The)24 b(template)227 2199 y(ma)m(y)39 b(b)s(e)f(another)h(FITS)e (HDU)i(or)g(an)f(ASCI)s(I)f(template)j(\014le.)64 b(If)38 b(the)h(input)e(template)j(\014le)e(name)h(is)227 2312 y(blank,)28 b(then)f(this)g(routine)g(b)s(eha)m(v)m(es)h(the)f(same)h (as)f(FTINIT.)g(The)f(curren)m(tly)i(supp)s(orted)d(format)i(of)h(the) 227 2425 y(ASCI)s(I)c(template)j(\014le)f(is)f(describ)s(ed)g(under)f (the)i(\014ts)p 2037 2425 28 4 v 32 w(parse)p 2277 2425 V 33 w(template)g(routine)g(\(in)g(the)f(general)i(Utilities)227 2538 y(section\),)32 b(but)e(this)g(ma)m(y)h(c)m(hange)h(sligh)m(tly)g (later)f(releases)g(of)g(CFITSIO.)334 2780 y Ff(FTTPLT\(unit,)45 b(filename,)g(tplfilename,)f(>)k(status\))0 3022 y Fi(6)81 b Fj(Flush)33 b(in)m(ternal)h(bu\013ers)f(of)h(data)g(to)g(the)g (output)g(FITS)f(\014le)h(previously)f(op)s(ened)g(with)g(ftop)s(en)h (or)f(ftinit.)227 3135 y(The)j(routine)h(usually)f(nev)m(er)h(needs)f (to)i(b)s(e)e(called,)j(but)d(doing)h(so)g(will)g(ensure)f(that)h(if)f (the)h(program)227 3247 y(subsequen)m(tly)30 b(ab)s(orts,)g(then)h(the) f(FITS)g(\014le)g(will)h(ha)m(v)m(e)h(at)f(least)g(b)s(een)f(closed)h (prop)s(erly)-8 b(.)382 3489 y Ff(FTFLUS\(unit,)44 b(>)k(status\))0 3731 y Fi(7)81 b Fj(Close)31 b(a)f(FITS)g(\014le)g(previously)g(op)s (ened)g(with)g(ftop)s(en)g(or)g(ftinit)382 3973 y Ff(FTCLOS\(unit,)44 b(>)k(status\))0 4214 y Fi(8)81 b Fj(Close)34 b(and)f(DELETE)g(a)h (FITS)f(\014le)h(previously)f(op)s(ened)g(with)g(ftop)s(en)g(or)h (ftinit.)51 b(This)33 b(routine)g(ma)m(y)i(b)s(e)227 4327 y(useful)29 b(in)h(cases)g(where)g(a)g(FITS)f(\014le)g(is)h (created,)h(but)e(an)h(error)f(o)s(ccurs)h(whic)m(h)f(prev)m(en)m(ts)i (the)e(complete)227 4440 y(\014le)i(from)f(b)s(eing)g(written.)382 4682 y Ff(FTDELT\(unit,)44 b(>)k(status\))0 4924 y Fi(9)81 b Fj(Get)31 b(the)g(v)-5 b(alue)31 b(of)f(an)g(un)m(used)g(I/O)g(unit)g (n)m(um)m(b)s(er)f(whic)m(h)h(ma)m(y)h(then)f(b)s(e)g(used)g(as)g (input)g(to)h(FTOPEN)f(or)227 5036 y(FTINIT.)36 b(This)f(routine)h (searc)m(hes)h(for)f(the)g(\014rst)f(un)m(used)g(unit)g(n)m(um)m(b)s (er)g(in)g(the)i(range)f(from)f(with)h(99)227 5149 y(do)m(wn)d(to)h (50.)50 b(This)32 b(routine)h(just)g(k)m(eeps)h(an)f(in)m(ternal)h (list)f(of)h(the)f(allo)s(cated)i(unit)e(n)m(um)m(b)s(ers)f(and)g(do)s (es)227 5262 y(not)26 b(ph)m(ysically)g(c)m(hec)m(k)g(that)g(the)g(F)-8 b(ortran)25 b(unit)g(is)g(a)m(v)-5 b(ailable)28 b(\(to)e(b)s(e)f (compatible)h(with)f(the)g(SPP)f(v)m(ersion)227 5375 y(of)35 b(FITSIO\).)g(Th)m(us)f(users)g(m)m(ust)h(not)g(indep)s(enden)m (tly)f(allo)s(cate)j(an)m(y)f(unit)e(n)m(um)m(b)s(ers)g(in)h(the)g (range)g(50)227 5488 y(-)42 b(99)g(if)f(this)g(routine)g(is)g(also)h (to)g(b)s(e)f(used)f(in)h(the)g(same)h(program.)73 b(This)40 b(routine)h(is)g(pro)m(vided)g(for)227 5601 y(con)m(v)m(enience)34 b(only)-8 b(,)32 b(and)e(it)i(is)f(not)h(required)e(that)i(the)f(unit)g (n)m(um)m(b)s(ers)f(used)g(b)m(y)h(FITSIO)f(b)s(e)h(allo)s(cated)227 5714 y(b)m(y)g(this)f(routine.)p eop end %%Page: 37 43 TeXDict begin 37 42 bop 0 299 a Fh(6.1.)72 b(FITS)30 b(FILE)g(OPEN)g(AND)h(CLOSE)e(SUBR)m(OUTINES:)1561 b Fj(37)382 555 y Ff(FTGIOU\()46 b(>)h(iounit,)f(status\))0 809 y Fi(10)g Fj(F)-8 b(ree)34 b(\(deallo)s(cate\))i(an)d(I/O)g(unit)f (n)m(um)m(b)s(er)g(whic)m(h)g(w)m(as)h(previously)g(allo)s(cated)i (with)e(FTGIOU.)g(All)g(pre-)227 922 y(viously)28 b(allo)s(cated)i (unit)d(n)m(um)m(b)s(ers)f(ma)m(y)i(b)s(e)f(deallo)s(cated)j(at)e(once) h(b)m(y)e(calling)i(FTFIOU)f(with)f(iounit)h(=)227 1034 y(-1.)382 1288 y Ff(FTFIOU\(iounit,)44 b(>)j(status\))0 1541 y Fi(11)f Fj(Return)30 b(the)h(F)-8 b(ortran)31 b(unit)g(n)m(um)m(b)s(er)e(that)i(corresp)s(onds)f(to)h(the)g(C)g (\014ts\014le)f(p)s(oin)m(ter)h(v)-5 b(alue,)32 b(or)e(vice)i(v)m (ersa.)227 1654 y(These)37 b(2)h(C)f(routines)g(ma)m(y)g(b)s(e)g (useful)f(in)h(mixed)g(language)i(programs)e(where)f(b)s(oth)h(C)g(and) f(F)-8 b(ortran)227 1767 y(subroutines)25 b(need)g(to)i(access)g(the)f (same)g(\014le.)40 b(F)-8 b(or)26 b(example,)i(if)e(a)g(FITS)f(\014le)h (is)g(op)s(ened)f(with)g(unit)g(12)i(b)m(y)227 1880 y(a)k(F)-8 b(ortran)31 b(subroutine,)f(then)g(a)h(C)f(routine)h(within)f(the)g (same)h(program)g(could)f(get)i(the)e(\014t\014le)h(p)s(oin)m(ter)227 1993 y(v)-5 b(alue)39 b(to)f(access)h(the)f(same)h(\014le)f(b)m(y)f (calling)j('fptr)d(=)h(CUnit2FITS\(12\)'.)64 b(These)38 b(routines)g(return)f(a)227 2106 y(v)-5 b(alue)31 b(of)g(zero)g(if)f (an)g(error)g(o)s(ccurs.)286 2359 y Ff(int)334 b(CFITS2Unit\(fitsfile) 42 b(*ptr\);)286 2472 y(fitsfile*)k(CUnit2FITS\(int)e(unit\);)0 2726 y Fi(11)i Fj(P)m(arse)32 b(the)g(input)e(\014lename)i(and)f (return)f(the)i(HDU)g(n)m(um)m(b)s(er)e(that)i(w)m(ould)f(b)s(e)g(mo)m (v)m(ed)i(to)f(if)f(the)h(\014le)f(w)m(ere)227 2838 y(op)s(ened)i(with) g(FTNOPN.)g(The)f(returned)g(HDU)i(n)m(um)m(b)s(er)e(b)s(egins)h(with)g (1)g(for)g(the)g(primary)g(arra)m(y)-8 b(,)35 b(so)227 2951 y(for)d(example,)g(if)g(the)g(input)f(\014lename)g(=)h(`m)m (y\014le.\014ts[2]')h(then)e(hdun)m(um)e(=)j(3)g(will)g(b)s(e)f (returned.)43 b(FIT-)227 3064 y(SIO)35 b(do)s(es)h(not)g(op)s(en)g(the) g(\014le)g(to)h(c)m(hec)m(k)h(if)e(the)g(extension)h(actually)h(exists) e(if)h(an)e(extension)i(n)m(um)m(b)s(er)227 3177 y(is)43 b(sp)s(eci\014ed.)75 b(If)42 b(an)g(extension)h(*name*)g(is)f(included) g(in)g(the)g(\014le)g(name)h(sp)s(eci\014cation)g(\(e.g.)77 b(`m)m(y-)227 3290 y(\014le.\014ts[EVENTS]')30 b(then)f(this)h(routine) g(will)g(ha)m(v)m(e)h(to)f(op)s(en)f(the)h(FITS)f(\014le)h(and)f(lo)s (ok)h(for)g(the)g(p)s(osition)227 3403 y(of)38 b(the)h(named)e (extension,)k(then)d(close)h(\014le)f(again.)64 b(This)38 b(is)g(not)g(p)s(ossible)f(if)h(the)g(\014le)g(is)g(b)s(eing)g(read)227 3516 y(from)e(the)g(stdin)f(stream,)j(and)d(an)h(error)f(will)h(b)s(e)g (returned)e(in)i(this)g(case.)58 b(If)35 b(the)h(\014lename)g(do)s(es)g (not)227 3629 y(sp)s(ecify)29 b(an)g(explicit)h(extension)g(\(e.g.)42 b('m)m(y\014le.\014ts'\))30 b(then)f(hdun)m(um)e(=)h(-99)j(will)e(b)s (e)g(returned,)f(whic)m(h)h(is)227 3742 y(functionally)34 b(equiv)-5 b(alen)m(t)35 b(to)g(hdun)m(um)c(=)i(1.)50 b(This)33 b(routine)g(is)h(mainly)g(used)e(for)i(bac)m(kw)m(ard)g (compati-)227 3855 y(bilit)m(y)g(in)e(the)g(fto)s(ols)h(soft)m(w)m(are) h(pac)m(k)-5 b(age)34 b(and)e(is)g(not)g(recommended)g(for)g(general)i (use.)46 b(It)32 b(is)h(generally)227 3968 y(b)s(etter)i(and)g(more)g (e\016cien)m(t)h(to)g(\014rst)e(op)s(en)g(the)h(FITS)f(\014le)h(with)g (FTNOPN,)g(then)g(use)f(FTGHDN)i(to)227 4080 y(determine)30 b(whic)m(h)g(HDU)g(in)f(the)h(\014le)g(has)g(b)s(een)f(op)s(ened,)g (rather)g(than)h(calling)h(FTEXTN)f(follo)m(w)m(ed)h(b)m(y)227 4193 y(a)g(call)h(to)f(FTNOPN.)382 4447 y Ff(FTEXTN\(filename,)43 b(>)48 b(nhdu,)e(status\))0 4700 y Fi(12)g Fj(Return)30 b(the)g(name)h(of)f(the)h(op)s(ened)e(FITS)h(\014le.)382 4954 y Ff(FTFLNM\(unit,)44 b(>)k(filename,)d(status\))0 5207 y Fi(13)h Fj(Return)30 b(the)g(I/O)g(mo)s(de)g(of)h(the)g(op)s(en) e(FITS)h(\014le)g(\(READONL)-8 b(Y)32 b(=)e(0,)h(READ)m(WRITE)g(=)f (1\).)382 5460 y Ff(FTFLMD\(unit,)44 b(>)k(iomode,)e(status\))0 5714 y Fi(14)g Fj(Return)30 b(the)g(\014le)h(t)m(yp)s(e)f(of)h(the)f (op)s(ened)g(FITS)g(\014le)g(\(e.g.)42 b('\014le://',)32 b('ftp://',)g(etc.\).)p eop end %%Page: 38 44 TeXDict begin 38 43 bop 0 299 a Fj(38)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTURLT\(unit,)44 b(>)k(urltype,)d (status\))0 821 y Fi(15)h Fj(P)m(arse)27 b(the)f(input)f(\014lename)i (or)f(URL)g(in)m(to)h(its)g(comp)s(onen)m(t)f(parts:)39 b(the)26 b(\014le)g(t)m(yp)s(e)h(\(\014le://,)h(ftp://,)g(h)m(ttp://,) 227 934 y(etc\),)34 b(the)e(base)g(input)e(\014le)i(name,)g(the)g(name) g(of)g(the)g(output)f(\014le)h(that)g(the)g(input)f(\014le)g(is)h(to)g (b)s(e)f(copied)227 1046 y(to)38 b(prior)e(to)h(op)s(ening,)h(the)f (HDU)g(or)f(extension)i(sp)s(eci\014cation,)h(the)e(\014ltering)f(sp)s (eci\014er,)i(the)f(binning)227 1159 y(sp)s(eci\014er,)e(and)e(the)i (column)f(sp)s(eci\014er.)51 b(Blank)34 b(strings)g(will)h(b)s(e)e (returned)g(for)h(an)m(y)g(comp)s(onen)m(ts)g(that)227 1272 y(are)d(not)g(presen)m(t)f(in)g(the)h(input)e(\014le)i(name.)334 1538 y Ff(FTIURL\(filename,)43 b(>)48 b(filetype,)d(infile,)h(outfile,) g(extspec,)f(filter,)716 1651 y(binspec,)g(colspec,)h(status\))0 1916 y Fi(16)g Fj(P)m(arse)e(the)g(input)f(\014le)h(name)f(and)g (return)g(the)h(ro)s(ot)g(\014le)f(name.)81 b(The)43 b(ro)s(ot)h(name)g(includes)f(the)h(\014le)227 2029 y(t)m(yp)s(e)35 b(if)g(sp)s(eci\014ed,)h(\(e.g.)56 b('ftp://')37 b(or)e('h)m(ttp://'\)) i(and)d(the)h(full)g(path)g(name,)h(to)g(the)f(exten)m(t)i(that)e(it)h (is)227 2142 y(sp)s(eci\014ed)26 b(in)f(the)i(input)e(\014lename.)39 b(It)26 b(do)s(es)g(not)g(include)g(the)g(HDU)h(name)f(or)g(n)m(um)m(b) s(er,)g(or)g(an)m(y)h(\014ltering)227 2255 y(sp)s(eci\014cations.)334 2520 y Ff(FTRTNM\(filename,)43 b(>)48 b(rootname,)d(status\))0 2786 y Fi(16)h Fj(T)-8 b(est)36 b(if)g(the)g(input)f(\014le)h(or)f(a)i (compressed)e(v)m(ersion)h(of)g(the)g(\014le)g(\(with)g(a)g(.gz,)i(.Z,) e(.z,)i(or)e(.zip)g(extension\))227 2899 y(exists)j(on)f(disk.)63 b(The)37 b(returned)g(v)-5 b(alue)38 b(of)g(the)h('exists')g(parameter) f(will)g(ha)m(v)m(e)i(1)e(of)g(the)g(4)g(follo)m(wing)227 3011 y(v)-5 b(alues:)370 3270 y Ff(2:)95 b(the)47 b(file)g(does)g(not)f (exist,)h(but)f(a)i(compressed)d(version)h(does)g(exist)370 3383 y(1:)95 b(the)47 b(disk)g(file)g(does)f(exist)370 3496 y(0:)95 b(neither)46 b(the)h(file)g(nor)g(a)g(compressed)e (version)h(of)h(the)g(file)g(exist)323 3609 y(-1:)94 b(the)47 b(input)g(file)f(name)h(is)g(not)g(a)g(disk)g(file)g(\(could)f (be)h(a)g(ftp,)g(http,)561 3722 y(smem,)g(or)g(mem)g(file,)f(or)h(a)h (file)e(piped)h(in)g(on)g(the)g(STDIN)f(stream\))286 3987 y(FTEXIST\(filename,)d(>)48 b(exists,)e(status\);)0 4327 y Fe(6.2)135 b(HDU-Lev)l(el)47 b(Op)t(erations)0 4579 y Fj(When)30 b(a)h(FITS)f(\014le)g(is)h(\014rst)e(op)s(ened)h(or)g (created,)i(the)f(in)m(ternal)g(bu\013ers)e(in)h(FITSIO)f (automatically)34 b(p)s(oin)m(t)c(to)0 4692 y(the)g(\014rst)g(HDU)h(in) f(the)g(\014le.)41 b(The)29 b(follo)m(wing)j(routines)e(ma)m(y)h(b)s(e) e(used)h(to)h(mo)m(v)m(e)g(to)g(another)f(HDU)h(in)f(the)h(\014le.)0 4805 y(Note)j(that)f(the)g(HDU)g(n)m(um)m(b)s(ering)f(con)m(v)m(en)m (tion)i(used)e(in)g(FITSIO)g(denotes)h(the)f(primary)g(arra)m(y)h(as)g (the)g(\014rst)0 4918 y(HDU,)e(the)g(\014rst)f(extension)h(in)f(a)g (FITS)g(\014le)g(is)h(the)f(second)h(HDU,)g(and)f(so)h(on.)0 5183 y Fi(1)81 b Fj(Mo)m(v)m(e)32 b(to)f(a)g(sp)s(eci\014ed)f (\(absolute\))h(HDU)g(in)g(the)f(FITS)g(\014le)g(\(nhdu)f(=)h(1)h(for)f (the)g(FITS)g(primary)f(arra)m(y\))382 5448 y Ff(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))0 5714 y Fi(2)81 b Fj(Mo)m(v)m(e)32 b(to)f(a)g(new)f(\(existing\))i(HDU)f(forw)m(ard)f(or)g(bac)m(kw)m (ards)h(relativ)m(e)h(to)f(the)g(CHDU)p eop end %%Page: 39 45 TeXDict begin 39 44 bop 0 299 a Fh(6.2.)72 b(HDU-LEVEL)31 b(OPERA)-8 b(TIONS)2414 b Fj(39)382 555 y Ff(FTMRHD\(unit,nmove,)43 b(>)k(hdutype,status\))0 797 y Fi(3)81 b Fj(Mo)m(v)m(e)22 b(to)f(the)f(\(\014rst\))h(HDU)g(whic)m(h)f(has)g(the)g(sp)s(eci\014ed) g(extension)h(t)m(yp)s(e)f(and)g(EXTNAME)g(\(or)h(HDUNAME\))227 910 y(and)34 b(EXTVER)g(k)m(eyw)m(ord)h(v)-5 b(alues.)53 b(The)34 b(hdut)m(yp)s(e)f(parameter)i(ma)m(y)g(ha)m(v)m(e)g(a)g(v)-5 b(alue)35 b(of)f(IMA)m(GE)p 3665 910 28 4 v 34 w(HDU)227 1023 y(\(0\),)43 b(ASCI)s(I)p 669 1023 V 31 w(TBL)c(\(1\),)j(BINAR)-8 b(Y)p 1468 1023 V 34 w(TBL)39 b(\(2\),)j(or)d(ANY)p 2234 1023 V 34 w(HDU)g(\(-1\))i(where)d(ANY)p 3173 1023 V 34 w(HDU)h(means)g(that)227 1136 y(only)30 b(the)g(extname)h(and)e (extv)m(er)i(v)-5 b(alues)30 b(will)g(b)s(e)f(used)g(to)i(lo)s(cate)g (the)f(correct)h(extension.)42 b(If)29 b(the)h(input)227 1249 y(v)-5 b(alue)27 b(of)f(extv)m(er)h(is)f(0)g(then)g(the)g(EXTVER)g (k)m(eyw)m(ord)g(is)g(ignored)g(and)g(the)g(\014rst)f(HDU)i(with)e(a)i (matc)m(hing)227 1361 y(EXTNAME)g(\(or)g(HDUNAME\))h(k)m(eyw)m(ord)f (will)g(b)s(e)f(found.)38 b(If)26 b(no)h(matc)m(hing)h(HDU)f(is)g (found)e(in)h(the)h(\014le)227 1474 y(then)i(the)g(curren)m(t)g(HDU)h (will)f(remain)g(unc)m(hanged)g(and)g(a)g(status)g(=)g(BAD)p 2884 1474 V 34 w(HDU)p 3123 1474 V 33 w(NUM)h(\(301\))h(will)f(b)s(e) 227 1587 y(returned.)382 1829 y Ff(FTMNHD\(unit,)44 b(hdutype,)i (extname,)f(extver,)h(>)i(status\))0 2071 y Fi(4)81 b Fj(Get)31 b(the)g(n)m(um)m(b)s(er)e(of)h(the)h(curren)m(t)f(HDU)h(in)f (the)h(FITS)e(\014le)i(\(primary)f(arra)m(y)g(=)g(1\))382 2312 y Ff(FTGHDN\(unit,)44 b(>)k(nhdu\))0 2554 y Fi(5)81 b Fj(Return)39 b(the)i(t)m(yp)s(e)g(of)g(the)g(curren)m(t)f(HDU)i(in)e (the)h(FITS)f(\014le.)71 b(The)41 b(p)s(ossible)f(v)-5 b(alues)41 b(for)f(hdut)m(yp)s(e)g(are)227 2667 y(IMA)m(GE)p 546 2667 V 34 w(HDU)31 b(\(0\),)h(ASCI)s(I)p 1242 2667 V 31 w(TBL)e(\(1\),)i(or)e(BINAR)-8 b(Y)p 2133 2667 V 34 w(TBL)30 b(\(2\).)382 2909 y Ff(FTGHDT\(unit,)44 b(>)k(hdutype,)d (status\))0 3150 y Fi(6)81 b Fj(Return)29 b(the)i(total)h(n)m(um)m(b)s (er)d(of)i(HDUs)f(in)h(the)f(FITS)g(\014le.)41 b(The)29 b(CHDU)i(remains)f(unc)m(hanged.)382 3392 y Ff(FTTHDU\(unit,)44 b(>)k(hdunum,)e(status\))0 3634 y Fi(7)81 b Fj(Create)34 b(\(app)s(end\))f(a)i(new)e(empt)m(y)h(HDU)h(at)g(the)f(end)f(of)h(the) h(FITS)e(\014le.)51 b(This)33 b(new)h(HDU)h(b)s(ecomes)f(the)227 3747 y(Curren)m(t)j(HDU,)i(but)e(it)h(is)g(completely)h(empt)m(y)f(and) g(con)m(tains)h(no)e(header)h(k)m(eyw)m(ords)g(or)g(data.)63 b(It)38 b(is)227 3860 y(recommended)30 b(that)h(FTI)s(IMG,)g(FTIT)-8 b(AB)30 b(or)h(FTIBIN)f(b)s(e)g(used)g(instead)g(of)h(this)f(routine.) 382 4101 y Ff(FTCRHD\(unit,)44 b(>)k(status\))0 4343 y Fi(8)81 b Fj(Create)30 b(a)f(primary)f(arra)m(y)i(\(if)g(none)f (already)g(exists\),)i(or)e(insert)g(a)h(new)f(IMA)m(GE)h(extension)g (immediately)227 4456 y(follo)m(wing)25 b(the)e(CHDU,)g(or)g(insert)g (a)g(new)g(Primary)f(Arra)m(y)h(at)h(the)f(b)s(eginning)f(of)h(the)g (\014le.)38 b(An)m(y)23 b(follo)m(wing)227 4569 y(extensions)29 b(in)g(the)g(\014le)f(will)h(b)s(e)f(shifted)h(do)m(wn)f(to)h(mak)m(e)h (ro)s(om)e(for)h(the)g(new)f(extension.)40 b(If)29 b(the)g(CHDU)227 4682 y(is)h(the)g(last)g(HDU)g(in)g(the)f(\014le)h(then)f(the)h(new)f (image)i(extension)f(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)g (end)227 4795 y(of)k(the)h(\014le.)52 b(One)33 b(can)h(force)h(a)g(new) e(primary)g(arra)m(y)i(to)g(b)s(e)e(inserted)h(at)h(the)f(b)s(eginning) f(of)h(the)h(FITS)227 4908 y(\014le)29 b(b)m(y)f(setting)i(status)e(=)h (-9)g(prior)e(to)j(calling)g(the)e(routine.)40 b(In)28 b(this)g(case)i(the)e(existing)i(primary)d(arra)m(y)227 5021 y(will)f(b)s(e)f(con)m(v)m(erted)i(to)g(an)e(IMA)m(GE)h (extension.)40 b(The)25 b(new)g(extension)i(\(or)f(primary)e(arra)m (y\))j(will)f(b)s(ecome)227 5133 y(the)32 b(CHDU.)f(The)g(FTI)s(IMGLL)f (routine)i(is)f(iden)m(tical)i(to)e(the)h(FTI)s(IMG)f(routine)g(except) h(that)f(the)h(4th)227 5246 y(parameter)25 b(\(the)g(length)g(of)f(eac) m(h)h(axis\))g(is)g(an)f(arra)m(y)h(of)f(64-bit)i(in)m(tegers)f(rather) f(than)g(an)g(arra)m(y)h(of)g(32-bit)227 5359 y(in)m(tegers.)382 5601 y Ff(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 5714 y(FTIIMGLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)41 b(>)47 b(status\))p eop end %%Page: 40 46 TeXDict begin 40 45 bop 0 299 a Fj(40)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(9)81 b Fj(Insert)30 b(a)i(new)f(ASCI)s(I)f (T)-8 b(ABLE)31 b(extension)h(immediately)h(follo)m(wing)f(the)g(CHDU.) g(An)m(y)f(follo)m(wing)i(exten-)227 668 y(sions)26 b(will)g(b)s(e)f (shifted)g(do)m(wn)g(to)h(mak)m(e)h(ro)s(om)e(for)h(the)f(new)g (extension.)40 b(If)25 b(there)h(are)g(no)g(other)f(follo)m(wing)227 781 y(extensions)32 b(then)f(the)h(new)f(table)h(extension)g(will)g (simply)f(b)s(e)g(app)s(ended)f(to)i(the)f(end)g(of)h(the)f(\014le.)44 b(The)227 894 y(new)33 b(extension)h(will)f(b)s(ecome)h(the)f(CHDU.)h (The)f(FTIT)-8 b(ABLL)33 b(routine)g(is)g(iden)m(tical)i(to)f(the)g (FTIT)-8 b(AB)227 1007 y(routine)36 b(except)g(that)g(the)f(2nd)g(and)g (3rd)g(parameters)g(\(that)i(giv)m(e)g(the)e(size)h(of)g(the)f(table\)) i(are)f(64-bit)227 1120 y(in)m(tegers)c(rather)e(than)g(32-bit)i(in)m (tegers.)382 1377 y Ff(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o (ype)o(,tbc)o(ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1490 y(status\))382 1603 y(FTITABLL\(unit,rowlenll,n)o(row)o (sll,)o(tfie)o(lds)o(,tty)o(pe,t)o(bco)o(l,tf)o(orm,)o(tun)o(it,e)o (xtna)o(me,)f(>)716 1716 y(status\))0 1974 y Fi(10)46 b Fj(Insert)25 b(a)h(new)f(binary)f(table)j(extension)f(immediately)g (follo)m(wing)h(the)f(CHDU.)g(An)m(y)g(follo)m(wing)g(extensions)227 2087 y(will)39 b(b)s(e)f(shifted)g(do)m(wn)g(to)h(mak)m(e)g(ro)s(om)g (for)f(the)g(new)g(extension.)66 b(If)38 b(there)h(are)f(no)h(other)f (follo)m(wing)227 2199 y(extensions)f(then)g(the)f(new)g(bin)m(table)h (extension)h(will)f(simply)f(b)s(e)g(app)s(ended)e(to)k(the)e(end)g(of) h(the)g(\014le.)227 2312 y(The)23 b(new)g(extension)h(will)f(b)s(ecome) h(the)f(CHDU.)h(The)f(FTIBINLL)g(routine)g(is)g(iden)m(tical)i(to)f (the)g(FTIBIN)227 2425 y(routine)30 b(except)i(that)e(the)h(2nd)e (parameter)i(\(that)g(giv)m(es)g(the)g(length)f(of)h(the)f(table\))h (is)g(a)f(64-bit)i(in)m(teger)227 2538 y(rather)f(than)f(a)g(32-bit)i (in)m(teger.)382 2796 y Ff(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o (,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 2909 y(FTIBINLL\(unit,nrowsll,tf)o(iel)o(ds,t)o (type)o(,tf)o(orm,)o(tuni)o(t,e)o(xtna)o(me,v)o(ari)o(dat)41 b(>)48 b(status\))0 3279 y Fi(11)e Fj(Resize)26 b(an)e(image)i(b)m(y)e (mo)s(di\014ng)f(the)i(size,)i(dimensions,)e(and/or)f(datat)m(yp)s(e)h (of)g(the)g(curren)m(t)f(primary)f(arra)m(y)227 3392 y(or)29 b(image)i(extension.)40 b(If)29 b(the)g(new)g(image,)i(as)e(sp) s(eci\014ed)f(b)m(y)h(the)g(input)f(argumen)m(ts,)i(is)f(larger)h(than) f(the)227 3505 y(curren)m(t)34 b(existing)h(image)g(in)f(the)g(FITS)f (\014le)h(then)f(zero)i(\014ll)f(data)h(will)f(b)s(e)f(inserted)h(at)g (the)g(end)g(of)g(the)227 3618 y(curren)m(t)25 b(image)h(and)e(an)m(y)i (follo)m(wing)g(extensions)g(will)f(b)s(e)f(mo)m(v)m(ed)i(further)e (bac)m(k)h(in)g(the)g(\014le.)39 b(Similarly)-8 b(,)27 b(if)227 3731 y(the)h(new)e(image)j(is)e(smaller)h(than)f(the)g(curren) m(t)g(image)h(then)f(an)m(y)h(follo)m(wing)h(extensions)e(will)h(b)s(e) e(shifted)227 3844 y(up)32 b(to)m(w)m(ards)i(the)g(b)s(eginning)e(of)h (the)h(FITS)e(\014le)h(and)g(the)g(image)h(data)g(will)g(b)s(e)e (truncated)h(to)h(the)f(new)227 3957 y(size.)41 b(This)25 b(routine)h(rewrites)h(the)f(BITPIX,)h(NAXIS,)f(and)g(NAXISn)g(k)m(eyw) m(ords)g(with)g(the)h(appropriate)227 4070 y(v)-5 b(alues)37 b(for)f(new)h(image.)60 b(The)36 b(FTRSIMLL)g(routine)g(is)h(iden)m (tical)h(to)g(the)e(FTRSIM)g(routine)h(except)227 4183 y(that)30 b(the)g(4th)g(parameter)g(\(the)g(length)g(of)f(eac)m(h)i (axis\))f(is)g(an)f(arra)m(y)h(of)g(64-bit)h(in)m(tegers)f(rather)g (than)f(an)227 4295 y(arra)m(y)i(of)g(32-bit)g(in)m(tegers.)382 4553 y Ff(FTRSIM\(unit,bitpix,naxis)o(,na)o(xes,)o(stat)o(us\))382 4666 y(FTRSIMLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)o(sta)o(tus\))0 4924 y Fi(12)46 b Fj(Delete)34 b(the)f(CHDU)g(in)f(the)g(FITS)f (\014le.)47 b(An)m(y)32 b(follo)m(wing)i(HDUs)f(will)g(b)s(e)e(shifted) h(forw)m(ard)g(in)g(the)g(\014le,)h(to)227 5036 y(\014ll)38 b(in)f(the)g(gap)h(created)g(b)m(y)g(the)f(deleted)h(HDU.)h(In)d(the)i (case)g(of)g(deleting)g(the)g(primary)e(arra)m(y)i(\(the)227 5149 y(\014rst)30 b(HDU)h(in)f(the)h(\014le\))g(then)f(the)h(curren)m (t)f(primary)f(arra)m(y)i(will)g(b)s(e)f(replace)h(b)m(y)g(a)g(n)m(ull) f(primary)f(arra)m(y)227 5262 y(con)m(taining)k(the)f(minim)m(um)e(set) i(of)g(required)e(k)m(eyw)m(ords)i(and)e(no)i(data.)44 b(If)31 b(there)g(are)h(more)f(extensions)227 5375 y(in)f(the)g(\014le) g(follo)m(wing)i(the)e(one)g(that)h(is)f(deleted,)h(then)f(the)g(the)g (CHDU)h(will)f(b)s(e)g(rede\014ned)e(to)j(p)s(oin)m(t)f(to)227 5488 y(the)d(follo)m(wing)h(extension.)41 b(If)26 b(there)h(are)g(no)g (follo)m(wing)h(extensions)f(then)g(the)g(CHDU)g(will)g(b)s(e)f (rede\014ned)227 5601 y(to)35 b(p)s(oin)m(t)f(to)h(the)f(previous)f (HDU.)i(The)e(output)h(HDUTYPE)g(parameter)h(indicates)f(the)h(t)m(yp)s (e)f(of)g(the)227 5714 y(new)c(CHDU)h(after)g(the)f(previous)g(CHDU)h (has)f(b)s(een)g(deleted.)p eop end %%Page: 41 47 TeXDict begin 41 46 bop 0 299 a Fh(6.3.)72 b(DEFINE)31 b(OR)f(REDEFINE)h(THE)f(STR)m(UCTURE)f(OF)h(THE)g(CHDU)1042 b Fj(41)382 555 y Ff(FTDHDU\(unit,)44 b(>)k(hdutype,status\))0 828 y Fi(13)e Fj(Cop)m(y)36 b(all)h(or)f(part)g(of)g(the)g(input)f (FITS)g(\014le)h(and)g(app)s(end)e(it)i(to)h(the)f(end)g(of)g(the)g (output)g(FITS)f(\014le.)57 b(If)227 941 y('previous')39 b(\(an)g(in)m(teger)h(parameter\))g(is)f(not)g(equal)g(to)h(0,)h(then)e (an)m(y)g(HDUs)g(preceding)g(the)g(curren)m(t)227 1054 y(HDU)f(in)e(the)h(input)e(\014le)i(will)g(b)s(e)f(copied)h(to)g(the)g (output)f(\014le.)60 b(Similarly)-8 b(,)39 b('curren)m(t')e(and)f ('follo)m(wing')227 1167 y(determine)j(whether)f(the)h(curren)m(t)g (HDU,)h(and/or)e(an)m(y)i(follo)m(wing)g(HDUs)f(in)g(the)g(input)f (\014le)g(will)i(b)s(e)227 1280 y(copied)32 b(to)g(the)g(output)f (\014le.)43 b(If)31 b(all)h(3)g(parameters)g(are)g(not)f(equal)h(to)g (zero,)h(then)e(the)g(en)m(tire)h(input)f(\014le)227 1393 y(will)g(b)s(e)e(copied.)41 b(On)30 b(return,)f(the)h(curren)m(t)g (HDU)h(in)f(the)g(input)f(\014le)h(will)h(b)s(e)e(unc)m(hanged,)h(and)g (the)g(last)227 1506 y(copied)h(HDU)g(will)g(b)s(e)f(the)g(curren)m(t)g (HDU)i(in)e(the)g(output)g(\014le.)382 1779 y Ff(FTCPFL\(iunit,)44 b(ounit,)i(previous,)f(current,)h(following,)f(>)i(status\))0 2052 y Fi(14)f Fj(Cop)m(y)35 b(the)f(en)m(tire)i(CHDU)f(from)f(the)g (FITS)g(\014le)h(asso)s(ciated)h(with)e(IUNIT)g(to)i(the)e(CHDU)h(of)g (the)g(FITS)227 2165 y(\014le)g(asso)s(ciated)h(with)e(OUNIT.)g(The)g (output)g(HDU)h(m)m(ust)f(b)s(e)g(empt)m(y)h(and)e(not)i(already)g(con) m(tain)h(an)m(y)227 2278 y(k)m(eyw)m(ords.)41 b(Space)29 b(will)g(b)s(e)g(reserv)m(ed)g(for)g(MOREKEYS)f(additional)h(k)m(eyw)m (ords)h(in)e(the)i(output)e(header)227 2391 y(if)j(there)f(is)h(not)f (already)h(enough)f(space.)382 2664 y Ff(FTCOPY\(iunit,ounit,morek)o (eys)o(,)42 b(>)47 b(status\))0 2937 y Fi(15)f Fj(Cop)m(y)27 b(the)h(header)f(\(and)g(not)g(the)g(data\))i(from)d(the)i(CHDU)g(asso) s(ciated)g(with)f(in)m(unit)g(to)h(the)f(CHDU)h(asso-)227 3050 y(ciated)f(with)e(outunit.)39 b(If)25 b(the)g(curren)m(t)h(output) f(HDU)h(is)f(not)h(completely)h(empt)m(y)-8 b(,)27 b(then)e(the)h(CHDU) g(will)227 3163 y(b)s(e)e(closed)i(and)e(a)i(new)e(HDU)h(will)h(b)s(e)e (app)s(ended)f(to)j(the)f(output)f(\014le.)39 b(This)24 b(routine)h(will)g(automatically)227 3276 y(transform)31 b(the)g(necessary)h(k)m(eyw)m(ords)f(when)g(cop)m(ying)h(a)f(primary)g (arra)m(y)h(to)f(and)g(image)i(extension,)f(or)227 3389 y(an)27 b(image)h(extension)f(to)g(a)h(primary)d(arra)m(y)-8 b(.)41 b(An)26 b(empt)m(y)h(output)f(data)i(unit)e(will)h(b)s(e)f (created)i(\(all)g(v)-5 b(alues)227 3501 y(=)30 b(0\).)382 3775 y Ff(FTCPHD\(inunit,)44 b(outunit,)h(>)j(status\))0 4048 y Fi(16)e Fj(Cop)m(y)d(just)g(the)g(data)h(from)f(the)g(CHDU)h (asso)s(ciated)g(with)f(IUNIT)g(to)h(the)f(CHDU)h(asso)s(ciated)g(with) 227 4161 y(OUNIT.)26 b(This)f(will)h(o)m(v)m(erwrite)h(an)m(y)f(data)g (previously)g(in)f(the)h(OUNIT)f(CHDU.)h(This)f(lo)m(w)i(lev)m(el)g (routine)227 4274 y(is)g(used)e(b)m(y)i(FTCOPY,)f(but)g(it)g(ma)m(y)i (also)f(b)s(e)f(useful)f(in)i(certain)g(application)h(programs)e(whic)m (h)g(w)m(an)m(t)h(to)227 4386 y(cop)m(y)j(the)f(data)h(from)f(one)g (FITS)f(\014le)h(to)h(another)f(but)g(also)h(w)m(an)m(t)g(to)g(mo)s (dify)e(the)h(header)g(k)m(eyw)m(ords)g(in)227 4499 y(the)j(pro)s (cess.)44 b(all)33 b(the)f(required)f(header)g(k)m(eyw)m(ords)h(m)m (ust)g(b)s(e)f(written)h(to)g(the)g(OUNIT)f(CHDU)h(b)s(efore)227 4612 y(calling)g(this)e(routine)382 4885 y Ff(FTCPDT\(iunit,ounit,)42 b(>)48 b(status\))0 5235 y Fe(6.3)135 b(De\014ne)45 b(or)g(Rede\014ne)h (the)f(structure)g(of)g(the)g(CHDU)0 5488 y Fj(It)32 b(should)f(rarely)h(b)s(e)g(necessary)g(to)h(call)g(the)f(subroutines)f (in)g(this)h(section.)47 b(FITSIO)30 b(in)m(ternally)j(calls)g(these)0 5601 y(routines)h(whenev)m(er)g(necessary)-8 b(,)36 b(so)e(an)m(y)g (calls)h(to)g(these)f(routines)g(b)m(y)g(application)h(programs)f(will) g(lik)m(ely)i(b)s(e)0 5714 y(redundan)m(t.)p eop end %%Page: 42 48 TeXDict begin 42 47 bop 0 299 a Fj(42)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(1)81 b Fj(This)36 b(routine)h(forces)h (FITSIO)e(to)i(scan)f(the)g(curren)m(t)g(header)g(k)m(eyw)m(ords)h (that)f(de\014ne)g(the)g(structure)g(of)227 668 y(the)31 b(HDU)f(\(suc)m(h)g(as)h(the)f(NAXISn,)g(PCOUNT)f(and)g(GCOUNT)h(k)m (eyw)m(ords\))h(so)f(that)h(it)f(can)h(initialize)227 781 y(the)36 b(in)m(ternal)g(bu\013ers)e(that)i(describ)s(e)f(the)h (HDU)g(structure.)55 b(This)35 b(routine)h(ma)m(y)g(b)s(e)e(used)h (instead)h(of)227 894 y(the)j(more)g(complicated)i(calls)f(to)f(ftp)s (def,)h(ftadef)f(or)g(ftb)s(def.)65 b(This)38 b(routine)h(is)g(also)h (v)m(ery)f(useful)f(for)227 1007 y(reinitializing)e(the)e(structure)g (of)g(an)f(HDU,)i(if)f(the)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)g(a)g (table,)i(as)e(sp)s(eci\014ed)f(b)m(y)h(the)227 1120 y(NAXIS2)d(k)m(eyw)m(ord,)g(has)f(b)s(een)g(mo)s(di\014ed)f(from)h(its) h(initial)g(v)-5 b(alue.)382 1363 y Ff(FTRDEF\(unit,)44 b(>)k(status\))141 b(\(DEPRECATED\))0 1606 y Fi(2)81 b Fj(De\014ne)27 b(the)g(structure)g(of)g(the)g(primary)f(arra)m(y)i (or)f(IMA)m(GE)h(extension.)40 b(When)27 b(writing)g(GR)m(OUP)m(ed)h (FITS)227 1719 y(\014les)43 b(that)h(b)m(y)e(con)m(v)m(en)m(tion)k(set) d(the)g(NAXIS1)g(k)m(eyw)m(ord)h(equal)f(to)h(0,)i(ftp)s(def)c(m)m(ust) h(b)s(e)f(called)i(with)227 1832 y(naxes\(1\))27 b(=)e(1,)i(NOT)e(0,)i (otherwise)f(FITSIO)e(will)i(rep)s(ort)f(an)g(error)g(status=308)i (when)d(trying)i(to)g(write)227 1945 y(data)31 b(to)g(a)g(group.)40 b(Note:)i(it)31 b(is)g(usually)f(simpler)g(to)h(call)h(FTRDEF)e(rather) h(than)f(this)g(routine.)382 2188 y Ff(FTPDEF\(unit,bitpix,naxis)o(,na) o(xes,)o(pcou)o(nt,)o(gcou)o(nt,)41 b(>)48 b(status\))93 b(\(DEPRECATED\))0 2431 y Fi(3)81 b Fj(De\014ne)32 b(the)h(structure)f (of)g(an)h(ASCI)s(I)e(table)i(\(T)-8 b(ABLE\))33 b(extension.)48 b(Note:)e(it)33 b(is)f(usually)g(simpler)g(to)i(call)227 2544 y(FTRDEF)d(rather)f(than)h(this)f(routine.)382 2787 y Ff(FTADEF\(unit,rowlen,tfiel)o(ds,)o(tbco)o(l,tf)o(orm)o(,nro)o(ws)42 b(>)47 b(status\))f(\(DEPRECATED\))0 3030 y Fi(4)81 b Fj(De\014ne)35 b(the)h(structure)f(of)g(a)h(binary)f(table)h(\(BINT)-8 b(ABLE\))37 b(extension.)56 b(Note:)d(it)36 b(is)f(usually)g(simpler)g (to)227 3143 y(call)d(FTRDEF)f(rather)f(than)g(this)g(routine.)382 3386 y Ff(FTBDEF\(unit,tfields,tfor)o(m,v)o(arid)o(at,n)o(row)o(s)42 b(>)47 b(status\))f(\(DEPRECATED\))0 3630 y Fi(5)81 b Fj(De\014ne)34 b(the)g(size)h(of)f(the)g(Curren)m(t)f(Data)i(Unit,)h(o) m(v)m(erriding)e(the)g(length)h(of)f(the)g(data)h(unit)e(as)h (previously)227 3742 y(de\014ned)e(b)m(y)h(ftp)s(def,)g(ftadef,)i(or)e (ftb)s(def.)48 b(This)33 b(is)g(useful)f(if)i(one)f(do)s(es)g(not)h (kno)m(w)f(the)g(total)i(size)f(of)g(the)227 3855 y(data)f(unit)f(un)m (til)h(after)f(the)h(data)g(ha)m(v)m(e)g(b)s(een)f(written.)46 b(The)32 b(size)h(\(in)f(b)m(ytes\))h(of)g(an)f(ASCI)s(I)f(or)h(Binary) 227 3968 y(table)27 b(is)f(giv)m(en)g(b)m(y)g(NAXIS1)g(*)g(NAXIS2.)40 b(\(Note)27 b(that)f(to)h(determine)f(the)f(v)-5 b(alue)27 b(of)f(NAXIS1)f(it)i(is)f(often)227 4081 y(more)32 b(con)m(v)m(enien)m (t)h(to)f(read)f(the)g(v)-5 b(alue)32 b(of)f(the)h(NAXIS1)f(k)m(eyw)m (ord)h(from)e(the)i(output)e(\014le,)i(rather)f(than)227 4194 y(computing)f(the)g(ro)m(w)g(length)h(directly)f(from)f(all)i(the) f(TF)m(ORM)h(k)m(eyw)m(ord)f(v)-5 b(alues\).)41 b(Note:)h(it)30 b(is)g(usually)227 4307 y(simpler)g(to)h(call)h(FTRDEF)f(rather)f(than) g(this)g(routine.)382 4550 y Ff(FTDDEF\(unit,bytlen,)42 b(>)48 b(status\))e(\(DEPRECATED\))0 4793 y Fi(6)81 b Fj(De\014ne)22 b(the)g(zero)i(indexed)d(b)m(yte)i(o\013set)g(of)g(the)f ('heap')h(measured)e(from)h(the)h(start)g(of)f(the)g(binary)g(table)h (data.)227 4906 y(By)30 b(default)g(the)f(heap)h(is)f(assumed)g(to)h (start)g(immediately)h(follo)m(wing)g(the)f(regular)f(table)i(data,)f (i.e.,)h(at)227 5019 y(lo)s(cation)38 b(NAXIS1)f(x)g(NAXIS2.)59 b(This)36 b(routine)g(is)h(only)f(relev)-5 b(an)m(t)38 b(for)e(binary)g(tables)h(whic)m(h)g(con)m(tain)227 5132 y(v)-5 b(ariable)36 b(length)g(arra)m(y)f(columns)g(\(with)h(TF)m(ORMn) f(=)f('Pt'\).)57 b(This)34 b(subroutine)g(also)i(automatically)227 5245 y(writes)23 b(the)g(v)-5 b(alue)23 b(of)g(theap)g(to)h(a)f(k)m (eyw)m(ord)g(in)g(the)g(extension)g(header.)38 b(This)22 b(subroutine)g(m)m(ust)h(b)s(e)f(called)227 5358 y(after)27 b(the)f(required)f(k)m(eyw)m(ords)i(ha)m(v)m(e)g(b)s(een)e(written)h (\(with)g(ftph)m(bn\))f(and)h(after)g(the)h(table)g(structure)e(has)227 5471 y(b)s(een)30 b(de\014ned)f(\(with)h(ftb)s(def)7 b(\))30 b(but)g(b)s(efore)g(an)m(y)g(data)h(is)g(written)f(to)h(the)g (table.)382 5714 y Ff(FTPTHP\(unit,theap,)43 b(>)k(status\))p eop end %%Page: 43 49 TeXDict begin 43 48 bop 0 299 a Fh(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fj(43)0 555 y Fe(6.4)135 b(FITS)44 b(Header)i(I/O)f(Subroutines)0 810 y Fc(6.4.1)112 b(Header)38 b(Space)h(and)f(P)m(osition)f(Routines)0 1021 y Fi(1)81 b Fj(Reserv)m(e)37 b(space)g(in)f(the)h(CHU)f(for)h (MOREKEYS)e(more)i(header)f(k)m(eyw)m(ords.)59 b(This)36 b(subroutine)f(ma)m(y)j(b)s(e)227 1134 y(called)e(to)g(reserv)m(e)g (space)f(for)g(k)m(eyw)m(ords)g(whic)m(h)g(are)g(to)h(b)s(e)e(written)h (at)g(a)h(later)g(time,)h(after)e(the)g(data)227 1247 y(unit)h(or)g(subsequen)m(t)f(extensions)h(ha)m(v)m(e)h(b)s(een)e (written)h(to)h(the)f(FITS)f(\014le.)58 b(If)35 b(this)h(subroutine)f (is)h(not)227 1360 y(explicitly)29 b(called,)g(then)e(the)g(initial)i (size)e(of)h(the)f(FITS)f(header)h(will)h(b)s(e)e(limited)i(to)g(the)f (space)h(a)m(v)-5 b(ailable)227 1473 y(at)24 b(the)g(time)g(that)g(the) g(\014rst)f(data)h(is)g(written)f(to)h(the)g(asso)s(ciated)h(data)f (unit.)38 b(FITSIO)22 b(has)i(the)f(abilit)m(y)i(to)227 1586 y(dynamically)g(add)e(more)h(space)h(to)g(the)f(header)g(if)g (needed,)h(ho)m(w)m(ev)m(er)g(it)g(is)f(more)g(e\016cien)m(t)h(to)g (preallo)s(cate)227 1699 y(the)31 b(required)e(space)i(if)g(the)f(size) h(is)g(kno)m(wn)f(in)g(adv)-5 b(ance.)382 1962 y Ff (FTHDEF\(unit,morekeys,)42 b(>)47 b(status\))0 2226 y Fi(2)81 b Fj(Return)23 b(the)i(n)m(um)m(b)s(er)e(of)h(existing)i(k)m (eyw)m(ords)e(in)h(the)f(CHU)g(\(NOT)h(including)f(the)g(END)h(k)m(eyw) m(ord)g(whic)m(h)f(is)227 2339 y(not)g(considered)f(a)g(real)h(k)m(eyw) m(ord\))g(and)f(the)g(remaining)h(space)f(a)m(v)-5 b(ailable)26 b(to)e(write)f(additional)i(k)m(eyw)m(ords)227 2452 y(in)39 b(the)h(CHU.)f(\(returns)f(KEYSADD)i(=)f(-1)h(if)f(the)g(header)g(has)g (not)h(y)m(et)g(b)s(een)e(closed\).)69 b(Note)40 b(that)227 2564 y(FITSIO)23 b(will)i(attempt)g(to)g(dynamically)g(add)e(space)i (for)f(more)g(k)m(eyw)m(ords)h(if)f(required)f(when)g(app)s(ending)227 2677 y(new)30 b(k)m(eyw)m(ords)h(to)g(a)g(header.)382 2941 y Ff(FTGHSP\(iunit,)44 b(>)j(keysexist,keysadd,status\))0 3204 y Fi(3)81 b Fj(Return)38 b(the)i(n)m(um)m(b)s(er)e(of)h(k)m(eyw)m (ords)h(in)f(the)g(header)g(and)g(the)g(curren)m(t)h(p)s(osition)f(in)g (the)g(header.)68 b(This)227 3317 y(returns)37 b(the)g(n)m(um)m(b)s(er) f(of)i(the)g(k)m(eyw)m(ord)g(record)f(that)h(will)g(b)s(e)f(read)g (next)h(\(or)g(one)g(greater)g(than)g(the)227 3430 y(p)s(osition)29 b(of)f(the)h(last)g(k)m(eyw)m(ord)g(that)g(w)m(as)f(read)g(or)h (written\).)40 b(A)29 b(v)-5 b(alue)28 b(of)h(1)g(is)f(returned)f(if)h (the)h(p)s(oin)m(ter)227 3543 y(is)i(p)s(ositioned)f(at)h(the)g(b)s (eginning)e(of)i(the)g(header.)382 3807 y Ff(FTGHPS\(iunit,)44 b(>)j(keysexist,key_no,status\))0 4102 y Fc(6.4.2)112 b(Read)38 b(or)f(W)-9 b(rite)37 b(Standard)i(Header)e(Routines)0 4321 y Fj(These)31 b(subroutines)e(pro)m(vide)i(a)g(simple)g(metho)s(d) f(of)h(reading)g(or)g(writing)g(most)g(of)g(the)g(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(that)0 4434 y(are)d(normally)g(required)f(in)h(a)g(FITS)f (\014les.)40 b(These)27 b(subroutines)g(are)h(pro)m(vided)f(for)h(con)m (v)m(enience)h(only)f(and)g(are)0 4547 y(not)36 b(required)e(to)i(b)s (e)f(used.)55 b(If)35 b(preferred,)h(users)e(ma)m(y)i(call)h(the)f(lo)m (w)m(er-lev)m(el)i(subroutines)c(describ)s(ed)h(in)g(the)0 4660 y(previous)30 b(section)i(to)g(individually)f(read)f(or)h(write)g (the)g(required)f(k)m(eyw)m(ords.)43 b(Note)32 b(that)g(in)e(most)i (cases,)g(the)0 4773 y(required)26 b(k)m(eyw)m(ords)h(suc)m(h)g(as)g (NAXIS,)f(TFIELD,)h(TTYPEn,)g(etc,)i(whic)m(h)d(de\014ne)g(the)h (structure)f(of)h(the)g(HDU)0 4886 y(m)m(ust)j(b)s(e)g(written)g(to)i (the)e(header)g(b)s(efore)g(an)m(y)h(data)g(can)g(b)s(e)e(written)i(to) g(the)g(image)g(or)g(table.)0 5149 y Fi(1)81 b Fj(Put)37 b(the)i(primary)e(header)h(or)g(IMA)m(GE)h(extension)f(k)m(eyw)m(ords)h (in)m(to)g(the)f(CHU.)g(There)g(are)g(2)h(a)m(v)-5 b(ailable)227 5262 y(routines:)39 b(The)27 b(simpler)f(FTPHPS)h(routine)g(is)g(equiv) -5 b(alen)m(t)29 b(to)e(calling)i(ftphpr)c(with)i(the)g(default)h(v)-5 b(alues)227 5375 y(of)35 b(SIMPLE)f(=)g(true,)i(p)s(coun)m(t)e(=)g(0,)i (gcoun)m(t)g(=)e(1,)i(and)e(EXTEND)h(=)f(true.)53 b(PCOUNT,)34 b(GCOUNT)227 5488 y(and)23 b(EXTEND)h(k)m(eyw)m(ords)g(are)h(not)f (required)f(in)g(the)h(primary)f(header)g(and)h(are)g(only)g(written)g (if)f(p)s(coun)m(t)227 5601 y(is)31 b(not)g(equal)h(to)g(zero,)g(gcoun) m(t)g(is)f(not)g(equal)g(to)h(zero)g(or)f(one,)g(and)g(if)g(extend)g (is)g(TR)m(UE,)g(resp)s(ectiv)m(ely)-8 b(.)227 5714 y(When)30 b(writing)h(to)g(an)f(IMA)m(GE)i(extension,)f(the)f(SIMPLE)g(and)g (EXTEND)g(parameters)h(are)g(ignored.)p eop end %%Page: 44 50 TeXDict begin 44 49 bop 0 299 a Fj(44)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTPHPS\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 781 y(FTPHPR\(unit,simple,bitpi)o(x,n)o(axis)o (,nax)o(es,)o(pcou)o(nt,g)o(cou)o(nt,e)o(xten)o(d,)41 b(>)48 b(status\))0 1082 y Fi(2)81 b Fj(Get)44 b(primary)e(header)h(or) h(IMA)m(GE)g(extension)g(k)m(eyw)m(ords)g(from)f(the)g(CHU.)h(When)f (reading)g(from)g(an)227 1195 y(IMA)m(GE)32 b(extension)f(the)f(SIMPLE) g(and)f(EXTEND)i(parameters)g(are)f(ignored.)382 1497 y Ff(FTGHPR\(unit,maxdim,)42 b(>)48 b(simple,bitpix,naxis,naxe)o(s,p)o (coun)o(t,gc)o(oun)o(t,ex)o(tend)o(,)716 1610 y(status\))0 1911 y Fi(3)81 b Fj(Put)34 b(the)h(ASCI)s(I)f(table)i(header)f(k)m(eyw) m(ords)g(in)m(to)h(the)f(CHU.)h(The)e(optional)i(TUNITn)e(and)h (EXTNAME)227 2024 y(k)m(eyw)m(ords)c(are)g(written)f(only)h(if)f(the)h (input)e(string)h(v)-5 b(alues)31 b(are)g(not)f(blank.)382 2325 y Ff(FTPHTB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o (ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 2438 y(status\))0 2739 y Fi(4)81 b Fj(Get)31 b(the)g(ASCI)s(I)d(table)k (header)e(k)m(eyw)m(ords)h(from)e(the)i(CHU)382 3041 y Ff(FTGHTB\(unit,maxdim,)42 b(>)48 b(rowlen,nrows,tfields,tty)o(pe,)o (tbco)o(l,tf)o(orm)o(,tun)o(it,)716 3154 y(extname,status\))0 3455 y Fi(5)81 b Fj(Put)34 b(the)h(binary)f(table)i(header)e(k)m(eyw)m (ords)i(in)m(to)f(the)g(CHU.)g(The)g(optional)h(TUNITn)e(and)g(EXTNAME) 227 3568 y(k)m(eyw)m(ords)i(are)g(written)f(only)g(if)h(the)f(input)f (string)i(v)-5 b(alues)35 b(are)h(not)f(blank.)55 b(The)35 b(p)s(coun)m(t)g(parameter,)227 3681 y(whic)m(h)f(sp)s(eci\014es)g(the) h(size)g(of)g(the)f(v)-5 b(ariable)35 b(length)g(arra)m(y)g(heap,)g (should)f(initially)h(=)f(0;)j(FITSIO)d(will)227 3794 y(automatically)27 b(up)s(date)c(the)h(PCOUNT)f(k)m(eyw)m(ord)h(v)-5 b(alue)24 b(if)g(an)m(y)g(v)-5 b(ariable)25 b(length)f(arra)m(y)h(data) f(is)g(written)227 3907 y(to)31 b(the)e(heap.)41 b(The)29 b(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(for)g(v)-5 b(ariable)30 b(length)g(v)m(ector)h(columns)e(should)g(ha)m(v)m(e)i (the)227 4019 y(form)c('Pt\(len\)')j(or)d('1Pt\(len\)')j(where)d(`t')h (is)g(the)g(data)g(t)m(yp)s(e)g(co)s(de)f(letter)i(\(A,I,J,E,D,)g (etc.\))42 b(and)27 b(`len')h(is)227 4132 y(an)g(in)m(teger)i(sp)s (ecifying)e(the)g(maxim)m(um)g(length)g(of)h(the)f(v)m(ectors)h(in)f (that)h(column)f(\(len)g(m)m(ust)g(b)s(e)g(greater)227 4245 y(than)j(or)h(equal)f(to)i(the)e(longest)i(v)m(ector)f(in)f(the)h (column\).)44 b(If)30 b(`len')i(is)g(not)f(sp)s(eci\014ed)g(when)f(the) i(table)g(is)227 4358 y(created)27 b(\(e.g.,)i(the)d(input)f(TF)m(ORMn) h(v)-5 b(alue)26 b(is)g(just)f('1Pt'\))j(then)d(FITSIO)g(will)h(scan)g (the)g(column)g(when)227 4471 y(the)k(table)g(is)f(\014rst)g(closed)h (and)f(will)g(app)s(end)f(the)h(maxim)m(um)h(length)f(to)h(the)g(TF)m (ORM)f(k)m(eyw)m(ord)h(v)-5 b(alue.)227 4584 y(Note)28 b(that)e(if)g(the)g(table)h(is)f(subsequen)m(tly)g(mo)s(di\014ed)f(to)i (increase)f(the)h(maxim)m(um)f(length)g(of)g(the)g(v)m(ectors)227 4697 y(then)k(the)h(mo)s(difying)f(program)g(is)g(resp)s(onsible)g(for) g(also)h(up)s(dating)e(the)i(TF)m(ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue.)382 4998 y Ff(FTPHBN\(unit,nrows,tfield)o(s,t)o(type)o(,tfo)o (rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at,)41 b(>)48 b(status\))0 5300 y Fi(6)81 b Fj(Get)31 b(the)g(binary)e(table)i (header)g(k)m(eyw)m(ords)f(from)g(the)h(CHU)382 5601 y Ff(FTGHBN\(unit,maxdim,)42 b(>)48 b(nrows,tfields,ttype,tfor)o(m,t)o (unit)o(,ext)o(nam)o(e,va)o(rida)o(t,)716 5714 y(status\))p eop end %%Page: 45 51 TeXDict begin 45 50 bop 0 299 a Fh(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fj(45)0 555 y Fc(6.4.3)112 b(W)-9 b(rite)37 b(Keyw)m(ord)g(Subroutines)0 764 y Fi(1)81 b Fj(Put)30 b(\(app)s(end\))f(an)h(80-c)m(haracter)j (record)e(in)m(to)g(the)g(CHU.)382 1022 y Ff(FTPREC\(unit,card,)43 b(>)k(status\))0 1280 y Fi(2)81 b Fj(Put)36 b(\(app)s(end\))g(a)i (COMMENT)f(k)m(eyw)m(ord)g(in)m(to)h(the)g(CHU.)f(Multiple)h(COMMENT)f (k)m(eyw)m(ords)g(will)h(b)s(e)227 1393 y(written)31 b(if)f(the)h(input)e(commen)m(t)i(string)g(is)f(longer)h(than)f(72)i(c) m(haracters.)382 1650 y Ff(FTPCOM\(unit,comment,)42 b(>)48 b(status\))0 1908 y Fi(3)81 b Fj(Put)24 b(\(app)s(end\))g(a)h(HISTOR)-8 b(Y)25 b(k)m(eyw)m(ord)g(in)m(to)h(the)f(CHU.)g(Multiple)h(HISTOR)-8 b(Y)24 b(k)m(eyw)m(ords)h(will)h(b)s(e)e(written)227 2021 y(if)31 b(the)f(input)g(history)g(string)g(is)h(longer)g(than)f (72)h(c)m(haracters.)382 2279 y Ff(FTPHIS\(unit,history,)42 b(>)48 b(status\))0 2537 y Fi(4)81 b Fj(Put)36 b(\(app)s(end\))f(the)h (D)m(A)-8 b(TE)38 b(k)m(eyw)m(ord)f(in)m(to)g(the)f(CHU.)h(The)f(k)m (eyw)m(ord)g(v)-5 b(alue)37 b(will)g(con)m(tain)h(the)e(curren)m(t)227 2650 y(system)c(date)g(as)g(a)f(c)m(haracter)i(string)f(in)f ('dd/mm/yy')g(format.)44 b(If)31 b(a)h(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(already)g(exists)227 2763 y(in)j(the)g(header,)i (then)d(this)h(subroutine)f(will)i(simply)e(up)s(date)h(the)g(k)m(eyw)m (ord)g(v)-5 b(alue)36 b(in-place)g(with)f(the)227 2876 y(curren)m(t)30 b(date.)382 3134 y Ff(FTPDAT\(unit,)44 b(>)k(status\))0 3392 y Fi(5)81 b Fj(Put)22 b(\(app)s(end\))f(a)i(new)f (k)m(eyw)m(ord)h(of)g(the)f(appropriate)h(datat)m(yp)s(e)g(in)m(to)h (the)e(CHU.)h(Note)h(that)f(FTPKYS)f(will)227 3504 y(only)33 b(write)g(string)f(v)-5 b(alues)33 b(up)e(to)j(68)f(c)m(haracters)h(in) e(length;)i(longer)f(strings)g(will)f(b)s(e)g(truncated.)47 b(The)227 3617 y(FTPKLS)27 b(routine)h(can)h(b)s(e)f(used)f(to)i(write) f(longer)h(strings,)g(using)e(a)i(non-standard)e(FITS)h(con)m(v)m(en)m (tion.)227 3730 y(The)23 b(E)h(and)f(D)h(v)m(ersions)g(of)g(this)f (routine)h(ha)m(v)m(e)h(the)f(added)f(feature)h(that)g(if)g(the)g ('decimals')h(parameter)f(is)227 3843 y(negativ)m(e,)i(then)20 b(the)i('G')g(displa)m(y)f(format)g(rather)g(then)g(the)g('E')h(format) f(will)h(b)s(e)e(used)g(when)g(constructing)227 3956 y(the)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)26 b(taking)f(the)g(absolute)g (v)-5 b(alue)24 b(of)h('decimals')g(for)f(the)g(precision.)39 b(This)23 b(will)i(suppress)227 4069 y(trailing)35 b(zeros,)h(and)d (will)i(use)e(a)i(\014xed)e(format)h(rather)g(than)f(an)h(exp)s(onen)m (tial)h(format,)h(dep)s(ending)c(on)227 4182 y(the)f(magnitude)f(of)h (the)f(v)-5 b(alue.)382 4440 y Ff(FTPKY[JKLS]\(unit,keyword)o(,ke)o (yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 4553 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))0 4811 y Fi(6)81 b Fj(Put)33 b(\(app)s(end\))h(a)g(string)g(v)-5 b(alued)34 b(k)m(eyw)m(ord)h(in)m (to)g(the)g(CHU)f(whic)m(h)g(ma)m(y)g(b)s(e)g(longer)h(than)e(68)i(c)m (haracters)227 4924 y(in)j(length.)64 b(This)37 b(uses)h(the)g(Long)g (String)g(Keyw)m(ord)g(con)m(v)m(en)m(tion)i(that)e(is)g(describ)s(ed)f (in)h(the)g("Usage)227 5036 y(Guidelines)33 b(and)e(Suggestions")j (section)f(of)g(this)f(do)s(cumen)m(t.)46 b(Since)33 b(this)f(uses)g(a)g(non-standard)g(FITS)227 5149 y(con)m(v)m(en)m(tion) 38 b(to)d(enco)s(de)h(the)f(long)h(k)m(eyw)m(ord)f(string,)i(programs)d (whic)m(h)h(use)g(this)g(routine)g(should)f(also)227 5262 y(call)e(the)e(FTPLSW)g(routine)h(to)g(add)e(some)i(COMMENT)f(k)m (eyw)m(ords)h(to)g(w)m(arn)f(users)f(of)i(the)f(FITS)g(\014le)227 5375 y(that)36 b(this)f(con)m(v)m(en)m(tion)j(is)d(b)s(eing)g(used.)55 b(FTPLSW)35 b(also)h(writes)g(a)f(k)m(eyw)m(ord)h(called)h(LONGSTRN)d (to)227 5488 y(record)c(the)h(v)m(ersion)f(of)h(the)f(longstring)h(con) m(v)m(en)m(tion)h(that)f(has)f(b)s(een)g(used,)f(in)h(case)h(a)g(new)f (con)m(v)m(en)m(tion)227 5601 y(is)f(adopted)g(at)g(some)g(p)s(oin)m(t) f(in)h(the)f(future.)40 b(If)28 b(the)g(LONGSTRN)g(k)m(eyw)m(ord)h(is)g (already)g(presen)m(t)f(in)h(the)227 5714 y(header,)i(then)f(FTPLSW)g (will)g(simply)g(return)g(and)f(will)i(not)g(write)f(duplicate)h(k)m (eyw)m(ords.)p eop end %%Page: 46 52 TeXDict begin 46 51 bop 0 299 a Fj(46)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTPKLS\(unit,keyword,keyv)o(al,)o(comm)o (ent,)41 b(>)47 b(status\))382 668 y(FTPLSW\(unit,)d(>)k(status\))0 891 y Fi(7)81 b Fj(Put)30 b(\(app)s(end\))g(a)h(new)f(k)m(eyw)m(ord)h (with)f(an)h(unde\014ned,)e(or)h(n)m(ull,)h(v)-5 b(alue)31 b(in)m(to)h(the)f(CHU.)g(The)f(v)-5 b(alue)31 b(string)227 1004 y(of)g(the)f(k)m(eyw)m(ord)h(is)g(left)g(blank)f(in)g(this)g (case.)382 1227 y Ff(FTPKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 1450 y Fi(8)81 b Fj(Put)41 b(\(app)s(end\))g(a)i(n) m(um)m(b)s(ered)d(sequence)j(of)f(k)m(eyw)m(ords)g(in)m(to)h(the)g (CHU.)f(One)f(ma)m(y)i(app)s(end)d(the)j(same)227 1563 y(commen)m(t)37 b(to)g(ev)m(ery)g(k)m(eyw)m(ord)g(\(and)f(eliminate)h (the)g(need)f(to)h(ha)m(v)m(e)g(an)f(arra)m(y)h(of)f(iden)m(tical)i (commen)m(t)227 1676 y(strings,)g(one)e(for)g(eac)m(h)h(k)m(eyw)m (ord\))g(b)m(y)f(including)g(the)g(amp)s(ersand)e(c)m(haracter)k(as)e (the)h(last)g(non-blank)227 1788 y(c)m(haracter)g(in)e(the)h (\(\014rst\))f(COMMENTS)f(string)h(parameter.)56 b(This)35 b(same)g(string)h(will)f(then)g(b)s(e)g(used)227 1901 y(for)30 b(the)g(commen)m(t)h(\014eld)f(in)f(all)i(the)f(k)m(eyw)m (ords.)41 b(\(Note)32 b(that)e(the)g(SPP)f(v)m(ersion)i(of)f(these)g (routines)g(only)227 2014 y(supp)s(orts)f(a)i(single)g(commen)m(t)g (string\).)382 2237 y Ff(FTPKN[JKLS]\(unit,keyroot)o(,st)o(artn)o(o,no) o(_ke)o(ys,k)o(eyva)o(ls,)o(comm)o(ents)o(,)42 b(>)47 b(status\))382 2350 y(FTPKN[EDFG]\(unit,keyroot)o(,st)o(artn)o(o,no)o (_ke)o(ys,k)o(eyva)o(ls,)o(deci)o(mals)o(,co)o(mmen)o(ts,)41 b(>)907 2463 y(status\))0 2686 y Fi(9)81 b Fj(Cop)m(y)21 b(an)h(indexed)f(k)m(eyw)m(ord)i(from)e(one)h(HDU)h(to)f(another,)i(mo) s(difying)e(the)g(index)f(n)m(um)m(b)s(er)f(of)i(the)g(k)m(eyw)m(ord) 227 2799 y(name)37 b(in)f(the)g(pro)s(cess.)58 b(F)-8 b(or)37 b(example,)i(this)d(routine)h(could)f(read)g(the)h(TLMIN3)f(k)m (eyw)m(ord)h(from)f(the)227 2912 y(input)28 b(HDU)h(\(b)m(y)f(giving)h (k)m(eyro)s(ot)h(=)d("TLMIN")i(and)f(inn)m(um)f(=)h(3\))h(and)f(write)g (it)h(to)g(the)f(output)g(HDU)227 3025 y(with)36 b(the)g(k)m(eyw)m(ord) h(name)f(TLMIN4)g(\(b)m(y)g(setting)i(outn)m(um)d(=)h(4\).)58 b(If)36 b(the)g(input)f(k)m(eyw)m(ord)i(do)s(es)f(not)227 3137 y(exist,)c(then)e(this)g(routine)g(simply)g(returns)f(without)i (indicating)g(an)f(error.)382 3360 y Ff(FTCPKY\(inunit,)44 b(outunit,)h(innum,)h(outnum,)g(keyroot,)g(>)h(status\))0 3583 y Fi(10)f Fj(Put)33 b(\(app)s(end\))f(a)h('triple)h(precision')g (k)m(eyw)m(ord)f(in)m(to)h(the)g(CHU)f(in)g(F28.16)i(format.)49 b(The)33 b(\015oating)h(p)s(oin)m(t)227 3696 y(k)m(eyw)m(ord)c(v)-5 b(alue)30 b(is)f(constructed)h(b)m(y)f(concatenating)j(the)d(input)g (in)m(teger)i(v)-5 b(alue)29 b(with)g(the)h(input)e(double)227 3809 y(precision)22 b(fraction)h(v)-5 b(alue)23 b(\(whic)m(h)f(m)m(ust) g(ha)m(v)m(e)h(a)f(v)-5 b(alue)23 b(b)s(et)m(w)m(een)g(0.0)g(and)e (1.0\).)40 b(The)21 b(FTGKYT)h(routine)227 3922 y(should)35 b(b)s(e)h(used)f(to)i(read)f(this)f(k)m(eyw)m(ord)i(v)-5 b(alue,)38 b(b)s(ecause)e(the)g(other)h(k)m(eyw)m(ord)f(reading)g (subroutines)227 4035 y(will)31 b(not)g(preserv)m(e)f(the)h(full)f (precision)g(of)h(the)f(v)-5 b(alue.)382 4258 y Ff (FTPKYT\(unit,keyword,intv)o(al,)o(dblv)o(al,c)o(omm)o(ent,)41 b(>)48 b(status\))0 4481 y Fi(11)e Fj(W)-8 b(rite)36 b(k)m(eyw)m(ords)g(to)f(the)h(CHDU)f(that)h(are)f(de\014ned)f(in)g(an)h (ASCI)s(I)f(template)i(\014le.)55 b(The)34 b(format)i(of)f(the)227 4594 y(template)d(\014le)f(is)f(describ)s(ed)f(under)g(the)i(ftgthd)f (routine)g(b)s(elo)m(w.)382 4816 y Ff(FTPKTP\(unit,)44 b(filename,)i(>)h(status\))0 5039 y Fi(12)f Fj(App)s(end)28 b(the)i(ph)m(ysical)g(units)g(string)g(to)g(an)g(existing)h(k)m(eyw)m (ord.)41 b(This)29 b(routine)h(uses)f(a)h(lo)s(cal)i(con)m(v)m(en)m (tion,)227 5152 y(sho)m(wn)g(in)g(the)h(follo)m(wing)h(example,)g(in)e (whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)f(square) g(brac)m(k)m(ets)227 5265 y(in)e(the)h(b)s(eginning)f(of)g(the)h(k)m (eyw)m(ord)g(commen)m(t)g(\014eld.)239 5488 y Ff(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)382 5714 y (FTPUNT\(unit,keyword,unit)o(s,)41 b(>)48 b(status\))p eop end %%Page: 47 53 TeXDict begin 47 52 bop 0 299 a Fh(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fj(47)0 555 y Fc(6.4.4)112 b(Insert)38 b(Keyw)m(ord)f(Subroutines)0 763 y Fi(1)81 b Fj(Insert)26 b(a)h(new)f(k)m(eyw)m(ord)h(record)g(in)m (to)g(the)g(CHU)g(at)g(the)g(sp)s(eci\014ed)f(p)s(osition)h(\(i.e.,)i (immediately)f(preceding)227 876 y(the)34 b(\(k)m(eyno\)th)g(k)m(eyw)m (ord)g(in)f(the)h(header.\))49 b(This)33 b('insert)g(record')h (subroutine)e(is)h(somewhat)h(less)g(e\016-)227 989 y(cien)m(t)28 b(then)f(the)g('app)s(end)e(record')i(subroutine)f(\(FTPREC\))g (describ)s(ed)g(ab)s(o)m(v)m(e)i(b)s(ecause)f(the)g(remaining)227 1101 y(k)m(eyw)m(ords)k(in)f(the)h(header)f(ha)m(v)m(e)h(to)g(b)s(e)f (shifted)g(do)m(wn)g(one)h(slot.)382 1353 y Ff (FTIREC\(unit,key_no,card,)41 b(>)47 b(status\))0 1604 y Fi(2)81 b Fj(Insert)36 b(a)h(new)f(k)m(eyw)m(ord)i(in)m(to)g(the)f (CHU.)g(The)f(new)g(k)m(eyw)m(ord)i(is)f(inserted)f(immediately)i (follo)m(wing)h(the)227 1717 y(last)27 b(k)m(eyw)m(ord)g(that)f(has)g (b)s(een)g(read)g(from)f(the)h(header.)40 b(The)25 b(FTIKLS)g (subroutine)g(w)m(orks)h(the)g(same)h(as)227 1830 y(the)h(FTIKYS)e (subroutine,)h(except)i(it)f(also)g(supp)s(orts)e(long)i(string)f(v)-5 b(alues)28 b(greater)g(than)f(68)h(c)m(haracters)227 1943 y(in)36 b(length.)59 b(These)36 b('insert)g(k)m(eyw)m(ord')h (subroutines)e(are)i(somewhat)g(less)f(e\016cien)m(t)i(then)e(the)g ('app)s(end)227 2056 y(k)m(eyw)m(ord')30 b(subroutines)e(describ)s(ed)g (ab)s(o)m(v)m(e)i(b)s(ecause)f(the)g(remaining)h(k)m(eyw)m(ords)f(in)g (the)g(header)g(ha)m(v)m(e)h(to)227 2168 y(b)s(e)g(shifted)g(do)m(wn)g (one)h(slot.)382 2420 y Ff(FTIKEY\(unit,)44 b(card,)j(>)g(status\))382 2533 y(FTIKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 2645 y(FTIKLS\(unit,keyword,keyv)o(al,)o(comm)o (ent,)41 b(>)47 b(status\))382 2758 y(FTIKY[EDFG]\(unit,keyword)o(,ke)o (yval)o(,dec)o(ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))0 3010 y Fi(3)81 b Fj(Insert)32 b(a)i(new)f(k)m(eyw)m(ord)h(with)f(an)h (unde\014ned,)e(or)h(n)m(ull,)h(v)-5 b(alue)34 b(in)m(to)h(the)e(CHU.)h (The)f(v)-5 b(alue)34 b(string)f(of)h(the)227 3123 y(k)m(eyw)m(ord)d (is)g(left)g(blank)f(in)g(this)g(case.)382 3374 y Ff (FTIKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 3663 y Fc(6.4.5)112 b(Read)38 b(Keyw)m(ord)g(Subroutines)0 3882 y Fj(These)29 b(routines)f(return)g(the)h(v)-5 b(alue)29 b(of)g(the)g(sp)s(eci\014ed)f(k)m(eyw)m(ord\(s\).)41 b(Wild)30 b(card)e(c)m(haracters)i(\(*,)h(?,)e(or)g(#\))f(ma)m(y)0 3995 y(b)s(e)f(used)h(when)f(sp)s(ecifying)h(the)g(name)g(of)g(the)g(k) m(eyw)m(ord)h(to)g(b)s(e)e(read:)39 b(a)29 b(')10 b(?')40 b(will)28 b(matc)m(h)h(an)m(y)g(single)f(c)m(haracter)0 4108 y(at)38 b(that)g(p)s(osition)f(in)g(the)h(k)m(eyw)m(ord)g(name)f (and)g(a)g('*')i(will)e(matc)m(h)h(an)m(y)g(length)g(\(including)f (zero\))h(string)g(of)0 4221 y(c)m(haracters.)65 b(The)37 b('#')h(c)m(haracter)h(will)f(matc)m(h)h(an)m(y)f(consecutiv)m(e)i (string)e(of)g(decimal)h(digits)f(\(0)h(-)f(9\).)64 b(Note)0 4334 y(that)30 b(when)f(a)g(wild)g(card)h(is)f(used)g(in)g(the)h(input) e(k)m(eyw)m(ord)i(name,)g(the)g(routine)f(will)h(only)g(searc)m(h)g (for)f(a)h(matc)m(h)0 4446 y(from)h(the)h(curren)m(t)g(header)g(p)s (osition)g(to)g(the)h(end)e(of)h(the)g(header.)45 b(It)32 b(will)g(not)g(resume)g(the)g(searc)m(h)g(from)g(the)0 4559 y(top)i(of)h(the)f(header)g(bac)m(k)h(to)g(the)f(original)h (header)f(p)s(osition)g(as)h(is)f(done)g(when)f(no)h(wildcards)f(are)i (included)0 4672 y(in)f(the)g(k)m(eyw)m(ord)h(name.)52 b(If)33 b(the)h(desired)g(k)m(eyw)m(ord)h(string)f(is)g(8-c)m (haracters)i(long)f(\(the)f(maxim)m(um)g(length)h(of)0 4785 y(a)h(k)m(eyw)m(ord)g(name\))g(then)g(a)g('*')g(ma)m(y)h(b)s(e)e (app)s(ended)f(as)h(the)h(nin)m(th)g(c)m(haracter)h(of)f(the)f(input)g (name)h(to)g(force)0 4898 y(the)31 b(k)m(eyw)m(ord)g(searc)m(h)h(to)f (stop)g(at)g(the)g(end)f(of)h(the)g(header)g(\(e.g.,)i('COMMENT)d(*')i (will)f(searc)m(h)g(for)g(the)g(next)0 5011 y(COMMENT)37 b(k)m(eyw)m(ord\).)64 b(The)37 b(\013grec)i(routine)f(ma)m(y)g(b)s(e)f (used)g(to)i(set)f(the)g(starting)g(p)s(osition)g(when)f(doing)0 5124 y(wild)30 b(card)g(searc)m(hes.)0 5375 y Fi(1)81 b Fj(Get)37 b(the)f(n)m(th)f(80-c)m(haracter)k(header)d(record)g(from)f (the)h(CHU.)h(The)e(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g (at)227 5488 y(k)m(ey)p 365 5488 28 4 v 34 w(no)42 b(=)f(1;)49 b(if)42 b(k)m(ey)p 996 5488 V 34 w(no)g(=)f(0)i(then)e(this)h (subroutine)f(simple)h(mo)m(v)m(es)i(the)e(in)m(ternal)h(p)s(oin)m(ter) f(to)h(the)227 5601 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g (subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g(at)g (the)g(top)g(of)g(the)227 5714 y(header;)31 b(it)g(also)g(returns)e(a)i (blank)f(card)g(v)-5 b(alue)31 b(in)f(this)g(case.)p eop end %%Page: 48 54 TeXDict begin 48 53 bop 0 299 a Fj(48)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))0 797 y Fi(2)81 b Fj(Get)31 b(the)g(name,)f(v)-5 b(alue)31 b(\(as)g(a)g(string\),)g(and)f(commen)m(t)i(of)e(the)h(n)m (th)f(k)m(eyw)m(ord)h(in)f(CHU.)h(This)f(routine)g(also)227 910 y(c)m(hec)m(ks)h(that)f(the)g(returned)e(k)m(eyw)m(ord)i(name)f (\(KEYW)m(ORD\))i(con)m(tains)g(only)e(legal)i(ASCI)s(I)d(c)m (haracters.)227 1023 y(Call)j(FTGREC)f(and)g(FTPSV)m(C)g(to)h(b)m (ypass)f(this)g(error)g(c)m(hec)m(k.)382 1264 y Ff (FTGKYN\(unit,key_no,)42 b(>)48 b(keyword,value,comment,st)o(atu)o(s\)) 0 1506 y Fi(3)81 b Fj(Get)31 b(the)g(80-c)m(haracter)i(header)d(record) g(for)g(the)h(named)f(k)m(eyw)m(ord)382 1748 y Ff (FTGCRD\(unit,keyword,)42 b(>)48 b(card,status\))0 1990 y Fi(4)81 b Fj(Get)26 b(the)f(next)h(k)m(eyw)m(ord)f(whose)g(name)h (matc)m(hes)g(one)f(of)h(the)f(strings)g(in)g('inclist')i(but)d(do)s (es)h(not)g(matc)m(h)i(an)m(y)227 2102 y(of)32 b(the)f(strings)g(in)g ('exclist'.)45 b(The)30 b(strings)h(in)g(inclist)h(and)f(exclist)h(ma)m (y)g(con)m(tain)h(wild)d(card)h(c)m(haracters)227 2215 y(\(*,)38 b(?,)e(and)e(#\))i(as)f(describ)s(ed)f(at)i(the)f(b)s (eginning)f(of)i(this)f(section.)56 b(This)34 b(routine)h(searc)m(hes)h (from)f(the)227 2328 y(curren)m(t)28 b(header)f(p)s(osition)h(to)g(the) g(end)f(of)h(the)g(header,)g(only)-8 b(,)29 b(and)e(do)s(es)g(not)h (con)m(tin)m(ue)h(the)f(searc)m(h)g(from)227 2441 y(the)41 b(top)g(of)g(the)g(header)g(bac)m(k)h(to)f(the)g(original)h(p)s (osition.)73 b(The)40 b(curren)m(t)h(header)f(p)s(osition)h(ma)m(y)h(b) s(e)227 2554 y(reset)33 b(with)e(the)h(ftgrec)h(routine.)44 b(Note)33 b(that)g(nexc)f(ma)m(y)g(b)s(e)f(set)h(=)g(0)g(if)f(there)h (are)g(no)g(k)m(eyw)m(ords)g(to)h(b)s(e)227 2667 y(excluded.)41 b(This)29 b(routine)i(returns)e(status)i(=)f(202)h(if)g(a)f(matc)m (hing)i(k)m(eyw)m(ord)f(is)f(not)h(found.)382 2909 y Ff(FTGNXK\(unit,inclist,ninc)o(,ex)o(clis)o(t,ne)o(xc,)41 b(>)48 b(card,status\))0 3150 y Fi(5)81 b Fj(Get)30 b(the)g(literal)i (k)m(eyw)m(ord)e(v)-5 b(alue)30 b(as)g(a)g(c)m(haracter)i(string.)40 b(Regardless)31 b(of)f(the)g(datat)m(yp)s(e)g(of)g(the)g(k)m(eyw)m (ord,)227 3263 y(this)37 b(routine)g(simply)g(returns)f(the)h(string)g (of)g(c)m(haracters)i(in)d(the)i(v)-5 b(alue)37 b(\014eld)g(of)g(the)g (k)m(eyw)m(ord)h(along)227 3376 y(with)30 b(the)h(commen)m(t)g (\014eld.)382 3618 y Ff(FTGKEY\(unit,keyword,)42 b(>)48 b(value,comment,status\))0 3860 y Fi(6)81 b Fj(Get)31 b(a)g(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(\(with)h(the)f(appropriate)h (datat)m(yp)s(e\))g(and)f(commen)m(t)i(from)e(the)g(CHU)382 4101 y Ff(FTGKY[EDJKLS]\(unit,keywo)o(rd,)41 b(>)48 b (keyval,comment,status\))0 4343 y Fi(7)81 b Fj(Read)22 b(a)g(string-v)-5 b(alued)23 b(k)m(eyw)m(ord)f(and)g(return)e(the)j (string)f(length,)i(the)e(v)-5 b(alue)23 b(string,)h(and/or)e(the)g (commen)m(t)227 4456 y(\014eld.)47 b(The)32 b(\014rst)g(routine,)h (FTGKSL,)f(simply)g(returns)f(the)i(length)g(of)g(the)f(c)m(haracter)i (string)f(v)-5 b(alue)33 b(of)227 4569 y(the)c(sp)s(eci\014ed)g(k)m (eyw)m(ord.)40 b(The)29 b(second)g(routine,)h(FTGSKY,)f(also)g(returns) f(up)g(to)i(maxc)m(har)f(c)m(haracters)227 4682 y(of)i(the)f(k)m(eyw)m (ord)h(v)-5 b(alue)31 b(string,)g(starting)g(with)f(the)g(\014rstc)m (har)g(c)m(haracter,)j(and)c(the)i(k)m(eyw)m(ord)g(commen)m(t)227 4795 y(string.)49 b(The)32 b(length)i(argumen)m(t)f(returns)f(the)h (total)i(length)e(of)h(the)f(k)m(eyw)m(ord)g(v)-5 b(alue)34 b(string)f(regardless)227 4908 y(of)i(ho)m(w)f(m)m(uc)m(h)g(of)g(the)h (string)f(is)g(actually)i(returned)d(\(whic)m(h)h(dep)s(ends)e(on)j (the)f(v)-5 b(alue)35 b(of)f(the)g(\014rstc)m(har)227 5021 y(and)c(maxc)m(har)h(argumen)m(ts\).)41 b(These)30 b(routines)h(supp)s(ort)d(string)j(k)m(eyw)m(ords)f(that)h(use)f(the)h (CONTINUE)227 5133 y(con)m(v)m(en)m(tion)25 b(to)e(con)m(tin)m(ue)g (long)g(string)f(v)-5 b(alues)23 b(o)m(v)m(er)h(m)m(ultiple)f(FITS)e (header)h(records.)38 b(Normally)-8 b(,)26 b(string-)227 5246 y(v)-5 b(alued)40 b(k)m(eyw)m(ords)h(ha)m(v)m(e)g(a)g(maxim)m(um)f (length)h(of)f(68)h(c)m(haracters,)k(ho)m(w)m(ev)m(er,)f(CONTINUE'd)39 b(string)227 5359 y(k)m(eyw)m(ords)31 b(ma)m(y)g(b)s(e)f(arbitrarily)g (long.)334 5601 y Ff(FTGKSL\(unit,keyword,)42 b(>)48 b(length,status\))334 5714 y(FTGSKY\(unit,keyword,first)o(cha)o(r,ma)o (xcha)o(r,>)41 b(keyval,length,comment,sta)o(tus\))p eop end %%Page: 49 55 TeXDict begin 49 54 bop 0 299 a Fh(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fj(49)0 555 y Fi(8)81 b Fj(Get)24 b(a)g(sequence)g(of)g(n)m(um)m(b)s(ered)e(k)m(eyw)m (ord)i(v)-5 b(alues.)38 b(These)24 b(routines)f(do)g(not)h(supp)s(ort)e (wild)h(card)g(c)m(haracters)227 668 y(in)30 b(the)h(ro)s(ot)g(name.) 382 930 y Ff(FTGKN[EDJKLS]\(unit,keyro)o(ot,)o(star)o(tno,)o(max)o (_key)o(s,)42 b(>)47 b(keyvals,nfound,status\))0 1192 y Fi(9)81 b Fj(Get)27 b(the)f(v)-5 b(alue)26 b(of)h(a)f(\015oating)h(p) s(oin)m(t)f(k)m(eyw)m(ord,)i(returning)d(the)h(in)m(teger)h(and)f (fractional)h(parts)f(of)g(the)g(v)-5 b(alue)227 1305 y(in)32 b(separate)g(subroutine)f(argumen)m(ts.)45 b(This)31 b(subroutine)f(ma)m(y)j(b)s(e)e(used)g(to)h(read)g(an)m(y)g(k)m(eyw)m (ord)g(but)f(is)227 1418 y(esp)s(ecially)h(useful)d(for)i(reading)f (the)h('triple)g(precision')f(k)m(eyw)m(ords)h(written)g(b)m(y)f (FTPKYT.)382 1680 y Ff(FTGKYT\(unit,keyword,)42 b(>)48 b(intval,dblval,comment,s)o(tat)o(us\))0 1941 y Fi(10)e Fj(Get)c(the)e(ph)m(ysical)i(units)e(string)g(in)h(an)f(existing)i(k)m (eyw)m(ord.)72 b(This)40 b(routine)g(uses)h(a)g(lo)s(cal)h(con)m(v)m (en)m(tion,)227 2054 y(sho)m(wn)32 b(in)g(the)h(follo)m(wing)h (example,)g(in)e(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h (enclosed)g(in)f(square)g(brac)m(k)m(ets)227 2167 y(in)37 b(the)h(b)s(eginning)e(of)i(the)f(k)m(eyw)m(ord)h(commen)m(t)g (\014eld.)61 b(A)38 b(blank)f(string)g(is)g(returned)f(if)i(no)f(units) g(are)227 2280 y(de\014ned)29 b(for)i(the)f(k)m(eyw)m(ord.)191 2542 y Ff(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)382 2768 y(FTGUNT\(unit,keyword,)c(>)48 b(units,status\))0 3061 y Fc(6.4.6)112 b(Mo)s(dify)39 b(Keyw)m(ord)e(Subroutines)0 3280 y Fj(Wild)32 b(card)f(c)m(haracters,)j(as)e(describ)s(ed)e(in)h (the)h(Read)g(Keyw)m(ord)f(section,)i(ab)s(o)m(v)m(e,)g(ma)m(y)g(b)s(e) d(used)h(when)g(sp)s(eci-)0 3393 y(fying)f(the)h(name)f(of)h(the)f(k)m (eyw)m(ord)h(to)g(b)s(e)f(mo)s(di\014ed.)0 3655 y Fi(1)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i(the)f(n)m(th)f(80-c)m (haracter)j(header)d(record)h(in)f(the)g(CHU)382 3917 y Ff(FTMREC\(unit,key_no,card,)41 b(>)47 b(status\))0 4179 y Fi(2)81 b Fj(Mo)s(dify)37 b(\(o)m(v)m(erwrite\))j(the)e(80-c)m (haracter)j(header)c(record)h(for)f(the)h(named)f(k)m(eyw)m(ord)h(in)g (the)g(CHU.)g(This)227 4292 y(can)31 b(b)s(e)f(used)f(to)i(o)m(v)m (erwrite)h(the)f(name)f(of)h(the)f(k)m(eyw)m(ord)h(as)g(w)m(ell)g(as)g (its)g(v)-5 b(alue)30 b(and)g(commen)m(t)i(\014elds.)382 4554 y Ff(FTMCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))0 4815 y Fi(3)81 b Fj(Mo)s(dify)33 b(\(o)m(v)m(erwrite\))k(the)d(name)g (of)h(an)f(existing)h(k)m(eyw)m(ord)f(in)g(the)h(CHU)f(preserving)f (the)i(curren)m(t)e(v)-5 b(alue)227 4928 y(and)30 b(commen)m(t)h (\014elds.)382 5190 y Ff(FTMNAM\(unit,oldkey,keywo)o(rd,)41 b(>)48 b(status\))0 5452 y Fi(4)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i(the)f(commen)m(t)g(\014eld)f(of)h(an)f (existing)h(k)m(eyw)m(ord)g(in)f(the)h(CHU)382 5714 y Ff(FTMCOM\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))p eop end %%Page: 50 56 TeXDict begin 50 55 bop 0 299 a Fj(50)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(5)81 b Fj(Mo)s(dify)24 b(the)h(v)-5 b(alue)25 b(and)f(commen)m(t)i(\014elds)e(of)h(an)f(existing)i(k)m(eyw) m(ord)f(in)f(the)h(CHU.)g(The)f(FTMKLS)g(subrou-)227 668 y(tine)35 b(w)m(orks)e(the)h(same)h(as)f(the)g(FTMKYS)f (subroutine,)h(except)h(it)g(also)f(supp)s(orts)e(long)j(string)f(v)-5 b(alues)227 781 y(greater)38 b(than)f(68)h(c)m(haracters)g(in)f (length.)60 b(Optionally)-8 b(,)40 b(one)d(ma)m(y)h(mo)s(dify)e(only)h (the)g(v)-5 b(alue)37 b(\014eld)g(and)227 894 y(lea)m(v)m(e)32 b(the)d(commen)m(t)i(\014eld)e(unc)m(hanged)g(b)m(y)g(setting)h(the)g (input)e(COMMENT)h(parameter)h(equal)g(to)g(the)227 1007 y(amp)s(ersand)f(c)m(haracter)k(\(&\).)42 b(The)30 b(E)g(and)g(D)h(v)m (ersions)g(of)g(this)g(routine)f(ha)m(v)m(e)i(the)f(added)f(feature)h (that)227 1120 y(if)26 b(the)h('decimals')g(parameter)g(is)f(negativ)m (e,)k(then)c(the)g('G')h(displa)m(y)f(format)h(rather)f(then)g(the)g ('E')h(format)227 1233 y(will)i(b)s(e)f(used)f(when)h(constructing)h (the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)30 b(taking)f(the)g(absolute)g(v)-5 b(alue)29 b(of)f('decimals')i(for)227 1346 y(the)37 b(precision.)60 b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) g(\014xed)e(format)i(rather)g(than)f(an)227 1458 y(exp)s(onen)m(tial)c (format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 b(alue.)382 1689 y Ff(FTMKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o (men)o(t,)42 b(>)47 b(status\))382 1802 y(FTMKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 1915 y (FTMKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))0 2146 y Fi(6)81 b Fj(Mo)s(dify)22 b(the)g(v)-5 b(alue)23 b(of)f(an)g(existing)i(k)m(eyw)m(ord)e(to)h(b)s (e)f(unde\014ned,)g(or)g(n)m(ull.)38 b(The)22 b(v)-5 b(alue)22 b(string)h(of)f(the)g(k)m(eyw)m(ord)227 2259 y(is)30 b(set)h(to)g(blank.)40 b(Optionally)-8 b(,)31 b(one)f(ma)m(y)h(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)e(unc)m (hanged)h(b)m(y)g(setting)h(the)f(input)227 2372 y(COMMENT)g(parameter) h(equal)g(to)g(the)g(amp)s(ersand)e(c)m(haracter)j(\(&\).)382 2602 y Ff(FTMKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 2888 y Fc(6.4.7)112 b(Up)s(date)39 b(Keyw)m(ord)e (Subroutines)0 3092 y Fi(1)81 b Fj(Up)s(date)36 b(an)g(80-c)m(haracter) j(record)d(in)g(the)h(CHU.)f(If)g(the)g(sp)s(eci\014ed)g(k)m(eyw)m(ord) h(already)f(exists)h(then)f(that)227 3205 y(header)j(record)f(will)h(b) s(e)f(replaced)i(with)e(the)h(input)f(CARD)g(string.)66 b(If)38 b(it)i(do)s(es)e(not)h(exist)g(then)g(the)227 3318 y(new)f(record)g(will)g(b)s(e)f(added)h(to)g(the)g(header.)64 b(The)37 b(FTUKLS)g(subroutine)g(w)m(orks)h(the)g(same)h(as)f(the)227 3431 y(FTUKYS)28 b(subroutine,)g(except)i(it)f(also)h(supp)s(orts)c (long)j(string)g(v)-5 b(alues)29 b(greater)h(than)e(68)h(c)m(haracters) h(in)227 3544 y(length.)382 3775 y Ff(FTUCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))0 4006 y Fi(2)81 b Fj(Up)s(date)44 b(the)i(v)-5 b(alue)45 b(and)g(commen)m(t)h(\014elds)e(of)h(a)h(k)m (eyw)m(ord)f(in)g(the)g(CHU.)h(The)e(sp)s(eci\014ed)g(k)m(eyw)m(ord)i (is)227 4118 y(mo)s(di\014ed)38 b(if)g(it)h(already)g(exists)g(\(b)m(y) g(calling)h(FTMKYx\))f(otherwise)f(a)h(new)f(k)m(eyw)m(ord)h(is)g (created)g(b)m(y)227 4231 y(calling)f(FTPKYx.)58 b(The)36 b(E)g(and)f(D)i(v)m(ersions)f(of)h(this)f(routine)g(ha)m(v)m(e)h(the)g (added)e(feature)i(that)g(if)f(the)227 4344 y('decimals')c(parameter)g (is)f(negativ)m(e,)i(then)d(the)h('G')h(displa)m(y)f(format)g(rather)g (then)f(the)h('E')g(format)h(will)227 4457 y(b)s(e)41 b(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)45 b(taking)d(the)f(absolute)h(v)-5 b(alue)42 b(of)g('decimals')g(for)227 4570 y(the)37 b(precision.)60 b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) g(\014xed)e(format)i(rather)g(than)f(an)227 4683 y(exp)s(onen)m(tial)c (format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 b(alue.)382 4914 y Ff(FTUKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o (men)o(t,)42 b(>)47 b(status\))382 5027 y(FTUKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 5140 y (FTUKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))0 5370 y Fi(3)81 b Fj(Up)s(date)23 b(the)g(v)-5 b(alue)24 b(of)g(an)f(existing)i(k)m(eyw)m(ord)f(to)g(b)s (e)f(unde\014ned,)f(or)i(n)m(ull,)h(or)e(insert)h(a)f(new)g (unde\014ned-v)-5 b(alue)227 5483 y(k)m(eyw)m(ord)30 b(if)f(it)h(do)s(esn't)f(already)h(exist.)41 b(The)29 b(v)-5 b(alue)30 b(string)f(of)g(the)h(k)m(eyw)m(ord)f(is)h(left)g (blank)f(in)f(this)i(case.)382 5714 y Ff(FTUKYU\(unit,keyword,comm)o (ent)o(,)42 b(>)47 b(status\))p eop end %%Page: 51 57 TeXDict begin 51 56 bop 0 299 a Fh(6.5.)72 b(D)m(A)-8 b(T)g(A)32 b(SCALING)e(AND)h(UNDEFINED)h(PIXEL)e(P)-8 b(ARAMETERS)1083 b Fj(51)0 555 y Fc(6.4.8)112 b(Delete)38 b(Keyw)m(ord)f(Subroutines)0 764 y Fi(1)81 b Fj(Delete)32 b(an)e(existing)h(k)m(eyw)m(ord)g(record.)40 b(The)30 b(space)h(previously)f(o)s(ccupied)g(b)m(y)g(the)g(k)m(eyw)m(ord)h(is)f (reclaimed)227 877 y(b)m(y)c(mo)m(ving)h(all)g(the)f(follo)m(wing)i (header)e(records)g(up)f(one)h(ro)m(w)h(in)e(the)i(header.)39 b(The)25 b(\014rst)h(routine)g(deletes)227 990 y(a)34 b(k)m(eyw)m(ord)f(at)h(a)g(sp)s(eci\014ed)e(p)s(osition)h(in)g(the)g (header)g(\(the)h(\014rst)e(k)m(eyw)m(ord)i(is)f(at)h(p)s(osition)f (1\),)i(whereas)227 1103 y(the)d(second)g(routine)g(deletes)h(a)f(sp)s (eci\014cally)g(named)f(k)m(eyw)m(ord.)46 b(Wild)32 b(card)f(c)m (haracters,)j(as)e(describ)s(ed)227 1215 y(in)f(the)g(Read)g(Keyw)m (ord)f(section,)i(ab)s(o)m(v)m(e,)g(ma)m(y)g(b)s(e)e(used)g(when)f(sp)s (ecifying)i(the)g(name)g(of)g(the)f(k)m(eyw)m(ord)227 1328 y(to)h(b)s(e)f(deleted)h(\(b)s(e)f(careful!\).)382 1586 y Ff(FTDREC\(unit,key_no,)42 b(>)48 b(status\))382 1699 y(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 2032 y Fe(6.5)135 b(Data)46 b(Scaling)g(and)e(Unde\014ned)h(Pixel)h(P)l (arameters)0 2282 y Fj(These)24 b(subroutines)f(de\014ne)h(or)h(mo)s (dify)e(the)i(in)m(ternal)g(parameters)g(used)f(b)m(y)g(FITSIO)g(to)h (either)g(scale)h(the)e(data)0 2395 y(or)33 b(to)i(represen)m(t)e (unde\014ned)e(pixels.)50 b(Generally)35 b(FITSIO)d(will)i(scale)g(the) g(data)g(according)g(to)g(the)g(v)-5 b(alues)34 b(of)0 2508 y(the)e(BSCALE)g(and)f(BZER)m(O)h(\(or)h(TSCALn)d(and)i(TZER)m (On\))f(k)m(eyw)m(ords,)i(ho)m(w)m(ev)m(er)h(these)e(subroutines)f(ma)m (y)0 2621 y(b)s(e)h(used)h(to)h(o)m(v)m(erride)g(the)f(k)m(eyw)m(ord)h (v)-5 b(alues.)49 b(This)32 b(ma)m(y)i(b)s(e)f(useful)f(when)g(one)i(w) m(an)m(ts)f(to)h(read)f(or)g(write)h(the)0 2734 y(ra)m(w)c(unscaled)f (v)-5 b(alues)29 b(in)h(the)f(FITS)g(\014le.)40 b(Similarly)-8 b(,)31 b(FITSIO)d(generally)j(uses)e(the)g(v)-5 b(alue)30 b(of)g(the)f(BLANK)h(or)0 2847 y(TNULLn)35 b(k)m(eyw)m(ord)h(to)g (signify)f(an)h(unde\014ned)d(pixel,)k(but)e(these)h(routines)g(ma)m(y) g(b)s(e)e(used)h(to)h(o)m(v)m(erride)h(this)0 2959 y(v)-5 b(alue.)41 b(These)30 b(subroutines)f(do)i(not)f(create)i(or)f(mo)s (dify)e(the)i(corresp)s(onding)e(header)h(k)m(eyw)m(ord)h(v)-5 b(alues.)0 3217 y Fi(1)81 b Fj(Reset)26 b(the)g(scaling)g(factors)g(in) f(the)h(primary)f(arra)m(y)h(or)f(image)i(extension;)h(do)s(es)d(not)g (c)m(hange)i(the)f(BSCALE)227 3330 y(and)i(BZER)m(O)g(k)m(eyw)m(ord)h (v)-5 b(alues)28 b(and)g(only)g(a\013ects)i(the)e(automatic)j(scaling)e (p)s(erformed)e(when)g(the)h(data)227 3443 y(elemen)m(ts)f(are)f (written/read)g(to/from)g(the)g(FITS)f(\014le.)39 b(When)25 b(reading)h(from)f(a)h(FITS)f(\014le)g(the)h(returned)227 3556 y(data)i(v)-5 b(alue)28 b(=)f(\(the)h(v)-5 b(alue)28 b(giv)m(en)h(in)e(the)g(FITS)g(arra)m(y\))h(*)g(BSCALE)f(+)g(BZER)m(O.) g(The)g(in)m(v)m(erse)i(form)m(ula)227 3668 y(is)34 b(used)f(when)g (writing)h(data)h(v)-5 b(alues)34 b(to)g(the)g(FITS)g(\014le.)51 b(\(NOTE:)34 b(BSCALE)f(and)g(BZER)m(O)h(m)m(ust)g(b)s(e)227 3781 y(declared)d(as)g(Double)g(Precision)g(v)-5 b(ariables\).)382 4039 y Ff(FTPSCL\(unit,bscale,bzero)o(,)42 b(>)47 b(status\))0 4296 y Fi(2)81 b Fj(Reset)39 b(the)f(scaling)i(parameters)e(for)h(a)f (table)h(column;)k(do)s(es)38 b(not)g(c)m(hange)i(the)e(TSCALn)f(or)h (TZER)m(On)227 4409 y(k)m(eyw)m(ord)29 b(v)-5 b(alues)29 b(and)e(only)i(a\013ects)g(the)g(automatic)h(scaling)f(p)s(erformed)e (when)g(the)i(data)g(elemen)m(ts)h(are)227 4522 y(written/read)i (to/from)g(the)g(FITS)f(\014le.)44 b(When)31 b(reading)g(from)g(a)h (FITS)f(\014le)g(the)h(returned)e(data)i(v)-5 b(alue)227 4635 y(=)40 b(\(the)h(v)-5 b(alue)40 b(giv)m(en)h(in)f(the)g(FITS)g (arra)m(y\))g(*)h(TSCAL)e(+)g(TZER)m(O.)h(The)f(in)m(v)m(erse)i(form)m (ula)g(is)f(used)227 4748 y(when)33 b(writing)h(data)h(v)-5 b(alues)35 b(to)f(the)h(FITS)e(\014le.)52 b(\(NOTE:)34 b(TSCAL)f(and)g(TZER)m(O)g(m)m(ust)h(b)s(e)f(declared)227 4861 y(as)e(Double)g(Precision)g(v)-5 b(ariables\).)382 5118 y Ff(FTTSCL\(unit,colnum,tscal)o(,tz)o(ero,)41 b(>)48 b(status\))0 5375 y Fi(3)81 b Fj(De\014ne)36 b(the)g(in)m(teger)i(v)-5 b(alue)36 b(to)h(b)s(e)e(used)h(to)h(signify)f(unde\014ned)e(pixels)i (in)g(the)g(primary)f(arra)m(y)i(or)f(image)227 5488 y(extension.)59 b(This)35 b(is)h(only)g(used)g(if)g(BITPIX)g(=)f(8,)j (16,)h(32.)59 b(or)36 b(64)h(This)e(do)s(es)h(not)g(create)i(or)e(c)m (hange)227 5601 y(the)27 b(v)-5 b(alue)28 b(of)f(the)g(BLANK)g(k)m(eyw) m(ord)h(in)e(the)i(header.)39 b(FTPNULLL)27 b(is)g(iden)m(tical)h(to)g (FTPNUL)f(except)227 5714 y(that)k(the)g(blank)f(v)-5 b(alue)31 b(is)f(a)h(64-bit)g(in)m(teger)h(instead)f(of)f(a)h(32-bit)h (in)m(teger.)p eop end %%Page: 52 58 TeXDict begin 52 57 bop 0 299 a Fj(52)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTPNUL\(unit,blank,)43 b(>)k(status\))382 668 y(FTPNULLL\(unit,blankll,)42 b(>)47 b(status\))0 919 y Fi(4)81 b Fj(De\014ne)36 b(the)g(string)g(to)g(b)s (e)f(used)g(to)i(signify)f(unde\014ned)e(pixels)i(in)f(a)h(column)g(in) g(an)f(ASCI)s(I)g(table.)58 b(This)227 1032 y(do)s(es)30 b(not)h(create)h(or)e(c)m(hange)i(the)e(v)-5 b(alue)31 b(of)g(the)f(TNULLn)g(k)m(eyw)m(ord.)382 1283 y Ff (FTSNUL\(unit,colnum,snull)41 b(>)47 b(status\))0 1534 y Fi(5)81 b Fj(De\014ne)34 b(the)h(v)-5 b(alue)34 b(to)h(b)s(e)f(used)g (to)h(signify)f(unde\014ned)e(pixels)j(in)f(an)g(in)m(teger)i(column)e (in)g(a)g(binary)g(table)227 1647 y(\(where)42 b(TF)m(ORMn)f(=)g('B',)i ('I',)f('J',)f(or)h('K'\).)g(This)f(do)s(es)g(not)h(create)h(or)e(c)m (hange)i(the)e(v)-5 b(alue)42 b(of)g(the)227 1760 y(TNULLn)d(k)m(eyw)m (ord.)71 b(FTTNULLL)39 b(is)i(iden)m(tical)h(to)e(FTTNUL)g(except)h (that)g(the)f(tn)m(ull)h(v)-5 b(alue)40 b(is)h(a)227 1872 y(64-bit)32 b(in)m(teger)g(instead)e(of)h(a)g(32-bit)g(in)m (teger.)382 2123 y Ff(FTTNUL\(unit,colnum,tnull)41 b(>)47 b(status\))382 2236 y(FTTNULLL\(unit,colnum,tnu)o(lll)o(l)42 b(>)47 b(status\))0 2569 y Fe(6.6)135 b(FITS)44 b(Primary)h(Arra)l(y)g (or)g(IMA)l(GE)g(Extension)h(I/O)f(Subroutines)0 2819 y Fj(These)26 b(subroutines)f(put)h(or)h(get)g(data)h(v)-5 b(alues)26 b(in)h(the)f(primary)g(data)h(arra)m(y)g(\(i.e.,)i(the)e (\014rst)f(HDU)h(in)f(the)h(FITS)0 2932 y(\014le\))35 b(or)g(an)f(IMA)m(GE)i(extension.)54 b(The)34 b(data)i(arra)m(y)f(is)f (represen)m(ted)h(as)g(a)g(single)g(one-dimensional)h(arra)m(y)f(of)0 3045 y(pixels)h(regardless)h(of)f(the)g(actual)h(dimensionalit)m(y)g (of)g(the)f(arra)m(y)-8 b(,)38 b(and)e(the)g(FPIXEL)g(parameter)g(giv)m (es)i(the)0 3158 y(p)s(osition)28 b(within)e(this)i(1-D)g(arra)m(y)g (of)g(the)g(\014rst)e(pixel)i(to)g(read)g(or)f(write.)40 b(Automatic)29 b(data)f(t)m(yp)s(e)g(con)m(v)m(ersion)h(is)0 3270 y(p)s(erformed)g(for)i(n)m(umeric)g(data)g(\(except)i(for)d (complex)i(data)f(t)m(yp)s(es\))h(if)f(the)g(data)g(t)m(yp)s(e)g(of)g (the)g(primary)f(arra)m(y)0 3383 y(\(de\014ned)e(b)m(y)g(the)h(BITPIX)f (k)m(eyw)m(ord\))h(di\013ers)g(from)f(the)g(data)i(t)m(yp)s(e)e(of)h (the)g(arra)m(y)g(in)f(the)h(calling)h(subroutine.)0 3496 y(The)41 b(data)i(v)-5 b(alues)42 b(are)g(also)h(scaled)f(b)m(y)g (the)g(BSCALE)f(and)g(BZER)m(O)h(header)f(v)-5 b(alues)42 b(as)g(they)g(are)g(b)s(eing)0 3609 y(written)32 b(or)g(read)g(from)g (the)g(FITS)g(arra)m(y)-8 b(.)47 b(The)31 b(ftpscl)i(subroutine)e(MUST) g(b)s(e)h(called)h(to)g(de\014ne)e(the)i(scaling)0 3722 y(parameters)h(when)e(writing)i(data)g(to)g(the)g(FITS)f(arra)m(y)h(or) f(to)h(o)m(v)m(erride)h(the)f(default)f(scaling)i(v)-5 b(alue)34 b(giv)m(en)g(in)0 3835 y(the)d(header)f(when)f(reading)i(the) f(FITS)g(arra)m(y)-8 b(.)0 3995 y(Tw)m(o)41 b(sets)f(of)h(subroutines)e (are)i(pro)m(vided)f(to)h(read)g(the)f(data)i(arra)m(y)f(whic)m(h)f (di\013er)g(in)g(the)h(w)m(a)m(y)g(unde\014ned)0 4108 y(pixels)35 b(are)h(handled.)55 b(The)35 b(\014rst)f(set)i(of)g (routines)f(\(FTGPVx\))h(simply)f(return)f(an)h(arra)m(y)h(of)g(data)g (elemen)m(ts)0 4221 y(in)c(whic)m(h)g(unde\014ned)e(pixels)i(are)h(set) f(equal)h(to)g(a)g(v)-5 b(alue)32 b(sp)s(eci\014ed)g(b)m(y)g(the)g (user)g(in)g(the)g('n)m(ullv)-5 b(al')33 b(parameter.)0 4334 y(An)h(additional)i(feature)f(of)f(these)h(subroutines)f(is)g (that)i(if)e(the)h(user)f(sets)h(n)m(ullv)-5 b(al)35 b(=)f(0,)i(then)f(no)f(c)m(hec)m(ks)i(for)0 4447 y(unde\014ned)d (pixels)j(will)g(b)s(e)e(p)s(erformed,)i(th)m(us)f(increasing)h(the)g (sp)s(eed)e(of)i(the)g(program.)55 b(The)35 b(second)h(set)g(of)0 4560 y(routines)31 b(\(FTGPFx\))i(returns)d(the)i(data)g(elemen)m(t)h (arra)m(y)f(and,)f(in)h(addition,)g(a)g(logical)i(arra)m(y)e(whic)m(h)f (de\014nes)0 4673 y(whether)40 b(the)g(corresp)s(onding)f(data)i(pixel) g(is)f(unde\014ned.)69 b(The)39 b(latter)j(set)f(of)f(subroutines)f(ma) m(y)i(b)s(e)f(more)0 4785 y(con)m(v)m(enien)m(t)33 b(to)g(use)e(in)g (some)g(circumstances,)i(ho)m(w)m(ev)m(er,)g(it)f(requires)f(an)g (additional)h(arra)m(y)g(of)g(logical)i(v)-5 b(alues)0 4898 y(whic)m(h)36 b(can)g(b)s(e)g(un)m(wieldy)f(when)h(w)m(orking)g (with)g(large)h(data)g(arra)m(ys.)58 b(Also)37 b(for)f(programmer)g (con)m(v)m(enience,)0 5011 y(sets)j(of)g(subroutines)f(to)h(directly)h (read)e(or)h(write)g(2)g(and)g(3)g(dimensional)g(arra)m(ys)g(ha)m(v)m (e)h(b)s(een)e(pro)m(vided,)j(as)0 5124 y(w)m(ell)31 b(as)f(a)g(set)g(of)g(subroutines)e(to)i(read)g(or)g(write)f(an)m(y)h (con)m(tiguous)h(rectangular)g(subset)e(of)h(pixels)g(within)f(the)0 5237 y(n-dimensional)h(arra)m(y)-8 b(.)0 5488 y Fi(1)81 b Fj(Get)39 b(the)g(data)h(t)m(yp)s(e)e(of)h(the)g(image)h(\(=)f (BITPIX)f(v)-5 b(alue\).)67 b(P)m(ossible)39 b(returned)f(v)-5 b(alues)39 b(are:)58 b(8,)41 b(16,)h(32,)227 5601 y(64,)36 b(-32,)h(or)d(-64)h(corresp)s(onding)e(to)h(unsigned)f(b)m(yte,)j (signed)e(2-b)m(yte)h(in)m(teger,)i(signed)d(4-b)m(yte)h(in)m(teger,) 227 5714 y(signed)c(8-b)m(yte)g(in)m(teger,)h(real,)g(and)d(double.)p eop end %%Page: 53 59 TeXDict begin 53 58 bop 0 299 a Fh(6.6.)72 b(FITS)30 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)e(I/O)i (SUBR)m(OUTINES)589 b Fj(53)227 555 y(The)26 b(second)f(subroutine)g (is)h(similar)g(to)g(FTGIDT,)h(except)f(that)h(if)f(the)f(image)j (pixel)e(v)-5 b(alues)26 b(are)g(scaled,)227 668 y(with)h(non-default)g (v)-5 b(alues)27 b(for)g(the)h(BZER)m(O)f(and)f(BSCALE)g(k)m(eyw)m (ords,)j(then)e(this)g(routine)g(will)g(return)227 781 y(the)32 b('equiv)-5 b(alen)m(t')33 b(data)e(t)m(yp)s(e)h(that)f(is)g (needed)g(to)h(store)g(the)f(scaled)h(v)-5 b(alues.)43 b(F)-8 b(or)32 b(example,)g(if)f(BITPIX)227 894 y(=)39 b(16)g(and)g(BSCALE)f(=)g(0.1)i(then)f(the)g(equiv)-5 b(alen)m(t)40 b(data)f(t)m(yp)s(e)g(is)g(\015oating)h(p)s(oin)m(t,)h (and)d(-32)i(will)g(b)s(e)227 1007 y(returned.)65 b(There)39 b(are)g(2)g(sp)s(ecial)h(cases:)58 b(if)39 b(the)g(image)h(con)m(tains) g(unsigned)e(2-b)m(yte)i(in)m(teger)g(v)-5 b(alues,)227 1120 y(with)40 b(BITPIX)g(=)f(16,)44 b(BSCALE)39 b(=)h(1,)j(and)c(BZER) m(O)h(=)g(32768,)45 b(then)39 b(this)h(routine)g(will)h(return)e(a)227 1233 y(non-standard)26 b(v)-5 b(alue)27 b(of)g(20)h(for)f(the)g(bitpix) g(v)-5 b(alue.)40 b(Similarly)27 b(if)f(the)i(image)g(con)m(tains)g (unsigned)e(4-b)m(yte)227 1346 y(in)m(tegers,)32 b(then)e(bitpix)g (will)h(b)s(e)f(returned)f(with)h(a)h(v)-5 b(alue)31 b(of)f(40.)382 1609 y Ff(FTGIDT\(unit,)44 b(>)k(bitpix,status\))382 1722 y(FTGIET\(unit,)c(>)k(bitpix,status\))0 1986 y Fi(2)81 b Fj(Get)31 b(the)g(dimension)e(\(n)m(um)m(b)s(er)h(of)g(axes)h(=)f (NAXIS\))h(of)f(the)h(image)382 2250 y Ff(FTGIDM\(unit,)44 b(>)k(naxis,status\))0 2513 y Fi(3)81 b Fj(Get)38 b(the)f(size)h(of)f (all)h(the)f(dimensions)g(of)g(the)g(image.)62 b(The)37 b(FTGISZLL)e(routine)i(returns)f(an)h(arra)m(y)h(of)227 2626 y(64-bit)32 b(in)m(tegers)g(instead)e(of)h(32-bit)g(in)m(tegers.) 382 2890 y Ff(FTGISZ\(unit,)44 b(maxdim,)i(>)i(naxes,status\))382 3003 y(FTGISZLL\(unit,)c(maxdim,)i(>)h(naxesll,status\))0 3266 y Fi(4)81 b Fj(Get)35 b(the)f(parameters)g(that)h(de\014ne)e(the)h (t)m(yp)s(e)g(and)g(size)g(of)h(the)f(image.)53 b(This)33 b(routine)h(simply)f(com)m(bines)227 3379 y(calls)40 b(to)f(the)g(ab)s(o)m(v)m(e)h(3)f(routines.)65 b(The)38 b(FTGIPRLL)g(routine)h(returns)e(an)i(arra)m(y)g(of)g(64-bit)h(in)m (tegers)227 3492 y(instead)31 b(of)f(32-bit)i(in)m(tegers.)382 3756 y Ff(FTGIPR\(unit,)44 b(maxdim,)i(>)i(bitpix,)d(naxis,)h(naxes,)h (int)f(*status\))382 3869 y(FTGIPRLL\(unit,)e(maxdim,)i(>)h(bitpix,)f (naxis,)g(naxesll,)f(int)i(*status\))0 4132 y Fi(5)81 b Fj(Put)25 b(elemen)m(ts)j(in)m(to)f(the)f(data)h(arra)m(y)-8 b(.)40 b(The)26 b(FTPPR[]LL)f(routines)h(accept)i(64-bit)f(in)m(tegers) h(for)d(fpixel)i(and)227 4245 y(nelemen)m(ts.)382 4509 y Ff(FTPPR[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o(valu) o(es,)41 b(>)48 b(status\))382 4622 y(FTPPR[BIJKED]LL\(unit,gro)o(up,)o (fpix)o(elll)o(,ne)o(leme)o(ntsl)o(l,v)o(alue)o(s,)42 b(>)47 b(status\))0 4886 y Fi(6)81 b Fj(Put)30 b(elemen)m(ts)i(in)m(to) f(the)g(data)g(arra)m(y)-8 b(,)32 b(substituting)e(the)g(appropriate)h (FITS)f(n)m(ull)g(v)-5 b(alue)31 b(for)f(all)i(elemen)m(ts)227 4999 y(whic)m(h)k(are)g(equal)g(to)g(the)g(v)-5 b(alue)37 b(of)e(NULL)-10 b(V)g(AL.)36 b(F)-8 b(or)37 b(in)m(teger)g(FITS)e(arra) m(ys,)i(the)f(n)m(ull)g(v)-5 b(alue)36 b(de\014ned)227 5111 y(b)m(y)28 b(the)g(previous)f(call)i(to)g(FTPNUL)f(will)g(b)s(e)f (substituted;)h(for)g(\015oating)h(p)s(oin)m(t)f(FITS)f(arra)m(ys)h (\(BITPIX)227 5224 y(=)38 b(-32)i(or)e(-64\))i(then)e(the)g(sp)s(ecial) h(IEEE)f(NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)38 b(will)h(b)s(e)f(substituted.)63 b(The)227 5337 y(FTPPN[]LL)31 b(routines)f(accept)i(64-bit)f(in)m(tegers)h(for)e(fpixel)h(and)e (nelemen)m(ts.)382 5601 y Ff(FTPPN[BIJKED]\(unit,group)o(,fp)o(ixel)o (,nel)o(eme)o(nts,)o(valu)o(es,)o(null)o(val)41 b(>)48 b(status\))382 5714 y(FTPPN[BIJKED]LL\(unit,gro)o(up,)o(fpix)o(elll)o (,ne)o(leme)o(ntsl)o(l,v)o(alue)o(s,nu)o(llv)o(al)42 b(>)47 b(status\))p eop end %%Page: 54 60 TeXDict begin 54 59 bop 0 299 a Fj(54)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(7)81 b Fj(Set)33 b(data)g(arra)m(y)h (elemen)m(ts)g(as)g(unde\014ned.)46 b(FTPPR)m(ULL)33 b(accepts)h(64-bit)h(in)m(tegers)f(for)f(fpixel)g(and)f(nele-)227 668 y(men)m(ts.)382 916 y Ff(FTPPRU\(unit,group,fpixel)o(,ne)o(leme)o (nts,)41 b(>)47 b(status\))382 1029 y(FTPPRULL\(unit,group,fpix)o(ell)o (l,ne)o(leme)o(nts)o(ll,)41 b(>)48 b(status\))0 1276 y Fi(8)81 b Fj(Get)36 b(elemen)m(ts)g(from)f(the)g(data)h(arra)m(y)-8 b(.)55 b(Unde\014ned)34 b(arra)m(y)h(elemen)m(ts)i(will)e(b)s(e)g (returned)f(with)g(a)i(v)-5 b(alue)35 b(=)227 1389 y(n)m(ullv)-5 b(al,)41 b(unless)c(n)m(ullv)-5 b(al)39 b(=)f(0)g(in)g(whic)m(h)f(case) i(no)f(c)m(hec)m(ks)i(for)e(unde\014ned)d(pixels)j(will)h(b)s(e)e(p)s (erformed.)227 1502 y(FTGPV[]LL)31 b(accepts)h(64-bit)f(in)m(tegers)h (for)e(fpixel)h(and)e(nelemen)m(ts.)382 1749 y Ff (FTGPV[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o(null)o (val)o(,)42 b(>)47 b(values,anyf,status\))382 1862 y (FTGPV[BIJKED]LL\(unit,gro)o(up,)o(fpix)o(elll)o(,ne)o(leme)o(ntsl)o (l,n)o(ullv)o(al,)41 b(>)48 b(values,anyf,status\))0 2110 y Fi(9)81 b Fj(Get)32 b(elemen)m(ts)g(and)f(n)m(ull\015ags)g(from) g(data)h(arra)m(y)-8 b(.)44 b(An)m(y)32 b(unde\014ned)d(arra)m(y)i (elemen)m(ts)i(will)e(ha)m(v)m(e)i(the)e(corre-)227 2223 y(sp)s(onding)e(\015agv)-5 b(als)31 b(elemen)m(t)h(set)f(equal)g(to)g (.TR)m(UE.)382 2470 y Ff(FTGPF[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel) o(eme)o(nts,)41 b(>)48 b(values,flagvals,anyf,st)o(atu)o(s\))0 2718 y Fi(10)e Fj(Put)30 b(v)-5 b(alues)31 b(in)m(to)g(group)f (parameters)382 2965 y Ff(FTPGP[BIJKED]\(unit,group)o(,fp)o(arm,)o (npar)o(m,v)o(alue)o(s,)42 b(>)47 b(status\))0 3213 y Fi(11)f Fj(Get)31 b(v)-5 b(alues)31 b(from)f(group)g(parameters)382 3460 y Ff(FTGGP[BIJKED]\(unit,group)o(,fp)o(arm,)o(npar)o(m,)41 b(>)48 b(values,status\))0 3708 y Fj(The)32 b(follo)m(wing)h(4)g (subroutines)e(transfer)g(FITS)h(images)h(with)f(2)g(or)g(3)h (dimensions)e(to)i(or)f(from)g(a)h(data)f(arra)m(y)0 3821 y(whic)m(h)h(has)g(b)s(een)g(declared)g(in)g(the)h(calling)h (program.)49 b(The)33 b(dimensionalit)m(y)h(of)g(the)f(FITS)g(image)h (is)f(passed)0 3933 y(b)m(y)26 b(the)g(naxis1,)h(naxis2,)h(and)d (naxis3)i(parameters)f(and)f(the)h(declared)h(dimensions)e(of)h(the)g (program)g(arra)m(y)h(are)0 4046 y(passed)k(in)f(the)i(dim1)e(and)h (dim2)g(parameters.)43 b(Note)32 b(that)g(the)f(program)g(arra)m(y)g (do)s(es)g(not)g(ha)m(v)m(e)i(to)e(ha)m(v)m(e)i(the)0 4159 y(same)28 b(dimensions)f(as)h(the)g(FITS)e(arra)m(y)-8 b(,)30 b(but)d(m)m(ust)g(b)s(e)g(at)i(least)f(as)g(big.)40 b(F)-8 b(or)29 b(example)f(if)f(a)h(FITS)f(image)i(with)0 4272 y(NAXIS1)i(=)f(NAXIS2)h(=)f(400)i(is)e(read)h(in)m(to)g(a)g (program)f(arra)m(y)h(whic)m(h)f(is)h(dimensioned)f(as)g(512)i(x)f(512) g(pixels,)0 4385 y(then)d(the)g(image)i(will)e(just)g(\014ll)g(the)h (lo)m(w)m(er)g(left)g(corner)f(of)h(the)f(arra)m(y)h(with)f(pixels)g (in)g(the)h(range)f(1)h(-)f(400)i(in)e(the)0 4498 y(X)k(an)g(Y)h (directions.)47 b(This)31 b(has)h(the)h(e\013ect)g(of)g(taking)g(a)g (con)m(tiguous)g(set)g(of)f(pixel)h(v)-5 b(alue)33 b(in)e(the)i(FITS)e (arra)m(y)0 4611 y(and)k(writing)g(them)g(to)h(a)g(non-con)m(tiguous)g (arra)m(y)f(in)g(program)g(memory)g(\(i.e.,)j(there)e(are)f(no)m(w)h (some)f(blank)0 4724 y(pixels)c(around)e(the)h(edge)i(of)e(the)h(image) g(in)f(the)h(program)f(arra)m(y\).)0 4971 y Fi(11)46 b Fj(Put)30 b(2-D)i(image)f(in)m(to)h(the)e(data)h(arra)m(y)382 5219 y Ff(FTP2D[BIJKED]\(unit,group)o(,di)o(m1,n)o(axis)o(1,n)o(axis)o (2,im)o(age)o(,)42 b(>)47 b(status\))0 5466 y Fi(12)f Fj(Put)30 b(3-D)i(cub)s(e)d(in)m(to)j(the)e(data)h(arra)m(y)382 5714 y Ff(FTP3D[BIJKED]\(unit,group)o(,di)o(m1,d)o(im2,)o(nax)o(is1,)o (naxi)o(s2,)o(naxi)o(s3,c)o(ube)o(,)42 b(>)47 b(status\))p eop end %%Page: 55 61 TeXDict begin 55 60 bop 0 299 a Fh(6.6.)72 b(FITS)30 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)e(I/O)i (SUBR)m(OUTINES)589 b Fj(55)0 555 y Fi(13)46 b Fj(Get)29 b(2-D)f(image)h(from)f(the)f(data)i(arra)m(y)-8 b(.)41 b(Unde\014ned)26 b(pixels)h(in)h(the)g(arra)m(y)g(will)g(b)s(e)f(set)h (equal)g(to)h(the)e(v)-5 b(alue)227 668 y(of)31 b('n)m(ullv)-5 b(al',)31 b(unless)f(n)m(ullv)-5 b(al=0)31 b(in)f(whic)m(h)g(case)i(no) e(testing)i(for)e(unde\014ned)e(pixels)i(will)h(b)s(e)f(p)s(erformed.) 382 947 y Ff(FTG2D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o (naxi)o(s1,n)o(axi)o(s2,)41 b(>)48 b(image,anyf,status\))0 1226 y Fi(14)e Fj(Get)31 b(3-D)h(cub)s(e)e(from)g(the)g(data)h(arra)m (y)-8 b(.)42 b(Unde\014ned)29 b(pixels)i(in)f(the)g(arra)m(y)h(will)g (b)s(e)f(set)h(equal)g(to)g(the)f(v)-5 b(alue)227 1339 y(of)31 b('n)m(ullv)-5 b(al',)31 b(unless)f(n)m(ullv)-5 b(al=0)31 b(in)f(whic)m(h)g(case)i(no)e(testing)i(for)e(unde\014ned)e (pixels)i(will)h(b)s(e)f(p)s(erformed.)382 1617 y Ff (FTG3D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o(dim2)o(,nax)o (is1)o(,nax)o(is2,)o(nax)o(is3,)41 b(>)1002 1730 y(cube,anyf,status\))0 2009 y Fj(The)i(follo)m(wing)h(subroutines)e(transfer)h(a)h (rectangular)g(subset)e(of)i(the)f(pixels)g(in)g(a)h(FITS)e (N-dimensional)0 2122 y(image)31 b(to)g(or)f(from)f(an)h(arra)m(y)g (whic)m(h)g(has)g(b)s(een)f(declared)h(in)g(the)g(calling)i(program.)40 b(The)29 b(fpixels)h(and)f(lpixels)0 2235 y(parameters)e(are)h(in)m (teger)g(arra)m(ys)g(whic)m(h)f(sp)s(ecify)f(the)i(starting)g(and)e (ending)h(pixels)g(in)g(eac)m(h)h(dimension)e(of)i(the)0 2348 y(FITS)36 b(image)i(that)f(are)g(to)h(b)s(e)e(read)g(or)h (written.)60 b(\(Note)38 b(that)g(these)f(are)g(the)g(starting)g(and)f (ending)h(pixels)0 2461 y(in)d(the)h(FITS)f(image,)k(not)d(in)f(the)h (declared)g(arra)m(y\).)55 b(The)34 b(arra)m(y)i(parameter)f(is)g (treated)g(simply)g(as)g(a)g(large)0 2574 y(one-dimensional)c(arra)m(y) f(of)h(the)f(appropriate)g(datat)m(yp)s(e)h(con)m(taining)h(the)e (pixel)g(v)-5 b(alues;)31 b(The)e(pixel)i(v)-5 b(alues)30 b(in)0 2686 y(the)c(FITS)f(arra)m(y)i(are)f(read/written)g(from/to)h (this)f(program)f(arra)m(y)i(in)e(strict)i(sequence)f(without)g(an)m(y) h(gaps;)g(it)0 2799 y(is)i(up)e(to)j(the)f(calling)h(routine)f(to)g (correctly)h(in)m(terpret)f(the)g(dimensionalit)m(y)h(of)f(this)g(arra) m(y)-8 b(.)41 b(The)28 b(t)m(w)m(o)i(families)0 2912 y(of)d(FITS)g(reading)g(routines)g(\(FTGSVx)g(and)g(FTGSFx)g (subroutines\))f(also)j(ha)m(v)m(e)f(an)f('incs')h(parameter)f(whic)m (h)0 3025 y(de\014nes)j(the)h(data)h(sampling)e(in)m(terv)-5 b(al)32 b(in)f(eac)m(h)h(dimension)e(of)h(the)g(FITS)f(arra)m(y)-8 b(.)43 b(F)-8 b(or)32 b(example,)g(if)f(incs\(1\)=2)0 3138 y(and)i(incs\(2\)=3)h(when)f(reading)g(a)h(2-dimensional)g(FITS)f (image,)i(then)e(only)h(ev)m(ery)g(other)f(pixel)h(in)f(the)h(\014rst)0 3251 y(dimension)e(and)h(ev)m(ery)h(3rd)e(pixel)i(in)f(the)g(second)g (dimension)f(will)i(b)s(e)e(returned)g(in)h(the)g('arra)m(y')h (parameter.)0 3364 y([Note:)39 b(the)25 b(FTGSSx)f(family)i(of)e (routines)h(whic)m(h)g(w)m(ere)g(presen)m(t)g(in)f(previous)g(v)m (ersions)h(of)g(FITSIO)f(ha)m(v)m(e)i(b)s(een)0 3477 y(sup)s(erseded)i(b)m(y)j(the)f(more)h(general)g(FTGSVx)f(family)h(of)g (routines.])0 3756 y Fi(15)46 b Fj(Put)30 b(an)g(arbitrary)g(data)h (subsection)g(in)m(to)g(the)g(data)g(arra)m(y)-8 b(.)382 4034 y Ff(FTPSS[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o (ls,l)o(pix)o(els,)o(arra)o(y,)41 b(>)48 b(status\))0 4313 y Fi(16)e Fj(Get)30 b(an)e(arbitrary)g(data)i(subsection)e(from)g (the)h(data)g(arra)m(y)-8 b(.)42 b(Unde\014ned)27 b(pixels)h(in)h(the)f (arra)m(y)i(will)e(b)s(e)g(set)227 4426 y(equal)k(to)h(the)e(v)-5 b(alue)33 b(of)e('n)m(ullv)-5 b(al',)33 b(unless)e(n)m(ullv)-5 b(al=0)33 b(in)e(whic)m(h)g(case)i(no)e(testing)i(for)e(unde\014ned)f (pixels)227 4539 y(will)h(b)s(e)f(p)s(erformed.)382 4818 y Ff(FTGSV[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o(ls,l) o(pix)o(els,)o(incs)o(,nu)o(llva)o(l,)42 b(>)1002 4931 y(array,anyf,status\))0 5209 y Fi(17)k Fj(Get)34 b(an)f(arbitrary)g (data)g(subsection)g(from)g(the)g(data)g(arra)m(y)-8 b(.)50 b(An)m(y)33 b(Unde\014ned)e(pixels)i(in)g(the)g(arra)m(y)h(will) 227 5322 y(ha)m(v)m(e)e(the)e(corresp)s(onding)g('\015agv)-5 b(als')31 b(elemen)m(t)h(set)f(equal)g(to)g(.TR)m(UE.)382 5601 y Ff(FTGSF[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o (ls,l)o(pix)o(els,)o(incs)o(,)42 b(>)1002 5714 y (array,flagvals,anyf,statu)o(s\))p eop end %%Page: 56 62 TeXDict begin 56 61 bop 0 299 a Fj(56)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fe(6.7)135 b(FITS)44 b(ASCI)t(I)g(and)h (Binary)g(T)-11 b(able)45 b(Data)h(I/O)f(Subroutines)0 809 y Fc(6.7.1)112 b(Column)39 b(Information)f(Subroutines)0 1017 y Fi(1)81 b Fj(Get)37 b(the)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(or) g(columns)g(in)g(the)h(curren)m(t)f(FITS)g(table.)59 b(The)36 b(n)m(um)m(b)s(er)f(of)h(ro)m(ws)h(is)f(giv)m(en)227 1129 y(b)m(y)f(the)h(NAXIS2)f(k)m(eyw)m(ord)h(and)f(the)g(n)m(um)m(b)s (er)f(of)h(columns)g(is)g(giv)m(en)h(b)m(y)g(the)f(TFIELDS)g(k)m(eyw)m (ord)g(in)227 1242 y(the)d(header)f(of)h(the)g(table.)45 b(The)31 b(FTGNR)-10 b(WLL)32 b(routine)g(is)f(iden)m(tical)i(to)g (FTGNR)-10 b(W)32 b(except)h(that)f(the)227 1355 y(n)m(um)m(b)s(er)d (of)i(ro)m(ws)f(is)h(returned)e(as)h(a)h(64-bit)h(in)m(teger)g(rather)e (than)g(a)h(32-bit)g(in)m(teger.)382 1608 y Ff(FTGNRW\(unit,)44 b(>)k(nrows,)e(status\))382 1721 y(FTGNRWLL\(unit,)e(>)j(nrowsll,)f (status\))382 1834 y(FTGNCL\(unit,)e(>)k(ncols,)e(status\))0 2087 y Fi(2)81 b Fj(Get)25 b(the)f(table)i(column)e(n)m(um)m(b)s(er)f (\(and)h(name\))h(of)f(the)h(column)f(whose)g(name)g(matc)m(hes)i(an)e (input)g(template)227 2200 y(name.)38 b(The)21 b(table)i(column)e (names)h(are)g(de\014ned)e(b)m(y)i(the)g(TTYPEn)e(k)m(eyw)m(ords)i(in)f (the)h(FITS)f(header.)37 b(If)22 b(a)227 2313 y(column)i(do)s(es)g(not) g(ha)m(v)m(e)h(a)f(TTYPEn)f(k)m(eyw)m(ord,)j(then)d(these)h(routines)g (assume)g(that)g(the)h(name)e(consists)227 2426 y(of)i(all)h(blank)f(c) m(haracters.)40 b(These)25 b(2)g(subroutines)e(p)s(erform)h(the)h(same) g(function)g(except)h(that)f(FTGCNO)227 2539 y(only)j(returns)e(the)h (n)m(um)m(b)s(er)f(of)h(the)g(matc)m(hing)i(column)e(whereas)g(FTGCNN)g (also)h(returns)e(the)i(name)f(of)227 2652 y(the)k(column.)40 b(If)30 b(CASESEN)f(=)h(.true.)41 b(then)30 b(the)h(column)f(name)g (matc)m(h)i(will)e(b)s(e)g(case-sensitiv)m(e.)227 2801 y(The)41 b(input)e(column)i(name)g(template)h(\(COL)-8 b(TEMPLA)g(TE\))41 b(is)g(\(1\))g(either)h(the)f(exact)h(name)f(of)g (the)227 2914 y(column)36 b(to)i(b)s(e)d(searc)m(hed)i(for,)h(or)e (\(2\))i(it)f(ma)m(y)g(con)m(tain)g(wild)f(cards)g(c)m(haracters)i (\(*,)h(?,)f(or)e(#\),)i(or)f(\(3\))227 3026 y(it)d(ma)m(y)g(con)m (tain)g(the)f(n)m(um)m(b)s(er)f(of)h(the)g(desired)g(column)g(\(where)g (the)g(n)m(um)m(b)s(er)f(is)h(expressed)f(as)h(ASCI)s(I)227 3139 y(digits\).)41 b(The)28 b(\014rst)g(2)h(wild)f(cards)g(b)s(eha)m (v)m(e)h(similarly)g(to)g(UNIX)g(\014lename)g(matc)m(hing:)40 b(the)29 b('*')g(c)m(haracter)227 3252 y(matc)m(hes)e(an)m(y)g (sequence)f(of)h(c)m(haracters)g(\(including)f(zero)h(c)m(haracters\))h (and)d(the)i(')10 b(?')39 b(c)m(haracter)28 b(matc)m(hes)227 3365 y(an)m(y)40 b(single)h(c)m(haracter.)71 b(The)39 b(#)h(wildcard)f(will)h(matc)m(h)h(an)m(y)f(consecutiv)m(e)i(string)e (of)g(decimal)g(digits)227 3478 y(\(0-9\).)45 b(As)31 b(an)g(example,)h(the)f(template)h(strings)f('AB?DE',)h('AB*E',)h(and)d ('AB*CDE')j(will)e(all)h(matc)m(h)227 3591 y(the)26 b(string)g ('ABCDE'.)i(If)d(more)h(than)g(one)g(column)g(name)g(in)g(the)g(table)h (matc)m(hes)g(the)f(template)i(string,)227 3704 y(then)33 b(the)h(\014rst)f(matc)m(h)h(is)f(returned)g(and)f(the)i(status)g(v)-5 b(alue)34 b(will)f(b)s(e)g(set)h(to)g(237)h(as)f(a)f(w)m(arning)h(that) g(a)227 3817 y(unique)g(matc)m(h)i(w)m(as)f(not)g(found.)53 b(T)-8 b(o)35 b(\014nd)f(the)h(other)g(cases)g(that)h(matc)m(h)g(the)f (template,)i(simply)e(call)227 3930 y(the)27 b(subroutine)f(again)i (lea)m(ving)h(the)e(input)f(status)h(v)-5 b(alue)28 b(equal)f(to)h(237) g(and)f(the)g(next)g(matc)m(hing)h(name)227 4043 y(will)k(then)g(b)s(e) f(returned.)43 b(Rep)s(eat)32 b(this)g(pro)s(cess)f(un)m(til)h(a)g (status)g(=)g(219)h(\(column)e(name)h(not)g(found\))f(is)227 4156 y(returned.)40 b(If)30 b(these)h(subroutines)e(fail)i(to)g(matc)m (h)g(the)g(template)h(to)f(an)m(y)g(of)f(the)h(columns)f(in)g(the)h (table,)227 4268 y(they)i(lastly)g(c)m(hec)m(k)h(if)f(the)f(template)i (can)f(b)s(e)e(in)m(terpreted)i(as)g(a)g(simple)f(p)s(ositiv)m(e)h(in)m (teger)h(\(e.g.,)h('7',)f(or)227 4381 y('512'\))i(and)d(if)g(so,)i (they)f(return)e(that)j(column)e(n)m(um)m(b)s(er.)49 b(If)33 b(no)g(matc)m(hes)i(are)f(found)e(then)h(a)h(status)g(=)227 4494 y(219)e(error)e(is)g(returned.)227 4643 y(Note)h(that)e(the)h (FITS)e(Standard)g(recommends)g(that)i(only)f(letters,)i(digits,)f(and) f(the)g(underscore)f(c)m(har-)227 4756 y(acter)44 b(b)s(e)e(used)g(in)h (column)f(names)h(\(with)g(no)f(em)m(b)s(edded)g(spaces)h(in)g(the)g (name\).)78 b(T)-8 b(railing)43 b(blank)227 4869 y(c)m(haracters)32 b(are)f(not)f(signi\014can)m(t.)382 5122 y Ff (FTGCNO\(unit,casesen,colt)o(emp)o(late)o(,)42 b(>)47 b(colnum,status\))382 5235 y(FTGCNN\(unit,casesen,colt)o(emp)o(late)o (,)42 b(>)47 b(colname,colnum,status\))0 5488 y Fi(3)81 b Fj(Get)39 b(the)g(datat)m(yp)s(e)h(of)e(a)h(column)g(in)f(an)g(ASCI)s (I)g(or)g(binary)g(table.)66 b(This)38 b(routine)h(returns)e(an)i(in)m (teger)227 5601 y(co)s(de)34 b(v)-5 b(alue)33 b(corresp)s(onding)f(to)i (the)g(datat)m(yp)s(e)g(of)f(the)g(column.)49 b(\(See)34 b(the)f(FTBNFM)i(and)d(FT)-8 b(ASFM)227 5714 y(subroutines)27 b(in)h(the)g(Utilities)j(section)e(of)f(this)g(do)s(cumen)m(t)g(for)g (a)h(list)g(of)f(the)h(co)s(de)f(v)-5 b(alues\).)41 b(The)27 b(v)m(ector)p eop end %%Page: 57 63 TeXDict begin 57 62 bop 0 299 a Fh(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fj(57)227 555 y(rep)s(eat)38 b(coun)m(t)g(\(whic)m(h)g(is)g(alw)m(a)m(y)h(1)f(for)g (ASCI)s(I)e(table)i(columns\))g(is)g(also)g(returned.)62 b(If)37 b(the)h(sp)s(eci\014ed)227 668 y(column)32 b(has)f(an)g(ASCI)s (I)f(c)m(haracter)j(datat)m(yp)s(e)g(\(co)s(de)f(=)f(16\))i(then)e(the) h(width)e(of)i(a)g(unit)f(string)h(in)f(the)227 781 y(column)i(is)g (also)h(returned.)48 b(Note)34 b(that)g(this)e(routine)h(supp)s(orts)f (the)h(lo)s(cal)h(con)m(v)m(en)m(tion)h(for)e(sp)s(ecifying)227 894 y(arra)m(ys)f(of)f(strings)g(within)f(a)i(binary)e(table)i(c)m (haracter)g(column,)g(using)e(the)h(syn)m(tax)h(TF)m(ORM)f(=)g('rAw') 227 1007 y(where)f('r')g(is)h(the)f(total)i(n)m(um)m(b)s(er)d(of)i(c)m (haracters)g(\(=)g(the)f(width)g(of)g(the)g(column\))h(and)f('w')g(is)g (the)h(width)227 1120 y(of)39 b(a)f(unit)g(string)g(within)g(the)g (column.)64 b(Th)m(us)37 b(if)h(the)g(column)g(has)g(TF)m(ORM)h(=)f ('60A12')i(then)e(this)227 1233 y(routine)29 b(will)g(return)f(dataco)s (de)i(=)e(16,)i(rep)s(eat)f(=)f(60,)j(and)d(width)g(=)g(12.)41 b(\(The)29 b(TDIMn)f(k)m(eyw)m(ord)h(ma)m(y)227 1346 y(also)35 b(b)s(e)e(used)g(to)h(sp)s(ecify)f(the)h(unit)f(string)h (length;)i(The)d(pair)g(of)h(k)m(eyw)m(ords)g(TF)m(ORMn)f(=)g('60A')j (and)227 1458 y(TDIMn)30 b(=)g('\(12,5\)')j(w)m(ould)e(ha)m(v)m(e)g (the)g(same)g(e\013ect)g(as)g(TF)m(ORMn)f(=)g('60A12'\).)227 1604 y(The)h(second)h(routine,)g(FTEQTY)f(is)g(similar)h(except)h(that) f(in)f(the)h(case)g(of)g(scaled)g(in)m(teger)h(columns)e(it)227 1717 y(returns)23 b(the)h('equiv)-5 b(alen)m(t')25 b(data)f(t)m(yp)s(e) g(that)h(is)e(needed)h(to)g(store)g(the)g(scaled)g(v)-5 b(alues,)26 b(and)d(not)h(necessarily)227 1830 y(the)38 b(ph)m(ysical)h(data)f(t)m(yp)s(e)g(of)g(the)g(unscaled)g(v)-5 b(alues)38 b(as)g(stored)g(in)g(the)g(FITS)f(table.)64 b(F)-8 b(or)38 b(example)h(if)227 1943 y(a)c('1I')g(column)f(in)g(a)g (binary)g(table)h(has)f(TSCALn)f(=)g(1)i(and)f(TZER)m(On)f(=)g(32768,) 38 b(then)c(this)g(column)227 2056 y(e\013ectiv)m(ely)27 b(con)m(tains)e(unsigned)e(short)g(in)m(teger)j(v)-5 b(alues,)25 b(and)f(th)m(us)f(the)h(returned)f(v)-5 b(alue)24 b(of)g(t)m(yp)s(eco)s(de)h(will)227 2169 y(b)s(e)32 b(the)h(co)s(de)g (for)g(an)f(unsigned)g(short)g(in)m(teger,)j(not)e(a)g(signed)g(short)f (in)m(teger.)49 b(Similarly)-8 b(,)34 b(if)f(a)g(column)227 2281 y(has)d(TTYPEn)g(=)g('1I')h(and)f(TSCALn)e(=)i(0.12,)j(then)d(the) g(returned)g(t)m(yp)s(eco)s(de)g(will)h(b)s(e)f(the)h(co)s(de)f(for)h (a)227 2394 y('real')h(column.)382 2626 y Ff(FTGTCL\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu)o(s\))382 2739 y(FTEQTY\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu)o (s\))0 2970 y Fi(4)81 b Fj(Return)22 b(the)i(displa)m(y)g(width)f(of)g (a)h(column.)39 b(This)22 b(is)i(the)g(length)g(of)f(the)h(string)g (that)g(will)g(b)s(e)f(returned)f(when)227 3083 y(reading)33 b(the)g(column)g(as)g(a)g(formatted)g(string.)48 b(The)32 b(displa)m(y)h(width)f(is)h(determined)g(b)m(y)f(the)h(TDISPn)227 3196 y(k)m(eyw)m(ord,)e(if)g(presen)m(t,)f(otherwise)h(b)m(y)f(the)h (data)g(t)m(yp)s(e)g(of)f(the)h(column.)382 3427 y Ff(FTGCDW\(unit,)44 b(colnum,)i(>)i(dispwidth,)d(status\))0 3659 y Fi(5)81 b Fj(Get)29 b(information)f(ab)s(out)g(an)g(existing)h(ASCI)s(I)e (table)i(column.)40 b(\(NOTE:)28 b(TSCAL)f(and)g(TZER)m(O)h(m)m(ust)g (b)s(e)227 3772 y(declared)j(as)g(Double)g(Precision)g(v)-5 b(ariables\).)41 b(All)31 b(the)g(returned)e(parameters)i(are)f(scalar) i(quan)m(tities.)382 4003 y Ff(FTGACL\(unit,colnum,)42 b(>)716 4116 y(ttype,tbcol,tunit,tform,)o(tsca)o(l,t)o(zero)o(,snu)o (ll,)o(tdis)o(p,st)o(atu)o(s\))0 4348 y Fi(6)81 b Fj(Get)29 b(information)f(ab)s(out)f(an)h(existing)h(binary)e(table)i(column.)40 b(\(NOTE:)28 b(TSCAL)e(and)i(TZER)m(O)f(m)m(ust)h(b)s(e)227 4461 y(declared)j(as)f(Double)g(Precision)h(v)-5 b(ariables\).)41 b(D)m(A)-8 b(T)g(A)g(TYPE)32 b(is)e(a)g(c)m(haracter)i(string)d(whic)m (h)h(returns)f(the)227 4574 y(datat)m(yp)s(e)35 b(of)g(the)f(column)g (as)g(de\014ned)f(b)m(y)h(the)g(TF)m(ORMn)g(k)m(eyw)m(ord)h(\(e.g.,)i ('I',)e('J','E',)g('D',)g(etc.\).)54 b(In)227 4686 y(the)27 b(case)g(of)g(an)f(ASCI)s(I)f(c)m(haracter)j(column,)f(D)m(A)-8 b(T)g(A)g(TYPE)29 b(will)d(ha)m(v)m(e)i(a)f(v)-5 b(alue)27 b(of)f(the)h(form)f('An')g(where)227 4799 y('n')34 b(is)g(an)g(in)m (teger)i(expressing)e(the)g(width)f(of)h(the)h(\014eld)e(in)h(c)m (haracters.)53 b(F)-8 b(or)35 b(example,)h(if)e(TF)m(ORM)g(=)227 4912 y('160A8')39 b(then)e(FTGBCL)f(will)h(return)f(D)m(A)-8 b(T)g(A)g(TYPE='A8')39 b(and)d(REPEA)-8 b(T=20.)60 b(All)37 b(the)g(returned)227 5025 y(parameters)31 b(are)g(scalar)g(quan)m (tities.)382 5257 y Ff(FTGBCL\(unit,colnum,)42 b(>)716 5370 y(ttype,tunit,datatype,rep)o(eat,)o(tsc)o(al,t)o(zero)o(,tn)o (ull,)o(tdis)o(p,s)o(tatu)o(s\))0 5601 y Fi(7)81 b Fj(Put)31 b(\(app)s(end\))g(a)i(TDIMn)f(k)m(eyw)m(ord)g(whose)g(v)-5 b(alue)33 b(has)f(the)g(form)g('\(l,m,n...\)')47 b(where)32 b(l,)h(m,)f(n...)46 b(are)33 b(the)227 5714 y(dimensions)d(of)g(a)h(m)m (ultidimensional)g(arra)m(y)g(column)f(in)g(a)h(binary)f(table.)p eop end %%Page: 58 64 TeXDict begin 58 63 bop 0 299 a Fj(58)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTPTDM\(unit,colnum,naxis)o(,na)o(xes,)41 b(>)48 b(status\))0 820 y Fi(8)81 b Fj(Return)29 b(the)h(n)m(um)m(b)s (er)e(of)i(and)g(size)g(of)g(the)g(dimensions)g(of)g(a)g(table)h (column.)40 b(Normally)31 b(this)f(information)227 933 y(is)h(giv)m(en)h(b)m(y)f(the)g(TDIMn)f(k)m(eyw)m(ord,)i(but)e(if)h (this)g(k)m(eyw)m(ord)g(is)g(not)g(presen)m(t)g(then)g(this)f(routine)h (returns)227 1046 y(NAXIS)f(=)g(1)h(and)f(NAXES\(1\))h(equal)g(to)g (the)g(rep)s(eat)g(coun)m(t)g(in)f(the)g(TF)m(ORM)h(k)m(eyw)m(ord.)382 1311 y Ff(FTGTDM\(unit,colnum,maxdi)o(m,)41 b(>)48 b (naxis,naxes,status\))0 1576 y Fi(9)81 b Fj(Deco)s(de)33 b(the)g(input)f(TDIMn)h(k)m(eyw)m(ord)g(string)f(\(e.g.)50 b('\(100,200\)'\))37 b(and)32 b(return)g(the)h(n)m(um)m(b)s(er)e(of)i (and)f(size)227 1689 y(of)c(the)g(dimensions)f(of)h(a)g(binary)f(table) h(column.)40 b(If)27 b(the)h(input)f(tdimstr)g(c)m(haracter)i(string)f (is)g(n)m(ull,)g(then)227 1801 y(this)d(routine)f(returns)f(naxis)h(=)h (1)f(and)g(naxes[0])i(equal)e(to)i(the)e(rep)s(eat)h(coun)m(t)g(in)f (the)g(TF)m(ORM)h(k)m(eyw)m(ord.)227 1914 y(This)30 b(routine)g(is)h (called)g(b)m(y)f(FTGTDM.)382 2179 y Ff(FTDTDM\(unit,tdimstr,coln)o (um,)o(maxd)o(im,)41 b(>)48 b(naxis,naxes,)c(status\))0 2444 y Fi(10)i Fj(Return)32 b(the)h(optimal)h(n)m(um)m(b)s(er)e(of)h (ro)m(ws)g(to)h(read)f(or)g(write)g(at)h(one)f(time)h(for)e(maxim)m(um) h(I/O)g(e\016ciency)-8 b(.)227 2557 y(Refer)31 b(to)g(the)g (\\Optimizing)g(Co)s(de")f(section)i(in)e(Chapter)g(5)g(for)h(more)f (discussion)g(on)g(ho)m(w)h(to)g(use)f(this)227 2670 y(routine.)382 2935 y Ff(FTGRSZ\(unit,)44 b(>)k(nrows,status\))0 3231 y Fc(6.7.2)112 b(Lo)m(w-Lev)m(el)39 b(T)-9 b(able)38 b(Access)f(Subroutines)0 3451 y Fj(The)d(follo)m(wing)h(subroutines)e (pro)m(vide)i(lo)m(w-lev)m(el)i(access)e(to)g(the)g(data)g(in)f(ASCI)s (I)e(or)i(binary)g(tables)h(and)f(are)0 3564 y(mainly)29 b(useful)f(as)i(an)f(e\016cien)m(t)h(w)m(a)m(y)g(to)g(cop)m(y)g(all)g (or)f(part)g(of)g(a)g(table)h(from)f(one)g(lo)s(cation)i(to)f(another.) 40 b(These)0 3677 y(routines)24 b(simply)g(read)g(or)h(write)f(the)h (sp)s(eci\014ed)e(n)m(um)m(b)s(er)g(of)i(consecutiv)m(e)h(b)m(ytes)f (in)f(an)g(ASCI)s(I)f(or)h(binary)g(table,)0 3790 y(without)37 b(regard)g(for)f(column)h(b)s(oundaries)e(or)i(the)g(ro)m(w)g(length)h (in)e(the)h(table.)61 b(The)37 b(\014rst)f(t)m(w)m(o)i(subroutines)0 3903 y(read)29 b(or)h(write)g(consecutiv)m(e)h(b)m(ytes)f(in)f(a)h (table)g(to)h(or)e(from)g(a)h(c)m(haracter)h(string)e(v)-5 b(ariable,)31 b(while)f(the)f(last)i(t)m(w)m(o)0 4016 y(subroutines)f(read)i(or)g(write)g(consecutiv)m(e)h(b)m(ytes)g(to)f (or)g(from)f(a)h(v)-5 b(ariable)33 b(declared)f(as)g(a)g(n)m(umeric)f (data)i(t)m(yp)s(e)0 4129 y(\(e.g.,)40 b(INTEGER,)d(INTEGER*2,)i(REAL,) d(DOUBLE)h(PRECISION\).)f(These)g(routines)h(do)f(not)h(p)s(erform)0 4242 y(an)m(y)c(mac)m(hine)g(dep)s(enden)m(t)f(data)i(con)m(v)m(ersion) g(or)e(b)m(yte)i(sw)m(apping,)f(except)h(that)f(con)m(v)m(ersion)h (to/from)f(ASCI)s(I)0 4355 y(format)d(is)g(p)s(erformed)e(b)m(y)h(the)h (FTGTBS)f(and)g(FTPTBS)g(routines)h(on)f(mac)m(hines)h(whic)m(h)g(do)f (not)h(use)f(ASCI)s(I)0 4468 y(c)m(haracter)j(co)s(des)e(in)g(the)h(in) m(ternal)g(data)g(represen)m(tations)h(\(e.g.,)g(on)e(IBM)h(mainframe)f (computers\).)0 4733 y Fi(1)81 b Fj(Read)26 b(a)h(consecutiv)m(e)h (string)f(of)f(c)m(haracters)i(from)e(an)g(ASCI)s(I)f(table)i(in)m(to)h (a)e(c)m(haracter)i(v)-5 b(ariable)28 b(\(spanning)227 4845 y(columns)k(and)g(m)m(ultiple)h(ro)m(ws)f(if)g(necessary\))h(This) f(routine)g(should)f(not)i(b)s(e)e(used)h(with)g(binary)f(tables)227 4958 y(b)s(ecause)g(of)f(complications)i(related)g(to)f(passing)f (string)g(v)-5 b(ariables)31 b(b)s(et)m(w)m(een)g(C)f(and)g(F)-8 b(ortran.)382 5223 y Ff(FTGTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(string,status\))0 5488 y Fi(2)81 b Fj(W)-8 b(rite)31 b(a)g(consecutiv)m(e)h(string)e(of)h(c)m(haracters)g(to)g(an)f(ASCI)s (I)f(table)i(from)f(a)h(c)m(haracter)h(v)-5 b(ariable)31 b(\(spanning)227 5601 y(columns)h(and)g(m)m(ultiple)h(ro)m(ws)f(if)g (necessary\))h(This)f(routine)g(should)f(not)i(b)s(e)e(used)h(with)g (binary)f(tables)227 5714 y(b)s(ecause)g(of)f(complications)i(related)g (to)f(passing)f(string)g(v)-5 b(ariables)31 b(b)s(et)m(w)m(een)g(C)f (and)g(F)-8 b(ortran.)p eop end %%Page: 59 65 TeXDict begin 59 64 bop 0 299 a Fh(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fj(59)382 555 y Ff(FTPTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,s)o(tri)o(ng,)41 b(>)48 b(status\))0 797 y Fi(3)81 b Fj(Read)27 b(a)h(consecutiv)m(e)i (arra)m(y)e(of)g(b)m(ytes)g(from)f(an)g(ASCI)s(I)f(or)i(binary)e(table) j(in)m(to)f(a)g(n)m(umeric)g(v)-5 b(ariable)28 b(\(span-)227 910 y(ning)k(columns)f(and)h(m)m(ultiple)g(ro)m(ws)g(if)g(necessary\).) 46 b(The)32 b(arra)m(y)g(parameter)g(ma)m(y)h(b)s(e)e(declared)h(as)h (an)m(y)227 1023 y(n)m(umerical)i(datat)m(yp)s(e)g(as)g(long)g(as)g (the)f(arra)m(y)h(is)f(at)h(least)h('nc)m(hars')f(b)m(ytes)f(long,)j (e.g.,)f(if)f(nc)m(hars)f(=)g(17,)227 1136 y(then)c(declare)i(the)e (arra)m(y)h(as)g(INTEGER*4)g(ARRA)-8 b(Y\(5\).)382 1379 y Ff(FTGTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(array,status\))0 1621 y Fi(4)81 b Fj(W)-8 b(rite)32 b(a)f(consecutiv)m(e)i(arra)m(y)f(of)f(b)m(ytes)g(to)h(an)e(ASCI)s(I)g (or)h(binary)f(table)i(from)e(a)i(n)m(umeric)e(v)-5 b(ariable)32 b(\(span-)227 1734 y(ning)j(columns)f(and)g(m)m(ultiple)h(ro)m(ws)g(if) f(necessary\))i(The)e(arra)m(y)h(parameter)g(ma)m(y)h(b)s(e)e(declared) h(as)g(an)m(y)227 1847 y(n)m(umerical)g(datat)m(yp)s(e)g(as)g(long)g (as)g(the)f(arra)m(y)h(is)f(at)h(least)h('nc)m(hars')f(b)m(ytes)f (long,)j(e.g.,)f(if)f(nc)m(hars)f(=)g(17,)227 1960 y(then)c(declare)i (the)e(arra)m(y)h(as)g(INTEGER*4)g(ARRA)-8 b(Y\(5\).)382 2202 y Ff(FTPTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,a)o(rra)o(y,)42 b(>)47 b(status\))0 2490 y Fc(6.7.3)112 b(Edit)37 b(Ro)m(ws)g(or)h (Columns)0 2696 y Fi(1)81 b Fj(Insert)26 b(blank)h(ro)m(ws)h(in)m(to)g (an)f(existing)h(ASCI)s(I)e(or)h(binary)g(table)h(\(in)g(the)f(CDU\).)h (All)g(the)g(ro)m(ws)f(F)m(OLLO)m(W-)227 2809 y(ING)35 b(ro)m(w)g(FR)m(O)m(W)g(are)g(shifted)f(do)m(wn)g(b)m(y)h(NR)m(O)m(WS)g (ro)m(ws.)53 b(If)34 b(FR)m(O)m(W)i(or)e(FR)m(O)m(WLL)i(equals)e(0)h (then)227 2922 y(the)27 b(blank)f(ro)m(ws)h(are)g(inserted)f(at)h(the)g (b)s(eginning)f(of)g(the)h(table.)41 b(These)26 b(routines)g(mo)s(dify) g(the)h(NAXIS2)227 3035 y(k)m(eyw)m(ord)35 b(to)h(re\015ect)f(the)g (new)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)g(in)f(the)h(table.)54 b(Note)36 b(that)f(it)h(is)e(*not*)i(necessary)f(to)227 3147 y(insert)c(ro)m(ws)f(in)g(a)h(table)g(b)s(efore)f(writing)g(data)i (to)f(those)g(ro)m(ws)f(\(indeed,)g(it)h(w)m(ould)g(b)s(e)e (ine\016cien)m(t)j(to)f(do)227 3260 y(so\).)54 b(Instead,)35 b(one)g(ma)m(y)g(simply)f(write)h(data)g(to)g(an)m(y)g(ro)m(w)f(of)h (the)g(table,)h(whether)e(that)h(ro)m(w)g(of)f(data)227 3373 y(already)d(exists)g(or)g(not.)382 3616 y Ff (FTIROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 3729 y(FTIROWLL\(unit,frowll,nro)o(wsl)o(l,)42 b(>)47 b(status\))0 3971 y Fi(2)81 b Fj(Delete)25 b(ro)m(ws)f(from)f(an)g(existing)i(ASCI)s (I)c(or)j(binary)f(table)h(\(in)f(the)h(CDU\).)g(The)f(NR)m(O)m(WS)h (\(or)g(NR)m(O)m(WSLL\))227 4084 y(is)e(the)g(n)m(um)m(b)s(er)f(of)h (ro)m(ws)g(are)g(deleted,)i(starting)f(with)f(ro)m(w)g(FR)m(O)m(W)h (\(or)f(FR)m(O)m(WLL\),)h(and)f(an)m(y)g(remaining)227 4197 y(ro)m(ws)f(in)g(the)f(table)i(are)f(shifted)g(up)e(to)j(\014ll)f (in)f(the)h(space.)38 b(These)21 b(routines)f(mo)s(dify)g(the)h(NAXIS2) g(k)m(eyw)m(ord)227 4310 y(to)31 b(re\015ect)g(the)g(new)f(n)m(um)m(b)s (er)f(of)h(ro)m(ws)h(in)f(the)g(table.)382 4552 y Ff (FTDROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 4665 y(FTDROWLL\(unit,frowll,nro)o(wsl)o(l,)42 b(>)47 b(status\))0 4907 y Fi(3)81 b Fj(Delete)26 b(a)f(list)g(of)g(ro)m(ws)f(from)g(an)h (ASCI)s(I)e(or)h(binary)g(table)h(\(in)g(the)f(CDU\).)i(In)e(the)g (\014rst)g(routine,)i('ro)m(wrange')227 5020 y(is)i(a)g(c)m(haracter)h (string)f(listing)h(the)f(ro)m(ws)f(or)h(ro)m(w)g(ranges)g(to)g(delete) h(\(e.g.,)i('2-4,)e(5,)g(8-9'\).)42 b(In)27 b(the)h(second)227 5133 y(routine,)37 b('ro)m(wlist')f(is)f(an)f(in)m(teger)j(arra)m(y)e (of)g(ro)m(w)g(n)m(um)m(b)s(ers)e(to)j(b)s(e)e(deleted)i(from)e(the)h (table.)56 b(nro)m(ws)34 b(is)227 5246 y(the)e(n)m(um)m(b)s(er)e(of)h (ro)m(w)h(n)m(um)m(b)s(ers)e(in)h(the)g(list.)45 b(The)31 b(\014rst)f(ro)m(w)i(in)f(the)g(table)i(is)e(1)h(not)f(0.)44 b(The)31 b(list)h(of)g(ro)m(w)227 5359 y(n)m(um)m(b)s(ers)d(m)m(ust)h (b)s(e)g(sorted)h(in)f(ascending)g(order.)382 5601 y Ff(FTDRRG\(unit,rowrange,)42 b(>)47 b(status\))382 5714 y(FTDRWS\(unit,rowlist,nrow)o(s,)41 b(>)48 b(status\))p eop end %%Page: 60 66 TeXDict begin 60 65 bop 0 299 a Fj(60)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(4)81 b Fj(Insert)43 b(a)i(blank)f(column)h (\(or)f(columns\))h(in)m(to)g(an)f(existing)i(ASCI)s(I)d(or)h(binary)g (table)h(\(in)g(the)f(CDU\).)227 668 y(COLNUM)c(sp)s(eci\014es)g(the)h (column)f(n)m(um)m(b)s(er)f(that)i(the)f(\(\014rst\))g(new)g(column)g (should)f(o)s(ccup)m(y)i(in)f(the)227 781 y(table.)58 b(NCOLS)34 b(sp)s(eci\014es)h(ho)m(w)h(man)m(y)g(columns)f(are)h(to)g (b)s(e)f(inserted.)57 b(An)m(y)35 b(existing)i(columns)e(from)227 894 y(this)k(p)s(osition)f(and)g(higher)g(are)h(mo)m(v)m(ed)g(o)m(v)m (er)h(to)f(allo)m(w)h(ro)s(om)e(for)h(the)f(new)g(column\(s\).)65 b(The)38 b(index)227 1007 y(n)m(um)m(b)s(er)j(on)h(all)h(the)f(follo)m (wing)h(k)m(eyw)m(ords)g(will)f(b)s(e)f(incremen)m(ted)i(if)f (necessary)g(to)h(re\015ect)f(the)g(new)227 1120 y(p)s(osition)32 b(of)f(the)g(column\(s\))h(in)f(the)g(table:)43 b(TBCOLn,)30 b(TF)m(ORMn,)i(TTYPEn,)e(TUNITn,)h(TNULLn,)227 1233 y(TSCALn,)22 b(TZER)m(On,)g(TDISPn,)g(TDIMn,)h(TLMINn,)g(TLMAXn,)f(TDMINn,)i (TDMAXn,)f(TCTYPn,)227 1346 y(TCRPXn,)30 b(TCR)-10 b(VLn,)29 b(TCDL)-8 b(Tn,)30 b(TCR)m(OTn,)f(and)g(TCUNIn.)382 1584 y Ff(FTICOL\(unit,colnum,ttype)o(,tf)o(orm,)41 b(>)48 b(status\))382 1697 y(FTICLS\(unit,colnum,ncols)o(,tt)o(ype,)o(tfor)o (m,)41 b(>)48 b(status\))0 1935 y Fi(5)81 b Fj(Mo)s(dify)37 b(the)g(v)m(ector)i(length)f(of)f(a)h(binary)e(table)i(column)f (\(e.g.,)k(c)m(hange)e(a)e(column)g(from)g(TF)m(ORMn)g(=)227 2048 y('1E')31 b(to)h('20E'\).)g(The)e(v)m(ector)i(length)e(ma)m(y)h(b) s(e)f(increased)h(or)f(decreased)h(from)f(the)g(curren)m(t)h(v)-5 b(alue.)382 2287 y Ff(FTMVEC\(unit,colnum,newve)o(cle)o(n,)42 b(>)47 b(status\))0 2525 y Fi(6)81 b Fj(Delete)29 b(a)f(column)g(from)f (an)g(existing)i(ASCI)s(I)d(or)i(binary)e(table)j(\(in)f(the)f(CDU\).)i (The)e(index)g(n)m(um)m(b)s(er)f(of)i(all)227 2638 y(the)k(k)m(eyw)m (ords)h(listed)f(ab)s(o)m(v)m(e)i(\(for)e(FTICOL\))f(will)h(b)s(e)g (decremen)m(ted)g(if)g(necessary)h(to)g(re\015ect)f(the)g(new)227 2751 y(p)s(osition)26 b(of)g(the)g(column\(s\))g(in)f(the)h(table.)40 b(Those)26 b(index)f(k)m(eyw)m(ords)h(that)g(refer)f(to)i(the)f (deleted)g(column)227 2864 y(will)33 b(also)g(b)s(e)f(deleted.)47 b(Note)33 b(that)g(the)g(ph)m(ysical)g(size)g(of)f(the)h(FITS)e(\014le) i(will)f(not)h(b)s(e)e(reduced)h(b)m(y)g(this)227 2977 y(op)s(eration,)e(and)e(the)h(empt)m(y)g(FITS)f(blo)s(c)m(ks)h(if)g(an) m(y)g(at)g(the)g(end)f(of)h(the)g(\014le)g(will)g(b)s(e)f(padded)g (with)g(zeros.)382 3216 y Ff(FTDCOL\(unit,colnum,)42 b(>)48 b(status\))0 3454 y Fi(7)81 b Fj(Cop)m(y)30 b(a)g(column)g(from) g(one)g(HDU)h(to)g(another)f(\(or)h(to)g(the)f(same)h(HDU\).)g(If)f (createcol)j(=)c(TR)m(UE,)i(then)f(a)227 3567 y(new)20 b(column)g(will)h(b)s(e)f(inserted)g(in)g(the)h(output)f(table,)k(at)d (p)s(osition)f(`outcolumn',)j(otherwise)e(the)g(existing)227 3680 y(output)29 b(column)f(will)h(b)s(e)f(o)m(v)m(erwritten)i(\(in)f (whic)m(h)f(case)i(it)f(m)m(ust)f(ha)m(v)m(e)i(a)f(compatible)h(datat)m (yp)s(e\).)42 b(Note)227 3793 y(that)31 b(the)g(\014rst)e(column)i(in)f (a)g(table)i(is)e(at)h(coln)m(um)g(=)f(1.)382 4031 y Ff(FTCPCL\(inunit,outunit,in)o(col)o(num,)o(outc)o(oln)o(um,c)o(reat)o (eco)o(l,)42 b(>)47 b(status\);)0 4319 y Fc(6.7.4)112 b(Read)38 b(and)h(W)-9 b(rite)36 b(Column)j(Data)e(Routines)0 4538 y Fj(These)22 b(subroutines)f(put)h(or)g(get)i(data)f(v)-5 b(alues)22 b(in)g(the)h(curren)m(t)f(ASCI)s(I)f(or)h(Binary)g(table)i (extension.)38 b(Automatic)0 4650 y(data)21 b(t)m(yp)s(e)g(con)m(v)m (ersion)g(is)f(p)s(erformed)f(for)h(n)m(umerical)h(data)g(t)m(yp)s(es)g (\(B,I,J,E,D\))h(if)e(the)h(data)g(t)m(yp)s(e)f(of)h(the)f(column)0 4763 y(\(de\014ned)32 b(b)m(y)i(the)f(TF)m(ORM)h(k)m(eyw)m(ord\))g (di\013ers)f(from)f(the)i(data)g(t)m(yp)s(e)f(of)h(the)f(calling)i (subroutine.)48 b(The)33 b(data)0 4876 y(v)-5 b(alues)30 b(are)h(also)g(scaled)f(b)m(y)g(the)g(TSCALn)f(and)g(TZER)m(On)g (header)h(v)-5 b(alues)30 b(as)g(they)g(are)h(b)s(eing)e(written)h(to)h (or)0 4989 y(read)j(from)f(the)h(FITS)f(arra)m(y)-8 b(.)51 b(The)33 b(fttscl)i(subroutine)d(MUST)i(b)s(e)f(used)g(to)h(de\014ne)f (the)h(scaling)h(parameters)0 5102 y(when)d(writing)h(data)h(to)g(the)f (table)h(or)f(to)h(o)m(v)m(erride)g(the)g(default)f(scaling)h(v)-5 b(alues)34 b(giv)m(en)g(in)f(the)g(header)g(when)0 5215 y(reading)27 b(from)g(the)g(table.)40 b(Note)29 b(that)e(it)h(is)f (*not*)h(necessary)f(to)h(insert)f(ro)m(ws)g(in)f(a)i(table)g(b)s (efore)e(writing)h(data)0 5328 y(to)j(those)h(ro)m(ws)e(\(indeed,)h(it) g(w)m(ould)g(b)s(e)f(ine\016cien)m(t)i(to)f(do)g(so\).)41 b(Instead,)30 b(one)g(ma)m(y)g(simply)f(write)h(data)g(to)h(an)m(y)0 5441 y(ro)m(w)f(of)h(the)g(table,)g(whether)f(that)h(ro)m(w)f(of)h (data)g(already)g(exists)g(or)f(not.)0 5601 y(In)i(the)i(case)g(of)f (binary)g(tables)h(with)f(v)m(ector)h(elemen)m(ts,)i(the)d('felem')h (parameter)g(de\014nes)e(the)i(starting)g(pixel)0 5714 y(within)k(the)g(elemen)m(t)i(v)m(ector.)65 b(This)38 b(parameter)g(is)g(ignored)h(with)e(ASCI)s(I)g(tables.)65 b(Similarly)-8 b(,)41 b(in)d(the)g(case)p eop end %%Page: 61 67 TeXDict begin 61 66 bop 0 299 a Fh(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fj(61)0 555 y(of)45 b(binary)e(tables)i(the)g('nelemen)m(ts')h(parameter)f(sp)s(eci\014es)f (the)g(total)i(n)m(um)m(b)s(er)d(of)i(v)m(ector)h(v)-5 b(alues)45 b(read)f(or)0 668 y(written)36 b(\(con)m(tin)m(uing)h(on)f (subsequen)m(t)f(ro)m(ws)g(if)h(required\))f(and)h(not)g(the)g(n)m(um)m (b)s(er)e(of)i(table)h(elemen)m(ts.)58 b(Tw)m(o)0 781 y(sets)36 b(of)f(subroutines)g(are)g(pro)m(vided)g(to)i(get)f(the)g (column)f(data)h(whic)m(h)f(di\013er)g(in)h(the)f(w)m(a)m(y)i (unde\014ned)c(pixels)0 894 y(are)f(handled.)42 b(The)31 b(\014rst)g(set)h(of)f(routines)h(\(FTGCV\))g(simply)f(return)f(an)h (arra)m(y)h(of)f(data)h(elemen)m(ts)h(in)e(whic)m(h)0 1007 y(unde\014ned)41 b(pixels)j(are)g(set)g(equal)g(to)h(a)f(v)-5 b(alue)44 b(sp)s(eci\014ed)f(b)m(y)g(the)h(user)f(in)g(the)h('n)m(ullv) -5 b(al')44 b(parameter.)81 b(An)0 1120 y(additional)44 b(feature)g(of)g(these)g(subroutines)e(is)i(that)g(if)f(the)h(user)e (sets)i(n)m(ullv)-5 b(al)44 b(=)f(0,)48 b(then)43 b(no)g(c)m(hec)m(ks)i (for)0 1233 y(unde\014ned)33 b(pixels)j(will)g(b)s(e)e(p)s(erformed,)i (th)m(us)f(increasing)h(the)g(sp)s(eed)e(of)i(the)g(program.)55 b(The)35 b(second)h(set)g(of)0 1346 y(routines)h(\(FTGCF\))h(returns)d (the)i(data)h(elemen)m(t)g(arra)m(y)g(and)e(in)h(addition)g(a)g (logical)j(arra)m(y)d(of)g(\015ags)g(whic)m(h)0 1458 y(de\014nes)29 b(whether)h(the)h(corresp)s(onding)e(data)i(pixel)g(is)f (unde\014ned.)0 1619 y(An)m(y)41 b(column,)i(regardless)e(of)g(it's)g (in)m(trinsic)g(datat)m(yp)s(e,)k(ma)m(y)c(b)s(e)f(read)h(as)g(a)g (string.)71 b(It)41 b(should)f(b)s(e)g(noted)0 1732 y(ho)m(w)m(ev)m(er) 32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)f(string)h(is)f (10)h(-)g(100)g(times)g(slo)m(w)m(er)h(than)e(reading)g(the)h(same)0 1844 y(column)g(as)h(a)g(n)m(um)m(b)s(er)e(due)h(to)h(the)g(large)h(o)m (v)m(erhead)f(in)g(constructing)g(the)g(formatted)g(strings.)44 b(The)31 b(displa)m(y)0 1957 y(format)26 b(of)g(the)h(returned)d (strings)i(will)g(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m (ord,)j(if)d(it)i(exists,)h(otherwise)e(b)m(y)0 2070 y(the)i(datat)m(yp)s(e)h(of)g(the)f(column.)40 b(The)28 b(length)g(of)h(the)f(returned)f(strings)h(can)g(b)s(e)g(determined)g (with)f(the)i(ftgcdw)0 2183 y(routine.)41 b(The)30 b(follo)m(wing)h (TDISPn)f(displa)m(y)g(formats)h(are)f(curren)m(tly)h(supp)s(orted:)191 2403 y Ff(Iw.m)142 b(Integer)191 2516 y(Ow.m)g(Octal)46 b(integer)191 2629 y(Zw.m)142 b(Hexadecimal)45 b(integer)191 2742 y(Fw.d)142 b(Fixed)46 b(floating)g(point)191 2854 y(Ew.d)142 b(Exponential)45 b(floating)g(point)191 2967 y(Dw.d)142 b(Exponential)45 b(floating)g(point)191 3080 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)d(not)j (lost,)g(else)f(Ew.d)0 3300 y Fj(where)37 b(w)h(is)g(the)g(width)f(in)h (c)m(haracters)h(of)f(the)h(displa)m(y)m(ed)f(v)-5 b(alues,)41 b(m)c(is)h(the)g(minim)m(um)g(n)m(um)m(b)s(er)e(of)i(digits)0 3413 y(displa)m(y)m(ed,)31 b(and)f(d)g(is)g(the)h(n)m(um)m(b)s(er)e(of) h(digits)h(to)g(the)g(righ)m(t)g(of)g(the)f(decimal.)42 b(The)30 b(.m)g(\014eld)g(is)g(optional.)0 3632 y Fi(1)81 b Fj(Put)30 b(elemen)m(ts)i(in)m(to)g(an)e(ASCI)s(I)f(or)i(binary)f (table)i(column)e(\(in)h(the)g(CDU\).)g(\(The)g(SPP)f(FSPCLS)f(routine) 227 3745 y(has)38 b(an)f(additional)i(in)m(teger)g(argumen)m(t)f(after) h(the)f(V)-10 b(ALUES)37 b(c)m(haracter)i(string)f(whic)m(h)f(sp)s (eci\014es)h(the)227 3858 y(size)31 b(of)g(the)g(1st)g(dimension)e(of)i (this)f(2-D)i(CHAR)e(arra)m(y\).)227 4002 y(The)24 b(alternate)i(v)m (ersion)f(of)g(these)g(routines,)h(whose)e(names)g(end)g(in)g('LL')h (after)g(the)g(datat)m(yp)s(e)g(c)m(haracter,)227 4115 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f(then)h(2*31)h(ro)m (ws.)57 b(When)35 b(calling)i(these)f(routines,)h(the)f(fro)m(w)g(and) 227 4228 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s(e)f(64-bit)h(in)m (teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g(normal)f(4-b)m(yte)i (in)m(tegers.)382 4447 y Ff(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o (row,)o(fel)o(em,n)o(elem)o(ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))382 4560 y(FTPCL[LBIJKEDCM]LL\(unit,)o(col)o(num,)o (frow)o(,fe)o(lem,)o(nele)o(men)o(ts,v)o(alue)o(s,)41 b(>)48 b(status\))0 4780 y Fi(2)81 b Fj(Put)29 b(elemen)m(ts)i(in)m(to) g(an)f(ASCI)s(I)e(or)i(binary)f(table)i(column)e(\(in)h(the)g(CDU\))g (substituting)g(the)g(appropriate)227 4893 y(FITS)c(n)m(ull)g(v)-5 b(alue)26 b(for)g(an)m(y)h(elemen)m(ts)g(that)g(are)f(equal)h(to)g (NULL)-10 b(V)g(AL.)26 b(F)-8 b(or)27 b(ASCI)s(I)e(T)-8 b(ABLE)26 b(extensions,)227 5006 y(the)31 b(n)m(ull)f(v)-5 b(alue)31 b(de\014ned)e(b)m(y)h(the)g(previous)g(call)i(to)f(FTSNUL)f (will)g(b)s(e)g(substituted;)g(F)-8 b(or)31 b(in)m(teger)h(FITS)227 5119 y(columns,)39 b(in)e(a)h(binary)f(table)h(the)f(n)m(ull)h(v)-5 b(alue)37 b(de\014ned)g(b)m(y)g(the)g(previous)g(call)i(to)f(FTTNUL)f (will)h(b)s(e)227 5232 y(substituted;)28 b(F)-8 b(or)28 b(\015oating)h(p)s(oin)m(t)e(FITS)f(columns)h(a)h(sp)s(ecial)g(IEEE)f (NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)28 b(will)227 5344 y(b)s(e)i(substituted.)227 5488 y(The)24 b(alternate)i(v)m(ersion) f(of)g(these)g(routines,)h(whose)e(names)g(end)g(in)g('LL')h(after)g (the)g(datat)m(yp)s(e)g(c)m(haracter,)227 5601 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f(then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h(the)f(fro)m(w)g(and)227 5714 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s(e)f(64-bit)h(in)m (teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g(normal)f(4-b)m(yte)i (in)m(tegers.)p eop end %%Page: 62 68 TeXDict begin 62 67 bop 0 299 a Fj(62)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTPCN[SBIJKED]\(unit,coln)o(um,)o(frow)o (,fel)o(em,)o(nele)o(ment)o(s,v)o(alue)o(s,nu)o(llv)o(al)42 b(>)47 b(status\))382 668 y(FTPCN[SBIJKED]LL\(unit,co)o(lnu)o(m,\(I)o (*8\))41 b(frow,\(I*8\))k(felem,nelements,values,)764 781 y(nullval)g(>)j(status\))0 1009 y Fi(3)81 b Fj(Put)37 b(bit)h(v)-5 b(alues)38 b(in)m(to)h(a)f(binary)f(b)m(yte)h(\('B'\))i (or)d(bit)h(\('X'\))h(table)g(column)f(\(in)f(the)h(CDU\).)h(LRA)-8 b(Y)38 b(is)g(an)227 1122 y(arra)m(y)c(of)g(logical)h(v)-5 b(alues)34 b(corresp)s(onding)e(to)i(the)g(sequence)f(of)h(bits)f(to)h (b)s(e)f(written.)49 b(If)33 b(LRA)-8 b(Y)34 b(is)f(true)227 1235 y(then)f(the)g(corresp)s(onding)f(bit)h(is)g(set)g(to)h(1,)g (otherwise)f(the)g(bit)g(is)g(set)h(to)g(0.)45 b(Note)34 b(that)e(in)g(the)g(case)h(of)227 1348 y('X')g(columns,)g(FITSIO)e (will)i(write)f(to)h(all)g(8)g(bits)f(of)g(eac)m(h)i(b)m(yte)f(whether) e(they)i(are)g(formally)f(v)-5 b(alid)33 b(or)227 1460 y(not.)46 b(Th)m(us)31 b(if)h(the)g(column)g(is)f(de\014ned)g(as)h ('4X',)i(and)d(one)h(calls)h(FTPCLX)f(with)f(fbit=1)h(and)f(n)m(bit=8,) 227 1573 y(then)j(all)h(8)f(bits)g(will)g(b)s(e)f(written)h(in)m(to)h (the)f(\014rst)g(b)m(yte)g(\(as)h(opp)s(osed)e(to)i(writing)e(the)i (\014rst)e(4)h(bits)g(in)m(to)227 1686 y(the)d(\014rst)f(ro)m(w)g(and)g (then)g(the)h(next)f(4)h(bits)f(in)m(to)i(the)e(next)h(ro)m(w\),)g(ev)m (en)g(though)f(the)h(last)g(4)g(bits)f(of)h(eac)m(h)227 1799 y(b)m(yte)g(are)g(formally)g(not)g(de\014ned.)382 2027 y Ff(FTPCLX\(unit,colnum,frow,)o(fbi)o(t,nb)o(it,l)o(ray)o(,)42 b(>)47 b(status\))0 2255 y Fi(4)81 b Fj(Set)30 b(table)h(elemen)m(ts)h (in)e(a)h(column)f(as)h(unde\014ned)382 2482 y Ff (FTPCLU\(unit,colnum,frow,)o(fel)o(em,n)o(elem)o(ent)o(s,)42 b(>)47 b(status\))0 2710 y Fi(5)81 b Fj(Get)34 b(elemen)m(ts)g(from)f (an)g(ASCI)s(I)f(or)h(binary)g(table)h(column)f(\(in)g(the)g(CDU\).)i (These)e(routines)g(return)f(the)227 2823 y(v)-5 b(alues)30 b(of)g(the)g(table)h(column)f(arra)m(y)g(elemen)m(ts.)42 b(Unde\014ned)28 b(arra)m(y)j(elemen)m(ts)g(will)f(b)s(e)f(returned)g (with)h(a)227 2936 y(v)-5 b(alue)26 b(=)g(n)m(ullv)-5 b(al,)27 b(unless)e(n)m(ullv)-5 b(al)26 b(=)f(0)h(\(or)g(=)f(')h(')g (for)f(ftgcvs\))i(in)e(whic)m(h)g(case)i(no)e(c)m(hec)m(king)j(for)d (unde\014ned)227 3049 y(v)-5 b(alues)28 b(will)g(b)s(e)f(p)s(erformed.) 39 b(The)27 b(ANYF)h(parameter)g(is)g(set)g(to)g(true)g(if)g(an)m(y)f (of)h(the)g(returned)f(elemen)m(ts)227 3162 y(are)f(unde\014ned.)37 b(\(Note:)i(the)26 b(ftgcl)g(routine)f(simple)g(gets)h(an)g(arra)m(y)f (of)g(logical)j(data)e(v)-5 b(alues)25 b(without)h(an)m(y)227 3275 y(c)m(hec)m(ks)39 b(for)e(unde\014ned)e(v)-5 b(alues;)41 b(use)c(the)g(ftgc\015)h(routine)f(to)h(c)m(hec)m(k)g(for)f (unde\014ned)e(logical)40 b(elemen)m(ts\).)227 3388 y(\(The)29 b(SPP)f(FSGCVS)g(routine)g(has)h(an)f(additional)i(in)m(teger)g (argumen)m(t)f(after)g(the)g(V)-10 b(ALUES)28 b(c)m(haracter)227 3501 y(string)j(whic)m(h)f(sp)s(eci\014es)g(the)g(size)i(of)e(the)h (1st)g(dimension)e(of)i(this)f(2-D)i(CHAR)e(arra)m(y\).)227 3646 y(The)24 b(alternate)i(v)m(ersion)f(of)g(these)g(routines,)h (whose)e(names)g(end)g(in)g('LL')h(after)g(the)g(datat)m(yp)s(e)g(c)m (haracter,)227 3758 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f (then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h (the)f(fro)m(w)g(and)227 3871 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s (e)f(64-bit)h(in)m(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g (normal)f(4-b)m(yte)i(in)m(tegers.)382 4099 y Ff (FTGCL\(unit,colnum,frow,f)o(ele)o(m,ne)o(leme)o(nts)o(,)42 b(>)47 b(values,status\))382 4212 y(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o (m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o(nts)o(,nul)o(lval)o(,)42 b(>)1098 4325 y(values,anyf,status\))382 4438 y (FTGCV[BIJKEDCM]LL\(unit,c)o(oln)o(um,\()o(I*8\))f(frow,)46 b(\(I*8\))h(felem,)f(nelements,)716 4551 y(nullval,)f(>)j (values,anyf,status\))0 4779 y Fi(6)81 b Fj(Get)44 b(elemen)m(ts)h(and) d(n)m(ull)i(\015ags)f(from)g(an)h(ASCI)s(I)d(or)j(binary)e(table)j (column)e(\(in)g(the)h(CHDU\).)g(These)227 4891 y(routines)29 b(return)e(the)i(v)-5 b(alues)29 b(of)g(the)g(table)h(column)e(arra)m (y)i(elemen)m(ts.)41 b(An)m(y)29 b(unde\014ned)d(arra)m(y)k(elemen)m (ts)227 5004 y(will)37 b(ha)m(v)m(e)h(the)f(corresp)s(onding)f(\015agv) -5 b(als)37 b(elemen)m(t)i(set)e(equal)g(to)h(.TR)m(UE.)f(The)f(ANYF)i (parameter)f(is)227 5117 y(set)30 b(to)g(true)g(if)f(an)m(y)h(of)f(the) h(returned)e(elemen)m(ts)j(are)f(unde\014ned.)38 b(\(The)29 b(SPP)f(FSGCFS)h(routine)h(has)f(an)227 5230 y(additional)e(in)m(teger) h(argumen)m(t)e(after)h(the)f(V)-10 b(ALUES)26 b(c)m(haracter)i(string) e(whic)m(h)f(sp)s(eci\014es)h(the)h(size)f(of)h(the)227 5343 y(1st)k(dimension)f(of)h(this)f(2-D)h(CHAR)g(arra)m(y\).)227 5488 y(The)24 b(alternate)i(v)m(ersion)f(of)g(these)g(routines,)h (whose)e(names)g(end)g(in)g('LL')h(after)g(the)g(datat)m(yp)s(e)g(c)m (haracter,)227 5601 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f (then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h (the)f(fro)m(w)g(and)227 5714 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s (e)f(64-bit)h(in)m(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g (normal)f(4-b)m(yte)i(in)m(tegers.)p eop end %%Page: 63 69 TeXDict begin 63 68 bop 0 299 a Fh(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fj(63)382 555 y Ff(FTGCF[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem) o(ent)o(s,)42 b(>)1193 668 y(values,flagvals,anyf,stat)o(us\))382 781 y(FTGCF[BIJKED]LL\(unit,col)o(num)o(,)g(\(I*8\))k(frow,)h(\(I*8\))f (felem,nelements,)d(>)1193 894 y(values,flagvals,anyf,stat)o(us\))0 1131 y Fi(7)81 b Fj(Get)29 b(an)f(arbitrary)g(data)h(subsection)f(from) g(an)g(N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h (column.)227 1244 y(Unde\014ned)k(pixels)h(in)g(the)h(arra)m(y)g(will)f (b)s(e)g(set)h(equal)f(to)h(the)g(v)-5 b(alue)36 b(of)f('n)m(ullv)-5 b(al',)38 b(unless)c(n)m(ullv)-5 b(al=0)36 b(in)227 1357 y(whic)m(h)d(case)i(no)e(testing)i(for)e(unde\014ned)e(pixels)j(will)f (b)s(e)g(p)s(erformed.)49 b(The)32 b(\014rst)h(and)g(last)h(ro)m(ws)g (in)f(the)227 1470 y(table)28 b(to)f(b)s(e)f(read)g(are)h(sp)s (eci\014ed)e(b)m(y)i(fpixels\(naxis+1\))g(and)f(lpixels\(naxis+1\),)j (and)d(hence)g(are)h(treated)227 1582 y(as)f(the)f(next)h(higher)f (dimension)g(of)g(the)h(FITS)e(N-dimensional)i(arra)m(y)-8 b(.)40 b(The)25 b(INCS)f(parameter)i(sp)s(eci\014es)227 1695 y(the)31 b(sampling)f(in)m(terv)-5 b(al)32 b(in)e(eac)m(h)h (dimension)f(b)s(et)m(w)m(een)h(the)g(data)g(elemen)m(ts)g(that)g(will) g(b)s(e)f(returned.)382 1932 y Ff(FTGSV[BIJKED]\(unit,colnu)o(m,n)o (axis)o(,nax)o(es,)o(fpix)o(els,)o(lpi)o(xels)o(,inc)o(s,n)o(ullv)o (al,)41 b(>)1002 2045 y(array,anyf,status\))0 2282 y Fi(8)81 b Fj(Get)29 b(an)f(arbitrary)g(data)h(subsection)f(from)g(an)g (N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h (column.)227 2395 y(An)m(y)39 b(Unde\014ned)e(pixels)i(in)g(the)g(arra) m(y)g(will)g(ha)m(v)m(e)h(the)f(corresp)s(onding)f('\015agv)-5 b(als')40 b(elemen)m(t)g(set)f(equal)227 2508 y(to)d(.TR)m(UE.)f(The)f (\014rst)g(and)g(last)i(ro)m(ws)f(in)f(the)h(table)h(to)f(b)s(e)g(read) f(are)h(sp)s(eci\014ed)f(b)m(y)h(fpixels\(naxis+1\))227 2621 y(and)k(lpixels\(naxis+1\),)k(and)38 b(hence)i(are)f(treated)i(as) e(the)g(next)h(higher)f(dimension)f(of)i(the)f(FITS)g(N-)227 2734 y(dimensional)g(arra)m(y)-8 b(.)66 b(The)38 b(INCS)g(parameter)h (sp)s(eci\014es)f(the)g(sampling)h(in)m(terv)-5 b(al)40 b(in)e(eac)m(h)i(dimension)227 2847 y(b)s(et)m(w)m(een)31 b(the)g(data)g(elemen)m(ts)h(that)f(will)f(b)s(e)g(returned.)382 3084 y Ff(FTGSF[BIJKED]\(unit,colnu)o(m,n)o(axis)o(,nax)o(es,)o(fpix)o (els,)o(lpi)o(xels)o(,inc)o(s,)41 b(>)1002 3197 y (array,flagvals,anyf,statu)o(s\))0 3433 y Fi(9)81 b Fj(Get)33 b(bit)g(v)-5 b(alues)34 b(from)e(a)h(b)m(yte)h(\('B'\))g(or)f(bit)g (\(`X`\))h(table)g(column)f(\(in)g(the)g(CDU\).)g(LRA)-8 b(Y)34 b(is)f(an)f(arra)m(y)i(of)227 3546 y(logical)41 b(v)-5 b(alues)39 b(corresp)s(onding)f(to)h(the)g(sequence)f(of)h(bits) g(to)g(b)s(e)f(read.)65 b(If)38 b(LRA)-8 b(Y)39 b(is)f(true)h(then)f (the)227 3659 y(corresp)s(onding)c(bit)g(w)m(as)g(set)h(to)g(1,)h (otherwise)f(the)f(bit)h(w)m(as)f(set)h(to)g(0.)53 b(Note)35 b(that)g(in)f(the)h(case)g(of)f('X')227 3772 y(columns,)41 b(FITSIO)d(will)h(read)f(all)i(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)f (whether)f(they)h(are)g(formally)h(v)-5 b(alid)39 b(or)f(not.)227 3885 y(Th)m(us)c(if)g(the)h(column)f(is)g(de\014ned)f(as)i('4X',)h(and) d(one)i(calls)h(FTGCX)e(with)g(fbit=1)h(and)e(n)m(bit=8,)j(then)227 3998 y(all)30 b(8)g(bits)f(will)g(b)s(e)g(read)g(from)g(the)g(\014rst)f (b)m(yte)i(\(as)g(opp)s(osed)e(to)i(reading)f(the)h(\014rst)e(4)i(bits) f(from)f(the)i(\014rst)227 4111 y(ro)m(w)g(and)e(then)h(the)h(\014rst)e (4)i(bits)f(from)g(the)g(next)g(ro)m(w\),)i(ev)m(en)f(though)f(the)g (last)h(4)g(bits)f(of)g(eac)m(h)i(b)m(yte)f(are)227 4224 y(formally)h(not)g(de\014ned.)382 4461 y Ff(FTGCX\(unit,colnum,frow,f)o (bit)o(,nbi)o(t,)42 b(>)47 b(lray,status\))0 4698 y Fi(10)f Fj(Read)31 b(an)m(y)g(consecutiv)m(e)h(set)f(of)g(bits)g(from)f(an)g ('X')i(or)e('B')i(column)e(and)g(in)m(terpret)h(them)g(as)g(an)f (unsigned)227 4811 y(n-bit)k(in)m(teger.)54 b(NBIT)35 b(m)m(ust)f(b)s(e)f(less)i(than)f(or)g(equal)h(to)g(16)g(when)f (calling)h(FTGCXI,)g(and)f(less)g(than)227 4924 y(or)e(equal)g(to)g(32) g(when)e(calling)j(FTGCXJ;)f(there)f(is)h(no)f(limit)h(on)g(the)f(v)-5 b(alue)32 b(of)g(NBIT)f(for)g(FTGCXD,)227 5036 y(but)38 b(the)h(returned)e(double)i(precision)f(v)-5 b(alue)39 b(only)g(has)f(48)i(bits)e(of)h(precision)g(on)f(most)h(32-bit)h(w)m (ord)227 5149 y(mac)m(hines.)64 b(The)37 b(NBITS)g(bits)h(are)g(in)m (terpreted)g(as)g(an)g(unsigned)e(in)m(teger)k(unless)d(NBITS)g(=)g(16) i(\(in)227 5262 y(FTGCXI\))e(or)g(32)g(\(in)g(FTGCXJ\))f(in)g(whic)m(h) h(case)g(the)g(string)g(of)f(bits)h(are)g(in)m(terpreted)f(as)h(16-bit) h(or)227 5375 y(32-bit)j(2's)f(complemen)m(t)h(signed)e(in)m(tegers.)69 b(If)39 b(NR)m(O)m(WS)i(is)e(greater)i(than)e(1)h(then)f(the)h(same)g (set)g(of)227 5488 y(bits)34 b(will)g(b)s(e)f(read)h(from)f(sequen)m (tial)i(ro)m(ws)f(in)f(the)h(table)g(starting)h(with)e(ro)m(w)h(FR)m(O) m(W.)h(Note)g(that)g(the)227 5601 y(n)m(um)m(b)s(ering)27 b(con)m(v)m(en)m(tion)j(used)d(here)g(for)h(the)g(FBIT)f(parameter)i (adopts)e(1)h(for)g(the)g(\014rst)f(elemen)m(t)i(of)f(the)227 5714 y(v)m(ector)k(of)f(bits;)f(this)h(is)f(the)h(Most)g(Signi\014can)m (t)g(Bit)g(of)g(the)f(in)m(teger)i(v)-5 b(alue.)p eop end %%Page: 64 70 TeXDict begin 64 69 bop 0 299 a Fj(64)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTGCX[IJD]\(unit,colnum,f)o(row)o(,nro)o (ws,f)o(bit)o(,nbi)o(t,)42 b(>)47 b(array,status\))0 788 y Fi(11)f Fj(Get)37 b(the)e(descriptor)h(for)f(a)h(v)-5 b(ariable)37 b(length)f(column)f(in)g(a)h(binary)f(table.)57 b(The)35 b(descriptor)h(consists)g(of)227 901 y(2)c(in)m(teger)g (parameters:)42 b(the)31 b(n)m(um)m(b)s(er)f(of)h(elemen)m(ts)i(in)d (the)h(arra)m(y)h(and)e(the)h(starting)h(o\013set)g(relativ)m(e)h(to) 227 1014 y(the)28 b(start)f(of)g(the)h(heap.)39 b(The)27 b(\014rst)f(routine)h(returns)f(a)h(single)h(descriptor)f(whereas)g (the)g(second)g(routine)227 1127 y(returns)i(the)i(descriptors)f(for)g (a)h(range)g(of)f(ro)m(ws)h(in)f(the)g(table.)382 1359 y Ff(FTGDES\(unit,colnum,rownu)o(m,)41 b(>)48 b (nelements,offset,status\))382 1472 y(FTGDESLL\(unit,colnum,row)o(num)o (,)42 b(>)47 b(nelementsll,offsetll,statu)o(s\))382 1698 y(FTGDESS\(unit,colnum,firs)o(tro)o(w,nr)o(ows)41 b(>)48 b(nelements,offset,)43 b(status\))382 1811 y(FTGDESSLL\(unit,colnum,fi) o(rst)o(row,)o(nrow)o(s)f(>)47 b(nelementsll,offsetll,)42 b(status\))0 2044 y Fi(12)k Fj(W)-8 b(rite)33 b(the)f(descriptor)g(for) f(a)i(v)-5 b(ariable)32 b(length)g(column)g(in)f(a)i(binary)e(table.)45 b(These)32 b(subroutines)e(can)j(b)s(e)227 2157 y(used)f(in)h (conjunction)g(with)g(FTGDES)g(to)g(enable)h(2)f(or)g(more)g(arra)m(ys) h(to)f(p)s(oin)m(t)g(to)h(the)f(same)g(storage)227 2270 y(lo)s(cation)f(to)f(sa)m(v)m(e)h(storage)g(space)f(if)f(the)h(arra)m (ys)g(are)g(iden)m(tical.)382 2503 y Ff(FTPDES\(unit,colnum,rownu)o (m,n)o(elem)o(ents)o(,of)o(fset)o(,)42 b(>)47 b(status\))382 2615 y(FTPDESLL\(unit,colnum,row)o(num)o(,nel)o(emen)o(tsl)o(l,of)o (fset)o(ll,)41 b(>)48 b(status\))0 2945 y Fe(6.8)135 b(Ro)l(w)46 b(Selection)g(and)f(Calculator)h(Routines)0 3195 y Fj(These)21 b(routines)f(all)i(parse)f(and)f(ev)-5 b(aluate)23 b(an)d(input)g(string)h(con)m(taining)i(a)e(user)f (de\014ned)g(arithmetic)i(expression.)0 3308 y(The)29 b(\014rst)f(3)i(routines)f(select)i(ro)m(ws)e(in)g(a)h(FITS)e(table,)j (based)e(on)g(whether)g(the)g(expression)g(ev)-5 b(aluates)31 b(to)f(true)0 3421 y(\(not)e(equal)f(to)h(zero\))g(or)f(false)h (\(zero\).)41 b(The)27 b(other)g(routines)g(ev)-5 b(aluate)29 b(the)e(expression)g(and)f(calculate)k(a)d(v)-5 b(alue)0 3534 y(for)35 b(eac)m(h)h(ro)m(w)g(of)f(the)h(table.)56 b(The)35 b(allo)m(w)m(ed)i(expression)e(syn)m(tax)g(is)h(describ)s(ed)e (in)h(the)g(ro)m(w)h(\014lter)f(section)h(in)0 3647 y(the)h(earlier)h (`Extended)e(File)i(Name)f(Syn)m(tax')g(c)m(hapter)h(of)f(this)f(do)s (cumen)m(t.)60 b(The)36 b(expression)h(ma)m(y)g(also)h(b)s(e)0 3760 y(written)28 b(to)i(a)e(text)i(\014le,)f(and)f(the)h(name)f(of)h (the)f(\014le,)h(prep)s(ended)e(with)h(a)h('@')f(c)m(haracter)i(ma)m(y) f(b)s(e)f(supplied)f(for)0 3873 y(the)34 b('expr')g(parameter)g(\(e.g.) 53 b('@\014lename.txt'\).)f(The)34 b(expression)f(in)h(the)g(\014le)g (can)g(b)s(e)f(arbitrarily)h(complex)0 3985 y(and)h(extend)h(o)m(v)m (er)h(m)m(ultiple)f(lines)g(of)g(the)f(\014le.)57 b(Lines)36 b(that)g(b)s(egin)f(with)g(2)h(slash)g(c)m(haracters)h(\('//'\))h(will) e(b)s(e)0 4098 y(ignored)30 b(and)g(ma)m(y)h(b)s(e)f(used)g(to)h(add)e (commen)m(ts)j(to)f(the)f(\014le.)0 4331 y Fi(1)81 b Fj(Ev)-5 b(aluate)38 b(a)f(b)s(o)s(olean)g(expression)g(o)m(v)m(er)h (the)g(indicated)f(ro)m(ws,)i(returning)d(an)h(arra)m(y)h(of)f(\015ags) g(indicating)227 4444 y(whic)m(h)30 b(ro)m(ws)h(ev)-5 b(aluated)31 b(to)g(TR)m(UE/F)-10 b(ALSE)430 4677 y Ff (FTFROW\(unit,expr,firstr)o(ow,)41 b(nrows,)46 b(>)i(n_good_rows,)c (row_status,)h(status\))0 4910 y Fi(2)81 b Fj(Find)29 b(the)i(\014rst)f(ro)m(w)g(whic)m(h)g(satis\014es)h(the)g(input)e(b)s (o)s(olean)h(expression)430 5142 y Ff(FTFFRW\(unit,)44 b(expr,)i(>)i(rownum,)e(status\))0 5375 y Fi(3)81 b Fj(Ev)-5 b(aluate)35 b(an)f(expression)h(on)f(all)h(ro)m(ws)g(of)f(a)h(table.)54 b(If)34 b(the)g(input)g(and)g(output)g(\014les)g(are)h(not)g(the)f (same,)227 5488 y(cop)m(y)i(the)g(TR)m(UE)f(ro)m(ws)g(to)h(the)f (output)g(\014le;)j(if)d(the)g(output)g(table)h(is)f(not)h(empt)m(y)-8 b(,)37 b(then)e(this)g(routine)227 5601 y(will)28 b(app)s(end)e(the)i (new)f(selected)i(ro)m(ws)e(after)h(the)g(existing)h(ro)m(ws.)39 b(If)27 b(the)h(\014les)g(are)f(the)h(same,)h(delete)g(the)227 5714 y(F)-10 b(ALSE)30 b(ro)m(ws)h(\(preserv)m(e)f(the)h(TR)m(UE)f(ro)m (ws\).)p eop end %%Page: 65 71 TeXDict begin 65 70 bop 0 299 a Fh(6.9.)72 b(CELESTIAL)29 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(SUBR)m(OUTINES)1307 b Fj(65)430 555 y Ff(FTSROW\(inunit,)43 b(outunit,)j(expr,)g(>)i (status\))0 816 y Fi(4)81 b Fj(Calculate)28 b(an)f(expression)f(for)h (the)f(indicated)i(ro)m(ws)e(of)h(a)g(table,)i(returning)d(the)h (results,)g(cast)h(as)f(datat)m(yp)s(e)227 929 y(\(TSHOR)-8 b(T,)32 b(TDOUBLE,)h(etc\),)h(in)e(arra)m(y)-8 b(.)48 b(If)31 b(n)m(ulv)-5 b(al==NULL,)33 b(UNDEFs)g(will)f(b)s(e)g(zero)s (ed)g(out.)47 b(F)-8 b(or)227 1042 y(v)m(ector)37 b(results,)f(the)f(n) m(um)m(b)s(er)e(of)i(elemen)m(ts)i(returned)c(ma)m(y)j(b)s(e)e(less)h (than)g(nelemen)m(ts)g(if)g(nelemen)m(ts)h(is)227 1155 y(not)30 b(an)g(ev)m(en)h(m)m(ultiple)f(of)g(the)g(result)g(dimension.) 40 b(Call)30 b(FTTEXP)g(to)g(obtain)h(the)f(dimensions)f(of)h(the)227 1268 y(results.)430 1529 y Ff(FTCROW\(unit,datatype,ex)o(pr,)o(firs)o (trow)o(,ne)o(leme)o(nts,)o(nul)o(val,)41 b(>)620 1642 y(array,anynul,status\))0 1903 y Fi(5)81 b Fj(Ev)-5 b(aluate)33 b(an)g(expression)f(and)h(write)f(the)h(result)g(either)g(to)h(a)f (column)f(\(if)h(the)g(expression)f(is)h(a)g(function)227 2016 y(of)d(other)g(columns)g(in)f(the)h(table\))h(or)f(to)g(a)h(k)m (eyw)m(ord)f(\(if)g(the)g(expression)f(ev)-5 b(aluates)32 b(to)e(a)g(constan)m(t)i(and)227 2129 y(is)f(not)f(a)h(function)f(of)h (other)f(columns)h(in)f(the)g(table\).)42 b(In)30 b(the)h(former)e (case,)j(the)f(parName)f(parameter)227 2242 y(is)40 b(the)g(name)f(of)h (the)g(column)f(\(whic)m(h)h(ma)m(y)g(or)f(ma)m(y)h(not)g(already)g (exist\))h(in)m(to)f(whic)m(h)g(to)g(write)g(the)227 2355 y(results,)e(and)f(parInfo)e(con)m(tains)j(an)f(optional)g(TF)m (ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue)38 b(if)e(a)h(new)f(column)h(is)f(b) s(eing)227 2468 y(created.)42 b(If)28 b(a)h(TF)m(ORM)h(v)-5 b(alue)29 b(is)g(not)g(sp)s(eci\014ed)g(then)f(a)i(default)f(format)g (will)h(b)s(e)e(used,)h(dep)s(ending)e(on)227 2581 y(the)35 b(expression.)54 b(If)34 b(the)h(expression)f(ev)-5 b(aluates)37 b(to)e(a)g(constan)m(t,)i(then)e(the)g(result)f(will)h(b)s(e)f(written) h(to)227 2693 y(the)28 b(k)m(eyw)m(ord)g(name)f(giv)m(en)h(b)m(y)g(the) f(parName)h(parameter,)h(and)d(the)i(parInfo)e(parameter)i(ma)m(y)g(b)s (e)f(used)227 2806 y(to)k(supply)e(an)h(optional)i(commen)m(t)f(for)f (the)g(k)m(eyw)m(ord.)42 b(If)29 b(the)i(k)m(eyw)m(ord)g(do)s(es)f(not) g(already)h(exist,)g(then)227 2919 y(the)f(name)f(of)h(the)g(k)m(eyw)m (ord)g(m)m(ust)f(b)s(e)g(preceded)g(with)g(a)h('#')f(c)m(haracter,)j (otherwise)e(the)f(result)h(will)g(b)s(e)227 3032 y(written)h(to)g(a)g (column)f(with)g(that)h(name.)430 3293 y Ff(FTCALC\(inunit,)43 b(expr,)k(outunit,)e(parName,)h(parInfo,)f(>)j(status\))0 3554 y Fi(6)81 b Fj(This)38 b(calculator)k(routine)e(is)f(similar)h(to) g(the)g(previous)f(routine,)j(except)f(that)f(the)g(expression)f(is)h (only)227 3667 y(ev)-5 b(aluated)42 b(o)m(v)m(er)f(the)f(sp)s (eci\014ed)g(ro)m(w)g(ranges.)70 b(nranges)39 b(sp)s(eci\014es)h(the)g (n)m(um)m(b)s(er)f(of)h(ro)m(w)h(ranges,)i(and)227 3780 y(\014rstro)m(w)30 b(and)g(lastro)m(w)h(giv)m(e)h(the)f(starting)g(and) f(ending)g(ro)m(w)g(n)m(um)m(b)s(er)f(of)i(eac)m(h)g(range.)430 4041 y Ff(FTCALC_RNG\(inunit,)42 b(expr,)47 b(outunit,)e(parName,)h (parInfo,)573 4154 y(nranges,)f(firstrow,)h(lastrow,)f(>)j(status\))0 4415 y Fi(7)81 b Fj(Ev)-5 b(aluate)36 b(the)f(giv)m(en)h(expression)f (and)g(return)f(dimension)g(and)h(t)m(yp)s(e)g(information)g(on)g(the)h (result.)54 b(The)227 4528 y(returned)37 b(dimensions)f(corresp)s(ond)g (to)j(a)e(single)i(ro)m(w)e(en)m(try)h(of)f(the)h(requested)f (expression,)j(and)d(are)227 4641 y(equiv)-5 b(alen)m(t)26 b(to)f(the)g(result)f(of)g(\014ts)p 1380 4641 28 4 v 33 w(read)p 1585 4641 V 32 w(tdim\(\).)40 b(Note)25 b(that)g(strings)f (are)h(considered)f(to)h(b)s(e)f(one)g(elemen)m(t)227 4754 y(regardless)31 b(of)g(string)f(length.)41 b(If)30 b(maxdim)g(==)g(0,)h(then)f(naxes)g(is)h(optional.)430 5015 y Ff(FTTEXP\(unit,)44 b(expr,)i(maxdim)g(>)i(datatype,)d(nelem,)h (naxis,)g(naxes,)g(status\))0 5350 y Fe(6.9)135 b(Celestial)48 b(Co)t(ordinate)e(System)f(Subroutines)0 5601 y Fj(The)36 b(FITS)g(comm)m(unit)m(y)h(has)f(adopted)h(a)g(set)g(of)g(k)m(eyw)m (ord)g(con)m(v)m(en)m(tions)h(that)f(de\014ne)f(the)h(transformations)0 5714 y(needed)30 b(to)i(con)m(v)m(ert)g(b)s(et)m(w)m(een)f(pixel)g(lo)s (cations)h(in)e(an)h(image)h(and)e(the)g(corresp)s(onding)g(celestial)j (co)s(ordinates)p eop end %%Page: 66 72 TeXDict begin 66 71 bop 0 299 a Fj(66)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fj(on)25 b(the)h(sky)-8 b(,)27 b(or)e(more)g(generally)-8 b(,)29 b(that)d(de\014ne)e(w)m(orld)h(co)s (ordinates)i(that)e(are)h(to)g(b)s(e)f(asso)s(ciated)i(with)e(an)m(y)h (pixel)0 668 y(lo)s(cation)36 b(in)e(an)h(n-dimensional)f(FITS)g(arra)m (y)-8 b(.)54 b(CFITSIO)33 b(is)h(distributed)g(with)g(a)h(couple)f(of)h (self-con)m(tained)0 781 y(W)-8 b(orld)28 b(Co)s(ordinate)f(System)f (\(W)m(CS\))i(routines,)g(ho)m(w)m(ev)m(er,)h(these)f(routines)f(DO)g (NOT)f(supp)s(ort)f(all)j(the)f(latest)0 894 y(W)m(CS)38 b(con)m(v)m(en)m(tions,)k(so)d(it)g(is)f(STR)m(ONGL)-8 b(Y)38 b(RECOMMENDED)h(that)f(soft)m(w)m(are)i(dev)m(elop)s(ers)e(use)g (a)h(more)0 1007 y(robust)30 b(external)h(W)m(CS)f(library)-8 b(.)41 b(Sev)m(eral)31 b(recommended)f(libraries)h(are:)95 1289 y Ff(WCSLIB)47 b(-)95 b(supported)45 b(by)i(Mark)g(Calabretta)95 1402 y(WCSTools)f(-)h(supported)f(by)h(Doug)g(Mink)95 1515 y(AST)g(library)f(-)i(developed)d(by)i(the)g(U.K.)g(Starlink)e (project)0 1797 y Fj(More)30 b(information)f(ab)s(out)g(the)g(W)m(CS)g (k)m(eyw)m(ord)h(con)m(v)m(en)m(tions)h(and)d(links)h(to)h(all)g(of)f (these)g(W)m(CS)g(libraries)h(can)0 1910 y(b)s(e)g(found)f(on)h(the)h (FITS)e(Supp)s(ort)g(O\016ce)h(w)m(eb)g(site)i(at)f(h)m (ttp://\014ts.gsfc.nasa.go)m(v)j(under)29 b(the)h(W)m(CS)h(link.)0 2070 y(The)i(functions)h(pro)m(vided)g(in)f(these)i(external)f(W)m(CS)g (libraries)h(will)f(need)g(access)h(to)g(the)f(W)m(CS)g(information)0 2183 y(con)m(tained)i(in)f(the)h(FITS)e(\014le)i(headers.)55 b(One)35 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(pass)f(this)g (information)h(to)g(the)f(external)0 2296 y(library)k(is)h(to)h(use)e (FITSIO)g(to)h(cop)m(y)h(the)f(header)f(k)m(eyw)m(ords)h(in)m(to)h(one) f(long)g(c)m(haracter)i(string,)g(and)d(then)0 2409 y(pass)29 b(this)h(string)g(to)g(an)g(in)m(terface)h(routine)f(in)g(the)g (external)g(library)g(that)g(will)g(extract)i(the)e(necessary)g(W)m(CS) 0 2522 y(information)h(\(e.g.,)h(see)f(the)f(astFitsChan)h(and)f (astPutCards)g(routines)g(in)g(the)h(Starlink)f(AST)g(library\).)0 2682 y(The)24 b(follo)m(wing)j(FITSIO)c(routines)i(DO)g(NOT)f(supp)s (ort)f(the)i(more)g(recen)m(t)h(W)m(CS)f(con)m(v)m(en)m(tions)i(that)f (ha)m(v)m(e)g(b)s(een)0 2795 y(appro)m(v)m(ed)37 b(as)h(part)f(of)g (the)h(FITS)e(standard.)61 b(Consequen)m(tly)-8 b(,)39 b(the)f(follo)m(wing)g(routines)g(ARE)f(NO)m(W)h(DEP-)0 2908 y(RECA)-8 b(TED.)29 b(It)f(is)h(STR)m(ONGL)-8 b(Y)28 b(RECOMMENDED)h(that)g(soft)m(w)m(are)h(dev)m(elop)s(ers)f(not)g(use)f (these)h(routines,)0 3021 y(and)h(instead)g(use)g(an)h(external)g(W)m (CS)f(library)-8 b(,)31 b(as)g(describ)s(ed)e(ab)s(o)m(v)m(e.)0 3181 y(These)21 b(routines)g(are)g(included)f(mainly)h(for)g(bac)m(kw)m (ard)g(compatibilit)m(y)j(with)c(existing)i(soft)m(w)m(are.)39 b(They)21 b(supp)s(ort)0 3294 y(the)30 b(follo)m(wing)i(standard)d(map) g(pro)5 b(jections:)41 b(-SIN,)30 b(-T)-8 b(AN,)31 b(-AR)m(C,)g(-NCP)-8 b(,)30 b(-GLS,)g(-MER,)h(and)e(-AIT)h(\(these)0 3407 y(are)f(the)g(legal)h(v)-5 b(alues)29 b(for)f(the)h(co)s(ordt)m(yp)s(e) f(parameter\).)41 b(These)28 b(routines)h(are)g(based)f(on)g(similar)h (functions)f(in)0 3520 y(Classic)j(AIPS.)f(All)h(the)g(angular)f(quan)m (tities)i(are)f(giv)m(en)g(in)f(units)g(of)g(degrees.)0 3802 y Fi(1)81 b Fj(Get)22 b(the)g(v)-5 b(alues)21 b(of)h(all)g(the)g (standard)f(FITS)f(celestial)k(co)s(ordinate)f(system)e(k)m(eyw)m(ords) h(from)f(the)h(header)f(of)h(a)227 3915 y(FITS)j(image)i(\(i.e.,)h(the) d(primary)g(arra)m(y)h(or)f(an)h(image)g(extension\).)40 b(These)26 b(v)-5 b(alues)25 b(ma)m(y)h(then)g(b)s(e)e(passed)227 4028 y(to)39 b(the)e(subroutines)g(that)h(p)s(erform)e(the)i(co)s (ordinate)g(transformations.)63 b(If)37 b(an)m(y)h(or)g(all)g(of)g(the) g(W)m(CS)227 4141 y(k)m(eyw)m(ords)32 b(are)f(not)g(presen)m(t,)h(then) f(default)g(v)-5 b(alues)31 b(will)h(b)s(e)e(returned.)41 b(If)31 b(the)g(\014rst)g(co)s(ordinate)g(axis)h(is)227 4254 y(the)d(declination-lik)m(e)j(co)s(ordinate,)e(then)e(this)g (routine)h(will)g(sw)m(ap)f(them)h(so)g(that)g(the)g(longitudinal-lik)m (e)227 4367 y(co)s(ordinate)i(is)g(returned)e(as)i(the)f(\014rst)g (axis.)227 4528 y(If)35 b(the)h(\014le)f(uses)g(the)g(new)m(er)h('CDj)p 1454 4528 28 4 v 32 w(i')g(W)m(CS)f(transformation)h(matrix)g(k)m(eyw)m (ords)f(instead)h(of)f(old)h(st)m(yle)227 4641 y('CDEL)-8 b(Tn')37 b(and)f('CR)m(OT)-8 b(A2')38 b(k)m(eyw)m(ords,)h(then)e(this)f (routine)h(will)g(calculate)j(and)c(return)g(the)h(v)-5 b(alues)227 4754 y(of)33 b(the)g(equiv)-5 b(alen)m(t)35 b(old-st)m(yle)f(k)m(eyw)m(ords.)49 b(Note)34 b(that)g(the)f(con)m(v)m (ersion)h(from)e(the)i(new-st)m(yle)g(k)m(eyw)m(ords)227 4867 y(to)e(the)f(old-st)m(yle)h(v)-5 b(alues)31 b(is)g(sometimes)g (only)g(an)g(appro)m(ximation,)h(so)e(if)h(the)g(appro)m(ximation)h(is) e(larger)227 4980 y(than)37 b(an)h(in)m(ternally)g(de\014ned)e (threshold)h(lev)m(el,)k(then)c(CFITSIO)f(will)i(still)g(return)e(the)i (appro)m(ximate)227 5093 y(W)m(CS)f(k)m(eyw)m(ord)g(v)-5 b(alues,)39 b(but)d(will)h(also)h(return)d(with)i(status)g(=)f(506,)k (to)e(w)m(arn)e(the)h(calling)h(program)227 5206 y(that)30 b(appro)m(ximations)f(ha)m(v)m(e)h(b)s(een)e(made.)40 b(It)29 b(is)g(then)f(up)g(to)h(the)g(calling)i(program)d(to)h(decide)h (whether)227 5319 y(the)k(appro)m(ximations)g(are)g(su\016cien)m(tly)g (accurate)i(for)d(the)h(particular)f(application,)j(or)e(whether)f (more)227 5432 y(precise)e(W)m(CS)f(transformations)h(m)m(ust)f(b)s(e)g (p)s(erformed)f(using)h(new-st)m(yle)h(W)m(CS)g(k)m(eyw)m(ords)f (directly)-8 b(.)382 5714 y Ff(FTGICS\(unit,)44 b(>)k (xrval,yrval,xrpix,yrpix)o(,xin)o(c,yi)o(nc,)o(rot,)o(coor)o(dty)o (pe,s)o(tatu)o(s\))p eop end %%Page: 67 73 TeXDict begin 67 72 bop 0 299 a Fh(6.10.)73 b(FILE)30 b(CHECKSUM)f(SUBR)m(OUTINES)2080 b Fj(67)0 555 y Fi(2)81 b Fj(Get)34 b(the)f(v)-5 b(alues)33 b(of)g(all)h(the)f(standard)f(FITS) h(celestial)i(co)s(ordinate)f(system)f(k)m(eyw)m(ords)g(from)g(the)g (header)227 668 y(of)j(a)h(FITS)e(table)h(where)g(the)g(X)g(and)f(Y)h (\(or)g(RA)g(and)g(DEC)f(co)s(ordinates)i(are)f(stored)g(in)g(2)g (separate)227 781 y(columns)c(of)g(the)g(table.)46 b(These)31 b(v)-5 b(alues)32 b(ma)m(y)h(then)e(b)s(e)h(passed)f(to)h(the)g (subroutines)f(that)h(p)s(erform)f(the)227 894 y(co)s(ordinate)g (transformations.)382 1114 y Ff(FTGTCS\(unit,xcol,ycol,)42 b(>)716 1227 y(xrval,yrval,xrpix,yrpix,)o(xinc)o(,yi)o(nc,r)o(ot,c)o (oor)o(dtyp)o(e,st)o(atu)o(s\))0 1446 y Fi(3)81 b Fj(Calculate)42 b(the)g(celestial)h(co)s(ordinate)f(corresp)s(onding)e(to)i(the)f (input)f(X)h(and)g(Y)g(pixel)g(lo)s(cation)i(in)e(the)227 1559 y(image.)382 1779 y Ff(FTWLDP\(xpix,ypix,xrval,y)o(rva)o(l,xr)o (pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 1892 y(coordtype,)k(>)i(xpos,ypos,status\))0 2112 y Fi(4)81 b Fj(Calculate)42 b(the)g(X)f(and)f(Y)h(pixel)h(lo)s(cation)g(corresp)s (onding)e(to)i(the)f(input)f(celestial)k(co)s(ordinate)e(in)f(the)227 2225 y(image.)382 2445 y Ff(FTXYPX\(xpos,ypos,xrval,y)o(rva)o(l,xr)o (pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 2557 y(coordtype,)k(>)i(xpix,ypix,status\))0 2885 y Fe(6.10)136 b(File)45 b(Chec)l(ksum)g(Subroutines)0 3135 y Fj(The)33 b(follo)m(wing)h(routines)f(either)h(compute)f(or)h(v)-5 b(alidate)34 b(the)g(c)m(hec)m(ksums)f(for)g(the)h(CHDU.)g(The)e(D)m(A) -8 b(T)g(ASUM)0 3248 y(k)m(eyw)m(ord)33 b(is)f(used)f(to)i(store)f(the) h(n)m(umerical)f(v)-5 b(alue)33 b(of)f(the)g(32-bit,)i(1's)f(complemen) m(t)g(c)m(hec)m(ksum)g(for)f(the)g(data)0 3361 y(unit)26 b(alone.)40 b(If)25 b(there)h(is)h(no)e(data)i(unit)f(then)f(the)h(v)-5 b(alue)27 b(is)f(set)g(to)h(zero.)40 b(The)26 b(n)m(umerical)g(v)-5 b(alue)27 b(is)f(stored)g(as)g(an)0 3474 y(ASCI)s(I)20 b(string)i(of)h(digits,)h(enclosed)f(in)e(quotes,)k(b)s(ecause)d(the)g (v)-5 b(alue)23 b(ma)m(y)f(b)s(e)f(to)s(o)i(large)g(to)g(represen)m(t)f (as)g(a)h(32-bit)0 3587 y(signed)28 b(in)m(teger.)41 b(The)27 b(CHECKSUM)g(k)m(eyw)m(ord)i(is)f(used)f(to)h(store)h(the)f (ASCI)s(I)e(enco)s(ded)i(COMPLEMENT)f(of)0 3700 y(the)f(c)m(hec)m(ksum) h(for)f(the)h(en)m(tire)g(HDU.)g(Storing)f(the)h(complemen)m(t,)h (rather)e(than)g(the)h(actual)g(c)m(hec)m(ksum,)h(forces)0 3812 y(the)k(c)m(hec)m(ksum)h(for)f(the)h(whole)f(HDU)h(to)g(equal)g (zero.)47 b(If)31 b(the)i(\014le)f(has)g(b)s(een)f(mo)s(di\014ed)g (since)i(the)f(c)m(hec)m(ksums)0 3925 y(w)m(ere)39 b(computed,)i(then)e (the)g(HDU)g(c)m(hec)m(ksum)h(will)f(usually)f(not)h(equal)h(zero.)66 b(These)39 b(c)m(hec)m(ksum)g(k)m(eyw)m(ord)0 4038 y(con)m(v)m(en)m (tions)34 b(are)f(based)f(on)g(a)g(pap)s(er)f(b)m(y)h(Rob)g(Seaman)g (published)f(in)h(the)g(pro)s(ceedings)g(of)g(the)h(AD)m(ASS)f(IV)0 4151 y(conference)f(in)f(Baltimore)i(in)f(No)m(v)m(em)m(b)s(er)g(1994)h (and)e(a)h(later)g(revision)g(in)f(June)f(1995.)0 4371 y Fi(1)81 b Fj(Compute)33 b(and)g(write)h(the)g(D)m(A)-8 b(T)g(ASUM)35 b(and)e(CHECKSUM)g(k)m(eyw)m(ord)h(v)-5 b(alues)34 b(for)f(the)h(CHDU)g(in)m(to)h(the)227 4484 y(curren)m(t)25 b(header.)38 b(The)24 b(D)m(A)-8 b(T)g(ASUM)27 b(v)-5 b(alue)25 b(is)f(the)h(32-bit)h(c)m(hec)m(ksum)f(for)f(the)h (data)g(unit,)h(expressed)e(as)h(a)227 4597 y(decimal)32 b(in)m(teger)f(enclosed)g(in)f(single)h(quotes.)41 b(The)30 b(CHECKSUM)g(k)m(eyw)m(ord)g(v)-5 b(alue)31 b(is)f(a)h(16-c)m(haracter) 227 4710 y(string)j(whic)m(h)f(is)h(the)f(ASCI)s(I-enco)s(ded)f(v)-5 b(alue)34 b(for)g(the)f(complemen)m(t)i(of)f(the)f(c)m(hec)m(ksum)i (for)e(the)h(whole)227 4823 y(HDU.)h(If)e(these)g(k)m(eyw)m(ords)h (already)g(exist,)h(their)e(v)-5 b(alues)34 b(will)g(b)s(e)f(up)s (dated)f(only)h(if)g(necessary)h(\(i.e.,)i(if)227 4936 y(the)31 b(\014le)f(has)g(b)s(een)g(mo)s(di\014ed)f(since)i(the)g (original)g(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(w)m(ere)g(computed\).)382 5155 y Ff(FTPCKS\(unit,)44 b(>)k(status\))0 5375 y Fi(2)81 b Fj(Up)s(date)28 b(the)h(CHECKSUM)e(k)m(eyw)m(ord)i(v)-5 b(alue)29 b(in)f(the)h(CHDU,)g(assuming)f(that)h(the)f(D)m(A)-8 b(T)g(ASUM)30 b(k)m(eyw)m(ord)227 5488 y(exists)36 b(and)f(already)h (has)f(the)h(correct)g(v)-5 b(alue.)56 b(This)35 b(routine)g (calculates)j(the)e(new)f(c)m(hec)m(ksum)h(for)f(the)227 5601 y(curren)m(t)40 b(header)g(unit,)j(adds)c(it)i(to)g(the)f(data)h (unit)f(c)m(hec)m(ksum,)k(enco)s(des)c(the)g(v)-5 b(alue)41 b(in)m(to)g(an)f(ASCI)s(I)227 5714 y(string,)31 b(and)f(writes)g(the)h (string)f(to)h(the)g(CHECKSUM)e(k)m(eyw)m(ord.)p eop end %%Page: 68 74 TeXDict begin 68 73 bop 0 299 a Fj(68)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTUCKS\(unit,)44 b(>)k(status\))0 807 y Fi(3)81 b Fj(V)-8 b(erify)35 b(the)f(CHDU)h(b)m(y)g(computing)f (the)h(c)m(hec)m(ksums)g(and)f(comparing)h(them)f(with)g(the)h(k)m(eyw) m(ords.)53 b(The)227 920 y(data)34 b(unit)f(is)g(v)m(eri\014ed)g (correctly)h(if)f(the)h(computed)f(c)m(hec)m(ksum)g(equals)h(the)f(v)-5 b(alue)34 b(of)f(the)g(D)m(A)-8 b(T)g(ASUM)227 1033 y(k)m(eyw)m(ord.)64 b(The)37 b(c)m(hec)m(ksum)i(for)f(the)g(en)m(tire)g(HDU)h(\(header)f (plus)f(data)i(unit\))e(is)h(correct)h(if)f(it)h(equals)227 1146 y(zero.)55 b(The)34 b(output)g(D)m(A)-8 b(T)g(A)m(OK)37 b(and)d(HDUOK)h(parameters)g(in)f(this)h(subroutine)e(are)i(in)m (tegers)h(whic)m(h)227 1259 y(will)27 b(ha)m(v)m(e)g(a)f(v)-5 b(alue)27 b(=)f(1)g(if)g(the)h(data)f(or)g(HDU)h(is)f(v)m(eri\014ed)h (correctly)-8 b(,)29 b(a)d(v)-5 b(alue)27 b(=)e(0)i(if)f(the)g(D)m(A)-8 b(T)g(ASUM)28 b(or)227 1372 y(CHECKSUM)h(k)m(eyw)m(ord)g(is)h(not)f (presen)m(t,)h(or)f(v)-5 b(alue)30 b(=)f(-1)h(if)f(the)h(computed)f(c)m (hec)m(ksum)h(is)f(not)h(correct.)382 1623 y Ff(FTVCKS\(unit,)44 b(>)k(dataok,hduok,status\))0 1875 y Fi(4)81 b Fj(Compute)25 b(and)h(return)f(the)i(c)m(hec)m(ksum)g(v)-5 b(alues)26 b(for)g(the)h(CHDU)f(\(as)h(double)f(precision)h(v)-5 b(ariables\))27 b(without)227 1988 y(creating)46 b(or)e(mo)s(difying)g (the)h(CHECKSUM)e(and)h(D)m(A)-8 b(T)g(ASUM)46 b(k)m(eyw)m(ords.)83 b(This)44 b(routine)g(is)h(used)227 2101 y(in)m(ternally)32 b(b)m(y)e(FTV)m(CKS,)g(but)g(ma)m(y)h(b)s(e)e(useful)h(in)g(other)h (situations)g(as)f(w)m(ell.)382 2353 y Ff(FTGCKS\(unit,)44 b(>)k(datasum,hdusum,status\))0 2604 y Fi(5)81 b Fj(Enco)s(de)33 b(a)h(c)m(hec)m(ksum)h(v)-5 b(alue)34 b(\(stored)g(in)g(a)g(double)g (precision)g(v)-5 b(ariable\))35 b(in)m(to)f(a)h(16-c)m(haracter)h (string.)51 b(If)227 2717 y(COMPLEMENT)30 b(=)g(.true.)41 b(then)30 b(the)g(32-bit)i(sum)d(v)-5 b(alue)31 b(will)g(b)s(e)f (complemen)m(ted)h(b)s(efore)f(enco)s(ding.)382 2969 y Ff(FTESUM\(sum,complement,)42 b(>)47 b(checksum\))0 3221 y Fi(6)81 b Fj(Deco)s(de)39 b(a)f(16)h(c)m(haracter)h(c)m(hec)m (ksum)e(string)g(in)m(to)h(a)g(double)e(precision)h(v)-5 b(alue.)65 b(If)37 b(COMPLEMENT)g(=)227 3334 y(.true.)k(then)30 b(the)h(32-bit)g(sum)f(v)-5 b(alue)31 b(will)f(b)s(e)g(complemen)m(ted) i(after)e(deco)s(ding.)382 3586 y Ff(FTDSUM\(checksum,compleme)o(nt,)41 b(>)48 b(sum\))0 3918 y Fe(6.11)180 b(Date)46 b(and)f(Time)g(Utilit)l (y)i(Routines)0 4168 y Fj(The)29 b(follo)m(wing)i(routines)f(help)f(to) i(construct)f(or)f(parse)h(the)g(FITS)f(date/time)i(strings.)41 b(Starting)30 b(in)f(the)h(y)m(ear)0 4281 y(2000,)k(the)d(FITS)g(D)m(A) -8 b(TE)32 b(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(\(and)h(the)f(v)-5 b(alues)32 b(of)f(other)h(`D)m(A)-8 b(TE-')33 b(k)m(eyw)m(ords\))f(m)m (ust)f(ha)m(v)m(e)i(the)0 4394 y(form)j('YYYY-MM-DD')k(\(date)e(only\)) f(or)g('YYYY-MM-DDThh:mm:ss.ddd...')61 b(\(date)38 b(and)e(time\))h (where)0 4507 y(the)30 b(n)m(um)m(b)s(er)f(of)i(decimal)g(places)g(in)f (the)g(seconds)g(v)-5 b(alue)31 b(is)f(optional.)42 b(These)30 b(times)h(are)f(in)g(UTC.)g(The)g(older)0 4620 y('dd/mm/yy')g(date)h (format)g(ma)m(y)g(not)g(b)s(e)e(used)h(for)g(dates)h(after)g(01)g(Jan) m(uary)f(2000.)0 4872 y Fi(1)81 b Fj(Get)31 b(the)g(curren)m(t)f (system)g(date.)42 b(The)29 b(returned)h(y)m(ear)h(has)f(4)h(digits)g (\(1999,)h(2000,)h(etc.\))382 5123 y Ff(FTGSDT\()46 b(>)h(day,)g (month,)f(year,)g(status)g(\))0 5375 y Fi(2)81 b Fj(Get)34 b(the)g(curren)m(t)g(system)f(date)i(and)e(time)h(string)g (\('YYYY-MM-DDThh:mm:ss'\).)53 b(The)33 b(time)i(will)f(b)s(e)227 5488 y(in)26 b(UTC/GMT)g(if)g(a)m(v)-5 b(ailable,)29 b(as)e(indicated)f(b)m(y)g(a)g(returned)f(timeref)h(v)-5 b(alue)27 b(=)e(0.)40 b(If)26 b(the)g(returned)e(v)-5 b(alue)227 5601 y(of)31 b(timeref)g(=)g(1)g(then)f(this)h(indicates)g (that)h(it)f(w)m(as)g(not)g(p)s(ossible)f(to)h(con)m(v)m(ert)i(the)d (lo)s(cal)i(time)g(to)f(UTC,)227 5714 y(and)f(th)m(us)g(the)h(lo)s(cal) g(time)g(w)m(as)g(returned.)p eop end %%Page: 69 75 TeXDict begin 69 74 bop 0 299 a Fh(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fj(69)382 555 y Ff(FTGSTM\(>)45 b(datestr,)h(timeref,)f(status\))0 823 y Fi(3)81 b Fj(Construct)26 b(a)i(date)g(string)f(from)g(the)g(input)f(date)i(v)-5 b(alues.)40 b(If)27 b(the)g(y)m(ear)h(is)g(b)s(et)m(w)m(een)f(1900)i (and)e(1998,)j(inclu-)227 936 y(siv)m(e,)38 b(then)c(the)i(returned)d (date)j(string)f(will)g(ha)m(v)m(e)i(the)e(old)g(FITS)f(format)i (\('dd/mm/yy'\),)h(otherwise)227 1048 y(the)32 b(date)g(string)f(will)g (ha)m(v)m(e)i(the)e(new)g(FITS)g(format)g(\('YYYY-MM-DD'\).)36 b(Use)c(FTTM2S)f(instead)g(to)227 1161 y(alw)m(a)m(ys)h(return)d(a)i (date)g(string)g(using)e(the)i(new)f(FITS)g(format.)382 1429 y Ff(FTDT2S\()46 b(year,)g(month,)g(day,)h(>)g(datestr,)f (status\))0 1696 y Fi(4)81 b Fj(Construct)34 b(a)i(new-format)f(date)h (+)f(time)h(string)f(\('YYYY-MM-DDThh:mm:ss.ddd...'\).)57 b(If)34 b(the)i(y)m(ear,)227 1809 y(mon)m(th,)d(and)e(da)m(y)h(v)-5 b(alues)32 b(all)h(=)e(0)h(then)g(only)g(the)g(time)g(is)g(enco)s(ded)f (with)h(format)g('hh:mm:ss.ddd...'.)227 1922 y(The)j(decimals)h (parameter)g(sp)s(eci\014es)e(ho)m(w)i(man)m(y)f(decimal)h(places)g(of) f(fractional)i(seconds)e(to)h(include)227 2035 y(in)30 b(the)h(string.)41 b(If)29 b(`decimals')j(is)f(negativ)m(e,)h(then)f (only)f(the)h(date)g(will)f(b)s(e)g(return)f(\('YYYY-MM-DD'\).)382 2302 y Ff(FTTM2S\()46 b(year,)g(month,)g(day,)h(hour,)f(minute,)g (second,)g(decimals,)764 2415 y(>)h(datestr,)f(status\))0 2683 y Fi(5)81 b Fj(Return)44 b(the)g(date)i(as)f(read)f(from)h(the)g (input)e(string,)49 b(where)44 b(the)h(string)g(ma)m(y)g(b)s(e)f(in)h (either)g(the)g(old)227 2796 y(\('dd/mm/yy'\))31 b(or)g(new)e (\('YYYY-MM-DDThh:mm:ss')k(or)d('YYYY-MM-DD'\))k(FITS)c(format.)382 3063 y Ff(FTS2DT\(datestr,)43 b(>)48 b(year,)e(month,)g(day,)h (status\))0 3330 y Fi(6)81 b Fj(Return)30 b(the)h(date)h(and)f(time)h (as)f(read)g(from)g(the)h(input)e(string,)h(where)g(the)h(string)f(ma)m (y)h(b)s(e)e(in)h(either)h(the)227 3443 y(old)d(or)f(new)g(FITS)g (format.)40 b(The)28 b(returned)f(hours,)h(min)m(utes,)h(and)f(seconds) g(v)-5 b(alues)29 b(will)f(b)s(e)g(set)h(to)g(zero)227 3556 y(if)k(the)h(input)e(string)h(do)s(es)g(not)h(include)f(the)g (time)h(\('dd/mm/yy')f(or)h('YYYY-MM-DD'\))j(.)c(Similarly)-8 b(,)227 3669 y(the)36 b(returned)e(y)m(ear,)j(mon)m(th,)g(and)d(date)i (v)-5 b(alues)36 b(will)f(b)s(e)g(set)h(to)g(zero)g(if)f(the)g(date)h (is)f(not)h(included)e(in)227 3782 y(the)d(input)e(string)i (\('hh:mm:ss.ddd...'\).)382 4050 y Ff(FTS2TM\(datestr,)43 b(>)48 b(year,)e(month,)g(day,)h(hour,)f(minute,)g(second,)g(status\))0 4392 y Fe(6.12)136 b(General)45 b(Utilit)l(y)i(Subroutines)0 4644 y Fj(The)30 b(follo)m(wing)i(utilit)m(y)f(subroutines)f(ma)m(y)h (b)s(e)e(useful)h(for)g(certain)h(applications:)0 4912 y Fi(1)81 b Fj(Return)29 b(the)i(starting)g(b)m(yte)g(address)e(of)i (the)f(CHDU)h(and)f(the)h(next)f(HDU.)382 5179 y Ff(FTGHAD\(iunit,)44 b(>)j(curaddr,)f(nextaddr\))0 5446 y Fi(2)81 b Fj(Con)m(v)m(ert)31 b(a)g(c)m(haracter)h(string)e(to)h(upp)s(ercase)e(\(op)s(erates)j(in)e (place\).)382 5714 y Ff(FTUPCH\(string\))p eop end %%Page: 70 76 TeXDict begin 70 75 bop 0 299 a Fj(70)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(3)81 b Fj(Compare)43 b(the)i(input)e (template)i(string)f(against)h(the)g(reference)f(string)g(to)h(see)g (if)f(they)g(matc)m(h.)82 b(The)227 668 y(template)36 b(string)f(ma)m(y)g(con)m(tain)g(wildcard)f(c)m(haracters:)51 b('*')35 b(will)g(matc)m(h)g(an)m(y)g(sequence)g(of)f(c)m(haracters)227 781 y(\(including)j(zero)h(c)m(haracters\))g(and)e(')10 b(?')60 b(will)38 b(matc)m(h)f(an)m(y)g(single)h(c)m(haracter)g(in)f (the)g(reference)g(string.)227 894 y(The)31 b('#')g(c)m(haracter)i (will)f(matc)m(h)g(an)m(y)f(consecutiv)m(e)j(string)d(of)g(decimal)h (digits)g(\(0)g(-)g(9\).)43 b(If)31 b(CASESN)f(=)227 1007 y(.true.)45 b(then)31 b(the)g(matc)m(h)i(will)f(b)s(e)f(case)h (sensitiv)m(e.)46 b(The)31 b(returned)f(MA)-8 b(TCH)32 b(parameter)g(will)g(b)s(e)f(.true.)227 1120 y(if)j(the)h(2)f(strings)g (matc)m(h,)j(and)c(EXA)m(CT)h(will)h(b)s(e)e(.true.)53 b(if)34 b(the)g(matc)m(h)h(is)g(exact)g(\(i.e.,)i(if)d(no)g(wildcard) 227 1233 y(c)m(haracters)e(w)m(ere)f(used)f(in)g(the)g(matc)m(h\).)42 b(Both)31 b(strings)f(m)m(ust)h(b)s(e)e(68)j(c)m(haracters)f(or)g(less) f(in)g(length.)382 1507 y Ff(FTCMPS\(str_template,)42 b(string,)k(casesen,)f(>)j(match,)e(exact\))0 1781 y Fi(4)81 b Fj(T)-8 b(est)31 b(that)g(the)f(k)m(eyw)m(ord)h(name)f(con)m (tains)i(only)e(legal)j(c)m(haracters:)42 b(A-Z,0-9,)32 b(h)m(yphen,)d(and)h(underscore.)382 2054 y Ff(FTTKEY\(keyword,)43 b(>)48 b(status\))0 2328 y Fi(5)81 b Fj(T)-8 b(est)31 b(that)g(the)f(k)m(eyw)m(ord)h(record)f(con)m(tains)i(only)e(legal)i (prin)m(table)f(ASCI)s(I)e(c)m(haracters)382 2602 y Ff(FTTREC\(card,)44 b(>)k(status\))0 2876 y Fi(6)81 b Fj(T)-8 b(est)25 b(whether)f(the)h (curren)m(t)f(header)h(con)m(tains)g(an)m(y)g(NULL)g(\(ASCI)s(I)e(0\))j (c)m(haracters.)40 b(These)24 b(c)m(haracters)j(are)227 2989 y(illegal)37 b(in)d(the)h(header,)g(but)f(they)g(will)h(go)g (undetected)g(b)m(y)f(most)h(of)g(the)f(CFITSIO)f(k)m(eyw)m(ord)i (header)227 3102 y(routines,)29 b(b)s(ecause)f(the)h(n)m(ull)f(is)g(in) m(terpreted)g(as)h(the)f(normal)g(end-of-string)h(terminator.)41 b(This)27 b(routine)227 3215 y(returns)h(the)g(p)s(osition)h(of)g(the)g (\014rst)f(n)m(ull)g(c)m(haracter)i(in)f(the)f(header,)h(or)g(zero)g (if)g(there)g(are)g(no)f(n)m(ulls.)40 b(F)-8 b(or)227 3328 y(example)37 b(a)f(returned)f(v)-5 b(alue)37 b(of)f(110)h(w)m (ould)f(indicate)h(that)g(the)f(\014rst)f(NULL)h(is)g(lo)s(cated)h(in)f (the)g(30th)227 3441 y(c)m(haracter)28 b(of)f(the)g(second)f(k)m(eyw)m (ord)h(in)f(the)h(header)f(\(recall)i(that)f(eac)m(h)h(header)e(record) h(is)f(80)h(c)m(haracters)227 3554 y(long\).)56 b(Note)36 b(that)g(this)f(is)g(one)g(of)g(the)g(few)g(FITSIO)f(routines)h(in)f (whic)m(h)h(the)g(returned)f(v)-5 b(alue)36 b(is)f(not)227 3667 y(necessarily)d(equal)e(to)i(the)e(status)h(v)-5 b(alue\).)382 3941 y Ff(FTNCHK\(unit,)44 b(>)k(status\))0 4215 y Fi(7)81 b Fj(P)m(arse)27 b(a)f(header)h(k)m(eyw)m(ord)g(record)f (and)g(return)f(the)i(name)f(of)h(the)f(k)m(eyw)m(ord)h(and)f(the)h (length)f(of)h(the)g(name.)227 4327 y(The)34 b(k)m(eyw)m(ord)h(name)f (normally)h(o)s(ccupies)f(the)h(\014rst)e(8)i(c)m(haracters)g(of)g(the) f(record,)i(except)f(under)e(the)227 4440 y(HIERAR)m(CH)e(con)m(v)m(en) m(tion)h(where)e(the)h(name)f(can)h(b)s(e)f(up)f(to)i(70)g(c)m (haracters)h(in)e(length.)382 4714 y Ff(FTGKNM\(card,)44 b(>)k(keyname,)d(keylength,)g(staThe)h('\\#')h(character)e(will)i (match)f(any)h(consecutive)e(string)191 4827 y(of)i(decimal)f(digits)g (\(0)h(-)h(9\).)f(tus\))0 5101 y Fi(8)81 b Fj(P)m(arse)34 b(a)h(header)f(k)m(eyw)m(ord)h(record.)52 b(This)33 b(subroutine)g (parses)h(the)g(input)g(header)g(record)g(to)h(return)e(the)227 5214 y(v)-5 b(alue)27 b(\(as)g(a)g(c)m(haracter)g(string\))g(and)f (commen)m(t)h(strings.)39 b(If)26 b(the)g(k)m(eyw)m(ord)h(has)f(no)g(v) -5 b(alue)27 b(\(columns)f(9-10)227 5327 y(not)h(equal)f(to)h('=)f ('\),)i(then)e(the)g(v)-5 b(alue)27 b(string)f(is)g(returned)f(blank)h (and)f(the)h(commen)m(t)i(string)e(is)g(set)g(equal)227 5440 y(to)31 b(column)g(9)f(-)h(80)g(of)g(the)f(input)g(string.)382 5714 y Ff(FTPSVC\(card,)44 b(>)k(value,comment,status\))p eop end %%Page: 71 77 TeXDict begin 71 76 bop 0 299 a Fh(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fj(71)0 555 y Fi(9)81 b Fj(Construct)41 b(a)h(prop)s(erly)f(formated)h(80-c)m(haracter)i (header)e(k)m(eyw)m(ord)g(record)f(from)h(the)g(input)e(k)m(eyw)m(ord) 227 668 y(name,)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)25 b(and)e(k)m(eyw)m(ord)h(commen)m(t)g(strings.)38 b(Hierarc)m(hical)26 b(k)m(eyw)m(ord)e(names)f(\(e.g.,)j("ESO)227 781 y(TELE)e(CAM"\))i(are) f(supp)s(orted.)37 b(The)25 b(v)-5 b(alue)25 b(string)g(ma)m(y)h(con)m (tain)g(an)f(in)m(teger,)i(\015oating)f(p)s(oin)m(t,)g(logical,)227 894 y(or)31 b(quoted)f(c)m(haracter)i(string)e(\(e.g.,)j("12",)f ("15.7",)h("T",)e(or)g("'NGC)g(1313'"\).)382 1153 y Ff (FTMKKY\(keyname,)43 b(value,)k(comment,)e(>)j(card,)e(status\))0 1413 y Fi(10)g Fj(Construct)35 b(a)g(sequence)g(k)m(eyw)m(ord)g(name)g (\(R)m(OOT)g(+)f(nnn\).)54 b(This)34 b(subroutine)f(app)s(ends)g(the)j (sequence)227 1526 y(n)m(um)m(b)s(er)29 b(to)i(the)g(ro)s(ot)g(string)f (to)h(create)h(a)f(k)m(eyw)m(ord)g(name)f(\(e.g.,)i('NAXIS')f(+)f(2)h (=)f('NAXIS2'\))382 1785 y Ff(FTKEYN\(keyroot,seq_no,)42 b(>)47 b(keyword,status\))0 2045 y Fi(11)f Fj(Construct)30 b(a)g(sequence)g(k)m(eyw)m(ord)h(name)f(\(n)f(+)h(R)m(OOT\).)g(This)f (subroutine)g(concatenates)j(the)f(sequence)227 2158 y(n)m(um)m(b)s(er)20 b(to)j(the)e(fron)m(t)h(of)g(the)f(ro)s(ot)h (string)g(to)g(create)h(a)f(k)m(eyw)m(ord)g(name)g(\(e.g.,)j(1)d(+)f ('CTYP')g(=)g('1CTYP'\))382 2417 y Ff(FTNKEY\(seq_no,keyroot,)42 b(>)47 b(keyword,status\))0 2677 y Fi(12)f Fj(Determine)35 b(the)f(datat)m(yp)s(e)g(of)g(a)g(k)m(eyw)m(ord)h(v)-5 b(alue)34 b(string.)50 b(This)33 b(subroutine)g(parses)g(the)h(k)m(eyw) m(ord)g(v)-5 b(alue)227 2790 y(string)31 b(\(usually)f(columns)g(11-30) j(of)d(the)h(header)f(record\))g(to)i(determine)e(its)h(datat)m(yp)s (e.)382 3049 y Ff(FTDTYP\(value,)44 b(>)j(dtype,status\))0 3309 y Fi(13)f Fj(Return)c(the)i(class)g(of)f(input)f(header)h(record.) 79 b(The)43 b(record)g(is)g(classi\014ed)g(in)m(to)h(one)g(of)f(the)g (follo)m(wing)227 3422 y(categories)36 b(\(the)e(class)f(v)-5 b(alues)34 b(are)f(de\014ned)f(in)h(\014tsio.h\).)49 b(Note)35 b(that)e(this)g(is)g(one)h(of)f(the)g(few)g(FITSIO)227 3535 y(routines)e(that)f(do)s(es)h(not)f(return)f(a)i(status)g(v)-5 b(alue.)334 3794 y Ff(Class)94 b(Value)619 b(Keywords)95 3907 y(TYP_STRUC_KEY)92 b(10)j(SIMPLE,)46 b(BITPIX,)g(NAXIS,)g(NAXISn,) g(EXTEND,)g(BLOCKED,)1002 4020 y(GROUPS,)g(PCOUNT,)g(GCOUNT,)g(END)1002 4133 y(XTENSION,)g(TFIELDS,)f(TTYPEn,)h(TBCOLn,)g(TFORMn,)g(THEAP,)1002 4246 y(and)h(the)g(first)f(4)i(COMMENT)e(keywords)f(in)i(the)g(primary) f(array)1002 4359 y(that)h(define)f(the)h(FITS)g(format.)95 4472 y(TYP_CMPRS_KEY)92 b(20)j(The)47 b(keywords)f(used)g(in)i(the)e (compressed)f(image)95 b(or)47 b(table)1002 4585 y(format,)f(including) f(ZIMAGE,)h(ZCMPTYPE,)f(ZNAMEn,)h(ZVALn,)1002 4698 y(ZTILEn,)g (ZBITPIX,)g(ZNAXISn,)f(ZSCALE,)h(ZZERO,)g(ZBLANK)95 4811 y(TYP_SCAL_KEY)140 b(30)95 b(BSCALE,)46 b(BZERO,)g(TSCALn,)g(TZEROn)95 4924 y(TYP_NULL_KEY)140 b(40)95 b(BLANK,)46 b(TNULLn)95 5036 y(TYP_DIM_KEY)188 b(50)95 b(TDIMn)95 5149 y(TYP_RANG_KEY)140 b(60)95 b(TLMINn,)46 b(TLMAXn,)g(TDMINn,)g(TDMAXn,)g(DATAMIN,)f (DATAMAX)95 5262 y(TYP_UNIT_KEY)140 b(70)95 b(BUNIT,)46 b(TUNITn)95 5375 y(TYP_DISP_KEY)140 b(80)95 b(TDISPn)95 5488 y(TYP_HDUID_KEY)d(90)j(EXTNAME,)46 b(EXTVER,)g(EXTLEVEL,)f (HDUNAME,)g(HDUVER,)h(HDULEVEL)95 5601 y(TYP_CKSUM_KEY)f(100)94 b(CHECKSUM,)46 b(DATASUM)95 5714 y(TYP_WCS_KEY)141 b(110)94 b(CTYPEn,)46 b(CUNITn,)g(CRVALn,)g(CRPIXn,)g(CROTAn,)f(CDELTn)p eop end %%Page: 72 78 TeXDict begin 72 77 bop 0 299 a Fj(72)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)1002 555 y Ff(CDj_is,)46 b(PVj_ms,)g(LONPOLEs,)f (LATPOLEs)1002 668 y(TCTYPn,)h(TCTYns,)g(TCUNIn,)g(TCUNns,)g(TCRVLn,)f (TCRVns,)h(TCRPXn,)1002 781 y(TCRPks,)g(TCDn_k,)g(TCn_ks,)g(TPVn_m,)g (TPn_ms,)f(TCDLTn,)h(TCROTn)1002 894 y(jCTYPn,)g(jCTYns,)g(jCUNIn,)g (jCUNns,)g(jCRVLn,)f(jCRVns,)h(iCRPXn,)1002 1007 y(iCRPns,)g(jiCDn,)94 b(jiCDns,)46 b(jPVn_m,)g(jPn_ms,)f(jCDLTn,)h(jCROTn)1002 1120 y(\(i,j,m,n)g(are)h(integers,)e(s)i(is)h(any)f(letter\))95 1233 y(TYP_REFSYS_KEY)d(120)j(EQUINOXs,)f(EPOCH,)g(MJD-OBSs,)f (RADECSYS,)g(RADESYSs)95 1346 y(TYP_COMM_KEY)140 b(130)47 b(COMMENT,)f(HISTORY,)f(\(blank)h(keyword\))95 1458 y(TYP_CONT_KEY)140 b(140)47 b(CONTINUE)95 1571 y(TYP_USER_KEY)140 b(150)47 b(all)g(other)g(keywords)430 1797 y(class)f(=)h(FTGKCL)f(\(char)h (*card\))0 2042 y Fi(14)f Fj(P)m(arse)f(the)g('TF)m(ORM')h(binary)e (table)i(column)e(format)h(string.)84 b(This)44 b(subroutine)g(parses)g (the)h(input)227 2155 y(TF)m(ORM)27 b(c)m(haracter)g(string)f(and)g (returns)f(the)h(in)m(teger)h(datat)m(yp)s(e)g(co)s(de,)h(the)e(rep)s (eat)g(coun)m(t)h(of)f(the)g(\014eld,)227 2268 y(and,)f(in)e(the)h (case)g(of)g(c)m(haracter)h(string)e(\014elds,)i(the)e(length)h(of)g (the)g(unit)f(string.)38 b(The)23 b(follo)m(wing)i(datat)m(yp)s(e)227 2381 y(co)s(des)e(are)h(returned)e(\(the)h(negativ)m(e)i(of)f(the)f(v) -5 b(alue)23 b(is)g(returned)f(if)h(the)g(column)g(con)m(tains)h(v)-5 b(ariable-length)227 2494 y(arra)m(ys\):)764 2739 y Ff(Datatype)761 b(DATACODE)46 b(value)764 2852 y(bit,)g(X)907 b(1)764 2965 y(byte,)46 b(B)811 b(11)764 3078 y(logical,)45 b(L)668 b(14)764 3191 y(ASCII)46 b(character,)f(A)286 b(16)764 3304 y(short)46 b(integer,)g(I)381 b(21)764 3417 y(integer,)45 b(J)668 b(41)764 3530 y(real,)46 b(E)811 b(42)764 3643 y(double)46 b(precision,)f(D)238 b(82)764 3756 y(complex)809 b(83)764 3868 y(double)46 b(complex)475 b(163)382 4094 y(FTBNFM\(tform,)44 b(>)j(datacode,repeat,width,stat)o(us\))0 4340 y Fi(15)f Fj(P)m(arse)38 b(the)f('TF)m(ORM')h(k)m(eyw)m(ord)g(v)-5 b(alue)37 b(that)h(de\014nes)e(the)h(column)g(format)h(in)e(an)h(ASCI)s (I)f(table.)62 b(This)227 4452 y(routine)31 b(parses)g(the)g(input)g (TF)m(ORM)g(c)m(haracter)i(string)e(and)f(returns)g(the)i(datat)m(yp)s (e)g(co)s(de,)f(the)h(width)227 4565 y(of)40 b(the)h(column,)h(and)e (\(if)g(it)g(is)h(a)f(\015oating)h(p)s(oin)m(t)f(column\))g(the)g(n)m (um)m(b)s(er)f(of)h(decimal)h(places)g(to)g(the)227 4678 y(righ)m(t)28 b(of)g(the)f(decimal)h(p)s(oin)m(t.)40 b(The)27 b(returned)f(datat)m(yp)s(e)i(co)s(des)f(are)h(the)g(same)f (as)h(for)f(the)g(binary)g(table,)227 4791 y(listed)41 b(ab)s(o)m(v)m(e,)j(with)c(the)g(follo)m(wing)i(additional)f(rules:)60 b(in)m(teger)42 b(columns)e(that)g(are)h(b)s(et)m(w)m(een)g(1)g(and)227 4904 y(4)36 b(c)m(haracters)i(wide)d(are)i(de\014ned)d(to)j(b)s(e)e (short)h(in)m(tegers)h(\(co)s(de)f(=)g(21\).)58 b(Wider)36 b(in)m(teger)h(columns)f(are)227 5017 y(de\014ned)j(to)i(b)s(e)e (regular)h(in)m(tegers)i(\(co)s(de)e(=)g(41\).)71 b(Similarly)-8 b(,)43 b(Fixed)d(decimal)h(p)s(oin)m(t)f(columns)g(\(with)227 5130 y(TF)m(ORM)30 b(=)g('Fw.d'\))g(are)g(de\014ned)f(to)h(b)s(e)g (single)g(precision)g(reals)g(\(co)s(de)h(=)e(42\))i(if)f(w)f(is)h(b)s (et)m(w)m(een)g(1)h(and)227 5243 y(7)i(c)m(haracters)h(wide,)f (inclusiv)m(e.)47 b(Wider)32 b('F')h(columns)f(will)h(return)e(a)i (double)f(precision)g(data)h(co)s(de)g(\(=)227 5356 y(82\).)54 b('Ew.d')34 b(format)g(columns)g(will)h(ha)m(v)m(e)g(dataco)s(de)g(=)f (42,)j(and)c('Dw.d')i(format)f(columns)g(will)h(ha)m(v)m(e)227 5469 y(dataco)s(de)d(=)e(82.)382 5714 y Ff(FTASFM\(tform,)44 b(>)j(datacode,width,decimals,st)o(atus)o(\))p eop end %%Page: 73 79 TeXDict begin 73 78 bop 0 299 a Fh(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fj(73)0 555 y Fi(16)46 b Fj(Calculate)32 b(the)f(starting)g(column)g(p)s(ositions)f(and)g (total)i(ASCI)s(I)d(table)j(width)d(based)i(on)f(the)h(input)e(arra)m (y)227 668 y(of)e(ASCI)s(I)e(table)i(TF)m(ORM)g(v)-5 b(alues.)40 b(The)26 b(SP)-8 b(A)m(CE)27 b(input)e(parameter)i (de\014nes)f(ho)m(w)h(man)m(y)f(blank)h(spaces)227 781 y(to)40 b(lea)m(v)m(e)i(b)s(et)m(w)m(een)e(eac)m(h)g(column)g(\(it)g (is)f(recommended)g(to)h(ha)m(v)m(e)h(one)e(space)h(b)s(et)m(w)m(een)g (columns)f(for)227 894 y(b)s(etter)31 b(h)m(uman)e(readabilit)m(y\).) 382 1153 y Ff(FTGABC\(tfields,tform,spa)o(ce,)41 b(>)48 b(rowlen,tbcol,status\))0 1413 y Fi(17)e Fj(P)m(arse)36 b(a)f(template)h(string)f(and)g(return)f(a)h(formatted)h(80-c)m (haracter)h(string)e(suitable)h(for)f(app)s(ending)e(to)227 1526 y(\(or)40 b(deleting)h(from\))e(a)h(FITS)f(header)h(\014le.)68 b(This)39 b(subroutine)f(is)i(useful)f(for)g(parsing)g(lines)h(from)f (an)227 1639 y(ASCI)s(I)34 b(template)j(\014le)f(and)e(reformatting)j (them)e(in)m(to)i(legal)g(FITS)d(header)i(records.)55 b(The)35 b(formatted)227 1752 y(string)c(ma)m(y)g(then)f(b)s(e)g (passed)g(to)i(the)e(FTPREC,)h(FTMCRD,)g(or)f(FTDKEY)h(subroutines)e (to)j(app)s(end)227 1865 y(or)f(mo)s(dify)e(a)i(FITS)f(header)g (record.)382 2124 y Ff(FTGTHD\(template,)43 b(>)48 b (card,hdtype,status\))0 2384 y Fj(The)23 b(input)h(TEMPLA)-8 b(TE)23 b(c)m(haracter)j(string)e(generally)h(should)e(con)m(tain)i(3)g (tok)m(ens:)38 b(\(1\))25 b(the)f(KEYNAME,)h(\(2\))0 2497 y(the)h(V)-10 b(ALUE,)26 b(and)f(\(3\))i(the)f(COMMENT)g(string.) 39 b(The)25 b(TEMPLA)-8 b(TE)26 b(string)g(m)m(ust)f(adhere)h(to)g(the) g(follo)m(wing)0 2610 y(format:)0 2869 y Fi(-)80 b Fj(The)24 b(KEYNAME)g(tok)m(en)h(m)m(ust)e(b)s(egin)h(in)f(columns)h(1-8)h(and)e (b)s(e)h(a)g(maxim)m(um)g(of)g(8)g(c)m(haracters)h(long.)39 b(If)24 b(the)227 2982 y(\014rst)32 b(8)h(c)m(haracters)h(of)e(the)h (template)h(line)e(are)h(blank)f(then)g(the)h(remainder)f(of)g(the)h (line)g(is)f(considered)227 3095 y(to)42 b(b)s(e)e(a)h(FITS)f(commen)m (t)h(\(with)g(a)g(blank)f(k)m(eyw)m(ord)h(name\).)72 b(A)41 b(legal)i(FITS)d(k)m(eyw)m(ord)h(name)f(ma)m(y)227 3208 y(only)35 b(con)m(tain)i(the)e(c)m(haracters)h(A-Z,)f(0-9,)j(and)c ('-')i(\(min)m(us)f(sign\))g(and)f(underscore.)54 b(This)34 b(subroutine)227 3321 y(will)42 b(automatically)i(con)m(v)m(ert)f(an)m (y)f(lo)m(w)m(ercase)i(c)m(haracters)e(to)h(upp)s(ercase)d(in)h(the)h (output)f(string.)73 b(If)227 3434 y(KEYNAME)33 b(=)f('COMMENT')h(or)g ('HISTOR)-8 b(Y')32 b(then)h(the)f(remainder)g(of)h(the)g(line)g(is)g (considered)f(to)227 3547 y(b)s(e)e(a)h(FITS)e(COMMENT)h(or)h(HISTOR)-8 b(Y)30 b(record,)g(resp)s(ectiv)m(ely)-8 b(.)0 3806 y Fi(-)80 b Fj(The)26 b(V)-10 b(ALUE)26 b(tok)m(en)h(m)m(ust)e(b)s(e)h (separated)g(from)f(the)i(KEYNAME)f(tok)m(en)h(b)m(y)f(one)g(or)g(more) g(spaces)g(and/or)227 3919 y(an)i('=')g(c)m(haracter.)41 b(The)27 b(datat)m(yp)s(e)i(of)f(the)g(V)-10 b(ALUE)27 b(tok)m(en)i(\(n)m(umeric,)g(logical,)i(or)d(c)m(haracter)h(string\))f (is)227 4032 y(automatically)35 b(determined)c(and)h(the)g(output)f (CARD)h(string)g(is)g(formatted)g(accordingly)-8 b(.)47 b(The)31 b(v)-5 b(alue)227 4145 y(tok)m(en)34 b(ma)m(y)f(b)s(e)f (forced)g(to)i(b)s(e)e(in)m(terpreted)g(as)h(a)g(string)g(\(e.g.)48 b(if)33 b(it)g(is)f(a)h(string)g(of)f(n)m(umeric)h(digits\))g(b)m(y)227 4258 y(enclosing)g(it)f(in)f(single)h(quotes.)45 b(If)31 b(the)h(v)-5 b(alue)32 b(tok)m(en)g(is)g(a)g(c)m(haracter)h(string)e (that)i(con)m(tains)f(1)g(or)g(more)227 4371 y(em)m(b)s(edded)39 b(blank)g(space)h(c)m(haracters)h(or)e(slash)h(\('/'\))h(c)m(haracters) g(then)e(the)g(en)m(tire)i(c)m(haracter)g(string)227 4484 y(m)m(ust)31 b(b)s(e)e(enclosed)i(in)f(single)h(quotes.)0 4743 y Fi(-)80 b Fj(The)28 b(COMMENT)g(tok)m(en)h(is)f(optional,)i(but) e(if)g(presen)m(t)g(m)m(ust)g(b)s(e)g(separated)g(from)g(the)h(V)-10 b(ALUE)28 b(tok)m(en)h(b)m(y)227 4856 y(a)i(blank)f(space)h(or)f(a)h ('/')g(c)m(haracter.)0 5116 y Fi(-)80 b Fj(One)32 b(exception)i(to)f (the)g(ab)s(o)m(v)m(e)h(rules)e(is)g(that)h(if)g(the)f(\014rst)g (non-blank)g(c)m(haracter)i(in)e(the)h(template)h(string)227 5229 y(is)h(a)g(min)m(us)f(sign)h(\('-'\))h(follo)m(w)m(ed)g(b)m(y)f(a) g(single)g(tok)m(en,)i(or)e(a)g(single)g(tok)m(en)h(follo)m(w)m(ed)g(b) m(y)f(an)f(equal)i(sign,)227 5341 y(then)29 b(it)g(is)g(in)m(terpreted) f(as)h(the)g(name)g(of)g(a)g(k)m(eyw)m(ord)g(whic)m(h)f(is)h(to)g(b)s (e)f(deleted)i(from)e(the)h(FITS)f(header.)0 5601 y Fi(-)80 b Fj(The)40 b(second)g(exception)h(is)f(that)h(if)f(the)g(template)h (string)f(starts)g(with)g(a)h(min)m(us)e(sign)h(and)f(is)h(follo)m(w)m (ed)227 5714 y(b)m(y)33 b(2)g(tok)m(ens)g(then)g(the)f(second)h(tok)m (en)h(is)e(in)m(terpreted)h(as)g(the)g(new)f(name)g(for)h(the)g(k)m (eyw)m(ord)g(sp)s(eci\014ed)p eop end %%Page: 74 80 TeXDict begin 74 79 bop 0 299 a Fj(74)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)227 555 y Fj(b)m(y)k(\014rst)e(tok)m(en.)52 b(In)33 b(this)g(case)i(the)e(old)h(k)m(eyw)m(ord)g(name)g(\(\014rst)f (tok)m(en\))i(is)e(returned)g(in)g(c)m(haracters)i(1-8)227 668 y(of)e(the)g(returned)e(CARD)i(string,)g(and)f(the)h(new)f(k)m(eyw) m(ord)h(name)g(\(the)g(second)f(tok)m(en\))i(is)f(returned)e(in)227 781 y(c)m(haracters)c(41-48)h(of)e(the)f(returned)g(CARD)g(string.)40 b(These)25 b(old)h(and)f(new)g(names)g(ma)m(y)h(then)f(b)s(e)g(passed) 227 894 y(to)31 b(the)g(FTMNAM)g(subroutine)f(whic)m(h)g(will)g(c)m (hange)i(the)e(k)m(eyw)m(ord)h(name.)0 1158 y(The)f(HDTYPE)g(output)g (parameter)h(indicates)g(ho)m(w)g(the)f(returned)g(CARD)g(string)g (should)g(b)s(e)g(in)m(terpreted:)382 1422 y Ff(hdtype)857 b(interpretation)382 1535 y(------)523 b(-------------------------)o (----)o(---)o(----)o(----)o(---)o(----)o(--)525 1648 y(-2)572 b(Modify)46 b(the)h(name)g(of)g(the)g(keyword)f(given)g(in)h (CARD\(1:8\))1193 1761 y(to)g(the)g(new)g(name)g(given)f(in)h (CARD\(41:48\))525 1986 y(-1)572 b(CARD\(1:8\))45 b(contains)h(the)h (name)g(of)g(a)g(keyword)f(to)h(be)g(deleted)1193 2099 y(from)g(the)g(FITS)f(header.)573 2325 y(0)572 b(append)46 b(the)h(CARD)g(string)f(to)h(the)g(FITS)g(header)f(if)h(the)1193 2438 y(keyword)f(does)h(not)g(already)e(exist,)h(otherwise)g(update) 1193 2551 y(the)h(value/comment)d(if)j(the)g(keyword)f(is)h(already)f (present)1193 2664 y(in)h(the)g(header.)573 2890 y(1)572 b(simply)46 b(append)g(this)h(keyword)f(to)h(the)g(FITS)g(header)f (\(CARD)1193 3003 y(is)h(either)f(a)i(HISTORY)e(or)h(COMMENT)f (keyword\).)573 3228 y(2)572 b(This)47 b(is)g(a)g(FITS)g(END)g(record;) f(it)h(should)f(not)h(be)g(written)1193 3341 y(to)g(the)g(FITS)g (header)f(because)g(FITSIO)g(automatically)1193 3454 y(appends)g(the)h(END)g(record)f(when)h(the)f(header)h(is)g(closed.)0 3718 y Fj(EXAMPLES:)30 b(The)g(follo)m(wing)i(lines)e(illustrate)i(v)-5 b(alid)31 b(input)e(template)j(strings:)286 3982 y Ff(INTVAL)46 b(7)i(This)f(is)g(an)g(integer)f(keyword)286 4095 y(RVAL)524 b(34.6)142 b(/)239 b(This)46 b(is)i(a)f(floating)f(point)g(keyword)286 4208 y(EVAL=-12.45E-03)92 b(This)46 b(is)i(a)f(floating)f(point)g (keyword)g(in)h(exponential)e(notation)286 4321 y(lval)i(F)g(This)g(is) g(a)h(boolean)e(keyword)859 4434 y(This)h(is)g(a)g(comment)f(keyword)g (with)h(a)g(blank)f(keyword)g(name)286 4547 y(SVAL1)h(=)g('Hello)f (world')142 b(/)95 b(this)47 b(is)g(a)g(string)f(keyword)286 4660 y(SVAL2)94 b('123.5')g(this)47 b(is)g(also)f(a)i(string)e(keyword) 286 4772 y(sval3)94 b(123+)h(/)g(this)47 b(is)g(also)f(a)i(string)e (keyword)g(with)g(the)h(value)g('123+)189 b(')286 4885 y(#)48 b(the)f(following)e(template)h(line)g(deletes)g(the)h(DATE)g (keyword)286 4998 y(-)h(DATE)286 5111 y(#)g(the)f(following)e(template) h(line)g(modifies)g(the)h(NAME)f(keyword)g(to)h(OBJECT)286 5224 y(-)h(NAME)e(OBJECT)0 5488 y Fi(18)g Fj(P)m(arse)35 b(the)g(input)f(string)h(con)m(taining)h(a)f(list)h(of)f(ro)m(ws)f(or)h (ro)m(w)g(ranges,)h(and)e(return)g(in)m(teger)i(arra)m(ys)f(con-)227 5601 y(taining)27 b(the)f(\014rst)f(and)g(last)i(ro)m(w)f(in)f(eac)m(h) i(range.)40 b(F)-8 b(or)26 b(example,)i(if)d(ro)m(wlist)i(=)e("3-5,)k (6,)e(8-9")h(then)d(it)i(will)227 5714 y(return)34 b(n)m(umranges)h(=)g (3,)h(rangemin)f(=)g(3,)i(6,)g(8)e(and)g(rangemax)g(=)g(5,)i(6,)g(9.)55 b(A)m(t)36 b(most,)h('maxranges')p eop end %%Page: 75 81 TeXDict begin 75 80 bop 0 299 a Fh(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fj(75)227 555 y(n)m(um)m(b)s(er)31 b(of)h(ranges)f(will)h(b)s(e)g(returned.)43 b('maxro)m(ws')32 b(is)g(the)g(maxim)m(um)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)f(the)h (table;)227 668 y(an)m(y)e(ro)m(ws)f(or)g(ranges)g(larger)h(than)f (this)g(will)g(b)s(e)g(ignored.)40 b(The)29 b(ro)m(ws)g(m)m(ust)g(b)s (e)f(sp)s(eci\014ed)h(in)f(increasing)227 781 y(order,)33 b(and)f(the)g(ranges)h(m)m(ust)f(not)g(o)m(v)m(erlap.)48 b(A)33 b(min)m(us)e(sign)i(ma)m(y)g(b)s(e)e(use)h(to)h(sp)s(ecify)f (all)h(the)g(ro)m(ws)f(to)227 894 y(the)h(upp)s(er)d(or)j(lo)m(w)m(er)h (b)s(ound,)d(so)i("50-")h(means)e(all)i(the)f(ro)m(ws)f(from)g(50)h(to) h(the)e(end)g(of)h(the)f(table,)j(and)227 1007 y("-")d(means)e(all)h (the)g(ro)m(ws)f(in)g(the)h(table,)g(from)f(1)h(-)g(maxro)m(ws.)191 1267 y Ff(FTRWRG\(rowlist,)44 b(maxrows,)h(maxranges,)g(>)525 1380 y(numranges,)g(rangemin,)g(rangemax,)h(status\))p eop end %%Page: 76 82 TeXDict begin 76 81 bop 0 299 a Fj(76)1319 b Fh(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)p eop end %%Page: 77 83 TeXDict begin 77 82 bop 0 1225 a Fg(Chapter)65 b(7)0 1687 y Fm(The)77 b(CFITSIO)f(Iterator)i(F)-19 b(unction)0 2180 y Fj(The)41 b(\014ts)p 325 2180 28 4 v 33 w(iterate)p 614 2180 V 34 w(data)i(function)e(in)h(CFITSIO)e(pro)m(vides)i(a)g (unique)e(metho)s(d)i(of)g(executing)h(an)e(arbitrary)0 2293 y(user-supplied)35 b(`w)m(ork')i(function)f(that)h(op)s(erates)g (on)g(ro)m(ws)f(of)h(data)g(in)f(FITS)g(tables)h(or)f(on)h(pixels)f(in) h(FITS)0 2406 y(images.)i(Rather)24 b(than)e(explicitly)j(reading)e (and)g(writing)g(the)g(FITS)g(images)h(or)f(columns)g(of)g(data,)i(one) f(instead)0 2518 y(calls)36 b(the)g(CFITSIO)d(iterator)k(routine,)g (passing)e(to)h(it)g(the)f(name)g(of)h(the)f(user's)g(w)m(ork)g (function)g(that)h(is)f(to)0 2631 y(b)s(e)30 b(executed)h(along)g(with) f(a)h(list)g(of)f(all)h(the)f(table)i(columns)e(or)g(image)h(arra)m(ys) g(that)g(are)f(to)h(b)s(e)f(passed)g(to)h(the)0 2744 y(w)m(ork)37 b(function.)61 b(The)37 b(CFITSIO)e(iterator)k(function)e (then)g(do)s(es)g(all)h(the)f(w)m(ork)g(of)h(allo)s(cating)h(memory)e (for)0 2857 y(the)28 b(arra)m(ys,)h(reading)f(the)g(input)e(data)j (from)e(the)h(FITS)f(\014le,)h(passing)g(them)g(to)g(the)g(w)m(ork)g (function,)g(and)f(then)0 2970 y(writing)36 b(an)m(y)h(output)f(data)h (bac)m(k)h(to)f(the)f(FITS)g(\014le)g(after)h(the)g(w)m(ork)g(function) f(exits.)59 b(Because)38 b(it)f(is)g(often)0 3083 y(more)g(e\016cien)m (t)i(to)f(pro)s(cess)f(only)g(a)h(subset)f(of)g(the)g(total)i(table)g (ro)m(ws)e(at)h(one)f(time,)j(the)e(iterator)g(function)0 3196 y(can)31 b(determine)f(the)h(optim)m(um)f(amoun)m(t)h(of)f(data)h (to)g(pass)f(in)g(eac)m(h)i(iteration)f(and)f(rep)s(eatedly)h(call)g (the)g(w)m(ork)0 3309 y(function)f(un)m(til)h(the)f(en)m(tire)i(table)f (b)s(een)e(pro)s(cessed.)0 3469 y(F)-8 b(or)37 b(man)m(y)f (applications)h(this)e(single)i(CFITSIO)d(iterator)k(function)d(can)h (e\013ectiv)m(ely)j(replace)e(all)g(the)f(other)0 3582 y(CFITSIO)g(routines)i(for)f(reading)h(or)f(writing)h(data)g(in)f(FITS) g(images)i(or)e(tables.)64 b(Using)37 b(the)h(iterator)h(has)0 3695 y(sev)m(eral)32 b(imp)s(ortan)m(t)e(adv)-5 b(an)m(tages)32 b(o)m(v)m(er)g(the)f(traditional)g(metho)s(d)f(of)h(reading)f(and)g (writing)g(FITS)g(data)h(\014les:)136 3961 y Fd(\017)46 b Fj(It)33 b(cleanly)h(separates)g(the)f(data)h(I/O)f(from)f(the)h (routine)g(that)h(op)s(erates)f(on)g(the)g(data.)49 b(This)32 b(leads)h(to)227 4074 y(a)e(more)g(mo)s(dular)e(and)h(`ob)5 b(ject)31 b(orien)m(ted')h(programming)e(st)m(yle.)136 4268 y Fd(\017)46 b Fj(It)27 b(simpli\014es)f(the)h(application)h (program)f(b)m(y)f(eliminating)i(the)f(need)g(to)g(allo)s(cate)i (memory)e(for)f(the)h(data)227 4381 y(arra)m(ys)e(and)f(eliminates)i (most)e(of)h(the)f(calls)i(to)f(the)g(CFITSIO)d(routines)j(that)g (explicitly)h(read)e(and)g(write)227 4494 y(the)31 b(data.)136 4689 y Fd(\017)46 b Fj(It)32 b(ensures)e(that)i(the)g(data)g(are)g(pro) s(cessed)f(as)h(e\016cien)m(tly)h(as)e(p)s(ossible.)44 b(This)31 b(is)g(esp)s(ecially)i(imp)s(ortan)m(t)227 4801 y(when)44 b(pro)s(cessing)g(tabular)h(data)h(since)f(the)g (iterator)h(function)e(will)h(calculate)i(the)e(most)g(e\016cien)m(t) 227 4914 y(n)m(um)m(b)s(er)36 b(of)i(ro)m(ws)g(in)f(the)h(table)g(to)g (b)s(e)f(passed)g(at)i(one)e(time)i(to)f(the)g(user's)e(w)m(ork)i (function)f(on)h(eac)m(h)227 5027 y(iteration.)136 5222 y Fd(\017)46 b Fj(Mak)m(es)39 b(it)e(p)s(ossible)g(for)g(larger)h(pro)5 b(jects)37 b(to)h(dev)m(elop)g(a)g(library)e(of)i(w)m(ork)f(functions)f (that)i(all)g(ha)m(v)m(e)h(a)227 5335 y(uniform)29 b(calling)j (sequence)f(and)f(are)h(all)g(indep)s(enden)m(t)e(of)i(the)f(details)i (of)e(the)h(FITS)e(\014le)i(format.)0 5601 y(There)f(are)h(basically)h (2)g(steps)e(in)h(using)f(the)h(CFITSIO)e(iterator)j(function.)42 b(The)30 b(\014rst)g(step)h(is)g(to)g(design)g(the)0 5714 y(w)m(ork)26 b(function)f(itself)h(whic)m(h)f(m)m(ust)h(ha)m(v)m (e)g(a)g(prescrib)s(ed)e(set)i(of)g(input)f(parameters.)39 b(One)25 b(of)h(these)g(parameters)1905 5942 y(77)p eop end %%Page: 78 84 TeXDict begin 78 83 bop 0 299 a Fj(78)1455 b Fh(CHAPTER)30 b(7.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(is)f(a)g(structure)g(con)m(taining)i(p)s(oin)m(ters)d(to)i (the)f(arra)m(ys)h(of)f(data;)h(the)f(w)m(ork)h(function)e(can)i(p)s (erform)d(an)m(y)i(desired)0 668 y(op)s(erations)k(on)h(these)f(arra)m (ys)h(and)e(do)s(es)h(not)g(need)g(to)h(w)m(orry)f(ab)s(out)g(ho)m(w)g (the)h(input)e(data)i(w)m(ere)f(read)g(from)0 781 y(the)e(\014le)f(or)g (ho)m(w)h(the)f(output)g(data)h(get)h(written)e(bac)m(k)h(to)h(the)e (\014le.)0 941 y(The)24 b(second)h(step)g(is)f(to)i(design)e(the)h (driv)m(er)g(routine)f(that)i(op)s(ens)e(all)h(the)g(necessary)g(FITS)f (\014les)h(and)f(initializes)0 1054 y(the)41 b(input)g(parameters)g(to) h(the)g(iterator)g(function.)73 b(The)41 b(driv)m(er)g(program)g(calls) h(the)g(CFITSIO)e(iterator)0 1167 y(function)30 b(whic)m(h)g(then)g (reads)g(the)h(data)g(and)f(passes)g(it)h(to)g(the)g(user's)e(w)m(ork)i (function.)0 1327 y(F)-8 b(urther)41 b(details)i(on)f(using)f(the)h (iterator)h(function)f(can)g(b)s(e)f(found)f(in)i(the)g(companion)g (CFITSIO)e(User's)0 1440 y(Guide,)31 b(and)e(in)h(the)h(iter)p 874 1440 28 4 v 33 w(a.f,)g(iter)p 1197 1440 V 34 w(b.f)f(and)f(iter)p 1677 1440 V 34 w(c.f)h(example)h(programs.)p eop end %%Page: 79 85 TeXDict begin 79 84 bop 0 1225 a Fg(Chapter)65 b(8)0 1687 y Fm(Extended)77 b(File)g(Name)g(Syn)-6 b(tax)0 2216 y Fe(8.1)135 b(Ov)l(erview)0 2466 y Fj(CFITSIO)30 b(supp)s(orts)f(an)j(extended)f(syn)m(tax)h(when)f(sp)s(ecifying)g(the) h(name)f(of)h(the)g(data)g(\014le)f(to)h(b)s(e)f(op)s(ened)g(or)0 2579 y(created)g(that)g(includes)f(the)h(follo)m(wing)h(features:)136 2813 y Fd(\017)46 b Fj(CFITSIO)40 b(can)i(read)f(IRAF)h(format)g (images)g(whic)m(h)f(ha)m(v)m(e)i(header)e(\014le)h(names)f(that)h(end) f(with)g(the)227 2926 y('.imh')d(extension,)i(as)e(w)m(ell)g(as)g (reading)f(and)g(writing)g(FITS)g(\014les,)i(This)e(feature)h(is)f (implemen)m(ted)h(in)227 3039 y(CFITSIO)29 b(b)m(y)i(\014rst)e(con)m(v) m(erting)k(the)d(IRAF)h(image)h(in)m(to)f(a)g(temp)s(orary)f(FITS)g (format)h(\014le)f(in)g(memory)-8 b(,)227 3152 y(then)35 b(op)s(ening)f(the)h(FITS)f(\014le.)54 b(An)m(y)35 b(of)g(the)g(usual)f (CFITSIO)g(routines)g(then)h(ma)m(y)g(b)s(e)f(used)g(to)i(read)227 3265 y(the)31 b(image)g(header)f(or)h(data.)41 b(Similarly)-8 b(,)31 b(ra)m(w)f(binary)g(data)h(arra)m(ys)f(can)h(b)s(e)f(read)g(b)m (y)g(con)m(v)m(erting)i(them)227 3378 y(on)f(the)f(\015y)g(in)m(to)h (virtual)g(FITS)f(images.)136 3557 y Fd(\017)46 b Fj(FITS)37 b(\014les)g(on)g(the)g(In)m(ternet)h(can)f(b)s(e)g(read)g(\(and)g (sometimes)h(written\))f(using)g(the)g(FTP)-8 b(,)38 b(HTTP)-8 b(,)37 b(or)227 3670 y(R)m(OOT)30 b(proto)s(cols.)136 3849 y Fd(\017)46 b Fj(FITS)30 b(\014les)g(can)h(b)s(e)f(pip)s(ed)f(b)s (et)m(w)m(een)i(tasks)f(on)h(the)f(stdin)g(and)g(stdout)g(streams.)136 4028 y Fd(\017)46 b Fj(FITS)20 b(\014les)h(can)g(b)s(e)f(read)g(and)g (written)h(in)f(shared)g(memory)-8 b(.)38 b(This)20 b(can)h(p)s(oten)m (tially)h(ac)m(hiev)m(e)h(m)m(uc)m(h)e(b)s(etter)227 4141 y(data)26 b(I/O)e(p)s(erformance)g(compared)h(to)h(reading)f(and)f (writing)g(the)h(same)h(FITS)e(\014les)g(on)h(magnetic)h(disk.)136 4320 y Fd(\017)46 b Fj(Compressed)30 b(FITS)f(\014les)i(in)f(gzip)h(or) f(Unix)g(COMPRESS)f(format)h(can)h(b)s(e)f(directly)h(read.)136 4499 y Fd(\017)46 b Fj(Output)28 b(FITS)h(\014les)g(can)g(b)s(e)g (written)g(directly)h(in)e(compressed)h(gzip)h(format,)g(th)m(us)e(sa)m (ving)i(disk)f(space.)136 4678 y Fd(\017)46 b Fj(FITS)26 b(table)h(columns)f(can)h(b)s(e)f(created,)i(mo)s(di\014ed,)f(or)f (deleted)h('on-the-\015y')g(as)g(the)g(table)g(is)f(op)s(ened)g(b)m(y) 227 4791 y(CFITSIO.)32 b(This)h(creates)i(a)e(virtual)h(FITS)f(\014le)g (con)m(taining)i(the)f(mo)s(di\014cations)f(that)h(is)g(then)f(op)s (ened)227 4904 y(b)m(y)e(the)f(application)i(program.)136 5083 y Fd(\017)46 b Fj(T)-8 b(able)29 b(ro)m(ws)e(ma)m(y)i(b)s(e)e (selected,)j(or)e(\014ltered)g(out,)g(on)g(the)g(\015y)f(when)g(the)h (table)h(is)f(op)s(ened)f(b)m(y)g(CFITSIO,)227 5196 y(based)f(on)h(an)f (arbitrary)h(user-sp)s(eci\014ed)e(expression.)39 b(Only)26 b(ro)m(ws)h(for)f(whic)m(h)g(the)h(expression)f(ev)-5 b(aluates)227 5309 y(to)31 b('TR)m(UE')g(are)g(retained)g(in)f(the)g (cop)m(y)i(of)e(the)h(table)g(that)g(is)f(op)s(ened)g(b)m(y)g(the)h (application)g(program.)136 5488 y Fd(\017)46 b Fj(Histogram)28 b(images)g(ma)m(y)f(b)s(e)f(created)h(on)f(the)h(\015y)f(b)m(y)g (binning)g(the)g(v)-5 b(alues)27 b(in)f(table)i(columns,)f(resulting) 227 5601 y(in)36 b(a)g(virtual)h(N-dimensional)f(FITS)g(image.)59 b(The)35 b(application)i(program)f(then)g(only)g(sees)g(the)h(FITS)227 5714 y(image)32 b(\(in)e(the)h(primary)e(arra)m(y\))j(instead)e(of)h (the)f(original)i(FITS)d(table.)1905 5942 y(79)p eop end %%Page: 80 86 TeXDict begin 80 85 bop 0 299 a Fj(80)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)43 b(latter)i(3)f(features)g(in)f(particular)h(add)f(v)m (ery)h(p)s(o)m(w)m(erful)f(data)h(pro)s(cessing)f(capabilities)j (directly)e(in)m(to)0 668 y(CFITSIO,)29 b(and)g(hence)h(in)m(to)h(ev)m (ery)f(task)h(that)f(uses)g(CFITSIO)e(to)j(read)f(or)g(write)g(FITS)f (\014les.)40 b(F)-8 b(or)31 b(example,)0 781 y(these)d(features)f (transform)f(a)i(v)m(ery)f(simple)g(program)g(that)h(just)f(copies)h (an)f(input)f(FITS)g(\014le)h(to)h(a)g(new)e(output)0 894 y(\014le)36 b(\(lik)m(e)h(the)f(`\014tscop)m(y')h(program)f(that)g (is)g(distributed)f(with)g(CFITSIO\))g(in)m(to)i(a)f(m)m(ultipurp)s (ose)f(FITS)g(\014le)0 1007 y(pro)s(cessing)24 b(to)s(ol.)40 b(By)25 b(app)s(ending)f(fairly)g(simple)h(quali\014ers)g(on)m(to)g (the)g(name)g(of)g(the)g(input)f(FITS)g(\014le,)i(the)f(user)0 1120 y(can)37 b(p)s(erform)f(quite)i(complex)g(table)g(editing)g(op)s (erations)f(\(e.g.,)k(create)e(new)d(columns,)j(or)e(\014lter)h(out)f (ro)m(ws)0 1233 y(in)g(a)g(table\))h(or)f(create)h(FITS)f(images)h(b)m (y)f(binning)e(or)i(histogramming)h(the)f(v)-5 b(alues)37 b(in)g(table)h(columns.)60 b(In)0 1346 y(addition,)33 b(these)g(functions)e(ha)m(v)m(e)j(b)s(een)d(co)s(ded)h(using)f(new)h (state-of-the)i(art)f(algorithms)g(that)g(are,)g(in)f(some)0 1458 y(cases,)g(10)f(-)f(100)i(times)f(faster)g(than)f(previous)g (widely)g(used)g(implemen)m(tations.)0 1619 y(Before)k(describing)f (the)h(complete)h(syn)m(tax)f(for)f(the)h(extended)f(FITS)g(\014le)g (names)g(in)g(the)h(next)g(section,)h(here)0 1732 y(are)c(a)g(few)f (examples)h(of)f(FITS)g(\014le)g(names)h(that)f(giv)m(e)i(a)f(quic)m(k) g(o)m(v)m(erview)h(of)f(the)f(allo)m(w)m(ed)i(syn)m(tax:)136 1960 y Fd(\017)46 b Ff('myfile.fits')p Fj(:)37 b(the)31 b(simplest)f(case)i(of)e(a)h(FITS)f(\014le)g(on)h(disk)e(in)i(the)f (curren)m(t)g(directory)-8 b(.)136 2137 y Fd(\017)46 b Ff('myfile.imh')p Fj(:)37 b(op)s(ens)28 b(an)h(IRAF)g(format)g(image) i(\014le)e(and)f(con)m(v)m(erts)i(it)g(on)f(the)g(\015y)f(in)m(to)i(a)f (temp)s(orary)227 2250 y(FITS)h(format)h(image)g(in)f(memory)h(whic)m (h)f(can)g(then)g(b)s(e)g(read)g(with)g(an)m(y)h(other)g(CFITSIO)e (routine.)136 2427 y Fd(\017)46 b Ff(rawfile.dat[i512,512])p Fj(:)35 b(op)s(ens)30 b(a)g(ra)m(w)h(binary)e(data)i(arra)m(y)g(\(a)g (512)g(x)f(512)i(short)e(in)m(teger)h(arra)m(y)g(in)227 2540 y(this)i(case\))i(and)d(con)m(v)m(erts)j(it)e(on)g(the)g(\015y)g (in)m(to)h(a)f(temp)s(orary)g(FITS)f(format)h(image)i(in)d(memory)h (whic)m(h)227 2652 y(can)e(then)f(b)s(e)g(read)g(with)g(an)m(y)h(other) f(CFITSIO)f(routine.)136 2830 y Fd(\017)46 b Ff(myfile.fits.gz)p Fj(:)d(if)33 b(this)g(is)g(the)g(name)g(of)h(a)f(new)g(output)g (\014le,)h(the)f('.gz')i(su\016x)d(will)h(cause)h(it)g(to)g(b)s(e)227 2942 y(compressed)c(in)g(gzip)h(format)g(when)e(it)i(is)g(written)f(to) h(disk.)136 3120 y Fd(\017)46 b Ff('myfile.fits.gz[events,)c(2]')p Fj(:)59 b(op)s(ens)40 b(and)f(uncompresses)g(the)i(gzipp)s(ed)e(\014le) i(m)m(y\014le.\014ts)f(then)227 3232 y(mo)m(v)m(es)34 b(to)f(the)f(extension)h(whic)m(h)f(has)f(the)i(k)m(eyw)m(ords)f (EXTNAME)g(=)g('EVENTS')g(and)g(EXTVER)f(=)227 3345 y(2.)136 3522 y Fd(\017)46 b Ff('-')p Fj(:)40 b(a)31 b(dash)f(\(min)m(us)g (sign\))h(signi\014es)f(that)h(the)g(input)f(\014le)g(is)h(to)g(b)s(e)f (read)g(from)g(the)h(stdin)f(\014le)g(stream,)227 3635 y(or)h(that)g(the)f(output)g(\014le)h(is)f(to)h(b)s(e)f(written)g(to)h (the)g(stdout)f(stream.)136 3812 y Fd(\017)46 b Ff ('ftp://legacy.gsfc.nasa.g)o(ov/t)o(est/)o(vel)o(a.fi)o(ts')p Fj(:)33 b(FITS)28 b(\014les)g(in)g(an)m(y)g(ftp)g(arc)m(hiv)m(e)i(site) f(on)f(the)227 3925 y(In)m(ternet)j(ma)m(y)g(b)s(e)f(directly)h(op)s (ened)e(with)h(read-only)h(access.)136 4102 y Fd(\017)46 b Ff('http://legacy.gsfc.nasa.)o(gov/)o(soft)o(war)o(e/te)o(st.f)o(its) o(')p Fj(:)d(an)m(y)34 b(v)-5 b(alid)35 b(URL)f(to)h(a)f(FITS)g(\014le) g(on)227 4215 y(the)d(W)-8 b(eb)31 b(ma)m(y)g(b)s(e)f(op)s(ened)f(with) h(read-only)h(access.)136 4392 y Fd(\017)46 b Ff ('root://legacy.gsfc.nasa.)o(gov/)o(test)o(/ve)o(la.f)o(its')o Fj(:)32 b(similar)24 b(to)g(ftp)f(access)i(except)g(that)f(it)g(pro-) 227 4505 y(vides)30 b(write)h(as)f(w)m(ell)h(as)g(read)f(access)h(to)g (the)f(\014les)h(across)f(the)h(net)m(w)m(ork.)41 b(This)29 b(uses)h(the)h(ro)s(ot)f(proto)s(col)227 4618 y(dev)m(elop)s(ed)h(at)g (CERN.)136 4795 y Fd(\017)46 b Ff('shmem://h2[events]')p Fj(:)35 b(op)s(ens)30 b(the)g(FITS)f(\014le)i(in)f(a)g(shared)f(memory) i(segmen)m(t)g(and)e(mo)m(v)m(es)j(to)f(the)227 4908 y(EVENTS)f(extension.)136 5085 y Fd(\017)46 b Ff('mem://')p Fj(:)52 b(creates)39 b(a)e(scratc)m(h)i(output)d(\014le)i(in)e(core)i (computer)f(memory)-8 b(.)62 b(The)37 b(resulting)g('\014le')h(will)227 5198 y(disapp)s(ear)25 b(when)f(the)i(program)f(exits,)i(so)f(this)f (is)h(mainly)f(useful)g(for)g(testing)i(purp)s(oses)c(when)i(one)g(do)s (es)227 5311 y(not)31 b(w)m(an)m(t)g(a)g(p)s(ermanen)m(t)f(cop)m(y)h (of)f(the)h(output)f(\014le.)136 5488 y Fd(\017)46 b Ff('myfile.fits[3;)e(Images\(10\)]')p Fj(:)49 b(op)s(ens)35 b(a)i(cop)m(y)g(of)f(the)g(image)i(con)m(tained)f(in)f(the)h(10th)f(ro) m(w)h(of)227 5601 y(the)26 b('Images')i(column)d(in)h(the)g(binary)g (table)g(in)g(the)g(3th)h(extension)f(of)g(the)h(FITS)e(\014le.)39 b(The)26 b(application)227 5714 y(just)k(sees)h(this)f(single)h(image)h (as)e(the)h(primary)e(arra)m(y)-8 b(.)p eop end %%Page: 81 87 TeXDict begin 81 86 bop 0 299 a Fh(8.1.)72 b(O)m(VER)-10 b(VIEW)3086 b Fj(81)136 555 y Fd(\017)46 b Ff('myfile.fits[1:512:2,)c (1:512:2]')p Fj(:)49 b(op)s(ens)35 b(a)h(section)h(of)e(the)h(input)f (image)i(ranging)f(from)f(the)227 668 y(1st)26 b(to)g(the)f(512th)h (pixel)g(in)e(X)i(and)e(Y,)i(and)e(selects)j(ev)m(ery)e(second)h(pixel) f(in)g(b)s(oth)f(dimensions,)i(resulting)227 781 y(in)k(a)h(256)h(x)e (256)i(pixel)e(image)i(in)e(this)g(case.)136 981 y Fd(\017)46 b Ff('myfile.fits[EVENTS][col)41 b(Rad)47 b(=)h(sqrt\(X**2)d(+)j (Y**2\)]')p Fj(:)38 b(creates)30 b(and)f(op)s(ens)f(a)h(temp)s(orary) 227 1094 y(\014le)f(on)f(the)g(\015y)g(\(in)g(memory)g(or)g(on)h (disk\))f(that)g(is)h(iden)m(tical)h(to)f(m)m(y\014le.\014ts)f(except)h (that)g(it)g(will)g(con)m(tain)227 1207 y(a)41 b(new)f(column)g(in)h (the)f(EVENTS)g(extension)h(called)h('Rad')f(whose)f(v)-5 b(alue)41 b(is)f(computed)h(using)f(the)227 1320 y(indicated)31 b(expression)f(whic)m(h)g(is)h(a)g(function)f(of)g(the)h(v)-5 b(alues)30 b(in)h(the)f(X)h(and)e(Y)i(columns.)136 1520 y Fd(\017)46 b Ff('myfile.fits[EVENTS][PHA)41 b(>)48 b(5]')p Fj(:)37 b(creates)27 b(and)e(op)s(ens)g(a)h(temp)s(orary)f (FITS)g(\014les)g(that)h(is)g(iden)m(ti-)227 1633 y(cal)k(to)g('m)m (y\014le.\014ts')f(except)h(that)f(the)g(EVENTS)f(table)i(will)f(only)g (con)m(tain)h(the)f(ro)m(ws)g(that)h(ha)m(v)m(e)g(v)-5 b(alues)227 1746 y(of)28 b(the)g(PHA)f(column)g(greater)i(than)e(5.)40 b(In)27 b(general,)i(an)m(y)f(arbitrary)f(b)s(o)s(olean)h(expression)f (using)g(a)h(C)f(or)227 1859 y(F)-8 b(ortran-lik)m(e)31 b(syn)m(tax,)e(whic)m(h)f(ma)m(y)h(com)m(bine)g(AND)g(and)f(OR)f(op)s (erators,)i(ma)m(y)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)227 1972 y(from)g(a)h(table.)136 2172 y Fd(\017)46 b Ff ('myfile.fits[EVENTS][bin)41 b(\(X,Y\)=1,2048,4]')p Fj(:)46 b(creates)37 b(a)e(temp)s(orary)g(FITS)f(primary)g(arra)m(y)227 2285 y(image)c(whic)m(h)f(is)g(computed)f(on)h(the)g(\015y)f(b)m(y)g (binning)g(\(i.e,)j(computing)d(the)h(2-dimensional)h(histogram\))227 2398 y(of)k(the)f(v)-5 b(alues)34 b(in)f(the)h(X)g(and)e(Y)i(columns)f (of)h(the)f(EVENTS)g(extension.)50 b(In)33 b(this)g(case)i(the)e(X)h (and)f(Y)227 2511 y(co)s(ordinates)h(range)g(from)f(1)h(to)g(2048)h (and)e(the)h(image)g(pixel)g(size)g(is)g(4)f(units)g(in)g(b)s(oth)g (dimensions,)h(so)227 2624 y(the)d(resulting)f(image)i(is)e(512)i(x)e (512)i(pixels)f(in)f(size.)136 2824 y Fd(\017)46 b Fj(The)31 b(\014nal)g(example)i(com)m(bines)f(man)m(y)f(of)h(these)g(feature)g (in)m(to)g(one)g(complex)g(expression)f(\(it)i(is)e(brok)m(en)227 2937 y(in)m(to)h(sev)m(eral)f(lines)g(for)f(clarit)m(y\):)323 3206 y Ff('ftp://legacy.gsfc.nasa)o(.gov)o(/dat)o(a/s)o(ampl)o(e.fi)o (ts.)o(gz[E)o(VENT)o(S])370 3319 y([col)47 b(phacorr)f(=)h(pha)g(*)h (1.1)f(-)g(0.3][phacorr)e(>=)i(5.0)g(&&)g(phacorr)f(<=)h(14.0])370 3432 y([bin)g(\(X,Y\)=32]')227 3701 y Fj(In)37 b(this)h(case,)j (CFITSIO)36 b(\(1\))j(copies)g(and)e(uncompresses)g(the)h(FITS)f (\014le)h(from)f(the)h(ftp)f(site)i(on)f(the)227 3814 y(legacy)g(mac)m(hine,)h(\(2\))e(mo)m(v)m(es)g(to)g(the)g('EVENTS')f (extension,)i(\(3\))f(calculates)i(a)d(new)g(column)g(called)227 3927 y('phacorr',)30 b(\(4\))f(selects)h(the)f(ro)m(ws)g(in)f(the)h (table)h(that)f(ha)m(v)m(e)h(phacorr)e(in)g(the)h(range)g(5)g(to)h(14,) g(and)e(\014nally)227 4040 y(\(5\))35 b(bins)d(the)h(remaining)g(ro)m (ws)g(on)h(the)f(X)g(and)g(Y)g(column)g(co)s(ordinates,)i(using)d(a)i (pixel)f(size)h(=)f(32)h(to)227 4153 y(create)d(a)f(2D)g(image.)42 b(All)30 b(this)f(pro)s(cessing)g(is)h(completely)h(transparen)m(t)e (to)i(the)e(application)i(program,)227 4266 y(whic)m(h)f(simply)g(sees) h(the)g(\014nal)f(2-D)h(image)h(in)e(the)g(primary)g(arra)m(y)h(of)f (the)h(op)s(ened)f(\014le.)0 4538 y(The)c(full)h(extended)g(CFITSIO)e (FITS)h(\014le)h(name)g(can)g(con)m(tain)h(sev)m(eral)g(di\013eren)m(t) g(comp)s(onen)m(ts)f(dep)s(ending)e(on)0 4651 y(the)31 b(con)m(text.)42 b(These)30 b(comp)s(onen)m(ts)h(are)g(describ)s(ed)e (in)h(the)g(follo)m(wing)i(sections:)0 4924 y Ff(When)47 b(creating)e(a)j(new)f(file:)143 5036 y(filetype://BaseFilename\(t)o (empl)o(ate)o(Name)o(\))0 5262 y(When)g(opening)e(an)j(existing)d (primary)h(array)g(or)i(image)e(HDU:)143 5375 y (filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o(loca)o(tio)o(n][I)o (mage)o(Sec)o(tion)o(])0 5601 y(When)h(opening)e(an)j(existing)d(table) i(HDU:)143 5714 y(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o (loca)o(tio)o(n][c)o(olFi)o(lte)o(r][r)o(owFi)o(lte)o(r][b)o(inSp)o (ec])p eop end %%Page: 82 88 TeXDict begin 82 87 bop 0 299 a Fj(82)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)41 b(\014let)m(yp)s(e,)k(BaseFilename,)i(outName,)e(HDUlo) s(cation,)i(and)41 b(ImageSection)i(comp)s(onen)m(ts,)i(if)d(presen)m (t,)0 668 y(m)m(ust)30 b(b)s(e)g(giv)m(en)i(in)e(that)h(order,)g(but)f (the)g(colFilter,)j(ro)m(wFilter,)g(and)c(binSp)s(ec)h(sp)s(eci\014ers) f(ma)m(y)j(follo)m(w)f(in)g(an)m(y)0 781 y(order.)39 b(Regardless)29 b(of)g(the)f(order,)g(ho)m(w)m(ev)m(er,)i(the)f (colFilter)h(sp)s(eci\014er,)e(if)g(presen)m(t,)h(will)g(b)s(e)e(pro)s (cessed)h(\014rst)f(b)m(y)0 894 y(CFITSIO,)i(follo)m(w)m(ed)j(b)m(y)e (the)h(ro)m(wFilter)h(sp)s(eci\014er,)e(and)f(\014nally)i(b)m(y)f(the)g (binSp)s(ec)f(sp)s(eci\014er.)0 1054 y(Multiple)40 b(colFilter)i(or)e (ro)m(wFilter)h(sp)s(eci\014cations)f(ma)m(y)g(app)s(ear)f(as)h (separated)g(brac)m(k)m(eted)h(expressions,)h(in)0 1167 y(an)m(y)c(order.)62 b(Multiple)39 b(colFilter)h(or)d(ro)m(wFilter)i (expressions)f(are)g(treated)g(in)m(ternally)h(as)f(a)g(single)g (e\013ectiv)m(e)0 1280 y(expression,)30 b(with)f(order)h(of)g(op)s (erations)g(determined)f(from)h(left)g(to)h(righ)m(t.)41 b(CFITSIO)28 b(do)s(es)i(not)g(supp)s(ort)e(the)0 1393 y(@\014lename.txt)j(complex)g(syn)m(tax)g(option)g(if)f(m)m(ultiple)h (expressions)f(are)h(also)h(used.)0 1719 y Fe(8.2)135 b(Filet)l(yp)t(e)0 1969 y Fj(The)37 b(t)m(yp)s(e)g(of)g(\014le)g (determines)g(the)g(medium)f(on)h(whic)m(h)g(the)g(\014le)g(is)h(lo)s (cated)g(\(e.g.,)i(disk)d(or)g(net)m(w)m(ork\))h(and,)0 2082 y(hence,)f(whic)m(h)e(in)m(ternal)h(device)g(driv)m(er)f(is)g (used)f(b)m(y)h(CFITSIO)f(to)i(read)f(and/or)g(write)g(the)g(\014le.)56 b(Curren)m(tly)0 2195 y(supp)s(orted)29 b(t)m(yp)s(es)h(are)382 2405 y Ff(file://)93 b(-)48 b(file)e(on)i(local)e(magnetic)g(disk)g (\(default\))382 2518 y(ftp://)141 b(-)48 b(a)f(readonly)f(file)g (accessed)g(with)h(the)g(anonymous)e(FTP)i(protocol.)907 2631 y(It)g(also)g(supports)93 b(ftp://username:password@)o(host)o(nam) o(e/..)o(.)907 2744 y(for)47 b(accessing)e(password-protected)e(ftp)k (sites.)382 2857 y(http://)93 b(-)48 b(a)f(readonly)f(file)g(accessed)g (with)h(the)g(HTTP)f(protocol.)93 b(It)907 2969 y(supports)45 b(username:password)e(just)k(like)g(the)g(ftp)g(driver.)907 3082 y(Proxy)f(HTTP)h(servers)f(are)h(supported)e(using)h(the)h (http_proxy)907 3195 y(environment)e(variable)g(\(see)i(following)e (note\).)286 3308 y(stream://)93 b(-)48 b(special)e(driver)g(to)h(read) g(an)g(input)f(FITS)h(file)f(from)h(the)g(stdin)907 3421 y(stream,)f(and/or)g(write)g(an)h(output)f(FITS)h(file)g(to)g(the)g (stdout)143 3534 y(stream.)94 b(This)46 b(driver)g(is)i(fragile)d(and)i (has)g(limited)143 3647 y(functionality)d(\(see)j(the)g(following)e (note\).)286 3760 y(gsiftp://)93 b(-)48 b(access)e(files)g(on)h(a)h (computational)c(grid)j(using)f(the)h(gridftp)907 3873 y(protocol)e(in)j(the)e(Globus)h(toolkit)e(\(see)i(following)e(note\).) 382 3986 y(root://)93 b(-)48 b(uses)e(the)h(CERN)g(root)g(protocol)e (for)i(writing)f(as)h(well)g(as)907 4099 y(reading)f(files)g(over)h (the)g(network.)382 4212 y(shmem://)e(-)j(opens)e(or)h(creates)f(a)i (file)e(which)h(persists)e(in)i(the)g(computer's)907 4324 y(shared)f(memory.)382 4437 y(mem://)141 b(-)48 b(opens)e(a)i(temporary)d(file)i(in)g(core)f(memory.)94 b(The)47 b(file)907 4550 y(disappears)e(when)h(the)h(program)f(exits)h (so)g(this)f(is)i(mainly)907 4663 y(useful)e(for)h(test)f(purposes)g (when)h(a)g(permanent)e(output)h(file)907 4776 y(is)h(not)g(desired.)0 4986 y Fj(If)35 b(the)h(\014let)m(yp)s(e)g(is)f(not)h(sp)s(eci\014ed,)h (then)e(t)m(yp)s(e)h(\014le://)h(is)e(assumed.)56 b(The)35 b(double)g(slashes)h('//')h(are)f(optional)0 5099 y(and)30 b(ma)m(y)h(b)s(e)e(omitted)j(in)e(most)h(cases.)0 5382 y Fc(8.2.1)112 b(Notes)37 b(ab)s(out)i(HTTP)d(pro)m(xy)i(serv)m(ers)0 5601 y Fj(A)32 b(pro)m(xy)g(HTTP)f(serv)m(er)h(ma)m(y)h(b)s(e)e(used)g (b)m(y)h(de\014ning)f(the)h(address)f(\(URL\))i(and)e(p)s(ort)g(n)m(um) m(b)s(er)g(of)h(the)g(pro)m(xy)0 5714 y(serv)m(er)f(with)f(the)g(h)m (ttp)p 801 5714 28 4 v 33 w(pro)m(xy)g(en)m(vironmen)m(t)h(v)-5 b(ariable.)42 b(F)-8 b(or)31 b(example)p eop end %%Page: 83 89 TeXDict begin 83 88 bop 0 299 a Fh(8.2.)72 b(FILETYPE)3128 b Fj(83)191 555 y Ff(setenv)46 b(http_proxy)f(http://heasarc.gsfc.nasa) o(.gov)o(:312)o(8)0 798 y Fj(will)38 b(cause)g(CFITSIO)f(to)h(use)g(p)s (ort)f(3128)i(on)f(the)g(heasarc)g(pro)m(xy)g(serv)m(er)g(whenev)m(er)g (reading)g(a)g(FITS)f(\014le)0 911 y(with)30 b(HTTP)-8 b(.)0 1199 y Fc(8.2.2)112 b(Notes)37 b(ab)s(out)i(the)e(stream)h (\014let)m(yp)s(e)g(driv)m(er)0 1418 y Fj(The)e(stream)h(driv)m(er)f (can)h(b)s(e)f(used)g(to)h(e\016cien)m(tly)i(read)d(a)h(FITS)f(\014le)h (from)f(the)h(stdin)f(\014le)g(stream)h(or)g(write)0 1531 y(a)44 b(FITS)e(to)i(the)g(stdout)f(\014le)g(stream.)80 b(Ho)m(w)m(ev)m(er,)49 b(b)s(ecause)43 b(these)h(input)e(and)h(output)g (streams)g(m)m(ust)h(b)s(e)0 1644 y(accessed)30 b(sequen)m(tially)-8 b(,)31 b(the)e(FITS)f(\014le)g(reading)h(or)f(writing)h(application)h (m)m(ust)e(also)i(read)e(and)g(write)h(the)g(\014le)0 1757 y(sequen)m(tially)-8 b(,)33 b(at)e(least)g(within)f(the)h (tolerances)h(describ)s(ed)d(b)s(elo)m(w.)0 1917 y(CFITSIO)34 b(supp)s(orts)f(2)j(di\013eren)m(t)f(metho)s(ds)g(for)g(accessing)i (FITS)d(\014les)h(on)h(the)f(stdin)g(and)f(stdout)h(streams.)0 2030 y(The)c(original)i(metho)s(d,)f(whic)m(h)f(is)h(in)m(v)m(ok)m(ed)h (b)m(y)f(sp)s(ecifying)f(a)h(dash)f(c)m(haracter,)j("-",)g(as)d(the)h (name)g(of)g(the)g(\014le)0 2143 y(when)g(op)s(ening)g(or)h(creating)h (it,)g(w)m(orks)e(b)m(y)h(storing)g(a)g(complete)h(cop)m(y)g(of)f(the)g (en)m(tire)g(FITS)f(\014le)h(in)f(memory)-8 b(.)0 2256 y(In)35 b(this)g(case,)k(when)34 b(reading)i(from)f(stdin,)i(CFITSIO)d (will)i(cop)m(y)h(the)e(en)m(tire)i(stream)f(in)m(to)h(memory)e(b)s (efore)0 2368 y(doing)c(an)m(y)h(pro)s(cessing)f(of)h(the)f(\014le.)44 b(Similarly)-8 b(,)32 b(when)f(writing)g(to)h(stdout,)g(CFITSIO)d(will) j(create)h(a)f(cop)m(y)g(of)0 2481 y(the)h(en)m(tire)g(FITS)f(\014le)g (in)h(memory)-8 b(,)33 b(b)s(efore)f(\014nally)h(\015ushing)e(it)i(out) f(to)i(the)e(stdout)h(stream)g(when)e(the)i(FITS)0 2594 y(\014le)g(is)g(closed.)49 b(Bu\013ering)33 b(the)g(en)m(tire)h(FITS)e (\014le)h(in)g(this)f(w)m(a)m(y)i(allo)m(ws)g(the)f(application)i(to)e (randomly)g(access)0 2707 y(an)m(y)h(part)f(of)h(the)f(FITS)g(\014le,)i (in)e(an)m(y)h(order,)f(but)g(it)h(also)h(requires)e(that)h(the)f(user) g(ha)m(v)m(e)i(su\016cien)m(t)f(a)m(v)-5 b(ailable)0 2820 y(memory)30 b(\(or)g(virtual)g(memory\))g(to)h(store)f(the)g(en)m (tire)h(\014le,)f(whic)m(h)f(ma)m(y)i(not)f(b)s(e)f(p)s(ossible)g(in)h (the)g(case)h(of)f(v)m(ery)0 2933 y(large)h(\014les.)0 3093 y(The)e(new)m(er)g(stream)h(\014let)m(yp)s(e)g(pro)m(vides)f(a)h (more)f(memory-e\016cien)m(t)i(metho)s(d)e(of)h(accessing)h(FITS)d (\014les)h(on)h(the)0 3206 y(stdin)37 b(or)h(stdout)g(streams.)64 b(Instead)38 b(of)g(storing)g(a)g(cop)m(y)h(of)f(the)g(en)m(tire)h (FITS)e(\014le)h(in)g(memory)-8 b(,)40 b(CFITSIO)0 3319 y(only)32 b(uses)g(a)g(set)h(of)f(in)m(ternal)h(bu\013er)e(whic)m(h)h (b)m(y)g(default)g(can)g(store)h(40)g(FITS)e(blo)s(c)m(ks,)i(or)g(ab)s (out)e(100K)i(b)m(ytes)0 3432 y(of)f(the)f(FITS)g(\014le.)43 b(The)31 b(application)i(program)e(m)m(ust)g(pro)s(cess)g(the)h(FITS)e (\014le)i(sequen)m(tially)h(from)e(b)s(eginning)0 3545 y(to)h(end,)e(within)g(this)h(100K)h(bu\013er.)41 b(Generally)32 b(sp)s(eaking)f(the)g(application)h(program)f(m)m(ust)f(conform)h(to)h (the)0 3658 y(follo)m(wing)g(restrictions:)136 3901 y Fd(\017)46 b Fj(The)36 b(program)f(m)m(ust)h(\014nish)e(reading)i(or)g (writing)f(the)h(header)g(k)m(eyw)m(ords)g(b)s(efore)f(reading)h(or)g (writing)227 4013 y(an)m(y)31 b(data)g(in)f(the)h(HDU.)136 4195 y Fd(\017)46 b Fj(The)24 b(HDU)h(can)f(con)m(tain)i(at)e(most)h (ab)s(out)f(1400)h(header)f(k)m(eyw)m(ords.)39 b(This)24 b(is)g(the)g(maxim)m(um)g(that)h(can)f(\014t)227 4308 y(in)g(the)g(nominal)h(40)g(FITS)e(blo)s(c)m(k)i(bu\013er.)37 b(In)24 b(principle,)h(this)f(limit)h(could)f(b)s(e)g(increased)g(b)m (y)g(recompiling)227 4421 y(CFITSIO)29 b(with)h(a)h(larger)g(bu\013er)e (limit,)j(whic)m(h)e(is)g(set)h(b)m(y)f(the)h(NIOBUF)g(parameter)g(in)f (\014tsio2.h.)136 4603 y Fd(\017)46 b Fj(The)32 b(program)g(m)m(ust)f (read)h(or)g(write)h(the)f(data)g(in)g(a)g(sequen)m(tial)i(manner)d (from)h(the)g(b)s(eginning)f(to)i(the)227 4716 y(end)26 b(of)g(the)h(HDU.)g(Note)h(that)f(CFITSIO's)e(in)m(ternal)i(100K)g (bu\013er)e(allo)m(ws)j(a)e(little)j(latitude)e(in)f(meeting)227 4829 y(this)31 b(requiremen)m(t.)136 5011 y Fd(\017)46 b Fj(The)30 b(program)g(cannot)h(mo)m(v)m(e)h(bac)m(k)f(to)g(a)g (previous)f(HDU)h(in)f(the)h(FITS)e(\014le.)136 5193 y Fd(\017)46 b Fj(Reading)c(or)f(writing)f(of)h(v)-5 b(ariable)42 b(length)f(arra)m(y)h(columns)e(in)h(binary)f(tables)i(is) f(not)g(supp)s(orted)e(on)227 5306 y(streams,)29 b(b)s(ecause)f(this)g (requires)g(mo)m(ving)g(bac)m(k)h(and)f(forth)f(b)s(et)m(w)m(een)i(the) f(\014xed-length)g(p)s(ortion)g(of)g(the)227 5419 y(binary)i(table)h (and)f(the)g(follo)m(wing)i(heap)e(area)i(where)e(the)g(arra)m(ys)h (are)g(actually)h(stored.)136 5601 y Fd(\017)46 b Fj(Reading)25 b(or)g(writing)f(of)h(tile-compressed)h(images)g(is)e(not)h(supp)s (orted)e(on)h(streams,)i(b)s(ecause)f(the)g(images)227 5714 y(are)31 b(in)m(ternally)g(stored)g(using)f(v)-5 b(ariable)31 b(length)g(arra)m(ys.)p eop end %%Page: 84 90 TeXDict begin 84 89 bop 0 299 a Fj(84)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fc(8.2.3)112 b(Notes)37 b(ab)s(out)i(the)e(gsiftp)h(\014let)m(yp) s(e)0 774 y Fj(DEPENDENCIES:)c(Globus)h(to)s(olkit)h(\(2.4.3)g(or)f (higher\))f(\(GT\))h(should)f(b)s(e)g(installed.)53 b(There)34 b(are)h(t)m(w)m(o)h(dif-)0 887 y(feren)m(t)31 b(w)m(a)m(ys)g(to)g (install)g(GT:)0 1047 y(1\))43 b(goto)h(the)f(globus)f(to)s(olkit)i(w)m (eb)e(page)i(www.globus.org)e(and)g(follo)m(w)h(the)g(do)m(wnload)g (and)e(compilation)0 1160 y(instructions;)0 1320 y(2\))j(goto)i(the)d (Virtual)i(Data)g(T)-8 b(o)s(olkit)45 b(w)m(eb)e(page)i(h)m (ttp://vdt.cs.wisc.edu/)g(and)e(follo)m(w)i(the)f(instructions)0 1433 y(\(STR)m(ONGL)-8 b(Y)31 b(SUGGESTED\);)0 1593 y(Once)23 b(a)h(globus)f(clien)m(t)h(has)f(b)s(een)g(installed)h(in)e(y)m(our)i (system)f(with)g(a)g(sp)s(eci\014c)g(\015a)m(v)m(our)h(it)f(is)g(p)s (ossible)g(to)h(compile)0 1706 y(and)30 b(install)h(the)g(CFITSIO)d (libraries.)41 b(Sp)s(eci\014c)30 b(con\014guration)h(\015ags)f(m)m (ust)h(b)s(e)e(used:)0 1866 y(1\))21 b({with-gsiftp[[=P)-8 b(A)g(TH]])22 b(Enable)f(Globus)f(T)-8 b(o)s(olkit)21 b(gsiftp)g(proto)s(col)g(supp)s(ort)d(P)-8 b(A)g(TH=GLOBUS)p 3532 1866 28 4 v 33 w(LOCA)g(TION)0 1979 y(i.e.)42 b(the)30 b(lo)s(cation)i(of)f(y)m(our)f(globus)g(installation)0 2139 y(2\))h({with-gsiftp-\015a)m(v)m(our[[=P)-8 b(A)g(TH])33 b(de\014nes)d(the)g(sp)s(eci\014c)g(Globus)h(\015a)m(v)m(our)f(ex.)41 b(gcc32)0 2300 y(Both)31 b(the)g(\015ags)f(m)m(ust)g(b)s(e)g(used)g (and)f(it)i(is)g(mandatory)f(to)h(set)g(b)s(oth)f(the)g(P)-8 b(A)g(TH)31 b(and)f(the)h(\015a)m(v)m(our.)0 2460 y(USA)m(GE:)g(T)-8 b(o)31 b(access)h(\014les)e(on)g(a)h(gridftp)f(serv)m(er)g(it)h(is)g (necessary)f(to)i(use)e(a)g(gsiftp)h(pre\014x:)0 2620 y(example:)41 b(gsiftp://remote)p 1003 2620 V 35 w(serv)m(er)p 1271 2620 V 34 w(fqhn/directory/\014lename)0 2780 y(The)f(gridftp)g (driv)m(er)g(uses)g(a)g(lo)s(cal)i(bu\013er)d(on)i(a)f(temp)s(orary)g (\014le)h(the)f(\014le)h(is)f(lo)s(cated)i(in)e(the)g(/tmp)h(direc-)0 2893 y(tory)-8 b(.)73 b(If)40 b(y)m(ou)h(ha)m(v)m(e)h(sp)s(ecial)g(p)s (ermissions)d(on)i(/tmp)g(or)g(y)m(ou)g(do)f(not)i(ha)m(v)m(e)g(a)f (/tmp)g(directory)-8 b(,)44 b(it)e(is)e(p)s(os-)0 3006 y(sible)d(to)h(force)g(another)g(lo)s(cation)g(setting)h(the)e(GSIFTP)p 2068 3006 V 32 w(TMPFILE)g(en)m(vironmen)m(t)h(v)-5 b(ariable)38 b(\(ex.)62 b(exp)s(ort)0 3119 y(GSIFTP)p 347 3119 V 32 w(TMPFILE=/y)m(our/lo)s(cation/y)m(ourtmp\014le\).)0 3279 y(Grid)34 b(FTP)g(supp)s(orts)f(m)m(ulti)h(c)m(hannel)h(transfer.) 52 b(By)35 b(default)f(a)h(single)g(c)m(hannel)g(transmission)f(is)g(a) m(v)-5 b(ailable.)0 3392 y(Ho)m(w)m(ev)m(er,)34 b(it)d(is)h(p)s (ossible)e(to)i(mo)s(dify)e(this)i(b)s(eha)m(vior)f(setting)h(the)f (GSIFTP)p 2691 3392 V 33 w(STREAMS)f(en)m(vironmen)m(t)h(v)-5 b(ari-)0 3505 y(able)31 b(\(ex.)41 b(exp)s(ort)30 b(GSIFTP)p 1016 3505 V 33 w(STREAMS=8\).)0 3790 y Fc(8.2.4)112 b(Notes)37 b(ab)s(out)i(the)e(ro)s(ot)g(\014let)m(yp)s(e)0 4009 y Fj(The)20 b(original)j(ro)s(otd)d(serv)m(er)h(can)h(b)s(e)e(obtained) h(from:)36 b Ff(ftp://root.cern.ch/root)o(/roo)o(td.t)o(ar.)o(gz)15 b Fj(but,)22 b(for)0 4122 y(it)33 b(to)h(w)m(ork)f(correctly)h(with)e (CFITSIO)g(one)h(has)f(to)i(use)e(a)i(mo)s(di\014ed)d(v)m(ersion)j (whic)m(h)e(supp)s(orts)f(a)i(command)0 4235 y(to)41 b(return)d(the)j(length)f(of)g(the)g(\014le.)70 b(This)39 b(mo)s(di\014ed)f(v)m(ersion)j(is)f(a)m(v)-5 b(ailable)42 b(in)e(ro)s(otd)f(sub)s(directory)g(in)h(the)0 4348 y(CFITSIO)29 b(ftp)h(area)h(at)286 4577 y Ff(ftp://legacy.gsfc.nasa.gov)o(/so)o (ftwa)o(re/f)o(its)o(io/c)o(/roo)o(t/r)o(ootd)o(.tar)o(.gz)o(.)0 4805 y Fj(This)j(small)g(serv)m(er)h(is)g(started)f(either)h(b)m(y)g (inetd)f(when)f(a)i(clien)m(t)h(requests)e(a)h(connection)h(to)f(a)f (ro)s(otd)h(serv)m(er)0 4918 y(or)30 b(b)m(y)g(hand)f(\(i.e.)42 b(from)30 b(the)g(command)g(line\).)42 b(The)29 b(ro)s(otd)h(serv)m(er) h(w)m(orks)f(with)g(the)g(R)m(OOT)g(TNetFile)i(class.)0 5031 y(It)e(allo)m(ws)g(remote)h(access)f(to)h(R)m(OOT)e(database)h (\014les)f(in)g(either)h(read)g(or)f(write)h(mo)s(de.)40 b(By)30 b(default)f(TNetFile)0 5144 y(assumes)38 b(p)s(ort)g(432)h (\(whic)m(h)f(requires)g(ro)s(otd)g(to)h(b)s(e)f(started)h(as)f(ro)s (ot\).)65 b(T)-8 b(o)39 b(run)e(ro)s(otd)h(via)h(inetd)f(add)g(the)0 5257 y(follo)m(wing)32 b(line)f(to)g(/etc/services:)95 5485 y Ff(rootd)238 b(432/tcp)0 5714 y Fj(and)30 b(to)h (/etc/inetd.conf,)i(add)d(the)g(follo)m(wing)i(line:)p eop end %%Page: 85 91 TeXDict begin 85 90 bop 0 299 a Fh(8.2.)72 b(FILETYPE)3128 b Fj(85)95 555 y Ff(rootd)47 b(stream)f(tcp)h(nowait)f(root)h (/user/rdm/root/bin/root)o(d)42 b(rootd)k(-i)0 829 y Fj(F)-8 b(orce)34 b(inetd)e(to)i(reread)e(its)h(conf)f(\014le)h(with)f ("kill)h(-HUP)g(".)47 b(Y)-8 b(ou)33 b(can)g(also)g(start) g(ro)s(otd)g(b)m(y)f(hand)0 942 y(running)j(directly)i(under)d(y)m(our) j(priv)-5 b(ate)37 b(accoun)m(t)g(\(no)g(ro)s(ot)g(system)f(privileges) h(needed\).)59 b(F)-8 b(or)37 b(example)g(to)0 1054 y(start)e(ro)s(otd) e(listening)i(on)f(p)s(ort)f(5151)j(just)d(t)m(yp)s(e:)49 b Ff(rootd)d(-p)h(5151)33 b Fj(Notice:)50 b(no)34 b(&)f(is)h(needed.)51 b(Ro)s(otd)35 b(will)0 1167 y(go)c(in)m(to)h(bac)m(kground)e(b)m(y)g (itself.)95 1441 y Ff(Rootd)47 b(arguments:)191 1554 y(-i)763 b(says)47 b(we)g(were)f(started)g(by)h(inetd)191 1667 y(-p)g(port#)476 b(specifies)45 b(a)j(different)d(port)i(to)g (listen)f(on)191 1780 y(-d)h(level)476 b(level)46 b(of)i(debug)e(info)h (written)e(to)j(syslog)1050 1893 y(0)f(=)h(no)f(debug)f(\(default\)) 1050 2005 y(1)h(=)h(minimum)1050 2118 y(2)f(=)h(medium)1050 2231 y(3)f(=)h(maximum)0 2505 y Fj(Ro)s(otd)29 b(can)f(also)h(b)s(e)f (con\014gured)g(for)g(anon)m(ymous)g(usage)h(\(lik)m(e)h(anon)m(ymous)e (ftp\).)40 b(T)-8 b(o)29 b(setup)f(ro)s(otd)g(to)h(accept)0 2618 y(anon)m(ymous)h(logins)h(do)g(the)f(follo)m(wing)i(\(while)f(b)s (eing)f(logged)i(in)e(as)g(ro)s(ot\):)143 2891 y Ff(-)48 b(Add)f(the)f(following)g(line)g(to)i(/etc/passwd:)239 3117 y(rootd:*:71:72:Anonymous)41 b(rootd:/var/spool/rootd:/b)o(in/)o (fals)o(e)239 3343 y(where)46 b(you)h(may)g(modify)f(the)h(uid,)f(gid)h (\(71,)g(72\))g(and)g(the)g(home)f(directory)239 3456 y(to)h(suite)f(your)h(system.)143 3681 y(-)h(Add)f(the)f(following)g (line)g(to)i(/etc/group:)239 3907 y(rootd:*:72:rootd)239 4133 y(where)e(the)h(gid)g(must)f(match)h(the)g(gid)g(in)g (/etc/passwd.)143 4359 y(-)h(Create)e(the)h(directories:)239 4585 y(mkdir)f(/var/spool/rootd)239 4698 y(mkdir)g (/var/spool/rootd/tmp)239 4811 y(chmod)g(777)h(/var/spool/rootd/tmp)239 5036 y(Where)f(/var/spool/rootd)d(must)k(match)f(the)h(rootd)g(home)f (directory)g(as)239 5149 y(specified)f(in)i(the)g(rootd)f(/etc/passwd)f (entry.)143 5375 y(-)j(To)f(make)f(writeable)g(directories)e(for)j (anonymous)f(do,)h(for)f(example:)239 5601 y(mkdir)g (/var/spool/rootd/pub)239 5714 y(chown)g(rootd:rootd)f (/var/spool/rootd/pub)p eop end %%Page: 86 92 TeXDict begin 86 91 bop 0 299 a Fj(86)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(That's)42 b(all.)76 b(Sev)m(eral)43 b(additional)g(remarks:)64 b(y)m(ou)42 b(can)g(login)h(to)g(an)f(anon)m(ymous)f(serv)m(er)i (either)f(with)g(the)0 668 y(names)31 b("anon)m(ymous")h(or)f("ro)s (otd".)43 b(The)31 b(passw)m(ord)f(should)g(b)s(e)h(of)g(t)m(yp)s(e)g (user@host.do.main.)43 b(Only)30 b(the)h(@)0 781 y(is)e(enforced)f(for) h(the)f(time)i(b)s(eing.)39 b(In)28 b(anon)m(ymous)h(mo)s(de)f(the)g (top)h(of)g(the)g(\014le)f(tree)i(is)e(set)h(to)h(the)e(ro)s(otd)h (home)0 894 y(directory)-8 b(,)39 b(therefore)e(only)f(\014les)h(b)s (elo)m(w)f(the)h(home)f(directory)h(can)f(b)s(e)g(accessed.)60 b(Anon)m(ymous)36 b(mo)s(de)g(only)0 1007 y(w)m(orks)30 b(when)g(the)g(serv)m(er)h(is)f(started)h(via)g(inetd.)0 1296 y Fc(8.2.5)112 b(Notes)37 b(ab)s(out)i(the)e(shmem)i(\014let)m(yp) s(e:)0 1515 y Fj(Shared)34 b(memory)h(\014les)g(are)g(curren)m(tly)g (supp)s(orted)e(on)i(most)h(Unix)f(platforms,)h(where)f(the)g(shared)f (memory)0 1627 y(segmen)m(ts)d(are)g(managed)g(b)m(y)f(the)g(op)s (erating)h(system)g(k)m(ernel)f(and)g(`liv)m(e')i(indep)s(enden)m(tly)d (of)i(pro)s(cesses.)40 b(They)0 1740 y(are)34 b(not)g(deleted)h(\(b)m (y)f(default\))g(when)f(the)h(pro)s(cess)f(whic)m(h)h(created)h(them)f (terminates,)h(although)g(they)f(will)0 1853 y(disapp)s(ear)e(if)h(the) h(system)f(is)g(reb)s(o)s(oted.)49 b(Applications)34 b(can)g(create)h(shared)d(memory)h(\014les)g(in)g(CFITSIO)f(b)m(y)0 1966 y(calling:)143 2214 y Ff(fit_create_file\(&fitsfile)o(ptr,)41 b("shmem://h2",)j(&status\);)0 2462 y Fj(where)25 b(the)g(ro)s(ot)h (`\014le')f(names)h(are)f(curren)m(tly)g(restricted)h(to)g(b)s(e)f ('h0',)i('h1',)g('h2',)g('h3',)f(etc.,)i(up)d(to)g(a)h(maxim)m(um)0 2575 y(n)m(um)m(b)s(er)20 b(de\014ned)f(b)m(y)i(the)g(the)g(v)-5 b(alue)22 b(of)f(SHARED)p 1746 2575 28 4 v 33 w(MAXSEG)g(\(equal)h(to)f (16)h(b)m(y)f(default\).)38 b(This)20 b(is)h(a)g(protot)m(yp)s(e)0 2688 y(implemen)m(tation)30 b(of)f(the)g(shared)f(memory)g(in)m (terface)i(and)e(a)h(more)g(robust)f(in)m(terface,)j(whic)m(h)d(will)h (ha)m(v)m(e)h(few)m(er)0 2801 y(restrictions)h(on)f(the)h(n)m(um)m(b)s (er)e(of)i(\014les)f(and)g(on)g(their)g(names,)h(ma)m(y)g(b)s(e)f(dev)m (elop)s(ed)g(in)g(the)h(future.)0 2961 y(When)23 b(op)s(ening)h(an)f (already)h(existing)h(FITS)e(\014le)h(in)f(shared)g(memory)h(one)g (calls)g(the)g(usual)g(CFITSIO)e(routine:)143 3209 y Ff(fits_open_file\(&fitsfilep)o(tr,)41 b("shmem://h7",)j(mode,)j (&status\))0 3457 y Fj(The)26 b(\014le)h(mo)s(de)g(can)g(b)s(e)f(READ)m (WRITE)h(or)g(READONL)-8 b(Y)28 b(just)e(as)h(with)f(disk)h(\014les.)39 b(More)28 b(than)e(one)h(pro)s(cess)0 3570 y(can)35 b(op)s(erate)g(on)f (READONL)-8 b(Y)35 b(mo)s(de)f(\014les)h(at)g(the)f(same)h(time.)54 b(CFITSIO)33 b(supp)s(orts)f(prop)s(er)h(\014le)i(lo)s(c)m(king)0 3682 y(\(b)s(oth)27 b(in)h(READONL)-8 b(Y)29 b(and)e(READ)m(WRITE)h(mo) s(des\),)h(so)f(calls)h(to)f(\014ts)p 2572 3682 V 33 w(op)s(en)p 2795 3682 V 32 w(\014le)g(ma)m(y)g(b)s(e)f(lo)s(c)m(k)m(ed) j(out)e(un)m(til)0 3795 y(another)j(other)f(pro)s(cess)g(closes)i(the)e (\014le.)0 3956 y(When)g(an)g(application)i(is)e(\014nished)f (accessing)j(a)e(FITS)g(\014le)g(in)g(a)h(shared)e(memory)h(segmen)m (t,)i(it)f(ma)m(y)g(close)g(it)0 4068 y(\(and)j(the)g(\014le)g(will)g (remain)f(in)h(the)g(system\))g(with)g(\014ts)p 1955 4068 V 32 w(close)p 2173 4068 V 34 w(\014le,)h(or)f(delete)h(it)g(with) e(\014ts)p 3191 4068 V 33 w(delete)p 3455 4068 V 34 w(\014le.)51 b(Ph)m(ys-)0 4181 y(ical)36 b(deletion)g(is)f(p)s(ostp)s(oned)e(un)m (til)j(the)f(last)g(pro)s(cess)g(calls)h(\013clos/\013delt.)56 b(\014ts)p 2801 4181 V 32 w(delete)p 3064 4181 V 34 w(\014le)35 b(tries)h(to)f(obtain)h(a)0 4294 y(READ)m(WRITE)e(lo)s(c)m(k)g(on)f (the)g(\014le)h(to)g(b)s(e)e(deleted,)j(th)m(us)e(it)h(can)f(b)s(e)g (blo)s(c)m(k)m(ed)h(if)f(the)h(ob)5 b(ject)34 b(w)m(as)f(not)h(op)s (ened)0 4407 y(in)c(READ)m(WRITE)h(mo)s(de.)0 4567 y(A)i(shared)f (memory)h(managemen)m(t)h(utilit)m(y)g(program)f(called)h(`smem',)f(is) g(included)f(with)h(the)g(CFITSIO)e(dis-)0 4680 y(tribution.)39 b(It)27 b(can)g(b)s(e)f(built)h(b)m(y)g(t)m(yping)g(`mak)m(e)h(smem';)g (then)f(t)m(yp)s(e)g(`smem)f(-h')h(to)h(get)g(a)f(list)g(of)g(v)-5 b(alid)27 b(options.)0 4793 y(Executing)37 b(smem)f(without)g(an)m(y)h (options)g(causes)f(it)h(to)g(list)g(all)g(the)g(shared)e(memory)i (segmen)m(ts)g(curren)m(tly)0 4906 y(residing)c(in)g(the)g(system)h (and)e(managed)i(b)m(y)f(the)h(shared)e(memory)h(driv)m(er.)49 b(T)-8 b(o)34 b(get)g(a)g(list)g(of)f(all)h(the)g(shared)0 5019 y(memory)c(ob)5 b(jects,)32 b(run)d(the)h(system)h(utilit)m(y)g (program)f(`ip)s(cs)h([-a]'.)0 5351 y Fe(8.3)135 b(Base)46 b(Filename)0 5601 y Fj(The)31 b(base)g(\014lename)h(is)f(the)h(name)f (of)h(the)f(\014le)h(optionally)g(including)f(the)h(director/sub)s (directory)f(path,)h(and)0 5714 y(in)e(the)h(case)g(of)g(`ftp',)f(`h)m (ttp',)i(and)d(`ro)s(ot')j(\014let)m(yp)s(es,)e(the)h(mac)m(hine)g (iden)m(ti\014er.)41 b(Examples:)p eop end %%Page: 87 93 TeXDict begin 87 92 bop 0 299 a Fh(8.3.)72 b(BASE)30 b(FILENAME)2830 b Fj(87)191 555 y Ff(myfile.fits)191 668 y(!data.fits)191 781 y(/data/myfile.fits)191 894 y(fits.gsfc.nasa.gov/ftp/s)o(ampl)o(eda)o(ta/m)o(yfil)o(e.f)o(its.)o (gz)0 1120 y Fj(When)29 b(creating)h(a)f(new)f(output)h(\014le)g(on)g (magnetic)h(disk)e(\(of)i(t)m(yp)s(e)f(\014le://\))h(if)f(the)g(base)g (\014lename)g(b)s(egins)f(with)0 1233 y(an)34 b(exclamation)j(p)s(oin)m (t)d(\(!\))54 b(then)34 b(an)m(y)g(existing)i(\014le)e(with)g(that)h (same)g(basename)g(will)g(b)s(e)e(deleted)i(prior)f(to)0 1346 y(creating)h(the)f(new)g(FITS)f(\014le.)51 b(Otherwise)34 b(if)g(the)g(\014le)g(to)g(b)s(e)g(created)h(already)f(exists,)i(then)d (CFITSIO)g(will)0 1459 y(return)g(an)h(error)f(and)g(will)i(not)f(o)m (v)m(erwrite)h(the)f(existing)h(\014le.)52 b(Note)35 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f(')10 b(!',)36 b(is)e(a)0 1572 y(sp)s(ecial)28 b(UNIX)g(c)m(haracter,)j(so)d(if)f(it)i (is)f(used)f(on)g(the)h(command)g(line)g(rather)g(than)f(en)m(tered)h (at)h(a)f(task)h(prompt,)0 1685 y(it)j(m)m(ust)f(b)s(e)g(preceded)g(b)m (y)h(a)g(bac)m(kslash)g(to)g(force)g(the)g(UNIX)g(shell)f(to)h(pass)f (it)i(v)m(erbatim)f(to)g(the)g(application)0 1798 y(program.)0 1958 y(If)24 b(the)i(output)e(disk)h(\014le)g(name)g(ends)f(with)g(the) h(su\016x)f('.gz',)k(then)d(CFITSIO)e(will)i(compress)g(the)g(\014le)g (using)g(the)0 2071 y(gzip)g(compression)f(algorithm)h(b)s(efore)f (writing)g(it)h(to)g(disk.)38 b(This)23 b(can)i(reduce)f(the)g(amoun)m (t)h(of)f(disk)g(space)h(used)0 2184 y(b)m(y)34 b(the)h(\014le.)53 b(Note)36 b(that)f(this)g(feature)g(requires)f(that)h(the)f (uncompressed)g(\014le)g(b)s(e)g(constructed)h(in)f(memory)0 2297 y(b)s(efore)c(it)h(is)f(compressed)g(and)g(written)h(to)g(disk,)f (so)g(it)h(can)g(fail)g(if)f(there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 b(ailable)33 b(memory)-8 b(.)0 2457 y(An)45 b(input)g(FITS)f(\014le)i (ma)m(y)g(b)s(e)f(compressed)g(with)h(the)f(gzip)h(or)g(Unix)f (compress)h(algorithms,)k(in)45 b(whic)m(h)0 2570 y(case)38 b(CFITSIO)e(will)i(uncompress)e(the)i(\014le)g(on)f(the)h(\015y)e(in)m (to)j(a)f(temp)s(orary)f(\014le)g(\(in)h(memory)f(or)g(on)h(disk\).)0 2683 y(Compressed)32 b(\014les)i(ma)m(y)g(only)f(b)s(e)g(op)s(ened)f (with)h(read-only)h(p)s(ermission.)49 b(When)33 b(sp)s(ecifying)g(the)h (name)f(of)h(a)0 2796 y(compressed)h(FITS)g(\014le)h(it)g(is)g(not)g (necessary)g(to)g(app)s(end)e(the)i(\014le)g(su\016x)e(\(e.g.,)39 b(`.gz')e(or)f(`.Z'\).)g(If)f(CFITSIO)0 2908 y(cannot)24 b(\014nd)e(the)h(input)f(\014le)i(name)f(without)g(the)g(su\016x,)h (then)f(it)h(will)g(automatically)i(searc)m(h)e(for)f(a)g(compressed)0 3021 y(\014le)36 b(with)f(the)h(same)g(ro)s(ot)g(name.)57 b(In)35 b(the)h(case)h(of)f(reading)g(ftp)f(and)g(h)m(ttp)h(t)m(yp)s(e) g(\014les,)h(CFITSIO)e(generally)0 3134 y(lo)s(oks)j(for)g(a)g (compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(\014rst,)h(b)s(efore)e (trying)h(to)h(op)s(en)e(the)h(uncompressed)e(\014le.)64 b(By)0 3247 y(default,)37 b(CFITSIO)e(copies)h(\(and)g(uncompressed)e (if)i(necessary\))g(the)g(ftp)f(or)h(h)m(ttp)g(FITS)f(\014le)g(in)m(to) i(memory)0 3360 y(on)f(the)g(lo)s(cal)h(mac)m(hine)f(b)s(efore)g(op)s (ening)f(it.)58 b(This)35 b(will)h(fail)g(if)g(the)g(lo)s(cal)h(mac)m (hine)g(do)s(es)e(not)h(ha)m(v)m(e)h(enough)0 3473 y(memory)g(to)h (hold)f(the)g(whole)h(FITS)e(\014le,)k(so)d(in)g(this)g(case,)k(the)c (output)g(\014lename)g(sp)s(eci\014er)g(\(see)h(the)g(next)0 3586 y(section\))32 b(can)f(b)s(e)e(used)h(to)h(further)e(con)m(trol)j (ho)m(w)e(CFITSIO)f(reads)h(ftp)g(and)g(h)m(ttp)g(\014les.)0 3746 y(If)i(the)h(input)f(\014le)h(is)g(an)g(IRAF)g(image)h(\014le)f (\(*.imh)g(\014le\))h(then)e(CFITSIO)f(will)j(automatically)h(con)m(v)m (ert)g(it)e(on)0 3859 y(the)27 b(\015y)g(in)m(to)h(a)g(virtual)f(FITS)f (image)j(b)s(efore)e(it)g(is)g(op)s(ened)g(b)m(y)g(the)g(application)i (program.)39 b(IRAF)27 b(images)i(can)0 3972 y(only)h(b)s(e)g(op)s (ened)g(with)g(READONL)-8 b(Y)31 b(\014le)f(access.)0 4132 y(Similarly)-8 b(,)32 b(if)f(the)g(input)f(\014le)i(is)f(a)g(ra)m (w)g(binary)f(data)i(arra)m(y)-8 b(,)33 b(then)d(CFITSIO)g(will)h(con)m (v)m(ert)i(it)e(on)g(the)h(\015y)e(in)m(to)0 4245 y(a)38 b(virtual)g(FITS)g(image)h(with)e(the)h(basic)h(set)f(of)g(required)f (header)h(k)m(eyw)m(ords)g(b)s(efore)g(it)g(is)g(op)s(ened)f(b)m(y)h (the)0 4358 y(application)32 b(program)f(\(with)g(READONL)-8 b(Y)31 b(access\).)44 b(In)30 b(this)h(case)h(the)f(data)g(t)m(yp)s(e)g (and)g(dimensions)f(of)h(the)0 4471 y(image)d(m)m(ust)f(b)s(e)f(sp)s (eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)g(the)f (\014lename)g(\(e.g.)41 b(ra)m(w\014le.dat[ib512,512]\).)j(The)0 4584 y(\014rst)30 b(c)m(haracter)i(\(case)f(insensitiv)m(e\))h (de\014nes)e(the)g(datat)m(yp)s(e)h(of)g(the)g(arra)m(y:)239 4810 y Ff(b)429 b(8-bit)46 b(unsigned)g(byte)239 4923 y(i)381 b(16-bit)46 b(signed)g(integer)239 5036 y(u)381 b(16-bit)46 b(unsigned)g(integer)239 5149 y(j)381 b(32-bit)46 b(signed)g(integer)239 5262 y(r)h(or)g(f)143 b(32-bit)46 b(floating)g(point)239 5375 y(d)381 b(64-bit)46 b(floating)g(point)0 5601 y Fj(An)40 b(optional)h(second)f(c)m(haracter)i(sp)s(eci\014es)e (the)h(b)m(yte)f(order)g(of)g(the)h(arra)m(y)g(v)-5 b(alues:)60 b(b)40 b(or)g(B)h(indicates)g(big)0 5714 y(endian)f(\(as)h(in)f(FITS)f (\014les)i(and)f(the)g(nativ)m(e)i(format)e(of)h(SUN)f(UNIX)h(w)m (orkstations)g(and)f(Mac)i(PCs\))e(and)p eop end %%Page: 88 94 TeXDict begin 88 93 bop 0 299 a Fj(88)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(l)41 b(or)g(L)g(indicates)g(little)i(endian)e(\(nativ)m(e)h (format)g(of)f(DEC)f(OSF)h(w)m(orkstations)h(and)e(IBM)i(PCs\).)72 b(If)40 b(this)0 668 y(c)m(haracter)32 b(is)e(omitted)i(then)e(the)g (arra)m(y)h(is)g(assumed)e(to)i(ha)m(v)m(e)h(the)f(nativ)m(e)g(b)m(yte) g(order)f(of)h(the)f(lo)s(cal)i(mac)m(hine.)0 781 y(These)d(datat)m(yp) s(e)h(c)m(haracters)h(are)e(then)g(follo)m(w)m(ed)i(b)m(y)e(a)h(series) f(of)g(one)h(or)f(more)g(in)m(teger)i(v)-5 b(alues)29 b(separated)h(b)m(y)0 894 y(commas)h(whic)m(h)g(de\014ne)e(the)i(size)h (of)e(eac)m(h)i(dimension)e(of)h(the)g(ra)m(w)f(arra)m(y)-8 b(.)43 b(Arra)m(ys)30 b(with)h(up)e(to)j(5)f(dimensions)0 1007 y(are)f(curren)m(tly)g(supp)s(orted.)38 b(Finally)-8 b(,)32 b(a)e(b)m(yte)g(o\013set)g(to)h(the)e(p)s(osition)h(of)g(the)g (\014rst)e(pixel)i(in)g(the)f(data)i(\014le)e(ma)m(y)0 1120 y(b)s(e)d(sp)s(eci\014ed)g(b)m(y)h(separating)h(it)f(with)g(a)g (':')39 b(from)27 b(the)g(last)g(dimension)g(v)-5 b(alue.)40 b(If)26 b(omitted,)j(it)e(is)g(assumed)f(that)0 1233 y(the)35 b(o\013set)h(=)f(0.)54 b(This)35 b(parameter)g(ma)m(y)h(b)s(e) e(used)g(to)i(skip)e(o)m(v)m(er)i(an)m(y)g(header)e(information)i(in)e (the)h(\014le)g(that)0 1346 y(precedes)30 b(the)h(binary)f(data.)41 b(F)-8 b(urther)30 b(examples:)95 1603 y Ff(raw.dat[b10000])521 b(1-dimensional)45 b(10000)h(pixel)g(byte)h(array)95 1715 y(raw.dat[rb400,400,12])233 b(3-dimensional)45 b(floating)g(point) h(big-endian)f(array)95 1828 y(img.fits[ib512,512:2880])89 b(reads)47 b(the)g(512)g(x)g(512)g(short)f(integer)g(array)g(in)1336 1941 y(a)i(FITS)e(file,)h(skipping)e(over)i(the)g(2880)g(byte)f(header) 0 2198 y Fj(One)25 b(sp)s(ecial)g(case)h(of)f(input)f(\014le)h(is)g (where)g(the)g(\014lename)g(=)g(`-')h(\(a)f(dash)g(or)g(min)m(us)f (sign\))h(or)g('stdin')g(or)g('stdout',)0 2311 y(whic)m(h)d (signi\014es)h(that)h(the)f(input)e(\014le)i(is)g(to)h(b)s(e)e(read)g (from)h(the)g(stdin)f(stream,)j(or)e(written)f(to)i(the)f(stdout)g (stream)0 2424 y(if)34 b(a)g(new)g(output)f(\014le)h(is)g(b)s(eing)g (created.)52 b(In)33 b(the)h(case)h(of)f(reading)h(from)e(stdin,)h (CFITSIO)f(\014rst)g(copies)i(the)0 2537 y(whole)g(stream)h(in)m(to)g (a)f(temp)s(orary)g(FITS)f(\014le)i(\(in)f(memory)g(or)g(on)g(disk\),)h (and)f(subsequen)m(t)f(reading)h(of)h(the)0 2650 y(FITS)c(\014le)h(o)s (ccurs)g(in)f(this)h(cop)m(y)-8 b(.)49 b(When)33 b(writing)g(to)g (stdout,)h(CFITSIO)d(\014rst)h(constructs)h(the)g(whole)g(\014le)g(in)0 2763 y(memory)h(\(since)i(random)d(access)j(is)e(required\),)i(then)e (\015ushes)f(it)i(out)g(to)g(the)f(stdout)h(stream)g(when)e(the)i (\014le)0 2876 y(is)30 b(closed.)42 b(In)29 b(addition,)i(if)f(the)g (output)g(\014lename)g(=)g('-.gz')i(or)e('stdout.gz')h(then)f(it)h (will)f(b)s(e)g(gzip)g(compressed)0 2989 y(b)s(efore)g(b)s(eing)g (written)g(to)h(stdout.)0 3149 y(This)25 b(abilit)m(y)j(to)e(read)g (and)f(write)h(on)g(the)g(stdin)g(and)f(stdout)h(steams)g(allo)m(ws)i (FITS)d(\014les)h(to)g(b)s(e)g(pip)s(ed)e(b)s(et)m(w)m(een)0 3262 y(tasks)42 b(in)f(memory)g(rather)g(than)h(ha)m(ving)g(to)g (create)h(temp)s(orary)e(in)m(termediate)i(FITS)d(\014les)i(on)f(disk.) 73 b(F)-8 b(or)0 3375 y(example)28 b(if)e(task1)i(creates)h(an)e (output)f(FITS)g(\014le,)i(and)f(task2)g(reads)g(an)g(input)f(FITS)g (\014le,)i(the)f(FITS)f(\014le)h(ma)m(y)0 3487 y(b)s(e)j(pip)s(ed)f(b)s (et)m(w)m(een)i(the)f(2)h(tasks)g(b)m(y)f(sp)s(ecifying)143 3744 y Ff(task1)47 b(-)g(|)g(task2)g(-)0 4001 y Fj(where)30 b(the)h(v)m(ertical)i(bar)e(is)f(the)h(Unix)g(piping)f(sym)m(b)s(ol.)42 b(This)30 b(assumes)g(that)i(the)f(2)g(tasks)g(read)g(the)g(name)g(of)0 4114 y(the)g(FITS)e(\014le)i(o\013)f(of)h(the)g(command)f(line.)0 4448 y Fe(8.4)135 b(Output)45 b(File)g(Name)h(when)f(Op)t(ening)g(an)g (Existing)h(File)0 4698 y Fj(An)36 b(optional)i(output)e(\014lename)h (ma)m(y)h(b)s(e)e(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h (follo)m(wing)g(the)f(base)g(\014le)0 4811 y(name)28 b(to)h(b)s(e)f(op)s(ened.)39 b(This)28 b(is)g(mainly)g(useful)g(in)g (those)g(cases)i(where)d(CFITSIO)g(creates)j(a)e(temp)s(orary)g(cop)m (y)0 4924 y(of)i(the)f(input)g(FITS)f(\014le)i(b)s(efore)f(it)h(is)f (op)s(ened)g(and)f(passed)h(to)h(the)g(application)h(program.)40 b(This)28 b(happ)s(ens)g(b)m(y)0 5036 y(default)i(when)g(op)s(ening)g (a)g(net)m(w)m(ork)h(FTP)g(or)f(HTTP-t)m(yp)s(e)g(\014le,)h(when)e (reading)h(a)h(compressed)f(FITS)g(\014le)g(on)0 5149 y(a)36 b(lo)s(cal)h(disk,)g(when)e(reading)h(from)g(the)g(stdin)f (stream,)j(or)d(when)g(a)i(column)e(\014lter,)j(ro)m(w)e(\014lter,)h (or)f(binning)0 5262 y(sp)s(eci\014er)29 b(is)g(included)g(as)h(part)f (of)g(the)h(input)f(\014le)g(sp)s(eci\014cation.)41 b(By)30 b(default)g(this)f(temp)s(orary)g(\014le)g(is)h(created)0 5375 y(in)g(memory)-8 b(.)41 b(If)29 b(there)h(is)g(not)g(enough)g (memory)g(to)h(create)g(the)g(\014le)f(cop)m(y)-8 b(,)31 b(then)f(CFITSIO)e(will)i(exit)h(with)f(an)0 5488 y(error.)45 b(In)32 b(these)g(cases)h(one)g(can)f(force)h(a)f(p)s(ermanen)m(t)g (\014le)g(to)h(b)s(e)e(created)i(on)f(disk,)g(instead)h(of)f(a)g(temp)s (orary)0 5601 y(\014le)38 b(in)f(memory)-8 b(,)40 b(b)m(y)d(supplying)f (the)i(name)g(in)f(paren)m(theses)h(immediately)h(follo)m(wing)g(the)e (base)h(\014le)g(name.)0 5714 y(The)30 b(output)g(\014lename)g(can)h (include)f(the)h(')10 b(!')41 b(clobb)s(er)30 b(\015ag.)p eop end %%Page: 89 95 TeXDict begin 89 94 bop 0 299 a Fh(8.4.)72 b(OUTPUT)30 b(FILE)g(NAME)h(WHEN)g(OPENING)f(AN)h(EXISTING)e(FILE)967 b Fj(89)0 555 y(Th)m(us,)48 b(if)d(the)g(input)f(\014lename)h(to)g (CFITSIO)f(is:)70 b Ff(file1.fits.gz\(file2.fit)o(s\))39 b Fj(then)44 b(CFITSIO)g(will)0 668 y(uncompress)39 b (`\014le1.\014ts.gz')j(in)m(to)f(the)f(lo)s(cal)h(disk)e(\014le)h (`\014le2.\014ts')h(b)s(efore)f(op)s(ening)f(it.)70 b(CFITSIO)38 b(do)s(es)i(not)0 781 y(automatically)33 b(delete)f(the)e(output)g (\014le,)h(so)g(it)g(will)f(still)i(exist)f(after)g(the)f(application)i (program)e(exits.)0 941 y(In)35 b(some)i(cases,)h(sev)m(eral)f (di\013eren)m(t)g(temp)s(orary)e(FITS)h(\014les)g(will)g(b)s(e)f (created)i(in)f(sequence,)i(for)e(instance,)i(if)0 1054 y(one)f(op)s(ens)g(a)g(remote)h(\014le)f(using)g(FTP)-8 b(,)37 b(then)g(\014lters)g(ro)m(ws)g(in)g(a)h(binary)e(table)i (extension,)i(then)c(create)j(an)0 1167 y(image)f(b)m(y)f(binning)f(a)h (pair)g(of)g(columns.)60 b(In)36 b(this)h(case,)j(the)d(remote)h (\014le)f(will)g(b)s(e)f(copied)h(to)h(a)f(temp)s(orary)0 1280 y(lo)s(cal)j(\014le,)h(then)d(a)h(second)f(temp)s(orary)h(\014le)f (will)h(b)s(e)f(created)i(con)m(taining)g(the)e(\014ltered)h(ro)m(ws)f (of)h(the)g(table,)0 1393 y(and)c(\014nally)g(a)h(third)e(temp)s(orary) h(\014le)h(con)m(taining)g(the)g(binned)e(image)i(will)g(b)s(e)f (created.)57 b(In)34 b(cases)i(lik)m(e)h(this)0 1506 y(where)28 b(m)m(ultiple)h(\014les)f(are)h(created,)h(the)e(out\014le)h (sp)s(eci\014er)f(will)g(b)s(e)g(in)m(terpreted)h(the)f(name)g(of)h (the)f(\014nal)g(\014le)h(as)0 1619 y(describ)s(ed)g(b)s(elo)m(w,)i(in) f(descending)g(priorit)m(y:)136 1869 y Fd(\017)46 b Fj(as)29 b(the)g(name)g(of)g(the)g(\014nal)f(image)i(\014le)f(if)f(an)h(image)h (within)e(a)h(single)g(binary)f(table)i(cell)g(is)e(op)s(ened)g(or)h (if)227 1982 y(an)i(image)g(is)g(created)g(b)m(y)f(binning)g(a)g(table) i(column.)136 2167 y Fd(\017)46 b Fj(as)33 b(the)f(name)h(of)f(the)h (\014le)f(con)m(taining)i(the)e(\014ltered)g(table)i(if)e(a)h(column)f (\014lter)g(and/or)g(a)h(ro)m(w)f(\014lter)h(are)227 2280 y(sp)s(eci\014ed.)136 2464 y Fd(\017)46 b Fj(as)31 b(the)f(name)h(of)f(the)h(lo)s(cal)h(cop)m(y)f(of)f(the)h(remote)g(FTP) f(or)h(HTTP)e(\014le.)136 2649 y Fd(\017)46 b Fj(as)31 b(the)g(name)g(of)g(the)f(uncompressed)g(v)m(ersion)h(of)g(the)f(FITS)g (\014le,)h(if)g(a)g(compressed)f(FITS)g(\014le)h(on)g(lo)s(cal)227 2762 y(disk)f(has)g(b)s(een)g(op)s(ened.)136 2946 y Fd(\017)46 b Fj(otherwise,)31 b(the)g(output)f(\014lename)g(is)h(ignored.)0 3197 y(The)e(output)f(\014le)h(sp)s(eci\014er)g(is)g(useful)f(when)g (reading)h(FTP)g(or)g(HTTP-t)m(yp)s(e)g(FITS)f(\014les)h(since)g(it)h (can)f(b)s(e)g(used)0 3310 y(to)34 b(create)i(a)e(lo)s(cal)h(disk)e (cop)m(y)i(of)f(the)g(\014le)f(that)i(can)f(b)s(e)f(reused)g(in)g(the)h (future.)50 b(If)33 b(the)h(output)g(\014le)f(name)h(=)0 3423 y(`*')i(then)e(a)i(lo)s(cal)g(\014le)f(with)g(the)g(same)g(name)g (as)g(the)h(net)m(w)m(ork)f(\014le)g(will)h(b)s(e)e(created.)56 b(Note)36 b(that)f(CFITSIO)0 3535 y(will)30 b(b)s(eha)m(v)m(e)g (di\013eren)m(tly)h(dep)s(ending)d(on)i(whether)f(the)h(remote)g (\014le)g(is)g(compressed)f(or)h(not)g(as)g(sho)m(wn)f(b)m(y)h(the)0 3648 y(follo)m(wing)i(examples:)136 3876 y Fd(\017)46 b Fj(`ftp://remote.mac)m(hine/tmp/m)m(y\014le.\014ts.gz\(*\)')k(-)43 b(the)g(remote)h(compressed)f(\014le)g(is)g(copied)h(to)g(the)227 3988 y(lo)s(cal)26 b(compressed)e(\014le)g(`m)m(y\014le.\014ts.gz',)k (whic)m(h)c(is)g(then)h(uncompressed)e(in)h(lo)s(cal)h(memory)f(b)s (efore)g(b)s(eing)227 4101 y(op)s(ened)30 b(and)g(passed)g(to)h(the)f (application)i(program.)136 4286 y Fd(\017)46 b Fj(`ftp://remote.mac)m (hine/tmp/m)m(y\014le.\014ts.gz\(m)m(y\014le.\014ts\)')d(-)37 b(the)g(remote)g(compressed)f(\014le)h(is)f(copied)227 4399 y(and)h(uncompressed)g(in)m(to)h(the)g(lo)s(cal)h(\014le)f(`m)m (y\014le.\014ts'.)64 b(This)36 b(example)j(requires)e(less)h(lo)s(cal)h (memory)227 4512 y(than)30 b(the)h(previous)f(example)h(since)g(the)f (\014le)h(is)f(uncompressed)f(on)h(disk)g(instead)h(of)f(in)h(memory)-8 b(.)136 4696 y Fd(\017)46 b Fj(`ftp://remote.mac)m(hine/tmp/m)m (y\014le.\014ts\(m)m(y\014le.\014ts.gz\)')28 b(-)21 b(this)g(will)h (usually)f(pro)s(duce)f(an)h(error)g(since)227 4809 y(CFITSIO)29 b(itself)i(cannot)g(compress)f(\014les.)0 5036 y(The)36 b(exact)i(b)s(eha)m(vior)e(of)h(CFITSIO)e(in)h(the)h(latter)g(case)h (dep)s(ends)c(on)j(the)f(t)m(yp)s(e)h(of)g(ftp)f(serv)m(er)g(running)f (on)0 5149 y(the)c(remote)g(mac)m(hine)g(and)f(ho)m(w)g(it)h(is)f (con\014gured.)40 b(In)30 b(some)h(cases,)g(if)f(the)h(\014le)f(`m)m (y\014le.\014ts.gz')j(exists)e(on)f(the)0 5262 y(remote)38 b(mac)m(hine,)h(then)e(the)g(serv)m(er)g(will)h(cop)m(y)f(it)h(to)f (the)h(lo)s(cal)g(mac)m(hine.)61 b(In)36 b(other)h(cases)h(the)f(ftp)g (serv)m(er)0 5375 y(will)f(automatically)j(create)e(and)f(transmit)g(a) g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(if)g(only)g(the)g (uncompressed)0 5488 y(v)m(ersion)27 b(exists.)41 b(This)26 b(can)h(get)h(rather)f(confusing,)h(so)f(users)f(should)g(use)h(a)g (certain)h(amoun)m(t)g(of)f(caution)h(when)0 5601 y(using)34 b(the)h(output)f(\014le)h(sp)s(eci\014er)f(with)h(FTP)f(or)h(HTTP)f (\014le)h(t)m(yp)s(es,)h(to)f(mak)m(e)h(sure)e(they)h(get)h(the)f(b)s (eha)m(vior)0 5714 y(that)c(they)g(exp)s(ect.)p eop end %%Page: 90 96 TeXDict begin 90 95 bop 0 299 a Fj(90)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fe(8.5)135 b(T)-11 b(emplate)46 b(File)g(Name)f(when)g(Creating)h (a)g(New)f(File)0 808 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g (created)g(with)g(a)f(call)i(to)g(\014ts)p 2101 808 28 4 v 32 w(create)p 2369 808 V 35 w(\014le,)g(the)f(name)g(of)g(a)g (template)h(\014le)e(ma)m(y)0 921 y(b)s(e)h(supplied)g(in)h(paren)m (theses)g(immediately)h(follo)m(wing)g(the)g(name)f(of)g(the)g(new)f (\014le)h(to)h(b)s(e)e(created.)71 b(This)0 1034 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h(structure)f(of)h(one)f(or)h(more)g (HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m (y)0 1147 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case) i(the)f(newly)g(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e (same)g(k)m(eyw)m(ords)g(in)0 1260 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g (template)i(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b) s(e)f(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 1373 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,) g(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h (FITS)f(k)m(eyw)m(ord)i(record.)0 1486 y(The)j(format)h(of)f(the)h (ASCI)s(I)e(template)i(\014le)g(is)f(describ)s(ed)f(b)s(elo)m(w.)0 1833 y Fe(8.6)135 b(Image)46 b(Tile-Compression)h(Sp)t(eci\014cation)0 2086 y Fj(When)28 b(sp)s(ecifying)g(the)h(name)g(of)f(the)h(output)f (FITS)g(\014le)g(to)h(b)s(e)f(created,)i(the)f(user)f(can)g(indicate)i (that)f(images)0 2198 y(should)d(b)s(e)h(written)g(in)g (tile-compressed)h(format)g(\(see)g(section)g(5.5,)h(\\Primary)e(Arra)m (y)h(or)f(IMA)m(GE)h(Extension)0 2311 y(I/O)f(Routines"\))i(b)m(y)e (enclosing)h(the)g(compression)f(parameters)h(in)f(square)g(brac)m(k)m (ets)i(follo)m(wing)g(the)f(ro)s(ot)f(disk)0 2424 y(\014le)j(name.)41 b(Here)31 b(are)g(some)g(examples)g(of)f(the)h(syn)m(tax)g(for)f(sp)s (ecifying)g(tile-compressed)i(output)e(images:)191 2695 y Ff(myfile.fit[compress])185 b(-)48 b(use)f(Rice)f(algorithm)g(and)h (default)e(tile)i(size)191 2921 y(myfile.fit[compress)42 b(GZIP])47 b(-)g(use)g(the)g(specified)e(compression)g(algorithm;)191 3034 y(myfile.fit[compress)d(Rice])238 b(only)46 b(the)h(first)g (letter)f(of)h(the)g(algorithm)191 3147 y(myfile.fit[compress)42 b(PLIO])238 b(name)46 b(is)i(required.)191 3373 y(myfile.fit[compress) 42 b(Rice)47 b(100,100])141 b(-)48 b(use)e(100)h(x)h(100)f(pixel)f (tile)h(size)191 3486 y(myfile.fit[compress)42 b(Rice)47 b(100,100;2])e(-)j(as)f(above,)f(and)h(use)g(noisebits)e(=)i(2)0 3833 y Fe(8.7)135 b(HDU)46 b(Lo)t(cation)f(Sp)t(eci\014cation)0 4086 y Fj(The)c(optional)h(HDU)h(lo)s(cation)g(sp)s(eci\014er)d (de\014nes)h(whic)m(h)g(HDU)h(\(Header-Data)i(Unit,)h(also)d(kno)m(wn)f (as)h(an)0 4199 y(`extension'\))36 b(within)d(the)i(FITS)e(\014le)h(to) h(initially)h(op)s(en.)51 b(It)34 b(m)m(ust)g(immediately)i(follo)m(w)f (the)f(base)h(\014le)f(name)0 4312 y(\(or)g(the)g(output)g(\014le)g (name)f(if)h(presen)m(t\).)52 b(If)33 b(it)h(is)g(not)g(sp)s(eci\014ed) g(then)f(the)h(\014rst)f(HDU)i(\(the)f(primary)f(arra)m(y\))0 4425 y(is)g(op)s(ened.)46 b(The)32 b(HDU)h(lo)s(cation)h(sp)s (eci\014er)e(is)h(required)f(if)g(the)h(colFilter,)i(ro)m(wFilter,)g (or)e(binSp)s(ec)e(sp)s(eci\014ers)0 4538 y(are)f(presen)m(t,)f(b)s (ecause)h(the)f(primary)f(arra)m(y)i(is)f(not)h(a)f(v)-5 b(alid)30 b(HDU)g(for)f(these)g(op)s(erations.)41 b(The)29 b(HDU)h(ma)m(y)g(b)s(e)0 4650 y(sp)s(eci\014ed)e(either)i(b)m(y)e (absolute)i(p)s(osition)f(n)m(um)m(b)s(er,)f(starting)i(with)e(0)i(for) e(the)h(primary)f(arra)m(y)-8 b(,)31 b(or)e(b)m(y)f(reference)0 4763 y(to)h(the)g(HDU)g(name,)g(and)f(optionally)-8 b(,)31 b(the)e(v)m(ersion)g(n)m(um)m(b)s(er)e(and)h(the)h(HDU)g(t)m(yp)s(e)g (of)f(the)h(desired)f(extension.)0 4876 y(The)k(lo)s(cation)h(of)f(an)g (image)i(within)d(a)i(single)f(cell)i(of)e(a)g(binary)g(table)h(ma)m(y) f(also)h(b)s(e)f(sp)s(eci\014ed,)g(as)g(describ)s(ed)0 4989 y(b)s(elo)m(w.)0 5149 y(The)26 b(absolute)h(p)s(osition)f(of)g (the)h(extension)g(is)f(sp)s(eci\014ed)f(either)i(b)m(y)f(enclosed)h (the)g(n)m(um)m(b)s(er)e(in)h(square)f(brac)m(k)m(ets)0 5262 y(\(e.g.,)k(`[1]')g(=)d(the)h(\014rst)f(extension)h(follo)m(wing)i (the)e(primary)e(arra)m(y\))j(or)f(b)m(y)f(preceded)h(the)g(n)m(um)m(b) s(er)e(with)i(a)g(plus)0 5375 y(sign)37 b(\(`+1'\).)63 b(T)-8 b(o)38 b(sp)s(ecify)f(the)g(HDU)h(b)m(y)g(name,)h(giv)m(e)g(the) e(name)h(of)f(the)h(desired)f(HDU)h(\(the)f(v)-5 b(alue)38 b(of)g(the)0 5488 y(EXTNAME)e(or)g(HDUNAME)h(k)m(eyw)m(ord\))g(and)f (optionally)h(the)f(extension)h(v)m(ersion)f(n)m(um)m(b)s(er)f(\(v)-5 b(alue)37 b(of)f(the)0 5601 y(EXTVER)27 b(k)m(eyw)m(ord\))i(and)e(the)h (extension)h(t)m(yp)s(e)e(\(v)-5 b(alue)29 b(of)f(the)g(XTENSION)f(k)m (eyw)m(ord:)40 b(IMA)m(GE,)29 b(ASCI)s(I)d(or)0 5714 y(T)-8 b(ABLE,)36 b(or)f(BINT)-8 b(ABLE\),)36 b(separated)f(b)m(y)g (commas)h(and)e(all)i(enclosed)g(in)f(square)g(brac)m(k)m(ets.)56 b(If)34 b(the)h(v)-5 b(alue)p eop end %%Page: 91 97 TeXDict begin 91 96 bop 0 299 a Fh(8.8.)72 b(IMA)m(GE)31 b(SECTION)2835 b Fj(91)0 555 y(of)34 b(EXTVER)f(and)f(XTENSION)h(are)h (not)f(sp)s(eci\014ed,)h(then)f(the)h(\014rst)e(extension)j(with)e(the) g(correct)i(v)-5 b(alue)34 b(of)0 668 y(EXTNAME)39 b(is)g(op)s(ened.)67 b(The)38 b(extension)i(name)f(and)f(t)m(yp)s(e)i(are)f(not)h(case)g (sensitiv)m(e,)j(and)38 b(the)h(extension)0 781 y(t)m(yp)s(e)29 b(ma)m(y)g(b)s(e)f(abbreviated)h(to)g(a)g(single)g(letter)h(\(e.g.,)h (I)d(=)g(IMA)m(GE)i(extension)f(or)f(primary)g(arra)m(y)-8 b(,)30 b(A)f(or)f(T)g(=)0 894 y(ASCI)s(I)d(table)i(extension,)h(and)e (B)h(=)f(binary)g(table)h(BINT)-8 b(ABLE)27 b(extension\).)41 b(If)26 b(the)g(HDU)h(lo)s(cation)i(sp)s(eci\014er)0 1007 y(is)h(equal)h(to)g(`[PRIMAR)-8 b(Y]')32 b(or)f(`[P]',)g(then)f (the)h(primary)e(arra)m(y)i(\(the)g(\014rst)f(HDU\))h(will)g(b)s(e)f (op)s(ened.)0 1167 y(FITS)k(images)i(are)f(most)h(commonly)f(stored)g (in)g(the)g(primary)f(arra)m(y)h(or)g(an)g(image)h(extension,)h(but)d (images)0 1280 y(can)d(also)h(b)s(e)e(stored)h(as)h(a)f(v)m(ector)h(in) f(a)g(single)h(cell)g(of)f(a)h(binary)e(table)i(\(i.e.)43 b(eac)m(h)32 b(ro)m(w)f(of)g(the)h(v)m(ector)g(column)0 1393 y(con)m(tains)d(a)g(di\013eren)m(t)f(image\).)42 b(Suc)m(h)27 b(an)h(image)i(can)e(b)s(e)g(op)s(ened)f(with)h(CFITSIO)e (b)m(y)i(sp)s(ecifying)g(the)g(desired)0 1506 y(column)k(name)g(and)f (the)h(ro)m(w)g(n)m(um)m(b)s(er)f(after)h(the)g(binary)f(table)i(HDU)g (sp)s(eci\014er)e(as)h(sho)m(wn)g(in)f(the)h(follo)m(wing)0 1619 y(examples.)71 b(The)40 b(column)g(name)h(is)f(separated)h(from)f (the)h(HDU)g(sp)s(eci\014er)f(b)m(y)g(a)h(semicolon)g(and)f(the)h(ro)m (w)0 1732 y(n)m(um)m(b)s(er)29 b(is)h(enclosed)h(in)e(paren)m(theses.) 41 b(In)30 b(this)g(case)h(CFITSIO)d(copies)j(the)f(image)i(from)d(the) i(table)g(cell)g(in)m(to)0 1844 y(a)h(temp)s(orary)e(primary)h(arra)m (y)g(b)s(efore)g(it)h(is)f(op)s(ened.)43 b(The)30 b(application)j (program)e(then)g(just)g(sees)g(the)h(image)0 1957 y(in)i(the)h (primary)e(arra)m(y)-8 b(,)37 b(without)d(an)m(y)h(extensions.)53 b(The)34 b(particular)g(ro)m(w)h(to)g(b)s(e)e(op)s(ened)h(ma)m(y)h(b)s (e)f(sp)s(eci\014ed)0 2070 y(either)28 b(b)m(y)f(giving)h(an)f (absolute)h(in)m(teger)h(ro)m(w)f(n)m(um)m(b)s(er)e(\(starting)i(with)f (1)h(for)f(the)g(\014rst)g(ro)m(w\),)i(or)e(b)m(y)g(sp)s(ecifying)0 2183 y(a)33 b(b)s(o)s(olean)f(expression)g(that)h(ev)-5 b(aluates)34 b(to)f(TR)m(UE)g(for)f(the)g(desired)g(ro)m(w.)47 b(The)32 b(\014rst)f(ro)m(w)i(that)g(satis\014es)g(the)0 2296 y(expression)28 b(will)g(b)s(e)g(used.)39 b(The)28 b(ro)m(w)g(selection)i(expression)e(has)g(the)g(same)g(syn)m(tax)h(as)f (describ)s(ed)f(in)h(the)g(Ro)m(w)0 2409 y(Filter)k(Sp)s(eci\014er)d (section,)j(b)s(elo)m(w.)0 2569 y(Examples:)143 2811 y Ff(myfile.fits[3])44 b(-)k(open)e(the)h(3rd)g(HDU)g(following)e(the)i (primary)f(array)143 2924 y(myfile.fits+3)92 b(-)48 b(same)e(as)h (above,)f(but)h(using)g(the)g(FTOOLS-style)d(notation)143 3037 y(myfile.fits[EVENTS])f(-)k(open)g(the)g(extension)e(that)i(has)g (EXTNAME)e(=)j('EVENTS')143 3150 y(myfile.fits[EVENTS,)43 b(2])95 b(-)47 b(same)g(as)g(above,)f(but)h(also)g(requires)e(EXTVER)h (=)i(2)143 3263 y(myfile.fits[events,2,b])42 b(-)47 b(same,)f(but)h (also)g(requires)f(XTENSION)f(=)j('BINTABLE')143 3376 y(myfile.fits[3;)c(images\(17\)])h(-)i(opens)g(the)g(image)f(in)h(row)g (17)g(of)g(the)g('images')1527 3489 y(column)f(in)i(the)e(3rd)h (extension)f(of)h(the)g(file.)143 3602 y(myfile.fits[3;)d (images\(exposure)g(>)j(100\)])g(-)g(as)g(above,)f(but)h(opens)g(the)f (image)907 3714 y(in)h(the)g(first)f(row)h(that)g(has)g(an)g ('exposure')e(column)h(value)907 3827 y(greater)g(than)g(100.)0 4158 y Fe(8.8)135 b(Image)46 b(Section)0 4408 y Fj(A)41 b(virtual)g(\014le)f(con)m(taining)i(a)f(rectangular)h(subsection)e(of) h(an)g(image)g(can)g(b)s(e)f(extracted)i(and)e(op)s(ened)g(b)m(y)0 4521 y(sp)s(ecifying)32 b(the)h(range)g(of)g(pixels)g(\(start:end\))g (along)h(eac)m(h)g(axis)f(to)g(b)s(e)f(extracted)i(from)e(the)h (original)g(image.)0 4634 y(One)d(can)h(also)h(sp)s(ecify)e(an)h (optional)h(pixel)f(incremen)m(t)g(\(start:end:step\))h(for)f(eac)m(h)h (axis)f(of)g(the)g(input)e(image.)0 4747 y(A)f(pixel)f(step)h(=)f(1)h (will)g(b)s(e)f(assumed)f(if)i(it)g(is)f(not)h(sp)s(eci\014ed.)39 b(If)27 b(the)h(start)g(pixel)g(is)f(larger)i(then)e(the)h(end)e (pixel,)0 4860 y(then)32 b(the)g(image)h(will)f(b)s(e)f(\015ipp)s(ed)f (\(pro)s(ducing)h(a)h(mirror)g(image\))h(along)g(that)f(dimension.)45 b(An)32 b(asterisk,)h('*',)0 4973 y(ma)m(y)39 b(b)s(e)e(used)h(to)h(sp) s(ecify)f(the)g(en)m(tire)h(range)g(of)f(an)h(axis,)i(and)c('-*')j (will)e(\015ip)g(the)g(en)m(tire)h(axis.)65 b(The)38 b(input)0 5086 y(image)31 b(can)f(b)s(e)f(in)g(the)h(primary)f(arra)m (y)-8 b(,)31 b(in)e(an)g(image)i(extension,)g(or)f(con)m(tained)g(in)g (a)g(v)m(ector)h(cell)g(of)f(a)g(binary)0 5199 y(table.)40 b(In)25 b(the)h(later)h(2)f(cases)h(the)f(extension)h(name)f(or)f(n)m (um)m(b)s(er)g(m)m(ust)h(b)s(e)f(sp)s(eci\014ed)g(b)s(efore)h(the)g (image)h(section)0 5312 y(sp)s(eci\014er.)0 5472 y(Examples:)95 5714 y Ff(myfile.fits[1:512:2,)43 b(2:512:2])i(-)95 b(open)47 b(a)h(256x256)d(pixel)i(image)p eop end %%Page: 92 98 TeXDict begin 92 97 bop 0 299 a Fj(92)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)668 555 y Ff(consisting)45 b(of)i(the)g(odd)g(numbered)f(columns)g(\(1st)g (axis\))h(and)668 668 y(the)g(even)g(numbered)e(rows)i(\(2nd)g(axis\))f (of)h(the)g(image)f(in)i(the)668 781 y(primary)e(array)g(of)i(the)e (file.)95 1007 y(myfile.fits[*,)e(512:256])i(-)h(open)g(an)g(image)g (consisting)e(of)i(all)g(the)g(columns)668 1120 y(in)g(the)g(input)g (image,)f(but)h(only)f(rows)h(256)g(through)f(512.)668 1233 y(The)h(image)f(will)h(be)g(flipped)f(along)g(the)h(2nd)g(axis)g (since)668 1346 y(the)g(starting)f(pixel)g(is)h(greater)f(than)h(the)g (ending)f(pixel.)95 1571 y(myfile.fits[*:2,)e(512:256:2])h(-)i(same)g (as)g(above)f(but)h(keeping)f(only)668 1684 y(every)h(other)f(row)h (and)g(column)f(in)h(the)g(input)f(image.)95 1910 y(myfile.fits[-*,)e (*])j(-)h(copy)e(the)h(entire)f(image,)g(flipping)g(it)h(along)668 2023 y(the)g(first)f(axis.)95 2249 y(myfile.fits[3][1:256,1:256)o(])c (-)47 b(opens)g(a)g(subsection)e(of)i(the)g(image)g(that)668 2362 y(is)g(in)h(the)e(3rd)h(extension)f(of)h(the)g(file.)95 2588 y(myfile.fits[4;)d(images\(12\)][1:10,1:10])e(-)48 b(open)e(an)h(image)g(consisting)286 2700 y(of)h(the)e(first)h(10)g (pixels)f(in)h(both)g(dimensions.)e(The)i(original)286 2813 y(image)g(resides)f(in)h(the)g(12th)f(row)h(of)g(the)g('images')f (vector)286 2926 y(column)g(in)i(the)f(table)f(in)h(the)g(4th)g (extension)e(of)i(the)g(file.)0 3203 y Fj(When)23 b(CFITSIO)f(op)s(ens) h(an)g(image)h(section)h(it)f(\014rst)f(creates)h(a)g(temp)s(orary)f (\014le)h(con)m(taining)h(the)e(image)i(section)0 3315 y(plus)32 b(a)i(cop)m(y)g(of)g(an)m(y)g(other)f(HDUs)h(in)f(the)h (\014le.)50 b(This)32 b(temp)s(orary)h(\014le)h(is)f(then)g(op)s(ened)g (b)m(y)g(the)h(application)0 3428 y(program,)28 b(so)g(it)g(is)f(not)h (p)s(ossible)f(to)h(write)g(to)g(or)g(mo)s(dify)f(the)g(input)g(\014le) g(when)g(sp)s(ecifying)g(an)h(image)h(section.)0 3541 y(Note)39 b(that)f(CFITSIO)e(automatically)k(up)s(dates)d(the)g(w)m (orld)h(co)s(ordinate)g(system)g(k)m(eyw)m(ords)f(in)g(the)h(header)0 3654 y(of)33 b(the)h(image)g(section,)h(if)e(they)h(exist,)h(so)e(that) h(the)f(co)s(ordinate)h(asso)s(ciated)h(with)e(eac)m(h)h(pixel)f(in)g (the)h(image)0 3767 y(section)e(will)e(b)s(e)g(computed)g(correctly)-8 b(.)0 4120 y Fe(8.9)135 b(Image)46 b(T)-11 b(ransform)45 b(Filters)0 4374 y Fj(CFITSIO)33 b(can)h(apply)g(a)h(user-sp)s (eci\014ed)e(mathematical)j(function)e(to)h(the)g(v)-5 b(alue)34 b(of)h(ev)m(ery)g(pixel)f(in)g(a)h(FITS)0 4487 y(image,)29 b(th)m(us)e(creating)h(a)g(new)e(virtual)h(image)i(in)d (computer)h(memory)g(that)h(is)f(then)f(op)s(ened)h(and)f(read)h(b)m(y) g(the)0 4600 y(application)32 b(program.)40 b(The)30 b(original)i(FITS)d(image)j(is)e(not)h(mo)s(di\014ed)e(b)m(y)h(this)h (pro)s(cess.)0 4760 y(The)20 b(image)j(transformation)e(sp)s(eci\014er) f(is)h(app)s(ended)e(to)j(the)f(input)f(FITS)h(\014le)g(name)g(and)f (is)h(enclosed)h(in)e(square)0 4873 y(brac)m(k)m(ets.)42 b(It)29 b(b)s(egins)f(with)h(the)g(letters)i('PIX')e(to)h(distinguish)e (it)i(from)e(other)i(t)m(yp)s(es)f(of)g(FITS)f(\014le)h(\014lters)g (that)0 4986 y(are)36 b(recognized)i(b)m(y)e(CFITSIO.)e(The)i(image)h (transforming)f(function)f(ma)m(y)i(use)f(an)m(y)g(of)g(the)h (mathematical)0 5099 y(op)s(erators)44 b(listed)h(in)f(the)h(follo)m (wing)h('Ro)m(w)f(Filtering)g(Sp)s(eci\014cation')g(section)h(of)e (this)h(do)s(cumen)m(t.)82 b(Some)0 5212 y(examples)31 b(of)f(image)i(transform)e(\014lters)g(are:)48 5488 y Ff([pix)46 b(X)i(*)f(2.0])715 b(-)48 b(multiply)d(each)i(pixel)f(by)h (2.0)48 5601 y([pix)f(sqrt\(X\)])714 b(-)48 b(take)e(the)h(square)f (root)h(of)g(each)g(pixel)48 5714 y([pix)f(X)i(+)f(#ZEROPT)571 b(-)48 b(add)e(the)h(value)g(of)g(the)g(ZEROPT)f(keyword)p eop end %%Page: 93 99 TeXDict begin 93 98 bop 0 299 a Fh(8.9.)72 b(IMA)m(GE)31 b(TRANSF)m(ORM)g(FIL)-8 b(TERS)2237 b Fj(93)48 555 y Ff([pix)46 b(X>0)h(?)h(log10\(X\))d(:)j(-99.])e(-)i(if)f(the)g(pixel)f (value)g(is)i(greater)1480 668 y(than)e(0,)h(compute)f(the)h(base)g(10) g(log,)1480 781 y(else)f(set)h(the)g(pixel)f(=)i(-99.)0 1043 y Fj(Use)24 b(the)g(letter)h('X')f(in)f(the)h(expression)g(to)g (represen)m(t)g(the)g(curren)m(t)f(pixel)h(v)-5 b(alue)24 b(in)f(the)h(image.)40 b(The)23 b(expression)0 1156 y(is)38 b(ev)-5 b(aluated)39 b(indep)s(enden)m(tly)e(for)g(eac)m(h)i(pixel)f (in)g(the)g(image)h(and)e(ma)m(y)h(b)s(e)g(a)g(function)f(of)h(1\))h (the)f(original)0 1269 y(pixel)32 b(v)-5 b(alue,)32 b(2\))g(the)f(v)-5 b(alue)32 b(of)f(other)h(pixels)f(in)g(the)g(image)i(at)f(a)f(giv)m(en) i(relativ)m(e)g(o\013set)f(from)f(the)g(p)s(osition)h(of)0 1382 y(the)d(pixel)f(that)h(is)g(b)s(eing)f(ev)-5 b(aluated,)30 b(and)e(3\))h(the)g(v)-5 b(alue)29 b(of)f(an)m(y)h(header)f(k)m(eyw)m (ords.)41 b(Header)29 b(k)m(eyw)m(ord)g(v)-5 b(alues)0 1495 y(are)31 b(represen)m(ted)f(b)m(y)g(the)h(name)f(of)h(the)f(k)m (eyw)m(ord)h(preceded)f(b)m(y)h(the)f('#')h(sign.)0 1655 y(T)-8 b(o)35 b(access)h(the)f(the)g(v)-5 b(alue)35 b(of)g(adjacen)m(t) h(pixels)f(in)f(the)h(image,)i(sp)s(ecify)e(the)g(\(1-D\))h(o\013set)g (from)e(the)h(curren)m(t)0 1768 y(pixel)c(in)f(curly)g(brac)m(k)m(ets.) 42 b(F)-8 b(or)31 b(example)48 2030 y Ff([pix)94 b(\(x{-1})46 b(+)i(x)f(+)h(x{+1}\))e(/)h(3])0 2292 y Fj(will)25 b(replace)g(eac)m(h) h(pixel)f(v)-5 b(alue)25 b(with)f(the)h(running)e(mean)i(of)f(the)h(v) -5 b(alues)25 b(of)g(that)g(pixel)g(and)f(it's)h(2)g(neigh)m(b)s(oring) 0 2405 y(pixels.)40 b(Note)30 b(that)g(in)e(this)g(notation)i(the)f (image)h(is)f(treated)g(as)g(a)g(1-D)h(arra)m(y)-8 b(,)30 b(where)e(eac)m(h)i(ro)m(w)f(of)g(the)g(image)0 2518 y(\(or)c(higher)f(dimensional)g(cub)s(e\))h(is)f(app)s(ended)f(one)h (after)h(another)g(in)f(one)h(long)g(arra)m(y)g(of)f(pixels.)39 b(It)25 b(is)f(p)s(ossible)0 2630 y(to)35 b(refer)f(to)h(pixels)f(in)g (the)g(ro)m(ws)g(ab)s(o)m(v)m(e)h(or)g(b)s(elo)m(w)f(the)g(curren)m(t)g (pixel)h(b)m(y)f(using)f(the)h(v)-5 b(alue)35 b(of)f(the)h(NAXIS1)0 2743 y(header)30 b(k)m(eyw)m(ord.)41 b(F)-8 b(or)32 b(example)48 3005 y Ff([pix)46 b(\(x{-#NAXIS1})f(+)i(x)h(+)f(x{#NAXIS1}\))e(/)i(3])0 3267 y Fj(will)34 b(compute)f(the)h(mean)f(of)g(eac)m(h)i(image)f (pixel)g(and)e(the)i(pixels)f(immediately)i(ab)s(o)m(v)m(e)f(and)f(b)s (elo)m(w)g(it)h(in)f(the)0 3380 y(adjacen)m(t)27 b(ro)m(ws)f(of)g(the)f (image.)41 b(The)25 b(follo)m(wing)i(more)f(complex)h(example)f (creates)h(a)f(smo)s(othed)g(virtual)g(image)0 3493 y(where)k(eac)m(h)h (pixel)g(is)g(a)f(3)h(x)f(3)h(b)s(o)m(xcar)g(a)m(v)m(erage)i(of)d(the)h (input)e(image)j(pixels:)95 3755 y Ff([pix)47 b(\(X)g(+)h(X{-1})e(+)i (X{+1})286 3868 y(+)g(X{-#NAXIS1})d(+)i(X{-#NAXIS1)e(-)i(1})h(+)f (X{-#NAXIS1)e(+)j(1})286 3981 y(+)g(X{#NAXIS1})d(+)i(X{#NAXIS1)f(-)h (1})g(+)h(X{#NAXIS1)d(+)i(1}\))g(/)h(9.])0 4243 y Fj(If)31 b(the)h(pixel)g(o\013set)h(extends)f(b)s(ey)m(ond)f(the)h(\014rst)f(or) h(last)h(pixel)f(in)f(the)h(image,)i(the)e(function)g(will)g(ev)-5 b(aluate)33 b(to)0 4356 y(unde\014ned,)28 b(or)j(NULL.)0 4516 y(F)-8 b(or)39 b(complex)g(or)g(commonly)g(used)e(image)j (\014ltering)f(op)s(erations,)i(one)d(can)h(write)g(the)f(expression)h (in)m(to)g(an)0 4629 y(external)i(text)h(\014le)f(and)f(then)g(imp)s (ort)g(it)h(in)m(to)h(the)e(\014lter)h(using)f(the)h(syn)m(tax)g('[pix) g(@\014lename.txt]'.)72 b(The)0 4742 y(mathematical)29 b(expression)e(can)g(extend)g(o)m(v)m(er)i(m)m(ultiple)e(lines)g(of)h (text)g(in)e(the)h(\014le.)40 b(An)m(y)27 b(lines)g(in)g(the)g (external)0 4855 y(text)h(\014le)e(that)i(b)s(egin)e(with)g(2)h(slash)f (c)m(haracters)i(\('//'\))h(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)h(b)s (e)f(used)g(to)h(add)f(commen)m(ts)0 4968 y(in)m(to)31 b(the)g(\014le.)0 5128 y(When)39 b(using)f(column)h(\014ltering)h(to)g (op)s(en)e(a)h(\014le)h(\\on)f(the)g(\015y)-8 b(,")42 b(it)e(is)f(p)s(ermitted)g(to)h(use)e(m)m(ultiple)i(column)0 5241 y(\014ltering)31 b(expressions.)40 b(F)-8 b(or)31 b(example,)g(the)g(syn)m(tax)95 5477 y Ff(filename.fits[col)44 b(*][col)i(-Y][col)f(Z=X+1])0 5714 y Fj(w)m(ould)30 b(b)s(e)g(treated)h (as)g(equiv)-5 b(alen)m(t)32 b(to)f(joining)f(the)h(expressions)f(with) g(semicolons,)i(or)p eop end %%Page: 94 100 TeXDict begin 94 99 bop 0 299 a Fj(94)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)95 555 y Ff(filename.fits[col)44 b(*;)j(-Y;col)f(Z=X+1])0 791 y Fj(Please)37 b(note)e(that)h(if)g(m)m(ultiple)g(column)f (\014ltering)g(expressions)g(are)h(used,)g(it)g(is)f(not)h(p)s (ermitted)f(to)h(also)g(use)0 904 y(the)31 b Ff([col)46 b(@filename.txt])27 b Fj(syn)m(tax)k(in)f(an)m(y)g(of)h(the)f (individual)g(expressions.)0 1064 y(By)d(default,)g(the)f(datat)m(yp)s (e)i(of)e(the)g(resulting)h(image)g(will)g(b)s(e)e(the)i(same)f(as)h (the)f(original)i(image,)g(but)e(one)g(ma)m(y)0 1177 y(force)31 b(a)g(di\013eren)m(t)g(datat)m(yp)s(e)g(b)m(y)f(app)s(ended) f(a)h(co)s(de)h(letter)h(to)f(the)f('pix')h(k)m(eyw)m(ord:)286 1438 y Ff(pixb)95 b(-)g(8-bit)46 b(byte)190 b(image)46 b(with)h(BITPIX)f(=)143 b(8)286 1551 y(pixi)95 b(-)47 b(16-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(16)286 1664 y(pixj)g(-)47 b(32-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(32)286 1777 y(pixr)g(-)47 b(32-bit)f(float)142 b(image)46 b(with)h(BITPIX)f(=)i(-32)286 1890 y(pixd)95 b(-)47 b(64-bit)f(float) 142 b(image)46 b(with)h(BITPIX)f(=)i(-64)0 2151 y Fj(Also)23 b(b)m(y)f(default,)j(an)m(y)d(other)h(HDUs)g(in)f(the)g(input)g(\014le) g(will)h(b)s(e)e(copied)i(without)g(c)m(hange)g(to)g(the)g(output)f (virtual)0 2264 y(FITS)k(\014le,)h(but)f(one)g(ma)m(y)h(discard)f(the)h (other)f(HDUs)h(b)m(y)f(adding)g(the)h(n)m(um)m(b)s(er)e('1')i(to)g (the)g('pix')f(k)m(eyw)m(ord)h(\(and)0 2377 y(follo)m(wing)32 b(an)m(y)f(optional)g(datat)m(yp)s(e)g(co)s(de)g(letter\).)42 b(F)-8 b(or)32 b(example:)239 2639 y Ff(myfile.fits[3][pixr1)90 b(sqrt\(X\)])0 2900 y Fj(will)23 b(create)i(a)e(virtual)g(FITS)f (\014le)h(con)m(taining)h(only)f(a)g(primary)f(arra)m(y)i(image)g(with) e(32-bit)i(\015oating)g(p)s(oin)m(t)f(pixels)0 3013 y(that)29 b(ha)m(v)m(e)h(a)f(v)-5 b(alue)30 b(equal)f(to)g(the)g(square)g(ro)s (ot)g(of)g(the)g(pixels)f(in)h(the)g(image)h(that)f(is)g(in)f(the)h (3rd)f(extension)i(of)0 3126 y(the)h('m)m(y\014le.\014ts')g(\014le.)0 3461 y Fe(8.10)136 b(Column)45 b(and)f(Keyw)l(ord)i(Filtering)g(Sp)t (eci\014cation)0 3712 y Fj(The)27 b(optional)i(column/k)m(eyw)m(ord)g (\014ltering)f(sp)s(eci\014er)f(is)h(used)f(to)i(mo)s(dify)e(the)h (column)g(structure)f(and/or)h(the)0 3825 y(header)38 b(k)m(eyw)m(ords)h(in)f(the)h(HDU)g(that)h(w)m(as)f(selected)h(with)e (the)h(previous)f(HDU)h(lo)s(cation)h(sp)s(eci\014er.)65 b(This)0 3938 y(\014ltering)42 b(sp)s(eci\014er)f(m)m(ust)h(b)s(e)f (enclosed)i(in)e(square)h(brac)m(k)m(ets)h(and)e(can)h(b)s(e)f (distinguished)g(from)h(a)g(general)0 4050 y(ro)m(w)d(\014lter)g(sp)s (eci\014er)f(\(describ)s(ed)g(b)s(elo)m(w\))h(b)m(y)g(the)g(fact)h (that)f(it)g(b)s(egins)f(with)h(the)g(string)g('col)h(')f(and)f(is)h (not)0 4163 y(immediately)30 b(follo)m(w)m(ed)g(b)m(y)e(an)g(equals)h (sign.)40 b(The)28 b(original)h(\014le)f(is)h(not)f(c)m(hanged)h(b)m(y) f(this)h(\014ltering)f(op)s(eration,)0 4276 y(and)40 b(instead)h(the)g(mo)s(di\014cations)g(are)g(made)f(on)h(a)g(cop)m(y)g (of)g(the)g(input)f(FITS)g(\014le)g(\(usually)h(in)f(memory\),)0 4389 y(whic)m(h)33 b(also)h(con)m(tains)g(a)f(cop)m(y)h(of)f(all)h(the) g(other)f(HDUs)h(in)e(the)h(\014le.)49 b(This)33 b(temp)s(orary)f (\014le)h(is)g(passed)g(to)h(the)0 4502 y(application)f(program)f(and)f (will)h(p)s(ersist)f(only)h(un)m(til)g(the)g(\014le)g(is)g(closed)h(or) f(un)m(til)g(the)g(program)f(exits,)j(unless)0 4615 y(the)d(out\014le)f (sp)s(eci\014er)g(\(see)h(ab)s(o)m(v)m(e\))h(is)f(also)g(supplied.)0 4775 y(The)g(column/k)m(eyw)m(ord)h(\014lter)f(can)g(b)s(e)g(used)f(to) i(p)s(erform)e(the)i(follo)m(wing)g(op)s(erations.)44 b(More)32 b(than)f(one)g(op)s(er-)0 4888 y(ation)g(ma)m(y)g(b)s(e)f(sp) s(eci\014ed)g(b)m(y)g(separating)h(them)f(with)h(commas)f(or)h (semi-colons.)136 5149 y Fd(\017)46 b Fj(Cop)m(y)36 b(only)g(a)g(sp)s (eci\014ed)g(list)g(of)g(columns)g(columns)f(to)i(the)f(\014ltered)g (input)f(\014le.)57 b(The)36 b(list)g(of)g(column)227 5262 y(name)41 b(should)e(b)s(e)g(separated)i(b)m(y)f(commas)h(or)f (semi-colons.)72 b(Wild)41 b(card)f(c)m(haracters)h(ma)m(y)g(b)s(e)f (used)227 5375 y(in)e(the)f(column)h(names)g(to)g(matc)m(h)g(m)m (ultiple)h(columns.)62 b(If)37 b(the)h(expression)g(con)m(tains)g(b)s (oth)f(a)h(list)h(of)227 5488 y(columns)29 b(to)h(b)s(e)f(included)g (and)g(columns)g(to)h(b)s(e)e(deleted,)j(then)e(all)h(the)g(columns)f (in)g(the)h(original)g(table)227 5601 y(except)36 b(the)e(explicitly)i (deleted)f(columns)f(will)h(app)s(ear)e(in)h(the)h(\014ltered)f(table)h (\(i.e.,)i(there)e(is)f(no)g(need)227 5714 y(to)d(explicitly)h(list)f (the)g(columns)f(to)h(b)s(e)f(included)f(if)i(an)m(y)f(columns)h(are)f (b)s(eing)g(deleted\).)p eop end %%Page: 95 101 TeXDict begin 95 100 bop 0 299 a Fh(8.10.)73 b(COLUMN)30 b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1075 b Fj(95)136 555 y Fd(\017)46 b Fj(Delete)32 b(a)d(column)g(or)g(k)m(eyw)m(ord)h(b)m(y)f(listing)h(the)f(name)g (preceded)g(b)m(y)g(a)g(min)m(us)g(sign)g(or)g(an)g(exclamation)227 668 y(mark)c(\(!\),)h(e.g.,)i('-TIME')d(will)g(delete)h(the)e(TIME)h (column)f(if)g(it)i(exists,)g(otherwise)f(the)g(TIME)f(k)m(eyw)m(ord.) 227 781 y(An)35 b(error)f(is)h(returned)e(if)i(neither)f(a)i(column)e (nor)g(k)m(eyw)m(ord)h(with)g(this)f(name)h(exists.)54 b(Note)36 b(that)g(the)227 894 y(exclamation)27 b(p)s(oin)m(t,)g(')10 b(!',)27 b(is)e(a)g(sp)s(ecial)h(UNIX)f(c)m(haracter,)j(so)d(if)g(it)h (is)f(used)f(on)h(the)g(command)g(line)g(rather)227 1007 y(than)33 b(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s (e)g(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)g(force)g(the)f(UNIX)h (shell)227 1120 y(to)d(ignore)g(it.)136 1307 y Fd(\017)46 b Fj(Rename)29 b(an)g(existing)g(column)f(or)h(k)m(eyw)m(ord)g(with)f (the)h(syn)m(tax)g('NewName)h(==)e(OldName'.)40 b(An)28 b(error)227 1420 y(is)j(returned)e(if)h(neither)h(a)f(column)g(nor)g(k) m(eyw)m(ord)h(with)f(this)h(name)f(exists.)136 1607 y Fd(\017)46 b Fj(App)s(end)37 b(a)j(new)f(column)f(or)i(k)m(eyw)m(ord)f (to)h(the)f(table.)68 b(T)-8 b(o)40 b(create)g(a)g(column,)h(giv)m(e)g (the)e(new)g(name,)227 1720 y(optionally)e(follo)m(w)m(ed)g(b)m(y)e (the)g(datat)m(yp)s(e)h(in)f(paren)m(theses,)i(follo)m(w)m(ed)g(b)m(y)e (a)h(single)g(equals)f(sign)g(and)g(an)227 1833 y(expression)g(to)h(b)s (e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue)35 b(\(e.g.,)j('new)m (col\(1J\))f(=)e(0')g(will)h(create)g(a)f(new)g(32-bit)227 1945 y(in)m(teger)k(column)e(called)i('new)m(col')f(\014lled)g(with)f (zeros\).)62 b(The)37 b(datat)m(yp)s(e)h(is)g(sp)s(eci\014ed)e(using)h (the)h(same)227 2058 y(syn)m(tax)28 b(that)h(is)e(allo)m(w)m(ed)j(for)d (the)h(v)-5 b(alue)28 b(of)g(the)g(FITS)f(TF)m(ORMn)g(k)m(eyw)m(ord)h (\(e.g.,)i('I',)f('J',)f('E',)g('D',)h(etc.)227 2171 y(for)37 b(binary)f(tables,)k(and)c('I8',)k(F12.3',)h('E20.12',)g(etc.) 62 b(for)37 b(ASCI)s(I)e(tables\).)62 b(If)37 b(the)g(datat)m(yp)s(e)h (is)f(not)227 2284 y(sp)s(eci\014ed)24 b(then)f(an)h(appropriate)h (datat)m(yp)s(e)g(will)f(b)s(e)g(c)m(hosen)g(dep)s(ending)f(on)h(the)g (form)g(of)g(the)g(expression)227 2397 y(\(ma)m(y)f(b)s(e)d(a)i(c)m (haracter)h(string,)h(logical,)h(bit,)f(long)e(in)m(teger,)j(or)c (double)g(column\).)38 b(An)21 b(appropriate)g(v)m(ector)227 2510 y(coun)m(t)31 b(\(in)g(the)f(case)i(of)e(binary)g(tables\))h(will) g(also)g(b)s(e)f(added)g(if)g(not)h(explicitly)h(sp)s(eci\014ed.)227 2660 y(When)26 b(creating)h(a)f(new)f(k)m(eyw)m(ord,)j(the)e(k)m(eyw)m (ord)g(name)g(m)m(ust)g(b)s(e)f(preceded)g(b)m(y)h(a)g(p)s(ound)e(sign) h('#',)j(and)227 2773 y(the)h(expression)f(m)m(ust)g(ev)-5 b(aluate)30 b(to)f(a)g(scalar)g(\(i.e.,)h(cannot)f(ha)m(v)m(e)h(a)f (column)f(name)g(in)g(the)h(expression\).)227 2886 y(The)j(commen)m(t)i (string)f(for)f(the)h(k)m(eyw)m(ord)h(ma)m(y)f(b)s(e)f(sp)s(eci\014ed)g (in)g(paren)m(theses)h(immediately)h(follo)m(wing)227 2999 y(the)29 b(k)m(eyw)m(ord)f(name)g(\(instead)h(of)f(supplying)f(a)h (datat)m(yp)s(e)h(as)g(in)e(the)i(case)g(of)f(creating)h(a)g(new)f (column\).)227 3112 y(If)c(the)h(k)m(eyw)m(ord)g(name)f(ends)g(with)g (a)h(p)s(ound)d(sign)i('#',)i(then)e(c\014tsio)i(will)e(substitute)h (the)f(n)m(um)m(b)s(er)f(of)i(the)227 3225 y(most)31 b(recen)m(tly)h(referenced)e(column)h(for)f(the)h(#)f(c)m(haracter)i(.) 41 b(This)29 b(is)i(esp)s(ecially)h(useful)d(when)h(writing)227 3337 y(a)c(column-related)g(k)m(eyw)m(ord)g(lik)m(e)g(TUNITn)e(for)h(a) h(newly)f(created)h(column,)g(as)g(sho)m(wn)e(in)h(the)g(follo)m(wing) 227 3450 y(examples.)227 3600 y(COMMENT)30 b(and)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)g(ma)m(y)h(also)h(b)s(e)e(created)h(with)f(the) h(follo)m(wing)g(syn)m(tax:)370 3848 y Ff(#COMMENT)46 b(=)h('This)g(is)g(a)g(comment)f(keyword')370 3961 y(#HISTORY)g(=)h ('This)g(is)g(a)g(history)f(keyword')227 4209 y Fj(Note)d(that)f(the)f (equal)h(sign)f(and)f(the)i(quote)f(c)m(haracters)i(will)f(b)s(e)e (remo)m(v)m(ed,)45 b(so)d(that)f(the)h(resulting)227 4322 y(header)30 b(k)m(eyw)m(ords)h(in)f(these)h(cases)g(will)g(lo)s (ok)g(lik)m(e)h(this:)370 4569 y Ff(COMMENT)46 b(This)h(is)g(a)h (comment)d(keyword)370 4682 y(HISTORY)h(This)h(is)g(a)h(history)d (keyword)227 4930 y Fj(These)29 b(t)m(w)m(o)h(sp)s(ecial)f(k)m(eyw)m (ords)h(are)f(alw)m(a)m(ys)h(app)s(ended)d(to)j(the)f(end)f(of)h(the)g (header)g(and)f(will)h(not)g(a\013ect)227 5043 y(an)m(y)i(previously)f (existing)h(COMMENT)f(or)h(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords.)136 5230 y Fd(\017)46 b Fj(Recompute)f(\(o)m(v)m(erwrite\))i(the)d(v)-5 b(alues)44 b(in)g(an)g(existing)i(column)e(or)g(k)m(eyw)m(ord)g(b)m(y)g (giving)i(the)e(name)227 5343 y(follo)m(w)m(ed)32 b(b)m(y)f(an)f (equals)h(sign)f(and)g(an)g(arithmetic)i(expression.)0 5601 y(The)23 b(expression)g(that)i(is)e(used)g(when)g(app)s(ending)f (or)h(recomputing)h(columns)f(or)h(k)m(eyw)m(ords)g(can)g(b)s(e)f (arbitrarily)0 5714 y(complex)36 b(and)g(ma)m(y)g(b)s(e)f(a)h(function) g(of)g(other)g(header)g(k)m(eyw)m(ord)g(v)-5 b(alues)36 b(and)f(other)h(columns)g(\(in)g(the)g(same)p eop end %%Page: 96 102 TeXDict begin 96 101 bop 0 299 a Fj(96)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(ro)m(w\).)63 b(The)37 b(full)g(syn)m(tax)i(and)e(a)m(v)-5 b(ailable)40 b(functions)d(for)g(the)h(expression)f(are)h(describ)s(ed) f(b)s(elo)m(w)h(in)f(the)h(ro)m(w)0 668 y(\014lter)30 b(sp)s(eci\014cation)i(section.)0 828 y(If)27 b(the)h(expression)g(con) m(tains)g(b)s(oth)f(a)h(list)h(of)f(columns)f(to)h(b)s(e)g(included)e (and)i(columns)f(to)h(b)s(e)f(deleted,)j(then)d(all)0 941 y(the)34 b(columns)g(in)g(the)g(original)h(table)g(except)g(the)f (explicitly)i(deleted)f(columns)e(will)i(app)s(ear)e(in)h(the)g (\014ltered)0 1054 y(table.)40 b(If)26 b(no)g(columns)f(to)i(b)s(e)f (deleted)g(are)h(sp)s(eci\014ed,)f(then)g(only)g(the)h(columns)e(that)i (are)f(explicitly)i(listed)f(will)0 1167 y(b)s(e)k(included)g(in)g(the) h(\014ltered)f(output)h(table.)45 b(T)-8 b(o)32 b(include)f(all)i(the)e (columns,)h(add)f(the)h('*')g(wildcard)g(sp)s(eci\014er)0 1280 y(at)f(the)g(end)e(of)i(the)f(list,)i(as)e(sho)m(wn)g(in)g(the)h (examples.)0 1440 y(F)-8 b(or)30 b(complex)h(or)e(commonly)h(used)f(op) s(erations,)i(one)e(can)h(also)h(place)g(the)e(op)s(erations)h(in)m(to) h(an)e(external)i(text)0 1553 y(\014le)g(and)f(imp)s(ort)g(it)h(in)m (to)h(the)f(column)g(\014lter)f(using)h(the)g(syn)m(tax)g('[col)h (@\014lename.txt]'.)43 b(The)31 b(op)s(erations)g(can)0 1666 y(extend)k(o)m(v)m(er)h(m)m(ultiple)g(lines)f(of)g(the)g(\014le,)h (but)e(m)m(ultiple)i(op)s(erations)f(m)m(ust)f(still)i(b)s(e)e (separated)i(b)m(y)e(commas)0 1779 y(or)e(semi-colons.)47 b(An)m(y)32 b(lines)h(in)f(the)g(external)h(text)g(\014le)f(that)h(b)s (egin)e(with)h(2)h(slash)e(c)m(haracters)j(\('//'\))g(will)f(b)s(e)0 1892 y(ignored)d(and)g(ma)m(y)h(b)s(e)f(used)g(to)h(add)e(commen)m(ts)j (in)m(to)f(the)g(\014le.)0 2052 y(Examples:)143 2439 y Ff([col)47 b(Time,)f(rate])667 b(-)47 b(only)g(the)g(Time)g(and)g (rate)f(columns)g(will)1670 2552 y(appear)h(in)g(the)g(filtered)e (input)i(file.)143 2778 y([col)g(Time,)f(*raw])667 b(-)47 b(include)f(the)h(Time)g(column)f(and)h(any)g(other)1670 2891 y(columns)f(whose)h(name)f(ends)h(with)g('raw'.)143 3117 y([col)g(-TIME;)f(Good)h(==)g(STATUS])141 b(-)47 b(deletes)f(the)h(TIME)g(column)f(and)1670 3230 y(renames)g(the)h (status)f(column)g(to)i('Good')143 3456 y([col)f(PI=PHA)f(*)h(1.1)g(+)h (0.2;)e(#TUNIT#\(column)e(units\))i(=)i('counts';*])1575 3569 y(-)f(creates)f(new)h(PI)g(column)f(from)h(PHA)g(values)1670 3681 y(and)g(also)g(writes)f(the)h(TUNITn)f(keyword)1670 3794 y(for)h(the)g(new)g(column.)94 b(The)47 b(final)f('*')1670 3907 y(expression)f(means)i(preserve)e(all)i(the)1670 4020 y(columns)f(in)h(the)g(input)g(table)f(in)h(the)1670 4133 y(virtual)f(output)g(table;)94 b(without)46 b(the)h('*')1670 4246 y(the)g(output)f(table)h(would)f(only)h(contain)1670 4359 y(the)g(single)f('PI')h(column.)143 4585 y([col)g(rate)f(=)i (rate/exposure,)c(TUNIT#\(&\))h(=)j('counts/s';*])1575 4698 y(-)f(recomputes)e(the)i(rate)g(column)f(by)h(dividing)1670 4811 y(it)h(by)f(the)g(EXPOSURE)e(keyword)h(value.)g(This)1670 4924 y(also)h(modifies)f(the)h(value)f(of)h(the)g(TUNITn)1670 5036 y(keyword)f(for)h(this)g(column.)f(The)h(use)f(of)i(the)1670 5149 y('&')f(character)f(for)h(the)f(keyword)g(comment)1670 5262 y(string)h(means)f(preserve)f(the)i(existing)1670 5375 y(comment)f(string)g(for)h(that)g(keyword.)e(The)1670 5488 y(final)i('*')g(preserves)e(all)i(the)g(columns)1670 5601 y(in)h(the)f(input)f(table)g(in)h(the)g(virtual)1670 5714 y(output)g(table.)p eop end %%Page: 97 103 TeXDict begin 97 102 bop 0 299 a Fh(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)2027 b Fj(97)0 555 y Fe(8.11)136 b(Ro)l(w)45 b(Filtering)h(Sp)t(eci\014cation)0 806 y Fj(When)29 b(en)m(tering)h(the)f(name)g(of)g(a)g(FITS)f(table)i (that)g(is)e(to)i(b)s(e)e(op)s(ened)h(b)m(y)f(a)i(program,)f(an)g (optional)h(ro)m(w)f(\014lter)0 919 y(ma)m(y)i(b)s(e)g(sp)s(eci\014ed)f (to)h(select)h(a)g(subset)e(of)h(the)g(ro)m(ws)f(in)h(the)g(table.)43 b(A)31 b(temp)s(orary)f(new)g(FITS)g(\014le)h(is)g(created)0 1032 y(on)25 b(the)h(\015y)e(whic)m(h)h(con)m(tains)h(only)g(those)g (ro)m(ws)f(for)g(whic)m(h)g(the)g(ro)m(w)g(\014lter)h(expression)f(ev) -5 b(aluates)26 b(to)g(true.)39 b(\(The)0 1144 y(primary)26 b(arra)m(y)h(and)f(an)m(y)g(other)h(extensions)g(in)f(the)h(input)f (\014le)g(are)h(also)h(copied)f(to)g(the)f(temp)s(orary)h(\014le\).)39 b(The)0 1257 y(original)30 b(FITS)f(\014le)g(is)g(closed)h(and)e(the)i (new)e(virtual)i(\014le)f(is)g(op)s(ened)f(b)m(y)h(the)h(application)g (program.)40 b(The)29 b(ro)m(w)0 1370 y(\014lter)37 b(expression)g(is)h (enclosed)g(in)f(square)g(brac)m(k)m(ets)i(follo)m(wing)g(the)e(\014le) h(name)f(and)g(extension)h(name)f(\(e.g.,)0 1483 y('\014le.\014ts[ev)m (en)m(ts][GRADE==50]')29 b(selects)d(only)f(those)h(ro)m(ws)f(where)f (the)h(GRADE)h(column)f(v)-5 b(alue)25 b(equals)g(50\).)0 1596 y(When)33 b(dealing)h(with)f(tables)g(where)g(eac)m(h)h(ro)m(w)f (has)g(an)g(asso)s(ciated)i(time)f(and/or)f(2D)g(spatial)i(p)s (osition,)f(the)0 1709 y(ro)m(w)e(\014lter)h(expression)e(can)i(also)g (b)s(e)f(used)f(to)i(select)h(ro)m(ws)e(based)g(on)g(the)g(times)h(in)f (a)g(Go)s(o)s(d)g(Time)g(In)m(terv)-5 b(als)0 1822 y(\(GTI\))31 b(extension,)g(or)f(on)h(spatial)g(p)s(osition)g(as)f(giv)m(en)i(in)e (a)g(SA)m(O-st)m(yle)i(region)f(\014le.)0 2114 y Fc(8.11.1)113 b(General)38 b(Syn)m(tax)0 2333 y Fj(The)32 b(ro)m(w)h(\014ltering)g (expression)g(can)g(b)s(e)f(an)h(arbitrarily)g(complex)g(series)g(of)g (op)s(erations)g(p)s(erformed)f(on)g(con-)0 2446 y(stan)m(ts,)39 b(k)m(eyw)m(ord)e(v)-5 b(alues,)38 b(and)e(column)g(data)i(tak)m(en)f (from)f(the)h(sp)s(eci\014ed)e(FITS)h(T)-8 b(ABLE)37 b(extension.)59 b(The)0 2559 y(expression)37 b(m)m(ust)h(ev)-5 b(aluate)39 b(to)g(a)f(b)s(o)s(olean)g(v)-5 b(alue)38 b(for)f(eac)m(h)i(ro)m(w)f(of)g(the)f(table,)k(where)c(a)h(v)-5 b(alue)39 b(of)e(F)-10 b(ALSE)0 2672 y(means)30 b(that)h(the)g(ro)m(w)f (will)h(b)s(e)f(excluded.)0 2832 y(F)-8 b(or)34 b(complex)g(or)g (commonly)f(used)g(\014lters,)h(one)g(can)g(place)g(the)g(expression)f (in)m(to)h(a)g(text)g(\014le)g(and)f(imp)s(ort)f(it)0 2945 y(in)m(to)38 b(the)e(ro)m(w)h(\014lter)g(using)f(the)h(syn)m(tax)g ('[@\014lename.txt]'.)61 b(The)36 b(expression)h(can)f(b)s(e)g (arbitrarily)h(complex)0 3058 y(and)27 b(extend)i(o)m(v)m(er)g(m)m (ultiple)g(lines)f(of)g(the)h(\014le.)40 b(An)m(y)28 b(lines)g(in)g(the)g(external)h(text)g(\014le)f(that)h(b)s(egin)f(with) g(2)g(slash)0 3171 y(c)m(haracters)k(\('//'\))g(will)f(b)s(e)f(ignored) g(and)g(ma)m(y)h(b)s(e)f(used)f(to)i(add)f(commen)m(ts)h(in)m(to)h(the) e(\014le.)0 3331 y(Keyw)m(ord)37 b(and)f(column)g(data)i(are)f (referenced)g(b)m(y)g(name.)60 b(An)m(y)37 b(string)f(of)h(c)m (haracters)i(not)e(surrounded)d(b)m(y)0 3444 y(quotes)41 b(\(ie,)j(a)d(constan)m(t)h(string\))f(or)f(follo)m(w)m(ed)i(b)m(y)f (an)f(op)s(en)g(paren)m(theses)h(\(ie,)j(a)d(function)f(name\))h(will)g (b)s(e)0 3557 y(initially)d(in)m(terpreted)e(as)h(a)g(column)f(name)g (and)g(its)h(con)m(ten)m(ts)h(for)e(the)h(curren)m(t)f(ro)m(w)g (inserted)g(in)m(to)i(the)e(ex-)0 3670 y(pression.)k(If)28 b(no)h(suc)m(h)g(column)g(exists,)h(a)g(k)m(eyw)m(ord)f(of)h(that)f (name)g(will)h(b)s(e)e(searc)m(hed)i(for)f(and)f(its)i(v)-5 b(alue)29 b(used,)0 3783 y(if)36 b(found.)55 b(T)-8 b(o)36 b(force)g(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)g(a)g(k)m(eyw)m (ord)g(\(in)g(case)g(there)g(is)g(b)s(oth)f(a)h(column)g(and)0 3896 y(k)m(eyw)m(ord)41 b(with)e(the)i(same)f(name\),)j(precede)d(the)h (k)m(eyw)m(ord)f(name)g(with)g(a)h(single)f(p)s(ound)e(sign,)43 b('#',)g(as)d(in)0 4009 y('#NAXIS2'.)g(Due)27 b(to)g(the)f (generalities)j(of)d(FITS)g(column)g(and)g(k)m(eyw)m(ord)h(names,)g(if) f(the)h(column)f(or)g(k)m(eyw)m(ord)0 4121 y(name)33 b(con)m(tains)h(a)f(space)h(or)f(a)g(c)m(haracter)h(whic)m(h)f(migh)m (t)h(app)s(ear)e(as)h(an)g(arithmetic)h(term)f(then)g(enclose)h(the)0 4234 y(name)c(in)g('$')i(c)m(haracters)g(as)e(in)g($MAX)i(PHA$)f(or)f (#$MAX-PHA$.)43 b(Names)31 b(are)f(case)i(insensitiv)m(e.)0 4394 y(T)-8 b(o)32 b(access)g(a)g(table)g(en)m(try)g(in)f(a)h(ro)m(w)f (other)h(than)f(the)g(curren)m(t)g(one,)h(follo)m(w)h(the)e(column's)h (name)f(with)g(a)h(ro)m(w)0 4507 y(o\013set)37 b(within)e(curly)g (braces.)57 b(F)-8 b(or)36 b(example,)i('PHA)p Fd(f)p Fj(-3)p Fd(g)p Fj(')g(will)e(ev)-5 b(aluate)38 b(to)e(the)g(v)-5 b(alue)36 b(of)g(column)f(PHA,)i(3)0 4620 y(ro)m(ws)28 b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s(eing)g(pro)s (cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g(absolute)h(ro)m(w)f (n)m(um)m(b)s(er,)g(only)h(a)0 4733 y(relativ)m(e)j(o\013set.)42 b(Ro)m(ws)31 b(that)g(fall)g(outside)g(the)f(table)h(will)g(b)s(e)f (treated)h(as)g(unde\014ned,)d(or)j(NULLs.)0 4893 y(When)36 b(using)f(ro)m(w)h(\014ltering)g(to)g(op)s(en)g(a)g(\014le)g(\\on)g (the)g(\015y)-8 b(,")38 b(it)e(is)g(p)s(ermitted)f(to)i(use)e(m)m (ultiple)i(ro)m(w)f(\014ltering)0 5006 y(expressions.)k(F)-8 b(or)31 b(example,)h(the)e(expression)95 5242 y Ff(filename.fits[#ROW) 43 b(>)48 b(5][X.gt.7])0 5478 y Fj(w)m(ould)30 b(b)s(e)g(treated)h(as)g (equiv)-5 b(alen)m(t)32 b(to)f(joining)f(the)h(expressions)f(with)g (logical)j(\\and")d(lik)m(e)i(this,)95 5714 y Ff(filename.fits[\(#ROW) 43 b(>)k(5\)&&\(X.gt.7\)])p eop end %%Page: 98 104 TeXDict begin 98 103 bop 0 299 a Fj(98)1618 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(Please)35 b(note)g(that)g(if)g(m)m(ultiple)g(ro)m(w)f (\014ltering)h(expressions)e(are)i(used,)g(it)g(is)f(not)h(p)s (ermitted)e(to)i(also)h(use)e(the)0 668 y Ff([@filename.txt])26 b Fj(syn)m(tax)31 b(in)f(an)m(y)h(of)f(the)h(individual)f(expressions.) 0 828 y(Bo)s(olean)i(op)s(erators)f(can)g(b)s(e)f(used)f(in)i(the)f (expression)h(in)f(either)h(their)g(F)-8 b(ortran)31 b(or)f(C)h(forms.)40 b(The)30 b(follo)m(wing)0 941 y(b)s(o)s(olean)g (op)s(erators)h(are)g(a)m(v)-5 b(ailable:)191 1191 y Ff("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)191 1304 y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)191 1417 y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)191 1530 y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 b(.AND.)h(&&)191 1643 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 b(~)0 1893 y Fj(Note)32 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)e(') 10 b(!',)33 b(is)e(a)g(sp)s(ecial)g(UNIX)h(c)m(haracter,)h(so)e(if)g (it)g(is)g(used)f(on)h(the)g(command)0 2005 y(line)i(rather)f(than)h (en)m(tered)g(at)g(a)g(task)g(prompt,)g(it)g(m)m(ust)f(b)s(e)g (preceded)h(b)m(y)f(a)h(bac)m(kslash)g(to)h(force)f(the)g(UNIX)0 2118 y(shell)e(to)g(ignore)g(it.)0 2279 y(The)h(expression)g(ma)m(y)i (also)f(include)f(arithmetic)i(op)s(erators)f(and)f(functions.)47 b(T)-8 b(rigonometric)34 b(functions)e(use)0 2391 y(radians,)23 b(not)g(degrees.)38 b(The)22 b(follo)m(wing)h(arithmetic)g(op)s (erators)g(and)e(functions)g(can)i(b)s(e)e(used)g(in)h(the)g (expression)0 2504 y(\(function)38 b(names)f(are)h(case)g(insensitiv)m (e\).)64 b(A)37 b(n)m(ull)h(v)-5 b(alue)38 b(will)f(b)s(e)g(returned)g (in)g(case)h(of)g(illegal)i(op)s(erations)0 2617 y(suc)m(h)30 b(as)h(divide)f(b)m(y)g(zero,)i(sqrt\(negativ)m(e\))h(log\(negativ)m (e\),)h(log10\(negativ)m(e\),)i(arccos\(.gt.)43 b(1\),)32 b(arcsin\(.gt.)42 b(1\).)191 2867 y Ff("addition")522 b(+)477 b("subtraction")d(-)191 2980 y("multiplication")234 b(*)477 b("division")618 b(/)191 3093 y("negation")522 b(-)477 b("exponentiation")330 b(**)143 b(^)191 3206 y("absolute)45 b(value")237 b(abs\(x\))g("cosine")714 b(cos\(x\))191 3319 y("sine")g(sin\(x\))237 b("tangent")666 b(tan\(x\))191 3432 y("arc)47 b(cosine")427 b(arccos\(x\))93 b("arc)47 b(sine")619 b(arcsin\(x\))191 3545 y("arc)47 b(tangent")379 b(arctan\(x\))93 b("arc)47 b(tangent")475 b(arctan2\(y,x\))191 3657 y("hyperbolic)45 b(cos")237 b(cosh\(x\))189 b("hyperbolic)45 b(sin")333 b(sinh\(x\))191 3770 y("hyperbolic)45 b(tan")237 b(tanh\(x\))189 b("round)46 b(to)h(nearest)f(int")h(round\(x\))191 3883 y("round)f(down)h(to)g (int")94 b(floor\(x\))141 b("round)46 b(up)h(to)h(int")285 b(ceil\(x\))191 3996 y("exponential")378 b(exp\(x\))237 b("square)46 b(root")476 b(sqrt\(x\))191 4109 y("natural)45 b(log")381 b(log\(x\))237 b("common)46 b(log")524 b(log10\(x\))191 4222 y("error)46 b(function")236 b(erf\(x\))h("complement)45 b(of)i(erf")190 b(erfc\(x\))191 4335 y("gamma)46 b(function")236 b(gamma\(x\))191 4448 y("modulus")570 b(x)48 b(\045)f(y)191 4561 y("bitwise)e(AND")381 b(x)48 b(&)f(y)286 b("bitwise)46 b(OR")524 b(x)47 b(|)h(y)191 4674 y("bitwise)d(XOR")381 b(x)48 b(^^)f(y)238 b(\(bitwise)46 b(operators)f(are)i(32-bit)f(int)h (only\))191 4787 y("random)f(#)h([0.0,1.0\)")e(random\(\))191 4899 y("random)h(Gaussian")188 b(randomn\(\))93 b("random)46 b(Poisson")332 b(randomp\(x\))191 5012 y("minimum")570 b(min\(x,y\))141 b("maximum")666 b(max\(x,y\))191 5125 y("cumulative)45 b(sum")237 b(accum\(x\))141 b("sequential)45 b(difference")g(seqdiff\(x\))191 5238 y("if-then-else")330 b(b?x:y)191 5351 y("angular)45 b(separation")g (angsep\(ra1,dec1,ra2,de2\))c(\(all)47 b(in)g(degrees\))191 5464 y("substring")474 b(strmid\(s,p,n\))44 b("string)i(search")237 b(strstr\(s,r\))0 5714 y Fj(The)30 b(bit)m(wise)h(op)s(erators)f(for)h (AND,)g(OR)f(and)g(X)m(OR)g(op)s(erate)h(up)s(on)e(32-bit)j(in)m(teger) f(expressions)f(only)-8 b(.)p eop end %%Page: 99 105 TeXDict begin 99 104 bop 0 299 a Fh(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)2027 b Fj(99)0 555 y(Three)30 b(di\013eren)m(t)h(random)f(n)m(um)m(b)s(er)f(functions) h(are)h(pro)m(vided:)41 b(random\(\),)30 b(with)h(no)f(argumen)m(ts,)h (pro)s(duces)f(a)0 668 y(uniform)g(random)f(deviate)k(b)s(et)m(w)m(een) e(0)g(and)f(1;)i(randomn\(\),)e(also)i(with)e(no)h(argumen)m(ts,)g(pro) s(duces)f(a)h(normal)0 781 y(\(Gaussian\))k(random)e(deviate)j(with)e (zero)h(mean)f(and)g(unit)f(standard)h(deviation;)j(randomp\(x\))d(pro) s(duces)f(a)0 894 y(P)m(oisson)27 b(random)f(deviate)h(whose)f(exp)s (ected)h(n)m(um)m(b)s(er)e(of)h(coun)m(ts)h(is)g(X.)f(X)h(ma)m(y)g(b)s (e)e(an)m(y)i(p)s(ositiv)m(e)g(real)g(n)m(um)m(b)s(er)0 1007 y(of)k(exp)s(ected)f(coun)m(ts,)h(including)f(fractional)i(v)-5 b(alues,)31 b(but)f(the)g(return)g(v)-5 b(alue)31 b(is)f(an)g(in)m (teger.)0 1167 y(When)d(the)g(random)g(functions)f(are)i(used)e(in)h(a) h(v)m(ector)g(expression,)g(b)m(y)f(default)h(the)f(same)h(random)e(v) -5 b(alue)28 b(will)0 1280 y(b)s(e)g(used)f(when)h(ev)-5 b(aluating)30 b(eac)m(h)f(elemen)m(t)h(of)f(the)g(v)m(ector.)41 b(If)28 b(di\013eren)m(t)h(random)f(n)m(um)m(b)s(ers)f(are)i(desired,)f (then)0 1393 y(the)37 b(name)g(of)g(a)g(v)m(ector)i(column)e(should)e (b)s(e)i(supplied)e(as)i(the)h(single)f(argumen)m(t)g(to)h(the)f (random)f(function)0 1506 y(\(e.g.,)e("\015ux)c(+)h(0.1)i(*)e (random\(\015ux\)",)h(where)f("\015ux")g(is)g(the)h(name)f(of)h(a)f(v)m (ector)i(column\).)44 b(This)31 b(will)g(create)0 1619 y(a)38 b(v)m(ector)i(of)e(random)f(n)m(um)m(b)s(ers)f(that)j(will)f(b)s (e)f(used)g(in)h(sequence)g(when)f(ev)-5 b(aluating)39 b(eac)m(h)g(elemen)m(t)h(of)e(the)0 1732 y(v)m(ector)32 b(expression.)0 1892 y(An)f(alternate)i(syn)m(tax)f(for)f(the)g(min)g (and)g(max)g(functions)g(has)g(only)g(a)h(single)g(argumen)m(t)g(whic)m (h)f(should)f(b)s(e)h(a)0 2005 y(v)m(ector)g(v)-5 b(alue)30 b(\(see)g(b)s(elo)m(w\).)41 b(The)29 b(result)g(will)h(b)s(e)e(the)i (minim)m(um/maxim)m(um)f(elemen)m(t)h(con)m(tained)h(within)e(the)0 2118 y(v)m(ector.)0 2278 y(The)35 b(accum\(x\))i(function)f(forms)f (the)h(cum)m(ulativ)m(e)i(sum)d(of)h(x,)h(elemen)m(t)h(b)m(y)e(elemen)m (t.)58 b(V)-8 b(ector)38 b(columns)e(are)0 2391 y(supp)s(orted)h (simply)h(b)m(y)g(p)s(erforming)f(the)i(summation)g(pro)s(cess)f (through)f(all)j(the)f(v)-5 b(alues.)65 b(Null)39 b(v)-5 b(alues)39 b(are)0 2503 y(treated)30 b(as)f(0.)41 b(The)29 b(seqdi\013\(x\))h(function)e(forms)h(the)g(sequen)m(tial)i (di\013erence)e(of)h(x,)f(elemen)m(t)i(b)m(y)e(elemen)m(t.)41 b(The)0 2616 y(\014rst)36 b(v)-5 b(alue)38 b(of)f(seqdi\013)g(is)g(the) g(\014rst)g(v)-5 b(alue)37 b(of)g(x.)61 b(A)37 b(single)h(n)m(ull)f(v) -5 b(alue)38 b(in)e(x)h(causes)h(a)f(pair)g(of)g(n)m(ulls)g(in)g(the)0 2729 y(output.)55 b(The)35 b(seqdi\013)g(and)g(accum)g(functions)g(are) h(functional)f(in)m(v)m(erses,)j(i.e.,)g(seqdi\013\(accum\(x\)\))f(==)e (x)g(as)0 2842 y(long)c(as)g(no)f(n)m(ull)g(v)-5 b(alues)31 b(are)g(presen)m(t.)0 3002 y(In)36 b(the)h(if-then-else)i(expression,)f ("b?x:y",)i(b)c(is)h(an)g(explicit)h(b)s(o)s(olean)f(v)-5 b(alue)37 b(or)g(expression.)61 b(There)36 b(is)h(no)0 3115 y(automatic)d(t)m(yp)s(e)e(con)m(v)m(ersion)h(from)e(n)m(umeric)h (to)g(b)s(o)s(olean)g(v)-5 b(alues,)33 b(so)f(one)g(needs)f(to)i(use)e ("iV)-8 b(al!=0")35 b(instead)0 3228 y(of)30 b(merely)g("iV)-8 b(al")32 b(as)e(the)g(b)s(o)s(olean)g(argumen)m(t.)41 b(x)30 b(and)f(y)h(can)g(b)s(e)f(an)m(y)h(scalar)h(data)g(t)m(yp)s(e)f (\(including)f(string\).)0 3388 y(The)22 b(angsep)g(function)f (computes)i(the)f(angular)g(separation)h(in)e(degrees)i(b)s(et)m(w)m (een)g(2)f(celestial)j(p)s(ositions,)e(where)0 3501 y(the)36 b(\014rst)f(2)h(parameters)g(giv)m(e)h(the)f(RA-lik)m(e)i(and)d (Dec-lik)m(e)j(co)s(ordinates)f(\(in)f(decimal)g(degrees\))h(of)f(the)g (\014rst)0 3614 y(p)s(osition,)31 b(and)e(the)i(3rd)f(and)g(4th)g (parameters)h(giv)m(e)h(the)e(co)s(ordinates)i(of)e(the)h(second)f(p)s (osition.)0 3774 y(The)38 b(substring)f(function)i(strmid\(S,P)-8 b(,N\))39 b(extracts)g(a)g(substring)f(from)g(S,)g(starting)h(at)g (string)g(p)s(osition)f(P)-8 b(,)0 3887 y(with)33 b(a)h(substring)f (length)h(N.)g(The)f(\014rst)g(c)m(haracter)j(p)s(osition)d(in)h(S)f (is)h(lab)s(eled)g(as)g(1.)51 b(If)33 b(P)g(is)h(0,)h(or)f(refers)f(to) 0 4000 y(a)i(p)s(osition)g(b)s(ey)m(ond)f(the)h(end)e(of)i(S,)g(then)f (the)h(extracted)h(substring)d(will)i(b)s(e)f(NULL.)h(S,)f(P)-8 b(,)36 b(and)e(N)g(ma)m(y)i(b)s(e)0 4113 y(functions)30 b(of)g(other)h(columns.)0 4273 y(The)39 b(string)h(searc)m(h)h (function)e(strstr\(S,R\))h(searc)m(hes)h(for)f(the)g(\014rst)f(o)s (ccurrence)h(of)g(the)g(substring)f(R)h(in)f(S.)0 4386 y(The)c(result)h(is)f(an)h(in)m(teger,)i(indicating)f(the)e(c)m (haracter)i(p)s(osition)f(of)g(the)g(\014rst)e(matc)m(h)j(\(where)e(1)h (is)g(the)g(\014rst)0 4499 y(c)m(haracter)c(p)s(osition)e(of)h(S\).)f (If)g(no)h(matc)m(h)g(is)f(found,)g(then)g(strstr\(\))g(returns)f(a)i (NULL)f(v)-5 b(alue.)0 4659 y(The)37 b(follo)m(wing)i(t)m(yp)s(e)f (casting)g(op)s(erators)g(are)g(a)m(v)-5 b(ailable,)42 b(where)37 b(the)h(enclosing)g(paren)m(theses)g(are)g(required)0 4772 y(and)30 b(tak)m(en)h(from)f(the)h(C)f(language)h(usage.)42 b(Also,)31 b(the)g(in)m(teger)g(to)h(real)f(casts)g(v)-5 b(alues)30 b(to)i(double)e(precision:)764 5011 y Ff("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 b(x)764 5124 y("integer)f(to)i(real")190 b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)0 5362 y Fj(In)30 b(addition,)g(sev)m(eral)i (constan)m(ts)g(are)f(built)f(in)g(for)g(use)g(in)g(n)m(umerical)h (expressions:)382 5601 y Ff(#pi)667 b(3.1415...)284 b(#e)620 b(2.7182...)382 5714 y(#deg)f(#pi/180)380 b(#row)524 b(current)46 b(row)h(number)p eop end %%Page: 100 106 TeXDict begin 100 105 bop 0 299 a Fj(100)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)382 555 y Ff(#null)428 b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 b(string)0 832 y Fj(A)40 b(string)f(constan)m(t)i(m)m (ust)e(b)s(e)g(enclosed)h(in)g(quotes)g(as)f(in)h('Crab'.)67 b(The)39 b("n)m(ull")i(constan)m(ts)f(are)g(useful)f(for)0 945 y(conditionally)g(setting)g(table)g(v)-5 b(alues)38 b(to)g(a)g(NULL,)g(or)g(unde\014ned,)f(v)-5 b(alue)39 b(\(eg.,)i("col1==-99)f(?)62 b(#NULL)38 b(:)0 1058 y(col1"\).)0 1218 y(In)m(teger)31 b(constan)m(ts)h(ma)m(y)f(b)s(e)f(sp)s(eci\014ed)f (using)h(the)h(follo)m(wing)h(notation,)525 1466 y Ff(13245)142 b(decimal)46 b(integer)525 1579 y(0x12f3)94 b(hexidecimal)45 b(integer)525 1692 y(0o1373)94 b(octal)46 b(integer)525 1805 y(0b01001)g(binary)g(integer)0 2053 y Fj(Note)22 b(that)e(in)m(teger)i(constan)m(ts)g(are)e(only)h(allo)m(w)m(ed)h(to)f (b)s(e)e(32-bit,)24 b(i.e.)38 b(b)s(et)m(w)m(een)21 b(-2)2787 2020 y Fa(\()2820 2053 y Fj(31\))p Fb(and)p Fj(+2)3211 2020 y Fa(\()3244 2053 y Fj(31\))p Fb(:I)7 b(nteg)s(er)s(constantsmay)s (beusedinany)s(ar)s(ithmeticexpr)s(essionw)r(her)s(eaninteg)s(er)s(w)r (oul)r(dbeappr)s(opr)s(iate:T)13 b(hus;)i(they)s(ar)s(edistinctf)10 b(r)s(ombitmask)s(s)p Fj(\()p Fb(w)r(hichmay)s(beof)g(ar)s(bitr)s(ar)s (y)s(l)r(eng)s(th;)15 b(al)r(l)r(ow)r(the)p Fj(")p Fb(w)r(il)r(dcar)s (d)p Fj(")p Fb(bit;)g(andmay)s(onl)r(y)s(beusedinl)r(og)s(ical)r(expr)s (essions)p Fj(;)g Fb(seebel)r(ow)r Fj(\))q Fb(:)0 2213 y Fj(There)27 b(is)g(also)i(a)e(function)g(for)h(testing)g(if)f(t)m(w)m (o)i(v)-5 b(alues)28 b(are)g(close)g(to)h(eac)m(h)f(other,)h(i.e.,)g (if)e(they)h(are)g("near")g(eac)m(h)0 2326 y(other)c(to)h(within)e(a)h (user)g(sp)s(eci\014ed)f(tolerance.)40 b(The)24 b(argumen)m(ts,)h(v)-5 b(alue)p 2502 2326 28 4 v 34 w(1)24 b(and)f(v)-5 b(alue)p 2979 2326 V 33 w(2)25 b(can)f(b)s(e)f(in)m(teger)i(or)f(real)0 2439 y(and)32 b(represen)m(t)h(the)g(t)m(w)m(o)h(v)-5 b(alues)33 b(who's)f(pro)m(ximit)m(y)i(is)f(b)s(eing)f(tested)h(to)h(b) s(e)e(within)g(the)h(sp)s(eci\014ed)f(tolerance,)0 2552 y(also)f(an)g(in)m(teger)g(or)g(real:)955 2829 y Ff(near\(value_1,)44 b(value_2,)h(tolerance\))0 3106 y Fj(When)24 b(a)i(NULL,)e(or)h (unde\014ned,)f(v)-5 b(alue)25 b(is)g(encoun)m(tered)g(in)g(the)f(FITS) g(table,)j(the)e(expression)g(will)g(ev)-5 b(aluate)26 b(to)0 3219 y(NULL)31 b(unless)f(the)h(unde\014ned)e(v)-5 b(alue)31 b(is)g(not)g(actually)h(required)e(for)h(ev)-5 b(aluation,)33 b(e.g.)43 b("TR)m(UE)31 b(.or.)43 b(NULL")0 3332 y(ev)-5 b(aluates)32 b(to)f(TR)m(UE.)g(The)f(follo)m(wing)h(t)m(w) m(o)h(functions)e(allo)m(w)i(some)f(NULL)f(detection)i(and)e(handling:) 430 3609 y Ff("a)47 b(null)f(value?")667 b(ISNULL\(x\))430 3722 y("define)45 b(a)j(value)e(for)h(null")190 b(DEFNULL\(x,y\))430 3835 y("declare)45 b(certain)h(value)g(null")h(SETNULL\(x,y\))0 4112 y Fj(ISNULL\(x\))24 b(returns)g(a)g(b)s(o)s(olean)h(v)-5 b(alue)25 b(of)f(TR)m(UE)h(if)f(the)h(argumen)m(t)g(x)f(is)g(NULL.)h (DEFNULL\(x,y\))h("de\014nes")0 4225 y(a)31 b(v)-5 b(alue)31 b(to)g(b)s(e)e(substituted)h(for)g(NULL)g(v)-5 b(alues;)31 b(it)g(returns)e(the)i(v)-5 b(alue)31 b(of)f(x)h(if)f(x)g(is)h(not)f (NULL,)h(otherwise)f(it)0 4338 y(returns)d(the)i(v)-5 b(alue)28 b(of)h(y)-8 b(.)40 b(SETNULL\(x,y\))28 b(allo)m(ws)i(NULL)e (v)-5 b(alues)29 b(to)g(b)s(e)f(inserted)g(in)m(to)h(a)g(v)-5 b(ariable;)30 b(if)e(x==y)-8 b(,)0 4451 y(a)34 b(NULL)g(v)-5 b(alue)35 b(is)f(returned;)g(otherwise)h(y)f(is)f(returned)g(\(x)h(and) g(y)g(m)m(ust)f(b)s(e)h(n)m(umerical,)h(and)f(x)f(m)m(ust)h(b)s(e)g(a)0 4564 y(scalar\).)0 4875 y Fc(8.11.2)113 b(Bit)36 b(Masks)0 5098 y Fj(Bit)g(masks)f(can)h(b)s(e)f(used)f(to)i(select)h(out)e(ro)m (ws)h(from)e(bit)i(columns)f(\(TF)m(ORMn)g(=)g(#X\))h(in)f(FITS)f (\014les.)55 b(T)-8 b(o)0 5211 y(represen)m(t)30 b(the)h(mask,)g (binary)-8 b(,)30 b(o)s(ctal,)i(and)e(hex)g(formats)g(are)h(allo)m(w)m (ed:)811 5488 y Ff(binary:)142 b(b0110xx1010000101xxxx00)o(01)811 5601 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))811 5714 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))p eop end %%Page: 101 107 TeXDict begin 101 106 bop 0 299 a Fh(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fj(101)0 555 y(In)22 b(all)i(the)f(represen)m(tations,)j(an)c(x)h(or)g(X)g(is)g (allo)m(w)m(ed)i(in)d(the)h(mask)g(as)g(a)h(wild)e(card.)38 b(Note)25 b(that)e(the)g(x)g(represen)m(ts)0 668 y(a)k(di\013eren)m(t)h (n)m(um)m(b)s(er)e(of)h(wild)f(card)h(bits)g(in)g(eac)m(h)h(represen)m (tation.)41 b(All)27 b(represen)m(tations)h(are)g(case)g(insensitiv)m (e.)0 781 y(Although)41 b(bitmasks)g(ma)m(y)g(b)s(e)f(of)h(arbitrary)f (length)h(and)f(con)m(tain)i(a)g(wildcard,)h(they)e(ma)m(y)g(only)g(b)s (e)f(used)0 894 y(in)c(logical)k(expressions,)e(unlik)m(e)f(in)m(teger) h(constan)m(ts)g(\(see)f(ab)s(o)m(v)m(e\))i(whic)m(h)d(ma)m(y)h(b)s(e)f (used)g(in)h(an)m(y)g(arithmetic)0 1007 y(expression.)0 1167 y(T)-8 b(o)28 b(construct)g(the)g(b)s(o)s(olean)f(expression)h (using)f(the)h(mask)f(as)h(the)g(b)s(o)s(olean)f(equal)h(op)s(erator)g (describ)s(ed)f(ab)s(o)m(v)m(e)0 1280 y(on)34 b(a)h(bit)g(table)h (column.)53 b(F)-8 b(or)35 b(example,)i(if)d(y)m(ou)h(had)f(a)h(7)g (bit)g(column)f(named)g(\015ags)h(in)f(a)h(FITS)f(table)i(and)0 1393 y(w)m(an)m(ted)31 b(all)g(ro)m(ws)g(ha)m(ving)g(the)f(bit)h (pattern)f(0010011,)k(the)c(selection)j(expression)d(w)m(ould)g(b)s(e:) 1336 1670 y Ff(flags)47 b(==)g(b0010011)191 1782 y(or)1336 1895 y(flags)g(.eq.)f(b10011)0 2172 y Fj(It)35 b(is)g(also)h(p)s (ossible)e(to)i(test)g(if)f(a)g(range)g(of)g(bits)g(is)g(less)g(than,)h (less)f(than)g(equal,)i(greater)f(than)e(and)h(greater)0 2285 y(than)30 b(equal)h(to)g(a)g(particular)g(b)s(o)s(olean)f(v)-5 b(alue:)1336 2562 y Ff(flags)47 b(<=)g(bxxx010xx)1336 2675 y(flags)g(.gt.)f(bxxx100xx)1336 2788 y(flags)h(.le.)f(b1xxxxxxx)0 3064 y Fj(Notice)32 b(the)f(use)f(of)h(the)f(x)g(bit)h(v)-5 b(alue)31 b(to)g(limit)g(the)f(range)h(of)g(bits)f(b)s(eing)g (compared.)0 3225 y(It)i(is)h(not)f(necessary)h(to)g(sp)s(ecify)f(the)h (leading)g(\(most)g(signi\014can)m(t\))h(zero)f(\(0\))g(bits)f(in)g (the)h(mask,)g(as)g(sho)m(wn)e(in)0 3338 y(the)g(second)f(expression)g (ab)s(o)m(v)m(e.)0 3498 y(Bit)44 b(wise)f(AND,)h(OR)e(and)g(NOT)h(op)s (erations)g(are)g(also)h(p)s(ossible)e(on)h(t)m(w)m(o)h(or)f(more)g (bit)g(\014elds)f(using)h(the)0 3611 y('&'\(AND\),)35 b(')p Fd(j)p Fj('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))34 b(op)s(erators.)51 b(All)34 b(of)f(these)h(op)s(erators)g(result)f(in)h (a)g(bit)f(\014eld)g(whic)m(h)0 3723 y(can)e(then)f(b)s(e)f(used)h (with)g(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 b(example:)1241 4000 y Ff(\(!flags\))45 b(==)j(b1101100)1241 4113 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)0 4390 y Fj(Bit)35 b(\014elds)f(can)g(b)s(e)f(app)s(ended)g(as)h(w)m(ell)h (using)f(the)g('+')g(op)s(erator.)53 b(Strings)33 b(can)i(b)s(e)e (concatenated)j(this)e(w)m(a)m(y)-8 b(,)0 4503 y(to)s(o.)0 4814 y Fc(8.11.3)113 b(V)-9 b(ector)36 b(Columns)0 5036 y Fj(V)-8 b(ector)37 b(columns)e(can)h(also)g(b)s(e)f(used)f(in)h (building)g(the)g(expression.)56 b(No)36 b(sp)s(ecial)g(syn)m(tax)f(is) h(required)e(if)i(one)0 5149 y(w)m(an)m(ts)46 b(to)f(op)s(erate)h(on)f (all)h(elemen)m(ts)g(of)f(the)h(v)m(ector.)86 b(Simply)44 b(use)h(the)g(column)g(name)g(as)g(for)g(a)g(scalar)0 5262 y(column.)d(V)-8 b(ector)32 b(columns)f(can)g(b)s(e)f(freely)h(in) m(termixed)h(with)e(scalar)i(columns)e(or)h(constan)m(ts)h(in)f (virtually)g(all)0 5375 y(expressions.)40 b(The)29 b(result)g(will)g(b) s(e)g(of)g(the)g(same)h(dimension)e(as)i(the)f(v)m(ector.)42 b(Tw)m(o)29 b(v)m(ectors)i(in)e(an)g(expression,)0 5488 y(though,)f(need)e(to)i(ha)m(v)m(e)g(the)f(same)g(n)m(um)m(b)s(er)f(of) h(elemen)m(ts)h(and)e(ha)m(v)m(e)j(the)e(same)g(dimensions.)39 b(The)26 b(only)h(places)0 5601 y(a)35 b(v)m(ector)h(column)e(cannot)h (b)s(e)f(used)f(\(for)i(no)m(w,)g(an)m(yw)m(a)m(y\))h(are)f(the)g(SA)m (O)f(region)h(functions)f(and)f(the)i(NEAR)0 5714 y(b)s(o)s(olean)30 b(function.)p eop end %%Page: 102 108 TeXDict begin 102 107 bop 0 299 a Fj(102)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(Arithmetic)24 b(and)e(logical)k(op)s(erations)d(are)h(all)g(p) s(erformed)d(on)i(an)g(elemen)m(t)h(b)m(y)f(elemen)m(t)i(basis.)38 b(Comparing)23 b(t)m(w)m(o)0 668 y(v)m(ector)32 b(columns,)e(eg)h ("COL1)f(==)g(COL2",)g(th)m(us)g(results)g(in)g(another)g(v)m(ector)i (of)e(b)s(o)s(olean)h(v)-5 b(alues)30 b(indicating)0 781 y(whic)m(h)g(elemen)m(ts)i(of)e(the)h(t)m(w)m(o)h(v)m(ectors)f(are) g(equal.)0 941 y(Sev)m(eral)e(functions)e(are)i(a)m(v)-5 b(ailable)30 b(that)e(op)s(erate)h(on)f(a)g(v)m(ector.)41 b(All)29 b(but)e(the)h(last)h(t)m(w)m(o)g(return)e(a)h(scalar)h (result:)191 1184 y Ff("minimum")284 b(MIN\(V\))475 b("maximum")714 b(MAX\(V\))191 1297 y("average")284 b(AVERAGE\(V\))f("median")762 b(MEDIAN\(V\))191 1410 y("summation")188 b(SUM\(V\))475 b("standard)46 b(deviation")188 b(STDDEV\(V\))191 1523 y("#)47 b(of)g(values")94 b(NELEM\(V\))379 b("#)48 b(of)f(non-null)e (values")94 b(NVALID\(V\))191 1635 y("#)47 b(axes")333 b(NAXIS\(V\))379 b("axis)47 b(dimension")379 b(NAXES\(V,n\))191 1748 y("axis)46 b(pos'n")142 b(AXISELEM\(V,n\))d("vector)46 b(element)g(pos'n")94 b(ELEMENTNUM\(V\))1670 1861 y("promote)46 b(to)h(array")285 b(ARRAY\(X,d\))0 2104 y Fj(where)40 b(V)h(represen)m(ts)g(the)g(name)g(of)h(a)f(v)m(ector)h(column)f(or)g (a)h(man)m(ually)f(constructed)g(v)m(ector)i(using)d(curly)0 2217 y(brac)m(k)m(ets)27 b(as)f(describ)s(ed)e(b)s(elo)m(w.)39 b(The)25 b(\014rst)g(6)h(of)g(these)g(functions)f(ignore)h(an)m(y)g(n)m (ull)f(v)-5 b(alues)26 b(in)f(the)h(v)m(ector)h(when)0 2330 y(computing)k(the)f(result.)41 b(The)30 b(STDDEV\(\))h(function)g (computes)f(the)h(sample)g(standard)e(deviation,)j(i.e.)42 b(it)31 b(is)0 2443 y(prop)s(ortional)f(to)h(1/SQR)-8 b(T\(N-1\))32 b(instead)f(of)g(1/SQR)-8 b(T\(N\),)31 b(where)f(N)h(is)f(NV)-10 b(ALID\(V\).)0 2603 y(The)25 b(NAXIS\(V\))i(function)e(returns)g(the)h(n)m(um)m(b)s(er)f(of)h(axes)g (of)g(the)g(v)m(ector,)j(for)c(example)i(a)f(2D)h(arra)m(y)f(w)m(ould)g (b)s(e)0 2716 y(NAXIS\(V\))34 b(==)f(2.)50 b(The)32 b(NAXES\(V,n\))i (function)f(returns)f(the)i(dimension)e(of)i(axis)g(n,)f(for)g(example) h(a)g(4x2)0 2829 y(arra)m(y)h(w)m(ould)f(ha)m(v)m(e)h(NAXES\(V,1\))h (==)d(4.)53 b(The)33 b(ELEMENTNUM\(V\))j(and)d(AXISELEM\(V,n\))h (functions)0 2942 y(return)42 b(v)m(ectors)j(of)f(the)g(same)g(size)g (as)g(the)f(input)g(v)m(ector)i(V.)f(ELEMENTNUM\(V\))g(returns)f(the)g (v)m(ector)0 3054 y(elemen)m(t)28 b(p)s(osition)e(for)g(eac)m(h)i (elemen)m(t)f(in)f(the)h(v)m(ector,)i(starting)e(from)e(1)i(in)f(eac)m (h)i(ro)m(w.)39 b(The)26 b(AXISELEM\(V,n\))0 3167 y(function)k(is)g (similar)h(but)f(returns)f(the)i(elemen)m(t)g(p)s(osition)g(of)f(axis)h (n)f(only)-8 b(.)0 3328 y(The)32 b(SUM)h(function)f(literally)j(sums)c (all)j(the)f(elemen)m(ts)h(in)f(x,)g(returning)f(a)h(scalar)h(v)-5 b(alue.)48 b(If)32 b(x)h(is)g(a)g(b)s(o)s(olean)0 3440 y(v)m(ector,)40 b(SUM)c(returns)f(the)h(n)m(um)m(b)s(er)f(of)i(TR)m(UE) f(elemen)m(ts.)60 b(The)36 b(NELEM)g(function)g(returns)f(the)h(n)m(um) m(b)s(er)0 3553 y(of)i(elemen)m(ts)h(in)f(v)m(ector)h(x)f(whereas)f(NV) -10 b(ALID)39 b(return)d(the)i(n)m(um)m(b)s(er)f(of)h(non-n)m(ull)f (elemen)m(ts)j(in)d(the)h(v)m(ector.)0 3666 y(\(NELEM)28 b(also)h(op)s(erates)f(on)g(bit)f(and)g(string)h(columns,)g(returning)f (their)h(column)f(widths.\))40 b(As)27 b(an)h(example,)0 3779 y(to)42 b(test)g(whether)f(all)h(elemen)m(ts)h(of)f(t)m(w)m(o)g(v) m(ectors)h(satisfy)f(a)g(giv)m(en)g(logical)i(comparison,)g(one)e(can)g (use)f(the)0 3892 y(expression)668 4135 y Ff(SUM\()47 b(COL1)f(>)i(COL2)f(\))g(==)g(NELEM\()f(COL1)h(\))0 4377 y Fj(whic)m(h)32 b(will)g(return)f(TR)m(UE)h(if)g(all)h(elemen)m(ts)g (of)f(COL1)g(are)g(greater)h(than)f(their)g(corresp)s(onding)f(elemen)m (ts)i(in)0 4490 y(COL2.)0 4650 y(The)g(ARRA)-8 b(Y\(X,d\))35 b(function)e(promotes)h(scalar)g(v)-5 b(alue)34 b(X)f(to)h(a)g(v)m (ector)h(\(or)f(arra)m(y\))g(table)h(elemen)m(t.)51 b(X)33 b(ma)m(y)0 4763 y(b)s(e)h(an)m(y)h(scalar-v)-5 b(alued)36 b(item,)g(including)f(a)g(column,)g(an)g(expression,)g(or)g(a)g (constan)m(t)h(v)-5 b(alue.)54 b(The)34 b(resulting)0 4876 y(v)m(ector)39 b(or)e(arra)m(y)h(will)g(ha)m(v)m(e)g(the)g(same)g (scalar)g(v)-5 b(alue)38 b(replicated)g(in)m(to)h(eac)m(h)f(elemen)m(t) h(p)s(osition.)62 b(This)36 b(ma)m(y)0 4989 y(b)s(e)e(a)i(useful)e(w)m (a)m(y)i(to)g(construct)g(large)g(arra)m(ys)f(without)g(using)g(the)g (cum)m(b)s(ersome)g Fd(f)p Fj(v)m(ector)p Fd(g)i Fj(notation.)56 b(The)0 5102 y(dimensions)26 b(of)h(the)h(new)e(arra)m(y)h(are)h(giv)m (en)g(b)m(y)f(the)g(second)g(argumen)m(t,)h(d.)39 b(d)27 b(can)g(either)g(b)s(e)g(a)g(single)h(constan)m(t)0 5215 y(in)m(teger)g(v)-5 b(alue,)28 b(or)f(a)f(v)m(ector)j(of)d(up)g(to)h (\014v)m(e)g(dimensions)f(of)g(the)h(form)f Fd(f)p Fj(Nx,Ny)-8 b(,...)p Fd(g)p Fj(.)43 b(Th)m(us,)26 b(ARRA)-8 b(Y\(TIME,4\))0 5328 y(w)m(ould)28 b(promote)g(TIME)g(to)h(b)s(e)e(a)i(4-v)m(ector,)i (and)d(ARRA)-8 b(Y\(0,)30 b Fd(f)p Fj(2,3,1)p Fd(g)p Fj(\))h(w)m(ould)d(construct)h(an)f(arra)m(y)g(of)g(all)h(0's)0 5441 y(with)h(dimensions)g(2)20 b Fd(\002)g Fj(3)h Fd(\002)f Fj(1.)0 5601 y(A)36 b(second)g(form)f(of)h(ARRA)-8 b(Y\(X,d\))37 b(can)f(b)s(e)f(used)g(where)g(X)h(is)g(a)g(v)m(ector)h(or)f(arra)m(y) -8 b(,)38 b(and)e(the)f(dimensions)g(d)0 5714 y(merely)c(c)m(hange)h (the)e(dimensions)g(of)h(X)f(without)h(c)m(hanging)g(the)g(total)i(n)m (um)m(b)s(er)c(of)h(v)m(ector)j(elemen)m(ts.)42 b(This)30 b(is)p eop end %%Page: 103 109 TeXDict begin 103 108 bop 0 299 a Fh(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fj(103)0 555 y(a)30 b(w)m(a)m(y)g(to)g(re-dimension)f(an)h(existing)g(arra)m(y) -8 b(.)41 b(F)-8 b(or)31 b(example,)f(ARRA)-8 b(Y\()p Fd(f)p Fj(1,2,3,4)p Fd(g)p Fj(,2,2\))36 b(w)m(ould)29 b(transform)g(the)0 668 y(4-v)m(ector)k(in)m(to)e(a)g(2)20 b Fd(\002)g Fj(2)31 b(arra)m(y)-8 b(.)0 828 y(T)g(o)32 b(sp)s(ecify)f(a)i(single)f(elemen)m(t)h(of)f(a)g(v)m(ector,)i(giv)m(e) f(the)f(column)f(name)h(follo)m(w)m(ed)h(b)m(y)f(a)g(comma-separated)h (list)0 941 y(of)c(co)s(ordinates)g(enclosed)h(in)e(square)h(brac)m(k)m (ets.)41 b(F)-8 b(or)30 b(example,)g(if)e(a)h(v)m(ector)i(column)d (named)h(PHAS)f(exists)h(in)0 1054 y(the)e(table)g(as)g(a)g(one)g (dimensional,)h(256)g(comp)s(onen)m(t)f(list)g(of)g(n)m(um)m(b)s(ers)e (from)h(whic)m(h)h(y)m(ou)g(w)m(an)m(ted)g(to)g(select)i(the)0 1167 y(57th)j(comp)s(onen)m(t)g(for)f(use)g(in)g(the)h(expression,)f (then)h(PHAS[57])g(w)m(ould)f(do)h(the)f(tric)m(k.)45 b(Higher)32 b(dimensional)0 1280 y(arra)m(ys)41 b(of)h(data)f(ma)m(y)h (app)s(ear)f(in)f(a)i(column.)73 b(But)41 b(in)g(order)f(to)i(in)m (terpret)f(them,)j(the)e(TDIMn)e(k)m(eyw)m(ord)0 1393 y(m)m(ust)34 b(app)s(ear)g(in)g(the)g(header.)52 b(Assuming)34 b(that)h(a)f(\(4,4,4,4\))k(arra)m(y)c(is)h(pac)m(k)m(ed)g(in)m(to)g (eac)m(h)h(ro)m(w)e(of)g(a)h(column)0 1506 y(named)26 b(ARRA)-8 b(Y4D,)28 b(the)f(\(1,2,3,4\))i(comp)s(onen)m(t)e(elemen)m(t) g(of)g(eac)m(h)g(ro)m(w)g(is)f(accessed)i(b)m(y)e(ARRA)-8 b(Y4D[1,2,3,4].)0 1619 y(Arra)m(ys)33 b(up)e(to)j(dimension)e(5)h(are)f (curren)m(tly)h(supp)s(orted.)46 b(Eac)m(h)33 b(v)m(ector)h(index)e (can)h(itself)g(b)s(e)f(an)h(expression,)0 1732 y(although)39 b(it)g(m)m(ust)g(ev)-5 b(aluate)40 b(to)f(an)g(in)m(teger)h(v)-5 b(alue)39 b(within)f(the)h(b)s(ounds)d(of)j(the)g(v)m(ector.)67 b(V)-8 b(ector)40 b(columns)0 1844 y(whic)m(h)31 b(con)m(tain)h(spaces) g(or)f(arithmetic)h(op)s(erators)g(m)m(ust)f(ha)m(v)m(e)h(their)f (names)g(enclosed)h(in)f("$")h(c)m(haracters)h(as)0 1957 y(with)d($ARRA)-8 b(Y-4D$[1,2,3,4].)0 2118 y(A)45 b(more)f(C-lik)m(e)i (syn)m(tax)g(for)e(sp)s(ecifying)g(v)m(ector)j(indices)d(is)h(also)h(a) m(v)-5 b(ailable.)85 b(The)45 b(elemen)m(t)h(used)d(in)i(the)0 2230 y(preceding)28 b(example)h(alternativ)m(ely)i(could)d(b)s(e)g(sp)s (eci\014ed)g(with)f(the)i(syn)m(tax)g(ARRA)-8 b(Y4D[4][3][2][1].)45 b(Note)30 b(the)0 2343 y(rev)m(erse)40 b(order)f(of)h(indices)f(\(as)h (in)f(C\),)h(as)f(w)m(ell)i(as)e(the)h(fact)g(that)g(the)g(v)-5 b(alues)40 b(are)f(still)i(ones-based)e(\(as)h(in)0 2456 y(F)-8 b(ortran)39 b({)g(adopted)g(to)g(a)m(v)m(oid)h(am)m(biguit)m(y)g (for)f(1D)g(v)m(ectors\).)67 b(With)39 b(this)g(syn)m(tax,)i(one)e(do)s (es)f(not)h(need)f(to)0 2569 y(sp)s(ecify)30 b(all)h(of)g(the)f (indices.)41 b(T)-8 b(o)31 b(extract)h(a)f(3D)g(slice)g(of)g(this)f(4D) h(arra)m(y)-8 b(,)32 b(use)e(ARRA)-8 b(Y4D[4].)0 2729 y(V)g(ariable-length)33 b(v)m(ector)f(columns)e(are)g(not)h(supp)s (orted.)0 2889 y(V)-8 b(ectors)24 b(can)e(b)s(e)f(man)m(ually)h (constructed)h(within)e(the)h(expression)g(using)f(a)h(comma-separated) i(list)f(of)f(elemen)m(ts)0 3002 y(surrounded)35 b(b)m(y)j(curly)g (braces)h(\(')p Fd(fg)p Fj('\).)66 b(F)-8 b(or)38 b(example,)j(')p Fd(f)p Fj(1,3,6,1)p Fd(g)p Fj(')h(is)d(a)f(4-elemen)m(t)i(v)m(ector)g (con)m(taining)g(the)0 3115 y(v)-5 b(alues)26 b(1,)h(3,)g(6,)g(and)e (1.)40 b(The)25 b(v)m(ector)i(can)f(con)m(tain)h(only)f(b)s(o)s(olean,) g(in)m(teger,)j(and)c(real)h(v)-5 b(alues)26 b(\(or)g(expressions\).)0 3228 y(The)e(elemen)m(ts)h(will)g(b)s(e)f(promoted)g(to)h(the)g (highest)f(datat)m(yp)s(e)h(presen)m(t.)39 b(An)m(y)24 b(elemen)m(ts)i(whic)m(h)e(are)h(themselv)m(es)0 3341 y(v)m(ectors,)40 b(will)d(b)s(e)f(expanded)g(out)h(with)g(eac)m(h)g(of) g(its)g(elemen)m(ts)i(b)s(ecoming)d(an)h(elemen)m(t)h(in)f(the)g (constructed)0 3454 y(v)m(ector.)0 3740 y Fc(8.11.4)113 b(Go)s(o)s(d)38 b(Time)g(In)m(terv)-6 b(al)37 b(Filtering)h(and)g (Calculation)0 3959 y Fj(There)27 b(are)h(t)m(w)m(o)g(functions)f(for)g (\014ltering)h(and)f(calculating)i(based)e(on)g(Go)s(o)s(d)h(Time)f(In) m(terv)-5 b(als,)29 b(or)e(GTIs.)39 b(GTIs)0 4072 y(are)c(commonly)g (used)f(to)h(express)f(fragmen)m(ted)h(time)g(ranges)g(that)g(are)g (not)g(easy)g(to)g(express)f(with)g(a)h(single)0 4185 y(start)j(and)f(stop)h(time.)63 b(The)37 b(time)h(in)m(terv)-5 b(als)39 b(are)f(de\014ned)e(in)i(a)g(FITS)f(table)h(extension)g(whic)m (h)g(con)m(tains)h(2)0 4298 y(columns)30 b(giving)h(the)g(start)g(and)f (stop)g(time)h(of)g(eac)m(h)g(go)s(o)s(d)f(in)m(terv)-5 b(al.)0 4458 y(A)32 b(common)g(\014ltering)f(metho)s(d)h(in)m(v)m(olv)m (es)h(selecting)h(ro)m(ws)d(whic)m(h)h(ha)m(v)m(e)g(a)g(time)h(v)-5 b(alue)32 b(whic)m(h)f(lies)i(within)e(an)m(y)0 4571 y(GTI.)36 b(The)g(gti\014lter\(\))i(\014ltering)e(op)s(eration)h (accepts)g(only)f(those)h(ro)m(ws)f(of)g(the)h(input)e(table)i(whic)m (h)f(ha)m(v)m(e)h(an)0 4684 y(asso)s(ciated)g(time)f(whic)m(h)g(falls)g (within)f(one)g(of)h(the)g(time)g(in)m(terv)-5 b(als)37 b(de\014ned)d(in)h(a)h(separate)h(GTI)e(extension.)0 4797 y(gti\014lter\(a,b,c,d\))43 b(ev)-5 b(aluates)41 b(eac)m(h)g(ro)m(w)g(of)f(the)g(input)f(table)i(and)f(returns)f(TR)m (UE)h(or)g(F)-10 b(ALSE)39 b(dep)s(ending)0 4910 y(whether)30 b(the)g(ro)m(w)h(is)f(inside)g(or)h(outside)f(the)h(go)s(o)s(d)f(time)h (in)m(terv)-5 b(al.)42 b(The)30 b(syn)m(tax)h(is)286 5142 y Ff(gtifilter\()45 b([)j("gtifile")d([,)i(expr)g([,)g ("STARTCOL",)e("STOPCOL")g(])j(])f(])g(\))191 5255 y(or)286 5368 y(gtifilter\()e([)j('gtifile')d([,)i(expr)g([,)g('STARTCOL',)e ('STOPCOL')g(])j(])f(])g(\))0 5601 y Fj(where)20 b(eac)m(h)h("[]")h (demarks)e(optional)h(parameters.)38 b(Note)21 b(that)g(the)g(quotes)f (around)g(the)g(gti\014le)i(and)d(ST)-8 b(AR)g(T/STOP)0 5714 y(column)33 b(are)h(required.)50 b(Either)34 b(single)g(or)g (double)f(quotes)h(ma)m(y)g(b)s(e)f(used.)50 b(In)33 b(cases)h(where)g(this)f(expression)p eop end %%Page: 104 110 TeXDict begin 104 109 bop 0 299 a Fj(104)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(is)30 b(en)m(tered)g(on)g(the)g(Unix)g(command)g(line,)g (enclose)h(the)f(en)m(tire)h(expression)f(in)f(double)h(quotes,)g(and)g (then)f(use)0 668 y(single)c(quotes)g(within)e(the)i(expression)f(to)h (enclose)g(the)g('gti\014le')h(and)d(other)i(terms.)38 b(It)25 b(is)f(also)h(usually)f(p)s(ossible)0 781 y(to)38 b(do)e(the)h(rev)m(erse,)j(and)c(enclose)i(the)f(whole)g(expression)g (in)f(single)i(quotes)f(and)f(then)h(use)f(double)g(quotes)0 894 y(within)d(the)g(expression.)50 b(The)33 b(gti\014le,)i(if)f(sp)s (eci\014ed,)f(can)h(b)s(e)f(blank)g(\(""\))i(whic)m(h)e(will)g(mean)h (to)g(use)f(the)h(\014rst)0 1007 y(extension)g(with)g(the)f(name)h ("*GTI*")h(in)f(the)f(curren)m(t)h(\014le,)h(a)f(plain)f(extension)h (sp)s(eci\014er)f(\(eg,)j("+2",)g("[2]",)0 1120 y(or)30 b("[STDGTI]"\))i(whic)m(h)e(will)h(b)s(e)f(used)f(to)j(select)g(an)e (extension)h(in)f(the)h(curren)m(t)f(\014le,)h(or)f(a)h(regular)g (\014lename)0 1233 y(with)f(or)h(without)f(an)h(extension)g(sp)s (eci\014er)f(whic)m(h)g(in)g(the)h(latter)h(case)f(will)g(mean)f(to)i (use)e(the)h(\014rst)e(extension)0 1346 y(with)37 b(an)g(extension)g (name)h("*GTI*".)62 b(Expr)36 b(can)h(b)s(e)g(an)m(y)g(arithmetic)i (expression,)f(including)f(simply)g(the)0 1458 y(time)f(column)g(name.) 57 b(A)36 b(v)m(ector)h(time)g(expression)e(will)h(pro)s(duce)f(a)h(v)m (ector)h(b)s(o)s(olean)f(result.)57 b(ST)-8 b(AR)g(TCOL)0 1571 y(and)27 b(STOPCOL)f(are)i(the)g(names)g(of)g(the)g(ST)-8 b(AR)g(T/STOP)26 b(columns)i(in)f(the)h(GTI)g(extension.)41 b(If)27 b(one)h(of)g(them)0 1684 y(is)i(sp)s(eci\014ed,)g(they)h(b)s (oth)f(m)m(ust)g(b)s(e.)0 1844 y(In)21 b(its)h(simplest)g(form,)i(no)d (parameters)h(need)g(to)h(b)s(e)e(pro)m(vided)g({)h(default)g(v)-5 b(alues)22 b(will)h(b)s(e)e(used.)37 b(The)21 b(expression)0 1957 y("gti\014lter\(\)")33 b(is)e(equiv)-5 b(alen)m(t)31 b(to)334 2216 y Ff(gtifilter\()45 b("",)i(TIME,)f("*START*",)f ("*STOP*")h(\))0 2474 y Fj(This)31 b(will)g(searc)m(h)h(the)g(curren)m (t)f(\014le)g(for)g(a)h(GTI)f(extension,)h(\014lter)g(the)f(TIME)g (column)g(in)g(the)h(curren)m(t)f(table,)0 2587 y(using)j(ST)-8 b(AR)g(T/STOP)34 b(times)i(tak)m(en)f(from)g(columns)f(in)h(the)g(GTI)g (extension)g(with)g(names)f(con)m(taining)j(the)0 2700 y(strings)32 b("ST)-8 b(AR)g(T")33 b(and)e("STOP".)46 b(The)32 b(wildcards)f(\('*'\))j(allo)m(w)g(sligh)m(t)f(v)-5 b(ariations)33 b(in)f(naming)g(con)m(v)m(en)m(tions)0 2812 y(suc)m(h)38 b(as)g("TST)-8 b(AR)g(T")39 b(or)f("ST)-8 b(AR)g(TTIME".)65 b(The)37 b(same)i(default)g(v)-5 b(alues)38 b(apply)g(for)g(unsp)s(eci\014ed)f(parame-)0 2925 y(ters)f(when)f(the)h (\014rst)f(one)i(or)f(t)m(w)m(o)h(parameters)f(are)h(sp)s(eci\014ed.)56 b(The)36 b(function)f(automatically)k(searc)m(hes)e(for)0 3038 y(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)f(in)g(the)h(curren)m(t)f(and)g (GTI)g(extensions,)i(applying)f(a)f(relativ)m(e)j(time)e(o\013set,)i (if)0 3151 y(necessary)-8 b(.)0 3311 y(The)38 b(related)h(function,)g (gti\014nd\(a,b,c,d\),)i(is)e(similar)f(to)h(gti\014lter\(\))h(but)d (instead)h(of)h(returning)e(true/false,)0 3424 y(gti\014nd\(\))f (returns)e(the)i(GTI)f(n)m(um)m(b)s(er)f(that)i(brac)m(k)m(ets)h(the)f (requested)f(time)h(sample.)57 b(gti\014nd\(\))35 b(returns)g(the)0 3537 y(ro)m(w)30 b(n)m(um)m(b)s(er)e(in)i(the)g(GTI)g(table)g(that)h (matc)m(hes)g(the)f(time)g(sample,)h(or)f(-1)g(if)g(the)g(time)h (sample)f(is)f(not)h(within)0 3650 y(an)m(y)g(GTI.)f(gti\014nd\(\))g (is)g(particularly)h(useful)f(when)f(en)m(tries)i(in)f(a)g(table)i(m)m (ust)e(b)s(e)f(categorized)k(b)m(y)d(whic)m(h)g(GTI)0 3763 y(the)36 b(fall)h(within.)56 b(F)-8 b(or)37 b(example,)h(if)e(ev)m (en)m(ts)h(in)f(an)f(ev)m(en)m(t)j(list)e(m)m(ust)g(b)s(e)f(separated)i (b)m(y)e(go)s(o)s(d)h(time)h(in)m(terv)-5 b(al.)0 3876 y(The)25 b(results)g(of)h(gti\014nd\(\))g(can)f(b)s(e)g(used)g(with)g (histogram)h(binning)e(tec)m(hniques)i(to)h(bin)d(an)i(ev)m(en)m(t)h (list)f(b)m(y)f(whic)m(h)0 3989 y(GTI.)286 4247 y Ff(gtifind\()46 b("gtifile")f(,)j(expr)e([,)h("STARTCOL",)e("STOPCOL")g(])j(\))0 4505 y Fj(The)33 b(requiremen)m(ts)g(for)f(sp)s(ecifying)h(the)h (gti\014le)g(are)f(the)g(same)h(as)f(for)g(gti\014lter\(\))i(as)e (describ)s(ed)f(ab)s(o)m(v)m(e.)50 b(Lik)m(e)0 4618 y(gti\014lter\(\),) 31 b(the)e(expr)g(is)g(the)g(time-lik)m(e)i(expression)e(and)f(is)h (optional)h(\(defaulting)g(to)f(TIME\).)h(The)e(start)i(and)0 4731 y(stop)g(columns)h(default)f(to)h(ST)-8 b(AR)g(T)30 b(and)g(STOP)-8 b(.)0 4891 y(The)28 b(function,)h(gtio)m(v)m (erlap\(a,b,c,d,e\),)34 b(computes)28 b(the)h(o)m(v)m(erlap)h(b)s(et)m (w)m(een)f(a)g(user-requested)f(time)i(range)f(and)0 5004 y(the)i(en)m(tries)g(in)f(a)h(GTI.)f(The)g(cases)i(of)e(no)g(o)m (v)m(erlap,)j(partial)e(o)m(v)m(erlap,)h(or)f(o)m(v)m(erlap)h(of)e(man) m(y)h(GTIs)f(within)g(the)0 5117 y(user)37 b(requested)h(range)g(are)g (handled.)61 b(gtio)m(v)m(erlap\(\))41 b(is)d(v)m(ery)g(useful)f(for)h (calculating)h(exp)s(osure)e(times)i(and)0 5230 y(fractional)32 b(exp)s(osures)d(of)i(individual)f(time)h(bins,)e(sa)m(y)i(for)f(a)h (ligh)m(t)h(curv)m(e.)41 b(The)30 b(syn)m(tax)h(of)f(gtio)m(v)m (erlap\(\))k(is)286 5488 y Ff(gtioverlap\()45 b("gtifile")g(,)j (startExpr,)d(stopExpr)g([,)j("STARTCOL",)c("STOPCOL")i(])h(\))191 5601 y(or)286 5714 y(gtioverlap\()e('gtifile')g(,)j(startExpr,)d (stopExpr)g([,)j('STARTCOL',)c('STOPCOL')i(])h(\))p eop end %%Page: 105 111 TeXDict begin 105 110 bop 0 299 a Fh(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fj(105)0 555 y(The)27 b(requiremen)m(ts)g(for)h(sp)s(ecifying)f(the)h(gti\014le) g(are)g(the)g(same)g(as)f(for)h(gti\014lter\(\))h(as)f(describ)s(ed)e (ab)s(o)m(v)m(e.)41 b(Unlik)m(e)0 668 y(gti\014lter\(\),)j(the)c (startExpr)f(and)f(stopExpr)h(are)h(not)g(optional.)69 b(startExpr)39 b(pro)m(vides)g(a)h(start)g(of)g(the)g(user)0 781 y(requested)34 b(time)h(in)m(terv)-5 b(al.)53 b(startExpr)34 b(is)g(t)m(ypically)i(TIME,)e(but)f(can)i(b)s(e)e(an)m(y)h(v)-5 b(alid)35 b(expression.)52 b(Lik)m(ewise,)0 894 y(stopExpr)39 b(pro)m(vides)i(the)f(stop)h(of)f(the)h(user)f(requested)g(time)h(in)m (terv)-5 b(al,)44 b(and)c(can)h(b)s(e)e(an)i(expression.)70 b(F)-8 b(or)0 1007 y(example,)31 b(for)f(a)h(ligh)m(t)h(curv)m(e)e (with)h(a)f(TIME)g(column)g(and)g(time)h(bin)f(size)h(of)g(1.0)g (seconds,)g(the)f(expression)286 1275 y Ff(gtioverlap\('gtifile',TIME,) o(TIM)o(E+1.)o(0\))0 1543 y Fj(w)m(ould)36 b(calculate)i(the)e(amoun)m (t)g(of)g(o)m(v)m(erlap)h(exp)s(osure)e(time)h(b)s(et)m(w)m(een)h(eac)m (h)f(one)g(second)g(time)h(bin)e(and)g(the)0 1656 y(GTI)e(in)f ('gti\014le'.)50 b(In)32 b(this)h(case)h(the)f(time)g(bin)f(is)h (assumed)f(to)i(b)s(egin)e(at)i(the)f(time)g(sp)s(eci\014ed)f(b)m(y)h (TIME)g(and)0 1768 y(end)d(1)h(second)g(later.)43 b(Neither)31 b(startExpr)f(nor)h(stopExpr)e(are)j(required)d(to)j(b)s(e)e(constan)m (t,)i(and)f(a)g(ligh)m(t)h(curv)m(e)0 1881 y(is)h(not)h(required)f(to)h (ha)m(v)m(e)g(a)g(constan)m(t)h(bin)e(size.)50 b(F)-8 b(or)34 b(tables,)i(the)d(o)m(v)m(erlap)i(is)f(calculated)h(for)e(eac)m (h)i(en)m(try)e(in)0 1994 y(the)e(table.)0 2154 y(It)d(is)f(also)i(p)s (ossible)e(to)h(calculate)i(a)e(single)g(o)m(v)m(erlap)h(v)-5 b(alue,)29 b(whic)m(h)e(w)m(ould)h(t)m(ypically)h(b)s(e)e(placed)h(in)f (a)h(k)m(eyw)m(ord.)0 2267 y(F)-8 b(or)42 b(example,)j(a)d(w)m(a)m(y)g (to)g(to)g(compute)g(the)f(total)i(o)m(v)m(erlap)g(exp)s(osure)d(of)i (a)f(\014le)h(whose)f(TIME)g(column)g(is)0 2380 y(b)s(ounded)28 b(b)m(y)i(the)h(k)m(eyw)m(ords)g(TST)-8 b(AR)g(T)29 b(and)h(TSTOP)-8 b(,)30 b(o)m(v)m(erlapping)h(with)f(the)h(sp)s(eci\014ed)f(GTI,)g(w)m (ould)g(b)s(e)286 2648 y Ff(#EXPOSURE)46 b(=)h (gtioverlap\('gtifile',#TST)o(ART)o(,#TS)o(TOP\))0 2916 y Fj(The)26 b Ff(#EXPOSURE)f Fj(syn)m(tax)i(with)g(a)g(leading)h(+)e (ensures)g(that)i(the)f(requested)g(v)-5 b(alues)27 b(are)g(treated)h (as)f(k)m(eyw)m(ords.)0 3029 y(Otherwise,)41 b(a)e(column)g(named)f (EXPOSURE)g(will)h(b)s(e)g(created)g(with)g(the)g(\(constan)m(t\))i (exp)s(osure)d(v)-5 b(alue)39 b(in)0 3142 y(eac)m(h)32 b(en)m(try)-8 b(.)0 3442 y Fc(8.11.5)113 b(Spatial)38 b(Region)g(Filtering)0 3663 y Fj(Another)g(common)g(\014ltering)g (metho)s(d)f(selects)i(ro)m(ws)f(based)g(on)f(whether)h(the)g(spatial)h (p)s(osition)e(asso)s(ciated)0 3776 y(with)32 b(eac)m(h)i(ro)m(w)e(is)h (lo)s(cated)h(within)e(a)h(giv)m(en)g(2-dimensional)g(region.)48 b(The)32 b(syn)m(tax)h(for)f(this)h(high-lev)m(el)h(\014lter)0 3889 y(is)334 4157 y Ff(regfilter\()45 b("regfilename")f([)k(,)f (Xexpr,)f(Yexpr)h([)g(,)h("wcs)e(cols")h(])g(])g(\))0 4425 y Fj(where)22 b(eac)m(h)i("[]")g(demarks)e(optional)i(parameters.) 38 b(The)22 b(region)h(\014le)g(name)f(is)h(required)f(and)g(m)m(ust)g (b)s(e)g(enclosed)0 4538 y(in)34 b(quotes.)51 b(The)33 b(remaining)h(parameters)h(are)f(optional.)52 b(There)33 b(are)i(2)f(supp)s(orted)e(formats)i(for)f(the)h(region)0 4650 y(\014le:)62 b(ASCI)s(I)39 b(\014le)h(or)h(FITS)f(binary)g(table.) 73 b(The)40 b(region)h(\014le)g(con)m(tains)h(a)f(list)g(of)g(one)g(or) g(more)g(geometric)0 4763 y(shap)s(es)30 b(\(circle,)j(ellipse,)g(b)s (o)m(x,)e(etc.\))44 b(whic)m(h)31 b(de\014nes)f(a)i(region)g(on)f(the)g (celestial)j(sphere)c(or)h(an)g(area)h(within)f(a)0 4876 y(particular)36 b(2D)g(image.)57 b(The)35 b(region)h(\014le)f(is)g(t)m (ypically)j(generated)e(using)f(an)g(image)i(displa)m(y)e(program)g (suc)m(h)0 4989 y(as)e(fv/PO)m(W)g(\(distribute)f(b)m(y)h(the)f(HEASAR) m(C\),)h(or)g(ds9)f(\(distributed)g(b)m(y)g(the)h(Smithsonian)f (Astroph)m(ysical)0 5102 y(Observ)-5 b(atory\).)69 b(Users)39 b(should)g(refer)g(to)h(the)g(do)s(cumen)m(tation)h(pro)m(vided)e(with) g(these)h(programs)f(for)h(more)0 5215 y(details)29 b(on)f(the)g(syn)m (tax)h(used)e(in)h(the)h(region)f(\014les.)40 b(The)28 b(FITS)f(region)i(\014le)f(format)h(is)f(de\014ned)f(in)h(a)g(do)s (cumen)m(t)0 5328 y(a)m(v)-5 b(ailable)33 b(from)d(the)g(FITS)g(Supp)s (ort)e(O\016ce)j(at)g(h)m(ttp://\014ts.gsfc.nasa.go)m(v/)k(registry/)c (region.h)m(tml)0 5488 y(In)21 b(its)h(simplest)g(form,)i(\(e.g.,)h (reg\014lter\("region.reg"\))h(\))c(the)g(co)s(ordinates)g(in)g(the)g (default)g('X')h(and)e('Y')h(columns)0 5601 y(will)43 b(b)s(e)g(used)f(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g (or)g(outside)g(the)g(area)h(sp)s(eci\014ed)e(in)h(the)g(region)h (\014le.)0 5714 y(Alternate)32 b(p)s(osition)e(column)g(names,)h(or)f (expressions,)h(ma)m(y)g(b)s(e)e(en)m(tered)i(if)g(needed,)f(as)h(in)p eop end %%Page: 106 112 TeXDict begin 106 111 bop 0 299 a Fj(106)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)382 555 y Ff(regfilter\("region.reg",)41 b(XPOS,)47 b(YPOS\))0 791 y Fj(Region)37 b(\014ltering)f(can)g(b)s(e)f(applied)g(most)h(unam) m(biguously)f(if)h(the)g(p)s(ositions)g(in)f(the)h(region)g(\014le)g (and)f(in)h(the)0 904 y(table)g(to)g(b)s(e)e(\014ltered)h(are)h(b)s (oth)e(giv)m(e)j(in)e(terms)g(of)g(absolute)h(celestial)i(co)s (ordinate)e(units.)54 b(In)35 b(this)g(case)h(the)0 1017 y(lo)s(cations)26 b(and)d(sizes)i(of)g(the)f(geometric)i(shap)s(es)e (in)g(the)g(region)h(\014le)f(are)h(sp)s(eci\014ed)f(in)g(angular)g (units)g(on)g(the)g(sky)0 1130 y(\(e.g.,)32 b(p)s(ositions)e(giv)m(en)i (in)e(R.A.)g(and)g(Dec.)42 b(and)30 b(sizes)h(in)f(arcseconds)g(or)h (arcmin)m(utes\).)41 b(Similarly)-8 b(,)31 b(eac)m(h)h(ro)m(w)0 1242 y(of)h(the)h(\014ltered)f(table)h(will)f(ha)m(v)m(e)i(a)e (celestial)j(co)s(ordinate)e(asso)s(ciated)g(with)f(it.)50 b(This)32 b(asso)s(ciation)j(is)e(usually)0 1355 y(implemen)m(ted)39 b(using)e(a)i(set)g(of)f(so-called)i('W)-8 b(orld)39 b(Co)s(ordinate)g(System')f(\(or)h(W)m(CS\))f(FITS)g(k)m(eyw)m(ords)g (that)0 1468 y(de\014ne)27 b(the)g(co)s(ordinate)h(transformation)g (that)g(m)m(ust)f(b)s(e)f(applied)h(to)h(the)g(v)-5 b(alues)27 b(in)g(the)h('X')g(and)e('Y')i(columns)0 1581 y(to)j(calculate)i(the)d (co)s(ordinate.)0 1741 y(Alternativ)m(ely)-8 b(,)30 b(one)d(can)g(p)s (erform)e(spatial)j(\014ltering)e(using)g(unitless)h('pixel')g(co)s (ordinates)h(for)e(the)h(regions)g(and)0 1854 y(ro)m(w)33 b(p)s(ositions.)49 b(In)33 b(this)g(case)h(the)f(user)g(m)m(ust)g(b)s (e)f(careful)h(to)h(ensure)f(that)g(the)h(p)s(ositions)f(in)g(the)g(2)g (\014les)h(are)0 1967 y(self-consisten)m(t.)54 b(A)34 b(t)m(ypical)i(problem)d(is)h(that)h(the)f(region)h(\014le)f(ma)m(y)h (b)s(e)e(generated)j(using)d(a)i(binned)d(image,)0 2080 y(but)g(the)h(un)m(binned)e(co)s(ordinates)i(are)g(giv)m(en)h(in)e(the) h(ev)m(en)m(t)i(table.)48 b(The)32 b(R)m(OSA)-8 b(T)33 b(ev)m(en)m(ts)h(\014les,)g(for)e(example,)0 2193 y(ha)m(v)m(e)f(X)f (and)f(Y)g(pixel)h(co)s(ordinates)g(that)h(range)f(from)f(1)h(-)g (15360.)42 b(These)30 b(co)s(ordinates)g(are)g(t)m(ypically)h(binned)0 2306 y(b)m(y)i(a)h(factor)g(of)f(32)h(to)g(pro)s(duce)e(a)i(480x480)i (pixel)d(image.)51 b(If)32 b(one)i(then)f(uses)g(a)g(region)h(\014le)f (generated)h(from)0 2419 y(this)c(image)i(\(in)f(image)g(pixel)g (units\))g(to)g(\014lter)f(the)h(R)m(OSA)-8 b(T)30 b(ev)m(en)m(ts)i (\014le,)f(then)f(the)h(X)g(and)f(Y)g(column)h(v)-5 b(alues)0 2532 y(m)m(ust)30 b(b)s(e)g(con)m(v)m(erted)i(to)f(corresp)s(onding)e (pixel)i(units)f(as)g(in:)382 2767 y Ff(regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))0 3003 y Fj(Note)h(that)f(this)f(binning)f (con)m(v)m(ersion)j(is)e(not)h(necessary)g(if)f(the)h(region)g(\014le)f (is)h(sp)s(eci\014ed)e(using)h(celestial)0 3116 y(co)s(ordinate)h (units)f(instead)g(of)g(pixel)h(units)f(b)s(ecause)g(CFITSIO)e(is)j (then)e(able)i(to)g(directly)g(compare)g(the)0 3229 y(celestial)30 b(co)s(ordinate)f(of)e(eac)m(h)i(ro)m(w)f(in)f(the)h(table)g(with)g (the)f(celestial)k(co)s(ordinates)d(in)f(the)h(region)g(\014le)g (without)0 3342 y(ha)m(ving)j(to)g(kno)m(w)f(an)m(ything)h(ab)s(out)f (ho)m(w)h(the)f(image)i(ma)m(y)f(ha)m(v)m(e)g(b)s(een)f(binned.)0 3502 y(The)f(last)h("w)m(cs)g(cols")h(parameter)f(should)e(rarely)h(b)s (e)g(needed.)40 b(If)29 b(supplied,)f(this)i(string)f(con)m(tains)i (the)e(names)0 3615 y(of)37 b(the)g(2)h(columns)f(\(space)h(or)f(comma) g(separated\))h(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)f (k)m(eyw)m(ords.)61 b(If)37 b(not)0 3728 y(supplied,)f(the)g(\014lter)g (will)h(scan)f(the)g(X)g(and)f(Y)h(expressions)g(for)g(column)f(names.) 58 b(If)35 b(only)h(one)h(is)f(found)e(in)0 3841 y(eac)m(h)e (expression,)e(those)h(columns)f(will)h(b)s(e)e(used,)h(otherwise)h(an) f(error)g(will)h(b)s(e)f(returned.)0 4001 y(These)g(region)h(shap)s(es) f(are)g(supp)s(orted)f(\(names)h(are)h(case)h(insensitiv)m(e\):)334 4236 y Ff(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)334 4349 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region) 334 4462 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 b(Rest)e(are)h(interiors)e(with)334 4575 y(Rectangle)236 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e (considered)334 4688 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) i(\))143 b(V)47 b(within)f(the)h(region)334 4801 y(Diamond)332 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))334 4914 y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))334 5027 y(Annulus)332 b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))334 5140 y(Ellipse)332 b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))334 5252 y(Elliptannulus)c(\() k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))334 5365 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))0 5601 y Fj(where)28 b(\(Xc,Yc\))j(is)d(the)h(co)s(ordinate)h(of)e(the)h (shap)s(e's)f(cen)m(ter;)j(\(X#,Y#\))e(are)g(the)g(co)s(ordinates)g(of) g(the)g(shap)s(e's)0 5714 y(edges;)36 b(Rxxx)d(are)h(the)f(shap)s(es')g (v)-5 b(arious)34 b(Radii)f(or)h(semi-ma)5 b(jor/minor)34 b(axes;)i(and)d(Axxx)g(are)h(the)f(angles)i(of)p eop end %%Page: 107 113 TeXDict begin 107 112 bop 0 299 a Fh(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fj(107)0 555 y(rotation)33 b(\(or)e(b)s(ounding)f(angles)i(for)f(Sector\))h(in)f (degrees.)44 b(F)-8 b(or)32 b(rotated)h(shap)s(es,)e(the)g(rotation)i (angle)f(can)g(b)s(e)0 668 y(left)g(o\013,)h(indicating)f(no)f (rotation.)46 b(Common)31 b(alternate)i(names)e(for)h(the)f(regions)h (can)g(also)h(b)s(e)d(used:)43 b(rotb)s(o)m(x)0 781 y(=)29 b(b)s(o)m(x;)g(rotrectangle)i(=)e(rectangle;)i(\(rot\)rhom)m(bus)e(=)f (\(rot\)diamond;)j(and)d(pie)h(=)f(sector.)42 b(When)28 b(a)i(shap)s(e's)0 894 y(name)e(is)g(preceded)f(b)m(y)h(a)g(min)m(us)g (sign,)g('-',)i(the)e(de\014ned)e(region)j(is)f(instead)g(the)g(area)h (*outside*)g(its)f(b)s(oundary)0 1007 y(\(ie,)36 b(the)e(region)h(is)f (in)m(v)m(erted\).)53 b(All)34 b(the)g(shap)s(es)f(within)h(a)g(single) h(region)f(\014le)h(are)f(OR'd)f(together)j(to)e(create)0 1120 y(the)29 b(region,)i(and)d(the)i(order)f(is)g(signi\014can)m(t.)41 b(The)29 b(o)m(v)m(erall)i(w)m(a)m(y)g(of)e(lo)s(oking)h(at)g(region)g (\014les)f(is)g(that)h(if)f(the)h(\014rst)0 1233 y(region)f(is)g(an)g (excluded)g(region)g(then)f(a)i(dumm)m(y)d(included)h(region)i(of)f (the)g(whole)g(detector)h(is)f(inserted)f(in)h(the)0 1346 y(fron)m(t.)40 b(Then)25 b(eac)m(h)j(region)f(sp)s(eci\014cation)h (as)f(it)g(is)g(pro)s(cessed)f(o)m(v)m(errides)h(an)m(y)g(selections)i (inside)d(of)h(that)g(region)0 1458 y(sp)s(eci\014ed)36 b(b)m(y)g(previous)g(regions.)59 b(Another)37 b(w)m(a)m(y)g(of)g (thinking)f(ab)s(out)g(this)g(is)h(that)g(if)f(a)h(previous)f(excluded) 0 1571 y(region)31 b(is)f(completely)i(inside)f(of)f(a)h(subsequen)m(t) e(included)h(region)h(the)g(excluded)f(region)h(is)f(ignored.)0 1732 y(The)44 b(p)s(ositional)i(co)s(ordinates)g(ma)m(y)f(b)s(e)g(giv)m (en)h(either)f(in)g(pixel)g(units,)j(decimal)e(degrees)g(or)f (hh:mm:ss.s,)0 1844 y(dd:mm:ss.s)25 b(units.)38 b(The)26 b(shap)s(e)f(sizes)i(ma)m(y)f(b)s(e)g(giv)m(en)h(in)e(pixels,)j (degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)40 b(Lo)s(ok)0 1957 y(at)31 b(examples)g(of)f(region)h(\014le)g(pro)s(duced)d(b)m(y)i (fv/PO)m(W)h(or)g(ds9)f(for)g(further)f(details)i(of)g(the)f(region)h (\014le)f(format.)0 2118 y(There)37 b(are)g(three)g(functions)g(that)g (are)h(primarily)f(for)f(use)h(with)g(SA)m(O)g(region)g(\014les)g(and)g (the)g(FSA)m(OI)g(task,)0 2230 y(but)e(they)h(can)h(b)s(e)e(used)g (directly)-8 b(.)59 b(They)36 b(return)f(a)h(b)s(o)s(olean)g(true)g(or) g(false)g(dep)s(ending)f(on)h(whether)f(a)i(t)m(w)m(o)0 2343 y(dimensional)31 b(p)s(oin)m(t)f(is)g(in)g(the)h(region)g(or)f (not:)191 2605 y Ff("point)46 b(in)h(a)h(circular)d(region")477 2718 y(circle\(xcntr,ycntr,radius)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 2944 y("point)h(in)h(an)g(elliptical)e(region")430 3057 y(ellipse\(xcntr,ycntr,xhl)o(f_w)o(dth,)o(yhlf)o(_wd)o(th,r)o(otat)o (ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 3282 y("point)h(in)h(a)h (rectangular)c(region")620 3395 y(box\(xcntr,ycntr,xfll_wdth,)o(yfll)o (_wd)o(th,r)o(otat)o(ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 3621 y(where)334 3734 y(\(xcntr,ycntr\))g(are)j(the)g(\(x,y\))f (position)g(of)h(the)g(center)f(of)h(the)g(region)334 3847 y(\(xhlf_wdth,yhlf_wdth\))42 b(are)47 b(the)g(\(x,y\))f(half)h (widths)f(of)h(the)g(region)334 3960 y(\(xfll_wdth,yfll_wdth\))42 b(are)47 b(the)g(\(x,y\))f(full)h(widths)f(of)h(the)g(region)334 4073 y(\(radius\))f(is)h(half)f(the)h(diameter)f(of)h(the)g(circle)334 4186 y(\(rotation\))e(is)i(the)g(angle\(degrees\))d(that)j(the)g (region)f(is)h(rotated)f(with)620 4299 y(respect)g(to)h (\(xcntr,ycntr\))334 4411 y(\(Xcoord,Ycoord\))d(are)j(the)g(\(x,y\))f (coordinates)f(to)i(test,)f(usually)g(column)620 4524 y(names)334 4637 y(NOTE:)g(each)h(parameter)e(can)i(itself)f(be)i(an)f (expression,)d(not)j(merely)f(a)620 4750 y(column)h(name)f(or)h (constant.)0 5043 y Fc(8.11.6)113 b(Example)38 b(Ro)m(w)f(Filters)191 5262 y Ff([)47 b(binary)f(&&)i(mag)f(<=)g(5.0])380 b(-)48 b(Extract)e(all)h(binary)f(stars)g(brighter)1766 5375 y(than)94 b(fifth)47 b(magnitude)e(\(note)h(that)1766 5488 y(the)h(initial)f(space)g(is)h(necessary)e(to)1766 5601 y(prevent)h(it)h(from)g(being)f(treated)g(as)h(a)1766 5714 y(binning)f(specification\))p eop end %%Page: 108 114 TeXDict begin 108 113 bop 0 299 a Fj(108)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 668 y Ff([#row)46 b(>=)h(125)g(&&)h(#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through)f(175)191 894 y([IMAGE[4,5])f(.gt.)h(100])476 b(-)48 b(Extract)e(all)h(rows)f (that)h(have)g(the)1766 1007 y(\(4,5\))f(component)g(of)h(the)g(IMAGE)f (column)1766 1120 y(greater)g(than)g(100)191 1346 y([abs\(sin\(theta)e (*)j(#deg\)\))f(<)i(0.5])e(-)i(Extract)e(all)h(rows)f(having)g(the)1766 1458 y(absolute)f(value)i(of)g(the)g(sine)g(of)g(theta)1766 1571 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h(angles)1766 1684 y(are)g(tabulated)e(in)i(degrees)191 1910 y([SUM\()f(SPEC)h(>)g (3*BACKGRND)e(\)>=1])94 b(-)48 b(Extract)e(all)h(rows)f(containing)f(a) 1766 2023 y(spectrum,)g(held)i(in)g(vector)f(column)1766 2136 y(SPEC,)g(with)h(at)g(least)f(one)h(value)g(3)1766 2249 y(times)f(greater)g(than)h(the)g(background)1766 2362 y(level)f(held)h(in)g(a)h(keyword,)d(BACKGRND)191 2588 y([VCOL=={1,4,2}])759 b(-)48 b(Extract)e(all)h(rows)f(whose)h (vector)f(column)1766 2700 y(VCOL)h(contains)e(the)i(3-elements)e(1,)i (4,)g(and)1766 2813 y(2.)191 3039 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g(expression)1766 3152 y(contained)e(within)h(the)h(text)g(file)1766 3265 y(rowFilter.txt)191 3491 y([gtifilter\(\)])855 b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)239 3604 y(extension,)92 b(filter)i(the)47 b(TIME)239 3717 y(column)f(in)h(the)g (current)f(table,)g(using)239 3830 y(START/STOP)f(times)h(taken)g(from) 239 3942 y(columns)f(in)j(the)f(GTI)94 b(extension)191 4168 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h (have)f(a)i(coordinate)1766 4281 y(\(as)f(given)f(in)h(the)g(X)h(and)f (Y)g(columns\))1766 4394 y(within)f(the)h(spatial)f(region)g(specified) 1766 4507 y(in)h(the)g(pow.reg)f(region)g(file.)191 4733 y([regfilter\("pow.reg",)c(Xs,)47 b(Ys\)])f(-)i(Same)f(as)g(above,)f (except)g(that)h(the)1766 4846 y(Xs)g(and)g(Ys)g(columns)f(will)h(be)g (used)f(to)1766 4959 y(determine)f(the)i(coordinate)e(of)i(each)1766 5072 y(row)g(in)g(the)g(table.)p eop end %%Page: 109 115 TeXDict begin 109 114 bop 0 299 a Fh(8.12.)113 b(BINNING)31 b(OR)f(HISTOGRAMMING)h(SPECIFICA)-8 b(TION)1268 b Fj(109)0 555 y Fe(8.12)180 b(Binning)45 b(or)g(Histogramming)i(Sp)t (eci\014cation)0 805 y Fj(The)22 b(optional)i(binning)e(sp)s(eci\014er) g(is)h(enclosed)h(in)f(square)f(brac)m(k)m(ets)j(and)d(can)h(b)s(e)f (distinguished)g(from)h(a)g(general)0 918 y(ro)m(w)32 b(\014lter)h(sp)s(eci\014cation)g(b)m(y)f(the)h(fact)g(that)g(it)g(b)s (egins)f(with)g(the)g(k)m(eyw)m(ord)h('bin')f(not)h(immediately)g (follo)m(w)m(ed)0 1031 y(b)m(y)41 b(an)f(equals)i(sign.)72 b(When)41 b(binning)e(is)i(sp)s(eci\014ed,)i(a)e(temp)s(orary)g (N-dimensional)g(FITS)f(primary)g(arra)m(y)0 1144 y(is)j(created)h(b)m (y)f(computing)h(the)f(histogram)h(of)f(the)g(v)-5 b(alues)44 b(in)e(the)i(sp)s(eci\014ed)e(columns)h(of)g(a)h(FITS)e(table)0 1257 y(extension.)f(After)30 b(the)f(histogram)h(is)g(computed)f(the)h (input)e(FITS)h(\014le)h(con)m(taining)h(the)e(table)i(is)e(then)g (closed)0 1370 y(and)34 b(the)h(temp)s(orary)f(FITS)g(primary)g(arra)m (y)h(is)g(op)s(ened)f(and)g(passed)g(to)h(the)g(application)h(program.) 54 b(Th)m(us,)0 1483 y(the)39 b(application)h(program)f(nev)m(er)g (sees)g(the)g(original)h(FITS)e(table)i(and)e(only)h(sees)h(the)f (image)h(in)e(the)h(new)0 1596 y(temp)s(orary)32 b(\014le)h(\(whic)m(h) g(has)f(no)h(additional)g(extensions\).)49 b(Ob)m(viously)-8 b(,)34 b(the)f(application)h(program)e(m)m(ust)h(b)s(e)0 1709 y(exp)s(ecting)e(to)g(op)s(en)f(a)h(FITS)e(image)j(and)e(not)g(a)h (FITS)f(table)h(in)f(this)g(case.)0 1869 y(The)g(data)h(t)m(yp)s(e)f (of)h(the)f(FITS)g(histogram)g(image)i(ma)m(y)f(b)s(e)f(sp)s(eci\014ed) f(b)m(y)h(app)s(ending)f('b')h(\(for)h(8-bit)g(b)m(yte\),)g('i')0 1982 y(\(for)g(16-bit)g(in)m(tegers\),)h('j')f(\(for)g(32-bit)g(in)m (teger\),)i('r')d(\(for)h(32-bit)g(\015oating)h(p)s(oin)m(ts\),)e(or)h ('d')f(\(for)h(64-bit)g(double)0 2095 y(precision)d(\015oating)h(p)s (oin)m(t\))g(to)f(the)h('bin')e(k)m(eyw)m(ord)i(\(e.g.)41 b('[binr)28 b(X]')g(creates)i(a)e(real)h(\015oating)g(p)s(oin)m(t)f (image\).)41 b(If)0 2208 y(the)26 b(datat)m(yp)s(e)h(is)f(not)g (explicitly)i(sp)s(eci\014ed)d(then)h(a)g(32-bit)h(in)m(teger)h(image)f (will)f(b)s(e)f(created)i(b)m(y)f(default,)i(unless)0 2320 y(the)h(w)m(eigh)m(ting)h(option)f(is)g(also)h(sp)s(eci\014ed)e (in)g(whic)m(h)h(case)g(the)g(image)h(will)f(ha)m(v)m(e)h(a)f(32-bit)h (\015oating)g(p)s(oin)m(t)e(data)0 2433 y(t)m(yp)s(e)j(b)m(y)f (default.)0 2594 y(The)24 b(histogram)g(image)i(ma)m(y)f(ha)m(v)m(e)g (from)f(1)g(to)h(4)g(dimensions)e(\(axes\),)k(dep)s(ending)c(on)h(the)g (n)m(um)m(b)s(er)f(of)h(columns)0 2706 y(that)31 b(are)g(sp)s (eci\014ed.)40 b(The)30 b(general)h(form)f(of)g(the)h(binning)e(sp)s (eci\014cation)i(is:)48 2955 y Ff([bin{bijrd})92 b (Xcol=min:max:binsize,)42 b(Ycol=)47 b(...,)f(Zcol=...,)f(Tcol=...;)h (weight])0 3203 y Fj(in)39 b(whic)m(h)g(up)f(to)i(4)g(columns,)h(eac)m (h)f(corresp)s(onding)e(to)i(an)g(axis)f(of)h(the)f(image,)k(are)d (listed.)67 b(The)39 b(column)0 3316 y(names)27 b(are)h(case)h (insensitiv)m(e,)g(and)e(the)h(column)f(n)m(um)m(b)s(er)f(ma)m(y)i(b)s (e)f(giv)m(en)h(instead)g(of)g(the)g(name,)g(preceded)f(b)m(y)0 3429 y(a)32 b(p)s(ound)e(sign)i(\(e.g.,)i([bin)d(#4=1:512]\).)47 b(If)31 b(the)h(column)g(name)g(is)f(not)h(sp)s(eci\014ed,)g(then)f (CFITSIO)g(will)h(\014rst)0 3542 y(try)37 b(to)h(use)f(the)g ('preferred)f(column')i(as)f(sp)s(eci\014ed)g(b)m(y)g(the)g(CPREF)g(k)m (eyw)m(ord)h(if)f(it)g(exists)h(\(e.g.,)j('CPREF)0 3655 y(=)i('DETX,DETY'\),)h(otherwise)g(column)f(names)g('X',)h('Y',)g('Z',) f(and)f('T')i(will)f(b)s(e)f(assumed)h(for)g(eac)m(h)h(of)0 3768 y(the)37 b(4)h(axes,)i(resp)s(ectiv)m(ely)-8 b(.)62 b(In)37 b(cases)h(where)e(the)i(column)f(name)g(could)g(b)s(e)f (confused)h(with)g(an)g(arithmetic)0 3881 y(expression,)30 b(enclose)i(the)f(column)f(name)g(in)g(paren)m(theses)h(to)g(force)g (the)f(name)h(to)g(b)s(e)f(in)m(terpreted)g(literally)-8 b(.)0 4041 y(In)31 b(addition)h(to)g(binning)f(b)m(y)g(a)h(FITS)f (column,)h(an)m(y)g(arbitrary)f(calculator)j(expression)e(ma)m(y)g(b)s (e)f(sp)s(eci\014ed)g(as)0 4154 y(w)m(ell.)42 b(Usage)31 b(of)g(this)f(form)g(w)m(ould)g(app)s(ear)g(as:)48 4402 y Ff([bin)94 b(Xcol\(arbitrary)44 b(expression\)=min:max:bins)o(ize,)d (...)47 b(])0 4650 y Fj(The)23 b(column)h(name)g(m)m(ust)f(still)i(b)s (e)e(sp)s(eci\014ed,)h(and)g(is)f(used)g(to)i(lab)s(el)f(co)s(ordinate) g(axes)h(of)f(the)g(resulting)f(image.)0 4763 y(The)30 b(expression)g(app)s(ears)g(immediately)i(after)e(the)h(name,)g (enclosed)g(in)f(paren)m(theses.)41 b(The)30 b(expression)g(ma)m(y)0 4876 y(use)h(an)m(y)i(com)m(bination)g(of)f(columns,)g(k)m(eyw)m(ords,) g(functions)g(and)f(constan)m(ts)i(and)e(allo)m(w)m(ed)j(b)m(y)d(the)h (CFITSIO)0 4989 y(calculator.)0 5149 y(The)d(column)f(name)h(\(and)g (optional)h(expression\))f(ma)m(y)h(b)s(e)e(follo)m(w)m(ed)j(b)m(y)e (an)g(equals)g(sign)g(and)g(then)f(the)i(lo)m(w)m(er)0 5262 y(and)f(upp)s(er)f(range)i(of)f(the)h(histogram,)h(and)e(the)h (size)g(of)g(the)g(histogram)g(bins,)f(separated)h(b)m(y)g(colons.)41 b(Spaces)0 5375 y(are)30 b(allo)m(w)m(ed)i(b)s(efore)e(and)f(after)i (the)f(equals)h(sign)f(but)f(not)h(within)g(the)g('min:max:binsize')h (string.)41 b(The)29 b(min,)0 5488 y(max)37 b(and)g(binsize)g(v)-5 b(alues)38 b(ma)m(y)g(b)s(e)f(in)m(teger)h(or)g(\015oating)g(p)s(oin)m (t)f(n)m(um)m(b)s(ers,)h(or)f(they)h(ma)m(y)f(b)s(e)g(the)h(names)f(of) 0 5601 y(k)m(eyw)m(ords)f(in)g(the)h(header)f(of)g(the)g(table.)59 b(If)36 b(the)g(latter,)k(then)c(the)g(v)-5 b(alue)37 b(of)f(that)h(k)m(eyw)m(ord)f(is)h(substituted)0 5714 y(in)m(to)31 b(the)g(expression.)p eop end %%Page: 110 116 TeXDict begin 110 115 bop 0 299 a Fj(110)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(Default)37 b(v)-5 b(alues)36 b(for)g(the)g(min,)h(max)f(and)g (binsize)g(quan)m(tities)h(will)f(b)s(e)f(used)h(if)f(not)i(explicitly) g(giv)m(en)g(in)f(the)0 668 y(binning)29 b(expression)h(as)h(sho)m(wn)f (in)g(these)h(examples:)191 894 y Ff([bin)47 b(x)g(=)g(:512:2])94 b(-)47 b(use)g(default)f(minimum)g(value)191 1007 y([bin)h(x)g(=)g (1::2])190 b(-)47 b(use)g(default)f(maximum)g(value)191 1120 y([bin)h(x)g(=)g(1:512])142 b(-)47 b(use)g(default)f(bin)h(size) 191 1233 y([bin)g(x)g(=)g(1:])286 b(-)47 b(use)g(default)f(maximum)g (value)g(and)h(bin)g(size)191 1346 y([bin)g(x)g(=)g(:512])190 b(-)47 b(use)g(default)f(minimum)g(value)g(and)h(bin)g(size)191 1459 y([bin)g(x)g(=)g(2])334 b(-)47 b(use)g(default)f(minimum)g(and)h (maximum)f(values)191 1572 y([bin)h(x])524 b(-)47 b(use)g(default)f (minimum,)g(maximum)g(and)g(bin)h(size)191 1685 y([bin)g(4])524 b(-)47 b(default)f(2-D)h(image,)f(bin)h(size)g(=)g(4)h(in)f(both)g (axes)191 1798 y([bin])619 b(-)47 b(default)f(2-D)h(image)0 2024 y Fj(CFITSIO)31 b(will)i(use)f(the)h(v)-5 b(alue)33 b(of)g(the)g(TLMINn,)f(TLMAXn,)h(and)f(TDBINn)h(k)m(eyw)m(ords,)h(if)e (they)h(exist,)h(for)0 2137 y(the)j(default)f(min,)i(max,)g(and)e (binsize,)i(resp)s(ectiv)m(ely)-8 b(.)61 b(If)36 b(they)h(do)f(not)h (exist)g(then)f(CFITSIO)f(will)i(use)f(the)0 2250 y(actual)d(minim)m (um)e(and)h(maxim)m(um)g(v)-5 b(alues)32 b(in)g(the)g(column)f(for)h (the)g(histogram)h(min)e(and)h(max)g(v)-5 b(alues.)45 b(The)0 2363 y(default)34 b(binsize)f(will)h(b)s(e)f(set)h(to)h(1,)g (or)e(\(max)h(-)g(min\))f(/)h(10.,)i(whic)m(hev)m(er)e(is)g(smaller,)h (so)e(that)i(the)e(histogram)0 2476 y(will)e(ha)m(v)m(e)g(at)g(least)h (10)f(bins)f(along)h(eac)m(h)h(axis.)0 2636 y(Please)d(note)f(that)g (if)g(explicit)h(min)e(and)g(max)h(v)-5 b(alues)28 b(\(or)f (TLMINn/TLMAXn)g(k)m(eyw)m(ords\))i(are)f(not)g(presen)m(t,)0 2749 y(then)g(CFITSIO)g(m)m(ust)g(c)m(hec)m(k)j(ev)m(ery)e(v)-5 b(alue)30 b(of)e(the)h(binned)f(quan)m(tit)m(y)i(in)e(adv)-5 b(ance)30 b(to)f(determine)g(the)g(binning)0 2861 y(limits.)43 b(This)30 b(is)h(esp)s(ecially)h(relev)-5 b(an)m(t)32 b(for)f(binning)f(expressions,)h(whic)m(h)g(m)m(ust)f(b)s(e)h(ev)-5 b(aluated)32 b(m)m(ultiple)f(times)0 2974 y(to)40 b(determine)f(the)g (limits)g(of)g(the)g(expression.)67 b(Th)m(us,)40 b(it)f(is)g(alw)m(a)m (ys)i(advisable)e(to)h(sp)s(ecify)e(min)h(and)f(max)0 3087 y(limits)31 b(where)f(p)s(ossible.)0 3247 y(A)41 b(shortcut)g(notation)h(is)f(allo)m(w)m(ed)i(if)e(all)h(the)f (columns/axes)h(ha)m(v)m(e)g(the)f(same)g(binning)f(sp)s (eci\014cation.)74 b(In)0 3360 y(this)33 b(case)g(all)h(the)f(column)f (names)h(ma)m(y)g(b)s(e)f(listed)h(within)f(paren)m(theses,)i(follo)m (w)m(ed)h(b)m(y)d(the)h(\(single\))h(binning)0 3473 y(sp)s (eci\014cation,)d(as)g(in:)191 3700 y Ff([bin)47 b(\(X,Y\)=1:512:2])191 3812 y([bin)g(\(X,Y\))f(=)h(5])0 4039 y Fj(The)31 b(optional)i(w)m (eigh)m(ting)h(factor)e(is)g(the)g(last)g(item)h(in)e(the)h(binning)f (sp)s(eci\014er)g(and,)h(if)f(presen)m(t,)i(is)e(separated)0 4152 y(from)38 b(the)g(list)h(of)f(columns)g(b)m(y)g(a)h(semi-colon.)65 b(As)39 b(the)f(histogram)h(is)f(accum)m(ulated,)k(this)c(w)m(eigh)m(t) i(is)e(used)0 4264 y(to)d(incremen)m(ted)f(the)g(v)-5 b(alue)35 b(of)f(the)g(appropriated)f(bin)h(in)f(the)h(histogram.)52 b(If)34 b(the)g(w)m(eigh)m(ting)i(factor)f(is)f(not)0 4377 y(sp)s(eci\014ed,)c(then)f(the)h(default)g(w)m(eigh)m(t)i(=)d(1)i (is)f(assumed.)39 b(The)30 b(w)m(eigh)m(ting)h(factor)g(ma)m(y)g(b)s(e) e(a)h(constan)m(t)i(in)m(teger)0 4490 y(or)d(\015oating)g(p)s(oin)m(t)g (n)m(um)m(b)s(er,)f(or)g(the)h(name)g(of)f(a)h(k)m(eyw)m(ord)g(con)m (taining)h(the)f(w)m(eigh)m(ting)i(v)-5 b(alue.)40 b(The)28 b(w)m(eigh)m(ting)0 4603 y(factor)35 b(ma)m(y)f(also)h(b)s(e)e(the)h (name)g(of)g(a)g(table)h(column)f(in)f(whic)m(h)h(case)h(the)f(v)-5 b(alue)34 b(in)g(that)g(column,)h(on)f(a)g(ro)m(w)0 4716 y(b)m(y)29 b(ro)m(w)f(basis,)i(will)f(b)s(e)f(used.)39 b(It)29 b(ma)m(y)g(also)h(b)s(e)e(an)h(expression,)g(enclosed)g(in)g (paren)m(thesis,)g(in)g(whic)m(h)f(case)i(the)0 4829 y(w)m(eigh)m(ting)i(v)-5 b(alue)31 b(will)g(b)s(e)e(ev)-5 b(aluated)32 b(for)e(eac)m(h)i(binned)d(ro)m(w)h(and)g(applied)g (accordingly)-8 b(.)0 4989 y(In)35 b(some)h(cases,)i(the)d(column)h(or) f(k)m(eyw)m(ord)h(ma)m(y)g(giv)m(e)h(the)f(recipro)s(cal)g(of)g(the)g (actual)h(w)m(eigh)m(t)g(v)-5 b(alue)36 b(that)g(is)0 5102 y(needed.)49 b(In)32 b(this)h(case,)i(precede)e(the)h(w)m(eigh)m (t)g(k)m(eyw)m(ord)g(or)f(column)g(name)g(b)m(y)g(a)g(slash)g('/')h(to) g(tell)g(CFITSIO)0 5215 y(to)40 b(use)e(the)i(recipro)s(cal)g(of)f(the) g(v)-5 b(alue)39 b(when)f(constructing)i(the)f(histogram.)68 b(An)38 b(expression,)j(enclosed)f(in)0 5328 y(paren)m(theses,)31 b(ma)m(y)g(also)g(app)s(ear)f(after)h(the)f(slash,)h(to)g(indicate)g (the)g(recipro)s(cal)g(v)-5 b(alue)31 b(of)g(the)f(expression.)0 5488 y(F)-8 b(or)35 b(complex)f(or)g(commonly)g(used)f(histograms,)j (one)e(can)g(also)h(place)g(its)f(description)g(in)m(to)h(a)f(text)h (\014le)f(and)0 5601 y(imp)s(ort)44 b(it)g(in)m(to)i(the)e(binning)f (sp)s(eci\014cation)i(using)f(the)h(syn)m(tax)f('[bin)g (@\014lename.txt]'.)84 b(The)44 b(\014le's)g(con-)0 5714 y(ten)m(ts)37 b(can)e(extend)h(o)m(v)m(er)h(m)m(ultiple)f(lines,)i (although)e(it)g(m)m(ust)f(still)i(conform)f(to)g(the)g(no-spaces)g (rule)f(for)h(the)p eop end %%Page: 111 117 TeXDict begin 111 116 bop 0 299 a Fh(8.12.)113 b(BINNING)31 b(OR)f(HISTOGRAMMING)h(SPECIFICA)-8 b(TION)1268 b Fj(111)0 555 y(min:max:binsize)37 b(syn)m(tax)h(and)e(eac)m(h)i(axis)g(sp)s (eci\014cation)g(m)m(ust)f(still)g(b)s(e)g(comma-separated.)62 b(An)m(y)37 b(lines)g(in)0 668 y(the)32 b(external)h(text)g(\014le)f (that)h(b)s(egin)e(with)h(2)g(slash)g(c)m(haracters)h(\('//'\))h(will)e (b)s(e)g(ignored)g(and)f(ma)m(y)i(b)s(e)e(used)g(to)0 781 y(add)f(commen)m(ts)h(in)m(to)g(the)g(\014le.)0 941 y(Examples:)191 1201 y Ff([bini)46 b(detx,)h(dety])762 b(-)47 b(2-D,)g(16-bit)f(integer)g(histogram)1861 1314 y(of)i(DETX)e(and)h(DETY)g(columns,)e(using)1861 1427 y(default)h(values)g(for)h(the)g(histogram)1861 1540 y(range)g(and)g(binsize)191 1766 y([bin)g(\(detx,)f(dety\)=16;)f (/exposure])g(-)i(2-D,)g(32-bit)f(real)h(histogram)e(of)i(DETX)1861 1878 y(and)g(DETY)g(columns)f(with)g(a)i(bin)f(size)f(=)i(16)1861 1991 y(in)g(both)e(axes.)h(The)f(histogram)g(values)1861 2104 y(are)h(divided)f(by)h(the)g(EXPOSURE)f(keyword)1861 2217 y(value.)191 2443 y([bin)h(time=TSTART:TSTOP:0.1])280 b(-)47 b(1-D)g(lightcurve,)e(range)h(determined)f(by)1861 2556 y(the)i(TSTART)f(and)h(TSTOP)g(keywords,)1861 2669 y(with)g(0.1)g(unit)g(size)f(bins.)191 2895 y([bin)h(pha,)f (time=8000.:8100.:0.1])90 b(-)47 b(2-D)g(image)g(using)f(default)g (binning)1861 3008 y(of)i(the)e(PHA)h(column)f(for)h(the)g(X)h(axis,) 1861 3120 y(and)f(1000)g(bins)g(in)g(the)g(range)1861 3233 y(8000.)g(to)g(8100.)f(for)h(the)g(Y)h(axis.)191 3459 y([bin)f(pha,)f(gti_num\(gtifind\(\)\)=1:2:1])41 b(-)48 b(a)f(2-D)g(image,)f(where)g(PHA)h(is)g(the)1861 3572 y(X)h(axis)e(and)h(the)g(Y)h(axis)e(is)i(an)f(expression)1861 3685 y(which)g(evaluates)e(to)i(the)g(GTI)g(number,)1861 3798 y(as)h(determined)d(using)h(the)1861 3911 y(GTIFIND\(\))g (function.)191 4137 y([bin)h(time=0:4000:2000,)c(HR\()k (\(LC2/LC1\).lt.1.5)c(?)k(1)h(:)f(2)h(\)=1:2:1])d(-)j(a)f(2-D)1861 4250 y(histogram)f(which)g(determines)f(the)i(number)1861 4362 y(of)h(samples)d(in)j(two)e(time)h(bins)g(between)f(0)h(and)1861 4475 y(4000)g(and)g(separating)e(hardness)g(ratio,)1861 4588 y(evaluated)h(as)h(\(LC2/LC1\),)e(between)h(less)g(than)1861 4701 y(1.5)h(or)g(greater)f(than)h(1.5.)94 b(The)47 b(?:)1861 4814 y(conditional)e(function)h(is)h(used)f(to)i(decide)1861 4927 y(less)f(\(or)g(greater\))e(than)i(1.5)g(and)g(assign)1861 5040 y(HR)h(bin)e(1)i(or)f(2.)191 5266 y([bin)g(@binFilter.txt])616 b(-)47 b(Use)g(the)g(contents)f(of)h(the)g(text)f(file)1861 5379 y(binFilter.txt)f(for)h(the)h(binning)1861 5492 y(specifications.)p eop end %%Page: 112 118 TeXDict begin 112 117 bop 0 299 a Fj(112)1573 b Fh(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)p eop end %%Page: 113 119 TeXDict begin 113 118 bop 0 1225 a Fg(Chapter)65 b(9)0 1687 y Fm(T)-19 b(emplate)76 b(Files)0 2180 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f(call)i(to)g (\014ts)p 2101 2180 28 4 v 32 w(create)p 2369 2180 V 35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e(ma)m(y)0 2293 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h(follo)m (wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e(created.)71 b(This)0 2406 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h (structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m(y)0 2518 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f(newly)g (created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g(k)m(eyw) m(ords)g(in)0 2631 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g(template)i (FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b)s(e)f (\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2744 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,)g (where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h(FITS) f(k)m(eyw)m(ord)i(record.)0 2857 y(The)j(format)h(of)f(the)h(ASCI)s(I)e (template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m(wing)i (sections.)0 3188 y Fe(9.1)135 b(Detailed)47 b(T)-11 b(emplate)46 b(Line)f(F)-11 b(ormat)0 3438 y Fj(The)30 b(format)h(of)f(eac)m(h)i(ASCI)s(I)c(template)k(line)f(closely)h(follo) m(ws)f(the)g(format)g(of)f(a)h(FITS)f(k)m(eyw)m(ord)g(record:)95 3682 y Ff(KEYWORD)46 b(=)i(KEYVALUE)d(/)j(COMMENT)0 3926 y Fj(except)22 b(that)g(free)g(format)f(ma)m(y)h(b)s(e)f(used)f (\(e.g.,)25 b(the)d(equals)f(sign)h(ma)m(y)f(app)s(ear)g(at)h(an)m(y)g (p)s(osition)f(in)g(the)h(line\))g(and)0 4039 y(T)-8 b(AB)34 b(c)m(haracters)g(are)g(allo)m(w)m(ed)h(and)e(are)g(treated)h (the)g(same)f(as)h(space)f(c)m(haracters.)51 b(The)33 b(KEYV)-10 b(ALUE)33 b(and)0 4152 y(COMMENT)d(\014elds)g(are)h (optional.)43 b(The)30 b(equals)h(sign)f(c)m(haracter)j(is)d(also)i (optional,)g(but)e(it)h(is)f(recommended)0 4264 y(that)42 b(it)f(b)s(e)g(included)f(for)h(clarit)m(y)-8 b(.)75 b(An)m(y)41 b(template)i(line)e(that)h(b)s(egins)f(with)f(the)i(p)s (ound)d('#')i(c)m(haracter)i(is)0 4377 y(ignored)30 b(b)m(y)h(the)f (template)i(parser)e(and)g(ma)m(y)h(b)s(e)e(use)h(to)h(insert)g(commen) m(ts)g(in)m(to)g(the)g(template)h(\014le)e(itself.)0 4538 y(The)c(KEYW)m(ORD)g(name)g(\014eld)g(is)g(limited)h(to)g(8)f(c)m (haracters)h(in)f(length)h(and)e(only)h(the)g(letters)i(A-Z,)e(digits)h (0-9,)0 4650 y(and)h(the)g(h)m(yphen)f(and)h(underscore)g(c)m (haracters)h(ma)m(y)g(b)s(e)f(used,)g(without)h(an)m(y)f(em)m(b)s (edded)g(spaces.)40 b(Lo)m(w)m(ercase)0 4763 y(letters)22 b(in)f(the)h(template)g(k)m(eyw)m(ord)g(name)f(will)g(b)s(e)g(con)m(v)m (erted)i(to)f(upp)s(ercase.)36 b(Leading)22 b(spaces)f(in)g(the)h (template)0 4876 y(line)k(preceding)g(the)f(k)m(eyw)m(ord)h(name)g(are) g(generally)h(ignored,)g(except)f(if)g(the)g(\014rst)f(8)h(c)m (haracters)h(of)f(a)g(template)0 4989 y(line)f(are)h(all)g(blank,)g (then)f(the)g(en)m(tire)h(line)g(is)f(treated)h(as)f(a)h(FITS)e(commen) m(t)i(k)m(eyw)m(ord)g(\(with)f(a)h(blank)e(k)m(eyw)m(ord)0 5102 y(name\))31 b(and)f(is)g(copied)h(v)m(erbatim)g(in)m(to)g(the)g (FITS)e(header.)0 5262 y(The)37 b(KEYV)-10 b(ALUE)37 b(\014eld)g(ma)m(y)h(ha)m(v)m(e)g(an)m(y)g(allo)m(w)m(ed)h(FITS)e(data) h(t)m(yp)s(e:)54 b(c)m(haracter)39 b(string,)h(logical,)h(in)m(teger,)0 5375 y(real,)28 b(complex)g(in)m(teger,)h(or)d(complex)i(real.)40 b(In)m(teger)28 b(v)-5 b(alues)27 b(m)m(ust)f(b)s(e)g(within)g(the)h (allo)m(w)m(ed)i(range)e(of)g(a)g('signed)0 5488 y(long')h(v)-5 b(ariable;)29 b(some)f(C)e(compilers)i(only)f(suppp)s(ort)e(4-b)m(yte)j (long)g(in)m(tegers)g(with)f(a)g(range)h(from)e(-2147483648)0 5601 y(to)31 b(+2147483647,)k(whereas)30 b(other)h(C)f(compilers)h (supp)s(ort)e(8-b)m(yte)j(in)m(tegers)f(with)f(a)h(range)g(of)g(plus)e (or)i(min)m(us)0 5714 y(2**63.)1882 5942 y(113)p eop end %%Page: 114 120 TeXDict begin 114 119 bop 0 299 a Fj(114)2295 b Fh(CHAPTER)30 b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fj(The)23 b(c)m(haracter)h(string)f(v)-5 b(alues)24 b(need)f(not)g(b)s(e)g (enclosed)g(in)g(single)h(quote)g(c)m(haracters)g(unless)f(they)g(are)h (necessary)0 668 y(to)37 b(distinguish)e(the)i(string)f(from)f(a)i (di\013eren)m(t)g(data)f(t)m(yp)s(e)h(\(e.g.)59 b(2.0)38 b(is)e(a)g(real)h(but)f('2.0')h(is)f(a)h(string\).)58 b(The)0 781 y(k)m(eyw)m(ord)38 b(has)g(an)g(unde\014ned)d(\(n)m(ull\))k (v)-5 b(alue)38 b(if)g(the)g(template)h(record)f(only)g(con)m(tains)h (blanks)e(follo)m(wing)j(the)0 894 y("=")31 b(or)f(b)s(et)m(w)m(een)h (the)g("=")g(and)f(the)g("/")i(commen)m(t)f(\014eld)f(delimiter.)0 1054 y(String)c(k)m(eyw)m(ord)h(v)-5 b(alues)27 b(longer)g(than)f(68)h (c)m(haracters)h(\(the)f(maxim)m(um)f(length)h(that)g(will)g(\014t)f (in)g(a)h(single)g(FITS)0 1167 y(k)m(eyw)m(ord)41 b(record\))g(are)g(p) s(ermitted)f(using)g(the)h(CFITSIO)e(long)i(string)g(con)m(v)m(en)m (tion.)74 b(They)40 b(can)h(either)g(b)s(e)0 1280 y(sp)s(eci\014ed)28 b(as)i(a)f(single)h(long)f(line)h(in)e(the)i(template,)h(or)e(b)m(y)f (using)h(m)m(ultiple)h(lines)f(where)f(the)i(con)m(tin)m(uing)g(lines)0 1393 y(con)m(tain)i(the)e('CONTINUE')g(k)m(eyw)m(ord,)h(as)g(in)f(this) g(example:)95 1657 y Ff(LONGKEY)46 b(=)i('This)e(is)h(a)h(long)e (string)g(value)h(that)f(is)i(contin&')95 1770 y(CONTINUE)94 b('ued)46 b(over)h(2)g(records')f(/)h(comment)f(field)h(goes)f(here)0 2035 y Fj(The)29 b(format)h(of)g(template)h(lines)e(with)h(CONTINUE)e (k)m(eyw)m(ord)i(is)g(v)m(ery)g(strict:)41 b(3)30 b(spaces)g(m)m(ust)f (follo)m(w)i(CON-)0 2147 y(TINUE)f(and)g(the)g(rest)h(of)f(the)h(line)g (is)f(copied)h(v)m(erbatim)g(to)g(the)g(FITS)e(\014le.)0 2308 y(The)i(start)h(of)g(the)f(optional)i(COMMENT)e(\014eld)g(m)m(ust) h(b)s(e)e(preceded)i(b)m(y)f("/",)i(whic)m(h)e(is)h(used)f(to)h (separate)g(it)0 2421 y(from)e(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(\014eld.)41 b(Exceptions)30 b(are)h(if)f(the)h(KEYW)m(ORD)g (name)f(\014eld)g(con)m(tains)h(COMMENT,)0 2533 y(HISTOR)-8 b(Y,)30 b(CONTINUE,)g(or)g(if)g(the)h(\014rst)f(8)g(c)m(haracters)i(of) f(the)f(template)i(line)f(are)g(blanks.)0 2694 y(More)c(than)f(one)h (Header-Data)i(Unit)e(\(HDU\))g(ma)m(y)g(b)s(e)f(de\014ned)f(in)h(the)h (template)h(\014le.)39 b(The)26 b(start)h(of)g(an)f(HDU)0 2806 y(de\014nition)k(is)g(denoted)h(with)f(a)h(SIMPLE)e(or)i(XTENSION) e(template)j(line:)0 2967 y(1\))i(SIMPLE)f(b)s(egins)g(a)h(Primary)g (HDU)g(de\014nition.)50 b(SIMPLE)33 b(ma)m(y)h(only)g(app)s(ear)f(as)h (the)g(\014rst)f(k)m(eyw)m(ord)h(in)0 3080 y(the)e(template)i(\014le.) 45 b(If)32 b(the)g(template)i(\014le)e(b)s(egins)f(with)h(XTENSION)f (instead)h(of)g(SIMPLE,)g(then)f(a)i(default)0 3192 y(empt)m(y)d (Primary)e(HDU)i(is)g(created,)h(and)d(the)i(template)h(is)e(then)g (assumed)f(to)i(de\014ne)f(the)h(k)m(eyw)m(ords)f(starting)0 3305 y(with)h(the)h(\014rst)e(extension)i(follo)m(wing)h(the)f(Primary) f(HDU.)0 3466 y(2\))35 b(XTENSION)e(marks)g(the)i(b)s(eginning)e(of)h (a)h(new)e(extension)i(HDU)f(de\014nition.)52 b(The)33 b(previous)h(HDU)h(will)0 3578 y(b)s(e)30 b(closed)h(at)g(this)f(p)s (oin)m(t)h(and)e(pro)s(cessing)i(of)f(the)h(next)f(extension)h(b)s (egins.)0 3918 y Fe(9.2)135 b(Auto-indexing)45 b(of)h(Keyw)l(ords)0 4169 y Fj(If)31 b(a)h(template)g(k)m(eyw)m(ord)g(name)f(ends)g(with)g (a)g("#")h(c)m(haracter,)i(it)e(is)f(said)g(to)h(b)s(e)f ('auto-indexed'.)44 b(Eac)m(h)32 b("#")0 4282 y(c)m(haracter)i(will)f (b)s(e)f(replaced)i(b)m(y)e(the)h(curren)m(t)g(in)m(teger)h(index)e(v) -5 b(alue,)34 b(whic)m(h)f(gets)g(reset)h(=)e(1)h(at)h(the)e(start)i (of)0 4395 y(eac)m(h)h(new)f(HDU)g(in)g(the)g(\014le)g(\(or)g(7)h(in)e (the)h(sp)s(ecial)h(case)g(of)f(a)g(GR)m(OUP)h(de\014nition\).)51 b(The)33 b(FIRST)g(indexed)0 4508 y(k)m(eyw)m(ord)c(in)f(eac)m(h)h (template)h(HDU)f(de\014nition)f(is)g(used)f(as)i(the)f('incremen)m (tor';)j(eac)m(h)e(subsequen)m(t)f(o)s(ccurrence)0 4620 y(of)k(this)f(SAME)g(k)m(eyw)m(ord)h(will)g(cause)g(the)g(index)f(v)-5 b(alue)32 b(to)g(b)s(e)f(incremen)m(ted.)44 b(This)31 b(b)s(eha)m(vior)g(can)h(b)s(e)f(rather)0 4733 y(subtle,)d(as)g (illustrated)h(in)e(the)h(follo)m(wing)h(examples)f(in)f(whic)m(h)h (the)g(TTYPE)e(k)m(eyw)m(ord)i(is)g(the)g(incremen)m(tor)g(in)0 4846 y(b)s(oth)i(cases:)95 5111 y Ff(TTYPE#)47 b(=)g(TIME)95 5224 y(TFORM#)g(=)g(1D)95 5337 y(TTYPE#)g(=)g(RATE)95 5449 y(TFORM#)g(=)g(1E)0 5714 y Fj(will)26 b(create)i(TTYPE1,)e(TF)m (ORM1,)i(TTYPE2,)f(and)e(TF)m(ORM2)i(k)m(eyw)m(ords.)40 b(But)26 b(if)g(the)g(template)h(lo)s(oks)f(lik)m(e,)p eop end %%Page: 115 121 TeXDict begin 115 120 bop 0 299 a Fh(9.3.)72 b(TEMPLA)-8 b(TE)30 b(P)-8 b(ARSER)30 b(DIRECTIVES)2028 b Fj(115)95 555 y Ff(TTYPE#)47 b(=)g(TIME)95 668 y(TTYPE#)g(=)g(RATE)95 781 y(TFORM#)g(=)g(1D)95 894 y(TFORM#)g(=)g(1E)0 1202 y Fj(this)31 b(results)f(in)h(a)g(FITS)f(\014les)h(with)f(TTYPE1,)h (TTYPE2,)g(TF)m(ORM2,)h(and)e(TF)m(ORM2,)i(whic)m(h)f(is)g(probably)0 1315 y(not)g(what)f(w)m(as)h(in)m(tended!)0 1706 y Fe(9.3)135 b(T)-11 b(emplate)46 b(P)l(arser)g(Directiv)l(es)0 1968 y Fj(In)29 b(addition)i(to)f(the)g(template)i(lines)e(whic)m(h)g (de\014ne)f(individual)h(k)m(eyw)m(ords,)g(the)g(template)i(parser)d (recognizes)0 2081 y(3)h(sp)s(ecial)h(directiv)m(es)g(whic)m(h)f(are)g (eac)m(h)h(preceded)f(b)m(y)f(the)h(bac)m(kslash)h(c)m(haracter:)90 b Ff(\\include,)45 b(\\group)p Fj(,)29 b(and)48 2194 y Ff(\\end)p Fj(.)0 2354 y(The)37 b('include')h(directiv)m(e)i(m)m(ust) d(b)s(e)h(follo)m(w)m(ed)h(b)m(y)f(a)g(\014lename.)63 b(It)38 b(forces)g(the)g(parser)f(to)i(temp)s(orarily)f(stop)0 2467 y(reading)d(the)g(curren)m(t)g(template)h(\014le)f(and)f(b)s(egin) h(reading)g(the)g(include)f(\014le.)55 b(Once)35 b(the)g(parser)f(reac) m(hes)i(the)0 2579 y(end)f(of)h(the)g(include)f(\014le)h(it)g(con)m (tin)m(ues)g(parsing)g(the)f(curren)m(t)h(template)h(\014le.)56 b(Include)35 b(\014les)h(can)g(b)s(e)f(nested,)0 2692 y(and)30 b(HDU)h(de\014nitions)f(can)g(span)g(m)m(ultiple)h(template)h (\014les.)0 2853 y(The)f(start)h(of)g(a)g(GR)m(OUP)h(de\014nition)e(is) h(denoted)g(with)f(the)h('group')g(directiv)m(e,)h(and)f(the)f(end)h (of)f(a)i(GR)m(OUP)0 2965 y(de\014nition)k(is)h(denoted)f(with)g(the)h ('end')f(directiv)m(e.)63 b(Eac)m(h)39 b(GR)m(OUP)e(con)m(tains)i(0)f (or)f(more)h(mem)m(b)s(er)f(blo)s(c)m(ks)0 3078 y(\(HDUs)44 b(or)f(GR)m(OUPs\).)79 b(Mem)m(b)s(er)42 b(blo)s(c)m(ks)i(of)f(t)m(yp)s (e)g(GR)m(OUP)g(can)g(con)m(tain)h(their)f(o)m(wn)g(mem)m(b)s(er)f(blo) s(c)m(ks.)0 3191 y(The)32 b(GR)m(OUP)g(de\014nition)g(itself)h(o)s (ccupies)g(one)f(FITS)g(\014le)g(HDU)h(of)f(sp)s(ecial)h(t)m(yp)s(e)f (\(GR)m(OUP)h(HDU\),)h(so)e(if)h(a)0 3304 y(template)f(sp)s(eci\014es)e (1)h(group)e(with)h(1)h(mem)m(b)s(er)f(HDU)h(lik)m(e:)0 3613 y Ff(\\group)0 3725 y(grpdescr)46 b(=)h('demo')0 3838 y(xtension)f(bintable)0 3951 y(#)h(this)g(bintable)f(has)h(0)g (cols,)f(0)i(rows)0 4064 y(\\end)0 4373 y Fj(then)30 b(the)h(parser)e(creates)j(a)f(FITS)f(\014le)g(with)g(3)h(HDUs)g(:)0 4681 y Ff(1\))47 b(dummy)g(PHDU)0 4794 y(2\))g(GROUP)g(HDU)f(\(has)h(1) h(member,)d(which)i(is)g(bintable)e(in)j(HDU)f(number)f(3\))0 4907 y(3\))h(bintable)f(\(member)g(of)h(GROUP)f(in)h(HDU)g(number)f (2\))0 5215 y Fj(T)-8 b(ec)m(hnically)32 b(sp)s(eaking,)e(the)f(GR)m (OUP)i(HDU)f(is)g(a)g(BINT)-8 b(ABLE)30 b(with)g(6)g(columns.)40 b(Applications)31 b(can)f(de\014ne)0 5328 y(additional)23 b(columns)f(in)f(a)i(GR)m(OUP)f(HDU)h(using)f(TF)m(ORMn)f(and)h(TTYPEn) f(\(where)g(n)h(is)g(7,)i(8,)h(....\))39 b(k)m(eyw)m(ords)0 5441 y(or)30 b(their)h(auto-indexing)g(equiv)-5 b(alen)m(ts.)0 5601 y(F)d(or)26 b(a)f(more)g(complicated)h(example)f(of)g(a)h (template)g(\014le)f(using)f(the)h(group)f(directiv)m(es,)k(lo)s(ok)d (at)g(the)g(sample.tpl)0 5714 y(\014le)30 b(that)h(is)g(included)e(in)i (the)f(CFITSIO)f(distribution.)p eop end %%Page: 116 122 TeXDict begin 116 121 bop 0 299 a Fj(116)2295 b Fh(CHAPTER)30 b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fe(9.4)135 b(F)-11 b(ormal)46 b(T)-11 b(emplate)45 b(Syn)l(tax)0 805 y Fj(The)30 b(template)i(syn)m(tax)f(can)f(formally)h(b)s(e)f (de\014ned)f(as)i(follo)m(ws:)191 1063 y Ff(TEMPLATE)45 b(=)j(BLOCK)e([)i(BLOCK)e(...)h(])334 1289 y(BLOCK)f(=)i({)f(HDU)g(|)h (GROUP)e(})334 1515 y(GROUP)g(=)i(\\GROUP)e([)h(BLOCK)g(...)g(])g (\\END)430 1741 y(HDU)f(=)i(XTENSION)d([)j(LINE)f(...)f(])i({)f (XTENSION)f(|)h(\\GROUP)f(|)i(\\END)f(|)g(EOF)g(})382 1967 y(LINE)f(=)i([)f(KEYWORD)f([)i(=)f(])h(])f([)g(VALUE)g(])g([)h(/)f (COMMENT)f(])191 2192 y(X)h(...)238 b(-)48 b(X)f(can)g(be)g(present)f (1)h(or)h(more)e(times)191 2305 y({)h(X)h(|)f(Y)h(})f(-)h(X)f(or)g(Y) 191 2418 y([)g(X)h(])238 b(-)48 b(X)f(is)g(optional)0 2676 y Fj(A)m(t)34 b(the)f(topmost)g(lev)m(el,)i(the)e(template)i (de\014nes)c(1)j(or)e(more)h(template)h(blo)s(c)m(ks.)49 b(Blo)s(c)m(ks)34 b(can)f(b)s(e)f(either)h(HDU)0 2789 y(\(Header)27 b(Data)h(Unit\))g(or)e(a)h(GR)m(OUP)-8 b(.)28 b(F)-8 b(or)27 b(eac)m(h)g(blo)s(c)m(k)g(the)g(parser)f(creates) i(1)f(\(or)g(more)f(for)h(GR)m(OUPs\))g(FITS)0 2902 y(\014le)j(HDUs.)0 3235 y Fe(9.5)135 b(Errors)0 3485 y Fj(In)24 b(general)h(the)f(\014ts)p 692 3485 28 4 v 33 w(execute)p 1019 3485 V 34 w(template\(\))i (function)e(tries)h(to)g(b)s(e)f(as)g(atomic)i(as)f(p)s(ossible,)g(so)f (either)h(ev)m(erything)0 3598 y(is)f(done)g(or)g(nothing)f(is)h(done.) 39 b(If)23 b(an)h(error)f(o)s(ccurs)h(during)f(parsing)g(of)h(the)g (template,)j(\014ts)p 3125 3598 V 33 w(execute)p 3452 3598 V 34 w(template\(\))0 3711 y(will)k(\(try)g(to\))h(delete)g(the)f (top)g(lev)m(el)h(BLOCK)e(\(with)h(all)g(its)h(c)m(hildren)e(if)h(an)m (y\))g(in)g(whic)m(h)f(the)h(error)f(o)s(ccurred,)0 3824 y(then)g(it)h(will)g(stop)f(reading)h(the)f(template)i(\014le)e(and)g (it)h(will)g(return)e(with)h(an)g(error.)0 4158 y Fe(9.6)135 b(Examples)0 4408 y Fj(1.)54 b(This)34 b(template)i(\014le)f(will)g (create)h(a)f(200)h(x)e(300)i(pixel)f(image,)j(with)c(4-b)m(yte)i(in)m (teger)g(pixel)f(v)-5 b(alues,)36 b(in)f(the)0 4521 y(primary)29 b(HDU:)95 4779 y Ff(SIMPLE)47 b(=)g(T)95 4891 y(BITPIX)g(=)g(32)95 5004 y(NAXIS)g(=)g(2)239 b(/)47 b(number)f(of)h(dimensions)95 5117 y(NAXIS1)g(=)g(100)95 b(/)47 b(length)f(of)h(first)g(axis)95 5230 y(NAXIS2)g(=)g(200)95 b(/)47 b(length)f(of)h(second)f(axis)95 5343 y(OBJECT)h(=)g(NGC)g(253)g(/)g(name)g(of)g(observed)f(object)0 5601 y Fj(The)35 b(allo)m(w)m(ed)i(v)-5 b(alues)36 b(of)f(BITPIX)g(are) h(8,)h(16,)h(32,)g(-32,)g(or)d(-64,)j(represen)m(ting,)f(resp)s(ectiv)m (ely)-8 b(,)39 b(8-bit)d(in)m(teger,)0 5714 y(16-bit)c(in)m(teger,)g (32-bit)f(in)m(teger,)h(32-bit)g(\015oating)f(p)s(oin)m(t,)g(or)f(64)h (bit)g(\015oating)g(p)s(oin)m(t)f(pixels.)p eop end %%Page: 117 123 TeXDict begin 117 122 bop 0 299 a Fh(9.6.)72 b(EXAMPLES)3039 b Fj(117)0 555 y(2.)39 b(T)-8 b(o)23 b(create)h(a)f(FITS)e(table,)26 b(the)c(template)i(\014rst)e(needs)g(to)i(include)e(XTENSION)g(=)g(T)-8 b(ABLE)23 b(or)f(BINT)-8 b(ABLE)0 668 y(to)31 b(de\014ne)e(whether)g (it)h(is)g(an)f(ASCI)s(I)g(or)g(binary)g(table,)i(and)f(NAXIS2)g(to)g (de\014ne)f(the)h(n)m(um)m(b)s(er)f(of)h(ro)m(ws)f(in)h(the)0 781 y(table.)50 b(Tw)m(o)34 b(template)g(lines)g(are)g(then)f(needed)f (to)i(de\014ne)f(the)g(name)h(\(TTYPEn\))e(and)h(FITS)g(data)h(format)0 894 y(\(TF)m(ORMn\))d(of)f(the)h(columns,)f(as)h(in)f(this)g(example:) 95 1154 y Ff(xtension)46 b(=)h(bintable)95 1267 y(naxis2)g(=)g(40)95 1380 y(ttype#)g(=)g(Name)95 1492 y(tform#)g(=)g(10a)95 1605 y(ttype#)g(=)g(Npoints)95 1718 y(tform#)g(=)g(j)95 1831 y(ttype#)g(=)g(Rate)95 1944 y(tunit#)g(=)g(counts/s)95 2057 y(tform#)g(=)g(e)0 2317 y Fj(The)26 b(ab)s(o)m(v)m(e)j(example)e (de\014nes)f(a)i(n)m(ull)f(primary)f(arra)m(y)h(follo)m(w)m(ed)i(b)m(y) e(a)g(40-ro)m(w)h(binary)e(table)i(extension)g(with)f(3)0 2430 y(columns)h(called)h('Name',)h('Np)s(oin)m(ts',)f(and)f('Rate',)i (with)e(data)h(formats)f(of)g('10A')i(\(ASCI)s(I)d(c)m(haracter)i (string\),)0 2543 y('1J')k(\(in)m(teger\))i(and)d('1E')i(\(\015oating)f (p)s(oin)m(t\),)h(resp)s(ectiv)m(ely)-8 b(.)50 b(Note)34 b(that)f(the)g(other)g(required)f(FITS)g(k)m(eyw)m(ords)0 2655 y(\(BITPIX,)37 b(NAXIS,)g(NAXIS1,)h(PCOUNT,)e(GCOUNT,)h(TFIELDS,)f (and)g(END\))h(do)g(not)g(need)f(to)h(b)s(e)f(ex-)0 2768 y(plicitly)j(de\014ned)d(in)i(the)f(template)i(b)s(ecause)f(their)g(v) -5 b(alues)38 b(can)g(b)s(e)f(inferred)f(from)i(the)f(other)h(k)m(eyw)m (ords)g(in)0 2881 y(the)d(template.)55 b(This)34 b(example)i(also)g (illustrates)f(that)h(the)f(templates)h(are)f(generally)h (case-insensitiv)m(e)h(\(the)0 2994 y(k)m(eyw)m(ord)29 b(names)g(and)g(TF)m(ORMn)f(v)-5 b(alues)30 b(are)f(con)m(v)m(erted)i (to)e(upp)s(er-case)g(in)f(the)h(FITS)g(\014le\))g(and)f(that)i(string) 0 3107 y(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(generally)g(do)f(not)h(need) f(to)h(b)s(e)f(enclosed)h(in)f(quotes.)p eop end %%Page: 118 124 TeXDict begin 118 123 bop 0 299 a Fj(118)2295 b Fh(CHAPTER)30 b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)p eop end %%Page: 119 125 TeXDict begin 119 124 bop 0 1225 a Fg(Chapter)65 b(10)0 1687 y Fm(Summary)76 b(of)i(all)f(FITSIO)0 1937 y(User-In)-6 b(terface)77 b(Subroutines)0 2429 y Fj(Error)29 b(Status)i(Routines)f (page)h(29)382 2696 y Ff(FTVERS\()46 b(>)h(version\))382 2809 y(FTGERR\(status,)d(>)j(errtext\))382 2922 y(FTGMSG\()f(>)h (errmsg\))382 3035 y(FTRPRT)f(\(stream,)f(>)j(status\))382 3147 y(FTPMSG\(errmsg\))382 3260 y(FTPMRK)382 3373 y(FTCMSG)382 3486 y(FTCMRK)0 3753 y Fj(FITS)30 b(File)h(Op)s(en)e(and)h(Close)h (Subroutines:)39 b(page)31 b(35)382 4020 y Ff (FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(blocksize,status\))382 4133 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 b(blocksize,status\))382 4246 y(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4359 y(FTDOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4472 y(FTTOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4585 y(FTIOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4698 y(FTREOPEN\(unit,)d(>)j(newunit,)f(status\)) 382 4811 y(FTINIT\(unit,filename,blo)o(cks)o(ize,)41 b(>)48 b(status\))382 4924 y(FTDKINIT\(unit,filename,b)o(loc)o(ksiz)o (e,)42 b(>)47 b(status\))382 5036 y(FTTPLT\(unit,)d(filename,)i (tplfilename,)e(>)j(status\))382 5149 y(FTFLUS\(unit,)d(>)k(status\)) 382 5262 y(FTCLOS\(unit,)c(>)k(status\))382 5375 y(FTDELT\(unit,)c(>)k (status\))382 5488 y(FTGIOU\()e(>)h(iounit,)f(status\))382 5601 y(FTFIOU\(iounit,)e(>)j(status\))0 5714 y(CFITS2Unit\(fitsfile)c (*ptr\))141 b(\(C)48 b(routine\))1882 5942 y Fj(119)p eop end %%Page: 120 126 TeXDict begin 120 125 bop 0 299 a Fj(120)281 b Fh(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(CUnit2FITS\(int)44 b(unit\))380 b(\(C)47 b(routine\))382 668 y(FTEXTN\(filename,)c(>)48 b(nhdu,)e(status\))382 781 y(FTFLNM\(unit,)e(>)k(filename,)d(status\)) 382 894 y(FTFLMD\(unit,)f(>)k(iomode,)e(status\))382 1007 y(FTURLT\(unit,)e(>)k(urltype,)d(status\))382 1120 y(FTIURL\(filename,)e(>)48 b(filetype,)d(infile,)h(outfile,)f(extspec,) h(filter,)716 1233 y(binspec,)f(colspec,)h(status\))382 1346 y(FTRTNM\(filename,)d(>)48 b(rootname,)d(status\))382 1458 y(FTEXIST\(filename,)e(>)k(exist,)f(status\))0 1695 y Fj(HDU-Lev)m(el)33 b(Op)s(erations:)40 b(page)31 b(38)382 1932 y Ff(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))382 2045 y(FTMRHD\(unit,nmove,)c(>)k(hdutype,status\))382 2158 y(FTGHDN\(unit,)d(>)k(nhdu\))382 2271 y(FTMNHD\(unit,)c(hdutype,)i (extname,)f(extver,)h(>)i(status\))382 2384 y(FTGHDT\(unit,)c(>)k (hdutype,)d(status\))382 2497 y(FTTHDU\(unit,)f(>)k(hdunum,)e(status\)) 382 2610 y(FTCRHD\(unit,)e(>)k(status\))382 2723 y (FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 2836 y(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o (ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 2949 y(status\))382 3061 y(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o (,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)f(>)48 b(status\))382 3174 y(FTRSIM\(unit,bitpix,naxis)o(,na)o(xes,)o(stat)o (us\))382 3287 y(FTDHDU\(unit,)c(>)k(hdutype,status\))382 3400 y(FTCPFL\(iunit,ounit,previ)o(ous)o(,)42 b(current,)j(following,)g (>)j(status\))382 3513 y(FTCOPY\(iunit,ounit,morek)o(eys)o(,)42 b(>)47 b(status\))382 3626 y(FTCPHD\(inunit,)d(outunit,)h(>)j(status\)) 382 3739 y(FTCPDT\(iunit,ounit,)42 b(>)48 b(status\))0 3976 y Fj(Subroutines)29 b(to)i(sp)s(ecify)f(or)g(mo)s(dify)g(the)g (structure)g(of)h(the)f(CHDU:)h(page)h(41)382 4213 y Ff(FTRDEF\(unit,)44 b(>)k(status\))93 b(\(DEPRECATED\))382 4326 y(FTPDEF\(unit,bitpix,naxis)o(,na)o(xes,)o(pcou)o(nt,)o(gcou)o (nt,)41 b(>)48 b(status\))93 b(\(DEPRECATED\))382 4439 y(FTADEF\(unit,rowlen,tfiel)o(ds,)o(tbco)o(l,tf)o(orm)o(,nro)o(ws)42 b(>)47 b(status\))94 b(\(DEPRECATED\))382 4551 y (FTBDEF\(unit,tfields,tfor)o(m,v)o(arid)o(at,n)o(row)o(s)42 b(>)47 b(status\))94 b(\(DEPRECATED\))382 4664 y(FTDDEF\(unit,bytlen,) 42 b(>)48 b(status\))93 b(\(DEPRECATED\))382 4777 y (FTPTHP\(unit,theap,)43 b(>)k(status\))0 5014 y Fj(Header)31 b(Space)f(and)g(P)m(osition)i(Subroutines:)39 b(page)31 b(43)382 5251 y Ff(FTHDEF\(unit,morekeys,)42 b(>)47 b(status\))382 5364 y(FTGHSP\(iunit,)d(>)j(keysexist,keysadd,status\))382 5477 y(FTGHPS\(iunit,)d(>)j(keysexist,key_no,status\))0 5714 y Fj(Read)31 b(or)f(W)-8 b(rite)32 b(Standard)d(Header)i (Subroutines:)39 b(page)31 b(43)p eop end %%Page: 121 127 TeXDict begin 121 126 bop 3764 299 a Fj(121)382 555 y Ff(FTPHPS\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 668 y(FTPHPR\(unit,simple,bitpi)o(x,n)o(axis)o(,nax)o(es,)o(pcou)o (nt,g)o(cou)o(nt,e)o(xten)o(d,)41 b(>)48 b(status\))382 781 y(FTGHPR\(unit,maxdim,)42 b(>)48 b(simple,bitpix,naxis,naxe)o(s,p)o (coun)o(t,gc)o(oun)o(t,ex)o(tend)o(,)716 894 y(status\))382 1007 y(FTPHTB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o (ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1120 y(status\))382 1233 y(FTGHTB\(unit,maxdim,)g(>)48 b(rowlen,nrows,tfields,tty)o(pe,)o(tbco)o(l,tf)o(orm)o(,tun)o(it,)716 1346 y(extname,status\))382 1458 y(FTPHBN\(unit,nrows,tfield)o(s,t)o (type)o(,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 1571 y(FTGHBN\(unit,maxdim,)42 b(>)48 b(nrows,tfields,ttype,tfor)o(m,t)o(unit)o(,ext)o(nam)o(e,va)o (rida)o(t,)716 1684 y(status\))0 1942 y Fj(W)-8 b(rite)32 b(Keyw)m(ord)e(Subroutines:)39 b(page)31 b(45)382 2199 y Ff(FTPREC\(unit,card,)43 b(>)k(status\))382 2312 y (FTPCOM\(unit,comment,)42 b(>)48 b(status\))382 2425 y(FTPHIS\(unit,history,)42 b(>)48 b(status\))382 2538 y(FTPDAT\(unit,)c(>)k(status\))382 2651 y(FTPKY[JKLS]\(unit,keyword)o (,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 2764 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o (omme)o(nt,)41 b(>)48 b(status\))382 2877 y(FTPKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 2990 y(FTPLSW\(unit,)d(>)k (status\))382 3103 y(FTPKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))382 3216 y(FTPKN[JKLS]\(unit,keyroot)o(,st)o(artn)o (o,no)o(_ke)o(ys,k)o(eyva)o(ls,)o(comm)o(ents)o(,)42 b(>)47 b(status\))382 3329 y(FTPKN[EDFG]\(unit,keyroot)o(,st)o(artn)o (o,no)o(_ke)o(ys,k)o(eyva)o(ls,)o(deci)o(mals)o(,co)o(mmen)o(ts,)41 b(>)907 3441 y(status\))382 3554 y(FTCPKYinunit,)j(outunit,)i(innum,)g (outnum,)f(keyroot,)h(>)h(status\))382 3667 y (FTPKYT\(unit,keyword,intv)o(al,)o(dblv)o(al,c)o(omm)o(ent,)41 b(>)48 b(status\))382 3780 y(FTPKTP\(unit,)c(filename,)i(>)h(status\)) 382 3893 y(FTPUNT\(unit,keyword,unit)o(s,)41 b(>)48 b(status\))0 4151 y Fj(Insert)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)31 b(47)382 4408 y Ff(FTIREC\(unit,key_no,card,)41 b(>)47 b(status\))382 4521 y(FTIKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o (men)o(t,)42 b(>)47 b(status\))382 4634 y(FTIKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 4747 y (FTIKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))382 4860 y(FTIKYU\(unit,keyword,comm)o(ent)o (,)42 b(>)47 b(status\))0 5118 y Fj(Read)31 b(Keyw)m(ord)f (Subroutines:)39 b(page)31 b(47)382 5375 y Ff(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))382 5488 y(FTGKYN\(unit,key_no,)42 b(>)48 b(keyword,value,comment,st)o(atu)o(s\))382 5601 y(FTGCRD\(unit,keyword,)42 b(>)48 b(card,status\))382 5714 y(FTGNXK\(unit,inclist,ninc)o(,ex)o(clis)o(t,ne)o(xc,)41 b(>)48 b(card,status\))p eop end %%Page: 122 128 TeXDict begin 122 127 bop 0 299 a Fj(122)281 b Fh(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTGKEY\(unit,keyword,)42 b(>)48 b(value,comment,status\))382 668 y(FTGKY[EDJKLS]\(unit,keywo)o (rd,)41 b(>)48 b(keyval,comment,status\))382 781 y (FTGKSL\(unit,keyword,)42 b(>)48 b(length,status\))382 894 y(FTGSKY\(unit,keyword,firs)o(tch)o(ar,m)o(axch)o(ar,)o(>)42 b(keyval,length,comment,st)o(atus)o(\))382 1007 y (FTGKN[EDJKLS]\(unit,keyro)o(ot,)o(star)o(tno,)o(max)o(_key)o(s,)g(>)47 b(keyvals,nfound,status\))382 1120 y(FTGKYT\(unit,keyword,)42 b(>)48 b(intval,dblval,comment,s)o(tat)o(us\))382 1233 y(FTGUNT\(unit,keyword,)42 b(>)48 b(units,status\))0 1489 y Fj(Mo)s(dify)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)31 b(49)382 1745 y Ff(FTMREC\(unit,key_no,card,)41 b(>)47 b(status\))382 1858 y(FTMCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))382 1971 y(FTMNAM\(unit,oldkey,keywo)o(rd,)41 b(>)48 b(status\))382 2084 y(FTMCOM\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))382 2197 y(FTMKY[JKLS]\(unit,keyword)o(,ke)o(yval)o (,com)o(men)o(t,)42 b(>)47 b(status\))382 2310 y (FTMKLS\(unit,keyword,keyv)o(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 2422 y(FTMKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o (ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))382 2535 y(FTMKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 2792 y Fj(Up)s(date)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)32 b(50)382 3048 y Ff(FTUCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))382 3161 y(FTUKY[JKLS]\(unit,keyword)o(,ke)o(yval)o (,com)o(men)o(t,)42 b(>)47 b(status\))382 3274 y (FTUKLS\(unit,keyword,keyv)o(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 3386 y(FTUKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o (ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))382 3499 y(FTUKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 3756 y Fj(Delete)33 b(Keyw)m(ord)d(Subroutines:)39 b(page)31 b(51)382 4012 y Ff(FTDREC\(unit,key_no,)42 b(>)48 b(status\))382 4125 y(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 4381 y Fj(De\014ne)31 b(Data)h(Scaling)f(P)m(arameters)g(and)f(Unde\014ned)f (Pixel)i(Flags:)42 b(page)31 b(51)382 4637 y Ff (FTPSCL\(unit,bscale,bzero)o(,)42 b(>)47 b(status\))382 4750 y(FTTSCL\(unit,colnum,tscal)o(,tz)o(ero,)41 b(>)48 b(status\))382 4863 y(FTPNUL\(unit,blank,)43 b(>)k(status\))382 4976 y(FTSNUL\(unit,colnum,snull)41 b(>)47 b(status\))382 5089 y(FTTNUL\(unit,colnum,tnull)41 b(>)47 b(status\))0 5345 y Fj(FITS)30 b(Primary)f(Arra)m(y)i(or)f(IMA)m(GE)i(Extension)e (I/O)h(Subroutines:)39 b(page)31 b(52)382 5601 y Ff(FTGIDT\(unit,)44 b(>)k(bitpix,status\))382 5714 y(FTGIET\(unit,)c(>)k(bitpix,status\))p eop end %%Page: 123 129 TeXDict begin 123 128 bop 3764 299 a Fj(123)382 555 y Ff(FTGIDM\(unit,)44 b(>)k(naxis,status\))382 668 y(FTGISZ\(unit,)c (maxdim,)i(>)i(naxes,status\))382 781 y(FTGIPR\(unit,)c(maxdim,)i(>)i (bitpix,naxis,naxes,stat)o(us\))382 894 y(FTPPR[BIJKED]\(unit,group)o (,fp)o(ixel)o(,nel)o(eme)o(nts,)o(valu)o(es,)41 b(>)48 b(status\))382 1007 y(FTPPN[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o (eme)o(nts,)o(valu)o(es,)o(null)o(val)41 b(>)48 b(status\))382 1120 y(FTPPRU\(unit,group,fpixel)o(,ne)o(leme)o(nts,)41 b(>)47 b(status\))382 1233 y(FTGPV[BIJKED]\(unit,group)o(,fp)o(ixel)o (,nel)o(eme)o(nts,)o(null)o(val)o(,)42 b(>)47 b(values,anyf,status\)) 382 1346 y(FTGPF[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,) 41 b(>)48 b(values,flagvals,anyf,st)o(atu)o(s\))382 1458 y(FTPGP[BIJKED]\(unit,group)o(,fp)o(arm,)o(npar)o(m,v)o(alue)o(s,)42 b(>)47 b(status\))382 1571 y(FTGGP[BIJKED]\(unit,group)o(,fp)o(arm,)o (npar)o(m,)41 b(>)48 b(values,status\))382 1684 y (FTP2D[BIJKED]\(unit,group)o(,di)o(m1,n)o(axis)o(1,n)o(axis)o(2,im)o (age)o(,)42 b(>)47 b(status\))382 1797 y(FTP3D[BIJKED]\(unit,group)o (,di)o(m1,d)o(im2,)o(nax)o(is1,)o(naxi)o(s2,)o(naxi)o(s3,c)o(ube)o(,)42 b(>)47 b(status\))382 1910 y(FTG2D[BIJKED]\(unit,group)o(,nu)o(llva)o (l,di)o(m1,)o(naxi)o(s1,n)o(axi)o(s2,)41 b(>)48 b(image,anyf,status\)) 382 2023 y(FTG3D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o(dim2)o (,nax)o(is1)o(,nax)o(is2,)o(nax)o(is3,)41 b(>)1002 2136 y(cube,anyf,status\))382 2249 y(FTPSS[BIJKED]\(unit,group)o(,na)o(xis,) o(naxe)o(s,f)o(pixe)o(ls,l)o(pix)o(els,)o(arra)o(y,)g(>)48 b(status\))382 2362 y(FTGSV[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o (s,f)o(pixe)o(ls,l)o(pix)o(els,)o(incs)o(,nu)o(llva)o(l,)42 b(>)1002 2475 y(array,anyf,status\))382 2588 y (FTGSF[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o(ls,l)o (pix)o(els,)o(incs)o(,)g(>)1002 2700 y(array,flagvals,anyf,statu)o(s\)) 0 2974 y Fj(T)-8 b(able)31 b(Column)e(Information)i(Subroutines:)39 b(page)31 b(56)382 3247 y Ff(FTGNRW\(unit,)44 b(>)k(nrows,)e(status\)) 382 3360 y(FTGNCL\(unit,)e(>)k(ncols,)e(status\))382 3473 y(FTGCNO\(unit,casesen,colt)o(emp)o(late)o(,)c(>)47 b(colnum,status\))382 3586 y(FTGCNN\(unit,casesen,colt)o(emp)o(late)o (,)42 b(>)47 b(colnam,colnum,status\))382 3699 y(FTGTCL\(unit,colnum,) 42 b(>)48 b(datacode,repeat,width,st)o(atu)o(s\))382 3812 y(FTEQTY\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu) o(s\))382 3925 y(FTGCDW\(unit,colnum,)42 b(>)48 b(dispwidth,status\)) 382 4038 y(FTGACL\(unit,colnum,)42 b(>)716 4151 y (ttype,tbcol,tunit,tform,)o(tsca)o(l,t)o(zero)o(,snu)o(ll,)o(tdis)o (p,st)o(atu)o(s\))382 4264 y(FTGBCL\(unit,colnum,)g(>)716 4377 y(ttype,tunit,datatype,rep)o(eat,)o(tsc)o(al,t)o(zero)o(,tn)o (ull,)o(tdis)o(p,s)o(tatu)o(s\))382 4489 y(FTPTDM\(unit,colnum,naxis)o (,na)o(xes,)f(>)48 b(status\))382 4602 y(FTGTDM\(unit,colnum,maxdi)o (m,)41 b(>)48 b(naxis,naxes,status\))382 4715 y (FTDTDM\(unit,tdimstr,coln)o(um,)o(maxd)o(im,)41 b(>)48 b(naxis,naxes,)c(status\))382 4828 y(FTGRSZ\(unit,)g(>)k (nrows,status\))0 5102 y Fj(Lo)m(w-Lev)m(el)32 b(T)-8 b(able)31 b(Access)h(Subroutines:)39 b(page)31 b(58)382 5375 y Ff(FTGTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(string,status\))382 5488 y(FTPTBS\(unit,frow,startch)o(ar,)o (ncha)o(rs,s)o(tri)o(ng,)41 b(>)48 b(status\))382 5601 y(FTGTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(array,status\))382 5714 y(FTPTBB\(unit,frow,startch)o(ar,)o(ncha)o (rs,a)o(rra)o(y,)42 b(>)47 b(status\))p eop end %%Page: 124 130 TeXDict begin 124 129 bop 0 299 a Fj(124)281 b Fh(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fj(Edit)g(Ro)m(ws)h(or)f(Columns)g (page)h(59)382 813 y Ff(FTIROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 926 y(FTDROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 1039 y(FTDRRG\(unit,rowrange,)42 b(>)47 b(status\))382 1152 y(FTDRWS\(unit,rowlist,nrow)o(s,)41 b(>)48 b(status\))382 1264 y(FTICOL\(unit,colnum,ttype)o(,tf)o(orm,)41 b(>)48 b(status\))382 1377 y(FTICLS\(unit,colnum,ncols)o(,tt)o(ype,)o (tfor)o(m,)41 b(>)48 b(status\))382 1490 y(FTMVEC\(unit,colnum,newve)o (cle)o(n,)42 b(>)47 b(status\))382 1603 y(FTDCOL\(unit,colnum,)42 b(>)48 b(status\))382 1716 y(FTCPCL\(inunit,outunit,in)o(col)o(num,)o (outc)o(oln)o(um,c)o(reat)o(eco)o(l,)42 b(>)47 b(status\);)0 1974 y Fj(Read)31 b(and)e(W)-8 b(rite)32 b(Column)e(Data)i(Routines)e (page)h(60)382 2231 y Ff(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,) o(fel)o(em,n)o(elem)o(ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))382 2344 y(FTPCN[BIJKED]\(unit,colnu)o(m,f)o(row,)o(fele)o (m,n)o(elem)o(ents)o(,va)o(lues)o(,nul)o(lva)o(l)42 b(>)47 b(status\))382 2457 y(FTPCLX\(unit,colnum,frow,)o(fbi)o(t,nb)o(it,l)o (ray)o(,)42 b(>)47 b(status\))382 2570 y(FTPCLU\(unit,colnum,frow,)o (fel)o(em,n)o(elem)o(ent)o(s,)42 b(>)47 b(status\))382 2683 y(FTGCL\(unit,colnum,frow,f)o(ele)o(m,ne)o(leme)o(nts)o(,)42 b(>)47 b(values,status\))382 2796 y(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o (m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o(nts)o(,nul)o(lval)o(,)42 b(>)1098 2909 y(values,anyf,status\))382 3022 y (FTGCF[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o (ent)o(s,)g(>)1193 3135 y(values,flagvals,anyf,stat)o(us\))382 3247 y(FTGSV[BIJKED]\(unit,colnu)o(m,n)o(axis)o(,nax)o(es,)o(fpix)o (els,)o(lpi)o(xels)o(,inc)o(s,n)o(ullv)o(al,)f(>)1002 3360 y(array,anyf,status\))382 3473 y(FTGSF[BIJKED]\(unit,colnu)o(m,n)o (axis)o(,nax)o(es,)o(fpix)o(els,)o(lpi)o(xels)o(,inc)o(s,)g(>)1002 3586 y(array,flagvals,anyf,statu)o(s\))382 3699 y (FTGCX\(unit,colnum,frow,f)o(bit)o(,nbi)o(t,)h(>)47 b(lray,status\))382 3812 y(FTGCX[IJD]\(unit,colnum,f)o(row)o(,nro)o(ws,f)o(bit)o(,nbi)o(t,) 42 b(>)47 b(array,status\))382 3925 y(FTGDES\(unit,colnum,rownu)o(m,)41 b(>)48 b(nelements,offset,status\))382 4038 y (FTPDES\(unit,colnum,rownu)o(m,n)o(elem)o(ents)o(,of)o(fset)o(,)42 b(>)47 b(status\))0 4295 y Fj(Ro)m(w)31 b(Selection)h(and)d(Calculator) j(Routines:)41 b(page)31 b(64)382 4553 y Ff(FTFROW\(unit,expr,firstro)o (w,)41 b(nrows,)47 b(>)g(n_good_rows,)d(row_status,)h(status\))382 4666 y(FTFFRW\(unit,)f(expr,)j(>)g(rownum,)f(status\))382 4779 y(FTSROW\(inunit,)e(outunit,)h(expr,)i(>)g(status)f(\))382 4892 y(FTCROW\(unit,datatype,exp)o(r,f)o(irst)o(row,)o(nel)o(emen)o (ts,n)o(ulv)o(al,)41 b(>)620 5005 y(array,anynul,status\))382 5118 y(FTCALC\(inunit,)j(expr,)i(outunit,)g(parName,)f(parInfo,)h(>)h (status\))382 5230 y(FTCALC_RNG\(inunit,)c(expr,)j(outunit,)g(parName,) f(parInfo,)573 5343 y(nranges,)g(firstrow,)h(lastrow,)f(>)j(status\)) 382 5456 y(FTTEXP\(unit,)c(expr,)j(>)g(datatype,)e(nelem,)h(naxis,)h (naxes,)f(status\))0 5714 y Fj(Celestial)32 b(Co)s(ordinate)f(System)f (Subroutines:)39 b(page)31 b(65)p eop end %%Page: 125 131 TeXDict begin 125 130 bop 3764 299 a Fj(125)382 555 y Ff(FTGICS\(unit,)44 b(>)k(xrval,yrval,xrpix,yrpix)o(,xin)o(c,yi)o(nc,)o (rot,)o(coor)o(dty)o(pe,s)o(tatu)o(s\))382 668 y (FTGTCS\(unit,xcol,ycol,)42 b(>)716 781 y(xrval,yrval,xrpix,yrpix,)o (xinc)o(,yi)o(nc,r)o(ot,c)o(oor)o(dtyp)o(e,st)o(atu)o(s\))382 894 y(FTWLDP\(xpix,ypix,xrval,y)o(rva)o(l,xr)o(pix,)o(yrp)o(ix,x)o (inc,)o(yin)o(c,ro)o(t,)1241 1007 y(coordtype,)j(>)i (xpos,ypos,status\))382 1120 y(FTXYPX\(xpos,ypos,xrval,y)o(rva)o(l,xr)o (pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 1233 y(coordtype,)e(>)i(xpix,ypix,status\))0 1490 y Fj(File)32 b(Chec)m(ksum)d(Subroutines:)40 b(page)31 b(67)382 1748 y Ff(FTPCKS\(unit,)44 b(>)k(status\))382 1861 y(FTUCKS\(unit,)c(>)k (status\))382 1974 y(FTVCKS\(unit,)c(>)k(dataok,hduok,status\))382 2087 y(FTGCKS\(unit,)c(>)k(datasum,hdusum,status\))382 2199 y(FTESUM\(sum,complement,)42 b(>)47 b(checksum\))382 2312 y(FTDSUM\(checksum,compleme)o(nt,)41 b(>)48 b(sum\))0 2683 y Fj(Time)30 b(and)g(Date)i(Utilit)m(y)h(Subroutines:)39 b(page)31 b(68)382 2940 y Ff(FTGSDT\()46 b(>)h(day,)g(month,)f(year,)g (status)g(\))382 3053 y(FTGSTM\(>)f(datestr,)h(timeref,)f(status\))382 3166 y(FTDT2S\()h(year,)g(month,)g(day,)h(>)g(datestr,)f(status\))382 3279 y(FTTM2S\()g(year,)g(month,)g(day,)h(hour,)f(minute,)g(second,)g (decimals,)764 3392 y(>)h(datestr,)f(status\))382 3505 y(FTS2DT\(datestr,)d(>)48 b(year,)e(month,)g(day,)h(status\))382 3618 y(FTS2TM\(datestr,)c(>)48 b(year,)e(month,)g(day,)h(hour,)f (minute,)g(second,)g(status\))0 3876 y Fj(General)31 b(Utilit)m(y)i(Subroutines:)39 b(page)31 b(69)382 4133 y Ff(FTGHAD\(unit,)44 b(>)k(curaddr,nextaddr\))382 4246 y(FTUPCH\(string\))382 4359 y(FTCMPS\(str_template,stri)o(ng,)o(case)o (sen,)41 b(>)47 b(match,exact\))382 4472 y(FTTKEY\(keyword,)c(>)48 b(status\))382 4585 y(FTTREC\(card,)c(>)k(status\))382 4698 y(FTNCHK\(unit,)c(>)k(status\))382 4811 y(FTGKNM\(unit,)c(>)k (keyword,)d(keylength,)g(status\))382 4924 y(FTMKKY\(keyword,)e (value,comment,)h(>)k(card,)e(status\))382 5036 y(FTPSVC\(card,)e(>)k (value,comment,status\))382 5149 y(FTKEYN\(keyroot,seq_no,)42 b(>)47 b(keyword,status\))382 5262 y(FTNKEY\(seq_no,keyroot,)42 b(>)47 b(keyword,status\))382 5375 y(FTDTYP\(value,)d(>)j (dtype,status\))382 5488 y(class)f(=)i(FTGKCL\(card\))382 5601 y(FTASFM\(tform,)c(>)j(datacode,width,decimals,st)o(atus)o(\))382 5714 y(FTBNFM\(tform,)d(>)j(datacode,repeat,width,stat)o(us\))p eop end %%Page: 126 132 TeXDict begin 126 131 bop 0 299 a Fj(126)281 b Fh(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Ff(FTGABC\(tfields,tform,spa)o (ce,)41 b(>)48 b(rowlen,tbcol,status\))382 668 y(FTGTHD\(template,)43 b(>)48 b(card,hdtype,status\))382 781 y(FTRWRG\(rowlist,)43 b(maxrows,)j(maxranges,)f(>)i(numranges,)e(rangemin,)716 894 y(rangemax,)g(status\))p eop end %%Page: 127 133 TeXDict begin 127 132 bop 0 1225 a Fg(Chapter)65 b(11)0 1687 y Fm(P)-6 b(arameter)77 b(De\014nitions)0 2180 y Ff(anyf)47 b(-)g(\(logical\))e(set)i(to)g(TRUE)g(if)g(any)g(of)g(the)g (returned)f(data)g(values)h(are)f(undefined)0 2293 y(array)g(-)i(\(any) e(datatype)g(except)g(character\))f(array)h(of)i(bytes)e(to)h(be)g (read)g(or)g(written.)0 2406 y(bitpix)f(-)i(\(integer\))d(bits)h(per)h (pixel:)f(8,)i(16,)f(32,)f(-32,)h(or)g(-64)0 2518 y(blank)f(-)i (\(integer\))d(value)h(used)h(for)g(undefined)e(pixels)h(in)i(integer)d (primary)h(array)0 2631 y(blank)g(-)i(\(integer*8\))d(value)h(used)h (for)f(undefined)g(pixels)g(in)h(integer)f(primary)g(array)0 2744 y(blocksize)f(-)j(\(integer\))d(2880-byte)g(logical)h(record)g (blocking)g(factor)477 2857 y(\(if)h(0)h(<)f(blocksize)e(<)j(11\))f(or) g(the)g(actual)f(block)g(size)h(in)g(bytes)477 2970 y(\(if)g(10)g(<)h (blocksize)d(<)j(28800\).)93 b(As)47 b(of)g(version)f(3.3)h(of)g (FITSIO,)477 3083 y(blocksizes)e(greater)h(than)h(2880)f(are)h(no)g (longer)g(supported.)0 3196 y(bscale)f(-)i(\(double)d(precision\))g (scaling)h(factor)g(for)h(the)g(primary)f(array)0 3309 y(bytlen)g(-)i(\(integer\))d(length)h(of)h(the)g(data)g(unit,)f(in)h (bytes)0 3422 y(bzero)f(-)i(\(double)e(precision\))f(zero)h(point)h (for)g(primary)e(array)i(scaling)0 3535 y(card)g(-)g(\(character*80\))d (header)i(record)g(to)h(be)h(read)e(or)h(written)0 3648 y(casesen)f(-)h(\(logical\))f(will)g(string)g(matching)g(be)h(case)g (sensitive?)0 3760 y(checksum)f(-)h(\(character*16\))d(encoded)i (checksum)f(string)0 3873 y(colname)h(-)h(\(character\))e(ASCII)h(name) h(of)g(the)g(column)0 3986 y(colnum)f(-)i(\(integer\))d(number)h(of)h (the)g(column)f(\(first)g(column)g(=)i(1\))0 4099 y(coltemplate)d(-)i (\(character\))e(template)g(string)i(to)g(be)g(matched)f(to)h(column)f (names)0 4212 y(comment)g(-)h(\(character\))e(the)i(keyword)f(comment)g (field)0 4325 y(comments)g(-)h(\(character)e(array\))h(keyword)g (comment)g(fields)0 4438 y(compid)g(-)i(\(integer\))d(the)i(type)f(of)i (computer)d(that)i(the)g(program)e(is)j(running)d(on)0 4551 y(complement)g(-)i(\(logical\))f(should)g(the)h(checksum)e(be)i (complemented?)0 4664 y(coordtype)e(-)j(\(character\))c(type)j(of)g (coordinate)e(projection)g(\(-SIN,)h(-TAN,)h(-ARC,)477 4777 y(-NCP,)g(-GLS,)f(-MER,)g(or)i(-AIT\))0 4890 y(cube)f(-)g(3D)g (data)g(cube)g(of)g(the)g(appropriate)d(datatype)0 5002 y(curaddr)i(-)h(\(integer\))f(starting)f(address)h(\(in)h(bytes\))f(of) h(the)g(CHDU)0 5115 y(current)f(-)h(\(integer\))f(if)h(not)g(equal)f (to)h(0,)g(copy)g(the)g(current)f(HDU)0 5228 y(datacode)g(-)h (\(integer\))e(symbolic)h(code)g(of)i(the)f(binary)f(table)g(column)g (datatype)0 5341 y(dataok)g(-)i(\(integer\))d(was)i(the)g(data)f(unit)h (verification)d(successful)h(\(=1\))i(or)430 5454 y(not)f(\(=)i(-1\).) 94 b(Equals)46 b(zero)h(if)g(the)g(DATASUM)f(keyword)f(is)j(not)f (present.)0 5567 y(datasum)f(-)h(\(double)f(precision\))f(32-bit)h(1's) h(complement)e(checksum)h(for)h(the)f(data)h(unit)0 5680 y(datatype)f(-)h(\(character\))e(datatype)g(\(format\))h(of)h(the)g (binary)f(table)g(column)1882 5942 y Fj(127)p eop end %%Page: 128 134 TeXDict begin 128 133 bop 0 299 a Fj(128)1779 b Fh(CHAPTER)30 b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Ff(datestr)94 b(-)47 b(\(string\))f(FITS)g(date/time)f(string:)h ('YYYY-MM-DDThh:mm:ss.ddd')o(,)525 668 y('YYYY-MM-dd',)e(or)j ('dd/mm/yy')0 781 y(day)g(-)g(\(integer\))f(current)f(day)i(of)h(the)e (month)0 894 y(dblval)g(-)i(\(double)d(precision\))g(fractional)g(part) i(of)g(the)g(keyword)f(value)0 1007 y(decimals)g(-)h(\(integer\))e (number)h(of)i(decimal)d(places)h(to)i(be)f(displayed)0 1120 y(dim1)g(-)g(\(integer\))e(actual)h(size)h(of)g(the)g(first)g (dimension)e(of)i(the)g(image)f(or)h(cube)g(array)0 1233 y(dim2)g(-)g(\(integer\))e(actual)h(size)h(of)g(the)g(second)f (dimension)g(of)h(the)g(cube)f(array)0 1346 y(dispwidth)f(-)j (\(integer\))d(-)i(the)g(display)f(width)h(\(length)e(of)j(string\))d (for)i(a)h(column)0 1458 y(dtype)e(-)i(\(character\))d(datatype)g(of)i (the)g(keyword)f(\('C',)g('L',)h('I',)94 b(or)48 b('F'\))764 1571 y(C)f(=)h(character)d(string)764 1684 y(L)i(=)h(logical)764 1797 y(I)f(=)h(integer)764 1910 y(F)f(=)h(floating)d(point)h(number)0 2023 y(errmsg)g(-)i(\(character*80\))43 b(oldest)k(error)f(message)g (on)h(the)g(internal)e(stack)0 2136 y(errtext)h(-)h(\(character*30\))d (descriptive)h(error)h(message)g(corresponding)e(to)j(error)g(number)0 2249 y(casesen)f(-)h(\(logical\))f(true)g(if)h(column)f(name)h (matching)f(is)h(case)f(sensitive)0 2362 y(exact)g(-)i(\(logical\))d (do)i(the)g(strings)f(match)g(exactly,)g(or)h(were)g(wildcards)e(used?) 0 2475 y(exclist)94 b(\(character)45 b(array\))h(list)g(of)h(names)g (to)g(be)g(excluded)f(from)g(search)0 2588 y(exists)142 b(-)47 b(flag)g(indicating)e(whether)g(the)i(file)g(or)g(compressed)e (file)i(exists)f(on)h(disk)0 2700 y(extend)f(-)i(\(logical\))d(true)h (if)i(there)e(may)h(be)g(extensions)e(following)g(the)i(primary)f(data) 0 2813 y(extname)g(-)h(\(character\))e(value)h(of)i(the)e(EXTNAME)g (keyword)g(\(if)h(not)g(blank\))0 2926 y(fbit)g(-)g(\(integer\))e (first)i(bit)g(in)g(the)g(field)f(to)h(be)g(read)g(or)g(written)0 3039 y(felem)f(-)i(\(integer\))d(first)h(pixel)h(of)g(the)g(element)f (vector)g(\(ignored)f(for)i(ASCII)g(tables\))0 3152 y(filename)f(-)h (\(character\))e(name)h(of)i(the)e(FITS)h(file)0 3265 y(flagvals)f(-)h(\(logical)f(array\))g(True)g(if)h(corresponding)e (data)h(element)g(is)h(undefined)0 3378 y(following)e(-)j(\(integer\))d (if)i(not)g(equal)f(to)i(0,)f(copy)f(all)h(following)f(HDUs)g(in)h(the) g(input)g(file)0 3491 y(fparm)f(-)i(\(integer\))d(sequence)h(number)g (of)h(the)g(first)f(group)h(parameter)e(to)i(read)g(or)g(write)0 3604 y(fpixel)f(-)i(\(integer\))d(the)i(first)f(pixel)g(position)0 3717 y(fpixels)g(-)h(\(integer)f(array\))g(the)h(first)f(included)g (pixel)g(in)h(each)g(dimension)0 3830 y(frow)g(-)g(\(integer\))e (beginning)h(row)h(number)f(\(first)g(row)h(of)g(table)f(=)i(1\))0 3942 y(frowll)e(-)i(\(integer*8\))c(beginning)i(row)g(number)h(\(first) f(row)h(of)g(table)f(=)i(1\))0 4055 y(gcount)e(-)i(\(integer\))d(value) h(of)h(the)g(GCOUNT)f(keyword)g(\(usually)g(=)h(1\))0 4168 y(group)f(-)i(\(integer\))d(sequence)h(number)g(of)h(the)g(data)f (group)h(\(=0)g(for)g(non-grouped)d(data\))0 4281 y(hdtype)i(-)i (\(integer\))d(header)h(record)g(type:)g(-1=delete;)93 b(0=append)46 b(or)h(replace;)907 4394 y(1=append;)e(2=this)h(is)h(the) g(END)g(keyword)0 4507 y(hduok)f(-)i(\(integer\))d(was)i(the)g(HDU)g (verification)d(successful)h(\(=1\))i(or)430 4620 y(not)f(\(=)i(-1\).) 94 b(Equals)46 b(zero)h(if)g(the)g(CHECKSUM)e(keyword)h(is)h(not)g (present.)0 4733 y(hdusum)f(-)i(\(double)d(precision\))g(32)j(bit)e (1's)h(complement)e(checksum)h(for)h(the)g(entire)f(CHDU)0 4846 y(hdutype)g(-)h(\(integer\))f(type)g(of)h(HDU:)g(0)g(=)h(primary)e (array)g(or)h(IMAGE,)f(1)i(=)f(ASCII)g(table,)907 4959 y(2)g(=)h(binary)e(table,)g(-1)h(=)h(any)e(HDU)h(type)g(or)g(unknown)f (type)0 5072 y(history)g(-)h(\(character\))e(the)i(HISTORY)f(keyword)g (comment)f(string)0 5185 y(hour)i(-)g(\(integer\))e(hour)i(from)g(0)g (-)h(23)0 5297 y(image)e(-)i(2D)f(image)f(of)i(the)e(appropriate)f (datatype)0 5410 y(inclist)94 b(\(character)45 b(array\))h(list)g(of)h (names)g(to)g(be)g(included)f(in)h(search)0 5523 y(incs)g(-)g (\(integer)f(array\))g(sampling)f(interval)h(for)h(pixels)f(in)h(each)g (FITS)f(dimension)0 5636 y(intval)g(-)i(\(integer\))d(integer)h(part)g (of)h(the)g(keyword)f(value)p eop end %%Page: 129 135 TeXDict begin 129 134 bop 3764 299 a Fj(129)0 555 y Ff(iounit)46 b(-)i(\(integer\))d(value)h(of)h(an)h(unused)e(I/O)h(unit)f(number)0 668 y(iunit)g(-)i(\(integer\))d(logical)h(unit)h(number)f(associated)f (with)h(the)h(input)g(FITS)f(file,)h(1-300)0 781 y(key_no)f(-)i (\(integer\))d(sequence)g(number)h(\(starting)g(with)g(1\))i(of)f(the)g (keyword)e(record)0 894 y(keylength)g(-)j(\(integer\))d(length)h(of)h (the)g(keyword)f(name)0 1007 y(keyroot)g(-)h(\(character\))e(root)i (string)f(for)h(the)g(keyword)e(name)0 1120 y(keysadd)h(-\(integer\))f (number)h(of)h(new)g(keyword)f(records)g(which)g(can)h(fit)g(in)g(the)g (CHU)0 1233 y(keysexist)e(-)j(\(integer\))d(number)h(of)h(existing)f (keyword)g(records)f(in)j(the)f(CHU)0 1346 y(keyval)f(-)i(value)e(of)h (the)g(keyword)f(in)h(the)g(appropriate)e(datatype)0 1458 y(keyvals)h(-)h(\(array\))f(value)g(of)i(the)f(keywords)e(in)i (the)g(appropriate)e(datatype)0 1571 y(keyword)h(-)h(\(character*8\))d (name)j(of)g(a)h(keyword)0 1684 y(lray)f(-)g(\(logical)f(array\))g (array)g(of)h(logical)f(values)g(corresponding)e(to)k(the)e(bit)h (array)0 1797 y(lpixels)f(-)h(\(integer)f(array\))g(the)h(last)f (included)g(pixel)g(in)i(each)e(dimension)0 1910 y(match)g(-)i (\(logical\))d(do)i(the)g(2)h(strings)d(match?)0 2023 y(maxdim)h(-)i(\(integer\))d(dimensioned)g(size)h(of)h(the)g(NAXES,)f (TTYPE,)g(TFORM)h(or)g(TUNIT)f(arrays)0 2136 y(max_keys)g(-)h (\(integer\))e(maximum)h(number)g(of)h(keywords)f(to)h(search)f(for)0 2249 y(minute)g(-)i(\(integer\))d(minute)h(of)h(an)g(hour)g(\(0)g(-)h (59\))0 2362 y(month)e(-)i(\(integer\))d(current)h(month)g(of)h(the)g (year)g(\(1)g(-)h(12\))0 2475 y(morekeys)e(-)h(\(integer\))e(will)i (leave)f(space)h(in)g(the)g(header)f(for)h(this)f(many)h(more)g (keywords)0 2588 y(naxes)f(-)i(\(integer)d(array\))h(size)h(of)g(each)g (dimension)e(in)i(the)g(FITS)g(array)0 2700 y(naxesll)f(-)h (\(integer*8)e(array\))h(size)h(of)g(each)g(dimension)e(in)i(the)g (FITS)g(array)0 2813 y(naxis)f(-)i(\(integer\))d(number)h(of)h (dimensions)e(in)j(the)e(FITS)h(array)0 2926 y(naxis1)f(-)i (\(integer\))d(length)h(of)h(the)g(X/first)f(axis)g(of)i(the)f(FITS)f (array)0 3039 y(naxis2)g(-)i(\(integer\))d(length)h(of)h(the)g (Y/second)f(axis)g(of)h(the)g(FITS)g(array)0 3152 y(naxis3)f(-)i (\(integer\))d(length)h(of)h(the)g(Z/third)f(axis)g(of)i(the)f(FITS)f (array)0 3265 y(nbit)h(-)g(\(integer\))e(number)h(of)i(bits)e(in)h(the) g(field)g(to)g(read)g(or)g(write)0 3378 y(nchars)f(-)i(\(integer\))d (number)h(of)h(characters)e(to)i(read)g(and)g(return)0 3491 y(ncols)f(-)i(\(integer\))d(number)h(of)h(columns)0 3604 y(nelements)e(-)j(\(integer\))d(number)h(of)h(data)g(elements)e (to)j(read)e(or)h(write)0 3717 y(nelementsll)e(-)i(\(integer*8\))e (number)h(of)h(data)g(elements)e(to)j(read)e(or)h(write)0 3830 y(nexc)142 b(\(integer\))93 b(number)46 b(of)h(names)g(in)g(the)g (exclusion)e(list)i(\(may)f(=)i(0\))0 3942 y(nhdu)f(-)g(\(integer\))e (absolute)h(number)g(of)h(the)g(HDU)g(\(1st)g(HDU)g(=)g(1\))0 4055 y(ninc)142 b(\(integer\))93 b(number)46 b(of)h(names)g(in)g(the)g (inclusion)e(list)0 4168 y(nmove)h(-)i(\(integer\))d(number)h(of)h (HDUs)g(to)g(move)g(\(+)g(or)g(-\),)g(relative)f(to)h(current)f (position)0 4281 y(nfound)g(-)i(\(integer\))d(number)h(of)h(keywords)f (found)g(\(highest)g(keyword)f(number\))0 4394 y(no_keys)h(-)h (\(integer\))f(number)g(of)h(keywords)e(to)j(write)e(in)h(the)g (sequence)0 4507 y(nparm)f(-)i(\(integer\))d(number)h(of)h(group)g (parameters)e(to)i(read)g(or)g(write)0 4620 y(nrows)f(-)i(\(integer\))d (number)h(of)h(rows)g(in)g(the)g(table)0 4733 y(nrowsll)f(-)h (\(integer*8\))e(number)h(of)h(rows)g(in)g(the)g(table)0 4846 y(nullval)f(-)h(value)g(to)g(represent)e(undefined)g(pixels,)h(of) h(the)g(appropriate)e(datatype)0 4959 y(nextaddr)h(-)h(\(integer\))e (starting)h(address)g(\(in)h(bytes\))f(of)h(the)g(HDU)g(following)e (the)i(CHDU)0 5072 y(offset)f(-)i(\(integer\))d(byte)h(offset)h(in)g (the)g(heap)f(to)h(the)g(first)g(element)f(of)h(the)g(array)0 5185 y(offsetll)f(-)h(\(integer*8\))e(byte)h(offset)g(in)i(the)f(heap)f (to)h(the)g(first)g(element)e(of)j(the)f(array)0 5297 y(oldkey)f(-)i(\(character\))c(old)j(name)g(of)g(keyword)f(to)h(be)g (modified)0 5410 y(ounit)f(-)i(\(integer\))d(logical)h(unit)h(number)f (associated)f(with)h(the)h(output)f(FITS)h(file)g(1-300)0 5523 y(pcount)f(-)i(\(integer\))d(value)h(of)h(the)g(PCOUNT)f(keyword)g (\(usually)g(=)h(0\))0 5636 y(previous)f(-)h(\(integer\))e(if)i(not)g (equal)g(to)g(0,)g(copy)g(all)g(previous)e(HDUs)i(in)g(the)g(input)f (file)p eop end %%Page: 130 136 TeXDict begin 130 135 bop 0 299 a Fj(130)1779 b Fh(CHAPTER)30 b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Ff(repeat)46 b(-)i(\(integer\))d(length)h(of)h(element)f(vector)g (\(e.g.)g(12J\);)h(ignored)f(for)g(ASCII)h(table)0 668 y(rot)g(-)g(\(double)f(precision\))f(celestial)g(coordinate)g(rotation) h(angle)g(\(degrees\))0 781 y(rowlen)g(-)i(\(integer\))d(length)h(of)h (a)h(table)e(row,)h(in)g(characters)e(or)i(bytes)0 894 y(rowlenll)f(-)h(\(integer*8\))e(length)h(of)h(a)g(table)g(row,)f(in)i (characters)d(or)i(bytes)0 1007 y(rowlist)f(-)h(\(integer)f(array\))g (list)h(of)g(row)g(numbers)e(to)j(be)f(deleted)f(in)h(increasing)e (order)0 1120 y(rownum)h(-)i(\(integer\))d(number)h(of)h(the)g(row)g (\(first)f(row)h(=)g(1\))0 1233 y(rowrange-)e(\(string\))h(list)g(of)i (rows)e(or)h(row)g(ranges)f(to)i(be)f(deleted)0 1346 y(rwmode)f(-)i(\(integer\))d(file)h(access)h(mode:)f(0)h(=)h(readonly,) d(1)j(=)f(readwrite)0 1458 y(second)142 b(\(double\)-)45 b(second)h(within)g(minute)g(\(0)h(-)h(60.9999999999\))c(\(leap)i (second!\))0 1571 y(seq_no)g(-)i(\(integer\))d(the)i(sequence)e(number) h(to)i(append)e(to)h(the)g(keyword)f(root)g(name)0 1684 y(simple)g(-)i(\(logical\))d(does)h(the)h(FITS)g(file)g(conform)e(to)j (all)f(the)f(FITS)h(standards)0 1797 y(snull)f(-)i(\(character\))d (value)h(used)h(to)g(represent)e(undefined)g(values)h(in)i(ASCII)e (table)0 1910 y(space)g(-)i(\(integer\))d(number)h(of)h(blank)g(spaces) f(to)h(leave)f(between)g(ASCII)h(table)f(columns)0 2023 y(startchar)f(-)j(\(integer\))d(first)h(character)g(in)h(the)g(row)g (to)g(be)g(read)0 2136 y(startno)f(-)h(\(integer\))f(value)g(of)h(the)g (first)f(keyword)g(sequence)g(number)g(\(usually)f(1\))0 2249 y(status)h(-)i(\(integer\))d(returned)g(error)i(status)f(code)g (\(0)i(=)f(OK\))0 2362 y(str_template)d(\(character\))h(template)h (string)g(to)h(be)g(matched)f(to)h(reference)e(string)0 2475 y(stream)h(-)i(\(character\))c(output)i(stream)g(for)h(the)g (report:)f(either)g('STDOUT')g(or)h('STDERR')0 2588 y(string)f(-)i (\(character\))c(character)i(string)0 2700 y(sum)h(-)g(\(double)f (precision\))f(32)i(bit)g(unsigned)f(checksum)f(value)0 2813 y(tbcol)h(-)i(\(integer)d(array\))h(column)h(number)f(of)h(the)g (first)f(character)f(in)j(the)e(field\(s\))0 2926 y(tdisp)g(-)i (\(character\))d(Fortran)g(type)i(display)f(format)g(for)h(the)g(table) f(column)0 3039 y(template-\(character\))c(template)k(string)g(for)h(a) g(FITS)g(header)f(record)0 3152 y(tfields)g(-)h(\(integer\))f(number)g (of)h(fields)f(\(columns\))f(in)i(the)g(table)0 3265 y(tform)f(-)i(\(character)d(array\))h(format)g(of)h(the)g(column\(s\);) e(allowed)h(values)g(are:)430 3378 y(For)g(ASCII)h(tables:)93 b(Iw,)47 b(Aw,)g(Fww.dd,)f(Eww.dd,)g(or)h(Dww.dd)430 3491 y(For)f(binary)h(tables:)e(rL,)i(rX,)g(rB,)g(rI,)g(rJ,)g(rA,)g (rAw,)f(rE,)h(rD,)g(rC,)g(rM)430 3604 y(where)f('w'=width)f(of)i(the)g (field,)f('d'=no.)g(of)h(decimals,)f('r'=repeat)f(count)430 3717 y(Note)h(that)h(the)g('rAw')f(form)h(is)g(non-standard)d (extension)i(to)h(the)430 3830 y(TFORM)f(keyword)g(syntax)g(that)g(is)i (not)f(specifically)d(defined)i(in)h(the)430 3942 y(Binary)f(Tables)g (definition)f(document.)0 4055 y(theap)h(-)i(\(integer\))d(zero)i (indexed)f(byte)g(offset)g(of)h(starting)f(address)g(of)h(the)g(heap) 430 4168 y(relative)e(to)i(the)g(beginning)e(of)j(the)f(binary)f(table) g(data)0 4281 y(tnull)g(-)i(\(integer\))d(value)h(used)h(to)g (represent)f(undefined)f(values)h(in)h(binary)f(table)0 4394 y(tnullll)g(-)h(\(integer*8\))e(value)h(used)h(to)g(represent)e (undefined)h(values)g(in)h(binary)f(table)0 4507 y(ttype)g(-)i (\(character)d(array\))h(label)g(for)h(table)g(column\(s\))0 4620 y(tscal)f(-)i(\(double)e(precision\))f(scaling)g(factor)i(for)f (table)h(column)0 4733 y(tunit)f(-)i(\(character)d(array\))h(physical)f (unit)i(for)g(table)f(column\(s\))0 4846 y(tzero)g(-)i(\(double)e (precision\))f(scaling)g(zero)i(point)f(for)h(table)g(column)0 4959 y(unit)94 b(-)48 b(\(integer\))d(logical)h(unit)h(number)f (associated)f(with)h(the)h(FITS)g(file)f(\(1-300\))0 5072 y(units)g(-)i(\(character\))d(the)h(keyword)g(units)h(string)f (\(e.g.,)g('km/s'\))0 5185 y(value)g(-)i(\(character\))d(the)h(keyword) g(value)h(string)0 5297 y(values)f(-)i(array)e(of)h(data)g(values)f(of) h(the)g(appropriate)e(datatype)0 5410 y(varidat)h(-)h(\(integer\))f (size)g(in)h(bytes)g(of)g(the)g('variable)e(length)h(data)h(area')525 5523 y(following)e(the)i(binary)f(table)h(data)f(\(usually)g(=)h(0\))0 5636 y(version)f(-)h(\(real\))f(current)g(revision)g(number)g(of)h(the) g(library)p eop end %%Page: 131 137 TeXDict begin 131 136 bop 3764 299 a Fj(131)0 555 y Ff(width)46 b(-)i(\(integer\))d(width)h(of)i(the)f(character)e(string)h(field)0 668 y(xcol)h(-)g(\(integer\))e(number)h(of)i(the)f(column)f(containing) f(the)i(X)g(coordinate)e(values)0 781 y(xinc)i(-)g(\(double)f (precision\))f(X)i(axis)g(coordinate)e(increment)g(at)i(reference)f (pixel)g(\(deg\))0 894 y(xpix)h(-)g(\(double)f(precision\))f(X)i(axis)g (pixel)f(location)0 1007 y(xpos)h(-)g(\(double)f(precision\))f(X)i (axis)g(celestial)e(coordinate)g(\(usually)h(RA\))h(\(deg\))0 1120 y(xrpix)f(-)i(\(double)e(precision\))f(X)i(axis)g(reference)e (pixel)h(array)h(location)0 1233 y(xrval)f(-)i(\(double)e(precision\))f (X)i(axis)g(coordinate)e(value)h(at)h(the)g(reference)e(pixel)i (\(deg\))0 1346 y(ycol)g(-)g(\(integer\))e(number)h(of)i(the)f(column)f (containing)f(the)i(X)g(coordinate)e(values)0 1458 y(year)i(-)g (\(integer\))e(last)i(2)g(digits)g(of)g(the)g(year)f(\(00)h(-)h(99\))0 1571 y(yinc)f(-)g(\(double)f(precision\))f(Y)i(axis)g(coordinate)e (increment)g(at)i(reference)f(pixel)g(\(deg\))0 1684 y(ypix)h(-)g(\(double)f(precision\))f(y)i(axis)g(pixel)f(location)0 1797 y(ypos)h(-)g(\(double)f(precision\))f(y)i(axis)g(celestial)e (coordinate)g(\(usually)h(DEC\))g(\(deg\))0 1910 y(yrpix)g(-)i (\(double)e(precision\))f(Y)i(axis)g(reference)e(pixel)h(array)h (location)0 2023 y(yrval)f(-)i(\(double)e(precision\))f(Y)i(axis)g (coordinate)e(value)h(at)h(the)g(reference)e(pixel)i(\(deg\))p eop end %%Page: 132 138 TeXDict begin 132 137 bop 0 299 a Fj(132)1779 b Fh(CHAPTER)30 b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)p eop end %%Page: 133 139 TeXDict begin 133 138 bop 0 1225 a Fg(Chapter)65 b(12)0 1687 y Fm(FITSIO)76 b(Error)h(Status)h(Co)6 b(des)0 2180 y Ff(Status)46 b(codes)g(in)i(the)f(range)f(-99)h(to)g(-999)94 b(and)47 b(1)h(to)f(999)g(are)g(reserved)e(for)i(future)0 2293 y(FITSIO)f(use.)95 2518 y(0)96 b(OK,)47 b(no)g(error)0 2631 y(101)95 b(input)46 b(and)h(output)f(files)g(are)h(the)g(same)0 2744 y(103)95 b(too)47 b(many)f(FITS)h(files)f(open)h(at)g(once;)f(all) h(internal)f(buffers)g(full)0 2857 y(104)95 b(error)46 b(opening)g(existing)f(file)0 2970 y(105)95 b(error)46 b(creating)g(new)g(FITS)h(file;)f(\(does)h(a)g(file)g(with)g(this)f (name)h(already)f(exist?\))0 3083 y(106)95 b(error)46 b(writing)g(record)g(to)h(FITS)g(file)0 3196 y(107)95 b(end-of-file)44 b(encountered)h(while)h(reading)g(record)g(from)h (FITS)g(file)0 3309 y(108)95 b(error)46 b(reading)g(record)g(from)h (file)0 3422 y(110)95 b(error)46 b(closing)g(FITS)g(file)0 3535 y(111)95 b(internal)45 b(array)i(dimensions)e(exceeded)0 3648 y(112)95 b(Cannot)46 b(modify)g(file)g(with)h(readonly)f(access)0 3760 y(113)95 b(Could)46 b(not)h(allocate)e(memory)0 3873 y(114)95 b(illegal)45 b(logical)h(unit)h(number;)f(must)g(be)i (between)d(1)j(-)f(300,)g(inclusive)0 3986 y(115)95 b(NULL)46 b(input)h(pointer)e(to)j(routine)0 4099 y(116)95 b(error)46 b(seeking)g(position)f(in)j(file)0 4325 y(121)95 b(invalid)45 b(URL)i(prefix)f(on)i(file)e(name)0 4438 y(122)95 b(tried)46 b(to)h(register)f(too)h(many)f(IO)h(drivers)0 4551 y(123)95 b(driver)46 b(initialization)e(failed)0 4664 y(124)95 b(matching)45 b(driver)h(is)h(not)g(registered)0 4777 y(125)95 b(failed)46 b(to)h(parse)f(input)h(file)f(URL)0 4890 y(126)95 b(parse)46 b(error)g(in)i(range)e(list)0 5115 y(151)95 b(bad)47 b(argument)e(in)i(shared)f(memory)g(driver)0 5228 y(152)95 b(null)46 b(pointer)g(passed)g(as)h(an)h(argument)0 5341 y(153)95 b(no)47 b(more)f(free)h(shared)f(memory)g(handles)0 5454 y(154)95 b(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)0 5567 y(155)95 b(IPC)47 b(error)f(returned)f(by)j(a)f(system)f(call)0 5680 y(156)95 b(no)47 b(memory)f(in)h(shared)f(memory)g(driver)1882 5942 y Fj(133)p eop end %%Page: 134 140 TeXDict begin 134 139 bop 0 299 a Fj(134)1613 b Fh(CHAPTER)30 b(12.)112 b(FITSIO)30 b(ERR)m(OR)g(ST)-8 b(A)g(TUS)30 b(CODES)0 555 y Ff(157)95 b(resource)45 b(deadlock)h(would)g(occur)0 668 y(158)95 b(attempt)45 b(to)j(open/create)c(lock)j(file)g(failed)0 781 y(159)95 b(shared)46 b(memory)g(block)g(cannot)g(be)h(resized)f(at) h(the)g(moment)0 1120 y(201)95 b(header)46 b(not)h(empty;)f(can't)g (write)g(required)g(keywords)0 1233 y(202)95 b(specified)45 b(keyword)h(name)g(was)h(not)g(found)g(in)g(the)g(header)0 1346 y(203)95 b(specified)45 b(header)h(record)g(number)g(is)h(out)g (of)g(bounds)0 1458 y(204)95 b(keyword)45 b(value)i(field)f(is)h(blank) 0 1571 y(205)95 b(keyword)45 b(value)i(string)f(is)h(missing)f(the)h (closing)f(quote)g(character)0 1684 y(206)95 b(illegal)45 b(indexed)h(keyword)g(name)h(\(e.g.)f('TFORM1000'\))0 1797 y(207)95 b(illegal)45 b(character)h(in)h(keyword)f(name)g(or)i (header)e(record)0 1910 y(208)95 b(keyword)45 b(does)i(not)g(have)g (expected)e(name.)i(Keyword)e(out)i(of)g(sequence?)0 2023 y(209)95 b(keyword)45 b(does)i(not)g(have)g(expected)e(integer)h (value)0 2136 y(210)95 b(could)46 b(not)h(find)g(the)f(required)g(END)h (header)f(keyword)0 2249 y(211)95 b(illegal)45 b(BITPIX)i(keyword)e (value)0 2362 y(212)95 b(illegal)45 b(NAXIS)i(keyword)f(value)0 2475 y(213)95 b(illegal)45 b(NAXISn)i(keyword)e(value:)h(must)h(be)g(0) h(or)f(positive)e(integer)0 2588 y(214)95 b(illegal)45 b(PCOUNT)i(keyword)e(value)0 2700 y(215)95 b(illegal)45 b(GCOUNT)i(keyword)e(value)0 2813 y(216)95 b(illegal)45 b(TFIELDS)h(keyword)g(value)0 2926 y(217)95 b(negative)45 b(ASCII)i(or)g(binary)f(table)g(width)h(value)f(\(NAXIS1\))0 3039 y(218)95 b(negative)45 b(number)h(of)h(rows)g(in)g(ASCII)g(or)g (binary)f(table)g(\(NAXIS2\))0 3152 y(219)95 b(column)46 b(name)g(\(TTYPE)g(keyword\))g(not)h(found)0 3265 y(220)95 b(illegal)45 b(SIMPLE)i(keyword)e(value)0 3378 y(221)95 b(could)46 b(not)h(find)g(the)f(required)g(SIMPLE)g(header)g(keyword)0 3491 y(222)95 b(could)46 b(not)h(find)g(the)f(required)g(BITPIX)g (header)g(keyword)0 3604 y(223)95 b(could)46 b(not)h(find)g(the)f (required)g(NAXIS)g(header)g(keyword)0 3717 y(224)95 b(could)46 b(not)h(find)g(all)f(the)h(required)f(NAXISn)g(keywords)g (in)h(the)g(header)0 3830 y(225)95 b(could)46 b(not)h(find)g(the)f (required)g(XTENSION)g(header)g(keyword)0 3942 y(226)95 b(the)47 b(CHDU)f(is)h(not)g(an)g(ASCII)g(table)f(extension)0 4055 y(227)95 b(the)47 b(CHDU)f(is)h(not)g(a)h(binary)e(table)g (extension)0 4168 y(228)95 b(could)46 b(not)h(find)g(the)f(required)g (PCOUNT)g(header)g(keyword)0 4281 y(229)95 b(could)46 b(not)h(find)g(the)f(required)g(GCOUNT)g(header)g(keyword)0 4394 y(230)95 b(could)46 b(not)h(find)g(the)f(required)g(TFIELDS)g (header)g(keyword)0 4507 y(231)95 b(could)46 b(not)h(find)g(all)f(the)h (required)f(TBCOLn)g(keywords)g(in)h(the)g(header)0 4620 y(232)95 b(could)46 b(not)h(find)g(all)f(the)h(required)f(TFORMn)g (keywords)g(in)h(the)g(header)0 4733 y(233)95 b(the)47 b(CHDU)f(is)h(not)g(an)g(IMAGE)g(extension)0 4846 y(234)95 b(illegal)45 b(TBCOL)i(keyword)f(value;)g(out)h(of)g(range)0 4959 y(235)95 b(this)46 b(operation)g(only)g(allowed)g(for)h(ASCII)f (or)h(BINARY)g(table)f(extension)0 5072 y(236)95 b(column)46 b(is)h(too)g(wide)f(to)i(fit)f(within)f(the)h(specified)e(width)h(of)h (the)g(ASCII)g(table)0 5185 y(237)95 b(the)47 b(specified)e(column)h (name)h(template)e(matched)h(more)h(than)f(one)h(column)f(name)0 5297 y(241)95 b(binary)46 b(table)g(row)h(width)f(is)i(not)e(equal)h (to)g(the)g(sum)g(of)g(the)g(field)f(widths)0 5410 y(251)95 b(unrecognizable)44 b(type)i(of)h(FITS)g(extension)0 5523 y(252)95 b(unrecognizable)44 b(FITS)i(record)0 5636 y(253)95 b(END)47 b(keyword)e(contains)h(non-blank)f(characters)g(in)i (columns)f(9-80)p eop end %%Page: 135 141 TeXDict begin 135 140 bop 3764 299 a Fj(135)0 555 y Ff(254)95 b(Header)46 b(fill)g(area)h(contains)f(non-blank)f(characters)0 668 y(255)95 b(Data)46 b(fill)h(area)g(contains)e(non-blank)g(on)j (non-zero)d(values)0 781 y(261)95 b(unable)46 b(to)h(parse)f(the)h (TFORM)g(keyword)e(value)i(string)0 894 y(262)95 b(unrecognizable)44 b(TFORM)i(datatype)f(code)0 1007 y(263)95 b(illegal)45 b(TDIMn)i(keyword)f(value)0 1233 y(301)95 b(illegal)45 b(HDU)i(number;)f(less)h(than)f(1)i(or)f(greater)f(than)h(internal)e (buffer)h(size)0 1346 y(302)95 b(column)46 b(number)g(out)h(of)g(range) f(\(1)h(-)h(999\))0 1458 y(304)95 b(attempt)45 b(to)j(move)e(to)h (negative)f(file)h(record)f(number)0 1571 y(306)95 b(attempted)45 b(to)i(read)g(or)g(write)f(a)i(negative)d(number)h(of)i(bytes)e(in)h (the)g(FITS)g(file)0 1684 y(307)95 b(illegal)45 b(starting)h(row)h (number)f(for)h(table)f(read)h(or)g(write)f(operation)0 1797 y(308)95 b(illegal)45 b(starting)h(element)g(number)g(for)h(table) f(read)h(or)g(write)f(operation)0 1910 y(309)95 b(attempted)45 b(to)i(read)g(or)g(write)f(character)g(string)g(in)h(non-character)d (table)i(column)0 2023 y(310)95 b(attempted)45 b(to)i(read)g(or)g (write)f(logical)g(value)g(in)i(non-logical)c(table)j(column)0 2136 y(311)95 b(illegal)45 b(ASCII)i(table)f(TFORM)h(format)f(code)g (for)h(attempted)e(operation)0 2249 y(312)95 b(illegal)45 b(binary)i(table)f(TFORM)g(format)g(code)h(for)g(attempted)e(operation) 0 2362 y(314)95 b(value)46 b(for)h(undefined)e(pixels)h(has)h(not)g (been)g(defined)0 2475 y(317)95 b(attempted)45 b(to)i(read)g(or)g (write)f(descriptor)f(in)i(a)h(non-descriptor)c(field)0 2588 y(320)95 b(number)46 b(of)h(array)f(dimensions)f(out)i(of)g(range) 0 2700 y(321)95 b(first)46 b(pixel)g(number)g(is)i(greater)d(than)i (the)g(last)g(pixel)f(number)0 2813 y(322)95 b(attempt)45 b(to)j(set)f(BSCALE)f(or)h(TSCALn)f(scaling)g(parameter)f(=)i(0)0 2926 y(323)95 b(illegal)45 b(axis)i(length)f(less)h(than)f(1)0 3152 y(340)h(NOT_GROUP_TABLE)d(340)142 b(Grouping)45 b(function)h(error)0 3265 y(341)h(HDU_ALREADY_MEMBER)0 3378 y(342)g(MEMBER_NOT_FOUND)0 3491 y(343)g(GROUP_NOT_FOUND)0 3604 y(344)g(BAD_GROUP_ID)0 3717 y(345)g(TOO_MANY_HDUS_TRACKED)0 3830 y(346)g(HDU_ALREADY_TRACKED)0 3942 y(347)g(BAD_OPTION)0 4055 y(348)g(IDENTICAL_POINTERS)0 4168 y(349)g(BAD_GROUP_ATTACH)0 4281 y(350)g(BAD_GROUP_DETACH)0 4507 y(360)g(NGP_NO_MEMORY)665 b(malloc)46 b(failed)0 4620 y(361)h(NGP_READ_ERR)713 b(read)46 b(error)h(from)f(file)0 4733 y(362)h(NGP_NUL_PTR)761 b(null)46 b(pointer)g(passed)g(as)h(an)g(argument.)1575 4846 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f(of)1575 4959 y(template)f(file)g(raises)g(this)h(error)0 5072 y(363)g(NGP_EMPTY_CURLINE)473 b(line)46 b(read)h(seems)f(to)h(be)h (empty)e(\(used)1575 5185 y(internally\))0 5297 y(364)h (NGP_UNREAD_QUEUE_FULL)281 b(cannot)46 b(unread)g(more)g(then)h(1)g (line)g(\(or)g(single)1575 5410 y(line)g(twice\))0 5523 y(365)g(NGP_INC_NESTING)569 b(too)46 b(deep)h(include)f(file)h(nesting) e(\(infinite)1575 5636 y(loop,)h(template)g(includes)f(itself)i(?\))p eop end %%Page: 136 142 TeXDict begin 136 141 bop 0 299 a Fj(136)1613 b Fh(CHAPTER)30 b(12.)112 b(FITSIO)30 b(ERR)m(OR)g(ST)-8 b(A)g(TUS)30 b(CODES)0 555 y Ff(366)47 b(NGP_ERR_FOPEN)665 b(fopen\(\))45 b(failed,)h(cannot)g(open)h(template)e(file)0 668 y(367)i(NGP_EOF)953 b(end)46 b(of)i(file)e(encountered)f(and)i(not)g(expected)0 781 y(368)g(NGP_BAD_ARG)761 b(bad)46 b(arguments)g(passed.)g(Usually)f (means)1575 894 y(internal)h(parser)g(error.)g(Should)g(not)h(happen)0 1007 y(369)g(NGP_TOKEN_NOT_EXPECT)329 b(token)46 b(not)h(expected)e (here)0 1233 y(401)95 b(error)46 b(attempting)f(to)i(convert)f(an)h (integer)f(to)h(a)h(formatted)d(character)g(string)0 1346 y(402)95 b(error)46 b(attempting)f(to)i(convert)f(a)h(real)g (value)f(to)i(a)f(formatted)e(character)h(string)0 1458 y(403)95 b(cannot)46 b(convert)g(a)h(quoted)f(string)g(keyword)g(to)h (an)g(integer)0 1571 y(404)95 b(attempted)45 b(to)i(read)g(a)g (non-logical)e(keyword)h(value)g(as)h(a)h(logical)e(value)0 1684 y(405)95 b(cannot)46 b(convert)g(a)h(quoted)f(string)g(keyword)g (to)h(a)h(real)e(value)0 1797 y(406)95 b(cannot)46 b(convert)g(a)h (quoted)f(string)g(keyword)g(to)h(a)h(double)e(precision)f(value)0 1910 y(407)95 b(error)46 b(attempting)f(to)i(read)g(character)e(string) h(as)h(an)h(integer)0 2023 y(408)95 b(error)46 b(attempting)f(to)i (read)g(character)e(string)h(as)h(a)h(real)e(value)0 2136 y(409)95 b(error)46 b(attempting)f(to)i(read)g(character)e(string) h(as)h(a)h(double)e(precision)f(value)0 2249 y(410)95 b(bad)47 b(keyword)e(datatype)h(code)0 2362 y(411)95 b(illegal)45 b(number)i(of)g(decimal)f(places)g(while)g(formatting)f (floating)h(point)g(value)0 2475 y(412)95 b(numerical)45 b(overflow)g(during)i(implicit)e(datatype)h(conversion)0 2588 y(413)95 b(error)46 b(compressing)f(image)0 2700 y(414)95 b(error)46 b(uncompressing)e(image)0 2813 y(420)95 b(error)46 b(in)h(date)g(or)g(time)g(conversion)0 3039 y(431)95 b(syntax)46 b(error)g(in)h(parser)f(expression)0 3152 y(432)95 b(expression)45 b(did)i(not)f(evaluate)g(to)h(desired)f (type)0 3265 y(433)95 b(vector)46 b(result)g(too)h(large)f(to)h(return) f(in)i(array)0 3378 y(434)95 b(data)46 b(parser)g(failed)g(not)h(sent)g (an)g(out)g(column)0 3491 y(435)95 b(bad)47 b(data)f(encounter)f(while) i(parsing)f(column)0 3604 y(436)95 b(parse)46 b(error:)g(output)g(file) h(not)g(of)g(proper)f(type)0 3830 y(501)95 b(celestial)45 b(angle)h(too)h(large)g(for)f(projection)0 3942 y(502)95 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)f(value)0 4055 y(503)95 b(error)46 b(in)h(celestial)e(coordinate)g(calculation)0 4168 y(504)95 b(unsupported)44 b(type)j(of)g(celestial)e(projection)0 4281 y(505)95 b(required)45 b(celestial)g(coordinate)g(keywords)h(not)h (found)0 4394 y(506)95 b(approximate)44 b(wcs)j(keyword)f(values)g (were)h(returned)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF cfitsio-4.3.1/docs/cfitsio.toc0000644000225700000360000002267014456514035015562 0ustar cagordonlhea\contentsline {chapter}{\numberline {1}Introduction }{1} \contentsline {section}{\numberline {1.1} A Brief Overview}{1} \contentsline {section}{\numberline {1.2}Sources of FITS Software and Information}{1} \contentsline {section}{\numberline {1.3}Acknowledgments}{2} \contentsline {section}{\numberline {1.4}Legal Stuff}{4} \contentsline {chapter}{\numberline {2} Creating the CFITSIO Library }{5} \contentsline {section}{\numberline {2.1}Building the Library}{5} \contentsline {subsection}{\numberline {2.1.1}Unix Systems}{5} \contentsline {subsection}{\numberline {2.1.2}VMS}{7} \contentsline {subsection}{\numberline {2.1.3}Windows PCs}{7} \contentsline {subsection}{\numberline {2.1.4}Macintosh PCs}{7} \contentsline {section}{\numberline {2.2}Testing the Library}{7} \contentsline {section}{\numberline {2.3}Linking Programs with CFITSIO}{9} \contentsline {section}{\numberline {2.4}Using CFITSIO in Multi-threaded Environments}{9} \contentsline {section}{\numberline {2.5}Getting Started with CFITSIO}{9} \contentsline {section}{\numberline {2.6}Example Program}{10} \contentsline {chapter}{\numberline {3} A FITS Primer }{13} \contentsline {chapter}{\numberline {4} Programming Guidelines }{15} \contentsline {section}{\numberline {4.1}CFITSIO Definitions}{15} \contentsline {section}{\numberline {4.2}Current Header Data Unit (CHDU)}{18} \contentsline {section}{\numberline {4.3}Function Names and Variable Datatypes}{18} \contentsline {section}{\numberline {4.4}Support for Unsigned Integers and Signed Bytes}{20} \contentsline {section}{\numberline {4.5}Dealing with Character Strings }{22} \contentsline {section}{\numberline {4.6}Implicit Data Type Conversion}{23} \contentsline {section}{\numberline {4.7}Data Scaling}{23} \contentsline {section}{\numberline {4.8}Support for IEEE Special Values}{24} \contentsline {section}{\numberline {4.9}Error Status Values and the Error Message Stack}{25} \contentsline {section}{\numberline {4.10}Variable-Length Arrays in Binary Tables}{25} \contentsline {section}{\numberline {4.11}Multiple Access to the Same FITS File}{27} \contentsline {section}{\numberline {4.12}When the Final Size of the FITS HDU is Unknown}{28} \contentsline {section}{\numberline {4.13}CFITSIO Size Limitations}{28} \contentsline {chapter}{\numberline {5}Basic CFITSIO Interface Routines }{31} \contentsline {section}{\numberline {5.1}CFITSIO Error Status Routines}{31} \contentsline {section}{\numberline {5.2}FITS File Access Routines}{32} \contentsline {section}{\numberline {5.3}HDU Access Routines}{35} \contentsline {section}{\numberline {5.4}Header Keyword Read/Write Routines}{37} \contentsline {subsection}{\numberline {5.4.1}Keyword Reading Routines}{38} \contentsline {subsection}{\numberline {5.4.2}Keyword Writing Routines}{41} \contentsline {section}{\numberline {5.5}Primary Array or IMAGE Extension I/O Routines}{43} \contentsline {section}{\numberline {5.6}Image Compression}{47} \contentsline {section}{\numberline {5.7}ASCII and Binary Table Routines}{53} \contentsline {subsection}{\numberline {5.7.1}Create New Table}{53} \contentsline {subsection}{\numberline {5.7.2}Column Information Routines}{53} \contentsline {subsection}{\numberline {5.7.3}Routines to Edit Rows or Columns}{56} \contentsline {subsection}{\numberline {5.7.4}Read and Write Column Data Routines}{58} \contentsline {subsection}{\numberline {5.7.5}Row Selection and Calculator Routines}{61} \contentsline {subsection}{\numberline {5.7.6}Column Binning or Histogramming Routines}{63} \contentsline {section}{\numberline {5.8}Utility Routines}{65} \contentsline {subsection}{\numberline {5.8.1}File Checksum Routines}{65} \contentsline {subsection}{\numberline {5.8.2}Date and Time Utility Routines}{67} \contentsline {subsection}{\numberline {5.8.3}General Utility Routines}{68} \contentsline {chapter}{\numberline {6} The CFITSIO Iterator Function }{79} \contentsline {section}{\numberline {6.1}The Iterator Work Function}{80} \contentsline {section}{\numberline {6.2}The Iterator Driver Function}{82} \contentsline {section}{\numberline {6.3}Guidelines for Using the Iterator Function}{83} \contentsline {section}{\numberline {6.4}Complete List of Iterator Routines}{84} \contentsline {chapter}{\numberline {7} World Coordinate System Routines }{87} \contentsline {section}{\numberline {7.1} Self-contained WCS Routines}{88} \contentsline {chapter}{\numberline {8} Hierarchical Grouping Routines }{91} \contentsline {section}{\numberline {8.1}Grouping Table Routines}{92} \contentsline {section}{\numberline {8.2}Group Member Routines}{94} \contentsline {chapter}{\numberline {9} Specialized CFITSIO Interface Routines }{97} \contentsline {section}{\numberline {9.1}FITS File Access Routines}{97} \contentsline {subsection}{\numberline {9.1.1}File Access}{97} \contentsline {subsection}{\numberline {9.1.2}Download Utility Functions}{101} \contentsline {section}{\numberline {9.2}HDU Access Routines}{102} \contentsline {section}{\numberline {9.3}Specialized Header Keyword Routines}{104} \contentsline {subsection}{\numberline {9.3.1}Header Information Routines}{104} \contentsline {subsection}{\numberline {9.3.2}Read and Write the Required Keywords}{104} \contentsline {subsection}{\numberline {9.3.3}Write Keyword Routines}{106} \contentsline {subsection}{\numberline {9.3.4}Insert Keyword Routines}{108} \contentsline {subsection}{\numberline {9.3.5}Read Keyword Routines}{109} \contentsline {subsection}{\numberline {9.3.6}Modify Keyword Routines}{111} \contentsline {subsection}{\numberline {9.3.7}Update Keyword Routines}{112} \contentsline {section}{\numberline {9.4}Define Data Scaling and Undefined Pixel Parameters}{113} \contentsline {section}{\numberline {9.5}Specialized FITS Primary Array or IMAGE Extension I/O Routines}{114} \contentsline {section}{\numberline {9.6}Specialized FITS ASCII and Binary Table Routines}{117} \contentsline {subsection}{\numberline {9.6.1}General Column Routines}{117} \contentsline {subsection}{\numberline {9.6.2}Low-Level Table Access Routines}{119} \contentsline {subsection}{\numberline {9.6.3}Write Column Data Routines}{119} \contentsline {subsection}{\numberline {9.6.4}Read Column Data Routines }{120} \contentsline {chapter}{\numberline {10} Extended File Name Syntax }{125} \contentsline {section}{\numberline {10.1}Overview}{125} \contentsline {section}{\numberline {10.2}Filetype}{128} \contentsline {subsection}{\numberline {10.2.1}Notes about HTTP proxy servers}{129} \contentsline {subsection}{\numberline {10.2.2}Notes about HTTPS and FTPS file access}{129} \contentsline {subsection}{\numberline {10.2.3}Notes about the stream filetype driver}{130} \contentsline {subsection}{\numberline {10.2.4}Notes about the gsiftp filetype}{131} \contentsline {subsection}{\numberline {10.2.5}Notes about the root filetype}{131} \contentsline {subsection}{\numberline {10.2.6}Notes about the shmem filetype:}{133} \contentsline {section}{\numberline {10.3}Base Filename}{133} \contentsline {section}{\numberline {10.4}Output File Name when Opening an Existing File}{135} \contentsline {section}{\numberline {10.5}Template File Name when Creating a New File}{137} \contentsline {section}{\numberline {10.6}Image Tile-Compression Specification}{137} \contentsline {section}{\numberline {10.7}HDU Location Specification}{137} \contentsline {section}{\numberline {10.8}Image Section}{139} \contentsline {section}{\numberline {10.9}Image Transform Filters}{140} \contentsline {section}{\numberline {10.10}Column and Keyword Filtering Specification}{141} \contentsline {section}{\numberline {10.11}Row Filtering Specification}{145} \contentsline {subsection}{\numberline {10.11.1}General Syntax}{145} \contentsline {subsection}{\numberline {10.11.2}Bit Masks}{148} \contentsline {subsection}{\numberline {10.11.3}Vector Columns}{149} \contentsline {subsection}{\numberline {10.11.4}Row Access}{151} \contentsline {subsection}{\numberline {10.11.5}Good Time Interval Filtering and Calculation}{152} \contentsline {subsection}{\numberline {10.11.6}Spatial Region Filtering}{154} \contentsline {subsection}{\numberline {10.11.7}Example Row Filters}{156} \contentsline {section}{\numberline {10.12} Binning or Histogramming Specification}{157} \contentsline {chapter}{\numberline {11}Template Files }{161} \contentsline {section}{\numberline {11.1}Detailed Template Line Format}{161} \contentsline {section}{\numberline {11.2}Auto-indexing of Keywords}{162} \contentsline {section}{\numberline {11.3}Template Parser Directives}{163} \contentsline {section}{\numberline {11.4}Formal Template Syntax}{164} \contentsline {section}{\numberline {11.5}Errors}{164} \contentsline {section}{\numberline {11.6}Examples}{164} \contentsline {chapter}{\numberline {12} Local FITS Conventions }{167} \contentsline {section}{\numberline {12.1}64-Bit Long Integers}{167} \contentsline {section}{\numberline {12.2}Long String Keyword Values.}{167} \contentsline {section}{\numberline {12.3}Arrays of Fixed-Length Strings in Binary Tables}{169} \contentsline {section}{\numberline {12.4}Keyword Units Strings}{169} \contentsline {section}{\numberline {12.5}HIERARCH Convention for Extended Keyword Names}{169} \contentsline {section}{\numberline {12.6}Tile-Compressed Image Format}{170} \contentsline {chapter}{\numberline {13} Optimizing Programs }{173} \contentsline {section}{\numberline {13.1}How CFITSIO Manages Data I/O}{173} \contentsline {section}{\numberline {13.2}Optimization Strategies}{174} \contentsline {chapter}{\numberline {A}Index of Routines }{179} \contentsline {chapter}{\numberline {B}Parameter Definitions }{185} \contentsline {chapter}{\numberline {C}CFITSIO Error Status Codes }{191} cfitsio-4.3.1/docs/cfortran.doc0000644000225700000360000027237313472024437015726 0ustar cagordonlhea/* cfortran.doc 4.3 */ /* www-zeus.desy.de/~burow OR anonymous ftp@zebra.desy.de */ /* Burkhard Burow burow@desy.de 1990 - 1998. */ See Licensing information at the end of this file. cfortran.h : Interfacing C or C++ and FORTRAN Supports: Alpha and VAX VMS, Alpha OSF, DECstation and VAX Ultrix, IBM RS/6000, Silicon Graphics, Sun, CRAY, Apollo, HP9000, LynxOS, Convex, Absoft, f2c, g77, NAG f90, PowerStation Fortran with Visual C++, NEC SX-4, Portland Group. C and C++ are generally equivalent as far as cfortran.h is concerned. Unless explicitly noted otherwise, mention of C implicitly includes C++. C++ compilers tested include: SunOS> CC +p +w # Clean compiles. IRIX> CC # Clean compiles. IRIX> CC -fullwarn # Still some warnings to be overcome. GNU> g++ -Wall # Compiles are clean, other than warnings for unused # cfortran.h static routines. N.B.: The best documentation on interfacing C or C++ and Fortran is in the chapter named something like 'Interfacing C and Fortran' to be found in the user's guide of almost every Fortran compiler. Understanding this information for one or more Fortran compilers greatly clarifies the aims and actions of cfortran.h. Such a chapter generally also addresses issues orthogonal to cfortran.h, for example the order of array indices, the index of the first element, as well as compiling and linking issues. 0 Short Summary of the Syntax Required to Create the Interface -------------------------------------------------------------- e.g. Prototyping a FORTRAN subroutine for C: /* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */ PROTOCCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT) #define SUB_NAME(A,B) CCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT, A,B) ^ - - number of arguments _____| | STRING BYTE PBYTE BYTEV(..)| / | STRINGV DOUBLE PDOUBLE DOUBLEV(..)| / | PSTRING FLOAT PFLOAT FLOATV(..)| types of arguments ____ / | PNSTRING INT PINT INTV(..)| \ | PPSTRING LOGICAL PLOGICAL LOGICALV(..)| \ | PSTRINGV LONG PLONG LONGV(..)| \ | ZTRINGV SHORT PSHORT SHORTV(..)| | PZTRINGV ROUTINE PVOID SIMPLE | - - e.g. Prototyping a FORTRAN function for C: /* PROTOCCALLSFFUNn is mandatory for both C and C++. */ PROTOCCALLSFFUN1(INT,FUN_NAME,fun_name,STRING) #define FUN_NAME(A) CCALLSFFUN1(FUN_NAME,fun_name,STRING, A) e.g. calling FUN_NAME from C: {int a; a = FUN_NAME("hello");} e.g. Creating a FORTRAN-callable wrapper for a C function returning void, with a 7 dimensional integer array argument: [Not supported from C++.] FCALLSCSUB1(csub_name,CSUB_NAME,csub_name,INTVVVVVVV) e.g. Creating a FORTRAN-callable wrapper for other C functions: FCALLSCFUN1(STRING,cfun_name,CFUN_NAME,cfun_name,INT) [ ^-- BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, VOID are other types returned by functions. ] e.g. COMMON BLOCKs: FORTRAN: common /fcb/ v,w,x character *(13) v, w(4), x(3,2) C: typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF; #define FCB COMMON_BLOCK(FCB,fcb) COMMON_BLOCK_DEF(FCB_DEF,FCB); FCB_DEF FCB; /* Define, i.e. allocate memory, in exactly one *.c file. */ e.g. accessing FCB in C: printf("%.13s",FCB.v); I Introduction -------------- cfortran.h is an easy-to-use powerful bridge between C and FORTRAN. It provides a completely transparent, machine independent interface between C and FORTRAN routines (= subroutines and/or functions) and global data, i.e. structures and COMMON blocks. The complete cfortran.h package consists of 4 files: the documentation in cfortran.doc, the engine cfortran.h, examples in cfortest.c and cfortex.f/or. [cfortex.for under VMS, cfortex.f on other machines.] The cfortran.h package continues to be developed. The most recent version is available via www at http://www-zeus.desy.de/~burow or via anonymous ftp at zebra.desy.de (131.169.2.244). The examples may be run using one of the following sets of instructions: N.B. Unlike earlier versions, cfortran.h 3.0 and later versions automatically uses the correct ANSI ## or pre-ANSI /**/ preprocessor operator as required by the C compiler. N.B. As a general rule when trying to determine how to link C and Fortran, link a trivial Fortran program using the Fortran compilers verbose option, in order to see how the Fortran compiler drives the linker. e.g. unix> cat f.f END unix> f77 -v f.f .. lots of info. follows ... N.B. If using a C main(), i.e. Fortran PROGRAM is not entry of the executable, and if the link bombs with a complaint about a missing "MAIN" (e.g. MAIN__, MAIN_, f90_main or similar), then Fortran has hijacked the entry point to the executable and wishes to call the rest of the executable via "MAIN". This can usually be satisfied by doing e.g. 'cc -Dmain=MAIN__ ...' but often kills the command line arguments in argv and argc. The f77 verbose option, usually -v, may point to a solution. RS/6000> # Users are strongly urged to use f77 -qextname and cc -Dextname RS/6000> # Use -Dextname=extname if extname is a symbol used in the C code. RS/6000> xlf -c -qextname cfortex.f RS/6000> cc -c -Dextname cfortest.c RS/6000> xlf -o cfortest cfortest.o cfortex.o && cfortest DECFortran> #Only DECstations with DECFortran for Ultrix RISC Systems. DECFortran> cc -c -DDECFortran cfortest.c DECFortran> f77 -o cfortest cfortest.o cfortex.f && cfortest IRIX xxxxxx 5.2 02282015 IP20 mips MIPS> # DECstations and Silicon Graphics using the MIPS compilers. MIPS> cc -o cfortest cfortest.c cfortex.f -lI77 -lU77 -lF77 && cfortest MIPS> # Can also let f77 drive linking, e.g. MIPS> cc -c cfortest.c MIPS> f77 -o cfortest cfortest.o cfortex.f && cfortest Apollo> # Some 'C compiler 68K Rev6.8' break. [See Section II o) Notes: Apollo] Apollo> f77 -c cfortex.f && cc -o cfortest cfortest.c cfortex.o && cfortest VMS> define lnk$library sys$library:vaxcrtl VMS> cc cfortest.c VMS> fortran cfortex.for VMS> link/exec=cfortest cfortest,cfortex VMS> run cfortest OSF1 xxxxxx V3.0 347 alpha Alpha/OSF> # Probably better to let cc drive linking, e.g. Alpha/OSF> f77 -c cfortex.f Alpha/OSF> cc -o cfortest cfortest.c cfortex.o -lUfor -lfor -lFutil -lots -lm Alpha/OSF> cfortest Alpha/OSF> # Else may need 'cc -Dmain=MAIN__' to let f77 drive linking. Sun> # Some old cc(1) need a little help. [See Section II o) Notes: Sun] Sun> f77 -o cfortest cfortest.c cfortex.f -lc -lm && cfortest Sun> # Some older f77 may require 'cc -Dmain=MAIN_'. CRAY> cft77 cfortex.f CRAY> cc -c cfortest.c CRAY> segldr -o cfortest.e cfortest.o cfortex.o CRAY> ./cfortest.e NEC> cc -c -Xa cfortest.c NEC> f77 -o cfortest cfortest.o cfortex.f && cfortest VAX/Ultrix/cc> # For cc on VAX Ultrix only, do the following once to cfortran.h. VAX/Ultrix/cc> mv cfortran.h cftmp.h && grep -v "^#pragma" cfortran.h VAX/Ultrix/f77> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. NOT'vcc' VAX/Ultrix/f77> CC -c -Dmain=MAIN_ cfortest.c VAX/Ultrix/f77> f77 -o cfortest cfortex.f cfortest.o && cfortest LynxOS> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. LynxOS> # Unfortunately cc is easily overwhelmed by cfortran.h, LynxOS> # and won't compile some of the cfortest.c demos. LynxOS> f2c -R cfortex.f LynxOS> CC -Dlynx -o cfortest cfortest.c cfortex.c -lf2c && cfortest HP9000> # Tested with HP-UX 7.05 B 9000/380 and with A.08.07 A 9000/730 HP9000> # CC may be either 'c89 -Aa' or 'cc -Aa' HP9000> # Depending on the compiler version, you may need to include the HP9000> # option '-tp,/lib/cpp' or worse, you'll have to stick to the K&R C. HP9000> # [See Section II o) Notes: HP9000] HP9000> # Users are strongly urged to use f77 +ppu and cc -Dextname HP9000> # Use -Dextname=extname if extname is a symbol used in the C code. HP9000> CC -Dextname -c cfortest.c HP9000> f77 +ppu cfortex.f -o cfortest cfortest.o && cfortest HP9000> # Older f77 may need HP9000> f77 -c cfortex.f HP9000> CC -o cfortest cfortest.c cfortex.o -lI77 -lF77 && cfortest HP0000> # If old-style f77 +800 compiled objects are required: HP9000> # #define hpuxFortran800 HP9000> cc -c -Aa -DhpuxFortran800 cfortest.c HP9000> f77 +800 -o cfortest cfortest.o cfortex.f f2c> # In the following, 'CC' is any C compiler. f2c> f2c -R cfortex.f f2c> CC -o cfortest -Df2cFortran cfortest.c cfortex.c -lf2c && cfortest Portland Group $ # Presumably other C compilers also work. Portland Group $ pgcc -DpgiFortran -c cfortest.c Portland Group $ pgf77 -o cfortest cfortex.f cfortest.o && cfortest NAGf90> # cfortex.f is distributed with Fortran 77 style comments. NAGf90> # To convert to f90 style comments do the following once to cfortex.f: NAGf90> mv cfortex.f cf_temp.f && sed 's/^C/\!/g' cf_temp.f > cfortex.f NAGf90> # In the following, 'CC' is any C compiler. NAGf90> CC -c -DNAGf90Fortran cfortest.c NAGf90> f90 -o cfortest cfortest.o cfortex.f && cfortest PC> # On a PC with PowerStation Fortran and Visual_C++ PC> cl /c cftest.c PC> fl32 cftest.obj cftex.for GNU> # GNU Fortran GNU> # See Section VI caveat on using 'gcc -traditional'. GNU> gcc -ansi -Wall -O -c -Df2cFortran cfortest.c GNU> g77 -ff2c -o cfortest cfortest.o cfortex.f && cfortest AbsoftUNIX> # Absoft Fortran for all UNIX based operating systems. AbsoftUNIX> # e.g. Linux or Next on Intel or Motorola68000. AbsoftUNIX> # Absoft f77 -k allows Fortran routines to be safely called from C. AbsoftUNIX> gcc -ansi -Wall -O -c -DAbsoftUNIXFortran cfortest.c AbsoftUNIX> f77 -k -o cfortest cfortest.o cfortex.f && cfortest AbsoftPro> # Absoft Pro Fortran for MacOS AbsoftPro> # Use #define AbsoftProFortran CLIPPER> # INTERGRAPH CLIX using CLIPPER C and Fortran compilers. CLIPPER> # N.B. - User, not cfortran.h, is responsible for CLIPPER> # f77initio() and f77uninitio() if required. CLIPPER> # - LOGICAL values are not mentioned in CLIPPER doc.s, CLIPPER> # so they may not yet be correct in cfortran.h. CLIPPER> # - K&R mode (-knr or Ac=knr) breaks FLOAT functions CLIPPER> # (see CLIPPER doc.s) and cfortran.h does not fix it up. CLIPPER> # [cfortran.h ok for old sun C which made the same mistake.] CLIPPER> acc cfortest.c -c -DCLIPPERFortran CLIPPER> af77 cfortex.f cfortest.o -o cfortest By changing the SELECTion ifdef of cfortest.c and recompiling one can try out a few dozen different few-line examples. The benefits of using cfortran.h include: 1. Machine/OS/compiler independent mixing of C and FORTRAN. 2. Identical (within syntax) calls across languages, e.g. C FORTRAN CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.) /* C*/ HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.); 3. Each routine need only be set up once in its lifetime. e.g. /* Setting up a FORTRAN routine to be called by C. ID,...,VMX are merely the names of arguments. These tags must be unique w.r.t. each other but are otherwise arbitrary. */ PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) #define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ ID,CHTITLE,NX,XMI,XMA,VMX) 4. Source code is NOT required for the C routines exported to FORTRAN, nor for the FORTRAN routines imported to C. In fact, routines are most easily prototyped using the information in the routines' documentation. 5. Routines, and the code calling them, can be coded naturally in the language of choice. C routines may be coded with the natural assumption of being called only by C code. cfortran.h does all the required work for FORTRAN code to call C routines. Similarly it also does all the work required for C to call FORTRAN routines. Therefore: - C programmers need not embed FORTRAN argument passing mechanisms into their code. - FORTRAN code need not be converted into C code. i.e. The honed and time-honored FORTRAN routines are called by C. 6. cfortran.h is a single ~1700 line C include file; portable to most remaining, if not all, platforms. 7. STRINGS and VECTORS of STRINGS along with the usual simple arguments to routines are supported as are functions returning STRINGS or numbers. Arrays of pointers to strings and values of structures as C arguments, will soon be implemented. After learning the machinery of cfortran.h, users can expand it to create custom types of arguments. [This requires no modification to cfortran.h, all the preprocessor directives required to implement the custom types can be defined outside cfortran.h] 8. cfortran.h requires each routine to be exported to be explicitly set up. While is usually only be done once in a header file it would be best if applications were required to do no work at all in order to cross languages. cfortran.h's simple syntax could be a convenient back-end for a program which would export FORTRAN or C routines directly from the source code. ----- Example 1 - cfortran.h has been used to make the C header file hbook.h, which then gives any C programmer, e.g. example.c, full and completely transparent access to CERN's HBOOK library of routines. Each HBOOK routine required about 3 lines of simple code in hbook.h. The example also demonstrates how FORTRAN common blocks are defined and used. /* hbook.h */ #include "cfortran.h" : PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) #define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ ID,CHTITLE,NX,XMI,XMA,VMX) : /* end hbook.h */ /* example.c */ #include "hbook.h" : typedef struct { int lines; int status[SIZE]; float p[SIZE]; /* momentum */ } FAKE_DEF; #define FAKE COMMON_BLOCK(FAKE,fake) COMMON_BLOCK_DEF(FAKE_DEF,FAKE); : main () { : HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.); /* c.f. the call in FORTRAN: CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.) */ : FAKE.p[7]=1.0; : } N.B. i) The routine is language independent. ii) hbook.h is machine independent. iii) Applications using routines via cfortran.h are machine independent. ----- Example 2 - Many VMS System calls are most easily called from FORTRAN, but cfortran.h now gives that ease in C. #include "cfortran.h" PROTOCCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING) #define LIB$SPAWN(command,input_file,output_file) \ CCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING, \ command,input_file,output_file) main () { LIB$SPAWN("set term/width=132","",""); } Obviously the cfortran.h command above could be put into a header file along with the description of the other system calls, but as this example shows, it's not much hassle to set up cfortran.h for even a single call. ----- Example 3 - cfortran.h and the source cstring.c create the cstring.obj library which gives FORTRAN access to all the functions in C's system library described by the system's C header file string.h. C EXAMPLE.FOR PROGRAM EXAMPLE DIMENSION I(20), J(30) : CALL MEMCPY(I,J,7) : END /* cstring.c */ #include /* string.h prototypes memcpy() */ #include "cfortran.h" : FCALLSCSUB3(memcpy,MEMCPY,memcpy,PVOID,PVOID,INT) : The simplicity exhibited in the above example exists for many but not all machines. Note 4. of Section II ii) details the limitations and describes tools which try to maintain the best possible interface when FORTRAN calls C routines. ----- II Using cfortran.h ------------------- The user is asked to look at the source files cfortest.c and cfortex.f for clarification by example. o) Notes: o Specifying the Fortran compiler cfortran.h generates interfaces for the default Fortran compiler. The default can be overridden by defining, . in the code, e.g.: #define NAGf90Fortran OR . in the compile directive, e.g.: unix> cc -DNAGf90Fortran one of the following before including cfortran.h: NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran IBMR2Fortran CRAYFortran mipsFortran DECFortran vmsFortran CONVEXFortran PowerStationFortran AbsoftUNIXFortran SXFortran pgiFortran AbsoftProFortran This also allows crosscompilation. If wanted, NAGf90Fortran, f2cFortran, DECFortran, AbsoftUNIXFortran, AbsoftProFortran and pgiFortran must be requested by the user. o /**/ cfortran.h (ab)uses the comment kludge /**/ when the ANSI C preprocessor catenation operator ## doesn't exist. In at least MIPS C, this kludge is sensitive to blanks surrounding arguments to macros. Therefore, for applications using non-ANSI C compilers, the argtype_i, routine_name, routine_type and common_block_name arguments to the PROTOCCALLSFFUNn, CCALLSFSUB/FUNn, FCALLSCSUB/FUNn and COMMON_BLOCK macros --- MUST NOT --- be followed by any white space characters such as blanks, tabs or newlines. o LOGICAL FORTRAN LOGICAL values of .TRUE. and .FALSE. do not agree with the C representation of TRUE and FALSE on all machines. cfortran.h does the conversion for LOGICAL and PLOGICAL arguments and for functions returning LOGICAL. Users must convert arrays of LOGICALs from C to FORTRAN with the C2FLOGICALV(array_name, elements_in_array); macro. Similarly, arrays of LOGICAL values may be converted from the FORTRAN into C representation by using F2CLOGICALV(array_name, elements_in_array); When C passes or returns LOGICAL values to FORTRAN, by default cfortran.h only makes the minimal changes required to the value. [e.g. Set/Unset the single relevant bit or do nothing for FORTRAN compilers which use 0 as FALSE and treat all other values as TRUE.] Therefore cfortran.h will pass LOGICALs to FORTRAN which do not have an identical representation to .TRUE. or .FALSE. This is fine except for abuses of FORTRAN/77 in the style of: logical l if (l .eq. .TRUE.) ! (1) instead of the correct: if (l .eqv. .TRUE.) ! (2) or: if (l) ! (3) For FORTRAN code which treats LOGICALs from C in the method of (1), LOGICAL_STRICT must be defined before including cfortran.h, either in the code, "#define LOGICAL_STRICT", or compile with "cc -DLOGICAL_STRICT". There is no reason to use LOGICAL_STRICT for FORTRAN code which does not do (1). At least the IBM's xlf and the Apollo's f77 do not even allow code along the lines of (1). DECstations' DECFortran and MIPS FORTRAN compilers use different internal representations for LOGICAL values. [Both compilers are usually called f77, although when both are installed on a single machine the MIPS' one is usually renamed. (e.g. f772.1 for version 2.10.)] cc doesn't know which FORTRAN compiler is present, so cfortran.h assumes MIPS f77. To use cc with DECFortran define the preprocessor constant 'DECFortran'. e.g. i) cc -DDECFortran -c the_code.c or ii) #define DECFortran /* in the C code or add to cfortran.h. */ MIPS f77 [SGI and DECstations], f2c, and f77 on VAX Ultrix treat .eqv./.neqv. as .eq./.ne.. Therefore, for these compilers, LOGICAL_STRICT is defined by default in cfortran.h. [The Sun and HP compilers have not been tested, so they may also require LOGICAL_STRICT as the default.] o SHORT and BYTE They are irrelevant for the CRAY where FORTRAN has no equivalent to C's short. Similarly BYTE is irrelevant for f2c and for VAX Ultrix f77 and fort. The author has tested SHORT and BYTE with a modified cfortest.c/cfortex.f on all machines supported except for the HP9000 and the Sun. BYTE is a signed 8-bit quantity, i.e. values are -128 to 127, on all machines except for the SGI [at least for MIPS Computer Systems 2.0.] On the SGI it is an unsigned 8-bit quantity, i.e. values are 0 to 255, although the SGI 'FORTRAN 77 Programmers Guide' claims BYTE is signed. Perhaps MIPS 2.0 is dated, since the DECstations using MIPS 2.10 f77 have a signed BYTE. To minimize the difficulties of signed and unsigned BYTE, cfortran.h creates the type 'INTEGER_BYTE' to agree with FORTRAN's BYTE. Users may define SIGNED_BYTE or UNSIGNED_BYTE, before including cfortran.h, to specify FORTRAN's BYTE. If neither is defined, cfortran.h assumes SIGNED_BYTE. o CRAY The type DOUBLE in cfortran.h corresponds to FORTRAN's DOUBLE PRECISION. The type FLOAT in cfortran.h corresponds to FORTRAN's REAL. On a classic CRAY [i.e. all models except for the t3e]: ( 64 bit) C float == C double == Fortran REAL (128 bit) C long double == Fortran DOUBLE PRECISION Therefore when moving a mixed C and FORTRAN app. to/from a classic CRAY, either the C code will have to change, or the FORTRAN code and cfortran.h declarations will have to change. DOUBLE_PRECISION is a cfortran.h macro which provides the former option, i.e. the C code is automatically changed. DOUBLE_PRECISION is 'long double' on classic CRAY and 'double' elsewhere. DOUBLE_PRECISION thus corresponds to FORTRAN's DOUBLE PRECISION on all machines, including classic CRAY. On a classic CRAY with the fortran compiler flag '-dp': Fortran DOUBLE PRECISION thus is also the faster 64bit type. (This switch is often used since the application is usually satisfied by 64 bit precision and the application needs the speed.) DOUBLE_PRECISION is thus not required in this case, since the classic CRAY behaves like all other machines. If DOUBLE_PRECISION is used nonetheless, then on the classic CRAY the default cfortran.h behavior must be overridden, for example by the C compiler option '-DDOUBLE_PRECISION=double'. On a CRAY t3e: (32 bit) C float == Fortran Unavailable (64 bit) C double == C long double == Fortran REAL == Fortran DOUBLE PRECISION Notes: - (32 bit) is available as Fortran REAL*4 and (64 bit) is available as Fortran REAL*8. Since cfortran.h is all about more portability, not about less portability, the use of the nonstandard REAL*4 and REAL*8 is strongly discouraged. - Fortran DOUBLE PRECISION is folded to REAL with the following warning: 'DOUBLE PRECISION is not supported on this platform. REAL will be used.' Similarly, Fortran REAL*16 is mapped to REAL*8 with a warning. This behavior differs from that of other machines, including the classic CRAY. FORTRAN_REAL is thus introduced for the t3e, just as DOUBLE_PRECISION is introduced for the classic CRAY. FORTRAN_REAL is 'double' on t3e and 'float' elsewhere. FORTRAN_REAL thus corresponds to FORTRAN's REAL on all machines, including t3e. o f2c f2c, by default promotes REAL functions to double. cfortran.h does not (yet) support this, so the f2c -R option must be used to turn this promotion off. o f2c [Thanks to Dario Autiero for pointing out the following.] f2c has a strange feature in that either one or two underscores are appended to a Fortran name of a routine or common block, depending on whether or not the original name contains an underscore. S.I. Feldman et al., "A fortran to C converter", Computing Science Technical Report No. 149. page 2, chapter 2: INTERLANGUAGE conventions ........... To avoid conflict with the names of library routines and with names that f2c generates, Fortran names may have one or two underscores appended. Fortran names are forced to lower case (unless the -U option described in Appendix B is in effect); external names, i.e. the names of fortran procedures and common blocks, have a single underscore appended if they do not contain any underscore and have a pair of underscores appended if they do contain underscores. Thus fortran subroutines names ABC, A_B_C and A_B_C_ result in C functions named abc_, a_b_c__ and a_b_c___. ........... cfortran.h is unable to change the naming convention on a name by name basis. Fortran routine and common block names which do not contain an underscore are unaffected by this feature. Names which do contain an underscore may use the following work-around: /* First 2 lines are a completely standard cfortran.h interface to the Fortran routine E_ASY . */ PROTOCCALLSFSUB2(E_ASY,e_asy, PINT, INT) #define E_ASY(A,B) CCALLSFSUB2(E_ASY,e_asy, PINT, INT, A, B) #ifdef f2cFortran #define e_asy_ e_asy__ #endif /* Last three lines are a work-around for the strange f2c naming feature. */ o NAG f90 The Fortran 77 subset of Fortran 90 is supported. Extending cfortran.h to interface C with all of Fortran 90 has not yet been examined. The NAG f90 library hijacks the main() of any program and starts the user's program with a call to: void f90_main(void); While this in itself is only a minor hassle, a major problem arises because NAG f90 provides no mechanism to access command line arguments. At least version 'NAGWare f90 compiler Version 1.1(334)' appended _CB to common block names instead of the usual _. To fix, add this to cfortran.h: #ifdef old_NAG_f90_CB_COMMON #define COMMON_BLOCK CFC_ /* for all other Fortran compilers */ #else #define COMMON_BLOCK(UN,LN) _(LN,_CB) #endif o RS/6000 Using "xlf -qextname ...", which appends an underscore, '_', to all FORTRAN external references, requires "cc -Dextname ..." so that cfortran.h also generates these underscores. Use -Dextname=extname if extname is a symbol used in the C code. The use of "xlf -qextname" is STRONGLY ENCOURAGED, since it allows for transparent naming schemes when mixing C and Fortran. o HP9000 Using "f77 +ppu ...", which appends an underscore, '_', to all FORTRAN external references, requires "cc -Dextname ..." so that cfortran.h also generates these underscores. Use -Dextname=extname if extname is a symbol used in the C code. The use of "f77 +ppu" is STRONGLY ENCOURAGED, since it allows for transparent naming schemes when mixing C and Fortran. At least one release of the HP /lib/cpp.ansi preprocessor is broken and will go into an infinite loop when trying to process cfortran.h with the ## catenation operator. The K&R version of cfortran.h must then be used and the K&R preprocessor must be specified. e.g. HP9000> cc -Aa -tp,/lib/cpp -c source.c The same problem with a similar solution exists on the Apollo. An irrelevant error message '0: extraneous name /usr/include' will appear for each source file due to another HP bug, and can be safely ignored. e.g. 'cc -v -c -Aa -tp,/lib/cpp cfortest.c' will show that the driver passes '-I /usr/include' instead of '-I/usr/include' to /lib/cpp On some machines the above error causes compilation to stop; one must then use K&R C, as with old HP compilers which don't support function prototyping. cfortran.h has to be informed that K&R C is to being used, e.g. HP9000> cc -D__CF__KnR -c source.c o AbsoftUNIXFortran By default, cfortran.h follows the default AbsoftUNIX/ProFortran and prepends _C to each COMMON BLOCK name. To override the cfortran.h behavior #define COMMON_BLOCK(UN,LN) before #including cfortran.h. [Search for COMMON_BLOCK in cfortran.h for examples.] o Apollo On at least one release, 'C compiler 68K Rev6.8(168)', the default C preprocessor, from cc -A xansi or cc -A ansi, enters an infinite loop when using cfortran.h. This Apollo bug can be circumvented by using: . cc -DANSI_C_preprocessor=0 to force use of /**/, instead of '##'. AND . The pre-ANSI preprocessor, i.e. use cc -Yp,/usr/lib The same problem with a similar solution exists on the HP. o Sun Old versions of cc(1), say <~1986, may require help for cfortran.h applications: . #pragma may not be understood, hence cfortran.h and cfortest.c may require sun> mv cfortran.h cftmp.h && grep -v "^#pragma" cfortran.h sun> mv cfortest.c cftmp.c && grep -v "^#pragma" cfortest.c . Old copies of math.h may not include the following from a newer math.h. [For an ancient math.h on a 386 or sparc, get similar from a new math.h.] #ifdef mc68000 /* 5 lines Copyright (c) 1988 by Sun Microsystems, Inc. */ #define FLOATFUNCTIONTYPE int #define RETURNFLOAT(x) return (*(int *)(&(x))) #define ASSIGNFLOAT(x,y) *(int *)(&x) = y #endif o CRAY, Sun, Apollo [pre 6.8 cc], VAX Ultrix and HP9000 Only FORTRAN routines with less than 15 arguments can be prototyped for C, since these compilers don't allow more than 31 arguments to a C macro. This can be overcome, [see Section IV], with access to any C compiler without this limitation, e.g. gcc, on ANY machine. o VAX Ultrix vcc (1) with f77 is not supported. Although: VAXUltrix> f77 -c cfortex.f VAXUltrix> vcc -o cfortest cfortest.c cfortex.o -lI77 -lU77 -lF77 && cfortest will link and run. However, the FORTRAN standard I/O is NOT merged with the stdin and stdout of C, and instead uses the files fort.6 and fort.5. For vcc, f77 can't drive the linking, as for gcc and cc, since vcc objects must be linked using lk (1). f77 -v doesn't tell much, and without VAX Ultrix manuals, the author can only wait for the info. required. fort (1) is not supported. Without VAX Ultrix manuals the author cannot convince vcc/gcc/cc and fort to generate names of routines and COMMON blocks that match at the linker, lk (1). i.e. vcc/gcc/cc prepend a single underscore to external references, e.g. NAME becomes _NAME, while fort does not modify the references. So ... either fort has prepend an underscore to external references, or vcc/gcc/cc have to generate unmodified names. man 1 fort mentions JBL, is JBL the only way? o VAX VMS C The compiler 'easily' exhausts its table space and generates: %CC-F-BUGCHECK, Compiler bug check during parser phase . Submit an SPR with a problem description. At line number 777 in DISK:[DIR]FILE.C;1. where the line given, '777', includes a call across C and FORTRAN via cfortran.h, usually with >7 arguments and/or very long argument expressions. This SPR can be staved off, with the simple modification to cfortran.h, such that the relevant CCALLSFSUBn (or CCALLSFFUNn or FCALLSCFUNn) is not cascaded up to CCALLSFSUB14, and instead has its own copy of the contents of CCALLSFSUB14. [If these instructions are not obvious after examining cfortran.h please contact the author.] [Thanks go to Mark Kyprianou (kyp@stsci.edu) for this solution.] o Mips compilers e.g. DECstations and SGI, require applications with a C main() and calls to GETARG(3F), i.e. FORTRAN routines returning the command line arguments, to use two macros as shown: : CF_DECLARE_GETARG; /* This must be external to all routines. */ : main(int argc, char *argv[]) { : CF_SET_GETARG(argc,argv); /* This must precede any calls to GETARG(3F). */ : } The macros are null and benign on all other systems. Sun's GETARG(3F) also doesn't work with a generic C main() and perhaps a workaround similar to the Mips' one exists. o Alpha/OSF Using the DEC Fortran and the DEC C compilers of DEC OSF/1 [RT] V1.2 (Rev. 10), Fortran, when called from C, has occasional trouble using a routine received as a dummy argument. e.g. In the following the Fortran routine 'e' will crash when it tries to use the C routine 'c' or the Fortran routine 'f'. The example works on other systems. C FORTRAN /* C */ integer function f() #include f = 2 int f_(); return int e_(int (*u)()); end int c(){ return 1;} integer function e(u) int d (int (*u)()) { return u();} integer u external u main() e=u() { /* Calls to d work. */ return printf("d (c ) returns %d.\n",d (c )); end printf("d (f_) returns %d.\n",d (f_)); /* Calls to e_ crash. */ printf("e_(c ) returns %d.\n",e_(c )); printf("e_(f_) returns %d.\n",e_(f_)); } Solutions to the problem are welcomed! A kludge which allows the above example to work correctly, requires an extra argument to be given when calling the dummy argument function. i.e. Replacing 'e=u()' by 'e=u(1)' allows the above example to work. o The FORTRAN routines are called using macro expansions, therefore the usual caveats for expressions in arguments apply. The expressions to the routines may be evaluated more than once, leading to lower performance and in the worst case bizarre bugs. o For those who wish to use cfortran.h in large applications. [See Section IV.] This release is intended to make it easy to get applications up and running. This implies that applications are not as efficient as they could be: - The current mechanism is inefficient if a single header file is used to describe a large library of FORTRAN functions. Code for a static wrapper fn. is generated in each piece of C source code for each FORTRAN function specified with the CCALLSFFUNn statement, irrespective of whether or not the function is ever called. - Code for several static utility routines internal to cfortran.h is placed into any source code which #includes cfortran.h. These routines should probably be in a library. i) Calling FORTRAN routines from C: -------------------------------- The FORTRAN routines are defined by one of the following two instructions: for a SUBROUTINE: /* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */ PROTOCCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) #define Routine_name(argname_1,..,argname_n) \ CCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \ argname_1,..,argname_n) for a FUNCTION: PROTOCCALLSFFUNn(routine_type,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) #define Routine_name(argname_1,..,argname_n) \ CCALLSFFUNn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \ argname_1,..,argname_n) Where: 'n' = 0->14 [SUBROUTINE's ->27] (easily expanded in cfortran.h to > 14 [27]) is the number of arguments to the routine. Routine_name = C name of the routine (IN UPPER CASE LETTERS).[see 2.below] ROUTINE_NAME = FORTRAN name of the routine (IN UPPER CASE LETTERS). routine_name = FORTRAN name of the routine (IN lower case LETTERS). routine_type = the type of argument returned by FORTRAN functions. = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID. [Instead of VOID one would usually use CCALLSFSUBn. VOID forces a wrapper function to be used.] argtype_i = the type of argument passed to the FORTRAN routine and must be consistent in the definition and prototyping of the routine s.a. = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING. For vectors, i.e. 1 dim. arrays use = BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, STRINGV, ZTRINGV. For vectors of vectors, i.e. 2 dim. arrays use = BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. For n-dim. arrays, 1<=n<=7 [7 is the maximum in Fortran 77], = BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. N.B. Array dimensions and types are checked by the C compiler. For routines changing the values of an argument, the keyword is prepended by a 'P'. = PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT, PSTRING, PSTRINGV, PZTRINGV. For EXTERNAL procedures passed as arguments use = ROUTINE. For exceptional arguments which require no massaging to fit the argument passing mechanisms use = PVOID. The argument is cast and passed as (void *). Although PVOID could be used to describe all array arguments on most (all?) machines , it shouldn't be because the C compiler can no longer check the type and dimension of the array. argname_i = any valid unique C tag, but must be consistent in the definition as shown. Notes: 1. cfortran.h may be expanded to handle a more argument type. To suppport new arguments requiring complicated massaging when passed between Fortran and C, the user will have to understand cfortran.h and follow its code and mechanisms. To define types requiring little or no massaging when passed between Fortran and C, the pseudo argument type SIMPLE may be used. For a user defined type called 'newtype', the definitions required are: /* The following 7 lines are required verbatim. 'newtype' is the name of the new user defined argument type. */ #define newtype_cfV( T,A,B,F) SIMPLE_cfV(T,A,B,F) #define newtype_cfSEP(T, B) SIMPLE_cfSEP(T,B) #define newtype_cfINT(N,A,B,X,Y,Z) SIMPLE_cfINT(N,A,B,X,Y,Z) #define newtype_cfSTR(N,T,A,B,C,D,E) SIMPLE_cfSTR(N,T,A,B,C,D,E) #define newtype_cfCC( T,A,B) SIMPLE_cfCC(T,A,B) #define newtype_cfAA( T,A,B) newtype_cfB(T,A) /* Argument B not used. */ #define newtype_cfU( T,A) newtype_cfN(T,A) /* 'parameter_type(A)' is a declaration for 'A' and describes the type of the parameter expected by the Fortran function. This type will be used in the prototype for the function, if using ANSI C, and to declare the argument used by the intermediate function if calling a Fortran FUNCTION. Valid 'parameter_type(A)' include: int A void (*A)() double A[17] */ #define newtype_cfN( T,A) parameter_type(A) /* Argument T not used. */ /* Before any argument of the new type is passed to the Fortran routine, it may be massaged as given by 'massage(A)'. */ #define newtype_cfB( T,A) massage(A) /* Argument T not used. */ An example of a simple user defined type is given cfortex.f and cfortest.c. Two uses of SIMPLE user defined types are [don't show the 7 verbatim #defines]: /* Pass the address of a structure, using a type called PSTRUCT */ #define PSTRUCT_cfN( T,A) void *A #define PSTRUCT_cfB( T,A) (void *) &(A) /* Pass an integer by value, (not standard F77 ), using a type called INTVAL */ #define INTVAL_cfN( T,A) int A #define INTVAL_cfB( T,A) (A) [If using VAX VMS, surrounding the #defines with "#pragma (no)standard" allows the %CC-I-PARAMNOTUSED messages to be avoided.] Upgrades to cfortran.h try to be, and have been, backwards compatible. This compatibility cannot be offered to user defined types. SIMPLE user defined types are less of a risk since they require so little effort in their creation. If a user defined type is required in more than one C header file of interfaces to libraries of Fortran routines, good programming practice, and ease of code maintenance, suggests keeping any user defined type within a single file which is #included as required. To date, changes to the SIMPLE macros were introduced in versions 2.6, 3.0 and 3.2 of cfortran.h. 2. Routine_name is the name of the macro which the C programmer will use in order to call a FORTRAN routine. In theory Routine_name could be any valid and unique name, but in practice, the name of the FORTRAN routine in UPPER CASE works everywhere and would seem to be an obvious choice. 3. cfortran.h encourages the exact specification of the type and dimension of array parameters because it allows the C compiler to detect errors in the arguments when calling the routine. cfortran.h does not strictly require the exact specification since the argument is merely the address of the array and is passed on to the calling routine. Any array parameter could be declared as PVOID, but this circumvents C's compiletime ability to check the correctness of arguments and is therefore discouraged. Passing the address of these arguments implies that PBYTEV, PFLOATV, ... , PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the calling code share the same array, i.e. the same values at the same memory location. These comments do NOT apply to arrays of (P)S/ZTRINGV. For these parameters, cfortran.h passes a massaged copy of the array to the routine. When the routine returns, S/ZTRINGV ignores the copy, while PS/ZTRINGV replaces the calling code's original array with copy, which may have been modified by the called routine. 4. (P)STRING(V): - STRING - If the argument is a fixed length character array, e.g. char ar[8];, the string is blank, ' ', padded on the right to fill out the array before being passed to the FORTRAN routine. The useful size of the string is the same in both languages, e.g. ar[8] is passed as character*7. If the argument is a pointer, the string cannot be blank padded, so the length is passed as strlen(argument). On return from the FORTRAN routine, pointer arguments are not disturbed, but arrays have the terminating '\0' replaced to its original position. i.e. The padding blanks are never visible to the C code. - PSTRING - The argument is massaged as with STRING before being passed to the FORTRAN routine. On return, the argument has all trailing blanks removed, regardless of whether the argument was a pointer or an array. - (P)STRINGV - Passes a 1- or 2-dimensional char array. e.g. char a[7],b[6][8]; STRINGV may thus also pass a string constant, e.g. "hiho". (P)STRINGV does NOT pass a pointer, e.g. char *, to either a 1- or a 2-dimensional array, since it cannot determine the array dimensions. A pointer can only be passed using (P)ZTRINGV. N.B. If a C routine receives a character array argument, e.g. char a[2][3], such an argument is actually a pointer and my thus not be passed by (P)STRINGV. Instead (P)ZTRINGV must be used. - STRINGV - The elements of the argument are copied into space malloc'd, and each element is padded with blanks. The useful size of each element is the same in both languages. Therefore char bb[6][8]; is equivalent to character*7 bb(6). On return from the routine the malloc'd space is simply released. - PSTRINGV - Since FORTRAN has no trailing '\0', elements in an array of strings are contiguous. Therefore each element of the C array is padded with blanks and strip out C's trailing '\0'. After returning from the routine, the trailing '\0' is reinserted and kill the trailing blanks in each element. - SUMMARY: STRING(V) arguments are blank padded during the call to the FORTRAN routine, but remain original in the C code. (P)STRINGV arguments are blank padded for the FORTRAN call, and after returning from FORTRAN trailing blanks are stripped off. 5. (P)ZTRINGV: - (P)ZTRINGV - is identical to (P)STRINGV, except that the dimensions of the array of strings is explicitly specified, which thus also allows a pointer to be passed. (P)ZTRINGV can thus pass a 1- or 2-dimensional char array, e.g. char b[6][8], or it can pass a pointer to such an array, e.g. char *p;. ZTRINGV may thus also pass a string constant, e.g. "hiho". If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1. [Users of (P)ZTRINGV should examine cfortest.c for examples.]: - (P)ZTRINGV must thus be used instead of (P)STRINGV whenever sizeof() can't be used to determine the dimensions of the array of string or strings. e.g. when calling FORTRAN from C with a char * received by C as an argument. - There is no (P)ZTRING type, since (P)ZTRINGV can pass a 1-dimensional array or a pointer to such an array, e.g. char a[7], *b; If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1. - To specify the numbers of elements, routine_name_ELEMS_j and routine_name_ELEMLEN_j must be defined as shown below before interfacing the routine with CCALLSFSUBn, PROTOCCALLSFFUNn, etc. #define routine_name_ELEMS_j ZTRINGV_ARGS(k) [..ARGS for subroutines, ..ARGF for functions.] or #define routine_name_ELEMS_j ZTRINGV_NUM(l) Where: routine_name is as above. j [1-n], is the argument being specifying. k [1-n], the value of the k'th argument is the dynamic number of elements for argument j. The k'th argument must be of type BYTE, DOUBLE, FLOAT, INT, LONG or SHORT. l the number of elements for argument j. This must be an integer constant available at compile time. i.e. it is static. - Similarly to specify the useful length, [i.e. don't count C's trailing '\0',] of each element: #define routine_name_ELEMLEN_j ZTRINGV_ARGS(m) [..ARGS for subroutines, ..ARGF for functions.] or #define routine_name_ELEMLEN_j ZTRINGV_NUM(q) Where: m [1-n], as for k but this is the length of each element. q as for l but this is the length of each element. 6. ROUTINE The argument is an EXTERNAL procedure. When C passes a routine to Fortran, the language of the function must be specified as follows: [The case of some_*_function must be given as shown.] When C passes a C routine to a Fortran: FORTRAN_ROUTINE(arg1, .... , C_FUNCTION(SOME_C_FUNCTION,some_c_function), ...., argn); and similarly when C passes a Fortran routine to Fortran: FORTRAN_ROUTINE(arg1, .... , FORTRAN_FUNCTION(SOME_FORT_FUNCTION,some_fort_function), ...., argn); If fcallsc has been redefined; the same definition of fcallsc used when creating the wrapper for 'some_c_function' must also be defined when C_FUNCTION is used. See ii) 4. of this section for when and how to redefine fcallsc. ROUTINE was introduced with cfortran.h version 2.6. Earlier versions of cfortran.h used PVOID to pass external procedures as arguments. Using PVOID for this purpose is no longer recommended since it won't work 'as is' for apolloFortran, hpuxFortran800, AbsoftUNIXFortran, AbsoftProFortran. 7. CRAY only: In a given piece of source code, where FFUNC is any FORTRAN routine, FORTRAN_FUNCTION(FFUNC,ffunc) disallows a previous #define FFUNC(..) CCALLSFSUBn(FFUNC,ffunc,...) [ or CCALLSFFUNn] in order to make the UPPER CASE FFUNC callable from C. #define Ffunc(..) ... is OK though, as are obviously any other names. ii) Calling C routines from FORTRAN: -------------------------------- Each of the following two statements to export a C routine to FORTRAN create FORTRAN 'wrappers', written in C, which must be compiled and linked along with the original C routines and with the FORTRAN calling code. FORTRAN callable 'wrappers' may also be created for C macros. i.e. in this section, the term 'C function' may be replaced by 'C macro'. for C functions returning void: FCALLSCSUBn( Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) for all other C functions: FCALLSCFUNn(routine_type,Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) Where: 'n' = 0->27 (easily expanded to > 27) stands for the number of arguments to the routine. Routine_name = the C name of the routine. [see 9. below] ROUTINE_NAME = the FORTRAN name of the routine (IN UPPER CASE LETTERS). routine_name = the FORTRAN name of the routine (IN lower case LETTERS). routine_type = the type of argument returned by C functions. = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID. [Instead of VOID, FCALLSCSUBn is recommended.] argtype_i = the type of argument passed to the FORTRAN routine and must be consistent in the definition and prototyping of the routine = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING. For vectors, i.e. 1 dim. arrays use = BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, STRINGV. For vectors of vectors, 2 dim. arrays use = BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. For n-dim. arrays use = BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. For routines changing the values of an argument, the keyword is prepended by a 'P'. = PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT, PSTRING, PNSTRING, PPSTRING, PSTRINGV. For EXTERNAL procedures passed as arguments use = ROUTINE. For exceptional arguments which require no massaging to fit the argument passing mechanisms use = PVOID. The argument is cast and passed as (void *). Notes: 0. For Fortran calling C++ routines, C++ does NOT easily allow support for: STRINGV. BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. BYTEV..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. Though there are ways to get around this restriction, the restriction is not serious since these types are unlikely to be used as arguments for a C++ routine. 1. FCALLSCSUB/FUNn expect that the routine to be 'wrapped' has been properly prototyped, or at least declared. 2. cfortran.h may be expanded to handle a new argument type not already among the above. 3. cfortran.h encourages the exact specification of the type and dimension of array parameters because it allows the C compiler to detect errors in the arguments when declaring the routine using FCALLSCSUB/FUNn, assuming the routine to be 'wrapped' has been properly prototyped. cfortran.h does not strictly require the exact specification since the argument is merely the address of the array and is passed on to the calling routine. Any array parameter could be declared as PVOID, but this circumvents C's compiletime ability to check the correctness of arguments and is therefore discouraged. Passing the address of these arguments implies that PBYTEV, PFLOATV, ... , PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the calling code share the same array, i.e. the same values at the same memory location. These comments do NOT apply to arrays of (P)STRINGV. For these parameters, cfortran.h passes a massaged copy of the array to the routine. When the routine returns, STRINGV ignores the copy, while PSTRINGV replaces the calling code's original array with copy, which may have been modified by the called routine. 4. (P(N))STRING arguments have any trailing blanks removed before being passed to C, the same holds true for each element in (P)STRINGV. Space is malloc'd in all cases big enough to hold the original string (elements) as well as C's terminating '\0'. i.e. The useful size of the string (elements) is the same in both languages. P(N)STRING(V) => the string (elements) will be copied from the malloc'd space back into the FORTRAN bytes. If one of the two escape mechanisms mentioned below for PNSTRING has been used, the copying back to FORTRAN is obviously not relevant. 5. (PN)STRING's, [NOT PSTRING's nor (P)STRINGV's,] behavior may be overridden in two cases. In both cases PNSTRING and STRING behave identically. a) If a (PN)STRING argument's first 4 bytes are all the NUL character, i.e. '\0\0\0\0' the NULL pointer is passed to the C routine. b) If the characters of a (PN)STRING argument contain at least one HEX-00, i.e. the NUL character, i.e. C strings' terminating '\0', the address of the string is simply passed to the C routine. i.e. The argument is treated in this case as it would be with PPSTRING, to which we refer the reader for more detail. Mechanism a) overrides b). Therefore, to use this mechanism to pass the NULL string, "", to C, the first character of the string must obviously be the NUL character, but of the first 4 characters in the string, at least one must not be HEX-00. Example: C FORTRAN /* C */ character*40 str #include "cfortran.h" C Set up a NULL as : void cs(char *s) {if (s) printf("%s.\n",s);} C i) 4 NUL characters. FCALLSCSUB1(cs,CS,cs,STRING) C ii) NULL pointer. character*4 NULL NULL = CHAR(0)//CHAR(0)//CHAR(0)//CHAR(0) data str/'just some string'/ C Passing the NULL pointer to cs. call cs(NULL) C Passing a copy of 'str' to cs. call cs(str) C Passing address of 'str' to cs. Trailing blanks NOT killed. str(40:) = NULL call cs(str) end Strings passed from Fortran to C via (PN)STRING must not have undefined contents, otherwise undefined behavior will result, since one of the above two escape mechanisms may occur depending on the contents of the string. This is not be a problem for STRING arguments, which are read-only in the C routine and hence must have a well defined value when being passed in. PNSTRING arguments require special care. Even if they are write-only in the C routine, PNSTRING's above two escape mechanisms require that the value of the argument be well defined when being passed in from Fortran to C. Therefore, unless one or both of PNSTRING's escape mechanisms are required, PSTRING should be used instead of PNSTRING. Prior to version 2.8, PSTRING did have the above two escape mechanisms, but they were removed from PSTRING to allow strings with undefined contents to be passed in. PNSTRING behaves like the old PSTRING. [Thanks go to Paul Dubois (dubios@icf.llnl.gov) for pointing out that PSTRING must allow for strings with undefined contents to be passed in.] Example: C FORTRAN /* C */ character*10 s,sn #include "cfortran.h" void ps(char *s) {strcpy(s,"hello");} C Can call ps with undef. s. FCALLSCSUB1(ps,PS,ps,PSTRING) call ps(s) FCALLSCSUB1(ps,PNS,pns,PNSTRING) print *,s,'=s' C Can't call pns with undef. s. C e.g. If first 4 bytes of s were C "\0\0\0\0", ps would try C to copy to NULL because C of PNSTRING mechanism. sn = "" call pns(sn) print *,sn,'=sn' end 6. PPSTRING The address of the string argument is simply passed to the C routine. Therefore the C routine and the FORTRAN calling code share the same string at the same memory location. If the C routine modifies the string, the string will also be modified for the FORTRAN calling code. The user is responsible for negociating the differences in representation of a string in Fortran and in C, i.e. the differences are not automatically resolved as they are for (P(N)STRING(V). This mechanism is provided for two reasons: - Some C routines require the string to exist at the given memory location, after the C routine has exited. Recall that for the usual (P(N)STRING(V) mechanism, a copy of the FORTRAN string is given to the C routine, and this copy ceases to exist after returning to the FORTRAN calling code. - This mechanism can save runtime CPU cycles over (P(N)STRING(V), since it does not perform their malloc, copy and kill trailing blanks of the string to be passed. Only in a small minority of cases does the potential benefit of the saved CPU cycles outweigh the programming effort required to manually resolve the differences in representation of a string in Fortran and in C. For arguments passed via PPSTRING, the argument passed may also be an array of strings. 7. ROUTINE ANSI C requires that the type of the value returned by the routine be known, For all ROUTINE arguments passed from Fortran to C, the type of ROUTINE is specified by defining a cast as follows: #undef ROUTINE_j #define ROUTINE_j (cast) where: j [1-n], is the argument being specifying. (cast) is a cast matching that of the argument expected by the C function protoytpe for which a wrapper is being defined. e.g. To create a Fortran wrapper for qsort(3C): #undef ROUTINE_4 #define ROUTINE_4 (int (*)(void *,void *)) FCALLSCSUB4(qsort,FQSORT,fqsort,PVOID,INT,INT,ROUTINE) In order to maintain backward compatibility, cfortran.h defines a generic cast for ROUTINE_1, ROUTINE_2, ..., ROUTINE_27. The user's definition is therefore strictly required only for DEC C, which at the moment is the only compiler which insists on the correct cast for pointers to functions. When using the ROUTINE argument inside some Fortran code: - it is difficult to pass a C routine as the parameter, since in many Fortran implementations, Fortran has no access to the normal C namespace. e.g. For most UNIX, Fortran implicitly only has access to C routines ending in _. If the calling Fortran code receives the routine as a parameter it can of course easily pass it along. - if a Fortran routine is passed directly as the parameter, the called C routine must call the parameter routine using the Fortran argument passing conventions. - if a Fortran routine is to be passed as the parameter, but if Fortran can be made to pass a C routine as the parameter, then it may be best to pass a C-callable wrapper for the Fortran routine. The called C routine is thus spared all Fortran argument passing conventions. cfortran.h can be used to create such a C-callable wrapper to the parameter Fortran routine. ONLY PowerStationFortran: This Fortran provides no easy way to pass a Fortran routine as an argument to a C routine. The problem arises because in Fortran the stack is cleared by the called routine, while in C/C++ it is cleared by the caller. The C/C++ stack clearing behavior can be changed to that of Fortran by using stdcall__ in the function prototype. The stdcall__ cannot be applied in this case since the called C routine expects the ROUTINE parameter to be a C routine and does not know that it should apply stdcall__. In principle the cfortran.h generated Fortran callable wrapper for the called C routine should be able to massage the ROUTINE argument such that stdcall__ is performed, but it is not yet known how this could be easily done. 8. THE FOLLOWING INSTRUCTIONS ARE NOT REQUIRED FOR VAX VMS ------------ (P)STRINGV information [NOT required for VAX VMS]: cfortran.h cannot convert the FORTRAN vector of STRINGS to the required C vector of STRINGS without explicitly knowing the number of elements in the vector. The application must do one of the following for each (P)STRINGV argument in a routine before that routine's FCALLSCFUNn/SUBn is called: #define routine_name_STRV_Ai NUM_ELEMS(j) or #define routine_name_STRV_Ai NUM_ELEM_ARG(k) or #define routine_name_STRV_Ai TERM_CHARS(l,m) where: routine_name is as above. i [i=1->n.] specifies the argument number of a STRING VECTOR. j would specify a fixed number of elements. k [k=1->n. k!=i] would specify an integer argument which specifies the number of elements. l [char] the terminating character at the beginning of an element, indicating to cfortran.h that the preceding elements in the vector are the valid ones. m [m=1-...] the number of terminating characters required to appear at the beginning of the terminating string element. The terminating element is NOT passed on to the C routine. e.g. #define ce_STRV_A1 TERM_CHARS(' ',2) FCALLSCSUB1(ce,CE,ce,STRINGV) cfortran.h will pass on all elements, in the 1st and only argument to the C routine ce, of the STRING VECTOR until, but not including, the first string element beginning with 2 blank, ' ', characters. 9. INSTRUCTIONS REQUIRED ONLY FOR FORTRAN COMPILERS WHICH GENERATE ------------- ROUTINE NAMES WHICH ARE UNDISTINGUISHABLE FROM C ROUTINE NAMES i.e. VAX VMS AbsoftUNIXFortran (AbsoftProFortran ok, since it uses Uppercase names.) HP9000 if not using the +ppu option of f77 IBM RS/6000 if not using the -qextname option of xlf Call them the same_namespace compilers. FCALLSCSUBn(...) and FCALLSCFUNn(...), when compiled, are expanded into 'wrapper' functions, so called because they wrap around the original C functions and interface the format of the original C functions' arguments and return values with the format of the FORTRAN call. Ideally one wants to be able to call the C routine from FORTRAN using the same name as the original C name. This is not a problem for FORTRAN compilers which append an underscore, '_', to the names of routines, since the original C routine has the name 'name', and the FORTRAN wrapper is called 'name_'. Similarly, if the FORTRAN compiler generates upper case names for routines, the original C routine 'name' can have a wrapper called 'NAME', [Assuming the C routine name is not in upper case.] For these compilers, e.g. Mips, CRAY, IBM RS/6000 'xlf -qextname', HP-UX 'f77 +ppu', the naming of the wrappers is done automatically. For same_namespace compilers things are not as simple, but cfortran.h tries to provide tools and guidelines to minimize the costs involved in meeting their constraints. The following two options can provide same_namespace compilers with distinct names for the wrapper and the original C function. These compilers are flagged by cfortran.h with the CF_SAME_NAMESPACE constant, so that the change in the C name occurs only when required. For the remainder of the discussion, routine names generated by FORTRAN compilers are referred to in lower case, these names should be read as upper case for the appropriate compilers. HP9000: (When f77 +ppu is not used.) f77 has a -U option which forces uppercase external names to be generated. Unfortunately, cc does not handle recursive macros. Hence, if one wished to use -U for separate C and FORTRAN namespaces, one would have to adopt a different convention of naming the macros which allow C to call FORTRAN subroutines. (Functions are not a problem.) The macros are currently the uppercase of the original FORTRAN name, and would have to be changed to lower case or mixed case, or to a different name. (Lower case would of course cause conflicts on many other machines.) Therefore, it is suggested that f77 -U not be used, and instead that Option a) or Option b) outlined below be used. VAX/VMS: For the name used by FORTRAN in calling a C routine to be the same as that of the C routine, the source code of the C routine is required. A preprocessor directive can then force the C compiler to generate a different name for the C routine. e.g. #if defined(vms) #define name name_ #endif void name() {printf("name: was called.\n");} FCALLSCSUB0(name,NAME,name) In the above, the C compiler generates the original routine with the name 'name_' and a wrapper called 'NAME'. This assumes that the name of the routine, as seen by the C programmer, is not in upper case. The VAX VMS linker is not case sensitive, allowing cfortran.h to export the upper case name as the wrapper, which then doesn't conflict with the routine name in C. Since the IBM, HP and AbsoftUNIXFortran platforms have case sensitive linkers this technique is not available to them. The above technique is required even if the C name is in mixed case, see Option a) for the other compilers, but is obviously not required when Option b) is used. Option a) Mixed Case names for the C routines to be called by FORTRAN. If the original C routines have mixed case names, there are no name space conflicts. Nevertheless for VAX/VMS, the technique outlined above must also used. Option b) Modifying the names of C routines when used by FORTRAN: The more robust naming mechanism, which guarantees portability to all machines, 'renames' C routines when called by FORTRAN. Indeed, one must change the names on same_namespace compilers when FORTRAN calls C routines for which the source is unavailable. [Even when the source is available, renaming may be preferable to Option a) for large libraries of C routines.] Obviously, if done for a single type of machine, it must be done for all machines since the names of routines used in FORTRAN code cannot be easily redefined for different machines. The simplest way to achieve this end is to do explicitly give the modified FORTRAN name in the FCALLSCSUBn(...) and FCALLSCFUNn(...) declarations. e.g. FCALLSCSUB0(name,CFNAME,cfname) This allows FORTRAN to call the C routine 'name' as 'cfname'. Any name can of course be used for a given routine when it is called from FORTRAN, although this is discouraged due to the confusion it is sure to cause. e.g. Bizarre, but valid and allowing C's 'call_back' routine to be called from FORTRAN as 'abcd': FCALLSCSUB0(call_back,ABCD,abcd) cfortran.h also provides preprocessor directives for a systematic 'renaming' of the C routines when they are called from FORTRAN. This is done by redefining the fcallsc macro before the FCALLSCSUB/FUN/n declarations as follows: #undef fcallsc #define fcallsc(UN,LN) preface_fcallsc(CF,cf,UN,LN) FCALLSCSUB0(hello,HELLO,hello) Will cause C's routine 'hello' to be known in FORTRAN as 'cfhello'. Similarly all subsequent FCALLSCSUB/FUN/n declarations will generate wrappers to allow FORTRAN to call C with the C routine's name prefaced by 'cf'. The following has the same effect, with subsequent FCALLSCSUB/FUN/n's appending the modifier to the original C routines name. #undef fcallsc #define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN) FCALLSCSUB0(Xroutine,ROUTINE,routine) Hence, C's Xroutine is called from FORTRAN as: CALL XROUTINEY() The original behavior of FCALLSCSUB/FUN/n, where FORTRAN routine names are left identical to those of C, is returned using: #undef fcallsc #define fcallsc(UN,LN) orig_fcallsc(UN,LN) In C, when passing a C routine, i.e. its wrapper, as an argument to a FORTRAN routine, the FORTRAN name declared is used and the correct fcallsc must be in effect. E.g. Passing 'name' and 'routine' of the above examples to the FORTRAN routines, FT1 and FT2, respectively: /* This might not be needed if fcallsc is already orig_fcallsc. */ #undef fcallsc #define fcallsc(UN,LN) orig_fcallsc(UN,LN) FT1(C_FUNCTION(CFNAME,cfname)); #undef fcallsc #define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN) FT1(C_FUNCTION(XROUTINE,xroutine)); If the names of C routines are modified when used by FORTRAN, fcallsc would usually be defined once in a header_file.h for the application. This definition would then be used and be valid for the entire application and fcallsc would at no point need to be redefined. ONCE AGAIN: THE DEFINITIONS, INSTRUCTIONS, DECLARATIONS AND DIFFICULTIES DESCRIBED HERE, NOTE 9. of II ii), APPLY ONLY FOR VAX VMS, IBM RS/6000 WITHOUT THE -qextname OPTION FOR xlf, OR HP-UX WITHOUT THE +ppu OPTION FOR f77 AbsoftUNIXFortran AND APPLY ONLY WHEN CREATING WRAPPERS WHICH ENABLE FORTRAN TO CALL C ROUTINES. iii) Using C to manipulate FORTRAN COMMON BLOCKS: ------------------------------------------------------- FORTRAN common blocks are set up with the following three constructs: 1. #define Common_block_name COMMON_BLOCK(COMMON_BLOCK_NAME,common_block_name) Common_block_name is in UPPER CASE. COMMON_BLOCK_NAME is in UPPER CASE. common_block_name is in lower case. [Common_block_name actually follows the same 'rules' as Routine_name in Note 2. of II i).] This construct exists to ensure that C code accessing the common block is machine independent. 2. COMMON_BLOCK_DEF(TYPEDEF_OF_STRUCT, Common_block_name); where typedef { ... } TYPEDEF_OF_STRUCT; declares the structure which maps on to the common block. The #define of Common_block_name must come before the use of COMMON_BLOCK_DEF. 3. In exactly one of the C source files, storage should be set aside for the common block with the definition: TYPEDEF_OF_STRUCT Common_block_name; The above definition may have to be omitted on some machines for a common block which is initialized by Fortran BLOCK DATA or is declared with a smaller size in the C routines than in the Fortran routines. The rules for common blocks are not well defined when linking/loading a mixture of C and Fortran, but the following information may help resolve problems. From the 2nd or ANSI ed. of K&R C, p.31, last paragraph: i) An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. ii) The variable must also be declared in each function that wants to access it; ... The declaration ... may be implicit from context. In Fortran, every routine says 'common /bar/ foo', i.e. part ii) of the above, but there's no part i) requirement. cc/ld on some machines don't require i) either. Therefore, when handling Fortran, and sometimes C, the loader/linker must automagically set aside storage for common blocks. Some loaders, including at least one for the CRAY, turn off the 'automagically set aside storage' capability for Fortran common blocks, if any C object declares that common block. Therefore, C code should define, i.e. set aside storage, for the the common block as shown above. e.g. C Fortran common /fcb/ v,w,x character *(13) v, w(4), x(3,2) /* C */ typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF; #define Fcb COMMON_BLOCK(FCB,fcb) COMMON_BLOCK_DEF(FCB_DEF,Fcb); FCB_DEF Fcb; /* Definition, which sets aside storage for Fcb, */ /* may appear in at most one C source file. */ C programs can place a string (or a multidimensional array of strings) into a FORTRAN common block using the following call: C2FCBSTR( CSTR, FSTR,DIMENSIONS); where: CSTR is a pointer to the first element of C's copy of the string (array). The C code must use a duplicate of, not the original, common block string, because the FORTRAN common block does not allocate space for C strings' terminating '\0'. FSTR is a pointer to the first element of the string (array) in the common block. DIMENSIONS is the number of dimensions of string array. e.g. char a[10] has DIMENSIONS=0. char aa[10][17] has DIMENSIONS=1. etc... C2FCBSTR will copy the string (array) from CSTR to FSTR, padding with blanks, ' ', the trailing characters as required. C2FCBSTR uses DIMENSIONS and FSTR to determine the lengths of the individual string elements and the total number of elements in the string array. Note that: - the number of string elements in CSTR and FSTR are identical. - for arrays of strings, the useful lengths of strings in CSTR and FSTR must be the same. i.e. CSTR elements each have 1 extra character to accommodate the terminating '\0'. - On most non-ANSI compilers, the DIMENSION argument cannot be prepended by any blanks. FCB2CSTR( FSTR, CSTR,DIMENSIONS) is the inverse of C2FCBSTR, and shares the same arguments and caveats. FCB2CSTR copies each string element of FSTR to CSTR, minus FORTRAN strings' trailing blanks. cfortran.h USERS ARE STRONGLY URGED TO EXAMINE THE COMMON BLOCK EXAMPLES IN cfortest.c AND cfortex.f. The use of strings in common blocks is demonstrated, along with a suggested way for C to imitate FORTRAN EQUIVALENCE'd variables. ===> USERS OF CFORTRAN.H NEED READ NO FURTHER <=== III Some Musings ---------------- cfortran.h is simple enough to be used by the most basic of applications, i.e. making a single C/FORTRAN routine available to the FORTRAN/C programmers. Yet cfortran.h is powerful enough to easily make entire C/FORTRAN libraries available to FORTRAN/C programmers. cfortran.h is the ideal tool for FORTRAN libraries which are being (re)written in C, but are to (continue to) support FORTRAN users. It allows the routines to be written in 'natural C', without having to consider the FORTRAN argument passing mechanisms of any machine. It also allows C code accessing these rewritten routines, to use the C entry point. Without cfortran.h, one risks the perverse practice of C code calling a C function using FORTRAN argument passing mechanisms! Perhaps the philosophy and mechanisms of cfortran.h could be used and extended to create other language bridges such as ADAFORTRAN, CPASCAL, COCCAM, etc. The code generation machinery inside cfortran.h, i.e. the global structure is quite good, being clean and workable as seen by its ability to meet the needs and constraints of many different compilers. Though the individual instructions of the A..., C..., T..., R... and K... tables deserve to be cleaned up. IV Getting Serious with cfortran.h ----------------------------------- cfortran.h is set up to be as simple as possible for the casual user. While this ease of use will always be present, 'hooks', i.e. preprocessor directives, are required in cfortran.h so that some of the following 'inefficiencies' can be eliminated if they cause difficulties: o cfortran.h contains a few small routines for string manipulation. These routines are declared static and are included and compiled in all source code which uses cfortran.h. Hooks should be provided in cfortran.h to create an object file of these routines, allowing cfortran.h to merely prototypes these routines in the application source code. This is the only 'problem' which afflicts both halves of cfortran.h. The remaining discussion refers to the C calls FORTRAN half only. o Similar to the above routines, cfortran.h generates code for a 'wrapper' routine for each FUNCTION exported from FORTRAN. Again cfortran.h needs preprocessor directives to create a single object file of these routines, and to merely prototype them in the applications. o Libraries often contain hundreds of routines. While the preprocessor makes quick work of generating the required interface code from cfortran.h and the application.h's, it may be convenient for very large stable libraries to have final_application.h's which already contain the interface code, i.e. these final_application.h's would not require cfortran.h. [The convenience can be imagined for the VAX VMS CC compiler which has a fixed amount of memory for preprocessor directives. Not requiring cfortran.h, with its hundreds of directives, could help prevent this compiler from choking on its internal limits quite so often.] With a similar goal in mind, cfortran.h defines 100's of preprocessor directives. There is always the potential that these will clash with other tags in the users code, so final_applications.h, which don't require cfortran.h, also provide the solution. In the same vein, routines with more than 14 arguments can not be interfaced by cfortran.h with compilers which limit C macros to 31 arguments. To resolve this difficulty, final_application.h's can be created on a compiler without this limitation. Therefore, new machinery is required to do: application.h + cfortran.h => final_application.h The following example may help clarify the means and ends: If the following definition of the HBOOK1 routine, the /*commented_out_part*/, is passed through the preprocessor [perhaps #undefing and #defining preprocessor constants if creating an application.h for compiler other than that of the preprocessor being used, e.g. cpp -Umips -DCRAY ... ] : #include "cfortran.h" PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) /*#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \*/ CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ ID,CHTITLE,NX,XMI,XMA,VMX) A function prototype is produced by the PROTOCCALLSFSUB6(...). Interface code is produced, based on the 'variables', ID,CHTITLE,NX,XMI,XMA,VMX, which will correctly massage a HBOOK1 call. Therefore, adding the #define line: 'prototype code' #define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ 'interface code'(ID,CHTITLE,NX,XMI,XMA,VMX) which is placed into final_application.h. The only known limitation of the above method does not allow the 'variable' names to include B1,B2,...,B9,BA,BB,... Obviously the machinery to automatically generate final_applications.h from cfortran.h and applications.h needs more than just some preprocessor directives, but a fairly simple unix shell script should be sufficient. Any takers? V Machine Dependencies of cfortran.h ------------------------------------ Porting cfortran.h applications, e.g. the hbook.h and cstring.c mentioned above, to other machines is trivial since they are machine independent. Porting cfortran.h requires a solid knowledge of the new machines C preprocessor, and its FORTRAN argument passing mechanisms. Logically cfortran.h exists as two halves, a "C CALLS FORTRAN" and a "FORTRAN CALLS C" utility. In some cases it may be perfectly reasonable to port only 'one half' of cfortran.h onto a new system. The lucky programmer porting cfortran.h to a new machine, must discover the FORTRAN argument passing mechanisms. A safe starting point is to assume that variables and arrays are simply passed by reference, but nothing is guaranteed. Strings, and n-dimensional arrays of strings are a different story. It is doubtful that any systems do it quite like VAX VMS does it, so that a UNIX or f2c versions may provide an easier starting point. cfortran.h uses and abuses the preprocessor's ## operator. Although the ## operator does not exist in many compilers, many kludges do. cfortran.h uses /**/ with no space allowed between the slashes, '/', and the macros or tags to be concatenated. e.g. #define concat(a,b) a/**/b /* works*/ main() { concat(pri,ntf)("hello"); /* e.g. */ } N.B. On some compilers without ##, /**/ may also not work. The author may be able to offer alternate kludges. VI Bugs in vendors C compilers and other curiosities ---------------------------------------------------- 1. ULTRIX xxxxxx 4.3 1 RISC Condolences to long suffering ultrix users! DEC supplies a working C front end for alpha/OSF, but not for ultrix. From K&R ANSI C p. 231: ultrix> cat cat.c #define cat(x, y) x ## y #define xcat(x,y) cat(x,y) cat(cat(1,2),3) xcat(xcat(1,2),3) ultrix> cc -E cat.c 123 <---- Should be: cat(1,2)3 123 <---- Correct. ultrix> The problem for cfortran.h, preventing use of -std and -std1: ultrix> cat c.c #define cat(x, y) x ## y #define xcat(x,y) cat(x,y) #define AB(X) X+X #define C(E,F,G) cat(E,F)(G) #define X(E,F,G) xcat(E,F)(G) C(A,B,2) X(A,B,2) ultrix> cc -std1 -E c.c 2+2 AB (2) <---- ????????????? ultrix> ultrix> cc -std0 -E c.c 2+2 AB(2) <---- ????????????? ultrix> Due to further ultrix preprocessor problems, for all definitions of definitions with arguments, cfortran.h >= 3.0 includes the arguments and recommends the same, even though it is not required by ANSI C. e.g. Users are advised to do #define fcallsc(UN,LN) orig_fcallsc(UN,LN) instead of #define fcallsc orig_fcallsc since ultrix fails to properly preprocess the latter example. CRAY used to (still does?) occasionally trip up on this problem. 2. ConvexOS convex C210 11.0 convex In a program with a C main, output to LUN=6=* from Fortran goes into $pwd/fort.6 instead of stdout. Presumably, a magic incantation can be called from the C main in order to properly initialize the Fortran I/O. 3. SunOS 5.3 Generic_101318-69 sun4m sparc The default data and code alignments produced by cc, gcc and f77 are compatible. If deviating from the defaults, consistent alignment options must be used across all objects compiled by cc and f77. [Does gcc provide such options?] 4. SunOS 5.3 Generic_101318-69 sun4m sparc with cc: SC3.0.1 13 Jul 1994 or equivalently ULTRIX 4.4 0 RISC using cc -oldc are K&R C preprocessors that suffer from infinite loop macros, e.g. zedy03> cat src.c #include "cfortran.h" PROTOCCALLSFFUN1(INT,FREV,frev, INTV) #define FREV(A1) CCALLSFFUN1( FREV,frev, INTV, A1) /* To avoid the problem, deletete these ---^^^^--- spaces. */ main() { static int a[] = {1,2}; FREV(a); return EXIT_SUCCESS; } zedy03> cc -c -Xs -v -DMAX_PREPRO_ARGS=31 -D__CF__KnR src.c "src.c", line 4: FREV: actuals too long "src.c", line 4: FREV: actuals too long .... 3427 more lines of the same message "src.c", line 4: FREV: actuals too long cc : Fatal error in /usr/ccs/lib/cpp Segmentation fault (core dumped) 5. Older sun C compilers To link to f77 objects, older sun C compilers require the math.h macros: #define RETURNFLOAT(x) { union {double _d; float _f; } _kluge; \ _kluge._f = (x); return _kluge._d; } #define ASSIGNFLOAT(x,y) { union {double _d; float _f; } _kluge; \ _kluge._d = (y); x = _kluge._f; } Unfortunately, in at least some copies of the sun math.h, the semi-colon for 'float _f;' is left out, leading to compiler warnings. The solution is to correct math.h, or to change cfortran.h to #define RETURNFLOAT(x) and ASSIGNFLOAT(x,y) instead of including math.h. 6. gcc version 2.6.3 and probably all other versions as well Unlike all other C compilers supported by cfortran.h, 'gcc -traditional' promotes to double all functions returning float as demonstrated bu the following example. /* m.c */ #include int main() { FLOAT_FUNCTION d(); float f; f = d(); printf("%f\n",f); return 0; } /* d.c */ float d() { return -123.124; } burow[29] gcc -c -traditional d.c burow[30] gcc -DFLOAT_FUNCTION=float m.c d.o && a.out 0.000000 burow[31] gcc -DFLOAT_FUNCTION=double m.c d.o && a.out -123.124001 burow[32] Thus, 'gcc -traditional' is not supported by cfortran.h. Support would require the same RETURNFLOAT, etc. macro machinery present in old sun math.h, before sun gave up the same promotion. 7. CRAY At least some versions of the t3e and t3d C preprocessor are broken in the fashion described below. At least some versions of the t90 C preprocessor do not have this problem. On the CRAY, all Fortran names are converted to uppercase. Generally the uppercase name is also used for the macro interface created by cfortran.h. For example, in the following interface, EASY is both the name of the macro in the original C code and EASY is the name of the resulting function to be called. #define EASY(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B) The fact that a macro called EASY() expands to a function called EASY() is not a problem for a working C preprocessor. From Kernighan and Ritchie, 2nd edition, p.230: In both kinds of macro, the replacement token sequence is repeatedly rescanned for more identifiers. However, once a given identifier has been replaced in a given expansion, it is not replaced if it turns up again during rescanning; instead it is left unchanged. Unfortunately, some CRAY preprocessors are broken and don't obey the above rule. A work-around is for the user to NOT use the uppercase name of the name of the macro interface provided by cfortran.h. For example: #define Easy(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B) Luckily, the above work-around is not required since the following work-around within cfortran.h also circumvents the bug: /* (UN), not UN, is required in order to get around CRAY preprocessor bug.*/ #define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */ Aside: The Visual C++ compiler is happy with UN, but barfs on (UN), so either (UN) causes nonstandard C/C++ or Visual C++ is broken. VII History and Acknowledgements -------------------------------- 1.0 - Supports VAX VMS using C 3.1 and FORTRAN 5.4. Oct. '90. 1.0 - Supports Silicon Graphics w. Mips Computer 2.0 f77 and cc. Feb. '91. [Port of C calls FORTRAN half only.] 1.1 - Supports Mips Computer System 2.0 f77 and cc. Mar. '91. [Runs on at least: Silicon Graphics IRIX 3.3.1 DECstations with Ultrix V4.1] 1.2 - Internals made simpler, smaller, faster, stronger. May '91. - Mips version works on IBM RS/6000, this is now called the unix version. 1.3 - UNIX and VAX VMS versions are merged into a single cfortran.h. July '91. - C can help manipulate (arrays of) strings in FORTRAN common blocks. - Dimensions of string arrays arguments can be explicit. - Supports Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7. 2.0 - Improved code generation machinery creates K&R or ANSI C. Aug. '91. - Supports Sun, CRAY. f2c with vcc on VAX Ultrix. - cfortran.h macros now require routine and COMMON block names in both upper and lower case. No changes required to applications though. - PROTOCCALLSFSUBn is eliminated, with no loss to cfortran.h performance. - Improved tools and guidelines for naming C routines called by FORTRAN. 2.1 - LOGICAL correctly supported across all machines. Oct. '91. - Improved support for DOUBLE PRECISION on the CRAY. - HP9000 fully supported. - VAX Ultrix cc or gcc with f77 now supported. 2.2 - SHORT, i.e. INTEGER*2, and BYTE now supported. Dec. '91. - LOGICAL_STRICT introduced. More compact and robust internal tables. - typeV and typeVV for type = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG,SHORT. - FORTRAN passing strings and NULL pointer to C routines improved. 2.3 - Extraneous arguments removed from many internal tables. May '92. - Introduce pseudo argument type SIMPLE for user defined types. - LynxOS using f2c supported. (Tested with LynxOS 2.0 386/AT.) 2.4 - Separation of internal C and Fortran compilation directives. Oct. '92. - f2c and NAG f90 supported on all machines. 2.5 - Minor mod.s to source and/or doc for HP9000, f2c, and NAG f90. Nov. '92. 2.6 - Support external procedures as arguments with type ROUTINE. Dec. '92. 2.7 - Support Alpha VMS. Support HP9000 f77 +ppu Jan. '93. - Support arrays with up to 7 dimensions. - Minor mod. of Fortran NULL to C via (P)STRING. - Specify the type of ROUTINE passed from Fortran to C [ANSI C requirement.] - Macros never receive a null parameter [RS/6000 requirement.] 2.8 - PSTRING for Fortran calls C no longer provides escape to pass April'93. NULL pointer nor to pass address of original string. PNSTRING introduced with old PSTRING's behavior. PPSTRING introduced to always pass original address of string. - Support Alpha/OSF. - Document that common blocks used in C should be declared AND defined. 3.0 - Automagic handling of ANSI ## versus K&R /**/ preprocessor op. March'95. - Less chance of name space collisions between cfortran.h and other codes. - SIMPLE macros, supporting user defined types, have changed names. 3.1 - Internal macro name _INT not used. Conflicted with IRIX 5.3. May '95. - SunOS, all versions, should work out of the box. - ZTRINGV_ARGS|F(k) may no longer point to a PDOUBLE or PFLOAT argument. - ConvexOS 11.0 supported. 3.2 - __hpux no longer needs to be restricted to MAX_PREPRO_ARGS=31. Oct. '95. - PSTRING bug fixed. - ZTRINGV_ARGS|F(k) may not point to a PBYTE,PINT,PLONG or PSHORT argument. - (P)ZTRINGV machinery improved. Should lead to fewer compiler warnings. (P)ZTRINGV no longer limits recursion or the nesting of routines. - SIMPLE macros, supporting user defined types, have changed slightly. 3.3 - Supports PowerStation Fortran with Visual C++. Nov. '95. - g77 should work using f2cFortran, though no changes made for it. - (PROTO)CCALLSFFUN10 extended to (PROTO)CCALLSFFUN14. - FCALLSCFUN10 and SUB10 extended to FCALLSCFUN14 and SUB14. 3.4 - C++ supported, Dec. '95. but it required the reintroduction of PROTOCCALLSFSUBn for users. - HP-UX f77 +800 supported. 3.5 - Absoft UNIX Fortran supported. Sept.'96. 3.6 - Minor corrections to cfortran.doc. Oct. '96. - Fixed bug for 15th argument. [Thanks to Tom Epperly at Aspen Tech.] - For AbsoftUNIXFortran, obey default of prepending _C to COMMON BLOCK name. - Fortran calling C with ROUTINE argument fixed and cleaned up. 3.7 - Circumvent IBM and HP "null argument" preprocessor warning. Oct. '96 3.8 - (P)STRINGV and (P)ZTRINGV can pass a 1- or 2-dim. char array. Feb. '97 (P)ZTRINGV thus effectively also provides (P)ZTRING. - (P)ZTRINGV accepts a (char *) pointer. 3.9 - Bug fixed for *VVVVV. May '97 - f2c: Work-around for strange underscore-dependent naming feature. - NEC SX-4 supported. - CRAY: LOGICAL conversion uses _btol and _ltob from CRAY's fortran.h. - CRAY: Avoid bug of some versions of the C preprocessor. - CRAY T3E: FORTRAN_REAL introduced. 4.0 - new/delete now used for C++. malloc/free still used for C. Jan. '98 - FALSE no longer is defined by cfortran.h . - Absoft Pro Fortran for MacOS supported. 4.1 - COMMA and COLON no longer are defined by cfortran.h . April'98 - Bug fixed when 10th arg. or beyond is a string. [Rob Lucchesi of NASA-Goddard pointed out this bug.] - CCALLSFSUB/FUN extended from 14 to 27 arguments. - Workaround SunOS CC 4.2 cast bug. [Thanks to Savrak SAR of CERN.] 4.2 - Portland Group needs -DpgiFortran . [Thank George Lai of NASA.] June '98 4.3 - (PROTO)CCALLSFSUB extended from 20 to 27 arguments. July '98 ['Support' implies these and more recent releases of the respective OS/compilers/linkers can be used with cfortran.h. Earlier releases may also work.] Acknowledgements: - CERN very generously sponsored a week in 1994 for me to work on cfortran.h. - M.L.Luvisetto (Istituto Nazionale Fisica Nucleare - Centro Nazionale Analisi Fotogrammi, Bologna, Italy) provided all the support for the port to the CRAY. Marisa's encouragement and enthusiasm was also much appreciated. - J.Bunn (CERN) supported the port to PowerStation Fortran with Visual C++. - Paul Schenk (UC Riverside, CERN PPE/OPAL) in June 1993 extended cfortran.h 2.7 to have C++ call Fortran. This was the starting point for full C++ in 3.4. - Glenn P.Davis of University Corp. for Atmospheric Research (UCAR) / Unidata supported the NEC SX-4 port and helped understand the CRAY. - Tony Goelz of Absoft Corporation ported cfortran.h to Absoft. - Though cfortran.h has been created in my 'copious' free time, I thank NSERC for their generous support of my grad. student and postdoc years. - Univ.Toronto, DESY, CERN and others have provided time on their computers. THIS PACKAGE, I.E. CFORTRAN.H, THIS DOCUMENT, AND THE CFORTRAN.H EXAMPLE PROGRAMS ARE PROPERTY OF THE AUTHOR WHO RESERVES ALL RIGHTS. THIS PACKAGE AND THE CODE IT PRODUCES MAY BE FREELY DISTRIBUTED WITHOUT FEES, SUBJECT TO THE FOLLOWING RESTRICTIONS: - YOU MUST ACCOMPANY ANY COPIES OR DISTRIBUTION WITH THIS (UNALTERED) NOTICE. - YOU MAY NOT RECEIVE MONEY FOR THE DISTRIBUTION OR FOR ITS MEDIA (E.G. TAPE, DISK, COMPUTER, PAPER.) - YOU MAY NOT PREVENT OTHERS FROM COPYING IT FREELY. - YOU MAY NOT DISTRIBUTE MODIFIED VERSIONS WITHOUT CLEARLY DOCUMENTING YOUR CHANGES AND NOTIFYING THE AUTHOR. - YOU MAY NOT MISREPRESENTED THE ORIGIN OF THIS SOFTWARE, EITHER BY EXPLICIT CLAIM OR BY OMISSION. THE INTENT OF THE ABOVE TERMS IS TO ENSURE THAT THE CFORTRAN.H PACKAGE NOT BE USED FOR PROFIT MAKING ACTIVITIES UNLESS SOME ROYALTY ARRANGEMENT IS ENTERED INTO WITH ITS AUTHOR. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. THE AUTHOR IS NOT RESPONSIBLE FOR ANY SUPPORT OR SERVICE OF THE CFORTRAN.H PACKAGE. Burkhard Burow burow@desy.de P.S. Your comments and questions are welcomed and usually promptly answered. VAX VMS and Ultrix, Alpha, OSF, Silicon Graphics (SGI), DECstation, Mips RISC, Sun, CRAY, Convex, IBM RS/6000, Apollo DomainOS, HP, LynxOS, f2c, NAG, Absoft, NEC SX-4, PowerStation and Visual C++ are registered trademarks of their respective owners. ============================================================================ ADDITIONAL LICENSING INFORMATION (added by W D Pence on 4 October 2007) The author of cfortran has subsequently stated that cfortran.h may optionally be used and distributed under the GNU Library General Public License (LGPL). This statement was made in an email to Kevin McCarty, which is reproduced below: ---------------------------------------- Date: Tue, 22 Oct 2002 12:48:00 -0400 From: Burkhard D Steinmacher-burow To: Kevin B. McCarty Subject: Re: CFortran licensing question Kevin, [Just noticed that I didn't send this yesterady.] I have no time right now to read through licenses. IIRC, library GPL is fairly unrestrictive, so I'll choose that. So..... You may consider this e-mail as a notice that as an alternative to any other cfortran licenses, I hereby relase all versions and all parts of cfortran under the the Library GPL license. From among these licenses, the user is free to choose the license or licenses under which cfortran is used. Contact me if you'd like to be able to choose another license. Burkhard steinmac@us.ibm.com, (914)945-3756, Fax 3684, Tieline 862 ------------------------------------------ /* end: cfortran.doc */ cfitsio-4.3.1/wcsutil.c0000644000225700000360000004060113472024437014312 0ustar cagordonlhea#include #include "fitsio2.h" #define D2R 0.01745329252 #define TWOPI 6.28318530717959 /*--------------------------------------------------------------------------*/ int ffwldp(double xpix, double ypix, double xref, double yref, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *type, double *xpos, double *ypos, int *status) /* This routine is based on the classic AIPS WCS routine. It converts from pixel location to RA,Dec for 9 projective geometries: "-CAR", "-SIN", "-TAN", "-ARC", "-NCP", "-GLS", "-MER", "-AIT" and "-STG". */ /*-----------------------------------------------------------------------*/ /* routine to determine accurate position for pixel coordinates */ /* returns 0 if successful otherwise: */ /* 501 = angle too large for projection; */ /* does: -CAR, -SIN, -TAN, -ARC, -NCP, -GLS, -MER, -AIT -STG projections*/ /* Input: */ /* f xpix x pixel number (RA or long without rotation) */ /* f ypiy y pixel number (dec or lat without rotation) */ /* d xref x reference coordinate value (deg) */ /* d yref y reference coordinate value (deg) */ /* f xrefpix x reference pixel */ /* f yrefpix y reference pixel */ /* f xinc x coordinate increment (deg) */ /* f yinc y coordinate increment (deg) */ /* f rot rotation (deg) (from N through E) */ /* c *type projection type code e.g. "-SIN"; */ /* Output: */ /* d *xpos x (RA) coordinate (deg) */ /* d *ypos y (dec) coordinate (deg) */ /*-----------------------------------------------------------------------*/ {double cosr, sinr, dx, dy, dz, temp, x, y, z; double sins, coss, dect, rat, dt, l, m, mg, da, dd, cos0, sin0; double dec0, ra0; double geo1, geo2, geo3; double deps = 1.0e-5; char *cptr; if (*status > 0) return(*status); /* Offset from ref pixel */ dx = (xpix-xrefpix) * xinc; dy = (ypix-yrefpix) * yinc; /* Take out rotation */ cosr = cos(rot * D2R); sinr = sin(rot * D2R); if (rot != 0.0) { temp = dx * cosr - dy * sinr; dy = dy * cosr + dx * sinr; dx = temp; } /* convert to radians */ ra0 = xref * D2R; dec0 = yref * D2R; l = dx * D2R; m = dy * D2R; sins = l*l + m*m; cos0 = cos(dec0); sin0 = sin(dec0); if (*type != '-') { /* unrecognized projection code */ return(*status = 504); } cptr = type + 1; if (*cptr == 'C') { /* linear -CAR */ if (*(cptr + 1) != 'A' || *(cptr + 2) != 'R') { return(*status = 504); } rat = ra0 + l; dect = dec0 + m; } else if (*cptr == 'T') { /* -TAN */ if (*(cptr + 1) != 'A' || *(cptr + 2) != 'N') { return(*status = 504); } x = cos0*cos(ra0) - l*sin(ra0) - m*cos(ra0)*sin0; y = cos0*sin(ra0) + l*cos(ra0) - m*sin(ra0)*sin0; z = sin0 + m* cos0; rat = atan2( y, x ); dect = atan ( z / sqrt(x*x+y*y) ); } else if (*cptr == 'S') { if (*(cptr + 1) == 'I' && *(cptr + 2) == 'N') { /* -SIN */ if (sins>1.0) return(*status = 501); coss = sqrt (1.0 - sins); dt = sin0 * coss + cos0 * m; if ((dt>1.0) || (dt<-1.0)) return(*status = 501); dect = asin (dt); rat = cos0 * coss - sin0 * m; if ((rat==0.0) && (l==0.0)) return(*status = 501); rat = atan2 (l, rat) + ra0; } else if (*(cptr + 1) == 'T' && *(cptr + 2) == 'G') { /* -STG Sterographic*/ dz = (4.0 - sins) / (4.0 + sins); if (fabs(dz)>1.0) return(*status = 501); dect = dz * sin0 + m * cos0 * (1.0+dz) / 2.0; if (fabs(dect)>1.0) return(*status = 501); dect = asin (dect); rat = cos(dect); if (fabs(rat)1.0) return(*status = 501); rat = asin (rat); mg = 1.0 + sin(dect) * sin0 + cos(dect) * cos0 * cos(rat); if (fabs(mg)deps) rat = TWOPI /2.0 - rat; rat = ra0 + rat; } else { return(*status = 504); } } else if (*cptr == 'A') { if (*(cptr + 1) == 'R' && *(cptr + 2) == 'C') { /* ARC */ if (sins>=TWOPI*TWOPI/4.0) return(*status = 501); sins = sqrt(sins); coss = cos (sins); if (sins!=0.0) sins = sin (sins) / sins; else sins = 1.0; dt = m * cos0 * sins + sin0 * coss; if ((dt>1.0) || (dt<-1.0)) return(*status = 501); dect = asin (dt); da = coss - dt * sin0; dt = l * sins * cos0; if ((da==0.0) && (dt==0.0)) return(*status = 501); rat = ra0 + atan2 (dt, da); } else if (*(cptr + 1) == 'I' && *(cptr + 2) == 'T') { /* -AIT Aitoff */ dt = yinc*cosr + xinc*sinr; if (dt==0.0) dt = 1.0; dt = dt * D2R; dy = yref * D2R; dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) - sin(dy)/sqrt((1.0+cos(dy))/2.0); if (dx==0.0) dx = 1.0; geo2 = dt / dx; dt = xinc*cosr - yinc* sinr; if (dt==0.0) dt = 1.0; dt = dt * D2R; dx = 2.0 * cos(dy) * sin(dt/2.0); if (dx==0.0) dx = 1.0; geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx; geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0); rat = ra0; dect = dec0; if ((l != 0.0) || (m != 0.0)) { dz = 4.0 - l*l/(4.0*geo1*geo1) - ((m+geo3)/geo2)*((m+geo3)/geo2) ; if ((dz>4.0) || (dz<2.0)) return(*status = 501); dz = 0.5 * sqrt (dz); dd = (m+geo3) * dz / geo2; if (fabs(dd)>1.0) return(*status = 501); dd = asin (dd); if (fabs(cos(dd))1.0) return(*status = 501); da = asin (da); rat = ra0 + 2.0 * da; dect = dd; } } else { return(*status = 504); } } else if (*cptr == 'N') { /* -NCP North celestial pole*/ if (*(cptr + 1) != 'C' || *(cptr + 2) != 'P') { return(*status = 504); } dect = cos0 - m * sin0; if (dect==0.0) return(*status = 501); rat = ra0 + atan2 (l, dect); dt = cos (rat-ra0); if (dt==0.0) return(*status = 501); dect = dect / dt; if ((dect>1.0) || (dect<-1.0)) return(*status = 501); dect = acos (dect); if (dec0<0.0) dect = -dect; } else if (*cptr == 'G') { /* -GLS global sinusoid */ if (*(cptr + 1) != 'L' || *(cptr + 2) != 'S') { return(*status = 504); } dect = dec0 + m; if (fabs(dect)>TWOPI/4.0) return(*status = 501); coss = cos (dect); if (fabs(l)>TWOPI*coss/2.0) return(*status = 501); rat = ra0; if (coss>deps) rat = rat + l / coss; } else if (*cptr == 'M') { /* -MER mercator*/ if (*(cptr + 1) != 'E' || *(cptr + 2) != 'R') { return(*status = 504); } dt = yinc * cosr + xinc * sinr; if (dt==0.0) dt = 1.0; dy = (yref/2.0 + 45.0) * D2R; dx = dy + dt / 2.0 * D2R; dy = log (tan (dy)); dx = log (tan (dx)); geo2 = dt * D2R / (dx - dy); geo3 = geo2 * dy; geo1 = cos (yref*D2R); if (geo1<=0.0) geo1 = 1.0; rat = l / geo1 + ra0; if (fabs(rat - ra0) > TWOPI) return(*status = 501); dt = 0.0; if (geo2!=0.0) dt = (m + geo3) / geo2; dt = exp (dt); dect = 2.0 * atan (dt) - TWOPI / 4.0; } else { return(*status = 504); } /* correct for RA rollover */ if (rat-ra0>TWOPI/2.0) rat = rat - TWOPI; if (rat-ra0<-TWOPI/2.0) rat = rat + TWOPI; if (rat < 0.0) rat += TWOPI; /* convert to degrees */ *xpos = rat / D2R; *ypos = dect / D2R; return(*status); } /*--------------------------------------------------------------------------*/ int ffxypx(double xpos, double ypos, double xref, double yref, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *type, double *xpix, double *ypix, int *status) /* This routine is based on the classic AIPS WCS routine. It converts from RA,Dec to pixel location to for 9 projective geometries: "-CAR", "-SIN", "-TAN", "-ARC", "-NCP", "-GLS", "-MER", "-AIT" and "-STG". */ /*-----------------------------------------------------------------------*/ /* routine to determine accurate pixel coordinates for an RA and Dec */ /* returns 0 if successful otherwise: */ /* 501 = angle too large for projection; */ /* 502 = bad values */ /* does: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, -AIT projections */ /* anything else is linear */ /* Input: */ /* d xpos x (RA) coordinate (deg) */ /* d ypos y (dec) coordinate (deg) */ /* d xref x reference coordinate value (deg) */ /* d yref y reference coordinate value (deg) */ /* f xrefpix x reference pixel */ /* f yrefpix y reference pixel */ /* f xinc x coordinate increment (deg) */ /* f yinc y coordinate increment (deg) */ /* f rot rotation (deg) (from N through E) */ /* c *type projection type code e.g. "-SIN"; */ /* Output: */ /* f *xpix x pixel number (RA or long without rotation) */ /* f *ypiy y pixel number (dec or lat without rotation) */ /*-----------------------------------------------------------------------*/ { double dx, dy, dz, r, ra0, dec0, ra, dec, coss, sins, dt, da, dd, sint; double l, m, geo1, geo2, geo3, sinr, cosr, cos0, sin0; double deps=1.0e-5; char *cptr; if (*type != '-') { /* unrecognized projection code */ return(*status = 504); } cptr = type + 1; dt = (xpos - xref); if (dt > 180) xpos -= 360; if (dt < -180) xpos += 360; /* NOTE: changing input argument xpos is OK (call-by-value in C!) */ /* default values - linear */ dx = xpos - xref; dy = ypos - yref; /* Correct for rotation */ r = rot * D2R; cosr = cos (r); sinr = sin (r); dz = dx*cosr + dy*sinr; dy = dy*cosr - dx*sinr; dx = dz; /* check axis increments - bail out if either 0 */ if ((xinc==0.0) || (yinc==0.0)) {*xpix=0.0; *ypix=0.0; return(*status = 502);} /* convert to pixels */ *xpix = dx / xinc + xrefpix; *ypix = dy / yinc + yrefpix; if (*cptr == 'C') { /* linear -CAR */ if (*(cptr + 1) != 'A' || *(cptr + 2) != 'R') { return(*status = 504); } return(*status); /* done if linear */ } /* Non linear position */ ra0 = xref * D2R; dec0 = yref * D2R; ra = xpos * D2R; dec = ypos * D2R; /* compute direction cosine */ coss = cos (dec); sins = sin (dec); cos0 = cos (dec0); sin0 = sin (dec0); l = sin(ra-ra0) * coss; sint = sins * sin0 + coss * cos0 * cos(ra-ra0); /* process by case */ if (*cptr == 'T') { /* -TAN tan */ if (*(cptr + 1) != 'A' || *(cptr + 2) != 'N') { return(*status = 504); } if (sint<=0.0) return(*status = 501); if( cos0<0.001 ) { /* Do a first order expansion around pole */ m = (coss * cos(ra-ra0)) / (sins * sin0); m = (-m + cos0 * (1.0 + m*m)) / sin0; } else { m = ( sins/sint - sin0 ) / cos0; } if( fabs(sin(ra0)) < 0.3 ) { l = coss*sin(ra)/sint - cos0*sin(ra0) + m*sin(ra0)*sin0; l /= cos(ra0); } else { l = coss*cos(ra)/sint - cos0*cos(ra0) + m*cos(ra0)*sin0; l /= -sin(ra0); } } else if (*cptr == 'S') { if (*(cptr + 1) == 'I' && *(cptr + 2) == 'N') { /* -SIN */ if (sint<0.0) return(*status = 501); m = sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0); } else if (*(cptr + 1) == 'T' && *(cptr + 2) == 'G') { /* -STG Sterographic*/ da = ra - ra0; if (fabs(dec)>TWOPI/4.0) return(*status = 501); dd = 1.0 + sins * sin(dec0) + coss * cos(dec0) * cos(da); if (fabs(dd)1.0) m = 1.0; m = acos (m); if (m!=0) m = m / sin(m); else m = 1.0; l = l * m; m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) * m; } else if (*(cptr + 1) == 'I' && *(cptr + 2) == 'T') { /* -AIT Aitoff */ da = (ra - ra0) / 2.0; if (fabs(da)>TWOPI/4.0) return(*status = 501); dt = yinc*cosr + xinc*sinr; if (dt==0.0) dt = 1.0; dt = dt * D2R; dy = yref * D2R; dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) - sin(dy)/sqrt((1.0+cos(dy))/2.0); if (dx==0.0) dx = 1.0; geo2 = dt / dx; dt = xinc*cosr - yinc* sinr; if (dt==0.0) dt = 1.0; dt = dt * D2R; dx = 2.0 * cos(dy) * sin(dt/2.0); if (dx==0.0) dx = 1.0; geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx; geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0); dt = sqrt ((1.0 + cos(dec) * cos(da))/2.0); if (fabs(dt)TWOPI/4.0) return(*status = 501); if (fabs(dec0)>TWOPI/4.0) return(*status = 501); m = dec - dec0; l = dt * coss; } else if (*cptr == 'M') { /* -MER mercator*/ if (*(cptr + 1) != 'E' || *(cptr + 2) != 'R') { return(*status = 504); } dt = yinc * cosr + xinc * sinr; if (dt==0.0) dt = 1.0; dy = (yref/2.0 + 45.0) * D2R; dx = dy + dt / 2.0 * D2R; dy = log (tan (dy)); dx = log (tan (dx)); geo2 = dt * D2R / (dx - dy); geo3 = geo2 * dy; geo1 = cos (yref*D2R); if (geo1<=0.0) geo1 = 1.0; dt = ra - ra0; l = geo1 * dt; dt = dec / 2.0 + TWOPI / 8.0; dt = tan (dt); if (dt #include #include #ifdef __APPLE__ #include #else #include #endif #include "fitsio.h" /* needed to define LONGLONG */ #include "drvrsmem.h" /* uses LONGLONG */ int main(int argc, char **argv) { int cmdok, listmode, longlistmode, recovermode, deletemode, id; int status; char *address; listmode = longlistmode = recovermode = deletemode = 0; id = -1; cmdok = 1; switch (argc) { case 1: listmode = 1; break; case 2: if (0 == strcmp("-l", argv[1])) longlistmode = 1; else if (0 == strcmp("-r", argv[1])) recovermode = 1; else if (0 == strcmp("-d", argv[1])) deletemode = 1; else cmdok = 0; break; case 3: if (0 == strcmp("-r", argv[1])) recovermode = 1; else if (0 == strcmp("-d", argv[1])) deletemode = 1; else { cmdok = 0; /* signal invalid cmd line syntax */ break; } if (1 != sscanf(argv[2], "%d", &id)) cmdok = 0; break; default: cmdok = 0; break; } if (0 == cmdok) { printf("usage :\n\n"); printf("smem - list all shared memory segments\n"); printf("\t!\tcouldn't obtain RDONLY lock - info unreliable\n"); printf("\tIdx\thandle of shared memory segment (visible by application)\n"); printf("\tKey\tcurrent system key of shared memory segment. Key\n"); printf("\t\tchanges whenever shmem segment is reallocated. Use\n"); printf("\t\tipcs (or ipcs -a) to view all shmem segments\n"); printf("\tNproc\tnumber of processes attached to segment\n"); printf("\tSize\tsize of shmem segment in bytes\n"); printf("\tFlags\tRESIZABLE - realloc allowed, PERSIST - segment is not\n"); printf("\t\tdeleted after shared_free called by last process attached\n"); printf("\t\tto it.\n"); printf("smem -d - delete all shared memory segments (may block)\n"); printf("smem -d id - delete specific shared memory segment (may block)\n"); printf("smem -r - unconditionally reset all shared memory segments\n\t\t(does not block, recovers zombie handles left by kill -9)\n"); printf("smem -r id - unconditionally reset specific shared memory segment\n"); } if (shared_init(0)) { printf("couldn't initialize shared memory, aborting ...\n"); return(10); } if (listmode) shared_list(id); else if (recovermode) shared_recover(id); else if (deletemode) shared_uncond_delete(id); for (id = 0; id <16; id++) { status = shared_getaddr(id, &address); if (!status)printf("id, status, address %d %d %ld %.30s\n", id, status, address, address); } return(0); } cfitsio-4.3.1/putcoli.c0000644000225700000360000010515713472024437014307 0ustar cagordonlhea/* This file, putcoli.c, contains routines that write data elements to */ /* a FITS image or table, with short datatype. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffppri( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ short *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; short nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem, 0, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcli(fptr, 2, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffppni( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ short *array, /* I - array of values that are written */ short nulval, /* I - undefined pixel value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). Any array values that are equal to the value of nulval will be replaced with the null pixel value that is appropriate for this column. */ { long row; short nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem, 1, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcni(fptr, 2, row, firstelem, nelem, array, nulval, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp2di(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ short *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { /* call the 3D writing routine, with the 3rd dimension = 1 */ ffp3di(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp3di(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ short *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 3-D cube of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow, ii, jj; long fpixel[3]= {1,1,1}, lpixel[3]; LONGLONG nfits, narray; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = (long) ncols; lpixel[1] = (long) nrows; lpixel[2] = (long) naxis3; fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel, 0, array, NULL, status); return(*status); } tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so write all at once */ ffpcli(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to write to */ narray = 0; /* next pixel in input array to be written */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* writing naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffpcli(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpssi(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long naxis, /* I - number of data axes in array */ long *naxes, /* I - size of each FITS axis */ long *fpixel, /* I - 1st pixel in each axis to write (1=1st) */ long *lpixel, /* I - last pixel in each axis to write */ short *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write a subsection of pixels to the primary array or image. A subsection is defined to be any contiguous rectangular array of pixels within the n-dimensional FITS data file. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow; LONGLONG fpix[7], dimen[7], astart, pstart; LONGLONG off2, off3, off4, off5, off6, off7; LONGLONG st10, st20, st30, st40, st50, st60, st70; LONGLONG st1, st2, st3, st4, st5, st6, st7; long ii, i1, i2, i3, i4, i5, i6, i7, irange[7]; if (*status > 0) return(*status); if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel, 0, array, NULL, status); return(*status); } if (naxis < 1 || naxis > 7) return(*status = BAD_DIMEN); tablerow=maxvalue(1,group); /* calculate the size and number of loops to perform in each dimension */ for (ii = 0; ii < 7; ii++) { fpix[ii]=1; irange[ii]=1; dimen[ii]=1; } for (ii = 0; ii < naxis; ii++) { fpix[ii]=fpixel[ii]; irange[ii]=lpixel[ii]-fpixel[ii]+1; dimen[ii]=naxes[ii]; } i1=irange[0]; /* compute the pixel offset between each dimension */ off2 = dimen[0]; off3 = off2 * dimen[1]; off4 = off3 * dimen[2]; off5 = off4 * dimen[3]; off6 = off5 * dimen[4]; off7 = off6 * dimen[5]; st10 = fpix[0]; st20 = (fpix[1] - 1) * off2; st30 = (fpix[2] - 1) * off3; st40 = (fpix[3] - 1) * off4; st50 = (fpix[4] - 1) * off5; st60 = (fpix[5] - 1) * off6; st70 = (fpix[6] - 1) * off7; /* store the initial offset in each dimension */ st1 = st10; st2 = st20; st3 = st30; st4 = st40; st5 = st50; st6 = st60; st7 = st70; astart = 0; for (i7 = 0; i7 < irange[6]; i7++) { for (i6 = 0; i6 < irange[5]; i6++) { for (i5 = 0; i5 < irange[4]; i5++) { for (i4 = 0; i4 < irange[3]; i4++) { for (i3 = 0; i3 < irange[2]; i3++) { pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7; for (i2 = 0; i2 < irange[1]; i2++) { if (ffpcli(fptr, 2, tablerow, pstart, i1, &array[astart], status) > 0) return(*status); astart += i1; pstart += off2; } st2 = st20; st3 = st3+off3; } st3 = st30; st4 = st4+off4; } st4 = st40; st5 = st5+off5; } st5 = st50; st6 = st6+off6; } st6 = st60; st7 = st7+off7; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpgpi( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long firstelem, /* I - first vector element to write(1 = 1st) */ long nelem, /* I - number of values to write */ short *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of group parameters to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffpcli(fptr, 1L, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpcli( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ short *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of values to a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer to a virtual column in a 1 or more grouped FITS primary array. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary. */ { int tcode, maxelem2, hdutype, writeraw; long twidth, incre; long ntodo; LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem; double scale, zero; char tform[20], cform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero, tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); maxelem = maxelem2; if (tcode == TSTRING) ffcfmt(tform, cform); /* derive C format for writing strings */ /* if there is no scaling and the native machine format is not byteswapped, then we can simply write the raw data bytes into the FITS file if the datatype of the FITS column is the same as the input values. Otherwise, we must convert the raw values into the scaled and/or machine dependent format in a temporary buffer that has been allocated for this purpose. */ if (scale == 1. && zero == 0. && MACHINE == NATIVE && tcode == TSHORT) { writeraw = 1; if (nelem < (LONGLONG)INT32_MAX) { maxelem = nelem; } else { maxelem = INT32_MAX/2; } } else writeraw = 0; /*---------------------------------------------------------------------*/ /* Now write the pixels to the FITS column. */ /* First call the ffXXfYY routine to (1) convert the datatype */ /* if necessary, and (2) scale the values by the FITS TSCALn and */ /* TZEROn linear scaling parameters into a temporary buffer. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to write */ next = 0; /* next element in array to be written */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to process a one time to the number that will fit in the buffer space or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre); ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */ switch (tcode) { case (TSHORT): if (writeraw) { /* write raw input bytes without conversion */ ffpi2b(fptr, ntodo, incre, &array[next], status); } else { /* convert the raw data before writing to FITS file */ ffi2fi2(&array[next], ntodo, scale, zero, (short *) buffer, status); ffpi2b(fptr, ntodo, incre, (short *) buffer, status); } break; case (TLONGLONG): ffi2fi8(&array[next], ntodo, scale, zero, (LONGLONG *) buffer, status); ffpi8b(fptr, ntodo, incre, (long *) buffer, status); break; case (TBYTE): ffi2fi1(&array[next], ntodo, scale, zero, (unsigned char *) buffer, status); ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status); break; case (TLONG): ffi2fi4(&array[next], ntodo, scale, zero, (INT32BIT *) buffer, status); ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status); break; case (TFLOAT): ffi2fr4(&array[next], ntodo, scale, zero, (float *) buffer, status); ffpr4b(fptr, ntodo, incre, (float *) buffer, status); break; case (TDOUBLE): ffi2fr8(&array[next], ntodo, scale, zero, (double *) buffer, status); ffpr8b(fptr, ntodo, incre, (double *) buffer, status); break; case (TSTRING): /* numerical column in an ASCII table */ if (cform[1] != 's') /* "%s" format is a string */ { ffi2fstr(&array[next], ntodo, scale, zero, cform, twidth, (char *) buffer, status); if (incre == twidth) /* contiguous bytes */ ffpbyt(fptr, ntodo * twidth, buffer, status); else ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); break; } /* can't write to string column, so fall thru to default: */ default: /* error trap */ snprintf(message,FLEN_ERRMSG, "Cannot write numbers to column %d which has format %s", colnum,tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous write operation */ { snprintf(message,FLEN_ERRMSG, "Error writing elements %.0f thru %.0f of input data array (ffpcli).", (double) (next+1), (double) (next+ntodo)); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while writing FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpcni( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ short *array, /* I - array of values to write */ short nulvalue, /* I - value used to flag undefined pixels */ int *status) /* IO - error status */ /* Write an array of elements to the specified column of a table. Any input pixels equal to the value of nulvalue will be replaced by the appropriate null value in the output FITS file. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary */ { tcolumn *colptr; LONGLONG ngood = 0, nbad = 0, ii; LONGLONG repeat, first, fstelm, fstrow; int tcode, overflow = 0; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode > 0) repeat = colptr->trepeat; /* repeat count for this column */ else repeat = firstelem -1 + nelem; /* variable length arrays */ /* if variable length array, first write the whole input vector, then go back and fill in the nulls */ if (tcode < 0) { if (ffpcli(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) { if (*status == NUM_OVERFLOW) { /* ignore overflows, which are possibly the null pixel values */ /* overflow = 1; */ *status = 0; } else { return(*status); } } } /* absolute element number in the column */ first = (firstrow - 1) * repeat + firstelem; for (ii = 0; ii < nelem; ii++) { if (array[ii] != nulvalue) /* is this a good pixel? */ { if (nbad) /* write previous string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0) return(*status); nbad=0; } ngood = ngood +1; /* the consecutive number of good pixels */ } else { if (ngood) /* write previous string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ if (ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status) > 0) { if (*status == NUM_OVERFLOW) { overflow = 1; *status = 0; } else { return(*status); } } } ngood=0; } nbad = nbad +1; /* the consecutive number of bad pixels */ } } /* finished loop; now just write the last set of pixels */ if (ngood) /* write last string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status); } } else if (nbad) /* write last string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ ffpclu(fptr, colnum, fstrow, fstelm, nbad, status); } if (*status <= 0) { if (overflow) { *status = NUM_OVERFLOW; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fi1(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ unsigned char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) (dvalue + .5); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fi2(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ short *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { memcpy(output, input, ntodo * sizeof(short) ); } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; output[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else { if (dvalue >= 0) output[ii] = (short) (dvalue + .5); else output[ii] = (short) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fi4(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ INT32BIT *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (INT32BIT) input[ii]; /* just copy input to output */ } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; output[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else { if (dvalue >= 0) output[ii] = (INT32BIT) (dvalue + .5); else output[ii] = (INT32BIT) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fi8(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ LONGLONG *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 9223372036854775808.) { /* Writing to unsigned long long column. Input values must not be negative */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else { output[ii] = ((LONGLONG) input[ii]) ^ 0x8000000000000000; } } } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = input[ii]; } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { if (dvalue >= 0) output[ii] = (LONGLONG) (dvalue + .5); else output[ii] = (LONGLONG) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fr4(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ float *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) ((input[ii] - zero) / scale); } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fr8(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ double *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (double) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (input[ii] - zero) / scale; } return(*status); } /*--------------------------------------------------------------------------*/ int ffi2fstr(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ char *cform, /* I - format for output string values */ long twidth, /* I - width of each field, in chars */ char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do scaling if required. */ { long ii; double dvalue; char *cptr; cptr = output; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { sprintf(output, cform, (double) input[ii]); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; sprintf(output, cform, dvalue); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } /* replace any commas with periods (e.g., in French locale) */ while ((cptr = strchr(cptr, ','))) *cptr = '.'; return(*status); } cfitsio-4.3.1/fitsio2.h0000644000225700000360000020037714523006111014177 0ustar cagordonlhea#ifndef _FITSIO2_H #define _FITSIO2_H #include "fitsio.h" /* Threading support using POSIX threads programming interface (supplied by Bruce O'Neel) All threaded programs MUST have the -D_REENTRANT on the compile line and must link with -lpthread. This means that when one builds cfitsio for threads you must have -D_REENTRANT on the gcc or cc command line. */ #ifdef _REENTRANT #include /* #include not needed any more */ extern pthread_mutex_t Fitsio_Lock; extern int Fitsio_Pthread_Status; #define FFLOCK1(lockname) (Fitsio_Pthread_Status = pthread_mutex_lock(&lockname)) #define FFUNLOCK1(lockname) (Fitsio_Pthread_Status = pthread_mutex_unlock(&lockname)) #define FFLOCK FFLOCK1(Fitsio_Lock) #define FFUNLOCK FFUNLOCK1(Fitsio_Lock) #define ffstrtok(str, tok, save) strtok_r(str, tok, save) #else #define FFLOCK #define FFUNLOCK #define ffstrtok(str, tok, save) strtok(str, tok) #endif /* If REPLACE_LINKS is defined, then whenever CFITSIO fails to open a file with write access because it is a soft link to a file that only has read access, then CFITSIO will attempt to replace the link with a local copy of the file, with write access. This feature was originally added to support the ftools in the Hera environment, where many of the user's data file are soft links. */ #if defined(BUILD_HERA) #define REPLACE_LINKS 1 #endif #define USE_LARGE_VALUE -99 /* flag used when writing images */ #define DBUFFSIZE 28800 /* size of data buffer in bytes */ #define NMAXFILES 10000 /* maximum number of FITS files that can be opened */ /* CFITSIO will allocate (NMAXFILES * 80) bytes of memory */ /* plus each file that is opened will use NIOBUF * 2880 bytes of memeory */ /* where NIOBUF is defined in fitio.h and has a default value of 40 */ #define MINDIRECT 8640 /* minimum size for direct reads and writes */ /* MINDIRECT must have a value >= 8640 */ /* it is useful to identify certain specific types of machines */ #define NATIVE 0 /* machine that uses non-byteswapped IEEE formats */ #define OTHERTYPE 1 /* any other type of machine */ #define VAXVMS 3 /* uses an odd floating point format */ #define ALPHAVMS 4 /* uses an odd floating point format */ #define IBMPC 5 /* used in drvrfile.c to work around a bug on PCs */ #define CRAY 6 /* requires a special NaN test algorithm */ #define GFLOAT 1 /* used for VMS */ #define IEEEFLOAT 2 /* used for VMS */ /* ======================================================================= */ /* The following logic is used to determine the type machine, */ /* whether the bytes are swapped, and the number of bits in a long value */ /* ======================================================================= */ /* The following platforms have sizeof(long) == 8 */ /* This block of code should match a similar block in fitsio.h */ /* and the block of code at the beginning of f77_wrap.h */ #if defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) ) /* old Dec Alpha platforms running OSF */ #define BYTESWAPPED TRUE #define LONGSIZE 64 #elif defined(__sparcv9) || (defined(__sparc__) && defined(__arch64__)) /* SUN Solaris7 in 64-bit mode */ #define BYTESWAPPED FALSE #define MACHINE NATIVE #define LONGSIZE 64 /* IBM System z mainframe support */ #elif defined(__s390x__) #define BYTESWAPPED FALSE #define LONGSIZE 64 #elif defined(__s390__) #define BYTESWAPPED FALSE #define LONGSIZE 32 #elif defined(__ia64__) || defined(__x86_64__) || defined(__AARCH64EL__) /* Intel itanium 64-bit PC, or AMD opteron 64-bit PC */ #define BYTESWAPPED TRUE #define LONGSIZE 64 #elif defined(_SX) /* Nec SuperUx */ #define BYTESWAPPED FALSE #define MACHINE NATIVE #define LONGSIZE 64 #elif defined(__powerpc64__) || defined(__64BIT__) || defined(__AARCH64EB__) /* IBM 64-bit AIX powerpc*/ /* could also test for __ppc64__ or __PPC64 */ # if defined(__LITTLE_ENDIAN__) # define BYTESWAPPED TRUE # else # define BYTESWAPPED FALSE # define MACHINE NATIVE # endif # define LONGSIZE 64 #elif defined(_MIPS_SZLONG) # if defined(MIPSEL) # define BYTESWAPPED TRUE # else # define BYTESWAPPED FALSE # define MACHINE NATIVE # endif # if _MIPS_SZLONG == 32 # define LONGSIZE 32 # elif _MIPS_SZLONG == 64 # define LONGSIZE 64 # else # error "can't handle long size given by _MIPS_SZLONG" # endif #elif defined(__riscv) /* RISC-V is always little endian */ #define BYTESWAPPED TRUE # if __riscv_xlen == 32 # define LONGSIZE 32 # elif __riscv_xlen == 64 # define LONGSIZE 64 # else # error "can't handle long size given by __riscv_xlen" # endif /* ============================================================== */ /* the following are all 32-bit byteswapped platforms */ #elif defined(vax) && defined(VMS) #define MACHINE VAXVMS #define BYTESWAPPED TRUE #elif defined(__alpha) && defined(__VMS) #if (__D_FLOAT == TRUE) /* this float option is the same as for VAX/VMS machines. */ #define MACHINE VAXVMS #define BYTESWAPPED TRUE #elif (__G_FLOAT == TRUE) /* G_FLOAT is the default for ALPHA VMS systems */ #define MACHINE ALPHAVMS #define BYTESWAPPED TRUE #define FLOATTYPE GFLOAT #elif (__IEEE_FLOAT == TRUE) #define MACHINE ALPHAVMS #define BYTESWAPPED TRUE #define FLOATTYPE IEEEFLOAT #endif /* end of alpha VMS case */ #elif defined(ultrix) && defined(unix) /* old Dec ultrix machines */ #define BYTESWAPPED TRUE #elif defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) \ || defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TURBOC__) \ || defined(_NI_mswin_) || defined(__EMX__) /* generic 32-bit IBM PC */ #define MACHINE IBMPC #define BYTESWAPPED TRUE #elif defined(__arm__) /* This assumes all ARM are little endian. In the future, it might be */ /* necessary to use "if defined(__ARMEL__)" to distinguish little from big. */ /* (__ARMEL__ would be defined on little-endian, but not on big-endian). */ #define BYTESWAPPED TRUE #elif defined(__tile__) /* 64-core 8x8-architecture Tile64 platform */ #define BYTESWAPPED TRUE #elif defined(__sh__) /* SuperH CPU can be used in both little and big endian modes */ #if defined(__LITTLE_ENDIAN__) #define BYTESWAPPED TRUE #else #define BYTESWAPPED FALSE #endif #else /* assume all other machine uses the same IEEE formats as used in FITS files */ /* e.g., Macs fall into this category */ #define MACHINE NATIVE #define BYTESWAPPED FALSE #endif #ifndef MACHINE #define MACHINE OTHERTYPE #endif /* assume longs are 4 bytes long, unless previously set otherwise */ #ifndef LONGSIZE #define LONGSIZE 32 #endif /* end of block that determine long size and byte swapping */ /* ==================================================================== */ #define IGNORE_EOF 1 #define REPORT_EOF 0 #define DATA_UNDEFINED -1 #define NULL_UNDEFINED 1234554321 #define ASCII_NULL_UNDEFINED 1 /* indicate no defined null value */ #define maxvalue(A,B) ((A) > (B) ? (A) : (B)) #define minvalue(A,B) ((A) < (B) ? (A) : (B)) /* faster string comparison macros */ #define FSTRCMP(a,b) ((a)[0]<(b)[0]? -1:(a)[0]>(b)[0]?1:strcmp((a),(b))) #define FSTRNCMP(a,b,n) ((a)[0]<(b)[0]?-1:(a)[0]>(b)[0]?1:strncmp((a),(b),(n))) #if defined(__VMS) || defined(VMS) #define FNANMASK 0xFFFF /* mask all bits */ #define DNANMASK 0xFFFF /* mask all bits */ #else #define FNANMASK 0x7F80 /* mask bits 1 - 8; all set on NaNs */ /* all 0 on underflow or 0. */ #define DNANMASK 0x7FF0 /* mask bits 1 - 11; all set on NaNs */ /* all 0 on underflow or 0. */ #endif #if MACHINE == CRAY /* Cray machines: the large negative integer corresponds to the 3 most sig digits set to 1. If these 3 bits are set in a floating point number (64 bits), then it represents a reserved value (i.e., a NaN) */ #define fnan(L) ( (L) >= 0xE000000000000000 ? 1 : 0) ) #else /* these functions work for both big and little endian machines */ /* that use the IEEE floating point format for internal numbers */ /* These functions tests whether the float value is a reserved IEEE */ /* value such as a Not-a-Number (NaN), or underflow, overflow, or */ /* infinity. The functions returns 1 if the value is a NaN, overflow */ /* or infinity; it returns 2 if the value is an denormalized underflow */ /* value; otherwise it returns 0. fnan tests floats, dnan tests doubles */ #define fnan(L) \ ( (L & FNANMASK) == FNANMASK ? 1 : (L & FNANMASK) == 0 ? 2 : 0) #define dnan(L) \ ( (L & DNANMASK) == DNANMASK ? 1 : (L & DNANMASK) == 0 ? 2 : 0) #endif #define DSCHAR_MAX 127.49 /* max double value that fits in an signed char */ #define DSCHAR_MIN -128.49 /* min double value that fits in an signed char */ #define DUCHAR_MAX 255.49 /* max double value that fits in an unsigned char */ #define DUCHAR_MIN -0.49 /* min double value that fits in an unsigned char */ #define DUSHRT_MAX 65535.49 /* max double value that fits in a unsigned short*/ #define DUSHRT_MIN -0.49 /* min double value that fits in an unsigned short */ #define DSHRT_MAX 32767.49 /* max double value that fits in a short */ #define DSHRT_MIN -32768.49 /* min double value that fits in a short */ #if LONGSIZE == 32 # define DLONG_MAX 2147483647.49 /* max double value that fits in a long */ # define DLONG_MIN -2147483648.49 /* min double value that fits in a long */ # define DULONG_MAX 4294967295.49 /* max double that fits in a unsigned long */ #else # define DLONG_MAX 9.2233720368547752E18 /* max double value long */ # define DLONG_MIN -9.2233720368547752E18 /* min double value long */ # define DULONG_MAX 1.84467440737095504E19 /* max double value ulong */ #endif #define DULONG_MIN -0.49 /* min double value that fits in an unsigned long */ #define DULONGLONG_MAX 18446744073709551615. /* max unsigned longlong */ #define DULONGLONG_MIN -0.49 #define DLONGLONG_MAX 9.2233720368547755807E18 /* max double value longlong */ #define DLONGLONG_MIN -9.2233720368547755808E18 /* min double value longlong */ #define DUINT_MAX 4294967295.49 /* max dbl that fits in a unsigned 4-byte int */ #define DUINT_MIN -0.49 /* min dbl that fits in an unsigned 4-byte int */ #define DINT_MAX 2147483647.49 /* max double value that fits in a 4-byte int */ #define DINT_MIN -2147483648.49 /* min double value that fits in a 4-byte int */ #ifndef UINT64_MAX #define UINT64_MAX 18446744073709551615U /* max unsigned 64-bit integer */ #endif #ifndef UINT32_MAX #define UINT32_MAX 4294967295U /* max unsigned 32-bit integer */ #endif #ifndef INT32_MAX #define INT32_MAX 2147483647 /* max 32-bit integer */ #endif #ifndef INT32_MIN #define INT32_MIN (-INT32_MAX -1) /* min 32-bit integer */ #endif #define COMPRESS_NULL_VALUE -2147483647 #define N_RANDOM 10000 /* DO NOT CHANGE THIS; used when quantizing real numbers */ int ffgnky(fitsfile *fptr, char *card, int *status); void ffcfmt(char *tform, char *cform); void ffcdsp(char *tform, char *cform); void ffswap2(short *values, long nvalues); void ffswap4(INT32BIT *values, long nvalues); void ffswap8(double *values, long nvalues); int ffi2c(LONGLONG ival, char *cval, int *status); int ffu2c(ULONGLONG ival, char *cval, int *status); int ffl2c(int lval, char *cval, int *status); int ffs2c(const char *instr, char *outstr, int *status); int ffs2c_nopad(const char *instr, char *outstr, int *status); int ffr2f(float fval, int decim, char *cval, int *status); int ffr2e(float fval, int decim, char *cval, int *status); int ffd2f(double dval, int decim, char *cval, int *status); int ffd2e(double dval, int decim, char *cval, int *status); int ffc2ii(const char *cval, long *ival, int *status); int ffc2jj(const char *cval, LONGLONG *ival, int *status); int ffc2ujj(const char *cval, ULONGLONG *ival, int *status); int ffc2ll(const char *cval, int *lval, int *status); int ffc2rr(const char *cval, float *fval, int *status); int ffc2dd(const char *cval, double *dval, int *status); int ffc2x(const char *cval, char *dtype, long *ival, int *lval, char *sval, double *dval, int *status); int ffc2xx(const char *cval, char *dtype, LONGLONG *ival, int *lval, char *sval, double *dval, int *status); int ffc2uxx(const char *cval, char *dtype, ULONGLONG *ival, int *lval, char *sval, double *dval, int *status); int ffc2s(const char *instr, char *outstr, int *status); int ffc2i(const char *cval, long *ival, int *status); int ffc2j(const char *cval, LONGLONG *ival, int *status); int ffc2uj(const char *cval, ULONGLONG *ival, int *status); int ffc2r(const char *cval, float *fval, int *status); int ffc2d(const char *cval, double *dval, int *status); int ffc2l(const char *cval, int *lval, int *status); void ffxmsg(int action, char *err_message); int ffgcnt(fitsfile *fptr, char *value, char *comm, int *status); int ffgtkn(fitsfile *fptr, int numkey, char *keyname, long *value, int *status); int ffgtknjj(fitsfile *fptr, int numkey, char *keyname, LONGLONG *value, int *status); int fftkyn(fitsfile *fptr, int numkey, char *keyname, char *value, int *status); int ffgphd(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, LONGLONG naxes[], long *pcount, long *gcount, int *extend, double *bscale, double *bzero, LONGLONG *blank, int *nspace, int *status); int ffgttb(fitsfile *fptr, LONGLONG *rowlen, LONGLONG *nrows, LONGLONG *pcount, long *tfield, int *status); int ffglkut(fitsfile *fptr,const char *keyname,int firstchar,int maxchar,int maxcomchar, char *value,int *valuelen,char *comm,int *comlen,int *status); int ffmkey(fitsfile *fptr, const char *card, int *status); int fits_make_longstr_key_util(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int position, int *status); /* ffmbyt has been moved to fitsio.h */ int ffgbyt(fitsfile *fptr, LONGLONG nbytes, void *buffer, int *status); int ffpbyt(fitsfile *fptr, LONGLONG nbytes, void *buffer, int *status); int ffgbytoff(fitsfile *fptr, long gsize, long ngroups, long offset, void *buffer, int *status); int ffpbytoff(fitsfile *fptr, long gsize, long ngroups, long offset, void *buffer, int *status); int ffldrc(fitsfile *fptr, long record, int err_mode, int *status); int ffwhbf(fitsfile *fptr, int *nbuff); int ffbfeof(fitsfile *fptr, int *status); int ffbfwt(FITSfile *Fptr, int nbuff, int *status); int ffpxsz(int datatype); int ffourl(char *url, char *urltype, char *outfile, char *tmplfile, char *compspec, int *status); int ffparsecompspec(fitsfile *fptr, char *compspec, int *status); int ffoptplt(fitsfile *fptr, const char *tempname, int *status); int fits_is_this_a_copy(char *urltype); char *fits_find_match_delim(char *, char); int fits_store_Fptr(FITSfile *Fptr, int *status); int fits_clear_Fptr(FITSfile *Fptr, int *status); int fits_already_open(fitsfile **fptr, char *url, char *urltype, char *infile, char *extspec, char *rowfilter, char *binspec, char *colspec, int mode, int noextsyn, int *isopen, int *status); int ffedit_columns(fitsfile **fptr, char *outfile, char *expr, int *status); int fits_get_col_minmax(fitsfile *fptr, int colnum, double *datamin, double *datamax, int *status); /* "Extended syntax" versions of histogram binning which permit expressions instead of just columns. The existing interfaces still work */ int fits_get_expr_minmax(fitsfile *fptr, char *expr, double *datamin, double *datamax, int *datatype, int *status); int ffbinse(char *binspec, int *imagetype, int *haxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double *weight, char *wtname, int *recip, char ***exprs, int *status); int ffbinre(char **binspec, char *colname, char **exprbeg, char **exprend, double *minin, double *maxin, double *binsizein, char *minname, char *maxname, char *binname, int *status); int ffhist2e(fitsfile **fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], char *colexpr[4], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], char *wtexpr, int recip, char *selectrow, int *status); int fits_calc_binningde(fitsfile *, int, char colname[4][FLEN_VALUE], char *colexpr[4], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], int *, int *, long *, double *, double *, double *, long *, int *); int fits_write_keys_histoe(fitsfile *fptr, fitsfile *histptr, int naxis, int *colnum, char colname[4][FLEN_VALUE], char *colexpr[4], int *status); int fits_make_histde(fitsfile *fptr, fitsfile *histptr, int *datatypes, int bitpix,int naxis, long *naxes, int *colnum, char *colexpr[4], double *amin, double *amax, double *binsize, double weight, int wtcolnum, char *wtexpr, int recip, char *selectrow, int *status); int ffwritehisto(long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *imagepars, void *userPointer); int ffcalchist(long totalrows, long offset, long firstrow, long nrows, int ncols, iteratorCol *colpars, void *userPointer); int ffpinit(fitsfile *fptr, int *status); int ffainit(fitsfile *fptr, int *status); int ffbinit(fitsfile *fptr, int *status); int ffchdu(fitsfile *fptr, int *status); int ffwend(fitsfile *fptr, int *status); int ffpdfl(fitsfile *fptr, int *status); int ffuptf(fitsfile *fptr, int *status); int ffdblk(fitsfile *fptr, long nblocks, int *status); int ffgext(fitsfile *fptr, int moveto, int *exttype, int *status); int ffgtbc(fitsfile *fptr, LONGLONG *totalwidth, int *status); int ffgtbp(fitsfile *fptr, char *name, char *value, int *status); int ffiblk(fitsfile *fptr, long nblock, int headdata, int *status); int ffshft(fitsfile *fptr, LONGLONG firstbyte, LONGLONG nbytes, LONGLONG nshift, int *status); int ffgcprll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int writemode, double *scale, double *zero, char *tform, long *twidth, int *tcode, int *maxelem, LONGLONG *startpos, LONGLONG *elemnum, long *incre, LONGLONG *repeat, LONGLONG *rowlen, int *hdutype, LONGLONG *tnull, char *snull, int *status); int ffflushx(FITSfile *fptr); int ffseek(FITSfile *fptr, LONGLONG position); int ffread(FITSfile *fptr, long nbytes, void *buffer, int *status); int ffwrite(FITSfile *fptr, long nbytes, void *buffer, int *status); int fftrun(fitsfile *fptr, LONGLONG filesize, int *status); int ffpcluc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *status); int ffgcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nultyp, char nulval, char *array, char *nularray, int *anynul, int *status); int ffgcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nultyp, char *nulval, char **array, char *nularray, int *anynul, int *status); int ffgcls2(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nultyp, char *nulval, char **array, char *nularray, int *anynul, int *status); int ffgclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned char nulval, unsigned char *array, char *nularray, int *anynul, int *status); int ffgclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, signed char nulval, signed char *array, char *nularray, int *anynul, int *status); int ffgclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned short nulval, unsigned short *array, char *nularray, int *anynul, int *status); int ffgcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, short nulval, short *array, char *nularray, int *anynul, int *status); int ffgcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned long nulval, unsigned long *array, char *nularray, int *anynul, int *status); int ffgclujj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, ULONGLONG nulval, ULONGLONG *array, char *nularray, int *anynul, int *status); int ffgcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, LONGLONG nulval, LONGLONG *array, char *nularray, int *anynul, int *status); int ffgclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, long nulval, long *array, char *nularray, int *anynul, int *status); int ffgcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned int nulval, unsigned int *array, char *nularray, int *anynul, int *status); int ffgclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, int nulval, int *array, char *nularray, int *anynul, int *status); int ffgcle(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, float nulval, float *array, char *nularray, int *anynul, int *status); int ffgcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, double nulval, double *array, char *nularray, int *anynul, int *status); int ffpi1b(fitsfile *fptr, long nelem, long incre, unsigned char *buffer, int *status); int ffpi2b(fitsfile *fptr, long nelem, long incre, short *buffer, int *status); int ffpi4b(fitsfile *fptr, long nelem, long incre, INT32BIT *buffer, int *status); int ffpi8b(fitsfile *fptr, long nelem, long incre, long *buffer, int *status); int ffpr4b(fitsfile *fptr, long nelem, long incre, float *buffer, int *status); int ffpr8b(fitsfile *fptr, long nelem, long incre, double *buffer, int *status); int ffgi1b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, unsigned char *buffer, int *status); int ffgi2b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, short *buffer, int *status); int ffgi4b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, INT32BIT *buffer, int *status); int ffgi8b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, long *buffer, int *status); int ffgr4b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, float *buffer, int *status); int ffgr8b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, double *buffer, int *status); int ffcins(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, LONGLONG nbytes, LONGLONG bytepos, int *status); int ffcdel(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, LONGLONG nbytes, LONGLONG bytepos, int *status); int ffkshf(fitsfile *fptr, int firstcol, int tfields, int nshift, int *status); int fffvcl(fitsfile *fptr, int *nvarcols, int *colnums, int *status); int fffi1i1(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi2i1(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi4i1(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi8i1(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffr4i1(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffr8i1(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffstri1(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi1s1(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi2s1(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi4s1(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi8s1(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffr4s1(float *input, long ntodo, double scale, double zero, int nullcheck, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffr8s1(double *input, long ntodo, double scale, double zero, int nullcheck, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffstrs1(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi1u2(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi2u2(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi4u2(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi8u2(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffr4u2(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffr8u2(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffstru2(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi1i2(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi2i2(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi4i2(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi8i2(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffr4i2(float *input, long ntodo, double scale, double zero, int nullcheck, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffr8i2(double *input, long ntodo, double scale, double zero, int nullcheck, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffstri2(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi1u4(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi2u4(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi4u4(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi8u4(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffr4u4(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffr8u4(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffstru4(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi1i4(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi2i4(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi4i4(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi8i4(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffr4i4(float *input, long ntodo, double scale, double zero, int nullcheck, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffr8i4(double *input, long ntodo, double scale, double zero, int nullcheck, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffstri4(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi1int(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi2int(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi4int(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi8int(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffr4int(float *input, long ntodo, double scale, double zero, int nullcheck, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffr8int(double *input, long ntodo, double scale, double zero, int nullcheck, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffstrint(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi1uint(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi2uint(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi4uint(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi8uint(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffr4uint(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffr8uint(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffstruint(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi1i8(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi2i8(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi4i8(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi8i8(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffr4i8(float *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffr8i8(double *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffstri8(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi1u8(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffi2u8(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffi4u8(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffi8u8(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffr4u8(float *input, long ntodo, double scale, double zero, int nullcheck, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffr8u8(double *input, long ntodo, double scale, double zero, int nullcheck, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffstru8(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, ULONGLONG nullval, char *nullarray, int *anynull, ULONGLONG *output, int *status); int fffi1r4(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi2r4(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi4r4(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi8r4(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffr4r4(float *input, long ntodo, double scale, double zero, int nullcheck, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffr8r4(double *input, long ntodo, double scale, double zero, int nullcheck, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffstrr4(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi1r8(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffi2r8(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffi4r8(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffi8r8(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffr4r8(float *input, long ntodo, double scale, double zero, int nullcheck, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffr8r8(double *input, long ntodo, double scale, double zero, int nullcheck, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffstrr8(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, double nullval, char *nullarray, int *anynull, double *output, int *status); int ffi1fi1(unsigned char *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffs1fi1(signed char *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffu2fi1(unsigned short *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi2fi1(short *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffu4fi1(unsigned long *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi4fi1(long *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffu8fi1(ULONGLONG *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi8fi1(LONGLONG *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffuintfi1(unsigned int *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffintfi1(int *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffr4fi1(float *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffr8fi1(double *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi1fi2(unsigned char *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffs1fi2(signed char *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffu2fi2(unsigned short *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi2fi2(short *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffu4fi2(unsigned long *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi4fi2(long *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffu8fi2(ULONGLONG *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi8fi2(LONGLONG *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffuintfi2(unsigned int *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffintfi2(int *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffr4fi2(float *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffr8fi2(double *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi1fi4(unsigned char *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffs1fi4(signed char *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffu2fi4(unsigned short *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi2fi4(short *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffu4fi4(unsigned long *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffu8fi4(ULONGLONG *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi4fi4(long *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi8fi4(LONGLONG *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffuintfi4(unsigned int *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffintfi4(int *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffr4fi4(float *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffr8fi4(double *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi4fi8(long *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi8fi8(LONGLONG *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi2fi8(short *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi1fi8(unsigned char *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffs1fi8(signed char *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffr4fi8(float *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffr8fi8(double *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffintfi8(int *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffu2fi8(unsigned short *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffu4fi8(unsigned long *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffu8fi8(ULONGLONG *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffuintfi8(unsigned int *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi1fr4(unsigned char *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffs1fr4(signed char *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffu2fr4(unsigned short *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi2fr4(short *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffu4fr4(unsigned long *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi4fr4(long *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffu8fr4(ULONGLONG *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi8fr4(LONGLONG *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffuintfr4(unsigned int *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffintfr4(int *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffr4fr4(float *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffr8fr4(double *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi1fr8(unsigned char *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffs1fr8(signed char *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffu2fr8(unsigned short *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi2fr8(short *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffu4fr8(unsigned long *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi4fr8(long *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffu8fr8(ULONGLONG *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi8fr8(LONGLONG *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffuintfr8(unsigned int *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffintfr8(int *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffr4fr8(float *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffr8fr8(double *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi1fstr(unsigned char *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffs1fstr(signed char *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffu2fstr(unsigned short *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffi2fstr(short *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffu4fstr(unsigned long *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffi4fstr(long *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffu8fstr(ULONGLONG *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffi8fstr(LONGLONG *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffintfstr(int *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffuintfstr(unsigned int *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffr4fstr(float *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffr8fstr(double *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); /* the following 4 routines are VMS macros used on VAX or Alpha VMS */ void ieevpd(double *inarray, double *outarray, long *nvals); void ieevud(double *inarray, double *outarray, long *nvals); void ieevpr(float *inarray, float *outarray, long *nvals); void ieevur(float *inarray, float *outarray, long *nvals); /* routines related to the lexical parser */ typedef struct ParseData_struct ParseData; int ffselect_table(fitsfile **fptr, char *outfile, char *expr, int *status); int ffiprs( fitsfile *fptr, int compressed, char *expr, int maxdim, int *datatype, long *nelem, int *naxis, long *naxes, ParseData *, int *status ); void ffcprs( ParseData * ); int ffcvtn( int inputType, void *input, char *undef, long ntodo, int outputType, void *nulval, void *output, int *anynull, int *status ); int fits_parser_workfn( long totalrows, long offset, long firstrow, long nrows, int nCols, iteratorCol *colData, void *userPtr ); int fits_uncompress_hkdata( ParseData *, fitsfile *fptr, long ntimes, double *times, int *status ); int ffffrw_work( long totalrows, long offset, long firstrow, long nrows, int nCols, iteratorCol *colData, void *userPtr ); int fits_translate_pixkeyword(char *inrec, char *outrec,char *patterns[][2], int npat, int naxis, int *colnum, int *pat_num, int *i, int *j, int *n, int *m, int *l, int *status); /* image compression routines */ int fits_write_compressed_img(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, int nullcheck, void *array, void *nulval, int *status); int fits_write_compressed_pixels(fitsfile *fptr, int datatype, LONGLONG fpixel, LONGLONG npixels, int nullcheck, void *array, void *nulval, int *status); int fits_write_compressed_img_plane(fitsfile *fptr, int datatype, int bytesperpixel, long nplane, long *firstcoord, long *lastcoord, long *naxes, int nullcheck, void *array, void *nullval, long *nread, int *status); int imcomp_init_table(fitsfile *outfptr, int bitpix, int naxis,long *naxes, int writebitpix, int *status); int imcomp_calc_max_elem (int comptype, int nx, int zbitpix, int blocksize); int imcomp_copy_imheader(fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_copy_img2comp(fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_copy_comp2img(fitsfile *infptr, fitsfile *outfptr, int norec, int *status); int imcomp_copy_prime2img(fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_compress_image (fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_compress_tile (fitsfile *outfptr, long row, int datatype, void *tiledata, long tilelen, long nx, long ny, int nullcheck, void *nullval, int *status); int imcomp_nullscale(int *idata, long tilelen, int nullflagval, int nullval, double scale, double zero, int * status); int imcomp_nullvalues(int *idata, long tilelen, int nullflagval, int nullval, int * status); int imcomp_scalevalues(int *idata, long tilelen, double scale, double zero, int * status); int imcomp_nullscalefloats(float *fdata, long tilelen, int *idata, double scale, double zero, int nullcheck, float nullflagval, int nullval, int *status); int imcomp_nullfloats(float *fdata, long tilelen, int *idata, int nullcheck, float nullflagval, int nullval, int *status); int imcomp_nullscaledoubles(double *fdata, long tilelen, int *idata, double scale, double zero, int nullcheck, double nullflagval, int nullval, int *status); int imcomp_nulldoubles(double *fdata, long tilelen, int *idata, int nullcheck, double nullflagval, int nullval, int *status); /* image decompression routines */ int fits_read_compressed_img(fitsfile *fptr, int datatype, LONGLONG *fpixel,LONGLONG *lpixel,long *inc, int nullcheck, void *nulval, void *array, char *nullarray, int *anynul, int *status); int fits_read_compressed_pixels(fitsfile *fptr, int datatype, LONGLONG fpixel, LONGLONG npixels, int nullcheck, void *nulval, void *array, char *nullarray, int *anynul, int *status); int fits_read_compressed_img_plane(fitsfile *fptr, int datatype, int bytesperpixel, long nplane, LONGLONG *firstcoord, LONGLONG *lastcoord, long *inc, long *naxes, int nullcheck, void *nullval, void *array, char *nullarray, int *anynul, long *nread, int *status); int imcomp_get_compressed_image_par(fitsfile *infptr, int *status); int imcomp_decompress_tile (fitsfile *infptr, int nrow, int tilesize, int datatype, int nullcheck, void *nulval, void *buffer, char *bnullarray, int *anynul, int *status); int imcomp_copy_overlap (char *tile, int pixlen, int ndim, long *tfpixel, long *tlpixel, char *bnullarray, char *image, long *fpixel, long *lpixel, long *inc, int nullcheck, char *nullarray, int *status); int imcomp_test_overlap (int ndim, long *tfpixel, long *tlpixel, long *fpixel, long *lpixel, long *inc, int *status); int imcomp_merge_overlap (char *tile, int pixlen, int ndim, long *tfpixel, long *tlpixel, char *bnullarray, char *image, long *fpixel, long *lpixel, int nullcheck, int *status); int imcomp_decompress_img(fitsfile *infptr, fitsfile *outfptr, int datatype, int *status); int fits_quantize_float (long row, float fdata[], long nx, long ny, int nullcheck, float in_null_value, float quantize_level, int dither_method, int idata[], double *bscale, double *bzero, int *iminval, int *imaxval); int fits_quantize_double (long row, double fdata[], long nx, long ny, int nullcheck, double in_null_value, float quantize_level, int dither_method, int idata[], double *bscale, double *bzero, int *iminval, int *imaxval); int fits_rcomp(int a[], int nx, unsigned char *c, int clen,int nblock); int fits_rcomp_short(short a[], int nx, unsigned char *c, int clen,int nblock); int fits_rcomp_byte(signed char a[], int nx, unsigned char *c, int clen,int nblock); int fits_rdecomp (unsigned char *c, int clen, unsigned int array[], int nx, int nblock); int fits_rdecomp_short (unsigned char *c, int clen, unsigned short array[], int nx, int nblock); int fits_rdecomp_byte (unsigned char *c, int clen, unsigned char array[], int nx, int nblock); int pl_p2li (int *pxsrc, int xs, short *lldst, int npix); int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix); int fits_init_randoms(void); int fits_unset_compression_param( fitsfile *fptr, int *status); int fits_unset_compression_request( fitsfile *fptr, int *status); int fitsio_init_lock(void); /* general driver routines */ int urltype2driver(char *urltype, int *driver); void fits_dwnld_prog_bar(int flag); int fits_net_timeout(int sec); int fits_register_driver( char *prefix, int (*init)(void), int (*fitsshutdown)(void), int (*setoptions)(int option), int (*getoptions)(int *options), int (*getversion)(int *version), int (*checkfile) (char *urltype, char *infile, char *outfile), int (*fitsopen)(char *filename, int rwmode, int *driverhandle), int (*fitscreate)(char *filename, int *driverhandle), int (*fitstruncate)(int driverhandle, LONGLONG filesize), int (*fitsclose)(int driverhandle), int (*fremove)(char *filename), int (*size)(int driverhandle, LONGLONG *sizex), int (*flush)(int driverhandle), int (*seek)(int driverhandle, LONGLONG offset), int (*fitsread) (int driverhandle, void *buffer, long nbytes), int (*fitswrite)(int driverhandle, void *buffer, long nbytes)); /* file driver I/O routines */ int file_init(void); int file_setoptions(int options); int file_getoptions(int *options); int file_getversion(int *version); int file_shutdown(void); int file_checkfile(char *urltype, char *infile, char *outfile); int file_open(char *filename, int rwmode, int *driverhandle); int file_compress_open(char *filename, int rwmode, int *hdl); int file_openfile(char *filename, int rwmode, FILE **diskfile); int file_create(char *filename, int *driverhandle); int file_truncate(int driverhandle, LONGLONG filesize); int file_size(int driverhandle, LONGLONG *filesize); int file_close(int driverhandle); int file_remove(char *filename); int file_flush(int driverhandle); int file_seek(int driverhandle, LONGLONG offset); int file_read (int driverhandle, void *buffer, long nbytes); int file_write(int driverhandle, void *buffer, long nbytes); int file_is_compressed(char *filename); /* stream driver I/O routines */ int stream_open(char *filename, int rwmode, int *driverhandle); int stream_create(char *filename, int *driverhandle); int stream_size(int driverhandle, LONGLONG *filesize); int stream_close(int driverhandle); int stream_flush(int driverhandle); int stream_seek(int driverhandle, LONGLONG offset); int stream_read (int driverhandle, void *buffer, long nbytes); int stream_write(int driverhandle, void *buffer, long nbytes); /* memory driver I/O routines */ int mem_init(void); int mem_setoptions(int options); int mem_getoptions(int *options); int mem_getversion(int *version); int mem_shutdown(void); int mem_create(char *filename, int *handle); int mem_create_comp(char *filename, int *handle); int mem_openmem(void **buffptr, size_t *buffsize, size_t deltasize, void *(*memrealloc)(void *p, size_t newsize), int *handle); int mem_createmem(size_t memsize, int *handle); int stdin_checkfile(char *urltype, char *infile, char *outfile); int stdin_open(char *filename, int rwmode, int *handle); int stdin2mem(int hd); int stdin2file(int hd); int stdout_close(int handle); int mem_compress_openrw(char *filename, int rwmode, int *hdl); int mem_compress_open(char *filename, int rwmode, int *hdl); int mem_compress_stdin_open(char *filename, int rwmode, int *hdl); int mem_zuncompress_and_write(int hdl, void *buffer, long nbytes); int mem_iraf_open(char *filename, int rwmode, int *hdl); int mem_rawfile_open(char *filename, int rwmode, int *hdl); int mem_size(int handle, LONGLONG *filesize); int mem_truncate(int handle, LONGLONG filesize); int mem_close_free(int handle); int mem_close_keep(int handle); int mem_close_comp(int handle); int mem_seek(int handle, LONGLONG offset); int mem_read(int hdl, void *buffer, long nbytes); int mem_write(int hdl, void *buffer, long nbytes); int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl); int iraf2mem(char *filename, char **buffptr, size_t *buffsize, size_t *filesize, int *status); /* root driver I/O routines */ int root_init(void); int root_setoptions(int options); int root_getoptions(int *options); int root_getversion(int *version); int root_shutdown(void); int root_open(char *filename, int rwmode, int *driverhandle); int root_create(char *filename, int *driverhandle); int root_close(int driverhandle); int root_flush(int driverhandle); int root_seek(int driverhandle, LONGLONG offset); int root_read (int driverhandle, void *buffer, long nbytes); int root_write(int driverhandle, void *buffer, long nbytes); int root_size(int handle, LONGLONG *filesize); /* http driver I/O routines */ int http_checkfile(char *urltype, char *infile, char *outfile); int http_open(char *filename, int rwmode, int *driverhandle); int http_file_open(char *filename, int rwmode, int *driverhandle); int http_compress_open(char *filename, int rwmode, int *driverhandle); /* https driver I/O routines */ int https_checkfile(char* urltype, char *infile, char *outfile); int https_open(char *filename, int rwmode, int *driverhandle); int https_file_open(char *filename, int rwmode, int *driverhandle); void https_set_verbose(int flag); /* ftps driver I/O routines */ int ftps_checkfile(char* urltype, char *infile, char *outfile); int ftps_open(char *filename, int rwmode, int *handle); int ftps_file_open(char *filename, int rwmode, int *handle); int ftps_compress_open(char *filename, int rwmode, int *driverhandle); /* ftp driver I/O routines */ int ftp_checkfile(char *urltype, char *infile, char *outfile); int ftp_open(char *filename, int rwmode, int *driverhandle); int ftp_file_open(char *filename, int rwmode, int *driverhandle); int ftp_compress_open(char *filename, int rwmode, int *driverhandle); int uncompress2mem(char *filename, FILE *diskfile, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); int uncompress2mem_from_mem( char *inmemptr, size_t inmemsize, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); int uncompress2file(char *filename, FILE *indiskfile, FILE *outdiskfile, int *status); int compress2mem_from_mem( char *inmemptr, size_t inmemsize, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); int compress2file_from_mem( char *inmemptr, size_t inmemsize, FILE *outdiskfile, size_t *filesize, /* O - size of file, in bytes */ int *status); #ifdef HAVE_GSIFTP /* prototypes for gsiftp driver I/O routines */ #include "drvrgsiftp.h" #endif #ifdef HAVE_SHMEM_SERVICES /* prototypes for shared memory driver I/O routines */ #include "drvrsmem.h" #endif /* A hack for nonunix machines, which lack strcasecmp and strncasecmp */ /* these functions are in fitscore.c */ int fits_strcasecmp (const char *s1, const char *s2 ); int fits_strncasecmp(const char *s1, const char *s2, size_t n); /* "recalloc" which is a reallocator in the style of calloc */ void *fits_recalloc(void *ptr, size_t old_num, size_t new_num, size_t size); /* end of the entire "ifndef _FITSIO2_H" block */ #endif cfitsio-4.3.1/imcopy.c0000644000225700000360000002223013472024437014116 0ustar cagordonlhea#include #include #include #include "fitsio.h" int main(int argc, char *argv[]) { fitsfile *infptr, *outfptr; /* FITS file pointers defined in fitsio.h */ int status = 0, tstatus, ii = 1, iteration = 0, single = 0, hdupos; int hdutype, bitpix, bytepix, naxis = 0, nkeys, datatype = 0, anynul; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; long first, totpix = 0, npix; double *array, bscale = 1.0, bzero = 0.0, nulval = 0.; char card[81]; if (argc != 3) { printf("\n"); printf("Usage: imcopy inputImage outputImage[compress]\n"); printf("\n"); printf("Copy an input image to an output image, optionally compressing\n"); printf("or uncompressing the image in the process. If the [compress]\n"); printf("qualifier is appended to the output file name then the input image\n"); printf("will be compressed using the tile-compressed format. In this format,\n"); printf("the image is divided into rectangular tiles and each tile of pixels\n"); printf("is compressed and stored in a variable-length row of a binary table.\n"); printf("If the [compress] qualifier is omitted, and the input image is\n"); printf("in tile-compressed format, then the output image will be uncompressed.\n"); printf("\n"); printf("If an extension name or number is appended to the input file name, \n"); printf("enclosed in square brackets, then only that single extension will be\n"); printf("copied to the output file. Otherwise, every extension in the input file\n"); printf("will be processed in turn and copied to the output file.\n"); printf("\n"); printf("Examples:\n"); printf("\n"); printf("1) imcopy image.fit 'cimage.fit[compress]'\n"); printf("\n"); printf(" This compresses the input image using the default parameters, i.e.,\n"); printf(" using the Rice compression algorithm and using row by row tiles.\n"); printf("\n"); printf("2) imcopy cimage.fit image2.fit\n"); printf("\n"); printf(" This uncompresses the image created in the first example.\n"); printf(" image2.fit should be identical to image.fit if the image\n"); printf(" has an integer datatype. There will be small differences\n"); printf(" in the pixel values if it is a floating point image.\n"); printf("\n"); printf("3) imcopy image.fit 'cimage.fit[compress GZIP 100,100;q 16]'\n"); printf("\n"); printf(" This compresses the input image using the following parameters:\n"); printf(" GZIP compression algorithm;\n"); printf(" 100 X 100 pixel compression tiles;\n"); printf(" quantization level = 16 (only used with floating point images)\n"); printf("\n"); printf("The full syntax of the compression qualifier is:\n"); printf(" [compress ALGORITHM TDIM1,TDIM2,...; q QLEVEL s SCALE]\n"); printf("where the allowed ALGORITHM values are:\n"); printf(" Rice, HCOMPRESS, HSCOMPRESS, GZIP, or PLIO. \n"); printf(" (HSCOMPRESS is a variant of HCOMPRESS in which a small\n"); printf(" amount of smoothing is applied to the uncompressed image\n"); printf(" to help suppress blocky compression artifacts in the image\n"); printf(" when using large values for the 'scale' parameter).\n"); printf("TDIMn is the size of the compression tile in each dimension,\n"); printf("\n"); printf("QLEVEL specifies the quantization level when converting a floating\n"); printf("point image into integers, prior to compressing the image. The\n"); printf("default value = 16, which means the image will be quantized into\n"); printf("integer levels that are spaced at intervals of sigma/16., where \n"); printf("sigma is the estimated noise level in background areas of the image.\n"); printf("If QLEVEL is negative, this means use the absolute value for the\n"); printf("quantization spacing (e.g. 'q -0.005' means quantize the floating\n"); printf("point image such that the scaled integers represent steps of 0.005\n"); printf("in the original image).\n"); printf("\n"); printf("SCALE is the integer scale factor that only applies to the HCOMPRESS\n"); printf("algorithm. The default value SCALE = 0 forces the image to be\n"); printf("losslessly compressed; Greater amounts of lossy compression (resulting\n"); printf("in smaller compressed files) can be specified with larger SCALE values.\n"); printf("\n"); printf("\n"); printf("Note that it may be necessary to enclose the file names\n"); printf("in single quote characters on the Unix command line.\n"); return(0); } /* Open the input file and create output file */ fits_open_file(&infptr, argv[1], READONLY, &status); fits_create_file(&outfptr, argv[2], &status); if (status != 0) { fits_report_error(stderr, status); return(status); } fits_get_hdu_num(infptr, &hdupos); /* Get the current HDU position */ /* Copy only a single HDU if a specific extension was given */ if (hdupos != 1 || strchr(argv[1], '[')) single = 1; for (; !status; hdupos++) /* Main loop through each extension */ { fits_get_hdu_type(infptr, &hdutype, &status); if (hdutype == IMAGE_HDU) { /* get image dimensions and total number of pixels in image */ for (ii = 0; ii < 9; ii++) naxes[ii] = 1; fits_get_img_param(infptr, 9, &bitpix, &naxis, naxes, &status); totpix = naxes[0] * naxes[1] * naxes[2] * naxes[3] * naxes[4] * naxes[5] * naxes[6] * naxes[7] * naxes[8]; } if (hdutype != IMAGE_HDU || naxis == 0 || totpix == 0) { /* just copy tables and null images */ fits_copy_hdu(infptr, outfptr, 0, &status); } else { /* Explicitly create new image, to support compression */ fits_create_img(outfptr, bitpix, naxis, naxes, &status); if (status) { fits_report_error(stderr, status); return(status); } if (fits_is_compressed_image(outfptr, &status)) { /* write default EXTNAME keyword if it doesn't already exist */ tstatus = 0; fits_read_card(infptr, "EXTNAME", card, &tstatus); if (tstatus) { strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE' / name of this binary table extension"); fits_write_record(outfptr, card, &status); } } /* copy all the user keywords (not the structural keywords) */ fits_get_hdrspace(infptr, &nkeys, NULL, &status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(infptr, ii, card, &status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY) fits_write_record(outfptr, card, &status); } /* delete default EXTNAME keyword if it exists */ /* if (!fits_is_compressed_image(outfptr, &status)) { tstatus = 0; fits_read_key(outfptr, TSTRING, "EXTNAME", card, NULL, &tstatus); if (!tstatus) { if (strcmp(card, "COMPRESSED_IMAGE") == 0) fits_delete_key(outfptr, "EXTNAME", &status); } } */ switch(bitpix) { case BYTE_IMG: datatype = TBYTE; break; case SHORT_IMG: datatype = TSHORT; break; case LONG_IMG: datatype = TINT; break; case FLOAT_IMG: datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; break; } bytepix = abs(bitpix) / 8; npix = totpix; iteration = 0; /* try to allocate memory for the entire image */ /* use double type to force memory alignment */ array = (double *) calloc(npix, bytepix); /* if allocation failed, divide size by 2 and try again */ while (!array && iteration < 10) { iteration++; npix = npix / 2; array = (double *) calloc(npix, bytepix); } if (!array) { printf("Memory allocation error\n"); return(0); } /* turn off any scaling so that we copy the raw pixel values */ fits_set_bscale(infptr, bscale, bzero, &status); fits_set_bscale(outfptr, bscale, bzero, &status); first = 1; while (totpix > 0 && !status) { /* read all or part of image then write it back to the output file */ fits_read_img(infptr, datatype, first, npix, &nulval, array, &anynul, &status); fits_write_img(outfptr, datatype, first, npix, array, &status); totpix = totpix - npix; first = first + npix; } free(array); } if (single) break; /* quit if only copying a single HDU */ fits_movrel_hdu(infptr, 1, NULL, &status); /* try to move to next HDU */ } if (status == END_OF_FILE) status = 0; /* Reset after normal error */ fits_close_file(outfptr, &status); fits_close_file(infptr, &status); /* if error occurred, print out error message */ if (status) fits_report_error(stderr, status); return(status); } cfitsio-4.3.1/editcol.c0000644000225700000360000033203214335036354014245 0ustar cagordonlhea/* This file, editcol.c, contains the set of FITSIO routines that */ /* insert or delete rows or columns in a table or resize an image */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffrsim(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ long *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* resize an existing primary array or IMAGE extension. */ { LONGLONG tnaxes[99]; int ii; if (*status > 0) return(*status); for (ii = 0; (ii < naxis) && (ii < 99); ii++) tnaxes[ii] = naxes[ii]; ffrsimll(fptr, bitpix, naxis, tnaxes, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffrsimll(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ LONGLONG *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* resize an existing primary array or IMAGE extension. */ { int ii, simple, obitpix, onaxis, extend, nmodify; long nblocks, longval; long pcount, gcount, longbitpix; LONGLONG onaxes[99], newsize, oldsize; char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD], message[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); /* get current image size parameters */ if (ffghprll(fptr, 99, &simple, &obitpix, &onaxis, onaxes, &pcount, &gcount, &extend, status) > 0) return(*status); longbitpix = bitpix; /* test for the 4 special cases that represent unsigned integers or signed bytes */ if (longbitpix == USHORT_IMG) longbitpix = SHORT_IMG; else if (longbitpix == ULONG_IMG) longbitpix = LONG_IMG; else if (longbitpix == SBYTE_IMG) longbitpix = BYTE_IMG; else if (longbitpix == ULONGLONG_IMG) longbitpix = LONGLONG_IMG; /* test that the new values are legal */ if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG && longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG) { snprintf(message, FLEN_ERRMSG, "Illegal value for BITPIX keyword: %d", bitpix); ffpmsg(message); return(*status = BAD_BITPIX); } if (naxis < 0 || naxis > 999) { snprintf(message, FLEN_ERRMSG, "Illegal value for NAXIS keyword: %d", naxis); ffpmsg(message); return(*status = BAD_NAXIS); } if (naxis == 0) newsize = 0; else newsize = 1; for (ii = 0; ii < naxis; ii++) { if (naxes[ii] < 0) { snprintf(message, FLEN_ERRMSG, "Illegal value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii])); ffpmsg(message); return(*status = BAD_NAXES); } newsize *= naxes[ii]; /* compute new image size, in pixels */ } /* compute size of old image, in bytes */ if (onaxis == 0) oldsize = 0; else { oldsize = 1; for (ii = 0; ii < onaxis; ii++) oldsize *= onaxes[ii]; oldsize = (oldsize + pcount) * gcount * (abs(obitpix) / 8); } oldsize = (oldsize + 2879) / 2880; /* old size, in blocks */ newsize = (newsize + pcount) * gcount * (labs(longbitpix) / 8); newsize = (newsize + 2879) / 2880; /* new size, in blocks */ if (newsize > oldsize) /* have to insert new blocks for image */ { nblocks = (long) (newsize - oldsize); if (ffiblk(fptr, nblocks, 1, status) > 0) return(*status); } else if (oldsize > newsize) /* have to delete blocks from image */ { nblocks = (long) (oldsize - newsize); if (ffdblk(fptr, nblocks, status) > 0) return(*status); } /* now update the header keywords */ strcpy(comment,"&"); /* special value to leave comments unchanged */ if (longbitpix != obitpix) { /* update BITPIX value */ ffmkyj(fptr, "BITPIX", longbitpix, comment, status); } if (naxis != onaxis) { /* update NAXIS value */ longval = naxis; ffmkyj(fptr, "NAXIS", longval, comment, status); } /* modify the existing NAXISn keywords */ nmodify = minvalue(naxis, onaxis); for (ii = 0; ii < nmodify; ii++) { ffkeyn("NAXIS", ii+1, keyname, status); ffmkyj(fptr, keyname, naxes[ii], comment, status); } if (naxis > onaxis) /* insert additional NAXISn keywords */ { strcpy(comment,"length of data axis"); for (ii = onaxis; ii < naxis; ii++) { ffkeyn("NAXIS", ii+1, keyname, status); ffikyj(fptr, keyname, naxes[ii], comment, status); } } else if (onaxis > naxis) /* delete old NAXISn keywords */ { for (ii = naxis; ii < onaxis; ii++) { ffkeyn("NAXIS", ii+1, keyname, status); ffdkey(fptr, keyname, status); } } /* Update the BSCALE and BZERO keywords, if an unsigned integer image or a signed byte image. */ if (bitpix == USHORT_IMG) { strcpy(comment, "offset data range to that of unsigned short"); ffukyg(fptr, "BZERO", 32768., 0, comment, status); strcpy(comment, "default scaling factor"); ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); } else if (bitpix == ULONG_IMG) { strcpy(comment, "offset data range to that of unsigned long"); ffukyg(fptr, "BZERO", 2147483648., 0, comment, status); strcpy(comment, "default scaling factor"); ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); } else if (bitpix == ULONGLONG_IMG) { strcpy(comment, "offset data range to that of unsigned long long"); ffukyg(fptr, "BZERO", 9223372036854775808., 0, comment, status); strcpy(comment, "default scaling factor"); ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); } else if (bitpix == SBYTE_IMG) { strcpy(comment, "offset data range to that of signed byte"); ffukyg(fptr, "BZERO", -128., 0, comment, status); strcpy(comment, "default scaling factor"); ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); } /* re-read the header, to make sure structures are updated */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffirow(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstrow, /* I - insert space AFTER this row */ /* 0 = insert space at beginning of table */ LONGLONG nrows, /* I - number of rows to insert */ int *status) /* IO - error status */ /* insert NROWS blank rows immediated after row firstrow (1 = first row). Set firstrow = 0 to insert space at the beginning of the table. */ { int tstatus; LONGLONG naxis1, naxis2; LONGLONG datasize, firstbyte, nshift, nbytes; LONGLONG freespace; long nblock; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only add rows to TABLE or BINTABLE extension (ffirow)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ /* get the current size of the table */ /* use internal structure since NAXIS2 keyword may not be up to date */ naxis1 = (fptr->Fptr)->rowlength; naxis2 = (fptr->Fptr)->numrows; if (firstrow > naxis2) { ffpmsg( "Insert position greater than the number of rows in the table (ffirow)"); return(*status = BAD_ROW_NUM); } else if (firstrow < 0) { ffpmsg("Insert position is less than 0 (ffirow)"); return(*status = BAD_ROW_NUM); } /* current data size */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nshift = naxis1 * nrows; /* no. of bytes to add to table */ if ( (freespace - nshift) < 0) /* not enough existing space? */ { nblock = (long) ((nshift - freespace + 2879) / 2880); /* number of blocks */ ffiblk(fptr, nblock, 1, status); /* insert the blocks */ } firstbyte = naxis1 * firstrow; /* relative insert position */ nbytes = datasize - firstbyte; /* no. of bytes to shift down */ firstbyte += ((fptr->Fptr)->datastart); /* absolute insert position */ ffshft(fptr, firstbyte, nbytes, nshift, status); /* shift rows and heap */ /* update the heap starting address */ (fptr->Fptr)->heapstart += nshift; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); /* update the NAXIS2 keyword */ ffmkyj(fptr, "NAXIS2", naxis2 + nrows, "&", status); ((fptr->Fptr)->numrows) += nrows; ((fptr->Fptr)->origrows) += nrows; return(*status); } /*--------------------------------------------------------------------------*/ int ffdrow(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstrow, /* I - first row to delete (1 = first) */ LONGLONG nrows, /* I - number of rows to delete */ int *status) /* IO - error status */ /* delete NROWS rows from table starting with firstrow (1 = first row of table). */ { int tstatus; LONGLONG naxis1, naxis2; LONGLONG datasize, firstbyte, nbytes, nshift; LONGLONG freespace; long nblock; char comm[FLEN_COMMENT]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrow)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* get the current */ /* ffgkyj(fptr, "NAXIS2", &naxis2, comm, status);*/ /* size of the table */ /* the NAXIS2 keyword may not be up to date, so use the structure value */ naxis2 = (fptr->Fptr)->numrows; if (firstrow > naxis2) { ffpmsg( "Delete position greater than the number of rows in the table (ffdrow)"); return(*status = BAD_ROW_NUM); } else if (firstrow < 1) { ffpmsg("Delete position is less than 1 (ffdrow)"); return(*status = BAD_ROW_NUM); } else if (firstrow + nrows - 1 > naxis2) { ffpmsg("No. of rows to delete exceeds size of table (ffdrow)"); return(*status = BAD_ROW_NUM); } nshift = naxis1 * nrows; /* no. of bytes to delete from table */ /* cur size of data */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; firstbyte = naxis1 * (firstrow + nrows - 1); /* relative del pos */ nbytes = datasize - firstbyte; /* no. of bytes to shift up */ firstbyte += ((fptr->Fptr)->datastart); /* absolute delete position */ ffshft(fptr, firstbyte, nbytes, nshift * (-1), status); /* shift data */ freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nblock = (long) ((nshift + freespace) / 2880); /* number of blocks */ /* delete integral number blocks */ if (nblock > 0) ffdblk(fptr, nblock, status); /* update the heap starting address */ (fptr->Fptr)->heapstart -= nshift; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (long)(fptr->Fptr)->heapstart, "&", &tstatus); /* update the NAXIS2 keyword */ ffmkyj(fptr, "NAXIS2", naxis2 - nrows, "&", status); ((fptr->Fptr)->numrows) -= nrows; ((fptr->Fptr)->origrows) -= nrows; /* Update the heap data, if any. This will remove any orphaned data */ /* that was only pointed to by the rows that have been deleted */ ffcmph(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdrrg(fitsfile *fptr, /* I - FITS file pointer to table */ char *ranges, /* I - ranges of rows to delete (1 = first) */ int *status) /* IO - error status */ /* delete the ranges of rows from the table (1 = first row of table). The 'ranges' parameter typically looks like: '10-20, 30 - 40, 55' or '50-' and gives a list of rows or row ranges separated by commas. */ { char *cptr; int nranges, nranges2, ii; long *minrow, *maxrow, nrows, *rowarray, jj, kk; LONGLONG naxis2; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrrg)"); return(*status = NOT_TABLE); } /* the NAXIS2 keyword may not be up to date, so use the structure value */ naxis2 = (fptr->Fptr)->numrows; /* find how many ranges were specified ( = no. of commas in string + 1) */ cptr = ranges; for (nranges = 1; (cptr = strchr(cptr, ',')); nranges++) cptr++; minrow = calloc(nranges, sizeof(long)); maxrow = calloc(nranges, sizeof(long)); if (!minrow || !maxrow) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory for row ranges (ffdrrg)"); if (maxrow) free(maxrow); if (minrow) free(minrow); return(*status); } /* parse range list into array of range min and max values */ ffrwrg(ranges, naxis2, nranges, &nranges2, minrow, maxrow, status); if (*status > 0 || nranges2 == 0) { free(maxrow); free(minrow); return(*status); } /* determine total number or rows to delete */ nrows = 0; for (ii = 0; ii < nranges2; ii++) { nrows = nrows + maxrow[ii] - minrow[ii] + 1; } rowarray = calloc(nrows, sizeof(long)); if (!rowarray) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory for row array (ffdrrg)"); return(*status); } for (kk = 0, ii = 0; ii < nranges2; ii++) { for (jj = minrow[ii]; jj <= maxrow[ii]; jj++) { rowarray[kk] = jj; kk++; } } /* delete the rows */ ffdrws(fptr, rowarray, nrows, status); free(rowarray); free(maxrow); free(minrow); return(*status); } /*--------------------------------------------------------------------------*/ int ffdrws(fitsfile *fptr, /* I - FITS file pointer */ long *rownum, /* I - list of rows to delete (1 = first) */ long nrows, /* I - number of rows to delete */ int *status) /* IO - error status */ /* delete the list of rows from the table (1 = first row of table). */ { LONGLONG naxis1, naxis2, insertpos, nextrowpos; long ii, nextrow; char comm[FLEN_COMMENT]; unsigned char *buffer; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrws)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* row width */ ffgkyjj(fptr, "NAXIS2", &naxis2, comm, status); /* number of rows */ /* check that input row list is in ascending order */ for (ii = 1; ii < nrows; ii++) { if (rownum[ii - 1] >= rownum[ii]) { ffpmsg("row numbers are not in increasing order (ffdrws)"); return(*status = BAD_ROW_NUM); } } if (rownum[0] < 1) { ffpmsg("first row to delete is less than 1 (ffdrws)"); return(*status = BAD_ROW_NUM); } else if (rownum[nrows - 1] > naxis2) { ffpmsg("last row to delete exceeds size of table (ffdrws)"); return(*status = BAD_ROW_NUM); } buffer = (unsigned char *) malloc( (size_t) naxis1); /* buffer for one row */ if (!buffer) { ffpmsg("malloc failed (ffdrws)"); return(*status = MEMORY_ALLOCATION); } /* byte location to start of first row to delete, and the next row */ insertpos = (fptr->Fptr)->datastart + ((rownum[0] - 1) * naxis1); nextrowpos = insertpos + naxis1; nextrow = rownum[0] + 1; /* work through the list of rows to delete */ for (ii = 1; ii < nrows; nextrow++, nextrowpos += naxis1) { if (nextrow < rownum[ii]) { /* keep this row, so copy it to the new position */ ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("error while copying good rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; } else { /* skip over this row since it is in the list */ ii++; } } /* finished with all the rows to delete; copy remaining rows */ while(nextrow <= naxis2) { ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("failed to copy remaining rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; nextrowpos += naxis1; nextrow++; } free(buffer); /* now delete the empty rows at the end of the table */ ffdrow(fptr, naxis2 - nrows + 1, nrows, status); /* Update the heap data, if any. This will remove any orphaned data */ /* that was only pointed to by the rows that have been deleted */ ffcmph(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdrwsll(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *rownum, /* I - list of rows to delete (1 = first) */ LONGLONG nrows, /* I - number of rows to delete */ int *status) /* IO - error status */ /* delete the list of rows from the table (1 = first row of table). */ { LONGLONG insertpos, nextrowpos; LONGLONG naxis1, naxis2, ii, nextrow; char comm[FLEN_COMMENT]; unsigned char *buffer; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrws)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* row width */ ffgkyjj(fptr, "NAXIS2", &naxis2, comm, status); /* number of rows */ /* check that input row list is in ascending order */ for (ii = 1; ii < nrows; ii++) { if (rownum[ii - 1] >= rownum[ii]) { ffpmsg("row numbers are not in increasing order (ffdrws)"); return(*status = BAD_ROW_NUM); } } if (rownum[0] < 1) { ffpmsg("first row to delete is less than 1 (ffdrws)"); return(*status = BAD_ROW_NUM); } else if (rownum[nrows - 1] > naxis2) { ffpmsg("last row to delete exceeds size of table (ffdrws)"); return(*status = BAD_ROW_NUM); } buffer = (unsigned char *) malloc( (size_t) naxis1); /* buffer for one row */ if (!buffer) { ffpmsg("malloc failed (ffdrwsll)"); return(*status = MEMORY_ALLOCATION); } /* byte location to start of first row to delete, and the next row */ insertpos = (fptr->Fptr)->datastart + ((rownum[0] - 1) * naxis1); nextrowpos = insertpos + naxis1; nextrow = rownum[0] + 1; /* work through the list of rows to delete */ for (ii = 1; ii < nrows; nextrow++, nextrowpos += naxis1) { if (nextrow < rownum[ii]) { /* keep this row, so copy it to the new position */ ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("error while copying good rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; } else { /* skip over this row since it is in the list */ ii++; } } /* finished with all the rows to delete; copy remaining rows */ while(nextrow <= naxis2) { ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("failed to copy remaining rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; nextrowpos += naxis1; nextrow++; } free(buffer); /* now delete the empty rows at the end of the table */ ffdrow(fptr, naxis2 - nrows + 1, nrows, status); /* Update the heap data, if any. This will remove any orphaned data */ /* that was only pointed to by the rows that have been deleted */ ffcmph(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffrwrg( char *rowlist, /* I - list of rows and row ranges */ LONGLONG maxrows, /* I - number of rows in the table */ int maxranges, /* I - max number of ranges to be returned */ int *numranges, /* O - number ranges returned */ long *minrow, /* O - first row in each range */ long *maxrow, /* O - last row in each range */ int *status) /* IO - status value */ { /* parse the input list of row ranges, returning the number of ranges, and the min and max row value in each range. The only characters allowed in the input rowlist are decimal digits, minus sign, and comma (and non-significant spaces) Example: list = "10-20, 30-35,50" would return numranges = 3, minrow[] = {10, 30, 50}, maxrow[] = {20, 35, 50} error is returned if min value of range is > max value of range or if the ranges are not monotonically increasing. */ char *next; long minval, maxval; if (*status > 0) return(*status); if (maxrows <= 0 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Input maximum range value is <= 0 (fits_parse_ranges)"); return(*status); } next = rowlist; *numranges = 0; while (*next == ' ')next++; /* skip spaces */ while (*next != '\0') { /* find min value of next range; *next must be '-' or a digit */ if (*next == '-') { minval = 1; /* implied minrow value = 1 */ } else if ( isdigit((int) *next) ) { minval = strtol(next, &next, 10); } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } while (*next == ' ')next++; /* skip spaces */ /* find max value of next range; *next must be '-', or ',' */ if (*next == '-') { next++; while (*next == ' ')next++; /* skip spaces */ if ( isdigit((int) *next) ) { maxval = strtol(next, &next, 10); } else if (*next == ',' || *next == '\0') { maxval = (long) maxrows; /* implied max value */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } } else if (*next == ',' || *next == '\0') { maxval = minval; /* only a single integer in this range */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } if (*numranges + 1 > maxranges) { *status = RANGE_PARSE_ERROR; ffpmsg("Overflowed maximum number of ranges (fits_parse_ranges)"); return(*status); } if (minval < 1 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: row number < 1"); ffpmsg(rowlist); return(*status); } if (maxval < minval) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: min > max"); ffpmsg(rowlist); return(*status); } if (*numranges > 0) { if (minval <= maxrow[(*numranges) - 1]) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list. Range minimum is"); ffpmsg(" less than or equal to previous range maximum"); ffpmsg(rowlist); return(*status); } } if (minval <= maxrows) { /* ignore range if greater than maxrows */ if (maxval > maxrows) maxval = (long) maxrows; minrow[*numranges] = minval; maxrow[*numranges] = maxval; (*numranges)++; } while (*next == ' ')next++; /* skip spaces */ if (*next == ',') { next++; while (*next == ' ')next++; /* skip more spaces */ } } if (*numranges == 0) { /* a null string was entered */ minrow[0] = 1; maxrow[0] = (long) maxrows; *numranges = 1; } return(*status); } /*--------------------------------------------------------------------------*/ int ffrwrgll( char *rowlist, /* I - list of rows and row ranges */ LONGLONG maxrows, /* I - number of rows in the list */ int maxranges, /* I - max number of ranges to be returned */ int *numranges, /* O - number ranges returned */ LONGLONG *minrow, /* O - first row in each range */ LONGLONG *maxrow, /* O - last row in each range */ int *status) /* IO - status value */ { /* parse the input list of row ranges, returning the number of ranges, and the min and max row value in each range. The only characters allowed in the input rowlist are decimal digits, minus sign, and comma (and non-significant spaces) Example: list = "10-20, 30-35,50" would return numranges = 3, minrow[] = {10, 30, 50}, maxrow[] = {20, 35, 50} error is returned if min value of range is > max value of range or if the ranges are not monotonically increasing. */ char *next; LONGLONG minval, maxval; double dvalue; if (*status > 0) return(*status); if (maxrows <= 0 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Input maximum range value is <= 0 (fits_parse_ranges)"); return(*status); } next = rowlist; *numranges = 0; while (*next == ' ')next++; /* skip spaces */ while (*next != '\0') { /* find min value of next range; *next must be '-' or a digit */ if (*next == '-') { minval = 1; /* implied minrow value = 1 */ } else if ( isdigit((int) *next) ) { /* read as a double, because the string to LONGLONG function */ /* is platform dependent (strtoll, strtol, _atoI64) */ dvalue = strtod(next, &next); minval = (LONGLONG) (dvalue + 0.1); } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } while (*next == ' ')next++; /* skip spaces */ /* find max value of next range; *next must be '-', or ',' */ if (*next == '-') { next++; while (*next == ' ')next++; /* skip spaces */ if ( isdigit((int) *next) ) { /* read as a double, because the string to LONGLONG function */ /* is platform dependent (strtoll, strtol, _atoI64) */ dvalue = strtod(next, &next); maxval = (LONGLONG) (dvalue + 0.1); } else if (*next == ',' || *next == '\0') { maxval = maxrows; /* implied max value */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } } else if (*next == ',' || *next == '\0') { maxval = minval; /* only a single integer in this range */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } if (*numranges + 1 > maxranges) { *status = RANGE_PARSE_ERROR; ffpmsg("Overflowed maximum number of ranges (fits_parse_ranges)"); return(*status); } if (minval < 1 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: row number < 1"); ffpmsg(rowlist); return(*status); } if (maxval < minval) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: min > max"); ffpmsg(rowlist); return(*status); } if (*numranges > 0) { if (minval <= maxrow[(*numranges) - 1]) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list. Range minimum is"); ffpmsg(" less than or equal to previous range maximum"); ffpmsg(rowlist); return(*status); } } if (minval <= maxrows) { /* ignore range if greater than maxrows */ if (maxval > maxrows) maxval = maxrows; minrow[*numranges] = minval; maxrow[*numranges] = maxval; (*numranges)++; } while (*next == ' ')next++; /* skip spaces */ if (*next == ',') { next++; while (*next == ' ')next++; /* skip more spaces */ } } if (*numranges == 0) { /* a null string was entered */ minrow[0] = 1; maxrow[0] = maxrows; *numranges = 1; } return(*status); } /*--------------------------------------------------------------------------*/ int fficol(fitsfile *fptr, /* I - FITS file pointer */ int numcol, /* I - position for new col. (1 = 1st) */ char *ttype, /* I - name of column (TTYPE keyword) */ char *tform, /* I - format of column (TFORM keyword) */ int *status) /* IO - error status */ /* Insert a new column into an existing table at position numcol. If numcol is greater than the number of existing columns in the table then the new column will be appended as the last column in the table. */ { char *name, *format; name = ttype; format = tform; fficls(fptr, numcol, 1, &name, &format, status); return(*status); } /*--------------------------------------------------------------------------*/ int fficls(fitsfile *fptr, /* I - FITS file pointer */ int fstcol, /* I - position for first new col. (1 = 1st) */ int ncols, /* I - number of columns to insert */ char **ttype, /* I - array of column names(TTYPE keywords) */ char **tform, /* I - array of formats of column (TFORM) */ int *status) /* IO - error status */ /* Insert 1 or more new columns into an existing table at position numcol. If fstcol is greater than the number of existing columns in the table then the new column will be appended as the last column in the table. */ { int colnum, datacode, decims, tfields, tstatus, ii; LONGLONG datasize, firstbyte, nbytes, nadd, naxis1, naxis2, freespace; LONGLONG tbcol, firstcol, delbyte; long nblock, width, repeat; char tfm[FLEN_VALUE], keyname[FLEN_KEYWORD], comm[FLEN_COMMENT], *cptr; char card[FLEN_CARD]; tcolumn *colptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only add columns to TABLE or BINTABLE extension (fficls)"); return(*status = NOT_TABLE); } /* is the column number valid? */ tfields = (fptr->Fptr)->tfield; if (fstcol < 1 ) return(*status = BAD_COL_NUM); else if (fstcol > tfields) colnum = tfields + 1; /* append as last column */ else colnum = fstcol; /* parse the tform value and calc number of bytes to add to each row */ delbyte = 0; for (ii = 0; ii < ncols; ii++) { if (strlen(tform[ii]) > FLEN_VALUE-1) { ffpmsg("Column format string too long (fficls)"); return (*status=BAD_TFORM); } strcpy(tfm, tform[ii]); ffupch(tfm); /* make sure format is in upper case */ if ((fptr->Fptr)->hdutype == ASCII_TBL) { ffasfm(tfm, &datacode, &width, &decims, status); delbyte += width + 1; /* add one space between the columns */ } else { ffbnfm(tfm, &datacode, &repeat, &width, status); if (datacode < 0) { /* variable length array column */ if (strchr(tfm, 'Q')) delbyte += 16; else delbyte += 8; } else if (datacode == 1) /* bit column; round up */ delbyte += (repeat + 7) / 8; /* to multiple of 8 bits */ else if (datacode == 16) /* ASCII string column */ delbyte += repeat; else /* numerical data type */ delbyte += (datacode / 10) * repeat; } } if (*status > 0) return(*status); /* get the current size of the table */ /* use internal structure since NAXIS2 keyword may not be up to date */ naxis1 = (fptr->Fptr)->rowlength; naxis2 = (fptr->Fptr)->numrows; /* current size of data */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nadd = delbyte * naxis2; /* no. of bytes to add to table */ if ( (freespace - nadd) < 0) /* not enough existing space? */ { nblock = (long) ((nadd - freespace + 2879) / 2880); /* number of blocks */ if (ffiblk(fptr, nblock, 1, status) > 0) /* insert the blocks */ return(*status); } /* shift heap down (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift down */ /* absolute heap pos */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; if (ffshft(fptr, firstbyte, nbytes, nadd, status) > 0) /* move heap */ return(*status); } /* update the heap starting address */ (fptr->Fptr)->heapstart += nadd; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); /* calculate byte position in the row where to insert the new column */ if (colnum > tfields) firstcol = naxis1; else { colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); firstcol = colptr->tbcol; } /* insert delbyte bytes in every row, at byte position firstcol */ ffcins(fptr, naxis1, naxis2, delbyte, firstcol, status); if ((fptr->Fptr)->hdutype == ASCII_TBL) { /* adjust the TBCOL values of the existing columns */ for(ii = 0; ii < tfields; ii++) { ffkeyn("TBCOL", ii + 1, keyname, status); ffgkyjj(fptr, keyname, &tbcol, comm, status); if (tbcol > firstcol) { tbcol += delbyte; ffmkyj(fptr, keyname, tbcol, "&", status); } } } /* update the mandatory keywords */ ffmkyj(fptr, "TFIELDS", tfields + ncols, "&", status); ffmkyj(fptr, "NAXIS1", naxis1 + delbyte, "&", status); /* increment the index value on any existing column keywords */ if(colnum <= tfields) ffkshf(fptr, colnum, tfields, ncols, status); /* add the required keywords for the new columns */ for (ii = 0; ii < ncols; ii++, colnum++) { strcpy(comm, "label for field"); ffkeyn("TTYPE", colnum, keyname, status); ffpkys(fptr, keyname, ttype[ii], comm, status); strcpy(comm, "format of field"); strcpy(tfm, tform[ii]); ffupch(tfm); /* make sure format is in upper case */ ffkeyn("TFORM", colnum, keyname, status); if (abs(datacode) == TSBYTE) { /* Replace the 'S' with an 'B' in the TFORMn code */ cptr = tfm; while (*cptr != 'S') cptr++; *cptr = 'B'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, keyname, status); strcpy(comm, "offset for signed bytes"); ffpkyg(fptr, keyname, -128., 0, comm, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else if (abs(datacode) == TUSHORT) { /* Replace the 'U' with an 'I' in the TFORMn code */ cptr = tfm; while (*cptr != 'U') cptr++; *cptr = 'I'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, keyname, status); strcpy(comm, "offset for unsigned integers"); ffpkyg(fptr, keyname, 32768., 0, comm, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else if (abs(datacode) == TULONG) { /* Replace the 'V' with an 'J' in the TFORMn code */ cptr = tfm; while (*cptr != 'V') cptr++; *cptr = 'J'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, keyname, status); strcpy(comm, "offset for unsigned integers"); ffpkyg(fptr, keyname, 2147483648., 0, comm, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else if (abs(datacode) == TULONGLONG) { /* Replace the 'W' with an 'K' in the TFORMn code */ cptr = tfm; while (*cptr != 'W') cptr++; *cptr = 'K'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, card, status); strcat(card, " "); /* make sure name is >= 8 chars long */ *(card+8) = '\0'; strcat(card, "= 9223372036854775808 / offset for unsigned integers"); fits_write_record(fptr, card, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else { ffpkys(fptr, keyname, tfm, comm, status); } if ((fptr->Fptr)->hdutype == ASCII_TBL) /* write the TBCOL keyword */ { if (colnum == tfields + 1) tbcol = firstcol + 2; /* allow space between preceding col */ else tbcol = firstcol + 1; strcpy(comm, "beginning column of field"); ffkeyn("TBCOL", colnum, keyname, status); ffpkyj(fptr, keyname, tbcol, comm, status); /* increment the column starting position for the next column */ ffasfm(tfm, &datacode, &width, &decims, status); firstcol += width + 1; /* add one space between the columns */ } } ffrdef(fptr, status); /* initialize the new table structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffmvec(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - position of col to be modified */ LONGLONG newveclen, /* I - new vector length of column (TFORM) */ int *status) /* IO - error status */ /* Modify the vector length of a column in a binary table, larger or smaller. E.g., change a column from TFORMn = '1E' to '20E'. */ { int datacode, tfields, tstatus; LONGLONG datasize, size, firstbyte, nbytes, nadd, ndelete; LONGLONG naxis1, naxis2, firstcol, freespace; LONGLONG width, delbyte, repeat; long nblock; char tfm[FLEN_VALUE], keyname[FLEN_KEYWORD], tcode[2]; tcolumn *colptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg( "Can only change vector length of a column in BINTABLE extension (ffmvec)"); return(*status = NOT_TABLE); } /* is the column number valid? */ tfields = (fptr->Fptr)->tfield; if (colnum < 1 || colnum > tfields) return(*status = BAD_COL_NUM); /* look up the current vector length and element width */ colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); datacode = colptr->tdatatype; /* datatype of the column */ repeat = colptr->trepeat; /* field repeat count */ width = colptr->twidth; /* width of a single element in chars */ if (datacode < 0) { ffpmsg( "Can't modify vector length of variable length column (ffmvec)"); return(*status = BAD_TFORM); } if (repeat == newveclen) return(*status); /* column already has the desired vector length */ if (datacode == TSTRING) width = 1; /* width was equal to width of unit string */ naxis1 = (fptr->Fptr)->rowlength; /* current width of the table */ naxis2 = (fptr->Fptr)->numrows; delbyte = (newveclen - repeat) * width; /* no. of bytes to insert */ if (datacode == TBIT) /* BIT column is a special case */ delbyte = ((newveclen + 7) / 8) - ((repeat + 7) / 8); if (delbyte > 0) /* insert space for more elements */ { /* current size of data */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nadd = (LONGLONG)delbyte * naxis2; /* no. of bytes to add to table */ if ( (freespace - nadd) < 0) /* not enough existing space? */ { nblock = (long) ((nadd - freespace + 2879) / 2880); /* number of blocks */ if (ffiblk(fptr, nblock, 1, status) > 0) /* insert the blocks */ return(*status); } /* shift heap down (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift down */ /* absolute heap pos */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; if (ffshft(fptr, firstbyte, nbytes, nadd, status) > 0) /* move heap */ return(*status); } /* update the heap starting address */ (fptr->Fptr)->heapstart += nadd; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); /* Must reset colptr before using it again. (fptr->Fptr)->tableptr may have been reallocated down in ffbinit via the call to ffiblk above.*/ colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); firstcol = colptr->tbcol + (repeat * width); /* insert position */ /* insert delbyte bytes in every row, at byte position firstcol */ ffcins(fptr, naxis1, naxis2, delbyte, firstcol, status); } else if (delbyte < 0) { /* current size of table */ size = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ((size + 2879) / 2880) * 2880 - size - ((LONGLONG)delbyte * naxis2); nblock = (long) (freespace / 2880); /* number of empty blocks to delete */ firstcol = colptr->tbcol + (newveclen * width); /* delete position */ /* delete elements from the vector */ ffcdel(fptr, naxis1, naxis2, -delbyte, firstcol, status); /* abs heap pos */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; ndelete = (LONGLONG)delbyte * naxis2; /* size of shift (negative) */ /* shift heap up (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift up */ if (ffshft(fptr, firstbyte, nbytes, ndelete, status) > 0) return(*status); } /* delete the empty blocks at the end of the HDU */ if (nblock > 0) ffdblk(fptr, nblock, status); /* update the heap starting address */ (fptr->Fptr)->heapstart += ndelete; /* ndelete is negative */ /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); } /* construct the new TFORM keyword for the column */ if (datacode == TBIT) strcpy(tcode,"X"); else if (datacode == TBYTE) strcpy(tcode,"B"); else if (datacode == TLOGICAL) strcpy(tcode,"L"); else if (datacode == TSTRING) strcpy(tcode,"A"); else if (datacode == TSHORT) strcpy(tcode,"I"); else if (datacode == TLONG) strcpy(tcode,"J"); else if (datacode == TLONGLONG) strcpy(tcode,"K"); else if (datacode == TFLOAT) strcpy(tcode,"E"); else if (datacode == TDOUBLE) strcpy(tcode,"D"); else if (datacode == TCOMPLEX) strcpy(tcode,"C"); else if (datacode == TDBLCOMPLEX) strcpy(tcode,"M"); /* write as a double value because the LONGLONG conversion */ /* character in snprintf is platform dependent ( %lld, %ld, %I64d ) */ snprintf(tfm,FLEN_VALUE,"%.0f%s",(double) newveclen, tcode); ffkeyn("TFORM", colnum, keyname, status); /* Keyword name */ ffmkys(fptr, keyname, tfm, "&", status); /* modify TFORM keyword */ ffmkyj(fptr, "NAXIS1", naxis1 + delbyte, "&", status); /* modify NAXIS1 */ ffrdef(fptr, status); /* reinitialize the new table structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcpcl(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int incol, /* I - number of input column */ int outcol, /* I - number for output column */ int create_col, /* I - create new col if TRUE, else overwrite */ int *status) /* IO - error status */ /* copy a column from infptr and insert it in the outfptr table. */ { int tstatus, colnum, typecode, otypecode, etypecode, anynull; int inHduType, outHduType; long tfields, repeat, orepeat, width, owidth, nrows, outrows; long inloop, outloop, maxloop, ndone, ntodo, npixels; long firstrow, firstelem, ii; char keyname[FLEN_KEYWORD], ttype[FLEN_VALUE], tform[FLEN_VALUE]; char ttype_comm[FLEN_COMMENT],tform_comm[FLEN_COMMENT]; char *lvalues = 0, nullflag, **strarray = 0; char nulstr[] = {'\5', '\0'}; /* unique null string value */ double dnull = 0.l, *dvalues = 0; float fnull = 0., *fvalues = 0; long long int *jjvalues = 0; unsigned long long int *ujjvalues = 0; if (*status > 0) return(*status); if (infptr->HDUposition != (infptr->Fptr)->curhdu) { ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); } else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(infptr, status); /* rescan header */ inHduType = (infptr->Fptr)->hdutype; if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) { ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); } else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(outfptr, status); /* rescan header */ outHduType = (outfptr->Fptr)->hdutype; if (*status > 0) return(*status); if (inHduType == IMAGE_HDU || outHduType == IMAGE_HDU) { ffpmsg ("Can not copy columns to or from IMAGE HDUs (ffcpcl)"); return(*status = NOT_TABLE); } if ( inHduType == BINARY_TBL && outHduType == ASCII_TBL) { ffpmsg ("Copying from Binary table to ASCII table is not supported (ffcpcl)"); return(*status = NOT_BTABLE); } /* get the datatype and vector repeat length of the column */ ffgtcl(infptr, incol, &typecode, &repeat, &width, status); /* ... and equivalent type code */ ffeqty(infptr, incol, &etypecode, 0, 0, status); if (typecode < 0) { ffpmsg("Variable-length columns are not supported (ffcpcl)"); return(*status = BAD_TFORM); } if (create_col) /* insert new column in output table? */ { tstatus = 0; ffkeyn("TTYPE", incol, keyname, &tstatus); ffgkys(infptr, keyname, ttype, ttype_comm, &tstatus); ffkeyn("TFORM", incol, keyname, &tstatus); if (ffgkys(infptr, keyname, tform, tform_comm, &tstatus) ) { ffpmsg ("Could not find TTYPE and TFORM keywords in input table (ffcpcl)"); return(*status = NO_TFORM); } if (inHduType == ASCII_TBL && outHduType == BINARY_TBL) { /* convert from ASCII table to BINARY table format string */ if (typecode == TSTRING) ffnkey(width, "A", tform, status); else if (typecode == TLONG) strcpy(tform, "1J"); else if (typecode == TSHORT) strcpy(tform, "1I"); else if (typecode == TFLOAT) strcpy(tform,"1E"); else if (typecode == TDOUBLE) strcpy(tform,"1D"); } if (ffgkyj(outfptr, "TFIELDS", &tfields, 0, &tstatus)) { ffpmsg ("Could not read TFIELDS keyword in output table (ffcpcl)"); return(*status = NO_TFIELDS); } colnum = minvalue((int) tfields + 1, outcol); /* output col. number */ /* create the empty column */ if (fficol(outfptr, colnum, ttype, tform, status) > 0) { ffpmsg ("Could not append new column to output file (ffcpcl)"); return(*status); } if ((infptr->Fptr == outfptr->Fptr) && (infptr->HDUposition == outfptr->HDUposition) && (colnum <= incol)) { incol++; /* the input column has been shifted over */ } /* copy the comment strings from the input file for TTYPE and TFORM */ tstatus = 0; ffkeyn("TTYPE", colnum, keyname, &tstatus); ffmcom(outfptr, keyname, ttype_comm, &tstatus); ffkeyn("TFORM", colnum, keyname, &tstatus); ffmcom(outfptr, keyname, tform_comm, &tstatus); /* copy other column-related keywords if they exist */ ffcpky(infptr, outfptr, incol, colnum, "TUNIT", status); ffcpky(infptr, outfptr, incol, colnum, "TSCAL", status); ffcpky(infptr, outfptr, incol, colnum, "TZERO", status); ffcpky(infptr, outfptr, incol, colnum, "TDISP", status); ffcpky(infptr, outfptr, incol, colnum, "TLMIN", status); ffcpky(infptr, outfptr, incol, colnum, "TLMAX", status); ffcpky(infptr, outfptr, incol, colnum, "TDIM", status); /* WCS keywords */ ffcpky(infptr, outfptr, incol, colnum, "TCTYP", status); ffcpky(infptr, outfptr, incol, colnum, "TCUNI", status); ffcpky(infptr, outfptr, incol, colnum, "TCRVL", status); ffcpky(infptr, outfptr, incol, colnum, "TCRPX", status); ffcpky(infptr, outfptr, incol, colnum, "TCDLT", status); ffcpky(infptr, outfptr, incol, colnum, "TCROT", status); if (inHduType == ASCII_TBL && outHduType == BINARY_TBL) { /* binary tables only have TNULLn keyword for integer columns */ if (typecode == TLONG || typecode == TSHORT) { /* check if null string is defined; replace with integer */ ffkeyn("TNULL", incol, keyname, &tstatus); if (ffgkys(infptr, keyname, ttype, 0, &tstatus) <= 0) { ffkeyn("TNULL", colnum, keyname, &tstatus); if (typecode == TLONG) ffpkyj(outfptr, keyname, -9999999L, "Null value", status); else ffpkyj(outfptr, keyname, -32768L, "Null value", status); } } } else { ffcpky(infptr, outfptr, incol, colnum, "TNULL", status); } /* rescan header to recognize the new keywords */ if (ffrdef(outfptr, status) ) return(*status); } else { colnum = outcol; /* get the datatype and vector repeat length of the output column */ ffgtcl(outfptr, outcol, &otypecode, &orepeat, &owidth, status); if (orepeat != repeat) { ffpmsg("Input and output vector columns must have same length (ffcpcl)"); return(*status = BAD_TFORM); } } ffgkyj(infptr, "NAXIS2", &nrows, 0, status); /* no. of input rows */ ffgkyj(outfptr, "NAXIS2", &outrows, 0, status); /* no. of output rows */ nrows = minvalue(nrows, outrows); if (typecode == TBIT) repeat = (repeat + 7) / 8; /* convert from bits to bytes */ else if (typecode == TSTRING && inHduType == BINARY_TBL) repeat = repeat / width; /* convert from chars to unit strings */ /* get optimum number of rows to copy at one time */ ffgrsz(infptr, &inloop, status); ffgrsz(outfptr, &outloop, status); /* adjust optimum number, since 2 tables are open at once */ maxloop = minvalue(inloop, outloop); /* smallest of the 2 tables */ maxloop = maxvalue(1, maxloop / 2); /* at least 1 row */ maxloop = minvalue(maxloop, nrows); /* max = nrows to be copied */ maxloop *= repeat; /* mult by no of elements in a row */ /* allocate memory for arrays */ if (typecode == TLOGICAL) { lvalues = (char *) calloc(maxloop, sizeof(char) ); if (!lvalues) { ffpmsg ("malloc failed to get memory for logicals (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } } else if (typecode == TSTRING) { /* allocate array of pointers */ strarray = (char **) calloc(maxloop, sizeof(strarray)); /* allocate space for each string */ for (ii = 0; ii < maxloop; ii++) strarray[ii] = (char *) calloc(width+1, sizeof(char)); } else if (typecode == TCOMPLEX) { fvalues = (float *) calloc(maxloop * 2, sizeof(float) ); if (!fvalues) { ffpmsg ("malloc failed to get memory for complex (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } fnull = 0.; } else if (typecode == TDBLCOMPLEX) { dvalues = (double *) calloc(maxloop * 2, sizeof(double) ); if (!dvalues) { ffpmsg ("malloc failed to get memory for dbl complex (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } dnull = 0.; } /* These are unsigned long-long ints that are not rescaled to floating point numbers */ else if (typecode == TLONGLONG && etypecode == TULONGLONG) { ujjvalues = (unsigned long long int *) calloc(maxloop, sizeof(unsigned long long int) ); if (!ujjvalues) { ffpmsg ("malloc failed to get memory for unsigned long long int (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } } /* These are long-long ints that are not rescaled to floating point numbers */ else if (typecode == TLONGLONG && etypecode != TDOUBLE) { jjvalues = (long long int *) calloc(maxloop, sizeof(long long int) ); if (!jjvalues) { ffpmsg ("malloc failed to get memory for long long int (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } } else /* other numerical datatype; read them all as doubles */ { dvalues = (double *) calloc(maxloop, sizeof(double) ); if (!dvalues) { ffpmsg ("malloc failed to get memory for doubles (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } dnull = -9.99991999E31; /* use an unlikely value for nulls */ } npixels = nrows * repeat; /* total no. of pixels to copy */ ntodo = minvalue(npixels, maxloop); /* no. to copy per iteration */ ndone = 0; /* total no. of pixels that have been copied */ while (ntodo) /* iterate through the table */ { firstrow = ndone / repeat + 1; firstelem = ndone - ((firstrow - 1) * repeat) + 1; /* read from input table */ if (typecode == TLOGICAL) ffgcl(infptr, incol, firstrow, firstelem, ntodo, lvalues, status); else if (typecode == TSTRING) ffgcvs(infptr, incol, firstrow, firstelem, ntodo, nulstr, strarray, &anynull, status); else if (typecode == TCOMPLEX) ffgcvc(infptr, incol, firstrow, firstelem, ntodo, fnull, fvalues, &anynull, status); else if (typecode == TDBLCOMPLEX) ffgcvm(infptr, incol, firstrow, firstelem, ntodo, dnull, dvalues, &anynull, status); /* Neither TULONGLONG nor TLONGLONG does null checking. Whatever null value is in input table is transferred to output table without checking. Since the TNULL value was copied, this should preserve null values */ else if (typecode == TLONGLONG && etypecode == TULONGLONG) ffgcvujj(infptr, incol, firstrow, firstelem, ntodo, /*nulval*/ 0, ujjvalues, &anynull, status); else if (typecode == TLONGLONG && etypecode != TDOUBLE) ffgcvjj(infptr, incol, firstrow, firstelem, ntodo, /*nulval*/ 0, jjvalues, &anynull, status); else /* all numerical types */ ffgcvd(infptr, incol, firstrow, firstelem, ntodo, dnull, dvalues, &anynull, status); if (*status > 0) { ffpmsg("Error reading input copy of column (ffcpcl)"); break; } /* write to output table */ if (typecode == TLOGICAL) { nullflag = 2; ffpcnl(outfptr, colnum, firstrow, firstelem, ntodo, lvalues, nullflag, status); } else if (typecode == TSTRING) { if (anynull) ffpcns(outfptr, colnum, firstrow, firstelem, ntodo, strarray, nulstr, status); else ffpcls(outfptr, colnum, firstrow, firstelem, ntodo, strarray, status); } else if (typecode == TCOMPLEX) { /* doesn't support writing nulls */ ffpclc(outfptr, colnum, firstrow, firstelem, ntodo, fvalues, status); } else if (typecode == TDBLCOMPLEX) { /* doesn't support writing nulls */ ffpclm(outfptr, colnum, firstrow, firstelem, ntodo, dvalues, status); } else if (typecode == TLONGLONG && etypecode == TULONGLONG) { /* No null checking because we did none to read */ ffpclujj(outfptr, colnum, firstrow, firstelem, ntodo, ujjvalues, status); } else if (typecode == TLONGLONG && etypecode != TDOUBLE) { /* No null checking because we did none to read */ ffpcljj(outfptr, colnum, firstrow, firstelem, ntodo, jjvalues, status); } else /* all other numerical types */ { if (anynull) ffpcnd(outfptr, colnum, firstrow, firstelem, ntodo, dvalues, dnull, status); else ffpcld(outfptr, colnum, firstrow, firstelem, ntodo, dvalues, status); } if (*status > 0) { ffpmsg("Error writing output copy of column (ffcpcl)"); break; } npixels -= ntodo; ndone += ntodo; ntodo = minvalue(npixels, maxloop); } /* free the previously allocated memory */ if (typecode == TLOGICAL) { free(lvalues); } else if (typecode == TSTRING) { for (ii = 0; ii < maxloop; ii++) free(strarray[ii]); free(strarray); } if (ujjvalues) free(ujjvalues); if (jjvalues) free(jjvalues); if (dvalues) free(dvalues); return(*status); } /*--------------------------------------------------------------------------*/ int ffccls(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int incol, /* I - number of first input column */ int outcol, /* I - number for first output column */ int ncols, /* I - number of columns to copy from input to output */ int create_col, /* I - create new col if TRUE, else overwrite */ int *status) /* IO - error status */ /* copy multiple columns from infptr and insert them in the outfptr table. Optimized for multiple-column case since it only expands the output file once using fits_insert_cols() instead of calling fits_insert_col() multiple times. */ { int tstatus, colnum, typecode, otypecode, anynull; int inHduType, outHduType; long tfields, repeat, orepeat, width, owidth, nrows, outrows; long inloop, outloop, maxloop, ndone, ntodo, npixels; long firstrow, firstelem, ii; char keyname[FLEN_KEYWORD], ttype[FLEN_VALUE], tform[FLEN_VALUE]; char ttype_comm[FLEN_COMMENT],tform_comm[FLEN_COMMENT]; char *lvalues = 0, nullflag, **strarray = 0; char nulstr[] = {'\5', '\0'}; /* unique null string value */ double dnull = 0.l, *dvalues = 0; float fnull = 0., *fvalues = 0; int typecodes[1000]; char *ttypes[1000], *tforms[1000], keyarr[1001][FLEN_CARD]; int ikey = 0; int icol, incol1, outcol1; if (*status > 0) return(*status); /* Do not allow more than internal array limit to be copied */ if (ncols > 1000) return (*status = ARRAY_TOO_BIG); if (infptr->HDUposition != (infptr->Fptr)->curhdu) { ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); } else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(infptr, status); /* rescan header */ inHduType = (infptr->Fptr)->hdutype; if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) { ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); } else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(outfptr, status); /* rescan header */ outHduType = (outfptr->Fptr)->hdutype; if (*status > 0) return(*status); if (inHduType == IMAGE_HDU || outHduType == IMAGE_HDU) { ffpmsg ("Can not copy columns to or from IMAGE HDUs (ffccls)"); return(*status = NOT_TABLE); } if ( (inHduType == BINARY_TBL && outHduType == ASCII_TBL) || (inHduType == ASCII_TBL && outHduType == BINARY_TBL) ) { ffpmsg ("Copying between Binary and ASCII tables is not supported (ffccls)"); return(*status = NOT_BTABLE); } /* Do not allow copying multiple columns in the same HDU because the permutations of possible overlapping copies is mind-bending */ if ((infptr->Fptr == outfptr->Fptr) && (infptr->HDUposition == outfptr->HDUposition)) { ffpmsg ("Copying multiple columns in same HDU is not supported (ffccls)"); return(*status = NOT_BTABLE); } /* Retrieve the number of columns in output file */ tstatus=0; if (ffgkyj(outfptr, "TFIELDS", &tfields, 0, &tstatus)) { ffpmsg ("Could not read TFIELDS keyword in output table (ffccls)"); return(*status = NO_TFIELDS); } colnum = minvalue((int) tfields + 1, outcol); /* output col. number */ /* Collect data about input column (type, repeat, etc) */ for (incol1 = incol, outcol1 = colnum, icol = 0; icol < ncols; icol++, incol1++, outcol1++) { ffgtcl(infptr, incol1, &typecode, &repeat, &width, status); if (typecode < 0) { ffpmsg("Variable-length columns are not supported (ffccls)"); return(*status = BAD_TFORM); } typecodes[icol] = typecode; tstatus = 0; ffkeyn("TTYPE", incol1, keyname, &tstatus); ffgkys(infptr, keyname, ttype, ttype_comm, &tstatus); ffkeyn("TFORM", incol1, keyname, &tstatus); if (ffgkys(infptr, keyname, tform, tform_comm, &tstatus) ) { ffpmsg ("Could not find TTYPE and TFORM keywords in input table (ffccls)"); return(*status = NO_TFORM); } /* If creating columns, we need to save these values */ if ( create_col ) { tforms[icol] = keyarr[ikey++]; ttypes[icol] = keyarr[ikey++]; strcpy(tforms[icol], tform); strcpy(ttypes[icol], ttype); } else { /* If not creating columns, then check the datatype and vector repeat length of the output column */ ffgtcl(outfptr, outcol1, &otypecode, &orepeat, &owidth, status); if (orepeat != repeat) { ffpmsg("Input and output vector columns must have same length (ffccls)"); return(*status = BAD_TFORM); } } } /* Insert columns into output file and copy all meta-data keywords, if requested */ if (create_col) { /* create the empty columns */ if (fficls(outfptr, colnum, ncols, ttypes, tforms, status) > 0) { ffpmsg ("Could not append new columns to output file (ffccls)"); return(*status); } /* Copy meta-data strings from input column to output */ for (incol1 = incol, outcol1 = colnum, icol = 0; icol < ncols; icol++, incol1++, outcol1++) { /* copy the comment strings from the input file for TTYPE and TFORM */ ffkeyn("TTYPE", incol1, keyname, status); ffgkys(infptr, keyname, ttype, ttype_comm, status); ffkeyn("TTYPE", outcol1, keyname, status); ffmcom(outfptr, keyname, ttype_comm, status); ffkeyn("TFORM", incol1, keyname, status); ffgkys(infptr, keyname, tform, tform_comm, status); ffkeyn("TFORM", outcol1, keyname, status); ffmcom(outfptr, keyname, tform_comm, status); /* copy other column-related keywords if they exist */ ffcpky(infptr, outfptr, incol1, outcol1, "TUNIT", status); ffcpky(infptr, outfptr, incol1, outcol1, "TSCAL", status); ffcpky(infptr, outfptr, incol1, outcol1, "TZERO", status); ffcpky(infptr, outfptr, incol1, outcol1, "TDISP", status); ffcpky(infptr, outfptr, incol1, outcol1, "TLMIN", status); ffcpky(infptr, outfptr, incol1, outcol1, "TLMAX", status); ffcpky(infptr, outfptr, incol1, outcol1, "TDIM", status); /* WCS keywords */ ffcpky(infptr, outfptr, incol1, outcol1, "TCTYP", status); ffcpky(infptr, outfptr, incol1, outcol1, "TCUNI", status); ffcpky(infptr, outfptr, incol1, outcol1, "TCRVL", status); ffcpky(infptr, outfptr, incol1, outcol1, "TCRPX", status); ffcpky(infptr, outfptr, incol1, outcol1, "TCDLT", status); ffcpky(infptr, outfptr, incol1, outcol1, "TCROT", status); ffcpky(infptr, outfptr, incol1, outcol1, "TNULL", status); } /* rescan header to recognize the new keywords */ if (ffrdef(outfptr, status) ) return(*status); } /* Copy columns using standard ffcpcl(); do this in a loop because the I/O-intensive column expanding is done */ for (incol1 = incol, outcol1 = colnum, icol = 0; icol < ncols; icol++, incol1++, outcol1++) { ffcpcl(infptr, outfptr, incol1, outcol1, 0, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffcprw(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ LONGLONG firstrow, /* I - number of first row to copy (1 based) */ LONGLONG nrows, /* I - number of rows to copy */ int *status) /* IO - error status */ /* copy consecutive set of rows from infptr and append it in the outfptr table. */ { LONGLONG innaxis1, innaxis2, outnaxis1, outnaxis2, ii, jj, icol; LONGLONG iVarCol, inPos, outPos, nVarBytes, nVarAllocBytes = 0; unsigned char *buffer, *varColBuff=0; int nInVarCols=0, nOutVarCols=0, varColDiff=0; int *inVarCols=0, *outVarCols=0; long nNewBlocks; LONGLONG hrepeat=0, hoffset=0; tcolumn *colptr=0; if (*status > 0) return(*status); if (infptr->HDUposition != (infptr->Fptr)->curhdu) { ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); } else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(infptr, status); /* rescan header */ if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) { ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); } else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(outfptr, status); /* rescan header */ if (*status > 0) return(*status); if ((infptr->Fptr)->hdutype == IMAGE_HDU || (outfptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg ("Can not copy rows to or from IMAGE HDUs (ffcprw)"); return(*status = NOT_TABLE); } if ( ((infptr->Fptr)->hdutype == BINARY_TBL && (outfptr->Fptr)->hdutype == ASCII_TBL) || ((infptr->Fptr)->hdutype == ASCII_TBL && (outfptr->Fptr)->hdutype == BINARY_TBL) ) { ffpmsg ("Copying rows between Binary and ASCII tables is not supported (ffcprw)"); return(*status = NOT_BTABLE); } ffgkyjj(infptr, "NAXIS1", &innaxis1, 0, status); /* width of input rows */ ffgkyjj(infptr, "NAXIS2", &innaxis2, 0, status); /* no. of input rows */ ffgkyjj(outfptr, "NAXIS1", &outnaxis1, 0, status); /* width of output rows */ ffgkyjj(outfptr, "NAXIS2", &outnaxis2, 0, status); /* no. of output rows */ if (*status > 0) return(*status); if (outnaxis1 != innaxis1) { ffpmsg ("Input and output tables do not have same width (ffcprw)"); return(*status = BAD_ROW_WIDTH); } if (firstrow + nrows - 1 > innaxis2) { ffpmsg ("Not enough rows in input table to copy (ffcprw)"); return(*status = BAD_ROW_NUM); } if ((infptr->Fptr)->tfield != (outfptr->Fptr)->tfield) { ffpmsg ("Input and output tables do not have same number of columns (ffcprw)"); return(*status = BAD_COL_NUM); } /* allocate buffer to hold 1 row of data */ buffer = malloc( (size_t) innaxis1); if (!buffer) { ffpmsg ("Unable to allocate memory (ffcprw)"); return(*status = MEMORY_ALLOCATION); } inVarCols = malloc(infptr->Fptr->tfield*sizeof(int)); outVarCols = malloc(outfptr->Fptr->tfield*sizeof(int)); fffvcl(infptr, &nInVarCols, inVarCols, status); fffvcl(outfptr, &nOutVarCols, outVarCols, status); if (nInVarCols != nOutVarCols) varColDiff=1; else { for (ii=0; iiFptr)->tableptr; for (icol=0; icol<(infptr->Fptr)->tfield; ++icol) { if (iVarCol < nInVarCols && inVarCols[iVarCol] == icol+1) { /* Copy from a variable length column */ ffgdesll(infptr, icol+1, ii, &hrepeat, &hoffset, status); /* If this is a bit column, hrepeat will be number of bits, not bytes. If it is a string column, hrepeat is the number of bytes, twidth is the max col width and can be ignored.*/ if (colptr->tdatatype == -TBIT) { nVarBytes = (hrepeat+7)/8; } else if (colptr->tdatatype == -TSTRING) { nVarBytes = hrepeat; } else { nVarBytes = hrepeat*colptr->twidth*sizeof(char); } inPos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + hoffset; outPos = (outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + (outfptr->Fptr)->heapsize; ffmbyt(infptr, inPos, REPORT_EOF, status); /* If this is not the last HDU in the file, then check if */ /* extending the heap would overwrite the following header. */ /* If so, then have to insert more blocks. */ if ( !((outfptr->Fptr)->lasthdu) ) { if (outPos+nVarBytes > (outfptr->Fptr)->headstart[(outfptr->Fptr)->curhdu+1]) { nNewBlocks = (long)(((outPos+nVarBytes - 1 - (outfptr->Fptr)->headstart[(outfptr->Fptr)-> curhdu+1]) / 2880) + 1); if (ffiblk(outfptr, nNewBlocks, 1, status) > 0) { ffpmsg("Failed to extend the size of the variable length heap (ffcprw)"); goto CLEANUP_RETURN; } } } if (nVarBytes) { if (nVarBytes > nVarAllocBytes) { /* Grow the copy buffer to accomodate the new maximum size. Note it is safe to call realloc() with null input pointer, which is equivalent to malloc(). */ unsigned char *varColBuff1 = (unsigned char *) realloc(varColBuff, nVarBytes); if (! varColBuff1) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory for variable column copy (ffcprw)"); goto CLEANUP_RETURN; } /* Record the new state */ varColBuff = varColBuff1; nVarAllocBytes = nVarBytes; } /* Copy date from input to output */ ffgbyt(infptr, nVarBytes, varColBuff, status); ffmbyt(outfptr, outPos, IGNORE_EOF, status); ffpbyt(outfptr, nVarBytes, varColBuff, status); } ffpdes(outfptr, icol+1, jj, hrepeat, (outfptr->Fptr)->heapsize, status); (outfptr->Fptr)->heapsize += nVarBytes; ++iVarCol; } ++colptr; } ++jj; } } else { /* copy the rows, 1 at a time */ for (ii = firstrow; ii < firstrow + nrows; ii++) { fits_read_tblbytes (infptr, ii, 1, innaxis1, buffer, status); fits_write_tblbytes(outfptr, jj, 1, innaxis1, buffer, status); jj++; } } outnaxis2 += nrows; fits_update_key(outfptr, TLONGLONG, "NAXIS2", &outnaxis2, 0, status); CLEANUP_RETURN: free(buffer); free(inVarCols); free(outVarCols); if (varColBuff) free(varColBuff); return(*status); } /*--------------------------------------------------------------------------*/ int ffcpsr(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ LONGLONG firstrow, /* I - number of first row to copy (1 based) */ LONGLONG nrows, /* I - number of rows to copy */ char *row_status, /* I - quality list of rows to keep (1) or not keep (0) */ int *status) /* IO - error status */ /* copy consecutive set of rows from infptr and append it in the outfptr table. */ { LONGLONG innaxis1, innaxis2, outnaxis1, outnaxis2, ii, jj, i0, icol; LONGLONG iVarCol, inPos, outPos, nVarBytes, nVarAllocBytes = 0; unsigned char *buffer, *varColBuff=0; int nInVarCols=0, nOutVarCols=0, varColDiff=0; int *inVarCols=0, *outVarCols=0; long nNewBlocks; LONGLONG hrepeat=0, hoffset=0; tcolumn *colptr=0; LONGLONG n_good_rows = nrows; if (*status > 0) return(*status); if (infptr->HDUposition != (infptr->Fptr)->curhdu) { ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); } else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(infptr, status); /* rescan header */ if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) { ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); } else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(outfptr, status); /* rescan header */ if (*status > 0) return(*status); if ((infptr->Fptr)->hdutype == IMAGE_HDU || (outfptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg ("Can not copy rows to or from IMAGE HDUs (ffcprw)"); return(*status = NOT_TABLE); } if ( ((infptr->Fptr)->hdutype == BINARY_TBL && (outfptr->Fptr)->hdutype == ASCII_TBL) || ((infptr->Fptr)->hdutype == ASCII_TBL && (outfptr->Fptr)->hdutype == BINARY_TBL) ) { ffpmsg ("Copying rows between Binary and ASCII tables is not supported (ffcprw)"); return(*status = NOT_BTABLE); } ffgkyjj(infptr, "NAXIS1", &innaxis1, 0, status); /* width of input rows */ ffgkyjj(infptr, "NAXIS2", &innaxis2, 0, status); /* no. of input rows */ ffgkyjj(outfptr, "NAXIS1", &outnaxis1, 0, status); /* width of output rows */ ffgkyjj(outfptr, "NAXIS2", &outnaxis2, 0, status); /* no. of output rows */ if (*status > 0) return(*status); if (outnaxis1 != innaxis1) { ffpmsg ("Input and output tables do not have same width (ffcprw)"); return(*status = BAD_ROW_WIDTH); } if (firstrow + nrows - 1 > innaxis2) { ffpmsg ("Not enough rows in input table to copy (ffcprw)"); return(*status = BAD_ROW_NUM); } if ((infptr->Fptr)->tfield != (outfptr->Fptr)->tfield) { ffpmsg ("Input and output tables do not have same number of columns (ffcprw)"); return(*status = BAD_COL_NUM); } /* allocate buffer to hold 1 row of data */ buffer = malloc( (size_t) innaxis1); if (!buffer) { ffpmsg ("Unable to allocate memory (ffcprw)"); return(*status = MEMORY_ALLOCATION); } inVarCols = malloc(infptr->Fptr->tfield*sizeof(int)); outVarCols = malloc(outfptr->Fptr->tfield*sizeof(int)); fffvcl(infptr, &nInVarCols, inVarCols, status); fffvcl(outfptr, &nOutVarCols, outVarCols, status); if (nInVarCols != nOutVarCols) varColDiff=1; else { for (ii=0; iiFptr)->tableptr; for (icol=0; icol<(infptr->Fptr)->tfield; ++icol) { if (iVarCol < nInVarCols && inVarCols[iVarCol] == icol+1) { /* Copy from a variable length column */ ffgdesll(infptr, icol+1, ii, &hrepeat, &hoffset, status); /* If this is a bit column, hrepeat will be number of bits, not bytes. If it is a string column, hrepeat is the number of bytes, twidth is the max col width and can be ignored.*/ if (colptr->tdatatype == -TBIT) { nVarBytes = (hrepeat+7)/8; } else if (colptr->tdatatype == -TSTRING) { nVarBytes = hrepeat; } else { nVarBytes = hrepeat*colptr->twidth*sizeof(char); } inPos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + hoffset; outPos = (outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + (outfptr->Fptr)->heapsize; ffmbyt(infptr, inPos, REPORT_EOF, status); /* If this is not the last HDU in the file, then check if */ /* extending the heap would overwrite the following header. */ /* If so, then have to insert more blocks. */ if ( !((outfptr->Fptr)->lasthdu) ) { if (outPos+nVarBytes > (outfptr->Fptr)->headstart[(outfptr->Fptr)->curhdu+1]) { nNewBlocks = (long)(((outPos+nVarBytes - 1 - (outfptr->Fptr)->headstart[(outfptr->Fptr)-> curhdu+1]) / 2880) + 1); if (ffiblk(outfptr, nNewBlocks, 1, status) > 0) { ffpmsg("Failed to extend the size of the variable length heap (ffcprw)"); goto CLEANUP_RETURN; } } } if (nVarBytes) { if (nVarBytes > nVarAllocBytes) { /* Grow the copy buffer to accomodate the new maximum size. Note it is safe to call realloc() with null input pointer, which is equivalent to malloc(). */ unsigned char *varColBuff1 = (unsigned char *) realloc(varColBuff, nVarBytes); if (! varColBuff1) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory for variable column copy (ffcprw)"); goto CLEANUP_RETURN; } /* Record the new state */ varColBuff = varColBuff1; nVarAllocBytes = nVarBytes; } /* Copy date from input to output */ ffgbyt(infptr, nVarBytes, varColBuff, status); ffmbyt(outfptr, outPos, IGNORE_EOF, status); ffpbyt(outfptr, nVarBytes, varColBuff, status); } ffpdes(outfptr, icol+1, jj, hrepeat, (outfptr->Fptr)->heapsize, status); (outfptr->Fptr)->heapsize += nVarBytes; ++iVarCol; } ++colptr; } ++jj; } } else { /* copy the rows, 1 at a time */ n_good_rows = 0; for (ii = firstrow, i0 = 0; i0 < nrows; i0++, ii++) { /* Ignore rows with row_status[] == 0 */ if (row_status && !row_status[i0]) continue; fits_read_tblbytes (infptr, ii, 1, innaxis1, buffer, status); fits_write_tblbytes(outfptr, jj, 1, innaxis1, buffer, status); n_good_rows ++; jj++; } } outnaxis2 += n_good_rows; fits_update_key(outfptr, TLONGLONG, "NAXIS2", &outnaxis2, 0, status); CLEANUP_RETURN: free(buffer); free(inVarCols); free(outVarCols); if (varColBuff) free(varColBuff); return(*status); } /*--------------------------------------------------------------------------*/ int ffcpky(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int incol, /* I - input index number */ int outcol, /* I - output index number */ char *rootname, /* I - root name of the keyword to be copied */ int *status) /* IO - error status */ /* copy an indexed keyword from infptr to outfptr. */ { int tstatus = 0; char keyname[FLEN_KEYWORD]; char value[FLEN_VALUE], comment[FLEN_COMMENT], card[FLEN_CARD]; ffkeyn(rootname, incol, keyname, &tstatus); if (ffgkey(infptr, keyname, value, comment, &tstatus) <= 0) { ffkeyn(rootname, outcol, keyname, &tstatus); ffmkky(keyname, value, comment, card, status); ffprec(outfptr, card, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffdcol(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column to delete (1 = 1st) */ int *status) /* IO - error status */ /* Delete a column from a table. */ { int ii, tstatus; LONGLONG firstbyte, size, ndelete, nbytes, naxis1, naxis2, firstcol, delbyte, freespace; LONGLONG tbcol; long nblock, nspace; char keyname[FLEN_KEYWORD], comm[FLEN_COMMENT]; tcolumn *colptr, *nextcol; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg ("Can only delete column from TABLE or BINTABLE extension (ffdcol)"); return(*status = NOT_TABLE); } if (colnum < 1 || colnum > (fptr->Fptr)->tfield ) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); firstcol = colptr->tbcol; /* starting byte position of the column */ /* use column width to determine how many bytes to delete in each row */ if ((fptr->Fptr)->hdutype == ASCII_TBL) { delbyte = colptr->twidth; /* width of ASCII column */ if (colnum < (fptr->Fptr)->tfield) /* check for space between next column */ { nextcol = colptr + 1; nspace = (long) ((nextcol->tbcol) - (colptr->tbcol) - delbyte); if (nspace > 0) delbyte++; } else if (colnum > 1) /* check for space between last 2 columns */ { nextcol = colptr - 1; nspace = (long) ((colptr->tbcol) - (nextcol->tbcol) - (nextcol->twidth)); if (nspace > 0) { delbyte++; firstcol--; /* delete the leading space */ } } } else /* a binary table */ { if (colnum < (fptr->Fptr)->tfield) { nextcol = colptr + 1; delbyte = (nextcol->tbcol) - (colptr->tbcol); } else { delbyte = ((fptr->Fptr)->rowlength) - (colptr->tbcol); } } naxis1 = (fptr->Fptr)->rowlength; /* current width of the table */ naxis2 = (fptr->Fptr)->numrows; /* current size of table */ size = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ((LONGLONG)delbyte * naxis2) + ((size + 2879) / 2880) * 2880 - size; nblock = (long) (freespace / 2880); /* number of empty blocks to delete */ ffcdel(fptr, naxis1, naxis2, delbyte, firstcol, status); /* delete col */ /* absolute heap position */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; ndelete = (LONGLONG)delbyte * naxis2; /* size of shift */ /* shift heap up (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift up */ if (ffshft(fptr, firstbyte, nbytes, -ndelete, status) > 0) /* mv heap */ return(*status); } /* delete the empty blocks at the end of the HDU */ if (nblock > 0) ffdblk(fptr, nblock, status); /* update the heap starting address */ (fptr->Fptr)->heapstart -= ndelete; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (long)(fptr->Fptr)->heapstart, "&", &tstatus); if ((fptr->Fptr)->hdutype == ASCII_TBL) { /* adjust the TBCOL values of the remaining columns */ for (ii = 1; ii <= (fptr->Fptr)->tfield; ii++) { ffkeyn("TBCOL", ii, keyname, status); ffgkyjj(fptr, keyname, &tbcol, comm, status); if (tbcol > firstcol) { tbcol = tbcol - delbyte; ffmkyj(fptr, keyname, tbcol, "&", status); } } } /* update the mandatory keywords */ ffmkyj(fptr, "TFIELDS", ((fptr->Fptr)->tfield) - 1, "&", status); ffmkyj(fptr, "NAXIS1", naxis1 - delbyte, "&", status); /* delete the index keywords starting with 'T' associated with the deleted column and subtract 1 from index of all higher keywords */ ffkshf(fptr, colnum, (fptr->Fptr)->tfield, -1, status); ffrdef(fptr, status); /* initialize the new table structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcins(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of the table, in bytes */ LONGLONG naxis2, /* I - number of rows in the table */ LONGLONG ninsert, /* I - number of bytes to insert in each row */ LONGLONG bytepos, /* I - rel. position in row to insert bytes */ int *status) /* IO - error status */ /* Insert 'ninsert' bytes into each row of the table at position 'bytepos'. */ { unsigned char buffer[10000], cfill; LONGLONG newlen, fbyte, nbytes, irow, nseg, ii; if (*status > 0) return(*status); if (naxis2 == 0) return(*status); /* just return if there are 0 rows in the table */ /* select appropriate fill value */ if ((fptr->Fptr)->hdutype == ASCII_TBL) cfill = 32; /* ASCII tables use blank fill */ else cfill = 0; /* primary array and binary tables use zero fill */ newlen = naxis1 + ninsert; if (newlen <= 10000) { /******************************************************************* CASE #1: optimal case where whole new row fits in the work buffer *******************************************************************/ for (ii = 0; ii < ninsert; ii++) buffer[ii] = cfill; /* initialize buffer with fill value */ /* first move the trailing bytes (if any) in the last row */ fbyte = bytepos + 1; nbytes = naxis1 - bytepos; /* If the last row hasn't yet been accessed in full, it's possible that logfilesize hasn't been updated to account for it (by way of an ffldrc call). This could cause ffgtbb to return with an EOF error. To prevent this, we must increase logfilesize here. */ if ((fptr->Fptr)->logfilesize < (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart) { (fptr->Fptr)->logfilesize = (((fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + 2879)/2880)*2880; } ffgtbb(fptr, naxis2, fbyte, nbytes, &buffer[ninsert], status); (fptr->Fptr)->rowlength = newlen; /* new row length */ /* write the row (with leading fill bytes) in the new place */ nbytes += ninsert; ffptbb(fptr, naxis2, fbyte, nbytes, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig. value */ /* now move the rest of the rows */ for (irow = naxis2 - 1; irow > 0; irow--) { /* read the row to be shifted (work backwards thru the table) */ ffgtbb(fptr, irow, fbyte, naxis1, &buffer[ninsert], status); (fptr->Fptr)->rowlength = newlen; /* new row length */ /* write the row (with the leading fill bytes) in the new place */ ffptbb(fptr, irow, fbyte, newlen, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } } else { /***************************************************************** CASE #2: whole row doesn't fit in work buffer; move row in pieces ****************************************************************** first copy the data, then go back and write fill into the new column start by copying the trailing bytes (if any) in the last row. */ nbytes = naxis1 - bytepos; nseg = (nbytes + 9999) / 10000; fbyte = (nseg - 1) * 10000 + bytepos + 1; nbytes = naxis1 - fbyte + 1; for (ii = 0; ii < nseg; ii++) { ffgtbb(fptr, naxis2, fbyte, nbytes, buffer, status); (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, naxis2, fbyte + ninsert, nbytes, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ fbyte -= 10000; nbytes = 10000; } /* now move the rest of the rows */ nseg = (naxis1 + 9999) / 10000; for (irow = naxis2 - 1; irow > 0; irow--) { fbyte = (nseg - 1) * 10000 + bytepos + 1; nbytes = naxis1 - (nseg - 1) * 10000; for (ii = 0; ii < nseg; ii++) { /* read the row to be shifted (work backwards thru the table) */ ffgtbb(fptr, irow, fbyte, nbytes, buffer, status); (fptr->Fptr)->rowlength = newlen; /* new row length */ /* write the row in the new place */ ffptbb(fptr, irow, fbyte + ninsert, nbytes, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ fbyte -= 10000; nbytes = 10000; } } /* now write the fill values into the new column */ nbytes = minvalue(ninsert, 10000); memset(buffer, cfill, (size_t) nbytes); /* initialize with fill value */ nseg = (ninsert + 9999) / 10000; (fptr->Fptr)->rowlength = newlen; /* new row length */ for (irow = 1; irow <= naxis2; irow++) { fbyte = bytepos + 1; nbytes = ninsert - ((nseg - 1) * 10000); for (ii = 0; ii < nseg; ii++) { ffptbb(fptr, irow, fbyte, nbytes, buffer, status); fbyte += nbytes; nbytes = 10000; } } (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffcdel(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of the table, in bytes */ LONGLONG naxis2, /* I - number of rows in the table */ LONGLONG ndelete, /* I - number of bytes to delete in each row */ LONGLONG bytepos, /* I - rel. position in row to delete bytes */ int *status) /* IO - error status */ /* delete 'ndelete' bytes from each row of the table at position 'bytepos'. */ { unsigned char buffer[10000]; LONGLONG i1, i2, ii, irow, nseg; LONGLONG newlen, remain, nbytes; if (*status > 0) return(*status); if (naxis2 == 0) return(*status); /* just return if there are 0 rows in the table */ newlen = naxis1 - ndelete; if (newlen <= 10000) { /******************************************************************* CASE #1: optimal case where whole new row fits in the work buffer *******************************************************************/ i1 = bytepos + 1; i2 = i1 + ndelete; for (irow = 1; irow < naxis2; irow++) { ffgtbb(fptr, irow, i2, newlen, buffer, status); /* read row */ (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, irow, i1, newlen, buffer, status); /* write row */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } /* now do the last row */ remain = naxis1 - (bytepos + ndelete); if (remain > 0) { ffgtbb(fptr, naxis2, i2, remain, buffer, status); /* read row */ (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, naxis2, i1, remain, buffer, status); /* write row */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } } else { /***************************************************************** CASE #2: whole row doesn't fit in work buffer; move row in pieces ******************************************************************/ nseg = (newlen + 9999) / 10000; for (irow = 1; irow < naxis2; irow++) { i1 = bytepos + 1; i2 = i1 + ndelete; nbytes = newlen - (nseg - 1) * 10000; for (ii = 0; ii < nseg; ii++) { ffgtbb(fptr, irow, i2, nbytes, buffer, status); /* read bytes */ (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, irow, i1, nbytes, buffer, status); /* rewrite bytes */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ i1 += nbytes; i2 += nbytes; nbytes = 10000; } } /* now do the last row */ remain = naxis1 - (bytepos + ndelete); if (remain > 0) { nseg = (remain + 9999) / 10000; i1 = bytepos + 1; i2 = i1 + ndelete; nbytes = remain - (nseg - 1) * 10000; for (ii = 0; ii < nseg; ii++) { ffgtbb(fptr, naxis2, i2, nbytes, buffer, status); (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, naxis2, i1, nbytes, buffer, status); /* write row */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ i1 += nbytes; i2 += nbytes; nbytes = 10000; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffkshf(fitsfile *fptr, /* I - FITS file pointer */ int colmin, /* I - starting col. to be incremented; 1 = 1st */ int colmax, /* I - last column to be incremented */ int incre, /* I - shift index number by this amount */ int *status) /* IO - error status */ /* shift the index value on any existing column keywords This routine will modify the name of any keyword that begins with 'T' and has an index number in the range COLMIN - COLMAX, inclusive. if incre is positive, then the index values will be incremented. if incre is negative, then the kewords with index = COLMIN will be deleted and the index of higher numbered keywords will be decremented. */ { int nkeys, nmore, nrec, tstatus, i1; long ivalue; char rec[FLEN_CARD], q[FLEN_KEYWORD], newkey[FLEN_KEYWORD]; ffghsp(fptr, &nkeys, &nmore, status); /* get number of keywords */ /* go thru header starting with the 9th keyword looking for 'TxxxxNNN' */ for (nrec = 9; nrec <= nkeys; nrec++) { ffgrec(fptr, nrec, rec, status); if (rec[0] == 'T') { i1 = 0; strncpy(q, &rec[1], 4); if (!strncmp(q, "BCOL", 4) || !strncmp(q, "FORM", 4) || !strncmp(q, "TYPE", 4) || !strncmp(q, "SCAL", 4) || !strncmp(q, "UNIT", 4) || !strncmp(q, "NULL", 4) || !strncmp(q, "ZERO", 4) || !strncmp(q, "DISP", 4) || !strncmp(q, "LMIN", 4) || !strncmp(q, "LMAX", 4) || !strncmp(q, "DMIN", 4) || !strncmp(q, "DMAX", 4) || !strncmp(q, "CTYP", 4) || !strncmp(q, "CRPX", 4) || !strncmp(q, "CRVL", 4) || !strncmp(q, "CDLT", 4) || !strncmp(q, "CROT", 4) || !strncmp(q, "CUNI", 4) ) i1 = 5; else if (!strncmp(rec, "TDIM", 4) ) i1 = 4; if (i1) { /* try reading the index number suffix */ q[0] = '\0'; strncat(q, &rec[i1], 8 - i1); tstatus = 0; ffc2ii(q, &ivalue, &tstatus); if (tstatus == 0 && ivalue >= colmin && ivalue <= colmax) { if (incre <= 0 && ivalue == colmin) { ffdrec(fptr, nrec, status); /* delete keyword */ nkeys = nkeys - 1; nrec = nrec - 1; } else { ivalue = ivalue + incre; q[0] = '\0'; strncat(q, rec, i1); ffkeyn(q, ivalue, newkey, status); /* NOTE: because of null termination, it is not equivalent to use strcpy() for the same calls */ strncpy(rec, " ", 8); /* erase old keyword name */ i1 = strlen(newkey); strncpy(rec, newkey, i1); /* overwrite new keyword name */ ffmrec(fptr, nrec, rec, status); /* modify the record */ } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffvcl(fitsfile *fptr, /* I - FITS file pointer */ int *nvarcols, /* O - Number of variable length columns found */ int *colnums, /* O - 1-based variable column positions */ int *status) /* IO - error status */ { /* Internal function to identify which columns in a binary table are variable length. The colnums array will be filled with nvarcols elements - the 1-based numbers of all variable length columns in the table. This ASSUMES calling function has passed in a colnums array large enough to hold these (colnums==NULL also allowed). */ int tfields=0,icol; tcolumn *colptr=0; *nvarcols = 0; if (*status > 0) return(*status); if ((fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg("Var-length column search can only be performed on Binary tables (fffvcl)"); return(*status = NOT_BTABLE); } if ((fptr->Fptr)->tableptr) { colptr = (fptr->Fptr)->tableptr; tfields = (fptr->Fptr)->tfield; for (icol=0; icoltdatatype < 0) { if (colnums) colnums[*nvarcols] = icol + 1; *nvarcols += 1; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffshft(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstbyte, /* I - position of first byte in block to shift */ LONGLONG nbytes, /* I - size of block of bytes to shift */ LONGLONG nshift, /* I - size of shift in bytes (+ or -) */ int *status) /* IO - error status */ /* Shift block of bytes by nshift bytes (positive or negative). A positive nshift value moves the block down further in the file, while a negative value shifts the block towards the beginning of the file. */ { #define shftbuffsize 100000 long ntomov; LONGLONG ptr, ntodo; char buffer[shftbuffsize]; if (*status > 0) return(*status); ntodo = nbytes; /* total number of bytes to shift */ if (nshift > 0) /* start at the end of the block and work backwards */ ptr = firstbyte + nbytes; else /* start at the beginning of the block working forwards */ ptr = firstbyte; while (ntodo) { /* number of bytes to move at one time */ ntomov = (long) (minvalue(ntodo, shftbuffsize)); if (nshift > 0) /* if moving block down ... */ ptr -= ntomov; /* move to position and read the bytes to be moved */ ffmbyt(fptr, ptr, REPORT_EOF, status); ffgbyt(fptr, ntomov, buffer, status); /* move by shift amount and write the bytes */ ffmbyt(fptr, ptr + nshift, IGNORE_EOF, status); if (ffpbyt(fptr, ntomov, buffer, status) > 0) { ffpmsg("Error while shifting block (ffshft)"); return(*status); } ntodo -= ntomov; if (nshift < 0) /* if moving block up ... */ ptr += ntomov; } /* now overwrite the old data with fill */ if ((fptr->Fptr)->hdutype == ASCII_TBL) memset(buffer, 32, shftbuffsize); /* fill ASCII tables with spaces */ else memset(buffer, 0, shftbuffsize); /* fill other HDUs with zeros */ if (nshift < 0) { ntodo = -nshift; /* point to the end of the shifted block */ ptr = firstbyte + nbytes + nshift; } else { ntodo = nshift; /* point to original beginning of the block */ ptr = firstbyte; } ffmbyt(fptr, ptr, REPORT_EOF, status); while (ntodo) { ntomov = (long) (minvalue(ntodo, shftbuffsize)); ffpbyt(fptr, ntomov, buffer, status); ntodo -= ntomov; } return(*status); } cfitsio-4.3.1/ricecomp.c0000644000225700000360000010542513640736632014433 0ustar cagordonlhea/* The following code was written by Richard White at STScI and made available for use in CFITSIO in July 1999. These routines were originally contained in 2 source files: rcomp.c and rdecomp.c, and the 'include' file now called ricecomp.h was originally called buffer.h. Note that beginning with CFITSIO v3.08, EOB checking was removed to improve speed, and so now the input compressed bytes buffers must have been allocated big enough so that they will never be overflowed. A simple rule of thumb that guarantees the buffer will be large enough is to make it 1% larger than the size of the input array of pixels that are being compressed. */ /*----------------------------------------------------------*/ /* */ /* START OF SOURCE FILE ORIGINALLY CALLED rcomp.c */ /* */ /*----------------------------------------------------------*/ /* @(#) rcomp.c 1.5 99/03/01 12:40:27 */ /* rcomp.c Compress image line using * (1) Difference of adjacent pixels * (2) Rice algorithm coding * * Returns number of bytes written to code buffer or * -1 on failure */ #include #include #include /* * nonzero_count is lookup table giving number of bits in 8-bit values not including * leading zeros used in fits_rdecomp, fits_rdecomp_short and fits_rdecomp_byte */ static const int nonzero_count[256] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; typedef unsigned char Buffer_t; typedef struct { int bitbuffer; /* bit buffer */ int bits_to_go; /* bits to go in buffer */ Buffer_t *start; /* start of buffer */ Buffer_t *current; /* current position in buffer */ Buffer_t *end; /* end of buffer */ } Buffer; #define putcbuf(c,mf) ((*(mf->current)++ = c), 0) #include "fitsio2.h" static void start_outputing_bits(Buffer *buffer); static int done_outputing_bits(Buffer *buffer); static int output_nbits(Buffer *buffer, int bits, int n); /* only used for diagnoistics static int case1, case2, case3; int fits_get_case(int *c1, int*c2, int*c3) { *c1 = case1; *c2 = case2; *c3 = case3; return(0); } */ /* this routine used to be called 'rcomp' (WDP) */ /*---------------------------------------------------------------------------*/ int fits_rcomp(int a[], /* input array */ int nx, /* number of input pixels */ unsigned char *c, /* output buffer */ int clen, /* max length of output */ int nblock) /* coding block size */ { Buffer bufmem, *buffer = &bufmem; /* int bsize; */ int i, j, thisblock; int lastpix, nextpix, pdiff; int v, fs, fsmask, top, fsmax, fsbits, bbits; int lbitbuffer, lbits_to_go; unsigned int psum; double pixelsum, dpsum; unsigned int *diff; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 4; */ /* nblock = 32; now an input parameter*/ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return(-1); } */ /* move out of switch block, to tweak performance */ fsbits = 5; fsmax = 25; bbits = 1<start = c; buffer->current = c; buffer->end = c+clen; buffer->bits_to_go = 8; /* * array for differences mapped to non-negative values */ diff = (unsigned int *) malloc(nblock*sizeof(unsigned int)); if (diff == (unsigned int *) NULL) { ffpmsg("fits_rcomp: insufficient memory"); return(-1); } /* * Code in blocks of nblock pixels */ start_outputing_bits(buffer); /* write out first int value to the first 4 bytes of the buffer */ if (output_nbits(buffer, a[0], 32) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } lastpix = a[0]; /* the first difference will always be zero */ thisblock = nblock; for (i=0; i> 1; for (fs = 0; psum>0; fs++) psum >>= 1; /* * write the codes * fsbits ID bits used to indicate split level */ if (fs >= fsmax) { /* Special high entropy case when FS >= fsmax * Just write pixel difference values directly, no Rice coding at all. */ if (output_nbits(buffer, fsmax+1, fsbits) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } for (j=0; jbitbuffer; lbits_to_go = buffer->bits_to_go; for (j=0; j> fs; /* * top is coded by top zeros + 1 */ if (lbits_to_go >= top+1) { lbitbuffer <<= top+1; lbitbuffer |= 1; lbits_to_go -= top+1; } else { lbitbuffer <<= lbits_to_go; putcbuf(lbitbuffer & 0xff,buffer); for (top -= lbits_to_go; top>=8; top -= 8) { putcbuf(0, buffer); } lbitbuffer = 1; lbits_to_go = 7-top; } /* * bottom FS bits are written without coding * code is output_nbits, moved into this routine to reduce overheads * This code potentially breaks if FS>24, so I am limiting * FS to 24 by choice of FSMAX above. */ if (fs > 0) { lbitbuffer <<= fs; lbitbuffer |= v & fsmask; lbits_to_go -= fs; while (lbits_to_go <= 0) { putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer); lbits_to_go += 8; } } } /* check if overflowed output buffer */ if (buffer->current > buffer->end) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } buffer->bitbuffer = lbitbuffer; buffer->bits_to_go = lbits_to_go; } } done_outputing_bits(buffer); free(diff); /* * return number of bytes used */ return(buffer->current - buffer->start); } /*---------------------------------------------------------------------------*/ int fits_rcomp_short( short a[], /* input array */ int nx, /* number of input pixels */ unsigned char *c, /* output buffer */ int clen, /* max length of output */ int nblock) /* coding block size */ { Buffer bufmem, *buffer = &bufmem; /* int bsize; */ int i, j, thisblock; /* NOTE: in principle, the following 2 variable could be declared as 'short' but in fact the code runs faster (on 32-bit Linux at least) as 'int' */ int lastpix, nextpix; /* int pdiff; */ short pdiff; int v, fs, fsmask, top, fsmax, fsbits, bbits; int lbitbuffer, lbits_to_go; /* unsigned int psum; */ unsigned short psum; double pixelsum, dpsum; unsigned int *diff; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 2; */ /* nblock = 32; now an input parameter */ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return(-1); } */ /* move these out of switch block to further tweak performance */ fsbits = 4; fsmax = 14; bbits = 1<start = c; buffer->current = c; buffer->end = c+clen; buffer->bits_to_go = 8; /* * array for differences mapped to non-negative values */ diff = (unsigned int *) malloc(nblock*sizeof(unsigned int)); if (diff == (unsigned int *) NULL) { ffpmsg("fits_rcomp: insufficient memory"); return(-1); } /* * Code in blocks of nblock pixels */ start_outputing_bits(buffer); /* write out first short value to the first 2 bytes of the buffer */ if (output_nbits(buffer, a[0], 16) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } lastpix = a[0]; /* the first difference will always be zero */ thisblock = nblock; for (i=0; i> 1; */ psum = ((unsigned short) dpsum ) >> 1; for (fs = 0; psum>0; fs++) psum >>= 1; /* * write the codes * fsbits ID bits used to indicate split level */ if (fs >= fsmax) { /* case3++; */ /* Special high entropy case when FS >= fsmax * Just write pixel difference values directly, no Rice coding at all. */ if (output_nbits(buffer, fsmax+1, fsbits) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } for (j=0; jbitbuffer; lbits_to_go = buffer->bits_to_go; for (j=0; j> fs; /* * top is coded by top zeros + 1 */ if (lbits_to_go >= top+1) { lbitbuffer <<= top+1; lbitbuffer |= 1; lbits_to_go -= top+1; } else { lbitbuffer <<= lbits_to_go; putcbuf(lbitbuffer & 0xff,buffer); for (top -= lbits_to_go; top>=8; top -= 8) { putcbuf(0, buffer); } lbitbuffer = 1; lbits_to_go = 7-top; } /* * bottom FS bits are written without coding * code is output_nbits, moved into this routine to reduce overheads * This code potentially breaks if FS>24, so I am limiting * FS to 24 by choice of FSMAX above. */ if (fs > 0) { lbitbuffer <<= fs; lbitbuffer |= v & fsmask; lbits_to_go -= fs; while (lbits_to_go <= 0) { putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer); lbits_to_go += 8; } } } /* check if overflowed output buffer */ if (buffer->current > buffer->end) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } buffer->bitbuffer = lbitbuffer; buffer->bits_to_go = lbits_to_go; } } done_outputing_bits(buffer); free(diff); /* * return number of bytes used */ return(buffer->current - buffer->start); } /*---------------------------------------------------------------------------*/ int fits_rcomp_byte( signed char a[], /* input array */ int nx, /* number of input pixels */ unsigned char *c, /* output buffer */ int clen, /* max length of output */ int nblock) /* coding block size */ { Buffer bufmem, *buffer = &bufmem; /* int bsize; */ int i, j, thisblock; /* NOTE: in principle, the following 2 variable could be declared as 'short' but in fact the code runs faster (on 32-bit Linux at least) as 'int' */ int lastpix, nextpix; /* int pdiff; */ signed char pdiff; int v, fs, fsmask, top, fsmax, fsbits, bbits; int lbitbuffer, lbits_to_go; /* unsigned int psum; */ unsigned char psum; double pixelsum, dpsum; unsigned int *diff; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 1; */ /* nblock = 32; now an input parameter */ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return(-1); } */ /* move these out of switch block to further tweak performance */ fsbits = 3; fsmax = 6; bbits = 1<start = c; buffer->current = c; buffer->end = c+clen; buffer->bits_to_go = 8; /* * array for differences mapped to non-negative values */ diff = (unsigned int *) malloc(nblock*sizeof(unsigned int)); if (diff == (unsigned int *) NULL) { ffpmsg("fits_rcomp: insufficient memory"); return(-1); } /* * Code in blocks of nblock pixels */ start_outputing_bits(buffer); /* write out first byte value to the first byte of the buffer */ if (output_nbits(buffer, a[0], 8) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } lastpix = a[0]; /* the first difference will always be zero */ thisblock = nblock; for (i=0; i> 1; */ psum = ((unsigned char) dpsum ) >> 1; for (fs = 0; psum>0; fs++) psum >>= 1; /* * write the codes * fsbits ID bits used to indicate split level */ if (fs >= fsmax) { /* Special high entropy case when FS >= fsmax * Just write pixel difference values directly, no Rice coding at all. */ if (output_nbits(buffer, fsmax+1, fsbits) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } for (j=0; jbitbuffer; lbits_to_go = buffer->bits_to_go; for (j=0; j> fs; /* * top is coded by top zeros + 1 */ if (lbits_to_go >= top+1) { lbitbuffer <<= top+1; lbitbuffer |= 1; lbits_to_go -= top+1; } else { lbitbuffer <<= lbits_to_go; putcbuf(lbitbuffer & 0xff,buffer); for (top -= lbits_to_go; top>=8; top -= 8) { putcbuf(0, buffer); } lbitbuffer = 1; lbits_to_go = 7-top; } /* * bottom FS bits are written without coding * code is output_nbits, moved into this routine to reduce overheads * This code potentially breaks if FS>24, so I am limiting * FS to 24 by choice of FSMAX above. */ if (fs > 0) { lbitbuffer <<= fs; lbitbuffer |= v & fsmask; lbits_to_go -= fs; while (lbits_to_go <= 0) { putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer); lbits_to_go += 8; } } } /* check if overflowed output buffer */ if (buffer->current > buffer->end) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } buffer->bitbuffer = lbitbuffer; buffer->bits_to_go = lbits_to_go; } } done_outputing_bits(buffer); free(diff); /* * return number of bytes used */ return(buffer->current - buffer->start); } /*---------------------------------------------------------------------------*/ /* bit_output.c * * Bit output routines * Procedures return zero on success, EOF on end-of-buffer * * Programmer: R. White Date: 20 July 1998 */ /* Initialize for bit output */ static void start_outputing_bits(Buffer *buffer) { /* * Buffer is empty to start with */ buffer->bitbuffer = 0; buffer->bits_to_go = 8; } /*---------------------------------------------------------------------------*/ /* Output N bits (N must be <= 32) */ static int output_nbits(Buffer *buffer, int bits, int n) { /* local copies */ int lbitbuffer; int lbits_to_go; /* AND mask for the right-most n bits */ static unsigned int mask[33] = {0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff}; /* * insert bits at end of bitbuffer */ lbitbuffer = buffer->bitbuffer; lbits_to_go = buffer->bits_to_go; if (lbits_to_go+n > 32) { /* * special case for large n: put out the top lbits_to_go bits first * note that 0 < lbits_to_go <= 8 */ lbitbuffer <<= lbits_to_go; /* lbitbuffer |= (bits>>(n-lbits_to_go)) & ((1<>(n-lbits_to_go)) & *(mask+lbits_to_go); putcbuf(lbitbuffer & 0xff,buffer); n -= lbits_to_go; lbits_to_go = 8; } lbitbuffer <<= n; /* lbitbuffer |= ( bits & ((1<>(-lbits_to_go)) & 0xff,buffer); lbits_to_go += 8; } buffer->bitbuffer = lbitbuffer; buffer->bits_to_go = lbits_to_go; return(0); } /*---------------------------------------------------------------------------*/ /* Flush out the last bits */ static int done_outputing_bits(Buffer *buffer) { if(buffer->bits_to_go < 8) { putcbuf(buffer->bitbuffer<bits_to_go,buffer); /* if (putcbuf(buffer->bitbuffer<bits_to_go,buffer) == EOF) return(EOF); */ } return(0); } /*---------------------------------------------------------------------------*/ /*----------------------------------------------------------*/ /* */ /* START OF SOURCE FILE ORIGINALLY CALLED rdecomp.c */ /* */ /*----------------------------------------------------------*/ /* @(#) rdecomp.c 1.4 99/03/01 12:38:41 */ /* rdecomp.c Decompress image line using * (1) Difference of adjacent pixels * (2) Rice algorithm coding * * Returns 0 on success or 1 on failure */ /* moved these 'includes' to the beginning of the file (WDP) #include #include */ /*---------------------------------------------------------------------------*/ /* this routine used to be called 'rdecomp' (WDP) */ int fits_rdecomp (unsigned char *c, /* input buffer */ int clen, /* length of input */ unsigned int array[], /* output array */ int nx, /* number of output pixels */ int nblock) /* coding block size */ { /* int bsize; */ int i, k, imax; int nbits, nzero, fs; unsigned char *cend, bytevalue; unsigned int b, diff, lastpix; int fsmax, fsbits, bbits; extern const int nonzero_count[]; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 4; */ /* nblock = 32; now an input parameter */ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return 1; } */ /* move out of switch block, to tweak performance */ fsbits = 5; fsmax = 25; bbits = 1<> nbits) - 1; b &= (1< nx) imax = nx; if (fs<0) { /* low-entropy case, all zero differences */ for ( ; i= 0; k -= 8) { b = *c++; diff |= b<0) { b = *c++; diff |= b>>(-k); b &= (1<>1; } else { diff = ~(diff>>1); } array[i] = diff+lastpix; lastpix = array[i]; } } else { /* normal case, Rice coding */ for ( ; i>nbits); b &= (1<>1; } else { diff = ~(diff>>1); } array[i] = diff+lastpix; lastpix = array[i]; } } if (c > cend) { ffpmsg("decompression error: hit end of compressed byte stream"); return 1; } } if (c < cend) { ffpmsg("decompression warning: unused bytes at end of compressed buffer"); } return 0; } /*---------------------------------------------------------------------------*/ /* this routine used to be called 'rdecomp' (WDP) */ int fits_rdecomp_short (unsigned char *c, /* input buffer */ int clen, /* length of input */ unsigned short array[], /* output array */ int nx, /* number of output pixels */ int nblock) /* coding block size */ { int i, imax; /* int bsize; */ int k; int nbits, nzero, fs; unsigned char *cend, bytevalue; unsigned int b, diff, lastpix; int fsmax, fsbits, bbits; extern const int nonzero_count[]; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 2; */ /* nblock = 32; now an input parameter */ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return 1; } */ /* move out of switch block, to tweak performance */ fsbits = 4; fsmax = 14; bbits = 1<> nbits) - 1; b &= (1< nx) imax = nx; if (fs<0) { /* low-entropy case, all zero differences */ for ( ; i= 0; k -= 8) { b = *c++; diff |= b<0) { b = *c++; diff |= b>>(-k); b &= (1<>1; } else { diff = ~(diff>>1); } array[i] = diff+lastpix; lastpix = array[i]; } } else { /* normal case, Rice coding */ for ( ; i>nbits); b &= (1<>1; } else { diff = ~(diff>>1); } array[i] = diff+lastpix; lastpix = array[i]; } } if (c > cend) { ffpmsg("decompression error: hit end of compressed byte stream"); return 1; } } if (c < cend) { ffpmsg("decompression warning: unused bytes at end of compressed buffer"); } return 0; } /*---------------------------------------------------------------------------*/ /* this routine used to be called 'rdecomp' (WDP) */ int fits_rdecomp_byte (unsigned char *c, /* input buffer */ int clen, /* length of input */ unsigned char array[], /* output array */ int nx, /* number of output pixels */ int nblock) /* coding block size */ { int i, imax; /* int bsize; */ int k; int nbits, nzero, fs; unsigned char *cend; unsigned int b, diff, lastpix; int fsmax, fsbits, bbits; extern const int nonzero_count[]; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 1; */ /* nblock = 32; now an input parameter */ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return 1; } */ /* move out of switch block, to tweak performance */ fsbits = 3; fsmax = 6; bbits = 1<> nbits) - 1; b &= (1< nx) imax = nx; if (fs<0) { /* low-entropy case, all zero differences */ for ( ; i= 0; k -= 8) { b = *c++; diff |= b<0) { b = *c++; diff |= b>>(-k); b &= (1<>1; } else { diff = ~(diff>>1); } array[i] = diff+lastpix; lastpix = array[i]; } } else { /* normal case, Rice coding */ for ( ; i>nbits); b &= (1<>1; } else { diff = ~(diff>>1); } array[i] = diff+lastpix; lastpix = array[i]; } } if (c > cend) { ffpmsg("decompression error: hit end of compressed byte stream"); return 1; } } if (c < cend) { ffpmsg("decompression warning: unused bytes at end of compressed buffer"); } return 0; } cfitsio-4.3.1/vmsieee.c0000644000225700000360000000730613472024437014262 0ustar cagordonlhea#include #include unsigned long CVT$CONVERT_FLOAT(); /* IEEVPAKR -- Pack a native floating point vector into an IEEE one. */ void ieevpr (unsigned int *native, unsigned int *ieee, int *nelem) { unsigned long status; unsigned long options; unsigned int *unanval; int nanval = -1; int i,n; unanval = (unsigned int *) &nanval; options = CVT$M_BIG_ENDIAN; n = *nelem; status = CVT$_NORMAL; for (i = 0; i < n ; i++) { status = CVT$CONVERT_FLOAT (&native[i], CVT$K_VAX_F, &ieee[i], CVT$K_IEEE_S, options); if (status != CVT$_NORMAL) { ieee[i] = *unanval; } } } /* IEEVPAKD -- Pack a native double floating point vector into an IEEE one. */ void ieevpd (unsigned long *native, unsigned long *ieee, int *nelem) { unsigned long status; unsigned long options; unsigned long *unanval; long nanval = -1; int i,n; unanval = (unsigned long *) &nanval; options = CVT$M_BIG_ENDIAN; n = *nelem * 2; status = CVT$_NORMAL; for (i = 0; i < n ; i=i+2) { status = CVT$CONVERT_FLOAT (&native[i], CVT$K_VAX_D, &ieee[i], CVT$K_IEEE_T, options); if (status != CVT$_NORMAL) { ieee[i] = *unanval; ieee[i+1] = *unanval; } } } /* IEEVUPKR -- Unpack an ieee vector into native single floating point vector. */ void ieevur (unsigned int *ieee, unsigned int *native, int *nelem) { unsigned long status; unsigned long options; unsigned int *unanval; int nanval = -1; int j,n; unanval = (unsigned int *) &nanval; options = CVT$M_ERR_UNDERFLOW+CVT$M_BIG_ENDIAN; n = *nelem; status = CVT$_NORMAL; for (j = 0; j < n ; j++) { status = CVT$CONVERT_FLOAT (&ieee[j], CVT$K_IEEE_S, &native[j], CVT$K_VAX_F, options); if (status != CVT$_NORMAL) switch(status) { case CVT$_INVVAL: case CVT$_NEGINF: case CVT$_OVERFLOW: case CVT$_POSINF: native[j] = *unanval; break; default: native[j] = 0; } } } /* IEEVUPKD -- Unpack an ieee vector into native double floating point vector. */ void ieevud (unsigned long *ieee, unsigned long *native, int *nelem) { unsigned long status; unsigned long options; unsigned long *unanval; long nanval = -1; int j,n; unanval = (unsigned long *) &nanval; options = CVT$M_BIG_ENDIAN + CVT$M_ERR_UNDERFLOW; n = *nelem * 2; status = CVT$_NORMAL; for (j = 0; j < n ; j=j+2) { status = CVT$CONVERT_FLOAT (&ieee[j], CVT$K_IEEE_T, &native[j], CVT$K_VAX_D, options); if (status != CVT$_NORMAL) switch(status) { case CVT$_INVVAL: case CVT$_NEGINF: case CVT$_OVERFLOW: case CVT$_POSINF: native[j] = *unanval; native[j+1] = *unanval; break; default: native[j] = 0; native[j+1] = 0; } } } cfitsio-4.3.1/iter_a.fit0000644000225700000360000037510013472024437014430 0ustar cagordonlheaSIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT Contact the NASA Science Office of Standards and Technology for the COMMENT FITS Definition document #100 and other FITS information. HISTORY TASK:FMERGE on file ratefile.fits HISTORY fmerge3.1c at 29/12/97 16:1:37. HISTORY TASK:FMERGE on file m1.fits HISTORY fmerge3.1c at 29/12/97 16:2:30. HISTORY TASK:FMERGE on file m3.fits HISTORY fmerge3.1c at 29/12/97 16:3:38. HISTORY TASK:FMERGE on file m5.fits HISTORY fmerge3.1c at 29/12/97 16:4:15. HISTORY TASK:FMERGE on file m7.fits HISTORY fmerge3.1c at 29/12/97 16:5:1.0 HISTORY TASK:FMERGE on file m9.fits HISTORY fmerge3.1c at 29/12/97 16:6:48. END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 12 / width of table in bytes NAXIS2 = 10000 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 3 / number of fields in each row TTYPE1 = 'Counts ' / label for field 1 TFORM1 = 'J ' / data format of field: 4-byte INTEGER TTYPE2 = 'Time ' / label for field 2 TFORM2 = 'E ' / data format of field: 4-byte REAL TTYPE3 = 'Rate ' / label for field 3 TFORM3 = 'E ' / data format of field: 4-byte REAL EXTNAME = 'rate ' / name of this binary table extension DEADTIME= 1.0 HISTORY This FITS file was created by the FCREATE task. HISTORY fcreate3.1 at 29/12/97 HISTORY File modified by user 'pence' with fv on 97-12-29T15:45:06 HISTORY File modified by user 'pence' with fv on 97-12-29T15:54:30 LIVETIME= 30554.5 / total integration time HISTORY TASK:FMERGE copied 26924 rows from file ratefile.fits HISTORY TASK:FMERGE appended 26924 rows from file r2.fits HISTORY TASK:FMERGE copied 53848 rows from file m1.fits HISTORY TASK:FMERGE appended 53848 rows from file m2.fits HISTORY TASK:FMERGE copied 107696 rows from file m3.fits HISTORY TASK:FMERGE appended 107696 rows from file m4.fits HISTORY TASK:FMERGE copied 215392 rows from file m5.fits HISTORY TASK:FMERGE appended 215392 rows from file m6.fits HISTORY TASK:FMERGE copied 430784 rows from file m7.fits HISTORY TASK:FMERGE appended 430784 rows from file m8.fits HISTORY TASK:FMERGE copied 861568 rows from file m9.fits HISTORY TASK:FMERGE appended 861568 rows from file m10.fits HISTORY File modified by user 'pence' with fv on 97-12-30T10:44:37 HISTORY File modified by user 'pence' with fv on 97-12-30T10:51:44 HISTORY ftabcopy V4.0a copied columns from ratefile.fits HISTORY ftabcopy V4.0a at 5/1/98 23:10:24 END ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À ?€A @@°?€@ cfitsio-4.3.1/getkey.c0000644000225700000360000040553414456514035014123 0ustar cagordonlhea/* This file, getkey.c, contains routines that read keywords from */ /* a FITS header. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include /* stddef.h is apparently needed to define size_t */ #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffghsp(fitsfile *fptr, /* I - FITS file pointer */ int *nexist, /* O - number of existing keywords in header */ int *nmore, /* O - how many more keywords will fit */ int *status) /* IO - error status */ /* returns the number of existing keywords (not counting the END keyword) and the number of more keyword that will fit in the current header without having to insert more FITS blocks. */ { if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (nexist) *nexist = (int) (( ((fptr->Fptr)->headend) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80); if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if (nmore) *nmore = -1; /* data not written yet, so room for any keywords */ } else { /* calculate space available between the data and the END card */ if (nmore) *nmore = (int) (((fptr->Fptr)->datastart - (fptr->Fptr)->headend) / 80 - 1); } return(*status); } /*--------------------------------------------------------------------------*/ int ffghps(fitsfile *fptr, /* I - FITS file pointer */ int *nexist, /* O - number of existing keywords in header */ int *position, /* O - position of next keyword to be read */ int *status) /* IO - error status */ /* return the number of existing keywords and the position of the next keyword that will be read. */ { if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (nexist) *nexist = (int) (( ((fptr->Fptr)->headend) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80); if (position) *position = (int) (( ((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80 + 1); return(*status); } /*--------------------------------------------------------------------------*/ int ffnchk(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* function returns the position of the first null character (ASCII 0), if any, in the current header. Null characters are illegal, but the other CFITSIO routines that read the header will not detect this error, because the null gets interpreted as a normal end of string character. */ { long ii, nblock; LONGLONG bytepos; int length, nullpos; char block[2881]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { return(0); /* Don't check a file that is just being created. */ /* It cannot contain nulls since CFITSIO wrote it. */ } else { /* calculate number of blocks in the header */ nblock = (long) (( (fptr->Fptr)->datastart - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) / 2880); } bytepos = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; ffmbyt(fptr, bytepos, REPORT_EOF, status); /* move to read pos. */ block[2880] = '\0'; for (ii = 0; ii < nblock; ii++) { if (ffgbyt(fptr, 2880, block, status) > 0) return(0); /* read error of some sort */ length = strlen(block); if (length != 2880) { nullpos = (ii * 2880) + length + 1; return(nullpos); } } return(0); } /*--------------------------------------------------------------------------*/ int ffmaky(fitsfile *fptr, /* I - FITS file pointer */ int nrec, /* I - one-based keyword number to move to */ int *status) /* IO - error status */ { /* move pointer to the specified absolute keyword position. E.g. this keyword will then be read by the next call to ffgnky. */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] + ( (nrec - 1) * 80); return(*status); } /*--------------------------------------------------------------------------*/ int ffmrky(fitsfile *fptr, /* I - FITS file pointer */ int nmove, /* I - relative number of keywords to move */ int *status) /* IO - error status */ { /* move pointer to the specified keyword position relative to the current position. E.g. this keyword will then be read by the next call to ffgnky. */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->nextkey += (nmove * 80); return(*status); } /*--------------------------------------------------------------------------*/ int ffgnky(fitsfile *fptr, /* I - FITS file pointer */ char *card, /* O - card string */ int *status) /* IO - error status */ /* read the next keyword from the header - used internally by cfitsio */ { int jj, nrec; LONGLONG bytepos, endhead; char message[FLEN_ERRMSG]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); card[0] = '\0'; /* make sure card is terminated, even affer read error */ /* Check that nextkey points to a legal keyword position. Note that headend is the current end of the header, i.e., the position where a new keyword would be appended, however, if there are more than 1 FITS block worth of blank keywords at the end of the header (36 keywords per 2880 byte block) then the actual physical END card must be located at a starting position which is just 2880 bytes prior to the start of the data unit. */ bytepos = (fptr->Fptr)->nextkey; endhead = maxvalue( ((fptr->Fptr)->headend), ((fptr->Fptr)->datastart - 2880) ); /* nextkey must be < endhead and > than headstart */ if (bytepos > endhead || bytepos < (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) { nrec= (int) ((bytepos - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) / 80 + 1); snprintf(message, FLEN_ERRMSG,"Cannot get keyword number %d. It does not exist.", nrec); ffpmsg(message); return(*status = KEY_OUT_BOUNDS); } ffmbyt(fptr, bytepos, REPORT_EOF, status); /* move to read pos. */ card[80] = '\0'; /* make sure card is terminate, even if ffgbyt fails */ if (ffgbyt(fptr, 80, card, status) <= 0) { (fptr->Fptr)->nextkey += 80; /* increment pointer to next keyword */ /* strip off trailing blanks with terminated string */ jj = 79; while (jj >= 0 && card[jj] == ' ') jj--; card[jj + 1] = '\0'; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgnxk( fitsfile *fptr, /* I - FITS file pointer */ char **inclist, /* I - list of included keyword names */ int ninc, /* I - number of names in inclist */ char **exclist, /* I - list of excluded keyword names */ int nexc, /* I - number of names in exclist */ char *card, /* O - first matching keyword */ int *status) /* IO - error status */ /* Return the next keyword that matches one of the names in inclist but does not match any of the names in exclist. The search goes from the current position to the end of the header, only. Wild card characters may be used in the name lists ('*', '?' and '#'). */ { int casesn, match, exact, namelen; long ii, jj; char keybuf[FLEN_CARD], keyname[FLEN_KEYWORD]; card[0] = '\0'; if (*status > 0) return(*status); casesn = FALSE; /* get next card, and return with an error if hit end of header */ while( ffgcrd(fptr, "*", keybuf, status) <= 0) { ffgknm(keybuf, keyname, &namelen, status); /* get the keyword name */ /* does keyword match any names in the include list? */ for (ii = 0; ii < ninc; ii++) { ffcmps(inclist[ii], keyname, casesn, &match, &exact); if (match) { /* does keyword match any names in the exclusion list? */ jj = -1; while ( ++jj < nexc ) { ffcmps(exclist[jj], keyname, casesn, &match, &exact); if (match) break; } if (jj >= nexc) { /* not in exclusion list, so return this keyword */ strcat(card, keybuf); return(*status); } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgky( fitsfile *fptr, /* I - FITS file pointer */ int datatype, /* I - datatype of the value */ const char *keyname, /* I - name of keyword to read */ void *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the keyword value and comment from the FITS header. Reads a keyword value with the datatype specified by the 2nd argument. */ { LONGLONG longval; ULONGLONG ulongval; double doubleval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (datatype == TSTRING) { ffgkys(fptr, keyname, (char *) value, comm, status); } else if (datatype == TBYTE) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > UCHAR_MAX || longval < 0) *status = NUM_OVERFLOW; else *(unsigned char *) value = (unsigned char) longval; } } else if (datatype == TSBYTE) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > 127 || longval < -128) *status = NUM_OVERFLOW; else *(signed char *) value = (signed char) longval; } } else if (datatype == TUSHORT) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > (unsigned short) USHRT_MAX || longval < 0) *status = NUM_OVERFLOW; else *(unsigned short *) value = (unsigned short) longval; } } else if (datatype == TSHORT) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > SHRT_MAX || longval < SHRT_MIN) *status = NUM_OVERFLOW; else *(short *) value = (short) longval; } } else if (datatype == TUINT) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > (unsigned int) UINT_MAX || longval < 0) *status = NUM_OVERFLOW; else *(unsigned int *) value = longval; } } else if (datatype == TINT) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > INT_MAX || longval < INT_MIN) *status = NUM_OVERFLOW; else *(int *) value = longval; } } else if (datatype == TLOGICAL) { ffgkyl(fptr, keyname, (int *) value, comm, status); } else if (datatype == TULONG) { if (ffgkyujj(fptr, keyname, &ulongval, comm, status) <= 0) { if (ulongval > ULONG_MAX) *status = NUM_OVERFLOW; else *(unsigned long *) value = ulongval; } } else if (datatype == TLONG) { if (ffgkyjj(fptr, keyname, &longval, comm, status) <= 0) { if (longval > LONG_MAX || longval < LONG_MIN) *status = NUM_OVERFLOW; else *(int *) value = longval; } ffgkyj(fptr, keyname, (long *) value, comm, status); } else if (datatype == TULONGLONG) { ffgkyujj(fptr, keyname, (ULONGLONG *) value, comm, status); } else if (datatype == TLONGLONG) { ffgkyjj(fptr, keyname, (LONGLONG *) value, comm, status); } else if (datatype == TFLOAT) { ffgkye(fptr, keyname, (float *) value, comm, status); } else if (datatype == TDOUBLE) { ffgkyd(fptr, keyname, (double *) value, comm, status); } else if (datatype == TCOMPLEX) { ffgkyc(fptr, keyname, (float *) value, comm, status); } else if (datatype == TDBLCOMPLEX) { ffgkym(fptr, keyname, (double *) value, comm, status); } else *status = BAD_DATATYPE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgkey( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ char *keyval, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the keyword value and comment. The value is just the literal string of characters in the value field of the keyword. In the case of a string valued keyword, the returned value includes the leading and closing quote characters. The value may be up to 70 characters long, and the comment may be up to 72 characters long. If the keyword has no value (no equal sign in column 9) then a null value is returned. */ { char card[FLEN_CARD]; keyval[0] = '\0'; if (comm) comm[0] = '\0'; if (*status > 0) return(*status); if (ffgcrd(fptr, keyname, card, status) > 0) /* get the 80-byte card */ return(*status); ffpsvc(card, keyval, comm, status); /* parse the value and comment */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgrec( fitsfile *fptr, /* I - FITS file pointer */ int nrec, /* I - number of keyword to read */ char *card, /* O - keyword card */ int *status) /* IO - error status */ /* Read (get) the nrec-th keyword, returning the entire keyword card up to 80 characters long. The first keyword in the header has nrec = 1, not 0. The returned card value is null terminated with any trailing blank characters removed. If nrec = 0, then this routine simply moves the current header pointer to the top of the header. */ { if (*status > 0) return(*status); if (nrec == 0) { ffmaky(fptr, 1, status); /* simply move to beginning of header */ if (card) card[0] = '\0'; /* and return null card */ } else if (nrec > 0) { ffmaky(fptr, nrec, status); ffgnky(fptr, card, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgcrd( fitsfile *fptr, /* I - FITS file pointer */ const char *name, /* I - name of keyword to read */ char *card, /* O - keyword card */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the entire keyword card up to 80 characters long. The returned card value is null terminated with any trailing blank characters removed. If the input name contains wild cards ('?' matches any single char and '*' matches any sequence of chars, # matches any string of decimal digits) then the search ends once the end of header is reached and does not automatically resume from the top of the header. */ { int nkeys, nextkey, ntodo, namelen, namelen_limit, namelenminus1, cardlen; int ii = 0, jj, kk, wild, match, exact, hier = 0; char keyname[FLEN_KEYWORD], cardname[FLEN_KEYWORD]; char *ptr1, *ptr2, *gotstar; if (*status > 0) return(*status); *keyname = '\0'; while (name[ii] == ' ') /* skip leading blanks in name */ ii++; strncat(keyname, &name[ii], FLEN_KEYWORD - 1); namelen = strlen(keyname); while (namelen > 0 && keyname[namelen - 1] == ' ') namelen--; /* ignore trailing blanks in name */ keyname[namelen] = '\0'; /* terminate the name */ for (ii=0; ii < namelen; ii++) keyname[ii] = toupper(keyname[ii]); /* make upper case */ if (FSTRNCMP("HIERARCH", keyname, 8) == 0) { if (namelen == 8) { /* special case: just looking for any HIERARCH keyword */ hier = 1; } else { /* ignore the leading HIERARCH and look for the 'real' name */ /* starting with first non-blank character following HIERARCH */ ptr1 = keyname; ptr2 = &keyname[8]; while(*ptr2 == ' ') ptr2++; namelen = 0; while(*ptr2) { *ptr1 = *ptr2; ptr1++; ptr2++; namelen++; } *ptr1 = '\0'; } } /* does input name contain wild card chars? ('?', '*', or '#') */ /* wild cards are currently not supported with HIERARCH keywords */ namelen_limit = namelen; gotstar = 0; if (namelen < 9 && (strchr(keyname,'?') || (gotstar = strchr(keyname,'*')) || strchr(keyname,'#')) ) { wild = 1; /* if we found a '*' wild card in the name, there might be */ /* more than one. Support up to 2 '*' in the template. */ /* Thus we need to compare keywords whose names have at least */ /* namelen - 2 characters. */ if (gotstar) namelen_limit -= 2; } else wild = 0; ffghps(fptr, &nkeys, &nextkey, status); /* get no. keywords and position */ namelenminus1 = maxvalue(namelen - 1, 1); ntodo = nkeys - nextkey + 1; /* first, read from next keyword to end */ for (jj=0; jj < 2; jj++) { for (kk = 0; kk < ntodo; kk++) { ffgnky(fptr, card, status); /* get next keyword */ if (hier) { if (FSTRNCMP("HIERARCH", card, 8) == 0) return(*status); /* found a HIERARCH keyword */ } else { ffgknm(card, cardname, &cardlen, status); /* get the keyword name */ if (cardlen >= namelen_limit) /* can't match if card < name */ { /* if there are no wild cards, lengths must be the same */ if (!( !wild && cardlen != namelen) ) { for (ii=0; ii < cardlen; ii++) { /* make sure keyword is in uppercase */ if (cardname[ii] > 96) { /* This assumes the ASCII character set in which */ /* upper case characters start at ASCII(97) */ /* Timing tests showed that this is 20% faster */ /* than calling the isupper function. */ cardname[ii] = toupper(cardname[ii]); /* make upper case */ } } if (wild) { ffcmps(keyname, cardname, 1, &match, &exact); if (match) return(*status); /* found a matching keyword */ } else if (keyname[namelenminus1] == cardname[namelenminus1]) { /* test the last character of the keyword name first, on */ /* the theory that it is less likely to match then the first */ /* character since many keywords begin with 'T', for example */ if (FSTRNCMP(keyname, cardname, namelenminus1) == 0) { return(*status); /* found the matching keyword */ } } else if (namelen == 0 && cardlen == 0) { /* matched a blank keyword */ return(*status); } } } } } if (wild || jj == 1) break; /* stop at end of header if template contains wildcards */ ffmaky(fptr, 1, status); /* reset pointer to beginning of header */ ntodo = nextkey - 1; /* number of keyword to read */ } return(*status = KEY_NO_EXIST); /* couldn't find the keyword */ } /*--------------------------------------------------------------------------*/ int ffgstr( fitsfile *fptr, /* I - FITS file pointer */ const char *string, /* I - string to match */ char *card, /* O - keyword card */ int *status) /* IO - error status */ /* Read (get) the next keyword record that contains the input character string, returning the entire keyword card up to 80 characters long. The returned card value is null terminated with any trailing blank characters removed. */ { int nkeys, nextkey, ntodo, stringlen; int jj, kk; if (*status > 0) return(*status); stringlen = strlen(string); if (stringlen > 80) { return(*status = KEY_NO_EXIST); /* matching string is too long to exist */ } ffghps(fptr, &nkeys, &nextkey, status); /* get no. keywords and position */ ntodo = nkeys - nextkey + 1; /* first, read from next keyword to end */ for (jj=0; jj < 2; jj++) { for (kk = 0; kk < ntodo; kk++) { ffgnky(fptr, card, status); /* get next keyword */ if (strstr(card, string) != 0) { return(*status); /* found the matching string */ } } ffmaky(fptr, 1, status); /* reset pointer to beginning of header */ ntodo = nextkey - 1; /* number of keyword to read */ } return(*status = KEY_NO_EXIST); /* couldn't find the keyword */ } /*--------------------------------------------------------------------------*/ int ffgknm( char *card, /* I - keyword card */ char *name, /* O - name of the keyword */ int *length, /* O - length of the keyword name */ int *status) /* IO - error status */ /* Return the name of the keyword, and the name length. This supports the ESO HIERARCH convention where keyword names may be > 8 characters long. */ { char *ptr1, *ptr2; int ii, namelength; namelength = FLEN_KEYWORD - 1; *name = '\0'; *length = 0; /* support for ESO HIERARCH keywords; find the '=' */ if (FSTRNCMP(card, "HIERARCH ", 9) == 0) { ptr2 = strchr(card, '='); if (!ptr2) /* no value indicator ??? */ { /* this probably indicates an error, so just return FITS name */ strcat(name, "HIERARCH"); *length = 8; return(*status); } /* find the start and end of the HIERARCH name */ ptr1 = &card[9]; while (*ptr1 == ' ') /* skip spaces */ ptr1++; strncat(name, ptr1, ptr2 - ptr1); ii = ptr2 - ptr1; while (ii > 0 && name[ii - 1] == ' ') /* remove trailing spaces */ ii--; name[ii] = '\0'; *length = ii; } else { for (ii = 0; ii < namelength; ii++) { /* look for string terminator, or a blank */ if (*(card+ii) != ' ' && *(card+ii) != '=' && *(card+ii) !='\0') { *(name+ii) = *(card+ii); } else { name[ii] = '\0'; *length = ii; return(*status); } } /* if we got here, keyword is namelength characters long */ name[namelength] = '\0'; *length = namelength; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgunt( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ char *unit, /* O - keyword units */ int *status) /* IO - error status */ /* Read (get) the units string from the comment field of the existing keyword. This routine uses a local FITS convention (not defined in the official FITS standard) in which the units are enclosed in square brackets following the '/' comment field delimiter, e.g.: KEYWORD = 12 / [kpc] comment string goes here */ { char valstring[FLEN_VALUE]; char comm[FLEN_COMMENT]; char *loc; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ if (comm[0] == '[') { loc = strchr(comm, ']'); /* find the closing bracket */ if (loc) *loc = '\0'; /* terminate the string */ strcpy(unit, &comm[1]); /* copy the string */ } else unit[0] = '\0'; return(*status); } /*--------------------------------------------------------------------------*/ int ffgkys( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ char *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Get KeYword with a String value: Read (get) a simple string valued keyword. The returned value may be up to 68 chars long ( + 1 null terminator char). The routine does not support the HEASARC convention for continuing long string values over multiple keywords. The ffgkls routine may be used to read long continued strings. The returned comment string may be up to 69 characters long (including null terminator). */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ value[0] = '\0'; ffc2s(valstring, value, status); /* remove quotes from string */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgksl( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ int *length, /* O - length of the string value */ int *status) /* IO - error status */ /* Get the length of the keyword value string. This routine explicitly supports the CONTINUE convention for long string values. */ { int dummy=0; if (*status > 0) return(*status); ffgkcsl(fptr, keyname, length, &dummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgkcsl( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ int *length, /* O - length of the string value */ int *comlength, /* O - length of comment string */ int *status) /* IO - error status */ /* Get the length of the keyword value string and comment string. This routine explicitly supports the CONTINUE convention for long string values. */ { if (*status > 0) return(*status); ffglkut(fptr, keyname, 0, 0, 0, (char *)0, length, (char *)0, comlength, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgkls( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ char **value, /* O - pointer to keyword value */ char *comm, /* O - keyword comment (may be NULL) */ int *status) /* IO - error status */ /* This is the original routine for reading long string keywords that use the CONTINUE keyword convention. In 2016 a new routine called ffgsky / fits_read_string_key was added, which may provide a more convenient user interface for most applications. Get Keyword with possible Long String value: Read (get) the named keyword, returning the value and comment. The returned value string may be arbitrarily long (by using the HEASARC convention for continuing long string values over multiple keywords) so this routine allocates the required memory for the returned string value. It is up to the calling routine to free the memory once it is finished with the value string. The returned comment string may be up to 69 characters long. */ { char valstring[FLEN_VALUE], nextcomm[FLEN_COMMENT], card[FLEN_CARD]; int contin, commSpace = 0, addCommDelim=0, keynum=0; size_t len; if (*status > 0) return(*status); *value = NULL; /* initialize a null pointer in case of error */ card[0] = '\0'; if (comm) comm[0] = '\0'; ffgcrd(fptr, keyname, card, status); if (*status > 0) return(*status); if (strlen(card) < FLEN_CARD-1) addCommDelim=1; ffpsvc(card,valstring, comm, status); if (*status > 0) return(*status); if (comm) { /* remaining space in comment string */ commSpace = FLEN_COMMENT-1 - strlen(comm); } if (!valstring[0]) /* null value string? */ { *value = (char *) malloc(1); /* allocate and return a null string */ **value = '\0'; } else { /* allocate space, plus 1 for null */ *value = (char *) malloc(strlen(valstring) + 1); ffc2s(valstring, *value, status); /* convert string to value */ len = strlen(*value); /* If last character is a & then value may be continued on next keyword */ contin = 1; while (contin) { if (len && *(*value+len-1) == '&') /* is last char an ampersand? */ { valstring[0] = '\0'; nextcomm[0] = '\0'; ffgcnt(fptr, valstring, nextcomm, status); if (*valstring || *nextcomm) /* If either valstring or nextcom is filled, this must be a CONTINUE line */ { *(*value+len-1) = '\0'; /* erase the trailing & char */ if (*valstring) { len += strlen(valstring) - 1; *value = (char *) realloc(*value, len + 1); /* increase size */ strcat(*value, valstring); /* append the continued chars */ } if (*nextcomm) { if ((commSpace > 0) && (*nextcomm != 0)) { /* If in here, input 'comm' cannot be 0 */ /* concantenate comment strings (if any) */ if (strlen(comm) && addCommDelim) { strcat(comm, " "); commSpace -=1; } strncat(comm, nextcomm, commSpace); commSpace = FLEN_COMMENT-1 - strlen(comm); } } /* Determine if a space delimiter is needed for next comment concatenation (if any). Assume it is if card length of the most recently read keyword is less than max. keynum is 1-based. */ ffghps(fptr,0,&keynum,status); ffgrec(fptr, keynum-1, card, status); addCommDelim = (strlen(card) < FLEN_CARD-1) ? 1 : 0; } else { contin = 0; } } else { contin = 0; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsky( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ int firstchar, /* I - first character of string to return */ int maxchar, /* I - maximum length of string to return */ /* (string will be null terminated) */ char *value, /* O - pointer to keyword value */ int *valuelen, /* O - total length of the keyword value string */ /* The returned 'value' string may only */ /* contain a piece of the total string, depending */ /* on the value of firstchar and maxchar */ char *comm, /* O - keyword comment (may be NULL) */ int *status) /* IO - error status */ /* Read and return the value of the specified string-valued keyword. This new routine was added in 2016 to provide a more convenient user interface than the older ffgkls routine. Read a string keyword, returning up to 'naxchars' characters of the value starting with the 'firstchar' character. The input 'value' string must be allocated at least 1 char bigger to allow for the terminating null character. This routine may be used to read continued string keywords that use the CONTINUE keyword convention, as well as normal string keywords that are contained within a single header record. This routine differs from the ffkls routine in that it does not internally allocate memory for the returned value string, and consequently the calling routine does not need to call fffree to free the memory. */ { char valstring[FLEN_VALUE], nextcomm[FLEN_COMMENT], card[FLEN_CARD]; char *tempstring; int contin, commSpace = 0, addCommDelim=0, keynum=0; size_t len; if (*status > 0) return(*status); tempstring = NULL; /* initialize in case of error */ *value = '\0'; if (valuelen) *valuelen = 0; card[0] = '\0'; if (comm) comm[0] = '\0'; ffgcrd(fptr, keyname, card, status); if (*status > 0) return(*status); if (strlen(card) < FLEN_CARD-1) addCommDelim=1; ffpsvc(card,valstring, comm, status); if (*status > 0) return(*status); if (comm) { /* remaining space in comment string */ commSpace = FLEN_COMMENT-1 - strlen(comm); } if (!valstring[0]) /* null value string? */ { tempstring = (char *) malloc(1); /* allocate and return a null string */ *tempstring = '\0'; } else { /* allocate space, plus 1 for null */ tempstring = (char *) malloc(strlen(valstring) + 1); ffc2s(valstring, tempstring, status); /* convert string to value */ len = strlen(tempstring); /* If last character is a & then value may be continued on next keyword */ contin = 1; while (contin && *status <= 0) { if (len && *(tempstring+len-1) == '&') /* is last char an ampersand? */ { valstring[0] = '\0'; nextcomm[0] = '\0'; ffgcnt(fptr, valstring, nextcomm, status); if (*valstring || *nextcomm) /* If either valstring or nextcom is filled, this must be a CONTINUE line */ { *(tempstring+len-1) = '\0'; /* erase the trailing & char */ if (*valstring) { len += strlen(valstring) - 1; tempstring = (char *) realloc(tempstring, len + 1); /* increase size */ strcat(tempstring, valstring); /* append the continued chars */ } if (*nextcomm) { if ((commSpace > 0) && (*nextcomm != 0)) { /* If in here, input 'comm' cannot be 0 */ /* concantenate comment strings (if any) */ if (strlen(comm) && addCommDelim) { strcat(comm, " "); commSpace -=1; } strncat(comm, nextcomm, commSpace); commSpace = FLEN_COMMENT-1 - strlen(comm); } } /* Determine if a space delimiter is needed for next comment concatenation (if any). Assume it is if card length of the most recently read keyword is less than max. keynum is 1-based. */ ffghps(fptr,0,&keynum,status); ffgrec(fptr, keynum-1, card, status); addCommDelim = (strlen(card) < FLEN_CARD-1) ? 1 : 0; } else { contin = 0; } } else { contin = 0; } } } if (tempstring) { len = strlen(tempstring); if (firstchar <= len) strncat(value, tempstring + (firstchar - 1), maxchar); free(tempstring); if (valuelen) *valuelen = len; /* total length of the keyword value */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffgskyc( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ int firstchar, /* I - first character of string to return */ int maxchar, /* I - maximum length of string to return */ /* (string will be null terminated) */ int maxcomchar, /* I - maximum length of comment to return */ char *value, /* O - pointer to keyword value */ int *valuelen, /* O - total length of the keyword value string */ /* The returned 'value' string may only */ /* contain a piece of the total string, depending */ /* on the value of firstchar and maxchar */ char *comm, /* O - keyword comment (may be NULL) */ int *comlen, /* O - total length of the comment string */ int *status) /* IO - error status */ { if (*status > 0) return(*status); ffglkut(fptr,keyname,firstchar,maxchar,maxcomchar,value,valuelen, comm,comlen,status); return(*status); } /*--------------------------------------------------------------------------*/ int ffglkut( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ int firstchar, /* I - first character of string to return */ int maxvalchar, /* I - maximum length of string to return */ /* (string will be null terminated) */ int maxcomchar, /* I - maximum length of comment to return */ char *value, /* O - pointer to keyword value (may be NULL) */ int *valuelen, /* O - total length of the keyword value string */ /* The returned 'value' string may only */ /* contain a piece of the total string, depending */ /* on the value of firstchar and maxvalchar */ char *comm, /* O - keyword comment (may be NULL) */ int *comlen, /* O - total length of comment string */ int *status) /* IO - error status */ { char valstring[FLEN_VALUE], comstring[FLEN_COMMENT], card[FLEN_CARD]; char *dynValStr=0, *dynComStr=0; int contin, addCommDelim=0, keynum=0; int lenOnly=0, savedKeyPos=1; size_t len=0, lenc=0; if (*status > 0) return(*status); if (maxvalchar==0 && maxcomchar==0) lenOnly = 1; if (value) *value = '\0'; if (comm) *comm = '\0'; /* If lenOnly, 'value' and 'comm' should not be accessed after this point.*/ *valuelen = 0; *comlen = 0; card[0] = '\0'; valstring[0] = '\0'; comstring[0] = '\0'; ffgcrd(fptr, keyname, card, status); if (*status > 0) return(*status); ffpsvc(card,valstring, comstring, status); if (*status > 0) return(*status); if (strlen(card) < FLEN_CARD-1 && *comstring) addCommDelim=1; /* If called in lenOnly mode, there's a good chance the user will soon call this again to read the value string. Therefore we'll save and later restore the original keyword position. */ if (lenOnly) { ffghps(fptr, 0, &savedKeyPos, status); if (savedKeyPos > 1) savedKeyPos -= 1; } if (!valstring[0]) /* null value string? */ { dynValStr = (char *) malloc(1); /* allocate and return a null string */ *dynValStr = '\0'; dynComStr = (char *)malloc(1); *dynComStr= '\0'; } else { /* allocate space, plus 1 for null */ dynValStr = (char *) malloc(strlen(valstring) + 1); ffc2s(valstring, dynValStr, status); /* convert string to value */ len = strlen(dynValStr); dynComStr = (char *) malloc(strlen(comstring)+1); dynComStr[0]=0; strcpy(dynComStr, comstring); lenc = strlen(dynComStr); /* If last character is a & then value may be continued on next keyword */ contin = 1; while (contin && *status <= 0) { if (len && *(dynValStr+len-1) == '&') /* is last char an ampersand? */ { valstring[0] = '\0'; comstring[0] = '\0'; ffgcnt(fptr, valstring, comstring, status); if (*valstring || *comstring) /* If either valstring or comstring is filled, this must be a CONTINUE line */ { *(dynValStr+len-1) = '\0'; /* erase the trailing & char */ len -= 1; if (*valstring) { len += strlen(valstring); dynValStr = (char *) realloc(dynValStr, len + 1); /* increase size */ strcat(dynValStr, valstring); /* append the continued chars */ } if (*comstring) { /* concantenate comment strings */ if (addCommDelim) { lenc += strlen(comstring) + 1; dynComStr = (char *) realloc(dynComStr, lenc + 1); strcat(dynComStr, " "); strcat(dynComStr, comstring); } else { lenc += strlen(comstring); dynComStr = (char *) realloc(dynComStr, lenc + 1); strcat(dynComStr, comstring); } } /* Determine if a space delimiter is needed for next comment concatenation (if any). Assume it is if card length of the most recently read keyword is less than max. keynum is 1-based. */ ffghps(fptr,0,&keynum,status); ffgrec(fptr, keynum-1, card, status); addCommDelim = ((strlen(card) < FLEN_CARD-1) && lenc) ? 1 : 0; } else { contin = 0; } } else { contin = 0; } } } /* Resetting len and lenc really shouldn't be necessary here, but just to make sure ... */ len = strlen(dynValStr); lenc = strlen(dynComStr); *valuelen = len; *comlen = lenc; if (lenOnly) ffmaky(fptr, savedKeyPos, status); else { if (value) { if (firstchar <= len) strncat(value,dynValStr+firstchar-1,maxvalchar); } if (comm) { strncat(comm,dynComStr,maxcomchar); } } free(dynValStr); free(dynComStr); return(*status); } /*--------------------------------------------------------------------------*/ int fffree( void *value, /* I - pointer to keyword value */ int *status) /* IO - error status */ /* Free the memory that was previously allocated by CFITSIO, such as by ffgkls or fits_hdr2str */ { if (*status > 0) return(*status); if (value) free(value); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcnt( fitsfile *fptr, /* I - FITS file pointer */ char *value, /* O - continued string value */ char *comm, /* O - continued comment string */ int *status) /* IO - error status */ /* Attempt to read the next keyword, returning the string value if it is a continuation of the previous string keyword value. This uses the HEASARC convention for continuing long string values over multiple keywords. Each continued string is terminated with a backslash character, and the continuation follows on the next keyword which must have the name CONTINUE without an equal sign in column 9 of the card. If the next card is not a continuation, then the returned value string will be null. */ { int tstatus; char card[FLEN_CARD], strval[FLEN_VALUE]; if (*status > 0) return(*status); tstatus = 0; value[0] = '\0'; if (ffgnky(fptr, card, &tstatus) > 0) /* read next keyword */ return(*status); /* hit end of header */ if (strncmp(card, "CONTINUE ", 10) == 0) /* a continuation card? */ { strncpy(card, "D2345678= ", 10); /* overwrite a dummy keyword name */ ffpsvc(card, strval, comm, &tstatus); /* get the string value & comment */ ffc2s(strval, value, &tstatus); /* remove the surrounding quotes */ if (tstatus) /* return null if error status was returned */ value[0] = '\0'; } else ffmrky(fptr, -1, status); /* reset the keyword pointer */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyl( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ int *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The returned value = 1 if the keyword is true, else = 0 if false. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ ffc2l(valstring, value, status); /* convert string to value */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ long *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The value will be implicitly converted to a (long) integer if it not already of this datatype. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ ffc2i(valstring, value, status); /* convert string to value */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyjj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ LONGLONG *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The value will be implicitly converted to a (LONGLONG) integer if it not already of this datatype. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ ffc2j(valstring, value, status); /* convert string to value */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyujj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ ULONGLONG *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The value will be implicitly converted to a (ULONGLONG) integer if it not already of this datatype. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ ffc2uj(valstring, value, status); /* convert string to value */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkye( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ float *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The value will be implicitly converted to a float if it not already of this datatype. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ ffc2r(valstring, value, status); /* convert string to value */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyd( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ double *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The value will be implicitly converted to a double if it not already of this datatype. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ ffc2d(valstring, value, status); /* convert string to value */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyc( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ float *value, /* O - keyword value (real,imag) */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The keyword must have a complex value. No implicit data conversion will be performed. */ { char valstring[FLEN_VALUE], message[FLEN_ERRMSG]; int len; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ if (valstring[0] != '(' ) /* test that this is a complex keyword */ { snprintf(message, FLEN_ERRMSG, "keyword %s does not have a complex value (ffgkyc):", keyname); ffpmsg(message); ffpmsg(valstring); return(*status = BAD_C2F); } valstring[0] = ' '; /* delete the opening parenthesis */ len = strcspn(valstring, ")" ); valstring[len] = '\0'; /* delete the closing parenthesis */ len = strcspn(valstring, ","); valstring[len] = '\0'; ffc2r(valstring, &value[0], status); /* convert the real part */ ffc2r(&valstring[len + 1], &value[1], status); /* convert imag. part */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkym( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ double *value, /* O - keyword value (real,imag) */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The keyword must have a complex value. No implicit data conversion will be performed. */ { char valstring[FLEN_VALUE], message[FLEN_ERRMSG]; int len; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ if (valstring[0] != '(' ) /* test that this is a complex keyword */ { snprintf(message, FLEN_ERRMSG, "keyword %s does not have a complex value (ffgkym):", keyname); ffpmsg(message); ffpmsg(valstring); return(*status = BAD_C2D); } valstring[0] = ' '; /* delete the opening parenthesis */ len = strcspn(valstring, ")" ); valstring[len] = '\0'; /* delete the closing parenthesis */ len = strcspn(valstring, ","); valstring[len] = '\0'; ffc2d(valstring, &value[0], status); /* convert the real part */ ffc2d(&valstring[len + 1], &value[1], status); /* convert the imag. part */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyt( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - name of keyword to read */ long *ivalue, /* O - integer part of keyword value */ double *fraction, /* O - fractional part of keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the named keyword, returning the value and comment. The integer and fractional parts of the value are returned in separate variables, to allow more numerical precision to be passed. This effectively passes a 'triple' precision value, with a 4-byte integer and an 8-byte fraction. The comment may be up to 69 characters long. */ { char valstring[FLEN_VALUE]; char *loc; if (*status > 0) return(*status); ffgkey(fptr, keyname, valstring, comm, status); /* read the keyword */ /* read the entire value string as a double, to get the integer part */ ffc2d(valstring, fraction, status); *ivalue = (long) *fraction; *fraction = *fraction - *ivalue; /* see if we need to read the fractional part again with more precision */ /* look for decimal point, without an exponential E or D character */ loc = strchr(valstring, '.'); if (loc) { if (!strchr(valstring, 'E') && !strchr(valstring, 'D')) ffc2d(loc, fraction, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgkyn( fitsfile *fptr, /* I - FITS file pointer */ int nkey, /* I - number of the keyword to read */ char *keyname, /* O - name of the keyword */ char *value, /* O - keyword value */ char *comm, /* O - keyword comment */ int *status) /* IO - error status */ /* Read (get) the nkey-th keyword returning the keyword name, value and comment. The value is just the literal string of characters in the value field of the keyword. In the case of a string valued keyword, the returned value includes the leading and closing quote characters. The value may be up to 70 characters long, and the comment may be up to 72 characters long. If the keyword has no value (no equal sign in column 9) then a null value is returned. If comm = NULL, then do not return the comment string. */ { char card[FLEN_CARD], sbuff[FLEN_CARD]; int namelen; keyname[0] = '\0'; value[0] = '\0'; if (comm) comm[0] = '\0'; if (*status > 0) return(*status); if (ffgrec(fptr, nkey, card, status) > 0 ) /* get the 80-byte card */ return(*status); ffgknm(card, keyname, &namelen, status); /* get the keyword name */ if (ffpsvc(card, value, comm, status) > 0) /* parse value and comment */ return(*status); if (fftrec(keyname, status) > 0) /* test keyword name; catches no END */ { snprintf(sbuff, FLEN_CARD, "Name of keyword no. %d contains illegal character(s): %s", nkey, keyname); ffpmsg(sbuff); if (nkey % 36 == 0) /* test if at beginning of 36-card FITS record */ ffpmsg(" (This may indicate a missing END keyword)."); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgkns( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - root name of keywords to read */ int nstart, /* I - starting index number */ int nmax, /* I - maximum number of keywords to return */ char *value[], /* O - array of pointers to keyword values */ int *nfound, /* O - number of values that were returned */ int *status) /* IO - error status */ /* Read (get) an indexed array of keywords with index numbers between NSTART and (NSTART + NMAX -1) inclusive. This routine does NOT support the HEASARC long string convention. */ { int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval; long ival; char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD]; char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign; if (*status > 0) return(*status); *nfound = 0; nend = nstart + nmax - 1; keyroot[0] = '\0'; strncat(keyroot, keyname, FLEN_KEYWORD - 1); lenroot = strlen(keyroot); if (lenroot == 0) /* root must be at least 1 char long */ return(*status); for (ii=0; ii < lenroot; ii++) /* make sure upper case */ keyroot[ii] = toupper(keyroot[ii]); ffghps(fptr, &nkeys, &mkeys, status); /* get the number of keywords */ undefinedval = FALSE; for (ii=3; ii <= nkeys; ii++) { if (ffgrec(fptr, ii, card, status) > 0) /* get next keyword */ return(*status); if (strncmp(keyroot, card, lenroot) == 0) /* see if keyword matches */ { keyindex[0] = '\0'; equalssign = strchr(card, '='); if (equalssign == 0) continue; /* keyword has no value */ if (equalssign - card - lenroot > 7) { return (*status=BAD_KEYCHAR); } strncat(keyindex, &card[lenroot], equalssign - card - lenroot); /* copy suffix */ tstatus = 0; if (ffc2ii(keyindex, &ival, &tstatus) <= 0) /* test suffix */ { if (ival <= nend && ival >= nstart) { ffpsvc(card, svalue, comm, status); /* parse the value */ ffc2s(svalue, value[ival-nstart], status); /* convert */ if (ival - nstart + 1 > *nfound) *nfound = ival - nstart + 1; /* max found */ if (*status == VALUE_UNDEFINED) { undefinedval = TRUE; *status = 0; /* reset status to read remaining values */ } } } } } if (undefinedval && (*status <= 0) ) *status = VALUE_UNDEFINED; /* report at least 1 value undefined */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgknl( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - root name of keywords to read */ int nstart, /* I - starting index number */ int nmax, /* I - maximum number of keywords to return */ int *value, /* O - array of keyword values */ int *nfound, /* O - number of values that were returned */ int *status) /* IO - error status */ /* Read (get) an indexed array of keywords with index numbers between NSTART and (NSTART + NMAX -1) inclusive. The returned value = 1 if the keyword is true, else = 0 if false. */ { int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval; long ival; char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD]; char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign; if (*status > 0) return(*status); *nfound = 0; nend = nstart + nmax - 1; keyroot[0] = '\0'; strncat(keyroot, keyname, FLEN_KEYWORD - 1); lenroot = strlen(keyroot); if (lenroot == 0) /* root must be at least 1 char long */ return(*status); for (ii=0; ii < lenroot; ii++) /* make sure upper case */ keyroot[ii] = toupper(keyroot[ii]); ffghps(fptr, &nkeys, &mkeys, status); /* get the number of keywords */ ffmaky(fptr, 3, status); /* move to 3rd keyword (skip 1st 2 keywords) */ undefinedval = FALSE; for (ii=3; ii <= nkeys; ii++) { if (ffgnky(fptr, card, status) > 0) /* get next keyword */ return(*status); if (strncmp(keyroot, card, lenroot) == 0) /* see if keyword matches */ { keyindex[0] = '\0'; equalssign = strchr(card, '='); if (equalssign == 0) continue; /* keyword has no value */ if (equalssign - card - lenroot > 7) { return (*status=BAD_KEYCHAR); } strncat(keyindex, &card[lenroot], equalssign - card - lenroot); /* copy suffix */ tstatus = 0; if (ffc2ii(keyindex, &ival, &tstatus) <= 0) /* test suffix */ { if (ival <= nend && ival >= nstart) { ffpsvc(card, svalue, comm, status); /* parse the value */ ffc2l(svalue, &value[ival-nstart], status); /* convert*/ if (ival - nstart + 1 > *nfound) *nfound = ival - nstart + 1; /* max found */ if (*status == VALUE_UNDEFINED) { undefinedval = TRUE; *status = 0; /* reset status to read remaining values */ } } } } } if (undefinedval && (*status <= 0) ) *status = VALUE_UNDEFINED; /* report at least 1 value undefined */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgknj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - root name of keywords to read */ int nstart, /* I - starting index number */ int nmax, /* I - maximum number of keywords to return */ long *value, /* O - array of keyword values */ int *nfound, /* O - number of values that were returned */ int *status) /* IO - error status */ /* Read (get) an indexed array of keywords with index numbers between NSTART and (NSTART + NMAX -1) inclusive. */ { int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval; long ival; char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD]; char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign; if (*status > 0) return(*status); *nfound = 0; nend = nstart + nmax - 1; keyroot[0] = '\0'; strncat(keyroot, keyname, FLEN_KEYWORD - 1); lenroot = strlen(keyroot); if (lenroot == 0) /* root must be at least 1 char long */ return(*status); for (ii=0; ii < lenroot; ii++) /* make sure upper case */ keyroot[ii] = toupper(keyroot[ii]); ffghps(fptr, &nkeys, &mkeys, status); /* get the number of keywords */ ffmaky(fptr, 3, status); /* move to 3rd keyword (skip 1st 2 keywords) */ undefinedval = FALSE; for (ii=3; ii <= nkeys; ii++) { if (ffgnky(fptr, card, status) > 0) /* get next keyword */ return(*status); if (strncmp(keyroot, card, lenroot) == 0) /* see if keyword matches */ { keyindex[0] = '\0'; equalssign = strchr(card, '='); if (equalssign == 0) continue; /* keyword has no value */ if (equalssign - card - lenroot > 7) { return (*status=BAD_KEYCHAR); } strncat(keyindex, &card[lenroot], equalssign - card - lenroot); /* copy suffix */ tstatus = 0; if (ffc2ii(keyindex, &ival, &tstatus) <= 0) /* test suffix */ { if (ival <= nend && ival >= nstart) { ffpsvc(card, svalue, comm, status); /* parse the value */ ffc2i(svalue, &value[ival-nstart], status); /* convert */ if (ival - nstart + 1 > *nfound) *nfound = ival - nstart + 1; /* max found */ if (*status == VALUE_UNDEFINED) { undefinedval = TRUE; *status = 0; /* reset status to read remaining values */ } } } } } if (undefinedval && (*status <= 0) ) *status = VALUE_UNDEFINED; /* report at least 1 value undefined */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgknjj( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - root name of keywords to read */ int nstart, /* I - starting index number */ int nmax, /* I - maximum number of keywords to return */ LONGLONG *value, /* O - array of keyword values */ int *nfound, /* O - number of values that were returned */ int *status) /* IO - error status */ /* Read (get) an indexed array of keywords with index numbers between NSTART and (NSTART + NMAX -1) inclusive. */ { int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval; long ival; char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD]; char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign; if (*status > 0) return(*status); *nfound = 0; nend = nstart + nmax - 1; keyroot[0] = '\0'; strncat(keyroot, keyname, FLEN_KEYWORD - 1); lenroot = strlen(keyroot); if (lenroot == 0) /* root must be at least 1 char long */ return(*status); for (ii=0; ii < lenroot; ii++) /* make sure upper case */ keyroot[ii] = toupper(keyroot[ii]); ffghps(fptr, &nkeys, &mkeys, status); /* get the number of keywords */ ffmaky(fptr, 3, status); /* move to 3rd keyword (skip 1st 2 keywords) */ undefinedval = FALSE; for (ii=3; ii <= nkeys; ii++) { if (ffgnky(fptr, card, status) > 0) /* get next keyword */ return(*status); if (strncmp(keyroot, card, lenroot) == 0) /* see if keyword matches */ { keyindex[0] = '\0'; equalssign = strchr(card, '='); if (equalssign == 0) continue; /* keyword has no value */ if (equalssign - card - lenroot > 7) { return (*status=BAD_KEYCHAR); } strncat(keyindex, &card[lenroot], equalssign - card - lenroot); /* copy suffix */ tstatus = 0; if (ffc2ii(keyindex, &ival, &tstatus) <= 0) /* test suffix */ { if (ival <= nend && ival >= nstart) { ffpsvc(card, svalue, comm, status); /* parse the value */ ffc2j(svalue, &value[ival-nstart], status); /* convert */ if (ival - nstart + 1 > *nfound) *nfound = ival - nstart + 1; /* max found */ if (*status == VALUE_UNDEFINED) { undefinedval = TRUE; *status = 0; /* reset status to read remaining values */ } } } } } if (undefinedval && (*status <= 0) ) *status = VALUE_UNDEFINED; /* report at least 1 value undefined */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgkne( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - root name of keywords to read */ int nstart, /* I - starting index number */ int nmax, /* I - maximum number of keywords to return */ float *value, /* O - array of keyword values */ int *nfound, /* O - number of values that were returned */ int *status) /* IO - error status */ /* Read (get) an indexed array of keywords with index numbers between NSTART and (NSTART + NMAX -1) inclusive. */ { int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval; long ival; char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD]; char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign; if (*status > 0) return(*status); *nfound = 0; nend = nstart + nmax - 1; keyroot[0] = '\0'; strncat(keyroot, keyname, FLEN_KEYWORD - 1); lenroot = strlen(keyroot); if (lenroot == 0) /* root must be at least 1 char long */ return(*status); for (ii=0; ii < lenroot; ii++) /* make sure upper case */ keyroot[ii] = toupper(keyroot[ii]); ffghps(fptr, &nkeys, &mkeys, status); /* get the number of keywords */ ffmaky(fptr, 3, status); /* move to 3rd keyword (skip 1st 2 keywords) */ undefinedval = FALSE; for (ii=3; ii <= nkeys; ii++) { if (ffgnky(fptr, card, status) > 0) /* get next keyword */ return(*status); if (strncmp(keyroot, card, lenroot) == 0) /* see if keyword matches */ { keyindex[0] = '\0'; equalssign = strchr(card, '='); if (equalssign == 0) continue; /* keyword has no value */ if (equalssign - card - lenroot > 7) { return (*status=BAD_KEYCHAR); } strncat(keyindex, &card[lenroot], equalssign - card - lenroot); /* copy suffix */ tstatus = 0; if (ffc2ii(keyindex, &ival, &tstatus) <= 0) /* test suffix */ { if (ival <= nend && ival >= nstart) { ffpsvc(card, svalue, comm, status); /* parse the value */ ffc2r(svalue, &value[ival-nstart], status); /* convert */ if (ival - nstart + 1 > *nfound) *nfound = ival - nstart + 1; /* max found */ if (*status == VALUE_UNDEFINED) { undefinedval = TRUE; *status = 0; /* reset status to read remaining values */ } } } } } if (undefinedval && (*status <= 0) ) *status = VALUE_UNDEFINED; /* report at least 1 value undefined */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgknd( fitsfile *fptr, /* I - FITS file pointer */ const char *keyname, /* I - root name of keywords to read */ int nstart, /* I - starting index number */ int nmax, /* I - maximum number of keywords to return */ double *value, /* O - array of keyword values */ int *nfound, /* O - number of values that were returned */ int *status) /* IO - error status */ /* Read (get) an indexed array of keywords with index numbers between NSTART and (NSTART + NMAX -1) inclusive. */ { int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval; long ival; char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD]; char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign; if (*status > 0) return(*status); *nfound = 0; nend = nstart + nmax - 1; keyroot[0] = '\0'; strncat(keyroot, keyname, FLEN_KEYWORD - 1); lenroot = strlen(keyroot); if (lenroot == 0) /* root must be at least 1 char long */ return(*status); for (ii=0; ii < lenroot; ii++) /* make sure upper case */ keyroot[ii] = toupper(keyroot[ii]); ffghps(fptr, &nkeys, &mkeys, status); /* get the number of keywords */ ffmaky(fptr, 3, status); /* move to 3rd keyword (skip 1st 2 keywords) */ undefinedval = FALSE; for (ii=3; ii <= nkeys; ii++) { if (ffgnky(fptr, card, status) > 0) /* get next keyword */ return(*status); if (strncmp(keyroot, card, lenroot) == 0) /* see if keyword matches */ { keyindex[0] = '\0'; equalssign = strchr(card, '='); if (equalssign == 0) continue; /* keyword has no value */ if (equalssign - card - lenroot > 7) { return (*status=BAD_KEYCHAR); } strncat(keyindex, &card[lenroot], equalssign - card - lenroot); /* copy suffix */ tstatus = 0; if (ffc2ii(keyindex, &ival, &tstatus) <= 0) /* test suffix */ { if (ival <= nend && ival >= nstart) /* is index within range? */ { ffpsvc(card, svalue, comm, status); /* parse the value */ ffc2d(svalue, &value[ival-nstart], status); /* convert */ if (ival - nstart + 1 > *nfound) *nfound = ival - nstart + 1; /* max found */ if (*status == VALUE_UNDEFINED) { undefinedval = TRUE; *status = 0; /* reset status to read remaining values */ } } } } } if (undefinedval && (*status <= 0) ) *status = VALUE_UNDEFINED; /* report at least 1 value undefined */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgtdm(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read */ int maxdim, /* I - maximum no. of dimensions to read; */ int *naxis, /* O - number of axes in the data array */ long naxes[], /* O - length of each data axis */ int *status) /* IO - error status */ /* read and parse the TDIMnnn keyword to get the dimensionality of a column */ { int tstatus = 0; char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE]; if (*status > 0) return(*status); ffkeyn("TDIM", colnum, keyname, status); /* construct keyword name */ ffgkys(fptr, keyname, tdimstr, NULL, &tstatus); /* try reading keyword */ ffdtdm(fptr, tdimstr, colnum, maxdim,naxis, naxes, status); /* decode it */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgtdmll(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read */ int maxdim, /* I - maximum no. of dimensions to read; */ int *naxis, /* O - number of axes in the data array */ LONGLONG naxes[], /* O - length of each data axis */ int *status) /* IO - error status */ /* read and parse the TDIMnnn keyword to get the dimensionality of a column */ { int tstatus = 0; char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE]; if (*status > 0) return(*status); ffkeyn("TDIM", colnum, keyname, status); /* construct keyword name */ ffgkys(fptr, keyname, tdimstr, NULL, &tstatus); /* try reading keyword */ ffdtdmll(fptr, tdimstr, colnum, maxdim,naxis, naxes, status); /* decode it */ return(*status); } /*--------------------------------------------------------------------------*/ int ffdtdm(fitsfile *fptr, /* I - FITS file pointer */ char *tdimstr, /* I - TDIMn keyword value string. e.g. (10,10) */ int colnum, /* I - number of the column */ int maxdim, /* I - maximum no. of dimensions to read; */ int *naxis, /* O - number of axes in the data array */ long naxes[], /* O - length of each data axis */ int *status) /* IO - error status */ /* decode the TDIMnnn keyword to get the dimensionality of a column. Check that the value is legal and consistent with the TFORM value. If colnum = 0, then the validity checking is disabled. */ { long dimsize, totalpix = 1; char *loc, *lastloc, message[FLEN_ERRMSG]; tcolumn *colptr = 0; if (*status > 0) return(*status); if (colnum != 0) { if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; /* set pointer to the first column */ colptr += (colnum - 1); /* increment to the correct column */ if (!tdimstr[0]) /* TDIMn keyword doesn't exist? */ { *naxis = 1; /* default = 1 dimensional */ if (maxdim > 0) naxes[0] = (long) colptr->trepeat; /* default length = repeat */ return(*status); } } *naxis = 0; loc = strchr(tdimstr, '(' ); /* find the opening quote */ if (!loc) { snprintf(message, FLEN_ERRMSG, "Illegal dimensions format: %s", tdimstr); return(*status = BAD_TDIM); } while (loc) { loc++; dimsize = strtol(loc, &loc, 10); /* read size of next dimension */ if (*naxis < maxdim) naxes[*naxis] = dimsize; if (dimsize < 0) { ffpmsg("one or more dimension are less than 0 (ffdtdm)"); ffpmsg(tdimstr); return(*status = BAD_TDIM); } totalpix *= dimsize; (*naxis)++; lastloc = loc; loc = strchr(loc, ','); /* look for comma before next dimension */ } loc = strchr(lastloc, ')' ); /* check for the closing quote */ if (!loc) { snprintf(message, FLEN_ERRMSG, "Illegal dimensions format: %s", tdimstr); return(*status = BAD_TDIM); } if (colnum != 0) { if ((colptr->tdatatype > 0) && ((long) colptr->trepeat != totalpix)) { snprintf(message, FLEN_ERRMSG, "column vector length, %ld, does not equal TDIMn array size, %ld", (long) colptr->trepeat, totalpix); ffpmsg(message); ffpmsg(tdimstr); return(*status = BAD_TDIM); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffdtdmll(fitsfile *fptr, /* I - FITS file pointer */ char *tdimstr, /* I - TDIMn keyword value string. e.g. (10,10) */ int colnum, /* I - number of the column */ int maxdim, /* I - maximum no. of dimensions to read; */ int *naxis, /* O - number of axes in the data array */ LONGLONG naxes[], /* O - length of each data axis */ int *status) /* IO - error status */ /* decode the TDIMnnn keyword to get the dimensionality of a column. Check that the value is legal and consistent with the TFORM value. */ { LONGLONG dimsize; LONGLONG totalpix = 1; char *loc, *lastloc, message[FLEN_ERRMSG]; tcolumn *colptr; double doublesize; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; /* set pointer to the first column */ colptr += (colnum - 1); /* increment to the correct column */ if (!tdimstr[0]) /* TDIMn keyword doesn't exist? */ { *naxis = 1; /* default = 1 dimensional */ if (maxdim > 0) naxes[0] = colptr->trepeat; /* default length = repeat */ } else { *naxis = 0; loc = strchr(tdimstr, '(' ); /* find the opening quote */ if (!loc) { snprintf(message, FLEN_ERRMSG, "Illegal TDIM keyword value: %s", tdimstr); return(*status = BAD_TDIM); } while (loc) { loc++; /* Read value as a double because the string to 64-bit int function is */ /* platform dependent (strtoll, strtol, _atoI64). This still gives */ /* about 48 bits of precision, which is plenty for this purpose. */ doublesize = strtod(loc, &loc); dimsize = (LONGLONG) (doublesize + 0.1); if (*naxis < maxdim) naxes[*naxis] = dimsize; if (dimsize < 0) { ffpmsg("one or more TDIM values are less than 0 (ffdtdm)"); ffpmsg(tdimstr); return(*status = BAD_TDIM); } totalpix *= dimsize; (*naxis)++; lastloc = loc; loc = strchr(loc, ','); /* look for comma before next dimension */ } loc = strchr(lastloc, ')' ); /* check for the closing quote */ if (!loc) { snprintf(message, FLEN_ERRMSG, "Illegal TDIM keyword value: %s", tdimstr); return(*status = BAD_TDIM); } if ((colptr->tdatatype > 0) && (colptr->trepeat != totalpix)) { snprintf(message, FLEN_ERRMSG, "column vector length, %.0f, does not equal TDIMn array size, %.0f", (double) (colptr->trepeat), (double) totalpix); ffpmsg(message); ffpmsg(tdimstr); return(*status = BAD_TDIM); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffghpr(fitsfile *fptr, /* I - FITS file pointer */ int maxdim, /* I - maximum no. of dimensions to read; */ int *simple, /* O - does file conform to FITS standard? 1/0 */ int *bitpix, /* O - number of bits per data value pixel */ int *naxis, /* O - number of axes in the data array */ long naxes[], /* O - length of each data axis */ long *pcount, /* O - number of group parameters (usually 0) */ long *gcount, /* O - number of random groups (usually 1 or 0) */ int *extend, /* O - may FITS file haave extensions? */ int *status) /* IO - error status */ /* Get keywords from the Header of the PRimary array: Check that the keywords conform to the FITS standard and return the parameters which determine the size and structure of the primary array or IMAGE extension. */ { int idummy, ii; LONGLONG lldummy; double ddummy; LONGLONG tnaxes[99]; ffgphd(fptr, maxdim, simple, bitpix, naxis, tnaxes, pcount, gcount, extend, &ddummy, &ddummy, &lldummy, &idummy, status); if (naxis && naxes) { for (ii = 0; (ii < *naxis) && (ii < maxdim); ii++) naxes[ii] = (long) tnaxes[ii]; } else if (naxes) { for (ii = 0; ii < maxdim; ii++) naxes[ii] = (long) tnaxes[ii]; } return(*status); } /*--------------------------------------------------------------------------*/ int ffghprll(fitsfile *fptr, /* I - FITS file pointer */ int maxdim, /* I - maximum no. of dimensions to read; */ int *simple, /* O - does file conform to FITS standard? 1/0 */ int *bitpix, /* O - number of bits per data value pixel */ int *naxis, /* O - number of axes in the data array */ LONGLONG naxes[], /* O - length of each data axis */ long *pcount, /* O - number of group parameters (usually 0) */ long *gcount, /* O - number of random groups (usually 1 or 0) */ int *extend, /* O - may FITS file haave extensions? */ int *status) /* IO - error status */ /* Get keywords from the Header of the PRimary array: Check that the keywords conform to the FITS standard and return the parameters which determine the size and structure of the primary array or IMAGE extension. */ { int idummy; LONGLONG lldummy; double ddummy; ffgphd(fptr, maxdim, simple, bitpix, naxis, naxes, pcount, gcount, extend, &ddummy, &ddummy, &lldummy, &idummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffghtb(fitsfile *fptr, /* I - FITS file pointer */ int maxfield, /* I - maximum no. of columns to read; */ long *naxis1, /* O - length of table row in bytes */ long *naxis2, /* O - number of rows in the table */ int *tfields, /* O - number of columns in the table */ char **ttype, /* O - name of each column */ long *tbcol, /* O - byte offset in row to each column */ char **tform, /* O - value of TFORMn keyword for each column */ char **tunit, /* O - value of TUNITn keyword for each column */ char *extnm, /* O - value of EXTNAME keyword, if any */ int *status) /* IO - error status */ /* Get keywords from the Header of the ASCII TaBle: Check that the keywords conform to the FITS standard and return the parameters which describe the table. */ { int ii, maxf, nfound, tstatus; long fields; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xtension[FLEN_VALUE], message[FLEN_ERRMSG]; LONGLONG llnaxis1, llnaxis2, pcount; if (*status > 0) return(*status); /* read the first keyword of the extension */ ffgkyn(fptr, 1, name, value, comm, status); if (!strcmp(name, "XTENSION")) { if (ffc2s(value, xtension, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } /* allow the quoted string value to begin in any column and */ /* allow any number of trailing blanks before the closing quote */ if ( (value[0] != '\'') || /* first char must be a quote */ ( strcmp(xtension, "TABLE") ) ) { snprintf(message, FLEN_ERRMSG, "This is not a TABLE extension: %s", value); ffpmsg(message); return(*status = NOT_ATABLE); } } else /* error: 1st keyword of extension != XTENSION */ { snprintf(message, FLEN_ERRMSG, "First keyword of the extension is not XTENSION: %s", name); ffpmsg(message); return(*status = NO_XTENSION); } if (ffgttb(fptr, &llnaxis1, &llnaxis2, &pcount, &fields, status) > 0) return(*status); if (naxis1) *naxis1 = (long) llnaxis1; if (naxis2) *naxis2 = (long) llnaxis2; if (pcount != 0) { snprintf(message, FLEN_ERRMSG, "PCOUNT = %.0f is illegal in ASCII table; must = 0", (double) pcount); ffpmsg(message); return(*status = BAD_PCOUNT); } if (tfields) *tfields = fields; if (maxfield < 0) maxf = fields; else maxf = minvalue(maxfield, fields); if (maxf > 0) { for (ii = 0; ii < maxf; ii++) { /* initialize optional keyword values */ if (ttype) *ttype[ii] = '\0'; if (tunit) *tunit[ii] = '\0'; } if (ttype) ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status); if (tunit) ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status); if (*status > 0) return(*status); if (tbcol) { ffgknj(fptr, "TBCOL", 1, maxf, tbcol, &nfound, status); if (*status > 0 || nfound != maxf) { ffpmsg( "Required TBCOL keyword(s) not found in ASCII table header (ffghtb)."); return(*status = NO_TBCOL); } } if (tform) { ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status); if (*status > 0 || nfound != maxf) { ffpmsg( "Required TFORM keyword(s) not found in ASCII table header (ffghtb)."); return(*status = NO_TFORM); } } } if (extnm) { extnm[0] = '\0'; tstatus = *status; ffgkys(fptr, "EXTNAME", extnm, comm, status); if (*status == KEY_NO_EXIST) *status = tstatus; /* keyword not required, so ignore error */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffghtbll(fitsfile *fptr, /* I - FITS file pointer */ int maxfield, /* I - maximum no. of columns to read; */ LONGLONG *naxis1, /* O - length of table row in bytes */ LONGLONG *naxis2, /* O - number of rows in the table */ int *tfields, /* O - number of columns in the table */ char **ttype, /* O - name of each column */ LONGLONG *tbcol, /* O - byte offset in row to each column */ char **tform, /* O - value of TFORMn keyword for each column */ char **tunit, /* O - value of TUNITn keyword for each column */ char *extnm, /* O - value of EXTNAME keyword, if any */ int *status) /* IO - error status */ /* Get keywords from the Header of the ASCII TaBle: Check that the keywords conform to the FITS standard and return the parameters which describe the table. */ { int ii, maxf, nfound, tstatus; long fields; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xtension[FLEN_VALUE], message[FLEN_ERRMSG]; LONGLONG llnaxis1, llnaxis2, pcount; if (*status > 0) return(*status); /* read the first keyword of the extension */ ffgkyn(fptr, 1, name, value, comm, status); if (!strcmp(name, "XTENSION")) { if (ffc2s(value, xtension, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } /* allow the quoted string value to begin in any column and */ /* allow any number of trailing blanks before the closing quote */ if ( (value[0] != '\'') || /* first char must be a quote */ ( strcmp(xtension, "TABLE") ) ) { snprintf(message, FLEN_ERRMSG, "This is not a TABLE extension: %s", value); ffpmsg(message); return(*status = NOT_ATABLE); } } else /* error: 1st keyword of extension != XTENSION */ { snprintf(message, FLEN_ERRMSG, "First keyword of the extension is not XTENSION: %s", name); ffpmsg(message); return(*status = NO_XTENSION); } if (ffgttb(fptr, &llnaxis1, &llnaxis2, &pcount, &fields, status) > 0) return(*status); if (naxis1) *naxis1 = llnaxis1; if (naxis2) *naxis2 = llnaxis2; if (pcount != 0) { snprintf(message, FLEN_ERRMSG, "PCOUNT = %.0f is illegal in ASCII table; must = 0", (double) pcount); ffpmsg(message); return(*status = BAD_PCOUNT); } if (tfields) *tfields = fields; if (maxfield < 0) maxf = fields; else maxf = minvalue(maxfield, fields); if (maxf > 0) { for (ii = 0; ii < maxf; ii++) { /* initialize optional keyword values */ if (ttype) *ttype[ii] = '\0'; if (tunit) *tunit[ii] = '\0'; } if (ttype) ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status); if (tunit) ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status); if (*status > 0) return(*status); if (tbcol) { ffgknjj(fptr, "TBCOL", 1, maxf, tbcol, &nfound, status); if (*status > 0 || nfound != maxf) { ffpmsg( "Required TBCOL keyword(s) not found in ASCII table header (ffghtbll)."); return(*status = NO_TBCOL); } } if (tform) { ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status); if (*status > 0 || nfound != maxf) { ffpmsg( "Required TFORM keyword(s) not found in ASCII table header (ffghtbll)."); return(*status = NO_TFORM); } } } if (extnm) { extnm[0] = '\0'; tstatus = *status; ffgkys(fptr, "EXTNAME", extnm, comm, status); if (*status == KEY_NO_EXIST) *status = tstatus; /* keyword not required, so ignore error */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffghbn(fitsfile *fptr, /* I - FITS file pointer */ int maxfield, /* I - maximum no. of columns to read; */ long *naxis2, /* O - number of rows in the table */ int *tfields, /* O - number of columns in the table */ char **ttype, /* O - name of each column */ char **tform, /* O - TFORMn value for each column */ char **tunit, /* O - TUNITn value for each column */ char *extnm, /* O - value of EXTNAME keyword, if any */ long *pcount, /* O - value of PCOUNT keyword */ int *status) /* IO - error status */ /* Get keywords from the Header of the BiNary table: Check that the keywords conform to the FITS standard and return the parameters which describe the table. */ { int ii, maxf, nfound, tstatus; long fields; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xtension[FLEN_VALUE], message[FLEN_ERRMSG]; LONGLONG naxis1ll, naxis2ll, pcountll; if (*status > 0) return(*status); /* read the first keyword of the extension */ ffgkyn(fptr, 1, name, value, comm, status); if (!strcmp(name, "XTENSION")) { if (ffc2s(value, xtension, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } /* allow the quoted string value to begin in any column and */ /* allow any number of trailing blanks before the closing quote */ if ( (value[0] != '\'') || /* first char must be a quote */ ( strcmp(xtension, "BINTABLE") && strcmp(xtension, "A3DTABLE") && strcmp(xtension, "3DTABLE") ) ) { snprintf(message, FLEN_ERRMSG, "This is not a BINTABLE extension: %s", value); ffpmsg(message); return(*status = NOT_BTABLE); } } else /* error: 1st keyword of extension != XTENSION */ { snprintf(message, FLEN_ERRMSG, "First keyword of the extension is not XTENSION: %s", name); ffpmsg(message); return(*status = NO_XTENSION); } if (ffgttb(fptr, &naxis1ll, &naxis2ll, &pcountll, &fields, status) > 0) return(*status); if (naxis2) *naxis2 = (long) naxis2ll; if (pcount) *pcount = (long) pcountll; if (tfields) *tfields = fields; if (maxfield < 0) maxf = fields; else maxf = minvalue(maxfield, fields); if (maxf > 0) { for (ii = 0; ii < maxf; ii++) { /* initialize optional keyword values */ if (ttype) *ttype[ii] = '\0'; if (tunit) *tunit[ii] = '\0'; } if (ttype) ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status); if (tunit) ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status); if (*status > 0) return(*status); if (tform) { ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status); if (*status > 0 || nfound != maxf) { ffpmsg( "Required TFORM keyword(s) not found in binary table header (ffghbn)."); return(*status = NO_TFORM); } } } if (extnm) { extnm[0] = '\0'; tstatus = *status; ffgkys(fptr, "EXTNAME", extnm, comm, status); if (*status == KEY_NO_EXIST) *status = tstatus; /* keyword not required, so ignore error */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffghbnll(fitsfile *fptr, /* I - FITS file pointer */ int maxfield, /* I - maximum no. of columns to read; */ LONGLONG *naxis2, /* O - number of rows in the table */ int *tfields, /* O - number of columns in the table */ char **ttype, /* O - name of each column */ char **tform, /* O - TFORMn value for each column */ char **tunit, /* O - TUNITn value for each column */ char *extnm, /* O - value of EXTNAME keyword, if any */ LONGLONG *pcount, /* O - value of PCOUNT keyword */ int *status) /* IO - error status */ /* Get keywords from the Header of the BiNary table: Check that the keywords conform to the FITS standard and return the parameters which describe the table. */ { int ii, maxf, nfound, tstatus; long fields; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xtension[FLEN_VALUE], message[FLEN_ERRMSG]; LONGLONG naxis1ll, naxis2ll, pcountll; if (*status > 0) return(*status); /* read the first keyword of the extension */ ffgkyn(fptr, 1, name, value, comm, status); if (!strcmp(name, "XTENSION")) { if (ffc2s(value, xtension, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } /* allow the quoted string value to begin in any column and */ /* allow any number of trailing blanks before the closing quote */ if ( (value[0] != '\'') || /* first char must be a quote */ ( strcmp(xtension, "BINTABLE") && strcmp(xtension, "A3DTABLE") && strcmp(xtension, "3DTABLE") ) ) { snprintf(message, FLEN_ERRMSG, "This is not a BINTABLE extension: %s", value); ffpmsg(message); return(*status = NOT_BTABLE); } } else /* error: 1st keyword of extension != XTENSION */ { snprintf(message, FLEN_ERRMSG, "First keyword of the extension is not XTENSION: %s", name); ffpmsg(message); return(*status = NO_XTENSION); } if (ffgttb(fptr, &naxis1ll, &naxis2ll, &pcountll, &fields, status) > 0) return(*status); if (naxis2) *naxis2 = naxis2ll; if (pcount) *pcount = pcountll; if (tfields) *tfields = fields; if (maxfield < 0) maxf = fields; else maxf = minvalue(maxfield, fields); if (maxf > 0) { for (ii = 0; ii < maxf; ii++) { /* initialize optional keyword values */ if (ttype) *ttype[ii] = '\0'; if (tunit) *tunit[ii] = '\0'; } if (ttype) ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status); if (tunit) ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status); if (*status > 0) return(*status); if (tform) { ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status); if (*status > 0 || nfound != maxf) { ffpmsg( "Required TFORM keyword(s) not found in binary table header (ffghbn)."); return(*status = NO_TFORM); } } } if (extnm) { extnm[0] = '\0'; tstatus = *status; ffgkys(fptr, "EXTNAME", extnm, comm, status); if (*status == KEY_NO_EXIST) *status = tstatus; /* keyword not required, so ignore error */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffgphd(fitsfile *fptr, /* I - FITS file pointer */ int maxdim, /* I - maximum no. of dimensions to read; */ int *simple, /* O - does file conform to FITS standard? 1/0 */ int *bitpix, /* O - number of bits per data value pixel */ int *naxis, /* O - number of axes in the data array */ LONGLONG naxes[], /* O - length of each data axis */ long *pcount, /* O - number of group parameters (usually 0) */ long *gcount, /* O - number of random groups (usually 1 or 0) */ int *extend, /* O - may FITS file haave extensions? */ double *bscale, /* O - array pixel linear scaling factor */ double *bzero, /* O - array pixel linear scaling zero point */ LONGLONG *blank, /* O - value used to represent undefined pixels */ int *nspace, /* O - number of blank keywords prior to END */ int *status) /* IO - error status */ { /* Get the Primary HeaDer parameters. Check that the keywords conform to the FITS standard and return the parameters which determine the size and structure of the primary array or IMAGE extension. */ int unknown, found_end, tstatus, ii, nextkey, namelen; long longbitpix, longnaxis; LONGLONG axislen; char message[FLEN_ERRMSG], keyword[FLEN_KEYWORD]; char card[FLEN_CARD]; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xtension[FLEN_VALUE]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (simple) *simple = 1; unknown = 0; /*--------------------------------------------------------------------*/ /* Get 1st keyword of HDU and test whether it is SIMPLE or XTENSION */ /*--------------------------------------------------------------------*/ ffgkyn(fptr, 1, name, value, comm, status); if ((fptr->Fptr)->curhdu == 0) /* Is this the beginning of the FITS file? */ { if (!strcmp(name, "SIMPLE")) { if (value[0] == 'F') { if (simple) *simple=0; /* not a simple FITS file */ } else if (value[0] != 'T') return(*status = BAD_SIMPLE); } else { snprintf(message, FLEN_ERRMSG, "First keyword of the file is not SIMPLE: %s", name); ffpmsg(message); return(*status = NO_SIMPLE); } } else /* not beginning of the file, so presumably an IMAGE extension */ { /* or it could be a compressed image in a binary table */ if (!strcmp(name, "XTENSION")) { if (ffc2s(value, xtension, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } /* allow the quoted string value to begin in any column and */ /* allow any number of trailing blanks before the closing quote */ if ( (value[0] != '\'') || /* first char must be a quote */ ( strcmp(xtension, "IMAGE") && strcmp(xtension, "IUEIMAGE") ) ) { unknown = 1; /* unknown type of extension; press on anyway */ snprintf(message, FLEN_ERRMSG, "This is not an IMAGE extension: %s", value); ffpmsg(message); } } else /* error: 1st keyword of extension != XTENSION */ { snprintf(message, FLEN_ERRMSG, "First keyword of the extension is not XTENSION: %s", name); ffpmsg(message); return(*status = NO_XTENSION); } } if (unknown && (fptr->Fptr)->compressimg) { /* this is a compressed image, so read ZBITPIX, ZNAXIS keywords */ unknown = 0; /* reset flag */ ffxmsg(3, message); /* clear previous spurious error message */ if (bitpix) { ffgidt(fptr, bitpix, status); /* get bitpix value */ if (*status > 0) { ffpmsg("Error reading BITPIX value of compressed image"); return(*status); } } if (naxis) { ffgidm(fptr, naxis, status); /* get NAXIS value */ if (*status > 0) { ffpmsg("Error reading NAXIS value of compressed image"); return(*status); } } if (naxes) { ffgiszll(fptr, maxdim, naxes, status); /* get NAXISn value */ if (*status > 0) { ffpmsg("Error reading NAXISn values of compressed image"); return(*status); } } nextkey = 9; /* skip required table keywords in the following search */ } else { /*----------------------------------------------------------------*/ /* Get 2nd keyword; test whether it is BITPIX with legal value */ /*----------------------------------------------------------------*/ ffgkyn(fptr, 2, name, value, comm, status); /* BITPIX = 2nd keyword */ if (strcmp(name, "BITPIX")) { snprintf(message, FLEN_ERRMSG, "Second keyword of the extension is not BITPIX: %s", name); ffpmsg(message); return(*status = NO_BITPIX); } if (ffc2ii(value, &longbitpix, status) > 0) { snprintf(message, FLEN_ERRMSG, "Value of BITPIX keyword is not an integer: %s", value); ffpmsg(message); return(*status = BAD_BITPIX); } else if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG && longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG) { snprintf(message, FLEN_ERRMSG, "Illegal value for BITPIX keyword: %s", value); ffpmsg(message); return(*status = BAD_BITPIX); } if (bitpix) *bitpix = longbitpix; /* do explicit type conversion */ /*---------------------------------------------------------------*/ /* Get 3rd keyword; test whether it is NAXIS with legal value */ /*---------------------------------------------------------------*/ ffgtkn(fptr, 3, "NAXIS", &longnaxis, status); if (*status == BAD_ORDER) return(*status = NO_NAXIS); else if (*status == NOT_POS_INT || longnaxis > 999) { snprintf(message,FLEN_ERRMSG,"NAXIS = %ld is illegal", longnaxis); ffpmsg(message); return(*status = BAD_NAXIS); } else if (naxis) *naxis = longnaxis; /* do explicit type conversion */ /*---------------------------------------------------------*/ /* Get the next NAXISn keywords and test for legal values */ /*---------------------------------------------------------*/ for (ii=0, nextkey=4; ii < longnaxis; ii++, nextkey++) { ffkeyn("NAXIS", ii+1, keyword, status); ffgtknjj(fptr, 4+ii, keyword, &axislen, status); if (*status == BAD_ORDER) return(*status = NO_NAXES); else if (*status == NOT_POS_INT) return(*status = BAD_NAXES); else if (ii < maxdim) if (naxes) naxes[ii] = axislen; } } /*---------------------------------------------------------*/ /* now look for other keywords of interest: */ /* BSCALE, BZERO, BLANK, PCOUNT, GCOUNT, EXTEND, and END */ /*---------------------------------------------------------*/ /* initialize default values in case keyword is not present */ if (bscale) *bscale = 1.0; if (bzero) *bzero = 0.0; if (pcount) *pcount = 0; if (gcount) *gcount = 1; if (extend) *extend = 0; if (blank) *blank = NULL_UNDEFINED; /* no default null value for BITPIX=8,16,32 */ *nspace = 0; found_end = 0; tstatus = *status; for (; !found_end; nextkey++) { /* get next keyword */ /* don't use ffgkyn here because it trys to parse the card to read */ /* the value string, thus failing to read the file just because of */ /* minor syntax errors in optional keywords. */ if (ffgrec(fptr, nextkey, card, status) > 0 ) /* get the 80-byte card */ { if (*status == KEY_OUT_BOUNDS) { found_end = 1; /* simply hit the end of the header */ *status = tstatus; /* reset error status */ } else { ffpmsg("Failed to find the END keyword in header (ffgphd)."); } } else /* got the next keyword without error */ { ffgknm(card, name, &namelen, status); /* get the keyword name */ if (fftrec(name, status) > 0) /* test keyword name; catches no END */ { snprintf(message, FLEN_ERRMSG, "Name of keyword no. %d contains illegal character(s): %s", nextkey, name); ffpmsg(message); if (nextkey % 36 == 0) /* test if at beginning of 36-card record */ ffpmsg(" (This may indicate a missing END keyword)."); } if (!strcmp(name, "BSCALE") && bscale) { *nspace = 0; /* reset count of blank keywords */ ffpsvc(card, value, comm, status); /* parse value and comment */ if (ffc2dd(value, bscale, status) > 0) /* convert to double */ { /* reset error status and continue, but still issue warning */ *status = tstatus; *bscale = 1.0; snprintf(message, FLEN_ERRMSG, "Error reading BSCALE keyword value as a double: %s", value); ffpmsg(message); } } else if (!strcmp(name, "BZERO") && bzero) { *nspace = 0; /* reset count of blank keywords */ ffpsvc(card, value, comm, status); /* parse value and comment */ if (ffc2dd(value, bzero, status) > 0) /* convert to double */ { /* reset error status and continue, but still issue warning */ *status = tstatus; *bzero = 0.0; snprintf(message, FLEN_ERRMSG, "Error reading BZERO keyword value as a double: %s", value); ffpmsg(message); } } else if (!strcmp(name, "BLANK") && blank) { *nspace = 0; /* reset count of blank keywords */ ffpsvc(card, value, comm, status); /* parse value and comment */ if (ffc2jj(value, blank, status) > 0) /* convert to LONGLONG */ { /* reset error status and continue, but still issue warning */ *status = tstatus; *blank = NULL_UNDEFINED; snprintf(message, FLEN_ERRMSG, "Error reading BLANK keyword value as an integer: %s", value); ffpmsg(message); } } else if (!strcmp(name, "PCOUNT") && pcount) { *nspace = 0; /* reset count of blank keywords */ ffpsvc(card, value, comm, status); /* parse value and comment */ if (ffc2ii(value, pcount, status) > 0) /* convert to long */ { snprintf(message, FLEN_ERRMSG, "Error reading PCOUNT keyword value as an integer: %s", value); ffpmsg(message); } } else if (!strcmp(name, "GCOUNT") && gcount) { *nspace = 0; /* reset count of blank keywords */ ffpsvc(card, value, comm, status); /* parse value and comment */ if (ffc2ii(value, gcount, status) > 0) /* convert to long */ { snprintf(message, FLEN_ERRMSG, "Error reading GCOUNT keyword value as an integer: %s", value); ffpmsg(message); } } else if (!strcmp(name, "EXTEND") && extend) { *nspace = 0; /* reset count of blank keywords */ ffpsvc(card, value, comm, status); /* parse value and comment */ if (ffc2ll(value, extend, status) > 0) /* convert to logical */ { /* reset error status and continue, but still issue warning */ *status = tstatus; *extend = 0; snprintf(message, FLEN_ERRMSG, "Error reading EXTEND keyword value as a logical: %s", value); ffpmsg(message); } } else if (!strcmp(name, "END")) found_end = 1; else if (!card[0] ) *nspace = *nspace + 1; /* this is a blank card in the header */ else *nspace = 0; /* reset count of blank keywords immediately before the END keyword to zero */ } if (*status > 0) /* exit on error after writing error message */ { if ((fptr->Fptr)->curhdu == 0) ffpmsg( "Failed to read the required primary array header keywords."); else ffpmsg( "Failed to read the required image extension header keywords."); return(*status); } } if (unknown) *status = NOT_IMAGE; return(*status); } /*--------------------------------------------------------------------------*/ int ffgttb(fitsfile *fptr, /* I - FITS file pointer*/ LONGLONG *rowlen, /* O - length of a table row, in bytes */ LONGLONG *nrows, /* O - number of rows in the table */ LONGLONG *pcount, /* O - value of PCOUNT keyword */ long *tfields, /* O - number of fields in the table */ int *status) /* IO - error status */ { /* Get and Test TaBle; Test that this is a legal ASCII or binary table and get some keyword values. We assume that the calling routine has already tested the 1st keyword of the extension to ensure that this is really a table extension. */ if (*status > 0) return(*status); if (fftkyn(fptr, 2, "BITPIX", "8", status) == BAD_ORDER) /* 2nd keyword */ return(*status = NO_BITPIX); /* keyword not BITPIX */ else if (*status == NOT_POS_INT) return(*status = BAD_BITPIX); /* value != 8 */ if (fftkyn(fptr, 3, "NAXIS", "2", status) == BAD_ORDER) /* 3rd keyword */ return(*status = NO_NAXIS); /* keyword not NAXIS */ else if (*status == NOT_POS_INT) return(*status = BAD_NAXIS); /* value != 2 */ if (ffgtknjj(fptr, 4, "NAXIS1", rowlen, status) == BAD_ORDER) /* 4th key */ return(*status = NO_NAXES); /* keyword not NAXIS1 */ else if (*status == NOT_POS_INT) return(*status == BAD_NAXES); /* bad NAXIS1 value */ if (ffgtknjj(fptr, 5, "NAXIS2", nrows, status) == BAD_ORDER) /* 5th key */ return(*status = NO_NAXES); /* keyword not NAXIS2 */ else if (*status == NOT_POS_INT) return(*status == BAD_NAXES); /* bad NAXIS2 value */ if (ffgtknjj(fptr, 6, "PCOUNT", pcount, status) == BAD_ORDER) /* 6th key */ return(*status = NO_PCOUNT); /* keyword not PCOUNT */ else if (*status == NOT_POS_INT) return(*status = BAD_PCOUNT); /* bad PCOUNT value */ if (fftkyn(fptr, 7, "GCOUNT", "1", status) == BAD_ORDER) /* 7th keyword */ return(*status = NO_GCOUNT); /* keyword not GCOUNT */ else if (*status == NOT_POS_INT) return(*status = BAD_GCOUNT); /* value != 1 */ if (ffgtkn(fptr, 8, "TFIELDS", tfields, status) == BAD_ORDER) /* 8th key*/ return(*status = NO_TFIELDS); /* keyword not TFIELDS */ else if (*status == NOT_POS_INT || *tfields > 999) return(*status == BAD_TFIELDS); /* bad TFIELDS value */ if (*status > 0) ffpmsg( "Error reading required keywords in the table header (FTGTTB)."); return(*status); } /*--------------------------------------------------------------------------*/ int ffgtkn(fitsfile *fptr, /* I - FITS file pointer */ int numkey, /* I - number of the keyword to read */ char *name, /* I - expected name of the keyword */ long *value, /* O - integer value of the keyword */ int *status) /* IO - error status */ { /* test that keyword number NUMKEY has the expected name and get the integer value of the keyword. Return an error if the keyword name does not match the input name, or if the value of the keyword is not a positive integer. */ char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE]; char comm[FLEN_COMMENT], message[FLEN_ERRMSG]; if (*status > 0) return(*status); keyname[0] = '\0'; valuestring[0] = '\0'; if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0) { if (strcmp(keyname, name) ) *status = BAD_ORDER; /* incorrect keyword name */ else { ffc2ii(valuestring, value, status); /* convert to integer */ if (*status > 0 || *value < 0 ) *status = NOT_POS_INT; } if (*status > 0) { snprintf(message, FLEN_ERRMSG, "ffgtkn found unexpected keyword or value for keyword no. %d.", numkey); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Expected positive integer keyword %s, but instead", name); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " found keyword %s with value %s", keyname, valuestring); ffpmsg(message); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgtknjj(fitsfile *fptr, /* I - FITS file pointer */ int numkey, /* I - number of the keyword to read */ char *name, /* I - expected name of the keyword */ LONGLONG *value, /* O - integer value of the keyword */ int *status) /* IO - error status */ { /* test that keyword number NUMKEY has the expected name and get the integer value of the keyword. Return an error if the keyword name does not match the input name, or if the value of the keyword is not a positive integer. */ char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE]; char comm[FLEN_COMMENT], message[FLEN_ERRMSG]; if (*status > 0) return(*status); keyname[0] = '\0'; valuestring[0] = '\0'; if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0) { if (strcmp(keyname, name) ) *status = BAD_ORDER; /* incorrect keyword name */ else { ffc2jj(valuestring, value, status); /* convert to integer */ if (*status > 0 || *value < 0 ) *status = NOT_POS_INT; } if (*status > 0) { snprintf(message, FLEN_ERRMSG, "ffgtknjj found unexpected keyword or value for keyword no. %d.", numkey); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Expected positive integer keyword %s, but instead", name); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " found keyword %s with value %s", keyname, valuestring); ffpmsg(message); } } return(*status); } /*--------------------------------------------------------------------------*/ int fftkyn(fitsfile *fptr, /* I - FITS file pointer */ int numkey, /* I - number of the keyword to read */ char *name, /* I - expected name of the keyword */ char *value, /* I - expected value of the keyword */ int *status) /* IO - error status */ { /* test that keyword number NUMKEY has the expected name and the expected value string. */ char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE]; char comm[FLEN_COMMENT], message[FLEN_ERRMSG]; if (*status > 0) return(*status); keyname[0] = '\0'; valuestring[0] = '\0'; if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0) { if (strcmp(keyname, name) ) *status = BAD_ORDER; /* incorrect keyword name */ if (strcmp(value, valuestring) ) *status = NOT_POS_INT; /* incorrect keyword value */ } if (*status > 0) { snprintf(message, FLEN_ERRMSG, "fftkyn found unexpected keyword or value for keyword no. %d.", numkey); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Expected keyword %s with value %s, but", name, value); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " found keyword %s with value %s", keyname, valuestring); ffpmsg(message); } return(*status); } /*--------------------------------------------------------------------------*/ int ffh2st(fitsfile *fptr, /* I - FITS file pointer */ char **header, /* O - returned header string */ int *status) /* IO - error status */ /* read header keywords into a long string of chars. This routine allocates memory for the string, so the calling routine must eventually free the memory when it is not needed any more. */ { int nkeys; long nrec; LONGLONG headstart; if (*status > 0) return(*status); /* get number of keywords in the header (doesn't include END) */ if (ffghsp(fptr, &nkeys, NULL, status) > 0) return(*status); nrec = (nkeys / 36 + 1); /* allocate memory for all the keywords (multiple of 2880 bytes) */ *header = (char *) calloc ( nrec * 2880 + 1, 1); if (!(*header)) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory to hold all the header keywords"); return(*status); } ffghadll(fptr, &headstart, NULL, NULL, status); /* get header address */ ffmbyt(fptr, headstart, REPORT_EOF, status); /* move to header */ ffgbyt(fptr, nrec * 2880, *header, status); /* copy header */ *(*header + (nrec * 2880)) = '\0'; return(*status); } /*--------------------------------------------------------------------------*/ int ffhdr2str( fitsfile *fptr, /* I - FITS file pointer */ int exclude_comm, /* I - if TRUE, exclude commentary keywords */ char **exclist, /* I - list of excluded keyword names */ int nexc, /* I - number of names in exclist */ char **header, /* O - returned header string */ int *nkeys, /* O - returned number of 80-char keywords */ int *status) /* IO - error status */ /* read header keywords into a long string of chars. This routine allocates memory for the string, so the calling routine must eventually free the memory when it is not needed any more. If exclude_comm is TRUE, then all the COMMENT, HISTORY, and keywords will be excluded from the output string of keywords. Any other list of keywords to be excluded may be specified with the exclist parameter. */ { int casesn, match, exact, totkeys; long ii, jj; char keybuf[162], keyname[FLEN_KEYWORD], *headptr; *nkeys = 0; if (*status > 0) return(*status); /* get number of keywords in the header (doesn't include END) */ if (ffghsp(fptr, &totkeys, NULL, status) > 0) return(*status); /* allocate memory for all the keywords */ /* (will reallocate it later to minimize the memory size) */ *header = (char *) calloc ( (totkeys + 1) * 80 + 1, 1); if (!(*header)) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory to hold all the header keywords"); return(*status); } headptr = *header; casesn = FALSE; /* read every keyword */ for (ii = 1; ii <= totkeys; ii++) { ffgrec(fptr, ii, keybuf, status); /* pad record with blanks so that it is at least 80 chars long */ strcat(keybuf, " "); keyname[0] = '\0'; strncat(keyname, keybuf, 8); /* copy the keyword name */ if (exclude_comm) { if (!FSTRCMP("COMMENT ", keyname) || !FSTRCMP("HISTORY ", keyname) || !FSTRCMP(" ", keyname) ) continue; /* skip this commentary keyword */ } /* does keyword match any names in the exclusion list? */ for (jj = 0; jj < nexc; jj++ ) { ffcmps(exclist[jj], keyname, casesn, &match, &exact); if (match) break; } if (jj == nexc) { /* not in exclusion list, add this keyword to the string */ strcpy(headptr, keybuf); headptr += 80; (*nkeys)++; } } /* add the END keyword */ strcpy(headptr, "END "); headptr += 80; (*nkeys)++; *headptr = '\0'; /* terminate the header string */ /* minimize the allocated memory */ *header = (char *) realloc(*header, (*nkeys *80) + 1); return(*status); } /*--------------------------------------------------------------------------*/ int ffcnvthdr2str( fitsfile *fptr, /* I - FITS file pointer */ int exclude_comm, /* I - if TRUE, exclude commentary keywords */ char **exclist, /* I - list of excluded keyword names */ int nexc, /* I - number of names in exclist */ char **header, /* O - returned header string */ int *nkeys, /* O - returned number of 80-char keywords */ int *status) /* IO - error status */ /* Same as ffhdr2str, except that if the input HDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of a normal uncompressed FITS image before concatenating the header keyword records. */ { fitsfile *tempfptr; if (*status > 0) return(*status); if (fits_is_compressed_image(fptr, status) ) { /* this is a tile compressed image, so need to make an uncompressed */ /* copy of the image header in memory before concatenating the keywords */ if (fits_create_file(&tempfptr, "mem://", status) > 0) { return(*status); } if (fits_img_decompress_header(fptr, tempfptr, status) > 0) { fits_delete_file(tempfptr, status); return(*status); } ffhdr2str(tempfptr, exclude_comm, exclist, nexc, header, nkeys, status); fits_close_file(tempfptr, status); } else { ffhdr2str(fptr, exclude_comm, exclist, nexc, header, nkeys, status); } return(*status); } cfitsio-4.3.1/testf77.out0000644000225700000360000010122313472024437014506 0ustar cagordonlhea FITSIO TESTPROG Try opening then closing a nonexistent file: ftopen iunit, status (expect an error) = 15 104 ftclos status = 104 ftinit create new file status = 0 test writing of long string keywords: 123456789012345678901234567890123456789012345678901234567890123456789012345 '12345678901234567890123456789012345678901234567890123456789012345678' 1234567890123456789012345678901234567890123456789012345678901234'6789012345 '1234567890123456789012345678901234567890123456789012345678901234''67' 1234567890123456789012345678901234567890123456789012345678901234''789012345 '1234567890123456789012345678901234567890123456789012345678901234''''' 1234567890123456789012345678901234567890123456789012345678901234567'9012345 '1234567890123456789012345678901234567890123456789012345678901234567' Wrote all Keywords successfully ftflus status = 0 HDU number = 1 Values read back from primary array (99 = null pixel) The 1st, and every 4th pixel should be undefined: 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 T (ftgpvb) 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 T (ftgpvi) 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 T (ftgpvj) 99. 2. 3.99. 5. 6. 7.99. 9.10.11.99.13.14.15.99.17.18.19.99. T (ftgpve) 99. 2. 3.99. 5. 6. 7.99. 9.10.11.99.13.14.15.99.17.18.19.99. T (ftgpvd) 0 2 3 0 5 6 7 0 9 10 11 0 13 14 15 0 17 18 19 0 T (ftgpfb) 0 2 3 0 5 6 7 0 9 10 11 0 13 14 15 0 17 18 19 0 T (ftgpfi) 0 2 3 0 5 6 7 0 9 10 11 0 13 14 15 0 17 18 19 0 T (ftgpfj) 0. 2. 3. 0. 5. 6. 7. 0. 9.10.11. 0.13.14.15. 0.17.18.19. 0. T (ftgpfe) 0. 2. 3. 0. 5. 6. 7. 0. 9.10.11. 0.13.14.15. 0.17.18.19. 0. T (ftgpfd) Closed then reopened the FITS file 10 times. HDU number = 1 Read back keywords: simple, bitpix, naxis, naxes = T 32 2 10 2 pcount, gcount, extend = 0 1 T KEY_PREC= 'This keyword was written by fxprec' / comment goes here KEY_PREC 'This keyword was written by fxprec comment goes here KEY_PREC= 'This keyword was written by fxprec' / comment goes here KY_PKNS1 :'first string' :fxpkns comment KEY_PKYS :value_string :fxpkys comment 0 KEY_PKYL : T:fxpkyl comment 0 KEY_PKYJ : 11:fxpkyj comment 0 KEY_PKYE : 11.00000:fxpkyj comment 0 KEY_PKYD : 11.00000:fxpkyj comment 0 KEY_PKYS :value_string :fxpkys comment 0 KEY_PKYL : T:fxpkyl comment 0 KEY_PKYJ : 11:fxpkyj comment 0 KEY_PKYE : 13.13131:fxpkye comment 0 KEY_PKYD : 15.15152:fxpkyd comment 0 KEY_PKYF : 12.12121:fxpkyf comment 0 KEY_PKYE : 13.13131:fxpkye comment 0 KEY_PKYG : 14.141414141414:fxpkyg comment 0 KEY_PKYD : 15.151515151515:fxpkyd comment 0 KEY_PKYT : 12345678:0.12345678901235fxpkyt comment 0 KEY_PKYJ : 11:[km/s/Mpc] fxpkyj comment 0 keyword unit=km/s/Mpc KEY_PKYJ : 11:fxpkyj comment 0 keyword unit= KEY_PKYJ : 11:[feet/second/second] fxpkyj comment 0 keyword unit=feet/second/second KEY_PKLS long string value = This is a very long string value that is continued over more than one keyword. header contains 61 keywords; located at keyword 23 ftgkns: first string second string ftgknl: T F T ftgknj: 11 12 13 ftgkne: 13.13131 14.14141 15.15152 ftgknd: 15.15152 16.16162 17.17172 Before deleting the HISTORY and DATE keywords... COMMENT HISTORY DATE KY_PKNS1 After deleting the keywords... COMMENT This keyword was written by fxpcom. KY_PKNS1= 'first string' / fxpkns comment After inserting the keywords... COMMENT continued over multiple keywords. The HEASARC convention uses the & KY_IREC = 'This keyword inserted by fxirec' KY_IKYS = 'insert_value_string' / ikys comment KY_IKYJ = 49 / ikyj comment KY_IKYL = T / ikyl comment KY_IKYE = 1.2346E+01 / ikye comment KY_IKYD = 1.23456789012346E+01 / ikyd comment KY_IKYF = 12.3456 / ikyf comment KY_IKYG = 12.3456789012346 / ikyg comment COMMENT character at the end of each substring which is then continued After modifying the keywords... COMMENT This keyword was modified by fxmrec KY_MREC = 'This keyword was modified by fxmcrd' NEWIKYS = 'modified_string' / ikys comment KY_IKYJ = 50 / This is a modified comment KY_IKYL = F / ikyl comment KY_IKYE = -1.2346E+01 / ikye comment KY_IKYD = -1.23456789012346E+01 / modified comment KY_IKYF = -12.3456 / ikyf comment KY_IKYG = -12.3456789012346 / ikyg comment COMMENT character at the end of each substring which is then continued After updating the keywords... COMMENT This keyword was modified by fxmrec KY_UCRD = 'This keyword was updated by fxucrd' NEWIKYS = 'updated_string' / ikys comment KY_IKYJ = 51 / This is a modified comment KY_IKYL = T / ikyl comment KY_IKYE = -1.3346E+01 / ikye comment KY_IKYD = -1.33456789012346E+01 / modified comment KY_IKYF = -13.3456 / ikyf comment KY_IKYG = -13.3456789012346 / ikyg comment COMMENT character at the end of each substring which is then continued Keywords found using wildcard search (should be 9)... KEY_PKYS= 'value_string' / fxpkys comment KEY_PKYL= T / fxpkyl comment KEY_PKYJ= 11 / [feet/second/second] fxpkyj comment KEY_PKYF= 12.12121 / fxpkyf comment KEY_PKYE= 1.313131E+01 / fxpkye comment KEY_PKYG= 14.14141414141414 / fxpkyg comment KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment NEWIKYS = 'updated_string' / ikys comment KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment ftibin status = 0 HDU number = 2 header contains 33 keywords located at keyword 1 header contains 33 keywords with room for 74 more TDIM3 = (1,2,8) 3 1 2 8 ftpcl_ status = 0 Find the column numbers a returned status value of 237 is expected and indicates that more than one column name matches the input column name template. Status = 219 indicates that there was no matching column name. Column Xvalue is number 3 status = 0 Column Avalue is number 1 status = 237 Column Lvalue is number 2 status = 237 Column Xvalue is number 3 status = 237 Column Bvalue is number 4 status = 237 Column Ivalue is number 5 status = 237 Column Jvalue is number 6 status = 237 Column Evalue is number 7 status = 237 Column Dvalue is number 8 status = 237 Column Cvalue is number 9 status = 237 Column Mvalue is number 10 status = 237 Column is number 0 status = 219 Information about each column: 15A 16 15 15 Avalue A 1.00 0.00 1234554321 1L 14 1 1 Lvalue m**2 L 1.00 0.00 1234554321 16X 1 16 1 Xvalue cm X 1.00 0.00 1234554321 1B 11 1 1 Bvalue erg/s B 1.00 0.00 99 1I 21 1 2 Ivalue km/s I 1.00 0.00 99 1J 41 1 4 Jvalue J 1.00 0.00 99 1E 42 1 4 Evalue E 1.00 0.00 1234554321 1D 82 1 8 Dvalue D 1.00 0.00 1234554321 1C 83 1 8 Cvalue C 1.00 0.00 1234554321 1M 163 1 16 Mvalue M 1.00 0.00 1234554321 ftitab status = 0 HDU number = 2 ftpcl_ status = 0 ASCII table: rowlen, nrows, tfields, extname: 76 11 5 Test-ASCII Name 1 A15 Ivalue 17 I10 m**2 Fvalue 28 F14.6 cm Evalue 43 E12.5 erg/s Dvalue 56 D21.14 km/s Data values read from ASCII table: first string 1 1 1 1. 1. second string 2 2 2 2. 2. 3 3 3 3. 3. UNDEFINED 4 4 4 4. 4. 5 5 5 5. 5. 6 6 6 6. 6. 7 7 7 7. 7. 8 8 8 8. 8. 9 9 9 9. 9. 10 10 10 10.10. 99 99 99 99.99. 1 1.000000 1.00000E+00 1.00000000000000E+00second string Column name is number 1 status = 0 Column Ivalue is number 2 status = 237 Column Fvalue is number 3 status = 237 Column Evalue is number 4 status = 237 Column Dvalue is number 5 status = 237 Column is number 0 status = 219 A15 16 1 15 Name 1 1.00 0.00 null1 I10 41 1 10 Ivalue 17 m**2 1.00 0.00 null2 F14.6 82 1 14 Fvalue 28 cm 1.00 0.00 null3 E12.5 42 1 12 Evalue 43 erg/s 1.00 0.00 null4 D21.14 82 1 21 Dvalue 56 km/s 1.00 0.00 null5 Data values after inserting 3 rows after row 2: first string 1 1 1 1. 1. second string 2 2 2 2. 2. 0 0 0 0. 0. 0 0 0 0. 0. 0 0 0 0. 0. 3 3 3 3. 3. UNDEFINED 4 4 4 4. 4. 5 5 5 5. 5. 6 6 6 6. 6. 7 7 7 7. 7. 8 8 8 8. 8. 9 9 9 9. 9. 10 10 10 10.10. 99 99 99 99.99. Data values after deleting 2 rows at row 10: first string 1 1 1 1. 1. second string 2 2 2 2. 2. 0 0 0 0. 0. 0 0 0 0. 0. 0 0 0 0. 0. 3 3 3 3. 3. UNDEFINED 4 4 4 4. 4. 5 5 5 5. 5. 6 6 6 6. 6. 9 9 9 9. 9. 10 10 10 10.10. 99 99 99 99.99. Data values after deleting column 3: first string 1 1 1. 1. second string 2 2 2. 2. 0 0 0. 0. 0 0 0. 0. 0 0 0. 0. 3 3 3. 3. UNDEFINED 4 4 4. 4. 5 5 5. 5. 6 6 6. 6. 9 9 9. 9. 10 10 10.10. 99 99 99.99. Data values after inserting column 5: first string 1 1 1. 1. 0 second string 2 2 2. 2. 0 0 0 0. 0. 0 0 0 0. 0. 0 0 0 0. 0. 0 3 3 3. 3. 0 UNDEFINED 4 4 4. 4. 0 5 5 5. 5. 0 6 6 6. 6. 0 9 9 9. 9. 0 10 10 10.10. 0 99 99 99.99. 0 HDU number = 3 Moved to binary table header contains 37 keywords with room for 70 more Binary table: nrows, tfields, extname, pcount: 21 10Test-BINTABLE 0 Avalue 15A Lvalue 1L m**2 Xvalue 16X cm Bvalue 1B erg/s Ivalue 1I km/s Jvalue 1J Evalue 1E Dvalue 1D Cvalue 1C Mvalue 1M Data values read from binary table: Bit column (X) data values: FTFFTTFF FTTTFFFF TTTTFFFF FTTTTTFF FFFFFFFF null string column value (should be blank): Read columns with ftgcv_: first string F 76 1 1 1 1. 1. 1. -2. 1. -2. second string T 112 2 2 2 2. 2. 3. -4. 3. -4. F 240 3 3 3 3. 3. 5. -6. 5. -6. NOT DEFINED F 124 0 -4 -4 -4. -4. 7. -8. 7. -8. NOT DEFINED T 0 5 5 5 5. 5. 9. -10. 9. -10. NOT DEFINED T 0 0 -6 -6 -6. -6. 11. -12. 11. -12. NOT DEFINED F 0 7 7 7 7. 7. 13. -14. 13. -14. NOT DEFINED F 0 0 -8 -8 -8. -8. 15. -16. 15. -16. NOT DEFINED F 0 9 9 9 9. 9. 17. -18. 17. -18. NOT DEFINED T 0 0 -10 -10 -10. -10. 19. -20. 19. -20. NOT DEFINED F 0 98 98 98 98. 98. 0. 0. 0. 0. NOT DEFINED T 0 12 12 12 12. 12. 0. 0. 0. 0. NOT DEFINED F 0 98 98 98 98. 98. 0. 0. 0. 0. NOT DEFINED F 0 0 -14 -14 -14. -14. 0. 0. 0. 0. NOT DEFINED F 0 98 98 98 98. 98. 0. 0. 0. 0. NOT DEFINED F 0 0 -16 -16 -16. -16. 0. 0. 0. 0. NOT DEFINED T 0 98 98 98 98. 98. 0. 0. 0. 0. NOT DEFINED T 0 0 -18 -18 -18. -18. 0. 0. 0. 0. NOT DEFINED T 0 98 98 98 98. 98. 0. 0. 0. 0. NOT DEFINED T 0 0 -20 -20 -20. -20. 0. 0. 0. 0. NOT DEFINED F 0 98 98 98 98. 98. 0. 0. 0. 0. Read columns with ftgcf_: first string F 76 1 1 1 1. 1. 1. -2. 1. -2. second string T 112 2 2 2 2. 2. 3. -4. 3. -4. F 240 3 3 3 3. 3. 5. -6. 5. -6. F 124 0 -4 -4 -4. -4. 7. -8. 7. -8. T 0 5 5 5 5. 5. 9. -10. 9. -10. T 0 0 -6 -6 -6. -6. 11. -12. 11. -12. F 0 7 7 7 7. 7. 13. -14. 13. -14. F 0 0 -8 -8 -8. -8. 15. -16. 15. -16. F 0 9 9 9 9. 9. 17. -18. 17. -18. T 0 0 -10 -10 -10. -10. 19. -20. 19. -20. F 0 99 99 T 0 12 12 F 0 99 99 F 0 0 -14 F 0 99 99 F 0 0 -16 T 0 99 99 T 0 0 -18 T 0 99 99 T 0 0 -20 F 0 99 99 Data values after inserting 3 rows after row 2: first string 1 1 1 1. 1. second string 2 2 2 2. 2. NOT DEFINED 0 0 0 0. 0. NOT DEFINED 0 0 0 0. 0. NOT DEFINED 0 0 0 0. 0. 3 3 3 3. 3. NOT DEFINED 0 -4 -4 -4. -4. NOT DEFINED 5 5 5 5. 5. NOT DEFINED 0 -6 -6 -6. -6. NOT DEFINED 7 7 7 7. 7. NOT DEFINED 0 -8 -8 -8. -8. NOT DEFINED 9 9 9 9. 9. NOT DEFINED 0 -10 -10 -10. -10. NOT DEFINED 98 98 98 98. 98. Data values after deleting 2 rows at row 10: first string 1 1 1 1. 1. second string 2 2 2 2. 2. NOT DEFINED 0 0 0 0. 0. NOT DEFINED 0 0 0 0. 0. NOT DEFINED 0 0 0 0. 0. 3 3 3 3. 3. NOT DEFINED 0 -4 -4 -4. -4. NOT DEFINED 5 5 5 5. 5. NOT DEFINED 0 -6 -6 -6. -6. NOT DEFINED 9 9 9 9. 9. NOT DEFINED 0 -10 -10 -10. -10. NOT DEFINED 98 98 98 98. 98. Data values after deleting column 6: first string 1 1 1. 1. second string 2 2 2. 2. NOT DEFINED 0 0 0. 0. NOT DEFINED 0 0 0. 0. NOT DEFINED 0 0 0. 0. 3 3 3. 3. NOT DEFINED 0 -4 -4. -4. NOT DEFINED 5 5 5. 5. NOT DEFINED 0 -6 -6. -6. NOT DEFINED 9 9 9. 9. NOT DEFINED 0 -10 -10. -10. NOT DEFINED 98 98 98. 98. Data values after inserting column 8: first string 1 1 1. 1. 0 second string 2 2 2. 2. 0 NOT DEFINED 0 0 0. 0. 0 NOT DEFINED 0 0 0. 0. 0 NOT DEFINED 0 0 0. 0. 0 3 3 3. 3. 0 NOT DEFINED 0 -4 -4. -4. 0 NOT DEFINED 5 5 5. 5. 0 NOT DEFINED 0 -6 -6. -6. 0 NOT DEFINED 9 9 9. 9. 0 NOT DEFINED 0 -10 -10. -10. 0 NOT DEFINED 98 98 98. 98. 0 Values after setting 1st 10 elements in column 8 = null: first string 1 1 1. 1. 98 second string 2 2 2. 2. 98 NOT DEFINED 0 0 0. 0. 98 NOT DEFINED 0 0 0. 0. 98 NOT DEFINED 0 0 0. 0. 98 3 3 3. 3. 98 NOT DEFINED 0 -4 -4. -4. 98 NOT DEFINED 5 5 5. 5. 98 NOT DEFINED 0 -6 -6. -6. 98 NOT DEFINED 9 9 9. 9. 98 NOT DEFINED 0 -10 -10. -10. 0 NOT DEFINED 98 98 98. 98. 0 ftibin status = 0 HDU number = 2 0 1000 10000 33000 66000 -999 0 1000 10000 32768 65535 -999 0 1000 10000 32800 65500 -999 0 1 10 33 66 -999 -32768-31768-22768 0 32767 -999 -1 9 99 327 654 -999 Create image extension: ftiimg status = 0 HDU number = 3 Wrote whole 2D array: ftp2di status = 0 Read whole 2D array: ftg2di status = 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 0 0 0 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 0 0 0 0 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 0 0 0 0 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 0 0 0 0 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 0 0 0 0 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 0 0 0 0 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 0 0 0 0 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 0 0 0 0 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 0 0 0 0 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 0 0 0 0 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 0 0 0 0 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 0 0 0 0 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 0 0 0 0 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 0 0 0 0 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 0 0 0 0 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 0 0 0 0 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 0 0 0 0 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 0 0 0 0 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 0 0 0 0 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 0 0 0 0 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 0 0 0 0 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 0 0 0 0 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 0 0 0 0 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 0 0 0 0 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Wrote subset 2D array: ftpssi status = 0 Read whole 2D array: ftg2di status = 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 0 0 0 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 0 0 0 0 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 0 0 0 0 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 0 0 0 0 40 41 42 43 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 54 0 0 0 0 50 51 52 53 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 64 0 0 0 0 60 61 62 63 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 74 0 0 0 0 70 71 72 73 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 84 0 0 0 0 80 81 82 83 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 94 0 0 0 0 90 91 92 93 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 104 0 0 0 0 100 101 102 103 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 114 0 0 0 0 110 111 112 113 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 124 0 0 0 0 120 121 122 123 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 134 0 0 0 0 130 131 132 133 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 144 0 0 0 0 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 0 0 0 0 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 0 0 0 0 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 0 0 0 0 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 0 0 0 0 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 0 0 0 0 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 0 0 0 0 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 0 0 0 0 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 0 0 0 0 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 0 0 0 0 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 0 0 0 0 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Read subset of 2D array: ftgsvi status = 0 41 43 -1 -3 -5 71 73 -31 -33 -35 Create image extension: ftiimg status = 0 HDU number = 4 Create temporary file: ftinit status = 0 Copy image extension to primary array of tmp file. ftcopy status = 0 SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 15 / length of data axis 1 NAXIS2 = 25 / length of data axis 2 EXTEND = T / FITS dataset may contain extensions Delete the tmp file: ftdelt status = 0 Delete the image extension hdutype, status = 1 0 HDU number = 4 ftcrhd status = 0 Variable length arrays: ftphbn status = 0 ftpcl_ status = 0 PCOUNT = 4446 HDU number = 6 A 0 L 0 F X 0 F B 1 0 I 1 0 J 1 0 E 1. 0. D 1. 0. Column 8 repeat and offset = 1 14 A ab 0 L 0 F T X 0 F T B 99 2 0 I 99 2 0 J 99 2 0 E 99. 2. 0. D 99. 2. 0. Column 8 repeat and offset = 2 49 A abc 0 L 0 F F F X 0 F T F B 1 99 3 0 I 1 99 3 0 J 1 99 3 0 E 1.99. 3. 0. D 1.99. 3. 0. Column 8 repeat and offset = 3 105 A abcd 0 L 0 F T F F X 0 F T F F B 1 2 99 4 0 I 1 2 99 4 0 J 1 2 99 4 0 E 1. 2.99. 4. 0. D 1. 2.99. 4. 0. Column 8 repeat and offset = 4 182 A abcde 0 L 0 F T F F T X 0 F T F F T B 1 2 3 99 5 0 I 1 2 3 99 5 0 J 1 2 3 99 5 0 E 1. 2. 3.99. 5. 0. D 1. 2. 3.99. 5. 0. Column 8 repeat and offset = 5 280 A abcdef 0 L 0 F T F F F T X 0 F T F F T T B 1 2 3 4 99 6 0 I 1 2 3 4 99 6 0 J 1 2 3 4 99 6 0 E 1. 2. 3. 4.99. 6. 0. D 1. 2. 3. 4.99. 6. 0. Column 8 repeat and offset = 6 399 A abcdefg 0 L 0 F T F F T F F X 0 F T F F T T F B 1 2 3 4 5 99 7 0 I 1 2 3 4 5 99 7 0 J 1 2 3 4 5 99 7 0 E 1. 2. 3. 4. 5.99. 7. 0. D 1. 2. 3. 4. 5.99. 7. 0. Column 8 repeat and offset = 7 539 A abcdefgh 0 L 0 F T F F T T F F X 0 F T F F T T F F B 1 2 3 4 5 6 99 8 0 I 1 2 3 4 5 6 99 8 0 J 1 2 3 4 5 6 99 8 0 E 1. 2. 3. 4. 5. 6.99. 8. 0. D 1. 2. 3. 4. 5. 6.99. 8. 0. Column 8 repeat and offset = 8 700 A abcdefghi 0 L 0 F T F F T T F F F X 0 F T F F T T F F F B 1 2 3 4 5 6 7 99 9 0 I 1 2 3 4 5 6 7 99 9 0 J 1 2 3 4 5 6 7 99 9 0 E 1. 2. 3. 4. 5. 6. 7.99. 9. 0. D 1. 2. 3. 4. 5. 6. 7.99. 9. 0. Column 8 repeat and offset = 9 883 A abcdefghij 0 L 0 F T F F T T F F F T X 0 F T F F T T F F F T B 1 2 3 4 5 6 7 8 99 10 0 I 1 2 3 4 5 6 7 8 99 10 0 J 1 2 3 4 5 6 7 8 99 10 0 E 1. 2. 3. 4. 5. 6. 7. 8.99.10. 0. D 1. 2. 3. 4. 5. 6. 7. 8.99.10. 0. Column 8 repeat and offset = 10 1087 A abcdefghijk 0 L 0 F T F F T T F F F F T X 0 F T F F T T F F F T T B 1 2 3 4 5 6 7 8 9 99 11 0 I 1 2 3 4 5 6 7 8 9 99 11 0 J 1 2 3 4 5 6 7 8 9 99 11 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.99.11. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.99.11. 0. Column 8 repeat and offset = 11 1312 A abcdefghijkl 0 L 0 F T F F T T F F F T F T X 0 F T F F T T F F F T T T B 1 2 3 4 5 6 7 8 9 10 99 12 0 I 1 2 3 4 5 6 7 8 9 10 99 12 0 J 1 2 3 4 5 6 7 8 9 10 99 12 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.99.12. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.99.12. 0. Column 8 repeat and offset = 12 1558 A abcdefghijklm 0 L 0 F T F F T T F F F T T F F X 0 F T F F T T F F F T T T F B 1 2 3 4 5 6 7 8 9 10 11 99 13 0 I 1 2 3 4 5 6 7 8 9 10 11 99 13 0 J 1 2 3 4 5 6 7 8 9 10 11 99 13 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.99.13. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.99.13. 0. Column 8 repeat and offset = 13 1825 A abcdefghijklmn 0 L 0 F T F F T T F F F T T T F F X 0 F T F F T T F F F T T T F F B 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 I 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 J 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.99.14. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.99.14. 0. Column 8 repeat and offset = 14 2113 A abcdefghijklmno 0 L 0 F T F F T T F F F T T T F F F X 0 F T F F T T F F F T T T F F F B 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.99.15. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.99.15. 0. Column 8 repeat and offset = 15 2422 A abcdefghijklmnop 0 L 0 F T F F T T F F F T T T F F F F X 0 F T F F T T F F F T T T F F F F B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.99.16. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.99.16. 0. Column 8 repeat and offset = 16 2752 A abcdefghijklmnopq 0 L 0 F T F F T T F F F T T T F F F F T X 0 F T F F T T F F F T T T F F F F T B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.99.17. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.99.17. 0. Column 8 repeat and offset = 17 3104 A abcdefghijklmnopqr 0 L 0 F T F F T T F F F T T T F F F F F T X 0 F T F F T T F F F T T T F F F F T T B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.99.18. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.99.18. 0. Column 8 repeat and offset = 18 3477 A abcdefghijklmnopqrs 0 L 0 F T F F T T F F F T T T F F F F T F T X 0 F T F F T T F F F T T T F F F F T T T B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.99.19. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.99.19. 0. Column 8 repeat and offset = 19 3871 A abcdefghijklmnopqrst 0 L 0 F T F F T T F F F T T T F F F F T T F T X 0 F T F F T T F F F T T T F F F F T T T T B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 E 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.18.99.20. 0. D 1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.18.99.20. 0. Column 8 repeat and offset = 20 4286 Create image extension: ftiimg status = 0 ftppr status = 0 Image values written with ftppr and read with ftgpv: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 F (byte) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 F (short) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 F (int) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 F (long) 0. 2. 4. 6. 8.10.12.14.16.18.20.22.24.26. F (float) 0. 2. 4. 6. 8.10.12.14.16.18.20.22.24.26. F (double) Wrote WCS keywords status = 0 Read WCS keywords with ftgics status = 0 CRVAL1, CRVAL2 = 45.830 63.570 CRPIX1, CRPIX2 = 256.000 257.000 CDELT1, CDELT2 = -0.00277777 0.00277777 Rotation = 0.000 CTYPE =-TAN Calculated sky coord. with ftwldp status = 0 Pixels ( 0.500000 0.500000) --> ( 47.385204 62.848968) Sky Calculated pixel coord. with ftxypx status = 0 Sky ( 47.385204 62.848968) --> ( 0.500000 0.500000) Pixels ftitab status = 0 ftpcl status = 0 Column values written with ftpcl and read with ftgcl: 0 3 6 9 12 15 18 21 24 27 F (byte) 0 3 6 9 12 15 18 21 24 27 F (short) 0 3 6 9 12 15 18 21 24 27 F (int) 0 3 6 9 12 15 18 21 24 27 F (long) 0. 3. 6. 9.12.15.18.21.24.27. F (float) 0. 3. 6. 9.12.15.18.21.24.27. F (double) Repeatedly move to the 1st 4 HDUs of the file: Encode checksum: 1234567890.0 -> dCW2fBU0dBU0dBU0 Decode checksum: dCW2fBU0dBU0dBU0 -> 1234567890.0 DATASUM = '2338390162' ftgcks data checksum, status = 2338390162.0 0 ftvcks datastatus, hdustatus, status = 1 1 0 ftupck status = 0 DATASUM = '2338390162' ftvcks datastatus, hdustatus, status = 1 1 0 ftclos status = 0 Normally, there should be 8 error messages on the stack all regarding 'numerical overflows': Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Status = 0: OK - no error cfitsio-4.3.1/CMakeLists.txt0000755000225700000360000002664014523040232015213 0ustar cagordonlhea#============================================================================== # CFITSIO CMakeLists.txt #============================================================================== # Ensure that build directory is not the source directory: IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) message(FATAL_ERROR "Please create a separate directory for building CFITSIO." ) ENDIF() CMAKE_MINIMUM_REQUIRED(VERSION 3.1) # Suppress warning about WIN32 no longer being defined on Cygwin: SET(CMAKE_LEGACY_CYGWIN_WIN32 0) PROJECT(CFITSIO DESCRIPTION "Library of C and Fortran subroutines for reading and writing data files in FITS data format." LANGUAGES C CXX ) # Define project version SET(${PROJECT_NAME}_MAJOR 4) SET(${PROJECT_NAME}_MINOR 3) SET(${PROJECT_NAME}_MICRO 1) SET(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_MAJOR}.${${PROJECT_NAME}_MINOR}.${${PROJECT_NAME}_MICRO}) SET(LIB_NAME cfitsio) # Allow @rpath token in target install name on Macs. # See "cmake --help-policy CMP0042" for more information. IF(POLICY CMP0042) CMAKE_POLICY(SET CMP0042 NEW) ENDIF() INCLUDE(CheckLibraryExists) INCLUDE(CheckFunctionExists) INCLUDE(CheckSymbolExists) INCLUDE(CheckCSourceCompiles) #============================================================================== # Build options: #============================================================================== # Allow the developer to select if Dynamic or Static libraries are built OPTION(BUILD_SHARED_LIBS "Build Shared Libraries" ON) # Allow curl dependency to be disabled with "-DUSE_CURL=OFF": OPTION(USE_CURL "USE_CURL" ON) OPTION(USE_PTHREADS "Thread-safe build (using pthreads)" OFF) OPTION(TESTS "Build test programs Testprog and cookbook" OFF) OPTION(UTILS "Build FPack, Funpack, and Fitscopy executables" OFF) OPTION(USE_SSE2 "Enable use of instructions in the SSE2 extended instruction set" OFF) OPTION(USE_SSSE3 "Enable use of instructions in the SSSE3 extended instruction set" OFF) IF(NOT WIN32) OPTION(USE_BZIP2 "Enable bzip2 support" OFF) ENDIF() #============================================================================== FIND_PACKAGE(ZLIB REQUIRED) IF(BUILD_SHARED_LIBS) SET (LIB_TYPE SHARED) ELSE() SET (LIB_TYPE STATIC) ENDIF(BUILD_SHARED_LIBS) IF(NOT WIN32) # Find curl library, for HTTPS support: IF(USE_CURL) FIND_PACKAGE(CURL) IF(CURL_FOUND) ADD_DEFINITIONS(-DCFITSIO_HAVE_CURL) ENDIF() ENDIF() ENDIF(NOT WIN32) IF(USE_PTHREADS) FIND_PACKAGE(Threads REQUIRED) ADD_DEFINITIONS(-D_REENTRANT) ENDIF(USE_PTHREADS) IF(USE_BZIP2) FIND_PACKAGE(BZip2 REQUIRED) ADD_DEFINITIONS(-DHAVE_BZIP2=1) ENDIF(USE_BZIP2) # Math library (not available in MSVC or MINGW) IF(MSVC OR MINGW) SET(M_LIB "") ELSE() FIND_LIBRARY(M_LIB m) ENDIF() # Support for remote file drivers is not implemented for native Windows: IF (NOT MSVC) # Find library needed for gethostbyname: CHECK_FUNCTION_EXISTS("gethostbyname" CMAKE_HAVE_GETHOSTBYNAME) IF (NOT CMAKE_HAVE_GETHOSTBYNAME) CHECK_LIBRARY_EXISTS("nsl" "gethostbyname" "" CMAKE_HAVE_GETHOSTBYNAME) ENDIF () # Find library needed for connect: CHECK_FUNCTION_EXISTS("connect" CMAKE_HAVE_CONNECT) IF (NOT CMAKE_HAVE_CONNECT) CHECK_LIBRARY_EXISTS("socket" "connect" "" CMAKE_HAVE_CONNECT) ENDIF () # Define HAVE_NET_SERVICES if gethostbyname & connect were found: IF (CMAKE_HAVE_GETHOSTBYNAME AND CMAKE_HAVE_CONNECT) ADD_DEFINITIONS(-DHAVE_NET_SERVICES) CHECK_SYMBOL_EXISTS(fmemopen "stdio.h" HAVE_FMEMOPEN) IF(HAVE_FMEMOPEN) ADD_DEFINITIONS(-DHAVE_FMEMOPEN) ENDIF() ENDIF() ENDIF() IF(MSVC OR BORLAND) # Define ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) # Need an empty unistd.h in MSVC for flex-generated eval_l.c: FILE(WRITE ${CMAKE_SOURCE_DIR}/unistd.h "") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ENDIF() IF(BORLAND) # Suppress spurious Borland compiler warnings about "Suspicious # pointer arithmetic", "Possibly incorrect assignment", and # "Comparing signed and unsigned values". ADD_DEFINITIONS(-w-spa) ADD_DEFINITIONS(-w-pia) ADD_DEFINITIONS(-w-csu) ENDIF() IF(USE_SSE2) IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") ADD_COMPILE_OPTIONS(-msse2) ENDIF() IF(MSVC) ADD_DEFINITIONS(-D__SSE2__=1) ENDIF() ENDIF() IF(USE_SSSE3) IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") ADD_COMPILE_OPTIONS(-mssse3) ENDIF() IF(MSVC) ADD_DEFINITIONS(-D__SSE2__=1 -D__SSSE3__=1) ENDIF() ENDIF() # Test for the unix ftruncate function CHECK_SYMBOL_EXISTS(ftruncate "unistd.h" HAVE_FTRUNCATE) IF(HAVE_FTRUNCATE) ADD_DEFINITIONS(-DHAVE_UNISTD_H -DHAVE_FTRUNCATE) ENDIF() # Check is System V IPC is supported on this machine CHECK_C_SOURCE_COMPILES(" #include #include #include int main() { shmat(0,0,0); shmdt(0); shmget(0, 0, 0); semget(0, 0, 0); return 0; }" HAVE_SHMEM_SERVICES) IF(HAVE_SHMEM_SERVICES) ADD_DEFINITIONS(-DHAVE_SHMEM_SERVICES) # Some systems define flock_t, for others we have to define it ourselves CHECK_C_SOURCE_COMPILES(" #include int main() { flock_t filler; return 0; }" HAVE_FLOCK_T) IF(HAVE_FLOCK_T) ADD_DEFINITIONS(-DHAVE_FLOCK_T) ENDIF() # Check union semun CHECK_C_SOURCE_COMPILES(" #include #include #include int main() { union semun filler; return 0; }" HAVE_UNION_SEMUN) IF(HAVE_UNION_SEMUN) ADD_DEFINITIONS(-DHAVE_UNION_SEMUN) ENDIF() ENDIF() IF(WIN32 AND BUILD_SHARED_LIBS) ADD_DEFINITIONS(-Dcfitsio_EXPORTS) ENDIF() #============================================================================== # CFITSIO source code: #============================================================================== set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") set (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/") set (BIN_DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") SET(H_FILES fitsio.h fitsio2.h longnam.h) SET(SRC_FILES buffers.c cfileio.c checksum.c drvrfile.c drvrmem.c drvrnet.c drvrsmem.c editcol.c edithdu.c eval_f.c eval_l.c eval_y.c f77_wrap1.c f77_wrap2.c f77_wrap3.c f77_wrap4.c fits_hcompress.c fits_hdecompress.c fitscore.c getcol.c getcolb.c getcold.c getcole.c getcoli.c getcolj.c getcolk.c getcoll.c getcols.c getcolsb.c getcolui.c getcoluj.c getcoluk.c getkey.c group.c grparser.c histo.c imcompress.c iraffits.c modkey.c pliocomp.c putcol.c putcolb.c putcold.c putcole.c putcoli.c putcolj.c putcolk.c putcoll.c putcols.c putcolsb.c putcolu.c putcolui.c putcoluj.c putcoluk.c putkey.c quantize.c region.c ricecomp.c scalnull.c simplerng.c swapproc.c wcssub.c wcsutil.c zcompress.c zuncompress.c ) # For future modifications: # drvrsmem.c is only usable if HAVE_SHMEM_SERVICES is defined: #drvrsmem.c # drvrgsiftp.c is only usable if HAVE_NET_SERVICES & HAVE_GSIFTP are defined: #drvrgsiftp.c #============================================================================== # Add libraries: #============================================================================== ADD_LIBRARY(${LIB_NAME} ${LIB_TYPE} ${H_FILES} ${SRC_FILES}) # Add an alias definition to handle export namespace for # add_subdirectory(): ADD_LIBRARY(${LIB_NAME}::${LIB_NAME} ALIAS ${LIB_NAME}) TARGET_INCLUDE_DIRECTORIES(${LIB_NAME} PUBLIC $ $ $ ) # Math: TARGET_LINK_LIBRARIES(${LIB_NAME} ${M_LIB}) # zlib: IF (ZLIB_FOUND) TARGET_INCLUDE_DIRECTORIES(${LIB_NAME} PUBLIC ${ZLIB_INCLUDE_DIR}) TARGET_LINK_LIBRARIES(${LIB_NAME} ${ZLIB_LIBRARIES}) # For cfitsio.pc.cmake: SET (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -lz") ENDIF(ZLIB_FOUND) # cURL: IF (CURL_FOUND) TARGET_INCLUDE_DIRECTORIES(${LIB_NAME} PUBLIC ${CURL_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${LIB_NAME} ${CURL_LIBRARIES}) # For cfitsio.pc.cmake: SET (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -lcurl") ENDIF(CURL_FOUND) # PThreads: IF (THREADS_FOUND) TARGET_LINK_LIBRARIES(${LIB_NAME} Threads::Threads) ENDIF(THREADS_FOUND) # BZip2: IF (BZIP2_FOUND) TARGET_INCLUDE_DIRECTORIES(${LIB_NAME} PUBLIC ${BZIP2_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${LIB_NAME} ${BZIP2_LIBRARIES}) SET (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -lbz2") ENDIF(BZIP2_FOUND) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${${PROJECT_NAME}_VERSION} SOVERSION ${${PROJECT_NAME}_MAJOR}) include(GNUInstallDirs) include(CMakePackageConfigHelpers) install(TARGETS ${LIB_NAME} EXPORT ${LIB_NAME}-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(EXPORT ${LIB_NAME}-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) install(FILES ${H_FILES} DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel) #============================================================================== # Optional test programs: #============================================================================== IF (TESTS) ENABLE_TESTING() ADD_EXECUTABLE(TestProg testprog.c) TARGET_LINK_LIBRARIES(TestProg ${LIB_NAME}) ADD_TEST(TestProg TestProg) # Copy testprog.tpt to build directory to allow quick test # of ./TestProg (or .\Release\TestProg.exe in MSVC): FILE(COPY ${CMAKE_SOURCE_DIR}/testprog.tpt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) ADD_EXECUTABLE(cookbook cookbook.c) TARGET_LINK_LIBRARIES(cookbook ${LIB_NAME}) ADD_TEST(cookbook cookbook) ENDIF(TESTS) #============================================================================== # Optional utilities: #============================================================================== IF (UTILS) ADD_EXECUTABLE(FPack fpack.c fpackutil.c) TARGET_LINK_LIBRARIES(FPack ${LIB_NAME}) ADD_EXECUTABLE(Funpack funpack.c fpackutil.c) TARGET_LINK_LIBRARIES(Funpack ${LIB_NAME}) ADD_EXECUTABLE(Fitscopy fitscopy.c) TARGET_LINK_LIBRARIES(Fitscopy ${LIB_NAME}) # To expand the command line arguments in Windows, see: # http://msdn.microsoft.com/en-us/library/8bch7bkk.aspx if(MSVC) set_target_properties(FPack Funpack PROPERTIES LINK_FLAGS "setargv.obj") endif(MSVC) install(TARGETS FPack Funpack Fitscopy RUNTIME DESTINATION bin) ENDIF(UTILS) #============================================================================== # cfitsio.pc #============================================================================== configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cfitsio.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/cfitsio.pc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cfitsio-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cfitsio-config.cmake @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cfitsio-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cfitsio-config-version.cmake @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cfitsio.pc DESTINATION lib/pkgconfig/) install(FILES ${CFITSIO_BINARY_DIR}/cfitsio-config.cmake ${CFITSIO_BINARY_DIR}/cfitsio-config-version.cmake DESTINATION lib/cfitsio-${CFITSIO_VERSION}) cfitsio-4.3.1/speed.c0000644000225700000360000003614313472024437013726 0ustar cagordonlhea#include #include #include #include #include /* Every program which uses the CFITSIO interface must include the the fitsio.h header file. This contains the prototypes for all the routines and defines the error status values and other symbolic constants used in the interface. */ #include "fitsio.h" #define minvalue(A,B) ((A) < (B) ? (A) : (B)) /* size of the image */ #define XSIZE 3000 #define YSIZE 3000 /* size of data buffer */ #define SHTSIZE 20000 static long sarray[ SHTSIZE ] = {SHTSIZE * 0}; /* no. of rows in binary table */ #define BROWS 2500000 /* no. of rows in ASCII table */ #define AROWS 400000 /* CLOCKS_PER_SEC should be defined by most compilers */ #if defined(CLOCKS_PER_SEC) #define CLOCKTICKS CLOCKS_PER_SEC #else /* on SUN OS machine, CLOCKS_PER_SEC is not defined, so set its value */ #define CLOCKTICKS 1000000 #define difftime(A,B) ((double) A - (double) B) #endif /* define variables for measuring elapsed time */ clock_t scpu, ecpu; time_t start, finish; long startsec; /* start of elapsed time interval */ int startmilli; /* start of elapsed time interval */ int writeimage(fitsfile *fptr, int *status); int writebintable(fitsfile *fptr, int *status); int writeasctable(fitsfile *fptr, int *status); int readimage(fitsfile *fptr, int *status); int readatable(fitsfile *fptr, int *status); int readbtable(fitsfile *fptr, int *status); void printerror( int status); int marktime(int *status); int gettime(double *elapse, float *elapscpu, int *status); int main(void); int main() { /************************************************************************* This program tests the speed of writing/reading FITS files with cfitsio **************************************************************************/ FILE *diskfile; fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ int status, ii; long rawloop; char filename[] = "speedcc.fit"; /* name for new FITS file */ char buffer[2880] = {2880 * 0}; time_t tbegin, tend; float rate, size, elapcpu, cpufrac; double elapse; tbegin = time(0); remove(filename); /* Delete old file if it already exists */ diskfile = fopen(filename,"w+b"); rawloop = XSIZE * YSIZE / 720; printf(" "); printf(" SIZE / ELAPSE(%%CPU) = RATE\n"); printf("RAW fwrite (2880 bytes/loop)... "); marktime(&status); for (ii = 0; ii < rawloop; ii++) if (fwrite(buffer, 1, 2880, diskfile) != 2880) printf("write error \n"); gettime(&elapse, &elapcpu, &status); cpufrac = elapcpu / elapse * 100.; size = 2880. * rawloop / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); /* read back the binary records */ fseek(diskfile, 0, 0); printf("RAW fread (2880 bytes/loop)... "); marktime(&status); for (ii = 0; ii < rawloop; ii++) if (fread(buffer, 1, 2880, diskfile) != 2880) printf("read error \n"); gettime(&elapse, &elapcpu, &status); cpufrac = elapcpu / elapse * 100.; size = 2880. * rawloop / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); fclose(diskfile); remove(filename); status = 0; fptr = 0; if (fits_create_file(&fptr, filename, &status)) /* create new FITS file */ printerror( status); if (writeimage(fptr, &status)) printerror( status); if (writebintable(fptr, &status)) printerror( status); if (writeasctable(fptr, &status)) printerror( status); if (readimage(fptr, &status)) printerror( status); if (readbtable(fptr, &status)) printerror( status); if (readatable(fptr, &status)) printerror( status); if (fits_close_file(fptr, &status)) printerror( status ); tend = time(0); elapse = difftime(tend, tbegin) + 0.5; printf("Total elapsed time = %.3fs, status = %d\n",elapse, status); return(0); } /*--------------------------------------------------------------------------*/ int writeimage(fitsfile *fptr, int *status) /**************************************************/ /* write the primary array containing a 2-D image */ /**************************************************/ { long nremain, ii; float rate, size, elapcpu, cpufrac; double elapse; /* initialize FITS image parameters */ int bitpix = 32; /* 32-bit signed integer pixel values */ long naxis = 2; /* 2-dimensional image */ long naxes[2] = {XSIZE, YSIZE }; /* image size */ /* write the required keywords for the primary array image */ if ( fits_create_img(fptr, bitpix, naxis, naxes, status) ) printerror( *status ); printf("\nWrite %dx%d I*4 image, %d pixels/loop: ",XSIZE,YSIZE,SHTSIZE); marktime(status); nremain = XSIZE * YSIZE; for (ii = 1; ii <= nremain; ii += SHTSIZE) { ffpprj(fptr, 0, ii, SHTSIZE, sarray, status); } ffflus(fptr, status); /* flush all buffers to disk */ gettime(&elapse, &elapcpu, status); cpufrac = elapcpu / elapse * 100.; size = XSIZE * 4. * YSIZE / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); return( *status ); } /*--------------------------------------------------------------------------*/ int writebintable (fitsfile *fptr, int *status) /*********************************************************/ /* Create a binary table extension containing 3 columns */ /*********************************************************/ { int tfields = 2; long nremain, ntodo, firstrow = 1, firstelem = 1, nrows; float rate, size, elapcpu, cpufrac; double elapse; char extname[] = "Speed_Test"; /* extension name */ /* define the name, datatype, and physical units for the columns */ char *ttype[] = { "first", "second" }; char *tform[] = {"1J", "1J" }; char *tunit[] = { " ", " " }; /* append a new empty binary table onto the FITS file */ if ( fits_create_tbl( fptr, BINARY_TBL, BROWS, tfields, ttype, tform, tunit, extname, status) ) printerror( *status ); /* get table row size and optimum number of rows to write per loop */ fits_get_rowsize(fptr, &nrows, status); nrows = minvalue(nrows, SHTSIZE); nremain = BROWS; printf("Write %7drow x %dcol bintable %4ld rows/loop:", BROWS, tfields, nrows); marktime(status); while(nremain) { ntodo = minvalue(nrows, nremain); ffpclj(fptr, 1, firstrow, firstelem, ntodo, sarray, status); ffpclj(fptr, 2, firstrow, firstelem, ntodo, sarray, status); firstrow += ntodo; nremain -= ntodo; } ffflus(fptr, status); /* flush all buffers to disk */ gettime(&elapse, &elapcpu, status); cpufrac = elapcpu / elapse * 100.; size = BROWS * 8. / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); return( *status ); } /*--------------------------------------------------------------------------*/ int writeasctable (fitsfile *fptr, int *status) /*********************************************************/ /* Create an ASCII table extension containing 2 columns */ /*********************************************************/ { int tfields = 2; long nremain, ntodo, firstrow = 1, firstelem = 1; long nrows; float rate, size, elapcpu, cpufrac; double elapse; char extname[] = "Speed_Test"; /* extension name */ /* define the name, datatype, and physical units for the columns */ char *ttype[] = { "first", "second" }; char *tform[] = {"I6", "I6" }; char *tunit[] = { " ", " " }; /* append a new empty ASCII table onto the FITS file */ if ( fits_create_tbl( fptr, ASCII_TBL, AROWS, tfields, ttype, tform, tunit, extname, status) ) printerror( *status ); /* get table row size and optimum number of rows to write per loop */ fits_get_rowsize(fptr, &nrows, status); nrows = minvalue(nrows, SHTSIZE); nremain = AROWS; printf("Write %7drow x %dcol asctable %4ld rows/loop:", AROWS, tfields, nrows); marktime(status); while(nremain) { ntodo = minvalue(nrows, nremain); ffpclj(fptr, 1, firstrow, firstelem, ntodo, sarray, status); ffpclj(fptr, 2, firstrow, firstelem, ntodo, sarray, status); firstrow += ntodo; nremain -= ntodo; } ffflus(fptr, status); /* flush all buffers to disk */ gettime(&elapse, &elapcpu, status); cpufrac = elapcpu / elapse * 100.; size = AROWS * 13. / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); return( *status ); } /*--------------------------------------------------------------------------*/ int readimage( fitsfile *fptr, int *status ) /*********************/ /* Read a FITS image */ /*********************/ { int anynull, hdutype; long nremain, ii; long longnull = 0; float rate, size, elapcpu, cpufrac; double elapse; /* move to the primary array */ if ( fits_movabs_hdu(fptr, 1, &hdutype, status) ) printerror( *status ); printf("\nRead back image "); marktime(status); nremain = XSIZE * YSIZE; for (ii=1; ii <= nremain; ii += SHTSIZE) { ffgpvj(fptr, 0, ii, SHTSIZE, longnull, sarray, &anynull, status); } gettime(&elapse, &elapcpu, status); cpufrac = elapcpu / elapse * 100.; size = XSIZE * 4. * YSIZE / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); return( *status ); } /*--------------------------------------------------------------------------*/ int readbtable( fitsfile *fptr, int *status ) /************************************************************/ /* read and print data values from the binary table */ /************************************************************/ { int hdutype, anynull; long nremain, ntodo, firstrow = 1, firstelem = 1; long nrows; long lnull = 0; float rate, size, elapcpu, cpufrac; double elapse; /* move to the table */ if ( fits_movrel_hdu(fptr, 1, &hdutype, status) ) printerror( *status ); /* get table row size and optimum number of rows to read per loop */ fits_get_rowsize(fptr, &nrows, status); nrows = minvalue(nrows, SHTSIZE); /* read the columns */ nremain = BROWS; printf("Read back BINTABLE "); marktime(status); while(nremain) { ntodo = minvalue(nrows, nremain); ffgcvj(fptr, 1, firstrow, firstelem, ntodo, lnull, sarray, &anynull, status); ffgcvj(fptr, 2, firstrow, firstelem, ntodo, lnull, sarray, &anynull, status); firstrow += ntodo; nremain -= ntodo; } gettime(&elapse, &elapcpu, status); cpufrac = elapcpu / elapse * 100.; size = BROWS * 8. / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); return( *status ); } /*--------------------------------------------------------------------------*/ int readatable( fitsfile *fptr, int *status ) /************************************************************/ /* read and print data values from an ASCII or binary table */ /************************************************************/ { int hdutype, anynull; long nremain, ntodo, firstrow = 1, firstelem = 1; long nrows; long lnull = 0; float rate, size, elapcpu, cpufrac; double elapse; /* move to the table */ if ( fits_movrel_hdu(fptr, 1, &hdutype, status) ) printerror( *status ); /* get table row size and optimum number of rows to read per loop */ fits_get_rowsize(fptr, &nrows, status); nrows = minvalue(nrows, SHTSIZE); /* read the columns */ nremain = AROWS; printf("Read back ASCII Table "); marktime(status); while(nremain) { ntodo = minvalue(nrows, nremain); ffgcvj(fptr, 1, firstrow, firstelem, ntodo, lnull, sarray, &anynull, status); ffgcvj(fptr, 2, firstrow, firstelem, ntodo, lnull, sarray, &anynull, status); firstrow += ntodo; nremain -= ntodo; } gettime(&elapse, &elapcpu, status); cpufrac = elapcpu / elapse * 100.; size = AROWS * 13. / 1000000.; rate = size / elapse; printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate); return( *status ); } /*--------------------------------------------------------------------------*/ void printerror( int status) { /*****************************************************/ /* Print out cfitsio error messages and exit program */ /*****************************************************/ char status_str[FLEN_STATUS], errmsg[FLEN_ERRMSG]; if (status) fprintf(stderr, "\n*** Error occurred during program execution ***\n"); fits_get_errstatus(status, status_str); /* get the error description */ fprintf(stderr, "\nstatus = %d: %s\n", status, status_str); /* get first message; null if stack is empty */ if ( fits_read_errmsg(errmsg) ) { fprintf(stderr, "\nError message stack:\n"); fprintf(stderr, " %s\n", errmsg); while ( fits_read_errmsg(errmsg) ) /* get remaining messages */ fprintf(stderr, " %s\n", errmsg); } exit( status ); /* terminate the program, returning error status */ } /*--------------------------------------------------------------------------*/ int marktime( int *status) { double telapse; time_t temp; struct timeval tv; temp = time(0); /* Since elapsed time is only measured to the nearest second */ /* keep getting the time until the seconds tick just changes. */ /* This provides more consistent timing measurements since the */ /* intervals all start on an integer seconds. */ telapse = 0.; scpu = clock(); start = time(0); /* while (telapse == 0.) { scpu = clock(); start = time(0); telapse = difftime( start, temp ); } */ gettimeofday (&tv, NULL); startsec = tv.tv_sec; startmilli = tv.tv_usec/1000; return( *status ); } /*--------------------------------------------------------------------------*/ int gettime(double *elapse, float *elapscpu, int *status) { struct timeval tv; int stopmilli; long stopsec; gettimeofday (&tv, NULL); ecpu = clock(); finish = time(0); stopmilli = tv.tv_usec/1000; stopsec = tv.tv_sec; *elapse = (stopsec - startsec) + (stopmilli - startmilli)/1000.; /* *elapse = difftime(finish, start) + 0.5; */ *elapscpu = (ecpu - scpu) * 1.0 / CLOCKTICKS; return( *status ); } cfitsio-4.3.1/winDumpExts.mak0000644000225700000360000001024113472024437015432 0ustar cagordonlhea# Microsoft Developer Studio Generated NMAKE File, Based on winDumpExts.dsp !IF "$(CFG)" == "" CFG=Win32 Debug !MESSAGE No configuration specified. Defaulting to Win32 Debug. !ENDIF !IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "winDumpExts.mak" CFG="Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "Win32 Release" OUTDIR=.\Release INTDIR=.\Release # Begin Custom Macros OutDir=.\Release # End Custom Macros ALL : "$(OUTDIR)\winDumpExts.exe" CLEAN : -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\winDumpExts.obj" -@erase "$(OUTDIR)\winDumpExts.exe" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" "$(INTDIR)" : if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" CPP=cl.exe CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\winDumpExts.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\winDumpExts.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\winDumpExts.pdb" /machine:I386 /out:"$(OUTDIR)\winDumpExts.exe" LINK32_OBJS= \ "$(INTDIR)\winDumpExts.obj" "$(OUTDIR)\winDumpExts.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ELSEIF "$(CFG)" == "Win32 Debug" OUTDIR=. INTDIR=.\Debug # Begin Custom Macros OutDir=. # End Custom Macros ALL : "$(OUTDIR)\winDumpExts.exe" CLEAN : -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(INTDIR)\winDumpExts.obj" -@erase "$(OUTDIR)\winDumpExts.exe" -@erase "$(OUTDIR)\winDumpExts.ilk" -@erase "$(OUTDIR)\winDumpExts.pdb" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" "$(INTDIR)" : if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\winDumpExts.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\winDumpExts.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\winDumpExts.pdb" /debug /machine:I386 /out:"$(OUTDIR)\winDumpExts.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\winDumpExts.obj" "$(OUTDIR)\winDumpExts.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("winDumpExts.dep") !INCLUDE "winDumpExts.dep" !ELSE !MESSAGE Warning: cannot find "winDumpExts.dep" !ENDIF !ENDIF !IF "$(CFG)" == "Win32 Release" || "$(CFG)" == "Win32 Debug" SOURCE=.\winDumpExts.c "$(INTDIR)\winDumpExts.obj" : $(SOURCE) "$(INTDIR)" !ENDIF cfitsio-4.3.1/testprog.std0000644000225700000360000020700013472024437015035 0ustar cagordonlheaSIMPLE = T / file does conform to FITS standard BITPIX = 32 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 10 / length of data axis 1 NAXIS2 = 2 / length of data axis 2 EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H KEY_PREC= 'This keyword was written by fxprec' / comment goes here CARD1 = '12345678901234567890123456789012345678901234567890123456789012345678'CARD2 = '1234567890123456789012345678901234567890123456789012345678901234''67'CARD3 = '1234567890123456789012345678901234567890123456789012345678901234'''''CARD4 = '1234567890123456789012345678901234567890123456789012345678901234567' KEY_PKYS= 'value_string' / fxpkys comment KEY_PKYL= T / fxpkyl comment KEY_PKYJ= 11 / [feet/second/second] fxpkyj comment KEY_PKYF= 12.12121 / fxpkyf comment KEY_PKYE= 1.313131E+01 / fxpkye comment KEY_PKYG= 14.14141414141414 / fxpkyg comment KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment KEY_PKYC= (1.313131E+01, 1.414141E+01) / fxpkyc comment KEY_PKYM= (1.51515151515152E+01, 1.61616161616162E+01) / fxpkym comment KEY_PKFC= (13.131313, 14.141414) / fxpkfc comment KEY_PKFM= (15.15151515151515, 16.16161616161616) / fxpkfm comment KEY_PKLS= 'This is a very long string value that is continued over more than o&'CONTINUE 'ne keyword.' / fxpkls comment LONGSTRN= 'OGIP 1.0' / The HEASARC Long String Convention may be used.COMMENT This FITS file may contain long string keyword values that are COMMENT continued over multiple keywords. The HEASARC convention uses the & COMMENT character at the end of each substring which is then continued COMMENT on the next keyword which has the name CONTINUE. KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment COMMENT This keyword was modified by fxmrec KY_UCRD = 'This keyword was updated by fxucrd' NEWIKYS = 'updated_string' / ikys comment KY_IKYJ = 51 / This is a modified comment KY_IKYL = T / ikyl comment KY_IKYE = -1.3346E+01 / ikye comment KY_IKYD = -1.33456789012346E+01 / modified comment KY_IKYF = -13.3456 / ikyf comment KY_IKYG = -13.3456789012346 / ikyg comment KY_PKNS1= 'first string' / fxpkns comment KY_PKNS2= 'second string' / fxpkns comment KY_PKNS3= ' ' / fxpkns comment KY_PKNL1= T / fxpknl comment KY_PKNL2= F / fxpknl comment KY_PKNL3= T / fxpknl comment KY_PKNJ1= 11 / fxpknj comment KY_PKNJ2= 12 / fxpknj comment KY_PKNJ3= 13 / fxpknj comment KY_PKNF1= 12.12121 / fxpknf comment KY_PKNF2= 13.13131 / fxpknf comment KY_PKNF3= 14.14141 / fxpknf comment KY_PKNE1= 1.313131E+01 / fxpkne comment KY_PKNE2= 1.414141E+01 / fxpkne comment KY_PKNE3= 1.515152E+01 / fxpkne comment KY_PKNG1= 14.1414141414141 / fxpkng comment KY_PKNG2= 15.1515151515152 / fxpkng comment KY_PKNG3= 16.1616161616162 / fxpkng comment KY_PKND1= 1.51515151515152E+01 / fxpknd comment KY_PKND2= 1.61616161616162E+01 / fxpknd comment KY_PKND3= 1.71717171717172E+01 / fxpknd comment TSTRING = '1 ' / tstring comment TLOGICAL= T / tlogical comment TBYTE = 11 / tbyte comment TSHORT = 21 / tshort comment TINT = 31 / tint comment TLONG = 41 / tlong comment TFLOAT = 42. / tfloat comment TDOUBLE = 82. / tdouble comment BLANK = -99 / value to use for undefined pixels KY_PKNE4= 1.313131E+01 / fxpkne comment TMPCARDA= 1001 / this is the 1st template card TMPCARD2= 'ABCD ' / this is the 2nd template card TMPCARD3= 1001.23 / this is the 3rd template card COMMENT this is the 5th template card HISTORY this is the 6th template card TMPCARD7= / comment for null keyword END ÿÿÿÿÿÿÿÿÿ ÿÿÿ ÿÿÿÿÿÿXTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 61 / width of table in bytes NAXIS2 = 20 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 10 / number of fields in each row TTYPE1 = 'Avalue ' / label for field 1 TFORM1 = '15A ' / data format of field: ASCII Character TTYPE2 = 'Lvalue ' / label for field 2 TFORM2 = '1L ' / data format of field: 1-byte LOGICAL TUNIT2 = 'm**2 ' / physical unit of field TTYPE3 = 'Xvalue ' / label for field 3 TFORM3 = '16X ' / data format of field: BIT TUNIT3 = 'cm ' / physical unit of field TTYPE4 = 'Bvalue ' / label for field 4 TFORM4 = '1B ' / data format of field: BYTE TUNIT4 = 'erg/s ' / physical unit of field TTYPE5 = 'Ivalue ' / label for field 5 TFORM5 = '1I ' / data format of field: 2-byte INTEGER TUNIT5 = 'km/s ' / physical unit of field TTYPE6 = 'Jvalue ' / label for field 6 TFORM6 = '1J ' / data format of field: 4-byte INTEGER TTYPE7 = 'Evalue ' / label for field 7 TFORM7 = '1E ' / data format of field: 4-byte REAL TTYPE8 = 'Dvalue ' / label for field 8 TFORM8 = '1D ' / data format of field: 8-byte DOUBLE TTYPE9 = 'Cvalue ' / label for field 9 TFORM9 = '1C ' / data format of field: COMPLEX TTYPE10 = 'Mvalue ' / label for field 10 TFORM10 = '1M ' / data format of field: DOUBLE COMPLEX EXTNAME = 'Test-BINTABLE' / name of this binary table extension EXTVER = 3 / extension version number TNULL4 = 77 / value for undefined pixels TNULL5 = 77 / value for undefined pixels TNULL6 = 77 / value for undefined pixels TSCAL4 = 1000 / scaling factor TSCAL5 = 1 / scaling factor TSCAL6 = 100 / scaling factor TZERO4 = 0 / scaling offset TZERO5 = 32768 / scaling offset TZERO6 = 100 / scaling offset NEW_KEY = 'written by fxprec' / to change checksum END €ÿÿÿÿƒè §c!GBÿŽMMMXTENSION= 'IMAGE ' / IMAGE extension BITPIX = -32 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 15 / length of data axis 1 NAXIS2 = 25 / length of data axis 2 PCOUNT = 0 / required keyword; must = 0 GCOUNT = 1 / required keyword; must = 1 END ?€@@@@€@ @À@àAAA A0A@APA`A A0A@APA`ApA€AˆAA˜A A¨A°A¸AÀA A¨A°A¸AÀAÈAÐAØAàAèAðAøBBBAðAøBBBB BBBBB B$B(B,B0B B$B(B,¿€ÀÀ@À€À ÀÀÀàÁÁBXBHBLBPBTÁ Á0Á@ÁPÁ`ÁpÁ€ÁˆÁÁ˜B€BpBtBxB|Á Á¨Á°Á¸ÁÀÁÈÁÐÁØÁàÁèB”BŒBŽBB’ÁðÁøÂ ÂÂÂÂB¨B B¢B¤B¦Â Â$Â(Â,Â0Â4Â8Â<Â@ÂDB¼B´B¶B¸BºÂHÂLÂPÂTÂXÂ\Â`ÂdÂhÂlBÐBÈBÊBÌBÎÂpÂtÂxÂ|€‚„†ˆŠBäBÜBÞBàB⌎’”–˜šœžBøBðBòBôBö ¢¤¦¨ª¬®°²CCCCC´¶¸º¼¾ÂÀÂÂÂÄÂÆCC C CCCCCCCCCCCCCCCCCCCCCCCC C!C"C#C$C C!C"C#C$C%C&C'C(C)C*C+C,C-C.C*C+C,C-C.C/C0C1C2C3C4C5C6C7C8C4C5C6C7C8C9C:C;C<C=C>C?C@CACBC>C?C@CACBCCCDCECFCGCHCICJCKCLCHCICJCKCLCMCNCOCPCQCRCSCTCUCVCRCSCTCUCVCWCXCYCZC[C\C]C^C_C`C\C]C^C_C`CaCbCcCdCeCfCgChCiCjCfCgChCiCjCkClCmCnCoCpCqCrCsCtCpCqCrCsCtCuCvCwCxCyCzC{C|C}C~XTENSION= 'TABLE ' / ASCII table extension BITPIX = 8 / 8-bit ASCII characters NAXIS = 2 / 2-dimensional ASCII table NAXIS1 = 76 / width of table in characters NAXIS2 = 12 / number of rows in table PCOUNT = 0 / no group parameters (required keyword) GCOUNT = 1 / one data group (required keyword) TFIELDS = 5 / number of fields in each row TTYPE1 = 'Name ' / label for field 1 TBCOL1 = 1 / beginning column of field 1 TFORM1 = 'A15 ' / Fortran-77 format of field TTYPE2 = 'Ivalue ' / label for field 2 TBCOL2 = 17 / beginning column of field 2 TFORM2 = 'I10 ' / Fortran-77 format of field TUNIT2 = 'm**2 ' / physical unit of field TTYPE3 = 'Evalue ' / label for field 4 TBCOL3 = 28 / beginning column of field 4 TFORM3 = 'E12.5 ' / Fortran-77 format of field TUNIT3 = 'erg/s ' / physical unit of field TTYPE4 = 'Dvalue ' / label for field 5 TBCOL4 = 41 / beginning column of field 5 TFORM4 = 'D21.14 ' / Fortran-77 format of field TUNIT4 = 'km/s ' / physical unit of field EXTNAME = 'Test-ASCII' / name of this ASCII table extension EXTVER = 2 / extension version number TNULL1 = 'null1 ' / value for undefined pixels TNULL2 = 'null2 ' / value for undefined pixels TNULL3 = 'null4 ' / value for undefined pixels TNULL4 = 'null5 ' / value for undefined pixels TTYPE5 = 'INSERT_COL' / label for field TFORM5 = 'F14.6 ' / format of field TBCOL5 = 63 / beginning column of field END first string 1 1.00000E+00 1.00000000000000E+00 second string 2 2.00000E+00 2.00000000000000E+00 3 3.00000E+00 3.00000000000000E+00 null1 4 4.00000E+00 4.00000000000000E+00 5 5.00000E+00 5.00000000000000E+00 6 6.00000E+00 6.00000000000000E+00 9 9.00000E+00 9.00000000000000E+00 10 1.00000E+01 1.00000000000000E+01 null2 null4 null5 XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 61 / width of table in bytes NAXIS2 = 22 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 10 / number of fields in each row TTYPE1 = 'Avalue ' / label for field 1 TFORM1 = '15A ' / data format of field: ASCII Character TTYPE2 = 'Lvalue ' / label for field 2 TFORM2 = '1L ' / data format of field: 1-byte LOGICAL TUNIT2 = 'm**2 ' / physical unit of field TTYPE3 = 'Xvalue ' / label for field 3 TFORM3 = '16X ' / data format of field: BIT TUNIT3 = 'cm ' / physical unit of field TTYPE4 = 'Bvalue ' / label for field 4 TFORM4 = '1B ' / data format of field: BYTE TUNIT4 = 'erg/s ' / physical unit of field TTYPE5 = 'Ivalue ' / label for field 5 TFORM5 = '1I ' / data format of field: 2-byte INTEGER TUNIT5 = 'km/s ' / physical unit of field TTYPE6 = 'Evalue ' / label for field 7 TFORM6 = '1E ' / data format of field: 4-byte REAL TTYPE7 = 'Dvalue ' / label for field 8 TFORM7 = '1D ' / data format of field: 8-byte DOUBLE TTYPE9 = 'Cvalue ' / label for field 9 TFORM9 = '1C ' / data format of field: COMPLEX TTYPE10 = 'Mvalue ' / label for field 10 TFORM10 = '1M ' / data format of field: DOUBLE COMPLEX EXTNAME = 'Test-BINTABLE' / name of this binary table extension EXTVER = 1 / extension version number TNULL4 = 99 / value for undefined pixels TNULL5 = 99 / value for undefined pixels TDIM3 = '(1,2,8) ' / size of the multidimensional array KEY_PREC= 'This keyword was written by f_prec' / comment here TTYPE8 = 'INSERT_COL' / label for field TFORM8 = '1E ' / format of field END first string FLp?€?ðÿÿÿÿ?€À?ðÀsecond string Tð|@@ÿÿÿÿ@@À€@Àÿÿÿÿÿÿÿÿÿÿÿÿ F@@@ÿÿÿÿ@ ÀÀ@À FÿüÀ€Àÿÿÿÿ@àÁ@À T@ @ÿÿÿÿAÁ @"À$TÿúÀÀÀÿÿÿÿA0Á@@&À(F A@"ÿÿÿÿAˆÁ@1À2TÿöÁ À$A˜Á @3À4ccÿÿÿÿÿÿÿÿÿÿÿÿT A@@(FccÿÿÿÿÿÿÿÿÿÿÿÿFÿòÁ`À,FccÿÿÿÿÿÿÿÿÿÿÿÿFÿðÁ€À0TccÿÿÿÿÿÿÿÿÿÿÿÿTÿîÁÀ2TccÿÿÿÿÿÿÿÿÿÿÿÿTÿìÁ À4FccÿÿÿÿÿÿÿÿÿÿÿÿXTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 80 / width of table in bytes NAXIS2 = 20 / number of rows in table PCOUNT = 4446 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 10 / number of fields in each row TTYPE1 = 'Avalue ' / label for field 1 TFORM1 = '1PA(20) ' / data format of field: variable length array TTYPE2 = 'Lvalue ' / label for field 2 TFORM2 = '1PL(20) ' / data format of field: variable length array TUNIT2 = 'm**2 ' / physical unit of field TTYPE3 = 'Xvalue ' / label for field 3 TFORM3 = '1PB(3) ' / data format of field: variable length array TUNIT3 = 'cm ' / physical unit of field TTYPE4 = 'Bvalue ' / label for field 4 TFORM4 = '1PB(20) ' / data format of field: variable length array TUNIT4 = 'erg/s ' / physical unit of field TTYPE5 = 'Ivalue ' / label for field 5 TFORM5 = '1PI(20) ' / data format of field: variable length array TUNIT5 = 'km/s ' / physical unit of field TTYPE6 = 'Jvalue ' / label for field 6 TFORM6 = '1PJ(20) ' / data format of field: variable length array TTYPE7 = 'Evalue ' / label for field 7 TFORM7 = '1PE(20) ' / data format of field: variable length array TTYPE8 = 'Dvalue ' / label for field 8 TFORM8 = '1PD(20) ' / data format of field: variable length array TTYPE9 = 'Cvalue ' / label for field 9 TFORM9 = '1PC(0) ' / data format of field: variable length array TTYPE10 = 'Mvalue ' / label for field 10 TFORM10 = '1PM(0) ' / data format of field: variable length array EXTNAME = 'Test-BINTABLE' / name of this binary table extension EXTVER = 4 / extension version number TNULL4 = 88 / value for undefined pixels TNULL5 = 88 / value for undefined pixels TNULL6 = 88 / value for undefined pixels END  !)1ADGHKQ]i…‰ŠŽ–¦¶ÖÛàáæð@FLMS_w¿ÆÍÎÕãÿS[cdl|œ¼ ü    + O s » ÅÏ Ñ Û ï  ?  𥠧 ² È ô  x „ ’ ž ¶ æ  v ƒ ’ Ÿ ¹ í !‰—¥§µÑ A±ÀÏÑàþ : v î þ    @ € À @ Q b e v ˜ Ü  ¨ º Ì Ï á  M •%8KNa‡Ó·Ëßâön¾F?€?ðabT@XXXÿÿÿÿ@ÿÿÿÿÿÿÿÿ@abcFF@XXX?€ÿÿÿÿ@@?ðÿÿÿÿÿÿÿÿ@abcdFTF@XXX?€@ÿÿÿÿ@€?ð@ÿÿÿÿÿÿÿÿ@abcdeFTFTHXXX?€@@@ÿÿÿÿ@ ?ð@@ÿÿÿÿÿÿÿÿ@abcdefFTFFTLXXX?€@@@@€ÿÿÿÿ@À?ð@@@ÿÿÿÿÿÿÿÿ@abcdefgFTFFTFLXXX?€@@@@€@ ÿÿÿÿ@à?ð@@@@ÿÿÿÿÿÿÿÿ@abcdefghFTFFTTFLXXX?€@@@@€@ @ÀÿÿÿÿA?ð@@@@@ÿÿÿÿÿÿÿÿ@ abcdefghiFTFFTTFFLX X X ?€@@@@€@ @À@àÿÿÿÿA?ð@@@@@@ÿÿÿÿÿÿÿÿ@"abcdefghijFTFFTTFFTL@X X X ?€@@@@€@ @À@àAÿÿÿÿA ?ð@@@@@@@ ÿÿÿÿÿÿÿÿ@$abcdefghijkFTFFTTFFFTL` X  X  X ?€@@@@€@ @À@àAAÿÿÿÿA0?ð@@@@@@@ @"ÿÿÿÿÿÿÿÿ@&abcdefghijklFTFFTTFFFTTLp X  X  X ?€@@@@€@ @À@àAAA ÿÿÿÿA@?ð@@@@@@@ @"@$ÿÿÿÿÿÿÿÿ@(abcdefghijklmFTFFTTFFFTTFLp X  X  X ?€@@@@€@ @À@àAAA A0ÿÿÿÿAP?ð@@@@@@@ @"@$@&ÿÿÿÿÿÿÿÿ@*abcdefghijklmnFTFFTTFFFTTTFLp X X X?€@@@@€@ @À@àAAA A0A@ÿÿÿÿA`?ð@@@@@@@ @"@$@&@(ÿÿÿÿÿÿÿÿ@,abcdefghijklmnoFTFFTTFFFTTTFFLp X X X?€@@@@€@ @À@àAAA A0A@APÿÿÿÿAp?ð@@@@@@@ @"@$@&@(@*ÿÿÿÿÿÿÿÿ@.abcdefghijklmnopFTFFTTFFFTTTFFFLp X X X?€@@@@€@ @À@àAAA A0A@APA`ÿÿÿÿA€?ð@@@@@@@ @"@$@&@(@*@,ÿÿÿÿÿÿÿÿ@0abcdefghijklmnopqFTFFTTFFFTTTFFFTLp€ X X X?€@@@@€@ @À@àAAA A0A@APA`ApÿÿÿÿAˆ?ð@@@@@@@ @"@$@&@(@*@,@.ÿÿÿÿÿÿÿÿ@1abcdefghijklmnopqrFTFFTTFFFTTTFFFFTLpÀ X X X?€@@@@€@ @À@àAAA A0A@APA`ApA€ÿÿÿÿA?ð@@@@@@@ @"@$@&@(@*@,@.@0ÿÿÿÿÿÿÿÿ@2abcdefghijklmnopqrsFTFFTTFFFTTTFFFFTTLpà X X X?€@@@@€@ @À@àAAA A0A@APA`ApA€AˆÿÿÿÿA˜?ð@@@@@@@ @"@$@&@(@*@,@.@0@1ÿÿÿÿÿÿÿÿ@3abcdefghijklmnopqrstFTFFTTFFFTTTFFFFTTTLpð X X X?€@@@@€@ @À@àAAA A0A@APA`ApA€AˆAÿÿÿÿA ?ð@@@@@@@ @"@$@&@(@*@,@.@0@1@2ÿÿÿÿÿÿÿÿ@4XTENSION= 'IMAGE ' / IMAGE extension BITPIX = 32 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 10 / length of data axis 1 NAXIS2 = 2 / length of data axis 2 PCOUNT = 0 / required keyword; must = 0 GCOUNT = 1 / required keyword; must = 1 CRVAL1 = 4.5830000000E+01 / comment CRVAL2 = 6.3570000000E+01 / comment CRPIX1 = 2.5600000000E+02 / comment CRPIX2 = 2.5700000000E+02 / comment CDELT1 = -2.7777700000E-03 / comment CDELT2 = 2.7777700000E-03 / comment CTYPE1 = 'RA---TAN' / comment CTYPE2 = 'DEC--TAN' / comment END  XTENSION= 'TABLE ' / ASCII table extension BITPIX = 8 / 8-bit ASCII characters NAXIS = 2 / 2-dimensional ASCII table NAXIS1 = 80 / width of table in characters NAXIS2 = 11 / number of rows in table PCOUNT = 0 / no group parameters (required keyword) GCOUNT = 1 / one data group (required keyword) TFIELDS = 5 / number of fields in each row TTYPE1 = 'Name ' / label for field 1 TBCOL1 = 1 / beginning column of field 1 TFORM1 = 'A15 ' / Fortran-77 format of field TTYPE2 = 'Ivalue ' / label for field 2 TBCOL2 = 17 / beginning column of field 2 TFORM2 = 'I11 ' / Fortran-77 format of field TUNIT2 = 'm**2 ' / physical unit of field TTYPE3 = 'Fvalue ' / label for field 3 TBCOL3 = 29 / beginning column of field 3 TFORM3 = 'F15.6 ' / Fortran-77 format of field TUNIT3 = 'cm ' / physical unit of field TTYPE4 = 'Evalue ' / label for field 4 TBCOL4 = 45 / beginning column of field 4 TFORM4 = 'E13.5 ' / Fortran-77 format of field TUNIT4 = 'erg/s ' / physical unit of field TTYPE5 = 'Dvalue ' / label for field 5 TBCOL5 = 59 / beginning column of field 5 TFORM5 = 'D22.14 ' / Fortran-77 format of field TUNIT5 = 'km/s ' / physical unit of field EXTNAME = 'new_table' / name of this ASCII table extension EXTVER = 5 / extension version number END first string 0 0.000000 0.00000E+00 0.00000000000000E+00second string 3 3.000000 3.00000E+00 3.00000000000000E+00 6 6.000000 6.00000E+00 6.00000000000000E+00 9 9.000000 9.00000E+00 9.00000000000000E+00 12 12.000000 1.20000E+01 1.20000000000000E+01 15 15.000000 1.50000E+01 1.50000000000000E+01 18 18.000000 1.80000E+01 1.80000000000000E+01 21 21.000000 2.10000E+01 2.10000000000000E+01 24 24.000000 2.40000E+01 2.40000000000000E+01 27 27.000000 2.70000E+01 2.70000000000000E+01 cfitsio-4.3.1/README_OLD.win0000644000225700000360000000671613472024437014637 0ustar cagordonlhea=============================================================================== =============================================================================== = NOTE: This is the old version of the README.win32 file that was distributed = with CFITSIO up until version 3.35 in 2013. These instruction may still work = with more recent versions of CFITSIO, however, users are strongly urged to = use the CMake procedures that are now documented in the new README.win32 file. =============================================================================== =============================================================================== Instructions on using CFITSIO on Windows platforms for C programmers These instructions use a simple DOS-style command window. It is also possible to build and use CFITSIO within a GUI programming environment such as Visual Studio, but this is not supported here. =============================================================================== 1. Build the CFITSIO dll library This step will create the cfitsio.def, cfitsio.dll, and cfitsio.lib files. (If you downloaded the CFITSIO .zip file that contains the pre-built binary .dll file, then SKIP THIS STEP). A. With Microsoft Visual C++: 1. Open a DOS command window and execute the vcvars32.bat file that is distributed with older versions of Visual C++, or simply open the Visual C++ command window (e.g., when using Visual Studio 2010). 2. Unpack the CFITSIO source files (cfitxxxx.zip) into a new empty directory 3. In the DOS command window, cd to that directory and enter the following commands: nmake winDumpExts.mak nmake makefile.vcc (ignore the compiler warning messages) B: With Borland C++: First, follow the instructions provided by Borland to set up the proper environment variables and configure files for the compiler. Unpack the cfitsio.zip source file distribution into a suitable directory. In a DOS command window, cd to that directory and then execute the makepc.bat batch file on the command line to build the CFITSIO library, and the testprog and cookbook sample programs. =============================================================================== 2. Test the CFITSIO library with Visual C++ Compile and link the testprog.c test program. When using Visual Studio, the command is: cl /MD testprog.c cfitsio.lib This will create the testprog.exe executable program. Running this program should print out a long series of diagnostic messages that should end with "Status = 0; OK - no error" =============================================================================== 3. Compile and link an application program that calls CFITSIO routines with Visual C++ Include the fitsio.h and longnam.h header files in the C source code. Link the program with the cfitsio.lib file: cl /MD your_program.c cfitsio.lib NOTE: The /MD command line switch must be specified on the cl command line to force the compiler/linker to use the appropriete runtime library. If this switch is omitted, then the fits_report_error function in CFITSIO will likely crash. When building programs in the Visual Studio environment, one can force the equivalent of the /MD switch by selecting 'Settings...' under the 'Project' menu, then click on the C/C++ tab and select the 'Code Generator' category. Then under 'User Run-time Library' select 'Multithreaded DLL'. cfitsio-4.3.1/fpackutil.c0000644000225700000360000023110313717263734014610 0ustar cagordonlhea/* FPACK utility routines R. Seaman, NOAO & W. Pence, NASA/GSFC */ #include #include #include #include /* #include "bzlib.h" only for experimental purposes */ #if defined(unix) || defined(__unix__) || defined(__unix) #include #endif #include #include "fitsio.h" #include "fpack.h" /* these filename buffer are used to delete temporary files */ /* in case the program is aborted */ char tempfilename[SZ_STR]; char tempfilename2[SZ_STR]; char tempfilename3[SZ_STR]; /* nearest integer function */ # define NINT(x) ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5)) # define NSHRT(x) ((x >= 0.) ? (short) (x + 0.5) : (short) (x - 0.5)) /* define variables for measuring elapsed time */ clock_t scpu, ecpu; long startsec; /* start of elapsed time interval */ int startmilli; /* start of elapsed time interval */ /* CLOCKS_PER_SEC should be defined by most compilers */ #if defined(CLOCKS_PER_SEC) #define CLOCKTICKS CLOCKS_PER_SEC #else /* on SUN OS machine, CLOCKS_PER_SEC is not defined, so set its value */ #define CLOCKTICKS 1000000 #endif FILE *outreport; /* dimension of central image area to be sampled for test statistics */ int XSAMPLE = 4100; int YSAMPLE = 4100; int fp_msg (char *msg) { printf ("%s", msg); return(0); } /*--------------------------------------------------------------------------*/ int fp_noop (void) { fp_msg ("Input and output files are unchanged.\n"); return(0); } /*--------------------------------------------------------------------------*/ void fp_abort_output (fitsfile *infptr, fitsfile *outfptr, int stat) { int status = 0, hdunum; char msg[SZ_STR]; if (infptr) { fits_file_name(infptr, tempfilename, &status); fits_get_hdu_num(infptr, &hdunum); fits_close_file (infptr, &status); snprintf(msg, SZ_STR,"Error processing file: %s\n", tempfilename); fp_msg (msg); snprintf(msg, SZ_STR," in HDU number %d\n", hdunum); fp_msg (msg); } else { snprintf(msg, SZ_STR,"Error: Unable to process input file\n"); fp_msg(msg); } fits_report_error (stderr, stat); if (outfptr) { fits_delete_file(outfptr, &status); fp_msg ("Input file is unchanged.\n"); } exit (stat); } /*--------------------------------------------------------------------------*/ int fp_version (void) { float version; char cfitsioversion[40]; fp_msg (FPACK_VERSION); fits_get_version(&version); snprintf(cfitsioversion, 40," CFITSIO version %5.3f", version); fp_msg(cfitsioversion); fp_msg ("\n"); return(0); } /*--------------------------------------------------------------------------*/ int fp_access (char *filename) { /* test if a file exists */ FILE *diskfile; diskfile = fopen(filename, "r"); if (diskfile) { fclose(diskfile); return(0); } else { return(-1); } } /*--------------------------------------------------------------------------*/ int fp_tmpnam(char *suffix, char *rootname, char *tmpnam) { /* create temporary file name */ int maxtry = 30, ii; if (strlen(suffix) + strlen(rootname) > SZ_STR-5) { fp_msg ("Error: filename is too long to create temporary file\n"); exit (-1); } strcpy (tmpnam, rootname); /* start with rootname */ strcat(tmpnam, suffix); /* append the suffix */ maxtry = SZ_STR - strlen(tmpnam) - 1; for (ii = 0; ii < maxtry; ii++) { if (fp_access(tmpnam)) break; /* good, the file does not exist */ if (strlen(tmpnam) > SZ_STR-2) { fp_msg ("\nCould not create temporary file name:\n"); fp_msg (tmpnam); fp_msg ("\n"); exit (-1); } strcat(tmpnam, "x"); /* append an x to the name, and try again */ } if (ii == maxtry) { fp_msg ("\nCould not create temporary file name:\n"); fp_msg (tmpnam); fp_msg ("\n"); exit (-1); } return(0); } /*--------------------------------------------------------------------------*/ int fp_init (fpstate *fpptr) { int ii; fpptr->comptype = RICE_1; fpptr->quantize_level = DEF_QLEVEL; fpptr->no_dither = 0; fpptr->dither_method = 1; fpptr->dither_offset = 0; fpptr->int_to_float = 0; /* thresholds when using the -i2f flag */ fpptr->n3ratio = 2.0; /* minimum ratio of image noise sigma / q */ fpptr->n3min = 6.; /* minimum noise sigma. */ fpptr->scale = DEF_HCOMP_SCALE; fpptr->smooth = DEF_HCOMP_SMOOTH; fpptr->rescale_noise = DEF_RESCALE_NOISE; fpptr->ntile[0] = (long) -1; /* -1 means extent of axis */ for (ii=1; ii < MAX_COMPRESS_DIM; ii++) fpptr->ntile[ii] = (long) 1; fpptr->to_stdout = 0; fpptr->listonly = 0; fpptr->clobber = 0; fpptr->delete_input = 0; fpptr->do_not_prompt = 0; fpptr->do_checksums = 1; fpptr->do_gzip_file = 0; fpptr->do_tables = 0; /* this is intended for testing purposes */ fpptr->do_images = 1; /* can be turned off with -tableonly switch */ fpptr->test_all = 0; fpptr->verbose = 0; fpptr->prefix[0] = 0; fpptr->extname[0] = 0; fpptr->delete_suffix = 0; fpptr->outfile[0] = 0; fpptr->firstfile = 1; /* magic number for initialization check, boolean for preflight */ fpptr->initialized = FP_INIT_MAGIC; fpptr->preflight_checked = 0; return(0); } /*--------------------------------------------------------------------------*/ int fp_list (int argc, char *argv[], fpstate fpvar) { fitsfile *infptr; char infits[SZ_STR], msg[SZ_STR]; int hdunum, iarg, stat=0; LONGLONG sizell; if (fpvar.initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } for (iarg=fpvar.firstfile; iarg < argc; iarg++) { strncpy (infits, argv[iarg], SZ_STR-1); infits[SZ_STR-1]=0; if (strchr (infits, '[') || strchr (infits, ']')) { fp_msg ("Error: section/extension notation not supported: "); fp_msg (infits); fp_msg ("\n"); exit (-1); } if (fp_access (infits) != 0) { fp_msg ("Error: can't find or read input file "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } fits_open_file (&infptr, infits, READONLY, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } /* move to the end of file, to get the total size in bytes */ fits_get_num_hdus (infptr, &hdunum, &stat); fits_movabs_hdu (infptr, hdunum, NULL, &stat); fits_get_hduaddrll(infptr, NULL, NULL, &sizell, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } snprintf (msg, SZ_STR,"# %s (", infits); fp_msg (msg); #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ snprintf(msg, SZ_STR,"%I64d bytes)\n", sizell); fp_msg (msg); #elif (USE_LL_SUFFIX == 1) snprintf(msg, SZ_STR,"%lld bytes)\n", sizell); fp_msg (msg); #else snprintf(msg, SZ_STR,"%ld bytes)\n", sizell); fp_msg (msg); #endif fp_info_hdu (infptr); fits_close_file (infptr, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } } return(0); } /*--------------------------------------------------------------------------*/ int fp_info_hdu (fitsfile *infptr) { long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; char msg[SZ_STR], val[SZ_CARD], com[SZ_CARD]; int naxis=0, hdutype, bitpix, hdupos, stat=0, ii; unsigned long datasum, hdusum; fits_movabs_hdu (infptr, 1, NULL, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } for (hdupos=1; ! stat; hdupos++) { fits_get_hdu_type (infptr, &hdutype, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } /* fits_get_hdu_type calls unknown extensions "IMAGE_HDU" * so consult XTENSION keyword itself */ fits_read_keyword (infptr, "XTENSION", val, com, &stat); if (stat == KEY_NO_EXIST) { /* in primary HDU which by definition is an "image" */ stat=0; /* clear for later error handling */ } else if (stat) { fp_abort_output(infptr, NULL, stat); } else if (hdutype == IMAGE_HDU) { /* that is, if XTENSION != "IMAGE" AND != "BINTABLE" */ if (strncmp (val+1, "IMAGE", 5) && strncmp (val+1, "BINTABLE", 5)) { /* assign something other than any of these */ hdutype = IMAGE_HDU + ASCII_TBL + BINARY_TBL; } } fits_get_chksum(infptr, &datasum, &hdusum, &stat); if (hdutype == IMAGE_HDU) { snprintf (msg, SZ_STR," %d IMAGE", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, &stat); snprintf (msg, SZ_STR," BITPIX=%d", bitpix); fp_msg (msg); if (naxis == 0) { snprintf (msg, SZ_STR," [no_pixels]"); fp_msg (msg); } else if (naxis == 1) { snprintf (msg, SZ_STR," [%ld]", naxes[1]); fp_msg (msg); } else { snprintf (msg, SZ_STR," [%ld", naxes[0]); fp_msg (msg); for (ii=1; ii < naxis; ii++) { snprintf (msg, SZ_STR,"x%ld", naxes[ii]); fp_msg (msg); } fp_msg ("]"); } if (fits_is_compressed_image (infptr, &stat)) { fits_read_keyword (infptr, "ZCMPTYPE", val, com, &stat); /* allow for quote in keyword value */ if (! strncmp (val+1, "RICE_1", 6)) fp_msg (" tiled_rice\n"); else if (! strncmp (val+1, "GZIP_1", 6)) fp_msg (" tiled_gzip_1\n"); else if (! strncmp (val+1, "GZIP_2", 6)) fp_msg (" tiled_gzip_2\n"); else if (! strncmp (val+1, "PLIO_1", 6)) fp_msg (" tiled_plio\n"); else if (! strncmp (val+1, "HCOMPRESS_1", 11)) fp_msg (" tiled_hcompress\n"); else fp_msg (" unknown\n"); } else fp_msg (" not_tiled\n"); } else if (hdutype == ASCII_TBL) { snprintf (msg, SZ_STR," %d ASCII_TBL", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu\n", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); } else if (hdutype == BINARY_TBL) { snprintf (msg, SZ_STR," %d BINARY_TBL", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu\n", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); } else { snprintf (msg, SZ_STR," %d OTHER", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); snprintf (msg, SZ_STR," %s\n", val); fp_msg (msg); } fits_movrel_hdu (infptr, 1, NULL, &stat); } return(0); } /*--------------------------------------------------------------------------*/ int fp_preflight (int argc, char *argv[], int unpack, fpstate *fpptr) { char infits[SZ_STR], outfits[SZ_STR]; int iarg, namelen, nfiles = 0; if (fpptr->initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } for (iarg=fpptr->firstfile; iarg < argc; iarg++) { outfits[0] = '\0'; if (strlen(argv[iarg]) > SZ_STR - 4) { /* allow for .fz or .gz suffix */ fp_msg ("Error: input file name\n "); fp_msg (argv[iarg]); fp_msg ("\n is too long\n"); fp_noop (); exit (-1); } strncpy (infits, argv[iarg], SZ_STR); if (infits[0] == '-' && infits[1] != '\0') { /* don't interpret this as intending to read input file from stdin */ fp_msg ("Error: invalid input file name\n "); fp_msg (argv[iarg]); fp_msg ("\n"); fp_noop (); exit (-1); } if (strchr (infits, '[') || strchr (infits, ']')) { fp_msg ("Error: section/extension notation not supported: "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } if (unpack) { /* ********** This section applies to funpack ************ */ /* check that input file exists */ if (infits[0] != '-') { /* if not reading from stdin stream */ if (fp_access (infits) != 0) { /* if not, then check if */ strcat(infits, ".fz"); /* a .fz version exsits */ if (fp_access (infits) != 0) { namelen = strlen(infits); infits[namelen - 3] = '\0'; /* remove the .fz suffix */ fp_msg ("Error: can't find or read input file "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } } else { /* make sure a .fz version of the same file doesn't exist */ namelen = strlen(infits); strcat(infits, ".fz"); if (fp_access (infits) == 0) { infits[namelen] = '\0'; /* remove the .fz suffix */ fp_msg ("Error: ambiguous input file name. Which file should be unpacked?:\n "); fp_msg (infits); fp_msg ("\n "); fp_msg (infits); fp_msg (".fz\n"); fp_noop (); exit (-1); } else { infits[namelen] = '\0'; /* remove the .fz suffix */ } } } /* if writing to stdout, then we are all done */ if (fpptr->to_stdout) { continue; } if (fpptr->outfile[0]) { /* user specified output file name */ nfiles++; if (nfiles > 1) { fp_msg ("Error: cannot use same output file name for multiple files:\n "); fp_msg (fpptr->outfile); fp_msg ("\n"); fp_noop (); exit (-1); } /* check that output file doesn't exist */ if (fp_access (fpptr->outfile) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (fpptr->outfile); fp_msg ("\n "); fp_noop (); exit (-1); } continue; } /* construct output file name to test */ if (fpptr->prefix[0]) { if (strlen(fpptr->prefix) + strlen(infits) > SZ_STR - 1) { fp_msg ("Error: output file name for\n "); fp_msg (infits); fp_msg ("\n is too long with the prefix\n"); fp_noop (); exit (-1); } strcpy(outfits,fpptr->prefix); } /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "output.fits"); } else { strcat(outfits, infits); } /* remove .gz or .bz2 suffix, if present (output is not gzipped) */ namelen = strlen(outfits); if (namelen >= 3 && !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } else if (namelen >= 4 && !strcmp(".bz2", outfits + namelen - 4)) { outfits[namelen - 4] = '\0'; } /* check for .fz suffix that is sometimes required */ /* and remove it if present */ if (infits[0] != '-') { /* if not reading from stdin stream */ namelen = strlen(outfits); if (namelen>=3 && !strcmp(".fz", outfits + namelen - 3) ) { /* suffix is present */ outfits[namelen - 3] = '\0'; } else if (fpptr->delete_suffix) { /* required suffix is missing */ fp_msg ("Error: input compressed file "); fp_msg (infits); fp_msg ("\n does not have the default .fz suffix.\n"); fp_noop (); exit (-1); } } /* if infits != outfits, make sure outfits doesn't already exist */ if (strcmp(infits, outfits)) { if (fp_access (outfits) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } } /* if gzipping the output, make sure .gz file doesn't exist */ if (fpptr->do_gzip_file) { if (strlen(outfits)+3 > SZ_STR-1) { fp_msg ("Error: output file name too long:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } strcat(outfits, ".gz"); if (fp_access (outfits) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } namelen = strlen(outfits); outfits[namelen - 3] = '\0'; /* remove the .gz suffix again */ } } else { /* ********** This section applies to fpack ************ */ /* check that input file exists */ if (infits[0] != '-') { /* if not reading from stdin stream */ if (fp_access (infits) != 0) { /* if not, then check if */ if (strlen(infits)+3 > SZ_STR-1) { fp_msg ("Error: input file name too long:\n "); fp_msg (infits); fp_msg ("\n "); fp_noop (); exit (-1); } strcat(infits, ".gz"); /* a gzipped version exsits */ if (fp_access (infits) != 0) { namelen = strlen(infits); infits[namelen - 3] = '\0'; /* remove the .gz suffix */ fp_msg ("Error: can't find or read input file "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } } } /* make sure the file to pack does not already have a .fz suffix */ namelen = strlen(infits); if (namelen>=3 && !strcmp(".fz", infits + namelen - 3) ) { fp_msg ("Error: fpack input file already has '.fz' suffix\n" ); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } /* if writing to stdout, or just testing the files, then we are all done */ if (fpptr->to_stdout || fpptr->test_all) { continue; } if (fpptr->outfile[0]) { /* user specified output file name */ nfiles++; if (nfiles > 1) { fp_msg("Error: cannot use same output file name for multiple files:\n "); fp_msg(fpptr->outfile); fp_msg ("\n"); fp_noop (); exit (-1); } /* check that output file doesn't exist */ if (fp_access (fpptr->outfile) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (fpptr->outfile); fp_msg ("\n "); fp_noop (); exit (-1); } continue; } /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "input.fits"); } else { strcpy(outfits, infits); } /* remove .gz suffix, if present (output is not gzipped) */ /* do the same if compression suffix is bz2 */ namelen = strlen(outfits); if (namelen >=3 && !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } else if (namelen >= 4 && !strcmp(".bz2", outfits + namelen - 4)) { outfits[namelen - 4] = '\0'; } /* remove .imh suffix (IRAF format image), and replace with .fits */ namelen = strlen(outfits); if (namelen >=4 && !strcmp(".imh", outfits + namelen - 4) ) { outfits[namelen - 4] = '\0'; if (strlen(outfits) == SZ_STR-5) strcat(outfits, ".fit"); else strcat(outfits, ".fits"); } /* If not clobbering the input file, add .fz suffix to output name */ if (! fpptr->clobber) { if (strlen(outfits) > SZ_STR-4) { fp_msg ("Error: output file name too long:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } else strcat(outfits, ".fz"); } /* if infits != outfits, make sure outfits doesn't already exist */ if (strcmp(infits, outfits)) { if (fp_access (outfits) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } } } /* end of fpack section */ } fpptr->preflight_checked++; return(0); } /*--------------------------------------------------------------------------*/ /* must run fp_preflight() before fp_loop() */ int fp_loop (int argc, char *argv[], int unpack, fpstate fpvar) { char infits[SZ_STR], outfits[SZ_STR]; char temp[SZ_STR], answer[30]; char valchar[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.#()+,-_@[]/^{}"; int ichar=0, outlen=0, iarg, islossless, namelen, iraf_infile = 0, status = 0, ifail; if (fpvar.initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } else if (! fpvar.preflight_checked) { fp_msg ("Error: internal preflight error\n"); exit (-1); } if (fpvar.test_all && fpvar.outfile[0]) { outreport = fopen(fpvar.outfile, "w"); fprintf(outreport," Filename Extension BITPIX NAXIS1 NAXIS2 Size N_nulls Minval Maxval Mean Sigm Noise1 Noise2 Noise3 Noise5 T_whole T_rowbyrow "); fprintf(outreport,"[Comp_ratio, Pack_cpu, Unpack_cpu, Lossless readtimes] (repeated for Rice, Hcompress, and GZIP)\n"); } tempfilename[0] = '\0'; tempfilename2[0] = '\0'; tempfilename3[0] = '\0'; /* set up signal handler to delete temporary file on abort */ #ifdef SIGINT if (signal(SIGINT, SIG_IGN) != SIG_IGN) { (void) signal(SIGINT, abort_fpack); } #endif #ifdef SIGTERM if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { (void) signal(SIGTERM, abort_fpack); } #endif #ifdef SIGHUP if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { (void) signal(SIGHUP, abort_fpack); } #endif for (iarg=fpvar.firstfile; iarg < argc; iarg++) { temp[0] = '\0'; outfits[0] = '\0'; islossless = 1; strncpy (infits, argv[iarg], SZ_STR - 1); infits[SZ_STR-1]=0; if (unpack) { /* ********** This section applies to funpack ************ */ /* find input file */ if (infits[0] != '-') { /* if not reading from stdin stream */ if (fp_access (infits) != 0) { /* if not, then */ strcat(infits, ".fz"); /* a .fz version must exsit */ /* fp_preflight already checked for enough size to add '.fz' */ } } if (fpvar.to_stdout) { strcpy(outfits, "-"); } else if (fpvar.outfile[0]) { /* user specified output file name */ strcpy(outfits, fpvar.outfile); } else { /* construct output file name */ if (fpvar.prefix[0]) { /* fp_preflight already checked this */ strcpy(outfits,fpvar.prefix); } /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "output.fits"); } else { strcat(outfits, infits); } /* remove .gz suffix, if present (output is not gzipped) */ namelen = strlen(outfits); if (namelen >= 3 && !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } else if (namelen >= 4 && !strcmp(".bz2", outfits + namelen - 4)) { outfits[namelen - 4] = '\0'; } /* check for .fz suffix that is sometimes required */ /* and remove it if present */ namelen = strlen(outfits); if (namelen >= 3 && !strcmp(".fz", outfits + namelen - 3) ) { /* suffix is present */ outfits[namelen - 3] = '\0'; } } } else { /* ********** This section applies to fpack ************ */ if (fpvar.to_stdout) { strcpy(outfits, "-"); } else if (! fpvar.test_all) { if (fpvar.outfile[0]) { /* user specified output file name */ strcpy(outfits, fpvar.outfile); } else { /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "input.fits"); } else { strcpy(outfits, infits); } /* Remove .gz suffix, if present (output is not gzipped). Do the same for .bz2 */ namelen = strlen(outfits); if (namelen >= 3 && !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } else if (namelen >= 4 && !strcmp(".bz2", outfits + namelen - 4)) { outfits[namelen - 4] = '\0'; } /* remove .imh suffix (IRAF format image), and replace with .fits */ namelen = strlen(outfits); if (namelen >= 4 && !strcmp(".imh", outfits + namelen - 4) ) { outfits[namelen - 4] = '\0'; if (strlen(outfits) == SZ_STR-5) strcat(outfits, ".fit"); else strcat(outfits, ".fits"); iraf_infile = 1; /* this is an IRAF format input file */ /* change the output name to "NAME.fits.fz" */ } /* If not clobbering the input file, add .fz suffix to output name */ if (! fpvar.clobber) strcat(outfits, ".fz"); } } } strncpy(temp, outfits, SZ_STR-1); temp[SZ_STR-1]=0; if (infits[0] != '-') { /* if not reading from stdin stream */ if (!strcmp(infits, outfits) ) { /* are input and output names the same? */ /* clobber the input file with the output file with the same name */ if (! fpvar.clobber) { fp_msg ("\nError: must use -F flag to clobber input file.\n"); exit (-1); } /* create temporary file name in the output directory (same as input directory)*/ fp_tmpnam("Tmp1", infits, outfits); strcpy(tempfilename, outfits); /* store temp file name, in case of abort */ } } /* *************** now do the real work ********************* */ if (fpvar.verbose && ! fpvar.to_stdout) printf("%s ", infits); if (fpvar.test_all) { /* compare all the algorithms */ /* create 2 temporary file names, in the CWD */ fp_tmpnam("Tmpfile1", "", tempfilename); fp_tmpnam("Tmpfile2", "", tempfilename2); fp_test (infits, tempfilename, tempfilename2, fpvar); remove(tempfilename); tempfilename[0] = '\0'; /* clear the temp file name */ remove(tempfilename2); tempfilename2[0] = '\0'; continue; } else if (unpack) { if (fpvar.to_stdout) { /* unpack the input file to the stdout stream */ fp_unpack (infits, outfits, fpvar); } else { /* unpack to temporary file, so other tasks can't open it until it is renamed */ /* create temporary file name, in the output directory */ fp_tmpnam("Tmp2", outfits, tempfilename2); /* unpack the input file to the temporary file */ fp_unpack (infits, tempfilename2, fpvar); /* rename the temporary file to it's real name */ ifail = rename(tempfilename2, outfits); if (ifail) { fp_msg("Failed to rename temporary file name:\n "); fp_msg(tempfilename2); fp_msg(" -> "); fp_msg(outfits); fp_msg("\n"); exit (-1); } else { tempfilename2[0] = '\0'; /* clear temporary file name */ } } } else { fp_pack (infits, outfits, fpvar, &islossless); } if (fpvar.to_stdout) { continue; } /* ********** clobber and/or delete files, if needed ************** */ if (!strcmp(infits, temp) && fpvar.clobber ) { if (!islossless && ! fpvar.do_not_prompt) { fp_msg ("\nFile "); fp_msg (infits); fp_msg ("\nwas compressed with a LOSSY method. Overwrite the\n"); fp_msg ("original file with the compressed version? (Y/N) "); fgets(answer, 29, stdin); if (answer[0] != 'Y' && answer[0] != 'y') { fp_msg ("\noriginal file NOT overwritten!\n"); remove(outfits); continue; } } if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ if (fits_delete_iraf_file(infits, &status)) { fp_msg("\nError deleting IRAF .imh and .pix files.\n"); fp_msg(infits); fp_msg ("\n"); exit (-1); } } #if defined(unix) || defined(__unix__) || defined(__unix) /* rename clobbers input on Unix platforms */ if (rename (outfits, temp) != 0) { fp_msg ("\nError renaming tmp file to "); fp_msg (temp); fp_msg ("\n"); exit (-1); } #else /* rename DOES NOT clobber existing files on Windows platforms */ /* so explicitly remove any existing file before renaming the file */ remove(temp); if (rename (outfits, temp) != 0) { fp_msg ("\nError renaming tmp file to "); fp_msg (temp); fp_msg ("\n"); exit (-1); } #endif tempfilename[0] = '\0'; /* clear temporary file name */ strcpy(outfits, temp); } else if (fpvar.clobber || fpvar.delete_input) { /* delete the input file */ if (!islossless && !fpvar.do_not_prompt) { /* user did not turn off delete prompt */ fp_msg ("\nFile "); fp_msg (infits); fp_msg ("\nwas compressed with a LOSSY method. \n"); fp_msg ("Delete the original file? (Y/N) "); fgets(answer, 29, stdin); if (answer[0] != 'Y' && answer[0] != 'y') { /* user abort */ fp_msg ("\noriginal file NOT deleted!\n"); } else { if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ if (fits_delete_iraf_file(infits, &status)) { fp_msg("\nError deleting IRAF .imh and .pix files.\n"); fp_msg(infits); fp_msg ("\n"); exit (-1); } } else if (remove(infits) != 0) { /* normal case of deleting input FITS file */ fp_msg ("\nError deleting input file "); fp_msg (infits); fp_msg ("\n"); exit (-1); } } } else { /* user said don't prompt, so just delete the input file */ if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ if (fits_delete_iraf_file(infits, &status)) { fp_msg("\nError deleting IRAF .imh and .pix files.\n"); fp_msg(infits); fp_msg ("\n"); exit (-1); } } else if (remove(infits) != 0) { /* normal case of deleting input FITS file */ fp_msg ("\nError deleting input file "); fp_msg (infits); fp_msg ("\n"); exit (-1); } } } iraf_infile = 0; if (fpvar.do_gzip_file) { /* gzip the output file */ strcpy(temp, "gzip -1 "); outlen = strlen(outfits); if (outlen + 8 > SZ_STR-1) { fp_msg("\nError: Output file name is too long.\n"); exit(-1); } for (ichar=0; ichar < outlen; ++ichar) { if (!strchr(valchar, outfits[ichar])) { fp_msg("\n Error: Invalid characters in output file name.\n"); exit(-1); } } strcat(temp,outfits); system(temp); strcat(outfits, ".gz"); /* only possibible with funpack */ } if (fpvar.verbose && ! fpvar.to_stdout) printf("-> %s\n", outfits); } if (fpvar.test_all && fpvar.outfile[0]) fclose(outreport); return(0); } /*--------------------------------------------------------------------------*/ /* fp_pack assumes the output file does not exist (checked by preflight) */ int fp_pack (char *infits, char *outfits, fpstate fpvar, int *islossless) { fitsfile *infptr, *outfptr; int stat=0; fits_open_file (&infptr, infits, READONLY, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } fits_create_file (&outfptr, outfits, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } if (stat) { fp_abort_output(infptr, outfptr, stat); } while (! stat) { /* LOOP OVER EACH HDU */ fits_set_lossy_int (outfptr, fpvar.int_to_float, &stat); fits_set_compression_type (outfptr, fpvar.comptype, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_pack_hdu (infptr, outfptr, fpvar, islossless, &stat); if (fpvar.do_checksums) { fits_write_chksum (outfptr, &stat); } fits_movrel_hdu (infptr, 1, NULL, &stat); } if (stat == END_OF_FILE) stat = 0; /* set checksum for case of newly created primary HDU */ if (fpvar.do_checksums) { fits_movabs_hdu (outfptr, 1, NULL, &stat); fits_write_chksum (outfptr, &stat); } if (stat) { fp_abort_output(infptr, outfptr, stat); } fits_close_file (outfptr, &stat); fits_close_file (infptr, &stat); return(0); } /*--------------------------------------------------------------------------*/ /* fp_unpack assumes the output file does not exist */ int fp_unpack (char *infits, char *outfits, fpstate fpvar) { fitsfile *infptr, *outfptr; int stat=0, hdutype, extnum, single = 0; char *loc, *hduloc, hduname[SZ_STR]; fits_open_file (&infptr, infits, READONLY, &stat); fits_create_file (&outfptr, outfits, &stat); if (stat) { fp_abort_output(infptr, outfptr, stat); } if (fpvar.extname[0]) { /* unpack a list of HDUs? */ /* move to the first HDU in the list */ hduloc = fpvar.extname; loc = strchr(hduloc, ','); /* look for 'comma' delimiter between names */ if (loc) *loc = '\0'; /* terminate the first name in the string */ strcpy(hduname, hduloc); /* copy the first name into temporary string */ if (loc) hduloc = loc + 1; /* advance to the beginning of the next name, if any */ else { hduloc += strlen(hduname); /* end of the list */ single = 1; /* only 1 HDU is being unpacked */ } if (isdigit( (int) hduname[0]) ) { extnum = strtol(hduname, &loc, 10); /* read the string as an integer */ /* check for junk following the integer */ if (*loc == '\0' ) /* no junk, so move to this HDU number (+1) */ { fits_movabs_hdu(infptr, extnum + 1, &hdutype, &stat); /* move to HDU number */ if (hdutype != IMAGE_HDU) stat = NOT_IMAGE; } else { /* the string is not an integer, so must be the column name */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } } else { /* move to the named image extension */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } } if (stat) { fp_msg ("Unable to find and move to extension '"); fp_msg(hduname); fp_msg("'\n"); fp_abort_output(infptr, outfptr, stat); } while (! stat) { if (single) stat = -1; /* special status flag to force output primary array */ fp_unpack_hdu (infptr, outfptr, fpvar, &stat); if (fpvar.do_checksums) { fits_write_chksum (outfptr, &stat); } /* move to the next HDU */ if (fpvar.extname[0]) { /* unpack a list of HDUs? */ if (!(*hduloc)) { stat = END_OF_FILE; /* we reached the end of the list */ } else { /* parse the next HDU name and move to it */ loc = strchr(hduloc, ','); if (loc) /* look for 'comma' delimiter between names */ *loc = '\0'; /* terminate the first name in the string */ strcpy(hduname, hduloc); /* copy the next name into temporary string */ if (loc) hduloc = loc + 1; /* advance to the beginning of the next name, if any */ else *hduloc = '\0'; /* end of the list */ if (isdigit( (int) hduname[0]) ) { extnum = strtol(hduname, &loc, 10); /* read the string as an integer */ /* check for junk following the integer */ if (*loc == '\0' ) /* no junk, so move to this HDU number (+1) */ { fits_movabs_hdu(infptr, extnum + 1, &hdutype, &stat); /* move to HDU number */ if (hdutype != IMAGE_HDU) stat = NOT_IMAGE; } else { /* the string is not an integer, so must be the column name */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } } else { /* move to the named image extension */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } if (stat) { fp_msg ("Unable to find and move to extension '"); fp_msg(hduname); fp_msg("'\n"); } } } else { /* increment to the next HDU */ fits_movrel_hdu (infptr, 1, NULL, &stat); } } if (stat == END_OF_FILE) stat = 0; /* set checksum for case of newly created primary HDU */ if (fpvar.do_checksums) { fits_movabs_hdu (outfptr, 1, NULL, &stat); fits_write_chksum (outfptr, &stat); } if (stat) { fp_abort_output(infptr, outfptr, stat); } fits_close_file (outfptr, &stat); fits_close_file (infptr, &stat); return(0); } /*--------------------------------------------------------------------------*/ /* fp_test assumes the output files do not exist */ int fp_test (char *infits, char *outfits, char *outfits2, fpstate fpvar) { fitsfile *inputfptr, *infptr, *outfptr, *outfptr2, *tempfile; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; int stat=0, totpix=0, naxis=0, ii, hdutype, bitpix = 0, extnum = 0, len; int tstatus = 0, hdunum, rescale_flag, bpix, ncols; char dtype[8], dimen[100]; double bscale, rescale, noisemin; long headstart, datastart, dataend; float origdata = 0., whole_cpu, whole_elapse, row_elapse, row_cpu, xbits; LONGLONG nrows; /* structure to hold image statistics (defined in fpack.h) */ imgstats imagestats; fits_open_file (&inputfptr, infits, READONLY, &stat); fits_create_file (&outfptr, outfits, &stat); fits_create_file (&outfptr2, outfits2, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } while (! stat) { /* LOOP OVER EACH HDU */ rescale_flag = 0; fits_get_hdu_type (inputfptr, &hdutype, &stat); if (hdutype == IMAGE_HDU) { fits_get_img_param (inputfptr, 9, &bitpix, &naxis, naxes, &stat); for (totpix=1, ii=0; ii < 9; ii++) totpix *= naxes[ii]; } if (!fits_is_compressed_image (inputfptr, &stat) && hdutype == IMAGE_HDU && naxis != 0 && totpix != 0 && fpvar.do_images) { /* rescale a scaled integer image to reduce noise? */ if (fpvar.rescale_noise != 0. && bitpix > 0 && bitpix < LONGLONG_IMG) { tstatus = 0; fits_read_key(inputfptr, TDOUBLE, "BSCALE", &bscale, 0, &tstatus); if (tstatus == 0 && bscale != 1.0) { /* image must be scaled */ if (bitpix == LONG_IMG) fp_i4stat(inputfptr, naxis, naxes, &imagestats, &stat); else fp_i2stat(inputfptr, naxis, naxes, &imagestats, &stat); /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; rescale = noisemin / fpvar.rescale_noise; if (rescale > 1.0) { /* all the criteria are met, so create a temporary file that */ /* contains a rescaled version of the image, in CWD */ /* create temporary file name */ fp_tmpnam("Tmpfile3", "", tempfilename3); fits_create_file(&tempfile, tempfilename3, &stat); fits_get_hdu_num(inputfptr, &hdunum); if (hdunum != 1) { /* the input hdu is an image extension, so create dummy primary */ fits_create_img(tempfile, 8, 0, naxes, &stat); } fits_copy_header(inputfptr, tempfile, &stat); /* copy the header */ /* rescale the data, so that it will compress more efficiently */ if (bitpix == LONG_IMG) fp_i4rescale(inputfptr, naxis, naxes, rescale, tempfile, &stat); else fp_i2rescale(inputfptr, naxis, naxes, rescale, tempfile, &stat); /* scale the BSCALE keyword by the inverse factor */ bscale = bscale * rescale; fits_update_key(tempfile, TDOUBLE, "BSCALE", &bscale, 0, &stat); /* rescan the header, to reset the actual scaling parameters */ fits_set_hdustruc(tempfile, &stat); infptr = tempfile; rescale_flag = 1; } } } if (!rescale_flag) /* just compress the input file, without rescaling */ infptr = inputfptr; /* compute basic statistics about the input image */ if (bitpix == BYTE_IMG) { bpix = 8; strcpy(dtype, "8 "); fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == SHORT_IMG) { bpix = 16; strcpy(dtype, "16 "); fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == LONG_IMG) { bpix = 32; strcpy(dtype, "32 "); fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == LONGLONG_IMG) { bpix = 64; strcpy(dtype, "64 "); } else if (bitpix == FLOAT_IMG) { bpix = 32; strcpy(dtype, "-32"); fp_r4stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == DOUBLE_IMG) { bpix = 64; strcpy(dtype, "-64"); fp_r4stat(infptr, naxis, naxes, &imagestats, &stat); } /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; xbits = (float) (log10(noisemin)/.301 + 1.792); printf("\n File: %s\n", infits); printf(" Ext BITPIX Dimens. Nulls Min Max Mean Sigma Noise2 Noise3 Noise5 Nbits MaxR\n"); printf(" %3d %s", extnum, dtype); snprintf(dimen,100," (%ld", naxes[0]); len =strlen(dimen); for (ii = 1; ii < naxis; ii++) { if (len < 99) snprintf(dimen+len,100-len,",%ld", naxes[ii]); len =strlen(dimen); } if (strlen(dimen)<99) strcat(dimen, ")"); printf("%-12s",dimen); fits_get_hduaddr(inputfptr, &headstart, &datastart, &dataend, &stat); origdata = (float) ((dataend - datastart)/1000000.); /* get elapsed and cpu times need to read the uncompressed image */ fits_read_image_speed (infptr, &whole_elapse, &whole_cpu, &row_elapse, &row_cpu, &stat); printf(" %5d %6.0f %6.0f %8.1f %#8.2g %#7.3g %#7.3g %#7.3g %#5.1f %#6.2f\n", imagestats.n_nulls, imagestats.minval, imagestats.maxval, imagestats.mean, imagestats.sigma, imagestats.noise2, imagestats.noise3, imagestats.noise5, xbits, bpix/xbits); printf("\n Type Ratio Size (MB) Pk (Sec) UnPk Exact ElpN CPUN Elp1 CPU1\n"); printf(" Native %5.3f %5.3f %5.3f %5.3f\n", whole_elapse, whole_cpu, row_elapse, row_cpu); if (fpvar.outfile[0]) { fprintf(outreport, " %s %d %d %ld %ld %#10.4g %d %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g", infits, extnum, bitpix, naxes[0], naxes[1], origdata, imagestats.n_nulls, imagestats.minval, imagestats.maxval, imagestats.mean, imagestats.sigma, imagestats.noise1, imagestats.noise2, imagestats.noise3, imagestats.noise5, whole_elapse, whole_cpu, row_elapse, row_cpu); } fits_set_lossy_int (outfptr, fpvar.int_to_float, &stat); if ( (bitpix > 0) && (fpvar.int_to_float != 0) ) { if ( (noisemin < (fpvar.n3ratio * fpvar.quantize_level) ) || (noisemin < fpvar.n3min)) { /* image contains too little noise to quantize effectively */ fits_set_lossy_int (outfptr, 0, &stat); fits_get_hdu_num(infptr, &hdunum); printf(" HDU %d does not meet noise criteria to be quantized, so losslessly compressed.\n", hdunum); } } /* test compression ratio and speed for each algorithm */ if (fpvar.quantize_level != 0) { fits_set_compression_type (outfptr, RICE_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); } if (fpvar.quantize_level != 0) { \ fits_set_compression_type (outfptr, HCOMPRESS_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); } if (fpvar.comptype == GZIP_2) { fits_set_compression_type (outfptr, GZIP_2, &stat); } else { fits_set_compression_type (outfptr, GZIP_1, &stat); } fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); /* fits_set_compression_type (outfptr, BZIP2_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); */ /* fits_set_compression_type (outfptr, PLIO_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); */ /* if (bitpix == SHORT_IMG || bitpix == LONG_IMG) { fits_set_compression_type (outfptr, NOCOMPRESS, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); } */ if (fpvar.outfile[0]) fprintf(outreport,"\n"); /* delete the temporary file */ if (rescale_flag) { fits_delete_file (infptr, &stat); tempfilename3[0] = '\0'; /* clear the temp filename */ } } else if ( (hdutype == BINARY_TBL) && fpvar.do_tables) { fits_get_num_rowsll(inputfptr, &nrows, &stat); fits_get_num_cols(inputfptr, &ncols, &stat); #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ printf("\n File: %s, HDU %d, %d cols X %I64d rows\n", infits, extnum, ncols, nrows); #elif (USE_LL_SUFFIX == 1) printf("\n File: %s, HDU %d, %d cols X %lld rows\n", infits, extnum, ncols, nrows); #else printf("\n File: %s, HDU %d, %d cols X %ld rows\n", infits, extnum, ncols, nrows); #endif fp_test_table(inputfptr, outfptr, outfptr2, fpvar, &stat); } else { fits_copy_hdu (inputfptr, outfptr, 0, &stat); fits_copy_hdu (inputfptr, outfptr2, 0, &stat); } fits_movrel_hdu (inputfptr, 1, NULL, &stat); extnum++; } if (stat == END_OF_FILE) stat = 0; fits_close_file (outfptr2, &stat); fits_close_file (outfptr, &stat); fits_close_file (inputfptr, &stat); if (stat) { fits_report_error (stderr, stat); } return(0); } /*--------------------------------------------------------------------------*/ int fp_pack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *islossless, int *status) { fitsfile *tempfile; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; int stat=0, totpix=0, naxis=0, ii, hdutype, bitpix; int tstatus, hdunum; double bscale, rescale; char outfits[SZ_STR], fzalgor[FLEN_VALUE]; long headstart, datastart, dataend, datasize; double noisemin; /* structure to hold image statistics (defined in fpack.h) */ imgstats imagestats; if (*status) return(0); fits_get_hdu_type (infptr, &hdutype, &stat); if (hdutype == IMAGE_HDU) { fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, &stat); for (totpix=1, ii=0; ii < 9; ii++) totpix *= naxes[ii]; } /* check directive keyword to see if this HDU should not be compressed */ tstatus = 0; if (!fits_read_key(infptr, TSTRING, "FZALGOR", fzalgor, NULL, &tstatus) ) { if (!strcmp(fzalgor, "NONE") || !strcmp(fzalgor, "none") ) { fits_copy_hdu (infptr, outfptr, 0, &stat); *status = stat; return(0); } } /* =============================================================== */ /* This block is only for binary table compression */ if (hdutype == BINARY_TBL && fpvar.do_tables) { fits_get_hduaddr(infptr, &headstart, &datastart, &dataend, status); datasize = dataend - datastart; if (datasize <= 2880) { /* data is less than 1 FITS block in size, so don't compress */ fits_copy_hdu (infptr, outfptr, 0, &stat); } else { fits_compress_table (infptr, outfptr, &stat); } *status = stat; return(0); } /* =============================================================== */ /* If this is not a non-null image HDU, just copy it verbatim */ if (fits_is_compressed_image (infptr, &stat) || hdutype != IMAGE_HDU || naxis == 0 || totpix == 0 || !fpvar.do_images) { fits_copy_hdu (infptr, outfptr, 0, &stat); } else { /* remaining code deals only with IMAGE HDUs */ /* special case: rescale a scaled integer image to reduce noise? */ if (fpvar.rescale_noise != 0. && bitpix > 0 && bitpix < LONGLONG_IMG) { tstatus = 0; fits_read_key(infptr, TDOUBLE, "BSCALE", &bscale, 0, &tstatus); if (tstatus == 0 && bscale != 1.0) { /* image must be scaled */ if (bitpix == LONG_IMG) fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); else fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; rescale = noisemin / fpvar.rescale_noise; if (rescale > 1.0) { /* all the criteria are met, so create a temporary file that */ /* contains a rescaled version of the image, in output directory */ /* create temporary file name */ fits_file_name(outfptr, outfits, &stat); /* get the output file name */ fp_tmpnam("Tmp3", outfits, tempfilename3); fits_create_file(&tempfile, tempfilename3, &stat); fits_get_hdu_num(infptr, &hdunum); if (hdunum != 1) { /* the input hdu is an image extension, so create dummy primary */ fits_create_img(tempfile, 8, 0, naxes, &stat); } fits_copy_header(infptr, tempfile, &stat); /* copy the header */ /* rescale the data, so that it will compress more efficiently */ if (bitpix == LONG_IMG) fp_i4rescale(infptr, naxis, naxes, rescale, tempfile, &stat); else fp_i2rescale(infptr, naxis, naxes, rescale, tempfile, &stat); /* scale the BSCALE keyword by the inverse factor */ bscale = bscale * rescale; fits_update_key(tempfile, TDOUBLE, "BSCALE", &bscale, 0, &stat); /* rescan the header, to reset the actual scaling parameters */ fits_set_hdustruc(tempfile, &stat); fits_img_compress (tempfile, outfptr, &stat); fits_delete_file (tempfile, &stat); tempfilename3[0] = '\0'; /* clear the temp filename */ *islossless = 0; /* used a lossy compression method */ *status = stat; return(0); } } } /* if requested to do lossy compression of integer images (by */ /* converting to float), then check if this HDU qualifies */ if ( (bitpix > 0) && (fpvar.int_to_float != 0) ) { if (bitpix >= LONG_IMG) fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); else fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); /* rescan the image header to reset scaling values (changed by fp_iNstat) */ ffrhdu(infptr, &hdutype, &stat); /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; if ( (noisemin < (fpvar.n3ratio * fpvar.quantize_level) ) || (imagestats.noise3 < fpvar.n3min)) { /* image contains too little noise to quantize effectively */ fits_set_lossy_int (outfptr, 0, &stat); fits_get_hdu_num(infptr, &hdunum); printf(" HDU %d does not meet noise criteria to be quantized, so losslessly compressed.\n", hdunum); } else { /* compressed image is not identical to original */ *islossless = 0; } } /* finally, do the actual image compression */ fits_img_compress (infptr, outfptr, &stat); if (bitpix < 0 || (fpvar.comptype == HCOMPRESS_1 && fpvar.scale != 0.)) { /* compressed image is not identical to original */ *islossless = 0; } } *status = stat; return(0); } /*--------------------------------------------------------------------------*/ int fp_unpack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *status) { int hdutype, lval; if (*status > 0) return(0); fits_get_hdu_type (infptr, &hdutype, status); /* =============================================================== */ /* This block is only for beta testing of binary table compression */ if (hdutype == BINARY_TBL) { fits_read_key(infptr, TLOGICAL, "ZTABLE", &lval, NULL, status); if (*status == 0 && lval != 0) { /* uncompress the table */ fits_uncompress_table (infptr, outfptr, status); } else { if (*status == KEY_NO_EXIST) /* table is not compressed */ *status = 0; fits_copy_hdu (infptr, outfptr, 0, status); } return(0); /* =============================================================== */ } else if (fits_is_compressed_image (infptr, status)) { /* uncompress the compressed image HDU */ fits_img_decompress (infptr, outfptr, status); } else { /* not a compressed image HDU, so just copy it to the output */ fits_copy_hdu (infptr, outfptr, 0, status); } return(0); } /*--------------------------------------------------------------------------*/ int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, float *whole_cpu, float *row_elapse, float *row_cpu, int *status) { unsigned char *carray, cnull = 0; short *sarray, snull=0; int bitpix, naxis, anynull, *iarray, inull = 0; long ii, naxes[9], fpixel[9]={1,1,1,1,1,1,1,1,1}, lpixel[9]={1,1,1,1,1,1,1,1,1}; long inc[9]={1,1,1,1,1,1,1,1,1} ; float *earray, enull = 0, filesize; double *darray, dnull = 0; if (*status) return(*status); fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, status); if (naxis != 2)return(*status); lpixel[0] = naxes[0]; lpixel[1] = naxes[1]; /* filesize in MB */ filesize = (float) (naxes[0] * abs(bitpix) / 8000000. * naxes[1]); /* measure time required to read the raw image */ fits_set_bscale(infptr, 1.0, 0.0, status); *whole_elapse = 0.; *whole_cpu = 0; if (bitpix == BYTE_IMG) { carray = calloc(naxes[1]*naxes[0], sizeof(char)); /* remove any cached uncompressed tile (dangerous to directly modify the structure!) */ /* (infptr->Fptr)->tilerow = 0; */ marktime(status); fits_read_subset(infptr, TBYTE, fpixel, lpixel, inc, &cnull, carray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { /* remove any cached uncompressed tile (dangerous to directly modify the structure!) */ /* (infptr->Fptr)->tilerow = 0; */ marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TBYTE, fpixel, naxes[0], &cnull, carray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(carray); } else if (bitpix == SHORT_IMG) { sarray = calloc(naxes[0]*naxes[1], sizeof(short)); marktime(status); fits_read_subset(infptr, TSHORT, fpixel, lpixel, inc, &snull, sarray, &anynull, status); gettime(whole_elapse, whole_cpu, status); /* get elapsped times */ /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TSHORT, fpixel, naxes[0], &snull, sarray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(sarray); } else if (bitpix == LONG_IMG) { iarray = calloc(naxes[0]*naxes[1], sizeof(int)); marktime(status); fits_read_subset(infptr, TINT, fpixel, lpixel, inc, &inull, iarray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TINT, fpixel, naxes[0], &inull, iarray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(iarray); } else if (bitpix == FLOAT_IMG) { earray = calloc(naxes[1]*naxes[0], sizeof(float)); marktime(status); fits_read_subset(infptr, TFLOAT, fpixel, lpixel, inc, &enull, earray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TFLOAT, fpixel, naxes[0], &enull, earray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(earray); } else if (bitpix == DOUBLE_IMG) { darray = calloc(naxes[1]*naxes[0], sizeof(double)); marktime(status); fits_read_subset(infptr, TDOUBLE, fpixel, lpixel, inc, &dnull, darray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TDOUBLE, fpixel, naxes[0], &dnull, darray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(darray); } if (whole_elapse) *whole_elapse = *whole_elapse / filesize; if (row_elapse) *row_elapse = *row_elapse / filesize; if (whole_cpu) *whole_cpu = *whole_cpu / filesize; if (row_cpu) *row_cpu = *row_cpu / filesize; return(*status); } /*--------------------------------------------------------------------------*/ int fp_test_hdu (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, fpstate fpvar, int *status) { /* This routine is only used for performance testing of image HDUs. */ /* Use fp_test_table for testing binary table HDUs. */ int stat = 0, hdutype, comptype; char ctype[20], lossless[4]; long headstart, datastart, dataend; float origdata = 0., compressdata = 0.; float compratio = 0., packcpu = 0., unpackcpu = 0.; float elapse, whole_elapse, row_elapse, whole_cpu, row_cpu; unsigned long datasum1, datasum2, hdusum; if (*status) return(0); origdata = 0; compressdata = 0; compratio = 0.; lossless[0] = '\0'; fits_get_compression_type(outfptr, &comptype, &stat); if (comptype == RICE_1) strcpy(ctype, "RICE"); else if (comptype == GZIP_1) strcpy(ctype, "GZIP1"); else if (comptype == GZIP_2) strcpy(ctype, "GZIP2");/* else if (comptype == BZIP2_1) strcpy(ctype, "BZIP2"); */ else if (comptype == PLIO_1) strcpy(ctype, "PLIO"); else if (comptype == HCOMPRESS_1) strcpy(ctype, "HCOMP"); else if (comptype == NOCOMPRESS) strcpy(ctype, "NONE"); else { fp_msg ("Error: unsupported image compression type "); *status = DATA_COMPRESSION_ERR; return(0); } /* -------------- COMPRESS the image ------------------ */ marktime(&stat); fits_img_compress (infptr, outfptr, &stat); /* get elapsped times */ gettime(&elapse, &packcpu, &stat); /* get elapsed and cpu times need to read the compressed image */ fits_read_image_speed (outfptr, &whole_elapse, &whole_cpu, &row_elapse, &row_cpu, &stat); if (!stat) { /* -------------- UNCOMPRESS the image ------------------ */ /* remove any cached uncompressed tile (dangerous to directly modify the structure!) */ /* (outfptr->Fptr)->tilerow = 0; */ marktime(&stat); fits_img_decompress (outfptr, outfptr2, &stat); /* get elapsped times */ gettime(&elapse, &unpackcpu, &stat); /* ----------------------------------------------------- */ /* get sizes of original and compressed images */ fits_get_hduaddr(infptr, &headstart, &datastart, &dataend, &stat); origdata = (float) ((dataend - datastart)/1000000.); fits_get_hduaddr(outfptr, &headstart, &datastart, &dataend, &stat); compressdata = (float) ((dataend - datastart)/1000000.); if (compressdata != 0) compratio = (float) origdata / (float) compressdata; /* is this uncompressed image identical to the original? */ fits_get_chksum(infptr, &datasum1, &hdusum, &stat); fits_get_chksum(outfptr2, &datasum2, &hdusum, &stat); if ( datasum1 == datasum2) { strcpy(lossless, "Yes"); } else { strcpy(lossless, "No"); } printf(" %-5s %6.2f %7.2f ->%7.2f %7.2f %7.2f %s %5.3f %5.3f %5.3f %5.3f\n", ctype, compratio, origdata, compressdata, packcpu, unpackcpu, lossless, whole_elapse, whole_cpu, row_elapse, row_cpu); if (fpvar.outfile[0]) { fprintf(outreport," %6.3f %5.2f %5.2f %s %7.3f %7.3f %7.3f %7.3f", compratio, packcpu, unpackcpu, lossless, whole_elapse, whole_cpu, row_elapse, row_cpu); } /* delete the output HDUs to concerve disk space */ fits_delete_hdu(outfptr, &hdutype, &stat); fits_delete_hdu(outfptr2, &hdutype, &stat); } else { printf(" %-5s (unable to compress image)\n", ctype); } /* try to recover from any compression errors */ if (stat == DATA_COMPRESSION_ERR) stat = 0; *status = stat; return(0); } /*--------------------------------------------------------------------------*/ int fp_test_table (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, fpstate fpvar, int *status) { /* this routine is for performance testing of the table compression methods */ int stat = 0, hdutype, tstatus = 0; char fzalgor[FLEN_VALUE]; LONGLONG headstart, datastart, dataend; float elapse, cpu; if (*status) return(0); /* check directive keyword to see if this HDU should not be compressed */ if (!fits_read_key(infptr, TSTRING, "FZALGOR", fzalgor, NULL, &tstatus) ) { if (!strcmp(fzalgor, "NONE") || !strcmp(fzalgor, "none")) { return(0); } } fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status); /* can't compress small tables with less than 2880 bytes of data */ if (dataend - datastart <= 2880) { return(0); } marktime(&stat); stat= -999; /* set special flag value */ fits_compress_table (infptr, outfptr, &stat); /* get elapsped times */ gettime(&elapse, &cpu, &stat); fits_delete_hdu(outfptr, &hdutype, &stat); printf("\nElapsed time = %f, cpu = %f\n", elapse, cpu); fits_report_error (stderr, stat); return(0); } /*--------------------------------------------------------------------------*/ int marktime(int *status) { #if defined(unix) || defined(__unix__) || defined(__unix) struct timeval tv; /* struct timezone tz; */ /* gettimeofday (&tv, &tz); */ gettimeofday (&tv, NULL); startsec = tv.tv_sec; startmilli = tv.tv_usec/1000; scpu = clock(); #else /* don't support high timing precision on Windows machines */ startsec = 0; startmilli = 0; scpu = clock(); #endif return( *status ); } /*--------------------------------------------------------------------------*/ int gettime(float *elapse, float *elapscpu, int *status) { #if defined(unix) || defined(__unix__) || defined(__unix) struct timeval tv; /* struct timezone tz; */ int stopmilli; long stopsec; /* gettimeofday (&tv, &tz); */ gettimeofday (&tv, NULL); ecpu = clock(); stopmilli = tv.tv_usec/1000; stopsec = tv.tv_sec; *elapse = (stopsec - startsec) + (stopmilli - startmilli)/1000.; *elapscpu = (ecpu - scpu) * 1.0 / CLOCKTICKS; /* printf(" (start: %ld + %d), stop: (%ld + %d) elapse: %f\n ", startsec,startmilli,stopsec, stopmilli, *elapse); */ #else /* set the elapsed time the same as the CPU time on Windows machines */ *elapscpu = (float) ((ecpu - scpu) * 1.0 / CLOCKTICKS); *elapse = *elapscpu; #endif return( *status ); } /*--------------------------------------------------------------------------*/ int fp_i2stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) { /* read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, and then compute basic statistics: min, max, mean, sigma, mean diff, etc. */ long fpixel[9] = {1,1,1,1,1,1,1,1,1}; long lpixel[9] = {1,1,1,1,1,1,1,1,1}; long inc[9] = {1,1,1,1,1,1,1,1,1}; long i1, i2, npix, ngood, nx, ny; short *intarray, minvalue, maxvalue, nullvalue; int anynul, tstatus, checknull = 1; double mean, sigma, noise1, noise2, noise3, noise5; /* select the middle XSAMPLE by YSAMPLE area of the image */ i1 = naxes[0]/2 - (XSAMPLE/2 - 1); i2 = naxes[0]/2 + (XSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[0]) i2 = naxes[0]; fpixel[0] = i1; lpixel[0] = i2; nx = i2 - i1 +1; if (naxis > 1) { i1 = naxes[1]/2 - (YSAMPLE/2 - 1); i2 = naxes[1]/2 + (YSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[1]) i2 = naxes[1]; fpixel[1] = i1; lpixel[1] = i2; } ny = i2 - i1 +1; npix = nx * ny; /* if there are higher dimensions, read the middle plane of the cube */ if (naxis > 2) { fpixel[2] = naxes[2]/2 + 1; lpixel[2] = naxes[2]/2 + 1; } intarray = calloc(npix, sizeof(short)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_read_subset_sht(infptr, 0, naxis, naxes, fpixel, lpixel, inc, 0, intarray, &anynul, status); /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TSHORT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { nullvalue = 0; checknull = 0; } /* compute statistics of the image */ fits_img_stats_short(intarray, nx, ny, checknull, nullvalue, &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); imagestats->n_nulls = npix - ngood; imagestats->minval = minvalue; imagestats->maxval = maxvalue; imagestats->mean = mean; imagestats->sigma = sigma; imagestats->noise1 = noise1; imagestats->noise2 = noise2; imagestats->noise3 = noise3; imagestats->noise5 = noise5; free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ int fp_i4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) { /* read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, and then compute basic statistics: min, max, mean, sigma, mean diff, etc. */ long fpixel[9] = {1,1,1,1,1,1,1,1,1}; long lpixel[9] = {1,1,1,1,1,1,1,1,1}; long inc[9] = {1,1,1,1,1,1,1,1,1}; long i1, i2, npix, ngood, nx, ny; int *intarray, minvalue, maxvalue, nullvalue; int anynul, tstatus, checknull = 1; double mean, sigma, noise1, noise2, noise3, noise5; /* select the middle XSAMPLE by YSAMPLE area of the image */ i1 = naxes[0]/2 - (XSAMPLE/2 - 1); i2 = naxes[0]/2 + (XSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[0]) i2 = naxes[0]; fpixel[0] = i1; lpixel[0] = i2; nx = i2 - i1 +1; if (naxis > 1) { i1 = naxes[1]/2 - (YSAMPLE/2 - 1); i2 = naxes[1]/2 + (YSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[1]) i2 = naxes[1]; fpixel[1] = i1; lpixel[1] = i2; } ny = i2 - i1 +1; npix = nx * ny; /* if there are higher dimensions, read the middle plane of the cube */ if (naxis > 2) { fpixel[2] = naxes[2]/2 + 1; lpixel[2] = naxes[2]/2 + 1; } intarray = calloc(npix, sizeof(int)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_read_subset_int(infptr, 0, naxis, naxes, fpixel, lpixel, inc, 0, intarray, &anynul, status); /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TINT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { nullvalue = 0; checknull = 0; } /* compute statistics of the image */ fits_img_stats_int(intarray, nx, ny, checknull, nullvalue, &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); imagestats->n_nulls = npix - ngood; imagestats->minval = minvalue; imagestats->maxval = maxvalue; imagestats->mean = mean; imagestats->sigma = sigma; imagestats->noise1 = noise1; imagestats->noise2 = noise2; imagestats->noise3 = noise3; imagestats->noise5 = noise5; free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ int fp_r4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) { /* read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, and then compute basic statistics: min, max, mean, sigma, mean diff, etc. */ long fpixel[9] = {1,1,1,1,1,1,1,1,1}; long lpixel[9] = {1,1,1,1,1,1,1,1,1}; long inc[9] = {1,1,1,1,1,1,1,1,1}; long i1, i2, npix, ngood, nx, ny; float *array, minvalue, maxvalue, nullvalue = FLOATNULLVALUE; int anynul,checknull = 1; double mean, sigma, noise1, noise2, noise3, noise5; /* select the middle XSAMPLE by YSAMPLE area of the image */ i1 = naxes[0]/2 - (XSAMPLE/2 - 1); i2 = naxes[0]/2 + (XSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[0]) i2 = naxes[0]; fpixel[0] = i1; lpixel[0] = i2; nx = i2 - i1 +1; if (naxis > 1) { i1 = naxes[1]/2 - (YSAMPLE/2 - 1); i2 = naxes[1]/2 + (YSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[1]) i2 = naxes[1]; fpixel[1] = i1; lpixel[1] = i2; } ny = i2 - i1 +1; npix = nx * ny; /* if there are higher dimensions, read the middle plane of the cube */ if (naxis > 2) { fpixel[2] = naxes[2]/2 + 1; lpixel[2] = naxes[2]/2 + 1; } array = calloc(npix, sizeof(float)); if (!array) { *status = MEMORY_ALLOCATION; return(*status); } fits_read_subset_flt(infptr, 0, naxis, naxes, fpixel, lpixel, inc, nullvalue, array, &anynul, status); /* are there any null values in the array? */ if (!anynul) { nullvalue = 0.; checknull = 0; } /* compute statistics of the image */ fits_img_stats_float(array, nx, ny, checknull, nullvalue, &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); imagestats->n_nulls = npix - ngood; imagestats->minval = minvalue; imagestats->maxval = maxvalue; imagestats->mean = mean; imagestats->sigma = sigma; imagestats->noise1 = noise1; imagestats->noise2 = noise2; imagestats->noise3 = noise3; imagestats->noise5 = noise5; free(array); return(*status); } /*--------------------------------------------------------------------------*/ int fp_i2rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, fitsfile *outfptr, int *status) { /* divide the integer pixel values in the input file by rescale, and write back out to the output file.. */ long ii, jj, nelem = 1, nx, ny; short *intarray, nullvalue; int anynul, tstatus, checknull = 1; nx = naxes[0]; ny = 1; for (ii = 1; ii < naxis; ii++) { ny = ny * naxes[ii]; } intarray = calloc(nx, sizeof(short)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TSHORT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { checknull = 0; } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_set_bscale(outfptr, 1.0, 0.0, status); for (ii = 0; ii < ny; ii++) { fits_read_img_sht(infptr, 1, nelem, nx, 0, intarray, &anynul, status); if (checknull) { for (jj = 0; jj < nx; jj++) { if (intarray[jj] != nullvalue) intarray[jj] = NSHRT( (intarray[jj] / rescale) ); } } else { for (jj = 0; jj < nx; jj++) intarray[jj] = NSHRT( (intarray[jj] / rescale) ); } fits_write_img_sht(outfptr, 1, nelem, nx, intarray, status); nelem += nx; } free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ int fp_i4rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, fitsfile *outfptr, int *status) { /* divide the integer pixel values in the input file by rescale, and write back out to the output file.. */ long ii, jj, nelem = 1, nx, ny; int *intarray, nullvalue; int anynul, tstatus, checknull = 1; nx = naxes[0]; ny = 1; for (ii = 1; ii < naxis; ii++) { ny = ny * naxes[ii]; } intarray = calloc(nx, sizeof(int)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TINT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { checknull = 0; } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_set_bscale(outfptr, 1.0, 0.0, status); for (ii = 0; ii < ny; ii++) { fits_read_img_int(infptr, 1, nelem, nx, 0, intarray, &anynul, status); if (checknull) { for (jj = 0; jj < nx; jj++) { if (intarray[jj] != nullvalue) intarray[jj] = NINT( (intarray[jj] / rescale) ); } } else { for (jj = 0; jj < nx; jj++) intarray[jj] = NINT( (intarray[jj] / rescale) ); } fits_write_img_int(outfptr, 1, nelem, nx, intarray, status); nelem += nx; } free(intarray); return(*status); } /* ======================================================================== * Signal and error handler. */ void abort_fpack(int sig) { /* clean up by deleting temporary files */ if (tempfilename[0]) { remove(tempfilename); } if (tempfilename2[0]) { remove(tempfilename2); } if (tempfilename3[0]) { remove(tempfilename3); } exit(-1); } cfitsio-4.3.1/eval_l.c0000644000225700000360000024664414335036354014101 0ustar cagordonlhea#line 1 "eval_l.c" #line 3 "eval_l.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 4 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif #ifdef yy_create_buffer #define fits_parser_yy_create_buffer_ALREADY_DEFINED #else #define yy_create_buffer fits_parser_yy_create_buffer #endif #ifdef yy_delete_buffer #define fits_parser_yy_delete_buffer_ALREADY_DEFINED #else #define yy_delete_buffer fits_parser_yy_delete_buffer #endif #ifdef yy_scan_buffer #define fits_parser_yy_scan_buffer_ALREADY_DEFINED #else #define yy_scan_buffer fits_parser_yy_scan_buffer #endif #ifdef yy_scan_string #define fits_parser_yy_scan_string_ALREADY_DEFINED #else #define yy_scan_string fits_parser_yy_scan_string #endif #ifdef yy_scan_bytes #define fits_parser_yy_scan_bytes_ALREADY_DEFINED #else #define yy_scan_bytes fits_parser_yy_scan_bytes #endif #ifdef yy_init_buffer #define fits_parser_yy_init_buffer_ALREADY_DEFINED #else #define yy_init_buffer fits_parser_yy_init_buffer #endif #ifdef yy_flush_buffer #define fits_parser_yy_flush_buffer_ALREADY_DEFINED #else #define yy_flush_buffer fits_parser_yy_flush_buffer #endif #ifdef yy_load_buffer_state #define fits_parser_yy_load_buffer_state_ALREADY_DEFINED #else #define yy_load_buffer_state fits_parser_yy_load_buffer_state #endif #ifdef yy_switch_to_buffer #define fits_parser_yy_switch_to_buffer_ALREADY_DEFINED #else #define yy_switch_to_buffer fits_parser_yy_switch_to_buffer #endif #ifdef yypush_buffer_state #define fits_parser_yypush_buffer_state_ALREADY_DEFINED #else #define yypush_buffer_state fits_parser_yypush_buffer_state #endif #ifdef yypop_buffer_state #define fits_parser_yypop_buffer_state_ALREADY_DEFINED #else #define yypop_buffer_state fits_parser_yypop_buffer_state #endif #ifdef yyensure_buffer_stack #define fits_parser_yyensure_buffer_stack_ALREADY_DEFINED #else #define yyensure_buffer_stack fits_parser_yyensure_buffer_stack #endif #ifdef yylex #define fits_parser_yylex_ALREADY_DEFINED #else #define yylex fits_parser_yylex #endif #ifdef yyrestart #define fits_parser_yyrestart_ALREADY_DEFINED #else #define yyrestart fits_parser_yyrestart #endif #ifdef yylex_init #define fits_parser_yylex_init_ALREADY_DEFINED #else #define yylex_init fits_parser_yylex_init #endif #ifdef yylex_init_extra #define fits_parser_yylex_init_extra_ALREADY_DEFINED #else #define yylex_init_extra fits_parser_yylex_init_extra #endif #ifdef yylex_destroy #define fits_parser_yylex_destroy_ALREADY_DEFINED #else #define yylex_destroy fits_parser_yylex_destroy #endif #ifdef yyget_debug #define fits_parser_yyget_debug_ALREADY_DEFINED #else #define yyget_debug fits_parser_yyget_debug #endif #ifdef yyset_debug #define fits_parser_yyset_debug_ALREADY_DEFINED #else #define yyset_debug fits_parser_yyset_debug #endif #ifdef yyget_extra #define fits_parser_yyget_extra_ALREADY_DEFINED #else #define yyget_extra fits_parser_yyget_extra #endif #ifdef yyset_extra #define fits_parser_yyset_extra_ALREADY_DEFINED #else #define yyset_extra fits_parser_yyset_extra #endif #ifdef yyget_in #define fits_parser_yyget_in_ALREADY_DEFINED #else #define yyget_in fits_parser_yyget_in #endif #ifdef yyset_in #define fits_parser_yyset_in_ALREADY_DEFINED #else #define yyset_in fits_parser_yyset_in #endif #ifdef yyget_out #define fits_parser_yyget_out_ALREADY_DEFINED #else #define yyget_out fits_parser_yyget_out #endif #ifdef yyset_out #define fits_parser_yyset_out_ALREADY_DEFINED #else #define yyset_out fits_parser_yyset_out #endif #ifdef yyget_leng #define fits_parser_yyget_leng_ALREADY_DEFINED #else #define yyget_leng fits_parser_yyget_leng #endif #ifdef yyget_text #define fits_parser_yyget_text_ALREADY_DEFINED #else #define yyget_text fits_parser_yyget_text #endif #ifdef yyget_lineno #define fits_parser_yyget_lineno_ALREADY_DEFINED #else #define yyget_lineno fits_parser_yyget_lineno #endif #ifdef yyset_lineno #define fits_parser_yyset_lineno_ALREADY_DEFINED #else #define yyset_lineno fits_parser_yyset_lineno #endif #ifdef yyget_column #define fits_parser_yyget_column_ALREADY_DEFINED #else #define yyget_column fits_parser_yyget_column #endif #ifdef yyset_column #define fits_parser_yyset_column_ALREADY_DEFINED #else #define yyset_column fits_parser_yyset_column #endif #ifdef yywrap #define fits_parser_yywrap_ALREADY_DEFINED #else #define yywrap fits_parser_yywrap #endif #ifdef yyget_lval #define fits_parser_yyget_lval_ALREADY_DEFINED #else #define yyget_lval fits_parser_yyget_lval #endif #ifdef yyset_lval #define fits_parser_yyset_lval_ALREADY_DEFINED #else #define yyset_lval fits_parser_yyset_lval #endif #ifdef yyalloc #define fits_parser_yyalloc_ALREADY_DEFINED #else #define yyalloc fits_parser_yyalloc #endif #ifdef yyrealloc #define fits_parser_yyrealloc_ALREADY_DEFINED #else #define yyrealloc fits_parser_yyrealloc #endif #ifdef yyfree #define fits_parser_yyfree_ALREADY_DEFINED #else #define yyfree fits_parser_yyfree #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #ifndef SIZE_MAX #define SIZE_MAX (~(size_t)0) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ /* begin standard C++ headers. */ /* TODO: this is always defined, so inline it */ #define yyconst const #if defined(__GNUC__) && __GNUC__ >= 3 #define yynoreturn __attribute__((__noreturn__)) #else #define yynoreturn #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an * integer in range [0..255] for use as an array index. */ #define YY_SC_TO_UI(c) ((YY_CHAR) (c)) /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin yyg->yyin_r #define yyout yyg->yyout_r #define yyextra yyg->yyextra_r #define yyleng yyg->yyleng_r #define yytext yyg->yytext_r #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin , yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = yyg->yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ int yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] void yyrestart ( FILE *input_file , yyscan_t yyscanner ); void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); void yypop_buffer_state ( yyscan_t yyscanner ); static void yyensure_buffer_stack ( yyscan_t yyscanner ); static void yy_load_buffer_state ( yyscan_t yyscanner ); static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); #define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); void *yyalloc ( yy_size_t , yyscan_t yyscanner ); void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); void yyfree ( void * , yyscan_t yyscanner ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef flex_uint8_t YY_CHAR; typedef int yy_state_type; #define yytext_ptr yytext_r static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); static int yy_get_next_buffer ( yyscan_t yyscanner ); static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; #define YY_NUM_RULES 30 #define YY_END_OF_BUFFER 31 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static const flex_int16_t yy_accept[174] = { 0, 0, 0, 31, 29, 1, 28, 18, 29, 29, 29, 29, 29, 29, 29, 10, 8, 8, 24, 29, 23, 13, 13, 13, 13, 9, 13, 13, 13, 13, 13, 17, 13, 13, 13, 13, 13, 13, 13, 29, 1, 22, 0, 12, 0, 11, 0, 13, 20, 0, 0, 0, 0, 0, 0, 0, 17, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 8, 0, 0, 0, 0, 26, 21, 25, 13, 13, 13, 2, 13, 13, 13, 4, 13, 13, 13, 13, 3, 13, 27, 13, 13, 13, 13, 13, 13, 13, 13, 13, 19, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6, 7, 14, 13, 23, 24, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0 } ; static const YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 6, 7, 1, 8, 9, 10, 11, 12, 13, 1, 13, 14, 1, 15, 16, 17, 17, 17, 17, 17, 17, 18, 18, 1, 1, 19, 20, 21, 1, 1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 32, 31, 33, 34, 31, 35, 36, 31, 37, 38, 31, 31, 39, 31, 31, 1, 1, 40, 41, 42, 1, 43, 44, 24, 45, 46, 47, 48, 29, 49, 31, 31, 50, 31, 51, 52, 31, 53, 54, 31, 55, 56, 31, 31, 57, 31, 31, 1, 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static const YY_CHAR yy_meta[59] = { 0, 1, 1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 5, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1 } ; static const flex_int16_t yy_base[182] = { 0, 0, 0, 412, 413, 409, 413, 390, 404, 401, 400, 398, 396, 34, 392, 70, 114, 16, 383, 46, 382, 29, 84, 359, 28, 358, 52, 157, 64, 91, 128, 358, 0, 40, 27, 69, 92, 100, 171, 340, 395, 413, 391, 413, 388, 387, 386, 413, 413, 383, 357, 358, 356, 336, 337, 335, 413, 139, 190, 352, 349, 71, 111, 135, 347, 348, 330, 327, 59, 64, 116, 325, 323, 175, 0, 59, 120, 326, 0, 413, 413, 413, 153, 184, 0, 202, 209, 210, 219, 351, 220, 228, 229, 211, 230, 240, 413, 221, 246, 254, 263, 264, 265, 266, 239, 275, 413, 346, 342, 310, 313, 309, 289, 292, 288, 275, 317, 327, 326, 325, 324, 323, 322, 298, 320, 297, 287, 317, 315, 314, 312, 311, 310, 249, 289, 243, 294, 298, 134, 246, 0, 413, 285, 413, 413, 288, 308, 309, 261, 261, 256, 221, 215, 246, 241, 223, 218, 213, 208, 197, 413, 166, 160, 413, 128, 122, 150, 154, 105, 101, 96, 413, 84, 413, 351, 354, 359, 364, 366, 368, 373, 89 } ; static const flex_int16_t yy_def[182] = { 0, 173, 1, 173, 173, 173, 173, 173, 174, 175, 176, 173, 177, 173, 173, 173, 173, 16, 173, 173, 173, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 173, 179, 178, 178, 178, 178, 178, 178, 173, 173, 173, 174, 173, 180, 175, 176, 173, 173, 177, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 17, 173, 173, 173, 181, 173, 173, 173, 178, 178, 179, 178, 178, 178, 178, 27, 178, 178, 178, 178, 178, 178, 173, 178, 178, 178, 178, 178, 178, 178, 178, 178, 173, 180, 180, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 181, 173, 178, 173, 173, 178, 178, 178, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 0, 173, 173, 173, 173, 173, 173, 173, 173 } ; static const flex_int16_t yy_nxt[472] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 14, 4, 15, 16, 17, 17, 17, 18, 19, 20, 21, 22, 23, 23, 24, 25, 26, 27, 23, 23, 28, 29, 30, 23, 23, 25, 23, 23, 4, 31, 32, 33, 22, 23, 34, 25, 35, 23, 36, 37, 38, 23, 23, 25, 23, 23, 39, 50, 173, 51, 83, 86, 52, 79, 80, 81, 173, 84, 84, 84, 136, 173, 137, 137, 137, 137, 87, 53, 98, 54, 84, 55, 57, 58, 58, 58, 58, 88, 90, 97, 59, 140, 84, 171, 60, 118, 61, 85, 85, 91, 62, 63, 64, 128, 84, 171, 119, 65, 130, 84, 171, 66, 129, 99, 67, 92, 68, 131, 69, 70, 71, 85, 100, 93, 84, 72, 73, 74, 74, 74, 74, 84, 84, 138, 138, 120, 101, 75, 75, 85, 84, 94, 94, 94, 103, 102, 121, 138, 138, 172, 104, 57, 115, 115, 115, 115, 76, 75, 75, 122, 132, 141, 95, 171, 77, 94, 133, 123, 84, 78, 89, 89, 89, 89, 170, 169, 168, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 57, 58, 58, 58, 58, 141, 84, 89, 167, 166, 84, 89, 89, 89, 89, 89, 58, 58, 58, 58, 142, 94, 96, 141, 84, 89, 75, 75, 85, 85, 141, 141, 141, 160, 80, 81, 105, 84, 48, 94, 141, 141, 141, 96, 143, 79, 75, 75, 160, 141, 141, 141, 85, 144, 41, 84, 94, 94, 94, 145, 141, 141, 84, 84, 84, 106, 48, 141, 163, 165, 85, 80, 84, 84, 84, 141, 164, 146, 163, 81, 94, 84, 84, 84, 141, 141, 141, 141, 143, 79, 144, 41, 84, 84, 162, 161, 141, 139, 94, 84, 106, 115, 115, 115, 115, 147, 141, 84, 159, 141, 48, 75, 75, 160, 106, 158, 84, 84, 84, 84, 137, 137, 137, 137, 137, 137, 137, 137, 84, 141, 141, 75, 75, 48, 160, 41, 144, 79, 84, 143, 81, 84, 80, 157, 156, 106, 155, 41, 144, 79, 143, 81, 80, 154, 153, 152, 151, 150, 149, 148, 108, 84, 84, 42, 108, 42, 42, 42, 45, 45, 45, 46, 141, 46, 46, 46, 49, 139, 49, 49, 49, 82, 82, 84, 84, 107, 135, 107, 107, 107, 134, 127, 126, 125, 124, 117, 116, 114, 113, 112, 111, 110, 109, 43, 47, 173, 108, 43, 40, 106, 96, 84, 84, 81, 79, 56, 43, 48, 47, 44, 43, 41, 40, 173, 3, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173 } ; static const flex_int16_t yy_chk[472] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 17, 13, 21, 24, 13, 19, 19, 19, 17, 34, 24, 21, 75, 17, 75, 75, 75, 75, 26, 13, 34, 13, 33, 13, 15, 15, 15, 15, 15, 26, 28, 33, 15, 181, 26, 172, 15, 61, 15, 22, 22, 28, 15, 15, 15, 68, 28, 170, 61, 15, 69, 35, 169, 15, 68, 35, 15, 29, 15, 69, 15, 15, 15, 22, 35, 29, 22, 15, 16, 16, 16, 16, 16, 29, 36, 76, 76, 62, 36, 16, 16, 22, 37, 30, 30, 30, 37, 36, 62, 138, 138, 168, 37, 57, 57, 57, 57, 57, 16, 16, 16, 63, 70, 82, 30, 167, 16, 30, 70, 63, 30, 16, 27, 27, 27, 27, 166, 165, 164, 27, 27, 27, 27, 27, 27, 30, 38, 38, 38, 73, 73, 73, 73, 73, 83, 82, 27, 162, 161, 27, 27, 27, 27, 27, 27, 58, 58, 58, 58, 83, 38, 159, 85, 38, 27, 58, 58, 85, 85, 86, 87, 93, 158, 86, 87, 38, 83, 157, 38, 88, 90, 97, 156, 88, 90, 58, 58, 155, 91, 92, 94, 85, 91, 92, 85, 94, 94, 94, 93, 104, 95, 86, 87, 93, 95, 154, 98, 153, 152, 85, 98, 88, 90, 97, 99, 151, 97, 150, 99, 94, 91, 92, 94, 100, 101, 102, 103, 100, 101, 102, 103, 104, 95, 149, 148, 105, 139, 94, 98, 105, 115, 115, 115, 115, 104, 142, 99, 135, 145, 142, 115, 115, 145, 134, 133, 100, 101, 102, 103, 136, 136, 136, 136, 137, 137, 137, 137, 105, 146, 147, 115, 115, 146, 147, 132, 131, 130, 142, 129, 128, 145, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 114, 113, 112, 111, 110, 109, 108, 146, 147, 174, 107, 174, 174, 174, 175, 175, 175, 176, 89, 176, 176, 176, 177, 77, 177, 177, 177, 178, 178, 179, 179, 180, 72, 180, 180, 180, 71, 67, 66, 65, 64, 60, 59, 55, 54, 53, 52, 51, 50, 49, 46, 45, 44, 42, 40, 39, 31, 25, 23, 20, 18, 14, 12, 11, 10, 9, 8, 7, 5, 3, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173 } ; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "eval.l" /************************************************************************/ /* */ /* CFITSIO Lexical Parser */ /* */ /* This specifies a thread-safe reentrant version of lex functions */ /* This specifies CFITSIO-unique names for lexer functions */ /* This facilitates calling between the Bison parser and this lexer */ #line 14 "eval.l" /* This file is one of 3 files containing code which parses an */ /* arithmetic expression and evaluates it in the context of an input */ /* FITS file table extension. The CFITSIO lexical parser is divided */ /* into the following 3 parts/files: the CFITSIO "front-end", */ /* eval_f.c, contains the interface between the user/CFITSIO and the */ /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ /* input string and parses it into tokens and identifies the FITS */ /* information required to evaluate the expression (ie, keywords and */ /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ /* receives the FLEX output and determines and performs the actual */ /* operations. The files eval_l.c and eval_y.c are produced from */ /* running flex and bison on the files eval.l and eval.y, respectively. */ /* (flex and bison are available from any GNU archive: see www.gnu.org) */ /* */ /* The grammar rules, rather than evaluating the expression in situ, */ /* builds a tree, or Nodal, structure mapping out the order of */ /* operations and expression dependencies. This "compilation" process */ /* allows for much faster processing of multiple rows. This technique */ /* was developed by Uwe Lammers of the XMM Science Analysis System, */ /* although the CFITSIO implementation is entirely code original. */ /* */ /* */ /* Modification History: */ /* */ /* Kent Blackburn c1992 Original parser code developed for the */ /* FTOOLS software package, in particular, */ /* the fselect task. */ /* Kent Blackburn c1995 BIT column support added */ /* Peter D Wilson Feb 1998 Vector column support added */ /* Peter D Wilson May 1998 Ported to CFITSIO library. User */ /* interface routines written, in essence */ /* making fselect, fcalc, and maketime */ /* capabilities available to all tools */ /* via single function calls. */ /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ /* create a run-time evaluation tree, */ /* inspired by the work of Uwe Lammers, */ /* resulting in a speed increase of */ /* 10-100 times. */ /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ /* allowing a purely vector-based usage */ /* */ /************************************************************************/ #include #include #include #ifdef sparc #include #else #include #endif #include "eval_defs.h" #include "eval_tab.h" /* This is a shorthand accessor to get at the "extra" data inside the lexer, which in our case is the lParse (ParseData) structure */ #define yylParse (yyextra) /***** Internal functions *****/ int fits_parser_yyGetVariable( ParseData *lParse, char *varName, FITS_PARSER_YYSTYPE *varVal ); static int find_variable( ParseData *lParse, char *varName ); static int expr_read( ParseData *lParse, char *buf, int nbytes ); /***** Definitions *****/ #define YY_NO_UNPUT /* Don't include YYUNPUT function */ #define YY_NEVER_INTERACTIVE 1 #define MAXCHR 256 #define MAXBIT 128 #define OCT_0 "000" #define OCT_1 "001" #define OCT_2 "010" #define OCT_3 "011" #define OCT_4 "100" #define OCT_5 "101" #define OCT_6 "110" #define OCT_7 "111" #define OCT_X "xxx" #define HEX_0 "0000" #define HEX_1 "0001" #define HEX_2 "0010" #define HEX_3 "0011" #define HEX_4 "0100" #define HEX_5 "0101" #define HEX_6 "0110" #define HEX_7 "0111" #define HEX_8 "1000" #define HEX_9 "1001" #define HEX_A "1010" #define HEX_B "1011" #define HEX_C "1100" #define HEX_D "1101" #define HEX_E "1110" #define HEX_F "1111" #define HEX_X "xxxx" /* MJT - 13 June 1996 read from buffer instead of stdin (as per old ftools.skel) */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( (result = expr_read( yylParse, (char *) buf, max_size )) < 0 ) \ YY_FATAL_ERROR( "read() in flex scanner failed" ); #line 925 "eval_l.c" #line 926 "eval_l.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif /* Holds the entire state of the reentrant scanner. */ struct yyguts_t { /* User-defined. Not touched by flex. */ YY_EXTRA_TYPE yyextra_r; /* The rest are the same as the globals declared in the non-reentrant scanner. */ FILE *yyin_r, *yyout_r; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; int yy_n_chars; int yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; int yy_did_buffer_switch_on_eof; int yy_start_stack_ptr; int yy_start_stack_depth; int *yy_start_stack; yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; int yylineno_r; int yy_flex_debug_r; char *yytext_r; int yy_more_flag; int yy_more_len; YYSTYPE * yylval_r; }; /* end struct yyguts_t */ static int yy_init_globals ( yyscan_t yyscanner ); /* This must go here because YYSTYPE and YYLTYPE are included * from bison output in section 1.*/ # define yylval yyg->yylval_r int yylex_init (yyscan_t* scanner); int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy ( yyscan_t yyscanner ); int yyget_debug ( yyscan_t yyscanner ); void yyset_debug ( int debug_flag , yyscan_t yyscanner ); YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); FILE *yyget_in ( yyscan_t yyscanner ); void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); FILE *yyget_out ( yyscan_t yyscanner ); void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); int yyget_leng ( yyscan_t yyscanner ); char *yyget_text ( yyscan_t yyscanner ); int yyget_lineno ( yyscan_t yyscanner ); void yyset_lineno ( int _line_number , yyscan_t yyscanner ); int yyget_column ( yyscan_t yyscanner ); void yyset_column ( int _column_no , yyscan_t yyscanner ); YYSTYPE * yyget_lval ( yyscan_t yyscanner ); void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap ( yyscan_t yyscanner ); #else extern int yywrap ( yyscan_t yyscanner ); #endif #endif #ifndef YY_NO_UNPUT static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner); #endif #ifndef yytext_ptr static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen ( const char * , yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput ( yyscan_t yyscanner ); #else static int input ( yyscan_t yyscanner ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner); #define YY_DECL int yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; if ( !yyg->yy_init ) { yyg->yy_init = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yyg->yy_start ) yyg->yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } yy_load_buffer_state( yyscanner ); } { #line 158 "eval.l" #line 1203 "eval_l.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = yyg->yy_c_buf_p; /* Support of yytext. */ *yy_cp = yyg->yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yyg->yy_start; yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 174 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 413 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yyg->yy_hold_char; yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 160 "eval.l" ; YY_BREAK case 2: YY_RULE_SETUP #line 161 "eval.l" { int len; len = strlen(yytext); while (yytext[len] == ' ') len--; len = len - 1; strncpy(yylval->str,&yytext[1],len); yylval->str[len] = '\0'; return( BITSTR ); } YY_BREAK case 3: YY_RULE_SETUP #line 171 "eval.l" { int len; char tmpstring[256]; char bitstring[256]; len = strlen(yytext); if (len >= 256) { char errMsg[100]; yylParse->status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Bit string exceeds maximum length: '"); strncat(errMsg, &(yytext[0]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { while (yytext[len] == ' ') len--; len = len - 1; strncpy(tmpstring,&yytext[1],len); } tmpstring[len] = '\0'; bitstring[0] = '\0'; len = 0; while ( tmpstring[len] != '\0') { switch ( tmpstring[len] ) { case '0': strcat(bitstring,OCT_0); break; case '1': strcat(bitstring,OCT_1); break; case '2': strcat(bitstring,OCT_2); break; case '3': strcat(bitstring,OCT_3); break; case '4': strcat(bitstring,OCT_4); break; case '5': strcat(bitstring,OCT_5); break; case '6': strcat(bitstring,OCT_6); break; case '7': strcat(bitstring,OCT_7); break; case 'x': case 'X': strcat(bitstring,OCT_X); break; } len++; } strcpy( yylval->str, bitstring ); return( BITSTR ); } YY_BREAK case 4: YY_RULE_SETUP #line 231 "eval.l" { int len; char tmpstring[256]; char bitstring[256]; len = strlen(yytext); if (len >= 256) { char errMsg[100]; yylParse->status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Hex string exceeds maximum length: '"); strncat(errMsg, &(yytext[0]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { while (yytext[len] == ' ') len--; len = len - 1; strncpy(tmpstring,&yytext[1],len); } tmpstring[len] = '\0'; bitstring[0] = '\0'; len = 0; while ( tmpstring[len] != '\0') { switch ( tmpstring[len] ) { case '0': strcat(bitstring,HEX_0); break; case '1': strcat(bitstring,HEX_1); break; case '2': strcat(bitstring,HEX_2); break; case '3': strcat(bitstring,HEX_3); break; case '4': strcat(bitstring,HEX_4); break; case '5': strcat(bitstring,HEX_5); break; case '6': strcat(bitstring,HEX_6); break; case '7': strcat(bitstring,HEX_7); break; case '8': strcat(bitstring,HEX_8); break; case '9': strcat(bitstring,HEX_9); break; case 'a': case 'A': strcat(bitstring,HEX_A); break; case 'b': case 'B': strcat(bitstring,HEX_B); break; case 'c': case 'C': strcat(bitstring,HEX_C); break; case 'd': case 'D': strcat(bitstring,HEX_D); break; case 'e': case 'E': strcat(bitstring,HEX_E); break; case 'f': case 'F': strcat(bitstring,HEX_F); break; case 'x': case 'X': strcat(bitstring,HEX_X); break; } len++; } strcpy( yylval->str, bitstring ); return( BITSTR ); } YY_BREAK case 5: YY_RULE_SETUP #line 322 "eval.l" { long int constval = 0; char *p; for (p = &(yytext[2]); *p; p++) { constval = (constval << 1) | (*p == '1'); } yylval->lng = constval; return( LONG ); } YY_BREAK case 6: YY_RULE_SETUP #line 331 "eval.l" { long int constval = 0; char *p; for (p = &(yytext[2]); *p; p++) { constval = (constval << 3) | (*p - '0'); } yylval->lng = constval; return( LONG ); } YY_BREAK case 7: YY_RULE_SETUP #line 340 "eval.l" { long int constval = 0; char *p; for (p = &(yytext[2]); *p; p++) { int v = (isdigit(*p) ? (*p - '0') : (*p - 'a' + 10)); constval = (constval << 4) | v; } yylval->lng = constval; return( LONG ); } YY_BREAK case 8: YY_RULE_SETUP #line 352 "eval.l" { yylval->lng = atol(yytext); return( LONG ); } YY_BREAK case 9: YY_RULE_SETUP #line 356 "eval.l" { if ((yytext[0] == 't') || (yytext[0] == 'T')) yylval->log = 1; else yylval->log = 0; return( BOOLEAN ); } YY_BREAK case 10: YY_RULE_SETUP #line 363 "eval.l" { yylval->dbl = atof(yytext); return( DOUBLE ); } YY_BREAK case 11: YY_RULE_SETUP #line 367 "eval.l" { if( !fits_strcasecmp(yytext,"#PI") ) { yylval->dbl = (double)(4) * atan((double)(1)); return( DOUBLE ); } else if( !fits_strcasecmp(yytext,"#E") ) { yylval->dbl = exp((double)(1)); return( DOUBLE ); } else if( !fits_strcasecmp(yytext,"#DEG") ) { yylval->dbl = ((double)4)*atan((double)1)/((double)180); return( DOUBLE ); } else if( !fits_strcasecmp(yytext,"#ROW") ) { return( ROWREF ); } else if( !fits_strcasecmp(yytext,"#NULL") ) { return( NULLREF ); } else if( !fits_strcasecmp(yytext,"#SNULL") ) { return( SNULLREF ); } else { int len; int result; if (yytext[1] == '$') { len = strlen(yytext) - 3; yylval->str[0] = '#'; strncpy(yylval->str+1,&yytext[2],len); yylval->str[len+1] = '\0'; yytext = yylval->str; } result = (*yylParse->getData)(yylParse, yytext, (yylval)); return result; } } YY_BREAK case 12: YY_RULE_SETUP #line 397 "eval.l" { int len; len = strlen(yytext) - 2; if (len >= MAX_STRLEN) { char errMsg[100]; yylParse->status = PARSE_SYNTAX_ERR; strcpy (errMsg,"String exceeds maximum length: '"); strncat(errMsg, &(yytext[1]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { strncpy(yylval->str,&yytext[1],len); } yylval->str[len] = '\0'; return( STRING ); } YY_BREAK case 13: YY_RULE_SETUP #line 414 "eval.l" { int len,type; if (yytext[0] == '$') { len = strlen(yytext) - 2; strncpy(yylval->str,&yytext[1],len); yylval->str[len] = '\0'; yytext = yylval->str; } type = fits_parser_yyGetVariable(yylParse, yytext, (yylval)); return( type ); } YY_BREAK case 14: YY_RULE_SETUP #line 426 "eval.l" { char *fname; int len=0; fname = &(yylval->str[0]); while( (fname[len]=toupper(yytext[len])) ) len++; if( FSTRCMP(fname,"BOX(")==0 || FSTRCMP(fname,"CIRCLE(")==0 || FSTRCMP(fname,"ELLIPSE(")==0 || FSTRCMP(fname,"NEAR(")==0 || FSTRCMP(fname,"ISNULL(")==0 ) /* Return type is always boolean */ return( BFUNCTION ); else if( FSTRCMP(fname,"GTIFILTER(")==0 ) return( GTIFILTER ); else if( FSTRCMP(fname,"GTIOVERLAP(")==0 ) return( GTIOVERLAP ); else if( FSTRCMP(fname,"GTIFIND(")==0 ) return( GTIFIND ); else if( FSTRCMP(fname,"REGFILTER(")==0 ) return( REGFILTER ); else if( FSTRCMP(fname,"STRSTR(")==0 ) return( IFUNCTION ); /* Returns integer */ else return( FUNCTION ); } YY_BREAK case 15: YY_RULE_SETUP #line 459 "eval.l" { return( INTCAST ); } YY_BREAK case 16: YY_RULE_SETUP #line 460 "eval.l" { return( FLTCAST ); } YY_BREAK case 17: YY_RULE_SETUP #line 461 "eval.l" { return( POWER ); } YY_BREAK case 18: YY_RULE_SETUP #line 462 "eval.l" { return( NOT ); } YY_BREAK case 19: YY_RULE_SETUP #line 463 "eval.l" { return( OR ); } YY_BREAK case 20: YY_RULE_SETUP #line 464 "eval.l" { return( AND ); } YY_BREAK case 21: YY_RULE_SETUP #line 465 "eval.l" { return( EQ ); } YY_BREAK case 22: YY_RULE_SETUP #line 466 "eval.l" { return( NE ); } YY_BREAK case 23: YY_RULE_SETUP #line 467 "eval.l" { return( GT ); } YY_BREAK case 24: YY_RULE_SETUP #line 468 "eval.l" { return( LT ); } YY_BREAK case 25: YY_RULE_SETUP #line 469 "eval.l" { return( GTE ); } YY_BREAK case 26: YY_RULE_SETUP #line 470 "eval.l" { return( LTE ); } YY_BREAK case 27: YY_RULE_SETUP #line 471 "eval.l" { return( XOR ); } YY_BREAK case 28: /* rule 28 can match eol */ YY_RULE_SETUP #line 472 "eval.l" { return( '\n' ); } YY_BREAK case 29: YY_RULE_SETUP #line 473 "eval.l" { return( yytext[0] ); } YY_BREAK case 30: YY_RULE_SETUP #line 474 "eval.l" ECHO; YY_BREAK #line 1694 "eval_l.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yyg->yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yyg->yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yyg->yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_END_OF_FILE: { yyg->yy_did_buffer_switch_on_eof = 0; if ( yywrap( yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yyg->yy_c_buf_p = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = yyg->yytext_ptr; int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc( (void *) b->yy_ch_buf, (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = NULL; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), yyg->yy_n_chars, num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } if ( yyg->yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin , yyscanner); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); /* "- 2" to take care of EOB's */ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); } yyg->yy_n_chars += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { yy_state_type yy_current_state; char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 174 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ char *yy_cp = yyg->yy_c_buf_p; YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 174 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 173); (void)yyg; return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT static void yyunput (int c, char * yy_bp , yyscan_t yyscanner) { char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_cp = yyg->yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yyg->yy_hold_char; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ int number_to_move = yyg->yy_n_chars + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yyg->yytext_ptr = yy_bp; yyg->yy_hold_char = *yy_cp; yyg->yy_c_buf_p = yy_cp; } #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner) #else static int input (yyscan_t yyscanner) #endif { int c; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; *yyg->yy_c_buf_p = yyg->yy_hold_char; if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) /* This was really a NUL. */ *yyg->yy_c_buf_p = '\0'; else { /* need more input */ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin , yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( yyscanner ) ) return 0; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(yyscanner); #else return input(yyscanner); #endif } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + offset; break; } } } c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ yyg->yy_hold_char = *++yyg->yy_c_buf_p; return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); yy_load_buffer_state( yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( yyscanner ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } static void yy_load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; yyg->yy_hold_char = *yyg->yy_c_buf_p; } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * @param yyscanner The scanner object. * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file , yyscanner); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * @param yyscanner The scanner object. */ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree( (void *) b->yy_ch_buf , yyscanner ); yyfree( (void *) b , yyscanner ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flush_buffer( b , yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( yyscanner ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * @param yyscanner The scanner object. */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; yyensure_buffer_stack(yyscanner); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * @param yyscanner The scanner object. */ void yypop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (yyscan_t yyscanner) { yy_size_t num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!yyg->yy_buffer_stack) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; } if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return NULL; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = NULL; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b , yyscanner ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) { return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = (yy_size_t) (_yybytes_len + 2); buf = (char *) yyalloc( n , yyscanner ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n , yyscanner); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = yyg->yy_hold_char; \ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ yyg->yy_hold_char = *yyg->yy_c_buf_p; \ *yyg->yy_c_buf_p = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; } /** Get the current line number. * @param yyscanner The scanner object. */ int yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yylineno; } /** Get the current column number. * @param yyscanner The scanner object. */ int yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yycolumn; } /** Get the input stream. * @param yyscanner The scanner object. */ FILE *yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; } /** Get the output stream. * @param yyscanner The scanner object. */ FILE *yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; } /** Get the length of the current token. * @param yyscanner The scanner object. */ int yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; } /** Get the current token. * @param yyscanner The scanner object. */ char *yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; } /** Set the user-defined data. This data is never touched by the scanner. * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; } /** Set the current line number. * @param _line_number line number * @param yyscanner The scanner object. */ void yyset_lineno (int _line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); yylineno = _line_number; } /** Set the current column. * @param _column_no column number * @param yyscanner The scanner object. */ void yyset_column (int _column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) YY_FATAL_ERROR( "yyset_column called with no buffer" ); yycolumn = _column_no; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * @param yyscanner The scanner object. * @see yy_switch_to_buffer */ void yyset_in (FILE * _in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = _in_str ; } void yyset_out (FILE * _out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = _out_str ; } int yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } void yyset_debug (int _bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = _bdebug ; } /* Accessor methods for yylval and yylloc */ YYSTYPE * yyget_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; } /* User-visible API */ /* yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ int yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); return yy_init_globals ( *ptr_yy_globals ); } /* yylex_init_extra has the same functionality as yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). * The user defined value in the first argument will be available to yyalloc in * the yyextra field. */ int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); yyset_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ yyg->yy_buffer_stack = NULL; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; yyg->yy_c_buf_p = NULL; yyg->yy_init = 0; yyg->yy_start = 0; yyg->yy_start_stack_ptr = 0; yyg->yy_start_stack_depth = 0; yyg->yy_start_stack = NULL; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = NULL; yyout = NULL; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ yyfree(yyg->yy_buffer_stack , yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ yyfree( yyg->yy_start_stack , yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ yyfree ( yyscanner , yyscanner ); yyscanner = NULL; return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (const char * s , yyscan_t yyscanner) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; return malloc(size); } void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return realloc(ptr, size); } void yyfree (void * ptr , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 474 "eval.l" int yywrap(yyscan_t scanner) { /* MJT -- 13 June 1996 Supplied for compatibility with pre-2.5.1 versions of flex which do not recognize %option noyywrap */ return(1); } /* expr_read is lifted from old ftools.skel. Now we can use any version of flex with no .skel file necessary! MJT - 13 June 1996 keep a memory of how many bytes have been read previously, so that an unlimited-sized buffer can be supported. PDW - 28 Feb 1998 */ static int expr_read(ParseData *lParse, char *buf, int nbytes) { int n; n = 0; if( !lParse->is_eobuf ) { do { buf[n++] = lParse->expr[lParse->index++]; } while ((nexpr[lParse->index] != '\0')); if( lParse->expr[lParse->index] == '\0' ) lParse->is_eobuf = 1; } buf[n] = '\0'; return(n); } int fits_parser_yyGetVariable( ParseData *lParse, char *varName, FITS_PARSER_YYSTYPE *thelval ) { int varNum, type; char errMsg[MAXVARNAME+25]; varNum = find_variable( lParse, varName ); if( varNum<0 ) { if( lParse->getData ) { type = (*lParse->getData)( lParse, varName, thelval ); } else { type = pERROR; lParse->status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Unable to find data: "); strncat(errMsg, varName, MAXVARNAME); ffpmsg (errMsg); } } else { /* Convert variable type into expression type */ switch( lParse->varData[ varNum ].type ) { case LONG: case DOUBLE: type = COLUMN; break; case BOOLEAN: type = BCOLUMN; break; case STRING: type = SCOLUMN; break; case BITSTR: type = BITCOL; break; default: type = pERROR; lParse->status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Bad datatype for data: "); strncat(errMsg, varName, MAXVARNAME); ffpmsg (errMsg); break; } thelval->lng = varNum; } return( type ); } static int find_variable(ParseData *lParse, char *varName) { int i; if( lParse->nCols ) for( i=0; inCols; i++ ) { if( ! fits_strncasecmp(lParse->varData[i].name,varName,MAXVARNAME) ) { return( i ); } } return( -1 ); } cfitsio-4.3.1/f77_wrap2.c0000644000225700000360000010253714335036354014345 0ustar cagordonlhea/************************************************************************ f77_wrap1.c and f77_wrap2.c have now been split into 4 files to prevent compile-time memory errors (from expansion of compiler commands). f77_wrap1.c was split into f77_wrap1.c and f77_wrap3.c, and f77_wrap2.c was split into f77_wrap2.c and f77_wrap4.c: f77_wrap1.c contains routines operating on whole files and some utility routines. f77_wrap2.c contains routines operating on primary array, image, or column elements. f77_wrap3.c contains routines operating on headers & keywords. f77_wrap4.c contains miscellaneous routines. Peter's original comments: Together, f77_wrap1.c and f77_wrap2.c contain C wrappers for all the CFITSIO routines prototyped in fitsio.h, except for the generic datatype routines and features not supported in fortran (eg, unsigned integers), a few routines prototyped in fitsio2.h, which only a handful of FTOOLS use, plus a few obsolete FITSIO routines not present in CFITSIO. This file allows Fortran code to use the CFITSIO library instead of the FITSIO library without modification. It also gives access to new routines not present in FITSIO. Fortran FTOOLS must continue using the old routine names from FITSIO (ie, ftxxxx), but most of the C-wrappers simply redirect those calls to the corresponding CFITSIO routines (ie, ffxxxx), with appropriate parameter massaging where necessary. The main exception are read/write routines ending in j (ie, long data) which get redirected to C routines ending in k (ie, int data). This is more consistent with the default integer type in Fortran. f77_wrap1.c primarily holds routines operating on whole files and extension headers. f77_wrap2.c handle routines which read and write the data portion, plus miscellaneous extra routines. File created by Peter Wilson (HSTX), Oct-Dec. 1997 ************************************************************************/ #include "fitsio2.h" #include "f77_wrap.h" FCALLSCSUB5(ffgextn,FTGEXTN,ftgextn,FITSUNIT,LONG,LONG,BYTEV,PINT) FCALLSCSUB5(ffpextn,FTPEXTN,ftpextn,FITSUNIT,LONG,LONG,BYTEV,PINT) /*------------ read primary array or image elements -------------*/ FCALLSCSUB8(ffgpvb,FTGPVB,ftgpvb,FITSUNIT,LONG,LONG,LONG,BYTE,BYTEV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvi,FTGPVI,ftgpvi,FITSUNIT,LONG,LONG,LONG,SHORT,SHORTV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvk,FTGPVJ,ftgpvj,FITSUNIT,LONG,LONG,LONG,INT,INTV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvjj,FTGPVK,ftgpvk,FITSUNIT,LONG,LONG,LONG,LONGLONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB8(ffgpve,FTGPVE,ftgpve,FITSUNIT,LONG,LONG,LONG,FLOAT,FLOATV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvd,FTGPVD,ftgpvd,FITSUNIT,LONG,LONG,LONG,DOUBLE,DOUBLEV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvb,FTGPVBLL,ftgpvbll,FITSUNIT,LONG,LONGLONG,LONGLONG,BYTE,BYTEV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvi,FTGPVILL,ftgpvill,FITSUNIT,LONG,LONGLONG,LONGLONG,SHORT,SHORTV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvk,FTGPVJLL,ftgpvjll,FITSUNIT,LONG,LONGLONG,LONGLONG,INT,INTV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvjj,FTGPVKLL,ftgpvkll,FITSUNIT,LONG,LONGLONG,LONGLONG,LONGLONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB8(ffgpve,FTGPVELL,ftgpvell,FITSUNIT,LONG,LONGLONG,LONGLONG,FLOAT,FLOATV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvd,FTGPVDLL,ftgpvdll,FITSUNIT,LONG,LONGLONG,LONGLONG,DOUBLE,DOUBLEV,PLOGICAL,PINT) #define ftgpfb_LOGV_A6 A4 FCALLSCSUB8(ffgpfb,FTGPFB,ftgpfb,FITSUNIT,LONG,LONG,LONG,BYTEV,LOGICALV,PLOGICAL,PINT) #define ftgpfi_LOGV_A6 A4 FCALLSCSUB8(ffgpfi,FTGPFI,ftgpfi,FITSUNIT,LONG,LONG,LONG,SHORTV,LOGICALV,PLOGICAL,PINT) #define ftgpfj_LOGV_A6 A4 FCALLSCSUB8(ffgpfk,FTGPFJ,ftgpfj,FITSUNIT,LONG,LONG,LONG,INTV,LOGICALV,PLOGICAL,PINT) #define ftgpfk_LOGV_A6 A4 FCALLSCSUB8(ffgpfjj,FTGPFK,ftgpfk,FITSUNIT,LONG,LONG,LONG,LONGLONGV,LOGICALV,PLOGICAL,PINT) #define ftgpfe_LOGV_A6 A4 FCALLSCSUB8(ffgpfe,FTGPFE,ftgpfe,FITSUNIT,LONG,LONG,LONG,FLOATV,LOGICALV,PLOGICAL,PINT) #define ftgpfd_LOGV_A6 A4 FCALLSCSUB8(ffgpfd,FTGPFD,ftgpfd,FITSUNIT,LONG,LONG,LONG,DOUBLEV,LOGICALV,PLOGICAL,PINT) FCALLSCSUB9(ffg2db,FTG2DB,ftg2db,FITSUNIT,LONG,BYTE,LONG,LONG,LONG,BYTEV,PLOGICAL,PINT) FCALLSCSUB9(ffg2di,FTG2DI,ftg2di,FITSUNIT,LONG,SHORT,LONG,LONG,LONG,SHORTV,PLOGICAL,PINT) FCALLSCSUB9(ffg2dk,FTG2DJ,ftg2dj,FITSUNIT,LONG,INT,LONG,LONG,LONG,INTV,PLOGICAL,PINT) FCALLSCSUB9(ffg2djj,FTG2DK,ftg2dk,FITSUNIT,LONG,LONGLONG,LONG,LONG,LONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB9(ffg2de,FTG2DE,ftg2de,FITSUNIT,LONG,FLOAT,LONG,LONG,LONG,FLOATV,PLOGICAL,PINT) FCALLSCSUB9(ffg2dd,FTG2DD,ftg2dd,FITSUNIT,LONG,DOUBLE,LONG,LONG,LONG,DOUBLEV,PLOGICAL,PINT) FCALLSCSUB11(ffg3db,FTG3DB,ftg3db,FITSUNIT,LONG,BYTE,LONG,LONG,LONG,LONG,LONG,BYTEV,PLOGICAL,PINT) FCALLSCSUB11(ffg3di,FTG3DI,ftg3di,FITSUNIT,LONG,SHORT,LONG,LONG,LONG,LONG,LONG,SHORTV,PLOGICAL,PINT) FCALLSCSUB11(ffg3dk,FTG3DJ,ftg3dj,FITSUNIT,LONG,INT,LONG,LONG,LONG,LONG,LONG,INTV,PLOGICAL,PINT) FCALLSCSUB11(ffg3djj,FTG3DK,ftg3dk,FITSUNIT,LONG,LONGLONG,LONG,LONG,LONG,LONG,LONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB11(ffg3de,FTG3DE,ftg3de,FITSUNIT,LONG,FLOAT,LONG,LONG,LONG,LONG,LONG,FLOATV,PLOGICAL,PINT) FCALLSCSUB11(ffg3dd,FTG3DD,ftg3dd,FITSUNIT,LONG,DOUBLE,LONG,LONG,LONG,LONG,LONG,DOUBLEV,PLOGICAL,PINT) /* The follow LONGV definitions have +1 appended because the */ /* routines use of NAXIS+1 elements of the long vectors. */ #define ftgsvb_LONGV_A4 A3+1 #define ftgsvb_LONGV_A5 A3+1 #define ftgsvb_LONGV_A6 A3+1 #define ftgsvb_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvb,FTGSVB,ftgsvb,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,BYTE,BYTEV,PLOGICAL,PINT) #define ftgsvi_LONGV_A4 A3+1 #define ftgsvi_LONGV_A5 A3+1 #define ftgsvi_LONGV_A6 A3+1 #define ftgsvi_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvi,FTGSVI,ftgsvi,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,SHORT,SHORTV,PLOGICAL,PINT) #define ftgsvj_LONGV_A4 A3+1 #define ftgsvj_LONGV_A5 A3+1 #define ftgsvj_LONGV_A6 A3+1 #define ftgsvj_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvk,FTGSVJ,ftgsvj,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,INT,INTV,PLOGICAL,PINT) #define ftgsvk_LONGV_A4 A3+1 #define ftgsvk_LONGV_A5 A3+1 #define ftgsvk_LONGV_A6 A3+1 #define ftgsvk_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvjj,FTGSVK,ftgsvk,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,LONGLONG,LONGLONGV,PLOGICAL,PINT) #define ftgsve_LONGV_A4 A3+1 #define ftgsve_LONGV_A5 A3+1 #define ftgsve_LONGV_A6 A3+1 #define ftgsve_LONGV_A7 A3+1 FCALLSCSUB11(ffgsve,FTGSVE,ftgsve,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,FLOAT,FLOATV,PLOGICAL,PINT) #define ftgsvd_LONGV_A4 A3+1 #define ftgsvd_LONGV_A5 A3+1 #define ftgsvd_LONGV_A6 A3+1 #define ftgsvd_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvd,FTGSVD,ftgsvd,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,DOUBLE,DOUBLEV,PLOGICAL,PINT) /* Must handle LOGICALV conversion manually */ void Cffgsfb( fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, int *flagval, int *anynul, int *status ); void Cffgsfb( fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, int *flagval, int *anynul, int *status ) { char *Cflagval; long nflagval; int i; for( nflagval=1, i=0; i #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffppruj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned long *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; unsigned long nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_pixels(fptr, TULONG, firstelem, nelem, 0, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcluj(fptr, 2, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffppnuj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned long *array, /* I - array of values that are written */ unsigned long nulval, /* I - undefined pixel value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). Any array values that are equal to the value of nulval will be replaced with the null pixel value that is appropriate for this column. */ { long row; unsigned long nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_write_compressed_pixels(fptr, TULONG, firstelem, nelem, 1, array, &nullvalue, status); return(*status); } row=maxvalue(1,group); ffpcnuj(fptr, 2, row, firstelem, nelem, array, nulval, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp2duj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ unsigned long *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { /* call the 3D writing routine, with the 3rd dimension = 1 */ ffp3duj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp3duj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ unsigned long *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 3-D cube of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow, ii, jj; long fpixel[3]= {1,1,1}, lpixel[3]; LONGLONG nfits, narray; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = (long) ncols; lpixel[1] = (long) nrows; lpixel[2] = (long) naxis3; fits_write_compressed_img(fptr, TULONG, fpixel, lpixel, 0, array, NULL, status); return(*status); } tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so write all at once */ ffpcluj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to write to */ narray = 0; /* next pixel in input array to be written */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* writing naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffpcluj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpssuj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long naxis, /* I - number of data axes in array */ long *naxes, /* I - size of each FITS axis */ long *fpixel, /* I - 1st pixel in each axis to write (1=1st) */ long *lpixel, /* I - last pixel in each axis to write */ unsigned long *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write a subsection of pixels to the primary array or image. A subsection is defined to be any contiguous rectangular array of pixels within the n-dimensional FITS data file. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow; LONGLONG fpix[7], dimen[7], astart, pstart; LONGLONG off2, off3, off4, off5, off6, off7; LONGLONG st10, st20, st30, st40, st50, st60, st70; LONGLONG st1, st2, st3, st4, st5, st6, st7; long ii, i1, i2, i3, i4, i5, i6, i7, irange[7]; if (*status > 0) return(*status); if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_write_compressed_img(fptr, TULONG, fpixel, lpixel, 0, array, NULL, status); return(*status); } if (naxis < 1 || naxis > 7) return(*status = BAD_DIMEN); tablerow=maxvalue(1,group); /* calculate the size and number of loops to perform in each dimension */ for (ii = 0; ii < 7; ii++) { fpix[ii]=1; irange[ii]=1; dimen[ii]=1; } for (ii = 0; ii < naxis; ii++) { fpix[ii]=fpixel[ii]; irange[ii]=lpixel[ii]-fpixel[ii]+1; dimen[ii]=naxes[ii]; } i1=irange[0]; /* compute the pixel offset between each dimension */ off2 = dimen[0]; off3 = off2 * dimen[1]; off4 = off3 * dimen[2]; off5 = off4 * dimen[3]; off6 = off5 * dimen[4]; off7 = off6 * dimen[5]; st10 = fpix[0]; st20 = (fpix[1] - 1) * off2; st30 = (fpix[2] - 1) * off3; st40 = (fpix[3] - 1) * off4; st50 = (fpix[4] - 1) * off5; st60 = (fpix[5] - 1) * off6; st70 = (fpix[6] - 1) * off7; /* store the initial offset in each dimension */ st1 = st10; st2 = st20; st3 = st30; st4 = st40; st5 = st50; st6 = st60; st7 = st70; astart = 0; for (i7 = 0; i7 < irange[6]; i7++) { for (i6 = 0; i6 < irange[5]; i6++) { for (i5 = 0; i5 < irange[4]; i5++) { for (i4 = 0; i4 < irange[3]; i4++) { for (i3 = 0; i3 < irange[2]; i3++) { pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7; for (i2 = 0; i2 < irange[1]; i2++) { if (ffpcluj(fptr, 2, tablerow, pstart, i1, &array[astart], status) > 0) return(*status); astart += i1; pstart += off2; } st2 = st20; st3 = st3+off3; } st3 = st30; st4 = st4+off4; } st4 = st40; st5 = st5+off5; } st5 = st50; st6 = st6+off6; } st6 = st60; st7 = st7+off7; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpgpuj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long firstelem, /* I - first vector element to write(1 = 1st) */ long nelem, /* I - number of values to write */ unsigned long *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of group parameters to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffpcluj(fptr, 1L, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpcluj( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned long *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of values to a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer to a virtual column in a 1 or more grouped FITS primary array. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary. */ { int tcode, maxelem, hdutype; long twidth, incre; long ntodo; LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull; double scale, zero; char tform[20], cform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); if (tcode == TSTRING) ffcfmt(tform, cform); /* derive C format for writing strings */ /*---------------------------------------------------------------------*/ /* Now write the pixels to the FITS column. */ /* First call the ffXXfYY routine to (1) convert the datatype */ /* if necessary, and (2) scale the values by the FITS TSCALn and */ /* TZEROn linear scaling parameters into a temporary buffer. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to write */ next = 0; /* next element in array to be written */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to process a one time to the number that will fit in the buffer space or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre); ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */ switch (tcode) { case (TLONG): ffu4fi4(&array[next], ntodo, scale, zero, (INT32BIT *) buffer, status); ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status); break; case (TLONGLONG): ffu4fi8(&array[next], ntodo, scale, zero, (LONGLONG *) buffer, status); ffpi8b(fptr, ntodo, incre, (long *) buffer, status); break; case (TBYTE): ffu4fi1(&array[next], ntodo, scale, zero, (unsigned char *) buffer, status); ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status); break; case (TSHORT): ffu4fi2(&array[next], ntodo, scale, zero, (short *) buffer, status); ffpi2b(fptr, ntodo, incre, (short *) buffer, status); break; case (TFLOAT): ffu4fr4(&array[next], ntodo, scale, zero, (float *) buffer, status); ffpr4b(fptr, ntodo, incre, (float *) buffer, status); break; case (TDOUBLE): ffu4fr8(&array[next], ntodo, scale, zero, (double *) buffer, status); ffpr8b(fptr, ntodo, incre, (double *) buffer, status); break; case (TSTRING): /* numerical column in an ASCII table */ if (cform[1] != 's') /* "%s" format is a string */ { ffu4fstr(&array[next], ntodo, scale, zero, cform, twidth, (char *) buffer, status); if (incre == twidth) /* contiguous bytes */ ffpbyt(fptr, ntodo * twidth, buffer, status); else ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); break; } /* can't write to string column, so fall thru to default: */ default: /* error trap */ snprintf(message,FLEN_ERRMSG, "Cannot write numbers to column %d which has format %s", colnum,tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous write operation */ { snprintf(message,FLEN_ERRMSG, "Error writing elements %.0f thru %.0f of input data array (ffpcluj).", (double) (next+1), (double) (next+ntodo)); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while writing FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpcnuj( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ unsigned long *array, /* I - array of values to write */ unsigned long nulvalue, /* I - value used to flag undefined pixels */ int *status) /* IO - error status */ /* Write an array of elements to the specified column of a table. Any input pixels equal to the value of nulvalue will be replaced by the appropriate null value in the output FITS file. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary */ { tcolumn *colptr; LONGLONG ngood = 0, nbad = 0, ii; LONGLONG repeat, first, fstelm, fstrow; int tcode, overflow = 0; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode > 0) repeat = colptr->trepeat; /* repeat count for this column */ else repeat = firstelem -1 + nelem; /* variable length arrays */ /* if variable length array, first write the whole input vector, then go back and fill in the nulls */ if (tcode < 0) { if (ffpcluj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) { if (*status == NUM_OVERFLOW) { /* ignore overflows, which are possibly the null pixel values */ /* overflow = 1; */ *status = 0; } else { return(*status); } } } /* absolute element number in the column */ first = (firstrow - 1) * repeat + firstelem; for (ii = 0; ii < nelem; ii++) { if (array[ii] != nulvalue) /* is this a good pixel? */ { if (nbad) /* write previous string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0) return(*status); nbad=0; } ngood = ngood +1; /* the consecutive number of good pixels */ } else { if (ngood) /* write previous string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ if (ffpcluj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status) > 0) { if (*status == NUM_OVERFLOW) { overflow = 1; *status = 0; } else { return(*status); } } } ngood=0; } nbad = nbad +1; /* the consecutive number of bad pixels */ } } /* finished loop; now just write the last set of pixels */ if (ngood) /* write last string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ ffpcluj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status); } } else if (nbad) /* write last string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ ffpclu(fptr, colnum, fstrow, fstelm, nbad, status); } if (*status <= 0) { if (overflow) { *status = NUM_OVERFLOW; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fi1(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ unsigned char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) (dvalue + .5); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fi2(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ short *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > SHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else output[ii] = (short) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; output[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else { if (dvalue >= 0) output[ii] = (short) (dvalue + .5); else output[ii] = (short) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fi4(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ INT32BIT *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 2147483648. && sizeof(long) == 4) { /* Instead of subtracting 2147483648, it is more efficient */ /* to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) output[ii] = ( *(long *) &input[ii] ) ^ 0x80000000; } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > INT32_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else output[ii] = input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; output[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else { if (dvalue >= 0) output[ii] = (INT32BIT) (dvalue + .5); else output[ii] = (INT32BIT) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fi8(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ LONGLONG *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 9223372036854775808.) { /* Writing to unsigned long long column. */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ /* no need to check range limits because all unsigned long values */ /* are valid ULONGLONG values. */ for (ii = 0; ii < ntodo; ii++) { output[ii] = ((LONGLONG) input[ii]) ^ 0x8000000000000000; } } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = input[ii]; } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { if (dvalue >= 0) output[ii] = (LONGLONG) (dvalue + .5); else output[ii] = (LONGLONG) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fr4(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ float *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) ((input[ii] - zero) / scale); } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fr8(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ double *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (double) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (input[ii] - zero) / scale; } return(*status); } /*--------------------------------------------------------------------------*/ int ffu4fstr(unsigned long *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ char *cform, /* I - format for output string values */ long twidth, /* I - width of each field, in chars */ char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do scaling if required. */ { long ii; double dvalue; char *cptr; cptr = output; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { sprintf(output, cform, (double) input[ii]); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; sprintf(output, cform, dvalue); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } /* replace any commas with periods (e.g., in French locale) */ while ((cptr = strchr(cptr, ','))) *cptr = '.'; return(*status); } /* ======================================================================== */ /* the following routines support the 'unsigned long long' data type */ /* ======================================================================== */ /*--------------------------------------------------------------------------*/ int ffpprujj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ ULONGLONG *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; unsigned long nullvalue; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ ffpmsg("writing TULONGLONG to compressed image is not supported"); return(*status = DATA_COMPRESSION_ERR); } row=maxvalue(1,group); ffpclujj(fptr, 2, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffppnujj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to write(1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ ULONGLONG *array, /* I - array of values that are written */ ULONGLONG nulval, /* I - undefined pixel value */ int *status) /* IO - error status */ /* Write an array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). Any array values that are equal to the value of nulval will be replaced with the null pixel value that is appropriate for this column. */ { long row; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ ffpmsg("writing TULONGLONG to compressed image is not supported"); return(*status = DATA_COMPRESSION_ERR); } row=maxvalue(1,group); ffpcnujj(fptr, 2, row, firstelem, nelem, array, nulval, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp2dujj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ ULONGLONG *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { /* call the 3D writing routine, with the 3rd dimension = 1 */ ffp3dujj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffp3dujj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ ULONGLONG *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write an entire 3-D cube of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow, ii, jj; long fpixel[3]= {1,1,1}, lpixel[3]; LONGLONG nfits, narray; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ ffpmsg("writing TULONGLONG to compressed image is not supported"); return(*status = DATA_COMPRESSION_ERR); } tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so write all at once */ ffpclujj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to write to */ narray = 0; /* next pixel in input array to be written */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* writing naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffpclujj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpssujj(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long naxis, /* I - number of data axes in array */ long *naxes, /* I - size of each FITS axis */ long *fpixel, /* I - 1st pixel in each axis to write (1=1st) */ long *lpixel, /* I - last pixel in each axis to write */ ULONGLONG *array, /* I - array to be written */ int *status) /* IO - error status */ /* Write a subsection of pixels to the primary array or image. A subsection is defined to be any contiguous rectangular array of pixels within the n-dimensional FITS data file. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long tablerow; LONGLONG fpix[7], dimen[7], astart, pstart; LONGLONG off2, off3, off4, off5, off6, off7; LONGLONG st10, st20, st30, st40, st50, st60, st70; LONGLONG st1, st2, st3, st4, st5, st6, st7; long ii, i1, i2, i3, i4, i5, i6, i7, irange[7]; if (*status > 0) return(*status); if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ ffpmsg("writing TULONGLONG to compressed image is not supported"); return(*status = DATA_COMPRESSION_ERR); } if (naxis < 1 || naxis > 7) return(*status = BAD_DIMEN); tablerow=maxvalue(1,group); /* calculate the size and number of loops to perform in each dimension */ for (ii = 0; ii < 7; ii++) { fpix[ii]=1; irange[ii]=1; dimen[ii]=1; } for (ii = 0; ii < naxis; ii++) { fpix[ii]=fpixel[ii]; irange[ii]=lpixel[ii]-fpixel[ii]+1; dimen[ii]=naxes[ii]; } i1=irange[0]; /* compute the pixel offset between each dimension */ off2 = dimen[0]; off3 = off2 * dimen[1]; off4 = off3 * dimen[2]; off5 = off4 * dimen[3]; off6 = off5 * dimen[4]; off7 = off6 * dimen[5]; st10 = fpix[0]; st20 = (fpix[1] - 1) * off2; st30 = (fpix[2] - 1) * off3; st40 = (fpix[3] - 1) * off4; st50 = (fpix[4] - 1) * off5; st60 = (fpix[5] - 1) * off6; st70 = (fpix[6] - 1) * off7; /* store the initial offset in each dimension */ st1 = st10; st2 = st20; st3 = st30; st4 = st40; st5 = st50; st6 = st60; st7 = st70; astart = 0; for (i7 = 0; i7 < irange[6]; i7++) { for (i6 = 0; i6 < irange[5]; i6++) { for (i5 = 0; i5 < irange[4]; i5++) { for (i4 = 0; i4 < irange[3]; i4++) { for (i3 = 0; i3 < irange[2]; i3++) { pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7; for (i2 = 0; i2 < irange[1]; i2++) { if (ffpclujj(fptr, 2, tablerow, pstart, i1, &array[astart], status) > 0) return(*status); astart += i1; pstart += off2; } st2 = st20; st3 = st3+off3; } st3 = st30; st4 = st4+off4; } st4 = st40; st5 = st5+off5; } st5 = st50; st6 = st6+off6; } st6 = st60; st7 = st7+off7; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpgpujj( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to write(1 = 1st group) */ long firstelem, /* I - first vector element to write(1 = 1st) */ long nelem, /* I - number of values to write */ ULONGLONG *array, /* I - array of values that are written */ int *status) /* IO - error status */ /* Write an array of group parameters to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being written). */ { long row; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffpclujj(fptr, 1L, row, firstelem, nelem, array, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpclujj( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ ULONGLONG *array, /* I - array of values to write */ int *status) /* IO - error status */ /* Write an array of values to a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer to a virtual column in a 1 or more grouped FITS primary array. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary. */ { int tcode, maxelem, hdutype; long twidth, incre; long ntodo; LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull; double scale, zero; char tform[20], cform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0) return(*status); if (tcode == TSTRING) ffcfmt(tform, cform); /* derive C format for writing strings */ /*---------------------------------------------------------------------*/ /* Now write the pixels to the FITS column. */ /* First call the ffXXfYY routine to (1) convert the datatype */ /* if necessary, and (2) scale the values by the FITS TSCALn and */ /* TZEROn linear scaling parameters into a temporary buffer. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to write */ next = 0; /* next element in array to be written */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to process a one time to the number that will fit in the buffer space or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, (repeat - elemnum)); wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre); ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */ switch (tcode) { case (TLONGLONG): ffu8fi8(&array[next], ntodo, scale, zero, (LONGLONG *) buffer, status); ffpi8b(fptr, ntodo, incre, (long *) buffer, status); break; case (TLONG): ffu8fi4(&array[next], ntodo, scale, zero, (INT32BIT *) buffer, status); ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status); break; case (TBYTE): ffu8fi1(&array[next], ntodo, scale, zero, (unsigned char *) buffer, status); ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status); break; case (TSHORT): ffu8fi2(&array[next], ntodo, scale, zero, (short *) buffer, status); ffpi2b(fptr, ntodo, incre, (short *) buffer, status); break; case (TFLOAT): ffu8fr4(&array[next], ntodo, scale, zero, (float *) buffer, status); ffpr4b(fptr, ntodo, incre, (float *) buffer, status); break; case (TDOUBLE): ffu8fr8(&array[next], ntodo, scale, zero, (double *) buffer, status); ffpr8b(fptr, ntodo, incre, (double *) buffer, status); break; case (TSTRING): /* numerical column in an ASCII table */ if (cform[1] != 's') /* "%s" format is a string */ { ffu8fstr(&array[next], ntodo, scale, zero, cform, twidth, (char *) buffer, status); if (incre == twidth) /* contiguous bytes */ ffpbyt(fptr, ntodo * twidth, buffer, status); else ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); break; } /* can't write to string column, so fall thru to default: */ default: /* error trap */ snprintf(message, FLEN_ERRMSG, "Cannot write numbers to column %d which has format %s", colnum,tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous write operation */ { snprintf(message, FLEN_ERRMSG, "Error writing elements %.0f thru %.0f of input data array (ffpcluj).", (double) (next+1), (double) (next+ntodo)); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum += ntodo; if (elemnum == repeat) /* completed a row; start on next row */ { elemnum = 0; rownum++; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while writing FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int ffpcnujj( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to write (1 = 1st col) */ LONGLONG firstrow, /* I - first row to write (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to write (1 = 1st) */ LONGLONG nelem, /* I - number of values to write */ ULONGLONG *array, /* I - array of values to write */ ULONGLONG nulvalue, /* I - value used to flag undefined pixels */ int *status) /* IO - error status */ /* Write an array of elements to the specified column of a table. Any input pixels equal to the value of nulvalue will be replaced by the appropriate null value in the output FITS file. The input array of values will be converted to the datatype of the column and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary */ { tcolumn *colptr; LONGLONG ngood = 0, nbad = 0, ii; LONGLONG repeat, first, fstelm, fstrow; int tcode, overflow = 0; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ tcode = colptr->tdatatype; if (tcode > 0) repeat = colptr->trepeat; /* repeat count for this column */ else repeat = firstelem -1 + nelem; /* variable length arrays */ /* if variable length array, first write the whole input vector, then go back and fill in the nulls */ if (tcode < 0) { if (ffpclujj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) { if (*status == NUM_OVERFLOW) { /* ignore overflows, which are possibly the null pixel values */ /* overflow = 1; */ *status = 0; } else { return(*status); } } } /* absolute element number in the column */ first = (firstrow - 1) * repeat + firstelem; for (ii = 0; ii < nelem; ii++) { if (array[ii] != nulvalue) /* is this a good pixel? */ { if (nbad) /* write previous string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0) return(*status); nbad=0; } ngood = ngood +1; /* the consecutive number of good pixels */ } else { if (ngood) /* write previous string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ if (ffpclujj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status) > 0) { if (*status == NUM_OVERFLOW) { overflow = 1; *status = 0; } else { return(*status); } } } ngood=0; } nbad = nbad +1; /* the consecutive number of bad pixels */ } } /* finished loop; now just write the last set of pixels */ if (ngood) /* write last string of good pixels */ { fstelm = ii - ngood + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ if (tcode > 0) { /* variable length arrays have already been written */ ffpclujj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status); } } else if (nbad) /* write last string of bad pixels */ { fstelm = ii - nbad + first; /* absolute element number */ fstrow = (fstelm - 1) / repeat + 1; /* starting row number */ fstelm = fstelm - (fstrow - 1) * repeat; /* relative number */ ffpclu(fptr, colnum, fstrow, fstelm, nbad, status); } if (*status <= 0) { if (overflow) { *status = NUM_OVERFLOW; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fi1(ULONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ unsigned char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > UCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DUCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = UCHAR_MAX; } else output[ii] = (unsigned char) (dvalue + .5); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fi2(ULONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ short *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > SHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else output[ii] = (short) input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DSHRT_MIN) { *status = OVERFLOW_ERR; output[ii] = SHRT_MIN; } else if (dvalue > DSHRT_MAX) { *status = OVERFLOW_ERR; output[ii] = SHRT_MAX; } else { if (dvalue >= 0) output[ii] = (short) (dvalue + .5); else output[ii] = (short) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fi4(ULONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ INT32BIT *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > INT32_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else output[ii] = input[ii]; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DINT_MIN) { *status = OVERFLOW_ERR; output[ii] = INT32_MIN; } else if (dvalue > DINT_MAX) { *status = OVERFLOW_ERR; output[ii] = INT32_MAX; } else { if (dvalue >= 0) output[ii] = (INT32BIT) (dvalue + .5); else output[ii] = (INT32BIT) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fi8(ULONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ LONGLONG *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required */ { long ii; double dvalue; if (scale == 1. && zero == 9223372036854775808.) { /* Writing to unsigned long long column. */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ /* no need to check range limits because all input values */ /* are valid ULONGLONG values. */ for (ii = 0; ii < ntodo; ii++) { output[ii] = ((LONGLONG) input[ii]) ^ 0x8000000000000000; } } else if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > LONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { output[ii] = input[ii]; } } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; if (dvalue < DLONGLONG_MIN) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MIN; } else if (dvalue > DLONGLONG_MAX) { *status = OVERFLOW_ERR; output[ii] = LONGLONG_MAX; } else { if (dvalue >= 0) output[ii] = (LONGLONG) (dvalue + .5); else output[ii] = (LONGLONG) (dvalue - .5); } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fr4(ULONGLONG *input , /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ float *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (float) ((input[ii] - zero) / scale); } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fr8(ULONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ double *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do datatype conversion and scaling if required. */ { long ii; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) output[ii] = (double) input[ii]; } else { for (ii = 0; ii < ntodo; ii++) output[ii] = (input[ii] - zero) / scale; } return(*status); } /*--------------------------------------------------------------------------*/ int ffu8fstr(ULONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ char *cform, /* I - format for output string values */ long twidth, /* I - width of each field, in chars */ char *output, /* O - output array of converted values */ int *status) /* IO - error status */ /* Copy input to output prior to writing output to a FITS file. Do scaling if required. */ { long ii; double dvalue; char *cptr; cptr = output; if (scale == 1. && zero == 0.) { for (ii = 0; ii < ntodo; ii++) { sprintf(output, cform, (double) input[ii]); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } else { for (ii = 0; ii < ntodo; ii++) { dvalue = (input[ii] - zero) / scale; sprintf(output, cform, dvalue); output += twidth; if (*output) /* if this char != \0, then overflow occurred */ *status = OVERFLOW_ERR; } } /* replace any commas with periods (e.g., in French locale) */ while ((cptr = strchr(cptr, ','))) *cptr = '.'; return(*status); } cfitsio-4.3.1/drvrfile.c0000644000225700000360000006753413472024437014453 0ustar cagordonlhea/* This file, drvrfile.c contains driver routines for disk files. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" #include "group.h" /* needed for fits_get_cwd in file_create */ #if defined(unix) || defined(__unix__) || defined(__unix) #include /* needed in file_openfile */ #ifdef REPLACE_LINKS #include #include #endif #endif #ifdef HAVE_FTRUNCATE #if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) #include /* needed for getcwd prototype on unix machines */ #endif #endif #define IO_SEEK 0 /* last file I/O operation was a seek */ #define IO_READ 1 /* last file I/O operation was a read */ #define IO_WRITE 2 /* last file I/O operation was a write */ static char file_outfile[FLEN_FILENAME]; typedef struct /* structure containing disk file structure */ { FILE *fileptr; LONGLONG currentpos; int last_io_op; } diskdriver; static diskdriver handleTable[NMAXFILES]; /* allocate diskfile handle tables */ /*--------------------------------------------------------------------------*/ int file_init(void) { int ii; for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ { handleTable[ii].fileptr = 0; } return(0); } /*--------------------------------------------------------------------------*/ int file_setoptions(int options) { /* do something with the options argument, to stop compiler warning */ options = 0; return(options); } /*--------------------------------------------------------------------------*/ int file_getoptions(int *options) { *options = 0; return(0); } /*--------------------------------------------------------------------------*/ int file_getversion(int *version) { *version = 10; return(0); } /*--------------------------------------------------------------------------*/ int file_shutdown(void) { return(0); } /*--------------------------------------------------------------------------*/ int file_open(char *filename, int rwmode, int *handle) { FILE *diskfile; int copyhandle, ii, status; char recbuf[2880]; size_t nread; /* if an output filename has been specified as part of the input file, as in "inputfile.fits(outputfile.fit)" then we have to create the output file, copy the input to it, then reopen the the new copy. */ if (*file_outfile) { /* open the original file, with readonly access */ status = file_openfile(filename, READONLY, &diskfile); if (status) { file_outfile[0] = '\0'; return(status); } /* create the output file */ status = file_create(file_outfile,handle); if (status) { ffpmsg("Unable to create output file for copy of input file:"); ffpmsg(file_outfile); file_outfile[0] = '\0'; return(status); } /* copy the file from input to output */ while(0 != (nread = fread(recbuf,1,2880, diskfile))) { status = file_write(*handle, recbuf, nread); if (status) { file_outfile[0] = '\0'; return(status); } } /* close both files */ fclose(diskfile); copyhandle = *handle; file_close(*handle); *handle = copyhandle; /* reuse the old file handle */ /* reopen the new copy, with correct rwmode */ status = file_openfile(file_outfile, rwmode, &diskfile); file_outfile[0] = '\0'; } else { *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].fileptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /*open the file */ status = file_openfile(filename, rwmode, &diskfile); } handleTable[*handle].fileptr = diskfile; handleTable[*handle].currentpos = 0; handleTable[*handle].last_io_op = IO_SEEK; return(status); } /*--------------------------------------------------------------------------*/ int file_openfile(char *filename, int rwmode, FILE **diskfile) /* lowest level routine to physically open a disk file */ { char mode[4]; #if defined(unix) || defined(__unix__) || defined(__unix) char tempname[1024], *cptr, user[80]; struct passwd *pwd; int ii = 0; #if defined(REPLACE_LINKS) struct stat stbuf; int success = 0; size_t n; FILE *f1, *f2; char buf[BUFSIZ]; #endif #endif if (rwmode == READWRITE) { strcpy(mode, "r+b"); /* open existing file with read-write */ } else { strcpy(mode, "rb"); /* open existing file readonly */ } #if MACHINE == ALPHAVMS || MACHINE == VAXVMS /* specify VMS record structure: fixed format, 2880 byte records */ /* but force stream mode access to enable random I/O access */ *diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); #elif defined(unix) || defined(__unix__) || defined(__unix) /* support the ~user/file.fits or ~/file.fits filenames in UNIX */ if (*filename == '~') { if (filename[1] == '/') { cptr = getenv("HOME"); if (cptr) { if (strlen(cptr) + strlen(filename+1) > 1023) return(FILE_NOT_OPENED); strcpy(tempname, cptr); strcat(tempname, filename+1); } else { if (strlen(filename) > 1023) return(FILE_NOT_OPENED); strcpy(tempname, filename); } } else { /* copy user name */ cptr = filename+1; while (*cptr && (*cptr != '/')) { user[ii] = *cptr; cptr++; ii++; } user[ii] = '\0'; /* get structure that includes name of user's home directory */ pwd = getpwnam(user); /* copy user's home directory */ if (strlen(pwd->pw_dir) + strlen(cptr) > 1023) return(FILE_NOT_OPENED); strcpy(tempname, pwd->pw_dir); strcat(tempname, cptr); } *diskfile = fopen(tempname, mode); } else { /* don't need to expand the input file name */ *diskfile = fopen(filename, mode); #if defined(REPLACE_LINKS) if (!(*diskfile) && (rwmode == READWRITE)) { /* failed to open file with READWRITE privilege. Test if */ /* the file we are trying to open is a soft link to a file that */ /* doesn't have write privilege. */ lstat(filename, &stbuf); if ((stbuf.st_mode & S_IFMT) == S_IFLNK) /* is this a soft link? */ { if ((f1 = fopen(filename, "rb")) != 0) /* try opening READONLY */ { if (strlen(filename) + 7 > 1023) return(FILE_NOT_OPENED); strcpy(tempname, filename); strcat(tempname, ".TmxFil"); if ((f2 = fopen(tempname, "wb")) != 0) /* create temp file */ { success = 1; while ((n = fread(buf, 1, BUFSIZ, f1)) > 0) { /* copy linked file to local temporary file */ if (fwrite(buf, 1, n, f2) != n) { success = 0; break; } } fclose(f2); } fclose(f1); if (success) { /* delete link and rename temp file to previous link name */ remove(filename); rename(tempname, filename); /* try once again to open the file with write access */ *diskfile = fopen(filename, mode); } else remove(tempname); /* clean up the failed copy */ } } } #endif } #else /* other non-UNIX machines */ *diskfile = fopen(filename, mode); #endif if (!(*diskfile)) /* couldn't open file */ { return(FILE_NOT_OPENED); } return(0); } /*--------------------------------------------------------------------------*/ int file_create(char *filename, int *handle) { FILE *diskfile; int ii; char mode[4]; int status = 0, rootlen, rootlen2, slen; char *cptr, *cpos; char cwd[FLEN_FILENAME], absURL[FLEN_FILENAME]; char rootstring[256], rootstring2[256]; char username[FLEN_FILENAME], userroot[FLEN_FILENAME], userroot2[FLEN_FILENAME]; cptr = getenv("HERA_DATA_DIRECTORY"); if (cptr) { /* This environment variable is defined in the Hera data analysis environment. */ /* It specifies the root directory path to the users data directories. */ /* CFITSIO will verify that the path to the file that is to be created */ /* is within this root directory + the user's home directory name. */ /* printf("env = %s\n",cptr); */ if (strlen(cptr) > 200) /* guard against possible string overflows */ return(FILE_NOT_CREATED); /* environment variable has the form "path/one/;/path/two/" where the */ /* second path is optional */ strcpy(rootstring, cptr); cpos = strchr(rootstring, ';'); if (cpos) { *cpos = '\0'; cpos++; strcpy(rootstring2, cpos); } else { *rootstring2 = '\0'; } /* printf("%s, %s\n", rootstring, rootstring2); printf("CWD = %s\n", cwd); printf("rootstring=%s, cwd=%s.\n", rootstring, cwd); */ /* Get the current working directory */ fits_get_cwd(cwd, &status); slen = strlen(cwd); if ((slen < FLEN_FILENAME) && cwd[slen-1] != '/') strcat(cwd,"/"); /* make sure the CWD ends with slash */ /* check that CWD string matches the rootstring */ rootlen = strlen(rootstring); if (strncmp(rootstring, cwd, rootlen)) { ffpmsg("invalid CWD: does not match root data directory"); return(FILE_NOT_CREATED); } else { /* get the user name from CWD (it follows the root string) */ strncpy(username, cwd+rootlen, 50); /* limit length of user name */ username[50]=0; cpos=strchr(username, '/'); if (!cpos) { ffpmsg("invalid CWD: not equal to root data directory + username"); return(FILE_NOT_CREATED); } else { *(cpos+1) = '\0'; /* truncate user name string */ /* construct full user root name */ strcpy(userroot, rootstring); strcat(userroot, username); rootlen = strlen(userroot); /* construct alternate full user root name */ strcpy(userroot2, rootstring2); strcat(userroot2, username); rootlen2 = strlen(userroot2); /* convert the input filename to absolute path relative to the CWD */ fits_relurl2url(cwd, filename, absURL, &status); /* printf("username = %s\n", username); printf("userroot = %s\n", userroot); printf("userroot2 = %s\n", userroot2); printf("filename = %s\n", filename); printf("ABS = %s\n", absURL); */ /* check that CWD string matches the rootstring or alternate root string */ if ( strncmp(userroot, absURL, rootlen) && strncmp(userroot2, absURL, rootlen2) ) { ffpmsg("invalid filename: path not within user directory"); return(FILE_NOT_CREATED); } } } /* if we got here, then the input filename appears to be valid */ } *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].fileptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ strcpy(mode, "w+b"); /* create new file with read-write */ diskfile = fopen(filename, "r"); /* does file already exist? */ if (diskfile) { fclose(diskfile); /* close file and exit with error */ return(FILE_NOT_CREATED); } #if MACHINE == ALPHAVMS || MACHINE == VAXVMS /* specify VMS record structure: fixed format, 2880 byte records */ /* but force stream mode access to enable random I/O access */ diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); #else diskfile = fopen(filename, mode); #endif if (!(diskfile)) /* couldn't create file */ { return(FILE_NOT_CREATED); } handleTable[ii].fileptr = diskfile; handleTable[ii].currentpos = 0; handleTable[ii].last_io_op = IO_SEEK; return(0); } /*--------------------------------------------------------------------------*/ int file_truncate(int handle, LONGLONG filesize) /* truncate the diskfile to a new smaller size */ { #ifdef HAVE_FTRUNCATE int fdesc; fdesc = fileno(handleTable[handle].fileptr); ftruncate(fdesc, (OFF_T) filesize); file_seek(handle, filesize); handleTable[handle].currentpos = filesize; handleTable[handle].last_io_op = IO_SEEK; #endif return(0); } /*--------------------------------------------------------------------------*/ int file_size(int handle, LONGLONG *filesize) /* return the size of the file in bytes */ { OFF_T position1,position2; FILE *diskfile; diskfile = handleTable[handle].fileptr; #if defined(_MSC_VER) && (_MSC_VER >= 1400) /* call the VISUAL C++ version of the routines which support */ /* Large Files (> 2GB) if they are supported (since VC 8.0) */ position1 = _ftelli64(diskfile); /* save current postion */ if (position1 < 0) return(SEEK_ERROR); if (_fseeki64(diskfile, 0, 2) != 0) /* seek to end of file */ return(SEEK_ERROR); position2 = _ftelli64(diskfile); /* get file size */ if (position2 < 0) return(SEEK_ERROR); if (_fseeki64(diskfile, position1, 0) != 0) /* seek back to original pos */ return(SEEK_ERROR); #elif _FILE_OFFSET_BITS - 0 == 64 /* call the newer ftello and fseeko routines , which support */ /* Large Files (> 2GB) if they are supported. */ position1 = ftello(diskfile); /* save current postion */ if (position1 < 0) return(SEEK_ERROR); if (fseeko(diskfile, 0, 2) != 0) /* seek to end of file */ return(SEEK_ERROR); position2 = ftello(diskfile); /* get file size */ if (position2 < 0) return(SEEK_ERROR); if (fseeko(diskfile, position1, 0) != 0) /* seek back to original pos */ return(SEEK_ERROR); #else position1 = ftell(diskfile); /* save current postion */ if (position1 < 0) return(SEEK_ERROR); if (fseek(diskfile, 0, 2) != 0) /* seek to end of file */ return(SEEK_ERROR); position2 = ftell(diskfile); /* get file size */ if (position2 < 0) return(SEEK_ERROR); if (fseek(diskfile, position1, 0) != 0) /* seek back to original pos */ return(SEEK_ERROR); #endif *filesize = (LONGLONG) position2; return(0); } /*--------------------------------------------------------------------------*/ int file_close(int handle) /* close the file */ { if (fclose(handleTable[handle].fileptr) ) return(FILE_NOT_CLOSED); handleTable[handle].fileptr = 0; return(0); } /*--------------------------------------------------------------------------*/ int file_remove(char *filename) /* delete the file from disk */ { remove(filename); return(0); } /*--------------------------------------------------------------------------*/ int file_flush(int handle) /* flush the file */ { if (fflush(handleTable[handle].fileptr) ) return(WRITE_ERROR); /* The flush operation is not supposed to move the internal */ /* file pointer, but it does on some Windows-95 compilers and */ /* perhaps others, so seek to original position to be sure. */ /* This seek will do no harm on other systems. */ #if MACHINE == IBMPC if (file_seek(handle, handleTable[handle].currentpos)) return(SEEK_ERROR); #endif return(0); } /*--------------------------------------------------------------------------*/ int file_seek(int handle, LONGLONG offset) /* seek to position relative to start of the file */ { #if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Microsoft visual studio C++ */ /* _fseeki64 supported beginning with version 8.0 */ if (_fseeki64(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) return(SEEK_ERROR); #elif _FILE_OFFSET_BITS - 0 == 64 if (fseeko(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) return(SEEK_ERROR); #else if (fseek(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) return(SEEK_ERROR); #endif handleTable[handle].currentpos = offset; return(0); } /*--------------------------------------------------------------------------*/ int file_read(int hdl, void *buffer, long nbytes) /* read bytes from the current position in the file */ { long nread; char *cptr; if (handleTable[hdl].last_io_op == IO_WRITE) { if (file_seek(hdl, handleTable[hdl].currentpos)) return(SEEK_ERROR); } nread = (long) fread(buffer, 1, nbytes, handleTable[hdl].fileptr); if (nread == 1) { cptr = (char *) buffer; /* some editors will add a single end-of-file character to a file */ /* Ignore it if the character is a zero, 10, or 32 */ if (*cptr == 0 || *cptr == 10 || *cptr == 32) return(END_OF_FILE); else return(READ_ERROR); } else if (nread != nbytes) { return(READ_ERROR); } handleTable[hdl].currentpos += nbytes; handleTable[hdl].last_io_op = IO_READ; return(0); } /*--------------------------------------------------------------------------*/ int file_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { if (handleTable[hdl].last_io_op == IO_READ) { if (file_seek(hdl, handleTable[hdl].currentpos)) return(SEEK_ERROR); } if((long) fwrite(buffer, 1, nbytes, handleTable[hdl].fileptr) != nbytes) return(WRITE_ERROR); handleTable[hdl].currentpos += nbytes; handleTable[hdl].last_io_op = IO_WRITE; return(0); } /*--------------------------------------------------------------------------*/ int file_compress_open(char *filename, int rwmode, int *hdl) /* This routine opens the compressed diskfile by creating a new uncompressed file then opening it. The input file name (the name of the compressed file) gets replaced with the name of the uncompressed file, which is initially stored in the global file_outfile string. file_outfile then gets set to a null string. */ { FILE *indiskfile, *outdiskfile; int status; char *cptr; /* open the compressed disk file */ status = file_openfile(filename, READONLY, &indiskfile); if (status) { ffpmsg("failed to open compressed disk file (file_compress_open)"); ffpmsg(filename); return(status); } /* name of the output uncompressed file is stored in the */ /* global variable called 'file_outfile'. */ cptr = file_outfile; if (*cptr == '!') { /* clobber any existing file with the same name */ cptr++; remove(cptr); } else { outdiskfile = fopen(file_outfile, "r"); /* does file already exist? */ if (outdiskfile) { ffpmsg("uncompressed file already exists: (file_compress_open)"); ffpmsg(file_outfile); fclose(outdiskfile); /* close file and exit with error */ file_outfile[0] = '\0'; return(FILE_NOT_CREATED); } } outdiskfile = fopen(cptr, "w+b"); /* create new file */ if (!outdiskfile) { ffpmsg("could not create uncompressed file: (file_compress_open)"); ffpmsg(file_outfile); file_outfile[0] = '\0'; return(FILE_NOT_CREATED); } /* uncompress file into another file */ uncompress2file(filename, indiskfile, outdiskfile, &status); fclose(indiskfile); fclose(outdiskfile); if (status) { ffpmsg("error in file_compress_open: failed to uncompressed file:"); ffpmsg(filename); ffpmsg(" into new output file:"); ffpmsg(file_outfile); file_outfile[0] = '\0'; return(status); } strcpy(filename, cptr); /* switch the names */ file_outfile[0] = '\0'; status = file_open(filename, rwmode, hdl); return(status); } /*--------------------------------------------------------------------------*/ int file_is_compressed(char *filename) /* I - FITS file name */ /* Test if the disk file is compressed. Returns 1 if compressed, 0 if not. This may modify the filename string by appending a compression suffex. */ { FILE *diskfile; unsigned char buffer[2]; char tmpfilename[FLEN_FILENAME]; /* Open file. Try various suffix combinations */ if (file_openfile(filename, 0, &diskfile)) { if (strlen(filename) > FLEN_FILENAME - 5) return(0); strcpy(tmpfilename,filename); strcat(filename,".gz"); if (file_openfile(filename, 0, &diskfile)) { #if HAVE_BZIP2 strcpy(filename,tmpfilename); strcat(filename,".bz2"); if (file_openfile(filename, 0, &diskfile)) { #endif strcpy(filename, tmpfilename); strcat(filename,".Z"); if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,".z"); /* it's often lower case on CDROMs */ if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,".zip"); if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,"-z"); /* VMS suffix */ if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,"-gz"); /* VMS suffix */ if (file_openfile(filename, 0, &diskfile)) { strcpy(filename,tmpfilename); /* restore original name */ return(0); /* file not found */ } } } } } #if HAVE_BZIP2 } #endif } } if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */ { fclose(diskfile); /* error reading file so just return */ return(0); } fclose(diskfile); /* see if the 2 bytes have the magic values for a compressed file */ if ( (memcmp(buffer, "\037\213", 2) == 0) || /* GZIP */ (memcmp(buffer, "\120\113", 2) == 0) || /* PKZIP */ (memcmp(buffer, "\037\036", 2) == 0) || /* PACK */ (memcmp(buffer, "\037\235", 2) == 0) || /* LZW */ #if HAVE_BZIP2 (memcmp(buffer, "BZ", 2) == 0) || /* BZip2 */ #endif (memcmp(buffer, "\037\240", 2) == 0)) /* LZH */ { return(1); /* this is a compressed file */ } else { return(0); /* not a compressed file */ } } /*--------------------------------------------------------------------------*/ int file_checkfile (char *urltype, char *infile, char *outfile) { /* special case: if file:// driver, check if the file is compressed */ if ( file_is_compressed(infile) ) { /* if output file has been specified, save the name for future use: */ /* This is the name of the uncompressed file to be created on disk. */ if (strlen(outfile)) { if (!strncmp(outfile, "mem:", 4) ) { /* uncompress the file in memory, with READ and WRITE access */ strcpy(urltype, "compressmem://"); /* use special driver */ *file_outfile = '\0'; } else { strcpy(urltype, "compressfile://"); /* use special driver */ /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile, "file://", 7) ) strcpy(file_outfile,outfile+7); else strcpy(file_outfile,outfile); } } else { /* uncompress the file in memory */ strcpy(urltype, "compress://"); /* use special driver */ *file_outfile = '\0'; /* no output file was specified */ } } else /* an ordinary, uncompressed FITS file on disk */ { /* save the output file name for later use when opening the file. */ /* In this case, the file to be opened will be opened READONLY, */ /* and copied to this newly created output file. The original file */ /* will be closed, and the copy will be opened by CFITSIO for */ /* subsequent processing (possibly with READWRITE access). */ if (strlen(outfile)) { file_outfile[0] = '\0'; strncat(file_outfile,outfile,FLEN_FILENAME-1); } } return 0; } /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ /**** driver routines for stream//: device (stdin or stdout) ********/ /*--------------------------------------------------------------------------*/ int stream_open(char *filename, int rwmode, int *handle) { /* read from stdin */ if (filename) rwmode = 1; /* dummy statement to suppress unused parameter compiler warning */ *handle = 1; /* 1 = stdin */ return(0); } /*--------------------------------------------------------------------------*/ int stream_create(char *filename, int *handle) { /* write to stdout */ if (filename) /* dummy statement to suppress unused parameter compiler warning */ *handle = 2; else *handle = 2; /* 2 = stdout */ return(0); } /*--------------------------------------------------------------------------*/ int stream_size(int handle, LONGLONG *filesize) /* return the size of the file in bytes */ { handle = 0; /* suppress unused parameter compiler warning */ /* this operation is not supported in a stream; return large value */ *filesize = LONG_MAX; return(0); } /*--------------------------------------------------------------------------*/ int stream_close(int handle) /* don't have to close stdin or stdout */ { handle = 0; /* suppress unused parameter compiler warning */ return(0); } /*--------------------------------------------------------------------------*/ int stream_flush(int handle) /* flush the file */ { if (handle == 2) fflush(stdout); return(0); } /*--------------------------------------------------------------------------*/ int stream_seek(int handle, LONGLONG offset) /* seeking is not allowed in a stream */ { offset = handle; /* suppress unused parameter compiler warning */ return(1); } /*--------------------------------------------------------------------------*/ int stream_read(int hdl, void *buffer, long nbytes) /* reading from stdin stream */ { long nread; if (hdl != 1) return(1); /* can only read from stdin */ nread = (long) fread(buffer, 1, nbytes, stdin); if (nread != nbytes) { /* return(READ_ERROR); */ return(END_OF_FILE); } return(0); } /*--------------------------------------------------------------------------*/ int stream_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { if (hdl != 2) return(1); /* can only write to stdout */ if((long) fwrite(buffer, 1, nbytes, stdout) != nbytes) return(WRITE_ERROR); return(0); } cfitsio-4.3.1/cfitsio.pc.in0000644000225700000360000000051014335036354015040 0ustar cagordonlheaprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: cfitsio Description: FITS File Subroutine Library URL: https://heasarc.gsfc.nasa.gov/fitsio/ Version: @CFITSIO_MAJOR@.@CFITSIO_MINOR@.@CFITSIO_MICRO@ Libs: -L${libdir} -lcfitsio Libs.private: @LIBS_CURL@ @LIBS@ -lm Cflags: -I${includedir} cfitsio-4.3.1/testprog.out0000644000225700000360000007673713472024437015077 0ustar cagordonlheaCFITSIO TESTPROG Try opening then closing a nonexistent file: ffopen fptr, status = 0 104 (expect an error) ffclos status = 115 ffinit create new file status = 0 Name of file = testprog.fit, I/O mode = 1 test writing of long string keywords: 123456789012345678901234567890123456789012345678901234567890123456789012345 '12345678901234567890123456789012345678901234567890123456789012345678' 1234567890123456789012345678901234567890123456789012345678901234'6789012345 '1234567890123456789012345678901234567890123456789012345678901234''67' 1234567890123456789012345678901234567890123456789012345678901234''789012345 '1234567890123456789012345678901234567890123456789012345678901234''''' 1234567890123456789012345678901234567890123456789012345678901234567'9012345 '1234567890123456789012345678901234567890123456789012345678901234567' ffflus status = 0 HDU number = 1 Values read back from primary array (99 = null pixel) The 1st, and every 4th pixel should be undefined: 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 1 (ffgpvb) 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 1 (ffgpvi) 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 1 (ffgpvj) 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 1 (ffgpve) 99 2 3 99 5 6 7 99 9 10 11 99 13 14 15 99 17 18 19 99 1 (ffgpvd) * 2 3 * 5 6 7 * 9 10 11 * 13 14 15 * 17 18 19 * 1 (ffgpfb) * 2 3 * 5 6 7 * 9 10 11 * 13 14 15 * 17 18 19 * 1 (ffgpfi) * 2 3 * 5 6 7 * 9 10 11 * 13 14 15 * 17 18 19 * 1 (ffgpfj) * 2 3 * 5 6 7 * 9 10 11 * 13 14 15 * 17 18 19 * 1 (ffgpfe) * 2 3 * 5 6 7 * 9 10 11 * 13 14 15 * 17 18 19 * 1 (ffgpfd) Closed then reopened the FITS file 10 times. HDU number = 1 Name of file = testprog.fit, I/O mode = 1 Read back keywords: simple = 1, bitpix = 32, naxis = 2, naxes = (10, 2) pcount = 0, gcount = 1, extend = 1 KEY_PREC= 'This keyword was written by fxprec' / comment goes here KEY_PREC : 'This keyword was written by fxprec' : comment goes here : KEY_PREC= 'This keyword was written by fxprec' / comment goes here KY_PKNS1 : 'first string' : fxpkns comment : KEY_PKYS value_string fxpkys comment 0 KEY_PKYL 1 fxpkyl comment 0 KEY_PKYJ 11 fxpkyj comment 0 KEY_PKYJ 11.000000 fxpkyj comment 0 KEY_PKYJ 11.000000 fxpkyj comment 0 KEY_PKY S value_string fxpkys comment 0 KEY_PKY L 1 fxpkyl comment 0 KEY_PKY BYTE 11 fxpkyj comment 0 KEY_PKY SHORT 11 fxpkyj comment 0 KEY_PKY INT 11 fxpkyj comment 0 KEY_PKY J 11 fxpkyj comment 0 KEY_PKY E 13.131310 fxpkye comment 0 KEY_PKY D 15.151515 fxpkyd comment 0 KEY_PKYF 12.121210 fxpkyf comment 0 KEY_PKYE 13.131310 fxpkye comment 0 KEY_PKYG 14.14141414141414 fxpkyg comment 0 KEY_PKYD 15.15151515151520 fxpkyd comment 0 KEY_PKYC 13.131310 14.141410 fxpkyc comment 0 KEY_PKFC 13.131313 14.141414 fxpkfc comment 0 KEY_PKYM 15.151515 16.161616 fxpkym comment 0 KEY_PKFM 15.151515 16.161616 fxpkfm comment 0 KEY_PKYT 12345678 0.12345678901235 fxpkyt comment 0 KEY_PKY J 11 [km/s/Mpc] fxpkyj comment 0 KEY_PKY units = km/s/Mpc KEY_PKY J 11 fxpkyj comment 0 KEY_PKY units = KEY_PKY J 11 [feet/second/second] fxpkyj comment 0 KEY_PKY units = feet/second/second KEY_PKLS long string value = This is a very long string value that is continued over more than one keyword. header contains 65 keywords; located at keyword 27 ffgkns: first string, second string, ffgknl: 1, 0, 1 ffgknj: 11, 12, 13 ffgkne: 13.131310, 14.141410, 15.151520 ffgknd: 15.151515, 16.161616, 17.171717 Before deleting the HISTORY and DATE keywords... COMMENT HISTORY DATE KY_PKNS1 After deleting the keywords... COMMENT This keyword was written by fxpcom. KY_PKNS1= 'first string' / fxpkns comment After inserting the keywords... COMMENT This keyword was written by fxpcom. KY_IREC = 'This keyword inserted by fxirec' KY_IKYS = 'insert_value_string' / ikys comment KY_IKYJ = 49 / ikyj comment KY_IKYL = T / ikyl comment KY_IKYE = 1.2346E+01 / ikye comment KY_IKYD = 1.23456789012346E+01 / ikyd comment KY_IKYF = 12.3456 / ikyf comment KY_IKYG = 12.3456789012346 / ikyg comment KY_PKNS1= 'first string' / fxpkns comment After modifying the keywords... COMMENT This keyword was modified by fxmrec KY_MREC = 'This keyword was modified by fxmcrd' NEWIKYS = 'modified_string' / ikys comment KY_IKYJ = 50 / This is a modified comment KY_IKYL = F / ikyl comment KY_IKYE = -1.2346E+01 / ikye comment KY_IKYD = -1.23456789012346E+01 / modified comment KY_IKYF = -12.3456 / ikyf comment KY_IKYG = -12.3456789012346 / ikyg comment KY_PKNS1= 'first string' / fxpkns comment After updating the keywords... COMMENT This keyword was modified by fxmrec KY_UCRD = 'This keyword was updated by fxucrd' NEWIKYS = 'updated_string' / ikys comment KY_IKYJ = 51 / This is a modified comment KY_IKYL = T / ikyl comment KY_IKYE = -1.3346E+01 / ikye comment KY_IKYD = -1.33456789012346E+01 / modified comment KY_IKYF = -13.3456 / ikyf comment KY_IKYG = -13.3456789012346 / ikyg comment KY_PKNS1= 'first string' / fxpkns comment Keywords found using wildcard search (should be 13)... KEY_PKYS= 'value_string' / fxpkys comment KEY_PKYL= T / fxpkyl comment KEY_PKYJ= 11 / [feet/second/second] fxpkyj comment KEY_PKYF= 12.12121 / fxpkyf comment KEY_PKYE= 1.313131E+01 / fxpkye comment KEY_PKYG= 14.14141414141414 / fxpkyg comment KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment KEY_PKYC= (1.313131E+01, 1.414141E+01) / fxpkyc comment KEY_PKYM= (1.51515151515152E+01, 1.61616161616162E+01) / fxpkym comment KEY_PKFC= (13.131313, 14.141414) / fxpkfc comment KEY_PKFM= (15.15151515151515, 16.16161616161616) / fxpkfm comment KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment NEWIKYS = 'updated_string' / ikys comment Copied keyword: ffgkne: 14.141410, 15.151520, 13.131310 Updated header using template file (ffpktp) ffibin status = 0 HDU number = 2 header contains 33 keywords; located at keyword 1 header contains 33 keywords with room for 74 more TDIM3 = (1,2,8), 3, 1, 2, 8 ffpcl_ status = 0 Find the column numbers; a returned status value of 237 is expected and indicates that more than one column name matches the input column name template. Status = 219 indicates that there was no matching column name. Column Xvalue is number 3; status = 0. Column Avalue is number 1; status = 237. Column Lvalue is number 2; status = 237. Column Xvalue is number 3; status = 237. Column Bvalue is number 4; status = 237. Column Ivalue is number 5; status = 237. Column Jvalue is number 6; status = 237. Column Evalue is number 7; status = 237. Column Dvalue is number 8; status = 237. Column Cvalue is number 9; status = 237. Column Mvalue is number 10; status = 237. Column is number 0; status = 219. Information about each column: 15A 16 15 15 Avalue, , A, 15, 1.000000, 0.000000, 1234554321, . 1L 14 1 1 Lvalue, m**2, L, 1, 1.000000, 0.000000, 1234554321, . 16X 1 16 1 Xvalue, cm, X, 16, 1.000000, 0.000000, 1234554321, . 1B 11 1 1 Bvalue, erg/s, B, 1, 1.000000, 0.000000, 99, . 1I 21 1 2 Ivalue, km/s, I, 1, 1.000000, 0.000000, 99, . 1J 41 1 4 Jvalue, , J, 1, 1.000000, 0.000000, 99, . 1E 42 1 4 Evalue, , E, 1, 1.000000, 0.000000, 1234554321, . 1D 82 1 8 Dvalue, , D, 1, 1.000000, 0.000000, 1234554321, . 1C 83 1 8 Cvalue, , C, 1, 1.000000, 0.000000, 1234554321, . 1M 163 1 16 Mvalue, , M, 1, 1.000000, 0.000000, 1234554321, . ffitab status = 0 HDU number = 2 ffpcl_ status = 0 ASCII table: rowlen, nrows, tfields, extname: 76 11 5 Test-ASCII Name 1 A15 Ivalue 17 I10 m**2 Fvalue 28 F14.6 cm Evalue 43 E12.5 erg/s Dvalue 56 D21.14 km/s Data values read from ASCII table: first string 1 1 1 1.0 1.0 second string 2 2 2 2.0 2.0 3 3 3 3.0 3.0 UNDEFINED 4 4 4 4.0 4.0 5 5 5 5.0 5.0 6 6 6 6.0 6.0 7 7 7 7.0 7.0 8 8 8 8.0 8.0 9 9 9 9.0 9.0 10 10 10 10.0 10.0 99 99 99 99.0 99.0 1 1.000000 1.00000E+00 1.00000000000000E+00second string Column name is number 1; status = 0. Column Ivalue is number 2; status = 237. Column Fvalue is number 3; status = 237. Column Evalue is number 4; status = 237. Column Dvalue is number 5; status = 237. Column is number 0; status = 219. A15 16 1 15 Name, 1, , A15, 1.000000, 0.000000, null1, . I10 41 1 10 Ivalue, 17, m**2, I10, 1.000000, 0.000000, null2, . F14.6 82 1 14 Fvalue, 28, cm, F14.6, 1.000000, 0.000000, null3, . E12.5 42 1 12 Evalue, 43, erg/s, E12.5, 1.000000, 0.000000, null4, . D21.14 82 1 21 Dvalue, 56, km/s, D21.14, 1.000000, 0.000000, null5, . Data values after inserting 3 rows after row 2: first string 1 1 1 1.0 1.0 second string 2 2 2 2.0 2.0 0 0 0 0.0 0.0 0 0 0 0.0 0.0 0 0 0 0.0 0.0 3 3 3 3.0 3.0 UNDEFINED 4 4 4 4.0 4.0 5 5 5 5.0 5.0 6 6 6 6.0 6.0 7 7 7 7.0 7.0 8 8 8 8.0 8.0 9 9 9 9.0 9.0 10 10 10 10.0 10.0 99 99 99 99.0 99.0 Data values after deleting 2 rows at row 10: first string 1 1 1 1.0 1.0 second string 2 2 2 2.0 2.0 0 0 0 0.0 0.0 0 0 0 0.0 0.0 0 0 0 0.0 0.0 3 3 3 3.0 3.0 UNDEFINED 4 4 4 4.0 4.0 5 5 5 5.0 5.0 6 6 6 6.0 6.0 9 9 9 9.0 9.0 10 10 10 10.0 10.0 99 99 99 99.0 99.0 Data values after deleting column 3: first string 1 1 1.0 1.0 second string 2 2 2.0 2.0 0 0 0.0 0.0 0 0 0.0 0.0 0 0 0.0 0.0 3 3 3.0 3.0 UNDEFINED 4 4 4.0 4.0 5 5 5.0 5.0 6 6 6.0 6.0 9 9 9.0 9.0 10 10 10.0 10.0 99 99 99.0 99.0 Data values after inserting column 5: first string 1 1 1.0 1.0 0 second string 2 2 2.0 2.0 0 0 0 0.0 0.0 0 0 0 0.0 0.0 0 0 0 0.0 0.0 0 3 3 3.0 3.0 0 UNDEFINED 4 4 4.0 4.0 0 5 5 5.0 5.0 0 6 6 6.0 6.0 0 9 9 9.0 9.0 0 10 10 10.0 10.0 0 99 99 99.0 99.0 0 Create temporary file: ffinit status = 0 Create null primary array: ffiimg status = 0 Create ASCII table with 0 columns: ffitab status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 Create Binary table with 0 columns: ffibin status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 Delete the tmp file: ffdelt status = 0 HDU number = 3 header contains 38 keywords with room for 69 more Binary table: nrows, tfields, extname, pcount: 21 10 Test-BINTABLE 0 Avalue 15A Lvalue 1L m**2 Xvalue 16X cm Bvalue 1B erg/s Ivalue 1I km/s Jvalue 1J Evalue 1E Dvalue 1D Cvalue 1C Mvalue 1M Data values read from binary table: Bit column (X) data values: 01001100 01110000 11110000 01111100 00000000 null string column value = -- (should be --) Read columns with ffgcv_: first string 0 76 1 1 1 1.0 1.0 ( 1.0, -2.0) ( 1.0, -2.0) second string 1 112 2 2 2 2.0 2.0 ( 3.0, -4.0) ( 3.0, -4.0) 0 240 3 3 3 3.0 3.0 ( 5.0, -6.0) ( 5.0, -6.0) NOT DEFINED 0 124 0 -4 -4 -4.0 -4.0 ( 7.0, -8.0) ( 7.0, -8.0) NOT DEFINED 1 0 5 5 5 5.0 5.0 ( 9.0,-10.0) ( 9.0,-10.0) NOT DEFINED 1 0 0 -6 -6 -6.0 -6.0 ( 11.0,-12.0) ( 11.0,-12.0) NOT DEFINED 0 0 7 7 7 7.0 7.0 ( 13.0,-14.0) ( 13.0,-14.0) NOT DEFINED 0 0 0 -8 -8 -8.0 -8.0 ( 15.0,-16.0) ( 15.0,-16.0) NOT DEFINED 0 0 9 9 9 9.0 9.0 ( 17.0,-18.0) ( 17.0,-18.0) NOT DEFINED 1 0 0 -10 -10 -10.0 -10.0 ( 19.0,-20.0) ( 19.0,-20.0) NOT DEFINED 0 0 98 98 98 98.0 98.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 1 0 12 12 12 12.0 12.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 0 0 98 98 98 98.0 98.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 0 0 0 -14 -14 -14.0 -14.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 0 0 98 98 98 98.0 98.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 0 0 0 -16 -16 -16.0 -16.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 1 0 98 98 98 98.0 98.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 1 0 0 -18 -18 -18.0 -18.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 1 0 98 98 98 98.0 98.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 1 0 0 -20 -20 -20.0 -20.0 ( 0.0, 0.0) ( 0.0, 0.0) NOT DEFINED 0 0 98 98 98 98.0 98.0 ( 0.0, 0.0) ( 0.0, 0.0) Read columns with ffgcf_: first string 0 76 1 1 1 1.0 1.0 ( 1.0, -2.0) ( 1.0, -2.0) second string 1 112 2 2 2 2.0 2.0 ( 3.0, -4.0) ( 3.0, -4.0) 0 240 3 3 3 3.0 3.0 ( 5.0, -6.0) ( 5.0, -6.0) 0 124 0 -4 -4 -4.0 -4.0 ( 7.0, -8.0) ( 7.0, -8.0) 1 0 5 5 5 5.0 5.0 ( 9.0,-10.0) ( 9.0,-10.0) 1 0 0 -6 -6 -6.0 -6.0 ( 11.0,-12.0) ( 11.0,-12.0) 0 0 7 7 7 7.0 7.0 ( 13.0,-14.0) ( 13.0,-14.0) 0 0 0 -8 -8 -8.0 -8.0 ( 15.0,-16.0) ( 15.0,-16.0) 0 0 9 9 9 9.0 9.0 ( 17.0,-18.0) ( 17.0,-18.0) 1 0 0 -10 -10 -10.0 -10.0 ( 19.0,-20.0) ( 19.0,-20.0) 0 0 99 99 1 0 12 12 0 0 99 99 0 0 0 -14 0 0 99 99 0 0 0 -16 1 0 99 99 1 0 0 -18 1 0 99 99 1 0 0 -20 0 0 99 99 Data values after inserting 3 rows after row 2: first string 1 1 1 1.0 1.0 second string 2 2 2 2.0 2.0 NOT DEFINED 0 0 0 0.0 0.0 NOT DEFINED 0 0 0 0.0 0.0 NOT DEFINED 0 0 0 0.0 0.0 3 3 3 3.0 3.0 NOT DEFINED 0 -4 -4 -4.0 -4.0 NOT DEFINED 5 5 5 5.0 5.0 NOT DEFINED 0 -6 -6 -6.0 -6.0 NOT DEFINED 7 7 7 7.0 7.0 NOT DEFINED 0 -8 -8 -8.0 -8.0 NOT DEFINED 9 9 9 9.0 9.0 NOT DEFINED 0 -10 -10 -10.0 -10.0 NOT DEFINED 98 98 98 98.0 98.0 Data values after deleting 2 rows at row 10: first string 1 1 1 1.0 1.0 second string 2 2 2 2.0 2.0 NOT DEFINED 0 0 0 0.0 0.0 NOT DEFINED 0 0 0 0.0 0.0 NOT DEFINED 0 0 0 0.0 0.0 3 3 3 3.0 3.0 NOT DEFINED 0 -4 -4 -4.0 -4.0 NOT DEFINED 5 5 5 5.0 5.0 NOT DEFINED 0 -6 -6 -6.0 -6.0 NOT DEFINED 9 9 9 9.0 9.0 NOT DEFINED 0 -10 -10 -10.0 -10.0 NOT DEFINED 98 98 98 98.0 98.0 Data values after deleting column 6: first string 1 1 1.0 1.0 second string 2 2 2.0 2.0 NOT DEFINED 0 0 0.0 0.0 NOT DEFINED 0 0 0.0 0.0 NOT DEFINED 0 0 0.0 0.0 3 3 3.0 3.0 NOT DEFINED 0 -4 -4.0 -4.0 NOT DEFINED 5 5 5.0 5.0 NOT DEFINED 0 -6 -6.0 -6.0 NOT DEFINED 9 9 9.0 9.0 NOT DEFINED 0 -10 -10.0 -10.0 NOT DEFINED 98 98 98.0 98.0 Data values after inserting column 8: first string 1 1 1.0 1.0 0 second string 2 2 2.0 2.0 0 NOT DEFINED 0 0 0.0 0.0 0 NOT DEFINED 0 0 0.0 0.0 0 NOT DEFINED 0 0 0.0 0.0 0 3 3 3.0 3.0 0 NOT DEFINED 0 -4 -4.0 -4.0 0 NOT DEFINED 5 5 5.0 5.0 0 NOT DEFINED 0 -6 -6.0 -6.0 0 NOT DEFINED 9 9 9.0 9.0 0 NOT DEFINED 0 -10 -10.0 -10.0 0 NOT DEFINED 98 98 98.0 98.0 0 Values after setting 1st 10 elements in column 8 = null: first string 1 1 1.0 1.0 98 second string 2 2 2.0 2.0 98 NOT DEFINED 0 0 0.0 0.0 98 NOT DEFINED 0 0 0.0 0.0 98 NOT DEFINED 0 0 0.0 0.0 98 3 3 3.0 3.0 98 NOT DEFINED 0 -4 -4.0 -4.0 98 NOT DEFINED 5 5 5.0 5.0 98 NOT DEFINED 0 -6 -6.0 -6.0 98 NOT DEFINED 9 9 9.0 9.0 98 NOT DEFINED 0 -10 -10.0 -10.0 0 NOT DEFINED 98 98 98.0 98.0 0 Create temporary file: ffinit status = 0 Create null primary array: ffiimg status = 0 Create binary table with 0 columns: ffibin status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 copy column, ffcpcl status = 0 Delete the tmp file: ffdelt status = 0 ffibin status = 0 HDU number = 2 0 1000 10000 33000 66000 -999 0 1000 10000 32768 65535 -999 0 1000 10000 32800 65500 -999 0 1 10 33 66 -999 -32768 -31768 -22768 0 32767 -999 -1 9 99 327 654 -999 Create image extension: ffiimg status = 0 HDU number = 3 Wrote whole 2D array: ffp2di status = 0 Read whole 2D array: ffg2di status = 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 0 0 0 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 0 0 0 0 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 0 0 0 0 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 0 0 0 0 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 0 0 0 0 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 0 0 0 0 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 0 0 0 0 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 0 0 0 0 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 0 0 0 0 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 0 0 0 0 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 0 0 0 0 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 0 0 0 0 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 0 0 0 0 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 0 0 0 0 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 0 0 0 0 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 0 0 0 0 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 0 0 0 0 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 0 0 0 0 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 0 0 0 0 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 0 0 0 0 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 0 0 0 0 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 0 0 0 0 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 0 0 0 0 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 0 0 0 0 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Wrote subset 2D array: ffpssi status = 0 Read whole 2D array: ffg2di status = 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 0 0 0 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 0 0 0 0 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 0 0 0 0 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 0 0 0 0 40 41 42 43 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 54 0 0 0 0 50 51 52 53 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 64 0 0 0 0 60 61 62 63 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 74 0 0 0 0 70 71 72 73 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 84 0 0 0 0 80 81 82 83 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 94 0 0 0 0 90 91 92 93 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 104 0 0 0 0 100 101 102 103 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 114 0 0 0 0 110 111 112 113 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 124 0 0 0 0 120 121 122 123 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 134 0 0 0 0 130 131 132 133 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 144 0 0 0 0 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 0 0 0 0 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 0 0 0 0 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 0 0 0 0 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 0 0 0 0 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 0 0 0 0 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 0 0 0 0 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 0 0 0 0 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 0 0 0 0 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 0 0 0 0 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 0 0 0 0 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Read subset of 2D array: ffgsvi status = 0 41 43 -1 -3 -5 71 73 -31 -33 -35 Create image extension: ffiimg status = 0 HDU number = 4 Create temporary file: ffinit status = 0 Copy image extension to primary array of tmp file. ffcopy status = 0 SIMPLE = T / file does conform to FITS standard BITPIX = 16 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 15 / length of data axis 1 NAXIS2 = 25 / length of data axis 2 EXTEND = T / FITS dataset may contain extensions Delete the tmp file: ffdelt status = 0 Delete the image extension; hdutype, status = 1 0 HDU number = 4 ffcrhd status = 0 Variable length arrays: ffphbn status = 0 ffpcl_ status = 0 PCOUNT = 4446 HDU number = 6 A 0 L 0 0 X 0 0 B 1 0 I 1 0 J 1 0 E 1 0 D 1 0 Column 8 repeat and offset = 1 14 A ab 0 L 0 1 0 X 0 1 0 B 99 2 0 I 99 2 0 J 99 2 0 E 99 2 0 D 99 2 0 Column 8 repeat and offset = 2 49 A abc 0 L 0 0 0 0 X 0 1 0 0 B 1 99 3 0 I 1 99 3 0 J 1 99 3 0 E 1 99 3 0 D 1 99 3 0 Column 8 repeat and offset = 3 105 A abcd 0 L 0 1 0 0 0 X 0 1 0 0 0 B 1 2 99 4 0 I 1 2 99 4 0 J 1 2 99 4 0 E 1 2 99 4 0 D 1 2 99 4 0 Column 8 repeat and offset = 4 182 A abcde 0 L 0 1 0 0 1 0 X 0 1 0 0 1 0 B 1 2 3 99 5 0 I 1 2 3 99 5 0 J 1 2 3 99 5 0 E 1 2 3 99 5 0 D 1 2 3 99 5 0 Column 8 repeat and offset = 5 280 A abcdef 0 L 0 1 0 0 0 1 0 X 0 1 0 0 1 1 0 B 1 2 3 4 99 6 0 I 1 2 3 4 99 6 0 J 1 2 3 4 99 6 0 E 1 2 3 4 99 6 0 D 1 2 3 4 99 6 0 Column 8 repeat and offset = 6 399 A abcdefg 0 L 0 1 0 0 1 0 0 0 X 0 1 0 0 1 1 0 0 B 1 2 3 4 5 99 7 0 I 1 2 3 4 5 99 7 0 J 1 2 3 4 5 99 7 0 E 1 2 3 4 5 99 7 0 D 1 2 3 4 5 99 7 0 Column 8 repeat and offset = 7 539 A abcdefgh 0 L 0 1 0 0 1 1 0 0 0 X 0 1 0 0 1 1 0 0 0 B 1 2 3 4 5 6 99 8 0 I 1 2 3 4 5 6 99 8 0 J 1 2 3 4 5 6 99 8 0 E 1 2 3 4 5 6 99 8 0 D 1 2 3 4 5 6 99 8 0 Column 8 repeat and offset = 8 700 A abcdefghi 0 L 0 1 0 0 1 1 0 0 0 0 X 0 1 0 0 1 1 0 0 0 0 B 1 2 3 4 5 6 7 99 9 0 I 1 2 3 4 5 6 7 99 9 0 J 1 2 3 4 5 6 7 99 9 0 E 1 2 3 4 5 6 7 99 9 0 D 1 2 3 4 5 6 7 99 9 0 Column 8 repeat and offset = 9 883 A abcdefghij 0 L 0 1 0 0 1 1 0 0 0 1 0 X 0 1 0 0 1 1 0 0 0 1 0 B 1 2 3 4 5 6 7 8 99 10 0 I 1 2 3 4 5 6 7 8 99 10 0 J 1 2 3 4 5 6 7 8 99 10 0 E 1 2 3 4 5 6 7 8 99 10 0 D 1 2 3 4 5 6 7 8 99 10 0 Column 8 repeat and offset = 10 1087 A abcdefghijk 0 L 0 1 0 0 1 1 0 0 0 0 1 0 X 0 1 0 0 1 1 0 0 0 1 1 0 B 1 2 3 4 5 6 7 8 9 99 11 0 I 1 2 3 4 5 6 7 8 9 99 11 0 J 1 2 3 4 5 6 7 8 9 99 11 0 E 1 2 3 4 5 6 7 8 9 99 11 0 D 1 2 3 4 5 6 7 8 9 99 11 0 Column 8 repeat and offset = 11 1312 A abcdefghijkl 0 L 0 1 0 0 1 1 0 0 0 1 0 1 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 B 1 2 3 4 5 6 7 8 9 10 99 12 0 I 1 2 3 4 5 6 7 8 9 10 99 12 0 J 1 2 3 4 5 6 7 8 9 10 99 12 0 E 1 2 3 4 5 6 7 8 9 10 99 12 0 D 1 2 3 4 5 6 7 8 9 10 99 12 0 Column 8 repeat and offset = 12 1558 A abcdefghijklm 0 L 0 1 0 0 1 1 0 0 0 1 1 0 0 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 B 1 2 3 4 5 6 7 8 9 10 11 99 13 0 I 1 2 3 4 5 6 7 8 9 10 11 99 13 0 J 1 2 3 4 5 6 7 8 9 10 11 99 13 0 E 1 2 3 4 5 6 7 8 9 10 11 99 13 0 D 1 2 3 4 5 6 7 8 9 10 11 99 13 0 Column 8 repeat and offset = 13 1825 A abcdefghijklmn 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 B 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 I 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 J 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 E 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 D 1 2 3 4 5 6 7 8 9 10 11 12 99 14 0 Column 8 repeat and offset = 14 2113 A abcdefghijklmno 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 B 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 E 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 D 1 2 3 4 5 6 7 8 9 10 11 12 13 99 15 0 Column 8 repeat and offset = 15 2422 A abcdefghijklmnop 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 99 16 0 Column 8 repeat and offset = 16 2752 A abcdefghijklmnopq 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 0 B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 99 17 0 Column 8 repeat and offset = 17 3104 A abcdefghijklmnopqr 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 1 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 1 0 B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 99 18 0 Column 8 repeat and offset = 18 3477 A abcdefghijklmnopqrs 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 0 1 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 1 1 0 B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 99 19 0 Column 8 repeat and offset = 19 3871 A abcdefghijklmnopqrst 0 L 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 X 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 J 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 99 20 0 Column 8 repeat and offset = 20 4286 ffcrim status = 0 ffppr status = 0 Image values written with ffppr and read with ffgpv: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 0 (byte) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 0 (short) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 0 (int) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 0 (long) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 0 (float) 0 2 4 6 8 10 12 14 16 18 20 22 24 26 0 (double) Wrote WCS keywords status = 0 Read WCS keywords with ffgics status = 0 CRVAL1, CRVAL2 = 45.830000000000, 63.570000000000 CRPIX1, CRPIX2 = 256.000000000000, 257.000000000000 CDELT1, CDELT2 = -0.002777770000, 0.002777770000 Rotation = 0.000, CTYPE = -TAN Calculated sky coordinate with ffwldp status = 0 Pixels ( 0.5000, 0.5000) --> ( 47.385204, 62.848968) Sky Calculated pixel coordinate with ffxypx status = 0 Sky ( 47.385204, 62.848968) --> ( 0.5000, 0.5000) Pixels ffcrtb status = 0 ffpcl status = 0 Column values written with ffpcl and read with ffgcl: 0 3 6 9 12 15 18 21 24 27 0 (byte) 0 3 6 9 12 15 18 21 24 27 0 (short) 0 3 6 9 12 15 18 21 24 27 0 (int) 0 3 6 9 12 15 18 21 24 27 0 (long) 0 3 6 9 12 15 18 21 24 27 0 (float) 0 3 6 9 12 15 18 21 24 27 0 (double) Repeatedly move to the 1st 4 HDUs of the file: 12343123431234312343123431234312343123431234312343 Move to extensions by name and version number: (ffmnhd) Test-BINTABLE, 1 = hdu 5, 0 Test-BINTABLE, 3 = hdu 2, 0 Test-BINTABLE, 4 = hdu 6, 0 Test-ASCII, 2 = hdu 4, 0 new_table, 5 = hdu 8, 0 Test-BINTABLE, 0 = hdu 2, 0 Test-BINTABLE, 17 = hdu 2, 301 (expect a 301 error status here) Total number of HDUs in the file = 8 Encode checksum: 1234567890 -> dCW2fBU0dBU0dBU0 Decode checksum: dCW2fBU0dBU0dBU0 -> 1234567890 DATASUM = '475248536' ffgcks data checksum, status = 475248536, 0 ffvcks datastatus, hdustatus, status = 1 1 0 ffupck status = 0 DATASUM = '475248536' ffvcks datastatus, hdustatus, status = 1 1 0 ffclos status = 0 Normally, there should be 8 error messages on the stack all regarding 'numerical overflows': Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Numerical overflow during type conversion while writing FITS data. Status = 0: OK - no error cfitsio-4.3.1/iraffits.c0000644000225700000360000016066113472024437014440 0ustar cagordonlhea/*------------------------------------------------------------------------*/ /* */ /* These routines have been modified by William Pence for use by CFITSIO */ /* The original files were provided by Doug Mink */ /*------------------------------------------------------------------------*/ /* File imhfile.c * August 6, 1998 * By Doug Mink, based on Mike VanHilst's readiraf.c * Module: imhfile.c (IRAF .imh image file reading and writing) * Purpose: Read and write IRAF image files (and translate headers) * Subroutine: irafrhead (filename, lfhead, fitsheader, lihead) * Read IRAF image header * Subroutine: irafrimage (fitsheader) * Read IRAF image pixels (call after irafrhead) * Subroutine: same_path (pixname, hdrname) * Put filename and header path together * Subroutine: iraf2fits (hdrname, irafheader, nbiraf, nbfits) * Convert IRAF image header to FITS image header * Subroutine: irafgeti4 (irafheader, offset) * Get 4-byte integer from arbitrary part of IRAF header * Subroutine: irafgetc2 (irafheader, offset) * Get character string from arbitrary part of IRAF v.1 header * Subroutine: irafgetc (irafheader, offset) * Get character string from arbitrary part of IRAF header * Subroutine: iraf2str (irafstring, nchar) * Convert 2-byte/char IRAF string to 1-byte/char string * Subroutine: irafswap (bitpix,string,nbytes) * Swap bytes in string in place, with FITS bits/pixel code * Subroutine: irafswap2 (string,nbytes) * Swap bytes in string in place * Subroutine irafswap4 (string,nbytes) * Reverse bytes of Integer*4 or Real*4 vector in place * Subroutine irafswap8 (string,nbytes) * Reverse bytes of Real*8 vector in place * Copyright: 2000 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include "fitsio2.h" #include /* define stderr, FD, and NULL */ #include #include /* stddef.h is apparently needed to define size_t */ #include #define FILE_NOT_OPENED 104 /* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */ #define SZ_IMPIXFILE 79 /* name of pixel storage file */ #define SZ_IMHDRFILE 79 /* length of header storage file */ #define SZ_IMTITLE 79 /* image title string */ #define LEN_IMHDR 2052 /* length of std header */ /* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */ #define SZ_IM2PIXFILE 255 /* name of pixel storage file */ #define SZ_IM2HDRFILE 255 /* name of header storage file */ #define SZ_IM2TITLE 383 /* image title string */ #define LEN_IM2HDR 2046 /* length of std header */ /* Offsets into header in bytes for parameters in IRAF version 1 images */ #define IM_HDRLEN 12 /* Length of header in 4-byte ints */ #define IM_PIXTYPE 16 /* Datatype of the pixels */ #define IM_NDIM 20 /* Number of dimensions */ #define IM_LEN 24 /* Length (as stored) */ #define IM_PHYSLEN 52 /* Physical length (as stored) */ #define IM_PIXOFF 88 /* Offset of the pixels */ #define IM_CTIME 108 /* Time of image creation */ #define IM_MTIME 112 /* Time of last modification */ #define IM_LIMTIME 116 /* Time of min,max computation */ #define IM_MAX 120 /* Maximum pixel value */ #define IM_MIN 124 /* Maximum pixel value */ #define IM_PIXFILE 412 /* Name of pixel storage file */ #define IM_HDRFILE 572 /* Name of header storage file */ #define IM_TITLE 732 /* Image name string */ /* Offsets into header in bytes for parameters in IRAF version 2 images */ #define IM2_HDRLEN 6 /* Length of header in 4-byte ints */ #define IM2_PIXTYPE 10 /* Datatype of the pixels */ #define IM2_SWAPPED 14 /* Pixels are byte swapped */ #define IM2_NDIM 18 /* Number of dimensions */ #define IM2_LEN 22 /* Length (as stored) */ #define IM2_PHYSLEN 50 /* Physical length (as stored) */ #define IM2_PIXOFF 86 /* Offset of the pixels */ #define IM2_CTIME 106 /* Time of image creation */ #define IM2_MTIME 110 /* Time of last modification */ #define IM2_LIMTIME 114 /* Time of min,max computation */ #define IM2_MAX 118 /* Maximum pixel value */ #define IM2_MIN 122 /* Maximum pixel value */ #define IM2_PIXFILE 126 /* Name of pixel storage file */ #define IM2_HDRFILE 382 /* Name of header storage file */ #define IM2_TITLE 638 /* Image name string */ /* Codes from iraf/unix/hlib/iraf.h */ #define TY_CHAR 2 #define TY_SHORT 3 #define TY_INT 4 #define TY_LONG 5 #define TY_REAL 6 #define TY_DOUBLE 7 #define TY_COMPLEX 8 #define TY_POINTER 9 #define TY_STRUCT 10 #define TY_USHORT 11 #define TY_UBYTE 12 #define LEN_PIXHDR 1024 #define MAXINT 2147483647 /* Biggest number that can fit in long */ static int isirafswapped(char *irafheader, int offset); static int irafgeti4(char *irafheader, int offset); static char *irafgetc2(char *irafheader, int offset, int nc); static char *irafgetc(char *irafheader, int offset, int nc); static char *iraf2str(char *irafstring, int nchar); static char *irafrdhead(const char *filename, int *lihead); static int irafrdimage (char **buffptr, size_t *buffsize, size_t *filesize, int *status); static int iraftofits (char *hdrname, char *irafheader, int nbiraf, char **buffptr, size_t *nbfits, size_t *fitssize, int *status); static char *same_path(char *pixname, const char *hdrname); static int swaphead=0; /* =1 to swap data bytes of IRAF header values */ static int swapdata=0; /* =1 to swap bytes in IRAF data pixels */ static void irafswap(int bitpix, char *string, int nbytes); static void irafswap2(char *string, int nbytes); static void irafswap4(char *string, int nbytes); static void irafswap8(char *string, int nbytes); static int pix_version (char *irafheader); static int irafncmp (char *irafheader, char *teststring, int nc); static int machswap(void); static int head_version (char *irafheader); static int hgeti4(char* hstring, char* keyword, int* val); static int hgets(char* hstring, char* keyword, int lstr, char* string); static char* hgetc(char* hstring, char* keyword); static char* ksearch(char* hstring, char* keyword); static char *blsearch (char* hstring, char* keyword); static char *strsrch (char* s1, char* s2); static char *strnsrch ( char* s1,char* s2,int ls1); static void hputi4(char* hstring,char* keyword, int ival); static void hputs(char* hstring,char* keyword,char* cval); static void hputcom(char* hstring,char* keyword,char* comment); static void hputl(char* hstring,char* keyword,int lval); static void hputc(char* hstring,char* keyword,char* cval); static int getirafpixname (const char *hdrname, char *irafheader, char *pixfilename, int *status); int iraf2mem(char *filename, char **buffptr, size_t *buffsize, size_t *filesize, int *status); void ffpmsg(const char *err_message); /* CFITS_API is defined below for use on Windows systems. */ /* It is used to identify the public functions which should be exported. */ /* This has no effect on non-windows platforms where "WIN32" is not defined */ /* this is only needed to export the "fits_delete_iraf_file" symbol, which */ /* is called in fpackutil.c (and perhaps in other applications programs) */ #if defined (WIN32) #if defined(cfitsio_EXPORTS) #define CFITS_API __declspec(dllexport) #else #define CFITS_API //__declspec(dllimport) #endif /* CFITS_API */ #else /* defined (WIN32) */ #define CFITS_API #endif int CFITS_API fits_delete_iraf_file(const char *filename, int *status); /*--------------------------------------------------------------------------*/ int fits_delete_iraf_file(const char *filename, /* name of input file */ int *status) /* IO - error status */ /* Delete the iraf .imh header file and the associated .pix data file */ { char *irafheader; int lenirafhead; char pixfilename[SZ_IM2PIXFILE+1]; /* read IRAF header into dynamically created char array (free it later!) */ irafheader = irafrdhead(filename, &lenirafhead); if (!irafheader) { return(*status = FILE_NOT_OPENED); } getirafpixname (filename, irafheader, pixfilename, status); /* don't need the IRAF header any more */ free(irafheader); if (*status > 0) return(*status); remove(filename); remove(pixfilename); return(*status); } /*--------------------------------------------------------------------------*/ int iraf2mem(char *filename, /* name of input file */ char **buffptr, /* O - memory pointer (initially NULL) */ size_t *buffsize, /* O - size of mem buffer, in bytes */ size_t *filesize, /* O - size of FITS file, in bytes */ int *status) /* IO - error status */ /* Driver routine that reads an IRAF image into memory, also converting it into FITS format. */ { char *irafheader; int lenirafhead; *buffptr = NULL; *buffsize = 0; *filesize = 0; /* read IRAF header into dynamically created char array (free it later!) */ irafheader = irafrdhead(filename, &lenirafhead); if (!irafheader) { return(*status = FILE_NOT_OPENED); } /* convert IRAF header to FITS header in memory */ iraftofits(filename, irafheader, lenirafhead, buffptr, buffsize, filesize, status); /* don't need the IRAF header any more */ free(irafheader); if (*status > 0) return(*status); *filesize = (((*filesize - 1) / 2880 ) + 1 ) * 2880; /* multiple of 2880 */ /* append the image data onto the FITS header */ irafrdimage(buffptr, buffsize, filesize, status); return(*status); } /*--------------------------------------------------------------------------*/ /* Subroutine: irafrdhead (was irafrhead in D. Mink's original code) * Purpose: Open and read the iraf .imh file. * Returns: NULL if failure, else pointer to IRAF .imh image header * Notes: The imhdr format is defined in iraf/lib/imhdr.h, some of * which defines or mimicked, above. */ static char *irafrdhead ( const char *filename, /* Name of IRAF header file */ int *lihead) /* Length of IRAF image header in bytes (returned) */ { FILE *fd; int nbr; char *irafheader; char errmsg[FLEN_ERRMSG]; long nbhead; int nihead; *lihead = 0; /* open the image header file */ fd = fopen (filename, "rb"); if (fd == NULL) { ffpmsg("unable to open IRAF header file:"); ffpmsg(filename); return (NULL); } /* Find size of image header file */ if (fseek(fd, 0, 2) != 0) /* move to end of the file */ { ffpmsg("IRAFRHEAD: cannot seek in file:"); ffpmsg(filename); return(NULL); } nbhead = ftell(fd); /* position = size of file */ if (nbhead < 0) { ffpmsg("IRAFRHEAD: cannot get pos. in file:"); ffpmsg(filename); return(NULL); } if (fseek(fd, 0, 0) != 0) /* move back to beginning */ { ffpmsg("IRAFRHEAD: cannot seek to beginning of file:"); ffpmsg(filename); return(NULL); } /* allocate initial sized buffer */ nihead = nbhead + 5000; irafheader = (char *) calloc (1, nihead); if (irafheader == NULL) { snprintf(errmsg, FLEN_ERRMSG,"IRAFRHEAD Cannot allocate %d-byte header", nihead); ffpmsg(errmsg); ffpmsg(filename); return (NULL); } *lihead = nihead; /* Read IRAF header */ nbr = fread (irafheader, 1, nbhead, fd); fclose (fd); /* Reject if header less than minimum length */ if (nbr < LEN_PIXHDR) { snprintf(errmsg, FLEN_ERRMSG,"IRAFRHEAD header file: %d / %d bytes read.", nbr,LEN_PIXHDR); ffpmsg(errmsg); ffpmsg(filename); free (irafheader); return (NULL); } return (irafheader); } /*--------------------------------------------------------------------------*/ static int irafrdimage ( char **buffptr, /* FITS image header (filled) */ size_t *buffsize, /* allocated size of the buffer */ size_t *filesize, /* actual size of the FITS file */ int *status) { FILE *fd; char *bang; int nax = 1, naxis1 = 1, naxis2 = 1, naxis3 = 1, naxis4 = 1, npaxis1 = 1, npaxis2; int bitpix, bytepix, i; char *fitsheader, *image; int nbr, nbimage, nbaxis, nbl, nbdiff; char *pixheader; char *linebuff; int imhver, lpixhead = 0; char pixname[SZ_IM2PIXFILE+1]; char errmsg[FLEN_ERRMSG]; size_t newfilesize; fitsheader = *buffptr; /* pointer to start of header */ /* Convert pixel file name to character string */ hgets (fitsheader, "PIXFILE", SZ_IM2PIXFILE, pixname); hgeti4 (fitsheader, "PIXOFF", &lpixhead); /* Open pixel file, ignoring machine name if present */ if ((bang = strchr (pixname, '!')) != NULL ) fd = fopen (bang + 1, "rb"); else fd = fopen (pixname, "rb"); /* Print error message and exit if pixel file is not found */ if (!fd) { ffpmsg("IRAFRIMAGE: Cannot open IRAF pixel file:"); ffpmsg(pixname); return (*status = FILE_NOT_OPENED); } /* Read pixel header */ pixheader = (char *) calloc (lpixhead, 1); if (pixheader == NULL) { ffpmsg("IRAFRIMAGE: Cannot alloc memory for pixel header"); ffpmsg(pixname); fclose (fd); return (*status = FILE_NOT_OPENED); } nbr = fread (pixheader, 1, lpixhead, fd); /* Check size of pixel header */ if (nbr < lpixhead) { snprintf(errmsg, FLEN_ERRMSG,"IRAF pixel file: %d / %d bytes read.", nbr,LEN_PIXHDR); ffpmsg(errmsg); free (pixheader); fclose (fd); return (*status = FILE_NOT_OPENED); } /* check pixel header magic word */ imhver = pix_version (pixheader); if (imhver < 1) { ffpmsg("File not valid IRAF pixel file:"); ffpmsg(pixname); free (pixheader); fclose (fd); return (*status = FILE_NOT_OPENED); } free (pixheader); /* Find number of bytes to read */ hgeti4 (fitsheader,"NAXIS",&nax); hgeti4 (fitsheader,"NAXIS1",&naxis1); hgeti4 (fitsheader,"NPAXIS1",&npaxis1); if (nax > 1) { hgeti4 (fitsheader,"NAXIS2",&naxis2); hgeti4 (fitsheader,"NPAXIS2",&npaxis2); } if (nax > 2) hgeti4 (fitsheader,"NAXIS3",&naxis3); if (nax > 3) hgeti4 (fitsheader,"NAXIS4",&naxis4); hgeti4 (fitsheader,"BITPIX",&bitpix); if (bitpix < 0) bytepix = -bitpix / 8; else bytepix = bitpix / 8; nbimage = naxis1 * naxis2 * naxis3 * naxis4 * bytepix; newfilesize = *filesize + nbimage; /* header + data */ newfilesize = (((newfilesize - 1) / 2880 ) + 1 ) * 2880; if (newfilesize > *buffsize) /* need to allocate more memory? */ { fitsheader = (char *) realloc (*buffptr, newfilesize); if (fitsheader == NULL) { snprintf(errmsg, FLEN_ERRMSG,"IRAFRIMAGE Cannot allocate %d-byte image buffer", (int) (*filesize)); ffpmsg(errmsg); ffpmsg(pixname); fclose (fd); return (*status = FILE_NOT_OPENED); } } *buffptr = fitsheader; *buffsize = newfilesize; image = fitsheader + *filesize; *filesize = newfilesize; /* Read IRAF image all at once if physical and image dimensions are the same */ if (npaxis1 == naxis1) nbr = fread (image, 1, nbimage, fd); /* Read IRAF image one line at a time if physical and image dimensions differ */ else { nbdiff = (npaxis1 - naxis1) * bytepix; nbaxis = naxis1 * bytepix; linebuff = image; nbr = 0; if (naxis2 == 1 && naxis3 > 1) naxis2 = naxis3; for (i = 0; i < naxis2; i++) { nbl = fread (linebuff, 1, nbaxis, fd); nbr = nbr + nbl; fseek (fd, nbdiff, 1); linebuff = linebuff + nbaxis; } } fclose (fd); /* Check size of image */ if (nbr < nbimage) { snprintf(errmsg, FLEN_ERRMSG,"IRAF pixel file: %d / %d bytes read.", nbr,nbimage); ffpmsg(errmsg); ffpmsg(pixname); return (*status = FILE_NOT_OPENED); } /* Byte-reverse image, if necessary */ if (swapdata) irafswap (bitpix, image, nbimage); return (*status); } /*--------------------------------------------------------------------------*/ /* Return IRAF image format version number from magic word in IRAF header*/ static int head_version ( char *irafheader) /* IRAF image header from file */ { /* Check header file magic word */ if (irafncmp (irafheader, "imhdr", 5) != 0 ) { if (strncmp (irafheader, "imhv2", 5) != 0) return (0); else return (2); } else return (1); } /*--------------------------------------------------------------------------*/ /* Return IRAF image format version number from magic word in IRAF pixel file */ static int pix_version ( char *irafheader) /* IRAF image header from file */ { /* Check pixel file header magic word */ if (irafncmp (irafheader, "impix", 5) != 0) { if (strncmp (irafheader, "impv2", 5) != 0) return (0); else return (2); } else return (1); } /*--------------------------------------------------------------------------*/ /* Verify that file is valid IRAF imhdr or impix by checking first 5 chars * Returns: 0 on success, 1 on failure */ static int irafncmp ( char *irafheader, /* IRAF image header from file */ char *teststring, /* C character string to compare */ int nc) /* Number of characters to compate */ { char *line; if ((line = iraf2str (irafheader, nc)) == NULL) return (1); if (strncmp (line, teststring, nc) == 0) { free (line); return (0); } else { free (line); return (1); } } /*--------------------------------------------------------------------------*/ /* Convert IRAF image header to FITS image header, returning FITS header */ static int iraftofits ( char *hdrname, /* IRAF header file name (may be path) */ char *irafheader, /* IRAF image header */ int nbiraf, /* Number of bytes in IRAF header */ char **buffptr, /* pointer to the FITS header */ size_t *nbfits, /* allocated size of the FITS header buffer */ size_t *fitssize, /* Number of bytes in FITS header (returned) */ /* = number of bytes to the end of the END keyword */ int *status) { char *objname; /* object name from FITS file */ int lstr, i, j, k, ib, nax, nbits; char *pixname, *newpixname, *bang, *chead; char *fitsheader; int nblock, nlines; char *fhead, *fhead1, *fp, endline[81]; char irafchar; char fitsline[81]; int pixtype; int imhver, n, imu, pixoff, impixoff; /* int immax, immin, imtime; */ int imndim, imlen, imphyslen, impixtype; char errmsg[FLEN_ERRMSG]; /* Set up last line of FITS header */ (void)strncpy (endline,"END", 3); for (i = 3; i < 80; i++) endline[i] = ' '; endline[80] = 0; /* Check header magic word */ imhver = head_version (irafheader); if (imhver < 1) { ffpmsg("File not valid IRAF image header"); ffpmsg(hdrname); return(*status = FILE_NOT_OPENED); } if (imhver == 2) { nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81); imndim = IM2_NDIM; imlen = IM2_LEN; imphyslen = IM2_PHYSLEN; impixtype = IM2_PIXTYPE; impixoff = IM2_PIXOFF; /* imtime = IM2_MTIME; */ /* immax = IM2_MAX; */ /* immin = IM2_MIN; */ } else { nlines = 24 + ((nbiraf - LEN_IMHDR) / 162); imndim = IM_NDIM; imlen = IM_LEN; imphyslen = IM_PHYSLEN; impixtype = IM_PIXTYPE; impixoff = IM_PIXOFF; /* imtime = IM_MTIME; */ /* immax = IM_MAX; */ /* immin = IM_MIN; */ } /* Initialize FITS header */ nblock = (nlines * 80) / 2880; *nbfits = (nblock + 5) * 2880 + 4; fitsheader = (char *) calloc (*nbfits, 1); if (fitsheader == NULL) { snprintf(errmsg, FLEN_ERRMSG,"IRAF2FITS Cannot allocate %d-byte FITS header", (int) (*nbfits)); ffpmsg(hdrname); return (*status = FILE_NOT_OPENED); } fhead = fitsheader; *buffptr = fitsheader; (void)strncpy (fitsheader, endline, 80); hputl (fitsheader, "SIMPLE", 1); fhead = fhead + 80; /* check if the IRAF file is in big endian (sun) format (= 0) or not. */ /* This is done by checking the 4 byte integer in the header that */ /* represents the iraf pixel type. This 4-byte word is guaranteed to */ /* have the least sig byte != 0 and the most sig byte = 0, so if the */ /* first byte of the word != 0, then the file in little endian format */ /* like on an Alpha machine. */ swaphead = isirafswapped(irafheader, impixtype); if (imhver == 1) swapdata = swaphead; /* vers 1 data has same swapness as header */ else swapdata = irafgeti4 (irafheader, IM2_SWAPPED); /* Set pixel size in FITS header */ pixtype = irafgeti4 (irafheader, impixtype); switch (pixtype) { case TY_CHAR: nbits = 8; break; case TY_UBYTE: nbits = 8; break; case TY_SHORT: nbits = 16; break; case TY_USHORT: nbits = -16; break; case TY_INT: case TY_LONG: nbits = 32; break; case TY_REAL: nbits = -32; break; case TY_DOUBLE: nbits = -64; break; default: snprintf(errmsg,FLEN_ERRMSG,"Unsupported IRAF data type: %d", pixtype); ffpmsg(errmsg); ffpmsg(hdrname); return (*status = FILE_NOT_OPENED); } hputi4 (fitsheader,"BITPIX",nbits); hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type"); fhead = fhead + 80; /* Set image dimensions in FITS header */ nax = irafgeti4 (irafheader, imndim); hputi4 (fitsheader,"NAXIS",nax); hputcom (fitsheader,"NAXIS", "IRAF .imh naxis"); fhead = fhead + 80; n = irafgeti4 (irafheader, imlen); hputi4 (fitsheader, "NAXIS1", n); hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]"); fhead = fhead + 80; if (nax > 1) { n = irafgeti4 (irafheader, imlen+4); hputi4 (fitsheader, "NAXIS2", n); hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]"); fhead = fhead + 80; } if (nax > 2) { n = irafgeti4 (irafheader, imlen+8); hputi4 (fitsheader, "NAXIS3", n); hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]"); fhead = fhead + 80; } if (nax > 3) { n = irafgeti4 (irafheader, imlen+12); hputi4 (fitsheader, "NAXIS4", n); hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]"); fhead = fhead + 80; } /* Set object name in FITS header */ if (imhver == 2) objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE); else objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE); if ((lstr = strlen (objname)) < 8) { for (i = lstr; i < 8; i++) objname[i] = ' '; objname[8] = 0; } hputs (fitsheader,"OBJECT",objname); hputcom (fitsheader,"OBJECT", "IRAF .imh title"); free (objname); fhead = fhead + 80; /* Save physical axis lengths so image file can be read */ n = irafgeti4 (irafheader, imphyslen); hputi4 (fitsheader, "NPAXIS1", n); hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]"); fhead = fhead + 80; if (nax > 1) { n = irafgeti4 (irafheader, imphyslen+4); hputi4 (fitsheader, "NPAXIS2", n); hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]"); fhead = fhead + 80; } if (nax > 2) { n = irafgeti4 (irafheader, imphyslen+8); hputi4 (fitsheader, "NPAXIS3", n); hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]"); fhead = fhead + 80; } if (nax > 3) { n = irafgeti4 (irafheader, imphyslen+12); hputi4 (fitsheader, "NPAXIS4", n); hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]"); fhead = fhead + 80; } /* Save image header filename in header */ hputs (fitsheader,"IMHFILE",hdrname); hputcom (fitsheader,"IMHFILE", "IRAF header file name"); fhead = fhead + 80; /* Save image pixel file pathname in header */ if (imhver == 2) pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); if (strncmp(pixname, "HDR", 3) == 0 ) { newpixname = same_path (pixname, hdrname); if (newpixname) { free (pixname); pixname = newpixname; } } if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { newpixname = same_path (pixname, hdrname); if (newpixname) { free (pixname); pixname = newpixname; } } if ((bang = strchr (pixname, '!')) != NULL ) hputs (fitsheader,"PIXFILE",bang+1); else hputs (fitsheader,"PIXFILE",pixname); free (pixname); hputcom (fitsheader,"PIXFILE", "IRAF .pix pixel file"); fhead = fhead + 80; /* Save image offset from star of pixel file */ pixoff = irafgeti4 (irafheader, impixoff); pixoff = (pixoff - 1) * 2; hputi4 (fitsheader, "PIXOFF", pixoff); hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)"); fhead = fhead + 80; /* Save IRAF file format version in header */ hputi4 (fitsheader,"IMHVER",imhver); hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)"); fhead = fhead + 80; /* Save flag as to whether to swap IRAF data for this file and machine */ if (swapdata) hputl (fitsheader, "PIXSWAP", 1); else hputl (fitsheader, "PIXSWAP", 0); hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T"); fhead = fhead + 80; /* Add user portion of IRAF header to FITS header */ fitsline[80] = 0; if (imhver == 2) { imu = LEN_IM2HDR; chead = irafheader; j = 0; for (k = 0; k < 80; k++) fitsline[k] = ' '; for (i = imu; i < nbiraf; i++) { irafchar = chead[i]; if (irafchar == 0) break; else if (irafchar == 10) { (void)strncpy (fhead, fitsline, 80); /* fprintf (stderr,"%80s\n",fitsline); */ if (strncmp (fitsline, "OBJECT ", 7) != 0) { fhead = fhead + 80; } for (k = 0; k < 80; k++) fitsline[k] = ' '; j = 0; } else { if (j > 80) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); /* fprintf (stderr,"%80s\n",fitsline); */ j = 9; fhead = fhead + 80; } for (k = 0; k < 80; k++) fitsline[k] = ' '; } if (irafchar > 32 && irafchar < 127) fitsline[j] = irafchar; j++; } } } else { imu = LEN_IMHDR; chead = irafheader; if (swaphead == 1) ib = 0; else ib = 1; for (k = 0; k < 80; k++) fitsline[k] = ' '; j = 0; for (i = imu; i < nbiraf; i=i+2) { irafchar = chead[i+ib]; if (irafchar == 0) break; else if (irafchar == 10) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); fhead = fhead + 80; } /* fprintf (stderr,"%80s\n",fitsline); */ j = 0; for (k = 0; k < 80; k++) fitsline[k] = ' '; } else { if (j > 80) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); j = 9; fhead = fhead + 80; } /* fprintf (stderr,"%80s\n",fitsline); */ for (k = 0; k < 80; k++) fitsline[k] = ' '; } if (irafchar > 32 && irafchar < 127) fitsline[j] = irafchar; j++; } } } /* Add END to last line */ (void)strncpy (fhead, endline, 80); /* Find end of last 2880-byte block of header */ fhead = ksearch (fitsheader, "END") + 80; nblock = *nbfits / 2880; fhead1 = fitsheader + (nblock * 2880); *fitssize = fhead - fitsheader; /* no. of bytes to end of END keyword */ /* Pad rest of header with spaces */ strncpy (endline," ",3); for (fp = fhead; fp < fhead1; fp = fp + 80) { (void)strncpy (fp, endline,80); } return (*status); } /*--------------------------------------------------------------------------*/ /* get the IRAF pixel file name */ static int getirafpixname ( const char *hdrname, /* IRAF header file name (may be path) */ char *irafheader, /* IRAF image header */ char *pixfilename, /* IRAF pixel file name */ int *status) { int imhver; char *pixname, *newpixname, *bang; /* Check header magic word */ imhver = head_version (irafheader); if (imhver < 1) { ffpmsg("File not valid IRAF image header"); ffpmsg(hdrname); return(*status = FILE_NOT_OPENED); } /* get image pixel file pathname in header */ if (imhver == 2) pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); if (strncmp(pixname, "HDR", 3) == 0 ) { newpixname = same_path (pixname, hdrname); if (newpixname) { free (pixname); pixname = newpixname; } } if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { newpixname = same_path (pixname, hdrname); if (newpixname) { free (pixname); pixname = newpixname; } } if ((bang = strchr (pixname, '!')) != NULL ) strcpy(pixfilename,bang+1); else strcpy(pixfilename,pixname); free (pixname); return (*status); } /*--------------------------------------------------------------------------*/ /* Put filename and header path together */ static char *same_path ( char *pixname, /* IRAF pixel file pathname */ const char *hdrname) /* IRAF image header file pathname */ { int len; char *newpixname; /* WDP - 10/16/2007 - increased allocation to avoid possible overflow */ /* newpixname = (char *) calloc (SZ_IM2PIXFILE, sizeof (char)); */ newpixname = (char *) calloc (2*SZ_IM2PIXFILE+1, sizeof (char)); if (newpixname == NULL) { ffpmsg("iraffits same_path: Cannot alloc memory for newpixname"); return (NULL); } /* Pixel file is in same directory as header */ if (strncmp(pixname, "HDR$", 4) == 0 ) { (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); /* find the end of the pathname */ len = strlen (newpixname); #ifndef VMS while( (len > 0) && (newpixname[len-1] != '/') ) #else while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) #endif len--; /* add name */ newpixname[len] = '\0'; (void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE); } /* Bare pixel file with no path is assumed to be same as HDR$filename */ else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); /* find the end of the pathname */ len = strlen (newpixname); #ifndef VMS while( (len > 0) && (newpixname[len-1] != '/') ) #else while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) #endif len--; /* add name */ newpixname[len] = '\0'; (void)strncat (newpixname, pixname, SZ_IM2PIXFILE); } /* Pixel file has same name as header file, but with .pix extension */ else if (strncmp (pixname, "HDR", 3) == 0) { /* load entire header name string into name buffer */ (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); len = strlen (newpixname); newpixname[len-3] = 'p'; newpixname[len-2] = 'i'; newpixname[len-1] = 'x'; } return (newpixname); } /*--------------------------------------------------------------------------*/ static int isirafswapped ( char *irafheader, /* IRAF image header */ int offset) /* Number of bytes to skip before number */ /* check if the IRAF file is in big endian (sun) format (= 0) or not */ /* This is done by checking the 4 byte integer in the header that */ /* represents the iraf pixel type. This 4-byte word is guaranteed to */ /* have the least sig byte != 0 and the most sig byte = 0, so if the */ /* first byte of the word != 0, then the file in little endian format */ /* like on an Alpha machine. */ { int swapped; if (irafheader[offset] != 0) swapped = 1; else swapped = 0; return (swapped); } /*--------------------------------------------------------------------------*/ static int irafgeti4 ( char *irafheader, /* IRAF image header */ int offset) /* Number of bytes to skip before number */ { char *ctemp, *cheader; int temp; cheader = irafheader; ctemp = (char *) &temp; if (machswap() != swaphead) { ctemp[3] = cheader[offset]; ctemp[2] = cheader[offset+1]; ctemp[1] = cheader[offset+2]; ctemp[0] = cheader[offset+3]; } else { ctemp[0] = cheader[offset]; ctemp[1] = cheader[offset+1]; ctemp[2] = cheader[offset+2]; ctemp[3] = cheader[offset+3]; } return (temp); } /*--------------------------------------------------------------------------*/ /* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */ static char *irafgetc2 ( char *irafheader, /* IRAF image header */ int offset, /* Number of bytes to skip before string */ int nc) /* Maximum number of characters in string */ { char *irafstring, *string; irafstring = irafgetc (irafheader, offset, 2*(nc+1)); string = iraf2str (irafstring, nc); free (irafstring); return (string); } /*--------------------------------------------------------------------------*/ /* IRAFGETC -- Get character string from arbitrary part of IRAF header */ static char *irafgetc ( char *irafheader, /* IRAF image header */ int offset, /* Number of bytes to skip before string */ int nc) /* Maximum number of characters in string */ { char *ctemp, *cheader; int i; cheader = irafheader; ctemp = (char *) calloc (nc+1, 1); if (ctemp == NULL) { ffpmsg("IRAFGETC Cannot allocate memory for string variable"); return (NULL); } for (i = 0; i < nc; i++) { ctemp[i] = cheader[offset+i]; if (ctemp[i] > 0 && ctemp[i] < 32) ctemp[i] = ' '; } return (ctemp); } /*--------------------------------------------------------------------------*/ /* Convert IRAF 2-byte/char string to 1-byte/char string */ static char *iraf2str ( char *irafstring, /* IRAF 2-byte/character string */ int nchar) /* Number of characters in string */ { char *string; int i, j; string = (char *) calloc (nchar+1, 1); if (string == NULL) { ffpmsg("IRAF2STR Cannot allocate memory for string variable"); return (NULL); } /* the chars are in bytes 1, 3, 5, ... if bigendian format (SUN) */ /* else in bytes 0, 2, 4, ... if little endian format (Alpha) */ if (irafstring[0] != 0) j = 0; else j = 1; /* Convert appropriate byte of input to output character */ for (i = 0; i < nchar; i++) { string[i] = irafstring[j]; j = j + 2; } return (string); } /*--------------------------------------------------------------------------*/ /* IRAFSWAP -- Reverse bytes of any type of vector in place */ static void irafswap ( int bitpix, /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ char *string, /* Address of starting point of bytes to swap */ int nbytes) /* Number of bytes to swap */ { switch (bitpix) { case 16: if (nbytes < 2) return; irafswap2 (string,nbytes); break; case 32: if (nbytes < 4) return; irafswap4 (string,nbytes); break; case -16: if (nbytes < 2) return; irafswap2 (string,nbytes); break; case -32: if (nbytes < 4) return; irafswap4 (string,nbytes); break; case -64: if (nbytes < 8) return; irafswap8 (string,nbytes); break; } return; } /*--------------------------------------------------------------------------*/ /* IRAFSWAP2 -- Swap bytes in string in place */ static void irafswap2 ( char *string, /* Address of starting point of bytes to swap */ int nbytes) /* Number of bytes to swap */ { char *sbyte, temp, *slast; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp = sbyte[0]; sbyte[0] = sbyte[1]; sbyte[1] = temp; sbyte= sbyte + 2; } return; } /*--------------------------------------------------------------------------*/ /* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ static void irafswap4 ( char *string, /* Address of Integer*4 or Real*4 vector */ int nbytes) /* Number of bytes to reverse */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /*--------------------------------------------------------------------------*/ /* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */ static void irafswap8 ( char *string, /* Address of Real*8 vector */ int nbytes) /* Number of bytes to reverse */ { char *sbyte, *slast; char temp[8]; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp[7] = sbyte[0]; temp[6] = sbyte[1]; temp[5] = sbyte[2]; temp[4] = sbyte[3]; temp[3] = sbyte[4]; temp[2] = sbyte[5]; temp[1] = sbyte[6]; temp[0] = sbyte[7]; sbyte[0] = temp[0]; sbyte[1] = temp[1]; sbyte[2] = temp[2]; sbyte[3] = temp[3]; sbyte[4] = temp[4]; sbyte[5] = temp[5]; sbyte[6] = temp[6]; sbyte[7] = temp[7]; sbyte = sbyte + 8; } return; } /*--------------------------------------------------------------------------*/ static int machswap (void) { char *ctest; int itest; itest = 1; ctest = (char *)&itest; if (*ctest) return (1); else return (0); } /*--------------------------------------------------------------------------*/ /* the following routines were originally in hget.c */ /*--------------------------------------------------------------------------*/ static int lhead0 = 0; /*--------------------------------------------------------------------------*/ /* Extract long value for variable from FITS header string */ static int hgeti4 (hstring,keyword,ival) char *hstring; /* character string containing FITS header information in the format = {/ } */ char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ival; { char *value; double dval; int minint; char val[30]; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { minint = -MAXINT - 1; if (strlen(value) > 29) return(0); strcpy (val, value); dval = atof (val); if (dval+0.001 > MAXINT) *ival = MAXINT; else if (dval >= 0) *ival = (int) (dval + 0.001); else if (dval-0.001 < minint) *ival = minint; else *ival = (int) (dval - 0.001); return (1); } else { return (0); } } /*-------------------------------------------------------------------*/ /* Extract string value for variable from FITS header string */ static int hgets (hstring, keyword, lstr, str) char *hstring; /* character string containing FITS header information in the format = {/ } */ char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *value; int lval; /* Get value and comment from header string */ value = hgetc (hstring,keyword); if (value != NULL) { lval = strlen (value); if (lval < lstr) strcpy (str, value); else if (lstr > 1) { strncpy (str, value, lstr-1); str[lstr-1]=0; } else { str[0] = value[0]; } return (1); } else return (0); } /*-------------------------------------------------------------------*/ /* Extract character value for variable from FITS header string */ static char * hgetc (hstring,keyword0) char *hstring; /* character string containing FITS header information in the format = {/ } */ char *keyword0; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ { static char cval[80]; char *value; char cwhite[2]; char squot[2], dquot[2], lbracket[2], rbracket[2], slash[2], comma[2]; char keyword[81]; /* large for ESO hierarchical keywords */ char line[100]; char *vpos, *cpar = NULL; char *q1, *q2 = NULL, *v1, *v2, *c1, *brack1, *brack2; char *saveptr; int ipar, i; squot[0] = 39; squot[1] = 0; dquot[0] = 34; dquot[1] = 0; lbracket[0] = 91; lbracket[1] = 0; comma[0] = 44; comma[1] = 0; rbracket[0] = 93; rbracket[1] = 0; slash[0] = 47; slash[1] = 0; /* Find length of variable name */ strncpy (keyword,keyword0, sizeof(keyword)-1); keyword[80]=0; brack1 = strsrch (keyword,lbracket); if (brack1 == NULL) brack1 = strsrch (keyword,comma); if (brack1 != NULL) { *brack1 = '\0'; brack1++; } /* Search header string for variable name */ vpos = ksearch (hstring,keyword); /* Exit if not found */ if (vpos == NULL) { return (NULL); } /* Initialize line to nulls */ for (i = 0; i < 100; i++) line[i] = 0; /* In standard FITS, data lasts until 80th character */ /* Extract entry for this variable from the header */ strncpy (line,vpos,80); /* check for quoted value */ q1 = strsrch (line,squot); c1 = strsrch (line,slash); if (q1 != NULL) { if (c1 != NULL && q1 < c1) q2 = strsrch (q1+1,squot); else if (c1 == NULL) q2 = strsrch (q1+1,squot); else q1 = NULL; } else { q1 = strsrch (line,dquot); if (q1 != NULL) { if (c1 != NULL && q1 < c1) q2 = strsrch (q1+1,dquot); else if (c1 == NULL) q2 = strsrch (q1+1,dquot); else q1 = NULL; } else { q1 = NULL; q2 = line + 10; } } /* Extract value and remove excess spaces */ if (q1 != NULL) { v1 = q1 + 1; v2 = q2; c1 = strsrch (q2,"/"); } else { v1 = strsrch (line,"=") + 1; c1 = strsrch (line,"/"); if (c1 != NULL) v2 = c1; else v2 = line + 79; } /* Ignore leading spaces */ while (*v1 == ' ' && v1 < v2) { v1++; } /* Drop trailing spaces */ *v2 = '\0'; v2--; while (*v2 == ' ' && v2 > v1) { *v2 = '\0'; v2--; } if (!strcmp (v1, "-0")) v1++; strcpy (cval,v1); value = cval; /* If keyword has brackets, extract appropriate token from value */ if (brack1 != NULL) { brack2 = strsrch (brack1,rbracket); if (brack2 != NULL) *brack2 = '\0'; ipar = atoi (brack1); if (ipar > 0) { cwhite[0] = ' '; cwhite[1] = '\0'; for (i = 1; i <= ipar; i++) { cpar = ffstrtok (v1,cwhite,&saveptr); v1 = NULL; } if (cpar != NULL) { strcpy (cval,cpar); } else value = NULL; } } return (value); } /*-------------------------------------------------------------------*/ /* Find beginning of fillable blank line before FITS header keyword line */ static char * blsearch (hstring,keyword) /* Find entry for keyword keyword in FITS header string hstring. (the keyword may have a maximum of eight letters) NULL is returned if the keyword is not found */ char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ char *keyword; /* character string containing the name of the variable to be returned. ksearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { char *loc, *headnext, *headlast, *pval, *lc, *line; char *bval; int icol, nextchar, lkey, nleft, lhstr; pval = 0; /* Search header string for variable name */ if (lhead0) lhstr = lhead0; else { lhstr = 0; while (lhstr < 57600 && hstring[lhstr] != 0) lhstr++; } headlast = hstring + lhstr; headnext = hstring; pval = NULL; while (headnext < headlast) { nleft = headlast - headnext; loc = strnsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } icol = (loc - hstring) % 80; lkey = strlen (keyword); nextchar = (int) *(loc + lkey); /* If this is not in the first 8 characters of a line, keep searching */ if (icol > 7) headnext = loc + 1; /* If parameter name in header is longer, keep searching */ else if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If preceeding characters in line are not blanks, keep searching */ else { line = loc - icol; for (lc = line; lc < loc; lc++) { if (*lc != ' ') headnext = loc + 1; } /* Return pointer to start of line if match */ if (loc >= headnext) { pval = line; break; } } } /* Return NULL if keyword is found at start of FITS header string */ if (pval == NULL) return (pval); /* Return NULL if found the first keyword in the header */ if (pval == hstring) return (NULL); /* Find last nonblank line before requested keyword */ bval = pval - 80; while (!strncmp (bval," ",8)) bval = bval - 80; bval = bval + 80; /* Return pointer to calling program if blank lines found */ if (bval < pval) return (bval); else return (NULL); } /*-------------------------------------------------------------------*/ /* Find FITS header line containing specified keyword */ static char *ksearch (hstring,keyword) /* Find entry for keyword keyword in FITS header string hstring. (the keyword may have a maximum of eight letters) NULL is returned if the keyword is not found */ char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ char *keyword; /* character string containing the name of the variable to be returned. ksearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { char *loc, *headnext, *headlast, *pval, *lc, *line; int icol, nextchar, lkey, nleft, lhstr; pval = 0; /* Search header string for variable name */ if (lhead0) lhstr = lhead0; else { lhstr = 0; while (lhstr < 57600 && hstring[lhstr] != 0) lhstr++; } headlast = hstring + lhstr; headnext = hstring; pval = NULL; while (headnext < headlast) { nleft = headlast - headnext; loc = strnsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } icol = (loc - hstring) % 80; lkey = strlen (keyword); nextchar = (int) *(loc + lkey); /* If this is not in the first 8 characters of a line, keep searching */ if (icol > 7) headnext = loc + 1; /* If parameter name in header is longer, keep searching */ else if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If preceeding characters in line are not blanks, keep searching */ else { line = loc - icol; for (lc = line; lc < loc; lc++) { if (*lc != ' ') headnext = loc + 1; } /* Return pointer to start of line if match */ if (loc >= headnext) { pval = line; break; } } } /* Return pointer to calling program */ return (pval); } /*-------------------------------------------------------------------*/ /* Find string s2 within null-terminated string s1 */ static char * strsrch (s1, s2) char *s1; /* String to search */ char *s2; /* String to look for */ { int ls1; ls1 = strlen (s1); return (strnsrch (s1, s2, ls1)); } /*-------------------------------------------------------------------*/ /* Find string s2 within string s1 */ static char * strnsrch (s1, s2, ls1) char *s1; /* String to search */ char *s2; /* String to look for */ int ls1; /* Length of string being searched */ { char *s,*s1e; char cfirst,clast; int i,ls2; /* Return null string if either pointer is NULL */ if (s1 == NULL || s2 == NULL) return (NULL); /* A zero-length pattern is found in any string */ ls2 = strlen (s2); if (ls2 ==0) return (s1); /* Only a zero-length string can be found in a zero-length string */ if (ls1 ==0) return (NULL); cfirst = s2[0]; clast = s2[ls2-1]; s1e = s1 + ls1 - ls2 + 1; s = s1; while (s < s1e) { /* Search for first character in pattern string */ if (*s == cfirst) { /* If single character search, return */ if (ls2 == 1) return (s); /* Search for last character in pattern string if first found */ if (s[ls2-1] == clast) { /* If two-character search, return */ if (ls2 == 2) return (s); /* If 3 or more characters, check for rest of search string */ i = 1; while (i < ls2 && s[i] == s2[i]) i++; /* If entire string matches, return */ if (i >= ls2) return (s); } } s++; } return (NULL); } /*-------------------------------------------------------------------*/ /* the following routines were originally in hget.c */ /*-------------------------------------------------------------------*/ /* HPUTI4 - Set int keyword = ival in FITS header string */ static void hputi4 (hstring,keyword,ival) char *hstring; /* character string containing FITS-style header information in the format = {/ } each entry is padded with spaces to 80 characters */ char *keyword; /* character string containing the name of the variable to be returned. hput searches for a line beginning with this string, and if there isn't one, creates one. The first 8 characters of keyword must be unique. */ int ival; /* int number */ { char value[30]; /* Translate value from binary to ASCII */ snprintf (value,30,"%d",ival); /* Put value into header string */ hputc (hstring,keyword,value); /* Return to calling program */ return; } /*-------------------------------------------------------------------*/ /* HPUTL - Set keyword = F if lval=0, else T, in FITS header string */ static void hputl (hstring, keyword,lval) char *hstring; /* FITS header */ char *keyword; /* Keyword name */ int lval; /* logical variable (0=false, else true) */ { char value[8]; /* Translate value from binary to ASCII */ if (lval) strcpy (value, "T"); else strcpy (value, "F"); /* Put value into header string */ hputc (hstring,keyword,value); /* Return to calling program */ return; } /*-------------------------------------------------------------------*/ /* HPUTS - Set character string keyword = 'cval' in FITS header string */ static void hputs (hstring,keyword,cval) char *hstring; /* FITS header */ char *keyword; /* Keyword name */ char *cval; /* character string containing the value for variable keyword. trailing and leading blanks are removed. */ { char squot = 39; char value[70]; int lcval; /* find length of variable string */ lcval = strlen (cval); if (lcval > 67) lcval = 67; /* Put quotes around string */ value[0] = squot; strncpy (&value[1],cval,lcval); value[lcval+1] = squot; value[lcval+2] = 0; /* Put value into header string */ hputc (hstring,keyword,value); /* Return to calling program */ return; } /*---------------------------------------------------------------------*/ /* HPUTC - Set character string keyword = value in FITS header string */ static void hputc (hstring,keyword,value) char *hstring; char *keyword; char *value; /* character string containing the value for variable keyword. trailing and leading blanks are removed. */ { char squot = 39; char line[100]; char newcom[50]; char blank[80]; char *v, *vp, *v1, *v2, *q1, *q2, *c1, *ve; int lkeyword, lcom, lval, lc, i; for (i = 0; i < 80; i++) blank[i] = ' '; /* find length of keyword and value */ lkeyword = strlen (keyword); lval = strlen (value); /* If COMMENT or HISTORY, always add it just before the END */ if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || strncmp (keyword,"HISTORY",7) == 0)) { /* Find end of header */ v1 = ksearch (hstring,"END"); v2 = v1 + 80; /* Move END down one line */ strncpy (v2, v1, 80); /* Insert keyword */ strncpy (v1,keyword,7); /* Pad with spaces */ for (vp = v1+lkeyword; vp < v2; vp++) *vp = ' '; /* Insert comment */ strncpy (v1+9,value,lval); return; } /* Otherwise search for keyword */ else v1 = ksearch (hstring,keyword); /* If parameter is not found, find a place to put it */ if (v1 == NULL) { /* First look for blank lines before END */ v1 = blsearch (hstring, "END"); /* Otherwise, create a space for it at the end of the header */ if (v1 == NULL) { ve = ksearch (hstring,"END"); v1 = ve; v2 = v1 + 80; strncpy (v2, ve, 80); } else v2 = v1 + 80; lcom = 0; newcom[0] = 0; } /* Otherwise, extract the entry for this keyword from the header */ else { strncpy (line, v1, 80); line[80] = 0; v2 = v1 + 80; /* check for quoted value */ q1 = strchr (line, squot); if (q1 != NULL) q2 = strchr (q1+1,squot); else q2 = line; /* extract comment and remove trailing spaces */ c1 = strchr (q2,'/'); if (c1 != NULL) { lcom = 80 - (c1 - line); strncpy (newcom, c1+1, lcom); vp = newcom + lcom - 1; while (vp-- > newcom && *vp == ' ') *vp = 0; lcom = strlen (newcom); } else { newcom[0] = 0; lcom = 0; } } /* Fill new entry with spaces */ for (vp = v1; vp < v2; vp++) *vp = ' '; /* Copy keyword to new entry */ strncpy (v1, keyword, lkeyword); /* Add parameter value in the appropriate place */ vp = v1 + 8; *vp = '='; vp = v1 + 9; *vp = ' '; vp = vp + 1; if (*value == squot) { strncpy (vp, value, lval); if (lval+12 > 31) lc = lval + 12; else lc = 30; } else { vp = v1 + 30 - lval; strncpy (vp, value, lval); lc = 30; } /* Add comment in the appropriate place */ if (lcom > 0) { if (lc+2+lcom > 80) lcom = 78 - lc; vp = v1 + lc + 2; /* Jul 16 1997: was vp = v1 + lc * 2 */ *vp = '/'; vp = vp + 1; strncpy (vp, newcom, lcom); for (v = vp + lcom; v < v2; v++) *v = ' '; } return; } /*-------------------------------------------------------------------*/ /* HPUTCOM - Set comment for keyword or on line in FITS header string */ static void hputcom (hstring,keyword,comment) char *hstring; char *keyword; char *comment; { char squot; char line[100]; int lkeyword, lcom; char *vp, *v1, *v2, *c0 = NULL, *c1, *q1, *q2; squot = 39; /* Find length of variable name */ lkeyword = strlen (keyword); /* If COMMENT or HISTORY, always add it just before the END */ if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || strncmp (keyword,"HISTORY",7) == 0)) { /* Find end of header */ v1 = ksearch (hstring,"END"); v2 = v1 + 80; strncpy (v2, v1, 80); /* blank out new line and insert keyword */ for (vp = v1; vp < v2; vp++) *vp = ' '; strncpy (v1, keyword, lkeyword); } /* search header string for variable name */ else { v1 = ksearch (hstring,keyword); v2 = v1 + 80; /* if parameter is not found, return without doing anything */ if (v1 == NULL) { return; } /* otherwise, extract entry for this variable from the header */ strncpy (line, v1, 80); /* check for quoted value */ q1 = strchr (line,squot); if (q1 != NULL) q2 = strchr (q1+1,squot); else q2 = NULL; if (q2 == NULL || q2-line < 31) c0 = v1 + 31; else c0 = v1 + (q2-line) + 2; /* allan: 1997-09-30, was c0=q2+2 */ strncpy (c0, "/ ",2); } /* create new entry */ lcom = strlen (comment); if (lcom > 0) { c1 = c0 + 2; if (c1+lcom > v2) lcom = v2 - c1; strncpy (c1, comment, lcom); } } cfitsio-4.3.1/getcolsb.c0000644000225700000360000022704313472024437014431 0ustar cagordonlhea/* This file, getcolsb.c, contains routines that read data elements from */ /* a FITS image or table, with signed char (signed byte) data type. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgpvsb(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ signed char nulval, /* I - value for undefined pixels */ signed char *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; char cdummy; int nullcheck = 1; signed char nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_read_compressed_pixels(fptr, TSBYTE, firstelem, nelem, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclsb(fptr, 2, row, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpfsb(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ signed char *array, /* O - array of values that are returned */ char *nularray, /* O - array of null pixel flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any undefined pixels in the returned array will be set = 0 and the corresponding nularray value will be set = 1. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; int nullcheck = 2; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_read_compressed_pixels(fptr, TSBYTE, firstelem, nelem, nullcheck, NULL, array, nularray, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclsb(fptr, 2, row, firstelem, nelem, 1, 2, 0, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg2dsb(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ signed char nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ signed char *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { /* call the 3D reading routine, with the 3rd dimension = 1 */ ffg3dsb(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg3dsb(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ signed char nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ signed char *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 3-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { long tablerow, ii, jj; LONGLONG nfits, narray; char cdummy; int nullcheck = 1; long inc[] = {1,1,1}; LONGLONG fpixel[] = {1,1,1}; LONGLONG lpixel[3]; signed char nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = ncols; lpixel[1] = nrows; lpixel[2] = naxis3; nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TSBYTE, fpixel, lpixel, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so read all at once */ ffgclsb(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to read */ narray = 0; /* next pixel in output array to be filled */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* reading naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffgclsb(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval, &array[narray], &cdummy, anynul, status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsvsb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ signed char nulval, /* I - value to set undefined pixels */ signed char *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii, i0, i1, i2, i3, i4, i5, i6, i7, i8, row, rstr, rstp, rinc; long str[9], stp[9], incr[9], dir[9]; long nelem, nultyp, ninc, numcol; LONGLONG felem, dsize[10], blcll[9], trcll[9]; int hdutype, anyf; char ldummy, msg[FLEN_ERRMSG]; int nullcheck = 1; signed char nullvalue; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvsb is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TSBYTE, blcll, trcll, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 1; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; dir[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { if (hdutype == IMAGE_HDU) { dir[ii] = -1; } else { snprintf(msg, FLEN_ERRMSG,"ffgsvsb: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; dsize[ii] = dsize[ii] * dir[ii]; } dsize[naxis] = dsize[naxis] * dir[naxis]; if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1; ninc = incr[0] * dir[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8]) { for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7]) { for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6]) { for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5]) { for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4]) { for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3]) { for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2]) { for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1]) { felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] + (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] + (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8]; if ( ffgclsb(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &ldummy, &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsfsb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ signed char *array, /* O - array to be filled and returned */ char *flagval, /* O - set to 1 if corresponding value is null */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dsize[10]; LONGLONG blcll[9], trcll[9]; long felem, nelem, nultyp, ninc, numcol; int hdutype, anyf; signed char nulval = 0; char msg[FLEN_ERRMSG]; int nullcheck = 2; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvsb is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } fits_read_compressed_img(fptr, TSBYTE, blcll, trcll, inc, nullcheck, NULL, array, flagval, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 2; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { snprintf(msg, FLEN_ERRMSG,"ffgsvsb: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; } if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0] - str[0]) / inc[0] + 1; ninc = incr[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8]) { for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7]) { for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6]) { for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5]) { for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4]) { for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3]) { for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2]) { for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1]) { felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] + (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] + (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8]; if ( ffgclsb(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &flagval[i0], &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffggpsb( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long firstelem, /* I - first vector element to read (1 = 1st) */ long nelem, /* I - number of values to read */ signed char *array, /* O - array of values that are returned */ int *status) /* IO - error status */ /* Read an array of group parameters from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). */ { long row; int idummy; char cdummy; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgclsb(fptr, 1, row, firstelem, nelem, 1, 1, 0, array, &cdummy, &idummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcvsb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ signed char nulval, /* I - value for null pixels */ signed char *array, /* O - array of values that are read */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = 0 in which case no checks for undefined pixels will be made. */ { char cdummy; ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfsb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ signed char *array, /* O - array of values that are read */ char *nularray, /* O - array of flags: 1 if null pixel; else 0 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Nularray will be set = 1 if the corresponding array pixel is undefined, otherwise nularray will = 0. */ { signed char dummy = 0; ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgclsb(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long elemincre, /* I - pixel increment; e.g., 2 = every other */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ signed char nulval, /* I - value for null pixels if nultyp = 1 */ signed char *array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer be a virtual column in a 1 or more grouped FITS primary array or image extension. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The output array of values will be converted from the datatype of the column and will be scaled by the FITS TSCALn and TZEROn values if necessary. */ { double scale, zero, power = 1., dtemp; int tcode, maxelem, hdutype, xcode, decimals; long twidth, incre; long ii, xwidth, ntodo; int nulcheck, readcheck = 0; LONGLONG repeat, startpos, elemnum, readptr, tnull; LONGLONG rowlen, rownum, remain, next, rowincre; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value if reading from ASCII table */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; union u_tag { char charval; signed char scharval; } u; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); buffer = cbuff; if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if (elemincre < 0) readcheck = -1; /* don't do range checking in this case */ ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero, tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status); /* special case: read column of T/F logicals */ if (tcode == TLOGICAL && elemincre == 1) { u.scharval = nulval; ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, u.charval, (char *) array, nularray, anynul, status); return(*status); } if (strchr(tform,'A') != NULL) { if (*status == BAD_ELEM_NUM) { /* ignore this error message */ *status = 0; ffcmsg(); /* clear error stack */ } /* interpret a 'A' ASCII column as a 'B' byte column ('8A' == '8B') */ /* This is an undocumented 'feature' in CFITSIO */ /* we have to reset some of the values returned by ffgcpr */ tcode = TBYTE; incre = 1; /* each element is 1 byte wide */ repeat = twidth; /* total no. of chars in the col */ twidth = 1; /* width of each element */ scale = 1.0; /* no scaling */ zero = 0.0; tnull = NULL_UNDEFINED; /* don't test for nulls */ maxelem = DBUFFSIZE; } if (*status > 0) return(*status); incre *= elemincre; /* multiply incre to just get every nth pixel */ if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */ { /* get the number of implied decimal places if no explicit decmal point */ ffasfm(tform, &xcode, &xwidth, &decimals, status); for(ii = 0; ii < decimals; ii++) power *= 10.; } /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default, check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (tcode%10 == 1 && /* if reading an integer column, and */ tnull == NULL_UNDEFINED) /* if a null value is not defined, */ nulcheck = 0; /* then do not check for null values. */ else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TBYTE && (tnull > 255 || tnull < 0) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED) nulcheck = 0; /*---------------------------------------------------------------------*/ /* Now read the pixels from the FITS column. If the column does not */ /* have the same datatype as the output array, then we have to read */ /* the raw values into a temporary buffer (of limited size). In */ /* the case of a vector colum read only 1 vector of values at a time */ /* then skip to the next row if more values need to be read. */ /* After reading the raw values, then call the fffXXYY routine to (1) */ /* test for undefined values, (2) convert the datatype if necessary, */ /* and (3) scale the values by the FITS TSCALn and TZEROn linear */ /* scaling parameters. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to read */ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to read at one time to the number that will fit in the buffer or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); if (elemincre >= 0) { ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1)); } else { ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1)); } readptr = startpos + (rownum * rowlen) + (elemnum * (incre / elemincre)); switch (tcode) { case (TBYTE): ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) &array[next], status); fffi1s1((unsigned char *)&array[next], ntodo, scale, zero, nulcheck, (unsigned char) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TSHORT): ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status); fffi2s1((short *) buffer, ntodo, scale, zero, nulcheck, (short) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TLONG): ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer, status); fffi4s1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, (INT32BIT) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TLONGLONG): ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status); fffi8s1( (LONGLONG *) buffer, ntodo, scale, zero, nulcheck, tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TFLOAT): ffgr4b(fptr, readptr, ntodo, incre, (float *) buffer, status); fffr4s1((float *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TDOUBLE): ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status); fffr8s1((double *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TSTRING): ffmbyt(fptr, readptr, REPORT_EOF, status); if (incre == twidth) /* contiguous bytes */ ffgbyt(fptr, ntodo * twidth, buffer, status); else ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); /* interpret the string as an ASCII formated number */ fffstrs1((char *) buffer, ntodo, scale, zero, twidth, power, nulcheck, snull, nulval, &nularray[next], anynul, &array[next], status); break; default: /* error trap for invalid column format */ snprintf(message, FLEN_ERRMSG, "Cannot read bytes from column %d which has format %s", colnum, tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; if (hdutype > 0) snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from column %d (ffgclsb).", dtemp+1., dtemp+ntodo, colnum); else snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from image (ffgclsb).", dtemp+1., dtemp+ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum = elemnum + (ntodo * elemincre); if (elemnum >= repeat) /* completed a row; start on later row */ { rowincre = elemnum / repeat; rownum += rowincre; elemnum = elemnum - (rowincre * repeat); } else if (elemnum < 0) /* completed a row; start on a previous row */ { rowincre = (-elemnum - 1) / repeat + 1; rownum -= rowincre; elemnum = (rowincre * repeat) + elemnum; } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while reading FITS data."); *status = NUM_OVERFLOW; } return(*status); } /*--------------------------------------------------------------------------*/ int fffi1s1(unsigned char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == -128.) { /* Instead of subtracting 128, it is more efficient */ /* to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) output[ii] = ( *(signed char *) &input[ii] ) ^ 0x80; } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; /* copy input */ } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == -128.) { /* Instead of subtracting 128, it is more efficient */ /* to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = ( *(signed char *) &input[ii] ) ^ 0x80; } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (signed char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi2s1(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < -128) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < -128) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi4s1(INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < -128) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < -128) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi8s1(LONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG tnull, /* I - value of FITS TNULLn keyword if any */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; ULONGLONG ulltemp; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else { output[ii] = (short) ulltemp; } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < -128) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of subtracting 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else { output[ii] = (short) ulltemp; } } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < -128) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > 127) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr4s1(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { /* use redundant boolean logic in following statement */ /* to suppress irritating Borland compiler warning message */ if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (zero > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr8s1(double *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (input[ii] > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (zero > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffstrs1(char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ long twidth, /* I - width of each substring of chars */ double implipower, /* I - power of 10 of implied decimal */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ char *snull, /* I - value of FITS null string, if any */ signed char nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ signed char *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to snull. If nullcheck= 0, then no special checking for nulls is performed. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { int nullen; long ii; double dvalue; char *cstring, message[FLEN_ERRMSG]; char *cptr, *tpos; char tempstore, chrzero = '0'; double val, power; int exponent, sign, esign, decpt; nullen = strlen(snull); cptr = input; /* pointer to start of input string */ for (ii = 0; ii < ntodo; ii++) { cstring = cptr; /* temporarily insert a null terminator at end of the string */ tpos = cptr + twidth; tempstore = *tpos; *tpos = 0; /* check if null value is defined, and if the */ /* column string is identical to the null string */ if (snull[0] != ASCII_NULL_UNDEFINED && !strncmp(snull, cptr, nullen) ) { if (nullcheck) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } cptr += twidth; } else { /* value is not the null value, so decode it */ /* remove any embedded blank characters from the string */ decpt = 0; sign = 1; val = 0.; power = 1.; exponent = 0; esign = 1; while (*cptr == ' ') /* skip leading blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for leading sign */ { if (*cptr == '-') sign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and value */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } if (*cptr == '.' || *cptr == ',') /* check for decimal point */ { decpt = 1; cptr++; while (*cptr == ' ') /* skip any blanks */ cptr++; while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ power = power * 10.; cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } } if (*cptr == 'E' || *cptr == 'D') /* check for exponent */ { cptr++; while (*cptr == ' ') /* skip blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for exponent sign */ { if (*cptr == '-') esign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and exp */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { exponent = exponent * 10 + *cptr - chrzero; /* accumulate exp */ cptr++; while (*cptr == ' ') /* skip embedded blanks */ cptr++; } } if (*cptr != 0) /* should end up at the null terminator */ { snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table"); ffpmsg(message); snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring); ffpmsg(message); /* restore the char that was overwritten by the null */ *tpos = tempstore; return(*status = BAD_C2D); } if (!decpt) /* if no explicit decimal, use implied */ power = implipower; dvalue = (sign * val / power) * pow(10., (double) (esign * exponent)); dvalue = dvalue * scale + zero; /* apply the scaling */ if (dvalue < DSCHAR_MIN) { *status = OVERFLOW_ERR; output[ii] = -128; } else if (dvalue > DSCHAR_MAX) { *status = OVERFLOW_ERR; output[ii] = 127; } else output[ii] = (signed char) dvalue; } /* restore the char that was overwritten by the null */ *tpos = tempstore; } return(*status); } cfitsio-4.3.1/getcoluk.c0000644000225700000360000022334513472024437014445 0ustar cagordonlhea/* This file, getcolk.c, contains routines that read data elements from */ /* a FITS image or table, with 'unsigned int' data type. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffgpvuk( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned int nulval, /* I - value for undefined pixels */ unsigned int *array, /* O - array of values that are returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Undefined elements will be set equal to NULVAL, unless NULVAL=0 in which case no checking for undefined values will be performed. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; char cdummy; int nullcheck = 1; unsigned int nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ nullvalue = nulval; /* set local variable */ fits_read_compressed_pixels(fptr, TUINT, firstelem, nelem, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgcluk(fptr, 2, row, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgpfuk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned int *array, /* O - array of values that are returned */ char *nularray, /* O - array of null pixel flags */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any undefined pixels in the returned array will be set = 0 and the corresponding nularray value will be set = 1. ANYNUL is returned with a value of .true. if any pixels are undefined. */ { long row; int nullcheck = 2; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ fits_read_compressed_pixels(fptr, TUINT, firstelem, nelem, nullcheck, NULL, array, nularray, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgcluk(fptr, 2, row, firstelem, nelem, 1, 2, 0L, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg2duk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ unsigned int nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ unsigned int *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 2-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { /* call the 3D reading routine, with the 3rd dimension = 1 */ ffg3duk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffg3duk(fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ unsigned int nulval, /* set undefined pixels equal to this */ LONGLONG ncols, /* I - number of pixels in each row of array */ LONGLONG nrows, /* I - number of rows in each plane of array */ LONGLONG naxis1, /* I - FITS image NAXIS1 value */ LONGLONG naxis2, /* I - FITS image NAXIS2 value */ LONGLONG naxis3, /* I - FITS image NAXIS3 value */ unsigned int *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an entire 3-D array of values to the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). Any null values in the array will be set equal to the value of nulval, unless nulval = 0 in which case no null checking will be performed. */ { long tablerow, ii, jj; char cdummy; int nullcheck = 1; long inc[] = {1,1,1}; LONGLONG fpixel[] = {1,1,1}, nfits, narray; LONGLONG lpixel[3]; unsigned int nullvalue; if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ lpixel[0] = ncols; lpixel[1] = nrows; lpixel[2] = naxis3; nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TUINT, fpixel, lpixel, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ tablerow=maxvalue(1,group); if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */ { /* all the image pixels are contiguous, so read all at once */ ffgcluk(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } if (ncols < naxis1 || nrows < naxis2) return(*status = BAD_DIMEN); nfits = 1; /* next pixel in FITS image to read */ narray = 0; /* next pixel in output array to be filled */ /* loop over naxis3 planes in the data cube */ for (jj = 0; jj < naxis3; jj++) { /* loop over the naxis2 rows in the FITS image, */ /* reading naxis1 pixels to each row */ for (ii = 0; ii < naxis2; ii++) { if (ffgcluk(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval, &array[narray], &cdummy, anynul, status) > 0) return(*status); nfits += naxis1; narray += ncols; } narray += (nrows - naxis2) * ncols; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsvuk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ unsigned int nulval, /* I - value to set undefined pixels */ unsigned int *array, /* O - array to be filled and returned */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9]; long nelem, nultyp, ninc, numcol; LONGLONG felem, dsize[10], blcll[9], trcll[9]; int hdutype, anyf; char ldummy, msg[FLEN_ERRMSG]; int nullcheck = 1; unsigned int nullvalue; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvuk is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } nullvalue = nulval; /* set local variable */ fits_read_compressed_img(fptr, TUINT, blcll, trcll, inc, nullcheck, &nullvalue, array, NULL, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 1; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { snprintf(msg, FLEN_ERRMSG,"ffgsvuk: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; } if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0] - str[0]) / inc[0] + 1; ninc = incr[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8]) { for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7]) { for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6]) { for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5]) { for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4]) { for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3]) { for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2]) { for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1]) { felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] + (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] + (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8]; if ( ffgcluk(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &ldummy, &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgsfuk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of the column to read (1 = 1st) */ int naxis, /* I - number of dimensions in the FITS array */ long *naxes, /* I - size of each dimension */ long *blc, /* I - 'bottom left corner' of the subsection */ long *trc, /* I - 'top right corner' of the subsection */ long *inc, /* I - increment to be applied in each dimension */ unsigned int *array, /* O - array to be filled and returned */ char *flagval, /* O - set to 1 if corresponding value is null */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read a subsection of data values from an image or a table column. This routine is set up to handle a maximum of nine dimensions. */ { long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc; long str[9],stp[9],incr[9],dsize[10]; LONGLONG blcll[9], trcll[9]; long felem, nelem, nultyp, ninc, numcol; long nulval = 0; int hdutype, anyf; char msg[FLEN_ERRMSG]; int nullcheck = 2; if (naxis < 1 || naxis > 9) { snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis); ffpmsg(msg); return(*status = BAD_DIMEN); } if (fits_is_compressed_image(fptr, status)) { /* this is a compressed image in a binary table */ for (ii=0; ii < naxis; ii++) { blcll[ii] = blc[ii]; trcll[ii] = trc[ii]; } fits_read_compressed_img(fptr, TUINT, blcll, trcll, inc, nullcheck, NULL, array, flagval, anynul, status); return(*status); } /* if this is a primary array, then the input COLNUM parameter should be interpreted as the row number, and we will alway read the image data from column 2 (any group parameters are in column 1). */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == IMAGE_HDU) { /* this is a primary array, or image extension */ if (colnum == 0) { rstr = 1; rstp = 1; } else { rstr = colnum; rstp = colnum; } rinc = 1; numcol = 2; } else { /* this is a table, so the row info is in the (naxis+1) elements */ rstr = blc[naxis]; rstp = trc[naxis]; rinc = inc[naxis]; numcol = colnum; } nultyp = 2; if (anynul) *anynul = FALSE; i0 = 0; for (ii = 0; ii < 9; ii++) { str[ii] = 1; stp[ii] = 1; incr[ii] = 1; dsize[ii] = 1; } for (ii = 0; ii < naxis; ii++) { if (trc[ii] < blc[ii]) { snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1); ffpmsg(msg); return(*status = BAD_PIX_NUM); } str[ii] = blc[ii]; stp[ii] = trc[ii]; incr[ii] = inc[ii]; dsize[ii + 1] = dsize[ii] * naxes[ii]; } if (naxis == 1 && naxes[0] == 1) { /* This is not a vector column, so read all the rows at once */ nelem = (rstp - rstr) / rinc + 1; ninc = rinc; rstp = rstr; } else { /* have to read each row individually, in all dimensions */ nelem = (stp[0] - str[0]) / inc[0] + 1; ninc = incr[0]; } for (row = rstr; row <= rstp; row += rinc) { for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8]) { for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7]) { for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6]) { for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5]) { for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4]) { for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3]) { for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2]) { for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1]) { felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] + (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] + (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8]; if ( ffgcluk(fptr, numcol, row, felem, nelem, ninc, nultyp, nulval, &array[i0], &flagval[i0], &anyf, status) > 0) return(*status); if (anyf && anynul) *anynul = TRUE; i0 += nelem; } } } } } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffggpuk( fitsfile *fptr, /* I - FITS file pointer */ long group, /* I - group to read (1 = 1st group) */ long firstelem, /* I - first vector element to read (1 = 1st) */ long nelem, /* I - number of values to read */ unsigned int *array, /* O - array of values that are returned */ int *status) /* IO - error status */ /* Read an array of group parameters from the primary array. Data conversion and scaling will be performed if necessary (e.g, if the datatype of the FITS array is not the same as the array being read). */ { long row; int idummy; char cdummy; /* the primary array is represented as a binary table: each group of the primary array is a row in the table, where the first column contains the group parameters and the second column contains the image itself. */ row=maxvalue(1,group); ffgcluk(fptr, 1, row, firstelem, nelem, 1, 1, 0L, array, &cdummy, &idummy, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcvuk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned int nulval, /* I - value for null pixels */ unsigned int *array, /* O - array of values that are read */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Any undefined pixels will be set equal to the value of 'nulval' unless nulval = 0 in which case no checks for undefined pixels will be made. */ { char cdummy; ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval, array, &cdummy, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcfuk(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ unsigned int *array, /* O - array of values that are read */ char *nularray, /* O - array of flags: 1 if null pixel; else 0 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. Automatic datatype conversion will be performed if the datatype of the column does not match the datatype of the array parameter. The output values will be scaled by the FITS TSCALn and TZEROn values if these values have been defined. Nularray will be set = 1 if the corresponding array pixel is undefined, otherwise nularray will = 0. */ { int dummy = 0; ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy, array, nularray, anynul, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcluk( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - number of column to read (1 = 1st col) */ LONGLONG firstrow, /* I - first row to read (1 = 1st row) */ LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */ LONGLONG nelem, /* I - number of values to read */ long elemincre, /* I - pixel increment; e.g., 2 = every other */ int nultyp, /* I - null value handling code: */ /* 1: set undefined pixels = nulval */ /* 2: set nularray=1 for undefined pixels */ unsigned int nulval, /* I - value for null pixels if nultyp = 1 */ unsigned int *array, /* O - array of values that are read */ char *nularray, /* O - array of flags = 1 if nultyp = 2 */ int *anynul, /* O - set to 1 if any values are null; else 0 */ int *status) /* IO - error status */ /* Read an array of values from a column in the current FITS HDU. The column number may refer to a real column in an ASCII or binary table, or it may refer be a virtual column in a 1 or more grouped FITS primary array or image extension. FITSIO treats a primary array as a binary table with 2 vector columns: the first column contains the group parameters (often with length = 0) and the second column contains the array of image pixels. Each row of the table represents a group in the case of multigroup FITS images. The output array of values will be converted from the datatype of the column and will be scaled by the FITS TSCALn and TZEROn values if necessary. */ { double scale, zero, power = 1., dtemp; int tcode, maxelem2, hdutype, xcode, decimals; long twidth, incre; long ii, xwidth, ntodo; int nulcheck; LONGLONG repeat, startpos, elemnum, readptr, tnull; LONGLONG rowlen, rownum, remain, next, rowincre, maxelem; char tform[20]; char message[FLEN_ERRMSG]; char snull[20]; /* the FITS null value if reading from ASCII table */ double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */ void *buffer; if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */ return(*status); /* call the 'short' or 'long' version of this routine, if possible */ if (sizeof(int) == sizeof(short)) ffgclui(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp, (unsigned short) nulval, (unsigned short *) array, nularray, anynul, status); else if (sizeof(int) == sizeof(long)) ffgcluj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp, (unsigned long) nulval, (unsigned long *) array, nularray, anynul, status); else { /* This is a special case: sizeof(int) is not equal to sizeof(short) or sizeof(long). This occurs on Alpha OSF systems where short = 2 bytes, int = 4 bytes, and long = 8 bytes. */ buffer = cbuff; if (anynul) *anynul = 0; if (nultyp == 2) memset(nularray, 0, (size_t) nelem); /* initialize nullarray */ /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero, tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 ) return(*status); maxelem = maxelem2; incre *= elemincre; /* multiply incre to just get every nth pixel */ if (tcode == TSTRING) /* setup for ASCII tables */ { /* get the number of implied decimal places if no explicit decmal point */ ffasfm(tform, &xcode, &xwidth, &decimals, status); for(ii = 0; ii < decimals; ii++) power *= 10.; } /*------------------------------------------------------------------*/ /* Decide whether to check for null values in the input FITS file: */ /*------------------------------------------------------------------*/ nulcheck = nultyp; /* by default check for null values in the FITS file */ if (nultyp == 1 && nulval == 0) nulcheck = 0; /* calling routine does not want to check for nulls */ else if (tcode%10 == 1 && /* if reading an integer column, and */ tnull == NULL_UNDEFINED) /* if a null value is not defined, */ nulcheck = 0; /* then do not check for null values. */ else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TBYTE && (tnull > 255 || tnull < 0) ) nulcheck = 0; /* Impossible null value */ else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED) nulcheck = 0; /*----------------------------------------------------------------------*/ /* If FITS column and output data array have same datatype, then we do */ /* not need to use a temporary buffer to store intermediate datatype. */ /*----------------------------------------------------------------------*/ if (tcode == TLONG) /* Special Case: */ { /* data are 4-bytes long, so read */ /* data directly into output buffer. */ if (nelem < (LONGLONG)INT32_MAX/4) { maxelem = nelem; } else { maxelem = INT32_MAX/4; } } /*---------------------------------------------------------------------*/ /* Now read the pixels from the FITS column. If the column does not */ /* have the same datatype as the output array, then we have to read */ /* the raw values into a temporary buffer (of limited size). In */ /* the case of a vector colum read only 1 vector of values at a time */ /* then skip to the next row if more values need to be read. */ /* After reading the raw values, then call the fffXXYY routine to (1) */ /* test for undefined values, (2) convert the datatype if necessary, */ /* and (3) scale the values by the FITS TSCALn and TZEROn linear */ /* scaling parameters. */ /*---------------------------------------------------------------------*/ remain = nelem; /* remaining number of values to read */ next = 0; /* next element in array to be read */ rownum = 0; /* row number, relative to firstrow */ while (remain) { /* limit the number of pixels to read at one time to the number that will fit in the buffer or to the number of pixels that remain in the current vector, which ever is smaller. */ ntodo = (long) minvalue(remain, maxelem); ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1)); readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre)); switch (tcode) { case (TLONG): ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next], status); fffi4uint((INT32BIT *) &array[next], ntodo, scale, zero, nulcheck, (INT32BIT) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TLONGLONG): ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status); fffi8uint( (LONGLONG *) buffer, ntodo, scale, zero, nulcheck, tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TBYTE): ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer, status); fffi1uint((unsigned char *) buffer, ntodo, scale, zero,nulcheck, (unsigned char) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TSHORT): ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status); fffi2uint((short *) buffer, ntodo, scale, zero, nulcheck, (short) tnull, nulval, &nularray[next], anynul, &array[next], status); break; case (TFLOAT): ffgr4b(fptr, readptr, ntodo, incre, (float *) buffer, status); fffr4uint((float *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TDOUBLE): ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status); fffr8uint((double *) buffer, ntodo, scale, zero, nulcheck, nulval, &nularray[next], anynul, &array[next], status); break; case (TSTRING): ffmbyt(fptr, readptr, REPORT_EOF, status); if (incre == twidth) /* contiguous bytes */ ffgbyt(fptr, ntodo * twidth, buffer, status); else ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer, status); fffstruint((char *) buffer, ntodo, scale, zero, twidth, power, nulcheck, snull, nulval, &nularray[next], anynul, &array[next], status); break; default: /* error trap for invalid column format */ snprintf(message, FLEN_ERRMSG, "Cannot read numbers from column %d which has format %s", colnum, tform); ffpmsg(message); if (hdutype == ASCII_TBL) return(*status = BAD_ATABLE_FORMAT); else return(*status = BAD_BTABLE_FORMAT); } /* End of switch block */ /*-------------------------*/ /* Check for fatal error */ /*-------------------------*/ if (*status > 0) /* test for error during previous read operation */ { dtemp = (double) next; if (hdutype > 0) snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from column %d (ffgcluk).", dtemp+1., dtemp+ntodo, colnum); else snprintf(message,FLEN_ERRMSG, "Error reading elements %.0f thru %.0f from image (ffgcluk).", dtemp+1., dtemp+ntodo); ffpmsg(message); return(*status); } /*--------------------------------------------*/ /* increment the counters for the next loop */ /*--------------------------------------------*/ remain -= ntodo; if (remain) { next += ntodo; elemnum = elemnum + (ntodo * elemincre); if (elemnum >= repeat) /* completed a row; start on later row */ { rowincre = elemnum / repeat; rownum += rowincre; elemnum = elemnum - (rowincre * repeat); } } } /* End of main while Loop */ /*--------------------------------*/ /* check for numerical overflow */ /*--------------------------------*/ if (*status == OVERFLOW_ERR) { ffpmsg( "Numerical overflow during type conversion while reading FITS data."); *status = NUM_OVERFLOW; } } /* end of DEC Alpha special case */ return(*status); } /*--------------------------------------------------------------------------*/ int fffi1uint(unsigned char *input,/* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned char tnull, /* I - value of FITS TNULLn keyword if any */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) output[ii] = (unsigned int) input[ii]; /* copy input */ } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = (unsigned int) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi2uint(short *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ short tnull, /* I - value of FITS TNULLn keyword if any */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else output[ii] = (unsigned int) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else output[ii] = (unsigned int) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi4uint(INT32BIT *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 2147483648.) { /* Instead of adding 2147483648, it is more efficient */ /* to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) output[ii] = ( *(unsigned int *) &input[ii] ) ^ 0x80000000; } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else output[ii] = (unsigned int) input[ii]; /* copy to output */ } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 2147483648.) { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else output[ii] = ( *(unsigned int *) &input[ii] ) ^ 0x80000000; } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else output[ii] = (unsigned int) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffi8uint(LONGLONG *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ LONGLONG tnull, /* I - value of FITS TNULLn keyword if any */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to tnull. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; ULONGLONG ulltemp; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > UINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) ulltemp; } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } else /* must check for null values */ { if (scale == 1. && zero == 9223372036854775808.) { /* The column we read contains unsigned long long values. */ /* Instead of adding 9223372036854775808, it is more efficient */ /* and more precise to just flip the sign bit with the XOR operator */ for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000); if (ulltemp > UINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else { output[ii] = (unsigned int) ulltemp; } } } } else if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { if (input[ii] < 0) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > UINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] == tnull) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr4uint(float *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 2) { if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (zero > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffr8uint(double *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do datatype conversion and scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to NaN. If nullcheck = 0, then no checking for nulls is performed and any null values will be transformed just like any other pixel. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { long ii; double dvalue; short *sptr, iret; if (nullcheck == 0) /* no null checking required */ { if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++) { if (input[ii] < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) input[ii]; } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++) { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } else /* must check for null values */ { sptr = (short *) input; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif if (scale == 1. && zero == 0.) /* no scaling */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ output[ii] = 0; } else { if (input[ii] < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (input[ii] > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) input[ii]; } } } else /* must scale the data */ { for (ii = 0; ii < ntodo; ii++, sptr += 4) { if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */ { if (iret == 1) /* is it a NaN? */ { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } else /* it's an underflow */ { if (zero < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (zero > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) zero; } } else { dvalue = input[ii] * scale + zero; if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (unsigned int) dvalue; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fffstruint(char *input, /* I - array of values to be converted */ long ntodo, /* I - number of elements in the array */ double scale, /* I - FITS TSCALn or BSCALE value */ double zero, /* I - FITS TZEROn or BZERO value */ long twidth, /* I - width of each substring of chars */ double implipower, /* I - power of 10 of implied decimal */ int nullcheck, /* I - null checking code; 0 = don't check */ /* 1:set null pixels = nullval */ /* 2: if null pixel, set nullarray = 1 */ char *snull, /* I - value of FITS null string, if any */ unsigned int nullval, /* I - set null pixels, if nullcheck = 1 */ char *nullarray, /* I - bad pixel array, if nullcheck = 2 */ int *anynull, /* O - set to 1 if any pixels are null */ unsigned int *output, /* O - array of converted pixels */ int *status) /* IO - error status */ /* Copy input to output following reading of the input from a FITS file. Check for null values and do scaling if required. The nullcheck code value determines how any null values in the input array are treated. A null value is an input pixel that is equal to snull. If nullcheck= 0, then no special checking for nulls is performed. If nullcheck = 1, then the output pixel will be set = nullval if the corresponding input pixel is null. If nullcheck = 2, then if the pixel is null then the corresponding value of nullarray will be set to 1; the value of nullarray for non-null pixels will = 0. The anynull parameter will be set = 1 if any of the returned pixels are null, otherwise anynull will be returned with a value = 0; */ { int nullen; long ii; double dvalue; char *cstring, message[FLEN_ERRMSG]; char *cptr, *tpos; char tempstore, chrzero = '0'; double val, power; int exponent, sign, esign, decpt; nullen = strlen(snull); cptr = input; /* pointer to start of input string */ for (ii = 0; ii < ntodo; ii++) { cstring = cptr; /* temporarily insert a null terminator at end of the string */ tpos = cptr + twidth; tempstore = *tpos; *tpos = 0; /* check if null value is defined, and if the */ /* column string is identical to the null string */ if (snull[0] != ASCII_NULL_UNDEFINED && !strncmp(snull, cptr, nullen) ) { if (nullcheck) { *anynull = 1; if (nullcheck == 1) output[ii] = nullval; else nullarray[ii] = 1; } cptr += twidth; } else { /* value is not the null value, so decode it */ /* remove any embedded blank characters from the string */ decpt = 0; sign = 1; val = 0.; power = 1.; exponent = 0; esign = 1; while (*cptr == ' ') /* skip leading blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for leading sign */ { if (*cptr == '-') sign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and value */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } if (*cptr == '.' || *cptr == ',') /* check for decimal point */ { decpt = 1; /* set flag to show there was a decimal point */ cptr++; while (*cptr == ' ') /* skip any blanks */ cptr++; while (*cptr >= '0' && *cptr <= '9') { val = val * 10. + *cptr - chrzero; /* accumulate the value */ power = power * 10.; cptr++; while (*cptr == ' ') /* skip embedded blanks in the value */ cptr++; } } if (*cptr == 'E' || *cptr == 'D') /* check for exponent */ { cptr++; while (*cptr == ' ') /* skip blanks */ cptr++; if (*cptr == '-' || *cptr == '+') /* check for exponent sign */ { if (*cptr == '-') esign = -1; cptr++; while (*cptr == ' ') /* skip blanks between sign and exp */ cptr++; } while (*cptr >= '0' && *cptr <= '9') { exponent = exponent * 10 + *cptr - chrzero; /* accumulate exp */ cptr++; while (*cptr == ' ') /* skip embedded blanks */ cptr++; } } if (*cptr != 0) /* should end up at the null terminator */ { snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table"); ffpmsg(message); snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring); ffpmsg(message); /* restore the char that was overwritten by the null */ *tpos = tempstore; return(*status = BAD_C2D); } if (!decpt) /* if no explicit decimal, use implied */ power = implipower; dvalue = (sign * val / power) * pow(10., (double) (esign * exponent)); dvalue = dvalue * scale + zero; /* apply the scaling */ if (dvalue < DUINT_MIN) { *status = OVERFLOW_ERR; output[ii] = 0; } else if (dvalue > DUINT_MAX) { *status = OVERFLOW_ERR; output[ii] = UINT_MAX; } else output[ii] = (long) dvalue; } /* restore the char that was overwritten by the null */ *tpos = tempstore; } return(*status); }